aboutsummaryrefslogtreecommitdiffstats
path: root/package
diff options
context:
space:
mode:
Diffstat (limited to 'package')
-rw-r--r--package/6in4/Makefile42
-rwxr-xr-xpackage/6in4/files/6in4.sh90
-rw-r--r--package/6rd/Makefile53
-rw-r--r--package/6rd/files/6rd.sh80
-rw-r--r--package/6rd/src/6rdcalc.c126
-rw-r--r--package/6rd/src/Makefile7
-rw-r--r--package/6to4/Makefile42
-rwxr-xr-xpackage/6to4/files/6to4.sh209
-rw-r--r--package/Makefile105
-rw-r--r--package/acx-mac80211/Makefile245
-rw-r--r--package/acx-mac80211/patches/001-make-compatible-with-recent-mac80211.patch43
-rw-r--r--package/acx-mac80211/patches/004-ratelimit_compile_fix.patch10
-rw-r--r--package/acx-mac80211/patches/100-hw-queue-check-fix.patch42
-rw-r--r--package/admswconfig/Makefile51
-rw-r--r--package/admswconfig/files/admswconfig68
-rw-r--r--package/admswconfig/files/admswswitch.sh28
-rw-r--r--package/admswconfig/patches/001-matrix.patch15
-rw-r--r--package/apex/Makefile58
-rw-r--r--package/apex/patches/001-compile_fix.patch20
-rw-r--r--package/apex/patches/100-openwrt_nslu2_armeb_config.patch23
-rw-r--r--package/apex/patches/120-openwrt_nslu2_16mb_armeb_config.patch23
-rw-r--r--package/apex/patches/140-openwrt_fsg3_armeb_config.patch23
-rw-r--r--package/apex/patches/150-limit_ram_to_64mb.patch22
-rw-r--r--package/apex/patches/160-openwrt_nas100d_armeb_config.patch20
-rw-r--r--package/ar7-atm/Config.in22
-rw-r--r--package/ar7-atm/Makefile99
-rw-r--r--package/ar7-atm/patches-D7.04.03.00/100-compile_fix.patch768
-rw-r--r--package/ar7-atm/patches-D7.04.03.00/110-interrupt_fix.patch37
-rw-r--r--package/ar7-atm/patches-D7.04.03.00/120-no_dumb_inline.patch11
-rw-r--r--package/ar7-atm/patches-D7.04.03.00/130-powercutback.patch44
-rw-r--r--package/ar7-atm/patches-D7.04.03.00/140-debug_mode.patch16
-rw-r--r--package/ar7-atm/patches-D7.04.03.00/150-tasklet_mode.patch11
-rw-r--r--package/ar7-atm/patches-D7.04.03.00/160-module-params.patch577
-rw-r--r--package/ar7-atm/patches-D7.04.03.00/170-bus_id_removal.patch30
-rw-r--r--package/ar7-atm/patches-D7.04.03.00/180-git_headers_include.patch54
-rw-r--r--package/ar7-atm/patches-D7.04.03.00/190-2.6.32_proc_fixes.patch79
-rw-r--r--package/ar7-atm/patches-D7.04.03.00/200-2.6.37_args.patch36
-rw-r--r--package/ar7-atm/patches-D7.04.03.00/210-3.3-remove-smp_lock.h.patch33
-rw-r--r--package/ar7-atm/patches-D7.05.01.00/100-compile_fix.patch808
-rw-r--r--package/ar7-atm/patches-D7.05.01.00/110-interrupt_fix.patch37
-rw-r--r--package/ar7-atm/patches-D7.05.01.00/120-no_dumb_inline.patch11
-rw-r--r--package/ar7-atm/patches-D7.05.01.00/130-powercutback.patch44
-rw-r--r--package/ar7-atm/patches-D7.05.01.00/140-debug_mode.patch16
-rw-r--r--package/ar7-atm/patches-D7.05.01.00/150-tasklet_mode.patch11
-rw-r--r--package/ar7-atm/patches-D7.05.01.00/160-module-params.patch663
-rw-r--r--package/ar7-atm/patches-D7.05.01.00/170-bus_id_removal.patch30
-rw-r--r--package/ar7-atm/patches-D7.05.01.00/180-git_headers_include.patch54
-rw-r--r--package/ar7-atm/patches-D7.05.01.00/190-2.6.32_proc_fixes.patch79
-rw-r--r--package/ar7-atm/patches-D7.05.01.00/200-2.6.37_args.patch36
-rw-r--r--package/ar7-atm/patches-D7.05.01.00/210-3.3-remove-smp_lock.h.patch33
-rw-r--r--package/arptables/Makefile42
-rw-r--r--package/arptables/patches/100-always_optimize.patch19
-rw-r--r--package/avila-wdt/Makefile40
-rw-r--r--package/avila-wdt/src/Makefile1
-rw-r--r--package/avila-wdt/src/avila-wdt.c231
-rw-r--r--package/base-files/Makefile155
-rwxr-xr-xpackage/base-files/files/bin/ipcalc.sh62
-rwxr-xr-xpackage/base-files/files/bin/login.sh19
-rw-r--r--package/base-files/files/etc/banner16
-rw-r--r--package/base-files/files/etc/config/network14
-rw-r--r--package/base-files/files/etc/config/system10
-rw-r--r--package/base-files/files/etc/diag.sh4
l---------package/base-files/files/etc/functions.sh1
-rw-r--r--package/base-files/files/etc/group10
-rw-r--r--package/base-files/files/etc/hosts1
-rw-r--r--package/base-files/files/etc/hotplug.d/ieee1394/10-ieee139413
-rw-r--r--package/base-files/files/etc/hotplug.d/usb/10-usb13
-rw-r--r--package/base-files/files/etc/hotplug2-common.rules43
-rw-r--r--package/base-files/files/etc/hotplug2-init.rules5
-rwxr-xr-xpackage/base-files/files/etc/init.d/boot103
-rwxr-xr-xpackage/base-files/files/etc/init.d/done20
-rwxr-xr-xpackage/base-files/files/etc/init.d/led80
-rwxr-xr-xpackage/base-files/files/etc/init.d/rcS26
-rwxr-xr-xpackage/base-files/files/etc/init.d/sysctl7
-rwxr-xr-xpackage/base-files/files/etc/init.d/sysntpd37
-rwxr-xr-xpackage/base-files/files/etc/init.d/umount8
-rwxr-xr-xpackage/base-files/files/etc/init.d/usb9
-rwxr-xr-xpackage/base-files/files/etc/init.d/watchdog13
-rw-r--r--package/base-files/files/etc/inittab4
-rw-r--r--package/base-files/files/etc/openwrt_release6
-rw-r--r--package/base-files/files/etc/openwrt_version1
-rw-r--r--package/base-files/files/etc/passwd5
-rwxr-xr-xpackage/base-files/files/etc/preinit44
-rw-r--r--package/base-files/files/etc/profile15
-rw-r--r--package/base-files/files/etc/protocols56
-rwxr-xr-xpackage/base-files/files/etc/rc.common85
-rw-r--r--package/base-files/files/etc/rc.local4
-rw-r--r--package/base-files/files/etc/services171
-rw-r--r--package/base-files/files/etc/shadow5
-rw-r--r--package/base-files/files/etc/shells1
-rw-r--r--package/base-files/files/etc/sysctl.conf27
-rw-r--r--package/base-files/files/etc/sysupgrade.conf5
-rw-r--r--package/base-files/files/etc/uci-defaults/migrate-shadow12
-rw-r--r--package/base-files/files/etc/uci-defaults/migrate-sysctl17
-rw-r--r--package/base-files/files/lib/firstboot/05_firstboot_skip10
-rw-r--r--package/base-files/files/lib/firstboot/10_determine_parts46
-rw-r--r--package/base-files/files/lib/firstboot/10_no_fo_clear_overlay17
-rw-r--r--package/base-files/files/lib/firstboot/10_reset_has_mini_fo12
-rw-r--r--package/base-files/files/lib/firstboot/20_has_mini_fo13
-rw-r--r--package/base-files/files/lib/firstboot/20_no_fo_mount_jffs15
-rw-r--r--package/base-files/files/lib/firstboot/20_reset_clear_jffs14
-rw-r--r--package/base-files/files/lib/firstboot/30_is_rootfs_mounted10
-rw-r--r--package/base-files/files/lib/firstboot/30_no_fo_pivot11
-rw-r--r--package/base-files/files/lib/firstboot/30_reset_copy_rom13
-rw-r--r--package/base-files/files/lib/firstboot/40_copy_ramoverlay15
-rw-r--r--package/base-files/files/lib/firstboot/40_no_fo_copy_ramoverlay14
-rw-r--r--package/base-files/files/lib/firstboot/50_pivot17
-rw-r--r--package/base-files/files/lib/firstboot/99_10_no_fo_cleanup13
-rw-r--r--package/base-files/files/lib/firstboot/99_10_with_fo_cleanup25
-rwxr-xr-xpackage/base-files/files/lib/functions.sh340
-rw-r--r--package/base-files/files/lib/functions/boot.sh150
-rw-r--r--package/base-files/files/lib/functions/network.sh170
-rw-r--r--package/base-files/files/lib/functions/service.sh129
-rw-r--r--package/base-files/files/lib/functions/uci-defaults.sh230
-rw-r--r--package/base-files/files/lib/preinit/02_default_set_state7
-rw-r--r--package/base-files/files/lib/preinit/05_mount_skip13
-rw-r--r--package/base-files/files/lib/preinit/10_check_for_mtd20
-rw-r--r--package/base-files/files/lib/preinit/10_essential_fs25
-rw-r--r--package/base-files/files/lib/preinit/10_indicate_failsafe18
-rw-r--r--package/base-files/files/lib/preinit/10_indicate_preinit52
-rw-r--r--package/base-files/files/lib/preinit/20_check_jffs2_ready19
-rw-r--r--package/base-files/files/lib/preinit/20_device_fs_mount37
-rw-r--r--package/base-files/files/lib/preinit/30_device_fs_daemons36
-rw-r--r--package/base-files/files/lib/preinit/30_failsafe_wait85
-rw-r--r--package/base-files/files/lib/preinit/40_init_shm10
-rw-r--r--package/base-files/files/lib/preinit/40_mount_devpts15
-rw-r--r--package/base-files/files/lib/preinit/40_mount_jffs226
-rw-r--r--package/base-files/files/lib/preinit/40_run_failsafe_hook13
-rw-r--r--package/base-files/files/lib/preinit/41_merge_overlay_hooks24
-rw-r--r--package/base-files/files/lib/preinit/50_choose_console31
-rw-r--r--package/base-files/files/lib/preinit/50_indicate_regular_preinit12
-rw-r--r--package/base-files/files/lib/preinit/60_init_hotplug10
-rw-r--r--package/base-files/files/lib/preinit/70_initramfs_test14
-rw-r--r--package/base-files/files/lib/preinit/70_pivot_jffs2_root14
-rw-r--r--package/base-files/files/lib/preinit/80_mount_root10
-rw-r--r--package/base-files/files/lib/preinit/90_init_console14
-rw-r--r--package/base-files/files/lib/preinit/90_mount_no_jffs212
-rw-r--r--package/base-files/files/lib/preinit/90_restore_config17
-rw-r--r--package/base-files/files/lib/preinit/99_10_failsafe_login18
-rw-r--r--package/base-files/files/lib/preinit/99_10_mount_no_mtd12
-rw-r--r--package/base-files/files/lib/preinit/99_10_run_init16
-rw-r--r--package/base-files/files/lib/upgrade/common.sh230
-rw-r--r--package/base-files/files/lib/upgrade/keep.d/base-files-essential9
-rw-r--r--package/base-files/files/rom/note3
-rwxr-xr-xpackage/base-files/files/sbin/firstboot34
-rwxr-xr-xpackage/base-files/files/sbin/hotplug-call17
-rwxr-xr-xpackage/base-files/files/sbin/led.sh25
-rwxr-xr-xpackage/base-files/files/sbin/mount_root26
-rwxr-xr-xpackage/base-files/files/sbin/sysupgrade187
-rwxr-xr-xpackage/base-files/files/sbin/wifi204
-rw-r--r--package/base-files/image-config.in185
-rw-r--r--package/block-mount/Config.in17
-rw-r--r--package/block-mount/Makefile70
-rw-r--r--package/block-mount/files/10-swap78
-rw-r--r--package/block-mount/files/20-fsck83
-rw-r--r--package/block-mount/files/40-mount91
-rw-r--r--package/block-mount/files/50_determine_usb_root65
-rw-r--r--package/block-mount/files/55_determine_extroot_sysupgrade63
-rw-r--r--package/block-mount/files/60_pivot_usb_root27
-rw-r--r--package/block-mount/files/block.sh264
-rw-r--r--package/block-mount/files/extmount.sh37
-rw-r--r--package/block-mount/files/fsck.sh34
-rw-r--r--package/block-mount/files/fstab.config20
-rw-r--r--package/block-mount/files/fstab.init88
-rw-r--r--package/block-mount/files/mount.sh103
-rw-r--r--package/brcm2708-gpu-fw/Makefile46
-rw-r--r--package/bridge-utils/Makefile51
-rw-r--r--package/bridge-utils/patches/001-libbridge_cflags.patch11
-rw-r--r--package/broadcom-diag/Makefile37
-rw-r--r--package/broadcom-diag/src/Makefile17
-rw-r--r--package/broadcom-diag/src/diag.c1686
-rw-r--r--package/broadcom-diag/src/diag.h134
-rw-r--r--package/broadcom-diag/src/gpio.h16
-rw-r--r--package/broadcom-wl/Makefile175
-rw-r--r--package/broadcom-wl/files/etc/hotplug.d/net/20-broadcom_wds61
-rwxr-xr-xpackage/broadcom-wl/files/etc/init.d/wlunbind29
-rw-r--r--package/broadcom-wl/files/lib/wifi/broadcom.sh392
-rw-r--r--package/broadcom-wl/patches/003-compat-2.6.35.patch39
-rw-r--r--package/broadcom-wl/patches/004-remove-pcmcia.patch22
-rw-r--r--package/broadcom-wl/patches/005-fix-mem-leak-on-unload.patch31
-rw-r--r--package/broadcom-wl/patches/006-generic-dma-api.patch88
-rw-r--r--package/broadcom-wl/patches/007-use-glue-driver.patch184
-rw-r--r--package/broadcom-wl/patches/008-fix_virtual_interfaces.patch11
-rw-r--r--package/broadcom-wl/patches/009-fix_compile_3_2.patch27
-rw-r--r--package/broadcom-wl/patches/010-remove_irqf_samble_random.patch11
-rw-r--r--package/broadcom-wl/patches/910-fallback-sprom.patch84
-rw-r--r--package/broadcom-wl/patches/912-pci-bus-nvram-hack.patch11
-rw-r--r--package/broadcom-wl/src/glue/Makefile17
-rw-r--r--package/broadcom-wl/src/glue/wl_glue.c317
-rw-r--r--package/broadcom-wl/src/glue/wl_glue.h22
-rw-r--r--package/broadcom-wl/src/wlc.c1086
-rw-r--r--package/busybox/Config.in24
-rw-r--r--package/busybox/Makefile115
-rw-r--r--package/busybox/config/Config.in778
-rw-r--r--package/busybox/config/archival/Config.in380
-rw-r--r--package/busybox/config/console-tools/Config.in177
-rw-r--r--package/busybox/config/coreutils/Config.in913
-rw-r--r--package/busybox/config/debianutils/Config.in86
-rw-r--r--package/busybox/config/e2fsprogs/Config.in72
-rw-r--r--package/busybox/config/e2fsprogs/old_e2fsprogs/Config.in70
-rw-r--r--package/busybox/config/editors/Config.in206
-rw-r--r--package/busybox/config/findutils/Config.in252
-rw-r--r--package/busybox/config/init/Config.in184
-rw-r--r--package/busybox/config/libbb/Config.in232
-rw-r--r--package/busybox/config/loginutils/Config.in329
-rw-r--r--package/busybox/config/mailutils/Config.in56
-rw-r--r--package/busybox/config/miscutils/Config.in766
-rw-r--r--package/busybox/config/modutils/Config.in269
-rw-r--r--package/busybox/config/networking/Config.in1088
-rw-r--r--package/busybox/config/networking/udhcp/Config.in155
-rw-r--r--package/busybox/config/printutils/Config.in29
-rw-r--r--package/busybox/config/procps/Config.in260
-rw-r--r--package/busybox/config/runit/Config.in90
-rw-r--r--package/busybox/config/selinux/Config.in125
-rw-r--r--package/busybox/config/shell/Config.in433
-rw-r--r--package/busybox/config/sysklogd/Config.in154
-rw-r--r--package/busybox/config/util-linux/Config.in985
-rwxr-xr-xpackage/busybox/convert_menuconfig.pl78
-rwxr-xr-xpackage/busybox/files/cron18
-rwxr-xr-xpackage/busybox/files/telnet37
-rw-r--r--package/busybox/patches/001-init_avoid_loop_opening_tty.patch15
-rw-r--r--package/busybox/patches/002-passwd_use_md5_hash_by_default_like_it_used_to_be.patch20
-rw-r--r--package/busybox/patches/003-brctl_show_fix.patch37
-rw-r--r--package/busybox/patches/004-upstream-percent_decode_in_place.patch237
-rw-r--r--package/busybox/patches/005-resource_h_include.patch10
-rw-r--r--package/busybox/patches/006-upstream_CVE-2011-2716_fixes.patch164
-rw-r--r--package/busybox/patches/110-wget_getopt_fix.patch11
-rw-r--r--package/busybox/patches/140-trylink_bash.patch8
-rw-r--r--package/busybox/patches/141-gen_build_files_bash.patch8
-rw-r--r--package/busybox/patches/150-no_static_libgcc.patch11
-rw-r--r--package/busybox/patches/200-etc_crontabs.patch22
-rw-r--r--package/busybox/patches/240-udhcpc_retries.patch20
-rw-r--r--package/busybox/patches/241-udhcpc-oversized_packets.patch99
-rw-r--r--package/busybox/patches/242-udhcpc_msgs.patch18
-rw-r--r--package/busybox/patches/243-udhcpc_changed_ifindex.patch15
-rw-r--r--package/busybox/patches/244-udhcpc_add_6rd_option.patch143
-rw-r--r--package/busybox/patches/250-ash_export-n.patch34
-rw-r--r--package/busybox/patches/251-ash_fix-redir-substitution.patch12
-rw-r--r--package/busybox/patches/300-netmsg.patch103
-rw-r--r--package/busybox/patches/310-passwd_access.patch41
-rw-r--r--package/busybox/patches/340-lock_util.patch172
-rw-r--r--package/busybox/patches/350-httpd_redir.patch90
-rw-r--r--package/busybox/patches/410-httpd_cgi_headers.patch16
-rw-r--r--package/busybox/patches/440-httpd_chdir.patch10
-rw-r--r--package/busybox/patches/470-insmod_search.patch137
-rw-r--r--package/busybox/patches/480-mount_union.patch29
-rw-r--r--package/busybox/patches/490-mount_disable_check.patch12
-rw-r--r--package/busybox/patches/510-awk_include.patch217
-rw-r--r--package/busybox/patches/524-udhcpc_renew.patch10
-rw-r--r--package/busybox/patches/610-ntpd_delayed_resolve.patch48
-rw-r--r--package/busybox/patches/700-hexdump_segfault_fix.patch11
-rw-r--r--package/busybox/patches/802-brctl_linux24.patch74
-rw-r--r--package/busybox/patches/803-id_getgrouplist.patch49
-rw-r--r--package/busybox/patches/902-telnetd_intr.patch10
-rw-r--r--package/busybox/patches/910-insmod-q-flag.patch33
-rw-r--r--package/busybox/patches/911-date-k-flag.patch83
-rw-r--r--package/busybox/patches/920-portability.patch13
-rw-r--r--package/busybox/patches/950-partial-checksum.patch87
-rw-r--r--package/button-hotplug/Makefile53
-rw-r--r--package/button-hotplug/src/Kconfig2
-rw-r--r--package/button-hotplug/src/Makefile1
-rw-r--r--package/button-hotplug/src/button-hotplug.c349
-rw-r--r--package/comgt/Makefile65
-rw-r--r--package/comgt/files/3g.chat12
-rw-r--r--package/comgt/files/3g.sh97
-rw-r--r--package/comgt/files/3g.usb33
-rw-r--r--package/comgt/files/evdo.chat17
-rw-r--r--package/comgt/files/getcardinfo.gcom14
-rw-r--r--package/comgt/files/getcarrier.gcom20
-rw-r--r--package/comgt/files/getcnum.gcom20
-rw-r--r--package/comgt/files/getimsi.gcom17
-rw-r--r--package/comgt/files/getstrength.gcom14
-rw-r--r--package/comgt/files/setmode.gcom26
-rw-r--r--package/comgt/files/setpin.gcom55
-rw-r--r--package/comgt/patches/001-compile_fix.patch23
-rw-r--r--package/compcache/Config.in29
-rw-r--r--package/compcache/Makefile75
-rw-r--r--package/compcache/files/compcache.config4
-rw-r--r--package/compcache/files/compcache.init48
-rw-r--r--package/compcache/patches/000-provide_lzo_kmod.patch647
-rw-r--r--package/compcache/patches/001-lzo-speed.patch181
-rw-r--r--package/compcache/patches/002-kernel-2.6.34-compat.patch10
-rw-r--r--package/compcache/patches/003-kernel-3.x-compat.patch31
-rw-r--r--package/crda/Makefile74
-rw-r--r--package/crda/files/hotplug.rule6
-rw-r--r--package/crda/patches/101-make_crypto_use_optional.patch13
-rw-r--r--package/cyassl/Makefile56
-rw-r--r--package/cyassl/patches/110-makefile_disable_examples_tests.patch46
-rw-r--r--package/cyassl/patches/120-makefile_destdir.patch71
-rw-r--r--package/cyassl/patches/130-configure_disable_pthreads_tests.patch444
-rw-r--r--package/dnsmasq/Makefile88
-rw-r--r--package/dnsmasq/files/dhcp.conf31
-rw-r--r--package/dnsmasq/files/dnsmasq.conf37
-rw-r--r--package/dnsmasq/files/dnsmasq.init529
-rw-r--r--package/dnsmasq/patches/0001-Set-prefix-on-link-bit-in-RAs.patch42
-rw-r--r--package/dnsmasq/patches/100-fix-dhcp-no-address-warning.patch49
-rw-r--r--package/dropbear/Makefile114
-rw-r--r--package/dropbear/files/dropbear.config5
-rwxr-xr-xpackage/dropbear/files/dropbear.init191
-rw-r--r--package/dropbear/patches/100-pubkey_path.patch91
-rw-r--r--package/dropbear/patches/110-change_user.patch18
-rw-r--r--package/dropbear/patches/120-openwrt_options.patch67
-rw-r--r--package/dropbear/patches/130-ssh_ignore_o_and_x_args.patch21
-rw-r--r--package/dropbear/patches/140-disable_assert.patch14
-rw-r--r--package/dropbear/patches/150-dbconvert_standalone.patch14
-rw-r--r--package/dropbear/patches/200-lcrypt_bsdfix.patch29
-rw-r--r--package/dropbear/patches/300-ipv6_addr_port_split.patch11
-rw-r--r--package/dropbear/patches/400-CVE-2012-0920.patch91
-rw-r--r--package/dropbear/patches/500-set-default-path.patch11
-rw-r--r--package/e2fsprogs/Makefile169
-rw-r--r--package/e2fsprogs/files/e2fsck.conf3
-rw-r--r--package/e2fsprogs/files/e2fsck.sh38
-rw-r--r--package/e2fsprogs/patches/001-link-against-libuuid.patch38
-rw-r--r--package/e2fsprogs/patches/002-no_malloc_h.patch10
-rw-r--r--package/ead/Makefile55
-rw-r--r--package/ead/src/Makefile33
-rw-r--r--package/ead/src/aes.c1061
-rw-r--r--package/ead/src/ead-client.c433
-rw-r--r--package/ead/src/ead-crypt.c179
-rw-r--r--package/ead/src/ead-crypt.h21
-rw-r--r--package/ead/src/ead-pcap.h71
-rw-r--r--package/ead/src/ead.c991
-rw-r--r--package/ead/src/ead.h139
-rw-r--r--package/ead/src/filter.c25
-rw-r--r--package/ead/src/libbridge.h84
-rw-r--r--package/ead/src/libbridge_init.c208
-rw-r--r--package/ead/src/libbridge_private.h35
-rw-r--r--package/ead/src/list.h602
-rw-r--r--package/ead/src/passwd3
-rw-r--r--package/ead/src/pfc.c54
-rw-r--r--package/ead/src/pw_encrypt_md5.c646
-rw-r--r--package/ead/src/sha1.c104
-rw-r--r--package/ead/src/tinysrp/Makefile.am28
-rw-r--r--package/ead/src/tinysrp/Makefile.in477
-rw-r--r--package/ead/src/tinysrp/Notes110
-rw-r--r--package/ead/src/tinysrp/acconfig.h9
-rw-r--r--package/ead/src/tinysrp/acinclude.m427
-rw-r--r--package/ead/src/tinysrp/aclocal.m4157
-rw-r--r--package/ead/src/tinysrp/bn.h471
-rw-r--r--package/ead/src/tinysrp/bn_add.c305
-rw-r--r--package/ead/src/tinysrp/bn_asm.c382
-rw-r--r--package/ead/src/tinysrp/bn_ctx.c142
-rw-r--r--package/ead/src/tinysrp/bn_div.c378
-rw-r--r--package/ead/src/tinysrp/bn_exp.c395
-rw-r--r--package/ead/src/tinysrp/bn_lcl.h419
-rw-r--r--package/ead/src/tinysrp/bn_lib.c576
-rw-r--r--package/ead/src/tinysrp/bn_mul.c176
-rw-r--r--package/ead/src/tinysrp/bn_prime.h325
-rw-r--r--package/ead/src/tinysrp/bn_shift.c139
-rw-r--r--package/ead/src/tinysrp/bn_sqr.c160
-rw-r--r--package/ead/src/tinysrp/bn_word.c130
-rw-r--r--package/ead/src/tinysrp/clitest.c112
-rw-r--r--package/ead/src/tinysrp/config.h.in79
-rwxr-xr-xpackage/ead/src/tinysrp/configure2421
-rw-r--r--package/ead/src/tinysrp/configure.in52
-rwxr-xr-xpackage/ead/src/tinysrp/install-sh250
-rwxr-xr-xpackage/ead/src/tinysrp/missing134
-rwxr-xr-xpackage/ead/src/tinysrp/mkinstalldirs39
-rw-r--r--package/ead/src/tinysrp/srvtest.c111
-rw-r--r--package/ead/src/tinysrp/stamp-h.in1
-rw-r--r--package/ead/src/tinysrp/t_client.c287
-rw-r--r--package/ead/src/tinysrp/t_client.h148
-rw-r--r--package/ead/src/tinysrp/t_conf.c1080
-rw-r--r--package/ead/src/tinysrp/t_conv.c226
-rw-r--r--package/ead/src/tinysrp/t_defines.h169
-rw-r--r--package/ead/src/tinysrp/t_getconf.c118
-rw-r--r--package/ead/src/tinysrp/t_getpass.c191
-rw-r--r--package/ead/src/tinysrp/t_math.c177
-rw-r--r--package/ead/src/tinysrp/t_misc.c338
-rw-r--r--package/ead/src/tinysrp/t_pw.c262
-rw-r--r--package/ead/src/tinysrp/t_pwd.h310
-rw-r--r--package/ead/src/tinysrp/t_read.c81
-rw-r--r--package/ead/src/tinysrp/t_read.h55
-rw-r--r--package/ead/src/tinysrp/t_server.c259
-rw-r--r--package/ead/src/tinysrp/t_server.h138
-rw-r--r--package/ead/src/tinysrp/t_sha.c166
-rw-r--r--package/ead/src/tinysrp/t_sha.h26
-rw-r--r--package/ead/src/tinysrp/t_truerand.c151
-rw-r--r--package/ead/src/tinysrp/tconf.c157
-rw-r--r--package/ead/src/tinysrp/tinysrp.c235
-rw-r--r--package/ead/src/tinysrp/tinysrp.h18
-rw-r--r--package/ead/src/tinysrp/tpasswd2
-rw-r--r--package/ead/src/tinysrp/tphrase.c348
-rw-r--r--package/ebtables/Makefile71
-rw-r--r--package/ep80579-drivers/Makefile92
-rw-r--r--package/ep80579-drivers/patches/001-igbe_update.patch11755
-rw-r--r--package/ep80579-drivers/patches/002-cflags_cleanup.patch22
-rw-r--r--package/ep80579-drivers/patches/003-new_irqf_constants.patch53
-rw-r--r--package/ep80579-drivers/patches/100-iegbe_netdev_ops.patch56
-rw-r--r--package/ep80579-drivers/patches/101-iegbe_fix_napi_interface.patch41
-rw-r--r--package/ep80579-drivers/patches/102-iegbe_nuke_polling_netdev.patch103
-rw-r--r--package/ep80579-drivers/patches/103-iegbe_convert_unicast_addr_list.patch60
-rw-r--r--package/ep80579-drivers/patches/104-iegbe_group_address_list_and_its_count.patch20
-rw-r--r--package/ep80579-drivers/patches/105-iegbe_new_dma_masks.patch20
-rw-r--r--package/ep80579-drivers/patches/106-iegbe_new_irqf_constant.patch12
-rw-r--r--package/ep80579-drivers/patches/150-ocracoke_island.patch747
-rw-r--r--package/ep80579-drivers/patches/200-can_fix_ioctl_numbers.patch11
-rw-r--r--package/ep80579-drivers/patches/210-can_include_linux_fs_h.patch11
-rw-r--r--package/ep80579-drivers/patches/220-can_fix_irq_request.patch23
-rw-r--r--package/ep80579-drivers/patches/230-can_remove_driver_data_direct_access.patch40
-rw-r--r--package/ep80579-drivers/patches/300-wdt_compile_fix.patch59
-rw-r--r--package/ep80579-drivers/patches/400-edma_fix_irq_request_warning.patch22
-rw-r--r--package/ep80579-drivers/patches/500-1588_fix_irq_request_warning.patch22
-rw-r--r--package/ep80579-drivers/patches/600-2.6.27_includes.patch22
-rw-r--r--package/ep80579-drivers/patches/601-2.6.32_includes.patch30
-rw-r--r--package/ep80579-drivers/patches/700-iegbe_kcompat_2.6.30.patch31
-rw-r--r--package/ep80579-drivers/patches/701-iegbe_poll_dev.patch11
-rw-r--r--package/ep80579-drivers/patches/710-3.3-fix-generated-header-locations.patch91
-rw-r--r--package/ep80579-drivers/patches/711-3.3-gbe-fixes.patch392
-rw-r--r--package/ep80579-drivers/patches/712-3.3-can-fixes.patch41
-rw-r--r--package/ep80579-drivers/patches/713-3.3-gpio-fixes.patch33
-rw-r--r--package/ep80579-drivers/patches/714-3.3-wdt-fixes.patch31
-rw-r--r--package/ep80579-drivers/patches/715-3.3-1588-fixes.patch33
-rw-r--r--package/fbtest/Makefile44
-rw-r--r--package/fbtest/src/Makefile14
-rw-r--r--package/fbtest/src/fbtest.c448
-rw-r--r--package/fconfig/Makefile45
-rw-r--r--package/firewall/Makefile58
-rw-r--r--package/firewall/files/bin/fw49
-rw-r--r--package/firewall/files/firewall.config176
-rw-r--r--package/firewall/files/firewall.hotplug22
-rwxr-xr-xpackage/firewall/files/firewall.init27
-rw-r--r--package/firewall/files/firewall.upgrade1
-rw-r--r--package/firewall/files/firewall.user4
-rw-r--r--package/firewall/files/lib/config.sh101
-rw-r--r--package/firewall/files/lib/core.sh159
-rw-r--r--package/firewall/files/lib/core_forwarding.sh44
-rw-r--r--package/firewall/files/lib/core_init.sh338
-rw-r--r--package/firewall/files/lib/core_interface.sh205
-rw-r--r--package/firewall/files/lib/core_redirect.sh130
-rw-r--r--package/firewall/files/lib/core_rule.sh110
-rw-r--r--package/firewall/files/lib/fw.sh324
-rw-r--r--package/firewall/files/lib/uci_firewall.sh5
-rw-r--r--package/firewall/files/reflection.hotplug132
-rw-r--r--package/fuse/Makefile108
-rw-r--r--package/fuse/patches/112-no_break_on_mknod.patch11
-rw-r--r--package/gdb/Makefile87
-rw-r--r--package/goldfish-qemu/Makefile70
-rw-r--r--package/goldfish-qemu/patches/100-darwin_fix.patch30
-rw-r--r--package/goldfish-qemu/patches/110-single_image.patch233
-rw-r--r--package/goldfish-qemu/skins/HVGA/arrow_down.pngbin0 -> 3438 bytes
-rw-r--r--package/goldfish-qemu/skins/HVGA/arrow_left.pngbin0 -> 4122 bytes
-rw-r--r--package/goldfish-qemu/skins/HVGA/arrow_right.pngbin0 -> 4147 bytes
-rw-r--r--package/goldfish-qemu/skins/HVGA/arrow_up.pngbin0 -> 3493 bytes
-rw-r--r--package/goldfish-qemu/skins/HVGA/back.pngbin0 -> 3564 bytes
-rw-r--r--package/goldfish-qemu/skins/HVGA/device.pngbin0 -> 45511 bytes
-rw-r--r--package/goldfish-qemu/skins/HVGA/end.pngbin0 -> 3562 bytes
-rw-r--r--package/goldfish-qemu/skins/HVGA/home.pngbin0 -> 3578 bytes
-rw-r--r--package/goldfish-qemu/skins/HVGA/key.pngbin0 -> 2857 bytes
-rw-r--r--package/goldfish-qemu/skins/HVGA/keyboard.pngbin0 -> 11032 bytes
-rw-r--r--package/goldfish-qemu/skins/HVGA/layout380
-rw-r--r--package/goldfish-qemu/skins/HVGA/menu.pngbin0 -> 3079 bytes
-rw-r--r--package/goldfish-qemu/skins/HVGA/power.pngbin0 -> 3782 bytes
-rw-r--r--package/goldfish-qemu/skins/HVGA/select.pngbin0 -> 3374 bytes
-rw-r--r--package/goldfish-qemu/skins/HVGA/send.pngbin0 -> 3561 bytes
-rw-r--r--package/goldfish-qemu/skins/HVGA/spacebar.pngbin0 -> 2916 bytes
-rw-r--r--package/goldfish-qemu/skins/HVGA/volume_down.pngbin0 -> 3586 bytes
-rw-r--r--package/goldfish-qemu/skins/HVGA/volume_up.pngbin0 -> 3856 bytes
-rw-r--r--package/gpio-button-hotplug/Makefile44
-rw-r--r--package/gpio-button-hotplug/src/Makefile1
-rw-r--r--package/gpio-button-hotplug/src/gpio-button-hotplug.c450
-rw-r--r--package/gpioctl/Makefile43
-rw-r--r--package/gpioctl/src/Makefile24
-rw-r--r--package/gpioctl/src/main.c76
-rw-r--r--package/grub/Makefile111
-rw-r--r--package/grub/patches/002-strip_note_gnu_build_id.patch22
-rw-r--r--package/grub/patches/010-fixes-1.patch4466
-rw-r--r--package/grub/patches/020-ext4_support.patch267
-rw-r--r--package/grub/patches/030-add-stage2-ldscripts.patch77
-rw-r--r--package/grub/patches/040-automake-compat.patch41
-rw-r--r--package/grub/patches/100-add_configure_macros.patch11
-rw-r--r--package/grub/patches/110-remove_configure_errors.patch38
-rw-r--r--package/grub/patches/200-darwin_fixes.patch48
-rw-r--r--package/grub/patches/210-remove_inline_asm.patch14
-rw-r--r--package/grub2/Makefile51
-rw-r--r--package/grub2/patches/100-grub_setup_root.patch77
-rw-r--r--package/hostap-driver/Makefile117
-rwxr-xr-xpackage/hostap-driver/files/lib/wifi/hostap.sh270
-rw-r--r--package/hostap-driver/patches/001-fix-txpower.patch175
-rw-r--r--package/hostap-utils/Makefile44
-rw-r--r--package/hostapd/Config.in47
-rw-r--r--package/hostapd/Makefile339
-rw-r--r--package/hostapd/files/hostapd-full.config164
-rw-r--r--package/hostapd/files/hostapd-mini.config157
-rw-r--r--package/hostapd/files/hostapd.sh276
-rw-r--r--package/hostapd/files/multicall.c28
-rw-r--r--package/hostapd/files/wpa_supplicant-full.config408
-rw-r--r--package/hostapd/files/wpa_supplicant-mini.config406
-rw-r--r--package/hostapd/files/wpa_supplicant.sh196
-rw-r--r--package/hostapd/files/wps-hotplug.sh6
-rw-r--r--package/hostapd/patches/100-pending_work.patch123
-rw-r--r--package/hostapd/patches/300-nl80211_multicall_fixes.patch60
-rw-r--r--package/hostapd/patches/310-multicall_bridge_fix.patch45
-rw-r--r--package/hostapd/patches/320-madwifi_key_fixes.patch34
-rw-r--r--package/hostapd/patches/400-noscan.patch32
-rw-r--r--package/hostapd/patches/410-multicall.patch246
-rw-r--r--package/hostapd/patches/420-timestamp_check.patch12
-rw-r--r--package/hostapd/patches/430-rescan_immediately.patch11
-rw-r--r--package/hostapd/patches/440-optional_rfkill.patch261
-rw-r--r--package/hostapd/patches/450-reload_freq_change.patch23
-rw-r--r--package/hostapd/patches/451-nl80211_del_beacon_bss.patch63
-rw-r--r--package/hostapd/patches/452-ctrl_iface_reload.patch98
-rw-r--r--package/hostapd/patches/453-ap_sta_support.patch221
-rw-r--r--package/hostapd/patches/460-disable_ctrl_iface_mib.patch168
-rw-r--r--package/hostapd/patches/470-wpa_ie_cap_workaround.patch56
-rw-r--r--package/hostapd/patches/480-terminate_on_setup_failure.patch81
-rw-r--r--package/hostapd/patches/500-random_pool_add_kernel.patch168
-rw-r--r--package/hostapd/patches/510-bring_down_interface.patch19
-rw-r--r--package/hostapd/patches/520-fix_wps_pin_crash.patch12
-rw-r--r--package/hostapd/patches/530-wps_single_auth_enc_type.patch25
-rw-r--r--package/hostapd/patches/540-dynamic_20_40_mhz.patch202
-rw-r--r--package/hostapd/patches/550-limit_debug_messages.patch213
-rw-r--r--package/hostapd/patches/560-indicate-features.patch82
-rw-r--r--package/hostapd/patches/570-genl_connect_debug.patch11
-rw-r--r--package/hostapd/patches/580-fix_bss_addr.patch11
-rw-r--r--package/hostapd/patches/590-hostapd_cli_ifdef.patch50
-rw-r--r--package/hostapd/patches/601-wpa_supplicant-add-new-config-params-to-be-used-with.patch211
-rw-r--r--package/hostapd/patches/602-driver_nl80211-use-new-parameters-during-ibss-join.patch59
-rw-r--r--package/hostapd/patches/604-wpa_s-support-htmode-param.patch156
-rw-r--r--package/hostapd/patches/610-max_num_sta_probe.patch13
-rw-r--r--package/hotplug2/Makefile65
-rw-r--r--package/hotplug2/files/hotplug2.rules10
-rw-r--r--package/hotplug2/patches/100-env_memleak.patch63
-rw-r--r--package/hotplug2/patches/110-static_worker.patch20
-rw-r--r--package/hotplug2/patches/120-sysfs_path_fix.patch14
-rw-r--r--package/hotplug2/patches/130-cancel_download_fix.patch18
-rw-r--r--package/hotplug2/patches/140-worker_fork_fix.patch56
-rw-r--r--package/hotplug2/patches/150-force_fork_slow.patch21
-rw-r--r--package/hotplug2/patches/160-event_block_fix.patch200
-rw-r--r--package/hotplug2/patches/170-non_fatal_include.patch21
-rw-r--r--package/hotplug2/src/udevtrigger.c345
-rw-r--r--package/i2c-gpio-custom/Makefile53
-rw-r--r--package/i2c-gpio-custom/src/Kconfig10
-rw-r--r--package/i2c-gpio-custom/src/Makefile1
-rw-r--r--package/i2c-gpio-custom/src/i2c-gpio-custom.c198
-rw-r--r--package/ifenslave/Makefile42
-rw-r--r--package/iproute2/Makefile115
-rw-r--r--package/iproute2/files/30-teql23
-rw-r--r--package/iproute2/patches/000-sync_pkt_sched_h.patch121
-rw-r--r--package/iproute2/patches/001-iproute2-2.6.11_Config.patch7
-rw-r--r--package/iproute2/patches/002-iproute2-ipxfrm_no_sctp.patch22
-rw-r--r--package/iproute2/patches/004-darwin_fixes.patch59
-rw-r--r--package/iproute2/patches/006-iproute2-tc_esfq.patch219
-rw-r--r--package/iproute2/patches/007-no_arpd.patch11
-rw-r--r--package/iproute2/patches/008-no_netem.patch11
-rw-r--r--package/iproute2/patches/100-allow_pfifo_fast.patch13
-rw-r--r--package/iproute2/patches/110-extra-ccopts.patch11
-rw-r--r--package/iproute2/patches/120-libnetlink-pic.patch8
-rw-r--r--package/iproute2/patches/200-act_connmark.patch84
-rw-r--r--package/iproute2/patches/210-add_codel.patch437
-rw-r--r--package/iptables/Makefile475
-rw-r--r--package/iptables/files/l7/aim.pat28
-rw-r--r--package/iptables/files/l7/bittorrent.pat25
-rw-r--r--package/iptables/files/l7/edonkey.pat37
-rw-r--r--package/iptables/files/l7/fasttrack.pat23
-rw-r--r--package/iptables/files/l7/ftp.pat46
-rw-r--r--package/iptables/files/l7/gnutella.pat34
-rw-r--r--package/iptables/files/l7/http.pat28
-rw-r--r--package/iptables/files/l7/ident.pat15
-rw-r--r--package/iptables/files/l7/irc.pat20
-rw-r--r--package/iptables/files/l7/jabber.pat24
-rw-r--r--package/iptables/files/l7/msnmessenger.pat28
-rw-r--r--package/iptables/files/l7/ntp.pat17
-rw-r--r--package/iptables/files/l7/pop3.pat50
-rw-r--r--package/iptables/files/l7/smtp.pat40
-rw-r--r--package/iptables/files/l7/ssl.pat16
-rw-r--r--package/iptables/files/l7/vnc.pat23
-rw-r--r--package/iptables/patches/002-layer7_2.22.patch371
-rw-r--r--package/iptables/patches/009-table-alignment.patch11
-rw-r--r--package/iptables/patches/010-multiport-linux-2.4-compat.patch265
-rw-r--r--package/iptables/patches/011-recent-add-reap.patch116
-rw-r--r--package/iptables/patches/020-iptables-disable-modprobe.patch18
-rw-r--r--package/iptables/patches/030-no-libnfnetlink.patch92
-rw-r--r--package/iptables/patches/100-bash-location.patch16
-rw-r--r--package/iptables/patches/110-linux_3.2_compat.patch12
-rw-r--r--package/iptables/patches/200-configurable_builtin.patch56
-rw-r--r--package/iw/Makefile54
-rw-r--r--package/iw/patches/001-nl80211_h_sync.patch96
-rw-r--r--package/iw/patches/100-rx_rate.patch105
-rw-r--r--package/iw/patches/110-per_chain_signal_strength.patch71
-rw-r--r--package/iw/patches/120-tdls_peer_indentation.patch11
-rw-r--r--package/iw/patches/130-antenna_gain.patch34
-rw-r--r--package/iwcap/Makefile50
-rw-r--r--package/iwcap/src/iwcap.c582
-rw-r--r--package/iwinfo/Makefile118
-rw-r--r--package/iwinfo/src/COPYING339
-rw-r--r--package/iwinfo/src/Makefile44
-rw-r--r--package/iwinfo/src/include/iwinfo.h190
-rw-r--r--package/iwinfo/src/include/iwinfo/api/broadcom.h131
-rw-r--r--package/iwinfo/src/include/iwinfo/api/madwifi.h160
-rw-r--r--package/iwinfo/src/include/iwinfo/api/nl80211.h2834
-rw-r--r--package/iwinfo/src/include/iwinfo/api/wext.h1139
-rw-r--r--package/iwinfo/src/include/iwinfo/lua.h80
-rw-r--r--package/iwinfo/src/include/iwinfo/madwifi.h83
-rw-r--r--package/iwinfo/src/include/iwinfo/nl80211.h125
-rw-r--r--package/iwinfo/src/include/iwinfo/utils.h47
-rw-r--r--package/iwinfo/src/include/iwinfo/wext.h84
-rw-r--r--package/iwinfo/src/include/iwinfo/wext_scan.h380
-rw-r--r--package/iwinfo/src/include/iwinfo/wl.h84
-rw-r--r--package/iwinfo/src/iwinfo_cli.c800
-rw-r--r--package/iwinfo/src/iwinfo_lib.c453
-rw-r--r--package/iwinfo/src/iwinfo_lua.c886
-rw-r--r--package/iwinfo/src/iwinfo_madwifi.c1082
-rw-r--r--package/iwinfo/src/iwinfo_nl80211.c2080
-rw-r--r--package/iwinfo/src/iwinfo_utils.c347
-rw-r--r--package/iwinfo/src/iwinfo_wext.c520
-rw-r--r--package/iwinfo/src/iwinfo_wext_scan.c527
-rw-r--r--package/iwinfo/src/iwinfo_wl.c645
-rw-r--r--package/ixp4xx-microcode/Makefile56
-rw-r--r--package/ixp4xx-microcode/src/IxNpeMicrocode.h144
-rw-r--r--package/ixp4xx-microcode/src/LICENSE.IPL27
-rw-r--r--package/kernel/Makefile49
-rw-r--r--package/kernel/modules/001-depends.mk37
-rw-r--r--package/kernel/modules/block.mk606
-rw-r--r--package/kernel/modules/crypto.mk473
-rw-r--r--package/kernel/modules/firewire.mk77
-rw-r--r--package/kernel/modules/fs.mk354
-rw-r--r--package/kernel/modules/hwmon.mk192
-rw-r--r--package/kernel/modules/i2c.mk274
-rw-r--r--package/kernel/modules/leds.mk152
-rw-r--r--package/kernel/modules/lib.mk167
-rw-r--r--package/kernel/modules/netdevices.mk665
-rw-r--r--package/kernel/modules/netfilter.mk573
-rw-r--r--package/kernel/modules/netsupport.mk865
-rw-r--r--package/kernel/modules/nls.mk228
-rw-r--r--package/kernel/modules/other.mk698
-rw-r--r--package/kernel/modules/pcmcia.mk80
-rw-r--r--package/kernel/modules/sound.mk184
-rw-r--r--package/kernel/modules/spi.mk90
-rw-r--r--package/kernel/modules/usb.mk899
-rw-r--r--package/kernel/modules/video.mk714
-rw-r--r--package/kernel/modules/virtual.mk171
-rw-r--r--package/kernel/modules/w1.mk160
-rw-r--r--package/kernel/modules/wireless.mk109
-rw-r--r--package/kexec-tools/Config.in21
-rw-r--r--package/kexec-tools/Makefile79
-rw-r--r--package/kexec-tools/patches/0004-mips_regdefs.patch103
-rw-r--r--package/libbsd/Makefile54
-rw-r--r--package/libipfix/Makefile47
-rw-r--r--package/libipfix/extra/append-wprobe-ie.pl38
-rw-r--r--package/libipfix/extra/wprobe-ie.txt14
-rw-r--r--package/libipfix/patches/100-openimp_sync.patch474
-rw-r--r--package/libipfix/patches/110-wprobe_ie.patch44
-rw-r--r--package/libipfix/patches/120-ipfixmisc.patch27
-rw-r--r--package/libjson-c/Makefile50
-rw-r--r--package/libnl-tiny/Makefile52
-rw-r--r--package/libnl-tiny/files/libnl-tiny.pc10
-rw-r--r--package/libnl-tiny/src/Makefile17
-rw-r--r--package/libnl-tiny/src/attr.c668
-rw-r--r--package/libnl-tiny/src/cache.c839
-rw-r--r--package/libnl-tiny/src/cache_mngt.c253
-rw-r--r--package/libnl-tiny/src/error.c108
-rw-r--r--package/libnl-tiny/src/genl.c268
-rw-r--r--package/libnl-tiny/src/genl_ctrl.c302
-rw-r--r--package/libnl-tiny/src/genl_family.c136
-rw-r--r--package/libnl-tiny/src/genl_mngt.c274
-rw-r--r--package/libnl-tiny/src/handlers.c162
-rw-r--r--package/libnl-tiny/src/include/linux/gen_stats.h67
-rw-r--r--package/libnl-tiny/src/include/linux/genetlink.h83
-rw-r--r--package/libnl-tiny/src/include/linux/if.h131
-rw-r--r--package/libnl-tiny/src/include/linux/if_addr.h62
-rw-r--r--package/libnl-tiny/src/include/linux/netlink.h150
-rw-r--r--package/libnl-tiny/src/include/netlink-generic.h20
-rw-r--r--package/libnl-tiny/src/include/netlink-local.h158
-rw-r--r--package/libnl-tiny/src/include/netlink-types.h81
-rw-r--r--package/libnl-tiny/src/include/netlink/addr.h69
-rw-r--r--package/libnl-tiny/src/include/netlink/attr.h726
-rw-r--r--package/libnl-tiny/src/include/netlink/cache-api.h199
-rw-r--r--package/libnl-tiny/src/include/netlink/cache.h128
-rw-r--r--package/libnl-tiny/src/include/netlink/data.h41
-rw-r--r--package/libnl-tiny/src/include/netlink/errno.h59
-rw-r--r--package/libnl-tiny/src/include/netlink/genl/ctrl.h37
-rw-r--r--package/libnl-tiny/src/include/netlink/genl/family.h130
-rw-r--r--package/libnl-tiny/src/include/netlink/genl/genl.h47
-rw-r--r--package/libnl-tiny/src/include/netlink/genl/mngt.h87
-rw-r--r--package/libnl-tiny/src/include/netlink/handlers.h230
-rw-r--r--package/libnl-tiny/src/include/netlink/list.h88
-rw-r--r--package/libnl-tiny/src/include/netlink/msg.h308
-rw-r--r--package/libnl-tiny/src/include/netlink/netlink-compat.h50
-rw-r--r--package/libnl-tiny/src/include/netlink/netlink-kernel.h196
-rw-r--r--package/libnl-tiny/src/include/netlink/netlink.h82
-rw-r--r--package/libnl-tiny/src/include/netlink/object-api.h331
-rw-r--r--package/libnl-tiny/src/include/netlink/object.h164
-rw-r--r--package/libnl-tiny/src/include/netlink/socket.h221
-rw-r--r--package/libnl-tiny/src/include/netlink/types.h121
-rw-r--r--package/libnl-tiny/src/include/netlink/utils.h78
-rw-r--r--package/libnl-tiny/src/include/netlink/version.h18
-rw-r--r--package/libnl-tiny/src/include/unl.h47
-rw-r--r--package/libnl-tiny/src/msg.c566
-rw-r--r--package/libnl-tiny/src/nl.c720
-rw-r--r--package/libnl-tiny/src/object.c279
-rw-r--r--package/libnl-tiny/src/socket.c406
-rw-r--r--package/libnl-tiny/src/unl.c290
-rw-r--r--package/libnl/Makefile56
-rw-r--r--package/libnl/patches/110-offsetof.patch12
-rw-r--r--package/libnl/patches/160-update_includes_for_iw.patch34
-rw-r--r--package/libpcap/Config.in15
-rw-r--r--package/libpcap/Makefile83
-rw-r--r--package/libpcap/patches/100-debian_shared_lib.patch178
-rw-r--r--package/libpcap/patches/102-makefile_disable_manpages.patch89
-rw-r--r--package/libpcap/patches/103-makefile_flex_workaround.patch14
-rw-r--r--package/libpcap/patches/201-space_optimization.patch133
-rw-r--r--package/libpcap/patches/202-protocol_api.patch141
-rw-r--r--package/libpcap/patches/203-undef_iw_mode_monitor.patch11
-rw-r--r--package/libreadline/Makefile66
-rw-r--r--package/libreadline/patches/100-fix_avr32_compile20
-rw-r--r--package/librpc/Makefile28
-rw-r--r--package/librpc/patches/100-compat_fix.patch214
-rw-r--r--package/libtool/Makefile49
-rw-r--r--package/libubox/Makefile64
-rw-r--r--package/linux-atm/Makefile153
-rwxr-xr-xpackage/linux-atm/files/br2684ctl90
-rw-r--r--package/linux-atm/patches/000-debian_16.patch270
-rw-r--r--package/linux-atm/patches/200-no_libfl.patch179
-rw-r--r--package/linux-atm/patches/300-objcopy_path.patch40
-rw-r--r--package/ltq-dsl-app/Config.in9
-rw-r--r--package/ltq-dsl-app/Makefile97
-rw-r--r--package/ltq-dsl-app/files/dsl_control316
-rw-r--r--package/ltq-dsl-app/files/dsl_notify.sh44
-rw-r--r--package/ltq-dsl/Config.in5
-rw-r--r--package/ltq-dsl/Makefile178
-rw-r--r--package/ltq-dsl/patches/100-dsl_compat.patch125
-rw-r--r--package/ltq-dsl/patches/110-fix_status_polling_loop.patch11
-rw-r--r--package/ltq-dsl/patches/500-portability.patch227
-rw-r--r--package/ltq-dsl/src/Makefile23
-rw-r--r--package/ltq-dsl/src/ifx_atm.h196
-rw-r--r--package/ltq-dsl/src/ifxmips_atm.h172
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_amazon_se.c324
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_ar9.c295
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_core.c4770
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_core.h271
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_danube.c326
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_fw_amazon_se.h3335
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_fw_ar9.h439
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_fw_ar9_retx.h611
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_fw_danube.h440
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_fw_danube_retx.h612
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_fw_regs_amazon_se.h30
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_fw_regs_ar9.h172
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_fw_regs_common.h546
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_fw_regs_danube.h178
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_fw_regs_vr9.h59
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_fw_vr9.h427
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_ppe_amazon_se.h94
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_ppe_ar9.h188
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_ppe_common.h365
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_ppe_danube.h129
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_ppe_vr9.h192
-rw-r--r--package/ltq-dsl/src/ifxmips_atm_vr9.c303
-rw-r--r--package/ltq-dsl/src/ifxmips_compat.h56
-rw-r--r--package/ltq-dsl/src/ifxmips_mei_interface.h702
-rw-r--r--package/ltq-dsl/src/lantiq_mei.c3038
-rw-r--r--package/ltq-ifxos/Makefile51
-rw-r--r--package/ltq-ifxos/patches/100-portability.patch11
-rw-r--r--package/ltq-ifxos/patches/120-fix_smp_lock.patch12
-rw-r--r--package/ltq-kpi2udp/Makefile48
-rw-r--r--package/ltq-kpi2udp/patches/100-configure.patch11
-rw-r--r--package/ltq-kpi2udp/patches/110-ifx_udp_redirect.patch29
-rw-r--r--package/ltq-tapi/Config.in88
-rw-r--r--package/ltq-tapi/Makefile70
-rw-r--r--package/ltq-tapi/patches/000-portability.patch82
-rw-r--r--package/ltq-tapi/patches/100-ifxmips.patch96
-rw-r--r--package/ltq-tapi/patches/200-linux-37.patch108
-rw-r--r--package/ltq-tapidemo/Config.in47
-rw-r--r--package/ltq-tapidemo/Makefile82
-rw-r--r--package/ltq-tapidemo/files/bringup_tapidemo89
-rw-r--r--package/ltq-tapidemo/patches/100-ifxmips.patch61
-rw-r--r--package/ltq-tapidemo/patches/110-filename.patch141
-rw-r--r--package/ltq-vmmc/Config.in95
-rw-r--r--package/ltq-vmmc/Makefile166
-rw-r--r--package/ltq-vmmc/files/vmmc.init19
-rw-r--r--package/ltq-vmmc/patches/000-portability.patch287
-rw-r--r--package/ltq-vmmc/patches/100-target.patch738
-rw-r--r--package/ltq-vmmc/patches/400-falcon.patch968
-rw-r--r--package/lua/Makefile178
-rw-r--r--package/lua/patches-host/010-lua-5.1.3-lnum-full-260308.patch3806
-rw-r--r--package/lua/patches-host/011-lnum-use-double.patch11
-rw-r--r--package/lua/patches-host/015-lnum-ppc-compat.patch13
-rw-r--r--package/lua/patches-host/030-archindependent-bytecode.patch115
-rw-r--r--package/lua/patches-host/100-no_readline.patch49
-rw-r--r--package/lua/patches/010-lua-5.1.3-lnum-full-260308.patch3736
-rw-r--r--package/lua/patches/011-lnum-use-double.patch11
-rw-r--r--package/lua/patches/015-lnum-ppc-compat.patch11
-rw-r--r--package/lua/patches/020-shared_liblua.patch140
-rw-r--r--package/lua/patches/030-archindependent-bytecode.patch111
-rw-r--r--package/lua/patches/100-no_readline.patch49
-rw-r--r--package/lua/patches/200-lua-path.patch15
-rw-r--r--package/lua/patches/300-opcode_performance.patch363
-rw-r--r--package/mac80211/Makefile1632
-rw-r--r--package/mac80211/files/b43-fwcutter-fw-dirname.patch16
-rwxr-xr-xpackage/mac80211/files/host_bin/b43-fwsquash.py122
-rw-r--r--package/mac80211/files/lib/wifi/mac80211.sh599
-rw-r--r--package/mac80211/files/regdb.txt697
-rw-r--r--package/mac80211/patches/000-disable_ethernet.patch12
-rw-r--r--package/mac80211/patches/001-disable_b44.patch13
-rw-r--r--package/mac80211/patches/002-disable_rfkill.patch38
-rw-r--r--package/mac80211/patches/003-disable_bt.patch15
-rw-r--r--package/mac80211/patches/005-disable_ssb_build.patch49
-rw-r--r--package/mac80211/patches/006-disable_bcma_build.patch30
-rw-r--r--package/mac80211/patches/007-remove_misc_drivers.patch61
-rw-r--r--package/mac80211/patches/008-disable_mesh.patch11
-rw-r--r--package/mac80211/patches/009-remove_mac80211_module_dependence.patch11
-rw-r--r--package/mac80211/patches/010-no_pcmcia.patch20
-rw-r--r--package/mac80211/patches/011-no_sdio.patch11
-rw-r--r--package/mac80211/patches/013-disable_b43_nphy.patch13
-rw-r--r--package/mac80211/patches/015-remove-rt2x00-options.patch20
-rw-r--r--package/mac80211/patches/016-remove_pid_algo.patch11
-rw-r--r--package/mac80211/patches/017-remove_ath9k_rc.patch11
-rw-r--r--package/mac80211/patches/018-revert_printk_va_format.patch188
-rw-r--r--package/mac80211/patches/019-remove_ath5k_pci_option.patch11
-rw-r--r--package/mac80211/patches/021-add_include_for_bcma.patch11
-rw-r--r--package/mac80211/patches/022-remove_crc8_and_cordic.patch166
-rw-r--r--package/mac80211/patches/023-ath9k_disable_btcoex.patch11
-rw-r--r--package/mac80211/patches/030-disable_tty_set_termios.patch16
-rw-r--r--package/mac80211/patches/050-compat_firmware.patch78
-rw-r--r--package/mac80211/patches/060-compat_add_module_pci_driver.patch22
-rw-r--r--package/mac80211/patches/070-disable_codel.patch19
-rw-r--r--package/mac80211/patches/071-add_codel_ifdef.patch19
-rw-r--r--package/mac80211/patches/100-disable_pcmcia_compat.patch65
-rw-r--r--package/mac80211/patches/110-disable_usb_compat.patch44
-rw-r--r--package/mac80211/patches/130-mesh_pathtbl_backport.patch10
-rw-r--r--package/mac80211/patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch38
-rw-r--r--package/mac80211/patches/300-pending_work.patch592
-rw-r--r--package/mac80211/patches/310-ap_scan.patch11
-rw-r--r--package/mac80211/patches/400-ath_move_debug_code.patch28
-rw-r--r--package/mac80211/patches/401-ath9k_blink_default.patch11
-rw-r--r--package/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch29
-rw-r--r--package/mac80211/patches/403-ath_regd_optional.patch46
-rw-r--r--package/mac80211/patches/404-world_regd_fixup.patch84
-rw-r--r--package/mac80211/patches/405-regd_no_assoc_hints.patch20
-rw-r--r--package/mac80211/patches/406-ath_regd_us.patch26
-rw-r--r--package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch10
-rw-r--r--package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch46
-rw-r--r--package/mac80211/patches/412-mac80211_allow_adhoc_and_ap.patch20
-rw-r--r--package/mac80211/patches/420-ath5k_disable_fast_cc.patch18
-rw-r--r--package/mac80211/patches/430-add_ath5k_platform.patch33
-rw-r--r--package/mac80211/patches/431-add_platform_eeprom_support_to_ath5k.patch56
-rw-r--r--package/mac80211/patches/432-ath5k_add_pciids.patch11
-rw-r--r--package/mac80211/patches/440-ath5k_channel_bw_debugfs.patch113
-rw-r--r--package/mac80211/patches/500-ath9k_eeprom_debugfs.patch65
-rw-r--r--package/mac80211/patches/501-ath9k-eeprom_endianess.patch102
-rw-r--r--package/mac80211/patches/502-ath9k_ahb_init.patch32
-rw-r--r--package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch13
-rw-r--r--package/mac80211/patches/511-ath9k_reduce_rxbuf.patch11
-rw-r--r--package/mac80211/patches/512-ath9k_channelbw_debugfs.patch128
-rw-r--r--package/mac80211/patches/513-mac80211_reduce_txqueuelen.patch10
-rw-r--r--package/mac80211/patches/520-mac80211_cur_txpower.patch31
-rw-r--r--package/mac80211/patches/521-ath9k_cur_txpower.patch19
-rw-r--r--package/mac80211/patches/522-ath9k_per_chain_signal_strength.patch384
-rw-r--r--package/mac80211/patches/523-cfg80211_fix_antenna_gain.patch12
-rw-r--r--package/mac80211/patches/524-mac80211_configure_antenna_gain.patch179
-rw-r--r--package/mac80211/patches/525-ath9k_use_configured_antenna_gain.patch34
-rw-r--r--package/mac80211/patches/526-cfg80211_fix_max_reg_power.patch21
-rw-r--r--package/mac80211/patches/530-ath9k_fix_initvals.patch208
-rw-r--r--package/mac80211/patches/540-ath9k_extra_leds.patch258
-rw-r--r--package/mac80211/patches/541-ath9k_extra_platform_leds.patch71
-rw-r--r--package/mac80211/patches/550-mac80211_optimize_mcs_rate_mask.patch98
-rw-r--r--package/mac80211/patches/551-ath9k_optimize_interrupt_mitigation.patch30
-rw-r--r--package/mac80211/patches/560-ath9k_reduce_ani_interval.patch11
-rw-r--r--package/mac80211/patches/561-ath9k_revert_initval_change.patch19
-rw-r--r--package/mac80211/patches/562-ath9k_add_idle_hack.patch20
-rw-r--r--package/mac80211/patches/563-ath9k_rx_dma_stop_check.patch28
-rw-r--r--package/mac80211/patches/564-ath9k_debugfs_diag.patch139
-rw-r--r--package/mac80211/patches/565-ath9k_disable_paprd.patch72
-rw-r--r--package/mac80211/patches/566-ath9k_use_ieee80211_free_txskb.patch149
-rw-r--r--package/mac80211/patches/600-rt2x00-disable-pci-code-if-CONFIG_PCI-not-defined.patch18
-rw-r--r--package/mac80211/patches/601-rt2x00-set_pci_mwi.patch13
-rw-r--r--package/mac80211/patches/602-rt2x00-introduce-rt2x00_platform_h.patch32
-rw-r--r--package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch274
-rw-r--r--package/mac80211/patches/604-rt2x00-add-CONFIG_RT2X00_LIB_EEPROM-option.patch10
-rw-r--r--package/mac80211/patches/605-rt2x00-pci-eeprom.patch46
-rw-r--r--package/mac80211/patches/606-rt2x00_no_realign.patch67
-rw-r--r--package/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch47
-rw-r--r--package/mac80211/patches/608-add_platform_data_mac_addr.patch63
-rw-r--r--package/mac80211/patches/620-rt2x00-support-rt3352.patch464
-rw-r--r--package/mac80211/patches/621-rt2x00-fix-rt3352-lnagain.patch30
-rw-r--r--package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch10
-rw-r--r--package/mac80211/patches/800-b43-gpio-mask-module-option.patch37
-rw-r--r--package/mac80211/patches/810-b43_no_pio.patch75
-rw-r--r--package/mac80211/patches/820-b43-add-antenna-control.patch131
-rw-r--r--package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch134
-rw-r--r--package/mac80211/patches/849-brcmsmac-add-device-found-on-some-SoCs-like-the-bcm4.patch39
-rw-r--r--package/mac80211/patches/850-brcmsmac-add-support-for-BCM43224.patch29
-rw-r--r--package/mac80211/patches/851-brcmsmac-start-adding-support-for-core-rev-28.patch75
-rw-r--r--package/maccalc/Makefile47
-rw-r--r--package/maccalc/src/Makefile14
-rw-r--r--package/maccalc/src/main.c256
-rw-r--r--package/madwifi/Config.in55
-rw-r--r--package/madwifi/Makefile266
-rw-r--r--package/madwifi/files/etc/hotplug.d/net/10-madwifi12
-rwxr-xr-xpackage/madwifi/files/lib/wifi/madwifi.sh498
-rw-r--r--package/madwifi/files/lib/wifi/madwifi_countrycodes.txt239
-rw-r--r--package/madwifi/patches/102-multicall_binary.patch315
-rw-r--r--package/madwifi/patches/104-autocreate_none.patch11
-rw-r--r--package/madwifi/patches/105-ratectl_attach.patch23
-rw-r--r--package/madwifi/patches/106-get_arch.patch21
-rw-r--r--package/madwifi/patches/111-minstrel_crash.patch12
-rw-r--r--package/madwifi/patches/113-no_ibss_pwrsave.patch12
-rw-r--r--package/madwifi/patches/122-replayfail_workaround.patch12
-rw-r--r--package/madwifi/patches/123-ccmp_checks.patch95
-rw-r--r--package/madwifi/patches/124-linux24_compat.patch202
-rw-r--r--package/madwifi/patches/126-rxerr_frames.patch13
-rw-r--r--package/madwifi/patches/200-no_debug.patch408
-rw-r--r--package/madwifi/patches/201-debug_fix.patch20
-rw-r--r--package/madwifi/patches/202-debug_variables.patch204
-rw-r--r--package/madwifi/patches/300-napi_polling.patch536
-rw-r--r--package/madwifi/patches/305-pureg_fix.patch168
-rw-r--r--package/madwifi/patches/309-micfail_detect.patch321
-rw-r--r--package/madwifi/patches/310-noise_get.patch55
-rw-r--r--package/madwifi/patches/311-bssid_alloc.patch11
-rw-r--r--package/madwifi/patches/312-erpupdate.patch68
-rw-r--r--package/madwifi/patches/317-bmask.patch13
-rw-r--r--package/madwifi/patches/323-dfs_optional.patch38
-rw-r--r--package/madwifi/patches/324-alignment.patch19
-rw-r--r--package/madwifi/patches/325-channel_spam.patch28
-rw-r--r--package/madwifi/patches/327-queue.patch40
-rw-r--r--package/madwifi/patches/330-beaconcal.patch166
-rw-r--r--package/madwifi/patches/331-memory_alloc.patch36
-rw-r--r--package/madwifi/patches/332-reset_beacons.patch11
-rw-r--r--package/madwifi/patches/333-apscan_mode.patch15
-rw-r--r--package/madwifi/patches/334-input.patch12
-rw-r--r--package/madwifi/patches/340-maxrate.patch98
-rw-r--r--package/madwifi/patches/341-minrate.patch114
-rw-r--r--package/madwifi/patches/342-performance.patch263
-rw-r--r--package/madwifi/patches/343-txqueue_races.patch34
-rw-r--r--package/madwifi/patches/344-minstrel_failcnt.patch11
-rw-r--r--package/madwifi/patches/345-minstrel_sampling.patch80
-rw-r--r--package/madwifi/patches/346-protmode_trig.patch135
-rw-r--r--package/madwifi/patches/347-tuning.patch99
-rw-r--r--package/madwifi/patches/348-ackcts.patch38
-rw-r--r--package/madwifi/patches/349-reset.patch12
-rw-r--r--package/madwifi/patches/350-wisoc_softled.patch11
-rw-r--r--package/madwifi/patches/351-scanlist.patch904
-rw-r--r--package/madwifi/patches/352-ani_fix.patch265
-rw-r--r--package/madwifi/patches/353-devid.patch19
-rw-r--r--package/madwifi/patches/354-lantiq_eeprom.patch95
-rw-r--r--package/madwifi/patches/355-eap_auth_disassoc.patch77
-rw-r--r--package/madwifi/patches/356-hidden_ssid.patch49
-rw-r--r--package/madwifi/patches/357-bgscan_thresh.patch160
-rw-r--r--package/madwifi/patches/358-ignore_broken_bssid.patch18
-rw-r--r--package/madwifi/patches/359-disable_reassoc.patch31
-rw-r--r--package/madwifi/patches/360-sta_nodes.patch242
-rw-r--r--package/madwifi/patches/361-bmiss_handling.patch102
-rw-r--r--package/madwifi/patches/362-rssithr.patch93
-rw-r--r--package/madwifi/patches/363-fix_turbo.patch11
-rw-r--r--package/madwifi/patches/364-memory_alloc.patch13
-rw-r--r--package/madwifi/patches/365-turbo_channelsearch.patch10
-rw-r--r--package/madwifi/patches/366-bstuck_thresh.patch52
-rw-r--r--package/madwifi/patches/367-roaming.patch77
-rw-r--r--package/madwifi/patches/368-sta_ie_preserve.patch49
-rw-r--r--package/madwifi/patches/369-mlme_assoc.patch10
-rw-r--r--package/madwifi/patches/370-wdsvap.patch1665
-rw-r--r--package/madwifi/patches/372-queue_vif.patch39
-rw-r--r--package/madwifi/patches/373-sanity_check.patch12
-rw-r--r--package/madwifi/patches/374-nbtt_fix.patch22
-rw-r--r--package/madwifi/patches/375-atim_tsf_update.patch141
-rw-r--r--package/madwifi/patches/377-disable_vlan_code.patch25
-rw-r--r--package/madwifi/patches/378-adhoc_crash_fix.patch14
-rw-r--r--package/madwifi/patches/379-invalid_rate_fix.patch405
-rw-r--r--package/madwifi/patches/380-noderef_hack.patch13
-rw-r--r--package/madwifi/patches/381-ibss_modes.patch23
-rw-r--r--package/madwifi/patches/382-relax_bintval.patch13
-rw-r--r--package/madwifi/patches/383-ibss_hostap.patch105
-rw-r--r--package/madwifi/patches/384-hwdetect.patch325
-rw-r--r--package/madwifi/patches/385-antenna_fix.patch10
-rw-r--r--package/madwifi/patches/386-acl_crashfix.patch116
-rw-r--r--package/madwifi/patches/387-maxassoc.patch85
-rw-r--r--package/madwifi/patches/388-apsta_fix.patch60
-rw-r--r--package/madwifi/patches/389-autochannel.patch249
-rw-r--r--package/madwifi/patches/390-frame_type.patch13
-rw-r--r--package/madwifi/patches/391-vap_auth.patch29
-rw-r--r--package/madwifi/patches/392-remove_wds_nodetracking.patch388
-rw-r--r--package/madwifi/patches/393-mbss_vap_auth.patch491
-rw-r--r--package/madwifi/patches/394-probereq.patch64
-rw-r--r--package/madwifi/patches/395-ath_ff_unmap.patch11
-rw-r--r--package/madwifi/patches/396-napi_ff_fix.patch65
-rw-r--r--package/madwifi/patches/400-new_hal.patch153
-rw-r--r--package/madwifi/patches/401-changeset_r3602.patch11
-rw-r--r--package/madwifi/patches/402-changeset_r3603.patch176
-rw-r--r--package/madwifi/patches/403-changeset_r3605.patch70
-rw-r--r--package/madwifi/patches/404-linux24_fix.patch15
-rw-r--r--package/madwifi/patches/405-retransmit_check.patch22
-rw-r--r--package/madwifi/patches/406-monitor_r3711.patch20
-rw-r--r--package/madwifi/patches/407-new_athinfo.patch2352
-rw-r--r--package/madwifi/patches/408-changeset_r3337.patch34
-rw-r--r--package/madwifi/patches/409-wext_compat.patch133
-rw-r--r--package/madwifi/patches/410-ar231x_2.6.28.patch281
-rw-r--r--package/madwifi/patches/411-autochannel_multi.patch347
-rw-r--r--package/madwifi/patches/412-fragmentation_fix.patch10
-rw-r--r--package/madwifi/patches/413-rxorn.patch31
-rw-r--r--package/madwifi/patches/414-txpower.patch262
-rw-r--r--package/madwifi/patches/415-chan_switch.patch187
-rw-r--r--package/madwifi/patches/416-wprobe.patch549
-rw-r--r--package/madwifi/patches/417-beacon_txpower.patch81
-rw-r--r--package/madwifi/patches/419-skb_unmap_crash.patch20
-rw-r--r--package/madwifi/patches/420-diversity_fix.patch86
-rw-r--r--package/madwifi/patches/421-channel_handling.patch1351
-rw-r--r--package/madwifi/patches/422-confchange_reset.patch31
-rw-r--r--package/madwifi/patches/423-phyerr_handling.patch28
-rw-r--r--package/madwifi/patches/424-timing.patch764
-rw-r--r--package/madwifi/patches/425-rc_rexmit.patch506
-rw-r--r--package/madwifi/patches/426-header_len.patch12
-rw-r--r--package/madwifi/patches/427-ignore_eeprom_ff.patch11
-rw-r--r--package/madwifi/patches/430-use_netdev_priv.patch1936
-rw-r--r--package/madwifi/patches/431-compile_fixes.patch35
-rw-r--r--package/madwifi/patches/432-netdev_ops.patch184
-rw-r--r--package/madwifi/patches/433-backport_remove_irq_none.patch21
-rw-r--r--package/madwifi/patches/434-name-alloc-fix.patch28
-rw-r--r--package/madwifi/patches/435-ibss_neighbor_fix.patch11
-rw-r--r--package/madwifi/patches/436-injection_checks.patch26
-rw-r--r--package/madwifi/patches/437-sysctl_cleanup.patch73
-rw-r--r--package/madwifi/patches/438-poweroffset_sysctl.patch59
-rw-r--r--package/madwifi/patches/439-wlanconfig_stack_usage.patch20
-rw-r--r--package/madwifi/patches/440-wme_cleanup.patch136
-rw-r--r--package/madwifi/patches/441-fix_ibss_node_handling.patch91
-rw-r--r--package/madwifi/patches/442-ibss_rx_filter.patch20
-rw-r--r--package/madwifi/patches/443-tx_drop_counter.patch25
-rw-r--r--package/madwifi/patches/444-beacon_update_war.patch17
-rw-r--r--package/madwifi/patches/445-fix_ps_sta_count.patch18
-rw-r--r--package/madwifi/patches/446-single_module.patch778
-rw-r--r--package/madwifi/patches/447-sta_reconnect.patch25
-rw-r--r--package/madwifi/patches/448-beacon_handling_fixes.patch407
-rw-r--r--package/madwifi/patches/449-fix_txbuf_leak.patch10
-rw-r--r--package/madwifi/patches/450-calibration.patch177
-rw-r--r--package/madwifi/patches/451-ibss_race_fix.patch342
-rw-r--r--package/madwifi/patches/452-minstrel_no_timer.patch134
-rw-r--r--package/madwifi/patches/453-procps.patch55
-rw-r--r--package/madwifi/patches/454-cca.patch186
-rw-r--r--package/madwifi/patches/455-beacon_watchdog.patch95
-rw-r--r--package/madwifi/patches/456-rfsilent.patch85
-rw-r--r--package/madwifi/patches/457-idletime.patch151
-rw-r--r--package/madwifi/patches/458-ibss_wpa_none.patch13
-rw-r--r--package/madwifi/patches/459-2.6.33_compile.patch524
-rw-r--r--package/madwifi/patches/460-pci_softled_disable.patch18
-rw-r--r--package/madwifi/patches/461-rx_stats_count_fix.patch23
-rw-r--r--package/madwifi/patches/462-fix_ap_scan.patch26
-rw-r--r--package/madwifi/patches/463-fix_txrate_display.patch10
-rw-r--r--package/madwifi/patches/464-0dbm_txpower_fix.patch30
-rw-r--r--package/madwifi/patches/465-mc_list-2.6.35.patch40
-rw-r--r--package/madwifi/patches/466-2.6.38_compile.patch14
-rw-r--r--package/madwifi/patches/470-mac_addresss_from_ath5k_platform_data.patch36
-rw-r--r--package/madwifi/patches/471-netdev_ops_mac_mtu.patch30
-rw-r--r--package/madwifi/patches/472-remove_11n_devids.patch20
-rw-r--r--package/madwifi/patches/473-mutex_fix.patch11
-rw-r--r--package/madwifi/patches/474_fix_ssid_scan_length.patch29
-rw-r--r--package/madwifi/patches/475-2.6.39-compile.patch11
-rw-r--r--package/madwifi/patches/476-3.0_detection_fix.patch25
-rw-r--r--package/madwifi/patches/477-3.2_fixes.patch45
-rw-r--r--package/madwifi/patches/478-remove_vlan_code.patch21
-rw-r--r--package/mkelfimage/Makefile35
-rw-r--r--package/mkelfimage/patches/no-stack-protector.patch11
-rw-r--r--package/mmc_over_gpio/Makefile78
-rw-r--r--package/mmc_over_gpio/files/mmc_over_gpio.config8
-rw-r--r--package/mmc_over_gpio/files/mmc_over_gpio.init83
-rw-r--r--package/mountd/Makefile46
-rw-r--r--package/mountd/files/mountd.config3
-rwxr-xr-xpackage/mountd/files/mountd.init19
-rw-r--r--package/mountd/patches/010-uci_rename_history_to_delta.patch27
-rw-r--r--package/mountd/patches/020-handle_timeout.patch32
-rw-r--r--package/mountd/patches/030-ext4_support.patch85
-rw-r--r--package/mountd/patches/040-optional-daemonize.patch13
-rw-r--r--package/mtd/Makefile50
-rw-r--r--package/mtd/src/Makefile16
l---------package/mtd/src/bcm_tag.h1
-rw-r--r--package/mtd/src/crc32.c95
-rw-r--r--package/mtd/src/crc32.h26
-rw-r--r--package/mtd/src/fis.c262
-rw-r--r--package/mtd/src/fis.h14
-rw-r--r--package/mtd/src/imagetag.c315
-rw-r--r--package/mtd/src/jffs2.c357
-rw-r--r--package/mtd/src/jffs2.h216
-rw-r--r--package/mtd/src/mtd.c750
-rw-r--r--package/mtd/src/mtd.h28
-rw-r--r--package/mtd/src/trx.c220
-rw-r--r--package/ncurses/Makefile151
-rw-r--r--package/ncurses/patches/100-ncurses-5.6-20080112-urxvt.patch175
-rw-r--r--package/ncurses/patches/101-ncurses-5.6-20080628-kbs.patch52
-rw-r--r--package/ncurses/patches/500-cross.patch11
-rw-r--r--package/ncurses/patches/900-terminfo.patch20
-rw-r--r--package/netifd/Makefile40
-rw-r--r--package/netifd/files/etc/hotplug.d/iface/00-netstate8
-rw-r--r--package/netifd/files/etc/hotplug.d/iface/10-sysctl36
-rwxr-xr-xpackage/netifd/files/etc/init.d/network47
-rwxr-xr-xpackage/netifd/files/lib/netifd/dhcp.script59
-rwxr-xr-xpackage/netifd/files/lib/netifd/proto/dhcp.sh49
-rwxr-xr-xpackage/netifd/files/lib/network/config.sh79
-rwxr-xr-xpackage/netifd/files/sbin/devstatus12
l---------package/netifd/files/sbin/ifdown1
-rwxr-xr-xpackage/netifd/files/sbin/ifstatus13
-rwxr-xr-xpackage/netifd/files/sbin/ifup79
-rwxr-xr-xpackage/netifd/files/usr/share/udhcpc/default.script57
-rw-r--r--package/nvram/Makefile60
-rwxr-xr-xpackage/nvram/files/nvram.init98
-rw-r--r--package/nvram/src/Makefile33
-rw-r--r--package/nvram/src/cli.c246
-rw-r--r--package/nvram/src/crc.c69
-rw-r--r--package/nvram/src/nvram.c556
-rw-r--r--package/nvram/src/nvram.h123
-rw-r--r--package/nvram/src/sdinitvals.h30
-rw-r--r--package/ocf-crypto-headers/Makefile36
-rw-r--r--package/ocf-crypto-headers/src/cryptodev.h480
-rw-r--r--package/om-watchdog/Makefile45
-rw-r--r--package/om-watchdog/files/om-watchdog15
-rw-r--r--package/om-watchdog/files/om-watchdog.init24
-rw-r--r--package/openssl/Config.in13
-rw-r--r--package/openssl/Makefile179
-rw-r--r--package/openssl/patches/110-optimize-for-size.patch13
-rw-r--r--package/openssl/patches/130-perl-path.patch64
-rw-r--r--package/openssl/patches/140-makefile-dirs.patch11
-rw-r--r--package/openssl/patches/150-no_engines.patch81
-rw-r--r--package/openssl/patches/160-disable_doc_tests.patch58
-rw-r--r--package/openssl/patches/170-bash_path.patch8
-rw-r--r--package/openssl/patches/180-fix_link_segfault.patch18
-rw-r--r--package/openssl/patches/190-remove_timestamp_check.patch23
-rw-r--r--package/openssl/patches/200-etrax_support.patch13
-rw-r--r--package/openssl/patches/210-fix_aes_mips.patch64
-rw-r--r--package/opkg/Makefile99
-rw-r--r--package/opkg/files/opkg.conf5
-rw-r--r--package/opkg/patches/001-ship-pkg-m4.patch168
-rw-r--r--package/opkg/patches/002-no-shave.patch37
-rw-r--r--package/opkg/patches/004-host_cpu.patch20
-rw-r--r--package/opkg/patches/007-force_static.patch71
-rw-r--r--package/opkg/patches/009-remove-upgrade-all.patch41
-rw-r--r--package/opkg/patches/011-old-config-location.patch12
-rw-r--r--package/opkg/patches/012-strip-trailing-conffiles-whitespace.patch23
-rw-r--r--package/opkg/patches/014-errors-to-stderr.patch15
-rw-r--r--package/opkg/patches/020-avoid_getline.patch317
-rw-r--r--package/opkg/patches/030-fix-double-free.patch10
-rw-r--r--package/owipcalc/Makefile49
-rw-r--r--package/owipcalc/src/owipcalc.c951
-rw-r--r--package/owsip/Makefile73
-rw-r--r--package/owsip/files/telephony.conf32
-rwxr-xr-xpackage/owsip/files/telephony.defaults55
-rw-r--r--package/owsip/files/telephony.init33
-rw-r--r--package/pjsip/Makefile101
-rw-r--r--package/pjsip/patches/0001-configure-fixup.patch78
-rw-r--r--package/pjsip/patches/0002-register-tapi.patch1333
-rw-r--r--package/pjsip/patches/0003-adds-PJ_DEF-pj_status_t-pjsua_add_snd_port-int-id.patch207
-rw-r--r--package/ppp/Makefile262
-rw-r--r--package/ppp/files/etc/ppp/chap-secrets1
-rw-r--r--package/ppp/files/etc/ppp/filter23
-rw-r--r--package/ppp/files/etc/ppp/options10
-rw-r--r--package/ppp/files/etc/ppp/options.pptp7
-rw-r--r--package/ppp/files/etc/ppp/radius.conf8
-rw-r--r--package/ppp/files/etc/ppp/radius/dictionary253
-rw-r--r--package/ppp/files/etc/ppp/radius/dictionary.asnet3
-rw-r--r--package/ppp/files/etc/ppp/radius/dictionary.microsoft80
-rw-r--r--package/ppp/files/etc/ppp/radius/servers2
-rwxr-xr-xpackage/ppp/files/lib/netifd/ppp-down13
-rwxr-xr-xpackage/ppp/files/lib/netifd/ppp-up22
-rwxr-xr-xpackage/ppp/files/ppp.sh222
-rw-r--r--package/ppp/patches/010-use_target_for_configure.patch24
-rw-r--r--package/ppp/patches/100-debian_ip-ip_option.patch96
-rw-r--r--package/ppp/patches/101-debian_close_dev_ppp.patch28
-rw-r--r--package/ppp/patches/103-debian_fix_link_pidfile.patch23
-rw-r--r--package/ppp/patches/105-debian_demand.patch172
-rw-r--r--package/ppp/patches/106-debian_stripMSdomain.patch47
-rw-r--r--package/ppp/patches/107-debian_pppoatm_wildcard.patch25
-rw-r--r--package/ppp/patches/110-debian_defaultroute.patch313
-rw-r--r--package/ppp/patches/120-debian_ipv6_updown_option.patch95
-rw-r--r--package/ppp/patches/200-makefile.patch55
-rw-r--r--package/ppp/patches/201-mppe_mppc_1.1.patch1495
-rw-r--r--package/ppp/patches/202-no_strip.patch88
-rw-r--r--package/ppp/patches/203-opt_flags.patch32
-rw-r--r--package/ppp/patches/204-radius_config.patch72
-rw-r--r--package/ppp/patches/205-no_exponential_timeout.patch29
-rw-r--r--package/ppp/patches/206-compensate_time_change.patch94
-rw-r--r--package/ppp/patches/207-lcp_mtu_max.patch25
-rw-r--r--package/ppp/patches/208-fix_status_code.patch24
-rw-r--r--package/ppp/patches/300-filter-pcap-includes-lib.patch20
-rw-r--r--package/ppp/patches/310-precompile_filter.patch196
-rw-r--r--package/ppp/patches/320-custom_iface_names.patch135
-rw-r--r--package/ppp/patches/330-retain_foreign_default_routes.patch22
-rw-r--r--package/ppp/patches/340-populate_default_gateway.patch34
-rw-r--r--package/ppp/patches/400-simplify_kernel_checks.patch154
-rw-r--r--package/ppp/patches/401-no_record_file.patch39
-rw-r--r--package/ppp/patches/403-no_wtmp.patch25
-rw-r--r--package/ppp/patches/404-remove_obsolete_protocol_names.patch151
-rw-r--r--package/ppp/patches/405-no_multilink_option.patch28
-rw-r--r--package/ppp/patches/430-pppol2tpv3-struct.patch30
-rw-r--r--package/ppp/patches/500-add-pptp-plugin.patch3065
-rw-r--r--package/ppp/utils/pfc.c51
-rw-r--r--package/ps3-utils/Makefile70
-rw-r--r--package/px5g/Makefile40
-rw-r--r--package/px5g/src/Makefile14
-rw-r--r--package/px5g/src/library/base64.c264
-rw-r--r--package/px5g/src/library/bignum.c2010
-rw-r--r--package/px5g/src/library/havege.c276
-rw-r--r--package/px5g/src/library/rsa.c750
-rw-r--r--package/px5g/src/library/sha1.c622
-rw-r--r--package/px5g/src/library/timing.c265
-rw-r--r--package/px5g/src/library/x509write.c1139
-rw-r--r--package/px5g/src/polarssl/base64.h93
-rw-r--r--package/px5g/src/polarssl/bignum.h437
-rw-r--r--package/px5g/src/polarssl/bn_mul.h731
-rw-r--r--package/px5g/src/polarssl/config.h329
-rw-r--r--package/px5g/src/polarssl/havege.h75
-rw-r--r--package/px5g/src/polarssl/rsa.h309
-rw-r--r--package/px5g/src/polarssl/sha1.h150
-rw-r--r--package/px5g/src/polarssl/timing.h81
-rw-r--r--package/px5g/src/polarssl/x509.h549
-rw-r--r--package/px5g/src/px5g.c197
-rw-r--r--package/qos-scripts/Makefile50
-rw-r--r--package/qos-scripts/files/etc/config/qos79
-rwxr-xr-xpackage/qos-scripts/files/etc/hotplug.d/iface/10-qos2
-rwxr-xr-xpackage/qos-scripts/files/etc/init.d/qos16
-rwxr-xr-xpackage/qos-scripts/files/usr/bin/qos-start4
-rwxr-xr-xpackage/qos-scripts/files/usr/bin/qos-stat67
-rwxr-xr-xpackage/qos-scripts/files/usr/bin/qos-stop6
-rwxr-xr-xpackage/qos-scripts/files/usr/lib/qos/generate.sh497
-rw-r--r--package/qos-scripts/files/usr/lib/qos/tcrules.awk95
-rw-r--r--package/rbcfg/Makefile49
-rw-r--r--package/rbcfg/src/Makefile14
-rw-r--r--package/rbcfg/src/cyg_crc.h109
-rw-r--r--package/rbcfg/src/cyg_crc32.c172
-rw-r--r--package/rbcfg/src/main.c791
-rw-r--r--package/rbcfg/src/rbcfg.h75
-rw-r--r--package/redboot-ar231x/Makefile52
-rw-r--r--package/redboot-ar231x/patches/010-fix-compile.patch181
-rw-r--r--package/relayd/Makefile42
-rw-r--r--package/relayd/files/relay.hotplug2
-rw-r--r--package/relayd/files/relay.init97
-rw-r--r--package/resolveip/Makefile44
-rw-r--r--package/resolveip/src/resolveip.c98
-rw-r--r--package/robocfg/Makefile39
-rw-r--r--package/robocfg/src/Makefile11
-rw-r--r--package/robocfg/src/etc53xx.h619
-rw-r--r--package/robocfg/src/robocfg.c581
-rw-r--r--package/rotary-gpio-custom/Makefile53
-rw-r--r--package/rotary-gpio-custom/src/Kconfig9
-rw-r--r--package/rotary-gpio-custom/src/Makefile1
-rw-r--r--package/rotary-gpio-custom/src/rotary-gpio-custom.c188
-rw-r--r--package/rssileds/Makefile47
-rw-r--r--package/rssileds/files/rssileds.init75
-rw-r--r--package/rssileds/src/rssileds.c280
-rw-r--r--package/rtc-rv5c386a/Makefile38
-rw-r--r--package/rtc-rv5c386a/src/Makefile18
-rw-r--r--package/rtc-rv5c386a/src/rtc.c611
-rw-r--r--package/sierra-directip/Makefile41
-rw-r--r--package/sierra-directip/patches/100-sierra_net_endian.patch22
-rw-r--r--package/sierra-directip/patches/110-drop_dhcp_requirement.patch14
-rw-r--r--package/sierra-directip/src/Makefile1
-rw-r--r--package/sierra-directip/src/sierra.c1409
-rw-r--r--package/sierra-directip/src/sierra_net.c1123
-rw-r--r--package/siit/Makefile40
-rw-r--r--package/siit/src/Makefile5
-rw-r--r--package/siit/src/siit.c1478
-rw-r--r--package/siit/src/siit.h61
-rw-r--r--package/soloscli/Makefile45
-rw-r--r--package/soloscli/files/etc/hotplug.d/atm/15-solos-init26
-rw-r--r--package/soloscli/files/etc/uci-default/solos15
-rw-r--r--package/soloscli/files/solos-log-stats19
-rw-r--r--package/soloscli/patches/000-Makefile.patch21
-rw-r--r--package/soloscli/patches/001-newline.patch15
-rw-r--r--package/spi-ks8995/Makefile54
-rw-r--r--package/spi-ks8995/src/Kconfig3
-rw-r--r--package/spi-ks8995/src/Makefile1
-rw-r--r--package/spi-ks8995/src/spi_ks8995.c419
-rw-r--r--package/spidev_test/Makefile42
-rw-r--r--package/swconfig/Makefile49
-rw-r--r--package/swconfig/files/switch.sh14
-rw-r--r--package/swconfig/src/Makefile12
-rw-r--r--package/swconfig/src/cli.c340
-rw-r--r--package/swconfig/src/swlib.c686
-rw-r--r--package/swconfig/src/swlib.h234
-rw-r--r--package/swconfig/src/uci.c248
-rw-r--r--package/switch/Makefile59
-rw-r--r--package/switch/files/switch.sh53
-rw-r--r--package/switch/src/Makefile18
-rw-r--r--package/switch/src/etc53xx.h619
-rw-r--r--package/switch/src/gpio.h25
-rw-r--r--package/switch/src/switch-adm.c595
-rw-r--r--package/switch/src/switch-core.c491
-rw-r--r--package/switch/src/switch-core.h52
-rw-r--r--package/switch/src/switch-robo.c583
-rw-r--r--package/toolchain/Makefile560
-rw-r--r--package/toolchain/eglibc-files/etc/nsswitch.conf13
-rw-r--r--package/trelay/Makefile50
-rw-r--r--package/trelay/files/trelay.config4
-rw-r--r--package/trelay/files/trelay.hotplug5
-rw-r--r--package/trelay/files/trelay.init32
-rw-r--r--package/trelay/src/Makefile1
-rw-r--r--package/trelay/src/trelay.c272
-rw-r--r--package/uboot-ar71xx/Makefile90
-rw-r--r--package/uboot-ar71xx/files/board/zyxel/nbg460n/Makefile46
-rw-r--r--package/uboot-ar71xx/files/board/zyxel/nbg460n/config.mk1
-rw-r--r--package/uboot-ar71xx/files/board/zyxel/nbg460n/lowlevel_init.S39
-rw-r--r--package/uboot-ar71xx/files/board/zyxel/nbg460n/nbg460n.c96
-rw-r--r--package/uboot-ar71xx/files/board/zyxel/nbg460n/u-boot.lds42
-rw-r--r--package/uboot-ar71xx/files/cpu/mips/ar71xx_serial.c177
-rw-r--r--package/uboot-ar71xx/files/drivers/net/ag71xx.c809
-rw-r--r--package/uboot-ar71xx/files/drivers/net/ag71xx.h374
-rw-r--r--package/uboot-ar71xx/files/drivers/net/phy/rtl8366.h188
-rw-r--r--package/uboot-ar71xx/files/drivers/net/phy/rtl8366_mii.c786
-rw-r--r--package/uboot-ar71xx/files/drivers/spi/ar71xx_spi.c191
-rw-r--r--package/uboot-ar71xx/files/include/asm-mips/ar71xx.h515
-rw-r--r--package/uboot-ar71xx/files/include/asm-mips/ar71xx_gpio.h65
-rw-r--r--package/uboot-ar71xx/files/include/configs/nbg460n.h136
-rw-r--r--package/uboot-ar71xx/patches/001-ar71xx.patch28
-rw-r--r--package/uboot-ar71xx/patches/002-ar71xx-spi.patch11
-rw-r--r--package/uboot-ar71xx/patches/010-enet-ag71xx.patch22
-rw-r--r--package/uboot-ar71xx/patches/011-switch-rtl8366sr.patch28
-rw-r--r--package/uboot-ar71xx/patches/020-freebsd-compat.patch11
-rw-r--r--package/uboot-ar71xx/patches/021-darwin_compat.patch23
-rw-r--r--package/uboot-ar71xx/patches/022-getline_backport.patch21
-rw-r--r--package/uboot-envtools/Makefile70
-rw-r--r--package/uboot-envtools/files/ar71xx31
-rw-r--r--package/uboot-envtools/files/kirkwood25
-rw-r--r--package/uboot-envtools/files/lantiq25
-rw-r--r--package/uboot-envtools/files/ramips27
-rw-r--r--package/uboot-envtools/files/uboot-envtools.sh36
-rw-r--r--package/uboot-envtools/patches/001-crc32_func_signature.patch130
-rw-r--r--package/uboot-envtools/patches/002-makefile.patch44
-rw-r--r--package/uboot-envtools/patches/003-nor-eraselen.patch14
-rw-r--r--package/uboot-envtools/patches/004-allow_mac_change.patch21
-rw-r--r--package/uboot-kirkwood/Makefile110
-rw-r--r--package/uboot-kirkwood/files/board/iomega/iconnect/Makefile43
-rw-r--r--package/uboot-kirkwood/files/board/iomega/iconnect/iconnect.c141
-rw-r--r--package/uboot-kirkwood/files/board/iomega/iconnect/iconnect.h39
-rw-r--r--package/uboot-kirkwood/files/board/iomega/iconnect/kwbimage.cfg165
-rw-r--r--package/uboot-kirkwood/files/include/configs/iconnect.h124
-rw-r--r--package/uboot-kirkwood/patches/0001-ib62x0.patch542
-rw-r--r--package/uboot-kirkwood/patches/0002-kwboot.patch873
-rw-r--r--package/uboot-kirkwood/patches/0003-ide_bus.patch17
-rw-r--r--package/uboot-kirkwood/patches/100-iconnect.patch10
-rw-r--r--package/uboot-kirkwood/patches/110-dockstar.patch35
-rw-r--r--package/uboot-lantiq/Makefile190
-rw-r--r--package/uboot-lantiq/arcadyan_psc166_32.conf71
-rw-r--r--package/uboot-lantiq/arcadyan_psc166_64.conf141
-rw-r--r--package/uboot-lantiq/easy50712_DDR166M.conf134
-rw-r--r--package/uboot-lantiq/easy50812.conf55
-rw-r--r--package/uboot-lantiq/files/board/arcadyan/Makefile62
-rw-r--r--package/uboot-lantiq/files/board/arcadyan/arcadyan_bootstrap.c48
-rw-r--r--package/uboot-lantiq/files/board/arcadyan/athrs26_phy.c812
-rw-r--r--package/uboot-lantiq/files/board/arcadyan/athrs26_phy.h134
-rw-r--r--package/uboot-lantiq/files/board/arcadyan/board.c517
-rw-r--r--package/uboot-lantiq/files/board/arcadyan/config.mk36
-rw-r--r--package/uboot-lantiq/files/board/arcadyan/ddr_settings.h50
-rw-r--r--package/uboot-lantiq/files/board/arcadyan/ddr_settings_psc_32.h51
-rw-r--r--package/uboot-lantiq/files/board/arcadyan/ddr_settings_psc_64.h47
-rw-r--r--package/uboot-lantiq/files/board/arcadyan/lowlevel_bootstrap_init.S583
-rw-r--r--package/uboot-lantiq/files/board/arcadyan/lowlevel_init.S279
-rw-r--r--package/uboot-lantiq/files/board/arcadyan/pmuenable.S48
-rw-r--r--package/uboot-lantiq/files/board/arcadyan/u-boot-bootstrap.lds74
-rw-r--r--package/uboot-lantiq/files/board/arcadyan/u-boot.lds70
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50712/Makefile62
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50712/config.mk40
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50712/danube.c436
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings.h50
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_PROMOSDDR400.h50
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_Samsung_166.h51
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_e111.h50
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_e166.h50
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_psc_166.h51
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_r111.h50
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_r166.h50
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50712/easy50712_bootstrap.c48
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50712/lowlevel_bootstrap_init.S606
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50712/lowlevel_init.S613
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50712/pmuenable.S48
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50712/u-boot-bootstrap.lds74
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50712/u-boot.lds70
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50812/Makefile62
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50812/ar9.c619
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr111_settings.h51
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr166_settings.h51
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr196_settings.h51
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr221_settings.h51
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr250_settings.h51
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50812/config.mk40
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50812/easy50812_bootstrap.c48
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50812/lowlevel_bootstrap_init.S597
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50812/lowlevel_init.S543
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50812/pmuenable.S48
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50812/u-boot-bootstrap.lds74
-rw-r--r--package/uboot-lantiq/files/board/infineon/easy50812/u-boot.lds70
-rw-r--r--package/uboot-lantiq/files/cpu/mips/ar9-clock.c67
-rw-r--r--package/uboot-lantiq/files/cpu/mips/ar9/Makefile46
-rw-r--r--package/uboot-lantiq/files/cpu/mips/ar9/clock.c67
-rw-r--r--package/uboot-lantiq/files/cpu/mips/ar9/ifx_cache.S60
-rw-r--r--package/uboot-lantiq/files/cpu/mips/danube-clock.c65
-rw-r--r--package/uboot-lantiq/files/cpu/mips/danube/Makefile46
-rw-r--r--package/uboot-lantiq/files/cpu/mips/danube/clock.c65
-rw-r--r--package/uboot-lantiq/files/cpu/mips/danube/ifx_cache.S60
-rw-r--r--package/uboot-lantiq/files/cpu/mips/ifx_asc.c218
-rw-r--r--package/uboot-lantiq/files/cpu/mips/ifx_asc.h199
-rw-r--r--package/uboot-lantiq/files/drivers/net/ifx_etop.c401
-rw-r--r--package/uboot-lantiq/files/drivers/net/ifx_etop.h91
-rw-r--r--package/uboot-lantiq/files/drivers/serial/ifx_asc.c218
-rw-r--r--package/uboot-lantiq/files/drivers/serial/ifx_asc.h199
-rw-r--r--package/uboot-lantiq/files/include/asm-mips/ar9.h424
-rw-r--r--package/uboot-lantiq/files/include/asm-mips/danube.h2015
-rw-r--r--package/uboot-lantiq/files/include/configs/arcadyan-common.h146
-rw-r--r--package/uboot-lantiq/files/include/configs/arv3527P.h17
-rw-r--r--package/uboot-lantiq/files/include/configs/arv4518PW.h16
-rw-r--r--package/uboot-lantiq/files/include/configs/arv4519PW.h21
-rw-r--r--package/uboot-lantiq/files/include/configs/arv4520PW.h20
-rw-r--r--package/uboot-lantiq/files/include/configs/arv4525PW.h18
-rw-r--r--package/uboot-lantiq/files/include/configs/arv452CPW.h20
-rw-r--r--package/uboot-lantiq/files/include/configs/arv7518PW.h16
-rw-r--r--package/uboot-lantiq/files/include/configs/arv7525PW.h18
-rw-r--r--package/uboot-lantiq/files/include/configs/arv752DPW.h19
-rw-r--r--package/uboot-lantiq/files/include/configs/arv752DPW22.h21
-rw-r--r--package/uboot-lantiq/files/include/configs/easy50712.h117
-rw-r--r--package/uboot-lantiq/files/include/configs/easy50812.h104
-rw-r--r--package/uboot-lantiq/files/include/configs/ifx-common.h192
-rwxr-xr-xpackage/uboot-lantiq/gct165
-rw-r--r--package/uboot-lantiq/patches/000-build-infos.patch60
-rw-r--r--package/uboot-lantiq/patches/010-fix-mips-flags.patch25
-rw-r--r--package/uboot-lantiq/patches/020-mips-enhancements.patch124
-rw-r--r--package/uboot-lantiq/patches/030-cfi-addr-fixup.patch225
-rw-r--r--package/uboot-lantiq/patches/040-compile.patch20
-rw-r--r--package/uboot-lantiq/patches/050-portability.patch31
-rw-r--r--package/uboot-lantiq/patches/100-ifx_targets.patch135
-rw-r--r--package/uboot-lantiq/patches/200-httpd.patch6164
-rw-r--r--package/uboot-lantiq/patches/300-arcadyan.patch98
-rw-r--r--package/uboot-lantiq/patches/400-lzma.patch1687
-rw-r--r--package/uboot-lantiq/patches/500-gigasx.patch35
-rw-r--r--package/uboot-omap35xx/Makefile89
-rw-r--r--package/uboot-omap35xx/files/include/configs/omap3_overo.h316
-rw-r--r--package/uboot-omap4/Makefile90
-rw-r--r--package/uboot-pxa/Makefile88
-rw-r--r--package/uboot-pxa/patches/001-squashfs_rootfstype_cmdline.patch13
-rw-r--r--package/uboot-xburst/Makefile102
-rw-r--r--package/uboot-xburst/files/board/n516/Makefile40
-rw-r--r--package/uboot-xburst/files/board/n516/config.mk33
-rw-r--r--package/uboot-xburst/files/board/n516/flash.c50
-rw-r--r--package/uboot-xburst/files/board/n516/n516.c126
-rw-r--r--package/uboot-xburst/files/board/n516/u-boot-nand.lds63
-rw-r--r--package/uboot-xburst/files/board/n516/u-boot.lds63
-rw-r--r--package/uboot-xburst/files/board/nanonote/Makefile38
-rw-r--r--package/uboot-xburst/files/board/nanonote/config.mk31
-rw-r--r--package/uboot-xburst/files/board/nanonote/nanonote.c123
-rw-r--r--package/uboot-xburst/files/board/nanonote/u-boot-nand.lds63
-rw-r--r--package/uboot-xburst/files/board/nanonote/u-boot.lds63
-rw-r--r--package/uboot-xburst/files/board/sakc/Makefile38
-rw-r--r--package/uboot-xburst/files/board/sakc/config.mk31
-rw-r--r--package/uboot-xburst/files/board/sakc/sakc.c94
-rw-r--r--package/uboot-xburst/files/board/sakc/u-boot-nand.lds63
-rw-r--r--package/uboot-xburst/files/board/sakc/u-boot.lds63
-rw-r--r--package/uboot-xburst/files/cpu/mips/jz4740.c559
-rw-r--r--package/uboot-xburst/files/cpu/mips/jz4740_nand.c199
-rw-r--r--package/uboot-xburst/files/cpu/mips/jz_lcd.c484
-rw-r--r--package/uboot-xburst/files/cpu/mips/jz_lcd.h260
-rw-r--r--package/uboot-xburst/files/cpu/mips/jz_mmc.c1416
-rw-r--r--package/uboot-xburst/files/cpu/mips/jz_mmc.h113
-rw-r--r--package/uboot-xburst/files/cpu/mips/jz_serial.c141
-rw-r--r--package/uboot-xburst/files/cpu/mips/mmc_protocol.h273
-rw-r--r--package/uboot-xburst/files/cpu/mips/nanonote_gpm940b0.c420
-rw-r--r--package/uboot-xburst/files/cpu/mips/nanonote_gpm940b0.h234
-rw-r--r--package/uboot-xburst/files/cpu/mips/usb_boot.S880
-rw-r--r--package/uboot-xburst/files/include/asm-mips/jz4740.h4892
-rw-r--r--package/uboot-xburst/files/include/configs/avt2.h26
-rw-r--r--package/uboot-xburst/files/include/configs/n516.h311
-rw-r--r--package/uboot-xburst/files/include/configs/nanonote.h191
-rw-r--r--package/uboot-xburst/files/include/configs/qi_lb60.h27
-rw-r--r--package/uboot-xburst/files/include/configs/sakc.h200
-rw-r--r--package/uboot-xburst/files/nand_spl/board/n516/Makefile104
-rw-r--r--package/uboot-xburst/files/nand_spl/board/n516/config.mk34
-rw-r--r--package/uboot-xburst/files/nand_spl/board/n516/u-boot.lds63
-rw-r--r--package/uboot-xburst/files/nand_spl/board/nanonote/Makefile104
-rw-r--r--package/uboot-xburst/files/nand_spl/board/nanonote/config.mk34
-rw-r--r--package/uboot-xburst/files/nand_spl/board/nanonote/u-boot.lds63
-rw-r--r--package/uboot-xburst/files/nand_spl/board/sakc/Makefile104
-rw-r--r--package/uboot-xburst/files/nand_spl/board/sakc/config.mk34
-rw-r--r--package/uboot-xburst/files/nand_spl/board/sakc/u-boot.lds63
-rw-r--r--package/uboot-xburst/files/nand_spl/nand_boot_jz4740.c429
-rw-r--r--package/uboot-xburst/patches/001-xburst.patch1669
-rw-r--r--package/uboot-xburst/patches/005-i2c.patch13
-rw-r--r--package/uboot-xburst/patches/009-n516.patch23
-rw-r--r--package/uboot-xburst/patches/010-sakc.patch32
-rw-r--r--package/ubus/Makefile80
-rwxr-xr-xpackage/ubus/files/ubus.init14
-rw-r--r--package/uci/Makefile88
-rw-r--r--package/uci/files/lib/config/uci.sh137
-rw-r--r--package/uclibc++/Makefile91
-rw-r--r--package/uclibc++/files/config.default58
-rw-r--r--package/uclibc++/patches/002-path_to_bash.patch11
-rw-r--r--package/uclibc++/patches/006-eabi_fix.patch38
-rw-r--r--package/udev/Config.in118
-rw-r--r--package/udev/Makefile156
-rw-r--r--package/udev/patches/0001-build-don-t-use-gc-sections.patch31
-rw-r--r--package/udev/patches/0002-udevd-add-lrt-for-message-queue-symbols.patch25
-rw-r--r--package/udev/patches/0003-add_btn_trigger_happy_define.patch13
-rw-r--r--package/uhttpd/Makefile164
-rw-r--r--package/uhttpd/files/uhttpd.config89
-rwxr-xr-xpackage/uhttpd/files/uhttpd.init135
-rw-r--r--package/uhttpd/src/Makefile89
-rw-r--r--package/uhttpd/src/uhttpd-cgi.c556
-rw-r--r--package/uhttpd/src/uhttpd-cgi.h43
-rw-r--r--package/uhttpd/src/uhttpd-file.c438
-rw-r--r--package/uhttpd/src/uhttpd-file.h36
-rw-r--r--package/uhttpd/src/uhttpd-lua.c579
-rw-r--r--package/uhttpd/src/uhttpd-lua.h44
-rw-r--r--package/uhttpd/src/uhttpd-mimetypes.h86
-rw-r--r--package/uhttpd/src/uhttpd-tls.c170
-rw-r--r--package/uhttpd/src/uhttpd-tls.h36
-rw-r--r--package/uhttpd/src/uhttpd-ubus.c957
-rw-r--r--package/uhttpd/src/uhttpd-ubus.h70
-rw-r--r--package/uhttpd/src/uhttpd-utils.c1081
-rw-r--r--package/uhttpd/src/uhttpd-utils.h140
-rw-r--r--package/uhttpd/src/uhttpd.c1288
-rw-r--r--package/uhttpd/src/uhttpd.h214
-rw-r--r--package/usbreset/Makefile44
-rw-r--r--package/usbreset/src/usbreset.c253
-rw-r--r--package/util-linux/Makefile591
-rw-r--r--package/util-linux/patches/000-compile.patch44
-rw-r--r--package/util-linux/patches/001-no-printf-alloc.patch108
-rw-r--r--package/vsc73x5-ucode/Makefile94
-rw-r--r--package/vsc73x5-ucode/files/Makefile20
-rw-r--r--package/w1-gpio-custom/Makefile54
-rw-r--r--package/w1-gpio-custom/src/Kconfig4
-rw-r--r--package/w1-gpio-custom/src/Makefile1
-rw-r--r--package/w1-gpio-custom/src/w1-gpio-custom.c185
-rw-r--r--package/wireless-tools/Makefile89
-rw-r--r--package/wireless-tools/patches/001-debian.patch35
-rw-r--r--package/wireless-tools/patches/002-fix-iwconfig-power-argument-parsing.patch13
-rw-r--r--package/wireless-tools/patches/003-we_essential_def.patch359
-rw-r--r--package/wireless-tools/patches/004-increase_iwlist_buffer.patch46
-rw-r--r--package/wprobe/Makefile143
-rw-r--r--package/wprobe/files/wprobe.config10
-rwxr-xr-xpackage/wprobe/files/wprobe.init72
-rw-r--r--package/wprobe/src/Makefile.inc12
-rw-r--r--package/wprobe/src/exporter/Makefile5
-rw-r--r--package/wprobe/src/exporter/wprobe-export.c304
-rw-r--r--package/wprobe/src/exporter/wprobe-export.h34
-rw-r--r--package/wprobe/src/filter/README.txt1
-rwxr-xr-xpackage/wprobe/src/filter/gen_filter.pl63
-rw-r--r--package/wprobe/src/filter/pfc.c58
-rw-r--r--package/wprobe/src/kernel/Makefile5
-rw-r--r--package/wprobe/src/kernel/linux/wprobe.h397
-rw-r--r--package/wprobe/src/kernel/wprobe-core.c1164
-rw-r--r--package/wprobe/src/kernel/wprobe-dummy.c96
-rw-r--r--package/wprobe/src/user/Makefile38
-rw-r--r--package/wprobe/src/user/list.h601
-rw-r--r--package/wprobe/src/user/wprobe-lib.c1210
-rw-r--r--package/wprobe/src/user/wprobe-util.c450
-rw-r--r--package/wprobe/src/user/wprobe.h213
-rw-r--r--package/wrt55agv2-spidevs/Makefile53
-rw-r--r--package/wrt55agv2-spidevs/src/Kconfig3
-rw-r--r--package/wrt55agv2-spidevs/src/Makefile1
-rw-r--r--package/wrt55agv2-spidevs/src/wrt55agv2_spidevs.c114
-rw-r--r--package/xfsprogs/Makefile87
-rw-r--r--package/xfsprogs/patches/001-automake-compat.patch84
-rw-r--r--package/xfsprogs/patches/100-no_aio.patch21
-rw-r--r--package/xfsprogs/patches/110-uclibc_no_ustat.patch36
-rw-r--r--package/xfsprogs/patches/120-portability.patch47
-rw-r--r--package/xfsprogs/patches/130-uclibc_no_xattr.patch36
-rw-r--r--package/xfsprogs/patches/140-no_po.patch20
-rw-r--r--package/yamonenv/Makefile38
-rw-r--r--package/yamonenv/patches/001-yamonenv_mtd_partition.patch11
-rw-r--r--package/zlib/Makefile69
1552 files changed, 278904 insertions, 0 deletions
diff --git a/package/6in4/Makefile b/package/6in4/Makefile
new file mode 100644
index 000000000..fdab29086
--- /dev/null
+++ b/package/6in4/Makefile
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2010-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=6in4
+PKG_VERSION:=11
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/6in4
+ SECTION:=ipv6
+ CATEGORY:=IPv6
+ DEPENDS:=+kmod-ipv6 +kmod-sit
+ TITLE:=IPv6-in-IPv4 configuration support
+ MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org>
+ PKGARCH:=all
+endef
+
+define Package/6in4/description
+Provides support for 6in4 tunnels in /etc/config/network.
+Refer to http://wiki.openwrt.org/doc/uci/network for
+configuration details.
+endef
+
+define Build/Compile
+endef
+
+define Build/Configure
+endef
+
+define Package/6in4/install
+ $(INSTALL_DIR) $(1)/lib/netifd/proto
+ $(INSTALL_BIN) ./files/6in4.sh $(1)/lib/netifd/proto/6in4.sh
+endef
+
+$(eval $(call BuildPackage,6in4))
diff --git a/package/6in4/files/6in4.sh b/package/6in4/files/6in4.sh
new file mode 100755
index 000000000..71bc68940
--- /dev/null
+++ b/package/6in4/files/6in4.sh
@@ -0,0 +1,90 @@
+#!/bin/sh
+# 6in4.sh - IPv6-in-IPv4 tunnel backend
+# Copyright (c) 2010-2012 OpenWrt.org
+
+[ -n "$INCLUDE_ONLY" ] || {
+ . /lib/functions.sh
+ . /lib/functions/network.sh
+ . ../netifd-proto.sh
+ init_proto "$@"
+}
+
+proto_6in4_setup() {
+ local cfg="$1"
+ local iface="$2"
+ local link="6in4-$cfg"
+
+ local mtu ttl ipaddr peeraddr ip6addr tunnelid username password
+ json_get_vars mtu ttl ipaddr peeraddr ip6addr tunnelid username password
+
+ [ -z "$ip6addr" -o -z "$peeraddr" ] && {
+ proto_notify_error "$cfg" "MISSING_ADDRESS"
+ proto_block_restart "$cfg"
+ return
+ }
+
+ ( proto_add_host_dependency "$cfg" 0.0.0.0 )
+
+ [ -z "$ipaddr" ] && {
+ local wanif
+ if ! network_find_wan wanif || ! network_get_ipaddr ipaddr "$wanif"; then
+ proto_notify_error "$cfg" "NO_WAN_LINK"
+ return
+ fi
+ }
+
+ local local6="${ip6addr%%/*}"
+ local mask6="${ip6addr##*/}"
+ [[ "$local6" = "$mask6" ]] && mask6=
+
+ proto_init_update "$link" 1
+ proto_add_ipv6_address "$local6" "$mask6"
+ proto_add_ipv6_route "::" 0
+
+ proto_add_tunnel
+ json_add_string mode sit
+ json_add_int mtu "${mtu:-1280}"
+ json_add_int ttl "${ttl:-64}"
+ json_add_string local "$ipaddr"
+ json_add_string remote "$peeraddr"
+ proto_close_tunnel
+
+ proto_send_update "$cfg"
+
+ [ -n "$tunnelid" -a -n "$username" -a -n "$password" ] && {
+ [ "${#password}" == 32 -a -z "${password//[a-fA-F0-9]/}" ] || {
+ password="$(echo -n "$password" | md5sum)"; password="${password%% *}"
+ }
+
+ local url="http://ipv4.tunnelbroker.net/ipv4_end.php?ip=AUTO&apikey=$username&pass=$password&tid=$tunnelid"
+ local try=0
+ local max=3
+
+ while [ $((++try)) -le $max ]; do
+ wget -qO/dev/null "$url" 2>/dev/null && break
+ sleep 1
+ done
+ }
+}
+
+proto_6in4_teardown() {
+ local cfg="$1"
+}
+
+proto_6in4_init_config() {
+ no_device=1
+ available=1
+
+ proto_config_add_string "ipaddr"
+ proto_config_add_string "ip6addr"
+ proto_config_add_string "peeraddr"
+ proto_config_add_string "tunnelid"
+ proto_config_add_string "username"
+ proto_config_add_string "password"
+ proto_config_add_int "mtu"
+ proto_config_add_int "ttl"
+}
+
+[ -n "$INCLUDE_ONLY" ] || {
+ add_protocol 6in4
+}
diff --git a/package/6rd/Makefile b/package/6rd/Makefile
new file mode 100644
index 000000000..3d4549674
--- /dev/null
+++ b/package/6rd/Makefile
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2010-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=6rd
+PKG_VERSION:=2
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/6rd
+ SECTION:=ipv6
+ CATEGORY:=IPv6
+ DEPENDS:=+kmod-ipv6 +kmod-sit
+ TITLE:=6rd configuration support
+ MAINTAINER:=Stéphan Kochen <stephan@kochen.nl>
+ PKGARCH:=all
+endef
+
+define Package/6rd/description
+Provides support for 6rd tunnels in /etc/config/network.
+Refer to http://wiki.openwrt.org/doc/uci/network for
+configuration details.
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CC)" \
+ CFLAGS="$(TARGET_CFLAGS) -Wall" \
+ LDFLAGS="$(TARGET_LDFLAGS)"
+endef
+
+define Package/6rd/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/6rdcalc $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/lib/netifd/proto
+ $(INSTALL_BIN) ./files/6rd.sh $(1)/lib/netifd/proto/6rd.sh
+endef
+
+$(eval $(call BuildPackage,6rd))
diff --git a/package/6rd/files/6rd.sh b/package/6rd/files/6rd.sh
new file mode 100644
index 000000000..59c3169b3
--- /dev/null
+++ b/package/6rd/files/6rd.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+# 6rd.sh - IPv6-in-IPv4 tunnel backend
+# Copyright (c) 2010-2012 OpenWrt.org
+
+[ -n "$INCLUDE_ONLY" ] || {
+ . /lib/functions.sh
+ . /lib/functions/network.sh
+ . ../netifd-proto.sh
+ init_proto "$@"
+}
+
+proto_6rd_setup() {
+ local cfg="$1"
+ local iface="$2"
+ local link="6rd-$cfg"
+
+ local mtu ttl ipaddr peeraddr ip6prefix ip6prefixlen ip4prefixlen
+ json_get_vars mtu ttl ipaddr peeraddr ip6prefix ip6prefixlen ip4prefixlen
+
+ [ -z "$ip6prefix" -o -z "$peeraddr" ] && {
+ proto_notify_error "$cfg" "MISSING_ADDRESS"
+ proto_block_restart "$cfg"
+ return
+ }
+
+ ( proto_add_host_dependency "$cfg" 0.0.0.0 )
+
+ [ -z "$ipaddr" ] && {
+ local wanif
+ if ! network_find_wan wanif || ! network_get_ipaddr ipaddr "$wanif"; then
+ proto_notify_error "$cfg" "NO_WAN_LINK"
+ return
+ fi
+ }
+
+ # Determine the relay prefix.
+ local ip4prefixlen="${ip4prefixlen:-0}"
+ local ip4prefix=$(ipcalc.sh "$ipaddr/$ip4prefixlen" | grep NETWORK)
+ ip4prefix="${ip4prefix#NETWORK=}"
+
+ # Determine our IPv6 address.
+ local ip6subnet=$(6rdcalc "$ip6prefix/$ip6prefixlen" "$ipaddr/$ip4prefixlen")
+ local ip6addr="${ip6subnet%%::*}::1"
+
+ proto_init_update "$link" 1
+ proto_add_ipv6_address "$ip6addr" "$ip6prefixlen"
+ proto_add_ipv6_route "::" 0 "::$peeraddr"
+
+ proto_add_tunnel
+ json_add_string mode sit
+ json_add_int mtu "${mtu:-1280}"
+ json_add_int ttl "${ttl:-64}"
+ json_add_string local "$ipaddr"
+ json_add_string 6rd-prefix "$ip6prefix/$ip6prefixlen"
+ json_add_string 6rd-relay-prefix "$ip4prefix/$ip4prefixlen"
+ proto_close_tunnel
+
+ proto_send_update "$cfg"
+}
+
+proto_6rd_teardown() {
+ local cfg="$1"
+}
+
+proto_6rd_init_config() {
+ no_device=1
+ available=1
+
+ proto_config_add_int "mtu"
+ proto_config_add_int "ttl"
+ proto_config_add_string "ipaddr"
+ proto_config_add_string "peeraddr"
+ proto_config_add_string "ip6prefix"
+ proto_config_add_string "ip6prefixlen"
+ proto_config_add_string "ip4prefixlen"
+}
+
+[ -n "$INCLUDE_ONLY" ] || {
+ add_protocol 6rd
+}
diff --git a/package/6rd/src/6rdcalc.c b/package/6rd/src/6rdcalc.c
new file mode 100644
index 000000000..56e07d255
--- /dev/null
+++ b/package/6rd/src/6rdcalc.c
@@ -0,0 +1,126 @@
+/*
+ * Utility used to calculate the 6rd subnet.
+ *
+ * Copyright 2012, Stéphan Kochen <stephan@kochen.nl>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/errno.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#define INET_PREFIXSTRLEN (INET_ADDRSTRLEN+3)
+#define INET6_PREFIXSTRLEN (INET6_ADDRSTRLEN+4)
+
+static void print_usage()
+{
+ fprintf(stderr, "Usage: 6rdcalc <v6 prefix>/<mask> <v4 address>/<mask>\n");
+ exit(1);
+}
+
+static void print_error()
+{
+ fprintf(stderr, "%s", strerror(errno));
+ exit(1);
+}
+
+static void parse_str(int af, char *str, void *addr, unsigned long *mask)
+{
+ int ret;
+ char *slash;
+
+ /* Split the address at the slash. */
+ if ((slash = strchr(str, '/')) == NULL)
+ print_usage();
+ *slash = '\0';
+
+ /* Parse the address. */
+ if ((ret = inet_pton(af, str, addr)) != 1) {
+ if (ret == 0)
+ print_usage();
+ else
+ print_error();
+ }
+
+ /* Parse the mask. */
+ *mask = strtoul(slash+1, NULL, 10);
+ if ((af == AF_INET && *mask > 32) ||
+ (af == AF_INET6 && *mask > 128))
+ print_usage();
+}
+
+int main(int argc, const char **argv)
+{
+ char v6str[INET6_PREFIXSTRLEN], v4str[INET_PREFIXSTRLEN];
+ struct in6_addr v6;
+ struct in_addr v4;
+ unsigned long v6it, v4it, mask;
+ unsigned char *byte4, *byte6;
+ unsigned char bit4, bit6;
+
+ /* Check parameters. */
+ if (argc != 3)
+ print_usage();
+
+ /* Parse the v6 address. */
+ strncpy(v6str, argv[1], INET6_PREFIXSTRLEN);
+ v6str[INET6_PREFIXSTRLEN-1] = '\0';
+ parse_str(AF_INET6, v6str, &v6, &v6it);
+
+ /* Parse the v4 address */
+ strncpy(v4str, argv[2], INET_PREFIXSTRLEN);
+ v6str[INET_PREFIXSTRLEN-1] = '\0';
+ parse_str(AF_INET, v4str, &v4, &v4it);
+
+ /* Check if the combined mask is within bounds. */
+ mask = (32 - v4it) + v6it;
+ if (mask > 128)
+ print_usage();
+
+ /* Combine the addresses. */
+ while (v4it < 32) {
+ byte6 = (unsigned char *)(&v6.s6_addr) + (v6it >> 3);
+ byte4 = (unsigned char *)(&v4.s_addr) + (v4it >> 3);
+ bit6 = 128 >> (v6it & 0x07);
+ bit4 = 128 >> (v4it & 0x07);
+
+ if (*byte4 & bit4)
+ *byte6 |= bit6;
+ else
+ *byte6 &= ~bit6;
+
+ v4it++; v6it++;
+ }
+
+ /* Clear remaining bits. */
+ while (v6it < 128) {
+ byte6 = (unsigned char *)(&v6.s6_addr) + (v6it >> 2);
+ bit6 = 128 >> (v6it & 0x07);
+
+ *byte6 &= ~bit6;
+
+ v6it++;
+ }
+
+ /* Print the subnet prefix. */
+ if (inet_ntop(AF_INET6, &v6, v6str, sizeof(v6str)) == NULL)
+ print_error();
+ printf("%s/%lu\n", v6str, mask);
+ return 0;
+}
diff --git a/package/6rd/src/Makefile b/package/6rd/src/Makefile
new file mode 100644
index 000000000..2881d4358
--- /dev/null
+++ b/package/6rd/src/Makefile
@@ -0,0 +1,7 @@
+all: 6rdcalc
+
+6rdcalc: 6rdcalc.c
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
+
+clean:
+ rm -f 6rdcalc
diff --git a/package/6to4/Makefile b/package/6to4/Makefile
new file mode 100644
index 000000000..f29571d86
--- /dev/null
+++ b/package/6to4/Makefile
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2010-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=6to4
+PKG_VERSION:=11
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/6to4
+ SECTION:=ipv6
+ CATEGORY:=IPv6
+ DEPENDS:=+kmod-ipv6 +kmod-sit
+ TITLE:=IPv6-to-IPv4 configuration support
+ MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org>
+ PKGARCH:=all
+endef
+
+define Package/6to4/description
+Provides support for 6to4 tunnels in /etc/config/network.
+Refer to http://wiki.openwrt.org/doc/uci/network for
+configuration details.
+endef
+
+define Build/Compile
+endef
+
+define Build/Configure
+endef
+
+define Package/6to4/install
+ $(INSTALL_DIR) $(1)/lib/netifd/proto
+ $(INSTALL_BIN) ./files/6to4.sh $(1)/lib/netifd/proto/6to4.sh
+endef
+
+$(eval $(call BuildPackage,6to4))
diff --git a/package/6to4/files/6to4.sh b/package/6to4/files/6to4.sh
new file mode 100755
index 000000000..3a616f675
--- /dev/null
+++ b/package/6to4/files/6to4.sh
@@ -0,0 +1,209 @@
+#!/bin/sh
+# 6to4.sh - IPv6-in-IPv4 tunnel backend
+# Copyright (c) 2010-2012 OpenWrt.org
+
+[ -n "$INCLUDE_ONLY" ] || {
+ . /lib/functions.sh
+ . /lib/functions/network.sh
+ . ../netifd-proto.sh
+ init_proto "$@"
+}
+
+find_6to4_prefix() {
+ local ip4="$1"
+ local oIFS="$IFS"; IFS="."; set -- $ip4; IFS="$oIFS"
+
+ printf "2002:%02x%02x:%02x%02x\n" $1 $2 $3 $4
+}
+
+test_6to4_rfc1918()
+{
+ local oIFS="$IFS"; IFS="."; set -- $1; IFS="$oIFS"
+ [ $1 -eq 10 ] && return 0
+ [ $1 -eq 192 ] && [ $2 -eq 168 ] && return 0
+ [ $1 -eq 172 ] && [ $2 -ge 16 ] && [ $2 -le 31 ] && return 0
+
+ # RFC 6598
+ [ $1 -eq 100 ] && [ $2 -ge 64 ] && [ $2 -le 127 ] && return 0
+
+ return 1
+}
+
+set_6to4_radvd_interface() {
+ local cfgid="$1"
+ local lanif="${2:-lan}"
+ local ifmtu="${3:-1280}"
+ local ifsection=""
+
+ find_ifsection() {
+ local net
+ local cfg="$1"
+ config_get net "$cfg" interface
+
+ [ "$net" = "$lanif" ] && {
+ ifsection="$cfg"
+ return 1
+ }
+ }
+
+ config_foreach find_ifsection interface
+
+ [ -z "$ifsection" ] && {
+ ifsection="iface_$sid"
+ uci_set_state radvd "$ifsection" "" interface
+ uci_set_state radvd "$ifsection" interface "$lanif"
+ }
+
+ uci_set_state radvd "$ifsection" ignore 0
+ uci_set_state radvd "$ifsection" IgnoreIfMissing 1
+ uci_set_state radvd "$ifsection" AdvSendAdvert 1
+ uci_set_state radvd "$ifsection" MaxRtrAdvInterval 30
+ uci_set_state radvd "$ifsection" AdvLinkMTU "$ifmtu"
+}
+
+set_6to4_radvd_prefix() {
+ local cfgid="$1"
+ local lanif="${2:-lan}"
+ local wanif="${3:-wan}"
+ local prefix="${4:-0:0:0:1::/64}"
+ local vlt="${5:-300}"
+ local plt="${6:-120}"
+ local pfxsection=""
+
+ find_pfxsection() {
+ local net base
+ local cfg="$1"
+ config_get net "$cfg" interface
+ config_get base "$cfg" Base6to4Interface
+
+ [ "$net" = "$lanif" ] && [ "$base" = "$wanif" ] && {
+ pfxsection="$cfg"
+ return 1
+ }
+ }
+
+ config_foreach find_pfxsection prefix
+
+ [ -z "$pfxsection" ] && {
+ pfxsection="prefix_${sid}_${lanif}"
+ uci_set_state radvd "$pfxsection" "" prefix
+ uci_set_state radvd "$pfxsection" ignore 0
+ uci_set_state radvd "$pfxsection" interface "$lanif"
+ uci_set_state radvd "$pfxsection" prefix "$prefix"
+ uci_set_state radvd "$pfxsection" AdvOnLink 1
+ uci_set_state radvd "$pfxsection" AdvAutonomous 1
+ uci_set_state radvd "$pfxsection" AdvValidLifetime "$vlt"
+ uci_set_state radvd "$pfxsection" AdvPreferredLifetime "$plt"
+ uci_set_state radvd "$pfxsection" Base6to4Interface "$wanif"
+ }
+}
+
+proto_6to4_setup() {
+ local cfg="$1"
+ local iface="$2"
+ local link="6to4-$cfg"
+
+ local mtu ttl ipaddr adv_subnet adv_interface adv_valid_lifetime adv_preferred_lifetime
+ json_get_vars mtu ttl ipaddr adv_subnet adv_interface adv_valid_lifetime adv_preferred_lifetime
+
+ ( proto_add_host_dependency "$cfg" 0.0.0.0 )
+
+ local wanif
+ if ! network_find_wan wanif; then
+ proto_notify_error "$cfg" "NO_WAN_LINK"
+ return
+ fi
+
+ [ -z "$ipaddr" ] && {
+ if ! network_get_ipaddr ipaddr "$wanif"; then
+ proto_notify_error "$cfg" "NO_WAN_ADDRESS"
+ return
+ fi
+ }
+
+ test_6to4_rfc1918 "$ipaddr" && {
+ proto_notify_error "$cfg" "INVALID_LOCAL_ADDRESS"
+ return
+ }
+
+ # find our local prefix
+ local prefix6=$(find_6to4_prefix "$ipaddr")
+ local local6="$prefix6::1"
+
+ proto_init_update "$link" 1
+ proto_add_ipv6_address "$local6" 16
+ proto_add_ipv6_route "::" 0 "::192.88.99.1"
+
+ proto_add_tunnel
+ json_add_string mode sit
+ json_add_int mtu "${mtu:-1280}"
+ json_add_int ttl "${ttl:-64}"
+ json_add_string local "$ipaddr"
+ proto_close_tunnel
+
+ proto_send_update "$cfg"
+
+ [ -f /etc/config/radvd ] && /etc/init.d/radvd enabled && {
+ local sid="6to4_$cfg"
+
+ uci_revert_state radvd
+ config_load radvd
+
+ adv_subnet=$((0x${adv_subnet:-1}))
+
+ local adv_subnets=""
+
+ for adv_interface in ${adv_interface:-lan}; do
+ local adv_ifname
+ network_get_device adv_ifname "${adv_interface:-lan}" || continue
+
+ local subnet6="$(printf "%s:%x::1/64" "$prefix6" $adv_subnet)"
+
+ logger -t "$link" " * Advertising IPv6 subnet $subnet6 on ${adv_interface:-lan} ($adv_ifname)"
+ ip -6 addr add $subnet6 dev $adv_ifname
+
+ set_6to4_radvd_interface "$sid" "$adv_interface" "$mtu"
+ set_6to4_radvd_prefix "$sid" "$adv_interface" \
+ "$wanif" "$(printf "0:0:0:%x::/64" $adv_subnet)" \
+ "$adv_valid_lifetime" "$adv_preferred_lifetime"
+
+ adv_subnets="${adv_subnets:+$adv_subnets }$adv_ifname:$subnet6"
+ adv_subnet=$(($adv_subnet + 1))
+ done
+
+ uci_set_state network "$cfg" adv_subnets "$adv_subnets"
+
+ /etc/init.d/radvd restart
+ }
+}
+
+proto_6to4_teardown() {
+ local cfg="$1"
+ local link="6to4-$cfg"
+
+ local adv_subnets=$(uci_get_state network "$cfg" adv_subnets)
+
+ grep -qs "^ *$link:" /proc/net/dev && {
+ [ -n "$adv_subnets" ] && {
+ uci_revert_state radvd
+ /etc/init.d/radvd enabled && /etc/init.d/radvd restart
+ }
+ }
+}
+
+proto_6to4_init_config() {
+ no_device=1
+ available=1
+
+ proto_config_add_string "ipaddr"
+ proto_config_add_int "mtu"
+ proto_config_add_int "ttl"
+ proto_config_add_string "adv_interface"
+ proto_config_add_string "adv_subnet"
+ proto_config_add_int "adv_valid_lifetime"
+ proto_config_add_int "adv_preferred_lifetime"
+}
+
+[ -n "$INCLUDE_ONLY" ] || {
+ add_protocol 6to4
+}
diff --git a/package/Makefile b/package/Makefile
new file mode 100644
index 000000000..5d942ca78
--- /dev/null
+++ b/package/Makefile
@@ -0,0 +1,105 @@
+#
+# Copyright (C) 2006-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+curdir:=package
+
+-include $(TMP_DIR)/.packagedeps
+$(curdir)/builddirs:=$(sort $(package-) $(package-y) $(package-m))
+ifeq ($(SDK),1)
+ $(curdir)/builddirs-install:=.
+else
+ $(curdir)/builddirs-default:=. $(sort $(package-y) $(package-m))
+ $(curdir)/builddirs-prereq:=. $(sort $(prereq-y) $(prereq-m))
+ $(curdir)/builddirs-install:=. $(filter-out base-files,$(sort $(package-y))) $(filter base-files,$(package-y))
+endif
+ifneq ($(IGNORE_ERRORS),)
+ $(curdir)/builddirs-ignore-compile:= $(if $(filter n m y, $(IGNORE_ERRORS)),$(foreach m,$(IGNORE_ERRORS),$(package-$(subst n,,$(m)))),$(package-m) $(package-))
+endif
+
+$(curdir)/install:=$(curdir)/install-cleanup
+
+$(curdir)/cleanup: $(TMP_DIR)/.build
+ - find $(STAGING_DIR_ROOT) -type d | $(XARGS) chmod 0755
+ rm -rf $(TARGET_DIR) $(STAGING_DIR_ROOT)
+
+ifdef CONFIG_USE_MKLIBS
+ define mklibs
+ rm -rf $(TMP_DIR)/mklibs-progs $(TMP_DIR)/mklibs-out
+ # first find all programs and add them to the mklibs list
+ find $(STAGING_DIR_ROOT) -type f -perm +100 -exec \
+ file -r -N -F '' {} + | \
+ awk ' /executable.*dynamically/ { print $$1 }' > $(TMP_DIR)/mklibs-progs
+ # find all loadable objects that are not regular libraries and add them to the list as well
+ find $(STAGING_DIR_ROOT) -type f -name \*.so\* -exec \
+ file -r -N -F '' {} + | \
+ awk ' /shared object/ { print $$1 }' >> $(TMP_DIR)/mklibs-progs
+ mkdir -p $(TMP_DIR)/mklibs-out
+ $(STAGING_DIR_HOST)/bin/mklibs -D \
+ -d $(TMP_DIR)/mklibs-out \
+ --sysroot $(STAGING_DIR_ROOT) \
+ -L /lib \
+ -L /usr/lib \
+ -L /usr/lib/ebtables \
+ --ldlib $(patsubst $(STAGING_DIR_ROOT)/%,/%,$(firstword $(wildcard \
+ $(foreach name,ld-uClibc.so.* ld-linux.so.* ld-*.so, \
+ $(STAGING_DIR_ROOT)/lib/$(name) \
+ )))) \
+ --target $(REAL_GNU_TARGET_NAME) \
+ `cat $(TMP_DIR)/mklibs-progs` 2>&1
+ $(RSTRIP) $(TMP_DIR)/mklibs-out
+ for lib in `ls $(TMP_DIR)/mklibs-out/*.so.* 2>/dev/null`; do \
+ LIB="$${lib##*/}"; \
+ DEST="`ls "$(TARGET_DIR)/lib/$$LIB" "$(TARGET_DIR)/usr/lib/$$LIB" 2>/dev/null`"; \
+ [ -n "$$DEST" ] || continue; \
+ echo "Copying stripped library $$lib to $$DEST"; \
+ cp "$$lib" "$$DEST" || exit 1; \
+ done
+ endef
+endif
+
+$(curdir)/rootfs-prepare: $(TMP_DIR)/.build
+ @-$(MAKE) package/preconfig
+ @if [ -d $(TOPDIR)/files ]; then \
+ ( cd $(TOPDIR)/files; find -type f ) | \
+ ( cd $(TARGET_DIR); while :; do \
+ read FILE; \
+ [ -z "$$FILE" ] && break; \
+ [ -L "$$FILE" ] || continue; \
+ echo "Removing symlink $(TARGET_DIR)/$$FILE"; \
+ rm -f "$$FILE"; \
+ done; ); \
+ $(CP) $(TOPDIR)/files/. $(TARGET_DIR); \
+ fi
+ @mkdir -p $(TARGET_DIR)/etc/rc.d
+ @( \
+ cd $(TARGET_DIR); \
+ for script in ./etc/init.d/*; do \
+ grep '#!/bin/sh /etc/rc.common' $$script >/dev/null || continue; \
+ IPKG_INSTROOT=$(TARGET_DIR) $$(which bash) ./etc/rc.common $$script enable; \
+ done || true \
+ )
+ @-find $(TARGET_DIR) -name CVS | $(XARGS) rm -rf
+ @-find $(TARGET_DIR) -name .svn | $(XARGS) rm -rf
+ @-find $(TARGET_DIR) -name '.#*' | $(XARGS) rm -f
+ rm -f $(TARGET_DIR)/usr/lib/opkg/info/*.postinst
+ $(if $(CONFIG_CLEAN_IPKG),rm -rf $(TARGET_DIR)/usr/lib/opkg)
+ $(call mklibs)
+
+$(curdir)/index: FORCE
+ @(cd $(PACKAGE_DIR); $(SCRIPT_DIR)/ipkg-make-index.sh . 2>&1 > Packages && \
+ gzip -9c Packages > Packages.gz \
+ )
+
+$(curdir)/flags-install:= -j1
+
+$(eval $(call stampfile,$(curdir),package,prereq,.config))
+$(eval $(call stampfile,$(curdir),package,cleanup,$(TMP_DIR)/.build))
+$(eval $(call stampfile,$(curdir),package,compile,$(TMP_DIR)/.build))
+$(eval $(call stampfile,$(curdir),package,install,$(TMP_DIR)/.build))
+$(eval $(call stampfile,$(curdir),package,rootfs-prepare,$(TMP_DIR)/.build))
+
+$(eval $(call subdir,$(curdir)))
diff --git a/package/acx-mac80211/Makefile b/package/acx-mac80211/Makefile
new file mode 100644
index 000000000..40b3ce5ed
--- /dev/null
+++ b/package/acx-mac80211/Makefile
@@ -0,0 +1,245 @@
+#
+# Copyright (C) 2007-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=acx-mac80211
+PKG_REV:=v20120607
+PKG_VERSION:=20120607
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=git://acx100.git.sourceforge.net/gitroot/acx100/acx-mac80211
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=$(PKG_REV)
+PKG_BUILD_DEPENDS:=mac80211
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/acx-mac80211
+ SUBMENU:=Wireless Drivers
+ TITLE:=ACX1xx mac80211 driver
+ DEPENDS:=@(PCI_SUPPORT||TARGET_ar7) @mipsel +kmod-mac80211
+ FILES:=$(PKG_BUILD_DIR)/acx-mac80211.ko
+ AUTOLOAD:=$(call AutoLoad,50,acx-mac80211)
+ MENU:=1
+endef
+
+define KernelPackage/acx-mac80211/config
+ menu "Configuration"
+ depends on PACKAGE_kmod-acx-mac80211
+
+ config ACX_ID_0D
+ bool "ACX1xx Radio ID 0D firmware"
+ help
+ Download and install firmware for:
+ ACX1xx cards with Radio ID 0D into /lib/firmware.
+
+ config ACX_ID_11
+ bool "ACX1xx Radio ID 11 firmware"
+ help
+ Download and install firmware for:
+ ACX1xx cards with Radio ID 11 into /lib/firmware.
+
+ config ACX_ID_15
+ bool "ACX1xx Radio ID 15 firmware"
+ help
+ Download and install firmware for:
+ ACX1xx cards with Radio ID 15 into /lib/firmware.
+
+ config ACX_ID_16
+ bool "ACX1xx Radio ID 16 firmware"
+ default y
+ help
+ Download and install firmware for:
+ ACX1xx cards with Radio ID 16 into /lib/firmware.
+
+ choice
+ prompt "ACX111 firmware version"
+ depends on ACX_ID_16
+ default ACX_DEFAULT if !TARGET_adm5120
+ default ACX_1_2_1_34 if TARGET_adm5120
+ help
+ This option allows you to select the version of the acx firmware.
+
+ config ACX_DEFAULT
+ bool "Default"
+ help
+ Default firmware for ACX111 devices.
+
+ If unsure, select this.
+
+ config ACX_1_2_1_34
+ bool "1.2.1_34"
+ help
+ 1.2.1_34 firmware for ACX111 devices. Works with Zyxel P-334WT.
+
+ If unsure, select the "default" firmware.
+
+ endchoice
+
+ config ACX_ID_17
+ bool "ACX1xx Radio ID 17 firmware"
+ help
+ Download and install firmware for:
+ ACX1xx cards with Radio ID 17 into /lib/firmware.
+
+ config ACX_ID_19
+ bool "ACX1xx Radio ID 19 firmware"
+ default y
+ help
+ Download and install firmware for:
+ ACX1xx cards with Radio ID 19 into /lib/firmware.
+
+ config ACX_ID_1B
+ bool "ACX1xx Radio ID 1B firmware"
+ help
+ Download and install firmware for:
+ ACX1xx cards with Radio ID 1b into /lib/firmware.
+
+ endmenu
+endef
+
+define KernelPackage/acx-mac80211/description
+ Driver for acx111 cards (mac80211 version)
+endef
+
+define Download/tiacx100
+ FILE:=tiacx100
+ URL:=http://acx100.erley.org/fw/acx100_1.9.8.b/
+ MD5SUM:=24a54fd30f7658fcbffc825b0dd7aa5b
+endef
+
+define Download/tiacx100r0d
+ FILE:=tiacx100r0D
+ URL:=http://acx100.erley.org/fw/acx100_1.9.8.b/
+ MD5SUM:=1c7413e7b0be4ef7d1e424a132e17fab
+endef
+
+define Download/tiacx100r11
+ FILE:=tiacx100r11
+ URL:=http://acx100.erley.org/fw/acx100_1.9.8.b/
+ MD5SUM:=a150750ad33c512edc4afee5270b37cb
+endef
+
+define Download/tiacx100r15
+ FILE:=tiacx100r15
+ URL:=http://acx100.erley.org/fw/acx100_1.9.8.b/
+ MD5SUM:=c99d01d4fcf0d6cc00441aff60690be4
+endef
+
+define Download/tiacx111c16
+ FILE:=tiacx111c16
+ URL:=http://acx100.erley.org/fw/acx111_2.3.1.31/
+ MD5SUM:=7026826460376f6b174f9225bd7781b9
+endef
+
+define Download/tiacx111c16_1
+ FILE:=tiacx111c16_1.2.1_34
+ URL:=http://sites.google.com/site/atorkhov/files/
+ MD5SUM:=fcd07de4b25e1d2aaf3b78b27c5b7ee9
+endef
+
+define Download/tiacx111c17
+ FILE:=tiacx111c17
+ URL:=http://acx100.erley.org/fw/acx111_2.3.1.31/
+ MD5SUM:=95552544ca6d2b4e8c6aeb80b8ae7fdf
+endef
+
+define Download/tiacx111c19
+ FILE:=tiacx111c19
+ URL:=http://acx100.erley.org/fw/acx111_2.3.1.31/
+ MD5SUM:=a1fa9681e297b4e36e257090fc12265a
+endef
+
+define Download/tiacx111usbc1b
+ FILE:=tiacx111usbc1B
+ URL:=http://acx100.erley.org/fw/acx111_2.4.0.70-USB/
+ MD5SUM:=c4edecd912b2417779d0b65e3a7dc86d
+endef
+
+PKG_EXTRA_KCONFIG:= \
+ CONFIG_ACX_MAC80211=m \
+ CONFIG_ACX_MAC80211_PCI=m \
+
+PKG_EXTRA_CFLAGS:= \
+ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(PKG_EXTRA_KCONFIG)))) \
+ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(PKG_EXTRA_KCONFIG)))) \
+
+LINUX_AUTOCONF_FILE:= generated/autoconf.h
+
+define Build/Compile
+ $(MAKE) -C "$(LINUX_DIR)" \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ SUBDIRS="$(PKG_BUILD_DIR)" \
+ $(PKG_EXTRA_KCONFIG) \
+ EXTRA_CFLAGS="$(PKG_EXTRA_CFLAGS) -DCONFIG_ACX_MAC80211_VERSION=\"KERNEL_VERSION(3,7,0)\"" \
+ LINUXINCLUDE="-I$(STAGING_DIR)/usr/include/mac80211 -I$(LINUX_DIR)/include \
+ -Iarch/$(LINUX_KARCH)/include \
+ -include $(LINUX_AUTOCONF_FILE) \
+ -include linux/compat-2.6.h" \
+ V="$(V)" \
+ modules
+endef
+
+define Build/Configure
+endef
+
+define KernelPackage/acx-mac80211/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+
+ifneq ($(CONFIG_ACX_ID_0D)$(CONFIG_ACX_ID_11)$(CONFIG_ACX_ID_15),)
+ $(INSTALL_DATA) $(DL_DIR)/tiacx100 $(1)/lib/firmware/
+endif
+
+ifneq ($(CONFIG_ACX_ID_0D),)
+ $(INSTALL_DATA) $(DL_DIR)/tiacx100r0D $(1)/lib/firmware/
+endif
+
+ifneq ($(CONFIG_ACX_ID_11),)
+ $(INSTALL_DATA) $(DL_DIR)/tiacx100r11 $(1)/lib/firmware/
+endif
+
+ifneq ($(CONFIG_ACX_ID_15),)
+ $(INSTALL_DATA) $(DL_DIR)/tiacx100r15 $(1)/lib/firmware/
+endif
+
+ifneq ($(CONFIG_ACX_DEFAULT),)
+ $(INSTALL_DATA) $(DL_DIR)/tiacx111c16 $(1)/lib/firmware/
+endif
+
+ifneq ($(CONFIG_ACX_1_2_1_34),)
+ $(INSTALL_DATA) $(DL_DIR)/tiacx111c16_1.2.1_34 $(1)/lib/firmware/tiacx111c16
+endif
+
+ifneq ($(CONFIG_ACX_ID_17),)
+ $(INSTALL_DATA) $(DL_DIR)/tiacx111c17 $(1)/lib/firmware/
+endif
+
+ifneq ($(CONFIG_ACX_ID_19),)
+ $(INSTALL_DATA) $(DL_DIR)/tiacx111c19 $(1)/lib/firmware/
+endif
+
+ifneq ($(CONFIG_ACX_ID_1B),)
+ $(INSTALL_DATA) $(DL_DIR)/tiacx111usbc1B $(1)/lib/firmware/
+endif
+
+endef
+
+$(eval $(call KernelPackage,acx-mac80211))
+$(eval $(call Download,tiacx100))
+$(eval $(call Download,tiacx100r0d))
+$(eval $(call Download,tiacx100r11))
+$(eval $(call Download,tiacx100r15))
+$(eval $(call Download,tiacx111c16))
+$(eval $(call Download,tiacx111c16_1))
+$(eval $(call Download,tiacx111c17))
+$(eval $(call Download,tiacx111c19))
+$(eval $(call Download,tiacx111usbc1b))
diff --git a/package/acx-mac80211/patches/001-make-compatible-with-recent-mac80211.patch b/package/acx-mac80211/patches/001-make-compatible-with-recent-mac80211.patch
new file mode 100644
index 000000000..34ecf6d4a
--- /dev/null
+++ b/package/acx-mac80211/patches/001-make-compatible-with-recent-mac80211.patch
@@ -0,0 +1,43 @@
+--- a/acx_func.h
++++ b/acx_func.h
+@@ -335,8 +335,11 @@ void acx_process_rxbuf(acx_device_t *ade
+ */
+ #if CONFIG_ACX_MAC80211_VERSION < KERNEL_VERSION(2, 6, 39)
+ int acx_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+-#else
++#elif CONFIG_ACX_MAC80211_VERSION < KERNEL_VERSION(3, 7, 0)
+ void acx_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
++#else
++void acx_op_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
++ struct sk_buff *skb);
+ #endif
+
+ void acx_tx_work(struct work_struct *work);
+--- a/common.c
++++ b/common.c
+@@ -232,8 +232,11 @@ static void acx_rx(acx_device_t *adev, r
+ /* Tx Path */
+ #if CONFIG_ACX_MAC80211_VERSION < KERNEL_VERSION(2, 6, 39)
+ int acx_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+-#else
++#elif CONFIG_ACX_MAC80211_VERSION < KERNEL_VERSION(3, 7, 0)
+ void acx_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
++#else
++void acx_op_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
++ struct sk_buff *skb);
+ #endif
+
+ //-void acx_tx_work(struct work_struct *work);
+@@ -5183,7 +5186,12 @@ out:
+ * acx_compat, and hiding this #if/else. OTOH, inclusion doesnt care
+ * about old kernels
+ */
++#if CONFIG_ACX_MAC80211_VERSION < KERNEL_VERSION(3, 7, 0)
+ OP_TX_RET_TYPE acx_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
++#else
++void acx_op_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
++ struct sk_buff *skb)
++#endif
+ {
+ acx_device_t *adev = ieee2adev(hw);
+
diff --git a/package/acx-mac80211/patches/004-ratelimit_compile_fix.patch b/package/acx-mac80211/patches/004-ratelimit_compile_fix.patch
new file mode 100644
index 000000000..56110eab0
--- /dev/null
+++ b/package/acx-mac80211/patches/004-ratelimit_compile_fix.patch
@@ -0,0 +1,10 @@
+--- a/common.c
++++ b/common.c
+@@ -34,6 +34,7 @@
+ #include <linux/pci.h>
+ #include <linux/nl80211.h>
+ #include <linux/ieee80211.h>
++#include <linux/ratelimit.h>
+
+ #include <net/mac80211.h>
+
diff --git a/package/acx-mac80211/patches/100-hw-queue-check-fix.patch b/package/acx-mac80211/patches/100-hw-queue-check-fix.patch
new file mode 100644
index 000000000..62f2998e8
--- /dev/null
+++ b/package/acx-mac80211/patches/100-hw-queue-check-fix.patch
@@ -0,0 +1,42 @@
+--- a/mem.c
++++ b/mem.c
+@@ -2026,7 +2026,7 @@ static int __devinit acxmem_probe(struct
+ */
+ ieee->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
+ | BIT(NL80211_IFTYPE_ADHOC);
+- ieee->queues = 1;
++ ieee->queues = 4;
+ /* OW TODO Check if RTS/CTS threshold can be included here */
+
+ /* TODO: although in the original driver the maximum value was
+--- a/pci.c
++++ b/pci.c
+@@ -1010,7 +1010,7 @@ static int __devinit acxpci_probe(struct
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC) |
+ BIT(NL80211_IFTYPE_AP);
+- ieee->queues = 1;
++ ieee->queues = 4;
+ /* OW TODO Check if RTS/CTS threshold can be included here */
+
+ /* TODO: although in the original driver the maximum value was
+@@ -1682,7 +1682,7 @@ static __devinit int vlynq_probe(struct
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC) |
+ BIT(NL80211_IFTYPE_AP);
+- ieee->queues = 1;
++ ieee->queues = 4;
+
+ /* We base signal quality on winlevel approach of previous driver
+ * TODO OW 20100615 This should into a common init code
+--- a/usb.c
++++ b/usb.c
+@@ -1627,7 +1627,7 @@ acxusb_probe(struct usb_interface *intf,
+ */
+ ieee->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
+ | BIT(NL80211_IFTYPE_ADHOC);
+- ieee->queues = 1;
++ ieee->queues = 4;
+ // OW TODO Check if RTS/CTS threshold can be included here
+
+ // We base signal quality on winlevel approach of previous driver
diff --git a/package/admswconfig/Makefile b/package/admswconfig/Makefile
new file mode 100644
index 000000000..6b06cfe6a
--- /dev/null
+++ b/package/admswconfig/Makefile
@@ -0,0 +1,51 @@
+#
+# Copyright (C) 2007 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=admswconfig
+PKG_VERSION:=0.1
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://downloads.openwrt.org/sources
+PKG_MD5SUM:=faafd4618f970119a665b11b21ac6a26
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/admswconfig
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=ADM5120 Switch configuration tool
+ DEPENDS:=@TARGET_adm5120
+ URL:=http://sharon.esrac.ele.tue.nl/users/pe1rxq/linux-adm/admswconfig/
+endef
+
+define Package/admswconfig/description
+ A program to configure the internal ethernet switch of an ADM5120 processor.
+ You need the corresponding driver for the switch in the kernel.
+ With this program you can configure which ports of the switch belong
+ to the different ethernet devices.
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+ $(TARGET_CC) $(TARGET_CFLAGS) -Os $(PKG_BUILD_DIR)/admswconfig.c -o $(PKG_BUILD_DIR)/$(PKG_NAME)
+endef
+
+define Package/admswconfig/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/admswconfig $(1)/sbin/
+ $(INSTALL_DIR) $(1)/lib/network/
+ $(INSTALL_DATA) ./files/admswswitch.sh $(1)/lib/network/admswswitch.sh
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/admswconfig $(1)/etc/init.d/admswconfig
+endef
+
+$(eval $(call BuildPackage,admswconfig))
diff --git a/package/admswconfig/files/admswconfig b/package/admswconfig/files/admswconfig
new file mode 100644
index 000000000..723103065
--- /dev/null
+++ b/package/admswconfig/files/admswconfig
@@ -0,0 +1,68 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+START=05
+
+start() {
+ [ -e /etc/config/network ] && exit 0
+
+ mkdir -p /etc/config
+
+ board_name=$(awk 'BEGIN{FS="[ \t]+:[ \t]"} /system type/ {print $2}' /proc/cpuinfo)
+
+ case "$board_name" in
+ "Compex WP54"*)
+ board="Compex WP54";;
+ esac
+
+ echo "$board" |awk '
+ function p(cfgname, name) {
+ if (c[name] != "") print " option " cfgname " \"" c[name] "\""
+ }
+
+ BEGIN {
+ FS="="
+ c["lan_ifname"]="eth0"
+ c["wan_ifname"]="eth1"
+ c["eth0ports"]="1 2 3 4"
+ c["eth1ports"]="0"
+ }
+ END {
+ board=$1
+ if (board == "Compex WP54") {
+ c["eth0ports"]="0"
+ c["eth1ports"]="1"
+ }
+
+ print "#### VLAN configuration "
+ print "config switch"
+ p("eth0", "eth0ports")
+ p("eth1", "eth1ports")
+ print ""
+ print ""
+ print "#### Loopback configuration"
+ print "config interface loopback"
+ print " option ifname \"lo\""
+ print " option proto static"
+ print " option ipaddr 127.0.0.1"
+ print " option netmask 255.0.0.0"
+ print ""
+ print ""
+ print "#### LAN configuration"
+ print "config interface lan"
+ print " option type bridge"
+ p("ifname", "lan_ifname")
+ p("macaddr", "lan_macaddr")
+ print " option proto static"
+ print " option ipaddr 192.168.1.1"
+ print " option netmask 255.255.255.0"
+ print ""
+ print ""
+ print "#### WAN configuration"
+ print "config interface wan"
+ p("ifname", "wan_ifname")
+ p("macaddr", "wan_macaddr")
+ print " option proto dhcp"
+ }' > /etc/config/network
+}
+
diff --git a/package/admswconfig/files/admswswitch.sh b/package/admswconfig/files/admswswitch.sh
new file mode 100644
index 000000000..984d7eea7
--- /dev/null
+++ b/package/admswconfig/files/admswswitch.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+setup_switch_vlan() {
+ config_get ports "$CONFIG_SECTION" "eth$1"
+ ports=`echo "$ports"| sed s/" "/""/g`
+ ifconfig eth$1 down
+ admswconfig eth$1 ${ports}c
+ ifconfig eth$1 up
+}
+
+setup_switch() {
+ config_cb() {
+ case "$1" in
+ switch)
+ option_cb() {
+ case "$1" in
+ eth*) setup_switch_vlan "${1##eth}";;
+ esac
+ }
+ ;;
+ *)
+ option_cb() { return 0; }
+ ;;
+ esac
+ }
+ config_load network
+}
diff --git a/package/admswconfig/patches/001-matrix.patch b/package/admswconfig/patches/001-matrix.patch
new file mode 100644
index 000000000..e50d51575
--- /dev/null
+++ b/package/admswconfig/patches/001-matrix.patch
@@ -0,0 +1,15 @@
+--- a/admswconfig.c
++++ b/admswconfig.c
+@@ -111,9 +111,9 @@ int main(int argc, char **argv)
+ }
+ } else {
+ /* display matrix */
+- printf("ethX\tport0\tport1\tport2\tport3\tport4");
+- if (info.ports == 6)
+- printf("\tport5");
++ printf("ethX");
++ for (i = 0; i < info.ports; i++)
++ printf("\tport%d", i);
+ printf("\tCPU\n");
+ for (i = 0; i < info.ports; i++) {
+ printf("%d", i);
diff --git a/package/apex/Makefile b/package/apex/Makefile
new file mode 100644
index 000000000..f17118e46
--- /dev/null
+++ b/package/apex/Makefile
@@ -0,0 +1,58 @@
+#
+# Copyright (C) 2006-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=apex
+PKG_VERSION:=1.6.9
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=ftp://ftp.buici.com/pub/apex/ \
+ ftp://metalab.unc.edu/pub/Linux/system/boot/apex/
+PKG_MD5SUM:=9606cf2e3fd2c9a86fe0b61388509a30
+PKG_TARGETS:=bin
+
+include $(INCLUDE_DIR)/package.mk
+
+export GCC_HONOUR_COPTS=s
+
+define Package/apex
+ SECTION:=boot
+ CATEGORY:=Boot Loaders
+ DEPENDS:=@TARGET_ixp4xx
+ DEFAULT:=y
+ TITLE:=Boot loader for NSLU2, FSG3, NAS100D and others
+ URL:=http://wiki.buici.com/wiki/Apex_Bootloader
+endef
+
+define build_apex
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ ARCH=arm \
+ $(1)_config
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ KBUILD_HAVE_NLS=no \
+ ARCH=arm \
+ clean all
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/apex.bin $(PKG_BUILD_DIR)/out/apex-$(2).bin
+endef
+
+define Build/Compile
+ $(INSTALL_DIR) $(PKG_BUILD_DIR)/out
+ $(call build_apex,slugos-nslu2-armeb,nslu2-armeb)
+ $(call build_apex,slugos-nslu2-16mb-armeb,nslu2-16mb-armeb)
+ $(call build_apex,slugos-fsg3-armeb,fsg3-armeb)
+ $(call build_apex,slugos-nas100d-armeb,nas100d-armeb)
+endef
+
+define Package/apex/install
+ $(INSTALL_DIR) $(STAGING_DIR)/apex
+ $(CP) $(PKG_BUILD_DIR)/out/*.bin $(1)/
+endef
+
+$(eval $(call BuildPackage,apex))
diff --git a/package/apex/patches/001-compile_fix.patch b/package/apex/patches/001-compile_fix.patch
new file mode 100644
index 000000000..8a25de657
--- /dev/null
+++ b/package/apex/patches/001-compile_fix.patch
@@ -0,0 +1,20 @@
+--- a/Makefile
++++ b/Makefile
+@@ -444,7 +444,7 @@ ifeq ($(config-targets),1)
+ include $(srctree)/src/arch-$(SRCARCH)/Makefile
+ export KBUILD_DEFCONFIG
+
+-config %config: scripts_basic outputmakefile FORCE
++%config: scripts_basic outputmakefile FORCE
+ $(Q)mkdir -p include/linux include/config
+ $(Q)$(MAKE) $(build)=scripts/kconfig $@
+
+@@ -1585,7 +1585,7 @@ endif
+ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+
+ # Modules
+-/ %/: prepare scripts FORCE
++%/: prepare scripts FORCE
+ $(cmd_crmodverdir)
+ $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
+ $(build)=$(build-dir)
diff --git a/package/apex/patches/100-openwrt_nslu2_armeb_config.patch b/package/apex/patches/100-openwrt_nslu2_armeb_config.patch
new file mode 100644
index 000000000..7e9cfdff1
--- /dev/null
+++ b/package/apex/patches/100-openwrt_nslu2_armeb_config.patch
@@ -0,0 +1,23 @@
+--- a/src/mach-ixp42x/slugos-nslu2-armeb_config
++++ b/src/mach-ixp42x/slugos-nslu2-armeb_config
+@@ -19,7 +19,7 @@ CONFIG_EXPERIMENTAL=y
+ #
+ # General Setup
+ #
+-CONFIG_TARGET_DESCRIPTION="SlugOS NSLU2 (bigendian)"
++CONFIG_TARGET_DESCRIPTION="OpenWRT NSLU2 (8MiB Flash)"
+ CONFIG_CROSS_COMPILE=""
+ CONFIG_AEABI=y
+ # CONFIG_DRIVER_LONG_LONG_SIZE is not set
+@@ -163,9 +163,9 @@ CONFIG_ENV_REGION_KERNEL_ALT="fis://kern
+ # Overrides
+ #
+ CONFIG_ENV_DEFAULT_CMDLINE_OVERRIDE=y
+-CONFIG_ENV_DEFAULT_CMDLINE="root=/dev/mtdblock4 rootfstype=jffs2 console=ttyS0,115200 init=/linuxrc"
++CONFIG_ENV_DEFAULT_CMDLINE="root=/dev/mtdblock4 rootfstype=squashfs,jffs2 console=ttyS0,115200 init=/etc/preinit noinitrd"
+ CONFIG_ENV_DEFAULT_CMDLINE_ALT_P=y
+-CONFIG_ENV_DEFAULT_CMDLINE_ALT="root=/dev/mtdblock4 rootfstype=jffs2 console=ttyS0,115200 init=/linuxrc"
++CONFIG_ENV_DEFAULT_CMDLINE_ALT="root=/dev/mtdblock4 rootfstype=squashfs,jffs2 console=ttyS0,115200 init=/etc/preinit noinitrd"
+ # CONFIG_ENV_DEFAULT_STARTUP_OVERRIDE is not set
+ # CONFIG_ENV_DEFAULT_STARTUP_ALT_P is not set
+ CONFIG_USES_NOR_BOOTFLASH=y
diff --git a/package/apex/patches/120-openwrt_nslu2_16mb_armeb_config.patch b/package/apex/patches/120-openwrt_nslu2_16mb_armeb_config.patch
new file mode 100644
index 000000000..614ef7fe8
--- /dev/null
+++ b/package/apex/patches/120-openwrt_nslu2_16mb_armeb_config.patch
@@ -0,0 +1,23 @@
+--- a/src/mach-ixp42x/slugos-nslu2-16mb-armeb_config
++++ b/src/mach-ixp42x/slugos-nslu2-16mb-armeb_config
+@@ -19,7 +19,7 @@ CONFIG_EXPERIMENTAL=y
+ #
+ # General Setup
+ #
+-CONFIG_TARGET_DESCRIPTION="SlugOS NSLU2/BE (16MiB Flash)"
++CONFIG_TARGET_DESCRIPTION="OpenWRT NSLU2 (16MiB Flash)"
+ CONFIG_CROSS_COMPILE=""
+ CONFIG_AEABI=y
+ # CONFIG_DRIVER_LONG_LONG_SIZE is not set
+@@ -163,9 +163,9 @@ CONFIG_ENV_REGION_KERNEL_ALT="fis://kern
+ # Overrides
+ #
+ CONFIG_ENV_DEFAULT_CMDLINE_OVERRIDE=y
+-CONFIG_ENV_DEFAULT_CMDLINE="root=/dev/mtdblock4 rootfstype=jffs2 console=ttyS0,115200 init=/linuxrc"
++CONFIG_ENV_DEFAULT_CMDLINE="root=/dev/mtdblock4 rootfstype=squashfs,jffs2 console=ttyS0,115200 init=/etc/preinit noinitrd"
+ CONFIG_ENV_DEFAULT_CMDLINE_ALT_P=y
+-CONFIG_ENV_DEFAULT_CMDLINE_ALT="root=/dev/mtdblock4 rootfstype=jffs2 console=ttyS0,115200 init=/linuxrc"
++CONFIG_ENV_DEFAULT_CMDLINE_ALT="root=/dev/mtdblock4 rootfstype=squashfs,jffs2 console=ttyS0,115200 init=/etc/preinit noinitrd"
+ # CONFIG_ENV_DEFAULT_STARTUP_OVERRIDE is not set
+ # CONFIG_ENV_DEFAULT_STARTUP_ALT_P is not set
+ CONFIG_USES_NOR_BOOTFLASH=y
diff --git a/package/apex/patches/140-openwrt_fsg3_armeb_config.patch b/package/apex/patches/140-openwrt_fsg3_armeb_config.patch
new file mode 100644
index 000000000..a1651e69a
--- /dev/null
+++ b/package/apex/patches/140-openwrt_fsg3_armeb_config.patch
@@ -0,0 +1,23 @@
+--- a/src/mach-ixp42x/slugos-fsg3-armeb_config
++++ b/src/mach-ixp42x/slugos-fsg3-armeb_config
+@@ -17,7 +17,7 @@ CONFIG_EXPERIMENTAL=y
+ #
+ # General Setup
+ #
+-CONFIG_TARGET_DESCRIPTION="SlugOS FSG3/BE"
++CONFIG_TARGET_DESCRIPTION="OpenWRT FSG3"
+ CONFIG_CROSS_COMPILE=""
+ CONFIG_AEABI=y
+ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+@@ -148,9 +148,9 @@ CONFIG_ENV_REGION_KERNEL_ALT="fis://kern
+ # Overrides
+ #
+ CONFIG_ENV_DEFAULT_CMDLINE_OVERRIDE=y
+-CONFIG_ENV_DEFAULT_CMDLINE="root=/dev/sda1 rootdelay=10 console=ttyS0,115200"
++CONFIG_ENV_DEFAULT_CMDLINE="root=/dev/sda1 rootdelay=10 console=ttyS0,115200 init=/etc/preinit noinitrd"
+ CONFIG_ENV_DEFAULT_CMDLINE_ALT_P=y
+-CONFIG_ENV_DEFAULT_CMDLINE_ALT="root=/dev/sda2 rootdelay=10 console=ttyS0,115200"
++CONFIG_ENV_DEFAULT_CMDLINE_ALT="root=/dev/mtdblock2 rootfstype=squashfs console=ttyS0,115200 init=/etc/preinit noinitrd"
+ # CONFIG_ENV_DEFAULT_STARTUP_OVERRIDE is not set
+ # CONFIG_ENV_DEFAULT_STARTUP_ALT_P is not set
+ CONFIG_USES_NOR_BOOTFLASH=y
diff --git a/package/apex/patches/150-limit_ram_to_64mb.patch b/package/apex/patches/150-limit_ram_to_64mb.patch
new file mode 100644
index 000000000..3e178166e
--- /dev/null
+++ b/package/apex/patches/150-limit_ram_to_64mb.patch
@@ -0,0 +1,22 @@
+--- a/src/mach-ixp42x/slugos-nslu2-armeb_config
++++ b/src/mach-ixp42x/slugos-nslu2-armeb_config
+@@ -137,7 +137,7 @@ CONFIG_AUTOBOOT_DELAY=10
+ CONFIG_ENV_STARTUP_KERNEL_COPY=y
+ # CONFIG_ENV_REGION_KERNEL_SWAP is not set
+ CONFIG_ENV_STARTUP_PREFIX_P=y
+-CONFIG_ENV_STARTUP_PREFIX="sdram-init; memscan -u 0+256m"
++CONFIG_ENV_STARTUP_PREFIX="sdram-init; memscan -u 0+64m"
+
+ #
+ # Regions
+--- a/src/mach-ixp42x/slugos-nslu2-16mb-armeb_config
++++ b/src/mach-ixp42x/slugos-nslu2-16mb-armeb_config
+@@ -137,7 +137,7 @@ CONFIG_AUTOBOOT_DELAY=10
+ CONFIG_ENV_STARTUP_KERNEL_COPY=y
+ # CONFIG_ENV_REGION_KERNEL_SWAP is not set
+ CONFIG_ENV_STARTUP_PREFIX_P=y
+-CONFIG_ENV_STARTUP_PREFIX="sdram-init; memscan -u 0+256m"
++CONFIG_ENV_STARTUP_PREFIX="sdram-init; memscan -u 0+64m"
+
+ #
+ # Regions
diff --git a/package/apex/patches/160-openwrt_nas100d_armeb_config.patch b/package/apex/patches/160-openwrt_nas100d_armeb_config.patch
new file mode 100644
index 000000000..0b0c985e4
--- /dev/null
+++ b/package/apex/patches/160-openwrt_nas100d_armeb_config.patch
@@ -0,0 +1,20 @@
+--- a/src/mach-ixp42x/slugos-nas100d-armeb_config
++++ b/src/mach-ixp42x/slugos-nas100d-armeb_config
+@@ -19,7 +19,7 @@ CONFIG_EXPERIMENTAL=y
+ #
+ # General Setup
+ #
+-CONFIG_TARGET_DESCRIPTION="SlugOS NAS100D/BE"
++CONFIG_TARGET_DESCRIPTION="OpenWRT NAS100D"
+ CONFIG_CROSS_COMPILE=""
+ CONFIG_AEABI=y
+ # CONFIG_DRIVER_LONG_LONG_SIZE is not set
+@@ -158,7 +158,7 @@ CONFIG_ENV_REGION_KERNEL="fis://kernel"
+ # Overrides
+ #
+ CONFIG_ENV_DEFAULT_CMDLINE_OVERRIDE=y
+-CONFIG_ENV_DEFAULT_CMDLINE="root=/dev/mtdblock2 rootfstype=jffs2 console=ttyS0,115200 init=/linuxrc"
++CONFIG_ENV_DEFAULT_CMDLINE="root=/dev/mtdblock2 rootfstype=squashfs,jffs2 console=ttyS0,115200 init=/etc/preinit noinitrd"
+ # CONFIG_ENV_DEFAULT_STARTUP_OVERRIDE is not set
+ CONFIG_USES_NOR_BOOTFLASH=y
+ CONFIG_RELOCATE_SIMPLE=y
diff --git a/package/ar7-atm/Config.in b/package/ar7-atm/Config.in
new file mode 100644
index 000000000..479b7ad07
--- /dev/null
+++ b/package/ar7-atm/Config.in
@@ -0,0 +1,22 @@
+menu "Configuration"
+ depends on (PACKAGE_kmod-sangam-atm-annex-a || PACKAGE_kmod-sangam-atm-annex-b)
+
+choice
+ prompt "Firmware version"
+ default AR7_ATM_FW_VERSION_704
+ help
+ This option allows you to switch between firmware/driver versions which
+ might improve the DSL line speed.
+
+config AR7_ATM_FW_VERSION_705
+ bool "D7.05.01.00"
+
+config AR7_ATM_FW_VERSION_704
+ bool "D7.04.03.00"
+
+config AR7_ATM_FW_VERSION_703
+ bool "D7.03.01.00"
+
+endchoice
+
+endmenu
diff --git a/package/ar7-atm/Makefile b/package/ar7-atm/Makefile
new file mode 100644
index 000000000..9568cce13
--- /dev/null
+++ b/package/ar7-atm/Makefile
@@ -0,0 +1,99 @@
+#
+# Copyright (C) 2006-2009 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=sangam_atm
+
+ifeq ($(CONFIG_AR7_ATM_FW_VERSION_705),y)
+PKG_VERSION:=D7.05.01.00
+PKG_MD5SUM:=42ee465be5cfbe9476fc25deb260d450
+PKG_RELEASE:=R1
+PATCH_DIR:=patches-$(PKG_VERSION)
+endif
+
+ifeq ($(CONFIG_AR7_ATM_FW_VERSION_704),y)
+PKG_VERSION:=D7.04.03.00
+PKG_MD5SUM:=3d76004e46f09e88931f91670cb420ad
+PKG_RELEASE:=R1
+PATCH_DIR:=patches-$(PKG_VERSION)
+endif
+
+ifeq ($(CONFIG_AR7_ATM_FW_VERSION_703),y)
+PKG_VERSION:=D7.03.01.00
+PKG_MD5SUM:=bc6e9c6adb1be25820c7ee661de8ca7d
+PKG_RELEASE:=R2
+PATCH_DIR:=patches-D7.04.03.00
+endif
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_RELEASE).tar.bz2
+PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/sangam-atm/Default
+ SUBMENU:=Network Devices
+ DEPENDS:=@TARGET_ar7 +kmod-atm
+ TITLE:=AR7 ADSL driver
+ FILES:=$(PKG_BUILD_DIR)/tiatm.ko
+ AUTOLOAD:=$(call AutoLoad,50,tiatm)
+ MENU:=1
+endef
+
+define KernelPackage/sangam-atm/config
+ source "$(SOURCE)/Config.in"
+endef
+
+define KernelPackage/sangam-atm-annex-a
+$(call KernelPackage/sangam-atm/Default)
+ TITLE+= (Annex A, ADSL over POTS)
+endef
+
+define KernelPackage/sangam-atm-annex-a/description
+ The AR7 ADSL driver for Annex A (ADSL over POTS).
+endef
+
+define KernelPackage/sangam-atm-annex-a/config
+$(call KernelPackage/sangam-atm/config)
+endef
+
+define KernelPackage/sangam-atm-annex-b
+$(call KernelPackage/sangam-atm/Default)
+ TITLE+= (Annex B, ADSL over ISDN)
+endef
+
+define KernelPackage/sangam-atm-annex-b/description
+ The AR7 ADSL driver for Annex B (ADSL over ISDN).
+endef
+
+define KernelPackage/sangam-atm-annex-a/config
+$(call KernelPackage/sangam-atm/config)
+endef
+
+define Build/Compile
+ $(MAKE) -C "$(LINUX_DIR)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ ARCH="$(LINUX_KARCH)" \
+ SUBDIRS="$(PKG_BUILD_DIR)" \
+ modules
+endef
+
+define KernelPackage/sangam-atm-annex-a/install
+ mkdir -p $(1)/lib/firmware
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/ar0700mp.bin $(1)/lib/firmware/
+ ln -sf ar0700mp.bin $(1)/lib/firmware/ar0700xx.bin
+endef
+
+define KernelPackage/sangam-atm-annex-b/install
+ mkdir -p $(1)/lib/firmware
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/ar0700db.bin $(1)/lib/firmware/
+ ln -sf ar0700db.bin $(1)/lib/firmware/ar0700xx.bin
+endef
+
+$(eval $(call KernelPackage,sangam-atm-annex-a))
+$(eval $(call KernelPackage,sangam-atm-annex-b))
diff --git a/package/ar7-atm/patches-D7.04.03.00/100-compile_fix.patch b/package/ar7-atm/patches-D7.04.03.00/100-compile_fix.patch
new file mode 100644
index 000000000..df5fe5396
--- /dev/null
+++ b/package/ar7-atm/patches-D7.04.03.00/100-compile_fix.patch
@@ -0,0 +1,768 @@
+--- a/cppi_cpaal5.c
++++ b/cppi_cpaal5.c
+@@ -352,7 +352,7 @@ static int halRxReturn(HAL_RECEIVEINFO *
+ {
+ /* malloc failed, add this RCB to Needs Buffer List */
+ TempRcb->FragCount = 1; /*MJH+030417*/
+- (HAL_RCB *)TempRcb->Eop = TempRcb; /* GSG +030430 */
++ TempRcb->Eop = TempRcb; /* GSG +030430 */
+
+ if(HalDev->NeedsCount < MAX_NEEDS) /* +MJH 030410 */
+ { /* +MJH 030410 */
+--- a/dsl_hal_api.c
++++ b/dsl_hal_api.c
+@@ -254,15 +254,15 @@
+ * of phyEnableDisableWord & phyControlWord to avoid changing API struct
+ * which may cause change required to application data structure.
+ ******************************************************************************/
+-#include <dev_host_interface.h>
+-#include <dsl_hal_register.h>
+-#include <dsl_hal_support.h>
++#include "dev_host_interface.h"
++#include "dsl_hal_register.h"
++#include "dsl_hal_support.h"
+
+ #ifndef NO_ADV_STATS
+-#include <dsl_hal_logtable.h>
++#include "dsl_hal_logtable.h"
+ #endif
+
+-#include <dsl_hal_version.h>
++#include "dsl_hal_version.h"
+
+ // UR8_MERGE_START CQ11054 Jack Zhang
+ static unsigned int highprecision_selected = 0; //By default we use low precision for backward compt.
+--- a/dsl_hal_support.c
++++ b/dsl_hal_support.c
+@@ -140,9 +140,9 @@
+ * oamFeature are overriden
+ // UR8_MERGE_END CQ10774 Ram
+ *******************************************************************************/
+-#include <dev_host_interface.h>
+-#include <dsl_hal_register.h>
+-#include <dsl_hal_support.h>
++#include "dev_host_interface.h"
++#include "dsl_hal_register.h"
++#include "dsl_hal_support.h"
+
+ #define NUM_READ_RETRIES 3
+ static unsigned int dslhal_support_adsl2ByteSwap32(unsigned int in32Bits);
+--- a/dsl_hal_support.h
++++ b/dsl_hal_support.h
+@@ -49,7 +49,7 @@
+ * 04Nov05 0.11.00 CPH Fixed T1413 mode got Zero DS/US rate when DSL_BIT_TMODE is set.
+ *******************************************************************************/
+
+-#include <dsl_hal_api.h>
++#include "dsl_hal_api.h"
+
+ #define virtual2Physical(a) (((int)a)&~0xe0000000)
+ /* External Function Prototype Declarations */
+--- a/Makefile
++++ b/Makefile
+@@ -1,18 +1,9 @@
+-# File: drivers/atm/ti_evm3/Makefile
+ #
+-# Makefile for the Texas Instruments EVM3 ADSL/ATM driver.
++# Makefile for the TIATM device driver.
+ #
+-#
+-# Copyright (c) 2000 Texas Instruments Incorporated.
+-# Jeff Harrell (jharrell@telogy.com)
+-# Viren Balar (vbalar@ti.com)
+-# Victor Wells (vwells@telogy.com)
+-#
+-include $(TOPDIR)/Rules.make
+-
+-
+-
+-
+-
+-
+
++CONFIG_SANGAM_ATM=m
++#EXTRA_CFLAGS += -DEL -I. -DPOST_SILICON -DCOMMON_NSP -DCONFIG_LED_MODULE -DDEREGISTER_LED -DNO_ACT
++EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -DNO_ACT -D__NO__VOICE_PATCH__ -DEL
++obj-$(CONFIG_SANGAM_ATM) := tiatm.o
++tiatm-objs += cpsar.o aal5sar.o tn7sar.o tn7atm.o tn7dsl.o dsl_hal_api.o dsl_hal_support.o
+--- a/tn7atm.c
++++ b/tn7atm.c
+@@ -61,7 +61,6 @@
+ * UR8_MERGE_END CQ11057*
+ *********************************************************************************************/
+
+-#include <linux/config.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -69,11 +68,14 @@
+ #include <linux/delay.h>
+ #include <linux/spinlock.h>
+ #include <linux/smp_lock.h>
+-#include <asm/io.h>
+-#include <asm/mips-boards/prom.h>
+ #include <linux/proc_fs.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
++
++#include <asm/io.h>
++#include <asm/ar7/ar7.h>
++#include <asm/ar7/prom.h>
++
+ #include "dsl_hal_api.h"
+ #include "tn7atm.h"
+ #include "tn7api.h"
+@@ -82,6 +84,7 @@
+ #include "dsl_hal_register.h"
+
+ #ifdef MODULE
++MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION ("Tnetd73xx ATM Device Driver");
+ MODULE_AUTHOR ("Zhicheng Tang");
+ #endif
+@@ -100,9 +103,9 @@ MODULE_AUTHOR ("Zhicheng Tang");
+
+ /*end of externs */
+
+-#ifndef TI_STATIC_ALLOCATIONS
+-#define TI_STATIC_ALLOCATIONS
+-#endif
++//#ifndef TI_STATIC_ALLOCATIONS
++//#define TI_STATIC_ALLOCATIONS
++//#endif
+
+ #define tn7atm_kfree_skb(x) dev_kfree_skb(x)
+
+@@ -114,7 +117,7 @@ static int EnableQoS = FALSE;
+ /* prototypes */
+ static int tn7atm_set_can_support_adsl2 (int can);
+
+-static int tn7atm_open (struct atm_vcc *vcc, short vpi, int vci);
++static int tn7atm_open (struct atm_vcc *vcc);
+
+ static void tn7atm_close (struct atm_vcc *vcc);
+
+@@ -257,13 +260,12 @@ static const struct atmdev_ops tn7atm_op
+ getsockopt: NULL,
+ setsockopt: NULL,
+ send: tn7atm_send,
+- sg_send: NULL,
+ phy_put: NULL,
+ phy_get: NULL,
+ change_qos: tn7atm_change_qos,
+ };
+
+-const char drv_proc_root_folder[] = "avalanche/";
++const char drv_proc_root_folder[] = "avalanche";
+ static struct proc_dir_entry *root_proc_dir_entry = NULL;
+ #define DRV_PROC_MODE 0644
+ static int proc_root_already_exists = TRUE;
+@@ -559,56 +561,6 @@ static int turbodsl_check_priority_type(
+
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+- * Function: int tn7atm_walk_vccs(struct atm_dev *dev, short *vcc, int *vci)
+- *
+- * Description: retrieve VPI/VCI for connection
+- *
+- *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+-static int tn7atm_walk_vccs (struct atm_vcc *vcc, short *vpi, int *vci)
+-{
+- struct atm_vcc *walk;
+-
+- /*
+- * find a free VPI
+- */
+- if (*vpi == ATM_VPI_ANY)
+- {
+-
+- for (*vpi = 0, walk = vcc->dev->vccs; walk; walk = walk->next)
+- {
+-
+- if ((walk->vci == *vci) && (walk->vpi == *vpi))
+- {
+- (*vpi)++;
+- walk = vcc->dev->vccs;
+- }
+- }
+- }
+-
+- /*
+- * find a free VCI
+- */
+- if (*vci == ATM_VCI_ANY)
+- {
+-
+- for (*vci = ATM_NOT_RSV_VCI, walk = vcc->dev->vccs; walk;
+- walk = walk->next)
+- {
+-
+- if ((walk->vpi = *vpi) && (walk->vci == *vci))
+- {
+- *vci = walk->vci + 1;
+- walk = vcc->dev->vccs;
+- }
+- }
+- }
+-
+- return 0;
+-}
+-
+-
+-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+- *
+ * Function: int tn7atm_sar_irq(void)
+ *
+ * Description: tnetd73xx SAR interrupt.
+@@ -693,7 +645,7 @@ static int __init tn7atm_irq_request (st
+ * Register SAR interrupt
+ */
+ priv->sar_irq = LNXINTNUM (ATM_SAR_INT); /* Interrupt line # */
+- if (request_irq (priv->sar_irq, tn7atm_sar_irq, SA_INTERRUPT, "SAR ", dev))
++ if (request_irq (priv->sar_irq, tn7atm_sar_irq, IRQF_DISABLED, "SAR ", dev))
+ printk ("Could not register tn7atm_sar_irq\n");
+
+ /*
+@@ -704,14 +656,14 @@ static int __init tn7atm_irq_request (st
+ {
+ def_sar_inter_pace = os_atoi (ptr);
+ }
+- avalanche_request_pacing (priv->sar_irq, ATM_SAR_INT_PACING_BLOCK_NUM,
+- def_sar_inter_pace);
++/* avalanche_request_pacing (priv->sar_irq, ATM_SAR_INT_PACING_BLOCK_NUM,
++ def_sar_inter_pace);*/
+
+ /*
+ * Reigster Receive interrupt A
+ */
+ priv->dsl_irq = LNXINTNUM (ATM_DSL_INT); /* Interrupt line # */
+- if (request_irq (priv->dsl_irq, tn7atm_dsl_irq, SA_INTERRUPT, "DSL ", dev))
++ if (request_irq (priv->dsl_irq, tn7atm_dsl_irq, IRQF_DISABLED, "DSL ", dev))
+ printk ("Could not register tn7atm_dsl_irq\n");
+
+ /***** VRB Tasklet Mode ****/
+@@ -875,11 +827,15 @@ static int __init tn7atm_get_ESI (struct
+ #define ATM_VBR_RT 5
+ #endif
+
+-int tn7atm_open (struct atm_vcc *vcc, short vpi, int vci)
++int tn7atm_open (struct atm_vcc *vcc)
+ {
+ tn7atm_activate_vc_parm_t tn7atm_activate_vc_parm;
+ int rc;
+ //int flags;
++ tn7atm_activate_vc_parm.pcr = 0x20000;
++ tn7atm_activate_vc_parm.scr = 0x20000;
++ tn7atm_activate_vc_parm.mbs = 0x20000;
++ tn7atm_activate_vc_parm.cdvt = 10000;
+
+ dgprintf(1, "tn7atm_open()\n");
+
+@@ -891,24 +847,18 @@ int tn7atm_open (struct atm_vcc *vcc, sh
+ return -1;
+ }
+
+- MOD_INC_USE_COUNT;
++// MOD_INC_USE_COUNT;
+
+- /* find a free VPI/VCI */
+- tn7atm_walk_vccs(vcc, &vpi, &vci);
+-
+- vcc->vpi = vpi;
+- vcc->vci = vci;
+-
+- if ((vci == ATM_VCI_UNSPEC) || (vpi == ATM_VCI_UNSPEC))
++ if ((vcc->vci == ATM_VCI_UNSPEC) || (vcc->vpi == ATM_VCI_UNSPEC))
+ {
+- MOD_DEC_USE_COUNT;
++// MOD_DEC_USE_COUNT;
+ return -EBUSY;
+ }
+
+- tn7atm_activate_vc_parm.vpi = vpi;
+- tn7atm_activate_vc_parm.vci = vci;
++ tn7atm_activate_vc_parm.vpi = vcc->vpi;
++ tn7atm_activate_vc_parm.vci = vcc->vci;
+
+- if ((vpi == CLEAR_EOC_VPI) && (vci == CLEAR_EOC_VCI))
++ if ((vcc->vpi == CLEAR_EOC_VPI) && (vcc->vci == CLEAR_EOC_VCI))
+ {
+ /* always use (max_dma_chan+1) for clear eoc */
+ tn7atm_activate_vc_parm.chan = EOC_DMA_CHAN;
+@@ -916,7 +866,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh
+ /* check to see whether clear eoc is opened or not */
+ if (tn7atm_activate_vc_parm.priv->lut[tn7atm_activate_vc_parm.chan].inuse)
+ {
+- MOD_DEC_USE_COUNT;
++// MOD_DEC_USE_COUNT;
+ printk("tn7atm_open: Clear EOC channel (dmachan=%d) already in use.\n", tn7atm_activate_vc_parm.chan);
+ return -EBUSY;
+ }
+@@ -925,7 +875,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh
+ if (rc)
+ {
+ printk("tn7atm_open: failed to setup clear_eoc\n");
+- MOD_DEC_USE_COUNT;
++// MOD_DEC_USE_COUNT;
+ return -EBUSY;
+ }
+ tn7atm_set_lut(tn7atm_activate_vc_parm.priv,vcc, tn7atm_activate_vc_parm.chan);
+@@ -934,17 +884,17 @@ int tn7atm_open (struct atm_vcc *vcc, sh
+ }
+ else /* PVC channel setup */
+ {
+- if ((vpi==REMOTE_MGMT_VPI) && (vci==REMOTE_MGMT_VCI))
++ if ((vcc->vpi==REMOTE_MGMT_VPI) && (vcc->vci==REMOTE_MGMT_VCI))
+ {
+ tn7atm_activate_vc_parm.chan = 14; /* always use chan 14 for MII PVC-base romote mgmt */
+ }
+ else
+ {
+- rc = tn7atm_lut_find(vpi, vci);
++ rc = tn7atm_lut_find(vcc->vpi, vcc->vci);
+ /* check to see whether PVC is opened or not */
+ if(ATM_NO_DMA_CHAN != rc)
+ {
+- MOD_DEC_USE_COUNT;
++// MOD_DEC_USE_COUNT;
+ printk("PVC already opened. dmachan = %d\n", rc);
+ return -EBUSY;
+ }
+@@ -976,6 +926,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh
+ tn7atm_activate_vc_parm.priority = 2;
+ break;
+
++#if 0
+ case ATM_VBR: /* Variable Bit Rate-Non RealTime*/
+ tn7atm_activate_vc_parm.qos = 1;
+ tn7atm_activate_vc_parm.priority = 1;
+@@ -997,6 +948,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh
+ tn7atm_activate_vc_parm.mbs = vcc->qos.txtp.max_pcr;
+ tn7atm_activate_vc_parm.cdvt = vcc->qos.txtp.max_cdv;
+ break;
++#endif
+
+ default:
+ tn7atm_activate_vc_parm.qos = 2;
+@@ -1024,7 +976,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh
+ if (rc < 0)
+ {
+ printk("failed to activate hw channel\n");
+- MOD_DEC_USE_COUNT;
++// MOD_DEC_USE_COUNT;
+ tn7atm_lut_clear(vcc, tn7atm_activate_vc_parm.chan);
+ //spin_unlock_irqrestore(&chan_init_lock, flags);
+ return -EBUSY;
+@@ -1114,7 +1066,7 @@ void tn7atm_close (struct atm_vcc *vcc)
+ tn7atm_lut_clear (vcc, dmachan);
+ //spin_unlock_irqrestore (&closeLock, closeFlag);
+
+- MOD_DEC_USE_COUNT;
++// MOD_DEC_USE_COUNT;
+
+ dgprintf (1, "Leave tn7atm_close\n");
+ }
+@@ -1528,8 +1480,7 @@ int tn7atm_receive (void *os_dev, int ch
+ * firewall is on */
+
+ dgprintf (3, "pushing the skb...\n");
+-
+- skb->stamp = vcc->timestamp = xtime;
++ __net_timestamp(skb);
+
+ xdump ((unsigned char *) skb->data, skb->len, 5);
+
+@@ -1725,8 +1676,7 @@ static void tn7atm_exit (void)
+
+ kfree (dev->dev_data);
+
+- // atm_dev_deregister (dev);
+- shutdown_atm_dev (dev);
++ atm_dev_deregister (dev);
+
+ /*
+ * remove proc entries
+@@ -1885,9 +1835,6 @@ static int __init tn7atm_detect (void)
+ /*
+ * Set up proc entry for atm stats
+ */
+- if (tn7atm_xlate_proc_name
+- (drv_proc_root_folder, &root_proc_dir_entry, &residual))
+- {
+ printk ("Creating new root folder %s in the proc for the driver stats \n",
+ drv_proc_root_folder);
+ root_proc_dir_entry = proc_mkdir (drv_proc_root_folder, NULL);
+@@ -1897,7 +1844,6 @@ static int __init tn7atm_detect (void)
+ return -ENOMEM;
+ }
+ proc_root_already_exists = FALSE;
+- }
+
+ /*
+ * AV: Clean-up. Moved all the definitions to the data structure.
+@@ -2479,7 +2425,5 @@ static int tn7atm_proc_qos_write(struct
+ return count;
+ }
+
+-#ifdef MODULE
+ module_init (tn7atm_detect);
+ module_exit (tn7atm_exit);
+-#endif /* MODULE */
+--- a/tn7atm.h
++++ b/tn7atm.h
+@@ -19,7 +19,8 @@
+ //#include "mips_support.h"
+ #include <linux/list.h>
+
+-#include <linux/config.h>
++#define MIPS_EXCEPTION_OFFSET 8
++#define LNXINTNUM(x)((x) + MIPS_EXCEPTION_OFFSET)
+
+ #ifdef CONFIG_MODVERSIONS
+ #include <linux/modversions.h>
+--- a/tn7dsl.c
++++ b/tn7dsl.c
+@@ -94,7 +94,6 @@
+ * 1/02/07 JZ CQ11054: Data Precision and Range Changes for TR-069 Conformance
+ * UR8_MERGE_END CQ11054*
+ *********************************************************************************************/
+-#include <linux/config.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -102,8 +101,6 @@
+ #include <linux/delay.h>
+ #include <linux/spinlock.h>
+ #include <linux/smp_lock.h>
+-#include <asm/io.h>
+-#include <asm/mips-boards/prom.h>
+ #include <linux/proc_fs.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
+@@ -111,6 +108,12 @@
+ #include <linux/timer.h>
+ #include <linux/vmalloc.h>
+ #include <linux/file.h>
++#include <linux/firmware.h>
++
++#include <asm/io.h>
++#include <asm/ar7/ar7.h>
++#include <asm/ar7/prom.h>
++
+ /* Modules specific header files */
+ #include "tn7atm.h"
+ #include "tn7api.h"
+@@ -173,7 +176,7 @@ led_reg_t ledreg[2];
+ static struct led_funcs ledreg[2];
+ #endif
+
+-#define DEV_DSLMOD 1
++#define DEV_DSLMOD CTL_UNNUMBERED
+ #define MAX_STR_SIZE 256
+ #define DSL_MOD_SIZE 256
+
+@@ -299,7 +302,7 @@ static PITIDSLHW_T pIhw;
+ static volatile int bshutdown;
+ static char info[MAX_STR_SIZE];
+ /* Used for DSL Polling enable */
+-static DECLARE_MUTEX_LOCKED (adsl_sem_overlay);
++static struct semaphore adsl_sem_overlay;
+
+ //kthread_t overlay_thread;
+ /* end of module wide declars */
+@@ -323,6 +326,14 @@ static int tn7dsl_proc_snr_print (char *
+ #define gDot1(a) ((a>0)?(a%10):((-a)%10))
+ // UR8_MERGE_END CQ11054*
+
++int avalanche_request_intr_pacing(int irq_nr, unsigned int blk_num,
++ unsigned int pace_value)
++{
++ printk("avalanche_request_pacing(%d, %u, %u); // not implemented\n", irq_nr, blk_num, pace_value);
++ return 0;
++}
++
++
+ int os_atoi(const char *pStr)
+ {
+ int MulNeg = (*pStr == '-' ? -1 : 1);
+@@ -359,39 +370,6 @@ void dprintf (int uDbgLevel, char *szFmt
+ #endif
+ }
+
+-int strcmp(const char *s1, const char *s2)
+-{
+-
+- int size = strlen(s1);
+-
+- return(strncmp(s1, s2, size));
+-}
+-
+-int strncmp(const char *s1, const char *s2, size_t size)
+-{
+- int i = 0;
+- int max_size = (int)size;
+-
+- while((s1[i] != 0) && i < max_size)
+- {
+- if(s2[i] == 0)
+- {
+- return -1;
+- }
+- if(s1[i] != s2[i])
+- {
+- return 1;
+- }
+- i++;
+- }
+- if(s2[i] != 0)
+- {
+- return 1;
+- }
+-
+- return 0;
+-}
+-
+ // * UR8_MERGE_START CQ10640 Jack Zhang
+ int tn7dsl_dump_dsp_memory(char *input_str) //cph99
+ {
+@@ -441,101 +419,74 @@ unsigned int shim_osGetCpuFrequency(void
+ return CpuFrequency;
+ }
+
+-int shim_osLoadFWImage(unsigned char *ptr)
++static void avsar_release(struct device *dev)
+ {
+- unsigned int bytesRead;
+- mm_segment_t oldfs;
+- static struct file *filp;
+- unsigned int imageLength=0x5ffff;
+-
+-
+- dgprintf(4, "tn7dsl_read_dsp()\n");
+-
+- dgprintf(4,"open file %s\n", DSP_FIRMWARE_PATH);
+-
+- filp=filp_open(DSP_FIRMWARE_PATH,00,O_RDONLY);
+- if(filp ==NULL)
+- {
+- printk("Failed: Could not open DSP binary file\n");
+- return -1;
+- }
+-
+- if (filp->f_dentry != NULL)
+- {
+- if (filp->f_dentry->d_inode != NULL)
+- {
+- printk ("DSP binary filesize = %d bytes\n",
+- (int) filp->f_dentry->d_inode->i_size);
+- imageLength = (unsigned int)filp->f_dentry->d_inode->i_size + 0x200;
+- }
+- }
+-
+- if (filp->f_op->read==NULL)
+- return -1; /* File(system) doesn't allow reads */
+-
+- /*
+- * Disable parameter checking
+- */
+- oldfs = get_fs();
+- set_fs(KERNEL_DS);
+-
+- /*
+- * Now read bytes from postion "StartPos"
+- */
+- filp->f_pos = 0;
+-
+- bytesRead = filp->f_op->read(filp,ptr,imageLength,&filp->f_pos);
+-
+- dgprintf(4,"file length = %d\n", bytesRead);
+-
+- set_fs(oldfs);
+-
+- /*
+- * Close the file
+- */
+- fput(filp);
+-
+- return bytesRead;
++ printk(KERN_DEBUG "avsar firmware released\n");
+ }
+
++static struct device avsar = {
++ .bus_id = "vlynq",
++ .release = avsar_release,
++};
+
+-unsigned int shim_read_overlay_page (void *ptr, unsigned int secOffset,
+- unsigned int secLength)
++int shim_osLoadFWImage(unsigned char *ptr)
+ {
+- unsigned int bytesRead;
+- mm_segment_t oldfs;
+- struct file *filp;
+-
+- dgprintf(4,"shim_read_overlay_page\n");
+- //dgprintf(4,"sec offset=%d, sec length =%d\n", secOffset, secLength);
++ const struct firmware *fw_entry;
++ size_t size;
+
+- filp=filp_open(DSP_FIRMWARE_PATH,00,O_RDONLY);
+- if(filp ==NULL)
+- {
+- printk("Failed: Could not open DSP binary file\n");
+- return -1;
+- }
+-
+- if (filp->f_op->read==NULL)
+- return -1; /* File(system) doesn't allow reads */
+-
+- /*
+- * Now read bytes from postion "StartPos"
+- */
+-
+- if(filp->f_op->llseek)
+- filp->f_op->llseek(filp,secOffset, 0);
+- oldfs = get_fs();
+- set_fs(KERNEL_DS);
+- filp->f_pos = secOffset;
+- bytesRead = filp->f_op->read(filp,ptr,secLength,&filp->f_pos);
+-
+- set_fs(oldfs);
+- /*
+- * Close the file
+- */
+- fput(filp);
+- return bytesRead;
++ printk("requesting firmware image \"ar0700xx.bin\"\n");
++ if(device_register(&avsar) < 0) {
++ printk(KERN_ERR
++ "avsar: device_register fails\n");
++ return -1;
++ }
++
++ if(request_firmware(&fw_entry, "ar0700xx.bin", &avsar)) {
++ printk(KERN_ERR
++ "avsar: Firmware not available\n");
++ device_unregister(&avsar);
++ return -1;
++ }
++ size = fw_entry->size;
++ device_unregister(&avsar);
++ if(size > 0x5ffff) {
++ printk(KERN_ERR
++ "avsar: Firmware too big (%d bytes)\n", size);
++ release_firmware(fw_entry);
++ return -1;
++ }
++ memcpy(ptr, fw_entry->data, size);
++ release_firmware(fw_entry);
++ return size;
++}
++
++unsigned int shim_read_overlay_page(void *ptr, unsigned int secOffset, unsigned int secLength)
++{
++ const struct firmware *fw_entry;
++
++ printk("requesting firmware image \"ar0700xx.bin\"\n");
++ if(device_register(&avsar) < 0) {
++ printk(KERN_ERR
++ "avsar: device_register fails\n");
++ return -1;
++ }
++
++ if(request_firmware(&fw_entry, "ar0700xx.bin", &avsar)) {
++ printk(KERN_ERR
++ "avsar: Firmware not available\n");
++ device_unregister(&avsar);
++ return -1;
++ }
++ device_unregister(&avsar);
++ if(fw_entry->size > secLength) {
++ printk(KERN_ERR
++ "avsar: Firmware too big (%d bytes)\n", fw_entry->size);
++ release_firmware(fw_entry);
++ return -1;
++ }
++ memcpy(ptr + secOffset, fw_entry->data, secLength);
++ release_firmware(fw_entry);
++ return secLength;
+ }
+
+ int shim_osLoadDebugFWImage(unsigned char *ptr)
+@@ -3064,6 +3015,7 @@ int tn7dsl_init(void *priv)
+ int high_precision_selected = 0;
+ // UR8_MERGE_END CQ11054*
+
++ sema_init(&adsl_sem_overlay, 0);
+ /*
+ * start dsl
+ */
+@@ -3442,7 +3394,7 @@ static int dslmod_sysctl(ctl_table *ctl,
+ */
+ if(write)
+ {
+- ret = proc_dostring(ctl, write, filp, buffer, lenp);
++ ret = proc_dostring(ctl, write, filp, buffer, lenp, 0);
+
+ switch (ctl->ctl_name)
+ {
+@@ -3528,14 +3480,14 @@ static int dslmod_sysctl(ctl_table *ctl,
+ else
+ {
+ len += sprintf(info+len, mod_req);
+- ret = proc_dostring(ctl, write, filp, buffer, lenp);
++ ret = proc_dostring(ctl, write, filp, buffer, lenp, 0);
+ }
+ return ret;
+ }
+
+
+ ctl_table dslmod_table[] = {
+- {DEV_DSLMOD, "dslmod", info, DSL_MOD_SIZE, 0644, NULL, &dslmod_sysctl}
++ {DEV_DSLMOD, "dslmod", info, DSL_MOD_SIZE, 0644, NULL, NULL, &dslmod_sysctl, &sysctl_string}
+ ,
+ {0}
+ };
+@@ -3558,8 +3510,7 @@ void tn7dsl_dslmod_sysctl_register(void)
+ if (initialized == 1)
+ return;
+
+- dslmod_sysctl_header = register_sysctl_table(dslmod_root_table, 1);
+- dslmod_root_table->child->de->owner = THIS_MODULE;
++ dslmod_sysctl_header = register_sysctl_table(dslmod_root_table);
+
+ /*
+ * set the defaults
+@@ -4821,4 +4772,4 @@ int tn7dsl_proc_PMDus(char* buf, char **
+ }
+ #endif //NO_ADV_STATS
+ #endif //TR69_PMD_IN
+-// * UR8_MERGE_END CQ11057 *
+\ No newline at end of file
++// * UR8_MERGE_END CQ11057 *
+--- a/tn7sar.c
++++ b/tn7sar.c
+@@ -42,7 +42,6 @@
+ * UR8_MERGE_END CQ10700
+ *******************************************************************************/
+
+-#include <linux/config.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -50,12 +49,13 @@
+ #include <linux/delay.h>
+ #include <linux/spinlock.h>
+ #include <linux/smp_lock.h>
+-#include <asm/io.h>
+-#include <asm/mips-boards/prom.h>
+ #include <linux/proc_fs.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
+
++#include <asm/io.h>
++#include <asm/ar7/ar7.h>
++#include <asm/ar7/prom.h>
+
+ #define _CPHAL_AAL5
+ #define _CPHAL_SAR
diff --git a/package/ar7-atm/patches-D7.04.03.00/110-interrupt_fix.patch b/package/ar7-atm/patches-D7.04.03.00/110-interrupt_fix.patch
new file mode 100644
index 000000000..9acb862e5
--- /dev/null
+++ b/package/ar7-atm/patches-D7.04.03.00/110-interrupt_fix.patch
@@ -0,0 +1,37 @@
+--- a/tn7atm.c
++++ b/tn7atm.c
+@@ -566,7 +566,7 @@ static int turbodsl_check_priority_type(
+ * Description: tnetd73xx SAR interrupt.
+ *
+ *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+-static void tn7atm_sar_irq (int irq, void *voiddev, struct pt_regs *regs)
++static irqreturn_t tn7atm_sar_irq (int irq, void *voiddev)
+ {
+ struct atm_dev *atmdev;
+ Tn7AtmPrivate *priv;
+@@ -593,6 +593,7 @@ static void tn7atm_sar_irq (int irq, voi
+ #ifdef TIATM_INST_SUPP
+ psp_trace_par (ATM_DRV_SAR_ISR_EXIT, retval);
+ #endif
++ return IRQ_HANDLED;
+ }
+
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+@@ -602,7 +603,7 @@ static void tn7atm_sar_irq (int irq, voi
+ * Description: tnetd73xx DSL interrupt.
+ *
+ *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+-static void tn7atm_dsl_irq (int irq, void *voiddev, struct pt_regs *regs)
++static irqreturn_t tn7atm_dsl_irq (int irq, void *voiddev)
+ {
+ struct atm_dev *atmdev;
+ Tn7AtmPrivate *priv;
+@@ -624,6 +625,8 @@ static void tn7atm_dsl_irq (int irq, voi
+ #ifdef TIATM_INST_SUPP
+ psp_trace_par (ATM_DRV_DSL_ISR_EXIT, retval);
+ #endif
++
++ return IRQ_HANDLED;
+ }
+
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/package/ar7-atm/patches-D7.04.03.00/120-no_dumb_inline.patch b/package/ar7-atm/patches-D7.04.03.00/120-no_dumb_inline.patch
new file mode 100644
index 000000000..2968fdc16
--- /dev/null
+++ b/package/ar7-atm/patches-D7.04.03.00/120-no_dumb_inline.patch
@@ -0,0 +1,11 @@
+--- a/tn7api.h
++++ b/tn7api.h
+@@ -107,7 +107,7 @@ int tn7dsl_proc_dbg_rmsgs4(char* buf, ch
+
+ int tn7dsl_proc_write_stats(struct file *fp, const char * buf, unsigned long count, void * data);
+ int tn7dsl_proc_modem(char* buf, char **start, off_t offset, int count,int *eof, void *data);
+-inline int tn7dsl_handle_interrupt(void);
++int tn7dsl_handle_interrupt(void);
+
+ void tn7dsl_dslmod_sysctl_register(void);
+ void tn7dsl_dslmod_sysctl_unregister(void);
diff --git a/package/ar7-atm/patches-D7.04.03.00/130-powercutback.patch b/package/ar7-atm/patches-D7.04.03.00/130-powercutback.patch
new file mode 100644
index 000000000..ec00df97a
--- /dev/null
+++ b/package/ar7-atm/patches-D7.04.03.00/130-powercutback.patch
@@ -0,0 +1,44 @@
+--- a/dsl_hal_advcfg.c
++++ b/dsl_hal_advcfg.c
+@@ -36,9 +36,9 @@
+ * 05Jul05 0.00.09 CPH CQ9775: Change dslhal_advcfg_configDsTones input parameters & support for ADSL2+
+ * 24Jul05 0.00.10 CPH Fixed comments in dslhal_advcfg_configDsTones function header
+ *******************************************************************************/
+-#include <dev_host_interface.h>
+-#include <dsl_hal_register.h>
+-#include <dsl_hal_support.h>
++#include "dev_host_interface.h"
++#include "dsl_hal_register.h"
++#include "dsl_hal_support.h"
+
+ /*****************************************************************************/
+ /* ACT API functions -- To be moved into their own independent module --RamP */
+--- a/Makefile
++++ b/Makefile
+@@ -4,6 +4,7 @@
+
+ CONFIG_SANGAM_ATM=m
+ #EXTRA_CFLAGS += -DEL -I. -DPOST_SILICON -DCOMMON_NSP -DCONFIG_LED_MODULE -DDEREGISTER_LED -DNO_ACT
+-EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -DNO_ACT -D__NO__VOICE_PATCH__ -DEL
++#EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -DNO_ACT -D__NO__VOICE_PATCH__ -DEL
++EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -D__NO__VOICE_PATCH__ -DEL
+ obj-$(CONFIG_SANGAM_ATM) := tiatm.o
+-tiatm-objs += cpsar.o aal5sar.o tn7sar.o tn7atm.o tn7dsl.o dsl_hal_api.o dsl_hal_support.o
++tiatm-objs += cpsar.o aal5sar.o tn7sar.o tn7atm.o tn7dsl.o dsl_hal_api.o dsl_hal_support.o dsl_hal_advcfg.o
+--- a/tn7dsl.c
++++ b/tn7dsl.c
+@@ -2869,6 +2869,14 @@ static int tn7dsl_set_dsl(void)
+ dslhal_api_setRateAdaptFlag(pIhw, os_atoi(ptr));
+ }
+
++ // set powercutback
++ ptr = NULL;
++ ptr = prom_getenv("powercutback");
++ if(ptr)
++ {
++ dslhal_advcfg_onOffPcb(pIhw, os_atoi(ptr));
++ }
++
+ // trellis
+ ptr = NULL;
+ ptr = prom_getenv("trellis");
diff --git a/package/ar7-atm/patches-D7.04.03.00/140-debug_mode.patch b/package/ar7-atm/patches-D7.04.03.00/140-debug_mode.patch
new file mode 100644
index 000000000..ce3697b10
--- /dev/null
+++ b/package/ar7-atm/patches-D7.04.03.00/140-debug_mode.patch
@@ -0,0 +1,16 @@
+--- a/tn7sar.c
++++ b/tn7sar.c
+@@ -103,10 +103,10 @@ enum
+
+ #define RESERVED_OAM_CHANNEL 15
+
+-#define AAL5_PARM "id=aal5, base = 0x03000000, offset = 0, int_line=15, ch0=[RxBufSize=1522; RxNumBuffers = 32; RxServiceMax = 50; TxServiceMax=50; TxNumBuffers=32; CpcsUU=0x5aa5; TxVc_CellRate=0x3000; TxVc_AtmHeader=0x00000640]"
+-#define SAR_PARM "id=sar,base = 0x03000000, reset_bit = 9, offset = 0; UniNni = 0, PdspEnable = 1"
++#define CH0_PARM "RxBufSize=1522, RxNumBuffers=32, RxServiceMax=50, TxServiceMax=50, TxNumBuffers=32, CpcsUU=0x5aa5, TxVc_CellRate=0x3000, TxVc_AtmHeader=0x00000640"
++#define AAL5_PARM "id=aal5, base=0x03000000, offset=0, int_line=15, ch0=[" CH0_PARM "]"
++#define SAR_PARM "id=sar, base=0x03000000, reset_bit=9, offset=0; UniNni=0, PdspEnable=1, Debug=0xFFFFFFFF"
+ #define RESET_PARM "id=ResetControl, base=0xA8611600"
+-#define CH0_PARM "RxBufSize=1522, RxNumBuffers = 32, RxServiceMax = 50, TxServiceMax=50, TxNumBuffers=32, CpcsUU=0x5aa5, TxVc_CellRate=0x3000, TxVc_AtmHeader=0x00000640"
+
+ #define MAX_PVC_TABLE_ENTRY 16
+
diff --git a/package/ar7-atm/patches-D7.04.03.00/150-tasklet_mode.patch b/package/ar7-atm/patches-D7.04.03.00/150-tasklet_mode.patch
new file mode 100644
index 000000000..97b8cecdd
--- /dev/null
+++ b/package/ar7-atm/patches-D7.04.03.00/150-tasklet_mode.patch
@@ -0,0 +1,11 @@
+--- a/Makefile
++++ b/Makefile
+@@ -5,6 +5,7 @@
+ CONFIG_SANGAM_ATM=m
+ #EXTRA_CFLAGS += -DEL -I. -DPOST_SILICON -DCOMMON_NSP -DCONFIG_LED_MODULE -DDEREGISTER_LED -DNO_ACT
+ #EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -DNO_ACT -D__NO__VOICE_PATCH__ -DEL
+-EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -D__NO__VOICE_PATCH__ -DEL
++#EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -D__NO__VOICE_PATCH__ -DEL
++EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -D__NO__VOICE_PATCH__ -DEL -DCPATM_TASKLET_MODE
+ obj-$(CONFIG_SANGAM_ATM) := tiatm.o
+ tiatm-objs += cpsar.o aal5sar.o tn7sar.o tn7atm.o tn7dsl.o dsl_hal_api.o dsl_hal_support.o dsl_hal_advcfg.o
diff --git a/package/ar7-atm/patches-D7.04.03.00/160-module-params.patch b/package/ar7-atm/patches-D7.04.03.00/160-module-params.patch
new file mode 100644
index 000000000..5b3dcbfe3
--- /dev/null
+++ b/package/ar7-atm/patches-D7.04.03.00/160-module-params.patch
@@ -0,0 +1,577 @@
+--- a/tn7atm.c
++++ b/tn7atm.c
+@@ -87,6 +87,146 @@
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION ("Tnetd73xx ATM Device Driver");
+ MODULE_AUTHOR ("Zhicheng Tang");
++
++int mp_sar_ipacemax = -1;
++module_param_named(ipacemax, mp_sar_ipacemax, int, 0);
++MODULE_PARM_DESC(ipacemax, "Interrupt pacing");
++
++char *mp_macc = NULL;
++module_param_named(macc, mp_macc, charp, 0);
++MODULE_PARM_DESC(macc, "MAC address");
++
++int mp_dsp_noboost = -1;
++module_param_named(dsp_noboost, mp_dsp_noboost, int, 0);
++MODULE_PARM_DESC(dsp_noboost, "Suppress DSP frequency boost");
++
++int mp_dsp_freq = -1;
++module_param_named(dsp_freq, mp_dsp_freq, int, 0);
++MODULE_PARM_DESC(dsp_freq, "Frequency to boost the DSP to");
++
++char *mp_featctl0 = NULL;
++module_param_named(featctl0, mp_featctl0, charp, 0);
++MODULE_PARM_DESC(featctl0, "DSL feature control 0");
++
++char *mp_featctl1 = NULL;
++module_param_named(featctl1, mp_featctl1, charp, 0);
++MODULE_PARM_DESC(featctl1, "DSL feature control 1");
++
++char *mp_phyctl0 = NULL;
++module_param_named(phyctl0, mp_phyctl0, charp, 0);
++MODULE_PARM_DESC(phyctl0, "DSL PHY control 0");
++
++char *mp_phyctl1 = NULL;
++module_param_named(phyctl1, mp_phyctl1, charp, 0);
++MODULE_PARM_DESC(phyctl1, "DSL PHY control 1");
++
++int mp_turbodsl = -1;
++module_param_named(turbodsl, mp_turbodsl, int, 0);
++MODULE_PARM_DESC(turbodsl, "Enable TurboDSL");
++
++int mp_sar_rxbuf = -1;
++module_param_named(sar_rxbuf, mp_sar_rxbuf, int, 0);
++MODULE_PARM_DESC(sar_rxbuf, "SAR RxBuf size");
++
++int mp_sar_rxmax = -1;
++module_param_named(sar_rxmax, mp_sar_rxmax, int, 0);
++MODULE_PARM_DESC(sar_rxmax, "SAR RxMax size");
++
++int mp_sar_txbuf = -1;
++module_param_named(sar_txbuf, mp_sar_txbuf, int, 0);
++MODULE_PARM_DESC(sar_txbuf, "SAR TxBuf size");
++
++int mp_sar_txmax = -1;
++module_param_named(sar_txmax, mp_sar_txmax, int, 0);
++MODULE_PARM_DESC(sar_txmax, "SAR TxMax size");
++
++char *mp_modulation = NULL;
++module_param_named(modulation, mp_modulation, charp, 0);
++MODULE_PARM_DESC(modulation, "Modulation");
++
++int mp_fine_gain_control = -1;
++module_param_named(fine_gain_control, mp_fine_gain_control, int, 0);
++MODULE_PARM_DESC(fine_gain_control, "Fine gain control");
++
++int mp_fine_gain_value = -1;
++module_param_named(fine_gain_value, mp_fine_gain_value, int, 0);
++MODULE_PARM_DESC(fine_gain_value, "Fine gain value");
++
++int mp_enable_margin_retrain = -1;
++module_param_named(enable_margin_retrain, mp_enable_margin_retrain, int, 0);
++MODULE_PARM_DESC(enable_margin_retrain, "Enable margin retrain");
++
++int mp_margin_threshold = -1;
++module_param_named(margin_threshold, mp_margin_threshold, int, 0);
++MODULE_PARM_DESC(margin_threshold, "Margin retrain treshold");
++
++int mp_enable_rate_adapt = -1;
++module_param_named(enable_rate_adapt, mp_enable_rate_adapt, int, 0);
++MODULE_PARM_DESC(enable_rate_adapt, "Enable rate adaption");
++
++int mp_powercutback = -1;
++module_param_named(powercutback, mp_powercutback, int, 0);
++MODULE_PARM_DESC(powercutback, "Enable / disable powercutback");
++
++int mp_trellis = -1;
++module_param_named(trellis, mp_trellis, int, 0);
++MODULE_PARM_DESC(trellis, "Enable / disable trellis coding");
++
++int mp_bitswap = -1;
++module_param_named(bitswap, mp_bitswap, int, 0);
++MODULE_PARM_DESC(bitswap, "Enable / disable bitswap");
++
++int mp_maximum_bits_per_carrier = -1;
++module_param_named(maximum_bits_per_carrier, mp_maximum_bits_per_carrier, int, 0);
++MODULE_PARM_DESC(maximum_bits_per_carrier, "Maximum bits per carrier");
++
++int mp_maximum_interleave_depth = -1;
++module_param_named(maximum_interleave_depth, mp_maximum_interleave_depth, int, 0);
++MODULE_PARM_DESC(maximum_interleave_depth, "Maximum interleave depth");
++
++int mp_pair_selection = -1;
++module_param_named(pair_selection, mp_pair_selection, int, 0);
++MODULE_PARM_DESC(pair_selection, "Pair selection");
++
++int mp_dgas_polarity = -1;
++module_param_named(dgas_polarity, mp_dgas_polarity, int, 0);
++MODULE_PARM_DESC(dgas_polarity, "DGAS polarity");
++
++int mp_los_alarm = -1;
++module_param_named(los_alarm, mp_los_alarm, int, 0);
++MODULE_PARM_DESC(los_alarm, "LOS alarm");
++
++char *mp_eoc_vendor_id = NULL;
++module_param_named(eoc_vendor_id, mp_eoc_vendor_id, charp, 0);
++MODULE_PARM_DESC(eoc_vendor_id, "EOC vendor id");
++
++int mp_eoc_vendor_revision = -1;
++module_param_named(eoc_vendor_revision, mp_eoc_vendor_revision, int, 0);
++MODULE_PARM_DESC(eoc_vendor_revision, "EOC vendor revision");
++
++char *mp_eoc_vendor_serialnum = NULL;
++module_param_named(eoc_vendor_serialnum, mp_eoc_vendor_serialnum, charp, 0);
++MODULE_PARM_DESC(eoc_vendor_serialnum, "EOC vendor serial number");
++
++char *mp_invntry_vernum = NULL;
++module_param_named(invntry_vernum, mp_invntry_vernum, charp, 0);
++MODULE_PARM_DESC(invntry_vernum, "Inventory revision number");
++
++int mp_dsl_bit_tmode = -1;
++module_param_named(dsl_bit_tmode, mp_dsl_bit_tmode, int, 0);
++MODULE_PARM_DESC(dsl_bit_tmode, "DSL bit training mode");
++
++int mp_high_precision = -1;
++module_param_named(high_precision, mp_high_precision, int, 0);
++MODULE_PARM_DESC(high_precision, "High precision");
++
++int mp_autopvc_enable = -1;
++module_param_named(autopvc_enable, mp_autopvc_enable, int, 0);
++MODULE_PARM_DESC(autopvc_enable, "Enable / disable automatic PVC");
++
++int mp_oam_lb_timeout = -1;
++module_param_named(oam_lb_timeout, mp_oam_lb_timeout, int, 0);
++MODULE_PARM_DESC(oam_lb_timeout, "OAM LB timeout");
+ #endif
+
+ #ifndef TRUE
+@@ -655,9 +795,9 @@ static int __init tn7atm_irq_request (st
+ * interrupt pacing
+ */
+ ptr = prom_getenv ("sar_ipacemax");
+- if (ptr)
++ if (ptr || mp_sar_ipacemax != -1)
+ {
+- def_sar_inter_pace = os_atoi (ptr);
++ def_sar_inter_pace = mp_sar_ipacemax == -1 ? os_atoi (ptr) : mp_sar_ipacemax;
+ }
+ /* avalanche_request_pacing (priv->sar_irq, ATM_SAR_INT_PACING_BLOCK_NUM,
+ def_sar_inter_pace);*/
+@@ -797,7 +937,7 @@ static int __init tn7atm_get_ESI (struct
+ char esi_addr[ESI_LEN] = { 0x00, 0x00, 0x11, 0x22, 0x33, 0x44 };
+ char *esiaddr_str = NULL;
+
+- esiaddr_str = prom_getenv ("maca");
++ esiaddr_str = mp_macc ? mp_macc : prom_getenv ("maca");
+
+ if (!esiaddr_str)
+ {
+@@ -1930,15 +2070,15 @@ static int tn7atm_autoDetectDspBoost (vo
+ //UR8_MERGE_END CQ10450*
+
+ cp = prom_getenv ("dsp_noboost");
+- if (cp)
++ if (cp || mp_dsp_noboost != -1)
+ {
+- dsp_noboost = os_atoi (cp);
++ dsp_noboost = mp_dsp_noboost == -1 ? os_atoi (cp) : mp_dsp_noboost;
+ }
+
+ cp = (char *) prom_getenv ("dsp_freq");
+- if (cp)
++ if (cp || mp_dsp_freq != -1)
+ {
+- dspfreq = os_atoi (cp);
++ dspfreq = mp_dsp_freq == -1 ? os_atoi (cp) : mp_dsp_freq;
+ if (dspfreq == 250)
+ {
+ boostDsp = 1;
+@@ -2187,8 +2327,9 @@ static int __init tn7atm_init (struct at
+ // Inter-Op DSL phy Control
+ // Note the setting of _dsl_Feature_0 and _dsl_Feature_1 must before
+ // dslhal_api_dslStartup (in tn7dsl_init()).
+- if ((ptr = prom_getenv ("DSL_FEATURE_CNTL_0")) != NULL)
++ if ((ptr = prom_getenv ("DSL_FEATURE_CNTL_0")) != NULL || mp_featctl0 != NULL)
+ {
++ if (mp_featctl0 != NULL) ptr = mp_featctl0;
+ if ((ptr[0] == '0') && (ptr[1] == 'x')) // skip 0x before pass to
+ // os_atoh
+ ptr += 2;
+@@ -2196,8 +2337,9 @@ static int __init tn7atm_init (struct at
+ _dsl_Feature_0_defined = 1;
+ }
+
+- if ((ptr = prom_getenv ("DSL_FEATURE_CNTL_1")) != NULL)
++ if ((ptr = prom_getenv ("DSL_FEATURE_CNTL_1")) != NULL || mp_featctl1 != NULL)
+ {
++ if (mp_featctl1 != NULL) ptr = mp_featctl1;
+ if ((ptr[0] == '0') && (ptr[1] == 'x')) // skip 0x before pass to
+ // os_atoh
+ ptr += 2;
+@@ -2209,8 +2351,9 @@ static int __init tn7atm_init (struct at
+ // DSL phy Feature Control
+ // Note the setting of _dsl_PhyControl_0 and _dsl_PhyControl_1 must before
+ // dslhal_api_dslStartup (in tn7dsl_init()).
+- if ((ptr = prom_getenv ("DSL_PHY_CNTL_0")) != NULL)
++ if ((ptr = prom_getenv ("DSL_PHY_CNTL_0")) != NULL || mp_phyctl0 != NULL)
+ {
++ if (mp_phyctl0 != NULL) ptr = mp_phyctl0;
+ if ((ptr[0] == '0') && (ptr[1] == 'x')) // skip 0x before pass to
+ // os_atoh
+ ptr += 2;
+@@ -2218,8 +2361,9 @@ static int __init tn7atm_init (struct at
+ _dsl_PhyControl_0_defined = 1;
+ }
+
+- if ((ptr = prom_getenv ("DSL_PHY_CNTL_1")) != NULL)
++ if ((ptr = prom_getenv ("DSL_PHY_CNTL_1")) != NULL || mp_phyctl1 != NULL)
+ {
++ if (mp_phyctl1 != NULL) ptr = mp_phyctl1;
+ if ((ptr[0] == '0') && (ptr[1] == 'x')) // skip 0x before pass to
+ // os_atoh
+ ptr += 2;
+@@ -2247,9 +2391,9 @@ static int __init tn7atm_init (struct at
+ priv->bTurboDsl = 1;
+ // read config for turbo dsl
+ ptr = prom_getenv ("TurboDSL");
+- if (ptr)
++ if (ptr || mp_turbodsl != -1)
+ {
+- priv->bTurboDsl = os_atoi (ptr);
++ priv->bTurboDsl = mp_turbodsl == -1 ? os_atoi (ptr) : mp_turbodsl;
+ }
+
+ // @Added to make Rx buffer number & Service max configurable through
+@@ -2257,30 +2401,30 @@ static int __init tn7atm_init (struct at
+ priv->sarRxBuf = RX_BUFFER_NUM;
+ ptr = NULL;
+ ptr = prom_getenv ("SarRxBuf");
+- if (ptr)
++ if (ptr || mp_sar_rxbuf != -1)
+ {
+- priv->sarRxBuf = os_atoi (ptr);
++ priv->sarRxBuf = mp_sar_rxbuf == -1 ? os_atoi (ptr) : mp_sar_rxbuf;
+ }
+ priv->sarRxMax = RX_SERVICE_MAX;
+ ptr = NULL;
+ ptr = prom_getenv ("SarRxMax");
+- if (ptr)
++ if (ptr || mp_sar_rxmax != -1)
+ {
+- priv->sarRxMax = os_atoi (ptr);
++ priv->sarRxMax = mp_sar_rxmax == -1 ? os_atoi (ptr) : mp_sar_rxmax;
+ }
+ priv->sarTxBuf = TX_BUFFER_NUM;
+ ptr = NULL;
+ ptr = prom_getenv ("SarTxBuf");
+- if (ptr)
++ if (ptr || mp_sar_txbuf != -1)
+ {
+- priv->sarTxBuf = os_atoi (ptr);
++ priv->sarTxBuf = mp_sar_txbuf == -1 ? os_atoi (ptr) : mp_sar_txbuf;
+ }
+ priv->sarTxMax = TX_SERVICE_MAX;
+ ptr = NULL;
+ ptr = prom_getenv ("SarTxMax");
+- if (ptr)
++ if (ptr || mp_sar_txmax != -1)
+ {
+- priv->sarTxMax = os_atoi (ptr);
++ priv->sarTxMax = mp_sar_txmax == -1 ? os_atoi (ptr) : mp_sar_txmax;
+ }
+
+ return 0;
+--- a/tn7dsl.c
++++ b/tn7dsl.c
+@@ -136,6 +136,27 @@
+ #define NEW_TRAINING_VAL_T1413 128
+ #define NEW_TRAINING_VAL_MMODE 255
+
++extern char *mp_modulation;
++extern int mp_fine_gain_control;
++extern int mp_fine_gain_value;
++extern int mp_enable_margin_retrain;
++extern int mp_margin_threshold;
++extern int mp_enable_rate_adapt;
++extern int mp_powercutback;
++extern int mp_trellis;
++extern int mp_bitswap;
++extern int mp_maximum_bits_per_carrier;
++extern int mp_maximum_interleave_depth;
++extern int mp_pair_selection;
++extern int mp_dgas_polarity;
++extern int mp_los_alarm;
++extern char *mp_eoc_vendor_id;
++extern int mp_eoc_vendor_revision;
++extern char *mp_eoc_vendor_serialnum;
++extern char *mp_invntry_vernum;
++extern int mp_dsl_bit_tmode;
++extern int mp_high_precision;
++
+ int testflag1 = 0;
+ extern int __guDbgLevel;
+ extern sar_stat_t sarStat;
+@@ -2818,84 +2839,80 @@ static int tn7dsl_set_dsl(void)
+
+ // modulation
+ ptr = prom_getenv("modulation");
+- if (ptr)
++ if (ptr || mp_modulation != NULL)
+ {
+- tn7dsl_set_modulation(ptr, FALSE);
++ tn7dsl_set_modulation(mp_modulation == NULL ? ptr : mp_modulation, FALSE);
+ }
+
+ // Fine Gains
+ ptr = prom_getenv("fine_gain_control");
+- if (ptr)
++ if (ptr || mp_fine_gain_control != -1)
+ {
+- value = os_atoi(ptr);
++ value = mp_fine_gain_control == -1 ? os_atoi(ptr) : mp_fine_gain_control;
+ tn7dsl_ctrl_fineGain(value);
+ }
+ ptr = NULL;
+ ptr = prom_getenv("fine_gain_value");
+- if(ptr)
+- tn7dsl_set_fineGainValue(os_atoh(ptr));
++ if(ptr || mp_fine_gain_value != -1)
++ tn7dsl_set_fineGainValue(mp_fine_gain_value == -1 ? os_atoh(ptr) : mp_fine_gain_value);
+
+ // margin retrain
+ ptr = NULL;
+ ptr = prom_getenv("enable_margin_retrain");
+- if(ptr)
++ value = mp_enable_margin_retrain == -1 ? (ptr ? os_atoi(ptr) : 0) : mp_enable_margin_retrain;
++
++ if (value == 1)
+ {
+- value = os_atoi(ptr);
+- if(value == 1)
++ dslhal_api_setMarginMonitorFlags(pIhw, 0, 1);
++ bMarginRetrainEnable = 1;
++ //printk("enable showtime margin monitor.\n");
++
++ ptr = NULL;
++ ptr = prom_getenv("margin_threshold");
++ value = mp_margin_threshold == -1 ? (ptr ? os_atoi(ptr) : 0) : mp_margin_threshold;
++
++ if(value >= 0)
+ {
+- dslhal_api_setMarginMonitorFlags(pIhw, 0, 1);
+- bMarginRetrainEnable = 1;
+- //printk("enable showtime margin monitor.\n");
+- ptr = NULL;
+- ptr = prom_getenv("margin_threshold");
+- if(ptr)
+- {
+- value = os_atoi(ptr);
+- //printk("Set margin threshold to %d x 0.5 db\n",value);
+- if(value >= 0)
+- {
+- dslhal_api_setMarginThreshold(pIhw, value);
+- bMarginThConfig=1;
+- }
+- }
++ dslhal_api_setMarginThreshold(pIhw, value);
++ bMarginThConfig=1;
+ }
+ }
+
+ // rate adapt
+ ptr = NULL;
+ ptr = prom_getenv("enable_rate_adapt");
+- if(ptr)
++ if(ptr || mp_enable_rate_adapt != -1)
+ {
+- dslhal_api_setRateAdaptFlag(pIhw, os_atoi(ptr));
++ dslhal_api_setRateAdaptFlag(pIhw, mp_enable_rate_adapt == -1 ? os_atoi(ptr) : mp_enable_rate_adapt);
+ }
+
+ // set powercutback
+ ptr = NULL;
+ ptr = prom_getenv("powercutback");
+- if(ptr)
++ if(ptr || mp_powercutback != -1)
+ {
+- dslhal_advcfg_onOffPcb(pIhw, os_atoi(ptr));
++ dslhal_advcfg_onOffPcb(pIhw, mp_powercutback == -1 ? os_atoi(ptr) : mp_powercutback);
+ }
+
+ // trellis
+ ptr = NULL;
+ ptr = prom_getenv("trellis");
+- if(ptr)
++ if(ptr || mp_trellis != -1)
+ {
+- dslhal_api_setTrellisFlag(pIhw, os_atoi(ptr));
+- trellis = os_atoi(ptr);
++ trellis = mp_trellis == -1 ? os_atoi(ptr) : mp_trellis;
++ dslhal_api_setTrellisFlag(pIhw, trellis);
+ //printk("trellis=%d\n");
+ }
+
+ // bitswap
+ ptr = NULL;
+ ptr = prom_getenv("bitswap");
+- if(ptr)
++ if(ptr || mp_bitswap != -1)
+ {
+ int offset[2] = {33, 0};
+ unsigned int bitswap;
+
+- bitswap = os_atoi(ptr);
++ bitswap = mp_bitswap == -1 ? os_atoi(ptr) : mp_bitswap;
+
+ tn7dsl_generic_read(2, offset);
+ dslReg &= dslhal_support_byteSwap32(0xFFFFFF00);
+@@ -2913,46 +2930,47 @@ static int tn7dsl_set_dsl(void)
+ // maximum bits per carrier
+ ptr = NULL;
+ ptr = prom_getenv("maximum_bits_per_carrier");
+- if(ptr)
++ if(ptr || mp_maximum_bits_per_carrier != -1)
+ {
+- dslhal_api_setMaxBitsPerCarrierUpstream(pIhw, os_atoi(ptr));
++ dslhal_api_setMaxBitsPerCarrierUpstream(pIhw, mp_maximum_bits_per_carrier == -1 ? os_atoi(ptr) : mp_maximum_bits_per_carrier);
+ }
+
+ // maximum interleave depth
+ ptr = NULL;
+ ptr = prom_getenv("maximum_interleave_depth");
+- if(ptr)
++ if(ptr || mp_maximum_interleave_depth != -1)
+ {
+- dslhal_api_setMaxInterleaverDepth(pIhw, os_atoi(ptr));
++ dslhal_api_setMaxInterleaverDepth(pIhw, mp_maximum_interleave_depth == -1 ? os_atoi(ptr) : mp_maximum_interleave_depth);
+ }
+
+ // inner and outer pairs
+ ptr = NULL;
+ ptr = prom_getenv("pair_selection");
+- if(ptr)
++ if(ptr || mp_pair_selection != -1)
+ {
+- dslhal_api_selectInnerOuterPair(pIhw, os_atoi(ptr));
++ dslhal_api_selectInnerOuterPair(pIhw, mp_pair_selection == -1 ? os_atoi(ptr) : mp_pair_selection);
+ }
+
+ ptr = NULL;
+ ptr = prom_getenv("dgas_polarity");
+- if(ptr)
++ if(ptr || mp_dgas_polarity != -1)
+ {
+ dslhal_api_configureDgaspLpr(pIhw, 1, 1);
+- dslhal_api_configureDgaspLpr(pIhw, 0, os_atoi(ptr));
++ dslhal_api_configureDgaspLpr(pIhw, 0, mp_dgas_polarity == -1 ? os_atoi(ptr) : mp_dgas_polarity);
+ }
+
+ ptr = NULL;
+ ptr = prom_getenv("los_alarm");
+- if(ptr)
++ if(ptr || mp_los_alarm != -1)
+ {
+- dslhal_api_disableLosAlarm(pIhw, os_atoi(ptr));
++ dslhal_api_disableLosAlarm(pIhw, mp_los_alarm == -1 ? os_atoi(ptr) : mp_los_alarm);
+ }
+
+ ptr = NULL;
+ ptr = prom_getenv("eoc_vendor_id");
+- if(ptr)
++ if(ptr || mp_eoc_vendor_id != NULL)
+ {
++ ptr = mp_eoc_vendor_id == NULL ? ptr : mp_eoc_vendor_id;
+ for(i=0;i<8;i++)
+ {
+ tmp[0]=ptr[i*2];
+@@ -2977,26 +2995,26 @@ static int tn7dsl_set_dsl(void)
+ }
+ ptr = NULL;
+ ptr = prom_getenv("eoc_vendor_revision");
+- if(ptr)
++ if(ptr || mp_eoc_vendor_revision != -1)
+ {
+- value = os_atoi(ptr);
++ value = mp_eoc_vendor_revision == -1 ? os_atoi(ptr) : mp_eoc_vendor_revision;
+ //printk("eoc rev=%d\n", os_atoi(ptr));
+ dslhal_api_setEocRevisionNumber(pIhw, (char *)&value);
+
+ }
+ ptr = NULL;
+ ptr = prom_getenv("eoc_vendor_serialnum");
+- if(ptr)
++ if(ptr || mp_eoc_vendor_serialnum != NULL)
+ {
+- dslhal_api_setEocSerialNumber(pIhw, ptr);
++ dslhal_api_setEocSerialNumber(pIhw, mp_eoc_vendor_serialnum == NULL ? ptr : mp_eoc_vendor_serialnum);
+ }
+
+ // CQ10037 Added invntry_vernum environment variable to be able to set version number in ADSL2, ADSL2+ modes.
+ ptr = NULL;
+ ptr = prom_getenv("invntry_vernum");
+- if(ptr)
++ if(ptr || mp_invntry_vernum != NULL)
+ {
+- dslhal_api_setEocRevisionNumber(pIhw, ptr);
++ dslhal_api_setEocRevisionNumber(pIhw, mp_invntry_vernum == NULL ? ptr : mp_invntry_vernum);
+ }
+
+ return 0;
+@@ -3041,7 +3059,7 @@ int tn7dsl_init(void *priv)
+ * backward compatibility.
+ */
+ cp = prom_getenv("DSL_BIT_TMODE");
+- if (cp)
++ if (cp || mp_dsl_bit_tmode != -1)
+ {
+ printk("%s : env var DSL_BIT_TMODE is set\n", __FUNCTION__);
+ /*
+@@ -3070,9 +3088,9 @@ int tn7dsl_init(void *priv)
+
+ // UR8_MERGE_START CQ11054 Jack Zhang
+ cp = prom_getenv("high_precision");
+- if (cp)
++ if (cp || mp_high_precision != -1)
+ {
+- high_precision_selected = os_atoi(cp);
++ high_precision_selected = mp_high_precision == -1 ? os_atoi(cp) : mp_high_precision;
+ }
+ if ( high_precision_selected)
+ {
+--- a/tn7sar.c
++++ b/tn7sar.c
+@@ -74,6 +74,8 @@ typedef void OS_SETUP;
+ /* PDSP Firmware files */
+ #include "tnetd7300_sar_firm.h"
+
++extern int mp_oam_lb_timeout;
++extern int mp_autopvc_enable;
+
+ enum
+ {
+@@ -817,9 +819,9 @@ int tn7sar_setup_oam_channel(Tn7AtmPriva
+ pHalDev = (HAL_DEVICE *)priv->pSarHalDev;
+
+ pauto_pvc = prom_getenv("autopvc_enable");
+- if(pauto_pvc) //CQ10273
++ if(pauto_pvc || mp_autopvc_enable != -1) //CQ10273
+ {
+- auto_pvc =tn7sar_strtoul(pauto_pvc, NULL, 10);
++ auto_pvc = mp_autopvc_enable == -1 ? tn7sar_strtoul(pauto_pvc, NULL, 10) : mp_autopvc_enable;
+ }
+
+ memset(&chInfo, 0xff, sizeof(chInfo));
+@@ -985,9 +987,9 @@ int tn7sar_init(struct atm_dev *dev, Tn7
+
+ /* read in oam lb timeout value */
+ pLbTimeout = prom_getenv("oam_lb_timeout");
+- if(pLbTimeout)
++ if(pLbTimeout || mp_oam_lb_timeout != -1)
+ {
+- lbTimeout =tn7sar_strtoul(pLbTimeout, NULL, 10);
++ lbTimeout = mp_oam_lb_timeout == -1 ? tn7sar_strtoul(pLbTimeout, NULL, 10) : mp_oam_lb_timeout;
+ oamLbTimeout = lbTimeout;
+ pHalFunc->Control(pHalDev,"OamLbTimeout", "Set", &lbTimeout);
+ }
diff --git a/package/ar7-atm/patches-D7.04.03.00/170-bus_id_removal.patch b/package/ar7-atm/patches-D7.04.03.00/170-bus_id_removal.patch
new file mode 100644
index 000000000..9f1f0fdae
--- /dev/null
+++ b/package/ar7-atm/patches-D7.04.03.00/170-bus_id_removal.patch
@@ -0,0 +1,30 @@
+--- a/tn7dsl.c
++++ b/tn7dsl.c
+@@ -109,6 +109,7 @@
+ #include <linux/vmalloc.h>
+ #include <linux/file.h>
+ #include <linux/firmware.h>
++#include <linux/version.h>
+
+ #include <asm/io.h>
+ #include <asm/ar7/ar7.h>
+@@ -446,7 +447,9 @@ static void avsar_release(struct device
+ }
+
+ static struct device avsar = {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
+ .bus_id = "vlynq",
++#endif
+ .release = avsar_release,
+ };
+
+@@ -455,6 +458,9 @@ int shim_osLoadFWImage(unsigned char *pt
+ const struct firmware *fw_entry;
+ size_t size;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
++ dev_set_name(&avsar, "avsar");
++#endif
+ printk("requesting firmware image \"ar0700xx.bin\"\n");
+ if(device_register(&avsar) < 0) {
+ printk(KERN_ERR
diff --git a/package/ar7-atm/patches-D7.04.03.00/180-git_headers_include.patch b/package/ar7-atm/patches-D7.04.03.00/180-git_headers_include.patch
new file mode 100644
index 000000000..6bd8f4876
--- /dev/null
+++ b/package/ar7-atm/patches-D7.04.03.00/180-git_headers_include.patch
@@ -0,0 +1,54 @@
+--- a/tn7atm.c
++++ b/tn7atm.c
+@@ -71,10 +71,16 @@
+ #include <linux/proc_fs.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
++#include <linux/version.h>
+
+ #include <asm/io.h>
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
+ #include <asm/ar7/ar7.h>
+ #include <asm/ar7/prom.h>
++#else
++#include <asm/mach-ar7/ar7.h>
++#include <asm/mach-ar7/prom.h>
++#endif
+
+ #include "dsl_hal_api.h"
+ #include "tn7atm.h"
+--- a/tn7dsl.c
++++ b/tn7dsl.c
+@@ -112,8 +112,13 @@
+ #include <linux/version.h>
+
+ #include <asm/io.h>
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
+ #include <asm/ar7/ar7.h>
+ #include <asm/ar7/prom.h>
++#else
++#include <asm/mach-ar7/ar7.h>
++#include <asm/mach-ar7/prom.h>
++#endif
+
+ /* Modules specific header files */
+ #include "tn7atm.h"
+--- a/tn7sar.c
++++ b/tn7sar.c
+@@ -52,10 +52,16 @@
+ #include <linux/proc_fs.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
++#include <linux/version.h>
+
+ #include <asm/io.h>
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
+ #include <asm/ar7/ar7.h>
+ #include <asm/ar7/prom.h>
++#else
++#include <asm/mach-ar7/ar7.h>
++#include <asm/mach-ar7/prom.h>
++#endif
+
+ #define _CPHAL_AAL5
+ #define _CPHAL_SAR
diff --git a/package/ar7-atm/patches-D7.04.03.00/190-2.6.32_proc_fixes.patch b/package/ar7-atm/patches-D7.04.03.00/190-2.6.32_proc_fixes.patch
new file mode 100644
index 000000000..11487bf7a
--- /dev/null
+++ b/package/ar7-atm/patches-D7.04.03.00/190-2.6.32_proc_fixes.patch
@@ -0,0 +1,79 @@
+--- a/tn7dsl.c
++++ b/tn7dsl.c
+@@ -203,7 +203,11 @@ led_reg_t ledreg[2];
+ static struct led_funcs ledreg[2];
+ #endif
+
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
+ #define DEV_DSLMOD CTL_UNNUMBERED
++#else
++#define DEV_DSLMOD 0
++#endif
+ #define MAX_STR_SIZE 256
+ #define DSL_MOD_SIZE 256
+
+@@ -3431,9 +3435,16 @@ static int dslmod_sysctl(ctl_table *ctl,
+ */
+ if(write)
+ {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
+ ret = proc_dostring(ctl, write, filp, buffer, lenp, 0);
+-
++#else
++ ret = proc_dostring(ctl, write, buffer, lenp, 0);
++#endif
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
+ switch (ctl->ctl_name)
++#else
++ switch ((long)ctl->extra2)
++#endif
+ {
+ case DEV_DSLMOD:
+ ptr = strpbrk(info, " \t");
+@@ -3517,14 +3528,29 @@ static int dslmod_sysctl(ctl_table *ctl,
+ else
+ {
+ len += sprintf(info+len, mod_req);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
+ ret = proc_dostring(ctl, write, filp, buffer, lenp, 0);
++#else
++ ret = proc_dostring(ctl, write, buffer, lenp, 0);
++#endif
+ }
+ return ret;
+ }
+
+
+ ctl_table dslmod_table[] = {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
+ {DEV_DSLMOD, "dslmod", info, DSL_MOD_SIZE, 0644, NULL, NULL, &dslmod_sysctl, &sysctl_string}
++#else
++ {
++ .procname = "dslmod",
++ .data = info,
++ .maxlen = DSL_MOD_SIZE,
++ .mode = 0644,
++ .proc_handler = &dslmod_sysctl,
++ .extra2 = (void *)DEV_DSLMOD,
++ }
++#endif
+ ,
+ {0}
+ };
+@@ -3532,7 +3558,16 @@ ctl_table dslmod_table[] = {
+ /* Make sure that /proc/sys/dev is there */
+ ctl_table dslmod_root_table[] = {
+ #ifdef CONFIG_PROC_FS
++ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
+ {CTL_DEV, "dev", NULL, 0, 0555, dslmod_table}
++ #else
++ {
++ .procname = "dev",
++ .maxlen = 0,
++ .mode = 0555,
++ .child = dslmod_table,
++ }
++ #endif
+ ,
+ #endif /* CONFIG_PROC_FS */
+ {0}
diff --git a/package/ar7-atm/patches-D7.04.03.00/200-2.6.37_args.patch b/package/ar7-atm/patches-D7.04.03.00/200-2.6.37_args.patch
new file mode 100644
index 000000000..59c1d58d1
--- /dev/null
+++ b/package/ar7-atm/patches-D7.04.03.00/200-2.6.37_args.patch
@@ -0,0 +1,36 @@
+--- a/tn7atm.c
++++ b/tn7atm.c
+@@ -1867,7 +1867,11 @@ static int __init tn7atm_register (Tn7At
+
+ dgprintf (4, "device %s being registered\n", priv->name);
+
++ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
+ mydev = atm_dev_register (priv->proc_name, &tn7atm_ops, -1, NULL);
++ #else
++ mydev = atm_dev_register (priv->proc_name, NULL, &tn7atm_ops, -1, NULL);
++ #endif
+
+ if (mydev == NULL)
+ {
+--- a/tn7dsl.c
++++ b/tn7dsl.c
+@@ -466,14 +466,17 @@ int shim_osLoadFWImage(unsigned char *pt
+ {
+ const struct firmware *fw_entry;
+ size_t size;
++ int ret;
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
+ dev_set_name(&avsar, "avsar");
+ #endif
+ printk("requesting firmware image \"ar0700xx.bin\"\n");
+- if(device_register(&avsar) < 0) {
++ dev_set_name(&avsar, "avsar");
++ ret = device_register(&avsar);
++ if (ret < 0) {
+ printk(KERN_ERR
+- "avsar: device_register fails\n");
++ "avsar: device_register fails, error%i\n", ret);
+ return -1;
+ }
+
diff --git a/package/ar7-atm/patches-D7.04.03.00/210-3.3-remove-smp_lock.h.patch b/package/ar7-atm/patches-D7.04.03.00/210-3.3-remove-smp_lock.h.patch
new file mode 100644
index 000000000..525218c3b
--- /dev/null
+++ b/package/ar7-atm/patches-D7.04.03.00/210-3.3-remove-smp_lock.h.patch
@@ -0,0 +1,33 @@
+--- a/tn7atm.c
++++ b/tn7atm.c
+@@ -67,7 +67,7 @@
+ #include <linux/atmdev.h>
+ #include <linux/delay.h>
+ #include <linux/spinlock.h>
+-#include <linux/smp_lock.h>
++#include <linux/interrupt.h>
+ #include <linux/proc_fs.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
+--- a/tn7sar.c
++++ b/tn7sar.c
+@@ -48,7 +48,7 @@
+ #include <linux/atmdev.h>
+ #include <linux/delay.h>
+ #include <linux/spinlock.h>
+-#include <linux/smp_lock.h>
++#include <linux/interrupt.h>
+ #include <linux/proc_fs.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
+--- a/tn7dsl.c
++++ b/tn7dsl.c
+@@ -100,7 +100,7 @@
+ #include <linux/atmdev.h>
+ #include <linux/delay.h>
+ #include <linux/spinlock.h>
+-#include <linux/smp_lock.h>
++#include <linux/interrupt.h>
+ #include <linux/proc_fs.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
diff --git a/package/ar7-atm/patches-D7.05.01.00/100-compile_fix.patch b/package/ar7-atm/patches-D7.05.01.00/100-compile_fix.patch
new file mode 100644
index 000000000..7dee22025
--- /dev/null
+++ b/package/ar7-atm/patches-D7.05.01.00/100-compile_fix.patch
@@ -0,0 +1,808 @@
+--- a/cppi_cpaal5.c
++++ b/cppi_cpaal5.c
+@@ -360,7 +360,7 @@ static int halRxReturn(HAL_RECEIVEINFO *
+ {
+ /* malloc failed, add this RCB to Needs Buffer List */
+ TempRcb->FragCount = 1; /*MJH+030417*/
+- (HAL_RCB *)TempRcb->Eop = TempRcb; /* GSG +030430 */
++ TempRcb->Eop = TempRcb; /* GSG +030430 */
+
+ if(HalDev->NeedsCount < MAX_NEEDS) /* +MJH 030410 */
+ { /* +MJH 030410 */
+--- a/dsl_hal_api.c
++++ b/dsl_hal_api.c
+@@ -273,15 +273,15 @@
+ * 09/15/07 CPH CQ11466 Added EFM support
+ * 09/27/07 EYin CQ11929: Added NFEC/INP/Lp/Rp reporting for only ADSL2/2+ mode.
+ ******************************************************************************/
+-#include <dev_host_interface.h>
+-#include <dsl_hal_register.h>
+-#include <dsl_hal_support.h>
++#include "dev_host_interface.h"
++#include "dsl_hal_register.h"
++#include "dsl_hal_support.h"
+
+ #ifndef NO_ADV_STATS
+-#include <dsl_hal_logtable.h>
++#include "dsl_hal_logtable.h"
+ #endif
+
+-#include <dsl_hal_version.h>
++#include "dsl_hal_version.h"
+
+ // UR8_MERGE_START CQ11054 Jack Zhang
+ static unsigned int highprecision_selected = 0; //By default we use low precision for backward compt.
+--- a/dsl_hal_support.c
++++ b/dsl_hal_support.c
+@@ -142,9 +142,9 @@
+ * UR8_MERGE_START_END CQ11922 Tim
+ * 04Sep07 0.14.00 Tim CQ11922: Added support for new scratchram for INP NDR tables
+ *******************************************************************************/
+-#include <dev_host_interface.h>
+-#include <dsl_hal_register.h>
+-#include <dsl_hal_support.h>
++#include "dev_host_interface.h"
++#include "dsl_hal_register.h"
++#include "dsl_hal_support.h"
+
+ #define NUM_READ_RETRIES 3
+ static unsigned int dslhal_support_adsl2ByteSwap32(unsigned int in32Bits);
+--- a/dsl_hal_support.h
++++ b/dsl_hal_support.h
+@@ -49,7 +49,7 @@
+ * 04Nov05 0.11.00 CPH Fixed T1413 mode got Zero DS/US rate when DSL_BIT_TMODE is set.
+ *******************************************************************************/
+
+-#include <dsl_hal_api.h>
++#include "dsl_hal_api.h"
+
+ #define virtual2Physical(a) (((int)a)&~0xe0000000)
+ /* External Function Prototype Declarations */
+--- a/Makefile
++++ b/Makefile
+@@ -1,18 +1,9 @@
+-# File: drivers/atm/ti_evm3/Makefile
+ #
+-# Makefile for the Texas Instruments EVM3 ADSL/ATM driver.
++# Makefile for the TIATM device driver.
+ #
+-#
+-# Copyright (c) 2000 Texas Instruments Incorporated.
+-# Jeff Harrell (jharrell@telogy.com)
+-# Viren Balar (vbalar@ti.com)
+-# Victor Wells (vwells@telogy.com)
+-#
+-include $(TOPDIR)/Rules.make
+-
+-
+-
+-
+-
+-
+
++CONFIG_SANGAM_ATM=m
++#EXTRA_CFLAGS += -DEL -I. -DPOST_SILICON -DCOMMON_NSP -DCONFIG_LED_MODULE -DDEREGISTER_LED -DNO_ACT
++EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -DNO_ACT -D__NO__VOICE_PATCH__ -DEL
++obj-$(CONFIG_SANGAM_ATM) := tiatm.o
++tiatm-objs += cpsar.o aal5sar.o tn7sar.o tn7atm.o tn7dsl.o dsl_hal_api.o dsl_hal_support.o
+--- a/tn7atm.c
++++ b/tn7atm.c
+@@ -66,7 +66,6 @@
+ * 09/18/07 CPH CQ11466 Added EFM Support
+ *********************************************************************************************/
+
+-#include <linux/config.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -74,11 +73,14 @@
+ #include <linux/delay.h>
+ #include <linux/spinlock.h>
+ #include <linux/smp_lock.h>
+-#include <asm/io.h>
+-#include <asm/mips-boards/prom.h>
+ #include <linux/proc_fs.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
++
++#include <asm/io.h>
++#include <asm/ar7/ar7.h>
++#include <asm/ar7/prom.h>
++
+ #include "dsl_hal_api.h"
+ #ifdef AR7_EFM
+ #include "tn7efm.h"
+@@ -90,6 +92,7 @@
+ #include "dsl_hal_register.h"
+
+ #ifdef MODULE
++MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION ("Tnetd73xx ATM Device Driver");
+ MODULE_AUTHOR ("Zhicheng Tang");
+ #endif
+@@ -108,9 +111,9 @@ MODULE_AUTHOR ("Zhicheng Tang");
+
+ /*end of externs */
+
+-#ifndef TI_STATIC_ALLOCATIONS
+-#define TI_STATIC_ALLOCATIONS
+-#endif
++//#ifndef TI_STATIC_ALLOCATIONS
++//#define TI_STATIC_ALLOCATIONS
++//#endif
+
+ #define tn7atm_kfree_skb(x) dev_kfree_skb(x)
+
+@@ -135,7 +138,7 @@ static int EnableQoS = FALSE;
+ /* prototypes */
+ static int tn7atm_set_can_support_adsl2 (int can);
+
+-static int tn7atm_open (struct atm_vcc *vcc, short vpi, int vci);
++static int tn7atm_open (struct atm_vcc *vcc);
+
+ void tn7atm_close (struct atm_vcc *vcc);
+
+@@ -298,13 +301,12 @@ static const struct atmdev_ops tn7atm_op
+ getsockopt: NULL,
+ setsockopt: NULL,
+ send: tn7atm_send,
+- sg_send: NULL,
+ phy_put: NULL,
+ phy_get: NULL,
+ change_qos: tn7atm_change_qos,
+ };
+
+-const char drv_proc_root_folder[] = "avalanche/";
++const char drv_proc_root_folder[] = "avalanche";
+ static struct proc_dir_entry *root_proc_dir_entry = NULL;
+ #define DRV_PROC_MODE 0644
+ static int proc_root_already_exists = TRUE;
+@@ -626,56 +628,6 @@ static int turbodsl_check_priority_type(
+
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+- * Function: int tn7atm_walk_vccs(struct atm_dev *dev, short *vcc, int *vci)
+- *
+- * Description: retrieve VPI/VCI for connection
+- *
+- *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+-static int tn7atm_walk_vccs (struct atm_vcc *vcc, short *vpi, int *vci)
+-{
+- struct atm_vcc *walk;
+-
+- /*
+- * find a free VPI
+- */
+- if (*vpi == ATM_VPI_ANY)
+- {
+-
+- for (*vpi = 0, walk = vcc->dev->vccs; walk; walk = walk->next)
+- {
+-
+- if ((walk->vci == *vci) && (walk->vpi == *vpi))
+- {
+- (*vpi)++;
+- walk = vcc->dev->vccs;
+- }
+- }
+- }
+-
+- /*
+- * find a free VCI
+- */
+- if (*vci == ATM_VCI_ANY)
+- {
+-
+- for (*vci = ATM_NOT_RSV_VCI, walk = vcc->dev->vccs; walk;
+- walk = walk->next)
+- {
+-
+- if ((walk->vpi = *vpi) && (walk->vci == *vci))
+- {
+- *vci = walk->vci + 1;
+- walk = vcc->dev->vccs;
+- }
+- }
+- }
+-
+- return 0;
+-}
+-
+-
+-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+- *
+ * Function: int tn7atm_sar_irq(void)
+ *
+ * Description: tnetd73xx SAR interrupt.
+@@ -766,7 +718,7 @@ static int __init tn7atm_irq_request (st
+
+ priv->sar_irq = LNXINTNUM (ATM_SAR_INT); /* Interrupt line # */
+
+- if (request_irq (priv->sar_irq, tn7atm_sar_irq, SA_INTERRUPT, "SAR ", dev))
++ if (request_irq (priv->sar_irq, tn7atm_sar_irq, IRQF_DISABLED, "SAR ", dev))
+ printk ("Could not register tn7atm_sar_irq\n");
+
+ /*
+@@ -777,8 +729,8 @@ static int __init tn7atm_irq_request (st
+ {
+ def_sar_inter_pace = os_atoi (ptr);
+ }
+- avalanche_request_pacing (priv->sar_irq, ATM_SAR_INT_PACING_BLOCK_NUM,
+- def_sar_inter_pace);
++ /* avalanche_request_pacing (priv->sar_irq, ATM_SAR_INT_PACING_BLOCK_NUM,
++ def_sar_inter_pace); */
+
+
+ #ifdef AR7_EFM
+@@ -790,7 +742,7 @@ static int __init tn7atm_irq_request (st
+ * Reigster Receive interrupt A
+ */
+ priv->dsl_irq = LNXINTNUM (ATM_DSL_INT); /* Interrupt line # */
+- if (request_irq (priv->dsl_irq, tn7atm_dsl_irq, SA_INTERRUPT, "DSL ", dev))
++ if (request_irq (priv->dsl_irq, tn7atm_dsl_irq, IRQF_DISABLED, "DSL ", dev))
+ printk ("Could not register tn7atm_dsl_irq\n");
+
+ /***** VRB Tasklet Mode ****/
+@@ -958,11 +910,15 @@ static int __init tn7atm_get_ESI (struct
+ #define ATM_VBR_RT 5
+ #endif
+
+-int tn7atm_open (struct atm_vcc *vcc, short vpi, int vci)
++int tn7atm_open (struct atm_vcc *vcc)
+ {
+ tn7atm_activate_vc_parm_t tn7atm_activate_vc_parm;
+ int rc;
+ //int flags;
++ tn7atm_activate_vc_parm.pcr = 0x20000;
++ tn7atm_activate_vc_parm.scr = 0x20000;
++ tn7atm_activate_vc_parm.mbs = 0x20000;
++ tn7atm_activate_vc_parm.cdvt = 10000;
+
+ dgprintf(1, "tn7atm_open()\n");
+
+@@ -974,24 +930,18 @@ int tn7atm_open (struct atm_vcc *vcc, sh
+ return -1;
+ }
+
+- MOD_INC_USE_COUNT;
++// MOD_INC_USE_COUNT;
+
+- /* find a free VPI/VCI */
+- tn7atm_walk_vccs(vcc, &vpi, &vci);
+-
+- vcc->vpi = vpi;
+- vcc->vci = vci;
+-
+- if ((vci == ATM_VCI_UNSPEC) || (vpi == ATM_VCI_UNSPEC))
++ if ((vcc->vci == ATM_VCI_UNSPEC) || (vcc->vpi == ATM_VCI_UNSPEC))
+ {
+- MOD_DEC_USE_COUNT;
++// MOD_DEC_USE_COUNT;
+ return -EBUSY;
+ }
+
+- tn7atm_activate_vc_parm.vpi = vpi;
+- tn7atm_activate_vc_parm.vci = vci;
++ tn7atm_activate_vc_parm.vpi = vcc->vpi;
++ tn7atm_activate_vc_parm.vci = vcc->vci;
+
+- if ((vpi == CLEAR_EOC_VPI) && (vci == CLEAR_EOC_VCI))
++ if ((vcc->vpi == CLEAR_EOC_VPI) && (vcc->vci == CLEAR_EOC_VCI))
+ {
+ /* always use (max_dma_chan+1) for clear eoc */
+ tn7atm_activate_vc_parm.chan = EOC_DMA_CHAN;
+@@ -999,7 +949,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh
+ /* check to see whether clear eoc is opened or not */
+ if (tn7atm_activate_vc_parm.priv->lut[tn7atm_activate_vc_parm.chan].inuse)
+ {
+- MOD_DEC_USE_COUNT;
++// MOD_DEC_USE_COUNT;
+ printk("tn7atm_open: Clear EOC channel (dmachan=%d) already in use.\n", tn7atm_activate_vc_parm.chan);
+ return -EBUSY;
+ }
+@@ -1008,7 +958,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh
+ if (rc)
+ {
+ printk("tn7atm_open: failed to setup clear_eoc\n");
+- MOD_DEC_USE_COUNT;
++// MOD_DEC_USE_COUNT;
+ return -EBUSY;
+ }
+ tn7atm_set_lut(tn7atm_activate_vc_parm.priv,vcc, tn7atm_activate_vc_parm.chan);
+@@ -1017,17 +967,17 @@ int tn7atm_open (struct atm_vcc *vcc, sh
+ }
+ else /* PVC channel setup */
+ {
+- if ((vpi==REMOTE_MGMT_VPI) && (vci==REMOTE_MGMT_VCI))
++ if ((vcc->vpi==REMOTE_MGMT_VPI) && (vcc->vci==REMOTE_MGMT_VCI))
+ {
+ tn7atm_activate_vc_parm.chan = 14; /* always use chan 14 for MII PVC-base romote mgmt */
+ }
+ else
+ {
+- rc = tn7atm_lut_find(vpi, vci);
++ rc = tn7atm_lut_find(vcc->vpi, vcc->vci);
+ /* check to see whether PVC is opened or not */
+ if(ATM_NO_DMA_CHAN != rc)
+ {
+- MOD_DEC_USE_COUNT;
++// MOD_DEC_USE_COUNT;
+ printk("PVC already opened. dmachan = %d\n", rc);
+ return -EBUSY;
+ }
+@@ -1059,6 +1009,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh
+ tn7atm_activate_vc_parm.priority = 2;
+ break;
+
++#if 0
+ case ATM_VBR: /* Variable Bit Rate-Non RealTime*/
+ tn7atm_activate_vc_parm.qos = 1;
+ tn7atm_activate_vc_parm.priority = 1;
+@@ -1080,6 +1031,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh
+ tn7atm_activate_vc_parm.mbs = vcc->qos.txtp.max_pcr;
+ tn7atm_activate_vc_parm.cdvt = vcc->qos.txtp.max_cdv;
+ break;
++#endif
+
+ default:
+ tn7atm_activate_vc_parm.qos = 2;
+@@ -1107,7 +1059,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh
+ if (rc < 0)
+ {
+ printk("failed to activate hw channel\n");
+- MOD_DEC_USE_COUNT;
++// MOD_DEC_USE_COUNT;
+ tn7atm_lut_clear(vcc, tn7atm_activate_vc_parm.chan);
+ //spin_unlock_irqrestore(&chan_init_lock, flags);
+ return -EBUSY;
+@@ -1197,7 +1149,7 @@ void tn7atm_close (struct atm_vcc *vcc)
+ tn7atm_lut_clear (vcc, dmachan);
+ //spin_unlock_irqrestore (&closeLock, closeFlag);
+
+- MOD_DEC_USE_COUNT;
++// MOD_DEC_USE_COUNT;
+
+ dgprintf (1, "Leave tn7atm_close\n");
+ }
+@@ -1630,8 +1582,7 @@ int tn7atm_receive (void *os_dev, int ch
+ * firewall is on */
+
+ dgprintf (3, "pushing the skb...\n");
+-
+- skb->stamp = vcc->timestamp = xtime;
++ __net_timestamp(skb);
+
+ xdump ((unsigned char *) skb->data, skb->len, 5);
+
+@@ -1854,8 +1805,7 @@ printk("!!!free atm irq: tn7atm_exit\n")
+
+ kfree (dev->dev_data);
+
+- // atm_dev_deregister (dev);
+- shutdown_atm_dev (dev);
++ atm_dev_deregister (dev);
+
+ /*
+ * remove proc entries
+@@ -2086,9 +2036,6 @@ static int __init tn7atm_detect (void)
+ * Set up proc entry for atm stats
+ */
+
+- if (tn7atm_xlate_proc_name
+- (drv_proc_root_folder, &root_proc_dir_entry, &residual))
+- {
+ printk ("Creating new root folder %s in the proc for the driver stats \n",
+ drv_proc_root_folder);
+ root_proc_dir_entry = proc_mkdir (drv_proc_root_folder, NULL);
+@@ -2098,7 +2045,6 @@ static int __init tn7atm_detect (void)
+ return -ENOMEM;
+ }
+ proc_root_already_exists = FALSE;
+- }
+
+
+ /*
+@@ -2731,7 +2677,5 @@ int tn7atm_proc_turbodsl_write(struct fi
+ return count;
+ }
+
+-#ifdef MODULE
+ module_init (tn7atm_detect);
+ module_exit (tn7atm_exit);
+-#endif /* MODULE */
+--- a/tn7atm.h
++++ b/tn7atm.h
+@@ -20,7 +20,8 @@
+ //#include "mips_support.h"
+ #include <linux/list.h>
+
+-#include <linux/config.h>
++#define MIPS_EXCEPTION_OFFSET 8
++#define LNXINTNUM(x)((x) + MIPS_EXCEPTION_OFFSET)
+
+ #ifdef CONFIG_MODVERSIONS
+ #include <linux/modversions.h>
+--- a/tn7dsl.c
++++ b/tn7dsl.c
+@@ -102,7 +102,6 @@
+ * UR8_MERGE_END CQ11813
+ * 09/18/07 CPH CQ11466: Added EFM support.
+ *********************************************************************************************/
+-#include <linux/config.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -110,8 +109,6 @@
+ #include <linux/delay.h>
+ #include <linux/spinlock.h>
+ #include <linux/smp_lock.h>
+-#include <asm/io.h>
+-#include <asm/mips-boards/prom.h>
+ #include <linux/proc_fs.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
+@@ -119,6 +116,12 @@
+ #include <linux/timer.h>
+ #include <linux/vmalloc.h>
+ #include <linux/file.h>
++#include <linux/firmware.h>
++
++#include <asm/io.h>
++#include <asm/ar7/ar7.h>
++#include <asm/ar7/prom.h>
++
+ /* Modules specific header files */
+ #ifdef AR7_EFM
+ #include "tn7efm.h"
+@@ -185,7 +188,7 @@ led_reg_t ledreg[2];
+ static struct led_funcs ledreg[2];
+ #endif
+
+-#define DEV_DSLMOD 1
++#define DEV_DSLMOD CTL_UNNUMBERED
+ #define MAX_STR_SIZE 256
+ #define DSL_MOD_SIZE 256
+
+@@ -316,7 +319,7 @@ static PITIDSLHW_T pIhw;
+ static volatile int bshutdown;
+ static char info[MAX_STR_SIZE];
+ /* Used for DSL Polling enable */
+-static DECLARE_MUTEX_LOCKED (adsl_sem_overlay);
++static struct semaphore adsl_sem_overlay;
+
+ //kthread_t overlay_thread;
+ /* end of module wide declars */
+@@ -369,6 +372,14 @@ int os_atoih (const char *pstr)
+ return val;
+ }
+
++int avalanche_request_intr_pacing(int irq_nr, unsigned int blk_num,
++ unsigned int pace_value)
++{
++ printk("avalanche_request_pacing(%d, %u, %u); // not implemented\n", irq_nr, blk_num, pace_value);
++ return 0;
++}
++
++
+ int os_atoi(const char *pStr)
+ {
+ int MulNeg = (*pStr == '-' ? -1 : 1);
+@@ -405,39 +416,6 @@ void dprintf (int uDbgLevel, char *szFmt
+ #endif
+ }
+
+-int strcmp(const char *s1, const char *s2)
+-{
+-
+- int size = strlen(s1);
+-
+- return(strncmp(s1, s2, size));
+-}
+-
+-int strncmp(const char *s1, const char *s2, size_t size)
+-{
+- int i = 0;
+- int max_size = (int)size;
+-
+- while((s1[i] != 0) && i < max_size)
+- {
+- if(s2[i] == 0)
+- {
+- return -1;
+- }
+- if(s1[i] != s2[i])
+- {
+- return 1;
+- }
+- i++;
+- }
+- if(s2[i] != 0)
+- {
+- return 1;
+- }
+-
+- return 0;
+-}
+-
+ // * UR8_MERGE_START CQ10640 Jack Zhang
+ int tn7dsl_dump_dsp_memory(char *input_str) //cph99
+ {
+@@ -487,144 +465,78 @@ unsigned int shim_osGetCpuFrequency(void
+ return CpuFrequency;
+ }
+
+-int shim_osLoadFWImage(unsigned char *ptr)
++static void avsar_release(struct device *dev)
+ {
+- unsigned int bytesRead;
+- mm_segment_t oldfs;
+- static struct file *filp;
+- unsigned int imageLength=0x5ffff;
+-
+-#ifdef AR7_EFM
+- int dp_alt=0;
+- char *ptr1=NULL;
+-#ifdef EFM_DEBUG
+- char *ptr2=NULL;
+- char *ptr3=NULL;
+-#endif
+-
+- if ((ptr1 = prom_getenv("DSL_DP_ALT")) != NULL)
+- {
+- dp_alt=os_atoi(ptr1);
+- if (dp_alt==1)
+- {
+- filp = filp_open(DSP_DEBUG_FIRMWARE_PATH,00,O_RDONLY);
+- if (!IS_ERR(filp))
+- {
+- strcpy (DSP_FIRMWARE_PATH, DSP_DEBUG_FIRMWARE_PATH);
+- }
+- }
+-#ifdef EFM_DEBUG
+- else if (dp_alt==2)
+- {
+- if ((ptr2 = prom_getenv("DSL_DP")) != NULL)
+- {
+- if (!strncmp(ptr2, "DSL_DP", 6))
+- { // indirect naming
+- if ((ptr3 = prom_getenv(ptr2)) != NULL)
+- filp = filp_open(ptr3,00,O_RDONLY);
+- ptr2 = ptr3; // redirect ptr2 to ptr3
+- }
+-
+- filp = filp_open(ptr2,00,O_RDONLY);
+- if (!IS_ERR(filp))
+- {
+- strcpy (DSP_FIRMWARE_PATH, ptr2);
+- }
+- }
+- }
+- printk("dp_path=%s\n", DSP_FIRMWARE_PATH);
+-#endif
+- }
+-#endif
+-
+- dgprintf(4, "tn7dsl_read_dsp()\n");
+-
+- dgprintf(4,"open file %s\n", DSP_FIRMWARE_PATH);
+-
+- filp=filp_open(DSP_FIRMWARE_PATH,00,O_RDONLY);
+- if(IS_ERR(filp))
+- {
+- printk("Failed: Could not open DSP binary file\n");
+- return -1;
+- }
+-
+- if (filp->f_dentry != NULL)
+- {
+- if (filp->f_dentry->d_inode != NULL)
+- {
+- printk ("DSP binary filesize = %d bytes\n",
+- (int) filp->f_dentry->d_inode->i_size);
+- imageLength = (unsigned int)filp->f_dentry->d_inode->i_size + 0x200;
+- }
+- }
+-
+- if (filp->f_op->read==NULL)
+- return -1; /* File(system) doesn't allow reads */
+-
+- /*
+- * Disable parameter checking
+- */
+- oldfs = get_fs();
+- set_fs(KERNEL_DS);
+-
+- /*
+- * Now read bytes from postion "StartPos"
+- */
+- filp->f_pos = 0;
+-
+- bytesRead = filp->f_op->read(filp,ptr,imageLength,&filp->f_pos);
+-
+- dgprintf(4,"file length = %d\n", bytesRead);
+-
+- set_fs(oldfs);
+-
+- /*
+- * Close the file
+- */
+- fput(filp);
+-
+- return bytesRead;
++ printk(KERN_DEBUG "avsar firmware released\n");
+ }
+
++static struct device avsar = {
++ .bus_id = "vlynq",
++ .release = avsar_release,
++};
+
+-unsigned int shim_read_overlay_page (void *ptr, unsigned int secOffset,
+- unsigned int secLength)
++int shim_osLoadFWImage(unsigned char *ptr)
+ {
+- unsigned int bytesRead;
+- mm_segment_t oldfs;
+- struct file *filp;
+-
+- dgprintf(4,"shim_read_overlay_page\n");
+- //dgprintf(4,"sec offset=%d, sec length =%d\n", secOffset, secLength);
++ const struct firmware *fw_entry;
++ size_t size;
+
+- filp=filp_open(DSP_FIRMWARE_PATH,00,O_RDONLY);
+- if(filp ==NULL)
+- {
+- printk("Failed: Could not open DSP binary file\n");
+- return -1;
+- }
+-
+- if (filp->f_op->read==NULL)
+- return -1; /* File(system) doesn't allow reads */
+-
+- /*
+- * Now read bytes from postion "StartPos"
+- */
++ printk("requesting firmware image \"ar0700xx.bin\"\n");
++ if(device_register(&avsar) < 0) {
++ printk(KERN_ERR
++ "avsar: device_register fails\n");
++ return -1;
++ }
++
++ if (request_firmware(&fw_entry, "ar0700xx.bin", &avsar)) {
++ printk(KERN_ERR
++ "avsar: Firmware not available\n");
++ device_unregister(&avsar);
++ return -1;
++ }
++ size = fw_entry->size;
++ device_unregister(&avsar);
++ if (size > 0x6ffff) {
++ printk(KERN_ERR
++ "avsar: Firmware too big (%d bytes)\n", size);
++ release_firmware(fw_entry);
++ return -1;
++ }
++ memcpy(ptr, fw_entry->data, size);
++ release_firmware(fw_entry);
++ return size;
++}
++
++unsigned int shim_read_overlay_page(void *ptr, unsigned int secOffset, unsigned int secLength)
++{
++ const struct firmware *fw_entry;
++
++ printk("requesting firmware image \"ar0700xx.bin\"\n");
++ if (device_register(&avsar) < 0) {
++ printk(KERN_ERR
++ "avsar: device_register fails\n");
++ return -1;
++ }
++
++ if (request_firmware(&fw_entry, "ar0700xx.bin", &avsar)) {
++ printk(KERN_ERR
++ "avsar: Firmware not available\n");
++ device_unregister(&avsar);
++ return -1;
++ }
++
++ device_unregister(&avsar);
++ if (fw_entry->size > secLength) {
++ printk(KERN_ERR
++ "avsar: Firmware too big (%d bytes)\n", fw_entry->size);
++ release_firmware(fw_entry);
++ return -1;
++ }
++ memcpy(ptr + secOffset, fw_entry->data, secLength);
++ release_firmware(fw_entry);
++ return secLength;
++}
+
+- if(filp->f_op->llseek)
+- filp->f_op->llseek(filp,secOffset, 0);
+- oldfs = get_fs();
+- set_fs(KERNEL_DS);
+- filp->f_pos = secOffset;
+- bytesRead = filp->f_op->read(filp,ptr,secLength,&filp->f_pos);
+
+- set_fs(oldfs);
+- /*
+- * Close the file
+- */
+- fput(filp);
+- return bytesRead;
+-}
+
+ int shim_osLoadDebugFWImage(unsigned char *ptr)
+ {
+@@ -3287,6 +3199,7 @@ int tn7dsl_init(void *priv)
+ int high_precision_selected = 0;
+ // UR8_MERGE_END CQ11054*
+
++ sema_init(&adsl_sem_overlay, 0);
+ /*
+ * start dsl
+ */
+@@ -3665,7 +3578,7 @@ static int dslmod_sysctl(ctl_table *ctl,
+ */
+ if(write)
+ {
+- ret = proc_dostring(ctl, write, filp, buffer, lenp);
++ ret = proc_dostring(ctl, write, filp, buffer, lenp, 0);
+
+ switch (ctl->ctl_name)
+ {
+@@ -3751,14 +3664,14 @@ static int dslmod_sysctl(ctl_table *ctl,
+ else
+ {
+ len += sprintf(info+len, mod_req);
+- ret = proc_dostring(ctl, write, filp, buffer, lenp);
++ ret = proc_dostring(ctl, write, filp, buffer, lenp, 0);
+ }
+ return ret;
+ }
+
+
+ ctl_table dslmod_table[] = {
+- {DEV_DSLMOD, "dslmod", info, DSL_MOD_SIZE, 0644, NULL, &dslmod_sysctl}
++ {DEV_DSLMOD, "dslmod", info, DSL_MOD_SIZE, 0644, NULL, NULL, &dslmod_sysctl, &sysctl_string}
+ ,
+ {0}
+ };
+@@ -3781,8 +3694,7 @@ void tn7dsl_dslmod_sysctl_register(void)
+ if (initialized == 1)
+ return;
+
+- dslmod_sysctl_header = register_sysctl_table(dslmod_root_table, 1);
+- dslmod_root_table->child->de->owner = THIS_MODULE;
++ dslmod_sysctl_header = register_sysctl_table(dslmod_root_table);
+
+ /*
+ * set the defaults
+--- a/tn7sar.c
++++ b/tn7sar.c
+@@ -43,7 +43,6 @@
+ * 09/18/07 CPH CQ11466: Added EFM support.
+ *******************************************************************************/
+
+-#include <linux/config.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -51,12 +50,13 @@
+ #include <linux/delay.h>
+ #include <linux/spinlock.h>
+ #include <linux/smp_lock.h>
+-#include <asm/io.h>
+-#include <asm/mips-boards/prom.h>
+ #include <linux/proc_fs.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
+
++#include <asm/io.h>
++#include <asm/ar7/ar7.h>
++#include <asm/ar7/prom.h>
+
+ #define _CPHAL_AAL5
+ #define _CPHAL_SAR
diff --git a/package/ar7-atm/patches-D7.05.01.00/110-interrupt_fix.patch b/package/ar7-atm/patches-D7.05.01.00/110-interrupt_fix.patch
new file mode 100644
index 000000000..112245769
--- /dev/null
+++ b/package/ar7-atm/patches-D7.05.01.00/110-interrupt_fix.patch
@@ -0,0 +1,37 @@
+--- a/tn7atm.c
++++ b/tn7atm.c
+@@ -633,7 +633,7 @@ static int turbodsl_check_priority_type(
+ * Description: tnetd73xx SAR interrupt.
+ *
+ *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+-static void tn7atm_sar_irq (int irq, void *voiddev, struct pt_regs *regs)
++static irqreturn_t tn7atm_sar_irq (int irq, void *voiddev)
+ {
+ struct atm_dev *atmdev;
+ Tn7AtmPrivate *priv;
+@@ -660,6 +660,7 @@ static void tn7atm_sar_irq (int irq, voi
+ #ifdef TIATM_INST_SUPP
+ psp_trace_par (ATM_DRV_SAR_ISR_EXIT, retval);
+ #endif
++ return IRQ_HANDLED;
+ }
+
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+@@ -669,7 +670,7 @@ static void tn7atm_sar_irq (int irq, voi
+ * Description: tnetd73xx DSL interrupt.
+ *
+ *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+-static void tn7atm_dsl_irq (int irq, void *voiddev, struct pt_regs *regs)
++static irqreturn_t tn7atm_dsl_irq (int irq, void *voiddev)
+ {
+ struct atm_dev *atmdev;
+ Tn7AtmPrivate *priv;
+@@ -691,6 +692,8 @@ static void tn7atm_dsl_irq (int irq, voi
+ #ifdef TIATM_INST_SUPP
+ psp_trace_par (ATM_DRV_DSL_ISR_EXIT, retval);
+ #endif
++
++ return IRQ_HANDLED;
+ }
+
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/package/ar7-atm/patches-D7.05.01.00/120-no_dumb_inline.patch b/package/ar7-atm/patches-D7.05.01.00/120-no_dumb_inline.patch
new file mode 100644
index 000000000..e9d99dff4
--- /dev/null
+++ b/package/ar7-atm/patches-D7.05.01.00/120-no_dumb_inline.patch
@@ -0,0 +1,11 @@
+--- a/tn7api.h
++++ b/tn7api.h
+@@ -118,7 +118,7 @@ int tn7dsl_proc_dbgmsg_write(struct file
+ int tn7dsl_proc_dbgmsg_read(char* buf, char **start, off_t offset, int count,int *eof, void *data);
+ #endif
+ //UR8_MERGE_END CQ11813
+-inline int tn7dsl_handle_interrupt(void);
++int tn7dsl_handle_interrupt(void);
+
+ void tn7dsl_dslmod_sysctl_register(void);
+ void tn7dsl_dslmod_sysctl_unregister(void);
diff --git a/package/ar7-atm/patches-D7.05.01.00/130-powercutback.patch b/package/ar7-atm/patches-D7.05.01.00/130-powercutback.patch
new file mode 100644
index 000000000..415486482
--- /dev/null
+++ b/package/ar7-atm/patches-D7.05.01.00/130-powercutback.patch
@@ -0,0 +1,44 @@
+--- a/dsl_hal_advcfg.c
++++ b/dsl_hal_advcfg.c
+@@ -36,9 +36,9 @@
+ * 05Jul05 0.00.09 CPH CQ9775: Change dslhal_advcfg_configDsTones input parameters & support for ADSL2+
+ * 24Jul05 0.00.10 CPH Fixed comments in dslhal_advcfg_configDsTones function header
+ *******************************************************************************/
+-#include <dev_host_interface.h>
+-#include <dsl_hal_register.h>
+-#include <dsl_hal_support.h>
++#include "dev_host_interface.h"
++#include "dsl_hal_register.h"
++#include "dsl_hal_support.h"
+
+ /*****************************************************************************/
+ /* ACT API functions -- To be moved into their own independent module --RamP */
+--- a/Makefile
++++ b/Makefile
+@@ -4,6 +4,7 @@
+
+ CONFIG_SANGAM_ATM=m
+ #EXTRA_CFLAGS += -DEL -I. -DPOST_SILICON -DCOMMON_NSP -DCONFIG_LED_MODULE -DDEREGISTER_LED -DNO_ACT
+-EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -DNO_ACT -D__NO__VOICE_PATCH__ -DEL
++#EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -DNO_ACT -D__NO__VOICE_PATCH__ -DEL
++EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -D__NO__VOICE_PATCH__ -DEL
+ obj-$(CONFIG_SANGAM_ATM) := tiatm.o
+-tiatm-objs += cpsar.o aal5sar.o tn7sar.o tn7atm.o tn7dsl.o dsl_hal_api.o dsl_hal_support.o
++tiatm-objs += cpsar.o aal5sar.o tn7sar.o tn7atm.o tn7dsl.o dsl_hal_api.o dsl_hal_support.o dsl_hal_advcfg.o
+--- a/tn7dsl.c
++++ b/tn7dsl.c
+@@ -3053,6 +3053,14 @@ static int tn7dsl_set_dsl(void)
+ dslhal_api_setRateAdaptFlag(pIhw, os_atoi(ptr));
+ }
+
++ // set powercutback
++ ptr = NULL;
++ ptr = prom_getenv("powercutback");
++ if(ptr)
++ {
++ dslhal_advcfg_onOffPcb(pIhw, os_atoi(ptr));
++ }
++
+ // trellis
+ ptr = NULL;
+ ptr = prom_getenv("trellis");
diff --git a/package/ar7-atm/patches-D7.05.01.00/140-debug_mode.patch b/package/ar7-atm/patches-D7.05.01.00/140-debug_mode.patch
new file mode 100644
index 000000000..3873827af
--- /dev/null
+++ b/package/ar7-atm/patches-D7.05.01.00/140-debug_mode.patch
@@ -0,0 +1,16 @@
+--- a/tn7sar.c
++++ b/tn7sar.c
+@@ -125,10 +125,10 @@ enum
+ //09/05/07: cph, move to tn7atm.h
+ // #define RESERVED_OAM_CHANNEL 15
+
+-#define AAL5_PARM "id=aal5, base = 0x03000000, offset = 0, int_line=15, ch0=[RxBufSize=1522; RxNumBuffers = 32; RxServiceMax = 50; TxServiceMax=50; TxNumBuffers=32; CpcsUU=0x5aa5; TxVc_CellRate=0x3000; TxVc_AtmHeader=0x00000640]"
+-#define SAR_PARM "id=sar,base = 0x03000000, reset_bit = 9, offset = 0; UniNni = 0, PdspEnable = 1"
++#define CH0_PARM "RxBufSize=1522, RxNumBuffers=32, RxServiceMax=50, TxServiceMax=50, TxNumBuffers=32, CpcsUU=0x5aa5, TxVc_CellRate=0x3000, TxVc_AtmHeader=0x00000640"
++#define AAL5_PARM "id=aal5, base=0x03000000, offset=0, int_line=15, ch0=[" CH0_PARM "]"
++#define SAR_PARM "id=sar, base=0x03000000, reset_bit=9, offset=0; UniNni=0, PdspEnable=1, Debug=0xFFFFFFFF"
+ #define RESET_PARM "id=ResetControl, base=0xA8611600"
+-#define CH0_PARM "RxBufSize=1522, RxNumBuffers = 32, RxServiceMax = 50, TxServiceMax=50, TxNumBuffers=32, CpcsUU=0x5aa5, TxVc_CellRate=0x3000, TxVc_AtmHeader=0x00000640"
+
+ #define MAX_PVC_TABLE_ENTRY 16
+
diff --git a/package/ar7-atm/patches-D7.05.01.00/150-tasklet_mode.patch b/package/ar7-atm/patches-D7.05.01.00/150-tasklet_mode.patch
new file mode 100644
index 000000000..97b8cecdd
--- /dev/null
+++ b/package/ar7-atm/patches-D7.05.01.00/150-tasklet_mode.patch
@@ -0,0 +1,11 @@
+--- a/Makefile
++++ b/Makefile
+@@ -5,6 +5,7 @@
+ CONFIG_SANGAM_ATM=m
+ #EXTRA_CFLAGS += -DEL -I. -DPOST_SILICON -DCOMMON_NSP -DCONFIG_LED_MODULE -DDEREGISTER_LED -DNO_ACT
+ #EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -DNO_ACT -D__NO__VOICE_PATCH__ -DEL
+-EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -D__NO__VOICE_PATCH__ -DEL
++#EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -D__NO__VOICE_PATCH__ -DEL
++EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -D__NO__VOICE_PATCH__ -DEL -DCPATM_TASKLET_MODE
+ obj-$(CONFIG_SANGAM_ATM) := tiatm.o
+ tiatm-objs += cpsar.o aal5sar.o tn7sar.o tn7atm.o tn7dsl.o dsl_hal_api.o dsl_hal_support.o dsl_hal_advcfg.o
diff --git a/package/ar7-atm/patches-D7.05.01.00/160-module-params.patch b/package/ar7-atm/patches-D7.05.01.00/160-module-params.patch
new file mode 100644
index 000000000..6e7d9de18
--- /dev/null
+++ b/package/ar7-atm/patches-D7.05.01.00/160-module-params.patch
@@ -0,0 +1,663 @@
+--- a/tn7atm.c
++++ b/tn7atm.c
+@@ -95,6 +95,146 @@
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION ("Tnetd73xx ATM Device Driver");
+ MODULE_AUTHOR ("Zhicheng Tang");
++
++int mp_sar_ipacemax = -1;
++module_param_named(ipacemax, mp_sar_ipacemax, int, 0);
++MODULE_PARM_DESC(ipacemax, "Interrupt pacing");
++
++char *mp_macc = NULL;
++module_param_named(macc, mp_macc, charp, 0);
++MODULE_PARM_DESC(macc, "MAC address");
++
++int mp_dsp_noboost = -1;
++module_param_named(dsp_noboost, mp_dsp_noboost, int, 0);
++MODULE_PARM_DESC(dsp_noboost, "Suppress DSP frequency boost");
++
++int mp_dsp_freq = -1;
++module_param_named(dsp_freq, mp_dsp_freq, int, 0);
++MODULE_PARM_DESC(dsp_freq, "Frequency to boost the DSP to");
++
++char *mp_featctl0 = NULL;
++module_param_named(featctl0, mp_featctl0, charp, 0);
++MODULE_PARM_DESC(featctl0, "DSL feature control 0");
++
++char *mp_featctl1 = NULL;
++module_param_named(featctl1, mp_featctl1, charp, 0);
++MODULE_PARM_DESC(featctl1, "DSL feature control 1");
++
++char *mp_phyctl0 = NULL;
++module_param_named(phyctl0, mp_phyctl0, charp, 0);
++MODULE_PARM_DESC(phyctl0, "DSL PHY control 0");
++
++char *mp_phyctl1 = NULL;
++module_param_named(phyctl1, mp_phyctl1, charp, 0);
++MODULE_PARM_DESC(phyctl1, "DSL PHY control 1");
++
++int mp_turbodsl = -1;
++module_param_named(turbodsl, mp_turbodsl, int, 0);
++MODULE_PARM_DESC(turbodsl, "Enable TurboDSL");
++
++int mp_sar_rxbuf = -1;
++module_param_named(sar_rxbuf, mp_sar_rxbuf, int, 0);
++MODULE_PARM_DESC(sar_rxbuf, "SAR RxBuf size");
++
++int mp_sar_rxmax = -1;
++module_param_named(sar_rxmax, mp_sar_rxmax, int, 0);
++MODULE_PARM_DESC(sar_rxmax, "SAR RxMax size");
++
++int mp_sar_txbuf = -1;
++module_param_named(sar_txbuf, mp_sar_txbuf, int, 0);
++MODULE_PARM_DESC(sar_txbuf, "SAR TxBuf size");
++
++int mp_sar_txmax = -1;
++module_param_named(sar_txmax, mp_sar_txmax, int, 0);
++MODULE_PARM_DESC(sar_txmax, "SAR TxMax size");
++
++char *mp_modulation = NULL;
++module_param_named(modulation, mp_modulation, charp, 0);
++MODULE_PARM_DESC(modulation, "Modulation");
++
++int mp_fine_gain_control = -1;
++module_param_named(fine_gain_control, mp_fine_gain_control, int, 0);
++MODULE_PARM_DESC(fine_gain_control, "Fine gain control");
++
++int mp_fine_gain_value = -1;
++module_param_named(fine_gain_value, mp_fine_gain_value, int, 0);
++MODULE_PARM_DESC(fine_gain_value, "Fine gain value");
++
++int mp_enable_margin_retrain = -1;
++module_param_named(enable_margin_retrain, mp_enable_margin_retrain, int, 0);
++MODULE_PARM_DESC(enable_margin_retrain, "Enable margin retrain");
++
++int mp_margin_threshold = -1;
++module_param_named(margin_threshold, mp_margin_threshold, int, 0);
++MODULE_PARM_DESC(margin_threshold, "Margin retrain treshold");
++
++int mp_enable_rate_adapt = -1;
++module_param_named(enable_rate_adapt, mp_enable_rate_adapt, int, 0);
++MODULE_PARM_DESC(enable_rate_adapt, "Enable rate adaption");
++
++int mp_powercutback = -1;
++module_param_named(powercutback, mp_powercutback, int, 0);
++MODULE_PARM_DESC(powercutback, "Enable / disable powercutback");
++
++int mp_trellis = -1;
++module_param_named(trellis, mp_trellis, int, 0);
++MODULE_PARM_DESC(trellis, "Enable / disable trellis coding");
++
++int mp_bitswap = -1;
++module_param_named(bitswap, mp_bitswap, int, 0);
++MODULE_PARM_DESC(bitswap, "Enable / disable bitswap");
++
++int mp_maximum_bits_per_carrier = -1;
++module_param_named(maximum_bits_per_carrier, mp_maximum_bits_per_carrier, int, 0);
++MODULE_PARM_DESC(maximum_bits_per_carrier, "Maximum bits per carrier");
++
++int mp_maximum_interleave_depth = -1;
++module_param_named(maximum_interleave_depth, mp_maximum_interleave_depth, int, 0);
++MODULE_PARM_DESC(maximum_interleave_depth, "Maximum interleave depth");
++
++int mp_pair_selection = -1;
++module_param_named(pair_selection, mp_pair_selection, int, 0);
++MODULE_PARM_DESC(pair_selection, "Pair selection");
++
++int mp_dgas_polarity = -1;
++module_param_named(dgas_polarity, mp_dgas_polarity, int, 0);
++MODULE_PARM_DESC(dgas_polarity, "DGAS polarity");
++
++int mp_los_alarm = -1;
++module_param_named(los_alarm, mp_los_alarm, int, 0);
++MODULE_PARM_DESC(los_alarm, "LOS alarm");
++
++char *mp_eoc_vendor_id = NULL;
++module_param_named(eoc_vendor_id, mp_eoc_vendor_id, charp, 0);
++MODULE_PARM_DESC(eoc_vendor_id, "EOC vendor id");
++
++int mp_eoc_vendor_revision = -1;
++module_param_named(eoc_vendor_revision, mp_eoc_vendor_revision, int, 0);
++MODULE_PARM_DESC(eoc_vendor_revision, "EOC vendor revision");
++
++char *mp_eoc_vendor_serialnum = NULL;
++module_param_named(eoc_vendor_serialnum, mp_eoc_vendor_serialnum, charp, 0);
++MODULE_PARM_DESC(eoc_vendor_serialnum, "EOC vendor serial number");
++
++char *mp_invntry_vernum = NULL;
++module_param_named(invntry_vernum, mp_invntry_vernum, charp, 0);
++MODULE_PARM_DESC(invntry_vernum, "Inventory revision number");
++
++int mp_dsl_bit_tmode = -1;
++module_param_named(dsl_bit_tmode, mp_dsl_bit_tmode, int, 0);
++MODULE_PARM_DESC(dsl_bit_tmode, "DSL bit training mode");
++
++int mp_high_precision = -1;
++module_param_named(high_precision, mp_high_precision, int, 0);
++MODULE_PARM_DESC(high_precision, "High precision");
++
++int mp_autopvc_enable = -1;
++module_param_named(autopvc_enable, mp_autopvc_enable, int, 0);
++MODULE_PARM_DESC(autopvc_enable, "Enable / disable automatic PVC");
++
++int mp_oam_lb_timeout = -1;
++module_param_named(oam_lb_timeout, mp_oam_lb_timeout, int, 0);
++MODULE_PARM_DESC(oam_lb_timeout, "OAM LB timeout");
+ #endif
+
+ #ifndef TRUE
+@@ -728,9 +868,9 @@ static int __init tn7atm_irq_request (st
+ * interrupt pacing
+ */
+ ptr = prom_getenv ("sar_ipacemax");
+- if (ptr)
++ if (ptr || mp_sar_ipacemax != -1)
+ {
+- def_sar_inter_pace = os_atoi (ptr);
++ def_sar_inter_pace = mp_sar_ipacemax == -1 ? os_atoi (ptr) : mp_sar_ipacemax;
+ }
+ /* avalanche_request_pacing (priv->sar_irq, ATM_SAR_INT_PACING_BLOCK_NUM,
+ def_sar_inter_pace); */
+@@ -880,7 +1020,7 @@ static int __init tn7atm_get_ESI (struct
+ char esi_addr[ESI_LEN] = { 0x00, 0x00, 0x11, 0x22, 0x33, 0x44 };
+ char *esiaddr_str = NULL;
+
+- esiaddr_str = prom_getenv ("macc");
++ esiaddr_str = mp_macc ? mp_macc : prom_getenv ("maca");
+
+ if (!esiaddr_str)
+ {
+@@ -2139,15 +2279,15 @@ static int tn7atm_autoDetectDspBoost (vo
+ //UR8_MERGE_END CQ10450*
+
+ cp = prom_getenv ("dsp_noboost");
+- if (cp)
++ if (cp || mp_dsp_noboost != -1)
+ {
+- dsp_noboost = os_atoi (cp);
++ dsp_noboost = mp_dsp_noboost == -1 ? os_atoi (cp) : mp_dsp_noboost;
+ }
+
+ cp = (char *) prom_getenv ("dsp_freq");
+- if (cp)
++ if (cp || mp_dsp_freq != -1)
+ {
+- dspfreq = os_atoi (cp);
++ dspfreq = mp_dsp_freq == -1 ? os_atoi (cp) : mp_dsp_freq;
+ if (dspfreq == 250)
+ {
+ boostDsp = 1;
+@@ -2396,15 +2536,17 @@ static int __init tn7atm_init (struct at
+ // Inter-Op DSL phy Control
+ // Note the setting of _dsl_Feature_0 and _dsl_Feature_1 must before
+ // dslhal_api_dslStartup (in tn7dsl_init()).
+- if ((ptr = prom_getenv ("DSL_FEATURE_CNTL_0")) != NULL)
++ if ((ptr = prom_getenv ("DSL_FEATURE_CNTL_0")) != NULL || mp_featctl0 != NULL)
+ {
+- _dsl_Feature_0 = os_atoih (ptr);
++ if (mp_featctl0 != NULL) ptr = mp_featctl0;
++ _dsl_Feature_0 = os_atoh (ptr);
+ _dsl_Feature_0_defined = 1;
+ }
+
+- if ((ptr = prom_getenv ("DSL_FEATURE_CNTL_1")) != NULL)
++ if ((ptr = prom_getenv ("DSL_FEATURE_CNTL_1")) != NULL || mp_featctl1 != NULL)
+ {
+- _dsl_Feature_1 = os_atoih (ptr);
++ if (mp_featctl1 != NULL) ptr = mp_featctl1;
++ _dsl_Feature_1 = os_atoh (ptr);
+ _dsl_Feature_1_defined = 1;
+ }
+
+@@ -2412,15 +2554,17 @@ static int __init tn7atm_init (struct at
+ // DSL phy Feature Control
+ // Note the setting of _dsl_PhyControl_0 and _dsl_PhyControl_1 must before
+ // dslhal_api_dslStartup (in tn7dsl_init()).
+- if ((ptr = prom_getenv ("DSL_PHY_CNTL_0")) != NULL)
++ if ((ptr = prom_getenv ("DSL_PHY_CNTL_0")) != NULL || mp_phyctl0 != NULL)
+ {
+- _dsl_PhyControl_0 = os_atoih (ptr);
++ if (mp_phyctl0 != NULL) ptr = mp_phyctl0;
++ _dsl_PhyControl_0 = os_atoh (ptr);
+ _dsl_PhyControl_0_defined = 1;
+ }
+
+- if ((ptr = prom_getenv ("DSL_PHY_CNTL_1")) != NULL)
++ if ((ptr = prom_getenv ("DSL_PHY_CNTL_1")) != NULL || mp_phyctl1 != NULL)
+ {
+- _dsl_PhyControl_1 = os_atoih (ptr);
++ if (mp_phyctl1 != NULL) ptr = mp_phyctl1;
++ _dsl_PhyControl_1 = os_atoh (ptr);
+ _dsl_PhyControl_1_defined = 1;
+ }
+
+@@ -2440,12 +2584,12 @@ static int __init tn7atm_init (struct at
+ // read config for turbo dsl
+
+ ptr = prom_getenv ("TurboDSL");
+- if (ptr)
++ if (ptr || mp_turbodsl != -1)
+ {
+ #if 1 //[KT]
+ bTurboDsl = os_atoi (ptr);
+ #else
+- priv->bTurboDsl = os_atoi (ptr);
++ priv->bTurboDsl = mp_turbodsl == -1 ? os_atoi (ptr) : mp_turbodsl;
+ #endif
+ }
+ else
+@@ -2459,33 +2603,33 @@ static int __init tn7atm_init (struct at
+ priv->sarRxBuf = RX_BUFFER_NUM;
+ ptr = NULL;
+ ptr = prom_getenv ("SarRxBuf");
+- if (ptr)
++ if (ptr || mp_sar_rxbuf != -1)
+ {
+- priv->sarRxBuf = os_atoi (ptr);
++ priv->sarRxBuf = mp_sar_rxbuf == -1 ? os_atoi (ptr) : mp_sar_rxbuf;
+ }
+
+ priv->sarRxMax = RX_SERVICE_MAX;
+ ptr = NULL;
+ ptr = prom_getenv ("SarRxMax");
+- if (ptr)
++ if (ptr || mp_sar_rxmax != -1)
+ {
+- priv->sarRxMax = os_atoi (ptr);
++ priv->sarRxMax = mp_sar_rxmax == -1 ? os_atoi (ptr) : mp_sar_rxmax;
+ }
+
+ priv->sarTxBuf = TX_BUFFER_NUM;
+ ptr = NULL;
+ ptr = prom_getenv ("SarTxBuf");
+- if (ptr)
++ if (ptr || mp_sar_txbuf != -1)
+ {
+- priv->sarTxBuf = os_atoi (ptr);
++ priv->sarTxBuf = mp_sar_txbuf == -1 ? os_atoi (ptr) : mp_sar_txbuf;
+ }
+
+ priv->sarTxMax = TX_SERVICE_MAX;
+ ptr = NULL;
+ ptr = prom_getenv ("SarTxMax");
+- if (ptr)
++ if (ptr || mp_sar_txmax != -1)
+ {
+- priv->sarTxMax = os_atoi (ptr);
++ priv->sarTxMax = mp_sar_txmax == -1 ? os_atoi (ptr) : mp_sar_txmax;
+ }
+
+ #ifdef AR7_EFM
+--- a/tn7dsl.c
++++ b/tn7dsl.c
+@@ -148,6 +148,27 @@
+ #define NEW_TRAINING_VAL_T1413 128
+ #define NEW_TRAINING_VAL_MMODE 255
+
++extern char *mp_modulation;
++extern int mp_fine_gain_control;
++extern int mp_fine_gain_value;
++extern int mp_enable_margin_retrain;
++extern int mp_margin_threshold;
++extern int mp_enable_rate_adapt;
++extern int mp_powercutback;
++extern int mp_trellis;
++extern int mp_bitswap;
++extern int mp_maximum_bits_per_carrier;
++extern int mp_maximum_interleave_depth;
++extern int mp_pair_selection;
++extern int mp_dgas_polarity;
++extern int mp_los_alarm;
++extern char *mp_eoc_vendor_id;
++extern int mp_eoc_vendor_revision;
++extern char *mp_eoc_vendor_serialnum;
++extern char *mp_invntry_vernum;
++extern int mp_dsl_bit_tmode;
++extern int mp_high_precision;
++
+ int testflag1 = 0;
+ extern int __guDbgLevel;
+ extern sar_stat_t sarStat;
+@@ -2933,24 +2954,24 @@ static int tn7dsl_set_dsl(void)
+ (unsigned char *) &oamFeature, 4);
+
+ ptr = prom_getenv("DSL_FEATURE_CNTL_0");
+- if(!ptr)
+- prom_setenv("DSL_FEATURE_CNTL_0", "0x00004000");
++ //if(!ptr)
++ //prom_setenv("DSL_FEATURE_CNTL_0", "0x00004000");
+
+ ptr = prom_getenv("DSL_FEATURE_CNTL_1");
+- if(!ptr)
+- prom_setenv("DSL_FEATURE_CNTL_1", "0x00000000");
++ //if(!ptr)
++ //prom_setenv("DSL_FEATURE_CNTL_1", "0x00000000");
+
+ ptr = prom_getenv("DSL_PHY_CNTL_0");
+- if(!ptr)
+- prom_setenv("DSL_PHY_CNTL_0", "0x00000400");
++ //if(!ptr)
++ //prom_setenv("DSL_PHY_CNTL_0", "0x00000400");
+
+ ptr = prom_getenv("enable_margin_retrain");
+- if(!ptr)
+- prom_setenv("enable_margin_retrain", "0");
++ //if(!ptr)
++ //prom_setenv("enable_margin_retrain", "0");
+
+ ptr = prom_getenv("modulation");
+- if(!ptr)
+- prom_setenv("modulation", "0xbf");
++ //if(!ptr)
++ //prom_setenv("modulation", "0xbf");
+
+ #define EOC_VENDOR_ID "4200534153000000"
+ #define EOC_VENDOR_REVISION "FW370090708b1_55"
+@@ -2959,25 +2980,25 @@ static int tn7dsl_set_dsl(void)
+ ptr = prom_getenv("eoc_vendor_id");
+ if(!ptr || strcmp(ptr,EOC_VENDOR_ID) != 0 || strlen(ptr) != strlen(EOC_VENDOR_ID))
+ {
+- if(ptr)
+- prom_unsetenv("eoc_vendor_id");
+- prom_setenv("eoc_vendor_id",EOC_VENDOR_ID);
++ //if(ptr)
++ //prom_unsetenv("eoc_vendor_id");
++ //prom_setenv("eoc_vendor_id",EOC_VENDOR_ID);
+ }
+
+ ptr = prom_getenv("eoc_vendor_revision");
+ if(!ptr || strcmp(ptr,EOC_VENDOR_REVISION) != 0 || strlen(ptr) != strlen(EOC_VENDOR_REVISION))
+ {
+- if(ptr)
+- prom_unsetenv("eoc_vendor_revision");
+- prom_setenv("eoc_vendor_revision",EOC_VENDOR_REVISION);
++ //if(ptr)
++ //prom_unsetenv("eoc_vendor_revision");
++ //prom_setenv("eoc_vendor_revision",EOC_VENDOR_REVISION);
+ }
+
+ ptr = prom_getenv("eoc_vendor_serialnum");
+ if(!ptr || strcmp(ptr,EOC_VENDOR_SERIALNUM) != 0 || strlen(ptr) != strlen(EOC_VENDOR_SERIALNUM))
+ {
+- if(ptr)
+- prom_unsetenv("eoc_vendor_serialnum");
+- prom_setenv("eoc_vendor_serialnum",EOC_VENDOR_SERIALNUM);
++ //if(ptr)
++ // prom_unsetenv("eoc_vendor_serialnum");
++ //prom_setenv("eoc_vendor_serialnum",EOC_VENDOR_SERIALNUM);
+ }
+
+ /* Do only if we are in the new Base PSP 7.4.*/
+@@ -2994,92 +3015,88 @@ static int tn7dsl_set_dsl(void)
+ we clear the modulation environment variable, as this could potentially
+ not have the same meaning in the new mode.
+ */
+- prom_unsetenv("modulation");
+- prom_setenv("DSL_UPG_DONE", "1");
++ //prom_unsetenv("modulation");
++ //prom_setenv("DSL_UPG_DONE", "1");
+ }
+ }
+ #endif
+
+ // modulation
+ ptr = prom_getenv("modulation");
+- if (ptr)
++ if (ptr || mp_modulation != NULL)
+ {
+- tn7dsl_set_modulation(ptr, FALSE);
++ tn7dsl_set_modulation(mp_modulation == NULL ? ptr : mp_modulation, FALSE);
+ }
+
+ // Fine Gains
+ ptr = prom_getenv("fine_gain_control");
+- if (ptr)
++ if (ptr || mp_fine_gain_control != -1)
+ {
+- value = os_atoi(ptr);
++ value = mp_fine_gain_control == -1 ? os_atoi(ptr) : mp_fine_gain_control;
+ tn7dsl_ctrl_fineGain(value);
+ }
+ ptr = NULL;
+ ptr = prom_getenv("fine_gain_value");
+- if(ptr)
+- tn7dsl_set_fineGainValue(os_atoh(ptr));
++ if(ptr || mp_fine_gain_value != -1)
++ tn7dsl_set_fineGainValue(mp_fine_gain_value == -1 ? os_atoh(ptr) : mp_fine_gain_value);
+
+ // margin retrain
+ ptr = NULL;
+ ptr = prom_getenv("enable_margin_retrain");
+- if(ptr)
++ value = mp_enable_margin_retrain == -1 ? (ptr ? os_atoi(ptr) : 0) : mp_enable_margin_retrain;
++
++ if (value == 1)
+ {
+- value = os_atoi(ptr);
+- if(value == 1)
++ dslhal_api_setMarginMonitorFlags(pIhw, 0, 1);
++ bMarginRetrainEnable = 1;
++ //printk("enable showtime margin monitor.\n");
++
++ ptr = NULL;
++ ptr = prom_getenv("margin_threshold");
++ value = mp_margin_threshold == -1 ? (ptr ? os_atoi(ptr) : 0) : mp_margin_threshold;
++
++ if(value >= 0)
+ {
+- dslhal_api_setMarginMonitorFlags(pIhw, 0, 1);
+- bMarginRetrainEnable = 1;
+- //printk("enable showtime margin monitor.\n");
+- ptr = NULL;
+- ptr = prom_getenv("margin_threshold");
+- if(ptr)
+- {
+- value = os_atoi(ptr);
+- //printk("Set margin threshold to %d x 0.5 db\n",value);
+- if(value >= 0)
+- {
+- dslhal_api_setMarginThreshold(pIhw, value);
+- bMarginThConfig=1;
+- }
+- }
++ dslhal_api_setMarginThreshold(pIhw, value);
++ bMarginThConfig=1;
+ }
+ }
+
+ // rate adapt
+ ptr = NULL;
+ ptr = prom_getenv("enable_rate_adapt");
+- if(ptr)
++ if(ptr || mp_enable_rate_adapt != -1)
+ {
+- dslhal_api_setRateAdaptFlag(pIhw, os_atoi(ptr));
++ dslhal_api_setRateAdaptFlag(pIhw, mp_enable_rate_adapt == -1 ? os_atoi(ptr) : mp_enable_rate_adapt);
+ }
+
+ // set powercutback
+ ptr = NULL;
+ ptr = prom_getenv("powercutback");
+- if(ptr)
++ if(ptr || mp_powercutback != -1)
+ {
+- dslhal_advcfg_onOffPcb(pIhw, os_atoi(ptr));
++ dslhal_advcfg_onOffPcb(pIhw, mp_powercutback == -1 ? os_atoi(ptr) : mp_powercutback);
+ }
+
+ // trellis
+ ptr = NULL;
+ ptr = prom_getenv("trellis");
+- if(ptr)
++ if(ptr || mp_trellis != -1)
+ {
+- dslhal_api_setTrellisFlag(pIhw, os_atoi(ptr));
+- trellis = os_atoi(ptr);
++ trellis = mp_trellis == -1 ? os_atoi(ptr) : mp_trellis;
++ dslhal_api_setTrellisFlag(pIhw, trellis);
+ //printk("trellis=%d\n");
+ }
+
+ // bitswap
+ ptr = NULL;
+ ptr = prom_getenv("bitswap");
+- if(ptr)
++ if(ptr || mp_bitswap != -1)
+ {
+ int offset[2] = {33, 0};
+ unsigned int bitswap;
+
+- bitswap = os_atoi(ptr);
++ bitswap = mp_bitswap == -1 ? os_atoi(ptr) : mp_bitswap;
+
+ tn7dsl_generic_read(2, offset);
+ dslReg &= dslhal_support_byteSwap32(0xFFFFFF00);
+@@ -3097,46 +3114,47 @@ static int tn7dsl_set_dsl(void)
+ // maximum bits per carrier
+ ptr = NULL;
+ ptr = prom_getenv("maximum_bits_per_carrier");
+- if(ptr)
++ if(ptr || mp_maximum_bits_per_carrier != -1)
+ {
+- dslhal_api_setMaxBitsPerCarrierUpstream(pIhw, os_atoi(ptr));
++ dslhal_api_setMaxBitsPerCarrierUpstream(pIhw, mp_maximum_bits_per_carrier == -1 ? os_atoi(ptr) : mp_maximum_bits_per_carrier);
+ }
+
+ // maximum interleave depth
+ ptr = NULL;
+ ptr = prom_getenv("maximum_interleave_depth");
+- if(ptr)
++ if(ptr || mp_maximum_interleave_depth != -1)
+ {
+- dslhal_api_setMaxInterleaverDepth(pIhw, os_atoi(ptr));
++ dslhal_api_setMaxInterleaverDepth(pIhw, mp_maximum_interleave_depth == -1 ? os_atoi(ptr) : mp_maximum_interleave_depth);
+ }
+
+ // inner and outer pairs
+ ptr = NULL;
+ ptr = prom_getenv("pair_selection");
+- if(ptr)
++ if(ptr || mp_pair_selection != -1)
+ {
+- dslhal_api_selectInnerOuterPair(pIhw, os_atoi(ptr));
++ dslhal_api_selectInnerOuterPair(pIhw, mp_pair_selection == -1 ? os_atoi(ptr) : mp_pair_selection);
+ }
+
+ ptr = NULL;
+ ptr = prom_getenv("dgas_polarity");
+- if(ptr)
++ if(ptr || mp_dgas_polarity != -1)
+ {
+ dslhal_api_configureDgaspLpr(pIhw, 1, 1);
+- dslhal_api_configureDgaspLpr(pIhw, 0, os_atoi(ptr));
++ dslhal_api_configureDgaspLpr(pIhw, 0, mp_dgas_polarity == -1 ? os_atoi(ptr) : mp_dgas_polarity);
+ }
+
+ ptr = NULL;
+ ptr = prom_getenv("los_alarm");
+- if(ptr)
++ if(ptr || mp_los_alarm != -1)
+ {
+- dslhal_api_disableLosAlarm(pIhw, os_atoi(ptr));
++ dslhal_api_disableLosAlarm(pIhw, mp_los_alarm == -1 ? os_atoi(ptr) : mp_los_alarm);
+ }
+
+ ptr = NULL;
+ ptr = prom_getenv("eoc_vendor_id");
+- if(ptr)
++ if(ptr || mp_eoc_vendor_id != NULL)
+ {
++ ptr = mp_eoc_vendor_id == NULL ? ptr : mp_eoc_vendor_id;
+ for(i=0;i<8;i++)
+ {
+ tmp[0]=ptr[i*2];
+@@ -3161,26 +3179,26 @@ static int tn7dsl_set_dsl(void)
+ }
+ ptr = NULL;
+ ptr = prom_getenv("eoc_vendor_revision");
+- if(ptr)
++ if(ptr || mp_eoc_vendor_revision != -1)
+ {
+- value = os_atoi(ptr);
++ value = mp_eoc_vendor_revision == -1 ? os_atoi(ptr) : mp_eoc_vendor_revision;
+ //printk("eoc rev=%d\n", os_atoi(ptr));
+ dslhal_api_setEocRevisionNumber(pIhw, (char *)&value);
+
+ }
+ ptr = NULL;
+ ptr = prom_getenv("eoc_vendor_serialnum");
+- if(ptr)
++ if(ptr || mp_eoc_vendor_serialnum != NULL)
+ {
+- dslhal_api_setEocSerialNumber(pIhw, ptr);
++ dslhal_api_setEocSerialNumber(pIhw, mp_eoc_vendor_serialnum == NULL ? ptr : mp_eoc_vendor_serialnum);
+ }
+
+ // CQ10037 Added invntry_vernum environment variable to be able to set version number in ADSL2, ADSL2+ modes.
+ ptr = NULL;
+ ptr = prom_getenv("invntry_vernum");
+- if(ptr)
++ if(ptr || mp_invntry_vernum != NULL)
+ {
+- dslhal_api_setEocRevisionNumber(pIhw, ptr);
++ dslhal_api_setEocRevisionNumber(pIhw, mp_invntry_vernum == NULL ? ptr : mp_invntry_vernum);
+ }
+
+ return 0;
+@@ -3225,7 +3243,7 @@ int tn7dsl_init(void *priv)
+ * backward compatibility.
+ */
+ cp = prom_getenv("DSL_BIT_TMODE");
+- if (cp)
++ if (cp || mp_dsl_bit_tmode != -1)
+ {
+ printk("%s : env var DSL_BIT_TMODE is set\n", __FUNCTION__);
+ /*
+@@ -3254,9 +3272,9 @@ int tn7dsl_init(void *priv)
+
+ // UR8_MERGE_START CQ11054 Jack Zhang
+ cp = prom_getenv("high_precision");
+- if (cp)
++ if (cp || mp_high_precision != -1)
+ {
+- high_precision_selected = os_atoi(cp);
++ high_precision_selected = mp_high_precision == -1 ? os_atoi(cp) : mp_high_precision;
+ }
+ if ( high_precision_selected)
+ {
+--- a/tn7sar.c
++++ b/tn7sar.c
+@@ -76,6 +76,8 @@ typedef void OS_SETUP;
+ #include "tn7atm.h"
+ #include "tn7api.h"
+
++extern int mp_oam_lb_timeout;
++extern int mp_autopvc_enable;
+
+ /* PDSP Firmware files */
+ #include "tnetd7300_sar_firm.h"
+@@ -932,9 +934,9 @@ int tn7sar_setup_oam_channel(Tn7AtmPriva
+ pHalDev = (HAL_DEVICE *)priv->pSarHalDev;
+
+ pauto_pvc = prom_getenv("autopvc_enable");
+- if(pauto_pvc) //CQ10273
++ if(pauto_pvc || mp_autopvc_enable != -1) //CQ10273
+ {
+- auto_pvc =tn7sar_strtoul(pauto_pvc, NULL, 10);
++ auto_pvc = mp_autopvc_enable == -1 ? tn7sar_strtoul(pauto_pvc, NULL, 10) : mp_autopvc_enable;
+ }
+
+ memset(&chInfo, 0xff, sizeof(chInfo));
+@@ -1133,9 +1135,9 @@ int tn7sar_init(struct atm_dev *dev, Tn7
+
+ /* read in oam lb timeout value */
+ pLbTimeout = prom_getenv("oam_lb_timeout");
+- if(pLbTimeout)
++ if(pLbTimeout || mp_oam_lb_timeout != -1)
+ {
+- lbTimeout =tn7sar_strtoul(pLbTimeout, NULL, 10);
++ lbTimeout = mp_oam_lb_timeout == -1 ? tn7sar_strtoul(pLbTimeout, NULL, 10) : mp_oam_lb_timeout;
+ oamLbTimeout = lbTimeout;
+ pHalFunc->Control(pHalDev,"OamLbTimeout", "Set", &lbTimeout);
+ }
diff --git a/package/ar7-atm/patches-D7.05.01.00/170-bus_id_removal.patch b/package/ar7-atm/patches-D7.05.01.00/170-bus_id_removal.patch
new file mode 100644
index 000000000..6692f40f6
--- /dev/null
+++ b/package/ar7-atm/patches-D7.05.01.00/170-bus_id_removal.patch
@@ -0,0 +1,30 @@
+--- a/tn7dsl.c
++++ b/tn7dsl.c
+@@ -117,6 +117,7 @@
+ #include <linux/vmalloc.h>
+ #include <linux/file.h>
+ #include <linux/firmware.h>
++#include <linux/version.h>
+
+ #include <asm/io.h>
+ #include <asm/ar7/ar7.h>
+@@ -492,7 +493,9 @@ static void avsar_release(struct device
+ }
+
+ static struct device avsar = {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
+ .bus_id = "vlynq",
++#endif
+ .release = avsar_release,
+ };
+
+@@ -501,6 +504,9 @@ int shim_osLoadFWImage(unsigned char *pt
+ const struct firmware *fw_entry;
+ size_t size;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
++ dev_set_name(&avsar, "avsar");
++#endif
+ printk("requesting firmware image \"ar0700xx.bin\"\n");
+ if(device_register(&avsar) < 0) {
+ printk(KERN_ERR
diff --git a/package/ar7-atm/patches-D7.05.01.00/180-git_headers_include.patch b/package/ar7-atm/patches-D7.05.01.00/180-git_headers_include.patch
new file mode 100644
index 000000000..feb6ea860
--- /dev/null
+++ b/package/ar7-atm/patches-D7.05.01.00/180-git_headers_include.patch
@@ -0,0 +1,54 @@
+--- a/tn7atm.c
++++ b/tn7atm.c
+@@ -76,10 +76,16 @@
+ #include <linux/proc_fs.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
++#include <linux/version.h>
+
+ #include <asm/io.h>
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
+ #include <asm/ar7/ar7.h>
+ #include <asm/ar7/prom.h>
++#else
++#include <asm/mach-ar7/ar7.h>
++#include <asm/mach-ar7/prom.h>
++#endif
+
+ #include "dsl_hal_api.h"
+ #ifdef AR7_EFM
+--- a/tn7dsl.c
++++ b/tn7dsl.c
+@@ -120,8 +120,13 @@
+ #include <linux/version.h>
+
+ #include <asm/io.h>
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
+ #include <asm/ar7/ar7.h>
+ #include <asm/ar7/prom.h>
++#else
++#include <asm/mach-ar7/ar7.h>
++#include <asm/mach-ar7/prom.h>
++#endif
+
+ /* Modules specific header files */
+ #ifdef AR7_EFM
+--- a/tn7sar.c
++++ b/tn7sar.c
+@@ -53,10 +53,16 @@
+ #include <linux/proc_fs.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
++#include <linux/version.h>
+
+ #include <asm/io.h>
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
+ #include <asm/ar7/ar7.h>
+ #include <asm/ar7/prom.h>
++#else
++#include <asm/mach-ar7/ar7.h>
++#include <asm/mach-ar7/prom.h>
++#endif
+
+ #define _CPHAL_AAL5
+ #define _CPHAL_SAR
diff --git a/package/ar7-atm/patches-D7.05.01.00/190-2.6.32_proc_fixes.patch b/package/ar7-atm/patches-D7.05.01.00/190-2.6.32_proc_fixes.patch
new file mode 100644
index 000000000..52ebbc152
--- /dev/null
+++ b/package/ar7-atm/patches-D7.05.01.00/190-2.6.32_proc_fixes.patch
@@ -0,0 +1,79 @@
+--- a/tn7dsl.c
++++ b/tn7dsl.c
+@@ -215,7 +215,11 @@ led_reg_t ledreg[2];
+ static struct led_funcs ledreg[2];
+ #endif
+
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
+ #define DEV_DSLMOD CTL_UNNUMBERED
++#else
++#define DEV_DSLMOD 0
++#endif
+ #define MAX_STR_SIZE 256
+ #define DSL_MOD_SIZE 256
+
+@@ -3615,9 +3619,16 @@ static int dslmod_sysctl(ctl_table *ctl,
+ */
+ if(write)
+ {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
+ ret = proc_dostring(ctl, write, filp, buffer, lenp, 0);
+-
++#else
++ ret = proc_dostring(ctl, write, buffer, lenp, 0);
++#endif
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
+ switch (ctl->ctl_name)
++#else
++ switch ((long)ctl->extra2)
++#endif
+ {
+ case DEV_DSLMOD:
+ ptr = strpbrk(info, " \t");
+@@ -3701,14 +3712,29 @@ static int dslmod_sysctl(ctl_table *ctl,
+ else
+ {
+ len += sprintf(info+len, mod_req);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
+ ret = proc_dostring(ctl, write, filp, buffer, lenp, 0);
++#else
++ ret = proc_dostring(ctl, write, buffer, lenp, 0);
++#endif
+ }
+ return ret;
+ }
+
+
+ ctl_table dslmod_table[] = {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
+ {DEV_DSLMOD, "dslmod", info, DSL_MOD_SIZE, 0644, NULL, NULL, &dslmod_sysctl, &sysctl_string}
++#else
++ {
++ .procname = "dslmod",
++ .data = info,
++ .maxlen = DSL_MOD_SIZE,
++ .mode = 0644,
++ .proc_handler = &dslmod_sysctl,
++ .extra2 = (void *)DEV_DSLMOD,
++ }
++#endif
+ ,
+ {0}
+ };
+@@ -3716,7 +3742,16 @@ ctl_table dslmod_table[] = {
+ /* Make sure that /proc/sys/dev is there */
+ ctl_table dslmod_root_table[] = {
+ #ifdef CONFIG_PROC_FS
++ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
+ {CTL_DEV, "dev", NULL, 0, 0555, dslmod_table}
++ #else
++ {
++ .procname = "dev",
++ .maxlen = 0,
++ .mode = 0555,
++ .child = dslmod_table,
++ }
++ #endif
+ ,
+ #endif /* CONFIG_PROC_FS */
+ {0}
diff --git a/package/ar7-atm/patches-D7.05.01.00/200-2.6.37_args.patch b/package/ar7-atm/patches-D7.05.01.00/200-2.6.37_args.patch
new file mode 100644
index 000000000..a3bff1b94
--- /dev/null
+++ b/package/ar7-atm/patches-D7.05.01.00/200-2.6.37_args.patch
@@ -0,0 +1,36 @@
+--- a/tn7atm.c
++++ b/tn7atm.c
+@@ -2000,7 +2000,11 @@ static int __init tn7atm_register (Tn7At
+
+ dgprintf (4, "device %s being registered\n", priv->name);
+
++ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
+ mydev = atm_dev_register (priv->proc_name, &tn7atm_ops, -1, NULL);
++ #else
++ mydev = atm_dev_register (priv->proc_name, NULL, &tn7atm_ops, -1, NULL);
++ #endif
+
+ if (mydev == NULL)
+ {
+--- a/tn7dsl.c
++++ b/tn7dsl.c
+@@ -512,14 +512,17 @@ int shim_osLoadFWImage(unsigned char *pt
+ {
+ const struct firmware *fw_entry;
+ size_t size;
++ int ret;
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
+ dev_set_name(&avsar, "avsar");
+ #endif
+ printk("requesting firmware image \"ar0700xx.bin\"\n");
+- if(device_register(&avsar) < 0) {
++ dev_set_name(&avsar, "avsar");
++ ret = device_register(&avsar);
++ if (ret < 0) {
+ printk(KERN_ERR
+- "avsar: device_register fails\n");
++ "avsar: device_register fails, error%i\n", ret);
+ return -1;
+ }
+
diff --git a/package/ar7-atm/patches-D7.05.01.00/210-3.3-remove-smp_lock.h.patch b/package/ar7-atm/patches-D7.05.01.00/210-3.3-remove-smp_lock.h.patch
new file mode 100644
index 000000000..975ebaf29
--- /dev/null
+++ b/package/ar7-atm/patches-D7.05.01.00/210-3.3-remove-smp_lock.h.patch
@@ -0,0 +1,33 @@
+--- a/tn7atm.c
++++ b/tn7atm.c
+@@ -72,7 +72,7 @@
+ #include <linux/atmdev.h>
+ #include <linux/delay.h>
+ #include <linux/spinlock.h>
+-#include <linux/smp_lock.h>
++#include <linux/interrupt.h>
+ #include <linux/proc_fs.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
+--- a/tn7sar.c
++++ b/tn7sar.c
+@@ -49,7 +49,7 @@
+ #include <linux/atmdev.h>
+ #include <linux/delay.h>
+ #include <linux/spinlock.h>
+-#include <linux/smp_lock.h>
++#include <linux/interrupt.h>
+ #include <linux/proc_fs.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
+--- a/tn7dsl.c
++++ b/tn7dsl.c
+@@ -108,7 +108,7 @@
+ #include <linux/atmdev.h>
+ #include <linux/delay.h>
+ #include <linux/spinlock.h>
+-#include <linux/smp_lock.h>
++#include <linux/interrupt.h>
+ #include <linux/proc_fs.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
diff --git a/package/arptables/Makefile b/package/arptables/Makefile
new file mode 100644
index 000000000..9d61813a2
--- /dev/null
+++ b/package/arptables/Makefile
@@ -0,0 +1,42 @@
+# Copyright (C) 2006-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=arptables
+PKG_VERSION:=0.0.3-4
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-v$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/ebtables
+PKG_MD5SUM:=1d4ab05761f063b0751645d8f2b8f8e5
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-v$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/arptables
+ SECTION:=net
+ CATEGORY:=Network
+ SUBMENU:=Firewall
+ TITLE:=ARP firewalling software
+ DEPENDS:=+kmod-arptables
+ URL:=http://ebtables.sourceforge.net
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ COPT_FLAGS="$(TARGET_CFLAGS)" \
+ KERNEL_DIR="./include/linux"
+endef
+
+define Package/arptables/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(CP) $(PKG_BUILD_DIR)/$(PKG_NAME) $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,arptables))
diff --git a/package/arptables/patches/100-always_optimize.patch b/package/arptables/patches/100-always_optimize.patch
new file mode 100644
index 000000000..b120eb783
--- /dev/null
+++ b/package/arptables/patches/100-always_optimize.patch
@@ -0,0 +1,19 @@
+Index: arptables-v0.0.3-4/libarptc/libarptc_incl.c
+===================================================================
+--- arptables-v0.0.3-4.orig/libarptc/libarptc_incl.c 2010-03-08 16:49:28.000000000 +0100
++++ arptables-v0.0.3-4/libarptc/libarptc_incl.c 2012-08-14 12:10:29.527945144 +0200
+@@ -11,14 +11,6 @@
+ /* (C)1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See
+ COPYING for details). */
+
+-#ifndef __OPTIMIZE__
+-STRUCT_ENTRY_TARGET *
+-GET_TARGET(STRUCT_ENTRY *e)
+-{
+- return (void *)e + e->target_offset;
+-}
+-#endif
+-
+ static int sockfd = -1;
+ static void *arptc_fn = NULL;
+
diff --git a/package/avila-wdt/Makefile b/package/avila-wdt/Makefile
new file mode 100644
index 000000000..5bf6bf4ad
--- /dev/null
+++ b/package/avila-wdt/Makefile
@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2008 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=avila-wdt
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/avila-wdt
+ SUBMENU:=Other modules
+ TITLE:=GPIO hardware watchdog driver for modified Avila boards
+ DEPENDS:=@GPIO_SUPPORT @TARGET_ixp4xx
+ FILES:=$(PKG_BUILD_DIR)/avila-wdt.ko
+ AUTOLOAD:=$(call AutoLoad,10,avila-wdt)
+endef
+
+MAKE_OPTS:= \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ SUBDIRS="$(PKG_BUILD_DIR)"
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ $(MAKE) -C "$(LINUX_DIR)" \
+ $(MAKE_OPTS) \
+ modules
+endef
+
+$(eval $(call KernelPackage,avila-wdt))
diff --git a/package/avila-wdt/src/Makefile b/package/avila-wdt/src/Makefile
new file mode 100644
index 000000000..90d90657e
--- /dev/null
+++ b/package/avila-wdt/src/Makefile
@@ -0,0 +1 @@
+obj-m := avila-wdt.o
diff --git a/package/avila-wdt/src/avila-wdt.c b/package/avila-wdt/src/avila-wdt.c
new file mode 100644
index 000000000..981f3857a
--- /dev/null
+++ b/package/avila-wdt/src/avila-wdt.c
@@ -0,0 +1,231 @@
+/*
+ * avila-wdt.c
+ * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+ *
+ * based on:
+ * drivers/char/watchdog/ixp4xx_wdt.c
+ *
+ * Watchdog driver for Intel IXP4xx network processors
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2004 (c) MontaVista, Software, Inc.
+ * Based on sa1100 driver, Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/uaccess.h>
+#include <mach/hardware.h>
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+static int heartbeat = 20; /* (secs) Default is 20 seconds */
+static unsigned long wdt_status;
+static atomic_t wdt_counter;
+struct timer_list wdt_timer;
+
+#define WDT_IN_USE 0
+#define WDT_OK_TO_CLOSE 1
+#define WDT_RUNNING 2
+
+static void wdt_refresh(unsigned long data)
+{
+ if (test_bit(WDT_RUNNING, &wdt_status)) {
+ if (atomic_dec_and_test(&wdt_counter)) {
+ printk(KERN_WARNING "Avila watchdog expired, expect a reboot soon!\n");
+ clear_bit(WDT_RUNNING, &wdt_status);
+ return;
+ }
+ }
+
+ /* strobe to the watchdog */
+ gpio_line_set(14, IXP4XX_GPIO_HIGH);
+ gpio_line_set(14, IXP4XX_GPIO_LOW);
+
+ mod_timer(&wdt_timer, jiffies + msecs_to_jiffies(500));
+}
+
+static void wdt_enable(void)
+{
+ atomic_set(&wdt_counter, heartbeat * 2);
+
+ /* Disable clock generator output on GPIO 14/15 */
+ *IXP4XX_GPIO_GPCLKR &= ~(1 << 8);
+
+ /* activate GPIO 14 out */
+ gpio_line_config(14, IXP4XX_GPIO_OUT);
+ gpio_line_set(14, IXP4XX_GPIO_LOW);
+
+ if (!test_bit(WDT_RUNNING, &wdt_status))
+ wdt_refresh(0);
+ set_bit(WDT_RUNNING, &wdt_status);
+}
+
+static void wdt_disable(void)
+{
+ /* Re-enable clock generator output on GPIO 14/15 */
+ *IXP4XX_GPIO_GPCLKR |= (1 << 8);
+}
+
+static int avila_wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(WDT_IN_USE, &wdt_status))
+ return -EBUSY;
+
+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+ wdt_enable();
+ return nonseekable_open(inode, file);
+}
+
+static ssize_t
+avila_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+ if (len) {
+ if (!nowayout) {
+ size_t i;
+
+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+ for (i = 0; i != len; i++) {
+ char c;
+
+ if (get_user(c, data + i))
+ return -EFAULT;
+ if (c == 'V')
+ set_bit(WDT_OK_TO_CLOSE, &wdt_status);
+ }
+ }
+ wdt_enable();
+ }
+ return len;
+}
+
+static struct watchdog_info ident = {
+ .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE |
+ WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+ .identity = "Avila Watchdog",
+};
+
+
+static long avila_wdt_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret = -ENOTTY;
+ int time;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ ret = copy_to_user((struct watchdog_info *)arg, &ident,
+ sizeof(ident)) ? -EFAULT : 0;
+ break;
+
+ case WDIOC_GETSTATUS:
+ ret = put_user(0, (int *)arg);
+ break;
+
+ case WDIOC_KEEPALIVE:
+ wdt_enable();
+ ret = 0;
+ break;
+
+ case WDIOC_SETTIMEOUT:
+ ret = get_user(time, (int *)arg);
+ if (ret)
+ break;
+
+ if (time <= 0 || time > 60) {
+ ret = -EINVAL;
+ break;
+ }
+
+ heartbeat = time;
+ wdt_enable();
+ /* Fall through */
+
+ case WDIOC_GETTIMEOUT:
+ ret = put_user(heartbeat, (int *)arg);
+ break;
+ }
+ return ret;
+}
+
+static int avila_wdt_release(struct inode *inode, struct file *file)
+{
+ if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
+ wdt_disable();
+ else
+ printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
+ "timer will not stop\n");
+ clear_bit(WDT_IN_USE, &wdt_status);
+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+ return 0;
+}
+
+
+static const struct file_operations avila_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = avila_wdt_write,
+ .unlocked_ioctl = avila_wdt_ioctl,
+ .open = avila_wdt_open,
+ .release = avila_wdt_release,
+};
+
+static struct miscdevice avila_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR + 1,
+ .name = "avila_watchdog",
+ .fops = &avila_wdt_fops,
+};
+
+static int __init avila_wdt_init(void)
+{
+ int ret;
+
+ init_timer(&wdt_timer);
+ wdt_timer.expires = 0;
+ wdt_timer.data = 0;
+ wdt_timer.function = wdt_refresh;
+ ret = misc_register(&avila_wdt_miscdev);
+ if (ret == 0)
+ printk(KERN_INFO "Avila Watchdog Timer: heartbeat %d sec\n",
+ heartbeat);
+ return ret;
+}
+
+static void __exit avila_wdt_exit(void)
+{
+ misc_deregister(&avila_wdt_miscdev);
+ del_timer(&wdt_timer);
+ wdt_disable();
+}
+
+
+module_init(avila_wdt_init);
+module_exit(avila_wdt_exit);
+
+MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>");
+MODULE_DESCRIPTION("Gateworks Avila Hardware Watchdog");
+
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 20s)");
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
diff --git a/package/base-files/Makefile b/package/base-files/Makefile
new file mode 100644
index 000000000..1d56e9fc7
--- /dev/null
+++ b/package/base-files/Makefile
@@ -0,0 +1,155 @@
+#
+# Copyright (C) 2007-2012 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+include $(INCLUDE_DIR)/version.mk
+
+PKG_NAME:=base-files
+PKG_RELEASE:=117
+
+PKG_FILE_DEPENDS:=$(PLATFORM_DIR)/ $(GENERIC_PLATFORM_DIR)/base-files/
+PKG_BUILD_DEPENDS:=opkg/host
+
+include $(INCLUDE_DIR)/package.mk
+
+ifneq ($(DUMP),1)
+ TARGET:=-$(BOARD)
+ ifneq ($(wildcard $(PLATFORM_DIR)/base-files-$(PROFILE) $(PLATFORM_SUBDIR)/base-files-$(PROFILE)),)
+ TARGET:=$(TARGET)-$(PROFILE)
+ endif
+endif
+
+define Package/base-files
+ SECTION:=base
+ CATEGORY:=Base system
+ DEPENDS:=+netifd +libc
+ TITLE:=Base filesystem for OpenWrt
+ URL:=http://openwrt.org/
+ VERSION:=$(PKG_RELEASE)-$(REVISION)
+endef
+
+define Package/base-files/conffiles
+/etc/hosts
+/etc/inittab
+/etc/group
+/etc/passwd
+/etc/shadow
+/etc/profile
+/etc/shells
+/etc/sysctl.conf
+/etc/rc.local
+/etc/sysupgrade.conf
+/etc/config/
+/etc/dropbear/
+/etc/crontabs/
+$(call $(TARGET)/conffiles)
+endef
+
+define Package/base-files/description
+ This package contains a base filesystem and system scripts for OpenWrt.
+endef
+
+ifneq ($(CONFIG_PREINITOPT),)
+define ImageConfigOptions
+ mkdir -p $(1)/lib/preinit
+ echo 'pi_suppress_stderr="$(CONFIG_TARGET_PREINIT_SUPPRESS_STDERR)"' >$(1)/lib/preinit/00_preinit.conf
+ echo 'fs_failsafe_wait_timeout=$(if $(CONFIG_TARGET_PREINIT_TIMEOUT),$(CONFIG_TARGET_PREINIT_TIMEOUT),2)' >>$(1)/lib/preinit/00_preinit.conf
+ echo 'pi_init_path=$(if $(CONFIG_TARGET_INIT_PATH),$(CONFIG_TARGET_INIT_PATH),"/bin:/sbin:/usr/bin:/usr/sbin")' >>$(1)/lib/preinit/00_preinit.conf
+ echo 'pi_init_env=$(if $(CONFIG_TARGET_INIT_ENV),$(CONFIG_TARGET_INIT_ENV),"")' >>$(1)/lib/preinit/00_preinit.conf
+ echo 'pi_init_cmd=$(if $(CONFIG_TARGET_INIT_CMD),$(CONFIG_TARGET_INIT_CMD),"/sbin/init")' >>$(1)/lib/preinit/00_preinit.conf
+ echo 'pi_init_suppress_stderr="$(CONFIG_TARGET_INIT_SUPPRESS_STDERR)"' >>$(1)/lib/preinit/00_preinit.conf
+ echo 'pi_ifname=$(if $(CONFIG_TARGET_PREINIT_IFNAME),$(CONFIG_TARGET_PREINIT_IFNAME),"")' >>$(1)/lib/preinit/00_preinit.conf
+ echo 'pi_ip=$(if $(CONFIG_TARGET_PREINIT_IP),$(CONFIG_TARGET_PREINIT_IP),"192.168.1.1")' >>$(1)/lib/preinit/00_preinit.conf
+ echo 'pi_netmask=$(if $(CONFIG_TARGET_PREINIT_NETMASK),$(CONFIG_TARGET_PREINIT_NETMASK),"255.255.255.0")' >>$(1)/lib/preinit/00_preinit.conf
+ echo 'pi_broadcast=$(if $(CONFIG_TARGET_PREINIT_BROADCAST),$(CONFIG_TARGET_PREINIT_BROADCAST),"192.168.1.255")' >>$(1)/lib/preinit/00_preinit.conf
+ echo 'pi_preinit_net_messages="$(CONFIG_TARGET_PREINIT_SHOW_NETMSG)"' >>$(1)/lib/preinit/00_preinit.conf
+ echo 'pi_preinit_no_failsafe_netmsg="$(CONFIG_TARGET_PREINIT_SUPPRESS_FAILSAFE_NETMSG)"' >>$(1)/lib/preinit/00_preinit.conf
+endef
+endif
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+endef
+
+define Build/Compile/Default
+
+endef
+Build/Compile = $(Build/Compile/Default)
+
+define Package/base-files/install
+ $(CP) ./files/* $(1)/
+ if [ -d $(GENERIC_PLATFORM_DIR)/base-files/. ]; then \
+ $(CP) $(GENERIC_PLATFORM_DIR)/base-files/* $(1)/; \
+ fi
+ if [ -d $(PLATFORM_DIR)/base-files/. ]; then \
+ $(CP) $(PLATFORM_DIR)/base-files/* $(1)/; \
+ fi
+ if [ -d $(PLATFORM_DIR)/base-files-$(PROFILE)/. ]; then \
+ $(CP) $(PLATFORM_DIR)/base-files-$(PROFILE)/* $(1)/; \
+ fi
+ if [ -d $(PLATFORM_DIR)/$(PROFILE)/base-files/. ]; then \
+ $(CP) $(PLATFORM_DIR)/$(PROFILE)/base-files/* $(1)/; \
+ fi
+ $(if $(filter-out $(PLATFORM_DIR),$(PLATFORM_SUBDIR)), \
+ if [ -d $(PLATFORM_SUBDIR)/base-files/. ]; then \
+ $(CP) $(PLATFORM_SUBDIR)/base-files/* $(1)/; \
+ fi; \
+ if [ -d $(PLATFORM_SUBDIR)/base-files-$(PROFILE)/. ]; then \
+ $(CP) $(PLATFORM_SUBDIR)/base-files-$(PROFILE)/* $(1)/; \
+ fi; \
+ if [ -d $(PLATFORM_SUBDIR)/$(PROFILE)/base-files/. ]; then \
+ $(CP) $(PLATFORM_SUBDIR)/$(PROFILE)/base-files/* $(1)/; \
+ fi \
+ )
+
+ $(VERSION_SED) \
+ $(1)/etc/banner \
+ $(1)/etc/openwrt_version \
+ $(1)/etc/openwrt_release
+
+ mkdir -p $(1)/CONTROL
+ mkdir -p $(1)/dev
+ mkdir -p $(1)/etc/crontabs
+ mkdir -p $(1)/etc/rc.d
+ mkdir -p $(1)/overlay
+ mkdir -p $(1)/lib/firmware
+ $(if $(LIB_SUFFIX),-ln -s lib $(1)/lib$(LIB_SUFFIX))
+ mkdir -p $(1)/mnt
+ mkdir -p $(1)/proc
+ mkdir -p $(1)/tmp
+ mkdir -p $(1)/usr/lib
+ $(if $(LIB_SUFFIX),-ln -s lib $(1)/usr/lib$(LIB_SUFFIX))
+ mkdir -p $(1)/usr/bin
+ mkdir -p $(1)/sys
+ mkdir -p $(1)/www
+ mkdir -p $(1)/root
+ ln -sf /proc/mounts $(1)/etc/mtab
+ rm -f $(1)/var
+ ln -sf /tmp $(1)/var
+ mkdir -p $(1)/etc
+ ln -sf /tmp/resolv.conf /tmp/fstab /tmp/TZ $(1)/etc/
+
+ chmod 0600 $(1)/etc/shadow
+ chmod 1777 $(1)/tmp
+
+ $(call ImageConfigOptions,$(1))
+ $(call Package/base-files/install-target,$(1))
+ for conffile in $(1)/etc/config/*; do \
+ if [ -f "$$$$conffile" ]; then \
+ grep "$$$${conffile##$(1)}" $(1)/CONTROL/conffiles || \
+ echo "$$$${conffile##$(1)}" >> $(1)/CONTROL/conffiles; \
+ fi \
+ done
+endef
+
+ifneq ($(DUMP),1)
+ -include $(PLATFORM_DIR)/base-files.mk
+endif
+
+$(eval $(call BuildPackage,base-files))
diff --git a/package/base-files/files/bin/ipcalc.sh b/package/base-files/files/bin/ipcalc.sh
new file mode 100755
index 000000000..d6ef16870
--- /dev/null
+++ b/package/base-files/files/bin/ipcalc.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+
+awk -f - $* <<EOF
+function bitcount(c) {
+ c=and(rshift(c, 1),0x55555555)+and(c,0x55555555)
+ c=and(rshift(c, 2),0x33333333)+and(c,0x33333333)
+ c=and(rshift(c, 4),0x0f0f0f0f)+and(c,0x0f0f0f0f)
+ c=and(rshift(c, 8),0x00ff00ff)+and(c,0x00ff00ff)
+ c=and(rshift(c,16),0x0000ffff)+and(c,0x0000ffff)
+ return c
+}
+
+function ip2int(ip) {
+ for (ret=0,n=split(ip,a,"\."),x=1;x<=n;x++) ret=or(lshift(ret,8),a[x])
+ return ret
+}
+
+function int2ip(ip,ret,x) {
+ ret=and(ip,255)
+ ip=rshift(ip,8)
+ for(;x<3;ret=and(ip,255)"."ret,ip=rshift(ip,8),x++);
+ return ret
+}
+
+BEGIN {
+ slpos=index(ARGV[1],"/")
+ if (slpos == 0) {
+ ipaddr=ip2int(ARGV[1])
+ netmask=ip2int(ARGV[2])
+ } else {
+ ipaddr=ip2int(substr(ARGV[1],0,slpos-1))
+ netmask=compl(2**(32-int(substr(ARGV[1],slpos+1)))-1)
+ ARGV[4]=ARGV[3]
+ ARGV[3]=ARGV[2]
+ }
+
+ network=and(ipaddr,netmask)
+ broadcast=or(network,compl(netmask))
+
+ start=or(network,and(ip2int(ARGV[3]),compl(netmask)))
+ limit=network+1
+ if (start<limit) start=limit
+
+ end=start+ARGV[4]
+ limit=or(network,compl(netmask))-1
+ if (end>limit) end=limit
+
+ print "IP="int2ip(ipaddr)
+ print "NETMASK="int2ip(netmask)
+ print "BROADCAST="int2ip(broadcast)
+ print "NETWORK="int2ip(network)
+ print "PREFIX="32-bitcount(compl(netmask))
+
+ # range calculations:
+ # ipcalc <ip> <netmask> <start> <num>
+
+ if (ARGC > 3) {
+ print "START="int2ip(start)
+ print "END="int2ip(end)
+ }
+}
+EOF
diff --git a/package/base-files/files/bin/login.sh b/package/base-files/files/bin/login.sh
new file mode 100755
index 000000000..04b3fe250
--- /dev/null
+++ b/package/base-files/files/bin/login.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+# Copyright (C) 2006-2011 OpenWrt.org
+
+if ( ! grep -qs '^root:[!x]\?:' /etc/shadow || \
+ ! grep -qs '^root:[!x]\?:' /etc/passwd ) && \
+ [ -z "$FAILSAFE" ]
+then
+ echo "Login failed."
+ exit 0
+else
+cat << EOF
+ === IMPORTANT ============================
+ Use 'passwd' to set your login password
+ this will disable telnet and enable SSH
+ ------------------------------------------
+EOF
+fi
+
+exec /bin/ash --login
diff --git a/package/base-files/files/etc/banner b/package/base-files/files/etc/banner
new file mode 100644
index 000000000..058cb5573
--- /dev/null
+++ b/package/base-files/files/etc/banner
@@ -0,0 +1,16 @@
+ _______ ________ __
+ | |.-----.-----.-----.| | | |.----.| |_
+ | - || _ | -__| || | | || _|| _|
+ |_______|| __|_____|__|__||________||__| |____|
+ |__| W I R E L E S S F R E E D O M
+ -----------------------------------------------------
+ ATTITUDE ADJUSTMENT (%C, %R)
+ -----------------------------------------------------
+ * 1/4 oz Vodka Pour all ingredients into mixing
+ * 1/4 oz Gin tin with ice, strain into glass.
+ * 1/4 oz Amaretto
+ * 1/4 oz Triple sec
+ * 1/4 oz Peach schnapps
+ * 1/4 oz Sour mix
+ * 1 splash Cranberry juice
+ -----------------------------------------------------
diff --git a/package/base-files/files/etc/config/network b/package/base-files/files/etc/config/network
new file mode 100644
index 000000000..a35fd2ef9
--- /dev/null
+++ b/package/base-files/files/etc/config/network
@@ -0,0 +1,14 @@
+# Copyright (C) 2006 OpenWrt.org
+
+config interface loopback
+ option ifname lo
+ option proto static
+ option ipaddr 127.0.0.1
+ option netmask 255.0.0.0
+
+config interface lan
+ option ifname eth0
+ option type bridge
+ option proto static
+ option ipaddr 192.168.1.1
+ option netmask 255.255.255.0
diff --git a/package/base-files/files/etc/config/system b/package/base-files/files/etc/config/system
new file mode 100644
index 000000000..d2124e417
--- /dev/null
+++ b/package/base-files/files/etc/config/system
@@ -0,0 +1,10 @@
+config system
+ option hostname OpenWrt
+ option timezone UTC
+
+config timeserver ntp
+ list server 0.openwrt.pool.ntp.org
+ list server 1.openwrt.pool.ntp.org
+ list server 2.openwrt.pool.ntp.org
+ list server 3.openwrt.pool.ntp.org
+ option enable_server 0
diff --git a/package/base-files/files/etc/diag.sh b/package/base-files/files/etc/diag.sh
new file mode 100644
index 000000000..8726a4398
--- /dev/null
+++ b/package/base-files/files/etc/diag.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+# Copyright (C) 2006-2009 OpenWrt.org
+
+set_state() { :; }
diff --git a/package/base-files/files/etc/functions.sh b/package/base-files/files/etc/functions.sh
new file mode 120000
index 000000000..13b3190e7
--- /dev/null
+++ b/package/base-files/files/etc/functions.sh
@@ -0,0 +1 @@
+../lib/functions.sh \ No newline at end of file
diff --git a/package/base-files/files/etc/group b/package/base-files/files/etc/group
new file mode 100644
index 000000000..d36685139
--- /dev/null
+++ b/package/base-files/files/etc/group
@@ -0,0 +1,10 @@
+root:x:0:
+daemon:x:1:
+adm:x:4:
+mail:x:8:
+audio:x:29:
+www-data:x:33:
+ftp:x:55:
+users:x:100:
+network:x:101:
+nogroup:x:65534:
diff --git a/package/base-files/files/etc/hosts b/package/base-files/files/etc/hosts
new file mode 100644
index 000000000..75721cd5a
--- /dev/null
+++ b/package/base-files/files/etc/hosts
@@ -0,0 +1 @@
+127.0.0.1 localhost
diff --git a/package/base-files/files/etc/hotplug.d/ieee1394/10-ieee1394 b/package/base-files/files/etc/hotplug.d/ieee1394/10-ieee1394
new file mode 100644
index 000000000..7e142a211
--- /dev/null
+++ b/package/base-files/files/etc/hotplug.d/ieee1394/10-ieee1394
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# Copyright (C) 2009 OpenWrt.org
+
+case "$ACTION" in
+ add)
+ # update LEDs
+ ;;
+ remove)
+ # update LEDs
+ ;;
+esac
+
diff --git a/package/base-files/files/etc/hotplug.d/usb/10-usb b/package/base-files/files/etc/hotplug.d/usb/10-usb
new file mode 100644
index 000000000..7e142a211
--- /dev/null
+++ b/package/base-files/files/etc/hotplug.d/usb/10-usb
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# Copyright (C) 2009 OpenWrt.org
+
+case "$ACTION" in
+ add)
+ # update LEDs
+ ;;
+ remove)
+ # update LEDs
+ ;;
+esac
+
diff --git a/package/base-files/files/etc/hotplug2-common.rules b/package/base-files/files/etc/hotplug2-common.rules
new file mode 100644
index 000000000..c284f8f3f
--- /dev/null
+++ b/package/base-files/files/etc/hotplug2-common.rules
@@ -0,0 +1,43 @@
+
+# uncomment me to log hotplug events
+# DEVPATH is set {
+# exec logger -s -t hotplug -p daemon.info "name=%DEVNAME%, path=%DEVPATH%"
+# }
+
+$include /etc/hotplug2-platform.rules
+
+DEVNAME ~~ (^null$|^full$|^ptmx$|^zero$|^gpio|^hvc) {
+ makedev /dev/%DEVNAME% 0666
+ next-event
+}
+
+DEVNAME == mapper/control {
+ makedev /dev/%DEVNAME% 0600
+ next-event
+}
+
+ACTION == add, DEVPATH is set {
+ makedev /dev/%DEVNAME% 0644
+}
+
+ACTION == add, DEVPATH is set, DEVNAME ~~ ^tty {
+ chmod 0666 /dev/%DEVNAME%
+}
+
+ACTION == add, DEVPATH is set, DEVNAME ~~ ^ppp {
+ chmod 0600 /dev/%DEVNAME%
+}
+
+ACTION == remove, DEVPATH is set, MAJOR is set, MINOR is set {
+ remove /dev/%DEVNAME%
+}
+
+FIRMWARE is set, ACTION == add {
+ exec /sbin/hotplug-call firmware
+ load-firmware /lib/firmware
+ next-event
+}
+
+SUBSYSTEM == platform {
+ exec /sbin/hotplug-call %SUBSYSTEM%
+}
diff --git a/package/base-files/files/etc/hotplug2-init.rules b/package/base-files/files/etc/hotplug2-init.rules
new file mode 100644
index 000000000..f01169776
--- /dev/null
+++ b/package/base-files/files/etc/hotplug2-init.rules
@@ -0,0 +1,5 @@
+$include /etc/hotplug2-common.rules
+
+SUBSYSTEM == button {
+ exec kill -USR1 1
+}
diff --git a/package/base-files/files/etc/init.d/boot b/package/base-files/files/etc/init.d/boot
new file mode 100755
index 000000000..43837a80f
--- /dev/null
+++ b/package/base-files/files/etc/init.d/boot
@@ -0,0 +1,103 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006-2011 OpenWrt.org
+
+START=10
+STOP=98
+
+system_config() {
+ local cfg="$1"
+
+ local hostname conloglevel timezone
+
+ config_get hostname "$cfg" hostname 'OpenWrt'
+ echo "$hostname" > /proc/sys/kernel/hostname
+
+ config_get conloglevel "$cfg" conloglevel
+ config_get buffersize "$cfg" buffersize
+ [ -z "$conloglevel" -a -z "$buffersize" ] || dmesg ${conloglevel:+-n $conloglevel} ${buffersize:+-s $buffersize}
+
+ config_get timezone "$cfg" timezone 'UTC'
+ echo "$timezone" > /tmp/TZ
+
+ config_get zonename "$cfg" zonename
+ [ -n "$zonename" ] && [ -f "/usr/share/zoneinfo/$zonename" ] && ln -s "/usr/share/zoneinfo/$zonename" /tmp/localtime
+
+ # apply timezone to kernel
+ date -k
+
+ if [ -x /sbin/syslogd ]; then
+ local args log_ip log_size log_port log_type log_file
+ config_get log_ip "$cfg" log_ip
+ config_get log_size "$cfg" log_size 16
+ config_get log_port "$cfg" log_port 514
+ config_get log_type "$cfg" log_type circular
+ config_get log_file "$cfg" log_file "/var/log/messages"
+ args="${log_ip:+-L -R ${log_ip}:${log_port}} ${conloglevel:+-l $conloglevel}"
+ if [ "$log_type" = "file" ]; then
+ args="$args -s $log_size -O $log_file -S"
+ else
+ args="$args -C${log_size}"
+ fi
+ service_start /sbin/syslogd $args
+ fi
+ if [ -x /sbin/klogd ]; then
+ config_get klogconloglevel "$cfg" klogconloglevel
+ args="${klogconloglevel:+-c $klogconloglevel}"
+ service_start /sbin/klogd $args
+ fi
+}
+
+apply_uci_config() {
+ sh -c '. /lib/functions.sh; include /lib/config; uci_apply_defaults'
+}
+
+start() {
+ [ -f /proc/mounts ] || /sbin/mount_root
+ [ -f /proc/jffs2_bbc ] && echo "S" > /proc/jffs2_bbc
+ [ -f /proc/net/vlan/config ] && vconfig set_name_type DEV_PLUS_VID_NO_PAD
+
+ mkdir -p /var/run
+ mkdir -p /var/log
+ mkdir -p /var/lock
+ mkdir -p /var/state
+ mkdir -p /tmp/.uci
+ chmod 0700 /tmp/.uci
+ touch /var/log/wtmp
+ touch /var/log/lastlog
+ touch /tmp/resolv.conf.auto
+ ln -sf /tmp/resolv.conf.auto /tmp/resolv.conf
+ grep -q debugfs /proc/filesystems && mount -t debugfs debugfs /sys/kernel/debug
+ [ "$FAILSAFE" = "true" ] && touch /tmp/.failsafe
+
+ load_modules /etc/modules.d/*
+
+ # allow wifi modules time to settle
+ sleep 1
+
+ /sbin/wifi detect > /tmp/wireless.tmp
+ [ -s /tmp/wireless.tmp ] && {
+ cat /tmp/wireless.tmp >> /etc/config/wireless
+ }
+ rm -f /tmp/wireless.tmp
+
+ apply_uci_config
+ config_load system
+ config_foreach system_config system
+
+ killall -q hotplug2
+ [ -x /sbin/hotplug2 ] && /sbin/hotplug2 --override --persistent \
+ --set-rules-file /etc/hotplug2.rules \
+ --set-coldplug-cmd /sbin/udevtrigger \
+ --max-children 1 >/dev/null 2>&1 &
+
+ # create /dev/root if it doesn't exist
+ [ -e /dev/root -o -h /dev/root ] || {
+ rootdev=$(awk 'BEGIN { RS=" "; FS="="; } $1 == "root" { print $2 }' < /proc/cmdline)
+ [ -n "$rootdev" ] && ln -s "$rootdev" /dev/root
+ }
+}
+
+stop() {
+ service_stop /sbin/klogd
+ service_stop /sbin/syslogd
+}
diff --git a/package/base-files/files/etc/init.d/done b/package/base-files/files/etc/init.d/done
new file mode 100755
index 000000000..827866912
--- /dev/null
+++ b/package/base-files/files/etc/init.d/done
@@ -0,0 +1,20 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+START=95
+boot() {
+ [ -d /tmp/root ] && {
+ lock /tmp/.switch2jffs
+ firstboot switch2jffs
+ lock -u /tmp/.switch2jffs
+ }
+
+ # process user commands
+ [ -f /etc/rc.local ] && {
+ sh /etc/rc.local
+ }
+
+ # set leds to normal state
+ . /etc/diag.sh
+ set_state done
+}
diff --git a/package/base-files/files/etc/init.d/led b/package/base-files/files/etc/init.d/led
new file mode 100755
index 000000000..43964bf0b
--- /dev/null
+++ b/package/base-files/files/etc/init.d/led
@@ -0,0 +1,80 @@
+#!/bin/sh /etc/rc.common
+# (C) 2008 openwrt.org
+
+START=96
+
+load_led() {
+ local name
+ local sysfs
+ local trigger
+ local dev
+ local mode
+ local default
+ local delayon
+ local delayoff
+ local interval
+
+ config_get sysfs $1 sysfs
+ config_get name $1 name "$sysfs"
+ config_get trigger $1 trigger "none"
+ config_get dev $1 dev
+ config_get mode $1 mode "link"
+ config_get_bool default $1 default "nil"
+ config_get delayon $1 delayon
+ config_get delayoff $1 delayoff
+ config_get interval $1 interval "50"
+ config_get port_state $1 port_state
+
+ [ -e /sys/class/leds/${sysfs}/brightness ] && {
+ echo "setting up led ${name}"
+ [ "$default" != nil ] && {
+ [ $default -eq 1 ] &&
+ echo 1 >/sys/class/leds/${sysfs}/brightness
+ [ $default -eq 1 ] ||
+ echo 0 >/sys/class/leds/${sysfs}/brightness
+ }
+ echo $trigger > /sys/class/leds/${sysfs}/trigger
+ case "$trigger" in
+ "netdev")
+ [ -n "$dev" ] && {
+ echo $dev > /sys/class/leds/${sysfs}/device_name
+ echo $mode > /sys/class/leds/${sysfs}/mode
+ }
+ ;;
+
+ "timer")
+ [ -n "$delayon" ] && \
+ echo $delayon > /sys/class/leds/${sysfs}/delay_on
+ [ -n "$delayoff" ] && \
+ echo $delayoff > /sys/class/leds/${sysfs}/delay_off
+ ;;
+
+ "usbdev")
+ [ -n "$dev" ] && {
+ echo $dev > /sys/class/leds/${sysfs}/device_name
+ echo $interval > /sys/class/leds/${sysfs}/activity_interval
+ }
+ ;;
+
+ "port_state")
+ [ -n "$port_state" ] && \
+ echo $port_state > /sys/class/leds/${sysfs}/port_state
+ ;;
+
+ switch[0-9]*)
+ local port_mask
+
+ config_get port_mask $1 port_mask
+ [ -n "$port_mask" ] && \
+ echo $port_mask > /sys/class/leds/${sysfs}/port_mask
+ ;;
+ esac
+ }
+}
+
+start() {
+ [ -e /sys/class/leds/ ] && {
+ config_load system
+ config_foreach load_led led
+ }
+}
diff --git a/package/base-files/files/etc/init.d/rcS b/package/base-files/files/etc/init.d/rcS
new file mode 100755
index 000000000..3ec9bfef6
--- /dev/null
+++ b/package/base-files/files/etc/init.d/rcS
@@ -0,0 +1,26 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+run_scripts() {
+ for i in /etc/rc.d/$1*; do
+ [ -x $i ] && $i $2 2>&1
+ done | $LOGGER
+}
+
+system_config() {
+ config_get_bool foreground $1 foreground 0
+}
+
+LOGGER="cat"
+[ -x /usr/bin/logger ] && LOGGER="logger -s -p 6 -t sysinit"
+
+. /lib/functions.sh
+
+config_load system
+config_foreach system_config system
+
+if [ "$1" = "S" -a "$foreground" != "1" ]; then
+ run_scripts "$1" "$2" &
+else
+ run_scripts "$1" "$2"
+fi
diff --git a/package/base-files/files/etc/init.d/sysctl b/package/base-files/files/etc/init.d/sysctl
new file mode 100755
index 000000000..239779055
--- /dev/null
+++ b/package/base-files/files/etc/init.d/sysctl
@@ -0,0 +1,7 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+START=99
+start() {
+ [ -f /etc/sysctl.conf ] && sysctl -p -e >&-
+}
diff --git a/package/base-files/files/etc/init.d/sysntpd b/package/base-files/files/etc/init.d/sysntpd
new file mode 100755
index 000000000..bb42ef7d3
--- /dev/null
+++ b/package/base-files/files/etc/init.d/sysntpd
@@ -0,0 +1,37 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2011 OpenWrt.org
+
+START=98
+
+SERVICE_DAEMONIZE=1
+SERVICE_WRITE_PID=1
+SERVICE_PID_FILE=/var/run/sysntpd.pid
+
+start() {
+ local peers
+ local args="-n"
+ local enable_server
+
+ config_load system
+ config_get peers ntp server
+ config_get_bool enable_server ntp enable_server 0
+
+ if [ $enable_server -ne 0 ]; then
+ append args "-l"
+ fi
+
+ if [ -n "$peers" ]; then
+ local peer
+ for peer in $peers; do
+ append args "-p $peer"
+ done
+ fi
+
+ if [ "$args" != "-n" ]; then
+ service_start /usr/sbin/ntpd $args
+ fi
+}
+
+stop() {
+ service_stop /usr/sbin/ntpd
+}
diff --git a/package/base-files/files/etc/init.d/umount b/package/base-files/files/etc/init.d/umount
new file mode 100755
index 000000000..5a750b93c
--- /dev/null
+++ b/package/base-files/files/etc/init.d/umount
@@ -0,0 +1,8 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+STOP=99
+stop() {
+ sync
+ umount -a -d -r
+}
diff --git a/package/base-files/files/etc/init.d/usb b/package/base-files/files/etc/init.d/usb
new file mode 100755
index 000000000..7b443b651
--- /dev/null
+++ b/package/base-files/files/etc/init.d/usb
@@ -0,0 +1,9 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+START=39
+start() {
+ [ -d /proc/bus/usb ] && {
+ /bin/mount -t usbfs none /proc/bus/usb
+ }
+}
diff --git a/package/base-files/files/etc/init.d/watchdog b/package/base-files/files/etc/init.d/watchdog
new file mode 100755
index 000000000..299c89142
--- /dev/null
+++ b/package/base-files/files/etc/init.d/watchdog
@@ -0,0 +1,13 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2008-2011 OpenWrt.org
+
+START=97
+
+start() {
+ [ -c /dev/watchdog ] || return 1
+ [ -x /sbin/watchdog ] || return 1
+ service_start /sbin/watchdog -t 5 /dev/watchdog
+}
+stop() {
+ service_stop /sbin/watchdog
+}
diff --git a/package/base-files/files/etc/inittab b/package/base-files/files/etc/inittab
new file mode 100644
index 000000000..ca90fd8a2
--- /dev/null
+++ b/package/base-files/files/etc/inittab
@@ -0,0 +1,4 @@
+::sysinit:/etc/init.d/rcS S boot
+::shutdown:/etc/init.d/rcS K shutdown
+ttyS0::askfirst:/bin/ash --login
+tty1::askfirst:/bin/ash --login
diff --git a/package/base-files/files/etc/openwrt_release b/package/base-files/files/etc/openwrt_release
new file mode 100644
index 000000000..8ad2d9d4f
--- /dev/null
+++ b/package/base-files/files/etc/openwrt_release
@@ -0,0 +1,6 @@
+DISTRIB_ID="%D"
+DISTRIB_RELEASE="%C"
+DISTRIB_REVISION="%R"
+DISTRIB_CODENAME="%n"
+DISTRIB_TARGET="%S"
+DISTRIB_DESCRIPTION="%D %N %V"
diff --git a/package/base-files/files/etc/openwrt_version b/package/base-files/files/etc/openwrt_version
new file mode 100644
index 000000000..4b14f596f
--- /dev/null
+++ b/package/base-files/files/etc/openwrt_version
@@ -0,0 +1 @@
+%V
diff --git a/package/base-files/files/etc/passwd b/package/base-files/files/etc/passwd
new file mode 100644
index 000000000..1d06a8036
--- /dev/null
+++ b/package/base-files/files/etc/passwd
@@ -0,0 +1,5 @@
+root:x:0:0:root:/root:/bin/ash
+daemon:*:1:1:daemon:/var:/bin/false
+ftp:*:55:55:ftp:/home/ftp:/bin/false
+network:*:101:101:network:/var:/bin/false
+nobody:*:65534:65534:nobody:/var:/bin/false
diff --git a/package/base-files/files/etc/preinit b/package/base-files/files/etc/preinit
new file mode 100755
index 000000000..0fdfa8cf8
--- /dev/null
+++ b/package/base-files/files/etc/preinit
@@ -0,0 +1,44 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin
+
+pi_ifname=
+pi_ip=192.168.1.1
+pi_broadcast=192.168.1.255
+pi_netmask=255.255.255.0
+
+fs_failsafe_ifname=
+fs_failsafe_ip=192.168.1.1
+fs_failsafe_broadcast=192.168.1.255
+fs_failsafe_netmask=255.255.255.0
+
+fs_failsafe_wait_timeout=2
+
+pi_suppress_stderr="y"
+pi_init_suppress_stderr="y"
+pi_init_path="/bin:/sbin:/usr/bin:/usr/sbin"
+pi_init_cmd="/sbin/init"
+
+. /lib/functions.sh
+. /lib/functions/boot.sh
+
+boot_hook_init preinit_essential
+boot_hook_init preinit_main
+boot_hook_init failsafe
+boot_hook_init initramfs
+boot_hook_init preinit_mount_root
+
+for pi_source_file in /lib/preinit/*; do
+ . $pi_source_file
+done
+
+boot_run_hook preinit_essential
+
+pi_mount_skip_next=false
+pi_jffs2_mount_success=false
+pi_failsafe_net_message=false
+
+boot_run_hook preinit_main
+
diff --git a/package/base-files/files/etc/profile b/package/base-files/files/etc/profile
new file mode 100644
index 000000000..171adc18e
--- /dev/null
+++ b/package/base-files/files/etc/profile
@@ -0,0 +1,15 @@
+#!/bin/sh
+[ -f /etc/banner ] && cat /etc/banner
+
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin
+export HOME=$(grep -e "^${USER:-root}:" /etc/passwd | cut -d ":" -f 6)
+export HOME=${HOME:-/root}
+export PS1='\u@\h:\w\$ '
+
+[ -x /bin/more ] || alias more=less
+[ -x /usr/bin/vim ] && alias vi=vim || alias vim=vi
+
+[ -z "$KSH_VERSION" -o \! -s /etc/mkshrc ] || . /etc/mkshrc
+
+[ -x /usr/bin/arp ] || arp() { cat /proc/net/arp; }
+[ -x /usr/bin/ldd ] || ldd() { LD_TRACE_LOADED_OBJECTS=1 $*; }
diff --git a/package/base-files/files/etc/protocols b/package/base-files/files/etc/protocols
new file mode 100644
index 000000000..53fecb6d3
--- /dev/null
+++ b/package/base-files/files/etc/protocols
@@ -0,0 +1,56 @@
+# Internet (IP) protocols
+#
+# Updated from http://www.iana.org/assignments/protocol-numbers and other
+# sources.
+# New protocols will be added on request if they have been officially
+# assigned by IANA and are not historical.
+# If you need a huge list of used numbers please install the nmap package.
+
+ip 0 IP # internet protocol, pseudo protocol number
+#hopopt 0 HOPOPT # IPv6 Hop-by-Hop Option [RFC1883]
+icmp 1 ICMP # internet control message protocol
+igmp 2 IGMP # Internet Group Management
+ggp 3 GGP # gateway-gateway protocol
+ipencap 4 IP-ENCAP # IP encapsulated in IP (officially ``IP'')
+st 5 ST # ST datagram mode
+tcp 6 TCP # transmission control protocol
+egp 8 EGP # exterior gateway protocol
+igp 9 IGP # any private interior gateway (Cisco)
+pup 12 PUP # PARC universal packet protocol
+udp 17 UDP # user datagram protocol
+hmp 20 HMP # host monitoring protocol
+xns-idp 22 XNS-IDP # Xerox NS IDP
+rdp 27 RDP # "reliable datagram" protocol
+iso-tp4 29 ISO-TP4 # ISO Transport Protocol class 4 [RFC905]
+xtp 36 XTP # Xpress Transfer Protocol
+ddp 37 DDP # Datagram Delivery Protocol
+idpr-cmtp 38 IDPR-CMTP # IDPR Control Message Transport
+ipv6 41 IPv6 # Internet Protocol, version 6
+ipv6-route 43 IPv6-Route # Routing Header for IPv6
+ipv6-frag 44 IPv6-Frag # Fragment Header for IPv6
+idrp 45 IDRP # Inter-Domain Routing Protocol
+rsvp 46 RSVP # Reservation Protocol
+gre 47 GRE # General Routing Encapsulation
+esp 50 IPSEC-ESP # Encap Security Payload [RFC2046]
+ah 51 IPSEC-AH # Authentication Header [RFC2402]
+skip 57 SKIP # SKIP
+ipv6-icmp 58 IPv6-ICMP # ICMP for IPv6
+ipv6-nonxt 59 IPv6-NoNxt # No Next Header for IPv6
+ipv6-opts 60 IPv6-Opts # Destination Options for IPv6
+rspf 73 RSPF CPHB # Radio Shortest Path First (officially CPHB)
+vmtp 81 VMTP # Versatile Message Transport
+eigrp 88 EIGRP # Enhanced Interior Routing Protocol (Cisco)
+ospf 89 OSPFIGP # Open Shortest Path First IGP
+ax.25 93 AX.25 # AX.25 frames
+ipip 94 IPIP # IP-within-IP Encapsulation Protocol
+etherip 97 ETHERIP # Ethernet-within-IP Encapsulation [RFC3378]
+encap 98 ENCAP # Yet Another IP encapsulation [RFC1241]
+# 99 # any private encryption scheme
+pim 103 PIM # Protocol Independent Multicast
+ipcomp 108 IPCOMP # IP Payload Compression Protocol
+vrrp 112 VRRP # Virtual Router Redundancy Protocol
+l2tp 115 L2TP # Layer Two Tunneling Protocol [RFC2661]
+isis 124 ISIS # IS-IS over IPv4
+sctp 132 SCTP # Stream Control Transmission Protocol
+fc 133 FC # Fibre Channel
+
diff --git a/package/base-files/files/etc/rc.common b/package/base-files/files/etc/rc.common
new file mode 100755
index 000000000..fa2df6cd2
--- /dev/null
+++ b/package/base-files/files/etc/rc.common
@@ -0,0 +1,85 @@
+#!/bin/sh
+# Copyright (C) 2006-2012 OpenWrt.org
+
+. $IPKG_INSTROOT/lib/functions.sh
+. $IPKG_INSTROOT/lib/functions/service.sh
+
+initscript=$1
+action=${2:-help}
+shift 2
+
+start() {
+ return 0
+}
+
+stop() {
+ return 0
+}
+
+reload() {
+ return 1
+}
+
+restart() {
+ trap '' TERM
+ stop "$@"
+ start "$@"
+}
+
+boot() {
+ start "$@"
+}
+
+shutdown() {
+ stop
+}
+
+disable() {
+ name="$(basename "${initscript}")"
+ rm -f "$IPKG_INSTROOT"/etc/rc.d/S??$name
+ rm -f "$IPKG_INSTROOT"/etc/rc.d/K??$name
+}
+
+enable() {
+ name="$(basename "${initscript}")"
+ disable
+ [ -n "$START" -o -n "$STOP" ] || {
+ echo "/etc/init.d/$name does not have a START or STOP value"
+ return 1
+ }
+ [ "$START" ] && ln -s "../init.d/$name" "$IPKG_INSTROOT/etc/rc.d/S${START}${name##S[0-9][0-9]}"
+ [ "$STOP" ] && ln -s "../init.d/$name" "$IPKG_INSTROOT/etc/rc.d/K${STOP}${name##K[0-9][0-9]}"
+}
+
+enabled() {
+ name="$(basename "${initscript}")"
+ [ -x "$IPKG_INSTROOT/etc/rc.d/S${START}${name##S[0-9][0-9]}" ]
+}
+
+depends() {
+ return 0
+}
+
+help() {
+ cat <<EOF
+Syntax: $initscript [command]
+
+Available commands:
+ start Start the service
+ stop Stop the service
+ restart Restart the service
+ reload Reload configuration files (or restart if that fails)
+ enable Enable service autostart
+ disable Disable service autostart
+$EXTRA_HELP
+EOF
+}
+
+${INIT_TRACE:+set -x}
+
+. "$initscript"
+
+ALL_COMMANDS="start stop reload restart boot shutdown enable disable enabled depends ${EXTRA_COMMANDS}"
+list_contains ALL_COMMANDS "$action" || action=help
+[ "$action" = "reload" ] && action='eval reload "$@" || restart "$@" && :'
+$action "$@"
diff --git a/package/base-files/files/etc/rc.local b/package/base-files/files/etc/rc.local
new file mode 100644
index 000000000..56394773c
--- /dev/null
+++ b/package/base-files/files/etc/rc.local
@@ -0,0 +1,4 @@
+# Put your custom commands here that should be executed once
+# the system init finished. By default this file does nothing.
+
+exit 0
diff --git a/package/base-files/files/etc/services b/package/base-files/files/etc/services
new file mode 100644
index 000000000..a12853efa
--- /dev/null
+++ b/package/base-files/files/etc/services
@@ -0,0 +1,171 @@
+echo 7/tcp
+echo 7/udp
+discard 9/tcp
+discard 9/udp
+daytime 13/tcp
+daytime 13/udp
+netstat 15/tcp
+chargen 19/tcp
+chargen 19/udp
+ftp-data 20/tcp
+ftp 21/tcp
+ssh 22/tcp
+ssh 22/udp
+telnet 23/tcp
+smtp 25/tcp
+time 37/tcp
+time 37/udp
+whois 43/tcp
+domain 53/tcp
+domain 53/udp
+bootps 67/tcp
+bootps 67/udp
+bootpc 68/tcp
+bootpc 68/udp
+tftp 69/udp
+finger 79/tcp
+www 80/tcp http
+kerberos 88/tcp kerberos5 krb5 kerberos-sec
+kerberos 88/udp kerberos5 krb5 kerberos-sec
+pop3 110/tcp
+pop3 110/udp
+sunrpc 111/tcp
+sunrpc 111/udp
+auth 113/tcp ident
+sftp 115/tcp
+nntp 119/tcp
+ntp 123/tcp
+ntp 123/udp
+netbios-ns 137/tcp
+netbios-ns 137/udp
+netbios-dgm 138/tcp
+netbios-dgm 138/udp
+netbios-ssn 139/tcp
+netbios-ssn 139/udp
+imap2 143/tcp imap
+imap2 143/udp imap
+snmp 161/tcp
+snmp 161/udp
+snmp-trap 162/tcp snmptrap
+snmp-trap 162/udp snmptrap
+xdmcp 177/tcp
+xdmcp 177/udp
+bgp 179/tcp
+bgp 179/udp
+imap3 220/tcp
+imap3 220/udp
+ldap 389/tcp
+ldap 389/udp
+https 443/tcp
+https 443/udp
+microsoft-ds 445/tcp
+microsoft-ds 445/udp
+isakmp 500/tcp
+isakmp 500/udp
+rtsp 554/tcp
+rtsp 554/udp
+ipp 631/tcp
+ipp 631/udp
+syslog 514/udp
+printer 515/tcp spooler
+dhcpv6-client 546/tcp
+dhcpv6-client 546/udp
+dhcpv6-server 547/tcp
+dhcpv6-server 547/udp
+afpovertcp 548/tcp
+afpovertcp 548/udp
+nntps 563/tcp snntp
+nntps 563/udp snntp
+ldaps 636/tcp
+ldaps 636/udp
+tinc 655/tcp
+tinc 655/udp
+rsync 873/tcp
+rsync 873/udp
+ftps-data 989/tcp
+ftps 990/tcp
+imaps 993/tcp
+imaps 993/udp
+ircs 994/tcp
+ircs 994/udp
+pop3s 995/tcp
+pop3s 995/udp
+socks 1080/tcp
+socks 1080/udp
+openvpn 1194/tcp
+openvpn 1194/udp
+l2f 1701/tcp l2tp
+l2f 1701/udp l2tp
+radius 1812/tcp
+radius 1812/udp
+radius-acct 1813/tcp radacct
+radius-acct 1813/udp radacct
+nfs 2049/tcp
+nfs 2049/udp
+dict 2628/tcp
+dict 2628/udp
+gpsd 2947/tcp
+gpsd 2947/udp
+icpv2 3130/tcp icp
+icpv2 3130/udp icp
+mysql 3306/tcp
+mysql 3306/udp
+nut 3493/tcp
+nut 3493/udp
+distcc 3632/tcp
+distcc 3632/udp
+daap 3689/tcp
+daap 3689/udp
+svn 3690/tcp subversion
+svn 3690/udp subversion
+epmd 4369/tcp
+epmd 4369/udp
+iax 4569/tcp
+iax 4569/udp
+mtn 4691/tcp
+mtn 4691/udp
+munin 4949/tcp
+sip 5060/tcp
+sip 5060/udp
+sip-tls 5061/tcp
+sip-tls 5061/udp
+xmpp-client 5222/tcp jabber-client
+xmpp-client 5222/udp jabber-client
+xmpp-server 5269/tcp jabber-server
+xmpp-server 5269/udp jabber-server
+mdns 5353/tcp
+mdns 5353/udp
+postgresql 5432/tcp postgres
+postgresql 5432/udp postgres
+x11 6000/tcp
+x11 6000/udp
+mysql-proxy 6446/tcp
+mysql-proxy 6446/udp
+bacula-dir 9101/tcp
+bacula-dir 9101/udp
+bacula-fd 9102/tcp
+bacula-fd 9102/udp
+bacula-sd 9103/tcp
+bacula-sd 9103/udp
+nbd 10809/tcp
+zabbix-agent 10050/tcp
+zabbix-agent 10050/udp
+zabbix-trapper 10051/tcp
+zabbix-trapper 10051/udp
+hkp 11371/tcp
+hkp 11371/udp
+ssmtp 465/tcp smtps
+spamd 783/tcp
+zebrasrv 2600/tcp
+zebra 2601/tcp
+ripd 2602/tcp
+ripngd 2603/tcp
+ospfd 2604/tcp
+bgpd 2605/tcp
+ospf6d 2606/tcp
+ospfapi 2607/tcp
+isisd 2608/tcp
+sane-port 6566/tcp sane saned
+ircd 6667/tcp
+git 9418/tcp
+
diff --git a/package/base-files/files/etc/shadow b/package/base-files/files/etc/shadow
new file mode 100644
index 000000000..e9898901b
--- /dev/null
+++ b/package/base-files/files/etc/shadow
@@ -0,0 +1,5 @@
+root:x:0:0:99999:7:::
+daemon:*:0:0:99999:7:::
+ftp:*:0:0:99999:7:::
+network:*:0:0:99999:7:::
+nobody:*:0:0:99999:7:::
diff --git a/package/base-files/files/etc/shells b/package/base-files/files/etc/shells
new file mode 100644
index 000000000..006aa38ce
--- /dev/null
+++ b/package/base-files/files/etc/shells
@@ -0,0 +1 @@
+/bin/ash
diff --git a/package/base-files/files/etc/sysctl.conf b/package/base-files/files/etc/sysctl.conf
new file mode 100644
index 000000000..4ea01bb4c
--- /dev/null
+++ b/package/base-files/files/etc/sysctl.conf
@@ -0,0 +1,27 @@
+kernel.panic=3
+net.ipv4.conf.default.arp_ignore=1
+net.ipv4.conf.all.arp_ignore=1
+net.ipv4.ip_forward=1
+net.ipv4.icmp_echo_ignore_broadcasts=1
+net.ipv4.icmp_ignore_bogus_error_responses=1
+net.ipv4.tcp_ecn=0
+net.ipv4.tcp_fin_timeout=30
+net.ipv4.tcp_keepalive_time=120
+net.ipv4.tcp_syncookies=1
+net.ipv4.tcp_timestamps=1
+net.ipv4.tcp_sack=1
+net.ipv4.tcp_dsack=1
+
+net.ipv6.conf.all.forwarding=1
+
+net.netfilter.nf_conntrack_acct=1
+net.netfilter.nf_conntrack_checksum=0
+net.netfilter.nf_conntrack_max=16384
+net.netfilter.nf_conntrack_tcp_timeout_established=3600
+net.netfilter.nf_conntrack_udp_timeout=60
+net.netfilter.nf_conntrack_udp_timeout_stream=180
+
+# disable bridge firewalling by default
+net.bridge.bridge-nf-call-arptables=0
+net.bridge.bridge-nf-call-ip6tables=0
+net.bridge.bridge-nf-call-iptables=0
diff --git a/package/base-files/files/etc/sysupgrade.conf b/package/base-files/files/etc/sysupgrade.conf
new file mode 100644
index 000000000..e06fd5e33
--- /dev/null
+++ b/package/base-files/files/etc/sysupgrade.conf
@@ -0,0 +1,5 @@
+## This file contains files and directories that should
+## be preserved during an upgrade.
+
+# /etc/example.conf
+# /etc/openvpn/
diff --git a/package/base-files/files/etc/uci-defaults/migrate-shadow b/package/base-files/files/etc/uci-defaults/migrate-shadow
new file mode 100644
index 000000000..b7ea5718c
--- /dev/null
+++ b/package/base-files/files/etc/uci-defaults/migrate-shadow
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+local ppwd="$(sed -ne '/^root:/s/^root:\([^:]*\):.*$/\1/p' /etc/passwd)"
+local spwd="$(sed -ne '/^root:/s/^root:\([^:]*\):.*$/\1/p' /etc/shadow)"
+
+if [ -n "${ppwd#[\!x]}" ] && [ -z "${spwd#[\!x]}" ]; then
+ logger -t migrate-shadow "Moving root password hash into shadow database"
+ sed -i -e "s:^root\:[^\:]*\::root\:x\::" /etc/passwd
+ sed -i -e "s:^root\:[^\:]*\::root\:$ppwd\::" /etc/shadow
+fi
+
+exit 0
diff --git a/package/base-files/files/etc/uci-defaults/migrate-sysctl b/package/base-files/files/etc/uci-defaults/migrate-sysctl
new file mode 100644
index 000000000..b3796a4d2
--- /dev/null
+++ b/package/base-files/files/etc/uci-defaults/migrate-sysctl
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+if [ ! -f "/rom/etc/sysctl.conf" ] || cmp -s "/rom/etc/sysctl.conf" "/etc/sysctl.conf"; then
+ exit 0
+fi
+
+fingerprint="$(md5sum /etc/sysctl.conf)"
+fingerprint="${fingerprint%% *}"
+
+if [ "$fingerprint" = "1b05ebb41f72cb84e5510573cd4aca26" ] || \
+ [ "$fingerprint" = "62deb895be1a7f496040187b7c930e4e" ]; then
+ logger -t migrate-sysctl "Updating sysctl.conf to use current defaults"
+ cp "/rom/etc/sysctl.conf" "/etc/sysctl.conf"
+fi
+
+exit 0
+
diff --git a/package/base-files/files/lib/firstboot/05_firstboot_skip b/package/base-files/files/lib/firstboot/05_firstboot_skip
new file mode 100644
index 000000000..5f44df621
--- /dev/null
+++ b/package/base-files/files/lib/firstboot/05_firstboot_skip
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+check_skip() {
+ if [ "$firstboot_skip_next" = "true" ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
diff --git a/package/base-files/files/lib/firstboot/10_determine_parts b/package/base-files/files/lib/firstboot/10_determine_parts
new file mode 100644
index 000000000..3f56e32a8
--- /dev/null
+++ b/package/base-files/files/lib/firstboot/10_determine_parts
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+set_mtd_part() {
+ partname="rootfs_data"
+ mtdpart="$(find_mtd_part $partname)"
+}
+
+set_rom_part() {
+ rom=$(awk '/squashfs/ {print $2}' /proc/mounts)
+}
+
+set_jffs_part() {
+ jffs=$(awk '/jffs2/ {print $2}' /proc/mounts)
+}
+
+determine_mtd_part() {
+ set_mtd_part
+ if [ -z "$mtdpart" ]; then
+ echo "MTD partition not found."
+ exit 1
+ fi
+}
+
+determine_rom_part() {
+ check_skip || {
+ set_rom_part
+ if [ -z "$rom" ]; then
+ echo "You do not have a squashfs partition; aborting"
+ echo "(firstboot cannot be run on jffs2 based firmwares)"
+ exit 1
+ fi
+ }
+}
+
+determine_jffs2_part() {
+ check_skip || {
+ set_jffs_part
+ }
+}
+
+boot_hook_add switch2jffs determine_mtd_part
+boot_hook_add jffs2reset determine_mtd_part
+boot_hook_add switch2jffs determine_rom_part
+boot_hook_add jffs2reset determine_rom_part
+boot_hook_add switch2jffs determine_jffs2_part
+boot_hook_add jffs2reset determine_jffs2_part
diff --git a/package/base-files/files/lib/firstboot/10_no_fo_clear_overlay b/package/base-files/files/lib/firstboot/10_no_fo_clear_overlay
new file mode 100644
index 000000000..8a7d9b066
--- /dev/null
+++ b/package/base-files/files/lib/firstboot/10_no_fo_clear_overlay
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+no_fo_clear_overlay() {
+ # switch back to squashfs temporarily
+ pivot /rom /mnt
+
+ # get rid of the old overlay
+ umount -l /mnt
+
+ # another umount to get rid of the bind from /tmp/root
+ umount -l /mnt
+}
+
+boot_hook_add no_fo no_fo_clear_overlay
diff --git a/package/base-files/files/lib/firstboot/10_reset_has_mini_fo b/package/base-files/files/lib/firstboot/10_reset_has_mini_fo
new file mode 100644
index 000000000..4e285840a
--- /dev/null
+++ b/package/base-files/files/lib/firstboot/10_reset_has_mini_fo
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+reset_check_for_overlay() {
+ if grep -qE '(mini_fo|overlay)' /proc/filesystems; then
+ reset_has_fo=true
+ fi
+}
+
+boot_hook_add jffs2reset reset_check_for_overlay
diff --git a/package/base-files/files/lib/firstboot/20_has_mini_fo b/package/base-files/files/lib/firstboot/20_has_mini_fo
new file mode 100644
index 000000000..8ca6a4fe5
--- /dev/null
+++ b/package/base-files/files/lib/firstboot/20_has_mini_fo
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+check_for_overlay() {
+ if ! grep -qE '(mini_fo|overlay)' /proc/filesystems; then
+ boot_run_hook no_fo
+ exit 1
+ fi
+}
+
+boot_hook_add switch2jffs check_for_overlay
diff --git a/package/base-files/files/lib/firstboot/20_no_fo_mount_jffs b/package/base-files/files/lib/firstboot/20_no_fo_mount_jffs
new file mode 100644
index 000000000..8a1d4e06d
--- /dev/null
+++ b/package/base-files/files/lib/firstboot/20_no_fo_mount_jffs
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+no_fo_mount_jffs() {
+ # initialize jffs2
+ mount "$mtdpart" /overlay -t jffs2 || exit
+
+ # workaround to ensure that union can attach properly
+ sync
+ ls /overlay >/dev/null
+}
+
+boot_hook_add no_fo no_fo_mount_jffs
diff --git a/package/base-files/files/lib/firstboot/20_reset_clear_jffs b/package/base-files/files/lib/firstboot/20_reset_clear_jffs
new file mode 100644
index 000000000..a3cd24fe9
--- /dev/null
+++ b/package/base-files/files/lib/firstboot/20_reset_clear_jffs
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+reset_clear_jffs() {
+ [ "$reset_has_fo" = "true" ] && {
+ rm -rf $jffs/* 2>&-
+ mount -o remount $jffs / 2>&-
+ exit 0
+ } || reset_has_fo=false
+}
+
+boot_hook_add jffs2reset reset_clear_jffs
diff --git a/package/base-files/files/lib/firstboot/30_is_rootfs_mounted b/package/base-files/files/lib/firstboot/30_is_rootfs_mounted
new file mode 100644
index 000000000..e2ba01d50
--- /dev/null
+++ b/package/base-files/files/lib/firstboot/30_is_rootfs_mounted
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+skip_if_rootfs_mounted() {
+ mount "$mtdpart" /rom/overlay -t jffs2 || exit
+}
+
+boot_hook_add switch2jffs skip_if_rootfs_mounted
diff --git a/package/base-files/files/lib/firstboot/30_no_fo_pivot b/package/base-files/files/lib/firstboot/30_no_fo_pivot
new file mode 100644
index 000000000..b5c2601ee
--- /dev/null
+++ b/package/base-files/files/lib/firstboot/30_no_fo_pivot
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+no_fo_pivot() {
+ # switch to the new (empty) jffs2
+ fopivot /overlay /rom 1
+}
+
+boot_hook_add no_fo no_fo_pivot
diff --git a/package/base-files/files/lib/firstboot/30_reset_copy_rom b/package/base-files/files/lib/firstboot/30_reset_copy_rom
new file mode 100644
index 000000000..d91c68947
--- /dev/null
+++ b/package/base-files/files/lib/firstboot/30_reset_copy_rom
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+reset_copy_rom() {
+ [ "$reset_has_fo" != "true" ] && {
+ dupe $jffs $rom
+ exit 0
+ }
+}
+
+boot_hook_add jffs2reset reset_copy_rom
diff --git a/package/base-files/files/lib/firstboot/40_copy_ramoverlay b/package/base-files/files/lib/firstboot/40_copy_ramoverlay
new file mode 100644
index 000000000..39c2edacb
--- /dev/null
+++ b/package/base-files/files/lib/firstboot/40_copy_ramoverlay
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+copy_ramoverlay() {
+ # try to avoid fs changing while copying
+ mount -o remount,ro none / 2>&-
+ # copy ramoverlay to jffs2
+ echo -n "copying files ... "
+ cp -a /tmp/root/* /rom/overlay 2>&-
+ echo "done"
+}
+
+boot_hook_add switch2jffs copy_ramoverlay
diff --git a/package/base-files/files/lib/firstboot/40_no_fo_copy_ramoverlay b/package/base-files/files/lib/firstboot/40_no_fo_copy_ramoverlay
new file mode 100644
index 000000000..ced7c1b66
--- /dev/null
+++ b/package/base-files/files/lib/firstboot/40_no_fo_copy_ramoverlay
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+no_fo_copy_ramoverlay() {
+ # copy ramoverlay to jffs2, must be done after switching
+ # to the new rootfs to avoid creating opaque directories
+ echo -n "copying files ... "
+ cp -a /tmp/root/* / >/dev/null 2>&1
+ sync
+}
+
+boot_hook_add no_fo no_fo_ramoverlay
diff --git a/package/base-files/files/lib/firstboot/50_pivot b/package/base-files/files/lib/firstboot/50_pivot
new file mode 100644
index 000000000..53801d7a8
--- /dev/null
+++ b/package/base-files/files/lib/firstboot/50_pivot
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+with_fo_pivot() {
+ # switch back to squashfs (temporarily)
+ # and park the ramdisk ontop of /tmp/root
+ pivot /rom /mnt
+ mount -o move /mnt /tmp/root
+
+ # /overlay is the overlay
+ # /rom is the readonly
+ fopivot /overlay /rom
+}
+
+boot_hook_add switch2jffs with_fo_pivot
diff --git a/package/base-files/files/lib/firstboot/99_10_no_fo_cleanup b/package/base-files/files/lib/firstboot/99_10_no_fo_cleanup
new file mode 100644
index 000000000..6dedcb1e8
--- /dev/null
+++ b/package/base-files/files/lib/firstboot/99_10_no_fo_cleanup
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+no_fo_cleanup() {
+ echo "done"
+ umount -l /overlay
+ umount -l /tmp/root
+ exit 0
+}
+
+boot_hook_add no_fo no_fo_cleanup
diff --git a/package/base-files/files/lib/firstboot/99_10_with_fo_cleanup b/package/base-files/files/lib/firstboot/99_10_with_fo_cleanup
new file mode 100644
index 000000000..0181b39d4
--- /dev/null
+++ b/package/base-files/files/lib/firstboot/99_10_with_fo_cleanup
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+with_fo_cleanup() {
+ # try to get rid of /tmp/root
+ # this will almost always fail
+ umount /tmp/root 2>&-
+ grep -q overlay /proc/filesystems && {
+ cd /
+ (
+ cd /overlay
+ find -type l
+ ) | while read FILE; do
+ [ -z "$FILE" ] && break
+ if ls -la "$FILE" 2>&- | grep -q '(overlay-whiteout)'; then
+ rm -f "$FILE"
+ fi
+ done
+ }
+ exit 0
+}
+
+boot_hook_add switch2jffs with_fo_cleanup
diff --git a/package/base-files/files/lib/functions.sh b/package/base-files/files/lib/functions.sh
new file mode 100755
index 000000000..b3a3885f2
--- /dev/null
+++ b/package/base-files/files/lib/functions.sh
@@ -0,0 +1,340 @@
+#!/bin/sh
+# Copyright (C) 2006-2011 OpenWrt.org
+# Copyright (C) 2006 Fokus Fraunhofer <carsten.tittel@fokus.fraunhofer.de>
+
+
+debug () {
+ ${DEBUG:-:} "$@"
+}
+mount() {
+ busybox mount "$@"
+}
+
+# newline
+N="
+"
+
+_C=0
+NO_EXPORT=1
+LOAD_STATE=1
+LIST_SEP=" "
+
+hotplug_dev() {
+ env -i ACTION=$1 INTERFACE=$2 /sbin/hotplug-call net
+}
+
+append() {
+ local var="$1"
+ local value="$2"
+ local sep="${3:- }"
+
+ eval "export ${NO_EXPORT:+-n} -- \"$var=\${$var:+\${$var}\${value:+\$sep}}\$value\""
+}
+
+list_contains() {
+ local var="$1"
+ local str="$2"
+ local val
+
+ eval "val=\" \${$var} \""
+ [ "${val%% $str *}" != "$val" ]
+}
+
+list_remove() {
+ local var="$1"
+ local remove="$2"
+ local val
+
+ eval "val=\" \${$var} \""
+ val1="${val%% $remove *}"
+ [ "$val1" = "$val" ] && return
+ val2="${val##* $remove }"
+ [ "$val2" = "$val" ] && return
+ val="${val1## } ${val2%% }"
+ val="${val%% }"
+ eval "export ${NO_EXPORT:+-n} -- \"$var=\$val\""
+}
+
+config_load() {
+ [ -n "$IPKG_INSTROOT" ] && return 0
+ uci_load "$@"
+}
+
+reset_cb() {
+ config_cb() { return 0; }
+ option_cb() { return 0; }
+ list_cb() { return 0; }
+}
+reset_cb
+
+package() {
+ return 0
+}
+
+config () {
+ local cfgtype="$1"
+ local name="$2"
+
+ export ${NO_EXPORT:+-n} CONFIG_NUM_SECTIONS=$(($CONFIG_NUM_SECTIONS + 1))
+ name="${name:-cfg$CONFIG_NUM_SECTIONS}"
+ append CONFIG_SECTIONS "$name"
+ [ -n "$NO_CALLBACK" ] || config_cb "$cfgtype" "$name"
+ export ${NO_EXPORT:+-n} CONFIG_SECTION="$name"
+ export ${NO_EXPORT:+-n} "CONFIG_${CONFIG_SECTION}_TYPE=$cfgtype"
+}
+
+option () {
+ local varname="$1"; shift
+ local value="$*"
+
+ export ${NO_EXPORT:+-n} "CONFIG_${CONFIG_SECTION}_${varname}=$value"
+ [ -n "$NO_CALLBACK" ] || option_cb "$varname" "$*"
+}
+
+list() {
+ local varname="$1"; shift
+ local value="$*"
+ local len
+
+ config_get len "$CONFIG_SECTION" "${varname}_LENGTH" 0
+ [ $len = 0 ] && append CONFIG_LIST_STATE "${CONFIG_SECTION}_${varname}"
+ len=$(($len + 1))
+ config_set "$CONFIG_SECTION" "${varname}_ITEM$len" "$value"
+ config_set "$CONFIG_SECTION" "${varname}_LENGTH" "$len"
+ append "CONFIG_${CONFIG_SECTION}_${varname}" "$value" "$LIST_SEP"
+ list_cb "$varname" "$*"
+}
+
+config_rename() {
+ local OLD="$1"
+ local NEW="$2"
+ local oldvar
+ local newvar
+
+ [ -n "$OLD" -a -n "$NEW" ] || return
+ for oldvar in `set | grep ^CONFIG_${OLD}_ | \
+ sed -e 's/\(.*\)=.*$/\1/'` ; do
+ newvar="CONFIG_${NEW}_${oldvar##CONFIG_${OLD}_}"
+ eval "export ${NO_EXPORT:+-n} \"$newvar=\${$oldvar}\""
+ unset "$oldvar"
+ done
+ export ${NO_EXPORT:+-n} CONFIG_SECTIONS="$(echo " $CONFIG_SECTIONS " | sed -e "s, $OLD , $NEW ,")"
+
+ [ "$CONFIG_SECTION" = "$OLD" ] && export ${NO_EXPORT:+-n} CONFIG_SECTION="$NEW"
+}
+
+config_unset() {
+ config_set "$1" "$2" ""
+}
+
+config_clear() {
+ local SECTION="$1"
+ local oldvar
+
+ list_remove CONFIG_SECTIONS "$SECTION"
+ export ${NO_EXPORT:+-n} CONFIG_SECTIONS="${SECTION:+$CONFIG_SECTIONS}"
+
+ for oldvar in `set | grep ^CONFIG_${SECTION:+${SECTION}_} | \
+ sed -e 's/\(.*\)=.*$/\1/'` ; do
+ unset $oldvar
+ done
+}
+
+# config_get <variable> <section> <option> [<default>]
+# config_get <section> <option>
+config_get() {
+ case "$3" in
+ "") eval echo "\${CONFIG_${1}_${2}:-\${4}}";;
+ *) eval export ${NO_EXPORT:+-n} -- "${1}=\${CONFIG_${2}_${3}:-\${4}}";;
+ esac
+}
+
+# config_get_bool <variable> <section> <option> [<default>]
+config_get_bool() {
+ local _tmp
+ config_get _tmp "$2" "$3" "$4"
+ case "$_tmp" in
+ 1|on|true|enabled) _tmp=1;;
+ 0|off|false|disabled) _tmp=0;;
+ *) _tmp="$4";;
+ esac
+ export ${NO_EXPORT:+-n} "$1=$_tmp"
+}
+
+config_set() {
+ local section="$1"
+ local option="$2"
+ local value="$3"
+ local old_section="$CONFIG_SECTION"
+
+ CONFIG_SECTION="$section"
+ option "$option" "$value"
+ CONFIG_SECTION="$old_section"
+}
+
+config_foreach() {
+ local ___function="$1"
+ [ "$#" -ge 1 ] && shift
+ local ___type="$1"
+ [ "$#" -ge 1 ] && shift
+ local section cfgtype
+
+ [ -z "$CONFIG_SECTIONS" ] && return 0
+ for section in ${CONFIG_SECTIONS}; do
+ config_get cfgtype "$section" TYPE
+ [ -n "$___type" -a "x$cfgtype" != "x$___type" ] && continue
+ eval "$___function \"\$section\" \"\$@\""
+ done
+}
+
+config_list_foreach() {
+ [ "$#" -ge 3 ] || return 0
+ local section="$1"; shift
+ local option="$1"; shift
+ local function="$1"; shift
+ local val
+ local len
+ local c=1
+
+ config_get len "${section}" "${option}_LENGTH"
+ [ -z "$len" ] && return 0
+ while [ $c -le "$len" ]; do
+ config_get val "${section}" "${option}_ITEM$c"
+ eval "$function \"\$val\" \"$@\""
+ c="$(($c + 1))"
+ done
+}
+
+load_modules() {
+ [ -d /etc/modules.d ] && {
+ cd /etc/modules.d
+ sed 's/^[^#]/insmod &/' $* | ash 2>&- || :
+ }
+}
+
+include() {
+ local file
+
+ for file in $(ls $1/*.sh 2>/dev/null); do
+ . $file
+ done
+}
+
+find_mtd_part() {
+ local PART="$(grep "\"$1\"" /proc/mtd | awk -F: '{print $1}')"
+ local PREFIX=/dev/mtdblock
+
+ PART="${PART##mtd}"
+ [ -d /dev/mtdblock ] && PREFIX=/dev/mtdblock/
+ echo "${PART:+$PREFIX$PART}"
+}
+
+strtok() { # <string> { <variable> [<separator>] ... }
+ local tmp
+ local val="$1"
+ local count=0
+
+ shift
+
+ while [ $# -gt 1 ]; do
+ tmp="${val%%$2*}"
+
+ [ "$tmp" = "$val" ] && break
+
+ val="${val#$tmp$2}"
+
+ export ${NO_EXPORT:+-n} "$1=$tmp"; count=$((count+1))
+ shift 2
+ done
+
+ if [ $# -gt 0 -a -n "$val" ]; then
+ export ${NO_EXPORT:+-n} "$1=$val"; count=$((count+1))
+ fi
+
+ return $count
+}
+
+
+jffs2_mark_erase() {
+ local part="$(find_mtd_part "$1")"
+ [ -z "$part" ] && {
+ echo Partition not found.
+ return 1
+ }
+ echo -e "\xde\xad\xc0\xde" | mtd -qq write - "$1"
+}
+
+uci_apply_defaults() {
+ cd /etc/uci-defaults || return 0
+ files="$(ls)"
+ [ -z "$files" ] && return 0
+ mkdir -p /tmp/.uci
+ for file in $files; do
+ ( . "./$(basename $file)" ) && rm -f "$file"
+ done
+ uci commit
+}
+
+group_add() {
+ local name="$1"
+ local gid="$2"
+ local rc
+ [ -f "${IPKG_INSTROOT}/etc/group" ] || return 1
+ [ -n "$IPKG_INSTROOT" ] || lock /var/lock/group
+ echo "${name}:x:${gid}:" >> ${IPKG_INSTROOT}/etc/group
+ rc=$?
+ [ -n "$IPKG_INSTROOT" ] || lock -u /var/lock/group
+ return $rc
+}
+
+group_exists() {
+ grep -qs "^${1}:" ${IPKG_INSTROOT}/etc/group
+}
+
+user_add() {
+ local name="${1}"
+ local uid="${2}"
+ local gid="${3:-$2}"
+ local desc="${4:-$1}"
+ local home="${5:-/var/run/$1}"
+ local shell="${6:-/bin/false}"
+ local rc
+ [ -f "${IPKG_INSTROOT}/etc/passwd" ] || return 1
+ [ -n "$IPKG_INSTROOT" ] || lock /var/lock/passwd
+ echo "${name}:x:${uid}:${gid}:${desc}:${home}:${shell}" >> ${IPKG_INSTROOT}/etc/passwd
+ echo "${name}:x:0:0:99999:7:::" >> ${IPKG_INSTROOT}/etc/shadow
+ rc=$?
+ [ -n "$IPKG_INSTROOT" ] || lock -u /var/lock/passwd
+ return $rc
+}
+
+user_exists() {
+ grep -qs "^${1}:" ${IPKG_INSTROOT}/etc/passwd
+}
+
+
+pi_include() {
+ if [ -f "/tmp/overlay/$1" ]; then
+ . "/tmp/overlay/$1"
+ elif [ -f "$1" ]; then
+ . "$1"
+ elif [ -d "/tmp/overlay/$1" ]; then
+ if [ -n "$(ls /tmp/overlay/$1/*.sh 2>/dev/null)" ]; then
+ for src_script in /tmp/overlay/$1/*.sh; do
+ . "$src_script"
+ done
+ fi
+ elif [ -d "$1" ]; then
+ if [ -n "$(ls $1/*.sh 2>/dev/null)" ]; then
+ for src_script in $1/*.sh; do
+ . "$src_script"
+ done
+ fi
+ else
+ echo "WARNING: $1 not found"
+ return 1
+ fi
+ return 0
+}
+
+[ -z "$IPKG_INSTROOT" -a -f /lib/config/uci.sh ] && . /lib/config/uci.sh
diff --git a/package/base-files/files/lib/functions/boot.sh b/package/base-files/files/lib/functions/boot.sh
new file mode 100644
index 000000000..8c3f27ba4
--- /dev/null
+++ b/package/base-files/files/lib/functions/boot.sh
@@ -0,0 +1,150 @@
+#!/bin/sh
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+mount() {
+ /bin/busybox mount -o noatime "$@"
+}
+
+boot_hook_splice_start() {
+ export -n PI_HOOK_SPLICE=1
+}
+
+boot_hook_splice_finish() {
+ local hook
+ for hook in $PI_STACK_LIST; do
+ local v; eval "v=\${${hook}_splice:+\$${hook}_splice }$hook"
+ export -n "${hook}=${v% }"
+ export -n "${hook}_splice="
+ done
+ export -n PI_HOOK_SPLICE=
+}
+
+boot_hook_init() {
+ local hook="${1}_hook"
+ export -n "PI_STACK_LIST=${PI_STACK_LIST:+$PI_STACK_LIST }$hook"
+ export -n "$hook="
+}
+
+boot_hook_add() {
+ local hook="${1}_hook${PI_HOOK_SPLICE:+_splice}"
+ local func="${2}"
+
+ [ -n "$func" ] && {
+ local v; eval "v=\$$hook"
+ export -n "$hook=${v:+$v }$func"
+ }
+}
+
+boot_hook_shift() {
+ local hook="${1}_hook"
+ local rvar="${2}"
+
+ local v; eval "v=\$$hook"
+ [ -n "$v" ] && {
+ local first="${v%% *}"
+
+ [ "$v" != "${v#* }" ] && \
+ export -n "$hook=${v#* }" || \
+ export -n "$hook="
+
+ export -n "$rvar=$first"
+ return 0
+ }
+
+ return 1
+}
+
+boot_run_hook() {
+ local hook="$1"
+ local func
+
+ while boot_hook_shift "$hook" func; do
+ local ran; eval "ran=\$PI_RAN_$func"
+ [ -n "$ran" ] || {
+ export -n "PI_RAN_$func=1"
+ $func "$1" "$2"
+ }
+ done
+}
+
+find_mtd_part() {
+ local PART="$(grep "\"$1\"" /proc/mtd | awk -F: '{print $1}')"
+ local PREFIX=/dev/mtdblock
+
+ PART="${PART##mtd}"
+ [ -d /dev/mtdblock ] && PREFIX=/dev/mtdblock/
+ echo "${PART:+$PREFIX$PART}"
+}
+
+jffs2_ready () {
+ mtdpart="$(find_mtd_part rootfs_data)"
+ [ -z "$mtdpart" ] && return 1
+ magic=$(hexdump $mtdpart -n 4 -e '4/1 "%02x"')
+ [ "$magic" != "deadc0de" ]
+}
+
+dupe() { # <new_root> <old_root>
+ cd $1
+ echo -n "creating directories... "
+ {
+ cd $2
+ find . -xdev -type d
+ echo "./dev ./overlay ./mnt ./proc ./tmp"
+ # xdev skips mounted directories
+ cd $1
+ } | xargs mkdir -p
+ echo "done"
+
+ echo -n "setting up symlinks... "
+ for file in $(cd $2; find . -xdev -type f;); do
+ case "$file" in
+ ./rom/note) ;; #nothing
+ ./etc/config*|\
+ ./usr/lib/opkg/info/*) cp -af $2/$file $file;;
+ *) ln -sf /rom/${file#./*} $file;;
+ esac
+ done
+ for file in $(cd $2; find . -xdev -type l;); do
+ cp -af $2/${file#./*} $file
+ done
+ echo "done"
+}
+
+pivot() { # <new_root> <old_root>
+ mount -o move /proc $1/proc && \
+ pivot_root $1 $1$2 && {
+ mount -o move $2/dev /dev
+ mount -o move $2/tmp /tmp
+ mount -o move $2/sys /sys 2>&-
+ mount -o move $2/overlay /overlay 2>&-
+ return 0
+ }
+}
+
+fopivot() { # <rw_root> <ro_root> <dupe?>
+ root=$1
+ {
+ if grep -q overlay /proc/filesystems; then
+ mount -t overlayfs -olowerdir=/,upperdir=$1 "overlayfs:$1" /mnt && root=/mnt
+ elif grep -q mini_fo /proc/filesystems; then
+ mount -t mini_fo -o base=/,sto=$1 "mini_fo:$1" /mnt 2>&- && root=/mnt
+ else
+ mount --bind / /mnt
+ mount --bind -o union "$1" /mnt && root=/mnt
+ fi
+ } || {
+ [ "$3" = "1" ] && {
+ mount | grep "on $1 type" 2>&- 1>&- || mount -o bind $1 $1
+ dupe $1 $rom
+ }
+ }
+ pivot $root $2
+}
+
+ramoverlay() {
+ mkdir -p /tmp/root
+ mount -t tmpfs -o mode=0755 root /tmp/root
+ fopivot /tmp/root /rom 1
+}
+
diff --git a/package/base-files/files/lib/functions/network.sh b/package/base-files/files/lib/functions/network.sh
new file mode 100644
index 000000000..a4652569b
--- /dev/null
+++ b/package/base-files/files/lib/functions/network.sh
@@ -0,0 +1,170 @@
+. /usr/share/libubox/jshn.sh
+
+__network_ipaddr()
+{
+ local __var="$1"
+ local __iface="$2"
+ local __family="$3"
+ local __prefix="${4:-0}"
+
+ local __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)"
+
+ json_load "${__tmp:-{}}"
+ json_get_type __tmp "ipv${__family}_address"
+
+ if [ "$__tmp" = array ]; then
+
+ json_select "ipv${__family}_address"
+ json_get_type __tmp 1
+
+ if [ "$__tmp" = object ]; then
+
+ json_select 1
+ json_get_var $__var address
+
+ [ $__prefix -gt 0 ] && {
+ json_get_var __tmp mask
+ eval "export -- \"$__var=\${$__var}/$__tmp\""
+ }
+
+ return 0
+ fi
+ fi
+
+ return 1
+}
+
+network_get_ipaddr() { __network_ipaddr "$1" "$2" 4 0; }
+network_get_ipaddr6() { __network_ipaddr "$1" "$2" 6 0; }
+
+network_get_subnet() { __network_ipaddr "$1" "$2" 4 1; }
+network_get_subnet6() { __network_ipaddr "$1" "$2" 6 1; }
+
+
+__network_gateway()
+{
+ local __var="$1"
+ local __iface="$2"
+ local __family="$3"
+
+ local __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)"
+ local __idx=1
+
+ json_load "${__tmp:-{}}"
+
+ if json_get_type __tmp route && [ "$__tmp" = array ]; then
+
+ json_select route
+
+ while json_get_type __tmp "$__idx" && [ "$__tmp" = object ]; do
+
+ json_select "$((__idx++))"
+ json_get_var __tmp target
+
+ case "${__family}/${__tmp}" in
+ 4/0.0.0.0|6/::)
+ json_get_var "$__var" nexthop
+ return $?
+ ;;
+ esac
+
+ json_select ".."
+
+ done
+ fi
+
+ return 1
+}
+
+network_get_gateway() { __network_gateway "$1" "$2" 4; }
+network_get_gateway6() { __network_gateway "$1" "$2" 6; }
+
+
+__network_dns() {
+ local __var="$1"
+ local __iface="$2"
+ local __field="$3"
+
+ local __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)"
+ local __dns=""
+ local __idx=1
+
+ json_load "${__tmp:-{}}"
+
+ if json_get_type __tmp "$__field" && [ "$__tmp" = array ]; then
+
+ json_select "$__field"
+
+ while json_get_type __tmp "$__idx" && [ "$__tmp" = string ]; do
+
+ json_get_var __tmp "$((__idx++))"
+ __dns="${__dns:+$__dns }$__tmp"
+
+ done
+ fi
+
+ eval "export -- \"$__var=$__dns\""
+ [ -n "$__dns" ]
+}
+
+network_get_dnsserver() { __network_dns "$1" "$2" dns_server; }
+network_get_dnssearch() { __network_dns "$1" "$2" dns_search; }
+
+
+__network_wan() {
+ local __var="$1"
+ local __family="$2"
+ local __iface
+
+ for __iface in $(ubus list | sed -ne 's/^network\.interface\.//p'); do
+ if __network_gateway "$__var" "$__iface" "$__family"; then
+ eval "export -- \"$__var=$__iface\""
+ return 0
+ fi
+ done
+
+ eval "export -- \"$__var=\""
+ return 1
+}
+
+network_find_wan() { __network_wan "$1" 4; }
+network_find_wan6() { __network_wan "$1" 6; }
+
+
+__network_device()
+{
+ local __var="$1"
+ local __iface="$2"
+ local __field="$3"
+
+ local __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)"
+ [ -n "$__tmp" ] || return 1
+
+ json_load "$__tmp"
+ json_get_var "$__var" "$__field"
+}
+
+network_is_up()
+{
+ local __up
+ __network_device __up "$1" up && [ $__up -eq 1 ]
+}
+
+network_get_device() { __network_device "$1" "$2" l3_device; }
+network_get_physdev() { __network_device "$1" "$2" device; }
+
+
+__network_defer()
+{
+ local __device="$1"
+ local __defer="$2"
+
+ json_init
+ json_add_string name "$__device"
+ json_add_boolean defer "$__defer"
+
+ ubus call network.device set_state "$(json_dump)" 2>/dev/null
+}
+
+network_defer_device() { __network_defer "$1" 1; }
+network_ready_device() { __network_defer "$1" 0; }
diff --git a/package/base-files/files/lib/functions/service.sh b/package/base-files/files/lib/functions/service.sh
new file mode 100644
index 000000000..cbb717d4d
--- /dev/null
+++ b/package/base-files/files/lib/functions/service.sh
@@ -0,0 +1,129 @@
+#
+# service: simple wrapper around start-stop-daemon
+#
+# Usage: service ACTION EXEC ARGS...
+#
+# Action:
+# -C check if EXEC is alive
+# -S start EXEC, passing it ARGS as its arguments
+# -K kill EXEC, sending it a TERM signal if not specified otherwise
+#
+# Environment variables exposed:
+# SERVICE_DAEMONIZE run EXEC in background
+# SERVICE_WRITE_PID create a pid-file and use it for matching
+# SERVICE_MATCH_EXEC use EXEC command-line for matching (default)
+# SERVICE_MATCH_NAME use EXEC process name for matching
+# SERVICE_USE_PID assume EXEC create its own pid-file and use it for matching
+# SERVICE_NAME process name to use (default to EXEC file part)
+# SERVICE_PID_FILE pid file to use (default to /var/run/$SERVICE_NAME.pid)
+# SERVICE_SIG signal to send when using -K
+# SERVICE_SIG_RELOAD default signal used when reloading
+# SERVICE_SIG_STOP default signal used when stopping
+# SERVICE_STOP_TIME time to wait for a process to stop gracefully before killing it
+# SERVICE_UID user EXEC should be run as
+# SERVICE_GID group EXEC should be run as
+#
+# SERVICE_DEBUG don't do anything, but show what would be done
+# SERVICE_QUIET don't print anything
+#
+
+SERVICE_QUIET=1
+SERVICE_SIG_RELOAD="HUP"
+SERVICE_SIG_STOP="TERM"
+SERVICE_STOP_TIME=5
+SERVICE_MATCH_EXEC=1
+
+service() {
+ local ssd
+ local exec
+ local name
+ local start
+ ssd="${SERVICE_DEBUG:+echo }start-stop-daemon${SERVICE_QUIET:+ -q}"
+ case "$1" in
+ -C)
+ ssd="$ssd -K -t"
+ ;;
+ -S)
+ ssd="$ssd -S${SERVICE_DAEMONIZE:+ -b}${SERVICE_WRITE_PID:+ -m}"
+ start=1
+ ;;
+ -K)
+ ssd="$ssd -K${SERVICE_SIG:+ -s $SERVICE_SIG}"
+ ;;
+ *)
+ echo "service: unknown ACTION '$1'" 1>&2
+ return 1
+ esac
+ shift
+ exec="$1"
+ [ -n "$exec" ] || {
+ echo "service: missing argument" 1>&2
+ return 1
+ }
+ [ -x "$exec" ] || {
+ echo "service: file '$exec' is not executable" 1>&2
+ return 1
+ }
+ name="${SERVICE_NAME:-${exec##*/}}"
+ [ -z "$SERVICE_USE_PID$SERVICE_WRITE_PID$SERVICE_PID_FILE" ] \
+ || ssd="$ssd -p ${SERVICE_PID_FILE:-/var/run/$name.pid}"
+ [ -z "$SERVICE_MATCH_NAME" ] || ssd="$ssd -n $name"
+ ssd="$ssd${SERVICE_UID:+ -c $SERVICE_UID${SERVICE_GID:+:$SERVICE_GID}}"
+ [ -z "$SERVICE_MATCH_EXEC$start" ] || ssd="$ssd -x $exec"
+ shift
+ $ssd${1:+ -- "$@"}
+}
+
+service_check() {
+ service -C "$@"
+}
+
+service_signal() {
+ SERVICE_SIG="${SERVICE_SIG:-USR1}" service -K "$@"
+}
+
+service_start() {
+ service -S "$@"
+}
+
+service_stop() {
+ local try
+ SERVICE_SIG="${SERVICE_SIG:-$SERVICE_SIG_STOP}" service -K "$@" || return 1
+ while [ $((try++)) -lt $SERVICE_STOP_TIME ]; do
+ service -C "$@" || return 0
+ sleep 1
+ done
+ SERVICE_SIG="KILL" service -K "$@"
+ sleep 1
+ ! service -C "$@"
+}
+
+service_reload() {
+ SERVICE_SIG="${SERVICE_SIG:-$SERVICE_SIG_RELOAD}" service -K "$@"
+}
+
+service_kill() {
+ cat 1>&2 << __END_OF_WARNING__
+#
+# WARNING: the 'service_kill' function is now deprecated and might be
+# removed soon. Consider using the other new service_* wrappers instead.
+#
+__END_OF_WARNING__
+ local name="${1}"
+ local pid="${2:-$(pidof "$name")}"
+ local grace="${3:-5}"
+
+ [ -f "$pid" ] && pid="$(head -n1 "$pid" 2>/dev/null)"
+
+ for pid in $pid; do
+ [ -d "/proc/$pid" ] || continue
+ local try=0
+ kill -TERM $pid 2>/dev/null && \
+ while grep -qs "$name" "/proc/$pid/cmdline" && [ $((try++)) -lt $grace ]; do sleep 1; done
+ kill -KILL $pid 2>/dev/null && \
+ while grep -qs "$name" "/proc/$pid/cmdline"; do sleep 1; done
+ done
+}
+
+
+
diff --git a/package/base-files/files/lib/functions/uci-defaults.sh b/package/base-files/files/lib/functions/uci-defaults.sh
new file mode 100644
index 000000000..477c00cfd
--- /dev/null
+++ b/package/base-files/files/lib/functions/uci-defaults.sh
@@ -0,0 +1,230 @@
+#!/bin/sh
+# Copyright (C) 2011 OpenWrt.org
+
+UCIDEF_LEDS_CHANGED=0
+
+ucidef_set_led_netdev() {
+ local cfg="led_$1"
+ local name=$2
+ local sysfs=$3
+ local dev=$4
+
+ uci -q get system.$cfg && return 0
+
+ uci batch <<EOF
+set system.$cfg='led'
+set system.$cfg.name='$name'
+set system.$cfg.sysfs='$sysfs'
+set system.$cfg.trigger='netdev'
+set system.$cfg.dev='$dev'
+set system.$cfg.mode='link tx rx'
+EOF
+ UCIDEF_LEDS_CHANGED=1
+}
+
+ucidef_set_led_usbdev() {
+ local cfg="led_$1"
+ local name=$2
+ local sysfs=$3
+ local dev=$4
+
+ uci -q get system.$cfg && return 0
+
+ uci batch <<EOF
+set system.$cfg='led'
+set system.$cfg.name='$name'
+set system.$cfg.sysfs='$sysfs'
+set system.$cfg.trigger='usbdev'
+set system.$cfg.dev='$dev'
+set system.$cfg.interval='50'
+EOF
+ UCIDEF_LEDS_CHANGED=1
+}
+
+ucidef_set_led_wlan() {
+ local cfg="led_$1"
+ local name=$2
+ local sysfs=$3
+ local trigger=$4
+
+ uci -q get system.$cfg && return 0
+
+ uci batch <<EOF
+set system.$cfg='led'
+set system.$cfg.name='$name'
+set system.$cfg.sysfs='$sysfs'
+set system.$cfg.trigger='$trigger'
+EOF
+ UCIDEF_LEDS_CHANGED=1
+}
+
+ucidef_set_led_switch() {
+ local cfg="led_$1"
+ local name=$2
+ local sysfs=$3
+ local trigger=$4
+ local port_mask=$5
+
+ uci -q get system.$cfg && return 0
+
+ uci batch <<EOF
+set system.$cfg='led'
+set system.$cfg.name='$name'
+set system.$cfg.sysfs='$sysfs'
+set system.$cfg.trigger='$trigger'
+set system.$cfg.port_mask='$port_mask'
+EOF
+ UCIDEF_LEDS_CHANGED=1
+}
+
+ucidef_set_led_default() {
+ local cfg="led_$1"
+ local name=$2
+ local sysfs=$3
+ local default=$4
+
+ uci -q get system.$cfg && return 0
+
+ uci batch <<EOF
+set system.$cfg='led'
+set system.$cfg.name='$name'
+set system.$cfg.sysfs='$sysfs'
+set system.$cfg.default='$default'
+EOF
+ UCIDEF_LEDS_CHANGED=1
+}
+
+ucidef_set_led_rssi() {
+ local cfg="led_$1"
+ local name=$2
+ local sysfs=$3
+ local iface=$4
+ local minq=$5
+ local maxq=$6
+ local offset=$7
+ local factor=$8
+
+ uci -q get system.$cfg && return 0
+
+ uci batch <<EOF
+set system.$cfg='led'
+set system.$cfg.name='$name'
+set system.$cfg.sysfs='$sysfs'
+set system.$cfg.trigger='rssi'
+set system.$cfg.iface='rssid_$iface'
+set system.$cfg.minq='$minq'
+set system.$cfg.maxq='$maxq'
+set system.$cfg.offset='$offset'
+set system.$cfg.factor='$factor'
+EOF
+ UCIDEF_LEDS_CHANGED=1
+}
+
+ucidef_set_rssimon() {
+ local dev="$1"
+ local refresh="$2"
+ local threshold="$3"
+
+ local cfg="rssid_$dev"
+
+ uci -q get system.$cfg && return 0
+
+ uci batch <<EOF
+set system.$cfg='rssid'
+set system.$cfg.dev='$dev'
+set system.$cfg.refresh='$refresh'
+set system.$cfg.threshold='$threshold'
+EOF
+ UCIDEF_LEDS_CHANGED=1
+}
+
+ucidef_commit_leds()
+{
+ [ "$UCIDEF_LEDS_CHANGED" == "1" ] && uci commit system
+}
+
+ucidef_set_interface_loopback() {
+ uci batch <<EOF
+set network.loopback='interface'
+set network.loopback.ifname='lo'
+set network.loopback.proto='static'
+set network.loopback.ipaddr='127.0.0.1'
+set network.loopback.netmask='255.0.0.0'
+EOF
+}
+
+ucidef_set_interface_raw() {
+ local cfg=$1
+ local ifname=$2
+
+ uci batch <<EOF
+set network.$cfg='interface'
+set network.$cfg.ifname='$ifname'
+set network.$cfg.proto='none'
+EOF
+}
+
+ucidef_set_interface_lan() {
+ local ifname=$1
+
+ uci batch <<EOF
+set network.lan='interface'
+set network.lan.ifname='$ifname'
+set network.lan.type='bridge'
+set network.lan.proto='static'
+set network.lan.ipaddr='192.168.1.1'
+set network.lan.netmask='255.255.255.0'
+EOF
+}
+
+ucidef_set_interface_wan() {
+ local ifname=$1
+
+ uci batch <<EOF
+set network.wan='interface'
+set network.wan.ifname='$ifname'
+set network.wan.proto='dhcp'
+EOF
+}
+
+ucidef_set_interfaces_lan_wan() {
+ local lan_ifname=$1
+ local wan_ifname=$2
+
+ ucidef_set_interface_lan "$lan_ifname"
+ ucidef_set_interface_wan "$wan_ifname"
+}
+
+ucidef_set_interface_macaddr() {
+ local ifname=$1
+ local mac=$2
+
+ uci batch <<EOF
+set network.$ifname.macaddr='$mac'
+EOF
+}
+
+ucidef_add_switch() {
+ local name=$1
+ local reset=$2
+ local enable=$3
+ uci batch <<EOF
+add network switch
+set network.@switch[-1].name='$name'
+set network.@switch[-1].reset='$reset'
+set network.@switch[-1].enable_vlan='$enable'
+EOF
+}
+
+ucidef_add_switch_vlan() {
+ local device=$1
+ local vlan=$2
+ local ports=$3
+ uci batch <<EOF
+add network switch_vlan
+set network.@switch_vlan[-1].device='$device'
+set network.@switch_vlan[-1].vlan='$vlan'
+set network.@switch_vlan[-1].ports='$ports'
+EOF
+}
+
diff --git a/package/base-files/files/lib/preinit/02_default_set_state b/package/base-files/files/lib/preinit/02_default_set_state
new file mode 100644
index 000000000..df4339572
--- /dev/null
+++ b/package/base-files/files/lib/preinit/02_default_set_state
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+define_default_set_state() {
+ . /etc/diag.sh
+}
+
+boot_hook_add preinit_main define_default_set_state
diff --git a/package/base-files/files/lib/preinit/05_mount_skip b/package/base-files/files/lib/preinit/05_mount_skip
new file mode 100644
index 000000000..c2b7ee79d
--- /dev/null
+++ b/package/base-files/files/lib/preinit/05_mount_skip
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+check_skip() {
+ if [ "$pi_mount_skip_next" = "true" ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
diff --git a/package/base-files/files/lib/preinit/10_check_for_mtd b/package/base-files/files/lib/preinit/10_check_for_mtd
new file mode 100644
index 000000000..66f185e1a
--- /dev/null
+++ b/package/base-files/files/lib/preinit/10_check_for_mtd
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+mount_no_mtd() {
+ mtd unlock rootfs
+ mount -o remount,rw /dev/root /
+}
+
+check_for_mtd() {
+ check_skip || {
+ grep -qs rootfs_data /proc/mtd || {
+ mount_no_mtd && pi_mount_skip_next=true
+ }
+ }
+}
+
+boot_hook_add preinit_mount_root check_for_mtd
+
diff --git a/package/base-files/files/lib/preinit/10_essential_fs b/package/base-files/files/lib/preinit/10_essential_fs
new file mode 100644
index 000000000..ab317dc20
--- /dev/null
+++ b/package/base-files/files/lib/preinit/10_essential_fs
@@ -0,0 +1,25 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+do_mount_procfs() {
+ mount proc /proc -t proc
+}
+
+do_mount_sysfs() {
+ mount sysfs /sys -t sysfs
+}
+
+calc_tmpfs_size() {
+ pi_size=$(awk '/MemTotal:/ {l=5242880;mt=($2*1024);print((s=mt/2)<l)&&(mt>l)?mt-l:s}' /proc/meminfo)
+}
+
+do_mount_tmpfs() {
+ calc_tmpfs_size
+ mount tmpfs /tmp -t tmpfs -o size=$pi_size,nosuid,nodev,mode=1777
+}
+
+boot_hook_add preinit_essential do_mount_procfs
+boot_hook_add preinit_essential do_mount_sysfs
+boot_hook_add preinit_essential do_mount_tmpfs
+
diff --git a/package/base-files/files/lib/preinit/10_indicate_failsafe b/package/base-files/files/lib/preinit/10_indicate_failsafe
new file mode 100644
index 000000000..7761fd3be
--- /dev/null
+++ b/package/base-files/files/lib/preinit/10_indicate_failsafe
@@ -0,0 +1,18 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+# commands for emitting messages to network in failsafe mode
+
+indicate_failsafe_led () {
+ set_state failsafe
+}
+
+indicate_failsafe() {
+ echo "- failsafe -"
+ preinit_net_echo "Entering Failsafe!\n"
+ indicate_failsafe_led
+}
+
+boot_hook_add failsafe indicate_failsafe
+
diff --git a/package/base-files/files/lib/preinit/10_indicate_preinit b/package/base-files/files/lib/preinit/10_indicate_preinit
new file mode 100644
index 000000000..ab6930518
--- /dev/null
+++ b/package/base-files/files/lib/preinit/10_indicate_preinit
@@ -0,0 +1,52 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+preinit_ip() {
+ # if the preinit interface isn't specified and ifname is set in
+ # preinit.arch use that interface
+ if [ -z "$pi_ifname" ]; then
+ pi_ifname=$ifname
+ fi
+
+ [ -n "$pi_ifname" ] && grep -q "$pi_ifname" /proc/net/dev && {
+ ifconfig $pi_ifname $pi_ip netmask $pi_netmask broadcast $pi_broadcast up
+ }
+}
+
+preinit_ip_deconfig() {
+ [ -n "$pi_ifname" ] && grep -q "$pi_ifname" /proc/net/dev && {
+ ifconfig $pi_ifname 0.0.0.0 down
+ }
+}
+
+preinit_net_echo() {
+ [ -n "$pi_ifname" ] && grep -q "$pi_ifname" /proc/net/dev && {
+ {
+ [ "$pi_preinit_net_messages" = "y" ] || {
+ [ "$pi_failsafe_net_message" = "true" ] &&
+ [ "$pi_preinit_no_failsafe_netmsg" != "y" ]
+ }
+
+ } && netmsg $pi_broadcast "$1"
+ }
+}
+
+preinit_echo() {
+ preinit_net_echo $1
+ echo $1
+}
+
+pi_indicate_led() {
+ set_state preinit
+}
+
+pi_indicate_preinit() {
+ echo "- preinit -"
+ preinit_net_echo "Doing OpenWRT Preinit\n"
+ pi_indicate_led
+}
+
+boot_hook_add preinit_main preinit_ip
+boot_hook_add preinit_main pi_indicate_preinit
+
diff --git a/package/base-files/files/lib/preinit/20_check_jffs2_ready b/package/base-files/files/lib/preinit/20_check_jffs2_ready
new file mode 100644
index 000000000..3c5cf67e8
--- /dev/null
+++ b/package/base-files/files/lib/preinit/20_check_jffs2_ready
@@ -0,0 +1,19 @@
+#!/bin/sh
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+mount_no_jffs2() {
+ echo "jffs2 not ready yet; using ramdisk"
+ ramoverlay
+}
+
+check_for_jffs2() {
+ check_skip || {
+ jffs2_ready || {
+ mount_no_jffs2 && pi_mount_skip_next=true
+ }
+ }
+}
+
+boot_hook_add preinit_mount_root check_for_jffs2
+
diff --git a/package/base-files/files/lib/preinit/20_device_fs_mount b/package/base-files/files/lib/preinit/20_device_fs_mount
new file mode 100644
index 000000000..832b1cf39
--- /dev/null
+++ b/package/base-files/files/lib/preinit/20_device_fs_mount
@@ -0,0 +1,37 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+do_move_devtmpfs() {
+ local mnt="$(grep devtmpfs /proc/mounts)"
+ mnt="${mnt#* }"; mnt="${mnt%% *}"
+
+ [ "$mnt" = "/dev" ] || mount -o move "$mnt" /dev
+}
+
+do_mount_devfs() {
+ mount devfs /dev -t devfs
+}
+
+do_mount_hotplug() {
+ mount -t tmpfs tmpfs /dev -o mode=0755,size=512K
+}
+
+do_mount_udev() {
+ mount -n -t tmpfs -o mode=0755 udev /dev
+}
+
+choose_device_fs() {
+ if grep -q devtmpfs /proc/mounts; then
+ do_move_devtmpfs
+ elif grep -q devfs /proc/filesystems; then
+ do_mount_devfs
+ elif [ -x /sbin/hotplug2 ]; then
+ do_mount_hotplug
+ elif [ -x /sbin/udevd ]; then
+ do_mount_udev
+ fi
+}
+
+boot_hook_add preinit_essential choose_device_fs
+
diff --git a/package/base-files/files/lib/preinit/30_device_fs_daemons b/package/base-files/files/lib/preinit/30_device_fs_daemons
new file mode 100644
index 000000000..5b3e2ad00
--- /dev/null
+++ b/package/base-files/files/lib/preinit/30_device_fs_daemons
@@ -0,0 +1,36 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+init_devfs() {
+ HOTPLUG=/sbin/hotplug-call
+}
+
+init_hotplug2() {
+ [ -c /dev/console ] || mknod /dev/console c 5 1
+ /sbin/hotplug2 --set-worker /lib/hotplug2/worker_fork.so --set-rules-file /etc/hotplug2-init.rules --no-persistent --set-coldplug-cmd /sbin/udevtrigger
+ /sbin/hotplug2 --set-worker /lib/hotplug2/worker_fork.so --set-rules-file /etc/hotplug2-init.rules --persistent &
+}
+
+init_udev() {
+ [ -d /lib/udev/devices ] && cp -af /lib/udev/devices/* /dev/
+ [ -c /dev/console ] || mknod -m 0600 /dev/console c 5 1
+ [ -c /dev/null ] || mknod -m 0666 /dev/null c 1 3
+ /sbin/udevd --daemon --resolve-names=never
+ /sbin/udevadm trigger
+ /sbin/udevadm settle
+}
+
+init_device_fs() {
+ HOTPLUG=
+ if grep -q devfs /proc/filesystems; then
+ init_devfs
+ elif [ -x /sbin/hotplug2 ]; then
+ init_hotplug2
+ elif [ -x /sbin/udevd ]; then
+ init_udev
+ fi
+}
+
+boot_hook_add preinit_essential init_device_fs
+
diff --git a/package/base-files/files/lib/preinit/30_failsafe_wait b/package/base-files/files/lib/preinit/30_failsafe_wait
new file mode 100644
index 000000000..04dc57df2
--- /dev/null
+++ b/package/base-files/files/lib/preinit/30_failsafe_wait
@@ -0,0 +1,85 @@
+#!/bin/sh
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+fs_wait_for_key () {
+ local timeout=$3
+ local timer
+ local do_failsafe
+ local keypress_true="$(mktemp)"
+ local keypress_wait="$(mktemp)"
+ local keypress_sec="$(mktemp)"
+ if [ -z "$keypress_wait" ]; then
+ keypress_wait=/tmp/.keypress_wait
+ touch $keypress_wait
+ fi
+ if [ -z "$keypress_true" ]; then
+ keypress_true=/tmp/.keypress_true
+ touch $keypress_true
+ fi
+ if [ -z "$keypress_sec" ]; then
+ keypress_sec=/tmp/.keypress_sec
+ touch $keypress_sec
+ fi
+
+ trap "echo 'true' >$keypress_true; lock -u $keypress_wait ; rm -f $keypress_wait" INT
+ trap "echo 'true' >$keypress_true; lock -u $keypress_wait ; rm -f $keypress_wait" USR1
+
+ [ -n "$timeout" ] || timeout=1
+ [ $timeout -ge 1 ] || timeout=1
+ timer=$timeout
+ lock $keypress_wait
+ {
+ while [ $timer -gt 0 ]; do
+ echo "$timer" >$keypress_sec
+ timer=$(($timer - 1))
+ sleep 1
+ done
+ lock -u $keypress_wait
+ rm -f $keypress_wait
+ } &
+
+ echo "Press the [$1] key and hit [enter] $2"
+ # if we're on the console we wait for input
+ {
+ while [ -r $keypress_wait ]; do
+ timer="$(cat $keypress_sec)"
+
+ [ -n "$timer" ] || timer=1
+ timer="${timer%%\ *}"
+ [ $timer -ge 1 ] || timer=1
+ do_failsafe=""
+ {
+ read -t "$timer" do_failsafe
+ if [ "$do_failsafe" = "$1" ]; then
+ echo "true" >$keypress_true
+ lock -u $keypress_wait
+ rm -f $keypress_wait
+ fi
+ }
+ done
+ }
+ lock -w $keypress_wait
+
+ trap - INT
+ trap - USR1
+
+ keypressed=1
+ [ "$(cat $keypress_true)" = "true" ] && keypressed=0
+ rm -f $keypress_true
+ rm -f $keypress_wait
+ rm -f $keypress_sec
+
+ return $keypressed
+}
+
+failsafe_wait() {
+ FAILSAFE=
+ pi_failsafe_net_message=true
+ preinit_net_echo "Please press button now to enter failsafe"
+ pi_failsafe_net_message=false
+ fs_wait_for_key f 'to enter failsafe mode' $fs_failsafe_wait_timeout && FAILSAFE=true && export FAILSAFE
+}
+
+boot_hook_add preinit_main failsafe_wait
+
diff --git a/package/base-files/files/lib/preinit/40_init_shm b/package/base-files/files/lib/preinit/40_init_shm
new file mode 100644
index 000000000..8971116a4
--- /dev/null
+++ b/package/base-files/files/lib/preinit/40_init_shm
@@ -0,0 +1,10 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+init_shm() {
+ [ -d /dev/shm ] || mkdir -p /dev/shm
+}
+
+boot_hook_add preinit_essential init_shm
+
diff --git a/package/base-files/files/lib/preinit/40_mount_devpts b/package/base-files/files/lib/preinit/40_mount_devpts
new file mode 100644
index 000000000..2d5010b91
--- /dev/null
+++ b/package/base-files/files/lib/preinit/40_mount_devpts
@@ -0,0 +1,15 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+init_devpts() {
+ [ -d /dev/pts ] || mkdir -p /dev/pts
+}
+
+do_mount_devpts() {
+ mount devpts /dev/pts -t devpts
+}
+
+boot_hook_add preinit_essential init_devpts
+boot_hook_add preinit_essential do_mount_devpts
+
diff --git a/package/base-files/files/lib/preinit/40_mount_jffs2 b/package/base-files/files/lib/preinit/40_mount_jffs2
new file mode 100644
index 000000000..00f45a890
--- /dev/null
+++ b/package/base-files/files/lib/preinit/40_mount_jffs2
@@ -0,0 +1,26 @@
+#!/bin/sh
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+find_mount_jffs2() {
+ mkdir -p /tmp/overlay
+ mount "$(find_mtd_part rootfs_data)" /tmp/overlay -t jffs2
+ mtd -qq unlock rootfs_data
+}
+
+jffs2_not_mounted() {
+ if [ "$pi_jffs2_mount_success" != "true" ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+do_mount_jffs2() {
+ check_skip || {
+ find_mount_jffs2 && pi_jffs2_mount_success=true
+ }
+}
+
+boot_hook_add preinit_mount_root do_mount_jffs2
+
diff --git a/package/base-files/files/lib/preinit/40_run_failsafe_hook b/package/base-files/files/lib/preinit/40_run_failsafe_hook
new file mode 100644
index 000000000..faa043c17
--- /dev/null
+++ b/package/base-files/files/lib/preinit/40_run_failsafe_hook
@@ -0,0 +1,13 @@
+#!/bin/sh
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+run_failsafe_hook() {
+ if [ "$FAILSAFE" = "true" ]; then
+ boot_run_hook failsafe
+ lock -w /tmp/.failsafe
+ fi
+}
+
+boot_hook_add preinit_main run_failsafe_hook
+
diff --git a/package/base-files/files/lib/preinit/41_merge_overlay_hooks b/package/base-files/files/lib/preinit/41_merge_overlay_hooks
new file mode 100644
index 000000000..4ca6877be
--- /dev/null
+++ b/package/base-files/files/lib/preinit/41_merge_overlay_hooks
@@ -0,0 +1,24 @@
+#!/bin/sh
+# Copyright (C) 2010 OpenWrt.org
+
+merge_overlay_hooks() {
+ jffs2_not_mounted || [ ! -d /tmp/overlay/lib/preinit ] || {
+ echo "- merge overlay components -"
+
+ mkdir -p /tmp/preinit-hook-merge
+ ln -sf /lib/preinit/* /tmp/overlay/lib/preinit/[0-9][0-9]_* /tmp/preinit-hook-merge/
+
+ boot_hook_splice_start
+
+ local pipart
+ for pipart in /tmp/preinit-hook-merge/*; do
+ . $pipart
+ done
+
+ boot_hook_splice_finish
+
+ rm -rf /tmp/preinit-hook-merge
+ }
+}
+
+boot_hook_add preinit_mount_root merge_overlay_hooks
diff --git a/package/base-files/files/lib/preinit/50_choose_console b/package/base-files/files/lib/preinit/50_choose_console
new file mode 100644
index 000000000..ecbc2eaf4
--- /dev/null
+++ b/package/base-files/files/lib/preinit/50_choose_console
@@ -0,0 +1,31 @@
+#!/bin/sh
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+choose_console() {
+ # the shell really doesn't like having stdin/out closed
+ # that's why we use /dev/pty/m0 and m1 (or equivalent) as replacement
+ # for /dev/console if there's no serial console available
+
+ if grep -q devfs /proc/filesystems; then
+ M0=/dev/pty/m0
+ M1=/dev/pty/m1
+ M2=/dev/pty/m1
+ elif [ -x /sbin/hotplug2 ]; then
+ M0=/dev/ptmx
+ M1=/dev/ptmx
+ M2=/dev/ptmx
+ elif [ -x /sbin/udevd ]; then
+ M0=/dev/pty/ptmx
+ M1=/dev/pty/ptmx
+ M2=/dev/pty/ptmx
+ fi
+ dd if=/dev/console of=/dev/null bs=1 count=0 >/dev/null 2>/dev/null && {
+ M0=/dev/console
+ M1=/dev/console
+ M2=/dev/console
+ }
+}
+
+boot_hook_add preinit_essential choose_console
+
diff --git a/package/base-files/files/lib/preinit/50_indicate_regular_preinit b/package/base-files/files/lib/preinit/50_indicate_regular_preinit
new file mode 100644
index 000000000..9cc01f219
--- /dev/null
+++ b/package/base-files/files/lib/preinit/50_indicate_regular_preinit
@@ -0,0 +1,12 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+indicate_regular_preinit() {
+ echo "- regular preinit -"
+ preinit_net_echo "Continuing with Regular Preinit\n"
+ pi_indicate_led
+}
+
+boot_hook_add preinit_main indicate_regular_preinit
+
diff --git a/package/base-files/files/lib/preinit/60_init_hotplug b/package/base-files/files/lib/preinit/60_init_hotplug
new file mode 100644
index 000000000..dc05e0ed0
--- /dev/null
+++ b/package/base-files/files/lib/preinit/60_init_hotplug
@@ -0,0 +1,10 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+init_hotplug() {
+ echo "$HOTPLUG" > /proc/sys/kernel/hotplug
+}
+
+boot_hook_add preinit_main init_hotplug
+
diff --git a/package/base-files/files/lib/preinit/70_initramfs_test b/package/base-files/files/lib/preinit/70_initramfs_test
new file mode 100644
index 000000000..15c0dcd90
--- /dev/null
+++ b/package/base-files/files/lib/preinit/70_initramfs_test
@@ -0,0 +1,14 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+initramfs_test() {
+ if [ -n "$INITRAMFS" ]; then
+ boot_run_hook initramfs
+ preinit_ip_deconfig
+ break
+ fi
+}
+
+boot_hook_add preinit_main initramfs_test
+
diff --git a/package/base-files/files/lib/preinit/70_pivot_jffs2_root b/package/base-files/files/lib/preinit/70_pivot_jffs2_root
new file mode 100644
index 000000000..821bfb14f
--- /dev/null
+++ b/package/base-files/files/lib/preinit/70_pivot_jffs2_root
@@ -0,0 +1,14 @@
+#!/bin/sh
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+rootfs_pivot() {
+ check_skip || jffs2_not_mounted || {
+ echo "switching to jffs2"
+ mount -o move /tmp/overlay /overlay 2>&-
+ fopivot /overlay /rom && pi_mount_skip_next=true
+ }
+}
+
+boot_hook_add preinit_mount_root rootfs_pivot
+
diff --git a/package/base-files/files/lib/preinit/80_mount_root b/package/base-files/files/lib/preinit/80_mount_root
new file mode 100644
index 000000000..cc8781687
--- /dev/null
+++ b/package/base-files/files/lib/preinit/80_mount_root
@@ -0,0 +1,10 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+do_mount_root() {
+ boot_run_hook preinit_mount_root
+}
+
+boot_hook_add preinit_main do_mount_root
+
diff --git a/package/base-files/files/lib/preinit/90_init_console b/package/base-files/files/lib/preinit/90_init_console
new file mode 100644
index 000000000..ca05755fd
--- /dev/null
+++ b/package/base-files/files/lib/preinit/90_init_console
@@ -0,0 +1,14 @@
+#!/bin/sh
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+init_console() {
+ if [ "$pi_suppress_stderr" = "y" ]; then
+ exec <$M0 >$M1 2>&0
+ else
+ exec <$M0 >$M1 2>$M2
+ fi
+}
+
+boot_hook_add preinit_essential init_console
+
diff --git a/package/base-files/files/lib/preinit/90_mount_no_jffs2 b/package/base-files/files/lib/preinit/90_mount_no_jffs2
new file mode 100644
index 000000000..d8ad4ae11
--- /dev/null
+++ b/package/base-files/files/lib/preinit/90_mount_no_jffs2
@@ -0,0 +1,12 @@
+#!/bin/sh
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+do_mount_no_jffs2() {
+ check_skip || {
+ mount_no_jffs2 && pi_mount_skip_next=true
+ }
+}
+
+boot_hook_add preinit_mount_root do_mount_no_jffs2
+
diff --git a/package/base-files/files/lib/preinit/90_restore_config b/package/base-files/files/lib/preinit/90_restore_config
new file mode 100644
index 000000000..210bf6184
--- /dev/null
+++ b/package/base-files/files/lib/preinit/90_restore_config
@@ -0,0 +1,17 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+restore_config() {
+ [ -f /sysupgrade.tgz ] && {
+ echo "- config restore -"
+ cd /
+ mv sysupgrade.tgz /tmp
+ tar xzf /tmp/sysupgrade.tgz
+ rm -f /tmp/sysupgrade.tgz
+ sync
+ }
+}
+
+boot_hook_add preinit_main restore_config
+
diff --git a/package/base-files/files/lib/preinit/99_10_failsafe_login b/package/base-files/files/lib/preinit/99_10_failsafe_login
new file mode 100644
index 000000000..05d6b7787
--- /dev/null
+++ b/package/base-files/files/lib/preinit/99_10_failsafe_login
@@ -0,0 +1,18 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+failsafe_netlogin () {
+ telnetd -l /bin/login.sh <> /dev/null 2>&1
+}
+
+failsafe_shell() {
+ lock /tmp/.failsafe
+ ash --login
+ echo "Please reboot system when done with failsafe network logins"
+}
+
+
+boot_hook_add failsafe failsafe_netlogin
+boot_hook_add failsafe failsafe_shell
+
diff --git a/package/base-files/files/lib/preinit/99_10_mount_no_mtd b/package/base-files/files/lib/preinit/99_10_mount_no_mtd
new file mode 100644
index 000000000..c4f38e415
--- /dev/null
+++ b/package/base-files/files/lib/preinit/99_10_mount_no_mtd
@@ -0,0 +1,12 @@
+#!/bin/sh
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+do_mount_no_mtd() {
+ check_skip || {
+ mount_no_mtd
+ }
+}
+
+boot_hook_add preinit_mount_root do_mount_no_mtd
+
diff --git a/package/base-files/files/lib/preinit/99_10_run_init b/package/base-files/files/lib/preinit/99_10_run_init
new file mode 100644
index 000000000..fef3a503e
--- /dev/null
+++ b/package/base-files/files/lib/preinit/99_10_run_init
@@ -0,0 +1,16 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+run_init() {
+ preinit_echo "- init -"
+ preinit_ip_deconfig
+ if [ "$pi_init_suppress_stderr" = "y" ]; then
+ exec env - PATH=$pi_init_path $pi_init_env $pi_init_cmd 2>&0
+ else
+ exec env - PATH=$pi_init_path $pi_init_env $pi_init_cmd
+ fi
+}
+
+boot_hook_add preinit_main run_init
+
diff --git a/package/base-files/files/lib/upgrade/common.sh b/package/base-files/files/lib/upgrade/common.sh
new file mode 100644
index 000000000..e6de34849
--- /dev/null
+++ b/package/base-files/files/lib/upgrade/common.sh
@@ -0,0 +1,230 @@
+#!/bin/sh
+
+RAM_ROOT=/tmp/root
+
+ldd() { LD_TRACE_LOADED_OBJECTS=1 $*; }
+libs() { ldd $* | awk '{print $3}'; }
+
+install_file() { # <file> [ <file> ... ]
+ for file in "$@"; do
+ dest="$RAM_ROOT/$file"
+ [ -f $file -a ! -f $dest ] && {
+ dir="$(dirname $dest)"
+ mkdir -p "$dir"
+ cp $file $dest
+ }
+ done
+}
+
+install_bin() { # <file> [ <symlink> ... ]
+ src=$1
+ files=$1
+ [ -x "$src" ] && files="$src $(libs $src)"
+ install_file $files
+ [ -e /lib/ld-linux.so.3 ] && {
+ install_file /lib/ld-linux.so.3
+ }
+ shift
+ for link in "$@"; do {
+ dest="$RAM_ROOT/$link"
+ dir="$(dirname $dest)"
+ mkdir -p "$dir"
+ [ -f "$dest" ] || ln -s $src $dest
+ }; done
+}
+
+pivot() { # <new_root> <old_root>
+ mount | grep "on $1 type" 2>&- 1>&- || mount -o bind $1 $1
+ mkdir -p $1$2 $1/proc $1/sys $1/dev $1/tmp $1/overlay && \
+ mount -o move /proc $1/proc && \
+ pivot_root $1 $1$2 || {
+ umount $1 $1
+ return 1
+ }
+
+ mount -o move $2/sys /sys
+ mount -o move $2/dev /dev
+ mount -o move $2/tmp /tmp
+ mount -o move $2/overlay /overlay 2>&-
+ return 0
+}
+
+run_ramfs() { # <command> [...]
+ install_bin /bin/busybox /bin/ash /bin/sh /bin/mount /bin/umount \
+ /sbin/pivot_root /usr/bin/wget /sbin/reboot /bin/sync /bin/dd \
+ /bin/grep /bin/cp /bin/mv /bin/tar /usr/bin/md5sum "/usr/bin/[" \
+ /bin/vi /bin/ls /bin/cat /usr/bin/awk /usr/bin/hexdump \
+ /bin/sleep /bin/zcat /usr/bin/bzcat /usr/bin/printf /usr/bin/wc
+
+ install_bin /sbin/mtd
+ for file in $RAMFS_COPY_BIN; do
+ install_bin $file
+ done
+ install_file /etc/resolv.conf /lib/functions.sh /lib/functions.sh /lib/upgrade/*.sh $RAMFS_COPY_DATA
+
+ pivot $RAM_ROOT /mnt || {
+ echo "Failed to switch over to ramfs. Please reboot."
+ exit 1
+ }
+
+ mount -o remount,ro /mnt
+ umount -l /mnt
+
+ grep /overlay /proc/mounts > /dev/null && {
+ mount -o remount,ro /overlay
+ umount -l /overlay
+ }
+
+ # spawn a new shell from ramdisk to reduce the probability of cache issues
+ exec /bin/busybox ash -c "$*"
+}
+
+kill_remaining() { # [ <signal> ]
+ local sig="${1:-TERM}"
+ echo -n "Sending $sig to remaining processes ... "
+
+ local stat
+ for stat in /proc/[0-9]*/stat; do
+ [ -f "$stat" ] || continue
+
+ local pid name state ppid rest
+ read pid name state ppid rest < $stat
+ name="${name#(}"; name="${name%)}"
+
+ local cmdline
+ read cmdline < /proc/$pid/cmdline
+
+ # Skip kernel threads
+ [ -n "$cmdline" ] || continue
+
+ case "$name" in
+ # Skip essential services
+ *ash*|*init*|*watchdog*|*ssh*|*dropbear*|*telnet*|*login*|*hostapd*|*wpa_supplicant*) : ;;
+
+ # Killable process
+ *)
+ if [ $pid -ne $$ ] && [ $ppid -ne $$ ]; then
+ echo -n "$name "
+ kill -$sig $pid 2>/dev/null
+ fi
+ ;;
+ esac
+ done
+ echo ""
+}
+
+run_hooks() {
+ local arg="$1"; shift
+ for func in "$@"; do
+ eval "$func $arg"
+ done
+}
+
+ask_bool() {
+ local default="$1"; shift;
+ local answer="$default"
+
+ [ "$INTERACTIVE" -eq 1 ] && {
+ case "$default" in
+ 0) echo -n "$* (y/N): ";;
+ *) echo -n "$* (Y/n): ";;
+ esac
+ read answer
+ case "$answer" in
+ y*) answer=1;;
+ n*) answer=0;;
+ *) answer="$default";;
+ esac
+ }
+ [ "$answer" -gt 0 ]
+}
+
+v() {
+ [ "$VERBOSE" -ge 1 ] && echo "$@"
+}
+
+rootfs_type() {
+ mount | awk '($3 ~ /^\/$/) && ($5 !~ /rootfs/) { print $5 }'
+}
+
+get_image() { # <source> [ <command> ]
+ local from="$1"
+ local conc="$2"
+ local cmd
+
+ case "$from" in
+ http://*|ftp://*) cmd="wget -O- -q";;
+ *) cmd="cat";;
+ esac
+ if [ -z "$conc" ]; then
+ local magic="$(eval $cmd $from | dd bs=2 count=1 2>/dev/null | hexdump -n 2 -e '1/1 "%02x"')"
+ case "$magic" in
+ 1f8b) conc="zcat";;
+ 425a) conc="bzcat";;
+ esac
+ fi
+
+ eval "$cmd $from ${conc:+| $conc}"
+}
+
+get_magic_word() {
+ get_image "$@" | dd bs=2 count=1 2>/dev/null | hexdump -v -n 2 -e '1/1 "%02x"'
+}
+
+get_magic_long() {
+ get_image "$@" | dd bs=4 count=1 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"'
+}
+
+refresh_mtd_partitions() {
+ mtd refresh rootfs
+}
+
+jffs2_copy_config() {
+ if grep rootfs_data /proc/mtd >/dev/null; then
+ # squashfs+jffs2
+ mtd -e rootfs_data jffs2write "$CONF_TAR" rootfs_data
+ else
+ # jffs2
+ mtd jffs2write "$CONF_TAR" rootfs
+ fi
+}
+
+default_do_upgrade() {
+ sync
+ if [ "$SAVE_CONFIG" -eq 1 -a -z "$USE_REFRESH" ]; then
+ get_image "$1" | mtd -j "$CONF_TAR" write - "${PART_NAME:-image}"
+ else
+ get_image "$1" | mtd write - "${PART_NAME:-image}"
+ fi
+}
+
+do_upgrade() {
+ v "Performing system upgrade..."
+ if type 'platform_do_upgrade' >/dev/null 2>/dev/null; then
+ platform_do_upgrade "$ARGV"
+ else
+ default_do_upgrade "$ARGV"
+ fi
+
+ [ "$SAVE_CONFIG" -eq 1 -a -n "$USE_REFRESH" ] && {
+ v "Refreshing partitions"
+ if type 'platform_refresh_partitions' >/dev/null 2>/dev/null; then
+ platform_refresh_partitions
+ else
+ refresh_mtd_partitions
+ fi
+ if type 'platform_copy_config' >/dev/null 2>/dev/null; then
+ platform_copy_config
+ else
+ jffs2_copy_config
+ fi
+ }
+ v "Upgrade completed"
+ [ -n "$DELAY" ] && sleep "$DELAY"
+ ask_bool 1 "Reboot" && {
+ v "Rebooting system..."
+ reboot -f
+ sleep 5
+ echo b 2>/dev/null >/proc/sysrq-trigger
+ }
+}
diff --git a/package/base-files/files/lib/upgrade/keep.d/base-files-essential b/package/base-files/files/lib/upgrade/keep.d/base-files-essential
new file mode 100644
index 000000000..2c611d29b
--- /dev/null
+++ b/package/base-files/files/lib/upgrade/keep.d/base-files-essential
@@ -0,0 +1,9 @@
+# Essential files that will be always kept
+/etc/hosts
+/etc/inittab
+/etc/group
+/etc/passwd
+/etc/profile
+/etc/shells
+/etc/sysctl.conf
+/etc/rc.local
diff --git a/package/base-files/files/rom/note b/package/base-files/files/rom/note
new file mode 100644
index 000000000..1746eb050
--- /dev/null
+++ b/package/base-files/files/rom/note
@@ -0,0 +1,3 @@
+SQUASHFS USERS:
+After firstboot has been run, / will be jffs2 and /rom will be squashfs
+(* except when in failsafe)
diff --git a/package/base-files/files/sbin/firstboot b/package/base-files/files/sbin/firstboot
new file mode 100755
index 000000000..4da299189
--- /dev/null
+++ b/package/base-files/files/sbin/firstboot
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+switch2jffs_hook=
+jffs2reset_hook=
+no_fo_hook=
+
+. /lib/functions/boot.sh
+
+firstboot_skip_next=false
+
+for fb_source_file in /lib/firstboot/*; do
+ . $fb_source_file
+done
+
+set_mtd_part
+set_rom_part
+set_jffs_part
+
+# invoked as an executable
+if [ "${0##*/}" = "firstboot" ]; then
+ if [ "$1" = "switch2jffs" ]; then
+ boot_run_hook switch2jffs
+ elif [ -n "$jffs" ]; then
+ reset_has_fo=true
+ echo "firstboot has already been run"
+ echo "jffs2 partition is mounted, only resetting files"
+ boot_run_hook jffs2reset
+ else
+ mtd erase "$partname"
+ mount "$mtdpart" /overlay -t jffs2
+ fopivot /overlay /rom 1
+ fi
+fi
+
diff --git a/package/base-files/files/sbin/hotplug-call b/package/base-files/files/sbin/hotplug-call
new file mode 100755
index 000000000..d627becc6
--- /dev/null
+++ b/package/base-files/files/sbin/hotplug-call
@@ -0,0 +1,17 @@
+#!/bin/sh
+# Copyright (C) 2006-2010 OpenWrt.org
+
+export HOTPLUG_TYPE="$1"
+
+. /lib/functions.sh
+
+PATH=/bin:/sbin:/usr/bin:/usr/sbin
+LOGNAME=root
+USER=root
+export PATH LOGNAME USER
+
+[ \! -z "$1" -a -d /etc/hotplug.d/$1 ] && {
+ for script in $(ls /etc/hotplug.d/$1/* 2>&-); do (
+ [ -f $script ] && . $script
+ ); done
+}
diff --git a/package/base-files/files/sbin/led.sh b/package/base-files/files/sbin/led.sh
new file mode 100755
index 000000000..d67a0f51c
--- /dev/null
+++ b/package/base-files/files/sbin/led.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+# (C) 2008 openwrt.org
+
+. /lib/functions.sh
+ACTION=$1
+NAME=$2
+do_led() {
+ local name
+ local sysfs
+ config_get name $1 name
+ config_get sysfs $1 sysfs
+ [ "$name" == "$NAME" -o "$sysfs" = "$NAME" -a -e "/sys/class/leds/${sysfs}" ] && {
+ [ "$ACTION" == "set" ] &&
+ echo 1 >/sys/class/leds/${sysfs}/brightness \
+ || echo 0 >/sys/class/leds/${sysfs}/brightness
+ exit 0
+ }
+}
+
+[ "$1" == "clear" -o "$1" == "set" ] &&
+ [ -n "$2" ] &&{
+ config_load system
+ config_foreach do_led
+ exit 1
+ }
diff --git a/package/base-files/files/sbin/mount_root b/package/base-files/files/sbin/mount_root
new file mode 100755
index 000000000..2d73dac53
--- /dev/null
+++ b/package/base-files/files/sbin/mount_root
@@ -0,0 +1,26 @@
+#!/bin/sh
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+# Initialize hook variables et by pulling in from preinit
+
+preinit_essential_hook=
+preinit_main_hook=
+failsafe_hook=
+initramfs_hook=
+preinit_mount_root=
+
+. /lib/functions/boot.sh
+
+for pi_source_file in /lib/preinit/*; do
+ . $pi_source_file
+done
+
+# Override function that doesn't apply to use of mount_root as a command rather
+# than as part of preinit
+
+preinit_echo() {
+ echo "$@"
+}
+
+boot_run_hook preinit_mount_root
diff --git a/package/base-files/files/sbin/sysupgrade b/package/base-files/files/sbin/sysupgrade
new file mode 100755
index 000000000..802848ade
--- /dev/null
+++ b/package/base-files/files/sbin/sysupgrade
@@ -0,0 +1,187 @@
+#!/bin/sh
+. /lib/functions.sh
+
+# initialize defaults
+RAMFS_COPY_BIN="" # extra programs for temporary ramfs root
+RAMFS_COPY_DATA="" # extra data files
+export INTERACTIVE=0
+export VERBOSE=1
+export SAVE_CONFIG=1
+export SAVE_OVERLAY=0
+export DELAY=
+export CONF_IMAGE=
+export CONF_BACKUP=
+export CONF_RESTORE=
+export HELP=0
+export FORCE=0
+
+# parse options
+while [ -n "$1" ]; do
+ case "$1" in
+ -i) export INTERACTIVE=1;;
+ -d) export DELAY="$2"; shift;;
+ -v) export VERBOSE="$(($VERBOSE + 1))";;
+ -q) export VERBOSE="$(($VERBOSE - 1))";;
+ -n) export SAVE_CONFIG=0;;
+ -c) export SAVE_OVERLAY=1;;
+ -b|--create-backup) export CONF_BACKUP="$2"; shift;;
+ -r|--restore-backup) export CONF_RESTORE="$2"; shift;;
+ -f) export CONF_IMAGE="$2"; shift;;
+ -F|--force) export FORCE=1;;
+ -h|--help) export HELP=1; break;;
+ -*)
+ echo "Invalid option: $1"
+ exit 1
+ ;;
+ *) break;;
+ esac
+ shift;
+done
+
+export CONFFILES=/tmp/sysupgrade.conffiles
+export CONF_TAR=/tmp/sysupgrade.tgz
+
+export ARGV="$*"
+export ARGC="$#"
+
+[ -z "$ARGV" -a -z "$CONF_BACKUP" -o $HELP -gt 0 ] && {
+ cat <<EOF
+Usage: $0 [options] <image file or URL>
+
+Options:
+ -d <delay> add a delay before rebooting
+ -f <config> restore configuration from .tar.gz (file or url)
+ -i interactive mode
+ -c attempt to preserve all changed files in /etc/
+ -b / --create-backup <file>
+ create .tar.gz of files specified in sysupgrade.conf
+ then exit. Does not flash an image. If file is '-',
+ i.e. stdout, verbosity is set to 0 (i.e. quiet).
+ -r / --restore-backup <file>
+ restore a .tar.gz created with sysupgrade -b
+ then exit. Does not flash an image. If file is '-',
+ the archive is read from stdin.
+ -n do not save configuration over reflash
+ -F / --force
+ Flash image even if image checks fail, this is dangerous!
+ -q less verbose
+ -v more verbose
+ -h / --help display this help
+
+EOF
+ exit 1
+}
+
+[ -n "$ARGV" -a -n "$CONF_BACKUP" ] && {
+ cat <<-EOF
+ -b/--create-backup does not perform a firmware upgrade. Do not
+ specify both -b and a firmware image.
+ EOF
+ exit 1
+}
+
+# prevent messages from clobbering the tarball when using stdout
+[ "$CONF_BACKUP" = "-" ] && export VERBOSE=0
+
+add_uci_conffiles() {
+ local file="$1"
+ ( find $(sed -ne '/^[[:space:]]*$/d; /^#/d; p' \
+ /etc/sysupgrade.conf /lib/upgrade/keep.d/* 2>/dev/null) \
+ -type f 2>/dev/null;
+ opkg list-changed-conffiles ) | sort -u > "$file"
+ return 0
+}
+
+add_overlayfiles() {
+ local file="$1"
+ find /overlay/etc/ -type f | sed \
+ -e 's,^/overlay/,/,' \
+ -e '\,/META_[a-zA-Z0-9]*$,d' \
+ -e '\,/functions.sh$,d' \
+ -e '\,/[^/]*-opkg$,d' \
+ > "$file"
+ return 0
+}
+
+# hooks
+sysupgrade_image_check="platform_check_image"
+[ $SAVE_OVERLAY = 0 -o ! -d /overlay/etc ] && \
+ sysupgrade_init_conffiles="add_uci_conffiles" || \
+ sysupgrade_init_conffiles="add_overlayfiles"
+
+include /lib/upgrade
+
+do_save_conffiles() {
+ local conf_tar="${1:-$CONF_TAR}"
+
+ [ -z "$(rootfs_type)" ] && {
+ echo "Cannot save config while running from ramdisk."
+ ask_bool 0 "Abort" && exit
+ return 0
+ }
+ run_hooks "$CONFFILES" $sysupgrade_init_conffiles
+ ask_bool 0 "Edit config file list" && vi "$CONFFILES"
+
+ v "Saving config files..."
+ [ "$VERBOSE" -gt 1 ] && TAR_V="v" || TAR_V=""
+ tar c${TAR_V}zf "$conf_tar" -T "$CONFFILES" 2>/dev/null
+}
+
+if [ -n "$CONF_BACKUP" ]; then
+ do_save_conffiles "$CONF_BACKUP"
+ exit $?
+fi
+
+if [ -f "$CONF_RESTORE" ] || [ "$CONF_RESTORE" = "-" ]; then
+ [ "$VERBOSE" -gt 1 ] && TAR_V="v" || TAR_V=""
+ tar -C / -x${TAR_V}zf "$CONF_RESTORE"
+ exit $?
+fi
+
+type platform_check_image >/dev/null 2>/dev/null || {
+ echo "Firmware upgrade is not implemented for this platform."
+ exit 1
+}
+
+for check in $sysupgrade_image_check; do
+ ( eval "$check \"\$ARGV\"" ) || {
+ if [ $FORCE -eq 1 ]; then
+ echo "Image check '$check' failed but --force given - will update anyway!"
+ break
+ else
+ echo "Image check '$check' failed."
+ exit 1
+ fi
+ }
+done
+
+if [ -n "$CONF_IMAGE" ]; then
+ case "$(get_magic_word $CONF_IMAGE cat)" in
+ # .gz files
+ 1f8b) ;;
+ *)
+ echo "Invalid config file. Please use only .tar.gz files"
+ exit 1
+ ;;
+ esac
+ get_image "$CONF_IMAGE" "cat" > "$CONF_TAR"
+ export SAVE_CONFIG=1
+elif ask_bool $SAVE_CONFIG "Keep config files over reflash"; then
+ do_save_conffiles
+ export SAVE_CONFIG=1
+else
+ export SAVE_CONFIG=0
+fi
+
+run_hooks "" $sysupgrade_pre_upgrade
+
+kill_remaining TERM
+sleep 3
+kill_remaining KILL
+
+if [ -n "$(rootfs_type)" ]; then
+ v "Switching to ramdisk..."
+ run_ramfs '. /lib/functions.sh; include /lib/upgrade; do_upgrade'
+else
+ do_upgrade
+fi
diff --git a/package/base-files/files/sbin/wifi b/package/base-files/files/sbin/wifi
new file mode 100755
index 000000000..ef207878b
--- /dev/null
+++ b/package/base-files/files/sbin/wifi
@@ -0,0 +1,204 @@
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+. /lib/functions.sh
+
+usage() {
+ cat <<EOF
+Usage: $0 [down|detect]
+enables (default), disables or detects a wifi configuration.
+EOF
+ exit 1
+}
+
+find_net_config() {(
+ local vif="$1"
+ local cfg
+ local ifname
+
+ config_get cfg "$vif" network
+
+ [ -z "$cfg" ] && {
+ include /lib/network
+ scan_interfaces
+
+ config_get ifname "$vif" ifname
+
+ cfg="$(find_config "$ifname")"
+ }
+ [ -z "$cfg" ] && return 0
+ echo "$cfg"
+)}
+
+
+bridge_interface() {(
+ local cfg="$1"
+ [ -z "$cfg" ] && return 0
+
+ include /lib/network
+ scan_interfaces
+
+ for cfg in $cfg; do
+ config_get iftype "$cfg" type
+ [ "$iftype" = bridge ] && config_get "$cfg" ifname
+ prepare_interface_bridge "$cfg"
+ return $?
+ done
+)}
+
+prepare_key_wep() {
+ local key="$1"
+ local hex=1
+
+ echo -n "$key" | grep -qE "[^a-fA-F0-9]" && hex=0
+ [ "${#key}" -eq 10 -a $hex -eq 1 ] || \
+ [ "${#key}" -eq 26 -a $hex -eq 1 ] || {
+ [ "${key:0:2}" = "s:" ] && key="${key#s:}"
+ key="$(echo -n "$key" | hexdump -ve '1/1 "%02x" ""')"
+ }
+ echo "$key"
+}
+
+wifi_fixup_hwmode() {
+ local device="$1"
+ local default="$2"
+ local hwmode hwmode_11n
+
+ config_get channel "$device" channel
+ config_get hwmode "$device" hwmode
+ case "$hwmode" in
+ 11bg) hwmode=bg;;
+ 11a) hwmode=a;;
+ 11b) hwmode=b;;
+ 11g) hwmode=g;;
+ 11n*)
+ hwmode_11n="${hwmode##11n}"
+ case "$hwmode_11n" in
+ a|g) ;;
+ default) hwmode_11n="$default"
+ esac
+ config_set "$device" hwmode_11n "$hwmode_11n"
+ ;;
+ *)
+ hwmode=
+ if [ "${channel:-0}" -gt 0 ]; then
+ if [ "${channel:-0}" -gt 14 ]; then
+ hwmode=a
+ else
+ hwmode=g
+ fi
+ else
+ hwmode="$default"
+ fi
+ ;;
+ esac
+ config_set "$device" hwmode "$hwmode"
+}
+
+wifi_updown() {
+ [ enable = "$1" ] && {
+ wifi_updown disable "$2"
+ scan_wifi
+ }
+ for device in ${2:-$DEVICES}; do (
+ config_get disabled "$device" disabled
+ [ 1 == "$disabled" ] && {
+ echo "'$device' is disabled"
+ set disable
+ }
+ config_get iftype "$device" type
+ if eval "type ${1}_$iftype" 2>/dev/null >/dev/null; then
+ eval "scan_$iftype '$device'"
+ eval "${1}_$iftype '$device'" || echo "$device($iftype): ${1} failed"
+ else
+ echo "$device($iftype): Interface type not supported"
+ fi
+ ); done
+}
+
+wifi_detect() {
+ for driver in ${2:-$DRIVERS}; do (
+ if eval "type detect_$driver" 2>/dev/null >/dev/null; then
+ eval "detect_$driver" || echo "$driver: Detect failed" >&2
+ else
+ echo "$driver: Hardware detection not supported" >&2
+ fi
+ ); done
+}
+
+start_net() {(
+ local iface="$1"
+ local config="$2"
+ local vifmac="$3"
+
+ [ -f "/var/run/$iface.pid" ] && kill "$(cat /var/run/${iface}.pid)" 2>/dev/null
+ [ -z "$config" ] || {
+ include /lib/network
+ scan_interfaces
+ for config in $config; do
+ setup_interface "$iface" "$config" "" "$vifmac"
+ done
+ }
+)}
+
+set_wifi_up() {
+ local cfg="$1"
+ local ifname="$2"
+ uci_set_state wireless "$cfg" up 1
+ uci_set_state wireless "$cfg" ifname "$ifname"
+}
+
+set_wifi_down() {
+ local cfg="$1"
+ local vifs vif vifstr
+
+ [ -f "/var/run/wifi-${cfg}.pid" ] &&
+ kill "$(cat "/var/run/wifi-${cfg}.pid")" 2>/dev/null
+ uci_revert_state wireless "$cfg"
+ config_get vifs "$cfg" vifs
+ for vif in $vifs; do
+ uci_revert_state wireless "$vif"
+ done
+}
+
+scan_wifi() {
+ local cfgfile="$1"
+ DEVICES=
+ config_cb() {
+ local type="$1"
+ local section="$2"
+
+ # section start
+ case "$type" in
+ wifi-device)
+ append DEVICES "$section"
+ config_set "$section" vifs ""
+ config_set "$section" ht_capab ""
+ ;;
+ esac
+
+ # section end
+ config_get TYPE "$CONFIG_SECTION" TYPE
+ case "$TYPE" in
+ wifi-iface)
+ config_get device "$CONFIG_SECTION" device
+ config_get vifs "$device" vifs
+ append vifs "$CONFIG_SECTION"
+ config_set "$device" vifs "$vifs"
+ ;;
+ esac
+ }
+ config_load "${cfgfile:-wireless}"
+}
+
+DEVICES=
+DRIVERS=
+include /lib/wifi
+scan_wifi
+
+case "$1" in
+ down) wifi_updown "disable" "$2";;
+ detect) wifi_detect "$2";;
+ --help|help) usage;;
+ *) wifi_updown "enable" "$2";;
+esac
diff --git a/package/base-files/image-config.in b/package/base-files/image-config.in
new file mode 100644
index 000000000..ac08c8da7
--- /dev/null
+++ b/package/base-files/image-config.in
@@ -0,0 +1,185 @@
+# Copyright (C) 2006-2012 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+menuconfig PREINITOPT
+ bool "Preinit configuration options" if IMAGEOPT
+ default n
+ help
+ These options are used to control the environment used to initialize
+ the system before running init (which typically mean /sbin/init which
+ switches to multiuser mode).
+
+config TARGET_PREINIT_SUPPRESS_STDERR
+ bool "Suppress stderr messages during preinit" if PREINITOPT
+ default y
+ help
+ Sends stderr to null during preinit. This is the default behaviour
+ in previous versions of OpenWRT. This also prevents init process
+ itself from displaying stderr, however processes launched by init
+ in multiuser through inittab will use the current terminal (e.g.
+ the ash shell launched by inittab will display stderr). That's
+ the same behaviour as seen in previous version of OpenWRT.
+
+config TARGET_PREINIT_TIMEOUT
+ int
+ prompt "Failsafe wait timeout" if PREINITOPT
+ default 2
+ help
+ How long to wait for failsafe mode to be entered before
+ continuing with a regular boot if failsafe not selected.
+
+config TARGET_PREINIT_SHOW_NETMSG
+ bool
+ prompt "Show all preinit network messages" if PREINITOPT
+ default n
+ help
+ Show preinit all network messages (via netmsg broadcast), not only
+ the message indicating to press reset to enter failsafe. Note that
+ if the architecture doesn't define an interface, and there is no
+ 'Preinit network interface' defined, then no messages will be
+ emitted, even if this is set.
+
+config TARGET_PREINIT_SUPPRESS_FAILSAFE_NETMSG
+ bool
+ prompt "Suppress network message indicating failsafe" if PREINITOPT
+ default n
+ help
+ If "Show all preinit network messages" above is not set, then
+ setting this option suppresses the only message that would be
+ emitted otherwise, name the network message to enter failsafe
+ (via netmsg).
+
+config TARGET_PREINIT_IFNAME
+ string
+ prompt "Preinit network interface" if PREINITOPT
+ default ""
+ help
+ Interface for sending preinit messages to network, and any other
+ default networking in failsafe or preinit. If empty
+ uses $ifname (if defined in /etc/preinit.arch).
+
+config TARGET_PREINIT_IP
+ string
+ prompt "IP address for preinit network messages" if PREINITOPT
+ default "192.168.1.1"
+ help
+ IP address used to configure interface for preinit network
+ messages, including failsafe messages
+
+config TARGET_PREINIT_NETMASK
+ string
+ prompt "Netmask for preinit network messages" if PREINITOPT
+ default "255.255.255.0"
+ help
+ Netmask used to configure interface for preinit network
+ messages, including failsafes messages
+
+config TARGET_PREINIT_BROADCAST
+ string
+ prompt "Broadcast address for preinit network messages" if PREINITOPT
+ default "192.168.1.255"
+ help
+ Broadcast address to which to send preinit network messages, as
+ as failsafe messages
+
+
+menuconfig INITOPT
+ bool "Init configuration options" if IMAGEOPT
+ default n
+ help
+ These option choose the command that will run as the 'init' command
+ (that is which is responsible for controlling the system once preinit
+ transfers control to it) as well as some options controlling its
+ behaviour. Normally init is /sbin/init.
+
+ config TARGET_INIT_PATH
+ string
+ prompt "PATH for regular boot" if INITOPT
+ default "/bin:/sbin:/usr/bin:/usr/sbin"
+ help
+ Default PATH used during normal operation
+
+ config TARGET_INIT_ENV
+ string
+ prompt "Environment variables to set when starting init (start with none)" if INITOPT
+ default ""
+ help
+ Should be a space seperated list of variable assignments. These
+ variables will be present in the environment. Spaces may not be
+ present (including through expansion) even in a quoted string
+ (env doesn't understanding quoting).
+
+ config TARGET_INIT_CMD
+ string
+ prompt "Init command" if INITOPT
+ default "/sbin/init"
+ help
+ The executable to run as the init process. Is 'exec'd by
+ preinit (which is the init that the kernel launches on boot).
+
+ config TARGET_INIT_SUPPRESS_STDERR
+ bool
+ prompt "Suppress stderr messages of init" if INITOPT
+ default y
+ help
+ Prevents showing stderr messages for init command if not already
+ suppressed during preinit. This is the default behaviour in
+ previous versions of OpenWRT. Removing this does nothing if
+ stderr is suppressed during preinit (which is the default).
+
+
+menuconfig VERSIONOPT
+ bool "Version configuration options" if IMAGEOPT
+ default n
+ help
+ These options allow to override the version information embedded in
+ the /etc/openwrt_version, /etc/openwrt_release, /etc/banner and
+ /etc/opkg.conf files. Usually there is no need to set these, but
+ they're useful for release builds or custom OpenWrt redistributions
+ that should carry custom version tags.
+
+ config VERSION_DIST
+ string
+ prompt "Release distribution" if VERSIONOPT
+ default "OpenWrt" if VERSIONOPT
+ help
+ This is the name of the release distribution.
+ If unspecified, it defaults to OpenWrt.
+
+ config VERSION_NICK
+ string
+ prompt "Release version nickname" if VERSIONOPT
+ help
+ This is the release codename embedded in the image.
+ If unspecified, it defaults to the name of source branch.
+
+ config VERSION_NUMBER
+ string
+ prompt "Release version number" if VERSIONOPT
+ help
+ This is the release version number embedded in the image.
+ If unspecified, it defaults to the svn or git-svn revision
+ of the build tree.
+
+ config VERSION_REPO
+ string
+ prompt "Release repository" if VERSIONOPT
+ default "http://downloads.openwrt.org/snapshots/trunk/%T/packages" if VERSIONOPT
+ help
+ This is the repository address embedded in the image, it defaults
+ to the trunk snapshot repo; the url may contain the following placeholders:
+ %R .. Revision number
+ %V .. Release version or revision number, uppercase
+ %v .. Release version or revision number, lowercase
+ %C .. Release version or "Bleeding Edge", uppercase
+ %c .. Release version or "bleeding_edge", lowercase
+ %N .. Release name, uppercase
+ %n .. Release name, lowercase
+ %D .. Distribution name or "OpenWrt", uppercase
+ %d .. Distribution name or "openwrt", lowercase
+ %T .. Target name
+ %S .. Target/Subtarget name
diff --git a/package/block-mount/Config.in b/package/block-mount/Config.in
new file mode 100644
index 000000000..2fa10b668
--- /dev/null
+++ b/package/block-mount/Config.in
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2010 Vertical Communications
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+config EXTROOT_SETTLETIME
+ int
+ prompt "Settle time for root block device (s)" if PACKAGE_block-mount
+ default 20
+ help
+ This is the amount of time, in seconds, to wait for the block device
+ the root filesystem is on to become available, after the kernel that
+ modules for the rootfs and device are loaded.
+
+
diff --git a/package/block-mount/Makefile b/package/block-mount/Makefile
new file mode 100644
index 000000000..799539e4b
--- /dev/null
+++ b/package/block-mount/Makefile
@@ -0,0 +1,70 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=block-mount
+PKG_VERSION:=0.2.0
+PKG_RELEASE:=9
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/block-mount/Default
+ SECTION:=base
+ CATEGORY:=Base system
+endef
+
+define Package/block-mount
+ $(call Package/block-mount/Default)
+ TITLE:=Block device mounting and checking
+ DEPENDS:= +blkid +swap-utils
+ MENU:=1
+endef
+
+define Package/block-mount/description
+ Scripts used to mount and check block devices (filesystems and swap), as well
+ as hotplug scripts to automount and check block devices when hotplug event (e.g.
+ from plugging in a device) occurs.
+ Also includes preinit scripts for mounting a block device as the root filesystem.
+ This allows one to have the root filesystem on devices other than the built in flash
+ device.
+endef
+
+define Package/block-mount/config
+ source "$(SOURCE)/Config.in"
+endef
+
+define Build/Compile
+endef
+
+define Package/block-mount/conffiles
+/etc/config/fstab
+endef
+
+define Package/block-mount/install
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/fstab.init $(1)/etc/init.d/fstab
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/fstab.config $(1)/etc/config/fstab
+ $(INSTALL_DIR) $(1)/lib/functions/fsck
+ $(INSTALL_DATA) ./files/mount.sh $(1)/lib/functions/
+ $(INSTALL_DATA) ./files/fsck.sh $(1)/lib/functions/
+ $(INSTALL_DATA) ./files/block.sh $(1)/lib/functions/
+ $(INSTALL_DIR) $(1)/etc/hotplug.d/block
+ $(INSTALL_DATA) ./files/10-swap $(1)/etc/hotplug.d/block/
+ $(INSTALL_DATA) ./files/20-fsck $(1)/etc/hotplug.d/block/
+ $(INSTALL_DATA) ./files/40-mount $(1)/etc/hotplug.d/block/
+ $(INSTALL_DATA) ./files/extmount.sh $(1)/lib/functions/
+ $(INSTALL_DIR) $(1)/lib/preinit
+ $(INSTALL_DATA) ./files/50_determine_usb_root $(1)/lib/preinit/
+ $(INSTALL_DATA) ./files/55_determine_extroot_sysupgrade $(1)/lib/preinit/
+ $(INSTALL_DATA) ./files/60_pivot_usb_root $(1)/lib/preinit/
+ echo "extroot_settle_time=\"$(CONFIG_EXTROOT_SETTLETIME)\"" >$(1)/lib/preinit/00_extroot.conf
+ $(INSTALL_DIR) $(1)/overlay
+endef
+
+$(eval $(call BuildPackage,block-mount))
diff --git a/package/block-mount/files/10-swap b/package/block-mount/files/10-swap
new file mode 100644
index 000000000..2837d2763
--- /dev/null
+++ b/package/block-mount/files/10-swap
@@ -0,0 +1,78 @@
+#!/bin/sh
+# Copyright (C) 2009-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+. /lib/functions/block.sh
+
+blkdev=`dirname $DEVPATH`
+
+if [ `basename $blkdev` != "block" ]; then
+
+ device=`basename $DEVPATH`
+
+
+ case "$ACTION" in
+ add)
+ local autoswap_from_fstab
+ local automount_from_fstab
+ local from_fstab
+ local anon_mount
+ local anon_swap
+ local anon_fsck
+ local mds_mount_device
+ local sds_swap_device
+ local sds_swap_enabled
+ local use_device
+ local do_swap=0
+
+ mount_dev_section_cb() {
+ mds_mount_device="$3"
+ }
+
+ swap_dev_section_cb() {
+ sds_swap_device="$2"
+ sds_swap_enabled="$3"
+ return 0
+ }
+
+ config_get_automount
+ automount_from_fstab="$from_fstab"
+
+ [ "$automount_from_fstab" -eq 1 ] && {
+ config_get_mount_section_by_device "/dev/$device"
+ }
+
+ # skip trying swap if this device is defined as a mount point
+ [ -z "$mds_mount_device" ] && {
+ config_get_autoswap
+ autoswap_from_fstab="$from_fstab"
+
+ [ "$autoswap_from_fstab" -eq 1 ] && {
+ config_get_swap_section_by_device "/dev/$device"
+ use_device="$sds_swap_device"
+ do_swap="$sds_swap_enabled"
+ }
+
+ [ -z "$use_device" ] && [ "$anon_swap" -eq 1 ] && {
+ use_device="/dev/$device" && do_swap=1
+ }
+ }
+
+ [ -n "$use_device" ] && [ "$do_swap" -eq 1 ] && {
+ grep -q "$use_device" /proc/swaps || grep -q "$use_device" /proc/mounts || {
+ swapon "$use_device"
+ }
+ }
+ reset_dev_section_cb
+ ;;
+ remove)
+ grep -q "/dev/$device" /proc/swaps && {
+ swapoff "/dev/$device"
+ }
+ ;;
+ esac
+fi
+
diff --git a/package/block-mount/files/20-fsck b/package/block-mount/files/20-fsck
new file mode 100644
index 000000000..c59e5abd7
--- /dev/null
+++ b/package/block-mount/files/20-fsck
@@ -0,0 +1,83 @@
+#!/bin/sh
+# Copyright (C) 2009-2010 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+. /lib/functions/block.sh
+. /lib/functions/fsck.sh
+
+blkdev=`dirname $DEVPATH`
+
+if [ `basename $blkdev` != "block" ]; then
+
+ device=`basename $DEVPATH`
+
+ case "$ACTION" in
+ add)
+ local from_fstab
+ local anon_mount
+ local anon_swap
+ local anon_fsck
+ local mds_mount_target
+ local mds_mount_device
+ local mds_mount_fstype
+ local mds_mount_enabled_fsck
+ local sds_swap_device
+ local use_device
+ local do_fsck=0
+ local fsck_type
+
+ local autoswap_from_fstab
+ local automount_from_fstab
+ local hotplug_blkid_fstype_match
+
+ mount_dev_section_cb() {
+ mds_mount_device="$3"
+ mds_mount_fstype="$4"
+ mds_mount_enabled_fsck="$7"
+ }
+
+ swap_dev_section_cb() {
+ sds_swap_device="$2"
+ return 0
+ }
+
+ config_get_automount
+ automount_from_fstab="$from_fstab"
+
+ [ "$automount_from_fstab" -eq 1 ] && {
+ config_get_mount_section_by_device "/dev/$device"
+ use_device="$mds_mount_device"
+ [ "$mds_mount_enabled_fsck" -eq 1 ] && {
+ do_fsck=1
+ fsck_type="$mds_mount_fstype"
+ }
+ }
+
+ [ -z "$use_device" ] && {
+ config_get_autoswap
+ autoswap_from_fstab="$from_fstab"
+
+ [ "$autoswap_from_fstab" -eq 1 ] && {
+ config_get_swap_section_by_device "/dev/$device"
+ use_device="$sds_swap_device" && do_fsck=0
+ }
+ }
+
+ grep -q "/dev/$device" /proc/swaps || grep -q "/dev/$device" /proc/mounts || {
+ [ "$anon_fsck" -eq 1 ] && [ -z "$use_device" ] && {
+ use_device="/dev/$device" && do_fsck=1 && mds_mount_fstype="" && hotplug_blkid_fstype_match=0
+ }
+ }
+
+ [ "$do_fsck" -eq 1 ] && {
+ libmount_fsck "$use_device" "$fsck_type" "$do_fsck"
+ }
+
+ reset_dev_section_cb
+ ;;
+ esac
+fi
+
diff --git a/package/block-mount/files/40-mount b/package/block-mount/files/40-mount
new file mode 100644
index 000000000..f1d63eba6
--- /dev/null
+++ b/package/block-mount/files/40-mount
@@ -0,0 +1,91 @@
+#!/bin/sh
+# Copyright (C) 2009-2012 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+. /lib/functions/block.sh
+
+blkdev=`dirname $DEVPATH`
+if [ `basename $blkdev` != "block" ]; then
+
+ device=`basename $DEVPATH`
+ mountpoint=`sed -ne "s|^[^ ]*/$device ||; T; s/ .*//p" /proc/self/mounts`
+
+ case "$ACTION" in
+ add)
+
+ local from_fstab
+ local anon_mount
+ local anon_swap
+ local anon_fsck
+ local mds_mount_target
+ local mds_mount_device
+ local mds_mount_fstype
+ local sds_swap_device
+ local use_device
+ local do_fsck=0
+ local fsck_type
+
+ local autoswap_from_fstab
+ local automount_from_fstab
+
+ mount_dev_section_cb() {
+ mds_mount_target="$2"
+ mds_mount_device="$3"
+ mds_mount_fstype="$4"
+ mds_mount_enabled="$6"
+ }
+
+ swap_dev_section_cb() {
+ sds_swap_device="$2"
+ return 0
+ }
+
+ config_get_automount
+ automount_from_fstab="$from_fstab"
+ [ "$automount_from_fstab" -eq 1 ] && {
+ config_get_mount_section_by_device "/dev/$device"
+ use_device="$mds_mount_device"
+ [ "$mds_mount_enabled" -eq 1 ] && {
+ if [ -n "$mds_mount_target" ]; then
+ grep -q "/dev/$device" /proc/swaps || grep -q "/dev/$device" /proc/mounts || {
+ ( mkdir -p "$mds_mount_target" && mount "$mds_mount_target" ) 2>&1 | tee /proc/self/fd/2 | logger -t 'fstab'
+ }
+ else
+ logger -t 'fstab' "Mount enabled for $mds_mount_device but it doesn't have a defined mountpoint (target)"
+ fi
+ }
+ }
+
+ [ -z "$use_device" ] && {
+ config_get_autoswap
+ autoswap_from_fstab="$from_fstab"
+
+ [ "$autoswap_from_fstab" -eq 1 ] && {
+ config_get_swap_section_by_device "/dev/$device"
+ use_device="$sds_swap_device"
+ }
+ }
+
+ grep -q "/dev/$device" /proc/swaps || grep -q "/dev/$device" /proc/mounts || {
+ [ "$anon_mount" -eq 1 -a -z "$use_device" ] && {
+ case "$device" in
+ mtdblock*) ;;
+ *)
+ ( mkdir -p /mnt/$device && mount /dev/$device /mnt/$device ) 2>&1 | tee /proc/self/fd/2 | logger -t 'fstab'
+ ;;
+ esac
+ }
+ }
+ reset_dev_section_cb
+ ;;
+ remove)
+ umount /dev/$device
+ umount $mountpoint
+ ;;
+ esac
+
+fi
+
diff --git a/package/block-mount/files/50_determine_usb_root b/package/block-mount/files/50_determine_usb_root
new file mode 100644
index 000000000..d39806266
--- /dev/null
+++ b/package/block-mount/files/50_determine_usb_root
@@ -0,0 +1,65 @@
+#!/bin/sh
+# Copyright (C) 2010 Vertical Communications
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+
+determine_external_root() {
+ pi_include /lib/functions/extmount.sh
+ pi_include /lib/functions/mount.sh
+
+ local OLD_UCI_CONFIG_DIR="$UCI_CONFIG_DIR"
+ local OLD_PATH="$PATH"
+ local OLD_LD_LIBRARY_PATH="$LD_LIBRARY_PATH"
+ set_jffs_mp
+ determine_root_device
+
+ # extroot requires extroot and fstab config files, therefore
+ # we assume configuration is incomplete and not to be used if either of them
+ # is missing (for jffs versions of these files on squashfs image)
+ if [ "$jffs" = "/tmp/overlay" ] && [ -r "/tmp/overlay/etc/config/fstab" ]; then
+ UCI_CONFIG_DIR="/tmp/overlay/etc/config"
+ ER_IS_SQUASHFS=true
+ ER_OVERLAY_PREFIX="/tmp/overlay"
+ PATH=$ER_OVERLAY_PREFIX/sbin:$PATH
+ LD_LIBRARY_PATH=$ER_OVERLAY_PREFIX/usr/lib:$LD_LIBRARY_PATH
+ export PATH LD_LIBRARY_PATH
+ fi
+
+ # For squashfs on firstboot root_device will be tmpfs for the ramoverlay,
+ # unless there is a saved config, in which case it will be /dev/root,
+ # however in the case of a saved config, it won't be restored until after
+ # this script, so there won't be a config on the first boot after
+ # flashing a squashfs-based filesystem
+ # For ext2, ramdisk, or jffs2 root filesystems root_device is /dev/root
+ # For squashfs after firstboot, root filesystem is /dev/root
+ # We only use the config from the root or jffs if the root_device is
+ # /dev/root
+ [ "$root_device" = "/dev/root" ] && {
+ er_load_modules
+ [ -n "$extroot_settle_time" ] && [ "$extroot_settle_time" -gt 0 ] && {
+ sleep $extroot_settle_time
+ }
+ config_load fstab
+ config_foreach config_mount_by_section mount 1
+ ER_OVERLAY_ROM="/no-extroot"
+
+ [ "$rootfs_found" = "1" ] && grep -q ' /overlay ' /proc/mounts && {
+ pi_extroot_mount_success=true
+ pi_mount_skip_next=false
+ ER_OVERLAY_ROM="/overlay"
+ }
+ [ "$rootfs_found" = "1" ] && grep -q ' /rom ' /proc/mounts && {
+ pi_extroot_mount_success=true
+ pi_mount_skip_next=false
+ ER_OVERLAY_ROM="/rom"
+ }
+ }
+ UCI_CONFIG_DIR="$OLD_UCI_CONFIG_DIR"
+ PATH="$OLD_PATH"
+ LD_LIBRARY_PATH="$OLD_LD_LIBRARY_PATH"
+ export PATH LD_LIBRARY_PATH
+}
+
+boot_hook_add preinit_mount_root determine_external_root
+
diff --git a/package/block-mount/files/55_determine_extroot_sysupgrade b/package/block-mount/files/55_determine_extroot_sysupgrade
new file mode 100644
index 000000000..b0cd9036c
--- /dev/null
+++ b/package/block-mount/files/55_determine_extroot_sysupgrade
@@ -0,0 +1,63 @@
+#!/bin/sh
+# Copyright (C) 2010 Daniel Dickinson
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+
+check_set_md5sum() {
+ local er_md5sum_file
+ er_md5sum_file="${ER_OVERLAY_PREFIX}/.extroot.md5sum"
+ local er_disabled
+ if [ "${ER_OVERLAY_ROM}" = "/rom" ]; then
+ er_disabled=/tmp/whole_root-disabled
+ else
+ er_disabled=/tmp${ER_OVERLAY_ROM}-disabled
+ fi
+
+ local er_extroot_md5sum
+ if [ -f $md5sum_file ]; then
+ er_extroot_md5sum="$(cat $er_md5sum_file)"
+ fi
+
+ local er_overlay_file="${ER_OVERLAY_ROM}/etc/extroot.md5sum"
+
+ local er_extroot_overlay_md5sum
+ if [ -f "$er_overlay_file" ]; then
+ er_extroot_overlay_md5sum="$(cat $er_overlay_file)"
+ fi
+
+ if [ -z "$er_extroot_overlay_md5sum" ]; then
+ cat $er_md5sum_file >$er_overlay_file
+ elif [ "$er_extroot_overlay_md5sum" != "$er_extroot_md5sum" ]; then
+ pi_extroot_mount_success="false"
+ mkdir -p $er_disabled
+ mount --move ${ER_OVERLAY_ROM} $er_disabled
+ fi
+}
+
+set_jffs_md5sum() {
+ # We do this anytime block-extroot exists, even on the first boot with
+ # no extroot defined.
+
+ local er_md5sum_file
+ er_md5sum_file="${ER_OVERLAY_PREFIX}/.extroot.md5sum"
+
+ local er_extroot_md5sum
+ if [ -f $er_md5sum_file ]; then
+ er_extroot_md5sum="$(cat $er_md5sum_file)"
+ fi
+ if [ -z "$er_extroot_md5sum" ]; then
+ dd if=/dev/urandom count=32 bs=1k 2>/dev/null | md5sum | cut -f1 -d\ >$er_md5sum_file
+ fi
+}
+
+determine_extroot_sysupgrade() {
+ check_skip || set_jffs_md5sum
+
+ check_skip || [ "$pi_extroot_mount_success" != "true" ] || {
+ check_set_md5sum
+ }
+}
+
+boot_hook_add preinit_mount_root determine_extroot_sysupgrade
+
diff --git a/package/block-mount/files/60_pivot_usb_root b/package/block-mount/files/60_pivot_usb_root
new file mode 100644
index 000000000..b610a4ade
--- /dev/null
+++ b/package/block-mount/files/60_pivot_usb_root
@@ -0,0 +1,27 @@
+#!/bin/sh
+# Copyright (C) 2010 Vertical Communications
+
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+# Determine if we are requested to mount external root
+
+external_root_pivot() {
+ check_skip || [ "$pi_extroot_mount_success" != "true" ] || {
+ echo "switching to external rootfs"
+ if [ "$ER_OVERLAY_ROM" = "/overlay" ]; then
+ if [ "$ER_IS_SQUASHFS" = "true" ]; then
+ umount /tmp/overlay
+ fi
+ mount -o remount,ro / && fopivot /overlay /rom && pi_mount_skip_next=true
+ elif [ "$ER_OVERLAY_ROM" = "/rom" ]; then
+ if [ "$ER_IS_SQUASHFS" = "true" ]; then
+ umount /tmp/overlay
+ fi
+ mount -o remount,ro / && pivot_rom /rom /rom && pi_mount_skip_next=true
+ fi
+ }
+}
+
+boot_hook_add preinit_mount_root external_root_pivot
+
diff --git a/package/block-mount/files/block.sh b/package/block-mount/files/block.sh
new file mode 100644
index 000000000..2b679a8e8
--- /dev/null
+++ b/package/block-mount/files/block.sh
@@ -0,0 +1,264 @@
+#!/bin/sh
+# Copyright 2010 Vertical Communications
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+. /lib/functions.sh
+
+reset_block_cb() {
+ mount_cb() {
+ dmc_mount_cfg="$1"
+ shift # skip optional param
+ dmc_target="$2"
+ dmc_mount_device="$3"
+ dmc_fstype="$4"
+ dmc_options="$5"
+ dmc_enabled="$6"
+ dmc_enabled_fsck="$7"
+ dmc_uuid="$8"
+ dmc_label="$9"
+ shift
+ dmc_is_rootfs="$9"
+ return 0
+ }
+ swap_cb() {
+ dsc_swap_cfg="$1"
+ shift # skip optional param
+ dsc_swap_device="$2"
+ dsc_enabled="$3"
+ dsc_uuid="$4"
+ dsc_label="$5"
+ return 0
+ }
+}
+reset_block_cb
+
+reset_dev_section_cb() {
+ mount_dev_section_cb() {
+ dmds_mount_cfg="$1"
+ dmds_mount_target="$2"
+ dmds_mount_device="$3"
+ dmds_mount_fstype="$4"
+ dmds_mount_options="$5"
+ dmds_mount_enabled="$6"
+ dmds_mount_enabled_fsck="$7"
+ dmds_mount_uuid="$8"
+ dmds_mount_label="$9"
+ shift
+ dmds_is_rootfs="$9"
+ return 0
+ }
+ swap_dev_section_cb() {
+ dsds_swap_cfg="$1"
+ dsds_swap_device="$2"
+ dsds_swap_enabled="$3"
+ dsds_swap_uuid="$4"
+ dsds_swap_label="$5"
+ return 0
+ }
+}
+reset_dev_section_cb
+
+config_get_mount() {
+ local gm_cfg="$1"
+ local gm_param="$2"
+ local gm_target
+ local gm_device
+ local gm_fstype
+ local gm_options
+ local gm_enabled
+ local gm_enabled_fsck
+ local gm_uuid
+ local gm_label
+ local gm_is_rootfs
+ config_get gm_target "$1" target
+ config_get gm_device "$1" device
+ config_get gm_fstype "$1" fstype 'auto'
+ config_get gm_options "$1" options 'rw'
+ config_get_bool gm_enabled "$1" enabled 1
+ config_get_bool gm_enabled_fsck "$1" enabled_fsck 0
+ config_get gm_uuid "$1" uuid
+ config_get gm_label "$1" label
+ config_get_bool gm_is_rootfs "$1" is_rootfs 0
+ mount_cb "$gm_cfg" "$gm_param" "$gm_target" "$gm_device" "$gm_fstype" "$gm_options" "$gm_enabled" "$gm_enabled_fsck" "$gm_uuid" "$gm_label" "$gm_is_rootfs"
+}
+
+config_get_swap() {
+ local gs_cfg="$1"
+ local gs_param="$2"
+ local gs_device
+ local gs_enabled
+ local gs_uuid
+ local gs_label
+ config_get gs_device "$1" device
+ config_get_bool gs_enabled "$1" enabled 1
+ config_get gs_uuid "$1" uuid
+ config_get gs_label "$1" label
+
+ swap_cb "$gs_cfg" "$gs_param" "$gs_device" "$gs_enabled" "$gs_uuid" "$gs_label"
+}
+
+config_get_automount() {
+ config_load fstab
+ config_get_bool from_fstab "automount" from_fstab 1
+ config_get_bool anon_mount "automount" anon_mount 1
+ config_get_bool anon_fsck "automount" anon_fsck 0
+}
+
+config_get_autoswap() {
+ config_load fstab
+ config_get_bool from_fstab "autoswap" from_fstab 1
+ config_get_bool anon_swap "autoswap" anon_swap 0
+}
+
+config_create_swap_fstab_entry() {
+ local device="$1"
+ local enabled="$2"
+
+ [ -n "$device" ] || return 0
+
+ local fstabnew
+
+ mkdir -p /var/lock
+ lock /var/lock/fstab.lck
+ fstabnew="$(mktemp -t '.fstab.XXXXXXXX')"
+ cat /tmp/fstab | grep -E -v "^$device[[:blank:]]" >>"$fstabnew"
+ [ "$enabled" -eq 1 ] && echo "$device none swap sw 0 0" >> "$fstabnew"
+ cat "$fstabnew" >/tmp/fstab
+ rm -f $fstabnew
+ lock -u /var/lock/fstab.lck
+}
+
+config_create_mount_fstab_entry() {
+ local device="$1"
+ local target="$2"
+ local fstype="$3"
+ local options="$4"
+ local enabled="$5"
+ options="${options:-rw}"
+ [ "$enabled" -eq 0 ] && options="noauto,$options"
+ [ -n "$target" ] || return 0
+ [ -n "$device" ] || return 0
+
+ local fstabnew
+
+ mkdir -p /var/lock
+ lock /var/lock/fstab.lck
+ fstabnew="$(mktemp -t '.fstab.XXXXXXXX')"
+ cat /tmp/fstab | grep -E -v "^$device[[:blank:]]" | grep -v "$target" >>"$fstabnew"
+ echo "$device $target $fstype $options 0 0" >>"$fstabnew"
+ cat "$fstabnew" >/tmp/fstab
+ rm -f $fstabnew
+ lock -u /var/lock/fstab.lck
+}
+
+libmount_find_token() {
+ local token="$1"
+ local value="$2"
+ local device
+ device="$(blkid -w /dev/null -c /dev/null | grep "$token=\"$value\"" | cut -f1 -d:)"
+ echo "$device"
+}
+
+libmount_find_device_by_id() {
+ local uuid="$1"
+ local label="$2"
+ local device="$3"
+ local cfg_device="$4"
+ local found_device
+
+ if [ -n "$uuid" ]; then
+ found_device="$(libmount_find_token "UUID" "$uuid")"
+ elif [ -n "$label" ]; then
+ found_device="$(libmount_find_token "LABEL" "$label")"
+ elif [ "$device" = "$cfg_device" ]; then
+ found_device="$device"
+ elif [ -z "$device" ] && [ -e "$cfg_device" ]; then
+ found_device="$cfg_device"
+ fi
+ [ -n "$device" ] && [ "$device" != "$found_device" ] && {
+ found_device=""
+ }
+ echo "$found_device"
+}
+
+config_get_mount_section_by_device() {
+ local msbd_device="$1"
+ local msbd_mount_cfg=
+ local msbd_target=
+ local msbd_mount_device=
+ local msbd_fstype=
+ local msbd_options=
+ local msbd_enabled=
+ local msbd_enabled_fsck=
+ local msbd_uuid=
+ local msbd_label=
+ local msbd_is_rootfs
+ local msbd_blkid_fstype_match=
+ mount_cb() {
+ local mc_cfg="$1"
+ local mc_device="$2"
+ shift
+ local mc_target="$2"
+ local mc_cfgdevice="$3"
+ local mc_fstype="$4"
+ local mc_uuid="$8"
+ local mc_label="$9"
+ shift
+ local mc_is_rootfs="$9"
+ local mc_found_device=""
+
+ mc_found_device="$(libmount_find_device_by_id "$mc_uuid" "$mc_label" "$mc_device" "$mc_cfgdevice")"
+ if [ -n "$mc_found_device" ]; then
+ msbd_mount_cfg="$mc_cfg"
+ msbd_target="$mc_target"
+ msbd_mount_device="$mc_found_device"
+ msbd_fstype="$mc_fstype"
+ msbd_options="$4"
+ msbd_enabled="$5"
+ msbd_enabled_fsck="$6"
+ msbd_uuid="$7"
+ msbd_label="$8"
+ msbd_is_rootfs="$9"
+ fi
+ return 0
+ }
+ config_foreach config_get_mount mount "$msbd_device"
+ [ -n "$msbd_mount_device" ] && config_create_mount_fstab_entry "$msbd_mount_device" "$msbd_target" "$msbd_fstype" "$msbd_options" "$msbd_enabled"
+ mount_dev_section_cb "$msbd_mount_cfg" "$msbd_target" "$msbd_mount_device" "$msbd_fstype" "$msbd_options" "$msbd_enabled" "$msbd_enabled_fsck" "$msbd_uuid" "$msbd_label" "$msbd_is_rootfs"
+ reset_block_cb
+}
+
+config_get_swap_section_by_device() {
+ local ssbd_device="$1"
+ local ssbd_swap_cfg=
+ local ssbd_swap_device=
+ local ssbd_enabled=
+ local ssbd_uuid=
+ local ssbd_label=
+ swap_cb() {
+ local sc_cfg="$1"
+ local sc_device="$2"
+ local sc_uuid="$5"
+ local sc_label="$6"
+ local sc_cfgdevice="$3"
+ local sc_found_device
+
+ sc_found_device="$(libmount_find_device_by_id "$sc_uuid" "$sc_label" "$sc_device" "$sc_cfgdevice")"
+ if [ -n "$sc_found_device" ]; then
+ ssbd_swap_cfg="$sc_cfg"
+ ssbd_swap_device="$sc_found_device"
+ ssbd_enabled="$4"
+ ssbd_uuid="$5"
+ ssbd_label="$6"
+ fi
+ return 0
+ }
+ config_foreach config_get_swap swap "$ssbd_device"
+ [ -n "$ssbd_swap_device" ] && config_create_swap_fstab_entry "$ssbd_swap_device" "$ssbd_enabled"
+ swap_dev_section_cb "$ssbd_swap_cfg" "$ssbd_swap_device" "$ssbd_enabled" "$ssbd_uuid" "$ssbd_label"
+ reset_block_cb
+}
+
+
diff --git a/package/block-mount/files/extmount.sh b/package/block-mount/files/extmount.sh
new file mode 100644
index 000000000..d6387cc58
--- /dev/null
+++ b/package/block-mount/files/extmount.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+# Copyright (C) 2006-2011 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+determine_root_device() {
+ root_device="$(mount | grep ' / ' | cut -f1 -d\ | grep -v rootfs )"
+}
+
+set_jffs_mp() {
+ jffs="$(awk '/jffs2/ {print $2}' /proc/mounts)"
+}
+
+er_load_modules() {
+ mkdir -p /tmp/extroot_modules/modules.d
+ mkdir -p /tmp/extroot_modules/modules
+ cp -L /etc/modules-boot.d/* /tmp/overlay/etc/modules-boot.d/* /tmp/extroot_modules/modules.d
+ ln -sf /lib/modules/*/* /tmp/overlay/lib/modules/*/* /tmp/extroot_modules/modules
+ local modules="$(cat /tmp/extroot_modules/modules.d/* 2>/dev/null)"
+ cd /tmp/extroot_modules/modules && [ -n "$modules" ] && {
+ echo "$modules" | sed -e 's/^\([^#].*\)/insmod \.\/\1.ko/'| sh 2>&- || :
+ }
+ rm -rf /tmp/extroot_modules
+}
+
+pivot_rom() { # <new_root> <old_root>
+ mount -o move /proc $1/proc && \
+ pivot_root $1 $1$2 && {
+ mount -o move $2/dev /dev
+ mount -o move $2/tmp /tmp
+ mount -o move $2/sys /sys 2>&-
+ return 0
+ }
+}
+
diff --git a/package/block-mount/files/fsck.sh b/package/block-mount/files/fsck.sh
new file mode 100644
index 000000000..3011160a4
--- /dev/null
+++ b/package/block-mount/files/fsck.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+# Copyright 2010 Vertical Communications
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+libmount_fsck() {
+ local device="$1"
+ local fsck_fstype="$2"
+ local fsck_enabled="$3"
+ local known_type
+ local found_fsck=0
+
+
+ grep -q "$device" /proc/swaps || grep -q "$device" /proc/mounts || {
+ [ -e "$device" ] && [ "$fsck_enabled" -eq 1 ] && {
+ for known_type in $libmount_known_fsck; do
+ if [ "$known_type" = "$fsck_fstype" ]; then
+ fsck_${known_type} "$device"
+ found_fsck=1
+ break
+ fi
+ done
+ if [ "$found_fsck" -ne 1 ]; then
+ logger -t 'fstab' "Unable to check/repair $device; no known fsck for filesystem type $fstype"
+ fi
+ }
+ }
+}
+
+libmount_known_fsck=""
+
+pi_include /lib/functions/fsck
+
diff --git a/package/block-mount/files/fstab.config b/package/block-mount/files/fstab.config
new file mode 100644
index 000000000..de52e20ce
--- /dev/null
+++ b/package/block-mount/files/fstab.config
@@ -0,0 +1,20 @@
+config global automount
+ option from_fstab 1
+ option anon_mount 1
+
+config global autoswap
+ option from_fstab 1
+ option anon_swap 0
+
+config mount
+ option target /home
+ option device /dev/sda1
+ option fstype ext4
+ option options rw,sync
+ option enabled 0
+ option enabled_fsck 0
+
+config swap
+ option device /dev/sda2
+ option enabled 0
+
diff --git a/package/block-mount/files/fstab.init b/package/block-mount/files/fstab.init
new file mode 100644
index 000000000..f54051ebb
--- /dev/null
+++ b/package/block-mount/files/fstab.init
@@ -0,0 +1,88 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2007 OpenWrt.org
+# Copyright (C) 2010 Vertical Communications
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+
+START=20
+
+EXTRA_COMMANDS="overlay_enable whole_root_enable"
+EXTRA_HELP=" overlay_enable Reenable overlay rootfs. (After you fix it).
+ whole_root_enable Reenable whole-disk rootfs. (After you fix it)."
+
+rootfs_enable() {
+ local extroot_type="$1"
+
+ if [ ! -d /tmp/${extroot_type}-disabled ]; then
+ echo "No disabled ${extroot_type} present (/tmp/${extroot_type}-disabled). Can't renable."
+ exit 1
+ fi
+
+ rm -f /tmp/${extroot_type}-disabled/.extroot.md5sum
+ rm -f /tmp/${extroot_type}-disabled/etc/extroot.md5sum
+ echo "Please reboot router to complete re-enabling external rootfs."
+}
+
+overlay_enable() {
+ rootfs_enable overlay
+}
+
+whole_root_enable() {
+ rootfs_enable whole_root
+}
+
+do_mount() {
+ local cfg="$1"
+ config_mount_by_section "$cfg"
+}
+
+do_swapon() {
+ local cfg="$1"
+ config_swapon_by_section "$cfg"
+}
+
+do_unmount() {
+ local cfg="$1"
+
+ config_get target "$cfg" target
+ config_get_bool enabled "$cfg" "enabled" '1'
+ [ -n "$target" -a "$enabled" -gt 0 ] || return 0
+ umount $target
+}
+
+do_swapoff() {
+ local cfg="$1"
+
+ config_get device "$cfg" device
+ config_get_bool enabled "$cfg" "enabled" '1'
+ [ -n "$device" -a "$enabled" -gt 0 ] && type swapoff >/dev/null || return 0
+ swapoff $device
+}
+
+start() {
+ . /lib/functions/mount.sh
+
+ config_load fstab
+ mkdir -p /var/lock
+ lock /var/lock/fstab.lck
+ [ -e /tmp/fstab ] || {
+ echo '# WARNING: this is an auto generated file, please use uci to set defined filesystems' > /tmp/fstab
+ }
+ lock -u /var/lock/fstab.lck
+ config_foreach do_swapon swap
+ config_foreach do_mount mount
+ config_foreach do_swapon swap # do swap a second time so that swap on filesystems is enabled
+}
+
+stop() {
+ . /lib/functions/mount.sh
+
+ config_load fstab
+ config_foreach do_unmount mount
+ config_foreach do_swapoff swap
+ swapoff -a
+}
+
+
diff --git a/package/block-mount/files/mount.sh b/package/block-mount/files/mount.sh
new file mode 100644
index 000000000..e96174ce9
--- /dev/null
+++ b/package/block-mount/files/mount.sh
@@ -0,0 +1,103 @@
+#!/bin/sh
+# Copyright 2010 Vertical Communications
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+
+pi_include /lib/functions/block.sh
+pi_include /lib/functions/fsck.sh
+
+config_mount_by_section() {
+ local cfg="$1"
+ local find_rootfs="$2"
+
+ mount_cb() {
+ local cfg="$1"
+ local device="$2"
+ shift
+ local target="$2"
+ local cfgdevice="$3"
+ local fstype="$4"
+ local options="$5"
+ local enabled="$6"
+ local enabled_fsck="$7"
+ local uuid="$8"
+ local label="$9"
+ shift
+ local is_rootfs="$9"
+ shift
+ local found_device=""
+
+ found_device="$(libmount_find_device_by_id "$uuid" "$label" "$device" "$cfgdevice")"
+ if [ -n "$found_device" ]; then
+ if [ "$find_rootfs" != "1" ] || ( [ "$is_rootfs" -eq 1 ] || [ "$target" = "/" ] || [ "$target" = "/overlay" ] ); then
+ [ "$enabled_fsck" -eq 1 ] && {
+ grep -q "$found_device" /proc/swaps || grep -q "$found_device" /proc/mounts || {
+ libmount_fsck "$found_device" "$fstype" "$enabled_fsck"
+ }
+ }
+
+ if [ "$find_rootfs" = "1" ]; then
+ if [ "$is_rootfs" -eq 1 ]; then
+ target=/overlay
+ elif [ "$target" = "/" ]; then
+ target=/rom
+ fi
+ else
+ if [ "$is_rootfs" -eq 1 ] || [ "$target" = "/overlay" ]; then
+ target=/tmp/overlay-disabled
+ elif [ "$target" = "/" ] || [ "$target" = "/rom" ]; then
+ target="/tmp/whole_root-disabled"
+ fi
+ fi
+
+ config_create_mount_fstab_entry "$found_device" "$target" "$fstype" "$options" "$enabled"
+ grep -q "$found_device" /proc/swaps || grep -q "$found_device" /proc/mounts || {
+ [ "$enabled" -eq 1 ] && mkdir -p "$target" && mount "$target" 2>&1 | tee /proc/self/fd/2 | logger -t 'fstab'
+ }
+
+ fi
+ fi
+ [ "$find_rootfs" = "1" ] && {
+ [ "$target" = "/overlay" ] && {
+ rootfs_found=1
+ }
+ [ "$target" = "/rom" ] && {
+ rootfs_found=1
+ }
+ }
+ return 0
+ }
+ config_get_mount "$cfg"
+ reset_block_cb
+}
+
+config_swapon_by_section() {
+ local cfg="$1"
+
+ swap_cb() {
+ local cfg="$1"
+ local device="$2"
+ local cfgdevice="$3"
+ local enabled="$4"
+ local uuid="$5"
+ local label="$6"
+ local uuid
+ local label
+
+ local found_device=""
+
+ found_device="$(libmount_find_device_by_id "$uuid" "$label" "$device" "$cfgdevice")"
+
+ if [ -n "$found_device" ]; then
+ config_create_swap_fstab_entry "$found_device" "$enabled"
+ grep -q "$found_device" /proc/swaps || grep -q "$found_device" /proc/mounts || {
+ [ "$enabled" -eq 1 ] && swapon "$found_device" | tee /proc/self/fd/2 | logger -t 'fstab'
+ }
+ fi
+ return 0
+ }
+ config_get_swap "$cfg"
+ reset_block_cb
+}
diff --git a/package/brcm2708-gpu-fw/Makefile b/package/brcm2708-gpu-fw/Makefile
new file mode 100644
index 000000000..45c727caf
--- /dev/null
+++ b/package/brcm2708-gpu-fw/Makefile
@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=brcm2708-gpu-fw
+PKG_REV:=29ce6bcf278e7e79cd8a2b84c6aa9db9864ca91d
+PKG_VERSION:=20120529
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=git://github.com/raspberrypi/firmware.git
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=$(PKG_REV)
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/brcm2708-gpu-fw
+ SECTION:=boot
+ CATEGORY:=Boot Loaders
+ DEPENDS:=@TARGET_brcm2708
+ TITLE:=brcm2708-gpu-fw
+ DEFAULT:=y if (TARGET_brcm2708)
+endef
+
+define Package/brcm2708-gpu-fw/description
+ GPU and kernel boot firmware for brcm2708.
+endef
+
+define Build/Compile
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(BUILD_DIR)/brcm2708-gpu-fw-boot
+ $(CP) $(PKG_BUILD_DIR)/boot/* $(BUILD_DIR)/brcm2708-gpu-fw-boot
+endef
+
+$(eval $(call BuildPackage,brcm2708-gpu-fw))
+
diff --git a/package/bridge-utils/Makefile b/package/bridge-utils/Makefile
new file mode 100644
index 000000000..f87551c6c
--- /dev/null
+++ b/package/bridge-utils/Makefile
@@ -0,0 +1,51 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=bridge-utils
+PKG_RELEASE:=1
+PKG_SOURCE_URL:=@SF/bridge
+PKG_VERSION:=1.5
+PKG_MD5SUM:=ec7b381160b340648dede58c31bb2238
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/bridge
+ SECTION:=net
+ CATEGORY:=Base system
+ TITLE:=Ethernet bridging configuration utility
+ URL:=http://bridge.sourceforge.net/
+endef
+
+define Package/bridge/description
+ Manage ethernet bridging: a way to connect networks together to
+ form a larger network.
+endef
+
+CONFIGURE_ARGS += \
+ --with-linux-headers="$(LINUX_DIR)" \
+
+define Build/Prepare
+$(call Build/Prepare/Default)
+ ( cd $(PKG_BUILD_DIR) ; \
+ [ -f ./configure ] || { \
+ ln -sf configure.in configure.ac ; \
+ autoconf ; \
+ } \
+ )
+endef
+
+define Package/bridge/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/brctl/brctl $(1)/usr/sbin
+endef
+
+$(eval $(call BuildPackage,bridge))
diff --git a/package/bridge-utils/patches/001-libbridge_cflags.patch b/package/bridge-utils/patches/001-libbridge_cflags.patch
new file mode 100644
index 000000000..e35a64947
--- /dev/null
+++ b/package/bridge-utils/patches/001-libbridge_cflags.patch
@@ -0,0 +1,11 @@
+--- a/libbridge/Makefile.in
++++ b/libbridge/Makefile.in
+@@ -5,7 +5,7 @@ AR=ar
+ RANLIB=@RANLIB@
+
+ CC=@CC@
+-CFLAGS = -Wall -g $(KERNEL_HEADERS)
++CFLAGS = -Wall -g @CFLAGS@ $(KERNEL_HEADERS)
+
+ prefix=@prefix@
+ exec_prefix=@exec_prefix@
diff --git a/package/broadcom-diag/Makefile b/package/broadcom-diag/Makefile
new file mode 100644
index 000000000..61b35290f
--- /dev/null
+++ b/package/broadcom-diag/Makefile
@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2006-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=broadcom-diag
+PKG_RELEASE:=10
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/diag
+ SUBMENU:=Other modules
+ DEPENDS:=@TARGET_brcm47xx
+ TITLE:=Driver for router LEDs and Buttons
+ FILES:=$(PKG_BUILD_DIR)/diag.ko
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ $(MAKE) -C "$(LINUX_DIR)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ ARCH="$(LINUX_KARCH)" \
+ SUBDIRS="$(PKG_BUILD_DIR)" \
+ EXTRA_CFLAGS="$(BUILDFLAGS)" \
+ modules
+endef
+
+$(eval $(call KernelPackage,diag))
diff --git a/package/broadcom-diag/src/Makefile b/package/broadcom-diag/src/Makefile
new file mode 100644
index 000000000..44c80a8bf
--- /dev/null
+++ b/package/broadcom-diag/src/Makefile
@@ -0,0 +1,17 @@
+#
+# Makefile for diag driver
+#
+# Copyright (C) 2005 Felix Fietkau <nbd@openwrt.org>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+
+obj-m := diag.o
+
+ifeq ($(MAKING_MODULES),1)
+
+-include $(TOPDIR)/Rules.make
+endif
diff --git a/package/broadcom-diag/src/diag.c b/package/broadcom-diag/src/diag.c
new file mode 100644
index 000000000..7e0ff02e1
--- /dev/null
+++ b/package/broadcom-diag/src/diag.c
@@ -0,0 +1,1686 @@
+/*
+ * diag.c - GPIO interface driver for Broadcom boards
+ *
+ * Copyright (C) 2006 Mike Baker <mbm@openwrt.org>,
+ * Copyright (C) 2006-2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2008 Andy Boyett <agb@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ */
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kmod.h>
+#include <linux/proc_fs.h>
+#include <linux/timer.h>
+#include <linux/version.h>
+#include <asm/uaccess.h>
+#include <linux/workqueue.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/kobject.h>
+#include <net/sock.h>
+extern u64 uevent_next_seqnum(void);
+
+#include "gpio.h"
+#include "diag.h"
+#define getvar(str) (nvram_get(str)?:"")
+
+static inline int startswith (char *source, char *cmp) { return !strncmp(source,cmp,strlen(cmp)); }
+static int fill_event(struct event_t *);
+static unsigned int gpiomask = 0;
+module_param(gpiomask, int, 0644);
+
+enum {
+ /* Linksys */
+ WAP54GV1,
+ WAP54GV2,
+ WAP54GV3,
+ WRT54GV1,
+ WRT54G,
+ WRTSL54GS,
+ WRT54G3G,
+ WRT54G3GV2_VF,
+ WRT150NV1,
+ WRT150NV11,
+ WRT160NV1,
+ WRT160NV3,
+ WRT300NV11,
+ WRT350N,
+ WRT600N,
+ WRT600NV11,
+ WRT610N,
+ WRT610NV2,
+ E3000V1,
+
+ /* ASUS */
+ WLHDD,
+ WL300G,
+ WL320GE,
+ WL330GE,
+ WL500G,
+ WL500GD,
+ WL500GP,
+ WL500GPV2,
+ WL500W,
+ WL520GC,
+ WL520GU,
+ ASUS_4702,
+ WL700GE,
+ RTN16,
+
+ /* Buffalo */
+ WBR2_G54,
+ WHR_G54S,
+ WHR_HP_G54,
+ WHR_G125,
+ WHR2_A54G54,
+ WLA2_G54L,
+ WZR_G300N,
+ WZR_RS_G54,
+ WZR_RS_G54HP,
+ BUFFALO_UNKNOWN,
+ BUFFALO_UNKNOWN_4710,
+
+ /* Siemens */
+ SE505V1,
+ SE505V2,
+
+ /* US Robotics */
+ USR5461,
+
+ /* Dell */
+ TM2300,
+ TM2300V2,
+
+ /* Motorola */
+ WE800G,
+ WR850GV1,
+ WR850GV2V3,
+ WR850GP,
+
+ /* Belkin */
+ BELKIN_UNKNOWN,
+ BELKIN_F7D4301,
+
+ /* Netgear */
+ WGT634U,
+ WNR834BV1,
+ WNR834BV2,
+
+ /* Trendware */
+ TEW411BRPP,
+
+ /* SimpleTech */
+ STI_NAS,
+
+ /* D-Link */
+ DIR130,
+ DIR320,
+ DIR330,
+ DWL3150,
+
+ /* Sitecom */
+ WL105B,
+
+ /* Western Digital */
+ WDNetCenter,
+
+ /* Askey */
+ RT210W,
+
+ /* OvisLink */
+ WL1600GL,
+
+ /* Microsoft */
+ MN700,
+
+ /* Edimax */
+ PS1208MFG,
+};
+
+static void __init bcm4780_init(void) {
+ int pin = 1 << 3;
+
+ /* Enables GPIO 3 that controls HDD and led power on ASUS WL-700gE */
+ printk(MODULE_NAME ": Spinning up HDD and enabling leds\n");
+ bcm47xx_gpio_outen(pin, pin);
+ bcm47xx_gpio_control(pin, 0);
+ bcm47xx_gpio_out(pin, pin);
+
+ /* Wait 5s, so the HDD can spin up */
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ * 5);
+}
+
+static void __init NetCenter_init(void) {
+ /* unset pin 6 (+12V) */
+ int pin = 1 << 6;
+ bcm47xx_gpio_outen(pin, pin);
+ bcm47xx_gpio_control(pin, 0);
+ bcm47xx_gpio_out(pin, pin);
+ /* unset pin 1 (turn off red led, blue will light alone if +5V comes up) */
+ pin = 1 << 1;
+ bcm47xx_gpio_outen(pin, pin);
+ bcm47xx_gpio_control(pin, 0);
+ bcm47xx_gpio_out(pin, pin);
+ /* unset pin 3 (+5V) and wait 5 seconds (harddisk spin up) */
+ bcm4780_init();
+}
+
+static void __init bcm57xx_init(void) {
+ int pin = 1 << 2;
+
+ /* FIXME: switch comes up, but port mappings/vlans not right */
+ bcm47xx_gpio_outen(pin, pin);
+ bcm47xx_gpio_control(pin, 0);
+ bcm47xx_gpio_out(pin, pin);
+}
+
+static struct platform_t __initdata platforms[] = {
+ /* Linksys */
+ [WAP54GV1] = {
+ .name = "Linksys WAP54G V1",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 0 },
+ },
+ .leds = {
+ { .name = "diag", .gpio = 1 << 3 },
+ { .name = "wlan", .gpio = 1 << 4 },
+ },
+ },
+ [WAP54GV2] = {
+ .name = "Linksys WAP54G V2",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 0 },
+ },
+ .leds = {
+ { .name = "wlan", .gpio = 1 << 5, .polarity = REVERSE },
+ /* GPIO 6 is b44 (eth0, LAN) PHY power */
+ },
+ },
+ [WAP54GV3] = {
+ .name = "Linksys WAP54G V3",
+ .buttons = {
+ /* FIXME: verify this */
+ { .name = "reset", .gpio = 1 << 7 },
+ { .name = "ses", .gpio = 1 << 0 },
+ },
+ .leds = {
+ /* FIXME: diag? */
+ { .name = "ses", .gpio = 1 << 1 },
+ },
+ },
+ [WRT54GV1] = {
+ .name = "Linksys WRT54G V1.x",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ },
+ .leds = {
+ { .name = "diag", .gpio = 0x13 | GPIO_TYPE_EXTIF, .polarity = NORMAL },
+ { .name = "dmz", .gpio = 0x12 | GPIO_TYPE_EXTIF, .polarity = NORMAL },
+ },
+ },
+ [WRT54G] = {
+ .name = "Linksys WRT54G/GS/GL",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ { .name = "ses", .gpio = 1 << 4 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 1, .polarity = NORMAL },
+ { .name = "dmz", .gpio = 1 << 7, .polarity = REVERSE },
+ { .name = "ses_white", .gpio = 1 << 2, .polarity = REVERSE },
+ { .name = "ses_orange", .gpio = 1 << 3, .polarity = REVERSE },
+ { .name = "wlan", .gpio = 1 << 0, .polarity = REVERSE },
+ },
+ },
+ [WRTSL54GS] = {
+ .name = "Linksys WRTSL54GS",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ { .name = "ses", .gpio = 1 << 4 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 1, .polarity = NORMAL },
+ { .name = "dmz", .gpio = 1 << 0, .polarity = REVERSE },
+ { .name = "ses_white", .gpio = 1 << 5, .polarity = REVERSE },
+ { .name = "ses_orange", .gpio = 1 << 7, .polarity = REVERSE },
+ },
+ },
+ [WRT54G3G] = {
+ .name = "Linksys WRT54G3G",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ { .name = "3g", .gpio = 1 << 4 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 1, .polarity = NORMAL },
+ { .name = "dmz", .gpio = 1 << 7, .polarity = REVERSE },
+ { .name = "3g_green", .gpio = 1 << 2, .polarity = NORMAL },
+ { .name = "3g_blue", .gpio = 1 << 3, .polarity = NORMAL },
+ { .name = "3g_blink", .gpio = 1 << 5, .polarity = NORMAL },
+ },
+ },
+ [WRT54G3GV2_VF] = {
+ .name = "Linksys WRT54G3GV2-VF",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ { .name = "3g", .gpio = 1 << 5 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 1, .polarity = NORMAL },
+ { .name = "3g_green", .gpio = 1 << 2, .polarity = NORMAL },
+ { .name = "3g_blue", .gpio = 1 << 3, .polarity = NORMAL },
+ },
+ },
+ [WRT150NV1] = {
+ .name = "Linksys WRT150N V1",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ { .name = "ses", .gpio = 1 << 4 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 1, .polarity = NORMAL },
+ { .name = "ses_green", .gpio = 1 << 5, .polarity = REVERSE },
+ { .name = "ses_amber", .gpio = 1 << 3, .polarity = REVERSE },
+ },
+ },
+ [WRT150NV11] = {
+ .name = "Linksys WRT150N V1.1",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ { .name = "ses", .gpio = 1 << 4 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 1, .polarity = NORMAL },
+ { .name = "ses_green", .gpio = 1 << 5, .polarity = REVERSE },
+ { .name = "ses_amber", .gpio = 1 << 3, .polarity = REVERSE },
+ },
+ },
+ [WRT160NV1] = {
+ .name = "Linksys WRT160N v1.x",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ { .name = "ses", .gpio = 1 << 4 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 1, .polarity = NORMAL },
+ { .name = "ses_blue", .gpio = 1 << 5, .polarity = REVERSE },
+ { .name = "ses_orange", .gpio = 1 << 3, .polarity = REVERSE },
+ },
+ },
+ [WRT160NV3] = {
+ .name = "Linksys WRT160N V3",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ { .name = "ses", .gpio = 1 << 5 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 1, .polarity = NORMAL },
+ { .name = "ses_blue", .gpio = 1 << 4, .polarity = REVERSE },
+ { .name = "ses_orange", .gpio = 1 << 2, .polarity = REVERSE },
+ },
+ },
+ [WRT300NV11] = {
+ .name = "Linksys WRT300N V1.1",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 }, // "Reset" on back panel
+ { .name = "ses", .gpio = 1 << 4 }, // "Reserved" on top panel
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 1, .polarity = NORMAL }, // "Power"
+ { .name = "ses_amber", .gpio = 1 << 3, .polarity = REVERSE }, // "Security" Amber
+ { .name = "ses_green", .gpio = 1 << 5, .polarity = REVERSE }, // "Security" Green
+ },
+ .platform_init = bcm57xx_init,
+ },
+ [WRT350N] = {
+ .name = "Linksys WRT350N",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ { .name = "ses", .gpio = 1 << 8 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 1, .polarity = NORMAL },
+ { .name = "ses_amber", .gpio = 1 << 3, .polarity = REVERSE },
+ { .name = "ses_green", .gpio = 1 << 9, .polarity = REVERSE },
+ { .name = "usb_blink", .gpio = 1 << 10, .polarity = REVERSE },
+ { .name = "usb", .gpio = 1 << 11, .polarity = REVERSE },
+ },
+ .platform_init = bcm57xx_init,
+ },
+ [WRT600N] = {
+ .name = "Linksys WRT600N",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ { .name = "ses", .gpio = 1 << 7 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 2, .polarity = REVERSE }, // Power LED
+ { .name = "usb", .gpio = 1 << 3, .polarity = REVERSE }, // USB LED
+ { .name = "wl0_ses_amber", .gpio = 1 << 8, .polarity = REVERSE }, // 2.4Ghz LED Amber
+ { .name = "wl0_ses_green", .gpio = 1 << 9, .polarity = REVERSE }, // 2.4Ghz LED Green
+ { .name = "wl1_ses_amber", .gpio = 1 << 10, .polarity = REVERSE }, // 5.6Ghz LED Amber
+ { .name = "wl1_ses_green", .gpio = 1 << 11, .polarity = REVERSE }, // 5.6Ghz LED Green
+ },
+ .platform_init = bcm57xx_init,
+ },
+ [WRT600NV11] = {
+ .name = "Linksys WRT600N V1.1",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ { .name = "ses", .gpio = 1 << 7 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 2, .polarity = REVERSE }, // Power LED
+ { .name = "usb", .gpio = 1 << 3, .polarity = REVERSE }, // USB LED
+ { .name = "wl0_ses_amber", .gpio = 1 << 8, .polarity = REVERSE }, // 2.4Ghz LED Amber
+ { .name = "wl0_ses_green", .gpio = 1 << 9, .polarity = REVERSE }, // 2.4Ghz LED Green
+ { .name = "wl1_ses_amber", .gpio = 1 << 10, .polarity = REVERSE }, // 5.6Ghz LED Amber
+ { .name = "wl1_ses_green", .gpio = 1 << 11, .polarity = REVERSE }, // 5.6Ghz LED Green
+ },
+ .platform_init = bcm57xx_init,
+ },
+ [WRT610N] = {
+ .name = "Linksys WRT610N",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ { .name = "ses", .gpio = 1 << 8 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 1, .polarity = NORMAL }, // Power LED
+ { .name = "usb", .gpio = 1 << 0, .polarity = REVERSE }, // USB LED
+ { .name = "ses_amber", .gpio = 1 << 3, .polarity = REVERSE }, // WiFi protected setup LED amber
+ { .name = "ses_blue", .gpio = 1 << 9, .polarity = REVERSE }, // WiFi protected setup LED blue
+ },
+ },
+ [WRT610NV2] = {
+ .name = "Linksys WRT610N V2",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ { .name = "ses", .gpio = 1 << 4 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 5, .polarity = NORMAL }, // Power LED
+ { .name = "usb", .gpio = 1 << 7, .polarity = NORMAL }, // USB LED
+ { .name = "ses_amber", .gpio = 1 << 0, .polarity = REVERSE }, // WiFi protected setup LED amber
+ { .name = "ses_blue", .gpio = 1 << 3, .polarity = REVERSE }, // WiFi protected setup LED blue
+ { .name = "wlan", .gpio = 1 << 1, .polarity = NORMAL }, // Wireless LED
+ },
+ },
+ [E3000V1] = {
+ .name = "Linksys E3000 V1",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ { .name = "ses", .gpio = 1 << 4 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 5, .polarity = NORMAL }, // Power LED
+ { .name = "usb", .gpio = 1 << 7, .polarity = NORMAL }, // USB LED
+ { .name = "ses_amber", .gpio = 1 << 0, .polarity = REVERSE }, // WiFi protected setup LED amber
+ { .name = "ses_blue", .gpio = 1 << 3, .polarity = REVERSE }, // WiFi protected setup LED blue
+ { .name = "wlan", .gpio = 1 << 1, .polarity = NORMAL }, // Wireless LED
+ },
+ },
+ /* Asus */
+ [WLHDD] = {
+ .name = "ASUS WL-HDD",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 0, .polarity = REVERSE },
+ { .name = "usb", .gpio = 1 << 2, .polarity = REVERSE },
+ },
+ },
+ [WL300G] = {
+ .name = "ASUS WL-300g",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 0, .polarity = REVERSE },
+ },
+ },
+ [WL320GE] = {
+ .name = "ASUS WL-320gE/WL-320gP",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ },
+ .leds = {
+ { .name = "wlan", .gpio = 1 << 0, .polarity = REVERSE },
+ { .name = "power", .gpio = 1 << 2, .polarity = REVERSE },
+ { .name = "link", .gpio = 1 << 11, .polarity = REVERSE },
+ },
+ },
+ [WL330GE] = {
+ .name = "ASUS WL-330gE",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 2 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 0, .polarity = REVERSE },
+ },
+ },
+ [WL500G] = {
+ .name = "ASUS WL-500g",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 0, .polarity = REVERSE },
+ },
+ },
+ [WL500GD] = {
+ .name = "ASUS WL-500g Deluxe",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 0, .polarity = REVERSE },
+ },
+ },
+ [WL500GP] = {
+ .name = "ASUS WL-500g Premium",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 0 },
+ { .name = "ses", .gpio = 1 << 4 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 1, .polarity = REVERSE },
+ },
+ },
+ [WL500GPV2] = {
+ .name = "ASUS WL-500g Premium V2",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 2 },
+ { .name = "ses", .gpio = 1 << 3 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 0, .polarity = REVERSE },
+ { .name = "wlan", .gpio = 1 << 1, .polarity = REVERSE },
+ },
+ },
+ [WL500W] = {
+ .name = "ASUS WL-500W",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ { .name = "ses", .gpio = 1 << 7 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 5, .polarity = REVERSE },
+ },
+ },
+ [WL520GC] = {
+ .name = "ASUS WL-520GC",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 2 },
+ { .name = "ses", .gpio = 1 << 3 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 0, .polarity = REVERSE },
+ { .name = "wlan", .gpio = 1 << 1, .polarity = REVERSE },
+ },
+ },
+ [WL520GU] = {
+ .name = "ASUS WL-520gU",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 2 },
+ { .name = "ses", .gpio = 1 << 3 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 0, .polarity = REVERSE },
+ { .name = "wlan", .gpio = 1 << 1, .polarity = REVERSE },
+ },
+ },
+ [ASUS_4702] = {
+ .name = "ASUS (unknown, BCM4702)",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 0, .polarity = REVERSE },
+ },
+ },
+ [WL700GE] = {
+ .name = "ASUS WL-700gE",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 7 }, // on back, hardwired, always resets device regardless OS state
+ { .name = "ses", .gpio = 1 << 4 }, // on back, actual name ezsetup
+ { .name = "power", .gpio = 1 << 0 }, // on front
+ { .name = "copy", .gpio = 1 << 6 }, // on front
+ },
+ .leds = {
+#if 0
+ // GPIO that controls power led also enables/disables some essential functions
+ // - power to HDD
+ // - switch leds
+ { .name = "power", .gpio = 1 << 3, .polarity = NORMAL }, // actual name power
+#endif
+ { .name = "diag", .gpio = 1 << 1, .polarity = REVERSE }, // actual name ready
+ },
+ .platform_init = bcm4780_init,
+ },
+ [RTN16] = {
+ .name = "ASUS RT-N16",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 8 },
+ { .name = "ses", .gpio = 1 << 5 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 1, .polarity = REVERSE },
+ { .name = "wlan", .gpio = 1 << 7, .polarity = NORMAL },
+ },
+ },
+ /* Buffalo */
+ [WHR_G54S] = {
+ .name = "Buffalo WHR-G54S",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 4 },
+ { .name = "bridge", .gpio = 1 << 5 },
+ { .name = "ses", .gpio = 1 << 0 },
+ },
+ .leds = {
+ { .name = "diag", .gpio = 1 << 7, .polarity = REVERSE },
+ { .name = "internal", .gpio = 1 << 3, .polarity = REVERSE },
+ { .name = "ses", .gpio = 1 << 6, .polarity = REVERSE },
+ { .name = "bridge", .gpio = 1 << 1, .polarity = REVERSE },
+ { .name = "wlan", .gpio = 1 << 2, .polarity = REVERSE },
+ },
+ },
+ [WBR2_G54] = {
+ .name = "Buffalo WBR2-G54",
+ /* FIXME: verify */
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 7 },
+ },
+ .leds = {
+ { .name = "diag", .gpio = 1 << 1, .polarity = REVERSE },
+ },
+ },
+ [WHR_HP_G54] = {
+ .name = "Buffalo WHR-HP-G54",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 4 },
+ { .name = "bridge", .gpio = 1 << 5 },
+ { .name = "ses", .gpio = 1 << 0 },
+ },
+ .leds = {
+ { .name = "diag", .gpio = 1 << 7, .polarity = REVERSE },
+ { .name = "internal", .gpio = 1 << 3, .polarity = REVERSE },
+ { .name = "bridge", .gpio = 1 << 1, .polarity = REVERSE },
+ { .name = "ses", .gpio = 1 << 6, .polarity = REVERSE },
+ { .name = "wlan", .gpio = 1 << 2, .polarity = REVERSE },
+ },
+ },
+ [WHR_G125] = {
+ .name = "Buffalo WHR-G125",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 4 },
+ { .name = "bridge", .gpio = 1 << 5 },
+ { .name = "ses", .gpio = 1 << 0 },
+ },
+ .leds = {
+ { .name = "diag", .gpio = 1 << 7, .polarity = REVERSE },
+ { .name = "internal", .gpio = 1 << 3, .polarity = REVERSE },
+ { .name = "bridge", .gpio = 1 << 1, .polarity = REVERSE },
+ { .name = "ses", .gpio = 1 << 6, .polarity = REVERSE },
+ { .name = "wlan", .gpio = 1 << 2, .polarity = REVERSE },
+ },
+ },
+ [WHR2_A54G54] = {
+ .name = "Buffalo WHR2-A54G54",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 4 },
+ },
+ .leds = {
+ { .name = "diag", .gpio = 1 << 7, .polarity = REVERSE },
+ },
+ },
+ [WLA2_G54L] = {
+ .name = "Buffalo WLA2-G54L",
+ /* FIXME: verify */
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 7 },
+ },
+ .leds = {
+ { .name = "diag", .gpio = 1 << 1, .polarity = REVERSE },
+ },
+ },
+ [WZR_G300N] = {
+ .name = "Buffalo WZR-G300N",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 4 },
+ },
+ .leds = {
+ { .name = "diag", .gpio = 1 << 7, .polarity = REVERSE },
+ { .name = "bridge", .gpio = 1 << 1, .polarity = REVERSE },
+ { .name = "ses", .gpio = 1 << 6, .polarity = REVERSE },
+ },
+ },
+ [WZR_RS_G54] = {
+ .name = "Buffalo WZR-RS-G54",
+ .buttons = {
+ { .name = "ses", .gpio = 1 << 0 },
+ { .name = "reset", .gpio = 1 << 4 },
+ },
+ .leds = {
+ { .name = "diag", .gpio = 1 << 7, .polarity = REVERSE },
+ { .name = "ses", .gpio = 1 << 6, .polarity = REVERSE },
+ { .name = "vpn", .gpio = 1 << 1, .polarity = REVERSE },
+ },
+ },
+ [WZR_RS_G54HP] = {
+ .name = "Buffalo WZR-RS-G54HP",
+ .buttons = {
+ { .name = "ses", .gpio = 1 << 0 },
+ { .name = "reset", .gpio = 1 << 4 },
+ },
+ .leds = {
+ { .name = "diag", .gpio = 1 << 7, .polarity = REVERSE },
+ { .name = "ses", .gpio = 1 << 6, .polarity = REVERSE },
+ { .name = "vpn", .gpio = 1 << 1, .polarity = REVERSE },
+ },
+ },
+ [BUFFALO_UNKNOWN] = {
+ .name = "Buffalo (unknown)",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 7 },
+ },
+ .leds = {
+ { .name = "diag", .gpio = 1 << 1, .polarity = REVERSE },
+ },
+ },
+ [BUFFALO_UNKNOWN_4710] = {
+ .name = "Buffalo (unknown, BCM4710)",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 4 },
+ },
+ .leds = {
+ { .name = "diag", .gpio = 1 << 1, .polarity = REVERSE },
+ },
+ },
+ /* Siemens */
+ [SE505V1] = {
+ .name = "Siemens SE505 V1",
+ .buttons = {
+ /* No usable buttons */
+ },
+ .leds = {
+// { .name = "power", .gpio = 1 << 0 .polarity = REVERSE }, // Usable when retrofitting D26 (?)
+ { .name = "dmz", .gpio = 1 << 4, .polarity = REVERSE }, // actual name WWW
+ { .name = "wlan", .gpio = 1 << 3, .polarity = REVERSE },
+ },
+ },
+ [SE505V2] = {
+ .name = "Siemens SE505 V2",
+ .buttons = {
+ /* No usable buttons */
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 5, .polarity = REVERSE },
+ { .name = "dmz", .gpio = 1 << 0, .polarity = REVERSE }, // actual name WWW
+ { .name = "wlan", .gpio = 1 << 3, .polarity = REVERSE },
+ },
+ },
+ /* US Robotics */
+ [USR5461] = {
+ .name = "U.S. Robotics USR5461",
+ .buttons = {
+ /* No usable buttons */
+ },
+ .leds = {
+ { .name = "wlan", .gpio = 1 << 0, .polarity = REVERSE },
+ { .name = "printer", .gpio = 1 << 1, .polarity = REVERSE },
+ },
+ },
+ /* Dell */
+ [TM2300] = {
+ .name = "Dell TrueMobile 2300",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 0 },
+ },
+ .leds = {
+ { .name = "wlan", .gpio = 1 << 6, .polarity = REVERSE },
+ { .name = "power", .gpio = 1 << 7, .polarity = REVERSE },
+ },
+ },
+ [TM2300V2] = {
+ .name = "Dell TrueMobile 2300 v2",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 0 },
+ },
+ .leds = {
+ { .name = "wlan", .gpio = 1 << 6, .polarity = REVERSE },
+ { .name = "power", .gpio = 1 << 7, .polarity = REVERSE },
+ },
+ },
+ /* Motorola */
+ [WE800G] = {
+ .name = "Motorola WE800G",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 0 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 4, .polarity = NORMAL },
+ { .name = "diag", .gpio = 1 << 2, .polarity = REVERSE },
+ { .name = "wlan_amber", .gpio = 1 << 1, .polarity = NORMAL },
+ },
+ },
+ [WR850GV1] = {
+ .name = "Motorola WR850G V1",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 0 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 4, .polarity = NORMAL },
+ { .name = "diag", .gpio = 1 << 3, .polarity = REVERSE },
+ { .name = "dmz", .gpio = 1 << 6, .polarity = NORMAL },
+ { .name = "wlan_red", .gpio = 1 << 5, .polarity = REVERSE },
+ { .name = "wlan_green", .gpio = 1 << 7, .polarity = REVERSE },
+ },
+ },
+ [WR850GV2V3] = {
+ .name = "Motorola WR850G V2/V3",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 5 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 1, .polarity = NORMAL },
+ { .name = "wlan", .gpio = 1 << 0, .polarity = REVERSE },
+ { .name = "wan", .gpio = 1 << 6, .polarity = INPUT },
+ { .name = "diag", .gpio = 1 << 7, .polarity = REVERSE },
+ },
+ },
+ [WR850GP] = {
+ .name = "Motorola WR850GP",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 5 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 1, .polarity = NORMAL },
+ { .name = "wlan", .gpio = 1 << 0, .polarity = REVERSE },
+ { .name = "dmz", .gpio = 1 << 6, .polarity = REVERSE },
+ { .name = "diag", .gpio = 1 << 7, .polarity = REVERSE },
+ },
+ },
+
+ /* Belkin */
+ [BELKIN_UNKNOWN] = {
+ .name = "Belkin (unknown)",
+ /* FIXME: verify & add detection */
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 7 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 5, .polarity = NORMAL },
+ { .name = "wlan", .gpio = 1 << 3, .polarity = NORMAL },
+ { .name = "connected", .gpio = 1 << 0, .polarity = NORMAL },
+ },
+ },
+ [BELKIN_F7D4301] = {
+ .name = "Belkin PlayMax F7D4301",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ { .name = "wps", .gpio = 1 << 8 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 11, .polarity = REVERSE },
+ { .name = "wlan", .gpio = 1 << 13, .polarity = REVERSE },
+ { .name = "led0", .gpio = 1 << 14, .polarity = REVERSE },
+ { .name = "led1", .gpio = 1 << 15, .polarity = REVERSE },
+ },
+ },
+ /* Netgear */
+ [WGT634U] = {
+ .name = "Netgear WGT634U",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 2 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 3, .polarity = NORMAL },
+ },
+ },
+ /* Netgear */
+ [WNR834BV1] = {
+ .name = "Netgear WNR834B V1",
+ .buttons = { /* TODO: add reset button and confirm LEDs - GPIO from dd-wrt */ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 4, .polarity = REVERSE },
+ { .name = "diag", .gpio = 1 << 5, .polarity = REVERSE },
+ { .name = "wlan", .gpio = 1 << 6, .polarity = REVERSE },
+ },
+ },
+ /* Netgear */
+ [WNR834BV2] = {
+ .name = "Netgear WNR834B V2",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 6 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 2, .polarity = NORMAL },
+ { .name = "diag", .gpio = 1 << 3, .polarity = NORMAL },
+ { .name = "connected", .gpio = 1 << 7, .polarity = NORMAL },
+ },
+ },
+ /* Trendware */
+ [TEW411BRPP] = {
+ .name = "Trendware TEW411BRP+",
+ .buttons = {
+ { /* No usable buttons */ },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 7, .polarity = NORMAL },
+ { .name = "wlan", .gpio = 1 << 1, .polarity = NORMAL },
+ { .name = "bridge", .gpio = 1 << 6, .polarity = NORMAL },
+ },
+ },
+ /* SimpleTech */
+ [STI_NAS] = {
+ .name = "SimpleTech SimpleShare NAS",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 0 }, // Power button on back, named reset to enable failsafe.
+ },
+ .leds = {
+ { .name = "diag", .gpio = 1 << 1, .polarity = REVERSE }, // actual name ready
+ },
+ .platform_init = bcm4780_init,
+ },
+ /* D-Link */
+ [DIR130] = {
+ .name = "D-Link DIR-130",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 3},
+ { .name = "reserved", .gpio = 1 << 7},
+ },
+ .leds = {
+ { .name = "diag", .gpio = 1 << 0},
+ { .name = "blue", .gpio = 1 << 6},
+ },
+ },
+ [DIR320] = {
+ .name = "D-Link DIR-320",
+ .buttons = {
+ { .name = "reserved", .gpio = 1 << 6},
+ { .name = "reset", .gpio = 1 << 7},
+ },
+ .leds = {
+ { .name = "wlan", .gpio = 1 << 0, .polarity = NORMAL },
+ { .name = "diag", .gpio = 1 << 1, .polarity = NORMAL }, /* "status led */
+ { .name = "red", .gpio = 1 << 3, .polarity = REVERSE },
+ { .name = "blue", .gpio = 1 << 4, .polarity = REVERSE },
+ { .name = "usb", .gpio = 1 << 5, .polarity = NORMAL },
+ },
+ },
+ [DIR330] = {
+ .name = "D-Link DIR-330",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 3},
+ { .name = "reserved", .gpio = 1 << 7},
+ },
+ .leds = {
+ { .name = "diag", .gpio = 1 << 0},
+ { .name = "usb", .gpio = 1 << 4},
+ { .name = "blue", .gpio = 1 << 6},
+ },
+ },
+ [DWL3150] = {
+ .name = "D-Link DWL-3150",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 7},
+ },
+ .leds = {
+ { .name = "diag", .gpio = 1 << 2},
+ { .name = "status", .gpio = 1 << 1},
+ },
+ },
+ /* Double check */
+ [WL105B] = {
+ .name = "Sitecom WL-105b",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 10},
+ },
+ .leds = {
+ { .name = "wlan", .gpio = 1 << 4},
+ { .name = "power", .gpio = 1 << 3},
+ },
+ },
+ /* Western Digital Net Center */
+ [WDNetCenter] = {
+ .name = "Western Digital NetCenter",
+ .buttons = {
+ { .name = "power", .gpio = 1 << 0},
+ { .name = "reset", .gpio = 1 << 7},
+ },
+ .platform_init = NetCenter_init,
+ },
+ /* Askey (and clones) */
+ [RT210W] = {
+ .name = "Askey RT210W",
+ .buttons = {
+ /* Power button is hard-wired to hardware reset */
+ /* but is also connected to GPIO 7 (probably for bootloader recovery) */
+ { .name = "power", .gpio = 1 << 7},
+ },
+ .leds = {
+ /* These were verified and named based on Belkin F5D4230-4 v1112 */
+ { .name = "connected", .gpio = 1 << 0, .polarity = REVERSE },
+ { .name = "wlan", .gpio = 1 << 3, .polarity = REVERSE },
+ { .name = "power", .gpio = 1 << 5, .polarity = REVERSE },
+ },
+ },
+ [WL1600GL] = {
+ .name = "OvisLink WL-1600GL",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 3 },
+ { .name = "ses", .gpio = 1 << 4 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 5, .polarity = REVERSE },
+ { .name = "wps", .gpio = 1 << 2, .polarity = REVERSE },
+ { .name = "wlan", .gpio = 1 << 1, .polarity = REVERSE },
+ { .name = "connected", .gpio = 1 << 0, .polarity = REVERSE },
+ },
+ },
+ /* Microsoft */
+ [MN700] = {
+ .name = "Microsoft MN-700",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 7 },
+ },
+ .leds = {
+ { .name = "power", .gpio = 1 << 6, .polarity = NORMAL },
+ },
+ },
+ /* Edimax */
+ [PS1208MFG] = {
+ .name = "Edimax PS-1208MFG",
+ .buttons = {
+ { .name = "reset", .gpio = 1 << 4 },
+ },
+ .leds = {
+ { .name = "status", .gpio = 1 << 1, .polarity = NORMAL },
+ { .name = "wlan", .gpio = 1 << 0, .polarity = NORMAL },
+ },
+ },
+};
+
+static struct platform_t __init *platform_detect(void)
+{
+ char *boardnum, *boardtype, *buf;
+
+ if (strcmp(getvar("nvram_type"), "cfe") == 0)
+ return &platforms[WGT634U];
+
+ /* Look for a model identifier */
+
+ /* Based on "model_name" */
+ if ((buf = nvram_get("model_name"))) {
+ if (!strcmp(buf, "DIR-130"))
+ return &platforms[DIR130];
+ if (!strcmp(buf, "DIR-330"))
+ return &platforms[DIR330];
+ }
+
+ /* Based on "wsc_modelname */
+ if ((buf = nvram_get("wsc_modelname"))) {
+ if (!strcmp(buf, "WRT610N"))
+ return &platforms[WRT610N];
+ }
+
+ /* Based on "model_no" */
+ if ((buf = nvram_get("model_no"))) {
+ if (startswith(buf,"WL700")) /* WL700* */
+ return &platforms[WL700GE];
+ }
+
+ /* Based on "hardware_version" */
+ if ((buf = nvram_get("hardware_version"))) {
+ if (startswith(buf,"WL500GPV2-")) /* WL500GPV2-* */
+ return &platforms[WL500GPV2];
+ if (startswith(buf,"WL520GC-")) /* WL520GU-* */
+ return &platforms[WL520GC];
+ if (startswith(buf,"WL520GU-")) /* WL520GU-* */
+ return &platforms[WL520GU];
+ if (startswith(buf,"WL330GE-")) /* WL330GE-* */
+ return &platforms[WL330GE];
+ if (startswith(buf,"RT-N16-")) /* RT-N16-* */
+ return &platforms[RTN16];
+ if (startswith(buf,"F7D4301")) /* F7D4301* */
+ return &platforms[BELKIN_F7D4301];
+ }
+
+ /* Based on "ModelId" */
+ if ((buf = nvram_get("ModelId"))) {
+ if (!strcmp(buf, "WR850GP"))
+ return &platforms[WR850GP];
+ if (!strcmp(buf, "WR850G"))
+ return &platforms[WR850GV2V3];
+ if (!strcmp(buf, "WX-5565") && !strcmp(getvar("boardtype"),"bcm94710ap"))
+ return &platforms[TM2300]; /* Dell TrueMobile 2300 */
+ if (startswith(buf,"WE800G")) /* WE800G* */
+ return &platforms[WE800G];
+ }
+
+ /* Buffalo */
+ if ((buf = (nvram_get("melco_id") ?: nvram_get("buffalo_id")))) {
+ /* Buffalo hardware, check id for specific hardware matches */
+ if (!strcmp(buf, "29bb0332"))
+ return &platforms[WBR2_G54];
+ if (!strcmp(buf, "29129"))
+ return &platforms[WLA2_G54L];
+ if (!strcmp(buf, "30189"))
+ return &platforms[WHR_HP_G54];
+ if (!strcmp(buf, "32093"))
+ return &platforms[WHR_G125];
+ if (!strcmp(buf, "30182"))
+ return &platforms[WHR_G54S];
+ if (!strcmp(buf, "290441dd"))
+ return &platforms[WHR2_A54G54];
+ if (!strcmp(buf, "31120"))
+ return &platforms[WZR_G300N];
+ if (!strcmp(buf, "30083"))
+ return &platforms[WZR_RS_G54];
+ if (!strcmp(buf, "30103"))
+ return &platforms[WZR_RS_G54HP];
+ }
+
+ /* no easy model number, attempt to guess */
+ boardnum = getvar("boardnum");
+ boardtype = getvar("boardtype");
+
+ if (!strcmp(boardnum, "20070615")) { /* Linksys WRT600N v1/V1.1 */
+ if (!strcmp(boardtype, "0x478") && !strcmp(getvar("cardbus"), "0") && !strcmp(getvar("switch_type"),"BCM5395"))
+ return &platforms[WRT600NV11];
+
+ if (!strcmp(boardtype, "0x478") && !strcmp(getvar("cardbus"), "0"))
+ return &platforms[WRT600N];
+ }
+
+ /*
+ * Normally, these would go inside the "CFE based - newer hardware" block below; however, during early init, the
+ * "pmon_ver" variable is not available on the E3000v1 (and probably the WRT610Nv2 also). Until this is figured out,
+ * these will need to remain here in order for platform detection to work.
+ */
+ if (!strcmp(boardnum, "42")) { /* Linksys */
+ if (!strcmp(boardtype, "0x04cf") && !strcmp(getvar("boot_hw_model"), "E300") && !strcmp(getvar("boot_hw_ver"), "1.0"))
+ return &platforms[E3000V1];
+
+ if (!strcmp(boardtype, "0x04cf") && !strcmp(getvar("boot_hw_model"), "WRT610N") && !strcmp(getvar("boot_hw_ver"), "2.0"))
+ return &platforms[WRT610NV2];
+ }
+
+ if (startswith(getvar("pmon_ver"), "CFE")) {
+ /* CFE based - newer hardware */
+ if (!strcmp(boardnum, "42")) { /* Linksys */
+ if (!strcmp(boardtype, "0x478") && !strcmp(getvar("boot_hw_model"), "WRT300N") && !strcmp(getvar("boot_hw_ver"), "1.1"))
+ return &platforms[WRT300NV11];
+
+ if (!strcmp(boardtype, "0x478") && !strcmp(getvar("cardbus"), "1"))
+ return &platforms[WRT350N];
+
+ if (!strcmp(boardtype, "0x0101") && !strcmp(getvar("boot_ver"), "v3.6"))
+ return &platforms[WRT54G3G];
+
+ if (!strcmp(boardtype, "0x042f") && !strcmp(getvar("model_name"), "WRT54G3GV2-VF"))
+ return &platforms[WRT54G3GV2_VF];
+
+ if (!strcmp(getvar("et1phyaddr"),"5") && !strcmp(getvar("et1mdcport"), "1"))
+ return &platforms[WRTSL54GS];
+
+ if (!strcmp(boardtype, "0x0472")) {
+ if(!strcmp(getvar("boot_hw_model"), "WRT150N")) {
+ if(!strcmp(getvar("boot_hw_ver"), "1"))
+ return &platforms[WRT150NV1];
+ else if(!strcmp(getvar("boot_hw_ver"), "1.1"))
+ return &platforms[WRT150NV11];
+ }
+ else if(!strcmp(getvar("boot_hw_model"), "WRT160N")) {
+ if(!strcmp(getvar("boot_hw_ver"), "1.0"))
+ return &platforms[WRT160NV1];
+ else if(!strcmp(getvar("boot_hw_ver"), "3.0"))
+ return &platforms[WRT160NV3];
+ }
+ }
+
+ /* default to WRT54G */
+ return &platforms[WRT54G];
+ }
+ if (!strcmp(boardnum, "1024") && !strcmp(boardtype, "0x0446"))
+ return &platforms[WAP54GV2];
+
+ if (!strcmp(boardnum, "8") && !strcmp(boardtype, "0x048e"))
+ return &platforms[WL1600GL];
+
+
+ if (!strcmp(boardnum, "44") || !strcmp(boardnum, "44\r")) {
+ if (!strcmp(boardtype,"0x0101") || !strcmp(boardtype, "0x0101\r"))
+ return &platforms[TM2300V2]; /* Dell TrueMobile 2300 v2 */
+ }
+
+ if (!strcmp(boardnum, "45")) { /* ASUS */
+ if (!strcmp(boardtype,"0x042f"))
+ return &platforms[WL500GP];
+ else if (!strcmp(boardtype,"0x0472"))
+ return &platforms[WL500W];
+ else if (!strcmp(boardtype,"0x467"))
+ return &platforms[WL320GE];
+ else
+ return &platforms[WL500GD];
+ }
+
+ if (!strcmp(boardnum, "10496"))
+ return &platforms[USR5461];
+
+ if (!strcmp(getvar("boardtype"), "0x0101") && !strcmp(getvar("boardrev"), "0x10")) /* SE505V2 With Modified CFE */
+ return &platforms[SE505V2];
+
+ if (!strcmp(boardtype, "0x048e") && !strcmp(getvar("boardrev"),"0x35") &&
+ !strcmp(getvar("boardflags"), "0x750")) /* D-Link DIR-320 */
+ return &platforms[DIR320];
+
+ if (!strncmp(boardnum, "TH",2) && !strcmp(boardtype,"0x042f")) {
+ return &platforms[WDNetCenter];
+ }
+
+ if (!strcmp(boardtype,"0x0472") && !strcmp(getvar("cardbus"), "1")) { /* Netgear WNR834B V1 and V2*/
+ if (!strcmp(boardnum, "08") || !strcmp(boardnum, "8"))
+ return &platforms[WNR834BV1];
+ if (!strcmp(boardnum, "01") || !strcmp(boardnum, "1"))
+ return &platforms[WNR834BV2];
+ }
+
+ } else { /* PMON based - old stuff */
+ if ((simple_strtoul(getvar("GemtekPmonVer"), NULL, 0) == 9) &&
+ (simple_strtoul(getvar("et0phyaddr"), NULL, 0) == 30)) {
+ return &platforms[WR850GV1];
+ }
+ if (startswith(boardtype, "bcm94710dev")) {
+ if (!strcmp(boardnum, "42"))
+ return &platforms[WRT54GV1];
+ if (simple_strtoul(boardnum, NULL, 0) == 2)
+ return &platforms[WAP54GV1];
+ }
+ /* MN-700 has also hardware_version 'WL500-...', so use boardnum */
+ if (startswith(getvar("hardware_version"), "WL500-")) {
+ if (!strcmp(getvar("boardnum"), "mn700"))
+ return &platforms[MN700];
+ else
+ return &platforms[WL500G];
+ }
+ if (startswith(getvar("hardware_version"), "WL300-")) {
+ /* Either WL-300g or WL-HDD, do more extensive checks */
+ if ((simple_strtoul(getvar("et0phyaddr"), NULL, 0) == 0) &&
+ (simple_strtoul(getvar("et1phyaddr"), NULL, 0) == 1))
+ return &platforms[WLHDD];
+ if ((simple_strtoul(getvar("et0phyaddr"), NULL, 0) == 0) &&
+ (simple_strtoul(getvar("et1phyaddr"), NULL, 0) == 10))
+ return &platforms[WL300G];
+ }
+ /* Sitecom WL-105b */
+ if (startswith(boardnum, "2") && simple_strtoul(getvar("GemtekPmonVer"), NULL, 0) == 1)
+ return &platforms[WL105B];
+
+ /* unknown asus stuff, probably bcm4702 */
+ if (startswith(boardnum, "asusX"))
+ return &platforms[ASUS_4702];
+
+ /* bcm4702 based Askey RT210W clones, Including:
+ * Askey RT210W (duh?)
+ * Siemens SE505v1
+ * Belkin F5D7230-4 before version v1444 (MiniPCI slot, not integrated)
+ */
+ if (!strcmp(boardtype,"bcm94710r4")
+ && !strcmp(boardnum ,"100")
+ && !strcmp(getvar("pmon_ver"),"v1.03.12.bk")
+ ){
+ return &platforms[RT210W];
+ }
+ }
+
+ if (buf || !strcmp(boardnum, "00")) {/* probably buffalo */
+ if (startswith(boardtype, "bcm94710ap"))
+ return &platforms[BUFFALO_UNKNOWN_4710];
+ else
+ return &platforms[BUFFALO_UNKNOWN];
+ }
+
+ if (startswith(getvar("CFEver"), "MotoWRv2") ||
+ startswith(getvar("CFEver"), "MotoWRv3") ||
+ !strcmp(getvar("MOTO_BOARD_TYPE"), "WR_FEM1")) {
+
+ return &platforms[WR850GV2V3];
+ }
+
+ if (!strcmp(boardnum, "44") && !strcmp(getvar("boardflags"),"0x0388")) { /* Trendware TEW-411BRP+ */
+ return &platforms[TEW411BRPP];
+ }
+
+ if (startswith(boardnum, "04FN")) /* SimpleTech SimpleShare */
+ return &platforms[STI_NAS];
+
+ if (!strcmp(boardnum, "10") && !strcmp(getvar("boardrev"), "0x13")) /* D-Link DWL-3150 */
+ return &platforms[DWL3150];
+
+ if (!strcmp(boardnum, "01") && !strcmp(boardtype, "0x048e") && /* Edimax PS1208MFG */
+ !strcmp(getvar("status_gpio"), "1")) /* gpio based detection */
+ return &platforms[PS1208MFG];
+
+ /* not found */
+ return NULL;
+}
+
+static inline void ssb_maskset32(struct ssb_device *dev,
+ u16 offset, u32 mask, u32 set)
+{
+ ssb_write32(dev, offset, (ssb_read32(dev, offset) & mask) | set);
+}
+
+static void gpio_set_irqenable(int enabled, irqreturn_t (*handler)(int, void *))
+{
+ int irq;
+
+ irq = gpio_to_irq(0);
+ if (irq == -EINVAL) return;
+
+ if (enabled) {
+ if (request_irq(irq, handler, IRQF_SHARED, "gpio", handler))
+ return;
+ } else {
+ free_irq(irq, handler);
+ }
+
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ if (bcm47xx_bus.ssb.chipco.dev)
+ ssb_maskset32(bcm47xx_bus.ssb.chipco.dev, SSB_CHIPCO_IRQMASK, ~SSB_CHIPCO_IRQ_GPIO, (enabled ? SSB_CHIPCO_IRQ_GPIO : 0));
+ break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ if (bcm47xx_bus.bcma.bus.drv_cc.core)
+ bcma_maskset32(bcm47xx_bus.bcma.bus.drv_cc.core, BCMA_CC_IRQMASK, ~BCMA_CC_IRQ_GPIO, (enabled ? BCMA_CC_IRQ_GPIO : 0));
+ break;
+#endif
+ }
+}
+
+static void register_buttons(struct button_t *b)
+{
+ for (; b->name; b++)
+ platform.button_mask |= b->gpio;
+
+ platform.button_mask &= ~gpiomask;
+
+ bcm47xx_gpio_outen(platform.button_mask, 0);
+ bcm47xx_gpio_control(platform.button_mask, 0);
+ platform.button_polarity = bcm47xx_gpio_in(~0) & platform.button_mask;
+ bcm47xx_gpio_polarity(platform.button_mask, platform.button_polarity);
+ bcm47xx_gpio_intmask(platform.button_mask, platform.button_mask);
+
+ gpio_set_irqenable(1, button_handler);
+}
+
+static void unregister_buttons(struct button_t *b)
+{
+ bcm47xx_gpio_intmask(platform.button_mask, 0);
+
+ gpio_set_irqenable(0, button_handler);
+}
+
+
+static void add_msg(struct event_t *event, char *msg, int argv)
+{
+ char *s;
+
+ if (argv)
+ return;
+
+ s = skb_put(event->skb, strlen(msg) + 1);
+ strcpy(s, msg);
+}
+
+static void hotplug_button(struct work_struct *work)
+{
+ struct event_t *event = container_of(work, struct event_t, wq);
+ char *s;
+
+ event->skb = alloc_skb(2048, GFP_KERNEL);
+
+ s = skb_put(event->skb, strlen(event->action) + 2);
+ sprintf(s, "%s@", event->action);
+ fill_event(event);
+
+ NETLINK_CB(event->skb).dst_group = 1;
+ broadcast_uevent(event->skb, 0, 1, GFP_KERNEL);
+
+ kfree(event);
+}
+
+
+static int fill_event (struct event_t *event)
+{
+ static char buf[128];
+
+ add_msg(event, "HOME=/", 0);
+ add_msg(event, "PATH=/sbin:/bin:/usr/sbin:/usr/bin", 0);
+ add_msg(event, "SUBSYSTEM=button", 0);
+ snprintf(buf, 128, "ACTION=%s", event->action);
+ add_msg(event, buf, 0);
+ snprintf(buf, 128, "BUTTON=%s", event->name);
+ add_msg(event, buf, 0);
+ snprintf(buf, 128, "SEEN=%ld", event->seen);
+ add_msg(event, buf, 0);
+ snprintf(buf, 128, "SEQNUM=%llu", uevent_next_seqnum());
+ add_msg(event, buf, 0);
+
+ return 0;
+}
+
+
+static irqreturn_t button_handler(int irq, void *dev_id)
+{
+ struct button_t *b;
+ u32 in, changed;
+
+ in = bcm47xx_gpio_in(~0) & platform.button_mask;
+ bcm47xx_gpio_polarity(platform.button_mask, in);
+ changed = platform.button_polarity ^ in;
+ platform.button_polarity = in;
+
+ changed &= ~bcm47xx_gpio_outen(0, 0);
+
+ for (b = platform.buttons; b->name; b++) {
+ struct event_t *event;
+
+ if (!(b->gpio & changed)) continue;
+
+ b->pressed ^= 1;
+
+ if ((event = (struct event_t *)kzalloc (sizeof(struct event_t), GFP_ATOMIC))) {
+ event->seen = (jiffies - b->seen)/HZ;
+ event->name = b->name;
+ event->action = b->pressed ? "pressed" : "released";
+ INIT_WORK(&event->wq, (void *)(void *)hotplug_button);
+ schedule_work(&event->wq);
+ }
+
+ b->seen = jiffies;
+ }
+ return IRQ_HANDLED;
+}
+
+static void register_leds(struct led_t *l)
+{
+ struct proc_dir_entry *p;
+ u32 mask = 0;
+ u32 oe_mask = 0;
+ u32 val = 0;
+
+ leds = proc_mkdir("led", diag);
+ if (!leds)
+ return;
+
+ for(; l->name; l++) {
+ if (l->gpio & gpiomask)
+ continue;
+
+ if (l->gpio & GPIO_TYPE_EXTIF) {
+ l->state = 0;
+ set_led_extif(l);
+ } else {
+ if (l->polarity != INPUT) oe_mask |= l->gpio;
+ mask |= l->gpio;
+ val |= (l->polarity == NORMAL)?0:l->gpio;
+ }
+
+ if (l->polarity == INPUT) continue;
+
+ if ((p = create_proc_entry(l->name, S_IRUSR, leds))) {
+ l->proc.type = PROC_LED;
+ l->proc.ptr = l;
+ p->data = (void *) &l->proc;
+ p->proc_fops = &diag_proc_fops;
+ }
+ }
+
+ bcm47xx_gpio_outen(mask, oe_mask);
+ bcm47xx_gpio_control(mask, 0);
+ bcm47xx_gpio_out(mask, val);
+ bcm47xx_gpio_intmask(mask, 0);
+}
+
+static void unregister_leds(struct led_t *l)
+{
+ for(; l->name; l++)
+ remove_proc_entry(l->name, leds);
+
+ remove_proc_entry("led", diag);
+}
+
+static void set_led_extif(struct led_t *led)
+{
+ volatile u8 *addr = (volatile u8 *) KSEG1ADDR(EXTIF_UART) + (led->gpio & ~GPIO_TYPE_MASK);
+ if (led->state)
+ *addr = 0xFF;
+ else
+ *addr;
+}
+
+static void led_flash(unsigned long dummy) {
+ struct led_t *l;
+ u32 mask = 0;
+ u8 extif_blink = 0;
+
+ for (l = platform.leds; l->name; l++) {
+ if (l->flash) {
+ if (l->gpio & GPIO_TYPE_EXTIF) {
+ extif_blink = 1;
+ l->state = !l->state;
+ set_led_extif(l);
+ } else {
+ mask |= l->gpio;
+ }
+ }
+ }
+
+ mask &= ~gpiomask;
+ if (mask) {
+ u32 val = ~bcm47xx_gpio_in(~0);
+
+ bcm47xx_gpio_outen(mask, mask);
+ bcm47xx_gpio_control(mask, 0);
+ bcm47xx_gpio_out(mask, val);
+ }
+ if (mask || extif_blink) {
+ mod_timer(&led_timer, jiffies + FLASH_TIME);
+ }
+}
+
+static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+ struct proc_dir_entry *dent = PDE(file->f_dentry->d_inode);
+ char *page;
+ int len = 0;
+
+ if ((page = kmalloc(1024, GFP_KERNEL)) == NULL)
+ return -ENOBUFS;
+
+ if (dent->data != NULL) {
+ struct prochandler_t *handler = (struct prochandler_t *) dent->data;
+ switch (handler->type) {
+ case PROC_LED: {
+ struct led_t * led = (struct led_t *) handler->ptr;
+ if (led->flash) {
+ len = sprintf(page, "f\n");
+ } else {
+ if (led->gpio & GPIO_TYPE_EXTIF) {
+ len = sprintf(page, "%d\n", led->state);
+ } else {
+ u32 in = (bcm47xx_gpio_in(~0) & led->gpio ? 1 : 0);
+ u8 p = (led->polarity == NORMAL ? 0 : 1);
+ len = sprintf(page, "%d\n", ((in ^ p) ? 1 : 0));
+ }
+ }
+ break;
+ }
+ case PROC_MODEL:
+ len = sprintf(page, "%s\n", platform.name);
+ break;
+ case PROC_GPIOMASK:
+ len = sprintf(page, "0x%04x\n", gpiomask);
+ break;
+ }
+ }
+ len += 1;
+
+ if (*ppos < len) {
+ len = min_t(int, len - *ppos, count);
+ if (copy_to_user(buf, (page + *ppos), len)) {
+ kfree(page);
+ return -EFAULT;
+ }
+ *ppos += len;
+ } else {
+ len = 0;
+ }
+
+ kfree(page);
+ return len;
+}
+
+
+static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+{
+ struct proc_dir_entry *dent = PDE(file->f_dentry->d_inode);
+ char *page;
+ int ret = -EINVAL;
+
+ if ((page = kmalloc(count + 1, GFP_KERNEL)) == NULL)
+ return -ENOBUFS;
+
+ if (copy_from_user(page, buf, count)) {
+ kfree(page);
+ return -EINVAL;
+ }
+ page[count] = 0;
+
+ if (dent->data != NULL) {
+ struct prochandler_t *handler = (struct prochandler_t *) dent->data;
+ switch (handler->type) {
+ case PROC_LED: {
+ struct led_t *led = (struct led_t *) handler->ptr;
+ int p = (led->polarity == NORMAL ? 0 : 1);
+
+ if (page[0] == 'f') {
+ led->flash = 1;
+ led_flash(0);
+ } else {
+ led->flash = 0;
+ if (led->gpio & GPIO_TYPE_EXTIF) {
+ led->state = p ^ ((page[0] == '1') ? 1 : 0);
+ set_led_extif(led);
+ } else {
+ bcm47xx_gpio_outen(led->gpio, led->gpio);
+ bcm47xx_gpio_control(led->gpio, 0);
+ bcm47xx_gpio_out(led->gpio, ((p ^ (page[0] == '1')) ? led->gpio : 0));
+ }
+ }
+ break;
+ }
+ case PROC_GPIOMASK:
+ gpiomask = simple_strtoul(page, NULL, 0);
+
+ if (platform.buttons) {
+ unregister_buttons(platform.buttons);
+ register_buttons(platform.buttons);
+ }
+
+ if (platform.leds) {
+ unregister_leds(platform.leds);
+ register_leds(platform.leds);
+ }
+ break;
+ }
+ ret = count;
+ }
+
+ kfree(page);
+ return ret;
+}
+
+static int __init diag_init(void)
+{
+ static struct proc_dir_entry *p;
+ static struct platform_t *detected;
+
+ detected = platform_detect();
+ if (!detected) {
+ printk(MODULE_NAME ": Router model not detected.\n");
+ return -ENODEV;
+ }
+ memcpy(&platform, detected, sizeof(struct platform_t));
+
+ printk(MODULE_NAME ": Detected '%s'\n", platform.name);
+ if (platform.platform_init != NULL) {
+ platform.platform_init();
+ }
+
+ if (!(diag = proc_mkdir("diag", NULL))) {
+ printk(MODULE_NAME ": proc_mkdir on /proc/diag failed\n");
+ return -EINVAL;
+ }
+
+ if ((p = create_proc_entry("model", S_IRUSR, diag))) {
+ p->data = (void *) &proc_model;
+ p->proc_fops = &diag_proc_fops;
+ }
+
+ if ((p = create_proc_entry("gpiomask", S_IRUSR | S_IWUSR, diag))) {
+ p->data = (void *) &proc_gpiomask;
+ p->proc_fops = &diag_proc_fops;
+ }
+
+ if (platform.buttons)
+ register_buttons(platform.buttons);
+
+ if (platform.leds)
+ register_leds(platform.leds);
+
+ return 0;
+}
+
+static void __exit diag_exit(void)
+{
+ del_timer(&led_timer);
+
+ if (platform.buttons)
+ unregister_buttons(platform.buttons);
+
+ if (platform.leds)
+ unregister_leds(platform.leds);
+
+ remove_proc_entry("model", diag);
+ remove_proc_entry("gpiomask", diag);
+ remove_proc_entry("diag", NULL);
+}
+
+module_init(diag_init);
+module_exit(diag_exit);
+
+MODULE_AUTHOR("Mike Baker, Felix Fietkau / OpenWrt.org");
+MODULE_LICENSE("GPL");
diff --git a/package/broadcom-diag/src/diag.h b/package/broadcom-diag/src/diag.h
new file mode 100644
index 000000000..698c37651
--- /dev/null
+++ b/package/broadcom-diag/src/diag.h
@@ -0,0 +1,134 @@
+/*
+ * diag.h - GPIO interface driver for Broadcom boards
+ *
+ * Copyright (C) 2006 Mike Baker <mbm@openwrt.org>,
+ * Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/irq.h>
+#define MODULE_NAME "diag"
+
+#define MAX_GPIO 16
+#define FLASH_TIME HZ/6
+
+enum polarity_t {
+ REVERSE = 0,
+ NORMAL = 1,
+ INPUT = 2,
+};
+
+enum {
+ PROC_BUTTON,
+ PROC_LED,
+ PROC_MODEL,
+ PROC_GPIOMASK
+};
+
+struct prochandler_t {
+ int type;
+ void *ptr;
+};
+
+struct button_t {
+ struct prochandler_t proc;
+ char *name;
+ u32 gpio;
+ unsigned long seen;
+ u8 pressed;
+};
+
+struct led_t {
+ struct prochandler_t proc;
+ char *name;
+ u32 gpio;
+ u8 polarity;
+ u8 flash;
+ u8 state;
+};
+
+struct platform_t {
+ char *name;
+
+ struct button_t buttons[MAX_GPIO];
+ u32 button_mask;
+ u32 button_polarity;
+ void (*platform_init)(void);
+
+ struct led_t leds[MAX_GPIO];
+};
+
+struct event_t {
+ struct work_struct wq;
+ unsigned long seen;
+ char *name, *action;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
+ struct sk_buff *skb;
+#else
+ char *scratch;
+ char *argv[4];
+ char *envp[7];
+ u8 enr, anr;
+#endif
+};
+
+extern char *nvram_get(char *str);
+
+static struct platform_t platform;
+
+/* buttons */
+
+static void register_buttons(struct button_t *b);
+static void unregister_buttons(struct button_t *b);
+
+static void hotplug_button(struct work_struct *work);
+static irqreturn_t button_handler(int irq, void *dev_id);
+
+/* leds */
+
+static void register_leds(struct led_t *l);
+static void unregister_leds(struct led_t *l);
+
+static void set_led_extif(struct led_t *led);
+static void led_flash(unsigned long dummy);
+
+/* 2.4 compatibility */
+#ifndef TIMER_INITIALIZER
+#define TIMER_INITIALIZER(_function, _expires, _data) \
+ { \
+ /* _expires and _data currently unused */ \
+ function: _function \
+ }
+#endif
+
+static struct timer_list led_timer = TIMER_INITIALIZER(&led_flash, 0, 0);
+
+/* proc */
+
+static struct proc_dir_entry *diag, *leds;
+
+static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos);
+static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count, loff_t *ppos);
+
+static struct file_operations diag_proc_fops = {
+ read: diag_proc_read,
+ write: diag_proc_write
+};
+
+static struct prochandler_t proc_model = { .type = PROC_MODEL };
+static struct prochandler_t proc_gpiomask = { .type = PROC_GPIOMASK };
+
diff --git a/package/broadcom-diag/src/gpio.h b/package/broadcom-diag/src/gpio.h
new file mode 100644
index 000000000..d0e3e06c8
--- /dev/null
+++ b/package/broadcom-diag/src/gpio.h
@@ -0,0 +1,16 @@
+#ifndef __DIAG_GPIO_H
+#define __DIAG_GPIO_H
+
+#include <linux/interrupt.h>
+#include <linux/ssb/ssb_embedded.h>
+#include <linux/gpio.h>
+#include <bcm47xx.h>
+
+#define EXTIF_ADDR 0x1f000000
+#define EXTIF_UART (EXTIF_ADDR + 0x00800000)
+
+#define GPIO_TYPE_NORMAL (0x0 << 24)
+#define GPIO_TYPE_EXTIF (0x1 << 24)
+#define GPIO_TYPE_MASK (0xf << 24)
+
+#endif /* __DIAG_GPIO_H */
diff --git a/package/broadcom-wl/Makefile b/package/broadcom-wl/Makefile
new file mode 100644
index 000000000..1a7da0f89
--- /dev/null
+++ b/package/broadcom-wl/Makefile
@@ -0,0 +1,175 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=broadcom-wl
+PKG_VERSION:=5.10.56.27.3
+PKG_RELEASE:=5
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)_$(ARCH).tar.bz2
+PKG_SOURCE_URL:=http://downloads.openwrt.org/sources
+
+PKG_MD5SUM.mipsel:=3363e3a6b3d9d73c49dea870c7834eac
+PKG_MD5SUM.mips:=f8de63debc75333d6b4e28193eb051ff
+PKG_MD5SUM:=$(PKG_MD5SUM.$(ARCH))
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/broadcom-wl/Default
+ SECTION:=kernel
+ CATEGORY:=Kernel modules
+ DEPENDS:=@PACKAGE_kmod-brcm-wl||PACKAGE_kmod-brcm-wl-mini
+ SUBMENU:=Proprietary BCM43xx WiFi driver
+ SUBMENUDEP:=@TARGET_brcm47xx||TARGET_brcm63xx
+endef
+
+define KernelPackage/brcm-wl/Default
+ $(call Package/broadcom-wl/Default)
+ SECTION:=kernel
+ DEPENDS:=@TARGET_brcm47xx||TARGET_brcm63xx +wireless-tools
+ TITLE:=Kernel driver for BCM43xx chipsets
+ FILES:=$(PKG_BUILD_DIR)/driver$(1)/wl.ko $(PKG_BUILD_DIR)/glue/wl_glue.ko
+ AUTOLOAD:=$(call AutoLoad,30,wl_glue wl)
+endef
+
+define KernelPackage/brcm-wl/Default/description
+ This package contains the proprietary wireless driver for the Broadcom
+ BCM43xx chipset.
+endef
+
+define KernelPackage/brcm-wl
+$(call KernelPackage/brcm-wl/Default,)
+ TITLE+= (normal version)
+endef
+
+define KernelPackage/brcm-wl/description
+$(call KernelPackage/brcm-wl/Default/description)
+endef
+
+define KernelPackage/brcm-wl-mini
+$(call KernelPackage/brcm-wl/Default,-mini)
+ TITLE+= (Legacy version)
+endef
+
+define KernelPackage/brcm-wl-mini/description
+$(call KernelPackage/brcm-wl/Default/description)
+endef
+
+define Package/wlc
+$(call Package/broadcom-wl/Default)
+ TITLE:=wl driver setup utility
+endef
+
+define Package/wlc/description
+ This package contains an utility for initializing the proprietary Broadcom
+ wl driver.
+endef
+
+define Package/wl
+$(call Package/broadcom-wl/Default)
+ TITLE:=Proprietary Broadcom wl driver config utility
+endef
+
+define Package/wl/description
+ This package contains the proprietary utility (wl) for configuring the
+ proprietary Broadcom wl driver.
+endef
+
+define Package/nas
+$(call Package/broadcom-wl/Default)
+ TITLE:=Proprietary Broadcom WPA/WPA2 authenticator
+endef
+
+define Package/nas/description
+ This package contains the proprietary WPA/WPA2 authenticator (nas) for the
+ proprietary Broadcom wl driver.
+endef
+
+MAKE_KMOD := $(MAKE) -C "$(LINUX_DIR)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ ARCH="$(LINUX_KARCH)" \
+ PATH="$(TARGET_PATH)" \
+ SUBDIRS="$(PKG_BUILD_DIR)/kmod" \
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ $(CP) $(PKG_BUILD_DIR)/driver $(PKG_BUILD_DIR)/driver-mini
+ $(CP) ./src/glue $(PKG_BUILD_DIR)/glue
+endef
+
+define Build/Compile
+ # Compile the kernel part
+ $(MAKE_KMOD) \
+ SUBDIRS="$(PKG_BUILD_DIR)/driver" \
+ MODFLAGS="-DMODULE -mlong-calls" \
+ modules
+
+ $(MAKE_KMOD) \
+ SUBDIRS="$(PKG_BUILD_DIR)/driver-mini" \
+ MODFLAGS="-DMODULE -mlong-calls" \
+ BUILD_TYPE="wl_apsta_mini" \
+ modules
+
+ # Compile glue driver
+ $(MAKE_KMOD) -C "$(LINUX_DIR)" \
+ SUBDIRS="$(PKG_BUILD_DIR)/glue" \
+ modules
+
+ # Compile libshared
+ $(MAKE) -C $(PKG_BUILD_DIR)/shared \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS) -I. -I$(PKG_BUILD_DIR)/driver/include" \
+ all
+
+ $(TARGET_CC) -o $(PKG_BUILD_DIR)/wlc \
+ -I$(PKG_BUILD_DIR)/shared -I$(PKG_BUILD_DIR)/driver/include \
+ ./src/wlc.c $(PKG_BUILD_DIR)/shared/libshared.a
+
+ $(TARGET_CC) -o $(PKG_BUILD_DIR)/nas \
+ $(PKG_BUILD_DIR)/nas_exe.o \
+ $(PKG_BUILD_DIR)/shared/libshared.a
+
+ $(TARGET_CC) -o $(PKG_BUILD_DIR)/wl \
+ $(PKG_BUILD_DIR)/wl_exe.o \
+ $(PKG_BUILD_DIR)/shared/libshared.a
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/shared/libshared.a $(1)/usr/lib/
+endef
+
+define Package/wlc/install
+ $(CP) ./files/* $(1)/
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/wlc $(1)/sbin/
+endef
+
+define Package/wlc/postinst
+#!/bin/sh
+[ -n "$${IPKG_INSTROOT}" ] || /etc/init.d/wlunbind enable || true
+endef
+
+define Package/wl/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/wl $(1)/usr/sbin/
+endef
+
+define Package/nas/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/nas $(1)/usr/sbin/
+ ln -sf nas $(1)/usr/sbin/nas4not
+ ln -sf nas $(1)/usr/sbin/nas4wds
+endef
+
+$(eval $(call KernelPackage,brcm-wl))
+$(eval $(call KernelPackage,brcm-wl-mini))
+$(eval $(call BuildPackage,wlc))
+$(eval $(call BuildPackage,wl))
+$(eval $(call BuildPackage,nas))
diff --git a/package/broadcom-wl/files/etc/hotplug.d/net/20-broadcom_wds b/package/broadcom-wl/files/etc/hotplug.d/net/20-broadcom_wds
new file mode 100644
index 000000000..0a563c2db
--- /dev/null
+++ b/package/broadcom-wl/files/etc/hotplug.d/net/20-broadcom_wds
@@ -0,0 +1,61 @@
+include /lib/wifi
+
+setup_broadcom_wds() {
+ local iface="$1"
+ local remote="$(wlc ifname "$iface" wdsmac)"
+
+ [ -z "$remote" ] && return
+
+ config_cb() {
+ [ -z "$CONFIG_SECTION" ] && return
+
+ config_get type "$CONFIG_SECTION" TYPE
+ [ "$type" = "wifi-iface" ] || return
+
+ config_get network "$CONFIG_SECTION" network
+ [ -z "$network" ] && return
+
+ config_get addr "$CONFIG_SECTION" bssid
+ addr=$(echo "$addr" | tr 'A-F' 'a-f')
+ [ "$addr" = "$remote" ] && {
+ local cfg="$CONFIG_SECTION"
+
+ include /lib/network
+ scan_interfaces
+
+ for network in $network; do
+ setup_interface "$iface" "$network"
+ done
+
+ config_get encryption "$cfg" encryption
+ config_get key "$cfg" key
+ config_get ssid "$cfg" ssid
+
+ [ "$encryption" != "none" ] && {
+ sleep 5
+ case "$encryption" in
+ psk|PSK)
+ nas4not "$network" "$iface" up auto tkip psk "$key" "$ssid"
+ ;;
+ psk2|PSK2)
+ nas4not "$network" "$iface" up auto aes psk "$key" "$ssid"
+ ;;
+ psk+psk2|psk2+psk|PSK+PSK2|PSK2+PSK)
+ nas4not "$network" "$iface" up auto aes+tkip psk "$key" "$ssid"
+ ;;
+ *)
+ nas4not lan "$iface" up auto aes "$encryption" "$key" "$ssid"
+ ;;
+ esac
+ }
+ }
+ }
+
+ config_load wireless
+}
+
+case "$ACTION" in
+ add|register)
+ [ "${INTERFACE%%0.*}" = wds ] && setup_broadcom_wds "$INTERFACE"
+ ;;
+esac
diff --git a/package/broadcom-wl/files/etc/init.d/wlunbind b/package/broadcom-wl/files/etc/init.d/wlunbind
new file mode 100755
index 000000000..0a29db565
--- /dev/null
+++ b/package/broadcom-wl/files/etc/init.d/wlunbind
@@ -0,0 +1,29 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2010-2011 OpenWrt.org
+
+START=09
+
+unbind_driver() {
+ local driver="$1"
+ local sysfs="/sys/bus/pci/drivers/$driver"
+ if [ -d "$sysfs" ]; then
+ local lnk
+ for lnk in $sysfs/*; do
+ [ -h "$lnk" ] || continue
+ case "${lnk##*/}" in
+ *:*:*.*)
+ logger "Unbinding WL PCI device ${lnk##*/} from $driver"
+ echo -n "${lnk##*/}" > "$sysfs/unbind"
+ ;;
+ esac
+ done
+ fi
+}
+
+boot() {
+ unbind_driver b43-pci-bridge
+ unbind_driver bcma-pci-bridge
+}
+
+start() { :; }
+stop() { :; }
diff --git a/package/broadcom-wl/files/lib/wifi/broadcom.sh b/package/broadcom-wl/files/lib/wifi/broadcom.sh
new file mode 100644
index 000000000..57e11e4b1
--- /dev/null
+++ b/package/broadcom-wl/files/lib/wifi/broadcom.sh
@@ -0,0 +1,392 @@
+append DRIVERS "broadcom"
+
+scan_broadcom() {
+ local device="$1"
+ local wds
+ local adhoc sta apmode mon disabled
+ local adhoc_if sta_if ap_if mon_if
+ local _c=0
+
+ config_get vifs "$device" vifs
+ for vif in $vifs; do
+ config_get_bool disabled "$vif" disabled 0
+ [ $disabled -eq 0 ] || continue
+
+ config_get mode "$vif" mode
+ _c=$(($_c + 1))
+ case "$mode" in
+ adhoc)
+ adhoc=1
+ adhoc_if="$vif"
+ ;;
+ sta)
+ sta=1
+ sta_if="$vif"
+ ;;
+ ap)
+ apmode=1
+ ap_if="${ap_if:+$ap_if }$vif"
+ ;;
+ wds)
+ config_get addr "$vif" bssid
+ [ -z "$addr" ] || {
+ addr=$(echo "$addr" | tr 'A-F' 'a-f')
+ append wds "$addr"
+ }
+ ;;
+ monitor)
+ mon=1
+ mon_if="$vif"
+ ;;
+ *) echo "$device($vif): Invalid mode";;
+ esac
+ done
+ config_set "$device" wds "$wds"
+
+ local _c=
+ for vif in ${adhoc_if:-$sta_if $ap_if $mon_if}; do
+ config_set "$vif" ifname "${device}${_c:+.$_c}"
+ _c=$((${_c:-0} + 1))
+ done
+ config_set "$device" vifs "${adhoc_if:-$sta_if $ap_if $mon_if}"
+
+ ifdown="down"
+ for vif in 0 1 2 3; do
+ append ifdown "vif $vif" "$N"
+ append ifdown "enabled 0" "$N"
+ done
+
+ ap=1
+ infra=1
+ if [ "$_c" -gt 1 ]; then
+ mssid=1
+ else
+ mssid=
+ fi
+ apsta=0
+ radio=1
+ monitor=0
+ case "$adhoc:$sta:$apmode:$mon" in
+ 1*)
+ ap=0
+ mssid=
+ infra=0
+ ;;
+ :1:1:)
+ apsta=1
+ wet=1
+ ;;
+ :1::)
+ wet=1
+ ap=0
+ mssid=
+ ;;
+ :::1)
+ wet=1
+ ap=0
+ mssid=
+ monitor=1
+ ;;
+ ::)
+ radio=0
+ ;;
+ esac
+}
+
+disable_broadcom() {
+ local device="$1"
+ set_wifi_down "$device"
+ wlc ifname "$device" down
+ wlc ifname "$device" bssid `wlc ifname "$device" default_bssid`
+ (
+ include /lib/network
+
+ # make sure the interfaces are down and removed from all bridges
+ for dev in $device ${device}.1 ${device}.2 ${device}.3; do
+ ifconfig "$dev" down 2>/dev/null >/dev/null && {
+ unbridge "$dev"
+ }
+ done
+ )
+ true
+}
+
+enable_broadcom() {
+ local device="$1"
+ local _c
+ config_get channel "$device" channel
+ config_get country "$device" country
+ config_get maxassoc "$device" maxassoc
+ config_get wds "$device" wds
+ config_get vifs "$device" vifs
+ config_get distance "$device" distance
+ config_get slottime "$device" slottime
+ config_get rxantenna "$device" rxantenna
+ config_get txantenna "$device" txantenna
+ config_get_bool frameburst "$device" frameburst
+ config_get macfilter "$device" macfilter
+ config_get maclist "$device" maclist
+ config_get macaddr "$device" macaddr
+ config_get txpower "$device" txpower
+ config_get frag "$device" frag
+ config_get rts "$device" rts
+ config_get hwmode "$device" hwmode
+ local vif_pre_up vif_post_up vif_do_up vif_txpower
+ local doth=0
+ local wmm=1
+
+ _c=0
+ nas="$(which nas)"
+ nas_cmd=
+ if_up=
+
+ [ -z "$slottime" ] && {
+ [ -n "$distance" ] && {
+ # slottime = 9 + (distance / 150) + (distance % 150 ? 1 : 0)
+ slottime="$((9 + ($distance / 150) + 1 - (150 - ($distance % 150)) / 150 ))"
+ }
+ } || {
+ slottime="${slottime:--1}"
+ }
+
+ case "$macfilter" in
+ allow|2)
+ macfilter=2;
+ ;;
+ deny|1)
+ macfilter=1;
+ ;;
+ disable|none|0)
+ macfilter=0;
+ ;;
+ esac
+
+ case "$hwmode" in
+ *b) hwmode=0;;
+ *bg) hwmode=1;;
+ *g) hwmode=2;;
+ *gst) hwmode=4;;
+ *lrs) hwmode=5;;
+ *) hwmode=1;;
+ esac
+
+ for vif in $vifs; do
+ config_get vif_txpower "$vif" txpower
+
+ config_get mode "$vif" mode
+ append vif_pre_up "vif $_c" "$N"
+ append vif_post_up "vif $_c" "$N"
+ append vif_do_up "vif $_c" "$N"
+
+ config_get_bool wmm "$vif" wmm "$wmm"
+ config_get_bool doth "$vif" doth "$doth"
+
+ [ "$mode" = "sta" ] || {
+ config_get_bool hidden "$vif" hidden 0
+ append vif_pre_up "closed $hidden" "$N"
+ config_get_bool isolate "$vif" isolate 0
+ append vif_pre_up "ap_isolate $isolate" "$N"
+ }
+
+ wsec_r=0
+ eap_r=0
+ wsec=0
+ auth=0
+ nasopts=
+ config_get enc "$vif" encryption
+ case "$enc" in
+ *wep*)
+ wsec_r=1
+ wsec=1
+ defkey=1
+ config_get key "$vif" key
+ case "$enc" in
+ *shared*) append vif_do_up "wepauth 1" "$N";;
+ *) append vif_do_up "wepauth 0" "$N";;
+ esac
+ case "$key" in
+ [1234])
+ defkey="$key"
+ for knr in 1 2 3 4; do
+ config_get k "$vif" key$knr
+ [ -n "$k" ] || continue
+ [ "$defkey" = "$knr" ] && def="=" || def=""
+ append vif_do_up "wepkey $def$knr,$k" "$N"
+ done
+ ;;
+ "");;
+ *) append vif_do_up "wepkey =1,$key" "$N";;
+ esac
+ ;;
+ *psk*)
+ wsec_r=1
+ config_get key "$vif" key
+
+ # psk version + default cipher
+ case "$enc" in
+ *mixed*|*psk+psk2*) auth=132; wsec=6;;
+ *psk2*) auth=128; wsec=4;;
+ *) auth=4; wsec=2;;
+ esac
+
+ # cipher override
+ case "$enc" in
+ *tkip+aes*|*tkip+ccmp*|*aes+tkip*|*ccmp+tkip*) wsec=6;;
+ *aes*|*ccmp*) wsec=4;;
+ *tkip*) wsec=2;;
+ esac
+
+ # group rekey interval
+ config_get rekey "$vif" wpa_group_rekey
+
+ eval "${vif}_key=\"\$key\""
+ nasopts="-k \"\$${vif}_key\"${rekey:+ -g $rekey}"
+ ;;
+ *wpa*)
+ wsec_r=1
+ eap_r=1
+ config_get auth_server "$vif" auth_server
+ [ -z "$auth_server" ] && config_get auth_server "$vif" server
+ config_get auth_port "$vif" auth_port
+ [ -z "$auth_port" ] && config_get auth_port "$vif" port
+ config_get auth_secret "$vif" auth_secret
+ [ -z "$auth_secret" ] && config_get auth_secret "$vif" key
+
+ # wpa version + default cipher
+ case "$enc" in
+ *mixed*|*wpa+wpa2*) auth=66; wsec=6;;
+ *wpa2*) auth=64; wsec=4;;
+ *) auth=2; wsec=2;;
+ esac
+
+ # cipher override
+ case "$enc" in
+ *tkip+aes*|*tkip+ccmp*|*aes+tkip*|*ccmp+tkip*) wsec=6;;
+ *aes*|*ccmp*) wsec=4;;
+ *tkip*) wsec=2;;
+ esac
+
+ # group rekey interval
+ config_get rekey "$vif" wpa_group_rekey
+
+ eval "${vif}_key=\"\$auth_secret\""
+ nasopts="-r \"\$${vif}_key\" -h $auth_server -p ${auth_port:-1812}${rekey:+ -g $rekey}"
+ ;;
+ esac
+ append vif_do_up "wsec $wsec" "$N"
+ append vif_do_up "wpa_auth $auth" "$N"
+ append vif_do_up "wsec_restrict $wsec_r" "$N"
+ append vif_do_up "eap_restrict $eap_r" "$N"
+
+ config_get ssid "$vif" ssid
+ append vif_post_up "vlan_mode 0" "$N"
+ append vif_post_up "ssid $ssid" "$N"
+ append vif_do_up "ssid $ssid" "$N"
+
+ [ "$mode" = "monitor" ] && {
+ append vif_post_up "monitor $monitor" "$N"
+ }
+
+ [ "$mode" = "adhoc" ] && {
+ config_get bssid "$vif" bssid
+ [ -n "$bssid" ] && {
+ append vif_pre_up "bssid $bssid" "$N"
+ append vif_pre_up "ibss_merge 0" "$N"
+ } || {
+ append vif_pre_up "ibss_merge 1" "$N"
+ }
+ }
+
+ append vif_post_up "enabled 1" "$N"
+
+ config_get ifname "$vif" ifname
+ #append if_up "ifconfig $ifname up" ";$N"
+
+ local net_cfg
+ net_cfg="$(find_net_config "$vif")"
+ [ -z "$net_cfg" ] || {
+ append if_up "set_wifi_up '$vif' '$ifname'" ";$N"
+ append if_up "start_net '$ifname' '$net_cfg'" ";$N"
+ }
+ [ -z "$nasopts" ] || {
+ eval "${vif}_ssid=\"\$ssid\""
+ nas_mode="-A"
+ [ "$mode" = "sta" ] && nas_mode="-S"
+ [ -z "$nas" ] || {
+ nas_cmd="${nas_cmd:+$nas_cmd$N}start-stop-daemon -S -b -p /var/run/nas.$ifname.pid -x $nas -- -P /var/run/nas.$ifname.pid -H 34954 -i $ifname $nas_mode -m $auth -w $wsec -s \"\$${vif}_ssid\" -g 3600 -F $nasopts"
+ }
+ }
+ _c=$(($_c + 1))
+ done
+ killall -KILL nas >&- 2>&-
+ wlc ifname "$device" stdin <<EOF
+$ifdown
+
+gmode ${hwmode:-1}
+apsta $apsta
+ap $ap
+${mssid:+mssid $mssid}
+infra $infra
+${wet:+wet 1}
+802.11d 0
+802.11h ${doth:-0}
+wme ${wmm:-1}
+rxant ${rxantenna:-3}
+txant ${txantenna:-3}
+fragthresh ${frag:-2346}
+rtsthresh ${rts:-2347}
+monitor ${monitor:-0}
+
+radio ${radio:-1}
+macfilter ${macfilter:-0}
+maclist ${maclist:-none}
+wds none
+${wds:+wds $wds}
+country ${country:-US}
+${channel:+channel $channel}
+maxassoc ${maxassoc:-128}
+slottime ${slottime:--1}
+${frameburst:+frameburst $frameburst}
+
+$vif_pre_up
+up
+$vif_post_up
+EOF
+ eval "$if_up"
+ wlc ifname "$device" stdin <<EOF
+$vif_do_up
+EOF
+
+ # use vif_txpower (from last wifi-iface) instead of txpower (from
+ # wifi-device) if the latter does not exist
+ txpower=${txpower:-$vif_txpower}
+ [ -z "$txpower" ] || iwconfig $device txpower ${txpower}dBm
+
+ eval "$nas_cmd"
+}
+
+
+detect_broadcom() {
+ local i=-1
+
+ while grep -qs "^ *wl$((++i)):" /proc/net/dev; do
+ config_get type wl${i} type
+ [ "$type" = broadcom ] && continue
+ cat <<EOF
+config wifi-device wl${i}
+ option type broadcom
+ option channel 11
+
+ # REMOVE THIS LINE TO ENABLE WIFI:
+ option disabled 1
+
+config wifi-iface
+ option device wl${i}
+ option network lan
+ option mode ap
+ option ssid OpenWrt${i#0}
+ option encryption none
+
+EOF
+ done
+}
diff --git a/package/broadcom-wl/patches/003-compat-2.6.35.patch b/package/broadcom-wl/patches/003-compat-2.6.35.patch
new file mode 100644
index 000000000..89b665371
--- /dev/null
+++ b/package/broadcom-wl/patches/003-compat-2.6.35.patch
@@ -0,0 +1,39 @@
+--- a/driver/wl_linux.c
++++ b/driver/wl_linux.c
+@@ -2082,7 +2082,11 @@ static void
+ _wl_set_multicast_list(struct net_device *dev)
+ {
+ wl_info_t *wl;
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,34)
+ struct dev_mc_list *mclist;
++#else
++ struct netdev_hw_addr *ha;
++#endif
+ int i;
+
+ if (!dev)
+@@ -2098,14 +2102,24 @@ _wl_set_multicast_list(struct net_device
+ wl->pub->allmulti = (dev->flags & IFF_ALLMULTI)? TRUE: FALSE;
+
+ /* copy the list of multicasts into our private table */
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,34)
+ for (i = 0, mclist = dev->mc_list; mclist && (i < dev->mc_count);
+ i++, mclist = mclist->next) {
++#else
++ i = 0;
++ netdev_for_each_mc_addr(ha, dev) {
++#endif
+ if (i >= MAXMULTILIST) {
+ wl->pub->allmulti = TRUE;
+ i = 0;
+ break;
+ }
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,34)
+ wl->pub->multicast[i] = *((struct ether_addr*) mclist->dmi_addr);
++#else
++ wl->pub->multicast[i] = *((struct ether_addr*) ha->addr);
++ i++;
++#endif
+ }
+ wl->pub->nmulticast = i;
+ wlc_set(wl->wlc, WLC_SET_PROMISC, (dev->flags & IFF_PROMISC));
diff --git a/package/broadcom-wl/patches/004-remove-pcmcia.patch b/package/broadcom-wl/patches/004-remove-pcmcia.patch
new file mode 100644
index 000000000..36dda47e1
--- /dev/null
+++ b/package/broadcom-wl/patches/004-remove-pcmcia.patch
@@ -0,0 +1,22 @@
+--- a/driver/include/linuxver.h
++++ b/driver/include/linuxver.h
+@@ -111,7 +111,7 @@ typedef irqreturn_t(*FN_ISR) (int irq, v
+ #endif /* not SANDGATE2G */
+ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67) */
+
+-#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
++#if 0
+
+ #include <pcmcia/cs_types.h>
+ #include <pcmcia/cs.h>
+--- a/driver/linux_osl.c
++++ b/driver/linux_osl.c
+@@ -62,7 +62,7 @@ struct osl_info {
+ };
+
+ /* PCMCIA attribute space access macros */
+-#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
++#if 0
+ struct pcmcia_dev {
+ dev_link_t link; /* PCMCIA device pointer */
+ dev_node_t node; /* PCMCIA node structure */
diff --git a/package/broadcom-wl/patches/005-fix-mem-leak-on-unload.patch b/package/broadcom-wl/patches/005-fix-mem-leak-on-unload.patch
new file mode 100644
index 000000000..41c246ff8
--- /dev/null
+++ b/package/broadcom-wl/patches/005-fix-mem-leak-on-unload.patch
@@ -0,0 +1,31 @@
+From: George Kashperko <george@znau.edu.ua>
+
+Release nvram variables buffer.
+Prevent block reserved by alloc_etherdev from being freed.
+Signed-off-by: George Kashperko <george@znau.edu.ua>
+---
+---
+--- a/driver/siutils.c
++++ b/driver/siutils.c
+@@ -647,7 +647,10 @@ si_detach(si_t *sih)
+ #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
+ if (sii != &ksii)
+ #endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
+- MFREE(sii->osh, sii, sizeof(si_info_t));
++ do {
++ MFREE(sii->osh, sii, sizeof(si_info_t));
++ nvram_exit((void *)&(sii->pub));
++ } while (0);
+ }
+
+ void *
+--- a/driver/wl_linux.c
++++ b/driver/wl_linux.c
+@@ -1477,7 +1477,6 @@ wl_free_if(wl_info_t *wl, wl_if_t *wlif)
+ free_netdev(wlif->dev);
+ #endif
+ }
+- MFREE(wl->osh, wlif, sizeof(wl_if_t));
+ }
+
+ #ifdef AP
diff --git a/package/broadcom-wl/patches/006-generic-dma-api.patch b/package/broadcom-wl/patches/006-generic-dma-api.patch
new file mode 100644
index 000000000..a90bbe1f9
--- /dev/null
+++ b/package/broadcom-wl/patches/006-generic-dma-api.patch
@@ -0,0 +1,88 @@
+From: George Kashperko <george@znau.edu.ua>
+
+broadcom-wl driver bound to ssb device with ssb driver probe
+have osh handle struct pdev pointer value initialized with
+ssb_device pointer. Later on pdev is used with legacy pci
+dma api as pci_dev thus causing oops sometimes.
+
+The patch replaces legacy pci dma api and pass relevant
+device struct pointer to avoid crashes.
+Signed-off-by: George Kashperko <george@znau.edu.ua>
+---
+ driver/linux_osl.c | 28 +++++++++++++++++++++++-----
+ 1 file changed, 23 insertions(+), 5 deletions(-)
+--- a/driver/linux_osl.c
++++ b/driver/linux_osl.c
+@@ -25,6 +25,9 @@
+ #include <asm/paccess.h>
+ #endif /* mips */
+ #include <pcicfg.h>
++#ifdef CONFIG_SSB
++#include <linux/ssb/ssb.h>
++#endif
+
+ #define PCI_CFG_RETRY 10
+
+@@ -364,12 +367,27 @@ osl_dma_consistent_align(void)
+ return (PAGE_SIZE);
+ }
+
++static struct device *
++osl_get_dmadev(osl_t *osh)
++{
++#ifdef CONFIG_SSB
++ if (osh->bustype == SI_BUS) {
++ /* This can be SiliconBackplane emulated as pci with Broadcom or
++ * ssb device. Less harmful is to check for pci_bus_type and if
++ * no match then assume we got ssb */
++ if (((struct pci_dev *)osh->pdev)->dev.bus != &pci_bus_type)
++ return ((struct ssb_device *)osh->pdev)->dma_dev;
++ }
++#endif
++ return &((struct pci_dev *)osh->pdev)->dev;
++}
++
+ void*
+ osl_dma_alloc_consistent(osl_t *osh, uint size, ulong *pap)
+ {
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+- return (pci_alloc_consistent(osh->pdev, size, (dma_addr_t*)pap));
++ return (dma_alloc_coherent(osl_get_dmadev(osh), size, (dma_addr_t*)pap, GFP_ATOMIC));
+ }
+
+ void
+@@ -377,7 +395,7 @@ osl_dma_free_consistent(osl_t *osh, void
+ {
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+- pci_free_consistent(osh->pdev, size, va, (dma_addr_t)pa);
++ dma_free_coherent(osl_get_dmadev(osh), size, va, (dma_addr_t)pa);
+ }
+
+ uint BCMFASTPATH
+@@ -386,13 +404,13 @@ osl_dma_map(osl_t *osh, void *va, uint s
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+
+ if (direction == DMA_TX)
+- return (pci_map_single(osh->pdev, va, size, PCI_DMA_TODEVICE));
++ return (dma_map_single(osl_get_dmadev(osh), va, size, PCI_DMA_TODEVICE));
+ else {
+ #ifdef mips
+ dma_cache_inv((uint)va, size);
+ return (virt_to_phys(va));
+ #else /* mips */
+- return (pci_map_single(osh->pdev, va, size, PCI_DMA_FROMDEVICE));
++ return (dma_map_single(osl_get_dmadev(osh), va, size, PCI_DMA_FROMDEVICE));
+ #endif /* mips */
+ }
+ }
+@@ -404,7 +422,7 @@ osl_dma_unmap(osl_t *osh, uint pa, uint
+
+ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
+ dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE;
+- pci_unmap_single(osh->pdev, (uint32)pa, size, dir);
++ dma_unmap_single(osl_get_dmadev(osh), (uint32)pa, size, dir);
+ }
+
+
diff --git a/package/broadcom-wl/patches/007-use-glue-driver.patch b/package/broadcom-wl/patches/007-use-glue-driver.patch
new file mode 100644
index 000000000..2639abcf6
--- /dev/null
+++ b/package/broadcom-wl/patches/007-use-glue-driver.patch
@@ -0,0 +1,184 @@
+--- a/driver/wl_linux.c
++++ b/driver/wl_linux.c
+@@ -85,10 +85,9 @@ typedef void wlc_hw_info_t;
+ #include <bcmjtag.h>
+ #endif /* BCMJTAG */
+
+-
+-#ifdef CONFIG_SSB
+-#include <linux/ssb/ssb.h>
+-#endif
++#if defined(CONFIG_SSB) || defined(CONFIG_BCMA)
++#include <wl_glue.h>
++#endif /* defined(CONFIG_SSB) || defined(CONFIG_BCMA) */
+
+ /* Linux wireless extension support */
+ #ifdef CONFIG_WIRELESS_EXT
+@@ -997,62 +996,32 @@ static struct pci_driver wl_pci_driver =
+ #endif /* CONFIG_PCI */
+ #endif
+
++#ifdef BCMJTAG
++static bcmjtag_driver_t wl_jtag_driver = {
++ wl_jtag_probe,
++ wl_jtag_detach,
++ wl_jtag_poll,
++ };
++#endif /* BCMJTAG */
+
+-static int wl_ssb_probe(struct ssb_device *dev, const struct ssb_device_id *id)
++#if defined(CONFIG_SSB) || defined(CONFIG_BCMA)
++static void * glue_attach_cb(u16 vendor, u16 device,
++ ulong mmio, void *dev, u32 irq)
+ {
+- wl_info_t *wl;
+- void *mmio;
+-
+- if (dev->bus->bustype != SSB_BUSTYPE_SSB) {
+- printk("Attaching to SSB behind PCI is not supported. Please remove the b43 ssb bridge\n");
+- return -EINVAL;
+- }
+-
+- mmio = (void *) 0x18000000 + dev->core_index * 0x1000;
+- wl = wl_attach(id->vendor, id->coreid, (ulong) mmio, SI_BUS, dev, dev->irq);
+- if (!wl) {
+- printk("wl_attach failed\n");
+- return -ENODEV;
+- }
+-
+- ssb_set_drvdata(dev, wl);
+-
+- return 0;
++ return wl_attach(vendor, device, mmio, SI_BUS, dev, irq);
+ }
+
+-static void wl_ssb_remove(struct ssb_device *dev)
++static void glue_remove_cb(void *wldev)
+ {
+- wl_info_t *wl = (wl_info_t *) ssb_get_drvdata(dev);
++ wl_info_t *wl = (wl_info_t *)wldev;
+
+ WL_LOCK(wl);
+ WL_APSTA_UPDN(("wl%d (%s): wl_remove() -> wl_down()\n", wl->pub->unit, wl->dev->name));
+ wl_down(wl);
+ WL_UNLOCK(wl);
+ wl_free(wl);
+- ssb_set_drvdata(dev, NULL);
+ }
+-
+-static const struct ssb_device_id wl_ssb_tbl[] = {
+- SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, SSB_ANY_REV),
+- SSB_DEVTABLE_END
+-};
+-
+-#ifdef CONFIG_SSB
+-static struct ssb_driver wl_ssb_driver = {
+- .name = KBUILD_MODNAME,
+- .id_table = wl_ssb_tbl,
+- .probe = wl_ssb_probe,
+- .remove = wl_ssb_remove,
+-};
+-#endif
+-
+-#ifdef BCMJTAG
+-static bcmjtag_driver_t wl_jtag_driver = {
+- wl_jtag_probe,
+- wl_jtag_detach,
+- wl_jtag_poll,
+- };
+-#endif /* BCMJTAG */
++#endif/* defined(CONFIG_SSB) || defined(CONFIG_BCMA) */
+
+
+ /**
+@@ -1067,11 +1036,13 @@ wl_module_init(void)
+ {
+ int error = -ENODEV;
+
+-#ifdef CONFIG_SSB
+- error = ssb_driver_register(&wl_ssb_driver);
++#if defined(CONFIG_SSB) || defined(CONFIG_BCMA)
++ wl_glue_set_attach_callback(&glue_attach_cb);
++ wl_glue_set_remove_callback(&glue_remove_cb);
++ error = wl_glue_register();
+ if (error)
+ return error;
+-#endif /* CONFIG_SSB */
++#endif /* defined(CONFIG_SSB) || defined(CONFIG_BCMA) */
+
+ #ifdef CONFIG_PCI
+ error = pci_register_driver(&wl_pci_driver);
+@@ -1082,7 +1053,9 @@ wl_module_init(void)
+ return 0;
+
+ error_pci:
+- ssb_driver_unregister(&wl_ssb_driver);
++#if defined(CONFIG_SSB) || defined(CONFIG_BCMA)
++ wl_glue_unregister();
++#endif /* defined(CONFIG_SSB) || defined(CONFIG_BCMA) */
+ return error;
+ }
+
+@@ -1099,9 +1072,9 @@ wl_module_exit(void)
+ #ifdef CONFIG_PCI
+ pci_unregister_driver(&wl_pci_driver);
+ #endif /* CONFIG_PCI */
+-#ifdef CONFIG_SSB
+- ssb_driver_unregister(&wl_ssb_driver);
+-#endif /* CONFIG_SSB */
++#if defined(CONFIG_SSB) || defined(CONFIG_BCMA)
++ wl_glue_unregister();
++#endif /* defined(CONFIG_SSB) || defined(CONFIG_BCMA) */
+ }
+
+ module_init(wl_module_init);
+--- a/driver/linux_osl.c
++++ b/driver/linux_osl.c
+@@ -25,9 +25,9 @@
+ #include <asm/paccess.h>
+ #endif /* mips */
+ #include <pcicfg.h>
+-#ifdef CONFIG_SSB
+-#include <linux/ssb/ssb.h>
+-#endif
++#if defined(CONFIG_SSB) || defined(CONFIG_BCMA)
++#include <wl_glue.h>
++#endif /* defined(CONFIG_SSB) || defined(CONFIG_BCMA) */
+
+ #define PCI_CFG_RETRY 10
+
+@@ -370,15 +370,17 @@ osl_dma_consistent_align(void)
+ static struct device *
+ osl_get_dmadev(osl_t *osh)
+ {
+-#ifdef CONFIG_SSB
++#if defined(CONFIG_SSB) || defined(CONFIG_BCMA)
+ if (osh->bustype == SI_BUS) {
+- /* This can be SiliconBackplane emulated as pci with Broadcom or
+- * ssb device. Less harmful is to check for pci_bus_type and if
+- * no match then assume we got ssb */
++ /* This can be SiliconBackplane emulated as pci with Broadcom,
++ * ssb or bcma device. Less harmful is to check for pci_bus_type and if
++ * no match then assume we got either ssb or bcma */
+ if (((struct pci_dev *)osh->pdev)->dev.bus != &pci_bus_type)
+- return ((struct ssb_device *)osh->pdev)->dma_dev;
++ {
++ return wl_glue_get_dmadev(osh->pdev);
++ }
+ }
+-#endif
++#endif /* defined(CONFIG_SSB) || defined(CONFIG_BCMA) */
+ return &((struct pci_dev *)osh->pdev)->dev;
+ }
+
+--- a/driver/Makefile
++++ b/driver/Makefile
+@@ -1,7 +1,7 @@
+ BUILD_TYPE=wl_apsta
+ include $(src)/$(BUILD_TYPE)/buildflags.mk
+
+-EXTRA_CFLAGS += -I$(src)/include -I$(src) -DBCMDRIVER $(WLFLAGS)
++EXTRA_CFLAGS += -I$(src)/include -I$(src) -I$(realpath $(src)/../glue) -DBCMDRIVER $(WLFLAGS)
+
+ wl-objs := $(BUILD_TYPE)/wl_prebuilt.o wl_iw.o wl_linux.o linux_osl.o siutils.o aiutils.o hndpmu.o bcmutils.o sbutils.o nicpci.o hnddma.o bcmsrom.o nvram_stub.o
+
diff --git a/package/broadcom-wl/patches/008-fix_virtual_interfaces.patch b/package/broadcom-wl/patches/008-fix_virtual_interfaces.patch
new file mode 100644
index 000000000..6cffa2781
--- /dev/null
+++ b/package/broadcom-wl/patches/008-fix_virtual_interfaces.patch
@@ -0,0 +1,11 @@
+--- a/driver/wl_linux.c
++++ b/driver/wl_linux.c
+@@ -1541,6 +1541,8 @@ wl_add_if(wl_info_t *wl, struct wlc_if*
+ return NULL;
+ }
+
++ wl_if_setup(wlif->dev);
++
+ sprintf(wlif->dev->name, "%s%d.%d", devname, wl->pub->unit, wlif->subunit);
+ if (remote)
+ bcopy(remote, &wlif->remote, ETHER_ADDR_LEN);
diff --git a/package/broadcom-wl/patches/009-fix_compile_3_2.patch b/package/broadcom-wl/patches/009-fix_compile_3_2.patch
new file mode 100644
index 000000000..628f2fdf2
--- /dev/null
+++ b/package/broadcom-wl/patches/009-fix_compile_3_2.patch
@@ -0,0 +1,27 @@
+--- a/driver/wl_linux.c
++++ b/driver/wl_linux.c
+@@ -462,6 +462,16 @@ wl_schedule_fn(wl_info_t *wl, void (*fn)
+ }
+ #endif /* DSLCPE_DELAY */
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
++#define WL_DEFAULT_OPS \
++ .ndo_open = wl_open, \
++ .ndo_stop = wl_close, \
++ .ndo_start_xmit = wl_start, \
++ .ndo_get_stats = wl_get_stats, \
++ .ndo_set_mac_address = wl_set_mac_address, \
++ .ndo_set_rx_mode = wl_set_multicast_list, \
++ .ndo_do_ioctl = wl_ioctl
++#else
+ #define WL_DEFAULT_OPS \
+ .ndo_open = wl_open, \
+ .ndo_stop = wl_close, \
+@@ -470,6 +480,7 @@ wl_schedule_fn(wl_info_t *wl, void (*fn)
+ .ndo_set_mac_address = wl_set_mac_address, \
+ .ndo_set_multicast_list = wl_set_multicast_list, \
+ .ndo_do_ioctl = wl_ioctl
++#endif
+
+ static const struct net_device_ops wl_ops = {
+ WL_DEFAULT_OPS,
diff --git a/package/broadcom-wl/patches/010-remove_irqf_samble_random.patch b/package/broadcom-wl/patches/010-remove_irqf_samble_random.patch
new file mode 100644
index 000000000..27b132d11
--- /dev/null
+++ b/package/broadcom-wl/patches/010-remove_irqf_samble_random.patch
@@ -0,0 +1,11 @@
+--- a/driver/wl_linux.c 2012-09-26 20:51:48.099454971 -0400
++++ b/driver/wl_linux.c 2012-09-26 20:53:24.115453441 -0400
+@@ -691,7 +691,7 @@
+ if (wl->bustype != JTAG_BUS)
+ #endif /* BCMJTAG */
+ {
+- if (request_irq(irq, wl_isr, IRQF_SHARED|IRQF_SAMPLE_RANDOM, dev->name, wl)) {
++ if (request_irq(irq, wl_isr, IRQF_SHARED, dev->name, wl)) {
+ WL_ERROR(("wl%d: request_irq() failed\n", unit));
+ goto fail;
+ }
diff --git a/package/broadcom-wl/patches/910-fallback-sprom.patch b/package/broadcom-wl/patches/910-fallback-sprom.patch
new file mode 100644
index 000000000..749ecbf31
--- /dev/null
+++ b/package/broadcom-wl/patches/910-fallback-sprom.patch
@@ -0,0 +1,84 @@
+--- a/driver/bcmsrom.c
++++ b/driver/bcmsrom.c
+@@ -39,6 +39,11 @@
+ #include <sbsdpcmdev.h>
+ #endif
+
++#if defined(CONFIG_SSB_PCIHOST) && defined(CONFIG_BOARD_BCM963XX)
++#include <linux/ssb/ssb.h>
++extern struct ssb_sprom bcm63xx_sprom;
++#endif
++
+ #ifdef WLTEST
+ #include <sbsprom.h>
+ #endif /* WLTEST */
+@@ -2058,6 +2063,10 @@ BCMATTACHFN(initvars_srom_pci)(si_t *sih
+ bool flash = FALSE;
+ int err = 0;
+
++#if defined(CONFIG_SSB_PCIHOST) && defined(CONFIG_BOARD_BCM963XX)
++ char eabuf[18];
++#endif
++
+ /*
+ * Apply CRC over SROM content regardless SROM is present or not,
+ * and use variable <devpath>sromrev's existance in flash to decide
+@@ -2120,6 +2129,58 @@ BCMATTACHFN(initvars_srom_pci)(si_t *sih
+ goto varscont;
+ }
+
++#if defined(CONFIG_SSB_PCIHOST) && defined(CONFIG_BOARD_BCM963XX)
++ base = vp = MALLOC(osh, MAXSZ_NVRAM_VARS);
++
++ if( base != NULL )
++ {
++ varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
++
++ printk("Got version %i SPROM from SSB\n", bcm63xx_sprom.revision);
++
++ varbuf_append(&b, vstr_sromrev, bcm63xx_sprom.revision);
++ varbuf_append(&b, vstr_boardrev, bcm63xx_sprom.board_rev);
++
++ /* ToDo: map bcm63xx_sprom.country_code */
++ varbuf_append(&b, vstr_noccode);
++
++ varbuf_append(&b, vstr_aa2g, bcm63xx_sprom.ant_available_bg);
++
++ varbuf_append(&b, vstr_pa0b[0], bcm63xx_sprom.pa0b0);
++ varbuf_append(&b, vstr_pa1b[0], bcm63xx_sprom.pa1b0);
++ varbuf_append(&b, vstr_pa0b[1], bcm63xx_sprom.pa0b1);
++ varbuf_append(&b, vstr_pa1b[1], bcm63xx_sprom.pa1b1);
++ varbuf_append(&b, vstr_pa0b[2], bcm63xx_sprom.pa0b2);
++ varbuf_append(&b, vstr_pa1b[2], bcm63xx_sprom.pa1b2);
++
++ varbuf_append(&b, vstr_pa0maxpwr, bcm63xx_sprom.maxpwr_bg);
++ varbuf_append(&b, vstr_pa0itssit, bcm63xx_sprom.itssi_bg);
++
++ varbuf_append(&b, vstr_boardflags, (bcm63xx_sprom.boardflags_hi << 16) | bcm63xx_sprom.boardflags_lo);
++ varbuf_append(&b, vstr_boardflags2, (bcm63xx_sprom.boardflags2_hi << 16) | bcm63xx_sprom.boardflags2_lo);
++
++ snprintf(eabuf, sizeof(eabuf), "%02x:%02x:%02x:%02x:%02x:%02x",
++ bcm63xx_sprom.il0mac[0], bcm63xx_sprom.il0mac[1], bcm63xx_sprom.il0mac[2],
++ bcm63xx_sprom.il0mac[3], bcm63xx_sprom.il0mac[4], bcm63xx_sprom.il0mac[5]
++ );
++
++ varbuf_append(&b, vstr_macaddr, eabuf);
++
++ /* final nullbyte terminator */
++ ASSERT(b.size >= 1);
++ vp = b.buf;
++ *vp++ = '\0';
++
++ ASSERT((vp - base) <= MAXSZ_NVRAM_VARS);
++ goto varsdone;
++ }
++ else
++ {
++ err = -2;
++ goto errout;
++ }
++#endif
++
+ BS_ERROR(("SROM CRC Error\n"));
+
+ #if defined(WLTEST)
diff --git a/package/broadcom-wl/patches/912-pci-bus-nvram-hack.patch b/package/broadcom-wl/patches/912-pci-bus-nvram-hack.patch
new file mode 100644
index 000000000..65e8bd395
--- /dev/null
+++ b/package/broadcom-wl/patches/912-pci-bus-nvram-hack.patch
@@ -0,0 +1,11 @@
+--- a/driver/siutils.c
++++ b/driver/siutils.c
+@@ -1859,7 +1859,7 @@ BCMINITFN(si_devpath)(si_t *sih, char *p
+ case PCI_BUS:
+ ASSERT((SI_INFO(sih))->osh != NULL);
+ slen = snprintf(path, (size_t)size, "pci/%u/%u/",
+- OSL_PCI_BUS((SI_INFO(sih))->osh),
++ OSL_PCI_BUS((SI_INFO(sih))->osh) + 1,
+ OSL_PCI_SLOT((SI_INFO(sih))->osh));
+ break;
+ case PCMCIA_BUS:
diff --git a/package/broadcom-wl/src/glue/Makefile b/package/broadcom-wl/src/glue/Makefile
new file mode 100644
index 000000000..81f0c8acf
--- /dev/null
+++ b/package/broadcom-wl/src/glue/Makefile
@@ -0,0 +1,17 @@
+#
+# Makefile for wl_glue driver
+#
+# Copyright (C) 2011 Jo-Philipp Wich <jow@openwrt.org>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+
+obj-m := wl_glue.o
+
+ifeq ($(MAKING_MODULES),1)
+-include $(TOPDIR)/Rules.make
+endif
+
diff --git a/package/broadcom-wl/src/glue/wl_glue.c b/package/broadcom-wl/src/glue/wl_glue.c
new file mode 100644
index 000000000..0504232a9
--- /dev/null
+++ b/package/broadcom-wl/src/glue/wl_glue.c
@@ -0,0 +1,317 @@
+/*
+ * wl_glue.c: Broadcom WL support module providing a unified SSB/BCMA handling.
+ * Copyright (C) 2011 Jo-Philipp Wich <jow@openwrt.org>
+ */
+
+#include "wl_glue.h"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#ifdef CONFIG_BCM47XX
+#include <bcm47xx.h>
+#endif
+
+#ifdef CONFIG_SSB
+#include <linux/ssb/ssb.h>
+#endif
+
+#ifdef CONFIG_BCMA
+#include <linux/bcma/bcma.h>
+#endif
+
+MODULE_AUTHOR("Jo-Philipp Wich (jow@openwrt.org)");
+MODULE_DESCRIPTION("Broadcom WL SSB/BCMA compatibility layer");
+MODULE_LICENSE("GPL");
+
+static wl_glue_attach_cb_t attach_cb = NULL;
+static wl_glue_remove_cb_t remove_cb = NULL;
+static enum wl_glue_bus_type active_bus_type = WL_GLUE_BUS_TYPE_UNSPEC;
+static int wl_glue_attached = 0;
+
+
+#ifdef CONFIG_SSB
+static int wl_glue_ssb_probe(struct ssb_device *dev, const struct ssb_device_id *id)
+{
+ void *mmio;
+ void *wldev;
+
+ if (!attach_cb)
+ {
+ pr_err("No attach callback registered\n");
+ return -ENOSYS;
+ }
+
+ if (dev->bus->bustype != SSB_BUSTYPE_SSB)
+ {
+ pr_err("Attaching to SSB behind PCI is not supported. Please remove the b43 ssb bridge\n");
+ return -EINVAL;
+ }
+
+ mmio = (void *) 0x18000000 + dev->core_index * 0x1000;
+ wldev = attach_cb(id->vendor, id->coreid, (ulong)mmio, dev, dev->irq);
+
+ if (!wldev)
+ {
+ pr_err("The attach callback failed, SSB probe aborted\n");
+ return -ENODEV;
+ }
+
+ ssb_set_drvdata(dev, wldev);
+ return 0;
+}
+
+static void wl_glue_ssb_remove(struct ssb_device *dev)
+{
+ void *wldev = ssb_get_drvdata(dev);
+
+ if (remove_cb)
+ remove_cb(wldev);
+
+ ssb_set_drvdata(dev, NULL);
+}
+
+static const struct ssb_device_id wl_glue_ssb_tbl[] = {
+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, SSB_ANY_REV),
+ SSB_DEVTABLE_END
+};
+
+static struct ssb_driver wl_glue_ssb_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = wl_glue_ssb_tbl,
+ .probe = wl_glue_ssb_probe,
+ .remove = wl_glue_ssb_remove,
+};
+#endif /* CONFIG_SSB */
+
+#ifdef CONFIG_BCMA
+static int wl_glue_bcma_probe(struct bcma_device *dev)
+{
+ void *mmio;
+ void *wldev;
+
+ if (!attach_cb)
+ {
+ pr_err("No attach callback registered\n");
+ return -ENOSYS;
+ }
+
+ if (dev->bus->hosttype != BCMA_HOSTTYPE_SOC)
+ {
+ pr_err("Unsupported BCMA bus type %d\n", dev->bus->hosttype);
+ return -EINVAL;
+ }
+
+ /*
+ * NB:
+ * 0x18000000 = BCMA_ADDR_BASE
+ * 0x1000 = BCMA_CORE_SIZE
+ */
+
+ mmio = (void *) 0x18000000 + dev->core_index * 0x1000;
+ wldev = attach_cb(dev->id.manuf, dev->id.id, (ulong)mmio, dev, dev->irq);
+
+ if (!wldev)
+ {
+ pr_err("The attach callback failed, BCMA probe aborted\n");
+ return -ENODEV;
+ }
+
+ bcma_set_drvdata(dev, wldev);
+ return 0;
+}
+
+static void wl_glue_bcma_remove(struct bcma_device *dev)
+{
+ void *wldev = bcma_get_drvdata(dev);
+
+ if (remove_cb)
+ remove_cb(wldev);
+
+ bcma_set_drvdata(dev, NULL);
+}
+
+static const struct bcma_device_id wl_glue_bcma_tbl[] = {
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, BCMA_ANY_REV, BCMA_ANY_CLASS),
+ BCMA_CORETABLE_END
+};
+
+static struct bcma_driver wl_glue_bcma_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = wl_glue_bcma_tbl,
+ .probe = wl_glue_bcma_probe,
+ .remove = wl_glue_bcma_remove,
+};
+#endif /* CONFIG_BCMA */
+
+
+void wl_glue_set_attach_callback(wl_glue_attach_cb_t cb)
+{
+ attach_cb = cb;
+}
+EXPORT_SYMBOL(wl_glue_set_attach_callback);
+
+void wl_glue_set_remove_callback(wl_glue_remove_cb_t cb)
+{
+ remove_cb = cb;
+}
+EXPORT_SYMBOL(wl_glue_set_remove_callback);
+
+int wl_glue_register(void)
+{
+ int err;
+
+ switch(active_bus_type)
+ {
+#ifdef CONFIG_SSB
+ case WL_GLUE_BUS_TYPE_SSB:
+ err = ssb_driver_register(&wl_glue_ssb_driver);
+ break;
+#endif /* CONFIG_SSB */
+
+#ifdef CONFIG_BCMA
+ case WL_GLUE_BUS_TYPE_BCMA:
+ err = bcma_driver_register(&wl_glue_bcma_driver);
+ break;
+#endif /* CONFIG_BCMA */
+
+ default:
+ pr_err("Not attaching through glue driver due to unsupported bus\n");
+ err = -ENOSYS;
+ break;
+ }
+
+ if (!err)
+ {
+ pr_info("SSB/BCMA glue driver successfully attached\n");
+ wl_glue_attached = 1;
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(wl_glue_register);
+
+int wl_glue_unregister(void)
+{
+ int err;
+
+ if (!wl_glue_attached)
+ return -ENOSYS;
+
+ switch (active_bus_type)
+ {
+#ifdef CONFIG_SSB
+ case WL_GLUE_BUS_TYPE_SSB:
+ ssb_driver_unregister(&wl_glue_ssb_driver);
+ err = 0;
+ break;
+#endif /* CONFIG_SSB */
+
+#ifdef CONFIG_BCMA
+ case WL_GLUE_BUS_TYPE_BCMA:
+ bcma_driver_unregister(&wl_glue_bcma_driver);
+ err = 0;
+ break;
+#endif /* CONFIG_BCMA */
+
+ default:
+ pr_err("Not removing glue driver due to unsupported bus\n");
+ err = -ENOSYS;
+ break;
+ }
+
+ if (!err)
+ {
+ pr_info("SSB/BCMA glue driver successfully detached\n");
+ wl_glue_attached = 0;
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(wl_glue_unregister);
+
+struct device * wl_glue_get_dmadev(void *dev)
+{
+ struct device *dma_dev;
+
+ switch (active_bus_type)
+ {
+#ifdef CONFIG_SSB
+ case WL_GLUE_BUS_TYPE_SSB:
+ dma_dev = ((struct ssb_device *)dev)->dma_dev;
+ break;
+#endif /* CONFIG_SSB */
+
+#ifdef CONFIG_BCMA
+ case WL_GLUE_BUS_TYPE_BCMA:
+ dma_dev = ((struct bcma_device *)dev)->dma_dev;
+ break;
+#endif /* CONFIG_BCMA */
+
+ default:
+ BUG();
+ dma_dev = NULL;
+ break;
+ }
+
+ return dma_dev;
+}
+EXPORT_SYMBOL(wl_glue_get_dmadev);
+
+
+static int __init wl_glue_init(void)
+{
+#ifdef CONFIG_BCM47XX
+ /*
+ * BCM47xx currently supports either SSB or BCMA bus,
+ * determine the used one from the info set by the
+ * platform setup code.
+ */
+ switch (bcm47xx_bus_type)
+ {
+#ifdef CONFIG_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ active_bus_type = WL_GLUE_BUS_TYPE_SSB;
+ break;
+#endif /* CONFIG_SSB */
+
+#ifdef CONFIG_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ active_bus_type = WL_GLUE_BUS_TYPE_BCMA;
+ break;
+#endif /* CONFIG_BCMA */
+ }
+#endif /* CONFIG_BCM47XX */
+
+#ifdef CONFIG_BCM63XX
+#ifdef CONFIG_SSB
+ /*
+ * BCM63xx currently only uses SSB, so assume that.
+ */
+ active_bus_type = WL_GLUE_BUS_TYPE_SSB;
+#endif /* CONFIG_SSB */
+#endif /* CONFIG_BCM63XX */
+
+ /* do not fail here, let wl_glue_register() return -ENOSYS later */
+ if (active_bus_type == WL_GLUE_BUS_TYPE_UNSPEC)
+ pr_err("Unable to determine used system bus type\n");
+
+ return 0;
+}
+
+static void __exit wl_glue_exit(void)
+{
+ if (wl_glue_attached)
+ {
+ if (wl_glue_unregister())
+ pr_err("Failed to unregister glue driver\n");
+
+ wl_glue_attached = 0;
+ }
+
+ return;
+}
+
+module_init(wl_glue_init);
+module_exit(wl_glue_exit);
diff --git a/package/broadcom-wl/src/glue/wl_glue.h b/package/broadcom-wl/src/glue/wl_glue.h
new file mode 100644
index 000000000..b3c8aa3b6
--- /dev/null
+++ b/package/broadcom-wl/src/glue/wl_glue.h
@@ -0,0 +1,22 @@
+/*
+ * wl_glue.h: Broadcom WL support module providing a unified SSB/BCMA handling.
+ * Copyright (C) 2011 Jo-Philipp Wich <jow@openwrt.org>
+ */
+
+#include <linux/types.h>
+
+typedef void * (*wl_glue_attach_cb_t)(u16, u16, ulong, void *, u32);
+typedef void (*wl_glue_remove_cb_t)(void *);
+
+enum wl_glue_bus_type {
+ WL_GLUE_BUS_TYPE_UNSPEC,
+ WL_GLUE_BUS_TYPE_SSB,
+ WL_GLUE_BUS_TYPE_BCMA
+};
+
+extern void wl_glue_set_attach_callback(wl_glue_attach_cb_t cb);
+extern void wl_glue_set_remove_callback(wl_glue_remove_cb_t cb);
+extern int wl_glue_register(void);
+extern int wl_glue_unregister(void);
+extern struct device * wl_glue_get_dmadev(void *);
+
diff --git a/package/broadcom-wl/src/wlc.c b/package/broadcom-wl/src/wlc.c
new file mode 100644
index 000000000..253809c9a
--- /dev/null
+++ b/package/broadcom-wl/src/wlc.c
@@ -0,0 +1,1086 @@
+/*
+ * wlc - Broadcom Wireless Driver Control Utility
+ *
+ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <glob.h>
+#include <ctype.h>
+
+#include <typedefs.h>
+#include <wlutils.h>
+#include <proto/802.11.h>
+
+#define VERSION "0.1"
+#define BUFSIZE 8192
+#define PTABLE_MAGIC 0xbadc0ded
+#define PTABLE_SLT1 1
+#define PTABLE_SLT2 2
+#define PTABLE_ACKW 3
+#define PTABLE_ADHM 4
+#define PTABLE_END 0xffffffff
+
+/*
+ * Copy each token in wordlist delimited by space into word
+ * Taken from Broadcom shutils.h
+ */
+#define foreach(word, wordlist, next) \
+ for (next = &wordlist[strspn(wordlist, " ")], \
+ strncpy(word, next, sizeof(word)), \
+ word[strcspn(word, " ")] = '\0', \
+ word[sizeof(word) - 1] = '\0', \
+ next = strchr(next, ' '); \
+ strlen(word); \
+ next = next ? &next[strspn(next, " ")] : "", \
+ strncpy(word, next, sizeof(word)), \
+ word[strcspn(word, " ")] = '\0', \
+ word[sizeof(word) - 1] = '\0', \
+ next = strchr(next, ' '))
+
+static char wlbuf[8192];
+static char interface[16] = "wl0";
+static unsigned long kmem_offset = 0;
+static int vif = 0, debug = 1, fromstdin = 0;
+
+typedef enum {
+ NONE = 0x00,
+
+ /* types */
+ PARAM_TYPE = 0x00f,
+ INT = 0x001,
+ STRING = 0x002,
+ MAC = 0x003,
+
+ /* options */
+ PARAM_OPTIONS = 0x0f0,
+ NOARG = 0x010,
+
+ /* modes */
+ PARAM_MODE = 0xf00,
+ GET = 0x100,
+ SET = 0x200,
+} wlc_param;
+
+struct wlc_call {
+ const char *name;
+ wlc_param param;
+ int (*handler)(wlc_param param, void *data, void *value);
+ union {
+ int num;
+ char *str;
+ void *ptr;
+ } data;
+ const char *desc;
+};
+
+/* can't use the system include because of the stupid broadcom header files */
+extern struct ether_addr *ether_aton(const char *asc);
+static inline int my_ether_ntoa(unsigned char *ea, char *buf)
+{
+ return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
+ ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]);
+}
+
+static int wlc_ioctl(wlc_param param, void *data, void *value)
+{
+ unsigned int *var = ((unsigned int *) data);
+ unsigned int ioc = *var;
+
+ if (param & NOARG) {
+ return wl_ioctl(interface, ioc, NULL, 0);
+ }
+ switch(param & PARAM_TYPE) {
+ case MAC:
+ return wl_ioctl(interface, ((param & SET) ? (ioc) : (ioc >> 16)) & 0xffff, value, 6);
+ case INT:
+ return wl_ioctl(interface, ((param & SET) ? (ioc) : (ioc >> 16)) & 0xffff, value, sizeof(int));
+ case STRING:
+ return wl_ioctl(interface, ((param & SET) ? (ioc) : (ioc >> 16)) & 0xffff, value, BUFSIZE);
+ }
+ return 0;
+}
+
+static int wlc_iovar(wlc_param param, void *data, void *value)
+{
+ int *val = (int *) value;
+ char *iov = *((char **) data);
+ int ret = 0;
+
+ if (param & SET) {
+ switch(param & PARAM_TYPE) {
+ case INT:
+ ret = wl_iovar_setint(interface, iov, *val);
+ break;
+ case MAC:
+ ret = wl_iovar_set(interface, iov, value, 6);
+ break;
+ }
+ }
+ if (param & GET) {
+ switch(param & PARAM_TYPE) {
+ case INT:
+ ret = wl_iovar_get(interface, iov, val, sizeof(int));
+ break;
+ case MAC:
+ ret = wl_iovar_get(interface, iov, value, 6);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int wlc_bssiovar(wlc_param param, void *data, void *value)
+{
+ int *val = (int *) value;
+ char *iov = *((char **) data);
+ int ret = 0;
+
+ if (param & SET) {
+ switch(param & PARAM_TYPE) {
+ case INT:
+ ret = wl_bssiovar_setint(interface, iov, vif, *val);
+ }
+ }
+ if (param & GET) {
+ switch(param & PARAM_TYPE) {
+ case INT:
+ ret = wl_bssiovar_get(interface, iov, vif, val, sizeof(int));
+ }
+ }
+
+ return ret;
+}
+
+static int wlc_vif_enabled(wlc_param param, void *data, void *value)
+{
+ int *val = (int *) value;
+ int buf[3];
+ int ret = 0;
+
+ sprintf((char *) buf, "bss");
+ buf[1] = vif;
+ if (param & SET) {
+ buf[2] = (*val ? 1 : 0);
+ ret = wl_ioctl(interface, WLC_SET_VAR, buf, sizeof(buf));
+ } else if (param & GET) {
+ ret = wl_ioctl(interface, WLC_GET_VAR, buf, sizeof(buf));
+ *val = buf[0];
+ }
+
+ return ret;
+}
+
+static int wlc_ssid(wlc_param param, void *data, void *value)
+{
+ int ret = -1, ret2 = -1;
+ char *dest = (char *) value;
+ wlc_ssid_t ssid;
+
+ if ((param & PARAM_MODE) == GET) {
+ ret = wl_bssiovar_get(interface, "ssid", vif, &ssid, sizeof(ssid));
+
+ if (ret)
+ /* if we can't get the ssid through the bssiovar, try WLC_GET_SSID */
+ ret = wl_ioctl(interface, WLC_GET_SSID, &ssid, sizeof(ssid));
+
+ if (!ret) {
+ memcpy(dest, ssid.SSID, ssid.SSID_len);
+ dest[ssid.SSID_len] = 0;
+ }
+ } else if ((param & PARAM_MODE) == SET) {
+ strncpy(ssid.SSID, value, 32);
+ ssid.SSID_len = strlen(value);
+
+ if (ssid.SSID_len > 32)
+ ssid.SSID_len = 32;
+
+ if (vif == 0) {
+ /* for the main interface, also try the WLC_SET_SSID call */
+ ret2 = wl_ioctl(interface, WLC_SET_SSID, &ssid, sizeof(ssid));
+ }
+
+ ret = wl_bssiovar_set(interface, "ssid", vif, &ssid, sizeof(ssid));
+ ret = (!ret2 ? 0 : ret);
+ }
+
+ return ret;
+}
+
+static int wlc_int(wlc_param param, void *data, void *value)
+{
+ int *var = *((int **) data);
+ int *val = (int *) value;
+
+ if ((param & PARAM_MODE) == SET) {
+ *var = *val;
+ } else if ((param & PARAM_MODE) == GET) {
+ *val = *var;
+ }
+
+ return 0;
+}
+
+static int wlc_flag(wlc_param param, void *data, void *value)
+{
+ int *var = *((int **) data);
+
+ *var = 1;
+
+ return 0;
+}
+
+static int wlc_string(wlc_param param, void *data, void *value)
+{
+ char *var = *((char **) data);
+
+ if ((param & PARAM_MODE) == GET) {
+ strcpy(value, var);
+ }
+
+ return 0;
+}
+
+static int wlc_afterburner(wlc_param param, void *data, void *value)
+{
+ int *val = (int *) value;
+ int ret = 0;
+
+ if ((param & PARAM_MODE) == GET) {
+ ret = wl_iovar_get(interface, "afterburner", val, sizeof(int));
+ } else {
+ wl_iovar_setint(interface, "wlfeatureflag", (*val ? 3 : 0));
+ ret = wl_iovar_setint(interface, "afterburner", (*val ? 1 : 0));
+ wl_iovar_setint(interface, "afterburner_override", *val);
+ }
+
+ return ret;
+}
+
+static int wlc_maclist(wlc_param param, void *data, void *value)
+{
+ unsigned int *var = ((unsigned int *) data);
+ unsigned int ioc = *var;
+ int limit = (sizeof(wlbuf) - 4) / sizeof(struct ether_addr);
+ struct maclist *list = (struct maclist *) wlbuf;
+ char *str = (char *) value;
+ char astr[30], *p;
+ struct ether_addr *addr;
+ int isset = 0;
+ int ret;
+
+ if ((param & PARAM_MODE) == GET) {
+ list->count = limit;
+ ret = wl_ioctl(interface, (ioc >> 16) & 0xffff, wlbuf, sizeof(wlbuf));
+
+ if (!ret)
+ while (list->count) {
+ str += sprintf(str, "%s", ((((char *) value) == str) ? "" : " "));
+ str += my_ether_ntoa((unsigned char *) &list->ea[list->count-- - 1], str);
+ }
+
+ return ret;
+ } else {
+ while (*str && isspace(*str))
+ *str++;
+
+ if (*str == '+') {
+ str++;
+
+ list->count = limit;
+ if (wl_ioctl(interface, (ioc >> 16) & 0xffff, wlbuf, sizeof(wlbuf)) == 0)
+ isset = 1;
+
+ while (*str && isspace(*str))
+ str++;
+ }
+
+ if (!isset)
+ memset(wlbuf, 0, sizeof(wlbuf));
+
+ foreach(astr, str, p) {
+ if (list->count >= limit)
+ break;
+
+ if ((addr = ether_aton(astr)) != NULL)
+ memcpy(&list->ea[list->count++], addr, sizeof(struct ether_addr));
+ }
+
+ return wl_ioctl(interface, ioc & 0xffff, wlbuf, sizeof(wlbuf));
+ }
+}
+
+static int wlc_radio(wlc_param param, void *data, void *value)
+{
+ int *val = (int *) value;
+ int ret;
+
+ if ((param & PARAM_MODE) == GET) {
+ ret = wl_ioctl(interface, WLC_GET_RADIO, val, sizeof(int));
+ *val = ((*val & 1) ? 0 : 1);
+ } else {
+ *val = (1 << 16) | (*val ? 0 : 1);
+ ret = wl_ioctl(interface, WLC_SET_RADIO, val, sizeof(int));
+ }
+
+ return ret;
+}
+
+static int wlc_wsec_key(wlc_param param, void *null, void *value)
+{
+ wl_wsec_key_t wsec_key;
+ unsigned char *index = value;
+ unsigned char *key;
+ unsigned char *data;
+ unsigned char hex[3];
+
+ if ((param & PARAM_MODE) != SET)
+ return 0;
+
+ memset(&wsec_key, 0, sizeof(wsec_key));
+ if (index[0] == '=') {
+ wsec_key.flags = WL_PRIMARY_KEY;
+ index++;
+ }
+
+ if ((index[0] < '1') || (index[0] > '4') || (index[1] != ','))
+ return -1;
+
+ key = index + 2;
+ if (strncmp(key, "d:", 2) == 0) { /* delete key */
+ } else if (strncmp(key, "s:", 2) == 0) { /* ascii key */
+ key += 2;
+ wsec_key.len = strlen(key);
+
+ if ((wsec_key.len != 5) && (wsec_key.len != 13))
+ return -1;
+
+ strcpy(wsec_key.data, key);
+ } else { /* hex key */
+ wsec_key.len = strlen(key);
+ if ((wsec_key.len != 10) && (wsec_key.len != 26))
+ return -1;
+
+ wsec_key.len /= 2;
+ data = wsec_key.data;
+ hex[2] = 0;
+ do {
+ hex[0] = *(key++);
+ hex[1] = *(key++);
+ *(data++) = (unsigned char) strtoul(hex, NULL, 16);
+ } while (*key != 0);
+ }
+
+ return wl_bssiovar_set(interface, "wsec_key", vif, &wsec_key, sizeof(wsec_key));
+}
+
+static inline int cw2ecw(int cw)
+{
+ int i;
+ for (cw++, i = 0; cw; i++) cw >>=1;
+ return i - 1;
+}
+
+static int wlc_wme_ac(wlc_param param, void *data, void *value)
+{
+ char *type = *((char **) data);
+ char *settings = (char *) value;
+ char cmd[100], *p, *val;
+ edcf_acparam_t params[AC_COUNT];
+ int ret;
+ int intval;
+ int cur = -1;
+ char *buf = wlbuf;
+
+ if ((param & PARAM_MODE) != SET)
+ return -1;
+
+ memset(params, 0, sizeof(params));
+ ret = wl_iovar_get(interface, type, params, sizeof(params));
+ memset(buf, 0, BUFSIZE);
+ strcpy(buf, type);
+ buf += strlen(buf) + 1;
+
+ foreach(cmd, settings, p) {
+ val = strchr(cmd, '=');
+ if (val == NULL) {
+ if (strcmp(cmd, "be") == 0)
+ cur = AC_BE;
+ else if (strcmp(cmd, "bk") == 0)
+ cur = AC_BK;
+ else if (strcmp(cmd, "vi") == 0)
+ cur = AC_VI;
+ else if (strcmp(cmd, "vo") == 0)
+ cur = AC_VO;
+ else
+ return -1;
+
+ /* just in case */
+ params[cur].ACI = (params[cur].ACI & (0x3 << 5)) | (cur << 5);
+ } else {
+ *(val++) = 0;
+
+ intval = strtoul(val, NULL, 10);
+ if (strcmp(cmd, "cwmin") == 0)
+ params[cur].ECW = (params[cur].ECW & ~(0xf)) | cw2ecw(intval);
+ else if (strcmp(cmd, "ecwmin") == 0)
+ params[cur].ECW = (params[cur].ECW & ~(0xf)) | (intval & 0xf);
+ else if (strcmp(cmd, "cwmax") == 0)
+ params[cur].ECW = (params[cur].ECW & ~(0xf << 4)) | (cw2ecw(intval) << 4);
+ else if (strcmp(cmd, "ecwmax") == 0)
+ params[cur].ECW = (params[cur].ECW & ~(0xf << 4)) | ((intval & 0xf) << 4);
+ else if (strcmp(cmd, "aifsn") == 0)
+ params[cur].ACI = (params[cur].ACI & ~(0xf)) | (intval & 0xf);
+ else if (strcmp(cmd, "txop") == 0)
+ params[cur].TXOP = intval >> 5;
+ else if (strcmp(cmd, "force") == 0)
+ params[cur].ACI = (params[cur].ACI & ~(1 << 4)) | ((intval) ? (1 << 4) : 0);
+ else return -1;
+
+ memcpy(buf, &params[cur], sizeof(edcf_acparam_t));
+ wl_ioctl(interface, WLC_SET_VAR, wlbuf, BUFSIZE);
+ }
+ }
+ return ret;
+}
+
+static int wlc_ifname(wlc_param param, void *data, void *value)
+{
+ char *val = (char *) value;
+ int ret = 0;
+
+ if (param & SET) {
+ if (strlen(val) < 16)
+ strcpy(interface, val);
+ else ret = -1;
+ }
+ if (param & GET) {
+ strcpy(val, interface);
+ }
+
+ return ret;
+}
+
+static int wlc_wdsmac(wlc_param param, void *data, void *value)
+{
+ unsigned char mac[6];
+ int ret = 0;
+
+ ret = wl_ioctl(interface, WLC_WDS_GET_REMOTE_HWADDR, &mac, 6);
+ if (ret == 0)
+ my_ether_ntoa(mac, value);
+
+ return ret;
+}
+
+static int wlc_pmk(wlc_param param, void *data, void *value)
+{
+ int ret = -1;
+ char *str = (char *) value;
+ wsec_pmk_t pmk;
+
+ /* driver doesn't support GET */
+
+ if ((param & PARAM_MODE) == SET) {
+ strncpy(pmk.key, value, WSEC_MAX_PSK_LEN);
+ pmk.key_len = strlen(value);
+
+ if (pmk.key_len > WSEC_MAX_PSK_LEN)
+ pmk.key_len = WSEC_MAX_PSK_LEN;
+
+ pmk.flags = WSEC_PASSPHRASE;
+
+ ret = wl_ioctl(interface, WLC_SET_WSEC_PMK, &pmk, sizeof(pmk));
+ }
+
+ return ret;
+}
+
+static const struct wlc_call wlc_calls[] = {
+ {
+ .name = "version",
+ .param = STRING|NOARG,
+ .handler = wlc_string,
+ .data.str = VERSION,
+ .desc = "Version of this program"
+ },
+ {
+ .name = "debug",
+ .param = INT,
+ .handler = wlc_int,
+ .data.ptr = &debug,
+ .desc = "wlc debug level"
+ },
+ {
+ .name = "stdin",
+ .param = NOARG,
+ .handler = wlc_flag,
+ .data.ptr = &fromstdin,
+ .desc = "Accept input from stdin"
+ },
+ {
+ .name = "ifname",
+ .param = STRING,
+ .handler = wlc_ifname,
+ .desc = "interface to send commands to"
+ },
+ {
+ .name = "up",
+ .param = NOARG,
+ .handler = wlc_ioctl,
+ .data.num = WLC_UP,
+ .desc = "Bring the interface up"
+ },
+ {
+ .name = "down",
+ .param = NOARG,
+ .handler = wlc_ioctl,
+ .data.num = WLC_DOWN,
+ .desc = "Bring the interface down"
+ },
+ {
+ .name = "radio",
+ .param = INT,
+ .handler = wlc_radio,
+ .desc = "Radio enabled flag"
+ },
+ {
+ .name = "ap",
+ .param = INT,
+ .handler = wlc_ioctl,
+ .data.num = ((WLC_GET_AP << 16) | WLC_SET_AP),
+ .desc = "Access Point mode"
+ },
+ {
+ .name = "mssid",
+ .param = INT,
+ .handler = wlc_iovar,
+ .data.str = "mbss",
+ .desc = "Multi-ssid mode"
+ },
+ {
+ .name = "apsta",
+ .param = INT,
+ .handler = wlc_iovar,
+ .data.str = "apsta",
+ .desc = "AP+STA mode"
+ },
+ {
+ .name = "infra",
+ .param = INT,
+ .handler = wlc_ioctl,
+ .data.num = ((WLC_GET_INFRA << 16) | WLC_SET_INFRA),
+ .desc = "Infrastructure mode"
+ },
+ {
+ .name = "wet",
+ .param = INT,
+ .handler = wlc_ioctl,
+ .data.num = ((WLC_GET_WET << 16) | WLC_SET_WET),
+ .desc = "Wireless repeater mode",
+ },
+ {
+ .name = "statimeout",
+ .param = INT,
+ .handler = wlc_iovar,
+ .data.str = "sta_retry_time",
+ .desc = "STA connection timeout"
+ },
+ {
+ .name = "country",
+ .param = STRING,
+ .handler = wlc_ioctl,
+ .data.num = ((WLC_GET_COUNTRY << 16) | WLC_SET_COUNTRY),
+ .desc = "Country code"
+ },
+ {
+ .name = "channel",
+ .param = INT,
+ .handler = wlc_ioctl,
+ .data.num = ((WLC_GET_CHANNEL << 16) | WLC_SET_CHANNEL),
+ .desc = "Channel",
+ },
+ {
+ .name = "vlan_mode",
+ .param = INT,
+ .handler = wlc_bssiovar,
+ .data.str = "vlan_mode",
+ .desc = "Parse 802.1Q tags",
+ },
+ {
+ .name = "vif",
+ .param = INT,
+ .handler = wlc_int,
+ .data.ptr = &vif,
+ .desc = "Current vif index"
+ },
+ {
+ .name = "enabled",
+ .param = INT,
+ .handler = wlc_vif_enabled,
+ .desc = "vif enabled flag"
+ },
+ {
+ .name = "ssid",
+ .param = STRING,
+ .handler = wlc_ssid,
+ .desc = "Interface ESSID"
+ },
+ {
+ .name = "closed",
+ .param = INT,
+ .handler = wlc_bssiovar,
+ .data.str = "closednet",
+ .desc = "Hidden ESSID flag"
+ },
+ {
+ .name = "wsec",
+ .param = INT,
+ .handler = wlc_bssiovar,
+ .data.str = "wsec",
+ .desc = "Security mode flags"
+ },
+ {
+ .name = "wepkey",
+ .param = STRING,
+ .handler = wlc_wsec_key,
+ .desc = "Set/Remove WEP keys"
+ },
+ {
+ .name = "wepauth",
+ .param = INT,
+ .handler = wlc_ioctl,
+ .data.num = ((WLC_GET_AUTH << 16) | WLC_SET_AUTH),
+ .desc = "WEP authentication type. 0 = OpenSystem, 1 = SharedKey"
+ },
+ {
+ .name = "wsec_restrict",
+ .param = INT,
+ .handler = wlc_bssiovar,
+ .data.str = "wsec_restrict",
+ .desc = "Drop unencrypted traffic"
+ },
+ {
+ .name = "eap_restrict",
+ .param = INT,
+ .handler = wlc_bssiovar,
+ .data.str = "eap_restrict",
+ .desc = "Only allow 802.1X traffic until 802.1X authorized"
+ },
+ {
+ .name = "wpa_auth",
+ .param = INT,
+ .handler = wlc_bssiovar,
+ .data.str = "wpa_auth",
+ .desc = "WPA authentication modes"
+ },
+ {
+ .name = "ap_isolate",
+ .param = INT,
+ .handler = wlc_bssiovar,
+ .data.str = "ap_isolate",
+ .desc = "Isolate connected clients"
+ },
+ {
+ .name = "supplicant",
+ .param = INT,
+ .handler = wlc_iovar,
+ .data.str = "sup_wpa",
+ .desc = "Built-in WPA supplicant"
+ },
+ {
+ .name = "passphrase",
+ .param = STRING,
+ .handler = wlc_pmk,
+ .desc = "Passphrase for built-in WPA supplicant",
+ },
+ {
+ .name = "maxassoc",
+ .param = INT,
+ .handler = wlc_iovar,
+ .data.str = "maxassoc",
+ .desc = "Max. number of associated clients",
+ },
+ {
+ .name = "wme",
+ .param = INT,
+ .handler = wlc_iovar,
+ .data.str = "wme",
+ .desc = "WME enabled"
+ },
+ {
+ .name = "wme_ac_ap",
+ .param = STRING,
+ .handler = wlc_wme_ac,
+ .data.str = "wme_ac_ap",
+ .desc = "Set WME AC options for AP mode",
+ },
+ {
+ .name = "wme_ac_sta",
+ .param = STRING,
+ .handler = wlc_wme_ac,
+ .data.str = "wme_ac_sta",
+ .desc = "Set WME AC options for STA mode",
+ },
+ {
+ .name = "wme_noack",
+ .param = INT,
+ .handler = wlc_iovar,
+ .data.str = "wme_noack",
+ .desc = "WME ACK disable request",
+ },
+ {
+ .name = "802.11d",
+ .param = INT,
+ .handler = wlc_ioctl,
+ .data.num = ((WLC_GET_REGULATORY << 16) | WLC_SET_REGULATORY),
+ .desc = "Enable/disable 802.11d regulatory management",
+ },
+ {
+ .name = "802.11h",
+ .param = INT,
+ .handler = wlc_ioctl,
+ .data.num = ((WLC_GET_SPECT_MANAGMENT << 16) | WLC_SET_SPECT_MANAGMENT),
+ .desc = "Enable/disable 802.11h spectrum management",
+ },
+ {
+ .name = "fragthresh",
+ .param = INT,
+ .handler = wlc_iovar,
+ .data.str = "fragthresh",
+ .desc = "Fragmentation threshold",
+ },
+ {
+ .name = "rtsthresh",
+ .param = INT,
+ .handler = wlc_iovar,
+ .data.str = "rtsthresh",
+ .desc = "RTS threshold"
+ },
+ {
+ .name = "slottime",
+ .param = INT,
+ .handler = wlc_iovar,
+ .data.str = "acktiming",
+ .desc = "Slot time"
+ },
+ {
+ .name = "rxant",
+ .param = INT,
+ .handler = wlc_ioctl,
+ .data.num = ((WLC_GET_ANTDIV << 16) | WLC_SET_ANTDIV),
+ .desc = "Rx antenna selection"
+ },
+ {
+ .name = "txant",
+ .param = INT,
+ .handler = wlc_ioctl,
+ .data.num = ((WLC_GET_TXANT << 16) | WLC_SET_TXANT),
+ .desc = "Tx antenna selection"
+ },
+ {
+ .name = "dtim",
+ .param = INT,
+ .handler = wlc_ioctl,
+ .data.num = ((WLC_GET_DTIMPRD << 16) | WLC_SET_DTIMPRD),
+ .desc = "DTIM period",
+ },
+ {
+ .name = "bcn",
+ .param = INT,
+ .handler = wlc_ioctl,
+ .data.num = ((WLC_GET_BCNPRD << 16) | WLC_SET_BCNPRD),
+ .desc = "Beacon interval"
+ },
+ {
+ .name = "frameburst",
+ .param = INT,
+ .handler = wlc_ioctl,
+ .data.num = ((WLC_GET_FAKEFRAG << 16) | WLC_SET_FAKEFRAG),
+ .desc = "Framebursting"
+ },
+ {
+ .name = "monitor",
+ .param = INT,
+ .handler = wlc_ioctl,
+ .data.num = ((WLC_GET_MONITOR << 16) | WLC_SET_MONITOR),
+ .desc = "Monitor mode"
+ },
+ {
+ .name = "passive_scan",
+ .param = INT,
+ .handler = wlc_ioctl,
+ .data.num = ((WLC_GET_PASSIVE_SCAN << 16) | WLC_SET_PASSIVE_SCAN),
+ .desc = "Passive scan mode"
+ },
+ {
+ .name = "macfilter",
+ .param = INT,
+ .handler = wlc_ioctl,
+ .data.num = ((WLC_GET_MACMODE << 16) | WLC_SET_MACMODE),
+ .desc = "MAC filter mode (0:disabled, 1:deny, 2:allow)"
+ },
+ {
+ .name = "maclist",
+ .param = STRING,
+ .data.num = ((WLC_GET_MACLIST << 16) | WLC_SET_MACLIST),
+ .handler = wlc_maclist,
+ .desc = "MAC filter list"
+ },
+ {
+ .name = "autowds",
+ .param = INT,
+ .handler = wlc_ioctl,
+ .data.num = ((WLC_GET_LAZYWDS << 16) | WLC_SET_LAZYWDS),
+ .desc = "Automatic WDS"
+ },
+ {
+ .name = "wds",
+ .param = STRING,
+ .data.num = ((WLC_GET_WDSLIST << 16) | WLC_SET_WDSLIST),
+ .handler = wlc_maclist,
+ .desc = "WDS connection list"
+ },
+ {
+ .name = "wdstimeout",
+ .param = INT,
+ .handler = wlc_iovar,
+ .data.str = "wdstimeout",
+ .desc = "WDS link detection timeout"
+ },
+ {
+ .name = "wdsmac",
+ .param = STRING|NOARG,
+ .handler = wlc_wdsmac,
+ .desc = "MAC of the remote WDS endpoint (only with wds0.* interfaces)"
+ },
+ {
+ .name = "afterburner",
+ .param = INT,
+ .handler = wlc_afterburner,
+ .desc = "Broadcom Afterburner"
+ },
+ {
+ .name = "ibss_merge",
+ .param = INT,
+ .handler = wlc_iovar,
+ .data.str = "ibss_coalesce_allowed",
+ .desc = "Allow IBSS merges"
+ },
+ {
+ .name = "bssid",
+ .param = MAC,
+ .handler = wlc_ioctl,
+ .data.num = ((WLC_GET_BSSID << 16) | WLC_SET_BSSID),
+ .desc = "BSSID"
+ },
+ {
+ .name = "default_bssid",
+ .param = MAC,
+ .handler = wlc_iovar,
+ .data.str = "perm_etheraddr",
+ .desc = "Default BSSID (read-only)"
+ },
+ {
+ .name = "assoclist",
+ .param = STRING,
+ .data.num = (WLC_GET_ASSOCLIST << 16),
+ .handler = wlc_maclist,
+ .desc = "MACs of associated stations"
+ },
+ {
+ .name = "gmode",
+ .param = INT,
+ .data.num = ((WLC_GET_GMODE << 16) | WLC_SET_GMODE),
+ .handler = wlc_ioctl,
+ .desc = "G Mode"
+ },
+};
+#define wlc_calls_size (sizeof(wlc_calls) / sizeof(struct wlc_call))
+
+static void usage(char *cmd)
+{
+ int i;
+ fprintf(stderr, "Usage: %s <command> [<argument> ...]\n"
+ "\n"
+ "Available commands:\n", cmd);
+ for (i = 0; i < wlc_calls_size; i++) {
+ fprintf(stderr, "\t%-16s\t%s\n", wlc_calls[i].name ?: "", wlc_calls[i].desc ?: "");
+ }
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+static int do_command(const struct wlc_call *cmd, char *arg)
+{
+ static char buf[BUFSIZE];
+ int set;
+ int ret = 0;
+ char *format, *end;
+ int intval;
+ void *ptr = (void *) buf;
+
+ if (debug >= 10) {
+ fprintf(stderr, "do_command %-16s\t'%s'\n", cmd->name, arg);
+ }
+
+ if ((arg == NULL) && ((cmd->param & PARAM_TYPE) != NONE)) {
+ set = 0;
+ ret = cmd->handler(cmd->param | GET, (void *) &cmd->data, (void *) buf);
+ if (ret == 0) {
+ switch(cmd->param & PARAM_TYPE) {
+ case INT:
+ intval = *((int *) buf);
+
+ if (intval > 65535)
+ format = "0x%08x\n";
+ else if (intval > 255)
+ format = "0x%04x\n";
+ else
+ format = "%d\n";
+
+ fprintf(stdout, format, intval);
+ break;
+ case STRING:
+ fprintf(stdout, "%s\n", buf);
+ break;
+ case MAC:
+ my_ether_ntoa(buf, buf + 6);
+ fprintf(stdout, "%s\n", buf + 6);
+ break;
+ }
+ }
+ } else { /* SET */
+ set = 1;
+ switch(cmd->param & PARAM_TYPE) {
+ case INT:
+ intval = strtoul(arg, &end, 10);
+ if (end && !(*end)) {
+ memcpy(buf, &intval, sizeof(intval));
+ } else {
+ fprintf(stderr, "%s: Invalid argument\n", cmd->name);
+ return -1;
+ }
+ break;
+ case STRING:
+ strncpy(buf, arg, BUFSIZE);
+ buf[BUFSIZE - 1] = 0;
+ break;
+ case MAC:
+ ptr = ether_aton(arg);
+ if (!ptr) {
+ fprintf(stderr, "%s: Invalid mac address '%s'\n", cmd->name, arg);
+ return -1;
+ }
+ break;
+ }
+
+ ret = cmd->handler(cmd->param | SET, (void *) &cmd->data, ptr);
+ }
+
+ if ((debug > 0) && (ret != 0))
+ fprintf(stderr, "Command '%s %s' failed: %d\n", (set == 1 ? "set" : "get"), cmd->name, ret);
+
+ return ret;
+}
+
+static struct wlc_call *find_cmd(char *name)
+{
+ int found = 0, i = 0;
+
+ while (!found && (i < wlc_calls_size)) {
+ if (strcmp(name, wlc_calls[i].name) == 0)
+ found = 1;
+ else
+ i++;
+ }
+
+ return (struct wlc_call *) (found ? &wlc_calls[i] : NULL);
+}
+
+int main(int argc, char **argv)
+{
+ static char buf[BUFSIZE];
+ char *s, *s2;
+ char *cmd = argv[0];
+ struct wlc_call *call;
+ int ret = 0;
+
+ if (argc < 2)
+ usage(argv[0]);
+
+ for(interface[2] = '0'; (interface[2] < '3') && (wl_probe(interface) != 0); interface[2]++);
+ if (interface[2] == '3') {
+ fprintf(stderr, "No Broadcom wl interface found!\n");
+ return -1;
+ }
+
+ argv++;
+ argc--;
+ while ((argc > 0) && (argv[0] != NULL)) {
+ if ((call = find_cmd(argv[0])) == NULL) {
+ fprintf(stderr, "Invalid command: %s\n\n", argv[0]);
+ usage(cmd);
+ }
+ if ((argc > 1) && (!(call->param & NOARG))) {
+ ret = do_command(call, argv[1]);
+ argv += 2;
+ argc -= 2;
+ } else {
+ ret = do_command(call, NULL);
+ argv++;
+ argc--;
+ }
+ }
+
+ while (fromstdin && !feof(stdin)) {
+ *buf = 0;
+ fgets(buf, BUFSIZE - 1, stdin);
+
+ if (*buf == 0)
+ continue;
+
+ if ((s = strchr(buf, '\r')) != NULL)
+ *s = 0;
+ if ((s = strchr(buf, '\n')) != NULL)
+ *s = 0;
+
+ s = buf;
+ while (isspace(*s))
+ s++;
+
+ if (!*s)
+ continue;
+
+ if ((s2 = strchr(buf, ' ')) != NULL)
+ *(s2++) = 0;
+
+ while (s2 && isspace(*s2))
+ s2++;
+
+ if ((call = find_cmd(buf)) == NULL) {
+ fprintf(stderr, "Invalid command: %s\n", buf);
+ ret = -1;
+ } else
+ ret = do_command(call, ((call->param & NOARG) ? NULL : s2));
+ }
+
+ return ret;
+}
diff --git a/package/busybox/Config.in b/package/busybox/Config.in
new file mode 100644
index 000000000..88d1aa213
--- /dev/null
+++ b/package/busybox/Config.in
@@ -0,0 +1,24 @@
+
+if PACKAGE_busybox
+
+config BUSYBOX_CONFIG_NOMMU
+ bool
+ depends NOMMU
+ default y if NOMMU
+ deselect BUSYBOX_CONFIG_ASH
+ deselect BUSYBOX_CONFIG_FEATURE_SH_IS_ASH
+ deselect BUSYBOX_CONFIG_LOCK
+
+config CONFIG_BUSYBOX_CONFIG_FEATURE_SH_IS_HUSH
+ bool
+ default y if NOMMU
+ default n if !NOMMU
+
+config BUSYBOX_CONFIG_HUSH
+ bool
+ default y if NOMMU
+ default n if !NOMMU
+
+source "package/busybox/config/Config.in"
+
+endif
diff --git a/package/busybox/Makefile b/package/busybox/Makefile
new file mode 100644
index 000000000..177a42ff3
--- /dev/null
+++ b/package/busybox/Makefile
@@ -0,0 +1,115 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=busybox
+PKG_VERSION:=1.19.4
+PKG_RELEASE:=5
+PKG_FLAGS:=essential
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://www.busybox.net/downloads \
+ http://distfiles.gentoo.org/distfiles/
+PKG_MD5SUM:=9c0cae5a0379228e7b55e5b29528df8e
+
+PKG_BUILD_DEPENDS:=BUSYBOX_CONFIG_FEATURE_HAVE_RPC:librpc
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+ifeq ($(DUMP),)
+ STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell $(SH_FUNC) grep '^CONFIG_BUSYBOX_' $(TOPDIR)/.config | md5s)
+endif
+
+ifneq ($(findstring c,$(OPENWRT_VERBOSE)),)
+ BB_MAKE_VERBOSE := V=1
+else
+ BB_MAKE_VERBOSE :=
+endif
+
+init-y :=
+init-$(CONFIG_BUSYBOX_CONFIG_HTTPD) += httpd
+init-$(CONFIG_BUSYBOX_CONFIG_CROND) += cron
+init-$(CONFIG_BUSYBOX_CONFIG_TELNETD) += telnet
+
+define Package/busybox
+ SECTION:=base
+ CATEGORY:=Base system
+ MAINTAINER:=Nicolas Thill <nico@openwrt.org>
+ TITLE:=Core utilities for embedded Linux
+ URL:=http://busybox.net/
+ DEPENDS:=+BUSYBOX_CONFIG_FEATURE_HAVE_RPC:librpc
+ MENU:=1
+endef
+
+define Package/busybox/description
+ The Swiss Army Knife of embedded Linux.
+ It slices, it dices, it makes Julian Fries.
+endef
+
+define Package/busybox/config
+ source "$(SOURCE)/Config.in"
+endef
+
+define Build/Configure
+ rm -f $(PKG_BUILD_DIR)/.configured*
+ grep 'CONFIG_BUSYBOX_' $(TOPDIR)/.config | sed -e "s,\\(# \)\\?CONFIG_BUSYBOX_\\(.*\\),\\1\\2,g" > $(PKG_BUILD_DIR)/.config
+ yes '' | $(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CC)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ KBUILD_HAVE_NLS=no \
+ ARCH="$(ARCH)" \
+ $(BB_MAKE_VERBOSE) \
+ oldconfig
+endef
+
+ifdef CONFIG_GCC_VERSION_LLVM
+ TARGET_CFLAGS += -fnested-functions
+endif
+
+LDLIBS:=m crypt
+ifdef CONFIG_BUSYBOX_CONFIG_FEATURE_HAVE_RPC
+ TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include
+ export LDFLAGS=$(TARGET_LDFLAGS)
+ LDLIBS += rpc
+endif
+
+define Build/Compile
+ +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CC)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ KBUILD_HAVE_NLS=no \
+ EXTRA_CFLAGS="$(TARGET_CFLAGS)" \
+ ARCH="$(ARCH)" \
+ SKIP_STRIP=y \
+ LDLIBS="$(LDLIBS)" \
+ $(BB_MAKE_VERBOSE) \
+ all
+ rm -rf $(PKG_INSTALL_DIR)
+ $(FIND) $(PKG_BUILD_DIR) -lname "*busybox" -exec rm \{\} \;
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CC)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ EXTRA_CFLAGS="$(TARGET_CFLAGS)" \
+ ARCH="$(ARCH)" \
+ CONFIG_PREFIX="$(PKG_INSTALL_DIR)" \
+ LDLIBS="$(LDLIBS)" \
+ $(BB_MAKE_VERBOSE) \
+ install
+endef
+
+define Package/busybox/install
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(CP) $(PKG_INSTALL_DIR)/* $(1)/
+ for tmp in $(init-y); do \
+ $(INSTALL_BIN) ./files/$$$$tmp $(1)/etc/init.d/$$$$tmp; \
+ done
+ -rm -rf $(1)/lib64
+endef
+
+$(eval $(call BuildPackage,busybox))
diff --git a/package/busybox/config/Config.in b/package/busybox/config/Config.in
new file mode 100644
index 000000000..00450364f
--- /dev/null
+++ b/package/busybox/config/Config.in
@@ -0,0 +1,778 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+
+config BUSYBOX_CONFIG_HAVE_DOT_CONFIG
+ bool
+ default y
+
+menu "Busybox Settings"
+
+menu "General Configuration"
+
+config BUSYBOX_CONFIG_DESKTOP
+ bool "Enable options for full-blown desktop systems"
+ default n
+ help
+ Enable options and features which are not essential.
+ Select this only if you plan to use busybox on full-blown
+ desktop machine with common Linux distro, not on an embedded box.
+
+config BUSYBOX_CONFIG_EXTRA_COMPAT
+ bool "Provide compatible behavior for rare corner cases (bigger code)"
+ default n
+ help
+ This option makes grep, sed etc handle rare corner cases
+ (embedded NUL bytes and such). This makes code bigger and uses
+ some GNU extensions in libc. You probably only need this option
+ if you plan to run busybox on desktop.
+
+config BUSYBOX_CONFIG_INCLUDE_SUSv2
+ bool "Enable obsolete features removed before SUSv3"
+ default y
+ help
+ This option will enable backwards compatibility with SuSv2,
+ specifically, old-style numeric options ('command -1 <file>')
+ will be supported in head, tail, and fold. (Note: should
+ affect renice too.)
+
+config BUSYBOX_CONFIG_USE_PORTABLE_CODE
+ bool "Avoid using GCC-specific code constructs"
+ default n
+ help
+ Use this option if you are trying to compile busybox with
+ compiler other than gcc.
+ If you do use gcc, this option may needlessly increase code size.
+
+config BUSYBOX_CONFIG_PLATFORM_LINUX
+ bool "Enable Linux-specific applets and features"
+ default y
+ help
+ For the most part, busybox requires only POSIX compatibility
+ from the target system, but some applets and features use
+ Linux-specific interfaces.
+
+ Answering 'N' here will disable such applets and hide the
+ corresponding configuration options.
+
+choice
+ prompt "Buffer allocation policy"
+ default BUSYBOX_CONFIG_FEATURE_BUFFERS_GO_ON_STACK
+ help
+ There are 3 ways BusyBox can handle buffer allocations:
+ - Use malloc. This costs code size for the call to xmalloc.
+ - Put them on stack. For some very small machines with limited stack
+ space, this can be deadly. For most folks, this works just fine.
+ - Put them in BSS. This works beautifully for computers with a real
+ MMU (and OS support), but wastes runtime RAM for uCLinux. This
+ behavior was the only one available for BusyBox versions 0.48 and
+ earlier.
+
+config BUSYBOX_CONFIG_FEATURE_BUFFERS_USE_MALLOC
+ bool "Allocate with Malloc"
+
+config BUSYBOX_CONFIG_FEATURE_BUFFERS_GO_ON_STACK
+ bool "Allocate on the Stack"
+
+config BUSYBOX_CONFIG_FEATURE_BUFFERS_GO_IN_BSS
+ bool "Allocate in the .bss section"
+
+endchoice
+
+config BUSYBOX_CONFIG_SHOW_USAGE
+ bool "Show terse applet usage messages"
+ default y
+ help
+ All BusyBox applets will show help messages when invoked with
+ wrong arguments. You can turn off printing these terse usage
+ messages if you say no here.
+ This will save you up to 7k.
+
+config BUSYBOX_CONFIG_FEATURE_VERBOSE_USAGE
+ bool "Show verbose applet usage messages"
+ default y
+ depends on BUSYBOX_CONFIG_SHOW_USAGE
+ help
+ All BusyBox applets will show more verbose help messages when
+ busybox is invoked with --help. This will add a lot of text to the
+ busybox binary. In the default configuration, this will add about
+ 13k, but it can add much more depending on your configuration.
+
+config BUSYBOX_CONFIG_FEATURE_COMPRESS_USAGE
+ bool "Store applet usage messages in compressed form"
+ default y
+ depends on BUSYBOX_CONFIG_SHOW_USAGE
+ help
+ Store usage messages in compressed form, uncompress them on-the-fly
+ when <applet> --help is called.
+
+ If you have a really tiny busybox with few applets enabled (and
+ bunzip2 isn't one of them), the overhead of the decompressor might
+ be noticeable. Also, if you run executables directly from ROM
+ and have very little memory, this might not be a win. Otherwise,
+ you probably want this.
+
+config BUSYBOX_CONFIG_FEATURE_INSTALLER
+ bool "Support --install [-s] to install applet links at runtime"
+ default n
+ help
+ Enable 'busybox --install [-s]' support. This will allow you to use
+ busybox at runtime to create hard links or symlinks for all the
+ applets that are compiled into busybox.
+
+config BUSYBOX_CONFIG_INSTALL_NO_USR
+ bool "Don't use /usr"
+ default n
+ help
+ Disable use of /usr. busybox --install and "make install"
+ will install applets only to /bin and /sbin,
+ never to /usr/bin or /usr/sbin.
+
+config BUSYBOX_CONFIG_LOCALE_SUPPORT
+ bool "Enable locale support (system needs locale for this to work)"
+ default n
+ help
+ Enable this if your system has locale support and you would like
+ busybox to support locale settings.
+
+config BUSYBOX_CONFIG_UNICODE_SUPPORT
+ bool "Support Unicode"
+ default n
+ help
+ This makes various applets aware that one byte is not
+ one character on screen.
+
+ Busybox aims to eventually work correctly with Unicode displays.
+ Any older encodings are not guaranteed to work.
+ Probably by the time when busybox will be fully Unicode-clean,
+ other encodings will be mainly of historic interest.
+
+config BUSYBOX_CONFIG_UNICODE_USING_LOCALE
+ bool "Use libc routines for Unicode (else uses internal ones)"
+ default n
+ depends on BUSYBOX_CONFIG_UNICODE_SUPPORT && BUSYBOX_CONFIG_LOCALE_SUPPORT
+ help
+ With this option on, Unicode support is implemented using libc
+ routines. Otherwise, internal implementation is used.
+ Internal implementation is smaller.
+
+config BUSYBOX_CONFIG_FEATURE_CHECK_UNICODE_IN_ENV
+ bool "Check $LANG environment variable"
+ default n
+ depends on BUSYBOX_CONFIG_UNICODE_SUPPORT && !BUSYBOX_CONFIG_UNICODE_USING_LOCALE
+ help
+ With this option on, Unicode support is activated
+ only if LANG variable has the value of the form "xxxx.utf8"
+
+ Otherwise, Unicode support will be always enabled and active.
+
+config BUSYBOX_CONFIG_SUBST_WCHAR
+ int "Character code to substitute unprintable characters with"
+ depends on BUSYBOX_CONFIG_UNICODE_SUPPORT
+ default 63
+ help
+ Typical values are 63 for '?' (works with any output device),
+ 30 for ASCII substitute control code,
+ 65533 (0xfffd) for Unicode replacement character.
+
+config BUSYBOX_CONFIG_LAST_SUPPORTED_WCHAR
+ int "Range of supported Unicode characters"
+ depends on BUSYBOX_CONFIG_UNICODE_SUPPORT
+ default 767
+ help
+ Any character with Unicode value bigger than this is assumed
+ to be non-printable on output device. Many applets replace
+ such chars with substitution character.
+
+ The idea is that many valid printable Unicode chars are
+ nevertheless are not displayed correctly. Think about
+ combining charachers, double-wide hieroglyphs, obscure
+ characters in dozens of ancient scripts...
+ Many terminals, terminal emulators, xterms etc will fail
+ to handle them correctly. Choose the smallest value
+ which suits your needs.
+
+ Typical values are:
+ 126 - ASCII only
+ 767 (0x2ff) - there are no combining chars in [0..767] range
+ (the range includes Latin 1, Latin Ext. A and B),
+ code is ~700 bytes smaller for this case.
+ 4351 (0x10ff) - there are no double-wide chars in [0..4351] range,
+ code is ~300 bytes smaller for this case.
+ 12799 (0x31ff) - nearly all non-ideographic characters are
+ available in [0..12799] range, including
+ East Asian scripts like katakana, hiragana, hangul,
+ bopomofo...
+ 0 - off, any valid printable Unicode character will be printed.
+
+config BUSYBOX_CONFIG_UNICODE_COMBINING_WCHARS
+ bool "Allow zero-width Unicode characters on output"
+ default n
+ depends on BUSYBOX_CONFIG_UNICODE_SUPPORT
+ help
+ With this option off, any Unicode char with width of 0
+ is substituted on output.
+
+config BUSYBOX_CONFIG_UNICODE_WIDE_WCHARS
+ bool "Allow wide Unicode characters on output"
+ default n
+ depends on BUSYBOX_CONFIG_UNICODE_SUPPORT
+ help
+ With this option off, any Unicode char with width > 1
+ is substituted on output.
+
+config BUSYBOX_CONFIG_UNICODE_BIDI_SUPPORT
+ bool "Bidirectional character-aware line input"
+ default n
+ depends on BUSYBOX_CONFIG_UNICODE_SUPPORT && !BUSYBOX_CONFIG_UNICODE_USING_LOCALE
+ help
+ With this option on, right-to-left Unicode characters
+ are treated differently on input (e.g. cursor movement).
+
+config BUSYBOX_CONFIG_UNICODE_NEUTRAL_TABLE
+ bool "In bidi input, support non-ASCII neutral chars too"
+ default n
+ depends on BUSYBOX_CONFIG_UNICODE_BIDI_SUPPORT
+ help
+ In most cases it's enough to treat only ASCII non-letters
+ (i.e. punctuation, numbers and space) as characters
+ with neutral directionality.
+ With this option on, more extensive (and bigger) table
+ of neutral chars will be used.
+
+config BUSYBOX_CONFIG_UNICODE_PRESERVE_BROKEN
+ bool "Make it possible to enter sequences of chars which are not Unicode"
+ default n
+ depends on BUSYBOX_CONFIG_UNICODE_SUPPORT
+ help
+ With this option on, on line-editing input (such as used by shells)
+ invalid UTF-8 bytes are not substituted with the selected
+ substitution character.
+ For example, this means that entering 'l', 's', ' ', 0xff, [Enter]
+ at shell prompt will list file named 0xff (single char name
+ with char value 255), not file named '?'.
+
+config BUSYBOX_CONFIG_LONG_OPTS
+ bool "Support for --long-options"
+ default y
+ help
+ Enable this if you want busybox applets to use the gnu --long-option
+ style, in addition to single character -a -b -c style options.
+
+config BUSYBOX_CONFIG_FEATURE_DEVPTS
+ bool "Use the devpts filesystem for Unix98 PTYs"
+ default y
+ help
+ Enable if you want BusyBox to use Unix98 PTY support. If enabled,
+ busybox will use /dev/ptmx for the master side of the pseudoterminal
+ and /dev/pts/<number> for the slave side. Otherwise, BSD style
+ /dev/ttyp<number> will be used. To use this option, you should have
+ devpts mounted.
+
+config BUSYBOX_CONFIG_FEATURE_CLEAN_UP
+ bool "Clean up all memory before exiting (usually not needed)"
+ default n
+ help
+ As a size optimization, busybox normally exits without explicitly
+ freeing dynamically allocated memory or closing files. This saves
+ space since the OS will clean up for us, but it can confuse debuggers
+ like valgrind, which report tons of memory and resource leaks.
+
+ Don't enable this unless you have a really good reason to clean
+ things up manually.
+
+config BUSYBOX_CONFIG_FEATURE_UTMP
+ bool "Support utmp file"
+ default n
+ help
+ The file /var/run/utmp is used to track who is currently logged in.
+ With this option on, certain applets (getty, login, telnetd etc)
+ will create and delete entries there.
+ "who" applet requires this option.
+
+config BUSYBOX_CONFIG_FEATURE_WTMP
+ bool "Support wtmp file"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_UTMP
+ help
+ The file /var/run/wtmp is used to track when users have logged into
+ and logged out of the system.
+ With this option on, certain applets (getty, login, telnetd etc)
+ will append new entries there.
+ "last" applet requires this option.
+
+config BUSYBOX_CONFIG_FEATURE_PIDFILE
+ bool "Support writing pidfiles"
+ default y
+ help
+ This option makes some applets (e.g. crond, syslogd, inetd) write
+ a pidfile in /var/run. Some applications rely on them.
+
+config BUSYBOX_CONFIG_FEATURE_SUID
+ bool "Support for SUID/SGID handling"
+ default y
+ help
+ With this option you can install the busybox binary belonging
+ to root with the suid bit set, enabling some applets to perform
+ root-level operations even when run by ordinary users
+ (for example, mounting of user mounts in fstab needs this).
+
+ Busybox will automatically drop priviledges for applets
+ that don't need root access.
+
+ If you are really paranoid and don't want to do this, build two
+ busybox binaries with different applets in them (and the appropriate
+ symlinks pointing to each binary), and only set the suid bit on the
+ one that needs it.
+
+ The applets which require root rights (need suid bit or
+ to be run by root) and will refuse to execute otherwise:
+ crontab, login, passwd, su, vlock, wall.
+
+ The applets which will use root rights if they have them
+ (via suid bit, or because run by root), but would try to work
+ without root right nevertheless:
+ findfs, ping[6], traceroute[6], mount.
+
+ Note that if you DONT select this option, but DO make busybox
+ suid root, ALL applets will run under root, which is a huge
+ security hole (think "cp /some/file /etc/passwd").
+
+config BUSYBOX_CONFIG_FEATURE_SUID_CONFIG
+ bool "Runtime SUID/SGID configuration via /etc/busybox.conf"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_SUID
+ help
+ Allow the SUID / SGID state of an applet to be determined at runtime
+ by checking /etc/busybox.conf. (This is sort of a poor man's sudo.)
+ The format of this file is as follows:
+
+ APPLET = [Ssx-][Ssx-][x-] [USER.GROUP]
+
+ s: USER or GROUP is allowed to execute APPLET.
+ APPLET will run under USER or GROUP
+ (reagardless of who's running it).
+ S: USER or GROUP is NOT allowed to execute APPLET.
+ APPLET will run under USER or GROUP.
+ This option is not very sensical.
+ x: USER/GROUP/others are allowed to execute APPLET.
+ No UID/GID change will be done when it is run.
+ -: USER/GROUP/others are not allowed to execute APPLET.
+
+ An example might help:
+
+ [SUID]
+ su = ssx root.0 # applet su can be run by anyone and runs with
+ # euid=0/egid=0
+ su = ssx # exactly the same
+
+ mount = sx- root.disk # applet mount can be run by root and members
+ # of group disk (but not anyone else)
+ # and runs with euid=0 (egid is not changed)
+
+ cp = --- # disable applet cp for everyone
+
+ The file has to be owned by user root, group root and has to be
+ writeable only by root:
+ (chown 0.0 /etc/busybox.conf; chmod 600 /etc/busybox.conf)
+ The busybox executable has to be owned by user root, group
+ root and has to be setuid root for this to work:
+ (chown 0.0 /bin/busybox; chmod 4755 /bin/busybox)
+
+ Robert 'sandman' Griebl has more information here:
+ <url: http://www.softforge.de/bb/suid.html >.
+
+config BUSYBOX_CONFIG_FEATURE_SUID_CONFIG_QUIET
+ bool "Suppress warning message if /etc/busybox.conf is not readable"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_SUID_CONFIG
+ help
+ /etc/busybox.conf should be readable by the user needing the SUID,
+ check this option to avoid users to be notified about missing
+ permissions.
+
+config BUSYBOX_CONFIG_SELINUX
+ bool "Support NSA Security Enhanced Linux"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Enable support for SELinux in applets ls, ps, and id. Also provide
+ the option of compiling in SELinux applets.
+
+ If you do not have a complete SELinux userland installed, this stuff
+ will not compile. Go visit
+ http://www.nsa.gov/selinux/index.html
+ to download the necessary stuff to allow busybox to compile with
+ this option enabled. Specifially, libselinux 1.28 or better is
+ directly required by busybox. If the installation is located in a
+ non-standard directory, provide it by invoking make as follows:
+ CFLAGS=-I<libselinux-include-path> \
+ LDFLAGS=-L<libselinux-lib-path> \
+ make
+
+ Most people will leave this set to 'N'.
+
+config BUSYBOX_CONFIG_FEATURE_PREFER_APPLETS
+ bool "exec prefers applets"
+ default y
+ help
+ This is an experimental option which directs applets about to
+ call 'exec' to try and find an applicable busybox applet before
+ searching the PATH. This is typically done by exec'ing
+ /proc/self/exe.
+ This may affect shell, find -exec, xargs and similar applets.
+ They will use applets even if /bin/<applet> -> busybox link
+ is missing (or is not a link to busybox). However, this causes
+ problems in chroot jails without mounted /proc and with ps/top
+ (command name can be shown as 'exe' for applets started this way).
+
+config BUSYBOX_CONFIG_BUSYBOX_EXEC_PATH
+ string "Path to BusyBox executable"
+ default "/proc/self/exe"
+ help
+ When Busybox applets need to run other busybox applets, BusyBox
+ sometimes needs to exec() itself. When the /proc filesystem is
+ mounted, /proc/self/exe always points to the currently running
+ executable. If you haven't got /proc, set this to wherever you
+ want to run BusyBox from.
+
+# These are auto-selected by other options
+
+config BUSYBOX_CONFIG_FEATURE_SYSLOG
+ bool #No description makes it a hidden option
+ default y
+ #help
+ # This option is auto-selected when you select any applet which may
+ # send its output to syslog. You do not need to select it manually.
+
+config BUSYBOX_CONFIG_FEATURE_HAVE_RPC
+ bool #No description makes it a hidden option
+ default n
+ #help
+ # This is automatically selected if any of enabled applets need it.
+ # You do not need to select it manually.
+
+endmenu
+
+menu 'Build Options'
+
+config BUSYBOX_CONFIG_STATIC
+ bool "Build BusyBox as a static binary (no shared libs)"
+ default n
+ help
+ If you want to build a static BusyBox binary, which does not
+ use or require any shared libraries, then enable this option.
+ This can cause BusyBox to be considerably larger, so you should
+ leave this option false unless you have a good reason (i.e.
+ your target platform does not support shared libraries, or
+ you are building an initrd which doesn't need anything but
+ BusyBox, etc).
+
+ Most people will leave this set to 'N'.
+
+config BUSYBOX_CONFIG_PIE
+ bool "Build BusyBox as a position independent executable"
+ default n
+ depends on !BUSYBOX_CONFIG_STATIC
+ help
+ Hardened code option. PIE binaries are loaded at a different
+ address at each invocation. This has some overhead,
+ particularly on x86-32 which is short on registers.
+
+ Most people will leave this set to 'N'.
+
+config BUSYBOX_CONFIG_NOMMU
+ bool "Force NOMMU build"
+ default n
+ help
+ Busybox tries to detect whether architecture it is being
+ built against supports MMU or not. If this detection fails,
+ or if you want to build NOMMU version of busybox for testing,
+ you may force NOMMU build here.
+
+ Most people will leave this set to 'N'.
+
+# PIE can be made to work with BUILD_LIBBUSYBOX, but currently
+# build system does not support that
+config BUSYBOX_CONFIG_BUILD_LIBBUSYBOX
+ bool "Build shared libbusybox"
+ default n
+ depends on !BUSYBOX_CONFIG_FEATURE_PREFER_APPLETS && !BUSYBOX_CONFIG_PIE && !BUSYBOX_CONFIG_STATIC
+ help
+ Build a shared library libbusybox.so.N.N.N which contains all
+ busybox code.
+
+ This feature allows every applet to be built as a tiny
+ separate executable. Enabling it for "one big busybox binary"
+ approach serves no purpose and increases code size.
+ You should almost certainly say "no" to this.
+
+### config FEATURE_FULL_LIBBUSYBOX
+### bool "Feature-complete libbusybox"
+### default n if !FEATURE_SHARED_BUSYBOX
+### depends on BUILD_LIBBUSYBOX
+### help
+### Build a libbusybox with the complete feature-set, disregarding
+### the actually selected config.
+###
+### Normally, libbusybox will only contain the features which are
+### used by busybox itself. If you plan to write a separate
+### standalone application which uses libbusybox say 'Y'.
+###
+### Note: libbusybox is GPL, not LGPL, and exports no stable API that
+### might act as a copyright barrier. We can and will modify the
+### exported function set between releases (even minor version number
+### changes), and happily break out-of-tree features.
+###
+### Say 'N' if in doubt.
+
+config BUSYBOX_CONFIG_FEATURE_INDIVIDUAL
+ bool "Produce a binary for each applet, linked against libbusybox"
+ default n
+ depends on BUSYBOX_CONFIG_BUILD_LIBBUSYBOX
+ help
+ If your CPU architecture doesn't allow for sharing text/rodata
+ sections of running binaries, but allows for runtime dynamic
+ libraries, this option will allow you to reduce memory footprint
+ when you have many different applets running at once.
+
+ If your CPU architecture allows for sharing text/rodata,
+ having single binary is more optimal.
+
+ Each applet will be a tiny program, dynamically linked
+ against libbusybox.so.N.N.N.
+
+ You need to have a working dynamic linker.
+
+config BUSYBOX_CONFIG_FEATURE_SHARED_BUSYBOX
+ bool "Produce additional busybox binary linked against libbusybox"
+ default n
+ depends on BUSYBOX_CONFIG_BUILD_LIBBUSYBOX
+ help
+ Build busybox, dynamically linked against libbusybox.so.N.N.N.
+
+ You need to have a working dynamic linker.
+
+### config BUILD_AT_ONCE
+### bool "Compile all sources at once"
+### default n
+### help
+### Normally each source-file is compiled with one invocation of
+### the compiler.
+### If you set this option, all sources are compiled at once.
+### This gives the compiler more opportunities to optimize which can
+### result in smaller and/or faster binaries.
+###
+### Setting this option will consume alot of memory, e.g. if you
+### enable all applets with all features, gcc uses more than 300MB
+### RAM during compilation of busybox.
+###
+### This option is most likely only beneficial for newer compilers
+### such as gcc-4.1 and above.
+###
+### Say 'N' unless you know what you are doing.
+
+config BUSYBOX_CONFIG_LFS
+ bool
+ default y
+ help
+ If you want to build BusyBox with large file support, then enable
+ this option. This will have no effect if your kernel or your C
+ library lacks large file support for large files. Some of the
+ programs that can benefit from large file support include dd, gzip,
+ cp, mount, tar, and many others. If you want to access files larger
+ than 2 Gigabytes, enable this option. Otherwise, leave it set to 'N'.
+
+config BUSYBOX_CONFIG_CROSS_COMPILER_PREFIX
+ string "Cross Compiler prefix"
+ default ""
+ help
+ If you want to build BusyBox with a cross compiler, then you
+ will need to set this to the cross-compiler prefix, for example,
+ "i386-uclibc-".
+
+ Note that CROSS_COMPILE environment variable or
+ "make CROSS_COMPILE=xxx ..." will override this selection.
+
+ Native builds leave this empty.
+
+config BUSYBOX_CONFIG_EXTRA_CFLAGS
+ string "Additional CFLAGS"
+ default ""
+ help
+ Additional CFLAGS to pass to the compiler verbatim.
+
+endmenu
+
+menu 'Debugging Options'
+
+config BUSYBOX_CONFIG_DEBUG
+ bool "Build BusyBox with extra Debugging symbols"
+ default n
+ help
+ Say Y here if you wish to examine BusyBox internals while applets are
+ running. This increases the size of the binary considerably, and
+ should only be used when doing development. If you are doing
+ development and want to debug BusyBox, answer Y.
+
+ Most people should answer N.
+
+config BUSYBOX_CONFIG_DEBUG_PESSIMIZE
+ bool "Disable compiler optimizations"
+ default n
+ depends on BUSYBOX_CONFIG_DEBUG
+ help
+ The compiler's optimization of source code can eliminate and reorder
+ code, resulting in an executable that's hard to understand when
+ stepping through it with a debugger. This switches it off, resulting
+ in a much bigger executable that more closely matches the source
+ code.
+
+config BUSYBOX_CONFIG_WERROR
+ bool "Abort compilation on any warning"
+ default n
+ help
+ Selecting this will add -Werror to gcc command line.
+
+ Most people should answer N.
+
+choice
+ prompt "Additional debugging library"
+ default BUSYBOX_CONFIG_NO_DEBUG_LIB
+ help
+ Using an additional debugging library will make BusyBox become
+ considerable larger and will cause it to run more slowly. You
+ should always leave this option disabled for production use.
+
+ dmalloc support:
+ ----------------
+ This enables compiling with dmalloc ( http://dmalloc.com/ )
+ which is an excellent public domain mem leak and malloc problem
+ detector. To enable dmalloc, before running busybox you will
+ want to properly set your environment, for example:
+ export DMALLOC_OPTIONS=debug=0x34f47d83,inter=100,log=logfile
+ The 'debug=' value is generated using the following command
+ dmalloc -p log-stats -p log-non-free -p log-bad-space \
+ -p log-elapsed-time -p check-fence -p check-heap \
+ -p check-lists -p check-blank -p check-funcs -p realloc-copy \
+ -p allow-free-null
+
+ Electric-fence support:
+ -----------------------
+ This enables compiling with Electric-fence support. Electric
+ fence is another very useful malloc debugging library which uses
+ your computer's virtual memory hardware to detect illegal memory
+ accesses. This support will make BusyBox be considerable larger
+ and run slower, so you should leave this option disabled unless
+ you are hunting a hard to find memory problem.
+
+
+config BUSYBOX_CONFIG_NO_DEBUG_LIB
+ bool "None"
+
+config BUSYBOX_CONFIG_DMALLOC
+ bool "Dmalloc"
+
+config BUSYBOX_CONFIG_EFENCE
+ bool "Electric-fence"
+
+endchoice
+
+endmenu
+
+menu 'Installation Options ("make install" behavior)'
+
+choice
+ prompt "What kind of applet links to install"
+ default BUSYBOX_CONFIG_INSTALL_APPLET_SYMLINKS
+ help
+ Choose what kind of links to applets are created by "make install".
+
+config BUSYBOX_CONFIG_INSTALL_APPLET_SYMLINKS
+ bool "as soft-links"
+ help
+ Install applets as soft-links to the busybox binary. This needs some
+ free inodes on the filesystem, but might help with filesystem
+ generators that can't cope with hard-links.
+
+config BUSYBOX_CONFIG_INSTALL_APPLET_HARDLINKS
+ bool "as hard-links"
+ help
+ Install applets as hard-links to the busybox binary. This might
+ count on a filesystem with few inodes.
+
+config BUSYBOX_CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS
+ bool "as script wrappers"
+ help
+ Install applets as script wrappers that call the busybox binary.
+
+config BUSYBOX_CONFIG_INSTALL_APPLET_DONT
+ bool "not installed"
+ help
+ Do not install applet links. Useful when you plan to use
+ busybox --install for installing links, or plan to use
+ a standalone shell and thus don't need applet links.
+
+endchoice
+
+choice
+ prompt "/bin/sh applet link"
+ default BUSYBOX_CONFIG_INSTALL_SH_APPLET_SYMLINK
+ depends on BUSYBOX_CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS
+ help
+ Choose how you install /bin/sh applet link.
+
+config BUSYBOX_CONFIG_INSTALL_SH_APPLET_SYMLINK
+ bool "as soft-link"
+ help
+ Install /bin/sh applet as soft-link to the busybox binary.
+
+config BUSYBOX_CONFIG_INSTALL_SH_APPLET_HARDLINK
+ bool "as hard-link"
+ help
+ Install /bin/sh applet as hard-link to the busybox binary.
+
+config BUSYBOX_CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER
+ bool "as script wrapper"
+ help
+ Install /bin/sh applet as script wrapper that calls
+ the busybox binary.
+
+endchoice
+
+config BUSYBOX_CONFIG_PREFIX
+ string "BusyBox installation prefix"
+ default "./_install"
+ help
+ Define your directory to install BusyBox files/subdirs in.
+
+endmenu
+
+source package/busybox/config/libbb/Config.in
+
+endmenu
+
+comment "Applets"
+
+source package/busybox/config/archival/Config.in
+source package/busybox/config/coreutils/Config.in
+source package/busybox/config/console-tools/Config.in
+source package/busybox/config/debianutils/Config.in
+source package/busybox/config/editors/Config.in
+source package/busybox/config/findutils/Config.in
+source package/busybox/config/init/Config.in
+source package/busybox/config/loginutils/Config.in
+source package/busybox/config/e2fsprogs/Config.in
+source package/busybox/config/modutils/Config.in
+source package/busybox/config/util-linux/Config.in
+source package/busybox/config/miscutils/Config.in
+source package/busybox/config/networking/Config.in
+source package/busybox/config/printutils/Config.in
+source package/busybox/config/mailutils/Config.in
+source package/busybox/config/procps/Config.in
+source package/busybox/config/runit/Config.in
+source package/busybox/config/selinux/Config.in
+source package/busybox/config/shell/Config.in
+source package/busybox/config/sysklogd/Config.in
diff --git a/package/busybox/config/archival/Config.in b/package/busybox/config/archival/Config.in
new file mode 100644
index 000000000..d2bfa4848
--- /dev/null
+++ b/package/busybox/config/archival/Config.in
@@ -0,0 +1,380 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Archival Utilities"
+
+
+
+config BUSYBOX_CONFIG_FEATURE_SEAMLESS_XZ
+ bool "Make tar, rpm, modprobe etc understand .xz data"
+ default n
+ help
+ Make tar, rpm, modprobe etc understand .xz data.
+
+config BUSYBOX_CONFIG_FEATURE_SEAMLESS_LZMA
+ bool "Make tar, rpm, modprobe etc understand .lzma data"
+ default n
+ help
+ Make tar, rpm, modprobe etc understand .lzma data.
+
+config BUSYBOX_CONFIG_FEATURE_SEAMLESS_BZ2
+ bool "Make tar, rpm, modprobe etc understand .bz2 data"
+ default n
+ help
+ Make tar, rpm, modprobe etc understand .bz2 data.
+
+config BUSYBOX_CONFIG_FEATURE_SEAMLESS_GZ
+ bool "Make tar, rpm, modprobe etc understand .gz data"
+ default y
+ help
+ Make tar, rpm, modprobe etc understand .gz data.
+
+config BUSYBOX_CONFIG_FEATURE_SEAMLESS_Z
+ bool "Make tar and gunzip understand .Z data"
+ default n
+ help
+ Make tar and gunzip understand .Z data.
+
+config BUSYBOX_CONFIG_AR
+ bool "ar"
+ default n # needs to be improved to be able to replace binutils ar
+ help
+ ar is an archival utility program used to create, modify, and
+ extract contents from archives. An archive is a single file holding
+ a collection of other files in a structure that makes it possible to
+ retrieve the original individual files (called archive members).
+ The original files' contents, mode (permissions), timestamp, owner,
+ and group are preserved in the archive, and can be restored on
+ extraction.
+
+ The stored filename is limited to 15 characters. (for more information
+ see long filename support).
+ ar has 60 bytes of overheads for every stored file.
+
+ This implementation of ar can extract archives, it cannot create or
+ modify them.
+ On an x86 system, the ar applet adds about 1K.
+
+ Unless you have a specific application which requires ar, you should
+ probably say N here.
+
+config BUSYBOX_CONFIG_FEATURE_AR_LONG_FILENAMES
+ bool "Support for long filenames (not needed for debs)"
+ default n
+ depends on BUSYBOX_CONFIG_AR
+ help
+ By default the ar format can only store the first 15 characters
+ of the filename, this option removes that limitation.
+ It supports the GNU ar long filename method which moves multiple long
+ filenames into a the data section of a new ar entry.
+
+config BUSYBOX_CONFIG_FEATURE_AR_CREATE
+ bool "Support archive creation"
+ default n
+ depends on BUSYBOX_CONFIG_AR
+ help
+ This enables archive creation (-c and -r) with busybox ar.
+
+config BUSYBOX_CONFIG_BUNZIP2
+ bool "bunzip2"
+ default y
+ help
+ bunzip2 is a compression utility using the Burrows-Wheeler block
+ sorting text compression algorithm, and Huffman coding. Compression
+ is generally considerably better than that achieved by more
+ conventional LZ77/LZ78-based compressors, and approaches the
+ performance of the PPM family of statistical compressors.
+
+ Unless you have a specific application which requires bunzip2, you
+ should probably say N here.
+
+config BUSYBOX_CONFIG_BZIP2
+ bool "bzip2"
+ default n
+ help
+ bzip2 is a compression utility using the Burrows-Wheeler block
+ sorting text compression algorithm, and Huffman coding. Compression
+ is generally considerably better than that achieved by more
+ conventional LZ77/LZ78-based compressors, and approaches the
+ performance of the PPM family of statistical compressors.
+
+ Unless you have a specific application which requires bzip2, you
+ should probably say N here.
+
+config BUSYBOX_CONFIG_CPIO
+ bool "cpio"
+ default n
+ help
+ cpio is an archival utility program used to create, modify, and
+ extract contents from archives.
+ cpio has 110 bytes of overheads for every stored file.
+
+ This implementation of cpio can extract cpio archives created in the
+ "newc" or "crc" format, it cannot create or modify them.
+
+ Unless you have a specific application which requires cpio, you
+ should probably say N here.
+
+config BUSYBOX_CONFIG_FEATURE_CPIO_O
+ bool "Support for archive creation"
+ default n
+ depends on BUSYBOX_CONFIG_CPIO
+ help
+ This implementation of cpio can create cpio archives in the "newc"
+ format only.
+
+config BUSYBOX_CONFIG_FEATURE_CPIO_P
+ bool "Support for passthrough mode"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_CPIO_O
+ help
+ Passthrough mode. Rarely used.
+
+config BUSYBOX_CONFIG_DPKG
+ bool "dpkg"
+ default n
+ select BUSYBOX_CONFIG_FEATURE_SEAMLESS_GZ
+ help
+ dpkg is a medium-level tool to install, build, remove and manage
+ Debian packages.
+
+ This implementation of dpkg has a number of limitations,
+ you should use the official dpkg if possible.
+
+config BUSYBOX_CONFIG_DPKG_DEB
+ bool "dpkg_deb"
+ default n
+ select BUSYBOX_CONFIG_FEATURE_SEAMLESS_GZ
+ help
+ dpkg-deb unpacks and provides information about Debian archives.
+
+ This implementation of dpkg-deb cannot pack archives.
+
+ Unless you have a specific application which requires dpkg-deb,
+ say N here.
+
+config BUSYBOX_CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY
+ bool "Extract only (-x)"
+ default n
+ depends on BUSYBOX_CONFIG_DPKG_DEB
+ help
+ This reduces dpkg-deb to the equivalent of
+ "ar -p <deb> data.tar.gz | tar -zx". However it saves space as none
+ of the extra dpkg-deb, ar or tar options are needed, they are linked
+ to internally.
+
+config BUSYBOX_CONFIG_GUNZIP
+ bool "gunzip"
+ default y
+ help
+ gunzip is used to decompress archives created by gzip.
+ You can use the `-t' option to test the integrity of
+ an archive, without decompressing it.
+
+config BUSYBOX_CONFIG_GZIP
+ bool "gzip"
+ default y
+ help
+ gzip is used to compress files.
+ It's probably the most widely used UNIX compression program.
+
+config BUSYBOX_CONFIG_FEATURE_GZIP_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_GZIP && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Enable use of long options, increases size by about 106 Bytes
+
+config BUSYBOX_CONFIG_LZOP
+ bool "lzop"
+ default n
+ help
+ Lzop compression/decompresion.
+
+config BUSYBOX_CONFIG_LZOP_COMPR_HIGH
+ bool "lzop compression levels 7,8,9 (not very useful)"
+ default n
+ depends on BUSYBOX_CONFIG_LZOP
+ help
+ High levels (7,8,9) of lzop compression. These levels
+ are actually slower than gzip at equivalent compression ratios
+ and take up 3.2K of code.
+
+config BUSYBOX_CONFIG_RPM2CPIO
+ bool "rpm2cpio"
+ default n
+ help
+ Converts a RPM file into a CPIO archive.
+
+config BUSYBOX_CONFIG_RPM
+ bool "rpm"
+ default n
+ help
+ Mini RPM applet - queries and extracts RPM packages.
+
+config BUSYBOX_CONFIG_TAR
+ bool "tar"
+ default y
+ help
+ tar is an archiving program. It's commonly used with gzip to
+ create compressed archives. It's probably the most widely used
+ UNIX archive program.
+
+config BUSYBOX_CONFIG_FEATURE_TAR_CREATE
+ bool "Enable archive creation"
+ default y
+ depends on BUSYBOX_CONFIG_TAR
+ help
+ If you enable this option you'll be able to create
+ tar archives using the `-c' option.
+
+config BUSYBOX_CONFIG_FEATURE_TAR_AUTODETECT
+ bool "Autodetect compressed tarballs"
+ default n
+ depends on BUSYBOX_CONFIG_TAR && (BUSYBOX_CONFIG_FEATURE_SEAMLESS_Z || BUSYBOX_CONFIG_FEATURE_SEAMLESS_GZ || BUSYBOX_CONFIG_FEATURE_SEAMLESS_BZ2 || BUSYBOX_CONFIG_FEATURE_SEAMLESS_LZMA || BUSYBOX_CONFIG_FEATURE_SEAMLESS_XZ)
+ help
+ With this option tar can automatically detect compressed
+ tarballs. Currently it works only on files (not pipes etc).
+
+config BUSYBOX_CONFIG_FEATURE_TAR_FROM
+ bool "Enable -X (exclude from) and -T (include from) options)"
+ default y
+ depends on BUSYBOX_CONFIG_TAR
+ help
+ If you enable this option you'll be able to specify
+ a list of files to include or exclude from an archive.
+
+config BUSYBOX_CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY
+ bool "Support for old tar header format"
+ default n
+ depends on BUSYBOX_CONFIG_TAR || BUSYBOX_CONFIG_DPKG
+ help
+ This option is required to unpack archives created in
+ the old GNU format; help to kill this old format by
+ repacking your ancient archives with the new format.
+
+config BUSYBOX_CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY
+ bool "Enable untarring of tarballs with checksums produced by buggy Sun tar"
+ default n
+ depends on BUSYBOX_CONFIG_TAR || BUSYBOX_CONFIG_DPKG
+ help
+ This option is required to unpack archives created by some old
+ version of Sun's tar (it was calculating checksum using signed
+ arithmetic). It is said to be fixed in newer Sun tar, but "old"
+ tarballs still exist.
+
+config BUSYBOX_CONFIG_FEATURE_TAR_GNU_EXTENSIONS
+ bool "Support for GNU tar extensions (long filenames)"
+ default y
+ depends on BUSYBOX_CONFIG_TAR || BUSYBOX_CONFIG_DPKG
+ help
+ With this option busybox supports GNU long filenames and
+ linknames.
+
+config BUSYBOX_CONFIG_FEATURE_TAR_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_TAR && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Enable use of long options, increases size by about 400 Bytes
+
+config BUSYBOX_CONFIG_FEATURE_TAR_TO_COMMAND
+ bool "Support for writing to an external program"
+ default n
+ depends on BUSYBOX_CONFIG_TAR && BUSYBOX_CONFIG_FEATURE_TAR_LONG_OPTIONS
+ help
+ If you enable this option you'll be able to instruct tar to send
+ the contents of each extracted file to the standard input of an
+ external program.
+
+config BUSYBOX_CONFIG_FEATURE_TAR_UNAME_GNAME
+ bool "Enable use of user and group names"
+ default n
+ depends on BUSYBOX_CONFIG_TAR
+ help
+ Enables use of user and group names in tar. This affects contents
+ listings (-t) and preserving permissions when unpacking (-p).
+ +200 bytes.
+
+config BUSYBOX_CONFIG_FEATURE_TAR_NOPRESERVE_TIME
+ bool "Enable -m (do not preserve time) option"
+ default n
+ depends on BUSYBOX_CONFIG_TAR
+ help
+ With this option busybox supports GNU tar -m
+ (do not preserve time) option.
+
+config BUSYBOX_CONFIG_FEATURE_TAR_SELINUX
+ bool "Support for extracting SELinux labels"
+ default n
+ depends on BUSYBOX_CONFIG_TAR && BUSYBOX_CONFIG_SELINUX
+ help
+ With this option busybox supports restoring SELinux labels
+ when extracting files from tar archives.
+
+config BUSYBOX_CONFIG_UNCOMPRESS
+ bool "uncompress"
+ default n
+ help
+ uncompress is used to decompress archives created by compress.
+ Not much used anymore, replaced by gzip/gunzip.
+
+config BUSYBOX_CONFIG_UNLZMA
+ bool "unlzma"
+ default n
+ help
+ unlzma is a compression utility using the Lempel-Ziv-Markov chain
+ compression algorithm, and range coding. Compression
+ is generally considerably better than that achieved by the bzip2
+ compressors.
+
+ The BusyBox unlzma applet is limited to de-compression only.
+ On an x86 system, this applet adds about 4K.
+
+ Unless you have a specific application which requires unlzma, you
+ should probably say N here.
+
+config BUSYBOX_CONFIG_FEATURE_LZMA_FAST
+ bool "Optimize unlzma for speed"
+ default n
+ depends on BUSYBOX_CONFIG_UNLZMA
+ help
+ This option reduces decompression time by about 25% at the cost of
+ a 1K bigger binary.
+
+config BUSYBOX_CONFIG_LZMA
+ bool "Provide lzma alias which supports only unpacking"
+ default n
+ depends on BUSYBOX_CONFIG_UNLZMA
+ help
+ Enable this option if you want commands like "lzma -d" to work.
+ IOW: you'll get lzma applet, but it will always require -d option.
+
+config BUSYBOX_CONFIG_UNXZ
+ bool "unxz"
+ default n
+ help
+ unxz is a unlzma successor.
+
+config BUSYBOX_CONFIG_XZ
+ bool "Provide xz alias which supports only unpacking"
+ default n
+ depends on BUSYBOX_CONFIG_UNXZ
+ help
+ Enable this option if you want commands like "xz -d" to work.
+ IOW: you'll get xz applet, but it will always require -d option.
+
+config BUSYBOX_CONFIG_UNZIP
+ bool "unzip"
+ default n
+ help
+ unzip will list or extract files from a ZIP archive,
+ commonly found on DOS/WIN systems. The default behavior
+ (with no options) is to extract the archive into the
+ current directory. Use the `-d' option to extract to a
+ directory of your choice.
+
+endmenu
diff --git a/package/busybox/config/console-tools/Config.in b/package/busybox/config/console-tools/Config.in
new file mode 100644
index 000000000..9069b0f1a
--- /dev/null
+++ b/package/busybox/config/console-tools/Config.in
@@ -0,0 +1,177 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Console Utilities"
+
+
+
+config BUSYBOX_CONFIG_CHVT
+ bool "chvt"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ This program is used to change to another terminal.
+ Example: chvt 4 (change to terminal /dev/tty4)
+
+config BUSYBOX_CONFIG_FGCONSOLE
+ bool "fgconsole"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ This program prints active (foreground) console number.
+
+config BUSYBOX_CONFIG_CLEAR
+ bool "clear"
+ default y
+ help
+ This program clears the terminal screen.
+
+config BUSYBOX_CONFIG_DEALLOCVT
+ bool "deallocvt"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ This program deallocates unused virtual consoles.
+
+config BUSYBOX_CONFIG_DUMPKMAP
+ bool "dumpkmap"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ This program dumps the kernel's keyboard translation table to
+ stdout, in binary format. You can then use loadkmap to load it.
+
+config BUSYBOX_CONFIG_KBD_MODE
+ bool "kbd_mode"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ This program reports and sets keyboard mode.
+
+config BUSYBOX_CONFIG_LOADFONT
+ bool "loadfont"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ This program loads a console font from standard input.
+
+config BUSYBOX_CONFIG_LOADKMAP
+ bool "loadkmap"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ This program loads a keyboard translation table from
+ standard input.
+
+config BUSYBOX_CONFIG_OPENVT
+ bool "openvt"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ This program is used to start a command on an unused
+ virtual terminal.
+
+config BUSYBOX_CONFIG_RESET
+ bool "reset"
+ default y
+ help
+ This program is used to reset the terminal screen, if it
+ gets messed up.
+
+config BUSYBOX_CONFIG_RESIZE
+ bool "resize"
+ default n
+ help
+ This program is used to (re)set the width and height of your current
+ terminal.
+
+config BUSYBOX_CONFIG_FEATURE_RESIZE_PRINT
+ bool "Print environment variables"
+ default n
+ depends on BUSYBOX_CONFIG_RESIZE
+ help
+ Prints the newly set size (number of columns and rows) of
+ the terminal.
+ E.g.:
+ COLUMNS=80;LINES=44;export COLUMNS LINES;
+
+config BUSYBOX_CONFIG_SETCONSOLE
+ bool "setconsole"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ This program redirects the system console to another device,
+ like the current tty while logged in via telnet.
+
+config BUSYBOX_CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_SETCONSOLE && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Support long options for the setconsole applet.
+
+config BUSYBOX_CONFIG_SETFONT
+ bool "setfont"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Allows to load console screen map. Useful for i18n.
+
+config BUSYBOX_CONFIG_FEATURE_SETFONT_TEXTUAL_MAP
+ bool "Support reading textual screen maps"
+ default n
+ depends on BUSYBOX_CONFIG_SETFONT
+ help
+ Support reading textual screen maps.
+
+config BUSYBOX_CONFIG_DEFAULT_SETFONT_DIR
+ string "Default directory for console-tools files"
+ default ""
+ depends on BUSYBOX_CONFIG_SETFONT
+ help
+ Directory to use if setfont's params are simple filenames
+ (not /path/to/file or ./file). Default is "" (no default directory).
+
+config BUSYBOX_CONFIG_SETKEYCODES
+ bool "setkeycodes"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ This program loads entries into the kernel's scancode-to-keycode
+ map, allowing unusual keyboards to generate usable keycodes.
+
+config BUSYBOX_CONFIG_SETLOGCONS
+ bool "setlogcons"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ This program redirects the output console of kernel messages.
+
+config BUSYBOX_CONFIG_SHOWKEY
+ bool "showkey"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Shows keys pressed.
+
+comment "Common options for loadfont and setfont"
+ depends on BUSYBOX_CONFIG_LOADFONT || BUSYBOX_CONFIG_SETFONT
+
+config BUSYBOX_CONFIG_FEATURE_LOADFONT_PSF2
+ bool "Support for PSF2 console fonts"
+ default n
+ depends on BUSYBOX_CONFIG_LOADFONT || BUSYBOX_CONFIG_SETFONT
+ help
+ Support PSF2 console fonts.
+
+config BUSYBOX_CONFIG_FEATURE_LOADFONT_RAW
+ bool "Support for old (raw) console fonts"
+ default n
+ depends on BUSYBOX_CONFIG_LOADFONT || BUSYBOX_CONFIG_SETFONT
+ help
+ Support old (raw) console fonts.
+
+endmenu
diff --git a/package/busybox/config/coreutils/Config.in b/package/busybox/config/coreutils/Config.in
new file mode 100644
index 000000000..08716b86f
--- /dev/null
+++ b/package/busybox/config/coreutils/Config.in
@@ -0,0 +1,913 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Coreutils"
+
+config BUSYBOX_CONFIG_BASENAME
+ bool "basename"
+ default y
+ help
+ basename is used to strip the directory and suffix from filenames,
+ leaving just the filename itself. Enable this option if you wish
+ to enable the 'basename' utility.
+config BUSYBOX_CONFIG_CAT
+ bool "cat"
+ default y
+ help
+ cat is used to concatenate files and print them to the standard
+ output. Enable this option if you wish to enable the 'cat' utility.
+config BUSYBOX_CONFIG_DATE
+ bool "date"
+ default y
+ help
+ date is used to set the system date or display the
+ current time in the given format.
+
+config BUSYBOX_CONFIG_FEATURE_DATE_ISOFMT
+ bool "Enable ISO date format output (-I)"
+ default y
+ depends on BUSYBOX_CONFIG_DATE
+ help
+ Enable option (-I) to output an ISO-8601 compliant
+ date/time string.
+
+# defaults to "no": stat's nanosecond field is a bit non-portable
+config BUSYBOX_CONFIG_FEATURE_DATE_NANO
+ bool "Support %[num]N nanosecond format specifier"
+ default n
+ depends on BUSYBOX_CONFIG_DATE # syscall(__NR_clock_gettime)
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Support %[num]N format specifier. Adds ~250 bytes of code.
+
+config BUSYBOX_CONFIG_FEATURE_DATE_COMPAT
+ bool "Support weird 'date MMDDhhmm[[YY]YY][.ss]' format"
+ default n
+ depends on BUSYBOX_CONFIG_DATE
+ help
+ System time can be set by 'date -s DATE' and simply 'date DATE',
+ but formats of DATE string are different. 'date DATE' accepts
+ a rather weird MMDDhhmm[[YY]YY][.ss] format with completely
+ unnatural placement of year between minutes and seconds.
+ date -s (and other commands like touch -d) use more sensible
+ formats (for one, ISO format YYYY-MM-DD hh:mm:ss.ssssss).
+
+ With this option off, 'date DATE' is 'date -s DATE' support
+ the same format. With it on, 'date DATE' additionally supports
+ MMDDhhmm[[YY]YY][.ss] format.
+config BUSYBOX_CONFIG_ID
+ bool "id"
+ default y
+ help
+ id displays the current user and group ID names.
+config BUSYBOX_CONFIG_GROUPS
+ bool "groups"
+ default n
+ help
+ Print the group names associated with current user id.
+config BUSYBOX_CONFIG_TEST
+ bool "test"
+ default y
+ help
+ test is used to check file types and compare values,
+ returning an appropriate exit code. The bash shell
+ has test built in, ash can build it in optionally.
+
+config BUSYBOX_CONFIG_FEATURE_TEST_64
+ bool "Extend test to 64 bit"
+ default y
+ depends on BUSYBOX_CONFIG_TEST || BUSYBOX_CONFIG_ASH_BUILTIN_TEST || BUSYBOX_CONFIG_HUSH
+ help
+ Enable 64-bit support in test.
+config BUSYBOX_CONFIG_TOUCH
+ bool "touch"
+ default y
+ help
+ touch is used to create or change the access and/or
+ modification timestamp of specified files.
+config BUSYBOX_CONFIG_TR
+ bool "tr"
+ default y
+ help
+ tr is used to squeeze, and/or delete characters from standard
+ input, writing to standard output.
+
+config BUSYBOX_CONFIG_FEATURE_TR_CLASSES
+ bool "Enable character classes (such as [:upper:])"
+ default n
+ depends on BUSYBOX_CONFIG_TR
+ help
+ Enable character classes, enabling commands such as:
+ tr [:upper:] [:lower:] to convert input into lowercase.
+
+config BUSYBOX_CONFIG_FEATURE_TR_EQUIV
+ bool "Enable equivalence classes"
+ default n
+ depends on BUSYBOX_CONFIG_TR
+ help
+ Enable equivalence classes, which essentially add the enclosed
+ character to the current set. For instance, tr [=a=] xyz would
+ replace all instances of 'a' with 'xyz'. This option is mainly
+ useful for cases when no other way of expressing a character
+ is possible.
+config BUSYBOX_CONFIG_BASE64
+ bool "base64"
+ default n
+ help
+ Base64 encode and decode
+config BUSYBOX_CONFIG_WHO
+ bool "who"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_UTMP
+ help
+ who is used to show who is logged on.
+config BUSYBOX_CONFIG_USERS
+ bool "users"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_UTMP
+ help
+ Print users currently logged on.
+
+config BUSYBOX_CONFIG_CAL
+ bool "cal"
+ default n
+ help
+ cal is used to display a monthly calender.
+
+config BUSYBOX_CONFIG_CATV
+ bool "catv"
+ default n
+ help
+ Display nonprinting characters as escape sequences (like some
+ implementations' cat -v option).
+
+config BUSYBOX_CONFIG_CHGRP
+ bool "chgrp"
+ default y
+ help
+ chgrp is used to change the group ownership of files.
+
+config BUSYBOX_CONFIG_CHMOD
+ bool "chmod"
+ default y
+ help
+ chmod is used to change the access permission of files.
+
+config BUSYBOX_CONFIG_CHOWN
+ bool "chown"
+ default y
+ help
+ chown is used to change the user and/or group ownership
+ of files.
+
+config BUSYBOX_CONFIG_FEATURE_CHOWN_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_CHOWN && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Enable use of long options
+
+config BUSYBOX_CONFIG_CHROOT
+ bool "chroot"
+ default y
+ help
+ chroot is used to change the root directory and run a command.
+ The default command is `/bin/sh'.
+
+config BUSYBOX_CONFIG_CKSUM
+ bool "cksum"
+ default n
+ help
+ cksum is used to calculate the CRC32 checksum of a file.
+
+config BUSYBOX_CONFIG_COMM
+ bool "comm"
+ default n
+ help
+ comm is used to compare two files line by line and return
+ a three-column output.
+
+config BUSYBOX_CONFIG_CP
+ bool "cp"
+ default y
+ help
+ cp is used to copy files and directories.
+
+config BUSYBOX_CONFIG_FEATURE_CP_LONG_OPTIONS
+ bool "Enable long options for cp"
+ default n
+ depends on BUSYBOX_CONFIG_CP && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Enable long options for cp.
+ Also add support for --parents option.
+
+config BUSYBOX_CONFIG_CUT
+ bool "cut"
+ default y
+ help
+ cut is used to print selected parts of lines from
+ each file to stdout.
+
+config BUSYBOX_CONFIG_DD
+ bool "dd"
+ default y
+ help
+ dd copies a file (from standard input to standard output,
+ by default) using specific input and output blocksizes,
+ while optionally performing conversions on it.
+
+config BUSYBOX_CONFIG_FEATURE_DD_SIGNAL_HANDLING
+ bool "Enable DD signal handling for status reporting"
+ default y
+ depends on BUSYBOX_CONFIG_DD
+ help
+ Sending a SIGUSR1 signal to a running `dd' process makes it
+ print to standard error the number of records read and written
+ so far, then to resume copying.
+
+ $ dd if=/dev/zero of=/dev/null&
+ $ pid=$! kill -USR1 $pid; sleep 1; kill $pid
+ 10899206+0 records in
+ 10899206+0 records out
+
+config BUSYBOX_CONFIG_FEATURE_DD_THIRD_STATUS_LINE
+ bool "Enable the third status line upon signal"
+ default n
+ depends on BUSYBOX_CONFIG_DD && BUSYBOX_CONFIG_FEATURE_DD_SIGNAL_HANDLING
+ help
+ Displays a coreutils-like third status line with transferred bytes,
+ elapsed time and speed.
+
+config BUSYBOX_CONFIG_FEATURE_DD_IBS_OBS
+ bool "Enable ibs, obs and conv options"
+ default y
+ depends on BUSYBOX_CONFIG_DD
+ help
+ Enables support for writing a certain number of bytes in and out,
+ at a time, and performing conversions on the data stream.
+
+config BUSYBOX_CONFIG_DF
+ bool "df"
+ default y
+ help
+ df reports the amount of disk space used and available
+ on filesystems.
+
+config BUSYBOX_CONFIG_FEATURE_DF_FANCY
+ bool "Enable -a, -i, -B"
+ default n
+ depends on BUSYBOX_CONFIG_DF
+ help
+ This option enables -a, -i and -B.
+
+ -a Show all filesystems
+ -i Inodes
+ -B <SIZE> Blocksize
+
+config BUSYBOX_CONFIG_DIRNAME
+ bool "dirname"
+ default y
+ help
+ dirname is used to strip a non-directory suffix from
+ a file name.
+
+config BUSYBOX_CONFIG_DOS2UNIX
+ bool "dos2unix/unix2dos"
+ default n
+ help
+ dos2unix is used to convert a text file from DOS format to
+ UNIX format, and vice versa.
+
+config BUSYBOX_CONFIG_UNIX2DOS
+ bool
+ default n
+ depends on BUSYBOX_CONFIG_DOS2UNIX
+ help
+ unix2dos is used to convert a text file from UNIX format to
+ DOS format, and vice versa.
+
+config BUSYBOX_CONFIG_DU
+ bool "du (default blocksize of 512 bytes)"
+ default y
+ help
+ du is used to report the amount of disk space used
+ for specified files.
+
+config BUSYBOX_CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K
+ bool "Use a default blocksize of 1024 bytes (1K)"
+ default y
+ depends on BUSYBOX_CONFIG_DU
+ help
+ Use a blocksize of (1K) instead of the default 512b.
+
+config BUSYBOX_CONFIG_ECHO
+ bool "echo (basic SuSv3 version taking no options)"
+ default y
+ help
+ echo is used to print a specified string to stdout.
+
+# this entry also appears in shell/Config.in, next to the echo builtin
+config BUSYBOX_CONFIG_FEATURE_FANCY_ECHO
+ bool "Enable echo options (-n and -e)"
+ default y
+ depends on BUSYBOX_CONFIG_ECHO || BUSYBOX_CONFIG_ASH_BUILTIN_ECHO || BUSYBOX_CONFIG_HUSH
+ help
+ This adds options (-n and -e) to echo.
+
+config BUSYBOX_CONFIG_ENV
+ bool "env"
+ default y
+ help
+ env is used to set an environment variable and run
+ a command; without options it displays the current
+ environment.
+
+config BUSYBOX_CONFIG_FEATURE_ENV_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_ENV && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Support long options for the env applet.
+
+config BUSYBOX_CONFIG_EXPAND
+ bool "expand"
+ default n
+ help
+ By default, convert all tabs to spaces.
+
+config BUSYBOX_CONFIG_FEATURE_EXPAND_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_EXPAND && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Support long options for the expand applet.
+
+config BUSYBOX_CONFIG_EXPR
+ bool "expr"
+ default y
+ help
+ expr is used to calculate numbers and print the result
+ to standard output.
+
+config BUSYBOX_CONFIG_EXPR_MATH_SUPPORT_64
+ bool "Extend Posix numbers support to 64 bit"
+ default y
+ depends on BUSYBOX_CONFIG_EXPR
+ help
+ Enable 64-bit math support in the expr applet. This will make
+ the applet slightly larger, but will allow computation with very
+ large numbers.
+
+config BUSYBOX_CONFIG_FALSE
+ bool "false"
+ default y
+ help
+ false returns an exit code of FALSE (1).
+
+config BUSYBOX_CONFIG_FOLD
+ bool "fold"
+ default n
+ help
+ Wrap text to fit a specific width.
+
+config BUSYBOX_CONFIG_FSYNC
+ bool "fsync"
+ default y
+ help
+ fsync is used to flush file-related cached blocks to disk.
+
+config BUSYBOX_CONFIG_HEAD
+ bool "head"
+ default y
+ help
+ head is used to print the first specified number of lines
+ from files.
+
+config BUSYBOX_CONFIG_FEATURE_FANCY_HEAD
+ bool "Enable head options (-c, -q, and -v)"
+ default y
+ depends on BUSYBOX_CONFIG_HEAD
+ help
+ This enables the head options (-c, -q, and -v).
+
+config BUSYBOX_CONFIG_HOSTID
+ bool "hostid"
+ default y
+ help
+ hostid prints the numeric identifier (in hexadecimal) for
+ the current host.
+
+config BUSYBOX_CONFIG_INSTALL
+ bool "install"
+ default n
+ help
+ Copy files and set attributes.
+
+config BUSYBOX_CONFIG_FEATURE_INSTALL_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_INSTALL && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Support long options for the install applet.
+
+####config LENGTH
+#### bool "length"
+#### default y
+#### help
+#### length is used to print out the length of a specified string.
+
+config BUSYBOX_CONFIG_LN
+ bool "ln"
+ default y
+ help
+ ln is used to create hard or soft links between files.
+
+config BUSYBOX_CONFIG_LOGNAME
+ bool "logname"
+ default n
+ help
+ logname is used to print the current user's login name.
+
+config BUSYBOX_CONFIG_LS
+ bool "ls"
+ default y
+ help
+ ls is used to list the contents of directories.
+
+config BUSYBOX_CONFIG_FEATURE_LS_FILETYPES
+ bool "Enable filetyping options (-p and -F)"
+ default y
+ depends on BUSYBOX_CONFIG_LS
+ help
+ Enable the ls options (-p and -F).
+
+config BUSYBOX_CONFIG_FEATURE_LS_FOLLOWLINKS
+ bool "Enable symlinks dereferencing (-L)"
+ default y
+ depends on BUSYBOX_CONFIG_LS
+ help
+ Enable the ls option (-L).
+
+config BUSYBOX_CONFIG_FEATURE_LS_RECURSIVE
+ bool "Enable recursion (-R)"
+ default y
+ depends on BUSYBOX_CONFIG_LS
+ help
+ Enable the ls option (-R).
+
+config BUSYBOX_CONFIG_FEATURE_LS_SORTFILES
+ bool "Sort the file names"
+ default y
+ depends on BUSYBOX_CONFIG_LS
+ help
+ Allow ls to sort file names alphabetically.
+
+config BUSYBOX_CONFIG_FEATURE_LS_TIMESTAMPS
+ bool "Show file timestamps"
+ default y
+ depends on BUSYBOX_CONFIG_LS
+ help
+ Allow ls to display timestamps for files.
+
+config BUSYBOX_CONFIG_FEATURE_LS_USERNAME
+ bool "Show username/groupnames"
+ default y
+ depends on BUSYBOX_CONFIG_LS
+ help
+ Allow ls to display username/groupname for files.
+
+config BUSYBOX_CONFIG_FEATURE_LS_COLOR
+ bool "Allow use of color to identify file types"
+ default y
+ depends on BUSYBOX_CONFIG_LS && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ This enables the --color option to ls.
+
+config BUSYBOX_CONFIG_FEATURE_LS_COLOR_IS_DEFAULT
+ bool "Produce colored ls output by default"
+ default y
+ depends on BUSYBOX_CONFIG_FEATURE_LS_COLOR
+ help
+ Saying yes here will turn coloring on by default,
+ even if no "--color" option is given to the ls command.
+ This is not recommended, since the colors are not
+ configurable, and the output may not be legible on
+ many output screens.
+
+config BUSYBOX_CONFIG_MD5SUM
+ bool "md5sum"
+ default y
+ help
+ md5sum is used to print or check MD5 checksums.
+
+config BUSYBOX_CONFIG_MKDIR
+ bool "mkdir"
+ default y
+ help
+ mkdir is used to create directories with the specified names.
+
+config BUSYBOX_CONFIG_FEATURE_MKDIR_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_MKDIR && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Support long options for the mkdir applet.
+
+config BUSYBOX_CONFIG_MKFIFO
+ bool "mkfifo"
+ default y
+ help
+ mkfifo is used to create FIFOs (named pipes).
+ The `mknod' program can also create FIFOs.
+
+config BUSYBOX_CONFIG_MKNOD
+ bool "mknod"
+ default y
+ help
+ mknod is used to create FIFOs or block/character special
+ files with the specified names.
+
+config BUSYBOX_CONFIG_MV
+ bool "mv"
+ default y
+ help
+ mv is used to move or rename files or directories.
+
+config BUSYBOX_CONFIG_FEATURE_MV_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_MV && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Support long options for the mv applet.
+
+config BUSYBOX_CONFIG_NICE
+ bool "nice"
+ default y
+ help
+ nice runs a program with modified scheduling priority.
+
+config BUSYBOX_CONFIG_NOHUP
+ bool "nohup"
+ default n
+ help
+ run a command immune to hangups, with output to a non-tty.
+
+config BUSYBOX_CONFIG_OD
+ bool "od"
+ default n
+ help
+ od is used to dump binary files in octal and other formats.
+
+config BUSYBOX_CONFIG_PRINTENV
+ bool "printenv"
+ default n
+ help
+ printenv is used to print all or part of environment.
+
+config BUSYBOX_CONFIG_PRINTF
+ bool "printf"
+ default y
+ help
+ printf is used to format and print specified strings.
+ It's similar to `echo' except it has more options.
+
+config BUSYBOX_CONFIG_PWD
+ bool "pwd"
+ default y
+ help
+ pwd is used to print the current directory.
+
+config BUSYBOX_CONFIG_READLINK
+ bool "readlink"
+ default n
+ help
+ This program reads a symbolic link and returns the name
+ of the file it points to
+
+config BUSYBOX_CONFIG_FEATURE_READLINK_FOLLOW
+ bool "Enable canonicalization by following all symlinks (-f)"
+ default n
+ depends on BUSYBOX_CONFIG_READLINK
+ help
+ Enable the readlink option (-f).
+
+config BUSYBOX_CONFIG_REALPATH
+ bool "realpath"
+ default n
+ help
+ Return the canonicalized absolute pathname.
+ This isn't provided by GNU shellutils, but where else does it belong.
+
+config BUSYBOX_CONFIG_RM
+ bool "rm"
+ default y
+ help
+ rm is used to remove files or directories.
+
+config BUSYBOX_CONFIG_RMDIR
+ bool "rmdir"
+ default y
+ help
+ rmdir is used to remove empty directories.
+
+config BUSYBOX_CONFIG_FEATURE_RMDIR_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_RMDIR && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Support long options for the rmdir applet, including
+ --ignore-fail-on-non-empty for compatibility with GNU rmdir.
+
+config BUSYBOX_CONFIG_SEQ
+ bool "seq"
+ default y
+ help
+ print a sequence of numbers
+
+config BUSYBOX_CONFIG_SHA1SUM
+ bool "sha1sum"
+ default n
+ help
+ Compute and check SHA1 message digest
+
+config BUSYBOX_CONFIG_SHA256SUM
+ bool "sha256sum"
+ default n
+ help
+ Compute and check SHA256 message digest
+
+config BUSYBOX_CONFIG_SHA512SUM
+ bool "sha512sum"
+ default n
+ help
+ Compute and check SHA512 message digest
+
+config BUSYBOX_CONFIG_SLEEP
+ bool "sleep"
+ default y
+ help
+ sleep is used to pause for a specified number of seconds.
+ It comes in 3 versions:
+ - small: takes one integer parameter
+ - fancy: takes multiple integer arguments with suffixes:
+ sleep 1d 2h 3m 15s
+ - fancy with fractional numbers:
+ sleep 2.3s 4.5h sleeps for 16202.3 seconds
+ Last one is "the most compatible" with coreutils sleep,
+ but it adds around 1k of code.
+
+config BUSYBOX_CONFIG_FEATURE_FANCY_SLEEP
+ bool "Enable multiple arguments and s/m/h/d suffixes"
+ default y
+ depends on BUSYBOX_CONFIG_SLEEP
+ help
+ Allow sleep to pause for specified minutes, hours, and days.
+
+config BUSYBOX_CONFIG_FEATURE_FLOAT_SLEEP
+ bool "Enable fractional arguments"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_FANCY_SLEEP
+ help
+ Allow for fractional numeric parameters.
+
+config BUSYBOX_CONFIG_SORT
+ bool "sort"
+ default y
+ help
+ sort is used to sort lines of text in specified files.
+
+config BUSYBOX_CONFIG_FEATURE_SORT_BIG
+ bool "Full SuSv3 compliant sort (support -ktcsbdfiozgM)"
+ default n
+ depends on BUSYBOX_CONFIG_SORT
+ help
+ Without this, sort only supports -r, -u, and an integer version
+ of -n. Selecting this adds sort keys, floating point support, and
+ more. This adds a little over 3k to a nonstatic build on x86.
+
+ The SuSv3 sort standard is available at:
+ http://www.opengroup.org/onlinepubs/007904975/utilities/sort.html
+
+config BUSYBOX_CONFIG_SPLIT
+ bool "split"
+ default n
+ help
+ split a file into pieces.
+
+config BUSYBOX_CONFIG_FEATURE_SPLIT_FANCY
+ bool "Fancy extensions"
+ default n
+ depends on BUSYBOX_CONFIG_SPLIT
+ help
+ Add support for features not required by SUSv3.
+ Supports additional suffixes 'b' for 512 bytes,
+ 'g' for 1GiB for the -b option.
+
+config BUSYBOX_CONFIG_STAT
+ bool "stat"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX # statfs()
+ help
+ display file or filesystem status.
+
+config BUSYBOX_CONFIG_FEATURE_STAT_FORMAT
+ bool "Enable custom formats (-c)"
+ default n
+ depends on BUSYBOX_CONFIG_STAT
+ help
+ Without this, stat will not support the '-c format' option where
+ users can pass a custom format string for output. This adds about
+ 7k to a nonstatic build on amd64.
+
+config BUSYBOX_CONFIG_STTY
+ bool "stty"
+ default n
+ help
+ stty is used to change and print terminal line settings.
+
+config BUSYBOX_CONFIG_SUM
+ bool "sum"
+ default n
+ help
+ checksum and count the blocks in a file
+
+config BUSYBOX_CONFIG_SYNC
+ bool "sync"
+ default y
+ help
+ sync is used to flush filesystem buffers.
+
+config BUSYBOX_CONFIG_TAC
+ bool "tac"
+ default n
+ help
+ tac is used to concatenate and print files in reverse.
+
+config BUSYBOX_CONFIG_TAIL
+ bool "tail"
+ default y
+ help
+ tail is used to print the last specified number of lines
+ from files.
+
+config BUSYBOX_CONFIG_FEATURE_FANCY_TAIL
+ bool "Enable extra tail options (-q, -s, -v, and -F)"
+ default y
+ depends on BUSYBOX_CONFIG_TAIL
+ help
+ The options (-q, -s, and -v) are provided by GNU tail, but
+ are not specific in the SUSv3 standard.
+
+ -q Never output headers giving file names
+ -s SEC Wait SEC seconds between reads with -f
+ -v Always output headers giving file names
+
+config BUSYBOX_CONFIG_TEE
+ bool "tee"
+ default y
+ help
+ tee is used to read from standard input and write
+ to standard output and files.
+
+config BUSYBOX_CONFIG_FEATURE_TEE_USE_BLOCK_IO
+ bool "Enable block I/O (larger/faster) instead of byte I/O"
+ default y
+ depends on BUSYBOX_CONFIG_TEE
+ help
+ Enable this option for a faster tee, at expense of size.
+
+config BUSYBOX_CONFIG_TRUE
+ bool "true"
+ default y
+ help
+ true returns an exit code of TRUE (0).
+
+config BUSYBOX_CONFIG_TTY
+ bool "tty"
+ default n
+ help
+ tty is used to print the name of the current terminal to
+ standard output.
+
+config BUSYBOX_CONFIG_UNAME
+ bool "uname"
+ default y
+ help
+ uname is used to print system information.
+
+config BUSYBOX_CONFIG_UNEXPAND
+ bool "unexpand"
+ default n
+ help
+ By default, convert only leading sequences of blanks to tabs.
+
+config BUSYBOX_CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_UNEXPAND && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Support long options for the unexpand applet.
+
+config BUSYBOX_CONFIG_UNIQ
+ bool "uniq"
+ default y
+ help
+ uniq is used to remove duplicate lines from a sorted file.
+
+config BUSYBOX_CONFIG_USLEEP
+ bool "usleep"
+ default n
+ help
+ usleep is used to pause for a specified number of microseconds.
+
+config BUSYBOX_CONFIG_UUDECODE
+ bool "uudecode"
+ default n
+ help
+ uudecode is used to decode a uuencoded file.
+
+config BUSYBOX_CONFIG_UUENCODE
+ bool "uuencode"
+ default n
+ help
+ uuencode is used to uuencode a file.
+
+config BUSYBOX_CONFIG_WC
+ bool "wc"
+ default y
+ help
+ wc is used to print the number of bytes, words, and lines,
+ in specified files.
+
+config BUSYBOX_CONFIG_FEATURE_WC_LARGE
+ bool "Support very large files in wc"
+ default n
+ depends on BUSYBOX_CONFIG_WC
+ help
+ Use "unsigned long long" in wc for counter variables.
+
+config BUSYBOX_CONFIG_WHOAMI
+ bool "whoami"
+ default n
+ help
+ whoami is used to print the username of the current
+ user id (same as id -un).
+
+config BUSYBOX_CONFIG_YES
+ bool "yes"
+ default y
+ help
+ yes is used to repeatedly output a specific string, or
+ the default string `y'.
+
+comment "Common options for cp and mv"
+ depends on BUSYBOX_CONFIG_CP || BUSYBOX_CONFIG_MV
+
+config BUSYBOX_CONFIG_FEATURE_PRESERVE_HARDLINKS
+ bool "Preserve hard links"
+ default y
+ depends on BUSYBOX_CONFIG_CP || BUSYBOX_CONFIG_MV
+ help
+ Allow cp and mv to preserve hard links.
+
+comment "Common options for ls, more and telnet"
+ depends on BUSYBOX_CONFIG_LS || BUSYBOX_CONFIG_MORE || BUSYBOX_CONFIG_TELNET
+
+config BUSYBOX_CONFIG_FEATURE_AUTOWIDTH
+ bool "Calculate terminal & column widths"
+ default y
+ depends on BUSYBOX_CONFIG_LS || BUSYBOX_CONFIG_MORE || BUSYBOX_CONFIG_TELNET
+ help
+ This option allows utilities such as 'ls', 'more' and 'telnet'
+ to determine the width of the screen, which can allow them to
+ display additional text or avoid wrapping text onto the next line.
+ If you leave this disabled, your utilities will be especially
+ primitive and will be unable to determine the current screen width.
+
+comment "Common options for df, du, ls"
+ depends on BUSYBOX_CONFIG_DF || BUSYBOX_CONFIG_DU || BUSYBOX_CONFIG_LS
+
+config BUSYBOX_CONFIG_FEATURE_HUMAN_READABLE
+ bool "Support for human readable output (example 13k, 23M, 235G)"
+ default y
+ depends on BUSYBOX_CONFIG_DF || BUSYBOX_CONFIG_DU || BUSYBOX_CONFIG_LS
+ help
+ Allow df, du, and ls to have human readable output.
+
+comment "Common options for md5sum, sha1sum, sha256sum, sha512sum"
+ depends on BUSYBOX_CONFIG_MD5SUM || BUSYBOX_CONFIG_SHA1SUM || BUSYBOX_CONFIG_SHA256SUM || BUSYBOX_CONFIG_SHA512SUM
+
+config BUSYBOX_CONFIG_FEATURE_MD5_SHA1_SUM_CHECK
+ bool "Enable -c, -s and -w options"
+ default y
+ depends on BUSYBOX_CONFIG_MD5SUM || BUSYBOX_CONFIG_SHA1SUM || BUSYBOX_CONFIG_SHA256SUM || BUSYBOX_CONFIG_SHA512SUM
+ help
+ Enabling the -c options allows files to be checked
+ against pre-calculated hash values.
+
+ -s and -w are useful options when verifying checksums.
+
+endmenu
diff --git a/package/busybox/config/debianutils/Config.in b/package/busybox/config/debianutils/Config.in
new file mode 100644
index 000000000..be69666ff
--- /dev/null
+++ b/package/busybox/config/debianutils/Config.in
@@ -0,0 +1,86 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Debian Utilities"
+
+
+
+config BUSYBOX_CONFIG_MKTEMP
+ bool "mktemp"
+ default y
+ help
+ mktemp is used to create unique temporary files
+
+config BUSYBOX_CONFIG_PIPE_PROGRESS
+ bool "pipe_progress"
+ default n
+ help
+ Display a dot to indicate pipe activity.
+
+config BUSYBOX_CONFIG_RUN_PARTS
+ bool "run-parts"
+ default n
+ help
+ run-parts is a utility designed to run all the scripts in a directory.
+
+ It is useful to set up a directory like cron.daily, where you need to
+ execute all the scripts in that directory.
+
+ In this implementation of run-parts some features (such as report
+ mode) are not implemented.
+
+ Unless you know that run-parts is used in some of your scripts
+ you can safely say N here.
+
+config BUSYBOX_CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_RUN_PARTS && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Support long options for the run-parts applet.
+
+config BUSYBOX_CONFIG_FEATURE_RUN_PARTS_FANCY
+ bool "Support additional arguments"
+ default n
+ depends on BUSYBOX_CONFIG_RUN_PARTS
+ help
+ Support additional options:
+ -l --list print the names of the all matching files (not
+ limited to executables), but don't actually run them.
+
+config BUSYBOX_CONFIG_START_STOP_DAEMON
+ bool "start-stop-daemon"
+ default y
+ help
+ start-stop-daemon is used to control the creation and
+ termination of system-level processes, usually the ones
+ started during the startup of the system.
+
+config BUSYBOX_CONFIG_FEATURE_START_STOP_DAEMON_FANCY
+ bool "Support additional arguments"
+ default n
+ depends on BUSYBOX_CONFIG_START_STOP_DAEMON
+ help
+ Support additional arguments.
+ -o|--oknodo ignored since we exit with 0 anyway
+ -v|--verbose
+ -N|--nicelevel N
+
+config BUSYBOX_CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_START_STOP_DAEMON && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Support long options for the start-stop-daemon applet.
+
+config BUSYBOX_CONFIG_WHICH
+ bool "which"
+ default y
+ help
+ which is used to find programs in your PATH and
+ print out their pathnames.
+
+endmenu
diff --git a/package/busybox/config/e2fsprogs/Config.in b/package/busybox/config/e2fsprogs/Config.in
new file mode 100644
index 000000000..282681db0
--- /dev/null
+++ b/package/busybox/config/e2fsprogs/Config.in
@@ -0,0 +1,72 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Linux Ext2 FS Progs"
+
+
+
+config BUSYBOX_CONFIG_CHATTR
+ bool "chattr"
+ default n
+ help
+ chattr changes the file attributes on a second extended file system.
+
+### config E2FSCK
+### bool "e2fsck"
+### default y
+### help
+### e2fsck is used to check Linux second extended file systems (ext2fs).
+### e2fsck also supports ext2 filesystems countaining a journal (ext3).
+### The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also
+### provided.
+
+config BUSYBOX_CONFIG_FSCK
+ bool "fsck"
+ default n
+ help
+ fsck is used to check and optionally repair one or more filesystems.
+ In actuality, fsck is simply a front-end for the various file system
+ checkers (fsck.fstype) available under Linux.
+
+config BUSYBOX_CONFIG_LSATTR
+ bool "lsattr"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ lsattr lists the file attributes on a second extended file system.
+
+### config MKE2FS
+### bool "mke2fs"
+### default y
+### help
+### mke2fs is used to create an ext2/ext3 filesystem. The normal compat
+### symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided.
+
+config BUSYBOX_CONFIG_TUNE2FS
+ bool "tune2fs"
+ default n # off: it is too limited compared to upstream version
+ help
+ tune2fs allows the system administrator to adjust various tunable
+ filesystem parameters on Linux ext2/ext3 filesystems.
+
+### config E2LABEL
+### bool "e2label"
+### default y
+### depends on TUNE2FS
+### help
+### e2label will display or change the filesystem label on the ext2
+### filesystem located on device.
+
+### NB: this one is now provided by util-linux/volume_id/*
+### config FINDFS
+### bool "findfs"
+### default y
+### depends on TUNE2FS
+### help
+### findfs will search the disks in the system looking for a filesystem
+### which has a label matching label or a UUID equal to uuid.
+
+endmenu
diff --git a/package/busybox/config/e2fsprogs/old_e2fsprogs/Config.in b/package/busybox/config/e2fsprogs/old_e2fsprogs/Config.in
new file mode 100644
index 000000000..105c93a56
--- /dev/null
+++ b/package/busybox/config/e2fsprogs/old_e2fsprogs/Config.in
@@ -0,0 +1,70 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Linux Ext2 FS Progs"
+
+
+
+config BUSYBOX_CONFIG_CHATTR
+ bool "chattr"
+ default n
+ help
+ chattr changes the file attributes on a second extended file system.
+
+config BUSYBOX_CONFIG_E2FSCK
+ bool "e2fsck"
+ default n
+ help
+ e2fsck is used to check Linux second extended file systems (ext2fs).
+ e2fsck also supports ext2 filesystems countaining a journal (ext3).
+ The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also
+ provided.
+
+config BUSYBOX_CONFIG_FSCK
+ bool "fsck"
+ default n
+ help
+ fsck is used to check and optionally repair one or more filesystems.
+ In actuality, fsck is simply a front-end for the various file system
+ checkers (fsck.fstype) available under Linux.
+
+config BUSYBOX_CONFIG_LSATTR
+ bool "lsattr"
+ default n
+ help
+ lsattr lists the file attributes on a second extended file system.
+
+config BUSYBOX_CONFIG_MKE2FS
+ bool "mke2fs"
+ default n
+ help
+ mke2fs is used to create an ext2/ext3 filesystem. The normal compat
+ symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided.
+
+config BUSYBOX_CONFIG_TUNE2FS
+ bool "tune2fs"
+ default n
+ help
+ tune2fs allows the system administrator to adjust various tunable
+ filesystem parameters on Linux ext2/ext3 filesystems.
+
+config BUSYBOX_CONFIG_E2LABEL
+ bool "e2label"
+ default n
+ depends on BUSYBOX_CONFIG_TUNE2FS
+ help
+ e2label will display or change the filesystem label on the ext2
+ filesystem located on device.
+
+config BUSYBOX_CONFIG_FINDFS
+ bool "findfs"
+ default n
+ depends on BUSYBOX_CONFIG_TUNE2FS
+ help
+ findfs will search the disks in the system looking for a filesystem
+ which has a label matching label or a UUID equal to uuid.
+
+endmenu
diff --git a/package/busybox/config/editors/Config.in b/package/busybox/config/editors/Config.in
new file mode 100644
index 000000000..21321dbb0
--- /dev/null
+++ b/package/busybox/config/editors/Config.in
@@ -0,0 +1,206 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Editors"
+
+config BUSYBOX_CONFIG_PATCH
+ bool "patch"
+ default n
+ help
+ Apply a unified diff formatted patch.
+config BUSYBOX_CONFIG_VI
+ bool "vi"
+ default y
+ help
+ 'vi' is a text editor. More specifically, it is the One True
+ text editor <grin>. It does, however, have a rather steep
+ learning curve. If you are not already comfortable with 'vi'
+ you may wish to use something else.
+
+config BUSYBOX_CONFIG_FEATURE_VI_MAX_LEN
+ int "Maximum screen width in vi"
+ range 256 16384
+ default 1024
+ depends on BUSYBOX_CONFIG_VI
+ help
+ Contrary to what you may think, this is not eating much.
+ Make it smaller than 4k only if you are very limited on memory.
+
+config BUSYBOX_CONFIG_FEATURE_VI_8BIT
+ bool "Allow vi to display 8-bit chars (otherwise shows dots)"
+ default n
+ depends on BUSYBOX_CONFIG_VI
+ help
+ If your terminal can display characters with high bit set,
+ you may want to enable this. Note: vi is not Unicode-capable.
+ If your terminal combines several 8-bit bytes into one character
+ (as in Unicode mode), this will not work properly.
+
+config BUSYBOX_CONFIG_FEATURE_VI_COLON
+ bool "Enable \":\" colon commands (no \"ex\" mode)"
+ default y
+ depends on BUSYBOX_CONFIG_VI
+ help
+ Enable a limited set of colon commands for vi. This does not
+ provide an "ex" mode.
+
+config BUSYBOX_CONFIG_FEATURE_VI_YANKMARK
+ bool "Enable yank/put commands and mark cmds"
+ default y
+ depends on BUSYBOX_CONFIG_VI
+ help
+ This will enable you to use yank and put, as well as mark in
+ busybox vi.
+
+config BUSYBOX_CONFIG_FEATURE_VI_SEARCH
+ bool "Enable search and replace cmds"
+ default y
+ depends on BUSYBOX_CONFIG_VI
+ help
+ Select this if you wish to be able to do search and replace in
+ busybox vi.
+
+config BUSYBOX_CONFIG_FEATURE_VI_REGEX_SEARCH
+ bool "Enable regex in search and replace"
+ default n # Uses GNU regex, which may be unavailable. FIXME
+ depends on BUSYBOX_CONFIG_FEATURE_VI_SEARCH
+ help
+ Use extended regex search.
+
+config BUSYBOX_CONFIG_FEATURE_VI_USE_SIGNALS
+ bool "Catch signals"
+ default y
+ depends on BUSYBOX_CONFIG_VI
+ help
+ Selecting this option will make busybox vi signal aware. This will
+ make busybox vi support SIGWINCH to deal with Window Changes, catch
+ Ctrl-Z and Ctrl-C and alarms.
+
+config BUSYBOX_CONFIG_FEATURE_VI_DOT_CMD
+ bool "Remember previous cmd and \".\" cmd"
+ default y
+ depends on BUSYBOX_CONFIG_VI
+ help
+ Make busybox vi remember the last command and be able to repeat it.
+
+config BUSYBOX_CONFIG_FEATURE_VI_READONLY
+ bool "Enable -R option and \"view\" mode"
+ default y
+ depends on BUSYBOX_CONFIG_VI
+ help
+ Enable the read-only command line option, which allows the user to
+ open a file in read-only mode.
+
+config BUSYBOX_CONFIG_FEATURE_VI_SETOPTS
+ bool "Enable set-able options, ai ic showmatch"
+ default y
+ depends on BUSYBOX_CONFIG_VI
+ help
+ Enable the editor to set some (ai, ic, showmatch) options.
+
+config BUSYBOX_CONFIG_FEATURE_VI_SET
+ bool "Support for :set"
+ default y
+ depends on BUSYBOX_CONFIG_VI
+ help
+ Support for ":set".
+
+config BUSYBOX_CONFIG_FEATURE_VI_WIN_RESIZE
+ bool "Handle window resize"
+ default y
+ depends on BUSYBOX_CONFIG_VI
+ help
+ Make busybox vi behave nicely with terminals that get resized.
+
+config BUSYBOX_CONFIG_FEATURE_VI_ASK_TERMINAL
+ bool "Use 'tell me cursor position' ESC sequence to measure window"
+ default y
+ depends on BUSYBOX_CONFIG_VI
+ help
+ If terminal size can't be retrieved and $LINES/$COLUMNS are not set,
+ this option makes vi perform a last-ditch effort to find it:
+ position cursor to 999,999 and ask terminal to report real
+ cursor position using "ESC [ 6 n" escape sequence, then read stdin.
+
+ This is not clean but helps a lot on serial lines and such.
+
+config BUSYBOX_CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
+ bool "Optimize cursor movement"
+ default y
+ depends on BUSYBOX_CONFIG_VI
+ help
+ This will make the cursor movement faster, but requires more memory
+ and it makes the applet a tiny bit larger.
+
+config BUSYBOX_CONFIG_AWK
+ bool "awk"
+ default y
+ help
+ Awk is used as a pattern scanning and processing language. This is
+ the BusyBox implementation of that programming language.
+
+config BUSYBOX_CONFIG_FEATURE_AWK_LIBM
+ bool "Enable math functions (requires libm)"
+ default y
+ depends on BUSYBOX_CONFIG_AWK
+ help
+ Enable math functions of the Awk programming language.
+ NOTE: This will require libm to be present for linking.
+
+config BUSYBOX_CONFIG_CMP
+ bool "cmp"
+ default y
+ help
+ cmp is used to compare two files and returns the result
+ to standard output.
+
+config BUSYBOX_CONFIG_DIFF
+ bool "diff"
+ default n
+ help
+ diff compares two files or directories and outputs the
+ differences between them in a form that can be given to
+ the patch command.
+
+config BUSYBOX_CONFIG_FEATURE_DIFF_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_DIFF && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Enable use of long options.
+
+config BUSYBOX_CONFIG_FEATURE_DIFF_DIR
+ bool "Enable directory support"
+ default n
+ depends on BUSYBOX_CONFIG_DIFF
+ help
+ This option enables support for directory and subdirectory
+ comparison.
+
+config BUSYBOX_CONFIG_ED
+ bool "ed"
+ default n
+ help
+ The original 1970's Unix text editor, from the days of teletypes.
+ Small, simple, evil. Part of SUSv3. If you're not already using
+ this, you don't need it.
+
+config BUSYBOX_CONFIG_SED
+ bool "sed"
+ default y
+ help
+ sed is used to perform text transformations on a file
+ or input from a pipeline.
+
+config BUSYBOX_CONFIG_FEATURE_ALLOW_EXEC
+ bool "Allow vi and awk to execute shell commands"
+ default y
+ depends on BUSYBOX_CONFIG_VI || BUSYBOX_CONFIG_AWK
+ help
+ Enables vi and awk features which allows user to execute
+ shell commands (using system() C call).
+
+endmenu
diff --git a/package/busybox/config/findutils/Config.in b/package/busybox/config/findutils/Config.in
new file mode 100644
index 000000000..8db1fdef9
--- /dev/null
+++ b/package/busybox/config/findutils/Config.in
@@ -0,0 +1,252 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Finding Utilities"
+
+config BUSYBOX_CONFIG_FIND
+ bool "find"
+ default y
+ help
+ find is used to search your system to find specified files.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_PRINT0
+ bool "Enable -print0: NUL-terminated output"
+ default y
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ Causes output names to be separated by a NUL character
+ rather than a newline. This allows names that contain
+ newlines and other whitespace to be more easily
+ interpreted by other programs.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_MTIME
+ bool "Enable -mtime: modified time matching"
+ default n
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ Allow searching based on the modification time of
+ files, in days.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_MMIN
+ bool "Enable -mmin: modified time matching by minutes"
+ default n
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ Allow searching based on the modification time of
+ files, in minutes.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_PERM
+ bool "Enable -perm: permissions matching"
+ default y
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ Enable searching based on file permissions.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_TYPE
+ bool "Enable -type: file type matching (file/dir/link/...)"
+ default y
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ Enable searching based on file type (file,
+ directory, socket, device, etc.).
+
+config BUSYBOX_CONFIG_FEATURE_FIND_XDEV
+ bool "Enable -xdev: 'stay in filesystem'"
+ default y
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ This option allows find to restrict searches to a single filesystem.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_MAXDEPTH
+ bool "Enable -mindepth N and -maxdepth N"
+ default y
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ This option enables -mindepth N and -maxdepth N option.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_NEWER
+ bool "Enable -newer: compare file modification times"
+ default n
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ Support the 'find -newer' option for finding any files which have
+ modification time that is more recent than the specified FILE.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_INUM
+ bool "Enable -inum: inode number matching"
+ default n
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ Support the 'find -inum' option for searching by inode number.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_EXEC
+ bool "Enable -exec: execute commands"
+ default y
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ Support the 'find -exec' option for executing commands based upon
+ the files matched.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_USER
+ bool "Enable -user: username/uid matching"
+ default y
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ Support the 'find -user' option for searching by username or uid.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_GROUP
+ bool "Enable -group: group/gid matching"
+ default y
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ Support the 'find -group' option for searching by group name or gid.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_NOT
+ bool "Enable the 'not' (!) operator"
+ default y
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ Support the '!' operator to invert the test results.
+ If 'Enable full-blown desktop' is enabled, then will also support
+ the non-POSIX notation '-not'.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_DEPTH
+ bool "Enable -depth"
+ default y
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ Process each directory's contents before the directory itself.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_PAREN
+ bool "Enable parens in options"
+ default y
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ Enable usage of parens '(' to specify logical order of arguments.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_SIZE
+ bool "Enable -size: file size matching"
+ default y
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ Support the 'find -size' option for searching by file size.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_PRUNE
+ bool "Enable -prune: exclude subdirectories"
+ default y
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ If the file is a directory, dont descend into it. Useful for
+ exclusion .svn and CVS directories.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_DELETE
+ bool "Enable -delete: delete files/dirs"
+ default n
+ depends on BUSYBOX_CONFIG_FIND && BUSYBOX_CONFIG_FEATURE_FIND_DEPTH
+ help
+ Support the 'find -delete' option for deleting files and directories.
+ WARNING: This option can do much harm if used wrong. Busybox will not
+ try to protect the user from doing stupid things. Use with care.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_PATH
+ bool "Enable -path: match pathname with shell pattern"
+ default y
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ The -path option matches whole pathname instead of just filename.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_REGEX
+ bool "Enable -regex: match pathname with regex"
+ default y
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ The -regex option matches whole pathname against regular expression.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_CONTEXT
+ bool "Enable -context: security context matching"
+ default n
+ depends on BUSYBOX_CONFIG_FIND && BUSYBOX_CONFIG_SELINUX
+ help
+ Support the 'find -context' option for matching security context.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_LINKS
+ bool "Enable -links: link count matching"
+ default n
+ depends on BUSYBOX_CONFIG_FIND
+ help
+ Support the 'find -links' option for matching number of links.
+config BUSYBOX_CONFIG_GREP
+ bool "grep"
+ default y
+ help
+ grep is used to search files for a specified pattern.
+
+config BUSYBOX_CONFIG_FEATURE_GREP_EGREP_ALIAS
+ bool "Enable extended regular expressions (egrep & grep -E)"
+ default y
+ depends on BUSYBOX_CONFIG_GREP
+ help
+ Enabled support for extended regular expressions. Extended
+ regular expressions allow for alternation (foo|bar), grouping,
+ and various repetition operators.
+
+config BUSYBOX_CONFIG_FEATURE_GREP_FGREP_ALIAS
+ bool "Alias fgrep to grep -F"
+ default y
+ depends on BUSYBOX_CONFIG_GREP
+ help
+ fgrep sees the search pattern as a normal string rather than
+ regular expressions.
+ grep -F always works, this just creates the fgrep alias.
+
+config BUSYBOX_CONFIG_FEATURE_GREP_CONTEXT
+ bool "Enable before and after context flags (-A, -B and -C)"
+ default y
+ depends on BUSYBOX_CONFIG_GREP
+ help
+ Print the specified number of leading (-B) and/or trailing (-A)
+ context surrounding our matching lines.
+ Print the specified number of context lines (-C).
+config BUSYBOX_CONFIG_XARGS
+ bool "xargs"
+ default y
+ help
+ xargs is used to execute a specified command for
+ every item from standard input.
+
+config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION
+ bool "Enable -p: prompt and confirmation"
+ default y
+ depends on BUSYBOX_CONFIG_XARGS
+ help
+ Support -p: prompt the user whether to run each command
+ line and read a line from the terminal.
+
+config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_QUOTES
+ bool "Enable single and double quotes and backslash"
+ default y
+ depends on BUSYBOX_CONFIG_XARGS
+ help
+ Support quoting in the input.
+
+config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT
+ bool "Enable -x: exit if -s or -n is exceeded"
+ default y
+ depends on BUSYBOX_CONFIG_XARGS
+ help
+ Support -x: exit if the command size (see the -s or -n option)
+ is exceeded.
+
+config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM
+ bool "Enable -0: NUL-terminated input"
+ default y
+ depends on BUSYBOX_CONFIG_XARGS
+ help
+ Support -0: input items are terminated by a NUL character
+ instead of whitespace, and the quotes and backslash
+ are not special.
+
+endmenu
diff --git a/package/busybox/config/init/Config.in b/package/busybox/config/init/Config.in
new file mode 100644
index 000000000..61c20140b
--- /dev/null
+++ b/package/busybox/config/init/Config.in
@@ -0,0 +1,184 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Init Utilities"
+
+config BUSYBOX_CONFIG_BOOTCHARTD
+ bool "bootchartd"
+ default n
+ help
+ bootchartd is commonly used to profile the boot process
+ for the purpose of speeding it up. In this case, it is started
+ by the kernel as the init process. This is configured by adding
+ the init=/sbin/bootchartd option to the kernel command line.
+
+ It can also be used to monitor the resource usage of a specific
+ application or the running system in general. In this case,
+ bootchartd is started interactively by running bootchartd start
+ and stopped using bootchartd stop.
+
+config BUSYBOX_CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER
+ bool "Compatible, bloated header"
+ default n
+ depends on BUSYBOX_CONFIG_BOOTCHARTD
+ help
+ Create extended header file compatible with "big" bootchartd.
+ "Big" bootchartd is a shell script and it dumps some
+ "convenient" info int the header, such as:
+ title = Boot chart for `hostname` (`date`)
+ system.uname = `uname -srvm`
+ system.release = `cat /etc/DISTRO-release`
+ system.cpu = `grep '^model name' /proc/cpuinfo | head -1` ($cpucount)
+ system.kernel.options = `cat /proc/cmdline`
+ This data is not mandatory for bootchart graph generation,
+ and is considered bloat. Nevertheless, this option
+ makes bootchartd applet to dump a subset of it.
+
+config BUSYBOX_CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE
+ bool "Support bootchartd.conf"
+ default n
+ depends on BUSYBOX_CONFIG_BOOTCHARTD
+ help
+ Enable reading and parsing of $PWD/bootchartd.conf
+ and /etc/bootchartd.conf files.
+config BUSYBOX_CONFIG_HALT
+ bool "poweroff, halt, and reboot"
+ default y
+ help
+ Stop all processes and either halt, reboot, or power off the system.
+
+config BUSYBOX_CONFIG_FEATURE_CALL_TELINIT
+ bool "Call telinit on shutdown and reboot"
+ default n
+ depends on BUSYBOX_CONFIG_HALT && !BUSYBOX_CONFIG_INIT
+ help
+ Call an external program (normally telinit) to facilitate
+ a switch to a proper runlevel.
+
+ This option is only available if you selected halt and friends,
+ but did not select init.
+
+config BUSYBOX_CONFIG_TELINIT_PATH
+ string "Path to telinit executable"
+ default "/sbin/telinit"
+ depends on BUSYBOX_CONFIG_FEATURE_CALL_TELINIT
+ help
+ When busybox halt and friends have to call external telinit
+ to facilitate proper shutdown, this path is to be used when
+ locating telinit executable.
+config BUSYBOX_CONFIG_INIT
+ bool "init"
+ default y
+ select BUSYBOX_CONFIG_FEATURE_SYSLOG
+ help
+ init is the first program run when the system boots.
+
+config BUSYBOX_CONFIG_FEATURE_USE_INITTAB
+ bool "Support reading an inittab file"
+ default y
+ depends on BUSYBOX_CONFIG_INIT
+ help
+ Allow init to read an inittab file when the system boot.
+
+config BUSYBOX_CONFIG_FEATURE_KILL_REMOVED
+ bool "Support killing processes that have been removed from inittab"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_USE_INITTAB
+ help
+ When respawn entries are removed from inittab and a SIGHUP is
+ sent to init, this option will make init kill the processes
+ that have been removed.
+
+config BUSYBOX_CONFIG_FEATURE_KILL_DELAY
+ int "How long to wait between TERM and KILL (0 - send TERM only)" if FEATURE_KILL_REMOVED
+ range 0 1024
+ default 0
+ depends on BUSYBOX_CONFIG_FEATURE_KILL_REMOVED
+ help
+ With nonzero setting, init sends TERM, forks, child waits N
+ seconds, sends KILL and exits. Setting it too high is unwise
+ (child will hang around for too long and could actually kill
+ the wrong process!)
+
+config BUSYBOX_CONFIG_FEATURE_INIT_SCTTY
+ bool "Run commands with leading dash with controlling tty"
+ default n
+ depends on BUSYBOX_CONFIG_INIT
+ help
+ If this option is enabled, init will try to give a controlling
+ tty to any command which has leading hyphen (often it's "-/bin/sh").
+ More precisely, init will do "ioctl(STDIN_FILENO, TIOCSCTTY, 0)".
+ If device attached to STDIN_FILENO can be a ctty but is not yet
+ a ctty for other session, it will become this process' ctty.
+ This is not the traditional init behavour, but is often what you want
+ in an embedded system where the console is only accessed during
+ development or for maintenance.
+ NB: using cttyhack applet may work better.
+
+config BUSYBOX_CONFIG_FEATURE_INIT_SYSLOG
+ bool "Enable init to write to syslog"
+ default y
+ depends on BUSYBOX_CONFIG_INIT
+
+config BUSYBOX_CONFIG_FEATURE_EXTRA_QUIET
+ bool "Be _extra_ quiet on boot"
+ default n
+ depends on BUSYBOX_CONFIG_INIT
+ help
+ Prevent init from logging some messages to the console during boot.
+
+config BUSYBOX_CONFIG_FEATURE_INIT_COREDUMPS
+ bool "Support dumping core for child processes (debugging only)"
+ default n
+ depends on BUSYBOX_CONFIG_INIT
+ help
+ If this option is enabled and the file /.init_enable_core
+ exists, then init will call setrlimit() to allow unlimited
+ core file sizes. If this option is disabled, processes
+ will not generate any core files.
+
+config BUSYBOX_CONFIG_FEATURE_INITRD
+ bool "Support running init from within an initrd (not initramfs)"
+ default n
+ depends on BUSYBOX_CONFIG_INIT
+ help
+ Legacy support for running init under the old-style initrd. Allows
+ the name linuxrc to act as init, and it doesn't assume init is PID 1.
+
+ This does not apply to initramfs, which runs /init as PID 1 and
+ requires no special support.
+
+config BUSYBOX_CONFIG_INIT_TERMINAL_TYPE
+ string "Initial terminal type"
+ default "linux"
+ depends on BUSYBOX_CONFIG_INIT
+ help
+ This is the initial value set by init for the TERM environment
+ variable. This variable is used by programs which make use of
+ extended terminal capabilities.
+
+ Note that on Linux, init attempts to detect serial terminal and
+ sets TERM to "vt102" if one is found.
+config BUSYBOX_CONFIG_MESG
+ bool "mesg"
+ default n
+ help
+ Mesg controls access to your terminal by others. It is typically
+ used to allow or disallow other users to write to your terminal
+
+config BUSYBOX_CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP
+ bool "Enable writing to tty only by group, not by everybody"
+ default n
+ depends on BUSYBOX_CONFIG_MESG
+ help
+ Usually, ttys are owned by group "tty", and "write" tool is
+ setgid to this group. This way, "mesg y" only needs to enable
+ "write by owning group" bit in tty mode.
+
+ If you set this option to N, "mesg y" will enable writing
+ by anybody at all. This is not recommended.
+
+endmenu
diff --git a/package/busybox/config/libbb/Config.in b/package/busybox/config/libbb/Config.in
new file mode 100644
index 000000000..6475403b5
--- /dev/null
+++ b/package/busybox/config/libbb/Config.in
@@ -0,0 +1,232 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Busybox Library Tuning"
+
+config BUSYBOX_CONFIG_FEATURE_SYSTEMD
+ bool "Enable systemd support"
+ default n
+ help
+ If you plan to use busybox daemons on a system where daemons
+ are controlled by systemd, enable this option.
+ If you don't use systemd, it is still safe to enable it,
+ but the downside is increased code size.
+config BUSYBOX_CONFIG_FEATURE_RTMINMAX
+ bool "Support RTMIN[+n] and RTMAX[-n] signal names"
+ default n
+ help
+ Support RTMIN[+n] and RTMAX[-n] signal names
+ in kill, killall etc. This costs ~250 bytes.
+
+config BUSYBOX_CONFIG_PASSWORD_MINLEN
+ int "Minimum password length"
+ default 6
+ range 5 32
+ help
+ Minimum allowable password length.
+
+config BUSYBOX_CONFIG_MD5_SIZE_VS_SPEED
+ int "MD5: Trade bytes for speed (0:fast, 3:slow)"
+ default 2
+ range 0 3
+ help
+ Trade binary size versus speed for the md5sum algorithm.
+ Approximate values running uClibc and hashing
+ linux-2.4.4.tar.bz2 were:
+ user times (sec) text size (386)
+ 0 (fastest) 1.1 6144
+ 1 1.4 5392
+ 2 3.0 5088
+ 3 (smallest) 5.1 4912
+
+config BUSYBOX_CONFIG_FEATURE_FAST_TOP
+ bool "Faster /proc scanning code (+100 bytes)"
+ default y
+ help
+ This option makes top (and ps) ~20% faster (or 20% less CPU hungry),
+ but code size is slightly bigger.
+
+config BUSYBOX_CONFIG_FEATURE_ETC_NETWORKS
+ bool "Support for /etc/networks"
+ default n
+ help
+ Enable support for network names in /etc/networks. This is
+ a rarely used feature which allows you to use names
+ instead of IP/mask pairs in route command.
+
+config BUSYBOX_CONFIG_FEATURE_USE_TERMIOS
+ bool "Use termios to manipulate the screen"
+ default n
+ depends on BUSYBOX_CONFIG_MORE || BUSYBOX_CONFIG_TOP || BUSYBOX_CONFIG_POWERTOP
+ help
+ This option allows utilities such as 'more' and 'top' to determine
+ the size of the screen. If you leave this disabled, your utilities
+ that display things on the screen will be especially primitive and
+ will be unable to determine the current screen size, and will be
+ unable to move the cursor.
+
+config BUSYBOX_CONFIG_FEATURE_EDITING
+ bool "Command line editing"
+ default y
+ help
+ Enable line editing (mainly for shell command line).
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_MAX_LEN
+ int "Maximum length of input"
+ range 128 8192
+ default 512
+ depends on BUSYBOX_CONFIG_FEATURE_EDITING
+ help
+ Line editing code uses on-stack buffers for storage.
+ You may want to decrease this parameter if your target machine
+ benefits from smaller stack usage.
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_VI
+ bool "vi-style line editing commands"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_EDITING
+ help
+ Enable vi-style line editing. In shells, this mode can be
+ turned on and off with "set -o vi" and "set +o vi".
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_HISTORY
+ int "History size"
+ # Don't allow way too big values here, code uses fixed "char *history[N]" struct member
+ range 0 9999
+ default 256
+ depends on BUSYBOX_CONFIG_FEATURE_EDITING
+ help
+ Specify command history size (0 - disable).
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_SAVEHISTORY
+ bool "History saving"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_EDITING
+ help
+ Enable history saving in shells.
+
+config BUSYBOX_CONFIG_FEATURE_REVERSE_SEARCH
+ bool "Reverse history search"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_EDITING_SAVEHISTORY
+ help
+ Enable readline-like Ctrl-R combination for reverse history search.
+ Increases code by about 0.5k.
+
+config BUSYBOX_CONFIG_FEATURE_TAB_COMPLETION
+ bool "Tab completion"
+ default y
+ depends on BUSYBOX_CONFIG_FEATURE_EDITING
+ help
+ Enable tab completion.
+
+config BUSYBOX_CONFIG_FEATURE_USERNAME_COMPLETION
+ bool "Username completion"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_TAB_COMPLETION
+ help
+ Enable username completion.
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_FANCY_PROMPT
+ bool "Fancy shell prompts"
+ default y
+ depends on BUSYBOX_CONFIG_FEATURE_EDITING
+ help
+ Setting this option allows for prompts to use things like \w and
+ \$ and escape codes.
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_ASK_TERMINAL
+ bool "Query cursor position from terminal"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_EDITING
+ help
+ Allow usage of "ESC [ 6 n" sequence. Terminal answers back with
+ current cursor position. This information is used to make line
+ editing more robust in some cases.
+ If you are not sure whether your terminals respond to this code
+ correctly, or want to save on code size (about 400 bytes),
+ then do not turn this option on.
+
+config BUSYBOX_CONFIG_FEATURE_NON_POSIX_CP
+ bool "Non-POSIX, but safer, copying to special nodes"
+ default y
+ help
+ With this option, "cp file symlink" will delete symlink
+ and create a regular file. This does not conform to POSIX,
+ but prevents a symlink attack.
+ Similarly, "cp file device" will not send file's data
+ to the device. (To do that, use "cat file >device")
+
+config BUSYBOX_CONFIG_FEATURE_VERBOSE_CP_MESSAGE
+ bool "Give more precise messages when copy fails (cp, mv etc)"
+ default n
+ help
+ Error messages with this feature enabled:
+ $ cp file /does_not_exist/file
+ cp: cannot create '/does_not_exist/file': Path does not exist
+ $ cp file /vmlinuz/file
+ cp: cannot stat '/vmlinuz/file': Path has non-directory component
+ If this feature is not enabled, they will be, respectively:
+ cp: cannot create '/does_not_exist/file': No such file or directory
+ cp: cannot stat '/vmlinuz/file': Not a directory
+ This will cost you ~60 bytes.
+
+config BUSYBOX_CONFIG_FEATURE_COPYBUF_KB
+ int "Copy buffer size, in kilobytes"
+ range 1 1024
+ default 4
+ help
+ Size of buffer used by cp, mv, install, wget etc.
+ Buffers which are 4 kb or less will be allocated on stack.
+ Bigger buffers will be allocated with mmap, with fallback to 4 kb
+ stack buffer if mmap fails.
+
+config BUSYBOX_CONFIG_FEATURE_SKIP_ROOTFS
+ bool "Skip rootfs in mount table"
+ default n
+ help
+ Ignore rootfs entry in mount table.
+
+ In Linux, kernel has a special filesystem, rootfs, which is initially
+ mounted on /. It contains initramfs data, if kernel is configured
+ to have one. Usually, another file system is mounted over / early
+ in boot process, and therefore most tools which manipulate
+ mount table, such as df, will skip rootfs entry.
+
+ However, some systems do not mount anything on /.
+ If you need to configure busybox for one of these systems,
+ you may find useful to turn this option off to make df show
+ initramfs statistic.
+
+ Otherwise, choose Y.
+
+config BUSYBOX_CONFIG_MONOTONIC_SYSCALL
+ bool "Use clock_gettime(CLOCK_MONOTONIC) syscall"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Use clock_gettime(CLOCK_MONOTONIC) syscall for measuring
+ time intervals (time, ping, traceroute etc need this).
+ Probably requires Linux 2.6+. If not selected, gettimeofday
+ will be used instead (which gives wrong results if date/time
+ is reset).
+
+config BUSYBOX_CONFIG_IOCTL_HEX2STR_ERROR
+ bool "Use ioctl names rather than hex values in error messages"
+ default y
+ help
+ Use ioctl names rather than hex values in error messages
+ (e.g. VT_DISALLOCATE rather than 0x5608). If disabled this
+ saves about 1400 bytes.
+
+config BUSYBOX_CONFIG_FEATURE_HWIB
+ bool "Support infiniband HW"
+ default n
+ help
+ Support for printing infiniband addresses in
+ network applets.
+
+endmenu
diff --git a/package/busybox/config/loginutils/Config.in b/package/busybox/config/loginutils/Config.in
new file mode 100644
index 000000000..8c32851a2
--- /dev/null
+++ b/package/busybox/config/loginutils/Config.in
@@ -0,0 +1,329 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Login/Password Management Utilities"
+
+config BUSYBOX_CONFIG_ADD_SHELL
+ bool "add-shell"
+ default n if BUSYBOX_CONFIG_DESKTOP
+ help
+ Add shells to /etc/shells.
+
+config BUSYBOX_CONFIG_REMOVE_SHELL
+ bool "remove-shell"
+ default n if BUSYBOX_CONFIG_DESKTOP
+ help
+ Remove shells from /etc/shells.
+
+config BUSYBOX_CONFIG_FEATURE_SHADOWPASSWDS
+ bool "Support for shadow passwords"
+ default y
+ help
+ Build support for shadow password in /etc/shadow. This file is only
+ readable by root and thus the encrypted passwords are no longer
+ publicly readable.
+
+config BUSYBOX_CONFIG_USE_BB_PWD_GRP
+ bool "Use internal password and group functions rather than system functions"
+ default n
+ help
+ If you leave this disabled, busybox will use the system's password
+ and group functions. And if you are using the GNU C library
+ (glibc), you will then need to install the /etc/nsswitch.conf
+ configuration file and the required /lib/libnss_* libraries in
+ order for the password and group functions to work. This generally
+ makes your embedded system quite a bit larger.
+
+ Enabling this option will cause busybox to directly access the
+ system's /etc/password, /etc/group files (and your system will be
+ smaller, and I will get fewer emails asking about how glibc NSS
+ works). When this option is enabled, you will not be able to use
+ PAM to access remote LDAP password servers and whatnot. And if you
+ want hostname resolution to work with glibc, you still need the
+ /lib/libnss_* libraries.
+
+ If you need to use glibc's nsswitch.conf mechanism
+ (e.g. if user/group database is NOT stored in /etc/passwd etc),
+ you must NOT use this option.
+
+ If you enable this option, it will add about 1.5k.
+
+config BUSYBOX_CONFIG_USE_BB_SHADOW
+ bool "Use internal shadow password functions"
+ default n
+ depends on BUSYBOX_CONFIG_USE_BB_PWD_GRP && BUSYBOX_CONFIG_FEATURE_SHADOWPASSWDS
+ help
+ If you leave this disabled, busybox will use the system's shadow
+ password handling functions. And if you are using the GNU C library
+ (glibc), you will then need to install the /etc/nsswitch.conf
+ configuration file and the required /lib/libnss_* libraries in
+ order for the shadow password functions to work. This generally
+ makes your embedded system quite a bit larger.
+
+ Enabling this option will cause busybox to directly access the
+ system's /etc/shadow file when handling shadow passwords. This
+ makes your system smaller (and I will get fewer emails asking about
+ how glibc NSS works). When this option is enabled, you will not be
+ able to use PAM to access shadow passwords from remote LDAP
+ password servers and whatnot.
+
+config BUSYBOX_CONFIG_USE_BB_CRYPT
+ bool "Use internal crypt functions"
+ default n
+ help
+ Busybox has internal DES and MD5 crypt functions.
+ They produce results which are identical to corresponding
+ standard C library functions.
+
+ If you leave this disabled, busybox will use the system's
+ crypt functions. Most C libraries use large (~70k)
+ static buffers there, and also combine them with more general
+ DES encryption/decryption.
+
+ For busybox, having large static buffers is undesirable,
+ especially on NOMMU machines. Busybox also doesn't need
+ DES encryption/decryption and can do with smaller code.
+
+ If you enable this option, it will add about 4.8k of code
+ if you are building dynamically linked executable.
+ In static build, it makes code _smaller_ by about 1.2k,
+ and likely many kilobytes less of bss.
+
+config BUSYBOX_CONFIG_USE_BB_CRYPT_SHA
+ bool "Enable SHA256/512 crypt functions"
+ default n
+ depends on BUSYBOX_CONFIG_USE_BB_CRYPT
+ help
+ Enable this if you have passwords starting with "$5$" or "$6$"
+ in your /etc/passwd or /etc/shadow files. These passwords
+ are hashed using SHA256 and SHA512 algorithms. Support for them
+ was added to glibc in 2008.
+ With this option off, login will fail password check for any
+ user which has password encrypted with these algorithms.
+
+config BUSYBOX_CONFIG_ADDUSER
+ bool "adduser"
+ default n
+ help
+ Utility for creating a new user account.
+
+config BUSYBOX_CONFIG_FEATURE_ADDUSER_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_ADDUSER && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Support long options for the adduser applet.
+
+config BUSYBOX_CONFIG_FEATURE_CHECK_NAMES
+ bool "Enable sanity check on user/group names in adduser and addgroup"
+ default n
+ depends on BUSYBOX_CONFIG_ADDUSER || BUSYBOX_CONFIG_ADDGROUP
+ help
+ Enable sanity check on user and group names in adduser and addgroup.
+ To avoid problems, the user or group name should consist only of
+ letters, digits, underscores, periods, at signs and dashes,
+ and not start with a dash (as defined by IEEE Std 1003.1-2001).
+ For compatibility with Samba machine accounts "$" is also supported
+ at the end of the user or group name.
+
+config BUSYBOX_CONFIG_FIRST_SYSTEM_ID
+ int "First valid system uid or gid for adduser and addgroup"
+ depends on BUSYBOX_CONFIG_ADDUSER || BUSYBOX_CONFIG_ADDGROUP
+ range 0 64900
+ default 100
+ help
+ First valid system uid or gid for adduser and addgroup
+
+config BUSYBOX_CONFIG_LAST_SYSTEM_ID
+ int "Last valid system uid or gid for adduser and addgroup"
+ depends on BUSYBOX_CONFIG_ADDUSER || BUSYBOX_CONFIG_ADDGROUP
+ range 0 64900
+ default 999
+ help
+ Last valid system uid or gid for adduser and addgroup
+
+config BUSYBOX_CONFIG_ADDGROUP
+ bool "addgroup"
+ default n
+ help
+ Utility for creating a new group account.
+
+config BUSYBOX_CONFIG_FEATURE_ADDGROUP_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_ADDGROUP && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Support long options for the addgroup applet.
+
+config BUSYBOX_CONFIG_FEATURE_ADDUSER_TO_GROUP
+ bool "Support for adding users to groups"
+ default n
+ depends on BUSYBOX_CONFIG_ADDGROUP
+ help
+ If called with two non-option arguments,
+ addgroup will add an existing user to an
+ existing group.
+
+config BUSYBOX_CONFIG_DELUSER
+ bool "deluser"
+ default n
+ help
+ Utility for deleting a user account.
+
+config BUSYBOX_CONFIG_DELGROUP
+ bool "delgroup"
+ default n
+ help
+ Utility for deleting a group account.
+
+config BUSYBOX_CONFIG_FEATURE_DEL_USER_FROM_GROUP
+ bool "Support for removing users from groups"
+ default n
+ depends on BUSYBOX_CONFIG_DELGROUP
+ help
+ If called with two non-option arguments, deluser
+ or delgroup will remove an user from a specified group.
+
+config BUSYBOX_CONFIG_GETTY
+ bool "getty"
+ default n
+ select BUSYBOX_CONFIG_FEATURE_SYSLOG
+ help
+ getty lets you log in on a tty. It is normally invoked by init.
+
+ Note that you can save a few bytes by disabling it and
+ using login applet directly.
+ If you need to reset tty attributes before calling login,
+ this script approximates getty:
+
+ exec </dev/$1 >/dev/$1 2>&1 || exit 1
+ reset
+ stty sane; stty ispeed 38400; stty ospeed 38400
+ printf "%s login: " "`hostname`"
+ read -r login
+ exec /bin/login "$login"
+
+config BUSYBOX_CONFIG_LOGIN
+ bool "login"
+ default n
+ select BUSYBOX_CONFIG_FEATURE_SYSLOG
+ help
+ login is used when signing onto a system.
+
+ Note that Busybox binary must be setuid root for this applet to
+ work properly.
+
+config BUSYBOX_CONFIG_PAM
+ bool "Support for PAM (Pluggable Authentication Modules)"
+ default n
+ depends on DEVEL
+ depends on BUSYBOX_CONFIG_LOGIN
+ help
+ Use PAM in login(1) instead of direct access to password database.
+
+ OpenWrt specific:
+ You should install libpam from the packages feed and compile it
+ before trying to build busysbox.
+
+config BUSYBOX_CONFIG_LOGIN_SCRIPTS
+ bool "Support for login scripts"
+ depends on BUSYBOX_CONFIG_LOGIN
+ default n
+ help
+ Enable this if you want login to execute $LOGIN_PRE_SUID_SCRIPT
+ just prior to switching from root to logged-in user.
+
+config BUSYBOX_CONFIG_FEATURE_NOLOGIN
+ bool "Support for /etc/nologin"
+ default n
+ depends on BUSYBOX_CONFIG_LOGIN
+ help
+ The file /etc/nologin is used by (some versions of) login(1).
+ If it exists, non-root logins are prohibited.
+
+config BUSYBOX_CONFIG_FEATURE_SECURETTY
+ bool "Support for /etc/securetty"
+ default n
+ depends on BUSYBOX_CONFIG_LOGIN
+ help
+ The file /etc/securetty is used by (some versions of) login(1).
+ The file contains the device names of tty lines (one per line,
+ without leading /dev/) on which root is allowed to login.
+
+config BUSYBOX_CONFIG_PASSWD
+ bool "passwd"
+ default y
+ select BUSYBOX_CONFIG_FEATURE_SYSLOG
+ help
+ passwd changes passwords for user and group accounts. A normal user
+ may only change the password for his/her own account, the super user
+ may change the password for any account. The administrator of a group
+ may change the password for the group.
+
+ Note that Busybox binary must be setuid root for this applet to
+ work properly.
+
+config BUSYBOX_CONFIG_FEATURE_PASSWD_WEAK_CHECK
+ bool "Check new passwords for weakness"
+ default y
+ depends on BUSYBOX_CONFIG_PASSWD
+ help
+ With this option passwd will refuse new passwords which are "weak".
+
+config BUSYBOX_CONFIG_CRYPTPW
+ bool "cryptpw"
+ default n
+ help
+ Encrypts the given password with the crypt(3) libc function
+ using the given salt. Debian has this utility under mkpasswd
+ name. Busybox provides mkpasswd as an alias for cryptpw.
+
+config BUSYBOX_CONFIG_CHPASSWD
+ bool "chpasswd"
+ default n
+ help
+ Reads a file of user name and password pairs from standard input
+ and uses this information to update a group of existing users.
+
+config BUSYBOX_CONFIG_SU
+ bool "su"
+ default n
+ select BUSYBOX_CONFIG_FEATURE_SYSLOG
+ help
+ su is used to become another user during a login session.
+ Invoked without a username, su defaults to becoming the super user.
+
+ Note that Busybox binary must be setuid root for this applet to
+ work properly.
+
+config BUSYBOX_CONFIG_FEATURE_SU_SYSLOG
+ bool "Enable su to write to syslog"
+ default n
+ depends on BUSYBOX_CONFIG_SU
+
+config BUSYBOX_CONFIG_FEATURE_SU_CHECKS_SHELLS
+ bool "Enable su to check user's shell to be listed in /etc/shells"
+ depends on BUSYBOX_CONFIG_SU
+ default n
+
+config BUSYBOX_CONFIG_SULOGIN
+ bool "sulogin"
+ default n
+ select BUSYBOX_CONFIG_FEATURE_SYSLOG
+ help
+ sulogin is invoked when the system goes into single user
+ mode (this is done through an entry in inittab).
+
+config BUSYBOX_CONFIG_VLOCK
+ bool "vlock"
+ default n
+ help
+ Build the "vlock" applet which allows you to lock (virtual) terminals.
+
+ Note that Busybox binary must be setuid root for this applet to
+ work properly.
+
+endmenu
diff --git a/package/busybox/config/mailutils/Config.in b/package/busybox/config/mailutils/Config.in
new file mode 100644
index 000000000..8db30310b
--- /dev/null
+++ b/package/busybox/config/mailutils/Config.in
@@ -0,0 +1,56 @@
+# DO NOT EDIT. This file is generated from Config.src
+menu "Mail Utilities"
+
+
+
+config BUSYBOX_CONFIG_MAKEMIME
+ bool "makemime"
+ default n
+ help
+ Create MIME-formatted messages.
+
+config BUSYBOX_CONFIG_FEATURE_MIME_CHARSET
+ string "Default charset"
+ default n
+ depends on BUSYBOX_CONFIG_MAKEMIME || BUSYBOX_CONFIG_REFORMIME || BUSYBOX_CONFIG_SENDMAIL
+ help
+ Default charset of the message.
+
+config BUSYBOX_CONFIG_POPMAILDIR
+ bool "popmaildir"
+ default n
+ help
+ Simple yet powerful POP3 mail popper. Delivers content
+ of remote mailboxes to local Maildir.
+
+config BUSYBOX_CONFIG_FEATURE_POPMAILDIR_DELIVERY
+ bool "Allow message filters and custom delivery program"
+ default n
+ depends on BUSYBOX_CONFIG_POPMAILDIR
+ help
+ Allow to use a custom program to filter the content
+ of the message before actual delivery (-F "prog [args...]").
+ Allow to use a custom program for message actual delivery
+ (-M "prog [args...]").
+
+config BUSYBOX_CONFIG_REFORMIME
+ bool "reformime"
+ default n
+ help
+ Parse MIME-formatted messages.
+
+config BUSYBOX_CONFIG_FEATURE_REFORMIME_COMPAT
+ bool "Accept and ignore options other than -x and -X"
+ default n
+ depends on BUSYBOX_CONFIG_REFORMIME
+ help
+ Accept (for compatibility only) and ignore options
+ other than -x and -X.
+
+config BUSYBOX_CONFIG_SENDMAIL
+ bool "sendmail"
+ default n
+ help
+ Barebones sendmail.
+
+endmenu
diff --git a/package/busybox/config/miscutils/Config.in b/package/busybox/config/miscutils/Config.in
new file mode 100644
index 000000000..e69d6847e
--- /dev/null
+++ b/package/busybox/config/miscutils/Config.in
@@ -0,0 +1,766 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Miscellaneous Utilities"
+
+config BUSYBOX_CONFIG_CONSPY
+ bool "conspy"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ A text-mode VNC like program for Linux virtual terminals.
+ example: conspy NUM shared access to console num
+ or conspy -nd NUM screenshot of console num
+ or conspy -cs NUM poor man's GNU screen like
+config BUSYBOX_CONFIG_LESS
+ bool "less"
+ default y
+ help
+ 'less' is a pager, meaning that it displays text files. It possesses
+ a wide array of features, and is an improvement over 'more'.
+
+config BUSYBOX_CONFIG_FEATURE_LESS_MAXLINES
+ int "Max number of input lines less will try to eat"
+ default 9999999
+ depends on BUSYBOX_CONFIG_LESS
+
+config BUSYBOX_CONFIG_FEATURE_LESS_BRACKETS
+ bool "Enable bracket searching"
+ default n
+ depends on BUSYBOX_CONFIG_LESS
+ help
+ This option adds the capability to search for matching left and right
+ brackets, facilitating programming.
+
+config BUSYBOX_CONFIG_FEATURE_LESS_FLAGS
+ bool "Enable extra flags"
+ default n
+ depends on BUSYBOX_CONFIG_LESS
+ help
+ The extra flags provided do the following:
+
+ The -M flag enables a more sophisticated status line.
+ The -m flag enables a simpler status line with a percentage.
+
+config BUSYBOX_CONFIG_FEATURE_LESS_MARKS
+ bool "Enable marks"
+ default n
+ depends on BUSYBOX_CONFIG_LESS
+ help
+ Marks enable positions in a file to be stored for easy reference.
+
+config BUSYBOX_CONFIG_FEATURE_LESS_REGEXP
+ bool "Enable regular expressions"
+ default n
+ depends on BUSYBOX_CONFIG_LESS
+ help
+ Enable regular expressions, allowing complex file searches.
+
+config BUSYBOX_CONFIG_FEATURE_LESS_WINCH
+ bool "Enable automatic resizing on window size changes"
+ default n
+ depends on BUSYBOX_CONFIG_LESS
+ help
+ Makes less track window size changes.
+
+config BUSYBOX_CONFIG_FEATURE_LESS_ASK_TERMINAL
+ bool "Use 'tell me cursor position' ESC sequence to measure window"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_LESS_WINCH
+ help
+ Makes less track window size changes.
+ If terminal size can't be retrieved and $LINES/$COLUMNS are not set,
+ this option makes less perform a last-ditch effort to find it:
+ position cursor to 999,999 and ask terminal to report real
+ cursor position using "ESC [ 6 n" escape sequence, then read stdin.
+
+ This is not clean but helps a lot on serial lines and such.
+
+config BUSYBOX_CONFIG_FEATURE_LESS_DASHCMD
+ bool "Enable flag changes ('-' command)"
+ default n
+ depends on BUSYBOX_CONFIG_LESS
+ help
+ This enables the ability to change command-line flags within
+ less itself ('-' keyboard command).
+
+config BUSYBOX_CONFIG_FEATURE_LESS_LINENUMS
+ bool "Enable dynamic switching of line numbers"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_LESS_DASHCMD
+ help
+ Enables "-N" command.
+config BUSYBOX_CONFIG_NANDWRITE
+ bool "nandwrite"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Write to the specified MTD device, with bad blocks awareness
+
+config BUSYBOX_CONFIG_NANDDUMP
+ bool "nanddump"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Dump the content of raw NAND chip
+config BUSYBOX_CONFIG_SETSERIAL
+ bool "setserial"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Retrieve or set Linux serial port.
+config BUSYBOX_CONFIG_UBIATTACH
+ bool "ubiattach"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Attach MTD device to an UBI device.
+
+config BUSYBOX_CONFIG_UBIDETACH
+ bool "ubidetach"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Detach MTD device from an UBI device.
+
+config BUSYBOX_CONFIG_UBIMKVOL
+ bool "ubimkvol"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Create a UBI volume.
+
+config BUSYBOX_CONFIG_UBIRMVOL
+ bool "ubirmvol"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Delete a UBI volume.
+
+config BUSYBOX_CONFIG_UBIRSVOL
+ bool "ubirsvol"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Resize a UBI volume.
+
+config BUSYBOX_CONFIG_UBIUPDATEVOL
+ bool "ubiupdatevol"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Update a UBI volume.
+
+config BUSYBOX_CONFIG_ADJTIMEX
+ bool "adjtimex"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Adjtimex reads and optionally sets adjustment parameters for
+ the Linux clock adjustment algorithm.
+
+config BUSYBOX_CONFIG_BBCONFIG
+ bool "bbconfig"
+ default n
+ help
+ The bbconfig applet will print the config file with which
+ busybox was built.
+
+config BUSYBOX_CONFIG_FEATURE_COMPRESS_BBCONFIG
+ bool "Compress bbconfig data"
+ default n
+ depends on BUSYBOX_CONFIG_BBCONFIG
+ help
+ Store bbconfig data in compressed form, uncompress them on-the-fly
+ before output.
+
+ If you have a really tiny busybox with few applets enabled (and
+ bunzip2 isn't one of them), the overhead of the decompressor might
+ be noticeable. Also, if you run executables directly from ROM
+ and have very little memory, this might not be a win. Otherwise,
+ you probably want this.
+
+config BUSYBOX_CONFIG_BEEP
+ bool "beep"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ The beep applets beeps in a given freq/Hz.
+
+config BUSYBOX_CONFIG_FEATURE_BEEP_FREQ
+ int "default frequency"
+ range 0 2147483647
+ default 4000
+ depends on BUSYBOX_CONFIG_BEEP
+ help
+ Frequency for default beep.
+
+config BUSYBOX_CONFIG_FEATURE_BEEP_LENGTH_MS
+ int "default length"
+ range 0 2147483647
+ default 30
+ depends on BUSYBOX_CONFIG_BEEP
+ help
+ Length in ms for default beep.
+
+config BUSYBOX_CONFIG_CHAT
+ bool "chat"
+ default n
+ help
+ Simple chat utility.
+
+config BUSYBOX_CONFIG_FEATURE_CHAT_NOFAIL
+ bool "Enable NOFAIL expect strings"
+ depends on BUSYBOX_CONFIG_CHAT
+ default n
+ help
+ When enabled expect strings which are started with a dash trigger
+ no-fail mode. That is when expectation is not met within timeout
+ the script is not terminated but sends next SEND string and waits
+ for next EXPECT string. This allows to compose far more flexible
+ scripts.
+
+config BUSYBOX_CONFIG_FEATURE_CHAT_TTY_HIFI
+ bool "Force STDIN to be a TTY"
+ depends on BUSYBOX_CONFIG_CHAT
+ default n
+ help
+ Original chat always treats STDIN as a TTY device and sets for it
+ so-called raw mode. This option turns on such behaviour.
+
+config BUSYBOX_CONFIG_FEATURE_CHAT_IMPLICIT_CR
+ bool "Enable implicit Carriage Return"
+ depends on BUSYBOX_CONFIG_CHAT
+ default n
+ help
+ When enabled make chat to terminate all SEND strings with a "\r"
+ unless "\c" is met anywhere in the string.
+
+config BUSYBOX_CONFIG_FEATURE_CHAT_SWALLOW_OPTS
+ bool "Swallow options"
+ depends on BUSYBOX_CONFIG_CHAT
+ default n
+ help
+ Busybox chat require no options. To make it not fail when used
+ in place of original chat (which has a bunch of options) turn
+ this on.
+
+config BUSYBOX_CONFIG_FEATURE_CHAT_SEND_ESCAPES
+ bool "Support weird SEND escapes"
+ depends on BUSYBOX_CONFIG_CHAT
+ default n
+ help
+ Original chat uses some escape sequences in SEND arguments which
+ are not sent to device but rather performs special actions.
+ E.g. "\K" means to send a break sequence to device.
+ "\d" delays execution for a second, "\p" -- for a 1/100 of second.
+ Before turning this option on think twice: do you really need them?
+
+config BUSYBOX_CONFIG_FEATURE_CHAT_VAR_ABORT_LEN
+ bool "Support variable-length ABORT conditions"
+ depends on BUSYBOX_CONFIG_CHAT
+ default n
+ help
+ Original chat uses fixed 50-bytes length ABORT conditions. Say N here.
+
+config BUSYBOX_CONFIG_FEATURE_CHAT_CLR_ABORT
+ bool "Support revoking of ABORT conditions"
+ depends on BUSYBOX_CONFIG_CHAT
+ default n
+ help
+ Support CLR_ABORT directive.
+
+config BUSYBOX_CONFIG_CHRT
+ bool "chrt"
+ default n
+ help
+ manipulate real-time attributes of a process.
+ This requires sched_{g,s}etparam support in your libc.
+
+config BUSYBOX_CONFIG_CROND
+ bool "crond"
+ default y
+ select BUSYBOX_CONFIG_FEATURE_SYSLOG
+ help
+ Crond is a background daemon that parses individual crontab
+ files and executes commands on behalf of the users in question.
+ This is a port of dcron from slackware. It uses files of the
+ format /var/spool/cron/crontabs/<username> files, for example:
+ $ cat /var/spool/cron/crontabs/root
+ # Run daily cron jobs at 4:40 every day:
+ 40 4 * * * /etc/cron/daily > /dev/null 2>&1
+
+config BUSYBOX_CONFIG_FEATURE_CROND_D
+ bool "Support option -d to redirect output to stderr"
+ depends on BUSYBOX_CONFIG_CROND
+ default n
+ help
+ -d sets loglevel to 0 (most verbose) and directs all output to stderr.
+
+config BUSYBOX_CONFIG_FEATURE_CROND_CALL_SENDMAIL
+ bool "Report command output via email (using sendmail)"
+ default n
+ depends on BUSYBOX_CONFIG_CROND
+ help
+ Command output will be sent to corresponding user via email.
+
+config BUSYBOX_CONFIG_FEATURE_CROND_DIR
+ string "crond spool directory"
+ default "/var/spool/cron"
+ depends on BUSYBOX_CONFIG_CROND || BUSYBOX_CONFIG_CRONTAB
+ help
+ Location of crond spool.
+
+config BUSYBOX_CONFIG_CRONTAB
+ bool "crontab"
+ default y
+ help
+ Crontab manipulates the crontab for a particular user. Only
+ the superuser may specify a different user and/or crontab directory.
+ Note that Busybox binary must be setuid root for this applet to
+ work properly.
+
+config BUSYBOX_CONFIG_DC
+ bool "dc"
+ default n
+ help
+ Dc is a reverse-polish desk calculator which supports unlimited
+ precision arithmetic.
+
+config BUSYBOX_CONFIG_FEATURE_DC_LIBM
+ bool "Enable power and exp functions (requires libm)"
+ default n
+ depends on BUSYBOX_CONFIG_DC
+ help
+ Enable power and exp functions.
+ NOTE: This will require libm to be present for linking.
+
+config BUSYBOX_CONFIG_DEVFSD
+ bool "devfsd (obsolete)"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ select BUSYBOX_CONFIG_FEATURE_SYSLOG
+ help
+ This is deprecated and should NOT be used anymore.
+ Use linux >= 2.6 (optionally with hotplug) and mdev instead!
+ See docs/mdev.txt for detailed instructions on how to use mdev
+ instead.
+
+ Provides compatibility with old device names on a devfs systems.
+ You should set it to true if you have devfs enabled.
+ The following keywords in devsfd.conf are supported:
+ "CLEAR_CONFIG", "INCLUDE", "OPTIONAL_INCLUDE", "RESTORE",
+ "PERMISSIONS", "EXECUTE", "COPY", "IGNORE",
+ "MKOLDCOMPAT", "MKNEWCOMPAT","RMOLDCOMPAT", "RMNEWCOMPAT".
+
+ But only if they are written UPPERCASE!!!!!!!!
+
+config BUSYBOX_CONFIG_DEVFSD_MODLOAD
+ bool "Adds support for MODLOAD keyword in devsfd.conf"
+ default n
+ depends on BUSYBOX_CONFIG_DEVFSD
+ help
+ This actually doesn't work with busybox modutils but needs
+ the external modutils.
+
+config BUSYBOX_CONFIG_DEVFSD_FG_NP
+ bool "Enables the -fg and -np options"
+ default n
+ depends on BUSYBOX_CONFIG_DEVFSD
+ help
+ -fg Run the daemon in the foreground.
+ -np Exit after parsing the configuration file.
+ Do not poll for events.
+
+config BUSYBOX_CONFIG_DEVFSD_VERBOSE
+ bool "Increases logging (and size)"
+ default n
+ depends on BUSYBOX_CONFIG_DEVFSD
+ help
+ Increases logging to stderr or syslog.
+
+config BUSYBOX_CONFIG_FEATURE_DEVFS
+ bool "Use devfs names for all devices (obsolete)"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ This is obsolete and should NOT be used anymore.
+ Use linux >= 2.6 (optionally with hotplug) and mdev instead!
+
+ For legacy systems -- if there is no way around devfsd -- this
+ tells busybox to look for names like /dev/loop/0 instead of
+ /dev/loop0. If your /dev directory has normal names instead of
+ devfs names, you don't want this.
+
+config BUSYBOX_CONFIG_DEVMEM
+ bool "devmem"
+ default n
+ help
+ devmem is a small program that reads and writes from physical
+ memory using /dev/mem.
+
+config BUSYBOX_CONFIG_EJECT
+ bool "eject"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Used to eject cdroms. (defaults to /dev/cdrom)
+
+config BUSYBOX_CONFIG_FEATURE_EJECT_SCSI
+ bool "SCSI support"
+ default n
+ depends on BUSYBOX_CONFIG_EJECT
+ help
+ Add the -s option to eject, this allows to eject SCSI-Devices and
+ usb-storage devices.
+
+config BUSYBOX_CONFIG_FBSPLASH
+ bool "fbsplash"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Shows splash image and progress bar on framebuffer device.
+ Can be used during boot phase of an embedded device. ~2kb.
+ Usage:
+ - use kernel option 'vga=xxx' or otherwise enable fb device.
+ - put somewhere fbsplash.cfg file and an image in .ppm format.
+ - $ setsid fbsplash [params] &
+ -c: hide cursor
+ -d /dev/fbN: framebuffer device (if not /dev/fb0)
+ -s path_to_image_file (can be "-" for stdin)
+ -i path_to_cfg_file (can be "-" for stdin)
+ -f path_to_fifo (can be "-" for stdin)
+ - if you want to run it only in presence of kernel parameter:
+ grep -q "fbsplash=on" </proc/cmdline && setsid fbsplash [params] &
+ - commands for fifo:
+ "NN" (ASCII decimal number) - percentage to show on progress bar
+ "exit" - well you guessed it
+
+config BUSYBOX_CONFIG_FLASHCP
+ bool "flashcp"
+ default n # doesn't build on Ubuntu 8.04
+ help
+ The flashcp binary, inspired by mtd-utils as of git head 5eceb74f7.
+ This utility is used to copy images into a MTD device.
+
+config BUSYBOX_CONFIG_FLASH_LOCK
+ bool "flash_lock"
+ default n # doesn't build on Ubuntu 8.04
+ help
+ The flash_lock binary from mtd-utils as of git head 5ec0c10d0. This
+ utility locks part or all of the flash device.
+
+config BUSYBOX_CONFIG_FLASH_UNLOCK
+ bool "flash_unlock"
+ default n # doesn't build on Ubuntu 8.04
+ help
+ The flash_unlock binary from mtd-utils as of git head 5ec0c10d0. This
+ utility unlocks part or all of the flash device.
+
+config BUSYBOX_CONFIG_FLASH_ERASEALL
+ bool "flash_eraseall"
+ default n # doesn't build on Ubuntu 8.04
+ help
+ The flash_eraseall binary from mtd-utils as of git head c4c6a59eb.
+ This utility is used to erase the whole MTD device.
+
+config BUSYBOX_CONFIG_IONICE
+ bool "ionice"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Set/set program io scheduling class and priority
+ Requires kernel >= 2.6.13
+
+config BUSYBOX_CONFIG_INOTIFYD
+ bool "inotifyd"
+ default n # doesn't build on Knoppix 5
+ help
+ Simple inotify daemon. Reports filesystem changes. Requires
+ kernel >= 2.6.13
+
+config BUSYBOX_CONFIG_LAST
+ bool "last"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_WTMP
+ help
+ 'last' displays a list of the last users that logged into the system.
+
+choice
+ prompt "Choose last implementation"
+ depends on BUSYBOX_CONFIG_LAST
+ default BUSYBOX_CONFIG_FEATURE_LAST_FANCY
+
+config BUSYBOX_CONFIG_FEATURE_LAST_SMALL
+ bool "small"
+ help
+ This is a small version of last with just the basic set of
+ features.
+
+config BUSYBOX_CONFIG_FEATURE_LAST_FANCY
+ bool "huge"
+ help
+ 'last' displays detailed information about the last users that
+ logged into the system (mimics sysvinit last). +900 bytes.
+endchoice
+
+config BUSYBOX_CONFIG_HDPARM
+ bool "hdparm"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Get/Set hard drive parameters. Primarily intended for ATA
+ drives. Adds about 13k (or around 30k if you enable the
+ FEATURE_HDPARM_GET_IDENTITY option)....
+
+config BUSYBOX_CONFIG_FEATURE_HDPARM_GET_IDENTITY
+ bool "Support obtaining detailed information directly from drives"
+ default n
+ depends on BUSYBOX_CONFIG_HDPARM
+ help
+ Enables the -I and -i options to obtain detailed information
+ directly from drives about their capabilities and supported ATA
+ feature set. If no device name is specified, hdparm will read
+ identify data from stdin. Enabling this option will add about 16k...
+
+config BUSYBOX_CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF
+ bool "Register an IDE interface (DANGEROUS)"
+ default n
+ depends on BUSYBOX_CONFIG_HDPARM
+ help
+ Enables the 'hdparm -R' option to register an IDE interface.
+ This is dangerous stuff, so you should probably say N.
+
+config BUSYBOX_CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF
+ bool "Un-register an IDE interface (DANGEROUS)"
+ default n
+ depends on BUSYBOX_CONFIG_HDPARM
+ help
+ Enables the 'hdparm -U' option to un-register an IDE interface.
+ This is dangerous stuff, so you should probably say N.
+
+config BUSYBOX_CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET
+ bool "Perform device reset (DANGEROUS)"
+ default n
+ depends on BUSYBOX_CONFIG_HDPARM
+ help
+ Enables the 'hdparm -w' option to perform a device reset.
+ This is dangerous stuff, so you should probably say N.
+
+config BUSYBOX_CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
+ bool "Tristate device for hotswap (DANGEROUS)"
+ default n
+ depends on BUSYBOX_CONFIG_HDPARM
+ help
+ Enables the 'hdparm -x' option to tristate device for hotswap,
+ and the '-b' option to get/set bus state. This is dangerous
+ stuff, so you should probably say N.
+
+config BUSYBOX_CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA
+ bool "Get/set using_dma flag"
+ default n
+ depends on BUSYBOX_CONFIG_HDPARM
+ help
+ Enables the 'hdparm -d' option to get/set using_dma flag.
+
+config BUSYBOX_CONFIG_LOCK
+ bool "lock"
+ default y
+ help
+ Small utility for using locks in scripts
+
+config BUSYBOX_CONFIG_MAKEDEVS
+ bool "makedevs"
+ default n
+ help
+ 'makedevs' is a utility used to create a batch of devices with
+ one command.
+
+ There are two choices for command line behaviour, the interface
+ as used by LEAF/Linux Router Project, or a device table file.
+
+ 'leaf' is traditionally what busybox follows, it allows multiple
+ devices of a particluar type to be created per command.
+ e.g. /dev/hda[0-9]
+ Device properties are passed as command line arguments.
+
+ 'table' reads device properties from a file or stdin, allowing
+ a batch of unrelated devices to be made with one command.
+ User/group names are allowed as an alternative to uid/gid.
+
+choice
+ prompt "Choose makedevs behaviour"
+ depends on BUSYBOX_CONFIG_MAKEDEVS
+ default BUSYBOX_CONFIG_FEATURE_MAKEDEVS_TABLE
+
+config BUSYBOX_CONFIG_FEATURE_MAKEDEVS_LEAF
+ bool "leaf"
+
+config BUSYBOX_CONFIG_FEATURE_MAKEDEVS_TABLE
+ bool "table"
+
+endchoice
+
+config BUSYBOX_CONFIG_MAN
+ bool "man"
+ default n
+ help
+ Format and display manual pages.
+
+config BUSYBOX_CONFIG_MICROCOM
+ bool "microcom"
+ default n
+ help
+ The poor man's minicom utility for chatting with serial port devices.
+
+config BUSYBOX_CONFIG_MOUNTPOINT
+ bool "mountpoint"
+ default n
+ help
+ mountpoint checks if the directory is a mountpoint.
+
+config BUSYBOX_CONFIG_MT
+ bool "mt"
+ default n
+ help
+ mt is used to control tape devices. You can use the mt utility
+ to advance or rewind a tape past a specified number of archive
+ files on the tape.
+
+config BUSYBOX_CONFIG_RAIDAUTORUN
+ bool "raidautorun"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ raidautorun tells the kernel md driver to
+ search and start RAID arrays.
+
+config BUSYBOX_CONFIG_READAHEAD
+ bool "readahead"
+ default n
+ depends on BUSYBOX_CONFIG_LFS
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Preload the files listed on the command line into RAM cache so that
+ subsequent reads on these files will not block on disk I/O.
+
+ This applet just calls the readahead(2) system call on each file.
+ It is mainly useful in system startup scripts to preload files
+ or executables before they are used. When used at the right time
+ (in particular when a CPU bound process is running) it can
+ significantly speed up system startup.
+
+ As readahead(2) blocks until each file has been read, it is best to
+ run this applet as a background job.
+
+config BUSYBOX_CONFIG_RFKILL
+ bool "rfkill"
+ default n # doesn't build on Ubuntu 9.04
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Enable/disable wireless devices.
+
+ rfkill list : list all wireless devices
+ rfkill list bluetooth : list all bluetooth devices
+ rfkill list 1 : list device corresponding to the given index
+ rfkill block|unblock wlan : block/unblock all wlan(wifi) devices
+
+config BUSYBOX_CONFIG_RUNLEVEL
+ bool "runlevel"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_UTMP
+ help
+ find the current and previous system runlevel.
+
+ This applet uses utmp but does not rely on busybox supporing
+ utmp on purpose. It is used by e.g. emdebian via /etc/init.d/rc.
+
+config BUSYBOX_CONFIG_RX
+ bool "rx"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Receive files using the Xmodem protocol.
+
+config BUSYBOX_CONFIG_SETSID
+ bool "setsid"
+ default n
+ help
+ setsid runs a program in a new session
+
+config BUSYBOX_CONFIG_STRINGS
+ bool "strings"
+ default y
+ help
+ strings prints the printable character sequences for each file
+ specified.
+
+config BUSYBOX_CONFIG_TASKSET
+ bool "taskset"
+ default n # doesn't build on some non-x86 targets (m68k)
+ help
+ Retrieve or set a processes's CPU affinity.
+ This requires sched_{g,s}etaffinity support in your libc.
+
+config BUSYBOX_CONFIG_FEATURE_TASKSET_FANCY
+ bool "Fancy output"
+ default n
+ depends on BUSYBOX_CONFIG_TASKSET
+ help
+ Add code for fancy output. This merely silences a compiler-warning
+ and adds about 135 Bytes. May be needed for machines with alot
+ of CPUs.
+
+config BUSYBOX_CONFIG_TIME
+ bool "time"
+ default y
+ help
+ The time command runs the specified program with the given arguments.
+ When the command finishes, time writes a message to standard output
+ giving timing statistics about this program run.
+
+config BUSYBOX_CONFIG_TIMEOUT
+ bool "timeout"
+ default n
+ help
+ Runs a program and watches it. If it does not terminate in
+ specified number of seconds, it is sent a signal.
+
+config BUSYBOX_CONFIG_TTYSIZE
+ bool "ttysize"
+ default n
+ help
+ A replacement for "stty size". Unlike stty, can report only width,
+ only height, or both, in any order. It also does not complain on
+ error, but returns default 80x24.
+ Usage in shell scripts: width=`ttysize w`.
+
+config BUSYBOX_CONFIG_VOLNAME
+ bool "volname"
+ default n
+ help
+ Prints a CD-ROM volume name.
+
+config BUSYBOX_CONFIG_WALL
+ bool "wall"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_UTMP
+ help
+ Write a message to all users that are logged in.
+
+config BUSYBOX_CONFIG_WATCHDOG
+ bool "watchdog"
+ default y
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ The watchdog utility is used with hardware or software watchdog
+ device drivers. It opens the specified watchdog device special file
+ and periodically writes a magic character to the device. If the
+ watchdog applet ever fails to write the magic character within a
+ certain amount of time, the watchdog device assumes the system has
+ hung, and will cause the hardware to reboot.
+
+endmenu
diff --git a/package/busybox/config/modutils/Config.in b/package/busybox/config/modutils/Config.in
new file mode 100644
index 000000000..77f98581f
--- /dev/null
+++ b/package/busybox/config/modutils/Config.in
@@ -0,0 +1,269 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Linux Module Utilities"
+
+config BUSYBOX_CONFIG_MODINFO
+ bool "modinfo"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Show information about a Linux Kernel module
+
+config BUSYBOX_CONFIG_MODPROBE_SMALL
+ bool "Simplified modutils"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Simplified modutils.
+
+ With this option modprobe does not require modules.dep file
+ and does not use /etc/modules.conf file.
+ It scans module files in /lib/modules/`uname -r` and
+ determines dependencies and module alias names on the fly.
+ This may make module loading slower, most notably
+ when one needs to load module by alias (this requires
+ scanning through module _bodies_).
+
+ At the first attempt to load a module by alias modprobe
+ will try to generate modules.dep.bb file in order to speed up
+ future loads by alias. Failure to do so (read-only /lib/modules,
+ etc) is not reported, and future modprobes will be slow too.
+
+ NB: modules.dep.bb file format is not compatible
+ with modules.dep file as created/used by standard module tools.
+
+ Additional module parameters can be stored in
+ /etc/modules/$module_name files.
+
+ Apart from modprobe, other utilities are also provided:
+ - insmod is an alias to modprobe
+ - rmmod is an alias to modprobe -r
+ - depmod generates modules.dep.bb
+
+ As of 2008-07, this code is experimental. It is 14kb smaller
+ than "non-small" modutils.
+
+config BUSYBOX_CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE
+ bool "Accept module options on modprobe command line"
+ default n
+ depends on BUSYBOX_CONFIG_MODPROBE_SMALL
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Allow insmod and modprobe take module options from command line.
+
+config BUSYBOX_CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED
+ bool "Skip loading of already loaded modules"
+ default n
+ depends on BUSYBOX_CONFIG_MODPROBE_SMALL
+ help
+ Check if the module is already loaded.
+
+config BUSYBOX_CONFIG_INSMOD
+ bool "insmod"
+ default y
+ depends on !BUSYBOX_CONFIG_MODPROBE_SMALL
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ insmod is used to load specified modules in the running kernel.
+
+config BUSYBOX_CONFIG_RMMOD
+ bool "rmmod"
+ default y
+ depends on !BUSYBOX_CONFIG_MODPROBE_SMALL
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ rmmod is used to unload specified modules from the kernel.
+
+config BUSYBOX_CONFIG_LSMOD
+ bool "lsmod"
+ default y
+ depends on !BUSYBOX_CONFIG_MODPROBE_SMALL
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ lsmod is used to display a list of loaded modules.
+
+config BUSYBOX_CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT
+ bool "Pretty output"
+ default y
+ depends on BUSYBOX_CONFIG_LSMOD
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ This option makes output format of lsmod adjusted to
+ the format of module-init-tools for Linux kernel 2.6.
+ Increases size somewhat.
+
+config BUSYBOX_CONFIG_MODPROBE
+ bool "modprobe"
+ default n
+ depends on !BUSYBOX_CONFIG_MODPROBE_SMALL
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Handle the loading of modules, and their dependencies on a high
+ level.
+
+config BUSYBOX_CONFIG_FEATURE_MODPROBE_BLACKLIST
+ bool "Blacklist support"
+ default n
+ depends on BUSYBOX_CONFIG_MODPROBE
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Say 'y' here to enable support for the 'blacklist' command in
+ modprobe.conf. This prevents the alias resolver to resolve
+ blacklisted modules. This is useful if you want to prevent your
+ hardware autodetection scripts to load modules like evdev, frame
+ buffer drivers etc.
+
+config BUSYBOX_CONFIG_DEPMOD
+ bool "depmod"
+ default n
+ depends on !BUSYBOX_CONFIG_MODPROBE_SMALL
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ depmod generates modules.dep (and potentially modules.alias
+ and modules.symbols) that contain dependency information
+ for modprobe.
+
+comment "Options common to multiple modutils"
+
+config BUSYBOX_CONFIG_FEATURE_2_4_MODULES
+ bool "Support version 2.2/2.4 Linux kernels"
+ default n
+ depends on BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_RMMOD || BUSYBOX_CONFIG_LSMOD
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Support module loading for 2.2.x and 2.4.x Linux kernels.
+ This increases size considerably. Say N unless you plan
+ to run ancient kernels.
+
+config BUSYBOX_CONFIG_FEATURE_INSMOD_TRY_MMAP
+ bool "Try to load module from a mmap'ed area"
+ default n
+ depends on BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_MODPROBE_SMALL
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ This option causes module loading code to try to mmap
+ module first. If it does not work (for example,
+ it does not work for compressed modules), module will be read
+ (and unpacked if needed) into a memory block allocated by malloc.
+
+ The only case when mmap works but malloc does not is when
+ you are trying to load a big module on a very memory-constrained
+ machine. Malloc will momentarily need 2x as much memory as mmap.
+
+ Choosing N saves about 250 bytes of code (on 32-bit x86).
+
+config BUSYBOX_CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+ bool "Enable module version checking"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_2_4_MODULES && (BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_MODPROBE)
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Support checking of versions for modules. This is used to
+ ensure that the kernel and module are made for each other.
+
+config BUSYBOX_CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
+ bool "Add module symbols to kernel symbol table"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_2_4_MODULES && (BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_MODPROBE)
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ By adding module symbols to the kernel symbol table, Oops messages
+ occuring within kernel modules can be properly debugged. By enabling
+ this feature, module symbols will always be added to the kernel symbol
+ table for proper debugging support. If you are not interested in
+ Oops messages from kernel modules, say N.
+
+config BUSYBOX_CONFIG_FEATURE_INSMOD_LOADINKMEM
+ bool "In kernel memory optimization (uClinux only)"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_2_4_MODULES && (BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_MODPROBE)
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ This is a special uClinux only memory optimization that lets insmod
+ load the specified kernel module directly into kernel space, reducing
+ memory usage by preventing the need for two copies of the module
+ being loaded into memory.
+
+config BUSYBOX_CONFIG_FEATURE_INSMOD_LOAD_MAP
+ bool "Enable insmod load map (-m) option"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_2_4_MODULES && BUSYBOX_CONFIG_INSMOD
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Enabling this, one would be able to get a load map
+ output on stdout. This makes kernel module debugging
+ easier.
+ If you don't plan to debug kernel modules, you
+ don't need this option.
+
+config BUSYBOX_CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
+ bool "Symbols in load map"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_INSMOD_LOAD_MAP && !BUSYBOX_CONFIG_MODPROBE_SMALL
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Without this option, -m will only output section
+ load map. With this option, -m will also output
+ symbols load map.
+
+config BUSYBOX_CONFIG_FEATURE_CHECK_TAINTED_MODULE
+ bool "Support tainted module checking with new kernels"
+ default y
+ depends on (BUSYBOX_CONFIG_LSMOD || BUSYBOX_CONFIG_FEATURE_2_4_MODULES) && !BUSYBOX_CONFIG_MODPROBE_SMALL
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Support checking for tainted modules. These are usually binary
+ only modules that will make the linux-kernel list ignore your
+ support request.
+ This option is required to support GPLONLY modules.
+
+config BUSYBOX_CONFIG_FEATURE_MODUTILS_ALIAS
+ bool "Support for module.aliases file"
+ default n
+ depends on BUSYBOX_CONFIG_DEPMOD || BUSYBOX_CONFIG_MODPROBE
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Generate and parse modules.alias containing aliases for bus
+ identifiers:
+ alias pcmcia:m*c*f03fn*pfn*pa*pb*pc*pd* parport_cs
+
+ and aliases for logical modules names e.g.:
+ alias padlock_aes aes
+ alias aes_i586 aes
+ alias aes_generic aes
+
+ Say Y if unsure.
+
+config BUSYBOX_CONFIG_FEATURE_MODUTILS_SYMBOLS
+ bool "Support for module.symbols file"
+ default n
+ depends on BUSYBOX_CONFIG_DEPMOD || BUSYBOX_CONFIG_MODPROBE
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Generate and parse modules.symbols containing aliases for
+ symbol_request() kernel calls, such as:
+ alias symbol:usb_sg_init usbcore
+
+ Say Y if unsure.
+
+config BUSYBOX_CONFIG_DEFAULT_MODULES_DIR
+ string "Default directory containing modules"
+ default "/lib/modules"
+ depends on BUSYBOX_CONFIG_DEPMOD || BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_MODPROBE || BUSYBOX_CONFIG_MODPROBE_SMALL || BUSYBOX_CONFIG_MODINFO
+ help
+ Directory that contains kernel modules.
+ Defaults to "/lib/modules"
+
+config BUSYBOX_CONFIG_DEFAULT_DEPMOD_FILE
+ string "Default name of modules.dep"
+ default "modules.dep"
+ depends on BUSYBOX_CONFIG_DEPMOD || BUSYBOX_CONFIG_MODPROBE || BUSYBOX_CONFIG_MODPROBE_SMALL || BUSYBOX_CONFIG_MODINFO
+ help
+ Filename that contains kernel modules dependencies.
+ Defaults to "modules.dep"
+
+endmenu
diff --git a/package/busybox/config/networking/Config.in b/package/busybox/config/networking/Config.in
new file mode 100644
index 000000000..3df7b1f12
--- /dev/null
+++ b/package/busybox/config/networking/Config.in
@@ -0,0 +1,1088 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Networking Utilities"
+
+config BUSYBOX_CONFIG_NAMEIF
+ bool "nameif"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ select BUSYBOX_CONFIG_FEATURE_SYSLOG
+ help
+ nameif is used to rename network interface by its MAC address.
+ Renamed interfaces MUST be in the down state.
+ It is possible to use a file (default: /etc/mactab)
+ with list of new interface names and MACs.
+ Maximum interface name length: IFNAMSIZ = 16
+ File fields are separated by space or tab.
+ File format:
+ # Comment
+ new_interface_name XX:XX:XX:XX:XX:XX
+
+config BUSYBOX_CONFIG_FEATURE_NAMEIF_EXTENDED
+ bool "Extended nameif"
+ default n
+ depends on BUSYBOX_CONFIG_NAMEIF
+ help
+ This extends the nameif syntax to support the bus_info, driver,
+ phyaddr selectors. The syntax is compatible to the normal nameif.
+ File format:
+ new_interface_name driver=asix bus=usb-0000:00:08.2-3
+ new_interface_name bus=usb-0000:00:08.2-3 00:80:C8:38:91:B5
+ new_interface_name phy_address=2 00:80:C8:38:91:B5
+ new_interface_name mac=00:80:C8:38:91:B5
+ new_interface_name 00:80:C8:38:91:B5
+config BUSYBOX_CONFIG_NBDCLIENT
+ bool "nbd-client"
+ default n
+ help
+ Network block device client
+config BUSYBOX_CONFIG_NC
+ bool "nc"
+ default y
+ help
+ A simple Unix utility which reads and writes data across network
+ connections.
+
+config BUSYBOX_CONFIG_NC_SERVER
+ bool "Netcat server options (-l)"
+ default n
+ depends on BUSYBOX_CONFIG_NC
+ help
+ Allow netcat to act as a server.
+
+config BUSYBOX_CONFIG_NC_EXTRA
+ bool "Netcat extensions (-eiw and filename)"
+ default n
+ depends on BUSYBOX_CONFIG_NC
+ help
+ Add -e (support for executing the rest of the command line after
+ making or receiving a successful connection), -i (delay interval for
+ lines sent), -w (timeout for initial connection).
+
+config BUSYBOX_CONFIG_NC_110_COMPAT
+ bool "Netcat 1.10 compatibility (+2.5k)"
+ default n # off specially for Rob
+ depends on BUSYBOX_CONFIG_NC
+ help
+ This option makes nc closely follow original nc-1.10.
+ The code is about 2.5k bigger. It enables
+ -s ADDR, -n, -u, -v, -o FILE, -z options, but loses
+ busybox-specific extensions: -f FILE and -ll.
+config BUSYBOX_CONFIG_PING
+ bool "ping"
+ default y
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ ping uses the ICMP protocol's mandatory ECHO_REQUEST datagram to
+ elicit an ICMP ECHO_RESPONSE from a host or gateway.
+
+config BUSYBOX_CONFIG_PING6
+ bool "ping6"
+ default y
+ depends on BUSYBOX_CONFIG_FEATURE_IPV6 && BUSYBOX_CONFIG_PING
+ help
+ This will give you a ping that can talk IPv6.
+
+config BUSYBOX_CONFIG_FEATURE_FANCY_PING
+ bool "Enable fancy ping output"
+ default y
+ depends on BUSYBOX_CONFIG_PING
+ help
+ Make the output from the ping applet include statistics, and at the
+ same time provide full support for ICMP packets.
+config BUSYBOX_CONFIG_WHOIS
+ bool "whois"
+ default n
+ help
+ whois is a client for the whois directory service
+
+config BUSYBOX_CONFIG_FEATURE_IPV6
+ bool "Enable IPv6 support"
+ default IPV6
+ help
+ Enable IPv6 support in busybox.
+ This adds IPv6 support in the networking applets.
+
+config BUSYBOX_CONFIG_FEATURE_UNIX_LOCAL
+ bool "Enable Unix domain socket support (usually not needed)"
+ default n
+ help
+ Enable Unix domain socket support in all busybox networking
+ applets. Address of the form local:/path/to/unix/socket
+ will be recognized.
+
+ This extension is almost never used in real world usage.
+ You most likely want to say N.
+
+config BUSYBOX_CONFIG_FEATURE_PREFER_IPV4_ADDRESS
+ bool "Prefer IPv4 addresses from DNS queries"
+ default y
+ depends on BUSYBOX_CONFIG_FEATURE_IPV6
+ help
+ Use IPv4 address of network host if it has one.
+
+ If this option is off, the first returned address will be used.
+ This may cause problems when your DNS server is IPv6-capable and
+ is returning IPv6 host addresses too. If IPv6 address
+ precedes IPv4 one in DNS reply, busybox network applets
+ (e.g. wget) will use IPv6 address. On an IPv6-incapable host
+ or network applets will fail to connect to the host
+ using IPv6 address.
+
+config BUSYBOX_CONFIG_VERBOSE_RESOLUTION_ERRORS
+ bool "Verbose resolution errors"
+ default y
+ help
+ Enable if you are not satisfied with simplistic
+ "can't resolve 'hostname.com'" and want to know more.
+ This may increase size of your executable a bit.
+
+config BUSYBOX_CONFIG_ARP
+ bool "arp"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Manipulate the system ARP cache.
+
+config BUSYBOX_CONFIG_ARPING
+ bool "arping"
+ default y
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Ping hosts by ARP packets.
+
+config BUSYBOX_CONFIG_BRCTL
+ bool "brctl"
+ default y
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Manage ethernet bridges.
+ Supports addbr/delbr and addif/delif.
+
+config BUSYBOX_CONFIG_FEATURE_BRCTL_FANCY
+ bool "Fancy options"
+ default y
+ depends on BUSYBOX_CONFIG_BRCTL
+ help
+ Add support for extended option like:
+ setageing, setfd, sethello, setmaxage,
+ setpathcost, setportprio, setbridgeprio,
+ stp
+ This adds about 600 bytes.
+
+config BUSYBOX_CONFIG_FEATURE_BRCTL_SHOW
+ bool "Support show"
+ default y
+ depends on BUSYBOX_CONFIG_BRCTL && BUSYBOX_CONFIG_FEATURE_BRCTL_FANCY
+ help
+ Add support for option which prints the current config:
+ show
+
+config BUSYBOX_CONFIG_DNSD
+ bool "dnsd"
+ default n
+ help
+ Small and static DNS server daemon.
+
+config BUSYBOX_CONFIG_ETHER_WAKE
+ bool "ether-wake"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Send a magic packet to wake up sleeping machines.
+
+config BUSYBOX_CONFIG_FAKEIDENTD
+ bool "fakeidentd"
+ default n
+ select BUSYBOX_CONFIG_FEATURE_SYSLOG
+ help
+ fakeidentd listens on the ident port and returns a predefined
+ fake value on any query.
+
+config BUSYBOX_CONFIG_FTPD
+ bool "ftpd"
+ default n
+ help
+ simple FTP daemon. You have to run it via inetd.
+
+config BUSYBOX_CONFIG_FEATURE_FTP_WRITE
+ bool "Enable upload commands"
+ default n
+ depends on BUSYBOX_CONFIG_FTPD
+ help
+ Enable all kinds of FTP upload commands (-w option)
+
+config BUSYBOX_CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST
+ bool "Enable workaround for RFC-violating clients"
+ default n
+ depends on BUSYBOX_CONFIG_FTPD
+ help
+ Some ftp clients (among them KDE's Konqueror) issue illegal
+ "LIST -l" requests. This option works around such problems.
+ It might prevent you from listing files starting with "-" and
+ it increases the code size by ~40 bytes.
+ Most other ftp servers seem to behave similar to this.
+
+config BUSYBOX_CONFIG_FTPGET
+ bool "ftpget"
+ default n
+ help
+ Retrieve a remote file via FTP.
+
+config BUSYBOX_CONFIG_FTPPUT
+ bool "ftpput"
+ default n
+ help
+ Store a remote file via FTP.
+
+config BUSYBOX_CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS
+ bool "Enable long options in ftpget/ftpput"
+ default n
+ depends on BUSYBOX_CONFIG_LONG_OPTS && (BUSYBOX_CONFIG_FTPGET || BUSYBOX_CONFIG_FTPPUT)
+ help
+ Support long options for the ftpget/ftpput applet.
+
+config BUSYBOX_CONFIG_HOSTNAME
+ bool "hostname"
+ default n
+ help
+ Show or set the system's host name.
+
+config BUSYBOX_CONFIG_HTTPD
+ bool "httpd"
+ default n
+ help
+ Serve web pages via an HTTP server.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_RANGES
+ bool "Support 'Ranges:' header"
+ default n
+ depends on BUSYBOX_CONFIG_HTTPD
+ help
+ Makes httpd emit "Accept-Ranges: bytes" header and understand
+ "Range: bytes=NNN-[MMM]" header. Allows for resuming interrupted
+ downloads, seeking in multimedia players etc.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_USE_SENDFILE
+ bool "Use sendfile system call"
+ default n
+ depends on BUSYBOX_CONFIG_HTTPD
+ help
+ When enabled, httpd will use the kernel sendfile() function
+ instead of read/write loop.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_SETUID
+ bool "Enable -u <user> option"
+ default n
+ depends on BUSYBOX_CONFIG_HTTPD
+ help
+ This option allows the server to run as a specific user
+ rather than defaulting to the user that starts the server.
+ Use of this option requires special privileges to change to a
+ different user.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_BASIC_AUTH
+ bool "Enable Basic http Authentication"
+ default n
+ depends on BUSYBOX_CONFIG_HTTPD
+ help
+ Utilizes password settings from /etc/httpd.conf for basic
+ authentication on a per url basis.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_AUTH_MD5
+ bool "Support MD5 crypted passwords for http Authentication"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_HTTPD_BASIC_AUTH
+ help
+ Enables basic per URL authentication from /etc/httpd.conf
+ using md5 passwords.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_CGI
+ bool "Support Common Gateway Interface (CGI)"
+ default n
+ depends on BUSYBOX_CONFIG_HTTPD
+ help
+ This option allows scripts and executables to be invoked
+ when specific URLs are requested.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
+ bool "Support for running scripts through an interpreter"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_HTTPD_CGI
+ help
+ This option enables support for running scripts through an
+ interpreter. Turn this on if you want PHP scripts to work
+ properly. You need to supply an additional line in your httpd
+ config file:
+ *.php:/path/to/your/php
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV
+ bool "Set REMOTE_PORT environment variable for CGI"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_HTTPD_CGI
+ help
+ Use of this option can assist scripts in generating
+ references that contain a unique port number.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_ENCODE_URL_STR
+ bool "Enable -e option (useful for CGIs written as shell scripts)"
+ default n
+ depends on BUSYBOX_CONFIG_HTTPD
+ help
+ This option allows html encoding of arbitrary strings for display
+ by the browser. Output goes to stdout.
+ For example, httpd -e "<Hello World>" produces
+ "&#60Hello&#32World&#62".
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_ERROR_PAGES
+ bool "Support for custom error pages"
+ default n
+ depends on BUSYBOX_CONFIG_HTTPD
+ help
+ This option allows you to define custom error pages in
+ the configuration file instead of the default HTTP status
+ error pages. For instance, if you add the line:
+ E404:/path/e404.html
+ in the config file, the server will respond the specified
+ '/path/e404.html' file instead of the terse '404 NOT FOUND'
+ message.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_PROXY
+ bool "Support for reverse proxy"
+ default n
+ depends on BUSYBOX_CONFIG_HTTPD
+ help
+ This option allows you to define URLs that will be forwarded
+ to another HTTP server. To setup add the following line to the
+ configuration file
+ P:/url/:http://hostname[:port]/new/path/
+ Then a request to /url/myfile will be forwarded to
+ http://hostname[:port]/new/path/myfile.
+
+config BUSYBOX_CONFIG_FEATURE_HTTPD_GZIP
+ bool "Support for GZIP content encoding"
+ default n
+ depends on BUSYBOX_CONFIG_HTTPD
+ help
+ Makes httpd send files using GZIP content encoding if the
+ client supports it and a pre-compressed <file>.gz exists.
+
+config BUSYBOX_CONFIG_IFCONFIG
+ bool "ifconfig"
+ default y
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Ifconfig is used to configure the kernel-resident network interfaces.
+
+config BUSYBOX_CONFIG_FEATURE_IFCONFIG_STATUS
+ bool "Enable status reporting output (+7k)"
+ default y
+ depends on BUSYBOX_CONFIG_IFCONFIG
+ help
+ If ifconfig is called with no arguments it will display the status
+ of the currently active interfaces.
+
+config BUSYBOX_CONFIG_FEATURE_IFCONFIG_SLIP
+ bool "Enable slip-specific options \"keepalive\" and \"outfill\""
+ default n
+ depends on BUSYBOX_CONFIG_IFCONFIG
+ help
+ Allow "keepalive" and "outfill" support for SLIP. If you're not
+ planning on using serial lines, leave this unchecked.
+
+config BUSYBOX_CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ
+ bool "Enable options \"mem_start\", \"io_addr\", and \"irq\""
+ default n
+ depends on BUSYBOX_CONFIG_IFCONFIG
+ help
+ Allow the start address for shared memory, start address for I/O,
+ and/or the interrupt line used by the specified device.
+
+config BUSYBOX_CONFIG_FEATURE_IFCONFIG_HW
+ bool "Enable option \"hw\" (ether only)"
+ default y
+ depends on BUSYBOX_CONFIG_IFCONFIG
+ help
+ Set the hardware address of this interface, if the device driver
+ supports this operation. Currently, we only support the 'ether'
+ class.
+
+config BUSYBOX_CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS
+ bool "Set the broadcast automatically"
+ default y
+ depends on BUSYBOX_CONFIG_IFCONFIG
+ help
+ Setting this will make ifconfig attempt to find the broadcast
+ automatically if the value '+' is used.
+
+config BUSYBOX_CONFIG_IFENSLAVE
+ bool "ifenslave"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Userspace application to bind several interfaces
+ to a logical interface (use with kernel bonding driver).
+
+config BUSYBOX_CONFIG_IFPLUGD
+ bool "ifplugd"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Network interface plug detection daemon.
+
+config BUSYBOX_CONFIG_IFUPDOWN
+ bool "ifupdown"
+ default n
+ help
+ Activate or deactivate the specified interfaces. This applet makes
+ use of either "ifconfig" and "route" or the "ip" command to actually
+ configure network interfaces. Therefore, you will probably also want
+ to enable either IFCONFIG and ROUTE, or enable
+ FEATURE_IFUPDOWN_IP and the various IP options. Of
+ course you could use non-busybox versions of these programs, so
+ against my better judgement (since this will surely result in plenty
+ of support questions on the mailing list), I do not force you to
+ enable these additional options. It is up to you to supply either
+ "ifconfig", "route" and "run-parts" or the "ip" command, either
+ via busybox or via standalone utilities.
+
+config BUSYBOX_CONFIG_IFUPDOWN_IFSTATE_PATH
+ string "Absolute path to ifstate file"
+ default n
+ depends on BUSYBOX_CONFIG_IFUPDOWN
+ help
+ ifupdown keeps state information in a file called ifstate.
+ Typically it is located in /var/run/ifstate, however
+ some distributions tend to put it in other places
+ (debian, for example, uses /etc/network/run/ifstate).
+ This config option defines location of ifstate.
+
+config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IP
+ bool "Use ip applet"
+ default n
+ depends on BUSYBOX_CONFIG_IFUPDOWN
+ help
+ Use the iproute "ip" command to implement "ifup" and "ifdown", rather
+ than the default of using the older 'ifconfig' and 'route' utilities.
+
+config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN
+ bool "Use busybox ip applet"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IP
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ select BUSYBOX_CONFIG_IP
+ select BUSYBOX_CONFIG_FEATURE_IP_ADDRESS
+ select BUSYBOX_CONFIG_FEATURE_IP_LINK
+ select BUSYBOX_CONFIG_FEATURE_IP_ROUTE
+ help
+ Use the busybox iproute "ip" applet to implement "ifupdown".
+
+ If left disabled, you must install the full-blown iproute2
+ utility or the "ifup" and "ifdown" applets will not work.
+
+config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN
+ bool "Use busybox ifconfig and route applets"
+ default n
+ depends on BUSYBOX_CONFIG_IFUPDOWN && !BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IP
+ select BUSYBOX_CONFIG_IFCONFIG
+ select BUSYBOX_CONFIG_ROUTE
+ help
+ Use the busybox iproute "ifconfig" and "route" applets to
+ implement the "ifup" and "ifdown" utilities.
+
+ If left disabled, you must install the full-blown ifconfig
+ and route utilities, or the "ifup" and "ifdown" applets will not
+ work.
+
+config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IPV4
+ bool "Support for IPv4"
+ default n
+ depends on BUSYBOX_CONFIG_IFUPDOWN
+ help
+ If you want ifup/ifdown to talk IPv4, leave this on.
+
+config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IPV6
+ bool "Support for IPv6"
+ default n
+ depends on BUSYBOX_CONFIG_IFUPDOWN && BUSYBOX_CONFIG_FEATURE_IPV6
+ help
+ If you need support for IPv6, turn this option on.
+
+### UNUSED
+###config FEATURE_IFUPDOWN_IPX
+### bool "Support for IPX"
+### default y
+### depends on IFUPDOWN
+### help
+### If this option is selected you can use busybox to work with IPX
+### networks.
+
+config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_MAPPING
+ bool "Enable mapping support"
+ default n
+ depends on BUSYBOX_CONFIG_IFUPDOWN
+ help
+ This enables support for the "mapping" stanza, unless you have
+ a weird network setup you don't need it.
+
+config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP
+ bool "Support for external dhcp clients"
+ default n
+ depends on BUSYBOX_CONFIG_IFUPDOWN
+ help
+ This enables support for the external dhcp clients. Clients are
+ tried in the following order: dhcpcd, dhclient, pump and udhcpc.
+ Otherwise, if udhcpc applet is enabled, it is used.
+ Otherwise, ifup/ifdown will have no support for DHCP.
+
+config BUSYBOX_CONFIG_INETD
+ bool "inetd"
+ default n
+ select BUSYBOX_CONFIG_FEATURE_SYSLOG
+ help
+ Internet superserver daemon
+
+config BUSYBOX_CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO
+ bool "Support echo service"
+ default n
+ depends on BUSYBOX_CONFIG_INETD
+ help
+ Echo received data internal inetd service
+
+config BUSYBOX_CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD
+ bool "Support discard service"
+ default n
+ depends on BUSYBOX_CONFIG_INETD
+ help
+ Internet /dev/null internal inetd service
+
+config BUSYBOX_CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME
+ bool "Support time service"
+ default n
+ depends on BUSYBOX_CONFIG_INETD
+ help
+ Return 32 bit time since 1900 internal inetd service
+
+config BUSYBOX_CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME
+ bool "Support daytime service"
+ default n
+ depends on BUSYBOX_CONFIG_INETD
+ help
+ Return human-readable time internal inetd service
+
+config BUSYBOX_CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
+ bool "Support chargen service"
+ default n
+ depends on BUSYBOX_CONFIG_INETD
+ help
+ Familiar character generator internal inetd service
+
+config BUSYBOX_CONFIG_FEATURE_INETD_RPC
+ bool "Support RPC services"
+ default n
+ depends on BUSYBOX_CONFIG_INETD
+ select BUSYBOX_CONFIG_FEATURE_HAVE_RPC
+ help
+ Support Sun-RPC based services
+
+config BUSYBOX_CONFIG_IP
+ bool "ip"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ The "ip" applet is a TCP/IP interface configuration and routing
+ utility. You generally don't need "ip" to use busybox with
+ TCP/IP.
+
+config BUSYBOX_CONFIG_FEATURE_IP_ADDRESS
+ bool "ip address"
+ default n
+ depends on BUSYBOX_CONFIG_IP
+ help
+ Address manipulation support for the "ip" applet.
+
+config BUSYBOX_CONFIG_FEATURE_IP_LINK
+ bool "ip link"
+ default n
+ depends on BUSYBOX_CONFIG_IP
+ help
+ Configure network devices with "ip".
+
+config BUSYBOX_CONFIG_FEATURE_IP_ROUTE
+ bool "ip route"
+ default n
+ depends on BUSYBOX_CONFIG_IP
+ help
+ Add support for routing table management to "ip".
+
+config BUSYBOX_CONFIG_FEATURE_IP_TUNNEL
+ bool "ip tunnel"
+ default n
+ depends on BUSYBOX_CONFIG_IP
+ help
+ Add support for tunneling commands to "ip".
+
+config BUSYBOX_CONFIG_FEATURE_IP_RULE
+ bool "ip rule"
+ default n
+ depends on BUSYBOX_CONFIG_IP
+ help
+ Add support for rule commands to "ip".
+
+config BUSYBOX_CONFIG_FEATURE_IP_SHORT_FORMS
+ bool "Support short forms of ip commands"
+ default n
+ depends on BUSYBOX_CONFIG_IP
+ help
+ Also support short-form of ip <OBJECT> commands:
+ ip addr -> ipaddr
+ ip link -> iplink
+ ip route -> iproute
+ ip tunnel -> iptunnel
+ ip rule -> iprule
+
+ Say N unless you desparately need the short form of the ip
+ object commands.
+
+config BUSYBOX_CONFIG_FEATURE_IP_RARE_PROTOCOLS
+ bool "Support displaying rarely used link types"
+ default n
+ depends on BUSYBOX_CONFIG_IP
+ help
+ If you are not going to use links of type "frad", "econet",
+ "bif" etc, you probably don't need to enable this.
+ Ethernet, wireless, infrared, ppp/slip, ip tunnelling
+ link types are supported without this option selected.
+
+config BUSYBOX_CONFIG_IPADDR
+ bool
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_IP_SHORT_FORMS && BUSYBOX_CONFIG_FEATURE_IP_ADDRESS
+
+config BUSYBOX_CONFIG_IPLINK
+ bool
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_IP_SHORT_FORMS && BUSYBOX_CONFIG_FEATURE_IP_LINK
+
+config BUSYBOX_CONFIG_IPROUTE
+ bool
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_IP_SHORT_FORMS && BUSYBOX_CONFIG_FEATURE_IP_ROUTE
+
+config BUSYBOX_CONFIG_IPTUNNEL
+ bool
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_IP_SHORT_FORMS && BUSYBOX_CONFIG_FEATURE_IP_TUNNEL
+
+config BUSYBOX_CONFIG_IPRULE
+ bool
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_IP_SHORT_FORMS && BUSYBOX_CONFIG_FEATURE_IP_RULE
+
+config BUSYBOX_CONFIG_IPCALC
+ bool "ipcalc"
+ default n
+ help
+ ipcalc takes an IP address and netmask and calculates the
+ resulting broadcast, network, and host range.
+
+config BUSYBOX_CONFIG_FEATURE_IPCALC_FANCY
+ bool "Fancy IPCALC, more options, adds 1 kbyte"
+ default n
+ depends on BUSYBOX_CONFIG_IPCALC
+ help
+ Adds the options hostname, prefix and silent to the output of
+ "ipcalc".
+
+config BUSYBOX_CONFIG_FEATURE_IPCALC_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_IPCALC && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Support long options for the ipcalc applet.
+
+config BUSYBOX_CONFIG_NETMSG
+ bool "netmsg"
+ default y
+ help
+ simple program for sending udp broadcast messages
+
+config BUSYBOX_CONFIG_NETSTAT
+ bool "netstat"
+ default y
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ netstat prints information about the Linux networking subsystem.
+
+config BUSYBOX_CONFIG_FEATURE_NETSTAT_WIDE
+ bool "Enable wide netstat output"
+ default y
+ depends on BUSYBOX_CONFIG_NETSTAT
+ help
+ Add support for wide columns. Useful when displaying IPv6 addresses
+ (-W option).
+
+config BUSYBOX_CONFIG_FEATURE_NETSTAT_PRG
+ bool "Enable PID/Program name output"
+ default y
+ depends on BUSYBOX_CONFIG_NETSTAT
+ help
+ Add support for -p flag to print out PID and program name.
+ +700 bytes of code.
+
+config BUSYBOX_CONFIG_NSLOOKUP
+ bool "nslookup"
+ default y
+ help
+ nslookup is a tool to query Internet name servers.
+
+config BUSYBOX_CONFIG_NTPD
+ bool "ntpd"
+ default y
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ The NTP client/server daemon.
+
+config BUSYBOX_CONFIG_FEATURE_NTPD_SERVER
+ bool "Make ntpd usable as a NTP server"
+ default y
+ depends on BUSYBOX_CONFIG_NTPD
+ help
+ Make ntpd usable as a NTP server. If you disable this option
+ ntpd will be usable only as a NTP client.
+
+config BUSYBOX_CONFIG_PSCAN
+ bool "pscan"
+ default n
+ help
+ Simple network port scanner.
+
+config BUSYBOX_CONFIG_ROUTE
+ bool "route"
+ default y
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Route displays or manipulates the kernel's IP routing tables.
+
+config BUSYBOX_CONFIG_SLATTACH
+ bool "slattach"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ slattach is a small utility to attach network interfaces to serial
+ lines.
+
+#config TC
+# bool "tc"
+# default y
+# help
+# show / manipulate traffic control settings
+#
+#config FEATURE_TC_INGRESS
+# def_bool n
+# depends on TC
+
+config BUSYBOX_CONFIG_TCPSVD
+ bool "tcpsvd"
+ default n
+ help
+ tcpsvd listens on a TCP port and runs a program for each new
+ connection.
+
+config BUSYBOX_CONFIG_TELNET
+ bool "telnet"
+ default y
+ help
+ Telnet is an interface to the TELNET protocol, but is also commonly
+ used to test other simple protocols.
+
+config BUSYBOX_CONFIG_FEATURE_TELNET_TTYPE
+ bool "Pass TERM type to remote host"
+ default y
+ depends on BUSYBOX_CONFIG_TELNET
+ help
+ Setting this option will forward the TERM environment variable to the
+ remote host you are connecting to. This is useful to make sure that
+ things like ANSI colors and other control sequences behave.
+
+config BUSYBOX_CONFIG_FEATURE_TELNET_AUTOLOGIN
+ bool "Pass USER type to remote host"
+ default n
+ depends on BUSYBOX_CONFIG_TELNET
+ help
+ Setting this option will forward the USER environment variable to the
+ remote host you are connecting to. This is useful when you need to
+ log into a machine without telling the username (autologin). This
+ option enables `-a' and `-l USER' arguments.
+
+config BUSYBOX_CONFIG_TELNETD
+ bool "telnetd"
+ default y
+ select BUSYBOX_CONFIG_FEATURE_SYSLOG
+ help
+ A daemon for the TELNET protocol, allowing you to log onto the host
+ running the daemon. Please keep in mind that the TELNET protocol
+ sends passwords in plain text. If you can't afford the space for an
+ SSH daemon and you trust your network, you may say 'y' here. As a
+ more secure alternative, you should seriously consider installing the
+ very small Dropbear SSH daemon instead:
+ http://matt.ucc.asn.au/dropbear/dropbear.html
+
+ Note that for busybox telnetd to work you need several things:
+ First of all, your kernel needs:
+ UNIX98_PTYS=y
+ DEVPTS_FS=y
+
+ Next, you need a /dev/pts directory on your root filesystem:
+
+ $ ls -ld /dev/pts
+ drwxr-xr-x 2 root root 0 Sep 23 13:21 /dev/pts/
+
+ Next you need the pseudo terminal master multiplexer /dev/ptmx:
+
+ $ ls -la /dev/ptmx
+ crw-rw-rw- 1 root tty 5, 2 Sep 23 13:55 /dev/ptmx
+
+ Any /dev/ttyp[0-9]* files you may have can be removed.
+ Next, you need to mount the devpts filesystem on /dev/pts using:
+
+ mount -t devpts devpts /dev/pts
+
+ You need to be sure that busybox has LOGIN and
+ FEATURE_SUID enabled. And finally, you should make
+ certain that Busybox has been installed setuid root:
+
+ chown root.root /bin/busybox
+ chmod 4755 /bin/busybox
+
+ with all that done, telnetd _should_ work....
+
+
+config BUSYBOX_CONFIG_FEATURE_TELNETD_STANDALONE
+ bool "Support standalone telnetd (not inetd only)"
+ default y
+ depends on BUSYBOX_CONFIG_TELNETD
+ help
+ Selecting this will make telnetd able to run standalone.
+
+config BUSYBOX_CONFIG_FEATURE_TELNETD_INETD_WAIT
+ bool "Support -w SEC option (inetd wait mode)"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_TELNETD_STANDALONE
+ help
+ This option allows you to run telnetd in "inet wait" mode.
+ Example inetd.conf line (note "wait", not usual "nowait"):
+
+ telnet stream tcp wait root /bin/telnetd telnetd -w10
+
+ In this example, inetd passes _listening_ socket_ as fd 0
+ to telnetd when connection appears.
+ telnetd will wait for connections until all existing
+ connections are closed, and no new connections
+ appear during 10 seconds. Then it exits, and inetd continues
+ to listen for new connections.
+
+ This option is rarely used. "tcp nowait" is much more usual
+ way of running tcp services, including telnetd.
+ You most probably want to say N here.
+
+config BUSYBOX_CONFIG_TFTP
+ bool "tftp"
+ default n
+ help
+ This enables the Trivial File Transfer Protocol client program. TFTP
+ is usually used for simple, small transfers such as a root image
+ for a network-enabled bootloader.
+
+config BUSYBOX_CONFIG_TFTPD
+ bool "tftpd"
+ default n
+ help
+ This enables the Trivial File Transfer Protocol server program.
+ It expects that stdin is a datagram socket and a packet
+ is already pending on it. It will exit after one transfer.
+ In other words: it should be run from inetd in nowait mode,
+ or from udpsvd. Example: "udpsvd -E 0 69 tftpd DIR"
+
+comment "Common options for tftp/tftpd"
+ depends on BUSYBOX_CONFIG_TFTP || BUSYBOX_CONFIG_TFTPD
+
+config BUSYBOX_CONFIG_FEATURE_TFTP_GET
+ bool "Enable 'tftp get' and/or tftpd upload code"
+ default n
+ depends on BUSYBOX_CONFIG_TFTP || BUSYBOX_CONFIG_TFTPD
+ help
+ Add support for the GET command within the TFTP client. This allows
+ a client to retrieve a file from a TFTP server.
+ Also enable upload support in tftpd, if tftpd is selected.
+
+ Note: this option does _not_ make tftpd capable of download
+ (the usual operation people need from it)!
+
+config BUSYBOX_CONFIG_FEATURE_TFTP_PUT
+ bool "Enable 'tftp put' and/or tftpd download code"
+ default n
+ depends on BUSYBOX_CONFIG_TFTP || BUSYBOX_CONFIG_TFTPD
+ help
+ Add support for the PUT command within the TFTP client. This allows
+ a client to transfer a file to a TFTP server.
+ Also enable download support in tftpd, if tftpd is selected.
+
+config BUSYBOX_CONFIG_FEATURE_TFTP_BLOCKSIZE
+ bool "Enable 'blksize' and 'tsize' protocol options"
+ default n
+ depends on BUSYBOX_CONFIG_TFTP || BUSYBOX_CONFIG_TFTPD
+ help
+ Allow tftp to specify block size, and tftpd to understand
+ "blksize" and "tsize" options.
+
+config BUSYBOX_CONFIG_FEATURE_TFTP_PROGRESS_BAR
+ bool "Enable tftp progress meter"
+ default n
+ depends on BUSYBOX_CONFIG_TFTP && BUSYBOX_CONFIG_FEATURE_TFTP_BLOCKSIZE
+ help
+ Show progress bar.
+
+config BUSYBOX_CONFIG_TFTP_DEBUG
+ bool "Enable debug"
+ default n
+ depends on BUSYBOX_CONFIG_TFTP || BUSYBOX_CONFIG_TFTPD
+ help
+ Make tftp[d] print debugging messages on stderr.
+ This is useful if you are diagnosing a bug in tftp[d].
+
+config BUSYBOX_CONFIG_TRACEROUTE
+ bool "traceroute"
+ default y
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Utility to trace the route of IP packets.
+
+config BUSYBOX_CONFIG_TRACEROUTE6
+ bool "traceroute6"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_IPV6 && BUSYBOX_CONFIG_TRACEROUTE
+ help
+ Utility to trace the route of IPv6 packets.
+
+config BUSYBOX_CONFIG_FEATURE_TRACEROUTE_VERBOSE
+ bool "Enable verbose output"
+ default y
+ depends on BUSYBOX_CONFIG_TRACEROUTE
+ help
+ Add some verbosity to traceroute. This includes among other things
+ hostnames and ICMP response types.
+
+config BUSYBOX_CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
+ bool "Enable loose source route"
+ default n
+ depends on BUSYBOX_CONFIG_TRACEROUTE
+ help
+ Add option to specify a loose source route gateway
+ (8 maximum).
+
+config BUSYBOX_CONFIG_FEATURE_TRACEROUTE_USE_ICMP
+ bool "Use ICMP instead of UDP"
+ default n
+ depends on BUSYBOX_CONFIG_TRACEROUTE
+ help
+ Add option -I to use ICMP ECHO instead of UDP datagrams.
+
+config BUSYBOX_CONFIG_TUNCTL
+ bool "tunctl"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ tunctl creates or deletes tun devices.
+
+config BUSYBOX_CONFIG_FEATURE_TUNCTL_UG
+ bool "Support owner:group assignment"
+ default n
+ depends on BUSYBOX_CONFIG_TUNCTL
+ help
+ Allow to specify owner and group of newly created interface.
+ 340 bytes of pure bloat. Say no here.
+
+source package/busybox/config/networking/udhcp/Config.in
+
+config BUSYBOX_CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS
+ string "ifup udhcpc command line options"
+ default "-R -n"
+ depends on BUSYBOX_CONFIG_IFUPDOWN && BUSYBOX_CONFIG_UDHCPC
+ help
+ Command line options to pass to udhcpc from ifup.
+ Intended to alter options not available in /etc/network/interfaces.
+ (IE: --syslog --background etc...)
+
+config BUSYBOX_CONFIG_UDPSVD
+ bool "udpsvd"
+ default n
+ help
+ udpsvd listens on an UDP port and runs a program for each new
+ connection.
+
+config BUSYBOX_CONFIG_VCONFIG
+ bool "vconfig"
+ default y
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Creates, removes, and configures VLAN interfaces
+
+config BUSYBOX_CONFIG_WGET
+ bool "wget"
+ default y
+ help
+ wget is a utility for non-interactive download of files from HTTP,
+ HTTPS, and FTP servers.
+
+config BUSYBOX_CONFIG_FEATURE_WGET_STATUSBAR
+ bool "Enable a nifty process meter (+2k)"
+ default y
+ depends on BUSYBOX_CONFIG_WGET
+ help
+ Enable the transfer progress bar for wget transfers.
+
+config BUSYBOX_CONFIG_FEATURE_WGET_AUTHENTICATION
+ bool "Enable HTTP authentication"
+ default y
+ depends on BUSYBOX_CONFIG_WGET
+ help
+ Support authenticated HTTP transfers.
+
+config BUSYBOX_CONFIG_FEATURE_WGET_LONG_OPTIONS
+ bool "Enable long options"
+ default y
+ depends on BUSYBOX_CONFIG_WGET && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Support long options for the wget applet.
+
+config BUSYBOX_CONFIG_FEATURE_WGET_TIMEOUT
+ bool "Enable read timeout option -T SEC"
+ default n
+ depends on BUSYBOX_CONFIG_WGET
+ help
+ Supports network read timeout for wget, so that wget will give
+ up and timeout when reading network data, through the -T command
+ line option. Currently only network data read timeout is
+ supported (i.e., timeout is not applied to the DNS nor TCP
+ connection initialization). When FEATURE_WGET_LONG_OPTIONS is
+ also enabled, the --timeout option will work in addition to -T.
+
+config BUSYBOX_CONFIG_ZCIP
+ bool "zcip"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ select BUSYBOX_CONFIG_FEATURE_SYSLOG
+ help
+ ZCIP provides ZeroConf IPv4 address selection, according to RFC 3927.
+ It's a daemon that allocates and defends a dynamically assigned
+ address on the 169.254/16 network, requiring no system administrator.
+
+ See http://www.zeroconf.org for further details, and "zcip.script"
+ in the busybox examples.
+
+endmenu
diff --git a/package/busybox/config/networking/udhcp/Config.in b/package/busybox/config/networking/udhcp/Config.in
new file mode 100644
index 000000000..f4d26ec9c
--- /dev/null
+++ b/package/busybox/config/networking/udhcp/Config.in
@@ -0,0 +1,155 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+
+
+config BUSYBOX_CONFIG_UDHCPD
+ bool "udhcp server (udhcpd)"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ udhcpd is a DHCP server geared primarily toward embedded systems,
+ while striving to be fully functional and RFC compliant.
+
+config BUSYBOX_CONFIG_DHCPRELAY
+ bool "dhcprelay"
+ default n
+ depends on BUSYBOX_CONFIG_UDHCPD
+ help
+ dhcprelay listens for dhcp requests on one or more interfaces
+ and forwards these requests to a different interface or dhcp
+ server.
+
+config BUSYBOX_CONFIG_DUMPLEASES
+ bool "Lease display utility (dumpleases)"
+ default n
+ depends on BUSYBOX_CONFIG_UDHCPD
+ help
+ dumpleases displays the leases written out by the udhcpd server.
+ Lease times are stored in the file by time remaining in lease, or
+ by the absolute time that it expires in seconds from epoch.
+
+config BUSYBOX_CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY
+ bool "Rewrite the lease file at every new acknowledge"
+ default n
+ depends on BUSYBOX_CONFIG_UDHCPD
+ help
+ If selected, udhcpd will write a new file with leases every
+ time a new lease has been accepted, thus eliminating the need
+ to send SIGUSR1 for the initial writing or updating. Any timed
+ rewriting remains undisturbed.
+
+config BUSYBOX_CONFIG_FEATURE_UDHCPD_BASE_IP_ON_MAC
+ bool "Select IP address based on client MAC"
+ default n
+ depends on BUSYBOX_CONFIG_UDHCPD
+ help
+ If selected, udhcpd will base its selection of IP address to offer
+ on the client's hardware address. Otherwise udhcpd uses the next
+ consecutive free address.
+
+ This reduces the frequency of IP address changes for clients
+ which let their lease expire, and makes consecutive DHCPOFFERS
+ for the same client to (almost always) contain the same
+ IP address.
+
+config BUSYBOX_CONFIG_DHCPD_LEASES_FILE
+ string "Absolute path to lease file"
+ default "/var/run/udhcpd.leases"
+ depends on BUSYBOX_CONFIG_UDHCPD
+ help
+ udhcpd stores addresses in a lease file. This is the absolute path
+ of the file. Normally it is safe to leave it untouched.
+
+config BUSYBOX_CONFIG_UDHCPC
+ bool "udhcp client (udhcpc)"
+ default y
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ udhcpc is a DHCP client geared primarily toward embedded systems,
+ while striving to be fully functional and RFC compliant.
+
+ The udhcp client negotiates a lease with the DHCP server and
+ runs a script when a lease is obtained or lost.
+
+config BUSYBOX_CONFIG_FEATURE_UDHCPC_ARPING
+ bool "Verify that the offered address is free, using ARP ping"
+ default n
+ depends on BUSYBOX_CONFIG_UDHCPC
+ help
+ If selected, udhcpc will send ARP probes and make sure
+ the offered address is really not in use by anyone. The client
+ will DHCPDECLINE the offer if the address is in use,
+ and restart the discover process.
+
+config BUSYBOX_CONFIG_FEATURE_UDHCP_PORT
+ bool "Enable '-P port' option for udhcpd and udhcpc"
+ default n
+ depends on BUSYBOX_CONFIG_UDHCPD || BUSYBOX_CONFIG_UDHCPC
+ help
+ At the cost of ~300 bytes, enables -P port option.
+ This feature is typically not needed.
+
+config BUSYBOX_CONFIG_UDHCP_DEBUG
+ int "Maximum verbosity level for udhcp applets (0..9)"
+ default 0
+ range 0 9
+ depends on BUSYBOX_CONFIG_UDHCPD || BUSYBOX_CONFIG_UDHCPC || BUSYBOX_CONFIG_DHCPRELAY
+ help
+ Verbosity can be increased with multiple -v options.
+ This option controls how high it can be cranked up.
+
+ Bigger values result in bigger code. Levels above 1
+ are very verbose and useful for debugging only.
+
+config BUSYBOX_CONFIG_FEATURE_UDHCP_RFC3397
+ bool "Support for RFC3397 domain search (experimental)"
+ default y
+ depends on BUSYBOX_CONFIG_UDHCPD || BUSYBOX_CONFIG_UDHCPC
+ help
+ If selected, both client and server will support passing of domain
+ search lists via option 119, specified in RFC 3397,
+ and SIP servers option 120, specified in RFC 3361.
+
+config BUSYBOX_CONFIG_FEATURE_UDHCP_8021Q
+ bool "Support for 802.1Q VLAN parameters"
+ default n
+ depends on BUSYBOX_CONFIG_UDHCPD || BUSYBOX_CONFIG_UDHCPC
+ help
+ If selected, both client and server will support passing of VLAN
+ ID and priority via options 132 and 133 as per 802.1Q.
+
+config BUSYBOX_CONFIG_UDHCPC_DEFAULT_SCRIPT
+ string "Absolute path to config script"
+ default "/usr/share/udhcpc/default.script"
+ depends on BUSYBOX_CONFIG_UDHCPC
+ help
+ This script is called after udhcpc receives an answer. See
+ examples/udhcp for a working example. Normally it is safe
+ to leave this untouched.
+
+config BUSYBOX_CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS
+ int "DHCP options slack buffer size"
+ default 80
+ range 0 924
+ depends on BUSYBOX_CONFIG_UDHCPD || BUSYBOX_CONFIG_UDHCPC
+ help
+ Some buggy DHCP servers send DHCP offer packets with option
+ field larger than we expect (which might also be considered a
+ buffer overflow attempt). These packets are normally discarded.
+ If circumstances beyond your control force you to support such
+ servers, this may help. The upper limit (924) makes dhcpc accept
+ even 1500 byte packets (maximum-sized ethernet packets).
+
+ This option does not make dhcp[cd] emit non-standard
+ sized packets.
+
+ Known buggy DHCP servers:
+ 3Com OfficeConnect Remote 812 ADSL Router:
+ seems to confuse maximum allowed UDP packet size with
+ maximum size of entire IP packet, and sends packets which are
+ 28 bytes too large.
+ Seednet (ISP) VDSL: sends packets 2 bytes too large.
diff --git a/package/busybox/config/printutils/Config.in b/package/busybox/config/printutils/Config.in
new file mode 100644
index 000000000..ca2ea9f56
--- /dev/null
+++ b/package/busybox/config/printutils/Config.in
@@ -0,0 +1,29 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Print Utilities"
+
+
+
+config BUSYBOX_CONFIG_LPD
+ bool "lpd"
+ default n
+ help
+ lpd is a print spooling daemon.
+
+config BUSYBOX_CONFIG_LPR
+ bool "lpr"
+ default n
+ help
+ lpr sends files (or standard input) to a print spooling daemon.
+
+config BUSYBOX_CONFIG_LPQ
+ bool "lpq"
+ default n
+ help
+ lpq is a print spool queue examination and manipulation program.
+
+endmenu
diff --git a/package/busybox/config/procps/Config.in b/package/busybox/config/procps/Config.in
new file mode 100644
index 000000000..d8d72a75e
--- /dev/null
+++ b/package/busybox/config/procps/Config.in
@@ -0,0 +1,260 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Process Utilities"
+
+config BUSYBOX_CONFIG_IOSTAT
+ bool "iostat"
+ default n
+ help
+ Report CPU and I/O statistics
+config BUSYBOX_CONFIG_MPSTAT
+ bool "mpstat"
+ default n
+ help
+ Per-processor statistics
+config BUSYBOX_CONFIG_NMETER
+ bool "nmeter"
+ default n
+ help
+ Prints selected system stats continuously, one line per update.
+config BUSYBOX_CONFIG_PMAP
+ bool "pmap"
+ default n
+ help
+ Display processes' memory mappings.
+config BUSYBOX_CONFIG_POWERTOP
+ bool "powertop"
+ default n
+ help
+ Analyze power consumption on Intel-based laptops
+config BUSYBOX_CONFIG_PSTREE
+ bool "pstree"
+ default n
+ help
+ Display a tree of processes.
+config BUSYBOX_CONFIG_PWDX
+ bool "pwdx"
+ default n
+ help
+ Report current working directory of a process
+config BUSYBOX_CONFIG_SMEMCAP
+ bool "smemcap"
+ default n
+ help
+ smemcap is a tool for capturing process data for smem,
+ a memory usage statistic tool.
+config BUSYBOX_CONFIG_UPTIME
+ bool "uptime"
+ default y
+ select BUSYBOX_CONFIG_PLATFORM_LINUX #sysinfo()
+ help
+ uptime gives a one line display of the current time, how long
+ the system has been running, how many users are currently logged
+ on, and the system load averages for the past 1, 5, and 15 minutes.
+
+config BUSYBOX_CONFIG_FEATURE_UPTIME_UTMP_SUPPORT
+ bool "Support for showing the number of users"
+ default n
+ depends on BUSYBOX_CONFIG_UPTIME && BUSYBOX_CONFIG_FEATURE_UTMP
+ help
+ Makes uptime display the number of users currently logged on.
+
+config BUSYBOX_CONFIG_FREE
+ bool "free"
+ default y
+ select BUSYBOX_CONFIG_PLATFORM_LINUX #sysinfo()
+ help
+ free displays the total amount of free and used physical and swap
+ memory in the system, as well as the buffers used by the kernel.
+ The shared memory column should be ignored; it is obsolete.
+
+config BUSYBOX_CONFIG_FUSER
+ bool "fuser"
+ default n
+ help
+ fuser lists all PIDs (Process IDs) that currently have a given
+ file open. fuser can also list all PIDs that have a given network
+ (TCP or UDP) port open.
+
+config BUSYBOX_CONFIG_KILL
+ bool "kill"
+ default y
+ help
+ The command kill sends the specified signal to the specified
+ process or process group. If no signal is specified, the TERM
+ signal is sent.
+
+config BUSYBOX_CONFIG_KILLALL
+ bool "killall"
+ default y
+ depends on BUSYBOX_CONFIG_KILL
+ help
+ killall sends a signal to all processes running any of the
+ specified commands. If no signal name is specified, SIGTERM is
+ sent.
+
+config BUSYBOX_CONFIG_KILLALL5
+ bool "killall5"
+ default n
+ depends on BUSYBOX_CONFIG_KILL
+
+config BUSYBOX_CONFIG_PGREP
+ bool "pgrep"
+ default y
+ help
+ Look for processes by name.
+
+config BUSYBOX_CONFIG_PIDOF
+ bool "pidof"
+ default y
+ help
+ Pidof finds the process id's (pids) of the named programs. It prints
+ those id's on the standard output.
+
+config BUSYBOX_CONFIG_FEATURE_PIDOF_SINGLE
+ bool "Enable argument for single shot (-s)"
+ default n
+ depends on BUSYBOX_CONFIG_PIDOF
+ help
+ Support argument '-s' for returning only the first pid found.
+
+config BUSYBOX_CONFIG_FEATURE_PIDOF_OMIT
+ bool "Enable argument for omitting pids (-o)"
+ default n
+ depends on BUSYBOX_CONFIG_PIDOF
+ help
+ Support argument '-o' for omitting the given pids in output.
+ The special pid %PPID can be used to name the parent process
+ of the pidof, in other words the calling shell or shell script.
+
+config BUSYBOX_CONFIG_PKILL
+ bool "pkill"
+ default n
+ help
+ Send signals to processes by name.
+
+config BUSYBOX_CONFIG_PS
+ bool "ps"
+ default y
+ help
+ ps gives a snapshot of the current processes.
+
+config BUSYBOX_CONFIG_FEATURE_PS_WIDE
+ bool "Enable wide output option (-w)"
+ default y
+ depends on BUSYBOX_CONFIG_PS
+ help
+ Support argument 'w' for wide output.
+ If given once, 132 chars are printed, and if given more
+ than once, the length is unlimited.
+
+config BUSYBOX_CONFIG_FEATURE_PS_TIME
+ bool "Enable time and elapsed time output"
+ default n
+ depends on BUSYBOX_CONFIG_PS && BUSYBOX_CONFIG_DESKTOP
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Support -o time and -o etime output specifiers.
+
+config BUSYBOX_CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS
+ bool "Enable additional ps columns"
+ default n
+ depends on BUSYBOX_CONFIG_PS && BUSYBOX_CONFIG_DESKTOP
+ help
+ Support -o rgroup, -o ruser, -o nice output specifiers.
+
+config BUSYBOX_CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS
+ bool "Support Linux prior to 2.4.0 and non-ELF systems"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_PS_TIME
+ help
+ Include support for measuring HZ on old kernels and non-ELF systems
+ (if you are on Linux 2.4.0+ and use ELF, you don't need this)
+
+config BUSYBOX_CONFIG_RENICE
+ bool "renice"
+ default n
+ help
+ Renice alters the scheduling priority of one or more running
+ processes.
+
+config BUSYBOX_CONFIG_BB_SYSCTL
+ bool "sysctl"
+ default y
+ help
+ Configure kernel parameters at runtime.
+
+config BUSYBOX_CONFIG_TOP
+ bool "top"
+ default y
+ help
+ The top program provides a dynamic real-time view of a running
+ system.
+
+config BUSYBOX_CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+ bool "Show CPU per-process usage percentage"
+ default y
+ depends on BUSYBOX_CONFIG_TOP
+ help
+ Make top display CPU usage for each process.
+ This adds about 2k.
+
+config BUSYBOX_CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS
+ bool "Show CPU global usage percentage"
+ default y
+ depends on BUSYBOX_CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+ help
+ Makes top display "CPU: NN% usr NN% sys..." line.
+ This adds about 0.5k.
+
+config BUSYBOX_CONFIG_FEATURE_TOP_SMP_CPU
+ bool "SMP CPU usage display ('c' key)"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS
+ help
+ Allow 'c' key to switch between individual/cumulative CPU stats
+ This adds about 0.5k.
+
+config BUSYBOX_CONFIG_FEATURE_TOP_DECIMALS
+ bool "Show 1/10th of a percent in CPU/mem statistics"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+ help
+ Show 1/10th of a percent in CPU/mem statistics.
+ This adds about 0.3k.
+
+config BUSYBOX_CONFIG_FEATURE_TOP_SMP_PROCESS
+ bool "Show CPU process runs on ('j' field)"
+ default n
+ depends on BUSYBOX_CONFIG_TOP
+ help
+ Show CPU where process was last found running on.
+ This is the 'j' field.
+
+config BUSYBOX_CONFIG_FEATURE_TOPMEM
+ bool "Topmem command ('s' key)"
+ default n
+ depends on BUSYBOX_CONFIG_TOP
+ help
+ Enable 's' in top (gives lots of memory info).
+
+config BUSYBOX_CONFIG_FEATURE_SHOW_THREADS
+ bool "Support for showing threads in ps/pstree/top"
+ default n
+ depends on BUSYBOX_CONFIG_PS || BUSYBOX_CONFIG_TOP || BUSYBOX_CONFIG_PSTREE
+ help
+ Enables the ps -T option, showing of threads in pstree,
+ and 'h' command in top.
+
+config BUSYBOX_CONFIG_WATCH
+ bool "watch"
+ default n
+ help
+ watch is used to execute a program periodically, showing
+ output to the screen.
+
+endmenu
diff --git a/package/busybox/config/runit/Config.in b/package/busybox/config/runit/Config.in
new file mode 100644
index 000000000..9d7c5970a
--- /dev/null
+++ b/package/busybox/config/runit/Config.in
@@ -0,0 +1,90 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Runit Utilities"
+
+
+
+config BUSYBOX_CONFIG_RUNSV
+ bool "runsv"
+ default n
+ help
+ runsv starts and monitors a service and optionally an appendant log
+ service.
+
+config BUSYBOX_CONFIG_RUNSVDIR
+ bool "runsvdir"
+ default n
+ help
+ runsvdir starts a runsv process for each subdirectory, or symlink to
+ a directory, in the services directory dir, up to a limit of 1000
+ subdirectories, and restarts a runsv process if it terminates.
+
+config BUSYBOX_CONFIG_FEATURE_RUNSVDIR_LOG
+ bool "Enable scrolling argument log"
+ depends on BUSYBOX_CONFIG_RUNSVDIR
+ default n
+ help
+ Enable feature where second parameter of runsvdir holds last error
+ message (viewable via top/ps). Otherwise (feature is off
+ or no parameter), error messages go to stderr only.
+
+config BUSYBOX_CONFIG_SV
+ bool "sv"
+ default n
+ help
+ sv reports the current status and controls the state of services
+ monitored by the runsv supervisor.
+
+config BUSYBOX_CONFIG_SV_DEFAULT_SERVICE_DIR
+ string "Default directory for services"
+ default "/var/service"
+ depends on BUSYBOX_CONFIG_SV
+ help
+ Default directory for services.
+ Defaults to "/var/service"
+
+config BUSYBOX_CONFIG_SVLOGD
+ bool "svlogd"
+ default n
+ help
+ svlogd continuously reads log data from its standard input, optionally
+ filters log messages, and writes the data to one or more automatically
+ rotated logs.
+
+config BUSYBOX_CONFIG_CHPST
+ bool "chpst"
+ default n
+ help
+ chpst changes the process state according to the given options, and
+ execs specified program.
+
+config BUSYBOX_CONFIG_SETUIDGID
+ bool "setuidgid"
+ default n
+ help
+ Sets soft resource limits as specified by options
+
+config BUSYBOX_CONFIG_ENVUIDGID
+ bool "envuidgid"
+ default n
+ help
+ Sets $UID to account's uid and $GID to account's gid
+
+config BUSYBOX_CONFIG_ENVDIR
+ bool "envdir"
+ default n
+ help
+ Sets various environment variables as specified by files
+ in the given directory
+
+config BUSYBOX_CONFIG_SOFTLIMIT
+ bool "softlimit"
+ default n
+ help
+ Sets soft resource limits as specified by options
+
+endmenu
diff --git a/package/busybox/config/selinux/Config.in b/package/busybox/config/selinux/Config.in
new file mode 100644
index 000000000..e7317ca81
--- /dev/null
+++ b/package/busybox/config/selinux/Config.in
@@ -0,0 +1,125 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "SELinux Utilities"
+ depends on BUSYBOX_CONFIG_SELINUX
+
+
+
+config BUSYBOX_CONFIG_CHCON
+ bool "chcon"
+ default n
+ depends on BUSYBOX_CONFIG_SELINUX
+ help
+ Enable support to change the security context of file.
+
+config BUSYBOX_CONFIG_FEATURE_CHCON_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_CHCON && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Support long options for the chcon applet.
+
+config BUSYBOX_CONFIG_GETENFORCE
+ bool "getenforce"
+ default n
+ depends on BUSYBOX_CONFIG_SELINUX
+ help
+ Enable support to get the current mode of SELinux.
+
+config BUSYBOX_CONFIG_GETSEBOOL
+ bool "getsebool"
+ default n
+ depends on BUSYBOX_CONFIG_SELINUX
+ help
+ Enable support to get SELinux boolean values.
+
+config BUSYBOX_CONFIG_LOAD_POLICY
+ bool "load_policy"
+ default n
+ depends on BUSYBOX_CONFIG_SELINUX
+ help
+ Enable support to load SELinux policy.
+
+config BUSYBOX_CONFIG_MATCHPATHCON
+ bool "matchpathcon"
+ default n
+ depends on BUSYBOX_CONFIG_SELINUX
+ help
+ Enable support to get default security context of the
+ specified path from the file contexts configuration.
+
+config BUSYBOX_CONFIG_RESTORECON
+ bool "restorecon"
+ default n
+ depends on BUSYBOX_CONFIG_SELINUX
+ help
+ Enable support to relabel files. The feature is almost
+ the same as setfiles, but usage is a little different.
+
+config BUSYBOX_CONFIG_RUNCON
+ bool "runcon"
+ default n
+ depends on BUSYBOX_CONFIG_SELINUX
+ help
+ Enable support to run command in speficied security context.
+
+config BUSYBOX_CONFIG_FEATURE_RUNCON_LONG_OPTIONS
+ bool "Enable long options"
+ default n
+ depends on BUSYBOX_CONFIG_RUNCON && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ Support long options for the runcon applet.
+
+config BUSYBOX_CONFIG_SELINUXENABLED
+ bool "selinuxenabled"
+ default n
+ depends on BUSYBOX_CONFIG_SELINUX
+ help
+ Enable support for this command to be used within shell scripts
+ to determine if selinux is enabled.
+
+config BUSYBOX_CONFIG_SETENFORCE
+ bool "setenforce"
+ default n
+ depends on BUSYBOX_CONFIG_SELINUX
+ help
+ Enable support to modify the mode SELinux is running in.
+
+config BUSYBOX_CONFIG_SETFILES
+ bool "setfiles"
+ default n
+ depends on BUSYBOX_CONFIG_SELINUX
+ help
+ Enable support to modify to relabel files.
+ Notice: If you built libselinux with -D_FILE_OFFSET_BITS=64,
+ (It is default in libselinux's Makefile), you _must_ enable
+ CONFIG_LFS.
+
+config BUSYBOX_CONFIG_FEATURE_SETFILES_CHECK_OPTION
+ bool "Enable check option"
+ default n
+ depends on BUSYBOX_CONFIG_SETFILES
+ help
+ Support "-c" option (check the validity of the contexts against
+ the specified binary policy) for setfiles. Requires libsepol.
+
+config BUSYBOX_CONFIG_SETSEBOOL
+ bool "setsebool"
+ default n
+ depends on BUSYBOX_CONFIG_SELINUX
+ help
+ Enable support for change boolean.
+ semanage and -P option is not supported yet.
+
+config BUSYBOX_CONFIG_SESTATUS
+ bool "sestatus"
+ default n
+ depends on BUSYBOX_CONFIG_SELINUX
+ help
+ Displays the status of SELinux.
+
+endmenu
diff --git a/package/busybox/config/shell/Config.in b/package/busybox/config/shell/Config.in
new file mode 100644
index 000000000..a271a386d
--- /dev/null
+++ b/package/busybox/config/shell/Config.in
@@ -0,0 +1,433 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Shells"
+
+config BUSYBOX_CONFIG_ASH
+ bool "ash"
+ default y
+ depends on !BUSYBOX_CONFIG_NOMMU
+ help
+ Tha 'ash' shell adds about 60k in the default configuration and is
+ the most complete and most pedantically correct shell included with
+ busybox. This shell is actually a derivative of the Debian 'dash'
+ shell (by Herbert Xu), which was created by porting the 'ash' shell
+ (written by Kenneth Almquist) from NetBSD.
+
+config BUSYBOX_CONFIG_ASH_BASH_COMPAT
+ bool "bash-compatible extensions"
+ default y
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ Enable bash-compatible extensions.
+
+config BUSYBOX_CONFIG_ASH_IDLE_TIMEOUT
+ bool "Idle timeout variable"
+ default n
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ Enables bash-like auto-logout after $TMOUT seconds of idle time.
+
+config BUSYBOX_CONFIG_ASH_JOB_CONTROL
+ bool "Job control"
+ default y
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ Enable job control in the ash shell.
+
+config BUSYBOX_CONFIG_ASH_ALIAS
+ bool "Alias support"
+ default y
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ Enable alias support in the ash shell.
+
+config BUSYBOX_CONFIG_ASH_GETOPTS
+ bool "Builtin getopt to parse positional parameters"
+ default y
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ Enable support for getopts builtin in ash.
+
+config BUSYBOX_CONFIG_ASH_BUILTIN_ECHO
+ bool "Builtin version of 'echo'"
+ default y
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ Enable support for echo builtin in ash.
+
+config BUSYBOX_CONFIG_ASH_BUILTIN_PRINTF
+ bool "Builtin version of 'printf'"
+ default y
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ Enable support for printf builtin in ash.
+
+config BUSYBOX_CONFIG_ASH_BUILTIN_TEST
+ bool "Builtin version of 'test'"
+ default y
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ Enable support for test builtin in ash.
+
+config BUSYBOX_CONFIG_ASH_CMDCMD
+ bool "'command' command to override shell builtins"
+ default y
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ Enable support for the ash 'command' builtin, which allows
+ you to run the specified command with the specified arguments,
+ even when there is an ash builtin command with the same name.
+
+config BUSYBOX_CONFIG_ASH_MAIL
+ bool "Check for new mail on interactive shells"
+ default n
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ Enable "check for new mail" function in the ash shell.
+
+config BUSYBOX_CONFIG_ASH_OPTIMIZE_FOR_SIZE
+ bool "Optimize for size instead of speed"
+ default n
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ Compile ash for reduced size at the price of speed.
+
+config BUSYBOX_CONFIG_ASH_RANDOM_SUPPORT
+ bool "Pseudorandom generator and $RANDOM variable"
+ default n
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ Enable pseudorandom generator and dynamic variable "$RANDOM".
+ Each read of "$RANDOM" will generate a new pseudorandom value.
+ You can reset the generator by using a specified start value.
+ After "unset RANDOM" the generator will switch off and this
+ variable will no longer have special treatment.
+
+config BUSYBOX_CONFIG_ASH_EXPAND_PRMT
+ bool "Expand prompt string"
+ default y
+ depends on BUSYBOX_CONFIG_ASH
+ help
+ "PS#" may contain volatile content, such as backquote commands.
+ This option recreates the prompt string from the environment
+ variable each time it is displayed.
+
+config BUSYBOX_CONFIG_CTTYHACK
+ bool "cttyhack"
+ default n
+ help
+ One common problem reported on the mailing list is the "can't
+ access tty; job control turned off" error message, which typically
+ appears when one tries to use a shell with stdin/stdout on
+ /dev/console.
+ This device is special - it cannot be a controlling tty.
+
+ The proper solution is to use the correct device instead of
+ /dev/console.
+
+ cttyhack provides a "quick and dirty" solution to this problem.
+ It analyzes stdin with various ioctls, trying to determine whether
+ it is a /dev/ttyN or /dev/ttySN (virtual terminal or serial line).
+ On Linux it also checks sysfs for a pointer to the active console.
+ If cttyhack is able to find the real console device, it closes
+ stdin/out/err and reopens that device.
+ Then it executes the given program. Opening the device will make
+ that device a controlling tty. This may require cttyhack
+ to be a session leader.
+
+ Example for /etc/inittab (for busybox init):
+
+ ::respawn:/bin/cttyhack /bin/sh
+
+ Starting an interactive shell from boot shell script:
+
+ setsid cttyhack sh
+
+ Giving controlling tty to shell running with PID 1:
+
+ # exec cttyhack sh
+
+ Without cttyhack, you need to know exact tty name,
+ and do something like this:
+
+ # exec setsid sh -c 'exec sh </dev/tty1 >/dev/tty1 2>&1'
+
+config BUSYBOX_CONFIG_HUSH
+ bool "hush"
+ default n
+ help
+ hush is a small shell (25k). It handles the normal flow control
+ constructs such as if/then/elif/else/fi, for/in/do/done, while loops,
+ case/esac. Redirections, here documents, $((arithmetic))
+ and functions are supported.
+
+ It will compile and work on no-mmu systems.
+
+ It does not handle select, aliases, tilde expansion,
+ &>file and >&file redirection of stdout+stderr.
+
+config BUSYBOX_CONFIG_HUSH_BASH_COMPAT
+ bool "bash-compatible extensions"
+ default y
+ depends on BUSYBOX_CONFIG_HUSH
+ help
+ Enable bash-compatible extensions.
+
+config BUSYBOX_CONFIG_HUSH_BRACE_EXPANSION
+ bool "Brace expansion"
+ default n
+ depends on BUSYBOX_CONFIG_HUSH_BASH_COMPAT
+ help
+ Enable {abc,def} extension.
+
+config BUSYBOX_CONFIG_HUSH_HELP
+ bool "help builtin"
+ default y
+ depends on BUSYBOX_CONFIG_HUSH
+ help
+ Enable help builtin in hush. Code size + ~1 kbyte.
+
+config BUSYBOX_CONFIG_HUSH_INTERACTIVE
+ bool "Interactive mode"
+ default y
+ depends on BUSYBOX_CONFIG_HUSH
+ help
+ Enable interactive mode (prompt and command editing).
+ Without this, hush simply reads and executes commands
+ from stdin just like a shell script from a file.
+ No prompt, no PS1/PS2 magic shell variables.
+
+config BUSYBOX_CONFIG_HUSH_SAVEHISTORY
+ bool "Save command history to .hush_history"
+ default n
+ depends on BUSYBOX_CONFIG_HUSH_INTERACTIVE && BUSYBOX_CONFIG_FEATURE_EDITING_SAVEHISTORY
+ help
+ Enable history saving in hush.
+
+config BUSYBOX_CONFIG_HUSH_JOB
+ bool "Job control"
+ default y
+ depends on BUSYBOX_CONFIG_HUSH_INTERACTIVE
+ help
+ Enable job control: Ctrl-Z backgrounds, Ctrl-C interrupts current
+ command (not entire shell), fg/bg builtins work. Without this option,
+ "cmd &" still works by simply spawning a process and immediately
+ prompting for next command (or executing next command in a script),
+ but no separate process group is formed.
+
+config BUSYBOX_CONFIG_HUSH_TICK
+ bool "Process substitution"
+ default y
+ depends on BUSYBOX_CONFIG_HUSH
+ help
+ Enable process substitution `command` and $(command) in hush.
+
+config BUSYBOX_CONFIG_HUSH_IF
+ bool "Support if/then/elif/else/fi"
+ default y
+ depends on BUSYBOX_CONFIG_HUSH
+ help
+ Enable if/then/elif/else/fi in hush.
+
+config BUSYBOX_CONFIG_HUSH_LOOPS
+ bool "Support for, while and until loops"
+ default y
+ depends on BUSYBOX_CONFIG_HUSH
+ help
+ Enable for, while and until loops in hush.
+
+config BUSYBOX_CONFIG_HUSH_CASE
+ bool "Support case ... esac statement"
+ default y
+ depends on BUSYBOX_CONFIG_HUSH
+ help
+ Enable case ... esac statement in hush. +400 bytes.
+
+config BUSYBOX_CONFIG_HUSH_FUNCTIONS
+ bool "Support funcname() { commands; } syntax"
+ default y
+ depends on BUSYBOX_CONFIG_HUSH
+ help
+ Enable support for shell functions in hush. +800 bytes.
+
+config BUSYBOX_CONFIG_HUSH_LOCAL
+ bool "Support local builtin"
+ default y
+ depends on BUSYBOX_CONFIG_HUSH_FUNCTIONS
+ help
+ Enable support for local variables in functions.
+
+config BUSYBOX_CONFIG_HUSH_RANDOM_SUPPORT
+ bool "Pseudorandom generator and $RANDOM variable"
+ default n
+ depends on BUSYBOX_CONFIG_HUSH
+ help
+ Enable pseudorandom generator and dynamic variable "$RANDOM".
+ Each read of "$RANDOM" will generate a new pseudorandom value.
+
+config BUSYBOX_CONFIG_HUSH_EXPORT_N
+ bool "Support 'export -n' option"
+ default y
+ depends on BUSYBOX_CONFIG_HUSH
+ help
+ export -n unexports variables. It is a bash extension.
+
+config BUSYBOX_CONFIG_HUSH_MODE_X
+ bool "Support 'hush -x' option and 'set -x' command"
+ default n
+ depends on BUSYBOX_CONFIG_HUSH
+ help
+ This instructs hush to print commands before execution.
+ Adds ~300 bytes.
+
+config BUSYBOX_CONFIG_MSH
+ bool "msh (deprecated: aliased to hush)"
+ default n
+ select BUSYBOX_CONFIG_HUSH
+ help
+ msh is deprecated and will be removed, please migrate to hush.
+
+
+choice
+ prompt "Choose which shell is aliased to 'sh' name"
+ default BUSYBOX_CONFIG_FEATURE_SH_IS_ASH
+ help
+ Choose which shell you want to be executed by 'sh' alias.
+ The ash shell is the most bash compatible and full featured one.
+
+# note: cannot use "select ASH" here, it breaks "make allnoconfig"
+config BUSYBOX_CONFIG_FEATURE_SH_IS_ASH
+ depends on BUSYBOX_CONFIG_ASH
+ bool "ash"
+ depends on !BUSYBOX_CONFIG_NOMMU
+
+config BUSYBOX_CONFIG_FEATURE_SH_IS_HUSH
+ depends on BUSYBOX_CONFIG_HUSH
+ bool "hush"
+
+config BUSYBOX_CONFIG_FEATURE_SH_IS_NONE
+ bool "none"
+
+endchoice
+
+choice
+ prompt "Choose which shell is aliased to 'bash' name"
+ default BUSYBOX_CONFIG_FEATURE_BASH_IS_NONE
+ help
+ Choose which shell you want to be executed by 'bash' alias.
+ The ash shell is the most bash compatible and full featured one.
+
+ Note that selecting this option does not switch on any bash
+ compatibility code. It merely makes it possible to install
+ /bin/bash (sym)link and run scripts which start with
+ #!/bin/bash line.
+
+ Many systems use it in scripts which use bash-specific features,
+ even simple ones like $RANDOM. Without this option, busybox
+ can't be used for running them because it won't recongnize
+ "bash" as a supported applet name.
+
+config BUSYBOX_CONFIG_FEATURE_BASH_IS_ASH
+ depends on BUSYBOX_CONFIG_ASH
+ bool "ash"
+ depends on !BUSYBOX_CONFIG_NOMMU
+
+config BUSYBOX_CONFIG_FEATURE_BASH_IS_HUSH
+ depends on BUSYBOX_CONFIG_HUSH
+ bool "hush"
+
+config BUSYBOX_CONFIG_FEATURE_BASH_IS_NONE
+ bool "none"
+
+endchoice
+
+
+config BUSYBOX_CONFIG_SH_MATH_SUPPORT
+ bool "POSIX math support"
+ default y
+ depends on BUSYBOX_CONFIG_ASH || BUSYBOX_CONFIG_HUSH
+ help
+ Enable math support in the shell via $((...)) syntax.
+
+config BUSYBOX_CONFIG_SH_MATH_SUPPORT_64
+ bool "Extend POSIX math support to 64 bit"
+ default y
+ depends on BUSYBOX_CONFIG_SH_MATH_SUPPORT
+ help
+ Enable 64-bit math support in the shell. This will make the shell
+ slightly larger, but will allow computation with very large numbers.
+ This is not in POSIX, so do not rely on this in portable code.
+
+config BUSYBOX_CONFIG_FEATURE_SH_EXTRA_QUIET
+ bool "Hide message on interactive shell startup"
+ default n
+ depends on BUSYBOX_CONFIG_HUSH || BUSYBOX_CONFIG_ASH
+ help
+ Remove the busybox introduction when starting a shell.
+
+config BUSYBOX_CONFIG_FEATURE_SH_STANDALONE
+ bool "Standalone shell"
+ default n
+ depends on (BUSYBOX_CONFIG_HUSH || BUSYBOX_CONFIG_ASH) && BUSYBOX_CONFIG_FEATURE_PREFER_APPLETS
+ help
+ This option causes busybox shells to use busybox applets
+ in preference to executables in the PATH whenever possible. For
+ example, entering the command 'ifconfig' into the shell would cause
+ busybox to use the ifconfig busybox applet. Specifying the fully
+ qualified executable name, such as '/sbin/ifconfig' will still
+ execute the /sbin/ifconfig executable on the filesystem. This option
+ is generally used when creating a statically linked version of busybox
+ for use as a rescue shell, in the event that you screw up your system.
+
+ This is implemented by re-execing /proc/self/exe (typically)
+ with right parameters. Some selected applets ("NOFORK" applets)
+ can even be executed without creating new process.
+ Instead, busybox will call <applet>_main() internally.
+
+ However, this causes problems in chroot jails without mounted /proc
+ and with ps/top (command name can be shown as 'exe' for applets
+ started this way).
+# untrue?
+# Note that this will *also* cause applets to take precedence
+# over shell builtins of the same name. So turning this on will
+# eliminate any performance gained by turning on the builtin "echo"
+# and "test" commands in ash.
+# untrue?
+# Note that when using this option, the shell will attempt to directly
+# run '/bin/busybox'. If you do not have the busybox binary sitting in
+# that exact location with that exact name, this option will not work at
+# all.
+
+config BUSYBOX_CONFIG_FEATURE_SH_NOFORK
+ bool "Run 'nofork' applets directly"
+ default n
+ depends on (BUSYBOX_CONFIG_HUSH || BUSYBOX_CONFIG_ASH) && BUSYBOX_CONFIG_FEATURE_PREFER_APPLETS
+ help
+ This option causes busybox shells to not execute typical
+ fork/exec/wait sequence, but call <applet>_main directly,
+ if possible. (Sometimes it is not possible: for example,
+ this is not possible in pipes).
+
+ This will be done only for some applets (those which are marked
+ NOFORK in include/applets.h).
+
+ This may significantly speed up some shell scripts.
+
+ This feature is relatively new. Use with care. Report bugs
+ to project mailing list.
+
+config BUSYBOX_CONFIG_FEATURE_SH_HISTFILESIZE
+ bool "Use $HISTFILESIZE"
+ default n
+ depends on BUSYBOX_CONFIG_HUSH || BUSYBOX_CONFIG_ASH
+ help
+ This option makes busybox shells to use $HISTFILESIZE variable
+ to set shell history size. Note that its max value is capped
+ by "History size" setting in library tuning section.
+
+
+endmenu
diff --git a/package/busybox/config/sysklogd/Config.in b/package/busybox/config/sysklogd/Config.in
new file mode 100644
index 000000000..20e1aff06
--- /dev/null
+++ b/package/busybox/config/sysklogd/Config.in
@@ -0,0 +1,154 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "System Logging Utilities"
+
+
+
+config BUSYBOX_CONFIG_SYSLOGD
+ bool "syslogd"
+ default y
+ help
+ The syslogd utility is used to record logs of all the
+ significant events that occur on a system. Every
+ message that is logged records the date and time of the
+ event, and will generally also record the name of the
+ application that generated the message. When used in
+ conjunction with klogd, messages from the Linux kernel
+ can also be recorded. This is terribly useful,
+ especially for finding what happened when something goes
+ wrong. And something almost always will go wrong if
+ you wait long enough....
+
+config BUSYBOX_CONFIG_FEATURE_ROTATE_LOGFILE
+ bool "Rotate message files"
+ default y
+ depends on BUSYBOX_CONFIG_SYSLOGD
+ help
+ This enables syslogd to rotate the message files
+ on his own. No need to use an external rotatescript.
+
+config BUSYBOX_CONFIG_FEATURE_REMOTE_LOG
+ bool "Remote Log support"
+ default y
+ depends on BUSYBOX_CONFIG_SYSLOGD
+ help
+ When you enable this feature, the syslogd utility can
+ be used to send system log messages to another system
+ connected via a network. This allows the remote
+ machine to log all the system messages, which can be
+ terribly useful for reducing the number of serial
+ cables you use. It can also be a very good security
+ measure to prevent system logs from being tampered with
+ by an intruder.
+
+config BUSYBOX_CONFIG_FEATURE_SYSLOGD_DUP
+ bool "Support -D (drop dups) option"
+ default n
+ depends on BUSYBOX_CONFIG_SYSLOGD
+ help
+ Option -D instructs syslogd to drop consecutive messages
+ which are totally the same.
+
+config BUSYBOX_CONFIG_FEATURE_SYSLOGD_CFG
+ bool "Support syslog.conf"
+ default n
+ depends on BUSYBOX_CONFIG_SYSLOGD
+ help
+ Supports restricted syslogd config. See docs/syslog.conf.txt
+
+config BUSYBOX_CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE
+ int "Read buffer size in bytes"
+ default 256
+ range 256 20000
+ depends on BUSYBOX_CONFIG_SYSLOGD
+ help
+ This option sets the size of the syslog read buffer.
+ Actual memory usage increases around five times the
+ change done here.
+
+config BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG
+ bool "Circular Buffer support"
+ default y
+ depends on BUSYBOX_CONFIG_SYSLOGD
+ help
+ When you enable this feature, the syslogd utility will
+ use a circular buffer to record system log messages.
+ When the buffer is filled it will continue to overwrite
+ the oldest messages. This can be very useful for
+ systems with little or no permanent storage, since
+ otherwise system logs can eventually fill up your
+ entire filesystem, which may cause your system to
+ break badly.
+
+config BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE
+ int "Circular buffer size in Kbytes (minimum 4KB)"
+ default 16
+ range 4 2147483647
+ depends on BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG
+ help
+ This option sets the size of the circular buffer
+ used to record system log messages.
+
+config BUSYBOX_CONFIG_LOGREAD
+ bool "logread"
+ default y
+ depends on BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG
+ help
+ If you enabled Circular Buffer support, you almost
+ certainly want to enable this feature as well. This
+ utility will allow you to read the messages that are
+ stored in the syslogd circular buffer.
+
+config BUSYBOX_CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING
+ bool "Double buffering"
+ default n
+ depends on BUSYBOX_CONFIG_LOGREAD
+ help
+ 'logread' ouput to slow serial terminals can have
+ side effects on syslog because of the semaphore.
+ This option make logread to double buffer copy
+ from circular buffer, minimizing semaphore
+ contention at some minor memory expense.
+
+config BUSYBOX_CONFIG_KLOGD
+ bool "klogd"
+ default y
+ help
+ klogd is a utility which intercepts and logs all
+ messages from the Linux kernel and sends the messages
+ out to the 'syslogd' utility so they can be logged. If
+ you wish to record the messages produced by the kernel,
+ you should enable this option.
+
+config BUSYBOX_CONFIG_FEATURE_KLOGD_KLOGCTL
+ bool "Use the klogctl() interface"
+ default y
+ depends on BUSYBOX_CONFIG_KLOGD
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ The klogd applet supports two interfaces for reading
+ kernel messages. Linux provides the klogctl() interface
+ which allows reading messages from the kernel ring buffer
+ independently from the file system.
+
+ If you answer 'N' here, klogd will use the more portable
+ approach of reading them from /proc or a device node.
+ However, this method requires the file to be available.
+
+ If in doubt, say 'Y'.
+
+config BUSYBOX_CONFIG_LOGGER
+ bool "logger"
+ default y
+ select BUSYBOX_CONFIG_FEATURE_SYSLOG
+ help
+ The logger utility allows you to send arbitrary text
+ messages to the system log (i.e. the 'syslogd' utility) so
+ they can be logged. This is generally used to help locate
+ problems that occur within programs and scripts.
+
+endmenu
diff --git a/package/busybox/config/util-linux/Config.in b/package/busybox/config/util-linux/Config.in
new file mode 100644
index 000000000..14d4777be
--- /dev/null
+++ b/package/busybox/config/util-linux/Config.in
@@ -0,0 +1,985 @@
+# DO NOT EDIT. This file is generated from Config.src
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Linux System Utilities"
+
+config BUSYBOX_CONFIG_BLOCKDEV
+ bool "blockdev"
+ default n
+ help
+ Performs some ioctls with block devices.
+config BUSYBOX_CONFIG_REV
+ bool "rev"
+ default n
+ help
+ Reverse lines of a file or files.
+
+config BUSYBOX_CONFIG_ACPID
+ bool "acpid"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ acpid listens to ACPI events coming either in textual form from
+ /proc/acpi/event (though it is marked deprecated it is still widely
+ used and _is_ a standard) or in binary form from specified evdevs
+ (just use /dev/input/event*).
+
+ It parses the event to retrieve ACTION and a possible PARAMETER.
+ It then spawns /etc/acpi/<ACTION>[/<PARAMETER>] either via run-parts
+ (if the resulting path is a directory) or directly as an executable.
+
+ N.B. acpid relies on run-parts so have the latter installed.
+
+config BUSYBOX_CONFIG_FEATURE_ACPID_COMPAT
+ bool "Accept and ignore redundant options"
+ default n
+ depends on BUSYBOX_CONFIG_ACPID
+ help
+ Accept and ignore compatibility options -g -m -s -S -v.
+
+config BUSYBOX_CONFIG_BLKID
+ bool "blkid"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ select BUSYBOX_CONFIG_VOLUMEID
+ help
+ Lists labels and UUIDs of all filesystems.
+ WARNING:
+ With all submodules selected, it will add ~8k to busybox.
+
+config BUSYBOX_CONFIG_FEATURE_BLKID_TYPE
+ bool "Print filesystem type"
+ default n
+ depends on BUSYBOX_CONFIG_BLKID
+ help
+ Show TYPE="filesystem type"
+
+config BUSYBOX_CONFIG_DMESG
+ bool "dmesg"
+ default y
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ dmesg is used to examine or control the kernel ring buffer. When the
+ Linux kernel prints messages to the system log, they are stored in
+ the kernel ring buffer. You can use dmesg to print the kernel's ring
+ buffer, clear the kernel ring buffer, change the size of the kernel
+ ring buffer, and change the priority level at which kernel messages
+ are also logged to the system console. Enable this option if you
+ wish to enable the 'dmesg' utility.
+
+config BUSYBOX_CONFIG_FEATURE_DMESG_PRETTY
+ bool "Pretty dmesg output"
+ default y
+ depends on BUSYBOX_CONFIG_DMESG
+ help
+ If you wish to scrub the syslog level from the output, say 'Y' here.
+ The syslog level is a string prefixed to every line with the form
+ "<#>".
+
+ With this option you will see:
+ # dmesg
+ Linux version 2.6.17.4 .....
+ BIOS-provided physical RAM map:
+ BIOS-e820: 0000000000000000 - 000000000009f000 (usable)
+
+ Without this option you will see:
+ # dmesg
+ <5>Linux version 2.6.17.4 .....
+ <6>BIOS-provided physical RAM map:
+ <6> BIOS-e820: 0000000000000000 - 000000000009f000 (usable)
+
+config BUSYBOX_CONFIG_FBSET
+ bool "fbset"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ fbset is used to show or change the settings of a Linux frame buffer
+ device. The frame buffer device provides a simple and unique
+ interface to access a graphics display. Enable this option
+ if you wish to enable the 'fbset' utility.
+
+config BUSYBOX_CONFIG_FEATURE_FBSET_FANCY
+ bool "Turn on extra fbset options"
+ default n
+ depends on BUSYBOX_CONFIG_FBSET
+ help
+ This option enables extended fbset options, allowing one to set the
+ framebuffer size, color depth, etc. interface to access a graphics
+ display. Enable this option if you wish to enable extended fbset
+ options.
+
+config BUSYBOX_CONFIG_FEATURE_FBSET_READMODE
+ bool "Turn on fbset readmode support"
+ default n
+ depends on BUSYBOX_CONFIG_FBSET
+ help
+ This option allows fbset to read the video mode database stored by
+ default n /etc/fb.modes, which can be used to set frame buffer
+ device to pre-defined video modes.
+
+config BUSYBOX_CONFIG_FDFLUSH
+ bool "fdflush"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ fdflush is only needed when changing media on slightly-broken
+ removable media drives. It is used to make Linux believe that a
+ hardware disk-change switch has been actuated, which causes Linux to
+ forget anything it has cached from the previous media. If you have
+ such a slightly-broken drive, you will need to run fdflush every time
+ you change a disk. Most people have working hardware and can safely
+ leave this disabled.
+
+config BUSYBOX_CONFIG_FDFORMAT
+ bool "fdformat"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ fdformat is used to low-level format a floppy disk.
+
+config BUSYBOX_CONFIG_FDISK
+ bool "fdisk"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ The fdisk utility is used to divide hard disks into one or more
+ logical disks, which are generally called partitions. This utility
+ can be used to list and edit the set of partitions or BSD style
+ 'disk slices' that are defined on a hard drive.
+
+config BUSYBOX_CONFIG_FDISK_SUPPORT_LARGE_DISKS
+ bool "Support over 4GB disks"
+ default y
+ depends on BUSYBOX_CONFIG_FDISK
+ depends on !BUSYBOX_CONFIG_LFS # with LFS no special code is needed
+ help
+ Enable this option to support large disks > 4GB.
+
+config BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE
+ bool "Write support"
+ default n
+ depends on BUSYBOX_CONFIG_FDISK
+ help
+ Enabling this option allows you to create or change a partition table
+ and write those changes out to disk. If you leave this option
+ disabled, you will only be able to view the partition table.
+
+config BUSYBOX_CONFIG_FEATURE_AIX_LABEL
+ bool "Support AIX disklabels"
+ default n
+ depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE
+ help
+ Enabling this option allows you to create or change AIX disklabels.
+ Most people can safely leave this option disabled.
+
+config BUSYBOX_CONFIG_FEATURE_SGI_LABEL
+ bool "Support SGI disklabels"
+ default n
+ depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE
+ help
+ Enabling this option allows you to create or change SGI disklabels.
+ Most people can safely leave this option disabled.
+
+config BUSYBOX_CONFIG_FEATURE_SUN_LABEL
+ bool "Support SUN disklabels"
+ default n
+ depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE
+ help
+ Enabling this option allows you to create or change SUN disklabels.
+ Most people can safely leave this option disabled.
+
+config BUSYBOX_CONFIG_FEATURE_OSF_LABEL
+ bool "Support BSD disklabels"
+ default n
+ depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE
+ help
+ Enabling this option allows you to create or change BSD disklabels
+ and define and edit BSD disk slices.
+
+config BUSYBOX_CONFIG_FEATURE_GPT_LABEL
+ bool "Support GPT disklabels"
+ default n
+ depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE
+ help
+ Enabling this option allows you to view GUID Partition Table
+ disklabels.
+
+config BUSYBOX_CONFIG_FEATURE_FDISK_ADVANCED
+ bool "Support expert mode"
+ default n
+ depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE
+ help
+ Enabling this option allows you to do terribly unsafe things like
+ define arbitrary drive geometry, move the beginning of data in a
+ partition, and similarly evil things. Unless you have a very good
+ reason you would be wise to leave this disabled.
+
+config BUSYBOX_CONFIG_FINDFS
+ bool "findfs"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ select BUSYBOX_CONFIG_VOLUMEID
+ help
+ Prints the name of a filesystem with given label or UUID.
+ WARNING:
+ With all submodules selected, it will add ~8k to busybox.
+
+config BUSYBOX_CONFIG_FLOCK
+ bool "flock"
+ default n
+ help
+ Manage locks from shell scripts
+
+config BUSYBOX_CONFIG_FREERAMDISK
+ bool "freeramdisk"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Linux allows you to create ramdisks. This utility allows you to
+ delete them and completely free all memory that was used for the
+ ramdisk. For example, if you boot Linux into a ramdisk and later
+ pivot_root, you may want to free the memory that is allocated to the
+ ramdisk. If you have no use for freeing memory from a ramdisk, leave
+ this disabled.
+
+config BUSYBOX_CONFIG_FSCK_MINIX
+ bool "fsck_minix"
+ default n
+ help
+ The minix filesystem is a nice, small, compact, read-write filesystem
+ with little overhead. It is not a journaling filesystem however and
+ can experience corruption if it is not properly unmounted or if the
+ power goes off in the middle of a write. This utility allows you to
+ check for and attempt to repair any corruption that occurs to a minix
+ filesystem.
+
+config BUSYBOX_CONFIG_MKFS_EXT2
+ bool "mkfs_ext2"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Utility to create EXT2 filesystems.
+
+config BUSYBOX_CONFIG_MKFS_MINIX
+ bool "mkfs_minix"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ The minix filesystem is a nice, small, compact, read-write filesystem
+ with little overhead. If you wish to be able to create minix
+ filesystems this utility will do the job for you.
+
+config BUSYBOX_CONFIG_FEATURE_MINIX2
+ bool "Support Minix fs v2 (fsck_minix/mkfs_minix)"
+ default n
+ depends on BUSYBOX_CONFIG_FSCK_MINIX || BUSYBOX_CONFIG_MKFS_MINIX
+ help
+ If you wish to be able to create version 2 minix filesystems, enable
+ this. If you enabled 'mkfs_minix' then you almost certainly want to
+ be using the version 2 filesystem support.
+
+config BUSYBOX_CONFIG_MKFS_REISER
+ bool "mkfs_reiser"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Utility to create ReiserFS filesystems.
+ Note: this applet needs a lot of testing and polishing.
+
+config BUSYBOX_CONFIG_MKFS_VFAT
+ bool "mkfs_vfat"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Utility to create FAT32 filesystems.
+
+config BUSYBOX_CONFIG_GETOPT
+ bool "getopt"
+ default n
+ help
+ The getopt utility is used to break up (parse) options in command
+ lines to make it easy to write complex shell scripts that also check
+ for legal (and illegal) options. If you want to write horribly
+ complex shell scripts, or use some horribly complex shell script
+ written by others, this utility may be for you. Most people will
+ wisely leave this disabled.
+
+config BUSYBOX_CONFIG_FEATURE_GETOPT_LONG
+ bool "Support option -l"
+ default n if BUSYBOX_CONFIG_LONG_OPTS
+ depends on BUSYBOX_CONFIG_GETOPT
+ help
+ Enable support for long options (option -l).
+
+config BUSYBOX_CONFIG_HEXDUMP
+ bool "hexdump"
+ default y
+ help
+ The hexdump utility is used to display binary data in a readable
+ way that is comparable to the output from most hex editors.
+
+config BUSYBOX_CONFIG_FEATURE_HEXDUMP_REVERSE
+ bool "Support -R, reverse of 'hexdump -Cv'"
+ default n
+ depends on BUSYBOX_CONFIG_HEXDUMP
+ help
+ The hexdump utility is used to display binary data in an ascii
+ readable way. This option creates binary data from an ascii input.
+ NB: this option is non-standard. It's unwise to use it in scripts
+ aimed to be portable.
+
+config BUSYBOX_CONFIG_HD
+ bool "hd"
+ default n
+ depends on BUSYBOX_CONFIG_HEXDUMP
+ help
+ hd is an alias to hexdump -C.
+
+config BUSYBOX_CONFIG_HWCLOCK
+ bool "hwclock"
+ default y
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ The hwclock utility is used to read and set the hardware clock
+ on a system. This is primarily used to set the current time on
+ shutdown in the hardware clock, so the hardware will keep the
+ correct time when Linux is _not_ running.
+
+config BUSYBOX_CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS
+ bool "Support long options (--hctosys,...)"
+ default n
+ depends on BUSYBOX_CONFIG_HWCLOCK && BUSYBOX_CONFIG_LONG_OPTS
+ help
+ By default, the hwclock utility only uses short options. If you
+ are overly fond of its long options, such as --hctosys, --utc, etc)
+ then enable this option.
+
+config BUSYBOX_CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS
+ bool "Use FHS /var/lib/hwclock/adjtime"
+ default n # util-linux-ng in Fedora 13 still uses /etc/adjtime
+ depends on BUSYBOX_CONFIG_HWCLOCK
+ help
+ Starting with FHS 2.3, the adjtime state file is supposed to exist
+ at /var/lib/hwclock/adjtime instead of /etc/adjtime. If you wish
+ to use the FHS behavior, answer Y here, otherwise answer N for the
+ classic /etc/adjtime path.
+
+ pathname.com/fhs/pub/fhs-2.3.html#VARLIBHWCLOCKSTATEDIRECTORYFORHWCLO
+
+config BUSYBOX_CONFIG_IPCRM
+ bool "ipcrm"
+ default n
+ help
+ The ipcrm utility allows the removal of System V interprocess
+ communication (IPC) objects and the associated data structures
+ from the system.
+
+config BUSYBOX_CONFIG_IPCS
+ bool "ipcs"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ The ipcs utility is used to provide information on the currently
+ allocated System V interprocess (IPC) objects in the system.
+
+config BUSYBOX_CONFIG_LOSETUP
+ bool "losetup"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ losetup is used to associate or detach a loop device with a regular
+ file or block device, and to query the status of a loop device. This
+ version does not currently support enabling data encryption.
+
+config BUSYBOX_CONFIG_LSPCI
+ bool "lspci"
+ default n
+ #select PLATFORM_LINUX
+ help
+ lspci is a utility for displaying information about PCI buses in the
+ system and devices connected to them.
+
+ This version uses sysfs (/sys/bus/pci/devices) only.
+
+config BUSYBOX_CONFIG_LSUSB
+ bool "lsusb"
+ default n
+ #select PLATFORM_LINUX
+ help
+ lsusb is a utility for displaying information about USB buses in the
+ system and devices connected to them.
+
+ This version uses sysfs (/sys/bus/usb/devices) only.
+
+config BUSYBOX_CONFIG_MDEV
+ bool "mdev"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ mdev is a mini-udev implementation for dynamically creating device
+ nodes in the /dev directory.
+
+ For more information, please see docs/mdev.txt
+
+config BUSYBOX_CONFIG_FEATURE_MDEV_CONF
+ bool "Support /etc/mdev.conf"
+ default n
+ depends on BUSYBOX_CONFIG_MDEV
+ help
+ Add support for the mdev config file to control ownership and
+ permissions of the device nodes.
+
+ For more information, please see docs/mdev.txt
+
+config BUSYBOX_CONFIG_FEATURE_MDEV_RENAME
+ bool "Support subdirs/symlinks"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_MDEV_CONF
+ help
+ Add support for renaming devices and creating symlinks.
+
+ For more information, please see docs/mdev.txt
+
+config BUSYBOX_CONFIG_FEATURE_MDEV_RENAME_REGEXP
+ bool "Support regular expressions substitutions when renaming device"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_MDEV_RENAME
+ help
+ Add support for regular expressions substitutions when renaming
+ device.
+
+config BUSYBOX_CONFIG_FEATURE_MDEV_EXEC
+ bool "Support command execution at device addition/removal"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_MDEV_CONF
+ help
+ This adds support for an optional field to /etc/mdev.conf for
+ executing commands when devices are created/removed.
+
+ For more information, please see docs/mdev.txt
+
+config BUSYBOX_CONFIG_FEATURE_MDEV_LOAD_FIRMWARE
+ bool "Support loading of firmwares"
+ default n
+ depends on BUSYBOX_CONFIG_MDEV
+ help
+ Some devices need to load firmware before they can be usable.
+
+ These devices will request userspace look up the files in
+ /lib/firmware/ and if it exists, send it to the kernel for
+ loading into the hardware.
+
+config BUSYBOX_CONFIG_MKSWAP
+ bool "mkswap"
+ default n
+ help
+ The mkswap utility is used to configure a file or disk partition as
+ Linux swap space. This allows Linux to use the entire file or
+ partition as if it were additional RAM, which can greatly increase
+ the capability of low-memory machines. This additional memory is
+ much slower than real RAM, but can be very helpful at preventing your
+ applications being killed by the Linux out of memory (OOM) killer.
+ Once you have created swap space using 'mkswap' you need to enable
+ the swap space using the 'swapon' utility.
+
+config BUSYBOX_CONFIG_FEATURE_MKSWAP_UUID
+ bool "UUID support"
+ default n
+ depends on BUSYBOX_CONFIG_MKSWAP
+ help
+ Generate swap spaces with universally unique identifiers.
+
+config BUSYBOX_CONFIG_MORE
+ bool "more"
+ default n
+ help
+ more is a simple utility which allows you to read text one screen
+ sized page at a time. If you want to read text that is larger than
+ the screen, and you are using anything faster than a 300 baud modem,
+ you will probably find this utility very helpful. If you don't have
+ any need to reading text files, you can leave this disabled.
+
+config BUSYBOX_CONFIG_MOUNT
+ bool "mount"
+ default y
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ All files and filesystems in Unix are arranged into one big directory
+ tree. The 'mount' utility is used to graft a filesystem onto a
+ particular part of the tree. A filesystem can either live on a block
+ device, or it can be accessible over the network, as is the case with
+ NFS filesystems. Most people using BusyBox will also want to enable
+ the 'mount' utility.
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_FAKE
+ bool "Support option -f"
+ default n
+ depends on BUSYBOX_CONFIG_MOUNT
+ help
+ Enable support for faking a file system mount.
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_VERBOSE
+ bool "Support option -v"
+ default n
+ depends on BUSYBOX_CONFIG_MOUNT
+ help
+ Enable multi-level -v[vv...] verbose messages. Useful if you
+ debug mount problems and want to see what is exactly passed
+ to the kernel.
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_HELPERS
+ bool "Support mount helpers"
+ default y
+ depends on BUSYBOX_CONFIG_MOUNT
+ help
+ Enable mounting of virtual file systems via external helpers.
+ E.g. "mount obexfs#-b00.11.22.33.44.55 /mnt" will in effect call
+ "obexfs -b00.11.22.33.44.55 /mnt"
+ Also "mount -t sometype [-o opts] fs /mnt" will try
+ "sometype [-o opts] fs /mnt" if simple mount syscall fails.
+ The idea is to use such virtual filesystems in /etc/fstab.
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_LABEL
+ bool "Support specifying devices by label or UUID"
+ default n
+ depends on BUSYBOX_CONFIG_MOUNT
+ select BUSYBOX_CONFIG_VOLUMEID
+ help
+ This allows for specifying a device by label or uuid, rather than by
+ name. This feature utilizes the same functionality as blkid/findfs.
+ This also enables label or uuid support for swapon.
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_NFS
+ bool "Support mounting NFS file systems"
+ default n
+ depends on BUSYBOX_CONFIG_MOUNT
+ select BUSYBOX_CONFIG_FEATURE_HAVE_RPC
+ select BUSYBOX_CONFIG_FEATURE_SYSLOG
+ help
+ Enable mounting of NFS file systems.
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_CIFS
+ bool "Support mounting CIFS/SMB file systems"
+ default y
+ depends on BUSYBOX_CONFIG_MOUNT
+ help
+ Enable support for samba mounts.
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_FLAGS
+ depends on BUSYBOX_CONFIG_MOUNT
+ bool "Support lots of -o flags in mount"
+ default y
+ help
+ Without this, mount only supports ro/rw/remount. With this, it
+ supports nosuid, suid, dev, nodev, exec, noexec, sync, async, atime,
+ noatime, diratime, nodiratime, loud, bind, move, shared, slave,
+ private, unbindable, rshared, rslave, rprivate, and runbindable.
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_FSTAB
+ depends on BUSYBOX_CONFIG_MOUNT
+ bool "Support /etc/fstab and -a"
+ default y
+ help
+ Support mount all and looking for files in /etc/fstab.
+
+config BUSYBOX_CONFIG_PIVOT_ROOT
+ bool "pivot_root"
+ default y
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ The pivot_root utility swaps the mount points for the root filesystem
+ with some other mounted filesystem. This allows you to do all sorts
+ of wild and crazy things with your Linux system and is far more
+ powerful than 'chroot'.
+
+ Note: This is for initrd in linux 2.4. Under initramfs (introduced
+ in linux 2.6) use switch_root instead.
+
+config BUSYBOX_CONFIG_RDATE
+ bool "rdate"
+ default n
+ help
+ The rdate utility allows you to synchronize the date and time of your
+ system clock with the date and time of a remote networked system using
+ the RFC868 protocol, which is built into the inetd daemon on most
+ systems.
+
+config BUSYBOX_CONFIG_RDEV
+ bool "rdev"
+ default n
+ help
+ Print the device node associated with the filesystem mounted at '/'.
+
+config BUSYBOX_CONFIG_READPROFILE
+ bool "readprofile"
+ default n
+ #select PLATFORM_LINUX
+ help
+ This allows you to parse /proc/profile for basic profiling.
+
+config BUSYBOX_CONFIG_RTCWAKE
+ bool "rtcwake"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ Enter a system sleep state until specified wakeup time.
+
+config BUSYBOX_CONFIG_SCRIPT
+ bool "script"
+ default n
+ help
+ The script makes typescript of terminal session.
+
+config BUSYBOX_CONFIG_SCRIPTREPLAY
+ bool "scriptreplay"
+ default n
+ help
+ This program replays a typescript, using timing information
+ given by script -t.
+
+config BUSYBOX_CONFIG_SETARCH
+ bool "setarch"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ The linux32 utility is used to create a 32bit environment for the
+ specified program (usually a shell). It only makes sense to have
+ this util on a system that supports both 64bit and 32bit userland
+ (like amd64/x86, ppc64/ppc, sparc64/sparc, etc...).
+
+config BUSYBOX_CONFIG_SWAPONOFF
+ bool "swaponoff"
+ default n
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ This option enables both the 'swapon' and the 'swapoff' utilities.
+ Once you have created some swap space using 'mkswap', you also need
+ to enable your swap space with the 'swapon' utility. The 'swapoff'
+ utility is used, typically at system shutdown, to disable any swap
+ space. If you are not using any swap space, you can leave this
+ option disabled.
+
+config BUSYBOX_CONFIG_FEATURE_SWAPON_PRI
+ bool "Support priority option -p"
+ default n
+ depends on BUSYBOX_CONFIG_SWAPONOFF
+ help
+ Enable support for setting swap device priority in swapon.
+
+config BUSYBOX_CONFIG_SWITCH_ROOT
+ bool "switch_root"
+ default y
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ The switch_root utility is used from initramfs to select a new
+ root device. Under initramfs, you have to use this instead of
+ pivot_root. (Stop reading here if you don't care why.)
+
+ Booting with initramfs extracts a gzipped cpio archive into rootfs
+ (which is a variant of ramfs/tmpfs). Because rootfs can't be moved
+ or unmounted*, pivot_root will not work from initramfs. Instead,
+ switch_root deletes everything out of rootfs (including itself),
+ does a mount --move that overmounts rootfs with the new root, and
+ then execs the specified init program.
+
+ * Because the Linux kernel uses rootfs internally as the starting
+ and ending point for searching through the kernel's doubly linked
+ list of active mount points. That's why.
+
+config BUSYBOX_CONFIG_UMOUNT
+ bool "umount"
+ default y
+ select BUSYBOX_CONFIG_PLATFORM_LINUX
+ help
+ When you want to remove a mounted filesystem from its current mount
+ point, for example when you are shutting down the system, the
+ 'umount' utility is the tool to use. If you enabled the 'mount'
+ utility, you almost certainly also want to enable 'umount'.
+
+config BUSYBOX_CONFIG_FEATURE_UMOUNT_ALL
+ bool "Support option -a"
+ default y
+ depends on BUSYBOX_CONFIG_UMOUNT
+ help
+ Support -a option to unmount all currently mounted filesystems.
+
+comment "Common options for mount/umount"
+ depends on BUSYBOX_CONFIG_MOUNT || BUSYBOX_CONFIG_UMOUNT
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_LOOP
+ bool "Support loopback mounts"
+ default y
+ depends on BUSYBOX_CONFIG_MOUNT || BUSYBOX_CONFIG_UMOUNT
+ help
+ Enabling this feature allows automatic mounting of files (containing
+ filesystem images) via the linux kernel's loopback devices.
+ The mount command will detect you are trying to mount a file instead
+ of a block device, and transparently associate the file with a
+ loopback device. The umount command will also free that loopback
+ device.
+
+ You can still use the 'losetup' utility (to manually associate files
+ with loop devices) if you need to do something advanced, such as
+ specify an offset or cryptographic options to the loopback device.
+ (If you don't want umount to free the loop device, use "umount -D".)
+
+config BUSYBOX_CONFIG_FEATURE_MOUNT_LOOP_CREATE
+ bool "Create new loopback devices if needed"
+ default n
+ depends on BUSYBOX_CONFIG_FEATURE_MOUNT_LOOP
+ help
+ Linux kernels >= 2.6.24 support unlimited loopback devices. They are
+ allocated for use when trying to use a loop device. The loop device
+ must however exist.
+
+ This feature lets mount to try to create next /dev/loopN device
+ if it does not find a free one.
+
+config BUSYBOX_CONFIG_FEATURE_MTAB_SUPPORT
+ bool "Support for the old /etc/mtab file"
+ default n
+ depends on BUSYBOX_CONFIG_MOUNT || BUSYBOX_CONFIG_UMOUNT
+ select BUSYBOX_CONFIG_FEATURE_MOUNT_FAKE
+ help
+ Historically, Unix systems kept track of the currently mounted
+ partitions in the file "/etc/mtab". These days, the kernel exports
+ the list of currently mounted partitions in "/proc/mounts", rendering
+ the old mtab file obsolete. (In modern systems, /etc/mtab should be
+ a symlink to /proc/mounts.)
+
+ The only reason to have mount maintain an /etc/mtab file itself is if
+ your stripped-down embedded system does not have a /proc directory.
+ If you must use this, keep in mind it's inherently brittle (for
+ example a mount under chroot won't update it), can't handle modern
+ features like separate per-process filesystem namespaces, requires
+ that your /etc directory be writable, tends to get easily confused
+ by --bind or --move mounts, won't update if you rename a directory
+ that contains a mount point, and so on. (In brief: avoid.)
+
+ About the only reason to use this is if you've removed /proc from
+ your kernel.
+
+config BUSYBOX_CONFIG_VOLUMEID
+ bool #No description makes it a hidden option
+ default n
+
+menu "Filesystem/Volume identification"
+ depends on BUSYBOX_CONFIG_VOLUMEID
+
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_EXT
+ bool "Ext filesystem"
+ default n
+ depends on BUSYBOX_CONFIG_VOLUMEID
+ help
+ TODO
+
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_BTRFS
+ bool "btrfs filesystem"
+ default n
+ depends on BUSYBOX_CONFIG_VOLUMEID
+ help
+ TODO
+
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_REISERFS
+ bool "Reiser filesystem"
+ default n
+ depends on BUSYBOX_CONFIG_VOLUMEID
+ help
+ TODO
+
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_FAT
+ bool "fat filesystem"
+ default n
+ depends on BUSYBOX_CONFIG_VOLUMEID
+ help
+ TODO
+
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_HFS
+ bool "hfs filesystem"
+ default n
+ depends on BUSYBOX_CONFIG_VOLUMEID
+ help
+ TODO
+
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_JFS
+ bool "jfs filesystem"
+ default n
+ depends on BUSYBOX_CONFIG_VOLUMEID
+ help
+ TODO
+
+### config FEATURE_VOLUMEID_UFS
+### bool "ufs filesystem"
+### default y
+### depends on VOLUMEID
+### help
+### TODO
+
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_XFS
+ bool "xfs filesystem"
+ default n
+ depends on BUSYBOX_CONFIG_VOLUMEID
+ help
+ TODO
+
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_NTFS
+ bool "ntfs filesystem"
+ default n
+ depends on BUSYBOX_CONFIG_VOLUMEID
+ help
+ TODO
+
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_ISO9660
+ bool "iso9660 filesystem"
+ default n
+ depends on BUSYBOX_CONFIG_VOLUMEID
+ help
+ TODO
+
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_UDF
+ bool "udf filesystem"
+ default n
+ depends on BUSYBOX_CONFIG_VOLUMEID
+ help
+ TODO
+
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_LUKS
+ bool "luks filesystem"
+ default n
+ depends on BUSYBOX_CONFIG_VOLUMEID
+ help
+ TODO
+
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_LINUXSWAP
+ bool "linux swap filesystem"
+ default n
+ depends on BUSYBOX_CONFIG_VOLUMEID
+ help
+ TODO
+
+### config FEATURE_VOLUMEID_LVM
+### bool "lvm"
+### default y
+### depends on VOLUMEID
+### help
+### TODO
+
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_CRAMFS
+ bool "cramfs filesystem"
+ default n
+ depends on BUSYBOX_CONFIG_VOLUMEID
+ help
+ TODO
+
+### config FEATURE_VOLUMEID_HPFS
+### bool "hpfs filesystem"
+### default y
+### depends on VOLUMEID
+### help
+### TODO
+
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_ROMFS
+ bool "romfs filesystem"
+ default n
+ depends on BUSYBOX_CONFIG_VOLUMEID
+ help
+ TODO
+
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_SYSV
+ bool "sysv filesystem"
+ default n
+ depends on BUSYBOX_CONFIG_VOLUMEID
+ help
+ TODO
+
+### config FEATURE_VOLUMEID_MINIX
+### bool "minix filesystem"
+### default y
+### depends on VOLUMEID
+### help
+### TODO
+
+### These only detect partition tables - not used (yet?)
+### config FEATURE_VOLUMEID_MAC
+### bool "mac filesystem"
+### default y
+### depends on VOLUMEID
+### help
+### TODO
+###
+### config FEATURE_VOLUMEID_MSDOS
+### bool "msdos filesystem"
+### default y
+### depends on VOLUMEID
+### help
+### TODO
+
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_OCFS2
+ bool "ocfs2 filesystem"
+ default n
+ depends on BUSYBOX_CONFIG_VOLUMEID
+ help
+ TODO
+
+### config FEATURE_VOLUMEID_HIGHPOINTRAID
+### bool "highpoint raid"
+### default y
+### depends on VOLUMEID
+### help
+### TODO
+
+### config FEATURE_VOLUMEID_ISWRAID
+### bool "intel raid"
+### default y
+### depends on VOLUMEID
+### help
+### TODO
+
+### config FEATURE_VOLUMEID_LSIRAID
+### bool "lsi raid"
+### default y
+### depends on VOLUMEID
+### help
+### TODO
+
+### config FEATURE_VOLUMEID_VIARAID
+### bool "via raid"
+### default y
+### depends on VOLUMEID
+### help
+### TODO
+
+### config FEATURE_VOLUMEID_SILICONRAID
+### bool "silicon raid"
+### default y
+### depends on VOLUMEID
+### help
+### TODO
+
+### config FEATURE_VOLUMEID_NVIDIARAID
+### bool "nvidia raid"
+### default y
+### depends on VOLUMEID
+### help
+### TODO
+
+### config FEATURE_VOLUMEID_PROMISERAID
+### bool "promise raid"
+### default y
+### depends on VOLUMEID
+### help
+### TODO
+
+config BUSYBOX_CONFIG_FEATURE_VOLUMEID_LINUXRAID
+ bool "linuxraid"
+ default n
+ depends on BUSYBOX_CONFIG_VOLUMEID
+ help
+ TODO
+
+endmenu
+
+endmenu
diff --git a/package/busybox/convert_menuconfig.pl b/package/busybox/convert_menuconfig.pl
new file mode 100755
index 000000000..0128bf78d
--- /dev/null
+++ b/package/busybox/convert_menuconfig.pl
@@ -0,0 +1,78 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+use strict;
+my $PATH = $ARGV[0];
+($PATH and -d $PATH) or die 'invalid path';
+my $DEFCONFIG = $ARGV[1];
+($DEFCONFIG and -f $DEFCONFIG) or die 'invalid config file';
+
+my %config;
+
+open CONFIG, $DEFCONFIG or die 'cannot open config file';
+while (<CONFIG>) {
+ /^CONFIG_([\w_]+)=([ym])/ and $config{$1} = $2;
+ /^CONFIG_([\w_]+)=(\d+)/ and $config{$1} = $2;
+ /^CONFIG_([\w_]+)=(".+")/ and $config{$1} = $2;
+}
+close CONFIG;
+
+open FIND, "find \"$PATH\" -name Config.in |";
+while (<FIND>) {
+ chomp;
+ my $input = $_;
+ s/^$PATH\///g;
+ s/sysdeps\/linux\///g;
+ my $output = $_;
+ print STDERR "$input => $output\n";
+ $output =~ /^(.+)\/[^\/]+$/ and system("mkdir -p $1");
+
+ open INPUT, $input;
+ open OUTPUT, ">$output";
+ my ($cur, $default_set, $line);
+ while ($line = <INPUT>) {
+ next if $line =~ /^\s*mainmenu/;
+
+ # FIXME: make this dynamic
+ $line =~ s/default FEATURE_BUFFERS_USE_MALLOC/default FEATURE_BUFFERS_GO_ON_STACK/;
+ $line =~ s/default FEATURE_SH_IS_NONE/default FEATURE_SH_IS_ASH/;
+
+ if ($line =~ /^\s*config\s*([\w_]+)/) {
+ $cur = $1;
+ undef $default_set;
+ }
+ if ($line =~ /^\s*(menu|choice|end|source)/) {
+ undef $cur;
+ undef $default_set;
+ }
+ $line =~ s/^(\s*source\s+)/$1package\/busybox\/config\//;
+
+ $line =~ s/^(\s*(prompt "[^"]+" if|config|depends|depends on|select|default|default \w if)\s+\!?)([A-Z_])/$1BUSYBOX_CONFIG_$3/g;
+ $line =~ s/(( \|\| | \&\& | \( )!?)([A-Z_])/$1BUSYBOX_CONFIG_$3/g;
+ $line =~ s/(\( ?!?)([A-Z_]+ (\|\||&&))/$1BUSYBOX_CONFIG_$2/g;
+
+ if ($cur) {
+ ($cur eq 'LFS') and do {
+ $line =~ s/^(\s*(bool|tristate|string))\s*".+"$/$1/;
+ };
+ if ($line =~ /^\s*default/) {
+ my $c;
+ $default_set = 1;
+ $c = $config{$cur} or $c = 'n';
+
+ $line =~ s/^(\s*default\s*)(\w+|"[^"]*")(.*)/$1$c$3/;
+ }
+ }
+
+ print OUTPUT $line;
+ }
+ close OUTPUT;
+ close INPUT;
+
+}
+close FIND;
diff --git a/package/busybox/files/cron b/package/busybox/files/cron
new file mode 100755
index 000000000..465b1ab45
--- /dev/null
+++ b/package/busybox/files/cron
@@ -0,0 +1,18 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006-2011 OpenWrt.org
+
+START=50
+
+SERVICE_USE_PID=1
+
+start () {
+ loglevel=$(uci_get "system.@system[0].cronloglevel")
+ [ -z "$(ls /etc/crontabs/)" ] && exit 1
+ mkdir -p /var/spool/cron
+ ln -s /etc/crontabs /var/spool/cron/ 2>/dev/null
+ service_start /usr/sbin/crond -c /etc/crontabs -l ${loglevel:-5}
+}
+
+stop() {
+ service_stop /usr/sbin/crond
+}
diff --git a/package/busybox/files/telnet b/package/busybox/files/telnet
new file mode 100755
index 000000000..994e713e7
--- /dev/null
+++ b/package/busybox/files/telnet
@@ -0,0 +1,37 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006-2011 OpenWrt.org
+
+START=50
+
+has_root_pwd() {
+ local pwd=$([ -f "$1" ] && cat "$1")
+ pwd="${pwd#*root:}"
+ pwd="${pwd%%:*}"
+
+ test -n "${pwd#[\!x]}"
+}
+
+get_root_home() {
+ local homedir=$([ -f "$1" ] && cat "$1")
+ homedir="${homedir#*:*:0:0:*:}"
+
+ echo "${homedir%%:*}"
+}
+
+has_ssh_pubkey() {
+ ( /etc/init.d/dropbear enabled 2> /dev/null && grep -qs "^ssh-" /etc/dropbear/authorized_keys ) || \
+ ( /etc/init.d/sshd enabled 2> /dev/null && grep -qs "^ssh-" "$(get_root_home /etc/passwd)"/.ssh/authorized_keys )
+}
+
+start() {
+ if ( ! has_ssh_pubkey && \
+ ! has_root_pwd /etc/passwd && ! has_root_pwd /etc/shadow ) || \
+ ( ! /etc/init.d/dropbear enabled 2> /dev/null && ! /etc/init.d/sshd enabled 2> /dev/null );
+ then
+ service_start /usr/sbin/telnetd -l /bin/login.sh
+ fi
+}
+
+stop() {
+ service_stop /usr/sbin/telnetd
+}
diff --git a/package/busybox/patches/001-init_avoid_loop_opening_tty.patch b/package/busybox/patches/001-init_avoid_loop_opening_tty.patch
new file mode 100644
index 000000000..4db64c34b
--- /dev/null
+++ b/package/busybox/patches/001-init_avoid_loop_opening_tty.patch
@@ -0,0 +1,15 @@
+--- a/init/init.c
++++ b/init/init.c
+@@ -573,8 +573,11 @@ static void run_actions(int action_type)
+ /* Only run stuff with pid == 0. If pid != 0,
+ * it is already running
+ */
+- if (a->pid == 0)
++ if (a->pid == 0) {
++ if (a->terminal[0] && access(a->terminal, R_OK | W_OK))
++ continue;
+ a->pid = run(a);
++ }
+ }
+ }
+ }
diff --git a/package/busybox/patches/002-passwd_use_md5_hash_by_default_like_it_used_to_be.patch b/package/busybox/patches/002-passwd_use_md5_hash_by_default_like_it_used_to_be.patch
new file mode 100644
index 000000000..ff79f3ee9
--- /dev/null
+++ b/package/busybox/patches/002-passwd_use_md5_hash_by_default_like_it_used_to_be.patch
@@ -0,0 +1,20 @@
+From eb80c2a5315ed08bd329448217695375d89732c9 Mon Sep 17 00:00:00 2001
+From: Nicolas Thill <nico@openwrt.org>
+Date: Wed, 9 Nov 2011 18:17:20 +0100
+Subject: [PATCH] passwd: use MD5 hash by default (like it used to be)
+
+---
+ loginutils/passwd.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+--- a/loginutils/passwd.c
++++ b/loginutils/passwd.c
+@@ -94,7 +94,7 @@ int passwd_main(int argc UNUSED_PARAM, c
+ };
+ unsigned opt;
+ int rc;
+- const char *opt_a = "d"; /* des */
++ const char *opt_a = "m"; /* md5 */
+ const char *filename;
+ char *myname;
+ char *name;
diff --git a/package/busybox/patches/003-brctl_show_fix.patch b/package/busybox/patches/003-brctl_show_fix.patch
new file mode 100644
index 000000000..8177fb01c
--- /dev/null
+++ b/package/busybox/patches/003-brctl_show_fix.patch
@@ -0,0 +1,37 @@
+--- a/networking/brctl.c
++++ b/networking/brctl.c
+@@ -129,7 +129,7 @@ int brctl_main(int argc UNUSED_PARAM, ch
+ "setageing\0" "setfd\0" "sethello\0" "setmaxage\0"
+ "setpathcost\0" "setportprio\0" "setbridgeprio\0"
+ )
+- IF_FEATURE_BRCTL_SHOW("showmacs\0" "show\0");
++ IF_FEATURE_BRCTL_SHOW("show\0");
+
+ enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif
+ IF_FEATURE_BRCTL_FANCY(,
+@@ -137,7 +137,7 @@ int brctl_main(int argc UNUSED_PARAM, ch
+ ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage,
+ ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio
+ )
+- IF_FEATURE_BRCTL_SHOW(, ARG_showmacs, ARG_show)
++ IF_FEATURE_BRCTL_SHOW(, ARG_show)
+ };
+
+ int fd;
+--- a/networking/Config.src
++++ b/networking/Config.src
+@@ -82,12 +82,12 @@ config FEATURE_BRCTL_FANCY
+ This adds about 600 bytes.
+
+ config FEATURE_BRCTL_SHOW
+- bool "Support show, showmac and showstp"
++ bool "Support show"
+ default y
+ depends on BRCTL && FEATURE_BRCTL_FANCY
+ help
+ Add support for option which prints the current config:
+- showmacs, showstp, show
++ show
+
+ config DNSD
+ bool "dnsd"
diff --git a/package/busybox/patches/004-upstream-percent_decode_in_place.patch b/package/busybox/patches/004-upstream-percent_decode_in_place.patch
new file mode 100644
index 000000000..d94ee4790
--- /dev/null
+++ b/package/busybox/patches/004-upstream-percent_decode_in_place.patch
@@ -0,0 +1,237 @@
+http://git.busybox.net/busybox/commit/?id=dd1061b6a79b0161597799e825bfefc27993ace5
+
+From dd1061b6a79b0161597799e825bfefc27993ace5 Mon Sep 17 00:00:00 2001
+From: Denys Vlasenko <vda.linux@googlemail.com>
+Date: Sun, 11 Sep 2011 21:04:02 +0200
+Subject: [PATCH] wget: URL-decode user:password before base64-encoding it into auth hdr. Closes 3625.
+
+function old new delta
+percent_decode_in_place - 152 +152
+parse_url 304 317 +13
+handle_incoming_and_exit 2795 2798 +3
+httpd_main 763 760 -3
+decodeString 152 - -152
+------------------------------------------------------------------------------
+(add/remove: 2/1 grow/shrink: 2/1 up/down: 168/-155) Total: 13 bytes
+
+Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
+
+--- a/include/libbb.h
++++ b/include/libbb.h
+@@ -1570,6 +1570,15 @@ int starts_with_cpu(const char *str) FAS
+ unsigned get_cpu_count(void) FAST_FUNC;
+
+
++/* Use strict=1 if you process input from untrusted source:
++ * it will return NULL on invalid %xx (bad hex chars)
++ * and str + 1 if decoded char is / or NUL.
++ * In non-strict mode, it always succeeds (returns str),
++ * and also it additionally decoded '+' to space.
++ */
++char *percent_decode_in_place(char *str, int strict) FAST_FUNC;
++
++
+ extern const char bb_uuenc_tbl_base64[];
+ extern const char bb_uuenc_tbl_std[];
+ void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC;
+--- /dev/null
++++ b/libbb/percent_decode.c
+@@ -0,0 +1,69 @@
++/* vi: set sw=4 ts=4: */
++/*
++ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
++ */
++
++//kbuild:lib-y += percent_decode.o
++
++#include "libbb.h"
++
++static unsigned hex_to_bin(unsigned char c)
++{
++ unsigned v;
++
++ v = c - '0';
++ if (v <= 9)
++ return v;
++ /* c | 0x20: letters to lower case, non-letters
++ * to (potentially different) non-letters */
++ v = (unsigned)(c | 0x20) - 'a';
++ if (v <= 5)
++ return v + 10;
++ return ~0;
++/* For testing:
++void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); }
++int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f');
++t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; }
++*/
++}
++
++char* FAST_FUNC percent_decode_in_place(char *str, int strict)
++{
++ /* note that decoded string is always shorter than original */
++ char *src = str;
++ char *dst = str;
++ char c;
++
++ while ((c = *src++) != '\0') {
++ unsigned v;
++
++ if (!strict && c == '+') {
++ *dst++ = ' ';
++ continue;
++ }
++ if (c != '%') {
++ *dst++ = c;
++ continue;
++ }
++ v = hex_to_bin(src[0]);
++ if (v > 15) {
++ bad_hex:
++ if (strict)
++ return NULL;
++ *dst++ = '%';
++ continue;
++ }
++ v = (v * 16) | hex_to_bin(src[1]);
++ if (v > 255)
++ goto bad_hex;
++ if (strict && (v == '/' || v == '\0')) {
++ /* caller takes it as indication of invalid
++ * (dangerous wrt exploits) chars */
++ return str + 1;
++ }
++ *dst++ = v;
++ src += 2;
++ }
++ *dst = '\0';
++ return str;
++}
+--- a/networking/httpd.c
++++ b/networking/httpd.c
+@@ -820,78 +820,6 @@ static char *encodeString(const char *st
+ }
+ #endif
+
+-/*
+- * Given a URL encoded string, convert it to plain ascii.
+- * Since decoding always makes strings smaller, the decode is done in-place.
+- * Thus, callers should xstrdup() the argument if they do not want the
+- * argument modified. The return is the original pointer, allowing this
+- * function to be easily used as arguments to other functions.
+- *
+- * string The first string to decode.
+- * option_d 1 if called for httpd -d
+- *
+- * Returns a pointer to the decoded string (same as input).
+- */
+-static unsigned hex_to_bin(unsigned char c)
+-{
+- unsigned v;
+-
+- v = c - '0';
+- if (v <= 9)
+- return v;
+- /* c | 0x20: letters to lower case, non-letters
+- * to (potentially different) non-letters */
+- v = (unsigned)(c | 0x20) - 'a';
+- if (v <= 5)
+- return v + 10;
+- return ~0;
+-/* For testing:
+-void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); }
+-int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f');
+-t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; }
+-*/
+-}
+-static char *decodeString(char *orig, int option_d)
+-{
+- /* note that decoded string is always shorter than original */
+- char *string = orig;
+- char *ptr = string;
+- char c;
+-
+- while ((c = *ptr++) != '\0') {
+- unsigned v;
+-
+- if (option_d && c == '+') {
+- *string++ = ' ';
+- continue;
+- }
+- if (c != '%') {
+- *string++ = c;
+- continue;
+- }
+- v = hex_to_bin(ptr[0]);
+- if (v > 15) {
+- bad_hex:
+- if (!option_d)
+- return NULL;
+- *string++ = '%';
+- continue;
+- }
+- v = (v * 16) | hex_to_bin(ptr[1]);
+- if (v > 255)
+- goto bad_hex;
+- if (!option_d && (v == '/' || v == '\0')) {
+- /* caller takes it as indication of invalid
+- * (dangerous wrt exploits) chars */
+- return orig + 1;
+- }
+- *string++ = v;
+- ptr += 2;
+- }
+- *string = '\0';
+- return orig;
+-}
+-
+ #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
+ /*
+ * Decode a base64 data stream as per rfc1521.
+@@ -1949,7 +1877,7 @@ static void handle_incoming_and_exit(con
+ }
+
+ /* Decode URL escape sequences */
+- tptr = decodeString(urlcopy, 0);
++ tptr = percent_decode_in_place(urlcopy, /*strict:*/ 1);
+ if (tptr == NULL)
+ send_headers_and_exit(HTTP_BAD_REQUEST);
+ if (tptr == urlcopy + 1) {
+@@ -2408,7 +2336,7 @@ int httpd_main(int argc UNUSED_PARAM, ch
+ , &verbose
+ );
+ if (opt & OPT_DECODE_URL) {
+- fputs(decodeString(url_for_decode, 1), stdout);
++ fputs(percent_decode_in_place(url_for_decode, /*strict:*/ 0), stdout);
+ return 0;
+ }
+ #if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR
+--- a/networking/wget.c
++++ b/networking/wget.c
+@@ -298,8 +298,13 @@ static void parse_url(const char *src_ur
+
+ sp = strrchr(h->host, '@');
+ if (sp != NULL) {
+- h->user = h->host;
++ // URL-decode "user:password" string before base64-encoding:
++ // wget http://test:my%20pass@example.com should send
++ // Authorization: Basic dGVzdDpteSBwYXNz
++ // which decodes to "test:my pass".
++ // Standard wget and curl do this too.
+ *sp = '\0';
++ h->user = percent_decode_in_place(h->host, /*strict:*/ 0);
+ h->host = sp + 1;
+ }
+
+@@ -661,12 +666,6 @@ static void download_one_url(const char
+
+ #if ENABLE_FEATURE_WGET_AUTHENTICATION
+ if (target.user) {
+-//TODO: URL-decode "user:password" string before base64-encoding:
+-//wget http://test:my%20pass@example.com should send
+-// Authorization: Basic dGVzdDpteSBwYXNz
+-//which decodes to "test:my pass", instead of what we send now:
+-// Authorization: Basic dGVzdDpteSUyMHBhc3M=
+-//Can reuse decodeString() from httpd.c
+ fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6,
+ base64enc(target.user));
+ }
diff --git a/package/busybox/patches/005-resource_h_include.patch b/package/busybox/patches/005-resource_h_include.patch
new file mode 100644
index 000000000..d66d66d67
--- /dev/null
+++ b/package/busybox/patches/005-resource_h_include.patch
@@ -0,0 +1,10 @@
+--- a/include/libbb.h
++++ b/include/libbb.h
+@@ -35,6 +35,7 @@
+ #include <sys/poll.h>
+ #include <sys/ioctl.h>
+ #include <sys/mman.h>
++#include <sys/resource.h>
+ #include <sys/socket.h>
+ #include <sys/stat.h>
+ #include <sys/time.h>
diff --git a/package/busybox/patches/006-upstream_CVE-2011-2716_fixes.patch b/package/busybox/patches/006-upstream_CVE-2011-2716_fixes.patch
new file mode 100644
index 000000000..94d5f34a1
--- /dev/null
+++ b/package/busybox/patches/006-upstream_CVE-2011-2716_fixes.patch
@@ -0,0 +1,164 @@
+--- busybox-1.19.4/networking/udhcp/common.c
++++ busybox-1.19.4-udhcp/networking/udhcp/common.c
+@@ -29,16 +29,16 @@ const struct dhcp_optflag dhcp_optflags[
+ // { OPTION_IP | OPTION_LIST , 0x07 }, /* DHCP_LOG_SERVER */
+ // { OPTION_IP | OPTION_LIST , 0x08 }, /* DHCP_COOKIE_SERVER */
+ { OPTION_IP | OPTION_LIST , 0x09 }, /* DHCP_LPR_SERVER */
+- { OPTION_STRING | OPTION_REQ, 0x0c }, /* DHCP_HOST_NAME */
++ { OPTION_STRING_HOST | OPTION_REQ, 0x0c }, /* DHCP_HOST_NAME */
+ { OPTION_U16 , 0x0d }, /* DHCP_BOOT_SIZE */
+- { OPTION_STRING | OPTION_REQ, 0x0f }, /* DHCP_DOMAIN_NAME */
++ { OPTION_STRING_HOST | OPTION_REQ, 0x0f }, /* DHCP_DOMAIN_NAME */
+ { OPTION_IP , 0x10 }, /* DHCP_SWAP_SERVER */
+ { OPTION_STRING , 0x11 }, /* DHCP_ROOT_PATH */
+ { OPTION_U8 , 0x17 }, /* DHCP_IP_TTL */
+ { OPTION_U16 , 0x1a }, /* DHCP_MTU */
+ { OPTION_IP | OPTION_REQ, 0x1c }, /* DHCP_BROADCAST */
+ { OPTION_IP_PAIR | OPTION_LIST , 0x21 }, /* DHCP_ROUTES */
+- { OPTION_STRING , 0x28 }, /* DHCP_NIS_DOMAIN */
++ { OPTION_STRING_HOST , 0x28 }, /* DHCP_NIS_DOMAIN */
+ { OPTION_IP | OPTION_LIST , 0x29 }, /* DHCP_NIS_SERVER */
+ { OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a }, /* DHCP_NTP_SERVER */
+ { OPTION_IP | OPTION_LIST , 0x2c }, /* DHCP_WINS_SERVER */
+@@ -46,7 +46,7 @@ const struct dhcp_optflag dhcp_optflags[
+ { OPTION_IP , 0x36 }, /* DHCP_SERVER_ID */
+ { OPTION_STRING , 0x38 }, /* DHCP_ERR_MESSAGE */
+ //TODO: must be combined with 'sname' and 'file' handling:
+- { OPTION_STRING , 0x42 }, /* DHCP_TFTP_SERVER_NAME */
++ { OPTION_STRING_HOST , 0x42 }, /* DHCP_TFTP_SERVER_NAME */
+ { OPTION_STRING , 0x43 }, /* DHCP_BOOT_FILE */
+ //TODO: not a string, but a set of LASCII strings:
+ // { OPTION_STRING , 0x4D }, /* DHCP_USER_CLASS */
+@@ -143,6 +143,7 @@ const uint8_t dhcp_option_lengths[] ALIG
+ [OPTION_IP_PAIR] = 8,
+ // [OPTION_BOOLEAN] = 1,
+ [OPTION_STRING] = 1, /* ignored by udhcp_str2optset */
++ [OPTION_STRING_HOST] = 1, /* ignored by udhcp_str2optset */
+ #if ENABLE_FEATURE_UDHCP_RFC3397
+ [OPTION_DNS_STRING] = 1, /* ignored by both udhcp_str2optset and xmalloc_optname_optval */
+ [OPTION_SIP_SERVERS] = 1,
+@@ -411,7 +412,9 @@ static NOINLINE void attach_option(
+ /* actually 255 is ok too, but adding a space can overlow it */
+
+ existing->data = xrealloc(existing->data, OPT_DATA + 1 + old_len + length);
+- if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING) {
++ if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING
++ || (optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING_HOST
++ ) {
+ /* add space separator between STRING options in a list */
+ existing->data[OPT_DATA + old_len] = ' ';
+ old_len++;
+@@ -475,6 +478,7 @@ int FAST_FUNC udhcp_str2optset(const cha
+ retval = udhcp_str2nip(val, buffer + 4);
+ break;
+ case OPTION_STRING:
++ case OPTION_STRING_HOST:
+ #if ENABLE_FEATURE_UDHCP_RFC3397
+ case OPTION_DNS_STRING:
+ #endif
+--- busybox-1.19.4/networking/udhcp/common.h
++++ busybox-1.19.4-udhcp/networking/udhcp/common.h
+@@ -80,6 +80,9 @@ enum {
+ OPTION_IP = 1,
+ OPTION_IP_PAIR,
+ OPTION_STRING,
++ /* Opts of STRING_HOST type will be sanitized before they are passed
++ * to udhcpc script's environment: */
++ OPTION_STRING_HOST,
+ // OPTION_BOOLEAN,
+ OPTION_U8,
+ OPTION_U16,
+--- busybox-1.19.4/networking/udhcp/dhcpc.c
++++ busybox-1.19.4-udhcp/networking/udhcp/dhcpc.c
+@@ -101,6 +101,7 @@ static const uint8_t len_of_option_as_st
+ [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2,
+ [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "),
+ [OPTION_STRING ] = 1,
++ [OPTION_STRING_HOST ] = 1,
+ #if ENABLE_FEATURE_UDHCP_RFC3397
+ [OPTION_DNS_STRING ] = 1, /* unused */
+ /* Hmmm, this severely overestimates size if SIP_SERVERS option
+@@ -135,6 +136,63 @@ static int mton(uint32_t mask)
+ return i;
+ }
+
++/* Check if a given label represents a valid DNS label
++ * Return pointer to the first character after the label upon success,
++ * NULL otherwise.
++ * See RFC1035, 2.3.1
++ */
++/* We don't need to be particularly anal. For example, allowing _, hyphen
++ * at the end, or leading and trailing dots would be ok, since it
++ * can't be used for attacks. (Leading hyphen can be, if someone uses
++ * cmd "$hostname"
++ * in the script: then hostname may be treated as an option)
++ */
++static const char *valid_domain_label(const char *label)
++{
++ unsigned char ch;
++ unsigned pos = 0;
++
++ for (;;) {
++ ch = *label;
++ if ((ch|0x20) < 'a' || (ch|0x20) > 'z') {
++ if (pos == 0) {
++ /* label must begin with letter */
++ return NULL;
++ }
++ if (ch < '0' || ch > '9') {
++ if (ch == '\0' || ch == '.')
++ return label;
++ /* DNS allows only '-', but we are more permissive */
++ if (ch != '-' && ch != '_')
++ return NULL;
++ }
++ }
++ label++;
++ pos++;
++ //Do we want this?
++ //if (pos > 63) /* NS_MAXLABEL; labels must be 63 chars or less */
++ // return NULL;
++ }
++}
++
++/* Check if a given name represents a valid DNS name */
++/* See RFC1035, 2.3.1 */
++static int good_hostname(const char *name)
++{
++ //const char *start = name;
++
++ for (;;) {
++ name = valid_domain_label(name);
++ if (!name)
++ return 0;
++ if (!name[0])
++ return 1;
++ //Do we want this?
++ //return ((name - start) < 1025); /* NS_MAXDNAME */
++ name++;
++ }
++}
++
+ /* Create "opt_name=opt_value" string */
+ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_optflag *optflag, const char *opt_name)
+ {
+@@ -185,8 +243,11 @@ static NOINLINE char *xmalloc_optname_op
+ break;
+ }
+ case OPTION_STRING:
++ case OPTION_STRING_HOST:
+ memcpy(dest, option, len);
+ dest[len] = '\0';
++ if (type == OPTION_STRING_HOST && !good_hostname(dest))
++ safe_strncpy(dest, "bad", len);
+ return ret; /* Short circuit this case */
+ case OPTION_STATIC_ROUTES: {
+ /* Option binary format:
+@@ -314,6 +375,7 @@ static char **fill_envp(struct dhcp_pack
+ /* +1 element for each option, +2 for subnet option: */
+ if (packet) {
+ /* note: do not search for "pad" (0) and "end" (255) options */
++//TODO: change logic to scan packet _once_
+ for (i = 1; i < 255; i++) {
+ temp = udhcp_get_option(packet, i);
+ if (temp) {
diff --git a/package/busybox/patches/110-wget_getopt_fix.patch b/package/busybox/patches/110-wget_getopt_fix.patch
new file mode 100644
index 000000000..100323146
--- /dev/null
+++ b/package/busybox/patches/110-wget_getopt_fix.patch
@@ -0,0 +1,11 @@
+--- a/networking/wget.c
++++ b/networking/wget.c
+@@ -873,7 +873,7 @@ int wget_main(int argc UNUSED_PARAM, cha
+ /* Ignored: */
+ // "tries\0" Required_argument "t"
+ /* Ignored (we always use PASV): */
+- "passive-ftp\0" No_argument "\xff"
++ "passive-ftp\0" No_argument "\xfd"
+ "header\0" Required_argument "\xfe"
+ "post-data\0" Required_argument "\xfd"
+ /* Ignored (we don't do ssl) */
diff --git a/package/busybox/patches/140-trylink_bash.patch b/package/busybox/patches/140-trylink_bash.patch
new file mode 100644
index 000000000..f9571fcbc
--- /dev/null
+++ b/package/busybox/patches/140-trylink_bash.patch
@@ -0,0 +1,8 @@
+--- a/scripts/trylink
++++ b/scripts/trylink
+@@ -1,4 +1,4 @@
+-#!/bin/sh
++#!/usr/bin/env bash
+
+ debug=false
+
diff --git a/package/busybox/patches/141-gen_build_files_bash.patch b/package/busybox/patches/141-gen_build_files_bash.patch
new file mode 100644
index 000000000..d258fb8bc
--- /dev/null
+++ b/package/busybox/patches/141-gen_build_files_bash.patch
@@ -0,0 +1,8 @@
+--- a/scripts/gen_build_files.sh
++++ b/scripts/gen_build_files.sh
+@@ -1,4 +1,4 @@
+-#!/bin/sh
++#!/usr/bin/env bash
+
+ # Note: was using sed OPTS CMD -- FILES
+ # but users complain that many sed implementations
diff --git a/package/busybox/patches/150-no_static_libgcc.patch b/package/busybox/patches/150-no_static_libgcc.patch
new file mode 100644
index 000000000..fde6fbb86
--- /dev/null
+++ b/package/busybox/patches/150-no_static_libgcc.patch
@@ -0,0 +1,11 @@
+--- a/Makefile.flags
++++ b/Makefile.flags
+@@ -50,7 +50,7 @@ CFLAGS += $(call cc-option,-fno-builtin-
+ # -fno-guess-branch-probability: prohibit pseudo-random guessing
+ # of branch probabilities (hopefully makes bloatcheck more stable):
+ CFLAGS += $(call cc-option,-fno-guess-branch-probability,)
+-CFLAGS += $(call cc-option,-funsigned-char -static-libgcc,)
++CFLAGS += $(call cc-option,-funsigned-char,)
+ CFLAGS += $(call cc-option,-falign-functions=1 -falign-jumps=1 -falign-labels=1 -falign-loops=1,)
+
+ # FIXME: These warnings are at least partially to be concerned about and should
diff --git a/package/busybox/patches/200-etc_crontabs.patch b/package/busybox/patches/200-etc_crontabs.patch
new file mode 100644
index 000000000..ebf299050
--- /dev/null
+++ b/package/busybox/patches/200-etc_crontabs.patch
@@ -0,0 +1,22 @@
+--- a/miscutils/crond.c
++++ b/miscutils/crond.c
+@@ -37,7 +37,7 @@
+
+
+ #define TMPDIR CONFIG_FEATURE_CROND_DIR
+-#define CRONTABS CONFIG_FEATURE_CROND_DIR "/crontabs"
++#define CRONTABS "/etc/crontabs"
+ #ifndef SENDMAIL
+ # define SENDMAIL "sendmail"
+ #endif
+--- a/miscutils/crontab.c
++++ b/miscutils/crontab.c
+@@ -22,7 +22,7 @@
+
+ #include "libbb.h"
+
+-#define CRONTABS CONFIG_FEATURE_CROND_DIR "/crontabs"
++#define CRONTABS "/etc/crontabs"
+ #ifndef CRONUPDATE
+ #define CRONUPDATE "cron.update"
+ #endif
diff --git a/package/busybox/patches/240-udhcpc_retries.patch b/package/busybox/patches/240-udhcpc_retries.patch
new file mode 100644
index 000000000..a9f4f3d1e
--- /dev/null
+++ b/package/busybox/patches/240-udhcpc_retries.patch
@@ -0,0 +1,20 @@
+--- a/networking/udhcp/dhcpc.c
++++ b/networking/udhcp/dhcpc.c
+@@ -1257,7 +1257,7 @@ int udhcpc_main(int argc UNUSED_PARAM, c
+
+ switch (state) {
+ case INIT_SELECTING:
+- if (packet_num < discover_retries) {
++ if (!discover_retries || packet_num < discover_retries) {
+ if (packet_num == 0)
+ xid = random_xid();
+ /* broadcast */
+@@ -1286,7 +1286,7 @@ int udhcpc_main(int argc UNUSED_PARAM, c
+ packet_num = 0;
+ continue;
+ case REQUESTING:
+- if (packet_num < discover_retries) {
++ if (!discover_retries || packet_num < discover_retries) {
+ /* send broadcast select packet */
+ send_select(xid, server_addr, requested_ip);
+ timeout = discover_timeout;
diff --git a/package/busybox/patches/241-udhcpc-oversized_packets.patch b/package/busybox/patches/241-udhcpc-oversized_packets.patch
new file mode 100644
index 000000000..471d704a7
--- /dev/null
+++ b/package/busybox/patches/241-udhcpc-oversized_packets.patch
@@ -0,0 +1,99 @@
+--- a/networking/udhcp/packet.c
++++ b/networking/udhcp/packet.c
+@@ -158,6 +158,11 @@ uint16_t FAST_FUNC udhcp_checksum(void *
+ return ~sum;
+ }
+
++int udhcp_get_payload_len(struct dhcp_packet *dhcp_pkt)
++{
++ return sizeof(struct dhcp_packet) - DHCP_OPTIONS_BUFSIZE + udhcp_end_option(dhcp_pkt->options) + sizeof(dhcp_pkt->options[0]);
++}
++
+ /* Construct a ip/udp header for a packet, send packet */
+ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt,
+ uint32_t source_nip, int source_port,
+@@ -166,10 +171,10 @@ int FAST_FUNC udhcp_send_raw_packet(stru
+ {
+ struct sockaddr_ll dest_sll;
+ struct ip_udp_dhcp_packet packet;
+- unsigned padding;
+ int fd;
+ int result = -1;
+ const char *msg;
++ int p_len = udhcp_get_payload_len(dhcp_pkt);
+
+ fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
+ if (fd < 0) {
+@@ -178,8 +183,8 @@ int FAST_FUNC udhcp_send_raw_packet(stru
+ }
+
+ memset(&dest_sll, 0, sizeof(dest_sll));
+- memset(&packet, 0, offsetof(struct ip_udp_dhcp_packet, data));
+- packet.data = *dhcp_pkt; /* struct copy */
++ memset(&packet, 0, sizeof(packet));
++ memcpy(&(packet.data), dhcp_pkt, p_len);
+
+ dest_sll.sll_family = AF_PACKET;
+ dest_sll.sll_protocol = htons(ETH_P_IP);
+@@ -192,36 +197,24 @@ int FAST_FUNC udhcp_send_raw_packet(stru
+ goto ret_close;
+ }
+
+- /* We were sending full-sized DHCP packets (zero padded),
+- * but some badly configured servers were seen dropping them.
+- * Apparently they drop all DHCP packets >576 *ethernet* octets big,
+- * whereas they may only drop packets >576 *IP* octets big
+- * (which for typical Ethernet II means 590 octets: 6+6+2 + 576).
+- *
+- * In order to work with those buggy servers,
+- * we truncate packets after end option byte.
+- */
+- padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(packet.data.options);
+-
+ packet.ip.protocol = IPPROTO_UDP;
+ packet.ip.saddr = source_nip;
+ packet.ip.daddr = dest_nip;
+ packet.udp.source = htons(source_port);
+ packet.udp.dest = htons(dest_port);
+- /* size, excluding IP header: */
+- packet.udp.len = htons(UDP_DHCP_SIZE - padding);
+- /* for UDP checksumming, ip.len is set to UDP packet len */
++ p_len += sizeof(packet.udp);
++ packet.udp.len = htons(p_len);
+ packet.ip.tot_len = packet.udp.len;
+- packet.udp.check = udhcp_checksum(&packet, IP_UDP_DHCP_SIZE - padding);
+- /* but for sending, it is set to IP packet len */
+- packet.ip.tot_len = htons(IP_UDP_DHCP_SIZE - padding);
++ p_len += sizeof(packet.ip);
++ packet.udp.check = udhcp_checksum(&packet, p_len);
++ packet.ip.tot_len = htons(p_len);
+ packet.ip.ihl = sizeof(packet.ip) >> 2;
+ packet.ip.version = IPVERSION;
+ packet.ip.ttl = IPDEFTTL;
+ packet.ip.check = udhcp_checksum(&packet.ip, sizeof(packet.ip));
+
+ udhcp_dump_packet(dhcp_pkt);
+- result = sendto(fd, &packet, IP_UDP_DHCP_SIZE - padding, /*flags:*/ 0,
++ result = sendto(fd, &packet, p_len, /*flags:*/ 0,
+ (struct sockaddr *) &dest_sll, sizeof(dest_sll));
+ msg = "sendto";
+ ret_close:
+@@ -239,7 +232,6 @@ int FAST_FUNC udhcp_send_kernel_packet(s
+ uint32_t dest_nip, int dest_port)
+ {
+ struct sockaddr_in client;
+- unsigned padding;
+ int fd;
+ int result = -1;
+ const char *msg;
+@@ -270,9 +262,7 @@ int FAST_FUNC udhcp_send_kernel_packet(s
+ }
+
+ udhcp_dump_packet(dhcp_pkt);
+-
+- padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(dhcp_pkt->options);
+- result = safe_write(fd, dhcp_pkt, DHCP_SIZE - padding);
++ result = safe_write(fd, dhcp_pkt, udhcp_get_payload_len(dhcp_pkt));
+ msg = "write";
+ ret_close:
+ close(fd);
diff --git a/package/busybox/patches/242-udhcpc_msgs.patch b/package/busybox/patches/242-udhcpc_msgs.patch
new file mode 100644
index 000000000..998e3b664
--- /dev/null
+++ b/package/busybox/patches/242-udhcpc_msgs.patch
@@ -0,0 +1,18 @@
+--- a/networking/udhcp/dhcpc.c
++++ b/networking/udhcp/dhcpc.c
+@@ -540,6 +540,7 @@ static int raw_bcast_from_client_config_
+ static NOINLINE int send_discover(uint32_t xid, uint32_t requested)
+ {
+ struct dhcp_packet packet;
++ static int msgs = 0;
+
+ /* Fill in: op, htype, hlen, cookie, chaddr fields,
+ * random xid field (we override it below),
+@@ -557,6 +558,7 @@ static NOINLINE int send_discover(uint32
+ */
+ add_client_options(&packet);
+
++ if (msgs++ < 3)
+ bb_info_msg("Sending discover...");
+ return raw_bcast_from_client_config_ifindex(&packet);
+ }
diff --git a/package/busybox/patches/243-udhcpc_changed_ifindex.patch b/package/busybox/patches/243-udhcpc_changed_ifindex.patch
new file mode 100644
index 000000000..4b28166bc
--- /dev/null
+++ b/package/busybox/patches/243-udhcpc_changed_ifindex.patch
@@ -0,0 +1,15 @@
+--- a/networking/udhcp/dhcpc.c
++++ b/networking/udhcp/dhcpc.c
+@@ -1205,6 +1205,12 @@ int udhcpc_main(int argc UNUSED_PARAM, c
+ /* silence "uninitialized!" warning */
+ unsigned timestamp_before_wait = timestamp_before_wait;
+
++ /* When running on a bridge, the ifindex may have changed (e.g. if
++ * member interfaces were added/removed or if the status of the
++ * bridge changed).
++ * Workaround: refresh it here before processing the next packet */
++ udhcp_read_interface(client_config.interface, &client_config.ifindex, NULL, client_config.client_mac);
++
+ //bb_error_msg("sockfd:%d, listen_mode:%d", sockfd, listen_mode);
+
+ /* Was opening raw or udp socket here
diff --git a/package/busybox/patches/244-udhcpc_add_6rd_option.patch b/package/busybox/patches/244-udhcpc_add_6rd_option.patch
new file mode 100644
index 000000000..9e30ef79a
--- /dev/null
+++ b/package/busybox/patches/244-udhcpc_add_6rd_option.patch
@@ -0,0 +1,143 @@
+--- a/networking/udhcp/common.c
++++ b/networking/udhcp/common.c
+@@ -60,6 +60,8 @@ const struct dhcp_optflag dhcp_optflags[
+ { OPTION_U8 , 0x85 }, /* DHCP_VLAN_PRIORITY */
+ #endif
+ { OPTION_STATIC_ROUTES , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */
++ { OPTION_6RD , 0xd4 }, /* DHCP_6RD (RFC) */
++ { OPTION_6RD , 0x96 }, /* DHCP_6RD (Comcast) */
+ { OPTION_STRING , 0xfc }, /* DHCP_WPAD */
+
+ /* Options below have no match in dhcp_option_strings[],
+@@ -127,6 +129,8 @@ const char dhcp_option_strings[] ALIGN1
+ "vlanpriority" "\0"/* DHCP_VLAN_PRIORITY */
+ #endif
+ "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */
++ "ip6rd" "\0" /* DHCP_6RD (RFC) */
++ "ip6rd" "\0" /* DHCP_6RD (Comcast) */
+ "wpad" "\0" /* DHCP_WPAD */
+ ;
+
+@@ -154,6 +158,7 @@ const uint8_t dhcp_option_lengths[] ALIG
+ [OPTION_S32] = 4,
+ /* Just like OPTION_STRING, we use minimum length here */
+ [OPTION_STATIC_ROUTES] = 5,
++ [OPTION_6RD] = 22,
+ };
+
+
+--- a/networking/udhcp/common.h
++++ b/networking/udhcp/common.h
+@@ -88,6 +88,7 @@ enum {
+ OPTION_S32,
+ OPTION_BIN,
+ OPTION_STATIC_ROUTES,
++ OPTION_6RD,
+ #if ENABLE_FEATURE_UDHCP_RFC3397
+ OPTION_DNS_STRING, /* RFC1035 compressed domain name list */
+ OPTION_SIP_SERVERS,
+--- a/networking/udhcp/dhcpc.c
++++ b/networking/udhcp/dhcpc.c
+@@ -100,6 +100,7 @@ static const uint8_t len_of_option_as_st
+ [OPTION_IP ] = sizeof("255.255.255.255 "),
+ [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2,
+ [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "),
++ [OPTION_6RD ] = sizeof("32 128 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF 255.255.255.255 "),
+ [OPTION_STRING ] = 1,
+ #if ENABLE_FEATURE_UDHCP_RFC3397
+ [OPTION_DNS_STRING ] = 1, /* unused */
+@@ -123,6 +124,23 @@ static int sprint_nip(char *dest, const
+ return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]);
+ }
+
++static int sprint_nip6(char *dest, const char *pre, const uint8_t *ip)
++{
++ int len = 0;
++ int off;
++ uint16_t word;
++
++ len += sprintf(dest, "%s", pre);
++
++ for (off = 0; off < 16; off += 2)
++ {
++ move_from_unaligned16(word, &ip[off]);
++ len += sprintf(dest+len, "%s%04X", off ? ":" : "", htons(word));
++ }
++
++ return len;
++}
++
+ /* really simple implementation, just count the bits */
+ static int mton(uint32_t mask)
+ {
+@@ -231,6 +249,70 @@ static NOINLINE char *xmalloc_optname_op
+ }
+
+ return ret;
++ }
++ case OPTION_6RD: {
++ /* Option binary format:
++ * 0 1 2 3
++ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ * | OPTION_6RD | option-length | IPv4MaskLen | 6rdPrefixLen |
++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ * | |
++ * | 6rdPrefix |
++ * | (16 octets) |
++ * | |
++ * | |
++ * | |
++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ * | 6rdBRIPv4Address(es) |
++ * . .
++ * . .
++ * . .
++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ *
++ * We convert it to a string "IPv4MaskLen 6rdPrefixLen 6rdPrefix 6rdBRIPv4Address"
++ */
++
++ /* Sanity check: ensure that our length is at least 22 bytes, that
++ * IPv4MaskLen is <= 32, 6rdPrefixLen <= 128 and that the sum of
++ * (32 - IPv4MaskLen) + 6rdPrefixLen is less than or equal to 128.
++ * If any of these requirements is not fulfilled, return with empty
++ * value.
++ */
++ if ((len >= 22) && (*option <= 32) && (*(option+1) <= 128) &&
++ (((32 - *option) + *(option+1)) <= 128))
++ {
++ /* IPv4MaskLen */
++ dest += sprintf(dest, "%u ", *option++);
++ len--;
++
++ /* 6rdPrefixLen */
++ dest += sprintf(dest, "%u ", *option++);
++ len--;
++
++ /* 6rdPrefix */
++ dest += sprint_nip6(dest, "", option);
++ option += 16;
++ len -= 16;
++
++ /* 6rdBRIPv4Addresses */
++ while (len >= 4)
++ {
++ dest += sprint_nip(dest, " ", option);
++ option += 4;
++ len -= 4;
++
++ /* the code to determine the option size fails to work with
++ * lengths that are not a multiple of the minimum length,
++ * adding all advertised 6rdBRIPv4Addresses here would
++ * overflow the destination buffer, therefore skip the rest
++ * for now
++ */
++ break;
++ }
++ }
++
++ return ret;
+ }
+ #if ENABLE_FEATURE_UDHCP_RFC3397
+ case OPTION_DNS_STRING:
diff --git a/package/busybox/patches/250-ash_export-n.patch b/package/busybox/patches/250-ash_export-n.patch
new file mode 100644
index 000000000..048c236b8
--- /dev/null
+++ b/package/busybox/patches/250-ash_export-n.patch
@@ -0,0 +1,34 @@
+--- a/shell/ash.c
++++ b/shell/ash.c
+@@ -12611,8 +12611,17 @@ exportcmd(int argc UNUSED_PARAM, char **
+ const char *p;
+ char **aptr;
+ int flag = argv[0][0] == 'r' ? VREADONLY : VEXPORT;
++ int mask = ~0;
++ int nopt;
++ while ((nopt = nextopt("np"))) {
++ if (nopt == 'n') {
++ mask = ~flag;
++ } else { /* p */
++ break;
++ }
++ }
+
+- if (nextopt("p") != 'p') {
++ if (nopt != 'p') {
+ aptr = argptr;
+ name = *aptr;
+ if (name) {
+@@ -12624,10 +12633,12 @@ exportcmd(int argc UNUSED_PARAM, char **
+ vp = *findvar(hashvar(name), name);
+ if (vp) {
+ vp->flags |= flag;
++ vp->flags &= mask;
+ continue;
+ }
+ }
+ setvar(name, p, flag);
++ setvar(name, p, flag & mask);
+ } while ((name = *++aptr) != NULL);
+ return 0;
+ }
diff --git a/package/busybox/patches/251-ash_fix-redir-substitution.patch b/package/busybox/patches/251-ash_fix-redir-substitution.patch
new file mode 100644
index 000000000..cb2ae94e0
--- /dev/null
+++ b/package/busybox/patches/251-ash_fix-redir-substitution.patch
@@ -0,0 +1,12 @@
+--- a/shell/ash.c
++++ b/shell/ash.c
+@@ -6846,8 +6846,7 @@ evalvar(char *p, int flags, struct strli
+ patloc = expdest - (char *)stackblock();
+ if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
+ startloc, varflags,
+-//TODO: | EXP_REDIR too? All other such places do it too
+- /* quotes: */ flags & (EXP_FULL | EXP_CASE),
++ /* quotes: */ flags & (EXP_FULL | EXP_CASE | EXP_REDIR),
+ var_str_list)
+ ) {
+ int amount = expdest - (
diff --git a/package/busybox/patches/300-netmsg.patch b/package/busybox/patches/300-netmsg.patch
new file mode 100644
index 000000000..e8b2513eb
--- /dev/null
+++ b/package/busybox/patches/300-netmsg.patch
@@ -0,0 +1,103 @@
+--- a/include/applets.src.h
++++ b/include/applets.src.h
+@@ -266,6 +266,7 @@ IF_MT(APPLET(mt, BB_DIR_BIN, BB_SUID_DRO
+ IF_MV(APPLET(mv, BB_DIR_BIN, BB_SUID_DROP))
+ IF_NAMEIF(APPLET(nameif, BB_DIR_SBIN, BB_SUID_DROP))
+ IF_NC(APPLET(nc, BB_DIR_USR_BIN, BB_SUID_DROP))
++IF_NETMSG(APPLET(netmsg, BB_DIR_BIN, BB_SUID_REQUIRE))
+ IF_NETSTAT(APPLET(netstat, BB_DIR_BIN, BB_SUID_DROP))
+ IF_NICE(APPLET(nice, BB_DIR_BIN, BB_SUID_DROP))
+ IF_NOHUP(APPLET(nohup, BB_DIR_USR_BIN, BB_SUID_DROP))
+--- a/networking/Config.src
++++ b/networking/Config.src
+@@ -612,6 +612,12 @@ config FEATURE_IPCALC_LONG_OPTIONS
+ help
+ Support long options for the ipcalc applet.
+
++config NETMSG
++ bool "netmsg"
++ default n
++ help
++ simple program for sending udp broadcast messages
++
+ config NETSTAT
+ bool "netstat"
+ default y
+--- a/networking/Kbuild.src
++++ b/networking/Kbuild.src
+@@ -27,6 +27,7 @@ lib-$(CONFIG_IP) += ip.o
+ lib-$(CONFIG_IPCALC) += ipcalc.o
+ lib-$(CONFIG_NAMEIF) += nameif.o
+ lib-$(CONFIG_NC) += nc.o
++lib-$(CONFIG_NETMSG) += netmsg.o
+ lib-$(CONFIG_NETSTAT) += netstat.o
+ lib-$(CONFIG_NSLOOKUP) += nslookup.o
+ lib-$(CONFIG_NTPD) += ntpd.o
+--- /dev/null
++++ b/networking/netmsg.c
+@@ -0,0 +1,65 @@
++/*
++ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
++ *
++ * This is free software, licensed under the GNU General Public License v2.
++ */
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <netdb.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include "busybox.h"
++
++//usage:#define netmsg_trivial_usage NOUSAGE_STR
++//usage:#define netmsg_full_usage ""
++
++#ifndef CONFIG_NETMSG
++int main(int argc, char **argv)
++#else
++int netmsg_main(int argc, char **argv)
++#endif
++{
++ int s;
++ struct sockaddr_in addr;
++ int optval = 1;
++ unsigned char buf[1001];
++
++ if (argc != 3) {
++ fprintf(stderr, "usage: %s <ip> \"<message>\"\n", argv[0]);
++ exit(1);
++ }
++
++ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
++ perror("Opening socket");
++ exit(1);
++ }
++
++ memset(&addr, 0, sizeof(addr));
++ addr.sin_family = AF_INET;
++ addr.sin_addr.s_addr = inet_addr(argv[1]);
++ addr.sin_port = htons(0x1337);
++
++ memset(buf, 0, 1001);
++ buf[0] = 0xde;
++ buf[1] = 0xad;
++
++ strncpy(buf + 2, argv[2], 998);
++
++ if (setsockopt (s, SOL_SOCKET, SO_BROADCAST, (caddr_t) &optval, sizeof (optval)) < 0) {
++ perror("setsockopt()");
++ goto fail;
++ }
++
++ if (sendto(s, buf, 1001, 0, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
++ perror("sendto()");
++ goto fail;
++ }
++
++ return 0;
++
++fail:
++ close(s);
++ exit(1);
++}
diff --git a/package/busybox/patches/310-passwd_access.patch b/package/busybox/patches/310-passwd_access.patch
new file mode 100644
index 000000000..daa1b9998
--- /dev/null
+++ b/package/busybox/patches/310-passwd_access.patch
@@ -0,0 +1,41 @@
+
+ Copyright (C) 2006 OpenWrt.org
+
+--- a/networking/httpd.c
++++ b/networking/httpd.c
+@@ -1700,21 +1700,32 @@ static int check_user_passwd(const char
+
+ if (ENABLE_FEATURE_HTTPD_AUTH_MD5) {
+ char *md5_passwd;
++ int user_len_p1;
+
+ md5_passwd = strchr(cur->after_colon, ':');
+- if (md5_passwd && md5_passwd[1] == '$' && md5_passwd[2] == '1'
++ user_len_p1 = md5_passwd + 1 - cur->after_colon;
++ if (md5_passwd && !strncmp(md5_passwd + 1, "$p$", 3)) {
++ struct passwd *pwd = NULL;
++
++ pwd = getpwnam(&md5_passwd[4]);
++ if(!pwd->pw_passwd || !pwd->pw_passwd[0] || pwd->pw_passwd[0] == '!')
++ return 1;
++
++ md5_passwd = pwd->pw_passwd;
++ goto check_md5_pw;
++ } else if (md5_passwd && md5_passwd[1] == '$' && md5_passwd[2] == '1'
+ && md5_passwd[3] == '$' && md5_passwd[4]
+ ) {
+ char *encrypted;
+- int r, user_len_p1;
++ int r;
+
+ md5_passwd++;
+- user_len_p1 = md5_passwd - cur->after_colon;
+ /* comparing "user:" */
+ if (strncmp(cur->after_colon, user_and_passwd, user_len_p1) != 0) {
+ continue;
+ }
+
++check_md5_pw:
+ encrypted = pw_encrypt(
+ user_and_passwd + user_len_p1 /* cleartext pwd from user */,
+ md5_passwd /*salt */, 1 /* cleanup */);
diff --git a/package/busybox/patches/340-lock_util.patch b/package/busybox/patches/340-lock_util.patch
new file mode 100644
index 000000000..eb346421a
--- /dev/null
+++ b/package/busybox/patches/340-lock_util.patch
@@ -0,0 +1,172 @@
+--- a/include/applets.src.h
++++ b/include/applets.src.h
+@@ -218,6 +218,7 @@ IF_LN(APPLET_NOEXEC(ln, ln, BB_DIR_BIN,
+ IF_LOAD_POLICY(APPLET(load_policy, BB_DIR_USR_SBIN, BB_SUID_DROP))
+ IF_LOADFONT(APPLET(loadfont, BB_DIR_USR_SBIN, BB_SUID_DROP))
+ IF_LOADKMAP(APPLET(loadkmap, BB_DIR_SBIN, BB_SUID_DROP))
++IF_LOCK(APPLET(lock, BB_DIR_BIN, BB_SUID_DROP))
+ IF_LOGGER(APPLET(logger, BB_DIR_USR_BIN, BB_SUID_DROP))
+ /* Needs to be run by root or be suid root - needs to change uid and gid: */
+ IF_LOGIN(APPLET(login, BB_DIR_BIN, BB_SUID_REQUIRE))
+--- a/miscutils/Config.src
++++ b/miscutils/Config.src
+@@ -419,6 +419,11 @@ config FEATURE_HDPARM_HDIO_GETSET_DMA
+ help
+ Enables the 'hdparm -d' option to get/set using_dma flag.
+
++config LOCK
++ bool "lock"
++ help
++ Small utility for using locks in scripts
++
+ config MAKEDEVS
+ bool "makedevs"
+ default y
+--- a/miscutils/Kbuild.src
++++ b/miscutils/Kbuild.src
+@@ -29,6 +29,7 @@ lib-$(CONFIG_INOTIFYD) += inotifyd.o
+ lib-$(CONFIG_FEATURE_LAST_SMALL)+= last.o
+ lib-$(CONFIG_FEATURE_LAST_FANCY)+= last_fancy.o
+ lib-$(CONFIG_LESS) += less.o
++lib-$(CONFIG_LOCK) += lock.o
+ lib-$(CONFIG_MAKEDEVS) += makedevs.o
+ lib-$(CONFIG_MAN) += man.o
+ lib-$(CONFIG_MICROCOM) += microcom.o
+--- /dev/null
++++ b/miscutils/lock.c
+@@ -0,0 +1,135 @@
++/*
++ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
++ *
++ * This is free software, licensed under the GNU General Public License v2.
++ */
++#include <sys/types.h>
++#include <sys/file.h>
++#include <sys/stat.h>
++#include <signal.h>
++#include <fcntl.h>
++#include <unistd.h>
++#include <stdio.h>
++#include "busybox.h"
++
++//usage:#define lock_trivial_usage NOUSAGE_STR
++//usage:#define lock_full_usage ""
++
++static int unlock = 0;
++static int shared = 0;
++static int waitonly = 0;
++static int fd;
++static char *file;
++
++static void usage(char *name)
++{
++ fprintf(stderr, "Usage: %s [-suw] <filename>\n"
++ " -s Use shared locking\n"
++ " -u Unlock\n"
++ " -w Wait for the lock to become free, don't acquire lock\n"
++ "\n", name);
++ exit(1);
++}
++
++static void exit_unlock(int sig)
++{
++ flock(fd, LOCK_UN);
++ exit(0);
++}
++
++static int do_unlock(void)
++{
++ FILE *f;
++ int i;
++
++ if ((f = fopen(file, "r")) == NULL)
++ return 0;
++
++ fscanf(f, "%d", &i);
++ if (i > 0)
++ kill(i, SIGTERM);
++
++ fclose(f);
++
++ return 0;
++}
++
++static int do_lock(void)
++{
++ int pid;
++ char pidstr[8];
++
++ if ((fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0700)) < 0) {
++ if ((fd = open(file, O_RDWR)) < 0) {
++ fprintf(stderr, "Can't open %s\n", file);
++ return 1;
++ }
++ }
++
++ if (flock(fd, (shared ? LOCK_SH : LOCK_EX)) < 0) {
++ fprintf(stderr, "Can't lock %s\n", file);
++ return 1;
++ }
++
++ pid = fork();
++
++ if (pid < 0)
++ return -1;
++
++ if (pid == 0) {
++ signal(SIGKILL, exit_unlock);
++ signal(SIGTERM, exit_unlock);
++ signal(SIGINT, exit_unlock);
++ if (waitonly)
++ exit_unlock(0);
++ else
++ while (1)
++ sleep(1);
++ } else {
++ if (!waitonly) {
++ lseek(fd, 0, SEEK_SET);
++ ftruncate(fd, 0);
++ sprintf(pidstr, "%d\n", pid);
++ write(fd, pidstr, strlen(pidstr));
++ close(fd);
++ }
++
++ return 0;
++ }
++ return 0;
++}
++
++int lock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
++int lock_main(int argc, char **argv)
++{
++ char **args = &argv[1];
++ int c = argc - 1;
++
++ while ((*args != NULL) && (*args)[0] == '-') {
++ char *ch = *args;
++ while (*(++ch) > 0) {
++ switch(*ch) {
++ case 'w':
++ waitonly = 1;
++ break;
++ case 's':
++ shared = 1;
++ break;
++ case 'u':
++ unlock = 1;
++ break;
++ }
++ }
++ c--;
++ args++;
++ }
++
++ if (c != 1)
++ usage(argv[0]);
++
++ file = *args;
++ if (unlock)
++ return do_unlock();
++ else
++ return do_lock();
++}
diff --git a/package/busybox/patches/350-httpd_redir.patch b/package/busybox/patches/350-httpd_redir.patch
new file mode 100644
index 000000000..11125e71f
--- /dev/null
+++ b/package/busybox/patches/350-httpd_redir.patch
@@ -0,0 +1,90 @@
+--- a/networking/httpd.c
++++ b/networking/httpd.c
+@@ -105,6 +105,7 @@
+ //usage: IF_FEATURE_HTTPD_BASIC_AUTH(" [-r REALM]")
+ //usage: " [-h HOME]\n"
+ //usage: "or httpd -d/-e" IF_FEATURE_HTTPD_AUTH_MD5("/-m") " STRING"
++//usage: " [-R <path> [-H <host>]]"
+ //usage:#define httpd_full_usage "\n\n"
+ //usage: "Listen for incoming HTTP requests\n"
+ //usage: "\n -i Inetd mode"
+@@ -121,6 +122,8 @@
+ //usage: "\n -m STRING MD5 crypt STRING")
+ //usage: "\n -e STRING HTML encode STRING"
+ //usage: "\n -d STRING URL decode STRING"
++//usage: "\n -R PATH Redirect target path"
++//usage: "\n -H HOST Redirect target host"
+
+ #include "libbb.h"
+ #if ENABLE_FEATURE_HTTPD_USE_SENDFILE
+@@ -272,6 +275,8 @@ struct globals {
+
+ const char *found_mime_type;
+ const char *found_moved_temporarily;
++ const char *redirect_path;
++ const char *redirect_host;
+ Htaccess_IP *ip_a_d; /* config allow/deny lines */
+
+ IF_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;)
+@@ -322,6 +327,8 @@ struct globals {
+ #define index_page (G.index_page )
+ #define found_mime_type (G.found_mime_type )
+ #define found_moved_temporarily (G.found_moved_temporarily)
++#define redirect_path (G.redirect_path )
++#define redirect_host (G.redirect_host )
+ #define last_mod (G.last_mod )
+ #define ip_a_d (G.ip_a_d )
+ #define g_realm (G.g_realm )
+@@ -956,8 +963,11 @@ static void send_headers(int responseNum
+ }
+ #endif
+ if (responseNum == HTTP_MOVED_TEMPORARILY) {
+- len += sprintf(iobuf + len, "Location: %s/%s%s\r\n",
++ len += sprintf(iobuf + len, "Location: %s%s%s%s%s%s\r\n",
++ (redirect_host ? "http://" : ""),
++ (redirect_host ? redirect_host : ""),
+ found_moved_temporarily,
++ (redirect_host ? "" : "/"),
+ (g_query ? "?" : ""),
+ (g_query ? g_query : ""));
+ }
+@@ -1925,8 +1935,12 @@ static void handle_incoming_and_exit(con
+ } while (*++tptr);
+ *++urlp = '\0'; /* terminate after last character */
+
++ /* redirect active */
++ if (redirect_path && (strncmp(urlcopy, redirect_path, strlen(redirect_path)) != 0))
++ found_moved_temporarily = redirect_path;
++
+ /* If URL is a directory, add '/' */
+- if (urlp[-1] != '/') {
++ if (!redirect_path && (urlp[-1] != '/')) {
+ if (is_directory(urlcopy + 1, 1, NULL)) {
+ found_moved_temporarily = urlcopy;
+ }
+@@ -2283,7 +2297,9 @@ static void sighup_handler(int sig UNUSE
+ }
+
+ enum {
+- c_opt_config_file = 0,
++ R_opt_redirect_path = 0,
++ H_opt_redirect_host,
++ c_opt_config_file,
+ d_opt_decode_url,
+ h_opt_home_httpd,
+ IF_FEATURE_HTTPD_ENCODE_URL_STR(e_opt_encode_url,)
+@@ -2332,12 +2348,13 @@ int httpd_main(int argc UNUSED_PARAM, ch
+ /* We do not "absolutize" path given by -h (home) opt.
+ * If user gives relative path in -h,
+ * $SCRIPT_FILENAME will not be set. */
+- opt = getopt32(argv, "c:d:h:"
++ opt = getopt32(argv, "R:H:c:d:h:"
+ IF_FEATURE_HTTPD_ENCODE_URL_STR("e:")
+ IF_FEATURE_HTTPD_BASIC_AUTH("r:")
+ IF_FEATURE_HTTPD_AUTH_MD5("m:")
+ IF_FEATURE_HTTPD_SETUID("u:")
+ "p:ifv",
++ &redirect_path, &redirect_host,
+ &opt_c_configFile, &url_for_decode, &home_httpd
+ IF_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode)
+ IF_FEATURE_HTTPD_BASIC_AUTH(, &g_realm)
diff --git a/package/busybox/patches/410-httpd_cgi_headers.patch b/package/busybox/patches/410-httpd_cgi_headers.patch
new file mode 100644
index 000000000..b02a5b9d7
--- /dev/null
+++ b/package/busybox/patches/410-httpd_cgi_headers.patch
@@ -0,0 +1,16 @@
+--- a/networking/httpd.c
++++ b/networking/httpd.c
+@@ -1222,10 +1222,10 @@ static NOINLINE void cgi_io_loop_and_exi
+ if (full_write(STDOUT_FILENO, HTTP_200, sizeof(HTTP_200)-1) != sizeof(HTTP_200)-1)
+ break;
+ }
+- /* Commented out:
+- if (!strstr(rbuf, "ontent-")) {
+- full_write(s, "Content-type: text/plain\r\n\r\n", 28);
++ if (!strstr(rbuf, "ontent-") && !strstr(rbuf, "ocation:")) {
++ full_write(1, "Content-type: text/plain\r\n\r\n", 28);
+ }
++ /* Previously commented out:
+ * Counter-example of valid CGI without Content-type:
+ * echo -en "HTTP/1.0 302 Found\r\n"
+ * echo -en "Location: http://www.busybox.net\r\n"
diff --git a/package/busybox/patches/440-httpd_chdir.patch b/package/busybox/patches/440-httpd_chdir.patch
new file mode 100644
index 000000000..401c6eb5d
--- /dev/null
+++ b/package/busybox/patches/440-httpd_chdir.patch
@@ -0,0 +1,10 @@
+--- a/networking/httpd.c
++++ b/networking/httpd.c
+@@ -1814,6 +1814,7 @@ static void handle_incoming_and_exit(con
+ char *header_ptr = header_ptr;
+ Htaccess_Proxy *proxy_entry;
+ #endif
++ xchdir(home_httpd);
+
+ /* Allocation of iobuf is postponed until now
+ * (IOW, server process doesn't need to waste 8k) */
diff --git a/package/busybox/patches/470-insmod_search.patch b/package/busybox/patches/470-insmod_search.patch
new file mode 100644
index 000000000..7f0188fc8
--- /dev/null
+++ b/package/busybox/patches/470-insmod_search.patch
@@ -0,0 +1,137 @@
+--- a/modutils/Config.src
++++ b/modutils/Config.src
+@@ -247,7 +247,7 @@ config FEATURE_MODUTILS_SYMBOLS
+ config DEFAULT_MODULES_DIR
+ string "Default directory containing modules"
+ default "/lib/modules"
+- depends on DEPMOD || MODPROBE || MODPROBE_SMALL || MODINFO
++ depends on DEPMOD || INSMOD || MODPROBE || MODPROBE_SMALL || MODINFO
+ help
+ Directory that contains kernel modules.
+ Defaults to "/lib/modules"
+--- a/modutils/insmod.c
++++ b/modutils/insmod.c
+@@ -11,6 +11,106 @@
+
+ #include "libbb.h"
+ #include "modutils.h"
++#include <sys/utsname.h>
++#ifndef CONFIG_FEATURE_2_4_MODULES
++#include <sys/mman.h>
++#include <asm/unistd.h>
++#include <sys/syscall.h>
++#endif
++
++static char *g_filename = NULL;
++
++static int FAST_FUNC check_module_name_match(const char *filename, struct stat *statbuf,
++ void *userdata, int depth)
++{
++ char *fullname = (char *) userdata;
++ char *tmp;
++
++ if (fullname[0] == '\0')
++ return FALSE;
++
++ tmp = bb_get_last_path_component_nostrip(filename);
++ if (strcmp(tmp, fullname) == 0) {
++ /* Stop searching if we find a match */
++ g_filename = xstrdup(filename);
++ return FALSE;
++ }
++
++ return TRUE;
++}
++
++static int find_module(char *filename)
++{
++ char *module_dir, real_module_dir[FILENAME_MAX];
++ int len, slen, ret = ENOENT, k_version;
++ struct utsname myuname;
++ const char *suffix = ".ko";
++ struct stat st;
++
++ /* check the kernel version */
++ if (uname(&myuname) != 0)
++ return EINVAL;
++
++ k_version = myuname.release[0] - '0';
++
++ if (k_version < 2 || k_version > 9)
++ return EINVAL;
++
++ if (k_version == 2) {
++ int k_patchlevel = myuname.release[2] - '0';
++ if (k_patchlevel <= 4)
++#if ENABLE_FEATURE_2_4_MODULES
++ suffix = ".o";
++#else
++ return EINVAL;
++#endif
++ }
++
++ len = strlen(filename);
++ slen = strlen(suffix);
++
++ /* check for suffix and absolute path first */
++ if ((len < slen + 2) || (strcmp(filename + len - slen, suffix) != 0)) {
++ filename = xasprintf("%s%s", filename, suffix);
++ } else {
++ filename = strdup(filename);
++ if ((stat(filename, &st) == 0) && S_ISREG(st.st_mode)) {
++ g_filename = filename;
++ return 0;
++ }
++ free(filename);
++ return ENOENT;
++ }
++
++ /* next: scan /lib/modules/<release> */
++ /* Jump through hoops in case /lib/modules/`uname -r`
++ * is a symlink. We do not want recursive_action to
++ * follow symlinks, but we do want to follow the
++ * /lib/modules/`uname -r` dir, So resolve it ourselves
++ * if it is a link... */
++ module_dir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, myuname.release);
++ if (realpath(module_dir, real_module_dir) != NULL) {
++ free(module_dir);
++ module_dir = real_module_dir;
++ }
++
++ recursive_action(module_dir, ACTION_RECURSE,
++ check_module_name_match, 0, filename, 0);
++
++ /* Check if we have a complete path */
++ if (g_filename == NULL)
++ goto done;
++
++ if ((stat(g_filename, &st) == 0) && S_ISREG(st.st_mode))
++ ret = 0;
++ else
++ free(g_filename);
++
++done:
++ free(filename);
++
++ return ret;
++}
+
+ /* 2.6 style insmod has no options and required filename
+ * (not module name - .ko can't be omitted) */
+@@ -58,9 +158,15 @@ int insmod_main(int argc UNUSED_PARAM, c
+ if (!filename)
+ bb_show_usage();
+
+- rc = bb_init_module(filename, parse_cmdline_module_options(argv, /*quote_spaces:*/ 0));
++ rc = find_module(filename);
++ if (rc || (g_filename == NULL))
++ goto done;
++
++ rc = bb_init_module(g_filename, parse_cmdline_module_options(argv, /*quote_spaces:*/ 0));
+ if (rc)
+ bb_error_msg("can't insert '%s': %s", filename, moderror(rc));
++ free (g_filename);
+
++done:
+ return rc;
+ }
diff --git a/package/busybox/patches/480-mount_union.patch b/package/busybox/patches/480-mount_union.patch
new file mode 100644
index 000000000..2f236a152
--- /dev/null
+++ b/package/busybox/patches/480-mount_union.patch
@@ -0,0 +1,29 @@
+--- a/util-linux/mount.c
++++ b/util-linux/mount.c
+@@ -136,6 +136,10 @@
+ # include <rpc/pmap_clnt.h>
+ #endif
+
++#ifndef MS_UNION
++#define MS_UNION 0x100 /* 256: Mount on top of a union */
++#endif
++
+
+ #if defined(__dietlibc__)
+ // 16.12.2006, Sampo Kellomaki (sampo@iki.fi)
+@@ -254,6 +258,7 @@ static const int32_t mount_options[] = {
+ /* "rslave" */ MS_SLAVE|MS_RECURSIVE,
+ /* "rprivate" */ MS_PRIVATE|MS_RECURSIVE,
+ /* "runbindable" */ MS_UNBINDABLE|MS_RECURSIVE,
++ /* "union" */ MS_UNION,
+ )
+
+ // Always understood.
+@@ -310,6 +315,7 @@ static const char mount_option_str[] =
+ "make-rslave\0"
+ "make-rprivate\0"
+ "make-runbindable\0"
++ "make-union\0"
+ )
+
+ // Always understood.
diff --git a/package/busybox/patches/490-mount_disable_check.patch b/package/busybox/patches/490-mount_disable_check.patch
new file mode 100644
index 000000000..2fcb7f7fc
--- /dev/null
+++ b/package/busybox/patches/490-mount_disable_check.patch
@@ -0,0 +1,12 @@
+--- a/util-linux/mount.c
++++ b/util-linux/mount.c
+@@ -128,9 +128,6 @@
+ #if ENABLE_FEATURE_MOUNT_NFS
+ /* This is just a warning of a common mistake. Possibly this should be a
+ * uclibc faq entry rather than in busybox... */
+-# if defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__)
+-# error "You need to build uClibc with UCLIBC_HAS_RPC for NFS support"
+-# endif
+ # include <rpc/rpc.h>
+ # include <rpc/pmap_prot.h>
+ # include <rpc/pmap_clnt.h>
diff --git a/package/busybox/patches/510-awk_include.patch b/package/busybox/patches/510-awk_include.patch
new file mode 100644
index 000000000..9f525acf8
--- /dev/null
+++ b/package/busybox/patches/510-awk_include.patch
@@ -0,0 +1,217 @@
+--- a/editors/awk.c
++++ b/editors/awk.c
+@@ -1,3 +1,4 @@
++
+ /* vi: set sw=4 ts=4: */
+ /*
+ * awk implementation for busybox
+@@ -81,9 +82,14 @@ typedef struct chain_s {
+ } chain;
+
+ /* Function */
++typedef var *(*awk_cfunc)(var *res, var *args, int nargs);
+ typedef struct func_s {
+ unsigned nargs;
++ enum { AWKFUNC, CFUNC } type;
++ union {
++ awk_cfunc cfunc;
+ struct chain_s body;
++ } x;
+ } func;
+
+ /* I/O stream */
+@@ -1473,7 +1479,8 @@ static void parse_program(char *p)
+ next_token(TC_FUNCTION);
+ g_pos++;
+ f = newfunc(t_string);
+- f->body.first = NULL;
++ f->type = AWKFUNC;
++ f->x.body.first = NULL;
+ f->nargs = 0;
+ while (next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) {
+ v = findvar(ahash, t_string);
+@@ -1482,7 +1489,7 @@ static void parse_program(char *p)
+ if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM)
+ break;
+ }
+- seq = &f->body;
++ seq = &f->x.body;
+ chain_group();
+ clear_array(ahash);
+
+@@ -2580,7 +2587,8 @@ static var *evaluate(node *op, var *res)
+ var *vbeg, *v;
+ const char *sv_progname;
+
+- if (!op->r.f->body.first)
++ if ((op->r.f->type == AWKFUNC) &&
++ !op->r.f->x.body.first)
+ syntax_error(EMSG_UNDEF_FUNC);
+
+ vbeg = v = nvalloc(op->r.f->nargs + 1);
+@@ -2597,7 +2605,10 @@ static var *evaluate(node *op, var *res)
+ fnargs = vbeg;
+ sv_progname = g_progname;
+
+- res = evaluate(op->r.f->body.first, res);
++ if (op->r.f->type == AWKFUNC)
++ res = evaluate(op->r.f->x.body.first, res);
++ else if (op->r.f->type == CFUNC)
++ res = op->r.f->x.cfunc(res, fnargs, op->r.f->nargs);
+
+ g_progname = sv_progname;
+ nvfree(fnargs);
+@@ -2991,6 +3002,143 @@ static rstream *next_input_file(void)
+ #undef files_happen
+ }
+
++/* read the contents of an entire file */
++static char *get_file(const char *fname)
++{
++ FILE *F;
++ char *s = NULL;
++ int i, j, flen;
++
++ F = fopen(fname, "r");
++ if (!F) {
++ return NULL;
++ }
++
++ if (fseek(F, 0, SEEK_END) == 0) {
++ flen = ftell(F);
++ s = (char *)xmalloc(flen+4);
++ fseek(F, 0, SEEK_SET);
++ i = 1 + fread(s+1, 1, flen, F);
++ } else {
++ for (i=j=1; j>0; i+=j) {
++ s = (char *)xrealloc(s, i+4096);
++ j = fread(s+i, 1, 4094, F);
++ }
++ }
++
++ s[i] = '\0';
++ fclose(F);
++ return s;
++}
++
++
++/* parse_include():
++ *
++ * taken from parse_program from awk.c
++ * END{} is not parsed here, and BEGIN{} is executed immediately
++ */
++static void parse_include(char *p)
++{
++ uint32_t tclass;
++ chain *initseq = NULL;
++ chain tmp;
++ func *f;
++ var *v, *tv;
++
++ tv = nvalloc(1);
++ memset(&tmp, 0, sizeof(tmp));
++ g_pos = p;
++ t_lineno = 1;
++ while ((tclass = next_token(TC_EOF | TC_OPSEQ |
++ TC_OPTERM | TC_BEGIN | TC_FUNCDECL)) != TC_EOF) {
++ if (tclass & TC_OPTERM)
++ continue;
++
++ seq = &tmp;
++ if (tclass & TC_BEGIN) {
++ initseq = xzalloc(sizeof(chain));
++ seq = initseq;
++ chain_group();
++ } else if (tclass & TC_FUNCDECL) {
++ next_token(TC_FUNCTION);
++ g_pos++;
++ f = newfunc(t_string);
++ f->type = AWKFUNC;
++ f->x.body.first = NULL;
++ f->nargs = 0;
++ while (next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) {
++ v = findvar(ahash, t_string);
++ v->x.aidx = (f->nargs)++;
++
++ if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM)
++ break;
++ }
++ seq = &(f->x.body);
++ chain_group();
++ clear_array(ahash);
++ }
++ }
++ if (initseq && initseq->first)
++ tv = evaluate(initseq->first, tv);
++ nvfree(tv);
++}
++
++
++/* include an awk file and run its BEGIN{} section */
++static xhash *includes = NULL;
++static void include_file(const char *filename)
++{
++ char *s;
++ var *v;
++ int oldlnr = g_lineno;
++ const char *oldprg = g_progname;
++
++ if (!includes)
++ includes = hash_init();
++
++ /* find out if the file has been included already */
++ v = findvar(includes, filename);
++ if (istrue(v))
++ return;
++ setvar_s(v, "1");
++
++ /* read include file */
++ s = get_file(filename);
++ if (!s) {
++ fprintf(stderr, "Could not open file.\n");
++ return;
++ }
++ g_lineno = 1;
++ g_progname = xstrdup(filename);
++ parse_include(s+1);
++ free(s);
++ g_lineno = oldlnr;
++ g_progname = oldprg;
++}
++
++static var *include(var *res, var *args, int nargs)
++{
++ const char *s;
++
++ nargs = nargs; /* shut up, gcc */
++ s = getvar_s(args);
++ if (s && (strlen(s) > 0))
++ include_file(s);
++
++ return res;
++}
++
++/* registers a global c function for the awk interpreter */
++static void register_cfunc(const char *name, awk_cfunc cfunc, int nargs)
++{
++ func *f;
++
++ f = newfunc(name);
++ f->type = CFUNC;
++ f->x.cfunc = cfunc;
++ f->nargs = nargs;
++}
++
+ int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+ int awk_main(int argc, char **argv)
+ {
+@@ -3056,6 +3204,9 @@ int awk_main(int argc, char **argv)
+ *s1 = '=';
+ }
+ }
++
++ register_cfunc("include", include, 1);
++
+ opt_complementary = "v::f::"; /* -v and -f can occur multiple times */
+ opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, &opt_W);
+ argv += optind;
diff --git a/package/busybox/patches/524-udhcpc_renew.patch b/package/busybox/patches/524-udhcpc_renew.patch
new file mode 100644
index 000000000..01edda3a5
--- /dev/null
+++ b/package/busybox/patches/524-udhcpc_renew.patch
@@ -0,0 +1,10 @@
+--- a/networking/udhcp/dhcpc.c
++++ b/networking/udhcp/dhcpc.c
+@@ -983,7 +983,6 @@ static void perform_renew(void)
+ state = RENEW_REQUESTED;
+ break;
+ case RENEW_REQUESTED: /* impatient are we? fine, square 1 */
+- udhcp_run_script(NULL, "deconfig");
+ case REQUESTING:
+ case RELEASED:
+ change_listen_mode(LISTEN_RAW);
diff --git a/package/busybox/patches/610-ntpd_delayed_resolve.patch b/package/busybox/patches/610-ntpd_delayed_resolve.patch
new file mode 100644
index 000000000..5e17ae16c
--- /dev/null
+++ b/package/busybox/patches/610-ntpd_delayed_resolve.patch
@@ -0,0 +1,48 @@
+--- a/networking/ntpd.c
++++ b/networking/ntpd.c
+@@ -216,6 +216,7 @@ typedef struct {
+ typedef struct {
+ len_and_sockaddr *p_lsa;
+ char *p_dotted;
++ char *p_hostname;
+ /* when to send new query (if p_fd == -1)
+ * or when receive times out (if p_fd >= 0): */
+ int p_fd;
+@@ -646,8 +647,9 @@ add_peers(char *s)
+ peer_t *p;
+
+ p = xzalloc(sizeof(*p));
+- p->p_lsa = xhost2sockaddr(s, 123);
+- p->p_dotted = xmalloc_sockaddr2dotted_noport(&p->p_lsa->u.sa);
++ p->p_hostname = s;
++ p->p_lsa = NULL;
++ p->p_dotted = NULL;
+ p->p_fd = -1;
+ p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3);
+ p->next_action_time = G.cur_time; /* = set_next(p, 0); */
+@@ -696,6 +698,25 @@ send_query_to_peer(peer_t *p)
+ *
+ * Uncomment this and use strace to see it in action:
+ */
++
++ /* See if the peer hostname already resolved yet, if not, retry to resolv and return on failure */
++ if (!p->p_lsa)
++ {
++ p->p_lsa = host2sockaddr(p->p_hostname, 123);
++
++ if (p->p_lsa)
++ {
++ p->p_dotted = xmalloc_sockaddr2dotted_noport(&p->p_lsa->u.sa);
++ VERB1 bb_error_msg("resolved peer %s to %s", p->p_hostname, p->p_dotted);
++ }
++ else
++ {
++ set_next(p, RETRY_INTERVAL);
++ VERB1 bb_error_msg("could not resolve peer %s, skipping", p->p_hostname);
++ return;
++ }
++ }
++
+ #define PROBE_LOCAL_ADDR /* { len_and_sockaddr lsa; lsa.len = LSA_SIZEOF_SA; getsockname(p->query.fd, &lsa.u.sa, &lsa.len); } */
+
+ if (p->p_fd == -1) {
diff --git a/package/busybox/patches/700-hexdump_segfault_fix.patch b/package/busybox/patches/700-hexdump_segfault_fix.patch
new file mode 100644
index 000000000..ab09fb3e4
--- /dev/null
+++ b/package/busybox/patches/700-hexdump_segfault_fix.patch
@@ -0,0 +1,11 @@
+--- a/libbb/dump.c
++++ b/libbb/dump.c
+@@ -301,7 +301,7 @@ static NOINLINE void rewrite(priv_dumper
+ ) {
+ fu->reps += (dumper->blocksize - fs->bcnt) / fu->bcnt;
+ }
+- if (fu->reps > 1) {
++ if (fu->reps > 1 && fu->nextpr) {
+ for (pr = fu->nextpr;; pr = pr->nextpr)
+ if (!pr->nextpr)
+ break;
diff --git a/package/busybox/patches/802-brctl_linux24.patch b/package/busybox/patches/802-brctl_linux24.patch
new file mode 100644
index 000000000..8cc19779a
--- /dev/null
+++ b/package/busybox/patches/802-brctl_linux24.patch
@@ -0,0 +1,74 @@
+--- a/networking/brctl.c
++++ b/networking/brctl.c
+@@ -56,7 +56,7 @@
+
+ /* Maximum number of ports supported per bridge interface. */
+ #ifndef MAX_PORTS
+-# define MAX_PORTS 32
++# define MAX_PORTS 1024
+ #endif
+
+ /* Use internal number parsing and not the "exact" conversion. */
+@@ -193,6 +193,7 @@ int brctl_main(int argc UNUSED_PARAM, ch
+ printf(bi.stp_enabled ? "\tyes" : "\tno");
+
+ /* print interface list */
++ memset(ifidx, 0, sizeof ifidx);
+ arm_ioctl(args, BRCTL_GET_PORT_LIST,
+ (unsigned long) ifidx, MAX_PORTS);
+ xioctl(fd, SIOCDEVPRIVATE, &ifr);
+@@ -221,9 +222,19 @@ int brctl_main(int argc UNUSED_PARAM, ch
+ br = *argv++;
+
+ if (key == ARG_addbr || key == ARG_delbr) { /* addbr or delbr */
+- ioctl_or_perror_and_die(fd,
+- key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR,
+- br, "bridge %s", br);
++ int ret;
++ ret = ioctl(fd,
++ key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR,
++ br);
++ if (ret < 0) {
++ arm_ioctl(args,
++ key == ARG_addbr ? BRCTL_ADD_BRIDGE : BRCTL_DEL_BRIDGE,
++ (unsigned long) br, 0);
++ ret = ioctl(fd, SIOCSIFBR, args);
++ }
++ if (ret < 0) {
++ bb_perror_msg_and_die("bridge %s", br);
++ }
+ goto done;
+ }
+
+@@ -232,14 +243,27 @@ int brctl_main(int argc UNUSED_PARAM, ch
+
+ strncpy_IFNAMSIZ(ifr.ifr_name, br);
+ if (key == ARG_addif || key == ARG_delif) { /* addif or delif */
++ int ret;
++ int if_index;
+ brif = *argv;
+- ifr.ifr_ifindex = if_nametoindex(brif);
+- if (!ifr.ifr_ifindex) {
++ if_index = if_nametoindex(brif);
++ if (!if_index) {
+ bb_perror_msg_and_die("iface %s", brif);
+ }
+- ioctl_or_perror_and_die(fd,
++ ifr.ifr_ifindex = if_index;
++ ret = ioctl(fd,
+ key == ARG_addif ? SIOCBRADDIF : SIOCBRDELIF,
+- &ifr, "bridge %s", br);
++ &ifr);
++ if (ret < 0) {
++ arm_ioctl(args,
++ key == ARG_addif ? BRCTL_ADD_IF : BRCTL_DEL_IF,
++ if_index, 0);
++ ifr.ifr_data = (char *) &args;
++ ret = ioctl(fd, SIOCDEVPRIVATE, &ifr);
++ }
++ if (ret < 0) {
++ bb_perror_msg_and_die("bridge %s", br);
++ }
+ goto done_next_argv;
+ }
+ #if ENABLE_FEATURE_BRCTL_FANCY
diff --git a/package/busybox/patches/803-id_getgrouplist.patch b/package/busybox/patches/803-id_getgrouplist.patch
new file mode 100644
index 000000000..638305ee7
--- /dev/null
+++ b/package/busybox/patches/803-id_getgrouplist.patch
@@ -0,0 +1,49 @@
+This patch disable supplementary groups handling in id with uClibc versions
+prior to v0.9.30, which are lacking the 'getgrouplist' function.
+
+Signed-off-by: Nicolas Thill <nico@openwrt.org>
+
+--- a/coreutils/id.c
++++ b/coreutils/id.c
+@@ -63,10 +63,12 @@
+
+ /* This is a NOEXEC applet. Be very careful! */
+
++#define HAVE_GETGROUPLIST 1
++
+ #if !ENABLE_USE_BB_PWD_GRP
+ #if defined(__UCLIBC_MAJOR__) && (__UCLIBC_MAJOR__ == 0)
+ #if (__UCLIBC_MINOR__ < 9) || (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ < 30)
+-#error "Sorry, you need at least uClibc version 0.9.30 for id applet to build"
++#undef HAVE_GETGROUPLIST
+ #endif
+ #endif
+ #endif
+@@ -128,7 +130,11 @@ static int get_groups(const char *userna
+ /* If the user is a member of more than
+ * *n groups, then -1 is returned. Otherwise >= 0.
+ * (and no defined way of detecting errors?!) */
++#if HAVE_GETGROUPLIST
+ m = getgrouplist(username, rgid, groups, n);
++#else
++ *n = -1;
++#endif
+ /* I guess *n < 0 might indicate error. Anyway,
+ * malloc'ing -1 bytes won't be good, so: */
+ if (*n < 0)
+@@ -210,6 +216,7 @@ int id_main(int argc UNUSED_PARAM, char
+ if (egid != rgid)
+ status |= print_group(egid, " ");
+ }
++#if HAVE_GETGROUPLIST
+ /* We are supplying largish buffer, trying
+ * to not run get_groups() twice. That might be slow
+ * ("user database in remote SQL server" case) */
+@@ -236,6 +243,7 @@ int id_main(int argc UNUSED_PARAM, char
+ }
+ if (ENABLE_FEATURE_CLEAN_UP)
+ free(groups);
++#endif
+ #if ENABLE_SELINUX
+ if (is_selinux_enabled()) {
+ if (getcon(&scontext) == 0)
diff --git a/package/busybox/patches/902-telnetd_intr.patch b/package/busybox/patches/902-telnetd_intr.patch
new file mode 100644
index 000000000..862ece055
--- /dev/null
+++ b/package/busybox/patches/902-telnetd_intr.patch
@@ -0,0 +1,10 @@
+--- a/networking/telnetd.c
++++ b/networking/telnetd.c
+@@ -330,6 +330,7 @@ make_new_session(
+
+ /* Restore default signal handling ASAP */
+ bb_signals((1 << SIGCHLD) + (1 << SIGPIPE), SIG_DFL);
++ signal(SIGINT, SIG_DFL);
+
+ pid = getpid();
+
diff --git a/package/busybox/patches/910-insmod-q-flag.patch b/package/busybox/patches/910-insmod-q-flag.patch
new file mode 100644
index 000000000..6002f20f1
--- /dev/null
+++ b/package/busybox/patches/910-insmod-q-flag.patch
@@ -0,0 +1,33 @@
+--- a/modutils/insmod.c
++++ b/modutils/insmod.c
+@@ -139,7 +139,7 @@ int insmod_main(int argc, char **argv) M
+ int insmod_main(int argc UNUSED_PARAM, char **argv)
+ {
+ char *filename;
+- int rc;
++ int rc, opt;
+
+ /* Compat note:
+ * 2.6 style insmod has no options and required filename
+@@ -149,10 +149,8 @@ int insmod_main(int argc UNUSED_PARAM, c
+ * or in $MODPATH.
+ */
+
+- IF_FEATURE_2_4_MODULES(
+- getopt32(argv, INSMOD_OPTS INSMOD_ARGS);
+- argv += optind - 1;
+- );
++ opt = getopt32(argv, INSMOD_OPTS, NULL, NULL);
++ argv += optind - 1;
+
+ filename = *++argv;
+ if (!filename)
+@@ -163,7 +161,7 @@ int insmod_main(int argc UNUSED_PARAM, c
+ goto done;
+
+ rc = bb_init_module(g_filename, parse_cmdline_module_options(argv, /*quote_spaces:*/ 0));
+- if (rc)
++ if (rc && !(opt & INSMOD_OPT_SILENT))
+ bb_error_msg("can't insert '%s': %s", filename, moderror(rc));
+ free (g_filename);
+
diff --git a/package/busybox/patches/911-date-k-flag.patch b/package/busybox/patches/911-date-k-flag.patch
new file mode 100644
index 000000000..c4f6db4db
--- /dev/null
+++ b/package/busybox/patches/911-date-k-flag.patch
@@ -0,0 +1,83 @@
+--- a/coreutils/date.c
++++ b/coreutils/date.c
+@@ -123,6 +123,7 @@
+ //usage: IF_FEATURE_DATE_ISOFMT(
+ //usage: "\n -D FMT Use FMT for -d TIME conversion"
+ //usage: )
++//usage: "\n -k Set Kernel timezone from localtime and exit"
+ //usage: "\n"
+ //usage: "\nRecognized TIME formats:"
+ //usage: "\n hh:mm[:ss]"
+@@ -135,6 +136,7 @@
+ //usage: "Wed Apr 12 18:52:41 MDT 2000\n"
+
+ #include "libbb.h"
++#include <sys/time.h>
+ #if ENABLE_FEATURE_DATE_NANO
+ # include <sys/syscall.h>
+ #endif
+@@ -145,8 +147,9 @@ enum {
+ OPT_UTC = (1 << 2), /* u */
+ OPT_DATE = (1 << 3), /* d */
+ OPT_REFERENCE = (1 << 4), /* r */
+- OPT_TIMESPEC = (1 << 5) * ENABLE_FEATURE_DATE_ISOFMT, /* I */
+- OPT_HINT = (1 << 6) * ENABLE_FEATURE_DATE_ISOFMT, /* D */
++ OPT_KERNELTZ = (1 << 5), /* k */
++ OPT_TIMESPEC = (1 << 6) * ENABLE_FEATURE_DATE_ISOFMT, /* I */
++ OPT_HINT = (1 << 7) * ENABLE_FEATURE_DATE_ISOFMT, /* D */
+ };
+
+ static void maybe_set_utc(int opt)
+@@ -164,12 +167,15 @@ static const char date_longopts[] ALIGN1
+ /* "universal\0" No_argument "u" */
+ "date\0" Required_argument "d"
+ "reference\0" Required_argument "r"
++ "set-kernel-tz\0" No_argument "k"
+ ;
+ #endif
+
+ int date_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+ int date_main(int argc UNUSED_PARAM, char **argv)
+ {
++ time_t tt;
++ struct timezone tz;
+ struct timespec ts;
+ struct tm tm_time;
+ char buf_fmt_dt2str[64];
+@@ -184,7 +190,7 @@ int date_main(int argc UNUSED_PARAM, cha
+ opt_complementary = "d--s:s--d"
+ IF_FEATURE_DATE_ISOFMT(":R--I:I--R");
+ IF_LONG_OPTS(applet_long_options = date_longopts;)
+- opt = getopt32(argv, "Rs:ud:r:"
++ opt = getopt32(argv, "Rs:ud:r:k"
+ IF_FEATURE_DATE_ISOFMT("I::D:"),
+ &date_str, &date_str, &filename
+ IF_FEATURE_DATE_ISOFMT(, &isofmt_arg, &fmt_str2dt));
+@@ -241,6 +247,27 @@ int date_main(int argc UNUSED_PARAM, cha
+ if (*argv)
+ bb_show_usage();
+
++ /* Setting of kernel timezone was requested */
++ if (opt & OPT_KERNELTZ) {
++ tt = time(NULL);
++ localtime_r(&tt, &tm_time);
++
++ /* workaround warp_clock() on first invocation */
++ memset(&tz, 0, sizeof(tz));
++ settimeofday(NULL, &tz);
++
++ memset(&tz, 0, sizeof(tz));
++ tz.tz_minuteswest = -(tm_time.tm_gmtoff / 60);
++
++ if (settimeofday(NULL, &tz))
++ {
++ bb_perror_msg("can't set kernel time zone");
++ return EXIT_FAILURE;
++ }
++
++ return EXIT_SUCCESS;
++ }
++
+ /* Now we have parsed all the information except the date format
+ * which depends on whether the clock is being set or read */
+
diff --git a/package/busybox/patches/920-portability.patch b/package/busybox/patches/920-portability.patch
new file mode 100644
index 000000000..4e5b9a057
--- /dev/null
+++ b/package/busybox/patches/920-portability.patch
@@ -0,0 +1,13 @@
+--- a/scripts/kconfig/mconf.c
++++ b/scripts/kconfig/mconf.c
+@@ -25,6 +25,10 @@
+ #include <unistd.h>
+ #include <locale.h>
+
++#ifndef SIGWINCH
++#define SIGWINCH 28
++#endif
++
+ #define LKC_DIRECT_LINK
+ #include "lkc.h"
+
diff --git a/package/busybox/patches/950-partial-checksum.patch b/package/busybox/patches/950-partial-checksum.patch
new file mode 100644
index 000000000..e595162c6
--- /dev/null
+++ b/package/busybox/patches/950-partial-checksum.patch
@@ -0,0 +1,87 @@
+diff -ur busybox-1.19.4.orig/networking/udhcp/dhcpc.c busybox-1.19.4/networking/udhcp/dhcpc.c
+--- busybox-1.19.4.orig/networking/udhcp/dhcpc.c 2012-09-06 22:33:53.476998721 +0400
++++ busybox-1.19.4/networking/udhcp/dhcpc.c 2012-09-07 01:09:46.693372304 +0400
+@@ -26,8 +26,8 @@
+ #include "dhcpc.h"
+
+ #include <netinet/if_ether.h>
+-#include <netpacket/packet.h>
+ #include <linux/filter.h>
++#include <linux/if_packet.h>
+
+ /* struct client_config_t client_config is in bb_common_bufsiz1 */
+
+@@ -784,17 +784,41 @@
+ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
+ {
+ int bytes;
++ int nocsum = 0;
+ struct ip_udp_dhcp_packet packet;
+ uint16_t check;
++ unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
++ struct iovec iov = {
++ .iov_base = &packet,
++ .iov_len = sizeof(packet),
++ };
++ struct msghdr msg = {
++ .msg_iov = &iov,
++ .msg_iovlen = 1,
++ .msg_control = cmsgbuf,
++ .msg_controllen = sizeof(cmsgbuf),
++ };
++ struct cmsghdr *cmsg;
+
+ memset(&packet, 0, sizeof(packet));
+- bytes = safe_read(fd, &packet, sizeof(packet));
++ do {
++ bytes = recvmsg(fd, &msg, 0);
++ } while (bytes < 0 && errno == EINTR);
++
+ if (bytes < 0) {
+ log1("Packet read error, ignoring");
+ /* NB: possible down interface, etc. Caller should pause. */
+ return bytes; /* returns -1 */
+ }
+
++ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
++ if (cmsg->cmsg_level == SOL_PACKET &&
++ cmsg->cmsg_type == PACKET_AUXDATA) {
++ struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg);
++ nocsum = aux->tp_status & TP_STATUS_CSUMNOTREADY;
++ }
++ }
++
+ if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp))) {
+ log1("Packet is too short, ignoring");
+ return -2;
+@@ -834,7 +858,7 @@
+ packet.ip.tot_len = packet.udp.len; /* yes, this is needed */
+ check = packet.udp.check;
+ packet.udp.check = 0;
+- if (check && check != udhcp_checksum(&packet, bytes)) {
++ if (!nocsum && check && check != udhcp_checksum(&packet, bytes)) {
+ log1("Packet with bad UDP checksum received, ignoring");
+ return -2;
+ }
+@@ -880,6 +904,7 @@
+ {
+ int fd;
+ struct sockaddr_ll sock;
++ int val;
+
+ /*
+ * Comment:
+@@ -946,6 +971,13 @@
+ log1("Attached filter to raw socket fd %d", fd); // log?
+ }
+
++ val = 1;
++ if (setsockopt(fd, SOL_PACKET, PACKET_AUXDATA, &val,
++ sizeof(val)) < 0) {
++ if (errno != ENOPROTOOPT)
++ log1("Failed to set auxiliary packet data for socket fd %d", fd);
++ }
++
+ log1("Created raw socket");
+
+ return fd;
diff --git a/package/button-hotplug/Makefile b/package/button-hotplug/Makefile
new file mode 100644
index 000000000..35ea6d411
--- /dev/null
+++ b/package/button-hotplug/Makefile
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2008-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=button-hotplug
+PKG_RELEASE:=3
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/button-hotplug
+ SUBMENU:=Other modules
+ TITLE:=Button Hotplug driver
+ FILES:=$(PKG_BUILD_DIR)/button-hotplug.ko
+ AUTOLOAD:=$(call AutoLoad,30,button-hotplug)
+ KCONFIG:=
+endef
+
+define KernelPackage/button-hotplug/description
+ Kernel module to generate button hotplug events
+endef
+
+EXTRA_KCONFIG:= \
+ CONFIG_BUTTON_HOTPLUG=m
+
+EXTRA_CFLAGS:= \
+ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \
+ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \
+
+MAKE_OPTS:= \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ SUBDIRS="$(PKG_BUILD_DIR)" \
+ EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
+ $(EXTRA_KCONFIG)
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ $(MAKE) -C "$(LINUX_DIR)" \
+ $(MAKE_OPTS) \
+ modules
+endef
+
+$(eval $(call KernelPackage,button-hotplug))
diff --git a/package/button-hotplug/src/Kconfig b/package/button-hotplug/src/Kconfig
new file mode 100644
index 000000000..aa292e9c1
--- /dev/null
+++ b/package/button-hotplug/src/Kconfig
@@ -0,0 +1,2 @@
+config BUTTON_HOTPLUG
+ tristate "Button Hotplug driver"
diff --git a/package/button-hotplug/src/Makefile b/package/button-hotplug/src/Makefile
new file mode 100644
index 000000000..230d604f8
--- /dev/null
+++ b/package/button-hotplug/src/Makefile
@@ -0,0 +1 @@
+obj-${CONFIG_BUTTON_HOTPLUG} += button-hotplug.o \ No newline at end of file
diff --git a/package/button-hotplug/src/button-hotplug.c b/package/button-hotplug/src/button-hotplug.c
new file mode 100644
index 000000000..4a8c4a88e
--- /dev/null
+++ b/package/button-hotplug/src/button-hotplug.c
@@ -0,0 +1,349 @@
+/*
+ * Button Hotplug driver
+ *
+ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * Based on the diag.c - GPIO interface driver for Broadcom boards
+ * Copyright (C) 2006 Mike Baker <mbm@openwrt.org>,
+ * Copyright (C) 2006-2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2008 Andy Boyett <agb@openwrt.org>
+ *
+ * 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/module.h>
+#include <linux/version.h>
+#include <linux/kmod.h>
+#include <linux/input.h>
+
+#include <linux/workqueue.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/kobject.h>
+
+#define DRV_NAME "button-hotplug"
+#define DRV_VERSION "0.4.1"
+#define DRV_DESC "Button Hotplug driver"
+
+#define BH_SKB_SIZE 2048
+
+#define PFX DRV_NAME ": "
+
+#undef BH_DEBUG
+
+#ifdef BH_DEBUG
+#define BH_DBG(fmt, args...) printk(KERN_DEBUG "%s: " fmt, DRV_NAME, ##args )
+#else
+#define BH_DBG(fmt, args...) do {} while (0)
+#endif
+
+#define BH_ERR(fmt, args...) printk(KERN_ERR "%s: " fmt, DRV_NAME, ##args )
+
+#ifndef BIT_MASK
+#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
+#endif
+
+struct bh_priv {
+ unsigned long *seen;
+ struct input_handle handle;
+};
+
+struct bh_event {
+ const char *name;
+ char *action;
+ unsigned long seen;
+
+ struct sk_buff *skb;
+ struct work_struct work;
+};
+
+struct bh_map {
+ unsigned int code;
+ const char *name;
+};
+
+extern u64 uevent_next_seqnum(void);
+
+#define BH_MAP(_code, _name) \
+ { \
+ .code = (_code), \
+ .name = (_name), \
+ }
+
+static struct bh_map button_map[] = {
+ BH_MAP(BTN_0, "BTN_0"),
+ BH_MAP(BTN_1, "BTN_1"),
+ BH_MAP(BTN_2, "BTN_2"),
+ BH_MAP(BTN_3, "BTN_3"),
+ BH_MAP(BTN_4, "BTN_4"),
+ BH_MAP(BTN_5, "BTN_5"),
+ BH_MAP(BTN_6, "BTN_6"),
+ BH_MAP(BTN_7, "BTN_7"),
+ BH_MAP(BTN_8, "BTN_8"),
+ BH_MAP(BTN_9, "BTN_9"),
+ BH_MAP(KEY_RESTART, "reset"),
+#ifdef KEY_WPS_BUTTON
+ BH_MAP(KEY_WPS_BUTTON, "wps"),
+#endif /* KEY_WPS_BUTTON */
+};
+
+/* -------------------------------------------------------------------------*/
+
+static int bh_event_add_var(struct bh_event *event, int argv,
+ const char *format, ...)
+{
+ static char buf[128];
+ char *s;
+ va_list args;
+ int len;
+
+ if (argv)
+ return 0;
+
+ va_start(args, format);
+ len = vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+
+ if (len >= sizeof(buf)) {
+ BH_ERR("buffer size too small\n");
+ WARN_ON(1);
+ return -ENOMEM;
+ }
+
+ s = skb_put(event->skb, len + 1);
+ strcpy(s, buf);
+
+ BH_DBG("added variable '%s'\n", s);
+
+ return 0;
+}
+
+static int button_hotplug_fill_event(struct bh_event *event)
+{
+ int ret;
+
+ ret = bh_event_add_var(event, 0, "HOME=%s", "/");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "PATH=%s",
+ "/sbin:/bin:/usr/sbin:/usr/bin");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SUBSYSTEM=%s", "button");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "ACTION=%s", event->action);
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "BUTTON=%s", event->name);
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SEEN=%ld", event->seen);
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SEQNUM=%llu", uevent_next_seqnum());
+
+ return ret;
+}
+
+static void button_hotplug_work(struct work_struct *work)
+{
+ struct bh_event *event = container_of(work, struct bh_event, work);
+ int ret = 0;
+
+ event->skb = alloc_skb(BH_SKB_SIZE, GFP_KERNEL);
+ if (!event->skb)
+ goto out_free_event;
+
+ ret = bh_event_add_var(event, 0, "%s@", event->action);
+ if (ret)
+ goto out_free_skb;
+
+ ret = button_hotplug_fill_event(event);
+ if (ret)
+ goto out_free_skb;
+
+ NETLINK_CB(event->skb).dst_group = 1;
+ broadcast_uevent(event->skb, 0, 1, GFP_KERNEL);
+
+ out_free_skb:
+ if (ret) {
+ BH_ERR("work error %d\n", ret);
+ kfree_skb(event->skb);
+ }
+ out_free_event:
+ kfree(event);
+}
+
+static int button_hotplug_create_event(const char *name, unsigned long seen,
+ int pressed)
+{
+ struct bh_event *event;
+
+ BH_DBG("create event, name=%s, seen=%lu, pressed=%d\n",
+ name, seen, pressed);
+
+ event = kzalloc(sizeof(*event), GFP_KERNEL);
+ if (!event)
+ return -ENOMEM;
+
+ event->name = name;
+ event->seen = seen;
+ event->action = pressed ? "pressed" : "released";
+
+ INIT_WORK(&event->work, (void *)(void *)button_hotplug_work);
+ schedule_work(&event->work);
+
+ return 0;
+}
+
+/* -------------------------------------------------------------------------*/
+
+#ifdef CONFIG_HOTPLUG
+static int button_get_index(unsigned int code)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(button_map); i++)
+ if (button_map[i].code == code)
+ return i;
+
+ return -1;
+}
+static void button_hotplug_event(struct input_handle *handle,
+ unsigned int type, unsigned int code, int value)
+{
+ struct bh_priv *priv = handle->private;
+ unsigned long seen = jiffies;
+ int btn;
+
+ BH_DBG("event type=%u, code=%u, value=%d\n", type, code, value);
+
+ if (type != EV_KEY)
+ return;
+
+ btn = button_get_index(code);
+ if (btn < 0)
+ return;
+
+ button_hotplug_create_event(button_map[btn].name,
+ (seen - priv->seen[btn]) / HZ, value);
+ priv->seen[btn] = seen;
+}
+#else
+static void button_hotplug_event(struct input_handle *handle,
+ unsigned int type, unsigned int code, int value)
+{
+}
+#endif /* CONFIG_HOTPLUG */
+
+static int button_hotplug_connect(struct input_handler *handler,
+ struct input_dev *dev, const struct input_device_id *id)
+{
+ struct bh_priv *priv;
+ int ret;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(button_map); i++)
+ if (test_bit(button_map[i].code, dev->keybit))
+ break;
+
+ if (i == ARRAY_SIZE(button_map))
+ return -ENODEV;
+
+ priv = kzalloc(sizeof(*priv) +
+ (sizeof(unsigned long) * ARRAY_SIZE(button_map)),
+ GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->seen = (unsigned long *) &priv[1];
+ priv->handle.private = priv;
+ priv->handle.dev = dev;
+ priv->handle.handler = handler;
+ priv->handle.name = DRV_NAME;
+
+ ret = input_register_handle(&priv->handle);
+ if (ret)
+ goto err_free_priv;
+
+ ret = input_open_device(&priv->handle);
+ if (ret)
+ goto err_unregister_handle;
+
+ BH_DBG("connected to %s\n", dev->name);
+
+ return 0;
+
+ err_unregister_handle:
+ input_unregister_handle(&priv->handle);
+
+ err_free_priv:
+ kfree(priv);
+ return ret;
+}
+
+static void button_hotplug_disconnect(struct input_handle *handle)
+{
+ struct bh_priv *priv = handle->private;
+
+ input_close_device(handle);
+ input_unregister_handle(handle);
+
+ kfree(priv);
+}
+
+static const struct input_device_id button_hotplug_ids[] = {
+ {
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
+ .evbit = { BIT_MASK(EV_KEY) },
+ },
+ {
+ /* Terminating entry */
+ },
+};
+
+MODULE_DEVICE_TABLE(input, button_hotplug_ids);
+
+static struct input_handler button_hotplug_handler = {
+ .event = button_hotplug_event,
+ .connect = button_hotplug_connect,
+ .disconnect = button_hotplug_disconnect,
+ .name = DRV_NAME,
+ .id_table = button_hotplug_ids,
+};
+
+/* -------------------------------------------------------------------------*/
+
+static int __init button_hotplug_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n");
+ ret = input_register_handler(&button_hotplug_handler);
+ if (ret)
+ BH_ERR("unable to register input handler\n");
+
+ return ret;
+}
+module_init(button_hotplug_init);
+
+static void __exit button_hotplug_exit(void)
+{
+ input_unregister_handler(&button_hotplug_handler);
+}
+module_exit(button_hotplug_exit);
+
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_LICENSE("GPL v2");
+
diff --git a/package/comgt/Makefile b/package/comgt/Makefile
new file mode 100644
index 000000000..6cb802c60
--- /dev/null
+++ b/package/comgt/Makefile
@@ -0,0 +1,65 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=comgt
+PKG_VERSION:=0.32
+PKG_RELEASE:=21
+
+PKG_SOURCE:=$(PKG_NAME).$(PKG_VERSION).tgz
+PKG_SOURCE_URL:=@SF/comgt
+PKG_MD5SUM:=db2452680c3d953631299e331daf49ef
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME).$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/comgt
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Option/Vodafone 3G/GPRS control tool
+ DEPENDS:=+chat
+ URL:=http://www.pharscape.org/comgt.html
+endef
+
+define Package/comgt/description
+ comgt is a scripting language interpreter useful for establishing
+ communications on serial lines and through PCMCIA modems as well as GPRS
+ and 3G datacards.
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ LDFLAGS="" \
+ comgt
+endef
+
+define Package/comgt/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/comgt $(1)/usr/bin/
+ ln -s comgt $(1)/usr/bin/gcom
+ $(INSTALL_DIR) $(1)/etc/chatscripts
+ $(INSTALL_DATA) ./files/3g.chat $(1)/etc/chatscripts/3g.chat
+ $(INSTALL_DATA) ./files/evdo.chat $(1)/etc/chatscripts/evdo.chat
+ $(INSTALL_DIR) $(1)/etc/gcom
+ $(INSTALL_DATA) ./files/setpin.gcom $(1)/etc/gcom/setpin.gcom
+ $(INSTALL_DATA) ./files/setmode.gcom $(1)/etc/gcom/setmode.gcom
+ $(INSTALL_DATA) ./files/getcardinfo.gcom $(1)/etc/gcom/getcardinfo.gcom
+ $(INSTALL_DATA) ./files/getstrength.gcom $(1)/etc/gcom/getstrength.gcom
+ $(INSTALL_DATA) ./files/getcarrier.gcom $(1)/etc/gcom/getcarrier.gcom
+ $(INSTALL_DATA) ./files/getcnum.gcom $(1)/etc/gcom/getcnum.gcom
+ $(INSTALL_DATA) ./files/getimsi.gcom $(1)/etc/gcom/getimsi.gcom
+ $(INSTALL_DIR) $(1)/etc/hotplug.d/tty
+ $(INSTALL_DATA) ./files/3g.usb $(1)/etc/hotplug.d/tty/30-3g
+ $(INSTALL_DIR) $(1)/lib/netifd/proto
+ $(INSTALL_BIN) ./files/3g.sh $(1)/lib/netifd/proto/3g.sh
+endef
+
+$(eval $(call BuildPackage,comgt))
diff --git a/package/comgt/files/3g.chat b/package/comgt/files/3g.chat
new file mode 100644
index 000000000..a1fa2a02d
--- /dev/null
+++ b/package/comgt/files/3g.chat
@@ -0,0 +1,12 @@
+ABORT BUSY
+ABORT 'NO CARRIER'
+ABORT ERROR
+REPORT CONNECT
+TIMEOUT 10
+"" "AT&F"
+OK "ATE1"
+OK 'AT+CGDCONT=1,"IP","$USE_APN"'
+SAY "Calling UMTS/GPRS"
+TIMEOUT 30
+OK "ATD*99***1#"
+CONNECT ' '
diff --git a/package/comgt/files/3g.sh b/package/comgt/files/3g.sh
new file mode 100644
index 000000000..2ed74b4c0
--- /dev/null
+++ b/package/comgt/files/3g.sh
@@ -0,0 +1,97 @@
+#!/bin/sh
+INCLUDE_ONLY=1
+
+. ../netifd-proto.sh
+. ./ppp.sh
+init_proto "$@"
+
+proto_3g_init_config() {
+ no_device=1
+ available=1
+ ppp_generic_init_config
+ proto_config_add_string "device"
+ proto_config_add_string "apn"
+ proto_config_add_string "service"
+ proto_config_add_string "pincode"
+}
+
+proto_3g_setup() {
+ local interface="$1"
+ local chat
+
+ json_get_var device device
+ json_get_var apn apn
+ json_get_var service service
+ json_get_var pincode pincode
+
+ [ -e "$device" ] || {
+ proto_set_available "$interface" 0
+ return 1
+ }
+
+ case "$service" in
+ cdma|evdo)
+ chat="/etc/chatscripts/evdo.chat"
+ ;;
+ *)
+ chat="/etc/chatscripts/3g.chat"
+ cardinfo=$(gcom -d "$device" -s /etc/gcom/getcardinfo.gcom)
+ if echo "$cardinfo" | grep -q Novatel; then
+ case "$service" in
+ umts_only) CODE=2;;
+ gprs_only) CODE=1;;
+ *) CODE=0;;
+ esac
+ export MODE="AT\$NWRAT=${CODE},2"
+ elif echo "$cardinfo" | grep -q Option; then
+ case "$service" in
+ umts_only) CODE=1;;
+ gprs_only) CODE=0;;
+ *) CODE=3;;
+ esac
+ export MODE="AT_OPSYS=${CODE}"
+ elif echo "$cardinfo" | grep -q "Sierra Wireless"; then
+ SIERRA=1
+ elif echo "$cardinfo" | grep -qi huawei; then
+ case "$service" in
+ umts_only) CODE="14,2";;
+ gprs_only) CODE="13,1";;
+ *) CODE="2,2";;
+ esac
+ export MODE="AT^SYSCFG=${CODE},3FFFFFFF,2,4"
+ fi
+
+ if [ -n "$pincode" ]; then
+ PINCODE="$pincode" gcom -d "$device" -s /etc/gcom/setpin.gcom || {
+ proto_notify_error "$interface" PIN_FAILED
+ proto_block_restart "$interface"
+ return 1
+ }
+ fi
+ [ -n "$MODE" ] && gcom -d "$device" -s /etc/gcom/setmode.gcom
+
+ # wait for carrier to avoid firmware stability bugs
+ [ -n "$SIERRA" ] && {
+ gcom -d "$device" -s /etc/gcom/getcarrier.gcom || return 1
+ }
+ ;;
+ esac
+
+ connect="${apn:+USE_APN=$apn }/usr/sbin/chat -t5 -v -E -f $chat"
+ ppp_generic_setup "$interface" \
+ noaccomp \
+ nopcomp \
+ novj \
+ nobsdcomp \
+ noauth \
+ lock \
+ crtscts \
+ 115200 "$device"
+ return 0
+}
+
+proto_3g_teardown() {
+ proto_kill_command "$interface"
+}
+
+add_protocol 3g
diff --git a/package/comgt/files/3g.usb b/package/comgt/files/3g.usb
new file mode 100644
index 000000000..fd6837e65
--- /dev/null
+++ b/package/comgt/files/3g.usb
@@ -0,0 +1,33 @@
+#!/bin/sh
+. /lib/functions.sh
+. /lib/netifd/netifd-proto.sh
+
+find_3g_iface() {
+ local cfg="$1"
+ local tty="$2"
+
+ local proto
+ config_get proto "$cfg" proto
+ [ "$proto" = 3g ] || return 0
+
+ # bypass state vars here because 00-netstate could clobber .device
+ local dev=$(uci_get network "$cfg" device)
+
+ if [ "${dev##*/}" = "${tty##*/}" ]; then
+ if [ "$ACTION" = add ]; then
+ available=1
+ else
+ available=0
+ fi
+ proto_set_available "$cfg" $available
+ fi
+}
+
+case "$DEVICENAME" in
+ tty*)
+ [ -e "/dev/$DEVICENAME" ] || [ "$ACTION" = remove ] || exit 0
+ config_load network
+ config_foreach find_3g_iface interface "/dev/$DEVICENAME"
+ ;;
+esac
+
diff --git a/package/comgt/files/evdo.chat b/package/comgt/files/evdo.chat
new file mode 100644
index 000000000..de49e41a1
--- /dev/null
+++ b/package/comgt/files/evdo.chat
@@ -0,0 +1,17 @@
+# This is a simple chat script based off of the one provided by Sierra Wireless
+# for CDMA connections. It should work for both Sprint and Verizon networks.
+
+ABORT BUSY
+ABORT 'NO CARRIER'
+ABORT ERROR
+ABORT 'NO DIAL TONE'
+ABORT 'NO ANSWER'
+ABORT DELAYED
+REPORT CONNECT
+TIMEOUT 10
+'' AT
+OK ATZ
+SAY 'Calling CDMA/EVDO'
+TIMEOUT 30
+OK ATDT#777
+CONNECT ''
diff --git a/package/comgt/files/getcardinfo.gcom b/package/comgt/files/getcardinfo.gcom
new file mode 100644
index 000000000..5c69a6460
--- /dev/null
+++ b/package/comgt/files/getcardinfo.gcom
@@ -0,0 +1,14 @@
+opengt
+ set com 115200n81
+ set comecho off
+ set senddelay 0.02
+ waitquiet 0.2 0.2
+ flash 0.1
+
+:start
+ send "ATI^m"
+ get 1 "" $s
+ print $s
+
+:continue
+ exit 0
diff --git a/package/comgt/files/getcarrier.gcom b/package/comgt/files/getcarrier.gcom
new file mode 100644
index 000000000..1e0216d46
--- /dev/null
+++ b/package/comgt/files/getcarrier.gcom
@@ -0,0 +1,20 @@
+opengt
+ set senddelay 0.05
+ waitquiet 1 0.2
+ let c=1
+ :loop
+ inc c
+ send "AT+CGATT?^m"
+ waitfor 5 "+CGATT: 1","+CGATT: 0"
+ print "\n."
+ if % = -1 goto error
+ if c > 10 goto toolong
+ if % = 0 goto out
+ sleep 2
+ if % = 1 goto loop
+ :toolong
+ exit 1
+ :error
+ exit 0
+ :out
+ exit 0
diff --git a/package/comgt/files/getcnum.gcom b/package/comgt/files/getcnum.gcom
new file mode 100644
index 000000000..450cf8c41
--- /dev/null
+++ b/package/comgt/files/getcnum.gcom
@@ -0,0 +1,20 @@
+opengt
+ set com 115200n81
+ set comecho off
+ set senddelay 0.02
+ waitquiet 0.2 0.2
+ flash 0.1
+
+:start
+ send "AT+CNUM^m"
+ get 1 "^m" $n
+ get 1 ":" $n
+ get 1 "\"" $n
+ get 1 "\"" $n
+ get 1 "\"" $n
+ get 1 "\"" $n
+ let n = len($n)
+ if n<1 goto continue
+ print $n
+:continue
+ exit 0
diff --git a/package/comgt/files/getimsi.gcom b/package/comgt/files/getimsi.gcom
new file mode 100644
index 000000000..04854561b
--- /dev/null
+++ b/package/comgt/files/getimsi.gcom
@@ -0,0 +1,17 @@
+opengt
+ set com 115200n81
+ set comecho off
+ set senddelay 0.02
+ waitquiet 0.2 0.2
+ flash 0.1
+
+:start
+ send "AT+CIMI^m"
+ get 1 "^m" $s
+ get 1 "^m" $s
+ let x = len($s)
+ if x<2 goto continue
+ let $s = $right($s, x-1)
+ print $s
+:continue
+ exit 0
diff --git a/package/comgt/files/getstrength.gcom b/package/comgt/files/getstrength.gcom
new file mode 100644
index 000000000..288628597
--- /dev/null
+++ b/package/comgt/files/getstrength.gcom
@@ -0,0 +1,14 @@
+opengt
+ set com 115200n81
+ set comecho off
+ set senddelay 0.02
+ waitquiet 0.2 0.2
+ flash 0.1
+
+:start
+ send "AT+CSQ^m"
+ get 1 "" $s
+ print $s
+
+:continue
+ exit 0
diff --git a/package/comgt/files/setmode.gcom b/package/comgt/files/setmode.gcom
new file mode 100644
index 000000000..4ce0b5fa7
--- /dev/null
+++ b/package/comgt/files/setmode.gcom
@@ -0,0 +1,26 @@
+# set wwan mode from environment
+opengt
+ set com 115200n81
+ set senddelay 0.02
+ waitquiet 1 0.2
+ flash 0.1
+
+:start
+ print "Trying to set mode\n"
+ send $env("MODE")
+ send "^m"
+
+ waitfor 15 "OK","ERR","ERROR"
+ if % = 0 goto continue
+ if % = 1 goto modeerror
+ if % = 2 goto modeerror
+
+ print "Timeout setting WWAN mode!\n"
+ exit 1
+
+:modeerror
+ print "Error setting WWAN mode!\n"
+ exit 1
+
+:continue
+ exit 0
diff --git a/package/comgt/files/setpin.gcom b/package/comgt/files/setpin.gcom
new file mode 100644
index 000000000..66350fe20
--- /dev/null
+++ b/package/comgt/files/setpin.gcom
@@ -0,0 +1,55 @@
+# set pin code from evnironment "$PINCODE"
+opengt
+ set com 115200n81
+ set senddelay 0.05
+ waitquiet 3 0.5
+ flash 0.1
+
+ let c=0
+:start
+ send "AT+CPIN?^m"
+ waitfor 15 "SIM PUK","SIM PIN","READY","ERROR","ERR"
+ if % = -1 goto timeout
+ if % = 0 goto ready
+ if % = 1 goto setpin
+ if % = 2 goto ready
+ if % = 3 goto checkrepeat
+ if % = 4 goto checkrepeat
+
+:checkrepeat
+ inc c
+ if c>3 goto pinerror
+ waitquiet 12 0.5
+ goto start
+
+:timeout
+ print "timeout checking for PIN."
+ exit 1
+
+:ready
+ print "SIM ready\n"
+ goto continue
+ exit 0
+
+:setpin
+ # check if output was "SIM PIN2", that's ok.
+ waitfor 1 "2"
+ if % = 0 goto ready
+
+ print "Trying to set PIN\n"
+ send "AT+CPIN=\""
+ send $env("PINCODE")
+ send "\"^m"
+
+ waitfor 20 "OK","ERR"
+ if % = -1 goto pinerror
+ if % = 0 goto continue
+ if % = 1 goto pinerror
+
+:pinerror
+ print "Error setting PIN, check card manually\n"
+ exit 1
+
+:continue
+ print "PIN set successfully\n"
+ exit 0
diff --git a/package/comgt/patches/001-compile_fix.patch b/package/comgt/patches/001-compile_fix.patch
new file mode 100644
index 000000000..15de850b7
--- /dev/null
+++ b/package/comgt/patches/001-compile_fix.patch
@@ -0,0 +1,23 @@
+--- a/Makefile
++++ b/Makefile
+@@ -32,6 +32,7 @@ SCRIPTPATH = /etc/comgt/
+ SCRIPTSRC = ./scripts/
+ BIN = $(CPROG)
+ MANP = comgt.1 sigmon.1
++CC = cc
+
+ CFLAGS = -c
+ LDFLAGS =
+@@ -70,10 +71,5 @@ clean:
+ -rm *~
+ -rm $(SCRIPTSRC)*~
+
+-
+-comgt: comgt.o
+- cc comgt.o $(LDFLAGS) -o comgt
+-
+-comgt.o: comgt.c comgt.h
+- cc comgt.c $(CFLAGS)
+-
++comgt: comgt.c comgt.h
++ $(CC) $(CFLAGS) -o comgt $< $(LDFLAGS)
diff --git a/package/compcache/Config.in b/package/compcache/Config.in
new file mode 100644
index 000000000..b5f75d00d
--- /dev/null
+++ b/package/compcache/Config.in
@@ -0,0 +1,29 @@
+menu "Configuration"
+ depends on PACKAGE_compcache
+
+config COMPCACHE_ENABLE
+ bool "enabled on boot"
+ default n
+ help
+ Enables compressed ram swap devices.
+
+config COMPCACHE_RAM_REPORTED
+ string "swap space reported to kernel in kb"
+ default "2048"
+ help
+ This is the amount of memory that will be reported
+ to the kernel as swap. The real ram in use will differ,
+ because of lzo compression.
+ Example:
+ 16 MB = 2048 KB
+ 32 MB = 4098 KB
+
+config COMPCACHE_BACKUP_DEV
+ string "Backup device for compcache"
+ default ""
+ help
+ Compcache will use this as a backup device for swap.
+ Example:
+ /dev/sda5
+
+endmenu
diff --git a/package/compcache/Makefile b/package/compcache/Makefile
new file mode 100644
index 000000000..5106293e8
--- /dev/null
+++ b/package/compcache/Makefile
@@ -0,0 +1,75 @@
+#
+# Copyright (C) 2009-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=compcache
+PKG_VERSION:=0.6.2
+PKG_RELEASE:=2
+PKG_SOURCE_URL:=http://compcache.googlecode.com/files/
+PKG_MD5SUM:=27aec78dc50e34fb800c74e879057743
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/ramzswap
+ SUBMENU:=Other modules
+ DEPENDS:=@BUSYBOX_CONFIG_SWAPONOFF
+ TITLE:=Driver for compressed ram swap device
+ VERSION:=$(LINUX_VERSION)-$(BOARD)-$(LINUX_RELEASE)+$(PKG_RELEASE)
+ FILES:=$(PKG_BUILD_DIR)/ramzswap.ko \
+ $(PKG_BUILD_DIR)/sub-projects/compression/lzo-kmod/lzo1x.ko
+ URL:=http://code.google.com/p/compcache/
+endef
+
+define Package/compcache
+ SECTION:=util
+ CATEGORY:=Utilities
+ DEPENDS:=+kmod-ramzswap
+ TITLE:=Compressed ram swap device
+ URL:=http://code.google.com/p/compcache/
+ MENU:=1
+endef
+
+include $(INCLUDE_DIR)/kernel-defaults.mk
+
+LZO = sub-projects/compression/lzo-kmod
+RZSC = sub-projects/rzscontrol
+
+BUILDFLAGS:=-DCONFIG_RAMZSWAP_STATS \
+ -I$(PKG_BUILD_DIR)/$(LZO) \
+ -Wall
+
+RZSCFLAGS:=-I$(PKG_BUILD_DIR)/$(RZSC)/../include \
+ -I$(PKG_BUILD_DIR)/$(RZSC)/../..
+
+define Build/Compile
+ $(MAKE) $(KERNEL_MAKEOPTS) EXTRA_CFLAGS="$(BUILDFLAGS)" M="$(PKG_BUILD_DIR)" modules
+ $(TARGET_CC) $(TARGET_CFLAGS) $(RZSCFLAGS) $(PKG_BUILD_DIR)/$(RZSC)/rzscontrol.c -o $(PKG_BUILD_DIR)/rzscontrol
+endef
+
+define Package/compcache/install
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/compcache.config $(1)/etc/config/compcache
+ $(SED) 's,%ENABLED%,$(if $(CONFIG_COMPCACHE_ENABLE),1,0),g' \
+ -e 's,%RAM_REPORTED%,$(call qstrip,$(CONFIG_COMPCACHE_RAM_REPORTED)),g' \
+ -e 's,%BACKUP_DEV%,$(call qstrip,$(CONFIG_COMPCACHE_BACKUP_DEV)),g' \
+ $(1)/etc/config/compcache
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/compcache.init $(1)/etc/init.d/compcache
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/rzscontrol $(1)/sbin/rzscontrol
+endef
+
+define Package/compcache/config
+ source "$(SOURCE)/Config.in"
+endef
+
+$(eval $(call BuildPackage,compcache))
+$(eval $(call KernelPackage,ramzswap))
diff --git a/package/compcache/files/compcache.config b/package/compcache/files/compcache.config
new file mode 100644
index 000000000..3faab3e14
--- /dev/null
+++ b/package/compcache/files/compcache.config
@@ -0,0 +1,4 @@
+config compcache
+ option 'enabled' '%ENABLED%'
+ option 'size_kbytes' '%RAM_REPORTED%'
+ option 'backup_dev' '%BACKUP_DEV%'
diff --git a/package/compcache/files/compcache.init b/package/compcache/files/compcache.init
new file mode 100644
index 000000000..5939d9f61
--- /dev/null
+++ b/package/compcache/files/compcache.init
@@ -0,0 +1,48 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2008 OpenWrt.org
+START=14
+
+load_modules() {
+ local section="$1"
+ config_get "size_kbytes" "$section" "size_kbytes"
+ config_get "backup_dev" "$section" "backup_dev"
+ #CC_PARAM_STR="memlimit_kb=$1 backing_dev=$BACKING_DEV"
+ config_get_bool "enabled" "$section" "enabled" '1'
+ if [ "$enabled" -gt 0 ]; then
+ if [ "`cat /proc/swaps | grep 'ramzswap0'`" != "" ]; then
+ echo "compcache already loaded"
+ else
+ if [ "$backup_dev" != "" ]; then
+ params_set="memlimit_kb=$size_kbytes backing_swap=$backup_dev"
+ else
+ params_set="disksize_kb=$size_kbytes"
+ fi
+ if [ "`lsmod | grep 'ramzswap'`" == "" ]; then
+ insmod lzo1x
+ insmod ramzswap $params_set
+ sleep 2
+ swapon /dev/ramzswap0
+ fi
+ fi
+ fi
+}
+
+remove_modules() {
+ local section="$1"
+ config_get_bool "enabled" "$section" "enabled" '1'
+ if [ "$enabled" -gt 0 ]; then
+ [ "`cat /proc/swaps | grep 'ramzswap0'`" != "" ] && swapoff /dev/ramzswap0
+ [ "`lsmod | grep 'ramzswap'`" != "" ] && rmmod ramzswap &> /dev/null
+ [ "`lsmod | grep 'lzo1x'`" != "" ] && rmmod lzo1x &> /dev/null
+ fi
+}
+
+start() {
+ config_load "compcache"
+ config_foreach load_modules "compcache"
+}
+
+stop() {
+ config_load "compcache"
+ config_foreach remove_modules "compcache"
+}
diff --git a/package/compcache/patches/000-provide_lzo_kmod.patch b/package/compcache/patches/000-provide_lzo_kmod.patch
new file mode 100644
index 000000000..1dab08507
--- /dev/null
+++ b/package/compcache/patches/000-provide_lzo_kmod.patch
@@ -0,0 +1,647 @@
+--- a/Makefile
++++ b/Makefile
+@@ -1,14 +1,17 @@
+ KERNEL_BUILD_PATH ?= "/lib/modules/$(shell uname -r)/build"
+
+ XVM = sub-projects/allocators/xvmalloc-kmod
++LZO = sub-projects/compression/lzo-kmod
+ EXTRA_CFLAGS := -DCONFIG_RAMZSWAP_STATS \
+ -Wall
+
+-obj-m += ramzswap.o
++obj-m += ramzswap.o $(LZO)/lzo1x.o
+ ramzswap-objs := ramzswap_drv.o $(XVM)/xvmalloc.o
++
+
+ all:
+ make -C $(KERNEL_BUILD_PATH) M=$(PWD) modules
++ make -C $(KERNEL_BUILD_PATH) M=$(PWD)/$(LZO) modules
+ make -C sub-projects/rzscontrol
+
+ doc:
+@@ -16,5 +19,6 @@ doc:
+
+ clean:
+ make -C $(KERNEL_BUILD_PATH) M=$(PWD) clean
++ make -C $(KERNEL_BUILD_PATH) M=$(PWD)/$(LZO) clean
+ make -C sub-projects/rzscontrol clean
+ @rm -rf *.ko
+--- a/ramzswap_drv.c
++++ b/ramzswap_drv.c
+@@ -23,13 +23,13 @@
+ #include <linux/device.h>
+ #include <linux/genhd.h>
+ #include <linux/highmem.h>
+-#include <linux/lzo.h>
+ #include <linux/string.h>
+ #include <linux/swap.h>
+ #include <linux/swapops.h>
+ #include <linux/vmalloc.h>
+ #include <linux/version.h>
+
++#include "lzo.h"
+ #include "compat.h"
+ #include "ramzswap_drv.h"
+
+--- /dev/null
++++ b/sub-projects/compression/lzo-kmod/lzo1x.c
+@@ -0,0 +1,7 @@
++#include <linux/module.h>
++
++#include "lzo1x_compress.c"
++#include "lzo1x_decompress.c"
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("LZO1X Lib");
+--- /dev/null
++++ b/sub-projects/compression/lzo-kmod/lzo1x_compress.c
+@@ -0,0 +1,227 @@
++/*
++ * LZO1X Compressor from MiniLZO
++ *
++ * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
++ *
++ * The full LZO package can be found at:
++ * http://www.oberhumer.com/opensource/lzo/
++ *
++ * Changed for kernel use by:
++ * Nitin Gupta <nitingupta910@gmail.com>
++ * Richard Purdie <rpurdie@openedhand.com>
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <asm/unaligned.h>
++
++#include "lzodefs.h"
++#include "lzo.h"
++
++static noinline size_t
++_lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
++ unsigned char *out, size_t *out_len, void *wrkmem)
++{
++ const unsigned char * const in_end = in + in_len;
++ const unsigned char * const ip_end = in + in_len - M2_MAX_LEN - 5;
++ const unsigned char ** const dict = wrkmem;
++ const unsigned char *ip = in, *ii = ip;
++ const unsigned char *end, *m, *m_pos;
++ size_t m_off, m_len, dindex;
++ unsigned char *op = out;
++
++ ip += 4;
++
++ for (;;) {
++ dindex = ((size_t)(0x21 * DX3(ip, 5, 5, 6)) >> 5) & D_MASK;
++ m_pos = dict[dindex];
++
++ if (m_pos < in)
++ goto literal;
++
++ if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET))
++ goto literal;
++
++ m_off = ip - m_pos;
++ if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
++ goto try_match;
++
++ dindex = (dindex & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f);
++ m_pos = dict[dindex];
++
++ if (m_pos < in)
++ goto literal;
++
++ if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET))
++ goto literal;
++
++ m_off = ip - m_pos;
++ if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
++ goto try_match;
++
++ goto literal;
++
++try_match:
++ if (get_unaligned((const unsigned short *)m_pos)
++ == get_unaligned((const unsigned short *)ip)) {
++ if (likely(m_pos[2] == ip[2]))
++ goto match;
++ }
++
++literal:
++ dict[dindex] = ip;
++ ++ip;
++ if (unlikely(ip >= ip_end))
++ break;
++ continue;
++
++match:
++ dict[dindex] = ip;
++ if (ip != ii) {
++ size_t t = ip - ii;
++
++ if (t <= 3) {
++ op[-2] |= t;
++ } else if (t <= 18) {
++ *op++ = (t - 3);
++ } else {
++ size_t tt = t - 18;
++
++ *op++ = 0;
++ while (tt > 255) {
++ tt -= 255;
++ *op++ = 0;
++ }
++ *op++ = tt;
++ }
++ do {
++ *op++ = *ii++;
++ } while (--t > 0);
++ }
++
++ ip += 3;
++ if (m_pos[3] != *ip++ || m_pos[4] != *ip++
++ || m_pos[5] != *ip++ || m_pos[6] != *ip++
++ || m_pos[7] != *ip++ || m_pos[8] != *ip++) {
++ --ip;
++ m_len = ip - ii;
++
++ if (m_off <= M2_MAX_OFFSET) {
++ m_off -= 1;
++ *op++ = (((m_len - 1) << 5)
++ | ((m_off & 7) << 2));
++ *op++ = (m_off >> 3);
++ } else if (m_off <= M3_MAX_OFFSET) {
++ m_off -= 1;
++ *op++ = (M3_MARKER | (m_len - 2));
++ goto m3_m4_offset;
++ } else {
++ m_off -= 0x4000;
++
++ *op++ = (M4_MARKER | ((m_off & 0x4000) >> 11)
++ | (m_len - 2));
++ goto m3_m4_offset;
++ }
++ } else {
++ end = in_end;
++ m = m_pos + M2_MAX_LEN + 1;
++
++ while (ip < end && *m == *ip) {
++ m++;
++ ip++;
++ }
++ m_len = ip - ii;
++
++ if (m_off <= M3_MAX_OFFSET) {
++ m_off -= 1;
++ if (m_len <= 33) {
++ *op++ = (M3_MARKER | (m_len - 2));
++ } else {
++ m_len -= 33;
++ *op++ = M3_MARKER | 0;
++ goto m3_m4_len;
++ }
++ } else {
++ m_off -= 0x4000;
++ if (m_len <= M4_MAX_LEN) {
++ *op++ = (M4_MARKER
++ | ((m_off & 0x4000) >> 11)
++ | (m_len - 2));
++ } else {
++ m_len -= M4_MAX_LEN;
++ *op++ = (M4_MARKER
++ | ((m_off & 0x4000) >> 11));
++m3_m4_len:
++ while (m_len > 255) {
++ m_len -= 255;
++ *op++ = 0;
++ }
++
++ *op++ = (m_len);
++ }
++ }
++m3_m4_offset:
++ *op++ = ((m_off & 63) << 2);
++ *op++ = (m_off >> 6);
++ }
++
++ ii = ip;
++ if (unlikely(ip >= ip_end))
++ break;
++ }
++
++ *out_len = op - out;
++ return in_end - ii;
++}
++
++int lzo1x_1_compress(const unsigned char *in, size_t in_len, unsigned char *out,
++ size_t *out_len, void *wrkmem)
++{
++ const unsigned char *ii;
++ unsigned char *op = out;
++ size_t t;
++
++ if (unlikely(in_len <= M2_MAX_LEN + 5)) {
++ t = in_len;
++ } else {
++ t = _lzo1x_1_do_compress(in, in_len, op, out_len, wrkmem);
++ op += *out_len;
++ }
++
++ if (t > 0) {
++ ii = in + in_len - t;
++
++ if (op == out && t <= 238) {
++ *op++ = (17 + t);
++ } else if (t <= 3) {
++ op[-2] |= t;
++ } else if (t <= 18) {
++ *op++ = (t - 3);
++ } else {
++ size_t tt = t - 18;
++
++ *op++ = 0;
++ while (tt > 255) {
++ tt -= 255;
++ *op++ = 0;
++ }
++
++ *op++ = tt;
++ }
++ do {
++ *op++ = *ii++;
++ } while (--t > 0);
++ }
++
++ *op++ = M4_MARKER | 1;
++ *op++ = 0;
++ *op++ = 0;
++
++ *out_len = op - out;
++ return LZO_E_OK;
++}
++EXPORT_SYMBOL_GPL(lzo1x_1_compress);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("LZO1X-1 Compressor");
++
+--- /dev/null
++++ b/sub-projects/compression/lzo-kmod/lzo1x_decompress.c
+@@ -0,0 +1,255 @@
++/*
++ * LZO1X Decompressor from MiniLZO
++ *
++ * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
++ *
++ * The full LZO package can be found at:
++ * http://www.oberhumer.com/opensource/lzo/
++ *
++ * Changed for kernel use by:
++ * Nitin Gupta <nitingupta910@gmail.com>
++ * Richard Purdie <rpurdie@openedhand.com>
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <asm/byteorder.h>
++#include <asm/unaligned.h>
++
++#include "lzodefs.h"
++#include "lzo.h"
++
++#define HAVE_IP(x, ip_end, ip) ((size_t)(ip_end - ip) < (x))
++#define HAVE_OP(x, op_end, op) ((size_t)(op_end - op) < (x))
++#define HAVE_LB(m_pos, out, op) (m_pos < out || m_pos >= op)
++
++#define COPY4(dst, src) \
++ put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
++
++int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
++ unsigned char *out, size_t *out_len)
++{
++ const unsigned char * const ip_end = in + in_len;
++ unsigned char * const op_end = out + *out_len;
++ const unsigned char *ip = in, *m_pos;
++ unsigned char *op = out;
++ size_t t;
++
++ *out_len = 0;
++
++ if (*ip > 17) {
++ t = *ip++ - 17;
++ if (t < 4)
++ goto match_next;
++ if (HAVE_OP(t, op_end, op))
++ goto output_overrun;
++ if (HAVE_IP(t + 1, ip_end, ip))
++ goto input_overrun;
++ do {
++ *op++ = *ip++;
++ } while (--t > 0);
++ goto first_literal_run;
++ }
++
++ while ((ip < ip_end)) {
++ t = *ip++;
++ if (t >= 16)
++ goto match;
++ if (t == 0) {
++ if (HAVE_IP(1, ip_end, ip))
++ goto input_overrun;
++ while (*ip == 0) {
++ t += 255;
++ ip++;
++ if (HAVE_IP(1, ip_end, ip))
++ goto input_overrun;
++ }
++ t += 15 + *ip++;
++ }
++ if (HAVE_OP(t + 3, op_end, op))
++ goto output_overrun;
++ if (HAVE_IP(t + 4, ip_end, ip))
++ goto input_overrun;
++
++ COPY4(op, ip);
++ op += 4;
++ ip += 4;
++ if (--t > 0) {
++ if (t >= 4) {
++ do {
++ COPY4(op, ip);
++ op += 4;
++ ip += 4;
++ t -= 4;
++ } while (t >= 4);
++ if (t > 0) {
++ do {
++ *op++ = *ip++;
++ } while (--t > 0);
++ }
++ } else {
++ do {
++ *op++ = *ip++;
++ } while (--t > 0);
++ }
++ }
++
++first_literal_run:
++ t = *ip++;
++ if (t >= 16)
++ goto match;
++ m_pos = op - (1 + M2_MAX_OFFSET);
++ m_pos -= t >> 2;
++ m_pos -= *ip++ << 2;
++
++ if (HAVE_LB(m_pos, out, op))
++ goto lookbehind_overrun;
++
++ if (HAVE_OP(3, op_end, op))
++ goto output_overrun;
++ *op++ = *m_pos++;
++ *op++ = *m_pos++;
++ *op++ = *m_pos;
++
++ goto match_done;
++
++ do {
++match:
++ if (t >= 64) {
++ m_pos = op - 1;
++ m_pos -= (t >> 2) & 7;
++ m_pos -= *ip++ << 3;
++ t = (t >> 5) - 1;
++ if (HAVE_LB(m_pos, out, op))
++ goto lookbehind_overrun;
++ if (HAVE_OP(t + 3 - 1, op_end, op))
++ goto output_overrun;
++ goto copy_match;
++ } else if (t >= 32) {
++ t &= 31;
++ if (t == 0) {
++ if (HAVE_IP(1, ip_end, ip))
++ goto input_overrun;
++ while (*ip == 0) {
++ t += 255;
++ ip++;
++ if (HAVE_IP(1, ip_end, ip))
++ goto input_overrun;
++ }
++ t += 31 + *ip++;
++ }
++ m_pos = op - 1;
++ m_pos -= le16_to_cpu(get_unaligned(
++ (const unsigned short *)ip)) >> 2;
++ ip += 2;
++ } else if (t >= 16) {
++ m_pos = op;
++ m_pos -= (t & 8) << 11;
++
++ t &= 7;
++ if (t == 0) {
++ if (HAVE_IP(1, ip_end, ip))
++ goto input_overrun;
++ while (*ip == 0) {
++ t += 255;
++ ip++;
++ if (HAVE_IP(1, ip_end, ip))
++ goto input_overrun;
++ }
++ t += 7 + *ip++;
++ }
++ m_pos -= le16_to_cpu(get_unaligned(
++ (const unsigned short *)ip)) >> 2;
++ ip += 2;
++ if (m_pos == op)
++ goto eof_found;
++ m_pos -= 0x4000;
++ } else {
++ m_pos = op - 1;
++ m_pos -= t >> 2;
++ m_pos -= *ip++ << 2;
++
++ if (HAVE_LB(m_pos, out, op))
++ goto lookbehind_overrun;
++ if (HAVE_OP(2, op_end, op))
++ goto output_overrun;
++
++ *op++ = *m_pos++;
++ *op++ = *m_pos;
++ goto match_done;
++ }
++
++ if (HAVE_LB(m_pos, out, op))
++ goto lookbehind_overrun;
++ if (HAVE_OP(t + 3 - 1, op_end, op))
++ goto output_overrun;
++
++ if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) {
++ COPY4(op, m_pos);
++ op += 4;
++ m_pos += 4;
++ t -= 4 - (3 - 1);
++ do {
++ COPY4(op, m_pos);
++ op += 4;
++ m_pos += 4;
++ t -= 4;
++ } while (t >= 4);
++ if (t > 0)
++ do {
++ *op++ = *m_pos++;
++ } while (--t > 0);
++ } else {
++copy_match:
++ *op++ = *m_pos++;
++ *op++ = *m_pos++;
++ do {
++ *op++ = *m_pos++;
++ } while (--t > 0);
++ }
++match_done:
++ t = ip[-2] & 3;
++ if (t == 0)
++ break;
++match_next:
++ if (HAVE_OP(t, op_end, op))
++ goto output_overrun;
++ if (HAVE_IP(t + 1, ip_end, ip))
++ goto input_overrun;
++
++ *op++ = *ip++;
++ if (t > 1) {
++ *op++ = *ip++;
++ if (t > 2)
++ *op++ = *ip++;
++ }
++
++ t = *ip++;
++ } while (ip < ip_end);
++ }
++
++ *out_len = op - out;
++ return LZO_E_EOF_NOT_FOUND;
++
++eof_found:
++ *out_len = op - out;
++ return (ip == ip_end ? LZO_E_OK :
++ (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
++input_overrun:
++ *out_len = op - out;
++ return LZO_E_INPUT_OVERRUN;
++
++output_overrun:
++ *out_len = op - out;
++ return LZO_E_OUTPUT_OVERRUN;
++
++lookbehind_overrun:
++ *out_len = op - out;
++ return LZO_E_LOOKBEHIND_OVERRUN;
++}
++
++EXPORT_SYMBOL_GPL(lzo1x_decompress_safe);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("LZO1X Decompressor");
++
+--- /dev/null
++++ b/sub-projects/compression/lzo-kmod/lzodefs.h
+@@ -0,0 +1,43 @@
++/*
++ * lzodefs.h -- architecture, OS and compiler specific defines
++ *
++ * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
++ *
++ * The full LZO package can be found at:
++ * http://www.oberhumer.com/opensource/lzo/
++ *
++ * Changed for kernel use by:
++ * Nitin Gupta <nitingupta910@gmail.com>
++ * Richard Purdie <rpurdie@openedhand.com>
++ */
++
++#define LZO_VERSION 0x2020
++#define LZO_VERSION_STRING "2.02"
++#define LZO_VERSION_DATE "Oct 17 2005"
++
++#define M1_MAX_OFFSET 0x0400
++#define M2_MAX_OFFSET 0x0800
++#define M3_MAX_OFFSET 0x4000
++#define M4_MAX_OFFSET 0xbfff
++
++#define M1_MIN_LEN 2
++#define M1_MAX_LEN 2
++#define M2_MIN_LEN 3
++#define M2_MAX_LEN 8
++#define M3_MIN_LEN 3
++#define M3_MAX_LEN 33
++#define M4_MIN_LEN 3
++#define M4_MAX_LEN 9
++
++#define M1_MARKER 0
++#define M2_MARKER 64
++#define M3_MARKER 32
++#define M4_MARKER 16
++
++#define D_BITS 14
++#define D_MASK ((1u << D_BITS) - 1)
++#define D_HIGH ((D_MASK >> 1) + 1)
++
++#define DX2(p, s1, s2) (((((size_t)((p)[2]) << (s2)) ^ (p)[1]) \
++ << (s1)) ^ (p)[0])
++#define DX3(p, s1, s2, s3) ((DX2((p)+1, s2, s3) << (s1)) ^ (p)[0])
+--- /dev/null
++++ b/sub-projects/compression/lzo-kmod/lzo.h
+@@ -0,0 +1,44 @@
++#ifndef __LZO_H__
++#define __LZO_H__
++/*
++ * LZO Public Kernel Interface
++ * A mini subset of the LZO real-time data compression library
++ *
++ * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
++ *
++ * The full LZO package can be found at:
++ * http://www.oberhumer.com/opensource/lzo/
++ *
++ * Changed for kernel use by:
++ * Nitin Gupta <nitingupta910@gmail.com>
++ * Richard Purdie <rpurdie@openedhand.com>
++ */
++
++#define LZO1X_MEM_COMPRESS (16384 * sizeof(unsigned char *))
++#define LZO1X_1_MEM_COMPRESS LZO1X_MEM_COMPRESS
++
++#define lzo1x_worst_compress(x) ((x) + ((x) / 16) + 64 + 3)
++
++/* This requires 'workmem' of size LZO1X_1_MEM_COMPRESS */
++int lzo1x_1_compress(const unsigned char *src, size_t src_len,
++ unsigned char *dst, size_t *dst_len, void *wrkmem);
++
++/* safe decompression with overrun testing */
++int lzo1x_decompress_safe(const unsigned char *src, size_t src_len,
++ unsigned char *dst, size_t *dst_len);
++
++/*
++ * Return values (< 0 = Error)
++ */
++#define LZO_E_OK 0
++#define LZO_E_ERROR (-1)
++#define LZO_E_OUT_OF_MEMORY (-2)
++#define LZO_E_NOT_COMPRESSIBLE (-3)
++#define LZO_E_INPUT_OVERRUN (-4)
++#define LZO_E_OUTPUT_OVERRUN (-5)
++#define LZO_E_LOOKBEHIND_OVERRUN (-6)
++#define LZO_E_EOF_NOT_FOUND (-7)
++#define LZO_E_INPUT_NOT_CONSUMED (-8)
++#define LZO_E_NOT_YET_IMPLEMENTED (-9)
++
++#endif
+--- /dev/null
++++ b/sub-projects/compression/lzo-kmod/Makefile
+@@ -0,0 +1,8 @@
++obj-m += lzo1x_compress.o lzo1x_decompress.o
++
++all:
++ make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
++
++clean:
++ make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
++
diff --git a/package/compcache/patches/001-lzo-speed.patch b/package/compcache/patches/001-lzo-speed.patch
new file mode 100644
index 000000000..130f79da6
--- /dev/null
+++ b/package/compcache/patches/001-lzo-speed.patch
@@ -0,0 +1,181 @@
+--- a/sub-projects/compression/lzo-kmod/lzo1x_compress.c
++++ b/sub-projects/compression/lzo-kmod/lzo1x_compress.c
+@@ -62,8 +62,12 @@ _lzo1x_1_do_compress(const unsigned char
+ goto literal;
+
+ try_match:
++#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+ if (get_unaligned((const unsigned short *)m_pos)
+ == get_unaligned((const unsigned short *)ip)) {
++#else
++ if (m_pos[0] == ip[0] && m_pos[1] == ip[1]) {
++#endif
+ if (likely(m_pos[2] == ip[2]))
+ goto match;
+ }
+@@ -94,9 +98,14 @@ match:
+ }
+ *op++ = tt;
+ }
+- do {
+- *op++ = *ii++;
+- } while (--t > 0);
++ if (t >= 2 * 4) {
++ memcpy(op, ii, t);
++ op += t;
++ ii += t;
++ } else
++ do {
++ *op++ = *ii++;
++ } while (--t > 0);
+ }
+
+ ip += 3;
+@@ -208,9 +217,14 @@ int lzo1x_1_compress(const unsigned char
+
+ *op++ = tt;
+ }
+- do {
+- *op++ = *ii++;
+- } while (--t > 0);
++ if (t >= 2 * 4) {
++ memcpy(op, ii, t);
++ op += t;
++ ii += t;
++ } else
++ do {
++ *op++ = *ii++;
++ } while (--t > 0);
+ }
+
+ *op++ = M4_MARKER | 1;
+@@ -224,4 +238,3 @@ EXPORT_SYMBOL_GPL(lzo1x_1_compress);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("LZO1X-1 Compressor");
+-
+--- a/sub-projects/compression/lzo-kmod/lzo1x_decompress.c
++++ b/sub-projects/compression/lzo-kmod/lzo1x_decompress.c
+@@ -45,10 +45,7 @@ int lzo1x_decompress_safe(const unsigned
+ goto output_overrun;
+ if (HAVE_IP(t + 1, ip_end, ip))
+ goto input_overrun;
+- do {
+- *op++ = *ip++;
+- } while (--t > 0);
+- goto first_literal_run;
++ goto prep_first_literal_run;
+ }
+
+ while ((ip < ip_end)) {
+@@ -71,30 +68,27 @@ int lzo1x_decompress_safe(const unsigned
+ if (HAVE_IP(t + 4, ip_end, ip))
+ goto input_overrun;
+
+- COPY4(op, ip);
+- op += 4;
+- ip += 4;
+- if (--t > 0) {
+- if (t >= 4) {
+- do {
+- COPY4(op, ip);
+- op += 4;
+- ip += 4;
+- t -= 4;
+- } while (t >= 4);
+- if (t > 0) {
+- do {
+- *op++ = *ip++;
+- } while (--t > 0);
+- }
+- } else {
++ t += (4 - 1);
++ if (t >= 2 * 4) {
++ memcpy(op, ip, t);
++ op += t;
++ ip += t;
++ } else {
++ do {
++ COPY4(op, ip);
++ op += 4;
++ ip += 4;
++ t -= 4;
++ } while (t >= 4);
++ if (t > 0) {
++prep_first_literal_run:
+ do {
+ *op++ = *ip++;
+ } while (--t > 0);
+ }
+ }
+
+-first_literal_run:
++//first_literal_run:
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+@@ -139,8 +133,7 @@ match:
+ t += 31 + *ip++;
+ }
+ m_pos = op - 1;
+- m_pos -= le16_to_cpu(get_unaligned(
+- (const unsigned short *)ip)) >> 2;
++ m_pos -= get_unaligned_le16(ip) >> 2;
+ ip += 2;
+ } else if (t >= 16) {
+ m_pos = op;
+@@ -158,8 +151,7 @@ match:
+ }
+ t += 7 + *ip++;
+ }
+- m_pos -= le16_to_cpu(get_unaligned(
+- (const unsigned short *)ip)) >> 2;
++ m_pos -= get_unaligned_le16(ip) >> 2;
+ ip += 2;
+ if (m_pos == op)
+ goto eof_found;
+@@ -184,21 +176,33 @@ match:
+ if (HAVE_OP(t + 3 - 1, op_end, op))
+ goto output_overrun;
+
+- if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) {
+- COPY4(op, m_pos);
+- op += 4;
+- m_pos += 4;
+- t -= 4 - (3 - 1);
+- do {
++ if (t >= 2 * 4 - (3 - 1)) {
++ /*
++ * Assume memcpy don't copy
++ * more than 32 bytes at once
++ */
++ if ((op - m_pos) >= 32) {
++ t += (3 - 1);
++ memcpy(op, m_pos, t);
++ op += t;
++ m_pos += t;
++ } else if ((op - m_pos) >= 4) {
+ COPY4(op, m_pos);
+ op += 4;
+ m_pos += 4;
+- t -= 4;
+- } while (t >= 4);
+- if (t > 0)
++ t -= 4 - (3 - 1);
+ do {
+- *op++ = *m_pos++;
+- } while (--t > 0);
++ COPY4(op, m_pos);
++ op += 4;
++ m_pos += 4;
++ t -= 4;
++ } while (t >= 4);
++ if (t > 0)
++ do {
++ *op++ = *m_pos++;
++ } while (--t > 0);
++ } else
++ goto copy_match;
+ } else {
+ copy_match:
+ *op++ = *m_pos++;
diff --git a/package/compcache/patches/002-kernel-2.6.34-compat.patch b/package/compcache/patches/002-kernel-2.6.34-compat.patch
new file mode 100644
index 000000000..5cd8129f8
--- /dev/null
+++ b/package/compcache/patches/002-kernel-2.6.34-compat.patch
@@ -0,0 +1,10 @@
+--- a/ramzswap_drv.c
++++ b/ramzswap_drv.c
+@@ -23,6 +23,7 @@
+ #include <linux/device.h>
+ #include <linux/genhd.h>
+ #include <linux/highmem.h>
++#include <linux/slab.h>
+ #include <linux/string.h>
+ #include <linux/swap.h>
+ #include <linux/swapops.h>
diff --git a/package/compcache/patches/003-kernel-3.x-compat.patch b/package/compcache/patches/003-kernel-3.x-compat.patch
new file mode 100644
index 000000000..70996ebe7
--- /dev/null
+++ b/package/compcache/patches/003-kernel-3.x-compat.patch
@@ -0,0 +1,31 @@
+Index: compcache-0.6.2/ramzswap_drv.c
+===================================================================
+--- compcache-0.6.2.orig/ramzswap_drv.c 2012-07-25 01:02:39.000000000 +0200
++++ compcache-0.6.2/ramzswap_drv.c 2012-07-25 01:04:29.270750850 +0200
+@@ -525,7 +525,7 @@
+
+ if (S_ISBLK(inode->i_mode)) {
+ bdev = I_BDEV(inode);
+- ret = bd_claim(bdev, setup_backing_swap);
++ ret = blkdev_get(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL, setup_backing_swap);
+ if (ret < 0) {
+ bdev = NULL;
+ goto bad_param;
+@@ -557,7 +557,7 @@
+
+ bad_param:
+ if (bdev)
+- bd_release(bdev);
++ blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+ filp_close(swap_file, NULL);
+
+ out:
+@@ -1097,7 +1097,7 @@
+ /* Close backing swap device, if present */
+ if (rzs->backing_swap) {
+ if (is_backing_blkdev)
+- bd_release(rzs->backing_swap);
++ blkdev_put(rzs->backing_swap, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+ filp_close(rzs->swap_file, NULL);
+ rzs->backing_swap = NULL;
+ memset(rzs->backing_swap_name, 0, MAX_SWAP_NAME_LEN);
diff --git a/package/crda/Makefile b/package/crda/Makefile
new file mode 100644
index 000000000..0d075f1da
--- /dev/null
+++ b/package/crda/Makefile
@@ -0,0 +1,74 @@
+#
+# Copyright (C) 2009-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=crda
+PKG_RELEASE:=1
+PKG_VERSION:=1.1.2
+PKG_SOURCE_URL:=http://wireless.kernel.org/download/crda
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_MD5SUM:=5226f65aebacf94baaf820f8b4e06df4
+
+PKG_REGULATORY_NAME:=regulatory
+PKG_REGULATORY_VERSION:=2011.04.28
+PKG_REGULATORY_SOURCE_URL:=http://wireless.kernel.org/download/wireless-regdb/regulatory.bins
+PKG_REGULATORY_SOURCE:=$(PKG_REGULATORY_VERSION)-$(PKG_REGULATORY_NAME).bin
+PKG_REGULATORY_MD5SUM:=1535e98bcaba732e2f8e8f62dac6f369
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/crda
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=Central Regulatory Domain Agent (CRDA)
+ DEPENDS:=+libnl-tiny
+ URL:=http://wireless.kernel.org/en/developers/Regulatory/CRDA
+endef
+
+define Download/wireless-regdb
+ FILE:=$(PKG_REGULATORY_SOURCE)
+ URL:=$(PKG_REGULATORY_SOURCE_URL)
+ VERSION:=$(PKG_REGULATORY_VERSION)
+ MD5SUM:=$(PKG_REGULATORY_MD5SUM)
+endef
+$(eval $(call Download,wireless-regdb))
+
+define Package/crda/description
+ This is the Central Regulatory Domain Agent for Linux. It serves one
+ purpose: tell Linux kernel what to enforce. In essence it is a udev
+ helper for communication between the kernel and userspace. You only
+ need to run this manually for debugging purposes. For manual changing
+ of regulatory domains use iw (iw reg set) or wpa_supplicant (feature
+ yet to be added).
+endef
+
+TARGET_CPPFLAGS := \
+ -I$(STAGING_DIR)/usr/include/libnl-tiny \
+ -D_GNU_SOURCE \
+ $(TARGET_CPPFLAGS)
+
+MAKE_FLAGS += \
+ NL1FOUND="" NL2FOUND=Y \
+ NLLIBNAME="libnl-tiny" \
+ NLLIBS="-lnl-tiny -lm" \
+ REG_BIN="$(DL_DIR)/$(PKG_REGULATORY_SOURCE)" \
+ crda
+
+define Package/crda/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_DIR) $(1)/etc/hotplug.d
+ $(INSTALL_DIR) $(1)/etc/hotplug.d/platform
+ $(INSTALL_DIR) $(1)/usr/lib/crda
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/crda $(1)/sbin/
+ $(INSTALL_DATA) ./files/hotplug.rule $(1)/etc/hotplug.d/platform/10-regulatory
+ $(INSTALL_DATA) $(DL_DIR)/$(PKG_REGULATORY_SOURCE) $(1)/usr/lib/crda/regulatory.bin
+endef
+
+$(eval $(call BuildPackage,crda))
+
diff --git a/package/crda/files/hotplug.rule b/package/crda/files/hotplug.rule
new file mode 100644
index 000000000..1ec033f46
--- /dev/null
+++ b/package/crda/files/hotplug.rule
@@ -0,0 +1,6 @@
+#!/bin/sh
+# Copyright (C) 2009 OpenWrt.org
+
+[ change = "$ACTION" -a regulatory.0 = "$DEVICENAME" ] && {
+ /sbin/crda
+}
diff --git a/package/crda/patches/101-make_crypto_use_optional.patch b/package/crda/patches/101-make_crypto_use_optional.patch
new file mode 100644
index 000000000..c7ace42c8
--- /dev/null
+++ b/package/crda/patches/101-make_crypto_use_optional.patch
@@ -0,0 +1,13 @@
+--- a/Makefile
++++ b/Makefile
+@@ -35,7 +35,9 @@ LDLIBS += `pkg-config --libs openssl`
+
+ reglib.o: keys-ssl.c
+
+-else
++endif
++
++ifeq ($(USE_GCRYPT),1)
+ CFLAGS += -DUSE_GCRYPT
+ LDLIBS += -lgcrypt
+
diff --git a/package/cyassl/Makefile b/package/cyassl/Makefile
new file mode 100644
index 000000000..442186aac
--- /dev/null
+++ b/package/cyassl/Makefile
@@ -0,0 +1,56 @@
+#
+# Copyright (C) 2006-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=cyassl
+PKG_VERSION:=1.6.5
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).zip
+PKG_SOURCE_URL:=http://www.yassl.com/
+PKG_MD5SUM:=98c2c6350acf1d089756a1de9ccb9903
+
+PKG_FIXUP:=patch-libtool
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/libcyassl
+ SECTION:=libs
+ SUBMENU:=SSL
+ CATEGORY:=Libraries
+ TITLE:=CyaSSL library
+ URL:=http://www.yassl.com/
+endef
+
+define Package/libcyassl/description
+CyaSSL is an SSL library optimized for small footprint, both on disk and for
+memory use.
+endef
+
+TARGET_CFLAGS += $(FPIC)
+
+CONFIGURE_ARGS += \
+ --without-zlib \
+ --enable-singleThreaded
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include/
+
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libcyassl.{a,so*,la} $(1)/usr/lib/
+endef
+
+define Package/libcyassl/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libcyassl.so* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,libcyassl))
diff --git a/package/cyassl/patches/110-makefile_disable_examples_tests.patch b/package/cyassl/patches/110-makefile_disable_examples_tests.patch
new file mode 100644
index 000000000..c66ab8c13
--- /dev/null
+++ b/package/cyassl/patches/110-makefile_disable_examples_tests.patch
@@ -0,0 +1,46 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1,4 +1,4 @@
+-SUBDIRS = src ctaocrypt examples testsuite sslSniffer
++SUBDIRS = src ctaocrypt
+ EXTRA_DIST = cyassl.dsp cyassl.dsw certs/*.pem certs/*.der certs/*.txt \
+ lib/dummy cyassl.sln cyassl.vcproj cyassl-iphone.xcodeproj/project.pbxproj \
+ doc/*.pdf swig/README swig/*.i swig/cyassl_adds.c swig/*.sh swig/runme.* \
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -193,7 +193,7 @@ target_os = @target_os@
+ target_vendor = @target_vendor@
+ top_builddir = @top_builddir@
+ top_srcdir = @top_srcdir@
+-SUBDIRS = src ctaocrypt examples testsuite sslSniffer
++SUBDIRS = src ctaocrypt
+ EXTRA_DIST = cyassl.dsp cyassl.dsw certs/*.pem certs/*.der certs/*.txt \
+ lib/dummy cyassl.sln cyassl.vcproj cyassl-iphone.xcodeproj/project.pbxproj \
+ doc/*.pdf swig/README swig/*.i swig/cyassl_adds.c swig/*.sh swig/runme.* \
+@@ -643,7 +643,7 @@ uninstall-am:
+
+ # !!!! first line of rule has to start with a hard (real) tab, not spaces
+ basic:
+- cd src; $(MAKE); cd ../testsuite; $(MAKE); cd ../
++ cd src; $(MAKE); cd ../
+
+ openssl-links:
+ cd lib; ln -s ../src/.libs/libcyassl.a libcrypto.a; \
+--- a/ctaocrypt/Makefile.am
++++ b/ctaocrypt/Makefile.am
+@@ -1,3 +1,3 @@
+-SUBDIRS = src test benchmark
++SUBDIRS = src
+ EXTRA_DIST = ctaocrypt.dsw ctaocrypt.dsp ctaocrypt.sln ctaocrypt.vcproj
+
+--- a/ctaocrypt/Makefile.in
++++ b/ctaocrypt/Makefile.in
+@@ -177,7 +177,7 @@ target_os = @target_os@
+ target_vendor = @target_vendor@
+ top_builddir = @top_builddir@
+ top_srcdir = @top_srcdir@
+-SUBDIRS = src test benchmark
++SUBDIRS = src
+ EXTRA_DIST = ctaocrypt.dsw ctaocrypt.dsp ctaocrypt.sln ctaocrypt.vcproj
+ all: all-recursive
+
diff --git a/package/cyassl/patches/120-makefile_destdir.patch b/package/cyassl/patches/120-makefile_destdir.patch
new file mode 100644
index 000000000..bf2027440
--- /dev/null
+++ b/package/cyassl/patches/120-makefile_destdir.patch
@@ -0,0 +1,71 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -10,19 +10,19 @@ basic:
+
+ openssl-links:
+ cd lib; ln -s ../src/.libs/libcyassl.a libcrypto.a; \
+- ln -s ../src/.libs/libcyassl.a libssl.a; \
+- ln -s ../src/.libs/libcyassl.a libcyassl.a; cd ../
++ ln -s ../src/.libs/libcyassl.a libssl.a; \
++ ln -s ../src/.libs/libcyassl.a libcyassl.a; cd ../
+
+ # !!! test -e with a .name like .libs then a * like *dylib fails so just
+ # look for the .dylib on OS X, and .so otherwise but copy all parts
+ install:
+- $(mkinstalldirs) $(DESTDIR)$(includedir) $(DESTDIR)$(libdir); \
+- cp -fpR include/* $(DESTDIR)$(includedir); \
+- cp -fpR ctaocrypt/include/* $(DESTDIR)$(includedir); \
+- cp -fpR src/libcyassl.la $(DESTDIR)$(libdir); \
+- if test -e src/.libs/libcyassl.a; then \
+- cp -fp src/.libs/libcyassl.a $(DESTDIR)$(libdir); fi; \
+- if test -e src/.libs/libcyassl.so; then \
+- cp -fpR src/.libs/libcyassl.so* $(DESTDIR)$(libdir); fi; \
+- if test -e src/.libs/libcyassl.dylib; then \
+- cp -fpR src/.libs/libcyassl.*dylib $(DESTDIR)$(libdir); fi;
++ $(mkinstalldirs) $(DESTDIR)$(includedir)/cyassl $(DESTDIR)$(libdir); \
++ cp -fpR include/* $(DESTDIR)$(includedir)/cyassl; \
++ cp -fpR ctaocrypt/include/* $(DESTDIR)$(includedir)/cyassl; \
++ cp -fpR src/libcyassl.la $(DESTDIR)$(libdir); \
++ if test -e src/.libs/libcyassl.a; then \
++ cp -fp src/.libs/libcyassl.a $(DESTDIR)$(libdir); fi; \
++ if test -e src/.libs/libcyassl.so; then \
++ cp -fpR src/.libs/libcyassl.so* $(DESTDIR)$(libdir); fi; \
++ if test -e src/.libs/libcyassl.dylib; then \
++ cp -fpR src/.libs/libcyassl.*dylib $(DESTDIR)$(libdir); fi;
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -647,22 +647,22 @@ basic:
+
+ openssl-links:
+ cd lib; ln -s ../src/.libs/libcyassl.a libcrypto.a; \
+- ln -s ../src/.libs/libcyassl.a libssl.a; \
+- ln -s ../src/.libs/libcyassl.a libcyassl.a; cd ../
++ ln -s ../src/.libs/libcyassl.a libssl.a; \
++ ln -s ../src/.libs/libcyassl.a libcyassl.a; cd ../
+
+ # !!! test -e with a .name like .libs then a * like *dylib fails so just
+ # look for the .dylib on OS X, and .so otherwise but copy all parts
+ install:
+- $(mkinstalldirs) $(DESTDIR)$(includedir) $(DESTDIR)$(libdir); \
+- cp -fpR include/* $(DESTDIR)$(includedir); \
+- cp -fpR ctaocrypt/include/* $(DESTDIR)$(includedir); \
+- cp -fpR src/libcyassl.la $(DESTDIR)$(libdir); \
+- if test -e src/.libs/libcyassl.a; then \
+- cp -fp src/.libs/libcyassl.a $(DESTDIR)$(libdir); fi; \
+- if test -e src/.libs/libcyassl.so; then \
+- cp -fpR src/.libs/libcyassl.so* $(DESTDIR)$(libdir); fi; \
+- if test -e src/.libs/libcyassl.dylib; then \
+- cp -fpR src/.libs/libcyassl.*dylib $(DESTDIR)$(libdir); fi;
++ $(mkinstalldirs) $(DESTDIR)$(includedir)/cyassl $(DESTDIR)$(libdir); \
++ cp -fpR include/* $(DESTDIR)$(includedir)/cyassl; \
++ cp -fpR ctaocrypt/include/* $(DESTDIR)$(includedir)/cyassl; \
++ cp -fpR src/libcyassl.la $(DESTDIR)$(libdir); \
++ if test -e src/.libs/libcyassl.a; then \
++ cp -fp src/.libs/libcyassl.a $(DESTDIR)$(libdir); fi; \
++ if test -e src/.libs/libcyassl.so; then \
++ cp -fpR src/.libs/libcyassl.so* $(DESTDIR)$(libdir); fi; \
++ if test -e src/.libs/libcyassl.dylib; then \
++ cp -fpR src/.libs/libcyassl.*dylib $(DESTDIR)$(libdir); fi;
+ # Tell versions [3.59,3.63) of GNU make to not export all variables.
+ # Otherwise a system limit (for SysV at least) may be exceeded.
+ .NOEXPORT:
diff --git a/package/cyassl/patches/130-configure_disable_pthreads_tests.patch b/package/cyassl/patches/130-configure_disable_pthreads_tests.patch
new file mode 100644
index 000000000..44fdf6ced
--- /dev/null
+++ b/package/cyassl/patches/130-configure_disable_pthreads_tests.patch
@@ -0,0 +1,444 @@
+--- a/configure
++++ b/configure
+@@ -888,10 +888,6 @@ BUILD_RIPEMD_TRUE
+ BUILD_RIPEMD_FALSE
+ BUILD_SHA512_TRUE
+ BUILD_SHA512_FALSE
+-acx_pthread_config
+-PTHREAD_CC
+-PTHREAD_LIBS
+-PTHREAD_CFLAGS
+ LIBOBJS
+ LTLIBOBJS'
+ ac_subst_files=''
+@@ -22251,430 +22247,6 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS con
+ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+-acx_pthread_ok=no
+-
+-# We used to check for pthread.h first, but this fails if pthread.h
+-# requires special compiler flags (e.g. on True64 or Sequent).
+-# It gets checked for in the link test anyway.
+-
+-# First of all, check if the user has set any of the PTHREAD_LIBS,
+-# etcetera environment variables, and if threads linking works using
+-# them:
+-if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+- save_CFLAGS="$CFLAGS"
+- CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+- save_LIBS="$LIBS"
+- LIBS="$PTHREAD_LIBS $LIBS"
+- { echo "$as_me:$LINENO: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5
+-echo $ECHO_N "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... $ECHO_C" >&6; }
+- cat >conftest.$ac_ext <<_ACEOF
+-/* confdefs.h. */
+-_ACEOF
+-cat confdefs.h >>conftest.$ac_ext
+-cat >>conftest.$ac_ext <<_ACEOF
+-/* end confdefs.h. */
+-
+-/* Override any GCC internal prototype to avoid an error.
+- Use char because int might match the return type of a GCC
+- builtin and then its argument prototype would still apply. */
+-#ifdef __cplusplus
+-extern "C"
+-#endif
+-char pthread_join ();
+-int
+-main ()
+-{
+-return pthread_join ();
+- ;
+- return 0;
+-}
+-_ACEOF
+-rm -f conftest.$ac_objext conftest$ac_exeext
+-if { (ac_try="$ac_link"
+-case "(($ac_try" in
+- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+- *) ac_try_echo=$ac_try;;
+-esac
+-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+- (eval "$ac_link") 2>conftest.er1
+- ac_status=$?
+- grep -v '^ *+' conftest.er1 >conftest.err
+- rm -f conftest.er1
+- cat conftest.err >&5
+- echo "$as_me:$LINENO: \$? = $ac_status" >&5
+- (exit $ac_status); } && {
+- test -z "$ac_c_werror_flag" ||
+- test ! -s conftest.err
+- } && test -s conftest$ac_exeext &&
+- $as_test_x conftest$ac_exeext; then
+- acx_pthread_ok=yes
+-else
+- echo "$as_me: failed program was:" >&5
+-sed 's/^/| /' conftest.$ac_ext >&5
+-
+-
+-fi
+-
+-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+- conftest$ac_exeext conftest.$ac_ext
+- { echo "$as_me:$LINENO: result: $acx_pthread_ok" >&5
+-echo "${ECHO_T}$acx_pthread_ok" >&6; }
+- if test x"$acx_pthread_ok" = xno; then
+- PTHREAD_LIBS=""
+- PTHREAD_CFLAGS=""
+- fi
+- LIBS="$save_LIBS"
+- CFLAGS="$save_CFLAGS"
+-fi
+-
+-# We must check for the threads library under a number of different
+-# names; the ordering is very important because some systems
+-# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+-# libraries is broken (non-POSIX).
+-
+-# Create a list of thread flags to try. Items starting with a "-" are
+-# C compiler flags, and other items are library names, except for "none"
+-# which indicates that we try without any flags at all, and "pthread-config"
+-# which is a program returning the flags for the Pth emulation library.
+-
+-acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+-
+-# The ordering *is* (sometimes) important. Some notes on the
+-# individual items follow:
+-
+-# pthreads: AIX (must check this before -lpthread)
+-# none: in case threads are in libc; should be tried before -Kthread and
+-# other compiler flags to prevent continual compiler warnings
+-# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+-# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+-# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+-# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+-# -pthreads: Solaris/gcc
+-# -mthreads: Mingw32/gcc, Lynx/gcc
+-# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+-# doesn't hurt to check since this sometimes defines pthreads too;
+-# also defines -D_REENTRANT)
+-# ... -mt is also the pthreads flag for HP/aCC
+-# pthread: Linux, etcetera
+-# --thread-safe: KAI C++
+-# pthread-config: use pthread-config program (for GNU Pth library)
+-
+-case "${host_cpu}-${host_os}" in
+- *solaris*)
+-
+- # On Solaris (at least, for some versions), libc contains stubbed
+- # (non-functional) versions of the pthreads routines, so link-based
+- # tests will erroneously succeed. (We need to link with -pthreads/-mt/
+- # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+- # a function called by this macro, so we could check for that, but
+- # who knows whether they'll stub that too in a future libc.) So,
+- # we'll just look for -pthreads and -lpthread first:
+-
+- acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags"
+- ;;
+-esac
+-
+-if test x"$acx_pthread_ok" = xno; then
+-for flag in $acx_pthread_flags; do
+-
+- case $flag in
+- none)
+- { echo "$as_me:$LINENO: checking whether pthreads work without any flags" >&5
+-echo $ECHO_N "checking whether pthreads work without any flags... $ECHO_C" >&6; }
+- ;;
+-
+- -*)
+- { echo "$as_me:$LINENO: checking whether pthreads work with $flag" >&5
+-echo $ECHO_N "checking whether pthreads work with $flag... $ECHO_C" >&6; }
+- PTHREAD_CFLAGS="$flag"
+- ;;
+-
+- pthread-config)
+- # Extract the first word of "pthread-config", so it can be a program name with args.
+-set dummy pthread-config; ac_word=$2
+-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+-if test "${ac_cv_prog_acx_pthread_config+set}" = set; then
+- echo $ECHO_N "(cached) $ECHO_C" >&6
+-else
+- if test -n "$acx_pthread_config"; then
+- ac_cv_prog_acx_pthread_config="$acx_pthread_config" # Let the user override the test.
+-else
+-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+-for as_dir in $PATH
+-do
+- IFS=$as_save_IFS
+- test -z "$as_dir" && as_dir=.
+- for ac_exec_ext in '' $ac_executable_extensions; do
+- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+- ac_cv_prog_acx_pthread_config="yes"
+- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+- break 2
+- fi
+-done
+-done
+-IFS=$as_save_IFS
+-
+- test -z "$ac_cv_prog_acx_pthread_config" && ac_cv_prog_acx_pthread_config="no"
+-fi
+-fi
+-acx_pthread_config=$ac_cv_prog_acx_pthread_config
+-if test -n "$acx_pthread_config"; then
+- { echo "$as_me:$LINENO: result: $acx_pthread_config" >&5
+-echo "${ECHO_T}$acx_pthread_config" >&6; }
+-else
+- { echo "$as_me:$LINENO: result: no" >&5
+-echo "${ECHO_T}no" >&6; }
+-fi
+-
+-
+- if test x"$acx_pthread_config" = xno; then continue; fi
+- PTHREAD_CFLAGS="`pthread-config --cflags`"
+- PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+- ;;
+-
+- *)
+- { echo "$as_me:$LINENO: checking for the pthreads library -l$flag" >&5
+-echo $ECHO_N "checking for the pthreads library -l$flag... $ECHO_C" >&6; }
+- PTHREAD_LIBS="-l$flag"
+- ;;
+- esac
+-
+- save_LIBS="$LIBS"
+- save_CFLAGS="$CFLAGS"
+- LIBS="$PTHREAD_LIBS $LIBS"
+- CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+-
+- # Check for various functions. We must include pthread.h,
+- # since some functions may be macros. (On the Sequent, we
+- # need a special flag -Kthread to make this header compile.)
+- # We check for pthread_join because it is in -lpthread on IRIX
+- # while pthread_create is in libc. We check for pthread_attr_init
+- # due to DEC craziness with -lpthreads. We check for
+- # pthread_cleanup_push because it is one of the few pthread
+- # functions on Solaris that doesn't have a non-functional libc stub.
+- # We try pthread_create on general principles.
+- cat >conftest.$ac_ext <<_ACEOF
+-/* confdefs.h. */
+-_ACEOF
+-cat confdefs.h >>conftest.$ac_ext
+-cat >>conftest.$ac_ext <<_ACEOF
+-/* end confdefs.h. */
+-#include <pthread.h>
+-int
+-main ()
+-{
+-pthread_t th; pthread_join(th, 0);
+- pthread_attr_init(0); pthread_cleanup_push(0, 0);
+- pthread_create(0,0,0,0); pthread_cleanup_pop(0);
+- ;
+- return 0;
+-}
+-_ACEOF
+-rm -f conftest.$ac_objext conftest$ac_exeext
+-if { (ac_try="$ac_link"
+-case "(($ac_try" in
+- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+- *) ac_try_echo=$ac_try;;
+-esac
+-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+- (eval "$ac_link") 2>conftest.er1
+- ac_status=$?
+- grep -v '^ *+' conftest.er1 >conftest.err
+- rm -f conftest.er1
+- cat conftest.err >&5
+- echo "$as_me:$LINENO: \$? = $ac_status" >&5
+- (exit $ac_status); } && {
+- test -z "$ac_c_werror_flag" ||
+- test ! -s conftest.err
+- } && test -s conftest$ac_exeext &&
+- $as_test_x conftest$ac_exeext; then
+- acx_pthread_ok=yes
+-else
+- echo "$as_me: failed program was:" >&5
+-sed 's/^/| /' conftest.$ac_ext >&5
+-
+-
+-fi
+-
+-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+- conftest$ac_exeext conftest.$ac_ext
+-
+- LIBS="$save_LIBS"
+- CFLAGS="$save_CFLAGS"
+-
+- { echo "$as_me:$LINENO: result: $acx_pthread_ok" >&5
+-echo "${ECHO_T}$acx_pthread_ok" >&6; }
+- if test "x$acx_pthread_ok" = xyes; then
+- break;
+- fi
+-
+- PTHREAD_LIBS=""
+- PTHREAD_CFLAGS=""
+-done
+-fi
+-
+-# Various other checks:
+-if test "x$acx_pthread_ok" = xyes; then
+- save_LIBS="$LIBS"
+- LIBS="$PTHREAD_LIBS $LIBS"
+- save_CFLAGS="$CFLAGS"
+- CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+-
+- # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+- { echo "$as_me:$LINENO: checking for joinable pthread attribute" >&5
+-echo $ECHO_N "checking for joinable pthread attribute... $ECHO_C" >&6; }
+- attr_name=unknown
+- for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+- cat >conftest.$ac_ext <<_ACEOF
+-/* confdefs.h. */
+-_ACEOF
+-cat confdefs.h >>conftest.$ac_ext
+-cat >>conftest.$ac_ext <<_ACEOF
+-/* end confdefs.h. */
+-#include <pthread.h>
+-int
+-main ()
+-{
+-int attr=$attr; return attr;
+- ;
+- return 0;
+-}
+-_ACEOF
+-rm -f conftest.$ac_objext conftest$ac_exeext
+-if { (ac_try="$ac_link"
+-case "(($ac_try" in
+- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+- *) ac_try_echo=$ac_try;;
+-esac
+-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+- (eval "$ac_link") 2>conftest.er1
+- ac_status=$?
+- grep -v '^ *+' conftest.er1 >conftest.err
+- rm -f conftest.er1
+- cat conftest.err >&5
+- echo "$as_me:$LINENO: \$? = $ac_status" >&5
+- (exit $ac_status); } && {
+- test -z "$ac_c_werror_flag" ||
+- test ! -s conftest.err
+- } && test -s conftest$ac_exeext &&
+- $as_test_x conftest$ac_exeext; then
+- attr_name=$attr; break
+-else
+- echo "$as_me: failed program was:" >&5
+-sed 's/^/| /' conftest.$ac_ext >&5
+-
+-
+-fi
+-
+-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+- conftest$ac_exeext conftest.$ac_ext
+- done
+- { echo "$as_me:$LINENO: result: $attr_name" >&5
+-echo "${ECHO_T}$attr_name" >&6; }
+- if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
+-
+-cat >>confdefs.h <<_ACEOF
+-#define PTHREAD_CREATE_JOINABLE $attr_name
+-_ACEOF
+-
+- fi
+-
+- { echo "$as_me:$LINENO: checking if more special flags are required for pthreads" >&5
+-echo $ECHO_N "checking if more special flags are required for pthreads... $ECHO_C" >&6; }
+- flag=no
+- case "${host_cpu}-${host_os}" in
+- *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
+- *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+- esac
+- { echo "$as_me:$LINENO: result: ${flag}" >&5
+-echo "${ECHO_T}${flag}" >&6; }
+- if test "x$flag" != xno; then
+- PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+- fi
+-
+- LIBS="$save_LIBS"
+- CFLAGS="$save_CFLAGS"
+-
+- # More AIX lossage: must compile with xlc_r or cc_r
+- if test x"$GCC" != xyes; then
+- for ac_prog in xlc_r cc_r
+-do
+- # Extract the first word of "$ac_prog", so it can be a program name with args.
+-set dummy $ac_prog; ac_word=$2
+-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+-if test "${ac_cv_prog_PTHREAD_CC+set}" = set; then
+- echo $ECHO_N "(cached) $ECHO_C" >&6
+-else
+- if test -n "$PTHREAD_CC"; then
+- ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test.
+-else
+-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+-for as_dir in $PATH
+-do
+- IFS=$as_save_IFS
+- test -z "$as_dir" && as_dir=.
+- for ac_exec_ext in '' $ac_executable_extensions; do
+- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+- ac_cv_prog_PTHREAD_CC="$ac_prog"
+- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+- break 2
+- fi
+-done
+-done
+-IFS=$as_save_IFS
+-
+-fi
+-fi
+-PTHREAD_CC=$ac_cv_prog_PTHREAD_CC
+-if test -n "$PTHREAD_CC"; then
+- { echo "$as_me:$LINENO: result: $PTHREAD_CC" >&5
+-echo "${ECHO_T}$PTHREAD_CC" >&6; }
+-else
+- { echo "$as_me:$LINENO: result: no" >&5
+-echo "${ECHO_T}no" >&6; }
+-fi
+-
+-
+- test -n "$PTHREAD_CC" && break
+-done
+-test -n "$PTHREAD_CC" || PTHREAD_CC="${CC}"
+-
+- else
+- PTHREAD_CC=$CC
+- fi
+-else
+- PTHREAD_CC="$CC"
+-fi
+-
+-
+-
+-
+-
+-# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+-if test x"$acx_pthread_ok" = xyes; then
+-
+-cat >>confdefs.h <<\_ACEOF
+-#define HAVE_PTHREAD 1
+-_ACEOF
+-
+- :
+-else
+- acx_pthread_ok=no
+-
+-fi
+-ac_ext=c
+-ac_cpp='$CPP $CPPFLAGS'
+-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+-ac_compiler_gnu=$ac_cv_c_compiler_gnu
+-
+-
+-
+-LIBS="$PTHREAD_LIBS $LIBS"
+-CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+-
+
+ { echo "$as_me:$LINENO: checking for library containing gethostbyname" >&5
+ echo $ECHO_N "checking for library containing gethostbyname... $ECHO_C" >&6; }
diff --git a/package/dnsmasq/Makefile b/package/dnsmasq/Makefile
new file mode 100644
index 000000000..4ad0f3774
--- /dev/null
+++ b/package/dnsmasq/Makefile
@@ -0,0 +1,88 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=dnsmasq
+PKG_VERSION:=2.62
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq
+PKG_MD5SUM:=f47e5cb8f5bac6343f24b2dbe317ab40
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/dnsmasq/Default
+ SECTION:=net
+ CATEGORY:=Base system
+ TITLE:=A lightweight DNS and DHCP server
+ URL:=http://www.thekelleys.org.uk/dnsmasq/
+endef
+
+define Package/dnsmasq
+$(call Package/dnsmasq/Default)
+ VARIANT:=nodhcpv6
+endef
+
+define Package/dnsmasq-dhcpv6
+$(call Package/dnsmasq/Default)
+ TITLE += (with DHCPv6 support)
+ DEPENDS:=@IPV6 +kmod-ipv6
+ VARIANT:=dhcpv6
+endef
+
+define Package/dnsmasq/description
+ It is intended to provide coupled DNS and DHCP service to a LAN.
+endef
+
+define Package/dnsmasq-dhcpv6/description
+$(call Package/dnsmasq/description)
+
+This is a variant with DHCPv6 support
+endef
+
+define Package/dnsmasq/conffiles
+/etc/config/dhcp
+/etc/dnsmasq.conf
+endef
+
+Package/dnsmasq-dhcpv6/conffiles = $(Package/dnsmasq/conffiles)
+
+TARGET_CFLAGS += \
+ -ffunction-sections -fdata-sections \
+ $(if $(CONFIG_IPV6),,-DNO_IPV6)
+
+ifeq ($(BUILD_VARIANT),nodhcpv6)
+ TARGET_CFLAGS += -DNO_DHCP6
+endif
+
+MAKE_FLAGS := \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ LDFLAGS="-Wl,--gc-sections" \
+ PREFIX="/usr"
+
+define Package/dnsmasq/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(CP) $(PKG_INSTALL_DIR)/usr/sbin/dnsmasq $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/dhcp.conf $(1)/etc/config/dhcp
+ $(INSTALL_DATA) ./files/dnsmasq.conf $(1)/etc/dnsmasq.conf
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/dnsmasq.init $(1)/etc/init.d/dnsmasq
+endef
+
+Package/dnsmasq-dhcpv6/install = $(Package/dnsmasq/install)
+
+$(eval $(call BuildPackage,dnsmasq))
+$(eval $(call BuildPackage,dnsmasq-dhcpv6))
diff --git a/package/dnsmasq/files/dhcp.conf b/package/dnsmasq/files/dhcp.conf
new file mode 100644
index 000000000..660b06ad4
--- /dev/null
+++ b/package/dnsmasq/files/dhcp.conf
@@ -0,0 +1,31 @@
+config dnsmasq
+ option domainneeded 1
+ option boguspriv 1
+ option filterwin2k 0 # enable for dial on demand
+ option localise_queries 1
+ option rebind_protection 1 # disable if upstream must serve RFC1918 addresses
+ option rebind_localhost 1 # enable for RBL checking and similar services
+ #list rebind_domain example.lan # whitelist RFC1918 responses for domains
+ option local '/lan/'
+ option domain 'lan'
+ option expandhosts 1
+ option nonegcache 0
+ option authoritative 1
+ option readethers 1
+ option leasefile '/tmp/dhcp.leases'
+ option resolvfile '/tmp/resolv.conf.auto'
+ #list server '/mycompany.local/1.2.3.4'
+ #option nonwildcard 1
+ #list interface br-lan
+ #list notinterface lo
+ #list bogusnxdomain '64.94.110.11'
+
+config dhcp lan
+ option interface lan
+ option start 100
+ option limit 150
+ option leasetime 12h
+
+config dhcp wan
+ option interface wan
+ option ignore 1
diff --git a/package/dnsmasq/files/dnsmasq.conf b/package/dnsmasq/files/dnsmasq.conf
new file mode 100644
index 000000000..bf5816be5
--- /dev/null
+++ b/package/dnsmasq/files/dnsmasq.conf
@@ -0,0 +1,37 @@
+# Change the following lines if you want dnsmasq to serve SRV
+# records.
+# You may add multiple srv-host lines.
+# The fields are <name>,<target>,<port>,<priority>,<weight>
+
+# A SRV record sending LDAP for the example.com domain to
+# ldapserver.example.com port 289
+#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389
+
+# Two SRV records for LDAP, each with different priorities
+#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389,1
+#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389,2
+
+# A SRV record indicating that there is no LDAP server for the domain
+# example.com
+#srv-host=_ldap._tcp.example.com
+
+# The following line shows how to make dnsmasq serve an arbitrary PTR
+# record. This is useful for DNS-SD.
+# The fields are <name>,<target>
+#ptr-record=_http._tcp.dns-sd-services,"New Employee Page._http._tcp.dns-sd-services"
+
+# Change the following lines to enable dnsmasq to serve TXT records.
+# These are used for things like SPF and zeroconf.
+# The fields are <name>,<text>,<text>...
+
+#Example SPF.
+#txt-record=example.com,"v=spf1 a -all"
+
+#Example zeroconf
+#txt-record=_http._tcp.example.com,name=value,paper=A4
+
+# Provide an alias for a "local" DNS name. Note that this _only_ works
+# for targets which are names from DHCP or /etc/hosts. Give host
+# "bert" another name, bertrand
+# The fields are <cname>,<target>
+#cname=bertand,bert
diff --git a/package/dnsmasq/files/dnsmasq.init b/package/dnsmasq/files/dnsmasq.init
new file mode 100644
index 000000000..85c22c374
--- /dev/null
+++ b/package/dnsmasq/files/dnsmasq.init
@@ -0,0 +1,529 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2007-2012 OpenWrt.org
+
+START=60
+
+SERVICE_USE_PID=1
+
+DNS_SERVERS=""
+DOMAIN=""
+
+ADD_LOCAL_DOMAIN=1
+ADD_LOCAL_HOSTNAME=1
+
+CONFIGFILE="/var/etc/dnsmasq.conf"
+
+xappend() {
+ local value="$1"
+
+ echo "${value#--}" >> $CONFIGFILE
+}
+
+dhcp_calc() {
+ local ip="$1"
+ local res=0
+
+ while [ -n "$ip" ]; do
+ part="${ip%%.*}"
+ res="$(($res * 256))"
+ res="$(($res + $part))"
+ [ "${ip%.*}" != "$ip" ] && ip="${ip#*.}" || ip=
+ done
+ echo "$res"
+}
+
+append_bool() {
+ local section="$1"
+ local option="$2"
+ local value="$3"
+ local _loctmp
+ config_get_bool _loctmp "$section" "$option" 0
+ [ $_loctmp -gt 0 ] && xappend "$value"
+}
+
+append_parm() {
+ local section="$1"
+ local option="$2"
+ local switch="$3"
+ local _loctmp
+ config_get _loctmp "$section" "$option"
+ [ -z "$_loctmp" ] && return 0
+ xappend "$switch=$_loctmp"
+}
+
+append_server() {
+ xappend "--server=$1"
+}
+
+append_address() {
+ xappend "--address=$1"
+}
+
+append_interface() {
+ local ifname=$(uci_get_state network "$1" ifname "$1")
+ xappend "--interface=$ifname"
+}
+
+append_notinterface() {
+ local ifname=$(uci_get_state network "$1" ifname "$1")
+ xappend "--except-interface=$ifname"
+}
+
+append_addnhosts() {
+ xappend "--addn-hosts=$1"
+}
+
+append_bogusnxdomain() {
+ xappend "--bogus-nxdomain=$1"
+}
+
+dnsmasq() {
+ local cfg="$1"
+ append_bool "$cfg" authoritative "--dhcp-authoritative"
+ append_bool "$cfg" nodaemon "--no-daemon"
+ append_bool "$cfg" domainneeded "--domain-needed"
+ append_bool "$cfg" filterwin2k "--filterwin2k"
+ append_bool "$cfg" nohosts "--no-hosts"
+ append_bool "$cfg" nonegcache "--no-negcache"
+ append_bool "$cfg" strictorder "--strict-order"
+ append_bool "$cfg" logqueries "--log-queries"
+ append_bool "$cfg" noresolv "--no-resolv"
+ append_bool "$cfg" localise_queries "--localise-queries"
+ append_bool "$cfg" readethers "--read-ethers"
+ append_bool "$cfg" dbus "--enable-dbus"
+ append_bool "$cfg" boguspriv "--bogus-priv"
+ append_bool "$cfg" expandhosts "--expand-hosts"
+ append_bool "$cfg" enable_tftp "--enable-tftp"
+ append_bool "$cfg" nonwildcard "--bind-interfaces"
+ append_bool "$cfg" fqdn "--dhcp-fqdn"
+
+ append_parm "$cfg" dhcpscript "--dhcp-script"
+ append_parm "$cfg" cachesize "--cache-size"
+ append_parm "$cfg" dnsforwardmax "--dns-forward-max"
+ append_parm "$cfg" port "--port"
+ append_parm "$cfg" ednspacket_max "--edns-packet-max"
+ append_parm "$cfg" dhcpleasemax "--dhcp-lease-max"
+ append_parm "$cfg" "queryport" "--query-port"
+ append_parm "$cfg" "domain" "--domain"
+ append_parm "$cfg" "local" "--server"
+ config_list_foreach "$cfg" "server" append_server
+ config_list_foreach "$cfg" "address" append_address
+ config_list_foreach "$cfg" "interface" append_interface
+ config_list_foreach "$cfg" "notinterface" append_notinterface
+ config_list_foreach "$cfg" "addnhosts" append_addnhosts
+ config_list_foreach "$cfg" "bogusnxdomain" append_bogusnxdomain
+ append_parm "$cfg" "leasefile" "--dhcp-leasefile"
+ append_parm "$cfg" "resolvfile" "--resolv-file"
+ append_parm "$cfg" "tftp_root" "--tftp-root"
+ append_parm "$cfg" "dhcp_boot" "--dhcp-boot"
+ append_parm "$cfg" "local_ttl" "--local-ttl"
+
+ config_get DOMAIN "$cfg" domain
+
+ config_get_bool ADD_LOCAL_DOMAIN "$cfg" add_local_domain 1
+ config_get_bool ADD_LOCAL_HOSTNAME "$cfg" add_local_hostname 1
+
+ config_get_bool readethers "$cfg" readethers
+ [ "$readethers" = "1" -a \! -e "/etc/ethers" ] && touch /etc/ethers
+
+ config_get leasefile $cfg leasefile
+ [ -n "$leasefile" -a \! -e "$leasefile" ] && touch "$leasefile"
+ config_get_bool cachelocal "$cfg" cachelocal 1
+
+ config_get hostsfile "$cfg" dhcphostsfile
+ [ -e "$hostsfile" ] && xappend "--dhcp-hostsfile=$hostsfile"
+
+ local rebind
+ config_get_bool rebind "$cfg" rebind_protection 1
+ [ $rebind -gt 0 ] && {
+ logger -t dnsmasq \
+ "DNS rebinding protection is active," \
+ "will discard upstream RFC1918 responses!"
+ xappend "--stop-dns-rebind"
+
+ local rebind_localhost
+ config_get_bool rebind_localhost "$cfg" rebind_localhost 0
+ [ $rebind_localhost -gt 0 ] && {
+ logger -t dnsmasq "Allowing 127.0.0.0/8 responses"
+ xappend "--rebind-localhost-ok"
+ }
+
+ append_rebind_domain() {
+ logger -t dnsmasq "Allowing RFC1918 responses for domain $1"
+ xappend "--rebind-domain-ok=$1"
+ }
+
+ config_list_foreach "$cfg" rebind_domain append_rebind_domain
+ }
+
+ dhcp_option_add "$cfg" "" 0
+
+ echo >> $CONFIGFILE
+}
+
+dhcp_subscrid_add() {
+ local cfg="$1"
+
+ config_get networkid "$cfg" networkid
+ [ -n "$networkid" ] || return 0
+
+ config_get subscriberid "$cfg" subscriberid
+ [ -n "$subscriberid" ] || return 0
+
+ xappend "--dhcp-subscrid=$networkid,$subscriberid"
+
+ config_get_bool force "$cfg" force 0
+
+ dhcp_option_add "$cfg" "$networkid" "$force"
+}
+
+dhcp_remoteid_add() {
+ local cfg="$1"
+
+ config_get networkid "$cfg" networkid
+ [ -n "$networkid" ] || return 0
+
+ config_get remoteid "$cfg" remoteid
+ [ -n "$remoteid" ] || return 0
+
+ xappend "--dhcp-remoteid=$networkid,$remoteid"
+
+ config_get_bool force "$cfg" force 0
+
+ dhcp_option_add "$cfg" "$networkid" "$force"
+}
+
+dhcp_circuitid_add() {
+ local cfg="$1"
+
+ config_get networkid "$cfg" networkid
+ [ -n "$networkid" ] || return 0
+
+ config_get circuitid "$cfg" circuitid
+ [ -n "$circuitid" ] || return 0
+
+ xappend "--dhcp-circuitid=$networkid,$circuitid"
+
+ config_get_bool force "$cfg" force 0
+
+ dhcp_option_add "$cfg" "$networkid" "$force"
+}
+
+dhcp_userclass_add() {
+ local cfg="$1"
+
+ config_get networkid "$cfg" networkid
+ [ -n "$networkid" ] || return 0
+
+ config_get userclass "$cfg" userclass
+ [ -n "$userclass" ] || return 0
+
+ xappend "--dhcp-userclass=$networkid,$userclass"
+
+ config_get_bool force "$cfg" force 0
+
+ dhcp_option_add "$cfg" "$networkid" "$force"
+}
+
+dhcp_vendorclass_add() {
+ local cfg="$1"
+
+ config_get networkid "$cfg" networkid
+ [ -n "$networkid" ] || return 0
+
+ config_get vendorclass "$cfg" vendorclass
+ [ -n "$vendorclass" ] || return 0
+
+ xappend "--dhcp-vendorclass=$networkid,$vendorclass"
+
+ config_get_bool force "$cfg" force 0
+
+ dhcp_option_add "$cfg" "$networkid" "$force"
+}
+
+dhcp_host_add() {
+ local cfg="$1"
+
+ config_get_bool force "$cfg" force 0
+
+ config_get networkid "$cfg" networkid
+ [ -n "$networkid" ] && dhcp_option_add "$cfg" "$networkid" "$force"
+
+ config_get name "$cfg" name
+ config_get ip "$cfg" ip
+ [ -n "$ip" -o -n "$name" ] || return 0
+
+ macs=""
+ config_get mac "$cfg" mac
+ for m in $mac; do append macs "$m" ","; done
+ [ -n "$macs" ] || return 0
+
+ config_get tag "$cfg" tag
+
+ xappend "--dhcp-host=$macs${networkid:+,net:$networkid}${tag:+,set:$tag}${ip:+,$ip}${name:+,$name}"
+}
+
+dhcp_tag_add() {
+ local cfg="$1"
+
+ tag="$cfg"
+
+ [ -n "$tag" ] || return 0
+
+ config_get_bool force "$cfg" force 0
+ [ "$force" = "0" ] && force=
+
+ config_get option "$cfg" dhcp_option
+ for o in $option; do
+ xappend "--dhcp-option${force:+-force}=tag:$tag,$o"
+ done
+}
+
+dhcp_mac_add() {
+ local cfg="$1"
+
+ config_get networkid "$cfg" networkid
+ [ -n "$networkid" ] || return 0
+
+ config_get mac "$cfg" mac
+ [ -n "$mac" ] || return 0
+
+ xappend "--dhcp-mac=$networkid,$mac"
+
+ dhcp_option_add "$cfg" "$networkid"
+}
+
+dhcp_boot_add() {
+ local cfg="$1"
+
+ config_get networkid "$cfg" networkid
+
+ config_get filename "$cfg" filename
+ [ -n "$filename" ] || return 0
+
+ config_get servername "$cfg" servername
+ [ -n "$servername" ] || return 0
+
+ config_get serveraddress "$cfg" serveraddress
+ [ -n "$serveraddress" ] || return 0
+
+ xappend "--dhcp-boot=${networkid:+net:$networkid,}$filename,$servername,$serveraddress"
+
+ config_get_bool force "$cfg" force 0
+
+ dhcp_option_add "$cfg" "$networkid" "$force"
+}
+
+
+dhcp_add() {
+ local cfg="$1"
+ config_get net "$cfg" interface
+ [ -n "$net" ] || return 0
+
+ config_get networkid "$cfg" networkid
+ [ -n "$networkid" ] || networkid="$net"
+
+ config_get ifname "$net" ifname
+ [ -n "$ifname" ] || return 0
+
+ config_get dnsserver "$net" dns
+ [ "$cachelocal" = "0" -a -n "$dnsserver" ] && {
+ DNS_SERVERS="$DNS_SERVERS $dnsserver"
+ }
+
+ append_bool "$cfg" ignore "--no-dhcp-interface=$ifname" && return 0
+
+ config_get proto "$net" proto
+ [ static = "$proto" ] || return 0
+
+ config_get ipaddr "$net" ipaddr
+ config_get netmask "$cfg" netmask
+ [ -n "$netmask" ] || config_get netmask "$net" netmask
+
+ #check for an already active dhcp server on the interface, unless 'force' is set
+ config_get_bool force "$cfg" force 0
+ [ $force -gt 0 ] || {
+ udhcpc -n -q -s /bin/true -t 1 -i $ifname >&- && {
+ logger -t dnsmasq \
+ "found already running DHCP-server on interface '$ifname'" \
+ "refusing to start, use 'option force 1' to override"
+ return 0
+ }
+ }
+
+ config_get start "$cfg" start
+ config_get limit "$cfg" limit
+ config_get leasetime "$cfg" leasetime
+ config_get options "$cfg" options
+ config_get_bool dynamicdhcp "$cfg" dynamicdhcp 1
+
+ leasetime="${leasetime:-12h}"
+ start="$(dhcp_calc "${start:-100}")"
+ limit="${limit:-150}"
+ [ "$limit" -gt 0 ] && limit=$((limit-1))
+ eval "$(ipcalc.sh $ipaddr $netmask $start $limit)"
+ if [ "$dynamicdhcp" = "0" ]; then END="static"; fi
+ xappend "--dhcp-range=$networkid,$START,$END,$NETMASK,$leasetime${options:+ $options}"
+
+ dhcp_option_add "$cfg" "$networkid"
+}
+
+dhcp_option_add() {
+ local cfg="$1"
+ local networkid="$2"
+ local force="$3"
+
+ [ "$force" = "0" ] && force=
+
+ config_get dhcp_option "$cfg" dhcp_option
+ for o in $dhcp_option; do
+ xappend "--dhcp-option${force:+-force}=${networkid:+$networkid,}$o"
+ done
+
+}
+
+dhcp_domain_add() {
+ local cfg="$1"
+ local ip name names
+
+ config_get names "$cfg" name "$2"
+ [ -n "$names" ] || return 0
+
+ config_get ip "$cfg" ip "$3"
+ [ -n "$ip" ] || return 0
+
+ local oIFS="$IFS"; IFS="."; set -- $ip; IFS="$oIFS"
+ local raddr="${4:+$4.$3.$2.$1.in-addr.arpa}"
+
+ for name in $names; do
+ local fqdn="$name"
+
+ [ "${fqdn%.*}" == "$fqdn" ] && \
+ fqdn="$fqdn${DOMAIN:+.$DOMAIN}"
+
+ xappend "--address=/$fqdn/$ip"
+
+ [ -n "$raddr" ] && {
+ xappend "--ptr-record=$raddr,$fqdn"
+ raddr=""
+ }
+ done
+}
+
+dhcp_srv_add() {
+ local cfg="$1"
+
+ config_get srv "$cfg" srv
+ [ -n "$srv" ] || return 0
+
+ config_get target "$cfg" target
+ [ -n "$target" ] || return 0
+
+ config_get port "$cfg" port
+ [ -n "$port" ] || return 0
+
+ config_get class "$cfg" class
+ config_get weight "$cfg" weight
+
+ local service="$srv,$target,$port${class:+,$class${weight:+,$weight}}"
+
+ xappend "--srv-host=$service"
+}
+
+dhcp_mx_add() {
+ local cfg="$1"
+ local domain relay pref
+
+ config_get domain "$cfg" domain
+ [ -n "$domain" ] || return 0
+
+ config_get relay "$cfg" relay
+ [ -n "$relay" ] || return 0
+
+ config_get pref "$cfg" pref 0
+
+ local service="$domain,$relay,$pref"
+
+ xappend "--mx-host=$service"
+}
+
+dhcp_cname_add() {
+ local cfg="$1"
+ local cname target
+
+ config_get cname "$cfg" cname
+ [ -n "$cname" ] || return 0
+
+ config_get target "$cfg" target
+ [ -n "$target" ] || return 0
+
+ xappend "--cname=${cname},${target}"
+}
+
+start() {
+ include /lib/network
+ scan_interfaces
+
+ local lanaddr
+ config_get lanaddr "lan" ipaddr
+
+ config_load dhcp
+
+ # before we can call xappend
+ mkdir -p $(dirname $CONFIGFILE)
+
+ echo "# auto-generated config file from /etc/config/dhcp" > $CONFIGFILE
+
+ # if we did this last, we could override auto-generated config
+ [ -f /etc/dnsmasq.conf ] && {
+ xappend "--conf-file=/etc/dnsmasq.conf"
+ }
+
+ args=""
+ config_foreach dnsmasq dnsmasq
+ config_foreach dhcp_host_add host
+ echo >> $CONFIGFILE
+ config_foreach dhcp_boot_add boot
+ config_foreach dhcp_mac_add mac
+ config_foreach dhcp_tag_add tag
+ config_foreach dhcp_vendorclass_add vendorclass
+ config_foreach dhcp_userclass_add userclass
+ config_foreach dhcp_circuitid_add circuitid
+ config_foreach dhcp_remoteid_add remoteid
+ config_foreach dhcp_subscrid_add subscrid
+ config_foreach dhcp_domain_add domain
+ echo >> $CONFIGFILE
+ config_foreach dhcp_srv_add srvhost
+ config_foreach dhcp_mx_add mxhost
+ echo >> $CONFIGFILE
+ config_foreach dhcp_add dhcp
+ echo >> $CONFIGFILE
+ config_foreach dhcp_cname_add cname
+ echo >> $CONFIGFILE
+
+ # add own hostname
+ [ $ADD_LOCAL_HOSTNAME -eq 1 ] && [ -n "$lanaddr" ] && {
+ local hostname="$(uci_get system.@system[0].hostname)"
+ dhcp_domain_add "" "${hostname:-OpenWrt}" "$lanaddr"
+ }
+
+ service_start /usr/sbin/dnsmasq -C $CONFIGFILE && {
+ rm -f /tmp/resolv.conf
+ [ $ADD_LOCAL_DOMAIN -eq 1 ] && [ -n "$DOMAIN" ] && {
+ echo "search $DOMAIN" >> /tmp/resolv.conf
+ }
+ DNS_SERVERS="$DNS_SERVERS 127.0.0.1"
+ for DNS_SERVER in $DNS_SERVERS ; do
+ echo "nameserver $DNS_SERVER" >> /tmp/resolv.conf
+ done
+ }
+}
+
+stop() {
+ service_stop /usr/sbin/dnsmasq && {
+ [ -f /tmp/resolv.conf ] && {
+ rm -f /tmp/resolv.conf
+ ln -s /tmp/resolv.conf.auto /tmp/resolv.conf
+ }
+ }
+}
diff --git a/package/dnsmasq/patches/0001-Set-prefix-on-link-bit-in-RAs.patch b/package/dnsmasq/patches/0001-Set-prefix-on-link-bit-in-RAs.patch
new file mode 100644
index 000000000..8ead9afa5
--- /dev/null
+++ b/package/dnsmasq/patches/0001-Set-prefix-on-link-bit-in-RAs.patch
@@ -0,0 +1,42 @@
+From fd05f127909bbf4f6983a4de2dcb611947488dee Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Sun, 12 Aug 2012 17:48:50 +0100
+Subject: [PATCH] Set prefix on-link bit in RAs
+
+---
+ CHANGELOG | 3 +++
+ src/radv.c | 4 ++--
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 8828694..e1daeef 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -45,6 +45,9 @@ version 2.63
+ uk.org.thekelleys.dnsmasq. Thanks to Mathieu
+ Trudel-Lapierre for the patch.
+
++ Set the "prefix on-link" bit in Router
++ Advertisements. Thanks to Gui Iribarren for the patch.
++
+
+ version 2.62
+ Update German translation. Thanks to Conrad Kostecki.
+diff --git a/src/radv.c b/src/radv.c
+index a3e691a..d1f5268 100644
+--- a/src/radv.c
++++ b/src/radv.c
+@@ -412,8 +412,8 @@ static int add_prefixes(struct in6_addr *local, int prefix,
+ opt->type = ICMP6_OPT_PREFIX;
+ opt->len = 4;
+ opt->prefix_len = prefix;
+- /* autonomous only if we're not doing dhcp */
+- opt->flags = do_slaac ? 0x40 : 0x00;
++ /* autonomous only if we're not doing dhcp, always set "on-link" */
++ opt->flags = do_slaac ? 0xC0 : 0x80;
+ opt->valid_lifetime = htonl(time);
+ opt->preferred_lifetime = htonl(deprecate ? 0 : time);
+ opt->reserved = 0;
+--
+1.7.10.GIT
+
diff --git a/package/dnsmasq/patches/100-fix-dhcp-no-address-warning.patch b/package/dnsmasq/patches/100-fix-dhcp-no-address-warning.patch
new file mode 100644
index 000000000..d108a7d3b
--- /dev/null
+++ b/package/dnsmasq/patches/100-fix-dhcp-no-address-warning.patch
@@ -0,0 +1,49 @@
+--- a/src/dhcp.c
++++ b/src/dhcp.c
+@@ -134,7 +134,7 @@ void dhcp_packet(time_t now, int pxe_fd)
+ struct iovec iov;
+ ssize_t sz;
+ int iface_index = 0, unicast_dest = 0, is_inform = 0;
+- struct in_addr iface_addr;
++ struct in_addr iface_addr, *addrp = NULL;
+ struct iface_param parm;
+ #ifdef HAVE_LINUX_NETWORK
+ struct arpreq arp_req;
+@@ -246,11 +246,9 @@ void dhcp_packet(time_t now, int pxe_fd)
+
+ ifr.ifr_addr.sa_family = AF_INET;
+ if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) != -1 )
+- iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
+- else
+ {
+- my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
+- return;
++ addrp = &iface_addr;
++ iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
+ }
+
+ for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
+@@ -272,7 +270,7 @@ void dhcp_packet(time_t now, int pxe_fd)
+ parm.current = NULL;
+ parm.ind = iface_index;
+
+- if (!iface_check(AF_INET, (struct all_addr *)&iface_addr, ifr.ifr_name))
++ if (!iface_check(AF_INET, (struct all_addr *)addrp, ifr.ifr_name))
+ {
+ /* If we failed to match the primary address of the interface, see if we've got a --listen-address
+ for a secondary */
+@@ -291,7 +289,13 @@ void dhcp_packet(time_t now, int pxe_fd)
+ there is more than one address on the interface in the same subnet */
+ complete_context(match.addr, iface_index, match.netmask, match.broadcast, &parm);
+ }
+-
++
++ if (!addrp)
++ {
++ my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
++ return;
++ }
++
+ if (!iface_enumerate(AF_INET, &parm, complete_context))
+ return;
+
diff --git a/package/dropbear/Makefile b/package/dropbear/Makefile
new file mode 100644
index 000000000..63cf86e14
--- /dev/null
+++ b/package/dropbear/Makefile
@@ -0,0 +1,114 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=dropbear
+PKG_VERSION:=2011.54
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:= \
+ http://matt.ucc.asn.au/dropbear/releases/ \
+ http://www.mirrors.wiretapped.net/security/cryptography/apps/ssh/dropbear/
+PKG_MD5SUM:=c627ffe09570fad7aa94d8eac2b9320c
+
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/dropbear/Default
+ URL:=http://matt.ucc.asn.au/dropbear/
+endef
+
+define Package/dropbear
+ $(call Package/dropbear/Default)
+ SECTION:=net
+ CATEGORY:=Base system
+ TITLE:=Small SSH2 client/server
+endef
+
+define Package/dropbear/description
+ A small SSH2 server/client designed for small memory environments.
+endef
+
+define Package/dropbear/conffiles
+/etc/dropbear/dropbear_rsa_host_key
+/etc/dropbear/dropbear_dss_host_key
+/etc/config/dropbear
+endef
+
+define Package/dropbearconvert
+ $(call Package/dropbear/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Utility for converting SSH keys
+endef
+
+CONFIGURE_ARGS += \
+ --with-shared \
+ --disable-pam \
+ --enable-openpty \
+ --enable-syslog \
+ $(if $(CONFIG_SHADOW_PASSWORDS),,--disable-shadow) \
+ --disable-lastlog \
+ --disable-utmp \
+ --disable-utmpx \
+ --disable-wtmp \
+ --disable-wtmpx \
+ --disable-loginfunc \
+ --disable-pututline \
+ --disable-pututxline \
+ --disable-zlib \
+ --enable-bundled-libtom
+
+TARGET_CFLAGS += -DARGTYPE=3 -ffunction-sections -fdata-sections
+TARGET_LDFLAGS += -Wl,--gc-sections
+
+define Build/Configure
+ $(SED) 's,^/\* #define PKG_MULTI.*,#define PKG_MULTI,g' $(PKG_BUILD_DIR)/options.h
+ $(SED) 's,^#define DO_HOST_LOOKUP,/* & */,g' $(PKG_BUILD_DIR)/options.h
+ $(call Build/Configure/Default)
+endef
+
+define Build/Compile
+ +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ LD="$(TARGET_CC)" \
+ PROGRAMS="dropbear dbclient dropbearkey scp" \
+ MULTI=1 SCPPROGRESS=1
+ +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ LD="$(TARGET_CC)" \
+ PROGRAMS="dropbearconvert"
+endef
+
+define Package/dropbear/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/dropbearmulti $(1)/usr/sbin/dropbear
+ $(INSTALL_DIR) $(1)/usr/bin
+ ln -sf ../sbin/dropbear $(1)/usr/bin/scp
+ ln -sf ../sbin/dropbear $(1)/usr/bin/ssh
+ ln -sf ../sbin/dropbear $(1)/usr/bin/dbclient
+ ln -sf ../sbin/dropbear $(1)/usr/bin/dropbearkey
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/dropbear.config $(1)/etc/config/dropbear
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/dropbear.init $(1)/etc/init.d/dropbear
+ $(INSTALL_DIR) $(1)/usr/lib/opkg/info
+ $(INSTALL_DIR) $(1)/etc/dropbear
+ touch $(1)/etc/dropbear/dropbear_rsa_host_key
+ touch $(1)/etc/dropbear/dropbear_dss_host_key
+endef
+
+define Package/dropbearconvert/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/dropbearconvert $(1)/usr/bin/dropbearconvert
+endef
+
+$(eval $(call BuildPackage,dropbear))
+$(eval $(call BuildPackage,dropbearconvert))
diff --git a/package/dropbear/files/dropbear.config b/package/dropbear/files/dropbear.config
new file mode 100644
index 000000000..2139ba0bb
--- /dev/null
+++ b/package/dropbear/files/dropbear.config
@@ -0,0 +1,5 @@
+config dropbear
+ option PasswordAuth 'on'
+ option RootPasswordAuth 'on'
+ option Port '22'
+# option BannerFile '/etc/banner'
diff --git a/package/dropbear/files/dropbear.init b/package/dropbear/files/dropbear.init
new file mode 100755
index 000000000..c909d2896
--- /dev/null
+++ b/package/dropbear/files/dropbear.init
@@ -0,0 +1,191 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2006 Carlos Sobrinho
+
+START=50
+STOP=50
+
+SERVICE_USE_PID=1
+
+NAME=dropbear
+PROG=/usr/sbin/dropbear
+PIDCOUNT=0
+EXTRA_COMMANDS="killclients"
+EXTRA_HELP=" killclients Kill ${NAME} processes except servers and yourself"
+
+dropbear_start()
+{
+ append_ports()
+ {
+ local ifname="$1"
+ local port="$2"
+
+ grep -qs "^ *$ifname:" /proc/net/dev || {
+ append args "-p $port"
+ return
+ }
+
+ for addr in $(
+ ifconfig "$ifname" | sed -ne '
+ /addr: *fe[89ab][0-9a-f]:/d
+ s/.* addr: *\([0-9a-f:\.]*\).*/\1/p
+ '
+ ); do
+ append args "-p $addr:$port"
+ done
+ }
+
+
+ local section="$1"
+
+ # check if section is enabled (default)
+ local enabled
+ config_get_bool enabled "${section}" enable 1
+ [ "${enabled}" -eq 0 ] && return 1
+
+ # verbose parameter
+ local verbosed
+ config_get_bool verbosed "${section}" verbose 0
+
+ # increase pid file count to handle multiple instances correctly
+ PIDCOUNT="$(( ${PIDCOUNT} + 1))"
+
+ # prepare parameters (initialise with pid file)
+ local pid_file="/var/run/${NAME}.${PIDCOUNT}.pid"
+ local args="-P $pid_file"
+ local val
+ # A) password authentication
+ config_get_bool val "${section}" PasswordAuth 1
+ [ "${val}" -eq 0 ] && append args "-s"
+ # B) listen interface and port
+ local port
+ local interface
+ config_get interface "${section}" Interface
+ config_get interface "${interface}" ifname "$interface"
+ config_get port "${section}" Port 22
+ append_ports "$interface" "$port"
+ # C) banner file
+ config_get val "${section}" BannerFile
+ [ -f "${val}" ] && append args "-b ${val}"
+ # D) gatewayports
+ config_get_bool val "${section}" GatewayPorts 0
+ [ "${val}" -eq 1 ] && append args "-a"
+ # E) root password authentication
+ config_get_bool val "${section}" RootPasswordAuth 1
+ [ "${val}" -eq 0 ] && append args "-g"
+ # F) root login
+ config_get_bool val "${section}" RootLogin 1
+ [ "${val}" -eq 0 ] && append args "-w"
+ # G) host keys
+ config_get val "${section}" rsakeyfile
+ [ -f "${val}" ] && append args "-r ${val}"
+ config_get val "${section}" dsskeyfile
+ [ -f "${val}" ] && append args "-d ${val}"
+
+ # execute program and return its exit code
+ [ "${verbosed}" -ne 0 ] && echo "${initscript}: section ${section} starting ${PROG} ${args}"
+ SERVICE_PID_FILE="$pid_file" service_start ${PROG} ${args}
+}
+
+keygen()
+{
+ for keytype in rsa dss; do
+ # check for keys
+ key=dropbear/dropbear_${keytype}_host_key
+ [ -f /tmp/$key -o -s /etc/$key ] || {
+ # generate missing keys
+ mkdir -p /tmp/dropbear
+ [ -x /usr/bin/dropbearkey ] && {
+ /usr/bin/dropbearkey -t $keytype -f /tmp/$key 2>&- >&- && exec /etc/rc.common "$initscript" start
+ } &
+ exit 0
+ }
+ done
+
+ lock /tmp/.switch2jffs
+ mkdir -p /etc/dropbear
+ mv /tmp/dropbear/dropbear_* /etc/dropbear/
+ lock -u /tmp/.switch2jffs
+ chown root /etc/dropbear
+ chmod 0700 /etc/dropbear
+}
+
+start()
+{
+ [ -s /etc/dropbear/dropbear_rsa_host_key -a \
+ -s /etc/dropbear/dropbear_dss_host_key ] || keygen
+
+ include /lib/network
+ scan_interfaces
+ config_load "${NAME}"
+ config_foreach dropbear_start dropbear
+}
+
+stop()
+{
+ local pid_file pid_files
+
+ pid_files=`ls /var/run/${NAME}.*.pid 2>/dev/null`
+
+ [ -z "$pid_files" ] && return 1
+
+ for pid_file in $pid_files; do
+ SERVICE_PID_FILE="$pid_file" service_stop ${PROG} && {
+ rm -f ${pid_file}
+ }
+ done
+}
+
+killclients()
+{
+ local ignore=''
+ local server
+ local pid
+
+ # if this script is run from inside a client session, then ignore that session
+ pid="$$"
+ while [ "${pid}" -ne 0 ]
+ do
+ # get parent process id
+ pid=`cut -d ' ' -f 4 "/proc/${pid}/stat"`
+ [ "${pid}" -eq 0 ] && break
+
+ # check if client connection
+ grep -F -q -e "${PROG}" "/proc/${pid}/cmdline" && {
+ append ignore "${pid}"
+ break
+ }
+ done
+
+ # get all server pids that should be ignored
+ for server in `cat /var/run/${NAME}.*.pid`
+ do
+ append ignore "${server}"
+ done
+
+ # get all running pids and kill client connections
+ local skip
+ for pid in `pidof "${NAME}"`
+ do
+ # check if correct program, otherwise process next pid
+ grep -F -q -e "${PROG}" "/proc/${pid}/cmdline" || {
+ continue
+ }
+
+ # check if pid should be ignored (servers, ourself)
+ skip=0
+ for server in ${ignore}
+ do
+ if [ "${pid}" == "${server}" ]
+ then
+ skip=1
+ break
+ fi
+ done
+ [ "${skip}" -ne 0 ] && continue
+
+ # kill process
+ echo "${initscript}: Killing ${pid}..."
+ kill -KILL ${pid}
+ done
+}
diff --git a/package/dropbear/patches/100-pubkey_path.patch b/package/dropbear/patches/100-pubkey_path.patch
new file mode 100644
index 000000000..c1802f51e
--- /dev/null
+++ b/package/dropbear/patches/100-pubkey_path.patch
@@ -0,0 +1,91 @@
+--- a/svr-authpubkey.c
++++ b/svr-authpubkey.c
+@@ -209,17 +209,21 @@ static int checkpubkey(unsigned char* al
+ goto out;
+ }
+
+- /* we don't need to check pw and pw_dir for validity, since
+- * its been done in checkpubkeyperms. */
+- len = strlen(ses.authstate.pw_dir);
+- /* allocate max required pathname storage,
+- * = path + "/.ssh/authorized_keys" + '\0' = pathlen + 22 */
+- filename = m_malloc(len + 22);
+- snprintf(filename, len + 22, "%s/.ssh/authorized_keys",
+- ses.authstate.pw_dir);
+-
+- /* open the file */
+- authfile = fopen(filename, "r");
++ if (ses.authstate.pw_uid != 0) {
++ /* we don't need to check pw and pw_dir for validity, since
++ * its been done in checkpubkeyperms. */
++ len = strlen(ses.authstate.pw_dir);
++ /* allocate max required pathname storage,
++ * = path + "/.ssh/authorized_keys" + '\0' = pathlen + 22 */
++ filename = m_malloc(len + 22);
++ snprintf(filename, len + 22, "%s/.ssh/authorized_keys",
++ ses.authstate.pw_dir);
++
++ /* open the file */
++ authfile = fopen(filename, "r");
++ } else {
++ authfile = fopen("/etc/dropbear/authorized_keys","r");
++ }
+ if (authfile == NULL) {
+ goto out;
+ }
+@@ -372,26 +376,35 @@ static int checkpubkeyperms() {
+ goto out;
+ }
+
+- /* allocate max required pathname storage,
+- * = path + "/.ssh/authorized_keys" + '\0' = pathlen + 22 */
+- filename = m_malloc(len + 22);
+- strncpy(filename, ses.authstate.pw_dir, len+1);
+-
+- /* check ~ */
+- if (checkfileperm(filename) != DROPBEAR_SUCCESS) {
+- goto out;
+- }
+-
+- /* check ~/.ssh */
+- strncat(filename, "/.ssh", 5); /* strlen("/.ssh") == 5 */
+- if (checkfileperm(filename) != DROPBEAR_SUCCESS) {
+- goto out;
+- }
+-
+- /* now check ~/.ssh/authorized_keys */
+- strncat(filename, "/authorized_keys", 16);
+- if (checkfileperm(filename) != DROPBEAR_SUCCESS) {
+- goto out;
++ if (ses.authstate.pw_uid == 0) {
++ if (checkfileperm("/etc/dropbear") != DROPBEAR_SUCCESS) {
++ goto out;
++ }
++ if (checkfileperm("/etc/dropbear/authorized_keys") != DROPBEAR_SUCCESS) {
++ goto out;
++ }
++ } else {
++ /* allocate max required pathname storage,
++ * = path + "/.ssh/authorized_keys" + '\0' = pathlen + 22 */
++ filename = m_malloc(len + 22);
++ strncpy(filename, ses.authstate.pw_dir, len+1);
++
++ /* check ~ */
++ if (checkfileperm(filename) != DROPBEAR_SUCCESS) {
++ goto out;
++ }
++
++ /* check ~/.ssh */
++ strncat(filename, "/.ssh", 5); /* strlen("/.ssh") == 5 */
++ if (checkfileperm(filename) != DROPBEAR_SUCCESS) {
++ goto out;
++ }
++
++ /* now check ~/.ssh/authorized_keys */
++ strncat(filename, "/authorized_keys", 16);
++ if (checkfileperm(filename) != DROPBEAR_SUCCESS) {
++ goto out;
++ }
+ }
+
+ /* file looks ok, return success */
diff --git a/package/dropbear/patches/110-change_user.patch b/package/dropbear/patches/110-change_user.patch
new file mode 100644
index 000000000..55747bc4d
--- /dev/null
+++ b/package/dropbear/patches/110-change_user.patch
@@ -0,0 +1,18 @@
+--- a/svr-chansession.c
++++ b/svr-chansession.c
+@@ -884,12 +884,12 @@ static void execchild(void *user_data) {
+ /* We can only change uid/gid as root ... */
+ if (getuid() == 0) {
+
+- if ((setgid(ses.authstate.pw_gid) < 0) ||
++ if ((ses.authstate.pw_gid != 0) && ((setgid(ses.authstate.pw_gid) < 0) ||
+ (initgroups(ses.authstate.pw_name,
+- ses.authstate.pw_gid) < 0)) {
++ ses.authstate.pw_gid) < 0))) {
+ dropbear_exit("Error changing user group");
+ }
+- if (setuid(ses.authstate.pw_uid) < 0) {
++ if ((ses.authstate.pw_uid != 0) && (setuid(ses.authstate.pw_uid) < 0)) {
+ dropbear_exit("Error changing user");
+ }
+ } else {
diff --git a/package/dropbear/patches/120-openwrt_options.patch b/package/dropbear/patches/120-openwrt_options.patch
new file mode 100644
index 000000000..42204aa64
--- /dev/null
+++ b/package/dropbear/patches/120-openwrt_options.patch
@@ -0,0 +1,67 @@
+--- a/options.h
++++ b/options.h
+@@ -38,7 +38,7 @@
+ * Both of these flags can be defined at once, don't compile without at least
+ * one of them. */
+ #define NON_INETD_MODE
+-#define INETD_MODE
++/*#define INETD_MODE*/
+
+ /* Setting this disables the fast exptmod bignum code. It saves ~5kB, but is
+ * perhaps 20% slower for pubkey operations (it is probably worth experimenting
+@@ -49,7 +49,7 @@
+ several kB in binary size however will make the symmetrical ciphers and hashes
+ slower, perhaps by 50%. Recommended for small systems that aren't doing
+ much traffic. */
+-/*#define DROPBEAR_SMALL_CODE*/
++#define DROPBEAR_SMALL_CODE
+
+ /* Enable X11 Forwarding - server only */
+ #define ENABLE_X11FWD
+@@ -78,7 +78,7 @@ much traffic. */
+
+ /* Enable "Netcat mode" option. This will forward standard input/output
+ * to a remote TCP-forwarded connection */
+-#define ENABLE_CLI_NETCAT
++/*#define ENABLE_CLI_NETCAT*/
+
+ /* Encryption - at least one required.
+ * Protocol RFC requires 3DES and recommends AES128 for interoperability.
+@@ -89,8 +89,8 @@ much traffic. */
+ #define DROPBEAR_AES256
+ /* Compiling in Blowfish will add ~6kB to runtime heap memory usage */
+ /*#define DROPBEAR_BLOWFISH*/
+-#define DROPBEAR_TWOFISH256
+-#define DROPBEAR_TWOFISH128
++/*#define DROPBEAR_TWOFISH256
++#define DROPBEAR_TWOFISH128*/
+
+ /* Enable "Counter Mode" for ciphers. This is more secure than normal
+ * CBC mode against certain attacks. This adds around 1kB to binary
+@@ -110,7 +110,7 @@ much traffic. */
+ * If you disable MD5, Dropbear will fall back to SHA1 fingerprints,
+ * which are not the standard form. */
+ #define DROPBEAR_SHA1_HMAC
+-#define DROPBEAR_SHA1_96_HMAC
++/*#define DROPBEAR_SHA1_96_HMAC*/
+ #define DROPBEAR_MD5_HMAC
+
+ /* Hostkey/public key algorithms - at least one required, these are used
+@@ -148,7 +148,7 @@ much traffic. */
+
+ /* Whether to print the message of the day (MOTD). This doesn't add much code
+ * size */
+-#define DO_MOTD
++/*#define DO_MOTD*/
+
+ /* The MOTD file path */
+ #ifndef MOTD_FILENAME
+@@ -192,7 +192,7 @@ much traffic. */
+ * note that it will be provided for all "hidden" client-interactive
+ * style prompts - if you want something more sophisticated, use
+ * SSH_ASKPASS instead. Comment out this var to remove this functionality.*/
+-#define DROPBEAR_PASSWORD_ENV "DROPBEAR_PASSWORD"
++/*#define DROPBEAR_PASSWORD_ENV "DROPBEAR_PASSWORD"*/
+
+ /* Define this (as well as ENABLE_CLI_PASSWORD_AUTH) to allow the use of
+ * a helper program for the ssh client. The helper program should be
diff --git a/package/dropbear/patches/130-ssh_ignore_o_and_x_args.patch b/package/dropbear/patches/130-ssh_ignore_o_and_x_args.patch
new file mode 100644
index 000000000..93647a99e
--- /dev/null
+++ b/package/dropbear/patches/130-ssh_ignore_o_and_x_args.patch
@@ -0,0 +1,21 @@
+--- a/cli-runopts.c
++++ b/cli-runopts.c
+@@ -287,6 +287,10 @@ void cli_getopts(int argc, char ** argv)
+ debug_trace = 1;
+ break;
+ #endif
++ case 'o':
++ next = &dummy;
++ case 'x':
++ break;
+ case 'F':
+ case 'e':
+ case 'c':
+@@ -298,7 +302,6 @@ void cli_getopts(int argc, char ** argv)
+ #ifndef ENABLE_CLI_LOCALTCPFWD
+ case 'L':
+ #endif
+- case 'o':
+ case 'b':
+ next = &dummy;
+ default:
diff --git a/package/dropbear/patches/140-disable_assert.patch b/package/dropbear/patches/140-disable_assert.patch
new file mode 100644
index 000000000..e99376333
--- /dev/null
+++ b/package/dropbear/patches/140-disable_assert.patch
@@ -0,0 +1,14 @@
+--- a/dbutil.h
++++ b/dbutil.h
+@@ -94,6 +94,10 @@ int m_str_to_uint(const char* str, unsig
+ #define DEF_MP_INT(X) mp_int X = {0, 0, 0, NULL}
+
+ /* Dropbear assertion */
+-#define dropbear_assert(X) do { if (!(X)) { fail_assert(#X, __FILE__, __LINE__); } } while (0)
++#ifndef DROPBEAR_ASSERT_ENABLED
++#define DROPBEAR_ASSERT_ENABLED 0
++#endif
++
++#define dropbear_assert(X) do { if (DROPBEAR_ASSERT_ENABLED && !(X)) { fail_assert(#X, __FILE__, __LINE__); } } while (0)
+
+ #endif /* _DBUTIL_H_ */
diff --git a/package/dropbear/patches/150-dbconvert_standalone.patch b/package/dropbear/patches/150-dbconvert_standalone.patch
new file mode 100644
index 000000000..3e0b00855
--- /dev/null
+++ b/package/dropbear/patches/150-dbconvert_standalone.patch
@@ -0,0 +1,14 @@
+--- a/options.h
++++ b/options.h
+@@ -5,6 +5,11 @@
+ #ifndef _OPTIONS_H_
+ #define _OPTIONS_H_
+
++#if !defined(DROPBEAR_CLIENT) && !defined(DROPBEAR_SERVER)
++#define DROPBEAR_SERVER
++#define DROPBEAR_CLIENT
++#endif
++
+ /******************************************************************
+ * Define compile-time options below - the "#ifndef DROPBEAR_XXX .... #endif"
+ * parts are to allow for commandline -DDROPBEAR_XXX options etc.
diff --git a/package/dropbear/patches/200-lcrypt_bsdfix.patch b/package/dropbear/patches/200-lcrypt_bsdfix.patch
new file mode 100644
index 000000000..57eb9670d
--- /dev/null
+++ b/package/dropbear/patches/200-lcrypt_bsdfix.patch
@@ -0,0 +1,29 @@
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -56,7 +56,7 @@ HEADERS=options.h dbutil.h session.h pac
+ loginrec.h atomicio.h x11fwd.h agentfwd.h tcpfwd.h compat.h \
+ listener.h fake-rfc2553.h
+
+-dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS) @CRYPTLIB@
++dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS)
+ dbclientobjs=$(COMMONOBJS) $(CLISVROBJS) $(CLIOBJS)
+ dropbearkeyobjs=$(COMMONOBJS) $(KEYOBJS)
+ dropbearconvertobjs=$(COMMONOBJS) $(CONVERTOBJS)
+@@ -77,7 +77,7 @@ STRIP=@STRIP@
+ INSTALL=@INSTALL@
+ CPPFLAGS=@CPPFLAGS@
+ CFLAGS+=-I. -I$(srcdir) $(CPPFLAGS) @CFLAGS@
+-LIBS+=@LIBS@
++LIBS+=@CRYPTLIB@ @LIBS@
+ LDFLAGS=@LDFLAGS@
+
+ EXEEXT=@EXEEXT@
+@@ -169,7 +169,7 @@ scp: $(SCPOBJS) $(HEADERS) Makefile
+ # multi-binary compilation.
+ MULTIOBJS=
+ ifeq ($(MULTI),1)
+- MULTIOBJS=dbmulti.o $(sort $(foreach prog, $(PROGRAMS), $($(prog)objs))) @CRYPTLIB@
++ MULTIOBJS=dbmulti.o $(sort $(foreach prog, $(PROGRAMS), $($(prog)objs)))
+ CFLAGS+=$(addprefix -DDBMULTI_, $(PROGRAMS)) -DDROPBEAR_MULTI
+ endif
+
diff --git a/package/dropbear/patches/300-ipv6_addr_port_split.patch b/package/dropbear/patches/300-ipv6_addr_port_split.patch
new file mode 100644
index 000000000..7da435ab1
--- /dev/null
+++ b/package/dropbear/patches/300-ipv6_addr_port_split.patch
@@ -0,0 +1,11 @@
+--- a/svr-runopts.c
++++ b/svr-runopts.c
+@@ -325,7 +325,7 @@ static void addportandaddress(char* spec
+ myspec = m_strdup(spec);
+
+ /* search for ':', that separates address and port */
+- svr_opts.ports[svr_opts.portcount] = strchr(myspec, ':');
++ svr_opts.ports[svr_opts.portcount] = strrchr(myspec, ':');
+
+ if (svr_opts.ports[svr_opts.portcount] == NULL) {
+ /* no ':' -> the whole string specifies just a port */
diff --git a/package/dropbear/patches/400-CVE-2012-0920.patch b/package/dropbear/patches/400-CVE-2012-0920.patch
new file mode 100644
index 000000000..164909f56
--- /dev/null
+++ b/package/dropbear/patches/400-CVE-2012-0920.patch
@@ -0,0 +1,91 @@
+
+# HG changeset patch
+# User Matt Johnston <matt@ucc.asn.au>
+# Date 1322947885 -28800
+# Node ID 818108bf7749bfecd4715a30e2583aac9dbe25e8
+# Parent 5e8d84f3ee7256d054ecf7e9f248765ccaa7f24f
+- Fix use-after-free if multiple command requests were sent. Move
+the original_command into chansess struct since that makes more sense
+
+--- a/auth.h
++++ b/auth.h
+@@ -133,7 +133,6 @@ struct PubKeyOptions {
+ int no_pty_flag;
+ /* "command=" option. */
+ unsigned char * forced_command;
+- unsigned char * original_command;
+ };
+ #endif
+
+--- a/chansession.h
++++ b/chansession.h
+@@ -69,6 +69,10 @@ struct ChanSess {
+ char * agentfile;
+ char * agentdir;
+ #endif
++
++#ifdef ENABLE_SVR_PUBKEY_OPTIONS
++ char *original_command;
++#endif
+ };
+
+ struct ChildPid {
+--- a/svr-authpubkeyoptions.c
++++ b/svr-authpubkeyoptions.c
+@@ -92,14 +92,15 @@ int svr_pubkey_allows_pty() {
+ * by any 'command' public key option. */
+ void svr_pubkey_set_forced_command(struct ChanSess *chansess) {
+ if (ses.authstate.pubkey_options) {
+- ses.authstate.pubkey_options->original_command = chansess->cmd;
+- if (!chansess->cmd)
+- {
+- ses.authstate.pubkey_options->original_command = m_strdup("");
++ if (chansess->cmd) {
++ /* original_command takes ownership */
++ chansess->original_command = chansess->cmd;
++ } else {
++ chansess->original_command = m_strdup("");
+ }
+- chansess->cmd = ses.authstate.pubkey_options->forced_command;
++ chansess->cmd = m_strdup(ses.authstate.pubkey_options->forced_command);
+ #ifdef LOG_COMMANDS
+- dropbear_log(LOG_INFO, "Command forced to '%s'", ses.authstate.pubkey_options->original_command);
++ dropbear_log(LOG_INFO, "Command forced to '%s'", chansess->original_command);
+ #endif
+ }
+ }
+--- a/svr-chansession.c
++++ b/svr-chansession.c
+@@ -217,6 +217,8 @@ static int newchansess(struct Channel *c
+
+ struct ChanSess *chansess;
+
++ TRACE(("new chansess %p", channel))
++
+ dropbear_assert(channel->typedata == NULL);
+
+ chansess = (struct ChanSess*)m_malloc(sizeof(struct ChanSess));
+@@ -279,6 +281,10 @@ static void closechansess(struct Channel
+ m_free(chansess->cmd);
+ m_free(chansess->term);
+
++#ifdef ENABLE_SVR_PUBKEY_OPTIONS
++ m_free(chansess->original_command);
++#endif
++
+ if (chansess->tty) {
+ /* write the utmp/wtmp login record */
+ li = chansess_login_alloc(chansess);
+@@ -924,10 +930,8 @@ static void execchild(void *user_data) {
+ }
+
+ #ifdef ENABLE_SVR_PUBKEY_OPTIONS
+- if (ses.authstate.pubkey_options &&
+- ses.authstate.pubkey_options->original_command) {
+- addnewvar("SSH_ORIGINAL_COMMAND",
+- ses.authstate.pubkey_options->original_command);
++ if (chansess->original_command) {
++ addnewvar("SSH_ORIGINAL_COMMAND", chansess->original_command);
+ }
+ #endif
+
diff --git a/package/dropbear/patches/500-set-default-path.patch b/package/dropbear/patches/500-set-default-path.patch
new file mode 100644
index 000000000..0bd3ffcc3
--- /dev/null
+++ b/package/dropbear/patches/500-set-default-path.patch
@@ -0,0 +1,11 @@
+--- a/options.h
++++ b/options.h
+@@ -297,7 +297,7 @@ be overridden at runtime with -I. 0 disa
+ #define DEFAULT_IDLE_TIMEOUT 0
+
+ /* The default path. This will often get replaced by the shell */
+-#define DEFAULT_PATH "/usr/bin:/bin"
++#define DEFAULT_PATH "/bin:/sbin:/usr/bin:/usr/sbin"
+
+ /* Some other defines (that mostly should be left alone) are defined
+ * in sysoptions.h */
diff --git a/package/e2fsprogs/Makefile b/package/e2fsprogs/Makefile
new file mode 100644
index 000000000..ebc21c906
--- /dev/null
+++ b/package/e2fsprogs/Makefile
@@ -0,0 +1,169 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+# Copyright 2010 Vertical Communications
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=e2fsprogs
+PKG_VERSION:=1.42.4
+PKG_MD5SUM:=b6e296f210d642361b7394437ff0f318
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/e2fsprogs
+
+PKG_BUILD_DEPENDS:=util-linux
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/e2fsprogs/Default
+ URL:=http://e2fsprogs.sourceforge.net/
+ SUBMENU:=Filesystem
+endef
+
+define Package/e2fsprogs
+$(call Package/e2fsprogs/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Ext2/3/4 filesystem utilities
+ DEPENDS:=+libblkid +libuuid +libext2fs
+endef
+
+define Package/e2fsprogs/description
+ This package contains essential ext2 filesystem utilities which consists of
+ e2fsck, mke2fs, tune2fs, and most of the other core ext2
+ filesystem utilities.
+endef
+
+define Package/libext2fs
+$(call Package/e2fsprogs/Default)
+ DEPENDS:=+libcom_err
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=ext2/3/4 filesystem library
+endef
+
+define Package/libext2fs/description
+ libext2fs is a library which can access ext2, ext3 and ext4 filesystems.
+endef
+
+define Package/libcom_err
+$(call Package/e2fsprogs/Default)
+ DEPENDS:=+libpthread
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=Common error description library
+endef
+
+define Package/libcom_err/description
+ libcom_err is a library providing common error descriptions
+endef
+
+define Package/tune2fs
+$(call Package/e2fsprogs)
+ TITLE:=Ext2 Filesystem tune utility
+ DEPENDS:= +e2fsprogs
+endef
+
+define Package/resize2fs
+$(call Package/e2fsprogs)
+ TITLE:=Ext2 Filesystem resize utility
+ DEPENDS:= +e2fsprogs
+endef
+
+define Package/badblocks
+$(call Package/e2fsprogs)
+ TITLE:=Ext2 Filesystem badblocks utility
+ DEPENDS:= +e2fsprogs
+endef
+
+TARGET_CFLAGS += $(FPIC)
+
+CONFIGURE_ARGS += \
+ --enable-elf-shlibs \
+ --disable-libuuid \
+ --disable-libblkid \
+ --disable-uuidd \
+ --disable-tls \
+ --disable-nls \
+ --disable-rpath
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ $(CP) $(SCRIPT_DIR)/config.{guess,sub} $(PKG_BUILD_DIR)/config/
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR)/util \
+ BUILDCC="$(HOSTCC)" \
+ CFLAGS="" \
+ CPPFLAGS="" \
+ LDFLAGS="" \
+ subst
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ BUILDCC="$(HOSTCC)" \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ all
+endef
+
+define Build/InstallDev
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ BUILDCC="$(HOSTCC)" \
+ DESTDIR="$(1)" \
+ install-libs
+ $(MAKE) -C $(PKG_BUILD_DIR)/lib/ext2fs \
+ BUILDCC="$(HOSTCC)" \
+ DESTDIR="$(1)" \
+ install
+endef
+
+define Package/e2fsprogs/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/e2fsck $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/mke2fs $(1)/usr/sbin/
+ ln -sf mke2fs $(1)/usr/sbin/mkfs.ext2
+ ln -sf mke2fs $(1)/usr/sbin/mkfs.ext3
+ ln -sf mke2fs $(1)/usr/sbin/mkfs.ext4
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libe2p.so.* $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_DIR) $(1)/lib/functions/fsck
+ $(INSTALL_DATA) ./files/e2fsck.sh $(1)/lib/functions/fsck/
+ $(INSTALL_DATA) ./files/e2fsck.conf $(1)/etc/e2fsck.conf
+endef
+
+define Package/libcom_err/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libcom_err.so.* $(1)/usr/lib/
+endef
+
+define Package/libext2fs/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libext2fs.so.* $(1)/usr/lib/
+endef
+
+define Package/tune2fs/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/tune2fs $(1)/usr/sbin/
+endef
+
+define Package/resize2fs/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/resize2fs $(1)/usr/sbin/
+endef
+
+define Package/badblocks/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/badblocks $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,e2fsprogs))
+$(eval $(call BuildPackage,libext2fs))
+$(eval $(call BuildPackage,libcom_err))
+$(eval $(call BuildPackage,tune2fs))
+$(eval $(call BuildPackage,resize2fs))
+$(eval $(call BuildPackage,badblocks))
diff --git a/package/e2fsprogs/files/e2fsck.conf b/package/e2fsprogs/files/e2fsck.conf
new file mode 100644
index 000000000..9c96b4958
--- /dev/null
+++ b/package/e2fsprogs/files/e2fsck.conf
@@ -0,0 +1,3 @@
+[options]
+broken_system_clock = true
+
diff --git a/package/e2fsprogs/files/e2fsck.sh b/package/e2fsprogs/files/e2fsck.sh
new file mode 100644
index 000000000..22031edb6
--- /dev/null
+++ b/package/e2fsprogs/files/e2fsck.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+# Copyright 2010 Vertical Communications
+# Copyright 2012 OpenWrt.org
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+fsck_e2fsck() {
+ set -o pipefail
+ e2fsck -p "$device" 2>&1 | logger -t "fstab: e2fsck ($device)"
+ local status="$?"
+ set +o pipefail
+ case "$status" in
+ 0|1) ;; #success
+ 2) reboot;;
+ 4) echo "e2fsck ($device): Warning! Uncorrected errors."| logger -t fstab
+ return 1
+ ;;
+ *) echo "e2fsck ($device): Error $status. Check not complete."| logger -t fstab;;
+ esac
+ return 0
+}
+
+fsck_ext2() {
+ fsck_e2fsck "$@"
+}
+
+fsck_ext3() {
+ fsck_e2fsck "$@"
+}
+
+fsck_ext4() {
+ fsck_e2fsck "$@"
+}
+
+append libmount_known_fsck "ext2"
+append libmount_known_fsck "ext3"
+append libmount_known_fsck "ext4"
diff --git a/package/e2fsprogs/patches/001-link-against-libuuid.patch b/package/e2fsprogs/patches/001-link-against-libuuid.patch
new file mode 100644
index 000000000..e0564dc35
--- /dev/null
+++ b/package/e2fsprogs/patches/001-link-against-libuuid.patch
@@ -0,0 +1,38 @@
+--- a/configure
++++ b/configure
+@@ -5038,7 +5038,7 @@ if test "${ac_cv_lib_blkid_blkid_get_cac
+ $as_echo_n "(cached) " >&6
+ else
+ ac_check_lib_save_LIBS=$LIBS
+-LIBS="-lblkid $LIBBLKID $LIBS"
++LIBS="-lblkid $LIBBLKID $LIBUUID $LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h. */
+
+--- a/misc/Makefile.in
++++ b/misc/Makefile.in
+@@ -146,10 +146,10 @@ partinfo: partinfo.o
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -o partinfo partinfo.o
+
+-e2initrd_helper: e2initrd_helper.o $(DEPLIBS) $(DEPLIBBLKID) $(LIBEXT2FS)
++e2initrd_helper: e2initrd_helper.o $(DEPLIBS) $(DEPLIBBLKID) $(DEPLIBUUID) $(LIBEXT2FS)
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -o e2initrd_helper e2initrd_helper.o $(LIBS) \
+- $(LIBBLKID) $(LIBEXT2FS) $(LIBINTL)
++ $(LIBBLKID) $(LIBUUID) $(LIBEXT2FS) $(LIBINTL)
+
+ tune2fs: $(TUNE2FS_OBJS) $(DEPLIBS) $(DEPLIBS_E2P) $(DEPLIBBLKID) \
+ $(DEPLIBUUID) $(DEPLIBQUOTA) $(LIBEXT2FS)
+@@ -289,9 +289,9 @@ dumpe2fs.profiled: $(PROFILED_DUMPE2FS_O
+ $(PROFILED_DUMPE2FS_OBJS) $(PROFILED_LIBS) \
+ $(PROFILED_LIBE2P) $(PROFILED_LIBUUID) $(LIBINTL)
+
+-fsck: $(FSCK_OBJS) $(DEPLIBBLKID)
++fsck: $(FSCK_OBJS) $(DEPLIBBLKID) $(DEPLIBUUID)
+ $(E) " LD $@"
+- $(Q) $(CC) $(ALL_LDFLAGS) -o fsck $(FSCK_OBJS) $(LIBBLKID) $(LIBINTL)
++ $(Q) $(CC) $(ALL_LDFLAGS) -o fsck $(FSCK_OBJS) $(LIBBLKID) $(LIBUUID) $(LIBINTL)
+
+ fsck.profiled: $(PROFILED_FSCK_OBJS) $(PROFILED_DEPLIBBLKID)
+ $(E) " LD $@"
diff --git a/package/e2fsprogs/patches/002-no_malloc_h.patch b/package/e2fsprogs/patches/002-no_malloc_h.patch
new file mode 100644
index 000000000..209b47c1c
--- /dev/null
+++ b/package/e2fsprogs/patches/002-no_malloc_h.patch
@@ -0,0 +1,10 @@
+--- a/util/symlinks.c
++++ b/util/symlinks.c
+@@ -8,7 +8,6 @@
+ #endif
+ #include <stdio.h>
+ #include <stdlib.h>
+-#include <malloc.h>
+ #include <string.h>
+ #include <fcntl.h>
+ #include <sys/param.h>
diff --git a/package/ead/Makefile b/package/ead/Makefile
new file mode 100644
index 000000000..8c3d4701c
--- /dev/null
+++ b/package/ead/Makefile
@@ -0,0 +1,55 @@
+#
+# Copyright (C) 2006-2008 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ead
+PKG_RELEASE:=1
+
+PKG_BUILD_DEPENDS:=libpcap
+PKG_BUILD_DIR:=$(BUILD_DIR)/ead
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+define Package/ead
+ SECTION:=net
+ CATEGORY:=Base system
+ TITLE:=Emergency Access Daemon
+ URL:=http://bridge.sourceforge.net/
+endef
+
+define Package/ead/description
+ Provides remote access to your device even if IP and firewall
+ configuration settings are defunct
+endef
+
+CONFIGURE_PATH = tinysrp
+
+TARGET_CFLAGS += \
+ -I$(LINUX_DIR)/include \
+ -I$(PKG_BUILD_DIR) \
+ -I$(PKG_BUILD_DIR)/tinysrp \
+ $(TARGET_CPPFLAGS)
+
+MAKE_FLAGS += \
+ CONFIGURE_ARGS="$(CONFIGURE_ARGS)" \
+ LIBS_EADCLIENT="$(PKG_BUILD_DIR)/tinysrp/libtinysrp.a" \
+ LIBS_EAD="$(PKG_BUILD_DIR)/tinysrp/libtinysrp.a $(STAGING_DIR)/usr/lib/libpcap.a" \
+ CFLAGS="$(TARGET_CFLAGS)"
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Package/ead/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/ead $(1)/sbin/
+endef
+
+$(eval $(call BuildPackage,ead))
diff --git a/package/ead/src/Makefile b/package/ead/src/Makefile
new file mode 100644
index 000000000..faef3b799
--- /dev/null
+++ b/package/ead/src/Makefile
@@ -0,0 +1,33 @@
+CC = gcc
+CPPFLAGS = -I. -Itinysrp
+CFLAGS = -Os -Wall
+LDFLAGS =
+LIBS_EADCLIENT = tinysrp/libtinysrp.a
+LIBS_EAD = tinysrp/libtinysrp.a -lpcap
+CONFIGURE_ARGS =
+
+all: ead ead-client
+
+obj = ead-crypt.o
+
+tinysrp/Makefile:
+ cd tinysrp; ./configure $(CONFIGURE_ARGS)
+
+tinysrp/libtinysrp.a: tinysrp/Makefile
+ -$(MAKE) -C tinysrp CFLAGS="$(CFLAGS)"
+
+%.o: %.c $(wildcard *.h) tinysrp/libtinysrp.a
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
+
+ead.o: filter.c
+ead-crypt.o: aes.c sha1.c
+
+ead: ead.o $(obj) tinysrp/libtinysrp.a
+ $(CC) -o $@ $< $(obj) $(LDFLAGS) $(LIBS_EAD)
+
+ead-client: ead-client.o $(obj)
+ $(CC) -o $@ $< $(obj) $(LDFLAGS) $(LIBS_EADCLIENT)
+
+clean:
+ rm -f *.o ead ead-client
+ if [ -f tinysrp/Makefile ]; then $(MAKE) -C tinysrp distclean; fi
diff --git a/package/ead/src/aes.c b/package/ead/src/aes.c
new file mode 100644
index 000000000..6f9db345f
--- /dev/null
+++ b/package/ead/src/aes.c
@@ -0,0 +1,1061 @@
+/*
+ * AES (Rijndael) cipher
+ *
+ * Modifications to public domain implementation:
+ * - support only 128-bit keys
+ * - cleanup
+ * - use C pre-processor to make it easier to change S table access
+ * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
+ * cost of reduced throughput (quite small difference on Pentium 4,
+ * 10-25% when using -O1 or -O2 optimization)
+ *
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
+ *
+ * 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.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+/*
+ * rijndael-alg-fst.c
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * 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 AUTHORS 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.
+ */
+
+/* #define FULL_UNROLL */
+#define AES_SMALL_TABLES
+
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+
+/*
+Te0[x] = S [x].[02, 01, 01, 03];
+Te1[x] = S [x].[03, 02, 01, 01];
+Te2[x] = S [x].[01, 03, 02, 01];
+Te3[x] = S [x].[01, 01, 03, 02];
+Te4[x] = S [x].[01, 01, 01, 01];
+
+Td0[x] = Si[x].[0e, 09, 0d, 0b];
+Td1[x] = Si[x].[0b, 0e, 09, 0d];
+Td2[x] = Si[x].[0d, 0b, 0e, 09];
+Td3[x] = Si[x].[09, 0d, 0b, 0e];
+Td4[x] = Si[x].[01, 01, 01, 01];
+*/
+
+static const u32 Te0[256] = {
+ 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+ 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+ 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+ 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+ 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+ 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+ 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+ 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+ 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+ 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+ 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+ 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+ 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+ 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+ 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+ 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+ 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+ 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+ 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+ 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+ 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+ 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+ 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+ 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+ 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+ 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+ 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+ 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+ 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+ 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+ 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+ 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+ 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+ 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+ 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+ 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+ 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+ 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+ 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+ 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+ 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+ 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+ 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+ 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+ 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+ 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+ 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+ 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+ 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+ 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+ 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+ 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+ 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+ 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+ 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+ 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+ 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+ 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+ 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+ 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+ 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+ 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+ 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+ 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+};
+#ifndef AES_SMALL_TABLES
+static const u32 Te1[256] = {
+ 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
+ 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
+ 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
+ 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
+ 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
+ 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
+ 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
+ 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
+ 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
+ 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
+ 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
+ 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
+ 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
+ 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
+ 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
+ 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
+ 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
+ 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
+ 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
+ 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
+ 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
+ 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
+ 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
+ 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
+ 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
+ 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
+ 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
+ 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
+ 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
+ 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
+ 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
+ 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
+ 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
+ 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
+ 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
+ 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
+ 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
+ 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
+ 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
+ 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
+ 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
+ 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
+ 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
+ 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
+ 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
+ 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
+ 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
+ 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
+ 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
+ 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
+ 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
+ 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
+ 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
+ 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
+ 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
+ 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
+ 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
+ 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
+ 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
+ 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
+ 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
+ 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
+ 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
+ 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
+};
+static const u32 Te2[256] = {
+ 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
+ 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
+ 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
+ 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
+ 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
+ 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
+ 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
+ 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
+ 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
+ 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
+ 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
+ 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
+ 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
+ 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
+ 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
+ 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
+ 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
+ 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
+ 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
+ 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
+ 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
+ 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
+ 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
+ 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
+ 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
+ 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
+ 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
+ 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
+ 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
+ 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
+ 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
+ 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
+ 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
+ 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
+ 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
+ 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
+ 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
+ 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
+ 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
+ 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
+ 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
+ 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
+ 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
+ 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
+ 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
+ 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
+ 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
+ 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
+ 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
+ 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
+ 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
+ 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
+ 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
+ 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
+ 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
+ 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
+ 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
+ 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
+ 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
+ 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
+ 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
+ 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
+ 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
+ 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
+};
+static const u32 Te3[256] = {
+
+ 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
+ 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
+ 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
+ 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
+ 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
+ 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
+ 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
+ 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
+ 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
+ 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
+ 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
+ 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
+ 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
+ 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
+ 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
+ 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
+ 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
+ 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
+ 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
+ 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
+ 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
+ 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
+ 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
+ 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
+ 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
+ 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
+ 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
+ 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
+ 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
+ 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
+ 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
+ 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
+ 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
+ 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
+ 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
+ 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
+ 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
+ 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
+ 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
+ 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
+ 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
+ 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
+ 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
+ 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
+ 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
+ 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
+ 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
+ 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
+ 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
+ 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
+ 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
+ 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
+ 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
+ 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
+ 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
+ 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
+ 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
+ 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
+ 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
+ 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
+ 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
+ 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
+ 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
+ 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
+};
+static const u32 Te4[256] = {
+ 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
+ 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
+ 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
+ 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
+ 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
+ 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
+ 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
+ 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
+ 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
+ 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
+ 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
+ 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
+ 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
+ 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
+ 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
+ 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
+ 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
+ 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
+ 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
+ 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
+ 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
+ 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
+ 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
+ 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
+ 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
+ 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
+ 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
+ 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
+ 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
+ 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
+ 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
+ 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
+ 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
+ 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
+ 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
+ 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
+ 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
+ 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
+ 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
+ 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
+ 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
+ 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
+ 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
+ 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
+ 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
+ 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
+ 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
+ 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
+ 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
+ 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
+ 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
+ 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
+ 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
+ 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
+ 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
+ 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
+ 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
+ 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
+ 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
+ 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
+ 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
+ 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
+ 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
+ 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
+};
+#endif /* AES_SMALL_TABLES */
+static const u32 Td0[256] = {
+ 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
+ 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
+ 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
+ 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
+ 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
+ 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
+ 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
+ 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
+ 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
+ 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
+ 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
+ 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
+ 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
+ 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
+ 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
+ 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
+ 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
+ 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
+ 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
+ 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
+ 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
+ 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
+ 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
+ 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
+ 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
+ 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
+ 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
+ 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
+ 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
+ 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
+ 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
+ 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
+ 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
+ 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
+ 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
+ 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
+ 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
+ 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
+ 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
+ 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
+ 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
+ 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
+ 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
+ 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
+ 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
+ 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
+ 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
+ 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
+ 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
+ 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
+ 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
+ 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
+ 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
+ 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
+ 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
+ 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
+ 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
+ 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
+ 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
+ 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
+ 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
+ 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
+ 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
+ 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
+};
+#ifndef AES_SMALL_TABLES
+static const u32 Td1[256] = {
+ 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
+ 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
+ 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
+ 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
+ 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
+ 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
+ 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
+ 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
+ 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
+ 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
+ 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
+ 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
+ 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
+ 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
+ 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
+ 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
+ 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
+ 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
+ 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
+ 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
+ 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
+ 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
+ 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
+ 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
+ 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
+ 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
+ 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
+ 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
+ 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
+ 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
+ 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
+ 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
+ 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
+ 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
+ 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
+ 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
+ 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
+ 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
+ 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
+ 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
+ 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
+ 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
+ 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
+ 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
+ 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
+ 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
+ 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
+ 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
+ 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
+ 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
+ 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
+ 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
+ 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
+ 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
+ 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
+ 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
+ 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
+ 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
+ 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
+ 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
+ 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
+ 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
+ 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
+ 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
+};
+static const u32 Td2[256] = {
+ 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
+ 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
+ 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
+ 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
+ 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
+ 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
+ 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
+ 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
+ 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
+ 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
+ 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
+ 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
+ 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
+ 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
+ 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
+ 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
+ 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
+ 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
+ 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
+ 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
+
+ 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
+ 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
+ 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
+ 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
+ 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
+ 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
+ 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
+ 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
+ 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
+ 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
+ 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
+ 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
+ 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
+ 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
+ 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
+ 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
+ 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
+ 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
+ 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
+ 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
+ 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
+ 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
+ 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
+ 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
+ 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
+ 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
+ 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
+ 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
+ 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
+ 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
+ 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
+ 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
+ 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
+ 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
+ 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
+ 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
+ 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
+ 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
+ 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
+ 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
+ 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
+ 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
+ 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
+ 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
+};
+static const u32 Td3[256] = {
+ 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
+ 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
+ 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
+ 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
+ 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
+ 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
+ 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
+ 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
+ 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
+ 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
+ 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
+ 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
+ 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
+ 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
+ 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
+ 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
+ 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
+ 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
+ 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
+ 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
+ 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
+ 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
+ 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
+ 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
+ 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
+ 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
+ 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
+ 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
+ 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
+ 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
+ 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
+ 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
+ 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
+ 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
+ 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
+ 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
+ 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
+ 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
+ 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
+ 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
+ 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
+ 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
+ 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
+ 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
+ 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
+ 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
+ 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
+ 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
+ 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
+ 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
+ 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
+ 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
+ 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
+ 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
+ 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
+ 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
+ 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
+ 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
+ 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
+ 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
+ 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
+ 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
+ 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
+ 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
+};
+static const u32 Td4[256] = {
+ 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
+ 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
+ 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
+ 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
+ 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
+ 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
+ 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
+ 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
+ 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
+ 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
+ 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
+ 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
+ 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
+ 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
+ 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
+ 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
+ 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
+ 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
+ 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
+ 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
+ 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
+ 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
+ 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
+ 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
+ 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
+ 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
+ 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
+ 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
+ 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
+ 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
+ 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
+ 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
+ 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
+ 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
+ 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
+ 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
+ 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
+ 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
+ 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
+ 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
+ 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
+ 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
+ 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
+ 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
+ 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
+ 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
+ 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
+ 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
+ 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
+ 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
+ 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
+ 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
+ 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
+ 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
+ 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
+ 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
+ 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
+ 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
+ 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
+ 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
+ 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
+ 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
+ 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
+ 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
+};
+static const u32 rcon[] = {
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
+ 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+#else /* AES_SMALL_TABLES */
+static const u8 Td4s[256] = {
+ 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U,
+ 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU,
+ 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U,
+ 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU,
+ 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU,
+ 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU,
+ 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U,
+ 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U,
+ 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U,
+ 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U,
+ 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU,
+ 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U,
+ 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU,
+ 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U,
+ 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U,
+ 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU,
+ 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU,
+ 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U,
+ 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U,
+ 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU,
+ 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U,
+ 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,
+ 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U,
+ 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U,
+ 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U,
+ 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU,
+ 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU,
+ 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU,
+ 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U,
+ 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U,
+ 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U,
+ 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,
+};
+static const u8 rcons[] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
+ /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+#endif /* AES_SMALL_TABLES */
+
+
+#ifndef AES_SMALL_TABLES
+
+#define RCON(i) rcon[(i)]
+
+#define TE0(i) Te0[((i) >> 24) & 0xff]
+#define TE1(i) Te1[((i) >> 16) & 0xff]
+#define TE2(i) Te2[((i) >> 8) & 0xff]
+#define TE3(i) Te3[(i) & 0xff]
+#define TE41(i) (Te4[((i) >> 24) & 0xff] & 0xff000000)
+#define TE42(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000)
+#define TE43(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00)
+#define TE44(i) (Te4[(i) & 0xff] & 0x000000ff)
+#define TE421(i) (Te4[((i) >> 16) & 0xff] & 0xff000000)
+#define TE432(i) (Te4[((i) >> 8) & 0xff] & 0x00ff0000)
+#define TE443(i) (Te4[(i) & 0xff] & 0x0000ff00)
+#define TE414(i) (Te4[((i) >> 24) & 0xff] & 0x000000ff)
+#define TE4(i) (Te4[(i)] & 0x000000ff)
+
+#define TD0(i) Td0[((i) >> 24) & 0xff]
+#define TD1(i) Td1[((i) >> 16) & 0xff]
+#define TD2(i) Td2[((i) >> 8) & 0xff]
+#define TD3(i) Td3[(i) & 0xff]
+#define TD41(i) (Td4[((i) >> 24) & 0xff] & 0xff000000)
+#define TD42(i) (Td4[((i) >> 16) & 0xff] & 0x00ff0000)
+#define TD43(i) (Td4[((i) >> 8) & 0xff] & 0x0000ff00)
+#define TD44(i) (Td4[(i) & 0xff] & 0x000000ff)
+#define TD0_(i) Td0[(i) & 0xff]
+#define TD1_(i) Td1[(i) & 0xff]
+#define TD2_(i) Td2[(i) & 0xff]
+#define TD3_(i) Td3[(i) & 0xff]
+
+#else /* AES_SMALL_TABLES */
+
+#define RCON(i) (rcons[(i)] << 24)
+
+static inline u32 rotr(u32 val, int bits)
+{
+ return (val >> bits) | (val << (32 - bits));
+}
+
+#define TE0(i) Te0[((i) >> 24) & 0xff]
+#define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8)
+#define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16)
+#define TE3(i) rotr(Te0[(i) & 0xff], 24)
+#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000)
+#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000)
+#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00)
+#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff)
+#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000)
+#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000)
+#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00)
+#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff)
+#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff)
+
+#define TD0(i) Td0[((i) >> 24) & 0xff]
+#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8)
+#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16)
+#define TD3(i) rotr(Td0[(i) & 0xff], 24)
+#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24)
+#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16)
+#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8)
+#define TD44(i) (Td4s[(i) & 0xff])
+#define TD0_(i) Td0[(i) & 0xff]
+#define TD1_(i) rotr(Td0[(i) & 0xff], 8)
+#define TD2_(i) rotr(Td0[(i) & 0xff], 16)
+#define TD3_(i) rotr(Td0[(i) & 0xff], 24)
+
+#endif /* AES_SMALL_TABLES */
+
+#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
+
+#ifdef _MSC_VER
+#define GETU32(p) SWAP(*((u32 *)(p)))
+#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
+#else
+#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \
+((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]))
+#define PUTU32(ct, st) { \
+(ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \
+(ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); }
+#endif
+
+/**
+ * Expand the cipher key into the encryption key schedule.
+ *
+ * @return the number of rounds for the given cipher key size.
+ */
+static void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[])
+{
+ int i;
+ u32 temp;
+
+ rk[0] = GETU32(cipherKey );
+ rk[1] = GETU32(cipherKey + 4);
+ rk[2] = GETU32(cipherKey + 8);
+ rk[3] = GETU32(cipherKey + 12);
+ for (i = 0; i < 10; i++) {
+ temp = rk[3];
+ rk[4] = rk[0] ^
+ TE421(temp) ^ TE432(temp) ^ TE443(temp) ^ TE414(temp) ^
+ RCON(i);
+ rk[5] = rk[1] ^ rk[4];
+ rk[6] = rk[2] ^ rk[5];
+ rk[7] = rk[3] ^ rk[6];
+ rk += 4;
+ }
+}
+
+#ifndef CONFIG_NO_AES_DECRYPT
+/**
+ * Expand the cipher key into the decryption key schedule.
+ *
+ * @return the number of rounds for the given cipher key size.
+ */
+static void rijndaelKeySetupDec(u32 rk[/*44*/], const u8 cipherKey[])
+{
+ int Nr = 10, i, j;
+ u32 temp;
+
+ /* expand the cipher key: */
+ rijndaelKeySetupEnc(rk, cipherKey);
+ /* invert the order of the round keys: */
+ for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
+ temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp;
+ temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
+ temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
+ temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
+ }
+ /* apply the inverse MixColumn transform to all round keys but the
+ * first and the last: */
+ for (i = 1; i < Nr; i++) {
+ rk += 4;
+ for (j = 0; j < 4; j++) {
+ rk[j] = TD0_(TE4((rk[j] >> 24) )) ^
+ TD1_(TE4((rk[j] >> 16) & 0xff)) ^
+ TD2_(TE4((rk[j] >> 8) & 0xff)) ^
+ TD3_(TE4((rk[j] ) & 0xff));
+ }
+ }
+}
+#endif /* CONFIG_NO_AES_DECRYPT */
+
+#ifndef CONFIG_NO_AES_ENCRYPT
+static void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16])
+{
+ u32 s0, s1, s2, s3, t0, t1, t2, t3;
+ const int Nr = 10;
+#ifndef FULL_UNROLL
+ int r;
+#endif /* ?FULL_UNROLL */
+
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ s0 = GETU32(pt ) ^ rk[0];
+ s1 = GETU32(pt + 4) ^ rk[1];
+ s2 = GETU32(pt + 8) ^ rk[2];
+ s3 = GETU32(pt + 12) ^ rk[3];
+
+#define ROUND(i,d,s) \
+d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \
+d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \
+d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \
+d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]
+
+#ifdef FULL_UNROLL
+
+ ROUND(1,t,s);
+ ROUND(2,s,t);
+ ROUND(3,t,s);
+ ROUND(4,s,t);
+ ROUND(5,t,s);
+ ROUND(6,s,t);
+ ROUND(7,t,s);
+ ROUND(8,s,t);
+ ROUND(9,t,s);
+
+ rk += Nr << 2;
+
+#else /* !FULL_UNROLL */
+
+ /* Nr - 1 full rounds: */
+ r = Nr >> 1;
+ for (;;) {
+ ROUND(1,t,s);
+ rk += 8;
+ if (--r == 0)
+ break;
+ ROUND(0,s,t);
+ }
+
+#endif /* ?FULL_UNROLL */
+
+#undef ROUND
+
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+ s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0];
+ PUTU32(ct , s0);
+ s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1];
+ PUTU32(ct + 4, s1);
+ s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2];
+ PUTU32(ct + 8, s2);
+ s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3];
+ PUTU32(ct + 12, s3);
+}
+#endif /* CONFIG_NO_AES_ENCRYPT */
+
+static void rijndaelDecrypt(const u32 rk[/*44*/], const u8 ct[16], u8 pt[16])
+{
+ u32 s0, s1, s2, s3, t0, t1, t2, t3;
+ const int Nr = 10;
+#ifndef FULL_UNROLL
+ int r;
+#endif /* ?FULL_UNROLL */
+
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ s0 = GETU32(ct ) ^ rk[0];
+ s1 = GETU32(ct + 4) ^ rk[1];
+ s2 = GETU32(ct + 8) ^ rk[2];
+ s3 = GETU32(ct + 12) ^ rk[3];
+
+#define ROUND(i,d,s) \
+d##0 = TD0(s##0) ^ TD1(s##3) ^ TD2(s##2) ^ TD3(s##1) ^ rk[4 * i]; \
+d##1 = TD0(s##1) ^ TD1(s##0) ^ TD2(s##3) ^ TD3(s##2) ^ rk[4 * i + 1]; \
+d##2 = TD0(s##2) ^ TD1(s##1) ^ TD2(s##0) ^ TD3(s##3) ^ rk[4 * i + 2]; \
+d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3]
+
+#ifdef FULL_UNROLL
+
+ ROUND(1,t,s);
+ ROUND(2,s,t);
+ ROUND(3,t,s);
+ ROUND(4,s,t);
+ ROUND(5,t,s);
+ ROUND(6,s,t);
+ ROUND(7,t,s);
+ ROUND(8,s,t);
+ ROUND(9,t,s);
+
+ rk += Nr << 2;
+
+#else /* !FULL_UNROLL */
+
+ /* Nr - 1 full rounds: */
+ r = Nr >> 1;
+ for (;;) {
+ ROUND(1,t,s);
+ rk += 8;
+ if (--r == 0)
+ break;
+ ROUND(0,s,t);
+ }
+
+#endif /* ?FULL_UNROLL */
+
+#undef ROUND
+
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+ s0 = TD41(t0) ^ TD42(t3) ^ TD43(t2) ^ TD44(t1) ^ rk[0];
+ PUTU32(pt , s0);
+ s1 = TD41(t1) ^ TD42(t0) ^ TD43(t3) ^ TD44(t2) ^ rk[1];
+ PUTU32(pt + 4, s1);
+ s2 = TD41(t2) ^ TD42(t1) ^ TD43(t0) ^ TD44(t3) ^ rk[2];
+ PUTU32(pt + 8, s2);
+ s3 = TD41(t3) ^ TD42(t2) ^ TD43(t1) ^ TD44(t0) ^ rk[3];
+ PUTU32(pt + 12, s3);
+}
+
+#define AES_PRIV_SIZE 44
diff --git a/package/ead/src/ead-client.c b/package/ead/src/ead-client.c
new file mode 100644
index 000000000..54d8b1343
--- /dev/null
+++ b/package/ead/src/ead-client.c
@@ -0,0 +1,433 @@
+/*
+ * Client for the Emergency Access Daemon
+ * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
+ *
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <t_pwd.h>
+#include <t_read.h>
+#include <t_sha.h>
+#include <t_defines.h>
+#include <t_client.h>
+#include "ead.h"
+#include "ead-crypt.h"
+
+#include "pw_encrypt_md5.c"
+
+#define EAD_TIMEOUT 400
+#define EAD_TIMEOUT_LONG 2000
+
+static char msgbuf[1500];
+static struct ead_msg *msg = (struct ead_msg *) msgbuf;
+static uint16_t nid = 0xffff;
+struct sockaddr_in local, remote;
+static int s = 0;
+static int sockflags;
+static struct in_addr serverip = {
+ .s_addr = 0x01010101 /* dummy */
+};
+
+static unsigned char *skey = NULL;
+static unsigned char bbuf[MAXPARAMLEN];
+static unsigned char saltbuf[MAXSALTLEN];
+static char *username = NULL;
+static char password[MAXPARAMLEN] = "";
+static char pw_md5[MD5_OUT_BUFSIZE];
+static char pw_salt[MAXSALTLEN];
+
+static struct t_client *tc = NULL;
+static struct t_num salt = { .data = saltbuf };
+static struct t_num *A, B;
+static struct t_preconf *tcp;
+static int auth_type = EAD_AUTH_DEFAULT;
+static int timeout = EAD_TIMEOUT;
+static uint16_t sid = 0;
+
+static void
+set_nonblock(int enable)
+{
+ if (enable == !!(sockflags & O_NONBLOCK));
+ return;
+
+ sockflags ^= O_NONBLOCK;
+ fcntl(s, F_SETFL, sockflags);
+}
+
+static int
+send_packet(int type, bool (*handler)(void), unsigned int max)
+{
+ struct timeval tv;
+ fd_set fds;
+ int nfds;
+ int len;
+ int res = 0;
+
+ type = htonl(type);
+ memcpy(&msg->ip, &serverip.s_addr, sizeof(msg->ip));
+ set_nonblock(0);
+ sendto(s, msgbuf, sizeof(struct ead_msg) + ntohl(msg->len), 0, (struct sockaddr *) &remote, sizeof(remote));
+ set_nonblock(1);
+
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+
+ FD_ZERO(&fds);
+ do {
+ FD_SET(s, &fds);
+ nfds = select(s + 1, &fds, NULL, NULL, &tv);
+
+ if (nfds <= 0)
+ break;
+
+ if (!FD_ISSET(s, &fds))
+ break;
+
+ len = read(s, msgbuf, sizeof(msgbuf));
+ if (len < 0)
+ break;
+
+ if (len < sizeof(struct ead_msg))
+ continue;
+
+ if (len < sizeof(struct ead_msg) + ntohl(msg->len))
+ continue;
+
+ if (msg->magic != htonl(EAD_MAGIC))
+ continue;
+
+ if ((nid != 0xffff) && (ntohs(msg->nid) != nid))
+ continue;
+
+ if (msg->type != type)
+ continue;
+
+ if (handler())
+ res++;
+
+ if ((max > 0) && (res >= max))
+ break;
+ } while (1);
+
+ return res;
+}
+
+static void
+prepare_password(void)
+{
+ switch(auth_type) {
+ case EAD_AUTH_DEFAULT:
+ break;
+ case EAD_AUTH_MD5:
+ md5_crypt(pw_md5, (unsigned char *) password, (unsigned char *) pw_salt);
+ strncpy(password, pw_md5, sizeof(password));
+ break;
+ }
+}
+
+static bool
+handle_pong(void)
+{
+ struct ead_msg_pong *pong = EAD_DATA(msg, pong);
+ int len = ntohl(msg->len) - sizeof(struct ead_msg_pong);
+
+ if (len <= 0)
+ return false;
+
+ pong->name[len] = 0;
+ auth_type = ntohs(pong->auth_type);
+ if (nid == 0xffff)
+ printf("%04x: %s\n", ntohs(msg->nid), pong->name);
+ sid = msg->sid;
+ return true;
+}
+
+static bool
+handle_prime(void)
+{
+ struct ead_msg_salt *sb = EAD_DATA(msg, salt);
+
+ salt.len = sb->len;
+ memcpy(salt.data, sb->salt, salt.len);
+
+ if (auth_type == EAD_AUTH_MD5) {
+ memcpy(pw_salt, sb->ext_salt, MAXSALTLEN);
+ pw_salt[MAXSALTLEN - 1] = 0;
+ }
+
+ tcp = t_getpreparam(sb->prime);
+ tc = t_clientopen(username, &tcp->modulus, &tcp->generator, &salt);
+ if (!tc) {
+ fprintf(stderr, "Client open failed\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+handle_b(void)
+{
+ struct ead_msg_number *num = EAD_DATA(msg, number);
+ int len = ntohl(msg->len) - sizeof(struct ead_msg_number);
+
+ B.data = bbuf;
+ B.len = len;
+ memcpy(bbuf, num->data, len);
+ return true;
+}
+
+static bool
+handle_none(void)
+{
+ return true;
+}
+
+static bool
+handle_done_auth(void)
+{
+ struct ead_msg_auth *auth = EAD_DATA(msg, auth);
+ if (t_clientverify(tc, auth->data) != 0) {
+ fprintf(stderr, "Client auth verify failed\n");
+ return false;
+ }
+ return true;
+}
+
+static bool
+handle_cmd_data(void)
+{
+ struct ead_msg_cmd_data *cmd = EAD_ENC_DATA(msg, cmd_data);
+ int datalen = ead_decrypt_message(msg) - sizeof(struct ead_msg_cmd_data);
+
+ if (datalen < 0)
+ return false;
+
+ if (datalen > 0) {
+ write(1, cmd->data, datalen);
+ }
+
+ return !!cmd->done;
+}
+static int
+send_ping(void)
+{
+ msg->type = htonl(EAD_TYPE_PING);
+ msg->len = 0;
+ return send_packet(EAD_TYPE_PONG, handle_pong, (nid == 0xffff ? 0 : 1));
+}
+
+static int
+send_username(void)
+{
+ msg->type = htonl(EAD_TYPE_SET_USERNAME);
+ msg->len = htonl(sizeof(struct ead_msg_user));
+ strcpy(EAD_DATA(msg, user)->username, username);
+ return send_packet(EAD_TYPE_ACK_USERNAME, handle_none, 1);
+}
+
+static int
+get_prime(void)
+{
+ msg->type = htonl(EAD_TYPE_GET_PRIME);
+ msg->len = 0;
+ return send_packet(EAD_TYPE_PRIME, handle_prime, 1);
+}
+
+static int
+send_a(void)
+{
+ struct ead_msg_number *num = EAD_DATA(msg, number);
+ A = t_clientgenexp(tc);
+ msg->type = htonl(EAD_TYPE_SEND_A);
+ msg->len = htonl(sizeof(struct ead_msg_number) + A->len);
+ memcpy(num->data, A->data, A->len);
+ return send_packet(EAD_TYPE_SEND_B, handle_b, 1);
+}
+
+static int
+send_auth(void)
+{
+ struct ead_msg_auth *auth = EAD_DATA(msg, auth);
+
+ prepare_password();
+ t_clientpasswd(tc, password);
+ skey = t_clientgetkey(tc, &B);
+ if (!skey)
+ return 0;
+
+ ead_set_key(skey);
+ msg->type = htonl(EAD_TYPE_SEND_AUTH);
+ msg->len = htonl(sizeof(struct ead_msg_auth));
+ memcpy(auth->data, t_clientresponse(tc), sizeof(auth->data));
+ return send_packet(EAD_TYPE_DONE_AUTH, handle_done_auth, 1);
+}
+
+static int
+send_command(const char *command)
+{
+ struct ead_msg_cmd *cmd = EAD_ENC_DATA(msg, cmd);
+
+ msg->type = htonl(EAD_TYPE_SEND_CMD);
+ cmd->type = htons(EAD_CMD_NORMAL);
+ cmd->timeout = htons(10);
+ strncpy((char *)cmd->data, command, 1024);
+ ead_encrypt_message(msg, sizeof(struct ead_msg_cmd) + strlen(command) + 1);
+ return send_packet(EAD_TYPE_RESULT_CMD, handle_cmd_data, 1);
+}
+
+
+static int
+usage(const char *prog)
+{
+ fprintf(stderr, "Usage: %s [-s <addr>] [-b <addr>] <node> <username>[:<password>] <command>\n"
+ "\n"
+ "\t-s <addr>: Set the server's source address to <addr>\n"
+ "\t-b <addr>: Set the broadcast address to <addr>\n"
+ "\t<node>: Node ID (4 digits hex)\n"
+ "\t<username>: Username to authenticate with\n"
+ "\n"
+ "\tPassing no arguments shows a list of active nodes on the network\n"
+ "\n", prog);
+ return -1;
+}
+
+
+int main(int argc, char **argv)
+{
+ int val = 1;
+ char *st = NULL;
+ const char *command = NULL;
+ const char *prog = argv[0];
+ int ch;
+
+ msg->magic = htonl(EAD_MAGIC);
+ msg->sid = 0;
+
+ memset(&local, 0, sizeof(local));
+ memset(&remote, 0, sizeof(remote));
+
+ remote.sin_family = AF_INET;
+ remote.sin_addr.s_addr = 0xffffffff;
+ remote.sin_port = htons(EAD_PORT);
+
+ local.sin_family = AF_INET;
+ local.sin_addr.s_addr = INADDR_ANY;
+ local.sin_port = 0;
+
+ while ((ch = getopt(argc, argv, "b:s:h")) != -1) {
+ switch(ch) {
+ case 's':
+ inet_aton(optarg, &serverip);
+ break;
+ case 'b':
+ inet_aton(optarg, &remote.sin_addr);
+ break;
+ case 'h':
+ return usage(prog);
+ }
+ }
+ argv += optind;
+ argc -= optind;
+
+ switch(argc) {
+ case 3:
+ command = argv[2];
+ /* fall through */
+ case 2:
+ username = argv[1];
+ st = strchr(username, ':');
+ if (st) {
+ *st = 0;
+ st++;
+ strncpy(password, st, sizeof(password));
+ password[sizeof(password) - 1] = 0;
+ /* hide command line password */
+ memset(st, 0, strlen(st));
+ }
+ /* fall through */
+ case 1:
+ nid = strtoul(argv[0], &st, 16);
+ if (st && st[0] != 0)
+ return usage(prog);
+ /* fall through */
+ case 0:
+ break;
+ default:
+ return usage(prog);
+ }
+
+ msg->nid = htons(nid);
+ s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (s < 0) {
+ perror("socket");
+ return -1;
+ }
+
+ setsockopt(s, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val));
+
+ if (bind(s, (struct sockaddr *)&local, sizeof(local)) < 0) {
+ perror("bind");
+ return -1;
+ }
+ sockflags = fcntl(s, F_GETFL);
+
+ if (!send_ping()) {
+ fprintf(stderr, "No devices found\n");
+ return 1;
+ }
+
+ if (nid == 0xffff)
+ return 0;
+
+ if (!username || !password[0])
+ return 0;
+
+ if (!send_username()) {
+ fprintf(stderr, "Device did not accept user name\n");
+ return 1;
+ }
+ timeout = EAD_TIMEOUT_LONG;
+ if (!get_prime()) {
+ fprintf(stderr, "Failed to get user password info\n");
+ return 1;
+ }
+ if (!send_a()) {
+ fprintf(stderr, "Failed to send local authentication data\n");
+ return 1;
+ }
+ if (!send_auth()) {
+ fprintf(stderr, "Authentication failed\n");
+ return 1;
+ }
+ if (!command) {
+ fprintf(stderr, "Authentication succesful\n");
+ return 0;
+ }
+ if (!send_command(command)) {
+ fprintf(stderr, "Command failed\n");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/package/ead/src/ead-crypt.c b/package/ead/src/ead-crypt.c
new file mode 100644
index 000000000..03721721d
--- /dev/null
+++ b/package/ead/src/ead-crypt.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
+ *
+ * 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.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include "ead.h"
+
+#include "sha1.c"
+#include "aes.c"
+
+#if EAD_DEBUGLEVEL >= 1
+#define DEBUG(n, format, ...) do { \
+ if (EAD_DEBUGLEVEL >= n) \
+ fprintf(stderr, format, ##__VA_ARGS__); \
+} while (0);
+
+#else
+#define DEBUG(n, format, ...) do {} while(0)
+#endif
+
+
+static uint32_t aes_enc_ctx[AES_PRIV_SIZE];
+static uint32_t aes_dec_ctx[AES_PRIV_SIZE];
+static uint32_t ead_rx_iv;
+static uint32_t ead_tx_iv;
+static uint32_t ivofs_vec;
+static unsigned int ivofs_idx = 0;
+static uint32_t W[80]; /* work space for sha1 */
+
+#define EAD_ENC_PAD 64
+
+void
+ead_set_key(unsigned char *skey)
+{
+ uint32_t *ivp = (uint32_t *)skey;
+
+ memset(aes_enc_ctx, 0, sizeof(aes_enc_ctx));
+ memset(aes_dec_ctx, 0, sizeof(aes_dec_ctx));
+
+ /* first 32 bytes of skey are used as aes key for
+ * encryption and decryption */
+ rijndaelKeySetupEnc(aes_enc_ctx, skey);
+ rijndaelKeySetupDec(aes_dec_ctx, skey);
+
+ /* the following bytes are used as initialization vector for messages
+ * (highest byte cleared to avoid overflow) */
+ ivp += 8;
+ ead_rx_iv = ntohl(*ivp) & 0x00ffffff;
+ ead_tx_iv = ead_rx_iv;
+
+ /* the last bytes are used to feed the random iv increment */
+ ivp++;
+ ivofs_vec = *ivp;
+}
+
+
+static bool
+ead_check_rx_iv(uint32_t iv)
+{
+ if (iv <= ead_rx_iv)
+ return false;
+
+ if (iv > ead_rx_iv + EAD_MAX_IV_INCR)
+ return false;
+
+ ead_rx_iv = iv;
+ return true;
+}
+
+
+static uint32_t
+ead_get_tx_iv(void)
+{
+ unsigned int ofs;
+
+ ofs = 1 + ((ivofs_vec >> 2 * ivofs_idx) & 0x3);
+ ivofs_idx = (ivofs_idx + 1) % 16;
+ ead_tx_iv += ofs;
+
+ return ead_tx_iv;
+}
+
+static void
+ead_hash_message(struct ead_msg_encrypted *enc, uint32_t *hash, int len)
+{
+ unsigned char *data = (unsigned char *) enc;
+
+ /* hash the packet with the stored hash part initialized to zero */
+ sha_init(hash);
+ memset(enc->hash, 0, sizeof(enc->hash));
+ while (len > 0) {
+ sha_transform(hash, data, W);
+ len -= 64;
+ data += 64;
+ }
+}
+
+void
+ead_encrypt_message(struct ead_msg *msg, unsigned int len)
+{
+ struct ead_msg_encrypted *enc = EAD_DATA(msg, enc);
+ unsigned char *data = (unsigned char *) enc;
+ uint32_t hash[5];
+ int enclen, i;
+
+ len += sizeof(struct ead_msg_encrypted);
+ enc->pad = (EAD_ENC_PAD - (len % EAD_ENC_PAD)) % EAD_ENC_PAD;
+ enclen = len + enc->pad;
+ msg->len = htonl(enclen);
+ enc->iv = htonl(ead_get_tx_iv());
+
+ ead_hash_message(enc, hash, enclen);
+ for (i = 0; i < 5; i++)
+ enc->hash[i] = htonl(hash[i]);
+ DEBUG(2, "SHA1 generate (0x%08x), len=%d\n", enc->hash[0], enclen);
+
+ while (enclen > 0) {
+ rijndaelEncrypt(aes_enc_ctx, data, data);
+ data += 16;
+ enclen -= 16;
+ }
+}
+
+int
+ead_decrypt_message(struct ead_msg *msg)
+{
+ struct ead_msg_encrypted *enc = EAD_DATA(msg, enc);
+ unsigned char *data = (unsigned char *) enc;
+ uint32_t hash_old[5], hash_new[5];
+ int len = ntohl(msg->len);
+ int i, enclen = len;
+
+ if (!len || (len % EAD_ENC_PAD > 0))
+ return 0;
+
+ while (len > 0) {
+ rijndaelDecrypt(aes_dec_ctx, data, data);
+ data += 16;
+ len -= 16;
+ }
+
+ data = (unsigned char *) enc;
+
+ if (enc->pad >= EAD_ENC_PAD) {
+ DEBUG(2, "Invalid padding length\n");
+ return 0;
+ }
+
+ if (!ead_check_rx_iv(ntohl(enc->iv))) {
+ DEBUG(2, "RX IV mismatch (0x%08x <> 0x%08x)\n", ead_rx_iv, ntohl(enc->iv));
+ return 0;
+ }
+
+ for (i = 0; i < 5; i++)
+ hash_old[i] = ntohl(enc->hash[i]);
+ ead_hash_message(enc, hash_new, enclen);
+ if (memcmp(hash_old, hash_new, sizeof(hash_old)) != 0) {
+ DEBUG(2, "SHA1 mismatch (0x%08x != 0x%08x), len=%d\n", hash_old[0], hash_new[0], enclen);
+ return 0;
+ }
+
+ enclen -= enc->pad + sizeof(struct ead_msg_encrypted);
+ return enclen;
+}
diff --git a/package/ead/src/ead-crypt.h b/package/ead/src/ead-crypt.h
new file mode 100644
index 000000000..831ec8a28
--- /dev/null
+++ b/package/ead/src/ead-crypt.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
+ *
+ * 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.
+ */
+
+#ifndef __EAD_CRYPT_H
+#define __EAD_CRYPT_H
+
+extern void ead_set_key(unsigned char *skey);
+extern void ead_encrypt_message(struct ead_msg *msg, unsigned int len);
+extern int ead_decrypt_message(struct ead_msg *msg);
+
+#endif
diff --git a/package/ead/src/ead-pcap.h b/package/ead/src/ead-pcap.h
new file mode 100644
index 000000000..0652ab48f
--- /dev/null
+++ b/package/ead/src/ead-pcap.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * 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.
+ *
+ * This file was part of the uIP TCP/IP stack.
+ *
+ */
+#ifndef __EAD_PCAP_H
+#define __EAD_PCAP_H
+
+#include <net/ethernet.h>
+#include <stdint.h>
+#include "ead.h"
+
+typedef uint8_t u8_t;
+typedef uint16_t u16_t;
+
+/* The UDP and IP headers. */
+struct ead_packet {
+ struct ether_header eh;
+ /* IP header. */
+ u8_t vhl,
+ tos,
+ len[2],
+ ipid[2],
+ ipoffset[2],
+ ttl,
+ proto;
+ u16_t ipchksum;
+ u16_t srcipaddr[2],
+ destipaddr[2];
+
+ /* UDP header. */
+ u16_t srcport,
+ destport;
+ u16_t udplen;
+ u16_t udpchksum;
+
+ struct ead_msg msg;
+} __attribute__((packed));
+
+#define UIP_PROTO_UDP 17
+#define UIP_IPH_LEN 20 /* Size of IP header */
+#define UIP_UDPH_LEN 8 /* Size of UDP header */
+#define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN)
+
+#endif
diff --git a/package/ead/src/ead.c b/package/ead/src/ead.c
new file mode 100644
index 000000000..36235207b
--- /dev/null
+++ b/package/ead/src/ead.c
@@ -0,0 +1,991 @@
+/*
+ * Emergency Access Daemon
+ * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
+ *
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/select.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <pcap.h>
+#include <pcap-bpf.h>
+#include <t_pwd.h>
+#include <t_read.h>
+#include <t_sha.h>
+#include <t_defines.h>
+#include <t_server.h>
+
+#include "list.h"
+#include "ead.h"
+#include "ead-pcap.h"
+#include "ead-crypt.h"
+
+#include "filter.c"
+
+#ifdef linux
+#include "libbridge_init.c"
+#endif
+
+#ifdef linux
+#include <linux/if_packet.h>
+#endif
+
+#define PASSWD_FILE "/etc/passwd"
+
+#ifndef DEFAULT_IFNAME
+#define DEFAULT_IFNAME "eth0"
+#endif
+
+#ifndef DEFAULT_DEVNAME
+#define DEFAULT_DEVNAME "Unknown"
+#endif
+
+#define PCAP_MRU 1600
+#define PCAP_TIMEOUT 200
+
+#if EAD_DEBUGLEVEL >= 1
+#define DEBUG(n, format, ...) do { \
+ if (EAD_DEBUGLEVEL >= n) \
+ fprintf(stderr, format, ##__VA_ARGS__); \
+} while (0);
+
+#else
+#define DEBUG(n, format, ...) do {} while(0)
+#endif
+
+struct ead_instance {
+ struct list_head list;
+ char ifname[16];
+ int pid;
+ char id;
+#ifdef linux
+ char bridge[16];
+ bool br_check;
+#endif
+};
+
+static char ethmac[6] = "\x00\x13\x37\x00\x00\x00"; /* last 3 bytes will be randomized */
+static pcap_t *pcap_fp = NULL;
+static pcap_t *pcap_fp_rx = NULL;
+static char pktbuf_b[PCAP_MRU];
+static struct ead_packet *pktbuf = (struct ead_packet *)pktbuf_b;
+static u16_t nid = 0xffff; /* node id */
+static char username[32] = "";
+static int state = EAD_TYPE_SET_USERNAME;
+static const char *passwd_file = PASSWD_FILE;
+static const char password[MAXPARAMLEN];
+static bool child_pending = false;
+
+static unsigned char abuf[MAXPARAMLEN + 1];
+static unsigned char pwbuf[MAXPARAMLEN];
+static unsigned char saltbuf[MAXSALTLEN];
+static unsigned char pw_saltbuf[MAXSALTLEN];
+static struct list_head instances;
+static const char *dev_name = DEFAULT_DEVNAME;
+static bool nonfork = false;
+static struct ead_instance *instance = NULL;
+
+static struct t_pwent tpe = {
+ .name = username,
+ .index = 1,
+ .password.data = pwbuf,
+ .password.len = 0,
+ .salt.data = saltbuf,
+ .salt.len = 0,
+};
+struct t_confent *tce = NULL;
+static struct t_server *ts = NULL;
+static struct t_num A, *B = NULL;
+unsigned char *skey;
+
+static void
+set_recv_type(pcap_t *p, bool rx)
+{
+#ifdef PACKET_RECV_TYPE
+ struct sockaddr_ll sll;
+ struct ifreq ifr;
+ int ifindex, mask;
+ int fd, ret;
+
+ fd = pcap_get_selectable_fd(p);
+ if (fd < 0)
+ return;
+
+ if (rx)
+ mask = 1 << PACKET_BROADCAST;
+ else
+ mask = 0;
+
+ ret = setsockopt(fd, SOL_PACKET, PACKET_RECV_TYPE, &mask, sizeof(mask));
+#endif
+}
+
+
+static pcap_t *
+ead_open_pcap(const char *ifname, char *errbuf, bool rx)
+{
+ pcap_t *p;
+
+ p = pcap_create(ifname, errbuf);
+ if (p == NULL)
+ goto out;
+
+ pcap_set_snaplen(p, PCAP_MRU);
+ pcap_set_promisc(p, rx);
+ pcap_set_timeout(p, PCAP_TIMEOUT);
+#ifdef HAS_PROTO_EXTENSION
+ pcap_set_protocol(p, (rx ? htons(ETH_P_IP) : 0));
+#endif
+ pcap_set_buffer_size(p, (rx ? 10 : 1) * PCAP_MRU);
+ pcap_activate(p);
+ set_recv_type(p, rx);
+out:
+ return p;
+}
+
+static void
+get_random_bytes(void *ptr, int len)
+{
+ int fd;
+
+ fd = open("/dev/urandom", O_RDONLY);
+ if (fd < 0) {
+ perror("open");
+ exit(1);
+ }
+ read(fd, ptr, len);
+ close(fd);
+}
+
+static bool
+prepare_password(void)
+{
+ static char lbuf[1024];
+ unsigned char dig[SHA_DIGESTSIZE];
+ BigInteger x, v, n, g;
+ SHA1_CTX ctxt;
+ int ulen = strlen(username);
+ FILE *f;
+
+ lbuf[sizeof(lbuf) - 1] = 0;
+
+ f = fopen(passwd_file, "r");
+ if (!f)
+ return false;
+
+ while (fgets(lbuf, sizeof(lbuf) - 1, f) != NULL) {
+ char *str, *s2;
+
+ if (strncmp(lbuf, username, ulen) != 0)
+ continue;
+
+ if (lbuf[ulen] != ':')
+ continue;
+
+ str = &lbuf[ulen + 1];
+
+ if (strncmp(str, "$1$", 3) != 0)
+ continue;
+
+ s2 = strchr(str + 3, '$');
+ if (!s2)
+ continue;
+
+ if (s2 - str >= MAXSALTLEN)
+ continue;
+
+ strncpy((char *) pw_saltbuf, str, s2 - str);
+ pw_saltbuf[s2 - str] = 0;
+
+ s2 = strchr(s2, ':');
+ if (!s2)
+ continue;
+
+ *s2 = 0;
+ if (s2 - str >= MAXPARAMLEN)
+ continue;
+
+ strncpy((char *)password, str, MAXPARAMLEN);
+ fclose(f);
+ goto hash_password;
+ }
+
+ /* not found */
+ fclose(f);
+ return false;
+
+hash_password:
+ tce = gettcid(tpe.index);
+ do {
+ t_random(tpe.password.data, SALTLEN);
+ } while (memcmp(saltbuf, (char *)dig, sizeof(saltbuf)) == 0);
+ if (saltbuf[0] == 0)
+ saltbuf[0] = 0xff;
+
+ n = BigIntegerFromBytes(tce->modulus.data, tce->modulus.len);
+ g = BigIntegerFromBytes(tce->generator.data, tce->generator.len);
+ v = BigIntegerFromInt(0);
+
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, (unsigned char *) username, strlen(username));
+ SHA1Update(&ctxt, (unsigned char *) ":", 1);
+ SHA1Update(&ctxt, (unsigned char *) password, strlen(password));
+ SHA1Final(dig, &ctxt);
+
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, saltbuf, tpe.salt.len);
+ SHA1Update(&ctxt, dig, sizeof(dig));
+ SHA1Final(dig, &ctxt);
+
+ /* x = H(s, H(u, ':', p)) */
+ x = BigIntegerFromBytes(dig, sizeof(dig));
+
+ BigIntegerModExp(v, g, x, n);
+ tpe.password.len = BigIntegerToBytes(v, (unsigned char *)pwbuf);
+
+ BigIntegerFree(v);
+ BigIntegerFree(x);
+ BigIntegerFree(g);
+ BigIntegerFree(n);
+ return true;
+}
+
+static u16_t
+chksum(u16_t sum, const u8_t *data, u16_t len)
+{
+ u16_t t;
+ const u8_t *dataptr;
+ const u8_t *last_byte;
+
+ dataptr = data;
+ last_byte = data + len - 1;
+
+ while(dataptr < last_byte) { /* At least two more bytes */
+ t = (dataptr[0] << 8) + dataptr[1];
+ sum += t;
+ if(sum < t) {
+ sum++; /* carry */
+ }
+ dataptr += 2;
+ }
+
+ if(dataptr == last_byte) {
+ t = (dataptr[0] << 8) + 0;
+ sum += t;
+ if(sum < t) {
+ sum++; /* carry */
+ }
+ }
+
+ /* Return sum in host byte order. */
+ return sum;
+}
+
+static void
+ead_send_packet_clone(struct ead_packet *pkt)
+{
+ u16_t len, sum;
+
+ memcpy(pktbuf, pkt, offsetof(struct ead_packet, msg));
+ memcpy(pktbuf->eh.ether_shost, ethmac, 6);
+ memcpy(pktbuf->eh.ether_dhost, pkt->eh.ether_shost, 6);
+
+ /* ip header */
+ len = sizeof(struct ead_packet) - sizeof(struct ether_header) + ntohl(pktbuf->msg.len);
+ pktbuf->len[0] = len >> 8;
+ pktbuf->len[1] = len & 0xff;
+ memcpy(pktbuf->srcipaddr, &pkt->msg.ip, 4);
+ memcpy(pktbuf->destipaddr, pkt->srcipaddr, 4);
+
+ /* ip checksum */
+ pktbuf->ipchksum = 0;
+ sum = chksum(0, (void *) &pktbuf->vhl, UIP_IPH_LEN);
+ if (sum == 0)
+ sum = 0xffff;
+ pktbuf->ipchksum = htons(~sum);
+
+ /* udp header */
+ pktbuf->srcport = pkt->destport;
+ pktbuf->destport = pkt->srcport;
+
+ /* udp checksum */
+ len -= UIP_IPH_LEN;
+ pktbuf->udplen = htons(len);
+ pktbuf->udpchksum = 0;
+ sum = len + UIP_PROTO_UDP;
+ sum = chksum(sum, (void *) &pktbuf->srcipaddr[0], 8); /* src, dest ip */
+ sum = chksum(sum, (void *) &pktbuf->srcport, len);
+ if (sum == 0)
+ sum = 0xffff;
+ pktbuf->udpchksum = htons(~sum);
+ pcap_sendpacket(pcap_fp, (void *) pktbuf, sizeof(struct ead_packet) + ntohl(pktbuf->msg.len));
+}
+
+static void
+set_state(int nstate)
+{
+ if (state == nstate)
+ return;
+
+ if (nstate < state) {
+ if ((nstate < EAD_TYPE_GET_PRIME) &&
+ (state >= EAD_TYPE_GET_PRIME)) {
+ t_serverclose(ts);
+ ts = NULL;
+ }
+ goto done;
+ }
+
+ switch(state) {
+ case EAD_TYPE_SET_USERNAME:
+ if (!prepare_password())
+ goto error;
+ ts = t_serveropenraw(&tpe, tce);
+ if (!ts)
+ goto error;
+ break;
+ case EAD_TYPE_GET_PRIME:
+ B = t_servergenexp(ts);
+ break;
+ case EAD_TYPE_SEND_A:
+ skey = t_servergetkey(ts, &A);
+ if (!skey)
+ goto error;
+
+ ead_set_key(skey);
+ break;
+ }
+done:
+ state = nstate;
+error:
+ return;
+}
+
+static bool
+handle_ping(struct ead_packet *pkt, int len, int *nstate)
+{
+ struct ead_msg *msg = &pktbuf->msg;
+ struct ead_msg_pong *pong = EAD_DATA(msg, pong);
+ int slen;
+
+ slen = strlen(dev_name);
+ if (slen > 1024)
+ slen = 1024;
+
+ msg->len = htonl(sizeof(struct ead_msg_pong) + slen);
+ strncpy(pong->name, dev_name, slen);
+ pong->name[slen] = 0;
+ pong->auth_type = htons(EAD_AUTH_MD5);
+
+ return true;
+}
+
+static bool
+handle_set_username(struct ead_packet *pkt, int len, int *nstate)
+{
+ struct ead_msg *msg = &pkt->msg;
+ struct ead_msg_user *user = EAD_DATA(msg, user);
+
+ set_state(EAD_TYPE_SET_USERNAME); /* clear old state */
+ strncpy(username, user->username, sizeof(username));
+ username[sizeof(username) - 1] = 0;
+
+ msg = &pktbuf->msg;
+ msg->len = 0;
+
+ *nstate = EAD_TYPE_GET_PRIME;
+ return true;
+}
+
+static bool
+handle_get_prime(struct ead_packet *pkt, int len, int *nstate)
+{
+ struct ead_msg *msg = &pktbuf->msg;
+ struct ead_msg_salt *salt = EAD_DATA(msg, salt);
+
+ msg->len = htonl(sizeof(struct ead_msg_salt));
+ salt->prime = tce->index - 1;
+ salt->len = ts->s.len;
+ memcpy(salt->salt, ts->s.data, ts->s.len);
+ memcpy(salt->ext_salt, pw_saltbuf, MAXSALTLEN);
+
+ *nstate = EAD_TYPE_SEND_A;
+ return true;
+}
+
+static bool
+handle_send_a(struct ead_packet *pkt, int len, int *nstate)
+{
+ struct ead_msg *msg = &pkt->msg;
+ struct ead_msg_number *number = EAD_DATA(msg, number);
+ len = ntohl(msg->len) - sizeof(struct ead_msg_number);
+
+ if (len > MAXPARAMLEN + 1)
+ return false;
+
+ A.len = len;
+ A.data = abuf;
+ memcpy(A.data, number->data, len);
+
+ msg = &pktbuf->msg;
+ number = EAD_DATA(msg, number);
+ msg->len = htonl(sizeof(struct ead_msg_number) + B->len);
+ memcpy(number->data, B->data, B->len);
+
+ *nstate = EAD_TYPE_SEND_AUTH;
+ return true;
+}
+
+static bool
+handle_send_auth(struct ead_packet *pkt, int len, int *nstate)
+{
+ struct ead_msg *msg = &pkt->msg;
+ struct ead_msg_auth *auth = EAD_DATA(msg, auth);
+
+ if (t_serververify(ts, auth->data) != 0) {
+ DEBUG(2, "Client authentication failed\n");
+ *nstate = EAD_TYPE_SET_USERNAME;
+ return false;
+ }
+
+ msg = &pktbuf->msg;
+ auth = EAD_DATA(msg, auth);
+ msg->len = htonl(sizeof(struct ead_msg_auth));
+
+ DEBUG(2, "Client authentication successful\n");
+ memcpy(auth->data, t_serverresponse(ts), sizeof(auth->data));
+
+ *nstate = EAD_TYPE_SEND_CMD;
+ return true;
+}
+
+static bool
+handle_send_cmd(struct ead_packet *pkt, int len, int *nstate)
+{
+ struct ead_msg *msg = &pkt->msg;
+ struct ead_msg_cmd *cmd = EAD_ENC_DATA(msg, cmd);
+ struct ead_msg_cmd_data *cmddata;
+ struct timeval tv, to, tn;
+ int pfd[2], fd;
+ fd_set fds;
+ pid_t pid;
+ bool stream = false;
+ int timeout;
+ int type;
+ int datalen;
+
+ datalen = ead_decrypt_message(msg) - sizeof(struct ead_msg_cmd);
+ if (datalen <= 0)
+ return false;
+
+ type = ntohs(cmd->type);
+ timeout = ntohs(cmd->timeout);
+
+ FD_ZERO(&fds);
+ cmd->data[datalen] = 0;
+ switch(type) {
+ case EAD_CMD_NORMAL:
+ if (pipe(pfd) < 0)
+ return false;
+
+ fcntl(pfd[0], F_SETFL, O_NONBLOCK | fcntl(pfd[0], F_GETFL));
+ child_pending = true;
+ pid = fork();
+ if (pid == 0) {
+ close(pfd[0]);
+ fd = open("/dev/null", O_RDWR);
+ if (fd > 0) {
+ dup2(fd, 0);
+ dup2(pfd[1], 1);
+ dup2(pfd[1], 2);
+ }
+ system((char *)cmd->data);
+ exit(0);
+ } else if (pid > 0) {
+ close(pfd[1]);
+ if (!timeout)
+ timeout = EAD_CMD_TIMEOUT;
+
+ stream = true;
+ break;
+ }
+ return false;
+ case EAD_CMD_BACKGROUND:
+ pid = fork();
+ if (pid == 0) {
+ /* close stdin, stdout, stderr, replace with fd to /dev/null */
+ fd = open("/dev/null", O_RDWR);
+ if (fd > 0) {
+ dup2(fd, 0);
+ dup2(fd, 1);
+ dup2(fd, 2);
+ }
+ system((char *)cmd->data);
+ exit(0);
+ } else if (pid > 0) {
+ break;
+ }
+ return false;
+ default:
+ return false;
+ }
+
+ msg = &pktbuf->msg;
+ cmddata = EAD_ENC_DATA(msg, cmd_data);
+
+ if (stream) {
+ int nfds, bytes;
+
+ /* send keepalive packets every 200 ms so that the client doesn't timeout */
+ gettimeofday(&to, NULL);
+ memcpy(&tn, &to, sizeof(tn));
+ tv.tv_usec = PCAP_TIMEOUT * 1000;
+ tv.tv_sec = 0;
+ do {
+ cmddata->done = 0;
+ FD_SET(pfd[0], &fds);
+ nfds = select(pfd[0] + 1, &fds, NULL, NULL, &tv);
+ bytes = 0;
+ if (nfds > 0) {
+ bytes = read(pfd[0], cmddata->data, 1024);
+ if (bytes < 0)
+ bytes = 0;
+ }
+ if (!bytes && !child_pending)
+ break;
+ DEBUG(3, "Sending %d bytes of console data, type=%d, timeout=%d\n", bytes, ntohl(msg->type), timeout);
+ ead_encrypt_message(msg, sizeof(struct ead_msg_cmd_data) + bytes);
+ ead_send_packet_clone(pkt);
+ gettimeofday(&tn, NULL);
+ } while (tn.tv_sec < to.tv_sec + timeout);
+ if (child_pending) {
+ kill(pid, SIGKILL);
+ return false;
+ }
+ }
+ cmddata->done = 1;
+ ead_encrypt_message(msg, sizeof(struct ead_msg_cmd_data));
+
+ return true;
+}
+
+
+
+static void
+parse_message(struct ead_packet *pkt, int len)
+{
+ bool (*handler)(struct ead_packet *pkt, int len, int *nstate);
+ int min_len = sizeof(struct ead_packet);
+ int nstate = state;
+ int type = ntohl(pkt->msg.type);
+
+ if ((type >= EAD_TYPE_GET_PRIME) &&
+ (state != type))
+ return;
+
+ if ((type != EAD_TYPE_PING) &&
+ ((ntohs(pkt->msg.sid) & EAD_INSTANCE_MASK) >>
+ EAD_INSTANCE_SHIFT) != instance->id)
+ return;
+
+ switch(type) {
+ case EAD_TYPE_PING:
+ handler = handle_ping;
+ break;
+ case EAD_TYPE_SET_USERNAME:
+ handler = handle_set_username;
+ min_len += sizeof(struct ead_msg_user);
+ break;
+ case EAD_TYPE_GET_PRIME:
+ handler = handle_get_prime;
+ break;
+ case EAD_TYPE_SEND_A:
+ handler = handle_send_a;
+ min_len += sizeof(struct ead_msg_number);
+ break;
+ case EAD_TYPE_SEND_AUTH:
+ handler = handle_send_auth;
+ min_len += sizeof(struct ead_msg_auth);
+ break;
+ case EAD_TYPE_SEND_CMD:
+ handler = handle_send_cmd;
+ min_len += sizeof(struct ead_msg_cmd) + sizeof(struct ead_msg_encrypted);
+ break;
+ default:
+ return;
+ }
+
+ if (len < min_len) {
+ DEBUG(2, "discarding packet: message too small\n");
+ return;
+ }
+
+ pktbuf->msg.magic = htonl(EAD_MAGIC);
+ pktbuf->msg.type = htonl(type + 1);
+ pktbuf->msg.nid = htons(nid);
+ pktbuf->msg.sid = pkt->msg.sid;
+ pktbuf->msg.len = 0;
+
+ if (handler(pkt, len, &nstate)) {
+ DEBUG(2, "sending response to packet type %d: %d\n", type + 1, ntohl(pktbuf->msg.len));
+ /* format response packet */
+ ead_send_packet_clone(pkt);
+ }
+ set_state(nstate);
+}
+
+static void
+handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
+{
+ struct ead_packet *pkt = (struct ead_packet *) bytes;
+
+ if (h->len < sizeof(struct ead_packet))
+ return;
+
+ if (pkt->eh.ether_type != htons(ETHERTYPE_IP))
+ return;
+
+ if (memcmp(pkt->eh.ether_dhost, "\xff\xff\xff\xff\xff\xff", 6) != 0)
+ return;
+
+ if (pkt->proto != UIP_PROTO_UDP)
+ return;
+
+ if (pkt->destport != htons(EAD_PORT))
+ return;
+
+ if (pkt->msg.magic != htonl(EAD_MAGIC))
+ return;
+
+ if (h->len < sizeof(struct ead_packet) + ntohl(pkt->msg.len))
+ return;
+
+ if ((pkt->msg.nid != 0xffff) &&
+ (pkt->msg.nid != htons(nid)))
+ return;
+
+ parse_message(pkt, h->len);
+}
+
+static void
+ead_pcap_reopen(bool first)
+{
+ static char errbuf[PCAP_ERRBUF_SIZE] = "";
+
+ if (pcap_fp_rx && (pcap_fp_rx != pcap_fp))
+ pcap_close(pcap_fp_rx);
+
+ if (pcap_fp)
+ pcap_close(pcap_fp);
+
+ pcap_fp_rx = NULL;
+ do {
+#ifdef linux
+ if (instance->bridge[0]) {
+ pcap_fp_rx = ead_open_pcap(instance->bridge, errbuf, 1);
+ pcap_fp = ead_open_pcap(instance->ifname, errbuf, 0);
+ } else
+#endif
+ {
+ pcap_fp = ead_open_pcap(instance->ifname, errbuf, 1);
+ }
+
+ if (!pcap_fp_rx)
+ pcap_fp_rx = pcap_fp;
+ if (first && !pcap_fp) {
+ DEBUG(1, "WARNING: unable to open interface '%s'\n", instance->ifname);
+ first = false;
+ }
+ if (!pcap_fp)
+ sleep(1);
+ } while (!pcap_fp);
+ pcap_setfilter(pcap_fp_rx, &pktfilter);
+}
+
+
+static void
+ead_pktloop(void)
+{
+ while (1) {
+ if (pcap_dispatch(pcap_fp_rx, 1, handle_packet, NULL) < 0) {
+ ead_pcap_reopen(false);
+ continue;
+ }
+ }
+}
+
+
+static int
+usage(const char *prog)
+{
+ fprintf(stderr, "Usage: %s [<options>]\n"
+ "Options:\n"
+ "\t-B Run in background mode\n"
+ "\t-d <device> Set the device to listen on\n"
+ "\t-D <name> Set the name of the device visible to clients\n"
+ "\t-p <file> Set the password file for authenticating\n"
+ "\t-P <file> Write a pidfile\n"
+ "\n", prog);
+ return -1;
+}
+
+static void
+server_handle_sigchld(int sig)
+{
+ struct ead_instance *in;
+ struct list_head *p;
+ int pid = 0;
+ wait(&pid);
+
+ list_for_each(p, &instances) {
+ in = list_entry(p, struct ead_instance, list);
+ if (pid != in->pid)
+ continue;
+
+ in->pid = 0;
+ break;
+ }
+}
+
+static void
+instance_handle_sigchld(int sig)
+{
+ int pid = 0;
+ wait(&pid);
+ child_pending = false;
+}
+
+static void
+start_server(struct ead_instance *i)
+{
+ if (!nonfork) {
+ i->pid = fork();
+ if (i->pid != 0) {
+ if (i->pid < 0)
+ i->pid = 0;
+ return;
+ }
+ }
+
+ instance = i;
+ signal(SIGCHLD, instance_handle_sigchld);
+ ead_pcap_reopen(true);
+ ead_pktloop();
+ pcap_close(pcap_fp);
+ if (pcap_fp_rx != pcap_fp)
+ pcap_close(pcap_fp_rx);
+
+ exit(0);
+}
+
+
+static void
+start_servers(bool restart)
+{
+ struct ead_instance *in;
+ struct list_head *p;
+
+ list_for_each(p, &instances) {
+ in = list_entry(p, struct ead_instance, list);
+ if (in->pid > 0)
+ continue;
+
+ sleep(1);
+ start_server(in);
+ }
+}
+
+static void
+stop_server(struct ead_instance *in, bool do_free)
+{
+ if (in->pid > 0)
+ kill(in->pid, SIGKILL);
+ in->pid = 0;
+ if (do_free) {
+ list_del(&in->list);
+ free(in);
+ }
+}
+
+static void
+server_handle_sigint(int sig)
+{
+ struct ead_instance *in;
+ struct list_head *p, *tmp;
+
+ list_for_each_safe(p, tmp, &instances) {
+ in = list_entry(p, struct ead_instance, list);
+ stop_server(in, true);
+ }
+ exit(1);
+}
+
+#ifdef linux
+static int
+check_bridge_port(const char *br, const char *port, void *arg)
+{
+ struct ead_instance *in;
+ struct list_head *p, *tmp;
+
+ list_for_each(p, &instances) {
+ in = list_entry(p, struct ead_instance, list);
+
+ if (strcmp(in->ifname, port) != 0)
+ continue;
+
+ in->br_check = true;
+ if (strcmp(in->bridge, br) == 0)
+ break;
+
+ strncpy(in->bridge, br, sizeof(in->bridge));
+ DEBUG(2, "assigning port %s to bridge %s\n", in->ifname, in->bridge);
+ stop_server(in, false);
+ }
+ return 0;
+}
+
+static int
+check_bridge(const char *name, void *arg)
+{
+ br_foreach_port(name, check_bridge_port, arg);
+ return 0;
+}
+#endif
+
+static void
+check_all_interfaces(void)
+{
+#ifdef linux
+ struct ead_instance *in;
+ struct list_head *p, *tmp;
+
+ br_foreach_bridge(check_bridge, NULL);
+
+ /* look for interfaces that are no longer part of a bridge */
+ list_for_each(p, &instances) {
+ in = list_entry(p, struct ead_instance, list);
+
+ if (in->br_check) {
+ in->br_check = false;
+ } else if (in->bridge[0]) {
+ DEBUG(2, "removing port %s from bridge %s\n", in->ifname, in->bridge);
+ in->bridge[0] = 0;
+ stop_server(in, false);
+ }
+ }
+#endif
+}
+
+
+int main(int argc, char **argv)
+{
+ struct ead_instance *in;
+ struct timeval tv;
+ const char *pidfile = NULL;
+ bool background = false;
+ int n_iface = 0;
+ int fd, ch;
+
+ if (argc == 1)
+ return usage(argv[0]);
+
+ INIT_LIST_HEAD(&instances);
+ while ((ch = getopt(argc, argv, "Bd:D:fhp:P:")) != -1) {
+ switch(ch) {
+ case 'B':
+ background = true;
+ break;
+ case 'f':
+ nonfork = true;
+ break;
+ case 'h':
+ return usage(argv[0]);
+ case 'd':
+ in = malloc(sizeof(struct ead_instance));
+ memset(in, 0, sizeof(struct ead_instance));
+ INIT_LIST_HEAD(&in->list);
+ strncpy(in->ifname, optarg, sizeof(in->ifname) - 1);
+ list_add(&in->list, &instances);
+ in->id = n_iface++;
+ break;
+ case 'D':
+ dev_name = optarg;
+ break;
+ case 'p':
+ passwd_file = optarg;
+ break;
+ case 'P':
+ pidfile = optarg;
+ break;
+ }
+ }
+ signal(SIGCHLD, server_handle_sigchld);
+ signal(SIGINT, server_handle_sigint);
+ signal(SIGTERM, server_handle_sigint);
+ signal(SIGKILL, server_handle_sigint);
+
+ if (!n_iface) {
+ fprintf(stderr, "Error: ead needs at least one interface\n");
+ return -1;
+ }
+
+ if (background) {
+ if (fork() > 0)
+ exit(0);
+
+ fd = open("/dev/null", O_RDWR);
+ dup2(fd, 0);
+ dup2(fd, 1);
+ dup2(fd, 2);
+ }
+
+ if (pidfile) {
+ char pid[8];
+ int len;
+
+ unlink(pidfile);
+ fd = open(pidfile, O_CREAT|O_WRONLY|O_EXCL, 0644);
+ if (fd > 0) {
+ len = sprintf(pid, "%d\n", getpid());
+ write(fd, pid, len);
+ close(fd);
+ }
+ }
+
+ /* randomize the mac address */
+ get_random_bytes(ethmac + 3, 3);
+ nid = *(((u16_t *) ethmac) + 2);
+
+ start_servers(false);
+#ifdef linux
+ br_init();
+#endif
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ while (1) {
+ check_all_interfaces();
+ start_servers(true);
+ sleep(1);
+ }
+#ifdef linux
+ br_shutdown();
+#endif
+
+ return 0;
+}
diff --git a/package/ead/src/ead.h b/package/ead/src/ead.h
new file mode 100644
index 000000000..54505ce28
--- /dev/null
+++ b/package/ead/src/ead.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
+ *
+ * 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.
+ */
+
+#ifndef __EAD_H
+#define __EAD_H
+
+#define EAD_DEBUGLEVEL 1
+
+#include <stdint.h>
+#include <stddef.h>
+
+#ifndef MAXSALTLEN
+#define MAXSALTLEN 32
+#endif
+
+#define EAD_PORT 56026UL
+#define EAD_MAGIC 3671771902UL
+#define EAD_CMD_TIMEOUT 10
+
+#define EAD_MAX_IV_INCR 128
+
+/* request/response types */
+/* response id == request id + 1 */
+enum ead_type {
+ EAD_TYPE_PING,
+ EAD_TYPE_PONG,
+
+ EAD_TYPE_SET_USERNAME,
+ EAD_TYPE_ACK_USERNAME,
+
+ EAD_TYPE_GET_PRIME,
+ EAD_TYPE_PRIME,
+
+ EAD_TYPE_SEND_A,
+ EAD_TYPE_SEND_B,
+
+ EAD_TYPE_SEND_AUTH,
+ EAD_TYPE_DONE_AUTH,
+
+ EAD_TYPE_SEND_CMD,
+ EAD_TYPE_RESULT_CMD,
+
+ EAD_TYPE_LAST
+};
+
+enum ead_auth_type {
+ EAD_AUTH_DEFAULT,
+ EAD_AUTH_MD5
+};
+
+enum ead_cmd_type {
+ EAD_CMD_NORMAL,
+ EAD_CMD_BACKGROUND,
+ EAD_CMD_LAST
+};
+
+struct ead_msg_pong {
+ uint16_t auth_type;
+ char name[];
+} __attribute__((packed));
+
+struct ead_msg_number {
+ uint8_t id;
+ unsigned char data[];
+} __attribute__((packed));
+
+struct ead_msg_salt {
+ uint8_t prime;
+ uint8_t len;
+ unsigned char salt[MAXSALTLEN];
+ unsigned char ext_salt[MAXSALTLEN];
+} __attribute__((packed));
+
+struct ead_msg_user {
+ char username[32];
+} __attribute__((packed));
+
+struct ead_msg_auth {
+ unsigned char data[20];
+} __attribute__((packed));
+
+struct ead_msg_cmd {
+ uint8_t type;
+ uint16_t timeout;
+ unsigned char data[];
+} __attribute__((packed));
+
+struct ead_msg_cmd_data {
+ uint8_t done;
+ unsigned char data[];
+} __attribute__((packed));
+
+struct ead_msg_encrypted {
+ uint32_t hash[5];
+ uint32_t iv;
+ uint8_t pad;
+ union {
+ struct ead_msg_cmd cmd;
+ struct ead_msg_cmd_data cmd_data;
+ } data[];
+} __attribute__((packed));
+
+
+#define EAD_DATA(_msg, _type) (&((_msg)->data[0]._type))
+#define EAD_ENC_DATA(_msg, _type) (&((_msg)->data[0].enc.data[0]._type))
+
+/* for ead_msg::sid */
+#define EAD_INSTANCE_MASK 0xf000
+#define EAD_INSTANCE_SHIFT 12
+
+struct ead_msg {
+ uint32_t magic;
+ uint32_t len;
+ uint32_t type;
+ uint16_t nid; /* node id */
+ uint16_t sid; /* session id */
+ uint32_t ip; /* source ip for responses from the server */
+ union {
+ struct ead_msg_pong pong;
+ struct ead_msg_user user;
+ struct ead_msg_number number;
+ struct ead_msg_auth auth;
+ struct ead_msg_salt salt;
+ struct ead_msg_encrypted enc;
+ } data[];
+} __attribute__((packed));
+
+
+#endif
diff --git a/package/ead/src/filter.c b/package/ead/src/filter.c
new file mode 100644
index 000000000..0759dc330
--- /dev/null
+++ b/package/ead/src/filter.c
@@ -0,0 +1,25 @@
+/* precompiled expression: udp and dst port 56026 */
+
+static struct bpf_insn pktfilter_insns[] = {
+ { .code = 0x0028, .jt = 0x00, .jf = 0x00, .k = 0x0000000c },
+ { .code = 0x0015, .jt = 0x00, .jf = 0x04, .k = 0x000086dd },
+ { .code = 0x0030, .jt = 0x00, .jf = 0x00, .k = 0x00000014 },
+ { .code = 0x0015, .jt = 0x00, .jf = 0x0b, .k = 0x00000011 },
+ { .code = 0x0028, .jt = 0x00, .jf = 0x00, .k = 0x00000038 },
+ { .code = 0x0015, .jt = 0x08, .jf = 0x09, .k = 0x0000dada },
+ { .code = 0x0015, .jt = 0x00, .jf = 0x08, .k = 0x00000800 },
+ { .code = 0x0030, .jt = 0x00, .jf = 0x00, .k = 0x00000017 },
+ { .code = 0x0015, .jt = 0x00, .jf = 0x06, .k = 0x00000011 },
+ { .code = 0x0028, .jt = 0x00, .jf = 0x00, .k = 0x00000014 },
+ { .code = 0x0045, .jt = 0x04, .jf = 0x00, .k = 0x00001fff },
+ { .code = 0x00b1, .jt = 0x00, .jf = 0x00, .k = 0x0000000e },
+ { .code = 0x0048, .jt = 0x00, .jf = 0x00, .k = 0x00000010 },
+ { .code = 0x0015, .jt = 0x00, .jf = 0x01, .k = 0x0000dada },
+ { .code = 0x0006, .jt = 0x00, .jf = 0x00, .k = 0x000005dc },
+ { .code = 0x0006, .jt = 0x00, .jf = 0x00, .k = 0x00000000 },
+};
+
+static struct bpf_program pktfilter = {
+ .bf_len = 16,
+ .bf_insns = pktfilter_insns,
+};
diff --git a/package/ead/src/libbridge.h b/package/ead/src/libbridge.h
new file mode 100644
index 000000000..6b70e46f6
--- /dev/null
+++ b/package/ead/src/libbridge.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2000 Lennert Buytenhek
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _LIBBRIDGE_H
+#define _LIBBRIDGE_H
+
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/if_bridge.h>
+
+/* defined in net/if.h but that conflicts with linux/if.h... */
+extern unsigned int if_nametoindex (const char *__ifname);
+extern char *if_indextoname (unsigned int __ifindex, char *__ifname);
+
+struct bridge_id
+{
+ unsigned char prio[2];
+ unsigned char addr[6];
+};
+
+struct bridge_info
+{
+ struct bridge_id designated_root;
+ struct bridge_id bridge_id;
+ unsigned root_path_cost;
+ struct timeval max_age;
+ struct timeval hello_time;
+ struct timeval forward_delay;
+ struct timeval bridge_max_age;
+ struct timeval bridge_hello_time;
+ struct timeval bridge_forward_delay;
+ u_int16_t root_port;
+ unsigned char stp_enabled;
+ unsigned char topology_change;
+ unsigned char topology_change_detected;
+ struct timeval ageing_time;
+ struct timeval hello_timer_value;
+ struct timeval tcn_timer_value;
+ struct timeval topology_change_timer_value;
+ struct timeval gc_timer_value;
+};
+
+struct fdb_entry
+{
+ u_int8_t mac_addr[6];
+ u_int16_t port_no;
+ unsigned char is_local;
+ struct timeval ageing_timer_value;
+};
+
+struct port_info
+{
+ unsigned port_no;
+ struct bridge_id designated_root;
+ struct bridge_id designated_bridge;
+ u_int16_t port_id;
+ u_int16_t designated_port;
+ u_int8_t priority;
+ unsigned char top_change_ack;
+ unsigned char config_pending;
+ unsigned char state;
+ unsigned path_cost;
+ unsigned designated_cost;
+ struct timeval message_age_timer_value;
+ struct timeval forward_delay_timer_value;
+ struct timeval hold_timer_value;
+};
+
+#endif
diff --git a/package/ead/src/libbridge_init.c b/package/ead/src/libbridge_init.c
new file mode 100644
index 000000000..36d0eb9b8
--- /dev/null
+++ b/package/ead/src/libbridge_init.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2000 Lennert Buytenhek
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "libbridge.h"
+#include "libbridge_private.h"
+
+int br_socket_fd = -1;
+
+static int br_init(void)
+{
+ if ((br_socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0)
+ return errno;
+ return 0;
+}
+
+static void br_shutdown(void)
+{
+ close(br_socket_fd);
+ br_socket_fd = -1;
+}
+
+/* If /sys/class/net/XXX/bridge exists then it must be a bridge */
+static int isbridge(const struct dirent *entry)
+{
+ char path[SYSFS_PATH_MAX];
+ struct stat st;
+
+ snprintf(path, SYSFS_PATH_MAX, SYSFS_CLASS_NET "%s/bridge", entry->d_name);
+ return stat(path, &st) == 0 && S_ISDIR(st.st_mode);
+}
+
+/*
+ * New interface uses sysfs to find bridges
+ */
+static int new_foreach_bridge(int (*iterator)(const char *name, void *),
+ void *arg)
+{
+ struct dirent **namelist;
+ int i, count = 0;
+
+ count = scandir(SYSFS_CLASS_NET, &namelist, isbridge, alphasort);
+ if (count < 0)
+ return -1;
+
+ for (i = 0; i < count; i++) {
+ if (iterator(namelist[i]->d_name, arg))
+ break;
+ }
+
+ for (i = 0; i < count; i++)
+ free(namelist[i]);
+ free(namelist);
+
+ return count;
+}
+
+/*
+ * Old interface uses ioctl
+ */
+static int old_foreach_bridge(int (*iterator)(const char *, void *),
+ void *iarg)
+{
+ int i, ret=0, num;
+ char ifname[IFNAMSIZ];
+ int ifindices[MAX_BRIDGES];
+ unsigned long args[3] = { BRCTL_GET_BRIDGES,
+ (unsigned long)ifindices, MAX_BRIDGES };
+
+ num = ioctl(br_socket_fd, SIOCGIFBR, args);
+ if (num < 0) {
+ dprintf("Get bridge indices failed: %s\n",
+ strerror(errno));
+ return -errno;
+ }
+
+ for (i = 0; i < num; i++) {
+ if (!if_indextoname(ifindices[i], ifname)) {
+ dprintf("get find name for ifindex %d\n",
+ ifindices[i]);
+ return -errno;
+ }
+
+ ++ret;
+ if(iterator(ifname, iarg))
+ break;
+ }
+
+ return ret;
+
+}
+
+/*
+ * Go over all bridges and call iterator function.
+ * if iterator returns non-zero then stop.
+ */
+static int br_foreach_bridge(int (*iterator)(const char *, void *),
+ void *arg)
+{
+ int ret;
+
+ ret = new_foreach_bridge(iterator, arg);
+ if (ret <= 0)
+ ret = old_foreach_bridge(iterator, arg);
+
+ return ret;
+}
+
+/*
+ * Only used if sysfs is not available.
+ */
+static int old_foreach_port(const char *brname,
+ int (*iterator)(const char *br, const char *port,
+ void *arg),
+ void *arg)
+{
+ int i, err, count;
+ struct ifreq ifr;
+ char ifname[IFNAMSIZ];
+ int ifindices[MAX_PORTS];
+ unsigned long args[4] = { BRCTL_GET_PORT_LIST,
+ (unsigned long)ifindices, MAX_PORTS, 0 };
+
+ memset(ifindices, 0, sizeof(ifindices));
+ strncpy(ifr.ifr_name, brname, IFNAMSIZ);
+ ifr.ifr_data = (char *) &args;
+
+ err = ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr);
+ if (err < 0) {
+ dprintf("list ports for bridge:'%s' failed: %s\n",
+ brname, strerror(errno));
+ return -errno;
+ }
+
+ count = 0;
+ for (i = 0; i < MAX_PORTS; i++) {
+ if (!ifindices[i])
+ continue;
+
+ if (!if_indextoname(ifindices[i], ifname)) {
+ dprintf("can't find name for ifindex:%d\n",
+ ifindices[i]);
+ continue;
+ }
+
+ ++count;
+ if (iterator(brname, ifname, arg))
+ break;
+ }
+
+ return count;
+}
+
+/*
+ * Iterate over all ports in bridge (using sysfs).
+ */
+static int br_foreach_port(const char *brname,
+ int (*iterator)(const char *br, const char *port, void *arg),
+ void *arg)
+{
+ int i, count;
+ struct dirent **namelist;
+ char path[SYSFS_PATH_MAX];
+
+ snprintf(path, SYSFS_PATH_MAX, SYSFS_CLASS_NET "%s/brif", brname);
+ count = scandir(path, &namelist, 0, alphasort);
+ if (count < 0)
+ return old_foreach_port(brname, iterator, arg);
+
+ for (i = 0; i < count; i++) {
+ if (namelist[i]->d_name[0] == '.'
+ && (namelist[i]->d_name[1] == '\0'
+ || (namelist[i]->d_name[1] == '.'
+ && namelist[i]->d_name[2] == '\0')))
+ continue;
+
+ if (iterator(brname, namelist[i]->d_name, arg))
+ break;
+ }
+ for (i = 0; i < count; i++)
+ free(namelist[i]);
+ free(namelist);
+
+ return count;
+}
diff --git a/package/ead/src/libbridge_private.h b/package/ead/src/libbridge_private.h
new file mode 100644
index 000000000..38fd60ed9
--- /dev/null
+++ b/package/ead/src/libbridge_private.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2000 Lennert Buytenhek
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _LIBBRIDGE_PRIVATE_H
+#define _LIBBRIDGE_PRIVATE_H
+
+#include <linux/sockios.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <linux/if_bridge.h>
+
+#define MAX_BRIDGES 1024
+#define MAX_PORTS 1024
+
+#define SYSFS_CLASS_NET "/sys/class/net/"
+#define SYSFS_PATH_MAX 256
+
+#define dprintf(fmt,arg...)
+
+#endif
diff --git a/package/ead/src/list.h b/package/ead/src/list.h
new file mode 100644
index 000000000..ac429c862
--- /dev/null
+++ b/package/ead/src/list.h
@@ -0,0 +1,602 @@
+/* GPL v2, adapted from the Linux kernel */
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+#include <stddef.h>
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr: the pointer to the member.
+ * @type: the type of the container struct this is embedded in.
+ * @member: the name of the member within the struct.
+ *
+ */
+#ifndef container_of
+#define container_of(ptr, type, member) ( \
+ (type *)( (char *)ptr - offsetof(type,member) ))
+#endif
+
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void INIT_LIST_HEAD(struct list_head *list)
+{
+ list->next = list;
+ list->prev = list;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty() on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ entry->next = NULL;
+ entry->prev = NULL;
+}
+
+/**
+ * list_replace - replace old entry by new one
+ * @old : the element to be replaced
+ * @new : the new element to insert
+ *
+ * If @old was empty, it will be overwritten.
+ */
+static inline void list_replace(struct list_head *old,
+ struct list_head *new)
+{
+ new->next = old->next;
+ new->next->prev = new;
+ new->prev = old->prev;
+ new->prev->next = new;
+}
+
+static inline void list_replace_init(struct list_head *old,
+ struct list_head *new)
+{
+ list_replace(old, new);
+ INIT_LIST_HEAD(old);
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+ struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add_tail(list, head);
+}
+
+/**
+ * list_is_last - tests whether @list is the last entry in list @head
+ * @list: the entry to test
+ * @head: the head of the list
+ */
+static inline int list_is_last(const struct list_head *list,
+ const struct list_head *head)
+{
+ return list->next == head;
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+ return head->next == head;
+}
+
+/**
+ * list_empty_careful - tests whether a list is empty and not being modified
+ * @head: the list to test
+ *
+ * Description:
+ * tests whether a list is empty _and_ checks that no other CPU might be
+ * in the process of modifying either member (next or prev)
+ *
+ * NOTE: using list_empty_careful() without synchronization
+ * can only be safe if the only activity that can happen
+ * to the list entry is list_del_init(). Eg. it cannot be used
+ * if another CPU could re-list_add() it.
+ */
+static inline int list_empty_careful(const struct list_head *head)
+{
+ struct list_head *next = head->next;
+ return (next == head) && (next == head->prev);
+}
+
+static inline void __list_splice(struct list_head *list,
+ struct list_head *head)
+{
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(struct list_head *list, struct list_head *head)
+{
+ if (!list_empty(list))
+ __list_splice(list, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head);
+ INIT_LIST_HEAD(list);
+ }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+/**
+ * list_first_entry - get the first element from a list
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_first_entry(ptr, type, member) \
+ list_entry((ptr)->next, type, member)
+
+/**
+ * list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ */
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); \
+ pos = pos->next)
+
+/**
+ * __list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ *
+ * This variant differs from list_for_each() in that it's the
+ * simplest possible list iteration code, no prefetching is done.
+ * Use this for code that knows the list to be very short (empty
+ * or 1 entry) most of the time.
+ */
+#define __list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_prev - iterate over a list backwards
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+ for (pos = (head)->prev; pos != (head); \
+ pos = pos->prev)
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/**
+ * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_prev_safe(pos, n, head) \
+ for (pos = (head)->prev, n = pos->prev; \
+ pos != (head); \
+ pos = n, n = pos->prev)
+
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_reverse - iterate backwards over list of given type.
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_reverse(pos, head, member) \
+ for (pos = list_entry((head)->prev, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.prev, typeof(*pos), member))
+
+/**
+ * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
+ * @pos: the type * to use as a start point
+ * @head: the head of the list
+ * @member: the name of the list_struct within the struct.
+ *
+ * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
+ */
+#define list_prepare_entry(pos, head, member) \
+ ((pos) ? : list_entry(head, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue - continue iteration over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Continue to iterate over list of given type, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue(pos, head, member) \
+ for (pos = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue_reverse - iterate backwards from the given point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Start to iterate over list of given type backwards, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue_reverse(pos, head, member) \
+ for (pos = list_entry(pos->member.prev, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.prev, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_from - iterate over list of given type from the current point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type, continuing from current position.
+ */
+#define list_for_each_entry_from(pos, head, member) \
+ for (; &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_continue
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type, continuing after current point,
+ * safe against removal of list entry.
+ */
+#define list_for_each_entry_safe_continue(pos, n, head, member) \
+ for (pos = list_entry(pos->member.next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_from
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type from current point, safe against
+ * removal of list entry.
+ */
+#define list_for_each_entry_safe_from(pos, n, head, member) \
+ for (n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_reverse
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate backwards over list of given type, safe against removal
+ * of list entry.
+ */
+#define list_for_each_entry_safe_reverse(pos, n, head, member) \
+ for (pos = list_entry((head)->prev, typeof(*pos), member), \
+ n = list_entry(pos->member.prev, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.prev, typeof(*n), member))
+
+/*
+ * Double linked lists with a single pointer list head.
+ * Mostly useful for hash tables where the two pointer list head is
+ * too wasteful.
+ * You lose the ability to access the tail in O(1).
+ */
+
+struct hlist_head {
+ struct hlist_node *first;
+};
+
+struct hlist_node {
+ struct hlist_node *next, **pprev;
+};
+
+#define HLIST_HEAD_INIT { .first = NULL }
+#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
+#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
+static inline void INIT_HLIST_NODE(struct hlist_node *h)
+{
+ h->next = NULL;
+ h->pprev = NULL;
+}
+
+static inline int hlist_unhashed(const struct hlist_node *h)
+{
+ return !h->pprev;
+}
+
+static inline int hlist_empty(const struct hlist_head *h)
+{
+ return !h->first;
+}
+
+static inline void __hlist_del(struct hlist_node *n)
+{
+ struct hlist_node *next = n->next;
+ struct hlist_node **pprev = n->pprev;
+ *pprev = next;
+ if (next)
+ next->pprev = pprev;
+}
+
+static inline void hlist_del(struct hlist_node *n)
+{
+ __hlist_del(n);
+ n->next = NULL;
+ n->pprev = NULL;
+}
+
+static inline void hlist_del_init(struct hlist_node *n)
+{
+ if (!hlist_unhashed(n)) {
+ __hlist_del(n);
+ INIT_HLIST_NODE(n);
+ }
+}
+
+
+static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
+{
+ struct hlist_node *first = h->first;
+ n->next = first;
+ if (first)
+ first->pprev = &n->next;
+ h->first = n;
+ n->pprev = &h->first;
+}
+
+
+/* next must be != NULL */
+static inline void hlist_add_before(struct hlist_node *n,
+ struct hlist_node *next)
+{
+ n->pprev = next->pprev;
+ n->next = next;
+ next->pprev = &n->next;
+ *(n->pprev) = n;
+}
+
+static inline void hlist_add_after(struct hlist_node *n,
+ struct hlist_node *next)
+{
+ next->next = n->next;
+ n->next = next;
+ next->pprev = &n->next;
+
+ if(next->next)
+ next->next->pprev = &next->next;
+}
+
+#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
+
+#define hlist_for_each(pos, head) \
+ for (pos = (head)->first; pos; pos = pos->next)
+
+#define hlist_for_each_safe(pos, n, head) \
+ for (pos = (head)->first; pos; pos = n)
+
+/**
+ * hlist_for_each_entry - iterate over list of given type
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry(tpos, pos, head, member) \
+ for (pos = (head)->first; pos && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_continue(tpos, pos, member) \
+ for (pos = (pos)->next; pos && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_from - iterate over a hlist continuing from current point
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_from(tpos, pos, member) \
+ for (; pos && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @n: another &struct hlist_node to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
+ for (pos = (head)->first; \
+ pos && ({ n = pos->next; 1; }) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = n)
+
+#endif
diff --git a/package/ead/src/passwd b/package/ead/src/passwd
new file mode 100644
index 000000000..eee7a8948
--- /dev/null
+++ b/package/ead/src/passwd
@@ -0,0 +1,3 @@
+root:$1$MCGAgYw.$Ip1GcyeUliId3wzVcKR/e/:0:0:root:/root:/bin/ash
+nobody:*:65534:65534:nobody:/var:/bin/false
+daemon:*:65534:65534:daemon:/var:/bin/false
diff --git a/package/ead/src/pfc.c b/package/ead/src/pfc.c
new file mode 100644
index 000000000..402e37f31
--- /dev/null
+++ b/package/ead/src/pfc.c
@@ -0,0 +1,54 @@
+/*
+ * Small pcap precompiler
+ * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
+ *
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pcap.h>
+
+int main (int argc, char ** argv)
+{
+ struct bpf_program filter;
+ pcap_t *pc;
+ int i;
+
+ if (argc != 2)
+ {
+ printf ("Usage: %s <expression>\n", argv[0]);
+ return 1;
+ }
+
+ pc = pcap_open_dead(DLT_EN10MB, 1500);
+ if (pcap_compile(pc, &filter, argv[1], 1, 0) != 0) {
+ printf("error in active-filter expression: %s\n", pcap_geterr(pc));
+ return 1;
+ }
+
+ printf("/* precompiled expression: %s */\n\n"
+ "static struct bpf_insn pktfilter_insns[] = {\n",
+ argv[1]);
+
+ for (i = 0; i < filter.bf_len; i++) {
+ struct bpf_insn *in = &filter.bf_insns[i];
+ printf("\t{ .code = 0x%04x, .jt = 0x%02x, .jf = 0x%02x, .k = 0x%08x },\n", in->code, in->jt, in->jf, in->k);
+ }
+ printf("};\n\n"
+ "static struct bpf_program pktfilter = {\n"
+ "\t.bf_len = %d,\n"
+ "\t.bf_insns = pktfilter_insns,\n"
+ "};\n", filter.bf_len);
+ return 0;
+
+}
diff --git a/package/ead/src/pw_encrypt_md5.c b/package/ead/src/pw_encrypt_md5.c
new file mode 100644
index 000000000..bc9f249fd
--- /dev/null
+++ b/package/ead/src/pw_encrypt_md5.c
@@ -0,0 +1,646 @@
+/*
+ * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ *
+ * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD5 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ *
+ * $FreeBSD: src/lib/libmd/md5c.c,v 1.9.2.1 1999/08/29 14:57:12 peter Exp $
+ *
+ * This code is the same as the code published by RSA Inc. It has been
+ * edited for clarity and style only.
+ *
+ * ----------------------------------------------------------------------------
+ * The md5_crypt() function was taken from freeBSD's libcrypt and contains
+ * this license:
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
+ *
+ * $FreeBSD: src/lib/libcrypt/crypt.c,v 1.7.2.1 1999/08/29 14:56:33 peter Exp $
+ *
+ * ----------------------------------------------------------------------------
+ * On April 19th, 2001 md5_crypt() was modified to make it reentrant
+ * by Erik Andersen <andersen@uclibc.org>
+ *
+ *
+ * June 28, 2001 Manuel Novoa III
+ *
+ * "Un-inlined" code using loops and static const tables in order to
+ * reduce generated code size (on i386 from approx 4k to approx 2.5k).
+ *
+ * June 29, 2001 Manuel Novoa III
+ *
+ * Completely removed static PADDING array.
+ *
+ * Reintroduced the loop unrolling in MD5_Transform and added the
+ * MD5_SIZE_OVER_SPEED option for configurability. Define below as:
+ * 0 fully unrolled loops
+ * 1 partially unrolled (4 ops per loop)
+ * 2 no unrolling -- introduces the need to swap 4 variables (slow)
+ * 3 no unrolling and all 4 loops merged into one with switch
+ * in each loop (glacial)
+ * On i386, sizes are roughly (-Os -fno-builtin):
+ * 0: 3k 1: 2.5k 2: 2.2k 3: 2k
+ *
+ *
+ * Since SuSv3 does not require crypt_r, modified again August 7, 2002
+ * by Erik Andersen to remove reentrance stuff...
+ */
+
+static const uint8_t ascii64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+/*
+ * Valid values are 1 (fastest/largest) to 3 (smallest/slowest).
+ */
+#define MD5_SIZE_OVER_SPEED 3
+
+/**********************************************************************/
+
+/* MD5 context. */
+struct MD5Context {
+ uint32_t state[4]; /* state (ABCD) */
+ uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
+ unsigned char buffer[64]; /* input buffer */
+};
+
+static void __md5_Init(struct MD5Context *);
+static void __md5_Update(struct MD5Context *, const unsigned char *, unsigned int);
+static void __md5_Pad(struct MD5Context *);
+static void __md5_Final(unsigned char [16], struct MD5Context *);
+static void __md5_Transform(uint32_t [4], const unsigned char [64]);
+
+
+#define MD5_MAGIC_STR "$1$"
+#define MD5_MAGIC_LEN (sizeof(MD5_MAGIC_STR) - 1)
+static const unsigned char __md5__magic[] = MD5_MAGIC_STR;
+
+
+#ifdef i386
+#define __md5_Encode memcpy
+#define __md5_Decode memcpy
+#else /* i386 */
+
+/*
+ * __md5_Encodes input (uint32_t) into output (unsigned char). Assumes len is
+ * a multiple of 4.
+ */
+static void
+__md5_Encode(unsigned char *output, uint32_t *input, unsigned int len)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = input[i];
+ output[j+1] = (input[i] >> 8);
+ output[j+2] = (input[i] >> 16);
+ output[j+3] = (input[i] >> 24);
+ }
+}
+
+/*
+ * __md5_Decodes input (unsigned char) into output (uint32_t). Assumes len is
+ * a multiple of 4.
+ */
+static void
+__md5_Decode(uint32_t *output, const unsigned char *input, unsigned int len)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) |
+ (((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24);
+}
+#endif /* i386 */
+
+/* F, G, H and I are basic MD5 functions. */
+#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)))
+
+/* ROTATE_LEFT rotates x left n bits. */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/*
+ * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+ * Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+ (a) = ROTATE_LEFT((a), (s)); \
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+ (a) = ROTATE_LEFT((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+ (a) = ROTATE_LEFT((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+ (a) = ROTATE_LEFT((a), (s)); \
+ (a) += (b); \
+ }
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context. */
+static void __md5_Init(struct MD5Context *context)
+{
+ context->count[0] = context->count[1] = 0;
+
+ /* Load magic initialization constants. */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+}
+
+/*
+ * MD5 block update operation. Continues an MD5 message-digest
+ * operation, processing another message block, and updating the
+ * context.
+ */
+static void __md5_Update(struct MD5Context *context, const unsigned char *input, unsigned int inputLen)
+{
+ unsigned int i, idx, partLen;
+
+ /* Compute number of bytes mod 64 */
+ idx = (context->count[0] >> 3) & 0x3F;
+
+ /* Update number of bits */
+ context->count[0] += (inputLen << 3);
+ if (context->count[0] < (inputLen << 3))
+ context->count[1]++;
+ context->count[1] += (inputLen >> 29);
+
+ partLen = 64 - idx;
+
+ /* Transform as many times as possible. */
+ if (inputLen >= partLen) {
+ memcpy(&context->buffer[idx], input, partLen);
+ __md5_Transform(context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ __md5_Transform(context->state, &input[i]);
+
+ idx = 0;
+ } else
+ i = 0;
+
+ /* Buffer remaining input */
+ memcpy(&context->buffer[idx], &input[i], inputLen - i);
+}
+
+/*
+ * MD5 padding. Adds padding followed by original length.
+ */
+static void __md5_Pad(struct MD5Context *context)
+{
+ unsigned char bits[8];
+ unsigned int idx, padLen;
+ unsigned char PADDING[64];
+
+ memset(PADDING, 0, sizeof(PADDING));
+ PADDING[0] = 0x80;
+
+ /* Save number of bits */
+ __md5_Encode(bits, context->count, 8);
+
+ /* Pad out to 56 mod 64. */
+ idx = (context->count[0] >> 3) & 0x3f;
+ padLen = (idx < 56) ? (56 - idx) : (120 - idx);
+ __md5_Update(context, PADDING, padLen);
+
+ /* Append length (before padding) */
+ __md5_Update(context, bits, 8);
+}
+
+/*
+ * MD5 finalization. Ends an MD5 message-digest operation, writing the
+ * the message digest and zeroizing the context.
+ */
+static void __md5_Final(unsigned char digest[16], struct MD5Context *context)
+{
+ /* Do padding. */
+ __md5_Pad(context);
+
+ /* Store state in digest */
+ __md5_Encode(digest, context->state, 16);
+
+ /* Zeroize sensitive information. */
+ memset(context, 0, sizeof(*context));
+}
+
+/* MD5 basic transformation. Transforms state based on block. */
+static void __md5_Transform(uint32_t state[4], const unsigned char block[64])
+{
+ uint32_t a, b, c, d, x[16];
+#if MD5_SIZE_OVER_SPEED > 1
+ uint32_t temp;
+ const unsigned char *ps;
+
+ static const unsigned char S[] = {
+ 7, 12, 17, 22,
+ 5, 9, 14, 20,
+ 4, 11, 16, 23,
+ 6, 10, 15, 21
+ };
+#endif /* MD5_SIZE_OVER_SPEED > 1 */
+
+#if MD5_SIZE_OVER_SPEED > 0
+ const uint32_t *pc;
+ const unsigned char *pp;
+ int i;
+
+ static const uint32_t C[] = {
+ /* round 1 */
+ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+ 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+ 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+ 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+ /* round 2 */
+ 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+ 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
+ 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+ 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+ /* round 3 */
+ 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+ 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+ 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
+ 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+ /* round 4 */
+ 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+ 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+ 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+ 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
+ };
+
+ static const unsigned char P[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */
+ 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */
+ 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */
+ 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */
+ };
+
+#endif /* MD5_SIZE_OVER_SPEED > 0 */
+
+ __md5_Decode(x, block, 64);
+
+ a = state[0]; b = state[1]; c = state[2]; d = state[3];
+
+#if MD5_SIZE_OVER_SPEED > 2
+ pc = C; pp = P; ps = S - 4;
+
+ for (i = 0; i < 64; i++) {
+ if ((i & 0x0f) == 0) ps += 4;
+ temp = a;
+ switch (i>>4) {
+ case 0:
+ temp += F(b, c, d);
+ break;
+ case 1:
+ temp += G(b, c, d);
+ break;
+ case 2:
+ temp += H(b, c, d);
+ break;
+ case 3:
+ temp += I(b, c, d);
+ break;
+ }
+ temp += x[*pp++] + *pc++;
+ temp = ROTATE_LEFT(temp, ps[i & 3]);
+ temp += b;
+ a = d; d = c; c = b; b = temp;
+ }
+#elif MD5_SIZE_OVER_SPEED > 1
+ pc = C; pp = P; ps = S;
+
+ /* Round 1 */
+ for (i = 0; i < 16; i++) {
+ FF(a, b, c, d, x[*pp], ps[i & 0x3], *pc); pp++; pc++;
+ temp = d; d = c; c = b; b = a; a = temp;
+ }
+
+ /* Round 2 */
+ ps += 4;
+ for (; i < 32; i++) {
+ GG(a, b, c, d, x[*pp], ps[i & 0x3], *pc); pp++; pc++;
+ temp = d; d = c; c = b; b = a; a = temp;
+ }
+ /* Round 3 */
+ ps += 4;
+ for (; i < 48; i++) {
+ HH(a, b, c, d, x[*pp], ps[i & 0x3], *pc); pp++; pc++;
+ temp = d; d = c; c = b; b = a; a = temp;
+ }
+
+ /* Round 4 */
+ ps += 4;
+ for (; i < 64; i++) {
+ II(a, b, c, d, x[*pp], ps[i & 0x3], *pc); pp++; pc++;
+ temp = d; d = c; c = b; b = a; a = temp;
+ }
+#elif MD5_SIZE_OVER_SPEED > 0
+ pc = C; pp = P;
+
+ /* Round 1 */
+ for (i = 0; i < 4; i++) {
+ FF(a, b, c, d, x[*pp], 7, *pc); pp++; pc++;
+ FF(d, a, b, c, x[*pp], 12, *pc); pp++; pc++;
+ FF(c, d, a, b, x[*pp], 17, *pc); pp++; pc++;
+ FF(b, c, d, a, x[*pp], 22, *pc); pp++; pc++;
+ }
+
+ /* Round 2 */
+ for (i = 0; i < 4; i++) {
+ GG(a, b, c, d, x[*pp], 5, *pc); pp++; pc++;
+ GG(d, a, b, c, x[*pp], 9, *pc); pp++; pc++;
+ GG(c, d, a, b, x[*pp], 14, *pc); pp++; pc++;
+ GG(b, c, d, a, x[*pp], 20, *pc); pp++; pc++;
+ }
+ /* Round 3 */
+ for (i = 0; i < 4; i++) {
+ HH(a, b, c, d, x[*pp], 4, *pc); pp++; pc++;
+ HH(d, a, b, c, x[*pp], 11, *pc); pp++; pc++;
+ HH(c, d, a, b, x[*pp], 16, *pc); pp++; pc++;
+ HH(b, c, d, a, x[*pp], 23, *pc); pp++; pc++;
+ }
+
+ /* Round 4 */
+ for (i = 0; i < 4; i++) {
+ II(a, b, c, d, x[*pp], 6, *pc); pp++; pc++;
+ II(d, a, b, c, x[*pp], 10, *pc); pp++; pc++;
+ II(c, d, a, b, x[*pp], 15, *pc); pp++; pc++;
+ II(b, c, d, a, x[*pp], 21, *pc); pp++; pc++;
+ }
+#else
+ /* Round 1 */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+ FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+ FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+ FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+ FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+ FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+ FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+ FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+ FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+ FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+ FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+ FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+ GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+ GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+ GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+ GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+ GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+ GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+ GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+ GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+ GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+ GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+ GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+ HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+ HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+ HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+ HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+ HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+ HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+ HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+ HH(b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
+ HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+ HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+ II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+ II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+ II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+ II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+ II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+ II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+ II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+ II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+ II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+ II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+#endif
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /* Zeroize sensitive information. */
+ memset(x, 0, sizeof(x));
+}
+
+
+static char*
+__md5_to64(char *s, unsigned v, int n)
+{
+ while (--n >= 0) {
+ *s++ = ascii64[v & 0x3f];
+ v >>= 6;
+ }
+ return s;
+}
+
+/*
+ * UNIX password
+ *
+ * Use MD5 for what it is best at...
+ */
+#define MD5_OUT_BUFSIZE 36
+static char *
+md5_crypt(char passwd[MD5_OUT_BUFSIZE], const unsigned char *pw, const unsigned char *salt)
+{
+ const unsigned char *sp, *ep;
+ char *p;
+ unsigned char final[17]; /* final[16] exists only to aid in looping */
+ int sl, pl, i, pw_len;
+ struct MD5Context ctx, ctx1;
+
+ /* Refine the Salt first */
+ sp = salt;
+
+ sp += MD5_MAGIC_LEN;
+
+ /* It stops at the first '$', max 8 chars */
+ for (ep = sp; *ep && *ep != '$' && ep < (sp+8); ep++)
+ continue;
+
+ /* get the length of the true salt */
+ sl = ep - sp;
+
+ __md5_Init(&ctx);
+
+ /* The password first, since that is what is most unknown */
+ pw_len = strlen((char*)pw);
+ __md5_Update(&ctx, pw, pw_len);
+
+ /* Then our magic string */
+ __md5_Update(&ctx, __md5__magic, MD5_MAGIC_LEN);
+
+ /* Then the raw salt */
+ __md5_Update(&ctx, sp, sl);
+
+ /* Then just as many characters of the MD5(pw, salt, pw) */
+ __md5_Init(&ctx1);
+ __md5_Update(&ctx1, pw, pw_len);
+ __md5_Update(&ctx1, sp, sl);
+ __md5_Update(&ctx1, pw, pw_len);
+ __md5_Final(final, &ctx1);
+ for (pl = pw_len; pl > 0; pl -= 16)
+ __md5_Update(&ctx, final, pl > 16 ? 16 : pl);
+
+ /* Don't leave anything around in vm they could use. */
+//TODO: the above comment seems to be wrong. final is used later.
+ memset(final, 0, sizeof(final));
+
+ /* Then something really weird... */
+ for (i = pw_len; i; i >>= 1) {
+ __md5_Update(&ctx, ((i & 1) ? final : (const unsigned char *) pw), 1);
+ }
+
+ /* Now make the output string */
+ passwd[0] = '$';
+ passwd[1] = '1';
+ passwd[2] = '$';
+ strncpy(passwd + 3, (char*)sp, sl);
+ passwd[sl + 3] = '$';
+
+ __md5_Final(final, &ctx);
+
+ /*
+ * and now, just to make sure things don't run too fast
+ * On a 60 Mhz Pentium this takes 34 msec, so you would
+ * need 30 seconds to build a 1000 entry dictionary...
+ */
+ for (i = 0; i < 1000; i++) {
+ __md5_Init(&ctx1);
+ if (i & 1)
+ __md5_Update(&ctx1, pw, pw_len);
+ else
+ __md5_Update(&ctx1, final, 16);
+
+ if (i % 3)
+ __md5_Update(&ctx1, sp, sl);
+
+ if (i % 7)
+ __md5_Update(&ctx1, pw, pw_len);
+
+ if (i & 1)
+ __md5_Update(&ctx1, final, 16);
+ else
+ __md5_Update(&ctx1, pw, pw_len);
+ __md5_Final(final, &ctx1);
+ }
+
+ p = passwd + sl + 4; /* 12 bytes max (sl is up to 8 bytes) */
+
+ /* Add 5*4+2 = 22 bytes of hash, + NUL byte. */
+ final[16] = final[5];
+ for (i = 0; i < 5; i++) {
+ unsigned l = (final[i] << 16) | (final[i+6] << 8) | final[i+12];
+ p = __md5_to64(p, l, 4);
+ }
+ p = __md5_to64(p, final[11], 2);
+ *p = '\0';
+
+ /* Don't leave anything around in vm they could use. */
+ memset(final, 0, sizeof(final));
+
+ return passwd;
+}
+
+#undef MD5_SIZE_OVER_SPEED
+#undef MD5_MAGIC_STR
+#undef MD5_MAGIC_LEN
+#undef __md5_Encode
+#undef __md5_Decode
+#undef F
+#undef G
+#undef H
+#undef I
+#undef ROTATE_LEFT
+#undef FF
+#undef GG
+#undef HH
+#undef II
+#undef S11
+#undef S12
+#undef S13
+#undef S14
+#undef S21
+#undef S22
+#undef S23
+#undef S24
+#undef S31
+#undef S32
+#undef S33
+#undef S34
+#undef S41
+#undef S42
+#undef S43
+#undef S44
diff --git a/package/ead/src/sha1.c b/package/ead/src/sha1.c
new file mode 100644
index 000000000..3683a7da7
--- /dev/null
+++ b/package/ead/src/sha1.c
@@ -0,0 +1,104 @@
+/*
+ * SHA transform algorithm, originally taken from code written by
+ * Peter Gutmann, and placed in the public domain.
+ */
+
+static uint32_t
+rol32(uint32_t word, int shift)
+{
+ return (word << shift) | (word >> (32 - shift));
+}
+
+/* The SHA f()-functions. */
+
+#define f1(x,y,z) (z ^ (x & (y ^ z))) /* x ? y : z */
+#define f2(x,y,z) (x ^ y ^ z) /* XOR */
+#define f3(x,y,z) ((x & y) + (z & (x ^ y))) /* majority */
+
+/* The SHA Mysterious Constants */
+
+#define K1 0x5A827999L /* Rounds 0-19: sqrt(2) * 2^30 */
+#define K2 0x6ED9EBA1L /* Rounds 20-39: sqrt(3) * 2^30 */
+#define K3 0x8F1BBCDCL /* Rounds 40-59: sqrt(5) * 2^30 */
+#define K4 0xCA62C1D6L /* Rounds 60-79: sqrt(10) * 2^30 */
+
+/**
+ * sha_transform - single block SHA1 transform
+ *
+ * @digest: 160 bit digest to update
+ * @data: 512 bits of data to hash
+ * @W: 80 words of workspace (see note)
+ *
+ * This function generates a SHA1 digest for a single 512-bit block.
+ * Be warned, it does not handle padding and message digest, do not
+ * confuse it with the full FIPS 180-1 digest algorithm for variable
+ * length messages.
+ *
+ * Note: If the hash is security sensitive, the caller should be sure
+ * to clear the workspace. This is left to the caller to avoid
+ * unnecessary clears between chained hashing operations.
+ */
+static void sha_transform(uint32_t *digest, const unsigned char *in, uint32_t *W)
+{
+ uint32_t a, b, c, d, e, t, i;
+
+ for (i = 0; i < 16; i++) {
+ int ofs = 4 * i;
+
+ /* word load/store may be unaligned here, so use bytes instead */
+ W[i] =
+ (in[ofs+0] << 24) |
+ (in[ofs+1] << 16) |
+ (in[ofs+2] << 8) |
+ in[ofs+3];
+ }
+
+ for (i = 0; i < 64; i++)
+ W[i+16] = rol32(W[i+13] ^ W[i+8] ^ W[i+2] ^ W[i], 1);
+
+ a = digest[0];
+ b = digest[1];
+ c = digest[2];
+ d = digest[3];
+ e = digest[4];
+
+ for (i = 0; i < 20; i++) {
+ t = f1(b, c, d) + K1 + rol32(a, 5) + e + W[i];
+ e = d; d = c; c = rol32(b, 30); b = a; a = t;
+ }
+
+ for (; i < 40; i ++) {
+ t = f2(b, c, d) + K2 + rol32(a, 5) + e + W[i];
+ e = d; d = c; c = rol32(b, 30); b = a; a = t;
+ }
+
+ for (; i < 60; i ++) {
+ t = f3(b, c, d) + K3 + rol32(a, 5) + e + W[i];
+ e = d; d = c; c = rol32(b, 30); b = a; a = t;
+ }
+
+ for (; i < 80; i ++) {
+ t = f2(b, c, d) + K4 + rol32(a, 5) + e + W[i];
+ e = d; d = c; c = rol32(b, 30); b = a; a = t;
+ }
+
+ digest[0] += a;
+ digest[1] += b;
+ digest[2] += c;
+ digest[3] += d;
+ digest[4] += e;
+}
+
+/**
+ * sha_init - initialize the vectors for a SHA1 digest
+ * @buf: vector to initialize
+ */
+static void sha_init(uint32_t *buf)
+{
+ buf[0] = 0x67452301;
+ buf[1] = 0xefcdab89;
+ buf[2] = 0x98badcfe;
+ buf[3] = 0x10325476;
+ buf[4] = 0xc3d2e1f0;
+}
+
diff --git a/package/ead/src/tinysrp/Makefile.am b/package/ead/src/tinysrp/Makefile.am
new file mode 100644
index 000000000..a8f899fe2
--- /dev/null
+++ b/package/ead/src/tinysrp/Makefile.am
@@ -0,0 +1,28 @@
+AUTOMAKE_OPTIONS = foreign no-dependencies
+
+noinst_HEADERS = t_client.h t_pwd.h t_server.h t_sha.h \
+ bn.h bn_lcl.h bn_prime.h t_defines.h t_read.h
+
+include_HEADERS = tinysrp.h
+
+lib_LIBRARIES = libtinysrp.a
+
+CFLAGS = -O2 @signed@
+
+libtinysrp_a_SOURCES = \
+ tinysrp.c t_client.c t_getconf.c t_conv.c t_getpass.c t_sha.c t_math.c \
+ t_misc.c t_pw.c t_read.c t_server.c t_truerand.c \
+ bn_add.c bn_ctx.c bn_div.c bn_exp.c bn_mul.c bn_word.c bn_asm.c bn_lib.c \
+ bn_shift.c bn_sqr.c
+
+noinst_PROGRAMS = srvtest clitest
+srvtest_SOURCES = srvtest.c
+clitest_SOURCES = clitest.c
+
+bin_PROGRAMS = tconf tphrase
+tconf_SOURCES = tconf.c t_conf.c
+tphrase_SOURCES = tphrase.c
+
+LDADD = libtinysrp.a
+
+EXTRA_DIST = tpasswd Notes
diff --git a/package/ead/src/tinysrp/Makefile.in b/package/ead/src/tinysrp/Makefile.in
new file mode 100644
index 000000000..4701cd523
--- /dev/null
+++ b/package/ead/src/tinysrp/Makefile.in
@@ -0,0 +1,477 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = .
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+LN_S = @LN_S@
+MAKEINFO = @MAKEINFO@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+signed = @signed@
+
+AUTOMAKE_OPTIONS = foreign no-dependencies
+
+noinst_HEADERS = t_client.h t_pwd.h t_server.h t_sha.h bn.h bn_lcl.h bn_prime.h t_defines.h t_read.h
+
+
+include_HEADERS = tinysrp.h
+
+lib_LIBRARIES = libtinysrp.a
+
+CFLAGS = -O2 @signed@
+
+libtinysrp_a_SOURCES = tinysrp.c t_client.c t_getconf.c t_conv.c t_getpass.c t_sha.c t_math.c t_misc.c t_pw.c t_read.c t_server.c t_truerand.c bn_add.c bn_ctx.c bn_div.c bn_exp.c bn_mul.c bn_word.c bn_asm.c bn_lib.c bn_shift.c bn_sqr.c
+
+
+noinst_PROGRAMS = srvtest clitest
+srvtest_SOURCES = srvtest.c
+clitest_SOURCES = clitest.c
+
+bin_PROGRAMS = tconf tphrase
+tconf_SOURCES = tconf.c t_conf.c
+tphrase_SOURCES = tphrase.c
+
+LDADD = libtinysrp.a
+
+EXTRA_DIST = tpasswd Notes
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(lib_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I.
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libtinysrp_a_LIBADD =
+libtinysrp_a_OBJECTS = tinysrp.o t_client.o t_getconf.o t_conv.o \
+t_getpass.o t_sha.o t_math.o t_misc.o t_pw.o t_read.o t_server.o \
+t_truerand.o bn_add.o bn_ctx.o bn_div.o bn_exp.o bn_mul.o bn_word.o \
+bn_asm.o bn_lib.o bn_shift.o bn_sqr.o
+AR = ar
+PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
+
+tconf_OBJECTS = tconf.o t_conf.o
+tconf_LDADD = $(LDADD)
+tconf_DEPENDENCIES = libtinysrp.a
+tconf_LDFLAGS =
+tphrase_OBJECTS = tphrase.o
+tphrase_LDADD = $(LDADD)
+tphrase_DEPENDENCIES = libtinysrp.a
+tphrase_LDFLAGS =
+srvtest_OBJECTS = srvtest.o
+srvtest_LDADD = $(LDADD)
+srvtest_DEPENDENCIES = libtinysrp.a
+srvtest_LDFLAGS =
+clitest_OBJECTS = clitest.o
+clitest_LDADD = $(LDADD)
+clitest_DEPENDENCIES = libtinysrp.a
+clitest_LDFLAGS =
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+HEADERS = $(include_HEADERS) $(noinst_HEADERS)
+
+DIST_COMMON = ./stamp-h.in Makefile.am Makefile.in acconfig.h \
+acinclude.m4 aclocal.m4 config.h.in configure configure.in install-sh \
+missing mkinstalldirs
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+SOURCES = $(libtinysrp_a_SOURCES) $(tconf_SOURCES) $(tphrase_SOURCES) $(srvtest_SOURCES) $(clitest_SOURCES)
+OBJECTS = $(libtinysrp_a_OBJECTS) $(tconf_OBJECTS) $(tphrase_OBJECTS) $(srvtest_OBJECTS) $(clitest_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .o .s
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+$(ACLOCAL_M4): configure.in acinclude.m4
+ cd $(srcdir) && $(ACLOCAL)
+
+$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
+ cd $(srcdir) && $(AUTOCONF)
+
+config.h: stamp-h
+ @if test ! -f $@; then \
+ rm -f stamp-h; \
+ $(MAKE) stamp-h; \
+ else :; fi
+stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES= CONFIG_HEADERS=config.h \
+ $(SHELL) ./config.status
+ @echo timestamp > stamp-h 2> /dev/null
+$(srcdir)/config.h.in: $(srcdir)/stamp-h.in
+ @if test ! -f $@; then \
+ rm -f $(srcdir)/stamp-h.in; \
+ $(MAKE) $(srcdir)/stamp-h.in; \
+ else :; fi
+$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h
+ cd $(top_srcdir) && $(AUTOHEADER)
+ @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null
+
+mostlyclean-hdr:
+
+clean-hdr:
+
+distclean-hdr:
+ -rm -f config.h
+
+maintainer-clean-hdr:
+
+mostlyclean-libLIBRARIES:
+
+clean-libLIBRARIES:
+ -test -z "$(lib_LIBRARIES)" || rm -f $(lib_LIBRARIES)
+
+distclean-libLIBRARIES:
+
+maintainer-clean-libLIBRARIES:
+
+install-libLIBRARIES: $(lib_LIBRARIES)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(libdir)
+ @list='$(lib_LIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$p"; \
+ $(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$p; \
+ else :; fi; \
+ done
+ @$(POST_INSTALL)
+ @list='$(lib_LIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(RANLIB) $(DESTDIR)$(libdir)/$$p"; \
+ $(RANLIB) $(DESTDIR)$(libdir)/$$p; \
+ else :; fi; \
+ done
+
+uninstall-libLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ list='$(lib_LIBRARIES)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(libdir)/$$p; \
+ done
+
+.c.o:
+ $(COMPILE) -c $<
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libtinysrp.a: $(libtinysrp_a_OBJECTS) $(libtinysrp_a_DEPENDENCIES)
+ -rm -f libtinysrp.a
+ $(AR) cru libtinysrp.a $(libtinysrp_a_OBJECTS) $(libtinysrp_a_LIBADD)
+ $(RANLIB) libtinysrp.a
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+ $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ list='$(bin_PROGRAMS)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ done
+
+mostlyclean-noinstPROGRAMS:
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+
+distclean-noinstPROGRAMS:
+
+maintainer-clean-noinstPROGRAMS:
+
+tconf: $(tconf_OBJECTS) $(tconf_DEPENDENCIES)
+ @rm -f tconf
+ $(LINK) $(tconf_LDFLAGS) $(tconf_OBJECTS) $(tconf_LDADD) $(LIBS)
+
+tphrase: $(tphrase_OBJECTS) $(tphrase_DEPENDENCIES)
+ @rm -f tphrase
+ $(LINK) $(tphrase_LDFLAGS) $(tphrase_OBJECTS) $(tphrase_LDADD) $(LIBS)
+
+srvtest: $(srvtest_OBJECTS) $(srvtest_DEPENDENCIES)
+ @rm -f srvtest
+ $(LINK) $(srvtest_LDFLAGS) $(srvtest_OBJECTS) $(srvtest_LDADD) $(LIBS)
+
+clitest: $(clitest_OBJECTS) $(clitest_DEPENDENCIES)
+ @rm -f clitest
+ $(LINK) $(clitest_LDFLAGS) $(clitest_OBJECTS) $(clitest_LDADD) $(LIBS)
+
+install-includeHEADERS: $(include_HEADERS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(includedir)
+ @list='$(include_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d= ; else d="$(srcdir)/"; fi; \
+ echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/$$p"; \
+ $(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/$$p; \
+ done
+
+uninstall-includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ list='$(include_HEADERS)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(includedir)/$$p; \
+ done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ -rm -rf $(distdir)
+ GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
+ mkdir $(distdir)/=build
+ mkdir $(distdir)/=inst
+ dc_install_base=`cd $(distdir)/=inst && pwd`; \
+ cd $(distdir)/=build \
+ && ../configure --srcdir=.. --prefix=$$dc_install_base \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) dist
+ -rm -rf $(distdir)
+ @banner="$(distdir).tar.gz is ready for distribution"; \
+ dashes=`echo "$$banner" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ echo "$$dashes"
+dist: distdir
+ -chmod -R a+r $(distdir)
+ GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
+ -rm -rf $(distdir)
+dist-all: distdir
+ -chmod -R a+r $(distdir)
+ GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
+ -rm -rf $(distdir)
+distdir: $(DISTFILES)
+ -rm -rf $(distdir)
+ mkdir $(distdir)
+ -chmod 777 $(distdir)
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pr $$d/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+all-recursive-am: config.h
+ $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+install-exec-am: install-libLIBRARIES install-binPROGRAMS
+install-exec: install-exec-am
+
+install-data-am: install-includeHEADERS
+install-data: install-data-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-libLIBRARIES uninstall-binPROGRAMS \
+ uninstall-includeHEADERS
+uninstall: uninstall-am
+all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(HEADERS) config.h
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(bindir) \
+ $(DESTDIR)$(includedir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am: mostlyclean-hdr mostlyclean-libLIBRARIES \
+ mostlyclean-compile mostlyclean-binPROGRAMS \
+ mostlyclean-noinstPROGRAMS mostlyclean-tags \
+ mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am: clean-hdr clean-libLIBRARIES clean-compile clean-binPROGRAMS \
+ clean-noinstPROGRAMS clean-tags clean-generic \
+ mostlyclean-am
+
+clean: clean-am
+
+distclean-am: distclean-hdr distclean-libLIBRARIES distclean-compile \
+ distclean-binPROGRAMS distclean-noinstPROGRAMS \
+ distclean-tags distclean-generic clean-am
+
+distclean: distclean-am
+ -rm -f config.status
+
+maintainer-clean-am: maintainer-clean-hdr maintainer-clean-libLIBRARIES \
+ maintainer-clean-compile maintainer-clean-binPROGRAMS \
+ maintainer-clean-noinstPROGRAMS maintainer-clean-tags \
+ maintainer-clean-generic distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+ -rm -f config.status
+
+.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \
+mostlyclean-libLIBRARIES distclean-libLIBRARIES clean-libLIBRARIES \
+maintainer-clean-libLIBRARIES uninstall-libLIBRARIES \
+install-libLIBRARIES mostlyclean-compile distclean-compile \
+clean-compile maintainer-clean-compile mostlyclean-binPROGRAMS \
+distclean-binPROGRAMS clean-binPROGRAMS maintainer-clean-binPROGRAMS \
+uninstall-binPROGRAMS install-binPROGRAMS mostlyclean-noinstPROGRAMS \
+distclean-noinstPROGRAMS clean-noinstPROGRAMS \
+maintainer-clean-noinstPROGRAMS uninstall-includeHEADERS \
+install-includeHEADERS tags mostlyclean-tags distclean-tags clean-tags \
+maintainer-clean-tags distdir info-am info dvi-am dvi check check-am \
+installcheck-am installcheck all-recursive-am install-exec-am \
+install-exec install-data-am install-data install-am install \
+uninstall-am uninstall all-redirect all-am all installdirs \
+mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/package/ead/src/tinysrp/Notes b/package/ead/src/tinysrp/Notes
new file mode 100644
index 000000000..a8620aa70
--- /dev/null
+++ b/package/ead/src/tinysrp/Notes
@@ -0,0 +1,110 @@
+t_* stuff is from the srp 1.7.1 dist
+bn_* stuff is from openssl 0.9.6
+
+(The 7 in libtinysrp's version number reflects the srp version.)
+
+Licensing and copyright for srp and openssl are as indicated in the relevant
+source files. Everything else here is GPL, including the tinysrp protocol.
+
+Changelog since initial release:
+
+0.7.4 more robust terminal modes in t_getpass
+ a potential buffer overflow in tinysrp
+0.7.5 uninitialized pointer bug in tconf
+
+Changes from the base srp and openssl distributions:
+
+I've removed everything that's not needed for client/server operations, and
+all the bn_* stuff that's only used for prime generation has been moved to
+t_conf.c, which isn't part of the library anymore. Also, all the routines
+used for passphrase file maintenance have been moved to tphrase.c.
+
+The library has been optimized (a bit) for space instead of speed. Since
+authentication is usually only done once, this isn't a big problem. Modern
+CPUs are plenty fast for this task, and even 100 MHz CPUs are fine. If you
+really need the speed, get the regular distributions.
+
+Note that if the server sends the client a prime that the client doesn't
+know about, the client MUST test for primality. Since this is pretty
+expensive, and takes 30 seconds on a 100 MHz machine, and uses lots of code,
+I've removed that ability from the client. So only KNOWN primes can be
+used. You can still generate new ones with tconf, but you have to install
+them in the table of known primes (pre_params) in t_getconf.c that's common
+to the client and server, and recompile. The configuration file is gone.
+
+The default prime (the last entry in the table) is 1024 bits; there are
+others with more bits but they will be correspondingly slower.
+
+The default tpasswd file (which is an ascii file that may be editted with a
+regular text editor) contains two users: moo (passphrase "glub glub") and
+"new user" (passphrase "this is a test"). Passphrases may be added or
+changed with tphrase; you can also change the user's prime. To delete a
+user, edit the tpasswd file and remove that line. The tpasswd file's
+default name is DEFAULT_PASSWD in t_pwd.h. Note that you can't change a
+user's username by editting the file: the username is encoded in the
+verifier. If you change a username you must set a new passphrase with
+tphrase.
+
+Here is an example session, using the supplied srvtest and clitest. First,
+start both programs in different windows, and enter the user names. Normally,
+the client would send the username to the server. Server lines are marked
+with S>, client lines with C>.
+
+S> % srvtest
+S> Enter username: moo
+S> index (to client): 5
+S> salt (to client): 19AI0Hc9jEkdFc
+
+C> % clitest
+C> Enter username: moo
+C> Enter index (from server): 5
+C> Enter salt (from server): 19AI0Hc9jEkdFc
+
+The server reports the index and salt values used for that user. They
+are sent over the network to the client. (Simulate this by cutting and
+pasting from one window to the other.)
+
+C> A (to server): 5wCDXRxLIv/zLazYfKupV/OY3BlhTZuJ71wVgI0HcL1kSJEpkMuWF.xEz/BV2wlJl7vk5Eoz9KMS1ccnaatsVP5D6CBm7UA.yVB59EQFN0dNBirvX29NAFdtdMsMppo5tHRy987XjJWrWSLpeibq6emr.gP8nYyX75GQqSiMY1j
+C> Enter password:
+
+S> Enter A (from client): 5wCDXRxLIv/zLazYfKupV/OY3BlhTZuJ71wVgI0HcL1kSJEpkMuWF.xEz/BV2wlJl7vk5Eoz9KMS1ccnaatsVP5D6CBm7UA.yVB59EQFN0dNBirvX29NAFdtdMsMppo5tHRy987XjJWrWSLpeibq6emr.gP8nYyX75GQqSiMY1j
+
+Now the client calculates A and sends it to the server, and while the
+server is munching on that, the client gets the password from the user.
+
+S> B (to client): 9dcCpulxQAbaDXI0NHWY6B.QH6B9fsoXs/x/5SCNBNJm/6H6bYfbVrwNmdquhLZjYMvpcgGc2mBYqL77RNfw1kVQo17//GfsByECBIjRnrAn02ffX9Y/llJcfscAQiii0hyZhJf9PT5wE7pC7WUjIgSqckIZ0JLNDbSr7fJcrgw
+S> Session key: ebbcf3a45c968defdcfff6e144ad8d4f5412167c9716e79cbf7cacfe18257947ad46fa5d6418a1fd
+
+The server now calculates B and sends it to the client. The session key
+is not sent -- it is a shared secret that can be used for encryption.
+
+C> Enter B (from server): 9dcCpulxQAbaDXI0NHWY6B.QH6B9fsoXs/x/5SCNBNJm/6H6bYfbVrwNmdquhLZjYMvpcgGc2mBYqL77RNfw1kVQo17//GfsByECBIjRnrAn02ffX9Y/llJcfscAQiii0hyZhJf9PT5wE7pC7WUjIgSqckIZ0JLNDbSr7fJcrgw
+C> Session key: ebbcf3a45c968defdcfff6e144ad8d4f5412167c9716e79cbf7cacfe18257947ad46fa5d6418a1fd
+C> Response (to server): b9ea99094a176c4be28eb469982066cc7146d180
+
+The client uses the B value to calculate its own copy of the shared secret
+session key, and sends a response to the server proving that it does know
+the correct key.
+
+S> Enter response (from client): b9ea99094a176c4be28eb469982066cc7146d180
+S> Authentication successful.
+S> Response (to client): cd46c839ccad2d0c76f3ca1905ae8ceda8d1c1dc
+
+The server authenticates the client. (You're in!)
+
+C> Enter server response: cd46c839ccad2d0c76f3ca1905ae8ceda8d1c1dc
+C> Server authentication successful.
+
+The client authenticates the server (prevents server spoofing in the case
+where the session key isn't used to encrypt the channel -- a spoofed server
+might just respond with random values and _pretend_ to authenticate the
+client; but the spoofed server won't know the session key and this check
+catches that).
+
+Final note:
+
+Remember that many breaches of security involve buggy software, such as
+servers susceptible to buffer overflow exploits that totally bypass any
+passphrase, secure or not. If an attacker roots your client, or the server,
+no form of authentication will work. Consider MAC-based schemes if this
+worries you.
diff --git a/package/ead/src/tinysrp/acconfig.h b/package/ead/src/tinysrp/acconfig.h
new file mode 100644
index 000000000..b74aed08f
--- /dev/null
+++ b/package/ead/src/tinysrp/acconfig.h
@@ -0,0 +1,9 @@
+#undef SHA1HANDSOFF
+
+#undef POSIX_TERMIOS
+
+#undef POSIX_SIGTYPE
+
+#undef VERSION
+
+#undef volatile
diff --git a/package/ead/src/tinysrp/acinclude.m4 b/package/ead/src/tinysrp/acinclude.m4
new file mode 100644
index 000000000..e0d0d04df
--- /dev/null
+++ b/package/ead/src/tinysrp/acinclude.m4
@@ -0,0 +1,27 @@
+dnl
+dnl check for signal type
+dnl
+dnl AC_RETSIGTYPE isn't quite right, but almost.
+dnl
+define(TYPE_SIGNAL,[
+AC_MSG_CHECKING([POSIX signal handlers])
+AC_CACHE_VAL(cv_has_posix_signals,
+[AC_TRY_COMPILE(
+[#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+#undef signal
+#endif
+extern void (*signal ()) ();], [],
+cv_has_posix_signals=yes, cv_has_posix_signals=no)])
+AC_MSG_RESULT($cv_has_posix_signals)
+if test $cv_has_posix_signals = yes; then
+ AC_DEFINE(RETSIGTYPE, void, [Return type is void])
+ AC_DEFINE(POSIX_SIGTYPE, [], [Have POSIX signals])
+else
+ if test $ac_cv_type_signal = void; then
+ AC_DEFINE(RETSIGTYPE, void, [Return type is void])
+ else
+ AC_DEFINE(RETSIGTYPE, int, [Return type is int])
+ fi
+fi])dnl
diff --git a/package/ead/src/tinysrp/aclocal.m4 b/package/ead/src/tinysrp/aclocal.m4
new file mode 100644
index 000000000..703fce4b7
--- /dev/null
+++ b/package/ead/src/tinysrp/aclocal.m4
@@ -0,0 +1,157 @@
+dnl aclocal.m4 generated automatically by aclocal 1.4a
+
+dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+dnl PARTICULAR PURPOSE.
+
+dnl
+dnl check for signal type
+dnl
+dnl AC_RETSIGTYPE isn't quite right, but almost.
+dnl
+define(TYPE_SIGNAL,[
+AC_MSG_CHECKING([POSIX signal handlers])
+AC_CACHE_VAL(cv_has_posix_signals,
+[AC_TRY_COMPILE(
+[#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+#undef signal
+#endif
+extern void (*signal ()) ();], [],
+cv_has_posix_signals=yes, cv_has_posix_signals=no)])
+AC_MSG_RESULT($cv_has_posix_signals)
+if test $cv_has_posix_signals = yes; then
+ AC_DEFINE(RETSIGTYPE, void, [Return type is void])
+ AC_DEFINE(POSIX_SIGTYPE, [], [Have POSIX signals])
+else
+ if test $ac_cv_type_signal = void; then
+ AC_DEFINE(RETSIGTYPE, void, [Return type is void])
+ else
+ AC_DEFINE(RETSIGTYPE, int, [Return type is int])
+ fi
+fi])dnl
+
+# Like AC_CONFIG_HEADER, but automatically create stamp file.
+
+AC_DEFUN(AM_CONFIG_HEADER,
+[AC_PREREQ([2.12])
+AC_CONFIG_HEADER([$1])
+dnl When config.status generates a header, we must update the stamp-h file.
+dnl This file resides in the same directory as the config header
+dnl that is generated. We must strip everything past the first ":",
+dnl and everything past the last "/".
+AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
+ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
+<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
+<<am_indx=1
+for am_file in <<$1>>; do
+ case " <<$>>CONFIG_HEADERS " in
+ *" <<$>>am_file "*<<)>>
+ echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
+ ;;
+ esac
+ am_indx=`expr "<<$>>am_indx" + 1`
+done<<>>dnl>>)
+changequote([,]))])
+
+# Do all the work for Automake. This macro actually does too much --
+# some checks are only needed if your package does certain things.
+# But this isn't really a big deal.
+
+# serial 1
+
+dnl Usage:
+dnl AM_INIT_AUTOMAKE(package,version, [no-define])
+
+AC_DEFUN(AM_INIT_AUTOMAKE,
+[AC_REQUIRE([AC_PROG_INSTALL])
+dnl We require 2.13 because we rely on SHELL being computed by configure.
+AC_PREREQ([2.13])
+PACKAGE=[$1]
+AC_SUBST(PACKAGE)
+VERSION=[$2]
+AC_SUBST(VERSION)
+dnl test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+fi
+ifelse([$3],,
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
+AC_REQUIRE([AM_SANITY_CHECK])
+AC_REQUIRE([AC_ARG_PROGRAM])
+dnl FIXME This is truly gross.
+missing_dir=`cd $ac_aux_dir && pwd`
+AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
+AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
+AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
+AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
+AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
+AC_REQUIRE([AC_PROG_MAKE_SET])])
+
+#
+# Check to make sure that the build environment is sane.
+#
+
+AC_DEFUN(AM_SANITY_CHECK,
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+ if test "[$]*" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftestfile`
+ fi
+ if test "[$]*" != "X $srcdir/configure conftestfile" \
+ && test "[$]*" != "X conftestfile $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
+ test "[$]2" = conftestfile
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+rm -f conftest*
+AC_MSG_RESULT(yes)])
+
+dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
+dnl The program must properly implement --version.
+AC_DEFUN(AM_MISSING_PROG,
+[AC_MSG_CHECKING(for working $2)
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if ($2 --version) < /dev/null > /dev/null 2>&1; then
+ $1=$2
+ AC_MSG_RESULT(found)
+else
+ $1="$3/missing $2"
+ AC_MSG_RESULT(missing)
+fi
+AC_SUBST($1)])
+
diff --git a/package/ead/src/tinysrp/bn.h b/package/ead/src/tinysrp/bn.h
new file mode 100644
index 000000000..0144dd961
--- /dev/null
+++ b/package/ead/src/tinysrp/bn.h
@@ -0,0 +1,471 @@
+/* crypto/bn/bn.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC 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 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_BN_H
+#define HEADER_BN_H
+
+#include <stdio.h> /* FILE */
+#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef VMS
+#undef BN_LLONG /* experimental, so far... */
+#endif
+
+#undef BN_MUL_COMBA
+#undef BN_SQR_COMBA
+#undef BN_RECURSION
+#undef RECP_MUL_MOD
+#undef MONT_MUL_MOD
+
+#if defined(SIZEOF_LONG_LONG) && SIZEOF_LONG_LONG == 8
+# if SIZEOF_LONG == 4
+# define THIRTY_TWO_BIT
+# else
+# define SIXTY_FOUR_BIT_LONG
+# endif
+#else
+# if SIZEOF_LONG == 4
+# define THIRTY_TWO_BIT
+# endif
+#endif
+
+#undef BN_LLONG
+
+/* assuming long is 64bit - this is the DEC Alpha
+ * unsigned long long is only 64 bits :-(, don't define
+ * BN_LLONG for the DEC Alpha */
+#ifdef SIXTY_FOUR_BIT_LONG
+#define BN_ULLONG unsigned long long
+#define BN_ULONG unsigned long
+#define BN_LONG long
+#define BN_BITS 128
+#define BN_BYTES 8
+#define BN_BITS2 64
+#define BN_BITS4 32
+#define BN_MASK (0xffffffffffffffffffffffffffffffffLL)
+#define BN_MASK2 (0xffffffffffffffffL)
+#define BN_MASK2l (0xffffffffL)
+#define BN_MASK2h (0xffffffff00000000L)
+#define BN_MASK2h1 (0xffffffff80000000L)
+#define BN_TBIT (0x8000000000000000L)
+#define BN_DEC_CONV (10000000000000000000UL)
+#define BN_DEC_FMT1 "%lu"
+#define BN_DEC_FMT2 "%019lu"
+#define BN_DEC_NUM 19
+#endif
+
+/* This is where the long long data type is 64 bits, but long is 32.
+ * For machines where there are 64bit registers, this is the mode to use.
+ * IRIX, on R4000 and above should use this mode, along with the relevant
+ * assembler code :-). Do NOT define BN_LLONG.
+ */
+#ifdef SIXTY_FOUR_BIT
+#undef BN_LLONG
+#undef BN_ULLONG
+#define BN_ULONG unsigned long long
+#define BN_LONG long long
+#define BN_BITS 128
+#define BN_BYTES 8
+#define BN_BITS2 64
+#define BN_BITS4 32
+#define BN_MASK2 (0xffffffffffffffffLL)
+#define BN_MASK2l (0xffffffffL)
+#define BN_MASK2h (0xffffffff00000000LL)
+#define BN_MASK2h1 (0xffffffff80000000LL)
+#define BN_TBIT (0x8000000000000000LL)
+#define BN_DEC_CONV (10000000000000000000LL)
+#define BN_DEC_FMT1 "%llu"
+#define BN_DEC_FMT2 "%019llu"
+#define BN_DEC_NUM 19
+#endif
+
+#ifdef THIRTY_TWO_BIT
+#if defined(WIN32) && !defined(__GNUC__)
+#define BN_ULLONG unsigned _int64
+#else
+#define BN_ULLONG unsigned long long
+#endif
+#define BN_ULONG unsigned long
+#define BN_LONG long
+#define BN_BITS 64
+#define BN_BYTES 4
+#define BN_BITS2 32
+#define BN_BITS4 16
+#ifdef WIN32
+/* VC++ doesn't like the LL suffix */
+#define BN_MASK (0xffffffffffffffffL)
+#else
+#define BN_MASK (0xffffffffffffffffLL)
+#endif
+#define BN_MASK2 (0xffffffffL)
+#define BN_MASK2l (0xffff)
+#define BN_MASK2h1 (0xffff8000L)
+#define BN_MASK2h (0xffff0000L)
+#define BN_TBIT (0x80000000L)
+#define BN_DEC_CONV (1000000000L)
+#define BN_DEC_FMT1 "%lu"
+#define BN_DEC_FMT2 "%09lu"
+#define BN_DEC_NUM 9
+#endif
+
+#ifdef SIXTEEN_BIT
+#ifndef BN_DIV2W
+#define BN_DIV2W
+#endif
+#define BN_ULLONG unsigned long
+#define BN_ULONG unsigned short
+#define BN_LONG short
+#define BN_BITS 32
+#define BN_BYTES 2
+#define BN_BITS2 16
+#define BN_BITS4 8
+#define BN_MASK (0xffffffff)
+#define BN_MASK2 (0xffff)
+#define BN_MASK2l (0xff)
+#define BN_MASK2h1 (0xff80)
+#define BN_MASK2h (0xff00)
+#define BN_TBIT (0x8000)
+#define BN_DEC_CONV (100000)
+#define BN_DEC_FMT1 "%u"
+#define BN_DEC_FMT2 "%05u"
+#define BN_DEC_NUM 5
+#endif
+
+#ifdef EIGHT_BIT
+#ifndef BN_DIV2W
+#define BN_DIV2W
+#endif
+#define BN_ULLONG unsigned short
+#define BN_ULONG unsigned char
+#define BN_LONG char
+#define BN_BITS 16
+#define BN_BYTES 1
+#define BN_BITS2 8
+#define BN_BITS4 4
+#define BN_MASK (0xffff)
+#define BN_MASK2 (0xff)
+#define BN_MASK2l (0xf)
+#define BN_MASK2h1 (0xf8)
+#define BN_MASK2h (0xf0)
+#define BN_TBIT (0x80)
+#define BN_DEC_CONV (100)
+#define BN_DEC_FMT1 "%u"
+#define BN_DEC_FMT2 "%02u"
+#define BN_DEC_NUM 2
+#endif
+
+#define BN_DEFAULT_BITS 1280
+
+#ifdef BIGNUM
+#undef BIGNUM
+#endif
+
+#define BN_FLG_MALLOCED 0x01
+#define BN_FLG_STATIC_DATA 0x02
+#define BN_FLG_FREE 0x8000 /* used for debuging */
+#define BN_set_flags(b,n) ((b)->flags|=(n))
+#define BN_get_flags(b,n) ((b)->flags&(n))
+
+typedef struct bignum_st
+ {
+ BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks. */
+ int top; /* Index of last used d +1. */
+ /* The next are internal book keeping for bn_expand. */
+ int dmax; /* Size of the d array. */
+ int neg; /* one if the number is negative */
+ int flags;
+ } BIGNUM;
+
+/* Used for temp variables */
+#define BN_CTX_NUM 12
+#define BN_CTX_NUM_POS 12
+typedef struct bignum_ctx
+ {
+ int tos;
+ BIGNUM bn[BN_CTX_NUM];
+ int flags;
+ int depth;
+ int pos[BN_CTX_NUM_POS];
+ int too_many;
+ } BN_CTX;
+
+/* Used for montgomery multiplication */
+typedef struct bn_mont_ctx_st
+ {
+ int ri; /* number of bits in R */
+ BIGNUM RR; /* used to convert to montgomery form */
+ BIGNUM N; /* The modulus */
+ BIGNUM Ni; /* R*(1/R mod N) - N*Ni = 1
+ * (Ni is only stored for bignum algorithm) */
+ BN_ULONG n0; /* least significant word of Ni */
+ int flags;
+ } BN_MONT_CTX;
+
+/* Used for reciprocal division/mod functions
+ * It cannot be shared between threads
+ */
+typedef struct bn_recp_ctx_st
+ {
+ BIGNUM N; /* the divisor */
+ BIGNUM Nr; /* the reciprocal */
+ int num_bits;
+ int shift;
+ int flags;
+ } BN_RECP_CTX;
+
+#define BN_to_montgomery(r,a,mont,ctx) BN_mod_mul_montgomery(\
+ r,a,&((mont)->RR),(mont),ctx)
+
+#define BN_prime_checks 0 /* default: select number of iterations
+ based on the size of the number */
+
+/* number of Miller-Rabin iterations for an error rate of less than 2^-80
+ * for random 'b'-bit input, b >= 100 (taken from table 4.4 in the Handbook
+ * of Applied Cryptography [Menezes, van Oorschot, Vanstone; CRC Press 1996];
+ * original paper: Damgaard, Landrock, Pomerance: Average case error estimates
+ * for the strong probable prime test. -- Math. Comp. 61 (1993) 177-194) */
+#define BN_prime_checks_for_size(b) ((b) >= 1300 ? 2 : \
+ (b) >= 850 ? 3 : \
+ (b) >= 650 ? 4 : \
+ (b) >= 550 ? 5 : \
+ (b) >= 450 ? 6 : \
+ (b) >= 400 ? 7 : \
+ (b) >= 350 ? 8 : \
+ (b) >= 300 ? 9 : \
+ (b) >= 250 ? 12 : \
+ (b) >= 200 ? 15 : \
+ (b) >= 150 ? 18 : \
+ /* b >= 100 */ 27)
+
+#define BN_num_bytes(a) ((BN_num_bits(a)+7)/8)
+#define BN_is_word(a,w) (((a)->top == 1) && ((a)->d[0] == (BN_ULONG)(w)))
+#define BN_is_zero(a) (((a)->top == 0) || BN_is_word(a,0))
+#define BN_is_one(a) (BN_is_word((a),1))
+#define BN_is_odd(a) (((a)->top > 0) && ((a)->d[0] & 1))
+#define BN_one(a) (BN_set_word((a),1))
+#define BN_zero(a) (BN_set_word((a),0))
+
+BIGNUM *BN_value_one(void);
+char * BN_options(void);
+BN_CTX *BN_CTX_new(void);
+void BN_CTX_init(BN_CTX *c);
+void BN_CTX_free(BN_CTX *c);
+void BN_CTX_start(BN_CTX *ctx);
+BIGNUM *BN_CTX_get(BN_CTX *ctx);
+void BN_CTX_end(BN_CTX *ctx);
+int BN_rand(BIGNUM *rnd, int bits, int top,int bottom);
+int BN_pseudo_rand(BIGNUM *rnd, int bits, int top,int bottom);
+int BN_num_bits(const BIGNUM *a);
+int BN_num_bits_word(BN_ULONG);
+BIGNUM *BN_new(void);
+void BN_init(BIGNUM *);
+void BN_clear_free(BIGNUM *a);
+BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b);
+BIGNUM *BN_bin2bn(const unsigned char *s,int len,BIGNUM *ret);
+int BN_bn2bin(const BIGNUM *a, unsigned char *to);
+int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int BN_mod(BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx);
+int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
+ BN_CTX *ctx);
+int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx);
+int BN_sqr(BIGNUM *r, BIGNUM *a,BN_CTX *ctx);
+BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w);
+BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w);
+int BN_mul_word(BIGNUM *a, BN_ULONG w);
+int BN_add_word(BIGNUM *a, BN_ULONG w);
+int BN_sub_word(BIGNUM *a, BN_ULONG w);
+int BN_set_word(BIGNUM *a, BN_ULONG w);
+BN_ULONG BN_get_word(BIGNUM *a);
+int BN_cmp(const BIGNUM *a, const BIGNUM *b);
+void BN_free(BIGNUM *a);
+int BN_is_bit_set(const BIGNUM *a, int n);
+int BN_lshift(BIGNUM *r, const BIGNUM *a, int n);
+int BN_lshift1(BIGNUM *r, BIGNUM *a);
+int BN_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p,BN_CTX *ctx);
+int BN_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m,BN_CTX *ctx);
+int BN_mod_exp_mont(BIGNUM *r, BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m,BN_CTX *ctx);
+int BN_mask_bits(BIGNUM *a,int n);
+int BN_mod_mul(BIGNUM *ret, BIGNUM *a, BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
+int BN_reciprocal(BIGNUM *r, BIGNUM *m, int len, BN_CTX *ctx);
+int BN_rshift(BIGNUM *r, BIGNUM *a, int n);
+int BN_rshift1(BIGNUM *r, BIGNUM *a);
+void BN_clear(BIGNUM *a);
+BIGNUM *BN_dup(const BIGNUM *a);
+int BN_ucmp(const BIGNUM *a, const BIGNUM *b);
+int BN_set_bit(BIGNUM *a, int n);
+int BN_clear_bit(BIGNUM *a, int n);
+int BN_gcd(BIGNUM *r,BIGNUM *in_a,BIGNUM *in_b,BN_CTX *ctx);
+BIGNUM *BN_mod_inverse(BIGNUM *ret,BIGNUM *a, const BIGNUM *n,BN_CTX *ctx);
+BIGNUM *BN_generate_prime(BIGNUM *ret,int bits,int safe,BIGNUM *add,
+ BIGNUM *rem,void (*callback)(int,int,void *),void *cb_arg);
+int BN_is_prime(const BIGNUM *p,int nchecks,
+ void (*callback)(int,int,void *),
+ BN_CTX *ctx,void *cb_arg);
+int BN_is_prime_fasttest(const BIGNUM *p,int nchecks,
+ void (*callback)(int,int,void *),BN_CTX *ctx,void *cb_arg,
+ int do_trial_division);
+
+BN_MONT_CTX *BN_MONT_CTX_new(void );
+void BN_MONT_CTX_init(BN_MONT_CTX *ctx);
+int BN_mod_mul_montgomery(BIGNUM *r,BIGNUM *a,BIGNUM *b,BN_MONT_CTX *mont,
+ BN_CTX *ctx);
+int BN_from_montgomery(BIGNUM *r,BIGNUM *a,BN_MONT_CTX *mont,BN_CTX *ctx);
+void BN_MONT_CTX_free(BN_MONT_CTX *mont);
+int BN_MONT_CTX_set(BN_MONT_CTX *mont,const BIGNUM *modulus,BN_CTX *ctx);
+BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to,BN_MONT_CTX *from);
+
+void BN_set_params(int mul,int high,int low,int mont);
+int BN_get_params(int which); /* 0, mul, 1 high, 2 low, 3 mont */
+
+void BN_RECP_CTX_init(BN_RECP_CTX *recp);
+BN_RECP_CTX *BN_RECP_CTX_new(void);
+void BN_RECP_CTX_free(BN_RECP_CTX *recp);
+int BN_RECP_CTX_set(BN_RECP_CTX *recp,const BIGNUM *rdiv,BN_CTX *ctx);
+int BN_mod_mul_reciprocal(BIGNUM *r, BIGNUM *x, BIGNUM *y,
+ BN_RECP_CTX *recp,BN_CTX *ctx);
+int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx);
+int BN_div_recp(BIGNUM *dv, BIGNUM *rem, BIGNUM *m,
+ BN_RECP_CTX *recp, BN_CTX *ctx);
+
+/* library internal functions */
+
+#define bn_expand(a,bits) ((((((bits+BN_BITS2-1))/BN_BITS2)) <= (a)->dmax)?\
+ (a):bn_expand2((a),(bits)/BN_BITS2+1))
+#define bn_wexpand(a,words) (((words) <= (a)->dmax)?(a):bn_expand2((a),(words)))
+BIGNUM *bn_expand2(BIGNUM *a, int words);
+
+#define bn_fix_top(a) \
+ { \
+ BN_ULONG *ftl; \
+ if ((a)->top > 0) \
+ { \
+ for (ftl= &((a)->d[(a)->top-1]); (a)->top > 0; (a)->top--) \
+ if (*(ftl--)) break; \
+ } \
+ }
+
+BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w);
+BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w);
+void bn_sqr_words(BN_ULONG *rp, BN_ULONG *ap, int num);
+BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
+BN_ULONG bn_add_words(BN_ULONG *rp, BN_ULONG *ap, BN_ULONG *bp,int num);
+BN_ULONG bn_sub_words(BN_ULONG *rp, BN_ULONG *ap, BN_ULONG *bp,int num);
+
+#ifdef BN_DEBUG
+ void bn_dump1(FILE *o, const char *a, BN_ULONG *b,int n);
+# define bn_print(a) {fprintf(stderr, #a "="); BN_print_fp(stderr,a); \
+ fprintf(stderr,"\n");}
+# define bn_dump(a,n) bn_dump1(stderr,#a,a,n);
+#else
+# define bn_print(a)
+# define bn_dump(a,b)
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+
+/* Error codes for the BN functions. */
+
+/* Function codes. */
+#define BN_F_BN_CTX_GET 116
+#define BN_F_BN_CTX_NEW 106
+#define BN_F_BN_DIV 107
+#define BN_F_BN_EXPAND2 108
+#define BN_F_BN_MOD_EXP2_MONT 118
+#define BN_F_BN_MOD_EXP_MONT 109
+#define BN_F_BN_MOD_EXP_MONT_WORD 117
+#define BN_F_BN_MOD_INVERSE 110
+#define BN_F_BN_MOD_MUL_RECIPROCAL 111
+#define BN_F_BN_MPI2BN 112
+#define BN_F_BN_NEW 113
+#define BN_F_BN_RAND 114
+#define BN_F_BN_USUB 115
+
+/* Reason codes. */
+#define BN_R_ARG2_LT_ARG3 100
+#define BN_R_BAD_RECIPROCAL 101
+#define BN_R_CALLED_WITH_EVEN_MODULUS 102
+#define BN_R_DIV_BY_ZERO 103
+#define BN_R_ENCODING_ERROR 104
+#define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA 105
+#define BN_R_INVALID_LENGTH 106
+#define BN_R_NOT_INITIALIZED 107
+#define BN_R_NO_INVERSE 108
+#define BN_R_TOO_MANY_TEMPORARY_VARIABLES 109
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/package/ead/src/tinysrp/bn_add.c b/package/ead/src/tinysrp/bn_add.c
new file mode 100644
index 000000000..aae4f2b93
--- /dev/null
+++ b/package/ead/src/tinysrp/bn_add.c
@@ -0,0 +1,305 @@
+/* crypto/bn/bn_add.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC 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 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include "bn_lcl.h"
+
+/* r can == a or b */
+int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
+ {
+ const BIGNUM *tmp;
+
+ bn_check_top(a);
+ bn_check_top(b);
+
+ /* a + b a+b
+ * a + -b a-b
+ * -a + b b-a
+ * -a + -b -(a+b)
+ */
+ if (a->neg ^ b->neg)
+ {
+ /* only one is negative */
+ if (a->neg)
+ { tmp=a; a=b; b=tmp; }
+
+ /* we are now a - b */
+
+ if (BN_ucmp(a,b) < 0)
+ {
+ if (!BN_usub(r,b,a)) return(0);
+ r->neg=1;
+ }
+ else
+ {
+ if (!BN_usub(r,a,b)) return(0);
+ r->neg=0;
+ }
+ return(1);
+ }
+
+ if (a->neg) /* both are neg */
+ r->neg=1;
+ else
+ r->neg=0;
+
+ if (!BN_uadd(r,a,b)) return(0);
+ return(1);
+ }
+
+/* unsigned add of b to a, r must be large enough */
+int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
+ {
+ register int i;
+ int max,min;
+ BN_ULONG *ap,*bp,*rp,carry,t1;
+ const BIGNUM *tmp;
+
+ bn_check_top(a);
+ bn_check_top(b);
+
+ if (a->top < b->top)
+ { tmp=a; a=b; b=tmp; }
+ max=a->top;
+ min=b->top;
+
+ if (bn_wexpand(r,max+1) == NULL)
+ return(0);
+
+ r->top=max;
+
+
+ ap=a->d;
+ bp=b->d;
+ rp=r->d;
+ carry=0;
+
+ carry=bn_add_words(rp,ap,bp,min);
+ rp+=min;
+ ap+=min;
+ bp+=min;
+ i=min;
+
+ if (carry)
+ {
+ while (i < max)
+ {
+ i++;
+ t1= *(ap++);
+ if ((*(rp++)=(t1+1)&BN_MASK2) >= t1)
+ {
+ carry=0;
+ break;
+ }
+ }
+ if ((i >= max) && carry)
+ {
+ *(rp++)=1;
+ r->top++;
+ }
+ }
+ if (rp != ap)
+ {
+ for (; i<max; i++)
+ *(rp++)= *(ap++);
+ }
+ /* memcpy(rp,ap,sizeof(*ap)*(max-i));*/
+ return(1);
+ }
+
+/* unsigned subtraction of b from a, a must be larger than b. */
+int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
+ {
+ int max,min;
+ register BN_ULONG t1,t2,*ap,*bp,*rp;
+ int i,carry;
+#if defined(IRIX_CC_BUG) && !defined(LINT)
+ int dummy;
+#endif
+
+ bn_check_top(a);
+ bn_check_top(b);
+
+ if (a->top < b->top) /* hmm... should not be happening */
+ {
+ return(0);
+ }
+
+ max=a->top;
+ min=b->top;
+ if (bn_wexpand(r,max) == NULL) return(0);
+
+ ap=a->d;
+ bp=b->d;
+ rp=r->d;
+
+#if 1
+ carry=0;
+ for (i=0; i<min; i++)
+ {
+ t1= *(ap++);
+ t2= *(bp++);
+ if (carry)
+ {
+ carry=(t1 <= t2);
+ t1=(t1-t2-1)&BN_MASK2;
+ }
+ else
+ {
+ carry=(t1 < t2);
+ t1=(t1-t2)&BN_MASK2;
+ }
+#if defined(IRIX_CC_BUG) && !defined(LINT)
+ dummy=t1;
+#endif
+ *(rp++)=t1&BN_MASK2;
+ }
+#else
+ carry=bn_sub_words(rp,ap,bp,min);
+ ap+=min;
+ bp+=min;
+ rp+=min;
+ i=min;
+#endif
+ if (carry) /* subtracted */
+ {
+ while (i < max)
+ {
+ i++;
+ t1= *(ap++);
+ t2=(t1-1)&BN_MASK2;
+ *(rp++)=t2;
+ if (t1 > t2) break;
+ }
+ }
+#if 0
+ memcpy(rp,ap,sizeof(*rp)*(max-i));
+#else
+ if (rp != ap)
+ {
+ for (;;)
+ {
+ if (i++ >= max) break;
+ rp[0]=ap[0];
+ if (i++ >= max) break;
+ rp[1]=ap[1];
+ if (i++ >= max) break;
+ rp[2]=ap[2];
+ if (i++ >= max) break;
+ rp[3]=ap[3];
+ rp+=4;
+ ap+=4;
+ }
+ }
+#endif
+
+ r->top=max;
+ bn_fix_top(r);
+ return(1);
+ }
+
+int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
+ {
+ int max;
+ int add=0,neg=0;
+ const BIGNUM *tmp;
+
+ bn_check_top(a);
+ bn_check_top(b);
+
+ /* a - b a-b
+ * a - -b a+b
+ * -a - b -(a+b)
+ * -a - -b b-a
+ */
+ if (a->neg)
+ {
+ if (b->neg)
+ { tmp=a; a=b; b=tmp; }
+ else
+ { add=1; neg=1; }
+ }
+ else
+ {
+ if (b->neg) { add=1; neg=0; }
+ }
+
+ if (add)
+ {
+ if (!BN_uadd(r,a,b)) return(0);
+ r->neg=neg;
+ return(1);
+ }
+
+ /* We are actually doing a - b :-) */
+
+ max=(a->top > b->top)?a->top:b->top;
+ if (bn_wexpand(r,max) == NULL) return(0);
+ if (BN_ucmp(a,b) < 0)
+ {
+ if (!BN_usub(r,b,a)) return(0);
+ r->neg=1;
+ }
+ else
+ {
+ if (!BN_usub(r,a,b)) return(0);
+ r->neg=0;
+ }
+ return(1);
+ }
+
diff --git a/package/ead/src/tinysrp/bn_asm.c b/package/ead/src/tinysrp/bn_asm.c
new file mode 100644
index 000000000..b24c9af7c
--- /dev/null
+++ b/package/ead/src/tinysrp/bn_asm.c
@@ -0,0 +1,382 @@
+/* crypto/bn/bn_asm.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC 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 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef BN_DEBUG
+# undef NDEBUG /* avoid conflicting definitions */
+# define NDEBUG
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include "bn_lcl.h"
+
+#if defined(BN_LLONG) || defined(BN_UMULT_HIGH)
+
+BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w)
+ {
+ BN_ULONG c1=0;
+
+ assert(num >= 0);
+ if (num <= 0) return(c1);
+
+ while (num&~3)
+ {
+ mul_add(rp[0],ap[0],w,c1);
+ mul_add(rp[1],ap[1],w,c1);
+ mul_add(rp[2],ap[2],w,c1);
+ mul_add(rp[3],ap[3],w,c1);
+ ap+=4; rp+=4; num-=4;
+ }
+ if (num)
+ {
+ mul_add(rp[0],ap[0],w,c1); if (--num==0) return c1;
+ mul_add(rp[1],ap[1],w,c1); if (--num==0) return c1;
+ mul_add(rp[2],ap[2],w,c1); return c1;
+ }
+
+ return(c1);
+ }
+
+BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w)
+ {
+ BN_ULONG c1=0;
+
+ assert(num >= 0);
+ if (num <= 0) return(c1);
+
+ while (num&~3)
+ {
+ mul(rp[0],ap[0],w,c1);
+ mul(rp[1],ap[1],w,c1);
+ mul(rp[2],ap[2],w,c1);
+ mul(rp[3],ap[3],w,c1);
+ ap+=4; rp+=4; num-=4;
+ }
+ if (num)
+ {
+ mul(rp[0],ap[0],w,c1); if (--num == 0) return c1;
+ mul(rp[1],ap[1],w,c1); if (--num == 0) return c1;
+ mul(rp[2],ap[2],w,c1);
+ }
+ return(c1);
+ }
+
+void bn_sqr_words(BN_ULONG *r, BN_ULONG *a, int n)
+ {
+ assert(n >= 0);
+ if (n <= 0) return;
+ while (n&~3)
+ {
+ sqr(r[0],r[1],a[0]);
+ sqr(r[2],r[3],a[1]);
+ sqr(r[4],r[5],a[2]);
+ sqr(r[6],r[7],a[3]);
+ a+=4; r+=8; n-=4;
+ }
+ if (n)
+ {
+ sqr(r[0],r[1],a[0]); if (--n == 0) return;
+ sqr(r[2],r[3],a[1]); if (--n == 0) return;
+ sqr(r[4],r[5],a[2]);
+ }
+ }
+
+#else /* !(defined(BN_LLONG) || defined(BN_UMULT_HIGH)) */
+
+BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w)
+ {
+ BN_ULONG c=0;
+ BN_ULONG bl,bh;
+
+ assert(num >= 0);
+ if (num <= 0) return((BN_ULONG)0);
+
+ bl=LBITS(w);
+ bh=HBITS(w);
+
+ for (;;)
+ {
+ mul_add(rp[0],ap[0],bl,bh,c);
+ if (--num == 0) break;
+ mul_add(rp[1],ap[1],bl,bh,c);
+ if (--num == 0) break;
+ mul_add(rp[2],ap[2],bl,bh,c);
+ if (--num == 0) break;
+ mul_add(rp[3],ap[3],bl,bh,c);
+ if (--num == 0) break;
+ ap+=4;
+ rp+=4;
+ }
+ return(c);
+ }
+
+BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w)
+ {
+ BN_ULONG carry=0;
+ BN_ULONG bl,bh;
+
+ assert(num >= 0);
+ if (num <= 0) return((BN_ULONG)0);
+
+ bl=LBITS(w);
+ bh=HBITS(w);
+
+ for (;;)
+ {
+ mul(rp[0],ap[0],bl,bh,carry);
+ if (--num == 0) break;
+ mul(rp[1],ap[1],bl,bh,carry);
+ if (--num == 0) break;
+ mul(rp[2],ap[2],bl,bh,carry);
+ if (--num == 0) break;
+ mul(rp[3],ap[3],bl,bh,carry);
+ if (--num == 0) break;
+ ap+=4;
+ rp+=4;
+ }
+ return(carry);
+ }
+
+void bn_sqr_words(BN_ULONG *r, BN_ULONG *a, int n)
+ {
+ assert(n >= 0);
+ if (n <= 0) return;
+ for (;;)
+ {
+ sqr64(r[0],r[1],a[0]);
+ if (--n == 0) break;
+
+ sqr64(r[2],r[3],a[1]);
+ if (--n == 0) break;
+
+ sqr64(r[4],r[5],a[2]);
+ if (--n == 0) break;
+
+ sqr64(r[6],r[7],a[3]);
+ if (--n == 0) break;
+
+ a+=4;
+ r+=8;
+ }
+ }
+
+#endif /* !(defined(BN_LLONG) || defined(BN_UMULT_HIGH)) */
+
+#if defined(BN_LLONG) && defined(BN_DIV2W)
+
+BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)
+ {
+ return((BN_ULONG)(((((BN_ULLONG)h)<<BN_BITS2)|l)/(BN_ULLONG)d));
+ }
+
+#else
+
+/* Divide h,l by d and return the result. */
+/* I need to test this some more :-( */
+BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)
+ {
+ BN_ULONG dh,dl,q,ret=0,th,tl,t;
+ int i,count=2;
+
+ if (d == 0) return(BN_MASK2);
+
+ i=BN_num_bits_word(d);
+ assert((i == BN_BITS2) || (h > (BN_ULONG)1<<i));
+
+ i=BN_BITS2-i;
+ if (h >= d) h-=d;
+
+ if (i)
+ {
+ d<<=i;
+ h=(h<<i)|(l>>(BN_BITS2-i));
+ l<<=i;
+ }
+ dh=(d&BN_MASK2h)>>BN_BITS4;
+ dl=(d&BN_MASK2l);
+ for (;;)
+ {
+ if ((h>>BN_BITS4) == dh)
+ q=BN_MASK2l;
+ else
+ q=h/dh;
+
+ th=q*dh;
+ tl=dl*q;
+ for (;;)
+ {
+ t=h-th;
+ if ((t&BN_MASK2h) ||
+ ((tl) <= (
+ (t<<BN_BITS4)|
+ ((l&BN_MASK2h)>>BN_BITS4))))
+ break;
+ q--;
+ th-=dh;
+ tl-=dl;
+ }
+ t=(tl>>BN_BITS4);
+ tl=(tl<<BN_BITS4)&BN_MASK2h;
+ th+=t;
+
+ if (l < tl) th++;
+ l-=tl;
+ if (h < th)
+ {
+ h+=d;
+ q--;
+ }
+ h-=th;
+
+ if (--count == 0) break;
+
+ ret=q<<BN_BITS4;
+ h=((h<<BN_BITS4)|(l>>BN_BITS4))&BN_MASK2;
+ l=(l&BN_MASK2l)<<BN_BITS4;
+ }
+ ret|=q;
+ return(ret);
+ }
+#endif /* !defined(BN_LLONG) && defined(BN_DIV2W) */
+
+#ifdef BN_LLONG
+BN_ULONG bn_add_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
+ {
+ BN_ULLONG ll=0;
+
+ assert(n >= 0);
+ if (n <= 0) return((BN_ULONG)0);
+
+ for (;;)
+ {
+ ll+=(BN_ULLONG)a[0]+b[0];
+ r[0]=(BN_ULONG)ll&BN_MASK2;
+ ll>>=BN_BITS2;
+ if (--n <= 0) break;
+
+ ll+=(BN_ULLONG)a[1]+b[1];
+ r[1]=(BN_ULONG)ll&BN_MASK2;
+ ll>>=BN_BITS2;
+ if (--n <= 0) break;
+
+ ll+=(BN_ULLONG)a[2]+b[2];
+ r[2]=(BN_ULONG)ll&BN_MASK2;
+ ll>>=BN_BITS2;
+ if (--n <= 0) break;
+
+ ll+=(BN_ULLONG)a[3]+b[3];
+ r[3]=(BN_ULONG)ll&BN_MASK2;
+ ll>>=BN_BITS2;
+ if (--n <= 0) break;
+
+ a+=4;
+ b+=4;
+ r+=4;
+ }
+ return((BN_ULONG)ll);
+ }
+#else /* !BN_LLONG */
+BN_ULONG bn_add_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
+ {
+ BN_ULONG c,l,t;
+
+ assert(n >= 0);
+ if (n <= 0) return((BN_ULONG)0);
+
+ c=0;
+ for (;;)
+ {
+ t=a[0];
+ t=(t+c)&BN_MASK2;
+ c=(t < c);
+ l=(t+b[0])&BN_MASK2;
+ c+=(l < t);
+ r[0]=l;
+ if (--n <= 0) break;
+
+ t=a[1];
+ t=(t+c)&BN_MASK2;
+ c=(t < c);
+ l=(t+b[1])&BN_MASK2;
+ c+=(l < t);
+ r[1]=l;
+ if (--n <= 0) break;
+
+ t=a[2];
+ t=(t+c)&BN_MASK2;
+ c=(t < c);
+ l=(t+b[2])&BN_MASK2;
+ c+=(l < t);
+ r[2]=l;
+ if (--n <= 0) break;
+
+ t=a[3];
+ t=(t+c)&BN_MASK2;
+ c=(t < c);
+ l=(t+b[3])&BN_MASK2;
+ c+=(l < t);
+ r[3]=l;
+ if (--n <= 0) break;
+
+ a+=4;
+ b+=4;
+ r+=4;
+ }
+ return((BN_ULONG)c);
+ }
+#endif /* !BN_LLONG */
diff --git a/package/ead/src/tinysrp/bn_ctx.c b/package/ead/src/tinysrp/bn_ctx.c
new file mode 100644
index 000000000..20a6605ab
--- /dev/null
+++ b/package/ead/src/tinysrp/bn_ctx.c
@@ -0,0 +1,142 @@
+/* crypto/bn/bn_ctx.c */
+/* Written by Ulf Moeller for the OpenSSL project. */
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL 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. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef BN_CTX_DEBUG
+# undef NDEBUG /* avoid conflicting definitions */
+# define NDEBUG
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <bn.h>
+
+
+BN_CTX *BN_CTX_new(void)
+ {
+ BN_CTX *ret;
+
+ ret=(BN_CTX *)malloc(sizeof(BN_CTX));
+ if (ret == NULL)
+ {
+ return(NULL);
+ }
+
+ BN_CTX_init(ret);
+ ret->flags=BN_FLG_MALLOCED;
+ return(ret);
+ }
+
+void BN_CTX_init(BN_CTX *ctx)
+ {
+ int i;
+ ctx->tos = 0;
+ ctx->flags = 0;
+ ctx->depth = 0;
+ ctx->too_many = 0;
+ for (i = 0; i < BN_CTX_NUM; i++)
+ BN_init(&(ctx->bn[i]));
+ }
+
+void BN_CTX_free(BN_CTX *ctx)
+ {
+ int i;
+
+ if (ctx == NULL) return;
+ assert(ctx->depth == 0);
+
+ for (i=0; i < BN_CTX_NUM; i++)
+ BN_clear_free(&(ctx->bn[i]));
+ if (ctx->flags & BN_FLG_MALLOCED)
+ free(ctx);
+ }
+
+void BN_CTX_start(BN_CTX *ctx)
+ {
+ if (ctx->depth < BN_CTX_NUM_POS)
+ ctx->pos[ctx->depth] = ctx->tos;
+ ctx->depth++;
+ }
+
+BIGNUM *BN_CTX_get(BN_CTX *ctx)
+ {
+ if (ctx->depth > BN_CTX_NUM_POS || ctx->tos >= BN_CTX_NUM)
+ {
+ if (!ctx->too_many)
+ {
+ /* disable error code until BN_CTX_end is called: */
+ ctx->too_many = 1;
+ }
+ return NULL;
+ }
+ return (&(ctx->bn[ctx->tos++]));
+ }
+
+void BN_CTX_end(BN_CTX *ctx)
+ {
+ if (ctx == NULL) return;
+ assert(ctx->depth > 0);
+ if (ctx->depth == 0)
+ /* should never happen, but we can tolerate it if not in
+ * debug mode (could be a 'goto err' in the calling function
+ * before BN_CTX_start was reached) */
+ BN_CTX_start(ctx);
+
+ ctx->too_many = 0;
+ ctx->depth--;
+ if (ctx->depth < BN_CTX_NUM_POS)
+ ctx->tos = ctx->pos[ctx->depth];
+ }
diff --git a/package/ead/src/tinysrp/bn_div.c b/package/ead/src/tinysrp/bn_div.c
new file mode 100644
index 000000000..fd21913d1
--- /dev/null
+++ b/package/ead/src/tinysrp/bn_div.c
@@ -0,0 +1,378 @@
+/* crypto/bn/bn_div.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC 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 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include "bn_lcl.h"
+
+#define NO_ASM
+
+/* The old slow way */
+#if 0
+int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
+ BN_CTX *ctx)
+ {
+ int i,nm,nd;
+ int ret = 0;
+ BIGNUM *D;
+
+ bn_check_top(m);
+ bn_check_top(d);
+ if (BN_is_zero(d))
+ {
+ return(0);
+ }
+
+ if (BN_ucmp(m,d) < 0)
+ {
+ if (rem != NULL)
+ { if (BN_copy(rem,m) == NULL) return(0); }
+ if (dv != NULL) BN_zero(dv);
+ return(1);
+ }
+
+ BN_CTX_start(ctx);
+ D = BN_CTX_get(ctx);
+ if (dv == NULL) dv = BN_CTX_get(ctx);
+ if (rem == NULL) rem = BN_CTX_get(ctx);
+ if (D == NULL || dv == NULL || rem == NULL)
+ goto end;
+
+ nd=BN_num_bits(d);
+ nm=BN_num_bits(m);
+ if (BN_copy(D,d) == NULL) goto end;
+ if (BN_copy(rem,m) == NULL) goto end;
+
+ /* The next 2 are needed so we can do a dv->d[0]|=1 later
+ * since BN_lshift1 will only work once there is a value :-) */
+ BN_zero(dv);
+ bn_wexpand(dv,1);
+ dv->top=1;
+
+ if (!BN_lshift(D,D,nm-nd)) goto end;
+ for (i=nm-nd; i>=0; i--)
+ {
+ if (!BN_lshift1(dv,dv)) goto end;
+ if (BN_ucmp(rem,D) >= 0)
+ {
+ dv->d[0]|=1;
+ if (!BN_usub(rem,rem,D)) goto end;
+ }
+/* CAN IMPROVE (and have now :=) */
+ if (!BN_rshift1(D,D)) goto end;
+ }
+ rem->neg=BN_is_zero(rem)?0:m->neg;
+ dv->neg=m->neg^d->neg;
+ ret = 1;
+ end:
+ BN_CTX_end(ctx);
+ return(ret);
+ }
+
+#else
+
+#if !defined(NO_ASM) && !defined(NO_INLINE_ASM) && !defined(PEDANTIC) && !defined(BN_DIV3W)
+# if defined(__GNUC__) && __GNUC__>=2
+# if defined(__i386)
+ /*
+ * There were two reasons for implementing this template:
+ * - GNU C generates a call to a function (__udivdi3 to be exact)
+ * in reply to ((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0 (I fail to
+ * understand why...);
+ * - divl doesn't only calculate quotient, but also leaves
+ * remainder in %edx which we can definitely use here:-)
+ *
+ * <appro@fy.chalmers.se>
+ */
+# define bn_div_words(n0,n1,d0) \
+ ({ asm volatile ( \
+ "divl %4" \
+ : "=a"(q), "=d"(rem) \
+ : "a"(n1), "d"(n0), "g"(d0) \
+ : "cc"); \
+ q; \
+ })
+# define REMAINDER_IS_ALREADY_CALCULATED
+# endif /* __<cpu> */
+# endif /* __GNUC__ */
+#endif /* NO_ASM */
+
+int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
+ BN_CTX *ctx)
+ {
+ int norm_shift,i,j,loop;
+ BIGNUM *tmp,wnum,*snum,*sdiv,*res;
+ BN_ULONG *resp,*wnump;
+ BN_ULONG d0,d1;
+ int num_n,div_n;
+
+ bn_check_top(num);
+ bn_check_top(divisor);
+
+ if (BN_is_zero(divisor))
+ {
+ return(0);
+ }
+
+ if (BN_ucmp(num,divisor) < 0)
+ {
+ if (rm != NULL)
+ { if (BN_copy(rm,num) == NULL) return(0); }
+ if (dv != NULL) BN_zero(dv);
+ return(1);
+ }
+
+ BN_CTX_start(ctx);
+ tmp=BN_CTX_get(ctx);
+ tmp->neg=0;
+ snum=BN_CTX_get(ctx);
+ sdiv=BN_CTX_get(ctx);
+ if (dv == NULL)
+ res=BN_CTX_get(ctx);
+ else res=dv;
+ if (res == NULL) goto err;
+
+ /* First we normalise the numbers */
+ norm_shift=BN_BITS2-((BN_num_bits(divisor))%BN_BITS2);
+ BN_lshift(sdiv,divisor,norm_shift);
+ sdiv->neg=0;
+ norm_shift+=BN_BITS2;
+ BN_lshift(snum,num,norm_shift);
+ snum->neg=0;
+ div_n=sdiv->top;
+ num_n=snum->top;
+ loop=num_n-div_n;
+
+ /* Lets setup a 'window' into snum
+ * This is the part that corresponds to the current
+ * 'area' being divided */
+ BN_init(&wnum);
+ wnum.d= &(snum->d[loop]);
+ wnum.top= div_n;
+ wnum.dmax= snum->dmax+1; /* a bit of a lie */
+
+ /* Get the top 2 words of sdiv */
+ /* i=sdiv->top; */
+ d0=sdiv->d[div_n-1];
+ d1=(div_n == 1)?0:sdiv->d[div_n-2];
+
+ /* pointer to the 'top' of snum */
+ wnump= &(snum->d[num_n-1]);
+
+ /* Setup to 'res' */
+ res->neg= (num->neg^divisor->neg);
+ if (!bn_wexpand(res,(loop+1))) goto err;
+ res->top=loop;
+ resp= &(res->d[loop-1]);
+
+ /* space for temp */
+ if (!bn_wexpand(tmp,(div_n+1))) goto err;
+
+ if (BN_ucmp(&wnum,sdiv) >= 0)
+ {
+ if (!BN_usub(&wnum,&wnum,sdiv)) goto err;
+ *resp=1;
+ res->d[res->top-1]=1;
+ }
+ else
+ res->top--;
+ resp--;
+
+ for (i=0; i<loop-1; i++)
+ {
+ BN_ULONG q,l0;
+#ifdef BN_DIV3W
+ q=bn_div_3_words(wnump,d1,d0);
+#else
+ BN_ULONG n0,n1,rem=0;
+
+ n0=wnump[0];
+ n1=wnump[-1];
+ if (n0 == d0)
+ q=BN_MASK2;
+ else /* n0 < d0 */
+ {
+#ifdef BN_LLONG
+ BN_ULLONG t2;
+
+#if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words)
+ q=(BN_ULONG)(((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0);
+#else
+ q=bn_div_words(n0,n1,d0);
+#endif
+
+#ifndef REMAINDER_IS_ALREADY_CALCULATED
+ /*
+ * rem doesn't have to be BN_ULLONG. The least we
+ * know it's less that d0, isn't it?
+ */
+ rem=(n1-q*d0)&BN_MASK2;
+#endif
+ t2=(BN_ULLONG)d1*q;
+
+ for (;;)
+ {
+ if (t2 <= ((((BN_ULLONG)rem)<<BN_BITS2)|wnump[-2]))
+ break;
+ q--;
+ rem += d0;
+ if (rem < d0) break; /* don't let rem overflow */
+ t2 -= d1;
+ }
+#else /* !BN_LLONG */
+ BN_ULONG t2l,t2h,ql,qh;
+
+ q=bn_div_words(n0,n1,d0);
+#ifndef REMAINDER_IS_ALREADY_CALCULATED
+ rem=(n1-q*d0)&BN_MASK2;
+#endif
+
+#ifdef BN_UMULT_HIGH
+ t2l = d1 * q;
+ t2h = BN_UMULT_HIGH(d1,q);
+#else
+ t2l=LBITS(d1); t2h=HBITS(d1);
+ ql =LBITS(q); qh =HBITS(q);
+ mul64(t2l,t2h,ql,qh); /* t2=(BN_ULLONG)d1*q; */
+#endif
+
+ for (;;)
+ {
+ if ((t2h < rem) ||
+ ((t2h == rem) && (t2l <= wnump[-2])))
+ break;
+ q--;
+ rem += d0;
+ if (rem < d0) break; /* don't let rem overflow */
+ if (t2l < d1) t2h--; t2l -= d1;
+ }
+#endif /* !BN_LLONG */
+ }
+#endif /* !BN_DIV3W */
+
+ l0=bn_mul_words(tmp->d,sdiv->d,div_n,q);
+ wnum.d--; wnum.top++;
+ tmp->d[div_n]=l0;
+ for (j=div_n+1; j>0; j--)
+ if (tmp->d[j-1]) break;
+ tmp->top=j;
+
+ j=wnum.top;
+ BN_sub(&wnum,&wnum,tmp);
+
+ snum->top=snum->top+wnum.top-j;
+
+ if (wnum.neg)
+ {
+ q--;
+ j=wnum.top;
+ BN_add(&wnum,&wnum,sdiv);
+ snum->top+=wnum.top-j;
+ }
+ *(resp--)=q;
+ wnump--;
+ }
+ if (rm != NULL)
+ {
+ BN_rshift(rm,snum,norm_shift);
+ rm->neg=num->neg;
+ }
+ BN_CTX_end(ctx);
+ return(1);
+err:
+ BN_CTX_end(ctx);
+ return(0);
+ }
+
+#endif
+
+/* rem != m */
+int BN_mod(BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx)
+ {
+#if 0 /* The old slow way */
+ int i,nm,nd;
+ BIGNUM *dv;
+
+ if (BN_ucmp(m,d) < 0)
+ return((BN_copy(rem,m) == NULL)?0:1);
+
+ BN_CTX_start(ctx);
+ dv=BN_CTX_get(ctx);
+
+ if (!BN_copy(rem,m)) goto err;
+
+ nm=BN_num_bits(rem);
+ nd=BN_num_bits(d);
+ if (!BN_lshift(dv,d,nm-nd)) goto err;
+ for (i=nm-nd; i>=0; i--)
+ {
+ if (BN_cmp(rem,dv) >= 0)
+ {
+ if (!BN_sub(rem,rem,dv)) goto err;
+ }
+ if (!BN_rshift1(dv,dv)) goto err;
+ }
+ BN_CTX_end(ctx);
+ return(1);
+ err:
+ BN_CTX_end(ctx);
+ return(0);
+#else
+ return(BN_div(NULL,rem,m,d,ctx));
+#endif
+ }
+
diff --git a/package/ead/src/tinysrp/bn_exp.c b/package/ead/src/tinysrp/bn_exp.c
new file mode 100644
index 000000000..09afb79f6
--- /dev/null
+++ b/package/ead/src/tinysrp/bn_exp.c
@@ -0,0 +1,395 @@
+/* crypto/bn/bn_exp.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC 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 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL 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. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+
+#include <stdio.h>
+#include "bn_lcl.h"
+
+#define TABLE_SIZE 32
+
+/* slow but works */
+int BN_mod_mul(BIGNUM *ret, BIGNUM *a, BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
+ {
+ BIGNUM *t;
+ int r=0;
+
+ bn_check_top(a);
+ bn_check_top(b);
+ bn_check_top(m);
+
+ BN_CTX_start(ctx);
+ if ((t = BN_CTX_get(ctx)) == NULL) goto err;
+ if (a == b)
+ { if (!BN_sqr(t,a,ctx)) goto err; }
+ else
+ { if (!BN_mul(t,a,b,ctx)) goto err; }
+ if (!BN_mod(ret,t,m,ctx)) goto err;
+ r=1;
+err:
+ BN_CTX_end(ctx);
+ return(r);
+ }
+
+int BN_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
+ BN_CTX *ctx)
+ {
+ int ret;
+
+ bn_check_top(a);
+ bn_check_top(p);
+ bn_check_top(m);
+
+#ifdef MONT_MUL_MOD
+ /* I have finally been able to take out this pre-condition of
+ * the top bit being set. It was caused by an error in BN_div
+ * with negatives. There was also another problem when for a^b%m
+ * a >= m. eay 07-May-97 */
+/* if ((m->d[m->top-1]&BN_TBIT) && BN_is_odd(m)) */
+
+ if (BN_is_odd(m))
+ {
+ if (a->top == 1)
+ {
+ BN_ULONG A = a->d[0];
+ ret=BN_mod_exp_mont_word(r,A,p,m,ctx,NULL);
+ }
+ else
+ ret=BN_mod_exp_mont(r,a,p,m,ctx,NULL);
+ }
+ else
+#endif
+#ifdef RECP_MUL_MOD
+ { ret=BN_mod_exp_recp(r,a,p,m,ctx); }
+#else
+ { ret=BN_mod_exp_simple(r,a,p,m,ctx); }
+#endif
+
+ return(ret);
+ }
+
+
+#ifdef RECP_MUL_MOD
+int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx)
+ {
+ int i,j,bits,ret=0,wstart,wend,window,wvalue;
+ int start=1,ts=0;
+ BIGNUM *aa;
+ BIGNUM val[TABLE_SIZE];
+ BN_RECP_CTX recp;
+
+ bits=BN_num_bits(p);
+
+ if (bits == 0)
+ {
+ BN_one(r);
+ return(1);
+ }
+
+ BN_CTX_start(ctx);
+ if ((aa = BN_CTX_get(ctx)) == NULL) goto err;
+
+ BN_RECP_CTX_init(&recp);
+ if (BN_RECP_CTX_set(&recp,m,ctx) <= 0) goto err;
+
+ BN_init(&(val[0]));
+ ts=1;
+
+ if (!BN_mod(&(val[0]),a,m,ctx)) goto err; /* 1 */
+
+ window = BN_window_bits_for_exponent_size(bits);
+ if (window > 1)
+ {
+ if (!BN_mod_mul_reciprocal(aa,&(val[0]),&(val[0]),&recp,ctx))
+ goto err; /* 2 */
+ j=1<<(window-1);
+ for (i=1; i<j; i++)
+ {
+ BN_init(&val[i]);
+ if (!BN_mod_mul_reciprocal(&(val[i]),&(val[i-1]),aa,&recp,ctx))
+ goto err;
+ }
+ ts=i;
+ }
+
+ start=1; /* This is used to avoid multiplication etc
+ * when there is only the value '1' in the
+ * buffer. */
+ wvalue=0; /* The 'value' of the window */
+ wstart=bits-1; /* The top bit of the window */
+ wend=0; /* The bottom bit of the window */
+
+ if (!BN_one(r)) goto err;
+
+ for (;;)
+ {
+ if (BN_is_bit_set(p,wstart) == 0)
+ {
+ if (!start)
+ if (!BN_mod_mul_reciprocal(r,r,r,&recp,ctx))
+ goto err;
+ if (wstart == 0) break;
+ wstart--;
+ continue;
+ }
+ /* We now have wstart on a 'set' bit, we now need to work out
+ * how bit a window to do. To do this we need to scan
+ * forward until the last set bit before the end of the
+ * window */
+ j=wstart;
+ wvalue=1;
+ wend=0;
+ for (i=1; i<window; i++)
+ {
+ if (wstart-i < 0) break;
+ if (BN_is_bit_set(p,wstart-i))
+ {
+ wvalue<<=(i-wend);
+ wvalue|=1;
+ wend=i;
+ }
+ }
+
+ /* wend is the size of the current window */
+ j=wend+1;
+ /* add the 'bytes above' */
+ if (!start)
+ for (i=0; i<j; i++)
+ {
+ if (!BN_mod_mul_reciprocal(r,r,r,&recp,ctx))
+ goto err;
+ }
+
+ /* wvalue will be an odd number < 2^window */
+ if (!BN_mod_mul_reciprocal(r,r,&(val[wvalue>>1]),&recp,ctx))
+ goto err;
+
+ /* move the 'window' down further */
+ wstart-=wend+1;
+ wvalue=0;
+ start=0;
+ if (wstart < 0) break;
+ }
+ ret=1;
+err:
+ BN_CTX_end(ctx);
+ for (i=0; i<ts; i++)
+ BN_clear_free(&(val[i]));
+ BN_RECP_CTX_free(&recp);
+ return(ret);
+ }
+#else
+
+/* The old fallback, simple version :-) */
+int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx)
+ {
+ int i,j,bits,ret=0,wstart,wend,window,wvalue,ts=0;
+ int start=1;
+ BIGNUM *d;
+ BIGNUM val[TABLE_SIZE];
+
+ bits=BN_num_bits(p);
+
+ if (bits == 0)
+ {
+ BN_one(r);
+ return(1);
+ }
+
+ BN_CTX_start(ctx);
+ if ((d = BN_CTX_get(ctx)) == NULL) goto err;
+
+ BN_init(&(val[0]));
+ ts=1;
+ if (!BN_mod(&(val[0]),a,m,ctx)) goto err; /* 1 */
+
+ window = BN_window_bits_for_exponent_size(bits);
+ if (window > 1)
+ {
+ if (!BN_mod_mul(d,&(val[0]),&(val[0]),m,ctx))
+ goto err; /* 2 */
+ j=1<<(window-1);
+ for (i=1; i<j; i++)
+ {
+ BN_init(&(val[i]));
+ if (!BN_mod_mul(&(val[i]),&(val[i-1]),d,m,ctx))
+ goto err;
+ }
+ ts=i;
+ }
+
+ start=1; /* This is used to avoid multiplication etc
+ * when there is only the value '1' in the
+ * buffer. */
+ wvalue=0; /* The 'value' of the window */
+ wstart=bits-1; /* The top bit of the window */
+ wend=0; /* The bottom bit of the window */
+
+ if (!BN_one(r)) goto err;
+
+ for (;;)
+ {
+ if (BN_is_bit_set(p,wstart) == 0)
+ {
+ if (!start)
+ if (!BN_mod_mul(r,r,r,m,ctx))
+ goto err;
+ if (wstart == 0) break;
+ wstart--;
+ continue;
+ }
+ /* We now have wstart on a 'set' bit, we now need to work out
+ * how bit a window to do. To do this we need to scan
+ * forward until the last set bit before the end of the
+ * window */
+ j=wstart;
+ wvalue=1;
+ wend=0;
+ for (i=1; i<window; i++)
+ {
+ if (wstart-i < 0) break;
+ if (BN_is_bit_set(p,wstart-i))
+ {
+ wvalue<<=(i-wend);
+ wvalue|=1;
+ wend=i;
+ }
+ }
+
+ /* wend is the size of the current window */
+ j=wend+1;
+ /* add the 'bytes above' */
+ if (!start)
+ for (i=0; i<j; i++)
+ {
+ if (!BN_mod_mul(r,r,r,m,ctx))
+ goto err;
+ }
+
+ /* wvalue will be an odd number < 2^window */
+ if (!BN_mod_mul(r,r,&(val[wvalue>>1]),m,ctx))
+ goto err;
+
+ /* move the 'window' down further */
+ wstart-=wend+1;
+ wvalue=0;
+ start=0;
+ if (wstart < 0) break;
+ }
+ ret=1;
+err:
+ BN_CTX_end(ctx);
+ for (i=0; i<ts; i++)
+ BN_clear_free(&(val[i]));
+ return(ret);
+ }
+#endif
diff --git a/package/ead/src/tinysrp/bn_lcl.h b/package/ead/src/tinysrp/bn_lcl.h
new file mode 100644
index 000000000..129ad658a
--- /dev/null
+++ b/package/ead/src/tinysrp/bn_lcl.h
@@ -0,0 +1,419 @@
+/* crypto/bn/bn_lcl.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC 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 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL 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. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_BN_LCL_H
+#define HEADER_BN_LCL_H
+
+#include <bn.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+ * BN_window_bits_for_exponent_size -- macro for sliding window mod_exp functions
+ *
+ *
+ * For window size 'w' (w >= 2) and a random 'b' bits exponent,
+ * the number of multiplications is a constant plus on average
+ *
+ * 2^(w-1) + (b-w)/(w+1);
+ *
+ * here 2^(w-1) is for precomputing the table (we actually need
+ * entries only for windows that have the lowest bit set), and
+ * (b-w)/(w+1) is an approximation for the expected number of
+ * w-bit windows, not counting the first one.
+ *
+ * Thus we should use
+ *
+ * w >= 6 if b > 671
+ * w = 5 if 671 > b > 239
+ * w = 4 if 239 > b > 79
+ * w = 3 if 79 > b > 23
+ * w <= 2 if 23 > b
+ *
+ * (with draws in between). Very small exponents are often selected
+ * with low Hamming weight, so we use w = 1 for b <= 23.
+ */
+#if 1
+#define BN_window_bits_for_exponent_size(b) \
+ ((b) > 671 ? 6 : \
+ (b) > 239 ? 5 : \
+ (b) > 79 ? 4 : \
+ (b) > 23 ? 3 : 1)
+#else
+/* Old SSLeay/OpenSSL table.
+ * Maximum window size was 5, so this table differs for b==1024;
+ * but it coincides for other interesting values (b==160, b==512).
+ */
+#define BN_window_bits_for_exponent_size(b) \
+ ((b) > 255 ? 5 : \
+ (b) > 127 ? 4 : \
+ (b) > 17 ? 3 : 1)
+#endif
+
+
+
+/* Pentium pro 16,16,16,32,64 */
+/* Alpha 16,16,16,16.64 */
+#define BN_MULL_SIZE_NORMAL (16) /* 32 */
+#define BN_MUL_RECURSIVE_SIZE_NORMAL (16) /* 32 less than */
+#define BN_SQR_RECURSIVE_SIZE_NORMAL (16) /* 32 */
+#define BN_MUL_LOW_RECURSIVE_SIZE_NORMAL (32) /* 32 */
+#define BN_MONT_CTX_SET_SIZE_WORD (64) /* 32 */
+
+#if !defined(NO_ASM) && !defined(NO_INLINE_ASM) && !defined(PEDANTIC)
+/*
+ * BN_UMULT_HIGH section.
+ *
+ * No, I'm not trying to overwhelm you when stating that the
+ * product of N-bit numbers is 2*N bits wide:-) No, I don't expect
+ * you to be impressed when I say that if the compiler doesn't
+ * support 2*N integer type, then you have to replace every N*N
+ * multiplication with 4 (N/2)*(N/2) accompanied by some shifts
+ * and additions which unavoidably results in severe performance
+ * penalties. Of course provided that the hardware is capable of
+ * producing 2*N result... That's when you normally start
+ * considering assembler implementation. However! It should be
+ * pointed out that some CPUs (most notably Alpha, PowerPC and
+ * upcoming IA-64 family:-) provide *separate* instruction
+ * calculating the upper half of the product placing the result
+ * into a general purpose register. Now *if* the compiler supports
+ * inline assembler, then it's not impossible to implement the
+ * "bignum" routines (and have the compiler optimize 'em)
+ * exhibiting "native" performance in C. That's what BN_UMULT_HIGH
+ * macro is about:-)
+ *
+ * <appro@fy.chalmers.se>
+ */
+# if defined(__alpha) && (defined(SIXTY_FOUR_BIT_LONG) || defined(SIXTY_FOUR_BIT))
+# if defined(__DECC)
+# include <c_asm.h>
+# define BN_UMULT_HIGH(a,b) (BN_ULONG)asm("umulh %a0,%a1,%v0",(a),(b))
+# elif defined(__GNUC__)
+# define BN_UMULT_HIGH(a,b) ({ \
+ register BN_ULONG ret; \
+ asm ("umulh %1,%2,%0" \
+ : "=r"(ret) \
+ : "r"(a), "r"(b)); \
+ ret; })
+# endif /* compiler */
+# elif defined(_ARCH_PPC) && defined(__64BIT__) && defined(SIXTY_FOUR_BIT_LONG)
+# if defined(__GNUC__)
+# define BN_UMULT_HIGH(a,b) ({ \
+ register BN_ULONG ret; \
+ asm ("mulhdu %0,%1,%2" \
+ : "=r"(ret) \
+ : "r"(a), "r"(b)); \
+ ret; })
+# endif /* compiler */
+# endif /* cpu */
+#endif /* NO_ASM */
+
+/*************************************************************
+ * Using the long long type
+ */
+#define Lw(t) (((BN_ULONG)(t))&BN_MASK2)
+#define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2)
+
+/* This is used for internal error checking and is not normally used */
+#ifdef BN_DEBUG
+# include <assert.h>
+# define bn_check_top(a) assert ((a)->top >= 0 && (a)->top <= (a)->dmax);
+#else
+# define bn_check_top(a)
+#endif
+
+/* This macro is to add extra stuff for development checking */
+#ifdef BN_DEBUG
+#define bn_set_max(r) ((r)->max=(r)->top,BN_set_flags((r),BN_FLG_STATIC_DATA))
+#else
+#define bn_set_max(r)
+#endif
+
+/* These macros are used to 'take' a section of a bignum for read only use */
+#define bn_set_low(r,a,n) \
+ { \
+ (r)->top=((a)->top > (n))?(n):(a)->top; \
+ (r)->d=(a)->d; \
+ (r)->neg=(a)->neg; \
+ (r)->flags|=BN_FLG_STATIC_DATA; \
+ bn_set_max(r); \
+ }
+
+#define bn_set_high(r,a,n) \
+ { \
+ if ((a)->top > (n)) \
+ { \
+ (r)->top=(a)->top-n; \
+ (r)->d= &((a)->d[n]); \
+ } \
+ else \
+ (r)->top=0; \
+ (r)->neg=(a)->neg; \
+ (r)->flags|=BN_FLG_STATIC_DATA; \
+ bn_set_max(r); \
+ }
+
+#ifdef BN_LLONG
+#define mul_add(r,a,w,c) { \
+ BN_ULLONG t; \
+ t=(BN_ULLONG)w * (a) + (r) + (c); \
+ (r)= Lw(t); \
+ (c)= Hw(t); \
+ }
+
+#define mul(r,a,w,c) { \
+ BN_ULLONG t; \
+ t=(BN_ULLONG)w * (a) + (c); \
+ (r)= Lw(t); \
+ (c)= Hw(t); \
+ }
+
+#define sqr(r0,r1,a) { \
+ BN_ULLONG t; \
+ t=(BN_ULLONG)(a)*(a); \
+ (r0)=Lw(t); \
+ (r1)=Hw(t); \
+ }
+
+#elif defined(BN_UMULT_HIGH)
+#define mul_add(r,a,w,c) { \
+ BN_ULONG high,low,ret,tmp=(a); \
+ ret = (r); \
+ high= BN_UMULT_HIGH(w,tmp); \
+ ret += (c); \
+ low = (w) * tmp; \
+ (c) = (ret<(c))?1:0; \
+ (c) += high; \
+ ret += low; \
+ (c) += (ret<low)?1:0; \
+ (r) = ret; \
+ }
+
+#define mul(r,a,w,c) { \
+ BN_ULONG high,low,ret,ta=(a); \
+ low = (w) * ta; \
+ high= BN_UMULT_HIGH(w,ta); \
+ ret = low + (c); \
+ (c) = high; \
+ (c) += (ret<low)?1:0; \
+ (r) = ret; \
+ }
+
+#define sqr(r0,r1,a) { \
+ BN_ULONG tmp=(a); \
+ (r0) = tmp * tmp; \
+ (r1) = BN_UMULT_HIGH(tmp,tmp); \
+ }
+
+#else
+/*************************************************************
+ * No long long type
+ */
+
+#define LBITS(a) ((a)&BN_MASK2l)
+#define HBITS(a) (((a)>>BN_BITS4)&BN_MASK2l)
+#define L2HBITS(a) ((BN_ULONG)((a)&BN_MASK2l)<<BN_BITS4)
+
+#define LLBITS(a) ((a)&BN_MASKl)
+#define LHBITS(a) (((a)>>BN_BITS2)&BN_MASKl)
+#define LL2HBITS(a) ((BN_ULLONG)((a)&BN_MASKl)<<BN_BITS2)
+
+#define mul64(l,h,bl,bh) \
+ { \
+ BN_ULONG m,m1,lt,ht; \
+ \
+ lt=l; \
+ ht=h; \
+ m =(bh)*(lt); \
+ lt=(bl)*(lt); \
+ m1=(bl)*(ht); \
+ ht =(bh)*(ht); \
+ m=(m+m1)&BN_MASK2; if (m < m1) ht+=L2HBITS(1L); \
+ ht+=HBITS(m); \
+ m1=L2HBITS(m); \
+ lt=(lt+m1)&BN_MASK2; if (lt < m1) ht++; \
+ (l)=lt; \
+ (h)=ht; \
+ }
+
+#define sqr64(lo,ho,in) \
+ { \
+ BN_ULONG l,h,m; \
+ \
+ h=(in); \
+ l=LBITS(h); \
+ h=HBITS(h); \
+ m =(l)*(h); \
+ l*=l; \
+ h*=h; \
+ h+=(m&BN_MASK2h1)>>(BN_BITS4-1); \
+ m =(m&BN_MASK2l)<<(BN_BITS4+1); \
+ l=(l+m)&BN_MASK2; if (l < m) h++; \
+ (lo)=l; \
+ (ho)=h; \
+ }
+
+#define mul_add(r,a,bl,bh,c) { \
+ BN_ULONG l,h; \
+ \
+ h= (a); \
+ l=LBITS(h); \
+ h=HBITS(h); \
+ mul64(l,h,(bl),(bh)); \
+ \
+ /* non-multiply part */ \
+ l=(l+(c))&BN_MASK2; if (l < (c)) h++; \
+ (c)=(r); \
+ l=(l+(c))&BN_MASK2; if (l < (c)) h++; \
+ (c)=h&BN_MASK2; \
+ (r)=l; \
+ }
+
+#define mul(r,a,bl,bh,c) { \
+ BN_ULONG l,h; \
+ \
+ h= (a); \
+ l=LBITS(h); \
+ h=HBITS(h); \
+ mul64(l,h,(bl),(bh)); \
+ \
+ /* non-multiply part */ \
+ l+=(c); if ((l&BN_MASK2) < (c)) h++; \
+ (c)=h&BN_MASK2; \
+ (r)=l&BN_MASK2; \
+ }
+#endif /* !BN_LLONG */
+
+void bn_mul_normal(BN_ULONG *r,BN_ULONG *a,int na,BN_ULONG *b,int nb);
+void bn_mul_comba8(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b);
+void bn_mul_comba4(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b);
+void bn_sqr_normal(BN_ULONG *r, BN_ULONG *a, int n, BN_ULONG *tmp);
+void bn_sqr_comba8(BN_ULONG *r,BN_ULONG *a);
+void bn_sqr_comba4(BN_ULONG *r,BN_ULONG *a);
+int bn_cmp_words(BN_ULONG *a,BN_ULONG *b,int n);
+void bn_mul_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,int n2,BN_ULONG *t);
+void bn_mul_part_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,
+ int tn, int n,BN_ULONG *t);
+void bn_sqr_recursive(BN_ULONG *r,BN_ULONG *a, int n2, BN_ULONG *t);
+void bn_mul_low_normal(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b, int n);
+void bn_mul_low_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,int n2,
+ BN_ULONG *t);
+void bn_mul_high(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,BN_ULONG *l,int n2,
+ BN_ULONG *t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/ead/src/tinysrp/bn_lib.c b/package/ead/src/tinysrp/bn_lib.c
new file mode 100644
index 000000000..cfa0d7566
--- /dev/null
+++ b/package/ead/src/tinysrp/bn_lib.c
@@ -0,0 +1,576 @@
+/* crypto/bn/bn_lib.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC 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 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef BN_DEBUG
+# undef NDEBUG /* avoid conflicting definitions */
+# define NDEBUG
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "bn_lcl.h"
+
+const char *BN_version="Big Number";
+
+/* For a 32 bit machine
+ * 2 - 4 == 128
+ * 3 - 8 == 256
+ * 4 - 16 == 512
+ * 5 - 32 == 1024
+ * 6 - 64 == 2048
+ * 7 - 128 == 4096
+ * 8 - 256 == 8192
+ */
+static int bn_limit_bits=0;
+static int bn_limit_num=8; /* (1<<bn_limit_bits) */
+static int bn_limit_bits_low=0;
+static int bn_limit_num_low=8; /* (1<<bn_limit_bits_low) */
+static int bn_limit_bits_high=0;
+static int bn_limit_num_high=8; /* (1<<bn_limit_bits_high) */
+static int bn_limit_bits_mont=0;
+static int bn_limit_num_mont=8; /* (1<<bn_limit_bits_mont) */
+
+int BN_num_bits_word(BN_ULONG l)
+ {
+ static const char bits[256]={
+ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,
+ 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ };
+
+#if defined(SIXTY_FOUR_BIT_LONG)
+ if (l & 0xffffffff00000000L)
+ {
+ if (l & 0xffff000000000000L)
+ {
+ if (l & 0xff00000000000000L)
+ {
+ return(bits[(int)(l>>56)]+56);
+ }
+ else return(bits[(int)(l>>48)]+48);
+ }
+ else
+ {
+ if (l & 0x0000ff0000000000L)
+ {
+ return(bits[(int)(l>>40)]+40);
+ }
+ else return(bits[(int)(l>>32)]+32);
+ }
+ }
+ else
+#else
+#ifdef SIXTY_FOUR_BIT
+ if (l & 0xffffffff00000000LL)
+ {
+ if (l & 0xffff000000000000LL)
+ {
+ if (l & 0xff00000000000000LL)
+ {
+ return(bits[(int)(l>>56)]+56);
+ }
+ else return(bits[(int)(l>>48)]+48);
+ }
+ else
+ {
+ if (l & 0x0000ff0000000000LL)
+ {
+ return(bits[(int)(l>>40)]+40);
+ }
+ else return(bits[(int)(l>>32)]+32);
+ }
+ }
+ else
+#endif
+#endif
+ {
+#if defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
+ if (l & 0xffff0000L)
+ {
+ if (l & 0xff000000L)
+ return(bits[(int)(l>>24L)]+24);
+ else return(bits[(int)(l>>16L)]+16);
+ }
+ else
+#endif
+ {
+#if defined(SIXTEEN_BIT) || defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
+ if (l & 0xff00L)
+ return(bits[(int)(l>>8)]+8);
+ else
+#endif
+ return(bits[(int)(l )] );
+ }
+ }
+ }
+
+int BN_num_bits(const BIGNUM *a)
+ {
+ BN_ULONG l;
+ int i;
+
+ bn_check_top(a);
+
+ if (a->top == 0) return(0);
+ l=a->d[a->top-1];
+ assert(l != 0);
+ i=(a->top-1)*BN_BITS2;
+ return(i+BN_num_bits_word(l));
+ }
+
+void BN_clear_free(BIGNUM *a)
+ {
+ int i;
+
+ if (a == NULL) return;
+ if (a->d != NULL)
+ {
+ memset(a->d,0,a->dmax*sizeof(a->d[0]));
+ if (!(BN_get_flags(a,BN_FLG_STATIC_DATA)))
+ free(a->d);
+ }
+ i=BN_get_flags(a,BN_FLG_MALLOCED);
+ memset(a,0,sizeof(BIGNUM));
+ if (i)
+ free(a);
+ }
+
+void BN_free(BIGNUM *a)
+ {
+ if (a == NULL) return;
+ if ((a->d != NULL) && !(BN_get_flags(a,BN_FLG_STATIC_DATA)))
+ free(a->d);
+ a->flags|=BN_FLG_FREE; /* REMOVE? */
+ if (a->flags & BN_FLG_MALLOCED)
+ free(a);
+ }
+
+void BN_init(BIGNUM *a)
+ {
+ memset(a,0,sizeof(BIGNUM));
+ }
+
+BIGNUM *BN_new(void)
+ {
+ BIGNUM *ret;
+
+ if ((ret=(BIGNUM *)malloc(sizeof(BIGNUM))) == NULL)
+ {
+ return(NULL);
+ }
+ ret->flags=BN_FLG_MALLOCED;
+ ret->top=0;
+ ret->neg=0;
+ ret->dmax=0;
+ ret->d=NULL;
+ return(ret);
+ }
+
+/* This is an internal function that should not be used in applications.
+ * It ensures that 'b' has enough room for a 'words' word number number.
+ * It is mostly used by the various BIGNUM routines. If there is an error,
+ * NULL is returned. If not, 'b' is returned. */
+
+BIGNUM *bn_expand2(BIGNUM *b, int words)
+ {
+ BN_ULONG *A,*a;
+ const BN_ULONG *B;
+ int i;
+
+ bn_check_top(b);
+
+ if (words > b->dmax)
+ {
+ bn_check_top(b);
+ if (BN_get_flags(b,BN_FLG_STATIC_DATA))
+ {
+ return(NULL);
+ }
+ a=A=(BN_ULONG *)malloc(sizeof(BN_ULONG)*(words+1));
+ if (A == NULL)
+ {
+ return(NULL);
+ }
+#if 1
+ B=b->d;
+ /* Check if the previous number needs to be copied */
+ if (B != NULL)
+ {
+#if 0
+ /* This lot is an unrolled loop to copy b->top
+ * BN_ULONGs from B to A
+ */
+/*
+ * I have nothing against unrolling but it's usually done for
+ * several reasons, namely:
+ * - minimize percentage of decision making code, i.e. branches;
+ * - avoid cache trashing;
+ * - make it possible to schedule loads earlier;
+ * Now let's examine the code below. The cornerstone of C is
+ * "programmer is always right" and that's what we love it for:-)
+ * For this very reason C compilers have to be paranoid when it
+ * comes to data aliasing and assume the worst. Yeah, but what
+ * does it mean in real life? This means that loop body below will
+ * be compiled to sequence of loads immediately followed by stores
+ * as compiler assumes the worst, something in A==B+1 style. As a
+ * result CPU pipeline is going to starve for incoming data. Secondly
+ * if A and B happen to share same cache line such code is going to
+ * cause severe cache trashing. Both factors have severe impact on
+ * performance of modern CPUs and this is the reason why this
+ * particular piece of code is #ifdefed away and replaced by more
+ * "friendly" version found in #else section below. This comment
+ * also applies to BN_copy function.
+ *
+ * <appro@fy.chalmers.se>
+ */
+ for (i=b->top&(~7); i>0; i-=8)
+ {
+ A[0]=B[0]; A[1]=B[1]; A[2]=B[2]; A[3]=B[3];
+ A[4]=B[4]; A[5]=B[5]; A[6]=B[6]; A[7]=B[7];
+ A+=8;
+ B+=8;
+ }
+ switch (b->top&7)
+ {
+ case 7:
+ A[6]=B[6];
+ case 6:
+ A[5]=B[5];
+ case 5:
+ A[4]=B[4];
+ case 4:
+ A[3]=B[3];
+ case 3:
+ A[2]=B[2];
+ case 2:
+ A[1]=B[1];
+ case 1:
+ A[0]=B[0];
+ case 0:
+ /* I need the 'case 0' entry for utrix cc.
+ * If the optimizer is turned on, it does the
+ * switch table by doing
+ * a=top&7
+ * a--;
+ * goto jump_table[a];
+ * If top is 0, this makes us jump to 0xffffffc
+ * which is rather bad :-(.
+ * eric 23-Apr-1998
+ */
+ ;
+ }
+#else
+ for (i=b->top>>2; i>0; i--,A+=4,B+=4)
+ {
+ /*
+ * The fact that the loop is unrolled
+ * 4-wise is a tribute to Intel. It's
+ * the one that doesn't have enough
+ * registers to accomodate more data.
+ * I'd unroll it 8-wise otherwise:-)
+ *
+ * <appro@fy.chalmers.se>
+ */
+ BN_ULONG a0,a1,a2,a3;
+ a0=B[0]; a1=B[1]; a2=B[2]; a3=B[3];
+ A[0]=a0; A[1]=a1; A[2]=a2; A[3]=a3;
+ }
+ switch (b->top&3)
+ {
+ case 3: A[2]=B[2];
+ case 2: A[1]=B[1];
+ case 1: A[0]=B[0];
+ case 0: ; /* ultrix cc workaround, see above */
+ }
+#endif
+ free(b->d);
+ }
+
+ b->d=a;
+ b->dmax=words;
+
+ /* Now need to zero any data between b->top and b->max */
+
+ A= &(b->d[b->top]);
+ for (i=(b->dmax - b->top)>>3; i>0; i--,A+=8)
+ {
+ A[0]=0; A[1]=0; A[2]=0; A[3]=0;
+ A[4]=0; A[5]=0; A[6]=0; A[7]=0;
+ }
+ for (i=(b->dmax - b->top)&7; i>0; i--,A++)
+ A[0]=0;
+#else
+ memset(A,0,sizeof(BN_ULONG)*(words+1));
+ memcpy(A,b->d,sizeof(b->d[0])*b->top);
+ b->d=a;
+ b->max=words;
+#endif
+
+/* memset(&(p[b->max]),0,((words+1)-b->max)*sizeof(BN_ULONG)); */
+/* { int i; for (i=b->max; i<words+1; i++) p[i]=i;} */
+
+ }
+ return(b);
+ }
+
+BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b)
+ {
+ int i;
+ BN_ULONG *A;
+ const BN_ULONG *B;
+
+ bn_check_top(b);
+
+ if (a == b) return(a);
+ if (bn_wexpand(a,b->top) == NULL) return(NULL);
+
+#if 1
+ A=a->d;
+ B=b->d;
+ for (i=b->top>>2; i>0; i--,A+=4,B+=4)
+ {
+ BN_ULONG a0,a1,a2,a3;
+ a0=B[0]; a1=B[1]; a2=B[2]; a3=B[3];
+ A[0]=a0; A[1]=a1; A[2]=a2; A[3]=a3;
+ }
+ switch (b->top&3)
+ {
+ case 3: A[2]=B[2];
+ case 2: A[1]=B[1];
+ case 1: A[0]=B[0];
+ case 0: ; /* ultrix cc workaround, see comments in bn_expand2 */
+ }
+#else
+ memcpy(a->d,b->d,sizeof(b->d[0])*b->top);
+#endif
+
+/* memset(&(a->d[b->top]),0,sizeof(a->d[0])*(a->max-b->top));*/
+ a->top=b->top;
+ if ((a->top == 0) && (a->d != NULL))
+ a->d[0]=0;
+ a->neg=b->neg;
+ return(a);
+ }
+
+int BN_set_word(BIGNUM *a, BN_ULONG w)
+ {
+ int i,n;
+ if (bn_expand(a,sizeof(BN_ULONG)*8) == NULL) return(0);
+
+ n=sizeof(BN_ULONG)/BN_BYTES;
+ a->neg=0;
+ a->top=0;
+ a->d[0]=(BN_ULONG)w&BN_MASK2;
+ if (a->d[0] != 0) a->top=1;
+ for (i=1; i<n; i++)
+ {
+ /* the following is done instead of
+ * w>>=BN_BITS2 so compilers don't complain
+ * on builds where sizeof(long) == BN_TYPES */
+#ifndef SIXTY_FOUR_BIT /* the data item > unsigned long */
+ w>>=BN_BITS4;
+ w>>=BN_BITS4;
+#else
+ w=0;
+#endif
+ a->d[i]=(BN_ULONG)w&BN_MASK2;
+ if (a->d[i] != 0) a->top=i+1;
+ }
+ return(1);
+ }
+
+/* ignore negative */
+BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)
+ {
+ unsigned int i,m;
+ unsigned int n;
+ BN_ULONG l;
+
+ if (ret == NULL) ret=BN_new();
+ if (ret == NULL) return(NULL);
+ l=0;
+ n=len;
+ if (n == 0)
+ {
+ ret->top=0;
+ return(ret);
+ }
+ if (bn_expand(ret,(int)(n+2)*8) == NULL)
+ return(NULL);
+ i=((n-1)/BN_BYTES)+1;
+ m=((n-1)%(BN_BYTES));
+ ret->top=i;
+ while (n-- > 0)
+ {
+ l=(l<<8L)| *(s++);
+ if (m-- == 0)
+ {
+ ret->d[--i]=l;
+ l=0;
+ m=BN_BYTES-1;
+ }
+ }
+ /* need to call this due to clear byte at top if avoiding
+ * having the top bit set (-ve number) */
+ bn_fix_top(ret);
+ return(ret);
+ }
+
+/* ignore negative */
+int BN_bn2bin(const BIGNUM *a, unsigned char *to)
+ {
+ int n,i;
+ BN_ULONG l;
+
+ n=i=BN_num_bytes(a);
+ while (i-- > 0)
+ {
+ l=a->d[i/BN_BYTES];
+ *(to++)=(unsigned char)(l>>(8*(i%BN_BYTES)))&0xff;
+ }
+ return(n);
+ }
+
+int BN_ucmp(const BIGNUM *a, const BIGNUM *b)
+ {
+ int i;
+ BN_ULONG t1,t2,*ap,*bp;
+
+ bn_check_top(a);
+ bn_check_top(b);
+
+ i=a->top-b->top;
+ if (i != 0) return(i);
+ ap=a->d;
+ bp=b->d;
+ for (i=a->top-1; i>=0; i--)
+ {
+ t1= ap[i];
+ t2= bp[i];
+ if (t1 != t2)
+ return(t1 > t2?1:-1);
+ }
+ return(0);
+ }
+
+int BN_cmp(const BIGNUM *a, const BIGNUM *b)
+ {
+ int i;
+ int gt,lt;
+ BN_ULONG t1,t2;
+
+ if ((a == NULL) || (b == NULL))
+ {
+ if (a != NULL)
+ return(-1);
+ else if (b != NULL)
+ return(1);
+ else
+ return(0);
+ }
+
+ bn_check_top(a);
+ bn_check_top(b);
+
+ if (a->neg != b->neg)
+ {
+ if (a->neg)
+ return(-1);
+ else return(1);
+ }
+ if (a->neg == 0)
+ { gt=1; lt= -1; }
+ else { gt= -1; lt=1; }
+
+ if (a->top > b->top) return(gt);
+ if (a->top < b->top) return(lt);
+ for (i=a->top-1; i>=0; i--)
+ {
+ t1=a->d[i];
+ t2=b->d[i];
+ if (t1 > t2) return(gt);
+ if (t1 < t2) return(lt);
+ }
+ return(0);
+ }
+
+int BN_is_bit_set(const BIGNUM *a, int n)
+ {
+ int i,j;
+
+ if (n < 0) return(0);
+ i=n/BN_BITS2;
+ j=n%BN_BITS2;
+ if (a->top <= i) return(0);
+ return((a->d[i]&(((BN_ULONG)1)<<j))?1:0);
+ }
diff --git a/package/ead/src/tinysrp/bn_mul.c b/package/ead/src/tinysrp/bn_mul.c
new file mode 100644
index 000000000..d2d9fc557
--- /dev/null
+++ b/package/ead/src/tinysrp/bn_mul.c
@@ -0,0 +1,176 @@
+/* crypto/bn/bn_mul.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC 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 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "bn_lcl.h"
+
+int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
+ {
+ int top,al,bl;
+ BIGNUM *rr;
+ int ret = 0;
+#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
+ int i;
+#endif
+#ifdef BN_RECURSION
+ BIGNUM *t;
+ int j,k;
+#endif
+
+#ifdef BN_COUNT
+ printf("BN_mul %d * %d\n",a->top,b->top);
+#endif
+
+ bn_check_top(a);
+ bn_check_top(b);
+ bn_check_top(r);
+
+ al=a->top;
+ bl=b->top;
+
+ if ((al == 0) || (bl == 0))
+ {
+ BN_zero(r);
+ return(1);
+ }
+ top=al+bl;
+
+ BN_CTX_start(ctx);
+ if ((r == a) || (r == b))
+ {
+ if ((rr = BN_CTX_get(ctx)) == NULL) goto err;
+ }
+ else
+ rr = r;
+ rr->neg=a->neg^b->neg;
+
+#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
+ i = al-bl;
+#endif
+#ifdef BN_MUL_COMBA
+ if (i == 0)
+ {
+# if 0
+ if (al == 4)
+ {
+ if (bn_wexpand(rr,8) == NULL) goto err;
+ rr->top=8;
+ bn_mul_comba4(rr->d,a->d,b->d);
+ goto end;
+ }
+# endif
+ if (al == 8)
+ {
+ if (bn_wexpand(rr,16) == NULL) goto err;
+ rr->top=16;
+ bn_mul_comba8(rr->d,a->d,b->d);
+ goto end;
+ }
+ }
+#endif /* BN_MUL_COMBA */
+ if (bn_wexpand(rr,top) == NULL) goto err;
+ rr->top=top;
+ bn_mul_normal(rr->d,a->d,al,b->d,bl);
+
+#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
+end:
+#endif
+ bn_fix_top(rr);
+ if (r != rr) BN_copy(r,rr);
+ ret=1;
+err:
+ BN_CTX_end(ctx);
+ return(ret);
+ }
+
+void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb)
+ {
+ BN_ULONG *rr;
+
+#ifdef BN_COUNT
+ printf(" bn_mul_normal %d * %d\n",na,nb);
+#endif
+
+ if (na < nb)
+ {
+ int itmp;
+ BN_ULONG *ltmp;
+
+ itmp=na; na=nb; nb=itmp;
+ ltmp=a; a=b; b=ltmp;
+
+ }
+ rr= &(r[na]);
+ rr[0]=bn_mul_words(r,a,na,b[0]);
+
+ for (;;)
+ {
+ if (--nb <= 0) return;
+ rr[1]=bn_mul_add_words(&(r[1]),a,na,b[1]);
+ if (--nb <= 0) return;
+ rr[2]=bn_mul_add_words(&(r[2]),a,na,b[2]);
+ if (--nb <= 0) return;
+ rr[3]=bn_mul_add_words(&(r[3]),a,na,b[3]);
+ if (--nb <= 0) return;
+ rr[4]=bn_mul_add_words(&(r[4]),a,na,b[4]);
+ rr+=4;
+ r+=4;
+ b+=4;
+ }
+ }
diff --git a/package/ead/src/tinysrp/bn_prime.h b/package/ead/src/tinysrp/bn_prime.h
new file mode 100644
index 000000000..b7cf9a9bf
--- /dev/null
+++ b/package/ead/src/tinysrp/bn_prime.h
@@ -0,0 +1,325 @@
+/* Auto generated by bn_prime.pl */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC 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 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef EIGHT_BIT
+#define NUMPRIMES 2048
+#else
+#define NUMPRIMES 54
+#endif
+static const unsigned int primes[NUMPRIMES]=
+ {
+ 2, 3, 5, 7, 11, 13, 17, 19,
+ 23, 29, 31, 37, 41, 43, 47, 53,
+ 59, 61, 67, 71, 73, 79, 83, 89,
+ 97, 101, 103, 107, 109, 113, 127, 131,
+ 137, 139, 149, 151, 157, 163, 167, 173,
+ 179, 181, 191, 193, 197, 199, 211, 223,
+ 227, 229, 233, 239, 241, 251,
+#ifndef EIGHT_BIT
+ 257, 263,
+ 269, 271, 277, 281, 283, 293, 307, 311,
+ 313, 317, 331, 337, 347, 349, 353, 359,
+ 367, 373, 379, 383, 389, 397, 401, 409,
+ 419, 421, 431, 433, 439, 443, 449, 457,
+ 461, 463, 467, 479, 487, 491, 499, 503,
+ 509, 521, 523, 541, 547, 557, 563, 569,
+ 571, 577, 587, 593, 599, 601, 607, 613,
+ 617, 619, 631, 641, 643, 647, 653, 659,
+ 661, 673, 677, 683, 691, 701, 709, 719,
+ 727, 733, 739, 743, 751, 757, 761, 769,
+ 773, 787, 797, 809, 811, 821, 823, 827,
+ 829, 839, 853, 857, 859, 863, 877, 881,
+ 883, 887, 907, 911, 919, 929, 937, 941,
+ 947, 953, 967, 971, 977, 983, 991, 997,
+ 1009,1013,1019,1021,1031,1033,1039,1049,
+ 1051,1061,1063,1069,1087,1091,1093,1097,
+ 1103,1109,1117,1123,1129,1151,1153,1163,
+ 1171,1181,1187,1193,1201,1213,1217,1223,
+ 1229,1231,1237,1249,1259,1277,1279,1283,
+ 1289,1291,1297,1301,1303,1307,1319,1321,
+ 1327,1361,1367,1373,1381,1399,1409,1423,
+ 1427,1429,1433,1439,1447,1451,1453,1459,
+ 1471,1481,1483,1487,1489,1493,1499,1511,
+ 1523,1531,1543,1549,1553,1559,1567,1571,
+ 1579,1583,1597,1601,1607,1609,1613,1619,
+ 1621,1627,1637,1657,1663,1667,1669,1693,
+ 1697,1699,1709,1721,1723,1733,1741,1747,
+ 1753,1759,1777,1783,1787,1789,1801,1811,
+ 1823,1831,1847,1861,1867,1871,1873,1877,
+ 1879,1889,1901,1907,1913,1931,1933,1949,
+ 1951,1973,1979,1987,1993,1997,1999,2003,
+ 2011,2017,2027,2029,2039,2053,2063,2069,
+ 2081,2083,2087,2089,2099,2111,2113,2129,
+ 2131,2137,2141,2143,2153,2161,2179,2203,
+ 2207,2213,2221,2237,2239,2243,2251,2267,
+ 2269,2273,2281,2287,2293,2297,2309,2311,
+ 2333,2339,2341,2347,2351,2357,2371,2377,
+ 2381,2383,2389,2393,2399,2411,2417,2423,
+ 2437,2441,2447,2459,2467,2473,2477,2503,
+ 2521,2531,2539,2543,2549,2551,2557,2579,
+ 2591,2593,2609,2617,2621,2633,2647,2657,
+ 2659,2663,2671,2677,2683,2687,2689,2693,
+ 2699,2707,2711,2713,2719,2729,2731,2741,
+ 2749,2753,2767,2777,2789,2791,2797,2801,
+ 2803,2819,2833,2837,2843,2851,2857,2861,
+ 2879,2887,2897,2903,2909,2917,2927,2939,
+ 2953,2957,2963,2969,2971,2999,3001,3011,
+ 3019,3023,3037,3041,3049,3061,3067,3079,
+ 3083,3089,3109,3119,3121,3137,3163,3167,
+ 3169,3181,3187,3191,3203,3209,3217,3221,
+ 3229,3251,3253,3257,3259,3271,3299,3301,
+ 3307,3313,3319,3323,3329,3331,3343,3347,
+ 3359,3361,3371,3373,3389,3391,3407,3413,
+ 3433,3449,3457,3461,3463,3467,3469,3491,
+ 3499,3511,3517,3527,3529,3533,3539,3541,
+ 3547,3557,3559,3571,3581,3583,3593,3607,
+ 3613,3617,3623,3631,3637,3643,3659,3671,
+ 3673,3677,3691,3697,3701,3709,3719,3727,
+ 3733,3739,3761,3767,3769,3779,3793,3797,
+ 3803,3821,3823,3833,3847,3851,3853,3863,
+ 3877,3881,3889,3907,3911,3917,3919,3923,
+ 3929,3931,3943,3947,3967,3989,4001,4003,
+ 4007,4013,4019,4021,4027,4049,4051,4057,
+ 4073,4079,4091,4093,4099,4111,4127,4129,
+ 4133,4139,4153,4157,4159,4177,4201,4211,
+ 4217,4219,4229,4231,4241,4243,4253,4259,
+ 4261,4271,4273,4283,4289,4297,4327,4337,
+ 4339,4349,4357,4363,4373,4391,4397,4409,
+ 4421,4423,4441,4447,4451,4457,4463,4481,
+ 4483,4493,4507,4513,4517,4519,4523,4547,
+ 4549,4561,4567,4583,4591,4597,4603,4621,
+ 4637,4639,4643,4649,4651,4657,4663,4673,
+ 4679,4691,4703,4721,4723,4729,4733,4751,
+ 4759,4783,4787,4789,4793,4799,4801,4813,
+ 4817,4831,4861,4871,4877,4889,4903,4909,
+ 4919,4931,4933,4937,4943,4951,4957,4967,
+ 4969,4973,4987,4993,4999,5003,5009,5011,
+ 5021,5023,5039,5051,5059,5077,5081,5087,
+ 5099,5101,5107,5113,5119,5147,5153,5167,
+ 5171,5179,5189,5197,5209,5227,5231,5233,
+ 5237,5261,5273,5279,5281,5297,5303,5309,
+ 5323,5333,5347,5351,5381,5387,5393,5399,
+ 5407,5413,5417,5419,5431,5437,5441,5443,
+ 5449,5471,5477,5479,5483,5501,5503,5507,
+ 5519,5521,5527,5531,5557,5563,5569,5573,
+ 5581,5591,5623,5639,5641,5647,5651,5653,
+ 5657,5659,5669,5683,5689,5693,5701,5711,
+ 5717,5737,5741,5743,5749,5779,5783,5791,
+ 5801,5807,5813,5821,5827,5839,5843,5849,
+ 5851,5857,5861,5867,5869,5879,5881,5897,
+ 5903,5923,5927,5939,5953,5981,5987,6007,
+ 6011,6029,6037,6043,6047,6053,6067,6073,
+ 6079,6089,6091,6101,6113,6121,6131,6133,
+ 6143,6151,6163,6173,6197,6199,6203,6211,
+ 6217,6221,6229,6247,6257,6263,6269,6271,
+ 6277,6287,6299,6301,6311,6317,6323,6329,
+ 6337,6343,6353,6359,6361,6367,6373,6379,
+ 6389,6397,6421,6427,6449,6451,6469,6473,
+ 6481,6491,6521,6529,6547,6551,6553,6563,
+ 6569,6571,6577,6581,6599,6607,6619,6637,
+ 6653,6659,6661,6673,6679,6689,6691,6701,
+ 6703,6709,6719,6733,6737,6761,6763,6779,
+ 6781,6791,6793,6803,6823,6827,6829,6833,
+ 6841,6857,6863,6869,6871,6883,6899,6907,
+ 6911,6917,6947,6949,6959,6961,6967,6971,
+ 6977,6983,6991,6997,7001,7013,7019,7027,
+ 7039,7043,7057,7069,7079,7103,7109,7121,
+ 7127,7129,7151,7159,7177,7187,7193,7207,
+ 7211,7213,7219,7229,7237,7243,7247,7253,
+ 7283,7297,7307,7309,7321,7331,7333,7349,
+ 7351,7369,7393,7411,7417,7433,7451,7457,
+ 7459,7477,7481,7487,7489,7499,7507,7517,
+ 7523,7529,7537,7541,7547,7549,7559,7561,
+ 7573,7577,7583,7589,7591,7603,7607,7621,
+ 7639,7643,7649,7669,7673,7681,7687,7691,
+ 7699,7703,7717,7723,7727,7741,7753,7757,
+ 7759,7789,7793,7817,7823,7829,7841,7853,
+ 7867,7873,7877,7879,7883,7901,7907,7919,
+ 7927,7933,7937,7949,7951,7963,7993,8009,
+ 8011,8017,8039,8053,8059,8069,8081,8087,
+ 8089,8093,8101,8111,8117,8123,8147,8161,
+ 8167,8171,8179,8191,8209,8219,8221,8231,
+ 8233,8237,8243,8263,8269,8273,8287,8291,
+ 8293,8297,8311,8317,8329,8353,8363,8369,
+ 8377,8387,8389,8419,8423,8429,8431,8443,
+ 8447,8461,8467,8501,8513,8521,8527,8537,
+ 8539,8543,8563,8573,8581,8597,8599,8609,
+ 8623,8627,8629,8641,8647,8663,8669,8677,
+ 8681,8689,8693,8699,8707,8713,8719,8731,
+ 8737,8741,8747,8753,8761,8779,8783,8803,
+ 8807,8819,8821,8831,8837,8839,8849,8861,
+ 8863,8867,8887,8893,8923,8929,8933,8941,
+ 8951,8963,8969,8971,8999,9001,9007,9011,
+ 9013,9029,9041,9043,9049,9059,9067,9091,
+ 9103,9109,9127,9133,9137,9151,9157,9161,
+ 9173,9181,9187,9199,9203,9209,9221,9227,
+ 9239,9241,9257,9277,9281,9283,9293,9311,
+ 9319,9323,9337,9341,9343,9349,9371,9377,
+ 9391,9397,9403,9413,9419,9421,9431,9433,
+ 9437,9439,9461,9463,9467,9473,9479,9491,
+ 9497,9511,9521,9533,9539,9547,9551,9587,
+ 9601,9613,9619,9623,9629,9631,9643,9649,
+ 9661,9677,9679,9689,9697,9719,9721,9733,
+ 9739,9743,9749,9767,9769,9781,9787,9791,
+ 9803,9811,9817,9829,9833,9839,9851,9857,
+ 9859,9871,9883,9887,9901,9907,9923,9929,
+ 9931,9941,9949,9967,9973,10007,10009,10037,
+ 10039,10061,10067,10069,10079,10091,10093,10099,
+ 10103,10111,10133,10139,10141,10151,10159,10163,
+ 10169,10177,10181,10193,10211,10223,10243,10247,
+ 10253,10259,10267,10271,10273,10289,10301,10303,
+ 10313,10321,10331,10333,10337,10343,10357,10369,
+ 10391,10399,10427,10429,10433,10453,10457,10459,
+ 10463,10477,10487,10499,10501,10513,10529,10531,
+ 10559,10567,10589,10597,10601,10607,10613,10627,
+ 10631,10639,10651,10657,10663,10667,10687,10691,
+ 10709,10711,10723,10729,10733,10739,10753,10771,
+ 10781,10789,10799,10831,10837,10847,10853,10859,
+ 10861,10867,10883,10889,10891,10903,10909,10937,
+ 10939,10949,10957,10973,10979,10987,10993,11003,
+ 11027,11047,11057,11059,11069,11071,11083,11087,
+ 11093,11113,11117,11119,11131,11149,11159,11161,
+ 11171,11173,11177,11197,11213,11239,11243,11251,
+ 11257,11261,11273,11279,11287,11299,11311,11317,
+ 11321,11329,11351,11353,11369,11383,11393,11399,
+ 11411,11423,11437,11443,11447,11467,11471,11483,
+ 11489,11491,11497,11503,11519,11527,11549,11551,
+ 11579,11587,11593,11597,11617,11621,11633,11657,
+ 11677,11681,11689,11699,11701,11717,11719,11731,
+ 11743,11777,11779,11783,11789,11801,11807,11813,
+ 11821,11827,11831,11833,11839,11863,11867,11887,
+ 11897,11903,11909,11923,11927,11933,11939,11941,
+ 11953,11959,11969,11971,11981,11987,12007,12011,
+ 12037,12041,12043,12049,12071,12073,12097,12101,
+ 12107,12109,12113,12119,12143,12149,12157,12161,
+ 12163,12197,12203,12211,12227,12239,12241,12251,
+ 12253,12263,12269,12277,12281,12289,12301,12323,
+ 12329,12343,12347,12373,12377,12379,12391,12401,
+ 12409,12413,12421,12433,12437,12451,12457,12473,
+ 12479,12487,12491,12497,12503,12511,12517,12527,
+ 12539,12541,12547,12553,12569,12577,12583,12589,
+ 12601,12611,12613,12619,12637,12641,12647,12653,
+ 12659,12671,12689,12697,12703,12713,12721,12739,
+ 12743,12757,12763,12781,12791,12799,12809,12821,
+ 12823,12829,12841,12853,12889,12893,12899,12907,
+ 12911,12917,12919,12923,12941,12953,12959,12967,
+ 12973,12979,12983,13001,13003,13007,13009,13033,
+ 13037,13043,13049,13063,13093,13099,13103,13109,
+ 13121,13127,13147,13151,13159,13163,13171,13177,
+ 13183,13187,13217,13219,13229,13241,13249,13259,
+ 13267,13291,13297,13309,13313,13327,13331,13337,
+ 13339,13367,13381,13397,13399,13411,13417,13421,
+ 13441,13451,13457,13463,13469,13477,13487,13499,
+ 13513,13523,13537,13553,13567,13577,13591,13597,
+ 13613,13619,13627,13633,13649,13669,13679,13681,
+ 13687,13691,13693,13697,13709,13711,13721,13723,
+ 13729,13751,13757,13759,13763,13781,13789,13799,
+ 13807,13829,13831,13841,13859,13873,13877,13879,
+ 13883,13901,13903,13907,13913,13921,13931,13933,
+ 13963,13967,13997,13999,14009,14011,14029,14033,
+ 14051,14057,14071,14081,14083,14087,14107,14143,
+ 14149,14153,14159,14173,14177,14197,14207,14221,
+ 14243,14249,14251,14281,14293,14303,14321,14323,
+ 14327,14341,14347,14369,14387,14389,14401,14407,
+ 14411,14419,14423,14431,14437,14447,14449,14461,
+ 14479,14489,14503,14519,14533,14537,14543,14549,
+ 14551,14557,14561,14563,14591,14593,14621,14627,
+ 14629,14633,14639,14653,14657,14669,14683,14699,
+ 14713,14717,14723,14731,14737,14741,14747,14753,
+ 14759,14767,14771,14779,14783,14797,14813,14821,
+ 14827,14831,14843,14851,14867,14869,14879,14887,
+ 14891,14897,14923,14929,14939,14947,14951,14957,
+ 14969,14983,15013,15017,15031,15053,15061,15073,
+ 15077,15083,15091,15101,15107,15121,15131,15137,
+ 15139,15149,15161,15173,15187,15193,15199,15217,
+ 15227,15233,15241,15259,15263,15269,15271,15277,
+ 15287,15289,15299,15307,15313,15319,15329,15331,
+ 15349,15359,15361,15373,15377,15383,15391,15401,
+ 15413,15427,15439,15443,15451,15461,15467,15473,
+ 15493,15497,15511,15527,15541,15551,15559,15569,
+ 15581,15583,15601,15607,15619,15629,15641,15643,
+ 15647,15649,15661,15667,15671,15679,15683,15727,
+ 15731,15733,15737,15739,15749,15761,15767,15773,
+ 15787,15791,15797,15803,15809,15817,15823,15859,
+ 15877,15881,15887,15889,15901,15907,15913,15919,
+ 15923,15937,15959,15971,15973,15991,16001,16007,
+ 16033,16057,16061,16063,16067,16069,16073,16087,
+ 16091,16097,16103,16111,16127,16139,16141,16183,
+ 16187,16189,16193,16217,16223,16229,16231,16249,
+ 16253,16267,16273,16301,16319,16333,16339,16349,
+ 16361,16363,16369,16381,16411,16417,16421,16427,
+ 16433,16447,16451,16453,16477,16481,16487,16493,
+ 16519,16529,16547,16553,16561,16567,16573,16603,
+ 16607,16619,16631,16633,16649,16651,16657,16661,
+ 16673,16691,16693,16699,16703,16729,16741,16747,
+ 16759,16763,16787,16811,16823,16829,16831,16843,
+ 16871,16879,16883,16889,16901,16903,16921,16927,
+ 16931,16937,16943,16963,16979,16981,16987,16993,
+ 17011,17021,17027,17029,17033,17041,17047,17053,
+ 17077,17093,17099,17107,17117,17123,17137,17159,
+ 17167,17183,17189,17191,17203,17207,17209,17231,
+ 17239,17257,17291,17293,17299,17317,17321,17327,
+ 17333,17341,17351,17359,17377,17383,17387,17389,
+ 17393,17401,17417,17419,17431,17443,17449,17467,
+ 17471,17477,17483,17489,17491,17497,17509,17519,
+ 17539,17551,17569,17573,17579,17581,17597,17599,
+ 17609,17623,17627,17657,17659,17669,17681,17683,
+ 17707,17713,17729,17737,17747,17749,17761,17783,
+ 17789,17791,17807,17827,17837,17839,17851,17863,
+#endif
+ };
diff --git a/package/ead/src/tinysrp/bn_shift.c b/package/ead/src/tinysrp/bn_shift.c
new file mode 100644
index 000000000..f403720ec
--- /dev/null
+++ b/package/ead/src/tinysrp/bn_shift.c
@@ -0,0 +1,139 @@
+/* crypto/bn/bn_shift.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC 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 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "bn_lcl.h"
+
+int BN_lshift(BIGNUM *r, const BIGNUM *a, int n)
+ {
+ int i,nw,lb,rb;
+ BN_ULONG *t,*f;
+ BN_ULONG l;
+
+ r->neg=a->neg;
+ if (bn_wexpand(r,a->top+(n/BN_BITS2)+1) == NULL) return(0);
+ nw=n/BN_BITS2;
+ lb=n%BN_BITS2;
+ rb=BN_BITS2-lb;
+ f=a->d;
+ t=r->d;
+ t[a->top+nw]=0;
+ if (lb == 0)
+ for (i=a->top-1; i>=0; i--)
+ t[nw+i]=f[i];
+ else
+ for (i=a->top-1; i>=0; i--)
+ {
+ l=f[i];
+ t[nw+i+1]|=(l>>rb)&BN_MASK2;
+ t[nw+i]=(l<<lb)&BN_MASK2;
+ }
+ memset(t,0,nw*sizeof(t[0]));
+/* for (i=0; i<nw; i++)
+ t[i]=0;*/
+ r->top=a->top+nw+1;
+ bn_fix_top(r);
+ return(1);
+ }
+
+int BN_rshift(BIGNUM *r, BIGNUM *a, int n)
+ {
+ int i,j,nw,lb,rb;
+ BN_ULONG *t,*f;
+ BN_ULONG l,tmp;
+
+ nw=n/BN_BITS2;
+ rb=n%BN_BITS2;
+ lb=BN_BITS2-rb;
+ if (nw > a->top || a->top == 0)
+ {
+ BN_zero(r);
+ return(1);
+ }
+ if (r != a)
+ {
+ r->neg=a->neg;
+ if (bn_wexpand(r,a->top-nw+1) == NULL) return(0);
+ }
+
+ f= &(a->d[nw]);
+ t=r->d;
+ j=a->top-nw;
+ r->top=j;
+
+ if (rb == 0)
+ {
+ for (i=j+1; i > 0; i--)
+ *(t++)= *(f++);
+ }
+ else
+ {
+ l= *(f++);
+ for (i=1; i<j; i++)
+ {
+ tmp =(l>>rb)&BN_MASK2;
+ l= *(f++);
+ *(t++) =(tmp|(l<<lb))&BN_MASK2;
+ }
+ *(t++) =(l>>rb)&BN_MASK2;
+ }
+ *t=0;
+ bn_fix_top(r);
+ return(1);
+ }
diff --git a/package/ead/src/tinysrp/bn_sqr.c b/package/ead/src/tinysrp/bn_sqr.c
new file mode 100644
index 000000000..2d3db70e3
--- /dev/null
+++ b/package/ead/src/tinysrp/bn_sqr.c
@@ -0,0 +1,160 @@
+/* crypto/bn/bn_sqr.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC 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 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "bn_lcl.h"
+
+/* r must not be a */
+/* I've just gone over this and it is now %20 faster on x86 - eay - 27 Jun 96 */
+int BN_sqr(BIGNUM *r, BIGNUM *a, BN_CTX *ctx)
+ {
+ int max,al;
+ int ret = 0;
+ BIGNUM *tmp,*rr;
+
+#ifdef BN_COUNT
+printf("BN_sqr %d * %d\n",a->top,a->top);
+#endif
+ bn_check_top(a);
+
+ al=a->top;
+ if (al <= 0)
+ {
+ r->top=0;
+ return(1);
+ }
+
+ BN_CTX_start(ctx);
+ rr=(a != r) ? r : BN_CTX_get(ctx);
+ tmp=BN_CTX_get(ctx);
+ if (tmp == NULL) goto err;
+
+ max=(al+al);
+ if (bn_wexpand(rr,max+1) == NULL) goto err;
+
+ r->neg=0;
+ if (al == 4)
+ {
+#ifndef BN_SQR_COMBA
+ BN_ULONG t[8];
+ bn_sqr_normal(rr->d,a->d,4,t);
+#else
+ bn_sqr_comba4(rr->d,a->d);
+#endif
+ }
+ else if (al == 8)
+ {
+#ifndef BN_SQR_COMBA
+ BN_ULONG t[16];
+ bn_sqr_normal(rr->d,a->d,8,t);
+#else
+ bn_sqr_comba8(rr->d,a->d);
+#endif
+ }
+ else
+ {
+ if (bn_wexpand(tmp,max) == NULL) goto err;
+ bn_sqr_normal(rr->d,a->d,al,tmp->d);
+ }
+
+ rr->top=max;
+ if ((max > 0) && (rr->d[max-1] == 0)) rr->top--;
+ if (rr != r) BN_copy(r,rr);
+ ret = 1;
+ err:
+ BN_CTX_end(ctx);
+ return(ret);
+ }
+
+/* tmp must have 2*n words */
+void bn_sqr_normal(BN_ULONG *r, BN_ULONG *a, int n, BN_ULONG *tmp)
+ {
+ int i,j,max;
+ BN_ULONG *ap,*rp;
+
+ max=n*2;
+ ap=a;
+ rp=r;
+ rp[0]=rp[max-1]=0;
+ rp++;
+ j=n;
+
+ if (--j > 0)
+ {
+ ap++;
+ rp[j]=bn_mul_words(rp,ap,j,ap[-1]);
+ rp+=2;
+ }
+
+ for (i=n-2; i>0; i--)
+ {
+ j--;
+ ap++;
+ rp[j]=bn_mul_add_words(rp,ap,j,ap[-1]);
+ rp+=2;
+ }
+
+ bn_add_words(r,r,r,max);
+
+ /* There will not be a carry */
+
+ bn_sqr_words(tmp,a,n);
+
+ bn_add_words(r,r,tmp,max);
+ }
diff --git a/package/ead/src/tinysrp/bn_word.c b/package/ead/src/tinysrp/bn_word.c
new file mode 100644
index 000000000..7820e08a8
--- /dev/null
+++ b/package/ead/src/tinysrp/bn_word.c
@@ -0,0 +1,130 @@
+/* crypto/bn/bn_word.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC 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 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include "bn_lcl.h"
+
+int BN_add_word(BIGNUM *a, BN_ULONG w)
+ {
+ BN_ULONG l;
+ int i;
+
+ if (a->neg)
+ {
+ a->neg=0;
+ i=BN_sub_word(a,w);
+ if (!BN_is_zero(a))
+ a->neg=!(a->neg);
+ return(i);
+ }
+ w&=BN_MASK2;
+ if (bn_wexpand(a,a->top+1) == NULL) return(0);
+ i=0;
+ for (;;)
+ {
+ l=(a->d[i]+(BN_ULONG)w)&BN_MASK2;
+ a->d[i]=l;
+ if (w > l)
+ w=1;
+ else
+ break;
+ i++;
+ }
+ if (i >= a->top)
+ a->top++;
+ return(1);
+ }
+
+int BN_sub_word(BIGNUM *a, BN_ULONG w)
+ {
+ int i;
+
+ if (BN_is_zero(a) || a->neg)
+ {
+ a->neg=0;
+ i=BN_add_word(a,w);
+ a->neg=1;
+ return(i);
+ }
+
+ w&=BN_MASK2;
+ if ((a->top == 1) && (a->d[0] < w))
+ {
+ a->d[0]=w-a->d[0];
+ a->neg=1;
+ return(1);
+ }
+ i=0;
+ for (;;)
+ {
+ if (a->d[i] >= w)
+ {
+ a->d[i]-=w;
+ break;
+ }
+ else
+ {
+ a->d[i]=(a->d[i]-w)&BN_MASK2;
+ i++;
+ w=1;
+ }
+ }
+ if ((a->d[i] == 0) && (i == (a->top-1)))
+ a->top--;
+ return(1);
+ }
diff --git a/package/ead/src/tinysrp/clitest.c b/package/ead/src/tinysrp/clitest.c
new file mode 100644
index 000000000..faaa5dd90
--- /dev/null
+++ b/package/ead/src/tinysrp/clitest.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 1997-1999 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following conditions apply:
+ *
+ * 1. Any software that incorporates the SRP authentication technology
+ * must display the following acknowlegment:
+ * "This product uses the 'Secure Remote Password' cryptographic
+ * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
+ *
+ * 2. Any software that incorporates all or part of the SRP distribution
+ * itself must also display the following acknowledgment:
+ * "This product includes software developed by Tom Wu and Eugene
+ * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
+ *
+ * 3. Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice and list of conditions.
+ */
+
+#include <stdio.h>
+#include "t_defines.h"
+#include "t_pwd.h"
+#include "t_client.h"
+
+int
+main()
+{
+ int index;
+ struct t_client * tc;
+ struct t_preconf *tcp;
+ struct t_num n;
+ struct t_num g;
+ struct t_num s;
+ struct t_num B;
+ char username[MAXUSERLEN];
+ char hexbuf[MAXHEXPARAMLEN];
+ char buf1[MAXPARAMLEN], buf2[MAXPARAMLEN], buf3[MAXSALTLEN];
+ unsigned char cbuf[20];
+ struct t_num * A;
+ unsigned char * skey;
+ char pass[128];
+
+ printf("Enter username: ");
+ fgets(username, sizeof(username), stdin);
+ username[strlen(username) - 1] = '\0';
+ printf("Enter index (from server): ");
+ fgets(hexbuf, sizeof(hexbuf), stdin);
+ index = atoi(hexbuf);
+ tcp = t_getpreparam(index - 1);
+ printf("Enter salt (from server): ");
+ fgets(hexbuf, sizeof(hexbuf), stdin);
+ s.data = buf3;
+ s.len = t_fromb64(s.data, hexbuf);
+
+ tc = t_clientopen(username, &tcp->modulus, &tcp->generator, &s);
+ if (tc == 0) {
+ printf("invalid n, g\n");
+ exit(1);
+ }
+
+ A = t_clientgenexp(tc);
+ printf("A (to server): %s\n", t_tob64(hexbuf, A->data, A->len));
+
+ t_getpass(pass, 128, "Enter password:");
+ t_clientpasswd(tc, pass);
+
+ printf("Enter B (from server): ");
+ fgets(hexbuf, sizeof(hexbuf), stdin);
+ B.data = buf1;
+ B.len = t_fromb64(B.data, hexbuf);
+
+ skey = t_clientgetkey(tc, &B);
+ printf("Session key: %s\n", t_tohex(hexbuf, skey, 40));
+ printf("Response (to server): %s\n",
+ t_tohex(hexbuf, t_clientresponse(tc), RESPONSE_LEN));
+
+ printf("Enter server response: ");
+ fgets(hexbuf, sizeof(hexbuf), stdin);
+ hexbuf[strlen(hexbuf) - 1] = '\0';
+ t_fromhex(cbuf, hexbuf);
+
+ if (t_clientverify(tc, cbuf) == 0)
+ printf("Server authentication successful.\n");
+ else
+ printf("Server authentication failed.\n");
+
+ t_clientclose(tc);
+
+ return 0;
+}
diff --git a/package/ead/src/tinysrp/config.h.in b/package/ead/src/tinysrp/config.h.in
new file mode 100644
index 000000000..a4b50c714
--- /dev/null
+++ b/package/ead/src/tinysrp/config.h.in
@@ -0,0 +1,79 @@
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if type char is unsigned and you are not using gcc. */
+#ifndef __CHAR_UNSIGNED__
+#undef __CHAR_UNSIGNED__
+#endif
+
+/* Define to empty if the keyword does not work. */
+#undef const
+
+/* Define as __inline if that's what the C compiler calls it. */
+#undef inline
+
+/* Define as the return type of signal handlers (int or void). */
+#undef RETSIGTYPE
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define if your processor stores words with the most significant
+ byte first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+#undef SHA1HANDSOFF
+
+#undef POSIX_TERMIOS
+
+#undef POSIX_SIGTYPE
+
+#undef volatile
+
+/* The number of bytes in a int. */
+#undef SIZEOF_INT
+
+/* The number of bytes in a long. */
+#undef SIZEOF_LONG
+
+/* The number of bytes in a long long. */
+#undef SIZEOF_LONG_LONG
+
+/* The number of bytes in a short. */
+#undef SIZEOF_SHORT
+
+/* Define if you have the memcpy function. */
+#undef HAVE_MEMCPY
+
+/* Define if you have the sigaction function. */
+#undef HAVE_SIGACTION
+
+/* Define if you have the strchr function. */
+#undef HAVE_STRCHR
+
+/* Define if you have the <sgtty.h> header file. */
+#undef HAVE_SGTTY_H
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define if you have the <termio.h> header file. */
+#undef HAVE_TERMIO_H
+
+/* Define if you have the <termios.h> header file. */
+#undef HAVE_TERMIOS_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Name of package */
+#undef PACKAGE
+
+/* Version number of package */
+#undef VERSION
+
diff --git a/package/ead/src/tinysrp/configure b/package/ead/src/tinysrp/configure
new file mode 100755
index 000000000..6ee76bf43
--- /dev/null
+++ b/package/ead/src/tinysrp/configure
@@ -0,0 +1,2421 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=t_pwd.h
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:559: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
+echo "configure:612: checking whether build environment is sane" >&5
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftestfile`
+ fi
+ if test "$*" != "X $srcdir/configure conftestfile" \
+ && test "$*" != "X conftestfile $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ { echo "configure: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" 1>&2; exit 1; }
+ fi
+
+ test "$2" = conftestfile
+ )
+then
+ # Ok.
+ :
+else
+ { echo "configure: error: newly created file is older than distributed files!
+Check your system clock" 1>&2; exit 1; }
+fi
+rm -f conftest*
+echo "$ac_t""yes" 1>&6
+if test "$program_transform_name" = s,x,x,; then
+ program_transform_name=
+else
+ # Double any \ or $. echo might interpret backslashes.
+ cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+ program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+ rm -f conftestsed
+fi
+test "$program_prefix" != NONE &&
+ program_transform_name="s,^,${program_prefix},; $program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:669: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftestmake <<\EOF
+all:
+ @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ SET_MAKE=
+else
+ echo "$ac_t""no" 1>&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+
+PACKAGE=libtinysrp
+
+VERSION=0.7.5
+
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+ { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; }
+fi
+cat >> confdefs.h <<EOF
+#define PACKAGE "$PACKAGE"
+EOF
+
+cat >> confdefs.h <<EOF
+#define VERSION "$VERSION"
+EOF
+
+
+
+missing_dir=`cd $ac_aux_dir && pwd`
+echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
+echo "configure:716: checking for working aclocal" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (aclocal --version) < /dev/null > /dev/null 2>&1; then
+ ACLOCAL=aclocal
+ echo "$ac_t""found" 1>&6
+else
+ ACLOCAL="$missing_dir/missing aclocal"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
+echo "configure:729: checking for working autoconf" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (autoconf --version) < /dev/null > /dev/null 2>&1; then
+ AUTOCONF=autoconf
+ echo "$ac_t""found" 1>&6
+else
+ AUTOCONF="$missing_dir/missing autoconf"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working automake""... $ac_c" 1>&6
+echo "configure:742: checking for working automake" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (automake --version) < /dev/null > /dev/null 2>&1; then
+ AUTOMAKE=automake
+ echo "$ac_t""found" 1>&6
+else
+ AUTOMAKE="$missing_dir/missing automake"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
+echo "configure:755: checking for working autoheader" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (autoheader --version) < /dev/null > /dev/null 2>&1; then
+ AUTOHEADER=autoheader
+ echo "$ac_t""found" 1>&6
+else
+ AUTOHEADER="$missing_dir/missing autoheader"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
+echo "configure:768: checking for working makeinfo" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (makeinfo --version) < /dev/null > /dev/null 2>&1; then
+ MAKEINFO=makeinfo
+ echo "$ac_t""found" 1>&6
+else
+ MAKEINFO="$missing_dir/missing makeinfo"
+ echo "$ac_t""missing" 1>&6
+fi
+
+
+
+test "$CFLAGS" = "" && CFLAGS="-O2"
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:788: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:818: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:869: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:901: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 912 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:917: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:943: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:948: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:957: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:976: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:1019: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
+echo "configure:1072: checking whether ln -s works" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ rm -f conftestdata
+if ln -s X conftestdata 2>/dev/null
+then
+ rm -f conftestdata
+ ac_cv_prog_LN_S="ln -s"
+else
+ ac_cv_prog_LN_S=ln
+fi
+fi
+LN_S="$ac_cv_prog_LN_S"
+if test "$ac_cv_prog_LN_S" = "ln -s"; then
+ echo "$ac_t""yes" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1095: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test "$program_transform_name" = s,x,x,; then
+ program_transform_name=
+else
+ # Double any \ or $. echo might interpret backslashes.
+ cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+ program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+ rm -f conftestsed
+fi
+test "$program_prefix" != NONE &&
+ program_transform_name="s,^,${program_prefix},; $program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:1144: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 1159 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1165: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 1176 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1182: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 1193 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1199: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:1224: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1229 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1237: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1254 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1272 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1293 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:1304: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+for ac_hdr in sgtty.h sys/ioctl.h sys/time.h termio.h termios.h unistd.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1331: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1336 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1341: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:1370: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1375 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:1424: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+echo $ac_n "checking for inline""... $ac_c" 1>&6
+echo "configure:1445: checking for inline" >&5
+if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat > conftest.$ac_ext <<EOF
+#line 1452 "configure"
+#include "confdefs.h"
+
+int main() {
+} $ac_kw foo() {
+; return 0; }
+EOF
+if { (eval echo configure:1459: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_inline=$ac_kw; break
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+done
+
+fi
+
+echo "$ac_t""$ac_cv_c_inline" 1>&6
+case "$ac_cv_c_inline" in
+ inline | yes) ;;
+ no) cat >> confdefs.h <<\EOF
+#define inline
+EOF
+ ;;
+ *) cat >> confdefs.h <<EOF
+#define inline $ac_cv_c_inline
+EOF
+ ;;
+esac
+
+echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
+echo "configure:1485: checking whether time.h and sys/time.h may both be included" >&5
+if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1490 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+int main() {
+struct tm *tp;
+; return 0; }
+EOF
+if { (eval echo configure:1499: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_time=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_time=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_time" 1>&6
+if test $ac_cv_header_time = yes; then
+ cat >> confdefs.h <<\EOF
+#define TIME_WITH_SYS_TIME 1
+EOF
+
+fi
+
+echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
+echo "configure:1520: checking whether byte ordering is bigendian" >&5
+if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_c_bigendian=unknown
+# See if sys/param.h defines the BYTE_ORDER macro.
+cat > conftest.$ac_ext <<EOF
+#line 1527 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/param.h>
+int main() {
+
+#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
+ bogus endian macros
+#endif
+; return 0; }
+EOF
+if { (eval echo configure:1538: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+cat > conftest.$ac_ext <<EOF
+#line 1542 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/param.h>
+int main() {
+
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+; return 0; }
+EOF
+if { (eval echo configure:1553: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_bigendian=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_bigendian=no
+fi
+rm -f conftest*
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+if test $ac_cv_c_bigendian = unknown; then
+if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1573 "configure"
+#include "confdefs.h"
+main () {
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long l;
+ char c[sizeof (long)];
+ } u;
+ u.l = 1;
+ exit (u.c[sizeof (long) - 1] == 1);
+}
+EOF
+if { (eval echo configure:1586: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_c_bigendian=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_c_bigendian=yes
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_c_bigendian" 1>&6
+if test $ac_cv_c_bigendian = yes; then
+ cat >> confdefs.h <<\EOF
+#define WORDS_BIGENDIAN 1
+EOF
+
+fi
+
+echo $ac_n "checking size of short""... $ac_c" 1>&6
+echo "configure:1610: checking size of short" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1618 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+main()
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", sizeof(short));
+ exit(0);
+}
+EOF
+if { (eval echo configure:1629: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_sizeof_short=`cat conftestval`
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_sizeof_short=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_short" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_SHORT $ac_cv_sizeof_short
+EOF
+
+
+echo $ac_n "checking size of int""... $ac_c" 1>&6
+echo "configure:1649: checking size of int" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1657 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+main()
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", sizeof(int));
+ exit(0);
+}
+EOF
+if { (eval echo configure:1668: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_sizeof_int=`cat conftestval`
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_sizeof_int=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_int" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+EOF
+
+
+echo $ac_n "checking size of long""... $ac_c" 1>&6
+echo "configure:1688: checking size of long" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1696 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+main()
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", sizeof(long));
+ exit(0);
+}
+EOF
+if { (eval echo configure:1707: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_sizeof_long=`cat conftestval`
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_sizeof_long=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_long" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+EOF
+
+
+echo $ac_n "checking size of long long""... $ac_c" 1>&6
+echo "configure:1727: checking size of long long" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_long_long'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1735 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+main()
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", sizeof(long long));
+ exit(0);
+}
+EOF
+if { (eval echo configure:1746: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_sizeof_long_long=`cat conftestval`
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_sizeof_long_long=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_long_long" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long
+EOF
+
+
+cat > conftest.$ac_ext <<EOF
+#line 1766 "configure"
+#include "confdefs.h"
+
+int main() {
+volatile int i;
+; return 0; }
+EOF
+if { (eval echo configure:1773: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define volatile
+EOF
+
+fi
+rm -f conftest*
+echo $ac_n "checking whether char is unsigned""... $ac_c" 1>&6
+echo "configure:1786: checking whether char is unsigned" >&5
+if eval "test \"`echo '$''{'ac_cv_c_char_unsigned'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$GCC" = yes; then
+ # GCC predefines this symbol on systems where it applies.
+cat > conftest.$ac_ext <<EOF
+#line 1793 "configure"
+#include "confdefs.h"
+#ifdef __CHAR_UNSIGNED__
+ yes
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "yes" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_c_char_unsigned=yes
+else
+ rm -rf conftest*
+ ac_cv_c_char_unsigned=no
+fi
+rm -f conftest*
+
+else
+if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1815 "configure"
+#include "confdefs.h"
+/* volatile prevents gcc2 from optimizing the test away on sparcs. */
+#if !defined(__STDC__) || __STDC__ != 1
+#define volatile
+#endif
+main() {
+ volatile char c = 255; exit(c < 0);
+}
+EOF
+if { (eval echo configure:1825: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_c_char_unsigned=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_c_char_unsigned=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_c_char_unsigned" 1>&6
+if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then
+ cat >> confdefs.h <<\EOF
+#define __CHAR_UNSIGNED__ 1
+EOF
+
+fi
+
+
+if test "$ac_cv_c_char_unsigned" = "yes"; then
+ signed=-signed
+fi
+
+
+for ac_func in sigaction strchr memcpy
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1857: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1862 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1885: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+echo $ac_n "checking POSIX signal handlers""... $ac_c" 1>&6
+echo "configure:1911: checking POSIX signal handlers" >&5
+if eval "test \"`echo '$''{'ac_cv_has_posix_signals'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1916 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+#undef signal
+#endif
+extern void (*signal ()) ();
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1928: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_has_posix_signals=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_has_posix_signals=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_has_posix_signals" 1>&6
+if test $ac_cv_has_posix_signals = yes; then
+ cat >> confdefs.h <<\EOF
+#define RETSIGTYPE void
+EOF
+ cat >> confdefs.h <<\EOF
+#define POSIX_SIGTYPE 1
+EOF
+
+else
+ if test $ac_cv_type_signal = void; then
+ cat >> confdefs.h <<\EOF
+#define RETSIGTYPE void
+EOF
+
+ else
+ cat >> confdefs.h <<\EOF
+#define RETSIGTYPE int
+EOF
+
+ fi
+fi
+ac_safe=`echo "termios.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for termios.h""... $ac_c" 1>&6
+echo "configure:1964: checking for termios.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1969 "configure"
+#include "confdefs.h"
+#include <termios.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1974: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ echo $ac_n "checking for cfsetispeed""... $ac_c" 1>&6
+echo "configure:1991: checking for cfsetispeed" >&5
+if eval "test \"`echo '$''{'ac_cv_func_cfsetispeed'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1996 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char cfsetispeed(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char cfsetispeed();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_cfsetispeed) || defined (__stub___cfsetispeed)
+choke me
+#else
+cfsetispeed();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2019: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_cfsetispeed=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_cfsetispeed=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'cfsetispeed`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define POSIX_TERMIOS 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+
+
+cat >> confdefs.h <<\EOF
+#define SHA1HANDSOFF 1
+EOF
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@PACKAGE@%$PACKAGE%g
+s%@VERSION@%$VERSION%g
+s%@ACLOCAL@%$ACLOCAL%g
+s%@AUTOCONF@%$AUTOCONF%g
+s%@AUTOMAKE@%$AUTOMAKE%g
+s%@AUTOHEADER@%$AUTOHEADER%g
+s%@MAKEINFO@%$MAKEINFO%g
+s%@SET_MAKE@%$SET_MAKE%g
+s%@CC@%$CC%g
+s%@LN_S@%$LN_S%g
+s%@RANLIB@%$RANLIB%g
+s%@CPP@%$CPP%g
+s%@signed@%$signed%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+ CONFIG_HEADERS="config.h"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h. And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+ ac_lines=`grep -c . conftest.vals`
+ # grep -c gives empty output for an empty file on some AIX systems.
+ if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+ # Write a limited-size here document to conftest.frag.
+ echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+ echo 'CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+ rm -f conftest.vals
+ mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ fi
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/package/ead/src/tinysrp/configure.in b/package/ead/src/tinysrp/configure.in
new file mode 100644
index 000000000..627d15a8c
--- /dev/null
+++ b/package/ead/src/tinysrp/configure.in
@@ -0,0 +1,52 @@
+dnl Process this file with autoconf to produce a configure script.
+
+AC_INIT(t_pwd.h)
+AM_CONFIG_HEADER(config.h)
+AM_INIT_AUTOMAKE(libtinysrp, 0.7.5)
+
+test "$CFLAGS" = "" && CFLAGS="-O2"
+
+dnl Checks for programs.
+
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_RANLIB
+AC_ARG_PROGRAM
+
+dnl Checks for header files.
+
+AC_HEADER_STDC
+AC_CHECK_HEADERS(sgtty.h sys/ioctl.h sys/time.h termio.h termios.h unistd.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+
+AC_C_CONST
+AC_C_INLINE
+AC_HEADER_TIME
+AC_C_BIGENDIAN
+AC_CHECK_SIZEOF(short)
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(long)
+AC_CHECK_SIZEOF(long long)
+AC_TRY_COMPILE(, [volatile int i;], , AC_DEFINE(volatile, ))
+AC_C_CHAR_UNSIGNED
+
+AC_SUBST(signed)dnl
+if test "$ac_cv_c_char_unsigned" = "yes"; then
+ signed=-signed
+fi
+
+dnl Checks for library functions.
+
+AC_CHECK_FUNCS(sigaction strchr memcpy)
+TYPE_SIGNAL
+AC_HEADER_CHECK(termios.h,AC_FUNC_CHECK(cfsetispeed,AC_DEFINE(POSIX_TERMIOS)))
+
+dnl User options
+
+dnl Some defines for now.
+
+AC_DEFINE(SHA1HANDSOFF)
+
+AC_OUTPUT(Makefile)
diff --git a/package/ead/src/tinysrp/install-sh b/package/ead/src/tinysrp/install-sh
new file mode 100755
index 000000000..e8436696c
--- /dev/null
+++ b/package/ead/src/tinysrp/install-sh
@@ -0,0 +1,250 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/package/ead/src/tinysrp/missing b/package/ead/src/tinysrp/missing
new file mode 100755
index 000000000..a6abd0698
--- /dev/null
+++ b/package/ead/src/tinysrp/missing
@@ -0,0 +1,134 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# 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.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+case "$1" in
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ automake touch all \`Makefile.in' files
+ bison touch file \`y.tab.c'
+ makeinfo touch the output file
+ yacc touch file \`y.tab.c'"
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing - GNU libit 0.0"
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+ aclocal)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acinclude.m4' or \`configure.in'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`configure.in'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acconfig.h' or \`configure.in'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ touch config.h.in
+ ;;
+
+ automake)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print \
+ | sed 's/^\(.*\).am$/touch \1.in/' \
+ | sh
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ touch y.tab.c
+ ;;
+
+ makeinfo)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+ fi
+ touch $file
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+ system. You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequirements for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/package/ead/src/tinysrp/mkinstalldirs b/package/ead/src/tinysrp/mkinstalldirs
new file mode 100755
index 000000000..3bc183603
--- /dev/null
+++ b/package/ead/src/tinysrp/mkinstalldirs
@@ -0,0 +1,39 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+
+errstatus=0
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp" 1>&2
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/package/ead/src/tinysrp/srvtest.c b/package/ead/src/tinysrp/srvtest.c
new file mode 100644
index 000000000..e09d501ad
--- /dev/null
+++ b/package/ead/src/tinysrp/srvtest.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 1997-1999 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following conditions apply:
+ *
+ * 1. Any software that incorporates the SRP authentication technology
+ * must display the following acknowlegment:
+ * "This product uses the 'Secure Remote Password' cryptographic
+ * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
+ *
+ * 2. Any software that incorporates all or part of the SRP distribution
+ * itself must also display the following acknowledgment:
+ * "This product includes software developed by Tom Wu and Eugene
+ * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
+ *
+ * 3. Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice and list of conditions.
+ */
+
+#include <stdio.h>
+#include "t_defines.h"
+#include "t_pwd.h"
+#include "t_server.h"
+
+int
+main(argc, argv)
+ int argc;
+ char * argv[];
+{
+ struct t_server * ts;
+ struct t_pw * tpw;
+ struct t_conf * tcnf;
+ struct t_num * B;
+ char username[MAXUSERLEN];
+ char hexbuf[MAXHEXPARAMLEN];
+ char buf[MAXPARAMLEN];
+ struct t_num A;
+ unsigned char * skey;
+ unsigned char cbuf[20];
+ FILE * fp;
+ FILE * fp2;
+ char confname[256];
+
+ printf("Enter username: ");
+ fgets(username, sizeof(username), stdin);
+ username[strlen(username) - 1] = '\0';
+ ts = t_serveropen(username);
+
+ if(ts == NULL) {
+ fprintf(stderr, "User %s not found\n", username);
+ exit(1);
+ }
+
+#if 0
+ printf("n: %s\n", t_tob64(hexbuf, ts->n.data, ts->n.len));
+ printf("g: %s\n", t_tob64(hexbuf, ts->g.data, ts->g.len));
+#endif
+ printf("index (to client): %d\n", ts->index);
+ printf("salt (to client): %s\n", t_tob64(hexbuf, ts->s.data, ts->s.len));
+
+ B = t_servergenexp(ts);
+ printf("Enter A (from client): ");
+ fgets(hexbuf, sizeof(hexbuf), stdin);
+ A.data = buf;
+ A.len = t_fromb64(A.data, hexbuf);
+
+ printf("B (to client): %s\n", t_tob64(hexbuf, B->data, B->len));
+
+ skey = t_servergetkey(ts, &A);
+ printf("Session key: %s\n", t_tohex(hexbuf, skey, 40));
+
+ /* printf("[Expected response: %s]\n", t_tohex(hexbuf, cbuf, 16)); */
+
+ printf("Enter response (from client): ");
+ fgets(hexbuf, sizeof(hexbuf), stdin);
+ hexbuf[strlen(hexbuf) - 1] = '\0';
+ t_fromhex(cbuf, hexbuf);
+
+ if(t_serververify(ts, cbuf) == 0) {
+ printf("Authentication successful.\n");
+ printf("Response (to client): %s\n",
+ t_tohex(hexbuf, t_serverresponse(ts), RESPONSE_LEN));
+ } else
+ printf("Authentication failed.\n");
+
+ t_serverclose(ts);
+
+ return 0;
+}
diff --git a/package/ead/src/tinysrp/stamp-h.in b/package/ead/src/tinysrp/stamp-h.in
new file mode 100644
index 000000000..9788f7023
--- /dev/null
+++ b/package/ead/src/tinysrp/stamp-h.in
@@ -0,0 +1 @@
+timestamp
diff --git a/package/ead/src/tinysrp/t_client.c b/package/ead/src/tinysrp/t_client.c
new file mode 100644
index 000000000..ebdd203af
--- /dev/null
+++ b/package/ead/src/tinysrp/t_client.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 1997-1999 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following conditions apply:
+ *
+ * 1. Any software that incorporates the SRP authentication technology
+ * must display the following acknowlegment:
+ * "This product uses the 'Secure Remote Password' cryptographic
+ * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
+ *
+ * 2. Any software that incorporates all or part of the SRP distribution
+ * itself must also display the following acknowledgment:
+ * "This product includes software developed by Tom Wu and Eugene
+ * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
+ *
+ * 3. Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice and list of conditions.
+ */
+
+#include <stdio.h>
+#include "t_defines.h"
+#include "t_pwd.h"
+#include "t_client.h"
+#include "t_sha.h"
+
+_TYPE( struct t_client * )
+t_clientopen(u, n, g, s)
+ const char * u;
+ struct t_num * n;
+ struct t_num * g;
+ struct t_num * s;
+{
+ struct t_client * tc;
+ unsigned char buf1[SHA_DIGESTSIZE], buf2[SHA_DIGESTSIZE];
+ SHA1_CTX ctxt;
+ int i, validated;
+ struct t_preconf * tpc;
+
+ BigInteger nn, gg, n12, r;
+
+ validated = 0;
+ if(n->len < MIN_MOD_BYTES)
+ return 0;
+ for(i = 0; i < t_getprecount(); ++i) {
+ tpc = t_getpreparam(i);
+ if(tpc->modulus.len == n->len && tpc->generator.len == g->len &&
+ memcmp(tpc->modulus.data, n->data, n->len) == 0 &&
+ memcmp(tpc->generator.data, g->data, g->len) == 0) {
+ validated = 1; /* Match found, done */
+ break;
+ }
+ }
+
+ if(validated == 0)
+ return 0;
+
+ if((tc = malloc(sizeof(struct t_client))) == 0)
+ return 0;
+
+ strncpy(tc->username, u, MAXUSERLEN);
+
+ SHA1Init(&tc->hash);
+
+ tc->n.len = n->len;
+ tc->n.data = tc->nbuf;
+ memcpy(tc->n.data, n->data, tc->n.len);
+
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, tc->n.data, tc->n.len);
+ SHA1Final(buf1, &ctxt);
+
+ tc->g.len = g->len;
+ tc->g.data = tc->gbuf;
+ memcpy(tc->g.data, g->data, tc->g.len);
+
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, tc->g.data, tc->g.len);
+ SHA1Final(buf2, &ctxt);
+
+ for(i = 0; i < sizeof(buf1); ++i)
+ buf1[i] ^= buf2[i];
+
+ SHA1Update(&tc->hash, buf1, sizeof(buf1));
+
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, tc->username, strlen(tc->username));
+ SHA1Final(buf1, &ctxt);
+
+ SHA1Update(&tc->hash, buf1, sizeof(buf1));
+
+ tc->s.len = s->len;
+ tc->s.data = tc->sbuf;
+ memcpy(tc->s.data, s->data, tc->s.len);
+
+ SHA1Update(&tc->hash, tc->s.data, tc->s.len);
+
+ tc->a.data = tc->abuf;
+ tc->A.data = tc->Abuf;
+ tc->p.data = tc->pbuf;
+ tc->v.data = tc->vbuf;
+
+ SHA1Init(&tc->ckhash);
+
+ return tc;
+}
+
+_TYPE( struct t_num * )
+t_clientgenexp(tc)
+ struct t_client * tc;
+{
+ BigInteger a, A, n, g;
+
+ if(tc->n.len < ALEN)
+ tc->a.len = tc->n.len;
+ else
+ tc->a.len = ALEN;
+
+ t_random(tc->a.data, tc->a.len);
+ a = BigIntegerFromBytes(tc->a.data, tc->a.len);
+ n = BigIntegerFromBytes(tc->n.data, tc->n.len);
+ g = BigIntegerFromBytes(tc->g.data, tc->g.len);
+ A = BigIntegerFromInt(0);
+ BigIntegerModExp(A, g, a, n);
+ tc->A.len = BigIntegerToBytes(A, tc->A.data);
+
+ BigIntegerFree(A);
+ BigIntegerFree(a);
+ BigIntegerFree(g);
+ BigIntegerFree(n);
+
+ SHA1Update(&tc->hash, tc->A.data, tc->A.len);
+ SHA1Update(&tc->ckhash, tc->A.data, tc->A.len);
+
+ return &tc->A;
+}
+
+_TYPE( void )
+t_clientpasswd(tc, password)
+ struct t_client * tc;
+ char * password;
+{
+ BigInteger n, g, p, v;
+ SHA1_CTX ctxt;
+ unsigned char dig[SHA_DIGESTSIZE];
+
+ n = BigIntegerFromBytes(tc->n.data, tc->n.len);
+ g = BigIntegerFromBytes(tc->g.data, tc->g.len);
+
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, tc->username, strlen(tc->username));
+ SHA1Update(&ctxt, ":", 1);
+ SHA1Update(&ctxt, password, strlen(password));
+ SHA1Final(dig, &ctxt);
+
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, tc->s.data, tc->s.len);
+ SHA1Update(&ctxt, dig, sizeof(dig));
+ SHA1Final(dig, &ctxt);
+
+ p = BigIntegerFromBytes(dig, sizeof(dig));
+
+ v = BigIntegerFromInt(0);
+ BigIntegerModExp(v, g, p, n);
+
+ tc->p.len = BigIntegerToBytes(p, tc->p.data);
+ BigIntegerFree(p);
+
+ tc->v.len = BigIntegerToBytes(v, tc->v.data);
+ BigIntegerFree(v);
+}
+
+_TYPE( unsigned char * )
+t_clientgetkey(tc, serverval)
+ struct t_client * tc;
+ struct t_num * serverval;
+{
+ BigInteger n, B, v, p, a, sum, S;
+ unsigned char sbuf[MAXPARAMLEN];
+ unsigned char dig[SHA_DIGESTSIZE];
+ unsigned slen;
+ unsigned int u;
+ SHA1_CTX ctxt;
+
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, serverval->data, serverval->len);
+ SHA1Final(dig, &ctxt);
+ u = (dig[0] << 24) | (dig[1] << 16) | (dig[2] << 8) | dig[3];
+ if(u == 0)
+ return NULL;
+
+ SHA1Update(&tc->hash, serverval->data, serverval->len);
+
+ B = BigIntegerFromBytes(serverval->data, serverval->len);
+ n = BigIntegerFromBytes(tc->n.data, tc->n.len);
+
+ if(BigIntegerCmp(B, n) >= 0 || BigIntegerCmpInt(B, 0) == 0) {
+ BigIntegerFree(B);
+ BigIntegerFree(n);
+ return NULL;
+ }
+ v = BigIntegerFromBytes(tc->v.data, tc->v.len);
+ if(BigIntegerCmp(B, v) < 0)
+ BigIntegerAdd(B, B, n);
+ BigIntegerSub(B, B, v);
+ BigIntegerFree(v);
+
+ a = BigIntegerFromBytes(tc->a.data, tc->a.len);
+ p = BigIntegerFromBytes(tc->p.data, tc->p.len);
+
+ sum = BigIntegerFromInt(0);
+ BigIntegerMulInt(sum, p, u);
+ BigIntegerAdd(sum, sum, a);
+
+ BigIntegerFree(p);
+ BigIntegerFree(a);
+
+ S = BigIntegerFromInt(0);
+ BigIntegerModExp(S, B, sum, n);
+ slen = BigIntegerToBytes(S, sbuf);
+
+ BigIntegerFree(S);
+ BigIntegerFree(sum);
+ BigIntegerFree(B);
+ BigIntegerFree(n);
+
+ t_sessionkey(tc->session_key, sbuf, slen);
+ memset(sbuf, 0, slen);
+
+ SHA1Update(&tc->hash, tc->session_key, sizeof(tc->session_key));
+
+ SHA1Final(tc->session_response, &tc->hash);
+ SHA1Update(&tc->ckhash, tc->session_response, sizeof(tc->session_response));
+ SHA1Update(&tc->ckhash, tc->session_key, sizeof(tc->session_key));
+
+ return tc->session_key;
+}
+
+_TYPE( int )
+t_clientverify(tc, resp)
+ struct t_client * tc;
+ unsigned char * resp;
+{
+ unsigned char expected[SHA_DIGESTSIZE];
+
+ SHA1Final(expected, &tc->ckhash);
+ return memcmp(expected, resp, sizeof(expected));
+}
+
+_TYPE( unsigned char * )
+t_clientresponse(tc)
+ struct t_client * tc;
+{
+ return tc->session_response;
+}
+
+_TYPE( void )
+t_clientclose(tc)
+ struct t_client * tc;
+{
+ memset(tc->abuf, 0, sizeof(tc->abuf));
+ memset(tc->pbuf, 0, sizeof(tc->pbuf));
+ memset(tc->vbuf, 0, sizeof(tc->vbuf));
+ memset(tc->session_key, 0, sizeof(tc->session_key));
+ free(tc);
+}
diff --git a/package/ead/src/tinysrp/t_client.h b/package/ead/src/tinysrp/t_client.h
new file mode 100644
index 000000000..42922aff1
--- /dev/null
+++ b/package/ead/src/tinysrp/t_client.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 1997-1999 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following conditions apply:
+ *
+ * 1. Any software that incorporates the SRP authentication technology
+ * must display the following acknowlegment:
+ * "This product uses the 'Secure Remote Password' cryptographic
+ * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
+ *
+ * 2. Any software that incorporates all or part of the SRP distribution
+ * itself must also display the following acknowledgment:
+ * "This product includes software developed by Tom Wu and Eugene
+ * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
+ *
+ * 3. Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice and list of conditions.
+ */
+
+#ifndef T_CLIENT_H
+#define T_CLIENT_H
+
+#include "t_sha.h"
+
+#if !defined(P)
+#ifdef __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+#endif
+
+/* For building dynamic link libraries under windows, windows NT
+ * using MSVC1.5 or MSVC2.0
+ */
+
+#ifndef _DLLDECL
+#define _DLLDECL
+
+#ifdef MSVC15 /* MSVC1.5 support for 16 bit apps */
+#define _MSVC15EXPORT _export
+#define _MSVC20EXPORT
+#define _DLLAPI _export _pascal
+#define _TYPE(a) a _MSVC15EXPORT
+#define DLLEXPORT 1
+
+#elif MSVC20
+#define _MSVC15EXPORT
+#define _MSVC20EXPORT _declspec(dllexport)
+#define _DLLAPI
+#define _TYPE(a) _MSVC20EXPORT a
+#define DLLEXPORT 1
+
+#else /* Default, non-dll. Use this for Unix or DOS */
+#define _MSVC15DEXPORT
+#define _MSVC20EXPORT
+#define _DLLAPI
+#define _TYPE(a) a
+#endif
+#endif
+
+#define ALEN 32
+#define MIN_MOD_BYTES 64 /* 512 bits */
+
+struct t_client {
+ struct t_num n;
+ struct t_num g;
+ struct t_num s;
+
+ struct t_num a;
+ struct t_num A;
+
+ struct t_num p;
+ struct t_num v;
+
+ SHA1_CTX hash, ckhash;
+
+ char username[MAXUSERLEN];
+ unsigned char session_key[SESSION_KEY_LEN];
+ unsigned char session_response[RESPONSE_LEN];
+
+ unsigned char nbuf[MAXPARAMLEN], gbuf[MAXPARAMLEN], sbuf[MAXSALTLEN];
+ unsigned char pbuf[MAXPARAMLEN], vbuf[MAXPARAMLEN];
+ unsigned char abuf[ALEN], Abuf[MAXPARAMLEN];
+};
+
+/*
+ * SRP client-side negotiation
+ *
+ * This code negotiates the client side of an SRP exchange.
+ * "t_clientopen" accepts a username, and N, g, and s parameters,
+ * which are usually sent by the server in the first round.
+ * The client should then call...
+ * "t_clientgenexp" will generate a random 256-bit exponent and
+ * raise g to that power, returning the result. This result
+ * should be sent to the server as w(p).
+ * "t_clientpasswd" accepts the user's password, which should be
+ * entered locally and updates the client's state.
+ * "t_clientgetkey" accepts the exponential y(p), which should
+ * be sent by the server in the next round and computes the
+ * 256-bit session key. This data should be saved before the
+ * session is closed.
+ * "t_clientresponse" computes the session key proof as SHA(y(p), K).
+ * "t_clientclose" closes the session and frees its memory.
+ *
+ * Note that authentication is not performed per se; it is up
+ * to either/both sides of the protocol to now verify securely
+ * that their session keys agree in order to establish authenticity.
+ * One possible way is through "oracle hashing"; one side sends
+ * r, the other replies with H(r,K), where H() is a hash function.
+ *
+ * t_clientresponse and t_clientverify now implement a version of
+ * the session-key verification described above.
+ */
+_TYPE( struct t_client * )
+ t_clientopen P((const char *, struct t_num *, struct t_num *,
+ struct t_num *));
+_TYPE( struct t_num * ) t_clientgenexp P((struct t_client *));
+_TYPE( void ) t_clientpasswd P((struct t_client *, char *));
+_TYPE( unsigned char * )
+ t_clientgetkey P((struct t_client *, struct t_num *));
+_TYPE( int ) t_clientverify P((struct t_client *, unsigned char *));
+_TYPE( unsigned char * ) t_clientresponse P((struct t_client *));
+_TYPE( void ) t_clientclose P((struct t_client *));
+
+#endif
diff --git a/package/ead/src/tinysrp/t_conf.c b/package/ead/src/tinysrp/t_conf.c
new file mode 100644
index 000000000..fbe6f410e
--- /dev/null
+++ b/package/ead/src/tinysrp/t_conf.c
@@ -0,0 +1,1080 @@
+/*
+ * Copyright (c) 1997-1999 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following conditions apply:
+ *
+ * 1. Any software that incorporates the SRP authentication technology
+ * must display the following acknowlegment:
+ * "This product uses the 'Secure Remote Password' cryptographic
+ * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
+ *
+ * 2. Any software that incorporates all or part of the SRP distribution
+ * itself must also display the following acknowledgment:
+ * "This product includes software developed by Tom Wu and Eugene
+ * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
+ *
+ * 3. Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice and list of conditions.
+ */
+
+#include <stdio.h>
+
+#include "t_defines.h"
+#include "t_pwd.h"
+#include "t_read.h"
+#include "bn.h"
+#include "bn_lcl.h"
+#include "bn_prime.h"
+
+#define TABLE_SIZE 32
+
+static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1,
+ const BIGNUM *a1_odd, int k, BN_CTX *ctx, BN_MONT_CTX *mont);
+
+/*
+ * This is the safe prime generation logic.
+ * To generate a safe prime p (where p = 2q+1 and q is prime), we start
+ * with a random odd q that is one bit shorter than the desired length
+ * of p. We use a simple 30-element sieve to filter the values of q
+ * and consider only those that are 11, 23, or 29 (mod 30). (If q were
+ * anything else, either q or p would be divisible by 2, 3, or 5).
+ * For the values of q that are left, we apply the following tests in
+ * this order:
+ *
+ * trial divide q
+ * let p = 2q + 1
+ * trial divide p
+ * apply Fermat test to q (2^q == 2 (mod q))
+ * apply Fermat test to p (2^p == 2 (mod p))
+ * apply real probablistic primality test to q
+ * apply real probablistic primality test to p
+ *
+ * A number that passes all these tests is considered a safe prime for
+ * our purposes. The tests are ordered this way for efficiency; the
+ * slower tests are run rarely if ever at all.
+ */
+
+static int
+trialdiv(x)
+ const BigInteger x;
+{
+ static int primes[] = { /* All odd primes < 256 */
+ 3, 5, 7, 11, 13, 17, 19, 23, 29,
+ 31, 37, 41, 43, 47, 53, 59, 61, 67,
+ 71, 73, 79, 83, 89, 97, 101, 103,
+ 107, 109, 113, 127, 131, 137, 139, 149, 151,
+ 157, 163, 167, 173, 179, 181, 191, 193, 197,
+ 199, 211, 223, 227, 229, 233, 239, 241, 251
+ };
+ static int nprimes = sizeof(primes) / sizeof(int);
+ int i;
+
+ for(i = 0; i < nprimes; ++i) {
+ if(BigIntegerModInt(x, primes[i]) == 0)
+ return primes[i];
+ }
+ return 1;
+}
+
+/* x + sieve30[x%30] == 11, 23, or 29 (mod 30) */
+
+static int sieve30[] =
+{ 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
+ 1, 12, 11, 10, 9, 8, 7, 6, 5, 4,
+ 3, 2, 1, 6, 5, 4, 3, 2, 1, 12
+};
+
+/* Find a Sophie-Germain prime between "lo" and "hi". NOTE: this is not
+ a "safe prime", but the smaller prime. Take 2q+1 to get the safe prime. */
+
+static void
+sophie_germain(q, lo, hi)
+ BigInteger q; /* assumed initialized */
+ const BigInteger lo;
+ const BigInteger hi;
+{
+ BigInteger m, p, r;
+ char parambuf[MAXPARAMLEN];
+ int foundprime = 0;
+ int i, mod30;
+
+ m = BigIntegerFromInt(0);
+ BigIntegerSub(m, hi, lo);
+ i = (BigIntegerBitLen(m) + 7) / 8;
+ t_random(parambuf, i);
+ r = BigIntegerFromBytes(parambuf, i);
+ BigIntegerMod(r, r, m);
+
+ BigIntegerAdd(q, r, lo);
+ if(BigIntegerModInt(q, 2) == 0)
+ BigIntegerAddInt(q, q, 1); /* make q odd */
+
+ mod30 = BigIntegerModInt(q, 30); /* mod30 = q % 30 */
+
+ BigIntegerFree(m);
+ m = BigIntegerFromInt(2); /* m = 2 */
+ p = BigIntegerFromInt(0);
+
+ while(BigIntegerCmp(q, hi) < 0) {
+ if(trialdiv(q) < 2) {
+ BigIntegerMulInt(p, q, 2); /* p = 2 * q */
+ BigIntegerAddInt(p, p, 1); /* p += 1 */
+ if(trialdiv(p) < 2) {
+ BigIntegerModExp(r, m, q, q); /* r = 2^q % q */
+ if(BigIntegerCmpInt(r, 2) == 0) { /* if(r == 2) */
+ BigIntegerModExp(r, m, p, p); /* r = 2^p % p */
+ if(BigIntegerCmpInt(r, 2) == 0) { /* if(r == 2) */
+ if(BigIntegerCheckPrime(q) && BigIntegerCheckPrime(p)) {
+ ++foundprime;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ i = sieve30[mod30];
+ BigIntegerAddInt(q, q, i); /* q += i */
+ mod30 = (mod30 + i) % 30;
+ }
+
+ /* should wrap around on failure */
+ if(!foundprime) {
+ fprintf(stderr, "Prime generation failed!\n");
+ exit(1);
+ }
+
+ BigIntegerFree(r);
+ BigIntegerFree(m);
+ BigIntegerFree(p);
+}
+
+_TYPE( struct t_confent * )
+t_makeconfent(tc, nsize)
+ struct t_conf * tc;
+ int nsize;
+{
+ BigInteger n, g, q, t, u;
+
+ t = BigIntegerFromInt(0);
+ u = BigIntegerFromInt(1); /* u = 1 */
+ BigIntegerLShift(t, u, nsize - 2); /* t = 2^(nsize-2) */
+ BigIntegerMulInt(u, t, 2); /* u = 2^(nsize-1) */
+
+ q = BigIntegerFromInt(0);
+ sophie_germain(q, t, u);
+
+ n = BigIntegerFromInt(0);
+ BigIntegerMulInt(n, q, 2);
+ BigIntegerAddInt(n, n, 1);
+
+ /* Look for a generator mod n */
+ g = BigIntegerFromInt(2);
+ while(1) {
+ BigIntegerModExp(t, g, q, n); /* t = g^q % n */
+ if(BigIntegerCmpInt(t, 1) == 0) /* if(t == 1) */
+ BigIntegerAddInt(g, g, 1); /* ++g */
+ else
+ break;
+ }
+ BigIntegerFree(t);
+ BigIntegerFree(u);
+ BigIntegerFree(q);
+
+ tc->tcbuf.modulus.data = tc->modbuf;
+ tc->tcbuf.modulus.len = BigIntegerToBytes(n, tc->tcbuf.modulus.data);
+ BigIntegerFree(n);
+
+ tc->tcbuf.generator.data = tc->genbuf;
+ tc->tcbuf.generator.len = BigIntegerToBytes(g, tc->tcbuf.generator.data);
+ BigIntegerFree(g);
+
+ tc->tcbuf.index = 1;
+ return &tc->tcbuf;
+}
+
+_TYPE( struct t_confent * )
+t_makeconfent_c(tc, nsize)
+ struct t_conf * tc;
+ int nsize;
+{
+ BigInteger g, n, p, q, j, k, t, u;
+ int psize, qsize;
+
+ psize = nsize / 2;
+ qsize = nsize - psize;
+
+ t = BigIntegerFromInt(1); /* t = 1 */
+ u = BigIntegerFromInt(0);
+ BigIntegerLShift(u, t, psize - 3); /* u = t*2^(psize-3) = 2^(psize-3) */
+ BigIntegerMulInt(t, u, 3); /* t = 3*u = 1.5*2^(psize-2) */
+ BigIntegerAdd(u, u, t); /* u += t [u = 2^(psize-1)] */
+ j = BigIntegerFromInt(0);
+ sophie_germain(j, t, u);
+
+ k = BigIntegerFromInt(0);
+ if(qsize != psize) {
+ BigIntegerFree(t);
+ t = BigIntegerFromInt(1); /* t = 1 */
+ BigIntegerLShift(u, t, qsize - 3); /* u = t*2^(qsize-3) = 2^(qsize-3) */
+ BigIntegerMulInt(t, u, 3); /* t = 3*u = 1.5*2^(qsize-2) */
+ BigIntegerAdd(u, u, t); /* u += t [u = 2^(qsize-1)] */
+ }
+ sophie_germain(k, t, u);
+
+ p = BigIntegerFromInt(0);
+ BigIntegerMulInt(p, j, 2); /* p = 2 * j */
+ BigIntegerAddInt(p, p, 1); /* p += 1 */
+
+ q = BigIntegerFromInt(0);
+ BigIntegerMulInt(q, k, 2); /* q = 2 * k */
+ BigIntegerAddInt(q, q, 1); /* q += 1 */
+
+ n = BigIntegerFromInt(0);
+ BigIntegerMul(n, p, q); /* n = p * q */
+ BigIntegerMul(u, j, k); /* u = j * k */
+
+ BigIntegerFree(p);
+ BigIntegerFree(q);
+ BigIntegerFree(j);
+ BigIntegerFree(k);
+
+ g = BigIntegerFromInt(2); /* g = 2 */
+
+ /* Look for a generator mod n */
+ while(1) {
+ BigIntegerModExp(t, g, u, n); /* t = g^u % n */
+ if(BigIntegerCmpInt(t, 1) == 0)
+ BigIntegerAddInt(g, g, 1); /* ++g */
+ else
+ break;
+ }
+
+ BigIntegerFree(u);
+ BigIntegerFree(t);
+
+ tc->tcbuf.modulus.data = tc->modbuf;
+ tc->tcbuf.modulus.len = BigIntegerToBytes(n, tc->tcbuf.modulus.data);
+ BigIntegerFree(n);
+
+ tc->tcbuf.generator.data = tc->genbuf;
+ tc->tcbuf.generator.len = BigIntegerToBytes(g, tc->tcbuf.generator.data);
+ BigIntegerFree(g);
+
+ tc->tcbuf.index = 1;
+ return &tc->tcbuf;
+}
+
+_TYPE( struct t_confent * )
+t_newconfent(tc)
+ struct t_conf * tc;
+{
+ tc->tcbuf.index = 0;
+ tc->tcbuf.modulus.data = tc->modbuf;
+ tc->tcbuf.modulus.len = 0;
+ tc->tcbuf.generator.data = tc->genbuf;
+ tc->tcbuf.generator.len = 0;
+ return &tc->tcbuf;
+}
+
+_TYPE( void )
+t_putconfent(ent, fp)
+ const struct t_confent * ent;
+ FILE * fp;
+{
+ char strbuf[MAXB64PARAMLEN];
+
+ fprintf(fp, "%d:%s:", ent->index,
+ t_tob64(strbuf, ent->modulus.data, ent->modulus.len));
+ fprintf(fp, "%s\n",
+ t_tob64(strbuf, ent->generator.data, ent->generator.len));
+}
+
+int
+BigIntegerBitLen(b)
+ BigInteger b;
+{
+ return BN_num_bits(b);
+}
+
+int
+BigIntegerCheckPrime(n)
+ BigInteger n;
+{
+ BN_CTX * ctx = BN_CTX_new();
+ int rv = BN_is_prime(n, 25, NULL, ctx, NULL);
+ BN_CTX_free(ctx);
+ return rv;
+}
+
+unsigned int
+BigIntegerModInt(d, m)
+ BigInteger d;
+ unsigned int m;
+{
+ return BN_mod_word(d, m);
+}
+
+void
+BigIntegerMod(result, d, m)
+ BigInteger result, d, m;
+{
+ BN_CTX * ctx = BN_CTX_new();
+ BN_mod(result, d, m, ctx);
+ BN_CTX_free(ctx);
+}
+
+void
+BigIntegerMul(result, m1, m2)
+ BigInteger result, m1, m2;
+{
+ BN_CTX * ctx = BN_CTX_new();
+ BN_mul(result, m1, m2, ctx);
+ BN_CTX_free(ctx);
+}
+
+void
+BigIntegerLShift(result, x, bits)
+ BigInteger result, x;
+ unsigned int bits;
+{
+ BN_lshift(result, x, bits);
+}
+
+int BN_is_prime(const BIGNUM *a, int checks, void (*callback)(int,int,void *),
+ BN_CTX *ctx_passed, void *cb_arg)
+ {
+ return BN_is_prime_fasttest(a, checks, callback, ctx_passed, cb_arg, 0);
+ }
+
+int BN_is_prime_fasttest(const BIGNUM *a, int checks,
+ void (*callback)(int,int,void *),
+ BN_CTX *ctx_passed, void *cb_arg,
+ int do_trial_division)
+ {
+ int i, j, ret = -1;
+ int k;
+ BN_CTX *ctx = NULL;
+ BIGNUM *A1, *A1_odd, *check; /* taken from ctx */
+ BN_MONT_CTX *mont = NULL;
+ const BIGNUM *A = NULL;
+
+ if (checks == BN_prime_checks)
+ checks = BN_prime_checks_for_size(BN_num_bits(a));
+
+ /* first look for small factors */
+ if (!BN_is_odd(a))
+ return(0);
+ if (do_trial_division)
+ {
+ for (i = 1; i < NUMPRIMES; i++)
+ if (BN_mod_word(a, primes[i]) == 0)
+ return 0;
+ if (callback != NULL) callback(1, -1, cb_arg);
+ }
+
+ if (ctx_passed != NULL)
+ ctx = ctx_passed;
+ else
+ if ((ctx=BN_CTX_new()) == NULL)
+ goto err;
+ BN_CTX_start(ctx);
+
+ /* A := abs(a) */
+ if (a->neg)
+ {
+ BIGNUM *t;
+ if ((t = BN_CTX_get(ctx)) == NULL) goto err;
+ BN_copy(t, a);
+ t->neg = 0;
+ A = t;
+ }
+ else
+ A = a;
+ A1 = BN_CTX_get(ctx);
+ A1_odd = BN_CTX_get(ctx);
+ check = BN_CTX_get(ctx);
+ if (check == NULL) goto err;
+
+ /* compute A1 := A - 1 */
+ if (!BN_copy(A1, A))
+ goto err;
+ if (!BN_sub_word(A1, 1))
+ goto err;
+ if (BN_is_zero(A1))
+ {
+ ret = 0;
+ goto err;
+ }
+
+ /* write A1 as A1_odd * 2^k */
+ k = 1;
+ while (!BN_is_bit_set(A1, k))
+ k++;
+ if (!BN_rshift(A1_odd, A1, k))
+ goto err;
+
+ /* Montgomery setup for computations mod A */
+ mont = BN_MONT_CTX_new();
+ if (mont == NULL)
+ goto err;
+ if (!BN_MONT_CTX_set(mont, A, ctx))
+ goto err;
+
+ for (i = 0; i < checks; i++)
+ {
+ if (!BN_pseudo_rand(check, BN_num_bits(A1), 0, 0))
+ goto err;
+ if (BN_cmp(check, A1) >= 0)
+ if (!BN_sub(check, check, A1))
+ goto err;
+ if (!BN_add_word(check, 1))
+ goto err;
+ /* now 1 <= check < A */
+
+ j = witness(check, A, A1, A1_odd, k, ctx, mont);
+ if (j == -1) goto err;
+ if (j)
+ {
+ ret=0;
+ goto err;
+ }
+ if (callback != NULL) callback(1,i,cb_arg);
+ }
+ ret=1;
+err:
+ if (ctx != NULL)
+ {
+ BN_CTX_end(ctx);
+ if (ctx_passed == NULL)
+ BN_CTX_free(ctx);
+ }
+ if (mont != NULL)
+ BN_MONT_CTX_free(mont);
+
+ return(ret);
+ }
+
+static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1,
+ const BIGNUM *a1_odd, int k, BN_CTX *ctx, BN_MONT_CTX *mont)
+ {
+ if (!BN_mod_exp_mont(w, w, a1_odd, a, ctx, mont)) /* w := w^a1_odd mod a */
+ return -1;
+ if (BN_is_one(w))
+ return 0; /* probably prime */
+ if (BN_cmp(w, a1) == 0)
+ return 0; /* w == -1 (mod a), 'a' is probably prime */
+ while (--k)
+ {
+ if (!BN_mod_mul(w, w, w, a, ctx)) /* w := w^2 mod a */
+ return -1;
+ if (BN_is_one(w))
+ return 1; /* 'a' is composite, otherwise a previous 'w' would
+ * have been == -1 (mod 'a') */
+ if (BN_cmp(w, a1) == 0)
+ return 0; /* w == -1 (mod a), 'a' is probably prime */
+ }
+ /* If we get here, 'w' is the (a-1)/2-th power of the original 'w',
+ * and it is neither -1 nor +1 -- so 'a' cannot be prime */
+ return 1;
+ }
+
+int BN_mod_exp_mont(BIGNUM *rr, BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
+ {
+ int i,j,bits,ret=0,wstart,wend,window,wvalue;
+ int start=1,ts=0;
+ BIGNUM *d,*r;
+ BIGNUM *aa;
+ BIGNUM val[TABLE_SIZE];
+ BN_MONT_CTX *mont=NULL;
+
+ bn_check_top(a);
+ bn_check_top(p);
+ bn_check_top(m);
+
+ if (!(m->d[0] & 1))
+ {
+ return(0);
+ }
+ bits=BN_num_bits(p);
+ if (bits == 0)
+ {
+ BN_one(rr);
+ return(1);
+ }
+ BN_CTX_start(ctx);
+ d = BN_CTX_get(ctx);
+ r = BN_CTX_get(ctx);
+ if (d == NULL || r == NULL) goto err;
+
+ /* If this is not done, things will break in the montgomery
+ * part */
+
+ if (in_mont != NULL)
+ mont=in_mont;
+ else
+ {
+ if ((mont=BN_MONT_CTX_new()) == NULL) goto err;
+ if (!BN_MONT_CTX_set(mont,m,ctx)) goto err;
+ }
+
+ BN_init(&val[0]);
+ ts=1;
+ if (BN_ucmp(a,m) >= 0)
+ {
+ if (!BN_mod(&(val[0]),a,m,ctx))
+ goto err;
+ aa= &(val[0]);
+ }
+ else
+ aa=a;
+ if (!BN_to_montgomery(&(val[0]),aa,mont,ctx)) goto err; /* 1 */
+
+ window = BN_window_bits_for_exponent_size(bits);
+ if (window > 1)
+ {
+ if (!BN_mod_mul_montgomery(d,&(val[0]),&(val[0]),mont,ctx)) goto err; /* 2 */
+ j=1<<(window-1);
+ for (i=1; i<j; i++)
+ {
+ BN_init(&(val[i]));
+ if (!BN_mod_mul_montgomery(&(val[i]),&(val[i-1]),d,mont,ctx))
+ goto err;
+ }
+ ts=i;
+ }
+
+ start=1; /* This is used to avoid multiplication etc
+ * when there is only the value '1' in the
+ * buffer. */
+ wvalue=0; /* The 'value' of the window */
+ wstart=bits-1; /* The top bit of the window */
+ wend=0; /* The bottom bit of the window */
+
+ if (!BN_to_montgomery(r,BN_value_one(),mont,ctx)) goto err;
+ for (;;)
+ {
+ if (BN_is_bit_set(p,wstart) == 0)
+ {
+ if (!start)
+ {
+ if (!BN_mod_mul_montgomery(r,r,r,mont,ctx))
+ goto err;
+ }
+ if (wstart == 0) break;
+ wstart--;
+ continue;
+ }
+ /* We now have wstart on a 'set' bit, we now need to work out
+ * how bit a window to do. To do this we need to scan
+ * forward until the last set bit before the end of the
+ * window */
+ j=wstart;
+ wvalue=1;
+ wend=0;
+ for (i=1; i<window; i++)
+ {
+ if (wstart-i < 0) break;
+ if (BN_is_bit_set(p,wstart-i))
+ {
+ wvalue<<=(i-wend);
+ wvalue|=1;
+ wend=i;
+ }
+ }
+
+ /* wend is the size of the current window */
+ j=wend+1;
+ /* add the 'bytes above' */
+ if (!start)
+ for (i=0; i<j; i++)
+ {
+ if (!BN_mod_mul_montgomery(r,r,r,mont,ctx))
+ goto err;
+ }
+
+ /* wvalue will be an odd number < 2^window */
+ if (!BN_mod_mul_montgomery(r,r,&(val[wvalue>>1]),mont,ctx))
+ goto err;
+
+ /* move the 'window' down further */
+ wstart-=wend+1;
+ wvalue=0;
+ start=0;
+ if (wstart < 0) break;
+ }
+ if (!BN_from_montgomery(rr,r,mont,ctx)) goto err;
+ ret=1;
+err:
+ if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont);
+ BN_CTX_end(ctx);
+ for (i=0; i<ts; i++)
+ BN_clear_free(&(val[i]));
+ return(ret);
+ }
+
+BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w)
+ {
+#ifndef BN_LLONG
+ BN_ULONG ret=0;
+#else
+ BN_ULLONG ret=0;
+#endif
+ int i;
+
+ w&=BN_MASK2;
+ for (i=a->top-1; i>=0; i--)
+ {
+#ifndef BN_LLONG
+ ret=((ret<<BN_BITS4)|((a->d[i]>>BN_BITS4)&BN_MASK2l))%w;
+ ret=((ret<<BN_BITS4)|(a->d[i]&BN_MASK2l))%w;
+#else
+ ret=(BN_ULLONG)(((ret<<(BN_ULLONG)BN_BITS2)|a->d[i])%
+ (BN_ULLONG)w);
+#endif
+ }
+ return((BN_ULONG)ret);
+ }
+
+static int bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom)
+ {
+ unsigned char *buf=NULL;
+ int ret=0,bit,bytes,mask;
+
+ if (bits == 0)
+ {
+ BN_zero(rnd);
+ return 1;
+ }
+
+ bytes=(bits+7)/8;
+ bit=(bits-1)%8;
+ mask=0xff<<bit;
+
+ buf=(unsigned char *)malloc(bytes);
+ if (buf == NULL)
+ {
+ goto err;
+ }
+
+ /* make a random number and set the top and bottom bits */
+ /* this ignores the pseudorand flag */
+
+ t_random(buf, bytes);
+
+ if (top)
+ {
+ if (bit == 0)
+ {
+ buf[0]=1;
+ buf[1]|=0x80;
+ }
+ else
+ {
+ buf[0]|=(3<<(bit-1));
+ buf[0]&= ~(mask<<1);
+ }
+ }
+ else
+ {
+ buf[0]|=(1<<bit);
+ buf[0]&= ~(mask<<1);
+ }
+ if (bottom) /* set bottom bits to whatever odd is */
+ buf[bytes-1]|=1;
+ if (!BN_bin2bn(buf,bytes,rnd)) goto err;
+ ret=1;
+err:
+ if (buf != NULL)
+ {
+ memset(buf,0,bytes);
+ free(buf);
+ }
+ return(ret);
+ }
+
+/* BN_pseudo_rand is the same as BN_rand, now. */
+
+int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom)
+ {
+ return bnrand(1, rnd, bits, top, bottom);
+ }
+
+#define MONT_WORD /* use the faster word-based algorithm */
+
+int BN_mod_mul_montgomery(BIGNUM *r, BIGNUM *a, BIGNUM *b,
+ BN_MONT_CTX *mont, BN_CTX *ctx)
+ {
+ BIGNUM *tmp,*tmp2;
+ int ret=0;
+
+ BN_CTX_start(ctx);
+ tmp = BN_CTX_get(ctx);
+ tmp2 = BN_CTX_get(ctx);
+ if (tmp == NULL || tmp2 == NULL) goto err;
+
+ bn_check_top(tmp);
+ bn_check_top(tmp2);
+
+ if (a == b)
+ {
+ if (!BN_sqr(tmp,a,ctx)) goto err;
+ }
+ else
+ {
+ if (!BN_mul(tmp,a,b,ctx)) goto err;
+ }
+ /* reduce from aRR to aR */
+ if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err;
+ ret=1;
+err:
+ BN_CTX_end(ctx);
+ return(ret);
+ }
+
+int BN_from_montgomery(BIGNUM *ret, BIGNUM *a, BN_MONT_CTX *mont,
+ BN_CTX *ctx)
+ {
+ int retn=0;
+
+#ifdef MONT_WORD
+ BIGNUM *n,*r;
+ BN_ULONG *ap,*np,*rp,n0,v,*nrp;
+ int al,nl,max,i,x,ri;
+
+ BN_CTX_start(ctx);
+ if ((r = BN_CTX_get(ctx)) == NULL) goto err;
+
+ if (!BN_copy(r,a)) goto err;
+ n= &(mont->N);
+
+ ap=a->d;
+ /* mont->ri is the size of mont->N in bits (rounded up
+ to the word size) */
+ al=ri=mont->ri/BN_BITS2;
+
+ nl=n->top;
+ if ((al == 0) || (nl == 0)) { r->top=0; return(1); }
+
+ max=(nl+al+1); /* allow for overflow (no?) XXX */
+ if (bn_wexpand(r,max) == NULL) goto err;
+ if (bn_wexpand(ret,max) == NULL) goto err;
+
+ r->neg=a->neg^n->neg;
+ np=n->d;
+ rp=r->d;
+ nrp= &(r->d[nl]);
+
+ /* clear the top words of T */
+#if 1
+ for (i=r->top; i<max; i++) /* memset? XXX */
+ r->d[i]=0;
+#else
+ memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG));
+#endif
+
+ r->top=max;
+ n0=mont->n0;
+
+#ifdef BN_COUNT
+ printf("word BN_from_montgomery %d * %d\n",nl,nl);
+#endif
+ for (i=0; i<nl; i++)
+ {
+#ifdef __TANDEM
+ {
+ long long t1;
+ long long t2;
+ long long t3;
+ t1 = rp[0] * (n0 & 0177777);
+ t2 = 037777600000l;
+ t2 = n0 & t2;
+ t3 = rp[0] & 0177777;
+ t2 = (t3 * t2) & BN_MASK2;
+ t1 = t1 + t2;
+ v=bn_mul_add_words(rp,np,nl,(BN_ULONG) t1);
+ }
+#else
+ v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
+#endif
+ nrp++;
+ rp++;
+ if (((nrp[-1]+=v)&BN_MASK2) >= v)
+ continue;
+ else
+ {
+ if (((++nrp[0])&BN_MASK2) != 0) continue;
+ if (((++nrp[1])&BN_MASK2) != 0) continue;
+ for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ;
+ }
+ }
+ bn_fix_top(r);
+
+ /* mont->ri will be a multiple of the word size */
+#if 0
+ BN_rshift(ret,r,mont->ri);
+#else
+ ret->neg = r->neg;
+ x=ri;
+ rp=ret->d;
+ ap= &(r->d[x]);
+ if (r->top < x)
+ al=0;
+ else
+ al=r->top-x;
+ ret->top=al;
+ al-=4;
+ for (i=0; i<al; i+=4)
+ {
+ BN_ULONG t1,t2,t3,t4;
+
+ t1=ap[i+0];
+ t2=ap[i+1];
+ t3=ap[i+2];
+ t4=ap[i+3];
+ rp[i+0]=t1;
+ rp[i+1]=t2;
+ rp[i+2]=t3;
+ rp[i+3]=t4;
+ }
+ al+=4;
+ for (; i<al; i++)
+ rp[i]=ap[i];
+#endif
+#else /* !MONT_WORD */
+ BIGNUM *t1,*t2;
+
+ BN_CTX_start(ctx);
+ t1 = BN_CTX_get(ctx);
+ t2 = BN_CTX_get(ctx);
+ if (t1 == NULL || t2 == NULL) goto err;
+
+ if (!BN_copy(t1,a)) goto err;
+ BN_mask_bits(t1,mont->ri);
+
+ if (!BN_mul(t2,t1,&mont->Ni,ctx)) goto err;
+ BN_mask_bits(t2,mont->ri);
+
+ if (!BN_mul(t1,t2,&mont->N,ctx)) goto err;
+ if (!BN_add(t2,a,t1)) goto err;
+ BN_rshift(ret,t2,mont->ri);
+#endif /* MONT_WORD */
+
+ if (BN_ucmp(ret, &(mont->N)) >= 0)
+ {
+ BN_usub(ret,ret,&(mont->N));
+ }
+ retn=1;
+ err:
+ BN_CTX_end(ctx);
+ return(retn);
+ }
+
+void BN_MONT_CTX_init(BN_MONT_CTX *ctx)
+ {
+ ctx->ri=0;
+ BN_init(&(ctx->RR));
+ BN_init(&(ctx->N));
+ BN_init(&(ctx->Ni));
+ ctx->flags=0;
+ }
+
+BN_MONT_CTX *BN_MONT_CTX_new(void)
+ {
+ BN_MONT_CTX *ret;
+
+ if ((ret=(BN_MONT_CTX *)malloc(sizeof(BN_MONT_CTX))) == NULL)
+ return(NULL);
+
+ BN_MONT_CTX_init(ret);
+ ret->flags=BN_FLG_MALLOCED;
+ return(ret);
+ }
+
+void BN_MONT_CTX_free(BN_MONT_CTX *mont)
+ {
+ if(mont == NULL)
+ return;
+
+ BN_free(&(mont->RR));
+ BN_free(&(mont->N));
+ BN_free(&(mont->Ni));
+ if (mont->flags & BN_FLG_MALLOCED)
+ free(mont);
+ }
+
+int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
+ {
+ BIGNUM Ri,*R;
+
+ BN_init(&Ri);
+ R= &(mont->RR); /* grab RR as a temp */
+ BN_copy(&(mont->N),mod); /* Set N */
+
+#ifdef MONT_WORD
+ {
+ BIGNUM tmod;
+ BN_ULONG buf[2];
+
+ mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
+ BN_zero(R);
+ BN_set_bit(R,BN_BITS2); /* R */
+
+ buf[0]=mod->d[0]; /* tmod = N mod word size */
+ buf[1]=0;
+ tmod.d=buf;
+ tmod.top=1;
+ tmod.dmax=2;
+ tmod.neg=mod->neg;
+ /* Ri = R^-1 mod N*/
+ if ((BN_mod_inverse(&Ri,R,&tmod,ctx)) == NULL)
+ goto err;
+ BN_lshift(&Ri,&Ri,BN_BITS2); /* R*Ri */
+ if (!BN_is_zero(&Ri))
+ BN_sub_word(&Ri,1);
+ else /* if N mod word size == 1 */
+ BN_set_word(&Ri,BN_MASK2); /* Ri-- (mod word size) */
+ BN_div(&Ri,NULL,&Ri,&tmod,ctx); /* Ni = (R*Ri-1)/N,
+ * keep only least significant word: */
+ mont->n0=Ri.d[0];
+ BN_free(&Ri);
+ }
+#else /* !MONT_WORD */
+ { /* bignum version */
+ mont->ri=BN_num_bits(mod);
+ BN_zero(R);
+ BN_set_bit(R,mont->ri); /* R = 2^ri */
+ /* Ri = R^-1 mod N*/
+ if ((BN_mod_inverse(&Ri,R,mod,ctx)) == NULL)
+ goto err;
+ BN_lshift(&Ri,&Ri,mont->ri); /* R*Ri */
+ BN_sub_word(&Ri,1);
+ /* Ni = (R*Ri-1) / N */
+ BN_div(&(mont->Ni),NULL,&Ri,mod,ctx);
+ BN_free(&Ri);
+ }
+#endif
+
+ /* setup RR for conversions */
+ BN_zero(&(mont->RR));
+ BN_set_bit(&(mont->RR),mont->ri*2);
+ BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx);
+
+ return(1);
+err:
+ return(0);
+ }
+
+BIGNUM *BN_value_one(void)
+ {
+ static BN_ULONG data_one=1L;
+ static BIGNUM const_one={&data_one,1,1,0};
+
+ return(&const_one);
+ }
+
+/* solves ax == 1 (mod n) */
+BIGNUM *BN_mod_inverse(BIGNUM *in, BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
+ {
+ BIGNUM *A,*B,*X,*Y,*M,*D,*R=NULL;
+ BIGNUM *T,*ret=NULL;
+ int sign;
+
+ bn_check_top(a);
+ bn_check_top(n);
+
+ BN_CTX_start(ctx);
+ A = BN_CTX_get(ctx);
+ B = BN_CTX_get(ctx);
+ X = BN_CTX_get(ctx);
+ D = BN_CTX_get(ctx);
+ M = BN_CTX_get(ctx);
+ Y = BN_CTX_get(ctx);
+ if (Y == NULL) goto err;
+
+ if (in == NULL)
+ R=BN_new();
+ else
+ R=in;
+ if (R == NULL) goto err;
+
+ BN_zero(X);
+ BN_one(Y);
+ if (BN_copy(A,a) == NULL) goto err;
+ if (BN_copy(B,n) == NULL) goto err;
+ sign=1;
+
+ while (!BN_is_zero(B))
+ {
+ if (!BN_div(D,M,A,B,ctx)) goto err;
+ T=A;
+ A=B;
+ B=M;
+ /* T has a struct, M does not */
+
+ if (!BN_mul(T,D,X,ctx)) goto err;
+ if (!BN_add(T,T,Y)) goto err;
+ M=Y;
+ Y=X;
+ X=T;
+ sign= -sign;
+ }
+ if (sign < 0)
+ {
+ if (!BN_sub(Y,n,Y)) goto err;
+ }
+
+ if (BN_is_one(A))
+ { if (!BN_mod(R,Y,n,ctx)) goto err; }
+ else
+ {
+ goto err;
+ }
+ ret=R;
+err:
+ if ((ret == NULL) && (in == NULL)) BN_free(R);
+ BN_CTX_end(ctx);
+ return(ret);
+ }
+
+int BN_set_bit(BIGNUM *a, int n)
+ {
+ int i,j,k;
+
+ i=n/BN_BITS2;
+ j=n%BN_BITS2;
+ if (a->top <= i)
+ {
+ if (bn_wexpand(a,i+1) == NULL) return(0);
+ for(k=a->top; k<i+1; k++)
+ a->d[k]=0;
+ a->top=i+1;
+ }
+
+ a->d[i]|=(((BN_ULONG)1)<<j);
+ return(1);
+ }
+
diff --git a/package/ead/src/tinysrp/t_conv.c b/package/ead/src/tinysrp/t_conv.c
new file mode 100644
index 000000000..d3fe246c4
--- /dev/null
+++ b/package/ead/src/tinysrp/t_conv.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 1997-1999 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following conditions apply:
+ *
+ * 1. Any software that incorporates the SRP authentication technology
+ * must display the following acknowlegment:
+ * "This product uses the 'Secure Remote Password' cryptographic
+ * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
+ *
+ * 2. Any software that incorporates all or part of the SRP distribution
+ * itself must also display the following acknowledgment:
+ * "This product includes software developed by Tom Wu and Eugene
+ * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
+ *
+ * 3. Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice and list of conditions.
+ */
+
+/*#define _POSIX_SOURCE*/
+#include <stdio.h>
+#include "t_defines.h"
+
+static int
+hexDigitToInt(c)
+ char c;
+{
+ if(c >= '0' && c <= '9')
+ return c - '0';
+ else if(c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ else if(c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ else
+ return 0;
+}
+
+/*
+ * Convert a hex string to a string of bytes; return size of dst
+ */
+_TYPE( int )
+t_fromhex(dst, src)
+ register char *dst, *src;
+{
+ register char *chp = dst;
+ register unsigned size = strlen(src);
+
+ /* FIXME: handle whitespace and non-hex digits by setting size and src
+ appropriately. */
+
+ if(size % 2 == 1) {
+ *chp++ = hexDigitToInt(*src++);
+ --size;
+ }
+ while(size > 0) {
+ *chp++ = (hexDigitToInt(*src) << 4) | hexDigitToInt(*(src + 1));
+ src += 2;
+ size -= 2;
+ }
+ return chp - dst;
+}
+
+/*
+ * Convert a string of bytes to their hex representation
+ */
+_TYPE( char * )
+t_tohex(dst, src, size)
+ register char *dst, *src;
+ register unsigned size;
+{
+ int notleading = 0;
+
+ register char *chp = dst;
+ if (size != 0) do {
+ if(notleading || *src != '\0') {
+ notleading = 1;
+ sprintf(chp, "%.2x", * (unsigned char *) src);
+ chp += 2;
+ }
+ ++src;
+ } while (--size != 0);
+ return dst;
+}
+
+static char b64table[] =
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
+
+/*
+ * Convert a base64 string into raw byte array representation.
+ */
+_TYPE( int )
+t_fromb64(dst, src)
+ register char *dst, *src;
+{
+ unsigned char *a;
+ char *loc;
+ int i, j;
+ unsigned int size;
+
+ while(*src && (*src == ' ' || *src == '\t' || *src == '\n'))
+ ++src;
+ size = strlen(src);
+
+ a = malloc((size + 1) * sizeof(unsigned char));
+ if(a == (unsigned char *) 0)
+ return -1;
+
+ i = 0;
+ while(i < size) {
+ loc = strchr(b64table, src[i]);
+ if(loc == (char *) 0)
+ break;
+ else
+ a[i] = loc - b64table;
+ ++i;
+ }
+ size = i;
+
+ i = size - 1;
+ j = size;
+ while(1) {
+ a[j] = a[i];
+ if(--i < 0)
+ break;
+ a[j] |= (a[i] & 3) << 6;
+ --j;
+ a[j] = (unsigned char) ((a[i] & 0x3c) >> 2);
+ if(--i < 0)
+ break;
+ a[j] |= (a[i] & 0xf) << 4;
+ --j;
+ a[j] = (unsigned char) ((a[i] & 0x30) >> 4);
+ if(--i < 0)
+ break;
+ a[j] |= (a[i] << 2);
+
+ a[--j] = 0;
+ if(--i < 0)
+ break;
+ }
+
+ while(a[j] == 0 && j <= size)
+ ++j;
+
+ memcpy(dst, a + j, size - j + 1);
+ free(a);
+ return size - j + 1;
+}
+
+/*
+ * Convert a raw byte string into a null-terminated base64 ASCII string.
+ */
+_TYPE( char * )
+t_tob64(dst, src, size)
+ register char *dst, *src;
+ register unsigned size;
+{
+ int c, pos = size % 3;
+ unsigned char b0 = 0, b1 = 0, b2 = 0, notleading = 0;
+ char *olddst = dst;
+
+ switch(pos) {
+ case 1:
+ b2 = src[0];
+ break;
+ case 2:
+ b1 = src[0];
+ b2 = src[1];
+ break;
+ }
+
+ while(1) {
+ c = (b0 & 0xfc) >> 2;
+ if(notleading || c != 0) {
+ *dst++ = b64table[c];
+ notleading = 1;
+ }
+ c = ((b0 & 3) << 4) | ((b1 & 0xf0) >> 4);
+ if(notleading || c != 0) {
+ *dst++ = b64table[c];
+ notleading = 1;
+ }
+ c = ((b1 & 0xf) << 2) | ((b2 & 0xc0) >> 6);
+ if(notleading || c != 0) {
+ *dst++ = b64table[c];
+ notleading = 1;
+ }
+ c = b2 & 0x3f;
+ if(notleading || c != 0) {
+ *dst++ = b64table[c];
+ notleading = 1;
+ }
+ if(pos >= size)
+ break;
+ else {
+ b0 = src[pos++];
+ b1 = src[pos++];
+ b2 = src[pos++];
+ }
+ }
+
+ *dst++ = '\0';
+ return olddst;
+}
diff --git a/package/ead/src/tinysrp/t_defines.h b/package/ead/src/tinysrp/t_defines.h
new file mode 100644
index 000000000..4128093f6
--- /dev/null
+++ b/package/ead/src/tinysrp/t_defines.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 1997-1999 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following conditions apply:
+ *
+ * 1. Any software that incorporates the SRP authentication technology
+ * must display the following acknowlegment:
+ * "This product uses the 'Secure Remote Password' cryptographic
+ * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
+ *
+ * 2. Any software that incorporates all or part of the SRP distribution
+ * itself must also display the following acknowledgment:
+ * "This product includes software developed by Tom Wu and Eugene
+ * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
+ *
+ * 3. Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice and list of conditions.
+ */
+
+#ifndef T_DEFINES_H
+#define T_DEFINES_H
+
+#ifndef P
+#if defined(__STDC__) || defined(__cplusplus)
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#ifndef _DLLDECL
+#define _DLLDECL
+
+#ifdef MSVC15 /* MSVC1.5 support for 16 bit apps */
+#define _MSVC15EXPORT _export
+#define _MSVC20EXPORT
+#define _DLLAPI _export _pascal
+#define _TYPE(a) a _MSVC15EXPORT
+#define DLLEXPORT 1
+
+#elif MSVC20
+#define _MSVC15EXPORT
+#define _MSVC20EXPORT _declspec(dllexport)
+#define _DLLAPI
+#define _TYPE(a) _MSVC20EXPORT a
+#define DLLEXPORT 1
+
+#else /* Default, non-dll. Use this for Unix or DOS */
+#define _MSVC15DEXPORT
+#define _MSVC20EXPORT
+#define _DLLAPI
+#define _TYPE(a) a
+#endif
+#endif
+
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <string.h>
+#else /* not STDC_HEADERS */
+#ifndef HAVE_STRCHR
+#define strchr index
+#define strrchr rindex
+#endif
+char *strchr(), *strrchr(), *strtok();
+#ifndef HAVE_MEMCPY
+#define memcpy(d, s, n) bcopy((s), (d), (n))
+#endif
+#endif /* not STDC_HEADERS */
+
+#include <sys/types.h>
+
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else /* not TIME_WITH_SYS_TIME */
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif /* not TIME_WITH_SYS_TIME */
+
+#if HAVE_TERMIOS_H
+#include <termios.h>
+#define STTY(fd, termio) tcsetattr(fd, TCSANOW, termio)
+#define GTTY(fd, termio) tcgetattr(fd, termio)
+#define TERMIO struct termios
+#define USE_TERMIOS
+#elif HAVE_TERMIO_H
+#include <sys/ioctl.h>
+#include <termio.h>
+#define STTY(fd, termio) ioctl(fd, TCSETA, termio)
+#define GTTY(fd, termio) ioctl(fd, TCGETA, termio)
+#define TEMRIO struct termio
+#define USE_TERMIO
+#elif HAVE_SGTTY_H
+#include <sgtty.h>
+#define STTY(fd, termio) stty(fd, termio)
+#define GTTY(fd, termio) gtty(fd, termio)
+#define TERMIO struct sgttyb
+#define USE_SGTTY
+#endif
+
+#ifdef USE_FTIME
+#include <sys/timeb.h>
+#endif
+
+#ifndef MATH_PRIV
+typedef void * BigInteger;
+#endif
+
+_TYPE( BigInteger ) BigIntegerFromInt P((unsigned int number));
+_TYPE( BigInteger ) BigIntegerFromBytes P((unsigned char * bytes, int length));
+_TYPE( int ) BigIntegerToBytes P((BigInteger src, unsigned char * dest));
+_TYPE( int ) BigIntegerBitLen P((BigInteger b));
+_TYPE( int ) BigIntegerCmp P((BigInteger c1, BigInteger c2));
+_TYPE( int ) BigIntegerCmpInt P((BigInteger c1, unsigned int c2));
+_TYPE( void ) BigIntegerLShift P((BigInteger result, BigInteger x,
+ unsigned int bits));
+_TYPE( void ) BigIntegerAdd P((BigInteger result, BigInteger a1, BigInteger a2));
+_TYPE( void ) BigIntegerAddInt P((BigInteger result,
+ BigInteger a1, unsigned int a2));
+_TYPE( void ) BigIntegerSub P((BigInteger result, BigInteger s1, BigInteger s2));
+_TYPE( void ) BigIntegerSubInt P((BigInteger result,
+ BigInteger s1, unsigned int s2));
+/* For BigIntegerMul{,Int}: result != m1, m2 */
+_TYPE( void ) BigIntegerMul P((BigInteger result, BigInteger m1, BigInteger m2));
+_TYPE( void ) BigIntegerMulInt P((BigInteger result,
+ BigInteger m1, unsigned int m2));
+_TYPE( void ) BigIntegerDivInt P((BigInteger result,
+ BigInteger d, unsigned int m));
+_TYPE( void ) BigIntegerMod P((BigInteger result, BigInteger d, BigInteger m));
+_TYPE( unsigned int ) BigIntegerModInt P((BigInteger d, unsigned int m));
+_TYPE( void ) BigIntegerModMul P((BigInteger result,
+ BigInteger m1, BigInteger m2, BigInteger m));
+_TYPE( void ) BigIntegerModExp P((BigInteger result, BigInteger base,
+ BigInteger expt, BigInteger modulus));
+_TYPE( void ) BigIntegerModExpInt P((BigInteger result, BigInteger base,
+ unsigned int expt, BigInteger modulus));
+_TYPE( int ) BigIntegerCheckPrime P((BigInteger n));
+_TYPE( void ) BigIntegerFree P((BigInteger b));
+
+#endif
diff --git a/package/ead/src/tinysrp/t_getconf.c b/package/ead/src/tinysrp/t_getconf.c
new file mode 100644
index 000000000..db6de6171
--- /dev/null
+++ b/package/ead/src/tinysrp/t_getconf.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 1997-1999 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following conditions apply:
+ *
+ * 1. Any software that incorporates the SRP authentication technology
+ * must display the following acknowlegment:
+ * "This product uses the 'Secure Remote Password' cryptographic
+ * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
+ *
+ * 2. Any software that incorporates all or part of the SRP distribution
+ * itself must also display the following acknowledgment:
+ * "This product includes software developed by Tom Wu and Eugene
+ * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
+ *
+ * 3. Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice and list of conditions.
+ */
+
+#include <stdio.h>
+
+#include "t_defines.h"
+#include "t_pwd.h"
+#include "t_read.h"
+
+/* Master builtin parameter storage object. The default that tphrase
+uses is the last one. */
+
+static struct pre_struct {
+ struct t_preconf preconf;
+ int state; /* 0 == uninitialized/first time */
+ unsigned char modbuf[MAXPARAMLEN];
+ unsigned char genbuf[MAXPARAMLEN];
+} pre_params[] = {
+ { { "2iQzj1CagQc/5ctbuJYLWlhtAsPHc7xWVyCPAKFRLWKADpASkqe9djWPFWTNTdeJtL8nAhImCn3Sr/IAdQ1FrGw0WvQUstPx3FO9KNcXOwisOQ1VlL.gheAHYfbYyBaxXL.NcJx9TUwgWDT0hRzFzqSrdGGTN3FgSTA1v4QnHtEygNj3eZ.u0MThqWUaDiP87nqha7XnT66bkTCkQ8.7T8L4KZjIImrNrUftedTTBi.WCi.zlrBxDuOM0da0JbUkQlXqvp0yvJAPpC11nxmmZOAbQOywZGmu9nhZNuwTlxjfIro0FOdthaDTuZRL9VL7MRPUDo/DQEyW.d4H.UIlzp",
+ "2",
+ NULL }, 0 },
+ { { "dUyyhxav9tgnyIg65wHxkzkb7VIPh4o0lkwfOKiPp4rVJrzLRYVBtb76gKlaO7ef5LYGEw3G.4E0jbMxcYBetDy2YdpiP/3GWJInoBbvYHIRO9uBuxgsFKTKWu7RnR7yTau/IrFTdQ4LY/q.AvoCzMxV0PKvD9Odso/LFIItn8PbTov3VMn/ZEH2SqhtpBUkWtmcIkEflhX/YY/fkBKfBbe27/zUaKUUZEUYZ2H2nlCL60.JIPeZJSzsu/xHDVcx",
+ "2",
+ NULL }, 0 },
+ { { "3NUKQ2Re4P5BEK0TLg2dX3gETNNNECPoe92h4OVMaDn3Xo/0QdjgG/EvM.hiVV1BdIGklSI14HA38Mpe5k04juR5/EXMU0r1WtsLhNXwKBlf2zEfoOh0zVmDvqInpU695f29Iy7sNW3U5RIogcs740oUp2Kdv5wuITwnIx84cnO.e467/IV1lPnvMCr0pd1dgS0a.RV5eBJr03Q65Xy61R",
+ "2",
+ NULL }, 0 },
+ { { "F//////////oG/QeY5emZJ4ncABWDmSqIa2JWYAPynq0Wk.fZiJco9HIWXvZZG4tU.L6RFDEaCRC2iARV9V53TFuJLjRL72HUI5jNPYNdx6z4n2wQOtxMiB/rosz0QtxUuuQ/jQYP.bhfya4NnB7.P9A6PHxEPJWV//////////",
+ "5",
+ "oakley prime 2" }, 0 },
+ { { "Ewl2hcjiutMd3Fu2lgFnUXWSc67TVyy2vwYCKoS9MLsrdJVT9RgWTCuEqWJrfB6uE3LsE9GkOlaZabS7M29sj5TnzUqOLJMjiwEzArfiLr9WbMRANlF68N5AVLcPWvNx6Zjl3m5Scp0BzJBz9TkgfhzKJZ.WtP3Mv/67I/0wmRZ",
+ "2",
+ NULL }, 0 },
+};
+
+_TYPE( int )
+t_getprecount()
+{
+ return (sizeof(pre_params) / sizeof(struct pre_struct));
+}
+
+static struct t_confent sysconf;
+
+/* id is index origin 1 */
+
+_TYPE( struct t_confent * )
+gettcid
+(id)
+ int id;
+{
+ struct t_preconf *tcp;
+
+ if (id <= 0 || id > t_getprecount()) {
+ return NULL;
+ }
+ tcp = t_getpreparam(id - 1);
+ sysconf.index = id;
+ sysconf.modulus = tcp->modulus;
+ sysconf.generator = tcp->generator;
+
+ return &sysconf;
+}
+
+_TYPE( struct t_preconf * )
+t_getpreparam(idx)
+ int idx;
+{
+ if(pre_params[idx].state == 0) {
+ /* Wire up storage */
+ pre_params[idx].preconf.modulus.data = pre_params[idx].modbuf;
+ pre_params[idx].preconf.generator.data = pre_params[idx].genbuf;
+
+ /* Convert from b64 to t_num */
+ pre_params[idx].preconf.modulus.len = t_fromb64(pre_params[idx].preconf.modulus.data, pre_params[idx].preconf.mod_b64);
+ pre_params[idx].preconf.generator.len = t_fromb64(pre_params[idx].preconf.generator.data, pre_params[idx].preconf.gen_b64);
+
+ pre_params[idx].state = 1;
+ }
+ return &(pre_params[idx].preconf);
+}
diff --git a/package/ead/src/tinysrp/t_getpass.c b/package/ead/src/tinysrp/t_getpass.c
new file mode 100644
index 000000000..6ae7fca4d
--- /dev/null
+++ b/package/ead/src/tinysrp/t_getpass.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright 1990 - 1995, Julianne Frances Haugh
+ * 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 Julianne F. Haugh 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 JULIE HAUGH 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 JULIE HAUGH 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.
+ */
+
+#include "t_defines.h"
+#ifdef _WIN32
+#include <windows.h>
+#include <io.h>
+#endif /* _WIN32 */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <signal.h>
+#include <stdio.h>
+
+static int sig_caught;
+#ifdef HAVE_SIGACTION
+static struct sigaction sigact;
+#endif
+
+/*ARGSUSED*/
+static RETSIGTYPE
+sig_catch (sig)
+int sig;
+{
+ sig_caught = 1;
+}
+
+_TYPE( int )
+t_getpass (buf, maxlen, prompt)
+ char *buf;
+ unsigned maxlen;
+ const char *prompt;
+{
+ char *cp;
+#ifdef _WIN32
+ HANDLE handle = (HANDLE) _get_osfhandle(_fileno(stdin));
+ DWORD mode;
+
+ GetConsoleMode( handle, &mode );
+ SetConsoleMode( handle, mode & ~ENABLE_ECHO_INPUT );
+
+ if(fputs(prompt, stdout) == EOF ||
+ fgets(buf, maxlen, stdin) == NULL) {
+ SetConsoleMode(handle,mode);
+ return -1;
+ }
+ cp = buf + strlen(buf) - 1;
+ if ( *cp == 0x0a )
+ *cp = '\0';
+ printf("\n");
+ SetConsoleMode(handle,mode);
+#else
+ FILE *fp;
+ int tty_opened = 0;
+
+#ifdef HAVE_SIGACTION
+ struct sigaction old_sigact;
+#else
+ RETSIGTYPE (*old_signal)();
+#endif
+ TERMIO new_modes;
+ TERMIO old_modes;
+
+ /*
+ * set a flag so the SIGINT signal can be re-sent if it
+ * is caught
+ */
+
+ sig_caught = 0;
+
+ /*
+ * if /dev/tty can't be opened, getpass() needs to read
+ * from stdin instead.
+ */
+
+ if ((fp = fopen ("/dev/tty", "r")) == 0) {
+ fp = stdin;
+ setbuf (fp, (char *) 0);
+ } else {
+ tty_opened = 1;
+ }
+
+ /*
+ * the current tty modes must be saved so they can be
+ * restored later on. echo will be turned off, except
+ * for the newline character (BSD has to punt on this)
+ */
+
+ if (GTTY (fileno (fp), &new_modes))
+ return -1;
+
+ old_modes = new_modes;
+
+#ifdef HAVE_SIGACTION
+ sigact.sa_handler = sig_catch;
+ (void) sigaction (SIGINT, &sigact, &old_sigact);
+#else
+ old_signal = signal (SIGINT, sig_catch);
+#endif
+
+#ifdef USE_SGTTY
+ new_modes.sg_flags &= ~ECHO;
+#else
+ new_modes.c_iflag &= ~IGNCR;
+ new_modes.c_iflag |= ICRNL;
+ new_modes.c_oflag |= OPOST|ONLCR;
+ new_modes.c_lflag &= ~(ECHO|ECHOE|ECHOK);
+ new_modes.c_lflag |= ICANON|ECHONL;
+#endif
+
+ if (STTY (fileno (fp), &new_modes))
+ goto out;
+
+ /*
+ * the prompt is output, and the response read without
+ * echoing. the trailing newline must be removed. if
+ * the fgets() returns an error, a NULL pointer is
+ * returned.
+ */
+
+ if (fputs (prompt, stdout) == EOF)
+ goto out;
+
+ (void) fflush (stdout);
+
+ if (fgets (buf, maxlen, fp) == buf) {
+ if ((cp = strchr (buf, '\n')))
+ *cp = '\0';
+ else
+ buf[maxlen - 1] = '\0';
+
+#ifdef USE_SGTTY
+ putc ('\n', stdout);
+#endif
+ }
+ else buf[0] = '\0';
+out:
+ /*
+ * the old SIGINT handler is restored after the tty
+ * modes. then /dev/tty is closed if it was opened in
+ * the beginning. finally, if a signal was caught it
+ * is sent to this process for normal processing.
+ */
+
+ if (STTY (fileno (fp), &old_modes))
+ { memset (buf, 0, maxlen); return -1; }
+
+#ifdef HAVE_SIGACTION
+ (void) sigaction (SIGINT, &old_sigact, NULL);
+#else
+ (void) signal (SIGINT, old_signal);
+#endif
+
+ if (tty_opened)
+ (void) fclose (fp);
+
+ if (sig_caught) {
+ kill (getpid (), SIGINT);
+ memset (buf, 0, maxlen);
+ return -1;
+ }
+#endif
+
+ return 0;
+}
diff --git a/package/ead/src/tinysrp/t_math.c b/package/ead/src/tinysrp/t_math.c
new file mode 100644
index 000000000..20161a011
--- /dev/null
+++ b/package/ead/src/tinysrp/t_math.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 1997-1999 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following conditions apply:
+ *
+ * 1. Any software that incorporates the SRP authentication technology
+ * must display the following acknowlegment:
+ * "This product uses the 'Secure Remote Password' cryptographic
+ * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
+ *
+ * 2. Any software that incorporates all or part of the SRP distribution
+ * itself must also display the following acknowledgment:
+ * "This product includes software developed by Tom Wu and Eugene
+ * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
+ *
+ * 3. Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice and list of conditions.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "config.h"
+
+#include "bn.h"
+typedef BIGNUM * BigInteger;
+#define MATH_PRIV
+
+#include "t_defines.h"
+#include "t_pwd.h"
+
+/* Math library interface stubs */
+
+BigInteger
+BigIntegerFromInt(n)
+ unsigned int n;
+{
+ BIGNUM * a = BN_new();
+ BN_set_word(a, n);
+ return a;
+}
+
+BigInteger
+BigIntegerFromBytes(bytes, length)
+ unsigned char * bytes;
+ int length;
+{
+ BIGNUM * a = BN_new();
+ BN_bin2bn(bytes, length, a);
+ return a;
+}
+
+int
+BigIntegerToBytes(src, dest)
+ BigInteger src;
+ unsigned char * dest;
+{
+ return BN_bn2bin(src, dest);
+}
+
+int
+BigIntegerCmp(c1, c2)
+ BigInteger c1, c2;
+{
+ return BN_cmp(c1, c2);
+}
+
+int
+BigIntegerCmpInt(c1, c2)
+ BigInteger c1;
+ unsigned int c2;
+{
+ BIGNUM * a = BN_new();
+ int rv;
+ BN_set_word(a, c2);
+ rv = BN_cmp(c1, a);
+ BN_free(a);
+ return rv;
+}
+
+void
+BigIntegerAdd(result, a1, a2)
+ BigInteger result, a1, a2;
+{
+ BN_add(result, a1, a2);
+}
+
+void
+BigIntegerAddInt(result, a1, a2)
+ BigInteger result, a1;
+ unsigned int a2;
+{
+ BIGNUM * a = BN_new();
+ BN_set_word(a, a2);
+ BN_add(result, a1, a);
+ BN_free(a);
+}
+
+void
+BigIntegerSub(result, s1, s2)
+ BigInteger result, s1, s2;
+{
+ BN_sub(result, s1, s2);
+}
+
+void
+BigIntegerMulInt(result, m1, m2)
+ BigInteger result, m1;
+ unsigned int m2;
+{
+ BN_CTX * ctx = BN_CTX_new();
+ BIGNUM * m = BN_new();
+ BN_set_word(m, m2);
+ BN_mul(result, m1, m, ctx);
+ BN_CTX_free(ctx);
+}
+
+void
+BigIntegerModMul(r, m1, m2, modulus)
+ BigInteger r, m1, m2, modulus;
+{
+ BN_CTX * ctx = BN_CTX_new();
+ BN_mod_mul(r, m1, m2, modulus, ctx);
+ BN_CTX_free(ctx);
+}
+
+void
+BigIntegerModExp(r, b, e, m)
+ BigInteger r, b, e, m;
+{
+ BN_CTX * ctx = BN_CTX_new();
+ BN_mod_exp(r, b, e, m, ctx);
+ BN_CTX_free(ctx);
+}
+
+void
+BigIntegerModExpInt(r, b, e, m)
+ BigInteger r, b;
+ unsigned int e;
+ BigInteger m;
+{
+ BN_CTX * ctx = BN_CTX_new();
+ BIGNUM * p = BN_new();
+ BN_set_word(p, e);
+ BN_mod_exp(r, b, p, m, ctx);
+ BN_free(p);
+ BN_CTX_free(ctx);
+}
+
+void
+BigIntegerFree(b)
+ BigInteger b;
+{
+ BN_free(b);
+}
diff --git a/package/ead/src/tinysrp/t_misc.c b/package/ead/src/tinysrp/t_misc.c
new file mode 100644
index 000000000..a23986f90
--- /dev/null
+++ b/package/ead/src/tinysrp/t_misc.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 1997-1999 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following conditions apply:
+ *
+ * 1. Any software that incorporates the SRP authentication technology
+ * must display the following acknowlegment:
+ * "This product uses the 'Secure Remote Password' cryptographic
+ * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
+ *
+ * 2. Any software that incorporates all or part of the SRP distribution
+ * itself must also display the following acknowledgment:
+ * "This product includes software developed by Tom Wu and Eugene
+ * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
+ *
+ * 3. Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice and list of conditions.
+ */
+
+#include "t_defines.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "t_sha.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+static unsigned char randpool[SHA_DIGESTSIZE], randout[SHA_DIGESTSIZE];
+static unsigned long randcnt = 0;
+static unsigned int outpos = 0;
+SHA1_CTX randctxt;
+
+/*
+ * t_envhash - Generate a 160-bit SHA hash of the environment
+ *
+ * This routine performs an SHA hash of all the "name=value" pairs
+ * in the environment concatenated together and dumps them in the
+ * output. While it is true that anyone on the system can see
+ * your environment, someone not on the system will have a very
+ * difficult time guessing it, especially since some systems play
+ * tricks with variable ordering and sometimes define quirky
+ * environment variables like $WINDOWID or $_.
+ */
+extern char ** environ;
+
+static void
+t_envhash(out)
+ unsigned char * out;
+{
+ char ** ptr;
+ char ebuf[256];
+ SHA1_CTX ctxt;
+
+ SHA1Init(&ctxt);
+ for(ptr = environ; *ptr; ++ptr) {
+ strncpy(ebuf, *ptr, 255);
+ ebuf[255] = '\0';
+ SHA1Update(&ctxt, ebuf, strlen(ebuf));
+ }
+ SHA1Final(out, &ctxt);
+}
+
+/*
+ * t_fshash - Generate a 160-bit SHA hash from the file system
+ *
+ * This routine climbs up the directory tree from the current
+ * directory, running stat() on each directory until it hits the
+ * root directory. This information is sensitive to the last
+ * access/modification times of all the directories above you,
+ * so someone who lists one of those directories injects some
+ * entropy into the system. Obviously, this hash is very sensitive
+ * to your current directory when the program is run.
+ *
+ * For good measure, it also performs an fstat on the standard input,
+ * usually your tty, throws that into the buffer, creates a file in
+ * /tmp (the inode is unpredictable on a busy system), and runs stat()
+ * on that before deleting it.
+ *
+ * The entire buffer is run once through SHA to obtain the final result.
+ */
+static void
+t_fshash(out)
+ unsigned char * out;
+{
+ char dotpath[128];
+ struct stat st;
+ SHA1_CTX ctxt;
+ int i, pinode;
+ dev_t pdev;
+
+ SHA1Init(&ctxt);
+ if(stat(".", &st) >= 0) {
+ SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st));
+ pinode = st.st_ino;
+ pdev = st.st_dev;
+ strcpy(dotpath, "..");
+ for(i = 0; i < 40; ++i) {
+ if(stat(dotpath, &st) < 0)
+ break;
+ if(st.st_ino == pinode && st.st_dev == pdev)
+ break;
+ SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st));
+ pinode = st.st_ino;
+ pdev = st.st_dev;
+ strcat(dotpath, "/..");
+ }
+ }
+
+ if(fstat(0, &st) >= 0)
+ SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st));
+
+ sprintf(dotpath, "/tmp/rnd.%d", getpid());
+ if(creat(dotpath, 0600) >= 0 && stat(dotpath, &st) >= 0)
+ SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st));
+ unlink(dotpath);
+
+ SHA1Final(out, &ctxt);
+}
+
+/*
+ * Generate a high-entropy seed for the strong random number generator.
+ * This uses a wide variety of quickly gathered and somewhat unpredictable
+ * system information. The 'preseed' structure is assembled from:
+ *
+ * The system time in seconds
+ * The system time in microseconds
+ * The current process ID
+ * The parent process ID
+ * A hash of the user's environment
+ * A hash gathered from the file system
+ * Input from a random device, if available
+ * Timings of system interrupts
+ *
+ * The entire structure (60 bytes on most systems) is fed to SHA to produce
+ * a 160-bit seed for the strong random number generator. It is believed
+ * that in the worst case (on a quiet system with no random device versus
+ * an attacker who has access to the system already), the seed contains at
+ * least about 80 bits of entropy. Versus an attacker who does not have
+ * access to the system, the entropy should be slightly over 128 bits.
+ */
+static char initialized = 0;
+
+static struct {
+ unsigned int trand1;
+ time_t sec;
+ time_t usec;
+ short pid;
+ short ppid;
+ unsigned char envh[SHA_DIGESTSIZE];
+ unsigned char fsh[SHA_DIGESTSIZE];
+ unsigned char devrand[20];
+ unsigned int trand2;
+} preseed;
+
+unsigned long raw_truerand();
+
+void
+t_initrand()
+{
+ SHA1_CTX ctxt;
+#ifdef USE_FTIME
+ struct timeb t;
+#else
+ struct timeval t;
+#endif
+ int i, r=0;
+
+ if(initialized)
+ return;
+
+ initialized = 1;
+
+ i = open("/dev/urandom", O_RDONLY);
+ if(i > 0) {
+ r += read(i, preseed.devrand, sizeof(preseed.devrand));
+ close(i);
+ }
+
+ /* Resort to truerand only if desperate for some Real entropy */
+ if(r == 0)
+ preseed.trand1 = raw_truerand();
+
+#ifdef USE_FTIME
+ ftime(&t);
+#else
+ gettimeofday(&t, NULL);
+#endif
+
+#ifdef USE_FTIME
+ preseed.sec = t.time;
+ preseed.usec = t.millitm;
+#else
+ preseed.sec = t.tv_sec;
+ preseed.usec = t.tv_usec;
+#endif
+ preseed.pid = getpid();
+ preseed.ppid = getppid();
+ t_envhash(preseed.envh);
+ t_fshash(preseed.fsh);
+
+ if(r == 0)
+ preseed.trand2 = raw_truerand();
+
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, (unsigned char *) &preseed, sizeof(preseed));
+ SHA1Final(randpool, &ctxt);
+ outpos = 0;
+ memset((unsigned char *) &preseed, 0, sizeof(preseed));
+ memset((unsigned char *) &ctxt, 0, sizeof(ctxt));
+}
+
+#define NUM_RANDOMS 12
+
+/*
+ * The strong random number generator. This uses a 160-bit seed
+ * and uses SHA-1 in a feedback configuration to generate successive
+ * outputs. If S[0] is set to the initial seed, then:
+ *
+ * S[i+1] = SHA-1(i || S[i])
+ * A[i] = SHA-1(S[i])
+ *
+ * where the A[i] are the output blocks starting with i=0.
+ * Each cycle generates 20 bytes of new output.
+ */
+_TYPE( void )
+t_random(data, size)
+ unsigned char * data;
+ unsigned size;
+{
+ if(!initialized)
+ t_initrand();
+
+ if(size <= 0) /* t_random(NULL, 0) forces seed initialization */
+ return;
+
+ while(size > outpos) {
+ if(outpos > 0) {
+ memcpy(data, randout + (sizeof(randout) - outpos), outpos);
+ data += outpos;
+ size -= outpos;
+ }
+
+ /* Recycle */
+ SHA1Init(&randctxt);
+ SHA1Update(&randctxt, randpool, sizeof(randpool));
+ SHA1Final(randout, &randctxt);
+ SHA1Init(&randctxt);
+ SHA1Update(&randctxt, (unsigned char *) &randcnt, sizeof(randcnt));
+ SHA1Update(&randctxt, randpool, sizeof(randpool));
+ SHA1Final(randpool, &randctxt);
+ ++randcnt;
+ outpos = sizeof(randout);
+ }
+
+ if(size > 0) {
+ memcpy(data, randout + (sizeof(randout) - outpos), size);
+ outpos -= size;
+ }
+}
+
+/*
+ * The interleaved session-key hash. This separates the even and the odd
+ * bytes of the input (ignoring the first byte if the input length is odd),
+ * hashes them separately, and re-interleaves the two outputs to form a
+ * single 320-bit value.
+ */
+_TYPE( unsigned char * )
+t_sessionkey(key, sk, sklen)
+ unsigned char * key;
+ unsigned char * sk;
+ unsigned sklen;
+{
+ unsigned i, klen;
+ unsigned char * hbuf;
+ unsigned char hout[SHA_DIGESTSIZE];
+ SHA1_CTX ctxt;
+
+ while(sklen > 0 && *sk == 0) { /* Skip leading 0's */
+ --sklen;
+ ++sk;
+ }
+
+ klen = sklen / 2;
+ if((hbuf = malloc(klen * sizeof(char))) == 0)
+ return 0;
+
+ for(i = 0; i < klen; ++i)
+ hbuf[i] = sk[sklen - 2 * i - 1];
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, hbuf, klen);
+ SHA1Final(hout, &ctxt);
+ for(i = 0; i < sizeof(hout); ++i)
+ key[2 * i] = hout[i];
+
+ for(i = 0; i < klen; ++i)
+ hbuf[i] = sk[sklen - 2 * i - 2];
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, hbuf, klen);
+ SHA1Final(hout, &ctxt);
+ for(i = 0; i < sizeof(hout); ++i)
+ key[2 * i + 1] = hout[i];
+
+ memset(hout, 0, sizeof(hout));
+ memset(hbuf, 0, klen);
+ free(hbuf);
+ return key;
+}
diff --git a/package/ead/src/tinysrp/t_pw.c b/package/ead/src/tinysrp/t_pw.c
new file mode 100644
index 000000000..18e929bb7
--- /dev/null
+++ b/package/ead/src/tinysrp/t_pw.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 1997-2000 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following conditions apply:
+ *
+ * 1. Any software that incorporates the SRP authentication technology
+ * must display the following acknowlegment:
+ * "This product uses the 'Secure Remote Password' cryptographic
+ * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
+ *
+ * 2. Any software that incorporates all or part of the SRP distribution
+ * itself must also display the following acknowledgment:
+ * "This product includes software developed by Tom Wu and Eugene
+ * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
+ *
+ * 3. Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice and list of conditions.
+ */
+
+#include "t_defines.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef USE_HOMEDIR
+#include <pwd.h>
+#endif
+#ifdef WIN32
+#include <io.h>
+#endif
+
+#include "t_pwd.h"
+#include "t_read.h"
+#include "t_sha.h"
+#include "t_server.h"
+
+static struct t_pw * syspw = NULL;
+static struct t_passwd tpass;
+
+_TYPE( struct t_server * )
+t_serveropen(username)
+ const char * username;
+{
+ struct t_passwd * p;
+ p = gettpnam(username);
+ if(p == NULL) {
+ return NULL;
+ } else {
+ return t_serveropenraw(&p->tp, &p->tc);
+ }
+}
+
+
+/* t_openpw(NULL) is deprecated - use settpent()/gettpnam() instead */
+
+_TYPE( struct t_pw * )
+t_openpw(fp)
+ FILE * fp;
+{
+ struct t_pw * tpw;
+ char close_flag = 0;
+
+ if(fp == NULL) { /* Deprecated */
+ if((fp = fopen(DEFAULT_PASSWD, "r")) == NULL)
+ return NULL;
+ close_flag = 1;
+ }
+ else
+ close_flag = 0;
+
+ if((tpw = malloc(sizeof(struct t_pw))) == NULL)
+ return NULL;
+ tpw->instream = fp;
+ tpw->close_on_exit = close_flag;
+ tpw->state = FILE_ONLY;
+
+ return tpw;
+}
+
+_TYPE( struct t_pw * )
+t_openpwbyname(pwname)
+ const char * pwname;
+{
+ FILE * fp;
+ struct t_pw * t;
+
+ if(pwname == NULL) /* Deprecated */
+ return t_openpw(NULL);
+
+ if((fp = fopen(pwname, "r")) == NULL)
+ return NULL;
+
+ t = t_openpw(fp);
+ t->close_on_exit = 1;
+ return t;
+}
+
+_TYPE( void )
+t_closepw(tpw)
+ struct t_pw * tpw;
+{
+ if(tpw->close_on_exit)
+ fclose(tpw->instream);
+ free(tpw);
+}
+
+_TYPE( void )
+t_rewindpw(tpw)
+ struct t_pw * tpw;
+{
+#ifdef ENABLE_YP
+ if(tpw->state == IN_NIS)
+ tpw->state = FILE_NIS;
+#endif
+ rewind(tpw->instream);
+}
+
+#ifdef ENABLE_YP
+static void
+savepwent(tpw, pwent)
+ struct t_pw * tpw;
+ struct t_pwent *pwent;
+{
+ tpw->pebuf.name = tpw->userbuf;
+ tpw->pebuf.password.data = tpw->pwbuf;
+ tpw->pebuf.salt.data = tpw->saltbuf;
+ strcpy(tpw->pebuf.name, pwent->name);
+ tpw->pebuf.password.len = pwent->password.len;
+ memcpy(tpw->pebuf.password.data, pwent->password.data, pwent->password.len);
+ tpw->pebuf.salt.len = pwent->salt.len;
+ memcpy(tpw->pebuf.salt.data, pwent->salt.data, pwent->salt.len);
+ tpw->pebuf.index = pwent->index;
+}
+#endif /* ENABLE_YP */
+
+_TYPE( struct t_pwent * )
+t_getpwbyname(tpw, user)
+ struct t_pw * tpw;
+ const char * user;
+{
+ char indexbuf[16];
+ char passbuf[MAXB64PARAMLEN];
+ char saltstr[MAXB64SALTLEN];
+ char username[MAXUSERLEN];
+#ifdef ENABLE_YP
+ struct t_passwd * nisent;
+#endif
+
+ t_rewindpw(tpw);
+
+ while(t_nextfield(tpw->instream, username, MAXUSERLEN) > 0) {
+#ifdef ENABLE_YP
+ if(tpw->state == FILE_NIS && *username == '+') {
+ if(strlen(username) == 1 || strcmp(user, username+1) == 0) {
+ nisent = _yp_gettpnam(user); /* Entry is +username or + */
+ if(nisent != NULL) {
+ savepwent(tpw, &nisent->tp);
+ return &tpw->pebuf;
+ }
+ }
+ }
+#endif
+ if(strcmp(user, username) == 0)
+ if(t_nextfield(tpw->instream, passbuf, MAXB64PARAMLEN) > 0 &&
+ (tpw->pebuf.password.len = t_fromb64(tpw->pwbuf, passbuf)) > 0 &&
+ t_nextfield(tpw->instream, saltstr, MAXB64SALTLEN) > 0 &&
+ (tpw->pebuf.salt.len = t_fromb64(tpw->saltbuf, saltstr)) > 0 &&
+ t_nextfield(tpw->instream, indexbuf, 16) > 0 &&
+ (tpw->pebuf.index = atoi(indexbuf)) > 0) {
+ strcpy(tpw->userbuf, username);
+ tpw->pebuf.name = tpw->userbuf;
+ tpw->pebuf.password.data = tpw->pwbuf;
+ tpw->pebuf.salt.data = tpw->saltbuf;
+ t_nextline(tpw->instream);
+ return &tpw->pebuf;
+ }
+ if(t_nextline(tpw->instream) < 0)
+ return NULL;
+ }
+ return NULL;
+}
+
+/* System password file accessors */
+
+static int
+pwinit()
+{
+ if(syspw == NULL) {
+ if((syspw = t_openpwbyname(DEFAULT_PASSWD)) == NULL)
+ return -1;
+ syspw->state = FILE_NIS;
+ }
+ return 0;
+}
+
+static void
+pwsetup(out, tpwd, tcnf)
+ struct t_passwd * out;
+ struct t_pwent * tpwd;
+ struct t_confent * tcnf;
+{
+ out->tp.name = tpwd->name;
+ out->tp.password.len = tpwd->password.len;
+ out->tp.password.data = tpwd->password.data;
+ out->tp.salt.len = tpwd->salt.len;
+ out->tp.salt.data = tpwd->salt.data;
+ out->tp.index = tpwd->index;
+
+ out->tc.index = tcnf->index;
+ out->tc.modulus.len = tcnf->modulus.len;
+ out->tc.modulus.data = tcnf->modulus.data;
+ out->tc.generator.len = tcnf->generator.len;
+ out->tc.generator.data = tcnf->generator.data;
+}
+
+_TYPE( struct t_passwd * )
+gettpnam
+(user)
+ const char * user;
+{
+ struct t_pwent * tpptr;
+ struct t_confent * tcptr;
+
+ if(pwinit() < 0)
+ return NULL;
+ tpptr = t_getpwbyname(syspw, user);
+ if(tpptr == NULL)
+ return NULL;
+ tcptr =
+ gettcid
+ (tpptr->index);
+ if(tcptr == NULL)
+ return NULL;
+ pwsetup(&tpass, tpptr, tcptr);
+ return &tpass;
+}
diff --git a/package/ead/src/tinysrp/t_pwd.h b/package/ead/src/tinysrp/t_pwd.h
new file mode 100644
index 000000000..73697bef3
--- /dev/null
+++ b/package/ead/src/tinysrp/t_pwd.h
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 1997-1999 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following conditions apply:
+ *
+ * 1. Any software that incorporates the SRP authentication technology
+ * must display the following acknowlegment:
+ * "This product uses the 'Secure Remote Password' cryptographic
+ * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
+ *
+ * 2. Any software that incorporates all or part of the SRP distribution
+ * itself must also display the following acknowledgment:
+ * "This product includes software developed by Tom Wu and Eugene
+ * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
+ *
+ * 3. Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice and list of conditions.
+ */
+
+#ifndef T_PWD_H
+#define T_PWD_H
+
+#ifndef P
+#if defined (__STDC__) || defined (__cplusplus)
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+#endif
+
+/* For building dynamic link libraries under windows, windows NT
+ * using MSVC1.5 or MSVC2.0
+ */
+
+#ifndef _DLLDECL
+#define _DLLDECL
+
+#ifdef MSVC15 /* MSVC1.5 support for 16 bit apps */
+#define _MSVC15EXPORT _export
+#define _MSVC20EXPORT
+#define _DLLAPI _export _pascal
+#define _TYPE(a) a _MSVC15EXPORT
+#define DLLEXPORT 1
+
+#elif MSVC20
+#define _MSVC15EXPORT
+#define _MSVC20EXPORT _declspec(dllexport)
+#define _DLLAPI
+#define _TYPE(a) _MSVC20EXPORT a
+#define DLLEXPORT 1
+
+#else /* Default, non-dll. Use this for Unix or DOS */
+#define _MSVC15DEXPORT
+#define _MSVC20EXPORT
+#define _DLLAPI
+#define _TYPE(a) a
+#endif
+#endif
+
+#define MAXPARAMBITS 2048
+#define MAXPARAMLEN ((MAXPARAMBITS + 7) / 8)
+#define MAXB64PARAMLEN ((MAXPARAMBITS + 5) / 6 + 1)
+#define MAXHEXPARAMLEN ((MAXPARAMBITS + 3) / 4 + 1)
+#define MAXOCTPARAMLEN ((MAXPARAMBITS + 2) / 3 + 1)
+
+#define MAXUSERLEN 32
+#define MAXSALTLEN 32
+#define MAXB64SALTLEN 44 /* 256 bits in b64 + null */
+#define SALTLEN 10 /* Normally 80 bits */
+
+#define RESPONSE_LEN 20 /* 160-bit proof hashes */
+#define SESSION_KEY_LEN (2 * RESPONSE_LEN) /* 320-bit session key */
+
+#define DEFAULT_PASSWD "tpasswd"
+
+struct t_num { /* Standard byte-oriented integer representation */
+ int len;
+ unsigned char * data;
+};
+
+struct t_preconf { /* Structure returned by t_getpreparam() */
+ char * mod_b64;
+ char * gen_b64;
+ char * comment;
+
+ struct t_num modulus;
+ struct t_num generator;
+};
+
+/*
+ * The built-in (known good) parameters access routines
+ *
+ * "t_getprecount" returns the number of precompiled parameter sets.
+ * "t_getpreparam" returns the indicated parameter set.
+ * Memory is statically allocated - callers need not perform any memory mgmt.
+ */
+_TYPE( int ) t_getprecount();
+_TYPE( struct t_preconf * ) t_getpreparam P((int));
+
+struct t_confent { /* One configuration file entry (index, N, g) */
+ int index;
+ struct t_num modulus;
+ struct t_num generator;
+};
+
+struct t_conf { /* An open configuration file */
+ FILE * instream;
+ char close_on_exit;
+ unsigned char modbuf[MAXPARAMLEN];
+ unsigned char genbuf[MAXPARAMLEN];
+ struct t_confent tcbuf;
+};
+
+/*
+ * The configuration file routines are designed along the lines of the
+ * "getpw" functions in the standard C library.
+ *
+ * "t_openconf" accepts a stdio stream and interprets it as a config file.
+ * "t_openconfbyname" accepts a filename and does the same thing.
+ * "t_closeconf" closes the config file.
+ * "t_getconfent" fetches the next sequential configuration entry.
+ * "t_getconfbyindex" fetches the configuration entry whose index
+ * matches the one supplied, or NULL if one can't be found.
+ * "t_getconflast" fetches the last configuration entry in the file.
+ * "t_makeconfent" generates a set of configuration entry parameters
+ * randomly.
+ * "t_newconfent" returns an empty configuration entry.
+ * "t_cmpconfent" compares two configuration entries a la strcmp.
+ * "t_checkconfent" verifies that a set of configuration parameters
+ * are suitable. N must be prime and should be a safe prime.
+ * "t_putconfent" writes a configuration entry to a stream.
+ */
+_TYPE( struct t_conf * ) t_openconf P((FILE *));
+_TYPE( struct t_conf * ) t_openconfbyname P((const char *));
+_TYPE( void ) t_closeconf P((struct t_conf *));
+_TYPE( void ) t_rewindconf P((struct t_conf *));
+_TYPE( struct t_confent * ) t_getconfent P((struct t_conf *));
+_TYPE( struct t_confent * ) t_getconfbyindex P((struct t_conf *, int));
+_TYPE( struct t_confent * ) t_getconflast P((struct t_conf *));
+_TYPE( struct t_confent * ) t_makeconfent P((struct t_conf *, int));
+_TYPE( struct t_confent * ) t_makeconfent_c P((struct t_conf *, int));
+_TYPE( struct t_confent * ) t_newconfent P((struct t_conf *));
+_TYPE( int ) t_cmpconfent P((const struct t_confent *, const struct t_confent *));
+_TYPE( int ) t_checkconfent P((const struct t_confent *));
+_TYPE( void ) t_putconfent P((const struct t_confent *, FILE *));
+
+/* libc-style system conf file access */
+_TYPE( struct t_confent *) gettcent();
+_TYPE( struct t_confent *) gettcid P((int));
+_TYPE( void ) settcent();
+_TYPE( void ) endtcent();
+
+#ifdef ENABLE_NSW
+extern struct t_confent * _gettcent();
+extern struct t_confent * _gettcid P((int));
+extern void _settcent();
+extern void _endtcent();
+#endif
+
+/* A hack to support '+'-style entries in the passwd file */
+
+typedef enum fstate {
+ FILE_ONLY, /* Ordinary file, don't consult NIS ever */
+ FILE_NIS, /* Currently accessing file, use NIS if encountered */
+ IN_NIS, /* Currently in a '+' entry; use NIS for getXXent */
+} FILE_STATE;
+
+struct t_pwent { /* A single password file entry */
+ char * name;
+ struct t_num password;
+ struct t_num salt;
+ int index;
+};
+
+struct t_pw { /* An open password file */
+ FILE * instream;
+ char close_on_exit;
+ FILE_STATE state;
+ char userbuf[MAXUSERLEN];
+ unsigned char pwbuf[MAXPARAMLEN];
+ unsigned char saltbuf[SALTLEN];
+ struct t_pwent pebuf;
+};
+
+/*
+ * The password manipulation routines are patterned after the getpw*
+ * standard C library function calls.
+ *
+ * "t_openpw" reads a stream as if it were a password file.
+ * "t_openpwbyname" opens the named file as a password file.
+ * "t_closepw" closes an open password file.
+ * "t_rewindpw" starts the internal file pointer from the beginning
+ * of the password file.
+ * "t_getpwent" retrieves the next sequential password entry.
+ * "t_getpwbyname" looks up the password entry corresponding to the
+ * specified user.
+ * "t_makepwent" constructs a password entry from a username, password,
+ * numeric salt, and configuration entry.
+ * "t_putpwent" writes a password entry to a stream.
+ */
+_TYPE( struct t_pw * ) t_openpw P((FILE *));
+_TYPE( struct t_pw * ) t_openpwbyname P((const char *));
+_TYPE( void ) t_closepw P((struct t_pw *));
+_TYPE( void ) t_rewindpw P((struct t_pw *));
+_TYPE( struct t_pwent * ) t_getpwent P((struct t_pw *));
+_TYPE( struct t_pwent * ) t_getpwbyname P((struct t_pw *, const char *));
+_TYPE( struct t_pwent * ) t_makepwent P((struct t_pw *, const char *,
+ const char *, const struct t_num *,
+ const struct t_confent *));
+_TYPE( void ) t_putpwent P((const struct t_pwent *, FILE *));
+
+struct t_passwd {
+ struct t_pwent tp;
+ struct t_confent tc;
+};
+
+/* libc-style system password file access */
+_TYPE( struct t_passwd * ) gettpent();
+_TYPE( struct t_passwd * ) gettpnam P((const char *));
+_TYPE( void ) settpent();
+_TYPE( void ) endtpent();
+
+#ifdef ENABLE_NSW
+extern struct t_passwd * _gettpent();
+extern struct t_passwd * _gettpnam P((const char *));
+extern void _settpent();
+extern void _endtpent();
+#endif
+
+/*
+ * Utility functions
+ *
+ * "t_verifypw" accepts a username and password, and checks against the
+ * system password file to see if the password for that user is correct.
+ * Returns > 0 if it is correct, 0 if not, and -1 if some error occurred
+ * (i.e. the user doesn't exist on the system). This is intended ONLY
+ * for local authentication; for remote authentication, look at the
+ * t_client and t_server source. (That's the whole point of SRP!)
+ * "t_changepw" modifies the specified file, substituting the given password
+ * entry for the one already in the file. If no matching entry is found,
+ * the new entry is simply appended to the file.
+ * "t_deletepw" removes the specified user from the specified file.
+ */
+_TYPE( int ) t_verifypw P((const char *, const char *));
+_TYPE( int ) t_changepw P((const char *, const struct t_pwent *));
+_TYPE( int ) t_deletepw P((const char *, const char *));
+
+/* Conversion utilities */
+
+/*
+ * All these calls accept output as the first parameter. In the case of
+ * t_tohex and t_tob64, the last argument is the length of the byte-string
+ * input.
+ */
+_TYPE( char * t_tohex ) P((char *, char *, unsigned));
+_TYPE( int ) t_fromhex P((char *, char *));
+_TYPE( char * ) t_tob64 P((char *, char *, unsigned));
+_TYPE( int ) t_fromb64 P((char *, char *));
+
+/* Miscellaneous utilities */
+
+/*
+ * "t_random" is a cryptographic random number generator, which is seeded
+ * from various high-entropy sources and uses a one-way hash function
+ * in a feedback configuration.
+ * "t_sessionkey" is the interleaved hash used to generate session keys
+ * from a large integer.
+ * "t_getpass" reads a password from the terminal without echoing.
+ */
+_TYPE( void ) t_random P((unsigned char *, unsigned));
+_TYPE( void ) t_stronginitrand();
+_TYPE( unsigned char * )
+ t_sessionkey P((unsigned char *, unsigned char *, unsigned));
+_TYPE( int ) t_getpass P((char *, unsigned, const char *));
+
+/*
+ * Return value of t_checkprime:
+ * < 0 : not prime
+ * = 0 : prime, but not safe
+ * > 0 : safe
+ */
+#define NUM_NOTPRIME -1
+#define NUM_NOTSAFE 0
+#define NUM_SAFE 1
+
+_TYPE( int ) t_checkprime P((const struct t_num *));
+
+#endif
diff --git a/package/ead/src/tinysrp/t_read.c b/package/ead/src/tinysrp/t_read.c
new file mode 100644
index 000000000..087b7d55b
--- /dev/null
+++ b/package/ead/src/tinysrp/t_read.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 1997-1999 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following conditions apply:
+ *
+ * 1. Any software that incorporates the SRP authentication technology
+ * must display the following acknowlegment:
+ * "This product uses the 'Secure Remote Password' cryptographic
+ * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
+ *
+ * 2. Any software that incorporates all or part of the SRP distribution
+ * itself must also display the following acknowledgment:
+ * "This product includes software developed by Tom Wu and Eugene
+ * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
+ *
+ * 3. Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice and list of conditions.
+ */
+
+#include <stdio.h>
+#include "config.h"
+
+#define FSEPARATOR ':'
+
+int
+t_nextfield(fp, s, max)
+FILE * fp;
+char * s;
+unsigned max;
+{
+ int c, count = 0;
+
+ while((c = getc(fp)) != EOF) {
+ if(c == '\n') {
+ ungetc(c, fp);
+ break;
+ }
+ else if(c == FSEPARATOR)
+ break;
+ if(count < max - 1) {
+ *s++ = c;
+ ++count;
+ }
+ }
+ *s++ = '\0';
+ return count;
+}
+
+int
+t_nextline(fp)
+FILE * fp;
+{
+ int c;
+
+ while((c = getc(fp)) != '\n')
+ if(c == EOF)
+ return -1;
+ return 0;
+}
diff --git a/package/ead/src/tinysrp/t_read.h b/package/ead/src/tinysrp/t_read.h
new file mode 100644
index 000000000..e621f793a
--- /dev/null
+++ b/package/ead/src/tinysrp/t_read.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1997-1999 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following conditions apply:
+ *
+ * 1. Any software that incorporates the SRP authentication technology
+ * must display the following acknowlegment:
+ * "This product uses the 'Secure Remote Password' cryptographic
+ * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
+ *
+ * 2. Any software that incorporates all or part of the SRP distribution
+ * itself must also display the following acknowledgment:
+ * "This product includes software developed by Tom Wu and Eugene
+ * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
+ *
+ * 3. Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice and list of conditions.
+ */
+
+#ifndef _T_READ_H_
+#define _T_READ_H_
+
+#if !defined(P)
+#ifdef __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+#endif
+
+extern int t_nextfield P((FILE *, char *, unsigned));
+extern int t_nextline P((FILE *));
+#endif
diff --git a/package/ead/src/tinysrp/t_server.c b/package/ead/src/tinysrp/t_server.c
new file mode 100644
index 000000000..6ab501bcb
--- /dev/null
+++ b/package/ead/src/tinysrp/t_server.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 1997-1999 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following conditions apply:
+ *
+ * 1. Any software that incorporates the SRP authentication technology
+ * must display the following acknowlegment:
+ * "This product uses the 'Secure Remote Password' cryptographic
+ * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
+ *
+ * 2. Any software that incorporates all or part of the SRP distribution
+ * itself must also display the following acknowledgment:
+ * "This product includes software developed by Tom Wu and Eugene
+ * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
+ *
+ * 3. Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice and list of conditions.
+ */
+
+#include <stdio.h>
+#include "t_defines.h"
+#include "t_pwd.h"
+#include "t_server.h"
+
+_TYPE( struct t_server * )
+t_serveropenraw(ent, tce)
+ struct t_pwent * ent;
+ struct t_confent * tce;
+{
+ struct t_server * ts;
+ unsigned char buf1[SHA_DIGESTSIZE], buf2[SHA_DIGESTSIZE];
+ SHA1_CTX ctxt;
+ int i;
+
+ if((ts = malloc(sizeof(struct t_server))) == 0)
+ return 0;
+
+ SHA1Init(&ts->ckhash);
+
+ ts->index = ent->index;
+ ts->n.len = tce->modulus.len;
+ ts->n.data = ts->nbuf;
+ memcpy(ts->n.data, tce->modulus.data, ts->n.len);
+
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, ts->n.data, ts->n.len);
+ SHA1Final(buf1, &ctxt);
+
+ ts->g.len = tce->generator.len;
+ ts->g.data = ts->gbuf;
+ memcpy(ts->g.data, tce->generator.data, ts->g.len);
+
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, ts->g.data, ts->g.len);
+ SHA1Final(buf2, &ctxt);
+
+ for(i = 0; i < sizeof(buf1); ++i)
+ buf1[i] ^= buf2[i];
+
+ SHA1Update(&ts->ckhash, buf1, sizeof(buf1));
+
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, ent->name, strlen(ent->name));
+ SHA1Final(buf1, &ctxt);
+
+ SHA1Update(&ts->ckhash, buf1, sizeof(buf1));
+
+ ts->v.len = ent->password.len;
+ ts->v.data = ts->vbuf;
+ memcpy(ts->v.data, ent->password.data, ts->v.len);
+
+ ts->s.len = ent->salt.len;
+ ts->s.data = ts->saltbuf;
+ memcpy(ts->s.data, ent->salt.data, ts->s.len);
+
+ SHA1Update(&ts->ckhash, ts->s.data, ts->s.len);
+
+ ts->b.data = ts->bbuf;
+ ts->B.data = ts->Bbuf;
+
+ SHA1Init(&ts->hash);
+ SHA1Init(&ts->oldhash);
+ SHA1Init(&ts->oldckhash);
+
+ return ts;
+}
+
+_TYPE( struct t_num * )
+t_servergenexp(ts)
+ struct t_server * ts;
+{
+ BigInteger b, B, v, n, g;
+
+ if(ts->n.len < BLEN)
+ ts->b.len = ts->n.len;
+ else
+ ts->b.len = BLEN;
+
+ t_random(ts->b.data, ts->b.len);
+ b = BigIntegerFromBytes(ts->b.data, ts->b.len);
+ n = BigIntegerFromBytes(ts->n.data, ts->n.len);
+ g = BigIntegerFromBytes(ts->g.data, ts->g.len);
+ B = BigIntegerFromInt(0);
+ BigIntegerModExp(B, g, b, n);
+
+ v = BigIntegerFromBytes(ts->v.data, ts->v.len);
+ BigIntegerAdd(B, B, v);
+ if(BigIntegerCmp(B, n) > 0)
+ BigIntegerSub(B, B, n);
+
+ ts->B.len = BigIntegerToBytes(B, ts->B.data);
+
+ BigIntegerFree(v);
+ BigIntegerFree(B);
+ BigIntegerFree(b);
+ BigIntegerFree(g);
+ BigIntegerFree(n);
+
+ SHA1Update(&ts->oldckhash, ts->B.data, ts->B.len);
+
+ return &ts->B;
+}
+
+_TYPE( unsigned char * )
+t_servergetkey(ts, clientval)
+ struct t_server * ts;
+ struct t_num * clientval;
+{
+ BigInteger n, v, A, b, prod, res, S;
+ SHA1_CTX ctxt;
+ unsigned char sbuf[MAXPARAMLEN];
+ unsigned char dig[SHA_DIGESTSIZE];
+ unsigned slen;
+ unsigned int u;
+
+ SHA1Update(&ts->ckhash, clientval->data, clientval->len);
+ SHA1Update(&ts->ckhash, ts->B.data, ts->B.len);
+
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, ts->B.data, ts->B.len);
+ SHA1Final(dig, &ctxt);
+ u = (dig[0] << 24) | (dig[1] << 16) | (dig[2] << 8) | dig[3];
+
+ SHA1Update(&ts->oldhash, clientval->data, clientval->len);
+ SHA1Update(&ts->hash, clientval->data, clientval->len);
+
+ n = BigIntegerFromBytes(ts->n.data, ts->n.len);
+ b = BigIntegerFromBytes(ts->b.data, ts->b.len);
+ v = BigIntegerFromBytes(ts->v.data, ts->v.len);
+ A = BigIntegerFromBytes(clientval->data, clientval->len);
+
+ prod = BigIntegerFromInt(0);
+ BigIntegerModExpInt(prod, v, u, n);
+ res = BigIntegerFromInt(0);
+ BigIntegerModMul(res, prod, A, n);
+
+ BigIntegerFree(A);
+ BigIntegerFree(v);
+ BigIntegerFree(prod);
+
+ if(BigIntegerCmpInt(res, 1) <= 0) { /* Check for Av^u == 1 (mod n) */
+ BigIntegerFree(res);
+ BigIntegerFree(b);
+ BigIntegerFree(n);
+ return NULL;
+ }
+
+ S = BigIntegerFromInt(0);
+
+ BigIntegerAddInt(S, res, 1);
+ if(BigIntegerCmp(S, n) == 0) { /* Check for Av^u == -1 (mod n) */
+ BigIntegerFree(res);
+ BigIntegerFree(b);
+ BigIntegerFree(n);
+ BigIntegerFree(S);
+ return NULL;
+ }
+
+ BigIntegerModExp(S, res, b, n);
+ slen = BigIntegerToBytes(S, sbuf);
+
+ BigIntegerFree(S);
+ BigIntegerFree(res);
+ BigIntegerFree(b);
+ BigIntegerFree(n);
+
+ t_sessionkey(ts->session_key, sbuf, slen);
+ memset(sbuf, 0, slen);
+
+ SHA1Update(&ts->oldhash, ts->session_key, sizeof(ts->session_key));
+ SHA1Update(&ts->oldckhash, ts->session_key, sizeof(ts->session_key));
+ SHA1Update(&ts->ckhash, ts->session_key, sizeof(ts->session_key));
+
+ return ts->session_key;
+}
+
+_TYPE( int )
+t_serververify(ts, resp)
+ struct t_server * ts;
+ unsigned char * resp;
+{
+ unsigned char expected[SHA_DIGESTSIZE];
+ int i;
+
+ SHA1Final(expected, &ts->oldckhash);
+ i = memcmp(expected, resp, sizeof(expected));
+ if(i == 0) {
+ SHA1Final(ts->session_response, &ts->oldhash);
+ return 0;
+ }
+ SHA1Final(expected, &ts->ckhash);
+ i = memcmp(expected, resp, sizeof(expected));
+ if(i == 0) {
+ SHA1Update(&ts->hash, expected, sizeof(expected));
+ SHA1Update(&ts->hash, ts->session_key, sizeof(ts->session_key));
+ SHA1Final(ts->session_response, &ts->hash);
+ }
+ return i;
+}
+
+_TYPE( unsigned char * )
+t_serverresponse(ts)
+ struct t_server * ts;
+{
+ return ts->session_response;
+}
+
+_TYPE( void )
+t_serverclose(ts)
+ struct t_server * ts;
+{
+ memset(ts->bbuf, 0, sizeof(ts->bbuf));
+ memset(ts->vbuf, 0, sizeof(ts->vbuf));
+ memset(ts->saltbuf, 0, sizeof(ts->saltbuf));
+ memset(ts->session_key, 0, sizeof(ts->session_key));
+ free(ts);
+}
diff --git a/package/ead/src/tinysrp/t_server.h b/package/ead/src/tinysrp/t_server.h
new file mode 100644
index 000000000..20970ffe0
--- /dev/null
+++ b/package/ead/src/tinysrp/t_server.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 1997-1999 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following conditions apply:
+ *
+ * 1. Any software that incorporates the SRP authentication technology
+ * must display the following acknowlegment:
+ * "This product uses the 'Secure Remote Password' cryptographic
+ * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
+ *
+ * 2. Any software that incorporates all or part of the SRP distribution
+ * itself must also display the following acknowledgment:
+ * "This product includes software developed by Tom Wu and Eugene
+ * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
+ *
+ * 3. Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice and list of conditions.
+ */
+
+#ifndef T_SERVER_H
+#define T_SERVER_H
+
+#include "t_sha.h"
+
+#if !defined(P)
+#ifdef __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+#endif
+
+#ifndef _DLLDECL
+#define _DLLDECL
+
+#ifdef MSVC15 /* MSVC1.5 support for 16 bit apps */
+#define _MSVC15EXPORT _export
+#define _MSVC20EXPORT
+#define _DLLAPI _export _pascal
+#define _TYPE(a) a _MSVC15EXPORT
+#define DLLEXPORT 1
+
+#elif MSVC20
+#define _MSVC15EXPORT
+#define _MSVC20EXPORT _declspec(dllexport)
+#define _DLLAPI
+#define _TYPE(a) _MSVC20EXPORT a
+#define DLLEXPORT 1
+
+#else /* Default, non-dll. Use this for Unix or DOS */
+#define _MSVC15DEXPORT
+#define _MSVC20EXPORT
+#define _DLLAPI
+#define _TYPE(a) a
+#endif
+#endif
+
+#define BLEN 32
+
+struct t_server {
+ int index;
+ struct t_num n;
+ struct t_num g;
+ struct t_num v;
+ struct t_num s;
+
+ struct t_num b;
+ struct t_num B;
+
+ SHA1_CTX oldhash, hash, oldckhash, ckhash;
+
+ unsigned char session_key[SESSION_KEY_LEN];
+ unsigned char session_response[RESPONSE_LEN];
+
+ unsigned char nbuf[MAXPARAMLEN], gbuf[MAXPARAMLEN], vbuf[MAXPARAMLEN];
+ unsigned char saltbuf[MAXSALTLEN], bbuf[BLEN], Bbuf[MAXPARAMLEN];
+};
+
+/*
+ * SRP server-side negotiation
+ *
+ * This code negotiates the server side of an SRP exchange.
+ * "t_serveropen" accepts a username (sent by the client), a pointer
+ * to an open password file, and a pointer to an open configuration
+ * file. The server should then call...
+ * "t_servergenexp" will generate a random 256-bit exponent and
+ * raise g (from the configuration file) to that power, returning
+ * the result. This result should be sent to the client as y(p).
+ * "t_servergetkey" accepts the exponential w(p), which should be
+ * sent by the client, and computes the 256-bit session key.
+ * This data should be saved before the session is closed.
+ * "t_serverresponse" computes the session key proof as SHA(w(p), K).
+ * "t_serverclose" closes the session and frees its memory.
+ *
+ * Note that authentication is not performed per se; it is up
+ * to either/both sides of the protocol to now verify securely
+ * that their session keys agree in order to establish authenticity.
+ * One possible way is through "oracle hashing"; one side sends
+ * r, the other replies with H(r,K), where H() is a hash function.
+ *
+ * t_serverresponse and t_serververify now implement a version of
+ * the session-key verification described above.
+ */
+_TYPE( struct t_server * )
+ t_serveropen P((const char *));
+_TYPE( struct t_server * )
+ t_serveropenfromfiles P((const char *, struct t_pw *, struct t_conf *));
+_TYPE( struct t_server * )
+ t_serveropenraw P((struct t_pwent *, struct t_confent *));
+_TYPE( struct t_num * ) t_servergenexp P((struct t_server *));
+_TYPE( unsigned char * ) t_servergetkey P((struct t_server *, struct t_num *));
+_TYPE( int ) t_serververify P((struct t_server *, unsigned char *));
+_TYPE( unsigned char * ) t_serverresponse P((struct t_server *));
+_TYPE( void ) t_serverclose P((struct t_server *));
+
+#endif
diff --git a/package/ead/src/tinysrp/t_sha.c b/package/ead/src/tinysrp/t_sha.c
new file mode 100644
index 000000000..cc41d6487
--- /dev/null
+++ b/package/ead/src/tinysrp/t_sha.c
@@ -0,0 +1,166 @@
+#include "t_defines.h"
+#include "t_sha.h"
+
+/*
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+ A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+ 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+/* #define WORDS_BIGENDIAN * This should be #define'd if true. */
+/* #define SHA1HANDSOFF * Copies data before messing with it. */
+
+#include <stdio.h>
+#include <string.h>
+
+static void SHA1Transform(uint32 state[5], const unsigned char buffer[64]);
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#ifndef WORDS_BIGENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+ |(rol(block->l[i],8)&0x00FF00FF))
+#else
+#define blk0(i) block->l[i]
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+ ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+static void SHA1Transform(uint32 state[5], const unsigned char buffer[64])
+{
+uint32 a, b, c, d, e;
+typedef union {
+ unsigned char c[64];
+ uint32 l[16];
+} CHAR64LONG16;
+CHAR64LONG16* block;
+#ifdef SHA1HANDSOFF
+static unsigned char workspace[64];
+ block = (CHAR64LONG16*)workspace;
+ memcpy(block, buffer, 64);
+#else
+ block = (CHAR64LONG16*)buffer;
+#endif
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void SHA1Init(SHA1_CTX* context)
+{
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void SHA1Update(SHA1_CTX* context, const unsigned char* data, unsigned int len)
+{
+unsigned int i, j;
+
+ j = (context->count[0] >> 3) & 63;
+ if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
+ context->count[1] += (len >> 29);
+ if ((j + len) > 63) {
+ memcpy(&context->buffer[j], data, (i = 64-j));
+ SHA1Transform(context->state, context->buffer);
+ for ( ; i + 63 < len; i += 64) {
+ SHA1Transform(context->state, &data[i]);
+ }
+ j = 0;
+ }
+ else i = 0;
+ memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/* Add padding and return the message digest. */
+
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
+{
+uint32 i, j;
+unsigned char finalcount[8];
+
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+ SHA1Update(context, (unsigned char *)"\200", 1);
+ while ((context->count[0] & 504) != 448) {
+ SHA1Update(context, (unsigned char *)"\0", 1);
+ }
+ SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
+ for (i = 0; i < 20; i++) {
+ digest[i] = (unsigned char)
+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+ /* Wipe variables */
+ i = j = 0;
+ memset(context->buffer, 0, 64);
+ memset(context->state, 0, 20);
+ memset(context->count, 0, 8);
+ memset(&finalcount, 0, 8);
+#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite its own static vars */
+ SHA1Transform(context->state, context->buffer);
+#endif
+}
diff --git a/package/ead/src/tinysrp/t_sha.h b/package/ead/src/tinysrp/t_sha.h
new file mode 100644
index 000000000..d10115e74
--- /dev/null
+++ b/package/ead/src/tinysrp/t_sha.h
@@ -0,0 +1,26 @@
+#ifndef T_SHA_H
+#define T_SHA_H
+
+#if !defined(P)
+#ifdef __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+#endif
+
+#define SHA_DIGESTSIZE 20
+
+typedef unsigned int uint32;
+
+typedef struct {
+ uint32 state[5];
+ uint32 count[2];
+ unsigned char buffer[64];
+} SHA1_CTX;
+
+void SHA1Init P((SHA1_CTX* context));
+void SHA1Update P((SHA1_CTX* context, const unsigned char* data, unsigned int len));
+void SHA1Final P((unsigned char digest[20], SHA1_CTX* context));
+
+#endif /* T_SHA_H */
diff --git a/package/ead/src/tinysrp/t_truerand.c b/package/ead/src/tinysrp/t_truerand.c
new file mode 100644
index 000000000..fa0d6ce60
--- /dev/null
+++ b/package/ead/src/tinysrp/t_truerand.c
@@ -0,0 +1,151 @@
+/*
+ * Physically random numbers (very nearly uniform)
+ * D. P. Mitchell
+ * Modified by Matt Blaze 7/95
+ */
+/*
+ * The authors of this software are Don Mitchell and Matt Blaze.
+ * Copyright (c) 1995 by AT&T.
+ * Permission to use, copy, and modify this software without fee
+ * is hereby granted, provided that this entire notice is included in
+ * all copies of any software which is or includes a copy or
+ * modification of this software and in all copies of the supporting
+ * documentation for such software.
+ *
+ * This software may be subject to United States export controls.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+/*
+ * WARNING: depending on the particular platform, raw_truerand()
+ * output may be biased or correlated. In general, you can expect
+ * about 16 bits of "pseudo-entropy" out of each 32 bit word returned
+ * by truerand(), but it may not be uniformly diffused. You should
+ * raw_therefore run the output through some post-whitening function
+ * (like MD5 or DES or whatever) before using it to generate key
+ * material. (RSAREF's random package does this for you when you feed
+ * raw_truerand() bits to the seed input function.)
+ *
+ * The application interface, for 8, 16, and 32 bit properly "whitened"
+ * random numbers, can be found in trand8(), trand16(), and trand32().
+ * Use those instead of calling raw_truerand() directly.
+ *
+ * The basic idea here is that between clock "skew" and various
+ * hard-to-predict OS event arrivals, counting a tight loop will yield
+ * a little (maybe a third of a bit or so) of "good" randomness per
+ * interval clock tick. This seems to work well even on unloaded
+ * machines. If there is a human operator at the machine, you should
+ * augment truerand with other measure, like keyboard event timing.
+ * On server machines (e.g., when you need to generate a
+ * Diffie-Hellman secret) truerand alone may be good enough.
+ *
+ * Test these assumptions on your own platform before fielding a
+ * system based on this software or these techniques.
+ *
+ * This software seems to work well (at 10 or so bits per
+ * raw_truerand() call) on a Sun Sparc-20 under SunOS 4.1.3 and on a
+ * P100 under BSDI 2.0. You're on your own elsewhere.
+ *
+ */
+
+#include "t_defines.h"
+
+#include <signal.h>
+#include <setjmp.h>
+#include <sys/time.h>
+#include <math.h>
+#include <stdio.h>
+
+#ifdef OLD_TRUERAND
+static jmp_buf env;
+#endif
+static unsigned volatile count
+#ifndef OLD_TRUERAND
+ , done = 0
+#endif
+;
+
+static unsigned ocount;
+static unsigned buffer;
+
+static void
+tick()
+{
+ struct itimerval it, oit;
+
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = 0;
+ it.it_value.tv_sec = 0;
+ it.it_value.tv_usec = 16665;
+ if (setitimer(ITIMER_REAL, &it, &oit) < 0)
+ perror("tick");
+}
+
+static void
+interrupt()
+{
+ if (count) {
+#ifdef OLD_TRUERAND
+ longjmp(env, 1);
+#else
+ ++done;
+ return;
+#endif
+ }
+
+ (void) signal(SIGALRM, interrupt);
+ tick();
+}
+
+static unsigned long
+roulette()
+{
+#ifdef OLD_TRUERAND
+ if (setjmp(env)) {
+ count ^= (count>>3) ^ (count>>6) ^ ocount;
+ count &= 0x7;
+ ocount=count;
+ buffer = (buffer<<3) ^ count;
+ return buffer;
+ }
+#else
+ done = 0;
+#endif
+ (void) signal(SIGALRM, interrupt);
+ count = 0;
+ tick();
+#ifdef OLD_TRUERAND
+ for (;;)
+#else
+ while(done == 0)
+#endif
+ count++; /* about 1 MHz on VAX 11/780 */
+#ifndef OLD_TRUERAND
+ count ^= (count>>3) ^ (count>>6) ^ ocount;
+ count &= 0x7;
+ ocount=count;
+ buffer = (buffer<<3) ^ count;
+ return buffer;
+#endif
+}
+
+unsigned long
+raw_truerand()
+{
+ count=0;
+ (void) roulette();
+ (void) roulette();
+ (void) roulette();
+ (void) roulette();
+ (void) roulette();
+ (void) roulette();
+ (void) roulette();
+ (void) roulette();
+ (void) roulette();
+ (void) roulette();
+ return roulette();
+}
diff --git a/package/ead/src/tinysrp/tconf.c b/package/ead/src/tinysrp/tconf.c
new file mode 100644
index 000000000..ad77f4cc1
--- /dev/null
+++ b/package/ead/src/tinysrp/tconf.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 1997-2000 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following conditions apply:
+ *
+ * 1. Any software that incorporates the SRP authentication technology
+ * must display the following acknowlegment:
+ * "This product uses the 'Secure Remote Password' cryptographic
+ * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU)."
+ *
+ * 2. Any software that incorporates all or part of the SRP distribution
+ * itself must also display the following acknowledgment:
+ * "This product includes software developed by Tom Wu and Eugene
+ * Jhong for the SRP Distribution (http://srp.stanford.edu/srp/)."
+ *
+ * 3. Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice and list of conditions.
+ */
+
+#include <unistd.h> /* close getlogin */
+#include <stdlib.h> /* atexit exit */
+#include <stdio.h>
+#include <string.h>
+
+#include "t_pwd.h"
+
+#define MIN_BASIS_BITS 512
+#define BASIS_BITS 2048
+
+extern int optind;
+extern char *optarg;
+
+extern int errno;
+
+char *progName;
+
+int debug = 0;
+int verbose = 0;
+int composite = 0;
+
+int main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char *chp;
+ char *configFile = NULL;
+ char cbuf[256];
+ char b64buf[MAXB64PARAMLEN];
+ int c, ch, i, lastidx, keylen, yesno, fsize, status, nparams;
+ FILE *efp;
+
+ struct t_preconf * tpc;
+ struct t_conf tcs;
+ struct t_conf * tc = &tcs;
+ struct t_confent * tcent;
+
+ progName = *argv;
+ if ((chp = strrchr(progName, '/')) != (char *) 0) progName = chp + 1;
+
+ while ((ch = getopt(argc, argv, "dv2c:")) != EOF)
+ switch(ch) {
+ case 'c':
+ configFile = optarg;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'd':
+ debug++;
+ break;
+ case '2':
+ composite++;
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-dv2] [-c configfile]\n", progName);
+ exit(1);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ lastidx = 0;
+ keylen = 0;
+
+ tcent = t_newconfent(tc);
+
+ printf("\nThis program will generate a set of parameters for the EPS\n");
+ printf("password file. The size of these parameters, measured in bits,\n");
+ printf("determines the level of security offered by SRP, and is related\n");
+ printf("to the security of similarly-sized RSA or Diffie-Hellman keys.\n");
+ printf("Choosing a predefined field is generally preferable to generating\n");
+ printf("a new field because clients can avoid costly parameter verification.\n");
+ printf("Either way, the values generated by this program are public and\n");
+ printf("can even shared between systems.\n");
+
+ printf("\nEnter the new field size, in bits. Suggested sizes:\n\n");
+ printf(" 512 (fast, minimally secure)\n");
+ printf(" 768 (moderate security)\n");
+ printf("1024 (most popular default)\n");
+ printf("1536 (additional security, possibly slow)\n");
+ printf("2048 (maximum supported security level)\n");
+ printf("\nField size (%d to %d): ", MIN_BASIS_BITS, BASIS_BITS);
+
+ fgets(cbuf, sizeof(cbuf), stdin);
+ fsize = atoi(cbuf);
+ if(fsize < MIN_BASIS_BITS || fsize > BASIS_BITS) {
+ fprintf(stderr, "%s: field size must be between %d and %d\n",
+ progName, MIN_BASIS_BITS, BASIS_BITS);
+ exit(1);
+ }
+
+ if(fsize <= keylen)
+ fprintf(stderr, "Warning: new field size is not larger than old field size\n");
+
+ printf("\nInitializing random number generator...");
+ fflush(stdout);
+ t_initrand();
+
+ if(composite)
+ printf("done.\n\nGenerating a %d-bit composite with safe prime factors. This may take a while.\n", fsize);
+ else
+ printf("done.\n\nGenerating a %d-bit safe prime. This may take a while.\n", fsize);
+
+ while((tcent = (composite ? t_makeconfent_c(tc, fsize) :
+ t_makeconfent(tc, fsize))) == NULL)
+ printf("Parameter generation failed, retrying...\n");
+ tcent->index = lastidx + 1;
+
+ printf("\nParameters successfully generated.\n");
+ printf("N = [%s]\n", t_tob64(b64buf,
+ tcent->modulus.data, tcent->modulus.len));
+ printf("g = [%s]\n", t_tob64(b64buf,
+ tcent->generator.data, tcent->generator.len));
+ printf("\nYou must update the pre_params array in t_getconf.c\n");
+}
diff --git a/package/ead/src/tinysrp/tinysrp.c b/package/ead/src/tinysrp/tinysrp.c
new file mode 100644
index 000000000..fc0105541
--- /dev/null
+++ b/package/ead/src/tinysrp/tinysrp.c
@@ -0,0 +1,235 @@
+/* This bit implements a simple API for using the SRP library over sockets. */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include "t_defines.h"
+#include "t_pwd.h"
+#include "t_server.h"
+#include "t_client.h"
+#include "tinysrp.h"
+
+#ifndef MSG_WAITALL
+#ifdef linux
+#define MSG_WAITALL 0x100 /* somehow not defined on my box */
+#endif
+#endif
+
+/* This is called by the client with a connected socket, username, and
+passphrase. pass can be NULL in which case the user is queried. */
+
+int tsrp_client_authenticate(int s, char *user, char *pass, TSRP_SESSION *tsrp)
+{
+ int i, index;
+ unsigned char username[MAXUSERLEN + 1], sbuf[MAXSALTLEN];
+ unsigned char msgbuf[MAXPARAMLEN + 1], bbuf[MAXPARAMLEN];
+ unsigned char passbuf[128], *skey;
+ struct t_client *tc;
+ struct t_preconf *tcp; /* @@@ should go away */
+ struct t_num salt, *A, B;
+
+ /* Send the username. */
+
+ i = strlen(user);
+ if (i > MAXUSERLEN) {
+ i = MAXUSERLEN;
+ }
+ msgbuf[0] = i;
+ memcpy(msgbuf + 1, user, i);
+ if (send(s, msgbuf, i + 1, 0) < 0) {
+ return 0;
+ }
+ memcpy(username, user, i);
+ username[i] = '\0';
+
+ /* Get the prime index and salt. */
+
+ i = recv(s, msgbuf, 2, MSG_WAITALL);
+ if (i <= 0) {
+ return 0;
+ }
+ index = msgbuf[0];
+ if (index <= 0 || index > t_getprecount()) {
+ return 0;
+ }
+ tcp = t_getpreparam(index - 1);
+ salt.len = msgbuf[1];
+ if (salt.len > MAXSALTLEN) {
+ return 0;
+ }
+ salt.data = sbuf;
+ i = recv(s, sbuf, salt.len, MSG_WAITALL);
+ if (i <= 0) {
+ return 0;
+ }
+
+ /* @@@ t_clientopen() needs a variant that takes the index */
+
+ tc = t_clientopen(username, &tcp->modulus, &tcp->generator, &salt);
+ if (tc == NULL) {
+ return 0;
+ }
+
+ /* Calculate A and send it to the server. */
+
+ A = t_clientgenexp(tc);
+ msgbuf[0] = A->len - 1; /* len is max 256 */
+ memcpy(msgbuf + 1, A->data, A->len);
+ if (send(s, msgbuf, A->len + 1, 0) < 0) {
+ return 0;
+ }
+
+ /* Ask the user for the passphrase. */
+
+ if (pass == NULL) {
+ t_getpass(passbuf, sizeof(passbuf), "Enter password:");
+ pass = passbuf;
+ }
+ t_clientpasswd(tc, pass);
+
+ /* Get B from the server. */
+
+ i = recv(s, msgbuf, 1, 0);
+ if (i <= 0) {
+ return 0;
+ }
+ B.len = msgbuf[0] + 1;
+ B.data = bbuf;
+ i = recv(s, bbuf, B.len, MSG_WAITALL);
+ if (i <= 0) {
+ return 0;
+ }
+
+ /* Compute the session key. */
+
+ skey = t_clientgetkey(tc, &B);
+ if (skey == NULL) {
+ return 0;
+ }
+
+ /* Send the response. */
+
+ if (send(s, t_clientresponse(tc), RESPONSE_LEN, 0) < 0) {
+ return 0;
+ }
+
+ /* Get the server's response. */
+
+ i = recv(s, msgbuf, RESPONSE_LEN, MSG_WAITALL);
+ if (i <= 0) {
+ return 0;
+ }
+ if (t_clientverify(tc, msgbuf) != 0) {
+ return 0;
+ }
+
+ /* All done. Now copy the key and clean up. */
+
+ if (tsrp) {
+ memcpy(tsrp->username, username, strlen(username) + 1);
+ memcpy(tsrp->key, skey, SESSION_KEY_LEN);
+ }
+ t_clientclose(tc);
+
+ return 1;
+}
+
+/* This is called by the server with a connected socket. */
+
+int tsrp_server_authenticate(int s, TSRP_SESSION *tsrp)
+{
+ int i, j;
+ unsigned char username[MAXUSERLEN], *skey;
+ unsigned char msgbuf[MAXPARAMLEN + 1], abuf[MAXPARAMLEN];
+ struct t_server *ts;
+ struct t_num A, *B;
+
+ /* Get the username. */
+
+ i = recv(s, msgbuf, 1, 0);
+ if (i <= 0) {
+ return 0;
+ }
+ j = msgbuf[0];
+ i = recv(s, username, j, MSG_WAITALL);
+ if (i <= 0) {
+ return 0;
+ }
+ username[j] = '\0';
+
+ ts = t_serveropen(username);
+ if (ts == NULL) {
+ return 0;
+ }
+
+ /* Send the prime index and the salt. */
+
+ msgbuf[0] = ts->index; /* max 256 primes... */
+ i = ts->s.len;
+ msgbuf[1] = i;
+ memcpy(msgbuf + 2, ts->s.data, i);
+ if (send(s, msgbuf, i + 2, 0) < 0) {
+ return 0;
+ }
+
+ /* Calculate B while we're waiting. */
+
+ B = t_servergenexp(ts);
+
+ /* Get A from the client. */
+
+ i = recv(s, msgbuf, 1, 0);
+ if (i <= 0) {
+ return 0;
+ }
+ A.len = msgbuf[0] + 1;
+ A.data = abuf;
+ i = recv(s, abuf, A.len, MSG_WAITALL);
+ if (i <= 0) {
+ return 0;
+ }
+
+ /* Now send B. */
+
+ msgbuf[0] = B->len - 1;
+ memcpy(msgbuf + 1, B->data, B->len);
+ if (send(s, msgbuf, B->len + 1, 0) < 0) {
+ return 0;
+ }
+
+ /* Calculate the session key while we're waiting. */
+
+ skey = t_servergetkey(ts, &A);
+ if (skey == NULL) {
+ return 0;
+ }
+
+ /* Get the response from the client. */
+
+ i = recv(s, msgbuf, RESPONSE_LEN, MSG_WAITALL);
+ if (i <= 0) {
+ return 0;
+ }
+ if (t_serververify(ts, msgbuf) != 0) {
+ return 0;
+ }
+
+ /* Client authenticated. Now authenticate ourselves to the client. */
+
+ if (send(s, t_serverresponse(ts), RESPONSE_LEN, 0) < 0) {
+ return 0;
+ }
+
+ /* Copy the key and clean up. */
+
+ if (tsrp) {
+ memcpy(tsrp->username, username, strlen(username) + 1);
+ memcpy(tsrp->key, skey, SESSION_KEY_LEN);
+ }
+ t_serverclose(ts);
+
+ return 1;
+}
diff --git a/package/ead/src/tinysrp/tinysrp.h b/package/ead/src/tinysrp/tinysrp.h
new file mode 100644
index 000000000..4420a196a
--- /dev/null
+++ b/package/ead/src/tinysrp/tinysrp.h
@@ -0,0 +1,18 @@
+/* Simple API for the tinysrp library. */
+
+#ifndef T_PWD_H
+#define MAXUSERLEN 32
+#define SESSION_KEY_LEN 40 /* 320-bit session key */
+#endif
+
+typedef struct {
+ char username[MAXUSERLEN + 1];
+ unsigned char key[SESSION_KEY_LEN];
+} TSRP_SESSION;
+
+/* These functions are passed a connected socket, and return true for a
+successful authentication. If tsrp is not NULL, the username and key
+fields are filled in. */
+
+extern int tsrp_server_authenticate(int s, TSRP_SESSION *tsrp);
+extern int tsrp_client_authenticate(int s, char *user, char *pass, TSRP_SESSION *tsrp);
diff --git a/package/ead/src/tinysrp/tpasswd b/package/ead/src/tinysrp/tpasswd
new file mode 100644
index 000000000..2ac7e2a1b
--- /dev/null
+++ b/package/ead/src/tinysrp/tpasswd
@@ -0,0 +1,2 @@
+moo:A9lHvOGAMJvw1m3vcDsQRUFovh6/QUmLDKqwhv.drKQzbE9nS7HrOZLUPx2MmS6ewwybN8RHqpWqnUJRCMFT14FMbYXR7kYNUUQNx43A7F.xrVOU7tlFq5NjoK9sfFtp6PMdbIOP5wzWmipiNFlCOu4sjlSZb.o7C1chLzTKU.0:19AI0Hc9jEkdFc:5
+new user:1FsanML2fbTOEsa072bLjyRD1LEqoRD2GwElfN0VmHeR.FAg5A.2.G5bTjIHmMmHL60kgoAHJZhRrgopalYmujlyAuQoKiHJb98SHm1oJaQ9nl/DrZCvfyw5LpVMqg.CupdiWz6OtmOz8fwC96ItExFnNDt6SmsVDIOn4HqXG6C0lLaqEvcqlN3gFDlJXyP2yldM.LJ1TkHTHmA3DjRkmWEUL3mWEgzkEHyPcRB3Jd5ncDT7jaNbJTTLRoOtgRsaqE7OXuPADoK8MGBcUquYBRrGwyU4Y/wW4gLc3QmV793zxkk.P3.dxkLSjro/Kk94D7kC6fx3K9tadLJyzd94rr:3v/KRlxT0.oYF1:1
diff --git a/package/ead/src/tinysrp/tphrase.c b/package/ead/src/tinysrp/tphrase.c
new file mode 100644
index 000000000..1aede0c83
--- /dev/null
+++ b/package/ead/src/tinysrp/tphrase.c
@@ -0,0 +1,348 @@
+/* Add passphrases to the tpasswd file. Use the last entry in the config
+file by default or a particular one specified by index. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "config.h"
+#include "t_pwd.h"
+#include "t_read.h"
+#include "t_sha.h"
+#include "t_defines.h"
+
+char *Progname;
+char Usage[] = "usage: %s [-n configindex] [-p passfile] user\n";
+#define USAGE() fprintf(stderr, Usage, Progname)
+
+void doit(char *);
+
+int Configindex = -1;
+char *Passfile = DEFAULT_PASSWD;
+
+int main(int argc, char **argv)
+{
+ int c;
+
+ Progname = *argv;
+
+ /* Parse option arguments. */
+
+ while ((c = getopt(argc, argv, "n:p:")) != EOF) {
+ switch (c) {
+
+ case 'n':
+ Configindex = atoi(optarg);
+ break;
+
+ case 'p':
+ Passfile = optarg;
+ break;
+
+ default:
+ USAGE();
+ exit(1);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1) {
+ USAGE();
+ exit(1);
+ }
+ doit(argv[0]);
+
+ return 0;
+}
+
+void doit(char *name)
+{
+ char passphrase[128], passphrase1[128];
+ FILE *f;
+ struct t_conf *tc;
+ struct t_confent *tcent;
+ struct t_pw eps_passwd;
+
+ /* Get the config entry. */
+
+ if (Configindex <= 0) {
+ Configindex = t_getprecount();
+ }
+ tcent = gettcid(Configindex);
+ if (tcent == NULL) {
+ fprintf(stderr, "Invalid configuration file entry.\n");
+ exit(1);
+ }
+
+ /* Ask for the passphrase twice. */
+
+ printf("Setting passphrase for %s\n", name);
+
+ if (t_getpass(passphrase, sizeof(passphrase), "Enter passphrase: ") < 0) {
+ exit(1);
+ }
+ if (t_getpass(passphrase1, sizeof(passphrase1), "Verify: ") < 0) {
+ exit(1);
+ }
+ if (strcmp(passphrase, passphrase1) != 0) {
+ fprintf(stderr, "mismatch\n");
+ exit(1);
+ }
+
+ /* Create the passphrase verifier. */
+
+ t_makepwent(&eps_passwd, name, passphrase, NULL, tcent);
+
+ /* Don't need these anymore. */
+
+ memset(passphrase, 0, sizeof(passphrase));
+ memset(passphrase1, 0, sizeof(passphrase1));
+
+ /* See if the passphrase file is there; create it if not. */
+
+ if ((f = fopen(Passfile, "r+")) == NULL) {
+ creat(Passfile, 0400);
+ } else {
+ fclose(f);
+ }
+
+ /* Change the passphrase. */
+
+ if (t_changepw(Passfile, &eps_passwd.pebuf) < 0) {
+ fprintf(stderr, "Error changing passphrase\n");
+ exit(1);
+ }
+}
+
+/* TODO: Implement a more general method to handle delete/change */
+
+_TYPE( int )
+t_changepw(pwname, diff)
+ const char * pwname;
+ const struct t_pwent * diff;
+{
+ char * bakfile;
+ char * bakfile2;
+ struct stat st;
+ FILE * passfp;
+ FILE * bakfp;
+
+ if(pwname == NULL)
+ pwname = DEFAULT_PASSWD;
+
+ if((passfp = fopen(pwname, "rb")) == NULL || fstat(fileno(passfp), &st) < 0)
+ return -1;
+
+ if((bakfile = malloc(strlen(pwname) + 5)) == NULL) {
+ fclose(passfp);
+ return -1;
+ }
+ else if((bakfile2 = malloc(strlen(pwname) + 5)) == NULL) {
+ fclose(passfp);
+ free(bakfile);
+ return -1;
+ }
+
+ sprintf(bakfile, "%s.bak", pwname);
+ sprintf(bakfile2, "%s.sav", pwname);
+
+ if((bakfp = fopen(bakfile2, "wb")) == NULL &&
+ (unlink(bakfile2) < 0 || (bakfp = fopen(bakfile2, "wb")) == NULL)) {
+ fclose(passfp);
+ fclose(bakfp);
+ return -1;
+ }
+
+#ifdef NO_FCHMOD
+ chmod(bakfile2, st.st_mode & 0777);
+#else
+ fchmod(fileno(bakfp), st.st_mode & 0777);
+#endif
+
+ t_pwcopy(bakfp, passfp, diff);
+
+ fclose(bakfp);
+ fclose(passfp);
+
+#ifdef USE_RENAME
+ unlink(bakfile);
+ if(rename(pwname, bakfile) < 0)
+ return -1;
+ if(rename(bakfile2, pwname) < 0)
+ return -1;
+#else
+ unlink(bakfile);
+ link(pwname, bakfile);
+ unlink(pwname);
+ link(bakfile2, pwname);
+ unlink(bakfile2);
+#endif
+ free(bakfile);
+ free(bakfile2);
+
+ return 0;
+}
+
+_TYPE( struct t_pwent * )
+t_makepwent(tpw, user, pass, salt, confent)
+ struct t_pw * tpw;
+ const char * user;
+ const char * pass;
+ const struct t_num * salt;
+ const struct t_confent * confent;
+{
+ BigInteger x, v, n, g;
+ unsigned char dig[SHA_DIGESTSIZE];
+ SHA1_CTX ctxt;
+
+ tpw->pebuf.name = tpw->userbuf;
+ tpw->pebuf.password.data = tpw->pwbuf;
+ tpw->pebuf.salt.data = tpw->saltbuf;
+
+ strncpy(tpw->pebuf.name, user, MAXUSERLEN);
+ tpw->pebuf.index = confent->index;
+
+ if(salt) {
+ tpw->pebuf.salt.len = salt->len;
+ memcpy(tpw->pebuf.salt.data, salt->data, salt->len);
+ }
+ else {
+ memset(dig, 0, SALTLEN); /* salt is 80 bits */
+ tpw->pebuf.salt.len = SALTLEN;
+ do {
+ t_random(tpw->pebuf.salt.data, SALTLEN);
+ } while(memcmp(tpw->pebuf.salt.data, dig, SALTLEN) == 0);
+ if(tpw->pebuf.salt.data[0] == 0)
+ tpw->pebuf.salt.data[0] = 0xff;
+ }
+
+ n = BigIntegerFromBytes(confent->modulus.data, confent->modulus.len);
+ g = BigIntegerFromBytes(confent->generator.data, confent->generator.len);
+ v = BigIntegerFromInt(0);
+
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, user, strlen(user));
+ SHA1Update(&ctxt, ":", 1);
+ SHA1Update(&ctxt, pass, strlen(pass));
+ SHA1Final(dig, &ctxt);
+
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, tpw->pebuf.salt.data, tpw->pebuf.salt.len);
+ SHA1Update(&ctxt, dig, sizeof(dig));
+ SHA1Final(dig, &ctxt);
+
+ /* x = H(s, H(u, ':', p)) */
+ x = BigIntegerFromBytes(dig, sizeof(dig));
+
+ BigIntegerModExp(v, g, x, n);
+ tpw->pebuf.password.len = BigIntegerToBytes(v, tpw->pebuf.password.data);
+
+ BigIntegerFree(v);
+ BigIntegerFree(x);
+ BigIntegerFree(g);
+ BigIntegerFree(n);
+
+ return &tpw->pebuf;
+}
+
+int
+t_pwcopy(pwdest, pwsrc, diff)
+ FILE * pwdest;
+ FILE * pwsrc;
+ struct t_pwent * diff;
+{
+ struct t_pw * src;
+ struct t_pwent * ent;
+
+ if((src = t_openpw(pwsrc)) == NULL)
+ return -1;
+
+ while((ent = t_getpwent(src)) != NULL)
+ if(diff && strcmp(diff->name, ent->name) == 0) {
+ t_putpwent(diff, pwdest);
+ diff = NULL;
+ }
+ else
+ t_putpwent(ent, pwdest);
+
+ if(diff)
+ t_putpwent(diff, pwdest);
+
+ return 0;
+}
+
+_TYPE( struct t_pwent * )
+t_getpwent(tpw)
+ struct t_pw * tpw;
+{
+ char indexbuf[16];
+ char passbuf[MAXB64PARAMLEN];
+ char saltstr[MAXB64SALTLEN];
+
+#ifdef ENABLE_YP
+ struct t_passwd * nisent;
+ /* FIXME: should tell caller to get conf entry from NIS also */
+
+ if(tpw->state == IN_NIS) {
+ nisent = _yp_gettpent();
+ if(nisent != NULL) {
+ savepwent(tpw, &nisent->tp);
+ return &tpw->pebuf;
+ }
+ tpw->state = FILE_NIS;
+ }
+#endif
+
+ while(1) {
+ if(t_nextfield(tpw->instream, tpw->userbuf, MAXUSERLEN) > 0) {
+#ifdef ENABLE_YP
+ if(tpw->state == FILE_NIS && *tpw->userbuf == '+') {
+ t_nextline(tpw->instream);
+ if(strlen(tpw->userbuf) > 1) { /* +name:... */
+ nisent = _yp_gettpnam(tpw->userbuf + 1);
+ if(nisent != NULL) {
+ savepwent(tpw, nisent);
+ return &tpw->pebuf;
+ }
+ }
+ else { /* +:... */
+ tpw->state = IN_NIS;
+ _yp_settpent();
+ return t_getpwent(tpw);
+ }
+ }
+#endif
+ if(t_nextfield(tpw->instream, passbuf, MAXB64PARAMLEN) > 0 &&
+ (tpw->pebuf.password.len = t_fromb64(tpw->pwbuf, passbuf)) > 0 &&
+ t_nextfield(tpw->instream, saltstr, MAXB64SALTLEN) > 0 &&
+ (tpw->pebuf.salt.len = t_fromb64(tpw->saltbuf, saltstr)) > 0 &&
+ t_nextfield(tpw->instream, indexbuf, 16) > 0 &&
+ (tpw->pebuf.index = atoi(indexbuf)) > 0) {
+ tpw->pebuf.name = tpw->userbuf;
+ tpw->pebuf.password.data = tpw->pwbuf;
+ tpw->pebuf.salt.data = tpw->saltbuf;
+ t_nextline(tpw->instream);
+ return &tpw->pebuf;
+ }
+ }
+ if(t_nextline(tpw->instream) < 0)
+ return NULL;
+ }
+}
+
+_TYPE( void )
+t_putpwent(ent, fp)
+ const struct t_pwent * ent;
+ FILE * fp;
+{
+ char strbuf[MAXB64PARAMLEN];
+ char saltbuf[MAXB64SALTLEN];
+
+ fprintf(fp, "%s:%s:%s:%d\n", ent->name,
+ t_tob64(strbuf, ent->password.data, ent->password.len),
+ t_tob64(saltbuf, ent->salt.data, ent->salt.len), ent->index);
+}
+
diff --git a/package/ebtables/Makefile b/package/ebtables/Makefile
new file mode 100644
index 000000000..17c6b37b8
--- /dev/null
+++ b/package/ebtables/Makefile
@@ -0,0 +1,71 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ebtables
+PKG_VERSION:=2.0.10-4
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-v$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/ebtables
+PKG_MD5SUM:=506742a3d44b9925955425a659c1a8d0
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/ebtables-v$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ebtables
+ SECTION:=net
+ CATEGORY:=Network
+ SUBMENU:=Firewall
+ DEPENDS:=+kmod-ebtables
+ TITLE:=Ethernet bridge firewall administration utility
+ URL:=http://ebtables.sourceforge.net/
+endef
+
+define Package/ebtables-utils
+ $(call Package/ebtables)
+ DEPENDS += ebtables
+ TITLE:=ebtables save/restore utilities
+endef
+
+define Package/ebtables/description
+ The ebtables program is a filtering tool for a bridging firewall. The
+ filtering is focussed on the Link Layer Ethernet frame fields. Apart
+ from filtering, it also gives the ability to alter the Ethernet MAC
+ addresses and implement a brouter.
+endef
+
+define Package/ebtables-utils/description
+ $(call Package/ebtables/description)
+endef
+
+MAKE_VARS += EXT_LIBSI="$(LIBGCC_S)"
+
+MAKE_FLAGS += \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ LIBDIR="/usr/lib/ebtables"
+
+define Package/ebtables/install
+ $(INSTALL_DIR) $(1)/etc
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/ethertypes $(1)/etc/
+ $(INSTALL_DIR) $(1)/usr/lib/ebtables
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/lib*.so $(1)/usr/lib/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/extensions/*.so $(1)/usr/lib/ebtables/
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/ebtables $(1)/usr/sbin/
+endef
+
+define Package/ebtables-utils/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/ebtables-save $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/ebtables-restore $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,ebtables))
+$(eval $(call BuildPackage,ebtables-utils))
diff --git a/package/ep80579-drivers/Makefile b/package/ep80579-drivers/Makefile
new file mode 100644
index 000000000..61d3bc2a1
--- /dev/null
+++ b/package/ep80579-drivers/Makefile
@@ -0,0 +1,92 @@
+#
+# Copyright (C) 2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=ep80579-drivers
+PKG_VERSION:=1.0.34
+PKG_RELEASE:=1
+
+PKG_SOURCE:=Embedded.L.1.0.34.ADI.R100.tar.gz
+PKG_SOURCE_URL:=ftp://ftp.adiengineering.com/Archive/OcracokeIsland/Drivers/Linux/1.0.34/
+PKG_MD5SUM:=61df9778f8c1f919257d2f48a0bcb000
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/ep80579-drivers/Default
+ DEPENDS:=@TARGET_x86_ep80579
+endef
+
+define KernelPackage/ep80579-eth
+$(call KernelPackage/ep80579-drivers/Default)
+ SUBMENU:=Network Devices
+ TITLE:=Intel EP80579 ethernet driver
+ FILES:= \
+ $(PKG_BUILD_DIR)/Embedded/src/GbE/gcu.ko \
+ $(PKG_BUILD_DIR)/Embedded/src/GbE/iegbe.ko
+ AUTOLOAD:=$(call AutoLoad,40,gcu iegbe)
+endef
+
+define KernelPackage/ep80579-misc
+$(call KernelPackage/ep80579-drivers/Default)
+ SUBMENU:=Other modules
+ TITLE:=Misc. Intel EP80579 drivers (DMA,, gpio)
+ FILES:= \
+ $(PKG_BUILD_DIR)/Embedded/src/EDMA/dma.ko \
+ $(PKG_BUILD_DIR)/Embedded/src/GPIO/gpio.ko
+ AUTOLOAD:=$(call AutoLoad,40,gpio dma)
+endef
+
+define KernelPackage/ep80579-can
+$(call KernelPackage/ep80579-drivers/Default)
+ SUBMENU:=Other modules
+ TITLE:=Intel EP80579 CAN driver
+ FILES:= \
+ $(PKG_BUILD_DIR)/Embedded/src/1588/timesync.ko \
+ $(PKG_BUILD_DIR)/Embedded/src/CAN/can.ko
+ AUTOLOAD:=$(call AutoLoad,40,timesync can)
+endef
+
+define Build/Prepare
+ rm -rf $(PKG_BUILD_DIR)
+ mkdir -p $(PKG_BUILD_DIR)
+ tar xzvf $(DL_DIR)/$(PKG_SOURCE) -C $(PKG_BUILD_DIR)/
+ $(Build/Patch)
+endef
+
+define Build/Compile/Subdir
+ $(MAKE) -C "$(LINUX_DIR)" \
+ KSRC="$(LINUX_DIR)" \
+ KOBJ="$(LINUX_DIR)" \
+ ENV_DIR=$(PKG_BUILD_DIR)/Embedded \
+ SUBDIRS="$(PKG_BUILD_DIR)/Embedded/src/$(1)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ ARCHIVER="$(TARGET_CROSS)ar" \
+ COMPILER="$(TARGET_CC)" \
+ LINKER="$(TARGET_CROSS)ld" \
+ ARCH="$(LINUX_KARCH)"
+endef
+
+define Build/Compile
+ $(call Build/Compile/Subdir,GbE)
+ $(call Build/Compile/Subdir,CAN)
+ $(call Build/Compile/Subdir,EDMA)
+ $(call Build/Compile/Subdir,GPIO)
+ $(call Build/Compile/Subdir,WDT)
+ $(call Build/Compile/Subdir,1588)
+endef
+
+define KernelPackage/ep80579-eth/install
+endef
+
+$(eval $(call KernelPackage,ep80579-can))
+$(eval $(call KernelPackage,ep80579-eth))
+$(eval $(call KernelPackage,ep80579-misc))
+
diff --git a/package/ep80579-drivers/patches/001-igbe_update.patch b/package/ep80579-drivers/patches/001-igbe_update.patch
new file mode 100644
index 000000000..80ca0ef8b
--- /dev/null
+++ b/package/ep80579-drivers/patches/001-igbe_update.patch
@@ -0,0 +1,11755 @@
+--- a/Embedded/src/GbE/gcu.h
++++ b/Embedded/src/GbE/gcu.h
+@@ -2,7 +2,7 @@
+
+ GPL LICENSE SUMMARY
+
+- Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY
+ Contact Information:
+ Intel Corporation
+
+- version: Embedded.L.1.0.34
++ version: Embedded.Release.Patch.L.1.0.7-5
+
+ Contact Information:
+
+--- a/Embedded/src/GbE/gcu_if.c
++++ b/Embedded/src/GbE/gcu_if.c
+@@ -2,7 +2,7 @@
+
+ GPL LICENSE SUMMARY
+
+- Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY
+ Contact Information:
+ Intel Corporation
+
+- version: Embedded.L.1.0.34
++ version: Embedded.Release.Patch.L.1.0.7-5
+
+ Contact Information:
+
+@@ -330,10 +330,17 @@ gcu_write_verify(uint32_t phy_num, uint3
+ */
+ void gcu_iegbe_resume(struct pci_dev *pdev)
+ {
++#if ( ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6) ) && \
++ ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) )
++ struct net_device *netdev = pci_get_drvdata(pdev);
++ struct gcu_adapter *adapter = netdev_priv(netdev);
++#endif
++
+ GCU_DBG("%s\n", __func__);
+
+ pci_restore_state(pdev);
+- pci_enable_device(pdev);
++ if(!pci_enable_device(pdev))
++ GCU_DBG("pci_enable_device failed!\n",);
+
+ return;
+ }
+@@ -348,6 +355,12 @@ EXPORT_SYMBOL(gcu_iegbe_resume);
+ */
+ int gcu_iegbe_suspend(struct pci_dev *pdev, uint32_t state)
+ {
++#if ( ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6) ) && \
++ ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) )
++ struct net_device *netdev = pci_get_drvdata(pdev);
++ struct gcu_adapter *adapter = netdev_priv(netdev);
++#endif
++
+ GCU_DBG("%s\n", __func__);
+
+ pci_save_state(pdev);
+--- a/Embedded/src/GbE/gcu_if.h
++++ b/Embedded/src/GbE/gcu_if.h
+@@ -2,7 +2,7 @@
+
+ GPL LICENSE SUMMARY
+
+- Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY
+ Contact Information:
+ Intel Corporation
+
+- version: Embedded.L.1.0.34
++ version: Embedded.Release.Patch.L.1.0.7-5
+
+ Contact Information:
+
+--- a/Embedded/src/GbE/gcu_main.c
++++ b/Embedded/src/GbE/gcu_main.c
+@@ -2,7 +2,7 @@
+
+ GPL LICENSE SUMMARY
+
+- Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY
+ Contact Information:
+ Intel Corporation
+
+- version: Embedded.L.1.0.34
++ version: Embedded.Release.Patch.L.1.0.7-5
+
+ Contact Information:
+
+@@ -94,6 +94,7 @@ static struct pci_driver gcu_driver = {
+
+ static struct gcu_adapter *global_adapter = 0;
+ static spinlock_t global_adapter_spinlock = SPIN_LOCK_UNLOCKED;
++static unsigned long g_intflags = 0;
+
+ MODULE_AUTHOR("Intel(R) Corporation");
+ MODULE_DESCRIPTION("Global Configuration Unit Driver");
+@@ -124,7 +125,7 @@ gcu_init_module(void)
+
+ printk(KERN_INFO "%s\n", gcu_copyright);
+
+- ret = pci_module_init(&gcu_driver);
++ ret = pci_register_driver(&gcu_driver);
+ if(ret >= 0) {
+ register_reboot_notifier(&gcu_notifier_reboot);
+ }
+@@ -199,8 +200,6 @@ gcu_probe(struct pci_dev *pdev,
+ return -ENOMEM;
+ }
+
+- SET_MODULE_OWNER(adapter);
+-
+ pci_set_drvdata(pdev, adapter);
+
+ adapter->pdev = pdev;
+@@ -238,7 +237,6 @@ gcu_probe(struct pci_dev *pdev,
+ return 0;
+ }
+
+-
+ /**
+ * gcu_probe_err - gcu_probe error handler
+ * @err: gcu_err_type
+@@ -295,7 +293,7 @@ gcu_notify_reboot(struct notifier_block
+ case SYS_DOWN:
+ case SYS_HALT:
+ case SYS_POWER_OFF:
+- while((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) {
++ while((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) {
+ if(pci_dev_driver(pdev) == &gcu_driver){
+ gcu_suspend(pdev, 0x3);
+ }
+@@ -318,6 +316,11 @@ static int
+ gcu_suspend(struct pci_dev *pdev, uint32_t state)
+ {
+ /*struct gcu_adapter *adapter = pci_get_drvdata(pdev); */
++#if ( ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6) ) && \
++ ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) )
++ struct net_device *netdev = pci_get_drvdata(pdev);
++ struct gcu_adapter *adapter = netdev_priv(netdev);
++#endif
+
+ GCU_DBG("%s\n", __func__);
+
+@@ -338,7 +341,6 @@ gcu_suspend(struct pci_dev *pdev, uint32
+ return state;
+ }
+
+-
+ /**
+ * alloc_gcu_adapter
+ *
+@@ -412,7 +414,7 @@ gcu_get_adapter(void)
+ return NULL;
+ }
+
+- spin_lock(&global_adapter_spinlock);
++ spin_lock_irqsave(&global_adapter_spinlock, g_intflags);
+
+ return global_adapter;
+ }
+@@ -437,7 +439,7 @@ gcu_release_adapter(const struct gcu_ada
+ *adapter = 0;
+ }
+
+- spin_unlock(&global_adapter_spinlock);
++ spin_unlock_irqrestore(&global_adapter_spinlock, g_intflags);
+
+ return;
+ }
+--- a/Embedded/src/GbE/gcu_reg.h
++++ b/Embedded/src/GbE/gcu_reg.h
+@@ -2,7 +2,7 @@
+
+ GPL LICENSE SUMMARY
+
+- Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY
+ Contact Information:
+ Intel Corporation
+
+- version: Embedded.L.1.0.34
++ version: Embedded.Release.Patch.L.1.0.7-5
+
+ Contact Information:
+
+--- a/Embedded/src/GbE/iegbe.7
++++ b/Embedded/src/GbE/iegbe.7
+@@ -1,7 +1,7 @@
+
+ .\" GPL LICENSE SUMMARY
+ .\"
+-.\" Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
++.\" Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+ .\"
+ .\" This program is free software; you can redistribute it and/or modify
+ .\" it under the terms of version 2 of the GNU General Public License as
+@@ -21,7 +21,7 @@
+ .\" Contact Information:
+ .\" Intel Corporation
+ .\"
+-.\" version: Embedded.L.1.0.34
++.\" version: Embedded.Release.Patch.L.1.0.7-5
+
+ .\" LICENSE
+ .\"
+--- a/Embedded/src/GbE/iegbe_ethtool.c
++++ b/Embedded/src/GbE/iegbe_ethtool.c
+@@ -2,7 +2,7 @@
+
+ GPL LICENSE SUMMARY
+
+- Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY
+ Contact Information:
+ Intel Corporation
+
+- version: Embedded.L.1.0.34
++ version: Embedded.Release.Patch.L.1.0.7-5
+
+ Contact Information:
+
+@@ -132,22 +132,6 @@ static const struct iegbe_stats iegbe_gs
+ { "cpp_master", E1000_STAT(icr_cpp_master) },
+ { "stat", E1000_STAT(icr_stat) },
+ #endif
+-#ifdef IEGBE_GBE_WORKAROUND
+- { "txqec", E1000_STAT(stats.txqec) },
+- { "tx_next_to_clean", E1000_STAT(stats.tx_next_to_clean) },
+- { "tx_next_to_use", E1000_STAT(stats.tx_next_to_use) },
+- { "num_tx_queues", E1000_STAT(stats.num_tx_queues) },
+-
+- { "num_rx_buf_alloc", E1000_STAT(stats.num_rx_buf_alloc) },
+- { "rx_next_to_clean", E1000_STAT(stats.rx_next_to_clean) },
+- { "rx_next_to_use", E1000_STAT(stats.rx_next_to_use) },
+- { "cc_gt_num_rx", E1000_STAT(stats.cc_gt_num_rx) },
+- { "tx_hnet", E1000_STAT(stats.tx_hnet) },
+- { "tx_hnentu", E1000_STAT(stats.tx_hnentu) },
+- { "RUC", E1000_STAT(stats.ruc) },
+- { "RFC", E1000_STAT(stats.rfc) },
+-
+-#endif
+ };
+ #define E1000_STATS_LEN \
+ sizeof(iegbe_gstrings_stats) / sizeof(struct iegbe_stats)
+@@ -158,7 +142,7 @@ static const char iegbe_gstrings_test[][
+ "Interrupt test (offline)", "Loopback test (offline)",
+ "Link test (on/offline)"
+ };
+-#define E1000_TEST_LEN (sizeof(iegbe_gstrings_test) / (ETH_GSTRING_LEN))
++#define E1000_TEST_LEN (sizeof(iegbe_gstrings_test) / ETH_GSTRING_LEN)
+ #endif /* ETHTOOL_TEST */
+
+ #define E1000_REGS_LEN 0x20
+@@ -176,9 +160,7 @@ iegbe_get_settings(struct net_device *ne
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+-#ifndef IEGBE_10_100_ONLY
+ SUPPORTED_1000baseT_Full|
+-#endif
+ SUPPORTED_Autoneg |
+ SUPPORTED_TP);
+
+@@ -259,21 +241,13 @@ iegbe_set_settings(struct net_device *ne
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+-#ifndef IEGBE_10_100_ONLY
+ ADVERTISED_1000baseT_Full|
+-#endif
+-
+ ADVERTISED_Autoneg |
+ ADVERTISED_TP;
+ ecmd->advertising = hw->autoneg_advertised;
+ }
+- } else {
+- uint16_t duplex;
+-
+- // ethtool uses DUPLEX_FULL/DUPLEX_HALF
+- // the driver needs FULL_DUPLEX/HALF_DUPLEX
+- duplex = (ecmd->duplex == DUPLEX_FULL) ? FULL_DUPLEX : HALF_DUPLEX;
+- if(iegbe_set_spd_dplx(adapter, ecmd->speed + duplex))
++ } else
++ if(iegbe_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)){
+ return -EINVAL;
+ }
+ /* reset the link */
+@@ -728,8 +702,8 @@ iegbe_set_ringparam(struct net_device *n
+ struct iegbe_rx_ring *rxdr, *rx_old, *rx_new;
+ int i, err, tx_ring_size, rx_ring_size;
+
+- tx_ring_size = sizeof(struct iegbe_tx_ring) * adapter->num_queues;
+- rx_ring_size = sizeof(struct iegbe_rx_ring) * adapter->num_queues;
++ tx_ring_size = sizeof(struct iegbe_tx_ring) * adapter->num_tx_queues;
++ rx_ring_size = sizeof(struct iegbe_rx_ring) * adapter->num_rx_queues;
+
+ if (netif_running(adapter->netdev)){
+ iegbe_down(adapter);
+@@ -768,10 +742,10 @@ iegbe_set_ringparam(struct net_device *n
+ E1000_MAX_TXD : E1000_MAX_82544_TXD));
+ E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE);
+
+- for (i = 0; i < adapter->num_queues; i++) {
+- txdr[i].count = txdr->count;
+- rxdr[i].count = rxdr->count;
+- }
++ for (i = 0; i < adapter->num_tx_queues; i++)
++ txdr[i].count = txdr->count;
++ for (i = 0; i < adapter->num_rx_queues; i++)
++ rxdr[i].count = rxdr->count;
+
+ if(netif_running(adapter->netdev)) {
+ /* Try to get new resources before deleting old */
+@@ -950,8 +924,7 @@ iegbe_eeprom_test(struct iegbe_adapter *
+
+ static irqreturn_t
+ iegbe_test_intr(int irq,
+- void *data,
+- struct pt_regs *regs)
++ void *data)
+ {
+ struct net_device *netdev = (struct net_device *) data;
+ struct iegbe_adapter *adapter = netdev_priv(netdev);
+@@ -973,7 +946,7 @@ iegbe_intr_test(struct iegbe_adapter *ad
+ /* Hook up test interrupt handler just for this test */
+ if(!request_irq(irq, &iegbe_test_intr, 0, netdev->name, netdev)) {
+ shared_int = FALSE;
+- } else if(request_irq(irq, &iegbe_test_intr, SA_SHIRQ,
++ } else if(request_irq(irq, &iegbe_test_intr, IRQF_SHARED,
+ netdev->name, netdev)){
+ *data = 1;
+ return -1;
+@@ -1393,7 +1366,7 @@ iegbe_set_phy_loopback(struct iegbe_adap
+ * attempt this 10 times.
+ */
+ while(iegbe_nonintegrated_phy_loopback(adapter) &&
+- count++ < 0xa) { };
++ count++ < 0xa);
+ if(count < 0xb) {
+ return 0;
+ }
+--- a/Embedded/src/GbE/iegbe.h
++++ b/Embedded/src/GbE/iegbe.h
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+ GPL LICENSE SUMMARY
+
+- Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+@@ -21,7 +21,7 @@ GPL LICENSE SUMMARY
+ Contact Information:
+ Intel Corporation
+
+- version: Embedded.L.1.0.34
++ version: Embedded.Release.Patch.L.1.0.7-5
+
+ Contact Information:
+
+@@ -127,9 +127,12 @@ struct iegbe_adapter;
+ #define E1000_MIN_RXD 80
+ #define E1000_MAX_82544_RXD 4096
+
++#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
+ /* Supported Rx Buffer Sizes */
+ #define E1000_RXBUFFER_128 128 /* Used for packet split */
+ #define E1000_RXBUFFER_256 256 /* Used for packet split */
++#define E1000_RXBUFFER_512 512
++#define E1000_RXBUFFER_1024 1024
+ #define E1000_RXBUFFER_2048 2048
+ #define E1000_RXBUFFER_4096 4096
+ #define E1000_RXBUFFER_8192 8192
+@@ -164,11 +167,9 @@ struct iegbe_adapter;
+ #define E1000_MASTER_SLAVE iegbe_ms_hw_default
+ #endif
+
+-#ifdef NETIF_F_HW_VLAN_TX
+-#define E1000_MNG_VLAN_NONE -1
+-#endif
++#define E1000_MNG_VLAN_NONE (-1)
+ /* Number of packet split data buffers (not including the header buffer) */
+-#define PS_PAGE_BUFFERS MAX_PS_BUFFERS-1
++#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1)
+
+ /* only works for sizes that are powers of 2 */
+ #define E1000_ROUNDUP(i, size) ((i) = (((i) + (size) - 1) & ~((size) - 1)))
+@@ -206,6 +207,7 @@ struct iegbe_tx_ring {
+ spinlock_t tx_lock;
+ uint16_t tdh;
+ uint16_t tdt;
++ boolean_t last_tx_tso;
+ uint64_t pkt;
+ };
+
+@@ -228,6 +230,9 @@ struct iegbe_rx_ring {
+ struct iegbe_ps_page *ps_page;
+ struct iegbe_ps_page_dma *ps_page_dma;
+
++ /* cpu for rx queue */
++ int cpu;
++
+ uint16_t rdh;
+ uint16_t rdt;
+ uint64_t pkt;
+@@ -252,10 +257,8 @@ struct iegbe_adapter {
+ struct timer_list tx_fifo_stall_timer;
+ struct timer_list watchdog_timer;
+ struct timer_list phy_info_timer;
+-#ifdef NETIF_F_HW_VLAN_TX
+ struct vlan_group *vlgrp;
+ uint16_t mng_vlan_id;
+-#endif
+ uint32_t bd_number;
+ uint32_t rx_buffer_len;
+ uint32_t part_num;
+@@ -265,8 +268,18 @@ struct iegbe_adapter {
+ uint16_t link_speed;
+ uint16_t link_duplex;
+ spinlock_t stats_lock;
+- atomic_t irq_sem;
+- struct work_struct tx_timeout_task;
++ spinlock_t tx_queue_lock;
++ unsigned int total_tx_bytes;
++ unsigned int total_tx_packets;
++ unsigned int total_rx_bytes;
++ unsigned int total_rx_packets;
++ /* Interrupt Throttle Rate */
++ uint32_t itr;
++ uint32_t itr_setting;
++ uint16_t tx_itr;
++ uint16_t rx_itr;
++
++ struct work_struct reset_task;
+ uint8_t fc_autoneg;
+
+ #ifdef ETHTOOL_PHYS_ID
+@@ -276,9 +289,8 @@ struct iegbe_adapter {
+
+ /* TX */
+ struct iegbe_tx_ring *tx_ring; /* One per active queue */
+-#ifdef CONFIG_E1000_MQ
+- struct iegbe_tx_ring **cpu_tx_ring; /* per-cpu */
+-#endif
++ unsigned int restart_queue;
++ unsigned long tx_queue_len;
+ uint32_t txd_cmd;
+ uint32_t tx_int_delay;
+ uint32_t tx_abs_int_delay;
+@@ -286,46 +298,33 @@ struct iegbe_adapter {
+ uint64_t gotcl_old;
+ uint64_t tpt_old;
+ uint64_t colc_old;
++ uint32_t tx_timeout_count;
+ uint32_t tx_fifo_head;
+ uint32_t tx_head_addr;
+ uint32_t tx_fifo_size;
++ uint8_t tx_timeout_factor;
+ atomic_t tx_fifo_stall;
+ boolean_t pcix_82544;
+ boolean_t detect_tx_hung;
+
+ /* RX */
+-#ifdef CONFIG_E1000_NAPI
+- boolean_t (*clean_rx) (struct iegbe_adapter *adapter,
++ bool (*clean_rx)(struct iegbe_adapter *adapter,
+ struct iegbe_rx_ring *rx_ring,
+ int *work_done, int work_to_do);
+-#else
+- boolean_t (*clean_rx) (struct iegbe_adapter *adapter,
+- struct iegbe_rx_ring *rx_ring);
+-#endif
+-
+-#ifdef IEGBE_GBE_WORKAROUND
+ void (*alloc_rx_buf) (struct iegbe_adapter *adapter,
+- struct iegbe_rx_ring *rx_ring,
+- int cleaned_count);
+-#else
+- void (*alloc_rx_buf) (struct iegbe_adapter *adapter,
+- struct iegbe_rx_ring *rx_ring);
+-#endif
+-
++ struct iegbe_rx_ring *rx_ring,
++ int cleaned_count);
+ struct iegbe_rx_ring *rx_ring; /* One per active queue */
+-#ifdef CONFIG_E1000_NAPI
++ struct napi_struct napi;
+ struct net_device *polling_netdev; /* One per active queue */
+-#endif
+-#ifdef CONFIG_E1000_MQ
+- struct net_device **cpu_netdev; /* per-cpu */
+- struct call_async_data_struct rx_sched_call_data;
+- int cpu_for_queue[4];
+-#endif
+- int num_queues;
++
++ int num_tx_queues;
++ int num_rx_queues;
+
+ uint64_t hw_csum_err;
+ uint64_t hw_csum_good;
+ uint64_t rx_hdr_split;
++ uint32_t alloc_rx_buff_failed;
+ uint32_t rx_int_delay;
+ uint32_t rx_abs_int_delay;
+ boolean_t rx_csum;
+@@ -334,8 +333,6 @@ struct iegbe_adapter {
+ uint64_t gorcl_old;
+ uint16_t rx_ps_bsize0;
+
+- /* Interrupt Throttle Rate */
+- uint32_t itr;
+
+ /* OS defined structs */
+ struct net_device *netdev;
+@@ -378,7 +375,21 @@ struct iegbe_adapter {
+ #ifdef CONFIG_PCI_MSI
+ boolean_t have_msi;
+ #endif
+-#define IEGBE_INTD_DISABLE 0x0400
++ /* to not mess up cache alignment, always add to the bottom */
++ boolean_t tso_force;
++ boolean_t smart_power_down; /* phy smart power down */
++ boolean_t quad_port_a;
++ unsigned long flags;
++ uint32_t eeprom_wol;
++ int bars;
++ int need_ioport;
+ };
++
++enum iegbe_state_t {
++ __E1000_TESTING,
++ __E1000_RESETTING,
++ __E1000_DOWN
++};
++#define IEGBE_INTD_DISABLE 0x0400
+ #endif /* _IEGBE_H_ */
+
+--- a/Embedded/src/GbE/iegbe_hw.c
++++ b/Embedded/src/GbE/iegbe_hw.c
+@@ -2,7 +2,7 @@
+
+ GPL LICENSE SUMMARY
+
+- Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY
+ Contact Information:
+ Intel Corporation
+
+- version: Embedded.L.1.0.34
++ version: Embedded.Release.Patch.L.1.0.7-5
+
+ Contact Information:
+
+@@ -2115,7 +2115,7 @@ iegbe_config_mac_to_phy(struct iegbe_hw
+
+ ret_val = iegbe_oem_set_trans_gasket(hw);
+ if(ret_val){
+- return ret_val;
++ return ret_val;
+ }
+ ret_val = iegbe_oem_phy_is_full_duplex(
+ hw, (int *) &is_FullDuplex);
+@@ -2164,7 +2164,7 @@ iegbe_config_mac_to_phy(struct iegbe_hw
+ }
+ /* Write the configured values back to the Device Control Reg. */
+ E1000_WRITE_REG(hw, CTRL, ctrl);
+- return E1000_SUCCESS;
++ return ret_val;
+ }
+
+ /*****************************************************************************
+@@ -2684,7 +2684,7 @@ iegbe_check_for_link(struct iegbe_hw *hw
+
+ if(hw->autoneg_failed == 0) {
+ hw->autoneg_failed = 1;
+- return 0;
++ return E1000_SUCCESS;
+ }
+ DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n");
+
+@@ -5875,7 +5875,7 @@ iegbe_get_cable_length(struct iegbe_hw *
+ max_agc = cur_agc;
+ }
+ }
+-
++
+ /* This is to fix a Klockwork defect, that the array index might
+ * be out of bounds. 113 is table size */
+ if (cur_agc < 0x71){
+--- a/Embedded/src/GbE/iegbe_hw.h
++++ b/Embedded/src/GbE/iegbe_hw.h
+@@ -2,7 +2,7 @@
+
+ GPL LICENSE SUMMARY
+
+- Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY
+ Contact Information:
+ Intel Corporation
+
+- version: Embedded.L.1.0.34
++ version: Embedded.Release.Patch.L.1.0.7-5
+
+ Contact Information:
+
+@@ -299,7 +299,7 @@ void iegbe_set_media_type(struct iegbe_h
+ /* Link Configuration */
+ int32_t iegbe_setup_link(struct iegbe_hw *hw);
+ int32_t iegbe_phy_setup_autoneg(struct iegbe_hw *hw);
+-void iegbe_config_collision_dist(struct iegbe_hw *hw);
++void iegbe_config_collision_dist(struct iegbe_hw *hw);
+ int32_t iegbe_config_fc_after_link_up(struct iegbe_hw *hw);
+ int32_t iegbe_check_for_link(struct iegbe_hw *hw);
+ int32_t iegbe_get_speed_and_duplex(struct iegbe_hw *hw, uint16_t * speed, uint16_t * duplex);
+@@ -588,14 +588,6 @@ uint8_t iegbe_arc_subsystem_valid(struct
+ * o LSC = Link Status Change
+ */
+
+-#ifdef IEGBE_GBE_WORKAROUND
+-#define IMS_ENABLE_MASK ( \
+- E1000_IMS_RXT0 | \
+- E1000_IMS_TXQE | \
+- E1000_IMS_RXDMT0 | \
+- E1000_IMS_RXSEQ | \
+- E1000_IMS_LSC)
+-#else
+ #define IMS_ENABLE_MASK ( \
+ E1000_IMS_RXT0 | \
+ E1000_IMS_TXDW | \
+@@ -606,8 +598,7 @@ uint8_t iegbe_arc_subsystem_valid(struct
+ E1000_ICR_PB | \
+ E1000_ICR_CPP_TARGET | \
+ E1000_ICR_CPP_MASTER | \
+- E1000_IMS_LSC)
+-#endif
++ E1000_ICR_LSC)
+
+ /* Number of high/low register pairs in the RAR. The RAR (Receive Address
+ * Registers) holds the directed and multicast addresses that we monitor. We
+@@ -923,10 +914,15 @@ struct iegbe_ffvt_entry {
+ #define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */
+ #define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */
+ #define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */
+-// Register conflict, does not exist for ICP_xxxx hardware
+-// #define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
+ #define E1000_CTRL_AUX 0x000E0 /* Aux Control -RW */
++#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
+ #define E1000_RCTL 0x00100 /* RX Control - RW */
++#define E1000_RDTR1 0x02820 /* RX Delay Timer (1) - RW */
++#define E1000_RDBAL1 0x02900 /* RX Descriptor Base Address Low (1) - RW */
++#define E1000_RDBAH1 0x02904 /* RX Descriptor Base Address High (1) - RW */
++#define E1000_RDLEN1 0x02908 /* RX Descriptor Length (1) - RW */
++#define E1000_RDH1 0x02910 /* RX Descriptor Head (1) - RW */
++#define E1000_RDT1 0x02918 /* RX Descriptor Tail (1) - RW */
+ #define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
+ #define E1000_TXCW 0x00178 /* TX Configuration Word - RW */
+ #define E1000_RXCW 0x00180 /* RX Configuration Word - RO */
+@@ -1282,8 +1278,6 @@ struct iegbe_ffvt_entry {
+ #define E1000_82542_FFMT E1000_FFMT
+ #define E1000_82542_FFVT E1000_FFVT
+ #define E1000_82542_HOST_IF E1000_HOST_IF
+-// Register conflict with ICP_xxxx hardware, no IAM
+-// #define E1000_82542_IAM E1000_IAM
+ #define E1000_82542_EEMNGCTL E1000_EEMNGCTL
+ #define E1000_82542_PSRCTL E1000_PSRCTL
+ #define E1000_82542_RAID E1000_RAID
+@@ -1329,6 +1323,7 @@ struct iegbe_hw_stats {
+ uint64_t algnerrc;
+ uint64_t symerrs;
+ uint64_t rxerrc;
++ uint64_t txerrc;
+ uint64_t mpc;
+ uint64_t scc;
+ uint64_t ecol;
+@@ -1363,6 +1358,7 @@ struct iegbe_hw_stats {
+ uint64_t ruc;
+ uint64_t rfc;
+ uint64_t roc;
++ uint64_t rlerrc;
+ uint64_t rjc;
+ uint64_t mgprc;
+ uint64_t mgpdc;
+@@ -1392,19 +1388,6 @@ struct iegbe_hw_stats {
+ uint64_t ictxqmtc;
+ uint64_t icrxdmtc;
+ uint64_t icrxoc;
+-#ifdef IEGBE_GBE_WORKAROUND
+- u64 txqec;
+- u64 tx_next_to_clean;
+- u64 tx_next_to_use;
+- u64 cc_gt_num_rx;
+- u64 tx_hnet;
+- u64 tx_hnentu;
+- u64 num_tx_queues;
+-
+- u64 num_rx_buf_alloc;
+- u64 rx_next_to_clean;
+- u64 rx_next_to_use;
+-#endif
+ };
+
+ /* Structure containing variables used by the shared code (iegbe_hw.c) */
+@@ -1484,6 +1467,7 @@ struct iegbe_hw {
+ boolean_t ifs_params_forced;
+ boolean_t in_ifs_mode;
+ boolean_t mng_reg_access_disabled;
++ boolean_t rx_needs_kicking;
+ boolean_t icp_xxxx_is_link_up;
+ };
+
+@@ -2358,17 +2342,23 @@ struct iegbe_host_command_info {
+ #define E1000_EXTCNF_SIZE_EXT_PHY_LENGTH 0x000000FF
+ #define E1000_EXTCNF_SIZE_EXT_DOCK_LENGTH 0x0000FF00
+ #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH 0x00FF0000
++#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001
++#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020
+
+ /* PBA constants */
++#define E1000_PBA_8K 0x0008 /* 8KB, default Rx allocation */
+ #define E1000_PBA_12K 0x000C /* 12KB, default Rx allocation */
+ #define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */
++#define E1000_PBA_20K 0x0014
+ #define E1000_PBA_22K 0x0016
+ #define E1000_PBA_24K 0x0018
+ #define E1000_PBA_30K 0x001E
+ #define E1000_PBA_32K 0x0020
++#define E1000_PBA_34K 0x0022
+ #define E1000_PBA_38K 0x0026
+ #define E1000_PBA_40K 0x0028
+ #define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */
++#define E1000_PBS_16K E1000_PBA_16K
+
+ /* Flow Control Constants */
+ #define FLOW_CONTROL_ADDRESS_LOW 0x00C28001
+@@ -2899,7 +2889,7 @@ struct iegbe_host_command_info {
+ #define M88E1000_14_PHY_ID M88E1000_E_PHY_ID
+ #define M88E1011_I_REV_4 0x04
+ #define M88E1111_I_PHY_ID 0x01410CC2
+-#define M88E1141_E_PHY_ID 0x01410CD4
++#define M88E1141_E_PHY_ID 0x01410CD0
+ #define L1LXT971A_PHY_ID 0x001378E0
+
+ /* Miscellaneous PHY bit definitions. */
+--- a/Embedded/src/GbE/iegbe_main.c
++++ b/Embedded/src/GbE/iegbe_main.c
+@@ -2,7 +2,7 @@
+
+ GPL LICENSE SUMMARY
+
+- Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY
+ Contact Information:
+ Intel Corporation
+
+- version: Embedded.L.1.0.34
++ version: Embedded.Release.Patch.L.1.0.7-5
+
+ Contact Information:
+
+@@ -42,103 +42,15 @@ GPL LICENSE SUMMARY
+
+ #include "iegbe.h"
+ #include "gcu_if.h"
+-
+-/* Change Log
+- * 6.0.58 4/20/05
+- * o iegbe_set_spd_dplx tests for compatible speed/duplex specification
+- * for fiber adapters
+- * 6.0.57 4/19/05
+- * o Added code to fix register test failure for devices >= 82571
+- *
+- * 6.0.52 3/15/05
+- * o Added stats_lock around iegbe_read_phy_reg commands to avoid concurrent
+- * calls, one from mii_ioctl and other from within update_stats while
+- * processing MIIREG ioctl.
+- *
+- * 6.1.2 4/13/05
+- * o Fixed ethtool diagnostics
+- * o Enabled flow control to take default eeprom settings
+- * o Added stats_lock around iegbe_read_phy_reg commands to avoid concurrent
+- * calls, one from mii_ioctl and other from within update_stats while processing
+- * MIIREG ioctl.
+- * 6.0.55 3/23/05
+- * o Support for MODULE_VERSION
+- * o Fix APM setting for 82544 based adapters
+- * 6.0.54 3/26/05
+- * o Added a timer to expire packets that were deferred for cleanup
+- * 6.0.52 3/15/05
+- * o Added stats_lock around iegbe_read_phy_reg commands to avoid concurrent
+- * calls, one from mii_ioctl and other from within update_stats while
+- * processing MIIREG ioctl.
+- * 6.0.47 3/2/05
+- * o Added enhanced functionality to the loopback diags to wrap the
+- * descriptor rings
+- * o Added manageability vlan filtering workaround.
+- *
+- * 6.0.44+ 2/15/05
+- * o Added code to handle raw packet based DHCP packets
+- * o Added code to fix the errata 10 buffer overflow issue
+- * o Sync up with WR01-05
+- * o applied Anton's patch to resolve tx hang in hardware
+- * o iegbe timeouts with early writeback patch
+- * o Removed Queensport IDs
+- * o fixed driver panic if MAC receives a bad large packets when packet
+- * split is enabled
+- * o Applied Andrew Mortons patch - iegbe stops working after resume
+- * 5.2.29 12/24/03
+- * o Bug fix: Endianess issue causing ethtool diags to fail on ppc.
+- * o Bug fix: Use pdev->irq instead of netdev->irq for MSI support.
+- * o Report driver message on user override of InterruptThrottleRate module
+- * parameter.
+- * o Bug fix: Change I/O address storage from uint32_t to unsigned long.
+- * o Feature: Added ethtool RINGPARAM support.
+- * o Feature: Added netpoll support.
+- * o Bug fix: Race between Tx queue and Tx clean fixed with a spin lock.
+- * o Bug fix: Allow 1000/Full setting for autoneg param for fiber connections.
+- * Jon D Mason [jonmason@us.ibm.com].
+- *
+- * 5.2.22 10/15/03
+- * o Bug fix: SERDES devices might be connected to a back-plane switch that
+- * doesn't support auto-neg, so add the capability to force 1000/Full.
+- * Also, since forcing 1000/Full, sample RxSynchronize bit to detect link
+- * state.
+- * o Bug fix: Flow control settings for hi/lo watermark didn't consider
+- * changes in the RX FIFO size, which could occur with Jumbo Frames or with
+- * the reduced FIFO in 82547.
+- * o Bug fix: Better propagation of error codes.
+- * [Janice Girouard (janiceg -a-t- us.ibm.com)]
+- * o Bug fix: hang under heavy Tx stress when running out of Tx descriptors;
+- * wasn't clearing context descriptor when backing out of send because of
+- * no-resource condition.
+- * o Bug fix: check netif_running in dev->poll so we don't have to hang in
+- * dev->close until all polls are finished. [Rober Olsson
+- * (robert.olsson@data.slu.se)].
+- * o Revert TxDescriptor ring size back to 256 since change to 1024 wasn't
+- * accepted into the kernel.
+- *
+- * 5.2.16 8/8/03
+- */
+-
+-#ifdef IEGBE_GBE_WORKAROUND
+-#define IEGBE_GBE_WORKAROUND_NUM_RX_DESCRIPTORS 1
+-#endif
++#include <linux/ipv6.h>
++#include <net/ip6_checksum.h>
+
+ char iegbe_driver_name[] = "iegbe";
+ char iegbe_driver_string[] = "Gigabit Ethernet Controller Driver";
+-#ifndef CONFIG_E1000_NAPI
+-#define DRIVERNAPI
+-#else
+-#define DRIVERNAPI "-NAPI"
+-#endif
+-#define DRV_VERSION "0.8.0"DRIVERNAPI
++#define DRV_VERSION "1.0.0-K28-NAPI"
+ char iegbe_driver_version[] = DRV_VERSION;
+-char iegbe_copyright[] = "Copyright (c) 1999-2007 Intel Corporation.";
++char iegbe_copyright[] = "Copyright (c) 1999-2009 Intel Corporation.";
+
+-#define E1000_FIFO_HDR 0x10
+-#define E1000_82547_PAD_LEN 0x3E0
+-#define MINIMUM_DHCP_PACKET_SIZE 282
+-#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 )
+-#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000
+
+ /* iegbe_pci_tbl - PCI Device ID Table
+ *
+@@ -148,95 +60,48 @@ char iegbe_copyright[] = "Copyright (c)
+ * {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
+ */
+ static struct pci_device_id iegbe_pci_tbl[] = {
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1000), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1001), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1004), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1008), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1009), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x100C), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x100D), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x100E), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x100F), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1010), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1011), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1012), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1013), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1014), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1015), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1016), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1017), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1018), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1019), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x101A), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x101D), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x101E), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1026), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1027), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1028), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x105E), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x105F), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1060), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1075), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1076), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1077), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1078), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x1079), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x107A), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x107B), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x107C), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x107D), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x107E), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x107F), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x108A), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x108B), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x108C), */
+-/* INTEL_E1000_ETHERNET_DEVICE(0x109A), */
+- INTEL_E1000_ETHERNET_DEVICE(0x5040),
+- INTEL_E1000_ETHERNET_DEVICE(0x5041),
+- INTEL_E1000_ETHERNET_DEVICE(0x5042),
+- INTEL_E1000_ETHERNET_DEVICE(0x5043),
+- INTEL_E1000_ETHERNET_DEVICE(0x5044),
+- INTEL_E1000_ETHERNET_DEVICE(0x5045),
+- INTEL_E1000_ETHERNET_DEVICE(0x5046),
+- INTEL_E1000_ETHERNET_DEVICE(0x5047),
+- INTEL_E1000_ETHERNET_DEVICE(0x5048),
+- INTEL_E1000_ETHERNET_DEVICE(0x5049),
+- INTEL_E1000_ETHERNET_DEVICE(0x504A),
+- INTEL_E1000_ETHERNET_DEVICE(0x504B),
+- /* required last entry */
++ INTEL_E1000_ETHERNET_DEVICE(0x5040),
++ INTEL_E1000_ETHERNET_DEVICE(0x5041),
++ INTEL_E1000_ETHERNET_DEVICE(0x5042),
++ INTEL_E1000_ETHERNET_DEVICE(0x5043),
++ INTEL_E1000_ETHERNET_DEVICE(0x5044),
++ INTEL_E1000_ETHERNET_DEVICE(0x5045),
++ INTEL_E1000_ETHERNET_DEVICE(0x5046),
++ INTEL_E1000_ETHERNET_DEVICE(0x5047),
++ INTEL_E1000_ETHERNET_DEVICE(0x5048),
++ INTEL_E1000_ETHERNET_DEVICE(0x5049),
++ INTEL_E1000_ETHERNET_DEVICE(0x504A),
++ INTEL_E1000_ETHERNET_DEVICE(0x504B),
++ /* required last entry */
+ {0,}
+ };
+
+ MODULE_DEVICE_TABLE(pci, iegbe_pci_tbl);
+
+-DEFINE_SPINLOCK(print_lock);
+
+ int iegbe_up(struct iegbe_adapter *adapter);
+ void iegbe_down(struct iegbe_adapter *adapter);
++void iegbe_reinit_locked(struct iegbe_adapter *adapter);
+ void iegbe_reset(struct iegbe_adapter *adapter);
+ int iegbe_set_spd_dplx(struct iegbe_adapter *adapter, uint16_t spddplx);
+ int iegbe_setup_all_tx_resources(struct iegbe_adapter *adapter);
+ int iegbe_setup_all_rx_resources(struct iegbe_adapter *adapter);
+ void iegbe_free_all_tx_resources(struct iegbe_adapter *adapter);
+ void iegbe_free_all_rx_resources(struct iegbe_adapter *adapter);
+-int iegbe_setup_tx_resources(struct iegbe_adapter *adapter,
++static int iegbe_setup_tx_resources(struct iegbe_adapter *adapter,
+ struct iegbe_tx_ring *txdr);
+-int iegbe_setup_rx_resources(struct iegbe_adapter *adapter,
++static int iegbe_setup_rx_resources(struct iegbe_adapter *adapter,
+ struct iegbe_rx_ring *rxdr);
+-void iegbe_free_tx_resources(struct iegbe_adapter *adapter,
++static void iegbe_free_tx_resources(struct iegbe_adapter *adapter,
+ struct iegbe_tx_ring *tx_ring);
+-void iegbe_free_rx_resources(struct iegbe_adapter *adapter,
++static void iegbe_free_rx_resources(struct iegbe_adapter *adapter,
+ struct iegbe_rx_ring *rx_ring);
+ void iegbe_update_stats(struct iegbe_adapter *adapter);
+-
+ static int iegbe_init_module(void);
+ static void iegbe_exit_module(void);
+ static int iegbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+ static void __devexit iegbe_remove(struct pci_dev *pdev);
+ static int iegbe_alloc_queues(struct iegbe_adapter *adapter);
+-#ifdef CONFIG_E1000_MQ
+-static void iegbe_setup_queue_mapping(struct iegbe_adapter *adapter);
+-#endif
+ static int iegbe_sw_init(struct iegbe_adapter *adapter);
+ static int iegbe_open(struct net_device *netdev);
+ static int iegbe_close(struct net_device *netdev);
+@@ -249,7 +114,8 @@ static void iegbe_clean_tx_ring(struct i
+ struct iegbe_tx_ring *tx_ring);
+ static void iegbe_clean_rx_ring(struct iegbe_adapter *adapter,
+ struct iegbe_rx_ring *rx_ring);
+-static void iegbe_set_multi(struct net_device *netdev);
++
++static void iegbe_set_rx_mode(struct net_device *netdev);
+ static void iegbe_update_phy_info(unsigned long data);
+ static void iegbe_watchdog(unsigned long data);
+ static void iegbe_82547_tx_fifo_stall(unsigned long data);
+@@ -257,66 +123,46 @@ static int iegbe_xmit_frame(struct sk_bu
+ static struct net_device_stats * iegbe_get_stats(struct net_device *netdev);
+ static int iegbe_change_mtu(struct net_device *netdev, int new_mtu);
+ static int iegbe_set_mac(struct net_device *netdev, void *p);
+-static irqreturn_t iegbe_intr(int irq, void *data, struct pt_regs *regs);
++static irqreturn_t iegbe_intr(int irq, void *data);
+
+-void iegbe_tasklet(unsigned long);
++static irqreturn_t iegbe_intr_msi(int irq, void *data);
+
+-#ifndef IEGBE_GBE_WORKAROUND
+-static boolean_t iegbe_clean_tx_irq(struct iegbe_adapter *adapter,
++static bool iegbe_clean_tx_irq(struct iegbe_adapter *adapter,
+ struct iegbe_tx_ring *tx_ring);
+-#endif
+-
+-#ifdef CONFIG_E1000_NAPI
+-static int iegbe_clean(struct net_device *poll_dev, int *budget);
+-static boolean_t iegbe_clean_rx_irq(struct iegbe_adapter *adapter,
++static int iegbe_clean(struct napi_struct *napi, int budget);
++static bool iegbe_clean_rx_irq(struct iegbe_adapter *adapter,
+ struct iegbe_rx_ring *rx_ring,
+ int *work_done, int work_to_do);
+-static boolean_t iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter,
++static bool iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter,
+ struct iegbe_rx_ring *rx_ring,
+ int *work_done, int work_to_do);
+-#else
+-static boolean_t iegbe_clean_rx_irq(struct iegbe_adapter *adapter,
+- struct iegbe_rx_ring *rx_ring);
+-static boolean_t iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter,
+- struct iegbe_rx_ring *rx_ring);
+-#endif
+
+-#ifdef IEGBE_GBE_WORKAROUND
++
+ static void iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter,
+ struct iegbe_rx_ring *rx_ring,
+ int cleaned_count);
+ static void iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter,
+ struct iegbe_rx_ring *rx_ring,
+ int cleaned_count);
+-#else
+-static void iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter,
+- struct iegbe_rx_ring *rx_ring);
+-static void iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter,
+- struct iegbe_rx_ring *rx_ring);
+-#endif
++
+
+ static int iegbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
+-#ifdef SIOCGMIIPHY
+ static int iegbe_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
+- int cmd);
+-#endif
++ int cmd);
+ void set_ethtool_ops(struct net_device *netdev);
+ extern int ethtool_ioctl(struct ifreq *ifr);
+ static void iegbe_enter_82542_rst(struct iegbe_adapter *adapter);
+ static void iegbe_leave_82542_rst(struct iegbe_adapter *adapter);
+ static void iegbe_tx_timeout(struct net_device *dev);
+-static void iegbe_tx_timeout_task(struct net_device *dev);
++static void iegbe_reset_task(struct work_struct *work);
+ static void iegbe_smartspeed(struct iegbe_adapter *adapter);
+ static inline int iegbe_82547_fifo_workaround(struct iegbe_adapter *adapter,
+- struct sk_buff *skb);
++ struct sk_buff *skb);
+
+-#ifdef NETIF_F_HW_VLAN_TX
+-static void iegbe_vlan_rx_register(struct net_device *netdev,
+- struct vlan_group *grp);
++static void iegbe_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
+ static void iegbe_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
+ static void iegbe_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
+ static void iegbe_restore_vlan(struct iegbe_adapter *adapter);
+-#endif
+
+ static int iegbe_notify_reboot(struct notifier_block *,
+ unsigned long event,
+@@ -331,15 +177,17 @@ static int iegbe_resume(struct pci_dev *
+ static void iegbe_netpoll (struct net_device *netdev);
+ #endif
+
+-#ifdef CONFIG_E1000_MQ
+-/* for multiple Rx queues */
++#define COPYBREAK_DEFAULT 256
++static unsigned int copybreak __read_mostly = COPYBREAK_DEFAULT;
++module_param(copybreak, uint, 0644);
++MODULE_PARM_DESC(copybreak,
++ "Maximum size of packet that is copied to a new buffer on receive");
+ void iegbe_rx_schedule(void *data);
+-#endif
+
+ struct notifier_block iegbe_notifier_reboot = {
+- .notifier_call = iegbe_notify_reboot,
+- .next = NULL,
+- .priority = 0
++ .notifier_call = iegbe_notify_reboot,
++ .next = NULL,
++ .priority = 0
+ };
+
+ /* Exported from other modules */
+@@ -347,14 +195,14 @@ struct notifier_block iegbe_notifier_reb
+ extern void iegbe_check_options(struct iegbe_adapter *adapter);
+
+ static struct pci_driver iegbe_driver = {
+- .name = iegbe_driver_name,
+- .id_table = iegbe_pci_tbl,
+- .probe = iegbe_probe,
+- .remove = __devexit_p(iegbe_remove),
+- /* Power Managment Hooks */
++ .name = iegbe_driver_name,
++ .id_table = iegbe_pci_tbl,
++ .probe = iegbe_probe,
++ .remove = __devexit_p(iegbe_remove),
++ /* Power Managment Hooks */
+ #ifdef CONFIG_PM
+- .suspend = iegbe_suspend,
+- .resume = iegbe_resume
++ .suspend = iegbe_suspend,
++ .resume = iegbe_resume
+ #endif
+ };
+
+@@ -364,46 +212,17 @@ MODULE_LICENSE("GPL");
+ MODULE_VERSION(DRV_VERSION);
+
+ static int debug = NETIF_MSG_DRV | NETIF_MSG_PROBE;
+-module_param(debug, int, 0);
++module_param(debug, int, 0x0);
+ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
+-static uint8_t gcu_suspend = 0;
+-static uint8_t gcu_resume = 0;
++static uint8_t gcu_suspend = 0x0;
++static uint8_t gcu_resume = 0x0;
+ struct pci_dev *gcu = NULL;
+
+-unsigned long tasklet_data;
+-DECLARE_TASKLET(iegbe_reset_tasklet, iegbe_tasklet, (unsigned long) &tasklet_data);
+
+ /**
+ * iegbe_iegbe_tasklet -*
+ **/
+-void iegbe_tasklet(unsigned long data)
+-{
+- char* err_msg = "TEST";
+- uint32_t *icr = (uint32_t*) data;
+- uint32_t gbe = *icr & 0x000000FF;
+- if( *icr & E1000_ICR_RX_DESC_FIFO_PAR) { /* 21 */
+- err_msg = "DMA Transmit Descriptor 2-bit ECC Error!";
+- }
+- if( *icr & E1000_ICR_TX_DESC_FIFO_PAR) { /* 20 */
+- err_msg = "DMA Receive Descriptor 2-bit ECC Error!";
+- }
+- if( *icr & E1000_ICR_PB) { /* 23 */
+- err_msg = "DMA Packet Buffer 2-bit ECC Error!";
+- }
+- if( *icr & E1000_ICR_CPP_TARGET) { /* 27 */
+- err_msg = "Statistic Register ECC Error!";
+- }
+- if( *icr & E1000_ICR_CPP_MASTER) {
+- err_msg = "CPP Error!";
+- }
+- spin_lock(&print_lock);
+- printk("IEGBE%d: System Reset due to: %s\n", gbe, err_msg);
+- dump_stack();
+- spin_unlock(&print_lock);
+- panic(err_msg);
+- return;
+-}
+ /**
+ * iegbe_init_module - Driver Registration Routine
+ *
+@@ -411,21 +230,24 @@ void iegbe_tasklet(unsigned long data)
+ * loaded. All it does is register with the PCI subsystem.
+ **/
+
+-static int __init
+-iegbe_init_module(void)
++static int __init iegbe_init_module(void)
+ {
+- int ret;
++ int ret;
+
+ printk(KERN_INFO "%s - version %s\n",
+- iegbe_driver_string, iegbe_driver_version);
++ iegbe_driver_string, iegbe_driver_version);
+
+- printk(KERN_INFO "%s\n", iegbe_copyright);
++ printk(KERN_INFO "%s\n", iegbe_copyright);
+
+- ret = pci_module_init(&iegbe_driver);
+- if(ret >= 0) {
+- register_reboot_notifier(&iegbe_notifier_reboot);
+- }
+- return ret;
++ ret = pci_register_driver(&iegbe_driver);
++ if (copybreak != COPYBREAK_DEFAULT) {
++ if (copybreak == 0)
++ printk(KERN_INFO "iegbe: copybreak disabled\n");
++ else
++ printk(KERN_INFO "iegbe: copybreak enabled for "
++ "packets <= %u bytes\n", copybreak);
++ }
++ return ret;
+ }
+
+ module_init(iegbe_init_module);
+@@ -437,29 +259,51 @@ module_init(iegbe_init_module);
+ * from memory.
+ **/
+
+-static void __exit
+-iegbe_exit_module(void)
++static void __exit iegbe_exit_module(void)
+ {
+-
+- unregister_reboot_notifier(&iegbe_notifier_reboot);
+- pci_unregister_driver(&iegbe_driver);
++ pci_unregister_driver(&iegbe_driver);
+ }
+
+ module_exit(iegbe_exit_module);
+
++static int iegbe_request_irq(struct iegbe_adapter *adapter)
++{
++ struct net_device *netdev = adapter->netdev;
++ irq_handler_t handler = iegbe_intr;
++ int irq_flags = IRQF_SHARED;
++ int err;
++ adapter->have_msi = !pci_enable_msi(adapter->pdev);
++ if (adapter->have_msi) {
++ handler = iegbe_intr_msi;
++ irq_flags = 0;
++ }
++ err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name,
++ netdev);
++ if (err) {
++ if (adapter->have_msi)
++ pci_disable_msi(adapter->pdev);
++ DPRINTK(PROBE, ERR,
++ "Unable to allocate interrupt Error: %d\n", err);
++ }
++ return err;
++}
++static void iegbe_free_irq(struct iegbe_adapter *adapter)
++{
++ struct net_device *netdev = adapter->netdev;
++ free_irq(adapter->pdev->irq, netdev);
++ if (adapter->have_msi)
++ pci_disable_msi(adapter->pdev);
++}
+ /**
+ * iegbe_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ **/
+
+-static inline void
+-iegbe_irq_disable(struct iegbe_adapter *adapter)
++static void iegbe_irq_disable(struct iegbe_adapter *adapter)
+ {
+-
+- atomic_inc(&adapter->irq_sem);
+- E1000_WRITE_REG(&adapter->hw, IMC, ~0);
+- E1000_WRITE_FLUSH(&adapter->hw);
+- synchronize_irq(adapter->pdev->irq);
++ E1000_WRITE_REG(&adapter->hw, IMC, ~0);
++ E1000_WRITE_FLUSH(&adapter->hw);
++ synchronize_irq(adapter->pdev->irq);
+ }
+
+ /**
+@@ -470,244 +314,414 @@ iegbe_irq_disable(struct iegbe_adapter *
+ static inline void
+ iegbe_irq_enable(struct iegbe_adapter *adapter)
+ {
+-
+- if(likely(atomic_dec_and_test(&adapter->irq_sem))) {
+- E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
+- E1000_WRITE_FLUSH(&adapter->hw);
+- }
++ E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
++ E1000_WRITE_FLUSH(&adapter->hw);
+ }
+-#ifdef NETIF_F_HW_VLAN_TX
+-void
+-iegbe_update_mng_vlan(struct iegbe_adapter *adapter)
+-{
+- struct net_device *netdev = adapter->netdev;
+- uint16_t vid = adapter->hw.mng_cookie.vlan_id;
+- uint16_t old_vid = adapter->mng_vlan_id;
+
+- if(adapter->vlgrp) {
+- if(!adapter->vlgrp->vlan_devices[vid]) {
+- if(adapter->hw.mng_cookie.status &
+- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
+- iegbe_vlan_rx_add_vid(netdev, vid);
+- adapter->mng_vlan_id = vid;
+- } else {
+- adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
+- }
+- if((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) &&
+- (vid != old_vid) &&
+- !adapter->vlgrp->vlan_devices[old_vid]) {
+- iegbe_vlan_rx_kill_vid(netdev, old_vid);
+- }
+- }
+-}
++static void iegbe_update_mng_vlan(struct iegbe_adapter *adapter)
++{
++ struct iegbe_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ u16 vid = hw->mng_cookie.vlan_id;
++ u16 old_vid = adapter->mng_vlan_id;
++ if (adapter->vlgrp) {
++ if (!vlan_group_get_device(adapter->vlgrp, vid)) {
++ if (hw->mng_cookie.status &
++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
++ iegbe_vlan_rx_add_vid(netdev, vid);
++ adapter->mng_vlan_id = vid;
++ } else
++ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
++
++ if ((old_vid != (u16)E1000_MNG_VLAN_NONE) &&
++ (vid != old_vid) &&
++ !vlan_group_get_device(adapter->vlgrp, old_vid))
++ iegbe_vlan_rx_kill_vid(netdev, old_vid);
++ } else
++ adapter->mng_vlan_id = vid;
++ }
+ }
+-#endif
+
+-int
+-iegbe_up(struct iegbe_adapter *adapter)
++/**
++ * iegbe_configure - configure the hardware for RX and TX
++ * @adapter = private board structure
++ **/
++static void iegbe_configure(struct iegbe_adapter *adapter)
+ {
+ struct net_device *netdev = adapter->netdev;
+- int i, err;
+- uint16_t pci_cmd;
+-
+- /* hardware has been reset, we need to reload some things */
+-
+- /* Reset the PHY if it was previously powered down */
+- if(adapter->hw.media_type == iegbe_media_type_copper
+- || (adapter->hw.media_type == iegbe_media_type_oem
+- && iegbe_oem_phy_is_copper(&adapter->hw))) {
+- uint16_t mii_reg;
+- iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
+- if(mii_reg & MII_CR_POWER_DOWN){
+- iegbe_phy_reset(&adapter->hw);
+- }
+- }
++ int i;
+
+- iegbe_set_multi(netdev);
++ iegbe_set_rx_mode(netdev);
+
+-#ifdef NETIF_F_HW_VLAN_TX
+ iegbe_restore_vlan(adapter);
+-#endif
+
+ iegbe_configure_tx(adapter);
+ iegbe_setup_rctl(adapter);
+ iegbe_configure_rx(adapter);
++ /* call E1000_DESC_UNUSED which always leaves
++ * at least 1 descriptor unused to make sure
++ * next_to_use != next_to_clean */
++ for (i = 0; i < adapter->num_rx_queues; i++) {
++ struct iegbe_rx_ring *ring = &adapter->rx_ring[i];
++ adapter->alloc_rx_buf(adapter, ring,
++ E1000_DESC_UNUSED(ring));
++ }
+
+-#ifdef IEGBE_GBE_WORKAROUND
+- for (i = 0; i < adapter->num_queues; i++)
+- adapter->alloc_rx_buf(adapter, &adapter->rx_ring[i],
+- IEGBE_GBE_WORKAROUND_NUM_RX_DESCRIPTORS + 1);
+-#else
+- for (i = 0; i < adapter->num_queues; i++)
+- adapter->alloc_rx_buf(adapter, &adapter->rx_ring[i]);
+-#endif
++ adapter->tx_queue_len = netdev->tx_queue_len;
++}
+
+-#ifdef CONFIG_PCI_MSI
+- if(adapter->hw.mac_type > iegbe_82547_rev_2
+- || adapter->hw.mac_type == iegbe_icp_xxxx) {
+- adapter->have_msi = TRUE;
+- if((err = pci_enable_msi(adapter->pdev))) {
+- DPRINTK(PROBE, ERR,
+- "Unable to allocate MSI interrupt Error: %d\n", err);
+- adapter->have_msi = FALSE;
+- }
+- }
+- pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd);
+- pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd | IEGBE_INTD_DISABLE);
++int iegbe_up(struct iegbe_adapter *adapter)
++{
++ /* hardware has been reset, we need to reload some things */
++ iegbe_configure(adapter);
+
+-#endif
+- if((err = request_irq(adapter->pdev->irq, &iegbe_intr,
+- SA_SHIRQ | SA_SAMPLE_RANDOM,
+- netdev->name, netdev))) {
+- DPRINTK(PROBE, ERR,
+- "Unable to allocate interrupt Error: %d\n", err);
+- return err;
+- }
++ clear_bit(__E1000_DOWN, &adapter->flags);
+
+- mod_timer(&adapter->watchdog_timer, jiffies);
++ napi_enable(&adapter->napi);
+
+-#ifdef CONFIG_E1000_NAPI
+- netif_poll_enable(netdev);
+-#endif
+ iegbe_irq_enable(adapter);
+
++ adapter->hw.get_link_status = 0x1;
+ return 0;
+ }
+
+-void
+-iegbe_down(struct iegbe_adapter *adapter)
+-{
+- struct net_device *netdev = adapter->netdev;
+-
+- iegbe_irq_disable(adapter);
+-#ifdef CONFIG_E1000_MQ
+- while (atomic_read(&adapter->rx_sched_call_data.count) != 0) { };
+-#endif
+- free_irq(adapter->pdev->irq, netdev);
+-#ifdef CONFIG_PCI_MSI
+- if((adapter->hw.mac_type > iegbe_82547_rev_2
+- || adapter->hw.mac_type == iegbe_icp_xxxx)
+- && adapter->have_msi == TRUE) {
+- pci_disable_msi(adapter->pdev);
+- }
+-#endif
+- del_timer_sync(&adapter->tx_fifo_stall_timer);
+- del_timer_sync(&adapter->watchdog_timer);
+- del_timer_sync(&adapter->phy_info_timer);
++/**
++ * iegbe_power_up_phy - restore link in case the phy was powered down
++ * @adapter: address of board private structure
++ *
++ * The phy may be powered down to save power and turn off link when the
++ * driver is unloaded and wake on lan is not enabled (among others)
++ * *** this routine MUST be followed by a call to iegbe_reset ***
++ *
++ **/
+
+-#ifdef CONFIG_E1000_NAPI
+- netif_poll_disable(netdev);
+-#endif
+- adapter->link_speed = 0;
+- adapter->link_duplex = 0;
+- netif_carrier_off(netdev);
+- netif_stop_queue(netdev);
++void iegbe_power_up_phy(struct iegbe_adapter *adapter)
++{
++ struct iegbe_hw *hw = &adapter->hw;
++ u16 mii_reg = 0;
+
+- iegbe_reset(adapter);
+- iegbe_clean_all_tx_rings(adapter);
+- iegbe_clean_all_rx_rings(adapter);
++ /* Just clear the power down bit to wake the phy back up */
++ if (hw->media_type == iegbe_media_type_copper) {
++ /* according to the manual, the phy will retain its
++ * settings across a power-down/up cycle */
++ iegbe_read_phy_reg(hw, PHY_CTRL, &mii_reg);
++ mii_reg &= ~MII_CR_POWER_DOWN;
++ iegbe_write_phy_reg(hw, PHY_CTRL, mii_reg);
++ }
++}
+
+- /* If WoL is not enabled and management mode is not IAMT
+- * or if WoL is not enabled and OEM PHY is copper based,
+- * power down the PHY so no link is implied when interface is down */
+- if(!adapter->wol
+- && ((adapter->hw.mac_type >= iegbe_82540
+- && adapter->hw.media_type == iegbe_media_type_copper
+- && !iegbe_check_mng_mode(&adapter->hw)
+- && !(E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN))
+- || (adapter->hw.media_type == iegbe_media_type_oem
+- && iegbe_oem_phy_is_copper(&adapter->hw)))){
++static void iegbe_power_down_phy(struct iegbe_adapter *adapter)
++{
++ struct iegbe_hw *hw = &adapter->hw;
+
+- uint16_t mii_reg;
+- iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
++ /* Power down the PHY so no link is implied when interface is down *
++ * The PHY cannot be powered down if any of the following is true *
++ * (a) WoL is enabled
++ * (b) AMT is active
++ * (c) SoL/IDER session is active */
++ if (!adapter->wol && hw->mac_type >= iegbe_82540 &&
++ hw->media_type == iegbe_media_type_copper) {
++ u16 mii_reg = 0;
++
++ switch (hw->mac_type) {
++ case iegbe_82540:
++ case iegbe_82545:
++ case iegbe_82545_rev_3:
++ case iegbe_82546:
++ case iegbe_82546_rev_3:
++ case iegbe_82541:
++ case iegbe_82541_rev_2:
++ case iegbe_82547:
++ case iegbe_82547_rev_2:
++ if (E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN)
++ goto out;
++ break;
++ case iegbe_82571:
++ case iegbe_82572:
++ case iegbe_82573:
++ if (iegbe_check_mng_mode(hw) ||
++ iegbe_check_phy_reset_block(hw))
++ goto out;
++ break;
++ default:
++ goto out;
++ }
++ iegbe_read_phy_reg(hw, PHY_CTRL, &mii_reg);
+ mii_reg |= MII_CR_POWER_DOWN;
+- iegbe_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg);
++ iegbe_write_phy_reg(hw, PHY_CTRL, mii_reg);
+ mdelay(1);
+ }
++out:
++ return;
+ }
+
+-void
+-iegbe_reset(struct iegbe_adapter *adapter)
++void iegbe_down(struct iegbe_adapter *adapter)
+ {
+- struct net_device *netdev = adapter->netdev;
+- uint32_t pba, manc;
+- uint16_t fc_high_water_mark = E1000_FC_HIGH_DIFF;
+- uint16_t fc_low_water_mark = E1000_FC_LOW_DIFF;
++ struct net_device *netdev = adapter->netdev;
+
++ /* signal that we're down so the interrupt handler does not
++ * reschedule our watchdog timer */
++ set_bit(__E1000_DOWN, &adapter->flags);
+
+- /* Repartition Pba for greater than 9k mtu
+- * To take effect CTRL.RST is required.
+- */
++ napi_disable(&adapter->napi);
+
+- switch (adapter->hw.mac_type) {
+- case iegbe_82547:
+- case iegbe_82547_rev_2:
+- pba = E1000_PBA_30K;
+- break;
+- case iegbe_82571:
+- case iegbe_82572:
+- pba = E1000_PBA_38K;
+- break;
+- case iegbe_82573:
+- pba = E1000_PBA_12K;
++ iegbe_irq_disable(adapter);
++
++ del_timer_sync(&adapter->tx_fifo_stall_timer);
++ del_timer_sync(&adapter->watchdog_timer);
++ del_timer_sync(&adapter->phy_info_timer);
++
++ netdev->tx_queue_len = adapter->tx_queue_len;
++ adapter->link_speed = 0;
++ adapter->link_duplex = 0;
++ netif_carrier_off(netdev);
++ netif_stop_queue(netdev);
++
++ iegbe_reset(adapter);
++ iegbe_clean_all_tx_rings(adapter);
++ iegbe_clean_all_rx_rings(adapter);
++}
++void iegbe_reinit_locked(struct iegbe_adapter *adapter)
++{
++ WARN_ON(in_interrupt());
++ while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
++ msleep(1);
++ iegbe_down(adapter);
++ iegbe_up(adapter);
++ clear_bit(__E1000_RESETTING, &adapter->flags);
++}
++
++void iegbe_reset(struct iegbe_adapter *adapter)
++{
++ struct iegbe_hw *hw = &adapter->hw;
++ u32 pba = 0, tx_space, min_tx_space, min_rx_space;
++ u16 fc_high_water_mark = E1000_FC_HIGH_DIFF;
++ bool legacy_pba_adjust = false;
++
++ /* Repartition Pba for greater than 9k mtu
++ * To take effect CTRL.RST is required.
++ */
++
++ switch (hw->mac_type) {
++ case iegbe_82542_rev2_0:
++ case iegbe_82542_rev2_1:
++ case iegbe_82543:
++ case iegbe_82544:
++ case iegbe_82540:
++ case iegbe_82541:
++ case iegbe_82541_rev_2:
++ case iegbe_icp_xxxx:
++ legacy_pba_adjust = true;
++ pba = E1000_PBA_48K;
+ break;
+- default:
++ case iegbe_82545:
++ case iegbe_82545_rev_3:
++ case iegbe_82546:
++ case iegbe_82546_rev_3:
+ pba = E1000_PBA_48K;
+ break;
+- }
++ case iegbe_82547:
++ case iegbe_82573:
++ case iegbe_82547_rev_2:
++ legacy_pba_adjust = true;
++ pba = E1000_PBA_30K;
++ break;
++ case iegbe_82571:
++ case iegbe_82572:
++ case iegbe_undefined:
++ case iegbe_num_macs:
++ break;
++ }
++
++ if (legacy_pba_adjust) {
++ if (adapter->netdev->mtu > E1000_RXBUFFER_8192)
++ pba -= 8; /* allocate more FIFO for Tx */
++ /* send an XOFF when there is enough space in the
++ * Rx FIFO to hold one extra full size Rx packet
++ */
+
+- if((adapter->hw.mac_type != iegbe_82573) &&
+- (adapter->rx_buffer_len > E1000_RXBUFFER_8192)) {
+- pba -= 0x8; /* allocate more FIFO for Tx */
+- /* send an XOFF when there is enough space in the
+- * Rx FIFO to hold one extra full size Rx packet
+- */
+- fc_high_water_mark = netdev->mtu + ENET_HEADER_SIZE +
+- ETHERNET_FCS_SIZE + 0x1;
+- fc_low_water_mark = fc_high_water_mark + 0x8;
+- }
+
++ if (hw->mac_type == iegbe_82547) {
++ adapter->tx_fifo_head = 0;
++ adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
++ adapter->tx_fifo_size =
++ (E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT;
++ atomic_set(&adapter->tx_fifo_stall, 0);
++ }
++ } else if (hw->max_frame_size > MAXIMUM_ETHERNET_FRAME_SIZE) {
++ E1000_WRITE_REG(&adapter->hw, PBA, pba);
++
++ /* To maintain wire speed transmits, the Tx FIFO should be
++ * large enough to accomodate two full transmit packets,
++ * rounded up to the next 1KB and expressed in KB. Likewise,
++ * the Rx FIFO should be large enough to accomodate at least
++ * one full receive packet and is similarly rounded up and
++ * expressed in KB. */
++ pba = E1000_READ_REG(&adapter->hw, PBA);
++ /* upper 16 bits has Tx packet buffer allocation size in KB */
++ tx_space = pba >> 16;
++ /* lower 16 bits has Rx packet buffer allocation size in KB */
++ pba &= 0xffff;
++ /* don't include ethernet FCS because hardware appends/strips */
++ min_rx_space = adapter->netdev->mtu + ENET_HEADER_SIZE +
++ VLAN_TAG_SIZE;
++ min_tx_space = min_rx_space;
++ min_tx_space *= 2;
++ min_tx_space = ALIGN(min_tx_space, 1024);
++ min_tx_space >>= 10;
++ min_rx_space = ALIGN(min_rx_space, 1024);
++ min_rx_space >>= 10;
++
++ /* If current Tx allocation is less than the min Tx FIFO size,
++ * and the min Tx FIFO size is less than the current Rx FIFO
++ * allocation, take space away from current Rx allocation */
++ if (tx_space < min_tx_space &&
++ ((min_tx_space - tx_space) < pba)) {
++ pba = pba - (min_tx_space - tx_space);
++
++ /* PCI/PCIx hardware has PBA alignment constraints */
++ switch (hw->mac_type) {
++ case iegbe_82545 ... iegbe_82546_rev_3:
++ pba &= ~(E1000_PBA_8K - 1);
++ break;
++ default:
++ break;
++ }
+
+- if(adapter->hw.mac_type == iegbe_82547) {
+- adapter->tx_fifo_head = 0;
+- adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
+- adapter->tx_fifo_size =
+- (E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT;
+- atomic_set(&adapter->tx_fifo_stall, 0);
++ /* if short on rx space, rx wins and must trump tx
++ * adjustment or use Early Receive if available */
++ if (pba < min_rx_space) {
++ switch (hw->mac_type) {
++ case iegbe_82573:
++ /* ERT enabled in iegbe_configure_rx */
++ break;
++ default:
++ pba = min_rx_space;
++ break;
++ }
++ }
++ }
+ }
+
+ E1000_WRITE_REG(&adapter->hw, PBA, pba);
+
+ /* flow control settings */
+- adapter->hw.fc_high_water = (pba << E1000_PBA_BYTES_SHIFT) -
+- fc_high_water_mark;
+- adapter->hw.fc_low_water = (pba << E1000_PBA_BYTES_SHIFT) -
+- fc_low_water_mark;
+- adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME;
+- adapter->hw.fc_send_xon = 1;
+- adapter->hw.fc = adapter->hw.original_fc;
++ /* Set the FC high water mark to 90% of the FIFO size.
++ * Required to clear last 3 LSB */
++ fc_high_water_mark = ((pba * 9216)/10) & 0xFFF8;
++ /* We can't use 90% on small FIFOs because the remainder
++ * would be less than 1 full frame. In this case, we size
++ * it to allow at least a full frame above the high water
++ * mark. */
++ if (pba < E1000_PBA_16K)
++ fc_high_water_mark = (pba * 1024) - 1600;
++
++ hw->fc_high_water = fc_high_water_mark;
++ hw->fc_low_water = fc_high_water_mark - 8;
++ hw->fc_pause_time = E1000_FC_PAUSE_TIME;
++ hw->fc_send_xon = 1;
++ hw->fc = hw->original_fc;
+
+ /* Allow time for pending master requests to run */
+- iegbe_reset_hw(&adapter->hw);
+- if(adapter->hw.mac_type >= iegbe_82544){
++ iegbe_reset_hw(hw);
++ if (hw->mac_type >= iegbe_82544)
+ E1000_WRITE_REG(&adapter->hw, WUC, 0);
+- }
+- if(iegbe_init_hw(&adapter->hw)) {
++
++ if (iegbe_init_hw(hw))
+ DPRINTK(PROBE, ERR, "Hardware Error\n");
+- }
+-#ifdef NETIF_F_HW_VLAN_TX
+ iegbe_update_mng_vlan(adapter);
+-#endif
++
++ /* if (adapter->hwflags & HWFLAGS_PHY_PWR_BIT) { */
++ if (hw->mac_type >= iegbe_82544 &&
++ hw->mac_type <= iegbe_82547_rev_2 &&
++ hw->autoneg == 1 &&
++ hw->autoneg_advertised == ADVERTISE_1000_FULL) {
++ u32 ctrl = E1000_READ_REG(&adapter->hw, CTRL);
++ /* clear phy power management bit if we are in gig only mode,
++ * which if enabled will attempt negotiation to 100Mb, which
++ * can cause a loss of link at power off or driver unload */
++ ctrl &= ~E1000_CTRL_SWDPIN3;
++ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
++ }
++
+ /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
+ E1000_WRITE_REG(&adapter->hw, VET, ETHERNET_IEEE_VLAN_TYPE);
+
+- iegbe_reset_adaptive(&adapter->hw);
+- iegbe_phy_get_info(&adapter->hw, &adapter->phy_info);
+- if(adapter->en_mng_pt) {
+- manc = E1000_READ_REG(&adapter->hw, MANC);
+- manc |= (E1000_MANC_ARP_EN | E1000_MANC_EN_MNG2HOST);
+- E1000_WRITE_REG(&adapter->hw, MANC, manc);
++ iegbe_reset_adaptive(hw);
++ iegbe_phy_get_info(hw, &adapter->phy_info);
++
++ if (!adapter->smart_power_down &&
++ (hw->mac_type == iegbe_82571 ||
++ hw->mac_type == iegbe_82572)) {
++ u16 phy_data = 0;
++ /* speed up time to link by disabling smart power down, ignore
++ * the return value of this function because there is nothing
++ * different we would do if it failed */
++ iegbe_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
++ &phy_data);
++ phy_data &= ~IGP02E1000_PM_SPD;
++ iegbe_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
++ phy_data);
++ }
++
++}
++
++/**
++ * Dump the eeprom for users having checksum issues
++ **/
++static void iegbe_dump_eeprom(struct iegbe_adapter *adapter)
++{
++ struct net_device *netdev = adapter->netdev;
++ struct ethtool_eeprom eeprom;
++ const struct ethtool_ops *ops = netdev->ethtool_ops;
++ u8 *data;
++ int i;
++ u16 csum_old, csum_new = 0;
++
++ eeprom.len = ops->get_eeprom_len(netdev);
++ eeprom.offset = 0;
++
++ data = kmalloc(eeprom.len, GFP_KERNEL);
++ if (!data) {
++ printk(KERN_ERR "Unable to allocate memory to dump EEPROM"
++ " data\n");
++ return;
+ }
++
++ ops->get_eeprom(netdev, &eeprom, data);
++
++ csum_old = (data[EEPROM_CHECKSUM_REG * 2]) +
++ (data[EEPROM_CHECKSUM_REG * 2 + 1] << 8);
++ for (i = 0; i < EEPROM_CHECKSUM_REG * 2; i += 2)
++ csum_new += data[i] + (data[i + 1] << 8);
++ csum_new = EEPROM_SUM - csum_new;
++
++ printk(KERN_ERR "/*********************/\n");
++ printk(KERN_ERR "Current EEPROM Checksum : 0x%04x\n", csum_old);
++ printk(KERN_ERR "Calculated : 0x%04x\n", csum_new);
++
++ printk(KERN_ERR "Offset Values\n");
++ printk(KERN_ERR "======== ======\n");
++ print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, data, 128, 0);
++
++ printk(KERN_ERR "Include this output when contacting your support "
++ "provider.\n");
++ printk(KERN_ERR "This is not a software error! Something bad "
++ "happened to your hardware or\n");
++ printk(KERN_ERR "EEPROM image. Ignoring this "
++ "problem could result in further problems,\n");
++ printk(KERN_ERR "possibly loss of data, corruption or system hangs!\n");
++ printk(KERN_ERR "The MAC Address will be reset to 00:00:00:00:00:00, "
++ "which is invalid\n");
++ printk(KERN_ERR "and requires you to set the proper MAC "
++ "address manually before continuing\n");
++ printk(KERN_ERR "to enable this network device.\n");
++ printk(KERN_ERR "Please inspect the EEPROM dump and report the issue "
++ "to your hardware vendor\n");
++ printk(KERN_ERR "or Intel Customer Support.\n");
++ printk(KERN_ERR "/*********************/\n");
++
++ kfree(data);
+ }
+
+ /**
+@@ -721,184 +735,166 @@ iegbe_reset(struct iegbe_adapter *adapte
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ **/
+-
+-static int __devinit
+-iegbe_probe(struct pci_dev *pdev,
++static int __devinit iegbe_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+ {
+- struct net_device *netdev;
+- struct iegbe_adapter *adapter;
+- unsigned long mmio_start, mmio_len;
+- uint32_t ctrl_ext;
+- uint32_t swsm;
++ struct net_device *netdev;
++ struct iegbe_adapter *adapter;
++ struct iegbe_hw *hw;
+
+ static int cards_found = 0;
++ int i, err, pci_using_dac;
++ u16 eeprom_data = 0;
++ u16 eeprom_apme_mask = E1000_EEPROM_APME;
++ int bars;
++ DECLARE_MAC_BUF(mac);
+
+- int i, err, pci_using_dac;
+- uint16_t eeprom_data = 0;
+- uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
++ bars = pci_select_bars(pdev, IORESOURCE_MEM);
++ err = pci_enable_device(pdev);
+
++ if (err)
++ return err;
+
+- if((err = pci_enable_device(pdev))) {
+- return err;
+- }
+- if(!(err = pci_set_dma_mask(pdev, PCI_DMA_64BIT))) {
++ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK) &&
++ !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
+ pci_using_dac = 1;
+- } else {
+- if((err = pci_set_dma_mask(pdev, PCI_DMA_32BIT))) {
+- E1000_ERR("No usable DMA configuration, aborting\n");
+- return err;
+- }
++ } else {
++ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
++ if (err) {
++ err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
++ if (err) {
++ E1000_ERR("No usable DMA configuration, "
++ "aborting\n");
++ goto err_dma;
++ }
++ }
+ pci_using_dac = 0;
+- }
+-
+- if((err = pci_request_regions(pdev, iegbe_driver_name))) {
+- return err;
+ }
+- pci_set_master(pdev);
+
+- netdev = alloc_etherdev(sizeof(struct iegbe_adapter));
+- if(!netdev) {
+- err = -ENOMEM;
+- goto err_alloc_etherdev;
+- }
++ err = pci_request_selected_regions(pdev, bars, iegbe_driver_name);
++ if (err)
++ goto err_pci_reg;
++
++ pci_set_master(pdev);
++
++ err = -ENOMEM;
++ netdev = alloc_etherdev(sizeof(struct iegbe_adapter));
++ if (!netdev)
++ goto err_alloc_etherdev;
+
+- SET_MODULE_OWNER(netdev);
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+
+- pci_set_drvdata(pdev, netdev);
+- adapter = netdev_priv(netdev);
+- adapter->netdev = netdev;
+- adapter->pdev = pdev;
+- adapter->hw.back = adapter;
+- adapter->msg_enable = (0x1 << debug) - 0x1;
+-
+- mmio_start = pci_resource_start(pdev, BAR_0);
+- mmio_len = pci_resource_len(pdev, BAR_0);
+-
+- adapter->hw.hw_addr = ioremap(mmio_start, mmio_len);
+- if(!adapter->hw.hw_addr) {
+- err = -EIO;
+- goto err_ioremap;
+- }
+-
+- for(i = BAR_1; i <= BAR_5; i++) {
+- if(pci_resource_len(pdev, i) == 0) {
+- continue;
+- }
+- if(pci_resource_flags(pdev, i) & IORESOURCE_IO) {
+- adapter->hw.io_base = pci_resource_start(pdev, i);
+- break;
+- }
+- }
+-
+- netdev->open = &iegbe_open;
+- netdev->stop = &iegbe_close;
+- netdev->hard_start_xmit = &iegbe_xmit_frame;
+- netdev->get_stats = &iegbe_get_stats;
+- netdev->set_multicast_list = &iegbe_set_multi;
++ pci_set_drvdata(pdev, netdev);
++ adapter = netdev_priv(netdev);
++ adapter->netdev = netdev;
++ adapter->pdev = pdev;
++ adapter->msg_enable = (1 << debug) - 1;
++ adapter->bars = bars;
++
++ hw = &adapter->hw;
++ hw->back = adapter;
++
++ err = -EIO;
++ hw->hw_addr = ioremap(pci_resource_start(pdev, BAR_0),
++ pci_resource_len(pdev, BAR_0));
++ if (!hw->hw_addr)
++ goto err_ioremap;
++
++ netdev->open = &iegbe_open;
++ netdev->stop = &iegbe_close;
++ netdev->hard_start_xmit = &iegbe_xmit_frame;
++ netdev->get_stats = &iegbe_get_stats;
++ netdev->set_rx_mode = &iegbe_set_rx_mode;
+ netdev->set_mac_address = &iegbe_set_mac;
+- netdev->change_mtu = &iegbe_change_mtu;
+- netdev->do_ioctl = &iegbe_ioctl;
++ netdev->change_mtu = &iegbe_change_mtu;
++ netdev->do_ioctl = &iegbe_ioctl;
+ set_ethtool_ops(netdev);
+-#ifdef HAVE_TX_TIMEOUT
+- netdev->tx_timeout = &iegbe_tx_timeout;
+- netdev->watchdog_timeo = 0x5 * HZ;
+-#endif
+-#ifdef CONFIG_E1000_NAPI
+- netdev->poll = &iegbe_clean;
+- netdev->weight = 0x40;
+-#endif
+-#ifdef NETIF_F_HW_VLAN_TX
+- netdev->vlan_rx_register = iegbe_vlan_rx_register;
+- netdev->vlan_rx_add_vid = iegbe_vlan_rx_add_vid;
+- netdev->vlan_rx_kill_vid = iegbe_vlan_rx_kill_vid;
+-#endif
++ netdev->tx_timeout = &iegbe_tx_timeout;
++ netdev->watchdog_timeo = 5 * HZ;
++ netif_napi_add(netdev, &adapter->napi, iegbe_clean, 64);
++ netdev->vlan_rx_register = iegbe_vlan_rx_register;
++ netdev->vlan_rx_add_vid = iegbe_vlan_rx_add_vid;
++ netdev->vlan_rx_kill_vid = iegbe_vlan_rx_kill_vid;
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+- netdev->poll_controller = iegbe_netpoll;
++ netdev->poll_controller = iegbe_netpoll;
+ #endif
+- strcpy(netdev->name, pci_name(pdev));
++ strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
+
+- netdev->mem_start = mmio_start;
+- netdev->mem_end = mmio_start + mmio_len;
+- netdev->base_addr = adapter->hw.io_base;
+
+- adapter->bd_number = cards_found;
++ adapter->bd_number = cards_found;
+
+- /* setup the private structure */
++ /* setup the private structure */
+
+- if((err = iegbe_sw_init(adapter))) {
+- goto err_sw_init;
+- }
+- if((err = iegbe_check_phy_reset_block(&adapter->hw))) {
+- DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
+- }
+-#ifdef MAX_SKB_FRAGS
+- if(adapter->hw.mac_type >= iegbe_82543) {
+-#ifdef NETIF_F_HW_VLAN_TX
+- netdev->features = NETIF_F_SG |
+- NETIF_F_HW_CSUM |
+- NETIF_F_HW_VLAN_TX |
+- NETIF_F_HW_VLAN_RX |
+- NETIF_F_HW_VLAN_FILTER;
+-#else
+- netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM;
+-#endif
+- }
++ err = iegbe_sw_init(adapter);
++ if (err)
++ goto err_sw_init;
++ err = -EIO;
++ if (iegbe_check_phy_reset_block(hw))
++ DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
+
+-#ifdef NETIF_F_TSO
+- if((adapter->hw.mac_type >= iegbe_82544) &&
+- (adapter->hw.mac_type != iegbe_82547)) {
+- netdev->features |= NETIF_F_TSO;
+- }
+-#ifdef NETIF_F_TSO_IPV6
+- if(adapter->hw.mac_type > iegbe_82547_rev_2) {
+- netdev->features |= NETIF_F_TSO_IPV6;
+- }
+-#endif
+-#endif
+- if(pci_using_dac) {
+- netdev->features |= NETIF_F_HIGHDMA;
++ if (hw->mac_type >= iegbe_82543) {
++ netdev->features = NETIF_F_SG |
++ NETIF_F_HW_CSUM |
++ NETIF_F_HW_VLAN_TX |
++ NETIF_F_HW_VLAN_RX |
++ NETIF_F_HW_VLAN_FILTER;
+ }
+-#endif
+-#ifdef NETIF_F_LLTX
+- netdev->features |= NETIF_F_LLTX;
+-#endif
+
+- adapter->en_mng_pt = iegbe_enable_mng_pass_thru(&adapter->hw);
++ if ((hw->mac_type >= iegbe_82544) &&
++ (hw->mac_type != iegbe_82547))
++ netdev->features |= NETIF_F_TSO;
+
+- /* before reading the EEPROM, reset the controller to
+- * put the device in a known good starting state */
++ if (hw->mac_type > iegbe_82547_rev_2)
++ netdev->features |= NETIF_F_TSO6;
++ if (pci_using_dac)
++ netdev->features |= NETIF_F_HIGHDMA;
++
++ netdev->features |= NETIF_F_LLTX;
+
+- iegbe_reset_hw(&adapter->hw);
++ adapter->en_mng_pt = iegbe_enable_mng_pass_thru(hw);
+
+- /* make sure the EEPROM is good */
+- if(iegbe_validate_eeprom_checksum(&adapter->hw) < 0) {
+- DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n");
+- err = -EIO;
++ /* initialize eeprom parameters */
++
++ if (iegbe_init_eeprom_params(hw)) {
++ E1000_ERR("EEPROM initialization failed\n");
+ goto err_eeprom;
+ }
+
+- /* copy the MAC address out of the EEPROM */
++ /* before reading the EEPROM, reset the controller to
++ * put the device in a known good starting state */
+
+- if(iegbe_read_mac_addr(&adapter->hw)) {
+- DPRINTK(PROBE, ERR, "EEPROM Read Error\n");
+- }
+- memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
++ iegbe_reset_hw(hw);
+
+- if(!is_valid_ether_addr(netdev->dev_addr)) {
+- DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
+- err = -EIO;
+- goto err_eeprom;
+- }
++ /* make sure the EEPROM is good */
++ if (iegbe_validate_eeprom_checksum(hw) < 0) {
++ DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n");
++ iegbe_dump_eeprom(adapter);
++ /*
++ * set MAC address to all zeroes to invalidate and temporary
++ * disable this device for the user. This blocks regular
++ * traffic while still permitting ethtool ioctls from reaching
++ * the hardware as well as allowing the user to run the
++ * interface after manually setting a hw addr using
++ * `ip set address`
++ */
++ memset(hw->mac_addr, 0, netdev->addr_len);
++ } else {
++ /* copy the MAC address out of the EEPROM */
++ if (iegbe_read_mac_addr(hw))
++ DPRINTK(PROBE, ERR, "EEPROM Read Error\n");
++ }
++ /* don't block initalization here due to bad MAC address */
++ memcpy(netdev->dev_addr, hw->mac_addr, netdev->addr_len);
++ memcpy(netdev->perm_addr, hw->mac_addr, netdev->addr_len);
+
+- iegbe_read_part_num(&adapter->hw, &(adapter->part_num));
++ if (!is_valid_ether_addr(netdev->perm_addr))
++ DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
+
+- iegbe_get_bus_info(&adapter->hw);
++ iegbe_get_bus_info(hw);
+
+ init_timer(&adapter->tx_fifo_stall_timer);
+ adapter->tx_fifo_stall_timer.function = &iegbe_82547_tx_fifo_stall;
+- adapter->tx_fifo_stall_timer.data = (unsigned long) adapter;
++ adapter->tx_fifo_stall_timer.data = (unsigned long)adapter;
+
+ init_timer(&adapter->watchdog_timer);
+ adapter->watchdog_timer.function = &iegbe_watchdog;
+@@ -906,75 +902,50 @@ iegbe_probe(struct pci_dev *pdev,
+
+ init_timer(&adapter->phy_info_timer);
+ adapter->phy_info_timer.function = &iegbe_update_phy_info;
+- adapter->phy_info_timer.data = (unsigned long) adapter;
+-
+- INIT_WORK(&adapter->tx_timeout_task,
+- (void (*)(void *))iegbe_tx_timeout_task, netdev);
++ adapter->phy_info_timer.data = (unsigned long)adapter;
+
+- /* we're going to reset, so assume we have no link for now */
+-
+- netif_carrier_off(netdev);
+- netif_stop_queue(netdev);
++ INIT_WORK(&adapter->reset_task, iegbe_reset_task);
+
+- iegbe_check_options(adapter);
++ iegbe_check_options(adapter);
+
+- /* Initial Wake on LAN setting
+- * If APM wake is enabled in the EEPROM,
+- * enable the ACPI Magic Packet filter
+- */
++ /* Initial Wake on LAN setting
++ * If APM wake is enabled in the EEPROM,
++ * enable the ACPI Magic Packet filter
++ */
+
+- switch(adapter->hw.mac_type) {
+- case iegbe_82542_rev2_0:
+- case iegbe_82542_rev2_1:
+- case iegbe_82543:
+- break;
+- case iegbe_82544:
+- iegbe_read_eeprom(&adapter->hw,
+- EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data);
+- eeprom_apme_mask = E1000_EEPROM_82544_APM;
+- break;
++ switch(adapter->hw.mac_type) {
++ case iegbe_82542_rev2_0:
++ case iegbe_82542_rev2_1:
++ case iegbe_82543:
++ break;
++ case iegbe_82544:
++ iegbe_read_eeprom(&adapter->hw,
++ EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data);
++ eeprom_apme_mask = E1000_EEPROM_82544_APM;
++ break;
+ case iegbe_icp_xxxx:
+- iegbe_read_eeprom(&adapter->hw,
+- EEPROM_INIT_CONTROL3_ICP_xxxx(adapter->bd_number),
+- 1, &eeprom_data);
+- eeprom_apme_mask = EEPROM_CTRL3_APME_ICP_xxxx;
+- break;
+- case iegbe_82546:
+- case iegbe_82546_rev_3:
+- if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1)
+- && (adapter->hw.media_type == iegbe_media_type_copper)) {
+- iegbe_read_eeprom(&adapter->hw,
+- EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
+- break;
+- }
+- /* Fall Through */
+- default:
+- iegbe_read_eeprom(&adapter->hw,
+- EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
+- break;
+- }
++ iegbe_read_eeprom(&adapter->hw,
++ EEPROM_INIT_CONTROL3_ICP_xxxx(adapter->bd_number),
++ 1, &eeprom_data);
++ eeprom_apme_mask = EEPROM_CTRL3_APME_ICP_xxxx;
++ break;
++ case iegbe_82546:
++ case iegbe_82546_rev_3:
++ if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1)
++ && (adapter->hw.media_type == iegbe_media_type_copper)) {
++ iegbe_read_eeprom(&adapter->hw,
++ EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
++ break;
++ }
++ /* Fall Through */
++ default:
++ iegbe_read_eeprom(&adapter->hw,
++ EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
++ break;
++ }
+ if(eeprom_data & eeprom_apme_mask) {
+- adapter->wol |= E1000_WUFC_MAG;
++ adapter->wol |= E1000_WUFC_MAG;
+ }
+- /* reset the hardware with the new settings */
+- iegbe_reset(adapter);
+-
+- /* Let firmware know the driver has taken over */
+- switch(adapter->hw.mac_type) {
+- case iegbe_82571:
+- case iegbe_82572:
+- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+- E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+- ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
+- break;
+- case iegbe_82573:
+- swsm = E1000_READ_REG(&adapter->hw, SWSM);
+- E1000_WRITE_REG(&adapter->hw, SWSM,
+- swsm | E1000_SWSM_DRV_LOAD);
+- break;
+- default:
+- break;
+- }
+
+ /* The ICP_xxxx device has multiple, duplicate interrupt
+ * registers, so disable all but the first one
+@@ -987,24 +958,40 @@ iegbe_probe(struct pci_dev *pdev,
+ E1000_WRITE_REG(&adapter->hw, IMC2, ~0UL);
+ }
+
+- strcpy(netdev->name, "eth%d");
+- if((err = register_netdev(netdev))) {
+- goto err_register;
+- }
++ iegbe_reset(adapter);
++ netif_carrier_off(netdev);
++ netif_stop_queue(netdev);
++ strcpy(netdev->name, "eth%d");
++ err = register_netdev(netdev);
++ if (err)
++ goto err_register;
++
+ DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n");
+
+- cards_found++;
+- return 0;
++ cards_found++;
++ return 0;
+
+ err_register:
+-err_sw_init:
+ err_eeprom:
+- iounmap(adapter->hw.hw_addr);
++ if (!iegbe_check_phy_reset_block(hw))
++ iegbe_phy_hw_reset(hw);
++ if (hw->flash_address)
++ iounmap(hw->flash_address);
++ for (i = 0; i < adapter->num_rx_queues; i++)
++ dev_put(&adapter->polling_netdev[i]);
++ kfree(adapter->tx_ring);
++ kfree(adapter->rx_ring);
++ kfree(adapter->polling_netdev);
++err_sw_init:
++ iounmap(hw->hw_addr);
+ err_ioremap:
+- free_netdev(netdev);
++ free_netdev(netdev);
+ err_alloc_etherdev:
+- pci_release_regions(pdev);
+- return err;
++ pci_release_selected_regions(pdev, bars);
++err_pci_reg:
++err_dma:
++ pci_disable_device(pdev);
++ return err;
+ }
+
+ /**
+@@ -1020,64 +1007,36 @@ err_alloc_etherdev:
+ static void __devexit
+ iegbe_remove(struct pci_dev *pdev)
+ {
+- struct net_device *netdev = pci_get_drvdata(pdev);
+- struct iegbe_adapter *adapter = netdev_priv(netdev);
+- uint32_t ctrl_ext;
+- uint32_t manc, swsm;
+-#ifdef CONFIG_E1000_NAPI
+- int i;
+-#endif
+-
+- if(adapter->hw.mac_type >= iegbe_82540
+- && adapter->hw.mac_type != iegbe_icp_xxxx
+- && adapter->hw.media_type == iegbe_media_type_copper) {
+- manc = E1000_READ_REG(&adapter->hw, MANC);
+- if(manc & E1000_MANC_SMBUS_EN) {
+- manc |= E1000_MANC_ARP_EN;
+- E1000_WRITE_REG(&adapter->hw, MANC, manc);
+- }
+- }
+-
+- switch(adapter->hw.mac_type) {
+- case iegbe_82571:
+- case iegbe_82572:
+- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+- E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+- ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
+- break;
+- case iegbe_82573:
+- swsm = E1000_READ_REG(&adapter->hw, SWSM);
+- E1000_WRITE_REG(&adapter->hw, SWSM,
+- swsm & ~E1000_SWSM_DRV_LOAD);
+- break;
+-
+- default:
+- break;
+- }
++ struct net_device *netdev = pci_get_drvdata(pdev);
++ struct iegbe_adapter *adapter = netdev_priv(netdev);
++ uint32_t manc;
++ int i;
++
++ if(adapter->hw.mac_type >= iegbe_82540
++ && adapter->hw.mac_type != iegbe_icp_xxxx
++ && adapter->hw.media_type == iegbe_media_type_copper) {
++ manc = E1000_READ_REG(&adapter->hw, MANC);
++ if(manc & E1000_MANC_SMBUS_EN) {
++ manc |= E1000_MANC_ARP_EN;
++ E1000_WRITE_REG(&adapter->hw, MANC, manc);
++ }
++ }
+
+- unregister_netdev(netdev);
+-#ifdef CONFIG_E1000_NAPI
+- for (i = 0; i < adapter->num_queues; i++)
++ unregister_netdev(netdev);
++ for (i = 0x0; i < adapter->num_rx_queues; i++)
+ dev_put(&adapter->polling_netdev[i]);
+-#endif
+
+ if(!iegbe_check_phy_reset_block(&adapter->hw)) {
+- iegbe_phy_hw_reset(&adapter->hw);
++ iegbe_phy_hw_reset(&adapter->hw);
+ }
+- kfree(adapter->tx_ring);
+- kfree(adapter->rx_ring);
+-#ifdef CONFIG_E1000_NAPI
+- kfree(adapter->polling_netdev);
+-#endif
++ kfree(adapter->tx_ring);
++ kfree(adapter->rx_ring);
++ kfree(adapter->polling_netdev);
+
+- iounmap(adapter->hw.hw_addr);
+- pci_release_regions(pdev);
++ iounmap(adapter->hw.hw_addr);
++ pci_release_regions(pdev);
+
+-#ifdef CONFIG_E1000_MQ
+- free_percpu(adapter->cpu_netdev);
+- free_percpu(adapter->cpu_tx_ring);
+-#endif
+- free_netdev(netdev);
++ free_netdev(netdev);
+ }
+
+ /**
+@@ -1092,118 +1051,78 @@ iegbe_remove(struct pci_dev *pdev)
+ static int __devinit
+ iegbe_sw_init(struct iegbe_adapter *adapter)
+ {
+- struct iegbe_hw *hw = &adapter->hw;
+- struct net_device *netdev = adapter->netdev;
+- struct pci_dev *pdev = adapter->pdev;
+-#ifdef CONFIG_E1000_NAPI
+- int i;
+-#endif
++ struct iegbe_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ struct pci_dev *pdev = adapter->pdev;
++ int i;
+
+- /* PCI config space info */
++ /* PCI config space info */
+
+- hw->vendor_id = pdev->vendor;
+- hw->device_id = pdev->device;
+- hw->subsystem_vendor_id = pdev->subsystem_vendor;
+- hw->subsystem_id = pdev->subsystem_device;
++ hw->vendor_id = pdev->vendor;
++ hw->device_id = pdev->device;
++ hw->subsystem_vendor_id = pdev->subsystem_vendor;
++ hw->subsystem_id = pdev->subsystem_device;
+
+- pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
++ pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
+
+- pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
++ pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
+
+- adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+- adapter->rx_ps_bsize0 = E1000_RXBUFFER_256;
+- hw->max_frame_size = netdev->mtu +
+- ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
+- hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
++ adapter->rx_buffer_len = E1000_RXBUFFER_2048;
++ adapter->rx_ps_bsize0 = E1000_RXBUFFER_256;
++ hw->max_frame_size = netdev->mtu +
++ ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
++ hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
+
+- /* identify the MAC */
++ /* identify the MAC */
+
+- if(iegbe_set_mac_type(hw)) {
++ if (iegbe_set_mac_type(hw)) {
+ DPRINTK(PROBE, ERR, "Unknown MAC Type\n");
+ return -EIO;
+ }
+
+- /* initialize eeprom parameters */
+-
+- if(iegbe_init_eeprom_params(hw)) {
+- E1000_ERR("EEPROM initialization failed\n");
+- return -EIO;
+- }
+-
+- switch(hw->mac_type) {
+- default:
+- break;
+- case iegbe_82541:
+- case iegbe_82547:
+- case iegbe_82541_rev_2:
+- case iegbe_82547_rev_2:
+- hw->phy_init_script = 0x1;
+- break;
+- }
+-
+- iegbe_set_media_type(hw);
++ iegbe_set_media_type(hw);
+
+- hw->wait_autoneg_complete = FALSE;
+- hw->tbi_compatibility_en = TRUE;
+- hw->adaptive_ifs = TRUE;
++ hw->wait_autoneg_complete = FALSE;
++ hw->tbi_compatibility_en = TRUE;
++ hw->adaptive_ifs = TRUE;
+
+- /* Copper options */
++ /* Copper options */
+
+- if(hw->media_type == iegbe_media_type_copper
++ if(hw->media_type == iegbe_media_type_copper
+ || (hw->media_type == iegbe_media_type_oem
+ && iegbe_oem_phy_is_copper(&adapter->hw))) {
+- hw->mdix = AUTO_ALL_MODES;
+- hw->disable_polarity_correction = FALSE;
+- hw->master_slave = E1000_MASTER_SLAVE;
+- }
++ hw->mdix = AUTO_ALL_MODES;
++ hw->disable_polarity_correction = FALSE;
++ hw->master_slave = E1000_MASTER_SLAVE;
++ }
+
+-#ifdef CONFIG_E1000_MQ
+- /* Number of supported queues */
+- switch (hw->mac_type) {
+- case iegbe_82571:
+- case iegbe_82572:
+- adapter->num_queues = 0x2;
+- break;
+- default:
+- adapter->num_queues = 0x1;
+- break;
+- }
+- adapter->num_queues = min(adapter->num_queues, num_online_cpus());
+-#else
+- adapter->num_queues = 0x1;
+-#endif
++ adapter->num_tx_queues = 0x1;
++ adapter->num_rx_queues = 0x1;
+
+ if (iegbe_alloc_queues(adapter)) {
+ DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n");
+ return -ENOMEM;
+ }
+
+-#ifdef CONFIG_E1000_NAPI
+- for (i = 0; i < adapter->num_queues; i++) {
++ for (i = 0; i < adapter->num_rx_queues; i++) {
+ adapter->polling_netdev[i].priv = adapter;
+- adapter->polling_netdev[i].poll = &iegbe_clean;
+- adapter->polling_netdev[i].weight = 0x40;
+ dev_hold(&adapter->polling_netdev[i]);
+ set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state);
+ }
+-#endif
+-
+-#ifdef CONFIG_E1000_MQ
+- iegbe_setup_queue_mapping(adapter);
+-#endif
++ spin_lock_init(&adapter->tx_queue_lock);
+
+ /*
+- * for ICP_XXXX style controllers, it is necessary to keep
+- * track of the last known state of the link to determine if
+- * the link experienced a change in state when iegbe_watchdog
+- * fires
+- */
+- adapter->hw.icp_xxxx_is_link_up = FALSE;
++ * for ICP_XXXX style controllers, it is necessary to keep
++ * track of the last known state of the link to determine if
++ * the link experienced a change in state when iegbe_watchdog
++ * fires
++ */
++ adapter->hw.icp_xxxx_is_link_up = FALSE;
+
+- atomic_set(&adapter->irq_sem, 1);
+- spin_lock_init(&adapter->stats_lock);
++ spin_lock_init(&adapter->stats_lock);
+
+- return 0;
++ set_bit(__E1000_DOWN, &adapter->flags);
++ return 0x0;
+ }
+
+ /**
+@@ -1218,71 +1137,31 @@ iegbe_sw_init(struct iegbe_adapter *adap
+ static int __devinit
+ iegbe_alloc_queues(struct iegbe_adapter *adapter)
+ {
+- int size;
+
+- size = sizeof(struct iegbe_tx_ring) * adapter->num_queues;
+- adapter->tx_ring = kmalloc(size, GFP_KERNEL);
+- if (!adapter->tx_ring){
++
++ adapter->tx_ring = kcalloc(adapter->num_tx_queues,
++ sizeof(struct iegbe_tx_ring), GFP_KERNEL);
++ if (!adapter->tx_ring)
+ return -ENOMEM;
+- }
+- memset(adapter->tx_ring, 0, size);
+
+- size = sizeof(struct iegbe_rx_ring) * adapter->num_queues;
+- adapter->rx_ring = kmalloc(size, GFP_KERNEL);
++ adapter->rx_ring = kcalloc(adapter->num_rx_queues,
++ sizeof(struct iegbe_rx_ring), GFP_KERNEL);
+ if (!adapter->rx_ring) {
+ kfree(adapter->tx_ring);
+ return -ENOMEM;
+ }
+- memset(adapter->rx_ring, 0, size);
+
+-#ifdef CONFIG_E1000_NAPI
+- size = sizeof(struct net_device) * adapter->num_queues;
+- adapter->polling_netdev = kmalloc(size, GFP_KERNEL);
++ adapter->polling_netdev = kcalloc(adapter->num_rx_queues,
++ sizeof(struct net_device),
++ GFP_KERNEL);
+ if (!adapter->polling_netdev) {
+ kfree(adapter->tx_ring);
+ kfree(adapter->rx_ring);
+ return -ENOMEM;
+ }
+- memset(adapter->polling_netdev, 0, size);
+-#endif
+-
+- return E1000_SUCCESS;
+-}
+
+-#ifdef CONFIG_E1000_MQ
+-static void __devinit
+-iegbe_setup_queue_mapping(struct iegbe_adapter *adapter)
+-{
+- int i, cpu;
+-
+- adapter->rx_sched_call_data.func = iegbe_rx_schedule;
+- adapter->rx_sched_call_data.info = adapter->netdev;
+- cpus_clear(adapter->rx_sched_call_data.cpumask);
+-
+- adapter->cpu_netdev = alloc_percpu(struct net_device *);
+- adapter->cpu_tx_ring = alloc_percpu(struct iegbe_tx_ring *);
+-
+- lock_cpu_hotplug();
+- i = 0;
+- for_each_online_cpu(cpu) {
+- *per_cpu_ptr(adapter->cpu_tx_ring, cpu) =
+- &adapter->tx_ring[i % adapter->num_queues];
+- /* This is incomplete because we'd like to assign separate
+- * physical cpus to these netdev polling structures and
+- * avoid saturating a subset of cpus.
+- */
+- if (i < adapter->num_queues) {
+- *per_cpu_ptr(adapter->cpu_netdev, cpu) =
+- &adapter->polling_netdev[i];
+- adapter->cpu_for_queue[i] = cpu;
+- } else {
+- *per_cpu_ptr(adapter->cpu_netdev, cpu) = NULL;
+- }
+- i++;
+- }
+- unlock_cpu_hotplug();
++ return E1000_SUCCESS;
+ }
+-#endif
+
+ /**
+ * iegbe_open - Called when a network interface is made active
+@@ -1300,40 +1179,62 @@ iegbe_setup_queue_mapping(struct iegbe_a
+ static int
+ iegbe_open(struct net_device *netdev)
+ {
+- struct iegbe_adapter *adapter = netdev_priv(netdev);
+- int err;
++ struct iegbe_adapter *adapter = netdev_priv(netdev);
++ struct iegbe_hw *hw = &adapter->hw;
++ int err;
++
+
++ /* allocate receive descriptors */
++ if (test_bit(__E1000_TESTING, &adapter->flags))
++ return -EBUSY;
+
+- /* allocate receive descriptors */
++ /* allocate transmit descriptors */
++ err = iegbe_setup_all_tx_resources(adapter);
++ if (err)
++ goto err_setup_tx;
+
+- if ((err = iegbe_setup_all_rx_resources(adapter))) {
++ err = iegbe_setup_all_rx_resources(adapter);
++ if (err)
+ goto err_setup_rx;
+- }
+- /* allocate transmit descriptors */
+- if ((err = iegbe_setup_all_tx_resources(adapter))) {
+- goto err_setup_tx;
+- }
+- if ((err = iegbe_up(adapter))) {
+- goto err_up;
+- }
+-#ifdef NETIF_F_HW_VLAN_TX
+- adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
+- if ((adapter->hw.mng_cookie.status &
+- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
+- iegbe_update_mng_vlan(adapter);
+- }
+-#endif
+
+- return E1000_SUCCESS;
++ iegbe_power_up_phy(adapter);
++ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
++ if ((hw->mng_cookie.status &
++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
++ iegbe_update_mng_vlan(adapter);
++ }
++
++ /* before we allocate an interrupt, we must be ready to handle it.
++ * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
++ * as soon as we call pci_request_irq, so we have to setup our
++ * clean_rx handler before we do so. */
++ iegbe_configure(adapter);
++ err = iegbe_request_irq(adapter);
++ if (err)
++ goto err_req_irq;
+
+-err_up:
+- iegbe_free_all_tx_resources(adapter);
+-err_setup_tx:
+- iegbe_free_all_rx_resources(adapter);
++ /* From here on the code is the same as iegbe_up() */
++ clear_bit(__E1000_DOWN, &adapter->flags);
++
++ napi_enable(&adapter->napi);
++
++ iegbe_irq_enable(adapter);
++
++ netif_start_queue(netdev);
++
++ /* fire a link status change interrupt to start the watchdog */
++
++ return E1000_SUCCESS;
++
++err_req_irq:
++ iegbe_power_down_phy(adapter);
++ iegbe_free_all_rx_resources(adapter);
+ err_setup_rx:
+- iegbe_reset(adapter);
++ iegbe_free_all_tx_resources(adapter);
++err_setup_tx:
++ iegbe_reset(adapter);
+
+- return err;
++ return err;
+ }
+
+ /**
+@@ -1348,22 +1249,25 @@ err_setup_rx:
+ * hardware, and all transmit and receive resources are freed.
+ **/
+
+-static int
+-iegbe_close(struct net_device *netdev)
++static int iegbe_close(struct net_device *netdev)
+ {
+- struct iegbe_adapter *adapter = netdev_priv(netdev);
+-
+- iegbe_down(adapter);
+-
+- iegbe_free_all_tx_resources(adapter);
+- iegbe_free_all_rx_resources(adapter);
++ struct iegbe_adapter *adapter = netdev_priv(netdev);
++ struct iegbe_hw *hw = &adapter->hw;
+
+-#ifdef NETIF_F_HW_VLAN_TX
+- if((adapter->hw.mng_cookie.status &
+- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
++ WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
++ iegbe_down(adapter);
++ iegbe_power_down_phy(adapter);
++ iegbe_free_irq(adapter);
++
++ iegbe_free_all_tx_resources(adapter);
++ iegbe_free_all_rx_resources(adapter);
++
++ if ((hw->mng_cookie.status &
++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
++ !(adapter->vlgrp &&
++ vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id))) {
+ iegbe_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
+ }
+-#endif
+ return 0;
+ }
+
+@@ -1375,19 +1279,19 @@ iegbe_close(struct net_device *netdev)
+ **/
+ static inline boolean_t
+ iegbe_check_64k_bound(struct iegbe_adapter *adapter,
+- void *start, unsigned long len)
++ void *start, unsigned long len)
+ {
+- unsigned long begin = (unsigned long) start;
+- unsigned long end = begin + len;
++ unsigned long begin = (unsigned long) start;
++ unsigned long end = begin + len;
+
+- /* First rev 82545 and 82546 need to not allow any memory
+- * write location to cross 64k boundary due to errata 23 */
+- if(adapter->hw.mac_type == iegbe_82545 ||
+- adapter->hw.mac_type == iegbe_82546) {
+- return ((begin ^ (end - 1)) >> 0x10) != 0 ? FALSE : TRUE;
+- }
++ /* First rev 82545 and 82546 need to not allow any memory
++ * write location to cross 64k boundary due to errata 23 */
++ if(adapter->hw.mac_type == iegbe_82545 ||
++ adapter->hw.mac_type == iegbe_82546) {
++ return ((begin ^ (end - 1)) >> 0x10) != 0x0 ? FALSE : TRUE;
++ }
+
+- return TRUE;
++ return TRUE;
+ }
+
+ /**
+@@ -1398,102 +1302,98 @@ iegbe_check_64k_bound(struct iegbe_adapt
+ * Return 0 on success, negative on failure
+ **/
+
+-int
+-iegbe_setup_tx_resources(struct iegbe_adapter *adapter,
++static int iegbe_setup_tx_resources(struct iegbe_adapter *adapter,
+ struct iegbe_tx_ring *txdr)
+ {
+- struct pci_dev *pdev = adapter->pdev;
+- int size;
++ struct pci_dev *pdev = adapter->pdev;
++ int size;
+
+- size = sizeof(struct iegbe_buffer) * txdr->count;
+- txdr->buffer_info = vmalloc(size);
+- if (!txdr->buffer_info) {
+- DPRINTK(PROBE, ERR,
+- "Unable to allocate memory for the transmit descriptor ring\n");
+- return -ENOMEM;
+- }
++ size = sizeof(struct iegbe_buffer) * txdr->count;
++ txdr->buffer_info = vmalloc(size);
++ if (!txdr->buffer_info) {
++ DPRINTK(PROBE, ERR,
++ "Unable to allocate memory for the transmit descriptor ring\n");
++ return -ENOMEM;
++ }
+ memset(txdr->buffer_info, 0, size);
+- memset(&txdr->previous_buffer_info, 0, sizeof(struct iegbe_buffer));
+
+- /* round up to nearest 4K */
++ /* round up to nearest 4K */
+
+- txdr->size = txdr->count * sizeof(struct iegbe_tx_desc);
+- E1000_ROUNDUP(txdr->size, 0x1000);
++ txdr->size = txdr->count * sizeof(struct iegbe_tx_desc);
++ txdr->size = ALIGN(txdr->size, 4096);
+
+- txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
+- if (!txdr->desc) {
++ txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
++ if (!txdr->desc) {
+ setup_tx_desc_die:
+- vfree(txdr->buffer_info);
+- DPRINTK(PROBE, ERR,
+- "Unable to allocate memory for the transmit descriptor ring\n");
+- return -ENOMEM;
+- }
+-
+- /* Fix for errata 23, can't cross 64kB boundary */
+- if (!iegbe_check_64k_bound(adapter, txdr->desc, txdr->size)) {
+- void *olddesc = txdr->desc;
+- dma_addr_t olddma = txdr->dma;
+- DPRINTK(TX_ERR, ERR, "txdr align check failed: %u bytes "
+- "at %p\n", txdr->size, txdr->desc);
+- /* Try again, without freeing the previous */
+- txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
+- /* Failed allocation, critical failure */
+- if (!txdr->desc) {
+- pci_free_consistent(pdev, txdr->size, olddesc, olddma);
+- goto setup_tx_desc_die;
+- }
++ vfree(txdr->buffer_info);
++ DPRINTK(PROBE, ERR,
++ "Unable to allocate memory for the transmit descriptor ring\n");
++ return -ENOMEM;
++ }
++
++ /* Fix for errata 23, can't cross 64kB boundary */
++ if (!iegbe_check_64k_bound(adapter, txdr->desc, txdr->size)) {
++ void *olddesc = txdr->desc;
++ dma_addr_t olddma = txdr->dma;
++ DPRINTK(TX_ERR, ERR, "txdr align check failed: %u bytes "
++ "at %p\n", txdr->size, txdr->desc);
++ /* Try again, without freeing the previous */
++ txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
++ /* Failed allocation, critical failure */
++ if (!txdr->desc) {
++ pci_free_consistent(pdev, txdr->size, olddesc, olddma);
++ goto setup_tx_desc_die;
++ }
+
+- if (!iegbe_check_64k_bound(adapter, txdr->desc, txdr->size)) {
+- /* give up */
+- pci_free_consistent(pdev, txdr->size, txdr->desc,
+- txdr->dma);
+- pci_free_consistent(pdev, txdr->size, olddesc, olddma);
+- DPRINTK(PROBE, ERR,
+- "Unable to allocate aligned memory "
+- "for the transmit descriptor ring\n");
+- vfree(txdr->buffer_info);
+- return -ENOMEM;
+- } else {
+- /* Free old allocation, new allocation was successful */
+- pci_free_consistent(pdev, txdr->size, olddesc, olddma);
+- }
+- }
++ if (!iegbe_check_64k_bound(adapter, txdr->desc, txdr->size)) {
++ /* give up */
++ pci_free_consistent(pdev, txdr->size, txdr->desc,
++ txdr->dma);
++ pci_free_consistent(pdev, txdr->size, olddesc, olddma);
++ DPRINTK(PROBE, ERR,
++ "Unable to allocate aligned memory "
++ "for the transmit descriptor ring\n");
++ vfree(txdr->buffer_info);
++ return -ENOMEM;
++ } else {
++ /* Free old allocation, new allocation was successful */
++ pci_free_consistent(pdev, txdr->size, olddesc, olddma);
++ }
++ }
+ memset(txdr->desc, 0, txdr->size);
+
+ txdr->next_to_use = 0;
+ txdr->next_to_clean = 0;
+- spin_lock_init(&txdr->tx_lock);
++ spin_lock_init(&txdr->tx_lock);
+
+ return 0;
+ }
+
+ /**
+ * iegbe_setup_all_tx_resources - wrapper to allocate Tx resources
+- * (Descriptors) for all queues
++ * (Descriptors) for all queues
+ * @adapter: board private structure
+ *
+- * If this function returns with an error, then it's possible one or
+- * more of the rings is populated (while the rest are not). It is the
+- * callers duty to clean those orphaned rings.
+- *
+ * Return 0 on success, negative on failure
+ **/
+
+-int
+-iegbe_setup_all_tx_resources(struct iegbe_adapter *adapter)
++int iegbe_setup_all_tx_resources(struct iegbe_adapter *adapter)
+ {
+ int i, err = 0;
+
+- for (i = 0; i < adapter->num_queues; i++) {
++ for (i = 0; i < adapter->num_tx_queues; i++) {
+ err = iegbe_setup_tx_resources(adapter, &adapter->tx_ring[i]);
+ if (err) {
+ DPRINTK(PROBE, ERR,
+ "Allocation for Tx Queue %u failed\n", i);
++ for (i-- ; i >= 0; i--)
++ iegbe_free_tx_resources(adapter,
++ &adapter->tx_ring[i]);
+ break;
+ }
+ }
+
+- return err;
++ return err;
+ }
+
+ /**
+@@ -1512,113 +1412,108 @@ iegbe_configure_tx(struct iegbe_adapter
+
+ /* Setup the HW Tx Head and Tail descriptor pointers */
+
+- switch (adapter->num_queues) {
++ switch (adapter->num_tx_queues) {
+ case 0x2:
+ tdba = adapter->tx_ring[0x1].dma;
+ tdlen = adapter->tx_ring[0x1].count *
+- sizeof(struct iegbe_tx_desc);
+- E1000_WRITE_REG(hw, TDBAL1, (tdba & 0x00000000ffffffffULL));
++ sizeof(struct iegbe_tx_desc);
++ E1000_WRITE_REG(hw, TDBAL1, (tdba & 0x00000000ffffffffULL));
+ E1000_WRITE_REG(hw, TDBAH1, (tdba >> 0x20));
+- E1000_WRITE_REG(hw, TDLEN1, tdlen);
+- E1000_WRITE_REG(hw, TDH1, 0);
+- E1000_WRITE_REG(hw, TDT1, 0);
++ E1000_WRITE_REG(hw, TDLEN1, tdlen);
++ E1000_WRITE_REG(hw, TDH1, 0x0);
++ E1000_WRITE_REG(hw, TDT1, 0x0);
+ adapter->tx_ring[0x1].tdh = E1000_TDH1;
+ adapter->tx_ring[0x1].tdt = E1000_TDT1;
+- /* Fall Through */
++ /* Fall Through */
+ case 0x1:
+- default:
+- tdba = adapter->tx_ring[0].dma;
+- tdlen = adapter->tx_ring[0].count *
+- sizeof(struct iegbe_tx_desc);
+- E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL));
++ default:
++ tdba = adapter->tx_ring[0x0].dma;
++ tdlen = adapter->tx_ring[0x0].count *
++ sizeof(struct iegbe_tx_desc);
++ E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL));
+ E1000_WRITE_REG(hw, TDBAH, (tdba >> 0x20));
+- E1000_WRITE_REG(hw, TDLEN, tdlen);
+- E1000_WRITE_REG(hw, TDH, 0);
+- E1000_WRITE_REG(hw, TDT, 0);
+- adapter->tx_ring[0].tdh = E1000_TDH;
+- adapter->tx_ring[0].tdt = E1000_TDT;
+- break;
+- }
+-
+- /* Set the default values for the Tx Inter Packet Gap timer */
+-
+- switch (hw->mac_type) {
+- case iegbe_82542_rev2_0:
+- case iegbe_82542_rev2_1:
+- tipg = DEFAULT_82542_TIPG_IPGT;
+- tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
+- tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
+- break;
+- default:
+- switch(hw->media_type) {
+- case iegbe_media_type_fiber:
+- case iegbe_media_type_internal_serdes:
+- tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
+- break;
+- case iegbe_media_type_copper:
+- tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
+- break;
+- case iegbe_media_type_oem:
+- default:
++ E1000_WRITE_REG(hw, TDLEN, tdlen);
++ E1000_WRITE_REG(hw, TDH, 0x0);
++ E1000_WRITE_REG(hw, TDT, 0x0);
++ adapter->tx_ring[0x0].tdh = E1000_TDH;
++ adapter->tx_ring[0x0].tdt = E1000_TDT;
++ break;
++ }
++
++ /* Set the default values for the Tx Inter Packet Gap timer */
++
++ switch (hw->mac_type) {
++ case iegbe_82542_rev2_0:
++ case iegbe_82542_rev2_1:
++ tipg = DEFAULT_82542_TIPG_IPGT;
++ tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
++ tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
++ break;
++ default:
++ switch(hw->media_type) {
++ case iegbe_media_type_fiber:
++ case iegbe_media_type_internal_serdes:
++ tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
++ break;
++ case iegbe_media_type_copper:
++ tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
++ break;
++ case iegbe_media_type_oem:
++ default:
+ tipg = (0xFFFFFFFFUL >> (sizeof(tipg)*0x8 -
+ E1000_TIPG_IPGR1_SHIFT))
+- & iegbe_oem_get_tipg(&adapter->hw);
+- break;
+- }
+- tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
+- tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
+- }
+- E1000_WRITE_REG(hw, TIPG, tipg);
++ & iegbe_oem_get_tipg(&adapter->hw);
++ break;
++ }
++ tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
++ tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
++ }
++ E1000_WRITE_REG(hw, TIPG, tipg);
+
+- /* Set the Tx Interrupt Delay register */
++ /* Set the Tx Interrupt Delay register */
+
+- E1000_WRITE_REG(hw, TIDV, adapter->tx_int_delay);
++ E1000_WRITE_REG(hw, TIDV, adapter->tx_int_delay);
+ if (hw->mac_type >= iegbe_82540) {
+- E1000_WRITE_REG(hw, TADV, adapter->tx_abs_int_delay);
++ E1000_WRITE_REG(hw, TADV, adapter->tx_abs_int_delay);
+ }
+- /* Program the Transmit Control Register */
++ /* Program the Transmit Control Register */
+
+- tctl = E1000_READ_REG(hw, TCTL);
++ tctl = E1000_READ_REG(hw, TCTL);
+
+- tctl &= ~E1000_TCTL_CT;
+- tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | E1000_TCTL_RTLC |
+- (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
++ tctl &= ~E1000_TCTL_CT;
++ tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | E1000_TCTL_RTLC |
++ (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
+
+- E1000_WRITE_REG(hw, TCTL, tctl);
++ E1000_WRITE_REG(hw, TCTL, tctl);
+
+- if (hw->mac_type == iegbe_82571 || hw->mac_type == iegbe_82572) {
+- tarc = E1000_READ_REG(hw, TARC0);
++ if (hw->mac_type == iegbe_82571 || hw->mac_type == iegbe_82572) {
++ tarc = E1000_READ_REG(hw, TARC0);
+ tarc |= ((0x1 << 0x19) | (0x1 << 0x15));
+- E1000_WRITE_REG(hw, TARC0, tarc);
+- tarc = E1000_READ_REG(hw, TARC1);
++ E1000_WRITE_REG(hw, TARC0, tarc);
++ tarc = E1000_READ_REG(hw, TARC1);
+ tarc |= (0x1 << 0x19);
+ if (tctl & E1000_TCTL_MULR) {
+ tarc &= ~(0x1 << 0x1c);
+ } else {
+ tarc |= (0x1 << 0x1c);
+ }
+- E1000_WRITE_REG(hw, TARC1, tarc);
+- }
++ E1000_WRITE_REG(hw, TARC1, tarc);
++ }
+
+- iegbe_config_collision_dist(hw);
++ iegbe_config_collision_dist(hw);
+
+- /* Setup Transmit Descriptor Settings for eop descriptor */
+- adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP |
+- E1000_TXD_CMD_IFCS;
++ /* Setup Transmit Descriptor Settings for eop descriptor */
++ adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP |
++ E1000_TXD_CMD_IFCS;
+
+ if (hw->mac_type < iegbe_82543) {
+- adapter->txd_cmd |= E1000_TXD_CMD_RPS;
++ adapter->txd_cmd |= E1000_TXD_CMD_RPS;
+ } else {
+-#ifdef IEGBE_GBE_WORKAROUND
+- /* Disable the RS bit in the Tx descriptor */
+- adapter->txd_cmd &= ~E1000_TXD_CMD_RS;
+-#else
+- adapter->txd_cmd |= E1000_TXD_CMD_RS;
+-#endif
++ adapter->txd_cmd |= E1000_TXD_CMD_RS;
+ }
+- /* Cache if we're 82544 running in PCI-X because we'll
+- * need this to apply a workaround later in the send path. */
+- if (hw->mac_type == iegbe_82544 &&
++ /* Cache if we're 82544 running in PCI-X because we'll
++ * need this to apply a workaround later in the send path. */
++ if (hw->mac_type == iegbe_82544 &&
+ hw->bus_type == iegbe_bus_type_pcix) {
+ adapter->pcix_82544 = 0x1;
+ }
+@@ -1632,96 +1527,95 @@ iegbe_configure_tx(struct iegbe_adapter
+ * Returns 0 on success, negative on failure
+ **/
+
+-int
+-iegbe_setup_rx_resources(struct iegbe_adapter *adapter,
++static int iegbe_setup_rx_resources(struct iegbe_adapter *adapter,
+ struct iegbe_rx_ring *rxdr)
+ {
+- struct pci_dev *pdev = adapter->pdev;
+- int size, desc_len;
+-
+- size = sizeof(struct iegbe_buffer) * rxdr->count;
+- rxdr->buffer_info = vmalloc(size);
+- if (!rxdr->buffer_info) {
+- DPRINTK(PROBE, ERR,
+- "Unable to allocate memory for the receive descriptor ring\n");
+- return -ENOMEM;
+- }
+- memset(rxdr->buffer_info, 0, size);
+-
+- size = sizeof(struct iegbe_ps_page) * rxdr->count;
+- rxdr->ps_page = kmalloc(size, GFP_KERNEL);
+- if (!rxdr->ps_page) {
+- vfree(rxdr->buffer_info);
+- DPRINTK(PROBE, ERR,
+- "Unable to allocate memory for the receive descriptor ring\n");
+- return -ENOMEM;
+- }
+- memset(rxdr->ps_page, 0, size);
+-
+- size = sizeof(struct iegbe_ps_page_dma) * rxdr->count;
+- rxdr->ps_page_dma = kmalloc(size, GFP_KERNEL);
+- if (!rxdr->ps_page_dma) {
+- vfree(rxdr->buffer_info);
+- kfree(rxdr->ps_page);
+- DPRINTK(PROBE, ERR,
+- "Unable to allocate memory for the receive descriptor ring\n");
+- return -ENOMEM;
+- }
+- memset(rxdr->ps_page_dma, 0, size);
++ struct iegbe_hw *hw = &adapter->hw;
++ struct pci_dev *pdev = adapter->pdev;
++ int size, desc_len;
+
+- if (adapter->hw.mac_type <= iegbe_82547_rev_2) {
+- desc_len = sizeof(struct iegbe_rx_desc);
+- } else {
+- desc_len = sizeof(union iegbe_rx_desc_packet_split);
++ size = sizeof(struct iegbe_buffer) * rxdr->count;
++ rxdr->buffer_info = vmalloc(size);
++ if (!rxdr->buffer_info) {
++ DPRINTK(PROBE, ERR,
++ "Unable to allocate memory for the receive descriptor ring\n");
++ return -ENOMEM;
+ }
+- /* Round up to nearest 4K */
+-
+- rxdr->size = rxdr->count * desc_len;
+- E1000_ROUNDUP(rxdr->size, 0x1000);
+-
+- rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
++ memset(rxdr->buffer_info, 0, size);
+
+- if (!rxdr->desc) {
+- DPRINTK(PROBE, ERR,
+- "Unable to allocate memory for the receive descriptor ring\n");
++ rxdr->ps_page = kcalloc(rxdr->count, sizeof(struct iegbe_ps_page),
++ GFP_KERNEL);
++ if (!rxdr->ps_page) {
++ vfree(rxdr->buffer_info);
++ DPRINTK(PROBE, ERR,
++ "Unable to allocate memory for the receive descriptor ring\n");
++ return -ENOMEM;
++ }
++
++ rxdr->ps_page_dma = kcalloc(rxdr->count,
++ sizeof(struct iegbe_ps_page_dma),
++ GFP_KERNEL);
++ if (!rxdr->ps_page_dma) {
++ vfree(rxdr->buffer_info);
++ kfree(rxdr->ps_page);
++ DPRINTK(PROBE, ERR,
++ "Unable to allocate memory for the receive descriptor ring\n");
++ return -ENOMEM;
++ }
++
++ if (hw->mac_type <= iegbe_82547_rev_2)
++ desc_len = sizeof(struct iegbe_rx_desc);
++ else
++ desc_len = sizeof(union iegbe_rx_desc_packet_split);
++
++ /* Round up to nearest 4K */
++
++ rxdr->size = rxdr->count * desc_len;
++ rxdr->size = ALIGN(rxdr->size, 4096);
++
++ rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
++
++ if (!rxdr->desc) {
++ DPRINTK(PROBE, ERR,
++ "Unable to allocate memory for the receive descriptor ring\n");
+ setup_rx_desc_die:
+- vfree(rxdr->buffer_info);
+- kfree(rxdr->ps_page);
+- kfree(rxdr->ps_page_dma);
+- return -ENOMEM;
+- }
+-
+- /* Fix for errata 23, can't cross 64kB boundary */
+- if (!iegbe_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
+- void *olddesc = rxdr->desc;
+- dma_addr_t olddma = rxdr->dma;
+- DPRINTK(RX_ERR, ERR, "rxdr align check failed: %u bytes "
+- "at %p\n", rxdr->size, rxdr->desc);
+- /* Try again, without freeing the previous */
+- rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
+- /* Failed allocation, critical failure */
+- if (!rxdr->desc) {
+- pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
+- DPRINTK(PROBE, ERR,
+- "Unable to allocate memory "
+- "for the receive descriptor ring\n");
+- goto setup_rx_desc_die;
+- }
++ vfree(rxdr->buffer_info);
++ kfree(rxdr->ps_page);
++ kfree(rxdr->ps_page_dma);
++ return -ENOMEM;
++ }
++
++ /* Fix for errata 23, can't cross 64kB boundary */
++ if (!iegbe_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
++ void *olddesc = rxdr->desc;
++ dma_addr_t olddma = rxdr->dma;
++ DPRINTK(RX_ERR, ERR, "rxdr align check failed: %u bytes "
++ "at %p\n", rxdr->size, rxdr->desc);
++ /* Try again, without freeing the previous */
++ rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
++ /* Failed allocation, critical failure */
++ if (!rxdr->desc) {
++ pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
++ DPRINTK(PROBE, ERR,
++ "Unable to allocate memory "
++ "for the receive descriptor ring\n");
++ goto setup_rx_desc_die;
++ }
+
+- if (!iegbe_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
+- /* give up */
+- pci_free_consistent(pdev, rxdr->size, rxdr->desc,
+- rxdr->dma);
+- pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
+- DPRINTK(PROBE, ERR,
+- "Unable to allocate aligned memory "
+- "for the receive descriptor ring\n");
+- goto setup_rx_desc_die;
+- } else {
+- /* Free old allocation, new allocation was successful */
+- pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
+- }
+- }
++ if (!iegbe_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
++ /* give up */
++ pci_free_consistent(pdev, rxdr->size, rxdr->desc,
++ rxdr->dma);
++ pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
++ DPRINTK(PROBE, ERR,
++ "Unable to allocate aligned memory "
++ "for the receive descriptor ring\n");
++ goto setup_rx_desc_die;
++ } else {
++ /* Free old allocation, new allocation was successful */
++ pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
++ }
++ }
+ memset(rxdr->desc, 0, rxdr->size);
+
+ rxdr->next_to_clean = 0;
+@@ -1732,7 +1626,7 @@ setup_rx_desc_die:
+
+ /**
+ * iegbe_setup_all_rx_resources - wrapper to allocate Rx resources
+- * (Descriptors) for all queues
++ * (Descriptors) for all queues
+ * @adapter: board private structure
+ *
+ * If this function returns with an error, then it's possible one or
+@@ -1742,21 +1636,23 @@ setup_rx_desc_die:
+ * Return 0 on success, negative on failure
+ **/
+
+-int
+-iegbe_setup_all_rx_resources(struct iegbe_adapter *adapter)
++int iegbe_setup_all_rx_resources(struct iegbe_adapter *adapter)
+ {
+ int i, err = 0;
+
+- for (i = 0; i < adapter->num_queues; i++) {
++ for (i = 0; i < adapter->num_rx_queues; i++) {
+ err = iegbe_setup_rx_resources(adapter, &adapter->rx_ring[i]);
+ if (err) {
+ DPRINTK(PROBE, ERR,
+ "Allocation for Rx Queue %u failed\n", i);
++ for (i-- ; i >= 0; i--)
++ iegbe_free_rx_resources(adapter,
++ &adapter->rx_ring[i]);
+ break;
+ }
+ }
+
+- return err;
++ return err;
+ }
+
+ /**
+@@ -1765,105 +1661,104 @@ iegbe_setup_all_rx_resources(struct iegb
+ **/
+ #define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \
+ (((S) & (PAGE_SIZE - 1)) ? 1 : 0))
+-static void
+-iegbe_setup_rctl(struct iegbe_adapter *adapter)
++static void iegbe_setup_rctl(struct iegbe_adapter *adapter)
+ {
+- uint32_t rctl, rfctl;
+- uint32_t psrctl = 0;
+-#ifdef CONFIG_E1000_PACKET_SPLIT
+- uint32_t pages = 0;
+-#endif
+-
+- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+-
+- rctl &= ~(0x3 << E1000_RCTL_MO_SHIFT);
+-
+- rctl |= E1000_RCTL_EN | E1000_RCTL_BAM |
+- E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
+- (adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
+-
+- if(adapter->hw.tbi_compatibility_on == 0x1) {
+- rctl |= E1000_RCTL_SBP;
+- } else {
+- rctl &= ~E1000_RCTL_SBP;
+- }
+- if(adapter->netdev->mtu <= ETH_DATA_LEN) {
+- rctl &= ~E1000_RCTL_LPE;
+- } else {
+- rctl |= E1000_RCTL_LPE;
+- }
+- /* Setup buffer sizes */
+- if(adapter->hw.mac_type >= iegbe_82571) {
+- /* We can now specify buffers in 1K increments.
+- * BSIZE and BSEX are ignored in this case. */
+- rctl |= adapter->rx_buffer_len << 0x11;
+- } else {
+- rctl &= ~E1000_RCTL_SZ_4096;
+- rctl |= E1000_RCTL_BSEX;
+- switch (adapter->rx_buffer_len) {
+- case E1000_RXBUFFER_2048:
+- default:
+- rctl |= E1000_RCTL_SZ_2048;
++ struct iegbe_hw *hw = &adapter->hw;
++ u32 rctl, rfctl;
++ u32 psrctl = 0;
++#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
++ u32 pages = 0;
++#endif
++
++ rctl = E1000_READ_REG(&adapter->hw, RCTL);
++
++ rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
++
++ rctl |= E1000_RCTL_EN | E1000_RCTL_BAM |
++ E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
++ (hw->mc_filter_type << E1000_RCTL_MO_SHIFT);
++
++ if (hw->tbi_compatibility_on == 1)
++ rctl |= E1000_RCTL_SBP;
++ else
++ rctl &= ~E1000_RCTL_SBP;
++
++ if (adapter->netdev->mtu <= ETH_DATA_LEN)
++ rctl &= ~E1000_RCTL_LPE;
++ else
++ rctl |= E1000_RCTL_LPE;
++
++ /* Setup buffer sizes */
++ /* We can now specify buffers in 1K increments.
++ * BSIZE and BSEX are ignored in this case. */
++ rctl &= ~E1000_RCTL_SZ_4096;
++ rctl |= E1000_RCTL_BSEX;
++ switch (adapter->rx_buffer_len) {
++ case E1000_RXBUFFER_256:
++ rctl |= E1000_RCTL_SZ_256;
+ rctl &= ~E1000_RCTL_BSEX;
+ break;
+- case E1000_RXBUFFER_4096:
+- rctl |= E1000_RCTL_SZ_4096;
+- break;
+- case E1000_RXBUFFER_8192:
+- rctl |= E1000_RCTL_SZ_8192;
+- break;
+- case E1000_RXBUFFER_16384:
+- rctl |= E1000_RCTL_SZ_16384;
+- break;
+- }
+- }
++ case E1000_RXBUFFER_2048:
++ default:
++ rctl |= E1000_RCTL_SZ_2048;
++ rctl &= ~E1000_RCTL_BSEX;
++ break;
++ case E1000_RXBUFFER_4096:
++ rctl |= E1000_RCTL_SZ_4096;
++ break;
++ case E1000_RXBUFFER_8192:
++ rctl |= E1000_RCTL_SZ_8192;
++ break;
++ case E1000_RXBUFFER_16384:
++ rctl |= E1000_RCTL_SZ_16384;
++ break;
++ }
+
+-#ifdef CONFIG_E1000_PACKET_SPLIT
+- /* 82571 and greater support packet-split where the protocol
+- * header is placed in skb->data and the packet data is
+- * placed in pages hanging off of skb_shinfo(skb)->nr_frags.
+- * In the case of a non-split, skb->data is linearly filled,
+- * followed by the page buffers. Therefore, skb->data is
+- * sized to hold the largest protocol header.
+- */
+- pages = PAGE_USE_COUNT(adapter->netdev->mtu);
+- if ((adapter->hw.mac_type > iegbe_82547_rev_2) && (pages <= 0x3) &&
+- PAGE_SIZE <= 0x4000) {
+- adapter->rx_ps_pages = pages;
+- } else {
++#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
++ /* 82571 and greater support packet-split where the protocol
++ * header is placed in skb->data and the packet data is
++ * placed in pages hanging off of skb_shinfo(skb)->nr_frags.
++ * In the case of a non-split, skb->data is linearly filled,
++ * followed by the page buffers. Therefore, skb->data is
++ * sized to hold the largest protocol header.
++ */
++ pages = PAGE_USE_COUNT(adapter->netdev->mtu);
++ if ((hw->mac_type >= iegbe_82571) && (pages <= 3) &&
++ PAGE_SIZE <= 16384 && (rctl & E1000_RCTL_LPE))
++ adapter->rx_ps_pages = pages;
++ else
+ adapter->rx_ps_pages = 0;
+- }
+ #endif
+- if (adapter->rx_ps_pages) {
+- /* Configure extra packet-split registers */
+- rfctl = E1000_READ_REG(&adapter->hw, RFCTL);
+- rfctl |= E1000_RFCTL_EXTEN;
+- /* disable IPv6 packet split support */
+- rfctl |= E1000_RFCTL_IPV6_DIS;
+- E1000_WRITE_REG(&adapter->hw, RFCTL, rfctl);
+-
+- rctl |= E1000_RCTL_DTYP_PS | E1000_RCTL_SECRC;
+-
+- psrctl |= adapter->rx_ps_bsize0 >>
+- E1000_PSRCTL_BSIZE0_SHIFT;
+-
+- switch (adapter->rx_ps_pages) {
+- case 0x3:
+- psrctl |= PAGE_SIZE <<
+- E1000_PSRCTL_BSIZE3_SHIFT;
+- case 0x2:
+- psrctl |= PAGE_SIZE <<
+- E1000_PSRCTL_BSIZE2_SHIFT;
+- case 0x1:
+- psrctl |= PAGE_SIZE >>
+- E1000_PSRCTL_BSIZE1_SHIFT;
+- break;
+- }
++ if (adapter->rx_ps_pages) {
++ /* Configure extra packet-split registers */
++ rfctl = E1000_READ_REG(&adapter->hw, RFCTL);
++ rfctl |= E1000_RFCTL_EXTEN;
++ /* disable IPv6 packet split support */
++ rfctl |= (E1000_RFCTL_IPV6_EX_DIS |
++ E1000_RFCTL_NEW_IPV6_EXT_DIS);
++
++ rctl |= E1000_RCTL_DTYP_PS;
++
++ psrctl |= adapter->rx_ps_bsize0 >>
++ E1000_PSRCTL_BSIZE0_SHIFT;
++
++ switch (adapter->rx_ps_pages) {
++ case 3:
++ psrctl |= PAGE_SIZE <<
++ E1000_PSRCTL_BSIZE3_SHIFT;
++ case 2:
++ psrctl |= PAGE_SIZE <<
++ E1000_PSRCTL_BSIZE2_SHIFT;
++ case 1:
++ psrctl |= PAGE_SIZE >>
++ E1000_PSRCTL_BSIZE1_SHIFT;
++ break;
++ }
+
+- E1000_WRITE_REG(&adapter->hw, PSRCTL, psrctl);
+- }
++ E1000_WRITE_REG(&adapter->hw, PSRCTL, psrctl);
++ }
+
+- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ }
+
+ /**
+@@ -1873,145 +1768,87 @@ iegbe_setup_rctl(struct iegbe_adapter *a
+ * Configure the Rx unit of the MAC after a reset.
+ **/
+
+-static void
+-iegbe_configure_rx(struct iegbe_adapter *adapter)
++static void iegbe_configure_rx(struct iegbe_adapter *adapter)
+ {
+- uint64_t rdba;
+- struct iegbe_hw *hw = &adapter->hw;
+- uint32_t rdlen, rctl, rxcsum, ctrl_ext;
+-#ifdef CONFIG_E1000_MQ
+- uint32_t reta, mrqc;
+- int i;
+-#endif
++ u64 rdba;
++ struct iegbe_hw *hw = &adapter->hw;
++ u32 rdlen, rctl, rxcsum, ctrl_ext;
+
+- if (adapter->rx_ps_pages) {
++ if (adapter->rx_ps_pages) {
+ rdlen = adapter->rx_ring[0].count *
+- sizeof(union iegbe_rx_desc_packet_split);
+- adapter->clean_rx = iegbe_clean_rx_irq_ps;
+- adapter->alloc_rx_buf = iegbe_alloc_rx_buffers_ps;
+- } else {
++ sizeof(union iegbe_rx_desc_packet_split);
++ adapter->clean_rx = iegbe_clean_rx_irq_ps;
++ adapter->alloc_rx_buf = iegbe_alloc_rx_buffers_ps;
++ } else {
+ rdlen = adapter->rx_ring[0].count *
+- sizeof(struct iegbe_rx_desc);
+- adapter->clean_rx = iegbe_clean_rx_irq;
+- adapter->alloc_rx_buf = iegbe_alloc_rx_buffers;
+- }
++ sizeof(struct iegbe_rx_desc);
++ adapter->clean_rx = iegbe_clean_rx_irq;
++ adapter->alloc_rx_buf = iegbe_alloc_rx_buffers;
++ }
+
+- /* disable receives while setting up the descriptors */
+- rctl = E1000_READ_REG(hw, RCTL);
+- E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
++ /* disable receives while setting up the descriptors */
++ rctl = E1000_READ_REG(hw, RCTL);
++ E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
+
+- /* set the Receive Delay Timer Register */
+- E1000_WRITE_REG(hw, RDTR, adapter->rx_int_delay);
++ /* set the Receive Delay Timer Register */
++ E1000_WRITE_REG(hw, RDTR, adapter->rx_int_delay);
+
+- if (hw->mac_type >= iegbe_82540) {
+- E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay);
+- if(adapter->itr > 0x1) {
+- E1000_WRITE_REG(hw, ITR,
+- 0x3b9aca00 / (adapter->itr * 0x100));
++ if (hw->mac_type >= iegbe_82540) {
++ E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay);
++ if (adapter->itr_setting != 0)
++ E1000_WRITE_REG(&adapter->hw, ITR, 1000000000 / (adapter->itr * 256));
+ }
+- }
+
+- if (hw->mac_type >= iegbe_82571) {
+- /* Reset delay timers after every interrupt */
+- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+- ctrl_ext |= E1000_CTRL_EXT_CANC;
+- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+- E1000_WRITE_FLUSH(hw);
+- }
++ if (hw->mac_type >= iegbe_82571) {
++ /* Reset delay timers after every interrupt */
++ ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
++ ctrl_ext |= E1000_CTRL_EXT_CANC;
++ E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
++ E1000_WRITE_FLUSH(hw);
++ }
+
+ /* Setup the HW Rx Head and Tail Descriptor Pointers and
+ * the Base and Length of the Rx Descriptor Ring */
+- switch (adapter->num_queues) {
+-#ifdef CONFIG_E1000_MQ
+- case 0x2:
+- rdba = adapter->rx_ring[0x1].dma;
+- E1000_WRITE_REG(hw, RDBAL1, (rdba & 0x00000000ffffffffULL));
+- E1000_WRITE_REG(hw, RDBAH1, (rdba >> 0x20));
+- E1000_WRITE_REG(hw, RDLEN1, rdlen);
+- E1000_WRITE_REG(hw, RDH1, 0);
+- E1000_WRITE_REG(hw, RDT1, 0);
+- adapter->rx_ring[1].rdh = E1000_RDH1;
+- adapter->rx_ring[1].rdt = E1000_RDT1;
+- /* Fall Through */
+-#endif
+- case 0x1:
+- default:
++ switch (adapter->num_rx_queues) {
++ case 1:
++ default:
+ rdba = adapter->rx_ring[0].dma;
+- E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL));
++ E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL));
+ E1000_WRITE_REG(hw, RDBAH, (rdba >> 0x20));
+- E1000_WRITE_REG(hw, RDLEN, rdlen);
+- E1000_WRITE_REG(hw, RDH, 0);
+- E1000_WRITE_REG(hw, RDT, 0);
+- adapter->rx_ring[0].rdh = E1000_RDH;
+- adapter->rx_ring[0].rdt = E1000_RDT;
+- break;
+- }
++ E1000_WRITE_REG(hw, RDLEN, rdlen);
++ adapter->rx_ring[0].rdh = ((hw->mac_type >= iegbe_82543) ? E1000_RDH : E1000_82542_RDH);
++ adapter->rx_ring[0].rdt = ((hw->mac_type >= iegbe_82543) ? E1000_RDT : E1000_82542_RDT);
++ break;
++ }
+
+-#ifdef CONFIG_E1000_MQ
+- if (adapter->num_queues > 0x1) {
+- uint32_t random[0xa];
+-
+- get_random_bytes(&random[0], FORTY);
+-
+- if (hw->mac_type <= iegbe_82572) {
+- E1000_WRITE_REG(hw, RSSIR, 0);
+- E1000_WRITE_REG(hw, RSSIM, 0);
+- }
+
+- switch (adapter->num_queues) {
+- case 0x2:
+- default:
+- reta = 0x00800080;
+- mrqc = E1000_MRQC_ENABLE_RSS_2Q;
+- break;
+- }
+-
+- /* Fill out redirection table */
+- for (i = 0; i < 0x20; i++)
+- E1000_WRITE_REG_ARRAY(hw, RETA, i, reta);
+- /* Fill out hash function seeds */
+- for (i = 0; i < 0xa; i++)
+- E1000_WRITE_REG_ARRAY(hw, RSSRK, i, random[i]);
+-
+- mrqc |= (E1000_MRQC_RSS_FIELD_IPV4 |
+- E1000_MRQC_RSS_FIELD_IPV4_TCP);
+- E1000_WRITE_REG(hw, MRQC, mrqc);
+- }
+-
+- /* Multiqueue and packet checksumming are mutually exclusive. */
+- if (hw->mac_type >= iegbe_82571) {
+- rxcsum = E1000_READ_REG(hw, RXCSUM);
+- rxcsum |= E1000_RXCSUM_PCSD;
+- E1000_WRITE_REG(hw, RXCSUM, rxcsum);
+- }
+-
+-#else
++ /* Enable 82543 Receive Checksum Offload for TCP and UDP */
++ if (hw->mac_type >= iegbe_82543) {
++ rxcsum = E1000_READ_REG(hw, RXCSUM);
++ if(adapter->rx_csum == TRUE) {
++ rxcsum |= E1000_RXCSUM_TUOFL;
++
++ /* Enable 82571 IPv4 payload checksum for UDP fragments
++ * Must be used in conjunction with packet-split. */
++ if ((hw->mac_type >= iegbe_82571) &&
++ (adapter->rx_ps_pages)) {
++ rxcsum |= E1000_RXCSUM_IPPCSE;
++ }
++ } else {
++ rxcsum &= ~E1000_RXCSUM_TUOFL;
++ /* don't need to clear IPPCSE as it defaults to 0 */
++ }
++ E1000_WRITE_REG(hw, RXCSUM, rxcsum);
++ }
+
+- /* Enable 82543 Receive Checksum Offload for TCP and UDP */
+- if (hw->mac_type >= iegbe_82543) {
+- rxcsum = E1000_READ_REG(hw, RXCSUM);
+- if(adapter->rx_csum == TRUE) {
+- rxcsum |= E1000_RXCSUM_TUOFL;
+-
+- /* Enable 82571 IPv4 payload checksum for UDP fragments
+- * Must be used in conjunction with packet-split. */
+- if ((hw->mac_type >= iegbe_82571) &&
+- (adapter->rx_ps_pages)) {
+- rxcsum |= E1000_RXCSUM_IPPCSE;
+- }
+- } else {
+- rxcsum &= ~E1000_RXCSUM_TUOFL;
+- /* don't need to clear IPPCSE as it defaults to 0 */
+- }
+- E1000_WRITE_REG(hw, RXCSUM, rxcsum);
+- }
+-#endif /* CONFIG_E1000_MQ */
++ /* enable early receives on 82573, only takes effect if using > 2048
++ * byte total frame size. for example only for jumbo frames */
++#define E1000_ERT_2048 0x100
++ if (hw->mac_type == iegbe_82573)
++ E1000_WRITE_REG(&adapter->hw, ERT, E1000_ERT_2048);
+
+- if (hw->mac_type == iegbe_82573) {
+- E1000_WRITE_REG(hw, ERT, 0x0100);
+- }
+ /* Enable Receives */
+- E1000_WRITE_REG(hw, RCTL, rctl);
++ E1000_WRITE_REG(hw, RCTL, rctl);
+ }
+
+ /**
+@@ -2022,20 +1859,19 @@ iegbe_configure_rx(struct iegbe_adapter
+ * Free all transmit software resources
+ **/
+
+-void
+-iegbe_free_tx_resources(struct iegbe_adapter *adapter,
++static void iegbe_free_tx_resources(struct iegbe_adapter *adapter,
+ struct iegbe_tx_ring *tx_ring)
+ {
+- struct pci_dev *pdev = adapter->pdev;
++ struct pci_dev *pdev = adapter->pdev;
+
+- iegbe_clean_tx_ring(adapter, tx_ring);
++ iegbe_clean_tx_ring(adapter, tx_ring);
+
+- vfree(tx_ring->buffer_info);
+- tx_ring->buffer_info = NULL;
++ vfree(tx_ring->buffer_info);
++ tx_ring->buffer_info = NULL;
+
+- pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma);
++ pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma);
+
+- tx_ring->desc = NULL;
++ tx_ring->desc = NULL;
+ }
+
+ /**
+@@ -2048,85 +1884,29 @@ iegbe_free_tx_resources(struct iegbe_ada
+ void
+ iegbe_free_all_tx_resources(struct iegbe_adapter *adapter)
+ {
+- int i;
++ int i;
+
+- for (i = 0; i < adapter->num_queues; i++)
++ for (i = 0x0; i < adapter->num_tx_queues; i++)
+ iegbe_free_tx_resources(adapter, &adapter->tx_ring[i]);
+ }
+
+ static inline void
+ iegbe_unmap_and_free_tx_resource(struct iegbe_adapter *adapter,
+- struct iegbe_buffer *buffer_info)
+-{
+- if(buffer_info->dma) {
+- pci_unmap_page(adapter->pdev,
+- buffer_info->dma,
+- buffer_info->length,
+- PCI_DMA_TODEVICE);
+- buffer_info->dma = 0;
+- }
+- if(buffer_info->skb) {
+- dev_kfree_skb_any(buffer_info->skb);
+- buffer_info->skb = NULL;
+- }
+-}
+-
+-#ifdef IEGBE_GBE_WORKAROUND
+-/**
+- * iegbe_clean_tx_ring_partial - Free Tx Buffers without using the DD
+- * bit in the descriptor
+- * @adapter: board private structure
+- * @tx_ring: ring to be cleaned
+- **/
+-static void iegbe_clean_tx_ring_partial(struct iegbe_adapter *adapter,
+- struct iegbe_tx_ring *tx_ring)
++ struct iegbe_buffer *buffer_info)
+ {
+- struct iegbe_buffer *buffer_info;
+- struct iegbe_tx_desc *tx_desc;
+- struct net_device *netdev = adapter->netdev;
+- unsigned int i;
+- unsigned tail;
+- unsigned head;
+- int cleaned = FALSE;
+-
+- tail = readl(adapter->hw.hw_addr + tx_ring->tdt);
+- head = readl(adapter->hw.hw_addr + tx_ring->tdh);
+-
+- if (head != tail) {
+- adapter->stats.tx_hnet++;
+- }
+- if (head != tx_ring->next_to_use) {
+- adapter->stats.tx_hnentu++;
+- }
+- /* Free all the Tx ring sk_buffs from next_to_clean up until
+- * the current head pointer
+- */
+- i = tx_ring->next_to_clean;
+- while(i != head) {
+- cleaned = TRUE;
+- tx_desc = E1000_TX_DESC(*tx_ring, i);
+-
+- buffer_info = &tx_ring->buffer_info[i];
+- iegbe_unmap_and_free_tx_resource(adapter, buffer_info);
+-
+- tx_desc->upper.data = 0;
+-
+- if (unlikely(++i == tx_ring->count)) { i = 0; }
+-
+- }
+- tx_ring->next_to_clean = head;
+-
+- spin_lock(&tx_ring->tx_lock);
+-
+- /* Wake up the queue if it's currently stopped */
+- if (unlikely(cleaned && netif_queue_stopped(netdev) &&
+- netif_carrier_ok(netdev))) {
+- netif_wake_queue(netdev);
++ if(buffer_info->dma) {
++ pci_unmap_page(adapter->pdev,
++ buffer_info->dma,
++ buffer_info->length,
++ PCI_DMA_TODEVICE);
++ buffer_info->dma = 0x0;
++ }
++ if(buffer_info->skb) {
++ dev_kfree_skb_any(buffer_info->skb);
++ buffer_info->skb = NULL;
+ }
+-
+- spin_unlock(&tx_ring->tx_lock);
+ }
+-#endif
++
+
+ /**
+ * iegbe_clean_tx_ring - Free Tx Buffers
+@@ -2134,38 +1914,34 @@ static void iegbe_clean_tx_ring_partial(
+ * @tx_ring: ring to be cleaned
+ **/
+
+-static void
+-iegbe_clean_tx_ring(struct iegbe_adapter *adapter,
++static void iegbe_clean_tx_ring(struct iegbe_adapter *adapter,
+ struct iegbe_tx_ring *tx_ring)
+ {
+- struct iegbe_buffer *buffer_info;
+- unsigned long size;
+- unsigned int i;
+-
+- /* Free all the Tx ring sk_buffs */
++ struct iegbe_hw *hw = &adapter->hw;
++ struct iegbe_buffer *buffer_info;
++ unsigned long size;
++ unsigned int i;
+
+- if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
+- iegbe_unmap_and_free_tx_resource(adapter,
+- &tx_ring->previous_buffer_info);
+- }
++ /* Free all the Tx ring sk_buffs */
+
+ for (i = 0; i < tx_ring->count; i++) {
+- buffer_info = &tx_ring->buffer_info[i];
+- iegbe_unmap_and_free_tx_resource(adapter, buffer_info);
+- }
++ buffer_info = &tx_ring->buffer_info[i];
++ iegbe_unmap_and_free_tx_resource(adapter, buffer_info);
++ }
+
+- size = sizeof(struct iegbe_buffer) * tx_ring->count;
++ size = sizeof(struct iegbe_buffer) * tx_ring->count;
+ memset(tx_ring->buffer_info, 0, size);
+
+- /* Zero out the descriptor ring */
++ /* Zero out the descriptor ring */
+
+ memset(tx_ring->desc, 0, tx_ring->size);
+
+ tx_ring->next_to_use = 0;
+ tx_ring->next_to_clean = 0;
++ tx_ring->last_tx_tso = 0;
+
+- writel(0, adapter->hw.hw_addr + tx_ring->tdh);
+- writel(0, adapter->hw.hw_addr + tx_ring->tdt);
++ writel(0, hw->hw_addr + tx_ring->tdh);
++ writel(0, hw->hw_addr + tx_ring->tdt);
+ }
+
+ /**
+@@ -2173,12 +1949,11 @@ iegbe_clean_tx_ring(struct iegbe_adapter
+ * @adapter: board private structure
+ **/
+
+-static void
+-iegbe_clean_all_tx_rings(struct iegbe_adapter *adapter)
++static void iegbe_clean_all_tx_rings(struct iegbe_adapter *adapter)
+ {
+- int i;
++ int i;
+
+- for (i = 0; i < adapter->num_queues; i++)
++ for (i = 0; i < adapter->num_tx_queues; i++)
+ iegbe_clean_tx_ring(adapter, &adapter->tx_ring[i]);
+ }
+
+@@ -2190,24 +1965,23 @@ iegbe_clean_all_tx_rings(struct iegbe_ad
+ * Free all receive software resources
+ **/
+
+-void
+-iegbe_free_rx_resources(struct iegbe_adapter *adapter,
++static void iegbe_free_rx_resources(struct iegbe_adapter *adapter,
+ struct iegbe_rx_ring *rx_ring)
+ {
+- struct pci_dev *pdev = adapter->pdev;
++ struct pci_dev *pdev = adapter->pdev;
+
+- iegbe_clean_rx_ring(adapter, rx_ring);
++ iegbe_clean_rx_ring(adapter, rx_ring);
+
+- vfree(rx_ring->buffer_info);
+- rx_ring->buffer_info = NULL;
+- kfree(rx_ring->ps_page);
+- rx_ring->ps_page = NULL;
+- kfree(rx_ring->ps_page_dma);
+- rx_ring->ps_page_dma = NULL;
++ vfree(rx_ring->buffer_info);
++ rx_ring->buffer_info = NULL;
++ kfree(rx_ring->ps_page);
++ rx_ring->ps_page = NULL;
++ kfree(rx_ring->ps_page_dma);
++ rx_ring->ps_page_dma = NULL;
+
+- pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma);
++ pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma);
+
+- rx_ring->desc = NULL;
++ rx_ring->desc = NULL;
+ }
+
+ /**
+@@ -2217,12 +1991,11 @@ iegbe_free_rx_resources(struct iegbe_ada
+ * Free all receive software resources
+ **/
+
+-void
+-iegbe_free_all_rx_resources(struct iegbe_adapter *adapter)
++void iegbe_free_all_rx_resources(struct iegbe_adapter *adapter)
+ {
+- int i;
++ int i;
+
+- for (i = 0; i < adapter->num_queues; i++)
++ for (i = 0; i < adapter->num_rx_queues; i++)
+ iegbe_free_rx_resources(adapter, &adapter->rx_ring[i]);
+ }
+
+@@ -2232,60 +2005,59 @@ iegbe_free_all_rx_resources(struct iegbe
+ * @rx_ring: ring to free buffers from
+ **/
+
+-static void
+-iegbe_clean_rx_ring(struct iegbe_adapter *adapter,
++static void iegbe_clean_rx_ring(struct iegbe_adapter *adapter,
+ struct iegbe_rx_ring *rx_ring)
+ {
+- struct iegbe_buffer *buffer_info;
+- struct iegbe_ps_page *ps_page;
+- struct iegbe_ps_page_dma *ps_page_dma;
+- struct pci_dev *pdev = adapter->pdev;
+- unsigned long size;
+- unsigned int i, j;
+-
+- /* Free all the Rx ring sk_buffs */
++ struct iegbe_hw *hw = &adapter->hw;
++ struct iegbe_buffer *buffer_info;
++ struct iegbe_ps_page *ps_page;
++ struct iegbe_ps_page_dma *ps_page_dma;
++ struct pci_dev *pdev = adapter->pdev;
++ unsigned long size;
++ unsigned int i, j;
++
++ /* Free all the Rx ring sk_buffs */
++
++ for (i = 0; i < rx_ring->count; i++) {
++ buffer_info = &rx_ring->buffer_info[i];
++ if(buffer_info->skb) {
++ pci_unmap_single(pdev,
++ buffer_info->dma,
++ buffer_info->length,
++ PCI_DMA_FROMDEVICE);
+
+- for(i = 0; i < rx_ring->count; i++) {
+- buffer_info = &rx_ring->buffer_info[i];
+- if(buffer_info->skb) {
+- ps_page = &rx_ring->ps_page[i];
+- ps_page_dma = &rx_ring->ps_page_dma[i];
+- pci_unmap_single(pdev,
+- buffer_info->dma,
+- buffer_info->length,
+- PCI_DMA_FROMDEVICE);
+-
+- dev_kfree_skb(buffer_info->skb);
+- buffer_info->skb = NULL;
+-
+- for(j = 0; j < adapter->rx_ps_pages; j++) {
+- if(!ps_page->ps_page[j]) { break; }
+- pci_unmap_single(pdev,
+- ps_page_dma->ps_page_dma[j],
+- PAGE_SIZE, PCI_DMA_FROMDEVICE);
+- ps_page_dma->ps_page_dma[j] = 0;
+- put_page(ps_page->ps_page[j]);
+- ps_page->ps_page[j] = NULL;
+- }
++ dev_kfree_skb(buffer_info->skb);
++ buffer_info->skb = NULL;
+ }
+- }
++ ps_page = &rx_ring->ps_page[i];
++ ps_page_dma = &rx_ring->ps_page_dma[i];
++ for (j = 0; j < adapter->rx_ps_pages; j++) {
++ if (!ps_page->ps_page[j]) break;
++ pci_unmap_page(pdev,
++ ps_page_dma->ps_page_dma[j],
++ PAGE_SIZE, PCI_DMA_FROMDEVICE);
++ ps_page_dma->ps_page_dma[j] = 0;
++ put_page(ps_page->ps_page[j]);
++ ps_page->ps_page[j] = NULL;
++ }
++ }
+
+- size = sizeof(struct iegbe_buffer) * rx_ring->count;
++ size = sizeof(struct iegbe_buffer) * rx_ring->count;
+ memset(rx_ring->buffer_info, 0, size);
+- size = sizeof(struct iegbe_ps_page) * rx_ring->count;
++ size = sizeof(struct iegbe_ps_page) * rx_ring->count;
+ memset(rx_ring->ps_page, 0, size);
+- size = sizeof(struct iegbe_ps_page_dma) * rx_ring->count;
++ size = sizeof(struct iegbe_ps_page_dma) * rx_ring->count;
+ memset(rx_ring->ps_page_dma, 0, size);
+
+- /* Zero out the descriptor ring */
++ /* Zero out the descriptor ring */
+
+ memset(rx_ring->desc, 0, rx_ring->size);
+
+ rx_ring->next_to_clean = 0;
+ rx_ring->next_to_use = 0;
+
+- writel(0, adapter->hw.hw_addr + rx_ring->rdh);
+- writel(0, adapter->hw.hw_addr + rx_ring->rdt);
++ writel(0, hw->hw_addr + rx_ring->rdh);
++ writel(0, hw->hw_addr + rx_ring->rdt);
+ }
+
+ /**
+@@ -2293,60 +2065,54 @@ iegbe_clean_rx_ring(struct iegbe_adapter
+ * @adapter: board private structure
+ **/
+
+-static void
+-iegbe_clean_all_rx_rings(struct iegbe_adapter *adapter)
++static void iegbe_clean_all_rx_rings(struct iegbe_adapter *adapter)
+ {
+- int i;
++ int i;
+
+- for (i = 0; i < adapter->num_queues; i++)
++ for (i = 0; i < adapter->num_rx_queues; i++)
+ iegbe_clean_rx_ring(adapter, &adapter->rx_ring[i]);
+ }
+
+ /* The 82542 2.0 (revision 2) needs to have the receive unit in reset
+ * and memory write and invalidate disabled for certain operations
+ */
+-static void
+-iegbe_enter_82542_rst(struct iegbe_adapter *adapter)
++static void iegbe_enter_82542_rst(struct iegbe_adapter *adapter)
+ {
+- struct net_device *netdev = adapter->netdev;
+- uint32_t rctl;
++ struct net_device *netdev = adapter->netdev;
++ uint32_t rctl;
+
+- iegbe_pci_clear_mwi(&adapter->hw);
++ iegbe_pci_clear_mwi(&adapter->hw);
+
+- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+- rctl |= E1000_RCTL_RST;
+- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+- E1000_WRITE_FLUSH(&adapter->hw);
++ rctl = E1000_READ_REG(&adapter->hw, RCTL);
++ rctl |= E1000_RCTL_RST;
++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
++ E1000_WRITE_FLUSH(&adapter->hw);
+ mdelay(0x5);
+
+ if(netif_running(netdev)) {
+- iegbe_clean_all_rx_rings(adapter);
+-}
++ iegbe_clean_all_rx_rings(adapter);
++ }
+ }
+
+ static void
+ iegbe_leave_82542_rst(struct iegbe_adapter *adapter)
+ {
+- struct net_device *netdev = adapter->netdev;
+- uint32_t rctl;
++ struct net_device *netdev = adapter->netdev;
++ uint32_t rctl;
+
+- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+- rctl &= ~E1000_RCTL_RST;
+- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+- E1000_WRITE_FLUSH(&adapter->hw);
++ rctl = E1000_READ_REG(&adapter->hw, RCTL);
++ rctl &= ~E1000_RCTL_RST;
++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
++ E1000_WRITE_FLUSH(&adapter->hw);
+ mdelay(0x5);
+
+ if(adapter->hw.pci_cmd_word & PCI_COMMAND_INVALIDATE) {
+- iegbe_pci_set_mwi(&adapter->hw);
++ iegbe_pci_set_mwi(&adapter->hw);
+ }
+ if(netif_running(netdev)) {
++ struct iegbe_rx_ring *ring = &adapter->rx_ring[0x0];
+ iegbe_configure_rx(adapter);
+-#ifdef IEGBE_GBE_WORKAROUND
+- iegbe_alloc_rx_buffers(adapter, &adapter->rx_ring[0],
+- IEGBE_GBE_WORKAROUND_NUM_RX_DESCRIPTORS + 1);
+-#else
+- iegbe_alloc_rx_buffers(adapter, &adapter->rx_ring[0]);
+-#endif
++ adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring));
+ }
+ }
+
+@@ -2358,133 +2124,153 @@ iegbe_leave_82542_rst(struct iegbe_adapt
+ * Returns 0 on success, negative on failure
+ **/
+
+-static int
+-iegbe_set_mac(struct net_device *netdev, void *p)
++static int iegbe_set_mac(struct net_device *netdev, void *p)
+ {
+- struct iegbe_adapter *adapter = netdev_priv(netdev);
+- struct sockaddr *addr = p;
++ struct iegbe_adapter *adapter = netdev_priv(netdev);
++ struct sockaddr *addr = p;
+
+ if(!is_valid_ether_addr(addr->sa_data)) {
+- return -EADDRNOTAVAIL;
++ return -EADDRNOTAVAIL;
+ }
+- /* 82542 2.0 needs to be in reset to write receive address registers */
++ /* 82542 2.0 needs to be in reset to write receive address registers */
+
+ if(adapter->hw.mac_type == iegbe_82542_rev2_0) {
+- iegbe_enter_82542_rst(adapter);
++ iegbe_enter_82542_rst(adapter);
+ }
+- memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+- memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
++ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
++ memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+
+- iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
++ iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, 0x0);
+
+- /* With 82571 controllers, LAA may be overwritten (with the default)
+- * due to controller reset from the other port. */
+- if (adapter->hw.mac_type == iegbe_82571) {
+- /* activate the work around */
++ /* With 82571 controllers, LAA may be overwritten (with the default)
++ * due to controller reset from the other port. */
++ if (adapter->hw.mac_type == iegbe_82571) {
++ /* activate the work around */
+ adapter->hw.laa_is_present = 0x1;
+
+- /* Hold a copy of the LAA in RAR[14] This is done so that
+- * between the time RAR[0] gets clobbered and the time it
+- * gets fixed (in iegbe_watchdog), the actual LAA is in one
+- * of the RARs and no incoming packets directed to this port
+- * are dropped. Eventaully the LAA will be in RAR[0] and
+- * RAR[14] */
+- iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr,
++ /* Hold a copy of the LAA in RAR[14] This is done so that
++ * between the time RAR[0] gets clobbered and the time it
++ * gets fixed (in iegbe_watchdog), the actual LAA is in one
++ * of the RARs and no incoming packets directed to this port
++ * are dropped. Eventaully the LAA will be in RAR[0] and
++ * RAR[14] */
++ iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr,
+ E1000_RAR_ENTRIES - 0x1);
+- }
++ }
+
+ if(adapter->hw.mac_type == iegbe_82542_rev2_0) {
+- iegbe_leave_82542_rst(adapter);
++ iegbe_leave_82542_rst(adapter);
+ }
+- return 0;
++ return 0x0;
+ }
+
+ /**
+- * iegbe_set_multi - Multicast and Promiscuous mode set
++ * iegbe_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set
+ * @netdev: network interface device structure
+ *
+- * The set_multi entry point is called whenever the multicast address
+- * list or the network interface flags are updated. This routine is
+- * responsible for configuring the hardware for proper multicast,
++ * The set_rx_mode entry point is called whenever the unicast or multicast
++ * address lists or the network interface flags are updated. This routine is
++ * responsible for configuring the hardware for proper unicast, multicast,
+ * promiscuous mode, and all-multi behavior.
+ **/
+
+-static void
+-iegbe_set_multi(struct net_device *netdev)
++static void iegbe_set_rx_mode(struct net_device *netdev)
+ {
+ struct iegbe_adapter *adapter = netdev_priv(netdev);
+ struct iegbe_hw *hw = &adapter->hw;
+- struct dev_mc_list *mc_ptr;
+- uint32_t rctl;
+- uint32_t hash_value;
++ struct dev_addr_list *uc_ptr;
++ struct dev_addr_list *mc_ptr;
++ u32 rctl;
++ u32 hash_value;
+ int i, rar_entries = E1000_RAR_ENTRIES;
++int mta_reg_count = E1000_NUM_MTA_REGISTERS;
+
+ /* reserve RAR[14] for LAA over-write work-around */
+- if (adapter->hw.mac_type == iegbe_82571) {
++ if (hw->mac_type == iegbe_82571)
+ rar_entries--;
+- }
++
+ /* Check for Promiscuous and All Multicast modes */
+
+- rctl = E1000_READ_REG(hw, RCTL);
++ rctl = E1000_READ_REG(&adapter->hw, RCTL);
+
+ if (netdev->flags & IFF_PROMISC) {
+ rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
+- } else if (netdev->flags & IFF_ALLMULTI) {
+- rctl |= E1000_RCTL_MPE;
+- rctl &= ~E1000_RCTL_UPE;
++ rctl &= ~E1000_RCTL_VFE;
+ } else {
+- rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE);
++ if (netdev->flags & IFF_ALLMULTI) {
++ rctl |= E1000_RCTL_MPE;
++ } else {
++ rctl &= ~E1000_RCTL_MPE;
++ }
++ }
++
++ uc_ptr = NULL;
++ if (netdev->uc_count > rar_entries - 1) {
++ rctl |= E1000_RCTL_UPE;
++ } else if (!(netdev->flags & IFF_PROMISC)) {
++ rctl &= ~E1000_RCTL_UPE;
++ uc_ptr = netdev->uc_list;
+ }
+
+- E1000_WRITE_REG(hw, RCTL, rctl);
++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+
+ /* 82542 2.0 needs to be in reset to write receive address registers */
+
+- if (hw->mac_type == iegbe_82542_rev2_0) {
++ if (hw->mac_type == iegbe_82542_rev2_0)
+ iegbe_enter_82542_rst(adapter);
+- }
+- /* load the first 14 multicast address into the exact filters 1-14
++
++ /* load the first 14 addresses into the exact filters 1-14. Unicast
++ * addresses take precedence to avoid disabling unicast filtering
++ * when possible.
++ *
+ * RAR 0 is used for the station MAC adddress
+ * if there are not 14 addresses, go ahead and clear the filters
+ * -- with 82571 controllers only 0-13 entries are filled here
+ */
+ mc_ptr = netdev->mc_list;
+
+- for (i = 0x1; i < rar_entries; i++) {
+- if (mc_ptr) {
+- iegbe_rar_set(hw, mc_ptr->dmi_addr, i);
++ for (i = 1; i < rar_entries; i++) {
++ if (uc_ptr) {
++ iegbe_rar_set(hw, uc_ptr->da_addr, i);
++ uc_ptr = uc_ptr->next;
++ } else if (mc_ptr) {
++ iegbe_rar_set(hw, mc_ptr->da_addr, i);
+ mc_ptr = mc_ptr->next;
+ } else {
+- E1000_WRITE_REG_ARRAY(hw, RA, i << 0x1, 0);
+- E1000_WRITE_REG_ARRAY(hw, RA, (i << 0x1) + 0x1, 0);
++ E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0);
++ E1000_WRITE_FLUSH(&adapter->hw);
++ E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0);
++ E1000_WRITE_FLUSH(&adapter->hw);
+ }
+ }
++ WARN_ON(uc_ptr != NULL);
+
+ /* clear the old settings from the multicast hash table */
+
+- for (i = 0; i < E1000_NUM_MTA_REGISTERS; i++)
++ for (i = 0; i < mta_reg_count; i++) {
+ E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
++ E1000_WRITE_FLUSH(&adapter->hw);
++ }
+
+ /* load any remaining addresses into the hash table */
+
+ for (; mc_ptr; mc_ptr = mc_ptr->next) {
+- hash_value = iegbe_hash_mc_addr(hw, mc_ptr->dmi_addr);
++ hash_value = iegbe_hash_mc_addr(hw, mc_ptr->da_addr);
+ iegbe_mta_set(hw, hash_value);
+ }
+
+- if (hw->mac_type == iegbe_82542_rev2_0) {
++ if (hw->mac_type == iegbe_82542_rev2_0)
+ iegbe_leave_82542_rst(adapter);
+ }
+-}
+
+ /* Need to wait a few seconds after link up to get diagnostic information from
+ * the phy */
+
+-static void
+-iegbe_update_phy_info(unsigned long data)
++static void iegbe_update_phy_info(unsigned long data)
+ {
+- struct iegbe_adapter *adapter = (struct iegbe_adapter *) data;
+- iegbe_phy_get_info(&adapter->hw, &adapter->phy_info);
++ struct iegbe_adapter *adapter = (struct iegbe_adapter *) data;
++ struct iegbe_hw *hw = &adapter->hw;
++ iegbe_phy_get_info(hw, &adapter->phy_info);
+ }
+
+ /**
+@@ -2492,54 +2278,54 @@ iegbe_update_phy_info(unsigned long data
+ * @data: pointer to adapter cast into an unsigned long
+ **/
+
+-static void
+-iegbe_82547_tx_fifo_stall(unsigned long data)
++static void iegbe_82547_tx_fifo_stall(unsigned long data)
+ {
+- struct iegbe_adapter *adapter = (struct iegbe_adapter *) data;
+- struct net_device *netdev = adapter->netdev;
+- uint32_t tctl;
++ struct iegbe_adapter *adapter = (struct iegbe_adapter *) data;
++ struct net_device *netdev = adapter->netdev;
++ u32 tctl;
+
+- if(atomic_read(&adapter->tx_fifo_stall)) {
+- if((E1000_READ_REG(&adapter->hw, TDT) ==
+- E1000_READ_REG(&adapter->hw, TDH)) &&
+- (E1000_READ_REG(&adapter->hw, TDFT) ==
+- E1000_READ_REG(&adapter->hw, TDFH)) &&
+- (E1000_READ_REG(&adapter->hw, TDFTS) ==
+- E1000_READ_REG(&adapter->hw, TDFHS))) {
+- tctl = E1000_READ_REG(&adapter->hw, TCTL);
+- E1000_WRITE_REG(&adapter->hw, TCTL,
+- tctl & ~E1000_TCTL_EN);
+- E1000_WRITE_REG(&adapter->hw, TDFT,
+- adapter->tx_head_addr);
+- E1000_WRITE_REG(&adapter->hw, TDFH,
+- adapter->tx_head_addr);
+- E1000_WRITE_REG(&adapter->hw, TDFTS,
+- adapter->tx_head_addr);
+- E1000_WRITE_REG(&adapter->hw, TDFHS,
+- adapter->tx_head_addr);
+- E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
+- E1000_WRITE_FLUSH(&adapter->hw);
+-
+- adapter->tx_fifo_head = 0;
+- atomic_set(&adapter->tx_fifo_stall, 0);
+- netif_wake_queue(netdev);
+- } else {
++ if(atomic_read(&adapter->tx_fifo_stall)) {
++ if((E1000_READ_REG(&adapter->hw, TDT) ==
++ E1000_READ_REG(&adapter->hw, TDH)) &&
++ (E1000_READ_REG(&adapter->hw, TDFT) ==
++ E1000_READ_REG(&adapter->hw, TDFH)) &&
++ (E1000_READ_REG(&adapter->hw, TDFTS) ==
++ E1000_READ_REG(&adapter->hw, TDFHS))) {
++ tctl = E1000_READ_REG(&adapter->hw, TCTL);
++ E1000_WRITE_REG(&adapter->hw, TCTL,
++ tctl & ~E1000_TCTL_EN);
++ E1000_WRITE_REG(&adapter->hw, TDFT,
++ adapter->tx_head_addr);
++ E1000_WRITE_REG(&adapter->hw, TDFH,
++ adapter->tx_head_addr);
++ E1000_WRITE_REG(&adapter->hw, TDFTS,
++ adapter->tx_head_addr);
++ E1000_WRITE_REG(&adapter->hw, TDFHS,
++ adapter->tx_head_addr);
++ E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
++ E1000_WRITE_FLUSH(&adapter->hw);
++
++ adapter->tx_fifo_head = 0x0;
++ atomic_set(&adapter->tx_fifo_stall, 0x0);
++ netif_wake_queue(netdev);
++ } else {
+ mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 0x1);
+- }
+- }
++ }
++ }
+ }
+
++
+ /**
+ * iegbe_watchdog - Timer Call-back
+ * @data: pointer to adapter cast into an unsigned long
+ **/
+-static void
+-iegbe_watchdog(unsigned long data)
++static void iegbe_watchdog(unsigned long data)
+ {
+- struct iegbe_adapter *adapter = (struct iegbe_adapter *) data;
+- struct net_device *netdev = adapter->netdev;
+- struct iegbe_tx_ring *txdr = &adapter->tx_ring[0];
+- uint32_t link;
++ struct iegbe_adapter *adapter = (struct iegbe_adapter *) data;
++ struct iegbe_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ struct iegbe_tx_ring *txdr = adapter->tx_ring;
++ u32 link, tctl;
+
+ /*
+ * Test the PHY for link status on icp_xxxx MACs.
+@@ -2547,123 +2333,305 @@ iegbe_watchdog(unsigned long data)
+ * in the adapter->hw structure, then set hw->get_link_status = 1
+ */
+ if(adapter->hw.mac_type == iegbe_icp_xxxx) {
+- int isUp = 0;
++ int isUp = 0x0;
+ int32_t ret_val;
+
+ ret_val = iegbe_oem_phy_is_link_up(&adapter->hw, &isUp);
+ if(ret_val != E1000_SUCCESS) {
+- isUp = 0;
+- }
++ isUp = 0x0;
++ }
+ if(isUp != adapter->hw.icp_xxxx_is_link_up) {
+ adapter->hw.get_link_status = 0x1;
+ }
+ }
+
+- iegbe_check_for_link(&adapter->hw);
+- if (adapter->hw.mac_type == iegbe_82573) {
+- iegbe_enable_tx_pkt_filtering(&adapter->hw);
++ iegbe_check_for_link(&adapter->hw);
++ if (adapter->hw.mac_type == iegbe_82573) {
++ iegbe_enable_tx_pkt_filtering(&adapter->hw);
+ #ifdef NETIF_F_HW_VLAN_TX
+ if (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id) {
+- iegbe_update_mng_vlan(adapter);
++ iegbe_update_mng_vlan(adapter);
+ }
+ #endif
+- }
++ }
+
+- if ((adapter->hw.media_type == iegbe_media_type_internal_serdes) &&
+- !(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE)) {
+- link = !adapter->hw.serdes_link_down;
+- } else {
++ if ((adapter->hw.media_type == iegbe_media_type_internal_serdes) &&
++ !(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE)) {
++ link = !adapter->hw.serdes_link_down;
++ } else {
+
+- if(adapter->hw.mac_type != iegbe_icp_xxxx) {
+- link = E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU;
+- } else {
+- int isUp = 0;
++ if(adapter->hw.mac_type != iegbe_icp_xxxx) {
++ link = E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU;
++ } else {
++ int isUp = 0x0;
+ if(iegbe_oem_phy_is_link_up(&adapter->hw, &isUp) != E1000_SUCCESS) {
+- isUp = 0;
++ isUp = 0x0;
+ }
+- link = isUp;
+- }
+- }
++ link = isUp;
++ }
++ }
+
+- if (link) {
+- if (!netif_carrier_ok(netdev)) {
+- iegbe_get_speed_and_duplex(&adapter->hw,
+- &adapter->link_speed,
+- &adapter->link_duplex);
+-
+- DPRINTK(LINK, INFO, "NIC Link is Up %d Mbps %s\n",
+- adapter->link_speed,
+- adapter->link_duplex == FULL_DUPLEX ?
+- "Full Duplex" : "Half Duplex");
++ if (link) {
++ if (!netif_carrier_ok(netdev)) {
++ u32 ctrl;
++ bool txb2b = true;
++ iegbe_get_speed_and_duplex(hw,
++ &adapter->link_speed,
++ &adapter->link_duplex);
+
+- netif_carrier_on(netdev);
+- netif_wake_queue(netdev);
+- mod_timer(&adapter->phy_info_timer, jiffies + 0x2 * HZ);
++ ctrl = E1000_READ_REG(&adapter->hw, CTRL);
++ DPRINTK(LINK, INFO, "NIC Link is Up %d Mbps %s, "
++ "Flow Control: %s\n",
++ adapter->link_speed,
++ adapter->link_duplex == FULL_DUPLEX ?
++ "Full Duplex" : "Half Duplex",
++ ((ctrl & E1000_CTRL_TFCE) && (ctrl &
++ E1000_CTRL_RFCE)) ? "RX/TX" : ((ctrl &
++ E1000_CTRL_RFCE) ? "RX" : ((ctrl &
++ E1000_CTRL_TFCE) ? "TX" : "None" )));
++
++ /* tweak tx_queue_len according to speed/duplex
++ * and adjust the timeout factor */
++ netdev->tx_queue_len = adapter->tx_queue_len;
++ adapter->tx_timeout_factor = 1;
++ switch (adapter->link_speed) {
++ case SPEED_10:
++ txb2b = false;
++ netdev->tx_queue_len = 10;
++ adapter->tx_timeout_factor = 8;
++ break;
++ case SPEED_100:
++ txb2b = false;
++ netdev->tx_queue_len = 100;
++ break;
++ }
++ if ((hw->mac_type == iegbe_82571 ||
++ hw->mac_type == iegbe_82572) &&
++ !txb2b) {
++ u32 tarc0;
++ tarc0 = E1000_READ_REG(&adapter->hw, TARC0);
++ tarc0 &= ~(1 << 21);
++ E1000_WRITE_REG(&adapter->hw, TARC0, tarc0);
++ }
++ /* disable TSO for pcie and 10/100 speeds, to avoid
++ * some hardware issues */
++ if (!adapter->tso_force &&
++ hw->bus_type == iegbe_bus_type_pci_express){
++ switch (adapter->link_speed) {
++ case SPEED_10:
++ case SPEED_100:
++ DPRINTK(PROBE,INFO,
++ "10/100 speed: disabling TSO\n");
++ netdev->features &= ~NETIF_F_TSO;
++ netdev->features &= ~NETIF_F_TSO6;
++ break;
++ case SPEED_1000:
++ netdev->features |= NETIF_F_TSO;
++ netdev->features |= NETIF_F_TSO6;
++ break;
++ default:
++ break;
++ }
++ }
++ tctl = E1000_READ_REG(&adapter->hw, TCTL);
++ tctl |= E1000_TCTL_EN;
++ E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
++ netif_carrier_on(netdev);
++ netif_wake_queue(netdev);
++ mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ));
+ adapter->smartspeed = 0;
++ } else {
++ if (hw->rx_needs_kicking) {
++ u32 rctl = E1000_READ_REG(&adapter->hw, RCTL);
++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl | E1000_RCTL_EN);
++ }
+ }
+- } else {
+- if (netif_carrier_ok(netdev)) {
++ } else {
++ if (netif_carrier_ok(netdev)) {
+ adapter->link_speed = 0;
+ adapter->link_duplex = 0;
+- DPRINTK(LINK, INFO, "NIC Link is Down\n");
+- netif_carrier_off(netdev);
+- netif_stop_queue(netdev);
+- mod_timer(&adapter->phy_info_timer, jiffies + 0x2 * HZ);
+- }
++ DPRINTK(LINK, INFO, "NIC Link is Down\n");
++ netif_carrier_off(netdev);
++ netif_stop_queue(netdev);
++ mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ));
++ }
+
+- iegbe_smartspeed(adapter);
+- }
++ iegbe_smartspeed(adapter);
++ }
++
++ iegbe_update_stats(adapter);
++
++ hw->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
++ adapter->tpt_old = adapter->stats.tpt;
++ hw->collision_delta = adapter->stats.colc - adapter->colc_old;
++ adapter->colc_old = adapter->stats.colc;
++
++ adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old;
++ adapter->gorcl_old = adapter->stats.gorcl;
++ adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old;
++ adapter->gotcl_old = adapter->stats.gotcl;
++
++ iegbe_update_adaptive(hw);
++
++ if (!netif_carrier_ok(netdev)) {
++ if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
++ /* We've lost link, so the controller stops DMA,
++ * but we've got queued Tx work that's never going
++ * to get done, so reset controller to flush Tx.
++ * (Do the reset outside of interrupt context). */
++ adapter->tx_timeout_count++;
++ schedule_work(&adapter->reset_task);
++ }
++ }
++
++ /* Cause software interrupt to ensure rx ring is cleaned */
++ E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0);
++
++ /* Force detection of hung controller every watchdog period */
++ adapter->detect_tx_hung = TRUE;
++
++ /* With 82571 controllers, LAA may be overwritten due to controller
++ * reset from the other port. Set the appropriate LAA in RAR[0] */
++ if (adapter->hw.mac_type == iegbe_82571 && adapter->hw.laa_is_present) {
++ iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, 0x0);
++ }
++ /* Reset the timer */
++ mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 2 * HZ));
++}
++
++enum latency_range {
++ lowest_latency = 0,
++ low_latency = 1,
++ bulk_latency = 2,
++ latency_invalid = 255
++};
+
+- iegbe_update_stats(adapter);
++/**
++ * iegbe_update_itr - update the dynamic ITR value based on statistics
++ * Stores a new ITR value based on packets and byte
++ * counts during the last interrupt. The advantage of per interrupt
++ * computation is faster updates and more accurate ITR for the current
++ * traffic pattern. Constants in this function were computed
++ * based on theoretical maximum wire speed and thresholds were set based
++ * on testing data as well as attempting to minimize response time
++ * while increasing bulk throughput.
++ * this functionality is controlled by the InterruptThrottleRate module
++ * parameter (see iegbe_param.c)
++ * @adapter: pointer to adapter
++ * @itr_setting: current adapter->itr
++ * @packets: the number of packets during this measurement interval
++ * @bytes: the number of bytes during this measurement interval
++ **/
++static unsigned int iegbe_update_itr(struct iegbe_adapter *adapter,
++ u16 itr_setting, int packets, int bytes)
++{
++ unsigned int retval = itr_setting;
++ struct iegbe_hw *hw = &adapter->hw;
+
+- adapter->hw.tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
+- adapter->tpt_old = adapter->stats.tpt;
+- adapter->hw.collision_delta = adapter->stats.colc - adapter->colc_old;
+- adapter->colc_old = adapter->stats.colc;
+-
+- adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old;
+- adapter->gorcl_old = adapter->stats.gorcl;
+- adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old;
+- adapter->gotcl_old = adapter->stats.gotcl;
+-
+- iegbe_update_adaptive(&adapter->hw);
+-
+- if (adapter->num_queues == 0x1 && !netif_carrier_ok(netdev)) {
+- if (E1000_DESC_UNUSED(txdr) + 0x1 < txdr->count) {
+- /* We've lost link, so the controller stops DMA,
+- * but we've got queued Tx work that's never going
+- * to get done, so reset controller to flush Tx.
+- * (Do the reset outside of interrupt context). */
+- schedule_work(&adapter->tx_timeout_task);
++ if (unlikely(hw->mac_type < iegbe_82540))
++ goto update_itr_done;
++
++ if (packets == 0)
++ goto update_itr_done;
++
++ switch (itr_setting) {
++ case lowest_latency:
++ /* jumbo frames get bulk treatment*/
++ if (bytes/packets > 8000)
++ retval = bulk_latency;
++ else if ((packets < 5) && (bytes > 512))
++ retval = low_latency;
++ break;
++ case low_latency: /* 50 usec aka 20000 ints/s */
++ if (bytes > 10000) {
++ /* jumbo frames need bulk latency setting */
++ if (bytes/packets > 8000)
++ retval = bulk_latency;
++ else if ((packets < 10) || ((bytes/packets) > 1200))
++ retval = bulk_latency;
++ else if ((packets > 35))
++ retval = lowest_latency;
++ } else if (bytes/packets > 2000)
++ retval = bulk_latency;
++ else if (packets <= 2 && bytes < 512)
++ retval = lowest_latency;
++ break;
++ case bulk_latency: /* 250 usec aka 4000 ints/s */
++ if (bytes > 25000) {
++ if (packets > 35)
++ retval = low_latency;
++ } else if (bytes < 6000) {
++ retval = low_latency;
+ }
++ break;
+ }
+
+- /* Dynamic mode for Interrupt Throttle Rate (ITR) */
+- if (adapter->hw.mac_type >= iegbe_82540 && adapter->itr == 0x1) {
+- /* Symmetric Tx/Rx gets a reduced ITR=2000; Total
+- * asymmetrical Tx or Rx gets ITR=8000; everyone
+- * else is between 2000-8000. */
+- uint32_t goc = (adapter->gotcl + adapter->gorcl) / 0x2710;
+- uint32_t dif = (adapter->gotcl > adapter->gorcl ?
+- adapter->gotcl - adapter->gorcl :
+- adapter->gorcl - adapter->gotcl) / 0x2710;
+- uint32_t itr = goc > 0 ? (dif * 0x1770 / goc + 0x7d0) : 0x1f40;
+- E1000_WRITE_REG(&adapter->hw, ITR, 0x3b9aca00 / (itr * 0x100));
+- }
++update_itr_done:
++ return retval;
++}
+
+- /* Cause software interrupt to ensure rx ring is cleaned */
+- E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0);
++static void iegbe_set_itr(struct iegbe_adapter *adapter)
++{
++ struct iegbe_hw *hw = &adapter->hw;
++ u16 current_itr;
++ u32 new_itr = adapter->itr;
+
+- /* Force detection of hung controller every watchdog period */
+- adapter->detect_tx_hung = TRUE;
++ if (unlikely(hw->mac_type < iegbe_82540))
++ return;
+
+- /* With 82571 controllers, LAA may be overwritten due to controller
+- * reset from the other port. Set the appropriate LAA in RAR[0] */
+- if (adapter->hw.mac_type == iegbe_82571 && adapter->hw.laa_is_present) {
+- iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
+- }
+- /* Reset the timer */
+- mod_timer(&adapter->watchdog_timer, jiffies + 0x2 * HZ);
++ /* for non-gigabit speeds, just fix the interrupt rate at 4000 */
++ if (unlikely(adapter->link_speed != SPEED_1000)) {
++ current_itr = 0;
++ new_itr = 4000;
++ goto set_itr_now;
++ }
++
++ adapter->tx_itr = iegbe_update_itr(adapter,
++ adapter->tx_itr,
++ adapter->total_tx_packets,
++ adapter->total_tx_bytes);
++ /* conservative mode (itr 3) eliminates the lowest_latency setting */
++ if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency)
++ adapter->tx_itr = low_latency;
++
++ adapter->rx_itr = iegbe_update_itr(adapter,
++ adapter->rx_itr,
++ adapter->total_rx_packets,
++ adapter->total_rx_bytes);
++ /* conservative mode (itr 3) eliminates the lowest_latency setting */
++ if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency)
++ adapter->rx_itr = low_latency;
++
++ current_itr = max(adapter->rx_itr, adapter->tx_itr);
++
++ switch (current_itr) {
++ /* counts and packets in update_itr are dependent on these numbers */
++ case lowest_latency:
++ new_itr = 70000;
++ break;
++ case low_latency:
++ new_itr = 20000; /* aka hwitr = ~200 */
++ break;
++ case bulk_latency:
++ new_itr = 4000;
++ break;
++ default:
++ break;
++ }
++
++set_itr_now:
++ if (new_itr != adapter->itr) {
++ /* this attempts to bias the interrupt rate towards Bulk
++ * by adding intermediate steps when interrupt rate is
++ * increasing */
++ new_itr = new_itr > adapter->itr ?
++ min(adapter->itr + (new_itr >> 2), new_itr) :
++ new_itr;
++ adapter->itr = new_itr;
++ E1000_WRITE_REG(&adapter->hw, ITR, 1000000000 / (new_itr * 256));
++ }
++
++ return;
+ }
+
+ #define E1000_TX_FLAGS_CSUM 0x00000001
+@@ -2673,55 +2641,48 @@ iegbe_watchdog(unsigned long data)
+ #define E1000_TX_FLAGS_VLAN_MASK 0xffff0000
+ #define E1000_TX_FLAGS_VLAN_SHIFT 16
+
+-static inline int
+-iegbe_tso(struct iegbe_adapter *adapter, struct iegbe_tx_ring *tx_ring,
+- struct sk_buff *skb)
++static int iegbe_tso(struct iegbe_adapter *adapter,
++ struct iegbe_tx_ring *tx_ring, struct sk_buff *skb)
+ {
+-#ifdef NETIF_F_TSO
+ struct iegbe_context_desc *context_desc;
++ struct iegbe_buffer *buffer_info;
+ unsigned int i;
+- uint32_t cmd_length = 0;
+- uint16_t ipcse = 0, tucse, mss;
+- uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
++ u32 cmd_length = 0;
++ u16 ipcse = 0, tucse, mss;
++ u8 ipcss, ipcso, tucss, tucso, hdr_len;
+ int err;
+
+ if (skb_is_gso(skb)) {
+ if (skb_header_cloned(skb)) {
+ err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+- if (err) {
++ if (err)
+ return err;
+ }
+- }
+
+- hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 0x2));
++ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+ mss = skb_shinfo(skb)->gso_size;
+ if (skb->protocol == htons(ETH_P_IP)) {
+- skb->nh.iph->tot_len = 0;
+- skb->nh.iph->check = 0;
+- skb->h.th->check =
+- ~csum_tcpudp_magic(skb->nh.iph->saddr,
+- skb->nh.iph->daddr,
+- 0,
+- IPPROTO_TCP,
+- 0);
++ struct iphdr *iph = ip_hdr(skb);
++ iph->tot_len = 0;
++ iph->check = 0;
++ tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
++ iph->daddr, 0,
++ IPPROTO_TCP,
++ 0);
+ cmd_length = E1000_TXD_CMD_IP;
+- ipcse = skb->h.raw - skb->data - 0x1;
+-#ifdef NETIF_F_TSO_IPV6
+- } else if (skb->protocol == ntohs(ETH_P_IPV6)) {
+- skb->nh.ipv6h->payload_len = 0;
+- skb->h.th->check =
+- ~csum_ipv6_magic(&skb->nh.ipv6h->saddr,
+- &skb->nh.ipv6h->daddr,
+- 0,
+- IPPROTO_TCP,
+- 0);
++ ipcse = skb_transport_offset(skb) - 1;
++ } else if (skb->protocol == htons(ETH_P_IPV6)) {
++ ipv6_hdr(skb)->payload_len = 0;
++ tcp_hdr(skb)->check =
++ ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
++ &ipv6_hdr(skb)->daddr,
++ 0, IPPROTO_TCP, 0);
+ ipcse = 0;
+-#endif
+ }
+- ipcss = skb->nh.raw - skb->data;
+- ipcso = (void *)&(skb->nh.iph->check) - (void *)skb->data;
+- tucss = skb->h.raw - skb->data;
+- tucso = (void *)&(skb->h.th->check) - (void *)skb->data;
++ ipcss = skb_network_offset(skb);
++ ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data;
++ tucss = skb_transport_offset(skb);
++ tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data;
+ tucse = 0;
+
+ cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
+@@ -2729,6 +2690,7 @@ iegbe_tso(struct iegbe_adapter *adapter,
+
+ i = tx_ring->next_to_use;
+ context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
++ buffer_info = &tx_ring->buffer_info[i];
+
+ context_desc->lower_setup.ip_fields.ipcss = ipcss;
+ context_desc->lower_setup.ip_fields.ipcso = ipcso;
+@@ -2740,205 +2702,218 @@ iegbe_tso(struct iegbe_adapter *adapter,
+ context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
+ context_desc->cmd_and_length = cpu_to_le32(cmd_length);
+
+- if (++i == tx_ring->count) { i = 0; }
++ buffer_info->time_stamp = jiffies;
++ buffer_info->next_to_watch = i;
++
++ if (++i == tx_ring->count) i = 0;
+ tx_ring->next_to_use = i;
+
+- return TRUE;
++ return true;
+ }
+-#endif
+-
+- return FALSE;
++ return false;
+ }
+
+-static inline boolean_t
+-iegbe_tx_csum(struct iegbe_adapter *adapter, struct iegbe_tx_ring *tx_ring,
+- struct sk_buff *skb)
++static bool iegbe_tx_csum(struct iegbe_adapter *adapter,
++ struct iegbe_tx_ring *tx_ring, struct sk_buff *skb)
+ {
+ struct iegbe_context_desc *context_desc;
++ struct iegbe_buffer *buffer_info;
+ unsigned int i;
+- uint8_t css;
++ u8 css;
+
+- if (likely(skb->ip_summed == CHECKSUM_HW)) {
+- css = skb->h.raw - skb->data;
++ if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
++ css = skb_transport_offset(skb);
+
+- i = tx_ring->next_to_use;
+- context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
++ i = tx_ring->next_to_use;
++ buffer_info = &tx_ring->buffer_info[i];
++ context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
+
++ context_desc->lower_setup.ip_config = 0;
+ context_desc->upper_setup.tcp_fields.tucss = css;
+- context_desc->upper_setup.tcp_fields.tucso = css + skb->csum;
++ context_desc->upper_setup.tcp_fields.tucso =
++ css + skb->csum_offset;
+ context_desc->upper_setup.tcp_fields.tucse = 0;
+ context_desc->tcp_seg_setup.data = 0;
+ context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
+
+- if (unlikely(++i == tx_ring->count)) { i = 0; }
++ buffer_info->time_stamp = jiffies;
++ buffer_info->next_to_watch = i;
++
++ if (unlikely(++i == tx_ring->count)) i = 0;
+ tx_ring->next_to_use = i;
+
+- return TRUE;
++ return true;
+ }
+
+- return FALSE;
++ return false;
+ }
+
+-#define E1000_MAX_TXD_PWR 12
+-#define E1000_MAX_DATA_PER_TXD (1<<E1000_MAX_TXD_PWR)
++#define E1000_MAX_TXD_PWR 12
++#define E1000_MAX_DATA_PER_TXD (1<<E1000_MAX_TXD_PWR)
+
+-static inline int
+-iegbe_tx_map(struct iegbe_adapter *adapter, struct iegbe_tx_ring *tx_ring,
+- struct sk_buff *skb, unsigned int first, unsigned int max_per_txd,
+- unsigned int nr_frags, unsigned int mss)
++static int iegbe_tx_map(struct iegbe_adapter *adapter,
++ struct iegbe_tx_ring *tx_ring,
++ struct sk_buff *skb, unsigned int first,
++ unsigned int max_per_txd, unsigned int nr_frags,
++ unsigned int mss)
+ {
+- struct iegbe_buffer *buffer_info;
+- unsigned int len = skb->len;
++ struct iegbe_hw *hw = &adapter->hw;
++ struct iegbe_buffer *buffer_info;
++ unsigned int len = skb->len;
+ unsigned int offset = 0, size, count = 0, i;
+-#ifdef MAX_SKB_FRAGS
+- unsigned int f;
+- len -= skb->data_len;
+-#endif
++ unsigned int f;
++ len -= skb->data_len;
+
+- i = tx_ring->next_to_use;
++ i = tx_ring->next_to_use;
++
++ while(len) {
++ buffer_info = &tx_ring->buffer_info[i];
++ size = min(len, max_per_txd);
++ /* Workaround for Controller erratum --
++ * descriptor for non-tso packet in a linear SKB that follows a
++ * tso gets written back prematurely before the data is fully
++ * DMA'd to the controller */
++ if (!skb->data_len && tx_ring->last_tx_tso &&
++ !skb_is_gso(skb)) {
++ tx_ring->last_tx_tso = 0;
++ size -= 4;
++ }
+
+- while(len) {
+- buffer_info = &tx_ring->buffer_info[i];
+- size = min(len, max_per_txd);
+-#ifdef NETIF_F_TSO
+ /* Workaround for premature desc write-backs
+ * in TSO mode. Append 4-byte sentinel desc */
+- if(unlikely(mss && !nr_frags && size == len && size > 0x8)) {
+- size -= 0x4;
++ if (unlikely(mss && !nr_frags && size == len && size > 8))
++ size -= 4;
++ /* work-around for errata 10 and it applies
++ * to all controllers in PCI-X mode
++ * The fix is to make sure that the first descriptor of a
++ * packet is smaller than 2048 - 16 - 16 (or 2016) bytes
++ */
++ if (unlikely((hw->bus_type == iegbe_bus_type_pcix) &&
++ (size > 2015) && count == 0))
++ size = 2015;
++
++ /* Workaround for potential 82544 hang in PCI-X. Avoid
++ * terminating buffers within evenly-aligned dwords. */
++ if(unlikely(adapter->pcix_82544 &&
++ !((unsigned long)(skb->data + offset + size - 1) & 4) &&
++ size > 4))
++ size -= 4;
++
++ buffer_info->length = size;
++ buffer_info->dma =
++ pci_map_single(adapter->pdev,
++ skb->data + offset,
++ size,
++ PCI_DMA_TODEVICE);
++ buffer_info->time_stamp = jiffies;
++ buffer_info->next_to_watch = i;
++
++ len -= size;
++ offset += size;
++ count++;
++ if (unlikely(++i == tx_ring->count)) i = 0;
++ }
++
++ for (f = 0; f < nr_frags; f++) {
++ struct skb_frag_struct *frag;
++
++ frag = &skb_shinfo(skb)->frags[f];
++ len = frag->size;
++ offset = frag->page_offset;
++
++ while(len) {
++ buffer_info = &tx_ring->buffer_info[i];
++ size = min(len, max_per_txd);
++ /* Workaround for premature desc write-backs
++ * in TSO mode. Append 4-byte sentinel desc */
++ if (unlikely(mss && f == (nr_frags-1) && size == len && size > 8))
++ size -= 4;
++ /* Workaround for potential 82544 hang in PCI-X.
++ * Avoid terminating buffers within evenly-aligned
++ * dwords. */
++ if(unlikely(adapter->pcix_82544 &&
++ !((unsigned long)(frag->page+offset+size-1) & 4) &&
++ size > 4))
++ size -= 4;
++
++ buffer_info->length = size;
++ buffer_info->dma =
++ pci_map_page(adapter->pdev,
++ frag->page,
++ offset,
++ size,
++ PCI_DMA_TODEVICE);
++ buffer_info->time_stamp = jiffies;
++ buffer_info->next_to_watch = i;
++
++ len -= size;
++ offset += size;
++ count++;
++ if (unlikely(++i == tx_ring->count)) i = 0;
+ }
+-#endif
+- /* work-around for errata 10 and it applies
+- * to all controllers in PCI-X mode
+- * The fix is to make sure that the first descriptor of a
+- * packet is smaller than 2048 - 16 - 16 (or 2016) bytes
+- */
+- if(unlikely((adapter->hw.bus_type == iegbe_bus_type_pcix) &&
+- (size > 0x7df) && count == 0)) {
+- size = 0x7df;
+- }
+- /* Workaround for potential 82544 hang in PCI-X. Avoid
+- * terminating buffers within evenly-aligned dwords. */
+- if(unlikely(adapter->pcix_82544 &&
+- !((unsigned long)(skb->data + offset + size - 0x8) & 0x4) &&
+- size > 0x4)) {
+- size -= 0x4;
+- }
+- buffer_info->length = size;
+- buffer_info->dma =
+- pci_map_single(adapter->pdev,
+- skb->data + offset,
+- size,
+- PCI_DMA_TODEVICE);
+- buffer_info->time_stamp = jiffies;
+-
+- len -= size;
+- offset += size;
+- count++;
+- if(unlikely(++i == tx_ring->count)) { i = 0; }
+- }
+-
+-#ifdef MAX_SKB_FRAGS
+- for(f = 0; f < nr_frags; f++) {
+- struct skb_frag_struct *frag;
+-
+- frag = &skb_shinfo(skb)->frags[f];
+- len = frag->size;
+- offset = frag->page_offset;
+-
+- while(len) {
+- buffer_info = &tx_ring->buffer_info[i];
+- size = min(len, max_per_txd);
+-#ifdef NETIF_F_TSO
+- /* Workaround for premature desc write-backs
+- * in TSO mode. Append 4-byte sentinel desc */
+- if(unlikely(mss && f == (nr_frags-0x1) &&
+- size == len && size > 0x8)) {
+- size -= 0x4;
+- }
+-#endif
+- /* Workaround for potential 82544 hang in PCI-X.
+- * Avoid terminating buffers within evenly-aligned
+- * dwords. */
+- if(unlikely(adapter->pcix_82544 &&
+- !((unsigned long)(frag->page+offset+size-0x1) & 0x4) &&
+- size > 0x4)) {
+- size -= 0x4;
+- }
+- buffer_info->length = size;
+- buffer_info->dma =
+- pci_map_page(adapter->pdev,
+- frag->page,
+- offset,
+- size,
+- PCI_DMA_TODEVICE);
+- buffer_info->time_stamp = jiffies;
+-
+- len -= size;
+- offset += size;
+- count++;
+- if(unlikely(++i == tx_ring->count)) { i = 0; }
+- }
+- }
+-#endif
++ }
+
+- i = (i == 0) ? tx_ring->count - 0x1 : i - 0x1;
+- tx_ring->buffer_info[i].skb = skb;
+- tx_ring->buffer_info[first].next_to_watch = i;
++ i = (i == 0) ? tx_ring->count - 1 : i - 1;
++ tx_ring->buffer_info[i].skb = skb;
++ tx_ring->buffer_info[first].next_to_watch = i;
+
+- return count;
++ return count;
+ }
+
+-static inline void
+-iegbe_tx_queue(struct iegbe_adapter *adapter, struct iegbe_tx_ring *tx_ring,
+- int tx_flags, int count)
++static void iegbe_tx_queue(struct iegbe_adapter *adapter,
++ struct iegbe_tx_ring *tx_ring, int tx_flags,
++ int count)
+ {
++ struct iegbe_hw *hw = &adapter->hw;
+ struct iegbe_tx_desc *tx_desc = NULL;
+ struct iegbe_buffer *buffer_info;
+- uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
++ u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
+ unsigned int i;
+
+- if(likely(tx_flags & E1000_TX_FLAGS_TSO)) {
++ if (likely(tx_flags & E1000_TX_FLAGS_TSO)) {
+ txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
+ E1000_TXD_CMD_TSE;
+- txd_upper |= E1000_TXD_POPTS_TXSM << 0x8;
++ txd_upper |= E1000_TXD_POPTS_TXSM << 8;
+
+- if(likely(tx_flags & E1000_TX_FLAGS_IPV4)) {
+- txd_upper |= E1000_TXD_POPTS_IXSM << 0x8;
+- }
++ if (likely(tx_flags & E1000_TX_FLAGS_IPV4))
++ txd_upper |= E1000_TXD_POPTS_IXSM << 8;
+ }
+
+- if(likely(tx_flags & E1000_TX_FLAGS_CSUM)) {
++ if (likely(tx_flags & E1000_TX_FLAGS_CSUM)) {
+ txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
+- txd_upper |= E1000_TXD_POPTS_TXSM << 0x8;
+- }
+-
+- if(unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) {
+- txd_lower |= E1000_TXD_CMD_VLE;
+- txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
++ txd_upper |= E1000_TXD_POPTS_TXSM << 8;
+ }
+
+- i = tx_ring->next_to_use;
++ if(unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) {
++ txd_lower |= E1000_TXD_CMD_VLE;
++ txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
++ }
+
+- while(count--) {
+- buffer_info = &tx_ring->buffer_info[i];
+- tx_desc = E1000_TX_DESC(*tx_ring, i);
+- tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
+- tx_desc->lower.data =
+- cpu_to_le32(txd_lower | buffer_info->length);
+- tx_desc->upper.data = cpu_to_le32(txd_upper);
+- if(unlikely(++i == tx_ring->count)) { i = 0; }
+- }
+- if(tx_desc != NULL) {
+- tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
+- }
+- /* Force memory writes to complete before letting h/w
+- * know there are new descriptors to fetch. (Only
+- * applicable for weak-ordered memory model archs,
+- * such as IA-64). */
+- wmb();
++ i = tx_ring->next_to_use;
+
+- tx_ring->next_to_use = i;
+- writel(i, adapter->hw.hw_addr + tx_ring->tdt);
++ while(count--) {
++ buffer_info = &tx_ring->buffer_info[i];
++ tx_desc = E1000_TX_DESC(*tx_ring, i);
++ tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
++ tx_desc->lower.data =
++ cpu_to_le32(txd_lower | buffer_info->length);
++ tx_desc->upper.data = cpu_to_le32(txd_upper);
++ if (unlikely(++i == tx_ring->count)) i = 0;
++ }
++
++ tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
++
++ /* Force memory writes to complete before letting h/w
++ * know there are new descriptors to fetch. (Only
++ * applicable for weak-ordered memory model archs,
++ * such as IA-64). */
++ wmb();
++
++ tx_ring->next_to_use = i;
++ writel(i, hw->hw_addr + tx_ring->tdt);
++ /* we need this if more than one processor can write to our tail
++ * at a time, it syncronizes IO on IA64/Altix systems */
++ mmiowb();
+ }
+
+ /**
+@@ -2950,113 +2925,132 @@ iegbe_tx_queue(struct iegbe_adapter *ada
+ * to the beginning of the Tx FIFO.
+ **/
+
+-static inline int
+-iegbe_82547_fifo_workaround(struct iegbe_adapter *adapter, struct sk_buff *skb)
++#define E1000_FIFO_HDR 0x10
++#define E1000_82547_PAD_LEN 0x3E0
++static int iegbe_82547_fifo_workaround(struct iegbe_adapter *adapter,
++ struct sk_buff *skb)
+ {
+- uint32_t fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
+- uint32_t skb_fifo_len = skb->len + E1000_FIFO_HDR;
++ u32 fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
++ u32 skb_fifo_len = skb->len + E1000_FIFO_HDR;
+
+- E1000_ROUNDUP(skb_fifo_len, E1000_FIFO_HDR);
++ skb_fifo_len = ALIGN(skb_fifo_len, E1000_FIFO_HDR);
+
+- if(adapter->link_duplex != HALF_DUPLEX) {
+- goto no_fifo_stall_required;
+- }
+- if(atomic_read(&adapter->tx_fifo_stall)) {
+- return 1;
++ if (adapter->link_duplex != HALF_DUPLEX)
++ goto no_fifo_stall_required;
++
++ if (atomic_read(&adapter->tx_fifo_stall))
++ return 1;
++
++ if(skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) {
++ atomic_set(&adapter->tx_fifo_stall, 1);
++ return 1;
+ }
+- if(skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) {
+- atomic_set(&adapter->tx_fifo_stall, 0x1);
+- return 1;
+- }
+
+ no_fifo_stall_required:
+- adapter->tx_fifo_head += skb_fifo_len;
+- if(adapter->tx_fifo_head >= adapter->tx_fifo_size) {
+- adapter->tx_fifo_head -= adapter->tx_fifo_size;
+- }
++ adapter->tx_fifo_head += skb_fifo_len;
++ if (adapter->tx_fifo_head >= adapter->tx_fifo_size)
++ adapter->tx_fifo_head -= adapter->tx_fifo_size;
+ return 0;
+ }
+
+-static inline int
+-iegbe_transfer_dhcp_info(struct iegbe_adapter *adapter, struct sk_buff *skb)
++#define MINIMUM_DHCP_PACKET_SIZE 282
++static int iegbe_transfer_dhcp_info(struct iegbe_adapter *adapter,
++ struct sk_buff *skb)
+ {
+ struct iegbe_hw *hw = &adapter->hw;
+- uint16_t length, offset;
+-#ifdef NETIF_F_HW_VLAN_TX
+- if(vlan_tx_tag_present(skb)) {
+- if(!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) &&
+- ( adapter->hw.mng_cookie.status &
+- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) ) {
++ u16 length, offset;
++ if (vlan_tx_tag_present(skb)) {
++ if (!((vlan_tx_tag_get(skb) == hw->mng_cookie.vlan_id) &&
++ ( hw->mng_cookie.status &
++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) )
+ return 0;
+ }
+- }
+-#endif
+- if(htons(ETH_P_IP) == skb->protocol) {
+- const struct iphdr *ip = skb->nh.iph;
+- if(IPPROTO_UDP == ip->protocol) {
+- struct udphdr *udp = (struct udphdr *)(skb->h.uh);
+- if(ntohs(udp->dest) == 0x43) { /* 0x43 = 67 */
+- offset = (uint8_t *)udp + 0x8 - skb->data;
+- length = skb->len - offset;
+-
+- return iegbe_mng_write_dhcp_info(hw,
+- (uint8_t *)udp + 0x8, length);
+- }
+- }
+- } else if((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) {
+- struct ethhdr *eth = (struct ethhdr *) skb->data;
+- if((htons(ETH_P_IP) == eth->h_proto)) {
++ if (skb->len > MINIMUM_DHCP_PACKET_SIZE) {
++ struct ethhdr *eth = (struct ethhdr *)skb->data;
++ if ((htons(ETH_P_IP) == eth->h_proto)) {
+ const struct iphdr *ip =
+- (struct iphdr *)((uint8_t *)skb->data+0xe);
+- if(IPPROTO_UDP == ip->protocol) {
++ (struct iphdr *)((u8 *)skb->data+14);
++ if (IPPROTO_UDP == ip->protocol) {
+ struct udphdr *udp =
+- (struct udphdr *)((uint8_t *)ip +
+- (ip->ihl << 0x2));
+- if(ntohs(udp->dest) == 0x43) {
+- offset = (uint8_t *)udp + 0x8 - skb->data;
++ (struct udphdr *)((u8 *)ip +
++ (ip->ihl << 2));
++ if (ntohs(udp->dest) == 67) {
++ offset = (u8 *)udp + 8 - skb->data;
+ length = skb->len - offset;
+
+ return iegbe_mng_write_dhcp_info(hw,
+- (uint8_t *)udp + 0x8,
++ (u8 *)udp + 8,
+ length);
+- }
++ }
+ }
+ }
+ }
+ return 0;
+ }
+
+-static int
+-iegbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
++static int __iegbe_maybe_stop_tx(struct net_device *netdev, int size)
++{
++ struct iegbe_adapter *adapter = netdev_priv(netdev);
++ struct iegbe_tx_ring *tx_ring = adapter->tx_ring;
++
++ netif_stop_queue(netdev);
++ /* Herbert's original patch had:
++ * smp_mb__after_netif_stop_queue();
++ * but since that doesn't exist yet, just open code it. */
++ smp_mb();
++
++ /* We need to check again in a case another CPU has just
++ * made room available. */
++ if (likely(E1000_DESC_UNUSED(tx_ring) < size))
++ return -EBUSY;
++
++ /* A reprieve! */
++ netif_start_queue(netdev);
++ ++adapter->restart_queue;
++ return 0;
++}
++
++static int iegbe_maybe_stop_tx(struct net_device *netdev,
++ struct iegbe_tx_ring *tx_ring, int size)
++{
++ if (likely(E1000_DESC_UNUSED(tx_ring) >= size))
++ return 0;
++ return __iegbe_maybe_stop_tx(netdev, size);
++}
++
++#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 )
++static int iegbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ {
+ struct iegbe_adapter *adapter = netdev_priv(netdev);
++ struct iegbe_hw *hw = &adapter->hw;
+ struct iegbe_tx_ring *tx_ring;
+ unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD;
+ unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
+ unsigned int tx_flags = 0;
+- unsigned int len = skb->len;
++ unsigned int len = skb->len - skb->data_len;
+ unsigned long flags = 0;
+- unsigned int nr_frags = 0;
+- unsigned int mss = 0;
++ unsigned int nr_frags;
++ unsigned int mss;
+ int count = 0;
+- int tso;
+-#ifdef MAX_SKB_FRAGS
++ int tso;
+ unsigned int f;
+- len -= skb->data_len;
+-#endif
+
+-#ifdef CONFIG_E1000_MQ
+- tx_ring = *per_cpu_ptr(adapter->cpu_tx_ring, smp_processor_id());
+-#else
++ /* This goes back to the question of how to logically map a tx queue
++ * to a flow. Right now, performance is impacted slightly negatively
++ * if using multiple tx queues. If the stack breaks away from a
++ * single qdisc implementation, we can look at this again. */
+ tx_ring = adapter->tx_ring;
+-#endif
+
+ if (unlikely(skb->len <= 0)) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+-#ifdef NETIF_F_TSO
++ /* 82571 and newer doesn't need the workaround that limited descriptor
++ * length to 4kB */
++ if (hw->mac_type >= iegbe_82571)
++ max_per_txd = 8192;
++
+ mss = skb_shinfo(skb)->gso_size;
+ /* The controller does a simple calculation to
+ * make sure there is enough room in the FIFO before
+@@ -3064,164 +3058,150 @@ iegbe_xmit_frame(struct sk_buff *skb, st
+ * 4 = ceil(buffer len/mss). To make sure we don't
+ * overrun the FIFO, adjust the max buffer len if mss
+ * drops. */
+- if(mss) {
+- max_per_txd = min(mss << 0x2, max_per_txd);
+- max_txd_pwr = fls(max_per_txd) - 0x1;
++ if (mss) {
++ u8 hdr_len;
++ max_per_txd = min(mss << 2, max_per_txd);
++ max_txd_pwr = fls(max_per_txd) - 1;
++
++ /* TSO Workaround for 82571/2/3 Controllers -- if skb->data
++ * points to just header, pull a few bytes of payload from
++ * frags into skb->data */
++ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
++ if (skb->data_len && hdr_len == len) {
++ switch (hw->mac_type) {
++ case iegbe_82544:
++ /* Make sure we have room to chop off 4 bytes,
++ * and that the end alignment will work out to
++ * this hardware's requirements
++ * NOTE: this is a TSO only workaround
++ * if end byte alignment not correct move us
++ * into the next dword */
++ break;
++ /* fall through */
++ case iegbe_82571:
++ case iegbe_82572:
++ case iegbe_82573:
++ break;
++ default:
++ /* do nothing */
++ break;
++ }
++ }
+ }
+
+- if((mss) || (skb->ip_summed == CHECKSUM_HW)) {
++ /* reserve a descriptor for the offload context */
++ if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL))
+ count++;
+- }
+ count++;
+-#else
+- if(skb->ip_summed == CHECKSUM_HW) {
++
++ /* Controller Erratum workaround */
++ if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb))
+ count++;
+- {
+-#endif
++
+ count += TXD_USE_COUNT(len, max_txd_pwr);
+
+- if(adapter->pcix_82544) {
++ if (adapter->pcix_82544)
+ count++;
+- }
++
+ /* work-around for errata 10 and it applies to all controllers
+ * in PCI-X mode, so add one more descriptor to the count
+ */
+- if(unlikely((adapter->hw.bus_type == iegbe_bus_type_pcix) &&
+- (len > 0x7df))) {
++ if (unlikely((hw->bus_type == iegbe_bus_type_pcix) &&
++ (len > 2015)))
+ count++;
+- }
+-#ifdef MAX_SKB_FRAGS
++
+ nr_frags = skb_shinfo(skb)->nr_frags;
+- for(f = 0; f < nr_frags; f++)
++ for (f = 0; f < nr_frags; f++)
+ count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size,
+ max_txd_pwr);
+- if(adapter->pcix_82544) {
++ if (adapter->pcix_82544)
+ count += nr_frags;
+- }
+-#ifdef NETIF_F_TSO
+- /* TSO Workaround for 82571/2 Controllers -- if skb->data
+- * points to just header, pull a few bytes of payload from
+- * frags into skb->data */
+- if (skb_is_gso(skb)) {
+- uint8_t hdr_len;
+- hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 0x2));
+- if (skb->data_len && (hdr_len < (skb->len - skb->data_len)) &&
+- (adapter->hw.mac_type == iegbe_82571 ||
+- adapter->hw.mac_type == iegbe_82572)) {
+- unsigned int pull_size;
+- pull_size = min((unsigned int)0x4, skb->data_len);
+- if (!__pskb_pull_tail(skb, pull_size)) {
+- printk(KERN_ERR "__pskb_pull_tail failed.\n");
+- dev_kfree_skb_any(skb);
+- return -EFAULT;
+- }
+- }
+- }
+-#endif
+-#endif
+
+- if(adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == iegbe_82573) ) {
++
++ if (hw->tx_pkt_filtering &&
++ (hw->mac_type == iegbe_82573))
+ iegbe_transfer_dhcp_info(adapter, skb);
+- }
+-#ifdef NETIF_F_LLTX
+- local_irq_save(flags);
+- if (!spin_trylock(&tx_ring->tx_lock)) {
++
++ if (!spin_trylock_irqsave(&tx_ring->tx_lock, flags))
+ /* Collision - tell upper layer to requeue */
+- local_irq_restore(flags);
+ return NETDEV_TX_LOCKED;
+- }
+-#else
+- spin_lock_irqsave(&tx_ring->tx_lock, flags);
+-#endif
+
+ /* need: count + 2 desc gap to keep tail from touching
+ * head, otherwise try next time */
+- if (unlikely(E1000_DESC_UNUSED(tx_ring) < count + 0x2)) {
+- netif_stop_queue(netdev);
++ if (unlikely(iegbe_maybe_stop_tx(netdev, tx_ring, count + 2))) {
+ spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
+ return NETDEV_TX_BUSY;
+ }
+
+- if(unlikely(adapter->hw.mac_type == iegbe_82547)) {
+- if(unlikely(iegbe_82547_fifo_workaround(adapter, skb))) {
++ if (unlikely(hw->mac_type == iegbe_82547)) {
++ if (unlikely(iegbe_82547_fifo_workaround(adapter, skb))) {
+ netif_stop_queue(netdev);
+- mod_timer(&adapter->tx_fifo_stall_timer, jiffies);
++ mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1);
+ spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
+ return NETDEV_TX_BUSY;
+ }
+ }
+
+-#ifndef NETIF_F_LLTX
+- spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
+-#endif
+-
+-#ifdef NETIF_F_HW_VLAN_TX
+- if(unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
++ if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
+ tx_flags |= E1000_TX_FLAGS_VLAN;
+ tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
+ }
+-#endif
+
+ first = tx_ring->next_to_use;
+
+ tso = iegbe_tso(adapter, tx_ring, skb);
+ if (tso < 0) {
+ dev_kfree_skb_any(skb);
+-#ifdef NETIF_F_LLTX
+ spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
+-#endif
+ return NETDEV_TX_OK;
+ }
+
+- if (likely(tso)) {
++ if (likely(tso)) {
++ tx_ring->last_tx_tso = 1;
+ tx_flags |= E1000_TX_FLAGS_TSO;
+- } else if (likely(iegbe_tx_csum(adapter, tx_ring, skb))) {
++ } else if (likely(iegbe_tx_csum(adapter, tx_ring, skb)))
+ tx_flags |= E1000_TX_FLAGS_CSUM;
+- }
++
+ /* Old method was to assume IPv4 packet by default if TSO was enabled.
+ * 82571 hardware supports TSO capabilities for IPv6 as well...
+ * no longer assume, we must. */
+- if (likely(skb->protocol == ntohs(ETH_P_IP))) {
++ if (likely(skb->protocol == htons(ETH_P_IP)))
+ tx_flags |= E1000_TX_FLAGS_IPV4;
+- }
++
+ iegbe_tx_queue(adapter, tx_ring, tx_flags,
+ iegbe_tx_map(adapter, tx_ring, skb, first,
+ max_per_txd, nr_frags, mss));
+
+ netdev->trans_start = jiffies;
+
+-#ifdef NETIF_F_LLTX
+ /* Make sure there is space in the ring for the next send. */
+- if (unlikely(E1000_DESC_UNUSED(tx_ring) < MAX_SKB_FRAGS + 0x2)) {
+- netif_stop_queue(netdev);
+- }
+- spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
+-#endif
++ iegbe_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2);
+
++ spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
+ return NETDEV_TX_OK;
+ }
+
++
+ /**
+ * iegbe_tx_timeout - Respond to a Tx Hang
+ * @netdev: network interface device structure
+ **/
+
+-static void
+-iegbe_tx_timeout(struct net_device *netdev)
++static void iegbe_tx_timeout(struct net_device *netdev)
+ {
+- struct iegbe_adapter *adapter = netdev_priv(netdev);
++ struct iegbe_adapter *adapter = netdev_priv(netdev);
+
+- /* Do the reset outside of interrupt context */
+- schedule_work(&adapter->tx_timeout_task);
++ /* Do the reset outside of interrupt context */
++ adapter->tx_timeout_count++;
++ schedule_work(&adapter->reset_task);
+ }
+
+-static void
+-iegbe_tx_timeout_task(struct net_device *netdev)
++static void iegbe_reset_task(struct work_struct *work)
+ {
+- struct iegbe_adapter *adapter = netdev_priv(netdev);
++ struct iegbe_adapter *adapter =
++ container_of(work, struct iegbe_adapter, reset_task);
+
+- iegbe_down(adapter);
+- iegbe_up(adapter);
++ iegbe_reinit_locked(adapter);
+ }
+
+ /**
+@@ -3232,13 +3212,12 @@ iegbe_tx_timeout_task(struct net_device
+ * The statistics are actually updated from the timer callback.
+ **/
+
+-static struct net_device_stats *
+-iegbe_get_stats(struct net_device *netdev)
++static struct net_device_stats *iegbe_get_stats(struct net_device *netdev)
+ {
+- struct iegbe_adapter *adapter = netdev_priv(netdev);
++ struct iegbe_adapter *adapter = netdev_priv(netdev);
+
+- iegbe_update_stats(adapter);
+- return &adapter->net_stats;
++ /* only return the current stats */
++ return &adapter->net_stats;
+ }
+
+ /**
+@@ -3249,67 +3228,55 @@ iegbe_get_stats(struct net_device *netde
+ * Returns 0 on success, negative on failure
+ **/
+
+-static int
+-iegbe_change_mtu(struct net_device *netdev, int new_mtu)
++static int iegbe_change_mtu(struct net_device *netdev, int new_mtu)
+ {
+- struct iegbe_adapter *adapter = netdev_priv(netdev);
+- int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
++ struct iegbe_adapter *adapter = netdev_priv(netdev);
++ struct iegbe_hw *hw = &adapter->hw;
++ int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
+
+- if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
+- (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+- DPRINTK(PROBE, ERR, "Invalid MTU setting\n");
+- return -EINVAL;
+- }
++ if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
++ (max_frame > MAX_JUMBO_FRAME_SIZE)) {
++ DPRINTK(PROBE, ERR, "Invalid MTU setting\n");
++ return -EINVAL;
++ }
+
++ /* Adapter-specific max frame size limits. */
++ switch (hw->mac_type) {
++ case iegbe_undefined ... iegbe_82542_rev2_1:
++ if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
++ DPRINTK(PROBE, ERR, "Jumbo Frames not supported.\n");
++ return -EINVAL;
++ }
++ break;
++ case iegbe_82571:
++ case iegbe_82572:
+ #define MAX_STD_JUMBO_FRAME_SIZE 9234
+- /* might want this to be bigger enum check... */
+- /* 82571 controllers limit jumbo frame size to 10500 bytes */
+- if ((adapter->hw.mac_type == iegbe_82571 ||
+- adapter->hw.mac_type == iegbe_82572) &&
+- max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
+- DPRINTK(PROBE, ERR, "MTU > 9216 bytes not supported "
+- "on 82571 and 82572 controllers.\n");
+- return -EINVAL;
+- }
+-
+- if(adapter->hw.mac_type == iegbe_82573 &&
+- max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
+- DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
+- "on 82573\n");
+- return -EINVAL;
+- }
+-
+- if(adapter->hw.mac_type > iegbe_82547_rev_2) {
+- adapter->rx_buffer_len = max_frame;
+- E1000_ROUNDUP(adapter->rx_buffer_len, 0x1024);
+- } else {
+- if(unlikely((adapter->hw.mac_type < iegbe_82543) &&
+- (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE))) {
+- DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
+- "on 82542\n");
+- return -EINVAL;
+-
+- } else {
+- if(max_frame <= E1000_RXBUFFER_2048) {
+- adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+- } else if(max_frame <= E1000_RXBUFFER_4096) {
+- adapter->rx_buffer_len = E1000_RXBUFFER_4096;
+- } else if(max_frame <= E1000_RXBUFFER_8192) {
+- adapter->rx_buffer_len = E1000_RXBUFFER_8192;
+- } else if(max_frame <= E1000_RXBUFFER_16384) {
+- adapter->rx_buffer_len = E1000_RXBUFFER_16384;
+- }
++ if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
++ DPRINTK(PROBE, ERR, "MTU > 9216 not supported.\n");
++ return -EINVAL;
+ }
++ break;
++ default:
++ break;
+ }
++ if (max_frame <= E1000_RXBUFFER_256)
++ adapter->rx_buffer_len = E1000_RXBUFFER_256;
++ else if (max_frame <= E1000_RXBUFFER_2048)
++ adapter->rx_buffer_len = E1000_RXBUFFER_2048;
++ else if (max_frame <= E1000_RXBUFFER_4096)
++ adapter->rx_buffer_len = E1000_RXBUFFER_4096;
++ else if (max_frame <= E1000_RXBUFFER_8192)
++ adapter->rx_buffer_len = E1000_RXBUFFER_8192;
++ else if (max_frame <= E1000_RXBUFFER_16384)
++ adapter->rx_buffer_len = E1000_RXBUFFER_16384;
+
+- netdev->mtu = new_mtu;
++ /* adjust allocation if LPE protects us, and we aren't using SBP */
+
+- if(netif_running(netdev)) {
+- iegbe_down(adapter);
+- iegbe_up(adapter);
+- }
++ netdev->mtu = new_mtu;
++ hw->max_frame_size = max_frame;
+
+- adapter->hw.max_frame_size = max_frame;
++ if (netif_running(netdev))
++ iegbe_reinit_locked(adapter);
+
+ return 0;
+ }
+@@ -3319,224 +3286,189 @@ iegbe_change_mtu(struct net_device *netd
+ * @adapter: board private structure
+ **/
+
+-void
+-iegbe_update_stats(struct iegbe_adapter *adapter)
++void iegbe_update_stats(struct iegbe_adapter *adapter)
+ {
+- struct iegbe_hw *hw = &adapter->hw;
+- unsigned long flags = 0;
+- uint16_t phy_tmp;
++ struct iegbe_hw *hw = &adapter->hw;
++ unsigned long flags = 0x0;
++ uint16_t phy_tmp;
+
+ #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
+
+- spin_lock_irqsave(&adapter->stats_lock, flags);
++ spin_lock_irqsave(&adapter->stats_lock, flags);
+
+- /* these counters are modified from iegbe_adjust_tbi_stats,
+- * called from the interrupt context, so they must only
+- * be written while holding adapter->stats_lock
+- */
++ /* these counters are modified from iegbe_adjust_tbi_stats,
++ * called from the interrupt context, so they must only
++ * be written while holding adapter->stats_lock
++ */
+
+- adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS);
+- adapter->stats.gprc += E1000_READ_REG(hw, GPRC);
+- adapter->stats.gorcl += E1000_READ_REG(hw, GORCL);
+- adapter->stats.gorch += E1000_READ_REG(hw, GORCH);
+- adapter->stats.bprc += E1000_READ_REG(hw, BPRC);
+- adapter->stats.mprc += E1000_READ_REG(hw, MPRC);
+- adapter->stats.roc += E1000_READ_REG(hw, ROC);
+- adapter->stats.prc64 += E1000_READ_REG(hw, PRC64);
+- adapter->stats.prc127 += E1000_READ_REG(hw, PRC127);
+- adapter->stats.prc255 += E1000_READ_REG(hw, PRC255);
+- adapter->stats.prc511 += E1000_READ_REG(hw, PRC511);
+- adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023);
+- adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522);
+-
+- adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS);
+- adapter->stats.mpc += E1000_READ_REG(hw, MPC);
+- adapter->stats.scc += E1000_READ_REG(hw, SCC);
+- adapter->stats.ecol += E1000_READ_REG(hw, ECOL);
+- adapter->stats.mcc += E1000_READ_REG(hw, MCC);
+- adapter->stats.latecol += E1000_READ_REG(hw, LATECOL);
+- adapter->stats.dc += E1000_READ_REG(hw, DC);
+- adapter->stats.sec += E1000_READ_REG(hw, SEC);
+- adapter->stats.rlec += E1000_READ_REG(hw, RLEC);
+- adapter->stats.xonrxc += E1000_READ_REG(hw, XONRXC);
+- adapter->stats.xontxc += E1000_READ_REG(hw, XONTXC);
+- adapter->stats.xoffrxc += E1000_READ_REG(hw, XOFFRXC);
+- adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC);
+- adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC);
+- adapter->stats.gptc += E1000_READ_REG(hw, GPTC);
+- adapter->stats.gotcl += E1000_READ_REG(hw, GOTCL);
+- adapter->stats.gotch += E1000_READ_REG(hw, GOTCH);
+- adapter->stats.rnbc += E1000_READ_REG(hw, RNBC);
+- adapter->stats.ruc += E1000_READ_REG(hw, RUC);
+- adapter->stats.rfc += E1000_READ_REG(hw, RFC);
+- adapter->stats.rjc += E1000_READ_REG(hw, RJC);
+- adapter->stats.torl += E1000_READ_REG(hw, TORL);
+- adapter->stats.torh += E1000_READ_REG(hw, TORH);
+- adapter->stats.totl += E1000_READ_REG(hw, TOTL);
+- adapter->stats.toth += E1000_READ_REG(hw, TOTH);
+- adapter->stats.tpr += E1000_READ_REG(hw, TPR);
+- adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64);
+- adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127);
+- adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255);
+- adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511);
+- adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023);
+- adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522);
+- adapter->stats.mptc += E1000_READ_REG(hw, MPTC);
+- adapter->stats.bptc += E1000_READ_REG(hw, BPTC);
+-
+- /* used for adaptive IFS */
+-
+- hw->tx_packet_delta = E1000_READ_REG(hw, TPT);
+- adapter->stats.tpt += hw->tx_packet_delta;
+- hw->collision_delta = E1000_READ_REG(hw, COLC);
+- adapter->stats.colc += hw->collision_delta;
+-
+- if(hw->mac_type >= iegbe_82543) {
+- adapter->stats.algnerrc += E1000_READ_REG(hw, ALGNERRC);
+- adapter->stats.rxerrc += E1000_READ_REG(hw, RXERRC);
+- adapter->stats.tncrs += E1000_READ_REG(hw, TNCRS);
+- adapter->stats.cexterr += E1000_READ_REG(hw, CEXTERR);
+- adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC);
+- adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC);
+- }
+- if(hw->mac_type > iegbe_82547_rev_2) {
+- adapter->stats.iac += E1000_READ_REG(hw, IAC);
+- adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC);
+- adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC);
+- adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC);
+- adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC);
+- adapter->stats.ictxatc += E1000_READ_REG(hw, ICTXATC);
+- adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC);
+- adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC);
+- adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC);
+- }
+-
+- /* Fill out the OS statistics structure */
+-
+- adapter->net_stats.rx_packets = adapter->stats.gprc;
+- adapter->net_stats.tx_packets = adapter->stats.gptc;
+- adapter->net_stats.rx_bytes = adapter->stats.gorcl;
+- adapter->net_stats.tx_bytes = adapter->stats.gotcl;
+- adapter->net_stats.multicast = adapter->stats.mprc;
+- adapter->net_stats.collisions = adapter->stats.colc;
+-
+- /* Rx Errors */
+-
+- adapter->net_stats.rx_errors = adapter->stats.rxerrc +
+- adapter->stats.crcerrs + adapter->stats.algnerrc +
+- adapter->stats.rlec + adapter->stats.mpc +
+- adapter->stats.cexterr;
+- adapter->net_stats.rx_dropped = adapter->stats.mpc;
+- adapter->net_stats.rx_length_errors = adapter->stats.rlec;
+- adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
+- adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc;
+- adapter->net_stats.rx_fifo_errors = adapter->stats.mpc;
+- adapter->net_stats.rx_missed_errors = adapter->stats.mpc;
+-
+- /* Tx Errors */
+-
+- adapter->net_stats.tx_errors = adapter->stats.ecol +
+- adapter->stats.latecol;
+- adapter->net_stats.tx_aborted_errors = adapter->stats.ecol;
+- adapter->net_stats.tx_window_errors = adapter->stats.latecol;
+- adapter->net_stats.tx_carrier_errors = adapter->stats.tncrs;
++ adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS);
++ adapter->stats.gprc += E1000_READ_REG(hw, GPRC);
++ adapter->stats.gorcl += E1000_READ_REG(hw, GORCL);
++ adapter->stats.gorch += E1000_READ_REG(hw, GORCH);
++ adapter->stats.bprc += E1000_READ_REG(hw, BPRC);
++ adapter->stats.mprc += E1000_READ_REG(hw, MPRC);
++ adapter->stats.roc += E1000_READ_REG(hw, ROC);
++ adapter->stats.prc64 += E1000_READ_REG(hw, PRC64);
++ adapter->stats.prc127 += E1000_READ_REG(hw, PRC127);
++ adapter->stats.prc255 += E1000_READ_REG(hw, PRC255);
++ adapter->stats.prc511 += E1000_READ_REG(hw, PRC511);
++ adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023);
++ adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522);
++
++ adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS);
++ adapter->stats.mpc += E1000_READ_REG(hw, MPC);
++ adapter->stats.scc += E1000_READ_REG(hw, SCC);
++ adapter->stats.ecol += E1000_READ_REG(hw, ECOL);
++ adapter->stats.mcc += E1000_READ_REG(hw, MCC);
++ adapter->stats.latecol += E1000_READ_REG(hw, LATECOL);
++ adapter->stats.dc += E1000_READ_REG(hw, DC);
++ adapter->stats.sec += E1000_READ_REG(hw, SEC);
++ adapter->stats.rlec += E1000_READ_REG(hw, RLEC);
++ adapter->stats.xonrxc += E1000_READ_REG(hw, XONRXC);
++ adapter->stats.xontxc += E1000_READ_REG(hw, XONTXC);
++ adapter->stats.xoffrxc += E1000_READ_REG(hw, XOFFRXC);
++ adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC);
++ adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC);
++ adapter->stats.gptc += E1000_READ_REG(hw, GPTC);
++ adapter->stats.gotcl += E1000_READ_REG(hw, GOTCL);
++ adapter->stats.gotch += E1000_READ_REG(hw, GOTCH);
++ adapter->stats.rnbc += E1000_READ_REG(hw, RNBC);
++ adapter->stats.ruc += E1000_READ_REG(hw, RUC);
++ adapter->stats.rfc += E1000_READ_REG(hw, RFC);
++ adapter->stats.rjc += E1000_READ_REG(hw, RJC);
++ adapter->stats.torl += E1000_READ_REG(hw, TORL);
++ adapter->stats.torh += E1000_READ_REG(hw, TORH);
++ adapter->stats.totl += E1000_READ_REG(hw, TOTL);
++ adapter->stats.toth += E1000_READ_REG(hw, TOTH);
++ adapter->stats.tpr += E1000_READ_REG(hw, TPR);
++ adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64);
++ adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127);
++ adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255);
++ adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511);
++ adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023);
++ adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522);
++ adapter->stats.mptc += E1000_READ_REG(hw, MPTC);
++ adapter->stats.bptc += E1000_READ_REG(hw, BPTC);
++
++ /* used for adaptive IFS */
++
++ hw->tx_packet_delta = E1000_READ_REG(hw, TPT);
++ adapter->stats.tpt += hw->tx_packet_delta;
++ hw->collision_delta = E1000_READ_REG(hw, COLC);
++ adapter->stats.colc += hw->collision_delta;
++
++ if(hw->mac_type >= iegbe_82543) {
++ adapter->stats.algnerrc += E1000_READ_REG(hw, ALGNERRC);
++ adapter->stats.rxerrc += E1000_READ_REG(hw, RXERRC);
++ adapter->stats.tncrs += E1000_READ_REG(hw, TNCRS);
++ adapter->stats.cexterr += E1000_READ_REG(hw, CEXTERR);
++ adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC);
++ adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC);
++ }
++ if(hw->mac_type > iegbe_82547_rev_2) {
++ adapter->stats.iac += E1000_READ_REG(hw, IAC);
++ adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC);
++ adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC);
++ adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC);
++ adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC);
++ adapter->stats.ictxatc += E1000_READ_REG(hw, ICTXATC);
++ adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC);
++ adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC);
++ adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC);
++ }
++
++ /* Fill out the OS statistics structure */
++
++ adapter->net_stats.rx_packets = adapter->stats.gprc;
++ adapter->net_stats.tx_packets = adapter->stats.gptc;
++ adapter->net_stats.rx_bytes = adapter->stats.gorcl;
++ adapter->net_stats.tx_bytes = adapter->stats.gotcl;
++ adapter->net_stats.multicast = adapter->stats.mprc;
++ adapter->net_stats.collisions = adapter->stats.colc;
++
++ /* Rx Errors */
++
++ adapter->net_stats.rx_errors = adapter->stats.rxerrc +
++ adapter->stats.crcerrs + adapter->stats.algnerrc +
++ adapter->stats.rlec + adapter->stats.mpc +
++ adapter->stats.cexterr;
++ adapter->net_stats.rx_dropped = adapter->stats.mpc;
++ adapter->net_stats.rx_length_errors = adapter->stats.rlec;
++ adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
++ adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc;
++ adapter->net_stats.rx_fifo_errors = adapter->stats.mpc;
++ adapter->net_stats.rx_missed_errors = adapter->stats.mpc;
++
++ /* Tx Errors */
++
++ adapter->net_stats.tx_errors = adapter->stats.ecol +
++ adapter->stats.latecol;
++ adapter->net_stats.tx_aborted_errors = adapter->stats.ecol;
++ adapter->net_stats.tx_window_errors = adapter->stats.latecol;
++ adapter->net_stats.tx_carrier_errors = adapter->stats.tncrs;
+
+- /* Tx Dropped needs to be maintained elsewhere */
++ /* Tx Dropped needs to be maintained elsewhere */
+
+- /* Phy Stats */
++ /* Phy Stats */
+
+- if(hw->media_type == iegbe_media_type_copper
++ if(hw->media_type == iegbe_media_type_copper
+ || (hw->media_type == iegbe_media_type_oem
+ && iegbe_oem_phy_is_copper(&adapter->hw))) {
+- if((adapter->link_speed == SPEED_1000) &&
+- (!iegbe_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) {
+- phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
+- adapter->phy_stats.idle_errors += phy_tmp;
+- }
++ if((adapter->link_speed == SPEED_1000) &&
++ (!iegbe_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) {
++ phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
++ adapter->phy_stats.idle_errors += phy_tmp;
++ }
+
+- if((hw->mac_type <= iegbe_82546) &&
+- (hw->phy_type == iegbe_phy_m88) &&
++ if((hw->mac_type <= iegbe_82546) &&
++ (hw->phy_type == iegbe_phy_m88) &&
+ !iegbe_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp)) {
+- adapter->phy_stats.receive_errors += phy_tmp;
+- }
++ adapter->phy_stats.receive_errors += phy_tmp;
++ }
+ }
+
+- spin_unlock_irqrestore(&adapter->stats_lock, flags);
++ spin_unlock_irqrestore(&adapter->stats_lock, flags);
+ }
+
+-#ifdef CONFIG_E1000_MQ
+-void
+-iegbe_rx_schedule(void *data)
++/**
++ * iegbe_intr_msi - Interrupt Handler
++ * @irq: interrupt number
++ * @data: pointer to a network interface device structure
++ **/
++
++static irqreturn_t iegbe_intr_msi(int irq, void *data)
+ {
+- struct net_device *poll_dev, *netdev = data;
+- struct iegbe_adapter *adapter = netdev->priv;
+- int this_cpu = get_cpu();
+-
+- poll_dev = *per_cpu_ptr(adapter->cpu_netdev, this_cpu);
+- if (poll_dev == NULL) {
+- put_cpu();
+- return;
++ struct net_device *netdev = data;
++ struct iegbe_adapter *adapter = netdev_priv(netdev);
++ struct iegbe_hw *hw = &adapter->hw;
++ u32 icr = E1000_READ_REG(&adapter->hw, ICR);
++ if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
++ hw->get_link_status = 1;
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
++ mod_timer(&adapter->watchdog_timer, jiffies + 1);
+ }
+
+- if (likely(netif_rx_schedule_prep(poll_dev))) {
+- __netif_rx_schedule(poll_dev);
+- } else {
+- iegbe_irq_enable(adapter);
+- }
+- put_cpu();
+-}
+-#endif
+-
+-#ifdef IEGBE_GBE_WORKAROUND
+-/*
+- * Check for tx hang condition. This is the condition where a
+- * decsriptor is in the hardware and hasn't been processed for a
+- * while. This code is similar to the check in iegbe_clean_rx_irq()
+- */
+-static void
+-iegbe_tx_hang_check(struct iegbe_adapter *adapter,
+- struct iegbe_tx_ring *tx_ring)
+-{
+- struct net_device *netdev = adapter->netdev;
+- unsigned int i;
++ if(unlikely(icr & (E1000_ICR_RX_DESC_FIFO_PAR
++ | E1000_ICR_TX_DESC_FIFO_PAR
++ | E1000_ICR_PB
++ | E1000_ICR_CPP_TARGET
++ | E1000_ICR_CPP_MASTER ))) {
+
+- /* Check for a hang condition using the buffer currently at the Tx
+- head pointer */
+- i = readl(adapter->hw.hw_addr + tx_ring->tdh);
+-
+- if (adapter->detect_tx_hung) {
+- /* Detect a transmit hang in hardware, this serializes the
+- * check with the clearing of time_stamp and movement of i */
+- adapter->detect_tx_hung = FALSE;
+-
+- if (tx_ring->buffer_info[i].dma &&
+- time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ)
+- && !(E1000_READ_REG(&adapter->hw, STATUS) &
+- E1000_STATUS_TXOFF)) {
+-
+- /* detected Tx unit hang */
+- DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n"
+- " TDH <%x>\n"
+- " TDT <%x>\n"
+- " next_to_use <%x>\n"
+- " next_to_clean <%x>\n"
+- "buffer_info[tdh]\n"
+- " dma <%zx>\n"
+- " time_stamp <%lx>\n"
+- " jiffies <%lx>\n",
+- readl(adapter->hw.hw_addr + tx_ring->tdh),
+- readl(adapter->hw.hw_addr + tx_ring->tdt),
+- tx_ring->next_to_use,
+- tx_ring->next_to_clean,
+- (size_t)tx_ring->buffer_info[i].dma,
+- tx_ring->buffer_info[i].time_stamp,
+- jiffies);
+- netif_stop_queue(netdev);
+- }
++ iegbe_irq_disable(adapter);
++ printk("Critical error! ICR = 0x%x\n", icr);
++ return IRQ_HANDLED;
+ }
+-}
++ if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) {
++ adapter->total_tx_bytes = 0;
++ adapter->total_tx_packets = 0;
++ adapter->total_rx_bytes = 0;
++ adapter->total_rx_packets = 0;
++ __netif_rx_schedule(netdev, &adapter->napi);
++ } else
++ iegbe_irq_enable(adapter);
+
+-#endif
++ return IRQ_HANDLED;
++}
+
+ /**
+ * iegbe_intr - Interrupt Handler
+@@ -3546,364 +3478,208 @@ iegbe_tx_hang_check(struct iegbe_adapter
+ **/
+
+ static irqreturn_t
+-iegbe_intr(int irq, void *data, struct pt_regs *regs)
++iegbe_intr(int irq, void *data)
+ {
+- struct net_device *netdev = data;
+- struct iegbe_adapter *adapter = netdev_priv(netdev);
+- struct iegbe_hw *hw = &adapter->hw;
+- uint32_t rctl, tctl;
+- uint32_t icr = E1000_READ_REG(hw, ICR);
+-#ifndef CONFIG_E1000_NAPI
+- uint32_t i;
+-#ifdef IEGBE_GBE_WORKAROUND
+- int rx_cleaned;
+-#endif
+-#endif
++ struct net_device *netdev = data;
++ struct iegbe_adapter *adapter = netdev_priv(netdev);
++ struct iegbe_hw *hw = &adapter->hw;
++ u32 icr = E1000_READ_REG(&adapter->hw, ICR);
+
+- if(unlikely(!icr)) {
++ if (unlikely(!icr))
+ return IRQ_NONE; /* Not our interrupt */
+- }
++
++ /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
++ * not set, then the adapter didn't send an interrupt */
++ if (unlikely(hw->mac_type >= iegbe_82571 &&
++ !(icr & E1000_ICR_INT_ASSERTED)))
++ return IRQ_NONE;
++
++
+ if(unlikely(icr & (E1000_ICR_RX_DESC_FIFO_PAR
+- | E1000_ICR_TX_DESC_FIFO_PAR
+- | E1000_ICR_PB
+- | E1000_ICR_CPP_TARGET
+- | E1000_ICR_CPP_MASTER ))) {
++ | E1000_ICR_TX_DESC_FIFO_PAR
++ | E1000_ICR_PB
++ | E1000_ICR_CPP_TARGET
++ | E1000_ICR_CPP_MASTER ))) {
+
+ iegbe_irq_disable(adapter);
+- tctl = E1000_READ_REG(&adapter->hw, TCTL);
+- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+- E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_TCTL_EN);
+- E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN);
+-
+- tasklet_data = (unsigned long) (icr + adapter->bd_number);
+- tasklet_schedule(&iegbe_reset_tasklet);
+-
+- return IRQ_HANDLED;
+- }
+-
+-#ifdef CONFIG_E1000_NAPI
+- atomic_inc(&adapter->irq_sem);
+-#ifdef IEGBE_GBE_WORKAROUND
+- /* Ensure that the TXQE interrupt is enabled in NAPI mode */
+- E1000_WRITE_REG(hw, IMC, ~E1000_IMS_TXQE);
+-#else
+- E1000_WRITE_REG(hw, IMC, ~0);
+-#endif
+- E1000_WRITE_FLUSH(hw);
+-#ifdef CONFIG_E1000_MQ
+- if (atomic_read(&adapter->rx_sched_call_data.count) == 0) {
+- cpu_set(adapter->cpu_for_queue[0],
+- adapter->rx_sched_call_data.cpumask);
+- for (i = 1; i < adapter->num_queues; i++) {
+- cpu_set(adapter->cpu_for_queue[i],
+- adapter->rx_sched_call_data.cpumask);
+- atomic_inc(&adapter->irq_sem);
+- }
+- atomic_set(&adapter->rx_sched_call_data.count, i);
+- smp_call_async_mask(&adapter->rx_sched_call_data);
+- } else {
+- DEBUGOUT("call_data.count == %u\n",
+- atomic_read(&adapter->rx_sched_call_data.count));
++ printk("Critical error! ICR = 0x%x\n", icr);
++ return IRQ_HANDLED;
+ }
+-#else
+- if (likely(netif_rx_schedule_prep(&adapter->polling_netdev[0]))) {
+- __netif_rx_schedule(&adapter->polling_netdev[0]);
+- } else {
+- iegbe_irq_enable(adapter);
+- }
+-#endif
+-
+-#ifdef IEGBE_GBE_WORKAROUND
+- /* Clean the Tx ring */
+- for (i = 0; i < E1000_MAX_INTR; i++) {
+- adapter->stats.rx_next_to_clean = adapter->rx_ring->next_to_clean;
+- adapter->stats.rx_next_to_use = adapter->rx_ring->next_to_use;
+-
+- adapter->stats.tx_next_to_clean = adapter->tx_ring->next_to_clean;
+- adapter->stats.tx_next_to_use = adapter->tx_ring->next_to_use;
+-
+- /* Only clean Tx descriptors for a TXQE interrupt */
+- if(icr & E1000_ICR_TXQE) {
+- adapter->stats.txqec++;
+- iegbe_clean_tx_ring_partial(adapter, adapter->tx_ring);
+- }
+- else {
+- iegbe_tx_hang_check(adapter, adapter->tx_ring);
+- }
+- }
+
+-#endif /*IEGBE_GBE_WORKAROUND */
+-
+-#else
+- /* Writing IMC and IMS is needed for 82547.
+- * Due to Hub Link bus being occupied, an interrupt
+- * de-assertion message is not able to be sent.
+- * When an interrupt assertion message is generated later,
+- * two messages are re-ordered and sent out.
+- * That causes APIC to think 82547 is in de-assertion
+- * state, while 82547 is in assertion state, resulting
+- * in dead lock. Writing IMC forces 82547 into
+- * de-assertion state.
+- */
+- if (hw->mac_type == iegbe_82547 || hw->mac_type == iegbe_82547_rev_2) {
+- atomic_inc(&adapter->irq_sem);
+- E1000_WRITE_REG(hw, IMC, ~0);
+- }
+-
+-#ifdef IEGBE_GBE_WORKAROUND
+-
+- for (i = 0; i < E1000_MAX_INTR; i++) {
+- rx_cleaned = adapter->clean_rx(adapter, adapter->rx_ring);
+- adapter->stats.rx_next_to_clean = adapter->rx_ring->next_to_clean;
+- adapter->stats.rx_next_to_use = adapter->rx_ring->next_to_use;
+-
+- adapter->stats.tx_next_to_clean = adapter->tx_ring->next_to_clean;
+- adapter->stats.tx_next_to_use = adapter->tx_ring->next_to_use;
+-
+- /* Only clean Tx descriptors for a TXQE interrupt */
+- if(icr & E1000_ICR_TXQE) {
+- adapter->stats.txqec++;
+- iegbe_clean_tx_ring_partial(adapter, adapter->tx_ring);
+- }
+- else {
+- iegbe_tx_hang_check(adapter, adapter->tx_ring);
+- }
+- if(!rx_cleaned) {
+- break;
+- }
++ /* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No
++ * need for the IMC write */
++ if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
++ hw->get_link_status = 1;
++ /* guard against interrupt when we're going down */
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
++ mod_timer(&adapter->watchdog_timer, jiffies + 1);
++
+ }
+
+-#else
+- for (i = 0; i < E1000_MAX_INTR; i++)
+- if(unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
+- !iegbe_clean_tx_irq(adapter, adapter->tx_ring))) {
+- break;
+- }
+-#endif
+-
+- if (hw->mac_type == iegbe_82547 || hw->mac_type == iegbe_82547_rev_2) {
+- iegbe_irq_enable(adapter);
+- }
+-#endif
+-#ifdef E1000_COUNT_ICR
+- adapter->icr_txdw += icr & 0x01UL;
+- icr >>= 0x1;
+- adapter->icr_txqe += icr & 0x01UL;
+- icr >>= 0x1;
+- adapter->icr_lsc += icr & 0x01UL;
+- icr >>= 0x1;
+- adapter->icr_rxseq += icr & 0x01UL;
+- icr >>= 0x1;
+- adapter->icr_rxdmt += icr & 0x01UL;
+- icr >>= 0x1;
+- adapter->icr_rxo += icr & 0x01UL;
+- icr >>= 0x1;
+- adapter->icr_rxt += icr & 0x01UL;
+- if(hw->mac_type != iegbe_icp_xxxx) {
+- icr >>= 0x2;
+- adapter->icr_mdac += icr & 0x01UL;
+- icr >>= 0x1;
+- adapter->icr_rxcfg += icr & 0x01UL;
+- icr >>= 0x1;
+- adapter->icr_gpi += icr & 0x01UL;
+- } else {
+- icr >>= 0x4;
+- }
+- if(hw->mac_type == iegbe_icp_xxxx) {
+- icr >>= 0xc;
+- adapter->icr_pb += icr & 0x01UL;
+- icr >>= 0x3;
+- adapter->icr_intmem_icp_xxxx += icr & 0x01UL;
+- icr >>= 0x1;
+- adapter->icr_cpp_target += icr & 0x01UL;
+- icr >>= 0x1;
+- adapter->icr_cpp_master += icr & 0x01UL;
+- icr >>= 0x1;
+- adapter->icr_stat += icr & 0x01UL;
++ if (unlikely(hw->mac_type < iegbe_82571)) {
++ E1000_WRITE_REG(&adapter->hw, IMC, ~0);
++ E1000_WRITE_FLUSH(&adapter->hw);
+ }
+-#endif
++ if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) {
++ adapter->total_tx_bytes = 0;
++ adapter->total_tx_packets = 0;
++ adapter->total_rx_bytes = 0;
++ adapter->total_rx_packets = 0;
++ __netif_rx_schedule(netdev, &adapter->napi);
++ } else
++ /* this really should not happen! if it does it is basically a
++ * bug, but not a hard error, so enable ints and continue */
++ iegbe_irq_enable(adapter);
+
+ return IRQ_HANDLED;
+ }
+
+-#ifdef CONFIG_E1000_NAPI
+ /**
+ * iegbe_clean - NAPI Rx polling callback
+ * @adapter: board private structure
+ **/
+-
+-static int
+-iegbe_clean(struct net_device *poll_dev, int *budget)
++static int iegbe_clean(struct napi_struct *napi, int budget)
+ {
+- struct iegbe_adapter *adapter;
+- int work_to_do = min(*budget, poll_dev->quota);
+- int tx_cleaned, i = 0, work_done = 0;
++ struct iegbe_adapter *adapter = container_of(napi, struct iegbe_adapter, napi);
++ struct net_device *poll_dev = adapter->netdev;
++ int tx_cleaned = 0, work_done = 0;
+
+ /* Must NOT use netdev_priv macro here. */
+ adapter = poll_dev->priv;
+
+- /* Keep link state information with original netdev */
+- if (!netif_carrier_ok(adapter->netdev)) {
+- goto quit_polling;
+- }
+- while (poll_dev != &adapter->polling_netdev[i]) {
+- i++;
+- if (unlikely(i == adapter->num_queues)) {
+- BUG();
+- }
+- }
+-
+-#ifdef IEGBE_GBE_WORKAROUND
+- /* Tx descriptors are cleaned in iegbe_intr(). No need to clean
+- them here */
+- tx_cleaned = FALSE;
+-#else
+- tx_cleaned = iegbe_clean_tx_irq(adapter, &adapter->tx_ring[i]);
+-#endif
+- adapter->clean_rx(adapter, &adapter->rx_ring[i],
+- &work_done, work_to_do);
+-
+- *budget -= work_done;
+- poll_dev->quota -= work_done;
+-
+- /* If no Tx and not enough Rx work done, exit the polling mode */
+- if((!tx_cleaned && (work_done == 0)) ||
+- !netif_running(adapter->netdev)) {
+-quit_polling:
+- netif_rx_complete(poll_dev);
++ /* iegbe_clean is called per-cpu. This lock protects
++ * tx_ring[0] from being cleaned by multiple cpus
++ * simultaneously. A failure obtaining the lock means
++ * tx_ring[0] is currently being cleaned anyway. */
++ if (spin_trylock(&adapter->tx_queue_lock)) {
++ tx_cleaned = iegbe_clean_tx_irq(adapter,
++ &adapter->tx_ring[0]);
++ spin_unlock(&adapter->tx_queue_lock);
++ }
++
++ adapter->clean_rx(adapter, &adapter->rx_ring[0],
++ &work_done, budget);
++
++ if (tx_cleaned)
++ work_done = budget;
++
++ /* If budget not fully consumed, exit the polling mode */
++ if (work_done < budget) {
++ if (likely(adapter->itr_setting & 3))
++ iegbe_set_itr(adapter);
++ netif_rx_complete(poll_dev, napi);
+ iegbe_irq_enable(adapter);
+- return 0;
+ }
+
+- return 1;
++ return work_done;
+ }
+
+-#endif
+-
+-
+-#ifndef IEGBE_GBE_WORKAROUND
+ /**
+ * iegbe_clean_tx_irq - Reclaim resources after transmit completes
+ * @adapter: board private structure
+ **/
+-
+-static boolean_t
+-iegbe_clean_tx_irq(struct iegbe_adapter *adapter,
++static bool iegbe_clean_tx_irq(struct iegbe_adapter *adapter,
+ struct iegbe_tx_ring *tx_ring)
+ {
+- struct net_device *netdev = adapter->netdev;
+- struct iegbe_tx_desc *tx_desc, *eop_desc;
+- struct iegbe_buffer *buffer_info;
+- unsigned int i, eop;
+- boolean_t cleaned = FALSE;
++ struct iegbe_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ struct iegbe_tx_desc *tx_desc, *eop_desc;
++ struct iegbe_buffer *buffer_info;
++ unsigned int i, eop;
++ unsigned int count = 0;
++ bool cleaned = false;
++ unsigned int total_tx_bytes=0, total_tx_packets=0;
+
+- i = tx_ring->next_to_clean;
+- eop = tx_ring->buffer_info[i].next_to_watch;
+- eop_desc = E1000_TX_DESC(*tx_ring, eop);
++ i = tx_ring->next_to_clean;
++ eop = tx_ring->buffer_info[i].next_to_watch;
++ eop_desc = E1000_TX_DESC(*tx_ring, eop);
+
+ while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
+- /* Premature writeback of Tx descriptors clear (free buffers
+- * and unmap pci_mapping) previous_buffer_info */
+- if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
+- iegbe_unmap_and_free_tx_resource(adapter,
+- &tx_ring->previous_buffer_info);
+- }
+-
+- for (cleaned = FALSE; !cleaned; ) {
+- tx_desc = E1000_TX_DESC(*tx_ring, i);
+- buffer_info = &tx_ring->buffer_info[i];
+- cleaned = (i == eop);
+-
+-#ifdef NETIF_F_TSO
+- if (!(netdev->features & NETIF_F_TSO)) {
+-#endif
+- iegbe_unmap_and_free_tx_resource(adapter,
+- buffer_info);
+-#ifdef NETIF_F_TSO
+- } else {
+- if (cleaned) {
+- memcpy(&tx_ring->previous_buffer_info,
+- buffer_info,
+- sizeof(struct iegbe_buffer));
+- memset(buffer_info, 0,
+- sizeof(struct iegbe_buffer));
+- } else {
+- iegbe_unmap_and_free_tx_resource(
+- adapter, buffer_info);
+- }
+- }
+-#endif
+-
+- tx_desc->buffer_addr = 0;
+- tx_desc->lower.data = 0;
++ for (cleaned = false; !cleaned; ) {
++ tx_desc = E1000_TX_DESC(*tx_ring, i);
++ buffer_info = &tx_ring->buffer_info[i];
++ cleaned = (i == eop);
++
++ if (cleaned) {
++ struct sk_buff *skb = buffer_info->skb;
++ unsigned int segs = 0, bytecount;
++ segs = skb_shinfo(skb)->gso_segs ?: 1;
++ bytecount = ((segs - 1) * skb_headlen(skb)) +
++ skb->len;
++ total_tx_packets += segs;
++ total_tx_bytes += bytecount;
++ }
++ iegbe_unmap_and_free_tx_resource(adapter, buffer_info);
+ tx_desc->upper.data = 0;
+
+- if (unlikely(++i == tx_ring->count)) { i = 0; }
+- }
+-
+- tx_ring->pkt++;
++ if (unlikely(++i == tx_ring->count)) i = 0;
++ }
+
+- eop = tx_ring->buffer_info[i].next_to_watch;
+- eop_desc = E1000_TX_DESC(*tx_ring, eop);
+- }
++ eop = tx_ring->buffer_info[i].next_to_watch;
++ eop_desc = E1000_TX_DESC(*tx_ring, eop);
++#define E1000_TX_WEIGHT 64
++ /* weight of a sort for tx, to avoid endless transmit cleanup */
++ if (count++ == E1000_TX_WEIGHT)
++ break;
++ }
+
+ tx_ring->next_to_clean = i;
+
+- spin_lock(&tx_ring->tx_lock);
++#define TX_WAKE_THRESHOLD 32
+
+- if (unlikely(cleaned && netif_queue_stopped(netdev) &&
+- netif_carrier_ok(netdev))) {
+- netif_wake_queue(netdev);
+- }
+- spin_unlock(&tx_ring->tx_lock);
+-
+- if (adapter->detect_tx_hung) {
+- /* Detect a transmit hang in hardware, this serializes the
+- * check with the clearing of time_stamp and movement of i */
+- adapter->detect_tx_hung = FALSE;
+-
+- if (tx_ring->buffer_info[i].dma &&
+- time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ)
+- && !(E1000_READ_REG(&adapter->hw, STATUS) &
+- E1000_STATUS_TXOFF)) {
+-
+- /* detected Tx unit hang */
+- i = tx_ring->next_to_clean;
+- eop = tx_ring->buffer_info[i].next_to_watch;
+- eop_desc = E1000_TX_DESC(*tx_ring, eop);
+- DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n"
+- " TDH <%x>\n"
+- " TDT <%x>\n"
+- " next_to_use <%x>\n"
+- " next_to_clean <%x>\n"
+- "buffer_info[next_to_clean]\n"
+- " dma <%zx>\n"
+- " time_stamp <%lx>\n"
+- " next_to_watch <%x>\n"
+- " jiffies <%lx>\n"
+- " next_to_watch.status <%x>\n",
+- readl(adapter->hw.hw_addr + tx_ring->tdh),
+- readl(adapter->hw.hw_addr + tx_ring->tdt),
+- tx_ring->next_to_use,
+- i,
+- (size_t)tx_ring->buffer_info[i].dma,
+- tx_ring->buffer_info[i].time_stamp,
+- eop,
+- jiffies,
+- eop_desc->upper.fields.status);
+- netif_stop_queue(netdev);
++ if (unlikely(cleaned && netif_carrier_ok(netdev) &&
++ E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) {
++ /* Make sure that anybody stopping the queue after this
++ * sees the new next_to_clean.
++ */
++ smp_mb();
++ if (netif_queue_stopped(netdev)) {
++ netif_wake_queue(netdev);
++ ++adapter->restart_queue;
+ }
+ }
+-#ifdef NETIF_F_TSO
+- if (unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
+- time_after(jiffies, tx_ring->previous_buffer_info.time_stamp + HZ))) {
+- iegbe_unmap_and_free_tx_resource(
+- adapter, &tx_ring->previous_buffer_info);
++
++ if (adapter->detect_tx_hung) {
++ /* Detect a transmit hang in hardware, this serializes the
++ * check with the clearing of time_stamp and movement of i */
++ adapter->detect_tx_hung = false;
++
++ if (tx_ring->buffer_info[eop].dma &&
++ time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
++ (adapter->tx_timeout_factor * HZ))
++ && !(E1000_READ_REG(hw, STATUS) & E1000_STATUS_TXOFF)) {
++
++ /* detected Tx unit hang */
++ DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n"
++ " Tx Queue <%lu>\n"
++ " TDH <%x>\n"
++ " TDT <%x>\n"
++ " next_to_use <%x>\n"
++ " next_to_clean <%x>\n"
++ "buffer_info[next_to_clean]\n"
++ " time_stamp <%lx>\n"
++ " next_to_watch <%x>\n"
++ " jiffies <%lx>\n"
++ " next_to_watch.status <%x>\n",
++ (unsigned long)((tx_ring - adapter->tx_ring) /
++ sizeof(struct iegbe_tx_ring)),
++ readl(hw->hw_addr + tx_ring->tdh),
++ readl(hw->hw_addr + tx_ring->tdt),
++ tx_ring->next_to_use,
++ tx_ring->next_to_clean,
++ tx_ring->buffer_info[eop].time_stamp,
++ eop,
++ jiffies,
++ eop_desc->upper.fields.status);
++ netif_stop_queue(netdev);
++ }
+ }
+-#endif
+- return cleaned;
++ adapter->total_tx_bytes += total_tx_bytes;
++ adapter->total_tx_packets += total_tx_packets;
++ adapter->net_stats.tx_bytes += total_tx_bytes;
++ adapter->net_stats.tx_packets += total_tx_packets;
++ return cleaned;
+ }
+-#endif
+
+ /**
+ * iegbe_rx_checksum - Receive Checksum Offload for 82543
+@@ -3913,192 +3689,193 @@ iegbe_clean_tx_irq(struct iegbe_adapter
+ * @sk_buff: socket buffer with received data
+ **/
+
+-static inline void
+-iegbe_rx_checksum(struct iegbe_adapter *adapter,
+- uint32_t status_err, uint32_t csum,
+- struct sk_buff *skb)
++static void iegbe_rx_checksum(struct iegbe_adapter *adapter, u32 status_err,
++ u32 csum, struct sk_buff *skb)
+ {
+- uint16_t status = (uint16_t)status_err;
+- uint8_t errors = (uint8_t)(status_err >> 0x18);
++ struct iegbe_hw *hw = &adapter->hw;
++ u16 status = (u16)status_err;
++ u8 errors = (u8)(status_err >> 24);
+ skb->ip_summed = CHECKSUM_NONE;
+
+- /* 82543 or newer only */
+- if(unlikely(adapter->hw.mac_type < iegbe_82543)) { return; }
+- /* Ignore Checksum bit is set */
+- if(unlikely(status & E1000_RXD_STAT_IXSM)) { return; }
+- /* TCP/UDP checksum error bit is set */
+- if(unlikely(errors & E1000_RXD_ERR_TCPE)) {
+- /* let the stack verify checksum errors */
+- adapter->hw_csum_err++;
+- return;
+- }
+- /* TCP/UDP Checksum has not been calculated */
+- if(adapter->hw.mac_type <= iegbe_82547_rev_2) {
+- if(!(status & E1000_RXD_STAT_TCPCS)) {
+- return;
++ /* 82543 or newer only */
++ if (unlikely(hw->mac_type < iegbe_82543)) return;
++ /* Ignore Checksum bit is set */
++ if (unlikely(status & E1000_RXD_STAT_IXSM)) return;
++ /* TCP/UDP checksum error bit is set */
++ if(unlikely(errors & E1000_RXD_ERR_TCPE)) {
++ /* let the stack verify checksum errors */
++ adapter->hw_csum_err++;
++ return;
++ }
++ /* TCP/UDP Checksum has not been calculated */
++ if (hw->mac_type <= iegbe_82547_rev_2) {
++ if (!(status & E1000_RXD_STAT_TCPCS))
++ return;
++ } else {
++ if (!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)))
++ return;
+ }
+- } else {
+- if(!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))) {
+- return;
+- }
++ /* It must be a TCP or UDP packet with a valid checksum */
++ if(likely(status & E1000_RXD_STAT_TCPCS)) {
++ /* TCP checksum is good */
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ } else if (hw->mac_type > iegbe_82547_rev_2) {
++ /* IP fragment with UDP payload */
++ /* Hardware complements the payload checksum, so we undo it
++ * and then put the value in host order for further stack use.
++ */
++ __sum16 sum = (__force __sum16)htons(csum);
++ skb->csum = csum_unfold(~sum);
++ skb->ip_summed = CHECKSUM_COMPLETE;
+ }
+- /* It must be a TCP or UDP packet with a valid checksum */
+- if(likely(status & E1000_RXD_STAT_TCPCS)) {
+- /* TCP checksum is good */
+- skb->ip_summed = CHECKSUM_UNNECESSARY;
+- } else if(adapter->hw.mac_type > iegbe_82547_rev_2) {
+- /* IP fragment with UDP payload */
+- /* Hardware complements the payload checksum, so we undo it
+- * and then put the value in host order for further stack use.
+- */
+- csum = ntohl(csum ^ 0xFFFF);
+- skb->csum = csum;
+- skb->ip_summed = CHECKSUM_HW;
+- }
+- adapter->hw_csum_good++;
++ adapter->hw_csum_good++;
+ }
+
+ /**
+ * iegbe_clean_rx_irq - Send received data up the network stack; legacy
+ * @adapter: board private structure
+ **/
+-
+-static boolean_t
+-#ifdef CONFIG_E1000_NAPI
+-iegbe_clean_rx_irq(struct iegbe_adapter *adapter,
++static bool iegbe_clean_rx_irq(struct iegbe_adapter *adapter,
+ struct iegbe_rx_ring *rx_ring,
+ int *work_done, int work_to_do)
+-#else
+-iegbe_clean_rx_irq(struct iegbe_adapter *adapter,
+- struct iegbe_rx_ring *rx_ring)
+-#endif
+ {
+- struct net_device *netdev = adapter->netdev;
+- struct pci_dev *pdev = adapter->pdev;
+- struct iegbe_rx_desc *rx_desc;
+- struct iegbe_buffer *buffer_info;
+- struct sk_buff *skb;
+- unsigned long flags = 0;
+- uint32_t length;
+- uint8_t last_byte;
+- unsigned int i;
+- boolean_t cleaned = FALSE;
+-
+-#ifdef IEGBE_GBE_WORKAROUND
+- /* Need to keep track of the amount of Rx descriptors that we
+- cleaned to ensure that we don't supply too many back to the
+- hardware */
+- int cleaned_count = 0;
+-#endif
+-
+- i = rx_ring->next_to_clean;
+- rx_desc = E1000_RX_DESC(*rx_ring, i);
+-
+- while(rx_desc->status & E1000_RXD_STAT_DD) {
+- buffer_info = &rx_ring->buffer_info[i];
+-#ifdef CONFIG_E1000_NAPI
+- if(*work_done >= work_to_do) {
+- break;
+- }
+- (*work_done)++;
+-#endif
+- cleaned = TRUE;
++ struct iegbe_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ struct pci_dev *pdev = adapter->pdev;
++ struct iegbe_rx_desc *rx_desc, *next_rxd;
++ struct iegbe_buffer *buffer_info, *next_buffer;
++ unsigned long flags;
++ u32 length;
++ u8 last_byte;
++ unsigned int i;
++ int cleaned_count = 0;
++ bool cleaned = false;
++ unsigned int total_rx_bytes=0, total_rx_packets=0;
+
+-#ifdef IEGBE_GBE_WORKAROUND
+- cleaned_count++;
+-#endif
++ i = rx_ring->next_to_clean;
++ rx_desc = E1000_RX_DESC(*rx_ring, i);
++ buffer_info = &rx_ring->buffer_info[i];
+
+- pci_unmap_single(pdev,
+- buffer_info->dma,
+- buffer_info->length,
+- PCI_DMA_FROMDEVICE);
++ while(rx_desc->status & E1000_RXD_STAT_DD) {
++ struct sk_buff *skb;
++ u8 status;
++ if (*work_done >= work_to_do)
++ break;
++ (*work_done)++;
+
++ status = rx_desc->status;
+ skb = buffer_info->skb;
+- length = le16_to_cpu(rx_desc->length);
++ buffer_info->skb = NULL;
++ prefetch(skb->data - NET_IP_ALIGN);
++ if (++i == rx_ring->count) i = 0;
++ next_rxd = E1000_RX_DESC(*rx_ring, i);
++ prefetch(next_rxd);
++ next_buffer = &rx_ring->buffer_info[i];
++ cleaned = true;
++ cleaned_count++;
++ pci_unmap_single(pdev,
++ buffer_info->dma,
++ buffer_info->length,
++ PCI_DMA_FROMDEVICE);
++
++ length = le16_to_cpu(rx_desc->length);
++
++ if (unlikely(!(status & E1000_RXD_STAT_EOP))) {
++ /* All receives must fit into a single buffer */
++ E1000_DBG("%s: Receive packet consumed multiple"
++ " buffers\n", netdev->name);
++ buffer_info->skb = skb;
++ goto next_desc;
++ }
+
+- if(unlikely(!(rx_desc->status & E1000_RXD_STAT_EOP))) {
+- /* All receives must fit into a single buffer */
+- E1000_DBG("%s: Receive packet consumed multiple"
+- " buffers\n", netdev->name);
+- dev_kfree_skb_irq(skb);
+- goto next_desc;
+- }
++ if(unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
++ last_byte = *(skb->data + length - 1);
++ if (TBI_ACCEPT(hw, status, rx_desc->errors, length,
++ last_byte)) {
++ spin_lock_irqsave(&adapter->stats_lock, flags);
++ iegbe_tbi_adjust_stats(hw, &adapter->stats,
++ length, skb->data);
++ spin_unlock_irqrestore(&adapter->stats_lock,
++ flags);
++ length--;
++ } else {
++ buffer_info->skb = skb;
++ goto next_desc;
++ }
++ }
+
+- if(unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
+- last_byte = *(skb->data + length - 0x1);
+- if(TBI_ACCEPT(&adapter->hw, rx_desc->status,
+- rx_desc->errors, length, last_byte)) {
+- spin_lock_irqsave(&adapter->stats_lock, flags);
+- iegbe_tbi_adjust_stats(&adapter->hw,
+- &adapter->stats,
+- length, skb->data);
+- spin_unlock_irqrestore(&adapter->stats_lock,
+- flags);
+- length--;
+- } else {
+- dev_kfree_skb_irq(skb);
+- goto next_desc;
++ /* adjust length to remove Ethernet CRC, this must be
++ * done after the TBI_ACCEPT workaround above */
++ length -= 4;
++
++ /* probably a little skewed due to removing CRC */
++ total_rx_bytes += length;
++ total_rx_packets++;
++
++ /* code added for copybreak, this should improve
++ * performance for small packets with large amounts
++ * of reassembly being done in the stack */
++ if (length < copybreak) {
++ struct sk_buff *new_skb =
++ netdev_alloc_skb(netdev, length + NET_IP_ALIGN);
++ if (new_skb) {
++ skb_reserve(new_skb, NET_IP_ALIGN);
++ skb_copy_to_linear_data_offset(new_skb,
++ -NET_IP_ALIGN,
++ (skb->data -
++ NET_IP_ALIGN),
++ (length +
++ NET_IP_ALIGN));
++ /* save the skb in buffer_info as good */
++ buffer_info->skb = skb;
++ skb = new_skb;
+ }
++ /* else just continue with the old one */
+ }
+-
+- /* Good Receive */
+- skb_put(skb, length - ETHERNET_FCS_SIZE);
++ /* Good Receive */
++ skb_put(skb, length);
+
+ /* Receive Checksum Offload */
+ iegbe_rx_checksum(adapter,
+- (uint32_t)(rx_desc->status) |
+- ((uint32_t)(rx_desc->errors) << 0x18),
+- rx_desc->csum, skb);
++ (u32)(status) |
++ ((u32)(rx_desc->errors) << 24),
++ le16_to_cpu(rx_desc->csum), skb);
++
+ skb->protocol = eth_type_trans(skb, netdev);
+-#ifdef CONFIG_E1000_NAPI
+-#ifdef NETIF_F_HW_VLAN_TX
+- if(unlikely(adapter->vlgrp &&
+- (rx_desc->status & E1000_RXD_STAT_VP))) {
++
++ if (unlikely(adapter->vlgrp &&
++ (status & E1000_RXD_STAT_VP))) {
+ vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
+- le16_to_cpu(rx_desc->special) &
+- E1000_RXD_SPC_VLAN_MASK);
++ le16_to_cpu(rx_desc->special));
+ } else {
+ netif_receive_skb(skb);
+ }
+-#else
+- netif_receive_skb(skb);
+-#endif
+-#else /* CONFIG_E1000_NAPI */
+-#ifdef NETIF_F_HW_VLAN_TX
+- if(unlikely(adapter->vlgrp &&
+- (rx_desc->status & E1000_RXD_STAT_VP))) {
+- vlan_hwaccel_rx(skb, adapter->vlgrp,
+- le16_to_cpu(rx_desc->special) &
+- E1000_RXD_SPC_VLAN_MASK);
+- } else {
+- netif_rx(skb);
+- }
+-#else
+- netif_rx(skb);
+-#endif
+-#endif /* CONFIG_E1000_NAPI */
++
+ netdev->last_rx = jiffies;
+- rx_ring->pkt++;
+
+ next_desc:
+ rx_desc->status = 0;
+- buffer_info->skb = NULL;
+- if(unlikely(++i == rx_ring->count)) { i = 0; }
+
+- rx_desc = E1000_RX_DESC(*rx_ring, i);
++ /* return some buffers to hardware, one at a time is too slow */
++ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
++ cleaned_count = 0;
++ }
++
++ /* use prefetched values */
++ rx_desc = next_rxd;
++ buffer_info = next_buffer;
+ }
+ rx_ring->next_to_clean = i;
+
+-#ifdef IEGBE_GBE_WORKAROUND
+- /* Only allocate the number of buffers that we have actually
+- cleaned! */
+- if (cleaned_count) {
+- adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
+- }
+-#else
+- adapter->alloc_rx_buf(adapter, rx_ring);
+-#endif
+-
++ cleaned_count = E1000_DESC_UNUSED(rx_ring);
++ if (cleaned_count)
++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
++
++ adapter->total_rx_packets += total_rx_packets;
++ adapter->total_rx_bytes += total_rx_bytes;
++ adapter->net_stats.rx_bytes += total_rx_bytes;
++ adapter->net_stats.rx_packets += total_rx_packets;
+ return cleaned;
+ }
+
+@@ -4107,161 +3884,153 @@ next_desc:
+ * @adapter: board private structure
+ **/
+
+-static boolean_t
+-#ifdef CONFIG_E1000_NAPI
+-iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter,
++static bool iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter,
+ struct iegbe_rx_ring *rx_ring,
+ int *work_done, int work_to_do)
+-#else
+-iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter,
+- struct iegbe_rx_ring *rx_ring)
+-#endif
+ {
+- union iegbe_rx_desc_packet_split *rx_desc;
+- struct net_device *netdev = adapter->netdev;
+- struct pci_dev *pdev = adapter->pdev;
+- struct iegbe_buffer *buffer_info;
+- struct iegbe_ps_page *ps_page;
+- struct iegbe_ps_page_dma *ps_page_dma;
+- struct sk_buff *skb;
+- unsigned int i, j;
+- uint32_t length, staterr;
+- boolean_t cleaned = FALSE;
+-
+-#ifdef IEGBE_GBE_WORKAROUND
+- /* Need to keep track of the amount of Rx descriptors that we
+- cleaned to ensure that we don't supply too many back to the
+- hardware */
+- int cleaned_count = 0;
+-#endif
+-
+- i = rx_ring->next_to_clean;
+- rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
+- staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
+-
+- while(staterr & E1000_RXD_STAT_DD) {
+- buffer_info = &rx_ring->buffer_info[i];
+- ps_page = &rx_ring->ps_page[i];
+- ps_page_dma = &rx_ring->ps_page_dma[i];
+-#ifdef CONFIG_E1000_NAPI
+- if(unlikely(*work_done >= work_to_do)) {
+- break;
+- }
+- (*work_done)++;
+-#endif
+- cleaned = TRUE;
+-
+-#ifdef IEGBE_GBE_WORKAROUND
+- cleaned_count++;
+-#endif
++ union iegbe_rx_desc_packet_split *rx_desc, *next_rxd;
++ struct net_device *netdev = adapter->netdev;
++ struct pci_dev *pdev = adapter->pdev;
++ struct iegbe_buffer *buffer_info, *next_buffer;
++ struct iegbe_ps_page *ps_page;
++ struct iegbe_ps_page_dma *ps_page_dma;
++ struct sk_buff *skb;
++ unsigned int i, j;
++ u32 length, staterr;
++ int cleaned_count = 0;
++ bool cleaned = false;
++ unsigned int total_rx_bytes=0, total_rx_packets=0;
++
++ i = rx_ring->next_to_clean;
++ rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
++ staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
++ buffer_info = &rx_ring->buffer_info[i];
+
+- pci_unmap_single(pdev, buffer_info->dma,
+- buffer_info->length,
+- PCI_DMA_FROMDEVICE);
++ while(staterr & E1000_RXD_STAT_DD) {
++ ps_page = &rx_ring->ps_page[i];
++ ps_page_dma = &rx_ring->ps_page_dma[i];
++
++ if (unlikely(*work_done >= work_to_do))
++ break;
++ (*work_done)++;
+
+ skb = buffer_info->skb;
++ prefetch(skb->data - NET_IP_ALIGN);
++ if (++i == rx_ring->count) i = 0;
++ next_rxd = E1000_RX_DESC_PS(*rx_ring, i);
++ prefetch(next_rxd);
++ next_buffer = &rx_ring->buffer_info[i];
++ cleaned = true;
++ cleaned_count++;
++ pci_unmap_single(pdev, buffer_info->dma,
++ buffer_info->length,
++ PCI_DMA_FROMDEVICE);
++
++ if(unlikely(!(staterr & E1000_RXD_STAT_EOP))) {
++ E1000_DBG("%s: Packet Split buffers didn't pick up"
++ " the full packet\n", netdev->name);
++ dev_kfree_skb_irq(skb);
++ goto next_desc;
++ }
+
+- if(unlikely(!(staterr & E1000_RXD_STAT_EOP))) {
+- E1000_DBG("%s: Packet Split buffers didn't pick up"
+- " the full packet\n", netdev->name);
+- dev_kfree_skb_irq(skb);
+- goto next_desc;
+- }
+-
+- if(unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) {
+- dev_kfree_skb_irq(skb);
+- goto next_desc;
+- }
+-
+- length = le16_to_cpu(rx_desc->wb.middle.length0);
++ if(unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) {
++ dev_kfree_skb_irq(skb);
++ goto next_desc;
++ }
+
+- if(unlikely(!length)) {
+- E1000_DBG("%s: Last part of the packet spanning"
+- " multiple descriptors\n", netdev->name);
+- dev_kfree_skb_irq(skb);
+- goto next_desc;
+- }
++ length = le16_to_cpu(rx_desc->wb.middle.length0);
+
+- /* Good Receive */
+- skb_put(skb, length);
+-
+- for(j = 0; j < adapter->rx_ps_pages; j++) {
+- if(!(length = le16_to_cpu(rx_desc->wb.upper.length[j]))) {
+- break;
+- }
+- pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j],
+- PAGE_SIZE, PCI_DMA_FROMDEVICE);
+- ps_page_dma->ps_page_dma[j] = 0;
+- skb_shinfo(skb)->frags[j].page =
+- ps_page->ps_page[j];
+- ps_page->ps_page[j] = NULL;
+- skb_shinfo(skb)->frags[j].page_offset = 0;
+- skb_shinfo(skb)->frags[j].size = length;
+- skb_shinfo(skb)->nr_frags++;
+- skb->len += length;
+- skb->data_len += length;
+- }
++ if(unlikely(!length)) {
++ E1000_DBG("%s: Last part of the packet spanning"
++ " multiple descriptors\n", netdev->name);
++ dev_kfree_skb_irq(skb);
++ goto next_desc;
++ }
+
+- iegbe_rx_checksum(adapter, staterr,
+- rx_desc->wb.lower.hi_dword.csum_ip.csum, skb);
+- skb->protocol = eth_type_trans(skb, netdev);
++ /* Good Receive */
++ skb_put(skb, length);
+
+- if(likely(rx_desc->wb.upper.header_status &
+- E1000_RXDPS_HDRSTAT_HDRSP)) {
+- adapter->rx_hdr_split++;
+-#ifdef HAVE_RX_ZERO_COPY
+- skb_shinfo(skb)->zero_copy = TRUE;
+-#endif
+- }
+-#ifdef CONFIG_E1000_NAPI
+-#ifdef NETIF_F_HW_VLAN_TX
+- if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
+- vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
+- le16_to_cpu(rx_desc->wb.middle.vlan) &
+- E1000_RXD_SPC_VLAN_MASK);
+- } else {
+- netif_receive_skb(skb);
+- }
+-#else
+- netif_receive_skb(skb);
+-#endif
+-#else /* CONFIG_E1000_NAPI */
+-#ifdef NETIF_F_HW_VLAN_TX
+- if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
+- vlan_hwaccel_rx(skb, adapter->vlgrp,
+- le16_to_cpu(rx_desc->wb.middle.vlan) &
+- E1000_RXD_SPC_VLAN_MASK);
+- } else {
+- netif_rx(skb);
+- }
+-#else
+- netif_rx(skb);
+-#endif
+-#endif /* CONFIG_E1000_NAPI */
+- netdev->last_rx = jiffies;
+- rx_ring->pkt++;
++ {
++ int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]);
++ if (l1 && (l1 <= copybreak) && ((length + l1) <= adapter->rx_ps_bsize0)) {
++ u8 *vaddr;
++ pci_dma_sync_single_for_cpu(pdev,
++ ps_page_dma->ps_page_dma[0],
++ PAGE_SIZE,
++ PCI_DMA_FROMDEVICE);
++ vaddr = kmap_atomic(ps_page->ps_page[0],
++ KM_SKB_DATA_SOFTIRQ);
++ memcpy(skb_tail_pointer(skb), vaddr, l1);
++ kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ);
++ pci_dma_sync_single_for_device(pdev,
++ ps_page_dma->ps_page_dma[0],
++ PAGE_SIZE, PCI_DMA_FROMDEVICE);
++ l1 -= 4;
++ skb_put(skb, l1);
++ goto copydone;
++ } /* if */
++ }
++ for (j = 0; j < adapter->rx_ps_pages; j++) {
++ length = le16_to_cpu(rx_desc->wb.upper.length[j]);
++ if (!length)
++ break;
++ pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j],
++ PAGE_SIZE, PCI_DMA_FROMDEVICE);
++ ps_page_dma->ps_page_dma[j] = 0;
++ skb_fill_page_desc(skb, j, ps_page->ps_page[j], 0,
++ length);
++ ps_page->ps_page[j] = NULL;
++ skb->len += length;
++ skb->data_len += length;
++ skb->truesize += length;
++ }
+
+-next_desc:
+- rx_desc->wb.middle.status_error &= ~0xFF;
+- buffer_info->skb = NULL;
+- if(unlikely(++i == rx_ring->count)) { i = 0; }
++ pskb_trim(skb, skb->len - 4);
++copydone:
++ total_rx_bytes += skb->len;
++ total_rx_packets++;
++ iegbe_rx_checksum(adapter, staterr,
++ le16_to_cpu(rx_desc->wb.lower.hi_dword.csum_ip.csum), skb);
++ skb->protocol = eth_type_trans(skb, netdev);
++
++ if(likely(rx_desc->wb.upper.header_status &
++ cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP)))
++ adapter->rx_hdr_split++;
++
++ if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
++ vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
++ le16_to_cpu(rx_desc->wb.middle.vlan));
++ } else {
++ netif_receive_skb(skb);
++ }
+
+- rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
+- staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
+- }
+- rx_ring->next_to_clean = i;
++ netdev->last_rx = jiffies;
+
+-#ifdef IEGBE_GBE_WORKAROUND
+- /* Only allocate the number of buffers that we have actually
+- cleaned! */
+- if (cleaned_count) {
+- adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
+- }
+-#else
+- adapter->alloc_rx_buf(adapter, rx_ring);
+-#endif
++next_desc:
++ rx_desc->wb.middle.status_error &= cpu_to_le32(~0xFF);
++ buffer_info->skb = NULL;
+
+- return cleaned;
++ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
++ cleaned_count = 0;
++ }
++
++ /* use prefetched values */
++ rx_desc = next_rxd;
++ buffer_info = next_buffer;
++ staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
++ }
++ rx_ring->next_to_clean = i;
++
++ cleaned_count = E1000_DESC_UNUSED(rx_ring);
++ if (cleaned_count)
++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
++
++ adapter->total_rx_packets += total_rx_packets;
++ adapter->total_rx_bytes += total_rx_bytes;
++ adapter->net_stats.rx_bytes += total_rx_bytes;
++ adapter->net_stats.rx_packets += total_rx_packets;
++ return cleaned;
+ }
+
+ /**
+@@ -4269,142 +4038,115 @@ next_desc:
+ * @adapter: address of board private structure
+ **/
+
+-#ifdef IEGBE_GBE_WORKAROUND
+-static void
+-iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter,
++
++static void iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter,
+ struct iegbe_rx_ring *rx_ring,
+ int cleaned_count)
+-#else
+-static void
+-iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter,
+- struct iegbe_rx_ring *rx_ring)
+-#endif
+ {
+- struct net_device *netdev = adapter->netdev;
+- struct pci_dev *pdev = adapter->pdev;
+- struct iegbe_rx_desc *rx_desc;
+- struct iegbe_buffer *buffer_info;
+- struct sk_buff *skb;
+- unsigned int i;
+- unsigned int bufsz = adapter->rx_buffer_len + NET_IP_ALIGN;
+-
+- i = rx_ring->next_to_use;
+- buffer_info = &rx_ring->buffer_info[i];
++ struct iegbe_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ struct pci_dev *pdev = adapter->pdev;
++ struct iegbe_rx_desc *rx_desc;
++ struct iegbe_buffer *buffer_info;
++ struct sk_buff *skb;
++ unsigned int i;
++ unsigned int bufsz = adapter->rx_buffer_len + NET_IP_ALIGN;
+
+-#ifdef IEGBE_GBE_WORKAROUND
+- if (cleaned_count > IEGBE_GBE_WORKAROUND_NUM_RX_DESCRIPTORS) {
+- adapter->stats.cc_gt_num_rx++;
+- }
+- while(cleaned_count-- && !buffer_info->skb) {
+-#else
+- while(!buffer_info->skb) {
+-#endif
+- skb = dev_alloc_skb(bufsz);
++ i = rx_ring->next_to_use;
++ buffer_info = &rx_ring->buffer_info[i];
+
+- if(unlikely(!skb)) {
+- /* Better luck next round */
+- break;
+- }
++ while (cleaned_count--) {
++ skb = buffer_info->skb;
++ if (skb) {
++ skb_trim(skb, 0);
++ goto map_skb;
++ }
++ skb = netdev_alloc_skb(netdev, bufsz);
++
++ if(unlikely(!skb)) {
++ /* Better luck next round */
++ adapter->alloc_rx_buff_failed++;
++ break;
++ }
+
+- /* Fix for errata 23, can't cross 64kB boundary */
+- if(!iegbe_check_64k_bound(adapter, skb->data, bufsz)) {
+- struct sk_buff *oldskb = skb;
+- DPRINTK(RX_ERR, ERR, "skb align check failed: %u bytes "
+- "at %p\n", bufsz, skb->data);
+- /* Try again, without freeing the previous */
+- skb = dev_alloc_skb(bufsz);
+- /* Failed allocation, critical failure */
+- if(!skb) {
+- dev_kfree_skb(oldskb);
+- break;
+- }
++ /* Fix for errata 23, can't cross 64kB boundary */
++ if(!iegbe_check_64k_bound(adapter, skb->data, bufsz)) {
++ struct sk_buff *oldskb = skb;
++ DPRINTK(RX_ERR, ERR, "skb align check failed: %u bytes "
++ "at %p\n", bufsz, skb->data);
++ /* Try again, without freeing the previous */
++ skb = netdev_alloc_skb(netdev, bufsz);
++ /* Failed allocation, critical failure */
++ if(!skb) {
++ dev_kfree_skb(oldskb);
++ break;
++ }
+
+- if(!iegbe_check_64k_bound(adapter, skb->data, bufsz)) {
+- /* give up */
+- dev_kfree_skb(skb);
+- dev_kfree_skb(oldskb);
+- break; /* while !buffer_info->skb */
+- } else {
+- /* Use new allocation */
+- dev_kfree_skb(oldskb);
++ if(!iegbe_check_64k_bound(adapter, skb->data, bufsz)) {
++ /* give up */
++ dev_kfree_skb(skb);
++ dev_kfree_skb(oldskb);
++ break; /* while !buffer_info->skb */
+ }
+- }
+- /* Make buffer alignment 2 beyond a 16 byte boundary
+- * this will result in a 16 byte aligned IP header after
+- * the 14 byte MAC header is removed
+- */
+- skb_reserve(skb, NET_IP_ALIGN);
+-
+- skb->dev = netdev;
+-
+- buffer_info->skb = skb;
+- buffer_info->length = adapter->rx_buffer_len;
+- buffer_info->dma = pci_map_single(pdev,
+- skb->data,
+- adapter->rx_buffer_len,
+- PCI_DMA_FROMDEVICE);
+-
+- /* Fix for errata 23, can't cross 64kB boundary */
+- if(!iegbe_check_64k_bound(adapter,
+- (void *)(unsigned long)buffer_info->dma,
+- adapter->rx_buffer_len)) {
+- DPRINTK(RX_ERR, ERR,
+- "dma align check failed: %u bytes at %p\n",
+- adapter->rx_buffer_len,
+- (void *)(unsigned long)buffer_info->dma);
+- dev_kfree_skb(skb);
+- buffer_info->skb = NULL;
+-
+- pci_unmap_single(pdev, buffer_info->dma,
+- adapter->rx_buffer_len,
+- PCI_DMA_FROMDEVICE);
+-
+- break; /* while !buffer_info->skb */
+- }
+- rx_desc = E1000_RX_DESC(*rx_ring, i);
+- rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
+-
+-#ifdef IEGBE_GBE_WORKAROUND_DISABLED
+- adapter->stats.num_rx_buf_alloc++;
++ /* Use new allocation */
++ dev_kfree_skb(oldskb);
++ }
++ /* Make buffer alignment 2 beyond a 16 byte boundary
++ * this will result in a 16 byte aligned IP header after
++ * the 14 byte MAC header is removed
++ */
++ skb_reserve(skb, NET_IP_ALIGN);
++
++
++ buffer_info->skb = skb;
++ buffer_info->length = adapter->rx_buffer_len;
++map_skb:
++ buffer_info->dma = pci_map_single(pdev,
++ skb->data,
++ adapter->rx_buffer_len,
++ PCI_DMA_FROMDEVICE);
++
++ /* Fix for errata 23, can't cross 64kB boundary */
++ if(!iegbe_check_64k_bound(adapter,
++ (void *)(unsigned long)buffer_info->dma,
++ adapter->rx_buffer_len)) {
++ DPRINTK(RX_ERR, ERR,
++ "dma align check failed: %u bytes at %p\n",
++ adapter->rx_buffer_len,
++ (void *)(unsigned long)buffer_info->dma);
++ dev_kfree_skb(skb);
++ buffer_info->skb = NULL;
++
++ pci_unmap_single(pdev, buffer_info->dma,
++ adapter->rx_buffer_len,
++ PCI_DMA_FROMDEVICE);
+
+- /* Force memory writes to complete before letting h/w
+- * know there are new descriptors to fetch. (Only
+- * applicable for weak-ordered memory model archs,
+- * such as IA-64). */
+- wmb();
+- writel(i, adapter->hw.hw_addr + rx_ring->rdt);
++ break; /* while !buffer_info->skb */
++ }
++ rx_desc = E1000_RX_DESC(*rx_ring, i);
++ rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
+
+-#endif
+-#ifndef IEGBE_GBE_WORKAROUND
+- if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 0x1)) == i)) {
+- /* Force memory writes to complete before letting h/w
+- * know there are new descriptors to fetch. (Only
+- * applicable for weak-ordered memory model archs,
+- * such as IA-64). */
+- wmb();
+- writel(i, adapter->hw.hw_addr + rx_ring->rdt);
+- }
+-#endif
+- if(unlikely(++i == rx_ring->count)) { i = 0; }
+- buffer_info = &rx_ring->buffer_info[i];
+- }
++ /* Force memory writes to complete before letting h/w
++ * know there are new descriptors to fetch. (Only
++ * applicable for weak-ordered memory model archs,
++ * such as IA-64). */
++ if (unlikely(++i == rx_ring->count))
++ i = 0;
++ buffer_info = &rx_ring->buffer_info[i];
++ }
+
+-#ifdef IEGBE_GBE_WORKAROUND
+ if (likely(rx_ring->next_to_use != i)) {
+- rx_ring->next_to_use = i;
+- if (unlikely(i-- == 0)) {
+- i = (rx_ring->count - 0x1);
+- }
++ rx_ring->next_to_use = i;
++ if (unlikely(i-- == 0))
++ i = (rx_ring->count - 1);
++
+ /* Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64). */
+ wmb();
+- writel(i, adapter->hw.hw_addr + rx_ring->rdt);
++ writel(i, hw->hw_addr + rx_ring->rdt);
+ }
+-#else
+- rx_ring->next_to_use = i;
+-#endif
+ }
+
+ /**
+@@ -4412,49 +4154,41 @@ iegbe_alloc_rx_buffers(struct iegbe_adap
+ * @adapter: address of board private structure
+ **/
+
+-#ifdef IEGBE_GBE_WORKAROUND
+-static void
+-iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter,
++
++static void iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter,
+ struct iegbe_rx_ring *rx_ring,
+ int cleaned_count)
+-#else
+-static void
+-iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter,
+- struct iegbe_rx_ring *rx_ring)
+-#endif
+ {
+- struct net_device *netdev = adapter->netdev;
+- struct pci_dev *pdev = adapter->pdev;
+- union iegbe_rx_desc_packet_split *rx_desc;
+- struct iegbe_buffer *buffer_info;
+- struct iegbe_ps_page *ps_page;
+- struct iegbe_ps_page_dma *ps_page_dma;
+- struct sk_buff *skb;
+- unsigned int i, j;
+-
+- i = rx_ring->next_to_use;
+- buffer_info = &rx_ring->buffer_info[i];
+- ps_page = &rx_ring->ps_page[i];
+- ps_page_dma = &rx_ring->ps_page_dma[i];
++ struct iegbe_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ struct pci_dev *pdev = adapter->pdev;
++ union iegbe_rx_desc_packet_split *rx_desc;
++ struct iegbe_buffer *buffer_info;
++ struct iegbe_ps_page *ps_page;
++ struct iegbe_ps_page_dma *ps_page_dma;
++ struct sk_buff *skb;
++ unsigned int i, j;
++
++ i = rx_ring->next_to_use;
++ buffer_info = &rx_ring->buffer_info[i];
++ ps_page = &rx_ring->ps_page[i];
++ ps_page_dma = &rx_ring->ps_page_dma[i];
+
+-#ifdef IEGBE_GBE_WORKAROUND
+- while(cleaned_count-- && !buffer_info->skb) {
+-#else
+- while(!buffer_info->skb) {
+-#endif
+- rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
++ while (cleaned_count--) {
++ rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
+
+ for (j = 0; j < PS_PAGE_BUFFERS; j++) {
+- if (j < adapter->rx_ps_pages) {
+- if (likely(!ps_page->ps_page[j])) {
+- ps_page->ps_page[j] =
+- alloc_page(GFP_ATOMIC);
++ if (j < adapter->rx_ps_pages) {
++ if (likely(!ps_page->ps_page[j])) {
++ ps_page->ps_page[j] =
++ alloc_page(GFP_ATOMIC);
+ if (unlikely(!ps_page->ps_page[j])) {
+- goto no_buffers;
++ adapter->alloc_rx_buff_failed++;
++ goto no_buffers;
+ }
+- ps_page_dma->ps_page_dma[j] =
+- pci_map_page(pdev,
+- ps_page->ps_page[j],
++ ps_page_dma->ps_page_dma[j] =
++ pci_map_page(pdev,
++ ps_page->ps_page[j],
+ 0, PAGE_SIZE,
+ PCI_DMA_FROMDEVICE);
+ }
+@@ -4462,26 +4196,26 @@ iegbe_alloc_rx_buffers_ps(struct iegbe_a
+ * change because each write-back erases
+ * this info.
+ */
+- rx_desc->read.buffer_addr[j+0x1] =
++ rx_desc->read.buffer_addr[j+1] =
+ cpu_to_le64(ps_page_dma->ps_page_dma[j]);
+- } else {
+- rx_desc->read.buffer_addr[j+0x1] = ~0;
+- }
++ } else
++ rx_desc->read.buffer_addr[j+1] = ~cpu_to_le64(0);
+ }
+
+- skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN);
++ skb = netdev_alloc_skb(netdev,
++ adapter->rx_ps_bsize0 + NET_IP_ALIGN);
+
+- if (unlikely(!skb)) {
++ if (unlikely(!skb)) {
++ adapter->alloc_rx_buff_failed++;
+ break;
+- }
++ }
++
+ /* Make buffer alignment 2 beyond a 16 byte boundary
+ * this will result in a 16 byte aligned IP header after
+ * the 14 byte MAC header is removed
+ */
+ skb_reserve(skb, NET_IP_ALIGN);
+
+- skb->dev = netdev;
+-
+ buffer_info->skb = skb;
+ buffer_info->length = adapter->rx_ps_bsize0;
+ buffer_info->dma = pci_map_single(pdev, skb->data,
+@@ -4490,27 +4224,28 @@ iegbe_alloc_rx_buffers_ps(struct iegbe_a
+
+ rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma);
+
+- if (unlikely((i & ~(E1000_RX_BUFFER_WRITE - 0x1)) == i)) {
+- /* Force memory writes to complete before letting h/w
+- * know there are new descriptors to fetch. (Only
+- * applicable for weak-ordered memory model archs,
+- * such as IA-64). */
+- wmb();
+- /* Hardware increments by 16 bytes, but packet split
+- * descriptors are 32 bytes...so we increment tail
+- * twice as much.
+- */
+- writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt);
+- }
+-
+- if (unlikely(++i == rx_ring->count)) { i = 0; }
++ if (unlikely(++i == rx_ring->count)) i = 0;
+ buffer_info = &rx_ring->buffer_info[i];
+ ps_page = &rx_ring->ps_page[i];
+ ps_page_dma = &rx_ring->ps_page_dma[i];
+ }
+
+ no_buffers:
+- rx_ring->next_to_use = i;
++ if (likely(rx_ring->next_to_use != i)) {
++ rx_ring->next_to_use = i;
++ if (unlikely(i-- == 0)) i = (rx_ring->count - 1);
++
++ /* Force memory writes to complete before letting h/w
++ * know there are new descriptors to fetch. (Only
++ * applicable for weak-ordered memory model archs,
++ * such as IA-64). */
++ wmb();
++ /* Hardware increments by 16 bytes, but packet split
++ * descriptors are 32 bytes...so we increment tail
++ * twice as much.
++ */
++ writel(i<<1, hw->hw_addr + rx_ring->rdt);
++ }
+ }
+
+ /**
+@@ -4521,52 +4256,52 @@ no_buffers:
+ static void
+ iegbe_smartspeed(struct iegbe_adapter *adapter)
+ {
+- uint16_t phy_status;
+- uint16_t phy_ctrl;
++ uint16_t phy_status;
++ uint16_t phy_ctrl;
+
+- if((adapter->hw.phy_type != iegbe_phy_igp) || !adapter->hw.autoneg ||
++ if((adapter->hw.phy_type != iegbe_phy_igp) || !adapter->hw.autoneg ||
+ !(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL)) {
+- return;
++ return;
+ }
+- if(adapter->smartspeed == 0) {
+- /* If Master/Slave config fault is asserted twice,
+- * we assume back-to-back */
+- iegbe_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
++ if(adapter->smartspeed == 0x0) {
++ /* If Master/Slave config fault is asserted twice,
++ * we assume back-to-back */
++ iegbe_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
+ if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) { return; }
+- iegbe_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
++ iegbe_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
+ if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) { return; }
+- iegbe_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
+- if(phy_ctrl & CR_1000T_MS_ENABLE) {
+- phy_ctrl &= ~CR_1000T_MS_ENABLE;
+- iegbe_write_phy_reg(&adapter->hw, PHY_1000T_CTRL,
+- phy_ctrl);
+- adapter->smartspeed++;
+- if(!iegbe_phy_setup_autoneg(&adapter->hw) &&
+- !iegbe_read_phy_reg(&adapter->hw, PHY_CTRL,
+- &phy_ctrl)) {
+- phy_ctrl |= (MII_CR_AUTO_NEG_EN |
+- MII_CR_RESTART_AUTO_NEG);
+- iegbe_write_phy_reg(&adapter->hw, PHY_CTRL,
+- phy_ctrl);
+- }
+- }
+- return;
+- } else if(adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
+- /* If still no link, perhaps using 2/3 pair cable */
+- iegbe_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
+- phy_ctrl |= CR_1000T_MS_ENABLE;
+- iegbe_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl);
+- if(!iegbe_phy_setup_autoneg(&adapter->hw) &&
+- !iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) {
+- phy_ctrl |= (MII_CR_AUTO_NEG_EN |
+- MII_CR_RESTART_AUTO_NEG);
+- iegbe_write_phy_reg(&adapter->hw, PHY_CTRL, phy_ctrl);
+- }
+- }
+- /* Restart process after E1000_SMARTSPEED_MAX iterations */
++ iegbe_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
++ if(phy_ctrl & CR_1000T_MS_ENABLE) {
++ phy_ctrl &= ~CR_1000T_MS_ENABLE;
++ iegbe_write_phy_reg(&adapter->hw, PHY_1000T_CTRL,
++ phy_ctrl);
++ adapter->smartspeed++;
++ if(!iegbe_phy_setup_autoneg(&adapter->hw) &&
++ !iegbe_read_phy_reg(&adapter->hw, PHY_CTRL,
++ &phy_ctrl)) {
++ phy_ctrl |= (MII_CR_AUTO_NEG_EN |
++ MII_CR_RESTART_AUTO_NEG);
++ iegbe_write_phy_reg(&adapter->hw, PHY_CTRL,
++ phy_ctrl);
++ }
++ }
++ return;
++ } else if(adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
++ /* If still no link, perhaps using 2/3 pair cable */
++ iegbe_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
++ phy_ctrl |= CR_1000T_MS_ENABLE;
++ iegbe_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl);
++ if(!iegbe_phy_setup_autoneg(&adapter->hw) &&
++ !iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) {
++ phy_ctrl |= (MII_CR_AUTO_NEG_EN |
++ MII_CR_RESTART_AUTO_NEG);
++ iegbe_write_phy_reg(&adapter->hw, PHY_CTRL, phy_ctrl);
++ }
++ }
++ /* Restart process after E1000_SMARTSPEED_MAX iterations */
+ if(adapter->smartspeed++ == E1000_SMARTSPEED_MAX) {
+- adapter->smartspeed = 0;
+-}
++ adapter->smartspeed = 0x0;
++ }
+ }
+
+ /**
+@@ -4576,23 +4311,22 @@ iegbe_smartspeed(struct iegbe_adapter *a
+ * @cmd:
+ **/
+
+-static int
+-iegbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
++static int iegbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+ {
+- switch (cmd) {
++ switch (cmd) {
+ #ifdef SIOCGMIIPHY
+- case SIOCGMIIPHY:
+- case SIOCGMIIREG:
+- case SIOCSMIIREG:
+- return iegbe_mii_ioctl(netdev, ifr, cmd);
++ case SIOCGMIIPHY:
++ case SIOCGMIIREG:
++ case SIOCSMIIREG:
++ return iegbe_mii_ioctl(netdev, ifr, cmd);
+ #endif
+ #ifdef ETHTOOL_OPS_COMPAT
+- case SIOCETHTOOL:
+- return ethtool_ioctl(ifr);
++ case SIOCETHTOOL:
++ return ethtool_ioctl(ifr);
+ #endif
+- default:
+- return -EOPNOTSUPP;
+- }
++ default:
++ return -EOPNOTSUPP;
++ }
+ }
+
+ #ifdef SIOCGMIIPHY
+@@ -4603,534 +4337,510 @@ iegbe_ioctl(struct net_device *netdev, s
+ * @cmd:
+ **/
+
+-static int
+-iegbe_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
++static int iegbe_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
++ int cmd)
+ {
+- struct iegbe_adapter *adapter = netdev_priv(netdev);
+- struct mii_ioctl_data *data = if_mii(ifr);
+- int retval;
+- uint16_t mii_reg;
+- uint16_t spddplx;
+- unsigned long flags;
+-
+- if((adapter->hw.media_type == iegbe_media_type_oem &&
+- !iegbe_oem_phy_is_copper(&adapter->hw)) ||
+- adapter->hw.media_type == iegbe_media_type_fiber ||
+- adapter->hw.media_type == iegbe_media_type_internal_serdes ) {
+- return -EOPNOTSUPP;
+- }
+- switch (cmd) {
+- case SIOCGMIIPHY:
+- data->phy_id = adapter->hw.phy_addr;
+- break;
+- case SIOCGMIIREG:
++ struct iegbe_adapter *adapter = netdev_priv(netdev);
++ struct mii_ioctl_data *data = if_mii(ifr);
++ int retval;
++ uint16_t mii_reg;
++ uint16_t spddplx;
++ unsigned long flags = 0;
++
++ if((adapter->hw.media_type == iegbe_media_type_oem
++ && !iegbe_oem_phy_is_copper(&adapter->hw))
++ ||adapter->hw.media_type != iegbe_media_type_copper) {
++ return -EOPNOTSUPP;
++ }
++ switch (cmd) {
++ case SIOCGMIIPHY:
++ data->phy_id = adapter->hw.phy_addr;
++ break;
++ case SIOCGMIIREG:
+ if(!capable(CAP_NET_ADMIN)) {
+- return -EPERM;
++ return -EPERM;
+ }
+- spin_lock_irqsave(&adapter->stats_lock, flags);
+- if(iegbe_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
+- &data->val_out)) {
+- spin_unlock_irqrestore(&adapter->stats_lock, flags);
+- return -EIO;
+- }
+- spin_unlock_irqrestore(&adapter->stats_lock, flags);
+- break;
+- case SIOCSMIIREG:
++ spin_lock_irqsave(&adapter->stats_lock, flags);
++ if(iegbe_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
++ &data->val_out)) {
++ spin_unlock_irqrestore(&adapter->stats_lock, flags);
++ return -EIO;
++ }
++ spin_unlock_irqrestore(&adapter->stats_lock, flags);
++ break;
++ case SIOCSMIIREG:
+ if(!capable(CAP_NET_ADMIN)){
+- return -EPERM;
++ return -EPERM;
+ }
+ if(data->reg_num & ~(0x1F)) {
+- return -EFAULT;
++ return -EFAULT;
+ }
+- mii_reg = data->val_in;
+- spin_lock_irqsave(&adapter->stats_lock, flags);
+- if(iegbe_write_phy_reg(&adapter->hw, data->reg_num,
+- mii_reg)) {
+- spin_unlock_irqrestore(&adapter->stats_lock, flags);
+- return -EIO;
+- }
+- switch(adapter->hw.phy_type) {
+- case iegbe_phy_m88:
+- switch (data->reg_num) {
+- case PHY_CTRL:
++ mii_reg = data->val_in;
++ spin_lock_irqsave(&adapter->stats_lock, flags);
++ if(iegbe_write_phy_reg(&adapter->hw, data->reg_num,
++ mii_reg)) {
++ spin_unlock_irqrestore(&adapter->stats_lock, flags);
++ return -EIO;
++ }
++ switch(adapter->hw.phy_type) {
++ case iegbe_phy_m88:
++ switch (data->reg_num) {
++ case PHY_CTRL:
+ if(mii_reg & MII_CR_POWER_DOWN) {
+- break;
++ break;
+ }
+- if(mii_reg & MII_CR_AUTO_NEG_EN) {
+- adapter->hw.autoneg = 1;
+- adapter->hw.autoneg_advertised = 0x2F;
+- } else {
++ if(mii_reg & MII_CR_AUTO_NEG_EN) {
++ adapter->hw.autoneg = 1;
++ adapter->hw.autoneg_advertised = 0x2F;
++ } else {
+ if(mii_reg & 0x40){
+- spddplx = SPEED_1000;
++ spddplx = SPEED_1000;
+ } else if(mii_reg & 0x2000) {
+- spddplx = SPEED_100;
++ spddplx = SPEED_100;
+ } else {
+- spddplx = SPEED_10;
++ spddplx = SPEED_10;
+ }
+- spddplx += (mii_reg & 0x100)
+- ? FULL_DUPLEX :
+- HALF_DUPLEX;
+- retval = iegbe_set_spd_dplx(adapter,
+- spddplx);
+- if(retval) {
+- spin_unlock_irqrestore(
+- &adapter->stats_lock,
+- flags);
+- return retval;
+- }
+- }
+- if(netif_running(adapter->netdev)) {
+- iegbe_down(adapter);
+- iegbe_up(adapter);
++ spddplx += (mii_reg & 0x100)
++ ? FULL_DUPLEX :
++ HALF_DUPLEX;
++ retval = iegbe_set_spd_dplx(adapter,
++ spddplx);
++ if(retval) {
++ spin_unlock_irqrestore(
++ &adapter->stats_lock,
++ flags);
++ return retval;
++ }
++ }
++ if(netif_running(adapter->netdev)) {
++ iegbe_down(adapter);
++ iegbe_up(adapter);
+ } else {
+- iegbe_reset(adapter);
++ iegbe_reset(adapter);
+ }
+- break;
+- case M88E1000_PHY_SPEC_CTRL:
+- case M88E1000_EXT_PHY_SPEC_CTRL:
+- if(iegbe_phy_reset(&adapter->hw)) {
+- spin_unlock_irqrestore(
+- &adapter->stats_lock, flags);
+- return -EIO;
+- }
+- break;
+- }
+- break;
++ break;
++ case M88E1000_PHY_SPEC_CTRL:
++ case M88E1000_EXT_PHY_SPEC_CTRL:
++ if(iegbe_phy_reset(&adapter->hw)) {
++ spin_unlock_irqrestore(
++ &adapter->stats_lock, flags);
++ return -EIO;
++ }
++ break;
++ }
++ break;
+
+- case iegbe_phy_oem:
+- retval = iegbe_oem_mii_ioctl(adapter, flags, ifr, cmd);
+- if(retval) {
+- spin_unlock_irqrestore(
+- &adapter->stats_lock, flags);
+- return retval;
+- }
+- break;
++ case iegbe_phy_oem:
++ retval = iegbe_oem_mii_ioctl(adapter, flags, ifr, cmd);
++ if(retval) {
++ spin_unlock_irqrestore(
++ &adapter->stats_lock, flags);
++ return retval;
++ }
++ break;
+
+- default:
+- switch (data->reg_num) {
+- case PHY_CTRL:
++ default:
++ switch (data->reg_num) {
++ case PHY_CTRL:
+ if(mii_reg & MII_CR_POWER_DOWN) {
+- break;
++ break;
+ }
+- if(netif_running(adapter->netdev)) {
+- iegbe_down(adapter);
+- iegbe_up(adapter);
++ if(netif_running(adapter->netdev)) {
++ iegbe_down(adapter);
++ iegbe_up(adapter);
+ } else {
+- iegbe_reset(adapter);
++ iegbe_reset(adapter);
+ }
+- break;
+- }
+- }
+- spin_unlock_irqrestore(&adapter->stats_lock, flags);
+- break;
+- default:
+- return -EOPNOTSUPP;
+- }
+- return E1000_SUCCESS;
++ break;
++ }
++ }
++ spin_unlock_irqrestore(&adapter->stats_lock, flags);
++ break;
++ default:
++ return -EOPNOTSUPP;
++ }
++ return E1000_SUCCESS;
+ }
+ #endif
+
+-void
+-iegbe_pci_set_mwi(struct iegbe_hw *hw)
++void iegbe_pci_set_mwi(struct iegbe_hw *hw)
+ {
+- struct iegbe_adapter *adapter = hw->back;
+-#ifdef HAVE_PCI_SET_MWI
+- int ret_val = pci_set_mwi(adapter->pdev);
+-
+- if(ret_val) {
+- DPRINTK(PROBE, ERR, "Error in setting MWI\n");
+- }
+-#else
+- pci_write_config_word(adapter->pdev, PCI_COMMAND,
+- adapter->hw.pci_cmd_word |
+- PCI_COMMAND_INVALIDATE);
+-#endif
++ struct iegbe_adapter *adapter = hw->back;
++ int ret_val = pci_set_mwi(adapter->pdev);
++
++ if (ret_val)
++ DPRINTK(PROBE, ERR, "Error in setting MWI\n");
+ }
+
+-void
+-iegbe_pci_clear_mwi(struct iegbe_hw *hw)
++void iegbe_pci_clear_mwi(struct iegbe_hw *hw)
+ {
+- struct iegbe_adapter *adapter = hw->back;
++ struct iegbe_adapter *adapter = hw->back;
+
+-#ifdef HAVE_PCI_SET_MWI
+- pci_clear_mwi(adapter->pdev);
+-#else
+- pci_write_config_word(adapter->pdev, PCI_COMMAND,
+- adapter->hw.pci_cmd_word &
+- ~PCI_COMMAND_INVALIDATE);
+-#endif
++ pci_clear_mwi(adapter->pdev);
+ }
+
+ void
+ iegbe_read_pci_cfg(struct iegbe_hw *hw, uint32_t reg, uint16_t *value)
+ {
+- struct iegbe_adapter *adapter = hw->back;
++ struct iegbe_adapter *adapter = hw->back;
+
+- pci_read_config_word(adapter->pdev, reg, value);
++ pci_read_config_word(adapter->pdev, reg, value);
+ }
+
+ void
+ iegbe_write_pci_cfg(struct iegbe_hw *hw, uint32_t reg, uint16_t *value)
+ {
+- struct iegbe_adapter *adapter = hw->back;
++ struct iegbe_adapter *adapter = hw->back;
+
+- pci_write_config_word(adapter->pdev, reg, *value);
++ pci_write_config_word(adapter->pdev, reg, *value);
+ }
+
+ uint32_t
+ iegbe_io_read(struct iegbe_hw *hw, unsigned long port)
+ {
+- return inl(port);
++ return inl(port);
+ }
+
+ void
+ iegbe_io_write(struct iegbe_hw *hw, unsigned long port, uint32_t value)
+ {
+- outl(value, port);
++ outl(value, port);
+ }
+
+-#ifdef NETIF_F_HW_VLAN_TX
+-static void
+-iegbe_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
++static void iegbe_vlan_rx_register(struct net_device *netdev,
++ struct vlan_group *grp)
+ {
+- struct iegbe_adapter *adapter = netdev_priv(netdev);
+- uint32_t ctrl, rctl;
+-
+- iegbe_irq_disable(adapter);
+- adapter->vlgrp = grp;
+-
+- if(grp) {
+- /* enable VLAN tag insert/strip */
+- ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+- ctrl |= E1000_CTRL_VME;
+- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+-
+- /* enable VLAN receive filtering */
+- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+- rctl |= E1000_RCTL_VFE;
+- rctl &= ~E1000_RCTL_CFIEN;
+- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+- iegbe_update_mng_vlan(adapter);
+- } else {
+- /* disable VLAN tag insert/strip */
+- ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+- ctrl &= ~E1000_CTRL_VME;
+- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
++ struct iegbe_adapter *adapter = netdev_priv(netdev);
++ uint32_t ctrl, rctl;
+
+- /* disable VLAN filtering */
+- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+- rctl &= ~E1000_RCTL_VFE;
+- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+- if(adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) {
+- iegbe_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
+- adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
+- }
+- }
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
++ iegbe_irq_disable(adapter);
++ adapter->vlgrp = grp;
++
++ if(grp) {
++ /* enable VLAN tag insert/strip */
++ ctrl = E1000_READ_REG(&adapter->hw, CTRL);
++ ctrl |= E1000_CTRL_VME;
++ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
++
++ /* enable VLAN receive filtering */
++ rctl = E1000_READ_REG(&adapter->hw, RCTL);
++ rctl |= E1000_RCTL_VFE;
++ rctl &= ~E1000_RCTL_CFIEN;
++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
++ iegbe_update_mng_vlan(adapter);
++ } else {
++ /* disable VLAN tag insert/strip */
++ ctrl = E1000_READ_REG(&adapter->hw, CTRL);
++ ctrl &= ~E1000_CTRL_VME;
++ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
++
++ /* disable VLAN filtering */
++ rctl = E1000_READ_REG(&adapter->hw, RCTL);
++ rctl &= ~E1000_RCTL_VFE;
++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
++ if(adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) {
++ iegbe_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
++ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
++ }
++ }
+
+- iegbe_irq_enable(adapter);
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
++ iegbe_irq_enable(adapter);
+ }
+
+-static void
+-iegbe_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
++static void iegbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+ {
+- struct iegbe_adapter *adapter = netdev_priv(netdev);
+- uint32_t vfta, index;
+- if((adapter->hw.mng_cookie.status &
+- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
++ struct iegbe_adapter *adapter = netdev_priv(netdev);
++ uint32_t vfta, index;
++ if((adapter->hw.mng_cookie.status &
++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+ (vid == adapter->mng_vlan_id)) {
+- return;
++ return;
+ }
+- /* add VID to filter table */
++ /* add VID to filter table */
+ index = (vid >> 0x5) & 0x7F;
+- vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
++ vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
+ vfta |= (0x1 << (vid & 0x1F));
+- iegbe_write_vfta(&adapter->hw, index, vfta);
++ iegbe_write_vfta(&adapter->hw, index, vfta);
+ }
+
+-static void
+-iegbe_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
++static void iegbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+ {
+ struct iegbe_adapter *adapter = netdev_priv(netdev);
+- uint32_t vfta, index;
++ u32 vfta, index;
+
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
+ iegbe_irq_disable(adapter);
+-
+- if(adapter->vlgrp) {
+- adapter->vlgrp->vlan_devices[vid] = NULL;
+- }
++ vlan_group_set_device(adapter->vlgrp, vid, NULL);
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
+ iegbe_irq_enable(adapter);
+
+- if((adapter->hw.mng_cookie.status &
+- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+- (vid == adapter->mng_vlan_id)) {
+- return;
+- }
+ /* remove VID from filter table */
+- index = (vid >> 0x5) & 0x7F;
++ index = (vid >> 0x5) & 0x7F;
+ vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
+- vfta &= ~(0x1 << (vid & 0x1F));
++ vfta &= ~(0x1 << (vid & 0x1F));
+ iegbe_write_vfta(&adapter->hw, index, vfta);
+ }
+
+-static void
+-iegbe_restore_vlan(struct iegbe_adapter *adapter)
++static void iegbe_restore_vlan(struct iegbe_adapter *adapter)
+ {
+ iegbe_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+
+- if(adapter->vlgrp) {
+- uint16_t vid;
+- for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+- if(!adapter->vlgrp->vlan_devices[vid]) {
++ if (adapter->vlgrp) {
++ u16 vid;
++ for (vid = 0x0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
++ if (!vlan_group_get_device(adapter->vlgrp, vid))
+ continue;
+- }
+ iegbe_vlan_rx_add_vid(adapter->netdev, vid);
+ }
+ }
+ }
+-#endif
+
+-int
+-iegbe_set_spd_dplx(struct iegbe_adapter *adapter, uint16_t spddplx)
++
++int iegbe_set_spd_dplx(struct iegbe_adapter *adapter, u16 spddplx)
+ {
+- adapter->hw.autoneg = 0;
++ adapter->hw.autoneg = 0x0;
+
+- /* Fiber NICs only allow 1000 gbps Full duplex */
+- if((adapter->hw.media_type == iegbe_media_type_fiber
++ /* Fiber NICs only allow 1000 gbps Full duplex */
++ if((adapter->hw.media_type == iegbe_media_type_fiber
+ || (adapter->hw.media_type == iegbe_media_type_oem
+ && !iegbe_oem_phy_is_copper(&adapter->hw)))
+- && spddplx != (SPEED_1000 + FULL_DUPLEX)) {
+- DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n");
+- return -EINVAL;
+- }
+-
+- switch(spddplx) {
+- case SPEED_10 + HALF_DUPLEX:
+- adapter->hw.forced_speed_duplex = iegbe_10_half;
+- break;
+- case SPEED_10 + FULL_DUPLEX:
+- adapter->hw.forced_speed_duplex = iegbe_10_full;
+- break;
+- case SPEED_100 + HALF_DUPLEX:
+- adapter->hw.forced_speed_duplex = iegbe_100_half;
+- break;
+- case SPEED_100 + FULL_DUPLEX:
+- adapter->hw.forced_speed_duplex = iegbe_100_full;
+- break;
+- case SPEED_1000 + FULL_DUPLEX:
++ && spddplx != (SPEED_1000 + DUPLEX_FULL)) {
++ DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n");
++ return -EINVAL;
++ }
++
++ switch(spddplx) {
++ case SPEED_10 + DUPLEX_HALF:
++ adapter->hw.forced_speed_duplex = iegbe_10_half;
++ break;
++ case SPEED_10 + DUPLEX_FULL:
++ adapter->hw.forced_speed_duplex = iegbe_10_full;
++ break;
++ case SPEED_100 + DUPLEX_HALF:
++ adapter->hw.forced_speed_duplex = iegbe_100_half;
++ break;
++ case SPEED_100 + DUPLEX_FULL:
++ adapter->hw.forced_speed_duplex = iegbe_100_full;
++ break;
++ case SPEED_1000 + DUPLEX_FULL:
+ adapter->hw.autoneg = 0x1;
+- adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
+- break;
+- case SPEED_1000 + HALF_DUPLEX: /* not supported */
+- default:
+- DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n");
+- return -EINVAL;
+- }
+- return 0;
++ adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
++ break;
++ case SPEED_1000 + DUPLEX_HALF: /* not supported */
++ default:
++ DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n");
++ return -EINVAL;
++ }
++ return 0x0;
+ }
+
+ static int
+ iegbe_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
+ {
+- struct pci_dev *pdev = NULL;
++ struct pci_dev *pdev = NULL;
+ pm_message_t state = {0x3};
+
+
+- switch(event) {
+- case SYS_DOWN:
+- case SYS_HALT:
+- case SYS_POWER_OFF:
+- while((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) {
++ switch(event) {
++ case SYS_DOWN:
++ case SYS_HALT:
++ case SYS_POWER_OFF:
++ while((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) {
+ if(pci_dev_driver(pdev) == &iegbe_driver) {
+- iegbe_suspend(pdev, state);
+- }
+- }
++ iegbe_suspend(pdev, state);
++ }
++ }
+ }
+- return NOTIFY_DONE;
++ return NOTIFY_DONE;
+ }
+
+ static int
+ iegbe_suspend(struct pci_dev *pdev, pm_message_t state)
+ {
+- struct net_device *netdev = pci_get_drvdata(pdev);
+- struct iegbe_adapter *adapter = netdev_priv(netdev);
+- uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm;
+- uint32_t wufc = adapter->wol;
+- uint16_t cmd_word;
++ struct net_device *netdev = pci_get_drvdata(pdev);
++ struct iegbe_adapter *adapter = netdev_priv(netdev);
++ uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm;
++ uint32_t wufc = adapter->wol;
++ uint16_t cmd_word;
+
+- netif_device_detach(netdev);
++ netif_device_detach(netdev);
+
+ if(netif_running(netdev)) {
+- iegbe_down(adapter);
++ WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
++ iegbe_down(adapter);
+ }
+- /*
+- * ICP_XXXX style MACs do not have a link up bit in
+- * the STATUS register, query the PHY directly
+- */
+- if(adapter->hw.mac_type != iegbe_icp_xxxx) {
+- status = E1000_READ_REG(&adapter->hw, STATUS);
++ /*
++ * ICP_XXXX style MACs do not have a link up bit in
++ * the STATUS register, query the PHY directly
++ */
++ if(adapter->hw.mac_type != iegbe_icp_xxxx) {
++ status = E1000_READ_REG(&adapter->hw, STATUS);
+ if(status & E1000_STATUS_LU) {
+- wufc &= ~E1000_WUFC_LNKC;
++ wufc &= ~E1000_WUFC_LNKC;
+ }
+- } else {
+- int isUp = 0;
++ } else {
++ int isUp = 0x0;
+ if(iegbe_oem_phy_is_link_up(&adapter->hw, &isUp) != E1000_SUCCESS) {
+- isUp = 0;
++ isUp = 0x0;
+ }
+ if(isUp) {
+- wufc &= ~E1000_WUFC_LNKC;
+- }
++ wufc &= ~E1000_WUFC_LNKC;
++ }
+ }
+
+- if(wufc) {
+- iegbe_setup_rctl(adapter);
+- iegbe_set_multi(netdev);
+-
+- /* turn on all-multi mode if wake on multicast is enabled */
+- if(adapter->wol & E1000_WUFC_MC) {
+- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+- rctl |= E1000_RCTL_MPE;
+- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+- }
++ if(wufc) {
++ iegbe_setup_rctl(adapter);
++ iegbe_set_rx_mode(netdev);
++
++ /* turn on all-multi mode if wake on multicast is enabled */
++ if(adapter->wol & E1000_WUFC_MC) {
++ rctl = E1000_READ_REG(&adapter->hw, RCTL);
++ rctl |= E1000_RCTL_MPE;
++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
++ }
+
+- if(adapter->hw.mac_type >= iegbe_82540) {
+- ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+- /* advertise wake from D3Cold */
+- #define E1000_CTRL_ADVD3WUC 0x00100000
+- /* phy power management enable */
+- ctrl |= E1000_CTRL_ADVD3WUC |
+- (adapter->hw.mac_type != iegbe_icp_xxxx
+- ? E1000_CTRL_EN_PHY_PWR_MGMT : 0);
++ if(adapter->hw.mac_type >= iegbe_82540) {
++ ctrl = E1000_READ_REG(&adapter->hw, CTRL);
++ /* advertise wake from D3Cold */
++ #define E1000_CTRL_ADVD3WUC 0x00100000
++ /* phy power management enable */
++ #define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000
++ ctrl |= E1000_CTRL_ADVD3WUC |
++ (adapter->hw.mac_type != iegbe_icp_xxxx
++ ? E1000_CTRL_EN_PHY_PWR_MGMT : 0x0);
+
+- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+- }
++ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
++ }
+
+- if(adapter->hw.media_type == iegbe_media_type_fiber ||
+- adapter->hw.media_type == iegbe_media_type_internal_serdes) {
+- /* keep the laser running in D3 */
+- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+- ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
+- E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext);
+- }
++ if(adapter->hw.media_type == iegbe_media_type_fiber ||
++ adapter->hw.media_type == iegbe_media_type_internal_serdes) {
++ /* keep the laser running in D3 */
++ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
++ ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
++ E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext);
++ }
+
+ /* Allow OEM PHYs (if any exist) to keep the laser
+ *running in D3 */
+ iegbe_oem_fiber_live_in_suspend(&adapter->hw);
+
+- /* Allow time for pending master requests to run */
+- iegbe_disable_pciex_master(&adapter->hw);
++ /* Allow time for pending master requests to run */
++ iegbe_disable_pciex_master(&adapter->hw);
+
+- E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN);
+- E1000_WRITE_REG(&adapter->hw, WUFC, wufc);
++ E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN);
++ E1000_WRITE_REG(&adapter->hw, WUFC, wufc);
+ pci_enable_wake(pdev, 0x3, 0x1);
+ pci_enable_wake(pdev, 0x4, 0x1); /* 4 == D3 cold */
+- } else {
+- E1000_WRITE_REG(&adapter->hw, WUC, 0);
+- E1000_WRITE_REG(&adapter->hw, WUFC, 0);
+- pci_enable_wake(pdev, 0x3, 0);
+- pci_enable_wake(pdev, 0x4, 0); /* 4 == D3 cold */
+- }
++ } else {
++ E1000_WRITE_REG(&adapter->hw, WUC, 0x0);
++ E1000_WRITE_REG(&adapter->hw, WUFC, 0x0);
++ pci_enable_wake(pdev, 0x3, 0x0);
++ pci_enable_wake(pdev, 0x4, 0x0); /* 4 == D3 cold */
++ }
+
+- pci_save_state(pdev);
+-
+- if(adapter->hw.mac_type >= iegbe_82540
+- && adapter->hw.mac_type != iegbe_icp_xxxx
+- && adapter->hw.media_type == iegbe_media_type_copper) {
+- manc = E1000_READ_REG(&adapter->hw, MANC);
+- if(manc & E1000_MANC_SMBUS_EN) {
+- manc |= E1000_MANC_ARP_EN;
+- E1000_WRITE_REG(&adapter->hw, MANC, manc);
++ pci_save_state(pdev);
++
++ if(adapter->hw.mac_type >= iegbe_82540
++ && adapter->hw.mac_type != iegbe_icp_xxxx
++ && adapter->hw.media_type == iegbe_media_type_copper) {
++ manc = E1000_READ_REG(&adapter->hw, MANC);
++ if(manc & E1000_MANC_SMBUS_EN) {
++ manc |= E1000_MANC_ARP_EN;
++ E1000_WRITE_REG(&adapter->hw, MANC, manc);
+ pci_enable_wake(pdev, 0x3, 0x1);
+ pci_enable_wake(pdev, 0x4, 0x1); /* 4 == D3 cold */
+- }
+- }
++ }
++ }
+
+- switch(adapter->hw.mac_type) {
+- case iegbe_82571:
+- case iegbe_82572:
+- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+- E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+- ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
+- break;
+- case iegbe_82573:
+- swsm = E1000_READ_REG(&adapter->hw, SWSM);
+- E1000_WRITE_REG(&adapter->hw, SWSM,
+- swsm & ~E1000_SWSM_DRV_LOAD);
+- break;
+- default:
+- break;
+- }
++ switch(adapter->hw.mac_type) {
++ case iegbe_82571:
++ case iegbe_82572:
++ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
++ E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
++ ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
++ break;
++ case iegbe_82573:
++ swsm = E1000_READ_REG(&adapter->hw, SWSM);
++ E1000_WRITE_REG(&adapter->hw, SWSM,
++ swsm & ~E1000_SWSM_DRV_LOAD);
++ break;
++ default:
++ break;
++ }
+
+- pci_disable_device(pdev);
+- if(adapter->hw.mac_type == iegbe_icp_xxxx) {
+- /*
+- * ICP xxxx devices are not true PCI devices, in the context
+- * of power management, disabling the bus mastership is not
+- * sufficient to disable the device, it is also necessary to
+- * disable IO, Memory, and Interrupts if they are enabled.
+- */
+- pci_read_config_word(pdev, PCI_COMMAND, &cmd_word);
++ pci_disable_device(pdev);
++ if(adapter->hw.mac_type == iegbe_icp_xxxx) {
++ /*
++ * ICP xxxx devices are not true PCI devices, in the context
++ * of power management, disabling the bus mastership is not
++ * sufficient to disable the device, it is also necessary to
++ * disable IO, Memory, and Interrupts if they are enabled.
++ */
++ pci_read_config_word(pdev, PCI_COMMAND, &cmd_word);
+ if(cmd_word & PCI_COMMAND_IO) {
+- cmd_word &= ~PCI_COMMAND_IO;
++ cmd_word &= ~PCI_COMMAND_IO;
+ }
+ if(cmd_word & PCI_COMMAND_MEMORY) {
+- cmd_word &= ~PCI_COMMAND_MEMORY;
++ cmd_word &= ~PCI_COMMAND_MEMORY;
+ }
+ if(cmd_word & PCI_COMMAND_INTX_DISABLE) {
+- cmd_word &= ~PCI_COMMAND_INTX_DISABLE;
++ cmd_word &= ~PCI_COMMAND_INTX_DISABLE;
+ }
+- pci_write_config_word(pdev, PCI_COMMAND, cmd_word);
+- }
++ pci_write_config_word(pdev, PCI_COMMAND, cmd_word);
++ }
+
+- state.event = (state.event > 0) ? 0x3 : 0;
+- pci_set_power_state(pdev, state.event);
+- if(gcu_suspend == 0)
++ state.event = (state.event > 0x0) ? 0x3 : 0x0;
++ pci_set_power_state(pdev, state.event);
++ if(gcu_suspend == 0x0)
+ {
+ if(gcu == NULL) {
+- gcu = pci_find_device(PCI_VENDOR_ID_INTEL, GCU_DEVID, NULL);
+- }
++ gcu = pci_get_device(PCI_VENDOR_ID_INTEL, GCU_DEVID, NULL);
++ }
+ gcu_iegbe_suspend(gcu, 0x3);
+- gcu_suspend = 1;
+- gcu_resume = 0;
++ gcu_suspend = 0x1;
++ gcu_resume = 0x0;
+ }
+- return 0;
++ return 0x0;
+ }
+
+ #ifdef CONFIG_PM
+ static int
+ iegbe_resume(struct pci_dev *pdev)
+ {
+- struct net_device *netdev = pci_get_drvdata(pdev);
+- struct iegbe_adapter *adapter = netdev_priv(netdev);
+- uint32_t manc, ret_val, swsm;
+- uint32_t ctrl_ext;
++ struct net_device *netdev = pci_get_drvdata(pdev);
++ struct iegbe_adapter *adapter = netdev_priv(netdev);
++ uint32_t manc, ret_val, swsm;
++ uint32_t ctrl_ext;
+ int offset;
+ uint32_t vdid;
+
+- if(gcu_resume == 0)
++ if(gcu_resume == 0x0)
+ {
+ if(gcu == NULL) {
+- gcu = pci_find_device(PCI_VENDOR_ID_INTEL, GCU_DEVID, NULL);
++ gcu = pci_get_device(PCI_VENDOR_ID_INTEL, GCU_DEVID, NULL);
+ pci_read_config_dword(gcu, 0x00, &vdid);
+- }
+-
++ }
++
+ if(gcu) {
+ gcu_iegbe_resume(gcu);
+- gcu_resume = 1;
+- gcu_suspend = 0;
++ gcu_resume = 0x1;
++ gcu_suspend = 0x0;
+ } else {
+ printk("Unable to resume GCU!\n");
+- }
++ }
+ }
+ pci_set_power_state(pdev, 0x0);
+- pci_restore_state(pdev);
+- ret_val = pci_enable_device(pdev);
+- pci_set_master(pdev);
++ pci_restore_state(pdev);
++ ret_val = pci_enable_device(pdev);
++ pci_set_master(pdev);
+
+ pci_enable_wake(pdev, 0x3, 0x0);
+ pci_enable_wake(pdev, 0x4, 0x0); /* 4 == D3 cold */
+
+- iegbe_reset(adapter);
+- E1000_WRITE_REG(&adapter->hw, WUS, ~0);
++ iegbe_reset(adapter);
++ E1000_WRITE_REG(&adapter->hw, WUS, ~0);
+ offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_ST)
+ + PCI_ST_SMIA_OFFSET;
+ pci_write_config_dword(adapter->pdev, offset, 0x00000006);
+@@ -5138,51 +4848,52 @@ iegbe_resume(struct pci_dev *pdev)
+ E1000_WRITE_REG(&adapter->hw, IMC2, ~0UL);
+
+ if(netif_running(netdev)) {
+- iegbe_up(adapter);
++ iegbe_up(adapter);
+ }
+- netif_device_attach(netdev);
+-
+- if(adapter->hw.mac_type >= iegbe_82540
+- && adapter->hw.mac_type != iegbe_icp_xxxx
+- && adapter->hw.media_type == iegbe_media_type_copper) {
+- manc = E1000_READ_REG(&adapter->hw, MANC);
+- manc &= ~(E1000_MANC_ARP_EN);
+- E1000_WRITE_REG(&adapter->hw, MANC, manc);
+- }
++ netif_device_attach(netdev);
+
+- switch(adapter->hw.mac_type) {
+- case iegbe_82571:
+- case iegbe_82572:
+- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+- E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+- ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
+- break;
+- case iegbe_82573:
+- swsm = E1000_READ_REG(&adapter->hw, SWSM);
+- E1000_WRITE_REG(&adapter->hw, SWSM,
+- swsm | E1000_SWSM_DRV_LOAD);
+- break;
+- default:
+- break;
+- }
++ if(adapter->hw.mac_type >= iegbe_82540
++ && adapter->hw.mac_type != iegbe_icp_xxxx
++ && adapter->hw.media_type == iegbe_media_type_copper) {
++ manc = E1000_READ_REG(&adapter->hw, MANC);
++ manc &= ~(E1000_MANC_ARP_EN);
++ E1000_WRITE_REG(&adapter->hw, MANC, manc);
++ }
++
++ switch(adapter->hw.mac_type) {
++ case iegbe_82571:
++ case iegbe_82572:
++ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
++ E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
++ ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
++ break;
++ case iegbe_82573:
++ swsm = E1000_READ_REG(&adapter->hw, SWSM);
++ E1000_WRITE_REG(&adapter->hw, SWSM,
++ swsm | E1000_SWSM_DRV_LOAD);
++ break;
++ default:
++ break;
++ }
++#endif
+
+- return 0;
++ return 0x0;
+ }
+-#endif
++
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ /*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+-static void
+-iegbe_netpoll(struct net_device *netdev)
++static void iegbe_netpoll(struct net_device *netdev)
+ {
+- struct iegbe_adapter *adapter = netdev_priv(netdev);
+- disable_irq(adapter->pdev->irq);
+- iegbe_intr(adapter->pdev->irq, netdev, NULL);
+- enable_irq(adapter->pdev->irq);
++ struct iegbe_adapter *adapter = netdev_priv(netdev);
++ disable_irq(adapter->pdev->irq);
++ iegbe_intr(adapter->pdev->irq, netdev);
++ enable_irq(adapter->pdev->irq);
+ }
+ #endif
+
++
+ /* iegbe_main.c */
+--- a/Embedded/src/GbE/iegbe_oem_phy.c
++++ b/Embedded/src/GbE/iegbe_oem_phy.c
+@@ -2,31 +2,31 @@
+
+ GPL LICENSE SUMMARY
+
+- Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+
+- This program is free software; you can redistribute it and/or modify
++ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License 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
++ 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
++ 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+- The full GNU General Public License is included in this distribution
++ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ Contact Information:
+ Intel Corporation
+
+- version: Embedded.L.1.0.34
++ version: Embedded.Release.Patch.L.1.0.7-5
+
+ Contact Information:
+
+- Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226
++ Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226
+
+ *****************************************************************************/
+ /**************************************************************************
+@@ -65,11 +65,6 @@ static int32_t iegbe_oem_link_m88_setup(
+ static int32_t iegbe_oem_set_phy_mode(struct iegbe_hw *hw);
+ static int32_t iegbe_oem_detect_phy(struct iegbe_hw *hw);
+
+-/* Define specific BCM functions */
+-static int32_t iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw);
+-static int32_t bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data);
+-static int32_t oi_phy_setup (struct iegbe_hw *hw);
+-
+ /**
+ * iegbe_oem_setup_link
+ * @hw: iegbe_hw struct containing device specific information
+@@ -84,7 +79,7 @@ iegbe_oem_setup_link(struct iegbe_hw *hw
+ {
+ #ifdef EXTERNAL_MDIO
+
+- /*
++ /*
+ * see iegbe_setup_copper_link() as the primary example. Look at both
+ * the M88 and IGP functions that are called for ideas, possibly for
+ * power management.
+@@ -102,14 +97,14 @@ iegbe_oem_setup_link(struct iegbe_hw *hw
+ }
+ /* AFU: add test to exit out if improper phy type
+ */
+- /* relevent parts of iegbe_copper_link_preconfig */
+- ctrl = E1000_READ_REG(hw, CTRL);
+- ctrl |= E1000_CTRL_SLU;
+- ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+- E1000_WRITE_REG(hw, CTRL, ctrl);
+-
++ /* relevent parts of iegbe_copper_link_preconfig */
++ ctrl = E1000_READ_REG(hw, CTRL);
++ ctrl |= E1000_CTRL_SLU;
++ ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
++ E1000_WRITE_REG(hw, CTRL, ctrl);
++
+ /* this is required for *hw init */
+- ret_val = iegbe_oem_detect_phy(hw);
++ ret_val = iegbe_oem_detect_phy(hw);
+ if(ret_val) {
+ return ret_val;
+ }
+@@ -119,23 +114,13 @@ iegbe_oem_setup_link(struct iegbe_hw *hw
+ }
+
+ switch (hw->phy_id) {
+- case BCM5395S_PHY_ID:
+- return E1000_SUCCESS;
+- break;
+-
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+ ret_val = iegbe_oem_link_m88_setup(hw);
+- if(ret_val) {
+- return ret_val;
+- }
+- break;
+- case BCM5481_PHY_ID:
+- ret_val = iegbe_oem_link_bcm5481_setup(hw);
+- if(ret_val) {
+- return ret_val;
++ if(ret_val) {
++ return ret_val;
+ }
+- break;
++ break;
+ default:
+ DEBUGOUT("Invalid PHY ID\n");
+ return -E1000_ERR_PHY_TYPE;
+@@ -143,16 +128,16 @@ iegbe_oem_setup_link(struct iegbe_hw *hw
+
+ if(hw->autoneg) {
+ ret_val = iegbe_copper_link_autoneg(hw);
+- if(ret_val) {
+- return ret_val;
+- }
++ if(ret_val) {
++ return ret_val;
+ }
++ }
+ else {
+ DEBUGOUT("Forcing speed and duplex\n");
+ ret_val = iegbe_phy_force_speed_duplex(hw);
+ }
+-
+- /*
++
++ /*
+ * Check link status. Wait up to 100 microseconds for link to become
+ * valid.
+ */
+@@ -194,51 +179,6 @@ iegbe_oem_setup_link(struct iegbe_hw *hw
+ #endif /* ifdef EXTERNAL_MDIO */
+ }
+
+-/**
+- * iegbe_oem_link_bcm5481_setup
+- * @hw: iegbe_hw struct containing device specific information
+- *
+- * Returns E1000_SUCCESS, negative E1000 error code on failure
+- *
+- * copied verbatim from iegbe_oem_link_m88_setup
+- **/
+-static int32_t
+-iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw)
+-{
+- int32_t ret_val;
+- uint16_t phy_data;
+-
+- //DEBUGFUNC(__func__);
+-
+- if(!hw)
+- return -1;
+-
+- /* phy_reset_disable is set in iegbe_oem_set_phy_mode */
+- if(hw->phy_reset_disable)
+- return E1000_SUCCESS;
+-
+- // Enable MDIX in extended control reg.
+- ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ECTRL, &phy_data);
+- if(ret_val)
+- {
+- DEBUGOUT("Unable to read BCM5481_ECTRL register\n");
+- return ret_val;
+- }
+-
+- phy_data &= ~BCM5481_ECTRL_DISMDIX;
+- ret_val = iegbe_oem_write_phy_reg_ex(hw, BCM5481_ECTRL, phy_data);
+- if(ret_val)
+- {
+- DEBUGOUT("Unable to write BCM5481_ECTRL register\n");
+- return ret_val;
+- }
+-
+- ret_val = oi_phy_setup (hw);
+- if (ret_val)
+- return ret_val;
+-
+- return E1000_SUCCESS;
+-}
+
+ /**
+ * iegbe_oem_link_m88_setup
+@@ -253,7 +193,7 @@ static int32_t
+ iegbe_oem_link_m88_setup(struct iegbe_hw *hw)
+ {
+ int32_t ret_val;
+- uint16_t phy_data;
++ uint16_t phy_data = 0;
+
+ DEBUGFUNC1("%s",__func__);
+
+@@ -261,7 +201,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw
+ return -1;
+ }
+
+- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL,
++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL,
+ &phy_data);
+ phy_data |= 0x00000008;
+ ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+@@ -279,7 +219,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw
+
+ phy_data &= ~M88E1000_PSCR_ASSERT_CRS_ON_TX;
+
+- /*
++ /*
+ * Options:
+ * MDI/MDI-X = 0 (default)
+ * 0 - Auto for all speeds
+@@ -305,7 +245,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw
+ break;
+ }
+
+- /*
++ /*
+ * Options:
+ * disable_polarity_correction = 0 (default)
+ * Automatic Correction for Reversed Cable Polarity
+@@ -316,25 +256,25 @@ iegbe_oem_link_m88_setup(struct iegbe_hw
+
+ if(hw->disable_polarity_correction == 1) {
+ phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
+- }
++ }
+ ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+ if(ret_val) {
+ DEBUGOUT("Unable to write M88E1000_PHY_SPEC_CTRL register\n");
+ return ret_val;
+ }
+
+- /*
++ /*
+ * Force TX_CLK in the Extended PHY Specific Control Register
+ * to 25MHz clock.
+ */
+- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_EXT_PHY_SPEC_CTRL,
++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_EXT_PHY_SPEC_CTRL,
+ &phy_data);
+ if(ret_val) {
+ DEBUGOUT("Unable to read M88E1000_EXT_PHY_SPEC_CTRL register\n");
+ return ret_val;
+ }
+
+- /*
++ /*
+ * For Truxton, it is necessary to add RGMII tx and rx
+ * timing delay though the EXT_PHY_SPEC_CTRL register
+ */
+@@ -350,13 +290,13 @@ iegbe_oem_link_m88_setup(struct iegbe_hw
+ phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
+ M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
+ }
+- ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_EXT_PHY_SPEC_CTRL,
++ ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_EXT_PHY_SPEC_CTRL,
+ phy_data);
+ if(ret_val) {
+ DEBUGOUT("Unable to read M88E1000_EXT_PHY_SPEC_CTRL register\n");
+ return ret_val;
+ }
+-
++
+
+ /* SW Reset the PHY so all changes take effect */
+ ret_val = iegbe_phy_hw_reset(hw);
+@@ -371,7 +311,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw
+ /**
+ * iegbe_oem_force_mdi
+ * @hw: iegbe_hw struct containing device specific information
+- * @resetPhy: returns true if after calling this function the
++ * @resetPhy: returns true if after calling this function the
+ * PHY requires a reset
+ *
+ * Returns E1000_SUCCESS, negative E1000 error code on failure
+@@ -379,7 +319,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw
+ * This is called from iegbe_phy_force_speed_duplex, which is
+ * called from iegbe_oem_setup_link.
+ **/
+-int32_t
++int32_t
+ iegbe_oem_force_mdi(struct iegbe_hw *hw, int *resetPhy)
+ {
+ #ifdef EXTERNAL_MDIO
+@@ -393,35 +333,30 @@ iegbe_oem_force_mdi(struct iegbe_hw *hw,
+ return -1;
+ }
+
+- /*
++ /*
+ * a boolean to indicate if the phy needs to be reset
+- *
++ *
+ * Make note that the M88 phy is what'll be used on Truxton
+ * see iegbe_phy_force_speed_duplex, which does the following for M88
+ */
+ switch (hw->phy_id) {
+- case BCM5395S_PHY_ID:
+- case BCM5481_PHY_ID:
+- DEBUGOUT("WARNING: An empty iegbe_oem_force_mdi() has been called!\n");
+- break;
+-
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+- ret_val = iegbe_oem_read_phy_reg_ex(hw,
+- M88E1000_PHY_SPEC_CTRL,
++ ret_val = iegbe_oem_read_phy_reg_ex(hw,
++ M88E1000_PHY_SPEC_CTRL,
+ &phy_data);
+ if(ret_val) {
+ DEBUGOUT("Unable to read M88E1000_PHY_SPEC_CTRL register\n");
+ return ret_val;
+ }
+-
++
+ /*
+- * Clear Auto-Crossover to force MDI manually. M88E1000 requires
++ * Clear Auto-Crossover to force MDI manually. M88E1000 requires
+ * MDI forced whenever speed are duplex are forced.
+ */
+-
++
+ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
+- ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL,
++ ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL,
+ phy_data);
+ if(ret_val) {
+ DEBUGOUT("Unable to write M88E1000_PHY_SPEC_CTRL register\n");
+@@ -458,7 +393,7 @@ iegbe_oem_force_mdi(struct iegbe_hw *hw,
+ * This is called from iegbe_phy_force_speed_duplex, which is
+ * called from iegbe_oem_setup_link.
+ **/
+-int32_t
++int32_t
+ iegbe_oem_phy_reset_dsp(struct iegbe_hw *hw)
+ {
+ #ifdef EXTERNAL_MDIO
+@@ -478,10 +413,8 @@ iegbe_oem_phy_reset_dsp(struct iegbe_hw
+ * no-op.
+ */
+ switch (hw->phy_id) {
+- case M88E1000_I_PHY_ID:
+- case M88E1141_E_PHY_ID:
+- case BCM5481_PHY_ID:
+- case BCM5395S_PHY_ID:
++ case M88E1000_I_PHY_ID:
++ case M88E1141_E_PHY_ID:
+ DEBUGOUT("No DSP to reset on OEM PHY\n");
+ break;
+ default:
+@@ -508,7 +441,7 @@ iegbe_oem_phy_reset_dsp(struct iegbe_hw
+ * This is called from iegbe_phy_force_speed_duplex, which is
+ * called from iegbe_oem_setup_link.
+ **/
+-int32_t
++int32_t
+ iegbe_oem_cleanup_after_phy_reset(struct iegbe_hw *hw)
+ {
+ #ifdef EXTERNAL_MDIO
+@@ -520,29 +453,24 @@ iegbe_oem_cleanup_after_phy_reset(struct
+
+ if(!hw) {
+ return -1;
+- }
++ }
+
+- /*
++ /*
+ * Make note that the M88 phy is what'll be used on Truxton.
+ * see iegbe_phy_force_speed_duplex, which does the following for M88
+ */
+ switch (hw->phy_id) {
+- case BCM5395S_PHY_ID:
+- case BCM5481_PHY_ID:
+- DEBUGOUT("WARNING: An empty iegbe_oem_cleanup_after_phy_reset() has been called!\n");
+- break;
+-
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+ /*
+- * Because we reset the PHY above, we need to re-force
++ * Because we reset the PHY above, we need to re-force
+ * TX_CLK in the Extended PHY Specific Control Register to
+ * 25MHz clock. This value defaults back to a 2.5MHz clock
+ * when the PHY is reset.
+ */
+
+ ret_val = iegbe_oem_read_phy_reg_ex(hw,
+- M88E1000_EXT_PHY_SPEC_CTRL,
++ M88E1000_EXT_PHY_SPEC_CTRL,
+ &phy_data);
+ if(ret_val) {
+ DEBUGOUT("Unable to read M88E1000_EXT_SPEC_CTRL register\n");
+@@ -550,22 +478,23 @@ iegbe_oem_cleanup_after_phy_reset(struct
+ }
+
+ phy_data |= M88E1000_EPSCR_TX_CLK_25;
+- ret_val = iegbe_oem_write_phy_reg_ex(hw,
+- M88E1000_EXT_PHY_SPEC_CTRL,
++ ret_val = iegbe_oem_write_phy_reg_ex(hw,
++ M88E1000_EXT_PHY_SPEC_CTRL,
+ phy_data);
+ if(ret_val) {
+- DEBUGOUT("Unable to write M88E1000_EXT_PHY_SPEC_CTRL register\n");
++ DEBUGOUT("Unable to write M88E1000_EXT_PHY_SPEC_CTRL "
++ "register\n");
+ return ret_val;
+ }
+
+ /*
+ * In addition, because of the s/w reset above, we need to enable
+- * CRX on TX. This must be set for both full and half duplex
++ * CRX on TX. This must be set for both full and half duplex
+ * operation.
+ */
+
+- ret_val = iegbe_oem_read_phy_reg_ex(hw,
+- M88E1000_PHY_SPEC_CTRL,
++ ret_val = iegbe_oem_read_phy_reg_ex(hw,
++ M88E1000_PHY_SPEC_CTRL,
+ &phy_data);
+ if(ret_val) {
+ DEBUGOUT("Unable to read M88E1000_PHY_SPEC_CTRL register\n");
+@@ -573,12 +502,12 @@ iegbe_oem_cleanup_after_phy_reset(struct
+ }
+
+ phy_data &= ~M88E1000_PSCR_ASSERT_CRS_ON_TX;
+- ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL,
++ ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL,
+ phy_data);
+ if(ret_val) {
+ DEBUGOUT("Unable to write M88E1000_PHY_SPEC_CTRL register\n");
+ return ret_val;
+- }
++ }
+ break;
+ default:
+ DEBUGOUT("Invalid PHY ID\n");
+@@ -604,12 +533,12 @@ iegbe_oem_cleanup_after_phy_reset(struct
+ * This is called from iegbe_oem_setup_link which is
+ * called from iegbe_setup_link.
+ **/
+-static int32_t
++static int32_t
+ iegbe_oem_set_phy_mode(struct iegbe_hw *hw)
+ {
+ /*
+ * it is unclear if it is necessary to set the phy mode. Right now only
+- * one MAC 82545 Rev 3 does it, but the other MACs like Tolapai do not.
++ * one MAC 82545 Rev 3 does it, but the other MACs like tola do not.
+ * Leave the functionality off for now until it is determined that Tolapai
+ * needs it as well.
+ */
+@@ -638,41 +567,37 @@ iegbe_oem_set_phy_mode(struct iegbe_hw *
+ #ifndef skip_set_mode
+ DEBUGOUT("No need to call oem_set_phy_mode on Truxton\n");
+ #else
+- /*
++ /*
+ * Make note that the M88 phy is what'll be used on Truxton.
+ *
+ * use iegbe_set_phy_mode as example
+ */
+ switch (hw->phy_id) {
+- case BCM5395S_PHY_ID:
+- case BCM5481_PHY_ID:
+- DEBUGOUT("WARNING: An empty iegbe_oem_set_phy_mode() has been called!\n");
+- break;
+-
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+- ret_val = iegbe_read_eeprom(hw,
+- EEPROM_PHY_CLASS_WORD,
+- 1,
++ ret_val = iegbe_read_eeprom(hw,
++ EEPROM_PHY_CLASS_WORD,
++ 1,
+ &eeprom_data);
+ if(ret_val) {
+ return ret_val;
+ }
+
+- if((eeprom_data != EEPROM_RESERVED_WORD) &&
+- (eeprom_data & EEPROM_PHY_CLASS_A))
++ if((eeprom_data != EEPROM_RESERVED_WORD) &&
++ (eeprom_data & EEPROM_PHY_CLASS_A))
+ {
+- ret_val = iegbe_oem_write_phy_reg_ex(hw,
+- M88E1000_PHY_PAGE_SELECT,
+- 0x000B);
++ ret_val = iegbe_oem_write_phy_reg_ex(hw,
++ M88E1000_PHY_PAGE_SELECT,
++ 0x000B);
+ if(ret_val) {
+- DEBUGOUT("Unable to write to M88E1000_PHY_PAGE_SELECT register on PHY\n");
++ DEBUGOUT("Unable to write to M88E1000_PHY_PAGE_SELECT "
++ "register on PHY\n");
+ return ret_val;
+ }
+
+- ret_val = iegbe_oem_write_phy_reg_ex(hw,
+- M88E1000_PHY_GEN_CONTROL,
+- 0x8104);
++ ret_val = iegbe_oem_write_phy_reg_ex(hw,
++ M88E1000_PHY_GEN_CONTROL,
++ 0x8104);
+ if(ret_val) {
+ DEBUGOUT("Unable to write to M88E1000_PHY_GEN_CONTROL"
+ "register on PHY\n");
+@@ -687,11 +612,12 @@ iegbe_oem_set_phy_mode(struct iegbe_hw *
+ return -E1000_ERR_PHY_TYPE;
+ }
+ #endif
+-
++
+ return E1000_SUCCESS;
+
+ }
+
++
+ /**
+ * iegbe_oem_detect_phy
+ * @hw: iegbe_hw struct containing device specific information
+@@ -702,7 +628,7 @@ iegbe_oem_set_phy_mode(struct iegbe_hw *
+ *
+ * This borrows heavily from iegbe_detect_gig_phy
+ **/
+-static int32_t
++static int32_t
+ iegbe_oem_detect_phy(struct iegbe_hw *hw)
+ {
+ int32_t ret_val;
+@@ -715,33 +641,20 @@ iegbe_oem_detect_phy(struct iegbe_hw *hw
+ }
+ hw->phy_type = iegbe_phy_oem;
+
+-{
+- // If MAC2 (BCM5395 switch), manually detect the phy
+- struct iegbe_adapter *adapter;
+- uint32_t device_number;
+- adapter = (struct iegbe_adapter *) hw->back;
+- device_number = PCI_SLOT(adapter->pdev->devfn);
+- if (device_number == ICP_XXXX_MAC_2) {
+- hw->phy_id = BCM5395S_PHY_ID;
+- hw->phy_revision = 0;
+- return E1000_SUCCESS;
+- }
+-}
+-
+-
+ ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_ID1, &phy_id_high);
+ if(ret_val) {
+ DEBUGOUT("Unable to read PHY register PHY_ID1\n");
+ return ret_val;
+ }
+-
++
+ usec_delay(0x14);
+ ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_ID2, &phy_id_low);
+ if(ret_val) {
+ DEBUGOUT("Unable to read PHY register PHY_ID2\n");
+ return ret_val;
+ }
+- hw->phy_id = (uint32_t) ((phy_id_high << 0x10) + phy_id_low);
++ hw->phy_id = (uint32_t) ((phy_id_high << 0x10) +
++ (phy_id_low & PHY_REVISION_MASK));
+ hw->phy_revision = (uint32_t) phy_id_low & ~PHY_REVISION_MASK;
+
+ return E1000_SUCCESS;
+@@ -753,15 +666,15 @@ iegbe_oem_detect_phy(struct iegbe_hw *hw
+ * @hw: iegbe_hw struct containing device specific information
+ *
+ * Returns the value of the Inter Packet Gap (IPG) Transmit Time (IPGT) in the
+- * Transmit IPG register appropriate for the given PHY. This field is only 10
++ * Transmit IPG register appropriate for the given PHY. This field is only 10
+ * bits wide.
+ *
+ * In the original iegbe code, only the IPGT field varied between media types.
+- * If the OEM phy requires setting IPG Receive Time 1 & 2 Registers, it would
++ * If the OEM phy requires setting IPG Receive Time 1 & 2 Registers, it would
+ * be required to modify the iegbe_config_tx() function to accomdate the change
+ *
+ **/
+-uint32_t
++uint32_t
+ iegbe_oem_get_tipg(struct iegbe_hw *hw)
+ {
+ #ifdef EXTERNAL_MDIO
+@@ -777,15 +690,13 @@ iegbe_oem_get_tipg(struct iegbe_hw *hw)
+ switch (hw->phy_id) {
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+- case BCM5481_PHY_ID:
+- case BCM5395S_PHY_ID:
+ phy_num = DEFAULT_ICP_XXXX_TIPG_IPGT;
+ break;
+ default:
+ DEBUGOUT("Invalid PHY ID\n");
+ return DEFAULT_ICP_XXXX_TIPG_IPGT;
+ }
+-
++
+ return phy_num;
+
+ #else /* ifdef EXTERNAL_MDIO */
+@@ -803,15 +714,15 @@ iegbe_oem_get_tipg(struct iegbe_hw *hw)
+ * iegbe_oem_phy_is_copper
+ * @hw: iegbe_hw struct containing device specific information
+ *
+- * Test for media type within the iegbe driver is common, so this is a simple
+- * test for copper PHYs. The ICP_XXXX family of controllers initially only
+- * supported copper interconnects (no TBI (ten bit interface) for Fiber
+- * existed). If future revs support either Fiber or an internal SERDES, it
+- * may become necessary to evaluate where this function is used to go beyond
++ * Test for media type within the iegbe driver is common, so this is a simple
++ * test for copper PHYs. The ICP_XXXX family of controllers initially only
++ * supported copper interconnects (no TBI (ten bit interface) for Fiber
++ * existed). If future revs support either Fiber or an internal SERDES, it
++ * may become necessary to evaluate where this function is used to go beyond
+ * determining whether or not media type is just copper.
+ *
+ **/
+-int
++int
+ iegbe_oem_phy_is_copper(struct iegbe_hw *hw)
+ {
+ #ifdef EXTERNAL_MDIO
+@@ -827,23 +738,21 @@ iegbe_oem_phy_is_copper(struct iegbe_hw
+ switch (hw->phy_id) {
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+- case BCM5481_PHY_ID:
+- case BCM5395S_PHY_ID:
+ isCopper = TRUE;
+ break;
+ default:
+ DEBUGOUT("Invalid PHY ID\n");
+ return -E1000_ERR_PHY_TYPE;
+ }
+-
++
+ return isCopper;
+
+ #else /* ifdef EXTERNAL_MDIO */
+
+- /*
++ /*
+ * caught between returning true or false. True allows it to
+ * be entered into && statements w/o ill effect, but false
+- * would make more sense
++ * would make more sense
+ */
+ DEBUGOUT("Invalid value for transceiver type, return FALSE\n");
+ return FALSE;
+@@ -856,19 +765,19 @@ iegbe_oem_phy_is_copper(struct iegbe_hw
+ * iegbe_oem_get_phy_dev_number
+ * @hw: iegbe_hw struct containing device specific information
+ *
+- * For ICP_XXXX family of devices, there are 3 MACs, each of which may
+- * have a different PHY (and indeed a different media interface). This
+- * function is used to indicate which of the MAC/PHY pairs we are interested
++ * For ICP_XXXX family of devices, there are 3 MACs, each of which may
++ * have a different PHY (and indeed a different media interface). This
++ * function is used to indicate which of the MAC/PHY pairs we are interested
+ * in.
+- *
++ *
+ **/
+-uint32_t
++uint32_t
+ iegbe_oem_get_phy_dev_number(struct iegbe_hw *hw)
+ {
+ #ifdef EXTERNAL_MDIO
+
+- /*
+- * for ICP_XXXX family of devices, the three network interfaces are
++ /*
++ * for ICP_XXXX family of devices, the three network interfaces are
+ * differentiated by their PCI device number, where the three share
+ * the same PCI bus
+ */
+@@ -886,15 +795,15 @@ iegbe_oem_get_phy_dev_number(struct iegb
+
+ switch(device_number)
+ {
+- case ICP_XXXX_MAC_0:
++ case ICP_XXXX_MAC_0:
++ hw->phy_addr = 0x00;
++ break;
++ case ICP_XXXX_MAC_1:
+ hw->phy_addr = 0x01;
+ break;
+- case ICP_XXXX_MAC_1:
++ case ICP_XXXX_MAC_2:
+ hw->phy_addr = 0x02;
+ break;
+- case ICP_XXXX_MAC_2:
+- hw->phy_addr = 0x00;
+- break;
+ default: hw->phy_addr = 0x00;
+ }
+ return hw->phy_addr;
+@@ -915,7 +824,7 @@ iegbe_oem_get_phy_dev_number(struct iegb
+ * @cmd: the original IOCTL command that instigated the call chain.
+ *
+ * This function abstracts out the code necessary to service the
+- * SIOCSMIIREG case within the iegbe_mii_ioctl() for oem PHYs.
++ * SIOCSMIIREG case within the iegbe_mii_ioctl() for oem PHYs.
+ * iegbe_mii_ioctl() was implemented for copper phy's only and this
+ * function will only be called if iegbe_oem_phy_is_copper() returns true for
+ * a given MAC. Note that iegbe_mii_ioctl() has a compile flag
+@@ -924,14 +833,14 @@ iegbe_oem_get_phy_dev_number(struct iegb
+ * NOTE: a spinlock is in effect for the duration of this call. It is
+ * imperative that a negative value be returned on any error, so
+ * the spinlock can be released properly.
+- *
++ *
+ **/
+ int
+ iegbe_oem_mii_ioctl(struct iegbe_adapter *adapter, unsigned long flags,
+ struct ifreq *ifr, int cmd)
+ {
+ #ifdef EXTERNAL_MDIO
+-
++
+ struct mii_ioctl_data *data = if_mii(ifr);
+ uint16_t mii_reg = data->val_in;
+ uint16_t spddplx;
+@@ -942,12 +851,6 @@ iegbe_oem_mii_ioctl(struct iegbe_adapter
+ if(!adapter || !ifr) {
+ return -1;
+ }
+-
+- // If MAC2 (BCM5395 switch) then leave now
+- if ((PCI_SLOT(adapter->pdev->devfn)) == ICP_XXXX_MAC_2) {
+- return -1;
+- }
+-
+ switch (data->reg_num) {
+ case PHY_CTRL:
+ if(mii_reg & MII_CR_POWER_DOWN) {
+@@ -956,7 +859,7 @@ iegbe_oem_mii_ioctl(struct iegbe_adapter
+ if(mii_reg & MII_CR_AUTO_NEG_EN) {
+ adapter->hw.autoneg = 1;
+ adapter->hw.autoneg_advertised = ICP_XXXX_AUTONEG_ADV_DEFAULT;
+- }
++ }
+ else {
+ if(mii_reg & 0x40) {
+ spddplx = SPEED_1000;
+@@ -976,7 +879,7 @@ iegbe_oem_mii_ioctl(struct iegbe_adapter
+ if(netif_running(adapter->netdev)) {
+ iegbe_down(adapter);
+ iegbe_up(adapter);
+- }
++ }
+ else {
+ iegbe_reset(adapter);
+ }
+@@ -1043,10 +946,10 @@ void iegbe_oem_fiber_live_in_suspend(str
+ * Note: The call to iegbe_get_regs() assumed an array of 24 elements
+ * where the last 11 are passed to this function. If the array
+ * that is passed to the calling function has its size or element
+- * defintions changed, this function becomes broken.
++ * defintions changed, this function becomes broken.
+ *
+ **/
+-void iegbe_oem_get_phy_regs(struct iegbe_adapter *adapter, uint32_t *data,
++void iegbe_oem_get_phy_regs(struct iegbe_adapter *adapter, uint32_t *data,
+ uint32_t data_len)
+ {
+ #define EXPECTED_ARRAY_LEN 11
+@@ -1062,13 +965,13 @@ void iegbe_oem_get_phy_regs(struct iegbe
+ * Use the corrected_length variable to make sure we don't exceed that
+ * length
+ */
+- corrected_len = data_len>EXPECTED_ARRAY_LEN
++ corrected_len = data_len>EXPECTED_ARRAY_LEN
+ ? EXPECTED_ARRAY_LEN : data_len;
+ memset(data, 0, corrected_len*sizeof(uint32_t));
+
+ #ifdef EXTERNAL_MDIO
+
+- /*
++ /*
+ * Fill data[] with...
+ *
+ * [0] = cable length
+@@ -1084,16 +987,11 @@ void iegbe_oem_get_phy_regs(struct iegbe
+ * [10] = mdix mode
+ */
+ switch (adapter->hw.phy_id) {
+- case BCM5395S_PHY_ID:
+- case BCM5481_PHY_ID:
+- DEBUGOUT("WARNING: An empty iegbe_oem_get_phy_regs() has been called!\n");
+- break;
+-
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+ if(corrected_len > 0) {
+- iegbe_oem_read_phy_reg_ex(&adapter->hw,
+- M88E1000_PHY_SPEC_STATUS,
++ iegbe_oem_read_phy_reg_ex(&adapter->hw,
++ M88E1000_PHY_SPEC_STATUS,
+ (uint16_t *) &data[0]);
+ }
+ if(corrected_len > 0x1){
+@@ -1106,7 +1004,7 @@ void iegbe_oem_get_phy_regs(struct iegbe
+ data[0x3] = 0x0; /* Dummy (to align w/ IGP phy reg dump) */
+ }
+ if(corrected_len > 0x4) {
+- iegbe_oem_read_phy_reg_ex(&adapter->hw, M88E1000_PHY_SPEC_CTRL,
++ iegbe_oem_read_phy_reg_ex(&adapter->hw, M88E1000_PHY_SPEC_CTRL,
+ (uint16_t *) &data[0x4]);
+ }
+ if(corrected_len > 0x5) {
+@@ -1144,7 +1042,7 @@ void iegbe_oem_get_phy_regs(struct iegbe
+ * This is called from iegbe_set_phy_loopback in response from call from
+ * ethtool to place the PHY into loopback mode.
+ **/
+-int
++int
+ iegbe_oem_phy_loopback(struct iegbe_adapter *adapter)
+ {
+ #ifdef EXTERNAL_MDIO
+@@ -1165,23 +1063,18 @@ iegbe_oem_phy_loopback(struct iegbe_adap
+ * was that nonintegrated called iegbe_phy_reset_clk_and_crs(),
+ * hopefully this won't matter as CRS required for half-duplex
+ * operation and this is set to full duplex.
+- *
++ *
+ * Make note that the M88 phy is what'll be used on Truxton
+ * Loopback configuration is the same for each of the supported PHYs.
+ */
+ switch (adapter->hw.phy_id) {
+- case BCM5395S_PHY_ID:
+- DEBUGOUT("WARNING: An empty iegbe_oem_phy_loopback() has been called!\n");
+- break;
+-
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+- case BCM5481_PHY_ID:
+
+ adapter->hw.autoneg = FALSE;
+
+ /* turn off Auto-MDI/MDIX */
+- /*ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw,
++ /*ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw,
+ M88E1000_PHY_SPEC_CTRL, 0x0808);
+ if(ret_val)
+ {
+@@ -1206,10 +1099,10 @@ iegbe_oem_phy_loopback(struct iegbe_adap
+ DEBUGOUT("Unable to write to register PHY_CTRL\n");
+ return ret_val;
+ }
+-
+-
++
++
+ /* force 1000, set loopback */
+- /*ret_val =
++ /*ret_val =
+ iegbe_oem_write_phy_reg_ex(&adapter->hw, PHY_CTRL, 0x4140); */
+ ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw, PHY_CTRL, 0x6100);
+ if(ret_val) {
+@@ -1228,21 +1121,21 @@ iegbe_oem_phy_loopback(struct iegbe_adap
+ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg);
+
+ /*
+- * Write out to PHY registers 29 and 30 to disable the Receiver.
++ * Write out to PHY registers 29 and 30 to disable the Receiver.
+ * This directly lifted from iegbe_phy_disable_receiver().
+- *
++ *
+ * The code is currently commented out as for the M88 used in
+ * Truxton, registers 29 and 30 are unutilized. Leave in, just
+- * in case we are on the receiving end of an 'undocumented'
++ * in case we are on the receiving end of an 'undocumented'
+ * feature
+ */
+- /*
++ /*
+ * iegbe_oem_write_phy_reg_ex(&adapter->hw, 29, 0x001F);
+ * iegbe_oem_write_phy_reg_ex(&adapter->hw, 30, 0x8FFC);
+ * iegbe_oem_write_phy_reg_ex(&adapter->hw, 29, 0x001A);
+ * iegbe_oem_write_phy_reg_ex(&adapter->hw, 30, 0x8FF0);
+ */
+-
++
+ break;
+ default:
+ DEBUGOUT("Invalid PHY ID\n");
+@@ -1268,15 +1161,15 @@ iegbe_oem_phy_loopback(struct iegbe_adap
+ * ethtool to place the PHY out of loopback mode. This handles the OEM
+ * specific part of loopback cleanup.
+ **/
+-void
++void
+ iegbe_oem_loopback_cleanup(struct iegbe_adapter *adapter)
+ {
+ #ifdef EXTERNAL_MDIO
+
+- /*
+- * This borrows liberally from iegbe_loopback_cleanup().
++ /*
++ * This borrows liberally from iegbe_loopback_cleanup().
+ * making note that the M88 phy is what'll be used on Truxton
+- *
++ *
+ * Loopback cleanup is the same for all supported PHYs.
+ */
+ int32_t ret_val;
+@@ -1289,38 +1182,32 @@ iegbe_oem_loopback_cleanup(struct iegbe_
+ }
+
+ switch (adapter->hw.phy_id) {
+- case BCM5395S_PHY_ID:
+- DEBUGOUT("WARNING: An empty iegbe_oem_loopback_cleanup() has been called!\n");
+- return;
+- break;
+-
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+- case BCM5481_PHY_ID:
+ default:
+ adapter->hw.autoneg = TRUE;
+-
+- ret_val = iegbe_oem_read_phy_reg_ex(&adapter->hw, PHY_CTRL,
++
++ ret_val = iegbe_oem_read_phy_reg_ex(&adapter->hw, PHY_CTRL,
+ &phy_reg);
+ if(ret_val) {
+ DEBUGOUT("Unable to read to register PHY_CTRL\n");
+ return;
+ }
+-
++
+ if(phy_reg & MII_CR_LOOPBACK) {
+ phy_reg &= ~MII_CR_LOOPBACK;
+-
+- ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw, PHY_CTRL,
++
++ ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw, PHY_CTRL,
+ phy_reg);
+ if(ret_val) {
+ DEBUGOUT("Unable to write to register PHY_CTRL\n");
+ return;
+ }
+-
++
+ iegbe_phy_reset(&adapter->hw);
+ }
+ }
+-
++
+ #endif /* ifdef EXTERNAL_MDIO */
+ return;
+
+@@ -1336,7 +1223,7 @@ iegbe_oem_loopback_cleanup(struct iegbe_
+ * Called by iegbe_check_downshift(), checks the PHY to see if it running
+ * at as speed slower than its maximum.
+ **/
+-uint32_t
++uint32_t
+ iegbe_oem_phy_speed_downgraded(struct iegbe_hw *hw, uint16_t *isDowngraded)
+ {
+ #ifdef EXTERNAL_MDIO
+@@ -1356,24 +1243,19 @@ iegbe_oem_phy_speed_downgraded(struct ie
+ */
+
+ switch (hw->phy_id) {
+- case BCM5395S_PHY_ID:
+- case BCM5481_PHY_ID:
+- *isDowngraded = 0;
+- break;
+-
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS,
++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS,
+ &phy_data);
+ if(ret_val) {
+ DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n");
+ return ret_val;
+ }
+-
+- *isDowngraded = (phy_data & M88E1000_PSSR_DOWNSHIFT)
++
++ *isDowngraded = (phy_data & M88E1000_PSSR_DOWNSHIFT)
+ >> M88E1000_PSSR_DOWNSHIFT_SHIFT;
+-
+- break;
++
++ break;
+ default:
+ DEBUGOUT("Invalid PHY ID\n");
+ return 1;
+@@ -1388,7 +1270,7 @@ iegbe_oem_phy_speed_downgraded(struct ie
+ }
+
+ *isDowngraded = 0;
+- return 0;
++ return 0;
+
+ #endif /* ifdef EXTERNAL_MDIO */
+ }
+@@ -1403,7 +1285,7 @@ iegbe_oem_phy_speed_downgraded(struct ie
+ * Called by iegbe_check_downshift(), checks the PHY to see if it running
+ * at as speed slower than its maximum.
+ **/
+-int32_t
++int32_t
+ iegbe_oem_check_polarity(struct iegbe_hw *hw, uint16_t *polarity)
+ {
+ #ifdef EXTERNAL_MDIO
+@@ -1417,33 +1299,27 @@ iegbe_oem_check_polarity(struct iegbe_hw
+ return -1;
+ }
+
+- /*
++ /*
+ * borrow liberally from iegbe_check_polarity.
+ * Make note that the M88 phy is what'll be used on Truxton
+ */
+
+ switch (hw->phy_id) {
+- case BCM5395S_PHY_ID:
+- case BCM5481_PHY_ID:
+- *polarity = 0;
+- break;
+-
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+ /* return the Polarity bit in the Status register. */
+- ret_val = iegbe_oem_read_phy_reg_ex(hw,
+- M88E1000_PHY_SPEC_STATUS,
++ ret_val = iegbe_oem_read_phy_reg_ex(hw,
++ M88E1000_PHY_SPEC_STATUS,
+ &phy_data);
+ if(ret_val) {
+ DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n");
+ return ret_val;
+ }
+
+- *polarity = (phy_data & M88E1000_PSSR_REV_POLARITY)
++ *polarity = (phy_data & M88E1000_PSSR_REV_POLARITY)
+ >> M88E1000_PSSR_REV_POLARITY_SHIFT;
+-
+- break;
+-
++
++ break;
+ default:
+ DEBUGOUT("Invalid PHY ID\n");
+ return -E1000_ERR_PHY_TYPE;
+@@ -1472,7 +1348,7 @@ iegbe_oem_check_polarity(struct iegbe_hw
+ * the MAC with the PHY. It turns out on ICP_XXXX, this is not
+ * done automagically.
+ **/
+-int32_t
++int32_t
+ iegbe_oem_phy_is_full_duplex(struct iegbe_hw *hw, int *isFD)
+ {
+ #ifdef EXTERNAL_MDIO
+@@ -1485,40 +1361,22 @@ iegbe_oem_phy_is_full_duplex(struct iegb
+ if(!hw || !isFD) {
+ return -1;
+ }
+- /*
++ /*
+ * Make note that the M88 phy is what'll be used on Truxton
+ * see iegbe_config_mac_to_phy
+ */
+-
++
+ switch (hw->phy_id) {
+- case BCM5395S_PHY_ID:
+- /* Always full duplex */
+- *isFD = 1;
+- break;
+-
+- case BCM5481_PHY_ID:
+- ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data);
+- if(ret_val) return ret_val;
+-
+- switch (BCM5481_ASTAT_HCD(phy_data)) {
+- case BCM5481_ASTAT_1KBTFD:
+- case BCM5481_ASTAT_100BTXFD:
+- *isFD = 1;
+- break;
+- default:
+- *isFD = 0;
+- }
+- break;
+-
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+- if(ret_val) {
+- DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n");
+- return ret_val;
+- }
++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS,
++ &phy_data);
++ if(ret_val) {
++ DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n");
++ return ret_val;
++ }
+ *isFD = (phy_data & M88E1000_PSSR_DPLX) != 0;
+-
++
+ break;
+ default:
+ DEBUGOUT("Invalid PHY ID\n");
+@@ -1546,7 +1404,7 @@ iegbe_oem_phy_is_full_duplex(struct iegb
+ * the MAC with the PHY. It turns out on ICP_XXXX, this is not
+ * done automagically.
+ **/
+-int32_t
++int32_t
+ iegbe_oem_phy_is_speed_1000(struct iegbe_hw *hw, int *is1000)
+ {
+ #ifdef EXTERNAL_MDIO
+@@ -1565,28 +1423,10 @@ iegbe_oem_phy_is_speed_1000(struct iegbe
+ */
+
+ switch (hw->phy_id) {
+- case BCM5395S_PHY_ID:
+- /* Always 1000mb */
+- *is1000 = 1;
+- break;
+-
+- case BCM5481_PHY_ID:
+- ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data);
+- if(ret_val) return ret_val;
+-
+- switch (BCM5481_ASTAT_HCD(phy_data)) {
+- case BCM5481_ASTAT_1KBTFD:
+- case BCM5481_ASTAT_1KBTHD:
+- *is1000 = 1;
+- break;
+- default:
+- *is1000 = 0;
+- }
+- break;
+-
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS,
++ &phy_data);
+ if(ret_val) {
+ DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n");
+ return ret_val;
+@@ -1638,28 +1478,9 @@ iegbe_oem_phy_is_speed_100(struct iegbe_
+ * see iegbe_config_mac_to_phy
+ */
+ switch (hw->phy_id) {
+- case BCM5395S_PHY_ID:
+- /* Always 1000Mb, never 100mb */
+- *is100 = 0;
+- break;
+-
+- case BCM5481_PHY_ID:
+- ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data);
+- if(ret_val) return ret_val;
+-
+- switch (BCM5481_ASTAT_HCD(phy_data)) {
+- case BCM5481_ASTAT_100BTXFD:
+- case BCM5481_ASTAT_100BTXHD:
+- *is100 = 1;
+- break;
+- default:
+- *is100 = 0;
+- }
+- break;
+-
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+- ret_val = iegbe_oem_read_phy_reg_ex(hw,
++ ret_val = iegbe_oem_read_phy_reg_ex(hw,
+ M88E1000_PHY_SPEC_STATUS,
+ &phy_data);
+ if(ret_val) {
+@@ -1714,29 +1535,24 @@ iegbe_oem_phy_get_info(struct iegbe_hw *
+ * see iegbe_phy_m88_get_info
+ */
+ switch (hw->phy_id) {
+- case BCM5395S_PHY_ID:
+- case BCM5481_PHY_ID:
+- DEBUGOUT("WARNING: An empty iegbe_oem_phy_get_info() has been called!\n");
+- break;
+-
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+- /* The downshift status is checked only once, after link is
+- * established and it stored in the hw->speed_downgraded parameter.*/
++ /* The downshift status is checked only once, after link is
++ * established and it stored in the hw->speed_downgraded parameter.*/
+ phy_info->downshift = (iegbe_downshift)hw->speed_downgraded;
+-
+- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL,
++
++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL,
+ &phy_data);
+ if(ret_val) {
+ DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_CTRL\n");
+ return ret_val;
+ }
+
+- phy_info->extended_10bt_distance =
+- (phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE)
++ phy_info->extended_10bt_distance =
++ (phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE)
+ >> M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT;
+ phy_info->polarity_correction =
+- (phy_data & M88E1000_PSCR_POLARITY_REVERSAL)
++ (phy_data & M88E1000_PSCR_POLARITY_REVERSAL)
+ >> M88E1000_PSCR_POLARITY_REVERSAL_SHIFT;
+
+ /* Check polarity status */
+@@ -1747,11 +1563,11 @@ iegbe_oem_phy_get_info(struct iegbe_hw *
+
+ phy_info->cable_polarity = polarity;
+
+- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS,
++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS,
+ &phy_data);
+ if(ret_val) {
+- DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n");
+- return ret_val;
++ DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n");
++ return ret_val;
+ }
+
+ phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX)
+@@ -1761,24 +1577,24 @@ iegbe_oem_phy_get_info(struct iegbe_hw *
+ /* Cable Length Estimation and Local/Remote Receiver Information
+ * are only valid at 1000 Mbps.
+ */
+- phy_info->cable_length =
++ phy_info->cable_length =
+ (phy_data & M88E1000_PSSR_CABLE_LENGTH)
+ >> M88E1000_PSSR_CABLE_LENGTH_SHIFT;
+
+- ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_1000T_STATUS,
++ ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_1000T_STATUS,
+ &phy_data);
+ if(ret_val) {
+ DEBUGOUT("Unable to read register PHY_1000T_STATUS\n");
+ return ret_val;
+ }
+
+- phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS)
++ phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS)
+ >> SR_1000T_LOCAL_RX_STATUS_SHIFT;
+-
+- phy_info->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS)
++
++ phy_info->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS)
+ >> SR_1000T_REMOTE_RX_STATUS_SHIFT;
+ }
+-
++
+ break;
+ default:
+ DEBUGOUT("Invalid PHY ID\n");
+@@ -1801,7 +1617,7 @@ iegbe_oem_phy_get_info(struct iegbe_hw *
+ * This function will perform a software initiated reset of
+ * the PHY
+ **/
+-int32_t
++int32_t
+ iegbe_oem_phy_hw_reset(struct iegbe_hw *hw)
+ {
+ #ifdef EXTERNAL_MDIO
+@@ -1815,18 +1631,13 @@ iegbe_oem_phy_hw_reset(struct iegbe_hw *
+ return -1;
+ }
+ /*
+- * This code pretty much copies the default case from
++ * This code pretty much copies the default case from
+ * iegbe_phy_reset() as that is what is appropriate for
+- * the M88 used in truxton.
++ * the M88 used in truxton.
+ */
+ switch (hw->phy_id) {
+- case BCM5395S_PHY_ID:
+- DEBUGOUT("WARNING: An empty iegbe_oem_phy_hw_reset() has been called!\n");
+- break;
+-
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+- case BCM5481_PHY_ID:
+ ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_CTRL, &phy_data);
+ if(ret_val) {
+ DEBUGOUT("Unable to read register PHY_CTRL\n");
+@@ -1864,7 +1675,7 @@ iegbe_oem_phy_hw_reset(struct iegbe_hw *
+ * to perform and post reset initialiation. Not all PHYs require
+ * this, which is why it was split off as a seperate function.
+ **/
+-void
++void
+ iegbe_oem_phy_init_script(struct iegbe_hw *hw)
+ {
+ #ifdef EXTERNAL_MDIO
+@@ -1877,19 +1688,17 @@ iegbe_oem_phy_init_script(struct iegbe_h
+
+ /* call the GCU func that can do any phy specific init
+ * functions after a reset
+- *
++ *
+ * Make note that the M88 phy is what'll be used on Truxton
+ *
+- * The closest thing is in iegbe_phy_init_script, however this is
++ * The closest thing is in iegbe_phy_init_script, however this is
+ * for the IGP style of phy. This is probably a no-op for truxton
+ * but may be needed by OEM's later on
+- *
++ *
+ */
+ switch (hw->phy_id) {
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+- case BCM5481_PHY_ID:
+- case BCM5395S_PHY_ID:
+ DEBUGOUT("Nothing to do for OEM PHY Init");
+ break;
+ default:
+@@ -1926,13 +1735,8 @@ iegbe_oem_read_phy_reg_ex(struct iegbe_h
+ return -1;
+ }
+
+- if (hw->phy_id == BCM5395S_PHY_ID) {
+- DEBUGOUT("WARNING: iegbe_oem_read_phy_reg_ex() has been unexpectedly called!\n");
+- return -1;
+- }
+-
+ /* call the GCU func that will read the phy
+- *
++ *
+ * Make note that the M88 phy is what'll be used on Truxton.
+ *
+ * The closest thing is in iegbe_read_phy_reg_ex.
+@@ -1940,7 +1744,7 @@ iegbe_oem_read_phy_reg_ex(struct iegbe_h
+ * NOTE: this is 1 (of 2) functions that is truly dependant on the
+ * gcu module
+ */
+-
++
+ ret_val = gcu_read_eth_phy(iegbe_oem_get_phy_dev_number(hw),
+ reg_addr, phy_data);
+ if(ret_val) {
+@@ -1962,10 +1766,10 @@ iegbe_oem_read_phy_reg_ex(struct iegbe_h
+ *
+ * Returns E1000_SUCCESS, negative E1000 error code on failure
+ *
+- * This is called from iegbe_config_mac_to_phy. Various supported
++ * This is called from iegbe_config_mac_to_phy. Various supported
+ * Phys may require the RGMII/RMII Translation gasket be set to RMII.
+ **/
+-int32_t
++int32_t
+ iegbe_oem_set_trans_gasket(struct iegbe_hw *hw)
+ {
+ #ifdef EXTERNAL_MDIO
+@@ -1978,17 +1782,12 @@ iegbe_oem_set_trans_gasket(struct iegbe_
+ }
+
+ switch (hw->phy_id) {
+- case BCM5395S_PHY_ID:
+- case BCM5481_PHY_ID:
+- DEBUGOUT("WARNING: An empty iegbe_oem_set_trans_gasket() has been called!\n");
+- break;
+-
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+ /* Gasket set correctly for Marvell Phys, so nothing to do */
+ break;
+ /* Add your PHY_ID here if your device requires an RMII interface
+- case YOUR_PHY_ID:
++ case YOUR_PHY_ID:
+ ctrl_aux_reg = E1000_READ_REG(hw, CTRL_AUX);
+ ctrl_aux_reg |= E1000_CTRL_AUX_ICP_xxxx_MII_TGS; // Set the RGMII_RMII bit
+ */
+@@ -2032,7 +1831,7 @@ iegbe_oem_write_phy_reg_ex(struct iegbe_
+ return -1;
+ }
+ /* call the GCU func that will write to the phy
+- *
++ *
+ * Make note that the M88 phy is what'll be used on Truxton.
+ *
+ * The closest thing is in iegbe_write_phy_reg_ex
+@@ -2062,11 +1861,11 @@ iegbe_oem_write_phy_reg_ex(struct iegbe_
+ * @hw struct iegbe_hw hardware specific data
+ *
+ * iegbe_reset_hw is called to reset the MAC. If, for
+- * some reason the PHY needs to be reset as well, this
++ * some reason the PHY needs to be reset as well, this
+ * should return TRUE and then iegbe_oem_phy_hw_reset()
+ * will be called.
+ **/
+-int
++int
+ iegbe_oem_phy_needs_reset_with_mac(struct iegbe_hw *hw)
+ {
+ #ifdef EXTERNAL_MDIO
+@@ -2079,16 +1878,14 @@ iegbe_oem_phy_needs_reset_with_mac(struc
+ return FALSE;
+ }
+
+- /*
++ /*
+ * From the original iegbe driver, the M88
+- * PHYs did not seem to need this reset,
++ * PHYs did not seem to need this reset,
+ * so returning FALSE.
+ */
+ switch (hw->phy_id) {
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+- case BCM5481_PHY_ID:
+- case BCM5395S_PHY_ID:
+ ret_val = FALSE;
+ break;
+ default:
+@@ -2116,7 +1913,7 @@ iegbe_oem_phy_needs_reset_with_mac(struc
+ * tweaking of the PHY, for PHYs that support a DSP.
+ *
+ **/
+-int32_t
++int32_t
+ iegbe_oem_config_dsp_after_link_change(struct iegbe_hw *hw,
+ int link_up)
+ {
+@@ -2138,8 +1935,6 @@ iegbe_oem_config_dsp_after_link_change(s
+ switch (hw->phy_id) {
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+- case BCM5481_PHY_ID:
+- case BCM5395S_PHY_ID:
+ DEBUGOUT("No DSP to configure on OEM PHY");
+ break;
+ default:
+@@ -2165,7 +1960,7 @@ iegbe_oem_config_dsp_after_link_change(s
+ *
+ *
+ **/
+-int32_t
++int32_t
+ iegbe_oem_get_cable_length(struct iegbe_hw *hw,
+ uint16_t *min_length,
+ uint16_t *max_length)
+@@ -2177,21 +1972,15 @@ iegbe_oem_get_cable_length(struct iegbe_
+ uint16_t phy_data;
+
+ DEBUGFUNC1("%s",__func__);
+-
++
+ if(!hw || !min_length || !max_length) {
+ return -1;
+ }
+
+ switch (hw->phy_id) {
+- case BCM5395S_PHY_ID:
+- case BCM5481_PHY_ID:
+- *min_length = 0;
+- *max_length = iegbe_igp_cable_length_150;
+- break;
+-
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+- ret_val = iegbe_oem_read_phy_reg_ex(hw,
++ ret_val = iegbe_oem_read_phy_reg_ex(hw,
+ M88E1000_PHY_SPEC_STATUS,
+ &phy_data);
+ if(ret_val) {
+@@ -2246,13 +2035,13 @@ iegbe_oem_get_cable_length(struct iegbe_
+ /**
+ * iegbe_oem_phy_is_link_up
+ * @hw iegbe_hw struct containing device specific information
+- * @isUp a boolean returning true if link is up
++ * @isUp a boolean returning true if link is up
+ *
+ * This is called as part of iegbe_config_mac_to_phy() to align
+ * the MAC with the PHY. It turns out on ICP_XXXX, this is not
+ * done automagically.
+ **/
+-int32_t
++int32_t
+ iegbe_oem_phy_is_link_up(struct iegbe_hw *hw, int *isUp)
+ {
+ #ifdef EXTERNAL_MDIO
+@@ -2266,35 +2055,19 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw
+ if(!hw || !isUp) {
+ return -1;
+ }
+- /*
++ /*
+ * Make note that the M88 phy is what'll be used on Truxton
+ * see iegbe_config_mac_to_phy
+ */
+
+ switch (hw->phy_id) {
+- case BCM5395S_PHY_ID:
+- /* Link always up */
+- *isUp = TRUE;
+- return E1000_SUCCESS;
+- break;
+-
+- case BCM5481_PHY_ID:
+- iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data);
+- ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data);
+- if(ret_val)
+- {
+- DEBUGOUT("Unable to read PHY register BCM5481_ESTAT\n");
+- return ret_val;
+- }
+- statusMask = BCM5481_ESTAT_LINK;
+- break;
+-
+- case M88E1000_I_PHY_ID:
++ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+- iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
++ iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS,
++ &phy_data);
+ statusMask = M88E1000_PSSR_LINK;
+- break;
++ break;
+ default:
+ DEBUGOUT("Invalid PHY ID\n");
+ return -E1000_ERR_PHY_TYPE;
+@@ -2319,213 +2092,3 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw
+ #endif /* ifdef EXTERNAL_MDIO */
+ }
+
+-
+-
+-//-----
+-// Read BCM5481 expansion register
+-//
+-int32_t
+-bcm5481_read_ex (struct iegbe_hw *hw, uint16_t reg, uint16_t *data)
+-{
+- int ret;
+- uint16_t selector;
+- uint16_t reg_data;
+-
+- // Get the current value of bits 15:12
+- ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, &selector);
+- if (ret)
+- return ret;
+-
+- // Select the expansion register
+- selector &= 0xf000;
+- selector |= (0xf << 8) | (reg);
+- iegbe_oem_write_phy_reg_ex (hw, 0x17, selector);
+-
+- // Read the expansion register
+- ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, &reg_data);
+-
+- // De-select the expansion registers.
+- selector &= 0xf000;
+- iegbe_oem_write_phy_reg_ex (hw, 0x17, selector);
+-
+- if (ret)
+- return ret;
+-
+- *data = reg_data;
+- return ret;
+-}
+-
+-//-----
+-// Read reg 0x18 sub-register
+-//
+-static int32_t
+-bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data)
+-{
+- int ret;
+- uint16_t tmp_data;
+-
+- // Select reg 0x18, sv
+- tmp_data = ((sv & BCM5481_R18H_SV_MASK) << 12) | BCM5481_R18H_SV_MCTRL;
+- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, tmp_data);
+- if(ret)
+- return ret;
+-
+- // Read reg 0x18, sv
+- ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R18H, &tmp_data);
+- if(ret)
+- return ret;
+-
+- *data = tmp_data;
+- return ret;
+-}
+-
+-//-----
+-// Read reg 0x1C sub-register
+-//
+-int32_t
+-bcm5481_read_1csv (struct iegbe_hw *hw, int sv, uint16_t *data)
+-{
+- int ret;
+- uint16_t tmp_data;
+-
+- // Select reg 0x1c, sv
+- tmp_data = ((sv & BCM5481_R1CH_SV_MASK) << BCM5481_R1CH_SV_SHIFT);
+-
+- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, tmp_data);
+- if(ret)
+- return ret;
+-
+- // Read reg 0x1c, sv
+- ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R1CH, &tmp_data);
+- if(ret)
+- return ret;
+-
+- *data = tmp_data;
+- return ret;
+-}
+-
+-//-----
+-// Read-modify-write a 0x1C register.
+-//
+-// hw - hardware access info.
+-// reg - 0x1C register to modify.
+-// data - bits which should be set.
+-// mask - the '1' bits in this argument will be cleared in the data
+-// read from 'reg' then 'data' will be or'd in and the result
+-// will be written to 'reg'.
+-
+-int32_t
+-bcm5481_rmw_1csv (struct iegbe_hw *hw, uint16_t reg, uint16_t data, uint16_t mask)
+-{
+- int32_t ret;
+- uint16_t reg_data;
+-
+- ret = 0;
+-
+- ret = bcm5481_read_1csv (hw, reg, &reg_data);
+- if (ret)
+- {
+- DEBUGOUT("Unable to read BCM5481 1CH register\n");
+- printk (KERN_ERR "Unable to read BCM5481 1CH register [0x%x]\n", reg);
+- return ret;
+- }
+-
+- reg_data &= ~mask;
+- reg_data |= (BCM5481_R1CH_WE | data);
+-
+- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, reg_data);
+- if(ret)
+- {
+- DEBUGOUT("Unable to write BCM5481 1CH register\n");
+- printk (KERN_ERR "Unable to write BCM5481 1CH register\n");
+- return ret;
+- }
+-
+- return ret;
+-}
+-
+-int32_t
+-oi_phy_setup (struct iegbe_hw *hw)
+-{
+- int ret;
+- uint16_t pmii_data;
+- uint16_t mctrl_data;
+- uint16_t cacr_data;
+- uint16_t sc1_data;
+- uint16_t lctl_data;
+-
+- ret = 0;
+-
+- // Set low power mode via reg 0x18, sv010, bit 6
+- // Do a read-modify-write on reg 0x18, sv010 register to preserve existing bits.
+- ret = bcm5481_read_18sv (hw, BCM5481_R18H_SV_PMII, &pmii_data);
+- if (ret)
+- {
+- DEBUGOUT("Unable to read BCM5481_R18H_SV_PMII register\n");
+- printk (KERN_ERR "Unable to read BCM5481_R18H_SV_PMII register\n");
+- return ret;
+- }
+-
+- // Set the LPM bit in the data just read and write back to sv010
+- // The shadow register select bits [2:0] are set by reading the sv010
+- // register.
+- pmii_data |= BCM5481_R18H_SV010_LPM;
+- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, pmii_data);
+- if(ret)
+- {
+- DEBUGOUT("Unable to write BCM5481_R18H register\n");
+- printk (KERN_ERR "Unable to write BCM5481_R18H register\n");
+- return ret;
+- }
+-
+-
+- // Set the RGMII RXD to RXC skew bit in reg 0x18, sv111
+-
+- if (bcm5481_read_18sv (hw, BCM5481_R18H_SV_MCTRL, &mctrl_data))
+- {
+- DEBUGOUT("Unable to read BCM5481_R18H_SV_MCTRL register\n");
+- printk (KERN_ERR "Unable to read BCM5481_R18H_SV_MCTRL register\n");
+- return ret;
+- }
+- mctrl_data |= (BCM5481_R18H_WE | BCM5481_R18H_SV111_SKEW);
+-
+- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, mctrl_data);
+- if(ret)
+- {
+- DEBUGOUT("Unable to write BCM5481_R18H register\n");
+- printk (KERN_ERR "Unable to write BCM5481_R18H register\n");
+- return ret;
+- }
+-
+-
+- // Enable RGMII transmit clock delay in reg 0x1c, sv00011
+- ret = bcm5481_read_1csv (hw, BCM5481_R1CH_CACR, &cacr_data);
+- if (ret)
+- {
+- DEBUGOUT("Unable to read BCM5481_R1CH_CACR register\n");
+- printk (KERN_ERR "Unable to read BCM5481_R1CH_CACR register\n");
+- return ret;
+- }
+-
+- cacr_data |= (BCM5481_R1CH_WE | BCM5481_R1CH_CACR_TCD);
+-
+- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, cacr_data);
+- if(ret)
+- {
+- DEBUGOUT("Unable to write BCM5481_R1CH register\n");
+- printk (KERN_ERR "Unable to write BCM5481_R1CH register\n");
+- return ret;
+- }
+-
+- // Enable dual link speed indication (0x1c, sv 00010, bit 2)
+- ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_SC1, BCM5481_R1CH_SC1_LINK, BCM5481_R1CH_SC1_LINK);
+- if (ret)
+- return ret;
+-
+- // Enable link and activity on ACTIVITY LED (0x1c, sv 01001, bit 4=1, bit 3=0)
+- ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_LCTRL, BCM5481_R1CH_LCTRL_ALEN, BCM5481_R1CH_LCTRL_ALEN | BCM5481_R1CH_LCTRL_AEN);
+- if (ret)
+- return ret;
+-
+- return ret;
+-}
+--- a/Embedded/src/GbE/iegbe_oem_phy.h
++++ b/Embedded/src/GbE/iegbe_oem_phy.h
+@@ -2,31 +2,31 @@
+
+ GPL LICENSE SUMMARY
+
+- Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+
+- This program is free software; you can redistribute it and/or modify
++ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License 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
++ 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
++ 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+- The full GNU General Public License is included in this distribution
++ The full GNU General Public License is included in this distribution
+ in the file called LICENSE.GPL.
+
+ Contact Information:
+ Intel Corporation
+
+- version: Embedded.L.1.0.34
++ version: Embedded.Release.Patch.L.1.0.7-5
+
+ Contact Information:
+-
+- Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226
++
++ Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226
+
+ *******************************************************************************/
+ #ifndef _IEGBE_OEM_PHY_H_
+@@ -45,10 +45,10 @@ int32_t iegbe_oem_set_trans_gasket(struc
+ uint32_t iegbe_oem_get_tipg(struct iegbe_hw *hw);
+ int iegbe_oem_phy_is_copper(struct iegbe_hw *hw);
+ uint32_t iegbe_oem_get_phy_dev_number(struct iegbe_hw *hw);
+-int iegbe_oem_mii_ioctl(struct iegbe_adapter *adapter, unsigned long flags,
++int iegbe_oem_mii_ioctl(struct iegbe_adapter *adapter, unsigned long flags,
+ struct ifreq *ifr, int cmd);
+ void iegbe_oem_fiber_live_in_suspend(struct iegbe_hw *hw);
+-void iegbe_oem_get_phy_regs(struct iegbe_adapter *adapter, uint32_t *data,
++void iegbe_oem_get_phy_regs(struct iegbe_adapter *adapter, uint32_t *data,
+ uint32_t data_length);
+ int iegbe_oem_phy_loopback(struct iegbe_adapter *adapter);
+ void iegbe_oem_loopback_cleanup(struct iegbe_adapter *adapter);
+@@ -94,81 +94,14 @@ int32_t iegbe_oem_phy_is_link_up(struct
+ #define ICP_XXXX_MAC_2 2
+
+ #define DEFAULT_ICP_XXXX_TIPG_IPGT 8 /* Inter Packet Gap Transmit Time */
+-#define ICP_XXXX_TIPG_IPGT_MASK 0x000003FFUL
+-#define BCM5481_PHY_ID 0x0143BCA2
+-#define BCM5395S_PHY_ID 0x0143BCF0
++#define ICP_XXXX_TIPG_IPGT_MASK 0x000003FFUL
+
+ /* Miscellaneous defines */
+ #ifdef IEGBE_10_100_ONLY
+- #define ICP_XXXX_AUTONEG_ADV_DEFAULT 0x0F
++ #define ICP_XXXX_AUTONEG_ADV_DEFAULT 0x0F
+ #else
+ #define ICP_XXXX_AUTONEG_ADV_DEFAULT 0x2F
+ #endif
+
+-//-----
+-// BCM5481 specifics
+-
+-#define BCM5481_ECTRL (0x10)
+-#define BCM5481_ESTAT (0x11)
+-#define BCM5481_RXERR (0x12)
+-#define BCM5481_EXPRW (0x15)
+-#define BCM5481_EXPACC (0x17)
+-#define BCM5481_ASTAT (0x19)
+-#define BCM5481_R18H (0x18)
+-#define BCM5481_R1CH (0x1c)
+-
+-//-----
+-// indirect register access via register 18h
+-
+-#define BCM5481_R18H_SV_MASK (7) // Mask for SV bits.
+-#define BCM5481_R18H_SV_ACTRL (0) // SV000 Aux. control
+-#define BCM5481_R18H_SV_10BT (1) // SV001 10Base-T
+-#define BCM5481_R18H_SV_PMII (2) // SV010 Power/MII control
+-#define BCM5481_R18H_SV_MTEST (4) // SV100 Misc. test
+-#define BCM5481_R18H_SV_MCTRL (7) // SV111 Misc. control
+-
+-#define BCM5481_R18H_SV001_POL (1 << 13) // Polarity
+-#define BCM5481_R18H_SV010_LPM (1 << 6)
+-#define BCM5481_R18H_SV111_SKEW (1 << 8)
+-#define BCM5481_R18H_WE (1 << 15) // Write enable
+-
+-// 0x1c registers
+-#define BCM5481_R1CH_SV_SHIFT (10)
+-#define BCM5481_R1CH_SV_MASK (0x1f)
+-#define BCM5481_R1CH_SC1 (0x02) // sv00010 Spare control 1
+-#define BCM5481_R1CH_CACR (0x03) // sv00011 Clock alignment control
+-#define BCM5481_R1CH_LCTRL (0x09) // sv01001 LED control
+-#define BCM5481_R1CH_LEDS1 (0x0d) // sv01101 LED selector 1
+-
+-// 0x1c common
+-#define BCM5481_R1CH_WE (1 << 15) // Write enable
+-
+-// 0x1c, sv 00010
+-#define BCM5481_R1CH_SC1_LINK (1 << 2) // sv00010 Linkspeed
+-
+-// 0x1c, sv 00011
+-#define BCM5481_R1CH_CACR_TCD (1 << 9) // sv00011 RGMII tx clock delay
+-
+-// 0x1c, sv 01001
+-#define BCM5481_R1CH_LCTRL_ALEN (1 << 4) // Activity/Link enable on ACTIVITY LED
+-#define BCM5481_R1CH_LCTRL_AEN (1 << 3) // Activity enable on ACTIVITY LED
+-
+-
+-#define BCM5481_ECTRL_DISMDIX (1 <<14)
+-
+-#define BCM5481_MCTRL_AUTOMDIX (1 <<9)
+-
+-#define BCM5481_ESTAT_LINK (1 << 8)
+-
+-#define BCM5481_ASTAT_ANC (1 << 15)
+-#define BCM5481_ASTAT_ANHCD (7 << 8)
+-#define BCM5481_ASTAT_HCD(x) ((x >> 8) & 7)
+-#define BCM5481_ASTAT_1KBTFD (0x7)
+-#define BCM5481_ASTAT_1KBTHD (0x6)
+-#define BCM5481_ASTAT_100BTXFD (0x5)
+-#define BCM5481_ASTAT_100BTXHD (0x3)
+-
+-// end BCM5481 specifics
+-
+ #endif /* ifndef _IEGBE_OEM_PHY_H_ */
+-
++
+--- a/Embedded/src/GbE/iegbe_osdep.h
++++ b/Embedded/src/GbE/iegbe_osdep.h
+@@ -2,7 +2,7 @@
+
+ GPL LICENSE SUMMARY
+
+- Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY
+ Contact Information:
+ Intel Corporation
+
+- version: Embedded.L.1.0.34
++ version: Embedded.Release.Patch.L.1.0.7-5
+
+ Contact Information:
+
+--- a/Embedded/src/GbE/iegbe_param.c
++++ b/Embedded/src/GbE/iegbe_param.c
+@@ -2,7 +2,7 @@
+
+ GPL LICENSE SUMMARY
+
+- Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY
+ Contact Information:
+ Intel Corporation
+
+- version: Embedded.L.1.0.34
++ version: Embedded.Release.Patch.L.1.0.7-5
+
+ Contact Information:
+
+@@ -239,11 +239,7 @@ E1000_PARAM(InterruptThrottleRate, "Inte
+ #define MAX_TXABSDELAY 0xFFFF
+ #define MIN_TXABSDELAY 0
+
+-#ifdef IEGBE_GBE_WORKAROUND
+-#define DEFAULT_ITR 0
+-#else
+ #define DEFAULT_ITR 8000
+-#endif
+
+
+ #define MAX_ITR 100000
+@@ -373,7 +369,7 @@ iegbe_check_options(struct iegbe_adapter
+ tx_ring->count = opt.def;
+ }
+ #endif
+- for (i = 0; i < adapter->num_queues; i++)
++ for (i = 0; i < adapter->num_tx_queues; i++)
+ tx_ring[i].count = tx_ring->count;
+ }
+ { /* Receive Descriptor Count */
+@@ -403,7 +399,7 @@ iegbe_check_options(struct iegbe_adapter
+ rx_ring->count = opt.def;
+ }
+ #endif
+- for (i = 0; i < adapter->num_queues; i++)
++ for (i = 0; i < adapter->num_rx_queues; i++)
+ rx_ring[i].count = rx_ring->count;
+ }
+ { /* Checksum Offload Enable/Disable */
+--- a/Embedded/src/GbE/kcompat.c
++++ b/Embedded/src/GbE/kcompat.c
+@@ -1,8 +1,8 @@
+-/************************************************************
+-
++/************************************************************
++
+ GPL LICENSE SUMMARY
+
+- Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+@@ -22,183 +22,192 @@ GPL LICENSE SUMMARY
+ Contact Information:
+ Intel Corporation
+
+- version: Embedded.L.1.0.34
+-
+- Contact Information:
+-
+- Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226
+-
+-**************************************************************/
+-/**************************************************************************
+- * @ingroup KCOMPAT_GENERAL
+- *
+- * @file kcompat.c
+- *
+- * @description
+- *
+- *
+- **************************************************************************/
+-#include "kcompat.h"
+-
+-/*************************************************************/
+-/* 2.4.13 => 2.4.3 */
+-#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0xd) )
+-
+-/**************************************/
+-/* PCI DMA MAPPING */
+-
+-#if defined(CONFIG_HIGHMEM)
+-
+-#ifndef PCI_DRAM_OFFSET
+-#define PCI_DRAM_OFFSET 0
+-#endif
+-
+-u64 _kc_pci_map_page(struct pci_dev *dev,
+- struct page *page,
+- unsigned long offset,
+- size_t size,
+- int direction)
+-{
+- u64 ret_val;
+- ret_val = (((u64)(page - mem_map) << PAGE_SHIFT) + offset +
+- PCI_DRAM_OFFSET);
+- return ret_val;
+-}
+-
+-#else /* CONFIG_HIGHMEM */
+-
+-u64 _kc_pci_map_page(struct pci_dev *dev,
+- struct page *page,
+- unsigned long offset,
+- size_t size,
+- int direction)
+-{
+- return pci_map_single(dev, (void *)page_address(page) + offset,
+- size, direction);
+-}
+-
+-#endif /* CONFIG_HIGHMEM */
+-
+-void _kc_pci_unmap_page(struct pci_dev *dev,
+- u64 dma_addr,
+- size_t size,
+- int direction)
+-{
+- return pci_unmap_single(dev, dma_addr, size, direction);
+-}
+-
+-#endif /* 2.4.13 => 2.4.3 */
+-
+-
+-/*****************************************************************************/
+-/* 2.4.3 => 2.4.0 */
+-#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0x3) )
+-
+-/**************************************/
+-/* PCI DRIVER API */
+-
+-int _kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask)
+-{
+- if(!pci_dma_supported(dev, mask)) {
+- return -EIO;
+- }
+- dev->dma_mask = mask;
+- return 0;
+-}
+-
+-int _kc_pci_request_regions(struct pci_dev *dev, char *res_name)
+-{
+- int i;
+-
+- for (i = 0; i < 0x6; i++) {
+- if (pci_resource_len(dev, i) == 0) {
+- continue;
+- }
+- if (pci_resource_flags(dev, i) & IORESOURCE_IO) {
+- if (!request_region(pci_resource_start(dev, i),
+- pci_resource_len(dev, i), res_name)) {
+- pci_release_regions(dev);
+- return -EBUSY;
+- }
+- } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) {
+- if (!request_mem_region(pci_resource_start(dev, i),
+- pci_resource_len(dev, i),
+- res_name)) {
+- pci_release_regions(dev);
+- return -EBUSY;
+- }
+- }
+- }
+- return 0;
+-}
+-
+-void _kc_pci_release_regions(struct pci_dev *dev)
+-{
+- int i;
+-
+- for (i = 0; i < 0x6; i++) {
+- if (pci_resource_len(dev, i) == 0) {
+- continue;
+- }
+- if (pci_resource_flags(dev, i) & IORESOURCE_IO){
+- release_region(pci_resource_start(dev, i),
+- pci_resource_len(dev, i));
+- } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) {
+- release_mem_region(pci_resource_start(dev, i),
+- pci_resource_len(dev, i));
+- }
+- }
+-}
+-
+-/**************************************/
+-/* NETWORK DRIVER API */
+-
+-struct net_device * _kc_alloc_etherdev(int sizeof_priv)
+-{
+- struct net_device *dev;
+- int alloc_size;
+-
+- alloc_size = sizeof(*dev) + sizeof_priv + IFNAMSIZ + 0x1f;
+-
+- dev = kmalloc(alloc_size, GFP_KERNEL);
+-
+- if (!dev) { return NULL; }
+-
+- memset(dev, 0, alloc_size);
+-
+- if (sizeof_priv) {
+- dev->priv = (void *) (((unsigned long)(dev + 1) + 0x1f) & ~0x1f);
+- }
+- dev->name[0] = '\0';
+-
+- ether_setup(dev);
+-
+- return dev;
+-}
+-
+-int _kc_is_valid_ether_addr(u8 *addr)
+-{
+- const char zaddr[0x6] = {0,};
+-
+- return !(addr[0]&1) && memcmp( addr, zaddr, 0x6);
+-}
+-
+-#endif /* 2.4.3 => 2.4.0 */
+-
+-
+-/*****************************************************************/
+-/* 2.4.6 => 2.4.3 */
+-#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0x6) )
+-
+-int _kc_pci_set_power_state(struct pci_dev *dev, int state)
+-{ return 0; }
+-int _kc_pci_save_state(struct pci_dev *dev, u32 *buffer)
+-{ return 0; }
+-int _kc_pci_restore_state(struct pci_dev *pdev, u32 *buffer)
+-{ return 0; }
+-int _kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable)
+-{ return 0; }
+-
+-#endif /* 2.4.6 => 2.4.3 */
+-
+-
++ version: Embedded.Release.Patch.L.1.0.7-5
++
++ Contact Information:
++
++ Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226
++
++**************************************************************/
++/**************************************************************************
++ * @ingroup KCOMPAT_GENERAL
++ *
++ * @file kcompat.c
++ *
++ * @description
++ *
++ *
++ **************************************************************************/
++#include "kcompat.h"
++
++/*************************************************************/
++/* 2.4.13 => 2.4.3 */
++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0xd) )
++
++/**************************************/
++/* PCI DMA MAPPING */
++
++#if defined(CONFIG_HIGHMEM)
++
++#ifndef PCI_DRAM_OFFSET
++#define PCI_DRAM_OFFSET 0
++#endif
++
++u64 _kc_pci_map_page(struct pci_dev *dev,
++ struct page *page,
++ unsigned long offset,
++ size_t size,
++ int direction)
++{
++ u64 ret_val;
++ ret_val = (((u64)(page - mem_map) << PAGE_SHIFT) + offset +
++ PCI_DRAM_OFFSET);
++ return ret_val;
++}
++
++#else /* CONFIG_HIGHMEM */
++
++u64 _kc_pci_map_page(struct pci_dev *dev,
++ struct page *page,
++ unsigned long offset,
++ size_t size,
++ int direction)
++{
++ return pci_map_single(dev, (void *)page_address(page) + offset,
++ size, direction);
++}
++
++#endif /* CONFIG_HIGHMEM */
++
++void _kc_pci_unmap_page(struct pci_dev *dev,
++ u64 dma_addr,
++ size_t size,
++ int direction)
++{
++ return pci_unmap_single(dev, dma_addr, size, direction);
++}
++
++#endif /* 2.4.13 => 2.4.3 */
++
++
++/*****************************************************************************/
++/* 2.4.3 => 2.4.0 */
++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0x3) )
++
++/**************************************/
++/* PCI DRIVER API */
++
++int _kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask)
++{
++ if(!pci_dma_supported(dev, mask)) {
++ return -EIO;
++ }
++ dev->dma_mask = mask;
++ return 0;
++}
++
++int _kc_pci_request_regions(struct pci_dev *dev, char *res_name)
++{
++ int i;
++
++ for (i = 0; i < 0x6; i++) {
++ if (pci_resource_len(dev, i) == 0) {
++ continue;
++ }
++ if (pci_resource_flags(dev, i) & IORESOURCE_IO) {
++ if (!request_region(pci_resource_start(dev, i),
++ pci_resource_len(dev, i), res_name)) {
++ pci_release_regions(dev);
++ return -EBUSY;
++ }
++ } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) {
++ if (!request_mem_region(pci_resource_start(dev, i),
++ pci_resource_len(dev, i),
++ res_name)) {
++ pci_release_regions(dev);
++ return -EBUSY;
++ }
++ }
++ }
++ return 0;
++}
++
++void _kc_pci_release_regions(struct pci_dev *dev)
++{
++ int i;
++
++ for (i = 0; i < 0x6; i++) {
++ if (pci_resource_len(dev, i) == 0) {
++ continue;
++ }
++ if (pci_resource_flags(dev, i) & IORESOURCE_IO){
++ release_region(pci_resource_start(dev, i),
++ pci_resource_len(dev, i));
++ } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) {
++ release_mem_region(pci_resource_start(dev, i),
++ pci_resource_len(dev, i));
++ }
++ }
++}
++
++/**************************************/
++/* NETWORK DRIVER API */
++
++struct net_device * _kc_alloc_etherdev(int sizeof_priv)
++{
++ struct net_device *dev;
++ int alloc_size;
++
++ alloc_size = sizeof(*dev) + sizeof_priv + IFNAMSIZ + 0x1f;
++
++ dev = kmalloc(alloc_size, GFP_KERNEL);
++
++ if (!dev) { return NULL; }
++
++ memset(dev, 0, alloc_size);
++
++ if (sizeof_priv) {
++ dev->priv = (void *) (((unsigned long)(dev + 1) + 0x1f) & ~0x1f);
++ }
++ dev->name[0] = '\0';
++
++ ether_setup(dev);
++
++ return dev;
++}
++
++int _kc_is_valid_ether_addr(u8 *addr)
++{
++ const char zaddr[0x6] = {0,};
++
++ return !(addr[0]&1) && memcmp( addr, zaddr, 0x6);
++}
++
++#endif /* 2.4.3 => 2.4.0 */
++
++
++/*****************************************************************/
++/* 2.4.6 => 2.4.3 */
++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0x6) )
++
++int _kc_pci_set_power_state(struct pci_dev *dev, int state)
++{ return 0; }
++int _kc_pci_save_state(struct pci_dev *dev, u32 *buffer)
++{ return 0; }
++int _kc_pci_restore_state(struct pci_dev *pdev, u32 *buffer)
++{ return 0; }
++int _kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable)
++{ return 0; }
++
++#endif /* 2.4.6 => 2.4.3 */
++
++
++
++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,24) )
++
++void dump_stack(void)
++{
++}
++
++#endif /* 2.4.24 */
++
+--- a/Embedded/src/GbE/kcompat_ethtool.c
++++ b/Embedded/src/GbE/kcompat_ethtool.c
+@@ -2,7 +2,7 @@
+ /*
+ * GPL LICENSE SUMMARY
+ *
+- * Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
++ * Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+@@ -22,7 +22,7 @@
+ * Contact Information:
+ * Intel Corporation
+ *
+- * version: Embedded.L.1.0.34
++ * version: Embedded.Release.Patch.L.1.0.7-5
+ */
+
+ /**************************************************************************
+@@ -779,6 +779,7 @@ static int ethtool_get_stats(struct net_
+ }
+
+ /* The main entry point in this file. Called from net/core/dev.c */
++
+ #define ETHTOOL_OPS_COMPAT
+ int ethtool_ioctl(struct ifreq *ifr)
+ {
+--- a/Embedded/src/GbE/kcompat.h
++++ b/Embedded/src/GbE/kcompat.h
+@@ -2,7 +2,7 @@
+
+ GPL LICENSE SUMMARY
+
+- Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY
+ Contact Information:
+ Intel Corporation
+
+- version: Embedded.L.1.0.34
++ version: Embedded.Release.Patch.L.1.0.7-5
+
+ Contact Information:
+
+@@ -69,15 +69,6 @@ GPL LICENSE SUMMARY
+ #define CONFIG_NET_POLL_CONTROLLER
+ #endif
+
+-#ifdef E1000_NAPI
+-#undef CONFIG_E1000_NAPI
+-#define CONFIG_E1000_NAPI
+-#endif
+-
+-#ifdef E1000_NO_NAPI
+-#undef CONFIG_E1000_NAPI
+-#endif
+-
+ #ifndef module_param
+ #define module_param(v,t,p) MODULE_PARM(v, "i");
+ #endif
+@@ -554,35 +545,14 @@ extern void _kc_pci_unmap_page(struct pc
+ #endif
+
+ /*****************************************************************************/
+-/* 2.4.23 => 2.4.22 */
+-#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) )
+-#ifdef CONFIG_E1000_NAPI
+-#ifndef netif_poll_disable
+-#define netif_poll_disable(x) _kc_netif_poll_disable(x)
+-static inline void _kc_netif_poll_disable(struct net_device *netdev)
+-{
+- while (test_and_set_bit(__LINK_STATE_RX_SCHED, &netdev->state)) {
+- /* No hurry */
+- current->state = TASK_INTERRUPTIBLE;
+- schedule_timeout(1);
+- }
+-}
+-#endif
+-#ifndef netif_poll_enable
+-#define netif_poll_enable(x) _kc_netif_poll_enable(x)
+-static inline void _kc_netif_poll_enable(struct net_device *netdev)
+-{
+- clear_bit(__LINK_STATE_RX_SCHED, &netdev->state);
+-}
+-#endif
+-#endif
+-#endif
+-
+-/*****************************************************************************/
+ /* 2.5.28 => 2.4.23 */
+ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) )
+
++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) )
++static inline void _kc_synchronize_irq(void) { barrier(); }
++#else
+ static inline void _kc_synchronize_irq() { synchronize_irq(); }
++#endif /* 2.4.23 */
+ #undef synchronize_irq
+ #define synchronize_irq(X) _kc_synchronize_irq()
+
+@@ -747,6 +717,37 @@ static inline struct mii_ioctl_data *_kc
+ #define skb_header_cloned(x) 0
+ #endif /* SKB_DATAREF_SHIFT not defined */
+
++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) )
++
++#define ioread32(addr) readl(addr)
++#define iowrite32(val,addr) writel(val,addr)
++
++#endif /* 2.6.10 */
++
++#ifndef DEFINE_SPINLOCK
++#define DEFINE_SPINLOCK(s) spinlock_t s = SPIN_LOCK_UNLOCKED
++#endif /* DEFINE_SPINLOCK */
++
++#ifndef PCI_COMMAND_INTX_DISABLE
++#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
++#endif /* PCI_COMMAND_INTX_DISABLE */
++
++#ifndef ETH_GSTRING_LEN
++#define ETH_GSTRING_LEN 32
++#endif /* ETH_GSTRING_LEN */
++
++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,24) )
++
++extern void dump_stack(void);
++
++#undef register_reboot_notifier
++#define register_reboot_notifier(a)
++
++#undef unregister_reboot_notifier
++#define unregister_reboot_notifier(a)
++
++#endif /* 2.4.24 */
++
+ #endif /* _KCOMPAT_H_ */
+
+
+--- a/Embedded/src/GbE/Makefile
++++ b/Embedded/src/GbE/Makefile
+@@ -1,6 +1,6 @@
+ # GPL LICENSE SUMMARY
+ #
+-# Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
++# Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+ #
+ # This program is free software; you can redistribute it and/or modify
+ # it under the terms of version 2 of the GNU General Public License as
+@@ -20,7 +20,7 @@
+ # Contact Information:
+ # Intel Corporation
+ #
+-# version: Embedded.L.1.0.34
++# version: Embedded.Release.Patch.L.1.0.7-5
+
+ ###########################################################################
+ # Driver files
+@@ -35,6 +35,8 @@ MDIO_PHONY_CFILES = gcu.c
+ MDIO_CFILES = gcu_main.c gcu_if.c
+ MDIO_HFILES = gcu.h gcu_if.h gcu_reg.h kcompat.h
+
++KVER=$(shell uname -r)
++
+ #
+ # Variables:
+ # KSRC (path to kernel source to build against)
+@@ -50,45 +52,16 @@ MDIO_HFILES = gcu.h gcu_if.h gcu_reg.h k
+
+ # set KSRC, KOBJ, and EXTERNAL_MDIO to default values of not already set
+ #
+-KOBJ ?= /usr/src/kernels/linux
+-KSRC ?= /usr/src/kernels/linux
++#KOBJ=/usr/src/kernels/linux
++#KSRC=/usr/src/kernels/linux
++#KSRC=$(KOBJ)
+ EXTERNAL_MDIO ?= 1
+ GBE_NAME = iegbe
+ GCU_NAME = gcu
+
+-# By default the workaround for the IEGBE writeback issue is enabled
+-#
+-IEGBE_GBE_WORKAROUND ?= 0
+-
+-# If the platform only supports 10/100 this variable needs to be set
+-# so the default advertisement is set appropriately.
+-# By default, this variable will be disabled.
+-#
+-IEGBE_10_100_ONLY ?= 0
+-
+-# check for version.h and autoconf.h for running kernel in /boot (SUSE)
+-ifneq (,$(wildcard /boot/vmlinuz.version.h))
+- VERSION_FILE := /boot/vmlinuz.version.h
+- CONFIG_FILE := /boot/vmlinuz.autoconf.h
+- KVER := $(shell $(CC) $(CFLAGS) -E -dM $(VERSION_FILE) | \
+- grep UTS_RELEASE | awk '{ print $$3 }' | sed 's/\"//g')
+- ifeq ($(KVER),$(shell uname -r))
+- # set up include path to override headers from kernel source
+- x:=$(shell rm -rf include)
+- x:=$(shell mkdir -p include/linux)
+- x:=$(shell cp /boot/vmlinuz.version.h include/linux/version.h)
+- x:=$(shell cp /boot/vmlinuz.autoconf.h include/linux/autoconf.h)
+- CFLAGS += -I./include
+- else
+- VERSION_FILE := $(KOBJ)/include/linux/version.h
+- UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h
+- CONFIG_FILE := $(KOBJ)/include/linux/autoconf.h
+- endif
+-else
+- VERSION_FILE := $(KOBJ)/include/linux/version.h
+- UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h
+- CONFIG_FILE := $(KOBJ)/include/linux/autoconf.h
+-endif
++VERSION_FILE := $(KSRC)/include/linux/version.h
++UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h
++CONFIG_FILE := $(KSRC)/include/linux/autoconf.h
+
+ ifeq (,$(wildcard $(VERSION_FILE)))
+ $(error Linux kernel source not configured - missing version.h)
+@@ -98,83 +71,8 @@ ifeq (,$(wildcard $(CONFIG_FILE)))
+ $(error Linux kernel source not configured - missing autoconf.h)
+ endif
+
+-# as of 2.6.16, kernel define UTS_RELEASE has been moved to utsrelease.h
+-# so check that file for kernel version string instead of version.h
+-USE_UTS_REL := $(shell [ -f $(UTS_REL_FILE) ] && echo "1")
+-
+-# pick a compiler
+-ifneq (,$(findstring egcs-2.91.66, $(shell cat /proc/version)))
+- CC := kgcc gcc cc
+-else
+- CC := gcc cc
+-endif
+-test_cc = $(shell $(cc) --version > /dev/null 2>&1 && echo $(cc))
+-CC := $(foreach cc, $(CC), $(test_cc))
+-CC := $(firstword $(CC))
+-ifeq (,$(CC))
+- $(error Compiler not found)
+-endif
+-
+-# we need to know what platform the driver is being built on
+-# some additional features are only built on Intel platforms
+-ARCH := $(shell uname -m | sed 's/i.86/i386/')
+-ifeq ($(ARCH),alpha)
+- CFLAGS += -ffixed-8 -mno-fp-regs
+-endif
+-ifeq ($(ARCH),x86_64)
+- CFLAGS += -mcmodel=kernel -mno-red-zone
+-endif
+-ifeq ($(ARCH),ppc)
+- CFLAGS += -msoft-float
+-endif
+-ifeq ($(ARCH),ppc64)
+- CFLAGS += -m64 -msoft-float
+- LDFLAGS += -melf64ppc
+-endif
+-
+-# standard flags for module builds
+-CFLAGS += -DLINUX -D__KERNEL__ -DMODULE -O2 -pipe -Wall
+-CFLAGS += -I$(KSRC)/include -I.
+-CFLAGS += $(shell [ -f $(KSRC)/include/linux/modversions.h ] && \
+- echo "-DMODVERSIONS -DEXPORT_SYMTAB \
+- -include $(KSRC)/include/linux/modversions.h")
+-
+-ifeq ($(IEGBE_GBE_WORKAROUND), 1)
+-CFLAGS += -DIEGBE_GBE_WORKAROUND -DE1000_NO_NAPI
+-endif
+-
+-ifeq ($(IEGBE_10_100_ONLY), 1)
+-CFLAGS += -DIEGBE_10_100_ONLY
+-endif
+-
+-CFLAGS += $(CFLAGS_EXTRA)
+-#ifeq (,$(shell echo $(CFLAGS_EXTRA) | grep NAPI))
+-#CFLAGS += -DE1000_NO_NAPI
+-#CFLAGS_EXTRA += -DE1000_NO_NAPI
+-#endif
+-
+-RHC := $(KSRC)/include/linux/rhconfig.h
+-ifneq (,$(wildcard $(RHC)))
+- # 7.3 typo in rhconfig.h
+- ifneq (,$(shell $(CC) $(CFLAGS) -E -dM $(RHC) | grep __module__bigmem))
+- CFLAGS += -D__module_bigmem
+- endif
+-endif
+-
+-# get the kernel version - we use this to find the correct install path
+-ifeq ($(USE_UTS_REL), 1)
+- KVER := $(shell $(CC) $(CFLAGS) -E -dM $(UTS_REL_FILE) | grep UTS_RELEASE | \
+- awk '{ print $$3 }' | sed 's/\"//g')
+-else
+- KVER := $(shell $(CC) $(CFLAGS) -E -dM $(VERSION_FILE) | grep UTS_RELEASE | \
+- awk '{ print $$3 }' | sed 's/\"//g')
+-endif
+-
+-KKVER := $(shell echo $(KVER) | \
+- awk '{ if ($$0 ~ /2\.[6-9]\./) print "1"; else print "0"}')
+-ifeq ($(KKVER), 0)
+- $(error *** Aborting the build. \
+- *** This driver is not supported on kernel versions older than 2.6.18)
++ifeq (,$(wildcard $(UTS_REL_FILE)))
++ $(error Linux kernel source not configured - missing utsrelease.h)
+ endif
+
+ # set the install path
+@@ -202,11 +100,11 @@ ifneq ($(SMP),$(shell uname -a | grep SM
+ endif
+
+ ifeq ($(SMP),1)
+- CFLAGS += -D__SMP__
++ EXTRA_CFLAGS += -D__SMP__
+ endif
+
+ ifeq ($(EXTERNAL_MDIO), 1)
+- CFLAGS += -DEXTERNAL_MDIO
++ EXTRA_CFLAGS += -DEXTERNAL_MDIO
+ endif
+
+ ###########################################################################
+@@ -223,7 +121,6 @@ MANSECTION = 7
+ MANFILE = $(TARGET:.ko=.$(MANSECTION))
+
+ ifneq ($(PATCHLEVEL),)
+- EXTRA_CFLAGS += $(CFLAGS_EXTRA)
+ obj-m += $(TARGET:.ko=.o)
+ iegbe-objs := $(CFILES:.c=.o)
+ ifeq ($(EXTERNAL_MDIO),1)
+--- a/filelist
++++ b/filelist
+@@ -1,41 +1,3 @@
+-Embedded/Makefile
+-Embedded/environment.mk
+-Embedded/src/1588/1588.c
+-Embedded/src/1588/1588.h
+-Embedded/src/1588/IxTimeSyncAcc_p.h
+-Embedded/src/1588/Makefile
+-Embedded/src/1588/ixtimesyncacc.c
+-Embedded/src/1588/ixtimesyncacc.h
+-Embedded/src/1588/linux_ioctls.h
+-Embedded/src/CAN/Makefile
+-Embedded/src/CAN/can_fifo.c
+-Embedded/src/CAN/can_fifo.h
+-Embedded/src/CAN/can_ioctl.h
+-Embedded/src/CAN/can_main.c
+-Embedded/src/CAN/can_main.h
+-Embedded/src/CAN/can_port.h
+-Embedded/src/CAN/icp_can.c
+-Embedded/src/CAN/icp_can.h
+-Embedded/src/CAN/icp_can_regs.h
+-Embedded/src/CAN/icp_can_types.h
+-Embedded/src/CAN/icp_can_user.h
+-Embedded/src/EDMA/Makefile
+-Embedded/src/EDMA/dma.h
+-Embedded/src/EDMA/dma_api.h
+-Embedded/src/EDMA/dma_client_api.c
+-Embedded/src/EDMA/dma_common.c
+-Embedded/src/EDMA/dma_internals.h
+-Embedded/src/EDMA/dma_linux.c
+-Embedded/src/EDMA/os/os.c
+-Embedded/src/EDMA/os/os.h
+-Embedded/src/EDMA/os/os_list.c
+-Embedded/src/EDMA/os/os_list.h
+-Embedded/src/EDMA/os/os_types.h
+-Embedded/src/GPIO/Makefile
+-Embedded/src/GPIO/common.h
+-Embedded/src/GPIO/gpio.h
+-Embedded/src/GPIO/gpio_ref.c
+-Embedded/src/GPIO/linux_ioctls.h
+ Embedded/src/GbE/Makefile
+ Embedded/src/GbE/gcu.h
+ Embedded/src/GbE/gcu_if.c
+@@ -55,16 +17,6 @@ Embedded/src/GbE/iegbe_param.c
+ Embedded/src/GbE/kcompat.c
+ Embedded/src/GbE/kcompat.h
+ Embedded/src/GbE/kcompat_ethtool.c
+-Embedded/src/WDT/Makefile
+-Embedded/src/WDT/iwdt.c
+-Embedded/src/WDT/iwdt.h
+-Embedded/src/patches/Intel_EP80579_RHEL5.patch
+-Embedded/src/patches/pci.ids_RHEL5.patch
+ LICENSE.GPL
+-build_system/build_files/Core/ia.mk
+-build_system/build_files/OS/linux_2.6.mk
+-build_system/build_files/OS/linux_2.6_kernel_space_rules.mk
+-build_system/build_files/common.mk
+-build_system/build_files/rules.mk
+ filelist
+ versionfile
+--- a/versionfile
++++ b/versionfile
+@@ -1,4 +1,4 @@
+-PACKAGE_TYPE=Embedded
++PACKAGE_TYPE=Embedded.Release.Patch
+
+ PACKAGE_OS=L
+
+@@ -6,4 +6,6 @@ PACKAGE_VERSION_MAJOR_NUMBER=1
+
+ PACKAGE_VERSION_MINOR_NUMBER=0
+
+-PACKAGE_VERSION_PATCH_NUMBER=34
++PACKAGE_VERSION_PATCH_NUMBER=7
++
++PACKAGE_VERSION_BUILD_NUMBER=5
diff --git a/package/ep80579-drivers/patches/002-cflags_cleanup.patch b/package/ep80579-drivers/patches/002-cflags_cleanup.patch
new file mode 100644
index 000000000..f89752795
--- /dev/null
+++ b/package/ep80579-drivers/patches/002-cflags_cleanup.patch
@@ -0,0 +1,22 @@
+--- a/build_system/build_files/common.mk
++++ b/build_system/build_files/common.mk
+@@ -122,7 +122,7 @@ CC=$(COMPILER)
+ LD=$(LINKER)
+ AR=$(ARCHIVER)
+
+-CFLAGS+=-O2
++#CFLAGS+=-O2
+
+
+ PWD= $(shell pwd)
+--- a/build_system/build_files/OS/linux_2.6.mk
++++ b/build_system/build_files/OS/linux_2.6.mk
+@@ -80,7 +80,7 @@ endif
+
+
+ ifeq ($(OS_LEVEL), kernel_space)
+-CFLAGS+=
++#CFLAGS+=
+ endif
+
+
diff --git a/package/ep80579-drivers/patches/003-new_irqf_constants.patch b/package/ep80579-drivers/patches/003-new_irqf_constants.patch
new file mode 100644
index 000000000..af231f218
--- /dev/null
+++ b/package/ep80579-drivers/patches/003-new_irqf_constants.patch
@@ -0,0 +1,53 @@
+--- a/Embedded/src/1588/1588.c
++++ b/Embedded/src/1588/1588.c
+@@ -291,7 +291,7 @@ int pci_probe(struct pci_dev *dev, const
+
+ }
+
+- if ( request_irq(dev->irq, &timesync_isr, SA_SHIRQ, DRIVERNAME,
++ if ( request_irq(dev->irq, &timesync_isr, IRQF_SHARED, DRIVERNAME,
+ &g_drvr_data) )
+ {
+ printk("%s-pci_probe: irq\n", DRIVERNAME);
+--- a/Embedded/src/CAN/can_main.c
++++ b/Embedded/src/CAN/can_main.c
+@@ -424,7 +424,7 @@ int can_open(struct inode *inode, struct
+ err = request_irq(
+ can_os->irq,
+ can_irq_handler,
+- SA_SHIRQ,
++ IRQF_SHARED,
+ iminor(can_os->inode) ? CAN_PROC_1 : CAN_PROC_0,
+ &(g_can_os[iminor(can_os->inode)])
+ );
+--- a/Embedded/src/EDMA/dma_linux.c
++++ b/Embedded/src/EDMA/dma_linux.c
+@@ -367,7 +367,7 @@ int32_t edma_resume(struct pci_dev *dev)
+ return -ENODEV;
+ }
+
+- if (request_irq(dev->irq, &edma_irq_handler, SA_SHIRQ,
++ if (request_irq(dev->irq, &edma_irq_handler, IRQF_SHARED,
+ g_char_drvr_name, dev) )
+ {
+
+@@ -829,7 +829,7 @@ int32_t edma_probe(struct pci_dev * dev,
+ /*
+ * Obtain a (shared) Interrupt Request (IRQ) Line from the OS.
+ */
+- if (request_irq(dev->irq, &edma_irq_handler, SA_SHIRQ,
++ if (request_irq(dev->irq, &edma_irq_handler, IRQF_SHARED,
+ g_char_drvr_name, dev) )
+ {
+
+--- a/Embedded/src/WDT/iwdt.c
++++ b/Embedded/src/WDT/iwdt.c
+@@ -1461,7 +1461,7 @@ static int __init wdt_init_one(struct pc
+
+ /* Request irq only if wdt_irq is other than 0 */
+ if (wdt_irq) {
+- if (request_irq(wdt_irq, wdt_isr, SA_INTERRUPT | SA_SHIRQ,
++ if (request_irq(wdt_irq, wdt_isr, IRQF_DISABLED | IRQF_SHARED,
+ "iwdt", &wdt_miscdev)) {
+ printk("IRQ %d is not free.\n", wdt_irq);
+ return -EIO;
diff --git a/package/ep80579-drivers/patches/100-iegbe_netdev_ops.patch b/package/ep80579-drivers/patches/100-iegbe_netdev_ops.patch
new file mode 100644
index 000000000..162449c69
--- /dev/null
+++ b/package/ep80579-drivers/patches/100-iegbe_netdev_ops.patch
@@ -0,0 +1,56 @@
+--- a/Embedded/src/GbE/iegbe_main.c
++++ b/Embedded/src/GbE/iegbe_main.c
+@@ -724,6 +724,26 @@ static void iegbe_dump_eeprom(struct ieg
+ kfree(data);
+ }
+
++static const struct net_device_ops iegbe_netdev_ops = {
++ .ndo_open = iegbe_open,
++ .ndo_stop = iegbe_close,
++ .ndo_start_xmit = iegbe_xmit_frame,
++ .ndo_get_stats = iegbe_get_stats,
++ .ndo_set_rx_mode = iegbe_set_rx_mode,
++ .ndo_set_mac_address = iegbe_set_mac,
++ .ndo_tx_timeout = iegbe_tx_timeout,
++ .ndo_change_mtu = iegbe_change_mtu,
++ .ndo_do_ioctl = iegbe_ioctl,
++ .ndo_validate_addr = eth_validate_addr,
++
++ .ndo_vlan_rx_register = iegbe_vlan_rx_register,
++ .ndo_vlan_rx_add_vid = iegbe_vlan_rx_add_vid,
++ .ndo_vlan_rx_kill_vid = iegbe_vlan_rx_kill_vid,
++#ifdef CONFIG_NET_POLL_CONTROLLER
++ .ndo_poll_controller = iegbe_netpoll,
++#endif
++};
++
+ /**
+ * iegbe_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+@@ -800,24 +820,11 @@ static int __devinit iegbe_probe(struct
+ if (!hw->hw_addr)
+ goto err_ioremap;
+
+- netdev->open = &iegbe_open;
+- netdev->stop = &iegbe_close;
+- netdev->hard_start_xmit = &iegbe_xmit_frame;
+- netdev->get_stats = &iegbe_get_stats;
+- netdev->set_rx_mode = &iegbe_set_rx_mode;
+- netdev->set_mac_address = &iegbe_set_mac;
+- netdev->change_mtu = &iegbe_change_mtu;
+- netdev->do_ioctl = &iegbe_ioctl;
++ netdev->netdev_ops = &iegbe_netdev_ops;
+ set_ethtool_ops(netdev);
+- netdev->tx_timeout = &iegbe_tx_timeout;
+ netdev->watchdog_timeo = 5 * HZ;
+ netif_napi_add(netdev, &adapter->napi, iegbe_clean, 64);
+- netdev->vlan_rx_register = iegbe_vlan_rx_register;
+- netdev->vlan_rx_add_vid = iegbe_vlan_rx_add_vid;
+- netdev->vlan_rx_kill_vid = iegbe_vlan_rx_kill_vid;
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+- netdev->poll_controller = iegbe_netpoll;
+-#endif
++
+ strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
+
+
diff --git a/package/ep80579-drivers/patches/101-iegbe_fix_napi_interface.patch b/package/ep80579-drivers/patches/101-iegbe_fix_napi_interface.patch
new file mode 100644
index 000000000..921d464ba
--- /dev/null
+++ b/package/ep80579-drivers/patches/101-iegbe_fix_napi_interface.patch
@@ -0,0 +1,41 @@
+--- a/Embedded/src/GbE/iegbe_main.c
++++ b/Embedded/src/GbE/iegbe_main.c
+@@ -3465,12 +3465,12 @@ static irqreturn_t iegbe_intr_msi(int ir
+ printk("Critical error! ICR = 0x%x\n", icr);
+ return IRQ_HANDLED;
+ }
+- if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) {
++ if (likely(napi_schedule_prep(&adapter->napi))) {
+ adapter->total_tx_bytes = 0;
+ adapter->total_tx_packets = 0;
+ adapter->total_rx_bytes = 0;
+ adapter->total_rx_packets = 0;
+- __netif_rx_schedule(netdev, &adapter->napi);
++ __napi_schedule(&adapter->napi);
+ } else
+ iegbe_irq_enable(adapter);
+
+@@ -3527,12 +3527,12 @@ iegbe_intr(int irq, void *data)
+ E1000_WRITE_REG(&adapter->hw, IMC, ~0);
+ E1000_WRITE_FLUSH(&adapter->hw);
+ }
+- if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) {
++ if (likely(napi_schedule_prep(&adapter->napi))) {
+ adapter->total_tx_bytes = 0;
+ adapter->total_tx_packets = 0;
+ adapter->total_rx_bytes = 0;
+ adapter->total_rx_packets = 0;
+- __netif_rx_schedule(netdev, &adapter->napi);
++ __napi_schedule(&adapter->napi);
+ } else
+ /* this really should not happen! if it does it is basically a
+ * bug, but not a hard error, so enable ints and continue */
+@@ -3574,7 +3574,7 @@ static int iegbe_clean(struct napi_struc
+ if (work_done < budget) {
+ if (likely(adapter->itr_setting & 3))
+ iegbe_set_itr(adapter);
+- netif_rx_complete(poll_dev, napi);
++ napi_complete(napi);
+ iegbe_irq_enable(adapter);
+ }
+
diff --git a/package/ep80579-drivers/patches/102-iegbe_nuke_polling_netdev.patch b/package/ep80579-drivers/patches/102-iegbe_nuke_polling_netdev.patch
new file mode 100644
index 000000000..f7ca62709
--- /dev/null
+++ b/package/ep80579-drivers/patches/102-iegbe_nuke_polling_netdev.patch
@@ -0,0 +1,103 @@
+--- a/Embedded/src/GbE/iegbe.h
++++ b/Embedded/src/GbE/iegbe.h
+@@ -316,7 +316,6 @@ struct iegbe_adapter {
+ int cleaned_count);
+ struct iegbe_rx_ring *rx_ring; /* One per active queue */
+ struct napi_struct napi;
+- struct net_device *polling_netdev; /* One per active queue */
+
+ int num_tx_queues;
+ int num_rx_queues;
+--- a/Embedded/src/GbE/iegbe_main.c
++++ b/Embedded/src/GbE/iegbe_main.c
+@@ -763,7 +763,7 @@ static int __devinit iegbe_probe(struct
+ struct iegbe_hw *hw;
+
+ static int cards_found = 0;
+- int i, err, pci_using_dac;
++ int err, pci_using_dac;
+ u16 eeprom_data = 0;
+ u16 eeprom_apme_mask = E1000_EEPROM_APME;
+ int bars;
+@@ -984,11 +984,8 @@ err_eeprom:
+ iegbe_phy_hw_reset(hw);
+ if (hw->flash_address)
+ iounmap(hw->flash_address);
+- for (i = 0; i < adapter->num_rx_queues; i++)
+- dev_put(&adapter->polling_netdev[i]);
+ kfree(adapter->tx_ring);
+ kfree(adapter->rx_ring);
+- kfree(adapter->polling_netdev);
+ err_sw_init:
+ iounmap(hw->hw_addr);
+ err_ioremap:
+@@ -1017,7 +1014,6 @@ iegbe_remove(struct pci_dev *pdev)
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct iegbe_adapter *adapter = netdev_priv(netdev);
+ uint32_t manc;
+- int i;
+
+ if(adapter->hw.mac_type >= iegbe_82540
+ && adapter->hw.mac_type != iegbe_icp_xxxx
+@@ -1030,15 +1026,11 @@ iegbe_remove(struct pci_dev *pdev)
+ }
+
+ unregister_netdev(netdev);
+- for (i = 0x0; i < adapter->num_rx_queues; i++)
+- dev_put(&adapter->polling_netdev[i]);
+-
+ if(!iegbe_check_phy_reset_block(&adapter->hw)) {
+ iegbe_phy_hw_reset(&adapter->hw);
+ }
+ kfree(adapter->tx_ring);
+ kfree(adapter->rx_ring);
+- kfree(adapter->polling_netdev);
+
+ iounmap(adapter->hw.hw_addr);
+ pci_release_regions(pdev);
+@@ -1061,7 +1053,6 @@ iegbe_sw_init(struct iegbe_adapter *adap
+ struct iegbe_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
+- int i;
+
+ /* PCI config space info */
+
+@@ -1111,11 +1102,6 @@ iegbe_sw_init(struct iegbe_adapter *adap
+ return -ENOMEM;
+ }
+
+- for (i = 0; i < adapter->num_rx_queues; i++) {
+- adapter->polling_netdev[i].priv = adapter;
+- dev_hold(&adapter->polling_netdev[i]);
+- set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state);
+- }
+ spin_lock_init(&adapter->tx_queue_lock);
+
+ /*
+@@ -1137,8 +1123,7 @@ iegbe_sw_init(struct iegbe_adapter *adap
+ * @adapter: board private structure to initialize
+ *
+ * We allocate one ring per queue at run-time since we don't know the
+- * number of queues at compile-time. The polling_netdev array is
+- * intended for Multiqueue, but should work fine with a single queue.
++ * number of queues at compile-time.
+ **/
+
+ static int __devinit
+@@ -1158,15 +1143,6 @@ iegbe_alloc_queues(struct iegbe_adapter
+ return -ENOMEM;
+ }
+
+- adapter->polling_netdev = kcalloc(adapter->num_rx_queues,
+- sizeof(struct net_device),
+- GFP_KERNEL);
+- if (!adapter->polling_netdev) {
+- kfree(adapter->tx_ring);
+- kfree(adapter->rx_ring);
+- return -ENOMEM;
+- }
+-
+ return E1000_SUCCESS;
+ }
+
diff --git a/package/ep80579-drivers/patches/103-iegbe_convert_unicast_addr_list.patch b/package/ep80579-drivers/patches/103-iegbe_convert_unicast_addr_list.patch
new file mode 100644
index 000000000..71d2d54e6
--- /dev/null
+++ b/package/ep80579-drivers/patches/103-iegbe_convert_unicast_addr_list.patch
@@ -0,0 +1,60 @@
+--- a/Embedded/src/GbE/iegbe_main.c
++++ b/Embedded/src/GbE/iegbe_main.c
+@@ -2161,7 +2161,8 @@ static void iegbe_set_rx_mode(struct net
+ {
+ struct iegbe_adapter *adapter = netdev_priv(netdev);
+ struct iegbe_hw *hw = &adapter->hw;
+- struct dev_addr_list *uc_ptr;
++ struct netdev_hw_addr *ha;
++ bool use_uc = false;
+ struct dev_addr_list *mc_ptr;
+ u32 rctl;
+ u32 hash_value;
+@@ -2187,12 +2188,11 @@ int mta_reg_count = E1000_NUM_MTA_REGIST
+ }
+ }
+
+- uc_ptr = NULL;
+ if (netdev->uc_count > rar_entries - 1) {
+ rctl |= E1000_RCTL_UPE;
+ } else if (!(netdev->flags & IFF_PROMISC)) {
+ rctl &= ~E1000_RCTL_UPE;
+- uc_ptr = netdev->uc_list;
++ use_uc = true;
+ }
+
+ E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+@@ -2210,13 +2210,20 @@ int mta_reg_count = E1000_NUM_MTA_REGIST
+ * if there are not 14 addresses, go ahead and clear the filters
+ * -- with 82571 controllers only 0-13 entries are filled here
+ */
++ i = 1;
++ if (use_uc)
++ list_for_each_entry(ha, &netdev->uc_list, list) {
++ if (i == rar_entries)
++ break;
++ iegbe_rar_set(hw, ha->addr, i++);
++ }
++
++ WARN_ON(i == rar_entries);
++
+ mc_ptr = netdev->mc_list;
+
+- for (i = 1; i < rar_entries; i++) {
+- if (uc_ptr) {
+- iegbe_rar_set(hw, uc_ptr->da_addr, i);
+- uc_ptr = uc_ptr->next;
+- } else if (mc_ptr) {
++ for (; i < rar_entries; i++) {
++ if (mc_ptr) {
+ iegbe_rar_set(hw, mc_ptr->da_addr, i);
+ mc_ptr = mc_ptr->next;
+ } else {
+@@ -2226,7 +2233,6 @@ int mta_reg_count = E1000_NUM_MTA_REGIST
+ E1000_WRITE_FLUSH(&adapter->hw);
+ }
+ }
+- WARN_ON(uc_ptr != NULL);
+
+ /* clear the old settings from the multicast hash table */
+
diff --git a/package/ep80579-drivers/patches/104-iegbe_group_address_list_and_its_count.patch b/package/ep80579-drivers/patches/104-iegbe_group_address_list_and_its_count.patch
new file mode 100644
index 000000000..c6eced6a5
--- /dev/null
+++ b/package/ep80579-drivers/patches/104-iegbe_group_address_list_and_its_count.patch
@@ -0,0 +1,20 @@
+--- a/Embedded/src/GbE/iegbe_main.c
++++ b/Embedded/src/GbE/iegbe_main.c
+@@ -2188,7 +2188,7 @@ int mta_reg_count = E1000_NUM_MTA_REGIST
+ }
+ }
+
+- if (netdev->uc_count > rar_entries - 1) {
++ if (netdev->uc.count > rar_entries - 1) {
+ rctl |= E1000_RCTL_UPE;
+ } else if (!(netdev->flags & IFF_PROMISC)) {
+ rctl &= ~E1000_RCTL_UPE;
+@@ -2212,7 +2212,7 @@ int mta_reg_count = E1000_NUM_MTA_REGIST
+ */
+ i = 1;
+ if (use_uc)
+- list_for_each_entry(ha, &netdev->uc_list, list) {
++ list_for_each_entry(ha, &netdev->uc.list, list) {
+ if (i == rar_entries)
+ break;
+ iegbe_rar_set(hw, ha->addr, i++);
diff --git a/package/ep80579-drivers/patches/105-iegbe_new_dma_masks.patch b/package/ep80579-drivers/patches/105-iegbe_new_dma_masks.patch
new file mode 100644
index 000000000..d5fc46f79
--- /dev/null
+++ b/package/ep80579-drivers/patches/105-iegbe_new_dma_masks.patch
@@ -0,0 +1,20 @@
+--- a/Embedded/src/GbE/iegbe_main.c
++++ b/Embedded/src/GbE/iegbe_main.c
+@@ -775,13 +775,13 @@ static int __devinit iegbe_probe(struct
+ if (err)
+ return err;
+
+- if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK) &&
+- !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
++ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) &&
++ !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
+ pci_using_dac = 1;
+ } else {
+- err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
++ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (err) {
+- err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
++ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (err) {
+ E1000_ERR("No usable DMA configuration, "
+ "aborting\n");
diff --git a/package/ep80579-drivers/patches/106-iegbe_new_irqf_constant.patch b/package/ep80579-drivers/patches/106-iegbe_new_irqf_constant.patch
new file mode 100644
index 000000000..a08e8c769
--- /dev/null
+++ b/package/ep80579-drivers/patches/106-iegbe_new_irqf_constant.patch
@@ -0,0 +1,12 @@
+--- a/Embedded/src/GbE/iegbe_ethtool.c
++++ b/Embedded/src/GbE/iegbe_ethtool.c
+@@ -944,7 +944,8 @@ iegbe_intr_test(struct iegbe_adapter *ad
+ *data = 0;
+
+ /* Hook up test interrupt handler just for this test */
+- if(!request_irq(irq, &iegbe_test_intr, 0, netdev->name, netdev)) {
++ if(!request_irq(irq, &iegbe_test_intr, IRQF_PROBE_SHARED, netdev->name,
++ netdev)) {
+ shared_int = FALSE;
+ } else if(request_irq(irq, &iegbe_test_intr, IRQF_SHARED,
+ netdev->name, netdev)){
diff --git a/package/ep80579-drivers/patches/150-ocracoke_island.patch b/package/ep80579-drivers/patches/150-ocracoke_island.patch
new file mode 100644
index 000000000..ae74e0c90
--- /dev/null
+++ b/package/ep80579-drivers/patches/150-ocracoke_island.patch
@@ -0,0 +1,747 @@
+--- a/Embedded/src/GbE/iegbe_oem_phy.c
++++ b/Embedded/src/GbE/iegbe_oem_phy.c
+@@ -65,6 +65,10 @@ static int32_t iegbe_oem_link_m88_setup(
+ static int32_t iegbe_oem_set_phy_mode(struct iegbe_hw *hw);
+ static int32_t iegbe_oem_detect_phy(struct iegbe_hw *hw);
+
++static int32_t iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw);
++static int32_t bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data);
++static int32_t oi_phy_setup (struct iegbe_hw *hw);
++
+ /**
+ * iegbe_oem_setup_link
+ * @hw: iegbe_hw struct containing device specific information
+@@ -114,6 +118,10 @@ iegbe_oem_setup_link(struct iegbe_hw *hw
+ }
+
+ switch (hw->phy_id) {
++ case BCM5395S_PHY_ID:
++ return E1000_SUCCESS;
++ break;
++
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+ ret_val = iegbe_oem_link_m88_setup(hw);
+@@ -121,6 +129,12 @@ iegbe_oem_setup_link(struct iegbe_hw *hw
+ return ret_val;
+ }
+ break;
++ case BCM5481_PHY_ID:
++ ret_val = iegbe_oem_link_bcm5481_setup(hw);
++ if(ret_val) {
++ return ret_val;
++ }
++ break;
+ default:
+ DEBUGOUT("Invalid PHY ID\n");
+ return -E1000_ERR_PHY_TYPE;
+@@ -179,6 +193,51 @@ iegbe_oem_setup_link(struct iegbe_hw *hw
+ #endif /* ifdef EXTERNAL_MDIO */
+ }
+
++/**
++ * iegbe_oem_link_bcm5481_setup
++ * @hw: iegbe_hw struct containing device specific information
++ *
++ * Returns E1000_SUCCESS, negative E1000 error code on failure
++ *
++ * copied verbatim from iegbe_oem_link_m88_setup
++ **/
++static int32_t
++iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw)
++{
++ int32_t ret_val;
++ uint16_t phy_data;
++
++ //DEBUGFUNC(__func__);
++
++ if(!hw)
++ return -1;
++
++ /* phy_reset_disable is set in iegbe_oem_set_phy_mode */
++ if(hw->phy_reset_disable)
++ return E1000_SUCCESS;
++
++ // Enable MDIX in extended control reg.
++ ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ECTRL, &phy_data);
++ if(ret_val)
++ {
++ DEBUGOUT("Unable to read BCM5481_ECTRL register\n");
++ return ret_val;
++ }
++
++ phy_data &= ~BCM5481_ECTRL_DISMDIX;
++ ret_val = iegbe_oem_write_phy_reg_ex(hw, BCM5481_ECTRL, phy_data);
++ if(ret_val)
++ {
++ DEBUGOUT("Unable to write BCM5481_ECTRL register\n");
++ return ret_val;
++ }
++
++ ret_val = oi_phy_setup (hw);
++ if (ret_val)
++ return ret_val;
++
++ return E1000_SUCCESS;
++}
+
+ /**
+ * iegbe_oem_link_m88_setup
+@@ -340,6 +399,11 @@ iegbe_oem_force_mdi(struct iegbe_hw *hw,
+ * see iegbe_phy_force_speed_duplex, which does the following for M88
+ */
+ switch (hw->phy_id) {
++ case BCM5395S_PHY_ID:
++ case BCM5481_PHY_ID:
++ DEBUGOUT("WARNING: An empty iegbe_oem_force_mdi() has been called!\n");
++ break;
++
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+ ret_val = iegbe_oem_read_phy_reg_ex(hw,
+@@ -415,6 +479,8 @@ iegbe_oem_phy_reset_dsp(struct iegbe_hw
+ switch (hw->phy_id) {
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
++ case BCM5481_PHY_ID:
++ case BCM5395S_PHY_ID:
+ DEBUGOUT("No DSP to reset on OEM PHY\n");
+ break;
+ default:
+@@ -460,6 +526,11 @@ iegbe_oem_cleanup_after_phy_reset(struct
+ * see iegbe_phy_force_speed_duplex, which does the following for M88
+ */
+ switch (hw->phy_id) {
++ case BCM5395S_PHY_ID:
++ case BCM5481_PHY_ID:
++ DEBUGOUT("WARNING: An empty iegbe_oem_cleanup_after_phy_reset() has been called!\n");
++ break;
++
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+ /*
+@@ -573,6 +644,11 @@ iegbe_oem_set_phy_mode(struct iegbe_hw *
+ * use iegbe_set_phy_mode as example
+ */
+ switch (hw->phy_id) {
++ case BCM5395S_PHY_ID:
++ case BCM5481_PHY_ID:
++ DEBUGOUT("WARNING: An empty iegbe_oem_set_phy_mode() has been called!\n");
++ break;
++
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+ ret_val = iegbe_read_eeprom(hw,
+@@ -641,6 +717,19 @@ iegbe_oem_detect_phy(struct iegbe_hw *hw
+ }
+ hw->phy_type = iegbe_phy_oem;
+
++{
++ // If MAC2 (BCM5395 switch), manually detect the phy
++ struct iegbe_adapter *adapter;
++ uint32_t device_number;
++ adapter = (struct iegbe_adapter *) hw->back;
++ device_number = PCI_SLOT(adapter->pdev->devfn);
++ if (device_number == ICP_XXXX_MAC_2) {
++ hw->phy_id = BCM5395S_PHY_ID;
++ hw->phy_revision = 0;
++ return E1000_SUCCESS;
++ }
++}
++
+ ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_ID1, &phy_id_high);
+ if(ret_val) {
+ DEBUGOUT("Unable to read PHY register PHY_ID1\n");
+@@ -690,6 +779,8 @@ iegbe_oem_get_tipg(struct iegbe_hw *hw)
+ switch (hw->phy_id) {
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
++ case BCM5481_PHY_ID:
++ case BCM5395S_PHY_ID:
+ phy_num = DEFAULT_ICP_XXXX_TIPG_IPGT;
+ break;
+ default:
+@@ -738,6 +829,8 @@ iegbe_oem_phy_is_copper(struct iegbe_hw
+ switch (hw->phy_id) {
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
++ case BCM5481_PHY_ID:
++ case BCM5395S_PHY_ID:
+ isCopper = TRUE;
+ break;
+ default:
+@@ -796,13 +889,13 @@ iegbe_oem_get_phy_dev_number(struct iegb
+ switch(device_number)
+ {
+ case ICP_XXXX_MAC_0:
+- hw->phy_addr = 0x00;
++ hw->phy_addr = 0x01;
+ break;
+ case ICP_XXXX_MAC_1:
+- hw->phy_addr = 0x01;
++ hw->phy_addr = 0x02;
+ break;
+ case ICP_XXXX_MAC_2:
+- hw->phy_addr = 0x02;
++ hw->phy_addr = 0x00;
+ break;
+ default: hw->phy_addr = 0x00;
+ }
+@@ -851,6 +944,12 @@ iegbe_oem_mii_ioctl(struct iegbe_adapter
+ if(!adapter || !ifr) {
+ return -1;
+ }
++
++ // If MAC2 (BCM5395 switch) then leave now
++ if ((PCI_SLOT(adapter->pdev->devfn)) == ICP_XXXX_MAC_2) {
++ return -1;
++ }
++
+ switch (data->reg_num) {
+ case PHY_CTRL:
+ if(mii_reg & MII_CR_POWER_DOWN) {
+@@ -987,6 +1086,11 @@ void iegbe_oem_get_phy_regs(struct iegbe
+ * [10] = mdix mode
+ */
+ switch (adapter->hw.phy_id) {
++ case BCM5395S_PHY_ID:
++ case BCM5481_PHY_ID:
++ DEBUGOUT("WARNING: An empty iegbe_oem_get_phy_regs() has been called!\n");
++ break;
++
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+ if(corrected_len > 0) {
+@@ -1068,8 +1172,13 @@ iegbe_oem_phy_loopback(struct iegbe_adap
+ * Loopback configuration is the same for each of the supported PHYs.
+ */
+ switch (adapter->hw.phy_id) {
++ case BCM5395S_PHY_ID:
++ DEBUGOUT("WARNING: An empty iegbe_oem_phy_loopback() has been called!\n");
++ break;
++
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
++ case BCM5481_PHY_ID:
+
+ adapter->hw.autoneg = FALSE;
+
+@@ -1182,8 +1291,14 @@ iegbe_oem_loopback_cleanup(struct iegbe_
+ }
+
+ switch (adapter->hw.phy_id) {
++ case BCM5395S_PHY_ID:
++ DEBUGOUT("WARNING: An empty iegbe_oem_loopback_cleanup() has been called!\n");
++ return;
++ break;
++
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
++ case BCM5481_PHY_ID:
+ default:
+ adapter->hw.autoneg = TRUE;
+
+@@ -1243,6 +1358,11 @@ iegbe_oem_phy_speed_downgraded(struct ie
+ */
+
+ switch (hw->phy_id) {
++ case BCM5395S_PHY_ID:
++ case BCM5481_PHY_ID:
++ *isDowngraded = 0;
++ break;
++
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS,
+@@ -1305,6 +1425,11 @@ iegbe_oem_check_polarity(struct iegbe_hw
+ */
+
+ switch (hw->phy_id) {
++ case BCM5395S_PHY_ID:
++ case BCM5481_PHY_ID:
++ *polarity = 0;
++ break;
++
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+ /* return the Polarity bit in the Status register. */
+@@ -1367,6 +1492,25 @@ iegbe_oem_phy_is_full_duplex(struct iegb
+ */
+
+ switch (hw->phy_id) {
++ case BCM5395S_PHY_ID:
++ /* Always full duplex */
++ *isFD = 1;
++ break;
++
++ case BCM5481_PHY_ID:
++ ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data);
++ if(ret_val) return ret_val;
++
++ switch (BCM5481_ASTAT_HCD(phy_data)) {
++ case BCM5481_ASTAT_1KBTFD:
++ case BCM5481_ASTAT_100BTXFD:
++ *isFD = 1;
++ break;
++ default:
++ *isFD = 0;
++ }
++ break;
++
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS,
+@@ -1423,6 +1567,25 @@ iegbe_oem_phy_is_speed_1000(struct iegbe
+ */
+
+ switch (hw->phy_id) {
++ case BCM5395S_PHY_ID:
++ /* Always 1000mb */
++ *is1000 = 1;
++ break;
++
++ case BCM5481_PHY_ID:
++ ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data);
++ if(ret_val) return ret_val;
++
++ switch (BCM5481_ASTAT_HCD(phy_data)) {
++ case BCM5481_ASTAT_1KBTFD:
++ case BCM5481_ASTAT_1KBTHD:
++ *is1000 = 1;
++ break;
++ default:
++ *is1000 = 0;
++ }
++ break;
++
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS,
+@@ -1478,6 +1641,25 @@ iegbe_oem_phy_is_speed_100(struct iegbe_
+ * see iegbe_config_mac_to_phy
+ */
+ switch (hw->phy_id) {
++ case BCM5395S_PHY_ID:
++ /* Always 1000Mb, never 100mb */
++ *is100 = 0;
++ break;
++
++ case BCM5481_PHY_ID:
++ ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data);
++ if(ret_val) return ret_val;
++
++ switch (BCM5481_ASTAT_HCD(phy_data)) {
++ case BCM5481_ASTAT_100BTXFD:
++ case BCM5481_ASTAT_100BTXHD:
++ *is100 = 1;
++ break;
++ default:
++ *is100 = 0;
++ }
++ break;
++
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+ ret_val = iegbe_oem_read_phy_reg_ex(hw,
+@@ -1535,6 +1717,11 @@ iegbe_oem_phy_get_info(struct iegbe_hw *
+ * see iegbe_phy_m88_get_info
+ */
+ switch (hw->phy_id) {
++ case BCM5395S_PHY_ID:
++ case BCM5481_PHY_ID:
++ DEBUGOUT("WARNING: An empty iegbe_oem_phy_get_info() has been called!\n");
++ break;
++
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+ /* The downshift status is checked only once, after link is
+@@ -1636,8 +1823,13 @@ iegbe_oem_phy_hw_reset(struct iegbe_hw *
+ * the M88 used in truxton.
+ */
+ switch (hw->phy_id) {
++ case BCM5395S_PHY_ID:
++ DEBUGOUT("WARNING: An empty iegbe_oem_phy_hw_reset() has been called!\n");
++ break;
++
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
++ case BCM5481_PHY_ID:
+ ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_CTRL, &phy_data);
+ if(ret_val) {
+ DEBUGOUT("Unable to read register PHY_CTRL\n");
+@@ -1699,6 +1891,8 @@ iegbe_oem_phy_init_script(struct iegbe_h
+ switch (hw->phy_id) {
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
++ case BCM5481_PHY_ID:
++ case BCM5395S_PHY_ID:
+ DEBUGOUT("Nothing to do for OEM PHY Init");
+ break;
+ default:
+@@ -1735,6 +1929,11 @@ iegbe_oem_read_phy_reg_ex(struct iegbe_h
+ return -1;
+ }
+
++ if (hw->phy_id == BCM5395S_PHY_ID) {
++ DEBUGOUT("WARNING: iegbe_oem_read_phy_reg_ex() has been unexpectedly called!\n");
++ return -1;
++ }
++
+ /* call the GCU func that will read the phy
+ *
+ * Make note that the M88 phy is what'll be used on Truxton.
+@@ -1782,6 +1981,11 @@ iegbe_oem_set_trans_gasket(struct iegbe_
+ }
+
+ switch (hw->phy_id) {
++ case BCM5395S_PHY_ID:
++ case BCM5481_PHY_ID:
++ DEBUGOUT("WARNING: An empty iegbe_oem_set_trans_gasket() has been called!\n");
++ break;
++
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+ /* Gasket set correctly for Marvell Phys, so nothing to do */
+@@ -1886,6 +2090,8 @@ iegbe_oem_phy_needs_reset_with_mac(struc
+ switch (hw->phy_id) {
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
++ case BCM5481_PHY_ID:
++ case BCM5395S_PHY_ID:
+ ret_val = FALSE;
+ break;
+ default:
+@@ -1935,6 +2141,8 @@ iegbe_oem_config_dsp_after_link_change(s
+ switch (hw->phy_id) {
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
++ case BCM5481_PHY_ID:
++ case BCM5395S_PHY_ID:
+ DEBUGOUT("No DSP to configure on OEM PHY");
+ break;
+ default:
+@@ -1978,6 +2186,12 @@ iegbe_oem_get_cable_length(struct iegbe_
+ }
+
+ switch (hw->phy_id) {
++ case BCM5395S_PHY_ID:
++ case BCM5481_PHY_ID:
++ *min_length = 0;
++ *max_length = iegbe_igp_cable_length_150;
++ break;
++
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+ ret_val = iegbe_oem_read_phy_reg_ex(hw,
+@@ -2061,6 +2275,23 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw
+ */
+
+ switch (hw->phy_id) {
++ case BCM5395S_PHY_ID:
++ /* Link always up */
++ *isUp = TRUE;
++ return E1000_SUCCESS;
++ break;
++
++ case BCM5481_PHY_ID:
++ iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data);
++ ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data);
++ if(ret_val)
++ {
++ DEBUGOUT("Unable to read PHY register BCM5481_ESTAT\n");
++ return ret_val;
++ }
++ statusMask = BCM5481_ESTAT_LINK;
++ break;
++
+ case M88E1000_I_PHY_ID:
+ case M88E1141_E_PHY_ID:
+ iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+@@ -2092,3 +2323,210 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw
+ #endif /* ifdef EXTERNAL_MDIO */
+ }
+
++
++
++//-----
++// Read BCM5481 expansion register
++//
++int32_t
++bcm5481_read_ex (struct iegbe_hw *hw, uint16_t reg, uint16_t *data)
++{
++ int ret;
++ uint16_t selector;
++ uint16_t reg_data;
++
++ // Get the current value of bits 15:12
++ ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, &selector);
++ if (ret)
++ return ret;
++
++ // Select the expansion register
++ selector &= 0xf000;
++ selector |= (0xf << 8) | (reg);
++ iegbe_oem_write_phy_reg_ex (hw, 0x17, selector);
++
++ // Read the expansion register
++ ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, &reg_data);
++
++ // De-select the expansion registers.
++ selector &= 0xf000;
++ iegbe_oem_write_phy_reg_ex (hw, 0x17, selector);
++
++ if (ret)
++ return ret;
++
++ *data = reg_data;
++ return ret;
++}
++
++//-----
++// Read reg 0x18 sub-register
++//
++static int32_t
++bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data)
++{
++ int ret;
++ uint16_t tmp_data;
++
++ // Select reg 0x18, sv
++ tmp_data = ((sv & BCM5481_R18H_SV_MASK) << 12) | BCM5481_R18H_SV_MCTRL;
++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, tmp_data);
++ if(ret)
++ return ret;
++
++ // Read reg 0x18, sv
++ ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R18H, &tmp_data);
++ if(ret)
++ return ret;
++
++ *data = tmp_data;
++ return ret;
++}
++
++//-----
++// Read reg 0x1C sub-register
++//
++int32_t
++bcm5481_read_1csv (struct iegbe_hw *hw, int sv, uint16_t *data)
++{
++ int ret;
++ uint16_t tmp_data;
++
++ // Select reg 0x1c, sv
++ tmp_data = ((sv & BCM5481_R1CH_SV_MASK) << BCM5481_R1CH_SV_SHIFT);
++
++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, tmp_data);
++ if(ret)
++ return ret;
++
++ // Read reg 0x1c, sv
++ ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R1CH, &tmp_data);
++ if(ret)
++ return ret;
++
++ *data = tmp_data;
++ return ret;
++}
++
++//-----
++// Read-modify-write a 0x1C register.
++//
++// hw - hardware access info.
++// reg - 0x1C register to modify.
++// data - bits which should be set.
++// mask - the '1' bits in this argument will be cleared in the data
++// read from 'reg' then 'data' will be or'd in and the result
++// will be written to 'reg'.
++
++int32_t
++bcm5481_rmw_1csv (struct iegbe_hw *hw, uint16_t reg, uint16_t data, uint16_t mask)
++{
++ int32_t ret;
++ uint16_t reg_data;
++
++ ret = 0;
++
++ ret = bcm5481_read_1csv (hw, reg, &reg_data);
++ if (ret)
++ {
++ DEBUGOUT("Unable to read BCM5481 1CH register\n");
++ printk (KERN_ERR "Unable to read BCM5481 1CH register [0x%x]\n", reg);
++ return ret;
++ }
++
++ reg_data &= ~mask;
++ reg_data |= (BCM5481_R1CH_WE | data);
++
++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, reg_data);
++ if(ret)
++ {
++ DEBUGOUT("Unable to write BCM5481 1CH register\n");
++ printk (KERN_ERR "Unable to write BCM5481 1CH register\n");
++ return ret;
++ }
++
++ return ret;
++}
++
++int32_t
++oi_phy_setup (struct iegbe_hw *hw)
++{
++ int ret;
++ uint16_t pmii_data;
++ uint16_t mctrl_data;
++ uint16_t cacr_data;
++
++ ret = 0;
++
++ // Set low power mode via reg 0x18, sv010, bit 6
++ // Do a read-modify-write on reg 0x18, sv010 register to preserve existing bits.
++ ret = bcm5481_read_18sv (hw, BCM5481_R18H_SV_PMII, &pmii_data);
++ if (ret)
++ {
++ DEBUGOUT("Unable to read BCM5481_R18H_SV_PMII register\n");
++ printk (KERN_ERR "Unable to read BCM5481_R18H_SV_PMII register\n");
++ return ret;
++ }
++
++ // Set the LPM bit in the data just read and write back to sv010
++ // The shadow register select bits [2:0] are set by reading the sv010
++ // register.
++ pmii_data |= BCM5481_R18H_SV010_LPM;
++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, pmii_data);
++ if(ret)
++ {
++ DEBUGOUT("Unable to write BCM5481_R18H register\n");
++ printk (KERN_ERR "Unable to write BCM5481_R18H register\n");
++ return ret;
++ }
++
++
++ // Set the RGMII RXD to RXC skew bit in reg 0x18, sv111
++
++ if (bcm5481_read_18sv (hw, BCM5481_R18H_SV_MCTRL, &mctrl_data))
++ {
++ DEBUGOUT("Unable to read BCM5481_R18H_SV_MCTRL register\n");
++ printk (KERN_ERR "Unable to read BCM5481_R18H_SV_MCTRL register\n");
++ return ret;
++ }
++ mctrl_data |= (BCM5481_R18H_WE | BCM5481_R18H_SV111_SKEW);
++
++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, mctrl_data);
++ if(ret)
++ {
++ DEBUGOUT("Unable to write BCM5481_R18H register\n");
++ printk (KERN_ERR "Unable to write BCM5481_R18H register\n");
++ return ret;
++ }
++
++ // Enable RGMII transmit clock delay in reg 0x1c, sv00011
++ ret = bcm5481_read_1csv (hw, BCM5481_R1CH_CACR, &cacr_data);
++ if (ret)
++ {
++ DEBUGOUT("Unable to read BCM5481_R1CH_CACR register\n");
++ printk (KERN_ERR "Unable to read BCM5481_R1CH_CACR register\n");
++ return ret;
++ }
++
++ cacr_data |= (BCM5481_R1CH_WE | BCM5481_R1CH_CACR_TCD);
++
++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, cacr_data);
++ if(ret)
++ {
++ DEBUGOUT("Unable to write BCM5481_R1CH register\n");
++ printk (KERN_ERR "Unable to write BCM5481_R1CH register\n");
++ return ret;
++ }
++
++ // Enable dual link speed indication (0x1c, sv 00010, bit 2)
++ ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_SC1, BCM5481_R1CH_SC1_LINK, BCM5481_R1CH_SC1_LINK);
++ if (ret)
++ return ret;
++
++ // Enable link and activity on ACTIVITY LED (0x1c, sv 01001, bit 4=1, bit 3=0)
++ ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_LCTRL, BCM5481_R1CH_LCTRL_ALEN, BCM5481_R1CH_LCTRL_ALEN | BCM5481_R1CH_LCTRL_AEN);
++ if (ret)
++ return ret;
++
++ return ret;
++}
+--- a/Embedded/src/GbE/iegbe_oem_phy.h
++++ b/Embedded/src/GbE/iegbe_oem_phy.h
+@@ -95,6 +95,8 @@ int32_t iegbe_oem_phy_is_link_up(struct
+
+ #define DEFAULT_ICP_XXXX_TIPG_IPGT 8 /* Inter Packet Gap Transmit Time */
+ #define ICP_XXXX_TIPG_IPGT_MASK 0x000003FFUL
++#define BCM5481_PHY_ID 0x0143BCA0
++#define BCM5395S_PHY_ID 0x0143BCF0
+
+ /* Miscellaneous defines */
+ #ifdef IEGBE_10_100_ONLY
+@@ -103,5 +105,65 @@ int32_t iegbe_oem_phy_is_link_up(struct
+ #define ICP_XXXX_AUTONEG_ADV_DEFAULT 0x2F
+ #endif
+
++/* BCM5481 specifics */
++
++#define BCM5481_ECTRL (0x10)
++#define BCM5481_ESTAT (0x11)
++#define BCM5481_RXERR (0x12)
++#define BCM5481_EXPRW (0x15)
++#define BCM5481_EXPACC (0x17)
++#define BCM5481_ASTAT (0x19)
++#define BCM5481_R18H (0x18)
++#define BCM5481_R1CH (0x1c)
++
++/* indirect register access via register 18h */
++
++#define BCM5481_R18H_SV_MASK (7) // Mask for SV bits.
++#define BCM5481_R18H_SV_ACTRL (0) // SV000 Aux. control
++#define BCM5481_R18H_SV_10BT (1) // SV001 10Base-T
++#define BCM5481_R18H_SV_PMII (2) // SV010 Power/MII control
++#define BCM5481_R18H_SV_MTEST (4) // SV100 Misc. test
++#define BCM5481_R18H_SV_MCTRL (7) // SV111 Misc. control
++
++#define BCM5481_R18H_SV001_POL (1 << 13) // Polarity
++#define BCM5481_R18H_SV010_LPM (1 << 6)
++#define BCM5481_R18H_SV111_SKEW (1 << 8)
++#define BCM5481_R18H_WE (1 << 15) // Write enable
++
++// 0x1c registers
++#define BCM5481_R1CH_SV_SHIFT (10)
++#define BCM5481_R1CH_SV_MASK (0x1f)
++#define BCM5481_R1CH_SC1 (0x02) // sv00010 Spare control 1
++#define BCM5481_R1CH_CACR (0x03) // sv00011 Clock alignment control
++#define BCM5481_R1CH_LCTRL (0x09) // sv01001 LED control
++#define BCM5481_R1CH_LEDS1 (0x0d) // sv01101 LED selector 1
++
++// 0x1c common
++#define BCM5481_R1CH_WE (1 << 15) // Write enable
++
++// 0x1c, sv 00010
++#define BCM5481_R1CH_SC1_LINK (1 << 2) // sv00010 Linkspeed
++
++// 0x1c, sv 00011
++#define BCM5481_R1CH_CACR_TCD (1 << 9) // sv00011 RGMII tx clock delay
++
++// 0x1c, sv 01001
++#define BCM5481_R1CH_LCTRL_ALEN (1 << 4) // Activity/Link enable on ACTIVITY LED
++#define BCM5481_R1CH_LCTRL_AEN (1 << 3) // Activity enable on ACTIVITY LED
++
++#define BCM5481_ECTRL_DISMDIX (1 <<14)
++
++#define BCM5481_MCTRL_AUTOMDIX (1 <<9)
++
++#define BCM5481_ESTAT_LINK (1 << 8)
++
++#define BCM5481_ASTAT_ANC (1 << 15)
++#define BCM5481_ASTAT_ANHCD (7 << 8)
++#define BCM5481_ASTAT_HCD(x) ((x >> 8) & 7)
++#define BCM5481_ASTAT_1KBTFD (0x7)
++#define BCM5481_ASTAT_1KBTHD (0x6)
++#define BCM5481_ASTAT_100BTXFD (0x5)
++#define BCM5481_ASTAT_100BTXHD (0x3)
++
+ #endif /* ifndef _IEGBE_OEM_PHY_H_ */
+
diff --git a/package/ep80579-drivers/patches/200-can_fix_ioctl_numbers.patch b/package/ep80579-drivers/patches/200-can_fix_ioctl_numbers.patch
new file mode 100644
index 000000000..291946625
--- /dev/null
+++ b/package/ep80579-drivers/patches/200-can_fix_ioctl_numbers.patch
@@ -0,0 +1,11 @@
+--- a/Embedded/src/CAN/icp_can_user.h
++++ b/Embedded/src/CAN/icp_can_user.h
+@@ -63,6 +63,8 @@
+ #ifndef __ICP_CAN_USER_H__
+ #define __ICP_CAN_USER_H__
+
++#include <linux/ioctl.h>
++
+ /*****************************************************************************
+ * Device IO control codes.
+ *****************************************************************************/
diff --git a/package/ep80579-drivers/patches/210-can_include_linux_fs_h.patch b/package/ep80579-drivers/patches/210-can_include_linux_fs_h.patch
new file mode 100644
index 000000000..26c53dcea
--- /dev/null
+++ b/package/ep80579-drivers/patches/210-can_include_linux_fs_h.patch
@@ -0,0 +1,11 @@
+--- a/Embedded/src/CAN/can_main.c
++++ b/Embedded/src/CAN/can_main.c
+@@ -70,6 +70,8 @@
+
+ #include "can_main.h"
+ #include "can_ioctl.h"
++#include <linux/fs.h>
++
+
+ MODULE_AUTHOR("Intel(R) Corporation");
+ MODULE_DESCRIPTION("Controller Area Network Driver");
diff --git a/package/ep80579-drivers/patches/220-can_fix_irq_request.patch b/package/ep80579-drivers/patches/220-can_fix_irq_request.patch
new file mode 100644
index 000000000..2950cc79e
--- /dev/null
+++ b/package/ep80579-drivers/patches/220-can_fix_irq_request.patch
@@ -0,0 +1,23 @@
+--- a/Embedded/src/CAN/can_main.c
++++ b/Embedded/src/CAN/can_main.c
+@@ -654,7 +654,7 @@ int can_dev_io(struct inode *inode, stru
+ /*****************************************************************************
+ * Interrupt handler.
+ *****************************************************************************/
+-irqreturn_t can_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
++irqreturn_t can_irq_handler(int irq, void *dev_id)
+ {
+ can_os_t *can_os = (can_os_t *) dev_id;
+ unsigned int int_status;
+--- a/Embedded/src/CAN/can_main.h
++++ b/Embedded/src/CAN/can_main.h
+@@ -165,8 +165,7 @@ int can_dev_io(
+
+ irqreturn_t can_irq_handler(
+ int irq,
+- void *dev_id,
+- struct pt_regs *regs);
++ void *dev_id);
+
+ void can_tasklet(
+ unsigned long arg
diff --git a/package/ep80579-drivers/patches/230-can_remove_driver_data_direct_access.patch b/package/ep80579-drivers/patches/230-can_remove_driver_data_direct_access.patch
new file mode 100644
index 000000000..19dbb7e0b
--- /dev/null
+++ b/package/ep80579-drivers/patches/230-can_remove_driver_data_direct_access.patch
@@ -0,0 +1,40 @@
+--- a/Embedded/src/CAN/can_main.c
++++ b/Embedded/src/CAN/can_main.c
+@@ -214,8 +214,8 @@ int can_pci_probe(struct pci_dev *dev, c
+ spin_lock_init(&(g_can_os[can_num].int_spinlock));
+ spin_lock_init(&(g_can_os[can_num].open_spinlock));
+
+- dev->dev.driver_data = (void *) &(g_can_os[can_num]);
+- if (!dev->dev.driver_data)
++ dev_set_drvdata(&dev->dev, (void *) &(g_can_os[can_num]));
++ if (!dev_get_drvdata(&dev->dev))
+ {
+ printk("Couldn't create CAN device %d. Exiting.\n",
+ dev->device);
+@@ -237,7 +237,7 @@ int can_pci_probe(struct pci_dev *dev, c
+ *****************************************************************************/
+ void can_pci_remove(struct pci_dev *dev)
+ {
+- can_os_t *can_os = dev->dev.driver_data;
++ can_os_t *can_os = dev_get_drvdata(&dev->dev);
+
+ iounmap(can_os->pci_remap);
+ icp_can_destroy(can_os->can);
+@@ -251,7 +251,7 @@ int can_pci_suspend(struct pci_dev *dev,
+ {
+ unsigned int i;
+ unsigned int int_status;
+- can_os_t *can_os = dev->dev.driver_data;
++ can_os_t *can_os = dev_get_drvdata(&dev->dev);
+ int err;
+
+ /* Indicate that we are suspending */
+@@ -322,7 +322,7 @@ int can_pci_suspend(struct pci_dev *dev,
+ int can_pci_resume(struct pci_dev *dev)
+ {
+ unsigned int i;
+- can_os_t *can_os = dev->dev.driver_data;
++ can_os_t *can_os = dev_get_drvdata(&dev->dev);
+
+ /* Restore PCI CFG space */
+ pci_restore_state(dev);
diff --git a/package/ep80579-drivers/patches/300-wdt_compile_fix.patch b/package/ep80579-drivers/patches/300-wdt_compile_fix.patch
new file mode 100644
index 000000000..59242b80b
--- /dev/null
+++ b/package/ep80579-drivers/patches/300-wdt_compile_fix.patch
@@ -0,0 +1,59 @@
+--- a/Embedded/src/WDT/iwdt.c
++++ b/Embedded/src/WDT/iwdt.c
+@@ -180,19 +180,19 @@ MODULE_PARM_DESC(wdt_scale, "Intel WDT s
+ module_param(wdt_intr_type, byte, WDT_INT_TYPE_IRQ);
+ MODULE_PARM_DESC(wdt_intr_type, "Intel WDT interrupt type (default SERIRQ).");
+
+-module_param(wdt_margin1, uint, TIMER_MARGIN);
++module_param(wdt_margin1, uint, 0);
+ MODULE_PARM_DESC(wdt_margin1, "First stage Intel WDT timeout in steps of 1 ms by default.");
+
+-module_param(wdt_margin2, uint, TIMER_MARGIN);
++module_param(wdt_margin2, uint, 0);
+ MODULE_PARM_DESC(wdt_margin2, "Second stage Intel WDT timeout in steps of 1 ms by default.");
+
+ module_param(nowayout, int, 0);
+ MODULE_PARM_DESC(nowayout, "Intel WDT can't be stopped once started (default=0)");
+
+-module_param(wdt_index_port, int, 0x4E);
++module_param(wdt_index_port, int, 0);
+ MODULE_PARM_DESC(wdt_index_port, "WDT Index Port (default 0x4e)");
+
+-module_param(wdt_data_port, int, 0x4E);
++module_param(wdt_data_port, int, 0);
+ MODULE_PARM_DESC(wdt_data_port, "WDT Data Port (default 0x4f)");
+
+ static int wdt_get_iobase(struct pci_dev *dev, u16 *iobase, int *irq);
+@@ -218,7 +218,7 @@ static ssize_t wdt_write(struct file *fi
+ size_t count, loff_t * pos);
+ static int wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg);
+-static irqreturn_t wdt_isr(int irq, void *dev_id, struct pt_regs *regs);
++static irqreturn_t wdt_isr(int irq, void *dev_id);
+ static void __exit wdt_cleanup(void);
+ static int __init wdt_init(void);
+ static int __init wdt_init_one(struct pci_dev *dev,
+@@ -255,7 +255,7 @@ static struct pci_driver wdt_driver = {
+ name: "iwdt",
+ id_table: lpc_pci_tbl,
+ probe: wdt_init_one,
+- remove: __devexit(wdt_remove_one),
++ remove: __devexit_p(wdt_remove_one),
+ suspend: wdt_pci_suspend,
+ resume: wdt_pci_resume,
+ };
+@@ -1393,12 +1393,12 @@ static int wdt_ioctl(struct inode *inode
+
+ /*
+ * Function Name: wdt_isr()
+- * Parameter: int irq - irq number, void *dev_id, struct pt_regs *regs
++ * Parameter: int irq - irq number, void *dev_id
+ * Return Value:: IRQ_NONE - if the interrupt is not for wdt.
+ * IRQ_HANDLED - if it is for wdt.
+ * Description: This is the interrupt service routine of the WDT.
+ */
+-static irqreturn_t wdt_isr(int irq, void *dev_id, struct pt_regs *regs)
++static irqreturn_t wdt_isr(int irq, void *dev_id)
+ {
+ u8 val;
+
diff --git a/package/ep80579-drivers/patches/400-edma_fix_irq_request_warning.patch b/package/ep80579-drivers/patches/400-edma_fix_irq_request_warning.patch
new file mode 100644
index 000000000..d858aff1f
--- /dev/null
+++ b/package/ep80579-drivers/patches/400-edma_fix_irq_request_warning.patch
@@ -0,0 +1,22 @@
+--- a/Embedded/src/EDMA/dma_linux.c
++++ b/Embedded/src/EDMA/dma_linux.c
+@@ -149,8 +149,7 @@ int32_t edma_suspend (struct pci_dev *de
+ int32_t edma_resume(struct pci_dev *dev);
+ int32_t initialize_edma_device(struct edma_device *device);
+
+-static irqreturn_t edma_irq_handler(int32_t irq, void * dev_id,
+- struct pt_regs * regs);
++static irqreturn_t edma_irq_handler(int32_t irq, void * dev_id);
+
+ /* Prototypes - Misc. */
+
+@@ -429,8 +428,7 @@ int32_t edma_release(struct inode * inod
+ * Return Values: HANDLED = 1, NOT_HANDLED = 0
+ *****************************************************************************/
+
+-static irqreturn_t edma_irq_handler(int32_t irq, void * dev_id,
+- struct pt_regs * regs)
++static irqreturn_t edma_irq_handler(int32_t irq, void * dev_id)
+ {
+
+ uint32_t clear_bits;
diff --git a/package/ep80579-drivers/patches/500-1588_fix_irq_request_warning.patch b/package/ep80579-drivers/patches/500-1588_fix_irq_request_warning.patch
new file mode 100644
index 000000000..f3f9acb1e
--- /dev/null
+++ b/package/ep80579-drivers/patches/500-1588_fix_irq_request_warning.patch
@@ -0,0 +1,22 @@
+--- a/Embedded/src/1588/1588.c
++++ b/Embedded/src/1588/1588.c
+@@ -631,7 +631,7 @@ int restore_interrupts(void)
+ IRQ_NONE => this device did not interrupt
+
+ ******************************************************************************/
+-irqreturn_t timesync_isr(int irq, void *dev_id, struct pt_regs *regs)
++irqreturn_t timesync_isr(int irq, void *dev_id)
+ {
+ if ( !ixTimeSyncAccEventAmmsFlagGet() && !ixTimeSyncAccEventAsmsFlagGet()&&
+ !ixTimeSyncAccEventAtmFlagGet() && !ixTimeSyncAccEventPpsmFlagGet()&&
+--- a/Embedded/src/1588/1588.h
++++ b/Embedded/src/1588/1588.h
+@@ -128,7 +128,7 @@ int pci_suspend(struct pci_dev *dev, pm_
+ int pci_resume(struct pci_dev *dev);
+ int pci_probe(struct pci_dev *dev, const struct pci_device_id *id);
+ void pci_remove(struct pci_dev *dev);
+-irqreturn_t timesync_isr(int irq, void *dev_id, struct pt_regs *regs);
++irqreturn_t timesync_isr(int irq, void *dev_id);
+
+ // private functions
+ int save_reg_state(void);
diff --git a/package/ep80579-drivers/patches/600-2.6.27_includes.patch b/package/ep80579-drivers/patches/600-2.6.27_includes.patch
new file mode 100644
index 000000000..c11275ece
--- /dev/null
+++ b/package/ep80579-drivers/patches/600-2.6.27_includes.patch
@@ -0,0 +1,22 @@
+--- a/Embedded/src/CAN/can_main.h
++++ b/Embedded/src/CAN/can_main.h
+@@ -65,7 +65,7 @@
+
+ #include <linux/interrupt.h>
+ #include <linux/pci.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ #include <linux/spinlock.h>
+ #include <linux/cdev.h>
+ #include <asm/uaccess.h>
+--- a/Embedded/src/EDMA/dma_linux.c
++++ b/Embedded/src/EDMA/dma_linux.c
+@@ -87,7 +87,7 @@
+ #include <linux/fcntl.h> /* O_ACCMODE */
+ #include <asm/system.h> /* cli, *_flags */
+ #include <asm/uaccess.h> /* copy_to_user */
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ #include <asm/io.h> /* inb(), outb() */
+ #include <linux/kmod.h>
+ #include <linux/ioport.h> /* request_region */
diff --git a/package/ep80579-drivers/patches/601-2.6.32_includes.patch b/package/ep80579-drivers/patches/601-2.6.32_includes.patch
new file mode 100644
index 000000000..291fb0a33
--- /dev/null
+++ b/package/ep80579-drivers/patches/601-2.6.32_includes.patch
@@ -0,0 +1,30 @@
+--- a/Embedded/src/1588/1588.c
++++ b/Embedded/src/1588/1588.c
+@@ -72,6 +72,7 @@
+ *
+ ****************************************************************************/
+
++#include <linux/sched.h>
+ #include "1588.h"
+
+ MODULE_AUTHOR("Intel(R) Corporation");
+--- a/Embedded/src/CAN/can_main.c
++++ b/Embedded/src/CAN/can_main.c
+@@ -68,6 +68,7 @@
+ *
+ **************************************************************************/
+
++#include <linux/sched.h>
+ #include "can_main.h"
+ #include "can_ioctl.h"
+ #include <linux/fs.h>
+--- a/Embedded/src/WDT/iwdt.c
++++ b/Embedded/src/WDT/iwdt.c
+@@ -137,6 +137,7 @@
+ #include <linux/watchdog.h>
+ #include <linux/miscdevice.h>
+ #include <linux/interrupt.h>
++#include <linux/sched.h>
+ #include "iwdt.h"
+
+ MODULE_AUTHOR("Intel(R) Corporation");
diff --git a/package/ep80579-drivers/patches/700-iegbe_kcompat_2.6.30.patch b/package/ep80579-drivers/patches/700-iegbe_kcompat_2.6.30.patch
new file mode 100644
index 000000000..ca8c1bb9e
--- /dev/null
+++ b/package/ep80579-drivers/patches/700-iegbe_kcompat_2.6.30.patch
@@ -0,0 +1,31 @@
+--- a/Embedded/src/GbE/kcompat.h
++++ b/Embedded/src/GbE/kcompat.h
+@@ -46,12 +46,6 @@ GPL LICENSE SUMMARY
+ #include <linux/sched.h>
+ #include <asm/io.h>
+
+-#ifndef IRQ_HANDLED
+-#define irqreturn_t void
+-#define IRQ_HANDLED
+-#define IRQ_NONE
+-#endif
+-
+ #ifndef SET_NETDEV_DEV
+ #define SET_NETDEV_DEV(net, pdev)
+ #endif
+@@ -748,6 +742,15 @@ extern void dump_stack(void);
+
+ #endif /* 2.4.24 */
+
++/*****************************************************************************/
++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) )
++#ifndef IRQ_HANDLED
++#define irqreturn_t void
++#define IRQ_HANDLED
++#define IRQ_NONE
++#endif
++#endif /* < 2.6.30 */
++
+ #endif /* _KCOMPAT_H_ */
+
+
diff --git a/package/ep80579-drivers/patches/701-iegbe_poll_dev.patch b/package/ep80579-drivers/patches/701-iegbe_poll_dev.patch
new file mode 100644
index 000000000..63a132685
--- /dev/null
+++ b/package/ep80579-drivers/patches/701-iegbe_poll_dev.patch
@@ -0,0 +1,11 @@
+--- a/Embedded/src/GbE/iegbe_main.c
++++ b/Embedded/src/GbE/iegbe_main.c
+@@ -3534,7 +3534,7 @@ static int iegbe_clean(struct napi_struc
+ int tx_cleaned = 0, work_done = 0;
+
+ /* Must NOT use netdev_priv macro here. */
+- adapter = poll_dev->priv;
++ adapter = netdev_priv(poll_dev);
+
+ /* iegbe_clean is called per-cpu. This lock protects
+ * tx_ring[0] from being cleaned by multiple cpus
diff --git a/package/ep80579-drivers/patches/710-3.3-fix-generated-header-locations.patch b/package/ep80579-drivers/patches/710-3.3-fix-generated-header-locations.patch
new file mode 100644
index 000000000..793d08d39
--- /dev/null
+++ b/package/ep80579-drivers/patches/710-3.3-fix-generated-header-locations.patch
@@ -0,0 +1,91 @@
+--- a/Embedded/src/GbE/Makefile
++++ b/Embedded/src/GbE/Makefile
+@@ -60,19 +60,19 @@ GBE_NAME = iegbe
+ GCU_NAME = gcu
+
+ VERSION_FILE := $(KSRC)/include/linux/version.h
+-UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h
+-CONFIG_FILE := $(KSRC)/include/linux/autoconf.h
++UTS_REL_FILE := $(KSRC)/include/generated/utsrelease.h
++CONFIG_FILE := $(KSRC)/include/generated/autoconf.h
+
+ ifeq (,$(wildcard $(VERSION_FILE)))
+ $(error Linux kernel source not configured - missing version.h)
+ endif
+
+ ifeq (,$(wildcard $(CONFIG_FILE)))
+- $(error Linux kernel source not configured - missing autoconf.h)
++ $(error Linux kernel source not configured - missing autoconf.h)
+ endif
+
+ ifeq (,$(wildcard $(UTS_REL_FILE)))
+- $(error Linux kernel source not configured - missing utsrelease.h)
++ $(error Linux kernel source not configured - missing utsrelease.h)
+ endif
+
+ # set the install path
+--- a/Embedded/src/1588/Makefile
++++ b/Embedded/src/1588/Makefile
+@@ -97,8 +97,8 @@ OUTPUT_PATH ?= /
+ EXTRA_LDFLAGS += -whole-archive
+
+ VERSION_FILE := $(KOBJ)/include/linux/version.h
+-UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h
+-CONFIG_FILE := $(KOBJ)/include/linux/autoconf.h
++UTS_REL_FILE := $(KSRC)/include/generated/utsrelease.h
++CONFIG_FILE := $(KOBJ)/include/generated/autoconf.h
+
+
+ # as of 2.6.16, kernel define UTS_RELEASE has been moved to utsrelease.h
+--- a/Embedded/src/CAN/Makefile
++++ b/Embedded/src/CAN/Makefile
+@@ -100,8 +100,8 @@ OUTPUT_PATH ?= /
+ EXTRA_LDFLAGS += -whole-archive
+
+ VERSION_FILE := $(KOBJ)/include/linux/version.h
+-UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h
+-CONFIG_FILE := $(KOBJ)/include/linux/autoconf.h
++UTS_REL_FILE := $(KSRC)/include/generated/utsrelease.h
++CONFIG_FILE := $(KOBJ)/include/generated/autoconf.h
+
+
+ # as of 2.6.16, kernel define UTS_RELEASE has been moved to utsrelease.h
+--- a/Embedded/src/EDMA/Makefile
++++ b/Embedded/src/EDMA/Makefile
+@@ -114,8 +114,8 @@ OUTPUT_PATH ?= /
+ EXTRA_LDFLAGS += -whole-archive
+
+ VERSION_FILE := $(KOBJ)/include/linux/version.h
+-UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h
+-CONFIG_FILE := $(KOBJ)/include/linux/autoconf.h
++UTS_REL_FILE := $(KSRC)/include/generated/utsrelease.h
++CONFIG_FILE := $(KOBJ)/include/generated/autoconf.h
+
+
+ # as of 2.6.16, kernel define UTS_RELEASE has been moved to utsrelease.h
+--- a/Embedded/src/GPIO/Makefile
++++ b/Embedded/src/GPIO/Makefile
+@@ -97,8 +97,8 @@ OUTPUT_PATH ?= /
+ EXTRA_LDFLAGS += -whole-archive
+
+ VERSION_FILE := $(KOBJ)/include/linux/version.h
+-UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h
+-CONFIG_FILE := $(KOBJ)/include/linux/autoconf.h
++UTS_REL_FILE := $(KSRC)/include/generated/utsrelease.h
++CONFIG_FILE := $(KOBJ)/include/generated/autoconf.h
+
+
+ # as of 2.6.16, kernel define UTS_RELEASE has been moved to utsrelease.h
+--- a/Embedded/src/WDT/Makefile
++++ b/Embedded/src/WDT/Makefile
+@@ -99,8 +99,8 @@ OUTPUT_PATH ?= /
+ EXTRA_LDFLAGS += -whole-archive
+
+ VERSION_FILE := $(KOBJ)/include/linux/version.h
+-UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h
+-CONFIG_FILE := $(KOBJ)/include/linux/autoconf.h
++UTS_REL_FILE := $(KSRC)/include/generated/utsrelease.h
++CONFIG_FILE := $(KOBJ)/include/generated/autoconf.h
+
+
+ # as of 2.6.16, kernel define UTS_RELEASE has been moved to utsrelease.h
diff --git a/package/ep80579-drivers/patches/711-3.3-gbe-fixes.patch b/package/ep80579-drivers/patches/711-3.3-gbe-fixes.patch
new file mode 100644
index 000000000..7b2df6398
--- /dev/null
+++ b/package/ep80579-drivers/patches/711-3.3-gbe-fixes.patch
@@ -0,0 +1,392 @@
+--- a/Embedded/src/GbE/kcompat.h
++++ b/Embedded/src/GbE/kcompat.h
+@@ -590,6 +590,10 @@ static inline void _kc_synchronize_irq()
+ #define ETHTOOL_OPS_COMPAT
+ #endif
+
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
++#define HAVE_NETIF_MSG 1
++#endif
++
+ #ifndef HAVE_NETIF_MSG
+ #define HAVE_NETIF_MSG 1
+ enum {
+--- a/Embedded/src/GbE/iegbe_main.c
++++ b/Embedded/src/GbE/iegbe_main.c
+@@ -159,9 +159,9 @@ static void iegbe_smartspeed(struct iegb
+ static inline int iegbe_82547_fifo_workaround(struct iegbe_adapter *adapter,
+ struct sk_buff *skb);
+
+-static void iegbe_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
+-static void iegbe_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
+-static void iegbe_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
++static bool iegbe_vlan_used(struct iegbe_adapter *adapter);
++static int iegbe_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
++static int iegbe_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
+ static void iegbe_restore_vlan(struct iegbe_adapter *adapter);
+
+ static int iegbe_notify_reboot(struct notifier_block *,
+@@ -324,8 +324,8 @@ static void iegbe_update_mng_vlan(struct
+ struct net_device *netdev = adapter->netdev;
+ u16 vid = hw->mng_cookie.vlan_id;
+ u16 old_vid = adapter->mng_vlan_id;
+- if (adapter->vlgrp) {
+- if (!vlan_group_get_device(adapter->vlgrp, vid)) {
++ if (iegbe_vlan_used(adapter)) {
++ if (!test_bit(old_vid, adapter->active_vlans)) {
+ if (hw->mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
+ iegbe_vlan_rx_add_vid(netdev, vid);
+@@ -335,7 +335,7 @@ static void iegbe_update_mng_vlan(struct
+
+ if ((old_vid != (u16)E1000_MNG_VLAN_NONE) &&
+ (vid != old_vid) &&
+- !vlan_group_get_device(adapter->vlgrp, old_vid))
++ !test_bit(old_vid, adapter->active_vlans))
+ iegbe_vlan_rx_kill_vid(netdev, old_vid);
+ } else
+ adapter->mng_vlan_id = vid;
+@@ -736,7 +736,6 @@ static const struct net_device_ops iegbe
+ .ndo_do_ioctl = iegbe_ioctl,
+ .ndo_validate_addr = eth_validate_addr,
+
+- .ndo_vlan_rx_register = iegbe_vlan_rx_register,
+ .ndo_vlan_rx_add_vid = iegbe_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = iegbe_vlan_rx_kill_vid,
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+@@ -767,7 +766,6 @@ static int __devinit iegbe_probe(struct
+ u16 eeprom_data = 0;
+ u16 eeprom_apme_mask = E1000_EEPROM_APME;
+ int bars;
+- DECLARE_MAC_BUF(mac);
+
+ bars = pci_select_bars(pdev, IORESOURCE_MEM);
+ err = pci_enable_device(pdev);
+@@ -1247,8 +1245,7 @@ static int iegbe_close(struct net_device
+
+ if ((hw->mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+- !(adapter->vlgrp &&
+- vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id))) {
++ !test_bit(adapter->mng_vlan_id, adapter->active_vlans)) {
+ iegbe_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
+ }
+ return 0;
+@@ -2163,11 +2160,13 @@ static void iegbe_set_rx_mode(struct net
+ struct iegbe_hw *hw = &adapter->hw;
+ struct netdev_hw_addr *ha;
+ bool use_uc = false;
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0))
+ struct dev_addr_list *mc_ptr;
+- u32 rctl;
+ u32 hash_value;
+- int i, rar_entries = E1000_RAR_ENTRIES;
+ int mta_reg_count = E1000_NUM_MTA_REGISTERS;
++#endif
++ u32 rctl;
++ int i, rar_entries = E1000_RAR_ENTRIES;
+
+ /* reserve RAR[14] for LAA over-write work-around */
+ if (hw->mac_type == iegbe_82571)
+@@ -2220,6 +2219,7 @@ int mta_reg_count = E1000_NUM_MTA_REGIST
+
+ WARN_ON(i == rar_entries);
+
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0))
+ mc_ptr = netdev->mc_list;
+
+ for (; i < rar_entries; i++) {
+@@ -2247,6 +2247,7 @@ int mta_reg_count = E1000_NUM_MTA_REGIST
+ hash_value = iegbe_hash_mc_addr(hw, mc_ptr->da_addr);
+ iegbe_mta_set(hw, hash_value);
+ }
++#endif
+
+ if (hw->mac_type == iegbe_82542_rev2_0)
+ iegbe_leave_82542_rst(adapter);
+@@ -2821,14 +2822,14 @@ static int iegbe_tx_map(struct iegbe_ada
+ * Avoid terminating buffers within evenly-aligned
+ * dwords. */
+ if(unlikely(adapter->pcix_82544 &&
+- !((unsigned long)(frag->page+offset+size-1) & 4) &&
++ !((unsigned long)(frag->page.p+offset+size-1) & 4) &&
+ size > 4))
+ size -= 4;
+
+ buffer_info->length = size;
+ buffer_info->dma =
+ pci_map_page(adapter->pdev,
+- frag->page,
++ frag->page.p,
+ offset,
+ size,
+ PCI_DMA_TODEVICE);
+@@ -3131,7 +3132,7 @@ static int iegbe_xmit_frame(struct sk_bu
+ }
+ }
+
+- if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
++ if (unlikely(iegbe_vlan_used(adapter) && vlan_tx_tag_present(skb))) {
+ tx_flags |= E1000_TX_FLAGS_VLAN;
+ tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
+ }
+@@ -3832,10 +3833,12 @@ static bool iegbe_clean_rx_irq(struct ie
+
+ skb->protocol = eth_type_trans(skb, netdev);
+
+- if (unlikely(adapter->vlgrp &&
++ if (unlikely(iegbe_vlan_used(adapter) &&
+ (status & E1000_RXD_STAT_VP))) {
+- vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
+- le16_to_cpu(rx_desc->special));
++ u16 vid;
++
++ vid = le16_to_cpu(rx_desc->special);
++ __vlan_hwaccel_put_tag(skb, vid);
+ } else {
+ netif_receive_skb(skb);
+ }
+@@ -3986,9 +3989,10 @@ copydone:
+ cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP)))
+ adapter->rx_hdr_split++;
+
+- if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
+- vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
+- le16_to_cpu(rx_desc->wb.middle.vlan));
++ if(unlikely(iegbe_vlan_used(adapter) && (staterr & E1000_RXD_STAT_VP))) {
++ u16 vid;
++ vid = le16_to_cpu(rx_desc->wb.middle.vlan);
++ __vlan_hwaccel_put_tag(skb, vid);
+ } else {
+ netif_receive_skb(skb);
+ }
+@@ -4496,17 +4500,25 @@ iegbe_io_write(struct iegbe_hw *hw, unsi
+ outl(value, port);
+ }
+
+-static void iegbe_vlan_rx_register(struct net_device *netdev,
+- struct vlan_group *grp)
++static bool iegbe_vlan_used(struct iegbe_adapter *adapter)
++{
++ u16 vid;
++
++ for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
++ return true;
++
++ return false;
++}
++
++static void iegbe_vlan_mode(struct net_device *netdev, bool vlan_on)
+ {
+ struct iegbe_adapter *adapter = netdev_priv(netdev);
+ uint32_t ctrl, rctl;
+
+ if (!test_bit(__E1000_DOWN, &adapter->flags))
+ iegbe_irq_disable(adapter);
+- adapter->vlgrp = grp;
+
+- if(grp) {
++ if(vlan_on) {
+ /* enable VLAN tag insert/strip */
+ ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+ ctrl |= E1000_CTRL_VME;
+@@ -4538,30 +4550,37 @@ static void iegbe_vlan_rx_register(struc
+ iegbe_irq_enable(adapter);
+ }
+
+-static void iegbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
++static int iegbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+ {
+ struct iegbe_adapter *adapter = netdev_priv(netdev);
+ uint32_t vfta, index;
+ if((adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+ (vid == adapter->mng_vlan_id)) {
+- return;
++ return 0;
+ }
++
++ if (!iegbe_vlan_used(adapter))
++ iegbe_vlan_mode(netdev, true);
++
+ /* add VID to filter table */
+ index = (vid >> 0x5) & 0x7F;
+ vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
+ vfta |= (0x1 << (vid & 0x1F));
+ iegbe_write_vfta(&adapter->hw, index, vfta);
++
++ set_bit(vid, adapter->active_vlans);
++
++ return 0;
+ }
+
+-static void iegbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
++static int iegbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+ {
+ struct iegbe_adapter *adapter = netdev_priv(netdev);
+ u32 vfta, index;
+
+ if (!test_bit(__E1000_DOWN, &adapter->flags))
+ iegbe_irq_disable(adapter);
+- vlan_group_set_device(adapter->vlgrp, vid, NULL);
+ if (!test_bit(__E1000_DOWN, &adapter->flags))
+ iegbe_irq_enable(adapter);
+
+@@ -4570,21 +4589,26 @@ static void iegbe_vlan_rx_kill_vid(struc
+ vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
+ vfta &= ~(0x1 << (vid & 0x1F));
+ iegbe_write_vfta(&adapter->hw, index, vfta);
++
++ clear_bit(vid, adapter->active_vlans);
++
++ if (!iegbe_vlan_used(adapter))
++ iegbe_vlan_mode(netdev, false);
++
++ return 0;
+ }
+
+ static void iegbe_restore_vlan(struct iegbe_adapter *adapter)
+ {
+- iegbe_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+-
+- if (adapter->vlgrp) {
+ u16 vid;
+- for (vid = 0x0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+- if (!vlan_group_get_device(adapter->vlgrp, vid))
+- continue;
++
++ if (!iegbe_vlan_used(adapter))
++ return;
++
++ iegbe_vlan_mode(adapter->netdev, true);
++ for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+ iegbe_vlan_rx_add_vid(adapter->netdev, vid);
+ }
+- }
+-}
+
+
+ int iegbe_set_spd_dplx(struct iegbe_adapter *adapter, u16 spddplx)
+@@ -4864,10 +4888,11 @@ iegbe_resume(struct pci_dev *pdev)
+ default:
+ break;
+ }
+-#endif
+
+ return 0x0;
+ }
++#endif
++
+
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ /*
+--- a/Embedded/src/GbE/iegbe_ethtool.c
++++ b/Embedded/src/GbE/iegbe_ethtool.c
+@@ -327,6 +327,7 @@ iegbe_set_pauseparam(struct net_device *
+ return 0;
+ }
+
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0))
+ static uint32_t
+ iegbe_get_rx_csum(struct net_device *netdev)
+ {
+@@ -392,6 +393,7 @@ iegbe_set_tso(struct net_device *netdev,
+ return 0;
+ }
+ #endif /* NETIF_F_TSO */
++#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)) */
+
+ static uint32_t
+ iegbe_get_msglevel(struct net_device *netdev)
+@@ -807,6 +809,7 @@ err_setup_rx:
+ E1000_82542_##R : E1000_##R; \
+ return 1; } }
+
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0))
+ static int
+ iegbe_reg_test(struct iegbe_adapter *adapter, uint64_t *data)
+ {
+@@ -1710,6 +1713,7 @@ iegbe_diag_test(struct net_device *netde
+ }
+ msleep_interruptible(0xfa0);
+ }
++#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)) */
+
+ static void
+ iegbe_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+@@ -1812,6 +1816,7 @@ iegbe_set_wol(struct net_device *netdev,
+ /* bit defines for adapter->led_status */
+ #define E1000_LED_ON 0
+
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0))
+ static void
+ iegbe_led_blink_callback(unsigned long data)
+ {
+@@ -1864,6 +1869,7 @@ iegbe_phys_id(struct net_device *netdev,
+
+ return 0;
+ }
++#endif
+
+ static int
+ iegbe_nway_reset(struct net_device *netdev)
+@@ -1876,11 +1882,13 @@ iegbe_nway_reset(struct net_device *netd
+ return 0;
+ }
+
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0))
+ static int
+ iegbe_get_stats_count(struct net_device *netdev)
+ {
+ return E1000_STATS_LEN;
+ }
++#endif
+
+ static void
+ iegbe_get_ethtool_stats(struct net_device *netdev,
+@@ -1936,6 +1944,8 @@ struct ethtool_ops iegbe_ethtool_ops = {
+ .set_ringparam = iegbe_set_ringparam,
+ .get_pauseparam = iegbe_get_pauseparam,
+ .set_pauseparam = iegbe_set_pauseparam,
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0))
+ .get_rx_csum = iegbe_get_rx_csum,
+ .set_rx_csum = iegbe_set_rx_csum,
+ .get_tx_csum = iegbe_get_tx_csum,
+@@ -1946,11 +1956,13 @@ struct ethtool_ops iegbe_ethtool_ops = {
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = iegbe_set_tso,
+ #endif
++
+ .self_test_count = iegbe_diag_test_count,
+ .self_test = iegbe_diag_test,
+- .get_strings = iegbe_get_strings,
+ .phys_id = iegbe_phys_id,
+ .get_stats_count = iegbe_get_stats_count,
++#endif
++ .get_strings = iegbe_get_strings,
+ .get_ethtool_stats = iegbe_get_ethtool_stats,
+ };
+
+--- a/Embedded/src/GbE/gcu_main.c
++++ b/Embedded/src/GbE/gcu_main.c
+@@ -93,7 +93,7 @@ static struct pci_driver gcu_driver = {
+ };
+
+ static struct gcu_adapter *global_adapter = 0;
+-static spinlock_t global_adapter_spinlock = SPIN_LOCK_UNLOCKED;
++static DEFINE_SPINLOCK(global_adapter_spinlock);
+ static unsigned long g_intflags = 0;
+
+ MODULE_AUTHOR("Intel(R) Corporation");
+--- a/Embedded/src/GbE/iegbe.h
++++ b/Embedded/src/GbE/iegbe.h
+@@ -257,7 +257,7 @@ struct iegbe_adapter {
+ struct timer_list tx_fifo_stall_timer;
+ struct timer_list watchdog_timer;
+ struct timer_list phy_info_timer;
+- struct vlan_group *vlgrp;
++ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
+ uint16_t mng_vlan_id;
+ uint32_t bd_number;
+ uint32_t rx_buffer_len;
diff --git a/package/ep80579-drivers/patches/712-3.3-can-fixes.patch b/package/ep80579-drivers/patches/712-3.3-can-fixes.patch
new file mode 100644
index 000000000..f46f90093
--- /dev/null
+++ b/package/ep80579-drivers/patches/712-3.3-can-fixes.patch
@@ -0,0 +1,41 @@
+--- a/Embedded/src/CAN/can_main.c
++++ b/Embedded/src/CAN/can_main.c
+@@ -72,6 +72,7 @@
+ #include "can_main.h"
+ #include "can_ioctl.h"
+ #include <linux/fs.h>
++#include <linux/module.h>
+
+
+ MODULE_AUTHOR("Intel(R) Corporation");
+@@ -110,7 +111,7 @@ struct file_operations file_ops = {
+ .owner = THIS_MODULE,
+ .read = can_read,
+ .write = can_write,
+- .ioctl = can_dev_io,
++ .unlocked_ioctl = can_dev_io,
+ .open = can_open,
+ .release = can_release
+ };
+@@ -594,8 +595,7 @@ int icp_can_reset(can_os_t *can_os)
+ /*****************************************************************************
+ * Device IO control function. Used by user apps to configure CAN device.
+ *****************************************************************************/
+-int can_dev_io(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg)
++long can_dev_io(struct file *filp, unsigned int cmd, unsigned long arg)
+ {
+ can_os_t *can_os;
+ unsigned int err=0;
+--- a/Embedded/src/CAN/can_main.h
++++ b/Embedded/src/CAN/can_main.h
+@@ -157,8 +157,7 @@ ssize_t can_write(
+ int icp_can_reset(
+ can_os_t *can_os);
+
+-int can_dev_io(
+- struct inode *inode,
++long can_dev_io(
+ struct file *filp,
+ unsigned int cmd,
+ unsigned long arg);
diff --git a/package/ep80579-drivers/patches/713-3.3-gpio-fixes.patch b/package/ep80579-drivers/patches/713-3.3-gpio-fixes.patch
new file mode 100644
index 000000000..47fb920d0
--- /dev/null
+++ b/package/ep80579-drivers/patches/713-3.3-gpio-fixes.patch
@@ -0,0 +1,33 @@
+--- a/Embedded/src/GPIO/gpio.h
++++ b/Embedded/src/GPIO/gpio.h
+@@ -121,8 +121,7 @@ int gpio_init(void);
+ void gpio_close(void);
+ int gpio_open(struct inode *inode, struct file *filp);
+ int gpio_release(struct inode *inode, struct file *filp);
+-int gpio_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg);
++long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+
+ // private driver functions
+ int gpio_getpininfo(int Signal, char *pBuff);
+@@ -134,7 +133,7 @@ struct file_operations file_ops =
+ .owner = THIS_MODULE,
+ .open = gpio_open,
+ .release = gpio_release,
+- .ioctl = gpio_ioctl,
++ .unlocked_ioctl = gpio_ioctl,
+ };
+
+ #endif
+--- a/Embedded/src/GPIO/gpio_ref.c
++++ b/Embedded/src/GPIO/gpio_ref.c
+@@ -251,8 +251,7 @@ int gpio_release(struct inode *inode, st
+ 0 => success
+ < 0 => error
+ ******************************************************************************/
+-int gpio_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg)
++long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ {
+ gpio_ioctl_t Info;
+ u_int bitstr = 0;
diff --git a/package/ep80579-drivers/patches/714-3.3-wdt-fixes.patch b/package/ep80579-drivers/patches/714-3.3-wdt-fixes.patch
new file mode 100644
index 000000000..60cc4aeb7
--- /dev/null
+++ b/package/ep80579-drivers/patches/714-3.3-wdt-fixes.patch
@@ -0,0 +1,31 @@
+--- a/Embedded/src/WDT/iwdt.c
++++ b/Embedded/src/WDT/iwdt.c
+@@ -217,8 +217,7 @@ static int wdt_open(struct inode *inode,
+ static int wdt_release(struct inode *inode, struct file *file);
+ static ssize_t wdt_write(struct file *file, const char *data,
+ size_t count, loff_t * pos);
+-static int wdt_ioctl(struct inode *inode, struct file *file,
+- unsigned int cmd, unsigned long arg);
++static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+ static irqreturn_t wdt_isr(int irq, void *dev_id);
+ static void __exit wdt_cleanup(void);
+ static int __init wdt_init(void);
+@@ -243,7 +242,7 @@ static struct pci_device_id lpc_pci_tbl[
+ static struct file_operations wdt_fops = {
+ owner: THIS_MODULE,
+ write: wdt_write,
+- ioctl: wdt_ioctl,
++ unlocked_ioctl: wdt_ioctl,
+ open: wdt_open,
+ release: wdt_release,
+ };
+@@ -1201,8 +1200,7 @@ char *wdt_get_ioctl_string(unsigned int
+ * Return Value: 0 - successful, negative value - failed.
+ * Description: This function is used to provide IO interface.
+ */
+-static int wdt_ioctl(struct inode *inode, struct file *file,
+- unsigned int cmd, unsigned long arg)
++static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+ u8 mode=0, scale=0, int_type=0;
+ u32 u_margin=0, dcount=0;
diff --git a/package/ep80579-drivers/patches/715-3.3-1588-fixes.patch b/package/ep80579-drivers/patches/715-3.3-1588-fixes.patch
new file mode 100644
index 000000000..ac5dd1f2e
--- /dev/null
+++ b/package/ep80579-drivers/patches/715-3.3-1588-fixes.patch
@@ -0,0 +1,33 @@
+--- a/Embedded/src/1588/1588.c
++++ b/Embedded/src/1588/1588.c
+@@ -664,8 +664,7 @@ irqreturn_t timesync_isr(int irq, void *
+ 0 => success
+ < 0 => error
+ ******************************************************************************/
+-int timesync_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg)
++long timesync_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ {
+ wait_queue_head_t *event = NULL;
+ unsigned int bytes_ret = 0;
+--- a/Embedded/src/1588/1588.h
++++ b/Embedded/src/1588/1588.h
+@@ -121,8 +121,7 @@ MODULE_DEVICE_TABLE(pci, pci_ids);
+ // Linux functions
+ int timesync_open(struct inode *inode, struct file *filp);
+ int timesync_release(struct inode *inode, struct file *filp);
+-int timesync_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg);
++long timesync_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+ void timesync_close(void);
+ int pci_suspend(struct pci_dev *dev, pm_message_t state);
+ int pci_resume(struct pci_dev *dev);
+@@ -142,7 +141,7 @@ struct file_operations file_ops =
+ .owner = THIS_MODULE,
+ .open = timesync_open,
+ .release = timesync_release,
+- .ioctl = timesync_ioctl,
++ .unlocked_ioctl = timesync_ioctl,
+ };
+
+ // Linux pci operations
diff --git a/package/fbtest/Makefile b/package/fbtest/Makefile
new file mode 100644
index 000000000..05e67cb63
--- /dev/null
+++ b/package/fbtest/Makefile
@@ -0,0 +1,44 @@
+#
+# Copyright (C) 2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=fbtest
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/fbtest
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Frame buffer device testing tool
+ DEPENDS:=@DISPLAY_SUPPORT
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CC)" \
+ CFLAGS="$(TARGET_CFLAGS) -Wall" \
+ LDFLAGS="$(TARGET_LDFLAGS)"
+endef
+
+define Package/fbtest/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/fbtest $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,fbtest))
diff --git a/package/fbtest/src/Makefile b/package/fbtest/src/Makefile
new file mode 100644
index 000000000..075bc0ecb
--- /dev/null
+++ b/package/fbtest/src/Makefile
@@ -0,0 +1,14 @@
+CC = gcc
+CFLAGS = -Wall
+OBJS = fbtest.o
+
+all: fbtest
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+fbtest: $(OBJS)
+ $(CC) -o $@ $(OBJS)
+
+clean:
+ rm -f rbcfg *.o
diff --git a/package/fbtest/src/fbtest.c b/package/fbtest/src/fbtest.c
new file mode 100644
index 000000000..6e9c2f85f
--- /dev/null
+++ b/package/fbtest/src/fbtest.c
@@ -0,0 +1,448 @@
+/******************************************************************************
+ * fbtest - fbtest.c
+ * test program for the tuxbox-framebuffer device
+ * tests all GTX/eNX supported modes
+ *
+ * (c) 2003 Carsten Juttner (carjay@gmx.net)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * The Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ******************************************************************************
+ * $Id: fbtest.c,v 1.5 2005/01/14 23:14:41 carjay Exp $
+ ******************************************************************************/
+
+// TODO: - should restore the colour map and mode to what it was before
+// - is colour map handled correctly?
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+#include <linux/fb.h>
+
+#include <error.h>
+
+#define FBDEV "/dev/fb0"
+
+struct vidsize{
+ int width;
+ int height;
+};
+static
+const struct vidsize vidsizetable[]={ // all supported sizes
+ {720,576},{720,480},{720,288},{720,240},
+ {640,576},{640,480},{640,288},{640,240},
+ {360,576},{360,480},{360,288},{360,240},
+ {320,576},{320,480},{320,288},{320,240}
+};
+#define VIDSIZENUM (sizeof(vidsizetable)/sizeof(struct vidsize))
+
+enum pixenum{ // keep in sync with pixname !
+ CLUT4=0,
+ CLUT8,
+ RGB565,
+ ARGB1555,
+ ARGB
+};
+const char *pixname[] = {
+ "CLUT4",
+ "CLUT8",
+ "RGB565",
+ "ARGB1555",
+ "ARGB"
+};
+
+struct pixelformat{
+ char *name;
+ struct fb_bitfield red;
+ struct fb_bitfield green;
+ struct fb_bitfield blue;
+ struct fb_bitfield transp;
+ char bpp;
+ char pixenum;
+};
+
+static // so far these are all modes supported by the eNX (only partially by GTX)
+const struct pixelformat pixelformattable[] = {
+ { .name = "CLUT4 ARGB8888", // CLUT4 (ARGB8888)
+ .bpp = 4, .pixenum = CLUT4,
+ .red = { .offset = 0, .length=8, .msb_right =0 },
+ .green = { .offset = 0, .length=8, .msb_right =0 },
+ .blue = { .offset = 0, .length=8, .msb_right =0 },
+ .transp= { .offset = 0, .length=8, .msb_right =0 }
+ },
+ { .name = "CLUT4 ARGB1555", // CLUT4 (ARGB1555)
+ .bpp = 4, .pixenum = CLUT4,
+ .red = { .offset = 0, .length=5, .msb_right =0 },
+ .green = { .offset = 0, .length=5, .msb_right =0 },
+ .blue = { .offset = 0, .length=5, .msb_right =0 },
+ .transp= { .offset = 0, .length=1, .msb_right =0 }
+ },
+ { .name = "CLUT8 ARGB8888", // CLUT8 (ARGB8888)
+ .bpp = 8, .pixenum = CLUT8,
+ .red = { .offset = 0, .length=8, .msb_right =0 },
+ .green = { .offset = 0, .length=8, .msb_right =0 },
+ .blue = { .offset = 0, .length=8, .msb_right =0 },
+ .transp= { .offset = 0, .length=8, .msb_right =0 }
+ },
+ { .name = "CLUT8 ARGB1555", // CLUT8 (ARGB1555)
+ .bpp = 8, .pixenum = CLUT8,
+ .red = { .offset = 0, .length=5, .msb_right =0 },
+ .green = { .offset = 0, .length=5, .msb_right =0 },
+ .blue = { .offset = 0, .length=5, .msb_right =0 },
+ .transp= { .offset = 0, .length=1, .msb_right =0 }
+ },
+ { .name = "ARGB1555", // ARGB1555
+ .bpp = 16, .pixenum = ARGB1555,
+ .red = { .offset = 10, .length=5, .msb_right =0 },
+ .green = { .offset = 5, .length=5, .msb_right =0 },
+ .blue = { .offset = 0, .length=5, .msb_right =0 },
+ .transp= { .offset = 15, .length=1, .msb_right =0 }
+ },
+ { .name = "RGB565", // RGB565
+ .bpp = 16, .pixenum = RGB565,
+ .red = { .offset = 11, .length=5, .msb_right =0 },
+ .green = { .offset = 5, .length=6, .msb_right =0 },
+ .blue = { .offset = 0, .length=5, .msb_right =0 },
+ .transp= { .offset = 0, .length=0, .msb_right =0 }
+ },
+ { .name = "ARGB", // 32 f*cking bits, the real McCoy :)
+ .bpp = 32, .pixenum = ARGB,
+ .red = { .offset = 16, .length=8, .msb_right =0 },
+ .green = { .offset = 8, .length=8, .msb_right =0 },
+ .blue = { .offset = 0, .length=8, .msb_right =0 },
+ .transp= { .offset = 24, .length=8, .msb_right =0 }
+ }
+};
+#define PIXELFORMATNUM (sizeof(pixelformattable)/sizeof(struct pixelformat))
+
+struct colour {
+ __u16 r;
+ __u16 g;
+ __u16 b;
+ __u16 a;
+};
+static
+struct colour colourtable[] = {
+ {.r =0xffff, .g = 0xffff, .b=0xffff, .a=0xffff}, // fully transparent white
+ {.r =0xffff, .g = 0x0000, .b=0x0000, .a=0x0000}, // red
+ {.r =0x0000, .g = 0xffff, .b=0x0000, .a=0x0000}, // green
+ {.r =0x0000, .g = 0x0000, .b=0xffff, .a=0x0000}, // blue
+ {.r =0x0000, .g = 0x0000, .b=0x0000, .a=0x0000} // black
+};
+#define COLOURNUM (sizeof(colourtable)/sizeof(struct colour))
+
+struct rect{
+ int x;
+ int y;
+ int width;
+ int height;
+ const struct colour *col;
+};
+struct pixel{ // up to 32 bits of pixel information
+ char byte[4];
+};
+
+void col2pixel (struct pixel *pix, const struct pixelformat *pixf, const struct colour *col){
+ switch (pixf->pixenum){
+ case RGB565:
+ pix->byte[0]=(col->r&0xf8)|(col->g&0xfc)>>5;
+ pix->byte[1]=(col->g&0xfc)<<3|(col->b&0xf8)>>3;
+ break;
+ case ARGB1555:
+ pix->byte[0]=(col->a&0x80)|(col->r&0xf8)>>1|(col->g&0xf8)>>6;
+ pix->byte[1]=(col->g&0xf8)<<2|(col->b&0xf8)>>3;
+ break;
+ case ARGB:
+ pix->byte[0]=col->a;
+ pix->byte[1]=col->r;
+ pix->byte[2]=col->g;
+ pix->byte[3]=col->b;
+ break;
+ default:
+ printf ("unknown pixelformat\n");
+ exit(1);
+ }
+}
+
+int setmode(int fbd, const struct pixelformat *pixf,const struct vidsize *vids){
+ struct fb_var_screeninfo var;
+ int stat;
+ stat = ioctl (fbd, FBIOGET_VSCREENINFO,&var);
+ if (stat<0) return -2;
+
+ var.xres= vids->width;
+ var.xres_virtual = vids->width;
+ var.yres= vids->height;
+ var.yres_virtual = vids->height;
+
+ var.bits_per_pixel = pixf->bpp;
+ var.red = pixf->red;
+ var.green = pixf->green;
+ var.blue = pixf->blue;
+ var.transp = pixf->transp;
+
+ stat = ioctl (fbd, FBIOPUT_VSCREENINFO,&var);
+ if (stat<0) return -1;
+ return 0;
+}
+
+// unefficient implementation, do NOT use it for your next ego shooter, please :)
+// for 4-Bit only rectangles with even width are supported
+// CLUT-modes use value of red component as index
+void drawrect(void *videoram, struct rect *r, const struct pixelformat *pixf, const struct vidsize *vids){
+ int x,y,corwidth, bpp = 0, tocopy = 1;
+ struct pixel pix;
+ unsigned char *pmem = videoram;
+ corwidth = r->width; // actually only "corrected" for 4 Bit
+
+ if (pixf->pixenum!=CLUT4&&pixf->pixenum!=CLUT8){
+ switch (pixf->pixenum){
+ case ARGB1555:
+ case RGB565:
+ bpp = 16;
+ tocopy = 2;
+ break;
+ case ARGB:
+ bpp = 32;
+ tocopy = 4;
+ break;
+ default:
+ printf ("drawrect: unknown pixelformat(%d) bpp:%d\n",pixf->pixenum,pixf->bpp);
+ exit(1);
+ }
+ col2pixel(&pix,pixf,r->col);
+ } else {
+ switch (pixf->pixenum){ // CLUT = Colour LookUp Table (palette)
+ case CLUT4: // take red value as index in this case
+ pix.byte[0]=(r->col->r)<<4|(r->col->r&0xf); // slightly cryptic... "rect->colour->red"
+ corwidth>>=1; // we copy bytes
+ bpp=4;
+ tocopy=1;
+ break;
+ case CLUT8:
+ pix.byte[0]=(r->col->r&0xff);
+ bpp=8;
+ tocopy=1;
+ break;
+ }
+ }
+ pmem=videoram+((((r->y*vids->width)+r->x)*bpp)>>3);
+ for (y=0;y<r->height;y++){
+ int offset = 0;
+ for (x=0;x<corwidth;x++){
+ memcpy (pmem+offset,pix.byte,tocopy);
+ offset+=tocopy;
+ }
+ pmem +=((vids->width*bpp)>>3); // skip one whole line, actually should be taken from "fix-info"
+ }
+}
+
+// create quick little test image, 4 colours from table
+void draw4field(void *videoram, const struct pixelformat *pixf, const struct vidsize *vids){
+ struct rect r;
+ struct colour c;
+ int height, width;
+ c.r = 1; // only used for the indexed modes, r is taken as index
+ height = vids->height;
+ width = vids->width;
+
+ r.height = height>>1;
+ r.width = width>>1;
+ r.x = 0; r.y = 0;
+ if (pixf->pixenum==CLUT4||pixf->pixenum==CLUT8) r.col = &c;
+ else r.col = &colourtable[1];
+ drawrect (videoram, &r, pixf, vids);
+
+ r.x = width/2; r.y = 0;
+ if (pixf->pixenum==CLUT4||pixf->pixenum==CLUT8) c.r = 2;
+ else r.col = &colourtable[2];
+ drawrect (videoram, &r, pixf, vids);
+
+ r.x = 0; r.y = height/2;
+ if (pixf->pixenum==CLUT4||pixf->pixenum==CLUT8) c.r = 3;
+ else r.col = &colourtable[3];
+ drawrect (videoram, &r, pixf, vids);
+
+ r.x = width/2; r.y = height/2;
+ if (pixf->pixenum==CLUT4||pixf->pixenum==CLUT8) c.r = 0;
+ else r.col = &colourtable[0];
+ drawrect (videoram, &r, pixf, vids);
+}
+
+void usage(char *name){
+ printf ("Usage: %s [options]\n"
+ "Options: -f<pixelformat>\n"
+ " where format is one of:\n"
+ " CLUT4,CLUT8,ARGB1555,RGB565,ARGB\n"
+ " -s<width>x<heigth>\n"
+ " where width is either 720,640,360,320\n"
+ " and height is either 288,240,480,576\n"
+ " -n\n"
+ " disables clearing the framebuffer after drawing\n"
+ " the testimage. This can be useful to keep the last\n"
+ " drawn image onscreen.\n"
+ "\nExample: %s -fRGB322\n",name,name);
+ exit(0);
+}
+
+int main (int argc,char **argv){
+ struct fb_fix_screeninfo fix;
+ struct fb_var_screeninfo var;
+ struct fb_cmap cmap;
+ struct rect r;
+ int fbd;
+ unsigned char *pfb;
+ int stat;
+ int optchar,fmode=-1,smode=-1,clear=1;
+ int i_cmap,i_size,i_pix;
+ extern char *optarg;
+
+ if (argc!=0&&argc>4) usage(argv[0]);
+ while ( (optchar = getopt (argc,argv,"f:s:n"))!= -1){
+ int i,height,width;
+ switch (optchar){
+ case 'f':
+ for (i=0;i<(sizeof(pixname)/sizeof(char*));i++){
+ if (!strncmp (optarg,pixname[i],strlen(pixname[i]))){
+ fmode=i;
+ printf ("displaying only %s-modes\n",pixname[i]);
+ break;
+ }
+ }
+ if (fmode==-1){
+ printf ("unknown pixelformat\n");
+ exit(0);
+ }
+ break;
+ case 's':
+ if (sscanf (optarg,"%dx%d",&width,&height)!=2){
+ printf ("parsing size failed\n");
+ exit(0);
+ } else {
+ printf ("requested size %dx%d\n",width,height);
+ for (i=0;i<VIDSIZENUM;i++){
+ if (vidsizetable[i].width == width &&
+ vidsizetable[i].height == height){
+ smode = i;
+ break;
+ }
+ }
+ if (smode==-1){
+ printf ("this size is not supported\n");
+ exit(0);
+ }
+ }
+ break;
+ case 'n':
+ clear = 0;
+ printf ("clearing framebuffer after drawing is disabled\n");
+ break;
+ case '?':
+ usage (argv[0]);
+ }
+ }
+
+ fbd = open (FBDEV, O_RDWR);
+ if (fbd<0){
+ perror ("Error opening framebuffer device");
+ return 1;
+ }
+ stat = ioctl (fbd, FBIOGET_FSCREENINFO,&fix);
+ if (stat<0){
+ perror ("Error getting fix screeninfo");
+ return 1;
+ }
+ stat = ioctl (fbd, FBIOGET_VSCREENINFO,&var);
+ if (stat<0){
+ perror ("Error getting var screeninfo");
+ return 1;
+ }
+ stat = ioctl (fbd, FBIOPUT_VSCREENINFO,&var);
+ if (stat<0){
+ perror ("Error setting mode");
+ return 1;
+ }
+ pfb = mmap (0, fix.smem_len, PROT_READ|PROT_WRITE, MAP_SHARED, fbd, 0);
+ if (pfb == MAP_FAILED){
+ perror ("Error mmap'ing framebuffer device");
+ return 1;
+ }
+
+ // iterate over all modes
+ for (i_pix=0;i_pix<PIXELFORMATNUM;i_pix++){
+ if (fmode!=-1 && pixelformattable[i_pix].pixenum != fmode) continue;
+ printf ("testing: %s",pixelformattable[i_pix].name);
+ printf (" for sizes: \n");
+ for (i_size=0;i_size<VIDSIZENUM;i_size++){
+ if (smode!=-1 && i_size!=smode) continue;
+ printf ("%dx%d ",vidsizetable[i_size].width,vidsizetable[i_size].height);
+ fflush(stdout);
+ if ((i_size%4)==3) printf ("\n");
+
+ // try to set mode
+ stat = setmode(fbd,&pixelformattable[i_pix],&vidsizetable[i_size]);
+ if (stat==-2) perror ("fbtest: could not get fb_var-screeninfo from fb-device");
+ else if (stat==-1){
+ printf ("\nCould not set mode %s (%dx%d), possible reasons:\n"
+ "- you have a GTX (soz m8)\n"
+ "- your configuration does not have enough graphics RAM\n"
+ "- you found a bug\n"
+ "choose your poison accordingly...\n",
+ pixelformattable[i_pix].name,vidsizetable[i_size].width,vidsizetable[i_size].height);
+ continue;
+ }
+ // fill cmap;
+ cmap.len = 1;
+ if ((pixelformattable[i_pix].bpp==4)||
+ ((pixelformattable[i_pix].bpp==8)&&(pixelformattable[i_pix].red.length!=3))){
+ for (i_cmap=0;i_cmap<COLOURNUM;i_cmap++){
+ cmap.start=i_cmap;
+ cmap.red=&colourtable[i_cmap].r;
+ cmap.green=&colourtable[i_cmap].g;
+ cmap.blue=&colourtable[i_cmap].b;
+ cmap.transp=&colourtable[i_cmap].a;
+ stat = ioctl (fbd, FBIOPUTCMAP, &cmap);
+ if (stat<0) printf ("setting colourmap failed\n");
+ }
+ }
+ // create the test image
+ draw4field(pfb,&pixelformattable[i_pix],&vidsizetable[i_size]);
+ usleep (500000);
+ // clear screen
+ if (clear){
+ r.x=r.y=0;r.width = vidsizetable[i_size].width; r.height = vidsizetable[i_size].height;
+ r.col = &colourtable[4];
+ drawrect(pfb,&r,&pixelformattable[i_pix],&vidsizetable[i_size]);
+ }
+ }
+ printf ("\n");
+ }
+
+ stat = munmap (pfb,fix.smem_len);
+ if (stat<0){
+ perror ("Error munmap'ing framebuffer device");
+ return 1;
+ }
+ close (fbd);
+ return 0;
+}
diff --git a/package/fconfig/Makefile b/package/fconfig/Makefile
new file mode 100644
index 000000000..14bbec57b
--- /dev/null
+++ b/package/fconfig/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2006-2008 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=fconfig
+PKG_VERSION:=20080329
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://andrzejekiert.ovh.org/software/fconfig/
+PKG_MD5SUM:=dac355e9f2a0f48c414c52e2034b6346
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/fconfig
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=RedBoot configuration editor
+ URL:=http://andrzejekiert.ovh.org/software.html.en
+endef
+
+define Package/fconfig/description
+ displays and (if writable) also edits the RedBoot configuration.
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+ $(call Build/Compile/Default)
+endef
+
+define Package/fconfig/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/fconfig $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,fconfig))
diff --git a/package/firewall/Makefile b/package/firewall/Makefile
new file mode 100644
index 000000000..05f42a62e
--- /dev/null
+++ b/package/firewall/Makefile
@@ -0,0 +1,58 @@
+#
+# Copyright (C) 2008-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=firewall
+
+PKG_VERSION:=2
+PKG_RELEASE:=53
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/firewall
+ SECTION:=net
+ CATEGORY:=Base system
+ URL:=http://openwrt.org/
+ TITLE:=OpenWrt firewall
+ MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org>
+ DEPENDS:=+iptables +kmod-ipt-conntrack +kmod-ipt-nat
+ PKGARCH:=all
+endef
+
+define Package/firewall/description
+ UCI based firewall for OpenWrt
+endef
+
+define Build/Compile
+ true
+endef
+
+define Package/firewall/conffiles
+/etc/config/firewall
+/etc/firewall.user
+endef
+
+define Package/firewall/install
+ $(INSTALL_DIR) $(1)/lib/firewall
+ $(INSTALL_DATA) ./files/lib/*.sh $(1)/lib/firewall
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) ./files/bin/fw $(1)/sbin
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/firewall.config $(1)/etc/config/firewall
+ $(INSTALL_DIR) $(1)/etc/init.d/
+ $(INSTALL_BIN) ./files/firewall.init $(1)/etc/init.d/firewall
+ $(INSTALL_DIR) $(1)/etc/hotplug.d/iface
+ $(INSTALL_DATA) ./files/firewall.hotplug $(1)/etc/hotplug.d/iface/20-firewall
+ $(INSTALL_DIR) $(1)/etc/hotplug.d/firewall
+ $(INSTALL_DATA) ./files/reflection.hotplug $(1)/etc/hotplug.d/firewall/10-nat-reflection
+ $(INSTALL_DIR) $(1)/etc
+ $(INSTALL_DATA) ./files/firewall.user $(1)/etc
+ $(INSTALL_DIR) $(1)/lib/upgrade/keep.d
+ $(INSTALL_DATA) ./files/firewall.upgrade $(1)/lib/upgrade/keep.d/firewall
+endef
+
+$(eval $(call BuildPackage,firewall))
diff --git a/package/firewall/files/bin/fw b/package/firewall/files/bin/fw
new file mode 100644
index 000000000..5d20cc83e
--- /dev/null
+++ b/package/firewall/files/bin/fw
@@ -0,0 +1,49 @@
+#!/bin/sh
+FW_LIBDIR=/lib/firewall
+
+. /lib/functions.sh
+. ${FW_LIBDIR}/fw.sh
+
+case "$(type fw)" in
+ *function) ;;
+ *) exit 255;;
+esac
+
+usage() {
+ echo $0 "<command>" "<family>" "<table>" "<chain>" "<target>" "{" "<rules>" "}"
+ exit 0
+}
+
+cmd=$1
+shift
+case "$cmd" in
+ --help|help) usage ;;
+ start|stop|reload|restart)
+ . ${FW_LIBDIR}/core.sh
+ fw_$cmd
+ exit $?
+ ;;
+esac
+
+fam=$1
+shift
+case "$fam" in
+ ip)
+ fam=i
+ if [ $# -gt 2 ]; then
+ for p in $(seq 2 $(($# - 1))); do
+ if eval "[ \$$p == '}' ]"; then
+ fam=I
+ break
+ fi
+ done
+ fi ;;
+ ip4) fam=4 ;;
+ ip6) fam=6 ;;
+ arp) fam=a ;;
+ eth) fam=e ;;
+ -*) exec $0 $cmd ${fam##*-} "$@" ;;
+esac
+
+fw "$cmd" "$fam" "$@"
+exit $?
diff --git a/package/firewall/files/firewall.config b/package/firewall/files/firewall.config
new file mode 100644
index 000000000..a87413904
--- /dev/null
+++ b/package/firewall/files/firewall.config
@@ -0,0 +1,176 @@
+config defaults
+ option syn_flood 1
+ option input ACCEPT
+ option output ACCEPT
+ option forward REJECT
+# Uncomment this line to disable ipv6 rules
+# option disable_ipv6 1
+
+config zone
+ option name lan
+ option network 'lan'
+ option input ACCEPT
+ option output ACCEPT
+ option forward REJECT
+
+config zone
+ option name wan
+ option network 'wan'
+ option input REJECT
+ option output ACCEPT
+ option forward REJECT
+ option masq 1
+ option mtu_fix 1
+
+config forwarding
+ option src lan
+ option dest wan
+
+# We need to accept udp packets on port 68,
+# see https://dev.openwrt.org/ticket/4108
+config rule
+ option name Allow-DHCP-Renew
+ option src wan
+ option proto udp
+ option dest_port 68
+ option target ACCEPT
+ option family ipv4
+
+# Allow IPv4 ping
+config rule
+ option name Allow-Ping
+ option src wan
+ option proto icmp
+ option icmp_type echo-request
+ option family ipv4
+ option target ACCEPT
+
+# Allow DHCPv6 replies
+# see https://dev.openwrt.org/ticket/10381
+config rule
+ option name Allow-DHCPv6
+ option src wan
+ option proto udp
+ option src_ip fe80::/10
+ option src_port 547
+ option dest_ip fe80::/10
+ option dest_port 546
+ option family ipv6
+ option target ACCEPT
+
+# Allow essential incoming IPv6 ICMP traffic
+config rule
+ option name Allow-ICMPv6-Input
+ option src wan
+ option proto icmp
+ list icmp_type echo-request
+ list icmp_type echo-reply
+ list icmp_type destination-unreachable
+ list icmp_type packet-too-big
+ list icmp_type time-exceeded
+ list icmp_type bad-header
+ list icmp_type unknown-header-type
+ list icmp_type router-solicitation
+ list icmp_type neighbour-solicitation
+ list icmp_type router-advertisement
+ list icmp_type neighbour-advertisement
+ option limit 1000/sec
+ option family ipv6
+ option target ACCEPT
+
+# Allow essential forwarded IPv6 ICMP traffic
+config rule
+ option name Allow-ICMPv6-Forward
+ option src wan
+ option dest *
+ option proto icmp
+ list icmp_type echo-request
+ list icmp_type echo-reply
+ list icmp_type destination-unreachable
+ list icmp_type packet-too-big
+ list icmp_type time-exceeded
+ list icmp_type bad-header
+ list icmp_type unknown-header-type
+ option limit 1000/sec
+ option family ipv6
+ option target ACCEPT
+
+# include a file with users custom iptables rules
+config include
+ option path /etc/firewall.user
+
+
+### EXAMPLE CONFIG SECTIONS
+# do not allow a specific ip to access wan
+#config rule
+# option src lan
+# option src_ip 192.168.45.2
+# option dest wan
+# option proto tcp
+# option target REJECT
+
+# block a specific mac on wan
+#config rule
+# option dest wan
+# option src_mac 00:11:22:33:44:66
+# option target REJECT
+
+# block incoming ICMP traffic on a zone
+#config rule
+# option src lan
+# option proto ICMP
+# option target DROP
+
+# port redirect port coming in on wan to lan
+#config redirect
+# option src wan
+# option src_dport 80
+# option dest lan
+# option dest_ip 192.168.16.235
+# option dest_port 80
+# option proto tcp
+
+# port redirect of remapped ssh port (22001) on wan
+#config redirect
+# option src wan
+# option src_dport 22001
+# option dest lan
+# option dest_port 22
+# option proto tcp
+
+# allow IPsec/ESP and ISAKMP passthrough
+#config rule
+# option src wan
+# option dest lan
+# option protocol esp
+# option target ACCEPT
+
+#config rule
+# option src wan
+# option dest lan
+# option src_port 500
+# option dest_port 500
+# option proto udp
+# option target ACCEPT
+
+### FULL CONFIG SECTIONS
+#config rule
+# option src lan
+# option src_ip 192.168.45.2
+# option src_mac 00:11:22:33:44:55
+# option src_port 80
+# option dest wan
+# option dest_ip 194.25.2.129
+# option dest_port 120
+# option proto tcp
+# option target REJECT
+
+#config redirect
+# option src lan
+# option src_ip 192.168.45.2
+# option src_mac 00:11:22:33:44:55
+# option src_port 1024
+# option src_dport 80
+# option dest_ip 194.25.2.129
+# option dest_port 120
+# option proto tcp
diff --git a/package/firewall/files/firewall.hotplug b/package/firewall/files/firewall.hotplug
new file mode 100644
index 000000000..52e779848
--- /dev/null
+++ b/package/firewall/files/firewall.hotplug
@@ -0,0 +1,22 @@
+#!/bin/sh
+# This script is executed as part of the hotplug event with
+# HOTPLUG_TYPE=iface, triggered by various scripts when an interface
+# is configured (ACTION=ifup) or deconfigured (ACTION=ifdown). The
+# interface is available as INTERFACE, the real device as DEVICE.
+
+[ "$DEVICE" == "lo" ] && exit 0
+
+. /lib/functions.sh
+. /lib/firewall/core.sh
+
+fw_init
+fw_is_loaded || exit 0
+
+case "$ACTION" in
+ ifup)
+ fw_configure_interface "$INTERFACE" add "$DEVICE" &
+ ;;
+ ifdown)
+ fw_configure_interface "$INTERFACE" del "$DEVICE"
+ ;;
+esac
diff --git a/package/firewall/files/firewall.init b/package/firewall/files/firewall.init
new file mode 100755
index 000000000..a2fd0a0e9
--- /dev/null
+++ b/package/firewall/files/firewall.init
@@ -0,0 +1,27 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2008-2010 OpenWrt.org
+
+START=45
+
+FW_LIBDIR=/lib/firewall
+
+fw() {
+ . $FW_LIBDIR/core.sh
+ fw_$1
+}
+
+start() {
+ fw start
+}
+
+stop() {
+ fw stop
+}
+
+restart() {
+ fw restart
+}
+
+reload() {
+ fw reload
+}
diff --git a/package/firewall/files/firewall.upgrade b/package/firewall/files/firewall.upgrade
new file mode 100644
index 000000000..64f63eb39
--- /dev/null
+++ b/package/firewall/files/firewall.upgrade
@@ -0,0 +1 @@
+/etc/firewall.user
diff --git a/package/firewall/files/firewall.user b/package/firewall/files/firewall.user
new file mode 100644
index 000000000..1ccbd0165
--- /dev/null
+++ b/package/firewall/files/firewall.user
@@ -0,0 +1,4 @@
+# This file is interpreted as shell script.
+# Put your custom iptables rules here, they will
+# be executed with each firewall (re-)start.
+
diff --git a/package/firewall/files/lib/config.sh b/package/firewall/files/lib/config.sh
new file mode 100644
index 000000000..8b2399fc8
--- /dev/null
+++ b/package/firewall/files/lib/config.sh
@@ -0,0 +1,101 @@
+# Copyright (C) 2009-2010 OpenWrt.org
+# Copyright (C) 2009 Malte S. Stretz <http://msquadrat.de>
+#
+# This is a temporary file, I hope to have some of this stuff merged into
+# /lib/functions.sh (without the fw_ prefix of course) one day.
+
+fw_config_append() { # <package>
+ CONFIG_APPEND=1 config_load "$@"
+ unset CONFIG_APPEND
+}
+
+fw_config_once() { # <function> <type>
+ local func=$1
+ local type=$2
+ shift 2
+
+ local config=cfg00nil
+ fw_config__once() {
+ config=$1
+ }
+ config_foreach fw_config__once "$type"
+
+ $func $config "$@"
+}
+
+fw_config_get_section() { # <config> <prefix> <type> <name> <default> ...
+ local config=$1
+ local prefix=$2
+ shift 2
+
+ [ -n "$config" ] || return 1
+ [ -n "$prefix" ] && {
+ prefix="${prefix}_"
+ export ${NO_EXPORT:+-n} -- "${prefix}NAME"="${config}"
+ config_get "${prefix}TYPE" "$config" TYPE
+ }
+
+ local enabled
+ config_get_bool enabled "$config" enabled 1
+ [ $enabled -eq 1 ] || return 1
+
+ [ "$1" == '{' ] && shift
+ while [ $# -ge 3 ]; do
+ local type=$1
+ local name=$2
+ local dflt=$3
+ shift 3
+ # TODO: Move handling of defaults to /lib/functions.sh
+ # and get replace the case block with the following
+ # two lines:
+ # type=${type#string}
+ # config_get${type:+_${type}} "${prefix}${name}" "$config" "$name" "$dflt" || return
+ case "$type" in
+ string)
+ local tmp
+ config_get tmp "$config" "$name" || return
+ [ -z "$tmp" ] && tmp=$dflt
+ export ${NO_EXPORT:+-n} -- "${prefix}${name}=${tmp}"
+ continue
+ ;;
+ boolean)
+ type=bool
+ ;;
+ esac;
+
+ local cmd=${prefix}config_get_${type}
+ type $cmd > /dev/null || {
+ cmd=config_get_${type}
+ }
+ type $cmd > /dev/null || {
+ echo "config type $type (for $name) not supported" >&2
+ return 1
+ }
+ $cmd "${prefix}${name}" "$config" "$name" "$dflt" || return
+ done
+}
+
+config_get_ipaddr() {
+ local varn=$1
+ local conf=$2
+ local name=$3
+ local dflt=$4
+
+ local addr
+ config_get addr "$conf" "$name" || return
+ [ -n "$addr" ] || addr=$dflt
+
+ local mask=${addr#*/}
+ [ "$mask" != "$addr" ] || mask=
+ addr=${addr%/*}
+
+ local vers=
+ case "$addr" in
+ *:*) vers=6; mask="${mask:-128}" ;;
+ *.*) vers=4; mask="${mask:-32}" ;;
+ esac
+
+ export ${NO_EXPORT:+-n} -- "${varn}=${addr}"
+ export ${NO_EXPORT:+-n} -- "${varn}_prefixlen=${mask}"
+ export ${NO_EXPORT:+-n} -- "${varn}_version=${vers}"
+}
diff --git a/package/firewall/files/lib/core.sh b/package/firewall/files/lib/core.sh
new file mode 100644
index 000000000..93d4d2e29
--- /dev/null
+++ b/package/firewall/files/lib/core.sh
@@ -0,0 +1,159 @@
+# Copyright (C) 2009-2010 OpenWrt.org
+
+FW_LIBDIR=${FW_LIBDIR:-/lib/firewall}
+
+. $FW_LIBDIR/fw.sh
+include /lib/network
+
+fw_start() {
+ fw_init
+
+ FW_DEFAULTS_APPLIED=
+
+ fw_is_loaded && {
+ echo "firewall already loaded" >&2
+ exit 1
+ }
+
+ uci_set_state firewall core "" firewall_state
+
+ fw_clear DROP
+
+ fw_callback pre core
+
+ echo "Loading defaults"
+ fw_config_once fw_load_defaults defaults
+
+ echo "Loading zones"
+ config_foreach fw_load_zone zone
+
+ echo "Loading forwardings"
+ config_foreach fw_load_forwarding forwarding
+
+ echo "Loading rules"
+ config_foreach fw_load_rule rule
+
+ echo "Loading redirects"
+ config_foreach fw_load_redirect redirect
+
+ echo "Loading includes"
+ config_foreach fw_load_include include
+
+ [ -z "$FW_NOTRACK_DISABLED" ] && {
+ echo "Optimizing conntrack"
+ config_foreach fw_load_notrack_zone zone
+ }
+
+ echo "Loading interfaces"
+ config_foreach fw_configure_interface interface add
+
+ fw_callback post core
+
+ uci_set_state firewall core zones "$FW_ZONES"
+ uci_set_state firewall core loaded 1
+}
+
+fw_stop() {
+ fw_init
+
+ fw_callback pre stop
+
+ local z n i
+ config_get z core zones
+ for z in $z; do
+ config_get n core "${z}_networks"
+ for n in $n; do
+ config_get i core "${n}_ifname"
+ [ -n "$i" ] && env -i ACTION=remove ZONE="$z" \
+ INTERFACE="$n" DEVICE="$i" /sbin/hotplug-call firewall
+ done
+
+ config_get i core "${z}_tcpmss"
+ [ "$i" == 1 ] && {
+ fw del i m FORWARD zone_${z}_MSSFIX
+ fw del i m zone_${z}_MSSFIX
+ }
+ done
+
+ fw_clear ACCEPT
+
+ fw_callback post stop
+
+ uci_revert_state firewall
+ config_clear
+
+ local h
+ for h in $FW_HOOKS; do unset $h; done
+
+ unset FW_HOOKS
+ unset FW_INITIALIZED
+}
+
+fw_restart() {
+ fw_stop
+ fw_start
+}
+
+fw_reload() {
+ fw_restart
+}
+
+fw_is_loaded() {
+ local bool=$(uci_get_state firewall.core.loaded)
+ return $((! ${bool:-0}))
+}
+
+
+fw_die() {
+ echo "Error:" "$@" >&2
+ fw_log error "$@"
+ fw_stop
+ exit 1
+}
+
+fw_log() {
+ local level="$1"
+ [ -n "$2" ] && shift || level=notice
+ [ "$level" != error ] || echo "Error: $@" >&2
+ logger -t firewall -p user.$level "$@"
+}
+
+
+fw_init() {
+ [ -z "$FW_INITIALIZED" ] || return 0
+
+ . $FW_LIBDIR/config.sh
+
+ scan_interfaces
+ fw_config_append firewall
+
+ local hooks="core stop defaults zone notrack synflood"
+ local file lib hk pp
+ for file in $FW_LIBDIR/core_*.sh; do
+ . $file
+ hk=$(basename $file .sh)
+ hk=${hk#core_}
+ append hooks $hk
+ done
+ for file in $FW_LIBDIR/*.sh; do
+ lib=$(basename $file .sh)
+ lib=${lib##[0-9][0-9]_}
+ case $lib in
+ core*|fw|config|uci_firewall) continue ;;
+ esac
+ . $file
+ for hk in $hooks; do
+ for pp in pre post; do
+ type ${lib}_${pp}_${hk}_cb >/dev/null && {
+ append FW_CB_${pp}_${hk} ${lib}
+ append FW_HOOKS FW_CB_${pp}_${hk}
+ }
+ done
+ done
+ done
+
+ fw_callback post init
+
+ FW_INITIALIZED=1
+ return 0
+}
diff --git a/package/firewall/files/lib/core_forwarding.sh b/package/firewall/files/lib/core_forwarding.sh
new file mode 100644
index 000000000..c4a968143
--- /dev/null
+++ b/package/firewall/files/lib/core_forwarding.sh
@@ -0,0 +1,44 @@
+# Copyright (C) 2009-2010 OpenWrt.org
+
+fw_config_get_forwarding() {
+ [ "${forwarding_NAME}" != "$1" ] || return
+ fw_config_get_section "$1" forwarding { \
+ string _name "$1" \
+ string name "" \
+ string src "" \
+ string dest "" \
+ string family "" \
+ } || return
+ [ -n "$forwarding_name" ] || forwarding_name=$forwarding__name
+}
+
+fw_load_forwarding() {
+ fw_config_get_forwarding "$1"
+
+ fw_callback pre forwarding
+
+ local chain=forward
+ [ -n "$forwarding_src" ] && {
+ chain=zone_${forwarding_src}_forward
+ }
+
+ local target=ACCEPT
+ [ -n "$forwarding_dest" ] && {
+ target=zone_${forwarding_dest}_ACCEPT
+ }
+
+ local mode
+ fw_get_family_mode mode ${forwarding_family:-x} ${forwarding_dest:-${forwarding_src:--}} i
+
+ fw add $mode f $chain $target ^
+
+ # propagate masq zone flag
+ [ -n "$forwarding_src" ] && list_contains FW_CONNTRACK_ZONES $forwarding_src && {
+ append FW_CONNTRACK_ZONES $forwarding_dest
+ }
+ [ -n "$forwarding_dest" ] && list_contains FW_CONNTRACK_ZONES $forwarding_dest && {
+ append FW_CONNTRACK_ZONES $forwarding_src
+ }
+
+ fw_callback post forwarding
+}
diff --git a/package/firewall/files/lib/core_init.sh b/package/firewall/files/lib/core_init.sh
new file mode 100644
index 000000000..035647998
--- /dev/null
+++ b/package/firewall/files/lib/core_init.sh
@@ -0,0 +1,338 @@
+# Copyright (C) 2009-2011 OpenWrt.org
+# Copyright (C) 2008 John Crispin <blogic@openwrt.org>
+
+FW_INITIALIZED=
+
+FW_ZONES=
+FW_ZONES4=
+FW_ZONES6=
+FW_CONNTRACK_ZONES=
+FW_NOTRACK_DISABLED=
+
+FW_DEFAULTS_APPLIED=
+FW_ADD_CUSTOM_CHAINS=
+FW_ACCEPT_REDIRECTS=
+FW_ACCEPT_SRC_ROUTE=
+
+FW_DEFAULT_INPUT_POLICY=REJECT
+FW_DEFAULT_OUTPUT_POLICY=REJECT
+FW_DEFAULT_FORWARD_POLICY=REJECT
+
+FW_DISABLE_IPV4=0
+FW_DISABLE_IPV6=0
+
+
+fw_load_defaults() {
+ fw_config_get_section "$1" defaults { \
+ string input $FW_DEFAULT_INPUT_POLICY \
+ string output $FW_DEFAULT_OUTPUT_POLICY \
+ string forward $FW_DEFAULT_FORWARD_POLICY \
+ boolean drop_invalid 0 \
+ boolean syn_flood 0 \
+ boolean synflood_protect 0 \
+ string synflood_rate 25 \
+ string synflood_burst 50 \
+ boolean tcp_syncookies 1 \
+ boolean tcp_ecn 0 \
+ boolean tcp_westwood 0 \
+ boolean tcp_window_scaling 1 \
+ boolean accept_redirects 0 \
+ boolean accept_source_route 0 \
+ boolean custom_chains 1 \
+ boolean disable_ipv6 0 \
+ } || return
+ [ -n "$FW_DEFAULTS_APPLIED" ] && {
+ fw_log error "duplicate defaults section detected, skipping"
+ return 1
+ }
+ FW_DEFAULTS_APPLIED=1
+
+ FW_DEFAULT_INPUT_POLICY=$defaults_input
+ FW_DEFAULT_OUTPUT_POLICY=$defaults_output
+ FW_DEFAULT_FORWARD_POLICY=$defaults_forward
+
+ FW_ADD_CUSTOM_CHAINS=$defaults_custom_chains
+
+ FW_ACCEPT_REDIRECTS=$defaults_accept_redirects
+ FW_ACCEPT_SRC_ROUTE=$defaults_accept_source_route
+
+ FW_DISABLE_IPV6=$defaults_disable_ipv6
+
+ fw_callback pre defaults
+
+ # Seems like there are only one sysctl for both IP versions.
+ for s in syncookies ecn westwood window_scaling; do
+ eval "sysctl -e -w net.ipv4.tcp_${s}=\$defaults_tcp_${s}" >/dev/null
+ done
+ fw_sysctl_interface all
+
+ fw add i f INPUT ACCEPT { -m conntrack --ctstate RELATED,ESTABLISHED }
+ fw add i f OUTPUT ACCEPT { -m conntrack --ctstate RELATED,ESTABLISHED }
+ fw add i f FORWARD ACCEPT { -m conntrack --ctstate RELATED,ESTABLISHED }
+
+ [ $defaults_drop_invalid == 1 ] && {
+ fw add i f INPUT DROP { -m conntrack --ctstate INVALID }
+ fw add i f OUTPUT DROP { -m conntrack --ctstate INVALID }
+ fw add i f FORWARD DROP { -m conntrack --ctstate INVALID }
+ FW_NOTRACK_DISABLED=1
+ }
+
+ fw add i f INPUT ACCEPT { -i lo }
+ fw add i f OUTPUT ACCEPT { -o lo }
+
+ # Compatibility to old 'syn_flood' parameter
+ [ $defaults_syn_flood == 1 ] && \
+ defaults_synflood_protect=1
+
+ [ "${defaults_synflood_rate%/*}" == "$defaults_synflood_rate" ] && \
+ defaults_synflood_rate="$defaults_synflood_rate/second"
+
+ [ $defaults_synflood_protect == 1 ] && {
+ echo "Loading synflood protection"
+ fw_callback pre synflood
+ fw add i f syn_flood
+ fw add i f syn_flood RETURN { \
+ -p tcp --syn \
+ -m limit --limit "${defaults_synflood_rate}" --limit-burst "${defaults_synflood_burst}" \
+ }
+ fw add i f syn_flood DROP
+ fw add i f INPUT syn_flood { -p tcp --syn }
+ fw_callback post synflood
+ }
+
+ [ $defaults_custom_chains == 1 ] && {
+ echo "Adding custom chains"
+ fw add i f input_rule
+ fw add i f output_rule
+ fw add i f forwarding_rule
+ fw add i n prerouting_rule
+ fw add i n postrouting_rule
+
+ fw add i f INPUT input_rule
+ fw add i f OUTPUT output_rule
+ fw add i f FORWARD forwarding_rule
+ fw add i n PREROUTING prerouting_rule
+ fw add i n POSTROUTING postrouting_rule
+ }
+
+ fw add i f input
+ fw add i f output
+ fw add i f forward
+
+ fw add i f INPUT input
+ fw add i f OUTPUT output
+ fw add i f FORWARD forward
+
+ fw add i f reject
+ fw add i f reject REJECT { --reject-with tcp-reset -p tcp }
+ fw add i f reject REJECT { --reject-with port-unreach }
+
+ fw_set_filter_policy
+
+ fw_callback post defaults
+}
+
+
+fw_config_get_zone() {
+ [ "${zone_NAME}" != "$1" ] || return
+ fw_config_get_section "$1" zone { \
+ string name "$1" \
+ string network "" \
+ string input "$FW_DEFAULT_INPUT_POLICY" \
+ string output "$FW_DEFAULT_OUTPUT_POLICY" \
+ string forward "$FW_DEFAULT_FORWARD_POLICY" \
+ boolean masq 0 \
+ string masq_src "" \
+ string masq_dest "" \
+ boolean conntrack 0 \
+ boolean mtu_fix 0 \
+ boolean custom_chains "$FW_ADD_CUSTOM_CHAINS" \
+ boolean log 0 \
+ string log_limit 10 \
+ string family "" \
+ } || return
+ [ -n "$zone_name" ] || zone_name=$zone_NAME
+ [ -n "$zone_network" ] || zone_network=$zone_name
+}
+
+fw_load_zone() {
+ fw_config_get_zone "$1"
+
+ list_contains FW_ZONES $zone_name && {
+ fw_log error "zone ${zone_name}: duplicated zone, skipping"
+ return 0
+ }
+ append FW_ZONES $zone_name
+
+ fw_callback pre zone
+
+ [ $zone_conntrack = 1 -o $zone_masq = 1 ] && \
+ append FW_CONNTRACK_ZONES "$zone_name"
+
+ local mode
+ case "$zone_family" in
+ *4)
+ mode=4
+ append FW_ZONES4 $zone_name
+ uci_set_state firewall core ${zone_name}_ipv4 1
+ ;;
+ *6)
+ mode=6
+ append FW_ZONES6 $zone_name
+ uci_set_state firewall core ${zone_name}_ipv6 1
+ ;;
+ *)
+ mode=i
+ append FW_ZONES4 $zone_name
+ append FW_ZONES6 $zone_name
+ uci_set_state firewall core ${zone_name}_ipv4 1
+ uci_set_state firewall core ${zone_name}_ipv6 1
+ ;;
+ esac
+
+ local chain=zone_${zone_name}
+
+ fw add $mode f ${chain}_ACCEPT
+ fw add $mode f ${chain}_DROP
+ fw add $mode f ${chain}_REJECT
+
+ # TODO: Rename to ${chain}_input
+ fw add $mode f ${chain}
+ fw add $mode f ${chain} ${chain}_${zone_input} $
+
+ fw add $mode f ${chain}_forward
+ fw add $mode f ${chain}_forward ${chain}_${zone_forward} $
+
+ # TODO: add ${chain}_output
+ fw add $mode f output ${chain}_${zone_output} $
+
+ # TODO: Rename to ${chain}_MASQUERADE
+ fw add $mode n ${chain}_nat
+ fw add $mode n ${chain}_prerouting
+
+ fw add $mode r ${chain}_notrack
+
+ [ $zone_mtu_fix == 1 ] && {
+ fw add $mode m ${chain}_MSSFIX
+ fw add $mode m FORWARD ${chain}_MSSFIX ^
+ uci_set_state firewall core ${zone_name}_tcpmss 1
+ }
+
+ [ $zone_custom_chains == 1 ] && {
+ [ $FW_ADD_CUSTOM_CHAINS == 1 ] || \
+ fw_die "zone ${zone_name}: custom_chains globally disabled"
+
+ fw add $mode f input_${zone_name}
+ fw add $mode f ${chain} input_${zone_name} ^
+
+ fw add $mode f forwarding_${zone_name}
+ fw add $mode f ${chain}_forward forwarding_${zone_name} ^
+
+ fw add $mode n prerouting_${zone_name}
+ fw add $mode n ${chain}_prerouting prerouting_${zone_name} ^
+ }
+
+ [ "$zone_log" == 1 ] && {
+ [ "${zone_log_limit%/*}" == "$zone_log_limit" ] && \
+ zone_log_limit="$zone_log_limit/minute"
+
+ local t
+ for t in REJECT DROP; do
+ fw add $mode f ${chain}_${t} LOG ^ \
+ { -m limit --limit $zone_log_limit --log-prefix "$t($zone_name): " }
+ done
+
+ [ $zone_mtu_fix == 1 ] && \
+ fw add $mode m ${chain}_MSSFIX LOG ^ \
+ { -m limit --limit $zone_log_limit --log-prefix "MSSFIX($zone_name): " }
+ }
+
+ # NB: if MASQUERADING for IPv6 becomes available we'll need a family check here
+ if [ "$zone_masq" == 1 ]; then
+ local msrc mdst
+ for msrc in ${zone_masq_src:-0.0.0.0/0}; do
+ case "$msrc" in
+ *.*) fw_get_negation msrc '-s' "$msrc" ;;
+ *) fw_get_subnet4 msrc '-s' "$msrc" || break ;;
+ esac
+
+ for mdst in ${zone_masq_dest:-0.0.0.0/0}; do
+ case "$mdst" in
+ *.*) fw_get_negation mdst '-d' "$mdst" ;;
+ *) fw_get_subnet4 mdst '-d' "$mdst" || break ;;
+ esac
+
+ fw add $mode n ${chain}_nat MASQUERADE $ { $msrc $mdst }
+ done
+ done
+ fi
+
+ fw_callback post zone
+}
+
+fw_load_notrack_zone() {
+ fw_config_get_zone "$1"
+ list_contains FW_CONNTRACK_ZONES "${zone_name}" && return
+
+ fw_callback pre notrack
+
+ fw add i r zone_${zone_name}_notrack NOTRACK $
+
+ fw_callback post notrack
+}
+
+
+fw_load_include() {
+ local name="$1"
+
+ local path
+ config_get path ${name} path
+
+ [ -e $path ] && (
+ config() {
+ fw_log error "You cannot use UCI in firewall includes!" >&2
+ exit 1
+ }
+ . $path
+ )
+}
+
+
+fw_clear() {
+ local policy=$1
+
+ fw_set_filter_policy $policy
+
+ local tab
+ for tab in f n r; do
+ fw del i $tab
+ done
+}
+
+fw_set_filter_policy() {
+ local policy=$1
+
+ local chn tgt
+ for chn in INPUT OUTPUT FORWARD; do
+ eval "tgt=\${policy:-\${FW_DEFAULT_${chn}_POLICY}}"
+ [ $tgt == "REJECT" ] && tgt=reject
+ [ $tgt == "ACCEPT" -o $tgt == "DROP" ] || {
+ fw add i f $chn $tgt $
+ tgt=DROP
+ }
+ fw policy i f $chn $tgt
+ done
+}
+
+
+fw_callback() {
+ local pp=$1
+ local hk=$2
+
+ local libs lib
+ eval "libs=\$FW_CB_${pp}_${hk}"
+ [ -n "$libs" ] || return
+ for lib in $libs; do
+ ${lib}_${pp}_${hk}_cb
+ done
+}
diff --git a/package/firewall/files/lib/core_interface.sh b/package/firewall/files/lib/core_interface.sh
new file mode 100644
index 000000000..3d6718431
--- /dev/null
+++ b/package/firewall/files/lib/core_interface.sh
@@ -0,0 +1,205 @@
+# Copyright (C) 2009-2012 OpenWrt.org
+
+fw__uci_state_add() {
+ local var="$1"
+ local item="$2"
+
+ local val="$(uci_get_state firewall core $var)"
+ local e1; for e1 in $item; do
+ local e2; for e2 in $val; do
+ [ "$e1" = "$e2" ] && e1=""
+ done
+ val="${val:+$val${e1:+ }}$e1"
+ done
+
+ uci_toggle_state firewall core $var "$val"
+}
+
+fw__uci_state_del() {
+ local var="$1"
+ local item="$2"
+
+ local rest=""
+ local val="$(uci_get_state firewall core $var)"
+ local e1; for e1 in $val; do
+ local e2; for e2 in $item; do
+ [ "$e1" = "$e2" ] && e1=""
+ done
+ rest="${rest:+$rest${e1:+ }}$e1"
+ done
+
+ uci_toggle_state firewall core $var "$rest"
+}
+
+fw_configure_interface() {
+ local iface=$1
+ local action=$2
+ local ifname=$3
+ local aliasnet=$4
+
+ [ "$action" == "add" ] && {
+ local status=$(uci_get_state network "$iface" up 0)
+ [ "$status" == 1 ] || [ -n "$aliasnet" ] || return 0
+ }
+
+ [ -n "$ifname" ] || {
+ ifname=$(uci_get_state network "$iface" ifname)
+ ifname="${ifname%%:*}"
+ [ -z "$ifname" ] && return 0
+ }
+
+ [ "$ifname" == "lo" ] && return 0
+
+ fw_callback pre interface
+
+ fw__do_rules() {
+ local action=$1
+ local zone=$2
+ local chain=zone_${zone}
+ local ifname=$3
+ local subnet=$4
+
+ local inet onet mode
+ fw_get_family_mode mode x $zone i
+
+ case "$mode/$subnet" in
+ # Zone supports v6 only or dual, need v6
+ G6/*:*|i/*:*)
+ inet="-s $subnet -d ::/0"
+ onet="-s ::/0 -d $subnet"
+ mode=6
+ ;;
+
+ # Zone supports v4 only or dual, need v4
+ G4/*.*.*.*|i/*.*.*.*)
+ inet="-s $subnet -d 0.0.0.0/0"
+ onet="-s 0.0.0.0/0 -d $subnet"
+ mode=4
+ ;;
+
+ # Need v6 while zone is v4
+ */*:*) fw_log info "zone $zone does not support IPv6 address family, skipping"; return ;;
+
+ # Need v4 while zone is v6
+ */*.*) fw_log info "zone $zone does not support IPv4 address family, skipping"; return ;;
+
+ # Strip prefix
+ *) mode="${mode#G}" ;;
+ esac
+
+ lock /var/run/firewall-interface.lock
+
+ fw $action $mode f ${chain}_ACCEPT ACCEPT $ { -o "$ifname" $onet }
+ fw $action $mode f ${chain}_ACCEPT ACCEPT $ { -i "$ifname" $inet }
+ fw $action $mode f ${chain}_DROP DROP $ { -o "$ifname" $onet }
+ fw $action $mode f ${chain}_DROP DROP $ { -i "$ifname" $inet }
+ fw $action $mode f ${chain}_REJECT reject $ { -o "$ifname" $onet }
+ fw $action $mode f ${chain}_REJECT reject $ { -i "$ifname" $inet }
+
+ [ "$(uci_get_state firewall core "${zone}_tcpmss")" == 1 ] && \
+ fw $action $mode m ${chain}_MSSFIX TCPMSS $ \
+ { -o "$ifname" -p tcp --tcp-flags SYN,RST SYN --clamp-mss-to-pmtu $onet }
+
+ fw $action $mode f input ${chain} $ { -i "$ifname" $inet }
+ fw $action $mode f forward ${chain}_forward $ { -i "$ifname" $inet }
+ fw $action $mode n PREROUTING ${chain}_prerouting $ { -i "$ifname" $inet }
+ fw $action $mode r PREROUTING ${chain}_notrack $ { -i "$ifname" $inet }
+ fw $action $mode n POSTROUTING ${chain}_nat $ { -o "$ifname" $onet }
+
+ lock -u /var/run/firewall-interface.lock
+ }
+
+ local old_zones old_ifname old_subnets
+ config_get old_zones core "${iface}_zone"
+ [ -n "$old_zones" ] && {
+ config_get old_ifname core "${iface}_ifname"
+ config_get old_subnets core "${iface}_subnets"
+
+ local z
+ for z in $old_zones; do
+ local n
+ for n in ${old_subnets:-""}; do
+ fw_log info "removing $iface ($old_ifname${n:+ alias $n}) from zone $z"
+ fw__do_rules del $z $old_ifname $n
+ done
+
+ [ -n "$old_subnets" ] || {
+ fw__uci_state_del "${z}_networks" "$iface"
+ env -i ACTION=remove ZONE="$z" INTERFACE="$iface" DEVICE="$ifname" /sbin/hotplug-call firewall
+ }
+ done
+
+ local old_aliases
+ config_get old_aliases core "${iface}_aliases"
+
+ local a
+ for a in $old_aliases; do
+ fw_configure_interface "$a" del "$old_ifname"
+ done
+
+ uci_revert_state firewall core "${iface}_zone"
+ uci_revert_state firewall core "${iface}_ifname"
+ uci_revert_state firewall core "${iface}_subnets"
+ uci_revert_state firewall core "${iface}_aliases"
+ }
+
+ [ "$action" == del ] && return
+
+ [ -z "$aliasnet" ] && {
+ local aliases
+ config_get aliases "$iface" aliases
+
+ local a
+ for a in $aliases; do
+ local ipaddr netmask ip6addr
+ config_get ipaddr "$a" ipaddr
+ config_get netmask "$a" netmask
+ config_get ip6addr "$a" ip6addr
+
+ [ -n "$ipaddr" ] && fw_configure_interface "$a" add "" "$ipaddr${netmask:+/$netmask}"
+ [ -n "$ip6addr" ] && fw_configure_interface "$a" add "" "$ip6addr"
+ done
+
+ fw_sysctl_interface $ifname
+ fw_callback post interface
+
+ uci_toggle_state firewall core "${iface}_aliases" "$aliases"
+ } || {
+ local subnets=
+ config_get subnets core "${iface}_subnets"
+ append subnets "$aliasnet"
+
+ config_set core "${iface}_subnets" "$subnets"
+ uci_toggle_state firewall core "${iface}_subnets" "$subnets"
+ }
+
+ local new_zones=
+ load_zone() {
+ fw_config_get_zone "$1"
+ list_contains zone_network "$iface" || return
+
+ fw_log info "adding $iface ($ifname${aliasnet:+ alias $aliasnet}) to zone $zone_name"
+ fw__do_rules add ${zone_name} "$ifname" "$aliasnet"
+ append new_zones $zone_name
+
+ [ -n "$aliasnet" ] || {
+ fw__uci_state_add "${zone_name}_networks" "${zone_network}"
+ env -i ACTION=add ZONE="$zone_name" INTERFACE="$iface" DEVICE="$ifname" /sbin/hotplug-call firewall
+ }
+ }
+ config_foreach load_zone zone
+
+ uci_toggle_state firewall core "${iface}_zone" "$new_zones"
+ uci_toggle_state firewall core "${iface}_ifname" "$ifname"
+}
+
+fw_sysctl_interface() {
+ local ifname=$1
+ {
+ sysctl -w net.ipv4.conf.${ifname}.accept_redirects=$FW_ACCEPT_REDIRECTS
+ sysctl -w net.ipv6.conf.${ifname}.accept_redirects=$FW_ACCEPT_REDIRECTS
+ sysctl -w net.ipv4.conf.${ifname}.accept_source_route=$FW_ACCEPT_SRC_ROUTE
+ sysctl -w net.ipv6.conf.${ifname}.accept_source_route=$FW_ACCEPT_SRC_ROUTE
+ } >/dev/null 2>/dev/null
+}
+
diff --git a/package/firewall/files/lib/core_redirect.sh b/package/firewall/files/lib/core_redirect.sh
new file mode 100644
index 000000000..fe396c1c1
--- /dev/null
+++ b/package/firewall/files/lib/core_redirect.sh
@@ -0,0 +1,130 @@
+# Copyright (C) 2009-2010 OpenWrt.org
+
+fw_config_get_redirect() {
+ [ "${redirect_NAME}" != "$1" ] || return
+ fw_config_get_section "$1" redirect { \
+ string _name "$1" \
+ string name "" \
+ string src "" \
+ ipaddr src_ip "" \
+ ipaddr src_dip "" \
+ string src_mac "" \
+ string src_port "" \
+ string src_dport "" \
+ string dest "" \
+ ipaddr dest_ip "" \
+ string dest_port "" \
+ string proto "tcpudp" \
+ string family "" \
+ string target "DNAT" \
+ string extra "" \
+ } || return
+ [ -n "$redirect_name" ] || redirect_name=$redirect__name
+}
+
+fw_load_redirect() {
+ fw_config_get_redirect "$1"
+
+ fw_callback pre redirect
+
+ local fwdchain natchain natopt nataddr natports srcdaddr srcdports
+ if [ "$redirect_target" == "DNAT" ]; then
+ [ -n "${redirect_src#*}" -a -n "$redirect_dest_ip$redirect_dest_port" ] || {
+ fw_log error "DNAT redirect ${redirect_name}: needs src and dest_ip or dest_port, skipping"
+ return 0
+ }
+
+ fwdopt=""
+ fwdchain=""
+
+ # Check whether only ports are given or whether the given dest ip is local,
+ # in this case match only DNATed traffic and allow it on input, not forward
+ if [ -z "$redirect_dest_ip" ] || /sbin/ifconfig | grep -qE "addr:${redirect_dest_ip//./\\.}\b"; then
+ fwdopt="-m conntrack --ctstate DNAT"
+ fwdchain="zone_${redirect_src}"
+ else
+ fwdchain="zone_${redirect_src}_forward"
+ fi
+
+ natopt="--to-destination"
+ natchain="zone_${redirect_src}_prerouting"
+ nataddr="$redirect_dest_ip"
+ fw_get_port_range natports "${redirect_dest_port#!}" "-"
+
+ fw_get_negation srcdaddr '-d' "${redirect_src_dip:+$redirect_src_dip/$redirect_src_dip_prefixlen}"
+ fw_get_port_range srcdports "$redirect_src_dport" ":"
+ fw_get_negation srcdports '--dport' "$srcdports"
+
+ list_contains FW_CONNTRACK_ZONES $redirect_src || \
+ append FW_CONNTRACK_ZONES $redirect_src
+
+ elif [ "$redirect_target" == "SNAT" ]; then
+ [ -n "${redirect_dest#*}" -a -n "$redirect_src_dip" ] || {
+ fw_log error "SNAT redirect ${redirect_name}: needs dest and src_dip, skipping"
+ return 0
+ }
+
+ fwdchain="${redirect_src:+zone_${redirect_src}_forward}"
+
+ natopt="--to-source"
+ natchain="zone_${redirect_dest}_nat"
+ nataddr="$redirect_src_dip"
+ fw_get_port_range natports "${redirect_src_dport#!}" "-"
+
+ fw_get_negation srcdaddr '-d' "${redirect_dest_ip:+$redirect_dest_ip/$redirect_dest_ip_prefixlen}"
+ fw_get_port_range srcdports "$redirect_dest_port" ":"
+ fw_get_negation srcdports '--dport' "$srcdports"
+
+ list_contains FW_CONNTRACK_ZONES $redirect_dest || \
+ append FW_CONNTRACK_ZONES $redirect_dest
+
+ else
+ fw_log error "redirect ${redirect_name}: target must be either DNAT or SNAT, skipping"
+ return 0
+ fi
+
+ local mode
+ fw_get_family_mode mode ${redirect_family:-x} ${redirect_src:-$redirect_dest} I
+
+ local srcaddr
+ fw_get_negation srcaddr '-s' "${redirect_src_ip:+$redirect_src_ip/$redirect_src_ip_prefixlen}"
+
+ local srcports
+ fw_get_port_range srcports "$redirect_src_port" ":"
+ fw_get_negation srcports '--sport' "$srcports"
+
+ local destaddr
+ fw_get_negation destaddr '-d' "${redirect_dest_ip:+$redirect_dest_ip/$redirect_dest_ip_prefixlen}"
+
+ local destports
+ fw_get_port_range destports "${redirect_dest_port:-$redirect_src_dport}" ":"
+ fw_get_negation destports '--dport' "$destports"
+
+ [ "$redirect_proto" == "tcpudp" ] && redirect_proto="tcp udp"
+ local pr; for pr in $redirect_proto; do
+ fw_get_negation pr '-p' "$pr"
+ local sm; for sm in ${redirect_src_mac:-""}; do
+ fw_get_negation sm '--mac-source' "$sm"
+ fw add $mode n $natchain $redirect_target + \
+ { $redirect_src_ip $redirect_dest_ip } { \
+ $srcaddr $srcdaddr $pr \
+ $srcports $srcdports \
+ ${sm:+-m mac $sm} \
+ $natopt $nataddr${natports:+:$natports} \
+ $redirect_options \
+ }
+
+ fw add $mode f ${fwdchain:-forward} ACCEPT + \
+ { $redirect_src_ip $redirect_dest_ip } { \
+ $srcaddr $destaddr \
+ $pr \
+ $srcports $destports \
+ ${sm:+-m mac $sm} \
+ $fwdopt \
+ $redirect_extra \
+ }
+ done
+ done
+
+ fw_callback post redirect
+}
diff --git a/package/firewall/files/lib/core_rule.sh b/package/firewall/files/lib/core_rule.sh
new file mode 100644
index 000000000..f49c42af5
--- /dev/null
+++ b/package/firewall/files/lib/core_rule.sh
@@ -0,0 +1,110 @@
+# Copyright (C) 2009-2010 OpenWrt.org
+
+fw_config_get_rule() {
+ [ "${rule_NAME}" != "$1" ] || return
+ fw_config_get_section "$1" rule { \
+ string _name "$1" \
+ string name "" \
+ string src "" \
+ ipaddr src_ip "" \
+ string src_mac "" \
+ string src_port "" \
+ string dest "" \
+ ipaddr dest_ip "" \
+ string dest_port "" \
+ string icmp_type "" \
+ string proto "tcpudp" \
+ string target "" \
+ string family "" \
+ string limit "" \
+ string limit_burst "" \
+ string extra "" \
+ } || return
+ [ -n "$rule_name" ] || rule_name=$rule__name
+}
+
+fw_load_rule() {
+ fw_config_get_rule "$1"
+
+ [ "$rule_target" != "NOTRACK" ] || [ -n "$rule_src" ] || [ "$rule_src" != "*" ] || {
+ fw_log error "NOTRACK rule ${rule_name}: needs src, skipping"
+ return 0
+ }
+
+ fw_callback pre rule
+
+ local table=f
+ local chain=input
+ local target="${rule_target:-REJECT}"
+ if [ "$target" == "NOTRACK" ]; then
+ table=r
+ chain="zone_${rule_src}_notrack"
+ else
+ if [ -n "$rule_src" ]; then
+ if [ "$rule_src" != "*" ]; then
+ chain="zone_${rule_src}${rule_dest:+_forward}"
+ else
+ chain="${rule_dest:+forward}"
+ chain="${chain:-input}"
+ fi
+ fi
+
+ if [ -n "$rule_dest" ]; then
+ if [ "$rule_dest" != "*" ]; then
+ target="zone_${rule_dest}_${target}"
+ elif [ "$target" = REJECT ]; then
+ target=reject
+ fi
+ fi
+ fi
+
+ local mode
+ fw_get_family_mode mode ${rule_family:-x} "$rule_src" I
+
+ local src_spec dest_spec
+ fw_get_negation src_spec '-s' "${rule_src_ip:+$rule_src_ip/$rule_src_ip_prefixlen}"
+ fw_get_negation dest_spec '-d' "${rule_dest_ip:+$rule_dest_ip/$rule_dest_ip_prefixlen}"
+
+ [ "$rule_proto" == "tcpudp" ] && rule_proto="tcp udp"
+ local pr; for pr in $rule_proto; do
+ local sports dports itypes
+ case "$pr" in
+ icmp|icmpv6|1|58)
+ sports=""; dports=""
+ itypes="$rule_icmp_type"
+ ;;
+ *)
+ sports="$rule_src_port"
+ dports="$rule_dest_port"
+ itypes=""
+ ;;
+ esac
+
+ fw_get_negation pr '-p' "$pr"
+ local sp; for sp in ${sports:-""}; do
+ fw_get_port_range sp $sp
+ fw_get_negation sp '--sport' "$sp"
+ local dp; for dp in ${dports:-""}; do
+ fw_get_port_range dp $dp
+ fw_get_negation dp '--dport' "$dp"
+ local sm; for sm in ${rule_src_mac:-""}; do
+ fw_get_negation sm '--mac-source' "$sm"
+ local it; for it in ${itypes:-""}; do
+ fw_get_negation it '--icmp-type' "$it"
+ fw add $mode $table $chain $target + \
+ { $rule_src_ip $rule_dest_ip } { \
+ $src_spec $dest_spec \
+ $pr $sp $dp $it \
+ ${sm:+-m mac $sm} \
+ ${rule_limit:+-m limit --limit $rule_limit \
+ ${rule_limit_burst:+--limit-burst $rule_limit_burst}} \
+ $rule_extra \
+ }
+ done
+ done
+ done
+ done
+ done
+
+ fw_callback post rule
+}
diff --git a/package/firewall/files/lib/fw.sh b/package/firewall/files/lib/fw.sh
new file mode 100644
index 000000000..76e294f56
--- /dev/null
+++ b/package/firewall/files/lib/fw.sh
@@ -0,0 +1,324 @@
+# Copyright (C) 2009-2010 OpenWrt.org
+# Copyright (C) 2009 Malte S. Stretz
+
+export FW_4_ERROR=0
+export FW_6_ERROR=0
+export FW_i_ERROR=0
+export FW_e_ERROR=0
+export FW_a_ERROR=0
+
+#TODO: remove this
+[ "${-#*x}" == "$-" ] && {
+ fw() {
+ fw__exec "$@"
+ }
+} || {
+ fw() {
+ local os=$-
+ set +x
+ fw__exec "$@"
+ local rc=$?
+ set -$os
+ return $rc
+ }
+}
+
+fw__exec() { # <action> <family> <table> <chain> <target> <position> { <rules> }
+ local cmd fam tab chn tgt pos
+ local i
+ for i in cmd fam tab chn tgt pos; do
+ if [ "$1" -a "$1" != '{' ]; then
+ eval "$i='$1'"
+ shift
+ else
+ eval "$i=-"
+ fi
+ done
+
+ fw__rc() {
+ export FW_${fam#G}_ERROR=$1
+ return $1
+ }
+
+ fw__dualip() {
+ fw $cmd 4 $tab $chn $tgt $pos "$@"
+ fw $cmd 6 $tab $chn $tgt $pos "$@"
+ fw__rc $((FW_4_ERROR | FW_6_ERROR))
+ }
+
+ fw__autoip() {
+ local ip4 ip6
+ shift
+ while [ "$1" != '}' ]; do
+ case "$1" in
+ *:*) ip6=1 ;;
+ *.*.*.*) ip4=1 ;;
+ esac
+ shift
+ done
+ shift
+ if [ "${ip4:-4}" == "${ip6:-6}" ]; then
+ echo "fw: can't mix ip4 and ip6" >&2
+ return 1
+ fi
+ local ver=${ip4:+4}${ip6:+6}
+ fam=i
+ fw $cmd ${ver:-i} $tab $chn $tgt $pos "$@"
+ fw__rc $?
+ }
+
+ fw__has() {
+ local tab=${1:-$tab}
+ if [ $tab == '-' ]; then
+ type $app > /dev/null 2> /dev/null
+ fw__rc $(($? & 1))
+ return
+ fi
+ [ "$app" != ip6tables ] || [ "$tab" != nat ]
+ fw__rc $?
+ }
+
+ fw__err() {
+ local err
+ eval "err=\$FW_${fam}_ERROR"
+ fw__rc $err
+ }
+
+ local app=
+ local pol=
+ case "$fam" in
+ *4) [ $FW_DISABLE_IPV4 == 0 ] && app=iptables || return ;;
+ *6) [ $FW_DISABLE_IPV6 == 0 ] && app=ip6tables || return ;;
+ i) fw__dualip "$@"; return ;;
+ I) fw__autoip "$@"; return ;;
+ e) app=ebtables ;;
+ a) app=arptables ;;
+ -) fw $cmd i $tab $chn $tgt $pos "$@"; return ;;
+ *) return 254 ;;
+ esac
+ case "$tab" in
+ f) tab=filter ;;
+ m) tab=mangle ;;
+ n) tab=nat ;;
+ r) tab=raw ;;
+ -) tab=filter ;;
+ esac
+ case "$cmd:$chn:$tgt:$pos" in
+ add:*:-:*) cmd=new-chain ;;
+ add:*:*:-) cmd=append ;;
+ add:*:*:$) cmd=append ;;
+ add:*:*:*) cmd=insert ;;
+ del:-:*:*) cmd=delete-chain; fw flush $fam $tab ;;
+ del:*:-:*) cmd=delete-chain; fw flush $fam $tab $chn ;;
+ del:*:*:*) cmd=delete ;;
+ flush:*) ;;
+ policy:*) pol=$tgt; tgt=- ;;
+ has:*) fw__has; return ;;
+ err:*) fw__err; return ;;
+ list:*) cmd="numeric --verbose --$cmd" ;;
+ *) return 254 ;;
+ esac
+ case "$chn" in
+ -) chn= ;;
+ esac
+ case "$tgt" in
+ -) tgt= ;;
+ esac
+
+ local rule_offset
+ case "$pos" in
+ ^) pos=1 ;;
+ $) pos= ;;
+ -) pos= ;;
+ +) eval "rule_offset=\${FW__RULE_OFS_${app}_${tab}_${chn}:-1}" ;;
+ esac
+
+ if ! fw__has - family || ! fw__has $tab ; then
+ export FW_${fam}_ERROR=0
+ return 0
+ fi
+
+ case "$fam" in
+ G*) shift; while [ $# -gt 0 ] && [ "$1" != "{" ]; do shift; done ;;
+ esac
+
+ if [ $# -gt 0 ]; then
+ shift
+ if [ $cmd == delete ]; then
+ pos=
+ fi
+ fi
+
+ local cmdline="$app --table ${tab} --${cmd} ${chn} ${pol} ${rule_offset:-${pos}} ${tgt:+--jump "$tgt"}"
+ while [ $# -gt 1 ]; do
+ # special parameter handling
+ case "$1:$2" in
+ -p:icmp*|-p:1|-p:58|--protocol:icmp*|--protocol:1|--protocol:58)
+ [ "$app" = ip6tables ] && \
+ cmdline="$cmdline -p icmpv6" || \
+ cmdline="$cmdline -p icmp"
+ shift
+ ;;
+ --icmp-type:*|--icmpv6-type:*)
+ local icmp_type
+ if [ "$app" = ip6tables ] && fw_check_icmptype6 icmp_type "$2"; then
+ cmdline="$cmdline $icmp_type"
+ elif [ "$app" = iptables ] && fw_check_icmptype4 icmp_type "$2"; then
+ cmdline="$cmdline $icmp_type"
+ else
+ local fam=IPv4; [ "$app" = ip6tables ] && fam=IPv6
+ fw_log info "ICMP type '$2' is not valid for $fam address family, skipping rule"
+ return 1
+ fi
+ shift
+ ;;
+ *) cmdline="$cmdline $1" ;;
+ esac
+ shift
+ done
+
+ [ -n "$FW_TRACE" ] && echo $cmdline >&2
+
+ $cmdline
+
+ local rv=$?
+ [ $rv -eq 0 ] && [ -n "$rule_offset" ] && \
+ export -- "FW__RULE_OFS_${app}_${tab}_${chn}=$(($rule_offset + 1))"
+ fw__rc $rv
+}
+
+fw_get_port_range() {
+ local _var=$1
+ local _ports=$2
+ local _delim=${3:-:}
+ if [ "$4" ]; then
+ fw_get_port_range $_var "${_ports}-${4}" $_delim
+ return
+ fi
+
+ local _first=${_ports%-*}
+ local _last=${_ports#*-}
+ if [ "${_first#!}" != "${_last#!}" ]; then
+ export -- "$_var=$_first$_delim${_last#!}"
+ else
+ export -- "$_var=$_first"
+ fi
+}
+
+fw_get_family_mode() {
+ local _var="$1"
+ local _hint="$2"
+ local _zone="$3"
+ local _mode="$4"
+
+ local _ipv4 _ipv6
+ [ "$_zone" != "*" ] && {
+ [ -n "$FW_ZONES4$FW_ZONES6" ] && {
+ list_contains FW_ZONES4 "$_zone" && _ipv4=1 || _ipv4=0
+ list_contains FW_ZONES6 "$_zone" && _ipv6=1 || _ipv6=0
+ } || {
+ _ipv4=$(uci_get_state firewall core "${_zone}_ipv4" 0)
+ _ipv6=$(uci_get_state firewall core "${_zone}_ipv6" 0)
+ }
+ } || {
+ _ipv4=1
+ _ipv6=1
+ }
+
+ case "$_hint:$_ipv4:$_ipv6" in
+ *4:1:*|*:1:0) export -n -- "$_var=G4" ;;
+ *6:*:1|*:0:1) export -n -- "$_var=G6" ;;
+ *) export -n -- "$_var=$_mode" ;;
+ esac
+}
+
+fw_get_negation() {
+ local _var="$1"
+ local _flag="$2"
+ local _value="$3"
+
+ [ "${_value#!}" != "$_value" ] && \
+ export -n -- "$_var=! $_flag ${_value#!}" || \
+ export -n -- "$_var=${_value:+$_flag $_value}"
+}
+
+fw_get_subnet4() {
+ local _var="$1"
+ local _flag="$2"
+ local _name="$3"
+
+ local _ipaddr="$(uci_get_state network "${_name#!}" ipaddr)"
+ local _netmask="$(uci_get_state network "${_name#!}" netmask)"
+
+ case "$_ipaddr" in
+ *.*.*.*)
+ [ "${_name#!}" != "$_name" ] && \
+ export -n -- "$_var=! $_flag $_ipaddr/${_netmask:-255.255.255.255}" || \
+ export -n -- "$_var=$_flag $_ipaddr/${_netmask:-255.255.255.255}"
+ return 0
+ ;;
+ esac
+
+ export -n -- "$_var="
+ return 1
+}
+
+fw_check_icmptype4() {
+ local _var="$1"
+ local _type="$2"
+ case "$_type" in
+ ![0-9]*) export -n -- "$_var=! --icmp-type ${_type#!}"; return 0 ;;
+ [0-9]*) export -n -- "$_var=--icmp-type $_type"; return 0 ;;
+ esac
+
+ [ -z "$FW_ICMP4_TYPES" ] && \
+ export FW_ICMP4_TYPES=$(
+ iptables -p icmp -h 2>/dev/null | \
+ sed -n -e '/^Valid ICMP Types:/ {
+ n; :r; s/[()]/ /g; s/[[:space:]]\+/\n/g; p; n; b r
+ }' | sort -u
+ )
+
+ local _check
+ for _check in $FW_ICMP4_TYPES; do
+ if [ "$_check" = "${_type#!}" ]; then
+ [ "${_type#!}" != "$_type" ] && \
+ export -n -- "$_var=! --icmp-type ${_type#!}" || \
+ export -n -- "$_var=--icmp-type $_type"
+ return 0
+ fi
+ done
+
+ export -n -- "$_var="
+ return 1
+}
+
+fw_check_icmptype6() {
+ local _var="$1"
+ local _type="$2"
+ case "$_type" in
+ ![0-9]*) export -n -- "$_var=! --icmpv6-type ${_type#!}"; return 0 ;;
+ [0-9]*) export -n -- "$_var=--icmpv6-type $_type"; return 0 ;;
+ esac
+
+ [ -z "$FW_ICMP6_TYPES" ] && \
+ export FW_ICMP6_TYPES=$(
+ ip6tables -p icmpv6 -h 2>/dev/null | \
+ sed -n -e '/^Valid ICMPv6 Types:/ {
+ n; :r; s/[()]/ /g; s/[[:space:]]\+/\n/g; p; n; b r
+ }' | sort -u
+ )
+
+ local _check
+ for _check in $FW_ICMP6_TYPES; do
+ if [ "$_check" = "${_type#!}" ]; then
+ [ "${_type#!}" != "$_type" ] && \
+ export -n -- "$_var=! --icmpv6-type ${_type#!}" || \
+ export -n -- "$_var=--icmpv6-type $_type"
+ return 0
+ fi
+ done
+
+ export -n -- "$_var="
+ return 1
+}
diff --git a/package/firewall/files/lib/uci_firewall.sh b/package/firewall/files/lib/uci_firewall.sh
new file mode 100644
index 000000000..7c95a7a93
--- /dev/null
+++ b/package/firewall/files/lib/uci_firewall.sh
@@ -0,0 +1,5 @@
+# This file is here for backwards compatibility and to override the
+# uci_firewall.sh from an earlier version.
+type fw_is_loaded >/dev/null || {
+ . /lib/firewall/core.sh
+}
diff --git a/package/firewall/files/reflection.hotplug b/package/firewall/files/reflection.hotplug
new file mode 100644
index 000000000..843c615bc
--- /dev/null
+++ b/package/firewall/files/reflection.hotplug
@@ -0,0 +1,132 @@
+#!/bin/sh
+
+. /lib/functions.sh
+. /lib/functions/network.sh
+
+if [ "$ACTION" = "add" ] && [ "$INTERFACE" = "wan" ]; then
+ local wanip
+ network_get_ipaddr wanip wan || return
+
+ iptables -t nat -F nat_reflection_in 2>/dev/null || {
+ iptables -t nat -N nat_reflection_in
+ iptables -t nat -A prerouting_rule -j nat_reflection_in
+ }
+
+ iptables -t nat -F nat_reflection_out 2>/dev/null || {
+ iptables -t nat -N nat_reflection_out
+ iptables -t nat -A postrouting_rule -j nat_reflection_out
+ }
+
+ iptables -t filter -F nat_reflection_fwd 2>/dev/null || {
+ iptables -t filter -N nat_reflection_fwd
+ iptables -t filter -A forwarding_rule -j nat_reflection_fwd
+ }
+
+ find_networks() {
+ find_networks_cb() {
+ local cfg="$1"
+ local zone="$2"
+
+ local name
+ config_get name "$cfg" name
+
+ [ "$name" = "$zone" ] && {
+ local network
+ config_get network "$cfg" network
+
+ echo ${network:-$zone}
+ return 1
+ }
+ }
+
+ config_foreach find_networks_cb zone "$1"
+ }
+
+ setup_fwd() {
+ local cfg="$1"
+
+ local reflection
+ config_get_bool reflection "$cfg" reflection 1
+ [ "$reflection" == 1 ] || return
+
+ local src
+ config_get src "$cfg" src
+
+ local target
+ config_get target "$cfg" target DNAT
+
+ [ "$src" = wan ] && [ "$target" = DNAT ] && {
+ local dest
+ config_get dest "$cfg" dest "lan"
+ [ "$dest" != "*" ] || return
+
+ local net
+ for net in $(find_networks "$dest"); do
+ local lannet
+ network_get_subnet lannet "$net" || return
+
+ local proto
+ config_get proto "$cfg" proto
+
+ local epmin epmax extport
+ config_get extport "$cfg" src_dport "1-65535"
+ [ -n "$extport" ] || return
+
+ epmin="${extport%[-:]*}"; epmax="${extport#*[-:]}"
+ [ "${epmin#!}" != "$epmax" ] || epmax=""
+
+ local ipmin ipmax intport
+ config_get intport "$cfg" dest_port "$extport"
+
+ ipmin="${intport%[-:]*}"; ipmax="${intport#*[-:]}"
+ [ "${ipmin#!}" != "$ipmax" ] || ipmax=""
+
+ local exthost
+ config_get exthost "$cfg" src_dip "$wanip"
+
+ local inthost
+ config_get inthost "$cfg" dest_ip
+ [ -n "$inthost" ] || return
+
+ [ "$proto" = all ] && proto="tcp udp"
+ [ "$proto" = tcpudp ] && proto="tcp udp"
+
+ [ "${inthost#!}" = "$inthost" ] || return 0
+ [ "${exthost#!}" = "$exthost" ] || return 0
+
+ [ "${epmin#!}" != "$epmin" ] && \
+ extport="! --dport ${epmin#!}${epmax:+:$epmax}" || \
+ extport="--dport $epmin${epmax:+:$epmax}"
+
+ [ "${ipmin#!}" != "$ipmin" ] && \
+ intport="! --dport ${ipmin#!}${ipmax:+:$ipmax}" || \
+ intport="--dport $ipmin${ipmax:+:$ipmax}"
+
+ local p
+ for p in ${proto:-tcp udp}; do
+ case "$p" in
+ tcp|udp|6|17)
+ iptables -t nat -A nat_reflection_in \
+ -s $lannet -d $exthost \
+ -p $p $extport \
+ -j DNAT --to $inthost:${ipmin#!}${ipmax:+-$ipmax}
+
+ iptables -t nat -A nat_reflection_out \
+ -s $lannet -d $inthost \
+ -p $p $intport \
+ -j SNAT --to-source ${lannet%%/*}
+
+ iptables -t filter -A nat_reflection_fwd \
+ -s $lannet -d $inthost \
+ -p $p $intport \
+ -j ACCEPT
+ ;;
+ esac
+ done
+ done
+ }
+ }
+
+ config_load firewall
+ config_foreach setup_fwd redirect
+fi
diff --git a/package/fuse/Makefile b/package/fuse/Makefile
new file mode 100644
index 000000000..9c5acc7cd
--- /dev/null
+++ b/package/fuse/Makefile
@@ -0,0 +1,108 @@
+#
+# Copyright (C) 2006-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=fuse
+PKG_VERSION:=2.9.0
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/$(PKG_NAME)
+PKG_MD5SUM:=894ee11674f89a915ae87524aed55bc4
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/fuse/Default
+ TITLE:=FUSE
+ URL:=http://fuse.sourceforge.net/
+endef
+
+define Package/fuse/Default/description
+ FUSE (Filesystem in UserSpacE)
+endef
+
+define Package/fuse-utils
+$(call Package/fuse/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libfuse
+ TITLE+= (utilities)
+ SUBMENU:=Filesystem
+endef
+
+define Package/fuse-utils/description
+$(call Package/fuse/Default/description)
+ This package contains the FUSE utilities.
+ - fusermount
+ - ulockmgr_server
+endef
+
+define Package/libfuse
+$(call Package/fuse/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE+= (library)
+ DEPENDS:=+kmod-fuse +libpthread
+ SUBMENU:=Filesystem
+endef
+
+define Package/libfuse/description
+$(call Package/fuse/Default/description)
+ This package contains the FUSE shared libraries, needed by other programs.
+ - libfuse
+ - libulockmgr
+endef
+
+# generic args
+CONFIGURE_ARGS += \
+ --enable-shared \
+ --enable-static \
+ --disable-rpath \
+ --disable-example \
+ --disable-mtab
+
+# generic package uses lib & utils
+CONFIGURE_ARGS += --enable-lib --enable-util
+
+define Build/InstallDev
+ @echo "--> Build/InstallDev enter"
+ mkdir -p $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/{fuse,*.h} $(1)/usr/include/
+ mkdir -p $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/*.{a,so*} $(1)/usr/lib/
+ mkdir -p $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/fuse.pc $(1)/usr/lib/pkgconfig/
+ $(SED) 's,-I$$$${includedir}/fuse,,g' $(1)/usr/lib/pkgconfig/fuse.pc
+ $(SED) 's,-L$$$${libdir},,g' $(1)/usr/lib/pkgconfig/fuse.pc
+ @echo "--> Build/InstallDev leave"
+endef
+
+define Package/fuse-utils/install
+ @echo "--> Package/fuse-utils/install enter"
+ $(INSTALL_DIR) $(1)/usr/bin
+ # use cp and keep fusermount sticky bit
+ $(FIND) $(PKG_INSTALL_DIR)/usr/bin/ -type f -exec $(CP) -a {} $(1)/usr/bin/ \;
+ @echo "--> Package/fuse-utils/install leave"
+endef
+
+define Package/libfuse/install
+ @echo "--> Package/libfuse/install enter"
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so.* $(1)/usr/lib/
+ @echo "--> Package/libfuse/install leave"
+endef
+
+define Package/kmod-fuse/install
+ @echo "--> Package/kmod-fuse/install enter/leave"
+endef
+
+$(eval $(call BuildPackage,fuse-utils))
+$(eval $(call BuildPackage,libfuse))
diff --git a/package/fuse/patches/112-no_break_on_mknod.patch b/package/fuse/patches/112-no_break_on_mknod.patch
new file mode 100644
index 000000000..5f913df6d
--- /dev/null
+++ b/package/fuse/patches/112-no_break_on_mknod.patch
@@ -0,0 +1,11 @@
+--- a/util/Makefile.in
++++ b/util/Makefile.in
+@@ -641,7 +641,7 @@ mount_util.c: $(top_srcdir)/lib/mount_ut
+
+ install-exec-hook:
+ -chmod u+s $(DESTDIR)$(bindir)/fusermount
+- @if test ! -e $(DESTDIR)/dev/fuse; then \
++ -@if test ! -e $(DESTDIR)/dev/fuse; then \
+ $(mkdir_p) $(DESTDIR)/dev; \
+ echo "mknod $(DESTDIR)/dev/fuse -m 0666 c 10 229 || true"; \
+ mknod $(DESTDIR)/dev/fuse -m 0666 c 10 229 || true; \
diff --git a/package/gdb/Makefile b/package/gdb/Makefile
new file mode 100644
index 000000000..10178b5cb
--- /dev/null
+++ b/package/gdb/Makefile
@@ -0,0 +1,87 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gdb
+PKG_VERSION:=6.8a
+PKG_RELEASE:=4
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=@GNU/gdb
+PKG_MD5SUM:=da20d043e6729f74b909bd507bcae5c9
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-6.8
+
+PKG_BUILD_PARALLEL:=0
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/gdb/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=@!(avr32||cris)
+ URL:=http://www.gnu.org/software/gdb/
+endef
+
+define Package/gdb
+$(call Package/gdb/Default)
+ TITLE:=GNU Debugger
+ DEPENDS+=+libreadline +libncurses
+endef
+
+define Package/gdb/description
+GDB, the GNU Project debugger, allows you to see what is going on `inside'
+another program while it executes -- or what another program was doing at the
+moment it crashed.
+endef
+
+define Package/gdbserver
+$(call Package/gdb/Default)
+ TITLE:=Remote server for GNU Debugger
+endef
+
+define Package/gdbserver/description
+GDBSERVER is a program that allows you to run GDB on a different machine than the
+one which is running the program being debugged.
+endef
+
+# XXX: add --disable-werror to prevent build failure with arm
+CONFIGURE_ARGS+= \
+ --with-system-readline \
+ --without-expat \
+ --disable-werror
+
+CONFIGURE_VARS+= \
+ ac_cv_search_tgetent="$(TARGET_LDFLAGS) -lncurses -lreadline"
+
+define Build/Compile
+ +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ CPPFLAGS="$(TARGET_CPPFLAGS)" \
+ all
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ CPPFLAGS="$(TARGET_CPPFLAGS)" \
+ install-gdb
+endef
+
+define Package/gdb/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/gdb $(1)/usr/bin/
+endef
+
+define Package/gdbserver/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/gdbserver $(1)/usr/bin/
+ifneq ($(CONFIG_USE_EGLIBC),)
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(TOOLCHAIN_DIR)/lib/libthread_db* $(1)/usr/lib
+endif
+endef
+
+$(eval $(call BuildPackage,gdb))
+$(eval $(call BuildPackage,gdbserver))
diff --git a/package/goldfish-qemu/Makefile b/package/goldfish-qemu/Makefile
new file mode 100644
index 000000000..e5b4083ea
--- /dev/null
+++ b/package/goldfish-qemu/Makefile
@@ -0,0 +1,70 @@
+#
+# Copyright (C) 2006-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=goldfish-qemu
+PKG_REV:=2b8ea29e2bd12f876a4d06647e6077bf72de567e
+PKG_VERSION:=20090429
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=git://android.git.kernel.org/platform/external/qemu
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_VERSION:=$(PKG_REV)
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_TARGETS:=bin
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/goldfish-qemu
+ SECTION:=emulator
+ CATEGORY:=Emulators
+ DEPENDS:=@TARGET_goldfish
+ TITLE:=A modified version of the Google Android Emulator
+ URL:=http://www.android.com/
+endef
+
+LIBSDL_PATCHED:=sdl-1.2.12-android-20080919
+
+define Download/libsdl-patched
+ FILE:=$(LIBSDL_PATCHED).tar.gz
+ URL:=http://android.git.kernel.org/pub
+ MD5SUM:=22df8cbb2ecb811938eba8410e861650
+endef
+$(eval $(call Download,libsdl-patched))
+
+Build/Exports=
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ zcat $(DL_DIR)/$(LIBSDL_PATCHED).tar.gz | tar x -C $(PKG_BUILD_DIR)
+endef
+
+define Build/Configure
+ [ -x $(PKG_BUILD_DIR)/libsdl/bin/sdl-config ] || ( \
+ cd $(PKG_BUILD_DIR)/$(LIBSDL_PATCHED); \
+ ./android-configure --prefix=$(PKG_BUILD_DIR)/libsdl; \
+ make all install; \
+ )
+endef
+
+define Build/Compile
+ (cd $(PKG_BUILD_DIR); \
+ [ -f $(PKG_BUILD_DIR)/objs/config.make ] || \
+ ./android-configure.sh --sdl-config=$(PKG_BUILD_DIR)/libsdl/bin/sdl-config \
+ )
+ $(MAKE) -C $(PKG_BUILD_DIR)
+endef
+
+define Package/goldfish-qemu/install
+ $(INSTALL_DIR) $(1)
+ $(CP) $(PKG_BUILD_DIR)/objs/emulator $(1)/
+ $(CP) ./skins $(1)/
+endef
+
+$(eval $(call BuildPackage,goldfish-qemu))
diff --git a/package/goldfish-qemu/patches/100-darwin_fix.patch b/package/goldfish-qemu/patches/100-darwin_fix.patch
new file mode 100644
index 000000000..a5f56b3cf
--- /dev/null
+++ b/package/goldfish-qemu/patches/100-darwin_fix.patch
@@ -0,0 +1,30 @@
+--- a/android-configure.sh
++++ b/android-configure.sh
+@@ -656,6 +656,9 @@ case "$CPU" in
+ *) HOST_CPU=$CPU
+ ;;
+ esac
++case "$OS" in
++ darwin*) echo "#define _BSD 1" >> $config_h;;
++esac
+ echo "#define HOST_$HOST_CPU 1" >> $config_h
+ log "Generate : $config_h"
+
+--- a/android/utils/display-quartz.m
++++ b/android/utils/display-quartz.m
+@@ -34,6 +34,7 @@ get_monitor_resolution( int *px_dpi, in
+ int
+ get_nearest_monitor_rect( int *x, int *y, int *width, int *height )
+ {
++#if 0
+ SDL_SysWMinfo info;
+ NSWindow* window;
+
+@@ -108,4 +109,7 @@ get_nearest_monitor_rect( int *x, int
+ }
+ return 0;
+ }
++#else
++ return -1;
++#endif
+ };
diff --git a/package/goldfish-qemu/patches/110-single_image.patch b/package/goldfish-qemu/patches/110-single_image.patch
new file mode 100644
index 000000000..92a9e543d
--- /dev/null
+++ b/package/goldfish-qemu/patches/110-single_image.patch
@@ -0,0 +1,233 @@
+--- a/android/cmdline-option.c
++++ b/android/cmdline-option.c
+@@ -50,16 +50,6 @@ android_parse_options( int *pargc, char
+ char arg2_tab[64], *arg2 = arg2_tab;
+ int nn;
+
+- /* process @<name> as a special exception meaning
+- * '-avd <name>'
+- */
+- if (aread[0][0] == '@') {
+- opt->avd = aread[0]+1;
+- nargs--;
+- aread++;
+- continue;
+- }
+-
+ /* anything that isn't an option past this points
+ * exits the loop
+ */
+--- a/android/cmdline-options.h
++++ b/android/cmdline-options.h
+@@ -60,21 +60,16 @@
+ */
+
+ CFG_PARAM( sysdir, "<dir>", "search for system disk images in <dir>" )
+-CFG_PARAM( system, "<file>", "read initial system image from <file>" )
+-CFG_PARAM( datadir, "<dir>", "write user data into <dir>" )
+-CFG_PARAM( kernel, "<file>", "use specific emulated kernel" )
+-CFG_PARAM( ramdisk, "<file>", "ramdisk image (default <system>/ramdisk.img" )
+-CFG_PARAM( image, "<file>", "obsolete, use -system <file> instead" )
+-CFG_PARAM( init_data, "<file>", "initial data image (default <system>/userdata.img" )
+-CFG_PARAM( initdata, "<file>", "same as '-init-data <file>'" )
+-CFG_PARAM( data, "<file>", "data image (default <datadir>/userdata-qemu.img" )
++CFG_PARAM( system, "<file>", "read system image from <file>, default: <system>/system.img" )
++CFG_PARAM( data, "<file>", "data image, default: <system>/data.img" )
++CFG_PARAM( kernel, "<file>", "use specific emulated kernel, default: kernel.bin" )
++CFG_PARAM( ramdisk, "<file>", "ramdisk image (default <system>/ramdisk.bin" )
+ CFG_PARAM( partition_size, "<size>", "system/data partition size in MBs" )
+ CFG_PARAM( cache, "<file>", "cache partition image (default is temporary file)" )
+ CFG_FLAG ( no_cache, "disable the cache partition" )
+ CFG_FLAG ( nocache, "same as -no-cache" )
+ OPT_PARAM( sdcard, "<file>", "SD card image (default <system>/sdcard.img")
+ OPT_FLAG ( wipe_data, "reset the use data image (copy it from initdata)" )
+-CFG_PARAM( avd, "<name>", "use a specific android virtual device" )
+ CFG_PARAM( skindir, "<dir>", "search skins in <dir> (default <system>/skins)" )
+ CFG_PARAM( skin, "<name>", "select a given skin" )
+ CFG_FLAG ( no_skin, "don't use any emulator skin" )
+--- a/android/main.c
++++ b/android/main.c
+@@ -1606,6 +1606,7 @@ report_console( const char* proto_port,
+ * containing 'fileName'. this is *not* the full
+ * path to 'fileName'.
+ */
++
+ static char*
+ _getSdkImagePath( const char* fileName )
+ {
+@@ -1617,8 +1618,6 @@ _getSdkImagePath( const char* fileName
+
+ static const char* const searchPaths[] = {
+ "", /* program's directory */
+- "/lib/images", /* this is for SDK 1.0 */
+- "/../platforms/android-1.1/images", /* this is for SDK 1.1 */
+ NULL
+ };
+
+@@ -1841,25 +1840,7 @@ int main(int argc, char **argv)
+ }
+ }
+
+- /* legacy support: we used to use -system <dir> and -image <file>
+- * instead of -sysdir <dir> and -system <file>, so handle this by checking
+- * whether the options point to directories or files.
+- */
+- if (opts->image != NULL) {
+- if (opts->system != NULL) {
+- if (opts->sysdir != NULL) {
+- derror( "You can't use -sysdir, -system and -image at the same time.\n"
+- "You should probably use '-sysdir <path> -system <file>'.\n" );
+- exit(2);
+- }
+- }
+- dwarning( "Please note that -image is obsolete and that -system is now used to point\n"
+- "to the system image. Next time, try using '-sysdir <path> -system <file>' instead.\n" );
+- opts->sysdir = opts->system;
+- opts->system = opts->image;
+- opts->image = NULL;
+- }
+- else if (opts->system != NULL && path_is_dir(opts->system)) {
++ if (opts->system != NULL && path_is_dir(opts->system)) {
+ if (opts->sysdir != NULL) {
+ derror( "Option -system should now be followed by a file path, not a directory one.\n"
+ "Please use '-sysdir <path>' to point to the system directory.\n" );
+@@ -1885,49 +1866,11 @@ int main(int argc, char **argv)
+ if (opts->noskin)
+ opts->no_skin = opts->noskin;
+
+- if (opts->initdata) {
+- opts->init_data = opts->initdata;
+- opts->initdata = NULL;
+- }
+-
+- /* If no AVD name was given, try to find the top of the
+- * Android build tree
+- */
+- if (opts->avd == NULL) {
+- do {
+- char* out = getenv("ANDROID_PRODUCT_OUT");
+-
+- if (out == NULL || out[0] == 0)
+- break;
+-
+- if (!path_exists(out)) {
+- derror("Can't access ANDROID_PRODUCT_OUT as '%s'\n"
+- "You need to build the Android system before launching the emulator",
+- out);
+- exit(2);
+- }
+-
+- android_build_root = path_parent( out, 4 );
+- if (android_build_root == NULL || !path_exists(android_build_root)) {
+- derror("Can't find the Android build root from '%s'\n"
+- "Please check the definition of the ANDROID_PRODUCT_OUT variable.\n"
+- "It should point to your product-specific build output directory.\n",
+- out );
+- exit(2);
+- }
+- android_build_out = out;
+- D( "found Android build root: %s", android_build_root );
+- D( "found Android build out: %s", android_build_out );
+- } while (0);
+- }
+ /* if no virtual device name is given, and we're not in the
+ * Android build system, we'll need to perform some auto-detection
+ * magic :-)
+ */
+- if (opts->avd == NULL && !android_build_out)
+ {
+- char dataDirIsSystem = 0;
+-
+ if (!opts->sysdir) {
+ opts->sysdir = _getSdkImagePath("system.img");
+ if (!opts->sysdir) {
+@@ -1945,47 +1888,30 @@ int main(int argc, char **argv)
+ }
+
+ if (!opts->system) {
+- opts->system = _getSdkSystemImage(opts->sysdir, "-image", "system.img");
+- D("autoconfig: -image %s", opts->image);
++ opts->system = _getSdkSystemImage(opts->sysdir, "-system", "system.img");
++ D("autoconfig: -system %s", opts->system);
+ }
+
+ if (!opts->kernel) {
+- opts->kernel = _getSdkSystemImage(opts->sysdir, "-kernel", "kernel-qemu");
++ opts->kernel = _getSdkSystemImage(opts->sysdir, "-kernel", "kernel.bin");
+ D("autoconfig: -kernel %s", opts->kernel);
+ }
+
+ if (!opts->ramdisk) {
+- opts->ramdisk = _getSdkSystemImage(opts->sysdir, "-ramdisk", "ramdisk.img");
++ opts->ramdisk = _getSdkSystemImage(opts->sysdir, "-ramdisk", "ramdisk.bin");
+ D("autoconfig: -ramdisk %s", opts->ramdisk);
+ }
+
+- /* if no data directory is specified, use the system directory */
+- if (!opts->datadir) {
+- opts->datadir = qemu_strdup(opts->sysdir);
+- dataDirIsSystem = 1;
+- D("autoconfig: -datadir %s", opts->sysdir);
+- }
+-
+ if (!opts->data) {
+ /* check for userdata-qemu.img in the data directory */
+- bufprint(tmp, tmpend, "%s/userdata-qemu.img", opts->datadir);
+- if (!path_exists(tmp)) {
+- derror(
+- "You did not provide the name of an Android Virtual Device\n"
+- "with the '-avd <name>' option. Read -help-avd for more information.\n\n"
+-
+- "If you *really* want to *NOT* run an AVD, consider using '-data <file>'\n"
+- "to specify a data partition image file (I hope you know what you're doing).\n"
+- );
+- exit(2);
+- }
++ bufprint(tmp, tmpend, "%s/data.img", opts->sysdir);
+
+ opts->data = qemu_strdup(tmp);
+ D("autoconfig: -data %s", opts->data);
+ }
+
+- if (!opts->sdcard && opts->datadir) {
+- bufprint(tmp, tmpend, "%s/sdcard.img", opts->datadir);
++ if (!opts->sdcard && opts->sysdir) {
++ bufprint(tmp, tmpend, "%s/sdcard.img", opts->sysdir);
+ if (path_exists(tmp)) {
+ opts->sdcard = qemu_strdup(tmp);
+ D("autoconfig: -sdcard %s", opts->sdcard);
+@@ -2029,19 +1955,6 @@ int main(int argc, char **argv)
+ android_avdParams->skinName = opts->skin;
+ android_avdParams->skinRootPath = opts->skindir;
+
+- /* setup the virtual device differently depending on whether
+- * we are in the Android build system or not
+- */
+- if (opts->avd != NULL)
+- {
+- android_avdInfo = avdInfo_new( opts->avd, android_avdParams );
+- if (android_avdInfo == NULL) {
+- /* an error message has already been printed */
+- dprint("could not find virtual device named '%s'", opts->avd);
+- exit(1);
+- }
+- }
+- else
+ {
+ if (!android_build_out) {
+ android_build_out = android_build_root = opts->sysdir;
+--- a/android/avd/info.c
++++ b/android/avd/info.c
+@@ -1233,10 +1233,8 @@ _getBuildImagePaths( AvdInfo* i, AvdInf
+ ** take care of checking the state
+ **/
+ imageLoader_set ( l, AVD_IMAGE_INITSYSTEM );
+- imageLoader_load( l, IMAGE_REQUIRED | IMAGE_DONT_LOCK );
+-
+- /* force the system image to read-only status */
+- l->pState[0] = IMAGE_STATE_READONLY;
++ l->pState[0] = IMAGE_STATE_MUSTLOCK;
++ imageLoader_load( l, IMAGE_REQUIRED );
+
+ /** cache partition handling
+ **/
diff --git a/package/goldfish-qemu/skins/HVGA/arrow_down.png b/package/goldfish-qemu/skins/HVGA/arrow_down.png
new file mode 100644
index 000000000..19b3764e8
--- /dev/null
+++ b/package/goldfish-qemu/skins/HVGA/arrow_down.png
Binary files differ
diff --git a/package/goldfish-qemu/skins/HVGA/arrow_left.png b/package/goldfish-qemu/skins/HVGA/arrow_left.png
new file mode 100644
index 000000000..113e58427
--- /dev/null
+++ b/package/goldfish-qemu/skins/HVGA/arrow_left.png
Binary files differ
diff --git a/package/goldfish-qemu/skins/HVGA/arrow_right.png b/package/goldfish-qemu/skins/HVGA/arrow_right.png
new file mode 100644
index 000000000..ffe3356c0
--- /dev/null
+++ b/package/goldfish-qemu/skins/HVGA/arrow_right.png
Binary files differ
diff --git a/package/goldfish-qemu/skins/HVGA/arrow_up.png b/package/goldfish-qemu/skins/HVGA/arrow_up.png
new file mode 100644
index 000000000..81c54df51
--- /dev/null
+++ b/package/goldfish-qemu/skins/HVGA/arrow_up.png
Binary files differ
diff --git a/package/goldfish-qemu/skins/HVGA/back.png b/package/goldfish-qemu/skins/HVGA/back.png
new file mode 100644
index 000000000..41034d910
--- /dev/null
+++ b/package/goldfish-qemu/skins/HVGA/back.png
Binary files differ
diff --git a/package/goldfish-qemu/skins/HVGA/device.png b/package/goldfish-qemu/skins/HVGA/device.png
new file mode 100644
index 000000000..465eb029d
--- /dev/null
+++ b/package/goldfish-qemu/skins/HVGA/device.png
Binary files differ
diff --git a/package/goldfish-qemu/skins/HVGA/end.png b/package/goldfish-qemu/skins/HVGA/end.png
new file mode 100644
index 000000000..6830a603b
--- /dev/null
+++ b/package/goldfish-qemu/skins/HVGA/end.png
Binary files differ
diff --git a/package/goldfish-qemu/skins/HVGA/home.png b/package/goldfish-qemu/skins/HVGA/home.png
new file mode 100644
index 000000000..7d021369b
--- /dev/null
+++ b/package/goldfish-qemu/skins/HVGA/home.png
Binary files differ
diff --git a/package/goldfish-qemu/skins/HVGA/key.png b/package/goldfish-qemu/skins/HVGA/key.png
new file mode 100644
index 000000000..7a3f563bd
--- /dev/null
+++ b/package/goldfish-qemu/skins/HVGA/key.png
Binary files differ
diff --git a/package/goldfish-qemu/skins/HVGA/keyboard.png b/package/goldfish-qemu/skins/HVGA/keyboard.png
new file mode 100644
index 000000000..bb076d315
--- /dev/null
+++ b/package/goldfish-qemu/skins/HVGA/keyboard.png
Binary files differ
diff --git a/package/goldfish-qemu/skins/HVGA/layout b/package/goldfish-qemu/skins/HVGA/layout
new file mode 100644
index 000000000..4c3d76420
--- /dev/null
+++ b/package/goldfish-qemu/skins/HVGA/layout
@@ -0,0 +1,380 @@
+parts {
+ device {
+ background {
+ image device.png
+ }
+ display {
+ width 320
+ height 480
+ x 31
+ y 72
+ }
+
+ buttons {
+ soft-left {
+ image menu.png
+ x 147
+ y 555
+ }
+ home {
+ image home.png
+ x 48
+ y 590
+ }
+ back {
+ image back.png
+ x 286
+ y 590
+ }
+ dpad-up {
+ image arrow_up.png
+ x 140
+ y 595
+ }
+ dpad-down {
+ image arrow_down.png
+ x 140
+ y 656
+ }
+ dpad-left {
+ image arrow_left.png
+ x 111
+ y 598
+ }
+ dpad-right {
+ image arrow_right.png
+ x 222
+ y 598
+ }
+ dpad-center {
+ image select.png
+ x 142
+ y 626
+ }
+ phone-dial {
+ image send.png
+ x 48
+ y 646
+ }
+ phone-hangup {
+ image end.png
+ x 286
+ y 646
+ }
+
+ power {
+ image power.png
+ x -38
+ y 52
+ }
+
+ volume-up {
+ image volume_up.png
+ x 362
+ y 260
+ }
+
+ volume-down {
+ image volume_down.png
+ x 362
+ y 310
+ }
+ }
+ }
+
+ keyboard {
+ background {
+ image keyboard.png
+ }
+ buttons {
+ 1 {
+ image key.png
+ x 0
+ y 0
+ }
+ 2 {
+ image key.png
+ x 37
+ y 0
+ }
+ 3 {
+ image key.png
+ x 74
+ y 0
+ }
+ 4 {
+ image key.png
+ x 111
+ y 0
+ }
+ 5 {
+ image key.png
+ x 148
+ y 0
+ }
+ 6 {
+ image key.png
+ x 185
+ y 0
+ }
+ 7 {
+ image key.png
+ x 222
+ y 0
+ }
+ 8 {
+ image key.png
+ x 259
+ y 0
+ }
+ 9 {
+ image key.png
+ x 296
+ y 0
+ }
+ 0 {
+ image key.png
+ x 333
+ y 0
+ }
+
+ q {
+ image key.png
+ x 0
+ y 36
+ }
+ w {
+ image key.png
+ x 37
+ y 36
+ }
+ e {
+ image key.png
+ x 74
+ y 36
+ }
+ r {
+ image key.png
+ x 111
+ y 36
+ }
+ t {
+ image key.png
+ x 148
+ y 36
+ }
+ y {
+ image key.png
+ x 185
+ y 36
+ }
+ u {
+ image key.png
+ x 222
+ y 36
+ }
+ i {
+ image key.png
+ x 259
+ y 36
+ }
+ o {
+ image key.png
+ x 296
+ y 36
+ }
+ p {
+ image key.png
+ x 333
+ y 36
+ }
+
+ a {
+ image key.png
+ x 0
+ y 72
+ }
+ s {
+ image key.png
+ x 37
+ y 72
+ }
+ d {
+ image key.png
+ x 74
+ y 72
+ }
+ f {
+ image key.png
+ x 111
+ y 72
+ }
+ g {
+ image key.png
+ x 148
+ y 72
+ }
+ h {
+ image key.png
+ x 185
+ y 72
+ }
+ j {
+ image key.png
+ x 222
+ y 72
+ }
+ k {
+ image key.png
+ x 259
+ y 72
+ }
+ l {
+ image key.png
+ x 296
+ y 72
+ }
+ DEL {
+ image key.png
+ x 333
+ y 72
+ }
+
+ CAP {
+ image key.png
+ x 0
+ y 108
+ }
+ z {
+ image key.png
+ x 37
+ y 108
+ }
+ x {
+ image key.png
+ x 74
+ y 108
+ }
+ c {
+ image key.png
+ x 111
+ y 108
+ }
+ v {
+ image key.png
+ x 148
+ y 108
+ }
+ b {
+ image key.png
+ x 185
+ y 108
+ }
+ n {
+ image key.png
+ x 222
+ y 108
+ }
+ m {
+ image key.png
+ x 259
+ y 108
+ }
+ PERIOD {
+ image key.png
+ x 296
+ y 108
+ }
+ ENTER {
+ image key.png
+ x 333
+ y 108
+ }
+
+ ALT {
+ image key.png
+ x 0
+ y 144
+ }
+ SYM {
+ image key.png
+ x 37
+ y 144
+ }
+ AT {
+ image key.png
+ x 74
+ y 144
+ }
+ SPACE {
+ image spacebar.png
+ x 111
+ y 144
+ }
+ SLASH {
+ image key.png
+ x 259
+ y 144
+ }
+ COMMA {
+ image key.png
+ x 296
+ y 144
+ }
+ ALT2 {
+ image key.png
+ x 333
+ y 144
+ }
+
+ }
+ }
+}
+
+layouts {
+ portrait {
+ width 900
+ height 730
+ color 0xe0e0e0
+ event EV_SW:0:1
+
+ part1 {
+ name device
+ x 40
+ y -18
+ }
+ part2 {
+ name keyboard
+ x 480
+ y 200
+ }
+ }
+
+ landscape {
+ width 900
+ height 670
+ color 0xe0e0e0
+ event EV_SW:0:0
+
+ part1 {
+ name device
+ x 50
+ y 440
+ rotation 3
+ }
+ part2 {
+ name keyboard
+ x 250
+ y 470
+ }
+ }
+}
+
+keyboard {
+ charmap qwerty2
+}
+
+network {
+ speed full
+ delay none
+}
diff --git a/package/goldfish-qemu/skins/HVGA/menu.png b/package/goldfish-qemu/skins/HVGA/menu.png
new file mode 100644
index 000000000..e81d8abcf
--- /dev/null
+++ b/package/goldfish-qemu/skins/HVGA/menu.png
Binary files differ
diff --git a/package/goldfish-qemu/skins/HVGA/power.png b/package/goldfish-qemu/skins/HVGA/power.png
new file mode 100644
index 000000000..5894288f0
--- /dev/null
+++ b/package/goldfish-qemu/skins/HVGA/power.png
Binary files differ
diff --git a/package/goldfish-qemu/skins/HVGA/select.png b/package/goldfish-qemu/skins/HVGA/select.png
new file mode 100644
index 000000000..803d49315
--- /dev/null
+++ b/package/goldfish-qemu/skins/HVGA/select.png
Binary files differ
diff --git a/package/goldfish-qemu/skins/HVGA/send.png b/package/goldfish-qemu/skins/HVGA/send.png
new file mode 100644
index 000000000..f547c8817
--- /dev/null
+++ b/package/goldfish-qemu/skins/HVGA/send.png
Binary files differ
diff --git a/package/goldfish-qemu/skins/HVGA/spacebar.png b/package/goldfish-qemu/skins/HVGA/spacebar.png
new file mode 100644
index 000000000..19fe60476
--- /dev/null
+++ b/package/goldfish-qemu/skins/HVGA/spacebar.png
Binary files differ
diff --git a/package/goldfish-qemu/skins/HVGA/volume_down.png b/package/goldfish-qemu/skins/HVGA/volume_down.png
new file mode 100644
index 000000000..f8a88dec8
--- /dev/null
+++ b/package/goldfish-qemu/skins/HVGA/volume_down.png
Binary files differ
diff --git a/package/goldfish-qemu/skins/HVGA/volume_up.png b/package/goldfish-qemu/skins/HVGA/volume_up.png
new file mode 100644
index 000000000..940457f70
--- /dev/null
+++ b/package/goldfish-qemu/skins/HVGA/volume_up.png
Binary files differ
diff --git a/package/gpio-button-hotplug/Makefile b/package/gpio-button-hotplug/Makefile
new file mode 100644
index 000000000..adb9a4526
--- /dev/null
+++ b/package/gpio-button-hotplug/Makefile
@@ -0,0 +1,44 @@
+#
+# Copyright (C) 2008-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=gpio-button-hotplug
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/gpio-button-hotplug
+ SUBMENU:=Other modules
+ TITLE:=Simple GPIO Button Hotplug driver
+ FILES:=$(PKG_BUILD_DIR)/gpio-button-hotplug.ko
+ AUTOLOAD:=$(call AutoLoad,30,gpio-button-hotplug)
+ KCONFIG:=
+endef
+
+define KernelPackage/button-hotplug/description
+ Kernel module to generate GPIO button hotplug events
+endef
+
+MAKE_OPTS:= \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ SUBDIRS="$(PKG_BUILD_DIR)"
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ $(MAKE) -C "$(LINUX_DIR)" \
+ $(MAKE_OPTS) \
+ modules
+endef
+
+$(eval $(call KernelPackage,gpio-button-hotplug))
diff --git a/package/gpio-button-hotplug/src/Makefile b/package/gpio-button-hotplug/src/Makefile
new file mode 100644
index 000000000..e96886563
--- /dev/null
+++ b/package/gpio-button-hotplug/src/Makefile
@@ -0,0 +1 @@
+obj-m += gpio-button-hotplug.o
diff --git a/package/gpio-button-hotplug/src/gpio-button-hotplug.c b/package/gpio-button-hotplug/src/gpio-button-hotplug.c
new file mode 100644
index 000000000..d25e70fec
--- /dev/null
+++ b/package/gpio-button-hotplug/src/gpio-button-hotplug.c
@@ -0,0 +1,450 @@
+/*
+ * GPIO Button Hotplug driver
+ *
+ * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * Based on the diag.c - GPIO interface driver for Broadcom boards
+ * Copyright (C) 2006 Mike Baker <mbm@openwrt.org>,
+ * Copyright (C) 2006-2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2008 Andy Boyett <agb@openwrt.org>
+ *
+ * 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/module.h>
+#include <linux/version.h>
+#include <linux/kmod.h>
+
+#include <linux/workqueue.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/kobject.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+
+#define DRV_NAME "gpio-keys-polled"
+
+#define BH_SKB_SIZE 2048
+
+#define PFX DRV_NAME ": "
+
+#undef BH_DEBUG
+
+#ifdef BH_DEBUG
+#define BH_DBG(fmt, args...) printk(KERN_DEBUG "%s: " fmt, DRV_NAME, ##args )
+#else
+#define BH_DBG(fmt, args...) do {} while (0)
+#endif
+
+#define BH_ERR(fmt, args...) printk(KERN_ERR "%s: " fmt, DRV_NAME, ##args )
+
+struct bh_priv {
+ unsigned long seen;
+};
+
+struct bh_event {
+ const char *name;
+ char *action;
+ unsigned long seen;
+
+ struct sk_buff *skb;
+ struct work_struct work;
+};
+
+struct bh_map {
+ unsigned int code;
+ const char *name;
+};
+
+struct gpio_keys_button_data {
+ struct delayed_work work;
+ struct bh_priv bh;
+ int last_state;
+ int count;
+ int threshold;
+ int can_sleep;
+};
+
+extern u64 uevent_next_seqnum(void);
+
+#define BH_MAP(_code, _name) \
+ { \
+ .code = (_code), \
+ .name = (_name), \
+ }
+
+static struct bh_map button_map[] = {
+ BH_MAP(BTN_0, "BTN_0"),
+ BH_MAP(BTN_1, "BTN_1"),
+ BH_MAP(BTN_2, "BTN_2"),
+ BH_MAP(BTN_3, "BTN_3"),
+ BH_MAP(BTN_4, "BTN_4"),
+ BH_MAP(BTN_5, "BTN_5"),
+ BH_MAP(BTN_6, "BTN_6"),
+ BH_MAP(BTN_7, "BTN_7"),
+ BH_MAP(BTN_8, "BTN_8"),
+ BH_MAP(BTN_9, "BTN_9"),
+ BH_MAP(KEY_RESTART, "reset"),
+#ifdef KEY_WPS_BUTTON
+ BH_MAP(KEY_WPS_BUTTON, "wps"),
+#endif /* KEY_WPS_BUTTON */
+};
+
+/* -------------------------------------------------------------------------*/
+
+static int bh_event_add_var(struct bh_event *event, int argv,
+ const char *format, ...)
+{
+ static char buf[128];
+ char *s;
+ va_list args;
+ int len;
+
+ if (argv)
+ return 0;
+
+ va_start(args, format);
+ len = vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+
+ if (len >= sizeof(buf)) {
+ BH_ERR("buffer size too small\n");
+ WARN_ON(1);
+ return -ENOMEM;
+ }
+
+ s = skb_put(event->skb, len + 1);
+ strcpy(s, buf);
+
+ BH_DBG("added variable '%s'\n", s);
+
+ return 0;
+}
+
+static int button_hotplug_fill_event(struct bh_event *event)
+{
+ int ret;
+
+ ret = bh_event_add_var(event, 0, "HOME=%s", "/");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "PATH=%s",
+ "/sbin:/bin:/usr/sbin:/usr/bin");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SUBSYSTEM=%s", "button");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "ACTION=%s", event->action);
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "BUTTON=%s", event->name);
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SEEN=%ld", event->seen);
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SEQNUM=%llu", uevent_next_seqnum());
+
+ return ret;
+}
+
+static void button_hotplug_work(struct work_struct *work)
+{
+ struct bh_event *event = container_of(work, struct bh_event, work);
+ int ret = 0;
+
+ event->skb = alloc_skb(BH_SKB_SIZE, GFP_KERNEL);
+ if (!event->skb)
+ goto out_free_event;
+
+ ret = bh_event_add_var(event, 0, "%s@", event->action);
+ if (ret)
+ goto out_free_skb;
+
+ ret = button_hotplug_fill_event(event);
+ if (ret)
+ goto out_free_skb;
+
+ NETLINK_CB(event->skb).dst_group = 1;
+ broadcast_uevent(event->skb, 0, 1, GFP_KERNEL);
+
+ out_free_skb:
+ if (ret) {
+ BH_ERR("work error %d\n", ret);
+ kfree_skb(event->skb);
+ }
+ out_free_event:
+ kfree(event);
+}
+
+static int button_hotplug_create_event(const char *name, unsigned long seen,
+ int pressed)
+{
+ struct bh_event *event;
+
+ BH_DBG("create event, name=%s, seen=%lu, pressed=%d\n",
+ name, seen, pressed);
+
+ event = kzalloc(sizeof(*event), GFP_KERNEL);
+ if (!event)
+ return -ENOMEM;
+
+ event->name = name;
+ event->seen = seen;
+ event->action = pressed ? "pressed" : "released";
+
+ INIT_WORK(&event->work, (void *)(void *)button_hotplug_work);
+ schedule_work(&event->work);
+
+ return 0;
+}
+
+/* -------------------------------------------------------------------------*/
+
+#ifdef CONFIG_HOTPLUG
+static int button_get_index(unsigned int code)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(button_map); i++)
+ if (button_map[i].code == code)
+ return i;
+
+ return -1;
+}
+static void button_hotplug_event(struct gpio_keys_button_data *data,
+ unsigned int type, unsigned int code, int value)
+{
+ struct bh_priv *priv = &data->bh;
+ unsigned long seen = jiffies;
+ int btn;
+
+ BH_DBG("event type=%u, code=%u, value=%d\n", type, code, value);
+
+ if (type != EV_KEY)
+ return;
+
+ btn = button_get_index(code);
+ if (btn < 0)
+ return;
+
+ button_hotplug_create_event(button_map[btn].name,
+ (seen - priv->seen) / HZ, value);
+ priv->seen = seen;
+}
+#else
+static void button_hotplug_event(struct gpio_keys_button_data *data,
+ unsigned int type, unsigned int code, int value)
+{
+}
+#endif /* CONFIG_HOTPLUG */
+
+struct gpio_keys_polled_dev {
+ struct delayed_work work;
+
+ struct device *dev;
+ struct gpio_keys_platform_data *pdata;
+ struct gpio_keys_button_data data[0];
+};
+
+static void gpio_keys_polled_check_state(struct gpio_keys_button *button,
+ struct gpio_keys_button_data *bdata)
+{
+ int state;
+
+ if (bdata->can_sleep)
+ state = !!gpio_get_value_cansleep(button->gpio);
+ else
+ state = !!gpio_get_value(button->gpio);
+
+ state = !!(state ^ button->active_low);
+ if (state != bdata->last_state) {
+ unsigned int type = button->type ?: EV_KEY;
+
+ button_hotplug_event(bdata, type, button->code, state);
+ bdata->count = 0;
+ bdata->last_state = state;
+ }
+}
+
+static void gpio_keys_polled_queue_work(struct gpio_keys_polled_dev *bdev)
+{
+ struct gpio_keys_platform_data *pdata = bdev->pdata;
+ unsigned long delay = msecs_to_jiffies(pdata->poll_interval);
+
+ if (delay >= HZ)
+ delay = round_jiffies_relative(delay);
+ schedule_delayed_work(&bdev->work, delay);
+}
+
+static void gpio_keys_polled_poll(struct work_struct *work)
+{
+ struct gpio_keys_polled_dev *bdev =
+ container_of(work, struct gpio_keys_polled_dev, work.work);
+ struct gpio_keys_platform_data *pdata = bdev->pdata;
+ int i;
+
+ for (i = 0; i < bdev->pdata->nbuttons; i++) {
+ struct gpio_keys_button_data *bdata = &bdev->data[i];
+
+ if (bdata->count < bdata->threshold)
+ bdata->count++;
+ else
+ gpio_keys_polled_check_state(&pdata->buttons[i], bdata);
+ }
+ gpio_keys_polled_queue_work(bdev);
+}
+
+static void __devinit gpio_keys_polled_open(struct gpio_keys_polled_dev *bdev)
+{
+ struct gpio_keys_platform_data *pdata = bdev->pdata;
+ int i;
+
+ if (pdata->enable)
+ pdata->enable(bdev->dev);
+
+ /* report initial state of the buttons */
+ for (i = 0; i < pdata->nbuttons; i++)
+ gpio_keys_polled_check_state(&pdata->buttons[i], &bdev->data[i]);
+
+ gpio_keys_polled_queue_work(bdev);
+}
+
+static void __devexit gpio_keys_polled_close(struct gpio_keys_polled_dev *bdev)
+{
+ struct gpio_keys_platform_data *pdata = bdev->pdata;
+
+ cancel_delayed_work_sync(&bdev->work);
+
+ if (pdata->disable)
+ pdata->disable(bdev->dev);
+}
+
+static int __devinit gpio_keys_polled_probe(struct platform_device *pdev)
+{
+ struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+ struct device *dev = &pdev->dev;
+ struct gpio_keys_polled_dev *bdev;
+ int error;
+ int i;
+
+ if (!pdata || !pdata->poll_interval)
+ return -EINVAL;
+
+ bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) +
+ pdata->nbuttons * sizeof(struct gpio_keys_button_data),
+ GFP_KERNEL);
+ if (!bdev) {
+ dev_err(dev, "no memory for private data\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < pdata->nbuttons; i++) {
+ struct gpio_keys_button *button = &pdata->buttons[i];
+ struct gpio_keys_button_data *bdata = &bdev->data[i];
+ unsigned int gpio = button->gpio;
+
+ if (button->wakeup) {
+ dev_err(dev, DRV_NAME " does not support wakeup\n");
+ error = -EINVAL;
+ goto err_free_gpio;
+ }
+
+ error = gpio_request(gpio,
+ button->desc ? button->desc : DRV_NAME);
+ if (error) {
+ dev_err(dev, "unable to claim gpio %u, err=%d\n",
+ gpio, error);
+ goto err_free_gpio;
+ }
+
+ error = gpio_direction_input(gpio);
+ if (error) {
+ dev_err(dev,
+ "unable to set direction on gpio %u, err=%d\n",
+ gpio, error);
+ goto err_free_gpio;
+ }
+
+ bdata->can_sleep = gpio_cansleep(gpio);
+ bdata->last_state = 0;
+ bdata->threshold = DIV_ROUND_UP(button->debounce_interval,
+ pdata->poll_interval);
+ }
+
+ bdev->dev = &pdev->dev;
+ bdev->pdata = pdata;
+ platform_set_drvdata(pdev, bdev);
+
+ INIT_DELAYED_WORK(&bdev->work, gpio_keys_polled_poll);
+
+ gpio_keys_polled_open(bdev);
+
+ return 0;
+
+err_free_gpio:
+ while (--i >= 0)
+ gpio_free(pdata->buttons[i].gpio);
+
+ kfree(bdev);
+ platform_set_drvdata(pdev, NULL);
+
+ return error;
+}
+
+static int __devexit gpio_keys_polled_remove(struct platform_device *pdev)
+{
+ struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev);
+ struct gpio_keys_platform_data *pdata = bdev->pdata;
+ int i = pdata->nbuttons;
+
+ gpio_keys_polled_close(bdev);
+
+ while (--i >= 0)
+ gpio_free(pdata->buttons[i].gpio);
+
+ kfree(bdev);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver gpio_keys_polled_driver = {
+ .probe = gpio_keys_polled_probe,
+ .remove = __devexit_p(gpio_keys_polled_remove),
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init gpio_keys_polled_init(void)
+{
+ return platform_driver_register(&gpio_keys_polled_driver);
+}
+
+static void __exit gpio_keys_polled_exit(void)
+{
+ platform_driver_unregister(&gpio_keys_polled_driver);
+}
+
+module_init(gpio_keys_polled_init);
+module_exit(gpio_keys_polled_exit);
+
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>");
+MODULE_DESCRIPTION("Polled GPIO Buttons hotplug driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/package/gpioctl/Makefile b/package/gpioctl/Makefile
new file mode 100644
index 000000000..50c4d3c65
--- /dev/null
+++ b/package/gpioctl/Makefile
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2008 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=gpioctl
+PKG_RELEASE:=1
+PKG_VERSION:=1.0
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/gpioctl
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Tool for controlling gpio pins
+ DEPENDS:=@GPIO_SUPPORT
+endef
+
+define Package/gpioctl/description
+ Tool for controlling gpio pins
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) CFLAGS="$(TARGET_CFLAGS) -I$(LINUX_DIR)/include"
+endef
+
+define Package/gpioctl/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/gpioctl $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,gpioctl))
diff --git a/package/gpioctl/src/Makefile b/package/gpioctl/src/Makefile
new file mode 100644
index 000000000..467697410
--- /dev/null
+++ b/package/gpioctl/src/Makefile
@@ -0,0 +1,24 @@
+PROGS = gpioctl
+
+INSTDIR = $(prefix)/usr/bin
+INSTMODE = 0755
+INSTOWNER = root
+INSTGROUP = root
+
+OBJS = main.o
+
+all: $(PROGS)
+$(PROGS): $(OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+ $(STRIP) $@
+
+%.o: %.c
+ $(CC) -c $(CFLAGS) $^ -o $@
+
+install: $(PROGS)
+ $(INSTALL) -d $(INSTDIR)
+ $(INSTALL) -m $(INSTMODE) -o $(INSTOWNER) -g $(INSTGROUP) $(PROGS) $(INSTDIR)
+
+clean:
+ rm -f $(PROGS) *.o core
+
diff --git a/package/gpioctl/src/main.c b/package/gpioctl/src/main.c
new file mode 100644
index 000000000..8ad27749b
--- /dev/null
+++ b/package/gpioctl/src/main.c
@@ -0,0 +1,76 @@
+/*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* 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, MA02111-1307USA
+*
+* Feedback, Bugs... blogic@openwrt.org
+*
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <linux/gpio_dev.h>
+#include <linux/ioctl.h>
+
+void
+print_usage()
+{
+ printf("gpioctl dirin|dirout|get|set|clear gpio\n");
+ exit(0);
+}
+
+int
+main(int argc, char **argv)
+{
+ int gpio_pin;
+ int fd;
+ int result = 0;
+
+ if (argc != 3)
+ {
+ print_usage();
+ }
+
+ if ((fd = open("/dev/gpio", O_RDWR)) < 0)
+ {
+ printf("Error whilst opening /dev/gpio\n");
+ return -1;
+ }
+
+ gpio_pin = atoi(argv[2]);
+
+ printf("using gpio pin %d\n", gpio_pin);
+
+ if (!strcmp(argv[1], "dirin"))
+ {
+ ioctl(fd, GPIO_DIR_IN, gpio_pin);
+ } else if (!strcmp(argv[1], "dirout"))
+ {
+ ioctl(fd, GPIO_DIR_OUT, gpio_pin);
+ } else if (!strcmp(argv[1], "get"))
+ {
+ result = ioctl(fd, GPIO_GET, gpio_pin);
+ printf("Pin %d is %s\n", gpio_pin, (result ? "HIGH" : "LOW"));
+ } else if (!strcmp(argv[1], "set"))
+ {
+ ioctl(fd, GPIO_SET, gpio_pin);
+ } else if (!strcmp(argv[1], "clear"))
+ {
+ ioctl(fd, GPIO_CLEAR, gpio_pin);
+ } else print_usage();
+
+ return result;
+}
diff --git a/package/grub/Makefile b/package/grub/Makefile
new file mode 100644
index 000000000..80b79f29e
--- /dev/null
+++ b/package/grub/Makefile
@@ -0,0 +1,111 @@
+#
+# Copyright (C) 2006-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=grub
+PKG_VERSION:=0.97
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=ftp://alpha.gnu.org/gnu/grub
+PKG_MD5SUM:=cd3f3eb54446be6003156158d51f4884
+
+PKG_BUILD_DEPENDS:= grub/host
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+include $(INCLUDE_DIR)/package.mk
+
+define Package/grub
+ SUBMENU:=Boot Loaders
+ CATEGORY:=Utilities
+ SECTION:=utils
+ TITLE:=GRand Unified Bootloader
+ URL:=http://www.gnu.org/software/grub/
+ DEPENDS:=@TARGET_x86
+endef
+
+
+MY_CONFIGURE_ARGS += \
+ --disable-auto-linux-mem-opt \
+ --disable-hercules \
+ --without-curses \
+
+MY_CONFIGURE_VARS += \
+ grub_cv_prog_objcopy_absolute=yes \
+
+CONFIGURE_ARGS += $(MY_CONFIGURE_ARGS)
+
+CONFIGURE_VARS += $(MY_CONFIGURE_VARS)
+
+ifeq ($(HOST_OS),Darwin)
+ HOST_CFLAGS += $(call host-cc-option,-m32)
+ HOST_CFLAGS += $(call host-cc-option,-fnested-functions)
+endif
+
+ifeq ($(HOST_OS),FreeBSD)
+ ifeq ($(HOST_ARCH),amd64)
+ HOST_CFLAGS += $(call host-cc-option,-m32)
+ HOST_CFLAGS += $(call host-cc-option,-B/usr/lib32)
+ HOST_CFLAGS += $(call host-cc-option,-L/usr/lib32)
+ endif
+endif
+
+HOST_CFLAGS += $(call host-cc-option,-fno-stack-protector)
+HOST_CFLAGS += $(call host-cc-option,-U_FORTIFY_SOURCE)
+
+HOST_CONFIGURE_ARGS += $(MY_CONFIGURE_ARGS) \
+ --sbindir="$(STAGING_DIR_HOST)/bin" \
+ --disable-graphics \
+
+HOST_CONFIGURE_VARS += $(MY_CONFIGURE_VARS)
+
+define Host/Configure
+ (cd $(HOST_BUILD_DIR); aclocal && autoconf && automake)
+ $(call Host/Configure/Default)
+endef
+
+ifeq ($(HOST_OS),Darwin)
+ define Host/Compile
+ $(MAKE) -C $(HOST_BUILD_DIR)/lib
+ $(MAKE) -C $(HOST_BUILD_DIR)/stage2 libgrub.a
+ $(MAKE) -C $(HOST_BUILD_DIR)/grub
+ endef
+ define Host/Install
+ $(MAKE) -C $(HOST_BUILD_DIR)/grub install
+ endef
+endif
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/grub $(1)/usr/lib/
+endef
+
+define Package/grub/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/* $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(CP) $(PKG_INSTALL_DIR)/usr/sbin/* $(1)/usr/sbin/
+endef
+
+ifeq ($(HOST_ARCH),x86_64)
+ define Require/working-gcc-m32
+ echo 'int main(int argc, char **argv) { return 0; }' | \
+ gcc -x c -o $(TMP_DIR)/a.out - -m32 -lc
+ endef
+endif
+
+$(eval $(call Require,working-gcc-m32, \
+ Please install 32 bit development files. (gcc-multilib on Debian/Ubuntu, gcc.i686, libgcc.i686, and glibc-devel.i686 on CentOS/Fedora/RHEL) \
+))
+
+$(eval $(call HostBuild))
+$(eval $(call BuildPackage,grub))
diff --git a/package/grub/patches/002-strip_note_gnu_build_id.patch b/package/grub/patches/002-strip_note_gnu_build_id.patch
new file mode 100644
index 000000000..40aa74dc7
--- /dev/null
+++ b/package/grub/patches/002-strip_note_gnu_build_id.patch
@@ -0,0 +1,22 @@
+--- a/stage1/Makefile.in
++++ b/stage1/Makefile.in
+@@ -427,7 +427,7 @@ uninstall-am: uninstall-info-am uninstal
+ uninstall-nodist_pkglibDATA
+
+ .exec:
+- $(OBJCOPY) -O binary $< $@
++ $(OBJCOPY) -O binary -R .comment -R .note -R .note.gnu.build-id $< $@
+ # Tell versions [3.59,3.63) of GNU make to not export all variables.
+ # Otherwise a system limit (for SysV at least) may be exceeded.
+ .NOEXPORT:
+--- a/stage2/Makefile.in
++++ b/stage2/Makefile.in
+@@ -3244,7 +3244,7 @@ pxegrub: pxeloader diskless
+ -rm -f $@
+ cat $^ > $@
+ .exec:
+- $(OBJCOPY) -O binary $< $@
++ $(OBJCOPY) -O binary -R .comment -R .note -R .note.gnu.build-id $< $@
+ # Tell versions [3.59,3.63) of GNU make to not export all variables.
+ # Otherwise a system limit (for SysV at least) may be exceeded.
+ .NOEXPORT:
diff --git a/package/grub/patches/010-fixes-1.patch b/package/grub/patches/010-fixes-1.patch
new file mode 100644
index 000000000..91a9e2190
--- /dev/null
+++ b/package/grub/patches/010-fixes-1.patch
@@ -0,0 +1,4466 @@
+Submitted By: Jim Gifford (jim at linuxfromscratch dot org)
+Date: 2006-07-04
+Initial Package Version: 0.97
+Origin: Debian
+Upstream Status: Unknown
+Description: Contains various fixes and enhancements
+ Graphics mode support
+ Fixes for Raid Support
+ XFS Filesystem Boot Freeze Fixes
+ Removed 2GB Memory Limitation
+ Freebsd support
+ Fixes for initrd support
+ Grub installation Fixes
+ Linux 2.6 geometry Fixes
+ Intel Mac Support
+ Autoconf and aclocal updates
+
+http://trac.cross-lfs.org/browser/trunk/patches/grub-0.97-fixes-1.patch
+
+--- a/aclocal.m4
++++ b/aclocal.m4
+@@ -1,7 +1,7 @@
+-# generated automatically by aclocal 1.9.4 -*- Autoconf -*-
++# generated automatically by aclocal 1.9.6 -*- Autoconf -*-
+
+-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+-# Free Software Foundation, Inc.
++# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
++# 2005 Free Software Foundation, Inc.
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+ # with or without modifications, as long as this notice is preserved.
+@@ -11,23 +11,11 @@
+ # even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ # PARTICULAR PURPOSE.
+
+-# -*- Autoconf -*-
+-# Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+-# Generated from amversion.in; do not edit by hand.
+-
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2, or (at your option)
+-# any later version.
+-
+-# 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
++# Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
+
+ # AM_AUTOMAKE_VERSION(VERSION)
+ # ----------------------------
+@@ -40,26 +28,15 @@ AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api
+ # Call AM_AUTOMAKE_VERSION so it can be traced.
+ # This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
+ AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+- [AM_AUTOMAKE_VERSION([1.9.4])])
+-
+-# AM_AUX_DIR_EXPAND
+-
+-# Copyright (C) 2001, 2003 Free Software Foundation, Inc.
++ [AM_AUTOMAKE_VERSION([1.9.6])])
+
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2, or (at your option)
+-# any later version.
++# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+-# 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.
++# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
+
+ # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+ # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
+@@ -106,26 +83,16 @@ AC_PREREQ([2.50])dnl
+ am_aux_dir=`cd $ac_aux_dir && pwd`
+ ])
+
+-# AM_CONDITIONAL -*- Autoconf -*-
++# AM_CONDITIONAL -*- Autoconf -*-
+
+-# Copyright (C) 1997, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
+-
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2, or (at your option)
+-# any later version.
+-
+-# 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.
++# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005
++# Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
+
+-# serial 6
++# serial 7
+
+ # AM_CONDITIONAL(NAME, SHELL-CONDITION)
+ # -------------------------------------
+@@ -149,26 +116,15 @@ AC_CONFIG_COMMANDS_PRE(
+ Usually this means the macro was only invoked conditionally.]])
+ fi])])
+
+-# serial 7 -*- Autoconf -*-
+
+-# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
++# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ # Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
+
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2, or (at your option)
+-# any later version.
+-
+-# 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.
+-
++# serial 8
+
+ # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+ # written in clear, in which case automake, when reading aclocal.m4,
+@@ -177,7 +133,6 @@ fi])])
+ # CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+-
+ # _AM_DEPENDENCIES(NAME)
+ # ----------------------
+ # See how the compiler implements dependency checking.
+@@ -317,27 +272,16 @@ AM_CONDITIONAL([AMDEP], [test "x$enable_
+ AC_SUBST([AMDEPBACKSLASH])
+ ])
+
+-# Generate code to set up dependency tracking. -*- Autoconf -*-
+-
+-# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+-# Free Software Foundation, Inc.
+-
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2, or (at your option)
+-# any later version.
++# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+-# 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.
++# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
++# Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
+
+-#serial 2
++#serial 3
+
+ # _AM_OUTPUT_DEPENDENCY_COMMANDS
+ # ------------------------------
+@@ -396,30 +340,19 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS]
+ [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+ ])
+
+-# Do all the work for Automake. -*- Autoconf -*-
++# Do all the work for Automake. -*- Autoconf -*-
+
+-# This macro actually does too much some checks are only needed if
+-# your package does certain things. But this isn't really a big deal.
+-
+-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
++# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ # Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
+
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2, or (at your option)
+-# any later version.
+-
+-# 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.
++# serial 12
+
+-# serial 11
++# This macro actually does too much. Some checks are only needed if
++# your package does certain things. But this isn't really a big deal.
+
+ # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+ # AM_INIT_AUTOMAKE([OPTIONS])
+@@ -521,51 +454,27 @@ for _am_header in $config_headers :; do
+ done
+ echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count])
+
++# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
+ # AM_PROG_INSTALL_SH
+ # ------------------
+ # Define $install_sh.
+-
+-# Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+-
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2, or (at your option)
+-# any later version.
+-
+-# 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.
+-
+ AC_DEFUN([AM_PROG_INSTALL_SH],
+ [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+ install_sh=${install_sh-"$am_aux_dir/install-sh"}
+ AC_SUBST(install_sh)])
+
+-# -*- Autoconf -*-
+-# Copyright (C) 2003 Free Software Foundation, Inc.
+-
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2, or (at your option)
+-# any later version.
+-
+-# 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.
++# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
+
+-# serial 1
++# serial 2
+
+ # Check whether the underlying file-system supports filenames
+ # with a leading dot. For instance MS-DOS doesn't.
+@@ -580,28 +489,17 @@ fi
+ rmdir .tst 2>/dev/null
+ AC_SUBST([am__leading_dot])])
+
+-# Add --enable-maintainer-mode option to configure.
++# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
+ # From Jim Meyering
+
+-# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004
++# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005
+ # Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
+
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2, or (at your option)
+-# any later version.
+-
+-# 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.
+-
+-# serial 3
++# serial 4
+
+ AC_DEFUN([AM_MAINTAINER_MODE],
+ [AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+@@ -620,26 +518,15 @@ AC_DEFUN([AM_MAINTAINER_MODE],
+
+ AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
+
+-# Check to see how 'make' treats includes. -*- Autoconf -*-
+-
+-# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
++# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2, or (at your option)
+-# any later version.
+-
+-# 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.
++# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
+
+-# serial 2
++# serial 3
+
+ # AM_MAKE_INCLUDE()
+ # -----------------
+@@ -683,27 +570,16 @@ AC_MSG_RESULT([$_am_result])
+ rm -f confinc confmf
+ ])
+
+-# -*- Autoconf -*-
+-
+-
+-# Copyright (C) 1997, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+-
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2, or (at your option)
+-# any later version.
++# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+-# 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.
++# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005
++# Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
+
+-# serial 3
++# serial 4
+
+ # AM_MISSING_PROG(NAME, PROGRAM)
+ # ------------------------------
+@@ -729,27 +605,16 @@ else
+ fi
+ ])
+
++# Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
+ # AM_PROG_MKDIR_P
+ # ---------------
+ # Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise.
+-
+-# Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+-
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2, or (at your option)
+-# any later version.
+-
+-# 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.
+-
++#
+ # Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories
+ # created by `make install' are always world readable, even if the
+ # installer happens to have an overly restrictive umask (e.g. 077).
+@@ -803,26 +668,15 @@ else
+ fi
+ AC_SUBST([mkdir_p])])
+
+-# Helper functions for option handling. -*- Autoconf -*-
++# Helper functions for option handling. -*- Autoconf -*-
+
+-# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+-
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2, or (at your option)
+-# any later version.
+-
+-# 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.
++# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
+
+-# serial 2
++# serial 3
+
+ # _AM_MANGLE_OPTION(NAME)
+ # -----------------------
+@@ -847,28 +701,16 @@ AC_DEFUN([_AM_SET_OPTIONS],
+ AC_DEFUN([_AM_IF_OPTION],
+ [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+-#
+-# Check to make sure that the build environment is sane.
+-#
+-
+-# Copyright (C) 1996, 1997, 2000, 2001, 2003 Free Software Foundation, Inc.
+-
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2, or (at your option)
+-# any later version.
++# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+-# 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.
++# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
++# Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
+
+-# serial 3
++# serial 4
+
+ # AM_SANITY_CHECK
+ # ---------------
+@@ -911,25 +753,14 @@ Check your system clock])
+ fi
+ AC_MSG_RESULT(yes)])
+
+-# AM_PROG_INSTALL_STRIP
+-
+-# Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+-
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2, or (at your option)
+-# any later version.
+-
+-# 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.
++# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
+
++# AM_PROG_INSTALL_STRIP
++# ---------------------
+ # One issue with vendor `install' (even GNU) is that you can't
+ # specify the program used to strip binaries. This is especially
+ # annoying in cross-compiling environments, where the build's strip
+@@ -952,25 +783,13 @@ AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+ # Check how to create a tarball. -*- Autoconf -*-
+
+-# Copyright (C) 2004 Free Software Foundation, Inc.
+-
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2, or (at your option)
+-# any later version.
+-
+-# 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.
+-
+-# serial 1
++# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
+
++# serial 2
+
+ # _AM_PROG_TAR(FORMAT)
+ # --------------------
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,51 @@
++2006-05-02 Pavel Roskin <proski@gnu.org>
++
++ * stage2/stage2.c (run_menu): Fix "savedefault" to save only top
++ level menu positions. Remember current position when calling a
++ submenu. Don't recalculate it when booting from a submenu.
++
++ * grub/main.c (main): Make sure the boot drive number doesn't
++ exceed 255.
++
++2006-05-02 Vesa Jaaskelainen <chaac@nic.fi>
++
++ * stage2/shared.h (vbe_mode): Back ported aligment fix from GRUB 2
++ to GRUB Legacy. Problem reported by Gerardo Richarte.
++
++2006-04-23 Robert Millan <robertmh@gnu.org>
++
++ * grub/asmstub.c (get_diskinfo): Optimize sysctl routine.
++
++2006-04-20 Robert Millan <robertmh@gnu.org>
++
++ Fixes for kernel of FreeBSD:
++ * grub/asmstub.c (get_diskinfo): Toggle "kern.geom.debugflags" sysctl
++ before opening a device for writing.
++ * util/grub-install.in: Devices don't have this "r" prefix anymore.
++
++2006-04-16 Yoshinori K. Okuji <okuji@enbug.org>
++
++ * docs/multiboot.texi: Correct the offset of address
++ fields. Reported by Jeroen Dekkers.
++
++2006-03-21 Yoshinori K. Okuji <okuji@enbug.org>
++
++ * stage2/builtins.c (setup_func): Specify the size of DEVICE to
++ grub_strncat instead of a strange number 256. Reported by Vitaly
++ Fertman <vitaly@namesys.com>.
++
++2005-09-29 Yoshinori K. Okuji <okuji@enbug.org>
++
++ * docs/multiboot.texi: Fix a bug in the byte order of
++ boot_device. I hope this won't affect any OS image.
++ Increased the version number to 0.6.94.
++
++2005-09-28 Yoshinori K. Okuji <okuji@enbug.org>
++
++ * stage2/boot.c (load_image): Even if an OS image is an ELF
++ object, use the a.out kludge if MULTIBOOT_AOUT_KLUDGE is
++ specified.
++
+ 2005-05-08 Yoshinori K. Okuji <okuji@enbug.org>
+
+ * configure.ac (AC_INIT): Upgraded to 0.97.
+--- a/configure
++++ b/configure
+@@ -311,7 +311,7 @@ ac_includes_default="\
+ # include <unistd.h>
+ #endif"
+
+-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar build build_cpu build_vendor build_os host host_cpu host_vendor host_os MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT PERL CC ac_ct_CC CFLAGS LDFLAGS CPPFLAGS EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CCAS RANLIB ac_ct_RANLIB STAGE1_CFLAGS STAGE2_CFLAGS GRUB_CFLAGS OBJCOPY ac_ct_OBJCOPY GRUB_LIBS CPP EGREP NETBOOT_SUPPORT_TRUE NETBOOT_SUPPORT_FALSE DISKLESS_SUPPORT_TRUE DISKLESS_SUPPORT_FALSE HERCULES_SUPPORT_TRUE HERCULES_SUPPORT_FALSE SERIAL_SUPPORT_TRUE SERIAL_SUPPORT_FALSE SERIAL_SPEED_SIMULATION_TRUE SERIAL_SPEED_SIMULATION_FALSE BUILD_EXAMPLE_KERNEL_TRUE BUILD_EXAMPLE_KERNEL_FALSE FSYS_CFLAGS NET_CFLAGS NET_EXTRAFLAGS NETBOOT_DRIVERS CCASFLAGS LIBOBJS LTLIBOBJS'
++ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar build build_cpu build_vendor build_os host host_cpu host_vendor host_os MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT PERL CC ac_ct_CC CFLAGS LDFLAGS CPPFLAGS EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CCAS RANLIB ac_ct_RANLIB STAGE1_CFLAGS STAGE2_CFLAGS GRUB_CFLAGS OBJCOPY ac_ct_OBJCOPY GRUB_LIBS CPP EGREP NETBOOT_SUPPORT_TRUE NETBOOT_SUPPORT_FALSE DISKLESS_SUPPORT_TRUE DISKLESS_SUPPORT_FALSE GRAPHICS_SUPPORT_TRUE GRAPHICS_SUPPORT_FALSE HERCULES_SUPPORT_TRUE HERCULES_SUPPORT_FALSE SERIAL_SUPPORT_TRUE SERIAL_SUPPORT_FALSE SERIAL_SPEED_SIMULATION_TRUE SERIAL_SPEED_SIMULATION_FALSE BUILD_EXAMPLE_KERNEL_TRUE BUILD_EXAMPLE_KERNEL_FALSE FSYS_CFLAGS NET_CFLAGS NET_EXTRAFLAGS NETBOOT_DRIVERS CCASFLAGS LIBOBJS LTLIBOBJS'
+ ac_subst_files=''
+
+ # Initialize some variables set by options.
+@@ -914,6 +914,7 @@ Optional Features:
+ set the default memory location for WD/SMC
+ --enable-cs-scan=LIST probe for CS89x0 base address using LIST
+ --enable-diskless enable diskless support
++ --disable-graphics disable graphics terminal support
+ --disable-hercules disable hercules terminal support
+ --disable-serial disable serial terminal support
+ --enable-serial-speed-simulation
+@@ -5966,6 +5967,22 @@ else
+ fi
+
+
++# Check whether --enable-graphics or --disable-graphics was given.
++if test "${enable_graphics+set}" = set; then
++ enableval="$enable_graphics"
++
++fi;
++
++
++if test "x$enable_graphics" != xno; then
++ GRAPHICS_SUPPORT_TRUE=
++ GRAPHICS_SUPPORT_FALSE='#'
++else
++ GRAPHICS_SUPPORT_TRUE='#'
++ GRAPHICS_SUPPORT_FALSE=
++fi
++
++
+ # Check whether --enable-hercules or --disable-hercules was given.
+ if test "${enable_hercules+set}" = set; then
+ enableval="$enable_hercules"
+@@ -6270,6 +6287,13 @@ echo "$as_me: error: conditional \"DISKL
+ Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
++if test -z "${GRAPHICS_SUPPORT_TRUE}" && test -z "${GRAPHICS_SUPPORT_FALSE}"; then
++ { { echo "$as_me:$LINENO: error: conditional \"GRAPHICS_SUPPORT\" was never defined.
++Usually this means the macro was only invoked conditionally." >&5
++echo "$as_me: error: conditional \"GRAPHICS_SUPPORT\" was never defined.
++Usually this means the macro was only invoked conditionally." >&2;}
++ { (exit 1); exit 1; }; }
++fi
+ if test -z "${HERCULES_SUPPORT_TRUE}" && test -z "${HERCULES_SUPPORT_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"HERCULES_SUPPORT\" was never defined.
+ Usually this means the macro was only invoked conditionally." >&5
+@@ -6907,6 +6931,8 @@ s,@NETBOOT_SUPPORT_TRUE@,$NETBOOT_SUPPOR
+ s,@NETBOOT_SUPPORT_FALSE@,$NETBOOT_SUPPORT_FALSE,;t t
+ s,@DISKLESS_SUPPORT_TRUE@,$DISKLESS_SUPPORT_TRUE,;t t
+ s,@DISKLESS_SUPPORT_FALSE@,$DISKLESS_SUPPORT_FALSE,;t t
++s,@GRAPHICS_SUPPORT_TRUE@,$GRAPHICS_SUPPORT_TRUE,;t t
++s,@GRAPHICS_SUPPORT_FALSE@,$GRAPHICS_SUPPORT_FALSE,;t t
+ s,@HERCULES_SUPPORT_TRUE@,$HERCULES_SUPPORT_TRUE,;t t
+ s,@HERCULES_SUPPORT_FALSE@,$HERCULES_SUPPORT_FALSE,;t t
+ s,@SERIAL_SUPPORT_TRUE@,$SERIAL_SUPPORT_TRUE,;t t
+--- a/configure.ac
++++ b/configure.ac
+@@ -595,6 +595,11 @@ AC_ARG_ENABLE(diskless,
+ [ --enable-diskless enable diskless support])
+ AM_CONDITIONAL(DISKLESS_SUPPORT, test "x$enable_diskless" = xyes)
+
++dnl Graphical splashscreen support
++AC_ARG_ENABLE(graphics,
++ [ --disable-graphics disable graphics terminal support])
++AM_CONDITIONAL(GRAPHICS_SUPPORT, test "x$enable_graphics" != xno)
++
+ dnl Hercules terminal
+ AC_ARG_ENABLE(hercules,
+ [ --disable-hercules disable hercules terminal support])
+--- a/docs/grub.8
++++ b/docs/grub.8
+@@ -1,5 +1,5 @@
+ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.23.
+-.TH GRUB "8" "May 2005" "grub (GNU GRUB 0.97)" FSF
++.TH GRUB "8" "September 2005" "grub (GNU GRUB 0.97)" FSF
+ .SH NAME
+ grub \- the grub shell
+ .SH SYNOPSIS
+--- a/docs/grub.texi
++++ b/docs/grub.texi
+@@ -2199,6 +2199,7 @@ Commands usable anywhere in the menu and
+ * rarp:: Initialize a network device via RARP
+ * serial:: Set up a serial device
+ * setkey:: Configure the key map
++* splashimage:: Use a splash image
+ * terminal:: Choose a terminal
+ * terminfo:: Define escape sequences for a terminal
+ * tftpserver:: Specify a TFTP server
+@@ -2578,6 +2579,16 @@ character each of the symbols correspond
+ @end deffn
+
+
++@node splashimage
++@subsection splashimage
++
++@deffn Command splashimage file
++Select an image to use as the background image. This should be
++specified using normal GRUB device naming syntax. The format of the
++file is a gzipped xpm which is 640x480 with a 14 color palette.
++@end deffn
++
++
+ @node terminal
+ @subsection terminal
+
+@@ -2685,6 +2696,7 @@ you forget a command, you can run the co
+ * module:: Load a module
+ * modulenounzip:: Load a module without decompression
+ * pause:: Wait for a key press
++* print:: Print a message
+ * quit:: Exit from the grub shell
+ * reboot:: Reboot your computer
+ * read:: Read data from memory
+@@ -3091,6 +3103,16 @@ change floppies.
+ @end deffn
+
+
++@node print
++@subsection print
++
++@deffn Command print message @dots{}
++Print the @var{message}. Note that placing @key{^G} (ASCII code 7) in the
++message will cause the speaker to emit the standard beep sound, which is
++useful for visually impaired people.
++@end deffn
++
++
+ @node quit
+ @subsection quit
+
+--- a/docs/multiboot.texi
++++ b/docs/multiboot.texi
+@@ -25,7 +25,7 @@
+ @ifinfo
+ Copyright @copyright{} 1995, 96 Bryan Ford <baford@@cs.utah.edu>
+ Copyright @copyright{} 1995, 96 Erich Stefan Boleyn <erich@@uruk.org>
+-Copyright @copyright{} 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
++Copyright @copyright{} 1999, 2000, 2001, 2002, 2005, 2006 Free Software Foundation, Inc.
+
+ Permission is granted to make and distribute verbatim copies of
+ this manual provided the copyright notice and this permission notice
+@@ -57,7 +57,7 @@ into another language, under the above c
+ @vskip 0pt plus 1filll
+ Copyright @copyright{} 1995, 96 Bryan Ford <baford@@cs.utah.edu>
+ Copyright @copyright{} 1995, 96 Erich Stefan Boleyn <erich@@uruk.org>
+-Copyright @copyright{} 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
++Copyright @copyright{} 1999, 2000, 2001, 2002, 2005, 2006 Free Software Foundation, Inc.
+
+ Permission is granted to make and distribute verbatim copies of
+ this manual provided the copyright notice and this permission notice
+@@ -80,7 +80,7 @@ into another language, under the above c
+ @top Multiboot Specification
+
+ This file documents Multiboot Specification, the proposal for the boot
+-sequence standard. This edition documents version 0.6.93.
++sequence standard. This edition documents version 0.6.94.
+ @end ifnottex
+
+ @menu
+@@ -426,7 +426,7 @@ mode table (@pxref{Boot information form
+ kernel.
+
+ If bit 16 in the @samp{flags} word is set, then the fields at offsets
+-8-24 in the Multiboot header are valid, and the boot loader should use
++12-28 in the Multiboot header are valid, and the boot loader should use
+ them instead of the fields in the actual executable header to calculate
+ where to load the OS image. This information does not need to be
+ provided if the kernel image is in @sc{elf} format, but it @emph{must}
+@@ -677,7 +677,7 @@ follows:
+ @example
+ @group
+ +-------+-------+-------+-------+
+-| drive | part1 | part2 | part3 |
++| part3 | part2 | part1 | drive |
+ +-------+-------+-------+-------+
+ @end group
+ @end example
+@@ -1199,6 +1199,13 @@ The maintainer changes to the GNU GRUB m
+ @email{bug-grub@@gnu.org}, from Bryan Ford and Erich Stefan Boleyn.
+ @end itemize
+
++@item
++The byte order of the @samp{boot_device} in Multiboot information is
++reversed. This was a mistake.
++
++@item
++The offset of the address fields were wrong.
++
+ @item 0.6
+ @itemize @bullet
+ @item
+--- a/grub/asmstub.c
++++ b/grub/asmstub.c
+@@ -42,6 +42,12 @@ int grub_stage2 (void);
+ #include <sys/time.h>
+ #include <termios.h>
+ #include <signal.h>
++#include <sys/mman.h>
++
++#include <limits.h>
++#ifndef PAGESIZE
++#define PAGESIZE 4096
++#endif
+
+ #ifdef __linux__
+ # include <sys/ioctl.h> /* ioctl */
+@@ -55,6 +61,10 @@ int grub_stage2 (void);
+ # endif /* ! BLKFLSBUF */
+ #endif /* __linux__ */
+
++#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
++# include <sys/sysctl.h>
++#endif
++
+ /* We want to prevent any circularararity in our stubs, as well as
+ libc name clashes. */
+ #define WITHOUT_LIBC_STUBS 1
+@@ -144,6 +154,22 @@ grub_stage2 (void)
+ assert (grub_scratch_mem == 0);
+ scratch = malloc (0x100000 + EXTENDED_MEMSIZE + 15);
+ assert (scratch);
++
++ {
++ char *p;
++ int ret;
++
++ /* Align to a multiple of PAGESIZE, assumed to be a power of two. */
++ p = (char *) (((long) scratch) & ~(PAGESIZE - 1));
++
++ /* The simulated stack needs to be executable, since GCC uses stack
++ * trampolines to implement nested functions.
++ */
++ ret = mprotect (p, 0x100000 + EXTENDED_MEMSIZE + 15,
++ PROT_READ | PROT_WRITE | PROT_EXEC);
++ assert (ret == 0);
++ }
++
+ grub_scratch_mem = (char *) ((((int) scratch) >> 4) << 4);
+
+ /* FIXME: simulate the memory holes using mprot, if available. */
+@@ -777,7 +803,39 @@ get_diskinfo (int drive, struct geometry
+
+ /* Open read/write, or read-only if that failed. */
+ if (! read_only)
+- disks[drive].flags = open (devname, O_RDWR);
++ {
++/* By default, kernel of FreeBSD does not allow overwriting MBR */
++#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
++#define GEOM_SYSCTL "kern.geom.debugflags"
++ int old_flags, flags;
++ size_t sizeof_int = sizeof (int);
++
++ if (sysctlbyname (GEOM_SYSCTL, &old_flags, &sizeof_int, NULL, 0) != 0)
++ grub_printf ("failed to get " GEOM_SYSCTL "sysctl: %s\n", strerror (errno));
++
++ if ((old_flags & 0x10) == 0)
++ {
++ /* "allow foot shooting", see geom(4) */
++ flags = old_flags | 0x10;
++
++ if (sysctlbyname (GEOM_SYSCTL, NULL, NULL, &flags, sizeof (int)) != 0)
++ {
++ flags = old_flags;
++ grub_printf ("failed to set " GEOM_SYSCTL "sysctl: %s\n", strerror (errno));
++ }
++ }
++ else
++ flags = old_flags;
++#endif
++ disks[drive].flags = open (devname, O_RDWR);
++#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
++ if (flags != old_flags)
++ {
++ if (sysctlbyname (GEOM_SYSCTL, NULL, NULL, &old_flags, sizeof (int)) != 0)
++ grub_printf ("failed to set " GEOM_SYSCTL "sysctl: %s\n", strerror (errno));
++ }
++#endif
++ }
+
+ if (disks[drive].flags == -1)
+ {
+--- a/grub/main.c
++++ b/grub/main.c
+@@ -32,6 +32,7 @@ int grub_stage2 (void);
+ #define WITHOUT_LIBC_STUBS 1
+ #include <shared.h>
+ #include <term.h>
++#include <device.h>
+
+ char *program_name = 0;
+ int use_config_file = 1;
+@@ -192,6 +193,12 @@ main (int argc, char **argv)
+ perror ("strtoul");
+ exit (1);
+ }
++ if (boot_drive >= NUM_DISKS)
++ {
++ fprintf (stderr, "boot_drive should be from 0 to %d\n",
++ NUM_DISKS - 1);
++ exit (1);
++ }
+ break;
+
+ case OPT_NO_CONFIG_FILE:
+--- a/lib/device.c
++++ b/lib/device.c
+@@ -131,6 +131,152 @@ get_kfreebsd_version ()
+ #include <shared.h>
+ #include <device.h>
+
++#if defined(__linux__)
++/* The 2.6 kernel has removed all of the geometry handling for IDE drives
++ * that did fixups for LBA, etc. This means that the geometry we get
++ * with the ioctl has a good chance of being wrong. So, we get to
++ * also know about partition tables and try to read what the geometry
++ * is there. *grumble* Very closely based on code from cfdisk
++ */
++static void get_kernel_geometry(int fd, long long *cyl, int *heads, int *sectors) {
++ struct hd_geometry hdg;
++
++ if (ioctl (fd, HDIO_GETGEO, &hdg))
++ return;
++
++ *cyl = hdg.cylinders;
++ *heads = hdg.heads;
++ *sectors = hdg.sectors;
++}
++
++struct partition {
++ unsigned char boot_ind; /* 0x80 - active */
++ unsigned char head; /* starting head */
++ unsigned char sector; /* starting sector */
++ unsigned char cyl; /* starting cylinder */
++ unsigned char sys_ind; /* What partition type */
++ unsigned char end_head; /* end head */
++ unsigned char end_sector; /* end sector */
++ unsigned char end_cyl; /* end cylinder */
++ unsigned char start4[4]; /* starting sector counting from 0 */
++ unsigned char size4[4]; /* nr of sectors in partition */
++};
++
++#define ALIGNMENT 2
++typedef union {
++ struct {
++ unsigned char align[ALIGNMENT];
++ unsigned char b[SECTOR_SIZE];
++ } c;
++ struct {
++ unsigned char align[ALIGNMENT];
++ unsigned char buffer[0x1BE];
++ struct partition part[4];
++ unsigned char magicflag[2];
++ } p;
++} partition_table;
++
++#define PART_TABLE_FLAG0 0x55
++#define PART_TABLE_FLAG1 0xAA
++
++static void
++get_partition_table_geometry(partition_table *bufp, long long *cyl, int *heads,
++ int *sectors) {
++ struct partition *p;
++ int i,h,s,hh,ss;
++ int first = 1;
++ int bad = 0;
++
++ if (bufp->p.magicflag[0] != PART_TABLE_FLAG0 ||
++ bufp->p.magicflag[1] != PART_TABLE_FLAG1) {
++ /* Matthew Wilcox: slightly friendlier version of
++ fatal(_("Bad signature on partition table"), 3);
++ */
++ fprintf(stderr, "Unknown partition table signature\n");
++ return;
++ }
++
++ hh = ss = 0;
++ for (i=0; i<4; i++) {
++ p = &(bufp->p.part[i]);
++ if (p->sys_ind != 0) {
++ h = p->end_head + 1;
++ s = (p->end_sector & 077);
++ if (first) {
++ hh = h;
++ ss = s;
++ first = 0;
++ } else if (hh != h || ss != s)
++ bad = 1;
++ }
++ }
++
++ if (!first && !bad) {
++ *heads = hh;
++ *sectors = ss;
++ }
++}
++
++static long long my_lseek (unsigned int fd, long long offset,
++ unsigned int origin)
++{
++#if defined(__linux__) && (!defined(__GLIBC__) || \
++ ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
++ /* Maybe libc doesn't have large file support. */
++ loff_t offset, result;
++ static int _llseek (uint filedes, ulong hi, ulong lo,
++ loff_t *res, uint wh);
++ _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
++ loff_t *, res, uint, wh);
++
++ if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET) < 0)
++ return (long long) -1;
++ return result;
++#else
++ return lseek(fd, offset, SEEK_SET);
++#endif
++}
++
++static void get_linux_geometry (int fd, struct geometry *geom) {
++ long long kern_cyl = 0; int kern_head = 0, kern_sectors = 0;
++ long long pt_cyl = 0; int pt_head = 0, pt_sectors = 0;
++ partition_table bufp;
++ char *buff, *buf_unaligned;
++
++ buf_unaligned = malloc(sizeof(partition_table) + 4095);
++ buff = (char *) (((unsigned long)buf_unaligned + 4096 - 1) &
++ (~(4096-1)));
++
++ get_kernel_geometry(fd, &kern_cyl, &kern_head, &kern_sectors);
++
++ if (my_lseek (fd, 0*SECTOR_SIZE, SEEK_SET) < 0) {
++ fprintf(stderr, "Unable to seek");
++ }
++
++ if (read(fd, buff, SECTOR_SIZE) == SECTOR_SIZE) {
++ memcpy(bufp.c.b, buff, SECTOR_SIZE);
++ get_partition_table_geometry(&bufp, &pt_cyl, &pt_head, &pt_sectors);
++ } else {
++ fprintf(stderr, "Unable to read partition table: %s\n", strerror(errno));
++ }
++
++ if (pt_head && pt_sectors) {
++ int cyl_size;
++
++ geom->heads = pt_head;
++ geom->sectors = pt_sectors;
++ cyl_size = pt_head * pt_sectors;
++ geom->cylinders = geom->total_sectors/cyl_size;
++ } else {
++ geom->heads = kern_head;
++ geom->sectors = kern_sectors;
++ geom->cylinders = kern_cyl;
++ }
++
++ return;
++}
++#endif
++
+ /* Get the geometry of a drive DRIVE. */
+ void
+ get_drive_geometry (struct geometry *geom, char **map, int drive)
+@@ -151,21 +297,16 @@ get_drive_geometry (struct geometry *geo
+ #if defined(__linux__)
+ /* Linux */
+ {
+- struct hd_geometry hdg;
+ unsigned long nr;
+-
+- if (ioctl (fd, HDIO_GETGEO, &hdg))
+- goto fail;
+
+ if (ioctl (fd, BLKGETSIZE, &nr))
+ goto fail;
+
+ /* Got the geometry, so save it. */
+- geom->cylinders = hdg.cylinders;
+- geom->heads = hdg.heads;
+- geom->sectors = hdg.sectors;
+ geom->total_sectors = nr;
+-
++ get_linux_geometry(fd, geom);
++ if (!geom->heads && !geom->cylinders && !geom->sectors)
++ goto fail;
+ goto success;
+ }
+
+@@ -403,6 +544,18 @@ get_dac960_disk_name (char *name, int co
+ }
+
+ static void
++get_cciss_disk_name (char *name, int controller, int drive)
++{
++ sprintf (name, "/dev/cciss/c%dd%d", controller, drive);
++}
++
++static void
++get_ida_disk_name (char *name, int controller, int drive)
++{
++ sprintf (name, "/dev/ida/c%dd%d", controller, drive);
++}
++
++static void
+ get_ataraid_disk_name (char *name, int unit)
+ {
+ sprintf (name, "/dev/ataraid/d%c", unit + '0');
+@@ -801,6 +954,74 @@ init_device_map (char ***map, const char
+ }
+ }
+ }
++
++ /* This is for CCISS, its like the DAC960 - we have
++ /dev/cciss/<controller>d<logical drive>p<partition>
++
++ It currently supports up to 3 controllers, 10 logical volumes
++ and 10 partitions
++
++ Code gratuitously copied from DAC960 above.
++ Horms <horms@verge.net.au> 23rd July 2004
++ */
++ {
++ int controller, drive;
++
++ for (controller = 0; controller < 2; controller++)
++ {
++ for (drive = 0; drive < 9; drive++)
++ {
++ char name[24];
++
++ get_cciss_disk_name (name, controller, drive);
++ if (check_device (name))
++ {
++ (*map)[num_hd + 0x80] = strdup (name);
++ assert ((*map)[num_hd + 0x80]);
++
++ /* If the device map file is opened, write the map. */
++ if (fp)
++ fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
++
++ num_hd++;
++ }
++ }
++ }
++ }
++
++ /* This is for Compaq Smart Array, its like the DAC960 - we have
++ /dev/ida/<controller>d<logical drive>p<partition>
++
++ It currently supports up to 3 controllers, 10 logical volumes
++ and 15 partitions
++
++ Code gratuitously copied from DAC960 above.
++ Piotr Roszatycki <dexter@debian.org>
++ */
++ {
++ int controller, drive;
++
++ for (controller = 0; controller < 2; controller++)
++ {
++ for (drive = 0; drive < 9; drive++)
++ {
++ char name[24];
++
++ get_ida_disk_name (name, controller, drive);
++ if (check_device (name))
++ {
++ (*map)[num_hd + 0x80] = strdup (name);
++ assert ((*map)[num_hd + 0x80]);
++
++ /* If the device map file is opened, write the map. */
++ if (fp)
++ fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
++
++ num_hd++;
++ }
++ }
++ }
++ }
+ #endif /* __linux__ */
+
+ /* OK, close the device map file if opened. */
+@@ -844,6 +1065,7 @@ write_to_partition (char **map, int driv
+ {
+ char dev[PATH_MAX]; /* XXX */
+ int fd;
++ off_t offset = (off_t) sector * (off_t) SECTOR_SIZE;
+
+ if ((partition & 0x00FF00) != 0x00FF00)
+ {
+@@ -861,8 +1083,14 @@ write_to_partition (char **map, int driv
+ if (strcmp (dev + strlen(dev) - 5, "/disc") == 0)
+ strcpy (dev + strlen(dev) - 5, "/part");
+ }
+- sprintf (dev + strlen(dev), "%d", ((partition >> 16) & 0xFF) + 1);
+-
++ sprintf (dev + strlen(dev), "%s%d",
++ /* Compaq smart and others */
++ (strncmp(dev, "/dev/ida/", 9) == 0 ||
++ strncmp(dev, "/dev/ataraid/", 13) == 0 ||
++ strncmp(dev, "/dev/cciss/", 11) == 0 ||
++ strncmp(dev, "/dev/rd/", 8) == 0) ? "p" : "",
++ ((partition >> 16) & 0xFF) + 1);
++
+ /* Open the partition. */
+ fd = open (dev, O_RDWR);
+ if (fd < 0)
+@@ -870,35 +1098,13 @@ write_to_partition (char **map, int driv
+ errnum = ERR_NO_PART;
+ return 0;
+ }
+-
+-#if defined(__linux__) && (!defined(__GLIBC__) || \
+- ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
+- /* Maybe libc doesn't have large file support. */
+- {
+- loff_t offset, result;
+- static int _llseek (uint filedes, ulong hi, ulong lo,
+- loff_t *res, uint wh);
+- _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
+- loff_t *, res, uint, wh);
+
+- offset = (loff_t) sector * (loff_t) SECTOR_SIZE;
+- if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
+- {
+- errnum = ERR_DEV_VALUES;
+- return 0;
+- }
+- }
+-#else
+- {
+- off_t offset = (off_t) sector * (off_t) SECTOR_SIZE;
+
+- if (lseek (fd, offset, SEEK_SET) != offset)
+- {
+- errnum = ERR_DEV_VALUES;
+- return 0;
+- }
+- }
+-#endif
++ if (my_lseek(fd, offset, SEEK_SET) != offset)
++ {
++ errnum = ERR_DEV_VALUES;
++ return 0;
++ }
+
+ if (write (fd, buf, size * SECTOR_SIZE) != (size * SECTOR_SIZE))
+ {
+--- a/stage2/asm.S
++++ b/stage2/asm.S
+@@ -1651,7 +1651,29 @@ ENTRY(gateA20)
+ jnz 3f
+ ret
+
+-3: /* use keyboard controller */
++3: /*
++ * try to switch gateA20 using PORT92, the "Fast A20 and Init"
++ * register
++ */
++ mov $0x92, %dx
++ inb %dx, %al
++ /* skip the port92 code if it's unimplemented (read returns 0xff) */
++ cmpb $0xff, %al
++ jz 6f
++
++ /* set or clear bit1, the ALT_A20_GATE bit */
++ movb 4(%esp), %ah
++ testb %ah, %ah
++ jz 4f
++ orb $2, %al
++ jmp 5f
++4: and $0xfd, %al
++
++ /* clear the INIT_NOW bit don't accidently reset the machine */
++5: and $0xfe, %al
++ outb %al, %dx
++
++6: /* use keyboard controller */
+ pushl %eax
+
+ call gloop1
+@@ -1661,9 +1683,12 @@ ENTRY(gateA20)
+
+ gloopint1:
+ inb $K_STATUS
++ cmpb $0xff, %al
++ jz gloopint1_done
+ andb $K_IBUF_FUL, %al
+ jnz gloopint1
+
++gloopint1_done:
+ movb $KB_OUTPUT_MASK, %al
+ cmpb $0, 0x8(%esp)
+ jz gdoit
+@@ -1684,6 +1709,8 @@ gdoit:
+
+ gloop1:
+ inb $K_STATUS
++ cmpb $0xff, %al
++ jz gloop2ret
+ andb $K_IBUF_FUL, %al
+ jnz gloop1
+
+@@ -1991,6 +2018,11 @@ ENTRY(ascii_key_map)
+ ENTRY(console_getkey)
+ push %ebp
+
++wait_for_key:
++ call EXT_C(console_checkkey)
++ incl %eax
++ jz wait_for_key
++
+ call EXT_C(prot_to_real)
+ .code16
+
+@@ -2216,7 +2248,304 @@ ENTRY(console_setcursor)
+ pop %ebx
+ pop %ebp
+ ret
+-
++
++
++/* graphics mode functions */
++#ifdef SUPPORT_GRAPHICS
++VARIABLE(cursorX)
++.word 0
++VARIABLE(cursorY)
++.word 0
++VARIABLE(cursorCount)
++.word 0
++VARIABLE(cursorBuf)
++.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
++
++
++/*
++ * set_int1c_handler(void)
++ */
++ENTRY(set_int1c_handler)
++ pushl %edi
++
++ /* save the original int1c handler */
++ movl $0x70, %edi
++ movw (%edi), %ax
++ movw %ax, ABS(int1c_offset)
++ movw 2(%edi), %ax
++ movw %ax, ABS(int1c_segment)
++
++ /* save the new int1c handler */
++ movw $ABS(int1c_handler), %ax
++ movw %ax, (%edi)
++ xorw %ax, %ax
++ movw %ax, 2(%edi)
++
++ popl %edi
++ ret
++
++
++/*
++ * unset_int1c_handler(void)
++ */
++ENTRY(unset_int1c_handler)
++ pushl %edi
++
++ /* check if int1c_handler is set */
++ movl $0x70, %edi
++ movw $ABS(int1c_handler), %ax
++ cmpw %ax, (%edi)
++ jne int1c_1
++ xorw %ax, %ax
++ cmpw %ax, 2(%edi)
++ jne int1c_1
++
++ /* restore the original */
++ movw ABS(int1c_offset), %ax
++ movw %ax, (%edi)
++ movw ABS(int1c_segment), %ax
++ movw %ax, 2(%edi)
++
++int1c_1:
++ popl %edi
++ ret
++
++
++/*
++ * blinks graphics cursor
++ */
++ .code16
++write_data:
++ movw $0, %ax
++ movw %ax, %ds
++
++ mov $0xA000, %ax /* video in es:di */
++ mov %ax, %es
++ mov $80, %ax
++ movw $ABS(cursorY), %si
++ mov %ds:(%si), %bx
++ mul %bx
++ movw $ABS(cursorX), %si
++ mov %ds:(%si), %bx
++ shr $3, %bx /* %bx /= 8 */
++ add %bx, %ax
++ mov %ax, %di
++
++ movw $ABS(cursorBuf), %si /* fontBuf in ds:si */
++
++ /* prepare for data moving */
++ mov $16, %dx /* altura da fonte */
++ mov $80, %bx /* bytes por linha */
++
++write_loop:
++ movb %ds:(%si), %al
++ xorb $0xff, %al
++ movb %al, %ds:(%si) /* invert cursorBuf */
++ movb %al, %es:(%di) /* write to video */
++ add %bx, %di
++ inc %si
++ dec %dx
++ jg write_loop
++ ret
++
++int1c_handler:
++ pusha
++ mov $0, %ax
++ mov %ax, %ds
++ mov $ABS(cursorCount), %si
++ mov %ds:(%si), %ax
++ inc %ax
++ mov %ax, %ds:(%si)
++ cmp $9, %ax
++ jne int1c_done
++
++ mov $0, %ax
++ mov %ax, %ds:(%si)
++ call write_data
++
++int1c_done:
++ popa
++ iret
++ /* call previous int1c handler */
++ /* ljmp */
++ .byte 0xea
++int1c_offset: .word 0
++int1c_segment: .word 0
++ .code32
++
++
++/*
++ * unsigned char set_videomode(unsigned char mode)
++ * BIOS call "INT 10H Function 0h" to set video mode
++ * Call with %ah = 0x0
++ * %al = video mode
++ * Returns old videomode.
++ */
++ENTRY(set_videomode)
++ pushl %ebp
++ movl %esp,%ebp
++ pushl %ebx
++ pushl %ecx
++
++ movb 8(%ebp), %cl
++
++ call EXT_C(prot_to_real)
++ .code16
++
++ xorb %al, %al
++ movb $0xf, %ah
++ int $0x10 /* Get Current Video mode */
++ movb %al, %ch
++ xorb %ah, %ah
++ movb %cl, %al
++ int $0x10 /* Set Video mode */
++
++ DATA32 call EXT_C(real_to_prot)
++ .code32
++
++ xorl %eax, %eax
++ movb %ch, %al
++
++ popl %ecx
++ popl %ebx
++ popl %ebp
++ ret
++
++
++/*
++ * int get_videomode()
++ * BIOS call "INT 10H Function 0Fh" to get current video mode
++ * Call with %al = 0x0
++ * %ah = 0xF
++ * Returns current videomode.
++ */
++ENTRY(get_videomode)
++ pushl %ebp
++ movl %esp,%ebp
++ pushl %ebx
++ pushl %ecx
++
++ call EXT_C(prot_to_real)
++ .code16
++
++ xorb %al, %al
++ movb $0xF, %ah
++ int $0x10 /* Get Current Video mode */
++ movb %al, %cl /* For now we only want display mode */
++
++ DATA32 call EXT_C(real_to_prot)
++ .code32
++
++ xorl %eax, %eax
++ movb %cl, %al
++
++ popl %ecx
++ popl %ebx
++ popl %ebp
++ ret
++
++
++/*
++ * unsigned char * graphics_get_font()
++ * BIOS call "INT 10H Function 11h" to set font
++ * Call with %ah = 0x11
++ */
++ENTRY(graphics_get_font)
++ push %ebp
++ push %ebx
++ push %ecx
++ push %edx
++
++ call EXT_C(prot_to_real)
++ .code16
++
++ movw $0x1130, %ax
++ movb $6, %bh /* font 8x16 */
++ int $0x10
++ movw %bp, %dx
++ movw %es, %cx
++
++ DATA32 call EXT_C(real_to_prot)
++ .code32
++
++ xorl %eax, %eax
++ movw %cx, %ax
++ shll $4, %eax
++ movw %dx, %ax
++
++ pop %edx
++ pop %ecx
++ pop %ebx
++ pop %ebp
++ ret
++
++
++/*
++ * graphics_set_palette(index, red, green, blue)
++ * BIOS call "INT 10H Function 10h" to set individual dac register
++ * Call with %ah = 0x10
++ * %bx = register number
++ * %ch = new value for green (0-63)
++ * %cl = new value for blue (0-63)
++ * %dh = new value for red (0-63)
++ */
++
++ENTRY(graphics_set_palette)
++ push %ebp
++ push %eax
++ push %ebx
++ push %ecx
++ push %edx
++
++ movw $0x3c8, %bx /* address write mode register */
++
++ /* wait vertical retrace */
++ movw $0x3da, %dx
++l1b:
++ inb %dx, %al /* wait vertical active display */
++ test $8, %al
++ jnz l1b
++
++l2b:
++ inb %dx, %al /* wait vertical retrace */
++ test $8, %al
++ jnz l2b
++
++ mov %bx, %dx
++ movb 0x18(%esp), %al /* index */
++ outb %al, %dx
++ inc %dx
++
++ movb 0x1c(%esp), %al /* red */
++ outb %al, %dx
++
++ movb 0x20(%esp), %al /* green */
++ outb %al, %dx
++
++ movb 0x24(%esp), %al /* blue */
++ outb %al, %dx
++
++ movw 0x18(%esp), %bx
++
++ call EXT_C(prot_to_real)
++ .code16
++
++ movb %bl, %bh
++ movw $0x1000, %ax
++ int $0x10
++
++ DATA32 call EXT_C(real_to_prot)
++ .code32
++
++ pop %edx
++ pop %ecx
++ pop %ebx
++ pop %eax
++ pop %ebp
++ ret
++#endif /* SUPPORT_GRAPHICS */
++
++
+ /*
+ * getrtsecs()
+ * if a seconds value can be read, read it and return it (BCD),
+--- a/stage2/boot.c
++++ b/stage2/boot.c
+@@ -1,7 +1,7 @@
+ /* boot.c - load and bootstrap a kernel */
+ /*
+ * GRUB -- GRand Unified Bootloader
+- * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
++ * Copyright (C) 1999,2000,2001,2002,2003,2004,2005 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -29,6 +29,8 @@ static int cur_addr;
+ entry_func entry_addr;
+ static struct mod_list mll[99];
+ static int linux_mem_size;
++static int elf_kernel_addr;
++static int elf_kernel_size;
+
+ /*
+ * The next two functions, 'load_image' and 'load_module', are the building
+@@ -96,7 +98,7 @@ load_image (char *kernel, char *arg, ker
+ lh = (struct linux_kernel_header *) buffer;
+
+ /* ELF loading supported if multiboot, FreeBSD and NetBSD. */
+- if ((type == KERNEL_TYPE_MULTIBOOT
++ if (((type == KERNEL_TYPE_MULTIBOOT && ! (flags & MULTIBOOT_AOUT_KLUDGE))
+ || pu.elf->e_ident[EI_OSABI] == ELFOSABI_FREEBSD
+ || grub_strcmp (pu.elf->e_ident + EI_BRAND, "FreeBSD") == 0
+ || suggested_type == KERNEL_TYPE_NETBSD)
+@@ -594,6 +596,7 @@ load_image (char *kernel, char *arg, ker
+
+ /* reset this to zero for now */
+ cur_addr = 0;
++ elf_kernel_addr = ~0;
+
+ /* scan for program segments */
+ for (i = 0; i < pu.elf->e_phnum; i++)
+@@ -630,6 +633,8 @@ load_image (char *kernel, char *arg, ker
+ /* mark memory as used */
+ if (cur_addr < memaddr + memsiz)
+ cur_addr = memaddr + memsiz;
++ if (elf_kernel_addr > cur_addr)
++ elf_kernel_addr = cur_addr;
+ printf (", <0x%x:0x%x:0x%x>", memaddr, filesiz,
+ memsiz - filesiz);
+ /* increment number of segments */
+@@ -647,6 +652,8 @@ load_image (char *kernel, char *arg, ker
+ }
+ }
+
++ elf_kernel_size = cur_addr - elf_kernel_addr;
++
+ if (! errnum)
+ {
+ if (! loaded)
+@@ -824,8 +831,11 @@ load_initrd (char *initrd)
+ moveto = (mbi.mem_upper + 0x400) << 10;
+
+ moveto = (moveto - len) & 0xfffff000;
+- max_addr = (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0203
+- ? lh->initrd_addr_max : LINUX_INITRD_MAX_ADDRESS);
++ max_addr = LINUX_INITRD_MAX_ADDRESS;
++ if (lh->header == LINUX_MAGIC_SIGNATURE &&
++ lh->version >= 0x0203 &&
++ lh->initrd_addr_max < max_addr)
++ max_addr = lh->initrd_addr_max;
+ if (moveto + len >= max_addr)
+ moveto = (max_addr - len) & 0xfffff000;
+
+@@ -864,6 +874,129 @@ bsd_boot_entry (int flags, int bootdev,
+ }
+ #endif
+
++#define mem_align4k(p) ((p) + 0xFFF) & 0xFFFFF000
++
++static void
++kfreebsd_setenv (char *env, const char *var, const char *value)
++{
++ while (1)
++ {
++ if (env[0] == '\0' && env[1] == '\0')
++ {
++ env++;
++ break;
++ }
++ else
++ env++;
++ }
++
++ grub_sprintf (env, "%s=%s", var, value);
++ env[grub_strlen (env) + 1] = '\0';
++}
++
++static char *
++kfreebsd_read_hints (char *buf)
++{
++ char *buf_end = buf;
++
++ if (grub_open ("/boot/device.hints"))
++ {
++ char *line_start;
++ int line_len = 0;
++ char *envp;
++ int env_len;
++
++ env_len = grub_read (buf, -1);
++ if (env_len)
++ {
++ buf_end += env_len;
++ *(buf_end++) = '\0';
++ }
++ else
++ return buf_end;
++
++ grub_close ();
++
++ envp = line_start = buf;
++ while (*envp)
++ {
++ char *envp_current = envp;
++
++ switch (*envp)
++ {
++ case ' ':
++ while (*envp == ' ')
++ {
++ envp++;
++ env_len--;
++ }
++ grub_memmove (envp_current, envp, env_len + 1);
++ envp = envp_current;
++ break;
++ case '#':
++ while (*envp != '\n')
++ {
++ envp++;
++ env_len--;
++ }
++ if (!line_len)
++ envp++;
++ grub_memmove (envp_current, envp, env_len + 1);
++ envp = envp_current;
++ break;
++ case '\n':
++ if (!line_len)
++ {
++ env_len--;
++ grub_memmove (line_start, envp, env_len + 1);
++ }
++ *(envp++) = '\0';
++ line_len = 0;
++ line_start = envp;
++ default:
++ envp++;
++ line_len++;
++ break;
++ }
++ }
++
++ buf_end = buf + env_len;
++ *(buf_end++) = '\0';
++ }
++
++ return buf_end;
++}
++
++static u32_t *
++kfreebsd_set_module_string (u32_t type, u32_t *dst, char *src)
++{
++ int size;
++
++ *(dst++) = type;
++ *(dst++) = size = grub_strlen (src) + 1;
++ grub_strcpy ((void *) dst, src);
++
++ return dst + (size + sizeof(u32_t) - 1) / sizeof(u32_t);
++}
++
++static u32_t *
++kfreebsd_set_module_var (u32_t type, u32_t *dst, u32_t src)
++{
++ *(dst++) = type;
++ *(dst++) = sizeof(u32_t);
++ *(dst++) = src;
++
++ return dst;
++}
++
++static u32_t *
++kfreebsd_set_modules (u32_t *modulep)
++{
++ /* XXX: Need to copy the whole module structure. */
++ /* XXX: How to pass the module name ? */
++
++ return modulep;
++}
+
+ /*
+ * All "*_boot" commands depend on the images being loaded into memory
+@@ -877,7 +1010,10 @@ void
+ bsd_boot (kernel_t type, int bootdev, char *arg)
+ {
+ char *str;
+- int clval = 0, i;
++ char *kernelname;
++ char *bsd_root;
++ int clval = 0;
++ int i;
+ struct bootinfo bi;
+
+ #ifdef GRUB_UTIL
+@@ -886,8 +1022,21 @@ bsd_boot (kernel_t type, int bootdev, ch
+ stop_floppy ();
+ #endif
+
++ while (*arg != '/')
++ arg++;
++ kernelname = arg;
++
+ while (*(++arg) && *arg != ' ');
++ *(arg++) = 0;
+ str = arg;
++
++ bsd_root = grub_strstr (str, "root=");
++ if (bsd_root)
++ {
++ bsd_root += 5;
++ /* XXX: should copy the str or terminate it. */
++ }
++
+ while (*str)
+ {
+ if (*str == '-')
+@@ -910,6 +1059,8 @@ bsd_boot (kernel_t type, int bootdev, ch
+ clval |= RB_GDB;
+ if (*str == 'h')
+ clval |= RB_SERIAL;
++ if (*str == 'p')
++ clval |= RB_PAUSE;
+ if (*str == 'm')
+ clval |= RB_MUTE;
+ if (*str == 'r')
+@@ -927,14 +1078,17 @@ bsd_boot (kernel_t type, int bootdev, ch
+
+ if (type == KERNEL_TYPE_FREEBSD)
+ {
++ char *envp;
++ u32_t *modp;
++
+ clval |= RB_BOOTINFO;
+
+ bi.bi_version = BOOTINFO_VERSION;
+
+- *arg = 0;
+- while ((--arg) > (char *) MB_CMDLINE_BUF && *arg != '/');
+- if (*arg == '/')
+- bi.bi_kernelname = arg + 1;
++ bi.bi_pad[0] = bi.bi_pad[1] = 0;
++
++ if (*kernelname == '/')
++ bi.bi_kernelname = kernelname;
+ else
+ bi.bi_kernelname = 0;
+
+@@ -961,6 +1115,30 @@ bsd_boot (kernel_t type, int bootdev, ch
+ bi.bi_basemem = mbi.mem_lower;
+ bi.bi_extmem = extended_memory;
+
++ /* Setup the environment. */
++ bi.bi_envp = cur_addr = mem_align4k (cur_addr);
++ grub_memset ((void *) cur_addr, 0, 2);
++ cur_addr = (int) kfreebsd_read_hints ((void *) cur_addr);
++
++ envp = (char *) bi.bi_envp;
++ kfreebsd_setenv (envp, "kernelname", kernelname);
++ kfreebsd_setenv (envp, "vfs.root.mountfrom", bsd_root);
++
++ /* Setup the modules list. */
++ bi.bi_modulep = cur_addr = mem_align4k (cur_addr);
++ modp = (u32_t *) bi.bi_modulep;
++ /* The first module is the kernel. */
++ modp = kfreebsd_set_module_string (MODINFO_NAME, modp, kernelname);
++ modp = kfreebsd_set_module_string (MODINFO_TYPE, modp, "elf kernel");
++ modp = kfreebsd_set_module_string (MODINFO_ARGS, modp, arg);
++ modp = kfreebsd_set_module_var (MODINFO_ADDR, modp, elf_kernel_addr);
++ modp = kfreebsd_set_module_var (MODINFO_SIZE, modp, elf_kernel_size);
++ /* Now the real modules. */
++ modp = kfreebsd_set_modules(modp);
++
++ /* Set the kernel end. */
++ bi.bi_kernend = cur_addr = mem_align4k (((int) modp) + 1);
++
+ if (mbi.flags & MB_INFO_AOUT_SYMS)
+ {
+ bi.bi_symtab = mbi.syms.a.addr;
+@@ -970,8 +1148,9 @@ bsd_boot (kernel_t type, int bootdev, ch
+ #if 0
+ else if (mbi.flags & MB_INFO_ELF_SHDR)
+ {
+- /* FIXME: Should check if a symbol table exists and, if exists,
+- pass the table to BI. */
++ bi.bi_symtab = mbi.syms.e.addr;
++ bi.bi_esymtab = mbi.syms.e.addr
++ + mbi.syms.e.size * mbi.syms.e.num * mbi.syms.e.shndx;
+ }
+ #endif
+ else
+--- a/stage2/builtins.c
++++ b/stage2/builtins.c
+@@ -28,6 +28,10 @@
+ #include <filesys.h>
+ #include <term.h>
+
++#ifdef SUPPORT_GRAPHICS
++# include <graphics.h>
++#endif
++
+ #ifdef SUPPORT_NETBOOT
+ # define GRUB 1
+ # include <etherboot.h>
+@@ -82,6 +86,10 @@ static unsigned short bios_drive_map[DRI
+ inside other functions. */
+ static int configfile_func (char *arg, int flags);
+
++static int savedefault_helper (char *arg, int flags);
++
++static int savedefault_shell (char *arg, int flags);
++
+ /* Initialize the data for builtins. */
+ void
+ init_builtins (void)
+@@ -237,12 +245,22 @@ static struct builtin builtin_blocklist
+ static int
+ boot_func (char *arg, int flags)
+ {
++ struct term_entry *prev_term = current_term;
+ /* Clear the int15 handler if we can boot the kernel successfully.
+ This assumes that the boot code never fails only if KERNEL_TYPE is
+ not KERNEL_TYPE_NONE. Is this assumption is bad? */
+ if (kernel_type != KERNEL_TYPE_NONE)
+ unset_int15_handler ();
+
++ /* if our terminal needed initialization, we should shut it down
++ * before booting the kernel, but we want to save what it was so
++ * we can come back if needed */
++ if (current_term->shutdown)
++ {
++ current_term->shutdown();
++ current_term = term_table; /* assumption: console is first */
++ }
++
+ #ifdef SUPPORT_NETBOOT
+ /* Shut down the networking. */
+ cleanup_net ();
+@@ -306,6 +324,13 @@ boot_func (char *arg, int flags)
+ return 1;
+ }
+
++ /* if we get back here, we should go back to what our term was before */
++ current_term = prev_term;
++ if (current_term->startup)
++ /* if our terminal fails to initialize, fall back to console since
++ * it should always work */
++ if (current_term->startup() == 0)
++ current_term = term_table; /* we know that console is first */
+ return 0;
+ }
+
+@@ -852,6 +877,251 @@ static struct builtin builtin_dhcp =
+ };
+ #endif /* SUPPORT_NETBOOT */
+
++#ifdef SUPPORT_GRAPHICS
++
++static int splashimage_func(char *arg, int flags) {
++ int i;
++
++ /* filename can only be 256 characters due to our buffer size */
++ if (grub_strlen(arg) > 256) {
++ grub_printf("Splash image filename too large\n");
++ grub_printf("Press any key to continue...");
++ getkey();
++ return 1;
++ }
++
++ /* get rid of TERM_NEED_INIT from the graphics terminal. */
++ for (i = 0; term_table[i].name; i++) {
++ if (grub_strcmp (term_table[i].name, "graphics") == 0) {
++ term_table[i].flags &= ~TERM_NEED_INIT;
++ break;
++ }
++ }
++
++ graphics_set_splash(arg);
++
++ if (flags == BUILTIN_CMDLINE && graphics_inited) {
++ graphics_end();
++ if (graphics_init() == 0) {
++ /* Fallback to default term */
++ current_term = term_table;
++ max_lines = current_term->max_lines;
++ if (current_term->cls)
++ current_term->cls();
++ grub_printf("Failed to set splash image and/or graphics mode\n");
++ return 1;
++ }
++ graphics_cls();
++ }
++
++ if (flags == BUILTIN_MENU)
++ current_term = term_table + i;
++
++ return 0;
++}
++
++static struct builtin builtin_splashimage =
++{
++ "splashimage",
++ splashimage_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++ "splashimage FILE",
++ "Load FILE as the background image when in graphics mode."
++};
++
++
++/* shade */
++static int
++shade_func(char *arg, int flags)
++{
++ int new_shade;
++
++ if (!arg || safe_parse_maxint(&arg, &new_shade) == 0)
++ return (1);
++
++ if (shade != new_shade) {
++ shade = new_shade;
++ if (flags == BUILTIN_CMDLINE && graphics_inited) {
++ graphics_end();
++ graphics_init();
++ graphics_cls();
++ }
++ }
++
++ return 0;
++}
++
++static struct builtin builtin_shade =
++{
++ "shade",
++ shade_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++ "shade INTEGER",
++ "If set to 0, disables the use of shaded text, else enables it."
++};
++
++
++/* foreground */
++static int
++foreground_func(char *arg, int flags)
++{
++ if (grub_strlen(arg) == 6) {
++ int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
++ int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
++ int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
++
++ foreground = (r << 16) | (g << 8) | b;
++ if (graphics_inited)
++ graphics_set_palette(15, r, g, b);
++
++ return 0;
++ }
++
++ return 1;
++}
++
++static struct builtin builtin_foreground =
++{
++ "foreground",
++ foreground_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++ "foreground RRGGBB",
++ "Sets the foreground color when in graphics mode."
++ "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
++};
++
++
++/* background */
++static int
++background_func(char *arg, int flags)
++{
++ if (grub_strlen(arg) == 6) {
++ int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
++ int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
++ int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
++
++ background = (r << 16) | (g << 8) | b;
++ if (graphics_inited)
++ graphics_set_palette(0, r, g, b);
++ return 0;
++ }
++
++ return 1;
++}
++
++static struct builtin builtin_background =
++{
++ "background",
++ background_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++ "background RRGGBB",
++ "Sets the background color when in graphics mode."
++ "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
++};
++
++
++/* border */
++static int
++border_func(char *arg, int flags)
++{
++ if (grub_strlen(arg) == 6) {
++ int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
++ int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
++ int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
++
++ window_border = (r << 16) | (g << 8) | b;
++ if (graphics_inited)
++ graphics_set_palette(0x11, r, g, b);
++
++ return 0;
++ }
++
++ return 1;
++}
++
++static struct builtin builtin_border =
++{
++ "border",
++ border_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++ "border RRGGBB",
++ "Sets the border video color when in graphics mode."
++ "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
++};
++
++
++/* viewport */
++static int
++viewport_func (char *arg, int flags)
++{
++ int i;
++ int x0 = 0, y0 = 0, x1 = 80, y1 = 30;
++ int *pos[4] = { &x0, &y0, &x1, &y1 };
++
++ if (!arg)
++ return (1);
++ for (i = 0; i < 4; i++) {
++ if (!*arg)
++ return (1);
++ while (*arg && (*arg == ' ' || *arg == '\t'))
++ ++arg;
++ if (!safe_parse_maxint(&arg, pos[i]))
++ return (1);
++ while (*arg && (*arg != ' ' && *arg != '\t'))
++ ++arg;
++ }
++
++ /* minimum size is 65 colums and 16 rows */
++ if (x0 > x1 - 66 || y0 > y1 - 16 || x0 < 0 || y0 < 0 || x1 > 80 || y1 > 30)
++ return 1;
++
++ view_x0 = x0;
++ view_y0 = y0;
++ view_x1 = x1;
++ view_y1 = y1;
++
++ if (flags == BUILTIN_CMDLINE && graphics_inited) {
++ graphics_end();
++ graphics_init();
++ graphics_cls();
++ }
++
++ return 0;
++}
++
++static struct builtin builtin_viewport =
++{
++ "viewport",
++ viewport_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++ "viewport x0 y0 x1 y1",
++ "Changes grub internals to output text in the window defined by"
++ " four parameters. The x and y parameters are 0 based. This option"
++ " only works with the graphics interface."
++};
++
++#endif /* SUPPORT_GRAPHICS */
++
++
++/* clear */
++static int
++clear_func()
++{
++ if (current_term->cls)
++ current_term->cls();
++
++ return 0;
++}
++
++static struct builtin builtin_clear =
++{
++ "clear",
++ clear_func,
++ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
++ "clear",
++ "Clear the screen"
++};
++
+
+ /* displayapm */
+ static int
+@@ -1454,14 +1724,20 @@ static struct builtin builtin_halt =
+
+
+ /* help */
+-#define MAX_SHORT_DOC_LEN 39
+-#define MAX_LONG_DOC_LEN 66
+-
+ static int
+ help_func (char *arg, int flags)
+ {
+- int all = 0;
+-
++ int all = 0, max_short_doc_len, max_long_doc_len;
++ max_short_doc_len = 39;
++ max_long_doc_len = 66;
++#ifdef SUPPORT_GRAPHICS
++ if (grub_memcmp (current_term->name, "graphics", sizeof ("graphics") - 1) == 0)
++ {
++ max_short_doc_len = (view_x1 - view_x0 + 1) / 2 - 1;
++ max_long_doc_len = (view_x1 - view_x0) - 14;
++ }
++#endif
++
+ if (grub_memcmp (arg, "--all", sizeof ("--all") - 1) == 0)
+ {
+ all = 1;
+@@ -1491,13 +1767,13 @@ help_func (char *arg, int flags)
+
+ len = grub_strlen ((*builtin)->short_doc);
+ /* If the length of SHORT_DOC is too long, truncate it. */
+- if (len > MAX_SHORT_DOC_LEN - 1)
+- len = MAX_SHORT_DOC_LEN - 1;
++ if (len > max_short_doc_len - 1)
++ len = max_short_doc_len - 1;
+
+ for (i = 0; i < len; i++)
+ grub_putchar ((*builtin)->short_doc[i]);
+
+- for (; i < MAX_SHORT_DOC_LEN; i++)
++ for (; i < max_short_doc_len; i++)
+ grub_putchar (' ');
+
+ if (! left)
+@@ -1546,10 +1822,10 @@ help_func (char *arg, int flags)
+ int i;
+
+ /* If LEN is too long, fold DOC. */
+- if (len > MAX_LONG_DOC_LEN)
++ if (len > max_long_doc_len)
+ {
+ /* Fold this line at the position of a space. */
+- for (len = MAX_LONG_DOC_LEN; len > 0; len--)
++ for (len = max_long_doc_len; len > 0; len--)
+ if (doc[len - 1] == ' ')
+ break;
+ }
+@@ -2323,6 +2599,25 @@ static struct builtin builtin_ioprobe =
+ "Probe I/O ports used for the drive DRIVE."
+ };
+
++/* print */
++static int
++print_func (char *arg, int flags)
++{
++ printf("%s\n", arg);
++
++ return 0;
++}
++
++static struct builtin builtin_print =
++{
++ "print",
++ print_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_NO_ECHO,
++ "print [MESSAGE ...]",
++ "Print MESSAGE."
++};
++
++
+
+ /* kernel */
+ static int
+@@ -3221,7 +3516,102 @@ static struct builtin builtin_rootnoveri
+ static int
+ savedefault_func (char *arg, int flags)
+ {
+-#if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL)
++#if !defined(SUPPORT_DISKLESS)
++ #if !defined(GRUB_UTIL)
++ savedefault_helper(arg, flags);
++ #else
++ savedefault_shell(arg, flags);
++ #endif
++#else /* !SUPPORT_DISKLESS */
++ errnum = ERR_UNRECOGNIZED;
++ return 1;
++#endif /* !SUPPORT_DISKLESS */
++}
++
++#if !defined(SUPPORT_DISKLESS) && defined(GRUB_UTIL)
++/* savedefault_shell */
++static int
++savedefault_shell(char *arg, int flags)
++ {
++ int once_only = 0;
++ int new_default;
++ int curr_default = -1;
++ int curr_prev_default = -1;
++ int new_prev_default = -1;
++ FILE *fp;
++ size_t bytes = 10;
++ char line[bytes];
++ char *default_file = (char *) DEFAULT_FILE_BUF;
++ char buf[bytes];
++ int i;
++
++ while (1)
++ {
++ if (grub_memcmp ("--default=", arg, sizeof ("--default=") - 1) == 0)
++ {
++ char *p = arg + sizeof ("--default=") - 1;
++ if (! safe_parse_maxint (&p, &new_default))
++ return 1;
++ arg = skip_to (0, arg);
++ }
++ else if (grub_memcmp ("--once", arg, sizeof ("--once") - 1) == 0)
++ {
++ once_only = 1;
++ arg = skip_to (0, arg);
++ }
++ else
++ break;
++ }
++
++ *default_file = 0;
++ grub_strncat (default_file, config_file, DEFAULT_FILE_BUFLEN);
++ for (i = grub_strlen(default_file); i >= 0; i--)
++ if (default_file[i] == '/')
++ {
++ i++;
++ break;
++ }
++ default_file[i] = 0;
++ grub_strncat (default_file + i, "default", DEFAULT_FILE_BUFLEN - i);
++
++ if(!(fp = fopen(default_file,"w")))
++ {
++ errnum = ERR_READ;
++ goto fail;
++ }
++
++ read(&line, -1);
++
++ sscanf(line, "%d:%d", &curr_prev_default, &curr_default);
++
++ if(curr_default != -1)
++ new_prev_default = curr_default;
++ else
++ {
++ if(curr_prev_default != -1)
++ new_prev_default = curr_prev_default;
++ else
++ new_prev_default = 0;
++ }
++
++ if(once_only)
++ sprintf(buf, "%d:%d\n", new_prev_default, new_default);
++ else
++ sprintf(buf, "%d\n", new_default);
++
++ fprintf(fp, buf);
++
++fail:
++ fclose(fp);
++ return errnum;
++}
++#endif
++
++/* savedefault_helper */
++static int
++savedefault_helper (char *arg, int flags)
++{
++#if !defined(SUPPORT_DISKLESS)
+ unsigned long tmp_drive = saved_drive;
+ unsigned long tmp_partition = saved_partition;
+ char *default_file = (char *) DEFAULT_FILE_BUF;
+@@ -3300,19 +3690,23 @@ savedefault_func (char *arg, int flags)
+ disk_read_hook = 0;
+ grub_close ();
+
+- if (len != sizeof (buf))
+- {
+- /* This is too small. Do not modify the file manually, please! */
+- errnum = ERR_READ;
+- goto fail;
+- }
+-
+ if (sector_count > 2)
+ {
+ /* Is this possible?! Too fragmented! */
+ errnum = ERR_FSYS_CORRUPT;
+ goto fail;
+ }
++
++ char *tmp;
++ if((tmp = grub_strstr(buf, ":")) != NULL)
++ {
++ int f_len = grub_strlen(buf) - grub_strlen(tmp);
++ char *def;
++ int a;
++ for(a = 0; a < f_len; a++)
++ grub_memcpy(&def[a], &buf[a], sizeof(char));
++ safe_parse_maxint (&def, &entryno);
++ }
+
+ /* Set up a string to be written. */
+ grub_memset (buf, '\n', sizeof (buf));
+@@ -3830,15 +4224,15 @@ setup_func (char *arg, int flags)
+ {
+ char tmp[16];
+ grub_sprintf (tmp, ",%d", (partition >> 16) & 0xFF);
+- grub_strncat (device, tmp, 256);
++ grub_strncat (device, tmp, sizeof (device));
+ }
+ if ((partition & 0x00FF00) != 0x00FF00)
+ {
+ char tmp[16];
+ grub_sprintf (tmp, ",%c", 'a' + ((partition >> 8) & 0xFF));
+- grub_strncat (device, tmp, 256);
++ grub_strncat (device, tmp, sizeof (device));
+ }
+- grub_strncat (device, ")", 256);
++ grub_strncat (device, ")", sizeof (device));
+ }
+
+ int embed_stage1_5 (char *stage1_5, int drive, int partition)
+@@ -4085,7 +4479,7 @@ static struct builtin builtin_setup =
+ };
+
+
+-#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
++#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS)
+ /* terminal */
+ static int
+ terminal_func (char *arg, int flags)
+@@ -4244,17 +4638,29 @@ terminal_func (char *arg, int flags)
+ end:
+ current_term = term_table + default_term;
+ current_term->flags = term_flags;
+-
++
+ if (lines)
+ max_lines = lines;
+ else
+- /* 24 would be a good default value. */
+- max_lines = 24;
+-
++ max_lines = current_term->max_lines;
++
+ /* If the interface is currently the command-line,
+ restart it to repaint the screen. */
+- if (current_term != prev_term && (flags & BUILTIN_CMDLINE))
++ if ((current_term != prev_term) && (flags & BUILTIN_CMDLINE)){
++ if (prev_term->shutdown)
++ prev_term->shutdown();
++ if (current_term->startup) {
++ /* If startup fails, return to previous term */
++ if (current_term->startup() == 0) {
++ current_term = prev_term;
++ max_lines = current_term->max_lines;
++ if (current_term->cls) {
++ current_term->cls();
++ }
++ }
++ }
+ grub_longjmp (restart_cmdline_env, 0);
++ }
+
+ return 0;
+ }
+@@ -4264,7 +4670,7 @@ static struct builtin builtin_terminal =
+ "terminal",
+ terminal_func,
+ BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
+- "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules]",
++ "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules] [graphics]",
+ "Select a terminal. When multiple terminals are specified, wait until"
+ " you push any key to continue. If both console and serial are specified,"
+ " the terminal to which you input a key first will be selected. If no"
+@@ -4276,7 +4682,7 @@ static struct builtin builtin_terminal =
+ " seconds. The option --lines specifies the maximum number of lines."
+ " The option --silent is used to suppress messages."
+ };
+-#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
++#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */
+
+
+ #ifdef SUPPORT_SERIAL
+@@ -4795,13 +5201,20 @@ static struct builtin builtin_vbeprobe =
+ /* The table of builtin commands. Sorted in dictionary order. */
+ struct builtin *builtin_table[] =
+ {
++#ifdef SUPPORT_GRAPHICS
++ &builtin_background,
++#endif
+ &builtin_blocklist,
+ &builtin_boot,
+ #ifdef SUPPORT_NETBOOT
+ &builtin_bootp,
+ #endif /* SUPPORT_NETBOOT */
++#ifdef SUPPORT_GRAPHICS
++ &builtin_border,
++#endif
+ &builtin_cat,
+ &builtin_chainloader,
++ &builtin_clear,
+ &builtin_cmp,
+ &builtin_color,
+ &builtin_configfile,
+@@ -4821,6 +5234,9 @@ struct builtin *builtin_table[] =
+ &builtin_embed,
+ &builtin_fallback,
+ &builtin_find,
++#ifdef SUPPORT_GRAPHICS
++ &builtin_foreground,
++#endif
+ &builtin_fstest,
+ &builtin_geometry,
+ &builtin_halt,
+@@ -4848,6 +5264,7 @@ struct builtin *builtin_table[] =
+ &builtin_parttype,
+ &builtin_password,
+ &builtin_pause,
++ &builtin_print,
+ #ifdef GRUB_UTIL
+ &builtin_quit,
+ #endif /* GRUB_UTIL */
+@@ -4864,9 +5281,13 @@ struct builtin *builtin_table[] =
+ #endif /* SUPPORT_SERIAL */
+ &builtin_setkey,
+ &builtin_setup,
+-#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
++#ifdef SUPPORT_GRAPHICS
++ &builtin_shade,
++ &builtin_splashimage,
++#endif /* SUPPORT_GRAPHICS */
++#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS)
+ &builtin_terminal,
+-#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
++#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */
+ #ifdef SUPPORT_SERIAL
+ &builtin_terminfo,
+ #endif /* SUPPORT_SERIAL */
+@@ -4880,5 +5301,8 @@ struct builtin *builtin_table[] =
+ &builtin_unhide,
+ &builtin_uppermem,
+ &builtin_vbeprobe,
++#ifdef SUPPORT_GRAPHICS
++ &builtin_viewport,
++#endif
+ 0
+ };
+--- a/stage2/char_io.c
++++ b/stage2/char_io.c
+@@ -29,12 +29,17 @@
+ # include <serial.h>
+ #endif
+
++#ifdef SUPPORT_GRAPHICS
++# include <graphics.h>
++#endif
++
+ #ifndef STAGE1_5
+ struct term_entry term_table[] =
+ {
+ {
+ "console",
+ 0,
++ 24,
+ console_putchar,
+ console_checkkey,
+ console_getkey,
+@@ -43,13 +48,16 @@ struct term_entry term_table[] =
+ console_cls,
+ console_setcolorstate,
+ console_setcolor,
+- console_setcursor
++ console_setcursor,
++ 0,
++ 0
+ },
+ #ifdef SUPPORT_SERIAL
+ {
+ "serial",
+ /* A serial device must be initialized. */
+ TERM_NEED_INIT,
++ 24,
+ serial_putchar,
+ serial_checkkey,
+ serial_getkey,
+@@ -58,6 +66,8 @@ struct term_entry term_table[] =
+ serial_cls,
+ serial_setcolorstate,
+ 0,
++ 0,
++ 0,
+ 0
+ },
+ #endif /* SUPPORT_SERIAL */
+@@ -65,6 +75,7 @@ struct term_entry term_table[] =
+ {
+ "hercules",
+ 0,
++ 24,
+ hercules_putchar,
+ console_checkkey,
+ console_getkey,
+@@ -73,11 +84,30 @@ struct term_entry term_table[] =
+ hercules_cls,
+ hercules_setcolorstate,
+ hercules_setcolor,
+- hercules_setcursor
++ hercules_setcursor,
++ 0,
++ 0
+ },
+ #endif /* SUPPORT_HERCULES */
++#ifdef SUPPORT_GRAPHICS
++ { "graphics",
++ TERM_NEED_INIT, /* flags */
++ 30, /* number of lines */
++ graphics_putchar, /* putchar */
++ console_checkkey, /* checkkey */
++ console_getkey, /* getkey */
++ graphics_getxy, /* getxy */
++ graphics_gotoxy, /* gotoxy */
++ graphics_cls, /* cls */
++ graphics_setcolorstate, /* setcolorstate */
++ graphics_setcolor, /* setcolor */
++ graphics_setcursor, /* nocursor */
++ graphics_init, /* initialize */
++ graphics_end /* shutdown */
++ },
++#endif /* SUPPORT_GRAPHICS */
+ /* This must be the last entry. */
+- { 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 }
+ };
+
+ /* This must be console. */
+@@ -305,9 +335,10 @@ real_get_cmdline (char *prompt, char *cm
+
+ /* XXX: These should be defined in shared.h, but I leave these here,
+ until this code is freezed. */
+-#define CMDLINE_WIDTH 78
+ #define CMDLINE_MARGIN 10
+-
++
++ /* command-line limits */
++ int cmdline_width = 78, col_start = 0;
+ int xpos, lpos, c, section;
+ /* The length of PROMPT. */
+ int plen;
+@@ -338,7 +369,7 @@ real_get_cmdline (char *prompt, char *cm
+
+ /* If the cursor is in the first section, display the first section
+ instead of the second. */
+- if (section == 1 && plen + lpos < CMDLINE_WIDTH)
++ if (section == 1 && plen + lpos < cmdline_width)
+ cl_refresh (1, 0);
+ else if (xpos - count < 1)
+ cl_refresh (1, 0);
+@@ -354,7 +385,7 @@ real_get_cmdline (char *prompt, char *cm
+ grub_putchar ('\b');
+ }
+ else
+- gotoxy (xpos, getxy () & 0xFF);
++ gotoxy (xpos + col_start, getxy () & 0xFF);
+ }
+ }
+
+@@ -364,7 +395,7 @@ real_get_cmdline (char *prompt, char *cm
+ lpos += count;
+
+ /* If the cursor goes outside, scroll the screen to the right. */
+- if (xpos + count >= CMDLINE_WIDTH)
++ if (xpos + count >= cmdline_width)
+ cl_refresh (1, 0);
+ else
+ {
+@@ -383,7 +414,7 @@ real_get_cmdline (char *prompt, char *cm
+ }
+ }
+ else
+- gotoxy (xpos, getxy () & 0xFF);
++ gotoxy (xpos + col_start, getxy () & 0xFF);
+ }
+ }
+
+@@ -398,14 +429,14 @@ real_get_cmdline (char *prompt, char *cm
+ if (full)
+ {
+ /* Recompute the section number. */
+- if (lpos + plen < CMDLINE_WIDTH)
++ if (lpos + plen < cmdline_width)
+ section = 0;
+ else
+- section = ((lpos + plen - CMDLINE_WIDTH)
+- / (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN) + 1);
++ section = ((lpos + plen - cmdline_width)
++ / (cmdline_width - 1 - CMDLINE_MARGIN) + 1);
+
+ /* From the start to the end. */
+- len = CMDLINE_WIDTH;
++ len = cmdline_width;
+ pos = 0;
+ grub_putchar ('\r');
+
+@@ -445,8 +476,8 @@ real_get_cmdline (char *prompt, char *cm
+ if (! full)
+ offset = xpos - 1;
+
+- start = ((section - 1) * (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN)
+- + CMDLINE_WIDTH - plen - CMDLINE_MARGIN);
++ start = ((section - 1) * (cmdline_width - 1 - CMDLINE_MARGIN)
++ + cmdline_width - plen - CMDLINE_MARGIN);
+ xpos = lpos + 1 - start;
+ start += offset;
+ }
+@@ -471,7 +502,7 @@ real_get_cmdline (char *prompt, char *cm
+
+ /* If the cursor is at the last position, put `>' or a space,
+ depending on if there are more characters in BUF. */
+- if (pos == CMDLINE_WIDTH)
++ if (pos == cmdline_width)
+ {
+ if (start + len < llen)
+ grub_putchar ('>');
+@@ -488,7 +519,7 @@ real_get_cmdline (char *prompt, char *cm
+ grub_putchar ('\b');
+ }
+ else
+- gotoxy (xpos, getxy () & 0xFF);
++ gotoxy (xpos + col_start, getxy () & 0xFF);
+ }
+
+ /* Initialize the command-line. */
+@@ -518,10 +549,10 @@ real_get_cmdline (char *prompt, char *cm
+
+ llen += l;
+ lpos += l;
+- if (xpos + l >= CMDLINE_WIDTH)
++ if (xpos + l >= cmdline_width)
+ cl_refresh (1, 0);
+- else if (xpos + l + llen - lpos > CMDLINE_WIDTH)
+- cl_refresh (0, CMDLINE_WIDTH - xpos);
++ else if (xpos + l + llen - lpos > cmdline_width)
++ cl_refresh (0, cmdline_width - xpos);
+ else
+ cl_refresh (0, l + llen - lpos);
+ }
+@@ -533,12 +564,22 @@ real_get_cmdline (char *prompt, char *cm
+ grub_memmove (buf + lpos, buf + lpos + count, llen - count + 1);
+ llen -= count;
+
+- if (xpos + llen + count - lpos > CMDLINE_WIDTH)
+- cl_refresh (0, CMDLINE_WIDTH - xpos);
++ if (xpos + llen + count - lpos > cmdline_width)
++ cl_refresh (0, cmdline_width - xpos);
+ else
+ cl_refresh (0, llen + count - lpos);
+ }
+
++ max_lines = current_term->max_lines;
++#ifdef SUPPORT_GRAPHICS
++ if (grub_memcmp (current_term->name, "graphics", sizeof ("graphics") - 1) == 0)
++ {
++ cmdline_width = (view_x1 - view_x0) - 2;
++ col_start = view_x0;
++ max_lines = view_y1 - view_y0;
++ }
++#endif
++
+ plen = grub_strlen (prompt);
+ llen = grub_strlen (cmdline);
+
+@@ -1006,6 +1047,48 @@ checkkey (void)
+ }
+ #endif /* ! STAGE1_5 */
+
++#ifndef STAGE1_5
++/* Internal pager. */
++int
++do_more (void)
++{
++ if (count_lines >= 0)
++ {
++ count_lines++;
++ if (count_lines >= max_lines - 2)
++ {
++ int tmp;
++
++ /* It's important to disable the feature temporarily, because
++ the following grub_printf call will print newlines. */
++ count_lines = -1;
++
++ grub_printf("\n");
++ if (current_term->setcolorstate)
++ current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
++
++ grub_printf ("[Hit return to continue]");
++
++ if (current_term->setcolorstate)
++ current_term->setcolorstate (COLOR_STATE_NORMAL);
++
++
++ do
++ {
++ tmp = ASCII_CHAR (getkey ());
++ }
++ while (tmp != '\n' && tmp != '\r');
++ grub_printf ("\r \r");
++
++ /* Restart to count lines. */
++ count_lines = 0;
++ return 1;
++ }
++ }
++ return 0;
++}
++#endif
++
+ /* Display an ASCII character. */
+ void
+ grub_putchar (int c)
+@@ -1034,38 +1117,11 @@ grub_putchar (int c)
+
+ if (c == '\n')
+ {
++ int flag;
+ /* Internal `more'-like feature. */
+- if (count_lines >= 0)
+- {
+- count_lines++;
+- if (count_lines >= max_lines - 2)
+- {
+- int tmp;
+-
+- /* It's important to disable the feature temporarily, because
+- the following grub_printf call will print newlines. */
+- count_lines = -1;
+-
+- if (current_term->setcolorstate)
+- current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
+-
+- grub_printf ("\n[Hit return to continue]");
+-
+- if (current_term->setcolorstate)
+- current_term->setcolorstate (COLOR_STATE_NORMAL);
+-
+- do
+- {
+- tmp = ASCII_CHAR (getkey ());
+- }
+- while (tmp != '\n' && tmp != '\r');
+- grub_printf ("\r \r");
+-
+- /* Restart to count lines. */
+- count_lines = 0;
+- return;
+- }
+- }
++ flag = do_more ();
++ if (flag)
++ return;
+ }
+
+ current_term->putchar (c);
+@@ -1090,7 +1146,7 @@ void
+ cls (void)
+ {
+ /* If the terminal is dumb, there is no way to clean the terminal. */
+- if (current_term->flags & TERM_DUMB)
++ if (current_term->flags & TERM_DUMB)
+ grub_putchar ('\n');
+ else
+ current_term->cls ();
+@@ -1175,13 +1231,13 @@ grub_strlen (const char *str)
+ #endif /* ! STAGE1_5 */
+
+ int
+-memcheck (int addr, int len)
++memcheck (unsigned long int addr, unsigned long int len)
+ {
+ #ifdef GRUB_UTIL
+- auto int start_addr (void);
+- auto int end_addr (void);
++ auto unsigned long int start_addr (void);
++ auto int unsigned long end_addr (void);
+
+- auto int start_addr (void)
++ auto unsigned long int start_addr (void)
+ {
+ int ret;
+ # if defined(HAVE_START_SYMBOL)
+@@ -1192,7 +1248,7 @@ memcheck (int addr, int len)
+ return ret;
+ }
+
+- auto int end_addr (void)
++ auto unsigned long int end_addr (void)
+ {
+ int ret;
+ # if defined(HAVE_END_SYMBOL)
+@@ -1217,6 +1273,16 @@ memcheck (int addr, int len)
+ return ! errnum;
+ }
+
++void
++grub_memcpy(void *dest, const void *src, int len)
++{
++ int i;
++ register char *d = (char*)dest, *s = (char*)src;
++
++ for (i = 0; i < len; i++)
++ d[i] = s[i];
++}
++
+ void *
+ grub_memmove (void *to, const void *from, int len)
+ {
+--- a/stage2/cmdline.c
++++ b/stage2/cmdline.c
+@@ -50,10 +50,11 @@ skip_to (int after_equal, char *cmdline)
+ void
+ print_cmdline_message (int forever)
+ {
+- printf (" [ Minimal BASH-like line editing is supported. For the first word, TAB\n"
+- " lists possible command completions. Anywhere else TAB lists the possible\n"
+- " completions of a device/filename.%s ]\n",
+- (forever ? "" : " ESC at any time exits."));
++ grub_printf(" [ Minimal BASH-like line editing is supported. For\n"
++ " the first word, TAB lists possible command\n"
++ " completions. Anywhere else TAB lists the possible\n"
++ " completions of a device/filename.%s ]\n",
++ (forever ? "" : " ESC at any time\n exits."));
+ }
+
+ /* Find the builtin whose command name is COMMAND and return the
+--- a/stage2/freebsd.h
++++ b/stage2/freebsd.h
+@@ -1,7 +1,7 @@
+
+ /*
+ * GRUB -- GRand Unified Bootloader
+- * Copyright (C) 2001 Free Software Foundation, Inc.
++ * Copyright (C) 2001, 2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -35,6 +35,10 @@
+ #define RB_CDROM 0x2000 /* use cdrom as root */
+ #define RB_GDB 0x8000 /* use GDB remote debugger instead of DDB */
+ #define RB_MUTE 0x10000 /* Come up with the console muted */
++#define RB_SELFTEST 0x20000 /* don't complete the boot; do selftest */
++#define RB_RESERVED1 0x40000 /* reserved for internal use of boot blocks */
++#define RB_RESERVED2 0x80000 /* reserved for internal use of boot blocks */
++#define RB_PAUSE 0x100000 /* pause after each output line during probe */
+ #define RB_MULTIPLE 0x20000000 /* Use multiple consoles */
+
+ #define RB_BOOTINFO 0x80000000 /* have `struct bootinfo *' arg */
+@@ -70,6 +74,9 @@
+
+ #define N_BIOS_GEOM 8
+
++typedef unsigned char u8_t;
++typedef unsigned int u32_t;
++
+ /*
+ * A zero bootinfo field often means that there is no info available.
+ * Flags are used to indicate the validity of fields where zero is a
+@@ -77,19 +84,33 @@
+ */
+ struct bootinfo
+ {
+- unsigned int bi_version;
+- unsigned char *bi_kernelname;
+- struct nfs_diskless *bi_nfs_diskless;
++ u32_t bi_version;
++ u8_t *bi_kernelname;
++ u32_t bi_nfs_diskless;
+ /* End of fields that are always present. */
+ #define bi_endcommon bi_n_bios_used
+- unsigned int bi_n_bios_used;
+- unsigned long bi_bios_geom[N_BIOS_GEOM];
+- unsigned int bi_size;
+- unsigned char bi_memsizes_valid;
+- unsigned char bi_bios_dev;
+- unsigned char bi_pad[2];
+- unsigned long bi_basemem;
+- unsigned long bi_extmem;
+- unsigned long bi_symtab;
+- unsigned long bi_esymtab;
++ u32_t bi_n_bios_used;
++ u32_t bi_bios_geom[N_BIOS_GEOM];
++ u32_t bi_size;
++ u8_t bi_memsizes_valid;
++ u8_t bi_bios_dev;
++ u8_t bi_pad[2];
++ u32_t bi_basemem;
++ u32_t bi_extmem;
++ u32_t bi_symtab;
++ u32_t bi_esymtab;
++ /* Items below only from advanced bootloader */
++ u32_t bi_kernend;
++ u32_t bi_envp;
++ u32_t bi_modulep;
+ };
++
++#define MODINFO_END 0x0000 /* End of list */
++#define MODINFO_NAME 0x0001 /* Name of module (string) */
++#define MODINFO_TYPE 0x0002 /* Type of module (string) */
++#define MODINFO_ADDR 0x0003 /* Loaded address */
++#define MODINFO_SIZE 0x0004 /* Size of module */
++#define MODINFO_EMPTY 0x0005 /* Has been deleted */
++#define MODINFO_ARGS 0x0006 /* Parameters string */
++#define MODINFO_METADATA 0x8000 /* Module-specfic */
++
+--- /dev/null
++++ b/stage2/graphics.c
+@@ -0,0 +1,585 @@
++/*
++ * graphics.c - graphics mode support for GRUB
++ * Implemented as a terminal type by Jeremy Katz <katzj@redhat.com> based
++ * on a patch by Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
++ * Options and enhancements made by Herton Ronaldo Krzesinski
++ * <herton@mandriva.com>
++ *
++ * GRUB -- GRand Unified Bootloader
++ * Copyright (C) 2001,2002 Red Hat, Inc.
++ * Portions copyright (C) 2000 Conectiva, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifdef SUPPORT_GRAPHICS
++
++#include <term.h>
++#include <shared.h>
++#include <graphics.h>
++
++int saved_videomode;
++unsigned char *font8x16;
++
++int graphics_inited = 0;
++static char splashimage[256];
++
++int shade = 1, no_cursor = 0;
++
++#define VSHADOW VSHADOW1
++unsigned char VSHADOW1[38400];
++unsigned char VSHADOW2[38400];
++unsigned char VSHADOW4[38400];
++unsigned char VSHADOW8[38400];
++
++/* define the default viewable area */
++int view_x0 = 0;
++int view_y0 = 0;
++int view_x1 = 80;
++int view_y1 = 30;
++
++/* text buffer has to be kept around so that we can write things as we
++ * scroll and the like */
++unsigned short text[80 * 30];
++
++/* graphics options */
++int foreground = (63 << 16) | (63 << 8) | (63), background = 0, window_border = 0;
++
++/* current position */
++static int fontx = 0;
++static int fonty = 0;
++
++/* global state so that we don't try to recursively scroll or cursor */
++static int no_scroll = 0;
++
++/* color state */
++static int graphics_standard_color = A_NORMAL;
++static int graphics_normal_color = A_NORMAL;
++static int graphics_highlight_color = A_REVERSE;
++static int graphics_current_color = A_NORMAL;
++static color_state graphics_color_state = COLOR_STATE_STANDARD;
++
++static inline void outb(unsigned short port, unsigned char val)
++{
++ __asm __volatile ("outb %0,%1"::"a" (val), "d" (port));
++}
++
++static void MapMask(int value) {
++ outb(0x3c4, 2);
++ outb(0x3c5, value);
++}
++
++/* bit mask register */
++static void BitMask(int value) {
++ outb(0x3ce, 8);
++ outb(0x3cf, value);
++}
++
++/* move the graphics cursor location to col, row */
++static void graphics_setxy(int col, int row) {
++ if (col >= view_x0 && col < view_x1) {
++ fontx = col;
++ cursorX = col << 3;
++ }
++ if (row >= view_y0 && row < view_y1) {
++ fonty = row;
++ cursorY = row << 4;
++ }
++}
++
++/* scroll the screen */
++static void graphics_scroll() {
++ int i, j, k;
++
++ /* we don't want to scroll recursively... that would be bad */
++ if (no_scroll)
++ return;
++ no_scroll = 1;
++
++ /* disable pager temporarily */
++ k = count_lines;
++ count_lines = -1;
++
++ /* move everything up a line */
++ for (j = view_y0 + 1; j < view_y1; j++) {
++ graphics_gotoxy(view_x0, j - 1);
++ for (i = view_x0; i < view_x1; i++) {
++ graphics_putchar(text[j * 80 + i]);
++ }
++ }
++
++ /* last line should be blank */
++ graphics_gotoxy(view_x0, view_y1 - 1);
++ for (i = view_x0; i < view_x1; i++)
++ graphics_putchar(' ');
++ graphics_setxy(view_x0, view_y1 - 1);
++
++ count_lines = k;
++
++ no_scroll = 0;
++}
++
++/* Set the splash image */
++void graphics_set_splash(char *splashfile) {
++ grub_strcpy(splashimage, splashfile);
++}
++
++/* Get the current splash image */
++char *graphics_get_splash(void) {
++ return splashimage;
++}
++
++/*
++ * Initialize a vga16 graphics display with the palette based off of
++ * the image in splashimage. If the image doesn't exist, leave graphics
++ * mode. The mode initiated is 12h. From "Ralf Brown's Interrupt List":
++ * text/ text pixel pixel colors disply scrn system
++ * grph resol box resolution pages addr
++ * 12h G 80x30 8x16 640x480 16/256K . A000 VGA,ATI VIP
++ * G 80x30 8x16 640x480 16/64 . A000 ATI EGA Wonder
++ * G . . 640x480 16 . . UltraVision+256K EGA
++ */
++int graphics_init()
++{
++ if (!graphics_inited) {
++ saved_videomode = set_videomode(0x12);
++ if (get_videomode() != 0x12) {
++ set_videomode(saved_videomode);
++ return 0;
++ }
++ graphics_inited = 1;
++ }
++ else
++ return 1;
++
++ font8x16 = (unsigned char*)graphics_get_font();
++
++ /* make sure that the highlight color is set correctly */
++ graphics_highlight_color = ((graphics_normal_color >> 4) |
++ ((graphics_normal_color & 0xf) << 4));
++
++ graphics_cls();
++
++ if (!read_image(splashimage)) {
++ grub_printf("Failed to read splash image (%s)\n", splashimage);
++ grub_printf("Press any key to continue...");
++ getkey();
++ set_videomode(saved_videomode);
++ graphics_inited = 0;
++ return 0;
++ }
++
++ set_int1c_handler();
++
++ return 1;
++}
++
++/* Leave graphics mode */
++void graphics_end(void)
++{
++ if (graphics_inited) {
++ unset_int1c_handler();
++ set_videomode(saved_videomode);
++ graphics_inited = 0;
++ no_cursor = 0;
++ }
++}
++
++/* Print ch on the screen. Handle any needed scrolling or the like */
++void graphics_putchar(int ch) {
++ ch &= 0xff;
++
++ graphics_cursor(0);
++
++ if (ch == '\n') {
++ if (fonty + 1 < view_y1)
++ graphics_setxy(fontx, fonty + 1);
++ else
++ graphics_scroll();
++ graphics_cursor(1);
++ return;
++ } else if (ch == '\r') {
++ graphics_setxy(view_x0, fonty);
++ graphics_cursor(1);
++ return;
++ }
++
++ graphics_cursor(0);
++
++ text[fonty * 80 + fontx] = ch;
++ text[fonty * 80 + fontx] &= 0x00ff;
++ if (graphics_current_color & 0xf0)
++ text[fonty * 80 + fontx] |= 0x100;
++
++ graphics_cursor(0);
++
++ if ((fontx + 1) >= view_x1) {
++ graphics_setxy(view_x0, fonty);
++ if (fonty + 1 < view_y1)
++ graphics_setxy(view_x0, fonty + 1);
++ else
++ graphics_scroll();
++ graphics_cursor(1);
++ do_more ();
++ graphics_cursor(0);
++ } else {
++ graphics_setxy(fontx + 1, fonty);
++ }
++
++ graphics_cursor(1);
++}
++
++/* get the current location of the cursor */
++int graphics_getxy(void) {
++ return (fontx << 8) | fonty;
++}
++
++void graphics_gotoxy(int x, int y) {
++ graphics_cursor(0);
++
++ graphics_setxy(x, y);
++
++ graphics_cursor(1);
++}
++
++void graphics_cls(void) {
++ int i;
++ unsigned char *mem, *s1, *s2, *s4, *s8;
++
++ graphics_cursor(0);
++ graphics_gotoxy(view_x0, view_y0);
++
++ mem = (unsigned char*)VIDEOMEM;
++ s1 = (unsigned char*)VSHADOW1;
++ s2 = (unsigned char*)VSHADOW2;
++ s4 = (unsigned char*)VSHADOW4;
++ s8 = (unsigned char*)VSHADOW8;
++
++ for (i = 0; i < 80 * 30; i++)
++ text[i] = ' ';
++ graphics_cursor(1);
++
++ BitMask(0xff);
++
++ /* plane 1 */
++ MapMask(1);
++ grub_memcpy(mem, s1, 38400);
++
++ /* plane 2 */
++ MapMask(2);
++ grub_memcpy(mem, s2, 38400);
++
++ /* plane 3 */
++ MapMask(4);
++ grub_memcpy(mem, s4, 38400);
++
++ /* plane 4 */
++ MapMask(8);
++ grub_memcpy(mem, s8, 38400);
++
++ MapMask(15);
++
++ if (no_cursor) {
++ no_cursor = 0;
++ set_int1c_handler();
++ }
++}
++
++void graphics_setcolorstate (color_state state) {
++ switch (state) {
++ case COLOR_STATE_STANDARD:
++ graphics_current_color = graphics_standard_color;
++ break;
++ case COLOR_STATE_NORMAL:
++ graphics_current_color = graphics_normal_color;
++ break;
++ case COLOR_STATE_HIGHLIGHT:
++ graphics_current_color = graphics_highlight_color;
++ break;
++ default:
++ graphics_current_color = graphics_standard_color;
++ break;
++ }
++
++ graphics_color_state = state;
++}
++
++void graphics_setcolor (int normal_color, int highlight_color) {
++ graphics_normal_color = normal_color;
++ graphics_highlight_color = highlight_color;
++
++ graphics_setcolorstate (graphics_color_state);
++}
++
++int graphics_setcursor (int on) {
++ if (!no_cursor && !on) {
++ no_cursor = 1;
++ unset_int1c_handler();
++ graphics_cursor(0);
++ }
++ else if(no_cursor && on) {
++ no_cursor = 0;
++ set_int1c_handler();
++ graphics_cursor(1);
++ }
++ return 0;
++}
++
++/* Read in the splashscreen image and set the palette up appropriately.
++ * Format of splashscreen is an xpm (can be gzipped) with 16 colors and
++ * 640x480. */
++int read_image(char *s)
++{
++ char buf[32], pal[16], c;
++ unsigned char base, mask, *s1, *s2, *s4, *s8;
++ unsigned i, len, idx, colors, x, y, width, height;
++
++ if (!grub_open(s))
++ return 0;
++
++ /* read header */
++ if (!grub_read((char*)&buf, 10) || grub_memcmp(buf, "/* XPM */\n", 10)) {
++ grub_close();
++ return 0;
++ }
++
++ /* parse info */
++ while (grub_read(&c, 1)) {
++ if (c == '"')
++ break;
++ }
++
++ while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
++ ;
++
++ i = 0;
++ width = c - '0';
++ while (grub_read(&c, 1)) {
++ if (c >= '0' && c <= '9')
++ width = width * 10 + c - '0';
++ else
++ break;
++ }
++ while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
++ ;
++
++ height = c - '0';
++ while (grub_read(&c, 1)) {
++ if (c >= '0' && c <= '9')
++ height = height * 10 + c - '0';
++ else
++ break;
++ }
++ while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
++ ;
++
++ colors = c - '0';
++ while (grub_read(&c, 1)) {
++ if (c >= '0' && c <= '9')
++ colors = colors * 10 + c - '0';
++ else
++ break;
++ }
++
++ base = 0;
++ while (grub_read(&c, 1) && c != '"')
++ ;
++
++ /* palette */
++ for (i = 0, idx = 1; i < colors; i++) {
++ len = 0;
++
++ while (grub_read(&c, 1) && c != '"')
++ ;
++ grub_read(&c, 1); /* char */
++ base = c;
++ grub_read(buf, 4); /* \t c # */
++
++ while (grub_read(&c, 1) && c != '"') {
++ if (len < sizeof(buf))
++ buf[len++] = c;
++ }
++
++ if (len == 6 && idx < 15) {
++ int r = ((hex(buf[0]) << 4) | hex(buf[1])) >> 2;
++ int g = ((hex(buf[2]) << 4) | hex(buf[3])) >> 2;
++ int b = ((hex(buf[4]) << 4) | hex(buf[5])) >> 2;
++
++ pal[idx] = base;
++ graphics_set_palette(idx, r, g, b);
++ ++idx;
++ }
++ }
++
++ x = y = len = 0;
++
++ s1 = (unsigned char*)VSHADOW1;
++ s2 = (unsigned char*)VSHADOW2;
++ s4 = (unsigned char*)VSHADOW4;
++ s8 = (unsigned char*)VSHADOW8;
++
++ for (i = 0; i < 38400; i++)
++ s1[i] = s2[i] = s4[i] = s8[i] = 0;
++
++ /* parse xpm data */
++ while (y < height) {
++ while (1) {
++ if (!grub_read(&c, 1)) {
++ grub_close();
++ return 0;
++ }
++ if (c == '"')
++ break;
++ }
++
++ while (grub_read(&c, 1) && c != '"') {
++ for (i = 1; i < 15; i++)
++ if (pal[i] == c) {
++ c = i;
++ break;
++ }
++
++ mask = 0x80 >> (x & 7);
++ if (c & 1)
++ s1[len + (x >> 3)] |= mask;
++ if (c & 2)
++ s2[len + (x >> 3)] |= mask;
++ if (c & 4)
++ s4[len + (x >> 3)] |= mask;
++ if (c & 8)
++ s8[len + (x >> 3)] |= mask;
++
++ if (++x >= 640) {
++ x = 0;
++
++ if (y < 480)
++ len += 80;
++ ++y;
++ }
++ }
++ }
++
++ grub_close();
++
++ graphics_set_palette(0, (background >> 16), (background >> 8) & 63,
++ background & 63);
++ graphics_set_palette(15, (foreground >> 16), (foreground >> 8) & 63,
++ foreground & 63);
++ graphics_set_palette(0x11, (window_border >> 16), (window_border >> 8) & 63,
++ window_border & 63);
++
++ return 1;
++}
++
++/* Convert a character which is a hex digit to the appropriate integer */
++int hex(int v)
++{
++ if (v >= 'A' && v <= 'F')
++ return (v - 'A' + 10);
++ if (v >= 'a' && v <= 'f')
++ return (v - 'a' + 10);
++ return (v - '0');
++}
++
++void graphics_cursor(int set) {
++ unsigned char *pat, *mem, *ptr, chr[16 << 2];
++ int i, ch, invert, offset;
++
++ if (set && (no_cursor || no_scroll))
++ return;
++
++ offset = cursorY * 80 + fontx;
++ ch = text[fonty * 80 + fontx] & 0xff;
++ invert = (text[fonty * 80 + fontx] & 0xff00) != 0;
++ pat = font8x16 + (ch << 4);
++
++ mem = (unsigned char*)VIDEOMEM + offset;
++
++ if (!set) {
++ for (i = 0; i < 16; i++) {
++ unsigned char mask = pat[i];
++
++ if (!invert) {
++ chr[i ] = ((unsigned char*)VSHADOW1)[offset];
++ chr[16 + i] = ((unsigned char*)VSHADOW2)[offset];
++ chr[32 + i] = ((unsigned char*)VSHADOW4)[offset];
++ chr[48 + i] = ((unsigned char*)VSHADOW8)[offset];
++
++ if (shade) {
++ if (ch == DISP_VERT || ch == DISP_LL ||
++ ch == DISP_UR || ch == DISP_LR) {
++ unsigned char pmask = ~(pat[i] >> 1);
++
++ chr[i ] &= pmask;
++ chr[16 + i] &= pmask;
++ chr[32 + i] &= pmask;
++ chr[48 + i] &= pmask;
++ }
++ if (i > 0 && ch != DISP_VERT) {
++ unsigned char pmask = ~(pat[i - 1] >> 1);
++
++ chr[i ] &= pmask;
++ chr[16 + i] &= pmask;
++ chr[32 + i] &= pmask;
++ chr[48 + i] &= pmask;
++ if (ch == DISP_HORIZ || ch == DISP_UR || ch == DISP_LR) {
++ pmask = ~pat[i - 1];
++
++ chr[i ] &= pmask;
++ chr[16 + i] &= pmask;
++ chr[32 + i] &= pmask;
++ chr[48 + i] &= pmask;
++ }
++ }
++ }
++ chr[i ] |= mask;
++ chr[16 + i] |= mask;
++ chr[32 + i] |= mask;
++ chr[48 + i] |= mask;
++
++ offset += 80;
++ }
++ else {
++ chr[i ] = mask;
++ chr[16 + i] = mask;
++ chr[32 + i] = mask;
++ chr[48 + i] = mask;
++ }
++ }
++ }
++ else {
++ MapMask(15);
++ ptr = mem;
++ for (i = 0; i < 16; i++, ptr += 80) {
++ cursorBuf[i] = pat[i];
++ *ptr = ~pat[i];
++ }
++ return;
++ }
++
++ offset = 0;
++ for (i = 1; i < 16; i <<= 1, offset += 16) {
++ int j;
++
++ MapMask(i);
++ ptr = mem;
++ for (j = 0; j < 16; j++, ptr += 80)
++ *ptr = chr[j + offset];
++ }
++
++ MapMask(15);
++}
++
++#endif /* SUPPORT_GRAPHICS */
+--- /dev/null
++++ b/stage2/graphics.h
+@@ -0,0 +1,44 @@
++/* graphics.h - graphics console interface */
++/*
++ * GRUB -- GRand Unified Bootloader
++ * Copyright (C) 2002 Free Software Foundation, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef GRAPHICS_H
++#define GRAPHICS_H
++
++/* magic constant */
++#define VIDEOMEM 0xA0000
++
++/* function prototypes */
++char *graphics_get_splash(void);
++
++int read_image(char *s);
++void graphics_cursor(int set);
++
++/* function prototypes for asm functions */
++void * graphics_get_font();
++void graphics_set_palette(int idx, int red, int green, int blue);
++void set_int1c_handler();
++void unset_int1c_handler();
++
++extern short cursorX, cursorY;
++extern char cursorBuf[16];
++extern int shade;
++extern int view_x0, view_y0, view_x1, view_y1;
++
++#endif /* GRAPHICS_H */
+--- a/stage2/Makefile.am
++++ b/stage2/Makefile.am
+@@ -7,7 +7,7 @@ noinst_HEADERS = apic.h defs.h dir.h dis
+ fat.h filesys.h freebsd.h fs.h hercules.h i386-elf.h \
+ imgact_aout.h iso9660.h jfs.h mb_header.h mb_info.h md5.h \
+ nbi.h pc_slice.h serial.h shared.h smp-imps.h term.h \
+- terminfo.h tparm.h nbi.h ufs2.h vstafs.h xfs.h
++ terminfo.h tparm.h nbi.h ufs2.h vstafs.h xfs.h graphics.h
+ EXTRA_DIST = setjmp.S apm.S $(noinst_SCRIPTS)
+
+ # For <stage1.h>.
+@@ -19,7 +19,7 @@ libgrub_a_SOURCES = boot.c builtins.c ch
+ disk_io.c fsys_ext2fs.c fsys_fat.c fsys_ffs.c fsys_iso9660.c \
+ fsys_jfs.c fsys_minix.c fsys_reiserfs.c fsys_ufs2.c \
+ fsys_vstafs.c fsys_xfs.c gunzip.c md5.c serial.c stage2.c \
+- terminfo.c tparm.c
++ terminfo.c tparm.c graphics.c
+ libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \
+ -DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \
+ -DFSYS_ISO9660=1 -DFSYS_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 \
+@@ -79,8 +79,14 @@ else
+ HERCULES_FLAGS =
+ endif
+
++if GRAPHICS_SUPPORT
++GRAPHICS_FLAGS = -DSUPPORT_GRAPHICS=1
++else
++GRAPHICS_FLAGS =
++endif
++
+ STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
+- $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS)
++ $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS) $(GRAPHICS_FLAGS)
+
+ STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000
+ STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1
+@@ -90,7 +96,8 @@ pre_stage2_exec_SOURCES = asm.S bios.c b
+ cmdline.c common.c console.c disk_io.c fsys_ext2fs.c \
+ fsys_fat.c fsys_ffs.c fsys_iso9660.c fsys_jfs.c fsys_minix.c \
+ fsys_reiserfs.c fsys_ufs2.c fsys_vstafs.c fsys_xfs.c gunzip.c \
+- hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c
++ hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c \
++ graphics.c
+ pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
+ pre_stage2_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
+ pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK)
+--- a/stage2/shared.h
++++ b/stage2/shared.h
+@@ -499,7 +499,11 @@ struct vbe_mode
+ unsigned char linear_reserved_field_position;
+ unsigned long max_pixel_clock;
+
+- unsigned char reserved3[189];
++ /* Reserved field to make structure to be 256 bytes long, VESA BIOS
++ Extension 3.0 Specification says to reserve 189 bytes here but
++ that doesn't make structure to be 256 bytes. So additional one is
++ added here. */
++ unsigned char reserved3[189 + 1];
+ } __attribute__ ((packed));
+
+
+@@ -792,6 +796,11 @@ int getxy (void);
+ /* Set the cursor position. */
+ void gotoxy (int x, int y);
+
++/* Internal pager
++ Returns 1 = if pager was used
++ 0 = if pager wasn't used */
++int do_more (void);
++
+ /* Displays an ASCII character. IBM displays will translate some
+ characters to special graphical ones (see the DISP_* constants). */
+ void grub_putchar (int c);
+@@ -871,6 +880,7 @@ int grub_sprintf (char *buffer, const ch
+ int grub_tolower (int c);
+ int grub_isspace (int c);
+ int grub_strncat (char *s1, const char *s2, int n);
++void grub_memcpy(void *dest, const void *src, int len);
+ void *grub_memmove (void *to, const void *from, int len);
+ void *grub_memset (void *start, int c, int len);
+ int grub_strncat (char *s1, const char *s2, int n);
+@@ -911,7 +921,7 @@ int substring (const char *s1, const cha
+ int nul_terminate (char *str);
+ int get_based_digit (int c, int base);
+ int safe_parse_maxint (char **str_ptr, int *myint_ptr);
+-int memcheck (int start, int len);
++int memcheck (unsigned long int start, unsigned long int len);
+ void grub_putstr (const char *str);
+
+ #ifndef NO_DECOMPRESSION
+--- a/stage2/stage2.c
++++ b/stage2/stage2.c
+@@ -20,6 +20,12 @@
+ #include <shared.h>
+ #include <term.h>
+
++#ifdef SUPPORT_GRAPHICS
++# include <graphics.h>
++#endif
++
++int col_start, col_end, row_start, box_size;
++
+ grub_jmp_buf restart_env;
+
+ #if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS)
+@@ -105,13 +111,13 @@ print_entry (int y, int highlight, char
+ if (highlight && current_term->setcolorstate)
+ current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
+
+- gotoxy (2, y);
++ gotoxy (2 + col_start, y);
+ grub_putchar (' ');
+- for (x = 3; x < 75; x++)
++ for (x = 3 + col_start; x < (col_end - 5); x++)
+ {
+- if (*entry && x <= 72)
++ if (*entry && x <= (col_end - 8))
+ {
+- if (x == 72)
++ if (x == (col_end - 8))
+ grub_putchar (DISP_RIGHT);
+ else
+ grub_putchar (*entry++);
+@@ -119,7 +125,7 @@ print_entry (int y, int highlight, char
+ else
+ grub_putchar (' ');
+ }
+- gotoxy (74, y);
++ gotoxy ((col_end - 6), y);
+
+ if (current_term->setcolorstate)
+ current_term->setcolorstate (COLOR_STATE_STANDARD);
+@@ -131,7 +137,7 @@ print_entries (int y, int size, int firs
+ {
+ int i;
+
+- gotoxy (77, y + 1);
++ gotoxy ((col_end - 3), y + 1);
+
+ if (first)
+ grub_putchar (DISP_UP);
+@@ -151,14 +157,14 @@ print_entries (int y, int size, int firs
+ menu_entries++;
+ }
+
+- gotoxy (77, y + size);
++ gotoxy ((col_end - 3), y + size);
+
+ if (*menu_entries)
+ grub_putchar (DISP_DOWN);
+ else
+ grub_putchar (' ');
+
+- gotoxy (74, y + entryno + 1);
++ gotoxy ((col_end - 6), y + entryno + 1);
+ }
+
+ static void
+@@ -196,30 +202,30 @@ print_border (int y, int size)
+ if (current_term->setcolorstate)
+ current_term->setcolorstate (COLOR_STATE_NORMAL);
+
+- gotoxy (1, y);
++ gotoxy (1 + col_start, y);
+
+ grub_putchar (DISP_UL);
+- for (i = 0; i < 73; i++)
++ for (i = col_start; i < (col_end - 7); i++)
+ grub_putchar (DISP_HORIZ);
+ grub_putchar (DISP_UR);
+
+ i = 1;
+ while (1)
+ {
+- gotoxy (1, y + i);
++ gotoxy (1 + col_start, y + i);
+
+ if (i > size)
+ break;
+
+ grub_putchar (DISP_VERT);
+- gotoxy (75, y + i);
++ gotoxy ((col_end - 5), y + i);
+ grub_putchar (DISP_VERT);
+
+ i++;
+ }
+
+ grub_putchar (DISP_LL);
+- for (i = 0; i < 73; i++)
++ for (i = col_start; i < (col_end - 7); i++)
+ grub_putchar (DISP_HORIZ);
+ grub_putchar (DISP_LR);
+
+@@ -233,6 +239,7 @@ run_menu (char *menu_entries, char *conf
+ {
+ int c, time1, time2 = -1, first_entry = 0;
+ char *cur_entry = 0;
++ struct term_entry *prev_term = NULL;
+
+ /*
+ * Main loop for menu UI.
+@@ -250,6 +257,22 @@ restart:
+ }
+ }
+
++ col_start = 0;
++ col_end = 80;
++ row_start = 0;
++ box_size = 12;
++ /* if we're using viewport we need to make sure to setup
++ coordinates correctly. */
++#ifdef SUPPORT_GRAPHICS
++ if (grub_memcmp (current_term->name, "graphics", sizeof ("graphics") - 1) == 0)
++ {
++ col_start = view_x0;
++ col_end = view_x1;
++ row_start = view_y0;
++ box_size = (view_y1 - view_y0) - 13;
++ }
++#endif
++
+ /* If the timeout was expired or wasn't set, force to show the menu
+ interface. */
+ if (grub_timeout < 0)
+@@ -302,36 +325,36 @@ restart:
+ if (current_term->flags & TERM_DUMB)
+ print_entries_raw (num_entries, first_entry, menu_entries);
+ else
+- print_border (3, 12);
++ print_border (3 + row_start, box_size);
+
+ grub_printf ("\n\
+- Use the %c and %c keys to select which entry is highlighted.\n",
++ Use the %c and %c keys to select which entry is highlighted.\n",
+ DISP_UP, DISP_DOWN);
+
+ if (! auth && password)
+ {
+ printf ("\
+- Press enter to boot the selected OS or \'p\' to enter a\n\
+- password to unlock the next set of features.");
++ Press enter to boot the selected OS or \'p\' to enter a\n\
++ password to unlock the next set of features.");
+ }
+ else
+ {
+ if (config_entries)
+ printf ("\
+- Press enter to boot the selected OS, \'e\' to edit the\n\
+- commands before booting, or \'c\' for a command-line.");
++ Press enter to boot the selected OS, \'e\' to edit the\n\
++ commands before booting, or \'c\' for a command-line.");
+ else
+ printf ("\
+- Press \'b\' to boot, \'e\' to edit the selected command in the\n\
+- boot sequence, \'c\' for a command-line, \'o\' to open a new line\n\
+- after (\'O\' for before) the selected line, \'d\' to remove the\n\
+- selected line, or escape to go back to the main menu.");
++ Press \'b\' to boot, \'e\' to edit the selected command in the\n\
++ boot sequence, \'c\' for a command-line, \'o\' to open a new line\n\
++ after (\'O\' for before) the selected line, \'d\' to remove the\n\
++ selected line, or escape to go back to the main menu.");
+ }
+
+ if (current_term->flags & TERM_DUMB)
+ grub_printf ("\n\nThe selected entry is %d ", entryno);
+ else
+- print_entries (3, 12, first_entry, entryno, menu_entries);
++ print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries);
+ }
+
+ /* XX using RT clock now, need to initialize value */
+@@ -358,10 +381,10 @@ restart:
+ entryno, grub_timeout);
+ else
+ {
+- gotoxy (3, 22);
+- grub_printf ("The highlighted entry will be booted automatically in %d seconds. ",
++ gotoxy (3 + col_start, 10 + box_size + row_start);
++ grub_printf (" The highlighted entry will be booted automatically in %d seconds. ",
+ grub_timeout);
+- gotoxy (74, 4 + entryno);
++ gotoxy ((col_end - 6), 4 + entryno + row_start);
+ }
+
+ grub_timeout--;
+@@ -387,12 +410,12 @@ restart:
+ if (current_term->flags & TERM_DUMB)
+ grub_putchar ('\r');
+ else
+- gotoxy (3, 22);
++ gotoxy (3 + col_start, 10 + box_size + row_start);
+ printf (" ");
+ grub_timeout = -1;
+ fallback_entryno = -1;
+ if (! (current_term->flags & TERM_DUMB))
+- gotoxy (74, 4 + entryno);
++ gotoxy ((col_end - 6), 4 + entryno + row_start);
+ }
+
+ /* We told them above (at least in SUPPORT_SERIAL) to use
+@@ -408,12 +431,12 @@ restart:
+ {
+ if (entryno > 0)
+ {
+- print_entry (4 + entryno, 0,
++ print_entry (4 + entryno + row_start, 0,
+ get_entry (menu_entries,
+ first_entry + entryno,
+ 0));
+ entryno--;
+- print_entry (4 + entryno, 1,
++ print_entry (4 + entryno + row_start, 1,
+ get_entry (menu_entries,
+ first_entry + entryno,
+ 0));
+@@ -421,7 +444,7 @@ restart:
+ else if (first_entry > 0)
+ {
+ first_entry--;
+- print_entries (3, 12, first_entry, entryno,
++ print_entries (3 + row_start, box_size, first_entry, entryno,
+ menu_entries);
+ }
+ }
+@@ -433,29 +456,29 @@ restart:
+ entryno++;
+ else
+ {
+- if (entryno < 11)
++ if (entryno < (box_size - 1))
+ {
+- print_entry (4 + entryno, 0,
++ print_entry (4 + entryno + row_start, 0,
+ get_entry (menu_entries,
+ first_entry + entryno,
+ 0));
+ entryno++;
+- print_entry (4 + entryno, 1,
++ print_entry (4 + entryno + row_start, 1,
+ get_entry (menu_entries,
+ first_entry + entryno,
+ 0));
+ }
+- else if (num_entries > 12 + first_entry)
++ else if (num_entries > box_size + first_entry)
+ {
+ first_entry++;
+- print_entries (3, 12, first_entry, entryno, menu_entries);
++ print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries);
+ }
+ }
+ }
+ else if (c == 7)
+ {
+ /* Page Up */
+- first_entry -= 12;
++ first_entry -= box_size;
+ if (first_entry < 0)
+ {
+ entryno += first_entry;
+@@ -463,20 +486,20 @@ restart:
+ if (entryno < 0)
+ entryno = 0;
+ }
+- print_entries (3, 12, first_entry, entryno, menu_entries);
++ print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries);
+ }
+ else if (c == 3)
+ {
+ /* Page Down */
+- first_entry += 12;
++ first_entry += box_size;
+ if (first_entry + entryno + 1 >= num_entries)
+ {
+- first_entry = num_entries - 12;
++ first_entry = num_entries - box_size;
+ if (first_entry < 0)
+ first_entry = 0;
+ entryno = num_entries - first_entry - 1;
+ }
+- print_entries (3, 12, first_entry, entryno, menu_entries);
++ print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries);
+ }
+
+ if (config_entries)
+@@ -489,7 +512,7 @@ restart:
+ if ((c == 'd') || (c == 'o') || (c == 'O'))
+ {
+ if (! (current_term->flags & TERM_DUMB))
+- print_entry (4 + entryno, 0,
++ print_entry (4 + entryno + row_start, 0,
+ get_entry (menu_entries,
+ first_entry + entryno,
+ 0));
+@@ -537,7 +560,7 @@ restart:
+
+ if (entryno >= num_entries)
+ entryno--;
+- if (first_entry && num_entries < 12 + first_entry)
++ if (first_entry && num_entries < box_size + first_entry)
+ first_entry--;
+ }
+
+@@ -549,7 +572,7 @@ restart:
+ grub_printf ("\n");
+ }
+ else
+- print_entries (3, 12, first_entry, entryno, menu_entries);
++ print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries);
+ }
+
+ cur_entry = menu_entries;
+@@ -570,7 +593,7 @@ restart:
+ if (current_term->flags & TERM_DUMB)
+ grub_printf ("\r ");
+ else
+- gotoxy (1, 21);
++ gotoxy (1 + col_start, 9 + box_size + row_start);
+
+ /* Wipe out the previously entered password */
+ grub_memset (entered, 0, sizeof (entered));
+@@ -651,7 +674,10 @@ restart:
+ *(new_heap++) = 0;
+
+ if (config_entries)
+- run_menu (heap, NULL, new_num_entries, new_heap, 0);
++ {
++ current_entryno = first_entry + entryno;
++ run_menu (heap, NULL, new_num_entries, new_heap, 0);
++ }
+ else
+ {
+ cls ();
+@@ -714,6 +740,15 @@ restart:
+
+ cls ();
+ setcursor (1);
++ /* if our terminal needed initialization, we should shut it down
++ * before booting the kernel, but we want to save what it was so
++ * we can come back if needed */
++ prev_term = current_term;
++ if (current_term->shutdown)
++ {
++ current_term->shutdown();
++ current_term = term_table; /* assumption: console is first */
++ }
+
+ while (1)
+ {
+@@ -727,7 +762,8 @@ restart:
+ cur_entry = get_entry (config_entries, first_entry + entryno, 1);
+
+ /* Set CURRENT_ENTRYNO for the command "savedefault". */
+- current_entryno = first_entry + entryno;
++ if (config_entries)
++ current_entryno = first_entry + entryno;
+
+ if (run_script (cur_entry, heap))
+ {
+@@ -748,6 +784,13 @@ restart:
+ break;
+ }
+
++ /* if we get back here, we should go back to what our term was before */
++ current_term = prev_term;
++ if (current_term->startup)
++ /* if our terminal fails to initialize, fall back to console since
++ * it should always work */
++ if (current_term->startup() == 0)
++ current_term = term_table; /* we know that console is first */
+ show_menu = 1;
+ goto restart;
+ }
+@@ -891,8 +934,18 @@ cmain (void)
+ len = grub_read (buf, sizeof (buf));
+ if (len > 0)
+ {
++ char *tmp;
++ char *def;
+ buf[sizeof (buf) - 1] = 0;
+- safe_parse_maxint (&p, &saved_entryno);
++
++ if((tmp = grub_strstr(p, ":")) != NULL)
++ {
++ *tmp++;
++ grub_memcpy(&def, &tmp, sizeof(p));
++ }else
++ grub_memcpy(&def, &p, sizeof(p));
++
++ safe_parse_maxint (&def, &saved_entryno);
+ }
+
+ grub_close ();
+@@ -1050,6 +1103,16 @@ cmain (void)
+ while (is_preset);
+ }
+
++ /* go ahead and make sure the terminal is setup */
++ if (current_term->startup)
++ {
++ /* If initialization fails, go back to default terminal */
++ if (current_term->startup() == 0)
++ {
++ current_term = term_table;
++ }
++ }
++
+ if (! num_entries)
+ {
+ /* If no acceptable config file, goto command-line, starting
+--- a/stage2/term.h
++++ b/stage2/term.h
+@@ -60,6 +60,8 @@ struct term_entry
+ const char *name;
+ /* The feature flags defined above. */
+ unsigned long flags;
++ /* Default for maximum number of lines if not specified */
++ unsigned short max_lines;
+ /* Put a character. */
+ void (*putchar) (int c);
+ /* Check if any input character is available. */
+@@ -79,6 +81,10 @@ struct term_entry
+ void (*setcolor) (int normal_color, int highlight_color);
+ /* Turn on/off the cursor. */
+ int (*setcursor) (int on);
++ /* function to start a terminal */
++ int (*startup) (void);
++ /* function to use to shutdown a terminal */
++ void (*shutdown) (void);
+ };
+
+ /* This lists up available terminals. */
+@@ -124,4 +130,24 @@ void hercules_setcolor (int normal_color
+ int hercules_setcursor (int on);
+ #endif
+
++#ifdef SUPPORT_GRAPHICS
++extern int foreground, background, window_border, graphics_inited, saved_videomode;
++
++void graphics_set_splash(char *splashfile);
++int set_videomode(int mode);
++int get_videomode(void);
++void graphics_putchar (int c);
++int graphics_getxy(void);
++void graphics_gotoxy(int x, int y);
++void graphics_cls(void);
++void graphics_setcolorstate (color_state state);
++void graphics_setcolor (int normal_color, int highlight_color);
++int graphics_setcursor (int on);
++int graphics_init(void);
++void graphics_end(void);
++
++int hex(int v);
++void graphics_set_palette(int idx, int red, int green, int blue);
++#endif /* SUPPORT_GRAPHICS */
++
+ #endif /* ! GRUB_TERM_HEADER */
+--- a/THANKS
++++ b/THANKS
+@@ -121,3 +121,4 @@ Vesa Jaaskelainen <jaaskela@tietomyrsky.
+ Yedidyah Bar-David <didi@post.tau.ac.il>
+ Yury V. Umanets <umka@namesys.com>
+ Yuri Zaporogets <yuriz@ukr.net>
++Vitaly Fertman <vitaly@namesys.com>
+--- a/util/grub-install.in
++++ b/util/grub-install.in
+@@ -81,6 +81,50 @@ Report bugs to <bug-grub@gnu.org>.
+ EOF
+ }
+
++# Usage: getraid_mdadm mddevice
++# Routine to find a physical device from an md device
++# If found, the first grub BIOS device (from device.map) is returned
++# If no BIOS drives match the RAID devices, the first device returned
++# from mdadm -D is returned
++getraid_mdadm() {
++ device=$1
++ mdadm=$(mdadm -D "$device") || {
++ echo "$PROG: mdadm -D $device failed" >&2
++ exit 1
++ }
++ eval "$(
++ echo "$mdadm" | awk '
++ $1 == "Number" && $2 == "Major" { start = 1; next }
++ $1 == "UUID" { print "uuid=" $3; start = 0; next }
++ !start { next }
++ $2 == 0 && $3 == 0 { next }
++ { devices = devices "\n" $NF }
++ END { print "devices='\''" devices "'\''" }
++ '
++ )"
++
++ # Convert RAID devices list into a list of disks
++ tmp_disks=`echo "$devices" | sed -e 's%\([sh]d[a-z]\)[0-9]*$%\1%' \
++ -e 's%\(d[0-9]*\)p[0-9]*$%\1%' \
++ -e 's%\(fd[0-9]*\)$%\1%' \
++ -e 's%/part[0-9]*$%/disc%' \
++ -e 's%\(c[0-7]d[0-9]*\).*$%\1%' \
++ -e '/^$/d' |
++ sed -n '1h;2,$H;${g;s/\n/|/g;p}'`
++
++ # Find first BIOS disk that's a member of the RAID array
++ # Default to first RAID member if no tmp_disks are BIOS devices
++ set -- `egrep $tmp_disks $device_map | \
++ sort | \
++ sed -n 1p `
++ device=${2:-${tmp_disks%%|*}}
++
++ # Return first partition on BIOS disk that's part of the RAID
++ echo "$devices" | \
++ sed -n "\:${device}:p" | \
++ sed -n 1p
++}
++
+ # Usage: convert os_device
+ # Convert an OS device to the corresponding GRUB drive.
+ # This part is OS-specific.
+@@ -96,6 +140,10 @@ convert () {
+ # Break the device name into the disk part and the partition part.
+ case "$host_os" in
+ linux*)
++ # Find an actual physical device if we're passed a RAID device
++ case $1 in
++ /dev/md*) set -- `getraid_mdadm $1`
++ esac
+ tmp_disk=`echo "$1" | sed -e 's%\([sh]d[a-z]\)[0-9]*$%\1%' \
+ -e 's%\(d[0-9]*\)p[0-9]*$%\1%' \
+ -e 's%\(fd[0-9]*\)$%\1%' \
+@@ -112,8 +160,8 @@ convert () {
+ tmp_disk=`echo "$1" | sed 's%\([sh]d[0-9]*\).*%\1%'`
+ tmp_part=`echo "$1" | sed "s%$tmp_disk%%"` ;;
+ freebsd* | kfreebsd*-gnu)
+- tmp_disk=`echo "$1" | sed 's%r\{0,1\}\([saw]d[0-9]*\).*$%r\1%' \
+- | sed 's%r\{0,1\}\(da[0-9]*\).*$%r\1%'`
++ tmp_disk=`echo "$1" | sed 's%r\{0,1\}\([saw]d[0-9]*\).*$%\1%' \
++ | sed 's%r\{0,1\}\(da[0-9]*\).*$%\1%'`
+ tmp_part=`echo "$1" \
+ | sed "s%.*/r\{0,1\}[saw]d[0-9]\(s[0-9]*[a-h]\)%\1%" \
+ | sed "s%.*/r\{0,1\}da[0-9]\(s[0-9]*[a-h]\)%\1%"`
+@@ -131,7 +179,7 @@ convert () {
+
+ # Get the drive name.
+ tmp_drive=`grep -v '^#' $device_map | grep "$tmp_disk *$" \
+- | sed 's%.*\(([hf]d[0-9][a-g0-9,]*)\).*%\1%'`
++ | sed 's%.*\(([hf]d[0-9][a-z0-9,]*)\).*%\1%'`
+
+ # If not found, print an error message and exit.
+ if test "x$tmp_drive" = x; then
+@@ -148,13 +196,13 @@ convert () {
+ gnu*)
+ if echo $tmp_part | grep "^s" >/dev/null; then
+ tmp_pc_slice=`echo $tmp_part \
+- | sed "s%s\([0-9]*\)[a-g]*$%\1%"`
++ | sed "s%s\([0-9]*\)[a-z]*$%\1%"`
+ tmp_drive=`echo "$tmp_drive" \
+ | sed "s%)%,\`expr "$tmp_pc_slice" - 1\`)%"`
+ fi
+- if echo $tmp_part | grep "[a-g]$" >/dev/null; then
++ if echo $tmp_part | grep "[a-z]$" >/dev/null; then
+ tmp_bsd_partition=`echo "$tmp_part" \
+- | sed "s%[^a-g]*\([a-g]\)$%\1%"`
++ | sed "s%[^a-z]*\([a-z]\)$%\1%"`
+ tmp_drive=`echo "$tmp_drive" \
+ | sed "s%)%,$tmp_bsd_partition)%"`
+ fi
+@@ -336,6 +384,10 @@ else
+ # Create a safe temporary file.
+ test -n "$mklog" && log_file=`$mklog`
+
++ # Before all invocations of the grub shell, call sync to make sure
++ # the raw device is in sync with any bufferring in filesystems.
++ sync
++
+ $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
+ quit
+ EOF
+@@ -450,6 +502,24 @@ rm -f $log_file
+ # Create a safe temporary file.
+ test -n "$mklog" && log_file=`$mklog`
+
++# Sync to prevent GRUB from not finding stage files (notably, on XFS)
++sync
++
++# XFS needs special magic
++xfs_frozen=false
++if which xfs_freeze > /dev/null ; then
++ cat << EOF
++Due to a bug in xfs_freeze, the following command might produce a segmentation
++fault when ${grubdir} is not in an XFS filesystem. This error is harmless and
++can be ignored.
++EOF
++ if xfs_freeze -f ${grubdir} ; then xfs_frozen=true ; fi
++fi
++
++# Before all invocations of the grub shell, call sync to make sure
++# the raw device is in sync with any bufferring in filesystems.
++sync
++
+ # Now perform the installation.
+ $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
+ root $root_drive
+@@ -457,6 +527,10 @@ setup $force_lba --stage2=$grubdir/stage
+ quit
+ EOF
+
++if ${xfs_frozen} ; then
++ xfs_freeze -u ${grubdir}
++fi
++
+ if grep "Error [0-9]*: " $log_file >/dev/null || test $debug = yes; then
+ cat $log_file 1>&2
+ exit 1
diff --git a/package/grub/patches/020-ext4_support.patch b/package/grub/patches/020-ext4_support.patch
new file mode 100644
index 000000000..06cd2c261
--- /dev/null
+++ b/package/grub/patches/020-ext4_support.patch
@@ -0,0 +1,267 @@
+--- a/stage2/fsys_ext2fs.c
++++ b/stage2/fsys_ext2fs.c
+@@ -51,6 +51,9 @@ typedef unsigned int __u32;
+ #define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
+ #define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
+
++/* Inode flags */
++#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
++
+ /* include/linux/ext2_fs.h */
+ struct ext2_super_block
+ {
+@@ -191,6 +194,42 @@ struct ext2_dir_entry
+ #define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
+ ~EXT2_DIR_ROUND)
+
++/* linux/ext4_fs_extents.h */
++/*
++ * This is the extent on-disk structure.
++ * It's used at the bottom of the tree.
++ */
++struct ext4_extent {
++ __u32 ee_block; /* first logical block extent covers */
++ __u16 ee_len; /* number of blocks covered by extent */
++ __u16 ee_start_hi; /* high 16 bits of physical block */
++ __u32 ee_start; /* low 32 bits of physical block */
++};
++
++/*
++ * This is index on-disk structure.
++ * It's used at all the levels except the bottom.
++ */
++struct ext4_extent_idx {
++ __u32 ei_block; /* index covers logical blocks from 'block' */
++ __u32 ei_leaf; /* pointer to the physical block of the next *
++ * level. leaf or next index could be there */
++ __u16 ei_leaf_hi; /* high 16 bits of physical block */
++ __u16 ei_unused;
++};
++
++/*
++ * Each block (leaves and indexes), even inode-stored has header.
++ */
++struct ext4_extent_header {
++ __u16 eh_magic; /* probably will support different formats */
++ __u16 eh_entries; /* number of valid entries */
++ __u16 eh_max; /* capacity of store in entries */
++ __u16 eh_depth; /* has tree real underlying blocks? */
++ __u32 eh_generation; /* generation of the tree */
++};
++
++#define EXT4_EXT_MAGIC 0xf30a
+
+ /* ext2/super.c */
+ #define log2(n) ffz(~(n))
+@@ -279,6 +318,27 @@ ext2_rdfsb (int fsblock, int buffer)
+ EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer);
+ }
+
++/* Walk through extents index tree to find the good leaf */
++static struct ext4_extent_header *
++ext4_recurse_extent_index(struct ext4_extent_header *extent_block, int logical_block)
++{
++ int i;
++ struct ext4_extent_idx *index = (struct ext4_extent_idx *) (extent_block + 1);
++ if (extent_block->eh_magic != EXT4_EXT_MAGIC)
++ return NULL;
++ if (extent_block->eh_depth == 0)
++ return extent_block;
++ for (i = 0; i < extent_block->eh_entries; i++)
++ {
++ if (logical_block < index[i].ei_block)
++ break;
++ }
++ if (i == 0 || !ext2_rdfsb(index[i-1].ei_leaf, DATABLOCK1))
++ return NULL;
++ return (ext4_recurse_extent_index((struct ext4_extent_header *) DATABLOCK1, logical_block));
++}
++
++
+ /* from
+ ext2/inode.c:ext2_bmap()
+ */
+@@ -287,7 +347,6 @@ ext2_rdfsb (int fsblock, int buffer)
+ static int
+ ext2fs_block_map (int logical_block)
+ {
+-
+ #ifdef E2DEBUG
+ unsigned char *i;
+ for (i = (unsigned char *) INODE;
+@@ -308,82 +367,106 @@ ext2fs_block_map (int logical_block)
+ printf ("logical block %d\n", logical_block);
+ #endif /* E2DEBUG */
+
+- /* if it is directly pointed to by the inode, return that physical addr */
+- if (logical_block < EXT2_NDIR_BLOCKS)
++ if (!(INODE->i_flags & EXT4_EXTENTS_FL))
+ {
+-#ifdef E2DEBUG
+- printf ("returning %d\n", (unsigned char *) (INODE->i_block[logical_block]));
+- printf ("returning %d\n", INODE->i_block[logical_block]);
+-#endif /* E2DEBUG */
+- return INODE->i_block[logical_block];
+- }
+- /* else */
+- logical_block -= EXT2_NDIR_BLOCKS;
+- /* try the indirect block */
+- if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK))
+- {
+- if (mapblock1 != 1
+- && !ext2_rdfsb (INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1))
+- {
+- errnum = ERR_FSYS_CORRUPT;
+- return -1;
+- }
+- mapblock1 = 1;
+- return ((__u32 *) DATABLOCK1)[logical_block];
+- }
+- /* else */
+- logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK);
+- /* now try the double indirect block */
+- if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)))
+- {
+- int bnum;
+- if (mapblock1 != 2
+- && !ext2_rdfsb (INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1))
+- {
+- errnum = ERR_FSYS_CORRUPT;
+- return -1;
+- }
+- mapblock1 = 2;
+- if ((bnum = (((__u32 *) DATABLOCK1)
+- [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)]))
+- != mapblock2
+- && !ext2_rdfsb (bnum, DATABLOCK2))
+- {
+- errnum = ERR_FSYS_CORRUPT;
+- return -1;
+- }
+- mapblock2 = bnum;
++ /* if it is directly pointed to by the inode, return that physical addr */
++ if (logical_block < EXT2_NDIR_BLOCKS)
++ {
++#ifdef E2DEBUG
++ printf ("returning %d\n", (unsigned char *) (INODE->i_block[logical_block]));
++ printf ("returning %d\n", INODE->i_block[logical_block]);
++#endif /* E2DEBUG */
++ return INODE->i_block[logical_block];
++ }
++ /* else */
++ logical_block -= EXT2_NDIR_BLOCKS;
++ /* try the indirect block */
++ if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK))
++ {
++ if (mapblock1 != 1 && !ext2_rdfsb (INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1))
++ {
++ errnum = ERR_FSYS_CORRUPT;
++ return -1;
++ }
++ mapblock1 = 1;
++ return ((__u32 *) DATABLOCK1)[logical_block];
++ }
++ /* else */
++ logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK);
++ /* now try the double indirect block */
++ if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)))
++ {
++ int bnum;
++ if (mapblock1 != 2 && !ext2_rdfsb (INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1))
++ {
++ errnum = ERR_FSYS_CORRUPT;
++ return -1;
++ }
++ mapblock1 = 2;
++ if ((bnum = (((__u32 *) DATABLOCK1)
++ [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)]))
++ != mapblock2
++ && !ext2_rdfsb (bnum, DATABLOCK2))
++ {
++ errnum = ERR_FSYS_CORRUPT;
++ return -1;
++ }
++ mapblock2 = bnum;
++ return ((__u32 *) DATABLOCK2)
++ [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
++ }
++ /* else */
++ mapblock2 = -1;
++ logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
++ if (mapblock1 != 3
++ && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1))
++ {
++ errnum = ERR_FSYS_CORRUPT;
++ return -1;
++ }
++ mapblock1 = 3;
++ if (!ext2_rdfsb (((__u32 *) DATABLOCK1)
++ [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
++ * 2)],
++ DATABLOCK2))
++ {
++ errnum = ERR_FSYS_CORRUPT;
++ return -1;
++ }
++ if (!ext2_rdfsb (((__u32 *) DATABLOCK2)
++ [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
++ & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)],
++ DATABLOCK2))
++ {
++ errnum = ERR_FSYS_CORRUPT;
++ return -1;
++ }
++
+ return ((__u32 *) DATABLOCK2)
+- [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
++ [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
+ }
+- /* else */
+- mapblock2 = -1;
+- logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
+- if (mapblock1 != 3
+- && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1))
+- {
+- errnum = ERR_FSYS_CORRUPT;
+- return -1;
+- }
+- mapblock1 = 3;
+- if (!ext2_rdfsb (((__u32 *) DATABLOCK1)
+- [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
+- * 2)],
+- DATABLOCK2))
+- {
+- errnum = ERR_FSYS_CORRUPT;
+- return -1;
+- }
+- if (!ext2_rdfsb (((__u32 *) DATABLOCK2)
+- [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
+- & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)],
+- DATABLOCK2))
++ /* inode is in extents format */
++ else
+ {
++ int i;
++ struct ext4_extent_header *extent_hdr =
++ ext4_recurse_extent_index((struct ext4_extent_header *) INODE->i_block, logical_block);
++ struct ext4_extent *extent = (struct ext4_extent *) (extent_hdr + 1);
++ if ( extent_hdr == NULL || extent_hdr->eh_magic != EXT4_EXT_MAGIC)
++ {
++ errnum = ERR_FSYS_CORRUPT;
++ return -1;
++ }
++ for (i = 0; i<extent_hdr->eh_entries; i++)
++ {
++ if (extent[i].ee_block <= logical_block && logical_block < extent[i].ee_block + extent[i].ee_len && !(extent[i].ee_len>>15))
++ return (logical_block - extent[i].ee_block + extent[i].ee_start);
++ }
++ /* We should not arrive here */
++
+ errnum = ERR_FSYS_CORRUPT;
+ return -1;
+ }
+- return ((__u32 *) DATABLOCK2)
+- [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
+ }
+
+ /* preconditions: all preconds of ext2fs_block_map */
diff --git a/package/grub/patches/030-add-stage2-ldscripts.patch b/package/grub/patches/030-add-stage2-ldscripts.patch
new file mode 100644
index 000000000..aff7ed466
--- /dev/null
+++ b/package/grub/patches/030-add-stage2-ldscripts.patch
@@ -0,0 +1,77 @@
+From 8858927ddc6797489cad322fc2d2134aeae543cd Mon Sep 17 00:00:00 2001
+From: Arnaud Lacombe <lacombar@gmail.com>
+Date: Sun, 11 Dec 2011 16:44:02 -0500
+Subject: [PATCH] add-stage2-ldscripts
+
+---
+ stage2/Makefile.am | 2 +-
+ stage2/Makefile.in | 2 +-
+ stage2/stage2.ldscripts | 30 ++++++++++++++++++++++++++++++
+ 3 files changed, 32 insertions(+), 2 deletions(-)
+ create mode 100644 stage2/stage2.ldscripts
+
+diff --git a/stage2/Makefile.am b/stage2/Makefile.am
+index f8e6d42..ea28a4d 100644
+--- a/stage2/Makefile.am
++++ b/stage2/Makefile.am
+@@ -55,7 +55,7 @@ noinst_PROGRAMS = pre_stage2.exec start.exec start_eltorito.exec \
+ endif
+ MOSTLYCLEANFILES = $(noinst_PROGRAMS)
+
+-PRE_STAGE2_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8200
++PRE_STAGE2_LINK = -nostdlib -Wl,-N -Wl,-Tstage2.ldscripts
+ START_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8000
+ NBLOADER_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,0
+ PXELOADER_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,7C00
+diff --git a/stage2/Makefile.in b/stage2/Makefile.in
+index d0062bd..7bee2d5 100644
+--- a/stage2/Makefile.in
++++ b/stage2/Makefile.in
+@@ -468,7 +468,7 @@ libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \
+ @DISKLESS_SUPPORT_FALSE@noinst_DATA = pre_stage2 start start_eltorito
+ @DISKLESS_SUPPORT_TRUE@noinst_DATA = pre_stage2 start start_eltorito nbloader pxeloader diskless
+ MOSTLYCLEANFILES = $(noinst_PROGRAMS)
+-PRE_STAGE2_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8200
++PRE_STAGE2_LINK = -nostdlib -Wl,-N -Wl,-Tstage2.ldscripts
+ START_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8000
+ NBLOADER_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,0
+ PXELOADER_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,7C00
+diff --git a/stage2/stage2.ldscripts b/stage2/stage2.ldscripts
+new file mode 100644
+index 0000000..2c8b8e1
+--- /dev/null
++++ b/stage2/stage2.ldscripts
+@@ -0,0 +1,30 @@
++/* Script for -N: mix text and data on same page; don't align data */
++OUTPUT_FORMAT("elf32-i386", "elf32-i386",
++ "elf32-i386")
++OUTPUT_ARCH(i386)
++ENTRY(_start)
++SECTIONS
++{
++ . = 0x8200;
++ .text :
++ {
++ _start = .;
++ *(.text .text.* )
++ }
++ .rodata : { *(.rodata .rodata.* ) }
++ /* Adjust the address for the data segment. We want to adjust up to
++ the same address within the page on the next page up. */
++ . = .;
++ .data : { *(.data .data.* ) }
++ __bss_start = .;
++ .bss :
++ {
++ *(.bss .bss.* )
++ *(COMMON)
++ . = ALIGN(. != 0 ? 32 / 8 : 1);
++ }
++ . = ALIGN(32 / 8);
++ . = ALIGN(32 / 8);
++ _end = .; PROVIDE (end = .);
++ .comment 0 : { *(.comment) }
++}
+--
+1.7.6.153.g78432
+
diff --git a/package/grub/patches/040-automake-compat.patch b/package/grub/patches/040-automake-compat.patch
new file mode 100644
index 000000000..da13cea7e
--- /dev/null
+++ b/package/grub/patches/040-automake-compat.patch
@@ -0,0 +1,41 @@
+--- a/stage1/Makefile.am
++++ b/stage1/Makefile.am
+@@ -1,7 +1,7 @@
+ pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
+-nodist_pkglib_DATA = stage1
++nodist_pkgdata_DATA = stage1
+
+-CLEANFILES = $(nodist_pkglib_DATA)
++CLEANFILES = $(nodist_pkgdata_DATA)
+
+ # We can't use builtins or standard includes.
+ AM_CCASFLAGS = $(STAGE1_CFLAGS) -fno-builtin -nostdinc
+--- a/stage2/Makefile.am
++++ b/stage2/Makefile.am
+@@ -32,7 +32,7 @@ pkglibdir = $(libdir)/$(PACKAGE)/$(host_
+ EXTRA_PROGRAMS = nbloader.exec pxeloader.exec diskless.exec
+
+ if DISKLESS_SUPPORT
+-pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
++pkgdata_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
+ ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \
+ reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5 \
+ nbgrub pxegrub
+@@ -43,7 +43,7 @@ noinst_PROGRAMS = pre_stage2.exec start.
+ reiserfs_stage1_5.exec ufs2_stage1_5.exec vstafs_stage1_5.exec \
+ xfs_stage1_5.exec nbloader.exec pxeloader.exec diskless.exec
+ else
+-pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
++pkgdata_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
+ ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \
+ reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5
+ noinst_DATA = pre_stage2 start start_eltorito
+@@ -112,7 +112,7 @@ else
+ BUILT_SOURCES = stage2_size.h
+ endif
+
+-CLEANFILES = $(pkglib_DATA) $(noinst_DATA) $(BUILT_SOURCES)
++CLEANFILES = $(pkgdata_DATA) $(noinst_DATA) $(BUILT_SOURCES)
+
+ stage2_size.h: pre_stage2
+ -rm -f stage2_size.h
diff --git a/package/grub/patches/100-add_configure_macros.patch b/package/grub/patches/100-add_configure_macros.patch
new file mode 100644
index 000000000..476f778bc
--- /dev/null
+++ b/package/grub/patches/100-add_configure_macros.patch
@@ -0,0 +1,11 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -56,6 +56,8 @@ fi
+
+ AC_CHECK_TOOL(CC, gcc)
+ AC_PROG_CC
++AM_PROG_CC_C_O
++AM_PROG_AS
+ # We need this for older versions of Autoconf.
+ _AM_DEPENDENCIES(CC)
+
diff --git a/package/grub/patches/110-remove_configure_errors.patch b/package/grub/patches/110-remove_configure_errors.patch
new file mode 100644
index 000000000..f090aa975
--- /dev/null
+++ b/package/grub/patches/110-remove_configure_errors.patch
@@ -0,0 +1,38 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -177,26 +177,22 @@ grub_ASM_ABSOLUTE_WITHOUT_ASTERISK
+
+ grub_CHECK_START_SYMBOL
+ grub_CHECK_USCORE_START_SYMBOL
+-if test "x$grub_cv_check_start_symbol" != "xyes" \
+- -a "x$grub_cv_check_uscore_start_symbol" != "xyes"; then
+- AC_MSG_ERROR([Neither start nor _start is defined])
+-fi
+
+ grub_CHECK_USCORE_USCORE_BSS_START_SYMBOL
+ grub_CHECK_USCORE_EDATA_SYMBOL
+ grub_CHECK_EDATA_SYMBOL
+-if test "x$grub_cv_check_uscore_uscore_bss_start_symbol" != "xyes" \
+- -a "x$grub_cv_check_uscore_edata_symbol" != "xyes" \
+- -a "x$grub_cv_check_edata_symbol" != "xyes"; then
+- AC_MSG_ERROR([None of __bss_start, _edata, edata defined])
+-fi
++# if test "x$grub_cv_check_uscore_uscore_bss_start_symbol" != "xyes" \
++# -a "x$grub_cv_check_uscore_edata_symbol" != "xyes" \
++# -a "x$grub_cv_check_edata_symbol" != "xyes"; then
++# AC_MSG_ERROR([None of __bss_start, _edata, edata defined])
++# fi
+
+ grub_CHECK_END_SYMBOL
+ grub_CHECK_USCORE_END_SYMBOL
+-if test "x$grub_cv_check_end_symbol" != "xyes" \
+- -a "x$grub_cv_check_uscore_end_symbol" != "xyes"; then
+- AC_MSG_ERROR([Neither end nor _end is defined])
+-fi
++#if test "x$grub_cv_check_end_symbol" != "xyes" \
++# -a "x$grub_cv_check_uscore_end_symbol" != "xyes"; then
++# AC_MSG_ERROR([Neither end nor _end is defined])
++#fi
+
+ # Check for curses libraries.
+ AC_ARG_WITH(curses,
diff --git a/package/grub/patches/200-darwin_fixes.patch b/package/grub/patches/200-darwin_fixes.patch
new file mode 100644
index 000000000..c5c55a918
--- /dev/null
+++ b/package/grub/patches/200-darwin_fixes.patch
@@ -0,0 +1,48 @@
+--- a/stage2/asm.S
++++ b/stage2/asm.S
+@@ -95,14 +95,16 @@ VARIABLE(stage2_id)
+ VARIABLE(force_lba)
+ .byte 0
+ VARIABLE(version_string)
+- .string VERSION
++ .ascii VERSION
++ .byte 0
+ VARIABLE(config_file)
+ #ifndef STAGE1_5
+- .string "/boot/grub/menu.lst"
++ .ascii "/boot/grub/menu.lst"
+ #else /* STAGE1_5 */
+ .long 0xffffffff
+- .string "/boot/grub/stage2"
++ .ascii "/boot/grub/stage2"
+ #endif /* STAGE1_5 */
++ .byte 0
+
+ /*
+ * Leave some breathing room for the config file name.
+@@ -762,7 +764,9 @@ ENTRY(chain_stage1)
+ call EXT_C(prot_to_real)
+ .code16
+
+-#ifdef ABSOLUTE_WITHOUT_ASTERISK
++#ifdef __APPLE__
++ DATA32 ADDR32 ljmp offset
++#elif defined(ABSOLUTE_WITHOUT_ASTERISK)
+ DATA32 ADDR32 ljmp (offset)
+ #else
+ DATA32 ADDR32 ljmp *(offset)
+--- a/stage2/char_io.c
++++ b/stage2/char_io.c
+@@ -1345,5 +1345,12 @@ grub_strcpy (char *dest, const char *src
+ #ifndef GRUB_UTIL
+ # undef memcpy
+ /* GCC emits references to memcpy() for struct copies etc. */
++#ifdef __APPLE__
++void *memcpy (void *dest, const void *src, int n)
++{
++ return grub_memmove(dest, src, n);
++}
++#else
+ void *memcpy (void *dest, const void *src, int n) __attribute__ ((alias ("grub_memmove")));
+ #endif
++#endif
diff --git a/package/grub/patches/210-remove_inline_asm.patch b/package/grub/patches/210-remove_inline_asm.patch
new file mode 100644
index 000000000..8eb9fc2c9
--- /dev/null
+++ b/package/grub/patches/210-remove_inline_asm.patch
@@ -0,0 +1,14 @@
+--- a/stage2/fsys_iso9660.c
++++ b/stage2/fsys_iso9660.c
+@@ -83,10 +83,7 @@ iso9660_devread (int sector, int byte_of
+
+ sector += (byte_offset >> sector_size_lg2);
+ byte_offset &= (buf_geom.sector_size - 1);
+- asm volatile ("shl%L0 %1,%0"
+- : "=r"(sector)
+- : "Ic"((int8_t)(ISO_SECTOR_BITS - sector_size_lg2)),
+- "0"(sector));
++ sector <<= ISO_SECTOR_BITS - sector_size_lg2;
+
+ #if !defined(STAGE1_5)
+ if (disk_read_hook && debug)
diff --git a/package/grub2/Makefile b/package/grub2/Makefile
new file mode 100644
index 000000000..b606f54be
--- /dev/null
+++ b/package/grub2/Makefile
@@ -0,0 +1,51 @@
+#
+# Copyright (C) 2006-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=grub
+PKG_VERSION:=2.00
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@GNU/grub
+PKG_MD5SUM:=e927540b6eda8b024fb0391eeaa4091c
+
+PKG_HOST_ONLY:=1
+HOST_BUILD_PARALLEL:=1
+PKG_BUILD_DEPENDS:=grub2/host
+
+include $(INCLUDE_DIR)/host-build.mk
+include $(INCLUDE_DIR)/package.mk
+
+define Package/grub2
+ SUBMENU:=Boot Loaders
+ CATEGORY:=Utilities
+ SECTION:=utils
+ TITLE:=GRand Unified Bootloader
+ URL:=http://www.gnu.org/software/grub/
+ DEPENDS:=@TARGET_x86
+endef
+
+HOST_CONFIGURE_ARGS += \
+ --target=$(REAL_GNU_TARGET_NAME) \
+ --sbindir="$(STAGING_DIR_HOST)/bin" \
+ --disable-werror \
+ --disable-nls
+
+HOST_MAKE_FLAGS += \
+ TARGET_RANLIB=$(TARGET_RANLIB) \
+ LIBLZMA=$(STAGING_DIR_HOST)/lib/liblzma.a
+
+define Host/Configure
+ $(SED) 's,(RANLIB),(TARGET_RANLIB),' $(HOST_BUILD_DIR)/grub-core/Makefile.in
+ $(Host/Configure/Default)
+endef
+
+$(eval $(call HostBuild))
+$(eval $(call BuildPackage,grub2))
diff --git a/package/grub2/patches/100-grub_setup_root.patch b/package/grub2/patches/100-grub_setup_root.patch
new file mode 100644
index 000000000..7775b2a22
--- /dev/null
+++ b/package/grub2/patches/100-grub_setup_root.patch
@@ -0,0 +1,77 @@
+--- a/util/grub-setup.c
++++ b/util/grub-setup.c
+@@ -141,12 +141,11 @@ write_rootdev (char *core_img, grub_devi
+ static void
+ setup (const char *dir,
+ const char *boot_file, const char *core_file,
+- const char *dest, int force,
++ const char *root, const char *dest, int force,
+ int fs_probe, int allow_floppy)
+ {
+ char *boot_path, *core_path, *core_path_dev, *core_path_dev_full;
+ char *boot_img, *core_img;
+- char *root = 0;
+ size_t boot_size, core_size;
+ grub_uint16_t core_sectors;
+ grub_device_t root_dev = 0, dest_dev, core_dev;
+@@ -253,7 +252,10 @@ setup (const char *dir,
+
+ core_dev = dest_dev;
+
+- {
++ if (root)
++ root_dev = grub_device_open(root);
++
++ if (!root_dev) {
+ char **root_devices = grub_guess_root_devices (dir);
+ char **cur;
+ int found = 0;
+@@ -263,6 +265,8 @@ setup (const char *dir,
+ char *drive;
+ grub_device_t try_dev;
+
++ if (root_dev)
++ break;
+ drive = grub_util_get_grub_dev (*cur);
+ if (!drive)
+ continue;
+@@ -956,6 +960,8 @@ static struct argp_option options[] = {
+ N_("install even if problems are detected"), 0},
+ {"skip-fs-probe",'s',0, 0,
+ N_("do not probe for filesystems in DEVICE"), 0},
++ {"root-device", 'r', N_("DEVICE"), 0,
++ N_("use DEVICE as the root device"), 0},
+ {"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
+ {"allow-floppy", 'a', 0, 0,
+ /* TRANSLATORS: The potential breakage isn't limited to floppies but it's
+@@ -993,6 +999,7 @@ struct arguments
+ char *core_file;
+ char *dir;
+ char *dev_map;
++ char *root_dev;
+ int force;
+ int fs_probe;
+ int allow_floppy;
+@@ -1040,6 +1047,13 @@ argp_parser (int key, char *arg, struct
+ arguments->dev_map = xstrdup (arg);
+ break;
+
++ case 'r':
++ if (arguments->root_dev)
++ free (arguments->root_dev);
++
++ arguments->root_dev = xstrdup (arg);
++ break;
++
+ case 'f':
+ arguments->force = 1;
+ break;
+@@ -1172,7 +1186,7 @@ main (int argc, char *argv[])
+ setup (arguments.dir ? : DEFAULT_DIRECTORY,
+ arguments.boot_file ? : DEFAULT_BOOT_FILE,
+ arguments.core_file ? : DEFAULT_CORE_FILE,
+- dest_dev, arguments.force,
++ arguments.root_dev, dest_dev, arguments.force,
+ arguments.fs_probe, arguments.allow_floppy);
+
+ /* Free resources. */
diff --git a/package/hostap-driver/Makefile b/package/hostap-driver/Makefile
new file mode 100644
index 000000000..d08fd9c0a
--- /dev/null
+++ b/package/hostap-driver/Makefile
@@ -0,0 +1,117 @@
+#
+# Copyright (C) 2006-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=hostap-driver
+PKG_VERSION:=0.4.9
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://hostap.epitest.fi/releases/
+PKG_MD5SUM:=c7534dc040ab90218257a78488ecd378
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/hostap/Default
+ VERSION:=$(LINUX_VERSION)-$(BOARD)-$(PKG_RELEASE)
+ SUBMENU:=Wireless Drivers
+ URL:=http://hostap.epitest.fi/
+endef
+
+define KernelPackage/hostap/Default/description
+ Host AP is a driver for 802.11b wireless cards based on Intersil
+ Prism2/2.5/3 chipset. It supports so called Host AP mode that allows the
+ card to act as an IEEE 802.11 access point.
+endef
+
+
+define KernelPackage/hostap
+$(call KernelPackage/hostap/Default)
+ TITLE:=Host AP support for Prism2/2.5/3
+ DEPENDS:=@PCI_SUPPORT||PCMCIA_SUPPORT +kmod-lib80211 +wireless-tools
+ KCONFIG:=CONFIG_HOSTAP CONFIG_HOSTAP_FIRMWARE=y CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+ FILES:=$(LINUX_DIR)/drivers/net/wireless/hostap/hostap.ko
+ AUTOLOAD:=$(call AutoLoad,60,hostap)
+endef
+
+define KernelPackage/hostap/description
+$(call KernelPackage/hostap/Default/description)
+ This package contains the base Host AP driver code that is shared by
+ different hardware models. You will also need to enable support for
+ PLX/PCI/CS version of the driver to actually use the driver.
+endef
+
+
+define KernelPackage/hostap-cs
+$(call KernelPackage/hostap/Default)
+ TITLE:=Host AP driver for PCMCIA adaptors
+ DEPENDS:=@PCMCIA_SUPPORT +kmod-hostap +kmod-pcmcia-core
+ KCONFIG:=CONFIG_HOSTAP_CS
+ FILES:=$(LINUX_DIR)/drivers/net/wireless/hostap/hostap_cs.ko
+ AUTOLOAD:=$(call AutoLoad,60,hostap_cs)
+endef
+
+define KernelPackage/hostap-cs/description
+$(call KernelPackage/hostap/Default/description)
+ This package contains the Host AP driver for Prism2/2.5/3 PC cards.
+endef
+
+
+define KernelPackage/hostap-pci
+$(call KernelPackage/hostap/Default)
+ TITLE:=Host AP driver for PCI adaptors
+ DEPENDS:=@PCI_SUPPORT +kmod-hostap
+ KCONFIG:=CONFIG_HOSTAP_PCI
+ FILES:=$(LINUX_DIR)/drivers/net/wireless/hostap/hostap_pci.ko
+ AUTOLOAD:=$(call AutoLoad,60,hostap_pci)
+endef
+
+define KernelPackage/hostap-pci/description
+$(call KernelPackage/hostap/Default/description)
+ This package contains the Host AP driver for Prism2.5 PCI adaptors.
+endef
+
+
+define KernelPackage/hostap-plx
+$(call KernelPackage/hostap/Default)
+ TITLE:=Host AP driver for PLX9052 based PCI adaptors
+ DEPENDS:=@PCI_SUPPORT +kmod-hostap
+ KCONFIG:=CONFIG_HOSTAP_PLX
+ FILES:=$(LINUX_DIR)/drivers/net/wireless/hostap/hostap_plx.ko
+ AUTOLOAD:=$(call AutoLoad,60,hostap_plx)
+endef
+
+define KernelPackage/hostap-plx/description
+$(call KernelPackage/hostap/Default/description)
+ This package contains the Host AP driver for Prism2/2.5/3 in PLX9052
+ based PCI adaptors.
+endef
+
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+endef
+
+define Build/Configure
+
+endef
+
+define Build/Compile
+
+endef
+
+define KernelPackage/hostap/install
+ $(INSTALL_DIR) $(1)/lib/wifi
+ $(INSTALL_DATA) ./files/lib/wifi/hostap.sh $(1)/lib/wifi
+endef
+
+$(eval $(call KernelPackage,hostap))
+$(eval $(call KernelPackage,hostap-cs))
+$(eval $(call KernelPackage,hostap-pci))
+$(eval $(call KernelPackage,hostap-plx))
diff --git a/package/hostap-driver/files/lib/wifi/hostap.sh b/package/hostap-driver/files/lib/wifi/hostap.sh
new file mode 100755
index 000000000..62d2e7e47
--- /dev/null
+++ b/package/hostap-driver/files/lib/wifi/hostap.sh
@@ -0,0 +1,270 @@
+#!/bin/sh
+append DRIVERS "prism2"
+
+find_prism2_phy() {
+ local device="$1"
+
+ local macaddr="$(config_get "$device" macaddr | tr 'A-Z' 'a-z')"
+ config_get phy "$device" phy
+ [ -z "$phy" -a -n "$macaddr" ] && {
+ cd /proc/net/hostap
+ for phy in $(ls -d wlan* 2>&-); do
+ [ "$macaddr" = "$(cat /sys/class/net/${phy}/address)" ] || continue
+ config_set "$device" phy "$phy"
+ break
+ done
+ config_get phy "$device" phy
+ }
+ [ -n "$phy" -a -d "/proc/net/hostap/$phy" ] || {
+ echo "phy for wifi device $1 not found"
+ return 1
+ }
+ [ -z "$macaddr" ] && {
+ config_set "$device" macaddr "$(cat /sys/class/net/${phy}/address)"
+ }
+ return 0
+}
+
+scan_prism2() {
+ local device="$1"
+ local mainvif
+ local wds
+
+ [ ${device%[0-9]} = "wlan" ] && config_set "$device" phy "$device" || find_prism2_phy "$device" || {
+ config_unset "$device" vifs
+ return 0
+ }
+ config_get phy "$device" phy
+
+ config_get vifs "$device" vifs
+ local _c=0
+ for vif in $vifs; do
+ config_get_bool disabled "$vif" disabled 0
+ [ $disabled = 0 ] || continue
+
+ config_get mode "$vif" mode
+ case "$mode" in
+ adhoc|sta|ap|monitor)
+ # Only one vif is allowed on AP, station, Ad-hoc or monitor mode
+ [ -z "$mainvif" ] && {
+ mainvif="$vif"
+ config_set "$vif" ifname "$phy"
+ }
+ ;;
+ wds)
+ config_get ssid "$vif" ssid
+ [ -z "$ssid" ] && continue
+ config_set "$vif" ifname "${phy}wds${_c}"
+ _c=$(($_c + 1))
+ addr="$ssid"
+ ${addr:+append wds "$vif"}
+ ;;
+ *) echo "$device($vif): Invalid mode, ignored."; continue;;
+ esac
+ done
+ config_set "$device" vifs "${mainvif:+$mainvif }${wds:+$wds}"
+}
+
+disable_prism2() (
+ local device="$1"
+
+ find_prism2_phy "$device" || return 0
+ config_get phy "$device" phy
+
+ set_wifi_down "$device"
+
+ include /lib/network
+ while read line < /proc/net/hostap/${phy}/wds; do
+ set $line
+ [ -f "/var/run/wifi-${1}.pid" ] &&
+ kill "$(cat "/var/run/wifi-${1}.pid")"
+ ifconfig "$1" down
+ unbridge "$1"
+ iwpriv "$phy" wds_del "$2"
+ done
+ unbridge "$phy"
+ return 0
+)
+
+enable_prism2() {
+ local device="$1"
+
+ find_prism2_phy "$device" || return 0
+ config_get phy "$device" phy
+
+ config_get rxantenna "$device" rxantenna
+ config_get txantenna "$device" txantenna
+ config_get_bool diversity "$device" diversity
+ [ -n "$diversity" ] && {
+ rxantenna="1"
+ txantenna="1"
+ }
+ [ -n "$rxantenna" ] && iwpriv "$phy" antsel_rx "$rxantenna"
+ [ -n "$txantenna" ] && iwpriv "$phy" antsel_tx "$txantenna"
+
+ config_get channel "$device" channel
+ [ -n "$channel" ] && iwconfig "$phy" channel "$channel" >/dev/null 2>/dev/null
+
+ config_get txpower "$device" txpower
+ [ -n "$txpower" ] && iwconfig "$phy" txpower "${txpower%%.*}"
+
+ config_get vifs "$device" vifs
+ local first=1
+ for vif in $vifs; do
+ config_get ifname "$vif" ifname
+ config_get ssid "$vif" ssid
+ config_get mode "$vif" mode
+
+ [ "$mode" = "wds" ] || iwconfig "$phy" essid ${ssid:+-- }"${ssid:-any}"
+
+ case "$mode" in
+ sta)
+ iwconfig "$phy" mode managed
+ config_get addr "$device" bssid
+ [ -z "$addr" ] || {
+ iwconfig "$phy" ap "$addr"
+ }
+ ;;
+ ap) iwconfig "$phy" mode master;;
+ wds) iwpriv "$phy" wds_add "$ssid";;
+ adhoc) iwconfig "$phy" mode ad-hoc;;
+ *) iwconfig "$phy" mode "$mode";;
+ esac
+
+ [ "$first" = 1 ] && {
+ config_get rate "$vif" rate
+ [ -n "$rate" ] && iwconfig "$phy" rate "${rate%%.*}"
+
+ config_get_bool hidden "$vif" hidden 0
+ iwpriv "$phy" enh_sec "$hidden"
+
+ config_get frag "$vif" frag
+ [ -n "$frag" ] && iwconfig "$phy" frag "${frag%%.*}"
+
+ config_get rts "$vif" rts
+ [ -n "$rts" ] && iwconfig "$phy" rts "${rts%%.*}"
+
+ config_get maclist "$vif" maclist
+ [ -n "$maclist" ] && {
+ # flush MAC list
+ iwpriv "$phy" maccmd 3
+ for mac in $maclist; do
+ iwpriv "$phy" addmac "$mac"
+ done
+ }
+ config_get macpolicy "$vif" macpolicy
+ case "$macpolicy" in
+ allow)
+ iwpriv "$phy" maccmd 2
+ ;;
+ deny)
+ iwpriv "$phy" maccmd 1
+ ;;
+ *)
+ # default deny policy if mac list exists
+ [ -n "$maclist" ] && iwpriv "$phy" maccmd 1
+ ;;
+ esac
+ # kick all stations if we have policy explicitly set
+ [ -n "$macpolicy" ] && iwpriv "$phy" maccmd 4
+ }
+
+ config_get enc "$vif" encryption
+ case "$enc" in
+ WEP|wep)
+ for idx in 1 2 3 4; do
+ config_get key "$vif" "key${idx}"
+ iwconfig "$ifname" enc "[$idx]" "${key:-off}"
+ done
+ config_get key "$vif" key
+ key="${key:-1}"
+ case "$key" in
+ [1234]) iwconfig "$ifname" enc "[$key]";;
+ *) iwconfig "$ifname" enc "$key";;
+ esac
+ ;;
+ psk*|wpa*)
+ start_hostapd=1
+ config_get key "$vif" key
+ ;;
+ esac
+
+ local net_cfg bridge
+ net_cfg="$(find_net_config "$vif")"
+ [ -z "$net_cfg" ] || {
+ bridge="$(bridge_interface "$net_cfg")"
+ config_set "$vif" bridge "$bridge"
+ start_net "$ifname" "$net_cfg"
+ }
+ set_wifi_up "$vif" "$ifname"
+
+ case "$mode" in
+ ap)
+ if [ -n "$start_hostapd" ] && eval "type hostapd_setup_vif" 2>/dev/null >/dev/null; then
+ hostapd_setup_vif "$vif" hostap || {
+ echo "enable_prism2($device): Failed to set up hostapd for interface $ifname" >&2
+ # make sure this wifi interface won't accidentally stay open without encryption
+ ifconfig "$ifname" down
+ continue
+ }
+ fi
+ ;;
+ wds|sta)
+ if eval "type wpa_supplicant_setup_vif" 2>/dev/null >/dev/null; then
+ wpa_supplicant_setup_vif "$vif" wext || {
+ echo "enable_prism2($device): Failed to set up wpa_supplicant for interface $ifname" >&2
+ ifconfig "$ifname" down
+ continue
+ }
+ fi
+ ;;
+ esac
+ first=0
+ done
+
+}
+
+check_prism2_device() {
+ [ ${1%[0-9]} = "wlan" ] && config_set "$1" phy "$1"
+ config_get phy "$1" phy
+ [ -z "$phy" ] && {
+ find_prism2_phy "$1" >/dev/null || return 0
+ config_get phy "$1" phy
+ }
+ [ "$phy" = "$dev" ] && found=1
+}
+
+detect_prism2() {
+ devidx=0
+ config_load wireless
+ while :; do
+ config_get type "radio$devidx" type
+ [ -n "$type" ] || break
+ devidx=$(($devidx + 1))
+ done
+ cd /proc/net/hostap
+ [ -d wlan* ] || return
+ for dev in $(ls -d wlan* 2>&-); do
+ found=0
+ config_foreach check_prism2_device wifi-device
+ [ "$found" -gt 0 ] && continue
+ cat <<EOF
+config wifi-device radio$devidx
+ option type prism2
+ option channel 11
+ option macaddr $(cat /sys/class/net/${dev}/address)
+
+ # REMOVE THIS LINE TO ENABLE WIFI:
+ option disabled 1
+
+config wifi-iface
+ option device radio$devidx
+ option network lan
+ option mode ap
+ option ssid OpenWrt
+ option encryption none
+
+EOF
+ devidx=$(($devidx + 1))
+ done
+}
diff --git a/package/hostap-driver/patches/001-fix-txpower.patch b/package/hostap-driver/patches/001-fix-txpower.patch
new file mode 100644
index 000000000..94ca34494
--- /dev/null
+++ b/package/hostap-driver/patches/001-fix-txpower.patch
@@ -0,0 +1,175 @@
+diff -Naur hostap-driver-0.3.7/driver/modules/hostap.c hostap-driver-0.3.7-patched/driver/modules/hostap.c
+--- hostap-driver-0.3.7/driver/modules/hostap.c 2004-08-28 06:26:46.000000000 +0300
++++ hostap-driver-0.3.7-patched/driver/modules/hostap.c 2005-04-20 17:20:56.000000000 +0300
+@@ -1164,6 +1164,36 @@
+ return ret;
+ }
+
++/* BUG FIX: Restore power setting value when lost due to F/W bug */
++
++int hostap_restore_power(struct net_device *dev)
++{
++ struct hostap_interface *iface = dev->priv;
++ local_info_t *local = iface->local;
++
++ u16 val;
++ int ret = 0;
++
++ if (local->txpower_type == PRISM2_TXPOWER_OFF) {
++ val = 0xff; /* use all standby and sleep modes */
++ ret = local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
++ HFA386X_CR_A_D_TEST_MODES2,
++ &val, NULL);
++ }
++
++#ifdef RAW_TXPOWER_SETTING
++ if (local->txpower_type == PRISM2_TXPOWER_FIXED) {
++ val = HFA384X_TEST_CFG_BIT_ALC;
++ local->func->cmd(dev, HFA384X_CMDCODE_TEST |
++ (HFA384X_TEST_CFG_BITS << 8), 0, &val, NULL);
++ val = prism2_txpower_dBm_to_hfa386x(local->txpower);
++ ret = (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
++ HFA386X_CR_MANUAL_TX_POWER, &val, NULL));
++ }
++#endif /* RAW_TXPOWER_SETTING */
++ return (ret ? -EOPNOTSUPP : 0);
++}
++
+
+ struct proc_dir_entry *hostap_proc;
+
+@@ -1214,6 +1244,7 @@
+ EXPORT_SYMBOL(hostap_set_hostapd_sta);
+ EXPORT_SYMBOL(hostap_add_interface);
+ EXPORT_SYMBOL(hostap_remove_interface);
++EXPORT_SYMBOL(hostap_restore_power);
+ EXPORT_SYMBOL(prism2_update_comms_qual);
+
+ module_init(hostap_init);
+diff -Naur hostap-driver-0.3.7/driver/modules/hostap.h hostap-driver-0.3.7-patched/driver/modules/hostap.h
+--- hostap-driver-0.3.7/driver/modules/hostap.h 2003-11-30 04:14:26.000000000 +0200
++++ hostap-driver-0.3.7-patched/driver/modules/hostap.h 2005-04-20 17:21:23.000000000 +0300
+@@ -36,6 +36,7 @@
+ const char *prefix, const char *name);
+ void hostap_remove_interface(struct net_device *dev, int rtnl_locked,
+ int remove_from_list);
++int hostap_restore_power(struct net_device *dev);
+ int prism2_update_comms_qual(struct net_device *dev);
+ int prism2_sta_send_mgmt(local_info_t *local, u8 *dst, u8 stype,
+ u8 *body, size_t bodylen);
+diff -Naur hostap-driver-0.3.7/driver/modules/hostap_ap.c hostap-driver-0.3.7-patched/driver/modules/hostap_ap.c
+--- hostap-driver-0.3.7/driver/modules/hostap_ap.c 2005-01-24 04:52:00.000000000 +0200
++++ hostap-driver-0.3.7-patched/driver/modules/hostap_ap.c 2005-04-21 20:06:12.000000000 +0300
+@@ -2346,13 +2346,13 @@
+ addr[count].sa_family = ARPHRD_ETHER;
+ memcpy(addr[count].sa_data, sta->addr, ETH_ALEN);
+ if (sta->last_rx_silence == 0)
+- qual[count].qual = sta->last_rx_signal < 27 ?
+- 0 : (sta->last_rx_signal - 27) * 92 / 127;
++ qual[count].qual = (sta->last_rx_signal - 156) == 0 ?
++ 0 : (sta->last_rx_signal - 156) * 92 / 64;
+ else
+- qual[count].qual = sta->last_rx_signal -
+- sta->last_rx_silence - 35;
+- qual[count].level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal);
+- qual[count].noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
++ qual[count].qual = (sta->last_rx_signal -
++ sta->last_rx_silence) * 92 / 64;
++ qual[count].level = sta->last_rx_signal;
++ qual[count].noise = sta->last_rx_silence;
+ qual[count].updated = sta->last_rx_updated;
+
+ sta->last_rx_updated = 0;
+@@ -2413,13 +2413,13 @@
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVQUAL;
+ if (sta->last_rx_silence == 0)
+- iwe.u.qual.qual = sta->last_rx_signal < 27 ?
+- 0 : (sta->last_rx_signal - 27) * 92 / 127;
++ iwe.u.qual.qual = (sta->last_rx_signal -156) == 0 ?
++ 0 : (sta->last_rx_signal - 156) * 92 / 64;
+ else
+- iwe.u.qual.qual = sta->last_rx_signal -
+- sta->last_rx_silence - 35;
+- iwe.u.qual.level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal);
+- iwe.u.qual.noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
++ iwe.u.qual.qual = (sta->last_rx_signal -
++ sta->last_rx_silence) * 92 / 64;
++ iwe.u.qual.level = sta->last_rx_signal;
++ iwe.u.qual.noise = sta->last_rx_silence;
+ iwe.u.qual.updated = sta->last_rx_updated;
+ iwe.len = IW_EV_QUAL_LEN;
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+diff -Naur hostap-driver-0.3.7/driver/modules/hostap_config.h hostap-driver-0.3.7-patched/driver/modules/hostap_config.h
+--- hostap-driver-0.3.7/driver/modules/hostap_config.h 2005-02-12 18:12:56.000000000 +0200
++++ hostap-driver-0.3.7-patched/driver/modules/hostap_config.h 2005-04-20 17:25:23.000000000 +0300
+@@ -94,6 +94,12 @@
+ */
+ /* #define PRISM2_NO_STATION_MODES */
+
++/* Enable TX power Setting functions
++ * (min att = -128 , max att = 127)
++ */
++
++#define RAW_TXPOWER_SETTING
++
+ /* Use Linux crypto API instead of own encryption implementation whenever
+ * possible. */
+ /* #define HOSTAP_USE_CRYPTO_API */
+diff -Naur hostap-driver-0.3.7/driver/modules/hostap_hw.c hostap-driver-0.3.7-patched/driver/modules/hostap_hw.c
+--- hostap-driver-0.3.7/driver/modules/hostap_hw.c 2005-02-05 09:20:09.000000000 +0200
++++ hostap-driver-0.3.7-patched/driver/modules/hostap_hw.c 2005-04-20 17:25:55.000000000 +0300
+@@ -1039,6 +1039,7 @@
+ dev->name, local->fragm_threshold);
+ }
+
++ hostap_restore_power(dev);
+ return res;
+ }
+
+diff -Naur hostap-driver-0.3.7/driver/modules/hostap_info.c hostap-driver-0.3.7-patched/driver/modules/hostap_info.c
+--- hostap-driver-0.3.7/driver/modules/hostap_info.c 2004-02-29 20:05:44.000000000 +0200
++++ hostap-driver-0.3.7-patched/driver/modules/hostap_info.c 2005-04-20 17:26:36.000000000 +0300
+@@ -418,6 +418,11 @@
+ }
+
+ /* Get BSSID if we have a valid AP address */
++
++ if ( val == HFA384X_LINKSTATUS_CONNECTED ||
++ val == HFA384X_LINKSTATUS_DISCONNECTED )
++ hostap_restore_power(local->dev);
++
+ if (connected) {
+ netif_carrier_on(local->dev);
+ netif_carrier_on(local->ddev);
+diff -Naur hostap-driver-0.3.7/driver/modules/hostap_ioctl.c hostap-driver-0.3.7-patched/driver/modules/hostap_ioctl.c
+--- hostap-driver-0.3.7/driver/modules/hostap_ioctl.c 2004-11-22 08:03:05.000000000 +0200
++++ hostap-driver-0.3.7-patched/driver/modules/hostap_ioctl.c 2005-04-20 17:42:41.000000000 +0300
+@@ -1453,23 +1453,20 @@
+ val = 255;
+
+ tmp = val;
+- tmp >>= 2;
+
+- return -12 - tmp;
++ return tmp;
+ }
+
+ static u16 prism2_txpower_dBm_to_hfa386x(int val)
+ {
+ signed char tmp;
+
+- if (val > 20)
+- return 128;
+- else if (val < -43)
++ if (val > 127)
+ return 127;
++ else if (val < -128)
++ return 128;
+
+ tmp = val;
+- tmp = -12 - tmp;
+- tmp <<= 2;
+
+ return (unsigned char) tmp;
+ }
diff --git a/package/hostap-utils/Makefile b/package/hostap-utils/Makefile
new file mode 100644
index 000000000..1d7b22122
--- /dev/null
+++ b/package/hostap-utils/Makefile
@@ -0,0 +1,44 @@
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=hostap-utils
+PKG_VERSION:=0.4.7
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://hostap.epitest.fi/releases/
+PKG_MD5SUM:=afe041581b8f01666e353bec20917c85
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/hostap-utils
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS:=kmod-hostap
+ TITLE:=Host AP driver utility programs
+ URL:=http://hostap.epitest.fi/
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS) -Wall" \
+ all
+endef
+
+define Package/hostap-utils/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/hostap_crypt_conf $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/hostap_diag $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/hostap_io_debug $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/hostap_rid $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/prism2_srec $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/split_combined_hex $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,hostap-utils))
diff --git a/package/hostapd/Config.in b/package/hostapd/Config.in
new file mode 100644
index 000000000..810c5a09a
--- /dev/null
+++ b/package/hostapd/Config.in
@@ -0,0 +1,47 @@
+# wpa_supplicant config
+config WPA_SUPPLICANT_NO_TIMESTAMP_CHECK
+ bool "Disable timestamp check"
+ depends PACKAGE_wpa-supplicant || PACKAGE_wpa-supplicant-mini || PACKAGE_wpad || PACKAGE_wpad-mini
+ default n
+ help
+ This disables the timestamp check for certificates in wpa_supplicant
+ Useful for devices without RTC that cannot reliably get the real date/time
+
+choice
+ prompt "Choose TLS provider"
+ default WPA_SUPPLICANT_INTERNAL
+ depends PACKAGE_wpa-supplicant || PACKAGE_wpad
+
+config WPA_SUPPLICANT_INTERNAL
+ bool "internal"
+
+config WPA_SUPPLICANT_OPENSSL
+ bool "openssl"
+ select PACKAGE_libopenssl
+
+endchoice
+
+config WPA_RFKILL_SUPPORT
+ bool "Add rfkill support"
+ depends PACKAGE_wpa-supplicant || PACKAGE_wpa-supplicant-mini || PACKAGE_wpad || PACKAGE_wpad-mini
+ default n
+
+config WPA_MSG_MIN_PRIORITY
+ int "Minimum debug message priority"
+ default 3
+ help
+ Useful values are:
+ 0 = all messages
+ 1 = raw message dumps
+ 2 = most debugging messages
+ 3 = info messages
+ 4 = warnings
+ 5 = errors
+
+config DRIVER_WEXT_SUPPORT
+ bool
+ default n
+
+config DRIVER_11N_SUPPORT
+ bool
+ default n
diff --git a/package/hostapd/Makefile b/package/hostapd/Makefile
new file mode 100644
index 000000000..5d279c51c
--- /dev/null
+++ b/package/hostapd/Makefile
@@ -0,0 +1,339 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=hostapd
+PKG_VERSION:=20120910
+PKG_RELEASE:=1
+PKG_REV:=762b99db7a76803d1ad274e87caa6fe870d47441
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=git://w1.fi/srv/git/hostap.git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=$(PKG_REV)
+PKG_SOURCE_PROTO:=git
+PKG_MIRROR_MD5SUM:=fa3227c146cb50732fe8511ce6d1d862
+
+PKG_BUILD_PARALLEL:=1
+
+PKG_BUILD_DEPENDS:= \
+ PACKAGE_kmod-madwifi:madwifi \
+
+PKG_CONFIG_DEPENDS:= \
+ CONFIG_WPA_SUPPLICANT_NO_TIMESTAMP_CHECK \
+ CONFIG_PACKAGE_kmod-ath9k \
+ CONFIG_PACKAGE_kmod-mac80211 \
+ CONFIG_PACKAGE_kmod-madwifi \
+ CONFIG_PACKAGE_hostapd \
+ CONFIG_PACKAGE_hostapd-mini \
+ CONFIG_PACKAGE_kmod-hostap \
+ CONFIG_WPA_RFKILL_SUPPORT \
+ CONFIG_DRIVER_WEXT_SUPPORT \
+ CONFIG_DRIVER_11N_SUPPORT
+
+LOCAL_TYPE=$(strip \
+ $(if $(findstring wpad,$(BUILD_VARIANT)),wpad, \
+ $(if $(findstring supplicant,$(BUILD_VARIANT)),supplicant, \
+ hostapd \
+ )))
+LOCAL_VARIANT=$(patsubst wpad-%,%,$(patsubst supplicant-%,%,$(BUILD_VARIANT)))
+
+ifeq ($(LOCAL_TYPE),supplicant)
+ ifeq ($(LOCAL_VARIANT),full)
+ PKG_CONFIG_DEPENDS += \
+ CONFIG_WPA_SUPPLICANT_INTERNAL \
+ CONFIG_WPA_SUPPLICANT_OPENSSL
+ endif
+endif
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+STAMP_CONFIGURED:=$(STAMP_CONFIGURED)_$(CONFIG_WPA_MSG_MIN_PRIORITY)
+
+ifneq ($(CONFIG_DRIVER_11N_SUPPORT),)
+ HOSTAPD_IEEE80211N:=y
+endif
+
+DRIVER_MAKEOPTS= \
+ CONFIG_DRIVER_NL80211=$(CONFIG_PACKAGE_kmod-mac80211) \
+ CONFIG_DRIVER_MADWIFI=$(CONFIG_PACKAGE_kmod-madwifi) \
+ CONFIG_DRIVER_HOSTAP=$(CONFIG_PACKAGE_kmod-hostap) \
+ CONFIG_IEEE80211N=$(HOSTAPD_IEEE80211N) \
+ CONFIG_IEEE80211W=$(CONFIG_PACKAGE_kmod-ath9k) \
+ CONFIG_DRIVER_WEXT=$(CONFIG_DRIVER_WEXT_SUPPORT) \
+ $(if $(CONFIG_WPA_RFKILL_SUPPORT),NEED_RFKILL=y)
+
+ifneq ($(LOCAL_TYPE),hostapd)
+ ifdef CONFIG_WPA_SUPPLICANT_OPENSSL
+ ifeq ($(LOCAL_VARIANT),full)
+ DRIVER_MAKEOPTS += CONFIG_TLS=openssl
+ TARGET_LDFLAGS += -lcrypto -lssl
+ endif
+ endif
+ ifdef CONFIG_WPA_SUPPLICANT_NO_TIMESTAMP_CHECK
+ TARGET_CFLAGS += -DNO_TIMESTAMP_CHECK
+ endif
+ DRIVER_MAKEOPTS += \
+ CONFIG_DRIVER_ROBOSWITCH=$(CONFIG_PACKAGE_kmod-switch)
+endif
+
+DRV_DEPENDS:=+PACKAGE_kmod-mac80211:libnl-tiny @(!(TARGET_avr32||TARGET_etrax)||BROKEN)
+
+define Package/hostapd/Default
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=IEEE 802.1x Authenticator
+ URL:=http://hostap.epitest.fi/
+ DEPENDS:=$(DRV_DEPENDS)
+ MAINTAINER:=Felix Fietkau <nbd@openwrt.org>
+endef
+
+define Package/hostapd
+$(call Package/hostapd/Default)
+ TITLE+= (full)
+ VARIANT:=full
+endef
+
+define Package/hostapd/description
+ This package contains a full featured IEEE 802.1x/WPA/EAP/RADIUS
+ Authenticator.
+endef
+
+define Package/hostapd-mini
+$(call Package/hostapd/Default)
+ TITLE+= (WPA-PSK only)
+ VARIANT:=mini
+endef
+
+define Package/hostapd-mini/description
+ This package contains a minimal IEEE 802.1x/WPA Authenticator (WPA-PSK only).
+endef
+
+define Package/hostapd-utils
+ $(call Package/hostapd/Default)
+ TITLE+= (utils)
+ DEPENDS:=@PACKAGE_hostapd||PACKAGE_hostapd-mini||PACKAGE_wpad||PACKAGE_wpad-mini
+endef
+
+define Package/hostapd-utils/description
+ This package contains a command line utility to control the
+ IEEE 802.1x/WPA/EAP/RADIUS Authenticator.
+endef
+
+define Package/wpad/Default
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=IEEE 802.1x Authenticator/Supplicant
+ URL:=http://hostap.epitest.fi/
+ MAINTAINER:=Felix Fietkau <nbd@openwrt.org>
+endef
+
+define Package/wpad
+$(call Package/wpad/Default)
+ TITLE+= (full)
+ DEPENDS:=$(DRV_DEPENDS) +WPA_SUPPLICANT_OPENSSL:libopenssl
+ VARIANT:=wpad-full
+endef
+
+define Package/wpad/description
+ This package contains a full featured IEEE 802.1x/WPA/EAP/RADIUS
+ Authenticator and Supplicant
+endef
+
+define Package/wpad-mini
+$(call Package/wpad/Default)
+ TITLE+= (WPA-PSK only)
+ DEPENDS:=$(DRV_DEPENDS)
+ VARIANT:=wpad-mini
+endef
+
+define Package/wpad-mini/description
+ This package contains a minimal IEEE 802.1x/WPA Authenticator and Supplicant (WPA-PSK only).
+endef
+
+define Package/wpa-supplicant
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=WPA Supplicant
+ URL:=http://hostap.epitest.fi/wpa_supplicant/
+ DEPENDS:=$(DRV_DEPENDS) +WPA_SUPPLICANT_OPENSSL:libopenssl
+ VARIANT:=supplicant-full
+ MAINTAINER:=Felix Fietkau <nbd@openwrt.org>
+endef
+
+define Package/wpa-supplicant/Description
+ WPA Supplicant
+endef
+
+define Package/wpa-supplicant/config
+ source "$(SOURCE)/Config.in"
+endef
+
+define Package/wpa-supplicant-mini
+ $(Package/wpa-supplicant)
+ TITLE:=WPA Supplicant (minimal version)
+ DEPENDS:=$(DRV_DEPENDS)
+ VARIANT:=supplicant-mini
+endef
+
+define Package/wpa-supplicant-mini/Description
+ WPA Supplicant (minimal version)
+endef
+
+define Package/wpa-cli
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS:=@PACKAGE_wpa-supplicant||PACKAGE_wpad-mini||PACKAGE_wpad
+ TITLE:=WPA Supplicant command line interface
+ MAINTAINER:=Felix Fietkau <nbd@openwrt.org>
+endef
+
+define Package/wpa-cli/Description
+ WPA Supplicant control utility
+endef
+
+
+ifneq ($(wildcard $(PKG_BUILD_DIR)/.config_*),$(subst .configured_,.config_,$(STAMP_CONFIGURED)))
+ define Build/Configure/rebuild
+ $(FIND) $(PKG_BUILD_DIR) -name \*.o -or -name \*.a | $(XARGS) rm -f
+ rm -f $(PKG_BUILD_DIR)/hostapd/hostapd
+ rm -f $(PKG_BUILD_DIR)/wpa_supplicant/wpa_supplicant
+ rm -f $(PKG_BUILD_DIR)/.config_*
+ touch $(subst .configured_,.config_,$(STAMP_CONFIGURED))
+ endef
+endif
+
+define Build/Configure
+ $(Build/Configure/rebuild)
+ $(CP) ./files/hostapd-$(LOCAL_VARIANT).config $(PKG_BUILD_DIR)/hostapd/.config
+ $(CP) ./files/wpa_supplicant-$(LOCAL_VARIANT).config $(PKG_BUILD_DIR)/wpa_supplicant/.config
+endef
+
+TARGET_CPPFLAGS := \
+ -I$(STAGING_DIR)/usr/include/libnl-tiny \
+ -I$(PKG_BUILD_DIR)/src/crypto \
+ $(TARGET_CPPFLAGS) \
+ -I$(STAGING_DIR)/usr/include/madwifi \
+ -DCONFIG_LIBNL20 \
+ -D_GNU_SOURCE \
+ $(if $(CONFIG_WPA_MSG_MIN_PRIORITY),-DCONFIG_MSG_MIN_PRIORITY=$(CONFIG_WPA_MSG_MIN_PRIORITY))
+
+TARGET_CFLAGS += -ffunction-sections -fdata-sections
+TARGET_LDFLAGS += -Wl,--gc-sections
+
+ifdef CONFIG_PACKAGE_kmod-mac80211
+ TARGET_LDFLAGS += -lm -lnl-tiny
+endif
+
+define Build/RunMake
+ CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \
+ $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/$(1) \
+ $(TARGET_CONFIGURE_OPTS) \
+ $(DRIVER_MAKEOPTS) \
+ LIBS="$(TARGET_LDFLAGS)" \
+ $(2)
+endef
+
+define Build/Compile/wpad
+ echo ` \
+ $(call Build/RunMake,hostapd,-s MULTICALL=1 dump_cflags); \
+ $(call Build/RunMake,wpa_supplicant,-s MULTICALL=1 dump_cflags) | \
+ sed -e 's,-n ,,g' -e 's,$(TARGET_CFLAGS),,' \
+ ` > $(PKG_BUILD_DIR)/.cflags
+ +$(call Build/RunMake,hostapd, \
+ CFLAGS="$$$$(cat $(PKG_BUILD_DIR)/.cflags)" \
+ MULTICALL=1 \
+ hostapd_cli hostapd_multi.a \
+ )
+ +$(call Build/RunMake,wpa_supplicant, \
+ CFLAGS="$$$$(cat $(PKG_BUILD_DIR)/.cflags)" \
+ MULTICALL=1 \
+ wpa_cli wpa_supplicant_multi.a \
+ )
+ $(TARGET_CC) -o $(PKG_BUILD_DIR)/wpad \
+ $(TARGET_CFLAGS) \
+ ./files/multicall.c \
+ $(PKG_BUILD_DIR)/hostapd/hostapd_multi.a \
+ $(PKG_BUILD_DIR)/wpa_supplicant/wpa_supplicant_multi.a \
+ $(TARGET_LDFLAGS)
+endef
+
+define Build/Compile/hostapd
+ $(call Build/RunMake,hostapd, \
+ hostapd hostapd_cli \
+ )
+endef
+
+define Build/Compile/supplicant
+ $(call Build/RunMake,wpa_supplicant, \
+ wpa_cli wpa_supplicant \
+ )
+endef
+
+define Build/Compile
+ $(Build/Compile/$(LOCAL_TYPE))
+endef
+
+define Install/hostapd
+ $(INSTALL_DIR) $(1)/lib/wifi
+ $(INSTALL_DATA) ./files/hostapd.sh $(1)/lib/wifi/hostapd.sh
+ $(INSTALL_DIR) $(1)/usr/sbin
+endef
+
+define Install/supplicant
+ $(INSTALL_DIR) $(1)/lib/wifi
+ $(INSTALL_DATA) ./files/wpa_supplicant.sh $(1)/lib/wifi/wpa_supplicant.sh
+ $(INSTALL_DIR) $(1)/usr/sbin
+endef
+
+define Package/hostapd/install
+ $(call Install/hostapd,$(1))
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/hostapd/hostapd $(1)/usr/sbin/
+endef
+Package/hostapd-mini/install = $(Package/hostapd/install)
+
+ifneq ($(LOCAL_TYPE),supplicant)
+ define Package/hostapd-utils/install
+ $(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/hotplug.d/button
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/hostapd/hostapd_cli $(1)/usr/sbin/
+ $(INSTALL_DATA) ./files/wps-hotplug.sh $(1)/etc/hotplug.d/button/50-wps
+ endef
+endif
+
+define Package/wpad/install
+ $(call Install/hostapd,$(1))
+ $(call Install/supplicant,$(1))
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/wpad $(1)/usr/sbin/
+ ln -sf wpad $(1)/usr/sbin/hostapd
+ ln -sf wpad $(1)/usr/sbin/wpa_supplicant
+endef
+Package/wpad-mini/install = $(Package/wpad/install)
+
+define Package/wpa-supplicant/install
+ $(call Install/supplicant,$(1))
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/wpa_supplicant/wpa_supplicant $(1)/usr/sbin/
+endef
+Package/wpa-supplicant-mini/install = $(Package/wpa-supplicant/install)
+
+ifneq ($(LOCAL_TYPE),hostapd)
+ define Package/wpa-cli/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(CP) $(PKG_BUILD_DIR)/wpa_supplicant/wpa_cli $(1)/usr/sbin/
+ endef
+endif
+
+$(eval $(call BuildPackage,hostapd))
+$(eval $(call BuildPackage,hostapd-mini))
+$(eval $(call BuildPackage,wpad))
+$(eval $(call BuildPackage,wpad-mini))
+$(eval $(call BuildPackage,wpa-supplicant))
+$(eval $(call BuildPackage,wpa-supplicant-mini))
+$(eval $(call BuildPackage,wpa-cli))
+$(eval $(call BuildPackage,hostapd-utils))
diff --git a/package/hostapd/files/hostapd-full.config b/package/hostapd/files/hostapd-full.config
new file mode 100644
index 000000000..3a0ce12fc
--- /dev/null
+++ b/package/hostapd/files/hostapd-full.config
@@ -0,0 +1,164 @@
+# Example hostapd build time configuration
+#
+# This file lists the configuration options that are used when building the
+# hostapd binary. All lines starting with # are ignored. Configuration option
+# lines must be commented out complete, if they are not to be included, i.e.,
+# just setting VARIABLE=n is not disabling that variable.
+#
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
+# be modified from here. In most cass, these lines should use += in order not
+# to override previous values of the variables.
+
+# Driver interface for Host AP driver
+CONFIG_DRIVER_HOSTAP=y
+
+# Driver interface for wired authenticator
+CONFIG_DRIVER_WIRED=y
+
+# Driver interface for madwifi driver
+CONFIG_DRIVER_MADWIFI=y
+#CFLAGS += -I../../madwifi # change to the madwifi source directory
+
+# Driver interface for Prism54 driver
+#CONFIG_DRIVER_PRISM54=y
+
+# Driver interface for drivers using the nl80211 kernel interface
+CONFIG_DRIVER_NL80211=y
+# driver_nl80211.c requires a rather new libnl (version 1.1) which may not be
+# shipped with your distribution yet. If that is the case, you need to build
+# newer libnl version and point the hostapd build to use it.
+#LIBNL=/usr/src/libnl
+#CFLAGS += -I$(LIBNL)/include
+#LIBS += -L$(LIBNL)/lib
+
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
+#CONFIG_DRIVER_BSD=y
+#CFLAGS += -I/usr/local/include
+#LIBS += -L/usr/local/lib
+
+# Driver interface for no driver (e.g., RADIUS server only)
+#CONFIG_DRIVER_NONE=y
+
+# IEEE 802.11F/IAPP
+CONFIG_IAPP=y
+
+# WPA2/IEEE 802.11i RSN pre-authentication
+CONFIG_RSN_PREAUTH=y
+
+# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
+CONFIG_PEERKEY=y
+
+# IEEE 802.11w (management frame protection)
+# This version is an experimental implementation based on IEEE 802.11w/D1.0
+# draft and is subject to change since the standard has not yet been finalized.
+# Driver support is also needed for IEEE 802.11w.
+#CONFIG_IEEE80211W=y
+
+# Integrated EAP server
+CONFIG_EAP=y
+
+# EAP-MD5 for the integrated EAP server
+CONFIG_EAP_MD5=y
+
+# EAP-TLS for the integrated EAP server
+CONFIG_EAP_TLS=y
+
+# EAP-MSCHAPv2 for the integrated EAP server
+CONFIG_EAP_MSCHAPV2=y
+
+# EAP-PEAP for the integrated EAP server
+CONFIG_EAP_PEAP=y
+
+# EAP-GTC for the integrated EAP server
+CONFIG_EAP_GTC=y
+
+# EAP-TTLS for the integrated EAP server
+CONFIG_EAP_TTLS=y
+
+# EAP-SIM for the integrated EAP server
+#CONFIG_EAP_SIM=y
+
+# EAP-AKA for the integrated EAP server
+#CONFIG_EAP_AKA=y
+
+# EAP-AKA' for the integrated EAP server
+# This requires CONFIG_EAP_AKA to be enabled, too.
+#CONFIG_EAP_AKA_PRIME=y
+
+# EAP-PAX for the integrated EAP server
+#CONFIG_EAP_PAX=y
+
+# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
+#CONFIG_EAP_PSK=y
+
+# EAP-SAKE for the integrated EAP server
+#CONFIG_EAP_SAKE=y
+
+# EAP-GPSK for the integrated EAP server
+#CONFIG_EAP_GPSK=y
+# Include support for optional SHA256 cipher suite in EAP-GPSK
+#CONFIG_EAP_GPSK_SHA256=y
+
+# EAP-FAST for the integrated EAP server
+# Note: Default OpenSSL package does not include support for all the
+# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
+# the OpenSSL library must be patched (openssl-0.9.9-session-ticket.patch)
+# to add the needed functions.
+#CONFIG_EAP_FAST=y
+
+# Wi-Fi Protected Setup (WPS)
+#CONFIG_WPS=y
+# Enable UPnP support for external WPS Registrars
+#CONFIG_WPS_UPNP=y
+
+# EAP-IKEv2
+#CONFIG_EAP_IKEV2=y
+
+# Trusted Network Connect (EAP-TNC)
+#CONFIG_EAP_TNC=y
+
+# PKCS#12 (PFX) support (used to read private key and certificate file from
+# a file that usually has extension .p12 or .pfx)
+CONFIG_PKCS12=y
+
+# RADIUS authentication server. This provides access to the integrated EAP
+# server from external hosts using RADIUS.
+#CONFIG_RADIUS_SERVER=y
+
+# Build IPv6 support for RADIUS operations
+CONFIG_IPV6=y
+
+# IEEE Std 802.11r-2008 (Fast BSS Transition)
+#CONFIG_IEEE80211R=y
+
+# Use the hostapd's IEEE 802.11 authentication (ACL), but without
+# the IEEE 802.11 Management capability (e.g., madwifi or FreeBSD/net80211)
+#CONFIG_DRIVER_RADIUS_ACL=y
+
+# IEEE 802.11n (High Throughput) support
+CONFIG_IEEE80211N=y
+
+# Remove debugging code that is printing out debug messages to stdout.
+# This can be used to reduce the size of the hostapd considerably if debugging
+# code is not needed.
+#CONFIG_NO_STDOUT_DEBUG=y
+
+# Remove support for RADIUS accounting
+#CONFIG_NO_ACCOUNTING=y
+
+# Remove support for RADIUS
+#CONFIG_NO_RADIUS=y
+
+# Remove support for VLANs
+#CONFIG_NO_VLAN=y
+
+CONFIG_TLS=internal
+CONFIG_INTERNAL_LIBTOMMATH=y
+CONFIG_INTERNAL_AES=y
+NEED_AES_DEC=y
+
+CONFIG_NO_DUMP_STATE=y
+
+CONFIG_WPS=y
+CONFIG_FULL_DYNAMIC_VLAN=y
+
diff --git a/package/hostapd/files/hostapd-mini.config b/package/hostapd/files/hostapd-mini.config
new file mode 100644
index 000000000..3e94a645b
--- /dev/null
+++ b/package/hostapd/files/hostapd-mini.config
@@ -0,0 +1,157 @@
+# Example hostapd build time configuration
+#
+# This file lists the configuration options that are used when building the
+# hostapd binary. All lines starting with # are ignored. Configuration option
+# lines must be commented out complete, if they are not to be included, i.e.,
+# just setting VARIABLE=n is not disabling that variable.
+#
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
+# be modified from here. In most cass, these lines should use += in order not
+# to override previous values of the variables.
+
+# Driver interface for Host AP driver
+CONFIG_DRIVER_HOSTAP=y
+
+# Driver interface for wired authenticator
+CONFIG_DRIVER_WIRED=y
+
+# Driver interface for madwifi driver
+CONFIG_DRIVER_MADWIFI=y
+#CFLAGS += -I../../madwifi # change to the madwifi source directory
+
+# Driver interface for Prism54 driver
+#CONFIG_DRIVER_PRISM54=y
+
+# Driver interface for drivers using the nl80211 kernel interface
+CONFIG_DRIVER_NL80211=y
+# driver_nl80211.c requires a rather new libnl (version 1.1) which may not be
+# shipped with your distribution yet. If that is the case, you need to build
+# newer libnl version and point the hostapd build to use it.
+#LIBNL=/usr/src/libnl
+#CFLAGS += -I$(LIBNL)/include
+#LIBS += -L$(LIBNL)/lib
+
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
+#CONFIG_DRIVER_BSD=y
+#CFLAGS += -I/usr/local/include
+#LIBS += -L/usr/local/lib
+
+# Driver interface for no driver (e.g., RADIUS server only)
+#CONFIG_DRIVER_NONE=y
+
+# IEEE 802.11F/IAPP
+# CONFIG_IAPP=y
+
+# WPA2/IEEE 802.11i RSN pre-authentication
+CONFIG_RSN_PREAUTH=y
+
+# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
+CONFIG_PEERKEY=y
+
+# IEEE 802.11w (management frame protection)
+# This version is an experimental implementation based on IEEE 802.11w/D1.0
+# draft and is subject to change since the standard has not yet been finalized.
+# Driver support is also needed for IEEE 802.11w.
+#CONFIG_IEEE80211W=y
+
+# Integrated EAP server
+#CONFIG_EAP=y
+
+# EAP-MD5 for the integrated EAP server
+#CONFIG_EAP_MD5=y
+
+# EAP-TLS for the integrated EAP server
+#CONFIG_EAP_TLS=y
+
+# EAP-MSCHAPv2 for the integrated EAP server
+#CONFIG_EAP_MSCHAPV2=y
+
+# EAP-PEAP for the integrated EAP server
+#CONFIG_EAP_PEAP=y
+
+# EAP-GTC for the integrated EAP server
+#CONFIG_EAP_GTC=y
+
+# EAP-TTLS for the integrated EAP server
+#CONFIG_EAP_TTLS=y
+
+# EAP-SIM for the integrated EAP server
+#CONFIG_EAP_SIM=y
+
+# EAP-AKA for the integrated EAP server
+#CONFIG_EAP_AKA=y
+
+# EAP-AKA' for the integrated EAP server
+# This requires CONFIG_EAP_AKA to be enabled, too.
+#CONFIG_EAP_AKA_PRIME=y
+
+# EAP-PAX for the integrated EAP server
+#CONFIG_EAP_PAX=y
+
+# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
+#CONFIG_EAP_PSK=y
+
+# EAP-SAKE for the integrated EAP server
+#CONFIG_EAP_SAKE=y
+
+# EAP-GPSK for the integrated EAP server
+#CONFIG_EAP_GPSK=y
+# Include support for optional SHA256 cipher suite in EAP-GPSK
+#CONFIG_EAP_GPSK_SHA256=y
+
+# EAP-FAST for the integrated EAP server
+# Note: Default OpenSSL package does not include support for all the
+# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
+# the OpenSSL library must be patched (openssl-0.9.9-session-ticket.patch)
+# to add the needed functions.
+#CONFIG_EAP_FAST=y
+
+# Wi-Fi Protected Setup (WPS)
+#CONFIG_WPS=y
+# Enable UPnP support for external WPS Registrars
+#CONFIG_WPS_UPNP=y
+
+# EAP-IKEv2
+#CONFIG_EAP_IKEV2=y
+
+# Trusted Network Connect (EAP-TNC)
+#CONFIG_EAP_TNC=y
+
+# PKCS#12 (PFX) support (used to read private key and certificate file from
+# a file that usually has extension .p12 or .pfx)
+#CONFIG_PKCS12=y
+
+# RADIUS authentication server. This provides access to the integrated EAP
+# server from external hosts using RADIUS.
+#CONFIG_RADIUS_SERVER=y
+
+# Build IPv6 support for RADIUS operations
+#CONFIG_IPV6=y
+
+# IEEE Std 802.11r-2008 (Fast BSS Transition)
+#CONFIG_IEEE80211R=y
+
+# Use the hostapd's IEEE 802.11 authentication (ACL), but without
+# the IEEE 802.11 Management capability (e.g., madwifi or FreeBSD/net80211)
+#CONFIG_DRIVER_RADIUS_ACL=y
+
+# IEEE 802.11n (High Throughput) support
+CONFIG_IEEE80211N=y
+
+# Remove debugging code that is printing out debug messages to stdout.
+# This can be used to reduce the size of the hostapd considerably if debugging
+# code is not needed.
+#CONFIG_NO_STDOUT_DEBUG=y
+
+# Remove support for RADIUS accounting
+CONFIG_NO_ACCOUNTING=y
+
+# Remove support for RADIUS
+CONFIG_NO_RADIUS=y
+
+# Remove support for VLANs
+#CONFIG_NO_VLAN=y
+
+CONFIG_TLS=internal
+
+CONFIG_NO_DUMP_STATE=y
diff --git a/package/hostapd/files/hostapd.sh b/package/hostapd/files/hostapd.sh
new file mode 100644
index 000000000..d60c26f3c
--- /dev/null
+++ b/package/hostapd/files/hostapd.sh
@@ -0,0 +1,276 @@
+hostapd_set_bss_options() {
+ local var="$1"
+ local vif="$2"
+ local enc wep_rekey wpa_group_rekey wpa_pair_rekey wpa_master_rekey wps_possible
+
+ config_get enc "$vif" encryption
+ config_get wep_rekey "$vif" wep_rekey # 300
+ config_get wpa_group_rekey "$vif" wpa_group_rekey # 300
+ config_get wpa_pair_rekey "$vif" wpa_pair_rekey # 300
+ config_get wpa_master_rekey "$vif" wpa_master_rekey # 640
+ config_get_bool ap_isolate "$vif" isolate 0
+ config_get_bool disassoc_low_ack "$vif" disassoc_low_ack 1
+ config_get max_num_sta "$vif" max_num_sta 0
+ config_get max_inactivity "$vif" max_inactivity 0
+
+ config_get device "$vif" device
+ config_get hwmode "$device" hwmode
+ config_get phy "$device" phy
+
+ append "$var" "ctrl_interface=/var/run/hostapd-$phy" "$N"
+
+ if [ "$ap_isolate" -gt 0 ]; then
+ append "$var" "ap_isolate=$ap_isolate" "$N"
+ fi
+ if [ "$max_num_sta" -gt 0 ]; then
+ append "$var" "max_num_sta=$max_num_sta" "$N"
+ fi
+ if [ "$max_inactivity" -gt 0 ]; then
+ append "$var" "ap_max_inactivity=$max_inactivity" "$N"
+ fi
+ append "$var" "disassoc_low_ack=$disassoc_low_ack" "$N"
+
+ # Examples:
+ # psk-mixed/tkip => WPA1+2 PSK, TKIP
+ # wpa-psk2/tkip+aes => WPA2 PSK, CCMP+TKIP
+ # wpa2/tkip+aes => WPA2 RADIUS, CCMP+TKIP
+ # ...
+
+ # TODO: move this parsing function somewhere generic, so that
+ # later it can be reused by drivers that don't use hostapd
+
+ # crypto defaults: WPA2 vs WPA1
+ case "$enc" in
+ wpa2*|*psk2*)
+ wpa=2
+ crypto="CCMP"
+ ;;
+ *mixed*)
+ wpa=3
+ crypto="CCMP TKIP"
+ ;;
+ *)
+ wpa=1
+ crypto="TKIP"
+ ;;
+ esac
+
+ # explicit override for crypto setting
+ case "$enc" in
+ *tkip+aes|*tkip+ccmp|*aes+tkip|*ccmp+tkip) crypto="CCMP TKIP";;
+ *aes|*ccmp) crypto="CCMP";;
+ *tkip) crypto="TKIP";;
+ esac
+
+ # enforce CCMP for 11ng and 11na
+ case "$hwmode:$crypto" in
+ *ng:TKIP|*na:TKIP) crypto="CCMP TKIP";;
+ esac
+
+ # use crypto/auth settings for building the hostapd config
+ case "$enc" in
+ *psk*)
+ config_get psk "$vif" key
+ if [ ${#psk} -eq 64 ]; then
+ append "$var" "wpa_psk=$psk" "$N"
+ else
+ append "$var" "wpa_passphrase=$psk" "$N"
+ fi
+ wps_possible=1
+ [ -n "$wpa_group_rekey" ] && append "$var" "wpa_group_rekey=$wpa_group_rekey" "$N"
+ [ -n "$wpa_pair_rekey" ] && append "$var" "wpa_ptk_rekey=$wpa_pair_rekey" "$N"
+ [ -n "$wpa_master_rekey" ] && append "$var" "wpa_gmk_rekey=$wpa_master_rekey" "$N"
+ ;;
+ *wpa*)
+ # required fields? formats?
+ # hostapd is particular, maybe a default configuration for failures
+ config_get auth_server "$vif" auth_server
+ [ -z "$auth_server" ] && config_get auth_server "$vif" server
+ append "$var" "auth_server_addr=$auth_server" "$N"
+ config_get auth_port "$vif" auth_port
+ [ -z "$auth_port" ] && config_get auth_port "$vif" port
+ auth_port=${auth_port:-1812}
+ append "$var" "auth_server_port=$auth_port" "$N"
+ config_get auth_secret "$vif" auth_secret
+ [ -z "$auth_secret" ] && config_get auth_secret "$vif" key
+ append "$var" "auth_server_shared_secret=$auth_secret" "$N"
+ config_get_bool auth_cache "$vif" auth_cache 0
+ [ "$auth_cache" -gt 0 ] || append "$var" "disable_pmksa_caching=1" "$N"
+ [ "$auth_cache" -gt 0 ] || append "$var" "okc=0" "$N"
+ config_get acct_server "$vif" acct_server
+ [ -n "$acct_server" ] && append "$var" "acct_server_addr=$acct_server" "$N"
+ config_get acct_port "$vif" acct_port
+ [ -n "$acct_port" ] && acct_port=${acct_port:-1813}
+ [ -n "$acct_port" ] && append "$var" "acct_server_port=$acct_port" "$N"
+ config_get acct_secret "$vif" acct_secret
+ [ -n "$acct_secret" ] && append "$var" "acct_server_shared_secret=$acct_secret" "$N"
+ config_get nasid "$vif" nasid
+ append "$var" "nas_identifier=$nasid" "$N"
+ append "$var" "eapol_key_index_workaround=1" "$N"
+ append "$var" "ieee8021x=1" "$N"
+ append "$var" "wpa_key_mgmt=WPA-EAP" "$N"
+ [ -n "$wpa_group_rekey" ] && append "$var" "wpa_group_rekey=$wpa_group_rekey" "$N"
+ [ -n "$wpa_pair_rekey" ] && append "$var" "wpa_ptk_rekey=$wpa_pair_rekey" "$N"
+ [ -n "$wpa_master_rekey" ] && append "$var" "wpa_gmk_rekey=$wpa_master_rekey" "$N"
+ ;;
+ *wep*)
+ config_get key "$vif" key
+ key="${key:-1}"
+ case "$key" in
+ [1234])
+ for idx in 1 2 3 4; do
+ local zidx
+ zidx=$(($idx - 1))
+ config_get ckey "$vif" "key${idx}"
+ [ -n "$ckey" ] && \
+ append "$var" "wep_key${zidx}=$(prepare_key_wep "$ckey")" "$N"
+ done
+ append "$var" "wep_default_key=$((key - 1))" "$N"
+ ;;
+ *)
+ append "$var" "wep_key0=$(prepare_key_wep "$key")" "$N"
+ append "$var" "wep_default_key=0" "$N"
+ [ -n "$wep_rekey" ] && append "$var" "wep_rekey_period=$wep_rekey" "$N"
+ ;;
+ esac
+ case "$enc" in
+ *shared*)
+ auth_algs=2
+ ;;
+ *mixed*)
+ auth_algs=3
+ ;;
+ esac
+ wpa=0
+ crypto=
+ ;;
+ *)
+ wpa=0
+ crypto=
+ ;;
+ esac
+ append "$var" "auth_algs=${auth_algs:-1}" "$N"
+ append "$var" "wpa=$wpa" "$N"
+ [ -n "$crypto" ] && append "$var" "wpa_pairwise=$crypto" "$N"
+ [ -n "$wpa_group_rekey" ] && append "$var" "wpa_group_rekey=$wpa_group_rekey" "$N"
+
+ config_get ssid "$vif" ssid
+ config_get bridge "$vif" bridge
+ config_get ieee80211d "$vif" ieee80211d
+ config_get iapp_interface "$vif" iapp_interface
+
+ config_get_bool wps_pbc "$vif" wps_pushbutton 0
+ config_get_bool wps_label "$vif" wps_label 0
+
+ config_get config_methods "$vif" wps_config
+ [ "$wps_pbc" -gt 0 ] && append config_methods push_button
+
+ [ -n "$wps_possible" -a -n "$config_methods" ] && {
+ config_get device_type "$vif" wps_device_type "6-0050F204-1"
+ config_get device_name "$vif" wps_device_name "OpenWrt AP"
+ config_get manufacturer "$vif" wps_manufacturer "openwrt.org"
+
+ append "$var" "eap_server=1" "$N"
+ append "$var" "wps_state=2" "$N"
+ append "$var" "ap_setup_locked=1" "$N"
+ append "$var" "device_type=$device_type" "$N"
+ append "$var" "device_name=$device_name" "$N"
+ append "$var" "manufacturer=$manufacturer" "$N"
+ append "$var" "config_methods=$config_methods" "$N"
+ }
+
+ append "$var" "ssid=$ssid" "$N"
+ [ -n "$bridge" ] && append "$var" "bridge=$bridge" "$N"
+ [ -n "$ieee80211d" ] && append "$var" "ieee80211d=$ieee80211d" "$N"
+ [ -n "$iapp_interface" ] && append "$var" iapp_interface=$(uci_get_state network "$iapp_interface" ifname "$iapp_interface") "$N"
+
+ if [ "$wpa" -ge "2" ]
+ then
+ # RSN -> allow preauthentication
+ config_get_bool rsn_preauth "$vif" rsn_preauth "$auth_cache"
+ if [ -n "$bridge" -a "$rsn_preauth" = 1 ]
+ then
+ append "$var" "rsn_preauth=1" "$N"
+ append "$var" "rsn_preauth_interfaces=$bridge" "$N"
+ fi
+
+ # RSN -> allow management frame protection
+ config_get ieee80211w "$vif" ieee80211w
+ case "$ieee80211w" in
+ [012])
+ append "$var" "ieee80211w=$ieee80211w" "$N"
+ [ "$ieee80211w" -gt "0" ] && {
+ config_get ieee80211w_max_timeout "$vif" ieee80211w_max_timeout
+ config_get ieee80211w_retry_timeout "$vif" ieee80211w_retry_timeout
+ [ -n "$ieee80211w_max_timeout" ] && \
+ append "$var" "assoc_sa_query_max_timeout=$ieee80211w_max_timeout" "$N"
+ [ -n "$ieee80211w_retry_timeout" ] && \
+ append "$var" "assoc_sa_query_retry_timeout=$ieee80211w_retry_timeout" "$N"
+ }
+ ;;
+ esac
+ fi
+}
+
+hostapd_set_log_options() {
+ local var="$1"
+ local cfg="$2"
+ local log_level log_80211 log_8021x log_radius log_wpa log_driver log_iapp log_mlme
+
+ config_get log_level "$cfg" log_level 2
+
+ config_get_bool log_80211 "$cfg" log_80211 1
+ config_get_bool log_8021x "$cfg" log_8021x 1
+ config_get_bool log_radius "$cfg" log_radius 1
+ config_get_bool log_wpa "$cfg" log_wpa 1
+ config_get_bool log_driver "$cfg" log_driver 1
+ config_get_bool log_iapp "$cfg" log_iapp 1
+ config_get_bool log_mlme "$cfg" log_mlme 1
+
+ local log_mask=$(( \
+ ($log_80211 << 0) | \
+ ($log_8021x << 1) | \
+ ($log_radius << 2) | \
+ ($log_wpa << 3) | \
+ ($log_driver << 4) | \
+ ($log_iapp << 5) | \
+ ($log_mlme << 6) \
+ ))
+
+ append "$var" "logger_syslog=$log_mask" "$N"
+ append "$var" "logger_syslog_level=$log_level" "$N"
+ append "$var" "logger_stdout=$log_mask" "$N"
+ append "$var" "logger_stdout_level=$log_level" "$N"
+}
+
+hostapd_setup_vif() {
+ local vif="$1"
+ local driver="$2"
+ local ifname device channel hwmode
+
+ hostapd_cfg=
+
+ config_get ifname "$vif" ifname
+ config_get device "$vif" device
+ config_get channel "$device" channel
+ config_get hwmode "$device" hwmode
+
+ hostapd_set_log_options hostapd_cfg "$device"
+ hostapd_set_bss_options hostapd_cfg "$vif"
+
+ case "$hwmode" in
+ *bg|*gdt|*gst|*fh) hwmode=g;;
+ *adt|*ast) hwmode=a;;
+ esac
+ [ "$channel" = auto ] && channel=
+ [ -n "$channel" -a -z "$hwmode" ] && wifi_fixup_hwmode "$device"
+ cat > /var/run/hostapd-$ifname.conf <<EOF
+driver=$driver
+interface=$ifname
+${hwmode:+hw_mode=${hwmode#11}}
+${channel:+channel=$channel}
+$hostapd_cfg
+EOF
+ hostapd -P /var/run/wifi-$ifname.pid -B /var/run/hostapd-$ifname.conf
+}
+
diff --git a/package/hostapd/files/multicall.c b/package/hostapd/files/multicall.c
new file mode 100644
index 000000000..c8e814bb5
--- /dev/null
+++ b/package/hostapd/files/multicall.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+
+extern int hostapd_main(int argc, char **argv);
+extern int wpa_supplicant_main(int argc, char **argv);
+
+int main(int argc, char **argv)
+{
+ bool restart = false;
+ const char *prog = argv[0];
+
+restart:
+ if (strstr(argv[0], "hostapd"))
+ return hostapd_main(argc, argv);
+ else if (strstr(argv[0], "wpa_supplicant"))
+ return wpa_supplicant_main(argc, argv);
+
+ if (!restart && argc > 1) {
+ argv++;
+ argc--;
+ restart = true;
+ goto restart;
+ }
+
+ fprintf(stderr, "Invalid command.\nUsage: %s wpa_supplicant|hostapd [<arguments>]\n", prog);
+ return 255;
+}
diff --git a/package/hostapd/files/wpa_supplicant-full.config b/package/hostapd/files/wpa_supplicant-full.config
new file mode 100644
index 000000000..f5abbad94
--- /dev/null
+++ b/package/hostapd/files/wpa_supplicant-full.config
@@ -0,0 +1,408 @@
+# Example wpa_supplicant build time configuration
+#
+# This file lists the configuration options that are used when building the
+# hostapd binary. All lines starting with # are ignored. Configuration option
+# lines must be commented out complete, if they are not to be included, i.e.,
+# just setting VARIABLE=n is not disabling that variable.
+#
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
+# be modified from here. In most cases, these lines should use += in order not
+# to override previous values of the variables.
+
+
+# Uncomment following two lines and fix the paths if you have installed OpenSSL
+# or GnuTLS in non-default location
+#CFLAGS += -I/usr/local/openssl/include
+#LIBS += -L/usr/local/openssl/lib
+
+# Some Red Hat versions seem to include kerberos header files from OpenSSL, but
+# the kerberos files are not in the default include path. Following line can be
+# used to fix build issues on such systems (krb5.h not found).
+#CFLAGS += -I/usr/include/kerberos
+
+# Example configuration for various cross-compilation platforms
+
+#### sveasoft (e.g., for Linksys WRT54G) ######################################
+#CC=mipsel-uclibc-gcc
+#CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc
+#CFLAGS += -Os
+#CPPFLAGS += -I../src/include -I../../src/router/openssl/include
+#LIBS += -L/opt/brcm/hndtools-mipsel-uclibc-0.9.19/lib -lssl
+###############################################################################
+
+#### openwrt (e.g., for Linksys WRT54G) #######################################
+#CC=mipsel-uclibc-gcc
+#CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc
+#CFLAGS += -Os
+#CPPFLAGS=-I../src/include -I../openssl-0.9.7d/include \
+# -I../WRT54GS/release/src/include
+#LIBS = -lssl
+###############################################################################
+
+
+# Driver interface for Host AP driver
+CONFIG_DRIVER_HOSTAP=y
+
+# Driver interface for Agere driver
+#CONFIG_DRIVER_HERMES=y
+# Change include directories to match with the local setup
+#CFLAGS += -I../../hcf -I../../include -I../../include/hcf
+#CFLAGS += -I../../include/wireless
+
+# Driver interface for madwifi driver
+# Deprecated; use CONFIG_DRIVER_WEXT=y instead.
+#CONFIG_DRIVER_MADWIFI=y
+# Set include directory to the madwifi source tree
+#CFLAGS += -I../../madwifi
+
+# Driver interface for ndiswrapper
+# Deprecated; use CONFIG_DRIVER_WEXT=y instead.
+#CONFIG_DRIVER_NDISWRAPPER=y
+
+# Driver interface for Atmel driver
+# CONFIG_DRIVER_ATMEL=y
+
+# Driver interface for old Broadcom driver
+# Please note that the newer Broadcom driver ("hybrid Linux driver") supports
+# Linux wireless extensions and does not need (or even work) with the old
+# driver wrapper. Use CONFIG_DRIVER_WEXT=y with that driver.
+#CONFIG_DRIVER_BROADCOM=y
+# Example path for wlioctl.h; change to match your configuration
+#CFLAGS += -I/opt/WRT54GS/release/src/include
+
+# Driver interface for Intel ipw2100/2200 driver
+# Deprecated; use CONFIG_DRIVER_WEXT=y instead.
+#CONFIG_DRIVER_IPW=y
+
+# Driver interface for Ralink driver
+#CONFIG_DRIVER_RALINK=y
+
+# Driver interface for generic Linux wireless extensions
+CONFIG_DRIVER_WEXT=y
+
+# Driver interface for Linux drivers using the nl80211 kernel interface
+CONFIG_DRIVER_NL80211=y
+
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
+#CONFIG_DRIVER_BSD=y
+#CFLAGS += -I/usr/local/include
+#LIBS += -L/usr/local/lib
+#LIBS_p += -L/usr/local/lib
+#LIBS_c += -L/usr/local/lib
+
+# Driver interface for Windows NDIS
+#CONFIG_DRIVER_NDIS=y
+#CFLAGS += -I/usr/include/w32api/ddk
+#LIBS += -L/usr/local/lib
+# For native build using mingw
+#CONFIG_NATIVE_WINDOWS=y
+# Additional directories for cross-compilation on Linux host for mingw target
+#CFLAGS += -I/opt/mingw/mingw32/include/ddk
+#LIBS += -L/opt/mingw/mingw32/lib
+#CC=mingw32-gcc
+# By default, driver_ndis uses WinPcap for low-level operations. This can be
+# replaced with the following option which replaces WinPcap calls with NDISUIO.
+# However, this requires that WZC is disabled (net stop wzcsvc) before starting
+# wpa_supplicant.
+# CONFIG_USE_NDISUIO=y
+
+# Driver interface for development testing
+#CONFIG_DRIVER_TEST=y
+
+# Include client MLME (management frame processing) for test driver
+# This can be used to test MLME operations in hostapd with the test interface.
+# space.
+#CONFIG_CLIENT_MLME=y
+
+# Driver interface for wired Ethernet drivers
+CONFIG_DRIVER_WIRED=y
+
+# Driver interface for the Broadcom RoboSwitch family
+#CONFIG_DRIVER_ROBOSWITCH=y
+
+# Driver interface for no driver (e.g., WPS ER only)
+#CONFIG_DRIVER_NONE=y
+
+# Enable IEEE 802.1X Supplicant (automatically included if any EAP method is
+# included)
+CONFIG_IEEE8021X_EAPOL=y
+
+# EAP-MD5
+CONFIG_EAP_MD5=y
+
+# EAP-MSCHAPv2
+CONFIG_EAP_MSCHAPV2=y
+
+# EAP-TLS
+CONFIG_EAP_TLS=y
+
+# EAL-PEAP
+CONFIG_EAP_PEAP=y
+
+# EAP-TTLS
+CONFIG_EAP_TTLS=y
+
+# EAP-FAST
+# Note: Default OpenSSL package does not include support for all the
+# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
+# the OpenSSL library must be patched (openssl-0.9.8d-tls-extensions.patch)
+# to add the needed functions.
+#CONFIG_EAP_FAST=y
+
+# EAP-GTC
+CONFIG_EAP_GTC=y
+
+# EAP-OTP
+CONFIG_EAP_OTP=y
+
+# EAP-SIM (enable CONFIG_PCSC, if EAP-SIM is used)
+#CONFIG_EAP_SIM=y
+
+# EAP-PSK (experimental; this is _not_ needed for WPA-PSK)
+#CONFIG_EAP_PSK=y
+
+# EAP-PAX
+#CONFIG_EAP_PAX=y
+
+# LEAP
+CONFIG_EAP_LEAP=y
+
+# EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used)
+#CONFIG_EAP_AKA=y
+
+# EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used).
+# This requires CONFIG_EAP_AKA to be enabled, too.
+#CONFIG_EAP_AKA_PRIME=y
+
+# Enable USIM simulator (Milenage) for EAP-AKA
+#CONFIG_USIM_SIMULATOR=y
+
+# EAP-SAKE
+#CONFIG_EAP_SAKE=y
+
+# EAP-GPSK
+#CONFIG_EAP_GPSK=y
+# Include support for optional SHA256 cipher suite in EAP-GPSK
+#CONFIG_EAP_GPSK_SHA256=y
+
+# EAP-TNC and related Trusted Network Connect support (experimental)
+#CONFIG_EAP_TNC=y
+
+# Wi-Fi Protected Setup (WPS)
+CONFIG_WPS=y
+
+# EAP-IKEv2
+#CONFIG_EAP_IKEV2=y
+
+# PKCS#12 (PFX) support (used to read private key and certificate file from
+# a file that usually has extension .p12 or .pfx)
+CONFIG_PKCS12=y
+
+# Smartcard support (i.e., private key on a smartcard), e.g., with openssl
+# engine.
+CONFIG_SMARTCARD=y
+
+# PC/SC interface for smartcards (USIM, GSM SIM)
+# Enable this if EAP-SIM or EAP-AKA is included
+#CONFIG_PCSC=y
+
+# Development testing
+#CONFIG_EAPOL_TEST=y
+
+# Select control interface backend for external programs, e.g, wpa_cli:
+# unix = UNIX domain sockets (default for Linux/*BSD)
+# udp = UDP sockets using localhost (127.0.0.1)
+# named_pipe = Windows Named Pipe (default for Windows)
+# y = use default (backwards compatibility)
+# If this option is commented out, control interface is not included in the
+# build.
+CONFIG_CTRL_IFACE=y
+
+# Include support for GNU Readline and History Libraries in wpa_cli.
+# When building a wpa_cli binary for distribution, please note that these
+# libraries are licensed under GPL and as such, BSD license may not apply for
+# the resulting binary.
+#CONFIG_READLINE=y
+
+# Remove debugging code that is printing out debug message to stdout.
+# This can be used to reduce the size of the wpa_supplicant considerably
+# if debugging code is not needed. The size reduction can be around 35%
+# (e.g., 90 kB).
+#CONFIG_NO_STDOUT_DEBUG=y
+
+# Remove WPA support, e.g., for wired-only IEEE 802.1X supplicant, to save
+# 35-50 kB in code size.
+#CONFIG_NO_WPA=y
+
+# Remove WPA2 support. This allows WPA to be used, but removes WPA2 code to
+# save about 1 kB in code size when building only WPA-Personal (no EAP support)
+# or 6 kB if building for WPA-Enterprise.
+#CONFIG_NO_WPA2=y
+
+# Remove IEEE 802.11i/WPA-Personal ASCII passphrase support
+# This option can be used to reduce code size by removing support for
+# converting ASCII passphrases into PSK. If this functionality is removed, the
+# PSK can only be configured as the 64-octet hexstring (e.g., from
+# wpa_passphrase). This saves about 0.5 kB in code size.
+#CONFIG_NO_WPA_PASSPHRASE=y
+
+# Disable scan result processing (ap_mode=1) to save code size by about 1 kB.
+# This can be used if ap_scan=1 mode is never enabled.
+#CONFIG_NO_SCAN_PROCESSING=y
+
+# Select configuration backend:
+# file = text file (e.g., wpa_supplicant.conf; note: the configuration file
+# path is given on command line, not here; this option is just used to
+# select the backend that allows configuration files to be used)
+# winreg = Windows registry (see win_example.reg for an example)
+CONFIG_BACKEND=file
+
+# Remove configuration write functionality (i.e., to allow the configuration
+# file to be updated based on runtime configuration changes). The runtime
+# configuration can still be changed, the changes are just not going to be
+# persistent over restarts. This option can be used to reduce code size by
+# about 3.5 kB.
+#CONFIG_NO_CONFIG_WRITE=y
+
+# Remove support for configuration blobs to reduce code size by about 1.5 kB.
+#CONFIG_NO_CONFIG_BLOBS=y
+
+# Select program entry point implementation:
+# main = UNIX/POSIX like main() function (default)
+# main_winsvc = Windows service (read parameters from registry)
+# main_none = Very basic example (development use only)
+#CONFIG_MAIN=main
+
+# Select wrapper for operatins system and C library specific functions
+# unix = UNIX/POSIX like systems (default)
+# win32 = Windows systems
+# none = Empty template
+#CONFIG_OS=unix
+
+# Select event loop implementation
+# eloop = select() loop (default)
+# eloop_win = Windows events and WaitForMultipleObject() loop
+# eloop_none = Empty template
+#CONFIG_ELOOP=eloop
+
+# Select layer 2 packet implementation
+# linux = Linux packet socket (default)
+# pcap = libpcap/libdnet/WinPcap
+# freebsd = FreeBSD libpcap
+# winpcap = WinPcap with receive thread
+# ndis = Windows NDISUIO (note: requires CONFIG_USE_NDISUIO=y)
+# none = Empty template
+#CONFIG_L2_PACKET=linux
+
+# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
+CONFIG_PEERKEY=y
+
+# IEEE 802.11w (management frame protection)
+# This version is an experimental implementation based on IEEE 802.11w/D1.0
+# draft and is subject to change since the standard has not yet been finalized.
+# Driver support is also needed for IEEE 802.11w.
+CONFIG_IEEE80211W=y
+
+# Select TLS implementation
+# openssl = OpenSSL (default)
+# gnutls = GnuTLS (needed for TLS/IA, see also CONFIG_GNUTLS_EXTRA)
+# internal = Internal TLSv1 implementation (experimental)
+# none = Empty template
+CONFIG_TLS=internal
+
+# Whether to enable TLS/IA support, which is required for EAP-TTLSv1.
+# You need CONFIG_TLS=gnutls for this to have any effect. Please note that
+# even though the core GnuTLS library is released under LGPL, this extra
+# library uses GPL and as such, the terms of GPL apply to the combination
+# of wpa_supplicant and GnuTLS if this option is enabled. BSD license may not
+# apply for distribution of the resulting binary.
+#CONFIG_GNUTLS_EXTRA=y
+
+# If CONFIG_TLS=internal is used, additional library and include paths are
+# needed for LibTomMath. Alternatively, an integrated, minimal version of
+# LibTomMath can be used. See beginning of libtommath.c for details on benefits
+# and drawbacks of this option.
+CONFIG_INTERNAL_LIBTOMMATH=y
+#ifndef CONFIG_INTERNAL_LIBTOMMATH
+#LTM_PATH=/usr/src/libtommath-0.39
+#CFLAGS += -I$(LTM_PATH)
+#LIBS += -L$(LTM_PATH)
+#LIBS_p += -L$(LTM_PATH)
+#endif
+# At the cost of about 4 kB of additional binary size, the internal LibTomMath
+# can be configured to include faster routines for exptmod, sqr, and div to
+# speed up DH and RSA calculation considerably
+CONFIG_INTERNAL_LIBTOMMATH_FAST=y
+
+# Include NDIS event processing through WMI into wpa_supplicant/wpasvc.
+# This is only for Windows builds and requires WMI-related header files and
+# WbemUuid.Lib from Platform SDK even when building with MinGW.
+#CONFIG_NDIS_EVENTS_INTEGRATED=y
+#PLATFORMSDKLIB="/opt/Program Files/Microsoft Platform SDK/Lib"
+
+# Add support for old DBus control interface
+# (fi.epitest.hostap.WPASupplicant)
+#CONFIG_CTRL_IFACE_DBUS=y
+
+# Add support for new DBus control interface
+# (fi.w1.hostap.wpa_supplicant1)
+#CONFIG_CTRL_IFACE_DBUS_NEW=y
+
+# Add introspection support for new DBus control interface
+#CONFIG_CTRL_IFACE_DBUS_INTRO=y
+
+# Add support for loading EAP methods dynamically as shared libraries.
+# When this option is enabled, each EAP method can be either included
+# statically (CONFIG_EAP_<method>=y) or dynamically (CONFIG_EAP_<method>=dyn).
+# Dynamic EAP methods are build as shared objects (eap_*.so) and they need to
+# be loaded in the beginning of the wpa_supplicant configuration file
+# (see load_dynamic_eap parameter in the example file) before being used in
+# the network blocks.
+#
+# Note that some shared parts of EAP methods are included in the main program
+# and in order to be able to use dynamic EAP methods using these parts, the
+# main program must have been build with the EAP method enabled (=y or =dyn).
+# This means that EAP-TLS/PEAP/TTLS/FAST cannot be added as dynamic libraries
+# unless at least one of them was included in the main build to force inclusion
+# of the shared code. Similarly, at least one of EAP-SIM/AKA must be included
+# in the main build to be able to load these methods dynamically.
+#
+# Please also note that using dynamic libraries will increase the total binary
+# size. Thus, it may not be the best option for targets that have limited
+# amount of memory/flash.
+#CONFIG_DYNAMIC_EAP_METHODS=y
+
+# IEEE Std 802.11r-2008 (Fast BSS Transition)
+#CONFIG_IEEE80211R=y
+
+# Add support for writing debug log to a file (/tmp/wpa_supplicant-log-#.txt)
+#CONFIG_DEBUG_FILE=y
+
+# Enable privilege separation (see README 'Privilege separation' for details)
+#CONFIG_PRIVSEP=y
+
+# Enable mitigation against certain attacks against TKIP by delaying Michael
+# MIC error reports by a random amount of time between 0 and 60 seconds
+#CONFIG_DELAYED_MIC_ERROR_REPORT=y
+
+# Enable tracing code for developer debugging
+# This tracks use of memory allocations and other registrations and reports
+# incorrect use with a backtrace of call (or allocation) location.
+#CONFIG_WPA_TRACE=y
+# For BSD, comment out these.
+#LIBS += -lexecinfo
+#LIBS_p += -lexecinfo
+#LIBS_c += -lexecinfo
+
+# Use libbfd to get more details for developer debugging
+# This enables use of libbfd to get more detailed symbols for the backtraces
+# generated by CONFIG_WPA_TRACE=y.
+#CONFIG_WPA_TRACE_BFD=y
+# For BSD, comment out these.
+#LIBS += -lbfd -liberty -lz
+#LIBS_p += -lbfd -liberty -lz
+#LIBS_c += -lbfd -liberty -lz
+
+NEED_80211_COMMON=y
+
+CONFIG_IBSS_RSN=y
diff --git a/package/hostapd/files/wpa_supplicant-mini.config b/package/hostapd/files/wpa_supplicant-mini.config
new file mode 100644
index 000000000..772e1d980
--- /dev/null
+++ b/package/hostapd/files/wpa_supplicant-mini.config
@@ -0,0 +1,406 @@
+# Example wpa_supplicant build time configuration
+#
+# This file lists the configuration options that are used when building the
+# hostapd binary. All lines starting with # are ignored. Configuration option
+# lines must be commented out complete, if they are not to be included, i.e.,
+# just setting VARIABLE=n is not disabling that variable.
+#
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
+# be modified from here. In most cases, these lines should use += in order not
+# to override previous values of the variables.
+
+
+# Uncomment following two lines and fix the paths if you have installed OpenSSL
+# or GnuTLS in non-default location
+#CFLAGS += -I/usr/local/openssl/include
+#LIBS += -L/usr/local/openssl/lib
+
+# Some Red Hat versions seem to include kerberos header files from OpenSSL, but
+# the kerberos files are not in the default include path. Following line can be
+# used to fix build issues on such systems (krb5.h not found).
+#CFLAGS += -I/usr/include/kerberos
+
+# Example configuration for various cross-compilation platforms
+
+#### sveasoft (e.g., for Linksys WRT54G) ######################################
+#CC=mipsel-uclibc-gcc
+#CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc
+#CFLAGS += -Os
+#CPPFLAGS += -I../src/include -I../../src/router/openssl/include
+#LIBS += -L/opt/brcm/hndtools-mipsel-uclibc-0.9.19/lib -lssl
+###############################################################################
+
+#### openwrt (e.g., for Linksys WRT54G) #######################################
+#CC=mipsel-uclibc-gcc
+#CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc
+#CFLAGS += -Os
+#CPPFLAGS=-I../src/include -I../openssl-0.9.7d/include \
+# -I../WRT54GS/release/src/include
+#LIBS = -lssl
+###############################################################################
+
+
+# Driver interface for Host AP driver
+CONFIG_DRIVER_HOSTAP=y
+
+# Driver interface for Agere driver
+#CONFIG_DRIVER_HERMES=y
+# Change include directories to match with the local setup
+#CFLAGS += -I../../hcf -I../../include -I../../include/hcf
+#CFLAGS += -I../../include/wireless
+
+# Driver interface for madwifi driver
+# Deprecated; use CONFIG_DRIVER_WEXT=y instead.
+#CONFIG_DRIVER_MADWIFI=y
+# Set include directory to the madwifi source tree
+#CFLAGS += -I../../madwifi
+
+# Driver interface for ndiswrapper
+# Deprecated; use CONFIG_DRIVER_WEXT=y instead.
+#CONFIG_DRIVER_NDISWRAPPER=y
+
+# Driver interface for Atmel driver
+# CONFIG_DRIVER_ATMEL=y
+
+# Driver interface for old Broadcom driver
+# Please note that the newer Broadcom driver ("hybrid Linux driver") supports
+# Linux wireless extensions and does not need (or even work) with the old
+# driver wrapper. Use CONFIG_DRIVER_WEXT=y with that driver.
+#CONFIG_DRIVER_BROADCOM=y
+# Example path for wlioctl.h; change to match your configuration
+#CFLAGS += -I/opt/WRT54GS/release/src/include
+
+# Driver interface for Intel ipw2100/2200 driver
+# Deprecated; use CONFIG_DRIVER_WEXT=y instead.
+#CONFIG_DRIVER_IPW=y
+
+# Driver interface for Ralink driver
+#CONFIG_DRIVER_RALINK=y
+
+# Driver interface for generic Linux wireless extensions
+CONFIG_DRIVER_WEXT=y
+
+# Driver interface for Linux drivers using the nl80211 kernel interface
+CONFIG_DRIVER_NL80211=y
+
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
+#CONFIG_DRIVER_BSD=y
+#CFLAGS += -I/usr/local/include
+#LIBS += -L/usr/local/lib
+#LIBS_p += -L/usr/local/lib
+#LIBS_c += -L/usr/local/lib
+
+# Driver interface for Windows NDIS
+#CONFIG_DRIVER_NDIS=y
+#CFLAGS += -I/usr/include/w32api/ddk
+#LIBS += -L/usr/local/lib
+# For native build using mingw
+#CONFIG_NATIVE_WINDOWS=y
+# Additional directories for cross-compilation on Linux host for mingw target
+#CFLAGS += -I/opt/mingw/mingw32/include/ddk
+#LIBS += -L/opt/mingw/mingw32/lib
+#CC=mingw32-gcc
+# By default, driver_ndis uses WinPcap for low-level operations. This can be
+# replaced with the following option which replaces WinPcap calls with NDISUIO.
+# However, this requires that WZC is disabled (net stop wzcsvc) before starting
+# wpa_supplicant.
+# CONFIG_USE_NDISUIO=y
+
+# Driver interface for development testing
+#CONFIG_DRIVER_TEST=y
+
+# Include client MLME (management frame processing) for test driver
+# This can be used to test MLME operations in hostapd with the test interface.
+# space.
+#CONFIG_CLIENT_MLME=y
+
+# Driver interface for wired Ethernet drivers
+CONFIG_DRIVER_WIRED=y
+
+# Driver interface for the Broadcom RoboSwitch family
+#CONFIG_DRIVER_ROBOSWITCH=y
+
+# Driver interface for no driver (e.g., WPS ER only)
+#CONFIG_DRIVER_NONE=y
+
+# Enable IEEE 802.1X Supplicant (automatically included if any EAP method is
+# included)
+# CONFIG_IEEE8021X_EAPOL=y
+
+# EAP-MD5
+# CONFIG_EAP_MD5=y
+
+# EAP-MSCHAPv2
+# CONFIG_EAP_MSCHAPV2=y
+
+# EAP-TLS
+# CONFIG_EAP_TLS=y
+
+# EAL-PEAP
+# CONFIG_EAP_PEAP=y
+
+# EAP-TTLS
+# CONFIG_EAP_TTLS=y
+
+# EAP-FAST
+# Note: Default OpenSSL package does not include support for all the
+# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
+# the OpenSSL library must be patched (openssl-0.9.8d-tls-extensions.patch)
+# to add the needed functions.
+#CONFIG_EAP_FAST=y
+
+# EAP-GTC
+# CONFIG_EAP_GTC=y
+
+# EAP-OTP
+# CONFIG_EAP_OTP=y
+
+# EAP-SIM (enable CONFIG_PCSC, if EAP-SIM is used)
+#CONFIG_EAP_SIM=y
+
+# EAP-PSK (experimental; this is _not_ needed for WPA-PSK)
+#CONFIG_EAP_PSK=y
+
+# EAP-PAX
+#CONFIG_EAP_PAX=y
+
+# LEAP
+# CONFIG_EAP_LEAP=y
+
+# EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used)
+#CONFIG_EAP_AKA=y
+
+# EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used).
+# This requires CONFIG_EAP_AKA to be enabled, too.
+#CONFIG_EAP_AKA_PRIME=y
+
+# Enable USIM simulator (Milenage) for EAP-AKA
+#CONFIG_USIM_SIMULATOR=y
+
+# EAP-SAKE
+#CONFIG_EAP_SAKE=y
+
+# EAP-GPSK
+#CONFIG_EAP_GPSK=y
+# Include support for optional SHA256 cipher suite in EAP-GPSK
+#CONFIG_EAP_GPSK_SHA256=y
+
+# EAP-TNC and related Trusted Network Connect support (experimental)
+#CONFIG_EAP_TNC=y
+
+# Wi-Fi Protected Setup (WPS)
+#CONFIG_WPS=y
+
+# EAP-IKEv2
+#CONFIG_EAP_IKEV2=y
+
+# PKCS#12 (PFX) support (used to read private key and certificate file from
+# a file that usually has extension .p12 or .pfx)
+# CONFIG_PKCS12=y
+
+# Smartcard support (i.e., private key on a smartcard), e.g., with openssl
+# engine.
+# CONFIG_SMARTCARD=y
+
+# PC/SC interface for smartcards (USIM, GSM SIM)
+# Enable this if EAP-SIM or EAP-AKA is included
+#CONFIG_PCSC=y
+
+# Development testing
+#CONFIG_EAPOL_TEST=y
+
+# Select control interface backend for external programs, e.g, wpa_cli:
+# unix = UNIX domain sockets (default for Linux/*BSD)
+# udp = UDP sockets using localhost (127.0.0.1)
+# named_pipe = Windows Named Pipe (default for Windows)
+# y = use default (backwards compatibility)
+# If this option is commented out, control interface is not included in the
+# build.
+CONFIG_CTRL_IFACE=y
+
+# Include support for GNU Readline and History Libraries in wpa_cli.
+# When building a wpa_cli binary for distribution, please note that these
+# libraries are licensed under GPL and as such, BSD license may not apply for
+# the resulting binary.
+#CONFIG_READLINE=y
+
+# Remove debugging code that is printing out debug message to stdout.
+# This can be used to reduce the size of the wpa_supplicant considerably
+# if debugging code is not needed. The size reduction can be around 35%
+# (e.g., 90 kB).
+#CONFIG_NO_STDOUT_DEBUG=y
+
+# Remove WPA support, e.g., for wired-only IEEE 802.1X supplicant, to save
+# 35-50 kB in code size.
+#CONFIG_NO_WPA=y
+
+# Remove WPA2 support. This allows WPA to be used, but removes WPA2 code to
+# save about 1 kB in code size when building only WPA-Personal (no EAP support)
+# or 6 kB if building for WPA-Enterprise.
+#CONFIG_NO_WPA2=y
+
+# Remove IEEE 802.11i/WPA-Personal ASCII passphrase support
+# This option can be used to reduce code size by removing support for
+# converting ASCII passphrases into PSK. If this functionality is removed, the
+# PSK can only be configured as the 64-octet hexstring (e.g., from
+# wpa_passphrase). This saves about 0.5 kB in code size.
+#CONFIG_NO_WPA_PASSPHRASE=y
+
+# Disable scan result processing (ap_mode=1) to save code size by about 1 kB.
+# This can be used if ap_scan=1 mode is never enabled.
+#CONFIG_NO_SCAN_PROCESSING=y
+
+# Select configuration backend:
+# file = text file (e.g., wpa_supplicant.conf; note: the configuration file
+# path is given on command line, not here; this option is just used to
+# select the backend that allows configuration files to be used)
+# winreg = Windows registry (see win_example.reg for an example)
+CONFIG_BACKEND=file
+
+# Remove configuration write functionality (i.e., to allow the configuration
+# file to be updated based on runtime configuration changes). The runtime
+# configuration can still be changed, the changes are just not going to be
+# persistent over restarts. This option can be used to reduce code size by
+# about 3.5 kB.
+#CONFIG_NO_CONFIG_WRITE=y
+
+# Remove support for configuration blobs to reduce code size by about 1.5 kB.
+#CONFIG_NO_CONFIG_BLOBS=y
+
+# Select program entry point implementation:
+# main = UNIX/POSIX like main() function (default)
+# main_winsvc = Windows service (read parameters from registry)
+# main_none = Very basic example (development use only)
+#CONFIG_MAIN=main
+
+# Select wrapper for operatins system and C library specific functions
+# unix = UNIX/POSIX like systems (default)
+# win32 = Windows systems
+# none = Empty template
+#CONFIG_OS=unix
+
+# Select event loop implementation
+# eloop = select() loop (default)
+# eloop_win = Windows events and WaitForMultipleObject() loop
+# eloop_none = Empty template
+#CONFIG_ELOOP=eloop
+
+# Select layer 2 packet implementation
+# linux = Linux packet socket (default)
+# pcap = libpcap/libdnet/WinPcap
+# freebsd = FreeBSD libpcap
+# winpcap = WinPcap with receive thread
+# ndis = Windows NDISUIO (note: requires CONFIG_USE_NDISUIO=y)
+# none = Empty template
+#CONFIG_L2_PACKET=linux
+
+# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
+# CONFIG_PEERKEY=y
+
+# IEEE 802.11w (management frame protection)
+# This version is an experimental implementation based on IEEE 802.11w/D1.0
+# draft and is subject to change since the standard has not yet been finalized.
+# Driver support is also needed for IEEE 802.11w.
+#CONFIG_IEEE80211W=y
+
+# Select TLS implementation
+# openssl = OpenSSL (default)
+# gnutls = GnuTLS (needed for TLS/IA, see also CONFIG_GNUTLS_EXTRA)
+# internal = Internal TLSv1 implementation (experimental)
+# none = Empty template
+CONFIG_TLS=internal
+
+# Whether to enable TLS/IA support, which is required for EAP-TTLSv1.
+# You need CONFIG_TLS=gnutls for this to have any effect. Please note that
+# even though the core GnuTLS library is released under LGPL, this extra
+# library uses GPL and as such, the terms of GPL apply to the combination
+# of wpa_supplicant and GnuTLS if this option is enabled. BSD license may not
+# apply for distribution of the resulting binary.
+#CONFIG_GNUTLS_EXTRA=y
+
+# If CONFIG_TLS=internal is used, additional library and include paths are
+# needed for LibTomMath. Alternatively, an integrated, minimal version of
+# LibTomMath can be used. See beginning of libtommath.c for details on benefits
+# and drawbacks of this option.
+#CONFIG_INTERNAL_LIBTOMMATH=y
+#ifndef CONFIG_INTERNAL_LIBTOMMATH
+#LTM_PATH=/usr/src/libtommath-0.39
+#CFLAGS += -I$(LTM_PATH)
+#LIBS += -L$(LTM_PATH)
+#LIBS_p += -L$(LTM_PATH)
+#endif
+# At the cost of about 4 kB of additional binary size, the internal LibTomMath
+# can be configured to include faster routines for exptmod, sqr, and div to
+# speed up DH and RSA calculation considerably
+#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
+
+# Include NDIS event processing through WMI into wpa_supplicant/wpasvc.
+# This is only for Windows builds and requires WMI-related header files and
+# WbemUuid.Lib from Platform SDK even when building with MinGW.
+#CONFIG_NDIS_EVENTS_INTEGRATED=y
+#PLATFORMSDKLIB="/opt/Program Files/Microsoft Platform SDK/Lib"
+
+# Add support for old DBus control interface
+# (fi.epitest.hostap.WPASupplicant)
+#CONFIG_CTRL_IFACE_DBUS=y
+
+# Add support for new DBus control interface
+# (fi.w1.hostap.wpa_supplicant1)
+#CONFIG_CTRL_IFACE_DBUS_NEW=y
+
+# Add introspection support for new DBus control interface
+#CONFIG_CTRL_IFACE_DBUS_INTRO=y
+
+# Add support for loading EAP methods dynamically as shared libraries.
+# When this option is enabled, each EAP method can be either included
+# statically (CONFIG_EAP_<method>=y) or dynamically (CONFIG_EAP_<method>=dyn).
+# Dynamic EAP methods are build as shared objects (eap_*.so) and they need to
+# be loaded in the beginning of the wpa_supplicant configuration file
+# (see load_dynamic_eap parameter in the example file) before being used in
+# the network blocks.
+#
+# Note that some shared parts of EAP methods are included in the main program
+# and in order to be able to use dynamic EAP methods using these parts, the
+# main program must have been build with the EAP method enabled (=y or =dyn).
+# This means that EAP-TLS/PEAP/TTLS/FAST cannot be added as dynamic libraries
+# unless at least one of them was included in the main build to force inclusion
+# of the shared code. Similarly, at least one of EAP-SIM/AKA must be included
+# in the main build to be able to load these methods dynamically.
+#
+# Please also note that using dynamic libraries will increase the total binary
+# size. Thus, it may not be the best option for targets that have limited
+# amount of memory/flash.
+#CONFIG_DYNAMIC_EAP_METHODS=y
+
+# IEEE Std 802.11r-2008 (Fast BSS Transition)
+#CONFIG_IEEE80211R=y
+
+# Add support for writing debug log to a file (/tmp/wpa_supplicant-log-#.txt)
+#CONFIG_DEBUG_FILE=y
+
+# Enable privilege separation (see README 'Privilege separation' for details)
+#CONFIG_PRIVSEP=y
+
+# Enable mitigation against certain attacks against TKIP by delaying Michael
+# MIC error reports by a random amount of time between 0 and 60 seconds
+#CONFIG_DELAYED_MIC_ERROR_REPORT=y
+
+# Enable tracing code for developer debugging
+# This tracks use of memory allocations and other registrations and reports
+# incorrect use with a backtrace of call (or allocation) location.
+#CONFIG_WPA_TRACE=y
+# For BSD, comment out these.
+#LIBS += -lexecinfo
+#LIBS_p += -lexecinfo
+#LIBS_c += -lexecinfo
+
+# Use libbfd to get more details for developer debugging
+# This enables use of libbfd to get more detailed symbols for the backtraces
+# generated by CONFIG_WPA_TRACE=y.
+#CONFIG_WPA_TRACE_BFD=y
+# For BSD, comment out these.
+#LIBS += -lbfd -liberty -lz
+#LIBS_p += -lbfd -liberty -lz
+#LIBS_c += -lbfd -liberty -lz
+
+NEED_80211_COMMON=y
diff --git a/package/hostapd/files/wpa_supplicant.sh b/package/hostapd/files/wpa_supplicant.sh
new file mode 100644
index 000000000..5c4bd93d0
--- /dev/null
+++ b/package/hostapd/files/wpa_supplicant.sh
@@ -0,0 +1,196 @@
+wpa_supplicant_setup_vif() {
+ local vif="$1"
+ local driver="$2"
+ local key="$key"
+ local options="$3"
+ local freq=""
+ local ht="$5"
+ local ap_scan=""
+ local scan_ssid="1"
+ [ -n "$4" ] && freq="frequency=$4"
+
+ # make sure we have the encryption type and the psk
+ [ -n "$enc" ] || {
+ config_get enc "$vif" encryption
+ }
+ [ -n "$key" ] || {
+ config_get key "$vif" key
+ }
+
+ local net_cfg bridge
+ config_get bridge "$vif" bridge
+ [ -z "$bridge" ] && {
+ net_cfg="$(find_net_config "$vif")"
+ [ -z "$net_cfg" ] || bridge="$(bridge_interface "$net_cfg")"
+ config_set "$vif" bridge "$bridge"
+ }
+
+ local mode ifname wds modestr=""
+ config_get mode "$vif" mode
+ config_get ifname "$vif" ifname
+ config_get_bool wds "$vif" wds 0
+ [ -z "$bridge" ] || [ "$mode" = ap ] || [ "$mode" = sta -a $wds -eq 1 ] || {
+ echo "wpa_supplicant_setup_vif($ifname): Refusing to bridge $mode mode interface"
+ return 1
+ }
+ [ "$mode" = "adhoc" ] && {
+ modestr="mode=1"
+ scan_ssid="0"
+ ap_scan="ap_scan=2"
+ }
+
+ key_mgmt='NONE'
+ case "$enc" in
+ *none*) ;;
+ *wep*)
+ config_get key "$vif" key
+ key="${key:-1}"
+ case "$key" in
+ [1234])
+ for idx in 1 2 3 4; do
+ local zidx
+ zidx=$(($idx - 1))
+ config_get ckey "$vif" "key${idx}"
+ [ -n "$ckey" ] && \
+ append "wep_key${zidx}" "wep_key${zidx}=$(prepare_key_wep "$ckey")"
+ done
+ wep_tx_keyidx="wep_tx_keyidx=$((key - 1))"
+ ;;
+ *)
+ wep_key0="wep_key0=$(prepare_key_wep "$key")"
+ wep_tx_keyidx="wep_tx_keyidx=0"
+ ;;
+ esac
+ ;;
+ *psk*)
+ key_mgmt='WPA-PSK'
+ # if you want to use PSK with a non-nl80211 driver you
+ # have to use WPA-NONE and wext driver for wpa_s
+ [ "$mode" = "adhoc" -a "$driver" != "nl80211" ] && {
+ key_mgmt='WPA-NONE'
+ driver='wext'
+ }
+ if [ ${#key} -eq 64 ]; then
+ passphrase="psk=${key}"
+ else
+ passphrase="psk=\"${key}\""
+ fi
+ case "$enc" in
+ *psk2*)
+ proto='proto=RSN'
+ config_get ieee80211w "$vif" ieee80211w
+ ;;
+ *psk*)
+ proto='proto=WPA'
+ ;;
+ esac
+ ;;
+ *wpa*|*8021x*)
+ proto='proto=WPA2'
+ key_mgmt='WPA-EAP'
+ config_get ieee80211w "$vif" ieee80211w
+ config_get ca_cert "$vif" ca_cert
+ config_get eap_type "$vif" eap_type
+ ca_cert=${ca_cert:+"ca_cert=\"$ca_cert\""}
+ case "$eap_type" in
+ tls)
+ pairwise='pairwise=CCMP'
+ group='group=CCMP'
+ config_get identity "$vif" identity
+ config_get client_cert "$vif" client_cert
+ config_get priv_key "$vif" priv_key
+ config_get priv_key_pwd "$vif" priv_key_pwd
+ identity="identity=\"$identity\""
+ client_cert="client_cert=\"$client_cert\""
+ priv_key="private_key=\"$priv_key\""
+ priv_key_pwd="private_key_passwd=\"$priv_key_pwd\""
+ ;;
+ peap|ttls)
+ config_get auth "$vif" auth
+ config_get identity "$vif" identity
+ config_get password "$vif" password
+ phase2="phase2=\"auth=${auth:-MSCHAPV2}\""
+ identity="identity=\"$identity\""
+ password="password=\"$password\""
+ ;;
+ esac
+ eap_type="eap=$(echo $eap_type | tr 'a-z' 'A-Z')"
+ ;;
+ esac
+
+ case "$ieee80211w" in
+ [012])
+ ieee80211w="ieee80211w=$ieee80211w"
+ ;;
+ esac
+
+ local fixed_freq bssid1 beacon_interval brates mrate
+ config_get ifname "$vif" ifname
+ config_get bridge "$vif" bridge
+ config_get ssid "$vif" ssid
+ config_get bssid "$vif" bssid
+ bssid1=${bssid:+"bssid=$bssid"}
+ beacon_interval=${beacon_int:+"beacon_interval=$beacon_int"}
+
+ local br brval brsub brstr
+ [ -n "$basic_rate_list" ] && {
+ for br in $basic_rate_list; do
+ brval="$(($br / 1000))"
+ brsub="$((($br / 100) % 10))"
+ [ "$brsub" -gt 0 ] && brval="$brval.$brsub"
+ [ -n "$brstr" ] && brstr="$brstr,"
+ brstr="$brstr$brval"
+ done
+ brates=${basic_rate_list:+"rates=$brstr"}
+ }
+
+ local mcval=""
+ [ -n "$mcast_rate" ] && {
+ mcval="$(($mcast_rate / 1000))"
+ mcsub="$(( ($mcast_rate / 100) % 10 ))"
+ [ "$mcsub" -gt 0 ] && mcval="$mcval.$mcsub"
+ mrate=${mcast_rate:+"mcast_rate=$mcval"}
+ }
+
+ local ht_str
+ [ -n "$ht" ] && ht_str="htmode=$ht"
+
+ rm -rf /var/run/wpa_supplicant-$ifname
+ cat > /var/run/wpa_supplicant-$ifname.conf <<EOF
+ctrl_interface=/var/run/wpa_supplicant-$ifname
+$ap_scan
+network={
+ $modestr
+ scan_ssid=$scan_ssid
+ ssid="$ssid"
+ $bssid1
+ key_mgmt=$key_mgmt
+ $proto
+ $freq
+ ${fixed:+"fixed_freq=1"}
+ $beacon_interval
+ $brates
+ $mrate
+ $ht_str
+ $ieee80211w
+ $passphrase
+ $pairwise
+ $group
+ $eap_type
+ $ca_cert
+ $client_cert
+ $priv_key
+ $priv_key_pwd
+ $phase2
+ $identity
+ $password
+ $wep_key0
+ $wep_key1
+ $wep_key2
+ $wep_key3
+ $wep_tx_keyidx
+}
+EOF
+ [ -z "$proto" -a "$key_mgmt" != "NONE" ] || \
+ wpa_supplicant ${bridge:+ -b $bridge} -B -P "/var/run/wifi-${ifname}.pid" -D ${driver:-wext} -i "$ifname" -c /var/run/wpa_supplicant-$ifname.conf $options
+}
diff --git a/package/hostapd/files/wps-hotplug.sh b/package/hostapd/files/wps-hotplug.sh
new file mode 100644
index 000000000..b5376cc55
--- /dev/null
+++ b/package/hostapd/files/wps-hotplug.sh
@@ -0,0 +1,6 @@
+if [ "$ACTION" = "pressed" -a "$BUTTON" = "wps" ]; then
+ for dir in /var/run/hostapd-*; do
+ [ -d "$dir" ] || continue
+ hostapd_cli -p "$dir" wps_pbc
+ done
+fi
diff --git a/package/hostapd/patches/100-pending_work.patch b/package/hostapd/patches/100-pending_work.patch
new file mode 100644
index 000000000..1c97a64ca
--- /dev/null
+++ b/package/hostapd/patches/100-pending_work.patch
@@ -0,0 +1,123 @@
+--- a/src/ap/ieee802_11.c
++++ b/src/ap/ieee802_11.c
+@@ -1506,13 +1506,6 @@ static void handle_assoc_cb(struct hosta
+ int new_assoc = 1;
+ struct ieee80211_ht_capabilities ht_cap;
+
+- if (!ok) {
+- hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
+- HOSTAPD_LEVEL_DEBUG,
+- "did not acknowledge association response");
+- return;
+- }
+-
+ if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) :
+ sizeof(mgmt->u.assoc_resp))) {
+ printf("handle_assoc_cb(reassoc=%d) - too short payload "
+@@ -1520,11 +1513,6 @@ static void handle_assoc_cb(struct hosta
+ return;
+ }
+
+- if (reassoc)
+- status = le_to_host16(mgmt->u.reassoc_resp.status_code);
+- else
+- status = le_to_host16(mgmt->u.assoc_resp.status_code);
+-
+ sta = ap_get_sta(hapd, mgmt->da);
+ if (!sta) {
+ printf("handle_assoc_cb: STA " MACSTR " not found\n",
+@@ -1532,6 +1520,19 @@ static void handle_assoc_cb(struct hosta
+ return;
+ }
+
++ if (!ok) {
++ hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
++ HOSTAPD_LEVEL_DEBUG,
++ "did not acknowledge association response");
++ sta->flags &= ~WLAN_STA_ASSOC_REQ_OK;
++ return;
++ }
++
++ if (reassoc)
++ status = le_to_host16(mgmt->u.reassoc_resp.status_code);
++ else
++ status = le_to_host16(mgmt->u.assoc_resp.status_code);
++
+ if (status != WLAN_STATUS_SUCCESS)
+ goto fail;
+
+@@ -1830,6 +1831,9 @@ void ieee802_11_rx_from_unknown(struct h
+
+ sta = ap_get_sta(hapd, src);
+ if (sta && (sta->flags & WLAN_STA_ASSOC)) {
++ if (!hapd->conf->wds_sta)
++ return;
++
+ if (wds && !(sta->flags & WLAN_STA_WDS)) {
+ wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for "
+ "STA " MACSTR " (aid %u)",
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -2661,10 +2661,10 @@ static int wpa_driver_nl80211_capa(struc
+ drv->data_tx_status = info.data_tx_status;
+
+ /*
+- * If poll command is supported mac80211 is new enough to
+- * have everything we need to not need monitor interfaces.
++ * If poll command and tx status are supported, mac80211 is new enough
++ * to have everything we need to not need monitor interfaces.
+ */
+- drv->use_monitor = !info.poll_command_supported;
++ drv->use_monitor = !info.poll_command_supported || !info.data_tx_status;
+
+ if (drv->device_ap_sme && drv->use_monitor) {
+ /*
+@@ -6392,8 +6392,8 @@ static int wpa_driver_nl80211_hapd_send_
+ pos = (u8 *) (hdr + 1);
+
+ if (qos) {
+- /* add an empty QoS header if needed */
+- pos[0] = 0;
++ /* Set highest priority in QoS header */
++ pos[0] = 7;
+ pos[1] = 0;
+ pos += 2;
+ }
+@@ -7698,6 +7698,10 @@ static int i802_set_wds_sta(void *priv,
+ }
+ return i802_set_sta_vlan(priv, addr, name, 0);
+ } else {
++ if (bridge_ifname)
++ linux_br_del_if(drv->global->ioctl_sock, bridge_ifname,
++ name);
++
+ i802_set_sta_vlan(priv, addr, bss->ifname, 0);
+ return wpa_driver_nl80211_if_remove(priv, WPA_IF_AP_VLAN,
+ name);
+@@ -8065,7 +8069,12 @@ static int wpa_driver_nl80211_if_remove(
+ if (ifindex <= 0)
+ return -1;
+
++ nl80211_remove_iface(drv, ifindex);
++
+ #ifdef HOSTAPD
++ if (type != WPA_IF_AP_BSS)
++ return 0;
++
+ if (bss->added_if_into_bridge) {
+ if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
+ bss->ifname) < 0)
+@@ -8079,13 +8088,6 @@ static int wpa_driver_nl80211_if_remove(
+ "bridge %s: %s",
+ bss->brname, strerror(errno));
+ }
+-#endif /* HOSTAPD */
+-
+- nl80211_remove_iface(drv, ifindex);
+-
+-#ifdef HOSTAPD
+- if (type != WPA_IF_AP_BSS)
+- return 0;
+
+ if (bss != &drv->first_bss) {
+ struct i802_bss *tbss;
diff --git a/package/hostapd/patches/300-nl80211_multicall_fixes.patch b/package/hostapd/patches/300-nl80211_multicall_fixes.patch
new file mode 100644
index 000000000..1d2519a93
--- /dev/null
+++ b/package/hostapd/patches/300-nl80211_multicall_fixes.patch
@@ -0,0 +1,60 @@
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -2988,6 +2988,7 @@ static void * wpa_driver_nl80211_init(vo
+ drv->monitor_sock = -1;
+ drv->eapol_tx_sock = -1;
+ drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
++ drv->nlmode = NL80211_IFTYPE_STATION;
+
+ if (wpa_driver_nl80211_init_nl(drv)) {
+ os_free(drv);
+@@ -3302,17 +3303,12 @@ static void wpa_driver_nl80211_send_rfki
+ wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);
+ }
+
+-
+ static int
+-wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
++wpa_driver_nl80211_finish_drv_init_sta(struct wpa_driver_nl80211_data *drv,
++ int *send_rfkill_event)
+ {
+ struct i802_bss *bss = &drv->first_bss;
+- int send_rfkill_event = 0;
+
+- drv->ifindex = if_nametoindex(bss->ifname);
+- drv->first_bss.ifindex = drv->ifindex;
+-
+-#ifndef HOSTAPD
+ /*
+ * Make sure the interface starts up in station mode unless this is a
+ * dynamically added interface (e.g., P2P) that was already configured
+@@ -3331,7 +3327,7 @@ wpa_driver_nl80211_finish_drv_init(struc
+ "interface '%s' due to rfkill",
+ bss->ifname);
+ drv->if_disabled = 1;
+- send_rfkill_event = 1;
++ *send_rfkill_event = 1;
+ } else {
+ wpa_printf(MSG_ERROR, "nl80211: Could not set "
+ "interface '%s' UP", bss->ifname);
+@@ -3341,7 +3337,19 @@ wpa_driver_nl80211_finish_drv_init(struc
+
+ netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
+ 1, IF_OPER_DORMANT);
+-#endif /* HOSTAPD */
++}
++
++static int
++wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
++{
++ struct i802_bss *bss = &drv->first_bss;
++ int send_rfkill_event = 0;
++
++ drv->ifindex = if_nametoindex(bss->ifname);
++ drv->first_bss.ifindex = drv->ifindex;
++
++ if (drv->nlmode == NL80211_IFTYPE_STATION)
++ wpa_driver_nl80211_finish_drv_init_sta(drv, &send_rfkill_event);
+
+ if (wpa_driver_nl80211_capa(drv))
+ return -1;
diff --git a/package/hostapd/patches/310-multicall_bridge_fix.patch b/package/hostapd/patches/310-multicall_bridge_fix.patch
new file mode 100644
index 000000000..59bfe5177
--- /dev/null
+++ b/package/hostapd/patches/310-multicall_bridge_fix.patch
@@ -0,0 +1,45 @@
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -893,6 +893,10 @@ static void wpa_driver_nl80211_event_rtm
+ return;
+ }
+
++ if (ifi->ifi_family == AF_BRIDGE &&
++ drv->nlmode != NL80211_IFTYPE_AP)
++ return;
++
+ wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x "
+ "(%s%s%s%s)",
+ drv->operstate, ifi->ifi_flags,
+@@ -1000,6 +1004,10 @@ static void wpa_driver_nl80211_event_rtm
+ attrlen = len;
+ attr = (struct rtattr *) buf;
+
++ if (ifi->ifi_family == AF_BRIDGE &&
++ drv->nlmode != NL80211_IFTYPE_AP)
++ return;
++
+ rta_len = RTA_ALIGN(sizeof(struct rtattr));
+ while (RTA_OK(attr, attrlen)) {
+ if (attr->rta_type == IFLA_IFNAME) {
+@@ -2990,6 +2998,11 @@ static void * wpa_driver_nl80211_init(vo
+ drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
+ drv->nlmode = NL80211_IFTYPE_STATION;
+
++#ifdef HOSTAPD
++ drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);
++ drv->if_indices = drv->default_if_indices;
++#endif
++
+ if (wpa_driver_nl80211_init_nl(drv)) {
+ os_free(drv);
+ return NULL;
+@@ -7819,8 +7832,6 @@ static void *i802_init(struct hostapd_da
+ br_ifindex = 0;
+ }
+
+- drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);
+- drv->if_indices = drv->default_if_indices;
+ for (i = 0; i < params->num_bridge; i++) {
+ if (params->bridge[i]) {
+ ifindex = if_nametoindex(params->bridge[i]);
diff --git a/package/hostapd/patches/320-madwifi_key_fixes.patch b/package/hostapd/patches/320-madwifi_key_fixes.patch
new file mode 100644
index 000000000..45a7ac6c8
--- /dev/null
+++ b/package/hostapd/patches/320-madwifi_key_fixes.patch
@@ -0,0 +1,34 @@
+--- a/src/drivers/driver_madwifi.c
++++ b/src/drivers/driver_madwifi.c
+@@ -453,7 +453,9 @@ wpa_driver_madwifi_set_key(const char *i
+
+ memset(&wk, 0, sizeof(wk));
+ wk.ik_type = cipher;
+- wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT;
++ wk.ik_flags = IEEE80211_KEY_RECV;
++ if (set_tx)
++ wk.ik_flags |= IEEE80211_KEY_XMIT;
+ if (addr == NULL || is_broadcast_ether_addr(addr)) {
+ memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
+ wk.ik_keyix = key_idx;
+@@ -465,6 +467,20 @@ wpa_driver_madwifi_set_key(const char *i
+ wk.ik_keylen = key_len;
+ memcpy(wk.ik_keydata, key, key_len);
+
++#ifdef WORDS_BIGENDIAN
++#define WPA_KEY_RSC_LEN 8
++ {
++ size_t i;
++ u8 tmp[WPA_KEY_RSC_LEN];
++ os_memset(tmp, 0, sizeof(tmp));
++ for (i = 0; i < seq_len; i++)
++ tmp[WPA_KEY_RSC_LEN - i - 1] = seq[i];
++ os_memcpy(&wk.ik_keyrsc, tmp, WPA_KEY_RSC_LEN);
++ }
++#else /* WORDS_BIGENDIAN */
++ os_memcpy(&wk.ik_keyrsc, seq, seq_len);
++#endif /* WORDS_BIGENDIAN */
++
+ ret = set80211priv(drv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk));
+ if (ret < 0) {
+ wpa_printf(MSG_DEBUG, "%s: Failed to set key (addr %s"
diff --git a/package/hostapd/patches/400-noscan.patch b/package/hostapd/patches/400-noscan.patch
new file mode 100644
index 000000000..69d026b3d
--- /dev/null
+++ b/package/hostapd/patches/400-noscan.patch
@@ -0,0 +1,32 @@
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -2485,6 +2485,8 @@ static int hostapd_config_fill(struct ho
+ }
+ #endif /* CONFIG_IEEE80211W */
+ #ifdef CONFIG_IEEE80211N
++ } else if (os_strcmp(buf, "noscan") == 0) {
++ conf->noscan = atoi(pos);
+ } else if (os_strcmp(buf, "ieee80211n") == 0) {
+ conf->ieee80211n = atoi(pos);
+ } else if (os_strcmp(buf, "ht_capab") == 0) {
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -497,6 +497,7 @@ struct hostapd_config {
+
+ int ht_op_mode_fixed;
+ u16 ht_capab;
++ int noscan;
+ int ieee80211n;
+ int secondary_channel;
+ int require_ht;
+--- a/src/ap/hw_features.c
++++ b/src/ap/hw_features.c
+@@ -493,7 +493,7 @@ static int ieee80211n_check_40mhz(struct
+ {
+ struct wpa_driver_scan_params params;
+
+- if (!iface->conf->secondary_channel)
++ if (!iface->conf->secondary_channel || iface->conf->noscan)
+ return 0; /* HT40 not used */
+
+ wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling "
diff --git a/package/hostapd/patches/410-multicall.patch b/package/hostapd/patches/410-multicall.patch
new file mode 100644
index 000000000..7900428ae
--- /dev/null
+++ b/package/hostapd/patches/410-multicall.patch
@@ -0,0 +1,246 @@
+--- a/hostapd/Makefile
++++ b/hostapd/Makefile
+@@ -14,6 +14,7 @@ CFLAGS += -I../src/utils
+ # CFLAGS += -DUSE_KERNEL_HEADERS -I/usr/src/linux/include
+
+ -include .config
++-include $(if $(MULTICALL), ../wpa_supplicant/.config)
+
+ ifndef CONFIG_OS
+ ifdef CONFIG_NATIVE_WINDOWS
+@@ -188,10 +189,14 @@ ifdef CONFIG_IEEE80211AC
+ CFLAGS += -DCONFIG_IEEE80211AC
+ endif
+
++ifndef MULTICALL
++CFLAGS += -DNO_SUPPLICANT
++endif
++
+ include ../src/drivers/drivers.mak
+-OBJS += $(DRV_AP_OBJS)
+-CFLAGS += $(DRV_AP_CFLAGS)
+-LDFLAGS += $(DRV_AP_LDFLAGS)
++OBJS += $(sort $(DRV_AP_OBJS) $(if $(MULTICALL),$(DRV_WPA_OBJS)))
++CFLAGS += $(DRV_AP_CFLAGS) $(if $(MULTICALL),$(DRV_WPA_CFLAGS))
++LDFLAGS += $(DRV_AP_LDFLAGS) $(if $(MULTICALL),$(DRV_WPA_LDFLAGS))
+ LIBS += $(DRV_AP_LIBS)
+
+ ifdef CONFIG_L2_PACKET
+@@ -867,6 +872,12 @@ install: all
+
+ BCHECK=../src/drivers/build.hostapd
+
++hostapd_multi.a: $(BCHECK) $(OBJS)
++ $(Q)$(CC) -c -o hostapd_multi.o -Dmain=hostapd_main $(CFLAGS) main.c
++ @$(E) " CC " $<
++ @rm -f $@
++ @$(AR) cr $@ hostapd_multi.o $(OBJS)
++
+ hostapd: $(BCHECK) $(OBJS)
+ $(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
+ @$(E) " LD " $@
+@@ -905,6 +916,12 @@ HOBJS += ../src/crypto/aes-internal.o
+ HOBJS += ../src/crypto/aes-internal-enc.o
+ endif
+
++dump_cflags:
++ @echo -n $(CFLAGS) " "
++
++dump_ldflags:
++ @echo -n $(LDFLAGS) $(LIBS) $(EXTRALIBS) " "
++
+ nt_password_hash: $(NOBJS)
+ $(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
+ @$(E) " LD " $@
+--- a/wpa_supplicant/Makefile
++++ b/wpa_supplicant/Makefile
+@@ -14,6 +14,7 @@ CFLAGS += -I../src
+ CFLAGS += -I../src/utils
+
+ -include .config
++-include $(if $(MULTICALL),../hostapd/.config)
+
+ BINALL=wpa_supplicant wpa_cli
+
+@@ -705,6 +706,10 @@ ifdef CONFIG_DYNAMIC_EAP_METHODS
+ CFLAGS += -DCONFIG_DYNAMIC_EAP_METHODS
+ LIBS += -ldl -rdynamic
+ endif
++else
++ ifdef MULTICALL
++ OBJS += ../src/eap_common/eap_common.o
++ endif
+ endif
+
+ ifdef CONFIG_AP
+@@ -713,9 +718,11 @@ NEED_EAP_COMMON=y
+ NEED_RSN_AUTHENTICATOR=y
+ CFLAGS += -DCONFIG_AP
+ OBJS += ap.o
++ifndef MULTICALL
+ CFLAGS += -DCONFIG_NO_RADIUS
+ CFLAGS += -DCONFIG_NO_ACCOUNTING
+ CFLAGS += -DCONFIG_NO_VLAN
++endif
+ OBJS += ../src/ap/hostapd.o
+ OBJS += ../src/ap/wpa_auth_glue.o
+ OBJS += ../src/ap/utils.o
+@@ -770,10 +777,18 @@ endif
+ ifdef CONFIG_HS20
+ OBJS += ../src/ap/hs20.o
+ endif
++else
++ ifdef MULTICALL
++ OBJS += ../src/eap_server/eap_server.o
++ OBJS += ../src/eap_server/eap_server_identity.o
++ OBJS += ../src/eap_server/eap_server_methods.o
++ endif
+ endif
+
+ ifdef NEED_RSN_AUTHENTICATOR
++ifndef MULTICALL
+ CFLAGS += -DCONFIG_NO_RADIUS
++endif
+ NEED_AES_WRAP=y
+ OBJS += ../src/ap/wpa_auth.o
+ OBJS += ../src/ap/wpa_auth_ie.o
+@@ -1515,6 +1530,12 @@ wpa_priv: $(BCHECK) $(OBJS_priv)
+
+ $(OBJS_c) $(OBJS_t) $(OBJS_t2) $(OBJS) $(BCHECK) $(EXTRA_progs): .config
+
++wpa_supplicant_multi.a: .config $(BCHECK) $(OBJS) $(EXTRA_progs)
++ $(Q)$(CC) -c -o wpa_supplicant_multi.o -Dmain=wpa_supplicant_main $(CFLAGS) main.c
++ @$(E) " CC " $<
++ @rm -f $@
++ @$(AR) cr $@ wpa_supplicant_multi.o $(OBJS)
++
+ wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs)
+ $(Q)$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS)
+ @$(E) " LD " $@
+@@ -1585,6 +1606,12 @@ eap_ikev2.so: ../src/eap_peer/eap_ikev2.
+ %@.service: %.service.arg.in
+ sed -e 's|\@BINDIR\@|$(BINDIR)|g' $< >$@
+
++dump_cflags:
++ @echo -n $(CFLAGS) " "
++
++dump_ldflags:
++ @echo -n $(LDFLAGS) $(LIBS) $(EXTRALIBS) " "
++
+ wpa_supplicant.exe: wpa_supplicant
+ mv -f $< $@
+ wpa_cli.exe: wpa_cli
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -3686,8 +3686,8 @@ union wpa_event_data {
+ * Driver wrapper code should call this function whenever an event is received
+ * from the driver.
+ */
+-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
+- union wpa_event_data *data);
++extern void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,
++ union wpa_event_data *data);
+
+
+ /*
+--- a/src/ap/drv_callbacks.c
++++ b/src/ap/drv_callbacks.c
+@@ -685,8 +685,8 @@ static void hostapd_event_eapol_rx(struc
+ }
+
+
+-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
+- union wpa_event_data *data)
++void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
++ union wpa_event_data *data)
+ {
+ struct hostapd_data *hapd = ctx;
+ #ifndef CONFIG_NO_STDOUT_DEBUG
+--- a/wpa_supplicant/wpa_priv.c
++++ b/wpa_supplicant/wpa_priv.c
+@@ -819,8 +819,8 @@ static void wpa_priv_send_ft_response(st
+ }
+
+
+-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
+- union wpa_event_data *data)
++static void supplicant_event(void *ctx, enum wpa_event_type event,
++ union wpa_event_data *data)
+ {
+ struct wpa_priv_interface *iface = ctx;
+
+@@ -962,6 +962,7 @@ int main(int argc, char *argv[])
+ if (os_program_init())
+ return -1;
+
++ wpa_supplicant_event = supplicant_event;
+ wpa_priv_fd_workaround();
+
+ for (;;) {
+--- a/wpa_supplicant/events.c
++++ b/wpa_supplicant/events.c
+@@ -2258,8 +2258,8 @@ static void wnm_action_rx(struct wpa_sup
+ }
+
+
+-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
+- union wpa_event_data *data)
++void supplicant_event(void *ctx, enum wpa_event_type event,
++ union wpa_event_data *data)
+ {
+ struct wpa_supplicant *wpa_s = ctx;
+ u16 reason_code = 0;
+--- a/wpa_supplicant/wpa_supplicant.c
++++ b/wpa_supplicant/wpa_supplicant.c
+@@ -2921,6 +2921,9 @@ static void wpa_supplicant_deinit_iface(
+ }
+ }
+
++extern void supplicant_event(void *ctx, enum wpa_event_type event,
++ union wpa_event_data *data);
++
+
+ /**
+ * wpa_supplicant_add_iface - Add a new network interface
+@@ -3113,6 +3116,7 @@ struct wpa_global * wpa_supplicant_init(
+ wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
+ #endif /* CONFIG_NO_WPA_MSG */
+
++ wpa_supplicant_event = supplicant_event;
+ wpa_debug_open_file(params->wpa_debug_file_path);
+ if (params->wpa_debug_syslog)
+ wpa_debug_open_syslog();
+--- a/hostapd/main.c
++++ b/hostapd/main.c
+@@ -530,6 +530,9 @@ static int hostapd_get_global_ctrl_iface
+ return 0;
+ }
+
++void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
++ union wpa_event_data *data);
++
+
+ int main(int argc, char *argv[])
+ {
+@@ -555,6 +558,7 @@ int main(int argc, char *argv[])
+ interfaces.global_iface_name = NULL;
+ interfaces.global_ctrl_sock = -1;
+
++ wpa_supplicant_event = hostapd_wpa_event;
+ for (;;) {
+ c = getopt(argc, argv, "Bde:f:hKP:tvg:");
+ if (c < 0)
+--- a/src/drivers/drivers.c
++++ b/src/drivers/drivers.c
+@@ -7,7 +7,11 @@
+ */
+
+ #include "includes.h"
++#include "common.h"
++#include "driver.h"
+
++void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,
++ union wpa_event_data *data);
+
+ #ifdef CONFIG_DRIVER_WEXT
+ extern struct wpa_driver_ops wpa_driver_wext_ops; /* driver_wext.c */
diff --git a/package/hostapd/patches/420-timestamp_check.patch b/package/hostapd/patches/420-timestamp_check.patch
new file mode 100644
index 000000000..b2d4a0511
--- /dev/null
+++ b/package/hostapd/patches/420-timestamp_check.patch
@@ -0,0 +1,12 @@
+--- a/src/tls/x509v3.c
++++ b/src/tls/x509v3.c
+@@ -1848,6 +1848,9 @@ int x509_certificate_chain_validate(stru
+ if (chain_trusted)
+ continue;
+
++#ifdef NO_TIMESTAMP_CHECK
++ disable_time_checks = 1;
++#endif
+ if (!disable_time_checks &&
+ ((unsigned long) now.sec <
+ (unsigned long) cert->not_before ||
diff --git a/package/hostapd/patches/430-rescan_immediately.patch b/package/hostapd/patches/430-rescan_immediately.patch
new file mode 100644
index 000000000..51d41f800
--- /dev/null
+++ b/package/hostapd/patches/430-rescan_immediately.patch
@@ -0,0 +1,11 @@
+--- a/wpa_supplicant/wpa_supplicant.c
++++ b/wpa_supplicant/wpa_supplicant.c
+@@ -2388,7 +2388,7 @@ static struct wpa_supplicant * wpa_suppl
+ if (wpa_s == NULL)
+ return NULL;
+ wpa_s->scan_req = 1;
+- wpa_s->scan_interval = 5;
++ wpa_s->scan_interval = 1;
+ wpa_s->new_connection = 1;
+ wpa_s->parent = wpa_s;
+ wpa_s->sched_scanning = 0;
diff --git a/package/hostapd/patches/440-optional_rfkill.patch b/package/hostapd/patches/440-optional_rfkill.patch
new file mode 100644
index 000000000..be18458b2
--- /dev/null
+++ b/package/hostapd/patches/440-optional_rfkill.patch
@@ -0,0 +1,261 @@
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -218,7 +218,9 @@ struct wpa_driver_nl80211_data {
+ int if_removed;
+ int if_disabled;
+ int ignore_if_down_event;
++#ifdef CONFIG_RFKILL
+ struct rfkill_data *rfkill;
++#endif
+ struct wpa_driver_capa capa;
+ int has_capability;
+
+@@ -2828,7 +2830,7 @@ static int wpa_driver_nl80211_init_nl(st
+ return 0;
+ }
+
+-
++#ifdef CONFIG_RFKILL
+ static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
+ {
+ wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked");
+@@ -2851,6 +2853,7 @@ static void wpa_driver_nl80211_rfkill_un
+ }
+ /* rtnetlink ifup handler will report interface as enabled */
+ }
++#endif /* CONFIG_RFKILL */
+
+
+ static void nl80211_get_phy_name(struct wpa_driver_nl80211_data *drv)
+@@ -2979,7 +2982,9 @@ static void * wpa_driver_nl80211_init(vo
+ void *global_priv)
+ {
+ struct wpa_driver_nl80211_data *drv;
++#ifdef CONFIG_RFKILL
+ struct rfkill_config *rcfg;
++#endif
+ struct i802_bss *bss;
+
+ if (global_priv == NULL)
+@@ -3013,6 +3018,7 @@ static void * wpa_driver_nl80211_init(vo
+
+ nl80211_get_phy_name(drv);
+
++#ifdef CONFIG_RFKILL
+ rcfg = os_zalloc(sizeof(*rcfg));
+ if (rcfg == NULL)
+ goto failed;
+@@ -3025,6 +3031,7 @@ static void * wpa_driver_nl80211_init(vo
+ wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available");
+ os_free(rcfg);
+ }
++#endif /* CONFIG_RFKILL */
+
+ if (wpa_driver_nl80211_finish_drv_init(drv))
+ goto failed;
+@@ -3311,10 +3318,12 @@ static void nl80211_mgmt_unsubscribe(str
+ }
+
+
++#ifdef CONFIG_RFKILL
+ static void wpa_driver_nl80211_send_rfkill(void *eloop_ctx, void *timeout_ctx)
+ {
+ wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);
+ }
++#endif /* CONFIG_RFKILL */
+
+ static int
+ wpa_driver_nl80211_finish_drv_init_sta(struct wpa_driver_nl80211_data *drv,
+@@ -3335,13 +3344,16 @@ wpa_driver_nl80211_finish_drv_init_sta(s
+ }
+
+ if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {
++#ifdef CONFIG_RFKILL
+ if (rfkill_is_blocked(drv->rfkill)) {
+ wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable "
+ "interface '%s' due to rfkill",
+ bss->ifname);
+ drv->if_disabled = 1;
+ *send_rfkill_event = 1;
+- } else {
++ } else
++#endif
++ {
+ wpa_printf(MSG_ERROR, "nl80211: Could not set "
+ "interface '%s' UP", bss->ifname);
+ return -1;
+@@ -3372,8 +3384,10 @@ wpa_driver_nl80211_finish_drv_init(struc
+ return -1;
+
+ if (send_rfkill_event) {
++#ifdef CONFIG_RFKILL
+ eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill,
+ drv, drv->ctx);
++#endif
+ }
+
+ return 0;
+@@ -3460,7 +3474,9 @@ static void wpa_driver_nl80211_deinit(vo
+
+ netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0,
+ IF_OPER_UP);
++#ifdef CONFIG_RFKILL
+ rfkill_deinit(drv->rfkill);
++#endif
+
+ eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
+
+--- a/src/drivers/driver_wext.c
++++ b/src/drivers/driver_wext.c
+@@ -742,7 +742,7 @@ static void wpa_driver_wext_event_rtm_de
+ }
+ }
+
+-
++#ifdef CONFIG_RFKILL
+ static void wpa_driver_wext_rfkill_blocked(void *ctx)
+ {
+ wpa_printf(MSG_DEBUG, "WEXT: RFKILL blocked");
+@@ -764,7 +764,7 @@ static void wpa_driver_wext_rfkill_unblo
+ }
+ /* rtnetlink ifup handler will report interface as enabled */
+ }
+-
++#endif /* CONFIG_RFKILL */
+
+ static void wext_get_phy_name(struct wpa_driver_wext_data *drv)
+ {
+@@ -810,7 +810,9 @@ void * wpa_driver_wext_init(void *ctx, c
+ {
+ struct wpa_driver_wext_data *drv;
+ struct netlink_config *cfg;
++#ifdef CONFIG_RFKILL
+ struct rfkill_config *rcfg;
++#endif
+ char path[128];
+ struct stat buf;
+
+@@ -845,6 +847,7 @@ void * wpa_driver_wext_init(void *ctx, c
+ goto err2;
+ }
+
++#ifdef CONFIG_RFKILL
+ rcfg = os_zalloc(sizeof(*rcfg));
+ if (rcfg == NULL)
+ goto err3;
+@@ -857,6 +860,7 @@ void * wpa_driver_wext_init(void *ctx, c
+ wpa_printf(MSG_DEBUG, "WEXT: RFKILL status not available");
+ os_free(rcfg);
+ }
++#endif /* CONFIG_RFKILL */
+
+ drv->mlme_sock = -1;
+
+@@ -874,7 +878,9 @@ void * wpa_driver_wext_init(void *ctx, c
+ return drv;
+
+ err3:
++#ifdef CONFIG_RFKILL
+ rfkill_deinit(drv->rfkill);
++#endif
+ netlink_deinit(drv->netlink);
+ err2:
+ close(drv->ioctl_sock);
+@@ -884,10 +890,12 @@ err1:
+ }
+
+
++#ifdef CONFIG_RFKILL
+ static void wpa_driver_wext_send_rfkill(void *eloop_ctx, void *timeout_ctx)
+ {
+ wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);
+ }
++#endif /* CONFIG_RFKILL */
+
+
+ static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
+@@ -895,13 +903,16 @@ static int wpa_driver_wext_finish_drv_in
+ int send_rfkill_event = 0;
+
+ if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1) < 0) {
++#ifdef CONFIG_RFKILL
+ if (rfkill_is_blocked(drv->rfkill)) {
+ wpa_printf(MSG_DEBUG, "WEXT: Could not yet enable "
+ "interface '%s' due to rfkill",
+ drv->ifname);
+ drv->if_disabled = 1;
+ send_rfkill_event = 1;
+- } else {
++ } else
++#endif
++ {
+ wpa_printf(MSG_ERROR, "WEXT: Could not set "
+ "interface '%s' UP", drv->ifname);
+ return -1;
+@@ -949,8 +960,10 @@ static int wpa_driver_wext_finish_drv_in
+ 1, IF_OPER_DORMANT);
+
+ if (send_rfkill_event) {
++#ifdef CONFIG_RFKILL
+ eloop_register_timeout(0, 0, wpa_driver_wext_send_rfkill,
+ drv, drv->ctx);
++#endif
+ }
+
+ return 0;
+@@ -980,7 +993,9 @@ void wpa_driver_wext_deinit(void *priv)
+
+ netlink_send_oper_ifla(drv->netlink, drv->ifindex, 0, IF_OPER_UP);
+ netlink_deinit(drv->netlink);
++#ifdef CONFIG_RFKILL
+ rfkill_deinit(drv->rfkill);
++#endif
+
+ if (drv->mlme_sock >= 0)
+ eloop_unregister_read_sock(drv->mlme_sock);
+--- a/src/drivers/drivers.mak
++++ b/src/drivers/drivers.mak
+@@ -25,7 +25,6 @@ NEED_SME=y
+ NEED_AP_MLME=y
+ NEED_NETLINK=y
+ NEED_LINUX_IOCTL=y
+-NEED_RFKILL=y
+
+ ifdef CONFIG_LIBNL32
+ DRV_LIBS += -lnl-3
+@@ -101,7 +100,6 @@ DRV_WPA_CFLAGS += -DCONFIG_DRIVER_WEXT
+ CONFIG_WIRELESS_EXTENSION=y
+ NEED_NETLINK=y
+ NEED_LINUX_IOCTL=y
+-NEED_RFKILL=y
+ endif
+
+ ifdef CONFIG_DRIVER_NDIS
+@@ -127,7 +125,6 @@ endif
+ ifdef CONFIG_WIRELESS_EXTENSION
+ DRV_WPA_CFLAGS += -DCONFIG_WIRELESS_EXTENSION
+ DRV_WPA_OBJS += ../src/drivers/driver_wext.o
+-NEED_RFKILL=y
+ endif
+
+ ifdef NEED_NETLINK
+@@ -140,6 +137,7 @@ endif
+
+ ifdef NEED_RFKILL
+ DRV_OBJS += ../src/drivers/rfkill.o
++DRV_WPA_CFLAGS += -DCONFIG_RFKILL
+ endif
+
+ ifdef CONFIG_VLAN_NETLINK
+--- a/src/drivers/driver_wext.h
++++ b/src/drivers/driver_wext.h
+@@ -22,7 +22,9 @@ struct wpa_driver_wext_data {
+ int ifindex2;
+ int if_removed;
+ int if_disabled;
++#ifdef CONFIG_RFKILL
+ struct rfkill_data *rfkill;
++#endif
+ u8 *assoc_req_ies;
+ size_t assoc_req_ies_len;
+ u8 *assoc_resp_ies;
diff --git a/package/hostapd/patches/450-reload_freq_change.patch b/package/hostapd/patches/450-reload_freq_change.patch
new file mode 100644
index 000000000..f11593fcd
--- /dev/null
+++ b/package/hostapd/patches/450-reload_freq_change.patch
@@ -0,0 +1,23 @@
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -140,6 +140,20 @@ int hostapd_reload_config(struct hostapd
+ oldconf = hapd->iconf;
+ iface->conf = newconf;
+
++ hostapd_select_hw_mode(iface);
++ iface->freq = hostapd_hw_get_freq(hapd, newconf->channel);
++
++ if (hostapd_set_freq(hapd, newconf->hw_mode, iface->freq,
++ newconf->channel,
++ newconf->ieee80211n,
++ newconf->secondary_channel)) {
++ wpa_printf(MSG_ERROR, "Could not set channel for "
++ "kernel driver");
++ }
++
++ if (iface->current_mode)
++ hostapd_prepare_rates(iface, iface->current_mode);
++
+ for (j = 0; j < iface->num_bss; j++) {
+ hapd = iface->bss[j];
+ hapd->iconf = newconf;
diff --git a/package/hostapd/patches/451-nl80211_del_beacon_bss.patch b/package/hostapd/patches/451-nl80211_del_beacon_bss.patch
new file mode 100644
index 000000000..801b78b12
--- /dev/null
+++ b/package/hostapd/patches/451-nl80211_del_beacon_bss.patch
@@ -0,0 +1,63 @@
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -3394,16 +3394,18 @@ wpa_driver_nl80211_finish_drv_init(struc
+ }
+
+
+-static int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv)
++static int wpa_driver_nl80211_del_bss_beacon(struct i802_bss *bss)
+ {
++ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+
++ bss->beacon_set = 0;
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -ENOMEM;
+
+ nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_BEACON);
+- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
+
+ return send_and_recv_msgs(drv, msg, NULL, NULL);
+ nla_put_failure:
+@@ -3411,6 +3413,21 @@ static int wpa_driver_nl80211_del_beacon
+ return -ENOBUFS;
+ }
+
++static int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv)
++{
++ struct i802_bss *bss;
++
++ for (bss = &drv->first_bss; bss; bss = bss->next)
++ wpa_driver_nl80211_del_bss_beacon(bss);
++
++ return 0;
++}
++
++static int wpa_driver_nl80211_stop_ap(void *priv)
++{
++ struct i802_bss *bss = priv;
++ return wpa_driver_nl80211_del_beacon(bss->drv);
++}
+
+ /**
+ * wpa_driver_nl80211_deinit - Deinitialize nl80211 driver interface
+@@ -9238,4 +9255,5 @@ const struct wpa_driver_ops wpa_driver_n
+ .send_tdls_mgmt = nl80211_send_tdls_mgmt,
+ .tdls_oper = nl80211_tdls_oper,
+ #endif /* CONFIG_TDLS */
++ .stop_ap = wpa_driver_nl80211_stop_ap,
+ };
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -2053,6 +2053,9 @@ struct wpa_driver_ops {
+ */
+ int (*probe_req_report)(void *priv, int report);
+
++
++ int (*stop_ap)(void *priv);
++
+ /**
+ * deinit_ap - Deinitialize AP mode
+ * @priv: Private driver interface data
diff --git a/package/hostapd/patches/452-ctrl_iface_reload.patch b/package/hostapd/patches/452-ctrl_iface_reload.patch
new file mode 100644
index 000000000..81dcfedde
--- /dev/null
+++ b/package/hostapd/patches/452-ctrl_iface_reload.patch
@@ -0,0 +1,98 @@
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -33,6 +33,7 @@
+ #include "wps/wps.h"
+ #include "config_file.h"
+ #include "ctrl_iface.h"
++#include "config_file.h"
+
+
+ struct wpa_ctrl_dst {
+@@ -43,6 +44,7 @@ struct wpa_ctrl_dst {
+ int errors;
+ };
+
++static char *reload_opts = NULL;
+
+ static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
+ const char *buf, size_t len);
+@@ -152,6 +154,68 @@ static int hostapd_ctrl_iface_new_sta(st
+ return 0;
+ }
+
++static int hostapd_ctrl_iface_set_down(struct hostapd_data *hapd)
++{
++ if (hapd->driver->stop_ap)
++ hapd->driver->stop_ap(hapd->drv_priv);
++ return 0;
++}
++
++static char *get_option(char *opt, char *str)
++{
++ int len = strlen(str);
++
++ if (!strncmp(opt, str, len))
++ return opt + len;
++ else
++ return NULL;
++}
++
++static struct hostapd_config *hostapd_ctrl_iface_config_read(const char *fname)
++{
++ struct hostapd_config *conf;
++ char *opt, *val;
++
++ conf = hostapd_config_read(fname);
++ if (!conf)
++ return NULL;
++
++ for (opt = strtok(reload_opts, " ");
++ opt;
++ opt = strtok(NULL, " ")) {
++
++ if ((val = get_option(opt, "channel=")))
++ conf->channel = atoi(val);
++ else if ((val = get_option(opt, "ht_capab=")))
++ conf->ht_capab = atoi(val);
++ else if ((val = get_option(opt, "ht_capab_mask=")))
++ conf->ht_capab &= atoi(val);
++ else if ((val = get_option(opt, "sec_chan=")))
++ conf->secondary_channel = atoi(val);
++ else if ((val = get_option(opt, "hw_mode=")))
++ conf->hw_mode = atoi(val);
++ else if ((val = get_option(opt, "ieee80211n=")))
++ conf->ieee80211n = atoi(val);
++ else
++ break;
++ }
++
++ return conf;
++}
++
++static int hostapd_ctrl_iface_update(struct hostapd_data *hapd, char *txt)
++{
++ struct hostapd_config * (*config_read_cb)(const char *config_fname);
++ struct hostapd_iface *iface = hapd->iface;
++
++ config_read_cb = iface->interfaces->config_read_cb;
++ iface->interfaces->config_read_cb = hostapd_ctrl_iface_config_read;
++ reload_opts = txt;
++
++ hostapd_reload_config(iface);
++
++ iface->interfaces->config_read_cb = config_read_cb;
++}
+
+ #ifdef CONFIG_IEEE80211W
+ #ifdef NEED_AP_MLME
+@@ -864,6 +928,10 @@ static void hostapd_ctrl_iface_receive(i
+ reply_len += res;
+ }
+ #endif /* CONFIG_NO_RADIUS */
++ } else if (os_strcmp(buf, "DOWN") == 0) {
++ hostapd_ctrl_iface_set_down(hapd);
++ } else if (os_strncmp(buf, "UPDATE ", 7) == 0) {
++ hostapd_ctrl_iface_update(hapd, buf + 7);
+ } else if (os_strcmp(buf, "STA-FIRST") == 0) {
+ reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
+ reply_size);
diff --git a/package/hostapd/patches/453-ap_sta_support.patch b/package/hostapd/patches/453-ap_sta_support.patch
new file mode 100644
index 000000000..4b6c0f164
--- /dev/null
+++ b/package/hostapd/patches/453-ap_sta_support.patch
@@ -0,0 +1,221 @@
+--- a/wpa_supplicant/wpa_supplicant_i.h
++++ b/wpa_supplicant/wpa_supplicant_i.h
+@@ -95,6 +95,8 @@ struct wpa_interface {
+ * receiving of EAPOL frames from an additional interface.
+ */
+ const char *bridge_ifname;
++
++ const char *hostapd_ctrl;
+ };
+
+ /**
+@@ -294,6 +296,8 @@ struct wpa_supplicant {
+ #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
+ char bridge_ifname[16];
+
++ struct wpa_ctrl *hostapd;
++
+ char *confname;
+ struct wpa_config *conf;
+ int countermeasures;
+--- a/wpa_supplicant/Makefile
++++ b/wpa_supplicant/Makefile
+@@ -13,6 +13,10 @@ PKG_CONFIG ?= pkg-config
+ CFLAGS += -I../src
+ CFLAGS += -I../src/utils
+
++ifdef MULTICALL
++CFLAGS += -DMULTICALL
++endif
++
+ -include .config
+ -include $(if $(MULTICALL),../hostapd/.config)
+
+@@ -76,6 +80,10 @@ OBJS_c = wpa_cli.o ../src/common/wpa_ctr
+ OBJS_c += ../src/utils/wpa_debug.o
+ OBJS_c += ../src/utils/common.o
+
++ifdef MULTICALL
++OBJS += ../src/common/wpa_ctrl.o
++endif
++
+ ifndef CONFIG_OS
+ ifdef CONFIG_NATIVE_WINDOWS
+ CONFIG_OS=win32
+--- a/wpa_supplicant/wpa_supplicant.c
++++ b/wpa_supplicant/wpa_supplicant.c
+@@ -107,6 +107,55 @@ extern int wpa_debug_show_keys;
+ extern int wpa_debug_timestamp;
+ extern struct wpa_driver_ops *wpa_drivers[];
+
++#ifdef MULTICALL
++static int hostapd_stop(struct wpa_supplicant *wpa_s)
++{
++ const char *cmd = "DOWN";
++ char buf[256];
++ int len = sizeof(buf);
++
++ if (wpa_ctrl_request(wpa_s->hostapd, cmd, os_strlen(cmd), buf, &len, NULL) < 0) {
++ wpa_printf(MSG_ERROR, "\nFailed to stop hostapd AP interfaces\n");
++ return -1;
++ }
++ return 0;
++}
++
++static int hostapd_reload(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
++{
++ char *cmd = NULL;
++ char buf[256];
++ int len = sizeof(buf);
++ int channel, hw_mode;
++ int ret;
++
++ if (!bss)
++ return;
++
++ if (bss->freq < 4000) {
++ hw_mode = HOSTAPD_MODE_IEEE80211G;
++ channel = (bss->freq - 2407) / 5;
++ } else {
++ hw_mode = HOSTAPD_MODE_IEEE80211A;
++ channel = (bss->freq - 5000) / 5;
++ }
++
++ if (asprintf(&cmd, "UPDATE channel=%d sec_chan=0 hw_mode=%d ieee80211n=%d",
++ channel, hw_mode, !!bss->ht_capab) < 0) {
++ return -1;
++ }
++
++ ret = wpa_ctrl_request(wpa_s->hostapd, cmd, os_strlen(cmd), buf, &len, NULL);
++ free(cmd);
++
++ if (ret < 0) {
++ wpa_printf(MSG_ERROR, "\nFailed to reload hostapd AP interfaces\n");
++ return -1;
++ }
++ return 0;
++}
++#endif
++
+ /* Configure default/group WEP keys for static WEP */
+ int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+ {
+@@ -672,8 +721,16 @@ void wpa_supplicant_set_state(struct wpa
+ #endif /* CONFIG_P2P */
+
+ sme_sched_obss_scan(wpa_s, 1);
++#ifdef MULTICALL
++ if (wpa_s->hostapd)
++ hostapd_reload(wpa_s, wpa_s->current_bss);
++#endif
+ } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
+ state == WPA_ASSOCIATED) {
++#ifdef MULTICALL
++ if (wpa_s->hostapd)
++ hostapd_stop(wpa_s);
++#endif
+ wpa_s->new_connection = 1;
+ wpa_drv_set_operstate(wpa_s, 0);
+ #ifndef IEEE8021X_EAPOL
+@@ -2727,6 +2784,21 @@ static int wpa_supplicant_init_iface(str
+ os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
+ sizeof(wpa_s->bridge_ifname));
+ }
++#ifdef MULTICALL
++ if (iface->hostapd_ctrl) {
++ char *cmd = "DOWN";
++ char buf[256];
++ int len = sizeof(buf);
++
++ wpa_s->hostapd = wpa_ctrl_open(iface->hostapd_ctrl);
++ if (!wpa_s->hostapd) {
++ wpa_printf(MSG_ERROR, "\nFailed to connect to hostapd\n");
++ return -1;
++ }
++ if (hostapd_stop(wpa_s) < 0)
++ return -1;
++ }
++#endif
+
+ /* RSNA Supplicant Key Management - INITIALIZE */
+ eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
+--- a/wpa_supplicant/bss.c
++++ b/wpa_supplicant/bss.c
+@@ -11,6 +11,7 @@
+ #include "utils/common.h"
+ #include "utils/eloop.h"
+ #include "common/ieee802_11_defs.h"
++#include "common/ieee802_11_common.h"
+ #include "drivers/driver.h"
+ #include "wpa_supplicant_i.h"
+ #include "config.h"
+@@ -139,6 +140,8 @@ struct wpa_bss * wpa_bss_get(struct wpa_
+
+ static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src)
+ {
++ struct ieee80211_ht_capabilities *capab;
++ struct ieee802_11_elems elems;
+ os_time_t usec;
+
+ dst->flags = src->flags;
+@@ -151,6 +154,12 @@ static void wpa_bss_copy_res(struct wpa_
+ dst->level = src->level;
+ dst->tsf = src->tsf;
+
++ memset(&elems, 0, sizeof(elems));
++ ieee802_11_parse_elems((u8 *) (src + 1), src->ie_len, &elems, 0);
++ capab = (struct ieee80211_ht_capabilities *) elems.ht_capabilities;
++ if (capab)
++ dst->ht_capab = le_to_host16(capab->ht_capabilities_info);
++
+ os_get_time(&dst->last_update);
+ dst->last_update.sec -= src->age / 1000;
+ usec = (src->age % 1000) * 1000;
+--- a/wpa_supplicant/bss.h
++++ b/wpa_supplicant/bss.h
+@@ -72,6 +72,7 @@ struct wpa_bss {
+ u8 bssid[ETH_ALEN];
+ u8 hessid[ETH_ALEN];
+ u8 ssid[32];
++ u16 ht_capab;
+ size_t ssid_len;
+ int freq;
+ u16 beacon_int;
+--- a/wpa_supplicant/main.c
++++ b/wpa_supplicant/main.c
+@@ -25,7 +25,7 @@ static void usage(void)
+ "usage:\n"
+ " wpa_supplicant [-BddhKLqqstuvW] [-P<pid file>] "
+ "[-g<global ctrl>] \\\n"
+- " -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] "
++ " -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] [-H<hostapd path>]"
+ "[-p<driver_param>] \\\n"
+ " [-b<br_ifname>] [-f<debug file>] [-e<entropy file>] "
+ "\\\n"
+@@ -67,6 +67,7 @@ static void usage(void)
+ #endif /* CONFIG_DEBUG_LINUX_TRACING */
+ printf(" -t = include timestamp in debug messages\n"
+ " -h = show this help text\n"
++ " -H = connect to a hostapd instance to manage state changes\n"
+ " -L = show license (BSD)\n"
+ " -o = override driver parameter for new interfaces\n"
+ " -O = override ctrl_interface parameter for new interfaces\n"
+@@ -155,7 +156,7 @@ int main(int argc, char *argv[])
+
+ for (;;) {
+ c = getopt(argc, argv,
+- "b:Bc:C:D:de:f:g:hi:KLNo:O:p:P:qsTtuvW");
++ "b:Bc:C:D:de:f:g:hH:i:KLNo:O:p:P:qsTtuvW");
+ if (c < 0)
+ break;
+ switch (c) {
+@@ -199,6 +200,9 @@ int main(int argc, char *argv[])
+ usage();
+ exitcode = 0;
+ goto out;
++ case 'H':
++ iface->hostapd_ctrl = optarg;
++ break;
+ case 'i':
+ iface->ifname = optarg;
+ break;
diff --git a/package/hostapd/patches/460-disable_ctrl_iface_mib.patch b/package/hostapd/patches/460-disable_ctrl_iface_mib.patch
new file mode 100644
index 000000000..2f03179a0
--- /dev/null
+++ b/package/hostapd/patches/460-disable_ctrl_iface_mib.patch
@@ -0,0 +1,168 @@
+--- a/hostapd/Makefile
++++ b/hostapd/Makefile
+@@ -135,6 +135,9 @@ endif
+ ifdef CONFIG_NO_CTRL_IFACE
+ CFLAGS += -DCONFIG_NO_CTRL_IFACE
+ else
++ifdef CONFIG_CTRL_IFACE_MIB
++CFLAGS += -DCONFIG_CTRL_IFACE_MIB
++endif
+ OBJS += ctrl_iface.o
+ OBJS += ../src/ap/ctrl_iface_ap.o
+ endif
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -899,6 +899,7 @@ static void hostapd_ctrl_iface_receive(i
+ } else if (os_strncmp(buf, "RELOG", 5) == 0) {
+ if (wpa_debug_reopen_file() < 0)
+ reply_len = -1;
++#ifdef CONFIG_CTRL_IFACE_MIB
+ } else if (os_strcmp(buf, "MIB") == 0) {
+ reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
+ if (reply_len >= 0) {
+@@ -928,10 +929,12 @@ static void hostapd_ctrl_iface_receive(i
+ reply_len += res;
+ }
+ #endif /* CONFIG_NO_RADIUS */
++#endif
+ } else if (os_strcmp(buf, "DOWN") == 0) {
+ hostapd_ctrl_iface_set_down(hapd);
+ } else if (os_strncmp(buf, "UPDATE ", 7) == 0) {
+ hostapd_ctrl_iface_update(hapd, buf + 7);
++#ifdef CONFIG_CTRL_IFACE_MIB
+ } else if (os_strcmp(buf, "STA-FIRST") == 0) {
+ reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
+ reply_size);
+@@ -941,6 +944,7 @@ static void hostapd_ctrl_iface_receive(i
+ } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
+ reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
+ reply_size);
++#endif
+ } else if (os_strcmp(buf, "ATTACH") == 0) {
+ if (hostapd_ctrl_iface_attach(hapd, &from, fromlen))
+ reply_len = -1;
+--- a/wpa_supplicant/Makefile
++++ b/wpa_supplicant/Makefile
+@@ -751,6 +751,9 @@ ifdef CONFIG_IEEE80211N
+ OBJS += ../src/ap/ieee802_11_ht.o
+ endif
+ ifdef CONFIG_CTRL_IFACE
++ifdef CONFIG_CTRL_IFACE_MIB
++CFLAGS += -DCONFIG_CTRL_IFACE_MIB
++endif
+ OBJS += ../src/ap/ctrl_iface_ap.o
+ endif
+
+--- a/wpa_supplicant/ctrl_iface.c
++++ b/wpa_supplicant/ctrl_iface.c
+@@ -4382,6 +4382,7 @@ char * wpa_supplicant_ctrl_iface_process
+ reply_len = -1;
+ } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
+ wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
++#ifdef CONFIG_CTRL_IFACE_MIB
+ } else if (os_strcmp(buf, "MIB") == 0) {
+ reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
+ if (reply_len >= 0) {
+@@ -4393,6 +4394,7 @@ char * wpa_supplicant_ctrl_iface_process
+ else
+ reply_len += res;
+ }
++#endif
+ } else if (os_strncmp(buf, "STATUS", 6) == 0) {
+ reply_len = wpa_supplicant_ctrl_iface_status(
+ wpa_s, buf + 6, reply, reply_size);
+@@ -4792,6 +4794,7 @@ char * wpa_supplicant_ctrl_iface_process
+ reply_len = wpa_supplicant_ctrl_iface_bss(
+ wpa_s, buf + 4, reply, reply_size);
+ #ifdef CONFIG_AP
++#ifdef CONFIG_CTRL_IFACE_MIB
+ } else if (os_strcmp(buf, "STA-FIRST") == 0) {
+ reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
+ } else if (os_strncmp(buf, "STA ", 4) == 0) {
+@@ -4800,6 +4803,7 @@ char * wpa_supplicant_ctrl_iface_process
+ } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
+ reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
+ reply_size);
++#endif
+ } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
+ if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
+ reply_len = -1;
+--- a/src/ap/ctrl_iface_ap.c
++++ b/src/ap/ctrl_iface_ap.c
+@@ -20,6 +20,7 @@
+ #include "ctrl_iface_ap.h"
+ #include "ap_drv_ops.h"
+
++#ifdef CONFIG_CTRL_IFACE_MIB
+
+ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
+ struct sta_info *sta,
+@@ -103,6 +104,7 @@ int hostapd_ctrl_iface_sta_next(struct h
+ return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen);
+ }
+
++#endif
+
+ #ifdef CONFIG_P2P_MANAGER
+ static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
+@@ -269,3 +271,4 @@ int hostapd_ctrl_iface_disassociate(stru
+
+ return 0;
+ }
++
+--- a/src/ap/ieee802_1x.c
++++ b/src/ap/ieee802_1x.c
+@@ -2034,6 +2034,7 @@ static const char * bool_txt(Boolean boo
+ return bool ? "TRUE" : "FALSE";
+ }
+
++#ifdef CONFIG_CTRL_IFACE_MIB
+
+ int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)
+ {
+@@ -2186,6 +2187,7 @@ int ieee802_1x_get_mib_sta(struct hostap
+ return len;
+ }
+
++#endif
+
+ static void ieee802_1x_finished(struct hostapd_data *hapd,
+ struct sta_info *sta, int success)
+--- a/src/ap/wpa_auth.c
++++ b/src/ap/wpa_auth.c
+@@ -2729,6 +2729,7 @@ static const char * wpa_bool_txt(int boo
+ return bool ? "TRUE" : "FALSE";
+ }
+
++#ifdef CONFIG_CTRL_IFACE_MIB
+
+ #define RSN_SUITE "%02x-%02x-%02x-%d"
+ #define RSN_SUITE_ARG(s) \
+@@ -2873,7 +2874,7 @@ int wpa_get_mib_sta(struct wpa_state_mac
+
+ return len;
+ }
+-
++#endif
+
+ void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth)
+ {
+--- a/src/rsn_supp/wpa.c
++++ b/src/rsn_supp/wpa.c
+@@ -1844,6 +1844,8 @@ static u32 wpa_key_mgmt_suite(struct wpa
+ }
+
+
++#ifdef CONFIG_CTRL_IFACE_MIB
++
+ #define RSN_SUITE "%02x-%02x-%02x-%d"
+ #define RSN_SUITE_ARG(s) \
+ ((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
+@@ -1927,6 +1929,7 @@ int wpa_sm_get_mib(struct wpa_sm *sm, ch
+
+ return (int) len;
+ }
++#endif
+ #endif /* CONFIG_CTRL_IFACE */
+
+
diff --git a/package/hostapd/patches/470-wpa_ie_cap_workaround.patch b/package/hostapd/patches/470-wpa_ie_cap_workaround.patch
new file mode 100644
index 000000000..00a32229d
--- /dev/null
+++ b/package/hostapd/patches/470-wpa_ie_cap_workaround.patch
@@ -0,0 +1,56 @@
+--- a/src/common/wpa_common.c
++++ b/src/common/wpa_common.c
+@@ -959,6 +959,31 @@ const char * wpa_key_mgmt_txt(int key_mg
+ }
+
+
++static void wpa_fixup_wpa_ie_rsn(u8 *assoc_ie, const u8 *wpa_msg_ie,
++ size_t rsn_ie_len)
++{
++ int pos, count;
++
++ pos = sizeof(struct rsn_ie_hdr) + RSN_SELECTOR_LEN;
++ if (rsn_ie_len < pos + 2)
++ return;
++
++ count = WPA_GET_LE16(wpa_msg_ie + pos);
++ pos += 2 + count * RSN_SELECTOR_LEN;
++ if (rsn_ie_len < pos + 2)
++ return;
++
++ count = WPA_GET_LE16(wpa_msg_ie + pos);
++ pos += 2 + count * RSN_SELECTOR_LEN;
++ if (rsn_ie_len < pos + 2)
++ return;
++
++ if (!assoc_ie[pos] && !assoc_ie[pos + 1] &&
++ (wpa_msg_ie[pos] || wpa_msg_ie[pos + 1]))
++ memcpy(&assoc_ie[pos], &wpa_msg_ie[pos], 2);
++}
++
++
+ int wpa_compare_rsn_ie(int ft_initial_assoc,
+ const u8 *ie1, size_t ie1len,
+ const u8 *ie2, size_t ie2len)
+@@ -966,8 +991,19 @@ int wpa_compare_rsn_ie(int ft_initial_as
+ if (ie1 == NULL || ie2 == NULL)
+ return -1;
+
+- if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)
+- return 0; /* identical IEs */
++ if (ie1len == ie2len) {
++ u8 *ie_tmp;
++
++ if (os_memcmp(ie1, ie2, ie1len) == 0)
++ return 0; /* identical IEs */
++
++ ie_tmp = alloca(ie1len);
++ memcpy(ie_tmp, ie1, ie1len);
++ wpa_fixup_wpa_ie_rsn(ie_tmp, ie2, ie1len);
++
++ if (os_memcmp(ie_tmp, ie2, ie1len) == 0)
++ return 0; /* only mismatch in RSN capabilties */
++ }
+
+ #ifdef CONFIG_IEEE80211R
+ if (ft_initial_assoc) {
diff --git a/package/hostapd/patches/480-terminate_on_setup_failure.patch b/package/hostapd/patches/480-terminate_on_setup_failure.patch
new file mode 100644
index 000000000..6168a5cfc
--- /dev/null
+++ b/package/hostapd/patches/480-terminate_on_setup_failure.patch
@@ -0,0 +1,81 @@
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -886,11 +886,8 @@ int hostapd_setup_interface_complete(str
+ size_t j;
+ u8 *prev_addr;
+
+- if (err) {
+- wpa_printf(MSG_ERROR, "Interface initialization failed");
+- eloop_terminate();
+- return -1;
+- }
++ if (err)
++ goto error;
+
+ wpa_printf(MSG_DEBUG, "Completing interface initialization");
+ if (hapd->iconf->channel) {
+@@ -906,7 +903,7 @@ int hostapd_setup_interface_complete(str
+ hapd->iconf->secondary_channel)) {
+ wpa_printf(MSG_ERROR, "Could not set channel for "
+ "kernel driver");
+- return -1;
++ goto error;
+ }
+ }
+
+@@ -917,7 +914,7 @@ int hostapd_setup_interface_complete(str
+ hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_WARNING,
+ "Failed to prepare rates table.");
+- return -1;
++ goto error;
+ }
+ }
+
+@@ -925,14 +922,14 @@ int hostapd_setup_interface_complete(str
+ hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) {
+ wpa_printf(MSG_ERROR, "Could not set RTS threshold for "
+ "kernel driver");
+- return -1;
++ goto error;
+ }
+
+ if (hapd->iconf->fragm_threshold > -1 &&
+ hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) {
+ wpa_printf(MSG_ERROR, "Could not set fragmentation threshold "
+ "for kernel driver");
+- return -1;
++ goto error;
+ }
+
+ prev_addr = hapd->own_addr;
+@@ -942,7 +939,7 @@ int hostapd_setup_interface_complete(str
+ if (j)
+ os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
+ if (hostapd_setup_bss(hapd, j == 0))
+- return -1;
++ goto error;
+ if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0)
+ prev_addr = hapd->own_addr;
+ }
+@@ -954,7 +951,7 @@ int hostapd_setup_interface_complete(str
+ if (hostapd_driver_commit(hapd) < 0) {
+ wpa_printf(MSG_ERROR, "%s: Failed to commit driver "
+ "configuration", __func__);
+- return -1;
++ goto error;
+ }
+
+ /*
+@@ -975,6 +972,11 @@ int hostapd_setup_interface_complete(str
+ iface->bss[0]->conf->iface);
+
+ return 0;
++
++error:
++ wpa_printf(MSG_ERROR, "Interface initialization failed");
++ eloop_terminate();
++ return -1;
+ }
+
+
diff --git a/package/hostapd/patches/500-random_pool_add_kernel.patch b/package/hostapd/patches/500-random_pool_add_kernel.patch
new file mode 100644
index 000000000..e54e881d8
--- /dev/null
+++ b/package/hostapd/patches/500-random_pool_add_kernel.patch
@@ -0,0 +1,168 @@
+--- a/src/crypto/random.c
++++ b/src/crypto/random.c
+@@ -33,6 +33,8 @@
+ #include "sha1.h"
+ #include "random.h"
+
++#define RANDOM_STAMPFILE "/var/run/.random_available"
++
+ #define POOL_WORDS 32
+ #define POOL_WORDS_MASK (POOL_WORDS - 1)
+ #define POOL_TAP1 26
+@@ -43,6 +45,8 @@
+ #define EXTRACT_LEN 16
+ #define MIN_READY_MARK 2
+
++#ifndef CONFIG_NO_RANDOM_POOL
++
+ static u32 pool[POOL_WORDS];
+ static unsigned int input_rotate = 0;
+ static unsigned int pool_pos = 0;
+@@ -123,7 +127,7 @@ static void random_extract(u8 *out)
+ }
+
+
+-void random_add_randomness(const void *buf, size_t len)
++static void random_pool_add_randomness(const void *buf, size_t len)
+ {
+ struct os_time t;
+ static unsigned int count = 0;
+@@ -213,16 +217,22 @@ int random_get_bytes(void *buf, size_t l
+ int random_pool_ready(void)
+ {
+ #ifdef __linux__
++ struct stat st;
+ int fd;
+ ssize_t res;
+
++ if (stat(RANDOM_STAMPFILE, &st) == 0)
++ return 1;
++
+ /*
+ * Make sure that there is reasonable entropy available before allowing
+ * some key derivation operations to proceed.
+ */
+
+- if (dummy_key_avail == sizeof(dummy_key))
++ if (dummy_key_avail == sizeof(dummy_key)) {
++ random_mark_pool_ready();
+ return 1; /* Already initialized - good to continue */
++ }
+
+ /*
+ * Try to fetch some more data from the kernel high quality
+@@ -257,6 +267,7 @@ int random_pool_ready(void)
+ if (dummy_key_avail == sizeof(dummy_key)) {
+ if (own_pool_ready < MIN_READY_MARK)
+ own_pool_ready = MIN_READY_MARK;
++ random_mark_pool_ready();
+ random_write_entropy();
+ return 1;
+ }
+@@ -269,6 +280,7 @@ int random_pool_ready(void)
+ total_collected + 10 * own_pool_ready > MIN_COLLECT_ENTROPY) {
+ wpa_printf(MSG_INFO, "random: Allow operation to proceed "
+ "based on internal entropy");
++ random_mark_pool_ready();
+ return 1;
+ }
+
+@@ -284,10 +296,16 @@ int random_pool_ready(void)
+
+ void random_mark_pool_ready(void)
+ {
++ int fd;
++
+ own_pool_ready++;
+ wpa_printf(MSG_DEBUG, "random: Mark internal entropy pool to be "
+ "ready (count=%u/%u)", own_pool_ready, MIN_READY_MARK);
+ random_write_entropy();
++
++ fd = open(RANDOM_STAMPFILE, O_CREAT | O_WRONLY | O_EXCL | O_NOFOLLOW, 0600);
++ if (fd >= 0)
++ close(fd);
+ }
+
+
+@@ -444,3 +462,22 @@ void random_deinit(void)
+ os_free(random_entropy_file);
+ random_entropy_file = NULL;
+ }
++
++#endif /* CONFIG_NO_RANDOM_POOL */
++
++
++void random_add_randomness(const void *buf, size_t len)
++{
++#ifdef __linux__
++ int fd;
++
++ fd = open("/dev/random", O_RDWR);
++ if (fd >= 0) {
++ write(fd, buf, len);
++ close(fd);
++ }
++#endif
++#ifndef CONFIG_NO_RANDOM_POOL
++ random_pool_add_randomness(buf, len);
++#endif
++}
+--- a/wpa_supplicant/Makefile
++++ b/wpa_supplicant/Makefile
+@@ -1217,9 +1217,8 @@ endif
+
+ ifdef CONFIG_NO_RANDOM_POOL
+ CFLAGS += -DCONFIG_NO_RANDOM_POOL
+-else
+-OBJS += ../src/crypto/random.o
+ endif
++OBJS += ../src/crypto/random.o
+
+ ifdef CONFIG_CTRL_IFACE
+ ifeq ($(CONFIG_CTRL_IFACE), y)
+--- a/wpa_supplicant/Android.mk
++++ b/wpa_supplicant/Android.mk
+@@ -1161,9 +1161,8 @@ endif
+
+ ifdef CONFIG_NO_RANDOM_POOL
+ L_CFLAGS += -DCONFIG_NO_RANDOM_POOL
+-else
+-OBJS += src/crypto/random.c
+ endif
++OBJS += src/crypto/random.c
+
+ ifdef CONFIG_CTRL_IFACE
+ ifeq ($(CONFIG_CTRL_IFACE), y)
+--- a/hostapd/Android.mk
++++ b/hostapd/Android.mk
+@@ -748,11 +748,11 @@ endif
+ ifdef CONFIG_NO_RANDOM_POOL
+ L_CFLAGS += -DCONFIG_NO_RANDOM_POOL
+ else
+-OBJS += src/crypto/random.c
+-HOBJS += src/crypto/random.c
+ HOBJS += $(SHA1OBJS)
+ HOBJS += src/crypto/md5.c
+ endif
++OBJS += src/crypto/random.c
++HOBJS += src/crypto/random.c
+
+ ifdef CONFIG_RADIUS_SERVER
+ L_CFLAGS += -DRADIUS_SERVER
+--- a/hostapd/Makefile
++++ b/hostapd/Makefile
+@@ -755,12 +755,12 @@ endif
+ ifdef CONFIG_NO_RANDOM_POOL
+ CFLAGS += -DCONFIG_NO_RANDOM_POOL
+ else
+-OBJS += ../src/crypto/random.o
+-HOBJS += ../src/crypto/random.o
+ HOBJS += ../src/utils/eloop.o
+ HOBJS += $(SHA1OBJS)
+ HOBJS += ../src/crypto/md5.o
+ endif
++OBJS += ../src/crypto/random.o
++HOBJS += ../src/crypto/random.o
+
+ ifdef CONFIG_RADIUS_SERVER
+ CFLAGS += -DRADIUS_SERVER
diff --git a/package/hostapd/patches/510-bring_down_interface.patch b/package/hostapd/patches/510-bring_down_interface.patch
new file mode 100644
index 000000000..7481eb152
--- /dev/null
+++ b/package/hostapd/patches/510-bring_down_interface.patch
@@ -0,0 +1,19 @@
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -7144,8 +7144,6 @@ static int wpa_driver_nl80211_set_mode(s
+ ret = nl80211_set_mode(drv, drv->ifindex, nlmode);
+ if (ret == -EACCES)
+ break;
+- res = linux_set_iface_flags(drv->global->ioctl_sock,
+- bss->ifname, 1);
+ if (res && !ret)
+ ret = -1;
+ else if (ret != -EBUSY)
+@@ -7161,6 +7159,7 @@ static int wpa_driver_nl80211_set_mode(s
+ "interface is down");
+ drv->nlmode = nlmode;
+ drv->ignore_if_down_event = 1;
++ linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1);
+ }
+
+ done:
diff --git a/package/hostapd/patches/520-fix_wps_pin_crash.patch b/package/hostapd/patches/520-fix_wps_pin_crash.patch
new file mode 100644
index 000000000..29d154cef
--- /dev/null
+++ b/package/hostapd/patches/520-fix_wps_pin_crash.patch
@@ -0,0 +1,12 @@
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -450,6 +450,9 @@ static int hostapd_ctrl_iface_wps_ap_pin
+ char *pos;
+ const char *pin_txt;
+
++ if (!hapd->wps)
++ return -1;
++
+ pos = os_strchr(txt, ' ');
+ if (pos)
+ *pos++ = '\0';
diff --git a/package/hostapd/patches/530-wps_single_auth_enc_type.patch b/package/hostapd/patches/530-wps_single_auth_enc_type.patch
new file mode 100644
index 000000000..f05ea35cf
--- /dev/null
+++ b/package/hostapd/patches/530-wps_single_auth_enc_type.patch
@@ -0,0 +1,25 @@
+--- a/src/ap/wps_hostapd.c
++++ b/src/ap/wps_hostapd.c
+@@ -873,11 +873,9 @@ int hostapd_init_wps(struct hostapd_data
+
+ if (conf->rsn_pairwise & WPA_CIPHER_CCMP)
+ wps->encr_types |= WPS_ENCR_AES;
+- if (conf->rsn_pairwise & WPA_CIPHER_TKIP)
++ else if (conf->rsn_pairwise & WPA_CIPHER_TKIP)
+ wps->encr_types |= WPS_ENCR_TKIP;
+- }
+-
+- if (conf->wpa & WPA_PROTO_WPA) {
++ } else if (conf->wpa & WPA_PROTO_WPA) {
+ if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK)
+ wps->auth_types |= WPS_AUTH_WPAPSK;
+ if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X)
+@@ -885,7 +883,7 @@ int hostapd_init_wps(struct hostapd_data
+
+ if (conf->wpa_pairwise & WPA_CIPHER_CCMP)
+ wps->encr_types |= WPS_ENCR_AES;
+- if (conf->wpa_pairwise & WPA_CIPHER_TKIP)
++ else if (conf->wpa_pairwise & WPA_CIPHER_TKIP)
+ wps->encr_types |= WPS_ENCR_TKIP;
+ }
+
diff --git a/package/hostapd/patches/540-dynamic_20_40_mhz.patch b/package/hostapd/patches/540-dynamic_20_40_mhz.patch
new file mode 100644
index 000000000..d58358c08
--- /dev/null
+++ b/package/hostapd/patches/540-dynamic_20_40_mhz.patch
@@ -0,0 +1,202 @@
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -2495,6 +2495,10 @@ static int hostapd_config_fill(struct ho
+ "ht_capab", line);
+ errors++;
+ }
++ } else if (os_strcmp(buf, "dynamic_ht40") == 0) {
++ conf->dynamic_ht40 = atoi(pos);
++ if (conf->dynamic_ht40 == 1)
++ conf->dynamic_ht40 = 1500;
+ } else if (os_strcmp(buf, "require_ht") == 0) {
+ conf->require_ht = atoi(pos);
+ #endif /* CONFIG_IEEE80211N */
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -501,6 +501,7 @@ struct hostapd_config {
+ int ieee80211n;
+ int secondary_channel;
+ int require_ht;
++ int dynamic_ht40;
+ u32 vht_capab;
+ int ieee80211ac;
+ int require_vht;
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -22,6 +22,7 @@
+ #include "beacon.h"
+ #include "iapp.h"
+ #include "ieee802_1x.h"
++#include "ieee802_11.h"
+ #include "ieee802_11_auth.h"
+ #include "vlan_init.h"
+ #include "wpa_auth.h"
+@@ -323,6 +324,7 @@ static void hostapd_cleanup_iface_pre(st
+
+ static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
+ {
++ hostapd_deinit_ht(iface);
+ hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
+ iface->hw_features = NULL;
+ os_free(iface->current_rates);
+--- a/src/ap/hostapd.h
++++ b/src/ap/hostapd.h
+@@ -251,6 +251,9 @@ struct hostapd_iface {
+ /* Overlapping BSS information */
+ int olbc_ht;
+
++ int force_20mhz;
++ struct os_time last_20mhz_trigger;
++
+ u16 ht_op_mode;
+ void (*scan_cb)(struct hostapd_iface *iface);
+ };
+--- a/src/ap/ieee802_11.c
++++ b/src/ap/ieee802_11.c
+@@ -1220,6 +1220,9 @@ static void handle_beacon(struct hostapd
+ sizeof(mgmt->u.beacon)), &elems,
+ 0);
+
++ if (!elems.ht_capabilities)
++ hostapd_trigger_20mhz(hapd->iface);
++
+ ap_list_process_beacon(hapd->iface, mgmt, &elems, fi);
+ }
+
+--- a/src/ap/ieee802_11.h
++++ b/src/ap/ieee802_11.h
+@@ -78,4 +78,17 @@ int hostapd_update_time_adv(struct hosta
+ void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr);
+ u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid);
+
++#ifdef CONFIG_IEEE80211N
++void hostapd_trigger_20mhz(struct hostapd_iface *iface);
++void hostapd_deinit_ht(struct hostapd_iface *iface);
++
++#else
++static inline void hostapd_deinit_ht(struct hostapd_iface *iface)
++{
++}
++static inline void hostapd_trigger_20mhz(struct hostapd_iface *iface)
++{
++}
++#endif /* CONFIG_IEEE80211N */
++
+ #endif /* IEEE802_11_H */
+--- a/src/ap/ieee802_11_ht.c
++++ b/src/ap/ieee802_11_ht.c
+@@ -20,9 +20,11 @@
+ #include "drivers/driver.h"
+ #include "hostapd.h"
+ #include "ap_config.h"
++#include "ap_drv_ops.h"
+ #include "sta_info.h"
+ #include "beacon.h"
+ #include "ieee802_11.h"
++#include "utils/eloop.h"
+
+
+ u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid)
+@@ -70,12 +72,15 @@ u8 * hostapd_eid_ht_operation(struct hos
+
+ oper->control_chan = hapd->iconf->channel;
+ oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode);
+- if (hapd->iconf->secondary_channel == 1)
+- oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |
+- HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
+- if (hapd->iconf->secondary_channel == -1)
+- oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
+- HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
++
++ if (!hapd->iface->force_20mhz) {
++ if (hapd->iconf->secondary_channel == 1)
++ oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |
++ HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
++ if (hapd->iconf->secondary_channel == -1)
++ oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
++ HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
++ }
+
+ pos += sizeof(*oper);
+
+@@ -271,3 +276,80 @@ void hostapd_get_ht_capab(struct hostapd
+
+ neg_ht_cap->ht_capabilities_info = host_to_le16(cap);
+ }
++
++static void hostapd_set_force_20mhz(struct hostapd_iface *iface);
++
++static void hostapd_restore_40mhz(void *eloop_data, void *user_ctx)
++{
++ struct hostapd_iface *iface = eloop_data;
++ struct os_time time;
++ int timeout;
++
++ if (!iface->last_20mhz_trigger.sec)
++ return;
++
++ os_get_time(&time);
++ timeout = iface->last_20mhz_trigger.sec + iface->conf->dynamic_ht40 -
++ time.sec;
++
++ if (timeout > 0) {
++ eloop_register_timeout(timeout, 0, hostapd_restore_40mhz,
++ iface, NULL);
++ return;
++ }
++
++ iface->last_20mhz_trigger.sec = 0;
++ iface->last_20mhz_trigger.usec = 0;
++
++ iface->force_20mhz = 0;
++ hostapd_set_force_20mhz(iface);
++}
++
++static void hostapd_set_force_20mhz(struct hostapd_iface *iface)
++{
++ int secondary_channel;
++ int i;
++
++ ieee802_11_set_beacons(iface);
++
++ for (i = 0; i < iface->num_bss; i++) {
++ struct hostapd_data *hapd = iface->bss[i];
++
++ if (iface->force_20mhz)
++ secondary_channel = 0;
++ else
++ secondary_channel = hapd->iconf->secondary_channel;
++
++ if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq,
++ hapd->iconf->channel,
++ hapd->iconf->ieee80211n,
++ secondary_channel)) {
++ wpa_printf(MSG_ERROR, "Could not set channel for "
++ "kernel driver");
++ }
++ }
++}
++
++void hostapd_deinit_ht(struct hostapd_iface *iface)
++{
++ eloop_cancel_timeout(hostapd_restore_40mhz, iface, NULL);
++}
++
++void hostapd_trigger_20mhz(struct hostapd_iface *iface)
++{
++ if (!iface->conf->dynamic_ht40)
++ return;
++
++ if (!iface->force_20mhz) {
++ iface->force_20mhz = 1;
++ hostapd_set_force_20mhz(iface);
++ }
++
++ if (!iface->last_20mhz_trigger.sec) {
++ eloop_cancel_timeout(hostapd_restore_40mhz, iface, NULL);
++ eloop_register_timeout(iface->conf->dynamic_ht40, 0,
++ hostapd_restore_40mhz, iface, NULL);
++ }
++
++ os_get_time(&iface->last_20mhz_trigger);
++}
diff --git a/package/hostapd/patches/550-limit_debug_messages.patch b/package/hostapd/patches/550-limit_debug_messages.patch
new file mode 100644
index 000000000..659e98011
--- /dev/null
+++ b/package/hostapd/patches/550-limit_debug_messages.patch
@@ -0,0 +1,213 @@
+--- a/src/utils/wpa_debug.c
++++ b/src/utils/wpa_debug.c
+@@ -201,7 +201,7 @@ void wpa_debug_close_linux_tracing(void)
+ *
+ * Note: New line '\n' is added to the end of the text when printing to stdout.
+ */
+-void wpa_printf(int level, const char *fmt, ...)
++void _wpa_printf(int level, const char *fmt, ...)
+ {
+ va_list ap;
+
+@@ -248,8 +248,8 @@ void wpa_printf(int level, const char *f
+ }
+
+
+-static void _wpa_hexdump(int level, const char *title, const u8 *buf,
+- size_t len, int show)
++void _wpa_hexdump(int level, const char *title, const u8 *buf,
++ size_t len, int show)
+ {
+ size_t i;
+
+@@ -375,20 +375,9 @@ static void _wpa_hexdump(int level, cons
+ #endif /* CONFIG_ANDROID_LOG */
+ }
+
+-void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)
+-{
+- _wpa_hexdump(level, title, buf, len, 1);
+-}
+-
+-
+-void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)
+-{
+- _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys);
+-}
+
+-
+-static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
+- size_t len, int show)
++void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
++ size_t len, int show)
+ {
+ size_t i, llen;
+ const u8 *pos = buf;
+@@ -495,19 +484,6 @@ static void _wpa_hexdump_ascii(int level
+ }
+
+
+-void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len)
+-{
+- _wpa_hexdump_ascii(level, title, buf, len, 1);
+-}
+-
+-
+-void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
+- size_t len)
+-{
+- _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
+-}
+-
+-
+ #ifdef CONFIG_DEBUG_FILE
+ static char *last_path = NULL;
+ #endif /* CONFIG_DEBUG_FILE */
+@@ -591,7 +567,7 @@ void wpa_msg_register_ifname_cb(wpa_msg_
+ }
+
+
+-void wpa_msg(void *ctx, int level, const char *fmt, ...)
++void _wpa_msg(void *ctx, int level, const char *fmt, ...)
+ {
+ va_list ap;
+ char *buf;
+@@ -625,7 +601,7 @@ void wpa_msg(void *ctx, int level, const
+ }
+
+
+-void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
++void _wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
+ {
+ va_list ap;
+ char *buf;
+--- a/src/utils/wpa_debug.h
++++ b/src/utils/wpa_debug.h
+@@ -43,6 +43,17 @@ int wpa_debug_open_file(const char *path
+ int wpa_debug_reopen_file(void);
+ void wpa_debug_close_file(void);
+
++/* internal */
++void _wpa_hexdump(int level, const char *title, const u8 *buf,
++ size_t len, int show);
++void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
++ size_t len, int show);
++extern int wpa_debug_show_keys;
++
++#ifndef CONFIG_MSG_MIN_PRIORITY
++#define CONFIG_MSG_MIN_PRIORITY 0
++#endif
++
+ /**
+ * wpa_debug_printf_timestamp - Print timestamp for debug output
+ *
+@@ -63,9 +74,15 @@ void wpa_debug_print_timestamp(void);
+ *
+ * Note: New line '\n' is added to the end of the text when printing to stdout.
+ */
+-void wpa_printf(int level, const char *fmt, ...)
++void _wpa_printf(int level, const char *fmt, ...)
+ PRINTF_FORMAT(2, 3);
+
++#define wpa_printf(level, ...) \
++ do { \
++ if (level >= CONFIG_MSG_MIN_PRIORITY) \
++ _wpa_printf(level, __VA_ARGS__); \
++ } while(0)
++
+ /**
+ * wpa_hexdump - conditional hex dump
+ * @level: priority level (MSG_*) of the message
+@@ -77,7 +94,13 @@ PRINTF_FORMAT(2, 3);
+ * output may be directed to stdout, stderr, and/or syslog based on
+ * configuration. The contents of buf is printed out has hex dump.
+ */
+-void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len);
++static inline void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)
++{
++ if (level < CONFIG_MSG_MIN_PRIORITY)
++ return;
++
++ _wpa_hexdump(level, title, buf, len, 1);
++}
+
+ static inline void wpa_hexdump_buf(int level, const char *title,
+ const struct wpabuf *buf)
+@@ -99,7 +122,13 @@ static inline void wpa_hexdump_buf(int l
+ * like wpa_hexdump(), but by default, does not include secret keys (passwords,
+ * etc.) in debug output.
+ */
+-void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len);
++static inline void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)
++{
++ if (level < CONFIG_MSG_MIN_PRIORITY)
++ return;
++
++ _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys);
++}
+
+ static inline void wpa_hexdump_buf_key(int level, const char *title,
+ const struct wpabuf *buf)
+@@ -121,8 +150,14 @@ static inline void wpa_hexdump_buf_key(i
+ * the hex numbers and ASCII characters (for printable range) are shown. 16
+ * bytes per line will be shown.
+ */
+-void wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
+- size_t len);
++static inline void wpa_hexdump_ascii(int level, const char *title,
++ const u8 *buf, size_t len)
++{
++ if (level < CONFIG_MSG_MIN_PRIORITY)
++ return;
++
++ _wpa_hexdump_ascii(level, title, buf, len, 1);
++}
+
+ /**
+ * wpa_hexdump_ascii_key - conditional hex dump, hide keys
+@@ -138,8 +173,14 @@ void wpa_hexdump_ascii(int level, const
+ * bytes per line will be shown. This works like wpa_hexdump_ascii(), but by
+ * default, does not include secret keys (passwords, etc.) in debug output.
+ */
+-void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
+- size_t len);
++static inline void wpa_hexdump_ascii_key(int level, const char *title,
++ const u8 *buf, size_t len)
++{
++ if (level < CONFIG_MSG_MIN_PRIORITY)
++ return;
++
++ _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
++}
+
+ /*
+ * wpa_dbg() behaves like wpa_msg(), but it can be removed from build to reduce
+@@ -172,7 +213,12 @@ void wpa_hexdump_ascii_key(int level, co
+ *
+ * Note: New line '\n' is added to the end of the text when printing to stdout.
+ */
+-void wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4);
++void _wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4);
++#define wpa_msg(ctx, level, ...) \
++ do { \
++ if (level >= CONFIG_MSG_MIN_PRIORITY) \
++ _wpa_msg(ctx, level, __VA_ARGS__); \
++ } while(0)
+
+ /**
+ * wpa_msg_ctrl - Conditional printf for ctrl_iface monitors
+@@ -186,8 +232,13 @@ void wpa_msg(void *ctx, int level, const
+ * attached ctrl_iface monitors. In other words, it can be used for frequent
+ * events that do not need to be sent to syslog.
+ */
+-void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
++void _wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
+ PRINTF_FORMAT(3, 4);
++#define wpa_msg_ctrl(ctx, level, ...) \
++ do { \
++ if (level >= CONFIG_MSG_MIN_PRIORITY) \
++ _wpa_msg_ctrl(ctx, level, __VA_ARGS__); \
++ } while(0)
+
+ typedef void (*wpa_msg_cb_func)(void *ctx, int level, const char *txt,
+ size_t len);
diff --git a/package/hostapd/patches/560-indicate-features.patch b/package/hostapd/patches/560-indicate-features.patch
new file mode 100644
index 000000000..d01e18b86
--- /dev/null
+++ b/package/hostapd/patches/560-indicate-features.patch
@@ -0,0 +1,82 @@
+--- a/hostapd/main.c
++++ b/hostapd/main.c
+@@ -13,6 +13,7 @@
+
+ #include "utils/common.h"
+ #include "utils/eloop.h"
++#include "utils/build_features.h"
+ #include "crypto/random.h"
+ #include "crypto/tls.h"
+ #include "common/version.h"
+@@ -560,7 +561,7 @@ int main(int argc, char *argv[])
+
+ wpa_supplicant_event = hostapd_wpa_event;
+ for (;;) {
+- c = getopt(argc, argv, "Bde:f:hKP:tvg:");
++ c = getopt(argc, argv, "Bde:f:hKP:tg:v::");
+ if (c < 0)
+ break;
+ switch (c) {
+@@ -592,6 +593,8 @@ int main(int argc, char *argv[])
+ wpa_debug_timestamp++;
+ break;
+ case 'v':
++ if (optarg)
++ exit(!has_feature(optarg));
+ show_version();
+ exit(1);
+ break;
+--- a/wpa_supplicant/main.c
++++ b/wpa_supplicant/main.c
+@@ -12,6 +12,7 @@
+ #endif /* __linux__ */
+
+ #include "common.h"
++#include "build_features.h"
+ #include "wpa_supplicant_i.h"
+ #include "driver_i.h"
+
+@@ -156,7 +157,7 @@ int main(int argc, char *argv[])
+
+ for (;;) {
+ c = getopt(argc, argv,
+- "b:Bc:C:D:de:f:g:hH:i:KLNo:O:p:P:qsTtuvW");
++ "b:Bc:C:D:de:f:g:hH:i:KLNo:O:p:P:qsTtuv::W");
+ if (c < 0)
+ break;
+ switch (c) {
+@@ -248,8 +249,12 @@ int main(int argc, char *argv[])
+ break;
+ #endif /* CONFIG_DBUS */
+ case 'v':
+- printf("%s\n", wpa_supplicant_version);
+- exitcode = 0;
++ if (optarg) {
++ exitcode = !has_feature(optarg);
++ } else {
++ printf("%s\n", wpa_supplicant_version);
++ exitcode = 0;
++ }
+ goto out;
+ case 'W':
+ params.wait_for_monitor++;
+--- /dev/null
++++ b/src/utils/build_features.h
+@@ -0,0 +1,17 @@
++#ifndef BUILD_FEATURES_H
++#define BUILD_FEATURES_H
++
++static inline int has_feature(const char *feat)
++{
++#ifdef IEEE8021X_EAPOL
++ if (!strcmp(feat, "eap"))
++ return 1;
++#endif
++#ifdef IEEE80211N
++ if (!strcmp(feat, "11n"))
++ return 1;
++#endif
++ return 0;
++}
++
++#endif /* BUILD_FEATURES_H */
diff --git a/package/hostapd/patches/570-genl_connect_debug.patch b/package/hostapd/patches/570-genl_connect_debug.patch
new file mode 100644
index 000000000..5f140489b
--- /dev/null
+++ b/package/hostapd/patches/570-genl_connect_debug.patch
@@ -0,0 +1,11 @@
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -127,7 +127,7 @@ static struct nl_handle * nl_create_hand
+ }
+
+ if (genl_connect(handle)) {
+- wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic "
++ wpa_printf(MSG_DEBUG, "nl80211: Failed to connect to generic "
+ "netlink (%s)", dbg);
+ nl80211_handle_destroy(handle);
+ return NULL;
diff --git a/package/hostapd/patches/580-fix_bss_addr.patch b/package/hostapd/patches/580-fix_bss_addr.patch
new file mode 100644
index 000000000..3a76668c1
--- /dev/null
+++ b/package/hostapd/patches/580-fix_bss_addr.patch
@@ -0,0 +1,11 @@
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -7738,7 +7738,7 @@ static int i802_set_wds_sta(void *priv,
+ if (!if_nametoindex(name)) {
+ if (nl80211_create_iface(drv, name,
+ NL80211_IFTYPE_AP_VLAN,
+- NULL, 1) < 0)
++ bss->addr, 1) < 0)
+ return -1;
+ if (bridge_ifname &&
+ linux_br_add_if(drv->global->ioctl_sock,
diff --git a/package/hostapd/patches/590-hostapd_cli_ifdef.patch b/package/hostapd/patches/590-hostapd_cli_ifdef.patch
new file mode 100644
index 000000000..705cef13d
--- /dev/null
+++ b/package/hostapd/patches/590-hostapd_cli_ifdef.patch
@@ -0,0 +1,50 @@
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -67,7 +67,6 @@ static const char *commands_help =
+ #ifdef CONFIG_IEEE80211W
+ " sa_query <addr> send SA Query to a station\n"
+ #endif /* CONFIG_IEEE80211W */
+-#ifdef CONFIG_WPS
+ " wps_pin <uuid> <pin> [timeout] [addr] add WPS Enrollee PIN\n"
+ " wps_check_pin <PIN> verify PIN checksum\n"
+ " wps_pbc indicate button pushed to initiate PBC\n"
+@@ -82,7 +81,6 @@ static const char *commands_help =
+ #endif /* CONFIG_WPS_NFC */
+ " wps_ap_pin <cmd> [params..] enable/disable AP PIN\n"
+ " wps_config <SSID> <auth> <encr> <key> configure AP\n"
+-#endif /* CONFIG_WPS */
+ " get_config show current configuration\n"
+ " help show this usage help\n"
+ " interface [ifname] show interfaces/select interface\n"
+@@ -343,7 +341,6 @@ static int hostapd_cli_cmd_sa_query(stru
+ #endif /* CONFIG_IEEE80211W */
+
+
+-#ifdef CONFIG_WPS
+ static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+ {
+@@ -573,7 +570,6 @@ static int hostapd_cli_cmd_wps_config(st
+ ssid_hex, argv[1]);
+ return wpa_ctrl_command(ctrl, buf);
+ }
+-#endif /* CONFIG_WPS */
+
+
+ static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
+@@ -799,7 +795,6 @@ static struct hostapd_cli_cmd hostapd_cl
+ #ifdef CONFIG_IEEE80211W
+ { "sa_query", hostapd_cli_cmd_sa_query },
+ #endif /* CONFIG_IEEE80211W */
+-#ifdef CONFIG_WPS
+ { "wps_pin", hostapd_cli_cmd_wps_pin },
+ { "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
+ { "wps_pbc", hostapd_cli_cmd_wps_pbc },
+@@ -814,7 +809,6 @@ static struct hostapd_cli_cmd hostapd_cl
+ #endif /* CONFIG_WPS_NFC */
+ { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
+ { "wps_config", hostapd_cli_cmd_wps_config },
+-#endif /* CONFIG_WPS */
+ { "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
+ { "get_config", hostapd_cli_cmd_get_config },
+ { "help", hostapd_cli_cmd_help },
diff --git a/package/hostapd/patches/601-wpa_supplicant-add-new-config-params-to-be-used-with.patch b/package/hostapd/patches/601-wpa_supplicant-add-new-config-params-to-be-used-with.patch
new file mode 100644
index 000000000..ac0d247d7
--- /dev/null
+++ b/package/hostapd/patches/601-wpa_supplicant-add-new-config-params-to-be-used-with.patch
@@ -0,0 +1,211 @@
+From 4bb69d15477e0f2b00e166845341dc933de47c58 Mon Sep 17 00:00:00 2001
+From: Antonio Quartulli <ordex@autistici.org>
+Date: Sun, 3 Jun 2012 18:22:56 +0200
+Subject: [PATCHv2 601/602] wpa_supplicant: add new config params to be used
+ with the ibss join command
+
+Signed-hostap: Antonio Quartulli <ordex@autistici.org>
+---
+ src/drivers/driver.h | 6 +++
+ wpa_supplicant/config.c | 96 +++++++++++++++++++++++++++++++++++++++
+ wpa_supplicant/config_ssid.h | 6 +++
+ wpa_supplicant/wpa_supplicant.c | 23 +++++++---
+ 4 files changed, 124 insertions(+), 7 deletions(-)
+
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -19,6 +19,7 @@
+
+ #define WPA_SUPPLICANT_DRIVER_VERSION 4
+
++#include "drivers/nl80211_copy.h"
+ #include "common/defs.h"
+
+ #define HOSTAPD_CHAN_DISABLED 0x00000001
+@@ -351,6 +352,11 @@ struct wpa_driver_associate_params {
+ */
+ int freq;
+
++ int beacon_interval;
++ int fixed_freq;
++ unsigned char rates[NL80211_MAX_SUPP_RATES];
++ int mcast_rate;
++
+ /**
+ * bg_scan_period - Background scan period in seconds, 0 to disable
+ * background scan, or -1 to indicate no change to default driver
+--- a/wpa_supplicant/config.c
++++ b/wpa_supplicant/config.c
+@@ -14,6 +14,7 @@
+ #include "rsn_supp/wpa.h"
+ #include "eap_peer/eap.h"
+ #include "p2p/p2p.h"
++#include "drivers/nl80211_copy.h"
+ #include "config.h"
+
+
+@@ -1463,6 +1464,97 @@ static char * wpa_config_write_p2p_clien
+
+ #endif /* CONFIG_P2P */
+
++static int wpa_config_parse_mcast_rate(const struct parse_data *data,
++ struct wpa_ssid *ssid, int line,
++ const char *value)
++{
++ ssid->mcast_rate = (int)(strtod(value, NULL) * 10);
++
++ return 0;
++}
++
++#ifndef NO_CONFIG_WRITE
++static char * wpa_config_write_mcast_rate(const struct parse_data *data,
++ struct wpa_ssid *ssid)
++{
++ char *value;
++ int res;
++
++ if (!ssid->mcast_rate == 0)
++ return NULL;
++
++ value = os_malloc(6); /* longest: 300.0 */
++ if (value == NULL)
++ return NULL;
++ res = os_snprintf(value, 5, "%.1f", (double)ssid->mcast_rate / 10);
++ if (res < 0) {
++ os_free(value);
++ return NULL;
++ }
++ return value;
++}
++#endif /* NO_CONFIG_WRITE */
++
++static int wpa_config_parse_rates(const struct parse_data *data,
++ struct wpa_ssid *ssid, int line,
++ const char *value)
++{
++ int i;
++ char *pos, *r, *sptr, *end;
++ double rate;
++
++ pos = (char *)value;
++ r = strtok_r(pos, ",", &sptr);
++ i = 0;
++ while (pos && i < NL80211_MAX_SUPP_RATES) {
++ rate = 0.0;
++ if (r)
++ rate = strtod(r, &end);
++ ssid->rates[i] = rate * 2;
++ if (*end != '\0' || rate * 2 != ssid->rates[i])
++ return 1;
++
++ i++;
++ r = strtok_r(NULL, ",", &sptr);
++ }
++
++ return 0;
++}
++
++#ifndef NO_CONFIG_WRITE
++static char * wpa_config_write_rates(const struct parse_data *data,
++ struct wpa_ssid *ssid)
++{
++ char *value, *pos;
++ int res, i;
++
++ if (ssid->rates[0] <= 0)
++ return NULL;
++
++ value = os_malloc(6 * NL80211_MAX_SUPP_RATES + 1);
++ if (value == NULL)
++ return NULL;
++ pos = value;
++ for (i = 0; i < NL80211_MAX_SUPP_RATES - 1; i++) {
++ res = os_snprintf(pos, 6, "%.1f,", (double)ssid->rates[i] / 2);
++ if (res < 0) {
++ os_free(value);
++ return NULL;
++ }
++ pos += res;
++ }
++ res = os_snprintf(pos, 6, "%.1f",
++ (double)ssid->rates[NL80211_MAX_SUPP_RATES - 1] / 2);
++ if (res < 0) {
++ os_free(value);
++ return NULL;
++ }
++
++ value[6 * NL80211_MAX_SUPP_RATES] = '\0';
++ return value;
++}
++#endif /* NO_CONFIG_WRITE */
++
+ /* Helper macros for network block parser */
+
+ #ifdef OFFSET
+@@ -1638,6 +1730,10 @@ static const struct parse_data ssid_fiel
+ #endif /* CONFIG_HT_OVERRIDES */
+ { INT(ap_max_inactivity) },
+ { INT(dtim_period) },
++ { INT_RANGE(fixed_freq, 0, 1) },
++ { INT_RANGE(beacon_interval, 0, 1000) },
++ { FUNC(rates) },
++ { FUNC(mcast_rate) },
+ };
+
+ #undef OFFSET
+--- a/wpa_supplicant/config_ssid.h
++++ b/wpa_supplicant/config_ssid.h
+@@ -11,6 +11,7 @@
+
+ #include "common/defs.h"
+ #include "eap_peer/eap_config.h"
++#include "drivers/nl80211_copy.h"
+
+ #define MAX_SSID_LEN 32
+
+@@ -529,6 +530,11 @@ struct wpa_ssid {
+ * disabled_until - Network block disabled until this time if non-zero
+ */
+ struct os_time disabled_until;
++
++ int fixed_freq;
++ int beacon_interval;
++ unsigned char rates[NL80211_MAX_SUPP_RATES];
++ double mcast_rate;
+ };
+
+ #endif /* CONFIG_SSID_H */
+--- a/wpa_supplicant/wpa_supplicant.c
++++ b/wpa_supplicant/wpa_supplicant.c
+@@ -1561,15 +1561,24 @@ void wpa_supplicant_associate(struct wpa
+ params.ssid_len = ssid->ssid_len;
+ }
+
+- if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
+- wpa_s->conf->ap_scan == 2) {
+- params.bssid = ssid->bssid;
+- params.fixed_bssid = 1;
++ if (ssid->mode == WPAS_MODE_IBSS) {
++ if (ssid->bssid_set && wpa_s->conf->ap_scan == 2) {
++ params.bssid = ssid->bssid;
++ params.fixed_bssid = 1;
++ }
++ if (ssid->frequency > 0 && params.freq == 0)
++ /* Initial channel for IBSS */
++ params.freq = ssid->frequency;
++ params.fixed_freq = ssid->fixed_freq;
++ params.beacon_interval = ssid->beacon_interval;
++ i = 0;
++ while (i < NL80211_MAX_SUPP_RATES) {
++ params.rates[i] = ssid->rates[i];
++ i++;
++ }
++ params.mcast_rate = ssid->mcast_rate;
+ }
+
+- if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
+- params.freq == 0)
+- params.freq = ssid->frequency; /* Initial channel for IBSS */
+ params.wpa_ie = wpa_ie;
+ params.wpa_ie_len = wpa_ie_len;
+ params.pairwise_suite = cipher_pairwise;
diff --git a/package/hostapd/patches/602-driver_nl80211-use-new-parameters-during-ibss-join.patch b/package/hostapd/patches/602-driver_nl80211-use-new-parameters-during-ibss-join.patch
new file mode 100644
index 000000000..c426a0bb2
--- /dev/null
+++ b/package/hostapd/patches/602-driver_nl80211-use-new-parameters-during-ibss-join.patch
@@ -0,0 +1,59 @@
+From ffc4445958a3ed4064f2e1bf73fa478a61c5cf7b Mon Sep 17 00:00:00 2001
+From: Antonio Quartulli <ordex@autistici.org>
+Date: Sun, 3 Jun 2012 18:42:25 +0200
+Subject: [PATCHv2 602/602] driver_nl80211: use new parameters during ibss join
+
+Signed-hostap: Antonio Quartulli <ordex@autistici.org>
+---
+ src/drivers/driver_nl80211.c | 33 ++++++++++++++++++++++++++++++++-
+ 1 file changed, 32 insertions(+), 1 deletion(-)
+
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -6587,7 +6587,7 @@ static int wpa_driver_nl80211_ibss(struc
+ struct wpa_driver_associate_params *params)
+ {
+ struct nl_msg *msg;
+- int ret = -1;
++ int ret = -1, i;
+ int count = 0;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex);
+@@ -6620,6 +6620,37 @@ retry:
+ wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
+
++ if (params->fixed_freq) {
++ wpa_printf(MSG_DEBUG, " * fixed_freq");
++ NLA_PUT_FLAG(msg, NL80211_ATTR_FREQ_FIXED);
++ }
++
++ if (params->beacon_interval > 0) {
++ wpa_printf(MSG_DEBUG, " * beacon_interval=%d",
++ params->beacon_interval);
++ NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL,
++ params->beacon_interval);
++ }
++
++ if (params->rates[0] > 0) {
++ wpa_printf(MSG_DEBUG, " * basic_rates:");
++ i = 0;
++ while (i < NL80211_MAX_SUPP_RATES &&
++ params->rates[i] > 0) {
++ wpa_printf(MSG_DEBUG, " %.1f",
++ (double)params->rates[i] / 2);
++ i++;
++ }
++ NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, i,
++ params->rates);
++ }
++
++ if (params->mcast_rate > 0) {
++ wpa_printf(MSG_DEBUG, " * mcast_rates=%.1f",
++ (double)params->mcast_rate / 10);
++ NLA_PUT_U32(msg, NL80211_ATTR_MCAST_RATE, params->mcast_rate);
++ }
++
+ ret = nl80211_set_conn_keys(params, msg);
+ if (ret)
+ goto nla_put_failure;
diff --git a/package/hostapd/patches/604-wpa_s-support-htmode-param.patch b/package/hostapd/patches/604-wpa_s-support-htmode-param.patch
new file mode 100644
index 000000000..44931f2f3
--- /dev/null
+++ b/package/hostapd/patches/604-wpa_s-support-htmode-param.patch
@@ -0,0 +1,156 @@
+From b9329c5dfeed7d5c55d2117d8dfe326fc40c8fb1 Mon Sep 17 00:00:00 2001
+From: Antonio Quartulli <ordex@autistici.org>
+Date: Tue, 3 Jul 2012 00:36:24 +0200
+Subject: [PATCH] wpa_s: support htmode param
+
+possible values are HT20, HT40-, HT40+ and NOHT
+
+Signed-off-by: Antonio Quartulli <ordex@autistici.org>
+---
+ src/drivers/driver.h | 2 ++
+ src/drivers/driver_nl80211.c | 16 ++++++++++
+ wpa_supplicant/config.c | 66 +++++++++++++++++++++++++++++++++++++++
+ wpa_supplicant/config_ssid.h | 2 ++
+ wpa_supplicant/wpa_supplicant.c | 2 ++
+ 5 files changed, 88 insertions(+)
+
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -356,6 +356,8 @@ struct wpa_driver_associate_params {
+ int fixed_freq;
+ unsigned char rates[NL80211_MAX_SUPP_RATES];
+ int mcast_rate;
++ int ht_set;
++ unsigned int htmode;
+
+ /**
+ * bg_scan_period - Background scan period in seconds, 0 to disable
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -6651,6 +6651,22 @@ retry:
+ NLA_PUT_U32(msg, NL80211_ATTR_MCAST_RATE, params->mcast_rate);
+ }
+
++ if (params->ht_set) {
++ switch(params->htmode) {
++ case NL80211_CHAN_HT20:
++ wpa_printf(MSG_DEBUG, " * ht=HT20");
++ break;
++ case NL80211_CHAN_HT40PLUS:
++ wpa_printf(MSG_DEBUG, " * ht=HT40+");
++ break;
++ case NL80211_CHAN_HT40MINUS:
++ wpa_printf(MSG_DEBUG, " * ht=HT40-");
++ break;
++ }
++ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
++ params->htmode);
++ }
++
+ ret = nl80211_set_conn_keys(params, msg);
+ if (ret)
+ goto nla_put_failure;
+--- a/wpa_supplicant/config.c
++++ b/wpa_supplicant/config.c
+@@ -1495,6 +1495,71 @@ static char * wpa_config_write_mcast_rat
+ }
+ #endif /* NO_CONFIG_WRITE */
+
++static int wpa_config_parse_htmode(const struct parse_data *data,
++ struct wpa_ssid *ssid, int line,
++ const char *value)
++{
++ int i;
++ static const struct {
++ const char *name;
++ unsigned int val;
++ } htmap[] = {
++ { .name = "HT20", .val = NL80211_CHAN_HT20, },
++ { .name = "HT40+", .val = NL80211_CHAN_HT40PLUS, },
++ { .name = "HT40-", .val = NL80211_CHAN_HT40MINUS, },
++ { .name = "NOHT", .val = NL80211_CHAN_NO_HT, },
++ };
++ ssid->ht_set = 0;;
++ for (i = 0; i < 4; i++) {
++ if (strcasecmp(htmap[i].name, value) == 0) {
++ ssid->htmode = htmap[i].val;
++ ssid->ht_set = 1;
++ break;
++ }
++ }
++
++ return 0;
++}
++
++#ifndef NO_CONFIG_WRITE
++static char * wpa_config_write_htmode(const struct parse_data *data,
++ struct wpa_ssid *ssid)
++{
++ char *value;
++ int res;
++
++ value = os_malloc(6); /* longest: HT40+ */
++ if (value == NULL)
++ return NULL;
++
++ switch(ssid->htmode) {
++ case NL80211_CHAN_HT20:
++ res = os_snprintf(value, 4, "HT20");
++ break;
++ case NL80211_CHAN_HT40PLUS:
++ res = os_snprintf(value, 5, "HT40+");
++ break;
++ case NL80211_CHAN_HT40MINUS:
++ res = os_snprintf(value, 5, "HT40-");
++ break;
++ case NL80211_CHAN_NO_HT:
++ res = os_snprintf(value, 4, "NOHT");
++ break;
++ default:
++ os_free(value);
++ return NULL;
++ }
++
++ if (res < 0) {
++ os_free(value);
++ return NULL;
++ }
++
++ return value;
++}
++#endif /* NO_CONFIG_WRITE */
++
++
+ static int wpa_config_parse_rates(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+@@ -1734,6 +1799,7 @@ static const struct parse_data ssid_fiel
+ { INT_RANGE(beacon_interval, 0, 1000) },
+ { FUNC(rates) },
+ { FUNC(mcast_rate) },
++ { FUNC(htmode) },
+ };
+
+ #undef OFFSET
+--- a/wpa_supplicant/config_ssid.h
++++ b/wpa_supplicant/config_ssid.h
+@@ -535,6 +535,8 @@ struct wpa_ssid {
+ int beacon_interval;
+ unsigned char rates[NL80211_MAX_SUPP_RATES];
+ double mcast_rate;
++ int ht_set;
++ unsigned int htmode;
+ };
+
+ #endif /* CONFIG_SSID_H */
+--- a/wpa_supplicant/wpa_supplicant.c
++++ b/wpa_supplicant/wpa_supplicant.c
+@@ -1577,6 +1577,8 @@ void wpa_supplicant_associate(struct wpa
+ i++;
+ }
+ params.mcast_rate = ssid->mcast_rate;
++ params.ht_set = ssid->ht_set;
++ params.htmode = ssid->htmode;
+ }
+
+ params.wpa_ie = wpa_ie;
diff --git a/package/hostapd/patches/610-max_num_sta_probe.patch b/package/hostapd/patches/610-max_num_sta_probe.patch
new file mode 100644
index 000000000..e22348c89
--- /dev/null
+++ b/package/hostapd/patches/610-max_num_sta_probe.patch
@@ -0,0 +1,13 @@
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -413,6 +413,10 @@ void handle_probe_req(struct hostapd_dat
+ return;
+ }
+
++ if (!sta && hapd->num_sta >= hapd->conf->max_num_sta)
++ wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " ignored,"
++ " too many connected stations.", MAC2STR(mgmt->sa));
++
+ #ifdef CONFIG_INTERWORKING
+ if (elems.interworking && elems.interworking_len >= 1) {
+ u8 ant = elems.interworking[0] & 0x0f;
diff --git a/package/hotplug2/Makefile b/package/hotplug2/Makefile
new file mode 100644
index 000000000..e8483ddc7
--- /dev/null
+++ b/package/hotplug2/Makefile
@@ -0,0 +1,65 @@
+#
+# Copyright (C) 2006-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=hotplug2
+PKG_REV:=201
+PKG_VERSION:=$(PKG_REV)
+PKG_RELEASE:=4
+
+PKG_SOURCE_PROTO:=svn
+PKG_SOURCE_VERSION:=$(PKG_REV)
+PKG_SOURCE_SUBDIR:=hotplug2-$(PKG_VERSION)
+PKG_SOURCE_URL:=http://svn.nomi.cz/svn/isteve/hotplug2
+PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.gz
+#PKG_SOURCE_URL:=http://isteve.bofh.cz/~isteve/hotplug2
+#PKG_MD5SUM:=ea2c01d027b4002e4e6b0ff266f51a51
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/hotplug2
+ SECTION:=base
+ CATEGORY:=Base system
+ VERSION:=1.0-beta-$(PKG_RELEASE)
+ TITLE:=Version 1.0 Dynamic device management subsystem for embedded systems
+ URL:=http://isteve.bofh.cz/~isteve/hotplug2/
+ DEPENDS:=+!USE_UCLIBC:libbsd
+endef
+
+define Package/hotplug2/description
+ Hotplug2 is a trivial replacement of some of the UDev functionality
+ in a tiny pack, intended for Linux early userspace: Init RAM FS and InitRD.
+ This is an implementation of Hotplug2-1.0-beta
+endef
+
+define Package/hotplug2/conffiles
+/etc/hotplug2.rules
+endef
+
+MAKE_FLAGS += \
+ COPTS="$(TARGET_CFLAGS)" \
+ STATIC_WORKER="fork"
+
+ifneq ($(CONFIG_USE_EGLIBC),)
+ TARGET_LDFLAGS += -lbsd
+endif
+
+define Build/Compile
+ $(call Build/Compile/Default)
+ $(TARGET_CC) $(TARGET_CFLAGS) $(TARGET_LDFLAGS) -o $(PKG_BUILD_DIR)/udevtrigger src/udevtrigger.c
+endef
+
+define Package/hotplug2/install
+ $(INSTALL_DIR) $(1)/etc
+ $(INSTALL_DATA) ./files/hotplug2.rules $(1)/etc/
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/udevtrigger $(1)/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/hotplug2 $(1)/sbin/
+endef
+
+$(eval $(call BuildPackage,hotplug2))
diff --git a/package/hotplug2/files/hotplug2.rules b/package/hotplug2/files/hotplug2.rules
new file mode 100644
index 000000000..246cc3ab4
--- /dev/null
+++ b/package/hotplug2/files/hotplug2.rules
@@ -0,0 +1,10 @@
+$include /etc/hotplug2-common.rules
+
+SUBSYSTEM ~~ (^net$|^input$|^button$|^usb$|^ieee1394$|^block$|^atm$|^zaptel$|^tty$) {
+ exec /sbin/hotplug-call %SUBSYSTEM%
+}
+
+DEVICENAME == watchdog {
+ exec /sbin/watchdog -t 5 /dev/watchdog
+ next-event
+}
diff --git a/package/hotplug2/patches/100-env_memleak.patch b/package/hotplug2/patches/100-env_memleak.patch
new file mode 100644
index 000000000..28a3e2510
--- /dev/null
+++ b/package/hotplug2/patches/100-env_memleak.patch
@@ -0,0 +1,63 @@
+--- a/action.c
++++ b/action.c
+@@ -31,6 +31,30 @@ static void action_dumb(const struct set
+ }
+
+ /**
++ * Creates a "key=value" string from the given key and value
++ *
++ * @1 Key
++ * @2 Value
++ *
++ * Returns: Newly allocated string in "key=value" form
++ *
++ */
++static char* alloc_env(const char *key, const char *value) {
++ size_t keylen, vallen;
++ char *combined;
++
++ keylen = strlen(key);
++ vallen = strlen(value) + 1;
++
++ combined = xmalloc(keylen + vallen + 1);
++ memcpy(combined, key, keylen);
++ combined[keylen] = '=';
++ memcpy(&combined[keylen + 1], value, vallen);
++
++ return combined;
++}
++
++/**
+ * Choose what action should be taken according to passed settings.
+ *
+ * @1 Hotplug settings
+@@ -41,16 +65,25 @@ static void action_dumb(const struct set
+ */
+ void action_perform(struct settings_t *settings, struct uevent_t *event) {
+ int i;
++ char **env;
++
++ env = xmalloc(sizeof(char *) * event->env_vars_c);
++
++ for (i = 0; i < event->env_vars_c; i++) {
++ env[i] = alloc_env(event->env_vars[i].key, event->env_vars[i].value);
++ putenv(env[i]);
++ }
+
+- for (i = 0; i < event->env_vars_c; i++)
+- setenv(event->env_vars[i].key, event->env_vars[i].value, 1);
+-
+ if (settings->dumb == 0) {
+ ruleset_execute(&settings->rules, event, settings);
+ } else {
+ action_dumb(settings, event);
+ }
+
+- for (i = 0; i < event->env_vars_c; i++)
++ for (i = 0; i < event->env_vars_c; i++) {
+ unsetenv(event->env_vars[i].key);
++ free(env[i]);
++ }
++
++ free(env);
+ }
diff --git a/package/hotplug2/patches/110-static_worker.patch b/package/hotplug2/patches/110-static_worker.patch
new file mode 100644
index 000000000..3a5181f74
--- /dev/null
+++ b/package/hotplug2/patches/110-static_worker.patch
@@ -0,0 +1,20 @@
+--- a/common.mak
++++ b/common.mak
+@@ -1,7 +1,7 @@
+ # vim:set sw=8 nosta:
+
+ COPTS=-Os -Wall -g
+-LDFLAGS=-g -ldl
++LDFLAGS=-g
+
+ CFLAGS=$(COPTS)
+ FPIC=-fPIC
+--- a/Makefile
++++ b/Makefile
+@@ -40,5 +40,6 @@ ifdef STATIC_WORKER
+ CFLAGS += -DSTATIC_WORKER=1
+ else
+ CFLAGS += $(FPIC)
++ LDFLAGS += -ldl
+ endif
+
diff --git a/package/hotplug2/patches/120-sysfs_path_fix.patch b/package/hotplug2/patches/120-sysfs_path_fix.patch
new file mode 100644
index 000000000..0903057c7
--- /dev/null
+++ b/package/hotplug2/patches/120-sysfs_path_fix.patch
@@ -0,0 +1,14 @@
+--- a/rules/command.c
++++ b/rules/command.c
+@@ -374,9 +374,9 @@ RULES_COMMAND_F(cmd_firmware) {
+ if (firmware == NULL)
+ return -1;
+
+- if (snprintf(sysfs_path_loading, PATH_MAX, "/sysfs%s/loading", devpath) >= PATH_MAX)
++ if (snprintf(sysfs_path_loading, PATH_MAX, "/sys%s/loading", devpath) >= PATH_MAX)
+ return -1;
+- if (snprintf(sysfs_path_data, PATH_MAX, "/sysfs%s/data", devpath) >= PATH_MAX)
++ if (snprintf(sysfs_path_data, PATH_MAX, "/sys%s/data", devpath) >= PATH_MAX)
+ return -1;
+ if (snprintf(firmware_path, PATH_MAX, "%s/%s", argv[0], firmware) >= PATH_MAX)
+ return -1;
diff --git a/package/hotplug2/patches/130-cancel_download_fix.patch b/package/hotplug2/patches/130-cancel_download_fix.patch
new file mode 100644
index 000000000..c94000dcc
--- /dev/null
+++ b/package/hotplug2/patches/130-cancel_download_fix.patch
@@ -0,0 +1,18 @@
+--- a/rules/command.c
++++ b/rules/command.c
+@@ -385,13 +385,13 @@ RULES_COMMAND_F(cmd_firmware) {
+
+ infp = fopen(firmware_path, "r");
+ if (infp == NULL) {
+- echo_to_file(sysfs_path_loading, "0\n", 2);
++ echo_to_file(sysfs_path_loading, "-1\n", 2);
+ return -1;
+ }
+ outfp = fopen(sysfs_path_data, "w");
+ if (outfp == NULL) {
+ fclose(infp);
+- echo_to_file(sysfs_path_loading, "0\n", 2);
++ echo_to_file(sysfs_path_loading, "-1\n", 2);
+ return -1;
+ }
+
diff --git a/package/hotplug2/patches/140-worker_fork_fix.patch b/package/hotplug2/patches/140-worker_fork_fix.patch
new file mode 100644
index 000000000..eaf3c5c36
--- /dev/null
+++ b/package/hotplug2/patches/140-worker_fork_fix.patch
@@ -0,0 +1,56 @@
+--- a/action.c
++++ b/action.c
+@@ -39,7 +39,7 @@ static void action_dumb(const struct set
+ * Returns: Newly allocated string in "key=value" form
+ *
+ */
+-static char* alloc_env(const char *key, const char *value) {
++char* alloc_env(const char *key, const char *value) {
+ size_t keylen, vallen;
+ char *combined;
+
+--- a/action.h
++++ b/action.h
+@@ -12,5 +12,6 @@
+ #include "settings.h"
+
+ void action_perform(struct settings_t *, struct uevent_t *);
++char* alloc_env(const char *, const char *);
+ #endif /* ifndef ACTION_H */
+
+--- a/workers/worker_fork.c
++++ b/workers/worker_fork.c
+@@ -380,6 +380,7 @@ static void worker_fork_deinit(void *in_
+
+
+ static int worker_fork_process(void *in_ctx, struct uevent_t *uevent) {
++ char **env;
+ int i;
+ struct worker_fork_child_t *child;
+ struct worker_fork_ctx_t *ctx = in_ctx;
+@@ -406,6 +407,12 @@ static int worker_fork_process(void *in_
+ * No child process is currently available.
+ */
+ if (child == NULL) {
++ env = xmalloc(sizeof(char *) * uevent->env_vars_c);
++ for (i = 0; i < uevent->env_vars_c; i++) {
++ env[i] = alloc_env(uevent->env_vars[i].key, uevent->env_vars[i].value);
++ putenv(env[i]);
++ }
++
+ /*
+ * Are the matching rules trivial enough that we
+ * can execute them in the main process?
+@@ -421,6 +428,12 @@ static int worker_fork_process(void *in_
+ */
+ if (ctx->children_count < ctx->max_children)
+ child = worker_fork_spawn(ctx);
++
++ for (i = 0; i < uevent->env_vars_c; i++) {
++ unsetenv(uevent->env_vars[i].key);
++ free(env[i]);
++ }
++ free(env);
+ }
+
+ /*
diff --git a/package/hotplug2/patches/150-force_fork_slow.patch b/package/hotplug2/patches/150-force_fork_slow.patch
new file mode 100644
index 000000000..47101f56b
--- /dev/null
+++ b/package/hotplug2/patches/150-force_fork_slow.patch
@@ -0,0 +1,21 @@
+--- a/workers/worker_fork.c
++++ b/workers/worker_fork.c
+@@ -396,7 +396,7 @@ static int worker_fork_process(void *in_
+ worker_fork_update_children(ctx);
+
+ child = NULL;
+- for (i = 0; i < ctx->children_count; i++) {
++ for (i = 0; i < ctx->children_count && i < ctx->max_children; i++) {
+ if (ctx->children[i]->busy == 0) {
+ child = ctx->children[i];
+ break;
+@@ -426,7 +426,8 @@ static int worker_fork_process(void *in_
+ /*
+ * We have to fork off a new child.
+ */
+- if (ctx->children_count < ctx->max_children)
++ if (ctx->children_count < ctx->max_children ||
++ (ruleset_flags(&ctx->settings->rules, uevent) & FLAG_SLOW))
+ child = worker_fork_spawn(ctx);
+
+ for (i = 0; i < uevent->env_vars_c; i++) {
diff --git a/package/hotplug2/patches/160-event_block_fix.patch b/package/hotplug2/patches/160-event_block_fix.patch
new file mode 100644
index 000000000..ac7e79ab1
--- /dev/null
+++ b/package/hotplug2/patches/160-event_block_fix.patch
@@ -0,0 +1,200 @@
+--- a/uevent.c
++++ b/uevent.c
+@@ -132,6 +132,8 @@ struct uevent_t *uevent_dup(const struct
+
+ dest = xmalloc(sizeof(struct uevent_t));
+ dest->action = src->action;
++ dest->seqnum = src->seqnum;
++ dest->action_str = strdup(src->action_str);
+ dest->env_vars_c = src->env_vars_c;
+ dest->env_vars = xmalloc(sizeof(struct env_var_t) * dest->env_vars_c);
+ dest->plain_s = src->plain_s;
+--- a/workers/worker_fork.c
++++ b/workers/worker_fork.c
+@@ -1,6 +1,69 @@
+ #include "worker_fork.h"
+
+ static struct worker_fork_ctx_t *global_ctx;
++static struct worker_fork_uevent_t *uevent_list;
++
++static void worker_fork_uevent_free(struct worker_fork_uevent_t *node) {
++ uevent_free(node->uevent);
++ free(node);
++}
++
++static void worker_fork_uevent_add(void *in_ctx, struct uevent_t *uevent) {
++ char **env;
++ int i;
++ struct worker_fork_ctx_t *ctx = in_ctx;
++ struct worker_fork_uevent_t *node, *walker;
++
++ node = malloc(sizeof (struct worker_fork_uevent_t));
++ node->uevent = uevent_dup(uevent);
++ node->next = NULL;
++
++ if (!uevent_list) uevent_list = node;
++ else {
++ /*
++ * Put events that need to fork first and in reverse order
++ */
++ env = xmalloc(sizeof(char *) * node->uevent->env_vars_c);
++ for (i = 0; i < node->uevent->env_vars_c; i++) {
++ env[i] = alloc_env(node->uevent->env_vars[i].key, node->uevent->env_vars[i].value);
++ putenv(env[i]);
++ }
++ if (ruleset_flags(&ctx->settings->rules, uevent) & FLAG_SLOW) {
++ node->next = uevent_list;
++ uevent_list = node;
++ }
++ else {
++ for (walker = uevent_list; walker->next; walker = walker->next);
++ walker->next = node;
++ }
++ for (i = 0; i < node->uevent->env_vars_c; i++) {
++ unsetenv(node->uevent->env_vars[i].key);
++ free(env[i]);
++ }
++ free(env);
++ }
++}
++
++static void worker_fork_uevent_del(struct worker_fork_uevent_t *node) {
++ struct worker_fork_uevent_t *walker;
++
++ if (node == uevent_list) {
++ uevent_list = node->next;
++ }
++ else {
++ for (walker = uevent_list; walker->next; walker = walker->next)
++ if (walker->next == node) walker->next = node->next;
++ }
++ worker_fork_uevent_free(node);
++}
++
++static void worker_fork_uevent_empty(void) {
++ struct worker_fork_uevent_t *walker;
++
++ if (!uevent_list) return;
++ for (walker = uevent_list; walker->next; walker = walker->next) worker_fork_uevent_free(walker);
++ uevent_list = NULL;
++}
+
+ /**
+ * Destroys data structures related to the given child ID (not PID).
+@@ -315,6 +378,8 @@ static void *worker_fork_init(struct set
+ struct worker_fork_ctx_t *ctx;
+ PRINTFUNC();
+
++ uevent_list = NULL;
++
+ ctx = malloc(sizeof(struct worker_fork_ctx_t));
+ ctx->children = NULL;
+ ctx->children_count = 0;
+@@ -376,6 +441,7 @@ static void worker_fork_deinit(void *in_
+ free(ctx->children);
+ free(ctx);
+ global_ctx = NULL;
++ worker_fork_uevent_empty();
+ }
+
+
+@@ -384,15 +450,26 @@ static int worker_fork_process(void *in_
+ int i;
+ struct worker_fork_child_t *child;
+ struct worker_fork_ctx_t *ctx = in_ctx;
++ struct worker_fork_uevent_t *node, *walker;
++ event_seqnum_t seqnum;
++
++ worker_fork_uevent_add(ctx, uevent);
++ walker = uevent_list;
+
+ /*
+- * A big loop, because if we fail to process the event,
++ * A big loop, because if we fail to process the events,
+ * we don't want to give up.
+ *
+ * TODO: Decide if we want to limit the number of attempts
+ * or set a time limit before reporting terminal failure.
+ */
+ do {
++ /*
++ * If more events are waiting, return to receive them
++ */
++ if (!seqnum_get(&seqnum) && seqnum > uevent->seqnum) break;
++
++ node = walker;
+ worker_fork_update_children(ctx);
+
+ child = NULL;
+@@ -407,9 +484,9 @@ static int worker_fork_process(void *in_
+ * No child process is currently available.
+ */
+ if (child == NULL) {
+- env = xmalloc(sizeof(char *) * uevent->env_vars_c);
+- for (i = 0; i < uevent->env_vars_c; i++) {
+- env[i] = alloc_env(uevent->env_vars[i].key, uevent->env_vars[i].value);
++ env = xmalloc(sizeof(char *) * node->uevent->env_vars_c);
++ for (i = 0; i < node->uevent->env_vars_c; i++) {
++ env[i] = alloc_env(node->uevent->env_vars[i].key, node->uevent->env_vars[i].value);
+ putenv(env[i]);
+ }
+
+@@ -418,8 +495,11 @@ static int worker_fork_process(void *in_
+ * can execute them in the main process?
+ */
+ if (ctx->always_fork == 0 && ctx->settings->dumb == 0 &&
+- (ruleset_flags(&ctx->settings->rules, uevent) & FLAG_MASK_SLOW) == 0) {
+- action_perform(ctx->settings, uevent);
++ (ruleset_flags(&ctx->settings->rules, node->uevent) & FLAG_MASK_SLOW) == 0) {
++ action_perform(ctx->settings, node->uevent);
++ walker = walker->next;
++ worker_fork_uevent_del(node);
++ if (walker) continue;
+ break;
+ }
+
+@@ -427,11 +507,11 @@ static int worker_fork_process(void *in_
+ * We have to fork off a new child.
+ */
+ if (ctx->children_count < ctx->max_children ||
+- (ruleset_flags(&ctx->settings->rules, uevent) & FLAG_SLOW))
++ (ruleset_flags(&ctx->settings->rules, node->uevent) & FLAG_SLOW))
+ child = worker_fork_spawn(ctx);
+
+- for (i = 0; i < uevent->env_vars_c; i++) {
+- unsetenv(uevent->env_vars[i].key);
++ for (i = 0; i < node->uevent->env_vars_c; i++) {
++ unsetenv(node->uevent->env_vars[i].key);
+ free(env[i]);
+ }
+ free(env);
+@@ -442,9 +522,14 @@ static int worker_fork_process(void *in_
+ */
+ if (child != NULL) {
+ child->busy = 1;
+- if (!worker_fork_relay_event(child->event_fd, uevent));
+- break;
+- child->busy = 0;
++ if (worker_fork_relay_event(child->event_fd, node->uevent)) {
++ child->busy = 0;
++ continue;
++ }
++ walker = walker->next;
++ worker_fork_uevent_del(node);
++ if (walker) continue;
++ break;
+ }
+
+ /*
+--- a/workers/worker_fork.h
++++ b/workers/worker_fork.h
+@@ -35,4 +35,9 @@ struct worker_fork_ctx_t {
+ struct settings_t *settings;
+ };
+
++struct worker_fork_uevent_t {
++ struct uevent_t *uevent;
++ struct worker_fork_uevent_t *next;
++};
++
+ #endif
diff --git a/package/hotplug2/patches/170-non_fatal_include.patch b/package/hotplug2/patches/170-non_fatal_include.patch
new file mode 100644
index 000000000..0b8e85283
--- /dev/null
+++ b/package/hotplug2/patches/170-non_fatal_include.patch
@@ -0,0 +1,21 @@
+Index: hotplug2-201/parser/parser.c
+===================================================================
+--- hotplug2-201.orig/parser/parser.c 2009-12-09 19:44:13.000000000 +0100
++++ hotplug2-201/parser/parser.c 2011-02-08 18:06:44.681213713 +0100
+@@ -1,5 +1,7 @@
+ #include "parser.h"
+
++#include <errno.h>
++
+ /*
+ * Grammar:
+ * input => directive // TOKEN_ROOTKW
+@@ -578,7 +580,7 @@
+ ctx.lexer.fp = fopen(filename, "r");
+ if (ctx.lexer.fp == NULL) {
+ parser_clear(&ctx);
+- return -1;
++ return (errno == ENOENT) ? 0 : -1;
+ }
+ ctx.lexer.filename = strdup(filename);
+
diff --git a/package/hotplug2/src/udevtrigger.c b/package/hotplug2/src/udevtrigger.c
new file mode 100644
index 000000000..297e64cc9
--- /dev/null
+++ b/package/hotplug2/src/udevtrigger.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2004-2006 Kay Sievers <kay@vrfy.org>
+ * Copyright (C) 2006 Hannes Reinecke <hare@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 of the License.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#define PATH_SIZE 512
+
+static int verbose;
+static int dry_run;
+
+void log_message(int priority, const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ vsyslog(priority, format, args);
+ va_end(args);
+}
+
+#undef err
+#define err(format, arg...) \
+ do { \
+ log_message(LOG_ERR ,"%s: " format ,__FUNCTION__ ,## arg); \
+ } while (0)
+
+#undef info
+#define info(format, arg...) \
+ do { \
+ log_message(LOG_INFO ,"%s: " format ,__FUNCTION__ ,## arg); \
+ } while (0)
+
+#ifdef DEBUG
+#undef dbg
+#define dbg(format, arg...) \
+ do { \
+ log_message(LOG_DEBUG ,"%s: " format ,__FUNCTION__ ,## arg); \
+ } while (0)
+#else
+#define dbg(...) do {} while(0)
+#endif
+
+
+static void trigger_uevent(const char *devpath)
+{
+ char filename[PATH_SIZE];
+ int fd;
+
+ strlcpy(filename, "/sys", sizeof(filename));
+ strlcat(filename, devpath, sizeof(filename));
+ strlcat(filename, "/uevent", sizeof(filename));
+
+ if (verbose)
+ printf("%s\n", devpath);
+
+ if (dry_run)
+ return;
+
+ fd = open(filename, O_WRONLY);
+ if (fd < 0) {
+ dbg("error on opening %s: %s\n", filename, strerror(errno));
+ return;
+ }
+
+ if (write(fd, "add", 3) < 0)
+ info("error on triggering %s: %s\n", filename, strerror(errno));
+
+ close(fd);
+}
+
+static int sysfs_resolve_link(char *devpath, size_t size)
+{
+ char link_path[PATH_SIZE];
+ char link_target[PATH_SIZE];
+ int len;
+ int i;
+ int back;
+
+ strlcpy(link_path, "/sys", sizeof(link_path));
+ strlcat(link_path, devpath, sizeof(link_path));
+ len = readlink(link_path, link_target, sizeof(link_target));
+ if (len <= 0)
+ return -1;
+ link_target[len] = '\0';
+ dbg("path link '%s' points to '%s'", devpath, link_target);
+
+ for (back = 0; strncmp(&link_target[back * 3], "../", 3) == 0; back++)
+ ;
+ dbg("base '%s', tail '%s', back %i", devpath, &link_target[back * 3], back);
+ for (i = 0; i <= back; i++) {
+ char *pos = strrchr(devpath, '/');
+
+ if (pos == NULL)
+ return -1;
+ pos[0] = '\0';
+ }
+ dbg("after moving back '%s'", devpath);
+ strlcat(devpath, "/", size);
+ strlcat(devpath, &link_target[back * 3], size);
+ return 0;
+}
+
+
+static int device_list_insert(const char *path)
+{
+ char filename[PATH_SIZE];
+ char devpath[PATH_SIZE];
+ struct stat statbuf;
+
+ dbg("add '%s'" , path);
+
+ /* we only have a device, if we have an uevent file */
+ strlcpy(filename, path, sizeof(filename));
+ strlcat(filename, "/uevent", sizeof(filename));
+ if (stat(filename, &statbuf) < 0)
+ return -1;
+ if (!(statbuf.st_mode & S_IWUSR))
+ return -1;
+
+ strlcpy(devpath, &path[4], sizeof(devpath));
+
+ /* resolve possible link to real target */
+ if (lstat(path, &statbuf) < 0)
+ return -1;
+ if (S_ISLNK(statbuf.st_mode))
+ if (sysfs_resolve_link(devpath, sizeof(devpath)) != 0)
+ return -1;
+
+ trigger_uevent(devpath);
+ return 0;
+}
+
+
+static void scan_subsystem(const char *subsys)
+{
+ char base[PATH_SIZE];
+ DIR *dir;
+ struct dirent *dent;
+
+ strlcpy(base, "/sys/", sizeof(base));
+ strlcat(base, subsys, sizeof(base));
+
+ dir = opendir(base);
+ if (dir != NULL) {
+ for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
+ char dirname[PATH_SIZE];
+ DIR *dir2;
+ struct dirent *dent2;
+
+ if (dent->d_name[0] == '.')
+ continue;
+
+ strlcpy(dirname, base, sizeof(dirname));
+ strlcat(dirname, "/", sizeof(dirname));
+ strlcat(dirname, dent->d_name, sizeof(dirname));
+ strlcat(dirname, "/devices", sizeof(dirname));
+
+ /* look for devices */
+ dir2 = opendir(dirname);
+ if (dir2 != NULL) {
+ for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
+ char dirname2[PATH_SIZE];
+
+ if (dent2->d_name[0] == '.')
+ continue;
+
+ strlcpy(dirname2, dirname, sizeof(dirname2));
+ strlcat(dirname2, "/", sizeof(dirname2));
+ strlcat(dirname2, dent2->d_name, sizeof(dirname2));
+ device_list_insert(dirname2);
+ }
+ closedir(dir2);
+ }
+ }
+ closedir(dir);
+ }
+}
+
+static void scan_block(void)
+{
+ char base[PATH_SIZE];
+ DIR *dir;
+ struct dirent *dent;
+
+ strlcpy(base, "/sys/block", sizeof(base));
+
+ dir = opendir(base);
+ if (dir != NULL) {
+ for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
+ char dirname[PATH_SIZE];
+ DIR *dir2;
+ struct dirent *dent2;
+
+ if (dent->d_name[0] == '.')
+ continue;
+
+ strlcpy(dirname, base, sizeof(dirname));
+ strlcat(dirname, "/", sizeof(dirname));
+ strlcat(dirname, dent->d_name, sizeof(dirname));
+ if (device_list_insert(dirname) != 0)
+ continue;
+
+ /* look for partitions */
+ dir2 = opendir(dirname);
+ if (dir2 != NULL) {
+ for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
+ char dirname2[PATH_SIZE];
+
+ if (dent2->d_name[0] == '.')
+ continue;
+
+ if (!strcmp(dent2->d_name,"device"))
+ continue;
+
+ strlcpy(dirname2, dirname, sizeof(dirname2));
+ strlcat(dirname2, "/", sizeof(dirname2));
+ strlcat(dirname2, dent2->d_name, sizeof(dirname2));
+ device_list_insert(dirname2);
+ }
+ closedir(dir2);
+ }
+ }
+ closedir(dir);
+ }
+}
+
+static void scan_class(void)
+{
+ char base[PATH_SIZE];
+ DIR *dir;
+ struct dirent *dent;
+
+ strlcpy(base, "/sys/class", sizeof(base));
+
+ dir = opendir(base);
+ if (dir != NULL) {
+ for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
+ char dirname[PATH_SIZE];
+ DIR *dir2;
+ struct dirent *dent2;
+
+ if (dent->d_name[0] == '.')
+ continue;
+
+ strlcpy(dirname, base, sizeof(dirname));
+ strlcat(dirname, "/", sizeof(dirname));
+ strlcat(dirname, dent->d_name, sizeof(dirname));
+ dir2 = opendir(dirname);
+ if (dir2 != NULL) {
+ for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
+ char dirname2[PATH_SIZE];
+
+ if (dent2->d_name[0] == '.')
+ continue;
+
+ if (!strcmp(dent2->d_name, "device"))
+ continue;
+
+ strlcpy(dirname2, dirname, sizeof(dirname2));
+ strlcat(dirname2, "/", sizeof(dirname2));
+ strlcat(dirname2, dent2->d_name, sizeof(dirname2));
+ device_list_insert(dirname2);
+ }
+ closedir(dir2);
+ }
+ }
+ closedir(dir);
+ }
+}
+
+int main(int argc, char *argv[], char *envp[])
+{
+ char base[PATH_SIZE];
+ struct stat statbuf;
+ int failed = 0;
+ int option;
+
+ openlog("udevtrigger", LOG_PID | LOG_CONS, LOG_DAEMON);
+
+ while (1) {
+ option = getopt(argc, argv, "vnh");
+ if (option == -1)
+ break;
+
+ switch (option) {
+ case 'v':
+ verbose = 1;
+ break;
+ case 'n':
+ dry_run = 1;
+ break;
+ case 'h':
+ printf("Usage: udevtrigger OPTIONS\n"
+ " -v print the list of devices while running\n"
+ " -n do not actually trigger the events\n"
+ " -h print this text\n"
+ "\n");
+ goto exit;
+ default:
+ goto exit;
+ }
+ }
+
+
+ /* if we have /sys/subsystem, forget all the old stuff */
+ scan_subsystem("bus");
+ scan_class();
+
+ /* scan "block" if it isn't a "class" */
+ strlcpy(base, "/sys/class/block", sizeof(base));
+ if (stat(base, &statbuf) != 0)
+ scan_block();
+
+exit:
+
+ closelog();
+ return 0;
+}
diff --git a/package/i2c-gpio-custom/Makefile b/package/i2c-gpio-custom/Makefile
new file mode 100644
index 000000000..8585a5ab5
--- /dev/null
+++ b/package/i2c-gpio-custom/Makefile
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2008 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=i2c-gpio-custom
+PKG_RELEASE:=2
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/i2c-gpio-custom
+ SUBMENU:=I2C support
+ TITLE:=Custom GPIO-based I2C device
+ DEPENDS:=@GPIO_SUPPORT +kmod-i2c-core +kmod-i2c-gpio
+ FILES:=$(PKG_BUILD_DIR)/i2c-gpio-custom.ko
+ KCONFIG:=
+endef
+
+define KernelPackage/i2c-gpio-custom/description
+ Kernel module for register a custom i2c-gpio platform device.
+endef
+
+EXTRA_KCONFIG:= \
+ CONFIG_I2C_GPIO_CUSTOM=m
+
+EXTRA_CFLAGS:= \
+ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \
+ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \
+
+MAKE_OPTS:= \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ SUBDIRS="$(PKG_BUILD_DIR)" \
+ EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
+ $(EXTRA_KCONFIG)
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ $(MAKE) -C "$(LINUX_DIR)" \
+ $(MAKE_OPTS) \
+ modules
+endef
+
+$(eval $(call KernelPackage,i2c-gpio-custom))
diff --git a/package/i2c-gpio-custom/src/Kconfig b/package/i2c-gpio-custom/src/Kconfig
new file mode 100644
index 000000000..e2e3a68d9
--- /dev/null
+++ b/package/i2c-gpio-custom/src/Kconfig
@@ -0,0 +1,10 @@
+config I2C_GPIO_CUSTOM
+ tristate "Custom GPIO-based I2C driver"
+ depends on GENERIC_GPIO
+ select I2C_GPIO
+ help
+ This is an I2C driver to register 1 to 4 custom I2C buses using
+ GPIO lines.
+
+ This support is also available as a module. If so, the module
+ will be called i2c-gpio-custom.
diff --git a/package/i2c-gpio-custom/src/Makefile b/package/i2c-gpio-custom/src/Makefile
new file mode 100644
index 000000000..dcb2e2abe
--- /dev/null
+++ b/package/i2c-gpio-custom/src/Makefile
@@ -0,0 +1 @@
+obj-${CONFIG_I2C_GPIO_CUSTOM} += i2c-gpio-custom.o \ No newline at end of file
diff --git a/package/i2c-gpio-custom/src/i2c-gpio-custom.c b/package/i2c-gpio-custom/src/i2c-gpio-custom.c
new file mode 100644
index 000000000..76ab5f39c
--- /dev/null
+++ b/package/i2c-gpio-custom/src/i2c-gpio-custom.c
@@ -0,0 +1,198 @@
+/*
+ * Custom GPIO-based I2C driver
+ *
+ * Copyright (C) 2007-2008 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * 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.
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * The behaviour of this driver can be altered by setting some parameters
+ * from the insmod command line.
+ *
+ * The following parameters are adjustable:
+ *
+ * bus0 These four arguments can be arrays of
+ * bus1 1-8 unsigned integers as follows:
+ * bus2
+ * bus3 <id>,<sda>,<scl>,<udelay>,<timeout>,<sda_od>,<scl_od>,<scl_oo>
+ *
+ * where:
+ *
+ * <id> ID to used as device_id for the corresponding bus (required)
+ * <sda> GPIO pin ID to used for SDA (required)
+ * <scl> GPIO pin ID to used for SCL (required)
+ * <udelay> signal toggle delay.
+ * <timeout> clock stretching timeout.
+ * <sda_od> SDA is configured as open drain.
+ * <scl_od> SCL is configured as open drain.
+ * <scl_oo> SCL output drivers cannot be turned off.
+ *
+ * See include/i2c-gpio.h for more information about the parameters.
+ *
+ * If this driver is built into the kernel, you can use the following kernel
+ * command line parameters, with the same values as the corresponding module
+ * parameters listed above:
+ *
+ * i2c-gpio-custom.bus0
+ * i2c-gpio-custom.bus1
+ * i2c-gpio-custom.bus2
+ * i2c-gpio-custom.bus3
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <linux/i2c-gpio.h>
+
+#define DRV_NAME "i2c-gpio-custom"
+#define DRV_DESC "Custom GPIO-based I2C driver"
+#define DRV_VERSION "0.1.1"
+
+#define PFX DRV_NAME ": "
+
+#define BUS_PARAM_ID 0
+#define BUS_PARAM_SDA 1
+#define BUS_PARAM_SCL 2
+#define BUS_PARAM_UDELAY 3
+#define BUS_PARAM_TIMEOUT 4
+#define BUS_PARAM_SDA_OD 5
+#define BUS_PARAM_SCL_OD 6
+#define BUS_PARAM_SCL_OO 7
+
+#define BUS_PARAM_REQUIRED 3
+#define BUS_PARAM_COUNT 8
+#define BUS_COUNT_MAX 4
+
+static unsigned int bus0[BUS_PARAM_COUNT] __initdata;
+static unsigned int bus1[BUS_PARAM_COUNT] __initdata;
+static unsigned int bus2[BUS_PARAM_COUNT] __initdata;
+static unsigned int bus3[BUS_PARAM_COUNT] __initdata;
+
+static unsigned int bus_nump[BUS_COUNT_MAX] __initdata;
+
+#define BUS_PARM_DESC \
+ " config -> id,sda,scl[,udelay,timeout,sda_od,scl_od,scl_oo]"
+
+module_param_array(bus0, uint, &bus_nump[0], 0);
+MODULE_PARM_DESC(bus0, "bus0" BUS_PARM_DESC);
+module_param_array(bus1, uint, &bus_nump[1], 0);
+MODULE_PARM_DESC(bus1, "bus1" BUS_PARM_DESC);
+module_param_array(bus2, uint, &bus_nump[2], 0);
+MODULE_PARM_DESC(bus2, "bus2" BUS_PARM_DESC);
+module_param_array(bus3, uint, &bus_nump[3], 0);
+MODULE_PARM_DESC(bus3, "bus3" BUS_PARM_DESC);
+
+static struct platform_device *devices[BUS_COUNT_MAX];
+static unsigned int nr_devices;
+
+static void i2c_gpio_custom_cleanup(void)
+{
+ int i;
+
+ for (i = 0; i < nr_devices; i++)
+ if (devices[i])
+ platform_device_put(devices[i]);
+}
+
+static int __init i2c_gpio_custom_add_one(unsigned int id, unsigned int *params)
+{
+ struct platform_device *pdev;
+ struct i2c_gpio_platform_data pdata;
+ int err;
+
+ if (!bus_nump[id])
+ return 0;
+
+ if (bus_nump[id] < BUS_PARAM_REQUIRED) {
+ printk(KERN_ERR PFX "not enough parameters for bus%d\n", id);
+ err = -EINVAL;
+ goto err;
+ }
+
+ pdev = platform_device_alloc("i2c-gpio", params[BUS_PARAM_ID]);
+ if (!pdev) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ pdata.sda_pin = params[BUS_PARAM_SDA];
+ pdata.scl_pin = params[BUS_PARAM_SCL];
+ pdata.udelay = params[BUS_PARAM_UDELAY];
+ pdata.timeout = params[BUS_PARAM_TIMEOUT];
+ pdata.sda_is_open_drain = params[BUS_PARAM_SDA_OD] != 0;
+ pdata.scl_is_open_drain = params[BUS_PARAM_SCL_OD] != 0;
+ pdata.scl_is_output_only = params[BUS_PARAM_SCL_OO] != 0;
+
+ err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
+ if (err)
+ goto err_put;
+
+ err = platform_device_add(pdev);
+ if (err)
+ goto err_put;
+
+ devices[nr_devices++] = pdev;
+ return 0;
+
+err_put:
+ platform_device_put(pdev);
+err:
+ return err;
+}
+
+static int __init i2c_gpio_custom_probe(void)
+{
+ int err;
+
+ printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n");
+
+ err = i2c_gpio_custom_add_one(0, bus0);
+ if (err) goto err;
+
+ err = i2c_gpio_custom_add_one(1, bus1);
+ if (err) goto err;
+
+ err = i2c_gpio_custom_add_one(2, bus2);
+ if (err) goto err;
+
+ err = i2c_gpio_custom_add_one(3, bus3);
+ if (err) goto err;
+
+ if (!nr_devices) {
+ printk(KERN_ERR PFX "no bus parameter(s) specified\n");
+ err = -ENODEV;
+ goto err;
+ }
+
+ return 0;
+
+err:
+ i2c_gpio_custom_cleanup();
+ return err;
+}
+
+#ifdef MODULE
+static int __init i2c_gpio_custom_init(void)
+{
+ return i2c_gpio_custom_probe();
+}
+module_init(i2c_gpio_custom_init);
+
+static void __exit i2c_gpio_custom_exit(void)
+{
+ i2c_gpio_custom_cleanup();
+}
+module_exit(i2c_gpio_custom_exit);
+#else
+subsys_initcall(i2c_gpio_custom_probe);
+#endif /* MODULE*/
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org >");
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_VERSION(DRV_VERSION);
diff --git a/package/ifenslave/Makefile b/package/ifenslave/Makefile
new file mode 100644
index 000000000..5292e451c
--- /dev/null
+++ b/package/ifenslave/Makefile
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=ifenslave
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ifenslave
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS:=+kmod-bonding
+ TITLE:=A utility to manipulate kernel ethernet bonding devices
+ VERSION:=$(LINUX_VERSION)-$(PKG_RELEASE)
+ URL:=http://www.kernel.org
+endef
+
+define Package/ifenslave/description
+ ifenslave is needed to add/remove interfaces to/from ethernet bond devices.
+endef
+
+define Build/Prepare
+endef
+
+define Build/Compile
+ $(TARGET_CC) $(TARGET_CFLAGS) -o $(PKG_BUILD_DIR)/ifenslave \
+ $(LINUX_DIR)/Documentation/networking/ifenslave.c
+endef
+
+define Package/ifenslave/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/ifenslave $(1)/sbin/
+endef
+
+$(eval $(call BuildPackage,ifenslave))
diff --git a/package/iproute2/Makefile b/package/iproute2/Makefile
new file mode 100644
index 000000000..8e89617e1
--- /dev/null
+++ b/package/iproute2/Makefile
@@ -0,0 +1,115 @@
+#
+# Copyright (C) 2006-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=iproute2
+PKG_VERSION:=3.3.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://kernel.org/pub/linux/utils/net/iproute2/
+PKG_MD5SUM:=308e7145218dd552c2766fe527e239e1
+PKG_BUILD_PARALLEL:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/iproute2-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/iproute2/Default
+ SECTION:=net
+ CATEGORY:=Network
+ URL:=http://linux-net.osdl.org/index.php/Iproute2
+endef
+
+define Package/ip
+$(call Package/iproute2/Default)
+ SUBMENU:=Routing and Redirection
+ DEPENDS:= +libnl-tiny
+ TITLE:=Routing control utility
+endef
+
+define Package/ip/conffiles
+/etc/iproute2/rt_tables
+endef
+
+define Package/tc
+$(call Package/iproute2/Default)
+ TITLE:=Traffic control utility
+ DEPENDS:=+kmod-sched-core
+endef
+
+define Package/genl
+$(call Package/iproute2/Default)
+ TITLE:=General netlink utility frontend
+endef
+
+define Package/ss
+$(call Package/iproute2/Default)
+ TITLE:=Socket statistics utility
+endef
+
+define Build/Configure
+ $(SED) "s,-I/usr/include/db3,," $(PKG_BUILD_DIR)/Makefile
+ $(SED) "s,^KERNEL_INCLUDE.*,KERNEL_INCLUDE=$(LINUX_DIR)/include," \
+ $(PKG_BUILD_DIR)/Makefile
+ $(SED) "s,^LIBC_INCLUDE.*,LIBC_INCLUDE=$(STAGING_DIR)/include," \
+ $(PKG_BUILD_DIR)/Makefile
+ echo "static const char SNAPSHOT[] = \"$(PKG_VERSION)-$(PKG_RELEASE)-openwrt\";" \
+ > $(PKG_BUILD_DIR)/include/SNAPSHOT.h
+endef
+
+ifdef CONFIG_USE_EGLIBC
+ ifndef CONFIG_EGLIBC_VERSION_2_13
+ TARGET_CFLAGS += -DHAVE_SETNS
+ endif
+endif
+
+MAKE_FLAGS += \
+ EXTRA_CCOPTS="$(TARGET_CFLAGS) -I../include -I$(STAGING_DIR)/usr/include/libnl-tiny" \
+ KERNEL_INCLUDE="$(LINUX_DIR)/include" \
+ FPIC="$(FPIC)"
+
+define Build/Compile
+ +$(MAKE_VARS) $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) $(MAKE_FLAGS)
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_BUILD_DIR)/include/libnetlink.h $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/lib/libnetlink.a $(1)/usr/lib/
+endef
+
+define Package/ip/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_DIR) $(1)/etc/iproute2
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/etc/iproute2/rt_tables $(1)/etc/iproute2
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/ip/ip $(1)/usr/sbin/
+endef
+
+define Package/tc/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/tc/tc $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/etc/hotplug.d/iface
+ $(INSTALL_BIN) ./files/30-teql $(1)/etc/hotplug.d/iface/
+endef
+
+define Package/genl/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/genl/genl $(1)/usr/sbin/
+endef
+
+define Package/ss/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc/ss $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,ip))
+$(eval $(call BuildPackage,tc))
+$(eval $(call BuildPackage,genl))
+$(eval $(call BuildPackage,ss))
diff --git a/package/iproute2/files/30-teql b/package/iproute2/files/30-teql
new file mode 100644
index 000000000..a0c0e503a
--- /dev/null
+++ b/package/iproute2/files/30-teql
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+. /lib/functions.sh
+
+if [ "$ACTION" != "ifup" ]; then
+ exit
+fi
+
+config_load network
+
+config_get teql $INTERFACE teql
+
+if [ "$teql" != "" ]; then
+ logger Adding device $DEVICE to TEQL master $teql
+ insmod sch_teql
+ tc qdisc add dev $DEVICE root $teql
+
+ # The kernel doesn't let us bring it up until it has at least one
+ # slave. So bring it up now, if it isn't already.
+ if ! cat /sys/class/net/$teql/carrier &>/dev/null; then
+ ifup $teql &
+ fi
+fi
diff --git a/package/iproute2/patches/000-sync_pkt_sched_h.patch b/package/iproute2/patches/000-sync_pkt_sched_h.patch
new file mode 100644
index 000000000..d3315a065
--- /dev/null
+++ b/package/iproute2/patches/000-sync_pkt_sched_h.patch
@@ -0,0 +1,121 @@
+--- a/include/linux/pkt_sched.h
++++ b/include/linux/pkt_sched.h
+@@ -193,6 +193,33 @@ struct tc_sfq_xstats {
+ __s32 allot;
+ };
+
++/* ESFQ section */
++
++enum
++{
++ /* traditional */
++ TCA_SFQ_HASH_CLASSIC,
++ TCA_SFQ_HASH_DST,
++ TCA_SFQ_HASH_SRC,
++ TCA_SFQ_HASH_FWMARK,
++ /* conntrack */
++ TCA_SFQ_HASH_CTORIGDST,
++ TCA_SFQ_HASH_CTORIGSRC,
++ TCA_SFQ_HASH_CTREPLDST,
++ TCA_SFQ_HASH_CTREPLSRC,
++ TCA_SFQ_HASH_CTNATCHG,
++};
++
++struct tc_esfq_qopt
++{
++ unsigned quantum; /* Bytes per round allocated to flow */
++ int perturb_period; /* Period of hash perturbation */
++ __u32 limit; /* Maximal packets in queue */
++ unsigned divisor; /* Hash divisor */
++ unsigned flows; /* Maximal number of flows */
++ unsigned hash_kind; /* Hash function to use for flow identification */
++};
++
+ /* RED section */
+
+ enum {
+@@ -633,4 +660,84 @@ struct tc_qfq_stats {
+ __u32 lmax;
+ };
+
++/* CODEL */
++
++enum {
++ TCA_CODEL_UNSPEC,
++ TCA_CODEL_TARGET,
++ TCA_CODEL_LIMIT,
++ TCA_CODEL_INTERVAL,
++ TCA_CODEL_ECN,
++ __TCA_CODEL_MAX
++};
++
++#define TCA_CODEL_MAX (__TCA_CODEL_MAX - 1)
++
++struct tc_codel_xstats {
++ __u32 maxpacket; /* largest packet we've seen so far */
++ __u32 count; /* how many drops we've done since the last time we
++ * entered dropping state
++ */
++ __u32 lastcount; /* count at entry to dropping state */
++ __u32 ldelay; /* in-queue delay seen by most recently dequeued packet */
++ __s32 drop_next; /* time to drop next packet */
++ __u32 drop_overlimit; /* number of time max qdisc packet limit was hit */
++ __u32 ecn_mark; /* number of packets we ECN marked instead of dropped */
++ __u32 dropping; /* are we in dropping state ? */
++};
++
++/* FQ_CODEL */
++
++enum {
++ TCA_FQ_CODEL_UNSPEC,
++ TCA_FQ_CODEL_TARGET,
++ TCA_FQ_CODEL_LIMIT,
++ TCA_FQ_CODEL_INTERVAL,
++ TCA_FQ_CODEL_ECN,
++ TCA_FQ_CODEL_FLOWS,
++ TCA_FQ_CODEL_QUANTUM,
++ __TCA_FQ_CODEL_MAX
++};
++
++#define TCA_FQ_CODEL_MAX (__TCA_FQ_CODEL_MAX - 1)
++
++enum {
++ TCA_FQ_CODEL_XSTATS_QDISC,
++ TCA_FQ_CODEL_XSTATS_CLASS,
++};
++
++struct tc_fq_codel_qd_stats {
++ __u32 maxpacket; /* largest packet we've seen so far */
++ __u32 drop_overlimit; /* number of time max qdisc
++ * packet limit was hit
++ */
++ __u32 ecn_mark; /* number of packets we ECN marked
++ * instead of being dropped
++ */
++ __u32 new_flow_count; /* number of time packets
++ * created a 'new flow'
++ */
++ __u32 new_flows_len; /* count of flows in new list */
++ __u32 old_flows_len; /* count of flows in old list */
++};
++
++struct tc_fq_codel_cl_stats {
++ __s32 deficit;
++ __u32 ldelay; /* in-queue delay seen by most recently
++ * dequeued packet
++ */
++ __u32 count;
++ __u32 lastcount;
++ __u32 dropping;
++ __s32 drop_next;
++};
++
++struct tc_fq_codel_xstats {
++ __u32 type;
++ union {
++ struct tc_fq_codel_qd_stats qdisc_stats;
++ struct tc_fq_codel_cl_stats class_stats;
++ };
++};
++
+ #endif
diff --git a/package/iproute2/patches/001-iproute2-2.6.11_Config.patch b/package/iproute2/patches/001-iproute2-2.6.11_Config.patch
new file mode 100644
index 000000000..ece865299
--- /dev/null
+++ b/package/iproute2/patches/001-iproute2-2.6.11_Config.patch
@@ -0,0 +1,7 @@
+--- /dev/null
++++ b/Config
+@@ -0,0 +1,4 @@
++# Fixed config to disable ATM support even if present on host system
++TC_CONFIG_ATM:=n
++TC_CONFIG_ACTION_GACT=y
++TC_CONFIG_ACTION_PROB=y
diff --git a/package/iproute2/patches/002-iproute2-ipxfrm_no_sctp.patch b/package/iproute2/patches/002-iproute2-ipxfrm_no_sctp.patch
new file mode 100644
index 000000000..3b1f4d647
--- /dev/null
+++ b/package/iproute2/patches/002-iproute2-ipxfrm_no_sctp.patch
@@ -0,0 +1,22 @@
+---
+ ip/ipxfrm.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/ip/ipxfrm.c
++++ b/ip/ipxfrm.c
+@@ -468,7 +468,6 @@ void xfrm_selector_print(struct xfrm_sel
+ switch (sel->proto) {
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+- case IPPROTO_SCTP:
+ case IPPROTO_DCCP:
+ default: /* XXX */
+ if (sel->sport_mask)
+@@ -1263,7 +1262,6 @@ static int xfrm_selector_upspec_parse(st
+ switch (sel->proto) {
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+- case IPPROTO_SCTP:
+ case IPPROTO_DCCP:
+ break;
+ default:
diff --git a/package/iproute2/patches/004-darwin_fixes.patch b/package/iproute2/patches/004-darwin_fixes.patch
new file mode 100644
index 000000000..e1a5e9756
--- /dev/null
+++ b/package/iproute2/patches/004-darwin_fixes.patch
@@ -0,0 +1,59 @@
+--- a/netem/maketable.c
++++ b/netem/maketable.c
+@@ -10,7 +10,9 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <math.h>
++#if !defined(__APPLE__) && !defined(__FreeBSD__)
+ #include <malloc.h>
++#endif
+ #include <string.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+--- a/netem/normal.c
++++ b/netem/normal.c
+@@ -8,8 +8,12 @@
+ #include <string.h>
+ #include <limits.h>
+
++#if !defined(__APPLE__) && !defined(__FreeBSD__)
+ #include <linux/types.h>
+ #include <linux/pkt_sched.h>
++#else
++#define NETEM_DIST_SCALE 8192
++#endif
+
+ #define TABLESIZE 16384
+ #define TABLEFACTOR NETEM_DIST_SCALE
+--- a/netem/pareto.c
++++ b/netem/pareto.c
+@@ -7,8 +7,12 @@
+ #include <math.h>
+ #include <limits.h>
+
++#if !defined(__APPLE__) && !defined(__FreeBSD__)
+ #include <linux/types.h>
+ #include <linux/pkt_sched.h>
++#else
++#define NETEM_DIST_SCALE 8192
++#endif
+
+ static const double a=3.0;
+ #define TABLESIZE 16384
+--- a/netem/paretonormal.c
++++ b/netem/paretonormal.c
+@@ -15,10 +15,13 @@
+ #include <string.h>
+ #include <math.h>
+ #include <limits.h>
++#if !defined(__APPLE__) && !defined(__FreeBSD__)
+ #include <malloc.h>
+-
+ #include <linux/types.h>
+ #include <linux/pkt_sched.h>
++#else
++#define NETEM_DIST_SCALE 8192
++#endif
+
+ #define TABLESIZE 16384
+ #define TABLEFACTOR NETEM_DIST_SCALE
diff --git a/package/iproute2/patches/006-iproute2-tc_esfq.patch b/package/iproute2/patches/006-iproute2-tc_esfq.patch
new file mode 100644
index 000000000..8016dbb96
--- /dev/null
+++ b/package/iproute2/patches/006-iproute2-tc_esfq.patch
@@ -0,0 +1,219 @@
+---
+ include/linux/pkt_sched.h | 59 +++++++++++++
+ tc/Makefile | 1
+ tc/q_esfq.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 260 insertions(+)
+
+--- a/tc/Makefile
++++ b/tc/Makefile
+@@ -8,6 +8,7 @@ SHARED_LIBS ?= y
+ TCMODULES :=
+ TCMODULES += q_fifo.o
+ TCMODULES += q_sfq.o
++TCMODULES += q_esfq.o
+ TCMODULES += q_red.o
+ TCMODULES += q_prio.o
+ TCMODULES += q_tbf.o
+--- /dev/null
++++ b/tc/q_esfq.c
+@@ -0,0 +1,200 @@
++/*
++ * q_esfq.c ESFQ.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
++ *
++ * Changes: Alexander Atanasov, <alex@ssi.bg>
++ * Alexander Clouter, <alex@digriz.org.uk>
++ * Corey Hickey, <bugfood-c@fatooh.org>
++ *
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <syslog.h>
++#include <fcntl.h>
++#include <math.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
++#include <string.h>
++
++#include "utils.h"
++#include "tc_util.h"
++
++static void explain(void)
++{
++ fprintf(stderr, "Usage: ... esfq [ perturb SECS ] [ quantum BYTES ] [ depth FLOWS ]\n\t[ divisor HASHBITS ] [ limit PKTS ] [ hash HASHTYPE]\n");
++ fprintf(stderr,"Where: \n");
++ fprintf(stderr,"HASHTYPE := { classic | src | dst | ctorigdst | ctorigsrc | ctrepldst | ctreplsrc | ctnatchg }\n");
++}
++
++#define usage() return(-1)
++
++static int esfq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
++{
++ int ok=0;
++ struct tc_esfq_qopt opt;
++
++ memset(&opt, 0, sizeof(opt));
++
++ opt.hash_kind= TCA_SFQ_HASH_CLASSIC;
++
++ while (argc > 0) {
++ if (strcmp(*argv, "quantum") == 0) {
++ NEXT_ARG();
++ if (get_size(&opt.quantum, *argv)) {
++ fprintf(stderr, "Illegal \"quantum\"\n");
++ return -1;
++ }
++ ok++;
++ } else if (strcmp(*argv, "perturb") == 0) {
++ NEXT_ARG();
++ if (get_integer(&opt.perturb_period, *argv, 0)) {
++ fprintf(stderr, "Illegal \"perturb\"\n");
++ return -1;
++ }
++ ok++;
++ } else if (strcmp(*argv, "depth") == 0) {
++ NEXT_ARG();
++ if (get_integer((int *) &opt.flows, *argv, 0)) {
++ fprintf(stderr, "Illegal \"depth\"\n");
++ return -1;
++ }
++ ok++;
++ } else if (strcmp(*argv, "divisor") == 0) {
++ NEXT_ARG();
++ if (get_integer((int *) &opt.divisor, *argv, 0)) {
++ fprintf(stderr, "Illegal \"divisor\"\n");
++ return -1;
++ }
++ if(opt.divisor >= 14) {
++ fprintf(stderr, "Illegal \"divisor\": must be < 14\n");
++ return -1;
++ }
++ opt.divisor=pow(2,opt.divisor);
++ ok++;
++ } else if (strcmp(*argv, "limit") == 0) {
++ NEXT_ARG();
++ if (get_integer((int *) &opt.limit, *argv, 0)) {
++ fprintf(stderr, "Illegal \"limit\"\n");
++ return -1;
++ }
++ ok++;
++ } else if (strcmp(*argv, "hash") == 0) {
++ NEXT_ARG();
++ if(strcmp(*argv, "classic") == 0) {
++ opt.hash_kind= TCA_SFQ_HASH_CLASSIC;
++ } else
++ if(strcmp(*argv, "dst") == 0) {
++ opt.hash_kind= TCA_SFQ_HASH_DST;
++ } else
++ if(strcmp(*argv, "src") == 0) {
++ opt.hash_kind= TCA_SFQ_HASH_SRC;
++ } else
++ if(strcmp(*argv, "ctorigsrc") == 0) {
++ opt.hash_kind= TCA_SFQ_HASH_CTORIGSRC;
++ } else
++ if(strcmp(*argv, "ctorigdst") == 0) {
++ opt.hash_kind= TCA_SFQ_HASH_CTORIGDST;
++ } else
++ if(strcmp(*argv, "ctreplsrc") == 0) {
++ opt.hash_kind= TCA_SFQ_HASH_CTREPLSRC;
++ } else
++ if(strcmp(*argv, "ctrepldst") == 0) {
++ opt.hash_kind= TCA_SFQ_HASH_CTREPLDST;
++ } else
++ if(strcmp(*argv, "ctnatchg") == 0) {
++ opt.hash_kind= TCA_SFQ_HASH_CTNATCHG;
++ } else {
++ fprintf(stderr, "Illegal \"hash\"\n");
++ explain();
++ return -1;
++ }
++ ok++;
++ } else if (strcmp(*argv, "help") == 0) {
++ explain();
++ return -1;
++ } else {
++ fprintf(stderr, "What is \"%s\"?\n", *argv);
++ explain();
++ return -1;
++ }
++ argc--; argv++;
++ }
++
++ if (ok)
++ addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt));
++ return 0;
++}
++
++static int esfq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
++{
++ struct tc_esfq_qopt *qopt;
++ SPRINT_BUF(b1);
++
++ if (opt == NULL)
++ return 0;
++
++ if (RTA_PAYLOAD(opt) < sizeof(*qopt))
++ return -1;
++ qopt = RTA_DATA(opt);
++ fprintf(f, "quantum %s ", sprint_size(qopt->quantum, b1));
++ if (show_details) {
++ fprintf(f, "limit %up flows %u/%u ",
++ qopt->limit, qopt->flows, qopt->divisor);
++ }
++ if (qopt->perturb_period)
++ fprintf(f, "perturb %dsec ", qopt->perturb_period);
++
++ fprintf(f,"hash: ");
++ switch(qopt->hash_kind)
++ {
++ case TCA_SFQ_HASH_CLASSIC:
++ fprintf(f,"classic");
++ break;
++ case TCA_SFQ_HASH_DST:
++ fprintf(f,"dst");
++ break;
++ case TCA_SFQ_HASH_SRC:
++ fprintf(f,"src");
++ break;
++ case TCA_SFQ_HASH_CTORIGSRC:
++ fprintf(f,"ctorigsrc");
++ break;
++ case TCA_SFQ_HASH_CTORIGDST:
++ fprintf(f,"ctorigdst");
++ break;
++ case TCA_SFQ_HASH_CTREPLSRC:
++ fprintf(f,"ctreplsrc");
++ break;
++ case TCA_SFQ_HASH_CTREPLDST:
++ fprintf(f,"ctrepldst");
++ break;
++ case TCA_SFQ_HASH_CTNATCHG:
++ fprintf(f,"ctnatchg");
++ break;
++ default:
++ fprintf(f,"Unknown");
++ }
++ return 0;
++}
++
++static int esfq_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstats)
++{
++ return 0;
++}
++
++
++struct qdisc_util esfq_qdisc_util = {
++ .id = "esfq",
++ .parse_qopt = esfq_parse_opt,
++ .print_qopt = esfq_print_opt,
++ .print_xstats = esfq_print_xstats,
++};
diff --git a/package/iproute2/patches/007-no_arpd.patch b/package/iproute2/patches/007-no_arpd.patch
new file mode 100644
index 000000000..6a7e24ecd
--- /dev/null
+++ b/package/iproute2/patches/007-no_arpd.patch
@@ -0,0 +1,11 @@
+--- a/misc/Makefile
++++ b/misc/Makefile
+@@ -1,7 +1,7 @@
+ SSOBJ=ss.o ssfilter.o
+ LNSTATOBJ=lnstat.o lnstat_util.o
+
+-TARGETS=ss nstat ifstat rtacct arpd lnstat
++TARGETS=ss nstat ifstat rtacct lnstat
+
+ include ../Config
+
diff --git a/package/iproute2/patches/008-no_netem.patch b/package/iproute2/patches/008-no_netem.patch
new file mode 100644
index 000000000..c804b14fc
--- /dev/null
+++ b/package/iproute2/patches/008-no_netem.patch
@@ -0,0 +1,11 @@
+--- a/Makefile
++++ b/Makefile
+@@ -33,7 +33,7 @@ CCOPTS = -D_GNU_SOURCE -O2 -Wstrict-prot
+ CFLAGS = $(CCOPTS) -I../include $(DEFINES)
+ YACCFLAGS = -d -t -v
+
+-SUBDIRS=lib ip tc misc netem genl
++SUBDIRS=lib ip tc misc genl
+
+ LIBNETLINK=../lib/libnetlink.a ../lib/libutil.a
+ LDLIBS += $(LIBNETLINK)
diff --git a/package/iproute2/patches/100-allow_pfifo_fast.patch b/package/iproute2/patches/100-allow_pfifo_fast.patch
new file mode 100644
index 000000000..b31d4b745
--- /dev/null
+++ b/package/iproute2/patches/100-allow_pfifo_fast.patch
@@ -0,0 +1,13 @@
+---
+ tc/q_fifo.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/tc/q_fifo.c
++++ b/tc/q_fifo.c
+@@ -98,5 +98,6 @@ struct qdisc_util pfifo_head_drop_qdisc_
+ extern int prio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt);
+ struct qdisc_util pfifo_fast_qdisc_util = {
+ .id = "pfifo_fast",
++ .parse_qopt = fifo_parse_opt,
+ .print_qopt = prio_print_opt,
+ };
diff --git a/package/iproute2/patches/110-extra-ccopts.patch b/package/iproute2/patches/110-extra-ccopts.patch
new file mode 100644
index 000000000..0bf822f28
--- /dev/null
+++ b/package/iproute2/patches/110-extra-ccopts.patch
@@ -0,0 +1,11 @@
+--- a/Makefile
++++ b/Makefile
+@@ -29,7 +29,7 @@ ADDLIB+=ipx_ntop.o ipx_pton.o
+
+ CC = gcc
+ HOSTCC = gcc
+-CCOPTS = -D_GNU_SOURCE -O2 -Wstrict-prototypes -Wall
++CCOPTS = -D_GNU_SOURCE -O2 -Wstrict-prototypes -Wall $(EXTRA_CCOPTS)
+ CFLAGS = $(CCOPTS) -I../include $(DEFINES)
+ YACCFLAGS = -d -t -v
+
diff --git a/package/iproute2/patches/120-libnetlink-pic.patch b/package/iproute2/patches/120-libnetlink-pic.patch
new file mode 100644
index 000000000..c7b78d063
--- /dev/null
+++ b/package/iproute2/patches/120-libnetlink-pic.patch
@@ -0,0 +1,8 @@
+--- a/lib/Makefile
++++ b/lib/Makefile
+@@ -1,4 +1,4 @@
+-CFLAGS += -fPIC
++CFLAGS+=$(FPIC)
+
+ UTILOBJ=utils.o rt_names.o ll_types.o ll_proto.o ll_addr.o inet_proto.o
+
diff --git a/package/iproute2/patches/200-act_connmark.patch b/package/iproute2/patches/200-act_connmark.patch
new file mode 100644
index 000000000..4a48ac3f0
--- /dev/null
+++ b/package/iproute2/patches/200-act_connmark.patch
@@ -0,0 +1,84 @@
+--- a/tc/Makefile
++++ b/tc/Makefile
+@@ -38,6 +38,7 @@ TCMODULES += m_mirred.o
+ TCMODULES += m_nat.o
+ TCMODULES += m_pedit.o
+ TCMODULES += m_skbedit.o
++TCMODULES += m_connmark.o
+ TCMODULES += m_csum.o
+ TCMODULES += p_ip.o
+ TCMODULES += p_icmp.o
+--- /dev/null
++++ b/tc/m_connmark.c
+@@ -0,0 +1,71 @@
++/*
++ * m_connmark.c Connection tracking marking import
++ *
++ * Copyright (c) 2011 Felix Fietkau <nbd@openwrt.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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.
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <string.h>
++#include "utils.h"
++#include "tc_util.h"
++
++static void
++explain(void)
++{
++ fprintf(stderr, "Usage: ... connmark\n");
++}
++
++static void
++usage(void)
++{
++ explain();
++ exit(-1);
++}
++
++static int
++parse_connmark(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
++ struct nlmsghdr *n)
++{
++ int argc = *argc_p;
++ char **argv = *argv_p;
++
++ if (matches(*argv, "connmark") != 0)
++ return -1;
++
++ NEXT_ARG();
++
++ *argc_p = argc;
++ *argv_p = argv;
++ return 0;
++}
++
++static int print_connmark(struct action_util *au, FILE *f, struct rtattr *arg)
++{
++ if (arg == NULL)
++ return -1;
++
++ fprintf(f, " connmark");
++
++ return 0;
++}
++
++struct action_util connmark_action_util = {
++ .id = "connmark",
++ .parse_aopt = parse_connmark,
++ .print_aopt = print_connmark,
++};
diff --git a/package/iproute2/patches/210-add_codel.patch b/package/iproute2/patches/210-add_codel.patch
new file mode 100644
index 000000000..a14e276c8
--- /dev/null
+++ b/package/iproute2/patches/210-add_codel.patch
@@ -0,0 +1,437 @@
+--- a/tc/Makefile
++++ b/tc/Makefile
+@@ -49,6 +49,8 @@ TCMODULES += em_cmp.o
+ TCMODULES += em_u32.o
+ TCMODULES += em_meta.o
+ TCMODULES += q_mqprio.o
++TCMODULES += q_codel.o
++TCMODULES += q_fq_codel.o
+
+ TCSO :=
+ ifeq ($(TC_CONFIG_ATM),y)
+--- /dev/null
++++ b/tc/q_codel.c
+@@ -0,0 +1,188 @@
++/*
++ * Codel - The Controlled-Delay Active Queue Management algorithm
++ *
++ * Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com>
++ * Copyright (C) 2011-2012 Van Jacobson <van@pollere.com>
++ * Copyright (C) 2012 Michael D. Taht <dave.taht@bufferbloat.net>
++ * Copyright (C) 2012 Eric Dumazet <edumazet@google.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,
++ * without modification.
++ * 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 names of the authors may not be used to endorse or promote products
++ * derived from this software without specific prior written permission.
++ *
++ * Alternatively, provided that this notice is retained in full, this
++ * software may be distributed under the terms of the GNU General
++ * Public License ("GPL") version 2, in which case the provisions of the
++ * GPL apply INSTEAD OF those given above.
++ *
++ * 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 MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * OWNER 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.
++ *
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <syslog.h>
++#include <fcntl.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
++#include <string.h>
++
++#include "utils.h"
++#include "tc_util.h"
++
++static void explain(void)
++{
++ fprintf(stderr, "Usage: ... codel [ limit PACKETS ] [ target TIME]\n");
++ fprintf(stderr, " [ interval TIME ] [ ecn ]\n");
++}
++
++static int codel_parse_opt(struct qdisc_util *qu, int argc, char **argv,
++ struct nlmsghdr *n)
++{
++ unsigned limit = 0;
++ unsigned target = 0;
++ unsigned interval = 0;
++ int ecn = -1;
++ struct rtattr *tail;
++
++ while (argc > 0) {
++ if (strcmp(*argv, "limit") == 0) {
++ NEXT_ARG();
++ if (get_unsigned(&limit, *argv, 0)) {
++ fprintf(stderr, "Illegal \"limit\"\n");
++ return -1;
++ }
++ } else if (strcmp(*argv, "target") == 0) {
++ NEXT_ARG();
++ if (get_time(&target, *argv)) {
++ fprintf(stderr, "Illegal \"target\"\n");
++ return -1;
++ }
++ } else if (strcmp(*argv, "interval") == 0) {
++ NEXT_ARG();
++ if (get_time(&interval, *argv)) {
++ fprintf(stderr, "Illegal \"interval\"\n");
++ return -1;
++ }
++ } else if (strcmp(*argv, "ecn") == 0) {
++ ecn = 1;
++ } else if (strcmp(*argv, "noecn") == 0) {
++ ecn = 0;
++ } else if (strcmp(*argv, "help") == 0) {
++ explain();
++ return -1;
++ } else {
++ fprintf(stderr, "What is \"%s\"?\n", *argv);
++ explain();
++ return -1;
++ }
++ argc--; argv++;
++ }
++
++ tail = NLMSG_TAIL(n);
++ addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
++ if (limit)
++ addattr_l(n, 1024, TCA_CODEL_LIMIT, &limit, sizeof(limit));
++ if (interval)
++ addattr_l(n, 1024, TCA_CODEL_INTERVAL, &interval, sizeof(interval));
++ if (target)
++ addattr_l(n, 1024, TCA_CODEL_TARGET, &target, sizeof(target));
++ if (ecn != -1)
++ addattr_l(n, 1024, TCA_CODEL_ECN, &ecn, sizeof(ecn));
++ tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
++ return 0;
++}
++
++static int codel_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
++{
++ struct rtattr *tb[TCA_CODEL_MAX + 1];
++ unsigned limit;
++ unsigned interval;
++ unsigned target;
++ unsigned ecn;
++ SPRINT_BUF(b1);
++
++ if (opt == NULL)
++ return 0;
++
++ parse_rtattr_nested(tb, TCA_CODEL_MAX, opt);
++
++ if (tb[TCA_CODEL_LIMIT] &&
++ RTA_PAYLOAD(tb[TCA_CODEL_LIMIT]) >= sizeof(__u32)) {
++ limit = rta_getattr_u32(tb[TCA_CODEL_LIMIT]);
++ fprintf(f, "limit %up ", limit);
++ }
++ if (tb[TCA_CODEL_TARGET] &&
++ RTA_PAYLOAD(tb[TCA_CODEL_TARGET]) >= sizeof(__u32)) {
++ target = rta_getattr_u32(tb[TCA_CODEL_TARGET]);
++ fprintf(f, "target %s ", sprint_time(target, b1));
++ }
++ if (tb[TCA_CODEL_INTERVAL] &&
++ RTA_PAYLOAD(tb[TCA_CODEL_INTERVAL]) >= sizeof(__u32)) {
++ interval = rta_getattr_u32(tb[TCA_CODEL_INTERVAL]);
++ fprintf(f, "interval %s ", sprint_time(interval, b1));
++ }
++ if (tb[TCA_CODEL_ECN] &&
++ RTA_PAYLOAD(tb[TCA_CODEL_ECN]) >= sizeof(__u32)) {
++ ecn = rta_getattr_u32(tb[TCA_CODEL_ECN]);
++ if (ecn)
++ fprintf(f, "ecn ");
++ }
++
++ return 0;
++}
++
++static int codel_print_xstats(struct qdisc_util *qu, FILE *f,
++ struct rtattr *xstats)
++{
++ struct tc_codel_xstats *st;
++ SPRINT_BUF(b1);
++
++ if (xstats == NULL)
++ return 0;
++
++ if (RTA_PAYLOAD(xstats) < sizeof(*st))
++ return -1;
++
++ st = RTA_DATA(xstats);
++ fprintf(f, " count %u lastcount %u ldelay %s",
++ st->count, st->lastcount, sprint_time(st->ldelay, b1));
++ if (st->dropping)
++ fprintf(f, " dropping");
++ if (st->drop_next < 0)
++ fprintf(f, " drop_next -%s", sprint_time(-st->drop_next, b1));
++ else
++ fprintf(f, " drop_next %s", sprint_time(st->drop_next, b1));
++ fprintf(f, "\n maxpacket %u ecn_mark %u drop_overlimit %u",
++ st->maxpacket, st->ecn_mark, st->drop_overlimit);
++ return 0;
++
++}
++
++struct qdisc_util codel_qdisc_util = {
++ .id = "codel",
++ .parse_qopt = codel_parse_opt,
++ .print_qopt = codel_print_opt,
++ .print_xstats = codel_print_xstats,
++};
+--- /dev/null
++++ b/tc/q_fq_codel.c
+@@ -0,0 +1,232 @@
++/*
++ * Fair Queue Codel
++ *
++ * Copyright (C) 2012 Eric Dumazet <edumazet@google.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,
++ * without modification.
++ * 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 names of the authors may not be used to endorse or promote products
++ * derived from this software without specific prior written permission.
++ *
++ * Alternatively, provided that this notice is retained in full, this
++ * software may be distributed under the terms of the GNU General
++ * Public License ("GPL") version 2, in which case the provisions of the
++ * GPL apply INSTEAD OF those given above.
++ *
++ * 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 MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * OWNER 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.
++ *
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <syslog.h>
++#include <fcntl.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
++#include <string.h>
++
++#include "utils.h"
++#include "tc_util.h"
++
++static void explain(void)
++{
++ fprintf(stderr, "Usage: ... fq_codel [ limit PACKETS ] [ flows NUMBER ]\n");
++ fprintf(stderr, " [ target TIME] [ interval TIME ]\n");
++ fprintf(stderr, " [ quantum BYTES ] [ [no]ecn ]\n");
++}
++
++static int fq_codel_parse_opt(struct qdisc_util *qu, int argc, char **argv,
++ struct nlmsghdr *n)
++{
++ unsigned limit = 0;
++ unsigned flows = 0;
++ unsigned target = 0;
++ unsigned interval = 0;
++ unsigned quantum = 0;
++ int ecn = -1;
++ struct rtattr *tail;
++
++ while (argc > 0) {
++ if (strcmp(*argv, "limit") == 0) {
++ NEXT_ARG();
++ if (get_unsigned(&limit, *argv, 0)) {
++ fprintf(stderr, "Illegal \"limit\"\n");
++ return -1;
++ }
++ } else if (strcmp(*argv, "flows") == 0) {
++ NEXT_ARG();
++ if (get_unsigned(&flows, *argv, 0)) {
++ fprintf(stderr, "Illegal \"flows\"\n");
++ return -1;
++ }
++ } else if (strcmp(*argv, "quantum") == 0) {
++ NEXT_ARG();
++ if (get_unsigned(&quantum, *argv, 0)) {
++ fprintf(stderr, "Illegal \"quantum\"\n");
++ return -1;
++ }
++ } else if (strcmp(*argv, "target") == 0) {
++ NEXT_ARG();
++ if (get_time(&target, *argv)) {
++ fprintf(stderr, "Illegal \"target\"\n");
++ return -1;
++ }
++ } else if (strcmp(*argv, "interval") == 0) {
++ NEXT_ARG();
++ if (get_time(&interval, *argv)) {
++ fprintf(stderr, "Illegal \"interval\"\n");
++ return -1;
++ }
++ } else if (strcmp(*argv, "ecn") == 0) {
++ ecn = 1;
++ } else if (strcmp(*argv, "noecn") == 0) {
++ ecn = 0;
++ } else if (strcmp(*argv, "help") == 0) {
++ explain();
++ return -1;
++ } else {
++ fprintf(stderr, "What is \"%s\"?\n", *argv);
++ explain();
++ return -1;
++ }
++ argc--; argv++;
++ }
++
++ tail = NLMSG_TAIL(n);
++ addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
++ if (limit)
++ addattr_l(n, 1024, TCA_FQ_CODEL_LIMIT, &limit, sizeof(limit));
++ if (flows)
++ addattr_l(n, 1024, TCA_FQ_CODEL_FLOWS, &flows, sizeof(flows));
++ if (quantum)
++ addattr_l(n, 1024, TCA_FQ_CODEL_QUANTUM, &quantum, sizeof(quantum));
++ if (interval)
++ addattr_l(n, 1024, TCA_FQ_CODEL_INTERVAL, &interval, sizeof(interval));
++ if (target)
++ addattr_l(n, 1024, TCA_FQ_CODEL_TARGET, &target, sizeof(target));
++ if (ecn != -1)
++ addattr_l(n, 1024, TCA_FQ_CODEL_ECN, &ecn, sizeof(ecn));
++ tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
++ return 0;
++}
++
++static int fq_codel_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
++{
++ struct rtattr *tb[TCA_FQ_CODEL_MAX + 1];
++ unsigned limit;
++ unsigned flows;
++ unsigned interval;
++ unsigned target;
++ unsigned ecn;
++ unsigned quantum;
++ SPRINT_BUF(b1);
++
++ if (opt == NULL)
++ return 0;
++
++ parse_rtattr_nested(tb, TCA_FQ_CODEL_MAX, opt);
++
++ if (tb[TCA_FQ_CODEL_LIMIT] &&
++ RTA_PAYLOAD(tb[TCA_FQ_CODEL_LIMIT]) >= sizeof(__u32)) {
++ limit = rta_getattr_u32(tb[TCA_FQ_CODEL_LIMIT]);
++ fprintf(f, "limit %up ", limit);
++ }
++ if (tb[TCA_FQ_CODEL_FLOWS] &&
++ RTA_PAYLOAD(tb[TCA_FQ_CODEL_FLOWS]) >= sizeof(__u32)) {
++ flows = rta_getattr_u32(tb[TCA_FQ_CODEL_FLOWS]);
++ fprintf(f, "flows %u ", flows);
++ }
++ if (tb[TCA_FQ_CODEL_QUANTUM] &&
++ RTA_PAYLOAD(tb[TCA_FQ_CODEL_QUANTUM]) >= sizeof(__u32)) {
++ quantum = rta_getattr_u32(tb[TCA_FQ_CODEL_QUANTUM]);
++ fprintf(f, "quantum %u ", quantum);
++ }
++ if (tb[TCA_FQ_CODEL_TARGET] &&
++ RTA_PAYLOAD(tb[TCA_FQ_CODEL_TARGET]) >= sizeof(__u32)) {
++ target = rta_getattr_u32(tb[TCA_FQ_CODEL_TARGET]);
++ fprintf(f, "target %s ", sprint_time(target, b1));
++ }
++ if (tb[TCA_FQ_CODEL_INTERVAL] &&
++ RTA_PAYLOAD(tb[TCA_FQ_CODEL_INTERVAL]) >= sizeof(__u32)) {
++ interval = rta_getattr_u32(tb[TCA_FQ_CODEL_INTERVAL]);
++ fprintf(f, "interval %s ", sprint_time(interval, b1));
++ }
++ if (tb[TCA_FQ_CODEL_ECN] &&
++ RTA_PAYLOAD(tb[TCA_FQ_CODEL_ECN]) >= sizeof(__u32)) {
++ ecn = rta_getattr_u32(tb[TCA_FQ_CODEL_ECN]);
++ if (ecn)
++ fprintf(f, "ecn ");
++ }
++
++ return 0;
++}
++
++static int fq_codel_print_xstats(struct qdisc_util *qu, FILE *f,
++ struct rtattr *xstats)
++{
++ struct tc_fq_codel_xstats *st;
++ SPRINT_BUF(b1);
++
++ if (xstats == NULL)
++ return 0;
++
++ if (RTA_PAYLOAD(xstats) < sizeof(*st))
++ return -1;
++
++ st = RTA_DATA(xstats);
++ if (st->type == TCA_FQ_CODEL_XSTATS_QDISC) {
++ fprintf(f, " maxpacket %u drop_overlimit %u new_flow_count %u ecn_mark %u",
++ st->qdisc_stats.maxpacket,
++ st->qdisc_stats.drop_overlimit,
++ st->qdisc_stats.new_flow_count,
++ st->qdisc_stats.ecn_mark);
++ fprintf(f, "\n new_flows_len %u old_flows_len %u",
++ st->qdisc_stats.new_flows_len,
++ st->qdisc_stats.old_flows_len);
++ }
++ if (st->type == TCA_FQ_CODEL_XSTATS_CLASS) {
++ fprintf(f, " deficit %d count %u lastcount %u ldelay %s",
++ st->class_stats.deficit,
++ st->class_stats.count,
++ st->class_stats.lastcount,
++ sprint_time(st->class_stats.ldelay, b1));
++ if (st->class_stats.dropping) {
++ fprintf(f, " dropping");
++ if (st->class_stats.drop_next < 0)
++ fprintf(f, " drop_next -%s",
++ sprint_time(-st->class_stats.drop_next, b1));
++ else
++ fprintf(f, " drop_next %s",
++ sprint_time(st->class_stats.drop_next, b1));
++ }
++ }
++ return 0;
++
++}
++
++struct qdisc_util fq_codel_qdisc_util = {
++ .id = "fq_codel",
++ .parse_qopt = fq_codel_parse_opt,
++ .print_qopt = fq_codel_print_opt,
++ .print_xstats = fq_codel_print_xstats,
++};
diff --git a/package/iptables/Makefile b/package/iptables/Makefile
new file mode 100644
index 000000000..ff7d42821
--- /dev/null
+++ b/package/iptables/Makefile
@@ -0,0 +1,475 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=iptables
+PKG_VERSION:=1.4.10
+PKG_RELEASE:=4
+
+PKG_MD5SUM:=f382fe693f0b59d87bd47bea65eca198
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://www.netfilter.org/projects/iptables/files \
+ ftp://ftp.be.netfilter.org/pub/netfilter/iptables/ \
+ ftp://ftp.de.netfilter.org/pub/netfilter/iptables/ \
+ ftp://ftp.no.netfilter.org/pub/netfilter/iptables/
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+ifneq ($(CONFIG_EXTERNAL_KERNEL_TREE),"")
+PATCH_DIR:=
+endif
+
+include $(INCLUDE_DIR)/package.mk
+ifeq ($(DUMP),)
+ -include $(LINUX_DIR)/.config
+ include $(INCLUDE_DIR)/netfilter.mk
+ STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell $(SH_FUNC) grep 'NETFILTER' $(LINUX_DIR)/.config | md5s)
+endif
+
+
+define Package/iptables/Default
+ SECTION:=net
+ CATEGORY:=Network
+ SUBMENU:=Firewall
+ URL:=http://netfilter.org/
+endef
+
+define Package/iptables/Module
+$(call Package/iptables/Default)
+ DEPENDS:=iptables $(1)
+endef
+
+define Package/iptables
+$(call Package/iptables/Default)
+ TITLE:=IPv4 firewall administration tool
+ MENU:=1
+ DEPENDS+= +kmod-ipt-core +libip4tc +libxtables
+endef
+
+define Package/iptables/description
+IPv4 firewall administration tool.
+
+ Matches:
+ - icmp
+ - tcp
+ - udp
+ - comment
+ - limit
+ - mac
+ - multiport
+
+ Targets:
+ - ACCEPT
+ - DROP
+ - REJECT
+ - LOG
+ - TCPMSS
+
+ Tables:
+ - filter
+ - mangle
+
+endef
+
+define Package/iptables-mod-conntrack-extra
+$(call Package/iptables/Module, +kmod-ipt-conntrack-extra)
+ TITLE:=Extra connection tracking extensions
+endef
+
+define Package/iptables-mod-conntrack-extra/description
+Extra iptables extensions for connection tracking.
+
+ Matches:
+ - connbytes
+ - connmark
+ - recent
+ - helper
+
+ Targets:
+ - CONNMARK
+
+endef
+
+define Package/iptables-mod-filter
+$(call Package/iptables/Module, +kmod-ipt-filter)
+ TITLE:=Content inspection extensions
+endef
+
+define Package/iptables-mod-filter/description
+iptables extensions for packet content inspection.
+Includes support for:
+
+ Matches:
+ - layer7
+ - string
+
+endef
+
+define Package/iptables-mod-ipopt
+$(call Package/iptables/Module, +kmod-ipt-ipopt)
+ TITLE:=IP/Packet option extensions
+endef
+
+define Package/iptables-mod-ipopt/description
+iptables extensions for matching/changing IP packet options.
+
+ Matches:
+ - dscp
+ - ecn
+ - length
+ - mark
+ - statistic
+ - tcpmss
+ - time
+ - unclean
+ - hl
+
+ Targets:
+ - DSCP
+ - CLASSIFY
+ - ECN
+ - MARK
+ - HL
+
+endef
+
+define Package/iptables-mod-ipsec
+$(call Package/iptables/Module, +kmod-ipt-ipsec)
+ TITLE:=IPsec extensions
+endef
+
+define Package/iptables-mod-ipsec/description
+iptables extensions for matching ipsec traffic.
+
+ Matches:
+ - ah
+ - esp
+ - policy
+
+endef
+
+define Package/iptables-mod-ipset
+$(call Package/iptables/Module,)
+ TITLE:=IPset iptables extensions
+endef
+
+define Package/iptables-mod-ipset/description
+IPset iptables extensions.
+
+ Matches:
+ - set
+
+ Targets:
+ - SET
+
+endef
+
+define Package/iptables-mod-nat-extra
+$(call Package/iptables/Module, +kmod-ipt-nat-extra)
+ TITLE:=Extra NAT extensions
+endef
+
+define Package/iptables-mod-nat-extra/description
+iptables extensions for extra NAT targets.
+
+ Targets:
+ - MIRROR
+ - NETMAP
+ - REDIRECT
+endef
+
+define Package/iptables-mod-ulog
+$(call Package/iptables/Module, +kmod-ipt-ulog)
+ TITLE:=user-space packet logging
+endef
+
+define Package/iptables-mod-ulog/description
+iptables extensions for user-space packet logging.
+
+ Targets:
+ - ULOG
+
+endef
+
+define Package/iptables-mod-hashlimit
+$(call Package/iptables/Module, +kmod-ipt-hashlimit)
+ TITLE:=hashlimit matching
+endef
+
+define Package/iptables-mod-hashlimit/description
+iptables extensions for hashlimit matching
+
+ Matches:
+ - hashlimit
+
+endef
+
+define Package/iptables-mod-iprange
+$(call Package/iptables/Module, +kmod-ipt-iprange)
+ TITLE:=IP range extension
+endef
+
+define Package/iptables-mod-iprange/description
+iptables extensions for matching ip ranges.
+
+ Matches:
+ - iprange
+
+endef
+
+define Package/iptables-mod-extra
+$(call Package/iptables/Module, +kmod-ipt-extra)
+ TITLE:=Other extra iptables extensions
+endef
+
+define Package/iptables-mod-extra/description
+Other extra iptables extensions.
+
+ Matches:
+ - condition
+ - owner
+ - physdev (if ebtables is enabled)
+ - pkttype
+ - quota
+
+endef
+
+define Package/iptables-mod-led
+$(call Package/iptables/Module, +kmod-ipt-led)
+ TITLE:=LED trigger iptables extension
+endef
+
+define Package/iptables-mod-led/description
+iptables extension for triggering a LED.
+
+ Targets:
+ - LED
+
+endef
+
+define Package/iptables-mod-tproxy
+$(call Package/iptables/Module, +kmod-ipt-tproxy)
+ TITLE:=Transparent proxy iptables extensions
+endef
+
+define Package/iptables-mod-tproxy/description
+Transparent proxy iptables extensions.
+
+ Matches:
+ - socket
+
+ Targets:
+ - TPROXY
+
+endef
+
+define Package/iptables-mod-tee
+$(call Package/iptables/Module, +kmod-ipt-tee)
+ TITLE:=TEE iptables extensions
+endef
+
+define Package/iptables-mod-tee/description
+TEE iptables extensions.
+
+ Targets:
+ - TEE
+
+endef
+
+define Package/iptables-mod-u32
+$(call Package/iptables/Module, +kmod-ipt-u32)
+ TITLE:=U32 iptables extensions
+endef
+
+define Package/iptables-mod-u32/description
+U32 iptables extensions.
+
+ Matches:
+ - u32
+
+endef
+
+define Package/ip6tables
+$(call Package/iptables/Default)
+ DEPENDS:=+kmod-ip6tables +libip6tc +libxtables
+ CATEGORY:=IPv6
+ TITLE:=IPv6 firewall administration tool
+ MENU:=1
+endef
+
+define Package/libiptc
+$(call Package/iptables/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ DEPENDS:=+libip4tc +libip6tc
+ TITLE:=IPv4/IPv6 firewall - shared libiptc library (compatibility stub)
+endef
+
+define Package/libip4tc
+$(call Package/iptables/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=IPv4 firewall - shared libiptc library
+endef
+
+define Package/libip6tc
+$(call Package/iptables/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=IPv6 firewall - shared libiptc library
+endef
+
+define Package/libxtables
+ $(call Package/iptables/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=IPv4/IPv6 firewall - shared xtables library
+endef
+
+define Package/libipq
+ $(call Package/iptables/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=IPv4/IPv6 firewall - shared libipq library
+endef
+
+TARGET_CPPFLAGS := \
+ -I$(PKG_BUILD_DIR)/include \
+ -I$(LINUX_DIR)/user_headers/include \
+ $(TARGET_CPPFLAGS)
+
+TARGET_CFLAGS += \
+ -I$(PKG_BUILD_DIR)/include \
+ -I$(LINUX_DIR)/user_headers/include
+
+CONFIGURE_ARGS += \
+ --enable-shared \
+ --enable-devel \
+ $(if $(CONFIG_IPV6),--enable-ipv6,--disable-ipv6) \
+ --enable-libipq \
+ --with-kernel="$(LINUX_DIR)/user_headers" \
+ --with-xtlibdir=/usr/lib/iptables \
+ --enable-static
+
+MAKE_FLAGS := \
+ $(TARGET_CONFIGURE_OPTS) \
+ COPT_FLAGS="$(TARGET_CFLAGS)" \
+ KERNEL_DIR="$(LINUX_DIR)/user_headers/" PREFIX=/usr \
+ KBUILD_OUTPUT="$(LINUX_DIR)" \
+ BUILTIN_MODULES="$(patsubst ipt_%,%,$(patsubst xt_%,%,$(IPT_BUILTIN) $(IPT_CONNTRACK-m) $(IPT_NAT-m)))"
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(INSTALL_DIR) $(1)/usr/include/iptables
+ $(INSTALL_DIR) $(1)/usr/include/net/netfilter
+
+ # XXX: iptables header fixup, some headers are not installed by iptables anymore
+ $(CP) $(PKG_BUILD_DIR)/include/net/netfilter/*.h $(1)/usr/include/net/netfilter/
+ $(CP) $(PKG_BUILD_DIR)/include/iptables/*.h $(1)/usr/include/iptables/
+ $(CP) $(PKG_BUILD_DIR)/include/iptables.h $(1)/usr/include/
+ $(CP) $(PKG_BUILD_DIR)/include/libipq/libipq.h $(1)/usr/include/
+ $(CP) $(PKG_BUILD_DIR)/include/libipulog $(1)/usr/include/
+ $(CP) $(PKG_BUILD_DIR)/include/libiptc $(1)/usr/include/
+
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libxtables.so* $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libip*tc.so* $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libipq.so* $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/xtables.pc $(1)/usr/lib/pkgconfig/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libiptc.pc $(1)/usr/lib/pkgconfig/
+endef
+
+define Package/iptables/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/iptables $(1)/usr/sbin/
+ $(LN) iptables $(1)/usr/sbin/iptables-save
+ $(LN) iptables $(1)/usr/sbin/iptables-restore
+ $(INSTALL_DIR) $(1)/usr/lib/iptables
+endef
+
+define Package/ip6tables/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ip6tables $(1)/usr/sbin/
+ $(LN) ip6tables $(1)/usr/sbin/ip6tables-save
+ $(LN) ip6tables $(1)/usr/sbin/ip6tables-restore
+ $(INSTALL_DIR) $(1)/usr/lib/iptables
+ (cd $(PKG_INSTALL_DIR)/usr/lib/iptables ; \
+ $(CP) libip6t_*.so $(1)/usr/lib/iptables/ \
+ )
+endef
+
+define Package/libiptc/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libiptc.so* $(1)/usr/lib/
+endef
+
+define Package/libip4tc/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libip4tc.so* $(1)/usr/lib/
+endef
+
+define Package/libip6tc/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libip6tc.so* $(1)/usr/lib/
+endef
+
+define Package/libxtables/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libxtables.so* $(1)/usr/lib/
+endef
+
+define Package/libipq/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libipq.so* $(1)/usr/lib/
+endef
+
+define BuildPlugin
+ define Package/$(1)/install
+ $(INSTALL_DIR) $$(1)/usr/lib/iptables
+ for m in $(patsubst xt_%,ipt_%,$(2)) $(patsubst ipt_%,xt_%,$(2)); do \
+ if [ -f $(PKG_INSTALL_DIR)/usr/lib/iptables/lib$$$$$$$${m}.so ]; then \
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/iptables/lib$$$$$$$${m}.so $$(1)/usr/lib/iptables/ ; \
+ fi; \
+ done
+ $(3)
+ endef
+
+ $$(eval $$(call BuildPackage,$(1)))
+endef
+
+L7_INSTALL:=\
+ $(INSTALL_DIR) $$(1)/etc/l7-protocols; \
+ $(CP) files/l7/*.pat $$(1)/etc/l7-protocols/
+
+
+$(eval $(call BuildPackage,iptables))
+$(eval $(call BuildPlugin,iptables-mod-conntrack-extra,$(IPT_CONNTRACK_EXTRA-m)))
+$(eval $(call BuildPlugin,iptables-mod-extra,$(IPT_EXTRA-m)))
+$(eval $(call BuildPlugin,iptables-mod-filter,$(IPT_FILTER-m),$(L7_INSTALL)))
+$(eval $(call BuildPlugin,iptables-mod-ipopt,$(IPT_IPOPT-m)))
+$(eval $(call BuildPlugin,iptables-mod-ipsec,$(IPT_IPSEC-m)))
+$(eval $(call BuildPlugin,iptables-mod-ipset,ipt_set ipt_SET))
+$(eval $(call BuildPlugin,iptables-mod-nat-extra,$(IPT_NAT_EXTRA-m)))
+$(eval $(call BuildPlugin,iptables-mod-iprange,$(IPT_IPRANGE-m)))
+$(eval $(call BuildPlugin,iptables-mod-ulog,$(IPT_ULOG-m)))
+$(eval $(call BuildPlugin,iptables-mod-hashlimit,$(IPT_HASHLIMIT-m)))
+$(eval $(call BuildPlugin,iptables-mod-led,$(IPT_LED-m)))
+$(eval $(call BuildPlugin,iptables-mod-tproxy,$(IPT_TPROXY-m)))
+$(eval $(call BuildPlugin,iptables-mod-tee,$(IPT_TEE-m)))
+$(eval $(call BuildPlugin,iptables-mod-u32,$(IPT_U32-m)))
+$(eval $(call BuildPackage,ip6tables))
+$(eval $(call BuildPackage,libiptc))
+$(eval $(call BuildPackage,libip4tc))
+$(eval $(call BuildPackage,libip6tc))
+$(eval $(call BuildPackage,libxtables))
+$(eval $(call BuildPackage,libipq))
diff --git a/package/iptables/files/l7/aim.pat b/package/iptables/files/l7/aim.pat
new file mode 100644
index 000000000..5c43930fd
--- /dev/null
+++ b/package/iptables/files/l7/aim.pat
@@ -0,0 +1,28 @@
+# AIM - AOL instant messenger (OSCAR and TOC)
+# Pattern attributes: good slow notsofast
+# Protocol groups: chat proprietary
+# Wiki: http://www.protocolinfo.org/wiki/AIM
+# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
+#
+# Usually runs on port 5190
+#
+# This may also match ICQ traffic.
+#
+# This pattern has been tested and is believed to work well.
+
+aim
+# See http://gridley.res.carleton.edu/~straitm/final (and various other places)
+# The first bit matches OSCAR signon and data commands, but not sure what
+# \x03\x0b matches, but it works apparently.
+# The next three bits match various parts of the TOC signon process.
+# The third one is the magic number "*", then 0x01 for "signon", then up to four
+# bytes ("up to" because l7-filter strips out nulls) which contain a sequence
+# number (2 bytes) the data length (2 more) and 3 nulls (which don't count),
+# then 0x01 for the version number (not sure if there ever has been another
+# version)
+# The fourth one is a command string, followed by some stuff, then the
+# beginning of the "roasted" password
+
+# This pattern is too slow!
+
+^(\*[\x01\x02].*\x03\x0b|\*\x01.?.?.?.?\x01)|flapon|toc_signon.*0x
diff --git a/package/iptables/files/l7/bittorrent.pat b/package/iptables/files/l7/bittorrent.pat
new file mode 100644
index 000000000..4a3ba88d5
--- /dev/null
+++ b/package/iptables/files/l7/bittorrent.pat
@@ -0,0 +1,25 @@
+# Bittorrent - P2P filesharing / publishing tool - http://www.bittorrent.com
+# Pattern attributes: good slow594 notsofast undermatch
+# Protocol groups: p2p open_source
+# Wiki: http://www.protocolinfo.org/wiki/Bittorrent
+# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
+#
+# This pattern has been tested and is believed to work well.
+# It will, however, not work on bittorrent streams that are encrypted, since
+# it's impossible to match (well) encrypted data.
+
+bittorrent
+
+# Does not attempt to match the HTTP download of the tracker
+# 0x13 is the length of "bittorrent protocol"
+# Second two bits match UDP wierdness
+# Next bit matches something Azureus does
+# Ditto on the next bit. Could also match on "user-agent: azureus", but that's in the next
+# packet and perhaps this will match multiple clients.
+# bitcomet-specific strings contributed by liangjun.
+
+# This is not a valid GNU basic regular expression (but that's ok).
+^(\x13bittorrent protocol|azver\x01$|get /scrape\?info_hash=get /announce\?info_hash=|get /client/bitcomet/|GET /data\?fid=)|d1:ad2:id20:|\x08'7P\)[RP]
+
+# This pattern is "fast", but won't catch as much
+#^(\x13bittorrent protocol|azver\x01$|get /scrape\?info_hash=)
diff --git a/package/iptables/files/l7/edonkey.pat b/package/iptables/files/l7/edonkey.pat
new file mode 100644
index 000000000..75807f8eb
--- /dev/null
+++ b/package/iptables/files/l7/edonkey.pat
@@ -0,0 +1,37 @@
+# eDonkey2000 - P2P filesharing - http://edonkey2000.com and others
+# Pattern attributes: good veryfast fast overmatch
+# Protocol groups: p2p
+# Wiki: http://www.protocolinfo.org/wiki/EDonkey
+# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
+#
+# Tested recently (April/May 2006) with eMule 0.47a and eDonkey2000 1.4
+# and a long time ago with something else.
+#
+# In addition to matching what you might expect, this matches much of
+# what eMule does when you tell it to only connect to the KAD network.
+# I don't quite know what to make of this.
+
+# Thanks to Matt Skidmore <fox AT woozle.org>
+
+edonkey
+
+# http://gd.tuwien.ac.at/opsys/linux/sf/p/pdonkey/eDonkey-protocol-0.6
+#
+# In addition to \xe3, \xc5 and \xd4, I see a lot of \xe5.
+# As of April 2006, I also see some \xe4.
+#
+# God this is a mess. What an irritating protocol.
+# This will match about 2% of streams with random data in them!
+# (But fortunately much fewer than 2% of streams that are other protocols.
+# You can test this with the data in ../testing/)
+
+^[\xc5\xd4\xe3-\xe5].?.?.?.?([\x01\x02\x05\x14\x15\x16\x18\x19\x1a\x1b\x1c\x20\x21\x32\x33\x34\x35\x36\x38\x40\x41\x42\x43\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58[\x60\x81\x82\x90\x91\x93\x96\x97\x98\x99\x9a\x9b\x9c\x9e\xa0\xa1\xa2\xa3\xa4]|\x59................?[ -~]|\x96....$)
+
+# matches everything and too much
+# ^(\xe3|\xc5|\xd4)
+
+# ipp2p essentially uses "\xe3....\x47", which doesn't seem at all right to me.
+
+# bandwidtharbitrator uses
+# e0.*@.*6[a-z].*p$|e0.*@.*[a-z]6[a-z].*p0$|e.*@.*[0-9]6.*p$|emule|edonkey
+# no comments to explain what all the mush is, of course...
diff --git a/package/iptables/files/l7/fasttrack.pat b/package/iptables/files/l7/fasttrack.pat
new file mode 100644
index 000000000..6ed8ff1d1
--- /dev/null
+++ b/package/iptables/files/l7/fasttrack.pat
@@ -0,0 +1,23 @@
+# FastTrack - P2P filesharing (Kazaa, Morpheus, iMesh, Grokster, etc)
+# Pattern attributes: good slow notsofast
+# Protocol groups: p2p
+# Wiki: http://www.protocolinfo.org/wiki/Fasttrack
+# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
+#
+# Tested with Kazaa Lite Resurrection 0.0.7.6F
+#
+# This appears to match the download connections well, but not the search
+# connections (I think they are encrypted :-( ).
+
+fasttrack
+# while this is a valid http request, this will be caught because
+# the http pattern matches the response (and therefore the next packet)
+# Even so, it's best to put this match earlier in the chain.
+# http://cvs.berlios.de/cgi-bin/viewcvs.cgi/gift-fasttrack/giFT-FastTrack/PROTOCOL?rev=HEAD&content-type=text/vnd.viewcvs-markup
+
+# This pattern is kinda slow, but not too bad.
+^get (/.download/[ -~]*|/.supernode[ -~]|/.status[ -~]|/.network[ -~]*|/.files|/.hash=[0-9a-f]*/[ -~]*) http/1.1|user-agent: kazaa|x-kazaa(-username|-network|-ip|-supernodeip|-xferid|-xferuid|tag)|^give [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]?[0-9]?[0-9]?
+
+# This isn't much faster:
+#^get (/.download/.*|/.supernode.|/.status.|/.network.*|/.files|/.hash=[0-9a-f]*/.*) http/1.1|user-agent: kazaa|x-kazaa(-username|-network|-ip|-supernodeip|-xferid|-xferuid|tag)|^give [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]?[0-9]?[0-9]?
+
diff --git a/package/iptables/files/l7/ftp.pat b/package/iptables/files/l7/ftp.pat
new file mode 100644
index 000000000..44d97c467
--- /dev/null
+++ b/package/iptables/files/l7/ftp.pat
@@ -0,0 +1,46 @@
+# FTP - File Transfer Protocol - RFC 959
+# Pattern attributes: great notsofast fast
+# Protocol groups: document_retrieval ietf_internet_standard
+# Wiki: http://protocolinfo.org/wiki/FTP
+# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
+#
+# Usually runs on port 21. Note that the data stream is on a dynamically
+# assigned port, which means that you will need the FTP connection
+# tracking module in your kernel to usefully match FTP data transfers.
+#
+# This pattern is well tested.
+#
+# Handles the first two things a server should say:
+#
+# First, the server says it's ready by sending "220". Most servers say
+# something after 220, even though they don't have to, and it usually
+# includes the string "ftp" (l7-filter is case insensitive). This
+# includes proftpd, vsftpd, wuftpd, warftpd, pureftpd, Bulletproof FTP
+# Server, and whatever ftp.microsoft.com uses. Almost all servers use only
+# ASCII printable characters between the "220" and the "FTP", but non-English
+# ones might use others.
+#
+# The next thing the server sends is a 331. All the above servers also
+# send something including "password" after this code. By default, we
+# do not match on this because it takes another packet and is more work
+# for regexec.
+
+ftp
+# by default, we allow only ASCII
+^220[\x09-\x0d -~]*ftp
+
+# This covers UTF-8 as well
+#^220[\x09-\x0d -~\x80-\xfd]*ftp
+
+# This allows any characters and is about 4x faster than either of the above
+# (which are about the same as each other)
+#^220.*ftp
+
+# This is much slower
+#^220[\x09-\x0d -~]*ftp|331[\x09-\x0d -~]*password
+
+# This pattern is more precise, but takes longer to match. (3 packets vs. 1)
+#^220[\x09-\x0d -~]*\x0d\x0aUSER[\x09-\x0d -~]*\x0d\x0a331
+
+# same as above, but slightly less precise and only takes 2 packets.
+#^220[\x09-\x0d -~]*\x0d\x0aUSER[\x09-\x0d -~]*\x0d\x0a
diff --git a/package/iptables/files/l7/gnutella.pat b/package/iptables/files/l7/gnutella.pat
new file mode 100644
index 000000000..770ed43b3
--- /dev/null
+++ b/package/iptables/files/l7/gnutella.pat
@@ -0,0 +1,34 @@
+# Gnutella - P2P filesharing
+# Pattern attributes: good notsofast notsofast
+# Protocol groups: p2p open_source
+# Wiki: http://www.protocolinfo.org/wiki/Gnutella
+# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
+#
+# This should match both Gnutella and "Gnutella2" ("Mike's protocol")
+#
+# Various clients use this protocol including Mactella, Shareaza,
+# GTK-gnutella, Gnucleus, Gnotella, LimeWire, iMesh and BearShare.
+#
+# This is tested with gtk-gnutella and Shareaza.
+
+# http://www.gnutella2.com/tiki-index.php?page=UDP%20Transceiver
+# http://rfc-gnutella.sf.net/
+# http://www.gnutella2.com/tiki-index.php?page=Gnutella2%20Specification
+# http://en.wikipedia.org/wiki/Shareaza
+
+gnutella
+
+# The first part matches UDP messages - All start with "GND", then have
+# a flag byte which is either \x00, \x01 or \x02, then two sequence bytes
+# that can be anything, then a fragment number, which must start at 1.
+# The rest matches TCP first client message or first server message (in case
+# we can't see client messages). Some parts of this are empirical rather than
+# document based. Assumes version is between 0.0 and 2.9. (usually is
+# 0.4 or 0.6). I'm guessing at many of the user-agents.
+# The last bit is emprical and probably only matches Limewire.
+^(gnd[\x01\x02]?.?.?\x01|gnutella connect/[012]\.[0-9]\x0d\x0a|get /uri-res/n2r\?urn:sha1:|get /.*user-agent: (gtk-gnutella|bearshare|mactella|gnucleus|gnotella|limewire|imesh)|get /.*content-type: application/x-gnutella-packets|giv [0-9]*:[0-9a-f]*/|queue [0-9a-f]* [1-9][0-9]?[0-9]?\.[1-9][0-9]?[0-9]?\.[1-9][0-9]?[0-9]?\.[1-9][0-9]?[0-9]?:[1-9][0-9]?[0-9]?[0-9]?|gnutella.*content-type: application/x-gnutella|...................?lime)
+
+# Needlessly precise, at the expense of time
+#^(gnd[\x01\x02]?.?.?\x01|gnutella connect/[012]\.[0-9]\x0d\x0a|get /uri-res/n2r\?urn:sha1:|get /[\x09-\x0d -~]*user-agent: (gtk-gnutella|bearshare|mactella|gnucleus|gnotella|limewire|imesh)|get /[\x09-\x0d -~]*content-type: application/x-gnutella-packets|giv [0-9]*:[0-9a-f]*/|queue [0-9a-f]* [1-9][0-9]?[0-9]?\.[1-9][0-9]?[0-9]?\.[1-9][0-9]?[0-9]?\.[1-9][0-9]?[0-9]?:[1-9][0-9]?[0-9]?[0-9]?|gnutella[\x09-\x0d -~]*content-type: application/x-gnutella|..................lime)
+
+
diff --git a/package/iptables/files/l7/http.pat b/package/iptables/files/l7/http.pat
new file mode 100644
index 000000000..5122310d2
--- /dev/null
+++ b/package/iptables/files/l7/http.pat
@@ -0,0 +1,28 @@
+# HTTP - HyperText Transfer Protocol - RFC 2616
+# Pattern attributes: great slow notsofast superset
+# Protocol groups: document_retrieval ietf_draft_standard
+# Wiki: http://protocolinfo.org/wiki/HTTP
+# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
+#
+# Usually runs on port 80
+#
+# This pattern has been tested and is believed to work well.
+#
+# this intentionally catches the response from the server rather than
+# the request so that other protocols which use http (like kazaa) can be
+# caught based on specific http requests regardless of the ordering of
+# filters... also matches posts
+
+# Sites that serve really long cookies may break this by pushing the
+# server response too far away from the beginning of the connection. To
+# fix this, increase the kernel's data buffer length.
+
+http
+# Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF (rfc 2616)
+# As specified in rfc 2616 a status code is preceeded and followed by a
+# space.
+http/(0\.9|1\.0|1\.1) [1-5][0-9][0-9] [\x09-\x0d -~]*(connection:|content-type:|content-length:|date:)|post [\x09-\x0d -~]* http/[01]\.[019]
+# A slightly faster version that might be good enough:
+#http/(0\.9|1\.0|1\.1) [1-5][0-9][0-9]|post [\x09-\x0d -~]* http/[01]\.[019]
+# old pattern(s):
+#(http[\x09-\x0d -~]*(200 ok|302 |304 )[\x09-\x0d -~]*(connection:|content-type:|content-length:))|^(post [\x09-\x0d -~]* http/)
diff --git a/package/iptables/files/l7/ident.pat b/package/iptables/files/l7/ident.pat
new file mode 100644
index 000000000..3205e5e69
--- /dev/null
+++ b/package/iptables/files/l7/ident.pat
@@ -0,0 +1,15 @@
+# Ident - Identification Protocol - RFC 1413
+# Pattern attributes: good fast fast
+# Protocol groups: networking ietf_proposed_standard
+# Wiki: http://www.protocolinfo.org/wiki/Ident
+# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
+#
+# Usually runs on port 113
+#
+# This pattern is believed to work.
+
+ident
+# "number , numberCRLF" possibly without the CR and/or LF.
+# ^$ is appropriate because the first packet should never have anything
+# else in it.
+^[1-9][0-9]?[0-9]?[0-9]?[0-9]?[\x09-\x0d]*,[\x09-\x0d]*[1-9][0-9]?[0-9]?[0-9]?[0-9]?(\x0d\x0a|[\x0d\x0a])?$
diff --git a/package/iptables/files/l7/irc.pat b/package/iptables/files/l7/irc.pat
new file mode 100644
index 000000000..e25360caf
--- /dev/null
+++ b/package/iptables/files/l7/irc.pat
@@ -0,0 +1,20 @@
+# IRC - Internet Relay Chat - RFC 1459
+# Pattern attributes: great veryfast fast
+# Protocol groups: chat ietf_proposed_standard
+# Wiki: http://www.protocolinfo.org/wiki/IRC
+# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
+#
+# Usually runs on port 6666 or 6667
+# Note that chat traffic runs on these ports, but IRC-DCC traffic (which
+# can use much more bandwidth) uses a dynamically assigned port, so you
+# must have the IRC connection tracking module in your kernel to classify
+# this.
+#
+# This pattern has been tested and is believed to work well.
+
+irc
+# First thing that happens is that the client sends NICK and USER, in
+# either order. This allows MIRC color codes (\x02-\x0d instead of
+# \x09-\x0d).
+^(nick[\x09-\x0d -~]*user[\x09-\x0d -~]*:|user[\x09-\x0d -~]*:[\x02-\x0d -~]*nick[\x09-\x0d -~]*\x0d\x0a)
+
diff --git a/package/iptables/files/l7/jabber.pat b/package/iptables/files/l7/jabber.pat
new file mode 100644
index 000000000..7c328905e
--- /dev/null
+++ b/package/iptables/files/l7/jabber.pat
@@ -0,0 +1,24 @@
+# Jabber (XMPP) - open instant messenger protocol - RFC 3920 - http://jabber.org
+# Pattern attributes: good notsofast notsofast
+# Protocol groups: chat ietf_proposed_standard
+# Wiki: http://www.protocolinfo.org/wiki/Jabber
+# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
+#
+# This pattern has been tested with Gaim and Gabber. It is only tested
+# with non-SSL mode Jabber with no proxies.
+
+# Thanks to Jan Hudec for some improvements.
+
+# Jabber seems to take a long time to set up a connection. I'm
+# connecting with Gabber 0.8.8 to 12jabber.org and the first 8 packets
+# is this:
+# <stream:stream to='12jabber.com' xmlns='jabber:client'
+# xmlns:stream='http://etherx.jabber.org/streams'><?xml
+# version='1.0'?><stream:stream
+# xmlns:stream='http://etherx.jabber.org/streams' id='3f73e951'
+# xmlns='jabber:client' from='12jabber.com'>
+#
+# No mention of my username or password yet, you'll note.
+
+jabber
+<stream:stream[\x09-\x0d ][ -~]*[\x09-\x0d ]xmlns=['"]jabber
diff --git a/package/iptables/files/l7/msnmessenger.pat b/package/iptables/files/l7/msnmessenger.pat
new file mode 100644
index 000000000..11dfc10be
--- /dev/null
+++ b/package/iptables/files/l7/msnmessenger.pat
@@ -0,0 +1,28 @@
+# MSN Messenger - Microsoft Network chat client
+# Pattern attributes: good slow notsofast
+# Protocol groups: chat proprietary
+# Wiki: http://www.protocolinfo.org/wiki/MSN_Messenger
+# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
+#
+# Usually uses TCP port 1863
+# http://www.hypothetic.org/docs/msn/index.php
+# http://msnpiki.msnfanatic.com/
+#
+# This pattern has been tested and is believed to work well.
+
+msnmessenger
+
+# First branch: login
+# ver: allow versions up to 99.
+# I've never seen a cvr other than cvr0. Maybe this will be trouble later?
+# Can't anchor at the beginning because sometimes this is encapsulated in
+# HTTP. But either way, the first packet ends like this.
+# Second/Third branches: accepting/sending a message
+# I will assume that these can also be encapsulated in HTTP, although I have
+# not checked. Example of each direction:
+# ANS 1 quadong@hotmail.com 1139803431.29427 17522047
+# USR 1 quadong@hotmail.com 530423708.968145.366138
+
+# Branches are written entirely separately for better performance.
+ver [0-9]+ msnp[1-9][0-9]? [\x09-\x0d -~]*cvr0\x0d\x0a$|usr 1 [!-~]+ [0-9. ]+\x0d\x0a$|ans 1 [!-~]+ [0-9. ]+\x0d\x0a$
+
diff --git a/package/iptables/files/l7/ntp.pat b/package/iptables/files/l7/ntp.pat
new file mode 100644
index 000000000..760cfdbe5
--- /dev/null
+++ b/package/iptables/files/l7/ntp.pat
@@ -0,0 +1,17 @@
+# (S)NTP - (Simple) Network Time Protocol - RFCs 1305 and 2030
+# Pattern attributes: good fast fast overmatch
+# Protocol groups: time_synchronization ietf_draft_standard
+# Wiki: http://www.protocolinfo.org/wiki/NTP
+# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
+#
+# This pattern is tested and is believed to work.
+
+# client|server
+# Requires the server's timestamp to be in the present or future (of 2005).
+# Tested with ntpdate on Linux.
+# Assumes version 2, 3 or 4.
+
+# Note that ntp packets are always 48 bytes, so you should match on that too.
+
+ntp
+^([\x13\x1b\x23\xd3\xdb\xe3]|[\x14\x1c$].......?.?.?.?.?.?.?.?.?[\xc6-\xff])
diff --git a/package/iptables/files/l7/pop3.pat b/package/iptables/files/l7/pop3.pat
new file mode 100644
index 000000000..3ae4c147b
--- /dev/null
+++ b/package/iptables/files/l7/pop3.pat
@@ -0,0 +1,50 @@
+# POP3 - Post Office Protocol version 3 (popular e-mail protocol) - RFC 1939
+# Pattern attributes: great veryfast fast
+# Protocol groups: mail ietf_internet_standard
+# Wiki: http://www.protocolinfo.org/wiki/POP
+# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
+#
+# This pattern has been tested somewhat.
+
+# this is a difficult protocol to match because of the relative lack of
+# distinguishing information. Read on.
+pop3
+
+# this the most conservative pattern. It should definitely work.
+#^(\+ok|-err)
+
+# this pattern assumes that the server says _something_ after +ok or -err
+# I think this is probably the way to go.
+^(\+ok |-err )
+
+# more that 90% of servers seem to say "pop" after "+ok", but not all.
+#^(\+ok .*pop)
+
+# Here's another tack. I think this is my second favorite.
+#^(\+ok [\x09-\x0d -~]*(ready|hello|pop|starting)|-err [\x09-\x0d -~]*(invalid|unknown|unimplemented|unrecognized|command))
+
+# this matches the server saying "you have N messages that are M bytes",
+# which the client probably asks for early in the session (not tested)
+#\+ok [0-9]+ [0-9]+
+
+# some sample servers:
+# RFC example: +OK POP3 server ready <1896.697170952@dbc.mtview.ca.us>
+# mail.dreamhost.com: +OK Hello there.
+# pop.carleton.edu: +OK POP3D(*) Server PMDFV6.2.2 at Fri, 12 Sep 2003 19:28:10 -0500 (CDT) (APOP disabled)
+# mail.earthlink.net: +OK NGPopper vEL_4_38 at earthlink.net ready <25509.1063412951@falcon>
+# *.email.umn.edu: +OK Cubic Circle's v1.22 1998/04/11 POP3 ready <7d1e0000da67623f@aquamarine.tc.umn.edu>
+# mail.yale.edu: +OK POP3 pantheon-po01 v2002.81 server ready
+# mail.gustavus.edu: +OK POP3 solen v2001.78 server ready
+# mail.reed.edu: +OK POP3 letra.reed.edu v2002.81 server ready
+# mail.bowdoin.edu: +OK mail.bowdoin.edu POP3 service (iPlanet Messaging Server 5.2 HotFix 1.15 (built Apr 28 2003))
+# pop.colby.edu: +OK Qpopper (version 4.0.5) at basalt starting.
+# mail.mac.com: +OK Netscape Messaging Multiplexor ready
+
+# various error strings:
+#-ERR Invalid command.
+#-ERR invalid command
+#-ERR unimplemented
+#-ERR Invalid command, try one of: USER name, PASS string, QUIT
+#-ERR Unknown AUTHORIZATION state command
+#-ERR Unrecognized command
+#-ERR Unknown command: "sadf'".
diff --git a/package/iptables/files/l7/smtp.pat b/package/iptables/files/l7/smtp.pat
new file mode 100644
index 000000000..2f5d1957f
--- /dev/null
+++ b/package/iptables/files/l7/smtp.pat
@@ -0,0 +1,40 @@
+# SMTP - Simple Mail Transfer Protocol - RFC 2821 (See also RFC 1869)
+# Pattern attributes: great notsofast fast
+# Protocol groups: mail ietf_internet_standard
+# Wiki: http://www.protocolinfo.org/wiki/SMTP
+# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
+#
+# usually runs on port 25
+#
+# This pattern has been tested and is believed to work well.
+
+# As usual, no text is required after "220", but all known servers have some
+# there. It (almost?) always has string "smtp" in it. The RFC examples
+# does not, so we match those too, just in case anyone has copied them
+# literally.
+#
+# Some examples:
+# 220 mail.stalker.com ESMTP CommuniGate Pro 4.1.3
+# 220 mail.vieodata.com ESMTP Merak 6.1.0; Mon, 15 Sep 2003 13:48:11 -0400
+# 220 mail.ut.caldera.com ESMTP
+# 220 persephone.pmail.gen.nz ESMTP server ready.
+# 220 smtp1.superb.net ESMTP
+# 220 mail.kerio.com Kerio MailServer 5.6.7 ESMTP ready
+# 220-mail.deerfield.com ESMTP VisNetic.MailServer.v6.0.9.0; Mon, 15 Sep 2003 13:4
+# 220 altn.com ESMTP MDaemon 6.8.5; Mon, 15 Sep 2003 12:46:42 -0500
+# 220 X1 NT-ESMTP Server ipsmin0165atl2.interland.net (IMail 6.06 73062-3)
+# 220 mail.icewarp.com ESMTP Merak 6.1.1; Mon, 15 Sep 2003 19:43:23 +0200
+# 220-mail.email-scan.com ESMTP
+# 220 smaug.dreamhost.com ESMTP
+# 220 kona.carleton.edu -- Server ESMTP (PMDF V6.2#30648)
+# 220 letra.reed.edu ESMTP Sendmail 8.12.9/8.12.9; Mon, 15 Sep 2003 10:35:57 -0700 (PDT)
+# 220-swan.mail.pas.earthlink.net ESMTP Exim 3.33 #1 Mon, 15 Sep 2003 10:32:15 -0700
+#
+# RFC examples:
+# 220 xyz.com Simple Mail Transfer Service Ready (RFC example)
+# 220 dbc.mtview.ca.us SMTP service ready
+
+smtp
+^220[\x09-\x0d -~]* (e?smtp|simple mail)
+userspace pattern=^220[\x09-\x0d -~]* (E?SMTP|[Ss]imple [Mm]ail)
+userspace flags=REG_NOSUB REG_EXTENDED
diff --git a/package/iptables/files/l7/ssl.pat b/package/iptables/files/l7/ssl.pat
new file mode 100644
index 000000000..ae30ee440
--- /dev/null
+++ b/package/iptables/files/l7/ssl.pat
@@ -0,0 +1,16 @@
+# SSL and TLS - Secure Socket Layer / Transport Layer Security - RFC 2246
+# Pattern attributes: good notsofast fast superset
+# Protocol groups: secure ietf_proposed_standard
+# Wiki: http://www.protocolinfo.org/wiki/SSL
+# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
+#
+# Usually runs on port 443
+#
+# This is a superset of validcertssl. For it to match, it must be first.
+#
+# This pattern has been tested and is believed to work well.
+
+ssl
+# Server Hello with certificate | Client Hello
+# This allows SSL 3.X, which includes TLS 1.0, known internally as SSL 3.1
+^(.?.?\x16\x03.*\x16\x03|.?.?\x01\x03\x01?.*\x0b)
diff --git a/package/iptables/files/l7/vnc.pat b/package/iptables/files/l7/vnc.pat
new file mode 100644
index 000000000..79d0ae8a2
--- /dev/null
+++ b/package/iptables/files/l7/vnc.pat
@@ -0,0 +1,23 @@
+# VNC - Virtual Network Computing. Also known as RFB - Remote Frame Buffer
+# Pattern attributes: great veryfast fast
+# Protocol groups: remote_access
+# Wiki: http://www.protocolinfo.org/wiki/VNC
+# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
+#
+# http://www.realvnc.com/documentation.html
+#
+# This pattern has been verified with vnc v3.3.7 on WinXP and Linux
+#
+# Thanks to Trevor Paskett <tpaskett AT cymphonix.com> for this pattern.
+
+vnc
+# Assumes single digit major and minor version numbers
+# This message should be all alone in the first packet, so ^$ is appropriate
+^rfb 00[1-9]\.00[0-9]\x0a$
+
+# This is a more restrictive version which assumes the version numbers
+# are ones actually in existance at the time of this writing, i.e. 3.3,
+# 3.7 and 3.8 (with some clients wrongly reporting 3.5). It should be
+# slightly faster, but probably not worth the extra maintenance.
+# ^rfb 003\.00[3578]\x0a$
+
diff --git a/package/iptables/patches/002-layer7_2.22.patch b/package/iptables/patches/002-layer7_2.22.patch
new file mode 100644
index 000000000..ba4531e3f
--- /dev/null
+++ b/package/iptables/patches/002-layer7_2.22.patch
@@ -0,0 +1,371 @@
+--- /dev/null
++++ b/extensions/libxt_layer7.c
+@@ -0,0 +1,368 @@
++/*
++ Shared library add-on to iptables for layer 7 matching support.
++
++ By Matthew Strait <quadong@users.sf.net>, Oct 2003-Aug 2008.
++
++ http://l7-filter.sf.net
++
++ This program is free software; you can redistribute it and/or
++ modify it under the terms of the GNU General Public License
++ as published by the Free Software Foundation; either version
++ 2 of the License, or (at your option) any later version.
++ http://www.gnu.org/licenses/gpl.txt
++*/
++
++#define _GNU_SOURCE
++#include <stdio.h>
++#include <netdb.h>
++#include <string.h>
++#include <stdlib.h>
++#include <getopt.h>
++#include <ctype.h>
++#include <dirent.h>
++
++#include <xtables.h>
++#include <linux/netfilter/xt_layer7.h>
++
++#define MAX_FN_LEN 256
++
++static char l7dir[MAX_FN_LEN] = "\0";
++
++/* Function which prints out usage message. */
++static void help(void)
++{
++ printf(
++ "layer7 match options:\n"
++ " --l7dir <directory> : Look for patterns here instead of /etc/l7-protocols/\n"
++ " (--l7dir must be specified before --l7proto if used)\n"
++ "[!] --l7proto <name>: Match named protocol using /etc/l7-protocols/.../name.pat\n");
++}
++
++static const struct option opts[] = {
++ { .name = "l7proto", .has_arg = 1, .val = 'p' },
++ { .name = "l7dir", .has_arg = 1, .val = 'd' },
++ { .name = NULL }
++};
++
++/* reads filename, puts protocol info into layer7_protocol_info, number of protocols to numprotos */
++static int parse_protocol_file(char * filename, const char * protoname, struct xt_layer7_info *info)
++{
++ FILE * f;
++ char * line = NULL;
++ size_t len = 0;
++
++ enum { protocol, pattern, done } datatype = protocol;
++
++ f = fopen(filename, "r");
++
++ if(!f)
++ return 0;
++
++ while(getline(&line, &len, f) != -1)
++ {
++ if(strlen(line) < 2 || line[0] == '#')
++ continue;
++
++ /* strip the pesky newline... */
++ if(line[strlen(line) - 1] == '\n')
++ line[strlen(line) - 1] = '\0';
++
++ if(datatype == protocol)
++ {
++ /* Ignore everything on the line beginning with the
++ first space or tab . For instance, this allows the
++ protocol line in http.pat to be "http " (or
++ "http I am so cool") instead of just "http". */
++ if(strchr(line, ' ')){
++ char * space = strchr(line, ' ');
++ space[0] = '\0';
++ }
++ if(strchr(line, '\t')){
++ char * space = strchr(line, '\t');
++ space[0] = '\0';
++ }
++
++ /* sanity check. First non-comment non-blank
++ line must be the same as the file name. */
++ if(strcmp(line, protoname))
++ xtables_error(OTHER_PROBLEM,
++ "Protocol name (%s) doesn't match file name (%s). Bailing out\n",
++ line, filename);
++
++ if(strlen(line) >= MAX_PROTOCOL_LEN)
++ xtables_error(PARAMETER_PROBLEM,
++ "Protocol name in %s too long!", filename);
++ strncpy(info->protocol, line, MAX_PROTOCOL_LEN);
++
++ datatype = pattern;
++ }
++ else if(datatype == pattern)
++ {
++ if(strlen(line) >= MAX_PATTERN_LEN)
++ xtables_error(PARAMETER_PROBLEM, "Pattern in %s too long!", filename);
++ strncpy(info->pattern, line, MAX_PATTERN_LEN);
++
++ datatype = done;
++ break;
++ }
++ else
++ xtables_error(OTHER_PROBLEM, "Internal error");
++ }
++
++ if(datatype != done)
++ xtables_error(OTHER_PROBLEM, "Failed to get all needed data from %s", filename);
++
++ if(line) free(line);
++ fclose(f);
++
++ return 1;
++}
++
++static int hex2dec(char c)
++{
++ switch (c)
++ {
++ case '0' ... '9':
++ return c - '0';
++ case 'a' ... 'f':
++ return c - 'a' + 10;
++ case 'A' ... 'F':
++ return c - 'A' + 10;
++ default:
++ xtables_error(OTHER_PROBLEM, "hex2dec: bad value!\n");
++ return 0;
++ }
++}
++
++/* takes a string with \xHH escapes and returns one with the characters
++they stand for */
++static char * pre_process(char * s)
++{
++ char * result = malloc(strlen(s) + 1);
++ int sindex = 0, rrindex = 0;
++ while( sindex < strlen(s) )
++ {
++ if( sindex + 3 < strlen(s) &&
++ s[sindex] == '\\' && s[sindex+1] == 'x' &&
++ isxdigit(s[sindex + 2]) && isxdigit(s[sindex + 3]) )
++ {
++ /* carefully remember to call tolower here... */
++ result[rrindex] = tolower( hex2dec(s[sindex + 2])*16 +
++ hex2dec(s[sindex + 3] ) );
++
++ switch ( result[rrindex] )
++ {
++ case 0x24:
++ case 0x28:
++ case 0x29:
++ case 0x2a:
++ case 0x2b:
++ case 0x2e:
++ case 0x3f:
++ case 0x5b:
++ case 0x5c:
++ case 0x5d:
++ case 0x5e:
++ case 0x7c:
++ fprintf(stderr,
++ "Warning: layer7 regexp contains a control character, %c, in hex (\\x%c%c).\n"
++ "I recommend that you write this as %c or \\%c, depending on what you meant.\n",
++ result[rrindex], s[sindex + 2], s[sindex + 3], result[rrindex], result[rrindex]);
++ break;
++ case 0x00:
++ fprintf(stderr,
++ "Warning: null (\\x00) in layer7 regexp. A null terminates the regexp string!\n");
++ break;
++ default:
++ break;
++ }
++
++
++ sindex += 3; /* 4 total */
++ }
++ else
++ result[rrindex] = tolower(s[sindex]);
++
++ sindex++;
++ rrindex++;
++ }
++ result[rrindex] = '\0';
++
++ return result;
++}
++
++#define MAX_SUBDIRS 128
++static char ** readl7dir(char * dirname)
++{
++ DIR * scratchdir;
++ struct dirent ** namelist;
++ char ** subdirs = malloc(MAX_SUBDIRS * sizeof(char *));
++
++ int n, d = 1;
++ subdirs[0] = "";
++
++ n = scandir(dirname, &namelist, 0, alphasort);
++
++ if (n < 0)
++ {
++ perror("scandir");
++ xtables_error(OTHER_PROBLEM, "Couldn't open %s\n", dirname);
++ }
++ else
++ {
++ while(n--)
++ {
++ char fulldirname[MAX_FN_LEN];
++
++ snprintf(fulldirname, MAX_FN_LEN, "%s/%s", dirname, namelist[n]->d_name);
++
++ if((scratchdir = opendir(fulldirname)) != NULL)
++ {
++ closedir(scratchdir);
++
++ if(!strcmp(namelist[n]->d_name, ".") ||
++ !strcmp(namelist[n]->d_name, ".."))
++ /* do nothing */ ;
++ else
++ {
++ subdirs[d] = malloc(strlen(namelist[n]->d_name) + 1);
++ strcpy(subdirs[d], namelist[n]->d_name);
++ d++;
++ if(d >= MAX_SUBDIRS - 1)
++ {
++ fprintf(stderr,
++ "Too many subdirectories, skipping the rest!\n");
++ break;
++ }
++ }
++ }
++ free(namelist[n]);
++ }
++ free(namelist);
++ }
++
++ subdirs[d] = NULL;
++
++ return subdirs;
++}
++
++static void parse_layer7_protocol(const char *s, struct xt_layer7_info *info)
++{
++ char filename[MAX_FN_LEN];
++ char * dir = NULL;
++ char ** subdirs;
++ int n = 0, done = 0;
++
++ if(strlen(l7dir) > 0) dir = l7dir;
++ else dir = "/etc/l7-protocols";
++
++ subdirs = readl7dir(dir);
++
++ while(subdirs[n] != NULL)
++ {
++ int c = snprintf(filename, MAX_FN_LEN, "%s/%s/%s.pat", dir, subdirs[n], s);
++
++ if(c > MAX_FN_LEN)
++ xtables_error(OTHER_PROBLEM,
++ "Filename beginning with %s is too long!\n", filename);
++
++ /* read in the pattern from the file */
++ if(parse_protocol_file(filename, s, info)){
++ done = 1;
++ break;
++ }
++
++ n++;
++ }
++
++ if(!done)
++ xtables_error(OTHER_PROBLEM,
++ "Couldn't find a pattern definition file for %s.\n", s);
++
++ /* process \xHH escapes and tolower everything. (our regex lib has no
++ case insensitivity option.) */
++ strncpy(info->pattern, pre_process(info->pattern), MAX_PATTERN_LEN);
++}
++
++/* Function which parses command options; returns true if it ate an option */
++static int parse(int c, char **argv, int invert, unsigned int *flags,
++ const void *entry, struct xt_entry_match **match)
++{
++ struct xt_layer7_info *layer7info =
++ (struct xt_layer7_info *)(*match)->data;
++
++ switch (c) {
++ case 'p':
++ parse_layer7_protocol(argv[optind-1], layer7info);
++ if (invert)
++ layer7info->invert = true;
++ *flags = 1;
++ break;
++
++ case 'd':
++ if(strlen(argv[optind-1]) >= MAX_FN_LEN)
++ xtables_error(PARAMETER_PROBLEM, "directory name too long\n");
++
++ strncpy(l7dir, argv[optind-1], MAX_FN_LEN);
++
++ *flags = 1;
++ break;
++
++ default:
++ return 0;
++ }
++
++ return 1;
++}
++
++/* Final check; must have specified --l7proto */
++static void final_check(unsigned int flags)
++{
++ if (!flags)
++ xtables_error(PARAMETER_PROBLEM,
++ "LAYER7 match: You must specify `--l7proto'");
++}
++
++static void print_protocol(char s[], int invert, int numeric)
++{
++ fputs("l7proto ", stdout);
++ if (invert) fputc('!', stdout);
++ printf("%s ", s);
++}
++
++/* Prints out the matchinfo. */
++static void print(const void *ip,
++ const struct xt_entry_match *match,
++ int numeric)
++{
++ printf("LAYER7 ");
++ print_protocol(((struct xt_layer7_info *)match->data)->protocol,
++ ((struct xt_layer7_info *)match->data)->invert, numeric);
++}
++/* Saves the union ipt_matchinfo in parsable form to stdout. */
++static void save(const void *ip, const struct xt_entry_match *match)
++{
++ const struct xt_layer7_info *info =
++ (const struct xt_layer7_info*) match->data;
++
++ printf("--l7proto %s%s ", (info->invert)? "! ":"", info->protocol);
++}
++
++static struct xtables_match layer7 = {
++ .family = AF_INET,
++ .name = "layer7",
++ .version = XTABLES_VERSION,
++ .size = XT_ALIGN(sizeof(struct xt_layer7_info)),
++ .userspacesize = XT_ALIGN(sizeof(struct xt_layer7_info)),
++ .help = &help,
++ .parse = &parse,
++ .final_check = &final_check,
++ .print = &print,
++ .save = &save,
++ .extra_opts = opts
++};
++
++void _init(void)
++{
++ xtables_register_match(&layer7);
++}
diff --git a/package/iptables/patches/009-table-alignment.patch b/package/iptables/patches/009-table-alignment.patch
new file mode 100644
index 000000000..53012ab32
--- /dev/null
+++ b/package/iptables/patches/009-table-alignment.patch
@@ -0,0 +1,11 @@
+--- a/libiptc/libiptc.c
++++ b/libiptc/libiptc.c
+@@ -69,7 +69,7 @@ static const char *hooknames[] = {
+ struct ipt_error_target
+ {
+ STRUCT_ENTRY_TARGET t;
+- char error[TABLE_MAXNAMELEN];
++ char error[FUNCTION_MAXNAMELEN];
+ };
+
+ struct chain_head;
diff --git a/package/iptables/patches/010-multiport-linux-2.4-compat.patch b/package/iptables/patches/010-multiport-linux-2.4-compat.patch
new file mode 100644
index 000000000..3b35f7e3c
--- /dev/null
+++ b/package/iptables/patches/010-multiport-linux-2.4-compat.patch
@@ -0,0 +1,265 @@
+--- a/extensions/libxt_multiport.c
++++ b/extensions/libxt_multiport.c
+@@ -15,21 +15,6 @@
+ #include <linux/netfilter/xt_multiport.h>
+
+ /* Function which prints out usage message. */
+-static void multiport_help(void)
+-{
+- printf(
+-"multiport match options:\n"
+-" --source-ports port[,port,port...]\n"
+-" --sports ...\n"
+-" match source port(s)\n"
+-" --destination-ports port[,port,port...]\n"
+-" --dports ...\n"
+-" match destination port(s)\n"
+-" --ports port[,port,port]\n"
+-" match both source and destination port(s)\n"
+-" NOTE: this kernel does not support port ranges in multiport.\n");
+-}
+-
+ static void multiport_help_v1(void)
+ {
+ printf(
+@@ -72,26 +57,6 @@ proto_to_name(u_int8_t proto)
+ }
+ }
+
+-static unsigned int
+-parse_multi_ports(const char *portstring, u_int16_t *ports, const char *proto)
+-{
+- char *buffer, *cp, *next;
+- unsigned int i;
+-
+- buffer = strdup(portstring);
+- if (!buffer) xtables_error(OTHER_PROBLEM, "strdup failed");
+-
+- for (cp=buffer, i=0; cp && i<XT_MULTI_PORTS; cp=next,i++)
+- {
+- next=strchr(cp, ',');
+- if (next) *next++='\0';
+- ports[i] = xtables_parse_port(cp, proto);
+- }
+- if (cp) xtables_error(PARAMETER_PROBLEM, "too many ports specified");
+- free(buffer);
+- return i;
+-}
+-
+ static void
+ parse_multi_ports_v1(const char *portstring,
+ struct xt_multiport_v1 *multiinfo,
+@@ -155,73 +120,6 @@ check_proto(u_int16_t pnum, u_int8_t inv
+ /* Function which parses command options; returns true if it
+ ate an option */
+ static int
+-__multiport_parse(int c, char **argv, int invert, unsigned int *flags,
+- struct xt_entry_match **match, u_int16_t pnum,
+- u_int8_t invflags)
+-{
+- const char *proto;
+- struct xt_multiport *multiinfo
+- = (struct xt_multiport *)(*match)->data;
+-
+- switch (c) {
+- case '1':
+- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+- proto = check_proto(pnum, invflags);
+- multiinfo->count = parse_multi_ports(optarg,
+- multiinfo->ports, proto);
+- multiinfo->flags = XT_MULTIPORT_SOURCE;
+- break;
+-
+- case '2':
+- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+- proto = check_proto(pnum, invflags);
+- multiinfo->count = parse_multi_ports(optarg,
+- multiinfo->ports, proto);
+- multiinfo->flags = XT_MULTIPORT_DESTINATION;
+- break;
+-
+- case '3':
+- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+- proto = check_proto(pnum, invflags);
+- multiinfo->count = parse_multi_ports(optarg,
+- multiinfo->ports, proto);
+- multiinfo->flags = XT_MULTIPORT_EITHER;
+- break;
+-
+- default:
+- return 0;
+- }
+-
+- if (invert)
+- xtables_error(PARAMETER_PROBLEM,
+- "multiport does not support invert");
+-
+- if (*flags)
+- xtables_error(PARAMETER_PROBLEM,
+- "multiport can only have one option");
+- *flags = 1;
+- return 1;
+-}
+-
+-static int
+-multiport_parse(int c, char **argv, int invert, unsigned int *flags,
+- const void *e, struct xt_entry_match **match)
+-{
+- const struct ipt_entry *entry = e;
+- return __multiport_parse(c, argv, invert, flags, match,
+- entry->ip.proto, entry->ip.invflags);
+-}
+-
+-static int
+-multiport_parse6(int c, char **argv, int invert, unsigned int *flags,
+- const void *e, struct xt_entry_match **match)
+-{
+- const struct ip6t_entry *entry = e;
+- return __multiport_parse(c, argv, invert, flags, match,
+- entry->ipv6.proto, entry->ipv6.invflags);
+-}
+-
+-static int
+ __multiport_parse_v1(int c, char **argv, int invert, unsigned int *flags,
+ struct xt_entry_match **match, u_int16_t pnum,
+ u_int8_t invflags)
+@@ -314,55 +212,6 @@ print_port(u_int16_t port, u_int8_t prot
+ }
+
+ /* Prints out the matchinfo. */
+-static void
+-__multiport_print(const struct xt_entry_match *match, int numeric,
+- u_int16_t proto)
+-{
+- const struct xt_multiport *multiinfo
+- = (const struct xt_multiport *)match->data;
+- unsigned int i;
+-
+- printf("multiport ");
+-
+- switch (multiinfo->flags) {
+- case XT_MULTIPORT_SOURCE:
+- printf("sports ");
+- break;
+-
+- case XT_MULTIPORT_DESTINATION:
+- printf("dports ");
+- break;
+-
+- case XT_MULTIPORT_EITHER:
+- printf("ports ");
+- break;
+-
+- default:
+- printf("ERROR ");
+- break;
+- }
+-
+- for (i=0; i < multiinfo->count; i++) {
+- printf("%s", i ? "," : "");
+- print_port(multiinfo->ports[i], proto, numeric);
+- }
+- printf(" ");
+-}
+-
+-static void multiport_print(const void *ip_void,
+- const struct xt_entry_match *match, int numeric)
+-{
+- const struct ipt_ip *ip = ip_void;
+- __multiport_print(match, numeric, ip->proto);
+-}
+-
+-static void multiport_print6(const void *ip_void,
+- const struct xt_entry_match *match, int numeric)
+-{
+- const struct ip6t_ip6 *ip = ip_void;
+- __multiport_print(match, numeric, ip->proto);
+-}
+-
+ static void __multiport_print_v1(const struct xt_entry_match *match,
+ int numeric, u_int16_t proto)
+ {
+@@ -419,48 +268,6 @@ static void multiport_print6_v1(const vo
+ }
+
+ /* Saves the union ipt_matchinfo in parsable form to stdout. */
+-static void __multiport_save(const struct xt_entry_match *match,
+- u_int16_t proto)
+-{
+- const struct xt_multiport *multiinfo
+- = (const struct xt_multiport *)match->data;
+- unsigned int i;
+-
+- switch (multiinfo->flags) {
+- case XT_MULTIPORT_SOURCE:
+- printf("--sports ");
+- break;
+-
+- case XT_MULTIPORT_DESTINATION:
+- printf("--dports ");
+- break;
+-
+- case XT_MULTIPORT_EITHER:
+- printf("--ports ");
+- break;
+- }
+-
+- for (i=0; i < multiinfo->count; i++) {
+- printf("%s", i ? "," : "");
+- print_port(multiinfo->ports[i], proto, 1);
+- }
+- printf(" ");
+-}
+-
+-static void multiport_save(const void *ip_void,
+- const struct xt_entry_match *match)
+-{
+- const struct ipt_ip *ip = ip_void;
+- __multiport_save(match, ip->proto);
+-}
+-
+-static void multiport_save6(const void *ip_void,
+- const struct xt_entry_match *match)
+-{
+- const struct ip6t_ip6 *ip = ip_void;
+- __multiport_save(match, ip->proto);
+-}
+-
+ static void __multiport_save_v1(const struct xt_entry_match *match,
+ u_int16_t proto)
+ {
+@@ -514,34 +321,6 @@ static struct xtables_match multiport_mt
+ {
+ .family = NFPROTO_IPV4,
+ .name = "multiport",
+- .revision = 0,
+- .version = XTABLES_VERSION,
+- .size = XT_ALIGN(sizeof(struct xt_multiport)),
+- .userspacesize = XT_ALIGN(sizeof(struct xt_multiport)),
+- .help = multiport_help,
+- .parse = multiport_parse,
+- .final_check = multiport_check,
+- .print = multiport_print,
+- .save = multiport_save,
+- .extra_opts = multiport_opts,
+- },
+- {
+- .family = NFPROTO_IPV6,
+- .name = "multiport",
+- .revision = 0,
+- .version = XTABLES_VERSION,
+- .size = XT_ALIGN(sizeof(struct xt_multiport)),
+- .userspacesize = XT_ALIGN(sizeof(struct xt_multiport)),
+- .help = multiport_help,
+- .parse = multiport_parse6,
+- .final_check = multiport_check,
+- .print = multiport_print6,
+- .save = multiport_save6,
+- .extra_opts = multiport_opts,
+- },
+- {
+- .family = NFPROTO_IPV4,
+- .name = "multiport",
+ .version = XTABLES_VERSION,
+ .revision = 1,
+ .size = XT_ALIGN(sizeof(struct xt_multiport_v1)),
diff --git a/package/iptables/patches/011-recent-add-reap.patch b/package/iptables/patches/011-recent-add-reap.patch
new file mode 100644
index 000000000..275265b99
--- /dev/null
+++ b/package/iptables/patches/011-recent-add-reap.patch
@@ -0,0 +1,116 @@
+From 20c706d4cba3227c9c44fb61c4d93b0ae84e1464 Mon Sep 17 00:00:00 2001
+From: Tim Gardner <tim.gardner@canonical.com>
+Date: Mon, 1 Mar 2010 19:00:29 -0700
+Subject: [PATCH] xt_recent: Added XT_RECENT_REAP logic and man page documentation
+
+Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
+---
+ extensions/libxt_recent.c | 20 ++++++++++++++++++++
+ extensions/libxt_recent.man | 5 +++++
+ include/linux/netfilter/xt_recent.h | 7 +++++++
+ 3 files changed, 32 insertions(+), 0 deletions(-)
+
+--- a/extensions/libxt_recent.c
++++ b/extensions/libxt_recent.c
+@@ -20,6 +20,7 @@ static const struct option recent_opts[]
+ {.name = "name", .has_arg = true, .val = 208},
+ {.name = "rsource", .has_arg = false, .val = 209},
+ {.name = "rdest", .has_arg = false, .val = 210},
++ {.name = "reap", .has_arg = false, .val = 211},
+ XT_GETOPT_TABLEEND,
+ };
+
+@@ -37,6 +38,7 @@ static void recent_help(void)
+ " --hitcount hits For check and update commands above.\n"
+ " Specifies that the match will only occur if source address seen hits times.\n"
+ " May be used in conjunction with the seconds option.\n"
++" --reap Remove entries that have expired. Can only be used with --seconds\n"
+ " --rttl For check and update commands above.\n"
+ " Specifies that the match will only occur if the source address and the TTL\n"
+ " match between this packet and the one which was set.\n"
+@@ -63,6 +65,8 @@ static void recent_init(struct xt_entry_
+ (XT_RECENT_SET | XT_RECENT_CHECK | \
+ XT_RECENT_UPDATE | XT_RECENT_REMOVE)
+
++#define XT_RECENT_SECONDS 1 << 31
++
+ static int recent_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+ {
+@@ -104,6 +108,7 @@ static int recent_parse(int c, char **ar
+
+ case 204:
+ info->seconds = atoi(optarg);
++ *flags |= XT_RECENT_SECONDS;
+ break;
+
+ case 205:
+@@ -139,6 +144,11 @@ static int recent_parse(int c, char **ar
+ info->side = XT_RECENT_DEST;
+ break;
+
++ case 211:
++ info->check_set |= XT_RECENT_REAP;
++ *flags |= XT_RECENT_REAP;
++ break;
++
+ default:
+ return 0;
+ }
+@@ -157,6 +167,12 @@ static void recent_check(unsigned int fl
+ xtables_error(PARAMETER_PROBLEM,
+ "recent: --rttl may only be used with --rcheck or "
+ "--update");
++ if ((flags & XT_RECENT_REAP) &&
++ ((flags & (XT_RECENT_SET | XT_RECENT_REMOVE)) ||
++ (!(flags & XT_RECENT_SECONDS))))
++ xtables_error(PARAMETER_PROBLEM,
++ "recent: --reap may only be used with --rcheck or "
++ "--update and --seconds");
+ }
+
+ static void recent_print(const void *ip, const struct xt_entry_match *match,
+@@ -185,6 +201,8 @@ static void recent_print(const void *ip,
+ printf("side: source ");
+ if (info->side == XT_RECENT_DEST)
+ printf("side: dest ");
++ if (info->check_set & XT_RECENT_REAP)
++ printf("reap ");
+ }
+
+ static void recent_save(const void *ip, const struct xt_entry_match *match)
+@@ -211,6 +229,8 @@ static void recent_save(const void *ip,
+ printf("--rsource ");
+ if (info->side == XT_RECENT_DEST)
+ printf("--rdest ");
++ if (info->check_set & XT_RECENT_REAP)
++ printf("--reap ");
+ }
+
+ static struct xtables_match recent_mt_reg = {
+--- a/extensions/libxt_recent.man
++++ b/extensions/libxt_recent.man
+@@ -41,6 +41,11 @@ This option must be used in conjunction
+ \fB\-\-update\fP. When used, this will narrow the match to only happen when the
+ address is in the list and was seen within the last given number of seconds.
+ .TP
++\fB\-\-reap\fP \fIreap\fP
++This option must be used in conjunction with \fB\-\-seconds\fP. When used, this
++will remove entries with the most recent timestamp older then \fB\-\-seconds\fP
++since the last packet was received.
++.TP
+ \fB\-\-hitcount\fP \fIhits\fP
+ This option must be used in conjunction with one of \fB\-\-rcheck\fP or
+ \fB\-\-update\fP. When used, this will narrow the match to only happen when the
+--- a/include/linux/netfilter/xt_recent.h
++++ b/include/linux/netfilter/xt_recent.h
+@@ -23,6 +23,9 @@ enum {
+ #define XT_RECENT_VALID_FLAGS (XT_RECENT_CHECK|XT_RECENT_SET|XT_RECENT_UPDATE|\
+ XT_RECENT_REMOVE|XT_RECENT_TTL|XT_RECENT_REAP)
+
++/* Only allowed with --rcheck and --update */
++#define XT_RECENT_MODIFIERS (XT_RECENT_TTL|XT_RECENT_REAP)
++
+ struct xt_recent_mtinfo {
+ __u32 seconds;
+ __u32 hit_count;
diff --git a/package/iptables/patches/020-iptables-disable-modprobe.patch b/package/iptables/patches/020-iptables-disable-modprobe.patch
new file mode 100644
index 000000000..338962ffb
--- /dev/null
+++ b/package/iptables/patches/020-iptables-disable-modprobe.patch
@@ -0,0 +1,18 @@
+--- a/xtables.c
++++ b/xtables.c
+@@ -305,6 +305,7 @@ static char *get_modprobe(void)
+
+ int xtables_insmod(const char *modname, const char *modprobe, bool quiet)
+ {
++#if 0
+ char *buf = NULL;
+ char *argv[4];
+ int status;
+@@ -348,6 +349,7 @@ int xtables_insmod(const char *modname,
+ free(buf);
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
+ return 0;
++#endif
+ return -1;
+ }
+
diff --git a/package/iptables/patches/030-no-libnfnetlink.patch b/package/iptables/patches/030-no-libnfnetlink.patch
new file mode 100644
index 000000000..cda9a7205
--- /dev/null
+++ b/package/iptables/patches/030-no-libnfnetlink.patch
@@ -0,0 +1,92 @@
+--- a/configure
++++ b/configure
+@@ -10917,75 +10917,7 @@ $as_echo "no" >&6; }
+ fi
+ fi
+
+-pkg_failed=no
+-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libnfnetlink" >&5
+-$as_echo_n "checking for libnfnetlink... " >&6; }
+-
+-if test -n "$libnfnetlink_CFLAGS"; then
+- pkg_cv_libnfnetlink_CFLAGS="$libnfnetlink_CFLAGS"
+- elif test -n "$PKG_CONFIG"; then
+- if test -n "$PKG_CONFIG" && \
+- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnfnetlink >= 1.0\""; } >&5
+- ($PKG_CONFIG --exists --print-errors "libnfnetlink >= 1.0") 2>&5
+- ac_status=$?
+- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+- test $ac_status = 0; }; then
+- pkg_cv_libnfnetlink_CFLAGS=`$PKG_CONFIG --cflags "libnfnetlink >= 1.0" 2>/dev/null`
+-else
+- pkg_failed=yes
+-fi
+- else
+- pkg_failed=untried
+-fi
+-if test -n "$libnfnetlink_LIBS"; then
+- pkg_cv_libnfnetlink_LIBS="$libnfnetlink_LIBS"
+- elif test -n "$PKG_CONFIG"; then
+- if test -n "$PKG_CONFIG" && \
+- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnfnetlink >= 1.0\""; } >&5
+- ($PKG_CONFIG --exists --print-errors "libnfnetlink >= 1.0") 2>&5
+- ac_status=$?
+- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+- test $ac_status = 0; }; then
+- pkg_cv_libnfnetlink_LIBS=`$PKG_CONFIG --libs "libnfnetlink >= 1.0" 2>/dev/null`
+-else
+- pkg_failed=yes
+-fi
+- else
+- pkg_failed=untried
+-fi
+-
+-
+-
+-if test $pkg_failed = yes; then
+- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-$as_echo "no" >&6; }
+-
+-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+- _pkg_short_errors_supported=yes
+-else
+- _pkg_short_errors_supported=no
+-fi
+- if test $_pkg_short_errors_supported = yes; then
+- libnfnetlink_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libnfnetlink >= 1.0" 2>&1`
+- else
+- libnfnetlink_PKG_ERRORS=`$PKG_CONFIG --print-errors "libnfnetlink >= 1.0" 2>&1`
+- fi
+- # Put the nasty error message in config.log where it belongs
+- echo "$libnfnetlink_PKG_ERRORS" >&5
+-
+- nfnetlink=0
+-elif test $pkg_failed = untried; then
+- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-$as_echo "no" >&6; }
+- nfnetlink=0
+-else
+- libnfnetlink_CFLAGS=$pkg_cv_libnfnetlink_CFLAGS
+- libnfnetlink_LIBS=$pkg_cv_libnfnetlink_LIBS
+- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+-$as_echo "yes" >&6; }
+- nfnetlink=1
+-fi
+- if test "$nfnetlink" = 1; then
++if false; then
+ HAVE_LIBNFNETLINK_TRUE=
+ HAVE_LIBNFNETLINK_FALSE='#'
+ else
+--- a/configure.ac
++++ b/configure.ac
+@@ -79,9 +79,7 @@ AM_CONDITIONAL([ENABLE_LARGEFILE], [test
+ AM_CONDITIONAL([ENABLE_DEVEL], [test "$enable_devel" = "yes"])
+ AM_CONDITIONAL([ENABLE_LIBIPQ], [test "$enable_libipq" = "yes"])
+
+-PKG_CHECK_MODULES([libnfnetlink], [libnfnetlink >= 1.0],
+- [nfnetlink=1], [nfnetlink=0])
+-AM_CONDITIONAL([HAVE_LIBNFNETLINK], [test "$nfnetlink" = 1])
++AM_CONDITIONAL([HAVE_LIBNFNETLINK], [false])
+
+ regular_CFLAGS="${largefile_cflags} \
+ -D_REENTRANT -Wall -Waggregate-return -Wmissing-declarations \
diff --git a/package/iptables/patches/100-bash-location.patch b/package/iptables/patches/100-bash-location.patch
new file mode 100644
index 000000000..818246e76
--- /dev/null
+++ b/package/iptables/patches/100-bash-location.patch
@@ -0,0 +1,16 @@
+--- a/autogen.sh
++++ b/autogen.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+
+ autoreconf -fi;
+ rm -Rf autom4te*.cache;
+--- a/iptables-apply
++++ b/iptables-apply
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # iptables-apply -- a safer way to update iptables remotely
+ #
diff --git a/package/iptables/patches/110-linux_3.2_compat.patch b/package/iptables/patches/110-linux_3.2_compat.patch
new file mode 100644
index 000000000..2cdd673d2
--- /dev/null
+++ b/package/iptables/patches/110-linux_3.2_compat.patch
@@ -0,0 +1,12 @@
+--- iptables-1.4.10/include/linux/types.h.orig 2011-11-07 00:08:33.000000000 +0100
++++ iptables-1.4.10/include/linux/types.h 2011-11-07 00:09:25.000000000 +0100
+@@ -34,5 +34,9 @@
+ typedef __u16 __bitwise __sum16;
+ typedef __u32 __bitwise __wsum;
+
++#define __aligned_u64 __u64 __attribute__((aligned(8)))
++#define __aligned_be64 __be64 __attribute__((aligned(8)))
++#define __aligned_le64 __le64 __attribute__((aligned(8)))
++
+ #endif /* __ASSEMBLY__ */
+ #endif /* _LINUX_TYPES_H */
diff --git a/package/iptables/patches/200-configurable_builtin.patch b/package/iptables/patches/200-configurable_builtin.patch
new file mode 100644
index 000000000..9f9cc387c
--- /dev/null
+++ b/package/iptables/patches/200-configurable_builtin.patch
@@ -0,0 +1,56 @@
+--- a/extensions/GNUmakefile.in
++++ b/extensions/GNUmakefile.in
+@@ -40,9 +40,24 @@
+ pfx_build_mod := $(filter-out @blacklist_modules@,${pfx_build_mod})
+ pf4_build_mod := $(filter-out @blacklist_modules@,${pf4_build_mod})
+ pf6_build_mod := $(filter-out @blacklist_modules@,${pf6_build_mod})
+-pfx_objs := $(patsubst %,libxt_%.o,${pfx_build_mod})
+-pf4_objs := $(patsubst %,libipt_%.o,${pf4_build_mod})
+-pf6_objs := $(patsubst %,libip6t_%.o,${pf6_build_mod})
++
++ifdef BUILTIN_MODULES
++pfx_build_static := $(filter $(BUILTIN_MODULES),${pfx_build_mod})
++pf4_build_static := $(filter $(BUILTIN_MODULES),${pf4_build_mod})
++pf6_build_static := $(filter $(BUILTIN_MODULES),${pf6_build_mod})
++else
++@ENABLE_STATIC_TRUE@ pfx_build_static := $(pfx_build_mod)
++@ENABLE_STATIC_TRUE@ pf4_build_static := $(pf4_build_mod)
++@ENABLE_STATIC_TRUE@ pf6_build_static := $(pf6_build_mod)
++endif
++
++pfx_build_mod := $(filter-out $(pfx_build_static),$(pfx_build_mod))
++pf4_build_mod := $(filter-out $(pf4_build_static),$(pf4_build_mod))
++pf6_build_mod := $(filter-out $(pf6_build_static),$(pf6_build_mod))
++
++pfx_objs := $(patsubst %,libxt_%.o,${pfx_build_static})
++pf4_objs := $(patsubst %,libipt_%.o,${pf4_build_static})
++pf6_objs := $(patsubst %,libip6t_%.o,${pf6_build_static})
+ pfx_solibs := $(patsubst %,libxt_%.so,${pfx_build_mod})
+ pf4_solibs := $(patsubst %,libipt_%.so,${pf4_build_mod})
+ pf6_solibs := $(patsubst %,libip6t_%.so,${pf6_build_mod})
+@@ -54,10 +69,10 @@
+ targets := libext4.a libext6.a matches4.man matches6.man \
+ targets4.man targets6.man
+ targets_install :=
+-@ENABLE_STATIC_TRUE@ libext4_objs := ${pfx_objs} ${pf4_objs}
+-@ENABLE_STATIC_TRUE@ libext6_objs := ${pfx_objs} ${pf6_objs}
+-@ENABLE_STATIC_FALSE@ targets += ${pfx_solibs} ${pf4_solibs} ${pf6_solibs}
+-@ENABLE_STATIC_FALSE@ targets_install += ${pfx_solibs} ${pf4_solibs} ${pf6_solibs}
++libext4_objs := ${pfx_objs} ${pf4_objs}
++libext6_objs := ${pfx_objs} ${pf6_objs}
++targets += ${pfx_solibs} ${pf4_solibs} ${pf6_solibs}
++targets_install := $(strip ${targets_install} ${pfx_solibs} ${pf4_solibs} ${pf6_solibs})
+
+ .SECONDARY:
+
+@@ -107,8 +122,8 @@
+ libext6.a: initext6.o ${libext6_objs}
+ ${AM_VERBOSE_AR} ${AR} crs $@ $^;
+
+-initext_func := $(addprefix xt_,${pfx_build_mod}) $(addprefix ipt_,${pf4_build_mod})
+-initext6_func := $(addprefix xt_,${pfx_build_mod}) $(addprefix ip6t_,${pf6_build_mod})
++initext_func := $(addprefix xt_,${pfx_build_static}) $(addprefix ipt_,${pf4_build_static})
++initext6_func := $(addprefix xt_,${pfx_build_static}) $(addprefix ip6t_,${pf6_build_static})
+
+ .initext4.dd: FORCE
+ @echo "${initext_func}" >$@.tmp; \
diff --git a/package/iw/Makefile b/package/iw/Makefile
new file mode 100644
index 000000000..f47d76b17
--- /dev/null
+++ b/package/iw/Makefile
@@ -0,0 +1,54 @@
+#
+# Copyright (C) 2007-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=iw
+PKG_VERSION:=3.6
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://wireless.kernel.org/download/iw/
+PKG_MD5SUM:=1c18bfbbc8773629e5e8ac733a39540c
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/iw
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=cfg80211 interface configuration utility
+ URL:=http://wireless.kernel.org/en/users/Documentation/iw
+ DEPENDS:= +libnl-tiny @(!(TARGET_avr32||TARGET_etrax)||BROKEN)
+endef
+
+define Build/Configure
+ echo "const char iw_version[] = \"$(PKG_VERSION)\";" > $(PKG_BUILD_DIR)/version.c
+ rm -f $(PKG_BUILD_DIR)/version.sh
+ touch $(PKG_BUILD_DIR)/version.sh
+ chmod +x $(PKG_BUILD_DIR)/version.sh
+endef
+
+TARGET_CPPFLAGS:= \
+ -I$(STAGING_DIR)/usr/include/libnl-tiny \
+ $(TARGET_CPPFLAGS) \
+ -DCONFIG_LIBNL20 \
+ -D_GNU_SOURCE
+
+MAKE_FLAGS += \
+ CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \
+ LDFLAGS="$(TARGET_LDFLAGS)" \
+ NL1FOUND="" NL2FOUND=Y \
+ NLLIBNAME="libnl-tiny" \
+ LIBS="-lm -lnl-tiny" \
+ V=1
+
+define Package/iw/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/iw $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,iw))
diff --git a/package/iw/patches/001-nl80211_h_sync.patch b/package/iw/patches/001-nl80211_h_sync.patch
new file mode 100644
index 000000000..8e776643b
--- /dev/null
+++ b/package/iw/patches/001-nl80211_h_sync.patch
@@ -0,0 +1,96 @@
+--- a/nl80211.h
++++ b/nl80211.h
+@@ -565,6 +565,14 @@
+ * %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ with
+ * %NL80211_ATTR_WIPHY_CHANNEL_TYPE.
+ *
++ * @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by
++ * its %NL80211_ATTR_WDEV identifier. It must have been created with
++ * %NL80211_CMD_NEW_INTERFACE previously. After it has been started, the
++ * P2P Device can be used for P2P operations, e.g. remain-on-channel and
++ * public action frame TX.
++ * @NL80211_CMD_STOP_P2P_DEVICE: Stop the given P2P Device, identified by
++ * its %NL80211_ATTR_WDEV identifier.
++ *
+ * @NL80211_CMD_MAX: highest used command number
+ * @__NL80211_CMD_AFTER_LAST: internal use
+ */
+@@ -708,6 +716,9 @@ enum nl80211_commands {
+
+ NL80211_CMD_CH_SWITCH_NOTIFY,
+
++ NL80211_CMD_START_P2P_DEVICE,
++ NL80211_CMD_STOP_P2P_DEVICE,
++
+ /* add new commands above here */
+
+ /* used to define NL80211_CMD_MAX below */
+@@ -1506,6 +1517,8 @@ enum nl80211_attrs {
+
+ NL80211_ATTR_USER_REG_HINT_TYPE,
+
++ NL80211_ATTR_WIPHY_ANTENNA_GAIN,
++
+ /* add attributes here, update the policy in nl80211.c */
+
+ __NL80211_ATTR_AFTER_LAST,
+@@ -1575,6 +1588,10 @@ enum nl80211_attrs {
+ * @NL80211_IFTYPE_MESH_POINT: mesh point
+ * @NL80211_IFTYPE_P2P_CLIENT: P2P client
+ * @NL80211_IFTYPE_P2P_GO: P2P group owner
++ * @NL80211_IFTYPE_P2P_DEVICE: P2P device interface type, this is not a netdev
++ * and therefore can't be created in the normal ways, use the
++ * %NL80211_CMD_START_P2P_DEVICE and %NL80211_CMD_STOP_P2P_DEVICE
++ * commands to create and destroy one
+ * @NL80211_IFTYPE_MAX: highest interface type number currently defined
+ * @NUM_NL80211_IFTYPES: number of defined interface types
+ *
+@@ -1593,6 +1610,7 @@ enum nl80211_iftype {
+ NL80211_IFTYPE_MESH_POINT,
+ NL80211_IFTYPE_P2P_CLIENT,
+ NL80211_IFTYPE_P2P_GO,
++ NL80211_IFTYPE_P2P_DEVICE,
+
+ /* keep last */
+ NUM_NL80211_IFTYPES,
+@@ -1744,6 +1762,8 @@ enum nl80211_sta_bss_param {
+ * @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update.
+ * @NL80211_STA_INFO_BEACON_LOSS: count of times beacon loss was detected (u32)
+ * @NL80211_STA_INFO_T_OFFSET: timing offset with respect to this STA (s64)
++ * @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU
++ * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average
+ * @__NL80211_STA_INFO_AFTER_LAST: internal
+ * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ */
+@@ -1768,6 +1788,8 @@ enum nl80211_sta_info {
+ NL80211_STA_INFO_STA_FLAGS,
+ NL80211_STA_INFO_BEACON_LOSS,
+ NL80211_STA_INFO_T_OFFSET,
++ NL80211_STA_INFO_CHAIN_SIGNAL,
++ NL80211_STA_INFO_CHAIN_SIGNAL_AVG,
+
+ /* keep last */
+ __NL80211_STA_INFO_AFTER_LAST,
+@@ -2994,12 +3016,18 @@ enum nl80211_ap_sme_features {
+ * @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested
+ * to work properly to suppport receiving regulatory hints from
+ * cellular base stations.
++ * @NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: If this is set, an active
++ * P2P Device (%NL80211_IFTYPE_P2P_DEVICE) requires its own channel
++ * in the interface combinations, even when it's only used for scan
++ * and remain-on-channel. This could be due to, for example, the
++ * remain-on-channel implementation requiring a channel context.
+ */
+ enum nl80211_feature_flags {
+- NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
+- NL80211_FEATURE_HT_IBSS = 1 << 1,
+- NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2,
+- NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3,
++ NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
++ NL80211_FEATURE_HT_IBSS = 1 << 1,
++ NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2,
++ NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3,
++ NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL = 1 << 4,
+ };
+
+ /**
diff --git a/package/iw/patches/100-rx_rate.patch b/package/iw/patches/100-rx_rate.patch
new file mode 100644
index 000000000..642b9f357
--- /dev/null
+++ b/package/iw/patches/100-rx_rate.patch
@@ -0,0 +1,105 @@
+--- a/station.c
++++ b/station.c
+@@ -29,13 +29,47 @@ enum plink_actions {
+ PLINK_ACTION_BLOCK,
+ };
+
++static void print_sta_bitrate(struct nlattr *nla, const char *name)
++{
++ struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
++
++ static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
++ [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
++ [NL80211_RATE_INFO_BITRATE32] = { .type = NLA_U32 },
++ [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
++ [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
++ [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
++ };
++
++ if (!nla)
++ return;
++
++ if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, nla, rate_policy)) {
++ fprintf(stderr, "failed to parse nested rate attributes!\n");
++ } else {
++ int rate = 0;
++ printf("\n\t%s:\t", name);
++ if (rinfo[NL80211_RATE_INFO_BITRATE32])
++ rate = nla_get_u32(rinfo[NL80211_RATE_INFO_BITRATE32]);
++ else if (rinfo[NL80211_RATE_INFO_BITRATE])
++ rate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
++ if (rate > 0)
++ printf("%d.%d MBit/s", rate / 10, rate % 10);
++
++ if (rinfo[NL80211_RATE_INFO_MCS])
++ printf(" MCS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]));
++ if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
++ printf(" 40Mhz");
++ if (rinfo[NL80211_RATE_INFO_SHORT_GI])
++ printf(" short GI");
++ }
++}
+
+ static int print_sta_handler(struct nl_msg *msg, void *arg)
+ {
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
+- struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
+ char mac_addr[20], state_name[10], dev[20];
+ struct nl80211_sta_flag_update *sta_flags;
+ static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
+@@ -47,6 +81,7 @@ static int print_sta_handler(struct nl_m
+ [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
+ [NL80211_STA_INFO_T_OFFSET] = { .type = NLA_U64 },
+ [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
++ [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
+ [NL80211_STA_INFO_LLID] = { .type = NLA_U16 },
+ [NL80211_STA_INFO_PLID] = { .type = NLA_U16 },
+ [NL80211_STA_INFO_PLINK_STATE] = { .type = NLA_U8 },
+@@ -56,14 +91,6 @@ static int print_sta_handler(struct nl_m
+ { .minlen = sizeof(struct nl80211_sta_flag_update) },
+ };
+
+- static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
+- [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
+- [NL80211_RATE_INFO_BITRATE32] = { .type = NLA_U32 },
+- [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
+- [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
+- [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
+- };
+-
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+@@ -119,28 +146,8 @@ static int print_sta_handler(struct nl_m
+ printf("\n\tToffset:\t%lld us",
+ (unsigned long long)nla_get_u64(sinfo[NL80211_STA_INFO_T_OFFSET]));
+
+- if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
+- if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
+- sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
+- fprintf(stderr, "failed to parse nested rate attributes!\n");
+- } else {
+- int rate = 0;
+- printf("\n\ttx bitrate:\t");
+- if (rinfo[NL80211_RATE_INFO_BITRATE32])
+- rate = nla_get_u32(rinfo[NL80211_RATE_INFO_BITRATE32]);
+- else if (rinfo[NL80211_RATE_INFO_BITRATE])
+- rate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
+- if (rate > 0)
+- printf("%d.%d MBit/s", rate / 10, rate % 10);
+-
+- if (rinfo[NL80211_RATE_INFO_MCS])
+- printf(" MCS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]));
+- if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
+- printf(" 40Mhz");
+- if (rinfo[NL80211_RATE_INFO_SHORT_GI])
+- printf(" short GI");
+- }
+- }
++ print_sta_bitrate(sinfo[NL80211_STA_INFO_TX_BITRATE], "tx bitrate");
++ print_sta_bitrate(sinfo[NL80211_STA_INFO_RX_BITRATE], "rx bitrate");
+
+ if (sinfo[NL80211_STA_INFO_LLID])
+ printf("\n\tmesh llid:\t%d",
diff --git a/package/iw/patches/110-per_chain_signal_strength.patch b/package/iw/patches/110-per_chain_signal_strength.patch
new file mode 100644
index 000000000..813a7d916
--- /dev/null
+++ b/package/iw/patches/110-per_chain_signal_strength.patch
@@ -0,0 +1,71 @@
+--- a/station.c
++++ b/station.c
+@@ -65,6 +65,33 @@ static void print_sta_bitrate(struct nla
+ }
+ }
+
++static char *get_chain_signal(struct nlattr *attr_list)
++{
++ struct nlattr *attr;
++ static char buf[64];
++ char *cur = buf;
++ int i = 0, rem;
++ const char *prefix;
++
++ if (!attr_list)
++ return "";
++
++ nla_for_each_nested(attr, attr_list, rem) {
++ if (i++ > 0)
++ prefix = ", ";
++ else
++ prefix = "[";
++
++ cur += snprintf(cur, sizeof(buf) - (cur - buf), "%s%d", prefix,
++ (int8_t) nla_get_u8(attr));
++ }
++
++ if (i)
++ snprintf(cur, sizeof(buf) - (cur - buf), "] ");
++
++ return buf;
++}
++
+ static int print_sta_handler(struct nl_msg *msg, void *arg)
+ {
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+@@ -89,7 +116,10 @@ static int print_sta_handler(struct nl_m
+ [NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_STA_FLAGS] =
+ { .minlen = sizeof(struct nl80211_sta_flag_update) },
++ [NL80211_STA_INFO_CHAIN_SIGNAL] = { .type = NLA_NESTED },
++ [NL80211_STA_INFO_CHAIN_SIGNAL_AVG] = { .type = NLA_NESTED },
+ };
++ char *chain;
+
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+@@ -136,12 +166,19 @@ static int print_sta_handler(struct nl_m
+ if (sinfo[NL80211_STA_INFO_TX_FAILED])
+ printf("\n\ttx failed:\t%u",
+ nla_get_u32(sinfo[NL80211_STA_INFO_TX_FAILED]));
++
++ chain = get_chain_signal(sinfo[NL80211_STA_INFO_CHAIN_SIGNAL]);
+ if (sinfo[NL80211_STA_INFO_SIGNAL])
+- printf("\n\tsignal: \t%d dBm",
+- (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]));
++ printf("\n\tsignal: \t%d %sdBm",
++ (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]),
++ chain);
++
++ chain = get_chain_signal(sinfo[NL80211_STA_INFO_CHAIN_SIGNAL_AVG]);
+ if (sinfo[NL80211_STA_INFO_SIGNAL_AVG])
+- printf("\n\tsignal avg:\t%d dBm",
+- (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]));
++ printf("\n\tsignal avg:\t%d %sdBm",
++ (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]),
++ chain);
++
+ if (sinfo[NL80211_STA_INFO_T_OFFSET])
+ printf("\n\tToffset:\t%lld us",
+ (unsigned long long)nla_get_u64(sinfo[NL80211_STA_INFO_T_OFFSET]));
diff --git a/package/iw/patches/120-tdls_peer_indentation.patch b/package/iw/patches/120-tdls_peer_indentation.patch
new file mode 100644
index 000000000..68368734e
--- /dev/null
+++ b/package/iw/patches/120-tdls_peer_indentation.patch
@@ -0,0 +1,11 @@
+--- a/station.c
++++ b/station.c
+@@ -267,7 +267,7 @@ static int print_sta_handler(struct nl_m
+ }
+
+ if (sta_flags->mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
+- printf("\n\tTDLS peer:\t\t");
++ printf("\n\tTDLS peer:\t");
+ if (sta_flags->set & BIT(NL80211_STA_FLAG_TDLS_PEER))
+ printf("yes");
+ else
diff --git a/package/iw/patches/130-antenna_gain.patch b/package/iw/patches/130-antenna_gain.patch
new file mode 100644
index 000000000..f3ca691e5
--- /dev/null
+++ b/package/iw/patches/130-antenna_gain.patch
@@ -0,0 +1,34 @@
+--- a/phy.c
++++ b/phy.c
+@@ -359,3 +359,31 @@ COMMAND(set, antenna, "<bitmap> | all |
+ NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_antenna,
+ "Set a bitmap of allowed antennas to use for TX and RX.\n"
+ "The driver may reject antenna configurations it cannot support.");
++
++static int handle_antenna_gain(struct nl80211_state *state,
++ struct nl_cb *cb,
++ struct nl_msg *msg,
++ int argc, char **argv,
++ enum id_input id)
++{
++ char *endptr;
++ int dbm;
++
++ /* get the required args */
++ if (argc != 1)
++ return 1;
++
++ dbm = strtol(argv[0], &endptr, 10);
++ if (*endptr)
++ return 2;
++
++ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_GAIN, dbm);
++
++ return 0;
++
++ nla_put_failure:
++ return -ENOBUFS;
++}
++COMMAND(set, antenna_gain, "<antenna gain in dBm>",
++ NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_antenna_gain,
++ "Specify antenna gain.");
diff --git a/package/iwcap/Makefile b/package/iwcap/Makefile
new file mode 100644
index 000000000..b406bdfb4
--- /dev/null
+++ b/package/iwcap/Makefile
@@ -0,0 +1,50 @@
+#
+# Copyright (C) 2012 Jo-Philipp Wich <jow@openwrt.org>
+#
+# This is free software, licensed under the Apache 2 license.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=iwcap
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+
+define Package/iwcap
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Simple radiotap capture utility
+ MAINTAINER:=Jo-Philipp Wich <jow@openwrt.org>
+endef
+
+define Package/iwcap/description
+ The iwcap utility receives radiotap packet data from wifi monitor interfaces
+ and outputs it to pcap format. It gathers recived packets in a fixed ring
+ buffer to dump them on demand which is useful for background monitoring.
+ Alternatively the utility can stream the data to stdout to act as remote
+ capture drone for Wireshark or similar programs.
+endef
+
+
+define Build/Prepare
+ $(INSTALL_DIR) $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+ $(TARGET_CC) $(TARGET_CFLAGS) \
+ -o $(PKG_BUILD_DIR)/iwcap $(PKG_BUILD_DIR)/iwcap.c
+endef
+
+
+define Package/iwcap/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/iwcap $(1)/usr/sbin/iwcap
+endef
+
+$(eval $(call BuildPackage,iwcap))
diff --git a/package/iwcap/src/iwcap.c b/package/iwcap/src/iwcap.c
new file mode 100644
index 000000000..a71dca232
--- /dev/null
+++ b/package/iwcap/src/iwcap.c
@@ -0,0 +1,582 @@
+/*
+ * iwcap.c - A simply radiotap capture utility outputting pcap dumps
+ *
+ * Copyright 2012 Jo-Philipp Wich <jow@openwrt.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <syslog.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <linux/if_packet.h>
+
+#define ARPHRD_IEEE80211_RADIOTAP 803
+
+#define DLT_IEEE802_11_RADIO 127
+#define LEN_IEEE802_11_HDR 32
+
+#define FRAMETYPE_MASK 0xFC
+#define FRAMETYPE_BEACON 0x80
+#define FRAMETYPE_DATA 0x08
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define le16(x) __bswap_16(x)
+#else
+#define le16(x) (x)
+#endif
+
+uint8_t run_dump = 0;
+uint8_t run_stop = 0;
+uint8_t run_daemon = 0;
+
+uint32_t frames_captured = 0;
+uint32_t frames_filtered = 0;
+
+int capture_sock = -1;
+const char *ifname = NULL;
+
+
+struct ringbuf {
+ uint32_t len; /* number of slots */
+ uint32_t fill; /* last used slot */
+ uint32_t slen; /* slot size */
+ void *buf; /* ring memory */
+};
+
+struct ringbuf_entry {
+ uint32_t len; /* used slot memory */
+ uint32_t olen; /* original data size */
+ uint32_t sec; /* epoch of slot creation */
+ uint32_t usec; /* epoch microseconds */
+};
+
+typedef struct pcap_hdr_s {
+ uint32_t magic_number; /* magic number */
+ uint16_t version_major; /* major version number */
+ uint16_t version_minor; /* minor version number */
+ int32_t thiszone; /* GMT to local correction */
+ uint32_t sigfigs; /* accuracy of timestamps */
+ uint32_t snaplen; /* max length of captured packets, in octets */
+ uint32_t network; /* data link type */
+} pcap_hdr_t;
+
+typedef struct pcaprec_hdr_s {
+ uint32_t ts_sec; /* timestamp seconds */
+ uint32_t ts_usec; /* timestamp microseconds */
+ uint32_t incl_len; /* number of octets of packet saved in file */
+ uint32_t orig_len; /* actual length of packet */
+} pcaprec_hdr_t;
+
+typedef struct ieee80211_radiotap_header {
+ u_int8_t it_version; /* set to 0 */
+ u_int8_t it_pad;
+ u_int16_t it_len; /* entire length */
+ u_int32_t it_present; /* fields present */
+} __attribute__((__packed__)) radiotap_hdr_t;
+
+
+int check_type(void)
+{
+ struct ifreq ifr;
+
+ strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+
+ if (ioctl(capture_sock, SIOCGIFHWADDR, &ifr) < 0)
+ return -1;
+
+ return (ifr.ifr_hwaddr.sa_family == ARPHRD_IEEE80211_RADIOTAP);
+}
+
+int set_promisc(int on)
+{
+ struct ifreq ifr;
+
+ strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+
+ if (ioctl(capture_sock, SIOCGIFFLAGS, &ifr) < 0)
+ return -1;
+
+ if (on && !(ifr.ifr_flags & IFF_PROMISC))
+ {
+ ifr.ifr_flags |= IFF_PROMISC;
+
+ if (ioctl(capture_sock, SIOCSIFFLAGS, &ifr))
+ return -1;
+
+ return 1;
+ }
+ else if (!on && (ifr.ifr_flags & IFF_PROMISC))
+ {
+ ifr.ifr_flags &= ~IFF_PROMISC;
+
+ if (ioctl(capture_sock, SIOCSIFFLAGS, &ifr))
+ return -1;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+
+void sig_dump(int sig)
+{
+ run_dump = 1;
+}
+
+void sig_teardown(int sig)
+{
+ run_stop = 1;
+}
+
+
+void write_pcap_header(FILE *o)
+{
+ pcap_hdr_t ghdr = {
+ .magic_number = 0xa1b2c3d4,
+ .version_major = 2,
+ .version_minor = 4,
+ .thiszone = 0,
+ .sigfigs = 0,
+ .snaplen = 0xFFFF,
+ .network = DLT_IEEE802_11_RADIO
+ };
+
+ fwrite(&ghdr, 1, sizeof(ghdr), o);
+}
+
+void write_pcap_frame(FILE *o, uint32_t *sec, uint32_t *usec,
+ uint16_t len, uint16_t olen)
+{
+ struct timeval tv;
+ pcaprec_hdr_t fhdr;
+
+ if (!sec || !usec)
+ {
+ gettimeofday(&tv, NULL);
+ }
+ else
+ {
+ tv.tv_sec = *sec;
+ tv.tv_usec = *usec;
+ }
+
+ fhdr.ts_sec = tv.tv_sec;
+ fhdr.ts_usec = tv.tv_usec;
+ fhdr.incl_len = len;
+ fhdr.orig_len = olen;
+
+ fwrite(&fhdr, 1, sizeof(fhdr), o);
+}
+
+
+struct ringbuf * ringbuf_init(uint32_t num_item, uint16_t len_item)
+{
+ static struct ringbuf r;
+
+ if (len_item <= 0)
+ return NULL;
+
+ r.buf = malloc(num_item * (len_item + sizeof(struct ringbuf_entry)));
+
+ if (r.buf)
+ {
+ r.len = num_item;
+ r.fill = 0;
+ r.slen = (len_item + sizeof(struct ringbuf_entry));
+
+ memset(r.buf, 0, num_item * len_item);
+
+ return &r;
+ }
+
+ return NULL;
+}
+
+struct ringbuf_entry * ringbuf_add(struct ringbuf *r)
+{
+ struct timeval t;
+ struct ringbuf_entry *e;
+
+ gettimeofday(&t, NULL);
+
+ e = r->buf + (r->fill++ * r->slen);
+ r->fill %= r->len;
+
+ memset(e, 0, r->slen);
+
+ e->sec = t.tv_sec;
+ e->usec = t.tv_usec;
+
+ return e;
+}
+
+struct ringbuf_entry * ringbuf_get(struct ringbuf *r, int i)
+{
+ struct ringbuf_entry *e = r->buf + (((r->fill + i) % r->len) * r->slen);
+
+ if (e->len > 0)
+ return e;
+
+ return NULL;
+}
+
+void ringbuf_free(struct ringbuf *r)
+{
+ free(r->buf);
+ memset(r, 0, sizeof(*r));
+}
+
+
+void msg(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+
+ if (run_daemon)
+ vsyslog(LOG_INFO | LOG_USER, fmt, ap);
+ else
+ vfprintf(stderr, fmt, ap);
+
+ va_end(ap);
+}
+
+
+int main(int argc, char **argv)
+{
+ int i, n;
+ struct ringbuf *ring;
+ struct ringbuf_entry *e;
+ struct sockaddr_ll local = {
+ .sll_family = AF_PACKET,
+ .sll_protocol = htons(ETH_P_ALL)
+ };
+
+ radiotap_hdr_t *rhdr;
+
+ uint8_t frametype;
+ uint8_t pktbuf[0xFFFF];
+ ssize_t pktlen;
+
+ FILE *o;
+
+ int opt;
+
+ uint8_t promisc = 0;
+ uint8_t streaming = 0;
+ uint8_t foreground = 0;
+ uint8_t filter_data = 0;
+ uint8_t filter_beacon = 0;
+ uint8_t header_written = 0;
+
+ uint32_t ringsz = 1024 * 1024; /* 1 Mbyte ring buffer */
+ uint16_t pktcap = 256; /* truncate frames after 265KB */
+
+ const char *output = NULL;
+
+
+ while ((opt = getopt(argc, argv, "i:r:c:o:sfhBD")) != -1)
+ {
+ switch (opt)
+ {
+ case 'i':
+ ifname = optarg;
+ if (!(local.sll_ifindex = if_nametoindex(ifname)))
+ {
+ msg("Unknown interface '%s'\n", ifname);
+ return 2;
+ }
+ break;
+
+ case 'r':
+ ringsz = atoi(optarg);
+ if (ringsz < (3 * pktcap))
+ {
+ msg("Ring size of %d bytes is too short, "
+ "must be at least %d bytes\n", ringsz, 3 * pktcap);
+ return 3;
+ }
+ break;
+
+ case 'c':
+ pktcap = atoi(optarg);
+ if (pktcap <= (sizeof(radiotap_hdr_t) + LEN_IEEE802_11_HDR))
+ {
+ msg("Packet truncate after %d bytes is too short, "
+ "must be at least %d bytes\n",
+ pktcap, sizeof(radiotap_hdr_t) + LEN_IEEE802_11_HDR);
+ return 4;
+ }
+ break;
+
+ case 's':
+ streaming = 1;
+ break;
+
+ case 'o':
+ output = optarg;
+ break;
+
+ case 'B':
+ filter_beacon = 1;
+ break;
+
+ case 'D':
+ filter_data = 1;
+ break;
+
+ case 'f':
+ foreground = 1;
+ break;
+
+ case 'h':
+ msg(
+ "Usage:\n"
+ " %s -i {iface} -s [-b] [-d]\n"
+ " %s -i {iface} -o {file} [-r len] [-c len] [-B] [-D] [-f]\n"
+ "\n"
+ " -i iface\n"
+ " Specify interface to use, must be in monitor mode and\n"
+ " produce IEEE 802.11 Radiotap headers.\n\n"
+ " -s\n"
+ " Stream to stdout instead of Dumping to file on USR1.\n\n"
+ " -o file\n"
+ " Write current ringbuffer contents to given output file\n"
+ " on receipt of SIGUSR1.\n\n"
+ " -r len\n"
+ " Specify the amount of bytes to use for the ringbuffer.\n"
+ " The default length is %d bytes.\n\n"
+ " -c len\n"
+ " Truncate captured packets after given amount of bytes.\n"
+ " The default size limit is %d bytes.\n\n"
+ " -B\n"
+ " Don't store beacon frames in ring, default is keep.\n\n"
+ " -D\n"
+ " Don't store data frames in ring, default is keep.\n\n"
+ " -f\n"
+ " Do not daemonize but keep running in foreground.\n\n"
+ " -h\n"
+ " Display this help.\n\n",
+ argv[0], argv[0], ringsz, pktcap);
+
+ return 1;
+ }
+ }
+
+ if (!streaming && !output)
+ {
+ msg("No output file specified\n");
+ return 1;
+ }
+
+ if (streaming && output)
+ {
+ msg("The -s and -o options are exclusive\n");
+ return 1;
+ }
+
+ if (streaming && isatty(1))
+ {
+ msg("Refusing to stream into a terminal\n");
+ return 1;
+ }
+
+ if (!local.sll_ifindex)
+ {
+ msg("No interface specified\n");
+ return 2;
+ }
+
+ if (!check_type())
+ {
+ msg("Bad interface: not ARPHRD_IEEE80211_RADIOTAP\n");
+ return 2;
+ }
+
+ if ((capture_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0)
+ {
+ msg("Unable to create raw socket: %s\n",
+ strerror(errno));
+ return 6;
+ }
+
+ if (bind(capture_sock, (struct sockaddr *)&local, sizeof(local)) == -1)
+ {
+ msg("Unable to bind to interface: %s\n",
+ strerror(errno));
+ return 7;
+ }
+
+ if (!streaming)
+ {
+ if (!foreground)
+ {
+ switch (fork())
+ {
+ case -1:
+ msg("Unable to fork: %s\n", strerror(errno));
+ return 8;
+
+ case 0:
+ umask(0077);
+ chdir("/");
+ freopen("/dev/null", "r", stdin);
+ freopen("/dev/null", "w", stdout);
+ freopen("/dev/null", "w", stderr);
+ run_daemon = 1;
+ break;
+
+ default:
+ msg("Daemon launched ...\n");
+ return 0;
+ }
+ }
+
+ msg("Monitoring interface %s ...\n", ifname);
+
+ if (!(ring = ringbuf_init(ringsz / pktcap, pktcap)))
+ {
+ msg("Unable to allocate ring buffer: %s\n",
+ strerror(errno));
+ return 5;
+ }
+
+ msg(" * Using %d bytes ringbuffer with %d slots\n", ringsz, ring->len);
+ msg(" * Truncating frames at %d bytes\n", pktcap);
+ msg(" * Dumping data to file %s\n", output);
+
+ signal(SIGUSR1, sig_dump);
+ }
+ else
+ {
+ msg("Monitoring interface %s ...\n", ifname);
+ msg(" * Streaming data to stdout\n");
+ }
+
+ msg(" * Beacon frames are %sfiltered\n", filter_beacon ? "" : "not ");
+ msg(" * Data frames are %sfiltered\n", filter_data ? "" : "not ");
+
+ signal(SIGINT, sig_teardown);
+ signal(SIGTERM, sig_teardown);
+
+ promisc = set_promisc(1);
+
+ /* capture loop */
+ while (1)
+ {
+ if (run_stop)
+ {
+ msg("Shutting down ...\n");
+
+ if (promisc)
+ set_promisc(0);
+
+ if (ring)
+ ringbuf_free(ring);
+
+ return 0;
+ }
+ else if (run_dump)
+ {
+ msg("Dumping ring to %s ...\n", output);
+
+ if (!(o = fopen(output, "w")))
+ {
+ msg("Unable to open %s: %s\n",
+ output, strerror(errno));
+ }
+ else
+ {
+ write_pcap_header(o);
+
+ /* sig_dump packet buffer */
+ for (i = 0, n = 0; i < ring->len; i++)
+ {
+ if (!(e = ringbuf_get(ring, i)))
+ continue;
+
+ write_pcap_frame(o, &(e->sec), &(e->usec), e->len, e->olen);
+ fwrite((void *)e + sizeof(*e), 1, e->len, o);
+ n++;
+ }
+
+ fclose(o);
+
+ msg(" * %d frames captured\n", frames_captured);
+ msg(" * %d frames filtered\n", frames_filtered);
+ msg(" * %d frames dumped\n", n);
+ }
+
+ run_dump = 0;
+ }
+
+ pktlen = recvfrom(capture_sock, pktbuf, sizeof(pktbuf), 0, NULL, 0);
+ frames_captured++;
+
+ /* check received frametype, if we should filter it, rewind the ring */
+ rhdr = (radiotap_hdr_t *)pktbuf;
+
+ if (pktlen <= sizeof(radiotap_hdr_t) || le16(rhdr->it_len) >= pktlen)
+ {
+ frames_filtered++;
+ continue;
+ }
+
+ frametype = *(uint8_t *)(pktbuf + le16(rhdr->it_len));
+
+ if ((filter_data && (frametype & FRAMETYPE_MASK) == FRAMETYPE_DATA) ||
+ (filter_beacon && (frametype & FRAMETYPE_MASK) == FRAMETYPE_BEACON))
+ {
+ frames_filtered++;
+ continue;
+ }
+
+ if (streaming)
+ {
+ if (!header_written)
+ {
+ write_pcap_header(stdout);
+ header_written = 1;
+ }
+
+ write_pcap_frame(stdout, NULL, NULL, pktlen, pktlen);
+ fwrite(pktbuf, 1, pktlen, stdout);
+ fflush(stdout);
+ }
+ else
+ {
+ e = ringbuf_add(ring);
+ e->olen = pktlen;
+ e->len = (pktlen > pktcap) ? pktcap : pktlen;
+
+ memcpy((void *)e + sizeof(*e), pktbuf, e->len);
+ }
+ }
+
+ return 0;
+}
diff --git a/package/iwinfo/Makefile b/package/iwinfo/Makefile
new file mode 100644
index 000000000..f05fe4a78
--- /dev/null
+++ b/package/iwinfo/Makefile
@@ -0,0 +1,118 @@
+#
+# Copyright (C) 2010-2012 Jo-Philipp Wich <xm@subsignal.org>
+#
+# This is free software, licensed under the GPL 2 license.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=libiwinfo
+PKG_RELEASE:=35
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+PKG_CONFIG_DEPENDS := \
+ CONFIG_PACKAGE_kmod-brcm-wl \
+ CONFIG_PACKAGE_kmod-brcm-wl-mini \
+ CONFIG_PACKAGE_kmod-brcm-wl-mimo \
+ CONFIG_PACKAGE_kmod-madwifi \
+ CONFIG_PACKAGE_kmod-mac80211
+
+include $(INCLUDE_DIR)/package.mk
+
+
+define Package/libiwinfo
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=Generalized Wireless Information Library (iwinfo)
+ DEPENDS:=+PACKAGE_kmod-mac80211:libnl-tiny
+ MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org>
+endef
+
+define Package/libiwinfo/description
+ Wireless information library with consistent interface for proprietary Broadcom,
+ madwifi, nl80211 and wext driver interfaces.
+endef
+
+
+define Package/libiwinfo-lua
+ SUBMENU:=Lua
+ SECTION:=lang
+ CATEGORY:=Languages
+ TITLE:=libiwinfo Lua binding
+ DEPENDS:=+libiwinfo +liblua +lua
+ MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org>
+endef
+
+define Package/libiwinfo-lua/description
+ This is the Lua binding for the iwinfo library. It provides access to all enabled
+ backends.
+endef
+
+
+define Package/iwinfo
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Generalized Wireless Information utility
+ DEPENDS:=+libiwinfo
+ MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org>
+endef
+
+define Package/iwinfo/description
+ Command line frontend for the wireless information library.
+endef
+
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Configure
+endef
+
+IWINFO_BACKENDS := \
+ $(if $(CONFIG_PACKAGE_kmod-brcm-wl),wl) \
+ $(if $(CONFIG_PACKAGE_kmod-brcm-wl-mini),wl) \
+ $(if $(CONFIG_PACKAGE_kmod-brcm-wl-mimo),wl) \
+ $(if $(CONFIG_PACKAGE_kmod-madwifi),madwifi) \
+ $(if $(CONFIG_PACKAGE_kmod-mac80211),nl80211)
+
+TARGET_CFLAGS += \
+ -I$(STAGING_DIR)/usr/include/libnl-tiny \
+ -I$(STAGING_DIR)/usr/include \
+ -D_GNU_SOURCE
+
+MAKE_FLAGS += \
+ FPIC="$(FPIC)" \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ LDFLAGS="$(TARGET_LDFLAGS)" \
+ BACKENDS="$(IWINFO_BACKENDS)"
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include/iwinfo
+ $(CP) $(PKG_BUILD_DIR)/include/iwinfo.h $(1)/usr/include/
+ $(CP) $(PKG_BUILD_DIR)/include/iwinfo/* $(1)/usr/include/iwinfo/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/libiwinfo.so $(1)/usr/lib/libiwinfo.so
+ $(INSTALL_DIR) $(1)/usr/lib/lua
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/iwinfo.so $(1)/usr/lib/lua/iwinfo.so
+endef
+
+define Package/libiwinfo/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/libiwinfo.so $(1)/usr/lib/libiwinfo.so
+endef
+
+define Package/libiwinfo-lua/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/iwinfo.so $(1)/usr/lib/lua/iwinfo.so
+endef
+
+define Package/iwinfo/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/iwinfo $(1)/usr/bin/iwinfo
+endef
+
+$(eval $(call BuildPackage,libiwinfo))
+$(eval $(call BuildPackage,libiwinfo-lua))
+$(eval $(call BuildPackage,iwinfo))
diff --git a/package/iwinfo/src/COPYING b/package/iwinfo/src/COPYING
new file mode 100644
index 000000000..d511905c1
--- /dev/null
+++ b/package/iwinfo/src/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/package/iwinfo/src/Makefile b/package/iwinfo/src/Makefile
new file mode 100644
index 000000000..572bef9f9
--- /dev/null
+++ b/package/iwinfo/src/Makefile
@@ -0,0 +1,44 @@
+IWINFO_BACKENDS = $(BACKENDS)
+IWINFO_CFLAGS = $(CFLAGS) -std=gnu99 -fstrict-aliasing -Iinclude
+
+IWINFO_LIB = libiwinfo.so
+IWINFO_LIB_LDFLAGS = $(LDFLAGS) -shared
+IWINFO_LIB_OBJ = iwinfo_utils.o iwinfo_wext.o iwinfo_wext_scan.o iwinfo_lib.o
+
+IWINFO_LUA = iwinfo.so
+IWINFO_LUA_LDFLAGS = $(LDFLAGS) -shared -L. -liwinfo -llua
+IWINFO_LUA_OBJ = iwinfo_lua.o
+
+IWINFO_CLI = iwinfo
+IWINFO_CLI_LDFLAGS = $(LDFLAGS) -L. -liwinfo
+IWINFO_CLI_OBJ = iwinfo_cli.o
+
+
+ifneq ($(filter wl,$(IWINFO_BACKENDS)),)
+ IWINFO_CFLAGS += -DUSE_WL
+ IWINFO_LIB_OBJ += iwinfo_wl.o
+endif
+
+ifneq ($(filter madwifi,$(IWINFO_BACKENDS)),)
+ IWINFO_CFLAGS += -DUSE_MADWIFI
+ IWINFO_LIB_OBJ += iwinfo_madwifi.o
+endif
+
+ifneq ($(filter nl80211,$(IWINFO_BACKENDS)),)
+ IWINFO_CFLAGS += -DUSE_NL80211
+ IWINFO_CLI_LDFLAGS += -lnl-tiny
+ IWINFO_LIB_LDFLAGS += -lnl-tiny
+ IWINFO_LIB_OBJ += iwinfo_nl80211.o
+endif
+
+
+%.o: %.c
+ $(CC) $(IWINFO_CFLAGS) $(FPIC) -c -o $@ $<
+
+compile: clean $(IWINFO_LIB_OBJ) $(IWINFO_LUA_OBJ) $(IWINFO_CLI_OBJ)
+ $(CC) $(IWINFO_LIB_LDFLAGS) -o $(IWINFO_LIB) $(IWINFO_LIB_OBJ)
+ $(CC) $(IWINFO_LUA_LDFLAGS) -o $(IWINFO_LUA) $(IWINFO_LUA_OBJ)
+ $(CC) $(IWINFO_CLI_LDFLAGS) -o $(IWINFO_CLI) $(IWINFO_CLI_OBJ)
+
+clean:
+ rm -f *.o $(IWINFO_LIB) $(IWINFO_LUA) $(IWINFO_CLI)
diff --git a/package/iwinfo/src/include/iwinfo.h b/package/iwinfo/src/include/iwinfo.h
new file mode 100644
index 000000000..868c10b35
--- /dev/null
+++ b/package/iwinfo/src/include/iwinfo.h
@@ -0,0 +1,190 @@
+#ifndef __IWINFO_H_
+#define __IWINFO_H_
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <glob.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <stdint.h>
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <net/if.h>
+#include <errno.h>
+
+
+#define IWINFO_BUFSIZE 24 * 1024
+#define IWINFO_ESSID_MAX_SIZE 32
+
+#define IWINFO_80211_A (1 << 0)
+#define IWINFO_80211_B (1 << 1)
+#define IWINFO_80211_G (1 << 2)
+#define IWINFO_80211_N (1 << 3)
+
+#define IWINFO_CIPHER_NONE (1 << 0)
+#define IWINFO_CIPHER_WEP40 (1 << 1)
+#define IWINFO_CIPHER_TKIP (1 << 2)
+#define IWINFO_CIPHER_WRAP (1 << 3)
+#define IWINFO_CIPHER_CCMP (1 << 4)
+#define IWINFO_CIPHER_WEP104 (1 << 5)
+#define IWINFO_CIPHER_AESOCB (1 << 6)
+#define IWINFO_CIPHER_CKIP (1 << 7)
+
+#define IWINFO_KMGMT_NONE (1 << 0)
+#define IWINFO_KMGMT_8021x (1 << 1)
+#define IWINFO_KMGMT_PSK (1 << 2)
+
+#define IWINFO_AUTH_OPEN (1 << 0)
+#define IWINFO_AUTH_SHARED (1 << 1)
+
+extern const char *IWINFO_CIPHER_NAMES[];
+extern const char *IWINFO_KMGMT_NAMES[];
+extern const char *IWINFO_AUTH_NAMES[];
+
+
+enum iwinfo_opmode {
+ IWINFO_OPMODE_UNKNOWN = 0,
+ IWINFO_OPMODE_MASTER = 1,
+ IWINFO_OPMODE_ADHOC = 2,
+ IWINFO_OPMODE_CLIENT = 3,
+ IWINFO_OPMODE_MONITOR = 4,
+};
+
+extern const char *IWINFO_OPMODE_NAMES[];
+
+
+struct iwinfo_rate_entry {
+ uint32_t rate;
+ int8_t mcs;
+ uint8_t is_40mhz:1;
+ uint8_t is_short_gi:1;
+};
+
+struct iwinfo_assoclist_entry {
+ uint8_t mac[6];
+ int8_t signal;
+ int8_t noise;
+ uint32_t inactive;
+ uint32_t rx_packets;
+ uint32_t tx_packets;
+ struct iwinfo_rate_entry rx_rate;
+ struct iwinfo_rate_entry tx_rate;
+};
+
+struct iwinfo_txpwrlist_entry {
+ uint8_t dbm;
+ uint16_t mw;
+};
+
+struct iwinfo_freqlist_entry {
+ uint8_t channel;
+ uint32_t mhz;
+ uint8_t restricted;
+};
+
+struct iwinfo_crypto_entry {
+ uint8_t enabled;
+ uint8_t wpa_version;
+ uint8_t group_ciphers;
+ uint8_t pair_ciphers;
+ uint8_t auth_suites;
+ uint8_t auth_algs;
+};
+
+struct iwinfo_scanlist_entry {
+ uint8_t mac[6];
+ uint8_t ssid[IWINFO_ESSID_MAX_SIZE+1];
+ enum iwinfo_opmode mode;
+ uint8_t channel;
+ uint8_t signal;
+ uint8_t quality;
+ uint8_t quality_max;
+ struct iwinfo_crypto_entry crypto;
+};
+
+struct iwinfo_country_entry {
+ uint16_t iso3166;
+ uint8_t ccode[4];
+};
+
+struct iwinfo_iso3166_label {
+ uint16_t iso3166;
+ uint8_t name[28];
+};
+
+struct iwinfo_hardware_id {
+ uint16_t vendor_id;
+ uint16_t device_id;
+ uint16_t subsystem_vendor_id;
+ uint16_t subsystem_device_id;
+};
+
+struct iwinfo_hardware_entry {
+ const char *vendor_name;
+ const char *device_name;
+ uint16_t vendor_id;
+ uint16_t device_id;
+ uint16_t subsystem_vendor_id;
+ uint16_t subsystem_device_id;
+ int16_t txpower_offset;
+ int16_t frequency_offset;
+};
+
+extern const struct iwinfo_iso3166_label IWINFO_ISO3166_NAMES[];
+extern const struct iwinfo_hardware_entry IWINFO_HARDWARE_ENTRIES[];
+
+
+struct iwinfo_ops {
+ int (*mode)(const char *, int *);
+ int (*channel)(const char *, int *);
+ int (*frequency)(const char *, int *);
+ int (*frequency_offset)(const char *, int *);
+ int (*txpower)(const char *, int *);
+ int (*txpower_offset)(const char *, int *);
+ int (*bitrate)(const char *, int *);
+ int (*signal)(const char *, int *);
+ int (*noise)(const char *, int *);
+ int (*quality)(const char *, int *);
+ int (*quality_max)(const char *, int *);
+ int (*mbssid_support)(const char *, int *);
+ int (*hwmodelist)(const char *, int *);
+ int (*ssid)(const char *, char *);
+ int (*bssid)(const char *, char *);
+ int (*country)(const char *, char *);
+ int (*hardware_id)(const char *, char *);
+ int (*hardware_name)(const char *, char *);
+ int (*encryption)(const char *, char *);
+ int (*assoclist)(const char *, char *, int *);
+ int (*txpwrlist)(const char *, char *, int *);
+ int (*scanlist)(const char *, char *, int *);
+ int (*freqlist)(const char *, char *, int *);
+ int (*countrylist)(const char *, char *, int *);
+ void (*close)(void);
+};
+
+const char * iwinfo_type(const char *ifname);
+const struct iwinfo_ops * iwinfo_backend(const char *ifname);
+void iwinfo_finish(void);
+
+#include "iwinfo/wext.h"
+
+#ifdef USE_WL
+#include "iwinfo/wl.h"
+#endif
+
+#ifdef USE_MADWIFI
+#include "iwinfo/madwifi.h"
+#endif
+
+#ifdef USE_NL80211
+#include "iwinfo/nl80211.h"
+#endif
+
+#endif
diff --git a/package/iwinfo/src/include/iwinfo/api/broadcom.h b/package/iwinfo/src/include/iwinfo/api/broadcom.h
new file mode 100644
index 000000000..50eedd9e4
--- /dev/null
+++ b/package/iwinfo/src/include/iwinfo/api/broadcom.h
@@ -0,0 +1,131 @@
+/*
+ * Custom OID/ioctl definitions for
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Definitions subject to change without notice.
+ *
+ * Copyright 2006, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ */
+
+#ifndef _BROADCOM_H
+#define _BROADCOM_H
+
+#define WL_MCSSET_LEN 16
+#define WL_MAX_STA_COUNT 32
+
+#define WL_BSS_RSSI_OFFSET 82
+#define WL_BSS_NOISE_OFFSET 84
+
+#define WLC_IOCTL_MAGIC 0x14e46c77
+#define WLC_IOCTL_MAXLEN 8192
+
+#define WLC_CNTRY_BUF_SZ 4
+
+#define WLC_GET_MAGIC 0
+#define WLC_GET_RATE 12
+#define WLC_GET_INFRA 19
+#define WLC_GET_AUTH 21
+#define WLC_GET_BSSID 23
+#define WLC_GET_SSID 25
+#define WLC_GET_CHANNEL 29
+#define WLC_GET_PASSIVE 48
+#define WLC_GET_COUNTRY 83
+#define WLC_GET_REVINFO 98
+#define WLC_GET_AP 117
+#define WLC_GET_RSSI 127
+#define WLC_GET_WSEC 133
+#define WLC_GET_PHY_NOISE 135
+#define WLC_GET_BSS_INFO 136
+#define WLC_GET_ASSOCLIST 159
+#define WLC_GET_WPA_AUTH 164
+#define WLC_GET_COUNTRY_LIST 261
+#define WLC_GET_VAR 262
+
+
+struct wl_ether_addr {
+ uint8_t octet[6];
+};
+
+struct wl_maclist {
+ uint count;
+ struct wl_ether_addr ea[1];
+};
+
+typedef struct wl_sta_rssi {
+ int rssi;
+ char mac[6];
+ uint16_t foo;
+} wl_sta_rssi_t;
+
+#define WL_NUMRATES 255 /* max # of rates in a rateset */
+typedef struct wl_rateset {
+ uint32_t count; /* # rates in this set */
+ uint8_t rates[WL_NUMRATES]; /* rates in 500kbps units w/hi bit set if basic */
+} wl_rateset_t;
+
+typedef struct wl_sta_info {
+ uint16_t ver; /* version of this struct */
+ uint16_t len; /* length in bytes of this structure */
+ uint16_t cap; /* sta's advertised capabilities */
+ uint32_t flags; /* flags defined below */
+ uint32_t idle; /* time since data pkt rx'd from sta */
+ unsigned char ea[6]; /* Station address */
+ wl_rateset_t rateset; /* rateset in use */
+ uint32_t in; /* seconds elapsed since associated */
+ uint32_t listen_interval_inms; /* Min Listen interval in ms for this STA */
+ uint32_t tx_pkts; /* # of packets transmitted */
+ uint32_t tx_failures; /* # of packets failed */
+ uint32_t rx_ucast_pkts; /* # of unicast packets received */
+ uint32_t rx_mcast_pkts; /* # of multicast packets received */
+ uint32_t tx_rate; /* Rate of last successful tx frame */
+ uint32_t rx_rate; /* Rate of last successful rx frame */
+} wl_sta_info_t;
+
+typedef struct wlc_ssid {
+ uint32_t ssid_len;
+ unsigned char ssid[32];
+} wlc_ssid_t;
+
+/* Linux network driver ioctl encoding */
+typedef struct wl_ioctl {
+ uint32_t cmd; /* common ioctl definition */
+ void *buf; /* pointer to user buffer */
+ uint32_t len; /* length of user buffer */
+ uint8_t set; /* get or set request (optional) */
+ uint32_t used; /* bytes read or written (optional) */
+ uint32_t needed; /* bytes needed (optional) */
+} wl_ioctl_t;
+
+/* Revision info */
+typedef struct wlc_rev_info {
+ uint vendorid; /* PCI vendor id */
+ uint deviceid; /* device id of chip */
+ uint radiorev; /* radio revision */
+ uint chiprev; /* chip revision */
+ uint corerev; /* core revision */
+ uint boardid; /* board identifier (usu. PCI sub-device id) */
+ uint boardvendor; /* board vendor (usu. PCI sub-vendor id) */
+ uint boardrev; /* board revision */
+ uint driverrev; /* driver version */
+ uint ucoderev; /* microcode version */
+ uint bus; /* bus type */
+ uint chipnum; /* chip number */
+} wlc_rev_info_t;
+
+typedef struct wl_country_list {
+ uint32_t buflen;
+ uint32_t band_set;
+ uint32_t band;
+ uint32_t count;
+ char country_abbrev[1];
+} wl_country_list_t;
+
+
+#endif
diff --git a/package/iwinfo/src/include/iwinfo/api/madwifi.h b/package/iwinfo/src/include/iwinfo/api/madwifi.h
new file mode 100644
index 000000000..80d32e195
--- /dev/null
+++ b/package/iwinfo/src/include/iwinfo/api/madwifi.h
@@ -0,0 +1,160 @@
+/*
+ * Header bits derived from MadWifi source:
+ * Copyright (c) 2001 Atsushi Onoe
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Distributed under the terms of the GPLv2 license.
+ *
+ * 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 _MADWIFI_H
+#define _MADWIFI_H
+
+/* ieee80211.h */
+#define IEEE80211_ADDR_LEN 6
+#define IEEE80211_RATE_VAL 0x7f
+#define IEEE80211_SEQ_SEQ_MASK 0xfff0
+#define IEEE80211_SEQ_SEQ_SHIFT 4
+
+
+/* ieee80211_crypto.h */
+#define IEEE80211_KEYBUF_SIZE 16
+#define IEEE80211_MICBUF_SIZE 16
+#define IEEE80211_TID_SIZE 17
+
+#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
+#define IEEE80211_CIPHER_MAX (IEEE80211_CIPHER_NONE + 1)
+
+
+/* ieee80211_ioctl.h */
+#define IEEE80211_KEY_DEFAULT 0x80
+#define IEEE80211_CHAN_MAX 255
+#define IEEE80211_CHAN_BYTES 32
+#define IEEE80211_RATE_MAXSIZE 15
+
+#define IEEE80211_IOCTL_GETKEY (SIOCDEVPRIVATE+3)
+#define IEEE80211_IOCTL_STA_STATS (SIOCDEVPRIVATE+5)
+#define IEEE80211_IOCTL_STA_INFO (SIOCDEVPRIVATE+6)
+
+#define IEEE80211_IOCTL_GETPARAM (SIOCIWFIRSTPRIV+1)
+#define IEEE80211_IOCTL_GETMODE (SIOCIWFIRSTPRIV+3)
+#define IEEE80211_IOCTL_GETCHANLIST (SIOCIWFIRSTPRIV+7)
+#define IEEE80211_IOCTL_GETCHANINFO (SIOCIWFIRSTPRIV+13)
+
+#define SIOC80211IFCREATE (SIOCDEVPRIVATE+7)
+#define SIOC80211IFDESTROY (SIOCDEVPRIVATE+8)
+
+#define IEEE80211_CLONE_BSSID 0x0001 /* allocate unique mac/bssid */
+#define IEEE80211_NO_STABEACONS 0x0002 /* Do not setup the station beacon timers */
+
+struct ieee80211_clone_params {
+ char icp_name[IFNAMSIZ]; /* device name */
+ u_int16_t icp_opmode; /* operating mode */
+ u_int16_t icp_flags; /* see below */
+};
+
+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 */
+};
+
+enum {
+ IEEE80211_PARAM_AUTHMODE = 3, /* authentication mode */
+ IEEE80211_PARAM_MCASTCIPHER = 5, /* multicast/default cipher */
+ IEEE80211_PARAM_MCASTKEYLEN = 6, /* multicast key length */
+ IEEE80211_PARAM_UCASTCIPHERS = 7, /* unicast cipher suites */
+ IEEE80211_PARAM_WPA = 10, /* WPA mode (0,1,2) */
+};
+
+/*
+ * 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 */
+};
+
+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;
+ u_int8_t ic_idletime; /* phy idle time in % */
+};
+
+struct ieee80211req_key {
+ u_int8_t ik_type; /* key/cipher type */
+ u_int8_t ik_pad;
+ u_int16_t ik_keyix; /* key index */
+ u_int8_t ik_keylen; /* key length in bytes */
+ u_int8_t ik_flags;
+ 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];
+};
+
+struct ieee80211req_chanlist {
+ u_int8_t ic_channels[IEEE80211_CHAN_BYTES];
+};
+
+struct ieee80211req_chaninfo {
+ u_int ic_nchans;
+ struct ieee80211_channel ic_chans[IEEE80211_CHAN_MAX];
+};
+
+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 */
+};
+
+#endif
diff --git a/package/iwinfo/src/include/iwinfo/api/nl80211.h b/package/iwinfo/src/include/iwinfo/api/nl80211.h
new file mode 100644
index 000000000..d73dcb8e8
--- /dev/null
+++ b/package/iwinfo/src/include/iwinfo/api/nl80211.h
@@ -0,0 +1,2834 @@
+#ifndef __LINUX_NL80211_H
+#define __LINUX_NL80211_H
+/*
+ * 802.11 netlink interface public header
+ *
+ * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2008 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2008 Luis Carlos Cobo <luisca@cozybit.com>
+ * Copyright 2008 Michael Buesch <m@bues.ch>
+ * Copyright 2008, 2009 Luis R. Rodriguez <lrodriguez@atheros.com>
+ * Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com>
+ * Copyright 2008 Colin McCabe <colin@cozybit.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <linux/types.h>
+
+/**
+ * DOC: Station handling
+ *
+ * Stations are added per interface, but a special case exists with VLAN
+ * interfaces. When a station is bound to an AP interface, it may be moved
+ * into a VLAN identified by a VLAN interface index (%NL80211_ATTR_STA_VLAN).
+ * The station is still assumed to belong to the AP interface it was added
+ * to.
+ *
+ * TODO: need more info?
+ */
+
+/**
+ * DOC: Frame transmission/registration support
+ *
+ * Frame transmission and registration support exists to allow userspace
+ * management entities such as wpa_supplicant react to management frames
+ * that are not being handled by the kernel. This includes, for example,
+ * certain classes of action frames that cannot be handled in the kernel
+ * for various reasons.
+ *
+ * Frame registration is done on a per-interface basis and registrations
+ * cannot be removed other than by closing the socket. It is possible to
+ * specify a registration filter to register, for example, only for a
+ * certain type of action frame. In particular with action frames, those
+ * that userspace registers for will not be returned as unhandled by the
+ * driver, so that the registered application has to take responsibility
+ * for doing that.
+ *
+ * The type of frame that can be registered for is also dependent on the
+ * driver and interface type. The frame types are advertised in wiphy
+ * attributes so applications know what to expect.
+ *
+ * NOTE: When an interface changes type while registrations are active,
+ * these registrations are ignored until the interface type is
+ * changed again. This means that changing the interface type can
+ * lead to a situation that couldn't otherwise be produced, but
+ * any such registrations will be dormant in the sense that they
+ * will not be serviced, i.e. they will not receive any frames.
+ *
+ * Frame transmission allows userspace to send for example the required
+ * responses to action frames. It is subject to some sanity checking,
+ * but many frames can be transmitted. When a frame was transmitted, its
+ * status is indicated to the sending socket.
+ *
+ * For more technical details, see the corresponding command descriptions
+ * below.
+ */
+
+/**
+ * DOC: Virtual interface / concurrency capabilities
+ *
+ * Some devices are able to operate with virtual MACs, they can have
+ * more than one virtual interface. The capability handling for this
+ * is a bit complex though, as there may be a number of restrictions
+ * on the types of concurrency that are supported.
+ *
+ * To start with, each device supports the interface types listed in
+ * the %NL80211_ATTR_SUPPORTED_IFTYPES attribute, but by listing the
+ * types there no concurrency is implied.
+ *
+ * Once concurrency is desired, more attributes must be observed:
+ * To start with, since some interface types are purely managed in
+ * software, like the AP-VLAN type in mac80211 for example, there's
+ * an additional list of these, they can be added at any time and
+ * are only restricted by some semantic restrictions (e.g. AP-VLAN
+ * cannot be added without a corresponding AP interface). This list
+ * is exported in the %NL80211_ATTR_SOFTWARE_IFTYPES attribute.
+ *
+ * Further, the list of supported combinations is exported. This is
+ * in the %NL80211_ATTR_INTERFACE_COMBINATIONS attribute. Basically,
+ * it exports a list of "groups", and at any point in time the
+ * interfaces that are currently active must fall into any one of
+ * the advertised groups. Within each group, there are restrictions
+ * on the number of interfaces of different types that are supported
+ * and also the number of different channels, along with potentially
+ * some other restrictions. See &enum nl80211_if_combination_attrs.
+ *
+ * All together, these attributes define the concurrency of virtual
+ * interfaces that a given device supports.
+ */
+
+/**
+ * enum nl80211_commands - supported nl80211 commands
+ *
+ * @NL80211_CMD_UNSPEC: unspecified command to catch errors
+ *
+ * @NL80211_CMD_GET_WIPHY: request information about a wiphy or dump request
+ * to get a list of all present wiphys.
+ * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or
+ * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME,
+ * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ,
+ * %NL80211_ATTR_WIPHY_CHANNEL_TYPE, %NL80211_ATTR_WIPHY_RETRY_SHORT,
+ * %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
+ * and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD.
+ * However, for setting the channel, see %NL80211_CMD_SET_CHANNEL
+ * instead, the support here is for backward compatibility only.
+ * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request
+ * or rename notification. Has attributes %NL80211_ATTR_WIPHY and
+ * %NL80211_ATTR_WIPHY_NAME.
+ * @NL80211_CMD_DEL_WIPHY: Wiphy deleted. Has attributes
+ * %NL80211_ATTR_WIPHY and %NL80211_ATTR_WIPHY_NAME.
+ *
+ * @NL80211_CMD_GET_INTERFACE: Request an interface's configuration;
+ * either a dump request on a %NL80211_ATTR_WIPHY or a specific get
+ * on an %NL80211_ATTR_IFINDEX is supported.
+ * @NL80211_CMD_SET_INTERFACE: Set type of a virtual interface, requires
+ * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_IFTYPE.
+ * @NL80211_CMD_NEW_INTERFACE: Newly created virtual interface or response
+ * to %NL80211_CMD_GET_INTERFACE. Has %NL80211_ATTR_IFINDEX,
+ * %NL80211_ATTR_WIPHY and %NL80211_ATTR_IFTYPE attributes. Can also
+ * be sent from userspace to request creation of a new virtual interface,
+ * then requires attributes %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFTYPE and
+ * %NL80211_ATTR_IFNAME.
+ * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes
+ * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from
+ * userspace to request deletion of a virtual interface, then requires
+ * attribute %NL80211_ATTR_IFINDEX.
+ *
+ * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified
+ * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC.
+ * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT,
+ * %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD.
+ * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA,
+ * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER,
+ * and %NL80211_ATTR_KEY_SEQ attributes.
+ * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX
+ * or %NL80211_ATTR_MAC.
+ *
+ * @NL80211_CMD_GET_BEACON: retrieve beacon information (returned in a
+ * %NL80222_CMD_NEW_BEACON message)
+ * @NL80211_CMD_SET_BEACON: set the beacon on an access point interface
+ * using the %NL80211_ATTR_BEACON_INTERVAL, %NL80211_ATTR_DTIM_PERIOD,
+ * %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL attributes.
+ * Following attributes are provided for drivers that generate full Beacon
+ * and Probe Response frames internally: %NL80211_ATTR_SSID,
+ * %NL80211_ATTR_HIDDEN_SSID, %NL80211_ATTR_CIPHERS_PAIRWISE,
+ * %NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS,
+ * %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY,
+ * %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_IE, %NL80211_ATTR_IE_PROBE_RESP,
+ * %NL80211_ATTR_IE_ASSOC_RESP.
+ * @NL80211_CMD_NEW_BEACON: add a new beacon to an access point interface,
+ * parameters are like for %NL80211_CMD_SET_BEACON.
+ * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it
+ *
+ * @NL80211_CMD_GET_STATION: Get station attributes for station identified by
+ * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_SET_STATION: Set station attributes for station identified by
+ * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_NEW_STATION: Add a station with given attributes to the
+ * the interface identified by %NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_DEL_STATION: Remove a station identified by %NL80211_ATTR_MAC
+ * or, if no MAC address given, all stations, on the interface identified
+ * by %NL80211_ATTR_IFINDEX.
+ *
+ * @NL80211_CMD_GET_MPATH: Get mesh path attributes for mesh path to
+ * destination %NL80211_ATTR_MAC on the interface identified by
+ * %NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_SET_MPATH: Set mesh path attributes for mesh path to
+ * destination %NL80211_ATTR_MAC on the interface identified by
+ * %NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_NEW_MPATH: Create a new mesh path for the destination given by
+ * %NL80211_ATTR_MAC via %NL80211_ATTR_MPATH_NEXT_HOP.
+ * @NL80211_CMD_DEL_MPATH: Delete a mesh path to the destination given by
+ * %NL80211_ATTR_MAC.
+ * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the
+ * the interface identified by %NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC
+ * or, if no MAC address given, all mesh paths, on the interface identified
+ * by %NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by
+ * %NL80211_ATTR_IFINDEX.
+ *
+ * @NL80211_CMD_GET_REG: ask the wireless core to send us its currently set
+ * regulatory domain.
+ * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command
+ * after being queried by the kernel. CRDA replies by sending a regulatory
+ * domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our
+ * current alpha2 if it found a match. It also provides
+ * NL80211_ATTR_REG_RULE_FLAGS, and a set of regulatory rules. Each
+ * regulatory rule is a nested set of attributes given by
+ * %NL80211_ATTR_REG_RULE_FREQ_[START|END] and
+ * %NL80211_ATTR_FREQ_RANGE_MAX_BW with an attached power rule given by
+ * %NL80211_ATTR_REG_RULE_POWER_MAX_ANT_GAIN and
+ * %NL80211_ATTR_REG_RULE_POWER_MAX_EIRP.
+ * @NL80211_CMD_REQ_SET_REG: ask the wireless core to set the regulatory domain
+ * to the specified ISO/IEC 3166-1 alpha2 country code. The core will
+ * store this as a valid request and then query userspace for it.
+ *
+ * @NL80211_CMD_GET_MESH_CONFIG: Get mesh networking properties for the
+ * interface identified by %NL80211_ATTR_IFINDEX
+ *
+ * @NL80211_CMD_SET_MESH_CONFIG: Set mesh networking properties for the
+ * interface identified by %NL80211_ATTR_IFINDEX
+ *
+ * @NL80211_CMD_SET_MGMT_EXTRA_IE: Set extra IEs for management frames. The
+ * interface is identified with %NL80211_ATTR_IFINDEX and the management
+ * frame subtype with %NL80211_ATTR_MGMT_SUBTYPE. The extra IE data to be
+ * added to the end of the specified management frame is specified with
+ * %NL80211_ATTR_IE. If the command succeeds, the requested data will be
+ * added to all specified management frames generated by
+ * kernel/firmware/driver.
+ * Note: This command has been removed and it is only reserved at this
+ * point to avoid re-using existing command number. The functionality this
+ * command was planned for has been provided with cleaner design with the
+ * option to specify additional IEs in NL80211_CMD_TRIGGER_SCAN,
+ * NL80211_CMD_AUTHENTICATE, NL80211_CMD_ASSOCIATE,
+ * NL80211_CMD_DEAUTHENTICATE, and NL80211_CMD_DISASSOCIATE.
+ *
+ * @NL80211_CMD_GET_SCAN: get scan results
+ * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters
+ * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the
+ * probe requests at CCK rate or not.
+ * @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to
+ * NL80211_CMD_GET_SCAN and on the "scan" multicast group)
+ * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons,
+ * partial scan results may be available
+ *
+ * @NL80211_CMD_START_SCHED_SCAN: start a scheduled scan at certain
+ * intervals, as specified by %NL80211_ATTR_SCHED_SCAN_INTERVAL.
+ * Like with normal scans, if SSIDs (%NL80211_ATTR_SCAN_SSIDS)
+ * are passed, they are used in the probe requests. For
+ * broadcast, a broadcast SSID must be passed (ie. an empty
+ * string). If no SSID is passed, no probe requests are sent and
+ * a passive scan is performed. %NL80211_ATTR_SCAN_FREQUENCIES,
+ * if passed, define which channels should be scanned; if not
+ * passed, all channels allowed for the current regulatory domain
+ * are used. Extra IEs can also be passed from the userspace by
+ * using the %NL80211_ATTR_IE attribute.
+ * @NL80211_CMD_STOP_SCHED_SCAN: stop a scheduled scan. Returns -ENOENT
+ * if scheduled scan is not running.
+ * @NL80211_CMD_SCHED_SCAN_RESULTS: indicates that there are scheduled scan
+ * results available.
+ * @NL80211_CMD_SCHED_SCAN_STOPPED: indicates that the scheduled scan has
+ * stopped. The driver may issue this event at any time during a
+ * scheduled scan. One reason for stopping the scan is if the hardware
+ * does not support starting an association or a normal scan while running
+ * a scheduled scan. This event is also sent when the
+ * %NL80211_CMD_STOP_SCHED_SCAN command is received or when the interface
+ * is brought down while a scheduled scan was running.
+ *
+ * @NL80211_CMD_GET_SURVEY: get survey resuls, e.g. channel occupation
+ * or noise level
+ * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to
+ * NL80211_CMD_GET_SURVEY and on the "scan" multicast group)
+ *
+ * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain
+ * has been changed and provides details of the request information
+ * that caused the change such as who initiated the regulatory request
+ * (%NL80211_ATTR_REG_INITIATOR), the wiphy_idx
+ * (%NL80211_ATTR_REG_ALPHA2) on which the request was made from if
+ * the initiator was %NL80211_REGDOM_SET_BY_COUNTRY_IE or
+ * %NL80211_REGDOM_SET_BY_DRIVER, the type of regulatory domain
+ * set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is
+ * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on
+ * to (%NL80211_ATTR_REG_ALPHA2).
+ * @NL80211_CMD_REG_BEACON_HINT: indicates to userspace that an AP beacon
+ * has been found while world roaming thus enabling active scan or
+ * any mode of operation that initiates TX (beacons) on a channel
+ * where we would not have been able to do either before. As an example
+ * if you are world roaming (regulatory domain set to world or if your
+ * driver is using a custom world roaming regulatory domain) and while
+ * doing a passive scan on the 5 GHz band you find an AP there (if not
+ * on a DFS channel) you will now be able to actively scan for that AP
+ * or use AP mode on your card on that same channel. Note that this will
+ * never be used for channels 1-11 on the 2 GHz band as they are always
+ * enabled world wide. This beacon hint is only sent if your device had
+ * either disabled active scanning or beaconing on a channel. We send to
+ * userspace the wiphy on which we removed a restriction from
+ * (%NL80211_ATTR_WIPHY) and the channel on which this occurred
+ * before (%NL80211_ATTR_FREQ_BEFORE) and after (%NL80211_ATTR_FREQ_AFTER)
+ * the beacon hint was processed.
+ *
+ * @NL80211_CMD_AUTHENTICATE: authentication request and notification.
+ * This command is used both as a command (request to authenticate) and
+ * as an event on the "mlme" multicast group indicating completion of the
+ * authentication process.
+ * When used as a command, %NL80211_ATTR_IFINDEX is used to identify the
+ * interface. %NL80211_ATTR_MAC is used to specify PeerSTAAddress (and
+ * BSSID in case of station mode). %NL80211_ATTR_SSID is used to specify
+ * the SSID (mainly for association, but is included in authentication
+ * request, too, to help BSS selection. %NL80211_ATTR_WIPHY_FREQ is used
+ * to specify the frequence of the channel in MHz. %NL80211_ATTR_AUTH_TYPE
+ * is used to specify the authentication type. %NL80211_ATTR_IE is used to
+ * define IEs (VendorSpecificInfo, but also including RSN IE and FT IEs)
+ * to be added to the frame.
+ * When used as an event, this reports reception of an Authentication
+ * frame in station and IBSS modes when the local MLME processed the
+ * frame, i.e., it was for the local STA and was received in correct
+ * state. This is similar to MLME-AUTHENTICATE.confirm primitive in the
+ * MLME SAP interface (kernel providing MLME, userspace SME). The
+ * included %NL80211_ATTR_FRAME attribute contains the management frame
+ * (including both the header and frame body, but not FCS). This event is
+ * also used to indicate if the authentication attempt timed out. In that
+ * case the %NL80211_ATTR_FRAME attribute is replaced with a
+ * %NL80211_ATTR_TIMED_OUT flag (and %NL80211_ATTR_MAC to indicate which
+ * pending authentication timed out).
+ * @NL80211_CMD_ASSOCIATE: association request and notification; like
+ * NL80211_CMD_AUTHENTICATE but for Association and Reassociation
+ * (similar to MLME-ASSOCIATE.request, MLME-REASSOCIATE.request,
+ * MLME-ASSOCIATE.confirm or MLME-REASSOCIATE.confirm primitives).
+ * @NL80211_CMD_DEAUTHENTICATE: deauthentication request and notification; like
+ * NL80211_CMD_AUTHENTICATE but for Deauthentication frames (similar to
+ * MLME-DEAUTHENTICATION.request and MLME-DEAUTHENTICATE.indication
+ * primitives).
+ * @NL80211_CMD_DISASSOCIATE: disassociation request and notification; like
+ * NL80211_CMD_AUTHENTICATE but for Disassociation frames (similar to
+ * MLME-DISASSOCIATE.request and MLME-DISASSOCIATE.indication primitives).
+ *
+ * @NL80211_CMD_MICHAEL_MIC_FAILURE: notification of a locally detected Michael
+ * MIC (part of TKIP) failure; sent on the "mlme" multicast group; the
+ * event includes %NL80211_ATTR_MAC to describe the source MAC address of
+ * the frame with invalid MIC, %NL80211_ATTR_KEY_TYPE to show the key
+ * type, %NL80211_ATTR_KEY_IDX to indicate the key identifier, and
+ * %NL80211_ATTR_KEY_SEQ to indicate the TSC value of the frame; this
+ * event matches with MLME-MICHAELMICFAILURE.indication() primitive
+ *
+ * @NL80211_CMD_JOIN_IBSS: Join a new IBSS -- given at least an SSID and a
+ * FREQ attribute (for the initial frequency if no peer can be found)
+ * and optionally a MAC (as BSSID) and FREQ_FIXED attribute if those
+ * should be fixed rather than automatically determined. Can only be
+ * executed on a network interface that is UP, and fixed BSSID/FREQ
+ * may be rejected. Another optional parameter is the beacon interval,
+ * given in the %NL80211_ATTR_BEACON_INTERVAL attribute, which if not
+ * given defaults to 100 TU (102.4ms).
+ * @NL80211_CMD_LEAVE_IBSS: Leave the IBSS -- no special arguments, the IBSS is
+ * determined by the network interface.
+ *
+ * @NL80211_CMD_TESTMODE: testmode command, takes a wiphy (or ifindex) attribute
+ * to identify the device, and the TESTDATA blob attribute to pass through
+ * to the driver.
+ *
+ * @NL80211_CMD_CONNECT: connection request and notification; this command
+ * requests to connect to a specified network but without separating
+ * auth and assoc steps. For this, you need to specify the SSID in a
+ * %NL80211_ATTR_SSID attribute, and can optionally specify the association
+ * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_MAC,
+ * %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT,
+ * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE and
+ * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT.
+ * It is also sent as an event, with the BSSID and response IEs when the
+ * connection is established or failed to be established. This can be
+ * determined by the STATUS_CODE attribute.
+ * @NL80211_CMD_ROAM: request that the card roam (currently not implemented),
+ * sent as an event when the card/driver roamed by itself.
+ * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify
+ * userspace that a connection was dropped by the AP or due to other
+ * reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and
+ * %NL80211_ATTR_REASON_CODE attributes are used.
+ *
+ * @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices
+ * associated with this wiphy must be down and will follow.
+ *
+ * @NL80211_CMD_REMAIN_ON_CHANNEL: Request to remain awake on the specified
+ * channel for the specified amount of time. This can be used to do
+ * off-channel operations like transmit a Public Action frame and wait for
+ * a response while being associated to an AP on another channel.
+ * %NL80211_ATTR_IFINDEX is used to specify which interface (and thus
+ * radio) is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the
+ * frequency for the operation and %NL80211_ATTR_WIPHY_CHANNEL_TYPE may be
+ * optionally used to specify additional channel parameters.
+ * %NL80211_ATTR_DURATION is used to specify the duration in milliseconds
+ * to remain on the channel. This command is also used as an event to
+ * notify when the requested duration starts (it may take a while for the
+ * driver to schedule this time due to other concurrent needs for the
+ * radio).
+ * When called, this operation returns a cookie (%NL80211_ATTR_COOKIE)
+ * that will be included with any events pertaining to this request;
+ * the cookie is also used to cancel the request.
+ * @NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL: This command can be used to cancel a
+ * pending remain-on-channel duration if the desired operation has been
+ * completed prior to expiration of the originally requested duration.
+ * %NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify the
+ * radio. The %NL80211_ATTR_COOKIE attribute must be given as well to
+ * uniquely identify the request.
+ * This command is also used as an event to notify when a requested
+ * remain-on-channel duration has expired.
+ *
+ * @NL80211_CMD_SET_TX_BITRATE_MASK: Set the mask of rates to be used in TX
+ * rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface
+ * and @NL80211_ATTR_TX_RATES the set of allowed rates.
+ *
+ * @NL80211_CMD_REGISTER_FRAME: Register for receiving certain mgmt frames
+ * (via @NL80211_CMD_FRAME) for processing in userspace. This command
+ * requires an interface index, a frame type attribute (optional for
+ * backward compatibility reasons, if not given assumes action frames)
+ * and a match attribute containing the first few bytes of the frame
+ * that should match, e.g. a single byte for only a category match or
+ * four bytes for vendor frames including the OUI. The registration
+ * cannot be dropped, but is removed automatically when the netlink
+ * socket is closed. Multiple registrations can be made.
+ * @NL80211_CMD_REGISTER_ACTION: Alias for @NL80211_CMD_REGISTER_FRAME for
+ * backward compatibility
+ * @NL80211_CMD_FRAME: Management frame TX request and RX notification. This
+ * command is used both as a request to transmit a management frame and
+ * as an event indicating reception of a frame that was not processed in
+ * kernel code, but is for us (i.e., which may need to be processed in a
+ * user space application). %NL80211_ATTR_FRAME is used to specify the
+ * frame contents (including header). %NL80211_ATTR_WIPHY_FREQ (and
+ * optionally %NL80211_ATTR_WIPHY_CHANNEL_TYPE) is used to indicate on
+ * which channel the frame is to be transmitted or was received. If this
+ * channel is not the current channel (remain-on-channel or the
+ * operational channel) the device will switch to the given channel and
+ * transmit the frame, optionally waiting for a response for the time
+ * specified using %NL80211_ATTR_DURATION. When called, this operation
+ * returns a cookie (%NL80211_ATTR_COOKIE) that will be included with the
+ * TX status event pertaining to the TX request.
+ * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the
+ * management frames at CCK rate or not in 2GHz band.
+ * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this
+ * command may be used with the corresponding cookie to cancel the wait
+ * time if it is known that it is no longer necessary.
+ * @NL80211_CMD_ACTION: Alias for @NL80211_CMD_FRAME for backward compatibility.
+ * @NL80211_CMD_FRAME_TX_STATUS: Report TX status of a management frame
+ * transmitted with %NL80211_CMD_FRAME. %NL80211_ATTR_COOKIE identifies
+ * the TX command and %NL80211_ATTR_FRAME includes the contents of the
+ * frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged
+ * the frame.
+ * @NL80211_CMD_ACTION_TX_STATUS: Alias for @NL80211_CMD_FRAME_TX_STATUS for
+ * backward compatibility.
+ * @NL80211_CMD_SET_CQM: Connection quality monitor configuration. This command
+ * is used to configure connection quality monitoring notification trigger
+ * levels.
+ * @NL80211_CMD_NOTIFY_CQM: Connection quality monitor notification. This
+ * command is used as an event to indicate the that a trigger level was
+ * reached.
+ * @NL80211_CMD_SET_CHANNEL: Set the channel (using %NL80211_ATTR_WIPHY_FREQ
+ * and %NL80211_ATTR_WIPHY_CHANNEL_TYPE) the given interface (identifed
+ * by %NL80211_ATTR_IFINDEX) shall operate on.
+ * In case multiple channels are supported by the device, the mechanism
+ * with which it switches channels is implementation-defined.
+ * When a monitor interface is given, it can only switch channel while
+ * no other interfaces are operating to avoid disturbing the operation
+ * of any other interfaces, and other interfaces will again take
+ * precedence when they are used.
+ *
+ * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface.
+ *
+ * @NL80211_CMD_JOIN_MESH: Join a mesh. The mesh ID must be given, and initial
+ * mesh config parameters may be given.
+ * @NL80211_CMD_LEAVE_MESH: Leave the mesh network -- no special arguments, the
+ * network is determined by the network interface.
+ *
+ * @NL80211_CMD_UNPROT_DEAUTHENTICATE: Unprotected deauthentication frame
+ * notification. This event is used to indicate that an unprotected
+ * deauthentication frame was dropped when MFP is in use.
+ * @NL80211_CMD_UNPROT_DISASSOCIATE: Unprotected disassociation frame
+ * notification. This event is used to indicate that an unprotected
+ * disassociation frame was dropped when MFP is in use.
+ *
+ * @NL80211_CMD_NEW_PEER_CANDIDATE: Notification on the reception of a
+ * beacon or probe response from a compatible mesh peer. This is only
+ * sent while no station information (sta_info) exists for the new peer
+ * candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH is set. On
+ * reception of this notification, userspace may decide to create a new
+ * station (@NL80211_CMD_NEW_STATION). To stop this notification from
+ * reoccurring, the userspace authentication daemon may want to create the
+ * new station with the AUTHENTICATED flag unset and maybe change it later
+ * depending on the authentication result.
+ *
+ * @NL80211_CMD_GET_WOWLAN: get Wake-on-Wireless-LAN (WoWLAN) settings.
+ * @NL80211_CMD_SET_WOWLAN: set Wake-on-Wireless-LAN (WoWLAN) settings.
+ * Since wireless is more complex than wired ethernet, it supports
+ * various triggers. These triggers can be configured through this
+ * command with the %NL80211_ATTR_WOWLAN_TRIGGERS attribute. For
+ * more background information, see
+ * http://wireless.kernel.org/en/users/Documentation/WoWLAN.
+ *
+ * @NL80211_CMD_SET_REKEY_OFFLOAD: This command is used give the driver
+ * the necessary information for supporting GTK rekey offload. This
+ * feature is typically used during WoWLAN. The configuration data
+ * is contained in %NL80211_ATTR_REKEY_DATA (which is nested and
+ * contains the data in sub-attributes). After rekeying happened,
+ * this command may also be sent by the driver as an MLME event to
+ * inform userspace of the new replay counter.
+ *
+ * @NL80211_CMD_PMKSA_CANDIDATE: This is used as an event to inform userspace
+ * of PMKSA caching dandidates.
+ *
+ * @NL80211_CMD_TDLS_OPER: Perform a high-level TDLS command (e.g. link setup).
+ * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame.
+ *
+ * @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP
+ * (or GO) interface (i.e. hostapd) to ask for unexpected frames to
+ * implement sending deauth to stations that send unexpected class 3
+ * frames. Also used as the event sent by the kernel when such a frame
+ * is received.
+ * For the event, the %NL80211_ATTR_MAC attribute carries the TA and
+ * other attributes like the interface index are present.
+ * If used as the command it must have an interface index and you can
+ * only unsubscribe from the event by closing the socket. Subscription
+ * is also for %NL80211_CMD_UNEXPECTED_4ADDR_FRAME events.
+ *
+ * @NL80211_CMD_UNEXPECTED_4ADDR_FRAME: Sent as an event indicating that the
+ * associated station identified by %NL80211_ATTR_MAC sent a 4addr frame
+ * and wasn't already in a 4-addr VLAN. The event will be sent similarly
+ * to the %NL80211_CMD_UNEXPECTED_FRAME event, to the same listener.
+ *
+ * @NL80211_CMD_PROBE_CLIENT: Probe an associated station on an AP interface
+ * by sending a null data frame to it and reporting when the frame is
+ * acknowleged. This is used to allow timing out inactive clients. Uses
+ * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_MAC. The command returns a
+ * direct reply with an %NL80211_ATTR_COOKIE that is later used to match
+ * up the event with the request. The event includes the same data and
+ * has %NL80211_ATTR_ACK set if the frame was ACKed.
+ *
+ * @NL80211_CMD_REGISTER_BEACONS: Register this socket to receive beacons from
+ * other BSSes when any interfaces are in AP mode. This helps implement
+ * OLBC handling in hostapd. Beacons are reported in %NL80211_CMD_FRAME
+ * messages. Note that per PHY only one application may register.
+ *
+ * @NL80211_CMD_SET_NOACK_MAP: sets a bitmap for the individual TIDs whether
+ * No Acknowledgement Policy should be applied.
+ *
+ * @NL80211_CMD_MAX: highest used command number
+ * @__NL80211_CMD_AFTER_LAST: internal use
+ */
+enum nl80211_commands {
+/* don't change the order or add anything between, this is ABI! */
+ NL80211_CMD_UNSPEC,
+
+ NL80211_CMD_GET_WIPHY, /* can dump */
+ NL80211_CMD_SET_WIPHY,
+ NL80211_CMD_NEW_WIPHY,
+ NL80211_CMD_DEL_WIPHY,
+
+ NL80211_CMD_GET_INTERFACE, /* can dump */
+ NL80211_CMD_SET_INTERFACE,
+ NL80211_CMD_NEW_INTERFACE,
+ NL80211_CMD_DEL_INTERFACE,
+
+ NL80211_CMD_GET_KEY,
+ NL80211_CMD_SET_KEY,
+ NL80211_CMD_NEW_KEY,
+ NL80211_CMD_DEL_KEY,
+
+ NL80211_CMD_GET_BEACON,
+ NL80211_CMD_SET_BEACON,
+ NL80211_CMD_NEW_BEACON,
+ NL80211_CMD_DEL_BEACON,
+
+ NL80211_CMD_GET_STATION,
+ NL80211_CMD_SET_STATION,
+ NL80211_CMD_NEW_STATION,
+ NL80211_CMD_DEL_STATION,
+
+ NL80211_CMD_GET_MPATH,
+ NL80211_CMD_SET_MPATH,
+ NL80211_CMD_NEW_MPATH,
+ NL80211_CMD_DEL_MPATH,
+
+ NL80211_CMD_SET_BSS,
+
+ NL80211_CMD_SET_REG,
+ NL80211_CMD_REQ_SET_REG,
+
+ NL80211_CMD_GET_MESH_CONFIG,
+ NL80211_CMD_SET_MESH_CONFIG,
+
+ NL80211_CMD_SET_MGMT_EXTRA_IE /* reserved; not used */,
+
+ NL80211_CMD_GET_REG,
+
+ NL80211_CMD_GET_SCAN,
+ NL80211_CMD_TRIGGER_SCAN,
+ NL80211_CMD_NEW_SCAN_RESULTS,
+ NL80211_CMD_SCAN_ABORTED,
+
+ NL80211_CMD_REG_CHANGE,
+
+ NL80211_CMD_AUTHENTICATE,
+ NL80211_CMD_ASSOCIATE,
+ NL80211_CMD_DEAUTHENTICATE,
+ NL80211_CMD_DISASSOCIATE,
+
+ NL80211_CMD_MICHAEL_MIC_FAILURE,
+
+ NL80211_CMD_REG_BEACON_HINT,
+
+ NL80211_CMD_JOIN_IBSS,
+ NL80211_CMD_LEAVE_IBSS,
+
+ NL80211_CMD_TESTMODE,
+
+ NL80211_CMD_CONNECT,
+ NL80211_CMD_ROAM,
+ NL80211_CMD_DISCONNECT,
+
+ NL80211_CMD_SET_WIPHY_NETNS,
+
+ NL80211_CMD_GET_SURVEY,
+ NL80211_CMD_NEW_SURVEY_RESULTS,
+
+ NL80211_CMD_SET_PMKSA,
+ NL80211_CMD_DEL_PMKSA,
+ NL80211_CMD_FLUSH_PMKSA,
+
+ NL80211_CMD_REMAIN_ON_CHANNEL,
+ NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
+
+ NL80211_CMD_SET_TX_BITRATE_MASK,
+
+ NL80211_CMD_REGISTER_FRAME,
+ NL80211_CMD_REGISTER_ACTION = NL80211_CMD_REGISTER_FRAME,
+ NL80211_CMD_FRAME,
+ NL80211_CMD_ACTION = NL80211_CMD_FRAME,
+ NL80211_CMD_FRAME_TX_STATUS,
+ NL80211_CMD_ACTION_TX_STATUS = NL80211_CMD_FRAME_TX_STATUS,
+
+ NL80211_CMD_SET_POWER_SAVE,
+ NL80211_CMD_GET_POWER_SAVE,
+
+ NL80211_CMD_SET_CQM,
+ NL80211_CMD_NOTIFY_CQM,
+
+ NL80211_CMD_SET_CHANNEL,
+ NL80211_CMD_SET_WDS_PEER,
+
+ NL80211_CMD_FRAME_WAIT_CANCEL,
+
+ NL80211_CMD_JOIN_MESH,
+ NL80211_CMD_LEAVE_MESH,
+
+ NL80211_CMD_UNPROT_DEAUTHENTICATE,
+ NL80211_CMD_UNPROT_DISASSOCIATE,
+
+ NL80211_CMD_NEW_PEER_CANDIDATE,
+
+ NL80211_CMD_GET_WOWLAN,
+ NL80211_CMD_SET_WOWLAN,
+
+ NL80211_CMD_START_SCHED_SCAN,
+ NL80211_CMD_STOP_SCHED_SCAN,
+ NL80211_CMD_SCHED_SCAN_RESULTS,
+ NL80211_CMD_SCHED_SCAN_STOPPED,
+
+ NL80211_CMD_SET_REKEY_OFFLOAD,
+
+ NL80211_CMD_PMKSA_CANDIDATE,
+
+ NL80211_CMD_TDLS_OPER,
+ NL80211_CMD_TDLS_MGMT,
+
+ NL80211_CMD_UNEXPECTED_FRAME,
+
+ NL80211_CMD_PROBE_CLIENT,
+
+ NL80211_CMD_REGISTER_BEACONS,
+
+ NL80211_CMD_UNEXPECTED_4ADDR_FRAME,
+
+ NL80211_CMD_SET_NOACK_MAP,
+
+ /* add new commands above here */
+
+ /* used to define NL80211_CMD_MAX below */
+ __NL80211_CMD_AFTER_LAST,
+ NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1
+};
+
+/*
+ * Allow user space programs to use #ifdef on new commands by defining them
+ * here
+ */
+#define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS
+#define NL80211_CMD_SET_MGMT_EXTRA_IE NL80211_CMD_SET_MGMT_EXTRA_IE
+#define NL80211_CMD_REG_CHANGE NL80211_CMD_REG_CHANGE
+#define NL80211_CMD_AUTHENTICATE NL80211_CMD_AUTHENTICATE
+#define NL80211_CMD_ASSOCIATE NL80211_CMD_ASSOCIATE
+#define NL80211_CMD_DEAUTHENTICATE NL80211_CMD_DEAUTHENTICATE
+#define NL80211_CMD_DISASSOCIATE NL80211_CMD_DISASSOCIATE
+#define NL80211_CMD_REG_BEACON_HINT NL80211_CMD_REG_BEACON_HINT
+
+#define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS
+
+/* source-level API compatibility */
+#define NL80211_CMD_GET_MESH_PARAMS NL80211_CMD_GET_MESH_CONFIG
+#define NL80211_CMD_SET_MESH_PARAMS NL80211_CMD_SET_MESH_CONFIG
+#define NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE NL80211_MESH_SETUP_IE
+
+/**
+ * enum nl80211_attrs - nl80211 netlink attributes
+ *
+ * @NL80211_ATTR_UNSPEC: unspecified attribute to catch errors
+ *
+ * @NL80211_ATTR_WIPHY: index of wiphy to operate on, cf.
+ * /sys/class/ieee80211/<phyname>/index
+ * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming)
+ * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters
+ * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz
+ * @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ
+ * if HT20 or HT40 are allowed (i.e., 802.11n disabled if not included):
+ * NL80211_CHAN_NO_HT = HT not allowed (i.e., same as not including
+ * this attribute)
+ * NL80211_CHAN_HT20 = HT20 only
+ * NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel
+ * NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel
+ * @NL80211_ATTR_WIPHY_RETRY_SHORT: TX retry limit for frames whose length is
+ * less than or equal to the RTS threshold; allowed range: 1..255;
+ * dot11ShortRetryLimit; u8
+ * @NL80211_ATTR_WIPHY_RETRY_LONG: TX retry limit for frames whose length is
+ * greater than the RTS threshold; allowed range: 1..255;
+ * dot11ShortLongLimit; u8
+ * @NL80211_ATTR_WIPHY_FRAG_THRESHOLD: fragmentation threshold, i.e., maximum
+ * length in octets for frames; allowed range: 256..8000, disable
+ * fragmentation with (u32)-1; dot11FragmentationThreshold; u32
+ * @NL80211_ATTR_WIPHY_RTS_THRESHOLD: RTS threshold (TX frames with length
+ * larger than or equal to this use RTS/CTS handshake); allowed range:
+ * 0..65536, disable with (u32)-1; dot11RTSThreshold; u32
+ * @NL80211_ATTR_WIPHY_COVERAGE_CLASS: Coverage Class as defined by IEEE 802.11
+ * section 7.3.2.9; dot11CoverageClass; u8
+ *
+ * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on
+ * @NL80211_ATTR_IFNAME: network interface name
+ * @NL80211_ATTR_IFTYPE: type of virtual interface, see &enum nl80211_iftype
+ *
+ * @NL80211_ATTR_MAC: MAC address (various uses)
+ *
+ * @NL80211_ATTR_KEY_DATA: (temporal) key data; for TKIP this consists of
+ * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC
+ * keys
+ * @NL80211_ATTR_KEY_IDX: key ID (u8, 0-3)
+ * @NL80211_ATTR_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11
+ * section 7.3.2.25.1, e.g. 0x000FAC04)
+ * @NL80211_ATTR_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and
+ * CCMP keys, each six bytes in little endian
+ *
+ * @NL80211_ATTR_BEACON_INTERVAL: beacon interval in TU
+ * @NL80211_ATTR_DTIM_PERIOD: DTIM period for beaconing
+ * @NL80211_ATTR_BEACON_HEAD: portion of the beacon before the TIM IE
+ * @NL80211_ATTR_BEACON_TAIL: portion of the beacon after the TIM IE
+ *
+ * @NL80211_ATTR_STA_AID: Association ID for the station (u16)
+ * @NL80211_ATTR_STA_FLAGS: flags, nested element with NLA_FLAG attributes of
+ * &enum nl80211_sta_flags (deprecated, use %NL80211_ATTR_STA_FLAGS2)
+ * @NL80211_ATTR_STA_LISTEN_INTERVAL: listen interval as defined by
+ * IEEE 802.11 7.3.1.6 (u16).
+ * @NL80211_ATTR_STA_SUPPORTED_RATES: supported rates, array of supported
+ * rates as defined by IEEE 802.11 7.3.2.2 but without the length
+ * restriction (at most %NL80211_MAX_SUPP_RATES).
+ * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station
+ * to, or the AP interface the station was originally added to to.
+ * @NL80211_ATTR_STA_INFO: information about a station, part of station info
+ * given for %NL80211_CMD_GET_STATION, nested attribute containing
+ * info as possible, see &enum nl80211_sta_info.
+ *
+ * @NL80211_ATTR_WIPHY_BANDS: Information about an operating bands,
+ * consisting of a nested array.
+ *
+ * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes).
+ * @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link.
+ * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path.
+ * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path
+ * info given for %NL80211_CMD_GET_MPATH, nested attribute described at
+ * &enum nl80211_mpath_info.
+ *
+ * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of
+ * &enum nl80211_mntr_flags.
+ *
+ * @NL80211_ATTR_REG_ALPHA2: an ISO-3166-alpha2 country code for which the
+ * current regulatory domain should be set to or is already set to.
+ * For example, 'CR', for Costa Rica. This attribute is used by the kernel
+ * to query the CRDA to retrieve one regulatory domain. This attribute can
+ * also be used by userspace to query the kernel for the currently set
+ * regulatory domain. We chose an alpha2 as that is also used by the
+ * IEEE-802.11d country information element to identify a country.
+ * Users can also simply ask the wireless core to set regulatory domain
+ * to a specific alpha2.
+ * @NL80211_ATTR_REG_RULES: a nested array of regulatory domain regulatory
+ * rules.
+ *
+ * @NL80211_ATTR_BSS_CTS_PROT: whether CTS protection is enabled (u8, 0 or 1)
+ * @NL80211_ATTR_BSS_SHORT_PREAMBLE: whether short preamble is enabled
+ * (u8, 0 or 1)
+ * @NL80211_ATTR_BSS_SHORT_SLOT_TIME: whether short slot time enabled
+ * (u8, 0 or 1)
+ * @NL80211_ATTR_BSS_BASIC_RATES: basic rates, array of basic
+ * rates in format defined by IEEE 802.11 7.3.2.2 but without the length
+ * restriction (at most %NL80211_MAX_SUPP_RATES).
+ *
+ * @NL80211_ATTR_HT_CAPABILITY: HT Capability information element (from
+ * association request when used with NL80211_CMD_NEW_STATION)
+ *
+ * @NL80211_ATTR_SUPPORTED_IFTYPES: nested attribute containing all
+ * supported interface types, each a flag attribute with the number
+ * of the interface mode.
+ *
+ * @NL80211_ATTR_MGMT_SUBTYPE: Management frame subtype for
+ * %NL80211_CMD_SET_MGMT_EXTRA_IE.
+ *
+ * @NL80211_ATTR_IE: Information element(s) data (used, e.g., with
+ * %NL80211_CMD_SET_MGMT_EXTRA_IE).
+ *
+ * @NL80211_ATTR_MAX_NUM_SCAN_SSIDS: number of SSIDs you can scan with
+ * a single scan request, a wiphy attribute.
+ * @NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS: number of SSIDs you can
+ * scan with a single scheduled scan request, a wiphy attribute.
+ * @NL80211_ATTR_MAX_SCAN_IE_LEN: maximum length of information elements
+ * that can be added to a scan request
+ * @NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN: maximum length of information
+ * elements that can be added to a scheduled scan request
+ * @NL80211_ATTR_MAX_MATCH_SETS: maximum number of sets that can be
+ * used with @NL80211_ATTR_SCHED_SCAN_MATCH, a wiphy attribute.
+ *
+ * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz)
+ * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive
+ * scanning and include a zero-length SSID (wildcard) for wildcard scan
+ * @NL80211_ATTR_BSS: scan result BSS
+ *
+ * @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain
+ * currently in effect. This could be any of the %NL80211_REGDOM_SET_BY_*
+ * @NL80211_ATTR_REG_TYPE: indicates the type of the regulatory domain currently
+ * set. This can be one of the nl80211_reg_type (%NL80211_REGDOM_TYPE_*)
+ *
+ * @NL80211_ATTR_SUPPORTED_COMMANDS: wiphy attribute that specifies
+ * an array of command numbers (i.e. a mapping index to command number)
+ * that the driver for the given wiphy supports.
+ *
+ * @NL80211_ATTR_FRAME: frame data (binary attribute), including frame header
+ * and body, but not FCS; used, e.g., with NL80211_CMD_AUTHENTICATE and
+ * NL80211_CMD_ASSOCIATE events
+ * @NL80211_ATTR_SSID: SSID (binary attribute, 0..32 octets)
+ * @NL80211_ATTR_AUTH_TYPE: AuthenticationType, see &enum nl80211_auth_type,
+ * represented as a u32
+ * @NL80211_ATTR_REASON_CODE: ReasonCode for %NL80211_CMD_DEAUTHENTICATE and
+ * %NL80211_CMD_DISASSOCIATE, u16
+ *
+ * @NL80211_ATTR_KEY_TYPE: Key Type, see &enum nl80211_key_type, represented as
+ * a u32
+ *
+ * @NL80211_ATTR_FREQ_BEFORE: A channel which has suffered a regulatory change
+ * due to considerations from a beacon hint. This attribute reflects
+ * the state of the channel _before_ the beacon hint processing. This
+ * attributes consists of a nested attribute containing
+ * NL80211_FREQUENCY_ATTR_*
+ * @NL80211_ATTR_FREQ_AFTER: A channel which has suffered a regulatory change
+ * due to considerations from a beacon hint. This attribute reflects
+ * the state of the channel _after_ the beacon hint processing. This
+ * attributes consists of a nested attribute containing
+ * NL80211_FREQUENCY_ATTR_*
+ *
+ * @NL80211_ATTR_CIPHER_SUITES: a set of u32 values indicating the supported
+ * cipher suites
+ *
+ * @NL80211_ATTR_FREQ_FIXED: a flag indicating the IBSS should not try to look
+ * for other networks on different channels
+ *
+ * @NL80211_ATTR_TIMED_OUT: a flag indicating than an operation timed out; this
+ * is used, e.g., with %NL80211_CMD_AUTHENTICATE event
+ *
+ * @NL80211_ATTR_USE_MFP: Whether management frame protection (IEEE 802.11w) is
+ * used for the association (&enum nl80211_mfp, represented as a u32);
+ * this attribute can be used
+ * with %NL80211_CMD_ASSOCIATE request
+ *
+ * @NL80211_ATTR_STA_FLAGS2: Attribute containing a
+ * &struct nl80211_sta_flag_update.
+ *
+ * @NL80211_ATTR_CONTROL_PORT: A flag indicating whether user space controls
+ * IEEE 802.1X port, i.e., sets/clears %NL80211_STA_FLAG_AUTHORIZED, in
+ * station mode. If the flag is included in %NL80211_CMD_ASSOCIATE
+ * request, the driver will assume that the port is unauthorized until
+ * authorized by user space. Otherwise, port is marked authorized by
+ * default in station mode.
+ * @NL80211_ATTR_CONTROL_PORT_ETHERTYPE: A 16-bit value indicating the
+ * ethertype that will be used for key negotiation. It can be
+ * specified with the associate and connect commands. If it is not
+ * specified, the value defaults to 0x888E (PAE, 802.1X). This
+ * attribute is also used as a flag in the wiphy information to
+ * indicate that protocols other than PAE are supported.
+ * @NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT: When included along with
+ * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, indicates that the custom
+ * ethertype frames used for key negotiation must not be encrypted.
+ *
+ * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver.
+ * We recommend using nested, driver-specific attributes within this.
+ *
+ * @NL80211_ATTR_DISCONNECTED_BY_AP: A flag indicating that the DISCONNECT
+ * event was due to the AP disconnecting the station, and not due to
+ * a local disconnect request.
+ * @NL80211_ATTR_STATUS_CODE: StatusCode for the %NL80211_CMD_CONNECT
+ * event (u16)
+ * @NL80211_ATTR_PRIVACY: Flag attribute, used with connect(), indicating
+ * that protected APs should be used. This is also used with NEW_BEACON to
+ * indicate that the BSS is to use protection.
+ *
+ * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT, ASSOCIATE, and NEW_BEACON
+ * to indicate which unicast key ciphers will be used with the connection
+ * (an array of u32).
+ * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT, ASSOCIATE, and NEW_BEACON to
+ * indicate which group key cipher will be used with the connection (a
+ * u32).
+ * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT, ASSOCIATE, and NEW_BEACON to
+ * indicate which WPA version(s) the AP we want to associate with is using
+ * (a u32 with flags from &enum nl80211_wpa_versions).
+ * @NL80211_ATTR_AKM_SUITES: Used with CONNECT, ASSOCIATE, and NEW_BEACON to
+ * indicate which key management algorithm(s) to use (an array of u32).
+ *
+ * @NL80211_ATTR_REQ_IE: (Re)association request information elements as
+ * sent out by the card, for ROAM and successful CONNECT events.
+ * @NL80211_ATTR_RESP_IE: (Re)association response information elements as
+ * sent by peer, for ROAM and successful CONNECT events.
+ *
+ * @NL80211_ATTR_PREV_BSSID: previous BSSID, to be used by in ASSOCIATE
+ * commands to specify using a reassociate frame
+ *
+ * @NL80211_ATTR_KEY: key information in a nested attribute with
+ * %NL80211_KEY_* sub-attributes
+ * @NL80211_ATTR_KEYS: array of keys for static WEP keys for connect()
+ * and join_ibss(), key information is in a nested attribute each
+ * with %NL80211_KEY_* sub-attributes
+ *
+ * @NL80211_ATTR_PID: Process ID of a network namespace.
+ *
+ * @NL80211_ATTR_GENERATION: Used to indicate consistent snapshots for
+ * dumps. This number increases whenever the object list being
+ * dumped changes, and as such userspace can verify that it has
+ * obtained a complete and consistent snapshot by verifying that
+ * all dump messages contain the same generation number. If it
+ * changed then the list changed and the dump should be repeated
+ * completely from scratch.
+ *
+ * @NL80211_ATTR_4ADDR: Use 4-address frames on a virtual interface
+ *
+ * @NL80211_ATTR_SURVEY_INFO: survey information about a channel, part of
+ * the survey response for %NL80211_CMD_GET_SURVEY, nested attribute
+ * containing info as possible, see &enum survey_info.
+ *
+ * @NL80211_ATTR_PMKID: PMK material for PMKSA caching.
+ * @NL80211_ATTR_MAX_NUM_PMKIDS: maximum number of PMKIDs a firmware can
+ * cache, a wiphy attribute.
+ *
+ * @NL80211_ATTR_DURATION: Duration of an operation in milliseconds, u32.
+ * @NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION: Device attribute that
+ * specifies the maximum duration that can be requested with the
+ * remain-on-channel operation, in milliseconds, u32.
+ *
+ * @NL80211_ATTR_COOKIE: Generic 64-bit cookie to identify objects.
+ *
+ * @NL80211_ATTR_TX_RATES: Nested set of attributes
+ * (enum nl80211_tx_rate_attributes) describing TX rates per band. The
+ * enum nl80211_band value is used as the index (nla_type() of the nested
+ * data. If a band is not included, it will be configured to allow all
+ * rates based on negotiated supported rates information. This attribute
+ * is used with %NL80211_CMD_SET_TX_BITRATE_MASK.
+ *
+ * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain
+ * at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME.
+ * @NL80211_ATTR_FRAME_TYPE: A u16 indicating the frame type/subtype for the
+ * @NL80211_CMD_REGISTER_FRAME command.
+ * @NL80211_ATTR_TX_FRAME_TYPES: wiphy capability attribute, which is a
+ * nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing
+ * information about which frame types can be transmitted with
+ * %NL80211_CMD_FRAME.
+ * @NL80211_ATTR_RX_FRAME_TYPES: wiphy capability attribute, which is a
+ * nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing
+ * information about which frame types can be registered for RX.
+ *
+ * @NL80211_ATTR_ACK: Flag attribute indicating that the frame was
+ * acknowledged by the recipient.
+ *
+ * @NL80211_ATTR_CQM: connection quality monitor configuration in a
+ * nested attribute with %NL80211_ATTR_CQM_* sub-attributes.
+ *
+ * @NL80211_ATTR_LOCAL_STATE_CHANGE: Flag attribute to indicate that a command
+ * is requesting a local authentication/association state change without
+ * invoking actual management frame exchange. This can be used with
+ * NL80211_CMD_AUTHENTICATE, NL80211_CMD_DEAUTHENTICATE,
+ * NL80211_CMD_DISASSOCIATE.
+ *
+ * @NL80211_ATTR_AP_ISOLATE: (AP mode) Do not forward traffic between stations
+ * connected to this BSS.
+ *
+ * @NL80211_ATTR_WIPHY_TX_POWER_SETTING: Transmit power setting type. See
+ * &enum nl80211_tx_power_setting for possible values.
+ * @NL80211_ATTR_WIPHY_TX_POWER_LEVEL: Transmit power level in signed mBm units.
+ * This is used in association with @NL80211_ATTR_WIPHY_TX_POWER_SETTING
+ * for non-automatic settings.
+ *
+ * @NL80211_ATTR_SUPPORT_IBSS_RSN: The device supports IBSS RSN, which mostly
+ * means support for per-station GTKs.
+ *
+ * @NL80211_ATTR_WIPHY_ANTENNA_TX: Bitmap of allowed antennas for transmitting.
+ * This can be used to mask out antennas which are not attached or should
+ * not be used for transmitting. If an antenna is not selected in this
+ * bitmap the hardware is not allowed to transmit on this antenna.
+ *
+ * Each bit represents one antenna, starting with antenna 1 at the first
+ * bit. Depending on which antennas are selected in the bitmap, 802.11n
+ * drivers can derive which chainmasks to use (if all antennas belonging to
+ * a particular chain are disabled this chain should be disabled) and if
+ * a chain has diversity antennas wether diversity should be used or not.
+ * HT capabilities (STBC, TX Beamforming, Antenna selection) can be
+ * derived from the available chains after applying the antenna mask.
+ * Non-802.11n drivers can derive wether to use diversity or not.
+ * Drivers may reject configurations or RX/TX mask combinations they cannot
+ * support by returning -EINVAL.
+ *
+ * @NL80211_ATTR_WIPHY_ANTENNA_RX: Bitmap of allowed antennas for receiving.
+ * This can be used to mask out antennas which are not attached or should
+ * not be used for receiving. If an antenna is not selected in this bitmap
+ * the hardware should not be configured to receive on this antenna.
+ * For a more detailed description see @NL80211_ATTR_WIPHY_ANTENNA_TX.
+ *
+ * @NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX: Bitmap of antennas which are available
+ * for configuration as TX antennas via the above parameters.
+ *
+ * @NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX: Bitmap of antennas which are available
+ * for configuration as RX antennas via the above parameters.
+ *
+ * @NL80211_ATTR_MCAST_RATE: Multicast tx rate (in 100 kbps) for IBSS
+ *
+ * @NL80211_ATTR_OFFCHANNEL_TX_OK: For management frame TX, the frame may be
+ * transmitted on another channel when the channel given doesn't match
+ * the current channel. If the current channel doesn't match and this
+ * flag isn't set, the frame will be rejected. This is also used as an
+ * nl80211 capability flag.
+ *
+ * @NL80211_ATTR_BSS_HTOPMODE: HT operation mode (u16)
+ *
+ * @NL80211_ATTR_KEY_DEFAULT_TYPES: A nested attribute containing flags
+ * attributes, specifying what a key should be set as default as.
+ * See &enum nl80211_key_default_types.
+ *
+ * @NL80211_ATTR_MESH_SETUP: Optional mesh setup parameters. These cannot be
+ * changed once the mesh is active.
+ * @NL80211_ATTR_MESH_CONFIG: Mesh configuration parameters, a nested attribute
+ * containing attributes from &enum nl80211_meshconf_params.
+ * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver
+ * allows auth frames in a mesh to be passed to userspace for processing via
+ * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag.
+ * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as
+ * defined in &enum nl80211_plink_state. Used when userspace is
+ * driving the peer link management state machine.
+ * @NL80211_MESH_SETUP_USERSPACE_AMPE must be enabled.
+ *
+ * @NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: indicates, as part of the wiphy
+ * capabilities, the supported WoWLAN triggers
+ * @NL80211_ATTR_WOWLAN_TRIGGERS: used by %NL80211_CMD_SET_WOWLAN to
+ * indicate which WoW triggers should be enabled. This is also
+ * used by %NL80211_CMD_GET_WOWLAN to get the currently enabled WoWLAN
+ * triggers.
+
+ * @NL80211_ATTR_SCHED_SCAN_INTERVAL: Interval between scheduled scan
+ * cycles, in msecs.
+
+ * @NL80211_ATTR_SCHED_SCAN_MATCH: Nested attribute with one or more
+ * sets of attributes to match during scheduled scans. Only BSSs
+ * that match any of the sets will be reported. These are
+ * pass-thru filter rules.
+ * For a match to succeed, the BSS must match all attributes of a
+ * set. Since not every hardware supports matching all types of
+ * attributes, there is no guarantee that the reported BSSs are
+ * fully complying with the match sets and userspace needs to be
+ * able to ignore them by itself.
+ * Thus, the implementation is somewhat hardware-dependent, but
+ * this is only an optimization and the userspace application
+ * needs to handle all the non-filtered results anyway.
+ * If the match attributes don't make sense when combined with
+ * the values passed in @NL80211_ATTR_SCAN_SSIDS (eg. if an SSID
+ * is included in the probe request, but the match attributes
+ * will never let it go through), -EINVAL may be returned.
+ * If ommited, no filtering is done.
+ *
+ * @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported
+ * interface combinations. In each nested item, it contains attributes
+ * defined in &enum nl80211_if_combination_attrs.
+ * @NL80211_ATTR_SOFTWARE_IFTYPES: Nested attribute (just like
+ * %NL80211_ATTR_SUPPORTED_IFTYPES) containing the interface types that
+ * are managed in software: interfaces of these types aren't subject to
+ * any restrictions in their number or combinations.
+ *
+ * @%NL80211_ATTR_REKEY_DATA: nested attribute containing the information
+ * necessary for GTK rekeying in the device, see &enum nl80211_rekey_data.
+ *
+ * @NL80211_ATTR_SCAN_SUPP_RATES: rates per to be advertised as supported in scan,
+ * nested array attribute containing an entry for each band, with the entry
+ * being a list of supported rates as defined by IEEE 802.11 7.3.2.2 but
+ * without the length restriction (at most %NL80211_MAX_SUPP_RATES).
+ *
+ * @NL80211_ATTR_HIDDEN_SSID: indicates whether SSID is to be hidden from Beacon
+ * and Probe Response (when response to wildcard Probe Request); see
+ * &enum nl80211_hidden_ssid, represented as a u32
+ *
+ * @NL80211_ATTR_IE_PROBE_RESP: Information element(s) for Probe Response frame.
+ * This is used with %NL80211_CMD_NEW_BEACON and %NL80211_CMD_SET_BEACON to
+ * provide extra IEs (e.g., WPS/P2P IE) into Probe Response frames when the
+ * driver (or firmware) replies to Probe Request frames.
+ * @NL80211_ATTR_IE_ASSOC_RESP: Information element(s) for (Re)Association
+ * Response frames. This is used with %NL80211_CMD_NEW_BEACON and
+ * %NL80211_CMD_SET_BEACON to provide extra IEs (e.g., WPS/P2P IE) into
+ * (Re)Association Response frames when the driver (or firmware) replies to
+ * (Re)Association Request frames.
+ *
+ * @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration
+ * of the station, see &enum nl80211_sta_wme_attr.
+ * @NL80211_ATTR_SUPPORT_AP_UAPSD: the device supports uapsd when working
+ * as AP.
+ *
+ * @NL80211_ATTR_ROAM_SUPPORT: Indicates whether the firmware is capable of
+ * roaming to another AP in the same ESS if the signal lever is low.
+ *
+ * @NL80211_ATTR_PMKSA_CANDIDATE: Nested attribute containing the PMKSA caching
+ * candidate information, see &enum nl80211_pmksa_candidate_attr.
+ *
+ * @NL80211_ATTR_TX_NO_CCK_RATE: Indicates whether to use CCK rate or not
+ * for management frames transmission. In order to avoid p2p probe/action
+ * frames are being transmitted at CCK rate in 2GHz band, the user space
+ * applications use this attribute.
+ * This attribute is used with %NL80211_CMD_TRIGGER_SCAN and
+ * %NL80211_CMD_FRAME commands.
+ *
+ * @NL80211_ATTR_TDLS_ACTION: Low level TDLS action code (e.g. link setup
+ * request, link setup confirm, link teardown, etc.). Values are
+ * described in the TDLS (802.11z) specification.
+ * @NL80211_ATTR_TDLS_DIALOG_TOKEN: Non-zero token for uniquely identifying a
+ * TDLS conversation between two devices.
+ * @NL80211_ATTR_TDLS_OPERATION: High level TDLS operation; see
+ * &enum nl80211_tdls_operation, represented as a u8.
+ * @NL80211_ATTR_TDLS_SUPPORT: A flag indicating the device can operate
+ * as a TDLS peer sta.
+ * @NL80211_ATTR_TDLS_EXTERNAL_SETUP: The TDLS discovery/setup and teardown
+ * procedures should be performed by sending TDLS packets via
+ * %NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be
+ * used for asking the driver to perform a TDLS operation.
+ *
+ * @NL80211_ATTR_DEVICE_AP_SME: This u32 attribute may be listed for devices
+ * that have AP support to indicate that they have the AP SME integrated
+ * with support for the features listed in this attribute, see
+ * &enum nl80211_ap_sme_features.
+ *
+ * @NL80211_ATTR_DONT_WAIT_FOR_ACK: Used with %NL80211_CMD_FRAME, this tells
+ * the driver to not wait for an acknowledgement. Note that due to this,
+ * it will also not give a status callback nor return a cookie. This is
+ * mostly useful for probe responses to save airtime.
+ *
+ * @NL80211_ATTR_FEATURE_FLAGS: This u32 attribute contains flags from
+ * &enum nl80211_feature_flags and is advertised in wiphy information.
+ * @NL80211_ATTR_PROBE_RESP_OFFLOAD: Indicates that the HW responds to probe
+ *
+ * requests while operating in AP-mode.
+ * This attribute holds a bitmap of the supported protocols for
+ * offloading (see &enum nl80211_probe_resp_offload_support_attr).
+ *
+ * @NL80211_ATTR_PROBE_RESP: Probe Response template data. Contains the entire
+ * probe-response frame. The DA field in the 802.11 header is zero-ed out,
+ * to be filled by the FW.
+ * @NL80211_ATTR_DISABLE_HT: Force HT capable interfaces to disable
+ * this feature. Currently, only supported in mac80211 drivers.
+ * @NL80211_ATTR_HT_CAPABILITY_MASK: Specify which bits of the
+ * ATTR_HT_CAPABILITY to which attention should be paid.
+ * Currently, only mac80211 NICs support this feature.
+ * The values that may be configured are:
+ * MCS rates, MAX-AMSDU, HT-20-40 and HT_CAP_SGI_40
+ * AMPDU density and AMPDU factor.
+ * All values are treated as suggestions and may be ignored
+ * by the driver as required. The actual values may be seen in
+ * the station debugfs ht_caps file.
+ *
+ * @NL80211_ATTR_DFS_REGION: region for regulatory rules which this country
+ * abides to when initiating radiation on DFS channels. A country maps
+ * to one DFS region.
+ *
+ * @NL80211_ATTR_NOACK_MAP: This u16 bitmap contains the No Ack Policy of
+ * up to 16 TIDs.
+ *
+ * @NL80211_ATTR_MAX: highest attribute number currently defined
+ * @__NL80211_ATTR_AFTER_LAST: internal use
+ */
+enum nl80211_attrs {
+/* don't change the order or add anything between, this is ABI! */
+ NL80211_ATTR_UNSPEC,
+
+ NL80211_ATTR_WIPHY,
+ NL80211_ATTR_WIPHY_NAME,
+
+ NL80211_ATTR_IFINDEX,
+ NL80211_ATTR_IFNAME,
+ NL80211_ATTR_IFTYPE,
+
+ NL80211_ATTR_MAC,
+
+ NL80211_ATTR_KEY_DATA,
+ NL80211_ATTR_KEY_IDX,
+ NL80211_ATTR_KEY_CIPHER,
+ NL80211_ATTR_KEY_SEQ,
+ NL80211_ATTR_KEY_DEFAULT,
+
+ NL80211_ATTR_BEACON_INTERVAL,
+ NL80211_ATTR_DTIM_PERIOD,
+ NL80211_ATTR_BEACON_HEAD,
+ NL80211_ATTR_BEACON_TAIL,
+
+ NL80211_ATTR_STA_AID,
+ NL80211_ATTR_STA_FLAGS,
+ NL80211_ATTR_STA_LISTEN_INTERVAL,
+ NL80211_ATTR_STA_SUPPORTED_RATES,
+ NL80211_ATTR_STA_VLAN,
+ NL80211_ATTR_STA_INFO,
+
+ NL80211_ATTR_WIPHY_BANDS,
+
+ NL80211_ATTR_MNTR_FLAGS,
+
+ NL80211_ATTR_MESH_ID,
+ NL80211_ATTR_STA_PLINK_ACTION,
+ NL80211_ATTR_MPATH_NEXT_HOP,
+ NL80211_ATTR_MPATH_INFO,
+
+ NL80211_ATTR_BSS_CTS_PROT,
+ NL80211_ATTR_BSS_SHORT_PREAMBLE,
+ NL80211_ATTR_BSS_SHORT_SLOT_TIME,
+
+ NL80211_ATTR_HT_CAPABILITY,
+
+ NL80211_ATTR_SUPPORTED_IFTYPES,
+
+ NL80211_ATTR_REG_ALPHA2,
+ NL80211_ATTR_REG_RULES,
+
+ NL80211_ATTR_MESH_CONFIG,
+
+ NL80211_ATTR_BSS_BASIC_RATES,
+
+ NL80211_ATTR_WIPHY_TXQ_PARAMS,
+ NL80211_ATTR_WIPHY_FREQ,
+ NL80211_ATTR_WIPHY_CHANNEL_TYPE,
+
+ NL80211_ATTR_KEY_DEFAULT_MGMT,
+
+ NL80211_ATTR_MGMT_SUBTYPE,
+ NL80211_ATTR_IE,
+
+ NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
+
+ NL80211_ATTR_SCAN_FREQUENCIES,
+ NL80211_ATTR_SCAN_SSIDS,
+ NL80211_ATTR_GENERATION, /* replaces old SCAN_GENERATION */
+ NL80211_ATTR_BSS,
+
+ NL80211_ATTR_REG_INITIATOR,
+ NL80211_ATTR_REG_TYPE,
+
+ NL80211_ATTR_SUPPORTED_COMMANDS,
+
+ NL80211_ATTR_FRAME,
+ NL80211_ATTR_SSID,
+ NL80211_ATTR_AUTH_TYPE,
+ NL80211_ATTR_REASON_CODE,
+
+ NL80211_ATTR_KEY_TYPE,
+
+ NL80211_ATTR_MAX_SCAN_IE_LEN,
+ NL80211_ATTR_CIPHER_SUITES,
+
+ NL80211_ATTR_FREQ_BEFORE,
+ NL80211_ATTR_FREQ_AFTER,
+
+ NL80211_ATTR_FREQ_FIXED,
+
+
+ NL80211_ATTR_WIPHY_RETRY_SHORT,
+ NL80211_ATTR_WIPHY_RETRY_LONG,
+ NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
+ NL80211_ATTR_WIPHY_RTS_THRESHOLD,
+
+ NL80211_ATTR_TIMED_OUT,
+
+ NL80211_ATTR_USE_MFP,
+
+ NL80211_ATTR_STA_FLAGS2,
+
+ NL80211_ATTR_CONTROL_PORT,
+
+ NL80211_ATTR_TESTDATA,
+
+ NL80211_ATTR_PRIVACY,
+
+ NL80211_ATTR_DISCONNECTED_BY_AP,
+ NL80211_ATTR_STATUS_CODE,
+
+ NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
+ NL80211_ATTR_CIPHER_SUITE_GROUP,
+ NL80211_ATTR_WPA_VERSIONS,
+ NL80211_ATTR_AKM_SUITES,
+
+ NL80211_ATTR_REQ_IE,
+ NL80211_ATTR_RESP_IE,
+
+ NL80211_ATTR_PREV_BSSID,
+
+ NL80211_ATTR_KEY,
+ NL80211_ATTR_KEYS,
+
+ NL80211_ATTR_PID,
+
+ NL80211_ATTR_4ADDR,
+
+ NL80211_ATTR_SURVEY_INFO,
+
+ NL80211_ATTR_PMKID,
+ NL80211_ATTR_MAX_NUM_PMKIDS,
+
+ NL80211_ATTR_DURATION,
+
+ NL80211_ATTR_COOKIE,
+
+ NL80211_ATTR_WIPHY_COVERAGE_CLASS,
+
+ NL80211_ATTR_TX_RATES,
+
+ NL80211_ATTR_FRAME_MATCH,
+
+ NL80211_ATTR_ACK,
+
+ NL80211_ATTR_PS_STATE,
+
+ NL80211_ATTR_CQM,
+
+ NL80211_ATTR_LOCAL_STATE_CHANGE,
+
+ NL80211_ATTR_AP_ISOLATE,
+
+ NL80211_ATTR_WIPHY_TX_POWER_SETTING,
+ NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
+
+ NL80211_ATTR_TX_FRAME_TYPES,
+ NL80211_ATTR_RX_FRAME_TYPES,
+ NL80211_ATTR_FRAME_TYPE,
+
+ NL80211_ATTR_CONTROL_PORT_ETHERTYPE,
+ NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT,
+
+ NL80211_ATTR_SUPPORT_IBSS_RSN,
+
+ NL80211_ATTR_WIPHY_ANTENNA_TX,
+ NL80211_ATTR_WIPHY_ANTENNA_RX,
+
+ NL80211_ATTR_MCAST_RATE,
+
+ NL80211_ATTR_OFFCHANNEL_TX_OK,
+
+ NL80211_ATTR_BSS_HT_OPMODE,
+
+ NL80211_ATTR_KEY_DEFAULT_TYPES,
+
+ NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION,
+
+ NL80211_ATTR_MESH_SETUP,
+
+ NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,
+ NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
+
+ NL80211_ATTR_SUPPORT_MESH_AUTH,
+ NL80211_ATTR_STA_PLINK_STATE,
+
+ NL80211_ATTR_WOWLAN_TRIGGERS,
+ NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED,
+
+ NL80211_ATTR_SCHED_SCAN_INTERVAL,
+
+ NL80211_ATTR_INTERFACE_COMBINATIONS,
+ NL80211_ATTR_SOFTWARE_IFTYPES,
+
+ NL80211_ATTR_REKEY_DATA,
+
+ NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
+ NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
+
+ NL80211_ATTR_SCAN_SUPP_RATES,
+
+ NL80211_ATTR_HIDDEN_SSID,
+
+ NL80211_ATTR_IE_PROBE_RESP,
+ NL80211_ATTR_IE_ASSOC_RESP,
+
+ NL80211_ATTR_STA_WME,
+ NL80211_ATTR_SUPPORT_AP_UAPSD,
+
+ NL80211_ATTR_ROAM_SUPPORT,
+
+ NL80211_ATTR_SCHED_SCAN_MATCH,
+ NL80211_ATTR_MAX_MATCH_SETS,
+
+ NL80211_ATTR_PMKSA_CANDIDATE,
+
+ NL80211_ATTR_TX_NO_CCK_RATE,
+
+ NL80211_ATTR_TDLS_ACTION,
+ NL80211_ATTR_TDLS_DIALOG_TOKEN,
+ NL80211_ATTR_TDLS_OPERATION,
+ NL80211_ATTR_TDLS_SUPPORT,
+ NL80211_ATTR_TDLS_EXTERNAL_SETUP,
+
+ NL80211_ATTR_DEVICE_AP_SME,
+
+ NL80211_ATTR_DONT_WAIT_FOR_ACK,
+
+ NL80211_ATTR_FEATURE_FLAGS,
+
+ NL80211_ATTR_PROBE_RESP_OFFLOAD,
+
+ NL80211_ATTR_PROBE_RESP,
+
+ NL80211_ATTR_DFS_REGION,
+
+ NL80211_ATTR_DISABLE_HT,
+ NL80211_ATTR_HT_CAPABILITY_MASK,
+
+ NL80211_ATTR_NOACK_MAP,
+
+ /* add attributes here, update the policy in nl80211.c */
+
+ __NL80211_ATTR_AFTER_LAST,
+ NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
+};
+
+/* source-level API compatibility */
+#define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION
+#define NL80211_ATTR_MESH_PARAMS NL80211_ATTR_MESH_CONFIG
+
+/*
+ * Allow user space programs to use #ifdef on new attributes by defining them
+ * here
+ */
+#define NL80211_CMD_CONNECT NL80211_CMD_CONNECT
+#define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY
+#define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES
+#define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS
+#define NL80211_ATTR_WIPHY_FREQ NL80211_ATTR_WIPHY_FREQ
+#define NL80211_ATTR_WIPHY_CHANNEL_TYPE NL80211_ATTR_WIPHY_CHANNEL_TYPE
+#define NL80211_ATTR_MGMT_SUBTYPE NL80211_ATTR_MGMT_SUBTYPE
+#define NL80211_ATTR_IE NL80211_ATTR_IE
+#define NL80211_ATTR_REG_INITIATOR NL80211_ATTR_REG_INITIATOR
+#define NL80211_ATTR_REG_TYPE NL80211_ATTR_REG_TYPE
+#define NL80211_ATTR_FRAME NL80211_ATTR_FRAME
+#define NL80211_ATTR_SSID NL80211_ATTR_SSID
+#define NL80211_ATTR_AUTH_TYPE NL80211_ATTR_AUTH_TYPE
+#define NL80211_ATTR_REASON_CODE NL80211_ATTR_REASON_CODE
+#define NL80211_ATTR_CIPHER_SUITES_PAIRWISE NL80211_ATTR_CIPHER_SUITES_PAIRWISE
+#define NL80211_ATTR_CIPHER_SUITE_GROUP NL80211_ATTR_CIPHER_SUITE_GROUP
+#define NL80211_ATTR_WPA_VERSIONS NL80211_ATTR_WPA_VERSIONS
+#define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES
+#define NL80211_ATTR_KEY NL80211_ATTR_KEY
+#define NL80211_ATTR_KEYS NL80211_ATTR_KEYS
+#define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS
+
+#define NL80211_MAX_SUPP_RATES 32
+#define NL80211_MAX_SUPP_HT_RATES 77
+#define NL80211_MAX_SUPP_REG_RULES 32
+#define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0
+#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16
+#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24
+#define NL80211_HT_CAPABILITY_LEN 26
+
+#define NL80211_MAX_NR_CIPHER_SUITES 5
+#define NL80211_MAX_NR_AKM_SUITES 2
+
+/**
+ * enum nl80211_iftype - (virtual) interface types
+ *
+ * @NL80211_IFTYPE_UNSPECIFIED: unspecified type, driver decides
+ * @NL80211_IFTYPE_ADHOC: independent BSS member
+ * @NL80211_IFTYPE_STATION: managed BSS member
+ * @NL80211_IFTYPE_AP: access point
+ * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points; VLAN interfaces
+ * are a bit special in that they must always be tied to a pre-existing
+ * AP type interface.
+ * @NL80211_IFTYPE_WDS: wireless distribution interface
+ * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames
+ * @NL80211_IFTYPE_MESH_POINT: mesh point
+ * @NL80211_IFTYPE_P2P_CLIENT: P2P client
+ * @NL80211_IFTYPE_P2P_GO: P2P group owner
+ * @NL80211_IFTYPE_MAX: highest interface type number currently defined
+ * @NUM_NL80211_IFTYPES: number of defined interface types
+ *
+ * These values are used with the %NL80211_ATTR_IFTYPE
+ * to set the type of an interface.
+ *
+ */
+enum nl80211_iftype {
+ NL80211_IFTYPE_UNSPECIFIED,
+ NL80211_IFTYPE_ADHOC,
+ NL80211_IFTYPE_STATION,
+ NL80211_IFTYPE_AP,
+ NL80211_IFTYPE_AP_VLAN,
+ NL80211_IFTYPE_WDS,
+ NL80211_IFTYPE_MONITOR,
+ NL80211_IFTYPE_MESH_POINT,
+ NL80211_IFTYPE_P2P_CLIENT,
+ NL80211_IFTYPE_P2P_GO,
+
+ /* keep last */
+ NUM_NL80211_IFTYPES,
+ NL80211_IFTYPE_MAX = NUM_NL80211_IFTYPES - 1
+};
+
+/**
+ * enum nl80211_sta_flags - station flags
+ *
+ * Station flags. When a station is added to an AP interface, it is
+ * assumed to be already associated (and hence authenticated.)
+ *
+ * @__NL80211_STA_FLAG_INVALID: attribute number 0 is reserved
+ * @NL80211_STA_FLAG_AUTHORIZED: station is authorized (802.1X)
+ * @NL80211_STA_FLAG_SHORT_PREAMBLE: station is capable of receiving frames
+ * with short barker preamble
+ * @NL80211_STA_FLAG_WME: station is WME/QoS capable
+ * @NL80211_STA_FLAG_MFP: station uses management frame protection
+ * @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated
+ * @NL80211_STA_FLAG_TDLS_PEER: station is a TDLS peer -- this flag should
+ * only be used in managed mode (even in the flags mask). Note that the
+ * flag can't be changed, it is only valid while adding a station, and
+ * attempts to change it will silently be ignored (rather than rejected
+ * as errors.)
+ * @NL80211_STA_FLAG_MAX: highest station flag number currently defined
+ * @__NL80211_STA_FLAG_AFTER_LAST: internal use
+ */
+enum nl80211_sta_flags {
+ __NL80211_STA_FLAG_INVALID,
+ NL80211_STA_FLAG_AUTHORIZED,
+ NL80211_STA_FLAG_SHORT_PREAMBLE,
+ NL80211_STA_FLAG_WME,
+ NL80211_STA_FLAG_MFP,
+ NL80211_STA_FLAG_AUTHENTICATED,
+ NL80211_STA_FLAG_TDLS_PEER,
+
+ /* keep last */
+ __NL80211_STA_FLAG_AFTER_LAST,
+ NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1
+};
+
+/**
+ * struct nl80211_sta_flag_update - station flags mask/set
+ * @mask: mask of station flags to set
+ * @set: which values to set them to
+ *
+ * Both mask and set contain bits as per &enum nl80211_sta_flags.
+ */
+struct nl80211_sta_flag_update {
+ __u32 mask;
+ __u32 set;
+} __attribute__((packed));
+
+/**
+ * enum nl80211_rate_info - bitrate information
+ *
+ * These attribute types are used with %NL80211_STA_INFO_TXRATE
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
+ * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
+ * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined
+ * @__NL80211_RATE_INFO_AFTER_LAST: internal use
+ */
+enum nl80211_rate_info {
+ __NL80211_RATE_INFO_INVALID,
+ NL80211_RATE_INFO_BITRATE,
+ NL80211_RATE_INFO_MCS,
+ NL80211_RATE_INFO_40_MHZ_WIDTH,
+ NL80211_RATE_INFO_SHORT_GI,
+
+ /* keep last */
+ __NL80211_RATE_INFO_AFTER_LAST,
+ NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_sta_bss_param - BSS information collected by STA
+ *
+ * These attribute types are used with %NL80211_STA_INFO_BSS_PARAM
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_STA_BSS_PARAM_INVALID: attribute number 0 is reserved
+ * @NL80211_STA_BSS_PARAM_CTS_PROT: whether CTS protection is enabled (flag)
+ * @NL80211_STA_BSS_PARAM_SHORT_PREAMBLE: whether short preamble is enabled
+ * (flag)
+ * @NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME: whether short slot time is enabled
+ * (flag)
+ * @NL80211_STA_BSS_PARAM_DTIM_PERIOD: DTIM period for beaconing (u8)
+ * @NL80211_STA_BSS_PARAM_BEACON_INTERVAL: Beacon interval (u16)
+ * @NL80211_STA_BSS_PARAM_MAX: highest sta_bss_param number currently defined
+ * @__NL80211_STA_BSS_PARAM_AFTER_LAST: internal use
+ */
+enum nl80211_sta_bss_param {
+ __NL80211_STA_BSS_PARAM_INVALID,
+ NL80211_STA_BSS_PARAM_CTS_PROT,
+ NL80211_STA_BSS_PARAM_SHORT_PREAMBLE,
+ NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME,
+ NL80211_STA_BSS_PARAM_DTIM_PERIOD,
+ NL80211_STA_BSS_PARAM_BEACON_INTERVAL,
+
+ /* keep last */
+ __NL80211_STA_BSS_PARAM_AFTER_LAST,
+ NL80211_STA_BSS_PARAM_MAX = __NL80211_STA_BSS_PARAM_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_sta_info - station information
+ *
+ * These attribute types are used with %NL80211_ATTR_STA_INFO
+ * when getting information about a station.
+ *
+ * @__NL80211_STA_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs)
+ * @NL80211_STA_INFO_RX_BYTES: total received bytes (u32, from this station)
+ * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+ * containing info as possible, see &enum nl80211_rate_info
+ * @NL80211_STA_INFO_RX_PACKETS: total received packet (u32, from this station)
+ * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (u32, to this
+ * station)
+ * @NL80211_STA_INFO_TX_RETRIES: total retries (u32, to this station)
+ * @NL80211_STA_INFO_TX_FAILED: total failed packets (u32, to this station)
+ * @NL80211_STA_INFO_SIGNAL_AVG: signal strength average (u8, dBm)
+ * @NL80211_STA_INFO_LLID: the station's mesh LLID
+ * @NL80211_STA_INFO_PLID: the station's mesh PLID
+ * @NL80211_STA_INFO_PLINK_STATE: peer link state for the station
+ * (see %enum nl80211_plink_state)
+ * @NL80211_STA_INFO_RX_BITRATE: last unicast data frame rx rate, nested
+ * attribute, like NL80211_STA_INFO_TX_BITRATE.
+ * @NL80211_STA_INFO_BSS_PARAM: current station's view of BSS, nested attribute
+ * containing info as possible, see &enum nl80211_sta_bss_param
+ * @NL80211_STA_INFO_CONNECTED_TIME: time since the station is last connected
+ * @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update.
+ * @NL80211_STA_INFO_BEACON_LOSS: count of times beacon loss was detected (u32)
+ * @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU
+ * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average
+ * @__NL80211_STA_INFO_AFTER_LAST: internal
+ * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ */
+enum nl80211_sta_info {
+ __NL80211_STA_INFO_INVALID,
+ NL80211_STA_INFO_INACTIVE_TIME,
+ NL80211_STA_INFO_RX_BYTES,
+ NL80211_STA_INFO_TX_BYTES,
+ NL80211_STA_INFO_LLID,
+ NL80211_STA_INFO_PLID,
+ NL80211_STA_INFO_PLINK_STATE,
+ NL80211_STA_INFO_SIGNAL,
+ NL80211_STA_INFO_TX_BITRATE,
+ NL80211_STA_INFO_RX_PACKETS,
+ NL80211_STA_INFO_TX_PACKETS,
+ NL80211_STA_INFO_TX_RETRIES,
+ NL80211_STA_INFO_TX_FAILED,
+ NL80211_STA_INFO_SIGNAL_AVG,
+ NL80211_STA_INFO_RX_BITRATE,
+ NL80211_STA_INFO_BSS_PARAM,
+ NL80211_STA_INFO_CONNECTED_TIME,
+ NL80211_STA_INFO_STA_FLAGS,
+ NL80211_STA_INFO_BEACON_LOSS,
+ NL80211_STA_INFO_CHAIN_SIGNAL,
+ NL80211_STA_INFO_CHAIN_SIGNAL_AVG,
+
+ /* keep last */
+ __NL80211_STA_INFO_AFTER_LAST,
+ NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_mpath_flags - nl80211 mesh path flags
+ *
+ * @NL80211_MPATH_FLAG_ACTIVE: the mesh path is active
+ * @NL80211_MPATH_FLAG_RESOLVING: the mesh path discovery process is running
+ * @NL80211_MPATH_FLAG_SN_VALID: the mesh path contains a valid SN
+ * @NL80211_MPATH_FLAG_FIXED: the mesh path has been manually set
+ * @NL80211_MPATH_FLAG_RESOLVED: the mesh path discovery process succeeded
+ */
+enum nl80211_mpath_flags {
+ NL80211_MPATH_FLAG_ACTIVE = 1<<0,
+ NL80211_MPATH_FLAG_RESOLVING = 1<<1,
+ NL80211_MPATH_FLAG_SN_VALID = 1<<2,
+ NL80211_MPATH_FLAG_FIXED = 1<<3,
+ NL80211_MPATH_FLAG_RESOLVED = 1<<4,
+};
+
+/**
+ * enum nl80211_mpath_info - mesh path information
+ *
+ * These attribute types are used with %NL80211_ATTR_MPATH_INFO when getting
+ * information about a mesh path.
+ *
+ * @__NL80211_MPATH_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_MPATH_INFO_FRAME_QLEN: number of queued frames for this destination
+ * @NL80211_MPATH_INFO_SN: destination sequence number
+ * @NL80211_MPATH_INFO_METRIC: metric (cost) of this mesh path
+ * @NL80211_MPATH_INFO_EXPTIME: expiration time for the path, in msec from now
+ * @NL80211_MPATH_INFO_FLAGS: mesh path flags, enumerated in
+ * &enum nl80211_mpath_flags;
+ * @NL80211_MPATH_INFO_DISCOVERY_TIMEOUT: total path discovery timeout, in msec
+ * @NL80211_MPATH_INFO_DISCOVERY_RETRIES: mesh path discovery retries
+ * @NL80211_MPATH_INFO_MAX: highest mesh path information attribute number
+ * currently defind
+ * @__NL80211_MPATH_INFO_AFTER_LAST: internal use
+ */
+enum nl80211_mpath_info {
+ __NL80211_MPATH_INFO_INVALID,
+ NL80211_MPATH_INFO_FRAME_QLEN,
+ NL80211_MPATH_INFO_SN,
+ NL80211_MPATH_INFO_METRIC,
+ NL80211_MPATH_INFO_EXPTIME,
+ NL80211_MPATH_INFO_FLAGS,
+ NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
+ NL80211_MPATH_INFO_DISCOVERY_RETRIES,
+
+ /* keep last */
+ __NL80211_MPATH_INFO_AFTER_LAST,
+ NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_band_attr - band attributes
+ * @__NL80211_BAND_ATTR_INVALID: attribute number 0 is reserved
+ * @NL80211_BAND_ATTR_FREQS: supported frequencies in this band,
+ * an array of nested frequency attributes
+ * @NL80211_BAND_ATTR_RATES: supported bitrates in this band,
+ * an array of nested bitrate attributes
+ * @NL80211_BAND_ATTR_HT_MCS_SET: 16-byte attribute containing the MCS set as
+ * defined in 802.11n
+ * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE
+ * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n
+ * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n
+ * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined
+ * @__NL80211_BAND_ATTR_AFTER_LAST: internal use
+ */
+enum nl80211_band_attr {
+ __NL80211_BAND_ATTR_INVALID,
+ NL80211_BAND_ATTR_FREQS,
+ NL80211_BAND_ATTR_RATES,
+
+ NL80211_BAND_ATTR_HT_MCS_SET,
+ NL80211_BAND_ATTR_HT_CAPA,
+ NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
+ NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
+
+ /* keep last */
+ __NL80211_BAND_ATTR_AFTER_LAST,
+ NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1
+};
+
+#define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA
+
+/**
+ * enum nl80211_frequency_attr - frequency attributes
+ * @__NL80211_FREQUENCY_ATTR_INVALID: attribute number 0 is reserved
+ * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz
+ * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current
+ * regulatory domain.
+ * @NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: Only passive scanning is
+ * permitted on this channel in current regulatory domain.
+ * @NL80211_FREQUENCY_ATTR_NO_IBSS: IBSS networks are not permitted
+ * on this channel in current regulatory domain.
+ * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory
+ * on this channel in current regulatory domain.
+ * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm
+ * (100 * dBm).
+ * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
+ * currently defined
+ * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
+ */
+enum nl80211_frequency_attr {
+ __NL80211_FREQUENCY_ATTR_INVALID,
+ NL80211_FREQUENCY_ATTR_FREQ,
+ NL80211_FREQUENCY_ATTR_DISABLED,
+ NL80211_FREQUENCY_ATTR_PASSIVE_SCAN,
+ NL80211_FREQUENCY_ATTR_NO_IBSS,
+ NL80211_FREQUENCY_ATTR_RADAR,
+ NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
+
+ /* keep last */
+ __NL80211_FREQUENCY_ATTR_AFTER_LAST,
+ NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1
+};
+
+#define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER
+
+/**
+ * enum nl80211_bitrate_attr - bitrate attributes
+ * @__NL80211_BITRATE_ATTR_INVALID: attribute number 0 is reserved
+ * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps
+ * @NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: Short preamble supported
+ * in 2.4 GHz band.
+ * @NL80211_BITRATE_ATTR_MAX: highest bitrate attribute number
+ * currently defined
+ * @__NL80211_BITRATE_ATTR_AFTER_LAST: internal use
+ */
+enum nl80211_bitrate_attr {
+ __NL80211_BITRATE_ATTR_INVALID,
+ NL80211_BITRATE_ATTR_RATE,
+ NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE,
+
+ /* keep last */
+ __NL80211_BITRATE_ATTR_AFTER_LAST,
+ NL80211_BITRATE_ATTR_MAX = __NL80211_BITRATE_ATTR_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_initiator - Indicates the initiator of a reg domain request
+ * @NL80211_REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world
+ * regulatory domain.
+ * @NL80211_REGDOM_SET_BY_USER: User asked the wireless core to set the
+ * regulatory domain.
+ * @NL80211_REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the
+ * wireless core it thinks its knows the regulatory domain we should be in.
+ * @NL80211_REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an
+ * 802.11 country information element with regulatory information it
+ * thinks we should consider. cfg80211 only processes the country
+ * code from the IE, and relies on the regulatory domain information
+ * structure passed by userspace (CRDA) from our wireless-regdb.
+ * If a channel is enabled but the country code indicates it should
+ * be disabled we disable the channel and re-enable it upon disassociation.
+ */
+enum nl80211_reg_initiator {
+ NL80211_REGDOM_SET_BY_CORE,
+ NL80211_REGDOM_SET_BY_USER,
+ NL80211_REGDOM_SET_BY_DRIVER,
+ NL80211_REGDOM_SET_BY_COUNTRY_IE,
+};
+
+/**
+ * enum nl80211_reg_type - specifies the type of regulatory domain
+ * @NL80211_REGDOM_TYPE_COUNTRY: the regulatory domain set is one that pertains
+ * to a specific country. When this is set you can count on the
+ * ISO / IEC 3166 alpha2 country code being valid.
+ * @NL80211_REGDOM_TYPE_WORLD: the regulatory set domain is the world regulatory
+ * domain.
+ * @NL80211_REGDOM_TYPE_CUSTOM_WORLD: the regulatory domain set is a custom
+ * driver specific world regulatory domain. These do not apply system-wide
+ * and are only applicable to the individual devices which have requested
+ * them to be applied.
+ * @NL80211_REGDOM_TYPE_INTERSECTION: the regulatory domain set is the product
+ * of an intersection between two regulatory domains -- the previously
+ * set regulatory domain on the system and the last accepted regulatory
+ * domain request to be processed.
+ */
+enum nl80211_reg_type {
+ NL80211_REGDOM_TYPE_COUNTRY,
+ NL80211_REGDOM_TYPE_WORLD,
+ NL80211_REGDOM_TYPE_CUSTOM_WORLD,
+ NL80211_REGDOM_TYPE_INTERSECTION,
+};
+
+/**
+ * enum nl80211_reg_rule_attr - regulatory rule attributes
+ * @__NL80211_REG_RULE_ATTR_INVALID: attribute number 0 is reserved
+ * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional
+ * considerations for a given frequency range. These are the
+ * &enum nl80211_reg_rule_flags.
+ * @NL80211_ATTR_FREQ_RANGE_START: starting frequencry for the regulatory
+ * rule in KHz. This is not a center of frequency but an actual regulatory
+ * band edge.
+ * @NL80211_ATTR_FREQ_RANGE_END: ending frequency for the regulatory rule
+ * in KHz. This is not a center a frequency but an actual regulatory
+ * band edge.
+ * @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this
+ * frequency range, in KHz.
+ * @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain
+ * for a given frequency range. The value is in mBi (100 * dBi).
+ * If you don't have one then don't send this.
+ * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for
+ * a given frequency range. The value is in mBm (100 * dBm).
+ * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number
+ * currently defined
+ * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use
+ */
+enum nl80211_reg_rule_attr {
+ __NL80211_REG_RULE_ATTR_INVALID,
+ NL80211_ATTR_REG_RULE_FLAGS,
+
+ NL80211_ATTR_FREQ_RANGE_START,
+ NL80211_ATTR_FREQ_RANGE_END,
+ NL80211_ATTR_FREQ_RANGE_MAX_BW,
+
+ NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
+ NL80211_ATTR_POWER_RULE_MAX_EIRP,
+
+ /* keep last */
+ __NL80211_REG_RULE_ATTR_AFTER_LAST,
+ NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_sched_scan_match_attr - scheduled scan match attributes
+ * @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved
+ * @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching,
+ * only report BSS with matching SSID.
+ * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
+ * attribute number currently defined
+ * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
+ */
+enum nl80211_sched_scan_match_attr {
+ __NL80211_SCHED_SCAN_MATCH_ATTR_INVALID,
+
+ NL80211_ATTR_SCHED_SCAN_MATCH_SSID,
+
+ /* keep last */
+ __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST,
+ NL80211_SCHED_SCAN_MATCH_ATTR_MAX =
+ __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_reg_rule_flags - regulatory rule flags
+ *
+ * @NL80211_RRF_NO_OFDM: OFDM modulation not allowed
+ * @NL80211_RRF_NO_CCK: CCK modulation not allowed
+ * @NL80211_RRF_NO_INDOOR: indoor operation not allowed
+ * @NL80211_RRF_NO_OUTDOOR: outdoor operation not allowed
+ * @NL80211_RRF_DFS: DFS support is required to be used
+ * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links
+ * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links
+ * @NL80211_RRF_PASSIVE_SCAN: passive scan is required
+ * @NL80211_RRF_NO_IBSS: no IBSS is allowed
+ */
+enum nl80211_reg_rule_flags {
+ NL80211_RRF_NO_OFDM = 1<<0,
+ NL80211_RRF_NO_CCK = 1<<1,
+ NL80211_RRF_NO_INDOOR = 1<<2,
+ NL80211_RRF_NO_OUTDOOR = 1<<3,
+ NL80211_RRF_DFS = 1<<4,
+ NL80211_RRF_PTP_ONLY = 1<<5,
+ NL80211_RRF_PTMP_ONLY = 1<<6,
+ NL80211_RRF_PASSIVE_SCAN = 1<<7,
+ NL80211_RRF_NO_IBSS = 1<<8,
+};
+
+/**
+ * enum nl80211_dfs_regions - regulatory DFS regions
+ *
+ * @NL80211_DFS_UNSET: Country has no DFS master region specified
+ * @NL80211_DFS_FCC_: Country follows DFS master rules from FCC
+ * @NL80211_DFS_FCC_: Country follows DFS master rules from ETSI
+ * @NL80211_DFS_JP_: Country follows DFS master rules from JP/MKK/Telec
+ */
+enum nl80211_dfs_regions {
+ NL80211_DFS_UNSET = 0,
+ NL80211_DFS_FCC = 1,
+ NL80211_DFS_ETSI = 2,
+ NL80211_DFS_JP = 3,
+};
+
+/**
+ * enum nl80211_survey_info - survey information
+ *
+ * These attribute types are used with %NL80211_ATTR_SURVEY_INFO
+ * when getting information about a survey.
+ *
+ * @__NL80211_SURVEY_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel
+ * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm)
+ * @NL80211_SURVEY_INFO_IN_USE: channel is currently being used
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME: amount of time (in ms) that the radio
+ * spent on this channel
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY: amount of the time the primary
+ * channel was sensed busy (either due to activity or energy detect)
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: amount of time the extension
+ * channel was sensed busy
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_RX: amount of time the radio spent
+ * receiving data
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_TX: amount of time the radio spent
+ * transmitting data
+ * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number
+ * currently defined
+ * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use
+ */
+enum nl80211_survey_info {
+ __NL80211_SURVEY_INFO_INVALID,
+ NL80211_SURVEY_INFO_FREQUENCY,
+ NL80211_SURVEY_INFO_NOISE,
+ NL80211_SURVEY_INFO_IN_USE,
+ NL80211_SURVEY_INFO_CHANNEL_TIME,
+ NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
+ NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY,
+ NL80211_SURVEY_INFO_CHANNEL_TIME_RX,
+ NL80211_SURVEY_INFO_CHANNEL_TIME_TX,
+
+ /* keep last */
+ __NL80211_SURVEY_INFO_AFTER_LAST,
+ NL80211_SURVEY_INFO_MAX = __NL80211_SURVEY_INFO_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_mntr_flags - monitor configuration flags
+ *
+ * Monitor configuration flags.
+ *
+ * @__NL80211_MNTR_FLAG_INVALID: reserved
+ *
+ * @NL80211_MNTR_FLAG_FCSFAIL: pass frames with bad FCS
+ * @NL80211_MNTR_FLAG_PLCPFAIL: pass frames with bad PLCP
+ * @NL80211_MNTR_FLAG_CONTROL: pass control frames
+ * @NL80211_MNTR_FLAG_OTHER_BSS: disable BSSID filtering
+ * @NL80211_MNTR_FLAG_COOK_FRAMES: report frames after processing.
+ * overrides all other flags.
+ *
+ * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use
+ * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag
+ */
+enum nl80211_mntr_flags {
+ __NL80211_MNTR_FLAG_INVALID,
+ NL80211_MNTR_FLAG_FCSFAIL,
+ NL80211_MNTR_FLAG_PLCPFAIL,
+ NL80211_MNTR_FLAG_CONTROL,
+ NL80211_MNTR_FLAG_OTHER_BSS,
+ NL80211_MNTR_FLAG_COOK_FRAMES,
+
+ /* keep last */
+ __NL80211_MNTR_FLAG_AFTER_LAST,
+ NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_meshconf_params - mesh configuration parameters
+ *
+ * Mesh configuration parameters. These can be changed while the mesh is
+ * active.
+ *
+ * @__NL80211_MESHCONF_INVALID: internal use
+ *
+ * @NL80211_MESHCONF_RETRY_TIMEOUT: specifies the initial retry timeout in
+ * millisecond units, used by the Peer Link Open message
+ *
+ * @NL80211_MESHCONF_CONFIRM_TIMEOUT: specifies the initial confirm timeout, in
+ * millisecond units, used by the peer link management to close a peer link
+ *
+ * @NL80211_MESHCONF_HOLDING_TIMEOUT: specifies the holding timeout, in
+ * millisecond units
+ *
+ * @NL80211_MESHCONF_MAX_PEER_LINKS: maximum number of peer links allowed
+ * on this mesh interface
+ *
+ * @NL80211_MESHCONF_MAX_RETRIES: specifies the maximum number of peer link
+ * open retries that can be sent to establish a new peer link instance in a
+ * mesh
+ *
+ * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh
+ * point.
+ *
+ * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically
+ * open peer links when we detect compatible mesh peers.
+ *
+ * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames
+ * containing a PREQ that an MP can send to a particular destination (path
+ * target)
+ *
+ * @NL80211_MESHCONF_PATH_REFRESH_TIME: how frequently to refresh mesh paths
+ * (in milliseconds)
+ *
+ * @NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT: minimum length of time to wait
+ * until giving up on a path discovery (in milliseconds)
+ *
+ * @NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT: The time (in TUs) for which mesh
+ * points receiving a PREQ shall consider the forwarding information from the
+ * root to be valid. (TU = time unit)
+ *
+ * @NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL: The minimum interval of time (in
+ * TUs) during which an MP can send only one action frame containing a PREQ
+ * reference element
+ *
+ * @NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: The interval of time (in TUs)
+ * that it takes for an HWMP information element to propagate across the mesh
+ *
+ * @NL80211_MESHCONF_HWMP_ROOTMODE: whether root mode is enabled or not
+ *
+ * @NL80211_MESHCONF_ELEMENT_TTL: specifies the value of TTL field set at a
+ * source mesh point for path selection elements.
+ *
+ * @NL80211_MESHCONF_HWMP_RANN_INTERVAL: The interval of time (in TUs) between
+ * root announcements are transmitted.
+ *
+ * @NL80211_MESHCONF_GATE_ANNOUNCEMENTS: Advertise that this mesh station has
+ * access to a broader network beyond the MBSS. This is done via Root
+ * Announcement frames.
+ *
+ * @NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL: The minimum interval of time (in
+ * TUs) during which a mesh STA can send only one Action frame containing a
+ * PERR element.
+ *
+ * @NL80211_MESHCONF_FORWARDING: set Mesh STA as forwarding or non-forwarding
+ * or forwarding entity (default is TRUE - forwarding entity)
+ *
+ * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
+ *
+ * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
+ */
+enum nl80211_meshconf_params {
+ __NL80211_MESHCONF_INVALID,
+ NL80211_MESHCONF_RETRY_TIMEOUT,
+ NL80211_MESHCONF_CONFIRM_TIMEOUT,
+ NL80211_MESHCONF_HOLDING_TIMEOUT,
+ NL80211_MESHCONF_MAX_PEER_LINKS,
+ NL80211_MESHCONF_MAX_RETRIES,
+ NL80211_MESHCONF_TTL,
+ NL80211_MESHCONF_AUTO_OPEN_PLINKS,
+ NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
+ NL80211_MESHCONF_PATH_REFRESH_TIME,
+ NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
+ NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
+ NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
+ NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
+ NL80211_MESHCONF_HWMP_ROOTMODE,
+ NL80211_MESHCONF_ELEMENT_TTL,
+ NL80211_MESHCONF_HWMP_RANN_INTERVAL,
+ NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
+ NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
+ NL80211_MESHCONF_FORWARDING,
+
+ /* keep last */
+ __NL80211_MESHCONF_ATTR_AFTER_LAST,
+ NL80211_MESHCONF_ATTR_MAX = __NL80211_MESHCONF_ATTR_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_mesh_setup_params - mesh setup parameters
+ *
+ * Mesh setup parameters. These are used to start/join a mesh and cannot be
+ * changed while the mesh is active.
+ *
+ * @__NL80211_MESH_SETUP_INVALID: Internal use
+ *
+ * @NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL: Enable this option to use a
+ * vendor specific path selection algorithm or disable it to use the default
+ * HWMP.
+ *
+ * @NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC: Enable this option to use a
+ * vendor specific path metric or disable it to use the default Airtime
+ * metric.
+ *
+ * @NL80211_MESH_SETUP_IE: Information elements for this mesh, for instance, a
+ * robust security network ie, or a vendor specific information element that
+ * vendors will use to identify the path selection methods and metrics in use.
+ *
+ * @NL80211_MESH_SETUP_USERSPACE_AUTH: Enable this option if an authentication
+ * daemon will be authenticating mesh candidates.
+ *
+ * @NL80211_MESH_SETUP_USERSPACE_AMPE: Enable this option if an authentication
+ * daemon will be securing peer link frames. AMPE is a secured version of Mesh
+ * Peering Management (MPM) and is implemented with the assistance of a
+ * userspace daemon. When this flag is set, the kernel will send peer
+ * management frames to a userspace daemon that will implement AMPE
+ * functionality (security capabilities selection, key confirmation, and key
+ * management). When the flag is unset (default), the kernel can autonomously
+ * complete (unsecured) mesh peering without the need of a userspace daemon.
+ *
+ * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number
+ * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use
+ */
+enum nl80211_mesh_setup_params {
+ __NL80211_MESH_SETUP_INVALID,
+ NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL,
+ NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC,
+ NL80211_MESH_SETUP_IE,
+ NL80211_MESH_SETUP_USERSPACE_AUTH,
+ NL80211_MESH_SETUP_USERSPACE_AMPE,
+
+ /* keep last */
+ __NL80211_MESH_SETUP_ATTR_AFTER_LAST,
+ NL80211_MESH_SETUP_ATTR_MAX = __NL80211_MESH_SETUP_ATTR_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_txq_attr - TX queue parameter attributes
+ * @__NL80211_TXQ_ATTR_INVALID: Attribute number 0 is reserved
+ * @NL80211_TXQ_ATTR_QUEUE: TX queue identifier (NL80211_TXQ_Q_*)
+ * @NL80211_TXQ_ATTR_TXOP: Maximum burst time in units of 32 usecs, 0 meaning
+ * disabled
+ * @NL80211_TXQ_ATTR_CWMIN: Minimum contention window [a value of the form
+ * 2^n-1 in the range 1..32767]
+ * @NL80211_TXQ_ATTR_CWMAX: Maximum contention window [a value of the form
+ * 2^n-1 in the range 1..32767]
+ * @NL80211_TXQ_ATTR_AIFS: Arbitration interframe space [0..255]
+ * @__NL80211_TXQ_ATTR_AFTER_LAST: Internal
+ * @NL80211_TXQ_ATTR_MAX: Maximum TXQ attribute number
+ */
+enum nl80211_txq_attr {
+ __NL80211_TXQ_ATTR_INVALID,
+ NL80211_TXQ_ATTR_QUEUE,
+ NL80211_TXQ_ATTR_TXOP,
+ NL80211_TXQ_ATTR_CWMIN,
+ NL80211_TXQ_ATTR_CWMAX,
+ NL80211_TXQ_ATTR_AIFS,
+
+ /* keep last */
+ __NL80211_TXQ_ATTR_AFTER_LAST,
+ NL80211_TXQ_ATTR_MAX = __NL80211_TXQ_ATTR_AFTER_LAST - 1
+};
+
+enum nl80211_txq_q {
+ NL80211_TXQ_Q_VO,
+ NL80211_TXQ_Q_VI,
+ NL80211_TXQ_Q_BE,
+ NL80211_TXQ_Q_BK
+};
+
+enum nl80211_channel_type {
+ NL80211_CHAN_NO_HT,
+ NL80211_CHAN_HT20,
+ NL80211_CHAN_HT40MINUS,
+ NL80211_CHAN_HT40PLUS
+};
+
+/**
+ * enum nl80211_bss - netlink attributes for a BSS
+ *
+ * @__NL80211_BSS_INVALID: invalid
+ * @NL80211_BSS_BSSID: BSSID of the BSS (6 octets)
+ * @NL80211_BSS_FREQUENCY: frequency in MHz (u32)
+ * @NL80211_BSS_TSF: TSF of the received probe response/beacon (u64)
+ * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16)
+ * @NL80211_BSS_CAPABILITY: capability field (CPU order, u16)
+ * @NL80211_BSS_INFORMATION_ELEMENTS: binary attribute containing the
+ * raw information elements from the probe response/beacon (bin);
+ * if the %NL80211_BSS_BEACON_IES attribute is present, the IEs here are
+ * from a Probe Response frame; otherwise they are from a Beacon frame.
+ * However, if the driver does not indicate the source of the IEs, these
+ * IEs may be from either frame subtype.
+ * @NL80211_BSS_SIGNAL_MBM: signal strength of probe response/beacon
+ * in mBm (100 * dBm) (s32)
+ * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon
+ * in unspecified units, scaled to 0..100 (u8)
+ * @NL80211_BSS_STATUS: status, if this BSS is "used"
+ * @NL80211_BSS_SEEN_MS_AGO: age of this BSS entry in ms
+ * @NL80211_BSS_BEACON_IES: binary attribute containing the raw information
+ * elements from a Beacon frame (bin); not present if no Beacon frame has
+ * yet been received
+ * @__NL80211_BSS_AFTER_LAST: internal
+ * @NL80211_BSS_MAX: highest BSS attribute
+ */
+enum nl80211_bss {
+ __NL80211_BSS_INVALID,
+ NL80211_BSS_BSSID,
+ NL80211_BSS_FREQUENCY,
+ NL80211_BSS_TSF,
+ NL80211_BSS_BEACON_INTERVAL,
+ NL80211_BSS_CAPABILITY,
+ NL80211_BSS_INFORMATION_ELEMENTS,
+ NL80211_BSS_SIGNAL_MBM,
+ NL80211_BSS_SIGNAL_UNSPEC,
+ NL80211_BSS_STATUS,
+ NL80211_BSS_SEEN_MS_AGO,
+ NL80211_BSS_BEACON_IES,
+
+ /* keep last */
+ __NL80211_BSS_AFTER_LAST,
+ NL80211_BSS_MAX = __NL80211_BSS_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_bss_status - BSS "status"
+ * @NL80211_BSS_STATUS_AUTHENTICATED: Authenticated with this BSS.
+ * @NL80211_BSS_STATUS_ASSOCIATED: Associated with this BSS.
+ * @NL80211_BSS_STATUS_IBSS_JOINED: Joined to this IBSS.
+ *
+ * The BSS status is a BSS attribute in scan dumps, which
+ * indicates the status the interface has wrt. this BSS.
+ */
+enum nl80211_bss_status {
+ NL80211_BSS_STATUS_AUTHENTICATED,
+ NL80211_BSS_STATUS_ASSOCIATED,
+ NL80211_BSS_STATUS_IBSS_JOINED,
+};
+
+/**
+ * enum nl80211_auth_type - AuthenticationType
+ *
+ * @NL80211_AUTHTYPE_OPEN_SYSTEM: Open System authentication
+ * @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only)
+ * @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r)
+ * @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP)
+ * @__NL80211_AUTHTYPE_NUM: internal
+ * @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm
+ * @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by
+ * trying multiple times); this is invalid in netlink -- leave out
+ * the attribute for this on CONNECT commands.
+ */
+enum nl80211_auth_type {
+ NL80211_AUTHTYPE_OPEN_SYSTEM,
+ NL80211_AUTHTYPE_SHARED_KEY,
+ NL80211_AUTHTYPE_FT,
+ NL80211_AUTHTYPE_NETWORK_EAP,
+
+ /* keep last */
+ __NL80211_AUTHTYPE_NUM,
+ NL80211_AUTHTYPE_MAX = __NL80211_AUTHTYPE_NUM - 1,
+ NL80211_AUTHTYPE_AUTOMATIC
+};
+
+/**
+ * enum nl80211_key_type - Key Type
+ * @NL80211_KEYTYPE_GROUP: Group (broadcast/multicast) key
+ * @NL80211_KEYTYPE_PAIRWISE: Pairwise (unicast/individual) key
+ * @NL80211_KEYTYPE_PEERKEY: PeerKey (DLS)
+ * @NUM_NL80211_KEYTYPES: number of defined key types
+ */
+enum nl80211_key_type {
+ NL80211_KEYTYPE_GROUP,
+ NL80211_KEYTYPE_PAIRWISE,
+ NL80211_KEYTYPE_PEERKEY,
+
+ NUM_NL80211_KEYTYPES
+};
+
+/**
+ * enum nl80211_mfp - Management frame protection state
+ * @NL80211_MFP_NO: Management frame protection not used
+ * @NL80211_MFP_REQUIRED: Management frame protection required
+ */
+enum nl80211_mfp {
+ NL80211_MFP_NO,
+ NL80211_MFP_REQUIRED,
+};
+
+enum nl80211_wpa_versions {
+ NL80211_WPA_VERSION_1 = 1 << 0,
+ NL80211_WPA_VERSION_2 = 1 << 1,
+};
+
+/**
+ * enum nl80211_key_default_types - key default types
+ * @__NL80211_KEY_DEFAULT_TYPE_INVALID: invalid
+ * @NL80211_KEY_DEFAULT_TYPE_UNICAST: key should be used as default
+ * unicast key
+ * @NL80211_KEY_DEFAULT_TYPE_MULTICAST: key should be used as default
+ * multicast key
+ * @NUM_NL80211_KEY_DEFAULT_TYPES: number of default types
+ */
+enum nl80211_key_default_types {
+ __NL80211_KEY_DEFAULT_TYPE_INVALID,
+ NL80211_KEY_DEFAULT_TYPE_UNICAST,
+ NL80211_KEY_DEFAULT_TYPE_MULTICAST,
+
+ NUM_NL80211_KEY_DEFAULT_TYPES
+};
+
+/**
+ * enum nl80211_key_attributes - key attributes
+ * @__NL80211_KEY_INVALID: invalid
+ * @NL80211_KEY_DATA: (temporal) key data; for TKIP this consists of
+ * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC
+ * keys
+ * @NL80211_KEY_IDX: key ID (u8, 0-3)
+ * @NL80211_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11
+ * section 7.3.2.25.1, e.g. 0x000FAC04)
+ * @NL80211_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and
+ * CCMP keys, each six bytes in little endian
+ * @NL80211_KEY_DEFAULT: flag indicating default key
+ * @NL80211_KEY_DEFAULT_MGMT: flag indicating default management key
+ * @NL80211_KEY_TYPE: the key type from enum nl80211_key_type, if not
+ * specified the default depends on whether a MAC address was
+ * given with the command using the key or not (u32)
+ * @NL80211_KEY_DEFAULT_TYPES: A nested attribute containing flags
+ * attributes, specifying what a key should be set as default as.
+ * See &enum nl80211_key_default_types.
+ * @__NL80211_KEY_AFTER_LAST: internal
+ * @NL80211_KEY_MAX: highest key attribute
+ */
+enum nl80211_key_attributes {
+ __NL80211_KEY_INVALID,
+ NL80211_KEY_DATA,
+ NL80211_KEY_IDX,
+ NL80211_KEY_CIPHER,
+ NL80211_KEY_SEQ,
+ NL80211_KEY_DEFAULT,
+ NL80211_KEY_DEFAULT_MGMT,
+ NL80211_KEY_TYPE,
+ NL80211_KEY_DEFAULT_TYPES,
+
+ /* keep last */
+ __NL80211_KEY_AFTER_LAST,
+ NL80211_KEY_MAX = __NL80211_KEY_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_tx_rate_attributes - TX rate set attributes
+ * @__NL80211_TXRATE_INVALID: invalid
+ * @NL80211_TXRATE_LEGACY: Legacy (non-MCS) rates allowed for TX rate selection
+ * in an array of rates as defined in IEEE 802.11 7.3.2.2 (u8 values with
+ * 1 = 500 kbps) but without the IE length restriction (at most
+ * %NL80211_MAX_SUPP_RATES in a single array).
+ * @NL80211_TXRATE_MCS: HT (MCS) rates allowed for TX rate selection
+ * in an array of MCS numbers.
+ * @__NL80211_TXRATE_AFTER_LAST: internal
+ * @NL80211_TXRATE_MAX: highest TX rate attribute
+ */
+enum nl80211_tx_rate_attributes {
+ __NL80211_TXRATE_INVALID,
+ NL80211_TXRATE_LEGACY,
+ NL80211_TXRATE_MCS,
+
+ /* keep last */
+ __NL80211_TXRATE_AFTER_LAST,
+ NL80211_TXRATE_MAX = __NL80211_TXRATE_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_band - Frequency band
+ * @NL80211_BAND_2GHZ: 2.4 GHz ISM band
+ * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz)
+ */
+enum nl80211_band {
+ NL80211_BAND_2GHZ,
+ NL80211_BAND_5GHZ,
+};
+
+enum nl80211_ps_state {
+ NL80211_PS_DISABLED,
+ NL80211_PS_ENABLED,
+};
+
+/**
+ * enum nl80211_attr_cqm - connection quality monitor attributes
+ * @__NL80211_ATTR_CQM_INVALID: invalid
+ * @NL80211_ATTR_CQM_RSSI_THOLD: RSSI threshold in dBm. This value specifies
+ * the threshold for the RSSI level at which an event will be sent. Zero
+ * to disable.
+ * @NL80211_ATTR_CQM_RSSI_HYST: RSSI hysteresis in dBm. This value specifies
+ * the minimum amount the RSSI level must change after an event before a
+ * new event may be issued (to reduce effects of RSSI oscillation).
+ * @NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT: RSSI threshold event
+ * @NL80211_ATTR_CQM_PKT_LOSS_EVENT: a u32 value indicating that this many
+ * consecutive packets were not acknowledged by the peer
+ * @__NL80211_ATTR_CQM_AFTER_LAST: internal
+ * @NL80211_ATTR_CQM_MAX: highest key attribute
+ */
+enum nl80211_attr_cqm {
+ __NL80211_ATTR_CQM_INVALID,
+ NL80211_ATTR_CQM_RSSI_THOLD,
+ NL80211_ATTR_CQM_RSSI_HYST,
+ NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT,
+ NL80211_ATTR_CQM_PKT_LOSS_EVENT,
+
+ /* keep last */
+ __NL80211_ATTR_CQM_AFTER_LAST,
+ NL80211_ATTR_CQM_MAX = __NL80211_ATTR_CQM_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_cqm_rssi_threshold_event - RSSI threshold event
+ * @NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW: The RSSI level is lower than the
+ * configured threshold
+ * @NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH: The RSSI is higher than the
+ * configured threshold
+ */
+enum nl80211_cqm_rssi_threshold_event {
+ NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+ NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+};
+
+
+/**
+ * enum nl80211_tx_power_setting - TX power adjustment
+ * @NL80211_TX_POWER_AUTOMATIC: automatically determine transmit power
+ * @NL80211_TX_POWER_LIMITED: limit TX power by the mBm parameter
+ * @NL80211_TX_POWER_FIXED: fix TX power to the mBm parameter
+ */
+enum nl80211_tx_power_setting {
+ NL80211_TX_POWER_AUTOMATIC,
+ NL80211_TX_POWER_LIMITED,
+ NL80211_TX_POWER_FIXED,
+};
+
+/**
+ * enum nl80211_wowlan_packet_pattern_attr - WoWLAN packet pattern attribute
+ * @__NL80211_WOWLAN_PKTPAT_INVALID: invalid number for nested attribute
+ * @NL80211_WOWLAN_PKTPAT_PATTERN: the pattern, values where the mask has
+ * a zero bit are ignored
+ * @NL80211_WOWLAN_PKTPAT_MASK: pattern mask, must be long enough to have
+ * a bit for each byte in the pattern. The lowest-order bit corresponds
+ * to the first byte of the pattern, but the bytes of the pattern are
+ * in a little-endian-like format, i.e. the 9th byte of the pattern
+ * corresponds to the lowest-order bit in the second byte of the mask.
+ * For example: The match 00:xx:00:00:xx:00:00:00:00:xx:xx:xx (where
+ * xx indicates "don't care") would be represented by a pattern of
+ * twelve zero bytes, and a mask of "0xed,0x07".
+ * Note that the pattern matching is done as though frames were not
+ * 802.11 frames but 802.3 frames, i.e. the frame is fully unpacked
+ * first (including SNAP header unpacking) and then matched.
+ * @NUM_NL80211_WOWLAN_PKTPAT: number of attributes
+ * @MAX_NL80211_WOWLAN_PKTPAT: max attribute number
+ */
+enum nl80211_wowlan_packet_pattern_attr {
+ __NL80211_WOWLAN_PKTPAT_INVALID,
+ NL80211_WOWLAN_PKTPAT_MASK,
+ NL80211_WOWLAN_PKTPAT_PATTERN,
+
+ NUM_NL80211_WOWLAN_PKTPAT,
+ MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1,
+};
+
+/**
+ * struct nl80211_wowlan_pattern_support - pattern support information
+ * @max_patterns: maximum number of patterns supported
+ * @min_pattern_len: minimum length of each pattern
+ * @max_pattern_len: maximum length of each pattern
+ *
+ * This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when
+ * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the
+ * capability information given by the kernel to userspace.
+ */
+struct nl80211_wowlan_pattern_support {
+ __u32 max_patterns;
+ __u32 min_pattern_len;
+ __u32 max_pattern_len;
+} __attribute__((packed));
+
+/**
+ * enum nl80211_wowlan_triggers - WoWLAN trigger definitions
+ * @__NL80211_WOWLAN_TRIG_INVALID: invalid number for nested attributes
+ * @NL80211_WOWLAN_TRIG_ANY: wake up on any activity, do not really put
+ * the chip into a special state -- works best with chips that have
+ * support for low-power operation already (flag)
+ * @NL80211_WOWLAN_TRIG_DISCONNECT: wake up on disconnect, the way disconnect
+ * is detected is implementation-specific (flag)
+ * @NL80211_WOWLAN_TRIG_MAGIC_PKT: wake up on magic packet (6x 0xff, followed
+ * by 16 repetitions of MAC addr, anywhere in payload) (flag)
+ * @NL80211_WOWLAN_TRIG_PKT_PATTERN: wake up on the specified packet patterns
+ * which are passed in an array of nested attributes, each nested attribute
+ * defining a with attributes from &struct nl80211_wowlan_trig_pkt_pattern.
+ * Each pattern defines a wakeup packet. The matching is done on the MSDU,
+ * i.e. as though the packet was an 802.3 packet, so the pattern matching
+ * is done after the packet is converted to the MSDU.
+ *
+ * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute
+ * carrying a &struct nl80211_wowlan_pattern_support.
+ * @NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED: Not a real trigger, and cannot be
+ * used when setting, used only to indicate that GTK rekeying is supported
+ * by the device (flag)
+ * @NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE: wake up on GTK rekey failure (if
+ * done by the device) (flag)
+ * @NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST: wake up on EAP Identity Request
+ * packet (flag)
+ * @NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE: wake up on 4-way handshake (flag)
+ * @NL80211_WOWLAN_TRIG_RFKILL_RELEASE: wake up when rfkill is released
+ * (on devices that have rfkill in the device) (flag)
+ * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers
+ * @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number
+ */
+enum nl80211_wowlan_triggers {
+ __NL80211_WOWLAN_TRIG_INVALID,
+ NL80211_WOWLAN_TRIG_ANY,
+ NL80211_WOWLAN_TRIG_DISCONNECT,
+ NL80211_WOWLAN_TRIG_MAGIC_PKT,
+ NL80211_WOWLAN_TRIG_PKT_PATTERN,
+ NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED,
+ NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE,
+ NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST,
+ NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE,
+ NL80211_WOWLAN_TRIG_RFKILL_RELEASE,
+
+ /* keep last */
+ NUM_NL80211_WOWLAN_TRIG,
+ MAX_NL80211_WOWLAN_TRIG = NUM_NL80211_WOWLAN_TRIG - 1
+};
+
+/**
+ * enum nl80211_iface_limit_attrs - limit attributes
+ * @NL80211_IFACE_LIMIT_UNSPEC: (reserved)
+ * @NL80211_IFACE_LIMIT_MAX: maximum number of interfaces that
+ * can be chosen from this set of interface types (u32)
+ * @NL80211_IFACE_LIMIT_TYPES: nested attribute containing a
+ * flag attribute for each interface type in this set
+ * @NUM_NL80211_IFACE_LIMIT: number of attributes
+ * @MAX_NL80211_IFACE_LIMIT: highest attribute number
+ */
+enum nl80211_iface_limit_attrs {
+ NL80211_IFACE_LIMIT_UNSPEC,
+ NL80211_IFACE_LIMIT_MAX,
+ NL80211_IFACE_LIMIT_TYPES,
+
+ /* keep last */
+ NUM_NL80211_IFACE_LIMIT,
+ MAX_NL80211_IFACE_LIMIT = NUM_NL80211_IFACE_LIMIT - 1
+};
+
+/**
+ * enum nl80211_if_combination_attrs -- interface combination attributes
+ *
+ * @NL80211_IFACE_COMB_UNSPEC: (reserved)
+ * @NL80211_IFACE_COMB_LIMITS: Nested attributes containing the limits
+ * for given interface types, see &enum nl80211_iface_limit_attrs.
+ * @NL80211_IFACE_COMB_MAXNUM: u32 attribute giving the total number of
+ * interfaces that can be created in this group. This number doesn't
+ * apply to interfaces purely managed in software, which are listed
+ * in a separate attribute %NL80211_ATTR_INTERFACES_SOFTWARE.
+ * @NL80211_IFACE_COMB_STA_AP_BI_MATCH: flag attribute specifying that
+ * beacon intervals within this group must be all the same even for
+ * infrastructure and AP/GO combinations, i.e. the GO(s) must adopt
+ * the infrastructure network's beacon interval.
+ * @NL80211_IFACE_COMB_NUM_CHANNELS: u32 attribute specifying how many
+ * different channels may be used within this group.
+ * @NUM_NL80211_IFACE_COMB: number of attributes
+ * @MAX_NL80211_IFACE_COMB: highest attribute number
+ *
+ * Examples:
+ * limits = [ #{STA} <= 1, #{AP} <= 1 ], matching BI, channels = 1, max = 2
+ * => allows an AP and a STA that must match BIs
+ *
+ * numbers = [ #{AP, P2P-GO} <= 8 ], channels = 1, max = 8
+ * => allows 8 of AP/GO
+ *
+ * numbers = [ #{STA} <= 2 ], channels = 2, max = 2
+ * => allows two STAs on different channels
+ *
+ * numbers = [ #{STA} <= 1, #{P2P-client,P2P-GO} <= 3 ], max = 4
+ * => allows a STA plus three P2P interfaces
+ *
+ * The list of these four possiblities could completely be contained
+ * within the %NL80211_ATTR_INTERFACE_COMBINATIONS attribute to indicate
+ * that any of these groups must match.
+ *
+ * "Combinations" of just a single interface will not be listed here,
+ * a single interface of any valid interface type is assumed to always
+ * be possible by itself. This means that implicitly, for each valid
+ * interface type, the following group always exists:
+ * numbers = [ #{<type>} <= 1 ], channels = 1, max = 1
+ */
+enum nl80211_if_combination_attrs {
+ NL80211_IFACE_COMB_UNSPEC,
+ NL80211_IFACE_COMB_LIMITS,
+ NL80211_IFACE_COMB_MAXNUM,
+ NL80211_IFACE_COMB_STA_AP_BI_MATCH,
+ NL80211_IFACE_COMB_NUM_CHANNELS,
+
+ /* keep last */
+ NUM_NL80211_IFACE_COMB,
+ MAX_NL80211_IFACE_COMB = NUM_NL80211_IFACE_COMB - 1
+};
+
+
+/**
+ * enum nl80211_plink_state - state of a mesh peer link finite state machine
+ *
+ * @NL80211_PLINK_LISTEN: initial state, considered the implicit
+ * state of non existant mesh peer links
+ * @NL80211_PLINK_OPN_SNT: mesh plink open frame has been sent to
+ * this mesh peer
+ * @NL80211_PLINK_OPN_RCVD: mesh plink open frame has been received
+ * from this mesh peer
+ * @NL80211_PLINK_CNF_RCVD: mesh plink confirm frame has been
+ * received from this mesh peer
+ * @NL80211_PLINK_ESTAB: mesh peer link is established
+ * @NL80211_PLINK_HOLDING: mesh peer link is being closed or cancelled
+ * @NL80211_PLINK_BLOCKED: all frames transmitted from this mesh
+ * plink are discarded
+ * @NUM_NL80211_PLINK_STATES: number of peer link states
+ * @MAX_NL80211_PLINK_STATES: highest numerical value of plink states
+ */
+enum nl80211_plink_state {
+ NL80211_PLINK_LISTEN,
+ NL80211_PLINK_OPN_SNT,
+ NL80211_PLINK_OPN_RCVD,
+ NL80211_PLINK_CNF_RCVD,
+ NL80211_PLINK_ESTAB,
+ NL80211_PLINK_HOLDING,
+ NL80211_PLINK_BLOCKED,
+
+ /* keep last */
+ NUM_NL80211_PLINK_STATES,
+ MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 1
+};
+
+#define NL80211_KCK_LEN 16
+#define NL80211_KEK_LEN 16
+#define NL80211_REPLAY_CTR_LEN 8
+
+/**
+ * enum nl80211_rekey_data - attributes for GTK rekey offload
+ * @__NL80211_REKEY_DATA_INVALID: invalid number for nested attributes
+ * @NL80211_REKEY_DATA_KEK: key encryption key (binary)
+ * @NL80211_REKEY_DATA_KCK: key confirmation key (binary)
+ * @NL80211_REKEY_DATA_REPLAY_CTR: replay counter (binary)
+ * @NUM_NL80211_REKEY_DATA: number of rekey attributes (internal)
+ * @MAX_NL80211_REKEY_DATA: highest rekey attribute (internal)
+ */
+enum nl80211_rekey_data {
+ __NL80211_REKEY_DATA_INVALID,
+ NL80211_REKEY_DATA_KEK,
+ NL80211_REKEY_DATA_KCK,
+ NL80211_REKEY_DATA_REPLAY_CTR,
+
+ /* keep last */
+ NUM_NL80211_REKEY_DATA,
+ MAX_NL80211_REKEY_DATA = NUM_NL80211_REKEY_DATA - 1
+};
+
+/**
+ * enum nl80211_hidden_ssid - values for %NL80211_ATTR_HIDDEN_SSID
+ * @NL80211_HIDDEN_SSID_NOT_IN_USE: do not hide SSID (i.e., broadcast it in
+ * Beacon frames)
+ * @NL80211_HIDDEN_SSID_ZERO_LEN: hide SSID by using zero-length SSID element
+ * in Beacon frames
+ * @NL80211_HIDDEN_SSID_ZERO_CONTENTS: hide SSID by using correct length of SSID
+ * element in Beacon frames but zero out each byte in the SSID
+ */
+enum nl80211_hidden_ssid {
+ NL80211_HIDDEN_SSID_NOT_IN_USE,
+ NL80211_HIDDEN_SSID_ZERO_LEN,
+ NL80211_HIDDEN_SSID_ZERO_CONTENTS
+};
+
+/**
+ * enum nl80211_sta_wme_attr - station WME attributes
+ * @__NL80211_STA_WME_INVALID: invalid number for nested attribute
+ * @NL80211_STA_WME_UAPSD_QUEUES: bitmap of uapsd queues. the format
+ * is the same as the AC bitmap in the QoS info field.
+ * @NL80211_STA_WME_MAX_SP: max service period. the format is the same
+ * as the MAX_SP field in the QoS info field (but already shifted down).
+ * @__NL80211_STA_WME_AFTER_LAST: internal
+ * @NL80211_STA_WME_MAX: highest station WME attribute
+ */
+enum nl80211_sta_wme_attr {
+ __NL80211_STA_WME_INVALID,
+ NL80211_STA_WME_UAPSD_QUEUES,
+ NL80211_STA_WME_MAX_SP,
+
+ /* keep last */
+ __NL80211_STA_WME_AFTER_LAST,
+ NL80211_STA_WME_MAX = __NL80211_STA_WME_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_pmksa_candidate_attr - attributes for PMKSA caching candidates
+ * @__NL80211_PMKSA_CANDIDATE_INVALID: invalid number for nested attributes
+ * @NL80211_PMKSA_CANDIDATE_INDEX: candidate index (u32; the smaller, the higher
+ * priority)
+ * @NL80211_PMKSA_CANDIDATE_BSSID: candidate BSSID (6 octets)
+ * @NL80211_PMKSA_CANDIDATE_PREAUTH: RSN pre-authentication supported (flag)
+ * @NUM_NL80211_PMKSA_CANDIDATE: number of PMKSA caching candidate attributes
+ * (internal)
+ * @MAX_NL80211_PMKSA_CANDIDATE: highest PMKSA caching candidate attribute
+ * (internal)
+ */
+enum nl80211_pmksa_candidate_attr {
+ __NL80211_PMKSA_CANDIDATE_INVALID,
+ NL80211_PMKSA_CANDIDATE_INDEX,
+ NL80211_PMKSA_CANDIDATE_BSSID,
+ NL80211_PMKSA_CANDIDATE_PREAUTH,
+
+ /* keep last */
+ NUM_NL80211_PMKSA_CANDIDATE,
+ MAX_NL80211_PMKSA_CANDIDATE = NUM_NL80211_PMKSA_CANDIDATE - 1
+};
+
+/**
+ * enum nl80211_tdls_operation - values for %NL80211_ATTR_TDLS_OPERATION
+ * @NL80211_TDLS_DISCOVERY_REQ: Send a TDLS discovery request
+ * @NL80211_TDLS_SETUP: Setup TDLS link
+ * @NL80211_TDLS_TEARDOWN: Teardown a TDLS link which is already established
+ * @NL80211_TDLS_ENABLE_LINK: Enable TDLS link
+ * @NL80211_TDLS_DISABLE_LINK: Disable TDLS link
+ */
+enum nl80211_tdls_operation {
+ NL80211_TDLS_DISCOVERY_REQ,
+ NL80211_TDLS_SETUP,
+ NL80211_TDLS_TEARDOWN,
+ NL80211_TDLS_ENABLE_LINK,
+ NL80211_TDLS_DISABLE_LINK,
+};
+
+/*
+ * enum nl80211_ap_sme_features - device-integrated AP features
+ * Reserved for future use, no bits are defined in
+ * NL80211_ATTR_DEVICE_AP_SME yet.
+enum nl80211_ap_sme_features {
+};
+ */
+
+/**
+ * enum nl80211_feature_flags - device/driver features
+ * @NL80211_FEATURE_SK_TX_STATUS: This driver supports reflecting back
+ * TX status to the socket error queue when requested with the
+ * socket option.
+ * @NL80211_FEATURE_HT_IBSS: This driver supports IBSS with HT datarates.
+ */
+enum nl80211_feature_flags {
+ NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
+ NL80211_FEATURE_HT_IBSS = 1 << 1,
+};
+
+/**
+ * enum nl80211_probe_resp_offload_support_attr - optional supported
+ * protocols for probe-response offloading by the driver/FW.
+ * To be used with the %NL80211_ATTR_PROBE_RESP_OFFLOAD attribute.
+ * Each enum value represents a bit in the bitmap of supported
+ * protocols. Typically a subset of probe-requests belonging to a
+ * supported protocol will be excluded from offload and uploaded
+ * to the host.
+ *
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS: Support for WPS ver. 1
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2: Support for WPS ver. 2
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P: Support for P2P
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U: Support for 802.11u
+ */
+enum nl80211_probe_resp_offload_support_attr {
+ NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS = 1<<0,
+ NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 = 1<<1,
+ NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P = 1<<2,
+ NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U = 1<<3,
+};
+
+#endif /* __LINUX_NL80211_H */
diff --git a/package/iwinfo/src/include/iwinfo/api/wext.h b/package/iwinfo/src/include/iwinfo/api/wext.h
new file mode 100644
index 000000000..6b5838e1b
--- /dev/null
+++ b/package/iwinfo/src/include/iwinfo/api/wext.h
@@ -0,0 +1,1139 @@
+/*
+ * This file define a set of standard wireless extensions
+ *
+ * Version : 22 16.3.07
+ *
+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+ * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
+ */
+
+#ifndef _LINUX_WIRELESS_H
+#define _LINUX_WIRELESS_H
+
+/************************** DOCUMENTATION **************************/
+/*
+ * Initial APIs (1996 -> onward) :
+ * -----------------------------
+ * Basically, the wireless extensions are for now a set of standard ioctl
+ * call + /proc/net/wireless
+ *
+ * The entry /proc/net/wireless give statistics and information on the
+ * driver.
+ * This is better than having each driver having its entry because
+ * its centralised and we may remove the driver module safely.
+ *
+ * Ioctl are used to configure the driver and issue commands. This is
+ * better than command line options of insmod because we may want to
+ * change dynamically (while the driver is running) some parameters.
+ *
+ * The ioctl mechanimsm are copied from standard devices ioctl.
+ * We have the list of command plus a structure descibing the
+ * data exchanged...
+ * Note that to add these ioctl, I was obliged to modify :
+ * # net/core/dev.c (two place + add include)
+ * # net/ipv4/af_inet.c (one place + add include)
+ *
+ * /proc/net/wireless is a copy of /proc/net/dev.
+ * We have a structure for data passed from the driver to /proc/net/wireless
+ * Too add this, I've modified :
+ * # net/core/dev.c (two other places)
+ * # include/linux/netdevice.h (one place)
+ * # include/linux/proc_fs.h (one place)
+ *
+ * New driver API (2002 -> onward) :
+ * -------------------------------
+ * This file is only concerned with the user space API and common definitions.
+ * The new driver API is defined and documented in :
+ * # include/net/iw_handler.h
+ *
+ * Note as well that /proc/net/wireless implementation has now moved in :
+ * # net/core/wireless.c
+ *
+ * Wireless Events (2002 -> onward) :
+ * --------------------------------
+ * Events are defined at the end of this file, and implemented in :
+ * # net/core/wireless.c
+ *
+ * Other comments :
+ * --------------
+ * Do not add here things that are redundant with other mechanisms
+ * (drivers init, ifconfig, /proc/net/dev, ...) and with are not
+ * wireless specific.
+ *
+ * These wireless extensions are not magic : each driver has to provide
+ * support for them...
+ *
+ * IMPORTANT NOTE : As everything in the kernel, this is very much a
+ * work in progress. Contact me if you have ideas of improvements...
+ */
+
+/***************************** INCLUDES *****************************/
+
+/* This header is used in user-space, therefore need to be sanitised
+ * for that purpose. Those includes are usually not compatible with glibc.
+ * To know which includes to use in user-space, check iwlib.h. */
+#ifdef __KERNEL__
+#include <linux/types.h> /* for "caddr_t" et al */
+#include <linux/socket.h> /* for "struct sockaddr" et al */
+#include <linux/if.h> /* for IFNAMSIZ and co... */
+#endif /* __KERNEL__ */
+
+/***************************** VERSION *****************************/
+/*
+ * This constant is used to know the availability of the wireless
+ * extensions and to know which version of wireless extensions it is
+ * (there is some stuff that will be added in the future...)
+ * I just plan to increment with each new version.
+ */
+#define WIRELESS_EXT 22
+
+/*
+ * Changes :
+ *
+ * V2 to V3
+ * --------
+ * Alan Cox start some incompatibles changes. I've integrated a bit more.
+ * - Encryption renamed to Encode to avoid US regulation problems
+ * - Frequency changed from float to struct to avoid problems on old 386
+ *
+ * V3 to V4
+ * --------
+ * - Add sensitivity
+ *
+ * V4 to V5
+ * --------
+ * - Missing encoding definitions in range
+ * - Access points stuff
+ *
+ * V5 to V6
+ * --------
+ * - 802.11 support (ESSID ioctls)
+ *
+ * V6 to V7
+ * --------
+ * - define IW_ESSID_MAX_SIZE and IW_MAX_AP
+ *
+ * V7 to V8
+ * --------
+ * - Changed my e-mail address
+ * - More 802.11 support (nickname, rate, rts, frag)
+ * - List index in frequencies
+ *
+ * V8 to V9
+ * --------
+ * - Support for 'mode of operation' (ad-hoc, managed...)
+ * - Support for unicast and multicast power saving
+ * - Change encoding to support larger tokens (>64 bits)
+ * - Updated iw_params (disable, flags) and use it for NWID
+ * - Extracted iw_point from iwreq for clarity
+ *
+ * V9 to V10
+ * ---------
+ * - Add PM capability to range structure
+ * - Add PM modifier : MAX/MIN/RELATIVE
+ * - Add encoding option : IW_ENCODE_NOKEY
+ * - Add TxPower ioctls (work like TxRate)
+ *
+ * V10 to V11
+ * ----------
+ * - Add WE version in range (help backward/forward compatibility)
+ * - Add retry ioctls (work like PM)
+ *
+ * V11 to V12
+ * ----------
+ * - Add SIOCSIWSTATS to get /proc/net/wireless programatically
+ * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space
+ * - Add new statistics (frag, retry, beacon)
+ * - Add average quality (for user space calibration)
+ *
+ * V12 to V13
+ * ----------
+ * - Document creation of new driver API.
+ * - Extract union iwreq_data from struct iwreq (for new driver API).
+ * - Rename SIOCSIWNAME as SIOCSIWCOMMIT
+ *
+ * V13 to V14
+ * ----------
+ * - Wireless Events support : define struct iw_event
+ * - Define additional specific event numbers
+ * - Add "addr" and "param" fields in union iwreq_data
+ * - AP scanning stuff (SIOCSIWSCAN and friends)
+ *
+ * V14 to V15
+ * ----------
+ * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg
+ * - Make struct iw_freq signed (both m & e), add explicit padding
+ * - Add IWEVCUSTOM for driver specific event/scanning token
+ * - Add IW_MAX_GET_SPY for driver returning a lot of addresses
+ * - Add IW_TXPOW_RANGE for range of Tx Powers
+ * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
+ * - Add IW_MODE_MONITOR for passive monitor
+ *
+ * V15 to V16
+ * ----------
+ * - Increase the number of bitrates in iw_range to 32 (for 802.11g)
+ * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a)
+ * - Reshuffle struct iw_range for increases, add filler
+ * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses
+ * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support
+ * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
+ * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index
+ *
+ * V16 to V17
+ * ----------
+ * - Add flags to frequency -> auto/fixed
+ * - Document (struct iw_quality *)->updated, add new flags (INVALID)
+ * - Wireless Event capability in struct iw_range
+ * - Add support for relative TxPower (yick !)
+ *
+ * V17 to V18 (From Jouni Malinen <jkmaline@cc.hut.fi>)
+ * ----------
+ * - Add support for WPA/WPA2
+ * - Add extended encoding configuration (SIOCSIWENCODEEXT and
+ * SIOCGIWENCODEEXT)
+ * - Add SIOCSIWGENIE/SIOCGIWGENIE
+ * - Add SIOCSIWMLME
+ * - Add SIOCSIWPMKSA
+ * - Add struct iw_range bit field for supported encoding capabilities
+ * - Add optional scan request parameters for SIOCSIWSCAN
+ * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA
+ * related parameters (extensible up to 4096 parameter values)
+ * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE,
+ * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND
+ *
+ * V18 to V19
+ * ----------
+ * - Remove (struct iw_point *)->pointer from events and streams
+ * - Remove header includes to help user space
+ * - Increase IW_ENCODING_TOKEN_MAX from 32 to 64
+ * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
+ * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
+ * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
+ *
+ * V19 to V20
+ * ----------
+ * - RtNetlink requests support (SET/GET)
+ *
+ * V20 to V21
+ * ----------
+ * - Remove (struct net_device *)->get_wireless_stats()
+ * - Change length in ESSID and NICK to strlen() instead of strlen()+1
+ * - Add IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers
+ * - Power/Retry relative values no longer * 100000
+ * - Add explicit flag to tell stats are in 802.11k RCPI : IW_QUAL_RCPI
+ *
+ * V21 to V22
+ * ----------
+ * - Prevent leaking of kernel space in stream on 64 bits.
+ */
+
+/**************************** CONSTANTS ****************************/
+
+/* -------------------------- IOCTL LIST -------------------------- */
+
+/* Wireless Identification */
+#define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */
+#define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */
+/* SIOCGIWNAME is used to verify the presence of Wireless Extensions.
+ * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"...
+ * Don't put the name of your driver there, it's useless. */
+
+/* Basic operations */
+#define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */
+#define SIOCGIWNWID 0x8B03 /* get network id (the cell) */
+#define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */
+#define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */
+#define SIOCSIWMODE 0x8B06 /* set operation mode */
+#define SIOCGIWMODE 0x8B07 /* get operation mode */
+#define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */
+#define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */
+
+/* Informative stuff */
+#define SIOCSIWRANGE 0x8B0A /* Unused */
+#define SIOCGIWRANGE 0x8B0B /* Get range of parameters */
+#define SIOCSIWPRIV 0x8B0C /* Unused */
+#define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */
+#define SIOCSIWSTATS 0x8B0E /* Unused */
+#define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */
+/* SIOCGIWSTATS is strictly used between user space and the kernel, and
+ * is never passed to the driver (i.e. the driver will never see it). */
+
+/* Spy support (statistics per MAC address - used for Mobile IP support) */
+#define SIOCSIWSPY 0x8B10 /* set spy addresses */
+#define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */
+#define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */
+#define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */
+
+/* Access Point manipulation */
+#define SIOCSIWAP 0x8B14 /* set access point MAC addresses */
+#define SIOCGIWAP 0x8B15 /* get access point MAC addresses */
+#define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */
+#define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */
+#define SIOCGIWSCAN 0x8B19 /* get scanning results */
+
+/* 802.11 specific support */
+#define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */
+#define SIOCGIWESSID 0x8B1B /* get ESSID */
+#define SIOCSIWNICKN 0x8B1C /* set node name/nickname */
+#define SIOCGIWNICKN 0x8B1D /* get node name/nickname */
+/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit
+ * within the 'iwreq' structure, so we need to use the 'data' member to
+ * point to a string in user space, like it is done for RANGE... */
+
+/* Other parameters useful in 802.11 and some other devices */
+#define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */
+#define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */
+#define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */
+#define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */
+#define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */
+#define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */
+#define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */
+#define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */
+#define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */
+#define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */
+
+/* Encoding stuff (scrambling, hardware security, WEP...) */
+#define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */
+#define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */
+/* Power saving stuff (power management, unicast and multicast) */
+#define SIOCSIWPOWER 0x8B2C /* set Power Management settings */
+#define SIOCGIWPOWER 0x8B2D /* get Power Management settings */
+/* Modulation bitmask */
+#define SIOCSIWMODUL 0x8B2E /* set Modulations settings */
+#define SIOCGIWMODUL 0x8B2F /* get Modulations settings */
+
+/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM).
+ * This ioctl uses struct iw_point and data buffer that includes IE id and len
+ * fields. More than one IE may be included in the request. Setting the generic
+ * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers
+ * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers
+ * are required to report the used IE as a wireless event, e.g., when
+ * associating with an AP. */
+#define SIOCSIWGENIE 0x8B30 /* set generic IE */
+#define SIOCGIWGENIE 0x8B31 /* get generic IE */
+
+/* WPA : IEEE 802.11 MLME requests */
+#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses
+ * struct iw_mlme */
+/* WPA : Authentication mode parameters */
+#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */
+#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */
+
+/* WPA : Extended version of encoding configuration */
+#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */
+#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */
+
+/* WPA2 : PMKSA cache management */
+#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */
+
+/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
+
+/* These 32 ioctl are wireless device private, for 16 commands.
+ * Each driver is free to use them for whatever purpose it chooses,
+ * however the driver *must* export the description of those ioctls
+ * with SIOCGIWPRIV and *must* use arguments as defined below.
+ * If you don't follow those rules, DaveM is going to hate you (reason :
+ * it make mixed 32/64bit operation impossible).
+ */
+#define SIOCIWFIRSTPRIV 0x8BE0
+#define SIOCIWLASTPRIV 0x8BFF
+/* Previously, we were using SIOCDEVPRIVATE, but we now have our
+ * separate range because of collisions with other tools such as
+ * 'mii-tool'.
+ * We now have 32 commands, so a bit more space ;-).
+ * Also, all 'even' commands are only usable by root and don't return the
+ * content of ifr/iwr to user (but you are not obliged to use the set/get
+ * convention, just use every other two command). More details in iwpriv.c.
+ * And I repeat : you are not forced to use them with iwpriv, but you
+ * must be compliant with it.
+ */
+
+/* ------------------------- IOCTL STUFF ------------------------- */
+
+/* The first and the last (range) */
+#define SIOCIWFIRST 0x8B00
+#define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */
+#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST)
+
+/* Odd : get (world access), even : set (root access) */
+#define IW_IS_SET(cmd) (!((cmd) & 0x1))
+#define IW_IS_GET(cmd) ((cmd) & 0x1)
+
+/* ----------------------- WIRELESS EVENTS ----------------------- */
+/* Those are *NOT* ioctls, do not issue request on them !!! */
+/* Most events use the same identifier as ioctl requests */
+
+#define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */
+#define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */
+#define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */
+#define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */
+#define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */
+#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..)
+ * (scan results); This includes id and
+ * length fields. One IWEVGENIE may
+ * contain more than one IE. Scan
+ * results may contain one or more
+ * IWEVGENIE events. */
+#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure
+ * (struct iw_michaelmicfailure)
+ */
+#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request.
+ * The data includes id and length
+ * fields and may contain more than one
+ * IE. This event is required in
+ * Managed mode if the driver
+ * generates its own WPA/RSN IE. This
+ * should be sent just before
+ * IWEVREGISTERED event for the
+ * association. */
+#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association
+ * Response. The data includes id and
+ * length fields and may contain more
+ * than one IE. This may be sent
+ * between IWEVASSOCREQIE and
+ * IWEVREGISTERED events for the
+ * association. */
+#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN
+ * pre-authentication
+ * (struct iw_pmkid_cand) */
+
+#define IWEVFIRST 0x8C00
+#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST)
+
+/* ------------------------- PRIVATE INFO ------------------------- */
+/*
+ * The following is used with SIOCGIWPRIV. It allow a driver to define
+ * the interface (name, type of data) for its private ioctl.
+ * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV
+ */
+
+#define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */
+#define IW_PRIV_TYPE_NONE 0x0000
+#define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */
+#define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */
+#define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */
+#define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */
+#define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */
+
+#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */
+
+#define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */
+
+/*
+ * Note : if the number of args is fixed and the size < 16 octets,
+ * instead of passing a pointer we will put args in the iwreq struct...
+ */
+
+/* ----------------------- OTHER CONSTANTS ----------------------- */
+
+/* Maximum frequencies in the range struct */
+#define IW_MAX_FREQUENCIES 32
+/* Note : if you have something like 80 frequencies,
+ * don't increase this constant and don't fill the frequency list.
+ * The user will be able to set by channel anyway... */
+
+/* Maximum bit rates in the range struct */
+#define IW_MAX_BITRATES 32
+
+/* Maximum tx powers in the range struct */
+#define IW_MAX_TXPOWER 8
+/* Note : if you more than 8 TXPowers, just set the max and min or
+ * a few of them in the struct iw_range. */
+
+/* Maximum of address that you may set with SPY */
+#define IW_MAX_SPY 8
+
+/* Maximum of address that you may get in the
+ list of access points in range */
+#define IW_MAX_AP 64
+
+/* Maximum size of the ESSID and NICKN strings */
+#define IW_ESSID_MAX_SIZE 32
+
+/* Modes of operation */
+#define IW_MODE_AUTO 0 /* Let the driver decides */
+#define IW_MODE_ADHOC 1 /* Single cell network */
+#define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */
+#define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */
+#define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */
+#define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */
+#define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */
+
+/* Statistics flags (bitmask in 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_ALL_UPDATED 0x07
+#define IW_QUAL_DBM 0x08 /* Level + Noise are dBm */
+#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */
+#define IW_QUAL_LEVEL_INVALID 0x20
+#define IW_QUAL_NOISE_INVALID 0x40
+#define IW_QUAL_RCPI 0x80 /* Level + Noise are 802.11k RCPI */
+#define IW_QUAL_ALL_INVALID 0x70
+
+/* Frequency flags */
+#define IW_FREQ_AUTO 0x00 /* Let the driver decides */
+#define IW_FREQ_FIXED 0x01 /* Force a specific value */
+
+/* Maximum number of size of encoding token available
+ * they are listed in the range structure */
+#define IW_MAX_ENCODING_SIZES 8
+
+/* Maximum size of the encoding token in bytes */
+#define IW_ENCODING_TOKEN_MAX 64 /* 512 bits (for now) */
+
+/* Flags for encoding (along with the token) */
+#define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */
+#define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */
+#define IW_ENCODE_MODE 0xF000 /* Modes defined below */
+#define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */
+#define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */
+#define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */
+#define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */
+#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */
+#define IW_ENCODE_TEMP 0x0400 /* Temporary key */
+
+/* Power management flags available (along with the value, if any) */
+#define IW_POWER_ON 0x0000 /* No details... */
+#define IW_POWER_TYPE 0xF000 /* Type of parameter */
+#define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */
+#define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */
+#define IW_POWER_SAVING 0x4000 /* Value is relative (how aggressive)*/
+#define IW_POWER_MODE 0x0F00 /* Power Management mode */
+#define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */
+#define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */
+#define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */
+#define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */
+#define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */
+#define IW_POWER_MODIFIER 0x000F /* Modify a parameter */
+#define IW_POWER_MIN 0x0001 /* Value is a minimum */
+#define IW_POWER_MAX 0x0002 /* Value is a maximum */
+#define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
+
+/* Transmit Power flags available */
+#define IW_TXPOW_TYPE 0x00FF /* Type of value */
+#define IW_TXPOW_DBM 0x0000 /* Value is in dBm */
+#define IW_TXPOW_MWATT 0x0001 /* Value is in mW */
+#define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */
+#define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */
+
+/* Retry limits and lifetime flags available */
+#define IW_RETRY_ON 0x0000 /* No details... */
+#define IW_RETRY_TYPE 0xF000 /* Type of parameter */
+#define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/
+#define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */
+#define IW_RETRY_MODIFIER 0x00FF /* Modify a parameter */
+#define IW_RETRY_MIN 0x0001 /* Value is a minimum */
+#define IW_RETRY_MAX 0x0002 /* Value is a maximum */
+#define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
+#define IW_RETRY_SHORT 0x0010 /* Value is for short packets */
+#define IW_RETRY_LONG 0x0020 /* Value is for long packets */
+
+/* Scanning request flags */
+#define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */
+#define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */
+#define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */
+#define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */
+#define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */
+#define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */
+#define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */
+#define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */
+#define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */
+/* struct iw_scan_req scan_type */
+#define IW_SCAN_TYPE_ACTIVE 0
+#define IW_SCAN_TYPE_PASSIVE 1
+/* Maximum size of returned data */
+#define IW_SCAN_MAX_DATA 4096 /* In bytes */
+
+/* Max number of char in custom event - use multiple of them if needed */
+#define IW_CUSTOM_MAX 256 /* In bytes */
+
+/* Generic information element */
+#define IW_GENERIC_IE_MAX 1024
+
+/* MLME requests (SIOCSIWMLME / struct iw_mlme) */
+#define IW_MLME_DEAUTH 0
+#define IW_MLME_DISASSOC 1
+#define IW_MLME_AUTH 2
+#define IW_MLME_ASSOC 3
+
+/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */
+#define IW_AUTH_INDEX 0x0FFF
+#define IW_AUTH_FLAGS 0xF000
+/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095)
+ * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the
+ * parameter that is being set/get to; value will be read/written to
+ * struct iw_param value field) */
+#define IW_AUTH_WPA_VERSION 0
+#define IW_AUTH_CIPHER_PAIRWISE 1
+#define IW_AUTH_CIPHER_GROUP 2
+#define IW_AUTH_KEY_MGMT 3
+#define IW_AUTH_TKIP_COUNTERMEASURES 4
+#define IW_AUTH_DROP_UNENCRYPTED 5
+#define IW_AUTH_80211_AUTH_ALG 6
+#define IW_AUTH_WPA_ENABLED 7
+#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8
+#define IW_AUTH_ROAMING_CONTROL 9
+#define IW_AUTH_PRIVACY_INVOKED 10
+
+/* IW_AUTH_WPA_VERSION values (bit field) */
+#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001
+#define IW_AUTH_WPA_VERSION_WPA 0x00000002
+#define IW_AUTH_WPA_VERSION_WPA2 0x00000004
+
+/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */
+#define IW_AUTH_CIPHER_NONE 0x00000001
+#define IW_AUTH_CIPHER_WEP40 0x00000002
+#define IW_AUTH_CIPHER_TKIP 0x00000004
+#define IW_AUTH_CIPHER_CCMP 0x00000008
+#define IW_AUTH_CIPHER_WEP104 0x00000010
+
+/* IW_AUTH_KEY_MGMT values (bit field) */
+#define IW_AUTH_KEY_MGMT_802_1X 1
+#define IW_AUTH_KEY_MGMT_PSK 2
+
+/* IW_AUTH_80211_AUTH_ALG values (bit field) */
+#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001
+#define IW_AUTH_ALG_SHARED_KEY 0x00000002
+#define IW_AUTH_ALG_LEAP 0x00000004
+
+/* IW_AUTH_ROAMING_CONTROL values */
+#define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */
+#define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming
+ * control */
+
+/* SIOCSIWENCODEEXT definitions */
+#define IW_ENCODE_SEQ_MAX_SIZE 8
+/* struct iw_encode_ext ->alg */
+#define IW_ENCODE_ALG_NONE 0
+#define IW_ENCODE_ALG_WEP 1
+#define IW_ENCODE_ALG_TKIP 2
+#define IW_ENCODE_ALG_CCMP 3
+/* struct iw_encode_ext ->ext_flags */
+#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001
+#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002
+#define IW_ENCODE_EXT_GROUP_KEY 0x00000004
+#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008
+
+/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */
+#define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */
+#define IW_MICFAILURE_GROUP 0x00000004
+#define IW_MICFAILURE_PAIRWISE 0x00000008
+#define IW_MICFAILURE_STAKEY 0x00000010
+#define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported)
+ */
+
+/* Bit field values for enc_capa in struct iw_range */
+#define IW_ENC_CAPA_WPA 0x00000001
+#define IW_ENC_CAPA_WPA2 0x00000002
+#define IW_ENC_CAPA_CIPHER_TKIP 0x00000004
+#define IW_ENC_CAPA_CIPHER_CCMP 0x00000008
+
+/* Event capability macros - in (struct iw_range *)->event_capa
+ * Because we have more than 32 possible events, we use an array of
+ * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */
+#define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \
+ (cmd - SIOCIWFIRSTPRIV + 0x60) : \
+ (cmd - SIOCSIWCOMMIT))
+#define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5)
+#define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F))
+/* Event capability constants - event autogenerated by the kernel
+ * This list is valid for most 802.11 devices, customise as needed... */
+#define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \
+ IW_EVENT_CAPA_MASK(0x8B06) | \
+ IW_EVENT_CAPA_MASK(0x8B1A))
+#define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A))
+/* "Easy" macro to set events in iw_range (less efficient) */
+#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd))
+#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; }
+
+/* Modulations bitmasks */
+#define IW_MODUL_ALL 0x00000000 /* Everything supported */
+#define IW_MODUL_FH 0x00000001 /* Frequency Hopping */
+#define IW_MODUL_DS 0x00000002 /* Original Direct Sequence */
+#define IW_MODUL_CCK 0x00000004 /* 802.11b : 5.5 + 11 Mb/s */
+#define IW_MODUL_11B (IW_MODUL_DS | IW_MODUL_CCK)
+#define IW_MODUL_PBCC 0x00000008 /* TI : 5.5 + 11 + 22 Mb/s */
+#define IW_MODUL_OFDM_A 0x00000010 /* 802.11a : 54 Mb/s */
+#define IW_MODUL_11A (IW_MODUL_OFDM_A)
+#define IW_MODUL_11AB (IW_MODUL_11B | IW_MODUL_11A)
+#define IW_MODUL_OFDM_G 0x00000020 /* 802.11g : 54 Mb/s */
+#define IW_MODUL_11G (IW_MODUL_11B | IW_MODUL_OFDM_G)
+#define IW_MODUL_11AG (IW_MODUL_11G | IW_MODUL_11A)
+#define IW_MODUL_TURBO 0x00000040 /* ATH : bonding, 108 Mb/s */
+/* In here we should define MIMO stuff. Later... */
+#define IW_MODUL_CUSTOM 0x40000000 /* Driver specific */
+
+/* Bitrate flags available */
+#define IW_BITRATE_TYPE 0x00FF /* Type of value */
+#define IW_BITRATE_UNICAST 0x0001 /* Maximum/Fixed unicast bitrate */
+#define IW_BITRATE_BROADCAST 0x0002 /* Fixed broadcast bitrate */
+
+/****************************** TYPES ******************************/
+
+/* --------------------------- SUBTYPES --------------------------- */
+/*
+ * Generic format for most parameters that fit in an int
+ */
+struct iw_param
+{
+ int32_t value; /* The value of the parameter itself */
+ uint8_t fixed; /* Hardware should not use auto select */
+ uint8_t disabled; /* Disable the feature */
+ uint16_t flags; /* Various specifc flags (if any) */
+};
+
+/*
+ * For all data larger than 16 octets, we need to use a
+ * pointer to memory allocated in user space.
+ */
+struct iw_point
+{
+ void *pointer; /* Pointer to the data (in user space) */
+ uint16_t length; /* number of fields or size in bytes */
+ uint16_t flags; /* Optional params */
+};
+
+/*
+ * A frequency
+ * For numbers lower than 10^9, we encode the number in 'm' and
+ * set 'e' to 0
+ * For number greater than 10^9, we divide it by the lowest power
+ * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')...
+ * The power of 10 is in 'e', the result of the division is in 'm'.
+ */
+struct iw_freq
+{
+ int32_t m; /* Mantissa */
+ int16_t e; /* Exponent */
+ uint8_t i; /* List index (when in range struct) */
+ uint8_t flags; /* Flags (fixed/auto) */
+};
+
+/*
+ * Quality of the link
+ */
+struct iw_quality
+{
+ uint8_t qual; /* link quality (%retries, SNR,
+ %missed beacons or better...) */
+ uint8_t level; /* signal level (dBm) */
+ uint8_t noise; /* noise level (dBm) */
+ uint8_t updated; /* Flags to know if updated */
+};
+
+/*
+ * Packet discarded in the wireless adapter due to
+ * "wireless" specific problems...
+ * Note : the list of counter and statistics in net_device_stats
+ * is already pretty exhaustive, and you should use that first.
+ * This is only additional stats...
+ */
+struct iw_discarded
+{
+ uint32_t nwid; /* Rx : Wrong nwid/essid */
+ uint32_t code; /* Rx : Unable to code/decode (WEP) */
+ uint32_t fragment; /* Rx : Can't perform MAC reassembly */
+ uint32_t retries; /* Tx : Max MAC retries num reached */
+ uint32_t misc; /* Others cases */
+};
+
+/*
+ * Packet/Time period missed in the wireless adapter due to
+ * "wireless" specific problems...
+ */
+struct iw_missed
+{
+ uint32_t beacon; /* Missed beacons/superframe */
+};
+
+/*
+ * Quality range (for spy threshold)
+ */
+struct iw_thrspy
+{
+ struct sockaddr addr; /* Source address (hw/mac) */
+ struct iw_quality qual; /* Quality of the link */
+ struct iw_quality low; /* Low threshold */
+ struct iw_quality high; /* High threshold */
+};
+
+/*
+ * Optional data for scan request
+ *
+ * Note: these optional parameters are controlling parameters for the
+ * scanning behavior, these do not apply to getting scan results
+ * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and
+ * provide a merged results with all BSSes even if the previous scan
+ * request limited scanning to a subset, e.g., by specifying an SSID.
+ * Especially, scan results are required to include an entry for the
+ * current BSS if the driver is in Managed mode and associated with an AP.
+ */
+struct iw_scan_req
+{
+ uint8_t scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */
+ uint8_t essid_len;
+ uint8_t num_channels; /* num entries in channel_list;
+ * 0 = scan all allowed channels */
+ uint8_t flags; /* reserved as padding; use zero, this may
+ * be used in the future for adding flags
+ * to request different scan behavior */
+ struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or
+ * individual address of a specific BSS */
+
+ /*
+ * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using
+ * the current ESSID. This allows scan requests for specific ESSID
+ * without having to change the current ESSID and potentially breaking
+ * the current association.
+ */
+ uint8_t essid[IW_ESSID_MAX_SIZE];
+
+ /*
+ * Optional parameters for changing the default scanning behavior.
+ * These are based on the MLME-SCAN.request from IEEE Std 802.11.
+ * TU is 1.024 ms. If these are set to 0, driver is expected to use
+ * reasonable default values. min_channel_time defines the time that
+ * will be used to wait for the first reply on each channel. If no
+ * replies are received, next channel will be scanned after this. If
+ * replies are received, total time waited on the channel is defined by
+ * max_channel_time.
+ */
+ uint32_t min_channel_time; /* in TU */
+ uint32_t max_channel_time; /* in TU */
+
+ struct iw_freq channel_list[IW_MAX_FREQUENCIES];
+};
+
+/* ------------------------- WPA SUPPORT ------------------------- */
+
+/*
+ * Extended data structure for get/set encoding (this is used with
+ * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_*
+ * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and
+ * only the data contents changes (key data -> this structure, including
+ * key data).
+ *
+ * If the new key is the first group key, it will be set as the default
+ * TX key. Otherwise, default TX key index is only changed if
+ * IW_ENCODE_EXT_SET_TX_KEY flag is set.
+ *
+ * Key will be changed with SIOCSIWENCODEEXT in all cases except for
+ * special "change TX key index" operation which is indicated by setting
+ * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY.
+ *
+ * tx_seq/rx_seq are only used when respective
+ * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal
+ * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start
+ * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally
+ * used only by an Authenticator (AP or an IBSS station) to get the
+ * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and
+ * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for
+ * debugging/testing.
+ */
+struct iw_encode_ext
+{
+ uint32_t ext_flags; /* IW_ENCODE_EXT_* */
+ uint8_t tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+ uint8_t rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+ struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast
+ * (group) keys or unicast address for
+ * individual keys */
+ uint16_t alg; /* IW_ENCODE_ALG_* */
+ uint16_t key_len;
+ uint8_t key[1];
+};
+
+/* SIOCSIWMLME data */
+struct iw_mlme
+{
+ uint16_t cmd; /* IW_MLME_* */
+ uint16_t reason_code;
+ struct sockaddr addr;
+};
+
+/* SIOCSIWPMKSA data */
+#define IW_PMKSA_ADD 1
+#define IW_PMKSA_REMOVE 2
+#define IW_PMKSA_FLUSH 3
+
+#define IW_PMKID_LEN 16
+
+struct iw_pmksa
+{
+ uint32_t cmd; /* IW_PMKSA_* */
+ struct sockaddr bssid;
+ uint8_t pmkid[IW_PMKID_LEN];
+};
+
+/* IWEVMICHAELMICFAILURE data */
+struct iw_michaelmicfailure
+{
+ uint32_t flags;
+ struct sockaddr src_addr;
+ uint8_t tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+};
+
+/* IWEVPMKIDCAND data */
+#define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */
+struct iw_pmkid_cand
+{
+ uint32_t flags; /* IW_PMKID_CAND_* */
+ uint32_t index; /* the smaller the index, the higher the
+ * priority */
+ struct sockaddr bssid;
+};
+
+/* ------------------------ WIRELESS STATS ------------------------ */
+/*
+ * Wireless statistics (used for /proc/net/wireless)
+ */
+struct iw_statistics
+{
+ uint16_t status; /* Status
+ * - device dependent for now */
+
+ struct iw_quality qual; /* Quality of the link
+ * (instant/mean/max) */
+ struct iw_discarded discard; /* Packet discarded counts */
+ struct iw_missed miss; /* Packet missed counts */
+};
+
+/* ------------------------ IOCTL REQUEST ------------------------ */
+/*
+ * This structure defines the payload of an ioctl, and is used
+ * below.
+ *
+ * Note that this structure should fit on the memory footprint
+ * of iwreq (which is the same as ifreq), which mean a max size of
+ * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
+ * You should check this when increasing the structures defined
+ * above in this file...
+ */
+union iwreq_data
+{
+ /* Config - generic */
+ char name[16];
+ /* Name : used to verify the presence of wireless extensions.
+ * Name of the protocol/provider... */
+
+ struct iw_point essid; /* Extended network name */
+ struct iw_param nwid; /* network id (or domain - the cell) */
+ struct iw_freq freq; /* frequency or channel :
+ * 0-1000 = channel
+ * > 1000 = frequency in Hz */
+
+ struct iw_param sens; /* signal level threshold */
+ struct iw_param bitrate; /* default bit rate */
+ struct iw_param txpower; /* default transmit power */
+ struct iw_param rts; /* RTS threshold threshold */
+ struct iw_param frag; /* Fragmentation threshold */
+ uint32_t mode; /* Operation mode */
+ struct iw_param retry; /* Retry limits & lifetime */
+
+ struct iw_point encoding; /* Encoding stuff : tokens */
+ struct iw_param power; /* PM duration/timeout */
+ struct iw_quality qual; /* Quality part of statistics */
+
+ struct sockaddr ap_addr; /* Access point address */
+ struct sockaddr addr; /* Destination address (hw/mac) */
+
+ struct iw_param param; /* Other small parameters */
+ struct iw_point data; /* Other large parameters */
+};
+
+/*
+ * The structure to exchange data for ioctl.
+ * This structure is the same as 'struct ifreq', but (re)defined for
+ * convenience...
+ * Do I need to remind you about structure size (32 octets) ?
+ */
+struct iwreq
+{
+ union
+ {
+ char ifrn_name[16]; /* if name, e.g. "eth0" */
+ } ifr_ifrn;
+
+ /* Data part (defined just above) */
+ union iwreq_data u;
+};
+
+/* -------------------------- IOCTL DATA -------------------------- */
+/*
+ * For those ioctl which want to exchange mode data that what could
+ * fit in the above structure...
+ */
+
+/*
+ * Range of parameters
+ */
+
+struct iw_range
+{
+ /* Informative stuff (to choose between different interface) */
+ uint32_t throughput; /* To give an idea... */
+ /* In theory this value should be the maximum benchmarked
+ * TCP/IP throughput, because with most of these devices the
+ * bit rate is meaningless (overhead an co) to estimate how
+ * fast the connection will go and pick the fastest one.
+ * I suggest people to play with Netperf or any benchmark...
+ */
+
+ /* NWID (or domain id) */
+ uint32_t min_nwid; /* Minimal NWID we are able to set */
+ uint32_t max_nwid; /* Maximal NWID we are able to set */
+
+ /* Old Frequency (backward compat - moved lower ) */
+ uint16_t old_num_channels;
+ uint8_t old_num_frequency;
+
+ /* Wireless event capability bitmasks */
+ uint32_t event_capa[6];
+
+ /* signal level threshold range */
+ int32_t sensitivity;
+
+ /* Quality of link & SNR stuff */
+ /* Quality range (link, level, noise)
+ * If the quality is absolute, it will be in the range [0 ; max_qual],
+ * if the quality is dBm, it will be in the range [max_qual ; 0].
+ * Don't forget that we use 8 bit arithmetics... */
+ struct iw_quality max_qual; /* Quality of the link */
+ /* This should contain the average/typical values of the quality
+ * indicator. This should be the threshold between a "good" and
+ * a "bad" link (example : monitor going from green to orange).
+ * Currently, user space apps like quality monitors don't have any
+ * way to calibrate the measurement. With this, they can split
+ * the range between 0 and max_qual in different quality level
+ * (using a geometric subdivision centered on the average).
+ * I expect that people doing the user space apps will feedback
+ * us on which value we need to put in each driver... */
+ struct iw_quality avg_qual; /* Quality of the link */
+
+ /* Rates */
+ uint8_t num_bitrates; /* Number of entries in the list */
+ int32_t bitrate[IW_MAX_BITRATES]; /* list, in bps */
+
+ /* RTS threshold */
+ int32_t min_rts; /* Minimal RTS threshold */
+ int32_t max_rts; /* Maximal RTS threshold */
+
+ /* Frag threshold */
+ int32_t min_frag; /* Minimal frag threshold */
+ int32_t max_frag; /* Maximal frag threshold */
+
+ /* Power Management duration & timeout */
+ int32_t min_pmp; /* Minimal PM period */
+ int32_t max_pmp; /* Maximal PM period */
+ int32_t min_pmt; /* Minimal PM timeout */
+ int32_t max_pmt; /* Maximal PM timeout */
+ uint16_t pmp_flags; /* How to decode max/min PM period */
+ uint16_t pmt_flags; /* How to decode max/min PM timeout */
+ uint16_t pm_capa; /* What PM options are supported */
+
+ /* Encoder stuff */
+ uint16_t encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */
+ uint8_t num_encoding_sizes; /* Number of entry in the list */
+ uint8_t max_encoding_tokens; /* Max number of tokens */
+ /* For drivers that need a "login/passwd" form */
+ uint8_t encoding_login_index; /* token index for login token */
+
+ /* Transmit power */
+ uint16_t txpower_capa; /* What options are supported */
+ uint8_t num_txpower; /* Number of entries in the list */
+ int32_t txpower[IW_MAX_TXPOWER]; /* list, in bps */
+
+ /* Wireless Extension version info */
+ uint8_t we_version_compiled; /* Must be WIRELESS_EXT */
+ uint8_t we_version_source; /* Last update of source */
+
+ /* Retry limits and lifetime */
+ uint16_t retry_capa; /* What retry options are supported */
+ uint16_t retry_flags; /* How to decode max/min retry limit */
+ uint16_t r_time_flags; /* How to decode max/min retry life */
+ int32_t min_retry; /* Minimal number of retries */
+ int32_t max_retry; /* Maximal number of retries */
+ int32_t min_r_time; /* Minimal retry lifetime */
+ int32_t max_r_time; /* Maximal retry lifetime */
+
+ /* Frequency */
+ uint16_t num_channels; /* Number of channels [0; num - 1] */
+ uint8_t num_frequency; /* Number of entry in the list */
+ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
+ /* Note : this frequency list doesn't need to fit channel numbers,
+ * because each entry contain its channel index */
+
+ uint32_t enc_capa; /* IW_ENC_CAPA_* bit field */
+
+ /* More power management stuff */
+ int32_t min_pms; /* Minimal PM saving */
+ int32_t max_pms; /* Maximal PM saving */
+ uint16_t pms_flags; /* How to decode max/min PM saving */
+
+ /* All available modulations for driver (hw may support less) */
+ int32_t modul_capa; /* IW_MODUL_* bit field */
+
+ /* More bitrate stuff */
+ uint32_t bitrate_capa; /* Types of bitrates supported */
+};
+
+/*
+ * Private ioctl interface information
+ */
+
+struct iw_priv_args
+{
+ uint32_t cmd; /* Number of the ioctl to issue */
+ uint16_t set_args; /* Type and number of args */
+ uint16_t get_args; /* Type and number of args */
+ char name[16]; /* Name of the extension */
+};
+
+/* ----------------------- WIRELESS EVENTS ----------------------- */
+/*
+ * Wireless events are carried through the rtnetlink socket to user
+ * space. They are encapsulated in the IFLA_WIRELESS field of
+ * a RTM_NEWLINK message.
+ */
+
+/*
+ * A Wireless Event. Contains basically the same data as the ioctl...
+ */
+struct iw_event
+{
+ uint16_t len; /* Real lenght of this stuff */
+ uint16_t cmd; /* Wireless IOCTL */
+ union iwreq_data u; /* IOCTL fixed payload */
+};
+
+/* Size of the Event prefix (including padding and alignement junk) */
+#define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data))
+/* Size of the various events */
+#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ)
+#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(uint32_t))
+#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq))
+#define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param))
+#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr))
+#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality))
+
+/* iw_point events are special. First, the payload (extra data) come at
+ * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second,
+ * we omit the pointer, so start at an offset. */
+#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \
+ (char *) NULL)
+#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \
+ IW_EV_POINT_OFF)
+
+/* Size of the Event prefix when packed in stream */
+#define IW_EV_LCP_PK_LEN (4)
+/* Size of the various events when packed in stream */
+#define IW_EV_CHAR_PK_LEN (IW_EV_LCP_PK_LEN + IFNAMSIZ)
+#define IW_EV_UINT_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(uint32_t))
+#define IW_EV_FREQ_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_freq))
+#define IW_EV_PARAM_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_param))
+#define IW_EV_ADDR_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct sockaddr))
+#define IW_EV_QUAL_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_quality))
+#define IW_EV_POINT_PK_LEN (IW_EV_LCP_PK_LEN + 4)
+
+#endif /* _LINUX_WIRELESS_H */
diff --git a/package/iwinfo/src/include/iwinfo/lua.h b/package/iwinfo/src/include/iwinfo/lua.h
new file mode 100644
index 000000000..d976c0cf4
--- /dev/null
+++ b/package/iwinfo/src/include/iwinfo/lua.h
@@ -0,0 +1,80 @@
+/*
+ * iwinfo - Wireless Information Library - Lua Headers
+ *
+ * Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * The iwinfo library 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.
+ *
+ * The iwinfo library 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 the iwinfo library. If not, see http://www.gnu.org/licenses/.
+ */
+
+#ifndef __IWINFO_LUALUB_H_
+#define __IWINFO_LUALIB_H_
+
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+
+#include "iwinfo.h"
+#include "iwinfo/wext_scan.h"
+
+
+#define IWINFO_META "iwinfo"
+#define IWINFO_WEXT_META "iwinfo.wext"
+
+#ifdef USE_WL
+#define IWINFO_WL_META "iwinfo.wl"
+#endif
+
+#ifdef USE_MADWIFI
+#define IWINFO_MADWIFI_META "iwinfo.madwifi"
+#endif
+
+#ifdef USE_NL80211
+#define IWINFO_NL80211_META "iwinfo.nl80211"
+#endif
+
+
+#define LUA_REG(type,op) \
+ { #op, iwinfo_L_##type##_##op }
+
+#define LUA_WRAP_INT(type,op) \
+ static int iwinfo_L_##type##_##op(lua_State *L) \
+ { \
+ const char *ifname = luaL_checkstring(L, 1); \
+ int rv; \
+ if( !type##_get_##op(ifname, &rv) ) \
+ lua_pushnumber(L, rv); \
+ else \
+ lua_pushnil(L); \
+ return 1; \
+ }
+
+#define LUA_WRAP_STRING(type,op) \
+ static int iwinfo_L_##type##_##op(lua_State *L) \
+ { \
+ const char *ifname = luaL_checkstring(L, 1); \
+ char rv[IWINFO_BUFSIZE]; \
+ memset(rv, 0, IWINFO_BUFSIZE); \
+ if( !type##_get_##op(ifname, rv) ) \
+ lua_pushstring(L, rv); \
+ else \
+ lua_pushnil(L); \
+ return 1; \
+ }
+
+#define LUA_WRAP_STRUCT(type,op) \
+ static int iwinfo_L_##type##_##op(lua_State *L) \
+ { \
+ return iwinfo_L_##op(L, type##_get_##op); \
+ }
+
+#endif
diff --git a/package/iwinfo/src/include/iwinfo/madwifi.h b/package/iwinfo/src/include/iwinfo/madwifi.h
new file mode 100644
index 000000000..14d81352b
--- /dev/null
+++ b/package/iwinfo/src/include/iwinfo/madwifi.h
@@ -0,0 +1,83 @@
+/*
+ * iwinfo - Wireless Information Library - Madwifi Headers
+ *
+ * Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * The iwinfo library 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.
+ *
+ * The iwinfo library 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 the iwinfo library. If not, see http://www.gnu.org/licenses/.
+ */
+
+#ifndef __IWINFO_MADWIFI_H_
+#define __IWINFO_MADWIFI_H_
+
+#include <fcntl.h>
+
+#include "iwinfo.h"
+#include "iwinfo/utils.h"
+#include "iwinfo/api/madwifi.h"
+
+int madwifi_probe(const char *ifname);
+int madwifi_get_mode(const char *ifname, int *buf);
+int madwifi_get_ssid(const char *ifname, char *buf);
+int madwifi_get_bssid(const char *ifname, char *buf);
+int madwifi_get_country(const char *ifname, char *buf);
+int madwifi_get_channel(const char *ifname, int *buf);
+int madwifi_get_frequency(const char *ifname, int *buf);
+int madwifi_get_frequency_offset(const char *ifname, int *buf);
+int madwifi_get_txpower(const char *ifname, int *buf);
+int madwifi_get_txpower_offset(const char *ifname, int *buf);
+int madwifi_get_bitrate(const char *ifname, int *buf);
+int madwifi_get_signal(const char *ifname, int *buf);
+int madwifi_get_noise(const char *ifname, int *buf);
+int madwifi_get_quality(const char *ifname, int *buf);
+int madwifi_get_quality_max(const char *ifname, int *buf);
+int madwifi_get_encryption(const char *ifname, char *buf);
+int madwifi_get_assoclist(const char *ifname, char *buf, int *len);
+int madwifi_get_txpwrlist(const char *ifname, char *buf, int *len);
+int madwifi_get_scanlist(const char *ifname, char *buf, int *len);
+int madwifi_get_freqlist(const char *ifname, char *buf, int *len);
+int madwifi_get_countrylist(const char *ifname, char *buf, int *len);
+int madwifi_get_hwmodelist(const char *ifname, int *buf);
+int madwifi_get_mbssid_support(const char *ifname, int *buf);
+int madwifi_get_hardware_id(const char *ifname, char *buf);
+int madwifi_get_hardware_name(const char *ifname, char *buf);
+void madwifi_close(void);
+
+static const struct iwinfo_ops madwifi_ops = {
+ .channel = madwifi_get_channel,
+ .frequency = madwifi_get_frequency,
+ .frequency_offset = madwifi_get_frequency_offset,
+ .txpower = madwifi_get_txpower,
+ .txpower_offset = madwifi_get_txpower_offset,
+ .bitrate = madwifi_get_bitrate,
+ .signal = madwifi_get_signal,
+ .noise = madwifi_get_noise,
+ .quality = madwifi_get_quality,
+ .quality_max = madwifi_get_quality_max,
+ .mbssid_support = madwifi_get_mbssid_support,
+ .hwmodelist = madwifi_get_hwmodelist,
+ .mode = madwifi_get_mode,
+ .ssid = madwifi_get_ssid,
+ .bssid = madwifi_get_bssid,
+ .country = madwifi_get_country,
+ .hardware_id = madwifi_get_hardware_id,
+ .hardware_name = madwifi_get_hardware_name,
+ .encryption = madwifi_get_encryption,
+ .assoclist = madwifi_get_assoclist,
+ .txpwrlist = madwifi_get_txpwrlist,
+ .scanlist = madwifi_get_scanlist,
+ .freqlist = madwifi_get_freqlist,
+ .countrylist = madwifi_get_countrylist,
+ .close = madwifi_close
+};
+
+#endif
diff --git a/package/iwinfo/src/include/iwinfo/nl80211.h b/package/iwinfo/src/include/iwinfo/nl80211.h
new file mode 100644
index 000000000..28545141d
--- /dev/null
+++ b/package/iwinfo/src/include/iwinfo/nl80211.h
@@ -0,0 +1,125 @@
+/*
+ * iwinfo - Wireless Information Library - NL80211 Headers
+ *
+ * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * The iwinfo library 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.
+ *
+ * The iwinfo library 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 the iwinfo library. If not, see http://www.gnu.org/licenses/.
+ */
+
+#ifndef __IWINFO_NL80211_H_
+#define __IWINFO_NL80211_H_
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <dirent.h>
+#include <signal.h>
+#include <sys/un.h>
+#include <netlink/netlink.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+
+#include "iwinfo.h"
+#include "iwinfo/utils.h"
+#include "iwinfo/api/nl80211.h"
+
+struct nl80211_state {
+ struct nl_sock *nl_sock;
+ struct nl_cache *nl_cache;
+ struct genl_family *nl80211;
+ struct genl_family *nlctrl;
+};
+
+struct nl80211_msg_conveyor {
+ struct nl_msg *msg;
+ struct nl_cb *cb;
+};
+
+struct nl80211_event_conveyor {
+ int wait;
+ int recv;
+};
+
+struct nl80211_group_conveyor {
+ const char *name;
+ int id;
+};
+
+struct nl80211_rssi_rate {
+ int16_t rate;
+ int8_t rssi;
+};
+
+struct nl80211_array_buf {
+ void *buf;
+ int count;
+};
+
+int nl80211_probe(const char *ifname);
+int nl80211_get_mode(const char *ifname, int *buf);
+int nl80211_get_ssid(const char *ifname, char *buf);
+int nl80211_get_bssid(const char *ifname, char *buf);
+int nl80211_get_country(const char *ifname, char *buf);
+int nl80211_get_channel(const char *ifname, int *buf);
+int nl80211_get_frequency(const char *ifname, int *buf);
+int nl80211_get_frequency_offset(const char *ifname, int *buf);
+int nl80211_get_txpower(const char *ifname, int *buf);
+int nl80211_get_txpower_offset(const char *ifname, int *buf);
+int nl80211_get_bitrate(const char *ifname, int *buf);
+int nl80211_get_signal(const char *ifname, int *buf);
+int nl80211_get_noise(const char *ifname, int *buf);
+int nl80211_get_quality(const char *ifname, int *buf);
+int nl80211_get_quality_max(const char *ifname, int *buf);
+int nl80211_get_encryption(const char *ifname, char *buf);
+int nl80211_get_assoclist(const char *ifname, char *buf, int *len);
+int nl80211_get_txpwrlist(const char *ifname, char *buf, int *len);
+int nl80211_get_scanlist(const char *ifname, char *buf, int *len);
+int nl80211_get_freqlist(const char *ifname, char *buf, int *len);
+int nl80211_get_countrylist(const char *ifname, char *buf, int *len);
+int nl80211_get_hwmodelist(const char *ifname, int *buf);
+int nl80211_get_mbssid_support(const char *ifname, int *buf);
+int nl80211_get_hardware_id(const char *ifname, char *buf);
+int nl80211_get_hardware_name(const char *ifname, char *buf);
+void nl80211_close(void);
+
+static const struct iwinfo_ops nl80211_ops = {
+ .channel = nl80211_get_channel,
+ .frequency = nl80211_get_frequency,
+ .frequency_offset = nl80211_get_frequency_offset,
+ .txpower = nl80211_get_txpower,
+ .txpower_offset = nl80211_get_txpower_offset,
+ .bitrate = nl80211_get_bitrate,
+ .signal = nl80211_get_signal,
+ .noise = nl80211_get_noise,
+ .quality = nl80211_get_quality,
+ .quality_max = nl80211_get_quality_max,
+ .mbssid_support = nl80211_get_mbssid_support,
+ .hwmodelist = nl80211_get_hwmodelist,
+ .mode = nl80211_get_mode,
+ .ssid = nl80211_get_ssid,
+ .bssid = nl80211_get_bssid,
+ .country = nl80211_get_country,
+ .hardware_id = nl80211_get_hardware_id,
+ .hardware_name = nl80211_get_hardware_name,
+ .encryption = nl80211_get_encryption,
+ .assoclist = nl80211_get_assoclist,
+ .txpwrlist = nl80211_get_txpwrlist,
+ .scanlist = nl80211_get_scanlist,
+ .freqlist = nl80211_get_freqlist,
+ .countrylist = nl80211_get_countrylist,
+ .close = nl80211_close
+};
+
+#endif
diff --git a/package/iwinfo/src/include/iwinfo/utils.h b/package/iwinfo/src/include/iwinfo/utils.h
new file mode 100644
index 000000000..d58ec5fb7
--- /dev/null
+++ b/package/iwinfo/src/include/iwinfo/utils.h
@@ -0,0 +1,47 @@
+/*
+ * iwinfo - Wireless Information Library - Utility Headers
+ *
+ * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * The iwinfo library 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.
+ *
+ * The iwinfo library 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 the iwinfo library. If not, see http://www.gnu.org/licenses/.
+ */
+
+#ifndef __IWINFO_UTILS_H_
+#define __IWINFO_UTILS_H_
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include "iwinfo.h"
+
+#define LOG10_MAGIC 1.25892541179
+
+int iwinfo_ioctl(int cmd, void *ifr);
+
+int iwinfo_dbm2mw(int in);
+int iwinfo_mw2dbm(int in);
+
+int iwinfo_ifup(const char *ifname);
+int iwinfo_ifdown(const char *ifname);
+int iwinfo_ifmac(const char *ifname);
+
+void iwinfo_close(void);
+
+struct iwinfo_hardware_entry * iwinfo_hardware(struct iwinfo_hardware_id *id);
+
+int iwinfo_hardware_id_from_mtd(struct iwinfo_hardware_id *id);
+
+void iwinfo_parse_rsn(struct iwinfo_crypto_entry *c, uint8_t *data, uint8_t len,
+ uint8_t defcipher, uint8_t defauth);
+
+#endif
diff --git a/package/iwinfo/src/include/iwinfo/wext.h b/package/iwinfo/src/include/iwinfo/wext.h
new file mode 100644
index 000000000..68b596ea8
--- /dev/null
+++ b/package/iwinfo/src/include/iwinfo/wext.h
@@ -0,0 +1,84 @@
+/*
+ * iwinfo - Wireless Information Library - Linux Wireless Extension Headers
+ *
+ * Copyright (C) 2009-2010 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * The iwinfo library 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.
+ *
+ * The iwinfo library 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 the iwinfo library. If not, see http://www.gnu.org/licenses/.
+ */
+
+#ifndef __IWINFO_WEXT_H_
+#define __IWINFO_WEXT_H_
+
+#include <fcntl.h>
+
+#include "iwinfo.h"
+#include "iwinfo/utils.h"
+#include "iwinfo/api/wext.h"
+
+
+int wext_probe(const char *ifname);
+int wext_get_mode(const char *ifname, int *buf);
+int wext_get_ssid(const char *ifname, char *buf);
+int wext_get_bssid(const char *ifname, char *buf);
+int wext_get_country(const char *ifname, char *buf);
+int wext_get_channel(const char *ifname, int *buf);
+int wext_get_frequency(const char *ifname, int *buf);
+int wext_get_frequency_offset(const char *ifname, int *buf);
+int wext_get_txpower(const char *ifname, int *buf);
+int wext_get_txpower_offset(const char *ifname, int *buf);
+int wext_get_bitrate(const char *ifname, int *buf);
+int wext_get_signal(const char *ifname, int *buf);
+int wext_get_noise(const char *ifname, int *buf);
+int wext_get_quality(const char *ifname, int *buf);
+int wext_get_quality_max(const char *ifname, int *buf);
+int wext_get_encryption(const char *ifname, char *buf);
+int wext_get_assoclist(const char *ifname, char *buf, int *len);
+int wext_get_txpwrlist(const char *ifname, char *buf, int *len);
+int wext_get_scanlist(const char *ifname, char *buf, int *len);
+int wext_get_freqlist(const char *ifname, char *buf, int *len);
+int wext_get_countrylist(const char *ifname, char *buf, int *len);
+int wext_get_hwmodelist(const char *ifname, int *buf);
+int wext_get_mbssid_support(const char *ifname, int *buf);
+int wext_get_hardware_id(const char *ifname, char *buf);
+int wext_get_hardware_name(const char *ifname, char *buf);
+void wext_close(void);
+
+static const struct iwinfo_ops wext_ops = {
+ .channel = wext_get_channel,
+ .frequency = wext_get_frequency,
+ .frequency_offset = wext_get_frequency_offset,
+ .txpower = wext_get_txpower,
+ .txpower_offset = wext_get_txpower_offset,
+ .bitrate = wext_get_bitrate,
+ .signal = wext_get_signal,
+ .noise = wext_get_noise,
+ .quality = wext_get_quality,
+ .quality_max = wext_get_quality_max,
+ .mbssid_support = wext_get_mbssid_support,
+ .hwmodelist = wext_get_hwmodelist,
+ .mode = wext_get_mode,
+ .ssid = wext_get_ssid,
+ .bssid = wext_get_bssid,
+ .country = wext_get_country,
+ .hardware_id = wext_get_hardware_id,
+ .hardware_name = wext_get_hardware_name,
+ .encryption = wext_get_encryption,
+ .assoclist = wext_get_assoclist,
+ .txpwrlist = wext_get_txpwrlist,
+ .scanlist = wext_get_scanlist,
+ .freqlist = wext_get_freqlist,
+ .countrylist = wext_get_countrylist,
+ .close = wext_close
+};
+
+#endif
diff --git a/package/iwinfo/src/include/iwinfo/wext_scan.h b/package/iwinfo/src/include/iwinfo/wext_scan.h
new file mode 100644
index 000000000..085c65310
--- /dev/null
+++ b/package/iwinfo/src/include/iwinfo/wext_scan.h
@@ -0,0 +1,380 @@
+/*
+ * iwinfo - Wireless Information Library - Linux Wireless Extension Headers
+ *
+ * Copyright (C) 2009-2010 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * The iwinfo library 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.
+ *
+ * The iwinfo library 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 the iwinfo library. If not, see http://www.gnu.org/licenses/.
+ */
+
+#ifndef __IWINFO_WEXT_SCAN_H_
+#define __IWINFO_WEXT_SCAN_H_
+
+#include <fcntl.h>
+
+#include "iwinfo.h"
+#include "iwinfo/utils.h"
+#include "iwinfo/api/wext.h"
+
+
+typedef struct stream_descr
+{
+ char * end; /* End of the stream */
+ char * current; /* Current event in stream of events */
+ char * value; /* Current value in event */
+} stream_descr;
+
+/*
+ * Describe how a standard IOCTL looks like.
+ */
+struct iw_ioctl_description
+{
+ uint8_t header_type; /* NULL, iw_point or other */
+ uint8_t token_type; /* Future */
+ uint16_t token_size; /* Granularity of payload */
+ uint16_t min_tokens; /* Min acceptable token number */
+ uint16_t max_tokens; /* Max acceptable token number */
+ uint32_t flags; /* Special handling of the request */
+};
+
+/* Type of headers we know about (basically union iwreq_data) */
+#define IW_HEADER_TYPE_NULL 0 /* Not available */
+#define IW_HEADER_TYPE_CHAR 2 /* char [IFNAMSIZ] */
+#define IW_HEADER_TYPE_UINT 4 /* __u32 */
+#define IW_HEADER_TYPE_FREQ 5 /* struct iw_freq */
+#define IW_HEADER_TYPE_ADDR 6 /* struct sockaddr */
+#define IW_HEADER_TYPE_POINT 8 /* struct iw_point */
+#define IW_HEADER_TYPE_PARAM 9 /* struct iw_param */
+#define IW_HEADER_TYPE_QUAL 10 /* struct iw_quality */
+
+/* Handling flags */
+/* Most are not implemented. I just use them as a reminder of some
+ * cool features we might need one day ;-) */
+#define IW_DESCR_FLAG_NONE 0x0000 /* Obvious */
+/* Wrapper level flags */
+#define IW_DESCR_FLAG_DUMP 0x0001 /* Not part of the dump command */
+#define IW_DESCR_FLAG_EVENT 0x0002 /* Generate an event on SET */
+#define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET : request is ROOT only */
+ /* SET : Omit payload from generated iwevent */
+#define IW_DESCR_FLAG_NOMAX 0x0008 /* GET : no limit on request size */
+/* Driver level flags */
+#define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */
+
+
+/*
+ * Meta-data about all the standard Wireless Extension request we
+ * know about.
+ */
+static const struct iw_ioctl_description standard_ioctl_descr[] = {
+ [SIOCSIWCOMMIT - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_NULL,
+ },
+ [SIOCGIWNAME - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_CHAR,
+ .flags = IW_DESCR_FLAG_DUMP,
+ },
+ [SIOCSIWNWID - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ .flags = IW_DESCR_FLAG_EVENT,
+ },
+ [SIOCGIWNWID - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ .flags = IW_DESCR_FLAG_DUMP,
+ },
+ [SIOCSIWFREQ - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_FREQ,
+ .flags = IW_DESCR_FLAG_EVENT,
+ },
+ [SIOCGIWFREQ - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_FREQ,
+ .flags = IW_DESCR_FLAG_DUMP,
+ },
+ [SIOCSIWMODE - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_UINT,
+ .flags = IW_DESCR_FLAG_EVENT,
+ },
+ [SIOCGIWMODE - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_UINT,
+ .flags = IW_DESCR_FLAG_DUMP,
+ },
+ [SIOCSIWSENS - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCGIWSENS - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCSIWRANGE - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_NULL,
+ },
+ [SIOCGIWRANGE - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = sizeof(struct iw_range),
+ .flags = IW_DESCR_FLAG_DUMP,
+ },
+ [SIOCSIWPRIV - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_NULL,
+ },
+ [SIOCGIWPRIV - SIOCIWFIRST] = { /* (handled directly by us) */
+ .header_type = IW_HEADER_TYPE_NULL,
+ },
+ [SIOCSIWSTATS - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_NULL,
+ },
+ [SIOCGIWSTATS - SIOCIWFIRST] = { /* (handled directly by us) */
+ .header_type = IW_HEADER_TYPE_NULL,
+ .flags = IW_DESCR_FLAG_DUMP,
+ },
+ [SIOCSIWSPY - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = sizeof(struct sockaddr),
+ .max_tokens = IW_MAX_SPY,
+ },
+ [SIOCGIWSPY - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = sizeof(struct sockaddr) +
+ sizeof(struct iw_quality),
+ .max_tokens = IW_MAX_SPY,
+ },
+ [SIOCSIWTHRSPY - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = sizeof(struct iw_thrspy),
+ .min_tokens = 1,
+ .max_tokens = 1,
+ },
+ [SIOCGIWTHRSPY - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = sizeof(struct iw_thrspy),
+ .min_tokens = 1,
+ .max_tokens = 1,
+ },
+ [SIOCSIWAP - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_ADDR,
+ },
+ [SIOCGIWAP - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_ADDR,
+ .flags = IW_DESCR_FLAG_DUMP,
+ },
+ [SIOCSIWMLME - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .min_tokens = sizeof(struct iw_mlme),
+ .max_tokens = sizeof(struct iw_mlme),
+ },
+ [SIOCGIWAPLIST - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = sizeof(struct sockaddr) +
+ sizeof(struct iw_quality),
+ .max_tokens = IW_MAX_AP,
+ .flags = IW_DESCR_FLAG_NOMAX,
+ },
+ [SIOCSIWSCAN - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .min_tokens = 0,
+ .max_tokens = sizeof(struct iw_scan_req),
+ },
+ [SIOCGIWSCAN - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = IW_SCAN_MAX_DATA,
+ .flags = IW_DESCR_FLAG_NOMAX,
+ },
+ [SIOCSIWESSID - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = IW_ESSID_MAX_SIZE + 1,
+ .flags = IW_DESCR_FLAG_EVENT,
+ },
+ [SIOCGIWESSID - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = IW_ESSID_MAX_SIZE + 1,
+ .flags = IW_DESCR_FLAG_DUMP,
+ },
+ [SIOCSIWNICKN - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = IW_ESSID_MAX_SIZE + 1,
+ },
+ [SIOCGIWNICKN - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = IW_ESSID_MAX_SIZE + 1,
+ },
+ [SIOCSIWRATE - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCGIWRATE - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCSIWRTS - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCGIWRTS - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCSIWFRAG - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCGIWFRAG - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCSIWTXPOW - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCGIWTXPOW - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCSIWRETRY - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCGIWRETRY - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCSIWENCODE - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = IW_ENCODING_TOKEN_MAX,
+ .flags = IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT,
+ },
+ [SIOCGIWENCODE - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = IW_ENCODING_TOKEN_MAX,
+ .flags = IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT,
+ },
+ [SIOCSIWPOWER - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCGIWPOWER - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCSIWMODUL - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCGIWMODUL - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCSIWGENIE - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = IW_GENERIC_IE_MAX,
+ },
+ [SIOCGIWGENIE - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = IW_GENERIC_IE_MAX,
+ },
+ [SIOCSIWAUTH - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCGIWAUTH - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCSIWENCODEEXT - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .min_tokens = sizeof(struct iw_encode_ext),
+ .max_tokens = sizeof(struct iw_encode_ext) +
+ IW_ENCODING_TOKEN_MAX,
+ },
+ [SIOCGIWENCODEEXT - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .min_tokens = sizeof(struct iw_encode_ext),
+ .max_tokens = sizeof(struct iw_encode_ext) +
+ IW_ENCODING_TOKEN_MAX,
+ },
+ [SIOCSIWPMKSA - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .min_tokens = sizeof(struct iw_pmksa),
+ .max_tokens = sizeof(struct iw_pmksa),
+ },
+};
+
+/*
+ * Meta-data about all the additional standard Wireless Extension events
+ * we know about.
+ */
+static const struct iw_ioctl_description standard_event_descr[] = {
+ [IWEVTXDROP - IWEVFIRST] = {
+ .header_type = IW_HEADER_TYPE_ADDR,
+ },
+ [IWEVQUAL - IWEVFIRST] = {
+ .header_type = IW_HEADER_TYPE_QUAL,
+ },
+ [IWEVCUSTOM - IWEVFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = IW_CUSTOM_MAX,
+ },
+ [IWEVREGISTERED - IWEVFIRST] = {
+ .header_type = IW_HEADER_TYPE_ADDR,
+ },
+ [IWEVEXPIRED - IWEVFIRST] = {
+ .header_type = IW_HEADER_TYPE_ADDR,
+ },
+ [IWEVGENIE - IWEVFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = IW_GENERIC_IE_MAX,
+ },
+ [IWEVMICHAELMICFAILURE - IWEVFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = sizeof(struct iw_michaelmicfailure),
+ },
+ [IWEVASSOCREQIE - IWEVFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = IW_GENERIC_IE_MAX,
+ },
+ [IWEVASSOCRESPIE - IWEVFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = IW_GENERIC_IE_MAX,
+ },
+ [IWEVPMKIDCAND - IWEVFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = sizeof(struct iw_pmkid_cand),
+ },
+};
+
+/* Size (in bytes) of various events */
+static const int event_type_size[] = {
+ IW_EV_LCP_PK_LEN, /* IW_HEADER_TYPE_NULL */
+ 0,
+ IW_EV_CHAR_PK_LEN, /* IW_HEADER_TYPE_CHAR */
+ 0,
+ IW_EV_UINT_PK_LEN, /* IW_HEADER_TYPE_UINT */
+ IW_EV_FREQ_PK_LEN, /* IW_HEADER_TYPE_FREQ */
+ IW_EV_ADDR_PK_LEN, /* IW_HEADER_TYPE_ADDR */
+ 0,
+ IW_EV_POINT_PK_LEN, /* Without variable payload */
+ IW_EV_PARAM_PK_LEN, /* IW_HEADER_TYPE_PARAM */
+ IW_EV_QUAL_PK_LEN, /* IW_HEADER_TYPE_QUAL */
+};
+
+
+static const unsigned int standard_ioctl_num =
+ (sizeof(standard_ioctl_descr) / sizeof(struct iw_ioctl_description));
+
+static const unsigned int standard_event_num =
+ (sizeof(standard_event_descr) / sizeof(struct iw_ioctl_description));
+
+#define IW_IE_CYPHER_NUM 8
+#define IW_IE_KEY_MGMT_NUM 3
+
+#endif
diff --git a/package/iwinfo/src/include/iwinfo/wl.h b/package/iwinfo/src/include/iwinfo/wl.h
new file mode 100644
index 000000000..db37e3759
--- /dev/null
+++ b/package/iwinfo/src/include/iwinfo/wl.h
@@ -0,0 +1,84 @@
+/*
+ * iwinfo - Wireless Information Library - Broadcom wl.o Headers
+ *
+ * Copyright (C) 2009-2010 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * The iwinfo library 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.
+ *
+ * The iwinfo library 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 the iwinfo library. If not, see http://www.gnu.org/licenses/.
+ */
+
+#ifndef __IWINFO_WL_H_
+#define __IWINFO_WL_H_
+
+#include <fcntl.h>
+
+#include "iwinfo.h"
+#include "iwinfo/utils.h"
+#include "iwinfo/api/broadcom.h"
+
+int wl_probe(const char *ifname);
+int wl_get_mode(const char *ifname, int *buf);
+int wl_get_ssid(const char *ifname, char *buf);
+int wl_get_bssid(const char *ifname, char *buf);
+int wl_get_country(const char *ifname, char *buf);
+int wl_get_channel(const char *ifname, int *buf);
+int wl_get_frequency(const char *ifname, int *buf);
+int wl_get_frequency_offset(const char *ifname, int *buf);
+int wl_get_txpower(const char *ifname, int *buf);
+int wl_get_txpower_offset(const char *ifname, int *buf);
+int wl_get_bitrate(const char *ifname, int *buf);
+int wl_get_signal(const char *ifname, int *buf);
+int wl_get_noise(const char *ifname, int *buf);
+int wl_get_quality(const char *ifname, int *buf);
+int wl_get_quality_max(const char *ifname, int *buf);
+int wl_get_enctype(const char *ifname, char *buf);
+int wl_get_encryption(const char *ifname, char *buf);
+int wl_get_assoclist(const char *ifname, char *buf, int *len);
+int wl_get_txpwrlist(const char *ifname, char *buf, int *len);
+int wl_get_scanlist(const char *ifname, char *buf, int *len);
+int wl_get_freqlist(const char *ifname, char *buf, int *len);
+int wl_get_countrylist(const char *ifname, char *buf, int *len);
+int wl_get_hwmodelist(const char *ifname, int *buf);
+int wl_get_mbssid_support(const char *ifname, int *buf);
+int wl_get_hardware_id(const char *ifname, char *buf);
+int wl_get_hardware_name(const char *ifname, char *buf);
+void wl_close(void);
+
+static const struct iwinfo_ops wl_ops = {
+ .channel = wl_get_channel,
+ .frequency = wl_get_frequency,
+ .frequency_offset = wl_get_frequency_offset,
+ .txpower = wl_get_txpower,
+ .txpower_offset = wl_get_txpower_offset,
+ .bitrate = wl_get_bitrate,
+ .signal = wl_get_signal,
+ .noise = wl_get_noise,
+ .quality = wl_get_quality,
+ .quality_max = wl_get_quality_max,
+ .mbssid_support = wl_get_mbssid_support,
+ .hwmodelist = wl_get_hwmodelist,
+ .mode = wl_get_mode,
+ .ssid = wl_get_ssid,
+ .bssid = wl_get_bssid,
+ .country = wl_get_country,
+ .hardware_id = wl_get_hardware_id,
+ .hardware_name = wl_get_hardware_name,
+ .encryption = wl_get_encryption,
+ .assoclist = wl_get_assoclist,
+ .txpwrlist = wl_get_txpwrlist,
+ .scanlist = wl_get_scanlist,
+ .freqlist = wl_get_freqlist,
+ .countrylist = wl_get_countrylist,
+ .close = wl_close
+};
+
+#endif
diff --git a/package/iwinfo/src/iwinfo_cli.c b/package/iwinfo/src/iwinfo_cli.c
new file mode 100644
index 000000000..7ec5aef95
--- /dev/null
+++ b/package/iwinfo/src/iwinfo_cli.c
@@ -0,0 +1,800 @@
+/*
+ * iwinfo - Wireless Information Library - Command line frontend
+ *
+ * Copyright (C) 2011 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * The iwinfo library 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.
+ *
+ * The iwinfo library 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 the iwinfo library. If not, see http://www.gnu.org/licenses/.
+ */
+
+#include <stdio.h>
+
+#include "iwinfo.h"
+
+
+static char * format_bssid(unsigned char *mac)
+{
+ static char buf[18];
+
+ snprintf(buf, sizeof(buf), "%02X:%02X:%02X:%02X:%02X:%02X",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+ return buf;
+}
+
+static char * format_ssid(char *ssid)
+{
+ static char buf[IWINFO_ESSID_MAX_SIZE+3];
+
+ if (ssid && ssid[0])
+ snprintf(buf, sizeof(buf), "\"%s\"", ssid);
+ else
+ snprintf(buf, sizeof(buf), "unknown");
+
+ return buf;
+}
+
+static char * format_channel(int ch)
+{
+ static char buf[8];
+
+ if (ch <= 0)
+ snprintf(buf, sizeof(buf), "unknown");
+ else
+ snprintf(buf, sizeof(buf), "%d", ch);
+
+ return buf;
+}
+
+static char * format_frequency(int freq)
+{
+ static char buf[10];
+
+ if (freq <= 0)
+ snprintf(buf, sizeof(buf), "unknown");
+ else
+ snprintf(buf, sizeof(buf), "%.3f GHz", ((float)freq / 1000.0));
+
+ return buf;
+}
+
+static char * format_txpower(int pwr)
+{
+ static char buf[10];
+
+ if (pwr < 0)
+ snprintf(buf, sizeof(buf), "unknown");
+ else
+ snprintf(buf, sizeof(buf), "%d dBm", pwr);
+
+ return buf;
+}
+
+static char * format_quality(int qual)
+{
+ static char buf[8];
+
+ if (qual < 0)
+ snprintf(buf, sizeof(buf), "unknown");
+ else
+ snprintf(buf, sizeof(buf), "%d", qual);
+
+ return buf;
+}
+
+static char * format_quality_max(int qmax)
+{
+ static char buf[8];
+
+ if (qmax < 0)
+ snprintf(buf, sizeof(buf), "unknown");
+ else
+ snprintf(buf, sizeof(buf), "%d", qmax);
+
+ return buf;
+}
+
+static char * format_signal(int sig)
+{
+ static char buf[10];
+
+ if (!sig)
+ snprintf(buf, sizeof(buf), "unknown");
+ else
+ snprintf(buf, sizeof(buf), "%d dBm", sig);
+
+ return buf;
+}
+
+static char * format_noise(int noise)
+{
+ static char buf[10];
+
+ if (!noise)
+ snprintf(buf, sizeof(buf), "unknown");
+ else
+ snprintf(buf, sizeof(buf), "%d dBm", noise);
+
+ return buf;
+}
+
+static char * format_rate(int rate)
+{
+ static char buf[14];
+
+ if (rate <= 0)
+ snprintf(buf, sizeof(buf), "unknown");
+ else
+ snprintf(buf, sizeof(buf), "%d.%d MBit/s",
+ rate / 1000, (rate % 1000) / 100);
+
+ return buf;
+}
+
+static char * format_enc_ciphers(int ciphers)
+{
+ static char str[128] = { 0 };
+ char *pos = str;
+
+ if (ciphers & IWINFO_CIPHER_WEP40)
+ pos += sprintf(pos, "WEP-40, ");
+
+ if (ciphers & IWINFO_CIPHER_WEP104)
+ pos += sprintf(pos, "WEP-104, ");
+
+ if (ciphers & IWINFO_CIPHER_TKIP)
+ pos += sprintf(pos, "TKIP, ");
+
+ if (ciphers & IWINFO_CIPHER_CCMP)
+ pos += sprintf(pos, "CCMP, ");
+
+ if (ciphers & IWINFO_CIPHER_WRAP)
+ pos += sprintf(pos, "WRAP, ");
+
+ if (ciphers & IWINFO_CIPHER_AESOCB)
+ pos += sprintf(pos, "AES-OCB, ");
+
+ if (ciphers & IWINFO_CIPHER_CKIP)
+ pos += sprintf(pos, "CKIP, ");
+
+ if (!ciphers || (ciphers & IWINFO_CIPHER_NONE))
+ pos += sprintf(pos, "NONE, ");
+
+ *(pos - 2) = 0;
+
+ return str;
+}
+
+static char * format_enc_suites(int suites)
+{
+ static char str[64] = { 0 };
+ char *pos = str;
+
+ if (suites & IWINFO_KMGMT_PSK)
+ pos += sprintf(pos, "PSK/");
+
+ if (suites & IWINFO_KMGMT_8021x)
+ pos += sprintf(pos, "802.1X/");
+
+ if (!suites || (suites & IWINFO_KMGMT_NONE))
+ pos += sprintf(pos, "NONE/");
+
+ *(pos - 1) = 0;
+
+ return str;
+}
+
+static char * format_encryption(struct iwinfo_crypto_entry *c)
+{
+ static char buf[512];
+
+ if (!c)
+ {
+ snprintf(buf, sizeof(buf), "unknown");
+ }
+ else if (c->enabled)
+ {
+ /* WEP */
+ if (c->auth_algs && !c->wpa_version)
+ {
+ if ((c->auth_algs & IWINFO_AUTH_OPEN) &&
+ (c->auth_algs & IWINFO_AUTH_SHARED))
+ {
+ snprintf(buf, sizeof(buf), "WEP Open/Shared (%s)",
+ format_enc_ciphers(c->pair_ciphers));
+ }
+ else if (c->auth_algs & IWINFO_AUTH_OPEN)
+ {
+ snprintf(buf, sizeof(buf), "WEP Open System (%s)",
+ format_enc_ciphers(c->pair_ciphers));
+ }
+ else if (c->auth_algs & IWINFO_AUTH_SHARED)
+ {
+ snprintf(buf, sizeof(buf), "WEP Shared Auth (%s)",
+ format_enc_ciphers(c->pair_ciphers));
+ }
+ }
+
+ /* WPA */
+ else if (c->wpa_version)
+ {
+ switch (c->wpa_version) {
+ case 3:
+ snprintf(buf, sizeof(buf), "mixed WPA/WPA2 %s (%s)",
+ format_enc_suites(c->auth_suites),
+ format_enc_ciphers(c->pair_ciphers | c->group_ciphers));
+ break;
+
+ case 2:
+ snprintf(buf, sizeof(buf), "WPA2 %s (%s)",
+ format_enc_suites(c->auth_suites),
+ format_enc_ciphers(c->pair_ciphers | c->group_ciphers));
+ break;
+
+ case 1:
+ snprintf(buf, sizeof(buf), "WPA %s (%s)",
+ format_enc_suites(c->auth_suites),
+ format_enc_ciphers(c->pair_ciphers | c->group_ciphers));
+ break;
+ }
+ }
+ else
+ {
+ snprintf(buf, sizeof(buf), "none");
+ }
+ }
+ else
+ {
+ snprintf(buf, sizeof(buf), "none");
+ }
+
+ return buf;
+}
+
+static char * format_hwmodes(int modes)
+{
+ static char buf[12];
+
+ if (modes <= 0)
+ snprintf(buf, sizeof(buf), "unknown");
+ else
+ snprintf(buf, sizeof(buf), "802.11%s%s%s%s",
+ (modes & IWINFO_80211_A) ? "a" : "",
+ (modes & IWINFO_80211_B) ? "b" : "",
+ (modes & IWINFO_80211_G) ? "g" : "",
+ (modes & IWINFO_80211_N) ? "n" : "");
+
+ return buf;
+}
+
+static char * format_assocrate(struct iwinfo_rate_entry *r)
+{
+ static char buf[40];
+ char *p = buf;
+ int l = sizeof(buf);
+
+ if (r->rate <= 0)
+ {
+ snprintf(buf, sizeof(buf), "unknown");
+ }
+ else
+ {
+ p += snprintf(p, l, "%s", format_rate(r->rate));
+ l = sizeof(buf) - (p - buf);
+
+ if (r->mcs >= 0)
+ {
+ p += snprintf(p, l, ", MCS %d, %dMHz", r->mcs, 20 + r->is_40mhz*20);
+ l = sizeof(buf) - (p - buf);
+
+ if (r->is_short_gi)
+ p += snprintf(p, l, ", short GI");
+ }
+ }
+
+ return buf;
+}
+
+
+static const char * print_type(const struct iwinfo_ops *iw, const char *ifname)
+{
+ const char *type = iwinfo_type(ifname);
+ return type ? type : "unknown";
+}
+
+static char * print_hardware_id(const struct iwinfo_ops *iw, const char *ifname)
+{
+ static char buf[20];
+ struct iwinfo_hardware_id ids;
+
+ if (!iw->hardware_id(ifname, (char *)&ids))
+ {
+ snprintf(buf, sizeof(buf), "%04X:%04X %04X:%04X",
+ ids.vendor_id, ids.device_id,
+ ids.subsystem_vendor_id, ids.subsystem_device_id);
+ }
+ else
+ {
+ snprintf(buf, sizeof(buf), "unknown");
+ }
+
+ return buf;
+}
+
+static char * print_hardware_name(const struct iwinfo_ops *iw, const char *ifname)
+{
+ static char buf[128];
+
+ if (iw->hardware_name(ifname, buf))
+ snprintf(buf, sizeof(buf), "unknown");
+
+ return buf;
+}
+
+static char * print_txpower_offset(const struct iwinfo_ops *iw, const char *ifname)
+{
+ int off;
+ static char buf[12];
+
+ if (iw->txpower_offset(ifname, &off))
+ snprintf(buf, sizeof(buf), "unknown");
+ else if (off != 0)
+ snprintf(buf, sizeof(buf), "%d dB", off);
+ else
+ snprintf(buf, sizeof(buf), "none");
+
+ return buf;
+}
+
+static char * print_frequency_offset(const struct iwinfo_ops *iw, const char *ifname)
+{
+ int off;
+ static char buf[12];
+
+ if (iw->frequency_offset(ifname, &off))
+ snprintf(buf, sizeof(buf), "unknown");
+ else if (off != 0)
+ snprintf(buf, sizeof(buf), "%.3f GHz", ((float)off / 1000.0));
+ else
+ snprintf(buf, sizeof(buf), "none");
+
+ return buf;
+}
+
+static char * print_ssid(const struct iwinfo_ops *iw, const char *ifname)
+{
+ char buf[IWINFO_ESSID_MAX_SIZE+1] = { 0 };
+
+ if (iw->ssid(ifname, buf))
+ memset(buf, 0, sizeof(buf));
+
+ return format_ssid(buf);
+}
+
+static char * print_bssid(const struct iwinfo_ops *iw, const char *ifname)
+{
+ static char buf[18] = { 0 };
+
+ if (iw->bssid(ifname, buf))
+ snprintf(buf, sizeof(buf), "00:00:00:00:00:00");
+
+ return buf;
+}
+
+static char * print_mode(const struct iwinfo_ops *iw, const char *ifname)
+{
+ int mode;
+ static char buf[128];
+
+ if (iw->mode(ifname, &mode))
+ mode = IWINFO_OPMODE_UNKNOWN;
+
+ snprintf(buf, sizeof(buf), "%s", IWINFO_OPMODE_NAMES[mode]);
+
+ return buf;
+}
+
+static char * print_channel(const struct iwinfo_ops *iw, const char *ifname)
+{
+ int ch;
+ if (iw->channel(ifname, &ch))
+ ch = -1;
+
+ return format_channel(ch);
+}
+
+static char * print_frequency(const struct iwinfo_ops *iw, const char *ifname)
+{
+ int freq;
+ if (iw->frequency(ifname, &freq))
+ freq = -1;
+
+ return format_frequency(freq);
+}
+
+static char * print_txpower(const struct iwinfo_ops *iw, const char *ifname)
+{
+ int pwr, off;
+ if (iw->txpower_offset(ifname, &off))
+ off = 0;
+
+ if (iw->txpower(ifname, &pwr))
+ pwr = -1;
+ else
+ pwr += off;
+
+ return format_txpower(pwr);
+}
+
+static char * print_quality(const struct iwinfo_ops *iw, const char *ifname)
+{
+ int qual;
+ if (iw->quality(ifname, &qual))
+ qual = -1;
+
+ return format_quality(qual);
+}
+
+static char * print_quality_max(const struct iwinfo_ops *iw, const char *ifname)
+{
+ int qmax;
+ if (iw->quality_max(ifname, &qmax))
+ qmax = -1;
+
+ return format_quality_max(qmax);
+}
+
+static char * print_signal(const struct iwinfo_ops *iw, const char *ifname)
+{
+ int sig;
+ if (iw->signal(ifname, &sig))
+ sig = 0;
+
+ return format_signal(sig);
+}
+
+static char * print_noise(const struct iwinfo_ops *iw, const char *ifname)
+{
+ int noise;
+ if (iw->noise(ifname, &noise))
+ noise = 0;
+
+ return format_noise(noise);
+}
+
+static char * print_rate(const struct iwinfo_ops *iw, const char *ifname)
+{
+ int rate;
+ if (iw->bitrate(ifname, &rate))
+ rate = -1;
+
+ return format_rate(rate);
+}
+
+static char * print_encryption(const struct iwinfo_ops *iw, const char *ifname)
+{
+ struct iwinfo_crypto_entry c = { 0 };
+ if (iw->encryption(ifname, (char *)&c))
+ return format_encryption(NULL);
+
+ return format_encryption(&c);
+}
+
+static char * print_hwmodes(const struct iwinfo_ops *iw, const char *ifname)
+{
+ int modes;
+ if (iw->hwmodelist(ifname, &modes))
+ modes = -1;
+
+ return format_hwmodes(modes);
+}
+
+static char * print_mbssid_supp(const struct iwinfo_ops *iw, const char *ifname)
+{
+ int supp;
+ static char buf[4];
+
+ if (iw->mbssid_support(ifname, &supp))
+ snprintf(buf, sizeof(buf), "no");
+ else
+ snprintf(buf, sizeof(buf), "%s", supp ? "yes" : "no");
+
+ return buf;
+}
+
+
+static void print_info(const struct iwinfo_ops *iw, const char *ifname)
+{
+ printf("%-9s ESSID: %s\n",
+ ifname,
+ print_ssid(iw, ifname));
+ printf(" Access Point: %s\n",
+ print_bssid(iw, ifname));
+ printf(" Mode: %s Channel: %s (%s)\n",
+ print_mode(iw, ifname),
+ print_channel(iw, ifname),
+ print_frequency(iw, ifname));
+ printf(" Tx-Power: %s Link Quality: %s/%s\n",
+ print_txpower(iw, ifname),
+ print_quality(iw, ifname),
+ print_quality_max(iw, ifname));
+ printf(" Signal: %s Noise: %s\n",
+ print_signal(iw, ifname),
+ print_noise(iw, ifname));
+ printf(" Bit Rate: %s\n",
+ print_rate(iw, ifname));
+ printf(" Encryption: %s\n",
+ print_encryption(iw, ifname));
+ printf(" Type: %s HW Mode(s): %s\n",
+ print_type(iw, ifname),
+ print_hwmodes(iw, ifname));
+ printf(" Hardware: %s [%s]\n",
+ print_hardware_id(iw, ifname),
+ print_hardware_name(iw, ifname));
+ printf(" TX power offset: %s\n",
+ print_txpower_offset(iw, ifname));
+ printf(" Frequency offset: %s\n",
+ print_frequency_offset(iw, ifname));
+ printf(" Supports VAPs: %s\n",
+ print_mbssid_supp(iw, ifname));
+}
+
+
+static void print_scanlist(const struct iwinfo_ops *iw, const char *ifname)
+{
+ int i, x, len;
+ char buf[IWINFO_BUFSIZE];
+ struct iwinfo_scanlist_entry *e;
+
+ if (iw->scanlist(ifname, buf, &len))
+ {
+ printf("Scanning not possible\n\n");
+ return;
+ }
+ else if (len <= 0)
+ {
+ printf("No scan results\n\n");
+ return;
+ }
+
+ for (i = 0, x = 1; i < len; i += sizeof(struct iwinfo_scanlist_entry), x++)
+ {
+ e = (struct iwinfo_scanlist_entry *) &buf[i];
+
+ printf("Cell %02d - Address: %s\n",
+ x,
+ format_bssid(e->mac));
+ printf(" ESSID: %s\n",
+ format_ssid(e->ssid));
+ printf(" Mode: %s Channel: %s\n",
+ IWINFO_OPMODE_NAMES[e->mode],
+ format_channel(e->channel));
+ printf(" Signal: %s Quality: %s/%s\n",
+ format_signal(e->signal - 0x100),
+ format_quality(e->quality),
+ format_quality_max(e->quality_max));
+ printf(" Encryption: %s\n\n",
+ format_encryption(&e->crypto));
+ }
+}
+
+
+static void print_txpwrlist(const struct iwinfo_ops *iw, const char *ifname)
+{
+ int len, pwr, off, i;
+ char buf[IWINFO_BUFSIZE];
+ struct iwinfo_txpwrlist_entry *e;
+
+ if (iw->txpwrlist(ifname, buf, &len) || len <= 0)
+ {
+ printf("No TX power information available\n");
+ return;
+ }
+
+ if (iw->txpower(ifname, &pwr))
+ pwr = -1;
+
+ if (iw->txpower_offset(ifname, &off))
+ off = 0;
+
+ for (i = 0; i < len; i += sizeof(struct iwinfo_txpwrlist_entry))
+ {
+ e = (struct iwinfo_txpwrlist_entry *) &buf[i];
+
+ printf("%s%3d dBm (%4d mW)\n",
+ (pwr == e->dbm) ? "*" : " ",
+ e->dbm + off,
+ iwinfo_dbm2mw(e->dbm + off));
+ }
+}
+
+
+static void print_freqlist(const struct iwinfo_ops *iw, const char *ifname)
+{
+ int i, len, ch;
+ char buf[IWINFO_BUFSIZE];
+ struct iwinfo_freqlist_entry *e;
+
+ if (iw->freqlist(ifname, buf, &len) || len <= 0)
+ {
+ printf("No frequency information available\n");
+ return;
+ }
+
+ if (iw->channel(ifname, &ch))
+ ch = -1;
+
+ for (i = 0; i < len; i += sizeof(struct iwinfo_freqlist_entry))
+ {
+ e = (struct iwinfo_freqlist_entry *) &buf[i];
+
+ printf("%s %s (Channel %s)%s\n",
+ (ch == e->channel) ? "*" : " ",
+ format_frequency(e->mhz),
+ format_channel(e->channel),
+ e->restricted ? " [restricted]" : "");
+ }
+}
+
+
+static void print_assoclist(const struct iwinfo_ops *iw, const char *ifname)
+{
+ int i, len;
+ char buf[IWINFO_BUFSIZE];
+ struct iwinfo_assoclist_entry *e;
+
+ if (iw->assoclist(ifname, buf, &len))
+ {
+ printf("No information available\n");
+ return;
+ }
+ else if (len <= 0)
+ {
+ printf("No station connected\n");
+ return;
+ }
+
+ for (i = 0; i < len; i += sizeof(struct iwinfo_assoclist_entry))
+ {
+ e = (struct iwinfo_assoclist_entry *) &buf[i];
+
+ printf("%s %s / %s (SNR %d) %d ms ago\n",
+ format_bssid(e->mac),
+ format_signal(e->signal),
+ format_noise(e->noise),
+ (e->signal - e->noise),
+ e->inactive);
+
+ printf(" RX: %-38s %8d Pkts.\n",
+ format_assocrate(&e->rx_rate),
+ e->rx_packets
+ );
+
+ printf(" TX: %-38s %8d Pkts.\n\n",
+ format_assocrate(&e->tx_rate),
+ e->tx_packets
+ );
+ }
+}
+
+
+static char * lookup_country(char *buf, int len, int iso3166)
+{
+ int i;
+ struct iwinfo_country_entry *c;
+
+ for (i = 0; i < len; i += sizeof(struct iwinfo_country_entry))
+ {
+ c = (struct iwinfo_country_entry *) &buf[i];
+
+ if (c->iso3166 == iso3166)
+ return c->ccode;
+ }
+
+ return NULL;
+}
+
+static void print_countrylist(const struct iwinfo_ops *iw, const char *ifname)
+{
+ int len;
+ char buf[IWINFO_BUFSIZE];
+ char *ccode;
+ char curcode[3];
+ const struct iwinfo_iso3166_label *l;
+
+ if (iw->countrylist(ifname, buf, &len))
+ {
+ printf("No country code information available\n");
+ return;
+ }
+
+ if (iw->country(ifname, curcode))
+ memset(curcode, 0, sizeof(curcode));
+
+ for (l = IWINFO_ISO3166_NAMES; l->iso3166; l++)
+ {
+ if ((ccode = lookup_country(buf, len, l->iso3166)) != NULL)
+ {
+ printf("%s %4s %c%c\n",
+ strncmp(ccode, curcode, 2) ? " " : "*",
+ ccode, (l->iso3166 / 256), (l->iso3166 % 256));
+ }
+ }
+}
+
+
+int main(int argc, char **argv)
+{
+ int i;
+ const struct iwinfo_ops *iw;
+
+ if (argc < 3)
+ {
+ fprintf(stderr,
+ "Usage:\n"
+ " iwinfo <device> info\n"
+ " iwinfo <device> scan\n"
+ " iwinfo <device> txpowerlist\n"
+ " iwinfo <device> freqlist\n"
+ " iwinfo <device> assoclist\n"
+ " iwinfo <device> countrylist\n"
+ );
+
+ return 1;
+ }
+
+ iw = iwinfo_backend(argv[1]);
+
+ if (!iw)
+ {
+ fprintf(stderr, "No such wireless device: %s\n", argv[1]);
+ return 1;
+ }
+
+ for (i = 2; i < argc; i++)
+ {
+ switch(argv[i][0])
+ {
+ case 'i':
+ print_info(iw, argv[1]);
+ break;
+
+ case 's':
+ print_scanlist(iw, argv[1]);
+ break;
+
+ case 't':
+ print_txpwrlist(iw, argv[1]);
+ break;
+
+ case 'f':
+ print_freqlist(iw, argv[1]);
+ break;
+
+ case 'a':
+ print_assoclist(iw, argv[1]);
+ break;
+
+ case 'c':
+ print_countrylist(iw, argv[1]);
+ break;
+
+ default:
+ fprintf(stderr, "Unknown command: %s\n", argv[i]);
+ return 1;
+ }
+ }
+
+ iwinfo_finish();
+
+ return 0;
+}
diff --git a/package/iwinfo/src/iwinfo_lib.c b/package/iwinfo/src/iwinfo_lib.c
new file mode 100644
index 000000000..dd65e45aa
--- /dev/null
+++ b/package/iwinfo/src/iwinfo_lib.c
@@ -0,0 +1,453 @@
+/*
+ * iwinfo - Wireless Information Library - Lua Bindings
+ *
+ * Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * The iwinfo library 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.
+ *
+ * The iwinfo library 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 the iwinfo library. If not, see http://www.gnu.org/licenses/.
+ */
+
+#include "iwinfo.h"
+
+
+/*
+ * name constants
+ */
+const char *IWINFO_CIPHER_NAMES[] = {
+ "NONE",
+ "WEP40",
+ "TKIP",
+ "WRAP",
+ "CCMP",
+ "WEP104",
+ "AES-OCB",
+ "CKIP",
+};
+
+const char *IWINFO_KMGMT_NAMES[] = {
+ "NONE",
+ "802.1X",
+ "PSK",
+};
+
+const char *IWINFO_AUTH_NAMES[] = {
+ "OPEN",
+ "SHARED",
+};
+
+const char *IWINFO_OPMODE_NAMES[] = {
+ "Unknown",
+ "Master",
+ "Ad-Hoc",
+ "Client",
+ "Monitor",
+};
+
+
+/*
+ * ISO3166 country labels
+ */
+
+const struct iwinfo_iso3166_label IWINFO_ISO3166_NAMES[] = {
+ { 0x3030 /* 00 */, "World" },
+ { 0x4144 /* AD */, "Andorra" },
+ { 0x4145 /* AE */, "United Arab Emirates" },
+ { 0x4146 /* AF */, "Afghanistan" },
+ { 0x4147 /* AG */, "Antigua and Barbuda" },
+ { 0x4149 /* AI */, "Anguilla" },
+ { 0x414C /* AL */, "Albania" },
+ { 0x414D /* AM */, "Armenia" },
+ { 0x414E /* AN */, "Netherlands Antilles" },
+ { 0x414F /* AO */, "Angola" },
+ { 0x4151 /* AQ */, "Antarctica" },
+ { 0x4152 /* AR */, "Argentina" },
+ { 0x4153 /* AS */, "American Samoa" },
+ { 0x4154 /* AT */, "Austria" },
+ { 0x4155 /* AU */, "Australia" },
+ { 0x4157 /* AW */, "Aruba" },
+ { 0x4158 /* AX */, "Aland Islands" },
+ { 0x415A /* AZ */, "Azerbaijan" },
+ { 0x4241 /* BA */, "Bosnia and Herzegovina" },
+ { 0x4242 /* BB */, "Barbados" },
+ { 0x4244 /* BD */, "Bangladesh" },
+ { 0x4245 /* BE */, "Belgium" },
+ { 0x4246 /* BF */, "Burkina Faso" },
+ { 0x4247 /* BG */, "Bulgaria" },
+ { 0x4248 /* BH */, "Bahrain" },
+ { 0x4249 /* BI */, "Burundi" },
+ { 0x424A /* BJ */, "Benin" },
+ { 0x424C /* BL */, "Saint Barthelemy" },
+ { 0x424D /* BM */, "Bermuda" },
+ { 0x424E /* BN */, "Brunei Darussalam" },
+ { 0x424F /* BO */, "Bolivia" },
+ { 0x4252 /* BR */, "Brazil" },
+ { 0x4253 /* BS */, "Bahamas" },
+ { 0x4254 /* BT */, "Bhutan" },
+ { 0x4256 /* BV */, "Bouvet Island" },
+ { 0x4257 /* BW */, "Botswana" },
+ { 0x4259 /* BY */, "Belarus" },
+ { 0x425A /* BZ */, "Belize" },
+ { 0x4341 /* CA */, "Canada" },
+ { 0x4343 /* CC */, "Cocos (Keeling) Islands" },
+ { 0x4344 /* CD */, "Congo" },
+ { 0x4346 /* CF */, "Central African Republic" },
+ { 0x4347 /* CG */, "Congo" },
+ { 0x4348 /* CH */, "Switzerland" },
+ { 0x4349 /* CI */, "Cote d'Ivoire" },
+ { 0x434B /* CK */, "Cook Islands" },
+ { 0x434C /* CL */, "Chile" },
+ { 0x434D /* CM */, "Cameroon" },
+ { 0x434E /* CN */, "China" },
+ { 0x434F /* CO */, "Colombia" },
+ { 0x4352 /* CR */, "Costa Rica" },
+ { 0x4355 /* CU */, "Cuba" },
+ { 0x4356 /* CV */, "Cape Verde" },
+ { 0x4358 /* CX */, "Christmas Island" },
+ { 0x4359 /* CY */, "Cyprus" },
+ { 0x435A /* CZ */, "Czech Republic" },
+ { 0x4445 /* DE */, "Germany" },
+ { 0x444A /* DJ */, "Djibouti" },
+ { 0x444B /* DK */, "Denmark" },
+ { 0x444D /* DM */, "Dominica" },
+ { 0x444F /* DO */, "Dominican Republic" },
+ { 0x445A /* DZ */, "Algeria" },
+ { 0x4543 /* EC */, "Ecuador" },
+ { 0x4545 /* EE */, "Estonia" },
+ { 0x4547 /* EG */, "Egypt" },
+ { 0x4548 /* EH */, "Western Sahara" },
+ { 0x4552 /* ER */, "Eritrea" },
+ { 0x4553 /* ES */, "Spain" },
+ { 0x4554 /* ET */, "Ethiopia" },
+ { 0x4649 /* FI */, "Finland" },
+ { 0x464A /* FJ */, "Fiji" },
+ { 0x464B /* FK */, "Falkland Islands" },
+ { 0x464D /* FM */, "Micronesia" },
+ { 0x464F /* FO */, "Faroe Islands" },
+ { 0x4652 /* FR */, "France" },
+ { 0x4741 /* GA */, "Gabon" },
+ { 0x4742 /* GB */, "United Kingdom" },
+ { 0x4744 /* GD */, "Grenada" },
+ { 0x4745 /* GE */, "Georgia" },
+ { 0x4746 /* GF */, "French Guiana" },
+ { 0x4747 /* GG */, "Guernsey" },
+ { 0x4748 /* GH */, "Ghana" },
+ { 0x4749 /* GI */, "Gibraltar" },
+ { 0x474C /* GL */, "Greenland" },
+ { 0x474D /* GM */, "Gambia" },
+ { 0x474E /* GN */, "Guinea" },
+ { 0x4750 /* GP */, "Guadeloupe" },
+ { 0x4751 /* GQ */, "Equatorial Guinea" },
+ { 0x4752 /* GR */, "Greece" },
+ { 0x4753 /* GS */, "South Georgia" },
+ { 0x4754 /* GT */, "Guatemala" },
+ { 0x4755 /* GU */, "Guam" },
+ { 0x4757 /* GW */, "Guinea-Bissau" },
+ { 0x4759 /* GY */, "Guyana" },
+ { 0x484B /* HK */, "Hong Kong" },
+ { 0x484D /* HM */, "Heard and McDonald Islands" },
+ { 0x484E /* HN */, "Honduras" },
+ { 0x4852 /* HR */, "Croatia" },
+ { 0x4854 /* HT */, "Haiti" },
+ { 0x4855 /* HU */, "Hungary" },
+ { 0x4944 /* ID */, "Indonesia" },
+ { 0x4945 /* IE */, "Ireland" },
+ { 0x494C /* IL */, "Israel" },
+ { 0x494D /* IM */, "Isle of Man" },
+ { 0x494E /* IN */, "India" },
+ { 0x494F /* IO */, "Chagos Islands" },
+ { 0x4951 /* IQ */, "Iraq" },
+ { 0x4952 /* IR */, "Iran" },
+ { 0x4953 /* IS */, "Iceland" },
+ { 0x4954 /* IT */, "Italy" },
+ { 0x4A45 /* JE */, "Jersey" },
+ { 0x4A4D /* JM */, "Jamaica" },
+ { 0x4A4F /* JO */, "Jordan" },
+ { 0x4A50 /* JP */, "Japan" },
+ { 0x4B45 /* KE */, "Kenya" },
+ { 0x4B47 /* KG */, "Kyrgyzstan" },
+ { 0x4B48 /* KH */, "Cambodia" },
+ { 0x4B49 /* KI */, "Kiribati" },
+ { 0x4B4D /* KM */, "Comoros" },
+ { 0x4B4E /* KN */, "Saint Kitts and Nevis" },
+ { 0x4B50 /* KP */, "North Korea" },
+ { 0x4B52 /* KR */, "South Korea" },
+ { 0x4B57 /* KW */, "Kuwait" },
+ { 0x4B59 /* KY */, "Cayman Islands" },
+ { 0x4B5A /* KZ */, "Kazakhstan" },
+ { 0x4C41 /* LA */, "Laos" },
+ { 0x4C42 /* LB */, "Lebanon" },
+ { 0x4C43 /* LC */, "Saint Lucia" },
+ { 0x4C49 /* LI */, "Liechtenstein" },
+ { 0x4C4B /* LK */, "Sri Lanka" },
+ { 0x4C52 /* LR */, "Liberia" },
+ { 0x4C53 /* LS */, "Lesotho" },
+ { 0x4C54 /* LT */, "Lithuania" },
+ { 0x4C55 /* LU */, "Luxembourg" },
+ { 0x4C56 /* LV */, "Latvia" },
+ { 0x4C59 /* LY */, "Libyan Arab Jamahiriya" },
+ { 0x4D41 /* MA */, "Morocco" },
+ { 0x4D43 /* MC */, "Monaco" },
+ { 0x4D44 /* MD */, "Moldova" },
+ { 0x4D45 /* ME */, "Montenegro" },
+ { 0x4D46 /* MF */, "Saint Martin (French part)" },
+ { 0x4D47 /* MG */, "Madagascar" },
+ { 0x4D48 /* MH */, "Marshall Islands" },
+ { 0x4D4B /* MK */, "Macedonia" },
+ { 0x4D4C /* ML */, "Mali" },
+ { 0x4D4D /* MM */, "Myanmar" },
+ { 0x4D4E /* MN */, "Mongolia" },
+ { 0x4D4F /* MO */, "Macao" },
+ { 0x4D50 /* MP */, "Northern Mariana Islands" },
+ { 0x4D51 /* MQ */, "Martinique" },
+ { 0x4D52 /* MR */, "Mauritania" },
+ { 0x4D53 /* MS */, "Montserrat" },
+ { 0x4D54 /* MT */, "Malta" },
+ { 0x4D55 /* MU */, "Mauritius" },
+ { 0x4D56 /* MV */, "Maldives" },
+ { 0x4D57 /* MW */, "Malawi" },
+ { 0x4D58 /* MX */, "Mexico" },
+ { 0x4D59 /* MY */, "Malaysia" },
+ { 0x4D5A /* MZ */, "Mozambique" },
+ { 0x4E41 /* NA */, "Namibia" },
+ { 0x4E43 /* NC */, "New Caledonia" },
+ { 0x4E45 /* NE */, "Niger" },
+ { 0x4E46 /* NF */, "Norfolk Island" },
+ { 0x4E47 /* NG */, "Nigeria" },
+ { 0x4E49 /* NI */, "Nicaragua" },
+ { 0x4E4C /* NL */, "Netherlands" },
+ { 0x4E4F /* NO */, "Norway" },
+ { 0x4E50 /* NP */, "Nepal" },
+ { 0x4E52 /* NR */, "Nauru" },
+ { 0x4E55 /* NU */, "Niue" },
+ { 0x4E5A /* NZ */, "New Zealand" },
+ { 0x4F4D /* OM */, "Oman" },
+ { 0x5041 /* PA */, "Panama" },
+ { 0x5045 /* PE */, "Peru" },
+ { 0x5046 /* PF */, "French Polynesia" },
+ { 0x5047 /* PG */, "Papua New Guinea" },
+ { 0x5048 /* PH */, "Philippines" },
+ { 0x504B /* PK */, "Pakistan" },
+ { 0x504C /* PL */, "Poland" },
+ { 0x504D /* PM */, "Saint Pierre and Miquelon" },
+ { 0x504E /* PN */, "Pitcairn" },
+ { 0x5052 /* PR */, "Puerto Rico" },
+ { 0x5053 /* PS */, "Palestinian Territory" },
+ { 0x5054 /* PT */, "Portugal" },
+ { 0x5057 /* PW */, "Palau" },
+ { 0x5059 /* PY */, "Paraguay" },
+ { 0x5141 /* QA */, "Qatar" },
+ { 0x5245 /* RE */, "Reunion" },
+ { 0x524F /* RO */, "Romania" },
+ { 0x5253 /* RS */, "Serbia" },
+ { 0x5255 /* RU */, "Russian Federation" },
+ { 0x5257 /* RW */, "Rwanda" },
+ { 0x5341 /* SA */, "Saudi Arabia" },
+ { 0x5342 /* SB */, "Solomon Islands" },
+ { 0x5343 /* SC */, "Seychelles" },
+ { 0x5344 /* SD */, "Sudan" },
+ { 0x5345 /* SE */, "Sweden" },
+ { 0x5347 /* SG */, "Singapore" },
+ { 0x5348 /* SH */, "St. Helena and Dependencies" },
+ { 0x5349 /* SI */, "Slovenia" },
+ { 0x534A /* SJ */, "Svalbard and Jan Mayen" },
+ { 0x534B /* SK */, "Slovakia" },
+ { 0x534C /* SL */, "Sierra Leone" },
+ { 0x534D /* SM */, "San Marino" },
+ { 0x534E /* SN */, "Senegal" },
+ { 0x534F /* SO */, "Somalia" },
+ { 0x5352 /* SR */, "Suriname" },
+ { 0x5354 /* ST */, "Sao Tome and Principe" },
+ { 0x5356 /* SV */, "El Salvador" },
+ { 0x5359 /* SY */, "Syrian Arab Republic" },
+ { 0x535A /* SZ */, "Swaziland" },
+ { 0x5443 /* TC */, "Turks and Caicos Islands" },
+ { 0x5444 /* TD */, "Chad" },
+ { 0x5446 /* TF */, "French Southern Territories" },
+ { 0x5447 /* TG */, "Togo" },
+ { 0x5448 /* TH */, "Thailand" },
+ { 0x544A /* TJ */, "Tajikistan" },
+ { 0x544B /* TK */, "Tokelau" },
+ { 0x544C /* TL */, "Timor-Leste" },
+ { 0x544D /* TM */, "Turkmenistan" },
+ { 0x544E /* TN */, "Tunisia" },
+ { 0x544F /* TO */, "Tonga" },
+ { 0x5452 /* TR */, "Turkey" },
+ { 0x5454 /* TT */, "Trinidad and Tobago" },
+ { 0x5456 /* TV */, "Tuvalu" },
+ { 0x5457 /* TW */, "Taiwan" },
+ { 0x545A /* TZ */, "Tanzania" },
+ { 0x5541 /* UA */, "Ukraine" },
+ { 0x5547 /* UG */, "Uganda" },
+ { 0x554D /* UM */, "U.S. Minor Outlying Islands" },
+ { 0x5553 /* US */, "United States" },
+ { 0x5559 /* UY */, "Uruguay" },
+ { 0x555A /* UZ */, "Uzbekistan" },
+ { 0x5641 /* VA */, "Vatican City State" },
+ { 0x5643 /* VC */, "St. Vincent and Grenadines" },
+ { 0x5645 /* VE */, "Venezuela" },
+ { 0x5647 /* VG */, "Virgin Islands, British" },
+ { 0x5649 /* VI */, "Virgin Islands, U.S." },
+ { 0x564E /* VN */, "Viet Nam" },
+ { 0x5655 /* VU */, "Vanuatu" },
+ { 0x5746 /* WF */, "Wallis and Futuna" },
+ { 0x5753 /* WS */, "Samoa" },
+ { 0x5945 /* YE */, "Yemen" },
+ { 0x5954 /* YT */, "Mayotte" },
+ { 0x5A41 /* ZA */, "South Africa" },
+ { 0x5A4D /* ZM */, "Zambia" },
+ { 0x5A57 /* ZW */, "Zimbabwe" },
+ { 0, "" }
+};
+
+/*
+ * hardware database
+ */
+
+const char VENDOR_UBNT[] = "Ubiquiti";
+const char VENDOR_ATH[] = "Atheros";
+const char VENDOR_RALINK[] = "RaLink";
+
+const struct iwinfo_hardware_entry IWINFO_HARDWARE_ENTRIES[] = {
+/* { vendor, model, vendorid, deviceid, subsys vendorid, subsys deviceid, poweroff, freqoff } */
+#if defined(USE_MADWIFI) || defined(USE_NL80211)
+ { VENDOR_UBNT, "PowerStation2 (18V)", 0xffff, 0xffff, 0xffff, 0xb102, 0, 0 },
+ { VENDOR_UBNT, "PowerStation2 (16D)", 0xffff, 0xffff, 0xffff, 0xb202, 0, 0 },
+ { VENDOR_UBNT, "PowerStation2 (EXT)", 0xffff, 0xffff, 0xffff, 0xb302, 0, 0 },
+ { VENDOR_UBNT, "PowerStation5 (22V)", 0xffff, 0xffff, 0xffff, 0xb105, 0, 0 },
+ { VENDOR_UBNT, "PowerStation5 (EXT)", 0xffff, 0xffff, 0xffff, 0xb305, 0, 0 },
+ { VENDOR_UBNT, "PicoStation2", 0xffff, 0xffff, 0xffff, 0xc302, 0, 0 },
+ { VENDOR_UBNT, "PicoStation2 HP", 0xffff, 0xffff, 0xffff, 0xc3a2, 10, 0 },
+ { VENDOR_UBNT, "WispStation5", 0xffff, 0xffff, 0xffff, 0xa105, 0, 0 },
+ { VENDOR_UBNT, "LiteStation2", 0xffff, 0xffff, 0xffff, 0xa002, 10, 0 },
+ { VENDOR_UBNT, "LiteStation5", 0xffff, 0xffff, 0xffff, 0xa005, 5, 0 },
+ { VENDOR_UBNT, "NanoStation2", 0xffff, 0xffff, 0xffff, 0xc002, 10, 0 },
+ { VENDOR_UBNT, "NanoStation5", 0xffff, 0xffff, 0xffff, 0xc005, 5, 0 },
+ { VENDOR_UBNT, "NanoStation Loco2", 0xffff, 0xffff, 0xffff, 0xc102, 10, 0 },
+ { VENDOR_UBNT, "NanoStation Loco5", 0xffff, 0xffff, 0xffff, 0xc105, 5, 0 },
+ { VENDOR_UBNT, "Bullet2", 0xffff, 0xffff, 0xffff, 0xc202, 10, 0 },
+ { VENDOR_UBNT, "Bullet5", 0xffff, 0xffff, 0xffff, 0xc205, 5, 0 },
+ { VENDOR_UBNT, "XR2", 0x168c, 0x001b, 0x0777, 0x3002, 10, 0 },
+ { VENDOR_UBNT, "XR2", 0x168c, 0x001b, 0x7777, 0x3002, 10, 0 },
+ { VENDOR_UBNT, "XR2.3", 0x168c, 0x001b, 0x0777, 0x3b02, 10, 0 },
+ { VENDOR_UBNT, "XR2.6", 0x168c, 0x001b, 0x0777, 0x3c02, 10, 0 },
+ { VENDOR_UBNT, "XR3-2.8", 0x168c, 0x001b, 0x0777, 0x3b03, 10, 0 },
+ { VENDOR_UBNT, "XR3-3.6", 0x168c, 0x001b, 0x0777, 0x3c03, 10, 0 },
+ { VENDOR_UBNT, "XR3", 0x168c, 0x001b, 0x0777, 0x3003, 10, 0 },
+ { VENDOR_UBNT, "XR4", 0x168c, 0x001b, 0x0777, 0x3004, 10, 0 },
+ { VENDOR_UBNT, "XR5", 0x168c, 0x001b, 0x0777, 0x3005, 10, 0 },
+ { VENDOR_UBNT, "XR5", 0x168c, 0x001b, 0x7777, 0x3005, 10, 0 },
+ { VENDOR_UBNT, "XR7", 0x168c, 0x001b, 0x0777, 0x3007, 10, 0 },
+ { VENDOR_UBNT, "XR9", 0x168c, 0x001b, 0x0777, 0x3009, 10, -1520 },
+ { VENDOR_ATH, "AR5413", 0x168c, 0x001b, 0x168c, 0x2063, 0, 0 },
+ { VENDOR_UBNT, "SRC", 0x168c, 0x0013, 0x168c, 0x1042, 1, 0 },
+ { VENDOR_UBNT, "SR2", 0x168c, 0x0013, 0x0777, 0x2041, 10, 0 },
+ { VENDOR_UBNT, "SR4", 0x168c, 0x0013, 0x0777, 0x2004, 6, 0 },
+ { VENDOR_UBNT, "SR4", 0x168c, 0x0013, 0x7777, 0x2004, 6, 0 },
+ { VENDOR_UBNT, "SR4C", 0x168c, 0x0013, 0x0777, 0x1004, 6, 0 },
+ { VENDOR_UBNT, "SR4C", 0x168c, 0x0013, 0x7777, 0x1004, 6, 0 },
+ { VENDOR_UBNT, "SR5", 0x168c, 0x0013, 0x168c, 0x2042, 7, 0 },
+ { VENDOR_UBNT, "SR9", 0x168c, 0x0013, 0x7777, 0x2009, 12, -1500 },
+ { VENDOR_UBNT, "SR71A", 0x168c, 0x0027, 0x168c, 0x2082, 10, 0 },
+ { VENDOR_UBNT, "SR71", 0x168c, 0x0027, 0x0777, 0x4082, 10, 0 },
+#endif
+#ifdef USE_NL80211
+ { VENDOR_UBNT, "PicoStation M2", 0x168c, 0x002a, 0x0777, 0xe302, 12, 0 }, /* ToDo: confirm offset */
+ { VENDOR_UBNT, "NanoStation M2", 0x168c, 0x002a, 0x0777, 0xe012, 12, 0 }, /* ToDo: confirm offset */
+ { VENDOR_UBNT, "NanoStation M5", 0x168c, 0x002a, 0x0777, 0xe005, 5, 0 }, /* ToDo: confirm offset */
+ { VENDOR_UBNT, "Bullet M2", 0x168c, 0x002a, 0x0777, 0xe202, 12, 0 },
+ { VENDOR_UBNT, "Bullet M5", 0x168c, 0x002a, 0x0777, 0xe805, 5, 0 },
+
+ { VENDOR_ATH, "AR9220", 0x168c, 0x0029, 0x168c, 0xa094, 0, 0 },
+ { VENDOR_ATH, "AR9223", 0x168c, 0x0029, 0x168c, 0xa095, 0, 0 },
+ { VENDOR_ATH, "AR9280", 0x168c, 0x002a, 0x168c, 0xa093, 0, 0 },
+ { VENDOR_ATH, "AR9285", 0x168c, 0x002b, 0x168c, 0xa091, 0, 0 },
+ { VENDOR_RALINK, "Rt3050", 0x1814, 0x3050, 0x1814, 0x0005, 0, 0 },
+ { VENDOR_RALINK, "Rt3052", 0x1814, 0x3052, 0x1814, 0x0008, 0, 0 },
+ { VENDOR_RALINK, "Rt3352", 0x1814, 0x3352, 0x1814, 0x000c, 0, 0 },
+#endif
+ { NULL }
+};
+
+
+const char * iwinfo_type(const char *ifname)
+{
+#ifdef USE_NL80211
+ if (nl80211_probe(ifname))
+ return "nl80211";
+ else
+#endif
+
+#ifdef USE_MADWIFI
+ if (madwifi_probe(ifname))
+ return "madwifi";
+ else
+#endif
+
+#ifdef USE_WL
+ if (wl_probe(ifname))
+ return "wl";
+ else
+#endif
+
+ if (wext_probe(ifname))
+ return "wext";
+
+ return NULL;
+}
+
+const struct iwinfo_ops * iwinfo_backend(const char *ifname)
+{
+ const char *type;
+ struct iwinfo_ops *ops;
+
+ type = iwinfo_type(ifname);
+ if (!type)
+ return NULL;
+
+#ifdef USE_NL80211
+ if (!strcmp(type, "nl80211"))
+ return &nl80211_ops;
+ else
+#endif
+
+#ifdef USE_MADWIFI
+ if (!strcmp(type, "madwifi"))
+ return &madwifi_ops;
+ else
+#endif
+
+#ifdef USE_WL
+ if (!strcmp(type, "wl"))
+ return &wl_ops;
+ else
+#endif
+
+ if (!strcmp(type, "wext"))
+ return &wext_ops;
+
+ return NULL;
+}
+
+void iwinfo_finish(void)
+{
+#ifdef USE_WL
+ wl_close();
+#endif
+#ifdef USE_MADWIFI
+ madwifi_close();
+#endif
+#ifdef USE_NL80211
+ nl80211_close();
+#endif
+ wext_close();
+ iwinfo_close();
+}
diff --git a/package/iwinfo/src/iwinfo_lua.c b/package/iwinfo/src/iwinfo_lua.c
new file mode 100644
index 000000000..bd8faf91f
--- /dev/null
+++ b/package/iwinfo/src/iwinfo_lua.c
@@ -0,0 +1,886 @@
+/*
+ * iwinfo - Wireless Information Library - Lua Bindings
+ *
+ * Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * The iwinfo library 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.
+ *
+ * The iwinfo library 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 the iwinfo library. If not, see http://www.gnu.org/licenses/.
+ */
+
+#include "iwinfo/lua.h"
+
+
+/* Determine type */
+static int iwinfo_L_type(lua_State *L)
+{
+ const char *ifname = luaL_checkstring(L, 1);
+ const char *type = iwinfo_type(ifname);
+
+ if (type)
+ lua_pushstring(L, type);
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+/* Shutdown backends */
+static int iwinfo_L__gc(lua_State *L)
+{
+ iwinfo_finish();
+ return 0;
+}
+
+/*
+ * Build a short textual description of the crypto info
+ */
+
+static char * iwinfo_crypto_print_ciphers(int ciphers)
+{
+ static char str[128] = { 0 };
+ char *pos = str;
+
+ if (ciphers & IWINFO_CIPHER_WEP40)
+ pos += sprintf(pos, "WEP-40, ");
+
+ if (ciphers & IWINFO_CIPHER_WEP104)
+ pos += sprintf(pos, "WEP-104, ");
+
+ if (ciphers & IWINFO_CIPHER_TKIP)
+ pos += sprintf(pos, "TKIP, ");
+
+ if (ciphers & IWINFO_CIPHER_CCMP)
+ pos += sprintf(pos, "CCMP, ");
+
+ if (ciphers & IWINFO_CIPHER_WRAP)
+ pos += sprintf(pos, "WRAP, ");
+
+ if (ciphers & IWINFO_CIPHER_AESOCB)
+ pos += sprintf(pos, "AES-OCB, ");
+
+ if (ciphers & IWINFO_CIPHER_CKIP)
+ pos += sprintf(pos, "CKIP, ");
+
+ if (!ciphers || (ciphers & IWINFO_CIPHER_NONE))
+ pos += sprintf(pos, "NONE, ");
+
+ *(pos - 2) = 0;
+
+ return str;
+}
+
+static char * iwinfo_crypto_print_suites(int suites)
+{
+ static char str[64] = { 0 };
+ char *pos = str;
+
+ if (suites & IWINFO_KMGMT_PSK)
+ pos += sprintf(pos, "PSK/");
+
+ if (suites & IWINFO_KMGMT_8021x)
+ pos += sprintf(pos, "802.1X/");
+
+ if (!suites || (suites & IWINFO_KMGMT_NONE))
+ pos += sprintf(pos, "NONE/");
+
+ *(pos - 1) = 0;
+
+ return str;
+}
+
+static char * iwinfo_crypto_desc(struct iwinfo_crypto_entry *c)
+{
+ static char desc[512] = { 0 };
+
+ if (c)
+ {
+ if (c->enabled)
+ {
+ /* WEP */
+ if (c->auth_algs && !c->wpa_version)
+ {
+ if ((c->auth_algs & IWINFO_AUTH_OPEN) &&
+ (c->auth_algs & IWINFO_AUTH_SHARED))
+ {
+ sprintf(desc, "WEP Open/Shared (%s)",
+ iwinfo_crypto_print_ciphers(c->pair_ciphers));
+ }
+ else if (c->auth_algs & IWINFO_AUTH_OPEN)
+ {
+ sprintf(desc, "WEP Open System (%s)",
+ iwinfo_crypto_print_ciphers(c->pair_ciphers));
+ }
+ else if (c->auth_algs & IWINFO_AUTH_SHARED)
+ {
+ sprintf(desc, "WEP Shared Auth (%s)",
+ iwinfo_crypto_print_ciphers(c->pair_ciphers));
+ }
+ }
+
+ /* WPA */
+ else if (c->wpa_version)
+ {
+ switch (c->wpa_version) {
+ case 3:
+ sprintf(desc, "mixed WPA/WPA2 %s (%s)",
+ iwinfo_crypto_print_suites(c->auth_suites),
+ iwinfo_crypto_print_ciphers(
+ c->pair_ciphers & c->group_ciphers));
+ break;
+
+ case 2:
+ sprintf(desc, "WPA2 %s (%s)",
+ iwinfo_crypto_print_suites(c->auth_suites),
+ iwinfo_crypto_print_ciphers(
+ c->pair_ciphers & c->group_ciphers));
+ break;
+
+ case 1:
+ sprintf(desc, "WPA %s (%s)",
+ iwinfo_crypto_print_suites(c->auth_suites),
+ iwinfo_crypto_print_ciphers(
+ c->pair_ciphers & c->group_ciphers));
+ break;
+ }
+ }
+ else
+ {
+ sprintf(desc, "None");
+ }
+ }
+ else
+ {
+ sprintf(desc, "None");
+ }
+ }
+ else
+ {
+ sprintf(desc, "Unknown");
+ }
+
+ return desc;
+}
+
+/* Build Lua table from crypto data */
+static void iwinfo_L_cryptotable(lua_State *L, struct iwinfo_crypto_entry *c)
+{
+ int i, j;
+
+ lua_newtable(L);
+
+ lua_pushboolean(L, c->enabled);
+ lua_setfield(L, -2, "enabled");
+
+ lua_pushstring(L, iwinfo_crypto_desc(c));
+ lua_setfield(L, -2, "description");
+
+ lua_pushboolean(L, (c->enabled && !c->wpa_version));
+ lua_setfield(L, -2, "wep");
+
+ lua_pushinteger(L, c->wpa_version);
+ lua_setfield(L, -2, "wpa");
+
+ lua_newtable(L);
+ for (i = 0, j = 1; i < 8; i++)
+ {
+ if (c->pair_ciphers & (1 << i))
+ {
+ lua_pushstring(L, IWINFO_CIPHER_NAMES[i]);
+ lua_rawseti(L, -2, j++);
+ }
+ }
+ lua_setfield(L, -2, "pair_ciphers");
+
+ lua_newtable(L);
+ for (i = 0, j = 1; i < 8; i++)
+ {
+ if (c->group_ciphers & (1 << i))
+ {
+ lua_pushstring(L, IWINFO_CIPHER_NAMES[i]);
+ lua_rawseti(L, -2, j++);
+ }
+ }
+ lua_setfield(L, -2, "group_ciphers");
+
+ lua_newtable(L);
+ for (i = 0, j = 1; i < 8; i++)
+ {
+ if (c->auth_suites & (1 << i))
+ {
+ lua_pushstring(L, IWINFO_KMGMT_NAMES[i]);
+ lua_rawseti(L, -2, j++);
+ }
+ }
+ lua_setfield(L, -2, "auth_suites");
+
+ lua_newtable(L);
+ for (i = 0, j = 1; i < 8; i++)
+ {
+ if (c->auth_algs & (1 << i))
+ {
+ lua_pushstring(L, IWINFO_AUTH_NAMES[i]);
+ lua_rawseti(L, -2, j++);
+ }
+ }
+ lua_setfield(L, -2, "auth_algs");
+}
+
+
+/* Wrapper for mode */
+static int iwinfo_L_mode(lua_State *L, int (*func)(const char *, int *))
+{
+ int mode;
+ const char *ifname = luaL_checkstring(L, 1);
+
+ if ((*func)(ifname, &mode))
+ mode = IWINFO_OPMODE_UNKNOWN;
+
+ lua_pushstring(L, IWINFO_OPMODE_NAMES[mode]);
+ return 1;
+}
+
+/* Wrapper for assoclist */
+static int iwinfo_L_assoclist(lua_State *L, int (*func)(const char *, char *, int *))
+{
+ int i, len;
+ char rv[IWINFO_BUFSIZE];
+ char macstr[18];
+ const char *ifname = luaL_checkstring(L, 1);
+ struct iwinfo_assoclist_entry *e;
+
+ lua_newtable(L);
+ memset(rv, 0, sizeof(rv));
+
+ if (!(*func)(ifname, rv, &len))
+ {
+ for (i = 0; i < len; i += sizeof(struct iwinfo_assoclist_entry))
+ {
+ e = (struct iwinfo_assoclist_entry *) &rv[i];
+
+ sprintf(macstr, "%02X:%02X:%02X:%02X:%02X:%02X",
+ e->mac[0], e->mac[1], e->mac[2],
+ e->mac[3], e->mac[4], e->mac[5]);
+
+ lua_newtable(L);
+
+ lua_pushnumber(L, e->signal);
+ lua_setfield(L, -2, "signal");
+
+ lua_pushnumber(L, e->noise);
+ lua_setfield(L, -2, "noise");
+
+ lua_pushnumber(L, e->inactive);
+ lua_setfield(L, -2, "inactive");
+
+ lua_pushnumber(L, e->rx_packets);
+ lua_setfield(L, -2, "rx_packets");
+
+ lua_pushnumber(L, e->tx_packets);
+ lua_setfield(L, -2, "tx_packets");
+
+ lua_pushnumber(L, e->rx_rate.rate);
+ lua_setfield(L, -2, "rx_rate");
+
+ lua_pushnumber(L, e->tx_rate.rate);
+ lua_setfield(L, -2, "tx_rate");
+
+ if (e->rx_rate.mcs >= 0)
+ {
+ lua_pushnumber(L, e->rx_rate.mcs);
+ lua_setfield(L, -2, "rx_mcs");
+
+ lua_pushboolean(L, e->rx_rate.is_40mhz);
+ lua_setfield(L, -2, "rx_40mhz");
+
+ lua_pushboolean(L, e->rx_rate.is_short_gi);
+ lua_setfield(L, -2, "rx_short_gi");
+ }
+
+ if (e->tx_rate.mcs >= 0)
+ {
+ lua_pushnumber(L, e->tx_rate.mcs);
+ lua_setfield(L, -2, "tx_mcs");
+
+ lua_pushboolean(L, e->tx_rate.is_40mhz);
+ lua_setfield(L, -2, "tx_40mhz");
+
+ lua_pushboolean(L, e->tx_rate.is_short_gi);
+ lua_setfield(L, -2, "tx_short_gi");
+ }
+
+ lua_setfield(L, -2, macstr);
+ }
+ }
+
+ return 1;
+}
+
+/* Wrapper for tx power list */
+static int iwinfo_L_txpwrlist(lua_State *L, int (*func)(const char *, char *, int *))
+{
+ int i, x, len;
+ char rv[IWINFO_BUFSIZE];
+ const char *ifname = luaL_checkstring(L, 1);
+ struct iwinfo_txpwrlist_entry *e;
+
+ memset(rv, 0, sizeof(rv));
+
+ if (!(*func)(ifname, rv, &len))
+ {
+ lua_newtable(L);
+
+ for (i = 0, x = 1; i < len; i += sizeof(struct iwinfo_txpwrlist_entry), x++)
+ {
+ e = (struct iwinfo_txpwrlist_entry *) &rv[i];
+
+ lua_newtable(L);
+
+ lua_pushnumber(L, e->mw);
+ lua_setfield(L, -2, "mw");
+
+ lua_pushnumber(L, e->dbm);
+ lua_setfield(L, -2, "dbm");
+
+ lua_rawseti(L, -2, x);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Wrapper for scan list */
+static int iwinfo_L_scanlist(lua_State *L, int (*func)(const char *, char *, int *))
+{
+ int i, x, len;
+ char rv[IWINFO_BUFSIZE];
+ char macstr[18];
+ const char *ifname = luaL_checkstring(L, 1);
+ struct iwinfo_scanlist_entry *e;
+
+ lua_newtable(L);
+ memset(rv, 0, sizeof(rv));
+
+ if (!(*func)(ifname, rv, &len))
+ {
+ for (i = 0, x = 1; i < len; i += sizeof(struct iwinfo_scanlist_entry), x++)
+ {
+ e = (struct iwinfo_scanlist_entry *) &rv[i];
+
+ lua_newtable(L);
+
+ /* BSSID */
+ sprintf(macstr, "%02X:%02X:%02X:%02X:%02X:%02X",
+ e->mac[0], e->mac[1], e->mac[2],
+ e->mac[3], e->mac[4], e->mac[5]);
+
+ lua_pushstring(L, macstr);
+ lua_setfield(L, -2, "bssid");
+
+ /* ESSID */
+ if (e->ssid[0])
+ {
+ lua_pushstring(L, (char *) e->ssid);
+ lua_setfield(L, -2, "ssid");
+ }
+
+ /* Channel */
+ lua_pushinteger(L, e->channel);
+ lua_setfield(L, -2, "channel");
+
+ /* Mode */
+ lua_pushstring(L, IWINFO_OPMODE_NAMES[e->mode]);
+ lua_setfield(L, -2, "mode");
+
+ /* Quality, Signal */
+ lua_pushinteger(L, e->quality);
+ lua_setfield(L, -2, "quality");
+
+ lua_pushinteger(L, e->quality_max);
+ lua_setfield(L, -2, "quality_max");
+
+ lua_pushnumber(L, (e->signal - 0x100));
+ lua_setfield(L, -2, "signal");
+
+ /* Crypto */
+ iwinfo_L_cryptotable(L, &e->crypto);
+ lua_setfield(L, -2, "encryption");
+
+ lua_rawseti(L, -2, x);
+ }
+ }
+
+ return 1;
+}
+
+/* Wrapper for frequency list */
+static int iwinfo_L_freqlist(lua_State *L, int (*func)(const char *, char *, int *))
+{
+ int i, x, len;
+ char rv[IWINFO_BUFSIZE];
+ const char *ifname = luaL_checkstring(L, 1);
+ struct iwinfo_freqlist_entry *e;
+
+ lua_newtable(L);
+ memset(rv, 0, sizeof(rv));
+
+ if (!(*func)(ifname, rv, &len))
+ {
+ for (i = 0, x = 1; i < len; i += sizeof(struct iwinfo_freqlist_entry), x++)
+ {
+ e = (struct iwinfo_freqlist_entry *) &rv[i];
+
+ lua_newtable(L);
+
+ /* MHz */
+ lua_pushinteger(L, e->mhz);
+ lua_setfield(L, -2, "mhz");
+
+ /* Channel */
+ lua_pushinteger(L, e->channel);
+ lua_setfield(L, -2, "channel");
+
+ /* Restricted (DFS/TPC/Radar) */
+ lua_pushboolean(L, e->restricted);
+ lua_setfield(L, -2, "restricted");
+
+ lua_rawseti(L, -2, x);
+ }
+ }
+
+ return 1;
+}
+
+/* Wrapper for crypto settings */
+static int iwinfo_L_encryption(lua_State *L, int (*func)(const char *, char *))
+{
+ const char *ifname = luaL_checkstring(L, 1);
+ struct iwinfo_crypto_entry c = { 0 };
+
+ if (!(*func)(ifname, (char *)&c))
+ {
+ iwinfo_L_cryptotable(L, &c);
+ return 1;
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+/* Wrapper for hwmode list */
+static int iwinfo_L_hwmodelist(lua_State *L, int (*func)(const char *, int *))
+{
+ const char *ifname = luaL_checkstring(L, 1);
+ int hwmodes = 0;
+
+ if (!(*func)(ifname, &hwmodes))
+ {
+ lua_newtable(L);
+
+ lua_pushboolean(L, hwmodes & IWINFO_80211_A);
+ lua_setfield(L, -2, "a");
+
+ lua_pushboolean(L, hwmodes & IWINFO_80211_B);
+ lua_setfield(L, -2, "b");
+
+ lua_pushboolean(L, hwmodes & IWINFO_80211_G);
+ lua_setfield(L, -2, "g");
+
+ lua_pushboolean(L, hwmodes & IWINFO_80211_N);
+ lua_setfield(L, -2, "n");
+
+ return 1;
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+/* Wrapper for mbssid_support */
+static int iwinfo_L_mbssid_support(lua_State *L, int (*func)(const char *, int *))
+{
+ const char *ifname = luaL_checkstring(L, 1);
+ int support = 0;
+
+ if (!(*func)(ifname, &support))
+ {
+ lua_pushboolean(L, support);
+ return 1;
+ }
+
+ lua_pushnil(L);
+ return 1;
+}
+
+/* Wrapper for hardware_id */
+static int iwinfo_L_hardware_id(lua_State *L, int (*func)(const char *, char *))
+{
+ const char *ifname = luaL_checkstring(L, 1);
+ struct iwinfo_hardware_id ids;
+
+ if (!(*func)(ifname, (char *)&ids))
+ {
+ lua_newtable(L);
+
+ lua_pushnumber(L, ids.vendor_id);
+ lua_setfield(L, -2, "vendor_id");
+
+ lua_pushnumber(L, ids.device_id);
+ lua_setfield(L, -2, "device_id");
+
+ lua_pushnumber(L, ids.subsystem_vendor_id);
+ lua_setfield(L, -2, "subsystem_vendor_id");
+
+ lua_pushnumber(L, ids.subsystem_device_id);
+ lua_setfield(L, -2, "subsystem_device_id");
+ }
+ else
+ {
+ lua_pushnil(L);
+ }
+
+ return 1;
+}
+
+/* Wrapper for country list */
+static char * iwinfo_L_country_lookup(char *buf, int len, int iso3166)
+{
+ int i;
+ struct iwinfo_country_entry *c;
+
+ for (i = 0; i < len; i += sizeof(struct iwinfo_country_entry))
+ {
+ c = (struct iwinfo_country_entry *) &buf[i];
+
+ if (c->iso3166 == iso3166)
+ return c->ccode;
+ }
+
+ return NULL;
+}
+
+static int iwinfo_L_countrylist(lua_State *L, int (*func)(const char *, char *, int *))
+{
+ int len, i, j;
+ char rv[IWINFO_BUFSIZE], alpha2[3];
+ char *ccode;
+ const char *ifname = luaL_checkstring(L, 1);
+ const struct iwinfo_iso3166_label *l;
+
+ lua_newtable(L);
+ memset(rv, 0, sizeof(rv));
+
+ if (!(*func)(ifname, rv, &len))
+ {
+ for (l = IWINFO_ISO3166_NAMES, j = 1; l->iso3166; l++)
+ {
+ if ((ccode = iwinfo_L_country_lookup(rv, len, l->iso3166)) != NULL)
+ {
+ sprintf(alpha2, "%c%c",
+ (l->iso3166 / 256), (l->iso3166 % 256));
+
+ lua_newtable(L);
+
+ lua_pushstring(L, alpha2);
+ lua_setfield(L, -2, "alpha2");
+
+ lua_pushstring(L, ccode);
+ lua_setfield(L, -2, "ccode");
+
+ lua_pushstring(L, l->name);
+ lua_setfield(L, -2, "name");
+
+ lua_rawseti(L, -2, j++);
+ }
+ }
+ }
+
+ return 1;
+}
+
+
+#ifdef USE_WL
+/* Broadcom */
+LUA_WRAP_INT(wl,channel)
+LUA_WRAP_INT(wl,frequency)
+LUA_WRAP_INT(wl,frequency_offset)
+LUA_WRAP_INT(wl,txpower)
+LUA_WRAP_INT(wl,txpower_offset)
+LUA_WRAP_INT(wl,bitrate)
+LUA_WRAP_INT(wl,signal)
+LUA_WRAP_INT(wl,noise)
+LUA_WRAP_INT(wl,quality)
+LUA_WRAP_INT(wl,quality_max)
+LUA_WRAP_STRING(wl,ssid)
+LUA_WRAP_STRING(wl,bssid)
+LUA_WRAP_STRING(wl,country)
+LUA_WRAP_STRING(wl,hardware_name)
+LUA_WRAP_STRUCT(wl,mode)
+LUA_WRAP_STRUCT(wl,assoclist)
+LUA_WRAP_STRUCT(wl,txpwrlist)
+LUA_WRAP_STRUCT(wl,scanlist)
+LUA_WRAP_STRUCT(wl,freqlist)
+LUA_WRAP_STRUCT(wl,countrylist)
+LUA_WRAP_STRUCT(wl,hwmodelist)
+LUA_WRAP_STRUCT(wl,encryption)
+LUA_WRAP_STRUCT(wl,mbssid_support)
+LUA_WRAP_STRUCT(wl,hardware_id)
+#endif
+
+#ifdef USE_MADWIFI
+/* Madwifi */
+LUA_WRAP_INT(madwifi,channel)
+LUA_WRAP_INT(madwifi,frequency)
+LUA_WRAP_INT(madwifi,frequency_offset)
+LUA_WRAP_INT(madwifi,txpower)
+LUA_WRAP_INT(madwifi,txpower_offset)
+LUA_WRAP_INT(madwifi,bitrate)
+LUA_WRAP_INT(madwifi,signal)
+LUA_WRAP_INT(madwifi,noise)
+LUA_WRAP_INT(madwifi,quality)
+LUA_WRAP_INT(madwifi,quality_max)
+LUA_WRAP_STRING(madwifi,ssid)
+LUA_WRAP_STRING(madwifi,bssid)
+LUA_WRAP_STRING(madwifi,country)
+LUA_WRAP_STRING(madwifi,hardware_name)
+LUA_WRAP_STRUCT(madwifi,mode)
+LUA_WRAP_STRUCT(madwifi,assoclist)
+LUA_WRAP_STRUCT(madwifi,txpwrlist)
+LUA_WRAP_STRUCT(madwifi,scanlist)
+LUA_WRAP_STRUCT(madwifi,freqlist)
+LUA_WRAP_STRUCT(madwifi,countrylist)
+LUA_WRAP_STRUCT(madwifi,hwmodelist)
+LUA_WRAP_STRUCT(madwifi,encryption)
+LUA_WRAP_STRUCT(madwifi,mbssid_support)
+LUA_WRAP_STRUCT(madwifi,hardware_id)
+#endif
+
+#ifdef USE_NL80211
+/* NL80211 */
+LUA_WRAP_INT(nl80211,channel)
+LUA_WRAP_INT(nl80211,frequency)
+LUA_WRAP_INT(nl80211,frequency_offset)
+LUA_WRAP_INT(nl80211,txpower)
+LUA_WRAP_INT(nl80211,txpower_offset)
+LUA_WRAP_INT(nl80211,bitrate)
+LUA_WRAP_INT(nl80211,signal)
+LUA_WRAP_INT(nl80211,noise)
+LUA_WRAP_INT(nl80211,quality)
+LUA_WRAP_INT(nl80211,quality_max)
+LUA_WRAP_STRING(nl80211,ssid)
+LUA_WRAP_STRING(nl80211,bssid)
+LUA_WRAP_STRING(nl80211,country)
+LUA_WRAP_STRING(nl80211,hardware_name)
+LUA_WRAP_STRUCT(nl80211,mode)
+LUA_WRAP_STRUCT(nl80211,assoclist)
+LUA_WRAP_STRUCT(nl80211,txpwrlist)
+LUA_WRAP_STRUCT(nl80211,scanlist)
+LUA_WRAP_STRUCT(nl80211,freqlist)
+LUA_WRAP_STRUCT(nl80211,countrylist)
+LUA_WRAP_STRUCT(nl80211,hwmodelist)
+LUA_WRAP_STRUCT(nl80211,encryption)
+LUA_WRAP_STRUCT(nl80211,mbssid_support)
+LUA_WRAP_STRUCT(nl80211,hardware_id)
+#endif
+
+/* Wext */
+LUA_WRAP_INT(wext,channel)
+LUA_WRAP_INT(wext,frequency)
+LUA_WRAP_INT(wext,frequency_offset)
+LUA_WRAP_INT(wext,txpower)
+LUA_WRAP_INT(wext,txpower_offset)
+LUA_WRAP_INT(wext,bitrate)
+LUA_WRAP_INT(wext,signal)
+LUA_WRAP_INT(wext,noise)
+LUA_WRAP_INT(wext,quality)
+LUA_WRAP_INT(wext,quality_max)
+LUA_WRAP_STRING(wext,ssid)
+LUA_WRAP_STRING(wext,bssid)
+LUA_WRAP_STRING(wext,country)
+LUA_WRAP_STRING(wext,hardware_name)
+LUA_WRAP_STRUCT(wext,mode)
+LUA_WRAP_STRUCT(wext,assoclist)
+LUA_WRAP_STRUCT(wext,txpwrlist)
+LUA_WRAP_STRUCT(wext,scanlist)
+LUA_WRAP_STRUCT(wext,freqlist)
+LUA_WRAP_STRUCT(wext,countrylist)
+LUA_WRAP_STRUCT(wext,hwmodelist)
+LUA_WRAP_STRUCT(wext,encryption)
+LUA_WRAP_STRUCT(wext,mbssid_support)
+LUA_WRAP_STRUCT(wext,hardware_id)
+
+#ifdef USE_WL
+/* Broadcom table */
+static const luaL_reg R_wl[] = {
+ LUA_REG(wl,channel),
+ LUA_REG(wl,frequency),
+ LUA_REG(wl,frequency_offset),
+ LUA_REG(wl,txpower),
+ LUA_REG(wl,txpower_offset),
+ LUA_REG(wl,bitrate),
+ LUA_REG(wl,signal),
+ LUA_REG(wl,noise),
+ LUA_REG(wl,quality),
+ LUA_REG(wl,quality_max),
+ LUA_REG(wl,mode),
+ LUA_REG(wl,ssid),
+ LUA_REG(wl,bssid),
+ LUA_REG(wl,country),
+ LUA_REG(wl,assoclist),
+ LUA_REG(wl,txpwrlist),
+ LUA_REG(wl,scanlist),
+ LUA_REG(wl,freqlist),
+ LUA_REG(wl,countrylist),
+ LUA_REG(wl,hwmodelist),
+ LUA_REG(wl,encryption),
+ LUA_REG(wl,mbssid_support),
+ LUA_REG(wl,hardware_id),
+ LUA_REG(wl,hardware_name),
+ { NULL, NULL }
+};
+#endif
+
+#ifdef USE_MADWIFI
+/* Madwifi table */
+static const luaL_reg R_madwifi[] = {
+ LUA_REG(madwifi,channel),
+ LUA_REG(madwifi,frequency),
+ LUA_REG(madwifi,frequency_offset),
+ LUA_REG(madwifi,txpower),
+ LUA_REG(madwifi,txpower_offset),
+ LUA_REG(madwifi,bitrate),
+ LUA_REG(madwifi,signal),
+ LUA_REG(madwifi,noise),
+ LUA_REG(madwifi,quality),
+ LUA_REG(madwifi,quality_max),
+ LUA_REG(madwifi,mode),
+ LUA_REG(madwifi,ssid),
+ LUA_REG(madwifi,bssid),
+ LUA_REG(madwifi,country),
+ LUA_REG(madwifi,assoclist),
+ LUA_REG(madwifi,txpwrlist),
+ LUA_REG(madwifi,scanlist),
+ LUA_REG(madwifi,freqlist),
+ LUA_REG(madwifi,countrylist),
+ LUA_REG(madwifi,hwmodelist),
+ LUA_REG(madwifi,encryption),
+ LUA_REG(madwifi,mbssid_support),
+ LUA_REG(madwifi,hardware_id),
+ LUA_REG(madwifi,hardware_name),
+ { NULL, NULL }
+};
+#endif
+
+#ifdef USE_NL80211
+/* NL80211 table */
+static const luaL_reg R_nl80211[] = {
+ LUA_REG(nl80211,channel),
+ LUA_REG(nl80211,frequency),
+ LUA_REG(nl80211,frequency_offset),
+ LUA_REG(nl80211,txpower),
+ LUA_REG(nl80211,txpower_offset),
+ LUA_REG(nl80211,bitrate),
+ LUA_REG(nl80211,signal),
+ LUA_REG(nl80211,noise),
+ LUA_REG(nl80211,quality),
+ LUA_REG(nl80211,quality_max),
+ LUA_REG(nl80211,mode),
+ LUA_REG(nl80211,ssid),
+ LUA_REG(nl80211,bssid),
+ LUA_REG(nl80211,country),
+ LUA_REG(nl80211,assoclist),
+ LUA_REG(nl80211,txpwrlist),
+ LUA_REG(nl80211,scanlist),
+ LUA_REG(nl80211,freqlist),
+ LUA_REG(nl80211,countrylist),
+ LUA_REG(nl80211,hwmodelist),
+ LUA_REG(nl80211,encryption),
+ LUA_REG(nl80211,mbssid_support),
+ LUA_REG(nl80211,hardware_id),
+ LUA_REG(nl80211,hardware_name),
+ { NULL, NULL }
+};
+#endif
+
+/* Wext table */
+static const luaL_reg R_wext[] = {
+ LUA_REG(wext,channel),
+ LUA_REG(wext,frequency),
+ LUA_REG(wext,frequency_offset),
+ LUA_REG(wext,txpower),
+ LUA_REG(wext,txpower_offset),
+ LUA_REG(wext,bitrate),
+ LUA_REG(wext,signal),
+ LUA_REG(wext,noise),
+ LUA_REG(wext,quality),
+ LUA_REG(wext,quality_max),
+ LUA_REG(wext,mode),
+ LUA_REG(wext,ssid),
+ LUA_REG(wext,bssid),
+ LUA_REG(wext,country),
+ LUA_REG(wext,assoclist),
+ LUA_REG(wext,txpwrlist),
+ LUA_REG(wext,scanlist),
+ LUA_REG(wext,freqlist),
+ LUA_REG(wext,countrylist),
+ LUA_REG(wext,hwmodelist),
+ LUA_REG(wext,encryption),
+ LUA_REG(wext,mbssid_support),
+ LUA_REG(wext,hardware_id),
+ LUA_REG(wext,hardware_name),
+ { NULL, NULL }
+};
+
+/* Common */
+static const luaL_reg R_common[] = {
+ { "type", iwinfo_L_type },
+ { "__gc", iwinfo_L__gc },
+ { NULL, NULL }
+};
+
+
+LUALIB_API int luaopen_iwinfo(lua_State *L) {
+ luaL_register(L, IWINFO_META, R_common);
+
+#ifdef USE_WL
+ luaL_newmetatable(L, IWINFO_WL_META);
+ luaL_register(L, NULL, R_wl);
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -2, "__index");
+ lua_setfield(L, -2, "wl");
+#endif
+
+#ifdef USE_MADWIFI
+ luaL_newmetatable(L, IWINFO_MADWIFI_META);
+ luaL_register(L, NULL, R_madwifi);
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -2, "__index");
+ lua_setfield(L, -2, "madwifi");
+#endif
+
+#ifdef USE_NL80211
+ luaL_newmetatable(L, IWINFO_NL80211_META);
+ luaL_register(L, NULL, R_nl80211);
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -2, "__index");
+ lua_setfield(L, -2, "nl80211");
+#endif
+
+ luaL_newmetatable(L, IWINFO_WEXT_META);
+ luaL_register(L, NULL, R_wext);
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -2, "__index");
+ lua_setfield(L, -2, "wext");
+
+ return 1;
+}
diff --git a/package/iwinfo/src/iwinfo_madwifi.c b/package/iwinfo/src/iwinfo_madwifi.c
new file mode 100644
index 000000000..832f40bd3
--- /dev/null
+++ b/package/iwinfo/src/iwinfo_madwifi.c
@@ -0,0 +1,1082 @@
+/*
+ * iwinfo - Wireless Information Library - Madwifi Backend
+ *
+ * Copyright (C) 2009-2010 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * The iwinfo library 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.
+ *
+ * The iwinfo library 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 the iwinfo library. If not, see http://www.gnu.org/licenses/.
+ *
+ * The signal handling code is derived from the official madwifi tools,
+ * wlanconfig.c in particular. The encryption property handling was
+ * inspired by the hostapd madwifi driver.
+ */
+
+#include "iwinfo/madwifi.h"
+#include "iwinfo/wext.h"
+
+
+/*
+ * Madwifi ISO 3166 to Country/Region Code mapping.
+ */
+
+static struct ISO3166_to_CCode
+{
+ u_int16_t iso3166;
+ u_int16_t ccode;
+} CountryCodes[] = {
+ { 0x3030 /* 00 */, 0 }, /* World */
+ { 0x4145 /* AE */, 784 }, /* U.A.E. */
+ { 0x414C /* AL */, 8 }, /* Albania */
+ { 0x414D /* AM */, 51 }, /* Armenia */
+ { 0x4152 /* AR */, 32 }, /* Argentina */
+ { 0x4154 /* AT */, 40 }, /* Austria */
+ { 0x4155 /* AU */, 36 }, /* Australia */
+ { 0x415A /* AZ */, 31 }, /* Azerbaijan */
+ { 0x4245 /* BE */, 56 }, /* Belgium */
+ { 0x4247 /* BG */, 100 }, /* Bulgaria */
+ { 0x4248 /* BH */, 48 }, /* Bahrain */
+ { 0x424E /* BN */, 96 }, /* Brunei Darussalam */
+ { 0x424F /* BO */, 68 }, /* Bolivia */
+ { 0x4252 /* BR */, 76 }, /* Brazil */
+ { 0x4259 /* BY */, 112 }, /* Belarus */
+ { 0x425A /* BZ */, 84 }, /* Belize */
+ { 0x4341 /* CA */, 124 }, /* Canada */
+ { 0x4348 /* CH */, 756 }, /* Switzerland */
+ { 0x434C /* CL */, 152 }, /* Chile */
+ { 0x434E /* CN */, 156 }, /* People's Republic of China */
+ { 0x434F /* CO */, 170 }, /* Colombia */
+ { 0x4352 /* CR */, 188 }, /* Costa Rica */
+ { 0x4359 /* CY */, 196 }, /* Cyprus */
+ { 0x435A /* CZ */, 203 }, /* Czech Republic */
+ { 0x4445 /* DE */, 276 }, /* Germany */
+ { 0x444B /* DK */, 208 }, /* Denmark */
+ { 0x444F /* DO */, 214 }, /* Dominican Republic */
+ { 0x445A /* DZ */, 12 }, /* Algeria */
+ { 0x4543 /* EC */, 218 }, /* Ecuador */
+ { 0x4545 /* EE */, 233 }, /* Estonia */
+ { 0x4547 /* EG */, 818 }, /* Egypt */
+ { 0x4553 /* ES */, 724 }, /* Spain */
+ { 0x4649 /* FI */, 246 }, /* Finland */
+ { 0x464F /* FO */, 234 }, /* Faeroe Islands */
+ { 0x4652 /* FR */, 250 }, /* France */
+ { 0x4652 /* FR */, 255 }, /* France2 */
+ { 0x4742 /* GB */, 826 }, /* United Kingdom */
+ { 0x4745 /* GE */, 268 }, /* Georgia */
+ { 0x4752 /* GR */, 300 }, /* Greece */
+ { 0x4754 /* GT */, 320 }, /* Guatemala */
+ { 0x484B /* HK */, 344 }, /* Hong Kong S.A.R., P.R.C. */
+ { 0x484E /* HN */, 340 }, /* Honduras */
+ { 0x4852 /* HR */, 191 }, /* Croatia */
+ { 0x4855 /* HU */, 348 }, /* Hungary */
+ { 0x4944 /* ID */, 360 }, /* Indonesia */
+ { 0x4945 /* IE */, 372 }, /* Ireland */
+ { 0x494C /* IL */, 376 }, /* Israel */
+ { 0x494E /* IN */, 356 }, /* India */
+ { 0x4951 /* IQ */, 368 }, /* Iraq */
+ { 0x4952 /* IR */, 364 }, /* Iran */
+ { 0x4953 /* IS */, 352 }, /* Iceland */
+ { 0x4954 /* IT */, 380 }, /* Italy */
+ { 0x4A4D /* JM */, 388 }, /* Jamaica */
+ { 0x4A4F /* JO */, 400 }, /* Jordan */
+ { 0x4A50 /* JP */, 392 }, /* Japan */
+ { 0x4A50 /* JP */, 393 }, /* Japan (JP1) */
+ { 0x4A50 /* JP */, 394 }, /* Japan (JP0) */
+ { 0x4A50 /* JP */, 395 }, /* Japan (JP1-1) */
+ { 0x4A50 /* JP */, 396 }, /* Japan (JE1) */
+ { 0x4A50 /* JP */, 397 }, /* Japan (JE2) */
+ { 0x4A50 /* JP */, 399 }, /* Japan (JP6) */
+ { 0x4A50 /* JP */, 900 }, /* Japan */
+ { 0x4A50 /* JP */, 901 }, /* Japan */
+ { 0x4A50 /* JP */, 902 }, /* Japan */
+ { 0x4A50 /* JP */, 903 }, /* Japan */
+ { 0x4A50 /* JP */, 904 }, /* Japan */
+ { 0x4A50 /* JP */, 905 }, /* Japan */
+ { 0x4A50 /* JP */, 906 }, /* Japan */
+ { 0x4A50 /* JP */, 907 }, /* Japan */
+ { 0x4A50 /* JP */, 908 }, /* Japan */
+ { 0x4A50 /* JP */, 909 }, /* Japan */
+ { 0x4A50 /* JP */, 910 }, /* Japan */
+ { 0x4A50 /* JP */, 911 }, /* Japan */
+ { 0x4A50 /* JP */, 912 }, /* Japan */
+ { 0x4A50 /* JP */, 913 }, /* Japan */
+ { 0x4A50 /* JP */, 914 }, /* Japan */
+ { 0x4A50 /* JP */, 915 }, /* Japan */
+ { 0x4A50 /* JP */, 916 }, /* Japan */
+ { 0x4A50 /* JP */, 917 }, /* Japan */
+ { 0x4A50 /* JP */, 918 }, /* Japan */
+ { 0x4A50 /* JP */, 919 }, /* Japan */
+ { 0x4A50 /* JP */, 920 }, /* Japan */
+ { 0x4A50 /* JP */, 921 }, /* Japan */
+ { 0x4A50 /* JP */, 922 }, /* Japan */
+ { 0x4A50 /* JP */, 923 }, /* Japan */
+ { 0x4A50 /* JP */, 924 }, /* Japan */
+ { 0x4A50 /* JP */, 925 }, /* Japan */
+ { 0x4A50 /* JP */, 926 }, /* Japan */
+ { 0x4A50 /* JP */, 927 }, /* Japan */
+ { 0x4A50 /* JP */, 928 }, /* Japan */
+ { 0x4A50 /* JP */, 929 }, /* Japan */
+ { 0x4A50 /* JP */, 930 }, /* Japan */
+ { 0x4A50 /* JP */, 931 }, /* Japan */
+ { 0x4A50 /* JP */, 932 }, /* Japan */
+ { 0x4A50 /* JP */, 933 }, /* Japan */
+ { 0x4A50 /* JP */, 934 }, /* Japan */
+ { 0x4A50 /* JP */, 935 }, /* Japan */
+ { 0x4A50 /* JP */, 936 }, /* Japan */
+ { 0x4A50 /* JP */, 937 }, /* Japan */
+ { 0x4A50 /* JP */, 938 }, /* Japan */
+ { 0x4A50 /* JP */, 939 }, /* Japan */
+ { 0x4A50 /* JP */, 940 }, /* Japan */
+ { 0x4A50 /* JP */, 941 }, /* Japan */
+ { 0x4B45 /* KE */, 404 }, /* Kenya */
+ { 0x4B50 /* KP */, 408 }, /* North Korea */
+ { 0x4B52 /* KR */, 410 }, /* South Korea */
+ { 0x4B52 /* KR */, 411 }, /* South Korea */
+ { 0x4B57 /* KW */, 414 }, /* Kuwait */
+ { 0x4B5A /* KZ */, 398 }, /* Kazakhstan */
+ { 0x4C42 /* LB */, 422 }, /* Lebanon */
+ { 0x4C49 /* LI */, 438 }, /* Liechtenstein */
+ { 0x4C54 /* LT */, 440 }, /* Lithuania */
+ { 0x4C55 /* LU */, 442 }, /* Luxembourg */
+ { 0x4C56 /* LV */, 428 }, /* Latvia */
+ { 0x4C59 /* LY */, 434 }, /* Libya */
+ { 0x4D41 /* MA */, 504 }, /* Morocco */
+ { 0x4D43 /* MC */, 492 }, /* Principality of Monaco */
+ { 0x4D4B /* MK */, 807 }, /* the Former Yugoslav Republic of Macedonia */
+ { 0x4D4F /* MO */, 446 }, /* Macau */
+ { 0x4D58 /* MX */, 484 }, /* Mexico */
+ { 0x4D59 /* MY */, 458 }, /* Malaysia */
+ { 0x4E49 /* NI */, 558 }, /* Nicaragua */
+ { 0x4E4C /* NL */, 528 }, /* Netherlands */
+ { 0x4E4F /* NO */, 578 }, /* Norway */
+ { 0x4E5A /* NZ */, 554 }, /* New Zealand */
+ { 0x4F4D /* OM */, 512 }, /* Oman */
+ { 0x5041 /* PA */, 591 }, /* Panama */
+ { 0x5045 /* PE */, 604 }, /* Peru */
+ { 0x5048 /* PH */, 608 }, /* Republic of the Philippines */
+ { 0x504B /* PK */, 586 }, /* Islamic Republic of Pakistan */
+ { 0x504C /* PL */, 616 }, /* Poland */
+ { 0x5052 /* PR */, 630 }, /* Puerto Rico */
+ { 0x5054 /* PT */, 620 }, /* Portugal */
+ { 0x5059 /* PY */, 600 }, /* Paraguay */
+ { 0x5141 /* QA */, 634 }, /* Qatar */
+ { 0x524F /* RO */, 642 }, /* Romania */
+ { 0x5255 /* RU */, 643 }, /* Russia */
+ { 0x5341 /* SA */, 682 }, /* Saudi Arabia */
+ { 0x5345 /* SE */, 752 }, /* Sweden */
+ { 0x5347 /* SG */, 702 }, /* Singapore */
+ { 0x5349 /* SI */, 705 }, /* Slovenia */
+ { 0x534B /* SK */, 703 }, /* Slovak Republic */
+ { 0x5356 /* SV */, 222 }, /* El Salvador */
+ { 0x5359 /* SY */, 760 }, /* Syria */
+ { 0x5448 /* TH */, 764 }, /* Thailand */
+ { 0x544E /* TN */, 788 }, /* Tunisia */
+ { 0x5452 /* TR */, 792 }, /* Turkey */
+ { 0x5454 /* TT */, 780 }, /* Trinidad y Tobago */
+ { 0x5457 /* TW */, 158 }, /* Taiwan */
+ { 0x5541 /* UA */, 804 }, /* Ukraine */
+ { 0x554B /* UK */, 826 }, /* United Kingdom */
+ { 0x5553 /* US */, 840 }, /* United States */
+ { 0x5553 /* US */, 842 }, /* United States (Public Safety)*/
+ { 0x5559 /* UY */, 858 }, /* Uruguay */
+ { 0x555A /* UZ */, 860 }, /* Uzbekistan */
+ { 0x5645 /* VE */, 862 }, /* Venezuela */
+ { 0x564E /* VN */, 704 }, /* Viet Nam */
+ { 0x5945 /* YE */, 887 }, /* Yemen */
+ { 0x5A41 /* ZA */, 710 }, /* South Africa */
+ { 0x5A57 /* ZW */, 716 }, /* Zimbabwe */
+};
+
+
+static const char * madwifi_phyname(const char *ifname)
+{
+ static char phyname[IFNAMSIZ];
+
+ if (strlen(ifname) > 5 && !strncmp(ifname, "radio", 5))
+ snprintf(phyname, sizeof(phyname), "wifi%s", ifname + 5);
+ else
+ snprintf(phyname, sizeof(phyname), "%s", ifname);
+
+ return (const char *)phyname;
+}
+
+static int madwifi_wrq(struct iwreq *wrq, const char *ifname, int cmd, void *data, size_t len)
+{
+ strncpy(wrq->ifr_name, ifname, IFNAMSIZ);
+
+ if( data != NULL )
+ {
+ if( len < IFNAMSIZ )
+ {
+ memcpy(wrq->u.name, data, len);
+ }
+ else
+ {
+ wrq->u.data.pointer = data;
+ wrq->u.data.length = len;
+ }
+ }
+
+ return iwinfo_ioctl(cmd, wrq);
+}
+
+static int get80211priv(const char *ifname, int op, void *data, size_t len)
+{
+ struct iwreq iwr;
+
+ if( madwifi_wrq(&iwr, ifname, op, data, len) < 0 )
+ return -1;
+
+ return iwr.u.data.length;
+}
+
+static char * madwifi_isvap(const char *ifname, const char *wifiname)
+{
+ int fd, ln;
+ char path[32];
+ char *ret = NULL;
+ static char name[IFNAMSIZ];
+
+ if( strlen(ifname) <= 9 )
+ {
+ sprintf(path, "/proc/sys/net/%s/%%parent", ifname);
+
+ if( (fd = open(path, O_RDONLY)) > -1 )
+ {
+ if( wifiname != NULL )
+ {
+ if( read(fd, name, strlen(wifiname)) == strlen(wifiname) )
+ ret = strncmp(name, wifiname, strlen(wifiname))
+ ? NULL : name;
+ }
+ else if( (ln = read(fd, name, IFNAMSIZ)) >= 4 )
+ {
+ name[ln-1] = 0;
+ ret = name;
+ }
+
+ (void) close(fd);
+ }
+ }
+
+ return ret;
+}
+
+static int madwifi_iswifi(const char *ifname)
+{
+ int ret;
+ char path[32];
+ struct stat s;
+ const char *phy;
+
+ ret = 0;
+ phy = madwifi_phyname(ifname);
+
+ if( strlen(phy) <= 7 )
+ {
+ sprintf(path, "/proc/sys/dev/%s/diversity", phy);
+
+ if( ! stat(path, &s) )
+ ret = (s.st_mode & S_IFREG);
+ }
+
+ return ret;
+}
+
+static char * madwifi_ifadd(const char *ifname)
+{
+ const char *wifidev = NULL;
+ struct ifreq ifr = { 0 };
+ struct ieee80211_clone_params cp = { 0 };
+ static char nif[IFNAMSIZ] = { 0 };
+
+ if( !(wifidev = madwifi_isvap(ifname, NULL)) && madwifi_iswifi(ifname) )
+ wifidev = madwifi_phyname(ifname);
+
+ if( wifidev )
+ {
+ snprintf(nif, sizeof(nif), "tmp.%s", ifname);
+
+ strncpy(cp.icp_name, nif, IFNAMSIZ);
+ cp.icp_opmode = IEEE80211_M_STA;
+ cp.icp_flags = IEEE80211_CLONE_BSSID;
+
+ strncpy(ifr.ifr_name, wifidev, IFNAMSIZ);
+ ifr.ifr_data = (void *)&cp;
+
+ if( !iwinfo_ioctl(SIOC80211IFCREATE, &ifr) )
+ {
+ return nif;
+ }
+ else
+ {
+ cp.icp_opmode = IEEE80211_M_MONITOR;
+
+ if( !iwinfo_ioctl(SIOC80211IFCREATE, &ifr) )
+ return nif;
+ }
+ }
+
+ return NULL;
+}
+
+static void madwifi_ifdel(const char *ifname)
+{
+ struct ifreq ifr = { 0 };
+
+ strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+ iwinfo_ioctl(SIOC80211IFDESTROY, &ifr);
+}
+
+
+int madwifi_probe(const char *ifname)
+{
+ return ( !!madwifi_isvap(ifname, NULL) || madwifi_iswifi(ifname) );
+}
+
+void madwifi_close(void)
+{
+ /* Nop */
+}
+
+int madwifi_get_mode(const char *ifname, int *buf)
+{
+ return wext_get_mode(ifname, buf);
+}
+
+int madwifi_get_ssid(const char *ifname, char *buf)
+{
+ return wext_get_ssid(ifname, buf);
+}
+
+int madwifi_get_bssid(const char *ifname, char *buf)
+{
+ return wext_get_bssid(ifname, buf);
+}
+
+int madwifi_get_channel(const char *ifname, int *buf)
+{
+ int i;
+ uint16_t freq;
+ struct iwreq wrq;
+ struct ieee80211req_chaninfo chans;
+
+ if( madwifi_wrq(&wrq, ifname, SIOCGIWFREQ, NULL, 0) >= 0 )
+ {
+ /* Madwifi returns a Hz frequency, get it's freq list to find channel index */
+ freq = (uint16_t)(wrq.u.freq.m / 100000);
+
+ if( get80211priv(ifname, IEEE80211_IOCTL_GETCHANINFO, &chans, sizeof(chans)) >= 0 )
+ {
+ *buf = 0;
+
+ for( i = 0; i < chans.ic_nchans; i++ )
+ {
+ if( freq == chans.ic_chans[i].ic_freq )
+ {
+ *buf = chans.ic_chans[i].ic_ieee;
+ break;
+ }
+ }
+
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+int madwifi_get_frequency(const char *ifname, int *buf)
+{
+ struct iwreq wrq;
+
+ if( madwifi_wrq(&wrq, ifname, SIOCGIWFREQ, NULL, 0) >= 0 )
+ {
+ *buf = (uint16_t)(wrq.u.freq.m / 100000);
+ return 0;
+ }
+
+ return -1;
+}
+
+int madwifi_get_txpower(const char *ifname, int *buf)
+{
+ return wext_get_txpower(ifname, buf);
+}
+
+int madwifi_get_bitrate(const char *ifname, int *buf)
+{
+ unsigned int mode, len, rate, rate_count;
+ uint8_t tmp[24*1024];
+ uint8_t *cp;
+ struct iwreq wrq;
+ struct ieee80211req_sta_info *si;
+
+ if( madwifi_wrq(&wrq, ifname, SIOCGIWMODE, NULL, 0) >= 0 )
+ {
+ mode = wrq.u.mode;
+
+ /* Calculate bitrate average from associated stations in ad-hoc mode */
+ if( mode == 1 )
+ {
+ rate = rate_count = 0;
+
+ if( (len = get80211priv(ifname, IEEE80211_IOCTL_STA_INFO, tmp, 24*1024)) > 0 )
+ {
+ cp = tmp;
+
+ do {
+ si = (struct ieee80211req_sta_info *) cp;
+
+ if( si->isi_rssi > 0 )
+ {
+ rate_count++;
+ rate += ((si->isi_rates[si->isi_txrate] & IEEE80211_RATE_VAL) / 2);
+ }
+
+ cp += si->isi_len;
+ len -= si->isi_len;
+ } while (len >= sizeof(struct ieee80211req_sta_info));
+ }
+
+ *buf = (rate == 0 || rate_count == 0) ? 0 : (rate / rate_count) * 1000;
+ return 0;
+ }
+
+ /* Return whatever wext tells us ... */
+ return wext_get_bitrate(ifname, buf);
+ }
+
+ return -1;
+}
+
+int madwifi_get_signal(const char *ifname, int *buf)
+{
+ unsigned int mode, len, rssi, rssi_count;
+ uint8_t tmp[24*1024];
+ uint8_t *cp;
+ struct iwreq wrq;
+ struct ieee80211req_sta_info *si;
+
+ if( madwifi_wrq(&wrq, ifname, SIOCGIWMODE, NULL, 0) >= 0 )
+ {
+ mode = wrq.u.mode;
+
+ /* Calculate signal average from associated stations in ap or ad-hoc mode */
+ if( mode == 1 )
+ {
+ rssi = rssi_count = 0;
+
+ if( (len = get80211priv(ifname, IEEE80211_IOCTL_STA_INFO, tmp, 24*1024)) > 0 )
+ {
+ cp = tmp;
+
+ do {
+ si = (struct ieee80211req_sta_info *) cp;
+
+ if( si->isi_rssi > 0 )
+ {
+ rssi_count++;
+ rssi -= (si->isi_rssi - 95);
+ }
+
+ cp += si->isi_len;
+ len -= si->isi_len;
+ } while (len >= sizeof(struct ieee80211req_sta_info));
+ }
+
+ *buf = (rssi == 0 || rssi_count == 0) ? 1 : -(rssi / rssi_count);
+ return 0;
+ }
+
+ /* Return whatever wext tells us ... */
+ return wext_get_signal(ifname, buf);
+ }
+
+ return -1;
+}
+
+int madwifi_get_noise(const char *ifname, int *buf)
+{
+ return wext_get_noise(ifname, buf);
+}
+
+int madwifi_get_quality(const char *ifname, int *buf)
+{
+ unsigned int mode, len, quality, quality_count;
+ uint8_t tmp[24*1024];
+ uint8_t *cp;
+ struct iwreq wrq;
+ struct ieee80211req_sta_info *si;
+
+ if( madwifi_wrq(&wrq, ifname, SIOCGIWMODE, NULL, 0) >= 0 )
+ {
+ mode = wrq.u.mode;
+
+ /* Calculate signal average from associated stations in ad-hoc mode */
+ if( mode == 1 )
+ {
+ quality = quality_count = 0;
+
+ if( (len = get80211priv(ifname, IEEE80211_IOCTL_STA_INFO, tmp, 24*1024)) > 0 )
+ {
+ cp = tmp;
+
+ do {
+ si = (struct ieee80211req_sta_info *) cp;
+
+ if( si->isi_rssi > 0 )
+ {
+ quality_count++;
+ quality += si->isi_rssi;
+ }
+
+ cp += si->isi_len;
+ len -= si->isi_len;
+ } while (len >= sizeof(struct ieee80211req_sta_info));
+ }
+
+ *buf = (quality == 0 || quality_count == 0) ? 0 : (quality / quality_count);
+ return 0;
+ }
+
+ /* Return whatever wext tells us ... */
+ return wext_get_quality(ifname, buf);
+ }
+
+ return -1;
+}
+
+int madwifi_get_quality_max(const char *ifname, int *buf)
+{
+ return wext_get_quality_max(ifname, buf);
+}
+
+int madwifi_get_encryption(const char *ifname, char *buf)
+{
+ int ciphers = 0, key_len = 0;
+ char keybuf[IW_ENCODING_TOKEN_MAX];
+ struct iwinfo_crypto_entry *c = (struct iwinfo_crypto_entry *)buf;
+ struct iwreq wrq;
+ struct ieee80211req_key wk;
+
+ memset(&wrq, 0, sizeof(wrq));
+
+ /* Obtain key info */
+ if( madwifi_wrq(&wrq, ifname, SIOCGIWENCODE, keybuf, sizeof(keybuf)) < 0 )
+ return -1;
+
+#if 0
+ /* Have any encryption? */
+ if( (wrq.u.data.flags & IW_ENCODE_DISABLED) || (wrq.u.data.length == 0) )
+ return 0;
+#endif
+
+ /* Save key len */
+ key_len = wrq.u.data.length;
+
+ /* Get wpa protocol version */
+ wrq.u.mode = IEEE80211_PARAM_WPA;
+ if( madwifi_wrq(&wrq, ifname, IEEE80211_IOCTL_GETPARAM, NULL, 0) >= 0 )
+ c->wpa_version = wrq.u.mode;
+
+ /* Get authentication suites */
+ wrq.u.mode = IEEE80211_PARAM_AUTHMODE;
+ if( madwifi_wrq(&wrq, ifname, IEEE80211_IOCTL_GETPARAM, NULL, 0) >= 0 )
+ {
+ switch(wrq.u.mode) {
+ case IEEE80211_AUTH_8021X:
+ c->auth_suites |= IWINFO_KMGMT_8021x;
+ break;
+
+ case IEEE80211_AUTH_WPA:
+ c->auth_suites |= IWINFO_KMGMT_PSK;
+ break;
+
+ case IEEE80211_AUTH_OPEN:
+ c->auth_algs |= IWINFO_AUTH_OPEN;
+ break;
+
+ case IEEE80211_AUTH_SHARED:
+ c->auth_algs |= IWINFO_AUTH_SHARED;
+ break;
+
+ default:
+ c->auth_suites |= IWINFO_KMGMT_NONE;
+ break;
+ }
+ }
+
+ memset(&wk, 0, sizeof(wk));
+ memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
+
+ /* Get key information */
+ if( get80211priv(ifname, IEEE80211_IOCTL_GETKEY, &wk, sizeof(wk)) >= 0 )
+ {
+ /* Type 0 == WEP */
+ if( (wk.ik_type == 0) && (c->auth_algs == 0) )
+ c->auth_algs = (IWINFO_AUTH_OPEN | IWINFO_AUTH_SHARED);
+ }
+
+ /* Get used pairwise ciphers */
+ wrq.u.mode = IEEE80211_PARAM_UCASTCIPHERS;
+ if( madwifi_wrq(&wrq, ifname, IEEE80211_IOCTL_GETPARAM, NULL, 0) >= 0 )
+ {
+ ciphers = wrq.u.mode;
+
+ if( c->wpa_version && ciphers & (1 << IEEE80211_CIPHER_TKIP) )
+ c->pair_ciphers |= IWINFO_CIPHER_TKIP;
+
+ if( c->wpa_version && ciphers & (1 << IEEE80211_CIPHER_AES_CCM) )
+ c->pair_ciphers |= IWINFO_CIPHER_CCMP;
+
+ if( c->wpa_version && ciphers & (1 << IEEE80211_CIPHER_AES_OCB) )
+ c->pair_ciphers |= IWINFO_CIPHER_AESOCB;
+
+ if( c->wpa_version && ciphers & (1 << IEEE80211_CIPHER_CKIP) )
+ c->pair_ciphers |= IWINFO_CIPHER_CKIP;
+
+ if( !c->pair_ciphers && ciphers & (1 << IEEE80211_CIPHER_WEP) )
+ {
+ switch(key_len) {
+ case 13:
+ c->pair_ciphers |= IWINFO_CIPHER_WEP104;
+ break;
+
+ case 5:
+ c->pair_ciphers |= IWINFO_CIPHER_WEP40;
+ break;
+
+ case 0:
+ break;
+
+ default:
+ c->pair_ciphers = IWINFO_CIPHER_WEP40 |
+ IWINFO_CIPHER_WEP104;
+ break;
+ }
+ }
+
+ if( ciphers & (1 << IEEE80211_CIPHER_NONE) )
+ c->pair_ciphers |= IWINFO_CIPHER_NONE;
+ }
+
+ /* Get used group cipher */
+ wrq.u.mode = IEEE80211_PARAM_MCASTCIPHER;
+ if( madwifi_wrq(&wrq, ifname, IEEE80211_IOCTL_GETPARAM, NULL, 0) >= 0 )
+ {
+ ciphers = c->wpa_version ? wrq.u.mode : IEEE80211_CIPHER_WEP;
+
+ switch(ciphers) {
+ case IEEE80211_CIPHER_TKIP:
+ c->group_ciphers |= IWINFO_CIPHER_TKIP;
+ break;
+
+ case IEEE80211_CIPHER_AES_CCM:
+ c->group_ciphers |= IWINFO_CIPHER_CCMP;
+ break;
+
+ case IEEE80211_CIPHER_AES_OCB:
+ c->group_ciphers |= IWINFO_CIPHER_AESOCB;
+ break;
+
+ case IEEE80211_CIPHER_CKIP:
+ c->group_ciphers |= IWINFO_CIPHER_CKIP;
+ break;
+
+ case IEEE80211_CIPHER_WEP:
+ switch(key_len) {
+ case 13:
+ c->group_ciphers |= IWINFO_CIPHER_WEP104;
+ break;
+
+ case 5:
+ c->group_ciphers |= IWINFO_CIPHER_WEP40;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case IEEE80211_CIPHER_NONE:
+ c->group_ciphers |= IWINFO_CIPHER_NONE;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ c->enabled = (c->wpa_version || (c->auth_algs && c->pair_ciphers)) ? 1 : 0;
+
+ return 0;
+}
+
+int madwifi_get_assoclist(const char *ifname, char *buf, int *len)
+{
+ int bl, tl, noise;
+ uint8_t *cp;
+ uint8_t tmp[24*1024];
+ struct ieee80211req_sta_info *si;
+ struct iwinfo_assoclist_entry entry;
+
+ if( (tl = get80211priv(ifname, IEEE80211_IOCTL_STA_INFO, tmp, 24*1024)) > 0 )
+ {
+ cp = tmp;
+ bl = 0;
+
+ if( madwifi_get_noise(ifname, &noise) )
+ noise = 0;
+
+ do {
+ si = (struct ieee80211req_sta_info *) cp;
+
+ memset(&entry, 0, sizeof(entry));
+
+ entry.signal = (si->isi_rssi - 95);
+ entry.noise = noise;
+ memcpy(entry.mac, &si->isi_macaddr, 6);
+
+ entry.inactive = si->isi_inact * 1000;
+
+ entry.tx_packets = (si->isi_txseqs[0] & IEEE80211_SEQ_SEQ_MASK)
+ >> IEEE80211_SEQ_SEQ_SHIFT;
+
+ entry.rx_packets = (si->isi_rxseqs[0] & IEEE80211_SEQ_SEQ_MASK)
+ >> IEEE80211_SEQ_SEQ_SHIFT;
+
+ entry.tx_rate.rate =
+ (si->isi_rates[si->isi_txrate] & IEEE80211_RATE_VAL) * 500;
+
+ /* XXX: this is just a guess */
+ entry.rx_rate.rate = entry.tx_rate.rate;
+
+ entry.rx_rate.mcs = -1;
+ entry.tx_rate.mcs = -1;
+
+ memcpy(&buf[bl], &entry, sizeof(struct iwinfo_assoclist_entry));
+
+ bl += sizeof(struct iwinfo_assoclist_entry);
+ cp += si->isi_len;
+ tl -= si->isi_len;
+ } while (tl >= sizeof(struct ieee80211req_sta_info));
+
+ *len = bl;
+ return 0;
+ }
+
+ return -1;
+}
+
+int madwifi_get_txpwrlist(const char *ifname, char *buf, int *len)
+{
+ int rc = -1;
+ char *res;
+
+ /* A wifiX device? */
+ if( madwifi_iswifi(ifname) )
+ {
+ if( (res = madwifi_ifadd(ifname)) != NULL )
+ {
+ rc = wext_get_txpwrlist(res, buf, len);
+ madwifi_ifdel(res);
+ }
+ }
+
+ /* Its an athX ... */
+ else if( !!madwifi_isvap(ifname, NULL) )
+ {
+ rc = wext_get_txpwrlist(ifname, buf, len);
+ }
+
+ return rc;
+}
+
+int madwifi_get_scanlist(const char *ifname, char *buf, int *len)
+{
+ int ret;
+ char *res;
+ DIR *proc;
+ struct dirent *e;
+
+ ret = -1;
+
+ /* We got a wifiX device passed, try to lookup a vap on it */
+ if( madwifi_iswifi(ifname) )
+ {
+ if( (proc = opendir("/proc/sys/net/")) != NULL )
+ {
+ while( (e = readdir(proc)) != NULL )
+ {
+ if( !!madwifi_isvap(e->d_name, ifname) )
+ {
+ if( iwinfo_ifup(e->d_name) )
+ {
+ ret = wext_get_scanlist(e->d_name, buf, len);
+ break;
+ }
+ }
+ }
+
+ closedir(proc);
+ }
+
+ /* Still nothing found, try to create a vap */
+ if( ret == -1 )
+ {
+ if( (res = madwifi_ifadd(ifname)) != NULL )
+ {
+ if( iwinfo_ifup(res) )
+ {
+ wext_get_scanlist(res, buf, len);
+ sleep(1);
+
+ wext_get_scanlist(res, buf, len);
+ sleep(1);
+
+ ret = wext_get_scanlist(res, buf, len);
+ }
+
+ iwinfo_ifdown(res);
+ madwifi_ifdel(res);
+ }
+ }
+ }
+
+ /* Got athX device? */
+ else if( !!madwifi_isvap(ifname, NULL) )
+ {
+ ret = wext_get_scanlist(ifname, buf, len);
+ }
+
+ return ret;
+}
+
+int madwifi_get_freqlist(const char *ifname, char *buf, int *len)
+{
+ int i, bl;
+ int rc = -1;
+ char *res;
+ struct ieee80211req_chaninfo chans;
+ struct iwinfo_freqlist_entry entry;
+
+ /* A wifiX device? */
+ if( madwifi_iswifi(ifname) )
+ {
+ if( (res = madwifi_ifadd(ifname)) != NULL )
+ {
+ rc = get80211priv(res, IEEE80211_IOCTL_GETCHANINFO,
+ &chans, sizeof(chans));
+
+ madwifi_ifdel(res);
+ }
+ }
+
+ /* Its an athX ... */
+ else if( !!madwifi_isvap(ifname, NULL) )
+ {
+ rc = get80211priv(ifname, IEEE80211_IOCTL_GETCHANINFO,
+ &chans, sizeof(chans));
+ }
+
+
+ /* Got chaninfo? */
+ if( rc >= 0 )
+ {
+ bl = 0;
+
+ for( i = 0; i < chans.ic_nchans; i++ )
+ {
+ entry.mhz = chans.ic_chans[i].ic_freq;
+ entry.channel = chans.ic_chans[i].ic_ieee;
+ entry.restricted = 0;
+
+ memcpy(&buf[bl], &entry, sizeof(struct iwinfo_freqlist_entry));
+ bl += sizeof(struct iwinfo_freqlist_entry);
+ }
+
+ *len = bl;
+ return 0;
+ }
+
+ return -1;
+}
+
+int madwifi_get_country(const char *ifname, char *buf)
+{
+ int i, fd, ccode = -1;
+ char buffer[34];
+ char *wifi = madwifi_iswifi(ifname)
+ ? (char *)ifname : madwifi_isvap(ifname, NULL);
+
+ struct ISO3166_to_CCode *e;
+
+ if( wifi )
+ {
+ snprintf(buffer, sizeof(buffer), "/proc/sys/dev/%s/countrycode", wifi);
+
+ if( (fd = open(buffer, O_RDONLY)) > -1 )
+ {
+ memset(buffer, 0, sizeof(buffer));
+
+ if( read(fd, buffer, sizeof(buffer)-1) > 0 )
+ ccode = atoi(buffer);
+
+ close(fd);
+ }
+ }
+
+ for( i = 0; i < (sizeof(CountryCodes)/sizeof(CountryCodes[0])); i++ )
+ {
+ e = &CountryCodes[i];
+
+ if( e->ccode == ccode )
+ {
+ sprintf(buf, "%c%c", e->iso3166 / 256, e->iso3166 % 256);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+int madwifi_get_countrylist(const char *ifname, char *buf, int *len)
+{
+ int i, count;
+ struct ISO3166_to_CCode *e, *p = NULL;
+ struct iwinfo_country_entry *c = (struct iwinfo_country_entry *)buf;
+
+ count = 0;
+
+ for( int i = 0; i < (sizeof(CountryCodes)/sizeof(CountryCodes[0])); i++ )
+ {
+ e = &CountryCodes[i];
+
+ if( !p || (e->iso3166 != p->iso3166) )
+ {
+ c->iso3166 = e->iso3166;
+ snprintf(c->ccode, sizeof(c->ccode), "%i", e->ccode);
+
+ c++;
+ count++;
+ }
+
+ p = e;
+ }
+
+ *len = (count * sizeof(struct iwinfo_country_entry));
+ return 0;
+}
+
+int madwifi_get_hwmodelist(const char *ifname, int *buf)
+{
+ char chans[IWINFO_BUFSIZE] = { 0 };
+ struct iwinfo_freqlist_entry *e = NULL;
+ int len = 0;
+
+ if( !madwifi_get_freqlist(ifname, chans, &len) )
+ {
+ for( e = (struct iwinfo_freqlist_entry *)chans; e->channel; e++ )
+ {
+ if( e->channel <= 14 )
+ {
+ *buf |= IWINFO_80211_B;
+ *buf |= IWINFO_80211_G;
+ }
+ else
+ {
+ *buf |= IWINFO_80211_A;
+ }
+ }
+
+ return 0;
+ }
+
+ return -1;
+}
+
+int madwifi_get_mbssid_support(const char *ifname, int *buf)
+{
+ /* Test whether we can create another interface */
+ char *nif = madwifi_ifadd(ifname);
+
+ if( nif )
+ {
+ *buf = iwinfo_ifup(nif);
+
+ iwinfo_ifdown(nif);
+ madwifi_ifdel(nif);
+
+ return 0;
+ }
+
+ return -1;
+}
+
+int madwifi_get_hardware_id(const char *ifname, char *buf)
+{
+ char vendor[64];
+ char device[64];
+ struct iwinfo_hardware_id *ids;
+ struct iwinfo_hardware_entry *e;
+ const char *phy = madwifi_phyname(ifname);
+
+ if (wext_get_hardware_id(phy, buf))
+ return iwinfo_hardware_id_from_mtd((struct iwinfo_hardware_id *)buf);
+
+ return 0;
+}
+
+static const struct iwinfo_hardware_entry *
+madwifi_get_hardware_entry(const char *ifname)
+{
+ struct iwinfo_hardware_id id;
+
+ if (madwifi_get_hardware_id(ifname, (char *)&id))
+ return NULL;
+
+ return iwinfo_hardware(&id);
+}
+
+int madwifi_get_hardware_name(const char *ifname, char *buf)
+{
+ const struct iwinfo_hardware_entry *hw;
+
+ if (!(hw = madwifi_get_hardware_entry(ifname)))
+ sprintf(buf, "Generic Atheros");
+ else
+ sprintf(buf, "%s %s", hw->vendor_name, hw->device_name);
+
+ return 0;
+}
+
+int madwifi_get_txpower_offset(const char *ifname, int *buf)
+{
+ const struct iwinfo_hardware_entry *hw;
+
+ if (!(hw = madwifi_get_hardware_entry(ifname)))
+ return -1;
+
+ *buf = hw->txpower_offset;
+ return 0;
+}
+
+int madwifi_get_frequency_offset(const char *ifname, int *buf)
+{
+ const struct iwinfo_hardware_entry *hw;
+
+ if (!(hw = madwifi_get_hardware_entry(ifname)))
+ return -1;
+
+ *buf = hw->frequency_offset;
+ return 0;
+}
diff --git a/package/iwinfo/src/iwinfo_nl80211.c b/package/iwinfo/src/iwinfo_nl80211.c
new file mode 100644
index 000000000..304a18b3e
--- /dev/null
+++ b/package/iwinfo/src/iwinfo_nl80211.c
@@ -0,0 +1,2080 @@
+/*
+ * iwinfo - Wireless Information Library - NL80211 Backend
+ *
+ * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * The iwinfo library 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.
+ *
+ * The iwinfo library 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 the iwinfo library. If not, see http://www.gnu.org/licenses/.
+ *
+ * The signal handling code is derived from the official madwifi tools,
+ * wlanconfig.c in particular. The encryption property handling was
+ * inspired by the hostapd madwifi driver.
+ *
+ * Parts of this code are derived from the Linux iw utility.
+ */
+
+#include "iwinfo/nl80211.h"
+#include "iwinfo/wext.h"
+
+#define min(x, y) ((x) < (y)) ? (x) : (y)
+
+static struct nl80211_state *nls = NULL;
+
+static int nl80211_init(void)
+{
+ int err, fd;
+
+ if (!nls)
+ {
+ nls = malloc(sizeof(struct nl80211_state));
+ if (!nls) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ nls->nl_sock = nl_socket_alloc();
+ if (!nls->nl_sock) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ if (genl_connect(nls->nl_sock)) {
+ err = -ENOLINK;
+ goto err;
+ }
+
+ fd = nl_socket_get_fd(nls->nl_sock);
+ if (fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC) < 0) {
+ err = -EINVAL;
+ goto err;
+ }
+
+ if (genl_ctrl_alloc_cache(nls->nl_sock, &nls->nl_cache)) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ nls->nl80211 = genl_ctrl_search_by_name(nls->nl_cache, "nl80211");
+ if (!nls->nl80211) {
+ err = -ENOENT;
+ goto err;
+ }
+
+ nls->nlctrl = genl_ctrl_search_by_name(nls->nl_cache, "nlctrl");
+ if (!nls->nlctrl) {
+ err = -ENOENT;
+ goto err;
+ }
+ }
+
+ return 0;
+
+
+err:
+ nl80211_close();
+ return err;
+}
+
+
+static int nl80211_msg_error(struct sockaddr_nl *nla,
+ struct nlmsgerr *err, void *arg)
+{
+ int *ret = arg;
+ *ret = err->error;
+ return NL_STOP;
+}
+
+static int nl80211_msg_finish(struct nl_msg *msg, void *arg)
+{
+ int *ret = arg;
+ *ret = 0;
+ return NL_SKIP;
+}
+
+static int nl80211_msg_ack(struct nl_msg *msg, void *arg)
+{
+ int *ret = arg;
+ *ret = 0;
+ return NL_STOP;
+}
+
+static int nl80211_msg_response(struct nl_msg *msg, void *arg)
+{
+ return NL_SKIP;
+}
+
+static void nl80211_free(struct nl80211_msg_conveyor *cv)
+{
+ if (cv)
+ {
+ if (cv->cb)
+ nl_cb_put(cv->cb);
+
+ if (cv->msg)
+ nlmsg_free(cv->msg);
+
+ cv->cb = NULL;
+ cv->msg = NULL;
+ }
+}
+
+static struct nl80211_msg_conveyor * nl80211_new(struct genl_family *family,
+ int cmd, int flags)
+{
+ static struct nl80211_msg_conveyor cv;
+
+ struct nl_msg *req = NULL;
+ struct nl_cb *cb = NULL;
+
+ req = nlmsg_alloc();
+ if (!req)
+ goto err;
+
+ cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!cb)
+ goto err;
+
+ genlmsg_put(req, 0, 0, genl_family_get_id(family), 0, flags, cmd, 0);
+
+ cv.msg = req;
+ cv.cb = cb;
+
+ return &cv;
+
+err:
+nla_put_failure:
+ if (cb)
+ nl_cb_put(cb);
+
+ if (req)
+ nlmsg_free(req);
+
+ return NULL;
+}
+
+static struct nl80211_msg_conveyor * nl80211_ctl(int cmd, int flags)
+{
+ if (nl80211_init() < 0)
+ return NULL;
+
+ return nl80211_new(nls->nlctrl, cmd, flags);
+}
+
+static struct nl80211_msg_conveyor * nl80211_msg(const char *ifname,
+ int cmd, int flags)
+{
+ int ifidx = -1, phyidx = -1;
+ struct nl80211_msg_conveyor *cv;
+
+ if (nl80211_init() < 0)
+ return NULL;
+
+ if (!strncmp(ifname, "phy", 3))
+ phyidx = atoi(&ifname[3]);
+ else if (!strncmp(ifname, "radio", 5))
+ phyidx = atoi(&ifname[5]);
+ else if (!strncmp(ifname, "mon.", 4))
+ ifidx = if_nametoindex(&ifname[4]);
+ else
+ ifidx = if_nametoindex(ifname);
+
+ if ((ifidx < 0) && (phyidx < 0))
+ return NULL;
+
+ cv = nl80211_new(nls->nl80211, cmd, flags);
+ if (!cv)
+ return NULL;
+
+ if (ifidx > -1)
+ NLA_PUT_U32(cv->msg, NL80211_ATTR_IFINDEX, ifidx);
+
+ if (phyidx > -1)
+ NLA_PUT_U32(cv->msg, NL80211_ATTR_WIPHY, phyidx);
+
+ return cv;
+
+nla_put_failure:
+ nl80211_free(cv);
+ return NULL;
+}
+
+static struct nl80211_msg_conveyor * nl80211_send(
+ struct nl80211_msg_conveyor *cv,
+ int (*cb_func)(struct nl_msg *, void *), void *cb_arg
+) {
+ static struct nl80211_msg_conveyor rcv;
+ int err = 1;
+
+ if (cb_func)
+ nl_cb_set(cv->cb, NL_CB_VALID, NL_CB_CUSTOM, cb_func, cb_arg);
+ else
+ nl_cb_set(cv->cb, NL_CB_VALID, NL_CB_CUSTOM, nl80211_msg_response, &rcv);
+
+ if (nl_send_auto_complete(nls->nl_sock, cv->msg) < 0)
+ goto err;
+
+ nl_cb_err(cv->cb, NL_CB_CUSTOM, nl80211_msg_error, &err);
+ nl_cb_set(cv->cb, NL_CB_FINISH, NL_CB_CUSTOM, nl80211_msg_finish, &err);
+ nl_cb_set(cv->cb, NL_CB_ACK, NL_CB_CUSTOM, nl80211_msg_ack, &err);
+
+ while (err > 0)
+ nl_recvmsgs(nls->nl_sock, cv->cb);
+
+ return &rcv;
+
+err:
+ nl_cb_put(cv->cb);
+ nlmsg_free(cv->msg);
+
+ return NULL;
+}
+
+static struct nlattr ** nl80211_parse(struct nl_msg *msg)
+{
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ static struct nlattr *attr[NL80211_ATTR_MAX + 1];
+
+ nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+ return attr;
+}
+
+
+static int nl80211_subscribe_cb(struct nl_msg *msg, void *arg)
+{
+ struct nl80211_group_conveyor *cv = arg;
+
+ struct nlattr **attr = nl80211_parse(msg);
+ struct nlattr *mgrpinfo[CTRL_ATTR_MCAST_GRP_MAX + 1];
+ struct nlattr *mgrp;
+ int mgrpidx;
+
+ if (!attr[CTRL_ATTR_MCAST_GROUPS])
+ return NL_SKIP;
+
+ nla_for_each_nested(mgrp, attr[CTRL_ATTR_MCAST_GROUPS], mgrpidx)
+ {
+ nla_parse(mgrpinfo, CTRL_ATTR_MCAST_GRP_MAX,
+ nla_data(mgrp), nla_len(mgrp), NULL);
+
+ if (mgrpinfo[CTRL_ATTR_MCAST_GRP_ID] &&
+ mgrpinfo[CTRL_ATTR_MCAST_GRP_NAME] &&
+ !strncmp(nla_data(mgrpinfo[CTRL_ATTR_MCAST_GRP_NAME]),
+ cv->name, nla_len(mgrpinfo[CTRL_ATTR_MCAST_GRP_NAME])))
+ {
+ cv->id = nla_get_u32(mgrpinfo[CTRL_ATTR_MCAST_GRP_ID]);
+ break;
+ }
+ }
+
+ return NL_SKIP;
+}
+
+static int nl80211_subscribe(const char *family, const char *group)
+{
+ struct nl80211_group_conveyor cv = { .name = group, .id = -ENOENT };
+ struct nl80211_msg_conveyor *req;
+
+ req = nl80211_ctl(CTRL_CMD_GETFAMILY, 0);
+ if (req)
+ {
+ NLA_PUT_STRING(req->msg, CTRL_ATTR_FAMILY_NAME, family);
+ nl80211_send(req, nl80211_subscribe_cb, &cv);
+
+nla_put_failure:
+ nl80211_free(req);
+ }
+
+ return nl_socket_add_membership(nls->nl_sock, cv.id);
+}
+
+
+static int nl80211_wait_cb(struct nl_msg *msg, void *arg)
+{
+ struct nl80211_event_conveyor *cv = arg;
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+
+ if (gnlh->cmd == cv->wait)
+ cv->recv = gnlh->cmd;
+
+ return NL_SKIP;
+}
+
+static int nl80211_wait_seq_check(struct nl_msg *msg, void *arg)
+{
+ return NL_OK;
+}
+
+static int nl80211_wait(const char *family, const char *group, int cmd)
+{
+ struct nl80211_event_conveyor cv = { .wait = cmd };
+ struct nl_cb *cb;
+
+ if (nl80211_subscribe(family, group))
+ return -ENOENT;
+
+ cb = nl_cb_alloc(NL_CB_DEFAULT);
+
+ if (!cb)
+ return -ENOMEM;
+
+ nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, nl80211_wait_seq_check, NULL);
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, nl80211_wait_cb, &cv );
+
+ while (!cv.recv)
+ nl_recvmsgs(nls->nl_sock, cb);
+
+ nl_cb_put(cb);
+
+ return 0;
+}
+
+
+static int nl80211_freq2channel(int freq)
+{
+ if (freq == 2484)
+ return 14;
+
+ if (freq < 2484)
+ return (freq - 2407) / 5;
+
+ return (freq / 5) - 1000;
+}
+
+static int nl80211_channel2freq(int channel, const char *band)
+{
+ if (channel == 14)
+ return 2484;
+
+ if ((channel < 14) && (!band || band[0] != 'a'))
+ return (channel * 5) + 2407;
+
+ if (channel > 0)
+ return (1000 + channel) * 5;
+
+ return 0;
+}
+
+static char * nl80211_getval(const char *ifname, const char *buf, const char *key)
+{
+ int i, len;
+ char lkey[64] = { 0 };
+ const char *ln = buf;
+ static char lval[256] = { 0 };
+
+ int matched_if = ifname ? 0 : 1;
+
+
+ for( i = 0, len = strlen(buf); i < len; i++ )
+ {
+ if (!lkey[0] && (buf[i] == ' ' || buf[i] == '\t'))
+ {
+ ln++;
+ }
+ else if (!lkey[0] && (buf[i] == '='))
+ {
+ if ((&buf[i] - ln) > 0)
+ memcpy(lkey, ln, min(sizeof(lkey) - 1, &buf[i] - ln));
+ }
+ else if (buf[i] == '\n')
+ {
+ if (lkey[0])
+ {
+ memcpy(lval, ln + strlen(lkey) + 1,
+ min(sizeof(lval) - 1, &buf[i] - ln - strlen(lkey) - 1));
+
+ if ((ifname != NULL) &&
+ (!strcmp(lkey, "interface") || !strcmp(lkey, "bss")) )
+ {
+ matched_if = !strcmp(lval, ifname);
+ }
+ else if (matched_if && !strcmp(lkey, key))
+ {
+ return lval;
+ }
+ }
+
+ ln = &buf[i+1];
+ memset(lkey, 0, sizeof(lkey));
+ memset(lval, 0, sizeof(lval));
+ }
+ }
+
+ return NULL;
+}
+
+static int nl80211_ifname2phy_cb(struct nl_msg *msg, void *arg)
+{
+ char *buf = arg;
+ struct nlattr **attr = nl80211_parse(msg);
+
+ if (attr[NL80211_ATTR_WIPHY_NAME])
+ memcpy(buf, nla_data(attr[NL80211_ATTR_WIPHY_NAME]),
+ nla_len(attr[NL80211_ATTR_WIPHY_NAME]));
+ else
+ buf[0] = 0;
+
+ return NL_SKIP;
+}
+
+static char * nl80211_ifname2phy(const char *ifname)
+{
+ static char phy[32] = { 0 };
+ struct nl80211_msg_conveyor *req;
+
+ memset(phy, 0, sizeof(phy));
+
+ req = nl80211_msg(ifname, NL80211_CMD_GET_WIPHY, 0);
+ if (req)
+ {
+ nl80211_send(req, nl80211_ifname2phy_cb, phy);
+ nl80211_free(req);
+ }
+
+ return phy[0] ? phy : NULL;
+}
+
+static char * nl80211_hostapd_info(const char *ifname)
+{
+ char *phy;
+ char path[32] = { 0 };
+ static char buf[4096] = { 0 };
+ FILE *conf;
+
+ if ((phy = nl80211_ifname2phy(ifname)) != NULL)
+ {
+ snprintf(path, sizeof(path), "/var/run/hostapd-%s.conf", phy);
+
+ if ((conf = fopen(path, "r")) != NULL)
+ {
+ fread(buf, sizeof(buf) - 1, 1, conf);
+ fclose(conf);
+
+ return buf;
+ }
+ }
+
+ return NULL;
+}
+
+static inline int nl80211_wpactl_recv(int sock, char *buf, int blen)
+{
+ fd_set rfds;
+ struct timeval tv = { 2, 0 };
+
+ FD_ZERO(&rfds);
+ FD_SET(sock, &rfds);
+
+ memset(buf, 0, blen);
+
+
+ if (select(sock + 1, &rfds, NULL, NULL, &tv) < 0)
+ return -1;
+
+ if (!FD_ISSET(sock, &rfds))
+ return -1;
+
+ return recv(sock, buf, blen, 0);
+}
+
+static char * nl80211_wpactl_info(const char *ifname, const char *cmd,
+ const char *event)
+{
+ int numtry = 0;
+ int sock = -1;
+ char *rv = NULL;
+ size_t remote_length, local_length;
+ static char buffer[10240] = { 0 };
+
+ struct sockaddr_un local = { 0 };
+ struct sockaddr_un remote = { 0 };
+
+
+ sock = socket(PF_UNIX, SOCK_DGRAM, 0);
+ if (sock < 0)
+ return NULL;
+
+ remote.sun_family = AF_UNIX;
+ remote_length = sizeof(remote.sun_family) + sprintf(remote.sun_path,
+ "/var/run/wpa_supplicant-%s/%s", ifname, ifname);
+
+ if (fcntl(sock, F_SETFD, fcntl(sock, F_GETFD) | FD_CLOEXEC) < 0)
+ goto out;
+
+ if (connect(sock, (struct sockaddr *) &remote, remote_length))
+ goto out;
+
+ local.sun_family = AF_UNIX;
+ local_length = sizeof(local.sun_family) +
+ sprintf(local.sun_path, "/var/run/iwinfo-%s-%d", ifname, getpid());
+
+ if (bind(sock, (struct sockaddr *) &local, local_length))
+ goto out;
+
+
+ if (event)
+ {
+ send(sock, "ATTACH", 6, 0);
+
+ if (nl80211_wpactl_recv(sock, buffer, sizeof(buffer)) <= 0)
+ goto out;
+ }
+
+
+ send(sock, cmd, strlen(cmd), 0);
+
+ while( numtry++ < 5 )
+ {
+ if (nl80211_wpactl_recv(sock, buffer, sizeof(buffer)) <= 0)
+ {
+ if (event)
+ continue;
+
+ break;
+ }
+
+ if ((!event && buffer[0] != '<') || (event && strstr(buffer, event)))
+ break;
+ }
+
+ rv = buffer;
+
+out:
+ close(sock);
+
+ if (local.sun_family)
+ unlink(local.sun_path);
+
+ return rv;
+}
+
+static inline int nl80211_readint(const char *path)
+{
+ int fd;
+ int rv = -1;
+ char buffer[16];
+
+ if ((fd = open(path, O_RDONLY)) > -1)
+ {
+ if (read(fd, buffer, sizeof(buffer)) > 0)
+ rv = atoi(buffer);
+
+ close(fd);
+ }
+
+ return rv;
+}
+
+static char * nl80211_phy2ifname(const char *ifname)
+{
+ int fd, ifidx = -1, cifidx = -1, phyidx = -1;
+ char buffer[64];
+ static char nif[IFNAMSIZ] = { 0 };
+
+ DIR *d;
+ struct dirent *e;
+
+ if (!ifname)
+ return NULL;
+ else if (!strncmp(ifname, "phy", 3))
+ phyidx = atoi(&ifname[3]);
+ else if (!strncmp(ifname, "radio", 5))
+ phyidx = atoi(&ifname[5]);
+
+ memset(nif, 0, sizeof(nif));
+
+ if (phyidx > -1)
+ {
+ if ((d = opendir("/sys/class/net")) != NULL)
+ {
+ while ((e = readdir(d)) != NULL)
+ {
+ snprintf(buffer, sizeof(buffer),
+ "/sys/class/net/%s/phy80211/index", e->d_name);
+
+ if (nl80211_readint(buffer) == phyidx)
+ {
+ snprintf(buffer, sizeof(buffer),
+ "/sys/class/net/%s/ifindex", e->d_name);
+
+ if ((cifidx = nl80211_readint(buffer)) >= 0 &&
+ ((ifidx < 0) || (cifidx < ifidx)))
+ {
+ ifidx = cifidx;
+ strncpy(nif, e->d_name, sizeof(nif));
+ }
+ }
+ }
+
+ closedir(d);
+ }
+ }
+
+ return nif[0] ? nif : NULL;
+}
+
+static char * nl80211_ifadd(const char *ifname)
+{
+ int phyidx;
+ char *rv = NULL;
+ static char nif[IFNAMSIZ] = { 0 };
+ struct nl80211_msg_conveyor *req, *res;
+
+ req = nl80211_msg(ifname, NL80211_CMD_NEW_INTERFACE, 0);
+ if (req)
+ {
+ snprintf(nif, sizeof(nif), "tmp.%s", ifname);
+
+ NLA_PUT_STRING(req->msg, NL80211_ATTR_IFNAME, nif);
+ NLA_PUT_U32(req->msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_STATION);
+
+ nl80211_send(req, NULL, NULL);
+
+ rv = nif;
+
+ nla_put_failure:
+ nl80211_free(req);
+ }
+
+ return rv;
+}
+
+static void nl80211_ifdel(const char *ifname)
+{
+ struct nl80211_msg_conveyor *req;
+
+ req = nl80211_msg(ifname, NL80211_CMD_DEL_INTERFACE, 0);
+ if (req)
+ {
+ NLA_PUT_STRING(req->msg, NL80211_ATTR_IFNAME, ifname);
+
+ nl80211_send(req, NULL, NULL);
+
+ nla_put_failure:
+ nl80211_free(req);
+ }
+}
+
+static void nl80211_hostapd_hup(const char *ifname)
+{
+ int fd, pid = 0;
+ char buf[32];
+ char *phy = nl80211_ifname2phy(ifname);
+
+ if (phy)
+ {
+ snprintf(buf, sizeof(buf), "/var/run/wifi-%s.pid", phy);
+ if ((fd = open(buf, O_RDONLY)) > 0)
+ {
+ if (read(fd, buf, sizeof(buf)) > 0)
+ pid = atoi(buf);
+
+ close(fd);
+ }
+
+ if (pid > 0)
+ kill(pid, 1);
+ }
+}
+
+
+int nl80211_probe(const char *ifname)
+{
+ return !!nl80211_ifname2phy(ifname);
+}
+
+void nl80211_close(void)
+{
+ if (nls)
+ {
+ if (nls->nlctrl)
+ genl_family_put(nls->nlctrl);
+
+ if (nls->nl80211)
+ genl_family_put(nls->nl80211);
+
+ if (nls->nl_sock)
+ nl_socket_free(nls->nl_sock);
+
+ if (nls->nl_cache)
+ nl_cache_free(nls->nl_cache);
+
+ free(nls);
+ nls = NULL;
+ }
+}
+
+int nl80211_get_mode(const char *ifname, int *buf)
+{
+ return wext_get_mode(ifname, buf);
+}
+
+int nl80211_get_ssid(const char *ifname, char *buf)
+{
+ char *ssid;
+
+ if (!wext_get_ssid(ifname, buf))
+ {
+ return 0;
+ }
+ else if ((ssid = nl80211_hostapd_info(ifname)) &&
+ (ssid = nl80211_getval(ifname, ssid, "ssid")))
+ {
+ memcpy(buf, ssid, strlen(ssid));
+ return 0;
+ }
+
+ return -1;
+}
+
+int nl80211_get_bssid(const char *ifname, char *buf)
+{
+ char *bssid;
+ unsigned char mac[6];
+
+ if (!wext_get_bssid(ifname, buf))
+ {
+ return 0;
+ }
+ else if ((bssid = nl80211_hostapd_info(ifname)) &&
+ (bssid = nl80211_getval(ifname, bssid, "bssid")))
+ {
+ mac[0] = strtol(&bssid[0], NULL, 16);
+ mac[1] = strtol(&bssid[3], NULL, 16);
+ mac[2] = strtol(&bssid[6], NULL, 16);
+ mac[3] = strtol(&bssid[9], NULL, 16);
+ mac[4] = strtol(&bssid[12], NULL, 16);
+ mac[5] = strtol(&bssid[15], NULL, 16);
+
+ sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+ return 0;
+ }
+
+ return -1;
+}
+
+
+static int nl80211_get_frequency_cb(struct nl_msg *msg, void *arg)
+{
+ int *freq = arg;
+ struct nlattr **attr = nl80211_parse(msg);
+ struct nlattr *binfo[NL80211_BSS_MAX + 1];
+
+ static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
+ [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
+ };
+
+ if (attr[NL80211_ATTR_BSS] &&
+ !nla_parse_nested(binfo, NL80211_BSS_MAX,
+ attr[NL80211_ATTR_BSS], bss_policy))
+ {
+ if (binfo[NL80211_BSS_FREQUENCY])
+ *freq = nla_get_u32(binfo[NL80211_BSS_FREQUENCY]);
+ }
+
+ return NL_SKIP;
+}
+
+int nl80211_get_frequency(const char *ifname, int *buf)
+{
+ char *res, *channel;
+ struct nl80211_msg_conveyor *req;
+
+ *buf = 0;
+
+ if ((res = nl80211_hostapd_info(ifname)) &&
+ (channel = nl80211_getval(NULL, res, "channel")))
+ {
+ *buf = nl80211_channel2freq(atoi(channel),
+ nl80211_getval(NULL, res, "hw_mode"));
+ }
+ else
+ {
+ res = nl80211_phy2ifname(ifname);
+ req = nl80211_msg(res ? res : ifname, NL80211_CMD_GET_SCAN, NLM_F_DUMP);
+
+ if (req)
+ {
+ nl80211_send(req, nl80211_get_frequency_cb, buf);
+ nl80211_free(req);
+ }
+ }
+
+ return (*buf == 0) ? -1 : 0;
+}
+
+int nl80211_get_channel(const char *ifname, int *buf)
+{
+ if (!nl80211_get_frequency(ifname, buf))
+ {
+ *buf = nl80211_freq2channel(*buf);
+ return 0;
+ }
+
+ return -1;
+}
+
+
+int nl80211_get_txpower(const char *ifname, int *buf)
+{
+ return wext_get_txpower(ifname, buf);
+}
+
+
+static int nl80211_fill_signal_cb(struct nl_msg *msg, void *arg)
+{
+ int8_t dbm;
+ int16_t mbit;
+ struct nl80211_rssi_rate *rr = arg;
+ struct nlattr **attr = nl80211_parse(msg);
+ struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
+ struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
+
+ static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
+ [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
+ [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
+ [NL80211_STA_INFO_LLID] = { .type = NLA_U16 },
+ [NL80211_STA_INFO_PLID] = { .type = NLA_U16 },
+ [NL80211_STA_INFO_PLINK_STATE] = { .type = NLA_U8 },
+ };
+
+ static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
+ [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
+ [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
+ [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
+ };
+
+ if (attr[NL80211_ATTR_STA_INFO])
+ {
+ if (!nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
+ attr[NL80211_ATTR_STA_INFO], stats_policy))
+ {
+ if (sinfo[NL80211_STA_INFO_SIGNAL])
+ {
+ dbm = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
+ rr->rssi = rr->rssi ? (int8_t)((rr->rssi + dbm) / 2) : dbm;
+ }
+
+ if (sinfo[NL80211_STA_INFO_TX_BITRATE])
+ {
+ if (!nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
+ sinfo[NL80211_STA_INFO_TX_BITRATE],
+ rate_policy))
+ {
+ if (rinfo[NL80211_RATE_INFO_BITRATE])
+ {
+ mbit = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
+ rr->rate = rr->rate
+ ? (int16_t)((rr->rate + mbit) / 2) : mbit;
+ }
+ }
+ }
+ }
+ }
+
+ return NL_SKIP;
+}
+
+static void nl80211_fill_signal(const char *ifname, struct nl80211_rssi_rate *r)
+{
+ DIR *d;
+ struct dirent *de;
+ struct nl80211_msg_conveyor *req;
+
+ r->rssi = 0;
+ r->rate = 0;
+
+ if ((d = opendir("/sys/class/net")) != NULL)
+ {
+ while ((de = readdir(d)) != NULL)
+ {
+ if (!strncmp(de->d_name, ifname, strlen(ifname)) &&
+ (!de->d_name[strlen(ifname)] ||
+ !strncmp(&de->d_name[strlen(ifname)], ".sta", 4)))
+ {
+ req = nl80211_msg(de->d_name, NL80211_CMD_GET_STATION,
+ NLM_F_DUMP);
+
+ if (req)
+ {
+ nl80211_send(req, nl80211_fill_signal_cb, r);
+ nl80211_free(req);
+ }
+ }
+ }
+
+ closedir(d);
+ }
+}
+
+int nl80211_get_bitrate(const char *ifname, int *buf)
+{
+ struct nl80211_rssi_rate rr;
+
+ if (!wext_get_bitrate(ifname, buf))
+ return 0;
+
+ nl80211_fill_signal(ifname, &rr);
+
+ if (rr.rate)
+ {
+ *buf = (rr.rate * 100);
+ return 0;
+ }
+
+ return -1;
+}
+
+int nl80211_get_signal(const char *ifname, int *buf)
+{
+ struct nl80211_rssi_rate rr;
+
+ if (!wext_get_signal(ifname, buf))
+ return 0;
+
+ nl80211_fill_signal(ifname, &rr);
+
+ if (rr.rssi)
+ {
+ *buf = rr.rssi;
+ return 0;
+ }
+
+ return -1;
+}
+
+static int nl80211_get_noise_cb(struct nl_msg *msg, void *arg)
+{
+ int8_t *noise = arg;
+ struct nlattr **tb = nl80211_parse(msg);
+ struct nlattr *si[NL80211_SURVEY_INFO_MAX + 1];
+
+ static struct nla_policy sp[NL80211_SURVEY_INFO_MAX + 1] = {
+ [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
+ [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
+ };
+
+ if (!tb[NL80211_ATTR_SURVEY_INFO])
+ return NL_SKIP;
+
+ if (nla_parse_nested(si, NL80211_SURVEY_INFO_MAX,
+ tb[NL80211_ATTR_SURVEY_INFO], sp))
+ return NL_SKIP;
+
+ if (!si[NL80211_SURVEY_INFO_NOISE])
+ return NL_SKIP;
+
+ if (!*noise || si[NL80211_SURVEY_INFO_IN_USE])
+ *noise = (int8_t)nla_get_u8(si[NL80211_SURVEY_INFO_NOISE]);
+
+ return NL_SKIP;
+}
+
+
+int nl80211_get_noise(const char *ifname, int *buf)
+{
+ int8_t noise;
+ struct nl80211_msg_conveyor *req;
+
+ req = nl80211_msg(ifname, NL80211_CMD_GET_SURVEY, NLM_F_DUMP);
+ if (req)
+ {
+ noise = 0;
+
+ nl80211_send(req, nl80211_get_noise_cb, &noise);
+ nl80211_free(req);
+
+ if (noise)
+ {
+ *buf = noise;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+int nl80211_get_quality(const char *ifname, int *buf)
+{
+ int signal;
+
+ if (wext_get_quality(ifname, buf))
+ {
+ *buf = 0;
+
+ if (!nl80211_get_signal(ifname, &signal))
+ {
+ /* A positive signal level is usually just a quality
+ * value, pass through as-is */
+ if (signal >= 0)
+ {
+ *buf = signal;
+ }
+
+ /* The cfg80211 wext compat layer assumes a signal range
+ * of -110 dBm to -40 dBm, the quality value is derived
+ * by adding 110 to the signal level */
+ else
+ {
+ if (signal < -110)
+ signal = -110;
+ else if (signal > -40)
+ signal = -40;
+
+ *buf = (signal + 110);
+ }
+ }
+ }
+
+ return 0;
+}
+
+int nl80211_get_quality_max(const char *ifname, int *buf)
+{
+ if (wext_get_quality_max(ifname, buf))
+ /* The cfg80211 wext compat layer assumes a maximum
+ * quality of 70 */
+ *buf = 70;
+
+ return 0;
+}
+
+int nl80211_get_encryption(const char *ifname, char *buf)
+{
+ int i;
+ char k[9];
+ char *val, *res;
+ struct iwinfo_crypto_entry *c = (struct iwinfo_crypto_entry *)buf;
+
+ /* WPA supplicant */
+ if ((res = nl80211_wpactl_info(ifname, "STATUS", NULL)) &&
+ (val = nl80211_getval(NULL, res, "pairwise_cipher")))
+ {
+ /* WEP */
+ if (strstr(val, "WEP"))
+ {
+ if (strstr(val, "WEP-40"))
+ c->pair_ciphers |= IWINFO_CIPHER_WEP40;
+
+ else if (strstr(val, "WEP-104"))
+ c->pair_ciphers |= IWINFO_CIPHER_WEP104;
+
+ c->enabled = 1;
+ c->group_ciphers = c->pair_ciphers;
+
+ c->auth_suites |= IWINFO_KMGMT_NONE;
+ c->auth_algs |= IWINFO_AUTH_OPEN; /* XXX: assumption */
+ }
+
+ /* WPA */
+ else
+ {
+ if (strstr(val, "TKIP"))
+ c->pair_ciphers |= IWINFO_CIPHER_TKIP;
+
+ else if (strstr(val, "CCMP"))
+ c->pair_ciphers |= IWINFO_CIPHER_CCMP;
+
+ else if (strstr(val, "NONE"))
+ c->pair_ciphers |= IWINFO_CIPHER_NONE;
+
+ else if (strstr(val, "WEP-40"))
+ c->pair_ciphers |= IWINFO_CIPHER_WEP40;
+
+ else if (strstr(val, "WEP-104"))
+ c->pair_ciphers |= IWINFO_CIPHER_WEP104;
+
+
+ if ((val = nl80211_getval(NULL, res, "group_cipher")))
+ {
+ if (strstr(val, "TKIP"))
+ c->group_ciphers |= IWINFO_CIPHER_TKIP;
+
+ else if (strstr(val, "CCMP"))
+ c->group_ciphers |= IWINFO_CIPHER_CCMP;
+
+ else if (strstr(val, "NONE"))
+ c->group_ciphers |= IWINFO_CIPHER_NONE;
+
+ else if (strstr(val, "WEP-40"))
+ c->group_ciphers |= IWINFO_CIPHER_WEP40;
+
+ else if (strstr(val, "WEP-104"))
+ c->group_ciphers |= IWINFO_CIPHER_WEP104;
+ }
+
+
+ if ((val = nl80211_getval(NULL, res, "key_mgmt")))
+ {
+ if (strstr(val, "WPA2"))
+ c->wpa_version = 2;
+
+ else if (strstr(val, "WPA"))
+ c->wpa_version = 1;
+
+
+ if (strstr(val, "PSK"))
+ c->auth_suites |= IWINFO_KMGMT_PSK;
+
+ else if (strstr(val, "EAP") || strstr(val, "802.1X"))
+ c->auth_suites |= IWINFO_KMGMT_8021x;
+
+ else if (strstr(val, "NONE"))
+ c->auth_suites |= IWINFO_KMGMT_NONE;
+ }
+
+ c->enabled = (c->wpa_version && c->auth_suites) ? 1 : 0;
+ }
+
+ return 0;
+ }
+
+ /* Hostapd */
+ else if ((res = nl80211_hostapd_info(ifname)))
+ {
+ if ((val = nl80211_getval(ifname, res, "wpa")) != NULL)
+ c->wpa_version = atoi(val);
+
+ val = nl80211_getval(ifname, res, "wpa_key_mgmt");
+
+ if (!val || strstr(val, "PSK"))
+ c->auth_suites |= IWINFO_KMGMT_PSK;
+
+ if (val && strstr(val, "EAP"))
+ c->auth_suites |= IWINFO_KMGMT_8021x;
+
+ if (val && strstr(val, "NONE"))
+ c->auth_suites |= IWINFO_KMGMT_NONE;
+
+ if ((val = nl80211_getval(ifname, res, "wpa_pairwise")) != NULL)
+ {
+ if (strstr(val, "TKIP"))
+ c->pair_ciphers |= IWINFO_CIPHER_TKIP;
+
+ if (strstr(val, "CCMP"))
+ c->pair_ciphers |= IWINFO_CIPHER_CCMP;
+
+ if (strstr(val, "NONE"))
+ c->pair_ciphers |= IWINFO_CIPHER_NONE;
+ }
+
+ if ((val = nl80211_getval(ifname, res, "auth_algs")) != NULL)
+ {
+ switch(atoi(val)) {
+ case 1:
+ c->auth_algs |= IWINFO_AUTH_OPEN;
+ break;
+
+ case 2:
+ c->auth_algs |= IWINFO_AUTH_SHARED;
+ break;
+
+ case 3:
+ c->auth_algs |= IWINFO_AUTH_OPEN;
+ c->auth_algs |= IWINFO_AUTH_SHARED;
+ break;
+
+ default:
+ break;
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ snprintf(k, sizeof(k), "wep_key%d", i);
+
+ if ((val = nl80211_getval(ifname, res, k)))
+ {
+ if ((strlen(val) == 5) || (strlen(val) == 10))
+ c->pair_ciphers |= IWINFO_CIPHER_WEP40;
+
+ else if ((strlen(val) == 13) || (strlen(val) == 26))
+ c->pair_ciphers |= IWINFO_CIPHER_WEP104;
+ }
+ }
+ }
+
+ c->group_ciphers = c->pair_ciphers;
+ c->enabled = (c->wpa_version || c->pair_ciphers) ? 1 : 0;
+
+ return 0;
+ }
+
+ return -1;
+}
+
+
+static int nl80211_get_assoclist_cb(struct nl_msg *msg, void *arg)
+{
+ struct nl80211_array_buf *arr = arg;
+ struct iwinfo_assoclist_entry *e = arr->buf;
+ struct nlattr **attr = nl80211_parse(msg);
+ struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
+ struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
+
+ static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
+ [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
+ [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
+ [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
+ };
+
+ static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
+ [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
+ [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
+ [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
+ };
+
+ /* advance to end of array */
+ e += arr->count;
+ memset(e, 0, sizeof(*e));
+
+ if (attr[NL80211_ATTR_MAC])
+ memcpy(e->mac, nla_data(attr[NL80211_ATTR_MAC]), 6);
+
+ if (attr[NL80211_ATTR_STA_INFO] &&
+ !nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
+ attr[NL80211_ATTR_STA_INFO], stats_policy))
+ {
+ if (sinfo[NL80211_STA_INFO_SIGNAL])
+ e->signal = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
+
+ if (sinfo[NL80211_STA_INFO_INACTIVE_TIME])
+ e->inactive = nla_get_u32(sinfo[NL80211_STA_INFO_INACTIVE_TIME]);
+
+ if (sinfo[NL80211_STA_INFO_RX_PACKETS])
+ e->rx_packets = nla_get_u32(sinfo[NL80211_STA_INFO_RX_PACKETS]);
+
+ if (sinfo[NL80211_STA_INFO_TX_PACKETS])
+ e->tx_packets = nla_get_u32(sinfo[NL80211_STA_INFO_TX_PACKETS]);
+
+ if (sinfo[NL80211_STA_INFO_RX_BITRATE] &&
+ !nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
+ sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy))
+ {
+ if (rinfo[NL80211_RATE_INFO_BITRATE])
+ e->rx_rate.rate =
+ nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]) * 100;
+
+ if (rinfo[NL80211_RATE_INFO_MCS])
+ e->rx_rate.mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
+
+ if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
+ e->rx_rate.is_40mhz = 1;
+
+ if (rinfo[NL80211_RATE_INFO_SHORT_GI])
+ e->rx_rate.is_short_gi = 1;
+ }
+
+ if (sinfo[NL80211_STA_INFO_TX_BITRATE] &&
+ !nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
+ sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy))
+ {
+ if (rinfo[NL80211_RATE_INFO_BITRATE])
+ e->tx_rate.rate =
+ nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]) * 100;
+
+ if (rinfo[NL80211_RATE_INFO_MCS])
+ e->tx_rate.mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
+
+ if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
+ e->tx_rate.is_40mhz = 1;
+
+ if (rinfo[NL80211_RATE_INFO_SHORT_GI])
+ e->tx_rate.is_short_gi = 1;
+ }
+ }
+
+ e->noise = 0; /* filled in by caller */
+ arr->count++;
+
+ return NL_SKIP;
+}
+
+int nl80211_get_assoclist(const char *ifname, char *buf, int *len)
+{
+ DIR *d;
+ int i, noise = 0;
+ struct dirent *de;
+ struct nl80211_msg_conveyor *req;
+ struct nl80211_array_buf arr = { .buf = buf, .count = 0 };
+ struct iwinfo_assoclist_entry *e;
+
+ if ((d = opendir("/sys/class/net")) != NULL)
+ {
+ while ((de = readdir(d)) != NULL)
+ {
+ if (!strncmp(de->d_name, ifname, strlen(ifname)) &&
+ (!de->d_name[strlen(ifname)] ||
+ !strncmp(&de->d_name[strlen(ifname)], ".sta", 4)))
+ {
+ req = nl80211_msg(de->d_name, NL80211_CMD_GET_STATION,
+ NLM_F_DUMP);
+
+ if (req)
+ {
+ nl80211_send(req, nl80211_get_assoclist_cb, &arr);
+ nl80211_free(req);
+ }
+ }
+ }
+
+ closedir(d);
+
+ if (!nl80211_get_noise(ifname, &noise))
+ for (i = 0, e = arr.buf; i < arr.count; i++, e++)
+ e->noise = noise;
+
+ *len = (arr.count * sizeof(struct iwinfo_assoclist_entry));
+ return 0;
+ }
+
+ return -1;
+}
+
+static int nl80211_get_txpwrlist_cb(struct nl_msg *msg, void *arg)
+{
+ int *dbm_max = arg;
+ int ch_cur, ch_cmp, bands_remain, freqs_remain;
+
+ struct nlattr **attr = nl80211_parse(msg);
+ struct nlattr *bands[NL80211_BAND_ATTR_MAX + 1];
+ struct nlattr *freqs[NL80211_FREQUENCY_ATTR_MAX + 1];
+ struct nlattr *band, *freq;
+
+ static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
+ [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },
+ [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG },
+ [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },
+ [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },
+ [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
+ [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },
+ };
+
+ ch_cur = *dbm_max; /* value int* is initialized with channel by caller */
+ *dbm_max = -1;
+
+ nla_for_each_nested(band, attr[NL80211_ATTR_WIPHY_BANDS], bands_remain)
+ {
+ nla_parse(bands, NL80211_BAND_ATTR_MAX, nla_data(band),
+ nla_len(band), NULL);
+
+ nla_for_each_nested(freq, bands[NL80211_BAND_ATTR_FREQS], freqs_remain)
+ {
+ nla_parse(freqs, NL80211_FREQUENCY_ATTR_MAX,
+ nla_data(freq), nla_len(freq), freq_policy);
+
+ ch_cmp = nl80211_freq2channel(nla_get_u32(
+ freqs[NL80211_FREQUENCY_ATTR_FREQ]));
+
+ if ((!ch_cur || (ch_cmp == ch_cur)) &&
+ freqs[NL80211_FREQUENCY_ATTR_MAX_TX_POWER])
+ {
+ *dbm_max = (int)(0.01 * nla_get_u32(
+ freqs[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]));
+
+ break;
+ }
+ }
+ }
+
+ return NL_SKIP;
+}
+
+int nl80211_get_txpwrlist(const char *ifname, char *buf, int *len)
+{
+ int ch_cur;
+ int dbm_max = -1, dbm_cur, dbm_cnt;
+ struct nl80211_msg_conveyor *req;
+ struct iwinfo_txpwrlist_entry entry;
+
+ if (nl80211_get_channel(ifname, &ch_cur))
+ ch_cur = 0;
+
+ req = nl80211_msg(ifname, NL80211_CMD_GET_WIPHY, 0);
+ if (req)
+ {
+ /* initialize the value pointer with channel for callback */
+ dbm_max = ch_cur;
+
+ nl80211_send(req, nl80211_get_txpwrlist_cb, &dbm_max);
+ nl80211_free(req);
+ }
+
+ if (dbm_max > 0)
+ {
+ for (dbm_cur = 0, dbm_cnt = 0;
+ dbm_cur < dbm_max;
+ dbm_cur++, dbm_cnt++)
+ {
+ entry.dbm = dbm_cur;
+ entry.mw = iwinfo_dbm2mw(dbm_cur);
+
+ memcpy(&buf[dbm_cnt * sizeof(entry)], &entry, sizeof(entry));
+ }
+
+ entry.dbm = dbm_max;
+ entry.mw = iwinfo_dbm2mw(dbm_max);
+
+ memcpy(&buf[dbm_cnt * sizeof(entry)], &entry, sizeof(entry));
+ dbm_cnt++;
+
+ *len = dbm_cnt * sizeof(entry);
+ return 0;
+ }
+
+ return -1;
+}
+
+static void nl80211_get_scancrypto(const char *spec,
+ struct iwinfo_crypto_entry *c)
+{
+ if (strstr(spec, "WPA") || strstr(spec, "WEP"))
+ {
+ c->enabled = 1;
+
+ if (strstr(spec, "WPA2-") && strstr(spec, "WPA-"))
+ c->wpa_version = 3;
+
+ else if (strstr(spec, "WPA2"))
+ c->wpa_version = 2;
+
+ else if (strstr(spec, "WPA"))
+ c->wpa_version = 1;
+
+ else if (strstr(spec, "WEP"))
+ c->auth_algs = IWINFO_AUTH_OPEN | IWINFO_AUTH_SHARED;
+
+
+ if (strstr(spec, "PSK"))
+ c->auth_suites |= IWINFO_KMGMT_PSK;
+
+ if (strstr(spec, "802.1X") || strstr(spec, "EAP"))
+ c->auth_suites |= IWINFO_KMGMT_8021x;
+
+ if (strstr(spec, "WPA-NONE"))
+ c->auth_suites |= IWINFO_KMGMT_NONE;
+
+
+ if (strstr(spec, "TKIP"))
+ c->pair_ciphers |= IWINFO_CIPHER_TKIP;
+
+ if (strstr(spec, "CCMP"))
+ c->pair_ciphers |= IWINFO_CIPHER_CCMP;
+
+ if (strstr(spec, "WEP-40"))
+ c->pair_ciphers |= IWINFO_CIPHER_WEP40;
+
+ if (strstr(spec, "WEP-104"))
+ c->pair_ciphers |= IWINFO_CIPHER_WEP104;
+
+ c->group_ciphers = c->pair_ciphers;
+ }
+ else
+ {
+ c->enabled = 0;
+ }
+}
+
+
+struct nl80211_scanlist {
+ struct iwinfo_scanlist_entry *e;
+ int len;
+};
+
+
+static void nl80211_get_scanlist_ie(struct nlattr **bss,
+ struct iwinfo_scanlist_entry *e)
+{
+ int ielen = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
+ unsigned char *ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
+ static unsigned char ms_oui[3] = { 0x00, 0x50, 0xf2 };
+
+ while (ielen >= 2 && ielen >= ie[1])
+ {
+ switch (ie[0])
+ {
+ case 0: /* SSID */
+ memcpy(e->ssid, ie + 2, min(ie[1], IWINFO_ESSID_MAX_SIZE));
+ break;
+
+ case 48: /* RSN */
+ iwinfo_parse_rsn(&e->crypto, ie + 2, ie[1],
+ IWINFO_CIPHER_CCMP, IWINFO_KMGMT_8021x);
+ break;
+
+ case 221: /* Vendor */
+ if (ie[1] >= 4 && !memcmp(ie + 2, ms_oui, 3) && ie[5] == 1)
+ iwinfo_parse_rsn(&e->crypto, ie + 6, ie[1] - 4,
+ IWINFO_CIPHER_TKIP, IWINFO_KMGMT_PSK);
+ break;
+ }
+
+ ielen -= ie[1] + 2;
+ ie += ie[1] + 2;
+ }
+}
+
+static int nl80211_get_scanlist_cb(struct nl_msg *msg, void *arg)
+{
+ int8_t rssi;
+ uint16_t caps;
+
+ struct nl80211_scanlist *sl = arg;
+ struct nlattr **tb = nl80211_parse(msg);
+ struct nlattr *bss[NL80211_BSS_MAX + 1];
+
+ static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
+ [NL80211_BSS_TSF] = { .type = NLA_U64 },
+ [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
+ [NL80211_BSS_BSSID] = { },
+ [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
+ [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
+ [NL80211_BSS_INFORMATION_ELEMENTS] = { },
+ [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
+ [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
+ [NL80211_BSS_STATUS] = { .type = NLA_U32 },
+ [NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },
+ [NL80211_BSS_BEACON_IES] = { },
+ };
+
+ if (!tb[NL80211_ATTR_BSS] ||
+ nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
+ bss_policy) ||
+ !bss[NL80211_BSS_BSSID])
+ {
+ return NL_SKIP;
+ }
+
+ if (bss[NL80211_BSS_CAPABILITY])
+ caps = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);
+ else
+ caps = 0;
+
+ memset(sl->e, 0, sizeof(*sl->e));
+ memcpy(sl->e->mac, nla_data(bss[NL80211_BSS_BSSID]), 6);
+
+ if (caps & (1<<1))
+ sl->e->mode = IWINFO_OPMODE_ADHOC;
+ else
+ sl->e->mode = IWINFO_OPMODE_MASTER;
+
+ if (caps & (1<<4))
+ sl->e->crypto.enabled = 1;
+
+ if (bss[NL80211_BSS_FREQUENCY])
+ sl->e->channel = nl80211_freq2channel(nla_get_u32(
+ bss[NL80211_BSS_FREQUENCY]));
+
+ if (bss[NL80211_BSS_INFORMATION_ELEMENTS])
+ nl80211_get_scanlist_ie(bss, sl->e);
+
+ if (bss[NL80211_BSS_SIGNAL_MBM])
+ {
+ sl->e->signal =
+ (uint8_t)((int32_t)nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]) / 100);
+
+ rssi = sl->e->signal - 0x100;
+
+ if (rssi < -110)
+ rssi = -110;
+ else if (rssi > -40)
+ rssi = -40;
+
+ sl->e->quality = (rssi + 110);
+ sl->e->quality_max = 70;
+ }
+
+ if (sl->e->crypto.enabled && !sl->e->crypto.wpa_version)
+ {
+ sl->e->crypto.auth_algs = IWINFO_AUTH_OPEN | IWINFO_AUTH_SHARED;
+ sl->e->crypto.pair_ciphers = IWINFO_CIPHER_WEP40 | IWINFO_CIPHER_WEP104;
+ }
+
+ sl->e++;
+ sl->len++;
+
+ return NL_SKIP;
+}
+
+static int nl80211_get_scanlist_nl(const char *ifname, char *buf, int *len)
+{
+ struct nl80211_msg_conveyor *req;
+ struct nl80211_scanlist sl = { .e = (struct iwinfo_scanlist_entry *)buf };
+
+ req = nl80211_msg(ifname, NL80211_CMD_TRIGGER_SCAN, 0);
+ if (req)
+ {
+ nl80211_send(req, NULL, NULL);
+ nl80211_free(req);
+ }
+
+ nl80211_wait("nl80211", "scan", NL80211_CMD_NEW_SCAN_RESULTS);
+
+ req = nl80211_msg(ifname, NL80211_CMD_GET_SCAN, NLM_F_DUMP);
+ if (req)
+ {
+ nl80211_send(req, nl80211_get_scanlist_cb, &sl);
+ nl80211_free(req);
+ }
+
+ *len = sl.len * sizeof(struct iwinfo_scanlist_entry);
+ return *len ? 0 : -1;
+}
+
+int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
+{
+ int freq, rssi, qmax, count;
+ char *res;
+ char ssid[128] = { 0 };
+ char bssid[18] = { 0 };
+ char cipher[256] = { 0 };
+
+ /* Got a radioX pseudo interface, find some interface on it or create one */
+ if (!strncmp(ifname, "radio", 5))
+ {
+ /* Reuse existing interface */
+ if ((res = nl80211_phy2ifname(ifname)) != NULL)
+ {
+ return nl80211_get_scanlist(res, buf, len);
+ }
+
+ /* Need to spawn a temporary iface for scanning */
+ else if ((res = nl80211_ifadd(ifname)) != NULL)
+ {
+ count = nl80211_get_scanlist(res, buf, len);
+ nl80211_ifdel(res);
+ return count;
+ }
+ }
+
+ struct iwinfo_scanlist_entry *e = (struct iwinfo_scanlist_entry *)buf;
+
+ /* WPA supplicant */
+ if ((res = nl80211_wpactl_info(ifname, "SCAN", "CTRL-EVENT-SCAN-RESULTS")))
+ {
+ if ((res = nl80211_wpactl_info(ifname, "SCAN_RESULTS", NULL)))
+ {
+ nl80211_get_quality_max(ifname, &qmax);
+
+ /* skip header line */
+ while (*res++ != '\n');
+
+ count = 0;
+
+ while (sscanf(res, "%17s %d %d %255s%*[ \t]%127[^\n]\n",
+ bssid, &freq, &rssi, cipher, ssid) > 0)
+ {
+ /* BSSID */
+ e->mac[0] = strtol(&bssid[0], NULL, 16);
+ e->mac[1] = strtol(&bssid[3], NULL, 16);
+ e->mac[2] = strtol(&bssid[6], NULL, 16);
+ e->mac[3] = strtol(&bssid[9], NULL, 16);
+ e->mac[4] = strtol(&bssid[12], NULL, 16);
+ e->mac[5] = strtol(&bssid[15], NULL, 16);
+
+ /* SSID */
+ memcpy(e->ssid, ssid, min(strlen(ssid), sizeof(e->ssid) - 1));
+
+ /* Mode (assume master) */
+ e->mode = IWINFO_OPMODE_MASTER;
+
+ /* Channel */
+ e->channel = nl80211_freq2channel(freq);
+
+ /* Signal */
+ e->signal = rssi;
+
+ /* Quality */
+ if (rssi < 0)
+ {
+ /* The cfg80211 wext compat layer assumes a signal range
+ * of -110 dBm to -40 dBm, the quality value is derived
+ * by adding 110 to the signal level */
+ if (rssi < -110)
+ rssi = -110;
+ else if (rssi > -40)
+ rssi = -40;
+
+ e->quality = (rssi + 110);
+ }
+ else
+ {
+ e->quality = rssi;
+ }
+
+ /* Max. Quality */
+ e->quality_max = qmax;
+
+ /* Crypto */
+ nl80211_get_scancrypto(cipher, &e->crypto);
+
+ /* advance to next line */
+ while (*res && *res++ != '\n');
+
+ count++;
+ e++;
+
+ memset(ssid, 0, sizeof(ssid));
+ memset(bssid, 0, sizeof(bssid));
+ memset(cipher, 0, sizeof(cipher));
+ }
+
+ *len = count * sizeof(struct iwinfo_scanlist_entry);
+ return 0;
+ }
+ }
+
+ /* AP scan */
+ else
+ {
+ /* Got a temp interface, don't create yet another one */
+ if (!strncmp(ifname, "tmp.", 4))
+ {
+ if (!iwinfo_ifup(ifname))
+ return -1;
+
+ nl80211_get_scanlist_nl(ifname, buf, len);
+ iwinfo_ifdown(ifname);
+ return 0;
+ }
+
+ /* Spawn a new scan interface */
+ else
+ {
+ if (!(res = nl80211_ifadd(ifname)))
+ goto out;
+
+ if (!iwinfo_ifmac(res))
+ goto out;
+
+ /* if we can take the new interface up, the driver supports an
+ * additional interface and there's no need to tear down the ap */
+ if (iwinfo_ifup(res))
+ {
+ nl80211_get_scanlist_nl(res, buf, len);
+ iwinfo_ifdown(res);
+ }
+
+ /* driver cannot create secondary interface, take down ap
+ * during scan */
+ else if (iwinfo_ifdown(ifname) && iwinfo_ifup(res))
+ {
+ nl80211_get_scanlist_nl(res, buf, len);
+ iwinfo_ifdown(res);
+ iwinfo_ifup(ifname);
+ nl80211_hostapd_hup(ifname);
+ }
+
+ out:
+ nl80211_ifdel(res);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static int nl80211_get_freqlist_cb(struct nl_msg *msg, void *arg)
+{
+ int bands_remain, freqs_remain;
+
+ struct nl80211_array_buf *arr = arg;
+ struct iwinfo_freqlist_entry *e = arr->buf;
+
+ struct nlattr **attr = nl80211_parse(msg);
+ struct nlattr *bands[NL80211_BAND_ATTR_MAX + 1];
+ struct nlattr *freqs[NL80211_FREQUENCY_ATTR_MAX + 1];
+ struct nlattr *band, *freq;
+
+ static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
+ [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },
+ [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG },
+ [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },
+ [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },
+ [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
+ [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },
+ };
+
+ nla_for_each_nested(band, attr[NL80211_ATTR_WIPHY_BANDS], bands_remain)
+ {
+ nla_parse(bands, NL80211_BAND_ATTR_MAX,
+ nla_data(band), nla_len(band), NULL);
+
+ nla_for_each_nested(freq, bands[NL80211_BAND_ATTR_FREQS], freqs_remain)
+ {
+ nla_parse(freqs, NL80211_FREQUENCY_ATTR_MAX,
+ nla_data(freq), nla_len(freq), NULL);
+
+ if (!freqs[NL80211_FREQUENCY_ATTR_FREQ] ||
+ freqs[NL80211_FREQUENCY_ATTR_DISABLED])
+ continue;
+
+ e->mhz = nla_get_u32(freqs[NL80211_FREQUENCY_ATTR_FREQ]);
+ e->channel = nl80211_freq2channel(e->mhz);
+
+ e->restricted = (
+ freqs[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] ||
+ freqs[NL80211_FREQUENCY_ATTR_NO_IBSS] ||
+ freqs[NL80211_FREQUENCY_ATTR_RADAR]
+ ) ? 1 : 0;
+
+ e++;
+ arr->count++;
+ }
+ }
+
+ return NL_SKIP;
+}
+
+int nl80211_get_freqlist(const char *ifname, char *buf, int *len)
+{
+ struct nl80211_msg_conveyor *req;
+ struct nl80211_array_buf arr = { .buf = buf, .count = 0 };
+
+ req = nl80211_msg(ifname, NL80211_CMD_GET_WIPHY, 0);
+ if (req)
+ {
+ nl80211_send(req, nl80211_get_freqlist_cb, &arr);
+ nl80211_free(req);
+ }
+
+ if (arr.count > 0)
+ {
+ *len = arr.count * sizeof(struct iwinfo_freqlist_entry);
+ return 0;
+ }
+
+ return -1;
+}
+
+static int nl80211_get_country_cb(struct nl_msg *msg, void *arg)
+{
+ char *buf = arg;
+ struct nlattr **attr = nl80211_parse(msg);
+
+ if (attr[NL80211_ATTR_REG_ALPHA2])
+ memcpy(buf, nla_data(attr[NL80211_ATTR_REG_ALPHA2]), 2);
+ else
+ buf[0] = 0;
+
+ return NL_SKIP;
+}
+
+int nl80211_get_country(const char *ifname, char *buf)
+{
+ int rv = -1;
+ struct nl80211_msg_conveyor *req;
+
+ req = nl80211_msg(ifname, NL80211_CMD_GET_REG, 0);
+ if (req)
+ {
+ nl80211_send(req, nl80211_get_country_cb, buf);
+ nl80211_free(req);
+
+ if (buf[0])
+ rv = 0;
+ }
+
+ return rv;
+}
+
+int nl80211_get_countrylist(const char *ifname, char *buf, int *len)
+{
+ int i, count;
+ struct iwinfo_country_entry *e = (struct iwinfo_country_entry *)buf;
+ const struct iwinfo_iso3166_label *l;
+
+ for (l = IWINFO_ISO3166_NAMES, count = 0; l->iso3166; l++, e++, count++)
+ {
+ e->iso3166 = l->iso3166;
+ e->ccode[0] = (l->iso3166 / 256);
+ e->ccode[1] = (l->iso3166 % 256);
+ }
+
+ *len = (count * sizeof(struct iwinfo_country_entry));
+ return 0;
+}
+
+static int nl80211_get_hwmodelist_cb(struct nl_msg *msg, void *arg)
+{
+ int *modes = arg;
+ int bands_remain, freqs_remain;
+ uint16_t caps = 0;
+ struct nlattr **attr = nl80211_parse(msg);
+ struct nlattr *bands[NL80211_BAND_ATTR_MAX + 1];
+ struct nlattr *freqs[NL80211_FREQUENCY_ATTR_MAX + 1];
+ struct nlattr *band, *freq;
+
+ *modes = 0;
+
+ if (attr[NL80211_ATTR_WIPHY_BANDS])
+ {
+ nla_for_each_nested(band, attr[NL80211_ATTR_WIPHY_BANDS], bands_remain)
+ {
+ nla_parse(bands, NL80211_BAND_ATTR_MAX,
+ nla_data(band), nla_len(band), NULL);
+
+ if (bands[NL80211_BAND_ATTR_HT_CAPA])
+ caps = nla_get_u16(bands[NL80211_BAND_ATTR_HT_CAPA]);
+
+ /* Treat any nonzero capability as 11n */
+ if (caps > 0)
+ *modes |= IWINFO_80211_N;
+
+ nla_for_each_nested(freq, bands[NL80211_BAND_ATTR_FREQS],
+ freqs_remain)
+ {
+ nla_parse(freqs, NL80211_FREQUENCY_ATTR_MAX,
+ nla_data(freq), nla_len(freq), NULL);
+
+ if (!freqs[NL80211_FREQUENCY_ATTR_FREQ])
+ continue;
+
+ if (nla_get_u32(freqs[NL80211_FREQUENCY_ATTR_FREQ]) < 2485)
+ {
+ *modes |= IWINFO_80211_B;
+ *modes |= IWINFO_80211_G;
+ }
+ else
+ {
+ *modes |= IWINFO_80211_A;
+ }
+ }
+ }
+ }
+
+ return NL_SKIP;
+}
+
+int nl80211_get_hwmodelist(const char *ifname, int *buf)
+{
+ struct nl80211_msg_conveyor *req;
+
+ req = nl80211_msg(ifname, NL80211_CMD_GET_WIPHY, 0);
+ if (req)
+ {
+ nl80211_send(req, nl80211_get_hwmodelist_cb, buf);
+ nl80211_free(req);
+ }
+
+ return *buf ? 0 : -1;
+}
+
+int nl80211_get_mbssid_support(const char *ifname, int *buf)
+{
+ /* Test whether we can create another interface */
+ char *nif = nl80211_ifadd(ifname);
+
+ if (nif)
+ {
+ *buf = (iwinfo_ifmac(nif) && iwinfo_ifup(nif));
+
+ iwinfo_ifdown(nif);
+ nl80211_ifdel(nif);
+
+ return 0;
+ }
+
+ return -1;
+}
+
+int nl80211_get_hardware_id(const char *ifname, char *buf)
+{
+ int rv;
+ char *res;
+
+ /* Got a radioX pseudo interface, find some interface on it or create one */
+ if (!strncmp(ifname, "radio", 5))
+ {
+ /* Reuse existing interface */
+ if ((res = nl80211_phy2ifname(ifname)) != NULL)
+ {
+ rv = wext_get_hardware_id(res, buf);
+ }
+
+ /* Need to spawn a temporary iface for finding IDs */
+ else if ((res = nl80211_ifadd(ifname)) != NULL)
+ {
+ rv = wext_get_hardware_id(res, buf);
+ nl80211_ifdel(res);
+ }
+ }
+ else
+ {
+ rv = wext_get_hardware_id(ifname, buf);
+ }
+
+ /* Failed to obtain hardware IDs, search board config */
+ if (rv)
+ {
+ rv = iwinfo_hardware_id_from_mtd((struct iwinfo_hardware_id *)buf);
+ }
+
+ return rv;
+}
+
+static const struct iwinfo_hardware_entry *
+nl80211_get_hardware_entry(const char *ifname)
+{
+ struct iwinfo_hardware_id id;
+
+ if (nl80211_get_hardware_id(ifname, (char *)&id))
+ return NULL;
+
+ return iwinfo_hardware(&id);
+}
+
+int nl80211_get_hardware_name(const char *ifname, char *buf)
+{
+ const struct iwinfo_hardware_entry *hw;
+
+ if (!(hw = nl80211_get_hardware_entry(ifname)))
+ sprintf(buf, "Generic MAC80211");
+ else
+ sprintf(buf, "%s %s", hw->vendor_name, hw->device_name);
+
+ return 0;
+}
+
+int nl80211_get_txpower_offset(const char *ifname, int *buf)
+{
+ const struct iwinfo_hardware_entry *hw;
+
+ if (!(hw = nl80211_get_hardware_entry(ifname)))
+ return -1;
+
+ *buf = hw->txpower_offset;
+ return 0;
+}
+
+int nl80211_get_frequency_offset(const char *ifname, int *buf)
+{
+ const struct iwinfo_hardware_entry *hw;
+
+ if (!(hw = nl80211_get_hardware_entry(ifname)))
+ return -1;
+
+ *buf = hw->frequency_offset;
+ return 0;
+}
diff --git a/package/iwinfo/src/iwinfo_utils.c b/package/iwinfo/src/iwinfo_utils.c
new file mode 100644
index 000000000..164e51f84
--- /dev/null
+++ b/package/iwinfo/src/iwinfo_utils.c
@@ -0,0 +1,347 @@
+/*
+ * iwinfo - Wireless Information Library - Shared utility routines
+ *
+ * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * The iwinfo library 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.
+ *
+ * The iwinfo library 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 the iwinfo library. If not, see http://www.gnu.org/licenses/.
+ *
+ * The signal handling code is derived from the official madwifi tools,
+ * wlanconfig.c in particular. The encryption property handling was
+ * inspired by the hostapd madwifi driver.
+ */
+
+#include "iwinfo/utils.h"
+
+
+static int ioctl_socket = -1;
+
+static int iwinfo_ioctl_socket(void)
+{
+ /* Prepare socket */
+ if( ioctl_socket == -1 )
+ {
+ ioctl_socket = socket(AF_INET, SOCK_DGRAM, 0);
+ fcntl(ioctl_socket, F_SETFD, fcntl(ioctl_socket, F_GETFD) | FD_CLOEXEC);
+ }
+
+ return ioctl_socket;
+}
+
+int iwinfo_ioctl(int cmd, void *ifr)
+{
+ int s = iwinfo_ioctl_socket();
+ return ioctl(s, cmd, ifr);
+}
+
+int iwinfo_dbm2mw(int in)
+{
+ double res = 1.0;
+ int ip = in / 10;
+ int fp = in % 10;
+ int k;
+
+ for(k = 0; k < ip; k++) res *= 10;
+ for(k = 0; k < fp; k++) res *= LOG10_MAGIC;
+
+ return (int)res;
+}
+
+int iwinfo_mw2dbm(int in)
+{
+ double fin = (double) in;
+ int res = 0;
+
+ while(fin > 10.0)
+ {
+ res += 10;
+ fin /= 10.0;
+ }
+
+ while(fin > 1.000001)
+ {
+ res += 1;
+ fin /= LOG10_MAGIC;
+ }
+
+ return (int)res;
+}
+
+int iwinfo_ifup(const char *ifname)
+{
+ struct ifreq ifr;
+
+ strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+
+ if( iwinfo_ioctl(SIOCGIFFLAGS, &ifr) )
+ return 0;
+
+ ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
+
+ return !iwinfo_ioctl(SIOCSIFFLAGS, &ifr);
+}
+
+int iwinfo_ifdown(const char *ifname)
+{
+ struct ifreq ifr;
+
+ strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+
+ if( iwinfo_ioctl(SIOCGIFFLAGS, &ifr) )
+ return 0;
+
+ ifr.ifr_flags &= ~(IFF_UP | IFF_RUNNING);
+
+ return !iwinfo_ioctl(SIOCSIFFLAGS, &ifr);
+}
+
+int iwinfo_ifmac(const char *ifname)
+{
+ struct ifreq ifr;
+
+ strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+
+ if( iwinfo_ioctl(SIOCGIFHWADDR, &ifr) )
+ return 0;
+
+ ifr.ifr_hwaddr.sa_data[1]++;
+ ifr.ifr_hwaddr.sa_data[2]++;
+
+ return !iwinfo_ioctl(SIOCSIFHWADDR, &ifr);
+}
+
+void iwinfo_close(void)
+{
+ if( ioctl_socket > -1 )
+ close(ioctl_socket);
+}
+
+struct iwinfo_hardware_entry * iwinfo_hardware(struct iwinfo_hardware_id *id)
+{
+ const struct iwinfo_hardware_entry *e;
+
+ for (e = IWINFO_HARDWARE_ENTRIES; e->vendor_name; e++)
+ {
+ if ((e->vendor_id != 0xffff) && (e->vendor_id != id->vendor_id))
+ continue;
+
+ if ((e->device_id != 0xffff) && (e->device_id != id->device_id))
+ continue;
+
+ if ((e->subsystem_vendor_id != 0xffff) &&
+ (e->subsystem_vendor_id != id->subsystem_vendor_id))
+ continue;
+
+ if ((e->subsystem_device_id != 0xffff) &&
+ (e->subsystem_device_id != id->subsystem_device_id))
+ continue;
+
+ return (struct iwinfo_hardware_entry *)e;
+ }
+
+ return NULL;
+}
+
+int iwinfo_hardware_id_from_mtd(struct iwinfo_hardware_id *id)
+{
+ FILE *mtd;
+ uint16_t *bc;
+
+ int fd, len, off;
+ char buf[128];
+
+ if (!(mtd = fopen("/proc/mtd", "r")))
+ return -1;
+
+ while (fgets(buf, sizeof(buf), mtd) > 0)
+ {
+ if (fscanf(mtd, "mtd%d: %*x %x %127s", &off, &len, buf) < 3 ||
+ (strcmp(buf, "\"boardconfig\"") && strcmp(buf, "\"EEPROM\"") &&
+ strcmp(buf, "\"factory\"")))
+ {
+ off = -1;
+ continue;
+ }
+
+ break;
+ }
+
+ fclose(mtd);
+
+ if (off < 0)
+ return -1;
+
+ snprintf(buf, sizeof(buf), "/dev/mtdblock%d", off);
+
+ if ((fd = open(buf, O_RDONLY)) < 0)
+ return -1;
+
+ bc = mmap(NULL, len, PROT_READ, MAP_PRIVATE|MAP_LOCKED, fd, 0);
+
+ if ((void *)bc != MAP_FAILED)
+ {
+ id->vendor_id = 0;
+ id->device_id = 0;
+
+ for (off = len / 2 - 0x800; off >= 0; off -= 0x800)
+ {
+ /* AR531X board data magic */
+ if ((bc[off] == 0x3533) && (bc[off + 1] == 0x3131))
+ {
+ id->vendor_id = bc[off + 0x7d];
+ id->device_id = bc[off + 0x7c];
+ id->subsystem_vendor_id = bc[off + 0x84];
+ id->subsystem_device_id = bc[off + 0x83];
+ break;
+ }
+
+ /* AR5416 EEPROM magic */
+ else if ((bc[off] == 0xA55A) || (bc[off] == 0x5AA5))
+ {
+ id->vendor_id = bc[off + 0x0D];
+ id->device_id = bc[off + 0x0E];
+ id->subsystem_vendor_id = bc[off + 0x13];
+ id->subsystem_device_id = bc[off + 0x14];
+ break;
+ }
+
+ /* Rt3xxx SoC */
+ else if ((bc[off] == 0x3352) || (bc[off] == 0x5233) ||
+ (bc[off] == 0x3350) || (bc[off] == 0x5033) ||
+ (bc[off] == 0x3050) || (bc[off] == 0x5030) ||
+ (bc[off] == 0x3052) || (bc[off] == 0x5230))
+ {
+ /* vendor: RaLink */
+ id->vendor_id = 0x1814;
+ id->subsystem_vendor_id = 0x1814;
+
+ /* device */
+ if (bc[off] & 0xf0 == 0x30)
+ id->device_id = (bc[off] >> 8) | (bc[off] & 0x00ff) << 8;
+ else
+ id->device_id = bc[off];
+
+ /* subsystem from EEPROM_NIC_CONF0_RF_TYPE */
+ id->subsystem_device_id = (bc[off + 0x1a] & 0x0f00) >> 8;
+ }
+ }
+
+ munmap(bc, len);
+ }
+
+ close(fd);
+
+ return (id->vendor_id && id->device_id) ? 0 : -1;
+}
+
+void iwinfo_parse_rsn(struct iwinfo_crypto_entry *c, uint8_t *data, uint8_t len,
+ uint8_t defcipher, uint8_t defauth)
+{
+ uint16_t i, count;
+
+ static unsigned char ms_oui[3] = { 0x00, 0x50, 0xf2 };
+ static unsigned char ieee80211_oui[3] = { 0x00, 0x0f, 0xac };
+
+ data += 2;
+ len -= 2;
+
+ if (!memcmp(data, ms_oui, 3))
+ c->wpa_version += 1;
+ else if (!memcmp(data, ieee80211_oui, 3))
+ c->wpa_version += 2;
+
+ if (len < 4)
+ {
+ c->group_ciphers |= defcipher;
+ c->pair_ciphers |= defcipher;
+ c->auth_suites |= defauth;
+ return;
+ }
+
+ if (!memcmp(data, ms_oui, 3) || !memcmp(data, ieee80211_oui, 3))
+ {
+ switch (data[3])
+ {
+ case 1: c->group_ciphers |= IWINFO_CIPHER_WEP40; break;
+ case 2: c->group_ciphers |= IWINFO_CIPHER_TKIP; break;
+ case 4: c->group_ciphers |= IWINFO_CIPHER_CCMP; break;
+ case 5: c->group_ciphers |= IWINFO_CIPHER_WEP104; break;
+ case 6: /* AES-128-CMAC */ break;
+ default: /* proprietary */ break;
+ }
+ }
+
+ data += 4;
+ len -= 4;
+
+ if (len < 2)
+ {
+ c->pair_ciphers |= defcipher;
+ c->auth_suites |= defauth;
+ return;
+ }
+
+ count = data[0] | (data[1] << 8);
+ if (2 + (count * 4) > len)
+ return;
+
+ for (i = 0; i < count; i++)
+ {
+ if (!memcmp(data + 2 + (i * 4), ms_oui, 3) ||
+ !memcmp(data + 2 + (i * 4), ieee80211_oui, 3))
+ {
+ switch (data[2 + (i * 4) + 3])
+ {
+ case 1: c->pair_ciphers |= IWINFO_CIPHER_WEP40; break;
+ case 2: c->pair_ciphers |= IWINFO_CIPHER_TKIP; break;
+ case 4: c->pair_ciphers |= IWINFO_CIPHER_CCMP; break;
+ case 5: c->pair_ciphers |= IWINFO_CIPHER_WEP104; break;
+ case 6: /* AES-128-CMAC */ break;
+ default: /* proprietary */ break;
+ }
+ }
+ }
+
+ data += 2 + (count * 4);
+ len -= 2 + (count * 4);
+
+ if (len < 2)
+ {
+ c->auth_suites |= defauth;
+ return;
+ }
+
+ count = data[0] | (data[1] << 8);
+ if (2 + (count * 4) > len)
+ return;
+
+ for (i = 0; i < count; i++)
+ {
+ if (!memcmp(data + 2 + (i * 4), ms_oui, 3) ||
+ !memcmp(data + 2 + (i * 4), ieee80211_oui, 3))
+ {
+ switch (data[2 + (i * 4) + 3])
+ {
+ case 1: c->auth_suites |= IWINFO_KMGMT_8021x; break;
+ case 2: c->auth_suites |= IWINFO_KMGMT_PSK; break;
+ case 3: /* FT/IEEE 802.1X */ break;
+ case 4: /* FT/PSK */ break;
+ case 5: /* IEEE 802.1X/SHA-256 */ break;
+ case 6: /* PSK/SHA-256 */ break;
+ default: /* proprietary */ break;
+ }
+ }
+ }
+
+ data += 2 + (count * 4);
+ len -= 2 + (count * 4);
+}
diff --git a/package/iwinfo/src/iwinfo_wext.c b/package/iwinfo/src/iwinfo_wext.c
new file mode 100644
index 000000000..cf3dccc18
--- /dev/null
+++ b/package/iwinfo/src/iwinfo_wext.c
@@ -0,0 +1,520 @@
+/*
+ * iwinfo - Wireless Information Library - Linux Wireless Extension Backend
+ *
+ * Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * The iwinfo library 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.
+ *
+ * The iwinfo library 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 the iwinfo library. If not, see http://www.gnu.org/licenses/.
+ *
+ * Parts of this code are derived from the Linux wireless tools, iwlib.c,
+ * iwlist.c and iwconfig.c in particular.
+ */
+
+#include "iwinfo.h"
+#include "iwinfo/wext.h"
+
+static double wext_freq2float(const struct iw_freq *in)
+{
+ int i;
+ double res = (double) in->m;
+ for(i = 0; i < in->e; i++) res *= 10;
+ return res;
+}
+
+static inline int wext_freq2mhz(const struct iw_freq *in)
+{
+ int i;
+
+ if( in->e == 6 )
+ {
+ return in->m;
+ }
+ else
+ {
+ return (int)(wext_freq2float(in) / 1000000);
+ }
+}
+
+static inline int wext_ioctl(const char *ifname, int cmd, struct iwreq *wrq)
+{
+ if( !strncmp(ifname, "mon.", 4) )
+ strncpy(wrq->ifr_name, &ifname[4], IFNAMSIZ);
+ else
+ strncpy(wrq->ifr_name, ifname, IFNAMSIZ);
+
+ return iwinfo_ioctl(cmd, wrq);
+}
+
+
+int wext_probe(const char *ifname)
+{
+ struct iwreq wrq;
+
+ if(wext_ioctl(ifname, SIOCGIWNAME, &wrq) >= 0)
+ return 1;
+
+ return 0;
+}
+
+void wext_close(void)
+{
+ /* Nop */
+}
+
+int wext_get_mode(const char *ifname, int *buf)
+{
+ struct iwreq wrq;
+
+ if(wext_ioctl(ifname, SIOCGIWMODE, &wrq) >= 0)
+ {
+ switch(wrq.u.mode)
+ {
+ case 1:
+ *buf = IWINFO_OPMODE_ADHOC;
+ break;
+
+ case 2:
+ *buf = IWINFO_OPMODE_CLIENT;
+ break;
+
+ case 3:
+ *buf = IWINFO_OPMODE_MASTER;
+ break;
+
+ case 6:
+ *buf = IWINFO_OPMODE_MONITOR;
+ break;
+
+ default:
+ *buf = IWINFO_OPMODE_UNKNOWN;
+ break;
+ }
+
+ return 0;
+ }
+
+ return -1;
+}
+
+int wext_get_ssid(const char *ifname, char *buf)
+{
+ struct iwreq wrq;
+
+ wrq.u.essid.pointer = (caddr_t) buf;
+ wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
+ wrq.u.essid.flags = 0;
+
+ if(wext_ioctl(ifname, SIOCGIWESSID, &wrq) >= 0)
+ return 0;
+
+ return -1;
+}
+
+int wext_get_bssid(const char *ifname, char *buf)
+{
+ struct iwreq wrq;
+
+ if(wext_ioctl(ifname, SIOCGIWAP, &wrq) >= 0)
+ {
+ sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
+ (uint8_t)wrq.u.ap_addr.sa_data[0], (uint8_t)wrq.u.ap_addr.sa_data[1],
+ (uint8_t)wrq.u.ap_addr.sa_data[2], (uint8_t)wrq.u.ap_addr.sa_data[3],
+ (uint8_t)wrq.u.ap_addr.sa_data[4], (uint8_t)wrq.u.ap_addr.sa_data[5]);
+
+ return 0;
+ }
+
+ return -1;
+}
+
+int wext_get_bitrate(const char *ifname, int *buf)
+{
+ struct iwreq wrq;
+
+ if(wext_ioctl(ifname, SIOCGIWRATE, &wrq) >= 0)
+ {
+ *buf = (wrq.u.bitrate.value / 1000);
+ return 0;
+ }
+
+ return -1;
+}
+
+int wext_get_channel(const char *ifname, int *buf)
+{
+ struct iwreq wrq;
+ struct iw_range range;
+ double freq;
+ int i;
+
+ if(wext_ioctl(ifname, SIOCGIWFREQ, &wrq) >= 0)
+ {
+ if( wrq.u.freq.m >= 1000 )
+ {
+ freq = wext_freq2float(&wrq.u.freq);
+ wrq.u.data.pointer = (caddr_t) &range;
+ wrq.u.data.length = sizeof(struct iw_range);
+ wrq.u.data.flags = 0;
+
+ if(wext_ioctl(ifname, SIOCGIWRANGE, &wrq) >= 0)
+ {
+ for(i = 0; i < range.num_frequency; i++)
+ {
+ if( wext_freq2float(&range.freq[i]) == freq )
+ {
+ *buf = range.freq[i].i;
+ return 0;
+ }
+ }
+ }
+ }
+ else
+ {
+ *buf = wrq.u.freq.m;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+int wext_get_frequency(const char *ifname, int *buf)
+{
+ struct iwreq wrq;
+ struct iw_range range;
+ int i, channel;
+
+ if(wext_ioctl(ifname, SIOCGIWFREQ, &wrq) >= 0)
+ {
+ /* We got a channel number instead ... */
+ if( wrq.u.freq.m < 1000 )
+ {
+ channel = wrq.u.freq.m;
+ wrq.u.data.pointer = (caddr_t) &range;
+ wrq.u.data.length = sizeof(struct iw_range);
+ wrq.u.data.flags = 0;
+
+ if(wext_ioctl(ifname, SIOCGIWRANGE, &wrq) >= 0)
+ {
+ for(i = 0; i < range.num_frequency; i++)
+ {
+ if( range.freq[i].i == channel )
+ {
+ *buf = wext_freq2mhz(&range.freq[i]);
+ return 0;
+ }
+ }
+ }
+ }
+ else
+ {
+ *buf = wext_freq2mhz(&wrq.u.freq);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+int wext_get_txpower(const char *ifname, int *buf)
+{
+ struct iwreq wrq;
+
+ wrq.u.txpower.flags = 0;
+
+ if(wext_ioctl(ifname, SIOCGIWTXPOW, &wrq) >= 0)
+ {
+ if(wrq.u.txpower.flags & IW_TXPOW_MWATT)
+ *buf = iwinfo_mw2dbm(wrq.u.txpower.value);
+ else
+ *buf = wrq.u.txpower.value;
+
+ return 0;
+ }
+
+ return -1;
+}
+
+int wext_get_signal(const char *ifname, int *buf)
+{
+ struct iwreq wrq;
+ struct iw_statistics stats;
+
+ wrq.u.data.pointer = (caddr_t) &stats;
+ wrq.u.data.length = sizeof(struct iw_statistics);
+ wrq.u.data.flags = 1;
+
+ if(wext_ioctl(ifname, SIOCGIWSTATS, &wrq) >= 0)
+ {
+ *buf = (stats.qual.updated & IW_QUAL_DBM)
+ ? (stats.qual.level - 0x100) : stats.qual.level;
+
+ return 0;
+ }
+
+ return -1;
+}
+
+int wext_get_noise(const char *ifname, int *buf)
+{
+ struct iwreq wrq;
+ struct iw_statistics stats;
+
+ wrq.u.data.pointer = (caddr_t) &stats;
+ wrq.u.data.length = sizeof(struct iw_statistics);
+ wrq.u.data.flags = 1;
+
+ if(wext_ioctl(ifname, SIOCGIWSTATS, &wrq) >= 0)
+ {
+ *buf = (stats.qual.updated & IW_QUAL_DBM)
+ ? (stats.qual.noise - 0x100) : stats.qual.noise;
+
+ return 0;
+ }
+
+ return -1;
+}
+
+int wext_get_quality(const char *ifname, int *buf)
+{
+ struct iwreq wrq;
+ struct iw_statistics stats;
+
+ wrq.u.data.pointer = (caddr_t) &stats;
+ wrq.u.data.length = sizeof(struct iw_statistics);
+ wrq.u.data.flags = 1;
+
+ if(wext_ioctl(ifname, SIOCGIWSTATS, &wrq) >= 0)
+ {
+ *buf = stats.qual.qual;
+ return 0;
+ }
+
+ return -1;
+}
+
+int wext_get_quality_max(const char *ifname, int *buf)
+{
+ struct iwreq wrq;
+ struct iw_range range;
+
+ wrq.u.data.pointer = (caddr_t) &range;
+ wrq.u.data.length = sizeof(struct iw_range);
+ wrq.u.data.flags = 0;
+
+ if(wext_ioctl(ifname, SIOCGIWRANGE, &wrq) >= 0)
+ {
+ *buf = range.max_qual.qual;
+ return 0;
+ }
+
+ return -1;
+}
+
+int wext_get_assoclist(const char *ifname, char *buf, int *len)
+{
+ /* Stub */
+ return -1;
+}
+
+int wext_get_txpwrlist(const char *ifname, char *buf, int *len)
+{
+ struct iwreq wrq;
+ struct iw_range range;
+ struct iwinfo_txpwrlist_entry entry;
+ int i;
+
+ wrq.u.data.pointer = (caddr_t) &range;
+ wrq.u.data.length = sizeof(struct iw_range);
+ wrq.u.data.flags = 0;
+
+ if( (wext_ioctl(ifname, SIOCGIWRANGE, &wrq) >= 0) &&
+ (range.num_txpower > 0) && (range.num_txpower <= IW_MAX_TXPOWER) &&
+ !(range.txpower_capa & IW_TXPOW_RELATIVE)
+ ) {
+ for( i = 0; i < range.num_txpower; i++ )
+ {
+ if( range.txpower_capa & IW_TXPOW_MWATT )
+ {
+ entry.dbm = iwinfo_mw2dbm(range.txpower[i]);
+ entry.mw = range.txpower[i];
+ }
+
+ /* Madwifi does neither set mW not dBm caps, also iwlist assumes
+ * dBm if mW is not set, so don't check here... */
+ else /* if( range.txpower_capa & IW_TXPOW_DBM ) */
+ {
+ entry.dbm = range.txpower[i];
+ entry.mw = iwinfo_dbm2mw(range.txpower[i]);
+ }
+
+ memcpy(&buf[i*sizeof(entry)], &entry, sizeof(entry));
+ }
+
+ *len = i * sizeof(entry);
+ return 0;
+ }
+
+ return -1;
+}
+
+int wext_get_freqlist(const char *ifname, char *buf, int *len)
+{
+ struct iwreq wrq;
+ struct iw_range range;
+ struct iwinfo_freqlist_entry entry;
+ int i, bl;
+
+ wrq.u.data.pointer = (caddr_t) &range;
+ wrq.u.data.length = sizeof(struct iw_range);
+ wrq.u.data.flags = 0;
+
+ if(wext_ioctl(ifname, SIOCGIWRANGE, &wrq) >= 0)
+ {
+ bl = 0;
+
+ for(i = 0; i < range.num_frequency; i++)
+ {
+ entry.mhz = wext_freq2mhz(&range.freq[i]);
+ entry.channel = range.freq[i].i;
+ entry.restricted = 0;
+
+ memcpy(&buf[bl], &entry, sizeof(struct iwinfo_freqlist_entry));
+ bl += sizeof(struct iwinfo_freqlist_entry);
+ }
+
+ *len = bl;
+ return 0;
+ }
+
+ return -1;
+}
+
+int wext_get_country(const char *ifname, char *buf)
+{
+ sprintf(buf, "00");
+ return 0;
+}
+
+int wext_get_countrylist(const char *ifname, char *buf, int *len)
+{
+ /* Stub */
+ return -1;
+}
+
+int wext_get_hwmodelist(const char *ifname, int *buf)
+{
+ char chans[IWINFO_BUFSIZE] = { 0 };
+ struct iwinfo_freqlist_entry *e = NULL;
+ int len = 0;
+
+ *buf = 0;
+
+ if( !wext_get_freqlist(ifname, chans, &len) )
+ {
+ for( e = (struct iwinfo_freqlist_entry *)chans; e->channel; e++ )
+ {
+ if( e->channel <= 14 )
+ {
+ *buf |= IWINFO_80211_B;
+ *buf |= IWINFO_80211_G;
+ }
+ else
+ {
+ *buf |= IWINFO_80211_A;
+ }
+ }
+
+ return 0;
+ }
+
+ return -1;
+}
+
+int wext_get_encryption(const char *ifname, char *buf)
+{
+ /* No reliable crypto info in wext */
+ return -1;
+}
+
+int wext_get_mbssid_support(const char *ifname, int *buf)
+{
+ /* No multi bssid support atm */
+ return -1;
+}
+
+static char * wext_sysfs_ifname_file(const char *ifname, const char *path)
+{
+ FILE *f;
+ static char buf[128];
+ char *rv = NULL;
+
+ snprintf(buf, sizeof(buf), "/sys/class/net/%s/%s", ifname, path);
+
+ if ((f = fopen(buf, "r")) != NULL)
+ {
+ memset(buf, 0, sizeof(buf));
+
+ if (fread(buf, 1, sizeof(buf), f))
+ rv = buf;
+
+ fclose(f);
+ }
+
+ return rv;
+}
+
+int wext_get_hardware_id(const char *ifname, char *buf)
+{
+ char *data;
+ struct iwinfo_hardware_id *id = (struct iwinfo_hardware_id *)buf;
+
+ memset(id, 0, sizeof(struct iwinfo_hardware_id));
+
+ data = wext_sysfs_ifname_file(ifname, "device/vendor");
+ if (data)
+ id->vendor_id = strtoul(data, NULL, 16);
+
+ data = wext_sysfs_ifname_file(ifname, "device/device");
+ if (data)
+ id->device_id = strtoul(data, NULL, 16);
+
+ data = wext_sysfs_ifname_file(ifname, "device/subsystem_device");
+ if (data)
+ id->subsystem_device_id = strtoul(data, NULL, 16);
+
+ data = wext_sysfs_ifname_file(ifname, "device/subsystem_vendor");
+ if (data)
+ id->subsystem_vendor_id = strtoul(data, NULL, 16);
+
+ return (id->vendor_id > 0 && id->device_id > 0) ? 0 : -1;
+}
+
+int wext_get_hardware_name(const char *ifname, char *buf)
+{
+ sprintf(buf, "Generic WEXT");
+ return 0;
+}
+
+int wext_get_txpower_offset(const char *ifname, int *buf)
+{
+ /* Stub */
+ *buf = 0;
+ return -1;
+}
+
+int wext_get_frequency_offset(const char *ifname, int *buf)
+{
+ /* Stub */
+ *buf = 0;
+ return -1;
+}
diff --git a/package/iwinfo/src/iwinfo_wext_scan.c b/package/iwinfo/src/iwinfo_wext_scan.c
new file mode 100644
index 000000000..ecd40d71e
--- /dev/null
+++ b/package/iwinfo/src/iwinfo_wext_scan.c
@@ -0,0 +1,527 @@
+/*
+ * iwinfo - Wireless Information Library - Linux Wireless Extension Backend
+ *
+ * Copyright (C) 2009-2010 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * The iwinfo library 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.
+ *
+ * The iwinfo library 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 the iwinfo library. If not, see http://www.gnu.org/licenses/.
+ *
+ * Parts of this code are derived from the Linux wireless tools, iwlib.c,
+ * iwlist.c and iwconfig.c in particular.
+ */
+
+#include "iwinfo.h"
+#include "iwinfo/wext_scan.h"
+
+
+static int wext_ioctl(const char *ifname, int cmd, struct iwreq *wrq)
+{
+ strncpy(wrq->ifr_name, ifname, IFNAMSIZ);
+ return iwinfo_ioctl(cmd, wrq);
+}
+
+static inline double wext_freq2float(const struct iw_freq *in)
+{
+ int i;
+ double res = (double) in->m;
+ for(i = 0; i < in->e; i++) res *= 10;
+ return res;
+}
+
+static inline int wext_extract_event(struct stream_descr *stream, struct iw_event *iwe, int wev)
+{
+ const struct iw_ioctl_description *descr = NULL;
+ int event_type = 0;
+ unsigned int event_len = 1;
+ char *pointer;
+ unsigned cmd_index; /* *MUST* be unsigned */
+
+ /* Check for end of stream */
+ if((stream->current + IW_EV_LCP_PK_LEN) > stream->end)
+ return 0;
+
+ /* Extract the event header (to get the event id).
+ * Note : the event may be unaligned, therefore copy... */
+ memcpy((char *) iwe, stream->current, IW_EV_LCP_PK_LEN);
+
+ /* Check invalid events */
+ if(iwe->len <= IW_EV_LCP_PK_LEN)
+ return -1;
+
+ /* Get the type and length of that event */
+ if(iwe->cmd <= SIOCIWLAST)
+ {
+ cmd_index = iwe->cmd - SIOCIWFIRST;
+ if(cmd_index < standard_ioctl_num)
+ descr = &(standard_ioctl_descr[cmd_index]);
+ }
+ else
+ {
+ cmd_index = iwe->cmd - IWEVFIRST;
+ if(cmd_index < standard_event_num)
+ descr = &(standard_event_descr[cmd_index]);
+ }
+
+ if(descr != NULL)
+ event_type = descr->header_type;
+
+ /* Unknown events -> event_type=0 => IW_EV_LCP_PK_LEN */
+ event_len = event_type_size[event_type];
+
+ /* Fixup for earlier version of WE */
+ if((wev <= 18) && (event_type == IW_HEADER_TYPE_POINT))
+ event_len += IW_EV_POINT_OFF;
+
+ /* Check if we know about this event */
+ if(event_len <= IW_EV_LCP_PK_LEN)
+ {
+ /* Skip to next event */
+ stream->current += iwe->len;
+ return 2;
+ }
+
+ event_len -= IW_EV_LCP_PK_LEN;
+
+ /* Set pointer on data */
+ if(stream->value != NULL)
+ pointer = stream->value; /* Next value in event */
+ else
+ pointer = stream->current + IW_EV_LCP_PK_LEN; /* First value in event */
+
+ /* Copy the rest of the event (at least, fixed part) */
+ if((pointer + event_len) > stream->end)
+ {
+ /* Go to next event */
+ stream->current += iwe->len;
+ return -2;
+ }
+
+ /* Fixup for WE-19 and later : pointer no longer in the stream */
+ /* Beware of alignement. Dest has local alignement, not packed */
+ if( (wev > 18) && (event_type == IW_HEADER_TYPE_POINT) )
+ memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF, pointer, event_len);
+ else
+ memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len);
+
+ /* Skip event in the stream */
+ pointer += event_len;
+
+ /* Special processing for iw_point events */
+ if(event_type == IW_HEADER_TYPE_POINT)
+ {
+ /* Check the length of the payload */
+ unsigned int extra_len = iwe->len - (event_len + IW_EV_LCP_PK_LEN);
+ if(extra_len > 0)
+ {
+ /* Set pointer on variable part (warning : non aligned) */
+ iwe->u.data.pointer = pointer;
+
+ /* Check that we have a descriptor for the command */
+ if(descr == NULL)
+ /* Can't check payload -> unsafe... */
+ iwe->u.data.pointer = NULL; /* Discard paylod */
+ else
+ {
+ /* Those checks are actually pretty hard to trigger,
+ * because of the checks done in the kernel... */
+
+ unsigned int token_len = iwe->u.data.length * descr->token_size;
+
+ /* Ugly fixup for alignement issues.
+ * If the kernel is 64 bits and userspace 32 bits,
+ * we have an extra 4+4 bytes.
+ * Fixing that in the kernel would break 64 bits userspace. */
+ if((token_len != extra_len) && (extra_len >= 4))
+ {
+ uint16_t alt_dlen = *((uint16_t *) pointer);
+ unsigned int alt_token_len = alt_dlen * descr->token_size;
+ if((alt_token_len + 8) == extra_len)
+ {
+ /* Ok, let's redo everything */
+ pointer -= event_len;
+ pointer += 4;
+ /* Dest has local alignement, not packed */
+ memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF, pointer, event_len);
+ pointer += event_len + 4;
+ iwe->u.data.pointer = pointer;
+ token_len = alt_token_len;
+ }
+ }
+
+ /* Discard bogus events which advertise more tokens than
+ * what they carry... */
+ if(token_len > extra_len)
+ iwe->u.data.pointer = NULL; /* Discard paylod */
+
+ /* Check that the advertised token size is not going to
+ * produce buffer overflow to our caller... */
+ if((iwe->u.data.length > descr->max_tokens)
+ && !(descr->flags & IW_DESCR_FLAG_NOMAX))
+ iwe->u.data.pointer = NULL; /* Discard paylod */
+
+ /* Same for underflows... */
+ if(iwe->u.data.length < descr->min_tokens)
+ iwe->u.data.pointer = NULL; /* Discard paylod */
+ }
+ }
+ else
+ /* No data */
+ iwe->u.data.pointer = NULL;
+
+ /* Go to next event */
+ stream->current += iwe->len;
+ }
+ else
+ {
+ /* Ugly fixup for alignement issues.
+ * If the kernel is 64 bits and userspace 32 bits,
+ * we have an extra 4 bytes.
+ * Fixing that in the kernel would break 64 bits userspace. */
+ if((stream->value == NULL)
+ && ((((iwe->len - IW_EV_LCP_PK_LEN) % event_len) == 4)
+ || ((iwe->len == 12) && ((event_type == IW_HEADER_TYPE_UINT) ||
+ (event_type == IW_HEADER_TYPE_QUAL))) ))
+ {
+ pointer -= event_len;
+ pointer += 4;
+ /* Beware of alignement. Dest has local alignement, not packed */
+ memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len);
+ pointer += event_len;
+ }
+
+ /* Is there more value in the event ? */
+ if((pointer + event_len) <= (stream->current + iwe->len))
+ /* Go to next value */
+ stream->value = pointer;
+ else
+ {
+ /* Go to next event */
+ stream->value = NULL;
+ stream->current += iwe->len;
+ }
+ }
+
+ return 1;
+}
+
+static inline void wext_fill_wpa(unsigned char *iebuf, int ielen, struct iwinfo_scanlist_entry *e)
+{
+ static unsigned char ms_oui[3] = { 0x00, 0x50, 0xf2 };
+
+ while (ielen >= 2 && ielen >= iebuf[1])
+ {
+ switch (iebuf[0])
+ {
+ case 48: /* RSN */
+ iwinfo_parse_rsn(&e->crypto, iebuf + 2, iebuf[1],
+ IWINFO_CIPHER_CCMP, IWINFO_KMGMT_8021x);
+ break;
+
+ case 221: /* Vendor */
+ if (iebuf[1] >= 4 && !memcmp(iebuf + 2, ms_oui, 3) && iebuf[5] == 1)
+ iwinfo_parse_rsn(&e->crypto, iebuf + 6, iebuf[1] - 4,
+ IWINFO_CIPHER_TKIP, IWINFO_KMGMT_PSK);
+ break;
+ }
+
+ ielen -= iebuf[1] + 2;
+ iebuf += iebuf[1] + 2;
+ }
+}
+
+
+static inline void wext_fill_entry(struct stream_descr *stream, struct iw_event *event,
+ struct iw_range *iw_range, int has_range, struct iwinfo_scanlist_entry *e)
+{
+ int i;
+ double freq;
+
+ /* Now, let's decode the event */
+ switch(event->cmd)
+ {
+ case SIOCGIWAP:
+ memcpy(e->mac, &event->u.ap_addr.sa_data, 6);
+ break;
+
+ case SIOCGIWFREQ:
+ if( event->u.freq.m >= 1000 )
+ {
+ freq = wext_freq2float(&(event->u.freq));
+
+ for(i = 0; i < iw_range->num_frequency; i++)
+ {
+ if( wext_freq2float(&iw_range->freq[i]) == freq )
+ {
+ e->channel = iw_range->freq[i].i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ e->channel = event->u.freq.m;
+ }
+
+ break;
+
+ case SIOCGIWMODE:
+ switch(event->u.mode)
+ {
+ case 1:
+ e->mode = IWINFO_OPMODE_ADHOC;
+ break;
+
+ case 2:
+ case 3:
+ e->mode = IWINFO_OPMODE_MASTER;
+ break;
+
+ default:
+ e->mode = IWINFO_OPMODE_UNKNOWN;
+ break;
+ }
+
+ break;
+
+ case SIOCGIWESSID:
+ if( event->u.essid.pointer && event->u.essid.length && event->u.essid.flags )
+ memcpy(e->ssid, event->u.essid.pointer, event->u.essid.length);
+
+ break;
+
+ case SIOCGIWENCODE:
+ e->crypto.enabled = !(event->u.data.flags & IW_ENCODE_DISABLED);
+ break;
+
+ case IWEVQUAL:
+ e->signal = event->u.qual.level;
+ e->quality = event->u.qual.qual;
+ e->quality_max = iw_range->max_qual.qual;
+ break;
+#if 0
+ case SIOCGIWRATE:
+ if(state->val_index == 0)
+ {
+ lua_pushstring(L, "bitrates");
+ lua_newtable(L);
+ }
+ //iw_print_bitrate(buffer, sizeof(buffer), event->u.bitrate.value);
+ snprintf(buffer, sizeof(buffer), "%d", event->u.bitrate.value);
+ lua_pushinteger(L, state->val_index + 1);
+ lua_pushstring(L, buffer);
+ lua_settable(L, -3);
+
+ /* Check for termination */
+ if(stream->value == NULL)
+ {
+ lua_settable(L, -3);
+ state->val_index = 0;
+ } else
+ state->val_index++;
+ break;
+#endif
+ case IWEVGENIE:
+ wext_fill_wpa(event->u.data.pointer, event->u.data.length, e);
+ break;
+ }
+}
+
+
+int wext_get_scanlist(const char *ifname, char *buf, int *len)
+{
+ struct iwreq wrq;
+ struct iw_scan_req scanopt; /* Options for 'set' */
+ unsigned char *buffer = NULL; /* Results */
+ int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */
+ struct iw_range range;
+ int has_range = 1;
+ struct timeval tv; /* Select timeout */
+ int timeout = 15000000; /* 15s */
+
+ int entrylen = 0;
+ struct iwinfo_scanlist_entry e;
+
+ wrq.u.data.pointer = (caddr_t) &range;
+ wrq.u.data.length = sizeof(struct iw_range);
+ wrq.u.data.flags = 0;
+
+ if( wext_ioctl(ifname, SIOCGIWRANGE, &wrq) >= 0 )
+ {
+ /* Init timeout value -> 250ms between set and first get */
+ tv.tv_sec = 0;
+ tv.tv_usec = 250000;
+
+ /* Clean up set args */
+ memset(&scanopt, 0, sizeof(scanopt));
+
+ wrq.u.data.pointer = NULL;
+ wrq.u.data.flags = 0;
+ wrq.u.data.length = 0;
+
+ /* Initiate Scanning */
+ if( wext_ioctl(ifname, SIOCSIWSCAN, &wrq) >= 0 )
+ {
+ timeout -= tv.tv_usec;
+
+ /* Forever */
+ while(1)
+ {
+ fd_set rfds; /* File descriptors for select */
+ int last_fd; /* Last fd */
+ int ret;
+
+ /* Guess what ? We must re-generate rfds each time */
+ FD_ZERO(&rfds);
+ last_fd = -1;
+ /* In here, add the rtnetlink fd in the list */
+
+ /* Wait until something happens */
+ ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
+
+ /* Check if there was an error */
+ if(ret < 0)
+ {
+ if(errno == EAGAIN || errno == EINTR)
+ continue;
+
+ return -1;
+ }
+
+ /* Check if there was a timeout */
+ if(ret == 0)
+ {
+ unsigned char *newbuf;
+
+ realloc:
+ /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */
+ newbuf = realloc(buffer, buflen);
+ if(newbuf == NULL)
+ {
+ if(buffer)
+ free(buffer);
+
+ return -1;
+ }
+
+ buffer = newbuf;
+
+ /* Try to read the results */
+ wrq.u.data.pointer = buffer;
+ wrq.u.data.flags = 0;
+ wrq.u.data.length = buflen;
+
+ if( wext_ioctl(ifname, SIOCGIWSCAN, &wrq) )
+ {
+ /* Check if buffer was too small (WE-17 only) */
+ if((errno == E2BIG) && (range.we_version_compiled > 16))
+ {
+ /* Some driver may return very large scan results, either
+ * because there are many cells, or because they have many
+ * large elements in cells (like IWEVCUSTOM). Most will
+ * only need the regular sized buffer. We now use a dynamic
+ * allocation of the buffer to satisfy everybody. Of course,
+ * as we don't know in advance the size of the array, we try
+ * various increasing sizes. Jean II */
+
+ /* Check if the driver gave us any hints. */
+ if(wrq.u.data.length > buflen)
+ buflen = wrq.u.data.length;
+ else
+ buflen *= 2;
+
+ /* Try again */
+ goto realloc;
+ }
+
+ /* Check if results not available yet */
+ if(errno == EAGAIN)
+ {
+ /* Restart timer for only 100ms*/
+ tv.tv_sec = 0;
+ tv.tv_usec = 100000;
+ timeout -= tv.tv_usec;
+
+ if(timeout > 0)
+ continue; /* Try again later */
+ }
+
+ /* Bad error */
+ free(buffer);
+ return -1;
+
+ } else {
+ /* We have the results, go to process them */
+ break;
+ }
+ }
+ }
+
+ if( wrq.u.data.length )
+ {
+ struct iw_event iwe;
+ struct stream_descr stream;
+ int ret;
+ int first = 1;
+
+ memset(&stream, 0, sizeof(stream));
+ stream.current = (char *)buffer;
+ stream.end = (char *)buffer + wrq.u.data.length;
+
+ do
+ {
+ /* Extract an event and print it */
+ ret = wext_extract_event(&stream, &iwe, range.we_version_compiled);
+
+ if(ret >= 0)
+ {
+ if( (iwe.cmd == SIOCGIWAP) || (ret == 0) )
+ {
+ if( first )
+ {
+ first = 0;
+ }
+ else if( (entrylen + sizeof(struct iwinfo_scanlist_entry)) <= IWINFO_BUFSIZE )
+ {
+ /* if encryption is off, clear the crypto strunct */
+ if( !e.crypto.enabled )
+ memset(&e.crypto, 0, sizeof(struct iwinfo_crypto_entry));
+
+ memcpy(&buf[entrylen], &e, sizeof(struct iwinfo_scanlist_entry));
+ entrylen += sizeof(struct iwinfo_scanlist_entry);
+ }
+ else
+ {
+ /* we exceed the callers buffer size, abort here ... */
+ break;
+ }
+
+ memset(&e, 0, sizeof(struct iwinfo_scanlist_entry));
+ }
+
+ wext_fill_entry(&stream, &iwe, &range, has_range, &e);
+ }
+
+ } while(ret > 0);
+
+ free(buffer);
+ *len = entrylen;
+ return 0;
+ }
+
+ *len = 0;
+ free(buffer);
+ return 0;
+ }
+ }
+
+ return -1;
+}
diff --git a/package/iwinfo/src/iwinfo_wl.c b/package/iwinfo/src/iwinfo_wl.c
new file mode 100644
index 000000000..3d15fc9ca
--- /dev/null
+++ b/package/iwinfo/src/iwinfo_wl.c
@@ -0,0 +1,645 @@
+/*
+ * iwinfo - Wireless Information Library - Broadcom wl.o Backend
+ *
+ * Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * The iwinfo library 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.
+ *
+ * The iwinfo library 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 the iwinfo library. If not, see http://www.gnu.org/licenses/.
+ *
+ * This code is based on the wlc.c utility published by OpenWrt.org .
+ */
+
+#include "iwinfo/wl.h"
+#include "iwinfo/wext.h"
+
+static int wl_ioctl(const char *name, int cmd, void *buf, int len)
+{
+ struct ifreq ifr;
+ wl_ioctl_t ioc;
+
+ /* do it */
+ ioc.cmd = cmd;
+ ioc.buf = buf;
+ ioc.len = len;
+
+ strncpy(ifr.ifr_name, name, IFNAMSIZ);
+ ifr.ifr_data = (caddr_t) &ioc;
+
+ return iwinfo_ioctl(SIOCDEVPRIVATE, &ifr);
+}
+
+static int wl_iovar(const char *name, const char *cmd, const char *arg,
+ int arglen, void *buf, int buflen)
+{
+ int cmdlen = strlen(cmd) + 1;
+
+ memcpy(buf, cmd, cmdlen);
+
+ if (arg && arglen > 0)
+ memcpy(buf + cmdlen, arg, arglen);
+
+ return wl_ioctl(name, WLC_GET_VAR, buf, buflen);
+}
+
+static struct wl_maclist * wl_read_assoclist(const char *ifname)
+{
+ struct wl_maclist *macs;
+ int maclen = 4 + WL_MAX_STA_COUNT * 6;
+
+ if ((macs = (struct wl_maclist *) malloc(maclen)) != NULL)
+ {
+ memset(macs, 0, maclen);
+ macs->count = WL_MAX_STA_COUNT;
+
+ if (!wl_ioctl(ifname, WLC_GET_ASSOCLIST, macs, maclen))
+ return macs;
+
+ free(macs);
+ }
+
+ return NULL;
+}
+
+
+int wl_probe(const char *ifname)
+{
+ int magic;
+ return (!wl_ioctl(ifname, WLC_GET_MAGIC, &magic, sizeof(magic)) &&
+ (magic == WLC_IOCTL_MAGIC));
+}
+
+void wl_close(void)
+{
+ /* Nop */
+}
+
+int wl_get_mode(const char *ifname, int *buf)
+{
+ int ret = -1;
+ int ap, infra, passive;
+
+ if ((ret = wl_ioctl(ifname, WLC_GET_AP, &ap, sizeof(ap))))
+ return ret;
+
+ if ((ret = wl_ioctl(ifname, WLC_GET_INFRA, &infra, sizeof(infra))))
+ return ret;
+
+ if ((ret = wl_ioctl(ifname, WLC_GET_PASSIVE, &passive, sizeof(passive))))
+ return ret;
+
+ if (passive)
+ *buf = IWINFO_OPMODE_MONITOR;
+ else if (!infra)
+ *buf = IWINFO_OPMODE_ADHOC;
+ else if (ap)
+ *buf = IWINFO_OPMODE_MASTER;
+ else
+ *buf = IWINFO_OPMODE_CLIENT;
+
+ return 0;
+}
+
+int wl_get_ssid(const char *ifname, char *buf)
+{
+ int ret = -1;
+ wlc_ssid_t ssid;
+
+ if (!(ret = wl_ioctl(ifname, WLC_GET_SSID, &ssid, sizeof(ssid))))
+ memcpy(buf, ssid.ssid, ssid.ssid_len);
+
+ return ret;
+}
+
+int wl_get_bssid(const char *ifname, char *buf)
+{
+ int ret = -1;
+ char bssid[6];
+
+ if (!(ret = wl_ioctl(ifname, WLC_GET_BSSID, bssid, 6)))
+ sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
+ (uint8_t)bssid[0], (uint8_t)bssid[1], (uint8_t)bssid[2],
+ (uint8_t)bssid[3], (uint8_t)bssid[4], (uint8_t)bssid[5]
+ );
+
+ return ret;
+}
+
+int wl_get_channel(const char *ifname, int *buf)
+{
+ return wl_ioctl(ifname, WLC_GET_CHANNEL, buf, sizeof(buf));
+}
+
+int wl_get_frequency(const char *ifname, int *buf)
+{
+ return wext_get_frequency(ifname, buf);
+}
+
+int wl_get_txpower(const char *ifname, int *buf)
+{
+ /* WLC_GET_VAR "qtxpower" */
+ return wext_get_txpower(ifname, buf);
+}
+
+int wl_get_bitrate(const char *ifname, int *buf)
+{
+ int ret = -1;
+ int rate = 0;
+
+ if( !(ret = wl_ioctl(ifname, WLC_GET_RATE, &rate, sizeof(rate))) && (rate > 0))
+ *buf = ((rate / 2) * 1000) + ((rate & 1) ? 500 : 0);
+
+ return ret;
+}
+
+int wl_get_signal(const char *ifname, int *buf)
+{
+ unsigned int ap, rssi, i, rssi_count;
+ int ioctl_req_version = 0x2000;
+ char tmp[WLC_IOCTL_MAXLEN];
+ struct wl_maclist *macs = NULL;
+ wl_sta_rssi_t starssi;
+
+ memset(tmp, 0, WLC_IOCTL_MAXLEN);
+ memcpy(tmp, &ioctl_req_version, sizeof(ioctl_req_version));
+
+ wl_ioctl(ifname, WLC_GET_BSS_INFO, tmp, WLC_IOCTL_MAXLEN);
+
+ if (!wl_ioctl(ifname, WLC_GET_AP, &ap, sizeof(ap)) && !ap)
+ {
+ *buf = tmp[WL_BSS_RSSI_OFFSET];
+ }
+ else
+ {
+ rssi = rssi_count = 0;
+
+ /* Calculate average rssi from conntected stations */
+ if ((macs = wl_read_assoclist(ifname)) != NULL)
+ {
+ for (i = 0; i < macs->count; i++)
+ {
+ memcpy(starssi.mac, &macs->ea[i], 6);
+
+ if (!wl_ioctl(ifname, WLC_GET_RSSI, &starssi, 12))
+ {
+ rssi -= starssi.rssi;
+ rssi_count++;
+ }
+ }
+
+ free(macs);
+ }
+
+ *buf = (rssi == 0 || rssi_count == 0) ? 1 : -(rssi / rssi_count);
+ }
+
+ return 0;
+}
+
+int wl_get_noise(const char *ifname, int *buf)
+{
+ unsigned int ap, noise;
+ int ioctl_req_version = 0x2000;
+ char tmp[WLC_IOCTL_MAXLEN];
+
+ memset(tmp, 0, WLC_IOCTL_MAXLEN);
+ memcpy(tmp, &ioctl_req_version, sizeof(ioctl_req_version));
+
+ wl_ioctl(ifname, WLC_GET_BSS_INFO, tmp, WLC_IOCTL_MAXLEN);
+
+ if ((wl_ioctl(ifname, WLC_GET_AP, &ap, sizeof(ap)) < 0) || ap)
+ {
+ if (wl_ioctl(ifname, WLC_GET_PHY_NOISE, &noise, sizeof(noise)) < 0)
+ noise = 0;
+ }
+ else
+ {
+ noise = tmp[WL_BSS_NOISE_OFFSET];
+ }
+
+ *buf = noise;
+
+ return 0;
+}
+
+int wl_get_quality(const char *ifname, int *buf)
+{
+ return wext_get_quality(ifname, buf);
+}
+
+int wl_get_quality_max(const char *ifname, int *buf)
+{
+ return wext_get_quality_max(ifname, buf);
+}
+
+int wl_get_encryption(const char *ifname, char *buf)
+{
+ uint32_t wsec, wauth, wpa;
+ struct iwinfo_crypto_entry *c = (struct iwinfo_crypto_entry *)buf;
+
+ if( wl_ioctl(ifname, WLC_GET_WPA_AUTH, &wpa, sizeof(uint32_t)) ||
+ wl_ioctl(ifname, WLC_GET_WSEC, &wsec, sizeof(uint32_t)) ||
+ wl_ioctl(ifname, WLC_GET_AUTH, &wauth, sizeof(uint32_t)) )
+ return -1;
+
+ switch(wsec)
+ {
+ case 2:
+ c->pair_ciphers |= IWINFO_CIPHER_TKIP;
+ break;
+
+ case 4:
+ c->pair_ciphers |= IWINFO_CIPHER_CCMP;
+ break;
+
+ case 6:
+ c->pair_ciphers |= IWINFO_CIPHER_TKIP;
+ c->pair_ciphers |= IWINFO_CIPHER_CCMP;
+ break;
+ }
+
+ switch(wpa)
+ {
+ case 0:
+ if (wsec && !wauth)
+ c->auth_algs |= IWINFO_AUTH_OPEN;
+
+ else if (wsec && wauth)
+ c->auth_algs |= IWINFO_AUTH_SHARED;
+
+ /* ToDo: evaluate WEP key lengths */
+ c->pair_ciphers = IWINFO_CIPHER_WEP40 | IWINFO_CIPHER_WEP104;
+ c->auth_suites |= IWINFO_KMGMT_NONE;
+ break;
+
+ case 2:
+ c->wpa_version = 1;
+ c->auth_suites |= IWINFO_KMGMT_8021x;
+ break;
+
+ case 4:
+ c->wpa_version = 1;
+ c->auth_suites |= IWINFO_KMGMT_PSK;
+ break;
+
+ case 32:
+ case 64:
+ c->wpa_version = 2;
+ c->auth_suites |= IWINFO_KMGMT_8021x;
+ break;
+
+ case 66:
+ c->wpa_version = 3;
+ c->auth_suites |= IWINFO_KMGMT_8021x;
+ break;
+
+ case 128:
+ c->wpa_version = 2;
+ c->auth_suites |= IWINFO_KMGMT_PSK;
+ break;
+
+ case 132:
+ c->wpa_version = 3;
+ c->auth_suites |= IWINFO_KMGMT_PSK;
+ break;
+
+ default:
+ break;
+ }
+
+ c->enabled = (c->wpa_version || c->auth_algs) ? 1 : 0;
+ c->group_ciphers = c->pair_ciphers;
+
+ return 0;
+}
+
+int wl_get_enctype(const char *ifname, char *buf)
+{
+ uint32_t wsec, wpa;
+ char algo[11];
+
+ if( wl_ioctl(ifname, WLC_GET_WPA_AUTH, &wpa, sizeof(uint32_t)) ||
+ wl_ioctl(ifname, WLC_GET_WSEC, &wsec, sizeof(uint32_t)) )
+ return -1;
+
+ switch(wsec)
+ {
+ case 2:
+ sprintf(algo, "TKIP");
+ break;
+
+ case 4:
+ sprintf(algo, "CCMP");
+ break;
+
+ case 6:
+ sprintf(algo, "TKIP, CCMP");
+ break;
+ }
+
+ switch(wpa)
+ {
+ case 0:
+ sprintf(buf, "%s", wsec ? "WEP" : "None");
+ break;
+
+ case 2:
+ sprintf(buf, "WPA 802.1X (%s)", algo);
+ break;
+
+ case 4:
+ sprintf(buf, "WPA PSK (%s)", algo);
+ break;
+
+ case 32:
+ sprintf(buf, "802.1X (%s)", algo);
+ break;
+
+ case 64:
+ sprintf(buf, "WPA2 802.1X (%s)", algo);
+ break;
+
+ case 66:
+ sprintf(buf, "mixed WPA/WPA2 802.1X (%s)", algo);
+ break;
+
+ case 128:
+ sprintf(buf, "WPA2 PSK (%s)", algo);
+ break;
+
+ case 132:
+ sprintf(buf, "mixed WPA/WPA2 PSK (%s)", algo);
+ break;
+
+ default:
+ sprintf(buf, "Unknown");
+ }
+
+ return 0;
+}
+
+static void wl_get_assoclist_cb(const char *ifname,
+ struct iwinfo_assoclist_entry *e)
+{
+ wl_sta_info_t sta = { 0 };
+
+ if (!wl_iovar(ifname, "sta_info", e->mac, 6, &sta, sizeof(sta)) &&
+ (sta.ver >= 2))
+ {
+ e->inactive = sta.idle * 1000;
+ e->rx_packets = sta.rx_ucast_pkts;
+ e->tx_packets = sta.tx_pkts;
+ e->rx_rate.rate = sta.rx_rate;
+ e->tx_rate.rate = sta.tx_rate;
+
+ /* ToDo: 11n */
+ e->rx_rate.mcs = -1;
+ e->tx_rate.mcs = -1;
+ }
+}
+
+int wl_get_assoclist(const char *ifname, char *buf, int *len)
+{
+ int i, j, noise;
+ int ap, infra, passive;
+ char line[128];
+ char macstr[18];
+ char devstr[IFNAMSIZ];
+ struct wl_maclist *macs;
+ struct wl_sta_rssi rssi;
+ struct iwinfo_assoclist_entry entry;
+ FILE *arp;
+
+ ap = infra = passive = 0;
+
+ wl_ioctl(ifname, WLC_GET_AP, &ap, sizeof(ap));
+ wl_ioctl(ifname, WLC_GET_INFRA, &infra, sizeof(infra));
+ wl_ioctl(ifname, WLC_GET_PASSIVE, &passive, sizeof(passive));
+
+ if (wl_get_noise(ifname, &noise))
+ noise = 0;
+
+ if ((ap || infra || passive) && ((macs = wl_read_assoclist(ifname)) != NULL))
+ {
+ for (i = 0, j = 0; i < macs->count; i++, j += sizeof(struct iwinfo_assoclist_entry))
+ {
+ memset(&entry, 0, sizeof(entry));
+ memcpy(rssi.mac, &macs->ea[i], 6);
+
+ if (!wl_ioctl(ifname, WLC_GET_RSSI, &rssi, sizeof(struct wl_sta_rssi)))
+ entry.signal = (rssi.rssi - 0x100);
+ else
+ entry.signal = 0;
+
+ entry.noise = noise;
+ memcpy(entry.mac, &macs->ea[i], 6);
+ wl_get_assoclist_cb(ifname, &entry);
+
+ memcpy(&buf[j], &entry, sizeof(entry));
+ }
+
+ *len = j;
+ free(macs);
+ return 0;
+ }
+ else if ((arp = fopen("/proc/net/arp", "r")) != NULL)
+ {
+ j = 0;
+
+ while (fgets(line, sizeof(line), arp) != NULL)
+ {
+ if (sscanf(line, "%*s 0x%*d 0x%*d %17s %*s %s", macstr, devstr) && !strcmp(devstr, ifname))
+ {
+ rssi.mac[0] = strtol(&macstr[0], NULL, 16);
+ rssi.mac[1] = strtol(&macstr[3], NULL, 16);
+ rssi.mac[2] = strtol(&macstr[6], NULL, 16);
+ rssi.mac[3] = strtol(&macstr[9], NULL, 16);
+ rssi.mac[4] = strtol(&macstr[12], NULL, 16);
+ rssi.mac[5] = strtol(&macstr[15], NULL, 16);
+
+ if (!wl_ioctl(ifname, WLC_GET_RSSI, &rssi, sizeof(struct wl_sta_rssi)))
+ entry.signal = (rssi.rssi - 0x100);
+ else
+ entry.signal = 0;
+
+ entry.noise = noise;
+ memcpy(entry.mac, rssi.mac, 6);
+ memcpy(&buf[j], &entry, sizeof(entry));
+
+ j += sizeof(entry);
+ }
+ }
+
+ *len = j;
+ (void) fclose(arp);
+ return 0;
+ }
+
+ return -1;
+}
+
+int wl_get_txpwrlist(const char *ifname, char *buf, int *len)
+{
+ struct iwinfo_txpwrlist_entry entry;
+ uint8_t dbm[11] = { 0, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24 };
+ uint8_t mw[11] = { 1, 3, 6, 10, 15, 25, 39, 63, 100, 158, 251 };
+ int i;
+
+ for (i = 0; i < 11; i++)
+ {
+ entry.dbm = dbm[i];
+ entry.mw = mw[i];
+ memcpy(&buf[i*sizeof(entry)], &entry, sizeof(entry));
+ }
+
+ *len = 11 * sizeof(entry);
+ return 0;
+}
+
+int wl_get_scanlist(const char *ifname, char *buf, int *len)
+{
+ return wext_get_scanlist(ifname, buf, len);
+}
+
+int wl_get_freqlist(const char *ifname, char *buf, int *len)
+{
+ return wext_get_freqlist(ifname, buf, len);
+}
+
+int wl_get_country(const char *ifname, char *buf)
+{
+ char ccode[WLC_CNTRY_BUF_SZ];
+
+ if (!wl_ioctl(ifname, WLC_GET_COUNTRY, ccode, WLC_CNTRY_BUF_SZ))
+ {
+ /* IL0 -> World */
+ if (!strcmp(ccode, "IL0"))
+ sprintf(buf, "00");
+
+ /* YU -> RS */
+ else if (!strcmp(ccode, "YU"))
+ sprintf(buf, "RS");
+
+ else
+ memcpy(buf, ccode, 2);
+
+ return 0;
+ }
+
+ return -1;
+}
+
+int wl_get_countrylist(const char *ifname, char *buf, int *len)
+{
+ int i, count;
+ char cdata[WLC_IOCTL_MAXLEN];
+ struct iwinfo_country_entry *c = (struct iwinfo_country_entry *)buf;
+ wl_country_list_t *cl = (wl_country_list_t *)cdata;
+
+ cl->buflen = sizeof(cdata);
+
+ if (!wl_ioctl(ifname, WLC_GET_COUNTRY_LIST, cl, cl->buflen))
+ {
+ for (i = 0, count = 0; i < cl->count; i++, c++)
+ {
+ sprintf(c->ccode, &cl->country_abbrev[i * WLC_CNTRY_BUF_SZ]);
+ c->iso3166 = c->ccode[0] * 256 + c->ccode[1];
+
+ /* IL0 -> World */
+ if (!strcmp(c->ccode, "IL0"))
+ c->iso3166 = 0x3030;
+
+ /* YU -> RS */
+ else if (!strcmp(c->ccode, "YU"))
+ c->iso3166 = 0x5253;
+ }
+
+ *len = (i * sizeof(struct iwinfo_country_entry));
+ return 0;
+ }
+
+ return -1;
+}
+
+int wl_get_hwmodelist(const char *ifname, int *buf)
+{
+ return wext_get_hwmodelist(ifname, buf);
+}
+
+int wl_get_mbssid_support(const char *ifname, int *buf)
+{
+ wlc_rev_info_t revinfo;
+
+ /* Multi bssid support only works on corerev >= 9 */
+ if (!wl_ioctl(ifname, WLC_GET_REVINFO, &revinfo, sizeof(revinfo)))
+ {
+ if (revinfo.corerev >= 9)
+ {
+ *buf = 1;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+int wl_get_hardware_id(const char *ifname, char *buf)
+{
+ wlc_rev_info_t revinfo;
+ struct iwinfo_hardware_id *ids = (struct iwinfo_hardware_id *)buf;
+
+ if (wl_ioctl(ifname, WLC_GET_REVINFO, &revinfo, sizeof(revinfo)))
+ return -1;
+
+ ids->vendor_id = revinfo.vendorid;
+ ids->device_id = revinfo.deviceid;
+ ids->subsystem_vendor_id = revinfo.boardvendor;
+ ids->subsystem_device_id = revinfo.boardid;
+
+ return 0;
+}
+
+int wl_get_hardware_name(const char *ifname, char *buf)
+{
+ struct iwinfo_hardware_id ids;
+
+ if (wl_get_hardware_id(ifname, (char *)&ids))
+ return -1;
+
+ sprintf(buf, "Broadcom BCM%04X", ids.device_id);
+
+ return 0;
+}
+
+int wl_get_txpower_offset(const char *ifname, int *buf)
+{
+ FILE *p;
+ char off[8];
+
+ *buf = 0;
+
+ if ((p = popen("/usr/sbin/nvram get opo", "r")) != NULL)
+ {
+ if (fread(off, 1, sizeof(off), p))
+ *buf = strtoul(off, NULL, 16);
+
+ pclose(p);
+ }
+
+ return 0;
+}
+
+int wl_get_frequency_offset(const char *ifname, int *buf)
+{
+ /* Stub */
+ *buf = 0;
+ return -1;
+}
diff --git a/package/ixp4xx-microcode/Makefile b/package/ixp4xx-microcode/Makefile
new file mode 100644
index 000000000..9ed912758
--- /dev/null
+++ b/package/ixp4xx-microcode/Makefile
@@ -0,0 +1,56 @@
+#
+# Copyright (C) 2007 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ixp4xx-microcode
+PKG_VERSION:=2.4
+PKG_RELEASE:=2
+
+PKG_SOURCE:=IPL_ixp400NpeLibraryWithCrypto-2_4.zip
+PKG_SOURCE_URL:=http://downloads.openwrt.org/sources
+PKG_MD5SUM:=dd5f6482e625ecb334469958bcd54b37
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ixp4xx-microcode
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=Microcode for the IXP4xx network engines
+ DEPENDS:=@TARGET_ixp4xx
+endef
+
+define Package/ixp4xx-microcode/description
+ This package contains the microcode needed to use the network engines in IXP4xx CPUs
+endef
+
+define Build/Prepare
+ rm -rf $(PKG_BUILD_DIR)
+ mkdir -p $(PKG_BUILD_DIR)
+ unzip -d $(PKG_BUILD_DIR)/ $(DL_DIR)/$(PKG_SOURCE)
+ mv $(PKG_BUILD_DIR)/ixp400_xscale_sw/src/npeDl/IxNpeMicrocode.c $(PKG_BUILD_DIR)/
+ rm -rf $(PKG_BUILD_DIR)/ixp400_xscale_sw
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ (cd $(PKG_BUILD_DIR); \
+ $(HOSTCC) -Wall -I$(STAGING_DIR_HOST)/include IxNpeMicrocode.c -o IxNpeMicrocode; \
+ ./IxNpeMicrocode -be \
+ )
+endef
+
+define Package/ixp4xx-microcode/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DIR) $(1)/usr/share/doc
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/NPE-A $(1)/lib/firmware/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/NPE-B $(1)/lib/firmware/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/NPE-C $(1)/lib/firmware/
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/LICENSE.IPL $(1)/usr/share/doc/
+endef
+
+$(eval $(call BuildPackage,ixp4xx-microcode))
diff --git a/package/ixp4xx-microcode/src/IxNpeMicrocode.h b/package/ixp4xx-microcode/src/IxNpeMicrocode.h
new file mode 100644
index 000000000..ffb22b200
--- /dev/null
+++ b/package/ixp4xx-microcode/src/IxNpeMicrocode.h
@@ -0,0 +1,144 @@
+/*
+ * IxNpeMicrocode.h - Headerfile for compiling the Intel microcode C file
+ *
+ * Copyright (C) 2006 Christian Hohnstaedt <chohnstaedt@innominate.com>
+ *
+ * This file is released under the GPLv2
+ *
+ *
+ * compile with
+ *
+ * gcc -Wall IxNpeMicrocode.c -o IxNpeMicrocode
+ *
+ * Executing the resulting binary on your build-host creates the
+ * "NPE-[ABC].xxxxxxxx" files containing the selected microcode
+ *
+ * fetch the IxNpeMicrocode.c from the Intel Access Library.
+ * It will include this header.
+ *
+ * select Images for every NPE from the following
+ * (used C++ comments for easy uncommenting ....)
+ */
+
+// #define IX_NPEDL_NPEIMAGE_NPEA_ETH_SPAN_MASK_FIREWALL_VLAN_QOS_HDR_CONV_EXTMIB
+// #define IX_NPEDL_NPEIMAGE_NPEA_ETH_SPAN_VLAN_QOS_HDR_CONV_EXTMIB
+// #define IX_NPEDL_NPEIMAGE_NPEA_ETH_LEARN_FILTER_SPAN_MASK_FIREWALL_VLAN_QOS_EXTMIB
+// #define IX_NPEDL_NPEIMAGE_NPEA_HSS_TSLOT_SWITCH
+#define IX_NPEDL_NPEIMAGE_NPEA_ETH_SPAN_FIREWALL_VLAN_QOS_HDR_CONV
+// #define IX_NPEDL_NPEIMAGE_NPEA_ETH_LEARN_FILTER_SPAN_FIREWALL_VLAN_QOS
+// #define IX_NPEDL_NPEIMAGE_NPEA_ETH_LEARN_FILTER_SPAN_FIREWALL
+// #define IX_NPEDL_NPEIMAGE_NPEA_HSS_2_PORT
+// #define IX_NPEDL_NPEIMAGE_NPEA_DMA
+// #define IX_NPEDL_NPEIMAGE_NPEA_ATM_MPHY_12_PORT
+// #define IX_NPEDL_NPEIMAGE_NPEA_HSS0_ATM_MPHY_1_PORT
+// #define IX_NPEDL_NPEIMAGE_NPEA_HSS0_ATM_SPHY_1_PORT
+// #define IX_NPEDL_NPEIMAGE_NPEA_HSS0
+// #define IX_NPEDL_NPEIMAGE_NPEA_WEP
+
+
+// #define IX_NPEDL_NPEIMAGE_NPEB_ETH_SPAN_MASK_FIREWALL_VLAN_QOS_HDR_CONV_EXTMIB
+// #define IX_NPEDL_NPEIMAGE_NPEB_ETH_SPAN_VLAN_QOS_HDR_CONV_EXTMIB
+// #define IX_NPEDL_NPEIMAGE_NPEB_ETH_LEARN_FILTER_SPAN_MASK_FIREWALL_VLAN_QOS_EXTMIB
+// #define IX_NPEDL_NPEIMAGE_NPEB_DMA
+#define IX_NPEDL_NPEIMAGE_NPEB_ETH_SPAN_FIREWALL_VLAN_QOS_HDR_CONV
+// #define IX_NPEDL_NPEIMAGE_NPEB_ETH_LEARN_FILTER_SPAN_FIREWALL_VLAN_QOS
+// #define IX_NPEDL_NPEIMAGE_NPEB_ETH_LEARN_FILTER_SPAN_FIREWALL
+
+
+// #define IX_NPEDL_NPEIMAGE_NPEC_ETH_SPAN_MASK_FIREWALL_VLAN_QOS_HDR_CONV_EXTMIB
+// #define IX_NPEDL_NPEIMAGE_NPEC_ETH_SPAN_VLAN_QOS_HDR_CONV_EXTMIB
+// #define IX_NPEDL_NPEIMAGE_NPEC_ETH_LEARN_FILTER_SPAN_MASK_FIREWALL_VLAN_QOS_EXTMIB
+// #define IX_NPEDL_NPEIMAGE_NPEC_DMA
+// #define IX_NPEDL_NPEIMAGE_NPEC_CRYPTO_AES_ETH_LEARN_FILTER_SPAN
+// #define IX_NPEDL_NPEIMAGE_NPEC_CRYPTO_AES_ETH_LEARN_FILTER_FIREWALL
+#define IX_NPEDL_NPEIMAGE_NPEC_CRYPTO_AES_CCM_ETH
+// #define IX_NPEDL_NPEIMAGE_NPEC_CRYPTO_AES_CCM_EXTSHA_ETH
+// #define IX_NPEDL_NPEIMAGE_NPEC_CRYPTO_ETH_LEARN_FILTER_SPAN_FIREWALL
+// #define IX_NPEDL_NPEIMAGE_NPEC_ETH_SPAN_FIREWALL_VLAN_QOS_HDR_CONV
+// #define IX_NPEDL_NPEIMAGE_NPEC_ETH_LEARN_FILTER_SPAN_FIREWALL_VLAN_QOS
+// #define IX_NPEDL_NPEIMAGE_NPEC_ETH_LEARN_FILTER_SPAN_FIREWALL
+
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <endian.h>
+#include <byteswap.h>
+#include <string.h>
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define to_le32(x) (x)
+#define to_be32(x) bswap_32(x)
+#else
+#define to_be32(x) (x)
+#define to_le32(x) bswap_32(x)
+#endif
+
+struct dl_image {
+ unsigned magic;
+ unsigned id;
+ unsigned size;
+ unsigned data[0];
+};
+
+const unsigned IxNpeMicrocode_array[];
+
+int main(int argc, char *argv[])
+{
+ struct dl_image *image = (struct dl_image *)IxNpeMicrocode_array;
+ int imgsiz, i, fd, cnt;
+ const unsigned *arrayptr = IxNpeMicrocode_array;
+ const char *names[] = { "IXP425", "IXP465", "unknown" };
+ int bigendian = 1;
+
+ if (argc > 1) {
+ if (!strcmp(argv[1], "-le"))
+ bigendian = 0;
+ else if (!strcmp(argv[1], "-be"))
+ bigendian = 1;
+ else {
+ printf("Usage: %s <-le|-be>\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+ }
+
+ for (image = (struct dl_image *)arrayptr, cnt=0;
+ (image->id != 0xfeedf00d) && (image->magic == 0xfeedf00d);
+ image = (struct dl_image *)(arrayptr), cnt++)
+ {
+ unsigned char field[4];
+ imgsiz = image->size + 3;
+ *(unsigned*)field = to_be32(image->id);
+ char filename[40], slnk[10];
+
+ sprintf(filename, "NPE-%c.%08x", (field[0] & 0xf) + 'A',
+ image->id);
+ sprintf(slnk, "NPE-%c", (field[0] & 0xf) + 'A');
+ printf("Writing image: %s.NPE_%c Func: %2x Rev: %02x.%02x "
+ "Size: %5d to: '%s'\n",
+ names[field[0] >> 4], (field[0] & 0xf) + 'A',
+ field[1], field[2], field[3], imgsiz*4, filename);
+ fd = open(filename, O_CREAT | O_RDWR | O_TRUNC, 0644);
+ if (fd >= 0) {
+ for (i=0; i<imgsiz; i++) {
+ *(unsigned*)field = bigendian ?
+ to_be32(arrayptr[i]) :
+ to_le32(arrayptr[i]);
+ write(fd, field, sizeof(field));
+ }
+ close(fd);
+ unlink(slnk);
+ symlink(filename, slnk);
+ } else {
+ perror(filename);
+ }
+ arrayptr += imgsiz;
+ }
+ close(fd);
+ return 0;
+}
diff --git a/package/ixp4xx-microcode/src/LICENSE.IPL b/package/ixp4xx-microcode/src/LICENSE.IPL
new file mode 100644
index 000000000..dad2566cf
--- /dev/null
+++ b/package/ixp4xx-microcode/src/LICENSE.IPL
@@ -0,0 +1,27 @@
+INTEL(R) SOFTWARE LICENSE AGREEMENT
+
+Copyright (c) 2007, Intel Corporation.
+All rights reserved.
+
+Redistribution. Redistribution and use in binary form, without modification, are permitted
+provided that the following conditions are met:
+o Redistributions must reproduce the above copyright notice and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+o Neither the name of Intel Corporation nor the names of its suppliers may be used to endorse
+or promote products derived from this software without specific prior written permission.
+o No reverse engineering, decompilation, or disassembly of this software is permitted.
+
+Limited patent license. Intel Corporation grants a world-wide, royalty-free, non-exclusive
+license under patents it now or hereafter owns or controls to make, have made, use, import,
+offer to sell and sell (.Utilize.) this software, but solely to the extent that any such patent is
+necessary to Utilize the software alone. The patent license shall not apply to any combinations
+which include this software. No hardware per se is licensed hereunder.
+DISCLAIMER. 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
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER 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.
diff --git a/package/kernel/Makefile b/package/kernel/Makefile
new file mode 100644
index 000000000..805081739
--- /dev/null
+++ b/package/kernel/Makefile
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2006-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=kernel
+PKG_FLAGS:=hold
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/packages
+SCAN_DEPS=modules/*.mk $(TOPDIR)/target/linux/*/modules.mk
+
+include $(INCLUDE_DIR)/package.mk
+ifeq ($(DUMP),)
+ -include $(LINUX_DIR)/.config
+endif
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+endef
+
+CONFIG_PACKAGE_kernel=y
+define Package/kernel
+ SECTION:=sys
+ CATEGORY:=Kernel
+ DEFAULT:=y
+ TITLE:=Virtual kernel package
+ VERSION:=$(LINUX_VERSION)-$(LINUX_RELEASE)-$(LINUX_VERMAGIC)
+ URL:=http://www.kernel.org/
+endef
+
+define Package/kernel/install
+ # nothing to do
+endef
+
+$(eval $(if $(DUMP),,$(call BuildPackage,kernel)))
+
+include $(sort $(wildcard ./modules/*.mk))
+-include $(TOPDIR)/target/linux/*/modules.mk
diff --git a/package/kernel/modules/001-depends.mk b/package/kernel/modules/001-depends.mk
new file mode 100644
index 000000000..6c493018d
--- /dev/null
+++ b/package/kernel/modules/001-depends.mk
@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2010-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define AddDepends/crc16
+ DEPENDS+= +kmod-lib-crc16 $(1)
+endef
+
+define AddDepends/hid
+ DEPENDS+= +kmod-hid $(1)
+endef
+
+define AddDepends/input
+ DEPENDS+= +kmod-input-core $(1)
+endef
+
+
+define AddDepends/nls
+ DEPENDS+= +kmod-nls-base $(foreach cp,$(1),+kmod-nls-$(cp))
+endef
+
+
+define SetDepends/rfkill
+ DEPENDS:= @(TARGET_ar71xx||TARGET_brcm47xx||TARGET_s3c24xx||TARGET_x86||TARGET_gemini)
+endef
+
+define AddDepends/rfkill
+ DEPENDS+= +(TARGET_ar71xx||TARGET_brcm47xx||TARGET_s3c24xx||TARGET_x86):kmod-rfkill $(1)
+endef
+
+
+define AddDepends/rtc
+ DEPENDS+= @RTC_SUPPORT
+endef
diff --git a/package/kernel/modules/block.mk b/package/kernel/modules/block.mk
new file mode 100644
index 000000000..a4288b2a8
--- /dev/null
+++ b/package/kernel/modules/block.mk
@@ -0,0 +1,606 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+BLOCK_MENU:=Block Devices
+
+define KernelPackage/aoe
+ SUBMENU:=$(BLOCK_MENU)
+ TITLE:=ATA over Ethernet support
+ KCONFIG:=CONFIG_ATA_OVER_ETH
+ FILES:=$(LINUX_DIR)/drivers/block/aoe/aoe.ko
+ AUTOLOAD:=$(call AutoLoad,30,aoe)
+endef
+
+define KernelPackage/aoe/description
+ Kernel support for ATA over Ethernet
+endef
+
+$(eval $(call KernelPackage,aoe))
+
+
+define KernelPackage/ata-core
+ SUBMENU:=$(BLOCK_MENU)
+ TITLE:=Serial and Parallel ATA support
+ DEPENDS:=@PCI_SUPPORT +kmod-scsi-core @(!TARGET_ubicom32||!TARGET_etrax)
+ KCONFIG:=CONFIG_ATA
+ FILES:=$(LINUX_DIR)/drivers/ata/libata.ko
+ AUTOLOAD:=$(call AutoLoad,21,libata,1)
+endef
+
+$(eval $(call KernelPackage,ata-core))
+
+
+define AddDepends/ata
+ SUBMENU:=$(BLOCK_MENU)
+ DEPENDS+=kmod-ata-core $(1)
+endef
+
+
+define KernelPackage/ata-ahci
+ TITLE:=AHCI Serial ATA support
+ KCONFIG:=CONFIG_SATA_AHCI
+ FILES:= \
+ $(LINUX_DIR)/drivers/ata/ahci.ko \
+ $(LINUX_DIR)/drivers/ata/libahci.ko
+ AUTOLOAD:=$(call AutoLoad,41,libahci ahci,1)
+ $(call AddDepends/ata)
+endef
+
+define KernelPackage/ata-ahci/description
+ Support for AHCI Serial ATA controllers.
+endef
+
+$(eval $(call KernelPackage,ata-ahci))
+
+
+define KernelPackage/ata-artop
+ TITLE:=ARTOP 6210/6260 PATA support
+ KCONFIG:=CONFIG_PATA_ARTOP
+ FILES:=$(LINUX_DIR)/drivers/ata/pata_artop.ko
+ AUTOLOAD:=$(call AutoLoad,41,pata_artop,1)
+ $(call AddDepends/ata)
+endef
+
+define KernelPackage/ata-artop/description
+ PATA support for ARTOP 6210/6260 host controllers.
+endef
+
+$(eval $(call KernelPackage,ata-artop))
+
+
+define KernelPackage/ata-marvell-sata
+ TITLE:=Marvell Serial ATA support
+ KCONFIG:=CONFIG_SATA_MV
+ FILES:=$(LINUX_DIR)/drivers/ata/sata_mv.ko
+ AUTOLOAD:=$(call AutoLoad,41,sata_mv,1)
+ $(call AddDepends/ata)
+endef
+
+define KernelPackage/ata-marvell-sata/description
+ SATA support for marvell chipsets
+endef
+
+$(eval $(call KernelPackage,ata-marvell-sata))
+
+
+define KernelPackage/ata-nvidia-sata
+ TITLE:=Nvidia Serial ATA support
+ KCONFIG:=CONFIG_SATA_NV
+ FILES:=$(LINUX_DIR)/drivers/ata/sata_nv.ko
+ AUTOLOAD:=$(call AutoLoad,41,sata_nv,1)
+ $(call AddDepends/ata)
+endef
+
+$(eval $(call KernelPackage,ata-nvidia-sata))
+
+
+define KernelPackage/ata-pdc202xx-old
+ SUBMENU:=$(BLOCK_MENU)
+ TITLE:=Older Promise PATA controller support
+ DEPENDS:=kmod-ata-core
+ KCONFIG:= \
+ CONFIG_ATA_SFF=y \
+ CONFIG_PATA_PDC_OLD
+ FILES:=$(LINUX_DIR)/drivers/ata/pata_pdc202xx_old.ko
+ AUTOLOAD:=$(call AutoLoad,41,pata_pdc202xx_old,1)
+endef
+
+define KernelPackage/ata-pdc202xx-old/description
+ This option enables support for the Promise 20246, 20262, 20263,
+ 20265 and 20267 adapters.
+endef
+
+$(eval $(call KernelPackage,ata-pdc202xx-old))
+
+
+define KernelPackage/ata-piix
+ TITLE:=Intel PIIX PATA/SATA support
+ KCONFIG:=CONFIG_ATA_PIIX
+ FILES:=$(LINUX_DIR)/drivers/ata/ata_piix.ko
+ AUTOLOAD:=$(call AutoLoad,41,ata_piix,1)
+ $(call AddDepends/ata)
+endef
+
+define KernelPackage/ata-piix/description
+ SATA support for Intel ICH5/6/7/8 series host controllers and
+ PATA support for Intel ESB/ICH/PIIX3/PIIX4 series host controllers.
+endef
+
+$(eval $(call KernelPackage,ata-piix))
+
+
+define KernelPackage/ata-sil
+ TITLE:=Silicon Image SATA support
+ KCONFIG:=CONFIG_SATA_SIL
+ FILES:=$(LINUX_DIR)/drivers/ata/sata_sil.ko
+ AUTOLOAD:=$(call AutoLoad,41,sata_sil,1)
+ $(call AddDepends/ata)
+endef
+
+define KernelPackage/ata-sil/description
+ Support for Silicon Image Serial ATA controllers.
+endef
+
+$(eval $(call KernelPackage,ata-sil))
+
+
+define KernelPackage/ata-sil24
+ TITLE:=Silicon Image 3124/3132 SATA support
+ KCONFIG:=CONFIG_SATA_SIL24
+ FILES:=$(LINUX_DIR)/drivers/ata/sata_sil24.ko
+ AUTOLOAD:=$(call AutoLoad,41,sata_sil24,1)
+ $(call AddDepends/ata)
+endef
+
+define KernelPackage/ata-sil24/description
+ Support for Silicon Image 3124/3132 Serial ATA controllers.
+endef
+
+$(eval $(call KernelPackage,ata-sil24))
+
+
+define KernelPackage/ata-sis
+ TITLE:=SIS SATA support
+ KCONFIG:=CONFIG_SATA_SIS
+ FILES:=$(LINUX_DIR)/drivers/ata/sata_sis.ko
+ AUTOLOAD:=$(call AutoLoad,41,sata_sis,1)
+ $(call AddDepends/ata)
+endef
+
+define KernelPackage/ata-sis/description
+ Support for SIS Serial ATA controllers.
+endef
+
+$(eval $(call KernelPackage,ata-sis))
+
+
+define KernelPackage/ata-via-sata
+ TITLE:=VIA SATA support
+ KCONFIG:=CONFIG_SATA_VIA
+ FILES:=$(LINUX_DIR)/drivers/ata/sata_via.ko
+ AUTOLOAD:=$(call AutoLoad,41,sata_via,1)
+ $(call AddDepends/ata)
+endef
+
+define KernelPackage/ata-via-sata/description
+ This option enables support for VIA Serial ATA.
+endef
+
+$(eval $(call KernelPackage,ata-via-sata))
+
+
+define KernelPackage/block2mtd
+ SUBMENU:=$(BLOCK_MENU)
+ TITLE:=Block device MTD emulation
+ KCONFIG:=CONFIG_MTD_BLOCK2MTD
+ FILES:=$(LINUX_DIR)/drivers/mtd/devices/block2mtd.ko
+endef
+
+$(eval $(call KernelPackage,block2mtd))
+
+
+define KernelPackage/dm
+ SUBMENU:=$(BLOCK_MENU)
+ TITLE:=Device Mapper
+ # All the "=n" are unnecessary, they're only there
+ # to stop the config from asking the question.
+ # MIRROR is M because I've needed it for pvmove.
+ KCONFIG:= \
+ CONFIG_BLK_DEV_MD=n \
+ CONFIG_DM_DEBUG=n \
+ CONFIG_DM_UEVENT=n \
+ CONFIG_DM_DELAY=n \
+ CONFIG_DM_MULTIPATH=n \
+ CONFIG_DM_ZERO=n \
+ CONFIG_DM_SNAPSHOT=n \
+ CONFIG_DM_LOG_USERSPACE=n \
+ CONFIG_MD=y \
+ CONFIG_BLK_DEV_DM \
+ CONFIG_DM_CRYPT \
+ CONFIG_DM_MIRROR
+ FILES:=$(LINUX_DIR)/drivers/md/dm-*.ko
+ AUTOLOAD:=$(call AutoLoad,30,dm-mod dm-log dm-region-hash dm-mirror dm-crypt)
+endef
+
+define KernelPackage/dm/description
+ Kernel module necessary for LVM2 support
+endef
+
+$(eval $(call KernelPackage,dm))
+
+
+define KernelPackage/md-mod
+ SUBMENU:=$(BLOCK_MENU)
+ TITLE:=MD RAID
+ KCONFIG:= \
+ CONFIG_MD=y \
+ CONFIG_BLK_DEV_MD=m \
+ CONFIG_MD_AUTODETECT=y \
+ CONFIG_MD_FAULTY=n
+ FILES:=$(LINUX_DIR)/drivers/md/md-mod.ko
+ AUTOLOAD:=$(call AutoLoad,27,md-mod)
+endef
+
+define KernelPackage/md-mod/description
+ Kernel RAID md module (md-mod.ko).
+ You will need to select at least one RAID level module below.
+endef
+
+$(eval $(call KernelPackage,md-mod))
+
+
+define KernelPackage/md/Depends
+ SUBMENU:=$(BLOCK_MENU)
+ DEPENDS:=kmod-md-mod $(1)
+endef
+
+
+define KernelPackage/md-linear
+$(call KernelPackage/md/Depends,)
+ TITLE:=RAID Linear Module
+ KCONFIG:=CONFIG_MD_LINEAR
+ FILES:=$(LINUX_DIR)/drivers/md/linear.ko
+ AUTOLOAD:=$(call AutoLoad,28,linear)
+endef
+
+define KernelPackage/md-linear/description
+ RAID "Linear" or "Append" driver module (linear.ko)
+endef
+
+$(eval $(call KernelPackage,md-linear))
+
+
+define KernelPackage/md-raid0
+$(call KernelPackage/md/Depends,)
+ TITLE:=RAID0 Module
+ KCONFIG:=CONFIG_MD_RAID0
+ FILES:=$(LINUX_DIR)/drivers/md/raid0.ko
+ AUTOLOAD:=$(call AutoLoad,28,raid0)
+endef
+
+define KernelPackage/md-raid0/description
+ RAID Level 0 (Striping) driver module (raid0.ko)
+endef
+
+$(eval $(call KernelPackage,md-raid0))
+
+
+define KernelPackage/md-raid1
+$(call KernelPackage/md/Depends,)
+ TITLE:=RAID1 Module
+ KCONFIG:=CONFIG_MD_RAID1
+ FILES:=$(LINUX_DIR)/drivers/md/raid1.ko
+ AUTOLOAD:=$(call AutoLoad,28,raid1)
+endef
+
+define KernelPackage/md-raid1/description
+ RAID Level 1 (Mirroring) driver (raid1.ko)
+endef
+
+$(eval $(call KernelPackage,md-raid1))
+
+
+define KernelPackage/md-raid10
+$(call KernelPackage/md/Depends,)
+ TITLE:=RAID10 Module
+ KCONFIG:=CONFIG_MD_RAID10
+ FILES:=$(LINUX_DIR)/drivers/md/raid10.ko
+ AUTOLOAD:=$(call AutoLoad,28,raid10)
+endef
+
+define KernelPackage/md-raid10/description
+ RAID Level 10 (Mirroring+Striping) driver module (raid10.ko)
+endef
+
+$(eval $(call KernelPackage,md-raid10))
+
+
+define KernelPackage/md-raid456
+$(call KernelPackage/md/Depends,)
+ TITLE:=RAID Level 456 Driver
+ KCONFIG:= \
+ CONFIG_XOR_BLOCKS \
+ CONFIG_ASYNC_CORE \
+ CONFIG_ASYNC_MEMCPY \
+ CONFIG_ASYNC_XOR \
+ CONFIG_ASYNC_PQ \
+ CONFIG_ASYNC_RAID6_RECOV \
+ CONFIG_ASYNC_RAID6_TEST=n \
+ CONFIG_MD_RAID6_PQ \
+ CONFIG_MD_RAID456 \
+ CONFIG_MULTICORE_RAID456=n
+ FILES:= \
+ $(LINUX_DIR)/crypto/xor.ko \
+ $(LINUX_DIR)/crypto/async_tx/async_tx.ko \
+ $(LINUX_DIR)/crypto/async_tx/async_memcpy.ko \
+ $(LINUX_DIR)/crypto/async_tx/async_xor.ko \
+ $(LINUX_DIR)/crypto/async_tx/async_pq.ko \
+ $(LINUX_DIR)/crypto/async_tx/async_raid6_recov.ko \
+ $(LINUX_DIR)/drivers/md/raid456.ko \
+ $(LINUX_DIR)/lib/raid6/raid6_pq.ko
+ AUTOLOAD:=$(call AutoLoad,28, xor async_tx async_memcpy async_xor raid6_pq async_pq async_raid6_recov raid456)
+endef
+
+define KernelPackage/md-raid456/description
+ RAID Level 4,5,6 kernel module (raid456.ko)
+
+ Includes the following modules required by
+ raid456.ko:
+ xor.ko
+ async_tx.ko
+ async_xor.ko
+ async_memcpy.ko
+ async_pq.ko
+ async_raid5_recov.ko
+ raid6_pq.ko
+endef
+
+$(eval $(call KernelPackage,md-raid456))
+
+
+define KernelPackage/md-multipath
+$(call KernelPackage/md/Depends,)
+ TITLE:=MD Multipath Module
+ KCONFIG:=CONFIG_MD_MULTIPATH
+ FILES:=$(LINUX_DIR)/drivers/md/multipath.ko
+ AUTOLOAD:=$(call AutoLoad,29,multipath)
+endef
+
+define KernelPackage/md-multipath/description
+ Multipath driver module (multipath.ko)
+endef
+
+$(eval $(call KernelPackage,md-multipath))
+
+
+define KernelPackage/ide-core
+ SUBMENU:=$(BLOCK_MENU)
+ TITLE:=IDE (ATA/ATAPI) device support
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:= \
+ CONFIG_IDE \
+ CONFIG_BLK_DEV_IDE \
+ CONFIG_BLK_DEV_IDEDISK \
+ CONFIG_IDE_GD \
+ CONFIG_IDE_GD_ATA=y \
+ CONFIG_IDE_GD_ATAPI=n \
+ CONFIG_IDEPCI_PCIBUS_ORDER=y \
+ CONFIG_BLK_DEV_IDEDMA_PCI=y \
+ CONFIG_BLK_DEV_IDEPCI=y
+ FILES:= \
+ $(LINUX_DIR)/drivers/ide/ide-core.ko \
+ $(LINUX_DIR)/drivers/ide/ide-gd_mod.ko
+ AUTOLOAD:= \
+ $(call AutoLoad,20,ide-core,1) \
+ $(call AutoLoad,40,ide-gd_mod,1)
+endef
+
+define KernelPackage/ide-core/description
+ Kernel support for IDE, useful for usb mass storage devices (e.g. on WL-HDD)
+ Includes:
+ - ide-core
+ - ide-gd_mod
+endef
+
+$(eval $(call KernelPackage,ide-core))
+
+
+define AddDepends/ide
+ SUBMENU:=$(BLOCK_MENU)
+ DEPENDS+=kmod-ide-core $(1)
+endef
+
+
+define KernelPackage/ide-generic
+ SUBMENU:=$(BLOCK_MENU)
+ DEPENDS:=@PCI_SUPPORT
+ TITLE:=Kernel support for generic PCI IDE chipsets
+ KCONFIG:=CONFIG_BLK_DEV_GENERIC
+ FILES:=$(LINUX_DIR)/drivers/ide/ide-pci-generic.ko
+ AUTOLOAD:=$(call AutoLoad,30,ide-pci-generic,1)
+ $(call AddDepends/ide)
+endef
+
+$(eval $(call KernelPackage,ide-generic))
+
+
+define KernelPackage/ide-generic-old
+ SUBMENU:=$(BLOCK_MENU)
+ TITLE:=Kernel support for generic (legacy) IDE chipsets
+ KCONFIG:=CONFIG_IDE_GENERIC
+ FILES:=$(LINUX_DIR)/drivers/ide/ide-generic.ko
+ AUTOLOAD:=$(call AutoLoad,30,ide-generic,1)
+ $(call AddDepends/ide)
+endef
+
+$(eval $(call KernelPackage,ide-generic-old))
+
+
+define KernelPackage/ide-aec62xx
+ TITLE:=Acard AEC62xx IDE driver
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_BLK_DEV_AEC62XX
+ FILES:=$(LINUX_DIR)/drivers/ide/aec62xx.ko
+ AUTOLOAD:=$(call AutoLoad,30,aec62xx,1)
+ $(call AddDepends/ide)
+endef
+
+define KernelPackage/ide-aec62xx/description
+ Support for Acard AEC62xx (Artop ATP8xx) IDE controllers.
+endef
+
+$(eval $(call KernelPackage,ide-aec62xx,1))
+
+
+define KernelPackage/ide-pdc202xx
+ TITLE:=Promise PDC202xx IDE driver
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_BLK_DEV_PDC202XX_OLD
+ FILES:=$(LINUX_DIR)/drivers/ide/pdc202xx_old.ko
+ AUTOLOAD:=$(call AutoLoad,30,pdc202xx_old,1)
+ $(call AddDepends/ide)
+endef
+
+define KernelPackage/ide-pdc202xx/description
+ Support for the Promise Ultra 33/66/100 (PDC202{46|62|65|67|68}) IDE
+ controllers.
+endef
+
+$(eval $(call KernelPackage,ide-pdc202xx))
+
+
+define KernelPackage/ide-it821x
+ TITLE:=ITE IT821x IDE driver
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_BLK_DEV_IT821X
+ FILES=$(LINUX_DIR)/drivers/ide/it821x.ko
+ AUTOLOAD:=$(call AutoLoad,30,it821x,1)
+ $(call AddDepends/ide)
+endef
+
+define KernelPackage/ide-it821x/description
+ Kernel module for the ITE IDE821x IDE controllers.
+endef
+
+$(eval $(call KernelPackage,ide-it821x))
+
+
+define KernelPackage/libsas
+ SUBMENU:=$(BLOCK_MENU)
+ TITLE:=SAS Domain Transport Attributes
+ KCONFIG:=CONFIG_SCSI_SAS_LIBSAS \
+ CONFIG_SCSI_SAS_ATTRS \
+ CONFIG_SCSI_SAS_ATA=y \
+ CONFIG_SCSI_SAS_HOST_SMP=y \
+ CONFIG_SCSI_SAS_LIBSAS_DEBUG=y
+ FILES:= \
+ $(LINUX_DIR)/drivers/scsi/scsi_transport_sas.ko \
+ $(LINUX_DIR)/drivers/scsi/libsas/libsas.ko
+ AUTOLOAD:=$(call AutoLoad,29,scsi_transport_sas libsas,1)
+endef
+
+define KernelPackage/libsas/description
+ SAS Domain Transport Attributes support.
+endef
+
+$(eval $(call KernelPackage,libsas,1))
+
+
+define KernelPackage/loop
+ SUBMENU:=$(BLOCK_MENU)
+ TITLE:=Loopback device support
+ KCONFIG:= \
+ CONFIG_BLK_DEV_LOOP \
+ CONFIG_BLK_DEV_CRYPTOLOOP=n
+ FILES:=$(LINUX_DIR)/drivers/block/loop.ko
+ AUTOLOAD:=$(call AutoLoad,30,loop)
+endef
+
+define KernelPackage/loop/description
+ Kernel module for loopback device support
+endef
+
+$(eval $(call KernelPackage,loop))
+
+
+define KernelPackage/mvsas
+ SUBMENU:=$(BLOCK_MENU)
+ TITLE:=Marvell 88SE6440 SAS/SATA driver
+ DEPENDS:=@TARGET_x86 +kmod-libsas
+ KCONFIG:= \
+ CONFIG_SCSI_MVSAS \
+ CONFIG_SCSI_MVSAS_TASKLET=n
+ FILES:=$(LINUX_DIR)/drivers/scsi/mvsas/mvsas.ko
+ AUTOLOAD:=$(call AutoLoad,40,mvsas,1)
+endef
+
+define KernelPackage/mvsas/description
+ Kernel support for the Marvell SAS SCSI adapters
+endef
+
+$(eval $(call KernelPackage,mvsas))
+
+
+define KernelPackage/nbd
+ SUBMENU:=$(BLOCK_MENU)
+ TITLE:=Network block device support
+ KCONFIG:=CONFIG_BLK_DEV_NBD
+ FILES:=$(LINUX_DIR)/drivers/block/nbd.ko
+ AUTOLOAD:=$(call AutoLoad,30,nbd)
+endef
+
+define KernelPackage/nbd/description
+ Kernel module for network block device support
+endef
+
+$(eval $(call KernelPackage,nbd))
+
+
+define KernelPackage/scsi-core
+ SUBMENU:=$(BLOCK_MENU)
+ TITLE:=SCSI device support
+ KCONFIG:= \
+ CONFIG_SCSI \
+ CONFIG_BLK_DEV_SD
+ FILES:= \
+ $(if $(findstring y,$(CONFIG_SCSI)),,$(LINUX_DIR)/drivers/scsi/scsi_mod.ko) \
+ $(LINUX_DIR)/drivers/scsi/sd_mod.ko
+ AUTOLOAD:=$(call AutoLoad,20,scsi_mod,1) $(call AutoLoad,40,sd_mod,1)
+endef
+
+$(eval $(call KernelPackage,scsi-core))
+
+
+define KernelPackage/scsi-generic
+ SUBMENU:=$(BLOCK_MENU)
+ TITLE:=Kernel support for SCSI generic
+ DEPENDS:=+kmod-scsi-core
+ KCONFIG:= \
+ CONFIG_CHR_DEV_SG
+ FILES:= \
+ $(LINUX_DIR)/drivers/scsi/sg.ko
+ AUTOLOAD:=$(call AutoLoad,65,sg)
+endef
+
+$(eval $(call KernelPackage,scsi-generic))
+
+
+define KernelPackage/scsi-cdrom
+ SUBMENU:=$(BLOCK_MENU)
+ TITLE:=Kernel support for CD / DVD drives
+ DEPENDS:=+kmod-scsi-core
+ KCONFIG:= \
+ CONFIG_BLK_DEV_SR \
+ CONFIG_BLK_DEV_SR_VENDOR=n
+ FILES:= \
+ $(LINUX_DIR)/drivers/cdrom/cdrom.ko \
+ $(LINUX_DIR)/drivers/scsi/sr_mod.ko
+ AUTOLOAD:=$(call AutoLoad,30,cdrom) $(call AutoLoad,45,sr_mod)
+endef
+
+$(eval $(call KernelPackage,scsi-cdrom))
+
diff --git a/package/kernel/modules/crypto.mk b/package/kernel/modules/crypto.mk
new file mode 100644
index 000000000..984ccc1f9
--- /dev/null
+++ b/package/kernel/modules/crypto.mk
@@ -0,0 +1,473 @@
+#
+# Copyright (C) 2006-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+CRYPTO_MENU:=Cryptographic API modules
+
+CRYPTO_MODULES = ALGAPI2=crypto_algapi
+
+CRYPTOMGR_MODULES = \
+ AEAD2=aead \
+ MANAGER2=cryptomgr \
+ BLKCIPHER2=crypto_blkcipher
+
+crypto_confvar=CONFIG_CRYPTO_$(word 1,$(subst =,$(space),$(1)))
+crypto_file=$(if $(findstring y,$($(call crypto_confvar,$(1)))),,$(LINUX_DIR)/crypto/$(word 2,$(subst =,$(space),$(1))).ko)
+crypto_name=$(if $(findstring y,$($(call crypto_confvar,$(1)))),,$(word 2,$(subst =,$(space),$(1))))
+
+# XXX: added CONFIG_CRYPTO_HMAC to KCONFIG so that CONFIG_CRYPTO_HASH is
+# always set, even if no hash modules are selected
+define KernelPackage/crypto-core
+ SUBMENU:=$(CRYPTO_MENU)
+ TITLE:=Core CryptoAPI modules
+ KCONFIG:= \
+ CONFIG_CRYPTO=y \
+ CONFIG_CRYPTO_HW=y \
+ CONFIG_CRYPTO_ALGAPI \
+ $(foreach mod,$(CRYPTO_MODULES),$(call crypto_confvar,$(mod)))
+ FILES:=$(foreach mod,$(CRYPTO_MODULES),$(call crypto_file,$(mod)))
+ AUTOLOAD:=$(call AutoLoad,01,$(foreach mod,$(CRYPTO_MODULES),$(call crypto_name,$(mod))),1)
+endef
+$(eval $(call KernelPackage,crypto-core))
+
+
+define AddDepends/crypto
+ SUBMENU:=$(CRYPTO_MENU)
+ DEPENDS+=kmod-crypto-core $(1)
+endef
+
+define KernelPackage/crypto-hash
+ TITLE:=CryptoAPI hash support
+ KCONFIG:=CONFIG_CRYPTO_HASH2
+ FILES:=$(LINUX_DIR)/crypto/crypto_hash.ko
+ AUTOLOAD:=$(call AutoLoad,02,crypto_hash,1)
+ $(call AddDepends/crypto)
+endef
+$(eval $(call KernelPackage,crypto-hash))
+
+define KernelPackage/crypto-manager
+ TITLE:=CryptoAPI algorithm manager
+ DEPENDS:=+kmod-crypto-hash
+ KCONFIG:= \
+ CONFIG_CRYPTO_AEAD \
+ CONFIG_CRYPTO_BLKCIPHER \
+ CONFIG_CRYPTO_MANAGER \
+ $(foreach mod,$(CRYPTOMGR_MODULES),$(call crypto_confvar,$(mod)))
+ FILES:=$(foreach mod,$(CRYPTOMGR_MODULES),$(call crypto_file,$(mod)))
+ AUTOLOAD:=$(call AutoLoad,03,$(foreach mod,$(CRYPTOMGR_MODULES),$(call crypto_name,$(mod))))
+ $(call AddDepends/crypto)
+endef
+$(eval $(call KernelPackage,crypto-manager))
+
+define KernelPackage/crypto-user
+ TITLE:=CryptoAPI userspace interface
+ DEPENDS:=+kmod-crypto-hash +kmod-crypto-manager
+ KCONFIG:= \
+ CONFIG_CRYPTO_USER_API \
+ CONFIG_CRYPTO_USER_API_HASH \
+ CONFIG_CRYPTO_USER_API_SKCIPHER
+ FILES:= \
+ $(LINUX_DIR)/crypto/af_alg.ko \
+ $(LINUX_DIR)/crypto/algif_hash.ko \
+ $(LINUX_DIR)/crypto/algif_skcipher.ko
+ AUTOLOAD:=$(call AutoLoad,09,af_alg algif_hash algif_skcipher)
+ $(call AddDepends/crypto)
+endef
+$(eval $(call KernelPackage,crypto-user))
+
+define KernelPackage/crypto-wq
+ TITLE:=CryptoAPI work queue handling
+ KCONFIG:=CONFIG_CRYPTO_WORKQUEUE
+ FILES:=$(LINUX_DIR)/crypto/crypto_wq.ko
+ AUTOLOAD:=$(call AutoLoad,09,crypto_wq)
+ $(call AddDepends/crypto)
+endef
+$(eval $(call KernelPackage,crypto-wq))
+
+define KernelPackage/crypto-rng
+ TITLE:=CryptoAPI random number generation
+ KCONFIG:=CONFIG_CRYPTO_RNG2
+ FILES:= \
+ $(LINUX_DIR)/crypto/rng.ko \
+ $(LINUX_DIR)/crypto/krng.ko
+ AUTOLOAD:=$(call AutoLoad,09,rng krng)
+ $(call AddDepends/crypto)
+endef
+$(eval $(call KernelPackage,crypto-rng))
+
+define KernelPackage/crypto-iv
+ TITLE:=CryptoAPI initialization vectors
+ DEPENDS:=+kmod-crypto-manager +kmod-crypto-rng +kmod-crypto-wq
+ KCONFIG:= CONFIG_CRYPTO_BLKCIPHER2
+ FILES:= \
+ $(LINUX_DIR)/crypto/eseqiv.ko \
+ $(LINUX_DIR)/crypto/chainiv.ko
+ AUTOLOAD:=$(call AutoLoad,10,eseqiv chainiv)
+ $(call AddDepends/crypto)
+endef
+$(eval $(call KernelPackage,crypto-iv))
+
+define KernelPackage/crypto-hw-padlock
+ TITLE:=VIA PadLock ACE with AES/SHA hw crypto module
+ DEPENDS:=+kmod-crypto-aes
+ KCONFIG:= \
+ CONFIG_CRYPTO_DEV_PADLOCK \
+ CONFIG_CRYPTO_DEV_PADLOCK_AES \
+ CONFIG_CRYPTO_DEV_PADLOCK_SHA
+ FILES:= \
+ $(LINUX_DIR)/drivers/crypto/padlock-aes.ko \
+ $(LINUX_DIR)/drivers/crypto/padlock-sha.ko
+ AUTOLOAD:=$(call AutoLoad,09,padlock-aes padlock-sha)
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-hw-padlock))
+
+
+define KernelPackage/crypto-hw-geode
+ TITLE:=AMD Geode hardware crypto module
+ KCONFIG:= \
+ CONFIG_CRYPTO_DEV_GEODE
+ FILES:=$(LINUX_DIR)/drivers/crypto/geode-aes.ko
+ AUTOLOAD:=$(call AutoLoad,09,geode-aes)
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-hw-geode))
+
+
+define KernelPackage/crypto-hw-hifn-795x
+ TITLE:=HIFN 795x crypto accelerator
+ DEPENDS:=@!TARGET_ubicom32
+ KCONFIG:= \
+ CONFIG_HW_RANDOM=y \
+ CONFIG_CRYPTO_DEV_HIFN_795X \
+ CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y
+ FILES:=$(LINUX_DIR)/drivers/crypto/hifn_795x.ko
+ AUTOLOAD:=$(call AutoLoad,09,hifn_795x)
+ $(call AddDepends/crypto,+kmod-crypto-des)
+endef
+
+$(eval $(call KernelPackage,crypto-hw-hifn-795x))
+
+
+define KernelPackage/crypto-hw-ppc4xx
+ TITLE:=AMCC PPC4xx hardware crypto module
+ DEPENDS:=@TARGET_ppc40x||TARGET_ppc44x
+ KCONFIG:= \
+ CONFIG_CRYPTO_DEV_PPC4XX
+ FILES:=$(LINUX_DIR)/drivers/crypto/amcc/crypto4xx.ko
+ AUTOLOAD:=$(call AutoLoad,90,crypto4xx)
+ $(call AddDepends/crypto)
+endef
+
+define KernelPackage/crypto-hw-ppc4xx/description
+ Kernel support for the AMCC PPC4xx HW crypto engine.
+endef
+
+$(eval $(call KernelPackage,crypto-hw-ppc4xx))
+
+
+define KernelPackage/crypto-aes
+ TITLE:=AES cipher CryptoAPI module
+ KCONFIG:=CONFIG_CRYPTO_AES CONFIG_CRYPTO_AES_586
+ FILES:=$(LINUX_DIR)/crypto/aes_generic.ko
+ AUTOLOAD:=$(call AutoLoad,09,aes_generic)
+ $(call AddDepends/crypto)
+endef
+
+define KernelPackage/crypto-aes/x86
+ FILES+=$(LINUX_DIR)/arch/x86/crypto/aes-i586.ko
+ AUTOLOAD:=$(call AutoLoad,09,aes_generic aes-i586)
+endef
+
+$(eval $(call KernelPackage,crypto-aes))
+
+
+define KernelPackage/crypto-arc4
+ TITLE:=ARC4 (RC4) cipher CryptoAPI module
+ KCONFIG:=CONFIG_CRYPTO_ARC4
+ FILES:=$(LINUX_DIR)/crypto/arc4.ko
+ AUTOLOAD:=$(call AutoLoad,09,arc4)
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-arc4))
+
+
+define KernelPackage/crypto-authenc
+ TITLE:=Combined mode wrapper for IPsec
+ DEPENDS:=+kmod-crypto-manager
+ KCONFIG:=CONFIG_CRYPTO_AUTHENC
+ FILES:=$(LINUX_DIR)/crypto/authenc.ko
+ AUTOLOAD:=$(call AutoLoad,09,authenc)
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-authenc))
+
+define KernelPackage/crypto-cbc
+ TITLE:=Cipher Block Chaining CryptoAPI module
+ DEPENDS:=+kmod-crypto-manager
+ KCONFIG:=CONFIG_CRYPTO_CBC
+ FILES:=$(LINUX_DIR)/crypto/cbc.ko
+ AUTOLOAD:=$(call AutoLoad,09,cbc)
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-cbc))
+
+define KernelPackage/crypto-crc32c
+ TITLE:=CRC32c CRC module
+ DEPENDS:=+kmod-crypto-hash
+ KCONFIG:=CONFIG_CRYPTO_CRC32C
+ FILES:=$(LINUX_DIR)/crypto/crc32c.ko
+ AUTOLOAD:=$(call AutoLoad,04,crc32c,1)
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-crc32c))
+
+define KernelPackage/crypto-des
+ TITLE:=DES/3DES cipher CryptoAPI module
+ KCONFIG:=CONFIG_CRYPTO_DES
+ FILES:=$(LINUX_DIR)/crypto/des_generic.ko
+ AUTOLOAD:=$(call AutoLoad,09,des_generic)
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-des))
+
+define KernelPackage/crypto-deflate
+ TITLE:=Deflate compression CryptoAPI module
+ DEPENDS:=+kmod-lib-zlib
+ KCONFIG:=CONFIG_CRYPTO_DEFLATE
+ FILES:=$(LINUX_DIR)/crypto/deflate.ko
+ AUTOLOAD:=$(call AutoLoad,09,deflate)
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-deflate))
+
+define KernelPackage/crypto-ecb
+ TITLE:=Electronic CodeBook CryptoAPI module
+ DEPENDS:=+kmod-crypto-manager
+ KCONFIG:=CONFIG_CRYPTO_ECB
+ FILES:=$(LINUX_DIR)/crypto/ecb.ko
+ AUTOLOAD:=$(call AutoLoad,09,ecb)
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-ecb))
+
+
+define KernelPackage/crypto-hmac
+ TITLE:=HMAC digest CryptoAPI module
+ DEPENDS:=+kmod-crypto-hash
+ KCONFIG:=CONFIG_CRYPTO_HMAC
+ FILES:=$(LINUX_DIR)/crypto/hmac.ko
+ DEPENDS:=+kmod-crypto-manager
+ AUTOLOAD:=$(call AutoLoad,09,hmac)
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-hmac))
+
+
+define KernelPackage/crypto-md4
+ TITLE:=MD4 digest CryptoAPI module
+ DEPENDS:=+kmod-crypto-hash
+ KCONFIG:=CONFIG_CRYPTO_MD4
+ FILES:=$(LINUX_DIR)/crypto/md4.ko
+ AUTOLOAD:=$(call AutoLoad,09,md4)
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-md4))
+
+
+define KernelPackage/crypto-md5
+ TITLE:=MD5 digest CryptoAPI module
+ DEPENDS:=+kmod-crypto-hash
+ KCONFIG:=CONFIG_CRYPTO_MD5
+ FILES:=$(LINUX_DIR)/crypto/md5.ko
+ AUTOLOAD:=$(call AutoLoad,09,md5)
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-md5))
+
+
+define KernelPackage/crypto-michael-mic
+ TITLE:=Michael MIC keyed digest CryptoAPI module
+ DEPENDS:=+kmod-crypto-hash
+ KCONFIG:=CONFIG_CRYPTO_MICHAEL_MIC
+ FILES:=$(LINUX_DIR)/crypto/michael_mic.ko
+ AUTOLOAD:=$(call AutoLoad,09,michael_mic)
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-michael-mic))
+
+
+define KernelPackage/crypto-sha1
+ TITLE:=SHA1 digest CryptoAPI module
+ DEPENDS:=+kmod-crypto-hash
+ KCONFIG:=CONFIG_CRYPTO_SHA1
+ FILES:=$(LINUX_DIR)/crypto/sha1_generic.ko
+ AUTOLOAD:=$(call AutoLoad,09,sha1_generic)
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-sha1))
+
+
+define KernelPackage/crypto-misc
+ TITLE:=Other CryptoAPI modules
+ DEPENDS:=+kmod-crypto-manager
+ KCONFIG:= \
+ CONFIG_CRYPTO_ANUBIS \
+ CONFIG_CRYPTO_BLOWFISH \
+ CONFIG_CRYPTO_CAMELLIA \
+ CONFIG_CRYPTO_CAST5 \
+ CONFIG_CRYPTO_CAST6 \
+ CONFIG_CRYPTO_FCRYPT \
+ CONFIG_CRYPTO_KHAZAD \
+ CONFIG_CRYPTO_SERPENT \
+ CONFIG_CRYPTO_SHA256 \
+ CONFIG_CRYPTO_SHA512 \
+ CONFIG_CRYPTO_TEA \
+ CONFIG_CRYPTO_TGR192 \
+ CONFIG_CRYPTO_TWOFISH \
+ CONFIG_CRYPTO_TWOFISH_COMMON \
+ CONFIG_CRYPTO_TWOFISH_586 \
+ CONFIG_CRYPTO_WP512
+ FILES:= \
+ $(LINUX_DIR)/crypto/anubis.ko \
+ $(LINUX_DIR)/crypto/camellia.ko \
+ $(LINUX_DIR)/crypto/cast5.ko \
+ $(LINUX_DIR)/crypto/cast6.ko \
+ $(LINUX_DIR)/crypto/fcrypt.ko \
+ $(LINUX_DIR)/crypto/khazad.ko \
+ $(LINUX_DIR)/crypto/sha256_generic.ko \
+ $(LINUX_DIR)/crypto/sha512_generic.ko \
+ $(LINUX_DIR)/crypto/tea.ko \
+ $(LINUX_DIR)/crypto/tgr192.ko \
+ $(LINUX_DIR)/crypto/twofish_common.ko \
+ $(LINUX_DIR)/crypto/wp512.ko \
+ $(LINUX_DIR)/crypto/twofish_generic.ko
+ FILES += \
+ $(LINUX_DIR)/crypto/blowfish_common.ko \
+ $(LINUX_DIR)/crypto/blowfish_generic.ko \
+ $(LINUX_DIR)/crypto/serpent_generic.ko
+ $(call AddDepends/crypto)
+endef
+
+
+define KernelPackage/crypto-misc/x86
+ FILES+=$(LINUX_DIR)/arch/x86/crypto/twofish-i586.ko
+endef
+
+$(eval $(call KernelPackage,crypto-misc))
+
+
+define KernelPackage/crypto-ocf
+ TITLE:=OCF modules
+ DEPENDS:=+@OPENSSL_ENGINE_CRYPTO @!TARGET_uml +kmod-crypto-manager
+ KCONFIG:= \
+ CONFIG_OCF_OCF \
+ CONFIG_OCF_CRYPTODEV \
+ CONFIG_OCF_CRYPTOSOFT \
+ CONFIG_OCF_FIPS=y \
+ CONFIG_OCF_RANDOMHARVEST=y
+ FILES:= \
+ $(LINUX_DIR)/crypto/ocf/ocf.ko \
+ $(LINUX_DIR)/crypto/ocf/cryptodev.ko \
+ $(LINUX_DIR)/crypto/ocf/cryptosoft.ko
+ AUTOLOAD:=$(call AutoLoad,09, \
+ ocf \
+ cryptodev \
+ cryptosoft \
+ )
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-ocf))
+
+
+define KernelPackage/crypto-ocf-hifn7751
+ TITLE:=OCF support for Hifn 6500/7751/7811/795x, Invertex AEON and NetSec 7751 devices
+ DEPENDS:=+@OPENSSL_ENGINE_CRYPTO @PCI_SUPPORT @!TARGET_uml kmod-crypto-ocf
+ KCONFIG:=CONFIG_OCF_HIFN
+ FILES:=$(LINUX_DIR)/crypto/ocf/hifn/hifn7751.ko
+ AUTOLOAD:=$(call AutoLoad,10,hifn7751)
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-ocf-hifn7751))
+
+
+define KernelPackage/crypto-ocf-hifnhipp
+ TITLE:=OCF support for Hifn 7855/8155 devices
+ DEPENDS:=+@OPENSSL_ENGINE_CRYPTO @PCI_SUPPORT @!TARGET_uml kmod-crypto-ocf
+ KCONFIG:=CONFIG_OCF_HIFNHIPP
+ FILES:=$(LINUX_DIR)/crypto/ocf/hifn/hifnHIPP.ko
+ AUTOLOAD:=$(call AutoLoad,10,hifnHIPP)
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-ocf-hifnhipp))
+
+
+define KernelPackage/crypto-null
+ TITLE:=Null CryptoAPI module
+ KCONFIG:=CONFIG_CRYPTO_NULL
+ FILES:=$(LINUX_DIR)/crypto/crypto_null.ko
+ AUTOLOAD:=$(call AutoLoad,09,crypto_null)
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-null))
+
+
+define KernelPackage/crypto-test
+ TITLE:=Test CryptoAPI module
+ KCONFIG:=CONFIG_CRYPTO_TEST
+ FILES:=$(LINUX_DIR)/crypto/tcrypt.ko
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-test))
+
+
+define KernelPackage/crypto-xts
+ TITLE:=XTS cipher CryptoAPI module
+ DEPENDS:=+kmod-crypto-manager
+ KCONFIG:= \
+ CONFIG_CRYPTO_GF128MUL \
+ CONFIG_CRYPTO_XTS
+ FILES:= \
+ $(LINUX_DIR)/crypto/xts.ko \
+ $(LINUX_DIR)/crypto/gf128mul.ko
+ AUTOLOAD:=$(call AutoLoad,09, \
+ gf128mul \
+ xts \
+ )
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-xts))
+
+define KernelPackage/crypto-mv-cesa
+ TITLE:=Marvell crypto engine
+ DEPENDS:=+kmod-crypto-manager +kmod-crypto-aes @TARGET_kirkwood||TARGET_orion
+ KCONFIG:=CONFIG_CRYPTO_DEV_MV_CESA
+ FILES:=$(LINUX_DIR)/drivers/crypto/mv_cesa.ko
+ AUTOLOAD:=$(call AutoLoad,09,mv_cesa)
+ $(call AddDepends/crypto)
+endef
+
+$(eval $(call KernelPackage,crypto-mv-cesa))
diff --git a/package/kernel/modules/firewire.mk b/package/kernel/modules/firewire.mk
new file mode 100644
index 000000000..34edf0c51
--- /dev/null
+++ b/package/kernel/modules/firewire.mk
@@ -0,0 +1,77 @@
+#
+# Copyright (C) 2008-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+FIREWIRE_MENU:=FireWire support
+
+
+define KernelPackage/firewire
+ SUBMENU:=$(FIREWIRE_MENU)
+ TITLE:=Support for FireWire (new stack)
+ DEPENDS:=@PCI_SUPPORT +kmod-lib-crc-itu-t
+ KCONFIG:=CONFIG_FIREWIRE
+ FILES:=$(LINUX_DIR)/drivers/firewire/firewire-core.ko
+ AUTOLOAD:=$(call AutoLoad,20,firewire-core)
+endef
+
+define KernelPackage/firewire/description
+ Kernel support for FireWire (new stack)
+endef
+
+$(eval $(call KernelPackage,firewire))
+
+
+define KernelPackage/firewire-ohci
+ SUBMENU:=$(FIREWIRE_MENU)
+ TITLE:=Support for OHCI-1394 controllers
+ DEPENDS:=kmod-firewire
+ KCONFIG:= \
+ CONFIG_FIREWIRE_OHCI \
+ CONFIG_FIREWIRE_OHCI_DEBUG=n \
+ CONFIG_FIREWIRE_OHCI_REMOTE_DMA=n
+ FILES:=$(LINUX_DIR)/drivers/firewire/firewire-ohci.ko
+ AUTOLOAD:=$(call AutoLoad,50,firewire-ohci)
+endef
+
+
+define KernelPackage/firewire-ohci/description
+ Kernel support for FireWire OHCI-1394 controllers
+endef
+
+$(eval $(call KernelPackage,firewire-ohci))
+
+
+define KernelPackage/firewire-sbp2
+ SUBMENU:=$(FIREWIRE_MENU)
+ TITLE:=Support for SBP-2 devices over FireWire
+ DEPENDS:=kmod-firewire +kmod-scsi-core
+ KCONFIG:=CONFIG_FIREWIRE_SBP2
+ FILES:=$(LINUX_DIR)/drivers/firewire/firewire-sbp2.ko
+ AUTOLOAD:=$(call AutoLoad,50,firewire-sbp2)
+endef
+
+define KernelPackage/firewire-sbp2/description
+ Kernel support for SBP-2 devices over FireWire
+endef
+
+$(eval $(call KernelPackage,firewire-sbp2))
+
+
+define KernelPackage/firewire-net
+ SUBMENU:=$(FIREWIRE_MENU)
+ TITLE:=Support for IP networking over FireWire
+ DEPENDS:=kmod-firewire
+ KCONFIG:=CONFIG_FIREWIRE_NET
+ FILES:=$(LINUX_DIR)/drivers/firewire/firewire-net.ko
+ AUTOLOAD:=$(call AutoLoad,50,firewire-net)
+endef
+
+define KernelPackage/firewire-net/description
+ Kernel support for IPv4 over FireWire
+endef
+
+$(eval $(call KernelPackage,firewire-net))
+
diff --git a/package/kernel/modules/fs.mk b/package/kernel/modules/fs.mk
new file mode 100644
index 000000000..0bc0d5578
--- /dev/null
+++ b/package/kernel/modules/fs.mk
@@ -0,0 +1,354 @@
+#
+# Copyright (C) 2006-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+FS_MENU:=Filesystems
+
+define KernelPackage/fs-autofs4
+ SUBMENU:=$(FS_MENU)
+ TITLE:=AUTOFS4 filesystem support
+ KCONFIG:=CONFIG_AUTOFS4_FS
+ FILES:=$(LINUX_DIR)/fs/autofs4/autofs4.ko
+ AUTOLOAD:=$(call AutoLoad,30,autofs4)
+endef
+
+define KernelPackage/fs-autofs4/description
+ Kernel module for AutoFS4 support
+endef
+
+$(eval $(call KernelPackage,fs-autofs4))
+
+
+define KernelPackage/fs-btrfs
+ SUBMENU:=$(FS_MENU)
+ TITLE:=BTRFS filesystem support
+ DEPENDS:=+kmod-lib-crc32c +kmod-lib-lzo +kmod-lib-zlib
+ KCONFIG:=\
+ CONFIG_BTRFS_FS \
+ CONFIG_BTRFS_FS_POSIX_ACL=n \
+ CONFIG_BTRFS_FS_CHECK_INTEGRITY=n
+ FILES:=\
+ $(LINUX_DIR)/fs/btrfs/btrfs.ko
+ AUTOLOAD:=$(call AutoLoad,30,btrfs,1)
+endef
+
+define KernelPackage/fs-btrfs/description
+ Kernel module for BTRFS support
+endef
+
+$(eval $(call KernelPackage,fs-btrfs))
+
+
+define KernelPackage/fs-cifs
+ SUBMENU:=$(FS_MENU)
+ TITLE:=CIFS support
+ KCONFIG:= \
+ CONFIG_CIFS \
+ CONFIG_CIFS_DFS_UPCALL=n \
+ CONFIG_CIFS_UPCALL=n
+ FILES:=$(LINUX_DIR)/fs/cifs/cifs.ko
+ AUTOLOAD:=$(call AutoLoad,30,cifs)
+ $(call AddDepends/nls)
+ DEPENDS+= \
+ +kmod-crypto-arc4 \
+ +kmod-crypto-hmac \
+ +kmod-crypto-md5 \
+ +kmod-crypto-md4 \
+ +kmod-crypto-des \
+ +kmod-crypto-ecb
+endef
+
+define KernelPackage/fs-cifs/description
+ Kernel module for CIFS support
+endef
+
+$(eval $(call KernelPackage,fs-cifs))
+
+
+define KernelPackage/fs-exportfs
+ SUBMENU:=$(FS_MENU)
+ TITLE:=exportfs kernel server support
+ KCONFIG:=CONFIG_EXPORTFS
+ FILES=$(LINUX_DIR)/fs/exportfs/exportfs.ko
+ AUTOLOAD:=$(call AutoLoad,20,exportfs)
+endef
+
+define KernelPackage/fs-exportfs/description
+ Kernel module for exportfs. Needed for some other modules.
+endef
+
+$(eval $(call KernelPackage,fs-exportfs))
+
+
+define KernelPackage/fs-ext4
+ SUBMENU:=$(FS_MENU)
+ TITLE:=EXT4 filesystem support
+ KCONFIG:= \
+ CONFIG_EXT4_FS \
+ CONFIG_JBD2
+ FILES:= \
+ $(LINUX_DIR)/fs/ext4/ext4.ko \
+ $(LINUX_DIR)/fs/jbd2/jbd2.ko \
+ $(LINUX_DIR)/fs/mbcache.ko
+ AUTOLOAD:=$(call AutoLoad,30,mbcache jbd2 ext4,1)
+ $(call AddDepends/crc16)
+endef
+
+define KernelPackage/fs-ext4/description
+ Kernel module for EXT4 filesystem support
+endef
+
+$(eval $(call KernelPackage,fs-ext4))
+
+
+define KernelPackage/fuse
+ SUBMENU:=$(FS_MENU)
+ TITLE:=FUSE (Filesystem in Userspace) support
+ KCONFIG:= CONFIG_FUSE_FS
+ FILES:=$(LINUX_DIR)/fs/fuse/fuse.ko
+ AUTOLOAD:=$(call AutoLoad,80,fuse)
+endef
+
+define KernelPackage/fuse/description
+ Kernel module for userspace filesystem support
+endef
+
+$(eval $(call KernelPackage,fuse))
+
+
+define KernelPackage/fs-hfs
+ SUBMENU:=$(FS_MENU)
+ TITLE:=HFS+ filesystem support
+ KCONFIG:=CONFIG_HFS_FS
+ FILES:=$(LINUX_DIR)/fs/hfs/hfs.ko
+ AUTOLOAD:=$(call AutoLoad,30,hfs)
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/fs-hfs/description
+ Kernel module for HFS filesystem support
+endef
+
+$(eval $(call KernelPackage,fs-hfs))
+
+
+define KernelPackage/fs-hfsplus
+ SUBMENU:=$(FS_MENU)
+ TITLE:=HFS+ filesystem support
+ KCONFIG:=CONFIG_HFSPLUS_FS
+ FILES:=$(LINUX_DIR)/fs/hfsplus/hfsplus.ko
+ AUTOLOAD:=$(call AutoLoad,30,hfsplus)
+ $(call AddDepends/nls,utf8)
+endef
+
+define KernelPackage/fs-hfsplus/description
+ Kernel module for HFS+ filesystem support
+endef
+
+$(eval $(call KernelPackage,fs-hfsplus))
+
+
+define KernelPackage/fs-isofs
+ SUBMENU:=$(FS_MENU)
+ TITLE:=ISO9660 filesystem support
+ KCONFIG:=CONFIG_ISO9660_FS CONFIG_JOLIET=y CONFIG_ZISOFS=n
+ FILES:=$(LINUX_DIR)/fs/isofs/isofs.ko
+ AUTOLOAD:=$(call AutoLoad,30,isofs)
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/fs-isofs/description
+ Kernel module for ISO9660 filesystem support
+endef
+
+$(eval $(call KernelPackage,fs-isofs))
+
+
+define KernelPackage/fs-minix
+ SUBMENU:=$(FS_MENU)
+ TITLE:=Minix filesystem support
+ KCONFIG:=CONFIG_MINIX_FS
+ FILES:=$(LINUX_DIR)/fs/minix/minix.ko
+ AUTOLOAD:=$(call AutoLoad,30,minix)
+endef
+
+define KernelPackage/fs-minix/description
+ Kernel module for Minix filesystem support
+endef
+
+$(eval $(call KernelPackage,fs-minix))
+
+
+define KernelPackage/fs-msdos
+ SUBMENU:=$(FS_MENU)
+ TITLE:=MSDOS filesystem support
+ KCONFIG:=CONFIG_MSDOS_FS
+ FILES:=$(LINUX_DIR)/fs/fat/msdos.ko
+ AUTOLOAD:=$(call AutoLoad,40,msdos)
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/fs-msdos/description
+ Kernel module for MSDOS filesystem support
+endef
+
+$(eval $(call KernelPackage,fs-msdos))
+
+
+define KernelPackage/fs-nfs
+ SUBMENU:=$(FS_MENU)
+ TITLE:=NFS filesystem support
+ DEPENDS:=+kmod-fs-nfs-common
+ KCONFIG:= \
+ CONFIG_NFS_FS \
+ CONFIG_NFS_USE_LEGACY_DNS=n \
+ CONFIG_NFS_USE_NEW_IDMAPPER=n
+ FILES:= \
+ $(LINUX_DIR)/fs/nfs/nfs.ko
+ AUTOLOAD:=$(call AutoLoad,40,nfs)
+endef
+
+define KernelPackage/fs-nfs/description
+ Kernel module for NFS support
+endef
+
+$(eval $(call KernelPackage,fs-nfs))
+
+
+define KernelPackage/fs-nfs-common
+ SUBMENU:=$(FS_MENU)
+ TITLE:=Common NFS filesystem modules
+ KCONFIG:= \
+ CONFIG_LOCKD \
+ CONFIG_SUNRPC
+ FILES:= \
+ $(LINUX_DIR)/fs/lockd/lockd.ko \
+ $(LINUX_DIR)/net/sunrpc/sunrpc.ko
+ AUTOLOAD:=$(call AutoLoad,30,sunrpc lockd)
+endef
+
+$(eval $(call KernelPackage,fs-nfs-common))
+
+
+define KernelPackage/fs-nfs-common-v4
+ SUBMENU:=$(FS_MENU)
+ TITLE:=Common NFS V4 filesystem modules
+ KCONFIG+=\
+ CONFIG_SUNRPC_GSS\
+ CONFIG_NFS_V4=y\
+ CONFIG_NFSD_V4=y
+ DEPENDS:= @BROKEN
+ FILES+=$(LINUX_DIR)/net/sunrpc/auth_gss/auth_rpcgss.ko
+ AUTOLOAD=$(call AutoLoad,30,auth_rpcgss)
+endef
+
+define KernelPackage/fs-nfs-common-v4/description
+ Kernel modules for NFS V4 & NFSD V4 kernel support
+endef
+
+$(eval $(call KernelPackage,fs-nfs-common-v4))
+
+
+define KernelPackage/fs-nfsd
+ SUBMENU:=$(FS_MENU)
+ TITLE:=NFS kernel server support
+ DEPENDS:=+kmod-fs-nfs-common +kmod-fs-exportfs
+ KCONFIG:= \
+ CONFIG_NFSD \
+ CONFIG_NFSD_FAULT_INJECTION=n
+ FILES:=$(LINUX_DIR)/fs/nfsd/nfsd.ko
+ AUTOLOAD:=$(call AutoLoad,40,nfsd)
+endef
+
+define KernelPackage/fs-nfsd/description
+ Kernel module for NFS kernel server support
+endef
+
+$(eval $(call KernelPackage,fs-nfsd))
+
+
+define KernelPackage/fs-ntfs
+ SUBMENU:=$(FS_MENU)
+ TITLE:=NTFS filesystem support
+ KCONFIG:=CONFIG_NTFS_FS
+ FILES:=$(LINUX_DIR)/fs/ntfs/ntfs.ko
+ AUTOLOAD:=$(call AutoLoad,30,ntfs)
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/fs-ntfs/description
+ Kernel module for NTFS filesystem support
+endef
+
+$(eval $(call KernelPackage,fs-ntfs))
+
+
+define KernelPackage/fs-reiserfs
+ SUBMENU:=$(FS_MENU)
+ TITLE:=ReiserFS filesystem support
+ KCONFIG:=CONFIG_REISERFS_FS
+ FILES:=$(LINUX_DIR)/fs/reiserfs/reiserfs.ko
+ AUTOLOAD:=$(call AutoLoad,30,reiserfs,1)
+endef
+
+define KernelPackage/fs-reiserfs/description
+ Kernel module for ReiserFS support
+endef
+
+$(eval $(call KernelPackage,fs-reiserfs))
+
+
+define KernelPackage/fs-udf
+ SUBMENU:=$(FS_MENU)
+ TITLE:=UDF filesystem support
+ KCONFIG:=CONFIG_UDF_FS
+ FILES:=$(LINUX_DIR)/fs/udf/udf.ko
+ AUTOLOAD:=$(call AutoLoad,30,udf)
+ DEPENDS:=+kmod-lib-crc-itu-t
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/fs-udf/description
+ Kernel module for UDF filesystem support
+endef
+
+$(eval $(call KernelPackage,fs-udf))
+
+
+define KernelPackage/fs-vfat
+ SUBMENU:=$(FS_MENU)
+ TITLE:=VFAT filesystem support
+ KCONFIG:= \
+ CONFIG_FAT_FS \
+ CONFIG_VFAT_FS
+ FILES:= \
+ $(LINUX_DIR)/fs/fat/fat.ko \
+ $(LINUX_DIR)/fs/fat/vfat.ko
+ AUTOLOAD:=$(call AutoLoad,30,fat vfat)
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/fs-vfat/description
+ Kernel module for VFAT filesystem support
+endef
+
+$(eval $(call KernelPackage,fs-vfat))
+
+
+define KernelPackage/fs-xfs
+ SUBMENU:=$(FS_MENU)
+ TITLE:=XFS filesystem support
+ KCONFIG:=CONFIG_XFS_FS
+ DEPENDS:= +kmod-fs-exportfs @!avr32
+ FILES:=$(LINUX_DIR)/fs/xfs/xfs.ko
+ AUTOLOAD:=$(call AutoLoad,30,xfs,1)
+endef
+
+define KernelPackage/fs-xfs/description
+ Kernel module for XFS support
+endef
+
+$(eval $(call KernelPackage,fs-xfs))
diff --git a/package/kernel/modules/hwmon.mk b/package/kernel/modules/hwmon.mk
new file mode 100644
index 000000000..d549336b3
--- /dev/null
+++ b/package/kernel/modules/hwmon.mk
@@ -0,0 +1,192 @@
+#
+# Copyright (C) 2006-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+HWMON_MENU:=Hardware Monitoring Support
+
+define KernelPackage/hwmon-core
+ SUBMENU:=$(HWMON_MENU)
+ TITLE:=Hardware monitoring support
+ KCONFIG:= \
+ CONFIG_HWMON \
+ CONFIG_HWMON_DEBUG_CHIP=n
+ FILES:= \
+ $(LINUX_DIR)/drivers/hwmon/hwmon.ko
+ AUTOLOAD:=$(call AutoLoad,40,hwmon)
+endef
+
+define KernelPackage/hwmon-core/description
+ Kernel modules for hardware monitoring
+endef
+
+$(eval $(call KernelPackage,hwmon-core))
+
+
+define AddDepends/hwmon
+ SUBMENU:=$(HWMON_MENU)
+ DEPENDS:=kmod-hwmon-core $(1)
+endef
+
+define KernelPackage/hwmon-vid
+ TITLE:=VID/VRM/VRD voltage conversion module.
+ KCONFIG:=CONFIG_HWMON_VID
+ FILES:=$(LINUX_DIR)/drivers/hwmon/hwmon-vid.ko
+ AUTOLOAD:=$(call AutoLoad,41,hwmon-vid)
+ $(call AddDepends/hwmon,)
+endef
+
+define KernelPackage/hwmon-vid/description
+ VID/VRM/VRD voltage conversion module for hardware monitoring.
+endef
+
+$(eval $(call KernelPackage,hwmon-vid))
+
+
+define KernelPackage/hwmon-adt7475
+ TITLE:=ADT7473/7475/7476/7490 monitoring support
+ KCONFIG:=CONFIG_SENSORS_ADT7475
+ FILES:=$(LINUX_DIR)/drivers/hwmon/adt7475.ko
+ AUTOLOAD:=$(call AutoLoad,60,adt7475)
+ $(call AddDepends/hwmon,+kmod-i2c-core +kmod-hwmon-vid)
+endef
+
+define KernelPackage/hwmon-adt7475/description
+ Kernel module for ADT7473/7475/7476/7490 thermal monitor chip.
+endef
+
+$(eval $(call KernelPackage,hwmon-adt7475))
+
+
+define KernelPackage/hwmon-lm63
+ TITLE:=LM63/64 monitoring support
+ KCONFIG:=CONFIG_SENSORS_LM63
+ FILES:=$(LINUX_DIR)/drivers/hwmon/lm63.ko
+ AUTOLOAD:=$(call AutoLoad,60,lm63)
+ $(call AddDepends/hwmon,+kmod-i2c-core)
+endef
+
+define KernelPackage/hwmon-lm63/description
+ Kernel module for lm63 and lm64 thermal monitor chip
+endef
+
+$(eval $(call KernelPackage,hwmon-lm63))
+
+
+define KernelPackage/hwmon-lm75
+ TITLE:=LM75 monitoring support
+ KCONFIG:=CONFIG_SENSORS_LM75
+ FILES:=$(LINUX_DIR)/drivers/hwmon/lm75.ko
+ AUTOLOAD:=$(call AutoLoad,60,lm75)
+ $(call AddDepends/hwmon,+kmod-i2c-core)
+endef
+
+define KernelPackage/hwmon-lm75/description
+ Kernel module for lm75 thermal monitor chip
+endef
+
+$(eval $(call KernelPackage,hwmon-lm75))
+
+
+define KernelPackage/hwmon-lm77
+ TITLE:=LM77 monitoring support
+ KCONFIG:=CONFIG_SENSORS_LM77
+ FILES:=$(LINUX_DIR)/drivers/hwmon/lm77.ko
+ AUTOLOAD:=$(call AutoLoad,60,lm77)
+ $(call AddDepends/hwmon,+kmod-i2c-core)
+endef
+
+define KernelPackage/hwmon-lm77/description
+ Kernel module for LM77 thermal monitor chip
+endef
+
+$(eval $(call KernelPackage,hwmon-lm77))
+
+
+define KernelPackage/hwmon-lm85
+ TITLE:=LM85 monitoring support
+ KCONFIG:=CONFIG_SENSORS_LM85
+ FILES:=$(LINUX_DIR)/drivers/hwmon/lm85.ko
+ AUTOLOAD:=$(call AutoLoad,60,lm85)
+ $(call AddDepends/hwmon,+kmod-i2c-core +kmod-hwmon-vid)
+endef
+
+define KernelPackage/hwmon-lm85/description
+ Kernel module for LM85 thermal monitor chip
+endef
+
+$(eval $(call KernelPackage,hwmon-lm85))
+
+
+define KernelPackage/hwmon-lm90
+ TITLE:=LM90 monitoring support
+ KCONFIG:=CONFIG_SENSORS_LM90
+ FILES:=$(LINUX_DIR)/drivers/hwmon/lm90.ko
+ AUTOLOAD:=$(call AutoLoad,60,lm90)
+ $(call AddDepends/hwmon,+kmod-i2c-core)
+endef
+
+define KernelPackage/hwmon-lm90/description
+ Kernel module for LM90 thermal monitor chip
+endef
+
+$(eval $(call KernelPackage,hwmon-lm90))
+
+define KernelPackage/hwmon-lm95241
+ TITLE:=LM95241 monitoring support
+ KCONFIG:=CONFIG_SENSORS_LM95241
+ FILES:=$(LINUX_DIR)/drivers/hwmon/lm95241.ko
+ AUTOLOAD:=$(call AutoLoad,60,lm95241)
+ $(call AddDepends/hwmon,+kmod-i2c-core)
+endef
+
+define KernelPackage/hwmon-lm95241/description
+ Kernel module for LM95241 thermal monitor chip
+endef
+
+$(eval $(call KernelPackage,hwmon-lm95241))
+
+define KernelPackage/hwmon-sht21
+ TITLE:=Sensiron SHT21 and compat. monitoring support
+ KCONFIG:=CONFIG_SENSORS_SHT21
+ FILES:=$(LINUX_DIR)/drivers/hwmon/sht21.ko
+ AUTOLOAD:=$(call AutoLoad,60,sht21)
+ $(call AddDepends/hwmon,+kmod-i2c-core)
+endef
+
+define KernelPackage/hwmon-sht21/description
+ Kernel module for Sensirion SHT21 and SHT25 temperature and humidity sensors chip
+endef
+
+$(eval $(call KernelPackage,hwmon-sht21))
+
+define KernelPackage/hwmon-pc87360
+ TITLE:=PC87360 monitoring support
+ KCONFIG:=CONFIG_SENSORS_PC87360
+ FILES:=$(LINUX_DIR)/drivers/hwmon/pc87360.ko
+ AUTOLOAD:=$(call AutoLoad,50,pc87360)
+ $(call AddDepends/hwmon,@TARGET_x86 +kmod-hwmon-vid)
+endef
+
+define KernelPackage/hwmon-pc87360/description
+ Kernel modules for PC87360 chips
+endef
+
+$(eval $(call KernelPackage,hwmon-pc87360))
+
+
+define KernelPackage/hwmon-w83627hf
+ TITLE:=Winbond W83627HF monitoring support
+ KCONFIG:=CONFIG_SENSORS_W83627HF
+ FILES:=$(LINUX_DIR)/drivers/hwmon/w83627hf.ko
+ AUTOLOAD:=$(call AutoLoad,50,w83627hf)
+$(call AddDepends/hwmon,@TARGET_rdc||TARGET_x86 +kmod-hwmon-vid)
+endef
+
+define KernelPacakge/hwmon-w83627hf/description
+ Kernel module for the Winbond W83627HF chips.
+endef
+
+$(eval $(call KernelPackage,hwmon-w83627hf))
diff --git a/package/kernel/modules/i2c.mk b/package/kernel/modules/i2c.mk
new file mode 100644
index 000000000..d0ebfccfc
--- /dev/null
+++ b/package/kernel/modules/i2c.mk
@@ -0,0 +1,274 @@
+#
+# Copyright (C) 2006-2009 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+I2C_MENU:=I2C support
+
+ModuleConfVar=$(word 1,$(subst :,$(space),$(1)))
+ModuleFullPath=$(if $(findstring y,$($(call ModuleConfVar,$(1)))),,$(LINUX_DIR)/$(word 2,$(subst :,$(space),$(1))).ko)
+ModuleKconfig=$(foreach mod,$(1),$(call ModuleConfVar,$(mod)))
+ModuleFiles=$(foreach mod,$(1),$(call ModuleFullPath,$(mod)))
+ModuleAuto=$(call AutoLoad,$(1),$(foreach mod,$(2),$(basename $(notdir $(call ModuleFullPath,$(mod))))),$(3))
+
+define i2c_defaults
+ SUBMENU:=$(I2C_MENU)
+ KCONFIG:=$(call ModuleKconfig,$(1))
+ FILES:=$(call ModuleFiles,$(1))
+ AUTOLOAD:=$(call ModuleAuto,$(2),$(1),$(3))
+endef
+
+I2C_CORE_MODULES:= \
+ CONFIG_I2C:drivers/i2c/i2c-core \
+ CONFIG_I2C_CHARDEV:drivers/i2c/i2c-dev
+
+define KernelPackage/i2c-core
+ $(call i2c_defaults,$(I2C_CORE_MODULES),51)
+ TITLE:=I2C support
+ DEPENDS:=@!TARGET_etrax
+endef
+
+define KernelPackage/i2c-core/description
+ Kernel modules for I2C support
+endef
+
+$(eval $(call KernelPackage,i2c-core))
+
+
+I2C_ALGOBIT_MODULES:= \
+ CONFIG_I2C_ALGOBIT:drivers/i2c/algos/i2c-algo-bit
+
+define KernelPackage/i2c-algo-bit
+ $(call i2c_defaults,$(I2C_ALGOBIT_MODULES),55)
+ TITLE:=I2C bit-banging interfaces
+ DEPENDS:=kmod-i2c-core
+endef
+
+define KernelPackage/i2c-algo-bit/description
+ Kernel modules for I2C bit-banging interfaces.
+endef
+
+$(eval $(call KernelPackage,i2c-algo-bit))
+
+
+I2C_ALGOPCA_MODULES:= \
+ CONFIG_I2C_ALGOPCA:drivers/i2c/algos/i2c-algo-pca
+
+define KernelPackage/i2c-algo-pca
+ $(call i2c_defaults,$(I2C_ALGOPCA_MODULES),55)
+ TITLE:=I2C PCA 9564 interfaces
+ DEPENDS:=kmod-i2c-core
+endef
+
+define KernelPackage/i2c-algo-pca/description
+ Kernel modules for I2C PCA 9564 interfaces.
+endef
+
+$(eval $(call KernelPackage,i2c-algo-pca))
+
+
+I2C_ALGOPCF_MODULES:= \
+ CONFIG_I2C_ALGOPCF:drivers/i2c/algos/i2c-algo-pcf
+
+define KernelPackage/i2c-algo-pcf
+ $(call i2c_defaults,$(I2C_ALGOPCF_MODULES),55)
+ TITLE:=I2C PCF 8584 interfaces
+ DEPENDS:=kmod-i2c-core
+endef
+
+define KernelPackage/i2c-algo-pcf/description
+ Kernel modules for I2C PCF 8584 interfaces
+endef
+
+$(eval $(call KernelPackage,i2c-algo-pcf))
+
+
+I2C_GPIO_MODULES:= \
+ CONFIG_I2C_GPIO:drivers/i2c/busses/i2c-gpio
+
+define KernelPackage/i2c-gpio
+ $(call i2c_defaults,$(I2C_GPIO_MODULES),59)
+ TITLE:=GPIO-based bitbanging I2C
+ DEPENDS:=@GPIO_SUPPORT +kmod-i2c-algo-bit
+endef
+
+define KernelPackage/i2c-gpio/description
+ Kernel modules for a very simple bitbanging I2C driver utilizing the
+ arch-neutral GPIO API to control the SCL and SDA lines.
+endef
+
+$(eval $(call KernelPackage,i2c-gpio))
+
+
+OF_I2C_MODULES:=\
+ CONFIG_OF_I2C:drivers/of/of_i2c
+
+define KernelPackage/of-i2c
+ $(call i2c_defaults,$(OF_I2C_MODULES),58)
+ TITLE:=OpenFirmware I2C accessors
+ DEPENDS:=@TARGET_ppc40x||TARGET_ppc4xx||TARGET_mpc52xx||TARGET_mpc83xx||TARGET_mpc85xx \
+ kmod-i2c-core
+endef
+
+define KernelPackage/of-i2c/description
+ Kernel module for OpenFirmware I2C accessors.
+endef
+
+$(eval $(call KernelPackage,of-i2c))
+
+I2C_MPC_MODULES:=\
+ CONFIG_I2C_MPC:drivers/i2c/busses/i2c-mpc
+
+define KernelPackage/i2c-mpc
+ $(call i2c_defaults,$(I2C_MPC_MODULES),59)
+ TITLE:=MPC I2C accessors
+ DEPENDS:=@TARGET_mpc52xx||TARGET_mpc83xx||TARGET_mpc85xx \
+ +kmod-i2c-core +kmod-of-i2c
+endef
+
+define KernelPackage/i2c-mpc/description
+ Kernel module for Freescale MPC52xx MPC83xx MPC85xx I2C accessors.
+endef
+
+$(eval $(call KernelPackage,i2c-mpc))
+
+I2C_IBM_IIC_MODULES:=\
+ CONFIG_I2C_IBM_IIC:drivers/i2c/busses/i2c-ibm_iic
+
+define KernelPackage/i2c-ibm-iic
+ $(call i2c_defaults,$(OF_I2C_MODULES),59)
+ TITLE:=IBM PPC 4xx on-chip I2C interface support
+ DEPENDS:=@TARGET_ppc40x||TARGET_ppc4xx +kmod-i2c-core +kmod-of-i2c
+endef
+
+define KernelPackage/i2c-ibm-iic/description
+ Kernel module for IIC peripheral found on embedded IBM PPC4xx based systems.
+endef
+
+$(eval $(call KernelPackage,i2c-ibm-iic))
+
+I2C_MV64XXX_MODULES:=\
+ CONFIG_I2C_MV64XXX:drivers/i2c/busses/i2c-mv64xxx
+
+define KernelPackage/i2c-mv64xxx
+ $(call i2c_defaults,$(I2C_MV64XXX_MODULES),59)
+ TITLE:=Orion Platform I2C interface support
+ DEPENDS:=@TARGET_kirkwood||TARGET_orion +kmod-i2c-core
+endef
+
+define KernelPackage/i2c-mv64xxx/description
+ Kernel module for I2C interface on the Kirkwood and Orion
+ family processors.
+endef
+
+$(eval $(call KernelPackage,i2c-mv64xxx))
+
+
+I2C_TINY_USB_MODULES:= \
+ CONFIG_I2C_TINY_USB:drivers/i2c/busses/i2c-tiny-usb
+
+define KernelPackage/i2c-tiny-usb
+ $(call i2c_defaults,$(I2C_TINY_USB_MODULES),59)
+ TITLE:=I2C Tiny USB adaptor
+ DEPENDS:=@USB_SUPPORT kmod-i2c-core
+endef
+
+define KernelPackage/i2c-tiny-usb/description
+ Kernel module for the I2C Tiny USB adaptor developed
+ by Till Harbaum (http://www.harbaum.org/till/i2c_tiny_usb).
+endef
+
+$(eval $(call KernelPackage,i2c-tiny-usb))
+
+I2C_MUX_MODULES:= \
+ CONFIG_I2C_MUX:drivers/i2c/i2c-mux
+
+define KernelPackage/i2c-mux
+ $(call i2c_defaults,$(I2C_MUX_MODULES),51)
+ TITLE:=I2C bus multiplexing support
+ DEPENDS:=kmod-i2c-core
+endef
+
+define KernelPackage/i2c-mux/description
+ Kernel modules for I2C bus multiplexing support.
+endef
+
+$(eval $(call KernelPackage,i2c-mux))
+
+I2C_MUX_GPIO_MODULES:= \
+ CONFIG_I2C_MUX_GPIO:drivers/i2c/muxes/gpio-i2cmux
+
+define KernelPackage/i2c-mux-gpio
+ $(call i2c_defaults,$(I2C_MUX_GPIO_MODULES),51)
+ TITLE:=GPIO-based I2C mux/switches
+ DEPENDS:=kmod-i2c-mux
+endef
+
+define KernelPackage/i2c-mux-gpio/description
+ Kernel modules for GENERIC_GPIO I2C bus mux/switching devices.
+endef
+
+$(eval $(call KernelPackage,i2c-mux-gpio))
+
+I2C_MUX_PCA954x_MODULES:= \
+ CONFIG_I2C_MUX_PCA954x:drivers/i2c/muxes/pca954x
+
+define KernelPackage/i2c-mux-pca954x
+ $(call i2c_defaults,$(I2C_MUX_PCA954x_MODULES),51)
+ TITLE:=Philips PCA954x I2C mux/switches
+ DEPENDS:=kmod-i2c-mux
+endef
+
+define KernelPackage/i2c-mux-pca954x/description
+ Kernel modules for PCA954x I2C bus mux/switching devices.
+endef
+
+$(eval $(call KernelPackage,i2c-mux-pca954x))
+## Support for pca954x seems to be in kernel since 2.6.36
+
+I2C_MUX_PCA9541_MODULES:= \
+ CONFIG_I2C_MUX_PCA9541:drivers/i2c/muxes/pca9541
+
+define KernelPackage/i2c-mux-pca9541
+ $(call i2c_defaults,$(I2C_MUX_PCA9541_MODULES),51)
+ TITLE:=Philips PCA9541 I2C mux/switches
+ DEPENDS:=kmod-i2c-mux
+endef
+
+define KernelPackage/i2c-mux-pca9541/description
+ Kernel modules for PCA9541 I2C bus mux/switching devices.
+endef
+
+$(eval $(call KernelPackage,i2c-mux-pca9541))
+
+GPIO_PCA953X_MODULES:= \
+ CONFIG_GPIO_PCA953X:drivers/gpio/gpio-pca953x
+
+define KernelPackage/pca953x
+ $(call i2c_defaults,$(GPIO_PCA953X_MODULES),51)
+ TITLE:=Philips PCA953x I2C GPIO extenders
+ DEPENDS:=kmod-i2c-core
+endef
+
+define KernelPackage/pca953x/description
+ Kernel modules for PCA953x I2C GPIO extenders.
+endef
+
+$(eval $(call KernelPackage,pca953x))
+
+GPIO_PCF857X_MODULES:= \
+ CONFIG_GPIO_PCF857X:drivers/gpio/gpio-pcf857x
+
+define KernelPackage/pcf857x
+ $(call i2c_defaults,$(GPIO_PCF857X_MODULES),51)
+ TITLE:=Philips PCF857x I2C GPIO extenders
+ DEPENDS:=kmod-i2c-core
+endef
+
+define KernelPackage/pcf857x/description
+ Kernel modules for PCF857x I2C GPIO extenders.
+endef
+
+$(eval $(call KernelPackage,pcf857x))
diff --git a/package/kernel/modules/leds.mk b/package/kernel/modules/leds.mk
new file mode 100644
index 000000000..b2970c609
--- /dev/null
+++ b/package/kernel/modules/leds.mk
@@ -0,0 +1,152 @@
+#
+# Copyright (C) 2006-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+LEDS_MENU:=LED modules
+
+
+define KernelPackage/leds-gpio
+ SUBMENU:=$(LEDS_MENU)
+ TITLE:=GPIO LED support
+ DEPENDS:= @GPIO_SUPPORT
+ KCONFIG:=CONFIG_LEDS_GPIO
+ FILES:=$(LINUX_DIR)/drivers/leds/leds-gpio.ko
+ AUTOLOAD:=$(call AutoLoad,60,leds-gpio)
+endef
+
+define KernelPackage/leds-gpio/description
+ Kernel module for LEDs on GPIO lines
+endef
+
+$(eval $(call KernelPackage,leds-gpio))
+
+
+define KernelPackage/ledtrig-heartbeat
+ SUBMENU:=$(LEDS_MENU)
+ TITLE:=LED Heartbeat Trigger
+ KCONFIG:=CONFIG_LEDS_TRIGGER_HEARTBEAT
+ FILES:=$(LINUX_DIR)/drivers/leds/ledtrig-heartbeat.ko
+ AUTOLOAD:=$(call AutoLoad,50,ledtrig-heartbeat)
+endef
+
+define KernelPackage/ledtrig-gpio/description
+ Kernel module that allows LEDs to blink like heart beat
+endef
+
+$(eval $(call KernelPackage,ledtrig-heartbeat))
+
+
+define KernelPackage/ledtrig-gpio
+ SUBMENU:=$(LEDS_MENU)
+ TITLE:=LED GPIO Trigger
+ KCONFIG:=CONFIG_LEDS_TRIGGER_GPIO
+ FILES:=$(LINUX_DIR)/drivers/leds/ledtrig-gpio.ko
+ AUTOLOAD:=$(call AutoLoad,50,ledtrig-gpio)
+endef
+
+define KernelPackage/ledtrig-gpio/description
+ Kernel module that allows LEDs to be controlled by gpio events.
+endef
+
+$(eval $(call KernelPackage,ledtrig-gpio))
+
+
+define KernelPackage/ledtrig-morse
+ SUBMENU:=$(LEDS_MENU)
+ TITLE:=LED Morse Trigger
+ KCONFIG:=CONFIG_LEDS_TRIGGER_MORSE
+ FILES:=$(LINUX_DIR)/drivers/leds/ledtrig-morse.ko
+ AUTOLOAD:=$(call AutoLoad,50,ledtrig-morse)
+endef
+
+define KernelPackage/ledtrig-morse/description
+ Kernel module to show morse coded messages on LEDs.
+endef
+
+$(eval $(call KernelPackage,ledtrig-morse))
+
+
+define KernelPackage/ledtrig-netdev
+ SUBMENU:=$(LEDS_MENU)
+ TITLE:=LED NETDEV Trigger
+ KCONFIG:=CONFIG_LEDS_TRIGGER_NETDEV
+ FILES:=$(LINUX_DIR)/drivers/leds/ledtrig-netdev.ko
+ AUTOLOAD:=$(call AutoLoad,50,ledtrig-netdev)
+endef
+
+define KernelPackage/ledtrig-netdev/description
+ Kernel module to drive LEDs based on network activity.
+endef
+
+$(eval $(call KernelPackage,ledtrig-netdev))
+
+
+define KernelPackage/ledtrig-netfilter
+ SUBMENU:=$(LEDS_MENU)
+ TITLE:=LED NetFilter Trigger
+ DEPENDS:=kmod-ipt-core
+ KCONFIG:=CONFIG_NETFILTER_XT_TARGET_LED
+ FILES:=$(LINUX_DIR)/net/netfilter/xt_LED.ko
+ AUTOLOAD:=$(call AutoLoad,50,xt_LED)
+endef
+
+define KernelPackage/ledtrig-netfilter/description
+ Kernel module to flash LED when a particular packets passing through your machine.
+
+ For example to create an LED trigger for incoming SSH traffic:
+ iptables -A INPUT -p tcp --dport 22 -j LED --led-trigger-id ssh --led-delay 1000
+ Then attach the new trigger to an LED on your system:
+ echo netfilter-ssh > /sys/class/leds/<ledname>/trigger
+endef
+
+$(eval $(call KernelPackage,ledtrig-netfilter))
+
+
+define KernelPackage/ledtrig-usbdev
+ SUBMENU:=$(LEDS_MENU)
+ TITLE:=LED USB device Trigger
+ DEPENDS:=@USB_SUPPORT +kmod-usb-core
+ KCONFIG:=CONFIG_LEDS_TRIGGER_USBDEV
+ FILES:=$(LINUX_DIR)/drivers/leds/ledtrig-usbdev.ko
+ AUTOLOAD:=$(call AutoLoad,50,ledtrig-usbdev)
+endef
+
+define KernelPackage/ledtrig-usbdev/description
+ Kernel module to drive LEDs based on USB device presence/activity.
+endef
+
+$(eval $(call KernelPackage,ledtrig-usbdev))
+
+
+define KernelPackage/ledtrig-default-on
+ SUBMENU:=$(LEDS_MENU)
+ TITLE:=LED Default ON Trigger
+ KCONFIG:=CONFIG_LEDS_TRIGGER_DEFAULT_ON
+ FILES:=$(LINUX_DIR)/drivers/leds/ledtrig-default-on.ko
+ AUTOLOAD:=$(call AutoLoad,50,ledtrig-default-on)
+endef
+
+define KernelPackage/ledtrig-default-on/description
+ Kernel module that allows LEDs to be initialised in the ON state.
+endef
+
+$(eval $(call KernelPackage,ledtrig-default-on))
+
+
+define KernelPackage/ledtrig-timer
+ SUBMENU:=$(LEDS_MENU)
+ TITLE:=LED Timer Trigger
+ KCONFIG:=CONFIG_LEDS_TRIGGER_TIMER
+ FILES:=$(LINUX_DIR)/drivers/leds/ledtrig-timer.ko
+ AUTOLOAD:=$(call AutoLoad,50,ledtrig-timer)
+endef
+
+define KernelPackage/ledtrig-timer/description
+ Kernel module that allows LEDs to be controlled by a programmable timer
+ via sysfs.
+endef
+
+$(eval $(call KernelPackage,ledtrig-timer))
diff --git a/package/kernel/modules/lib.mk b/package/kernel/modules/lib.mk
new file mode 100644
index 000000000..2875fb237
--- /dev/null
+++ b/package/kernel/modules/lib.mk
@@ -0,0 +1,167 @@
+#
+# Copyright (C) 2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+LIB_MENU:=Libraries
+
+define KernelPackage/lib-crc-ccitt
+ SUBMENU:=$(LIB_MENU)
+ TITLE:=CRC-CCITT support
+ KCONFIG:=CONFIG_CRC_CCITT
+ FILES:=$(LINUX_DIR)/lib/crc-ccitt.ko
+ AUTOLOAD:=$(call AutoLoad,20,crc-ccitt)
+endef
+
+define KernelPackage/lib-crc-ccitt/description
+ Kernel module for CRC-CCITT support
+endef
+
+$(eval $(call KernelPackage,lib-crc-ccitt))
+
+
+define KernelPackage/lib-crc-itu-t
+ SUBMENU:=$(LIB_MENU)
+ TITLE:=CRC ITU-T V.41 support
+ KCONFIG:=CONFIG_CRC_ITU_T
+ FILES:=$(LINUX_DIR)/lib/crc-itu-t.ko
+ AUTOLOAD:=$(call AutoLoad,20,crc-itu-t)
+endef
+
+define KernelPackage/lib-crc-itu-t/description
+ Kernel module for CRC ITU-T V.41 support
+endef
+
+$(eval $(call KernelPackage,lib-crc-itu-t))
+
+
+define KernelPackage/lib-crc7
+ SUBMENU:=$(LIB_MENU)
+ TITLE:=CRC7 support
+ KCONFIG:=CONFIG_CRC7
+ FILES:=$(LINUX_DIR)/lib/crc7.ko
+ AUTOLOAD:=$(call AutoLoad,20,crc7)
+endef
+
+define KernelPackage/lib-crc7/description
+ Kernel module for CRC7 support
+endef
+
+$(eval $(call KernelPackage,lib-crc7))
+
+
+define KernelPackage/lib-crc8
+ SUBMENU:=$(LIB_MENU)
+ TITLE:=CRC8 support
+ DEPENDS:= @!LINUX_2_6_39
+ KCONFIG:=CONFIG_CRC8
+ FILES:=$(LINUX_DIR)/lib/crc8.ko
+ AUTOLOAD:=$(call AutoLoad,20,crc8)
+endef
+
+define KernelPackage/lib-crc8/description
+ Kernel module for CRC8 support
+endef
+
+$(eval $(call KernelPackage,lib-crc8))
+
+
+define KernelPackage/lib-crc16
+ SUBMENU:=$(LIB_MENU)
+ TITLE:=CRC16 support
+ KCONFIG:=CONFIG_CRC16
+ FILES:=$(LINUX_DIR)/lib/crc16.ko
+ AUTOLOAD:=$(call AutoLoad,20,crc16,1)
+endef
+
+define KernelPackage/lib-crc16/description
+ Kernel module for CRC16 support
+endef
+
+$(eval $(call KernelPackage,lib-crc16))
+
+
+define KernelPackage/lib-crc32c
+ SUBMENU:=$(LIB_MENU)
+ TITLE:=CRC32 support
+ KCONFIG:=CONFIG_LIBCRC32C
+ DEPENDS:=+kmod-crypto-crc32c
+ FILES:=$(LINUX_DIR)/lib/libcrc32c.ko
+ AUTOLOAD:=$(call AutoLoad,20,libcrc32c,1)
+endef
+
+define KernelPackage/lib-crc32c/description
+ Kernel module for CRC32 support
+endef
+
+$(eval $(call KernelPackage,lib-crc32c))
+
+
+define KernelPackage/lib-lzo
+ SUBMENU:=$(LIB_MENU)
+ TITLE:=LZO support
+ KCONFIG:= \
+ CONFIG_LZO_COMPRESS \
+ CONFIG_LZO_DECOMPRESS
+ FILES:= \
+ $(LINUX_DIR)/lib/lzo/lzo_compress.ko \
+ $(LINUX_DIR)/lib/lzo/lzo_decompress.ko
+ AUTOLOAD:=$(call AutoLoad,20, lzo_compress lzo_decompress,1)
+endef
+
+define KernelPackage/lib-lzo/description
+ Kernel module for LZO compression/decompression support
+endef
+
+$(eval $(call KernelPackage,lib-lzo))
+
+
+define KernelPackage/lib-textsearch
+SUBMENU:=$(LIB_MENU)
+ TITLE:=Textsearch support
+ KCONFIG:= \
+ CONFIG_TEXTSEARCH=y \
+ CONFIG_TEXTSEARCH_KMP \
+ CONFIG_TEXTSEARCH_BM \
+ CONFIG_TEXTSEARCH_FSM
+ FILES:= \
+ $(LINUX_DIR)/lib/ts_kmp.ko \
+ $(LINUX_DIR)/lib/ts_bm.ko \
+ $(LINUX_DIR)/lib/ts_fsm.ko
+ AUTOLOAD:=$(call AutoLoad,20,ts_kmp ts_bm ts_fsm)
+endef
+
+$(eval $(call KernelPackage,lib-textsearch))
+
+
+define KernelPackage/lib-zlib
+ SUBMENU:=$(LIB_MENU)
+ TITLE:=Zlib support
+ KCONFIG:= \
+ CONFIG_ZLIB_DEFLATE \
+ CONFIG_ZLIB_INFLATE
+ FILES:= \
+ $(LINUX_DIR)/lib/zlib_deflate/zlib_deflate.ko \
+ $(LINUX_DIR)/lib/zlib_inflate/zlib_inflate.ko
+ AUTOLOAD:=$(call AutoLoad,08,zlib_deflate zlib_inflate,1)
+endef
+
+$(eval $(call KernelPackage,lib-zlib))
+
+
+define KernelPackage/lib-cordic
+ SUBMENU:=$(LIB_MENU)
+ TITLE:=Cordic function support
+ DEPENDS:= @!LINUX_2_6_39
+ KCONFIG:=CONFIG_CORDIC
+ FILES:=$(LINUX_DIR)/lib/cordic.ko
+ AUTOLOAD:=$(call AutoLoad,20,cordic)
+endef
+
+define KernelPackage/lib-cordic/description
+ Kernel module for Cordic function support
+endef
+
+$(eval $(call KernelPackage,lib-cordic))
diff --git a/package/kernel/modules/netdevices.mk b/package/kernel/modules/netdevices.mk
new file mode 100644
index 000000000..180be301c
--- /dev/null
+++ b/package/kernel/modules/netdevices.mk
@@ -0,0 +1,665 @@
+#
+# Copyright (C) 2006-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+NETWORK_DEVICES_MENU:=Network Devices
+
+define KernelPackage/sis190
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=SiS 190 Fast/Gigabit Ethernet support
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_SIS190
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/sis/sis190.ko
+ AUTOLOAD:=$(call AutoLoad,50,sis190)
+endef
+
+$(eval $(call KernelPackage,sis190))
+
+define KernelPackage/skge
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=SysKonnect Yukon support
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_SKGE \
+ CONFIG_SKGE_DEBUG=n \
+ CONFIG_SKGE_GENESIS=n
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/marvell/skge.ko
+ AUTOLOAD:=$(call AutoLoad,50,skge)
+endef
+
+$(eval $(call KernelPackage,skge))
+
+define KernelPackage/atl2
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=Atheros L2 Fast Ethernet support
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_ATL2
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/atheros/atlx/atl2.ko
+ AUTOLOAD:=$(call AutoLoad,50,atl2)
+endef
+
+$(eval $(call KernelPackage,atl2))
+
+define KernelPackage/atl1
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=Atheros L1 Gigabit Ethernet support
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_ATL1
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/atheros/atlx/atl1.ko
+ AUTOLOAD:=$(call AutoLoad,50,atl1)
+endef
+
+$(eval $(call KernelPackage,atl1))
+
+define KernelPackage/atl1c
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=Atheros L1C
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_ATL1C
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/atheros/atl1c/atl1c.ko
+ AUTOLOAD:=$(call AutoLoad,50,atl1c)
+endef
+
+$(eval $(call KernelPackage,atl1c))
+
+define KernelPackage/atl1e
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=Atheros L1E
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_ATL1E
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/atheros/atl1e/atl1e.ko
+ AUTOLOAD:=$(call AutoLoad,50,atl1e)
+endef
+
+$(eval $(call KernelPackage,atl1e))
+
+define KernelPackage/libphy
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=PHY library
+ KCONFIG:=CONFIG_PHYLIB
+ FILES:=$(LINUX_DIR)/drivers/net/phy/libphy.ko
+ AUTOLOAD:=$(call AutoLoad,40,libphy)
+endef
+
+define KernelPackage/libphy/description
+ PHY library
+endef
+
+$(eval $(call KernelPackage,libphy))
+
+define KernelPackage/et131x
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=Agere ET131x Gigabit Ethernet driver
+ URL:=http://sourceforge.net/projects/et131x
+ FILES:=$(LINUX_DIR)/drivers/staging/et131x/et131x.$(LINUX_KMOD_SUFFIX)
+ KCONFIG:= \
+ CONFIG_ET131X \
+ CONFIG_ET131X_DEBUG=n
+ DEPENDS:=@PCI_SUPPORT
+ AUTOLOAD:=$(call AutoLoad,70,et131x)
+endef
+
+define KernelPackage/et131x/description
+ This package contains the et131x kernel module.
+endef
+
+$(eval $(call KernelPackage,et131x))
+
+define KernelPackage/swconfig
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=switch configuration API
+ DEPENDS:=+kmod-libphy
+ KCONFIG:=CONFIG_SWCONFIG
+ FILES:=$(LINUX_DIR)/drivers/net/phy/swconfig.ko
+ AUTOLOAD:=$(call AutoLoad,41,swconfig)
+endef
+
+define KernelPackage/swconfig/description
+ Switch configuration API module
+endef
+
+$(eval $(call KernelPackage,swconfig))
+
+define KernelPackage/switch-ip17xx
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=IC+ IP17XX switch support
+ DEPENDS:=+kmod-swconfig
+ KCONFIG:=CONFIG_IP17XX_PHY
+ FILES:=$(LINUX_DIR)/drivers/net/phy/ip17xx.ko
+ AUTOLOAD:=$(call AutoLoad,42,ip17xx)
+endef
+
+define KernelPackage/switch-ip17xx/description
+ IC+ IP175C/IP178C switch support
+endef
+
+$(eval $(call KernelPackage,switch-ip17xx))
+
+define KernelPackage/switch-rtl8366-smi
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=Realtek RTL8366 SMI switch interface support
+ DEPENDS:=@GPIO_SUPPORT +kmod-swconfig
+ KCONFIG:=CONFIG_RTL8366_SMI
+ FILES:=$(LINUX_DIR)/drivers/net/phy/rtl8366_smi.ko
+ AUTOLOAD:=$(call AutoLoad,42,rtl8366_smi)
+endef
+
+define KernelPackage/switch-rtl8366_smi/description
+ Realtek RTL8366 series SMI switch interface support
+endef
+
+$(eval $(call KernelPackage,switch-rtl8366-smi))
+
+define KernelPackage/switch-rtl8366rb
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=Realtek RTL8366RB switch support
+ DEPENDS:=+kmod-switch-rtl8366-smi
+ KCONFIG:=CONFIG_RTL8366RB_PHY
+ FILES:=$(LINUX_DIR)/drivers/net/phy/rtl8366rb.ko
+ AUTOLOAD:=$(call AutoLoad,43,rtl8366rb)
+endef
+
+define KernelPackage/switch-rtl8366rb/description
+ Realtek RTL8366RB switch support
+endef
+
+$(eval $(call KernelPackage,switch-rtl8366rb))
+
+define KernelPackage/switch-rtl8366s
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=Realtek RTL8366S switch support
+ DEPENDS:=+kmod-switch-rtl8366-smi
+ KCONFIG:=CONFIG_RTL8366S_PHY
+ FILES:=$(LINUX_DIR)/drivers/net/phy/rtl8366s.ko
+ AUTOLOAD:=$(call AutoLoad,43,rtl8366s)
+endef
+
+define KernelPackage/switch-rtl8366s/description
+ Realtek RTL8366S switch support
+endef
+
+$(eval $(call KernelPackage,switch-rtl8366s))
+
+define KernelPackage/natsemi
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=National Semiconductor DP8381x series
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_NATSEMI
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/natsemi/natsemi.ko
+ AUTOLOAD:=$(call AutoLoad,20,natsemi)
+endef
+
+define KernelPackage/natsemi/description
+ Kernel modules for National Semiconductor DP8381x series PCI Ethernet
+ adapters.
+endef
+
+$(eval $(call KernelPackage,natsemi))
+
+
+define KernelPackage/r6040
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=RDC Fast-Ethernet support
+ DEPENDS:=@PCI_SUPPORT +kmod-libphy
+ KCONFIG:=CONFIG_R6040 \
+ CONFIG_R6040_NAPI=y
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/rdc/r6040.ko
+ AUTOLOAD:=$(call AutoLoad,99,r6040)
+endef
+
+define KernelPackage/r6040/description
+ Kernel modules for RDC Fast-Ethernet adapters.
+endef
+
+$(eval $(call KernelPackage,r6040))
+
+
+define KernelPackage/sis900
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=SiS 900 Ethernet support
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_SIS900
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/sis/sis900.ko
+ AUTOLOAD:=$(call AutoLoad,50,sis900)
+endef
+
+define KernelPackage/sis900/description
+ Kernel modules for Sis 900 Ethernet adapters.
+endef
+
+$(eval $(call KernelPackage,sis900))
+
+
+define KernelPackage/sky2
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=SysKonnect Yukon2 support
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_SKY2
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/marvell/sky2.ko
+ AUTOLOAD:=$(call AutoLoad,50,sky2)
+endef
+
+define KernelPackage/sky2/description
+ This driver supports Gigabit Ethernet adapters based on the
+ Marvell Yukon 2 chipset:
+ Marvell 88E8021/88E8022/88E8035/88E8036/88E8038/88E8050/88E8052/
+ 88E8053/88E8055/88E8061/88E8062, SysKonnect SK-9E21D/SK-9S21
+
+ There is companion driver for the older Marvell Yukon and
+ Genesis based adapters: skge.
+endef
+
+$(eval $(call KernelPackage,sky2))
+
+
+define KernelPackage/via-rhine
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=Via Rhine ethernet support
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_VIA_RHINE \
+ CONFIG_VIA_RHINE_MMIO=y
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/via/via-rhine.ko
+ AUTOLOAD:=$(call AutoLoad,50,via-rhine)
+endef
+
+define KernelPackage/via-rhine/description
+ Kernel modules for Via Rhine Ethernet chipsets.
+endef
+
+$(eval $(call KernelPackage,via-rhine))
+
+
+define KernelPackage/via-velocity
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=VIA Velocity Gigabit Ethernet Adapter kernel support
+ DEPENDS:=@TARGET_ixp4xx||TARGET_mpc83xx||PCI_SUPPORT +kmod-lib-crc-ccitt
+ KCONFIG:=CONFIG_VIA_VELOCITY
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/via/via-velocity.ko
+ AUTOLOAD:=$(call AutoLoad,50,via-velocity)
+endef
+
+define KernelPackage/via-velocity/description
+ Kernel modules for VIA Velocity Gigabit Ethernet chipsets.
+endef
+
+$(eval $(call KernelPackage,via-velocity))
+
+
+define KernelPackage/8139too
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=RealTek RTL-8139 PCI Fast Ethernet Adapter kernel support
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_8139TOO \
+ CONFIG_8139TOO_PIO=y \
+ CONFIG_8139TOO_TUNE_TWISTER=n \
+ CONFIG_8139TOO_8129=n \
+ CONFIG_8139_OLD_RX_RESET=n
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/realtek/8139too.ko
+ AUTOLOAD:=$(call AutoLoad,50,8139too)
+endef
+
+define KernelPackage/8139too/description
+ Kernel modules for RealTek RTL-8139 PCI Fast Ethernet adapters.
+endef
+
+$(eval $(call KernelPackage,8139too))
+
+
+define KernelPackage/8139cp
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=RealTek RTL-8139C+ PCI Fast Ethernet Adapter kernel support
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_8139CP
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/realtek/8139cp.ko
+ AUTOLOAD:=$(call AutoLoad,50,8139cp)
+endef
+
+define KernelPackage/8139cp/description
+ Kernel module for RealTek RTL-8139C+ PCI Fast Ethernet adapters.
+endef
+
+$(eval $(call KernelPackage,8139cp))
+
+
+define KernelPackage/r8169
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=RealTek RTL-8169 PCI Gigabit Ethernet Adapter kernel support
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_R8169 \
+ CONFIG_R8169_NAPI=y \
+ CONFIG_R8169_VLAN=n
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/realtek/r8169.ko
+ AUTOLOAD:=$(call AutoLoad,50,r8169)
+endef
+
+define KernelPackage/r8169/description
+ Kernel modules for RealTek RTL-8169 PCI Gigabit Ethernet adapters.
+endef
+
+$(eval $(call KernelPackage,r8169))
+
+
+define KernelPackage/ne2k-pci
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=ne2k-pci Ethernet Adapter kernel support
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_NE2K_PCI
+ FILES:= \
+ $(LINUX_DIR)/drivers/net/ethernet/8390/ne2k-pci.ko \
+ $(LINUX_DIR)/drivers/net/ethernet/8390/8390.ko
+ AUTOLOAD:=$(call AutoLoad,50,8390 ne2k-pci)
+endef
+
+define KernelPackage/ne2k-pci/description
+ Kernel modules for NE2000 PCI Ethernet Adapter kernel.
+endef
+
+$(eval $(call KernelPackage,ne2k-pci))
+
+
+define KernelPackage/e100
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=Intel(R) PRO/100+ cards kernel support
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_E100
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/intel/e100.ko
+ AUTOLOAD:=$(call AutoLoad,50,e100)
+endef
+
+define KernelPackage/e100/description
+ Kernel modules for Intel(R) PRO/100+ Ethernet adapters.
+endef
+
+define KernelPackage/e100/install
+ $(INSTALL_DIR) $(1)/lib/firmware/e100
+ $(foreach file,d101m_ucode.bin d101s_ucode.bin d102e_ucode.bin, \
+ $(TARGET_CROSS)objcopy -Iihex -Obinary $(LINUX_DIR)/firmware/e100/$(file).ihex $(1)/lib/firmware/e100/$(file); \
+ )
+endef
+
+$(eval $(call KernelPackage,e100))
+
+
+define KernelPackage/e1000
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=Intel(R) PRO/1000 PCI cards kernel support
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_E1000 \
+ CONFIG_E1000_DISABLE_PACKET_SPLIT=n \
+ CONFIG_E1000_NAPI=y
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/intel/e1000/e1000.ko
+ AUTOLOAD:=$(call AutoLoad,35,e1000)
+endef
+
+define KernelPackage/e1000/description
+ Kernel modules for Intel(R) PRO/1000 PCI Ethernet adapters.
+endef
+
+$(eval $(call KernelPackage,e1000))
+
+
+define KernelPackage/e1000e
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=Intel(R) PRO/1000 PCIe cards kernel support
+ DEPENDS:=@PCIE_SUPPORT
+ KCONFIG:=CONFIG_E1000E
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/intel/e1000e/e1000e.ko
+ AUTOLOAD:=$(call AutoLoad,50,e1000e)
+endef
+
+define KernelPackage/e1000e/description
+ Kernel modules for Intel(R) PRO/1000 PCIe Ethernet adapters.
+endef
+
+$(eval $(call KernelPackage,e1000e))
+
+
+define KernelPackage/b44
+ TITLE:=Broadcom 44xx driver
+ KCONFIG:=CONFIG_B44
+ DEPENDS:=@PCI_SUPPORT +kmod-ssb
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/broadcom/b44.ko
+ AUTOLOAD:=$(call AutoLoad,50,b44)
+endef
+
+define KernelPackage/b44/description
+ Kernel modules for Broadcom 44xx Ethernet adapters.
+endef
+
+$(eval $(call KernelPackage,b44))
+
+
+define KernelPackage/3c59x
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=3Com 3c590/3c900 series (592/595/597) Vortex/Boomerang
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_VORTEX
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/3com/3c59x.ko
+ AUTOLOAD:=$(call AutoLoad,50,3c59x)
+endef
+
+define KernelPackage/3c59x/description
+ This option enables driver support for a large number of 10mbps and
+ 10/100mbps EISA, PCI and PCMCIA 3Com Ethernet adapters:
+ - "Vortex" (Fast EtherLink 3c590/3c592/3c595/3c597) EISA and PCI
+ - "Boomerang" (EtherLink XL 3c900 or 3c905) PCI
+ - "Cyclone" (3c540/3c900/3c905/3c980/3c575/3c656) PCI and Cardbus
+ - "Tornado" (3c905) PCI
+ - "Hurricane" (3c555/3cSOHO) PCI
+endef
+
+$(eval $(call KernelPackage,3c59x))
+
+
+define KernelPackage/pcnet32
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=AMD PCnet32 PCI support
+ DEPENDS:=@(PCI_SUPPORT||TARGET_malta)
+ KCONFIG:=CONFIG_PCNET32
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/amd/pcnet32.ko
+ AUTOLOAD:=$(call AutoLoad,50,pcnet32)
+endef
+
+define KernelPackage/pcnet32/description
+ Kernel modules for AMD PCnet32 Ethernet adapters.
+endef
+
+$(eval $(call KernelPackage,pcnet32))
+
+
+define KernelPackage/tg3
+ TITLE:=Broadcom Tigon3 Gigabit Ethernet
+ KCONFIG:=CONFIG_TIGON3
+ DEPENDS:=+!TARGET_brcm47xx:kmod-libphy @!TARGET_ubicom32
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/broadcom/tg3.ko
+ AUTOLOAD:=$(call AutoLoad,50,tg3)
+endef
+
+define KernelPackage/tg3/description
+ Kernel modules for Broadcom Tigon3 Gigabit Ethernet adapters.
+endef
+
+$(eval $(call KernelPackage,tg3))
+
+
+define KernelPackage/hfcpci
+ TITLE:=HFC PCI cards (single port) support for mISDN
+ KCONFIG:=CONFIG_MISDN_HFCPCI
+ DEPENDS:=+kmod-misdn
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ FILES:=$(LINUX_DIR)/drivers/isdn/hardware/mISDN/hfcpci.ko
+ AUTOLOAD:=$(call AutoLoad,31,hfcpci)
+endef
+
+define KernelPackage/hfcpci/description
+ Kernel modules for Cologne AG's HFC pci cards (single port)
+ using the mISDN V2 stack.
+endef
+
+$(eval $(call KernelPackage,hfcpci))
+
+
+define KernelPackage/hfcmulti
+ TITLE:=HFC multiport cards (HFC-4S/8S/E1) support for mISDN
+ KCONFIG:=CONFIG_MISDN_HFCMULTI
+ DEPENDS:=+kmod-misdn
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ FILES:=$(LINUX_DIR)/drivers/isdn/hardware/mISDN/hfcmulti.ko
+ AUTOLOAD:=$(call AutoLoad,31,hfcmulti)
+endef
+
+define KernelPackage/hfcmulti/description
+ Kernel modules for Cologne AG's HFC multiport cards (HFC-4S/8S/E1)
+ using the mISDN V2 stack.
+endef
+
+$(eval $(call KernelPackage,hfcmulti))
+
+
+define KernelPackage/gigaset
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=Siemens Gigaset support for isdn4linux
+ DEPENDS:=@USB_SUPPORT +kmod-isdn4linux +kmod-lib-crc-ccitt +kmod-usb-core
+ URL:=http://gigaset307x.sourceforge.net/
+ KCONFIG:= \
+ CONFIG_ISDN_DRV_GIGASET \
+ CONFIG_GIGASET_BASE \
+ CONFIG_GIGASET_M101 \
+ CONFIG_GIGASET_M105 \
+ CONFIG_GIGASET_UNDOCREQ=y \
+ CONFIG_GIGASET_I4L=y
+ FILES:= \
+ $(LINUX_DIR)/drivers/isdn/gigaset/gigaset.ko \
+ $(LINUX_DIR)/drivers/isdn/gigaset/bas_gigaset.ko \
+ $(LINUX_DIR)/drivers/isdn/gigaset/ser_gigaset.ko \
+ $(LINUX_DIR)/drivers/isdn/gigaset/usb_gigaset.ko
+ AUTOLOAD:=$(call AutoLoad,50,gigaset bas_gigaset ser_gigaset usb_gigaset)
+endef
+
+define KernelPackage/gigaset/description
+ This driver supports the Siemens Gigaset SX205/255 family of
+ ISDN DECT bases, including the predecessors Gigaset 3070/3075
+ and 4170/4175 and their T-Com versions Sinus 45isdn and Sinus
+ 721X.
+endef
+
+$(eval $(call KernelPackage,gigaset))
+
+
+define KernelPackage/macvlan
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=MAC-VLAN support
+ KCONFIG:=CONFIG_MACVLAN
+ FILES:=$(LINUX_DIR)/drivers/net/macvlan.ko
+ AUTOLOAD:=$(call AutoLoad,50,macvlan)
+endef
+
+define KernelPackage/macvlan/description
+ A kernel module which allows one to create virtual interfaces that
+ map packets to or from specific MAC addresses to a particular interface.
+endef
+
+$(eval $(call KernelPackage,macvlan))
+
+define KernelPackage/tulip
+ TITLE:=Tulip family network device support
+ DEPENDS:=@PCI_SUPPORT
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ KCONFIG:= \
+ CONFIG_NET_TULIP=y \
+ CONFIG_DE2104X \
+ CONFIG_DE2104X_DSL=0 \
+ CONFIG_TULIP \
+ CONFIG_TULIP_MWI=y \
+ CONFIG_TULIP_MMIO=y \
+ CONFIG_TULIP_NAPI=y \
+ CONFIG_TULIP_NAPI_HW_MITIGATION=y \
+ CONFIG_DE4X5 \
+ CONFIG_WINBOND_840 \
+ CONFIG_DM9102 \
+ CONFIG_ULI526X
+ FILES:= \
+ $(LINUX_DIR)/drivers/net/ethernet/dec/tulip/tulip.ko \
+ $(LINUX_DIR)/drivers/net/ethernet/dec/tulip/de2104x.ko \
+ $(LINUX_DIR)/drivers/net/ethernet/dec/tulip/de4x5.ko \
+ $(LINUX_DIR)/drivers/net/ethernet/dec/tulip/dmfe.ko \
+ $(LINUX_DIR)/drivers/net/ethernet/dec/tulip/uli526x.ko \
+ $(LINUX_DIR)/drivers/net/ethernet/dec/tulip/winbond-840.ko
+ AUTOLOAD:=$(call AutoLoad,50,tulip)
+endef
+
+define KernelPackage/tulip/description
+ Kernel modules for the Tulip family of network cards,
+ including DECchip Tulip, DIGITAL EtherWORKS, Winbond W89c840,
+ Davicom DM910x/DM980x and ULi M526x controller support.
+endef
+
+$(eval $(call KernelPackage,tulip))
+
+
+define KernelPackage/solos-pci
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=Solos ADSL2+ multiport modem
+ DEPENDS:=@PCI_SUPPORT +kmod-atm
+ KCONFIG:=CONFIG_ATM_SOLOS
+ FILES:=$(LINUX_DIR)/drivers/atm/solos-pci.ko
+ AUTOLOAD:=$(call AutoLoad,50,solos-pci)
+endef
+
+define KernelPackage/solos-pci/description
+ Kernel module for Traverse Technologies' Solos PCI cards
+ and Geos ADSL2+ x86 motherboard.
+endef
+
+$(eval $(call KernelPackage,solos-pci))
+
+define KernelPackage/dummy
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=Dummy network device
+ KCONFIG:=CONFIG_DUMMY
+ FILES:=$(LINUX_DIR)/drivers/net/dummy.ko
+ AUTOLOAD:=$(call AutoLoad,34,dummy)
+endef
+
+define KernelPackage/dummy/description
+ The dummy network device
+endef
+
+$(eval $(call KernelPackage,dummy))
+
+define KernelPackage/ifb
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=Intermediate Functional Block support
+ KCONFIG:= \
+ CONFIG_IFB \
+ CONFIG_NET_CLS=y
+ FILES:=$(LINUX_DIR)/drivers/net/ifb.ko
+ AUTOLOAD:=$(call AutoLoad,34,ifb)
+endef
+
+define KernelPackage/ifb/description
+ The Intermediate Functional Block
+endef
+
+$(eval $(call KernelPackage,ifb))
+
+define KernelPackage/dm9000
+ SUBMENU:=$(NETWORK_DEVICES_MENU)
+ TITLE:=Davicom 9000 Ethernet support
+ DEPENDS:=@PCI_SUPPORT
+ KCONFIG:=CONFIG_DM9000 \
+ CONFIG_DM9000_DEBUGLEVEL=4 \
+ CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+ FILES:=$(LINUX_DIR)/drivers/net/ethernet/davicom/dm9000.ko
+ AUTOLOAD:=$(call AutoLoad,34,dm9000)
+endef
+
+define KernelPackage/dm9000/description
+ Kernel driver for Davicom 9000 Ethernet adapters.
+endef
+
+$(eval $(call KernelPackage,dm9000))
diff --git a/package/kernel/modules/netfilter.mk b/package/kernel/modules/netfilter.mk
new file mode 100644
index 000000000..ff34664c2
--- /dev/null
+++ b/package/kernel/modules/netfilter.mk
@@ -0,0 +1,573 @@
+
+#
+# Copyright (C) 2006-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+NF_MENU:=Netfilter Extensions
+NF_KMOD:=1
+include $(INCLUDE_DIR)/netfilter.mk
+
+define KernelPackage/ipt-core
+ SUBMENU:=$(NF_MENU)
+ TITLE:=Netfilter core
+ KCONFIG:= \
+ CONFIG_NETFILTER=y \
+ CONFIG_NETFILTER_ADVANCED=y \
+ $(KCONFIG_IPT_CORE)
+ FILES:=$(foreach mod,$(IPT_CORE-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,40,$(notdir $(IPT_CORE-m)))
+endef
+
+define KernelPackage/ipt-core/description
+ Netfilter core kernel modules
+ Includes:
+ - comment
+ - limit
+ - LOG
+ - mac
+ - multiport
+ - REJECT
+ - TCPMSS
+endef
+
+$(eval $(call KernelPackage,ipt-core))
+
+
+define AddDepends/ipt
+ SUBMENU:=$(NF_MENU)
+ DEPENDS+= kmod-ipt-core $(1)
+endef
+
+
+define KernelPackage/ipt-conntrack
+ TITLE:=Basic connection tracking modules
+ KCONFIG:=$(KCONFIG_IPT_CONNTRACK)
+ FILES:=$(foreach mod,$(IPT_CONNTRACK-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,41,$(notdir $(IPT_CONNTRACK-m)))
+ $(call AddDepends/ipt)
+endef
+
+define KernelPackage/ipt-conntrack/description
+ Netfilter (IPv4) kernel modules for connection tracking
+ Includes:
+ - conntrack
+ - defrag
+ - iptables_raw
+ - NOTRACK
+ - state
+endef
+
+$(eval $(call KernelPackage,ipt-conntrack))
+
+
+define KernelPackage/ipt-conntrack-extra
+ TITLE:=Extra connection tracking modules
+ KCONFIG:=$(KCONFIG_IPT_CONNTRACK_EXTRA)
+ FILES:=$(foreach mod,$(IPT_CONNTRACK_EXTRA-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,42,$(notdir $(IPT_CONNTRACK_EXTRA-m)))
+ $(call AddDepends/ipt,+kmod-ipt-conntrack)
+endef
+
+define KernelPackage/ipt-conntrack-extra/description
+ Netfilter (IPv4) extra kernel modules for connection tracking
+ Includes:
+ - connbytes
+ - connmark/CONNMARK
+ - conntrack
+ - helper
+ - recent
+endef
+
+$(eval $(call KernelPackage,ipt-conntrack-extra))
+
+
+define KernelPackage/ipt-filter
+ TITLE:=Modules for packet content inspection
+ KCONFIG:=$(KCONFIG_IPT_FILTER)
+ FILES:=$(foreach mod,$(IPT_FILTER-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,45,$(notdir $(IPT_FILTER-m)))
+ $(call AddDepends/ipt,+kmod-lib-textsearch)
+endef
+
+define KernelPackage/ipt-filter/description
+ Netfilter (IPv4) kernel modules for packet content inspection
+ Includes:
+ - layer7
+ - string
+endef
+
+$(eval $(call KernelPackage,ipt-filter))
+
+
+define KernelPackage/ipt-ipopt
+ TITLE:=Modules for matching/changing IP packet options
+ KCONFIG:=$(KCONFIG_IPT_IPOPT)
+ FILES:=$(foreach mod,$(IPT_IPOPT-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,45,$(notdir $(IPT_IPOPT-m)))
+ $(call AddDepends/ipt)
+endef
+
+define KernelPackage/ipt-ipopt/description
+ Netfilter (IPv4) modules for matching/changing IP packet options
+ Includes:
+ - CLASSIFY
+ - dscp/DSCP
+ - ecn/ECN
+ - hl/HL
+ - length
+ - mark/MARK
+ - statistic
+ - tcpmss
+ - time
+ - ttl/TTL
+ - unclean
+endef
+
+$(eval $(call KernelPackage,ipt-ipopt))
+
+
+define KernelPackage/ipt-ipsec
+ TITLE:=Modules for matching IPSec packets
+ KCONFIG:=$(KCONFIG_IPT_IPSEC)
+ FILES:=$(foreach mod,$(IPT_IPSEC-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,45,$(notdir $(IPT_IPSEC-m)))
+ $(call AddDepends/ipt)
+endef
+
+define KernelPackage/ipt-ipsec/description
+ Netfilter (IPv4) modules for matching IPSec packets
+ Includes:
+ - ah
+ - esp
+ - policy
+endef
+
+$(eval $(call KernelPackage,ipt-ipsec))
+
+
+define KernelPackage/ipt-nat
+ TITLE:=Basic NAT targets
+ KCONFIG:=$(KCONFIG_IPT_NAT)
+ FILES:=$(foreach mod,$(IPT_NAT-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,42,$(notdir $(IPT_NAT-m)))
+ $(call AddDepends/ipt,+kmod-ipt-conntrack)
+endef
+
+define KernelPackage/ipt-nat/description
+ Netfilter (IPv4) kernel modules for basic NAT targets
+ Includes:
+ - MASQUERADE
+endef
+
+$(eval $(call KernelPackage,ipt-nat))
+
+
+define KernelPackage/ipt-nat-extra
+ TITLE:=Extra NAT targets
+ KCONFIG:=$(KCONFIG_IPT_NAT_EXTRA)
+ FILES:=$(foreach mod,$(IPT_NAT_EXTRA-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,43,$(notdir $(IPT_NAT_EXTRA-m)))
+ $(call AddDepends/ipt,+kmod-ipt-nat)
+endef
+
+define KernelPackage/ipt-nat-extra/description
+ Netfilter (IPv4) kernel modules for extra NAT targets
+ Includes:
+ - NETMAP
+ - REDIRECT
+endef
+
+$(eval $(call KernelPackage,ipt-nat-extra))
+
+
+define KernelPackage/ipt-nathelper
+ TITLE:=Basic Conntrack and NAT helpers
+ KCONFIG:=$(KCONFIG_IPT_NATHELPER)
+ FILES:=$(foreach mod,$(IPT_NATHELPER-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,45,$(notdir $(IPT_NATHELPER-m)))
+ $(call AddDepends/ipt,+kmod-ipt-nat)
+endef
+
+define KernelPackage/ipt-nathelper/description
+ Default Netfilter (IPv4) Conntrack and NAT helpers
+ Includes:
+ - ftp
+ - irc
+ - tftp
+endef
+
+$(eval $(call KernelPackage,ipt-nathelper))
+
+
+define KernelPackage/ipt-nathelper-extra
+ TITLE:=Extra Conntrack and NAT helpers
+ KCONFIG:=$(KCONFIG_IPT_NATHELPER_EXTRA)
+ FILES:=$(foreach mod,$(IPT_NATHELPER_EXTRA-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,45,$(notdir $(IPT_NATHELPER_EXTRA-m)))
+ $(call AddDepends/ipt,+kmod-ipt-nat +kmod-lib-textsearch)
+endef
+
+define KernelPackage/ipt-nathelper-extra/description
+ Extra Netfilter (IPv4) Conntrack and NAT helpers
+ Includes:
+ - amanda
+ - h323
+ - mms
+ - pptp
+ - proto_gre
+ - sip
+ - snmp_basic
+ - broadcast
+endef
+
+$(eval $(call KernelPackage,ipt-nathelper-extra))
+
+
+define KernelPackage/ipt-queue
+ TITLE:=Module for user-space packet queueing
+ KCONFIG:=$(KCONFIG_IPT_QUEUE)
+ FILES:=$(foreach mod,$(IPT_QUEUE-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,45,$(notdir $(IPT_QUEUE-m)))
+ $(call AddDepends/ipt)
+endef
+
+define KernelPackage/ipt-queue/description
+ Netfilter (IPv4) module for user-space packet queueing
+ Includes:
+ - QUEUE
+endef
+
+$(eval $(call KernelPackage,ipt-queue))
+
+
+define KernelPackage/ipt-ulog
+ TITLE:=Module for user-space packet logging
+ KCONFIG:=$(KCONFIG_IPT_ULOG)
+ FILES:=$(foreach mod,$(IPT_ULOG-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,45,$(notdir $(IPT_ULOG-m)))
+ $(call AddDepends/ipt)
+endef
+
+define KernelPackage/ipt-ulog/description
+ Netfilter (IPv4) module for user-space packet logging
+ Includes:
+ - ULOG
+endef
+
+$(eval $(call KernelPackage,ipt-ulog))
+
+
+define KernelPackage/ipt-debug
+ TITLE:=Module for debugging/development
+ KCONFIG:=$(KCONFIG_IPT_DEBUG)
+ DEFAULT:=n
+ FILES:=$(foreach mod,$(IPT_DEBUG-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,45,$(notdir $(IPT_DEBUG-m)))
+ $(call AddDepends/ipt)
+endef
+
+define KernelPackage/ipt-debug/description
+ Netfilter modules for debugging/development of the firewall
+ Includes:
+ - TRACE
+endef
+
+$(eval $(call KernelPackage,ipt-debug))
+
+
+define KernelPackage/ipt-led
+ TITLE:=Module to trigger a LED with a Netfilter rule
+ KCONFIG:=$(KCONFIG_IPT_LED)
+ FILES:=$(foreach mod,$(IPT_LED-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,61,$(notdir $(IPT_LED-m)))
+ $(call AddDepends/ipt)
+endef
+
+define KernelPackage/ipt-led/description
+ Netfilter target to trigger a LED when a network packet is matched.
+endef
+
+$(eval $(call KernelPackage,ipt-led))
+
+define KernelPackage/ipt-tproxy
+ TITLE:=Transparent proxying support
+ DEPENDS+=+IPV6:kmod-ipv6
+ KCONFIG:= \
+ CONFIG_NETFILTER_TPROXY \
+ CONFIG_NETFILTER_XT_MATCH_SOCKET \
+ CONFIG_NETFILTER_XT_TARGET_TPROXY
+ FILES:= \
+ $(LINUX_DIR)/net/netfilter/nf_tproxy_core.ko \
+ $(foreach mod,$(IPT_TPROXY-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,50,$(notdir nf_tproxy_core $(IPT_TPROXY-m)))
+ $(call AddDepends/ipt)
+endef
+
+define KernelPackage/ipt-tproxy/description
+ Kernel modules for Transparent Proxying
+endef
+
+$(eval $(call KernelPackage,ipt-tproxy))
+
+define KernelPackage/ipt-tee
+ TITLE:=TEE support
+ KCONFIG:= \
+ CONFIG_NETFILTER_XT_TARGET_TEE
+ FILES:= \
+ $(LINUX_DIR)/net/netfilter/xt_TEE.ko \
+ $(foreach mod,$(IPT_TEE-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,45,$(notdir nf_tee $(IPT_TEE-m)))
+ $(call AddDepends/ipt)
+endef
+
+define KernelPackage/ipt-tee/description
+ Kernel modules for TEE
+endef
+
+$(eval $(call KernelPackage,ipt-tee))
+
+
+define KernelPackage/ipt-u32
+ TITLE:=U32 support
+ KCONFIG:= \
+ CONFIG_NETFILTER_XT_MATCH_U32
+ FILES:= \
+ $(LINUX_DIR)/net/netfilter/xt_u32.ko \
+ $(foreach mod,$(IPT_U32-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,45,$(notdir nf_tee $(IPT_U32-m)))
+ $(call AddDepends/ipt)
+endef
+
+define KernelPackage/ipt-u32/description
+ Kernel modules for U32
+endef
+
+$(eval $(call KernelPackage,ipt-u32))
+
+
+define KernelPackage/ipt-iprange
+ TITLE:=Module for matching ip ranges
+ KCONFIG:=$(KCONFIG_IPT_IPRANGE)
+ FILES:=$(foreach mod,$(IPT_IPRANGE-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,45,$(notdir $(IPT_IPRANGE-m)))
+ $(call AddDepends/ipt)
+endef
+
+define KernelPackage/ipt-iprange/description
+ Netfilter (IPv4) module for matching ip ranges
+ Includes:
+ - iprange
+endef
+
+$(eval $(call KernelPackage,ipt-iprange))
+
+
+define KernelPackage/ipt-extra
+ TITLE:=Extra modules
+ KCONFIG:=$(KCONFIG_IPT_EXTRA)
+ FILES:=$(foreach mod,$(IPT_EXTRA-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,45,$(notdir $(IPT_EXTRA-m)))
+ $(call AddDepends/ipt)
+endef
+
+define KernelPackage/ipt-extra/description
+ Other Netfilter (IPv4) kernel modules
+ Includes:
+ - owner
+ - physdev (if bridge support was enabled in kernel)
+ - pkttype
+ - quota
+endef
+
+$(eval $(call KernelPackage,ipt-extra))
+
+
+define KernelPackage/ip6tables
+ SUBMENU:=$(NF_MENU)
+ TITLE:=IPv6 modules
+ DEPENDS:=+kmod-ipv6
+ KCONFIG:=$(KCONFIG_IPT_IPV6)
+ FILES:=$(foreach mod,$(IPT_IPV6-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,49,$(notdir $(IPT_IPV6-m)))
+endef
+
+define KernelPackage/ip6tables/description
+ Netfilter IPv6 firewalling support
+endef
+
+$(eval $(call KernelPackage,ip6tables))
+
+
+define KernelPackage/arptables
+ SUBMENU:=$(NF_MENU)
+ TITLE:=ARP firewalling modules
+ FILES:=$(LINUX_DIR)/net/ipv4/netfilter/arp*.ko
+ KCONFIG:=CONFIG_IP_NF_ARPTABLES \
+ CONFIG_IP_NF_ARPFILTER \
+ CONFIG_IP_NF_ARP_MANGLE
+ AUTOLOAD:=$(call AutoLoad,49,$(notdir $(patsubst %.ko,%,$(wildcard $(LINUX_DIR)/net/ipv4/netfilter/arp*.ko))))
+endef
+
+define KernelPackage/arptables/description
+ Kernel modules for ARP firewalling
+endef
+
+$(eval $(call KernelPackage,arptables))
+
+
+define KernelPackage/ebtables
+ SUBMENU:=$(NF_MENU)
+ TITLE:=Bridge firewalling modules
+ FILES:=$(foreach mod,$(EBTABLES-m),$(LINUX_DIR)/net/$(mod).ko)
+ KCONFIG:=CONFIG_BRIDGE_NETFILTER=y \
+ $(KCONFIG_EBTABLES)
+ AUTOLOAD:=$(call AutoLoad,49,$(notdir $(EBTABLES-m)))
+endef
+
+define KernelPackage/ebtables/description
+ ebtables is a general, extensible frame/packet identification
+ framework. It provides you to do Ethernet
+ filtering/NAT/brouting on the Ethernet bridge.
+endef
+
+$(eval $(call KernelPackage,ebtables))
+
+
+define AddDepends/ebtables
+ SUBMENU:=$(NF_MENU)
+ DEPENDS+=kmod-ebtables $(1)
+endef
+
+
+define KernelPackage/ebtables-ipv4
+ TITLE:=ebtables: IPv4 support
+ FILES:=$(foreach mod,$(EBTABLES_IP4-m),$(LINUX_DIR)/net/$(mod).ko)
+ KCONFIG:=$(KCONFIG_EBTABLES_IP4)
+ AUTOLOAD:=$(call AutoLoad,49,$(notdir $(EBTABLES_IP4-m)))
+ $(call AddDepends/ebtables)
+endef
+
+define KernelPackage/ebtables-ipv4/description
+ This option adds the IPv4 support to ebtables, which allows basic
+ IPv4 header field filtering, ARP filtering as well as SNAT, DNAT targets.
+endef
+
+$(eval $(call KernelPackage,ebtables-ipv4))
+
+
+define KernelPackage/ebtables-ipv6
+ TITLE:=ebtables: IPv6 support
+ FILES:=$(foreach mod,$(EBTABLES_IP6-m),$(LINUX_DIR)/net/$(mod).ko)
+ KCONFIG:=$(KCONFIG_EBTABLES_IP6)
+ AUTOLOAD:=$(call AutoLoad,49,$(notdir $(EBTABLES_IP6-m)))
+ $(call AddDepends/ebtables)
+endef
+
+define KernelPackage/ebtables-ipv6/description
+ This option adds the IPv6 support to ebtables, which allows basic
+ IPv6 header field filtering and target support.
+endef
+
+$(eval $(call KernelPackage,ebtables-ipv6))
+
+
+define KernelPackage/ebtables-watchers
+ TITLE:=ebtables: watchers support
+ FILES:=$(foreach mod,$(EBTABLES_WATCHERS-m),$(LINUX_DIR)/net/$(mod).ko)
+ KCONFIG:=$(KCONFIG_EBTABLES_WATCHERS)
+ AUTOLOAD:=$(call AutoLoad,49,$(notdir $(EBTABLES_WATCHERS-m)))
+ $(call AddDepends/ebtables)
+endef
+
+define KernelPackage/ebtables-watchers/description
+ This option adds the log watchers, that you can use in any rule
+ in any ebtables table.
+endef
+
+$(eval $(call KernelPackage,ebtables-watchers))
+
+
+define KernelPackage/nfnetlink
+ SUBMENU:=$(NF_MENU)
+ TITLE:=Netlink-based userspace interface
+ DEPENDS:=+kmod-ipt-core
+ FILES:=$(LINUX_DIR)/net/netfilter/nfnetlink.ko
+ KCONFIG:=CONFIG_NETFILTER_NETLINK
+ AUTOLOAD:=$(call AutoLoad,48,nfnetlink)
+endef
+
+define KernelPackage/nfnetlink/description
+ Kernel modules support for a netlink-based userspace interface
+endef
+
+$(eval $(call KernelPackage,nfnetlink))
+
+
+define AddDepends/nfnetlink
+ SUBMENU:=$(NF_MENU)
+ DEPENDS+=+kmod-nfnetlink $(1)
+endef
+
+
+define KernelPackage/nfnetlink-log
+ TITLE:=Netfilter LOG over NFNETLINK interface
+ FILES:=$(LINUX_DIR)/net/netfilter/nfnetlink_log.ko
+ KCONFIG:=CONFIG_NETFILTER_NETLINK_LOG
+ AUTOLOAD:=$(call AutoLoad,48,nfnetlink_log)
+ $(call AddDepends/nfnetlink)
+endef
+
+define KernelPackage/nfnetlink-log/description
+ Kernel modules support for logging packets via NFNETLINK
+endef
+
+$(eval $(call KernelPackage,nfnetlink-log))
+
+
+define KernelPackage/nfnetlink-queue
+ TITLE:=Netfilter QUEUE over NFNETLINK interface
+ FILES:=$(LINUX_DIR)/net/netfilter/nfnetlink_queue.ko
+ KCONFIG:=CONFIG_NETFILTER_NETLINK_QUEUE
+ AUTOLOAD:=$(call AutoLoad,48,nfnetlink_queue)
+ $(call AddDepends/nfnetlink)
+endef
+
+define KernelPackage/nfnetlink-queue/description
+ Kernel modules support for queueing packets via NFNETLINK
+endef
+
+$(eval $(call KernelPackage,nfnetlink-queue))
+
+
+define KernelPackage/nf-conntrack-netlink
+ TITLE:=Connection tracking netlink interface
+ FILES:=$(LINUX_DIR)/net/netfilter/nf_conntrack_netlink.ko
+ KCONFIG:=CONFIG_NF_CT_NETLINK
+ AUTOLOAD:=$(call AutoLoad,49,nf_conntrack_netlink)
+ $(call AddDepends/nfnetlink,+kmod-ipt-conntrack)
+endef
+
+define KernelPackage/nf-conntrack-netlink/description
+ Kernel modules support for a netlink-based connection tracking
+ userspace interface
+endef
+
+$(eval $(call KernelPackage,nf-conntrack-netlink))
+
+define KernelPackage/ipt-hashlimit
+ SUBMENU:=$(NF_MENU)
+ TITLE:=Netfilter hashlimit match
+ KCONFIG:=$(KCONFIG_IPT_HASHLIMIT)
+ FILES:=$(LINUX_DIR)/net/netfilter/xt_hashlimit.ko
+ AUTOLOAD:=$(call AutoLoad,50,xt_hashlimit)
+ $(call KernelPackage/ipt)
+endef
+
+define KernelPackage/ipt-hashlimit/description
+ Kernel modules support for the hashlimit bucket match module
+endef
+
+$(eval $(call KernelPackage,ipt-hashlimit))
diff --git a/package/kernel/modules/netsupport.mk b/package/kernel/modules/netsupport.mk
new file mode 100644
index 000000000..b4e2a425a
--- /dev/null
+++ b/package/kernel/modules/netsupport.mk
@@ -0,0 +1,865 @@
+#
+# Copyright (C) 2006-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+NETWORK_SUPPORT_MENU:=Network Support
+
+define KernelPackage/atm
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=ATM support
+ KCONFIG:= \
+ CONFIG_ATM \
+ CONFIG_ATM_BR2684
+ FILES:= \
+ $(LINUX_DIR)/net/atm/atm.ko \
+ $(LINUX_DIR)/net/atm/br2684.ko
+ AUTOLOAD:=$(call AutoLoad,30,atm br2684)
+endef
+
+define KernelPackage/atm/description
+ Kernel modules for ATM support
+endef
+
+$(eval $(call KernelPackage,atm))
+
+
+define KernelPackage/atmtcp
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=ATM over TCP
+ DEPENDS:=kmod-atm
+ KCONFIG:=CONFIG_ATM_TCP CONFIG_ATM_DRIVERS=y
+ FILES:=$(LINUX_DIR)/drivers/atm/atmtcp.ko
+ AUTOLOAD:=$(call AutoLoad,40,atmtcp)
+endef
+
+define KernelPackage/atmtcp/description
+ Kernel module for ATM over TCP support
+endef
+
+$(eval $(call KernelPackage,atmtcp))
+
+
+define KernelPackage/appletalk
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=Appletalk protocol support
+ KCONFIG:= \
+ CONFIG_ATALK \
+ CONFIG_DEV_APPLETALK \
+ CONFIG_IPDDP \
+ CONFIG_IPDDP_ENCAP=y \
+ CONFIG_IPDDP_DECAP=y
+ FILES:= \
+ $(LINUX_DIR)/net/appletalk/appletalk.ko \
+ $(LINUX_DIR)/drivers/net/appletalk/ipddp.ko
+ AUTOLOAD:=$(call AutoLoad,40,appletalk ipddp)
+endef
+
+define KernelPackage/appletalk/description
+ Kernel module for AppleTalk protocol.
+endef
+
+$(eval $(call KernelPackage,appletalk))
+
+
+define KernelPackage/bonding
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=Ethernet bonding driver
+ KCONFIG:=CONFIG_BONDING
+ FILES:=$(LINUX_DIR)/drivers/net/bonding/bonding.ko
+ AUTOLOAD:=$(call AutoLoad,40,bonding)
+endef
+
+define KernelPackage/bonding/description
+ Kernel module for NIC bonding.
+endef
+
+$(eval $(call KernelPackage,bonding))
+
+
+define KernelPackage/bridge
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=Ethernet bridging support
+ DEPENDS:=+kmod-stp
+ KCONFIG:= \
+ CONFIG_BRIDGE \
+ CONFIG_BRIDGE_IGMP_SNOOPING=y
+ FILES:=$(LINUX_DIR)/net/bridge/bridge.ko
+ AUTOLOAD:=$(call AutoLoad,11,bridge)
+endef
+
+define KernelPackage/bridge/description
+ Kernel module for Ethernet bridging.
+endef
+
+$(eval $(call KernelPackage,bridge))
+
+define KernelPackage/llc
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=ANSI/IEEE 802.2 LLC support
+ KCONFIG:=CONFIG_LLC
+ FILES:=$(LINUX_DIR)/net/llc/llc.ko
+ AUTOLOAD:=$(call AutoLoad,09,llc)
+endef
+
+define KernelPackage/llc/description
+ Kernel module for ANSI/IEEE 802.2 LLC support.
+endef
+
+$(eval $(call KernelPackage,llc))
+
+define KernelPackage/stp
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=Ethernet Spanning Tree Protocol support
+ DEPENDS:=+kmod-llc
+ KCONFIG:=CONFIG_STP
+ FILES:=$(LINUX_DIR)/net/802/stp.ko
+ AUTOLOAD:=$(call AutoLoad,10,stp)
+endef
+
+define KernelPackage/stp/description
+ Kernel module for Ethernet Spanning Tree Protocol support.
+endef
+
+$(eval $(call KernelPackage,stp))
+
+define KernelPackage/8021q
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=802.1Q VLAN support
+ KCONFIG:=CONFIG_VLAN_8021Q \
+ CONFIG_VLAN_8021Q_GVRP=n
+ FILES:=$(LINUX_DIR)/net/8021q/8021q.ko
+ AUTOLOAD:=$(call AutoLoad,12,8021q)
+endef
+
+define KernelPackage/8021q/description
+ Kernel module for 802.1Q VLAN support
+endef
+
+$(eval $(call KernelPackage,8021q))
+
+
+define KernelPackage/capi
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=CAPI (ISDN) Support
+ KCONFIG:= \
+ CONFIG_ISDN_CAPI \
+ CONFIG_ISDN_CAPI_CAPI20 \
+ CONFIG_ISDN_CAPIFS \
+ CONFIG_ISDN_CAPI_CAPIFS
+ FILES:= \
+ $(LINUX_DIR)/drivers/isdn/capi/kernelcapi.ko \
+ $(LINUX_DIR)/drivers/isdn/capi/capi.ko
+ AUTOLOAD:=$(call AutoLoad,30,kernelcapi capi)
+endef
+
+define KernelPackage/capi/description
+ Kernel module for basic CAPI (ISDN) support
+endef
+
+$(eval $(call KernelPackage,capi))
+
+define KernelPackage/misdn
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=mISDN (ISDN) Support
+ KCONFIG:= \
+ CONFIG_ISDN=y \
+ CONFIG_MISDN \
+ CONFIG_MISDN_DSP \
+ CONFIG_MISDN_L1OIP
+ FILES:= \
+ $(LINUX_DIR)/drivers/isdn/mISDN/mISDN_core.ko \
+ $(LINUX_DIR)/drivers/isdn/mISDN/mISDN_dsp.ko \
+ $(LINUX_DIR)/drivers/isdn/mISDN/l1oip.ko
+ AUTOLOAD:=$(call AutoLoad,30,mISDN_core mISDN_dsp l1oip)
+endef
+
+define KernelPackage/misdn/description
+ Modular ISDN driver support
+endef
+
+$(eval $(call KernelPackage,misdn))
+
+
+define KernelPackage/isdn4linux
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=Old ISDN4Linux (deprecated)
+ KCONFIG:= \
+ CONFIG_ISDN=y \
+ CONFIG_ISDN_I4L \
+ CONFIG_ISDN_PPP=y \
+ CONFIG_ISDN_PPP_VJ=y \
+ CONFIG_ISDN_MPP=y \
+ CONFIG_IPPP_FILTER=y \
+ CONFIG_ISDN_PPP_BSDCOMP \
+ CONFIG_ISDN_CAPI_MIDDLEWARE=y \
+ CONFIG_ISDN_CAPI_CAPIFS_BOOL=y \
+ CONFIG_ISDN_AUDIO=y \
+ CONFIG_ISDN_TTY_FAX=y \
+ CONFIG_ISDN_X25=y \
+ CONFIG_ISDN_DIVERSION
+ FILES:= \
+ $(LINUX_DIR)/drivers/isdn/divert/dss1_divert.ko \
+ $(LINUX_DIR)/drivers/isdn/i4l/isdn.ko \
+ $(LINUX_DIR)/drivers/isdn/i4l/isdn_bsdcomp.ko
+ AUTOLOAD:=$(call AutoLoad,40,isdn isdn_bsdcomp dss1_divert)
+endef
+
+define KernelPackage/isdn4linux/description
+ This driver allows you to use an ISDN adapter for networking
+endef
+
+$(eval $(call KernelPackage,isdn4linux))
+
+
+define KernelPackage/ipip
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=IP-in-IP encapsulation
+ DEPENDS:=+kmod-iptunnel4
+ KCONFIG:=CONFIG_NET_IPIP
+ FILES:=$(LINUX_DIR)/net/ipv4/ipip.ko
+ AUTOLOAD:=$(call AutoLoad,32,ipip)
+endef
+
+define KernelPackage/ipip/description
+ Kernel modules for IP-in-IP encapsulation
+endef
+
+$(eval $(call KernelPackage,ipip))
+
+
+IPSEC-m:= \
+ key/af_key \
+ xfrm/xfrm_ipcomp \
+ xfrm/xfrm_user \
+
+define KernelPackage/ipsec
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=IPsec related modules (IPv4 and IPv6)
+ DEPENDS:=+kmod-crypto-authenc +kmod-crypto-iv +kmod-crypto-des +kmod-crypto-hmac +kmod-crypto-md5 +kmod-crypto-sha1 +kmod-crypto-deflate +kmod-crypto-cbc
+ KCONFIG:= \
+ CONFIG_NET_KEY \
+ CONFIG_XFRM_USER \
+ CONFIG_INET_IPCOMP \
+ CONFIG_XFRM_IPCOMP
+ FILES:=$(foreach mod,$(IPSEC-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,30,$(notdir $(IPSEC-m)))
+endef
+
+define KernelPackage/ipsec/description
+ Kernel modules for IPsec support in both IPv4 and IPv6.
+ Includes:
+ - af_key
+ - xfrm_ipcomp
+ - xfrm_user
+endef
+
+$(eval $(call KernelPackage,ipsec))
+
+
+IPSEC4-m:= \
+ ipv4/ah4 \
+ ipv4/esp4 \
+ ipv4/xfrm4_mode_beet \
+ ipv4/xfrm4_mode_transport \
+ ipv4/xfrm4_mode_tunnel \
+ ipv4/xfrm4_tunnel \
+ ipv4/ipcomp \
+
+define KernelPackage/ipsec4
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=IPsec related modules (IPv4)
+ DEPENDS:=kmod-ipsec +kmod-iptunnel4
+ KCONFIG:= \
+ CONFIG_INET_AH \
+ CONFIG_INET_ESP \
+ CONFIG_INET_IPCOMP \
+ CONFIG_INET_XFRM_MODE_BEET \
+ CONFIG_INET_XFRM_MODE_TRANSPORT \
+ CONFIG_INET_XFRM_MODE_TUNNEL \
+ CONFIG_INET_XFRM_TUNNEL
+ FILES:=$(foreach mod,$(IPSEC4-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,32,$(notdir $(IPSEC4-m)))
+endef
+
+define KernelPackage/ipsec4/description
+ Kernel modules for IPsec support in IPv4.
+ Includes:
+ - ah4
+ - esp4
+ - ipcomp4
+ - xfrm4_mode_beet
+ - xfrm4_mode_transport
+ - xfrm4_mode_tunnel
+ - xfrm4_tunnel
+endef
+
+$(eval $(call KernelPackage,ipsec4))
+
+
+IPSEC6-m:= \
+ ipv6/ah6 \
+ ipv6/esp6 \
+ ipv6/xfrm6_mode_beet \
+ ipv6/xfrm6_mode_transport \
+ ipv6/xfrm6_mode_tunnel \
+ ipv6/xfrm6_tunnel \
+ ipv6/ipcomp6 \
+
+define KernelPackage/ipsec6
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=IPsec related modules (IPv6)
+ DEPENDS:=kmod-ipsec +kmod-iptunnel6
+ KCONFIG:= \
+ CONFIG_INET6_AH \
+ CONFIG_INET6_ESP \
+ CONFIG_INET6_IPCOMP \
+ CONFIG_INET6_XFRM_MODE_BEET \
+ CONFIG_INET6_XFRM_MODE_TRANSPORT \
+ CONFIG_INET6_XFRM_MODE_TUNNEL \
+ CONFIG_INET6_XFRM_TUNNEL
+ FILES:=$(foreach mod,$(IPSEC6-m),$(LINUX_DIR)/net/$(mod).ko)
+ AUTOLOAD:=$(call AutoLoad,32,$(notdir $(IPSEC6-m)))
+endef
+
+define KernelPackage/ipsec6/description
+ Kernel modules for IPsec support in IPv6.
+ Includes:
+ - ah6
+ - esp6
+ - ipcomp6
+ - xfrm6_mode_beet
+ - xfrm6_mode_transport
+ - xfrm6_mode_tunnel
+ - xfrm6_tunnel
+endef
+
+$(eval $(call KernelPackage,ipsec6))
+
+
+# NOTE: tunnel4 is not selectable by itself, so enable ipip for that
+define KernelPackage/iptunnel4
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=IPv4 tunneling
+ KCONFIG:= \
+ CONFIG_NET_IPIP \
+ CONFIG_INET_TUNNEL
+ FILES:=$(LINUX_DIR)/net/ipv4/tunnel4.ko
+ AUTOLOAD:=$(call AutoLoad,31,tunnel4)
+endef
+
+define KernelPackage/iptunnel4/description
+ Kernel modules for IPv4 tunneling
+endef
+
+$(eval $(call KernelPackage,iptunnel4))
+
+
+define KernelPackage/iptunnel6
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=IPv6 tunneling
+ DEPENDS:= +kmod-ipv6
+ KCONFIG:= \
+ CONFIG_INET6_TUNNEL
+ FILES:=$(LINUX_DIR)/net/ipv6/tunnel6.ko
+ AUTOLOAD:=$(call AutoLoad,31,tunnel6)
+endef
+
+define KernelPackage/iptunnel6/description
+ Kernel modules for IPv6 tunneling
+endef
+
+$(eval $(call KernelPackage,iptunnel6))
+
+
+define KernelPackage/ipv6
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=IPv6 support
+ KCONFIG:= \
+ CONFIG_IPV6 \
+ CONFIG_IPV6_PRIVACY=y \
+ CONFIG_IPV6_MULTIPLE_TABLES=y \
+ CONFIG_IPV6_MROUTE=y \
+ CONFIG_IPV6_PIMSM_V2=n \
+ CONFIG_IPV6_SUBTREES=y
+ FILES:=$(LINUX_DIR)/net/ipv6/ipv6.ko
+ AUTOLOAD:=$(call AutoLoad,20,ipv6)
+endef
+
+define KernelPackage/ipv6/description
+ Kernel modules for IPv6 support
+endef
+
+$(eval $(call KernelPackage,ipv6))
+
+
+define KernelPackage/sit
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ DEPENDS:=+kmod-ipv6 +kmod-iptunnel4
+ TITLE:=IPv6-in-IPv4 tunnel
+ KCONFIG:=CONFIG_IPV6_SIT \
+ CONFIG_IPV6_SIT_6RD=y
+ FILES:=$(LINUX_DIR)/net/ipv6/sit.ko
+ AUTOLOAD:=$(call AutoLoad,32,sit)
+endef
+
+define KernelPackage/sit/description
+ Kernel modules for IPv6-in-IPv4 tunnelling
+endef
+
+$(eval $(call KernelPackage,sit))
+
+
+define KernelPackage/ip6-tunnel
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=IP-in-IPv6 tunnelling
+ DEPENDS:= +kmod-ipv6 +kmod-iptunnel6
+ KCONFIG:= CONFIG_IPV6_TUNNEL
+ FILES:=$(LINUX_DIR)/net/ipv6/ip6_tunnel.ko
+ AUTOLOAD:=$(call AutoLoad,32,ip6_tunnel)
+endef
+
+define KernelPackage/ip6-tunnel/description
+ Kernel modules for IPv6-in-IPv6 and IPv4-in-IPv6 tunnelling
+endef
+
+$(eval $(call KernelPackage,ip6-tunnel))
+
+
+define KernelPackage/gre
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=GRE support
+ DEPENDS:=+PACKAGE_kmod-ipv6:kmod-ipv6
+ KCONFIG:=CONFIG_NET_IPGRE CONFIG_NET_IPGRE_DEMUX
+ FILES:=$(LINUX_DIR)/net/ipv4/ip_gre.ko $(LINUX_DIR)/net/ipv4/gre.ko
+ AUTOLOAD:=$(call AutoLoad,39,gre ip_gre)
+endef
+
+define KernelPackage/gre/description
+ Generic Routing Encapsulation support
+endef
+
+$(eval $(call KernelPackage,gre))
+
+
+define KernelPackage/tun
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=Universal TUN/TAP driver
+ KCONFIG:=CONFIG_TUN
+ FILES:=$(LINUX_DIR)/drivers/net/tun.ko
+ AUTOLOAD:=$(call AutoLoad,30,tun)
+endef
+
+define KernelPackage/tun/description
+ Kernel support for the TUN/TAP tunneling device
+endef
+
+$(eval $(call KernelPackage,tun))
+
+
+define KernelPackage/ppp
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=PPP modules
+ DEPENDS:=+kmod-lib-crc-ccitt
+ KCONFIG:= \
+ CONFIG_PPP \
+ CONFIG_PPP_ASYNC \
+ CONFIG_SLHC
+ FILES:= \
+ $(LINUX_DIR)/drivers/net/ppp/ppp_async.ko \
+ $(LINUX_DIR)/drivers/net/ppp/ppp_generic.ko \
+ $(LINUX_DIR)/drivers/net/slip/slhc.ko
+ AUTOLOAD:=$(call AutoLoad,30,slhc ppp_generic ppp_async)
+endef
+
+define KernelPackage/ppp/description
+ Kernel modules for PPP support
+endef
+
+$(eval $(call KernelPackage,ppp))
+
+
+define KernelPackage/ppp-synctty
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=PPP sync tty support
+ DEPENDS:=kmod-ppp
+ KCONFIG:=CONFIG_PPP_SYNC_TTY
+ FILES:=$(LINUX_DIR)/drivers/net/ppp/ppp_synctty.ko
+ AUTOLOAD:=$(call AutoLoad,40,ppp_synctty)
+endef
+
+define KernelPackage/ppp-synctty/description
+ Kernel modules for PPP sync tty support
+endef
+
+$(eval $(call KernelPackage,ppp-synctty))
+
+
+define KernelPackage/pppox
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=PPPoX helper
+ DEPENDS:=kmod-ppp
+ KCONFIG:=CONFIG_PPPOE
+ FILES:=$(LINUX_DIR)/drivers/net/ppp/pppox.ko
+ AUTOLOAD:=$(call AutoLoad,40,pppox)
+endef
+
+define KernelPackage/pppox/description
+ Kernel helper module for PPPoE and PPTP support
+endef
+
+$(eval $(call KernelPackage,pppox))
+
+
+define KernelPackage/pppoe
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=PPPoE support
+ DEPENDS:=kmod-ppp +kmod-pppox
+ KCONFIG:=CONFIG_PPPOE
+ FILES:=$(LINUX_DIR)/drivers/net/ppp/pppoe.ko
+ AUTOLOAD:=$(call AutoLoad,41,pppoe)
+endef
+
+define KernelPackage/pppoe/description
+ Kernel module for PPPoE (PPP over Ethernet) support
+endef
+
+$(eval $(call KernelPackage,pppoe))
+
+
+define KernelPackage/pppoa
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=PPPoA support
+ DEPENDS:=kmod-ppp +kmod-atm
+ KCONFIG:=CONFIG_PPPOATM CONFIG_ATM_DRIVERS=y
+ FILES:=$(LINUX_DIR)/net/atm/pppoatm.ko
+ AUTOLOAD:=$(call AutoLoad,40,pppoatm)
+endef
+
+define KernelPackage/pppoa/description
+ Kernel modules for PPPoA (PPP over ATM) support
+endef
+
+$(eval $(call KernelPackage,pppoa))
+
+
+define KernelPackage/pptp
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=PPtP support
+ DEPENDS:=kmod-ppp +kmod-gre +kmod-pppox
+ KCONFIG:=CONFIG_PPTP
+ FILES:=$(LINUX_DIR)/drivers/net/ppp/pptp.ko
+ AUTOLOAD:=$(call AutoLoad,41,pptp)
+endef
+
+$(eval $(call KernelPackage,pptp))
+
+
+define KernelPackage/pppol2tp
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=PPPoL2TP support
+ DEPENDS:=kmod-ppp +kmod-pppox +kmod-l2tp
+ KCONFIG:=CONFIG_PPPOL2TP
+ FILES:=$(LINUX_DIR)/net/l2tp/l2tp_ppp.ko
+ AUTOLOAD:=$(call AutoLoad,41,l2tp_ppp)
+endef
+
+define KernelPackage/pppol2tp/description
+ Kernel modules for PPPoL2TP (PPP over L2TP) support
+endef
+
+$(eval $(call KernelPackage,pppol2tp))
+
+
+define KernelPackage/ipoa
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=IPoA support
+ DEPENDS:=kmod-atm
+ KCONFIG:=CONFIG_ATM_CLIP
+ FILES:=$(LINUX_DIR)/net/atm/clip.ko
+ AUTOLOAD:=$(call AutoLoad,40,clip)
+endef
+
+define KernelPackage/ipoa/description
+ Kernel modules for IPoA (IP over ATM) support
+endef
+
+$(eval $(call KernelPackage,ipoa))
+
+
+define KernelPackage/mppe
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=Microsoft PPP compression/encryption
+ DEPENDS:=kmod-ppp +kmod-crypto-core +kmod-crypto-arc4 +kmod-crypto-sha1 +kmod-crypto-ecb
+ KCONFIG:= \
+ CONFIG_PPP_MPPE_MPPC \
+ CONFIG_PPP_MPPE
+ FILES:=$(LINUX_DIR)/drivers/net/ppp/ppp_mppe.ko
+ AUTOLOAD:=$(call AutoLoad,31,ppp_mppe)
+endef
+
+define KernelPackage/mppe/description
+ Kernel modules for Microsoft PPP compression/encryption
+endef
+
+$(eval $(call KernelPackage,mppe))
+
+
+SCHED_MODULES = $(patsubst $(LINUX_DIR)/net/sched/%.ko,%,$(wildcard $(LINUX_DIR)/net/sched/*.ko))
+SCHED_MODULES_CORE = sch_ingress sch_codel sch_fq_codel sch_hfsc cls_fw cls_route cls_flow cls_tcindex cls_u32 em_u32 act_mirred act_skbedit
+SCHED_MODULES_FILTER = $(SCHED_MODULES_CORE) act_connmark sch_esfq
+SCHED_MODULES_EXTRA = $(filter-out $(SCHED_MODULES_FILTER),$(SCHED_MODULES))
+SCHED_FILES = $(patsubst %,$(LINUX_DIR)/net/sched/%.ko,$(filter $(SCHED_MODULES_CORE),$(SCHED_MODULES)))
+SCHED_FILES_EXTRA = $(patsubst %,$(LINUX_DIR)/net/sched/%.ko,$(SCHED_MODULES_EXTRA))
+
+define KernelPackage/sched-core
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=Traffic schedulers
+ KCONFIG:= \
+ CONFIG_NET_SCHED=y \
+ CONFIG_NET_SCH_HFSC \
+ CONFIG_NET_SCH_INGRESS \
+ CONFIG_NET_SCH_CODEL \
+ CONFIG_NET_SCH_FQ_CODEL \
+ CONFIG_NET_CLS=y \
+ CONFIG_NET_CLS_ACT=y \
+ CONFIG_NET_CLS_FLOW \
+ CONFIG_NET_CLS_FW \
+ CONFIG_NET_CLS_ROUTE4 \
+ CONFIG_NET_CLS_TCINDEX \
+ CONFIG_NET_CLS_U32 \
+ CONFIG_NET_ACT_MIRRED \
+ CONFIG_NET_ACT_SKBEDIT \
+ CONFIG_NET_EMATCH=y \
+ CONFIG_NET_EMATCH_U32
+ FILES:=$(SCHED_FILES)
+endef
+
+define KernelPackage/sched-core/description
+ Core kernel scheduler support for IP traffic
+endef
+
+$(eval $(call KernelPackage,sched-core))
+
+
+define KernelPackage/sched-connmark
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=Traffic shaper conntrack mark support
+ DEPENDS:=+kmod-sched-core +kmod-ipt-core +kmod-ipt-conntrack-extra
+ KCONFIG:=CONFIG_NET_ACT_CONNMARK
+ FILES:=$(LINUX_DIR)/net/sched/act_connmark.ko
+endef
+$(eval $(call KernelPackage,sched-connmark))
+
+define KernelPackage/sched-esfq
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=Traffic shaper ESFQ support
+ DEPENDS:=+kmod-sched-core +kmod-ipt-core
+ KCONFIG:= \
+ CONFIG_NET_SCH_ESFQ \
+ CONFIG_NET_SCH_ESFQ_NFCT=y
+ FILES:=$(LINUX_DIR)/net/sched/sch_esfq.ko
+endef
+$(eval $(call KernelPackage,sched-esfq))
+
+define KernelPackage/sched
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=Extra traffic schedulers
+ DEPENDS:=+kmod-sched-core
+ KCONFIG:= \
+ CONFIG_NET_SCH_DSMARK \
+ CONFIG_NET_SCH_HTB \
+ CONFIG_NET_SCH_FIFO \
+ CONFIG_NET_SCH_GRED \
+ CONFIG_NET_SCH_PRIO \
+ CONFIG_NET_SCH_RED \
+ CONFIG_NET_SCH_TBF \
+ CONFIG_NET_SCH_SFQ \
+ CONFIG_NET_SCH_TEQL \
+ CONFIG_NET_CLS_BASIC \
+ CONFIG_NET_ACT_POLICE \
+ CONFIG_NET_ACT_IPT \
+ CONFIG_NET_EMATCH_CMP \
+ CONFIG_NET_EMATCH_NBYTE \
+ CONFIG_NET_EMATCH_META \
+ CONFIG_NET_EMATCH_TEXT
+ FILES:=$(SCHED_FILES_EXTRA)
+endef
+
+define KernelPackage/sched/description
+ Extra kernel schedulers modules for IP traffic
+endef
+
+$(eval $(call KernelPackage,sched))
+
+
+define KernelPackage/ax25
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=AX25 support
+ KCONFIG:= \
+ CONFIG_AX25 \
+ CONFIG_MKISS
+ FILES:= \
+ $(LINUX_DIR)/net/ax25/ax25.ko \
+ $(LINUX_DIR)/drivers/net/hamradio/mkiss.ko
+ AUTOLOAD:=$(call AutoLoad,80,ax25 mkiss)
+ $(call AddDepends/crc16)
+endef
+
+define KernelPackage/ax25/description
+ Kernel modules for AX25 support
+endef
+
+$(eval $(call KernelPackage,ax25))
+
+
+define KernelPackage/mp-alg
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=ECMP caching algorithms
+ KCONFIG:= \
+ CONFIG_IP_ROUTE_MULTIPATH_RR \
+ CONFIG_IP_ROUTE_MULTIPATH_RANDOM \
+ CONFIG_IP_ROUTE_MULTIPATH_WRANDOM \
+ CONFIG_IP_ROUTE_MULTIPATH_DRR
+ FILES:= \
+ $(LINUX_DIR)/net/ipv4/multipath_rr.ko \
+ $(LINUX_DIR)/net/ipv4/multipath_random.ko \
+ $(LINUX_DIR)/net/ipv4/multipath_wrandom.ko \
+ $(LINUX_DIR)/net/ipv4/multipath_drr.ko
+ AUTOLOAD:=$(call AutoLoad,35,multipath_rr multipath_random multipath_wrandom multipath_drr)
+endef
+
+define KernelPackage/mp-alg/description
+ Kernel modules that provide several different algorithms for multipath
+ route selection from the route cache. The iproute "mpath" argument allows
+ specifying which algorithm to use for routes.
+ quagga (at least <=0.99.6) requires a multipath patch to support this
+ cached mp route feature.
+endef
+
+$(eval $(call KernelPackage,mp-alg))
+
+
+define KernelPackage/pktgen
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ DEPENDS:=@!TARGET_uml
+ TITLE:=Network packet generator
+ KCONFIG:=CONFIG_NET_PKTGEN
+ FILES:=$(LINUX_DIR)/net/core/pktgen.ko
+ AUTOLOAD:=$(call AutoLoad,99,pktgen)
+endef
+
+define KernelPackage/pktgen/description
+ Kernel modules for the Network Packet Generator
+endef
+
+$(eval $(call KernelPackage,pktgen))
+
+define KernelPackage/l2tp
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=Layer Two Tunneling Protocol (L2TP)
+ KCONFIG:=CONFIG_L2TP \
+ CONFIG_L2TP_V3=y \
+ CONFIG_L2TP_DEBUGFS=n
+ FILES:=$(LINUX_DIR)/net/l2tp/l2tp_core.ko \
+ $(LINUX_DIR)/net/l2tp/l2tp_netlink.ko
+ AUTOLOAD:=$(call AutoLoad,32,l2tp_core l2tp_netlink)
+endef
+
+define KernelPackage/l2tp/description
+ Kernel modules for L2TP V3 Support
+endef
+
+$(eval $(call KernelPackage,l2tp))
+
+
+define KernelPackage/l2tp-eth
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=L2TP ethernet pseudowire support for L2TPv3
+ DEPENDS:=+kmod-l2tp
+ KCONFIG:=CONFIG_L2TP_ETH
+ FILES:=$(LINUX_DIR)/net/l2tp/l2tp_eth.ko
+ AUTOLOAD:=$(call AutoLoad,33,l2tp_eth)
+endef
+
+define KernelPackage/l2tp-eth/description
+ Kernel modules for L2TP ethernet pseudowire support for L2TPv3
+endef
+
+$(eval $(call KernelPackage,l2tp-eth))
+
+define KernelPackage/l2tp-ip
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=L2TP IP encapsulation for L2TPv3
+ DEPENDS:=+kmod-l2tp
+ KCONFIG:=CONFIG_L2TP_IP
+ FILES:=$(LINUX_DIR)/net/l2tp/l2tp_ip.ko
+ AUTOLOAD:=$(call AutoLoad,33,l2tp_ip)
+endef
+
+define KernelPackage/l2tp-ip/description
+ Kernel modules for L2TP IP encapsulation for L2TPv3
+endef
+
+$(eval $(call KernelPackage,l2tp-ip))
+
+
+define KernelPackage/sctp
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=SCTP protocol kernel support
+ KCONFIG:=\
+ CONFIG_IP_SCTP \
+ CONFIG_SCTP_DBG_MSG=n \
+ CONFIG_SCTP_DBG_OBJCNT=n \
+ CONFIG_SCTP_HMAC_NONE=n \
+ CONFIG_SCTP_HMAC_SHA1=n \
+ CONFIG_SCTP_HMAC_MD5=y
+ FILES:= $(LINUX_DIR)/net/sctp/sctp.ko
+ AUTOLOAD:= $(call AutoLoad,32,sctp)
+ DEPENDS:=+kmod-lib-crc32c +kmod-crypto-md5 +kmod-crypto-hmac
+endef
+
+define KernelPackage/sctp/description
+ Kernel modules for SCTP protocol support
+endef
+
+$(eval $(call KernelPackage,sctp))
+
+
+define KernelPackage/netem
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=Network emulation functionality
+ DEPENDS:=+kmod-sched
+ KCONFIG:=CONFIG_NET_SCH_NETEM
+ FILES:=$(LINUX_DIR)/net/sched/sch_netem.ko
+ AUTOLOAD:=$(call AutoLoad,99,netem)
+endef
+
+define KernelPackage/netem/description
+ Kernel modules for emulating the properties of wide area networks
+endef
+
+$(eval $(call KernelPackage,netem))
+
+define KernelPackage/slip
+ SUBMENU:=$(NETWORK_SUPPORT_MENU)
+ TITLE:=SLIP modules
+ KCONFIG:= \
+ CONFIG_SLIP \
+ CONFIG_SLIP_COMPRESSED=y \
+ CONFIG_SLIP_SMART=y \
+ CONFIG_SLIP_MODE_SLIP6=y
+
+ FILES:= \
+ $(LINUX_DIR)/drivers/net/slip/slip.ko
+ AUTOLOAD:=$(call AutoLoad,30,slip)
+endef
+
+define KernelPackage/slip/description
+ Kernel modules for SLIP support
+endef
+
+$(eval $(call KernelPackage,slip))
+
diff --git a/package/kernel/modules/nls.mk b/package/kernel/modules/nls.mk
new file mode 100644
index 000000000..28791b6b7
--- /dev/null
+++ b/package/kernel/modules/nls.mk
@@ -0,0 +1,228 @@
+#
+# Copyright (C) 2006-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define KernelPackage/nls-base
+ SUBMENU:=Native Language Support
+ TITLE:=Native Language Support
+ KCONFIG:=CONFIG_NLS
+ FILES:=$(LINUX_DIR)/fs/nls/nls_base.ko
+ AUTOLOAD:=$(call AutoLoad,20,nls_base,1)
+endef
+
+define KernelPackage/nls-base/description
+ Kernel module for NLS (Native Language Support)
+endef
+
+$(eval $(call KernelPackage,nls-base))
+
+
+define KernelPackage/nls-cp437
+ SUBMENU:=Native Language Support
+ TITLE:=Codepage 437 (United States, Canada)
+ KCONFIG:=CONFIG_NLS_CODEPAGE_437
+ FILES:=$(LINUX_DIR)/fs/nls/nls_cp437.ko
+ AUTOLOAD:=$(call AutoLoad,25,nls_cp437)
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/nls-cp437/description
+ Kernel module for NLS Codepage 437 (United States, Canada)
+endef
+
+$(eval $(call KernelPackage,nls-cp437))
+
+
+define KernelPackage/nls-cp775
+ SUBMENU:=Native Language Support
+ TITLE:=Codepage 775 (Baltic Rim)
+ KCONFIG:=CONFIG_NLS_CODEPAGE_775
+ FILES:=$(LINUX_DIR)/fs/nls/nls_cp775.ko
+ AUTOLOAD:=$(call AutoLoad,25,nls_cp775)
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/nls-cp775/description
+ Kernel module for NLS Codepage 775 (Baltic Rim)
+endef
+
+$(eval $(call KernelPackage,nls-cp775))
+
+
+define KernelPackage/nls-cp850
+ SUBMENU:=Native Language Support
+ TITLE:=Codepage 850 (Europe)
+ KCONFIG:=CONFIG_NLS_CODEPAGE_850
+ FILES:=$(LINUX_DIR)/fs/nls/nls_cp850.ko
+ AUTOLOAD:=$(call AutoLoad,25,nls_cp850)
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/nls-cp850/description
+ Kernel module for NLS Codepage 850 (Europe)
+endef
+
+$(eval $(call KernelPackage,nls-cp850))
+
+
+define KernelPackage/nls-cp852
+ SUBMENU:=Native Language Support
+ TITLE:=Codepage 852 (Europe)
+ KCONFIG:=CONFIG_NLS_CODEPAGE_852
+ FILES:=$(LINUX_DIR)/fs/nls/nls_cp852.ko
+ AUTOLOAD:=$(call AutoLoad,25,nls_cp852)
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/nls-cp852/description
+ Kernel module for NLS Codepage 852 (Europe)
+endef
+
+$(eval $(call KernelPackage,nls-cp852))
+
+
+define KernelPackage/nls-cp866
+ SUBMENU:=Native Language Support
+ TITLE:=Codepage 866 (Cyrillic)
+ KCONFIG:=CONFIG_NLS_CODEPAGE_866
+ FILES:=$(LINUX_DIR)/fs/nls/nls_cp866.ko
+ AUTOLOAD:=$(call AutoLoad,25,nls_cp866)
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/nls-cp866/description
+ Kernel module for NLS Codepage 866 (Cyrillic)
+endef
+
+$(eval $(call KernelPackage,nls-cp866))
+
+
+define KernelPackage/nls-cp1250
+ SUBMENU:=Native Language Support
+ TITLE:=Codepage 1250 (Eastern Europe)
+ KCONFIG:=CONFIG_NLS_CODEPAGE_1250
+ FILES:=$(LINUX_DIR)/fs/nls/nls_cp1250.ko
+ AUTOLOAD:=$(call AutoLoad,25,nls_cp1250)
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/nls-cp1250/description
+ Kernel module for NLS Codepage 1250 (Eastern Europe)
+endef
+
+$(eval $(call KernelPackage,nls-cp1250))
+
+
+define KernelPackage/nls-cp1251
+ SUBMENU:=Native Language Support
+ TITLE:=Codepage 1251 (Russian)
+ KCONFIG:=CONFIG_NLS_CODEPAGE_1251
+ FILES:=$(LINUX_DIR)/fs/nls/nls_cp1251.ko
+ AUTOLOAD:=$(call AutoLoad,25,nls_cp1251)
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/nls-cp1251/description
+ Kernel module for NLS Codepage 1251 (Russian)
+endef
+
+$(eval $(call KernelPackage,nls-cp1251))
+
+
+define KernelPackage/nls-iso8859-1
+ SUBMENU:=Native Language Support
+ TITLE:=ISO 8859-1 (Latin 1; Western European Languages)
+ KCONFIG:=CONFIG_NLS_ISO8859_1
+ FILES:=$(LINUX_DIR)/fs/nls/nls_iso8859-1.ko
+ AUTOLOAD:=$(call AutoLoad,25,nls_iso8859-1)
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/nls-iso8859-1/description
+ Kernel module for NLS ISO 8859-1 (Latin 1)
+endef
+
+$(eval $(call KernelPackage,nls-iso8859-1))
+
+
+define KernelPackage/nls-iso8859-2
+ SUBMENU:=Native Language Support
+ TITLE:=ISO 8859-2 (Latin 2; Central European Languages)
+ KCONFIG:=CONFIG_NLS_ISO8859_2
+ FILES:=$(LINUX_DIR)/fs/nls/nls_iso8859-2.ko
+ AUTOLOAD:=$(call AutoLoad,25,nls_iso8859-2)
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/nls-iso8859-2/description
+ Kernel module for NLS ISO 8859-2 (Latin 2)
+endef
+
+$(eval $(call KernelPackage,nls-iso8859-2))
+
+
+define KernelPackage/nls-iso8859-13
+ SUBMENU:=Native Language Support
+ TITLE:=ISO 8859-13 (Latin 7; Baltic)
+ KCONFIG:=CONFIG_NLS_ISO8859_13
+ FILES:=$(LINUX_DIR)/fs/nls/nls_iso8859-13.ko
+ AUTOLOAD:=$(call AutoLoad,25,nls_iso8859-13)
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/nls-iso8859-13/description
+ Kernel module for NLS ISO 8859-13 (Latin 7; Baltic)
+endef
+
+$(eval $(call KernelPackage,nls-iso8859-13))
+
+
+define KernelPackage/nls-iso8859-15
+ SUBMENU:=Native Language Support
+ TITLE:=ISO 8859-15 (Latin 9; Western, with Euro symbol)
+ KCONFIG:=CONFIG_NLS_ISO8859_15
+ FILES:=$(LINUX_DIR)/fs/nls/nls_iso8859-15.ko
+ AUTOLOAD:=$(call AutoLoad,25,nls_iso8859-15)
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/nls-iso8859-15/description
+ Kernel module for NLS ISO 8859-15 (Latin 9)
+endef
+
+$(eval $(call KernelPackage,nls-iso8859-15))
+
+
+define KernelPackage/nls-koi8r
+ SUBMENU:=Native Language Support
+ TITLE:=KOI8-R (Russian)
+ KCONFIG:=CONFIG_NLS_KOI8_R
+ FILES:=$(LINUX_DIR)/fs/nls/nls_koi8-r.ko
+ AUTOLOAD:=$(call AutoLoad,25,nls_koi8-r)
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/nls-koi8r/description
+ Kernel module for NLS KOI8-R (Russian)
+endef
+
+$(eval $(call KernelPackage,nls-koi8r))
+
+
+define KernelPackage/nls-utf8
+ SUBMENU:=Native Language Support
+ TITLE:=UTF-8
+ KCONFIG:=CONFIG_NLS_UTF8
+ FILES:=$(LINUX_DIR)/fs/nls/nls_utf8.ko
+ AUTOLOAD:=$(call AutoLoad,25,nls_utf8)
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/nls-utf8/description
+ Kernel module for NLS UTF-8
+endef
+
+$(eval $(call KernelPackage,nls-utf8))
diff --git a/package/kernel/modules/other.mk b/package/kernel/modules/other.mk
new file mode 100644
index 000000000..57614387a
--- /dev/null
+++ b/package/kernel/modules/other.mk
@@ -0,0 +1,698 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+OTHER_MENU:=Other modules
+
+WATCHDOG_DIR:=watchdog
+
+
+define KernelPackage/bluetooth
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=Bluetooth support
+ DEPENDS:=@USB_SUPPORT +kmod-usb-core
+ KCONFIG:= \
+ CONFIG_BLUEZ \
+ CONFIG_BLUEZ_L2CAP \
+ CONFIG_BLUEZ_SCO \
+ CONFIG_BLUEZ_RFCOMM \
+ CONFIG_BLUEZ_BNEP \
+ CONFIG_BLUEZ_HCIUART \
+ CONFIG_BLUEZ_HCIUSB \
+ CONFIG_BLUEZ_HIDP \
+ CONFIG_BT \
+ CONFIG_BT_L2CAP=y \
+ CONFIG_BT_SCO=y \
+ CONFIG_BT_RFCOMM \
+ CONFIG_BT_BNEP \
+ CONFIG_BT_HCIBTUSB \
+ CONFIG_BT_HCIUSB \
+ CONFIG_BT_HCIUART \
+ CONFIG_BT_HCIUART_H4 \
+ CONFIG_BT_HIDP \
+ CONFIG_HID_SUPPORT=y
+ $(call AddDepends/crc16)
+ $(call AddDepends/hid)
+ $(call AddDepends/rfkill)
+ FILES:= \
+ $(LINUX_DIR)/net/bluetooth/bluetooth.ko \
+ $(LINUX_DIR)/net/bluetooth/rfcomm/rfcomm.ko \
+ $(LINUX_DIR)/net/bluetooth/bnep/bnep.ko \
+ $(LINUX_DIR)/net/bluetooth/hidp/hidp.ko \
+ $(LINUX_DIR)/drivers/bluetooth/hci_uart.ko \
+ $(LINUX_DIR)/drivers/bluetooth/btusb.ko
+ AUTOLOAD:=$(call AutoLoad,90,bluetooth rfcomm bnep hidp hci_uart btusb)
+endef
+
+define KernelPackage/bluetooth/description
+ Kernel support for Bluetooth devices
+endef
+
+$(eval $(call KernelPackage,bluetooth))
+
+
+define KernelPackage/bluetooth-hci-h4p
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=HCI driver with H4 Nokia extensions
+ DEPENDS:=@TARGET_omap24xx +kmod-bluetooth
+ KCONFIG:=CONFIG_BT_HCIH4P
+ FILES:=$(LINUX_DIR)/drivers/bluetooth/hci_h4p/hci_h4p.ko
+ AUTOLOAD:=$(call AutoLoad,91,hci_h4p)
+endef
+
+define KernelPackage/bluetooth-hci-h4p/description
+ HCI driver with H4 Nokia extensions
+endef
+
+$(eval $(call KernelPackage,bluetooth-hci-h4p))
+
+
+define KernelPackage/eeprom-93cx6
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=EEPROM 93CX6 support
+ KCONFIG:=CONFIG_EEPROM_93CX6
+ FILES:=$(LINUX_DIR)/drivers/misc/eeprom/eeprom_93cx6.ko
+ AUTOLOAD:=$(call AutoLoad,20,eeprom_93cx6)
+endef
+
+define KernelPackage/eeprom-93cx6/description
+ Kernel module for EEPROM 93CX6 support
+endef
+
+$(eval $(call KernelPackage,eeprom-93cx6))
+
+
+define KernelPackage/eeprom-at24
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=EEPROM AT24 support
+ KCONFIG:=CONFIG_EEPROM_AT24
+ DEPENDS:=+kmod-i2c-core
+ FILES:=$(LINUX_DIR)/drivers/misc/eeprom/at24.ko
+ AUTOLOAD:=$(call AutoLoad,60,at24)
+endef
+
+define KernelPackage/eeprom-at24/description
+ Kernel module for most I2C EEPROMs
+endef
+
+$(eval $(call KernelPackage,eeprom-at24))
+
+
+define KernelPackage/eeprom-at25
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=EEPROM AT25 support
+ KCONFIG:=CONFIG_EEPROM_AT25
+ FILES:=$(LINUX_DIR)/drivers/misc/eeprom/at25.ko
+ AUTOLOAD:=$(call AutoLoad,61,at25)
+endef
+
+define KernelPackage/eeprom-at25/description
+ Kernel module for most SPI EEPROMs
+endef
+
+$(eval $(call KernelPackage,eeprom-at25))
+
+
+define KernelPackage/gpio-dev
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=Generic GPIO char device support
+ DEPENDS:=@GPIO_SUPPORT
+ KCONFIG:=CONFIG_GPIO_DEVICE
+ FILES:=$(LINUX_DIR)/drivers/char/gpio_dev.ko
+ AUTOLOAD:=$(call AutoLoad,40,gpio_dev)
+endef
+
+define KernelPackage/gpio-dev/description
+ Kernel module to allows control of GPIO pins using a character device.
+endef
+
+$(eval $(call KernelPackage,gpio-dev))
+
+
+define KernelPackage/gpio-nxp-74hc164
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=NXP 74HC164 GPIO expander support
+ KCONFIG:=CONFIG_GPIO_NXP_74HC164
+ FILES:=$(LINUX_DIR)/drivers/gpio/nxp_74hc164.ko
+ AUTOLOAD:=$(call AutoLoad,99,nxp_74hc164)
+endef
+
+define KernelPackage/gpio-nxp-74hc164/description
+ Kernel module for NXP 74HC164 GPIO expander
+endef
+
+$(eval $(call KernelPackage,gpio-nxp-74hc164))
+
+define KernelPackage/hid
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=HID Devices
+ KCONFIG:=CONFIG_HID
+ FILES:=$(LINUX_DIR)/drivers/hid/hid.ko
+ AUTOLOAD:=$(call AutoLoad,61,hid)
+ $(call AddDepends/input,+kmod-input-evdev)
+endef
+
+define KernelPackage/hid/description
+ Kernel modules for HID devices
+endef
+
+$(eval $(call KernelPackage,hid))
+
+
+define KernelPackage/input-core
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=Input device core
+ KCONFIG:=CONFIG_INPUT
+ FILES:=$(LINUX_DIR)/drivers/input/input-core.ko
+ AUTOLOAD:=$(call AutoLoad,19,input-core)
+endef
+
+define KernelPackage/input-core/description
+ Kernel modules for support of input device
+endef
+
+$(eval $(call KernelPackage,input-core))
+
+
+define KernelPackage/input-evdev
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=Input event device
+ KCONFIG:=CONFIG_INPUT_EVDEV
+ FILES:=$(LINUX_DIR)/drivers/input/evdev.ko
+ AUTOLOAD:=$(call AutoLoad,60,evdev)
+ $(call AddDepends/input)
+endef
+
+define KernelPackage/input-evdev/description
+ Kernel modules for support of input device events
+endef
+
+$(eval $(call KernelPackage,input-evdev))
+
+
+define KernelPackage/input-gpio-buttons
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=Polled GPIO buttons input device
+ DEPENDS:=@GPIO_SUPPORT +kmod-input-polldev
+ KCONFIG:= \
+ CONFIG_INPUT_GPIO_BUTTONS \
+ CONFIG_INPUT_MISC=y
+ FILES:=$(LINUX_DIR)/drivers/input/misc/gpio_buttons.ko
+ AUTOLOAD:=$(call AutoLoad,62,gpio_buttons)
+endef
+
+define KernelPackage/input-gpio-buttons/description
+ Kernel module for support polled GPIO buttons input device
+endef
+
+$(eval $(call KernelPackage,input-gpio-buttons))
+
+
+define KernelPackage/input-gpio-keys
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=GPIO key support
+ DEPENDS:= @GPIO_SUPPORT
+ KCONFIG:= \
+ CONFIG_KEYBOARD_GPIO \
+ CONFIG_INPUT_KEYBOARD=y
+ FILES:=$(LINUX_DIR)/drivers/input/keyboard/gpio_keys.ko
+ AUTOLOAD:=$(call AutoLoad,60,gpio_keys)
+ $(call AddDepends/input)
+endef
+
+define KernelPackage/input-gpio-keys/description
+ This driver implements support for buttons connected
+ to GPIO pins of various CPUs (and some other chips).
+endef
+
+$(eval $(call KernelPackage,input-gpio-keys))
+
+
+define KernelPackage/input-gpio-keys-polled
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=Polled GPIO key support
+ DEPENDS:=@GPIO_SUPPORT +kmod-input-polldev
+ KCONFIG:= \
+ CONFIG_KEYBOARD_GPIO_POLLED \
+ CONFIG_INPUT_KEYBOARD=y
+ FILES:=$(LINUX_DIR)/drivers/input/keyboard/gpio_keys_polled.ko
+ AUTOLOAD:=$(call AutoLoad,62,gpio_keys_polled)
+ $(call AddDepends/input)
+endef
+
+define KernelPackage/input-gpio-keys-polled/description
+ Kernel module for support polled GPIO keys input device
+endef
+
+$(eval $(call KernelPackage,input-gpio-keys-polled))
+
+
+define KernelPackage/input-gpio-encoder
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=GPIO rotay encoder
+ KCONFIG:=CONFIG_INPUT_GPIO_ROTARY_ENCODER
+ FILES:=$(LINUX_DIR)/drivers/input/misc/rotary_encoder.ko
+ AUTOLOAD:=$(call AutoLoad,62,rotary_encoder)
+ $(call AddDepends/input,@GPIO_SUPPORT)
+endef
+
+define KernelPackage/gpio-encoder/description
+ Kernel module to use rotary encoders connected to GPIO pins
+endef
+
+$(eval $(call KernelPackage,input-gpio-encoder))
+
+
+define KernelPackage/input-joydev
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=Joystick device support
+ KCONFIG:=CONFIG_INPUT_JOYDEV
+ FILES:=$(LINUX_DIR)/drivers/input/joydev.ko
+ AUTOLOAD:=$(call AutoLoad,62,joydev)
+ $(call AddDepends/input)
+endef
+
+define KernelPackage/input-joydev/description
+ Kernel module for joystick support
+endef
+
+$(eval $(call KernelPackage,input-joydev))
+
+
+define KernelPackage/input-polldev
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=Polled Input device support
+ KCONFIG:=CONFIG_INPUT_POLLDEV
+ FILES:=$(LINUX_DIR)/drivers/input/input-polldev.ko
+ AUTOLOAD:=$(call AutoLoad,20,input-polldev)
+ $(call AddDepends/input)
+endef
+
+define KernelPackage/input-polldev/description
+ Kernel module for support of polled input devices
+endef
+
+$(eval $(call KernelPackage,input-polldev))
+
+
+define KernelPackage/lp
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=Parallel port and line printer support
+ DEPENDS:=@BROKEN
+ KCONFIG:= \
+ CONFIG_PARPORT \
+ CONFIG_PRINTER \
+ CONFIG_PPDEV
+ FILES:= \
+ $(LINUX_DIR)/drivers/parport/parport.ko \
+ $(LINUX_DIR)/drivers/char/lp.ko \
+ $(LINUX_DIR)/drivers/char/ppdev.ko
+ AUTOLOAD:=$(call AutoLoad,50,parport lp)
+endef
+
+$(eval $(call KernelPackage,lp))
+
+
+define KernelPackage/mmc
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=MMC/SD Card Support
+ KCONFIG:= \
+ CONFIG_MMC \
+ CONFIG_MMC_BLOCK \
+ CONFIG_MMC_DEBUG=n \
+ CONFIG_MMC_UNSAFE_RESUME=n \
+ CONFIG_MMC_BLOCK_BOUNCE=y \
+ CONFIG_MMC_SDHCI=n \
+ CONFIG_MMC_TIFM_SD=n \
+ CONFIG_MMC_WBSD=n \
+ CONFIG_SDIO_UART=n
+ FILES:= \
+ $(LINUX_DIR)/drivers/mmc/core/mmc_core.ko \
+ $(LINUX_DIR)/drivers/mmc/card/mmc_block.ko
+ AUTOLOAD:=$(call AutoLoad,90,mmc_core mmc_block,1)
+endef
+
+define KernelPackage/mmc/description
+ Kernel support for MMC/SD cards
+endef
+
+$(eval $(call KernelPackage,mmc))
+
+
+define KernelPackage/oprofile
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=OProfile profiling support
+ KCONFIG:=CONFIG_OPROFILE
+ FILES:=$(LINUX_DIR)/arch/$(LINUX_KARCH)/oprofile/oprofile.ko
+ DEPENDS:=@KERNEL_PROFILING
+endef
+
+define KernelPackage/oprofile/description
+ Kernel module for support for oprofile system profiling.
+endef
+
+$(eval $(call KernelPackage,oprofile))
+
+
+define KernelPackage/rfkill
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=RF switch subsystem support
+ KCONFIG:= \
+ CONFIG_RFKILL \
+ CONFIG_RFKILL_INPUT=y \
+ CONFIG_RFKILL_LEDS=y
+ FILES:= \
+ $(LINUX_DIR)/net/rfkill/rfkill.ko
+ AUTOLOAD:=$(call AutoLoad,20,rfkill)
+ $(call SetDepends/rfkill)
+endef
+
+define KernelPackage/rfkill/description
+ Say Y here if you want to have control over RF switches
+ found on many WiFi and Bluetooth cards.
+endef
+
+$(eval $(call KernelPackage,rfkill))
+
+
+define KernelPackage/softdog
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=Software watchdog driver
+ KCONFIG:=CONFIG_SOFT_WATCHDOG
+ FILES:=$(LINUX_DIR)/drivers/$(WATCHDOG_DIR)/softdog.ko
+ AUTOLOAD:=$(call AutoLoad,50,softdog)
+endef
+
+define KernelPackage/softdog/description
+ Software watchdog driver
+endef
+
+$(eval $(call KernelPackage,softdog))
+
+
+define KernelPackage/ssb
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=Silicon Sonics Backplane glue code
+ DEPENDS:=@PCI_SUPPORT @!TARGET_brcm47xx @!TARGET_brcm63xx
+ KCONFIG:=\
+ CONFIG_SSB \
+ CONFIG_SSB_B43_PCI_BRIDGE=y \
+ CONFIG_SSB_DRIVER_MIPS=n \
+ CONFIG_SSB_DRIVER_PCICORE=y \
+ CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y \
+ CONFIG_SSB_PCIHOST=y \
+ CONFIG_SSB_PCIHOST_POSSIBLE=y \
+ CONFIG_SSB_POSSIBLE=y \
+ CONFIG_SSB_SPROM=y \
+ CONFIG_SSB_SILENT=y
+ FILES:=$(LINUX_DIR)/drivers/ssb/ssb.ko
+ AUTOLOAD:=$(call AutoLoad,29,ssb)
+endef
+
+define KernelPackage/ssb/description
+ Silicon Sonics Backplane glue code.
+endef
+
+$(eval $(call KernelPackage,ssb))
+
+
+define KernelPackage/bcma
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=BCMA support
+ DEPENDS:=@PCI_SUPPORT @!TARGET_brcm47xx
+ KCONFIG:=\
+ CONFIG_BCMA \
+ CONFIG_BCMA_POSSIBLE=y \
+ CONFIG_BCMA_BLOCKIO=y \
+ CONFIG_BCMA_HOST_PCI_POSSIBLE=y \
+ CONFIG_BCMA_HOST_PCI=y \
+ CONFIG_BCMA_DRIVER_MIPS=n \
+ CONFIG_BCMA_DRIVER_PCI_HOSTMODE=n \
+ CONFIG_BCMA_DRIVER_GMAC_CMN=n \
+ CONFIG_BCMA_DEBUG=n
+ FILES:=$(LINUX_DIR)/drivers/bcma/bcma.ko
+ AUTOLOAD:=$(call AutoLoad,29,bcma)
+endef
+
+define KernelPackage/bcma/description
+ Bus driver for Broadcom specific Advanced Microcontroller Bus Architecture.
+endef
+
+$(eval $(call KernelPackage,bcma))
+
+
+define KernelPackage/wdt-omap
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=OMAP Watchdog timer
+ DEPENDS:=@(TARGET_omap24xx||TARGET_omap35xx)
+ KCONFIG:=CONFIG_OMAP_WATCHDOG
+ FILES:=$(LINUX_DIR)/drivers/$(WATCHDOG_DIR)/omap_wdt.ko
+ AUTOLOAD:=$(call AutoLoad,50,omap_wdt.ko)
+endef
+
+define KernelPackage/wdt-omap/description
+ Kernel module for TI omap watchdog timer.
+endef
+
+$(eval $(call KernelPackage,wdt-omap))
+
+
+define KernelPackage/wdt-orion
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=Marvell Orion Watchdog timer
+ DEPENDS:=@TARGET_orion||@TARGET_kirkwood
+ KCONFIG:=CONFIG_ORION_WATCHDOG
+ FILES:=$(LINUX_DIR)/drivers/$(WATCHDOG_DIR)/orion_wdt.ko
+ AUTOLOAD:=$(call AutoLoad,50,orion_wdt)
+endef
+
+define KernelPackage/wdt-orion/description
+ Kernel module for Marvell orion watchdog timer.
+endef
+
+$(eval $(call KernelPackage,wdt-orion))
+
+
+define KernelPackage/booke-wdt
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=PowerPC Book-E Watchdog Timer
+ DEPENDS:=@(TARGET_mpc85xx||TARGET_ppc40x||TARGET_ppc44x)
+ KCONFIG:=CONFIG_BOOKE_WDT
+ FILES:=$(LINUX_DIR)/drivers/$(WATCHDOG_DIR)/booke_wdt.ko
+ AUTOLOAD:=$(call AutoLoad,50,booke_wdt)
+endef
+
+define KernelPackage/booke-wdt/description
+ Kernel module for PowerPC Book-E Watchdog Timer.
+endef
+
+$(eval $(call KernelPackage,booke-wdt))
+
+
+define KernelPackage/pwm
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=PWM generic API
+ KCONFIG:=CONFIG_GENERIC_PWM
+ FILES:=$(LINUX_DIR)/drivers/pwm/pwm.ko
+ AUTOLOAD:=$(call AutoLoad,50,pwm)
+endef
+
+define KernelPackage/pwm/description
+ Kernel module that implement a generic PWM API
+endef
+
+$(eval $(call KernelPackage,pwm))
+
+
+define KernelPackage/pwm-gpio
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=PWM over GPIO
+ DEPENDS:=+kmod-pwm
+ KCONFIG:=CONFIG_GPIO_PWM
+ FILES:=$(LINUX_DIR)/drivers/pwm/gpio-pwm.ko
+ AUTOLOAD:=$(call AutoLoad,51,gpio-pwm)
+endef
+
+define KernelPackage/pwm-gpio/description
+ Kernel module to models a single-channel PWM device using a timer and a GPIO pin
+endef
+
+$(eval $(call KernelPackage,pwm-gpio))
+
+
+define KernelPackage/rtc-marvell
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=Marvell SoC built-in RTC support
+ $(call AddDepends/rtc)
+ DEPENDS+=@TARGET_kirkwood||TARGET_orion
+ KCONFIG:=CONFIG_RTC_DRV_MV
+ FILES:=$(LINUX_DIR)/drivers/rtc/rtc-mv.ko
+ AUTOLOAD:=$(call AutoLoad,60,rtc-mv)
+endef
+
+define KernelPackage/rtc-marvell/description
+ Kernel module for Marvell SoC built-in RTC.
+endef
+
+$(eval $(call KernelPackage,rtc-marvell))
+
+define KernelPackage/rtc-pcf8563
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=Philips PCF8563/Epson RTC8564 RTC support
+ $(call AddDepends/rtc)
+ KCONFIG:=CONFIG_RTC_DRV_PCF8563
+ FILES:=$(LINUX_DIR)/drivers/rtc/rtc-pcf8563.ko
+ AUTOLOAD:=$(call AutoLoad,60,rtc-pcf8563)
+endef
+
+define KernelPackage/rtc-pcf8563/description
+ Kernel module for Philips PCF8563 RTC chip.
+ The Epson RTC8564 should work as well.
+endef
+
+$(eval $(call KernelPackage,rtc-pcf8563))
+
+
+define KernelPackage/rtc-pcf2123
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=Philips PCF2123 RTC support
+ $(call AddDepends/rtc)
+ KCONFIG:=CONFIG_RTC_DRV_PCF2123
+ FILES:=$(LINUX_DIR)/drivers/rtc/rtc-pcf2123.ko
+ AUTOLOAD:=$(call AutoLoad,60,rtc-pcf2123)
+endef
+
+define KernelPackage/rtc-pcf2123/description
+ Kernel module for Philips PCF2123 RTC chip.
+endef
+
+$(eval $(call KernelPackage,rtc-pcf2123))
+
+define KernelPackage/rtc-pt7c4338
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=Pericom PT7C4338 RTC support
+ $(call AddDepends/rtc,+kmod-i2c-core)
+ KCONFIG:=CONFIG_RTC_DRV_PT7C4338
+ FILES:=$(LINUX_DIR)/drivers/rtc/rtc-pt7c4338.ko
+ AUTOLOAD:=$(call AutoLoad,60,rtc-pt7c4338)
+endef
+
+define KernelPackage/rtc-pt7c4338/description
+ Kernel module for Pericom PT7C4338 i2c RTC chip.
+endef
+
+$(eval $(call KernelPackage,rtc-pt7c4338))
+
+
+define KernelPackage/mtdtests
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=MTD subsystem tests
+ KCONFIG:=CONFIG_MTD_TESTS
+ FILES:=\
+ $(LINUX_DIR)/drivers/mtd/tests/mtd_nandecctest.ko \
+ $(LINUX_DIR)/drivers/mtd/tests/mtd_oobtest.ko \
+ $(LINUX_DIR)/drivers/mtd/tests/mtd_pagetest.ko \
+ $(LINUX_DIR)/drivers/mtd/tests/mtd_readtest.ko \
+ $(LINUX_DIR)/drivers/mtd/tests/mtd_speedtest.ko \
+ $(LINUX_DIR)/drivers/mtd/tests/mtd_stresstest.ko \
+ $(LINUX_DIR)/drivers/mtd/tests/mtd_subpagetest.ko \
+ $(LINUX_DIR)/drivers/mtd/tests/mtd_torturetest.ko
+endef
+
+define KernelPackage/mtdtests/description
+ Kernel modules for MTD subsystem/driver testing.
+endef
+
+$(eval $(call KernelPackage,mtdtests))
+
+
+define KernelPackage/nand
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=NAND flash support
+ DEPENDS:=@!LINUX_2_6_39
+ KCONFIG:=CONFIG_MTD_NAND \
+ CONFIG_MTD_NAND_IDS \
+ CONFIG_MTD_NAND_ECC
+ FILES:= \
+ $(LINUX_DIR)/drivers/mtd/nand/nand_ids.ko \
+ $(LINUX_DIR)/drivers/mtd/nand/nand_ecc.ko \
+ $(LINUX_DIR)/drivers/mtd/nand/nand.ko
+ AUTOLOAD:=$(call AutoLoad,20,nand_ids nand_ecc nand)
+endef
+
+define KernelPackage/nand/description
+ Kernel module for NAND support.
+endef
+
+$(eval $(call KernelPackage,nand))
+
+
+define KernelPackage/nandsim
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=NAND simulator
+ DEPENDS:=+kmod-nand
+ KCONFIG:=CONFIG_MTD_NAND_NANDSIM
+ FILES:=$(LINUX_DIR)/drivers/mtd/nand/nandsim.ko
+endef
+
+define KernelPackage/nandsim/description
+ Kernel module for NAND flash simulation.
+endef
+
+$(eval $(call KernelPackage,nandsim))
+
+define KernelPackage/serial-8250
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=8250 UARTs
+ KCONFIG:= CONFIG_SERIAL_8250 \
+ CONFIG_SERIAL_8250_NR_UARTS=16 \
+ CONFIG_SERIAL_8250_RUNTIME_UARTS=16 \
+ CONFIG_SERIAL_8250_EXTENDED=y \
+ CONFIG_SERIAL_8250_MANY_PORTS=y \
+ CONFIG_SERIAL_8250_SHARE_IRQ=y \
+ CONFIG_SERIAL_8250_DETECT_IRQ=n \
+ CONFIG_SERIAL_8250_RSA=n
+ FILES:=$(LINUX_DIR)/drivers/tty/serial/8250/8250.ko
+endef
+
+define KernelPackage/serial-8250/description
+ Kernel module for 8250 UART based serial ports.
+endef
+
+$(eval $(call KernelPackage,serial-8250))
+
+
+define KernelPackage/acpi-button
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=ACPI Button Support
+ DEPENDS:=@(TARGET_x86_generic||TARGET_x86_kvm_guest||TARGET_x86_xen_domu) +kmod-input-evdev
+ KCONFIG:=CONFIG_ACPI_BUTTON
+ FILES:=$(LINUX_DIR)/drivers/acpi/button.ko
+ AUTOLOAD:=$(call AutoLoad,06,button)
+endef
+
+define KernelPackage/acpi-button/description
+ Kernel module for ACPI Button support
+endef
+
+$(eval $(call KernelPackage,acpi-button))
+
+define KernelPackage/regmap
+ SUBMENU:=$(OTHER_MENU)
+ TITLE:=Generic register map support
+ KCONFIG:=CONFIG_REGMAP=y \
+ CONFIG_REGMAP_SPI \
+ CONFIG_REGMAP_I2C
+ FILES:=$(LINUX_DIR)/drivers/base/regmap/regmap-i2c.ko \
+ $(LINUX_DIR)/drivers/base/regmap/regmap-spi.ko
+ AUTOLOAD:=$(call AutoLoad,10,regmap-i2c regmap-spi)
+endef
+
+define KernelPackage/regmap/description
+ Generic register map support
+endef
+
+$(eval $(call KernelPackage,regmap))
diff --git a/package/kernel/modules/pcmcia.mk b/package/kernel/modules/pcmcia.mk
new file mode 100644
index 000000000..cac727719
--- /dev/null
+++ b/package/kernel/modules/pcmcia.mk
@@ -0,0 +1,80 @@
+#
+# Copyright (C) 2006-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+PCMCIA_MENU:=PCMCIA support
+
+define KernelPackage/pcmcia-core
+ SUBMENU:=$(PCMCIA_MENU)
+ TITLE:=PCMCIA/CardBus support
+ DEPENDS:=@PCMCIA_SUPPORT
+ KCONFIG:= \
+ CONFIG_PCMCIA \
+ CONFIG_CARDBUS \
+ CONFIG_PCCARD \
+ PCMCIA_DEBUG=n
+ FILES:= \
+ $(LINUX_DIR)/drivers/pcmcia/pcmcia_core.ko \
+ $(LINUX_DIR)/drivers/pcmcia/pcmcia.ko
+ AUTOLOAD:=$(call AutoLoad,25,pcmcia_core pcmcia)
+endef
+
+define KernelPackage/pcmcia-core/description
+ Kernel support for PCMCIA/CardBus controllers
+endef
+
+$(eval $(call KernelPackage,pcmcia-core))
+
+define KernelPackage/pcmcia-rsrc
+ SUBMENU:=$(PCMCIA_MENU)
+ TITLE:=PCMCIA resource support
+ DEPENDS:=kmod-pcmcia-core
+ KCONFIG:=CONFIG_PCCARD_NONSTATIC=y
+# For Linux 2.6.35+
+ifneq ($(wildcard $(LINUX_DIR)/drivers/pcmcia/pcmcia_rsrc.ko),)
+ FILES:=$(LINUX_DIR)/drivers/pcmcia/pcmcia_rsrc.ko
+ AUTOLOAD:=$(call AutoLoad,26,pcmcia_rsrc)
+else
+ FILES:=$(LINUX_DIR)/drivers/pcmcia/rsrc_nonstatic.ko
+ AUTOLOAD:=$(call AutoLoad,26,rsrc_nonstatic)
+endif
+endef
+
+define KernelPackage/pcmcia-rsrc/description
+ Kernel support for PCMCIA resource allocation
+endef
+
+$(eval $(call KernelPackage,pcmcia-rsrc))
+
+
+define KernelPackage/pcmcia-yenta
+ SUBMENU:=$(PCMCIA_MENU)
+ TITLE:=yenta socket driver
+ DEPENDS:=kmod-pcmcia-rsrc
+ KCONFIG:=CONFIG_YENTA
+ FILES:=$(LINUX_DIR)/drivers/pcmcia/yenta_socket.ko
+ AUTOLOAD:=$(call AutoLoad,41,pcmcia_rsrc yenta_socket)
+endef
+
+$(eval $(call KernelPackage,pcmcia-yenta))
+
+
+define KernelPackage/pcmcia-serial
+ SUBMENU:=$(PCMCIA_MENU)
+ TITLE:=Serial devices support
+ DEPENDS:=kmod-pcmcia-core
+ KCONFIG:= \
+ CONFIG_PCMCIA_SERIAL_CS \
+ CONFIG_SERIAL_8250_CS
+ FILES:=$(LINUX_DIR)/drivers/tty/serial/8250/serial_cs.ko
+ AUTOLOAD:=$(call AutoLoad,45,serial_cs)
+endef
+
+define KernelPackage/pcmcia-serial/description
+ Kernel support for PCMCIA/CardBus serial devices
+endef
+
+$(eval $(call KernelPackage,pcmcia-serial))
diff --git a/package/kernel/modules/sound.mk b/package/kernel/modules/sound.mk
new file mode 100644
index 000000000..f054d870c
--- /dev/null
+++ b/package/kernel/modules/sound.mk
@@ -0,0 +1,184 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+SOUND_MENU:=Sound Support
+
+define KernelPackage/pcspkr
+ SUBMENU:=$(SOUND_MENU)
+ TITLE:=PC speaker support
+ KCONFIG:=CONFIG_INPUT_PCSPKR
+ FILES:=$(LINUX_DIR)/drivers/input/misc/pcspkr.ko
+ AUTOLOAD:=$(call AutoLoad,50,pcspkr)
+endef
+
+define KernelPackage/pcspkr/description
+ This enables sounds (tones) through the pc speaker
+endef
+
+$(eval $(call KernelPackage,pcspkr))
+
+
+# allow targets to override the soundcore stuff
+SOUNDCORE_LOAD ?= \
+ soundcore \
+ snd \
+ snd-page-alloc \
+ snd-hwdep \
+ snd-seq-device \
+ snd-rawmidi \
+ snd-timer \
+ snd-pcm \
+ snd-mixer-oss \
+ snd-pcm-oss
+
+SOUNDCORE_FILES ?= \
+ $(LINUX_DIR)/sound/soundcore.ko \
+ $(LINUX_DIR)/sound/core/snd.ko \
+ $(LINUX_DIR)/sound/core/snd-page-alloc.ko \
+ $(LINUX_DIR)/sound/core/snd-hwdep.ko \
+ $(LINUX_DIR)/sound/core/seq/snd-seq-device.ko \
+ $(LINUX_DIR)/sound/core/snd-rawmidi.ko \
+ $(LINUX_DIR)/sound/core/snd-timer.ko \
+ $(LINUX_DIR)/sound/core/snd-pcm.ko \
+ $(LINUX_DIR)/sound/core/oss/snd-mixer-oss.ko \
+ $(LINUX_DIR)/sound/core/oss/snd-pcm-oss.ko
+
+define KernelPackage/sound-core
+ SUBMENU:=$(SOUND_MENU)
+ TITLE:=Sound support
+ DEPENDS:=@AUDIO_SUPPORT
+ KCONFIG:= \
+ CONFIG_SOUND \
+ CONFIG_SND \
+ CONFIG_SND_HWDEP \
+ CONFIG_SND_RAWMIDI \
+ CONFIG_SND_TIMER \
+ CONFIG_SND_PCM \
+ CONFIG_SND_SEQUENCER \
+ CONFIG_SND_VIRMIDI \
+ CONFIG_SND_SEQ_DUMMY \
+ CONFIG_SND_SEQUENCER_OSS=y \
+ CONFIG_HOSTAUDIO \
+ CONFIG_SND_PCM_OSS \
+ CONFIG_SND_MIXER_OSS \
+ CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+ FILES:=$(SOUNDCORE_FILES)
+ AUTOLOAD:=$(call AutoLoad,30,$(SOUNDCORE_LOAD))
+ $(call AddDepends/input)
+endef
+
+define KernelPackage/sound-core/uml
+ FILES:= \
+ $(LINUX_DIR)/sound/soundcore.ko \
+ $(LINUX_DIR)/arch/um/drivers/hostaudio.ko
+ AUTOLOAD:=$(call AutoLoad,30,soundcore hostaudio)
+endef
+
+define KernelPackage/sound-core/description
+ Kernel modules for sound support
+endef
+
+$(eval $(call KernelPackage,sound-core))
+
+
+define AddDepends/sound
+ SUBMENU:=$(SOUND_MENU)
+ DEPENDS+=kmod-sound-core $(1) @!TARGET_uml
+endef
+
+
+define KernelPackage/ac97
+ TITLE:=ac97 controller
+ KCONFIG:=CONFIG_SND_AC97_CODEC
+ FILES:= \
+ $(LINUX_DIR)/sound/ac97_bus.ko \
+ $(LINUX_DIR)/sound/pci/ac97/snd-ac97-codec.ko
+ AUTOLOAD:=$(call AutoLoad,35,ac97_bus snd-ac97-codec)
+ $(call AddDepends/sound)
+endef
+
+define KernelPackage/ac97/description
+ The ac97 controller
+endef
+
+$(eval $(call KernelPackage,ac97))
+
+
+define KernelPackage/sound-seq
+ TITLE:=Sequencer support
+ FILES:= \
+ $(LINUX_DIR)/sound/core/seq/snd-seq.ko \
+ $(LINUX_DIR)/sound/core/seq/snd-seq-midi-event.ko \
+ $(LINUX_DIR)/sound/core/seq/snd-seq-midi.ko
+ AUTOLOAD:=$(call AutoLoad,35,snd-seq snd-seq-midi-event snd-seq-midi)
+ $(call AddDepends/sound)
+endef
+
+define KernelPackage/sound-seq/description
+ Kernel modules for sequencer support
+endef
+
+$(eval $(call KernelPackage,sound-seq))
+
+
+define KernelPackage/sound-i8x0
+ TITLE:=Intel/SiS/nVidia/AMD/ALi AC97 Controller
+ DEPENDS:=+kmod-ac97
+ KCONFIG:=CONFIG_SND_INTEL8X0
+ FILES:=$(LINUX_DIR)/sound/pci/snd-intel8x0.ko
+ AUTOLOAD:=$(call AutoLoad,36,snd-intel8x0)
+ $(call AddDepends/sound)
+endef
+
+define KernelPackage/sound-i8x0/description
+ support for the integrated AC97 sound device on motherboards
+ with Intel/SiS/nVidia/AMD chipsets, or ALi chipsets using
+ the M5455 Audio Controller.
+endef
+
+$(eval $(call KernelPackage,sound-i8x0))
+
+
+define KernelPackage/sound-cs5535audio
+ TITLE:=CS5535 PCI Controller
+ DEPENDS:=+kmod-ac97
+ KCONFIG:=CONFIG_SND_CS5535AUDIO
+ FILES:=$(LINUX_DIR)/sound/pci/cs5535audio/snd-cs5535audio.ko
+ AUTOLOAD:=$(call AutoLoad,36,snd-cs5535audio)
+ $(call AddDepends/sound)
+endef
+
+define KernelPackage/sound-cs5535audio/description
+ support for the integrated AC97 sound device on olpc
+endef
+
+$(eval $(call KernelPackage,sound-cs5535audio))
+
+
+define KernelPackage/sound-soc-core
+ TITLE:=SoC sound support
+ KCONFIG:= \
+ CONFIG_SND_SOC \
+ CONFIG_SND_SOC_ALL_CODECS=n
+ FILES:=$(LINUX_DIR)/sound/soc/snd-soc-core.ko
+ AUTOLOAD:=$(call AutoLoad,55, snd-soc-core)
+ $(call AddDepends/sound)
+endef
+
+$(eval $(call KernelPackage,sound-soc-core))
+
+
+define KernelPackage/sound-soc-ac97
+ TITLE:=AC97 Codec support
+ KCONFIG:=CONFIG_SND_SOC_AC97_CODEC
+ FILES:=$(LINUX_DIR)/sound/soc/codecs/snd-soc-ac97.ko
+ AUTOLOAD:=$(call AutoLoad,57,snd-soc-ac97)
+ DEPENDS:=+kmod-ac97 +kmod-sound-soc-core
+ $(call AddDepends/sound)
+endef
+
+$(eval $(call KernelPackage,sound-soc-ac97))
diff --git a/package/kernel/modules/spi.mk b/package/kernel/modules/spi.mk
new file mode 100644
index 000000000..416209825
--- /dev/null
+++ b/package/kernel/modules/spi.mk
@@ -0,0 +1,90 @@
+#
+# Copyright (C) 2006-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+SPI_MENU:=SPI Support
+
+define KernelPackage/mmc-spi
+ SUBMENU:=$(SPI_MENU)
+ TITLE:=MMC/SD over SPI Support
+ DEPENDS:=+kmod-mmc +kmod-lib-crc-itu-t +kmod-lib-crc7
+ KCONFIG:=CONFIG_MMC_SPI \
+ CONFIG_SPI=y \
+ CONFIG_SPI_MASTER=y
+ FILES:=$(LINUX_DIR)/drivers/mmc/host/mmc_spi.ko
+ AUTOLOAD:=$(call AutoLoad,90,mmc_spi)
+endef
+
+define KernelPackage/mmc-spi/description
+ Kernel support for MMC/SD over SPI
+endef
+
+$(eval $(call KernelPackage,mmc-spi))
+
+
+define KernelPackage/spi-bitbang
+ SUBMENU:=$(SPI_MENU)
+ TITLE:=Serial Peripheral Interface bitbanging library
+ KCONFIG:=CONFIG_SPI_BITBANG \
+ CONFIG_SPI=y \
+ CONFIG_SPI_MASTER=y
+ FILES:=$(LINUX_DIR)/drivers/spi/spi-bitbang.ko
+ AUTOLOAD:=$(call AutoLoad,91,spi-bitbang)
+endef
+
+define KernelPackage/spi-bitbang/description
+ This package contains the SPI bitbanging library
+endef
+
+$(eval $(call KernelPackage,spi-bitbang))
+
+
+define KernelPackage/spi-gpio-old
+ SUBMENU:=$(SPI_MENU)
+ TITLE:=Old GPIO based bitbanging SPI controller (DEPRECATED)
+ DEPENDS:=@GPIO_SUPPORT +kmod-spi-bitbang
+ KCONFIG:=CONFIG_SPI_GPIO_OLD
+ FILES:=$(LINUX_DIR)/drivers/spi/spi_gpio_old.ko
+ AUTOLOAD:=$(call AutoLoad,92,spi_gpio_old)
+endef
+
+define KernelPackage/spi-gpio-old/description
+ This package contains the GPIO based bitbanging SPI controller driver
+endef
+
+$(eval $(call KernelPackage,spi-gpio-old))
+
+define KernelPackage/spi-gpio
+ SUBMENU:=$(SPI_MENU)
+ TITLE:=GPIO-based bitbanging SPI Master
+ DEPENDS:=@GPIO_SUPPORT +kmod-spi-bitbang
+ KCONFIG:=CONFIG_SPI_GPIO
+ FILES:=$(LINUX_DIR)/drivers/spi/spi-gpio.ko
+ AUTOLOAD:=$(call AutoLoad,92,spi-gpio)
+endef
+
+define KernelPackage/spi-gpio/description
+ This package contains the GPIO-based bitbanging SPI Master
+endef
+
+$(eval $(call KernelPackage,spi-gpio))
+
+define KernelPackage/spi-dev
+ SUBMENU:=$(SPI_MENU)
+ TITLE:=User mode SPI device driver
+ KCONFIG:=CONFIG_SPI_SPIDEV \
+ CONFIG_SPI=y \
+ CONFIG_SPI_MASTER=y
+ FILES:=$(LINUX_DIR)/drivers/spi/spidev.ko
+ AUTOLOAD:=$(call AutoLoad,93,spidev)
+endef
+
+define KernelPackage/spi-dev/description
+ This package contains the user mode SPI device driver
+endef
+
+$(eval $(call KernelPackage,spi-dev))
+
diff --git a/package/kernel/modules/usb.mk b/package/kernel/modules/usb.mk
new file mode 100644
index 000000000..a54f2aa3f
--- /dev/null
+++ b/package/kernel/modules/usb.mk
@@ -0,0 +1,899 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+USB_MENU:=USB Support
+
+USBNET_DIR:=net/usb
+USBHID_DIR?=hid/usbhid
+USBINPUT_DIR?=input/misc
+
+define KernelPackage/usb-core
+ SUBMENU:=$(USB_MENU)
+ TITLE:=Support for USB
+ DEPENDS:=@USB_SUPPORT
+ KCONFIG:=CONFIG_USB CONFIG_XPS_USB_HCD_XILINX=n CONFIG_USB_FHCI_HCD=n
+ FILES:= \
+ $(LINUX_DIR)/drivers/usb/core/usbcore.ko \
+ $(LINUX_DIR)/drivers/usb/usb-common.ko
+ AUTOLOAD:=$(call AutoLoad,20,usb-common usbcore,1)
+ $(call AddDepends/nls)
+endef
+
+define KernelPackage/usb-core/description
+ Kernel support for USB
+endef
+
+$(eval $(call KernelPackage,usb-core))
+
+
+define AddDepends/usb
+ SUBMENU:=$(USB_MENU)
+ DEPENDS+=+!TARGET_etrax:kmod-usb-core $(1)
+endef
+
+
+define KernelPackage/usb-gadget
+ TITLE:=USB Gadget support
+ KCONFIG:=CONFIG_USB_GADGET
+ FILES:=
+ AUTOLOAD:=
+ DEPENDS:=@USB_GADGET_SUPPORT
+ $(call AddDepends/usb)
+endef
+
+define KernelPackage/usb-gadget/description
+ Kernel support for USB Gadget mode.
+endef
+
+$(eval $(call KernelPackage,usb-gadget))
+
+
+define KernelPackage/usb-eth-gadget
+ TITLE:=USB Ethernet Gadget support
+ KCONFIG:= \
+ CONFIG_USB_ETH \
+ CONFIG_USB_ETH_RNDIS=y \
+ CONFIG_USB_ETH_EEM=y
+ DEPENDS:=+kmod-usb-gadget
+ FILES:=$(LINUX_DIR)/drivers/usb/gadget/g_ether.ko
+ AUTOLOAD:=$(call AutoLoad,52,g_ether)
+ $(call AddDepends/usb)
+endef
+
+define KernelPackage/usb-eth-gadget/description
+ Kernel support for USB Ethernet Gadget.
+endef
+
+$(eval $(call KernelPackage,usb-eth-gadget))
+
+
+define KernelPackage/usb-uhci
+ TITLE:=Support for UHCI controllers
+ KCONFIG:= \
+ CONFIG_USB_UHCI_ALT \
+ CONFIG_USB_UHCI_HCD
+ FILES:=$(LINUX_DIR)/drivers/usb/host/uhci-hcd.ko
+ AUTOLOAD:=$(call AutoLoad,50,uhci-hcd,1)
+ $(call AddDepends/usb)
+endef
+
+define KernelPackage/usb-uhci/description
+ Kernel support for USB UHCI controllers
+endef
+
+$(eval $(call KernelPackage,usb-uhci,1))
+
+
+define KernelPackage/usb-ohci
+ TITLE:=Support for OHCI controllers
+ DEPENDS:=+TARGET_brcm47xx:kmod-usb-brcm47xx
+ KCONFIG:= \
+ CONFIG_USB_OHCI \
+ CONFIG_USB_OHCI_HCD \
+ CONFIG_USB_OHCI_ATH79=y \
+ CONFIG_USB_OHCI_BCM63XX=y \
+ CONFIG_USB_OHCI_RT3883=y \
+ CONFIG_USB_OCTEON_OHCI=y
+ FILES:=$(LINUX_DIR)/drivers/usb/host/ohci-hcd.ko
+ AUTOLOAD:=$(call AutoLoad,50,ohci-hcd,1)
+ $(call AddDepends/usb)
+endef
+
+define KernelPackage/usb-ohci/description
+ Kernel support for USB OHCI controllers
+endef
+
+$(eval $(call KernelPackage,usb-ohci,1))
+
+
+define KernelPackage/usb2
+ TITLE:=Support for USB2 controllers
+ DEPENDS:=+TARGET_brcm47xx:kmod-usb-brcm47xx
+ KCONFIG:=CONFIG_USB_EHCI_HCD \
+ CONFIG_USB_EHCI_ATH79=y \
+ CONFIG_USB_EHCI_BCM63XX=y \
+ CONFIG_USB_EHCI_RT3883=y \
+ CONFIG_USB_OCTEON_EHCI=y \
+ CONFIG_USB_EHCI_FSL=n
+ FILES:=$(LINUX_DIR)/drivers/usb/host/ehci-hcd.ko
+ AUTOLOAD:=$(call AutoLoad,40,ehci-hcd,1)
+ $(call AddDepends/usb)
+endef
+
+define KernelPackage/usb2/description
+ Kernel support for USB2 (EHCI) controllers
+endef
+
+$(eval $(call KernelPackage,usb2))
+
+
+define KernelPackage/usb-acm
+ TITLE:=Support for modems/isdn controllers
+ KCONFIG:=CONFIG_USB_ACM
+ FILES:=$(LINUX_DIR)/drivers/usb/class/cdc-acm.ko
+ AUTOLOAD:=$(call AutoLoad,60,cdc-acm)
+$(call AddDepends/usb)
+endef
+
+define KernelPackage/usb-acm/description
+ Kernel support for USB ACM devices (modems/isdn controllers)
+endef
+
+$(eval $(call KernelPackage,usb-acm))
+
+
+define KernelPackage/usb-audio
+ TITLE:=Support for USB audio devices
+ KCONFIG:= \
+ CONFIG_USB_AUDIO \
+ CONFIG_SND_USB_AUDIO
+ $(call AddDepends/usb)
+ $(call AddDepends/sound)
+# For Linux 2.6.35+
+ifneq ($(wildcard $(LINUX_DIR)/sound/usb/snd-usbmidi-lib.ko),)
+ FILES:= \
+ $(LINUX_DIR)/sound/usb/snd-usbmidi-lib.ko \
+ $(LINUX_DIR)/sound/usb/snd-usb-audio.ko
+ AUTOLOAD:=$(call AutoLoad,60,snd-usbmidi-lib snd-usb-audio)
+else
+ FILES:= \
+ $(LINUX_DIR)/sound/usb/snd-usb-lib.ko \
+ $(LINUX_DIR)/sound/usb/snd-usb-audio.ko
+ AUTOLOAD:=$(call AutoLoad,60,snd-usb-lib snd-usb-audio)
+endif
+endef
+
+define KernelPackage/usb-audio/description
+ Kernel support for USB audio devices
+endef
+
+$(eval $(call KernelPackage,usb-audio))
+
+
+define KernelPackage/usb-printer
+ TITLE:=Support for printers
+ KCONFIG:=CONFIG_USB_PRINTER
+ FILES:=$(LINUX_DIR)/drivers/usb/class/usblp.ko
+ AUTOLOAD:=$(call AutoLoad,60,usblp)
+ $(call AddDepends/usb)
+endef
+
+define KernelPackage/usb-printer/description
+ Kernel support for USB printers
+endef
+
+$(eval $(call KernelPackage,usb-printer))
+
+
+define KernelPackage/usb-serial
+ TITLE:=Support for USB-to-Serial converters
+ KCONFIG:=CONFIG_USB_SERIAL
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/usbserial.ko
+ AUTOLOAD:=$(call AutoLoad,60,usbserial)
+ $(call AddDepends/usb)
+endef
+
+define KernelPackage/usb-serial/description
+ Kernel support for USB-to-Serial converters
+endef
+
+$(eval $(call KernelPackage,usb-serial))
+
+
+define AddDepends/usb-serial
+ SUBMENU:=$(USB_MENU)
+ DEPENDS+=kmod-usb-serial $(1)
+endef
+
+
+define KernelPackage/usb-serial-belkin
+ TITLE:=Support for Belkin devices
+ KCONFIG:=CONFIG_USB_SERIAL_BELKIN
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/belkin_sa.ko
+ AUTOLOAD:=$(call AutoLoad,65,belkin_sa)
+ $(call AddDepends/usb-serial)
+endef
+
+define KernelPackage/usb-serial-belkin/description
+ Kernel support for Belkin USB-to-Serial converters
+endef
+
+$(eval $(call KernelPackage,usb-serial-belkin))
+
+
+define KernelPackage/usb-serial-ch341
+ TITLE:=Support for CH341 devices
+ KCONFIG:=CONFIG_USB_SERIAL_CH341
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/ch341.ko
+ AUTOLOAD:=$(call AutoLoad,65,ch341)
+ $(call AddDepends/usb-serial)
+endef
+
+define KernelPackage/usb-serial-ch341/description
+ Kernel support for Winchiphead CH341 USB-to-Serial converters
+endef
+
+$(eval $(call KernelPackage,usb-serial-ch341))
+
+
+define KernelPackage/usb-serial-ftdi
+ TITLE:=Support for FTDI devices
+ KCONFIG:=CONFIG_USB_SERIAL_FTDI_SIO
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/ftdi_sio.ko
+ AUTOLOAD:=$(call AutoLoad,65,ftdi_sio)
+ $(call AddDepends/usb-serial)
+endef
+
+define KernelPackage/usb-serial-ftdi/description
+ Kernel support for FTDI USB-to-Serial converters
+endef
+
+$(eval $(call KernelPackage,usb-serial-ftdi))
+
+
+define KernelPackage/usb-serial-ti-usb
+ TITLE:=Support for TI USB 3410/5052
+ KCONFIG:=CONFIG_USB_SERIAL_TI
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/ti_usb_3410_5052.ko
+ AUTOLOAD:=$(call AutoLoad,65,ti_usb_3410_5052)
+ $(call AddDepends/usb-serial)
+endef
+
+define KernelPackage/usb-serial-ti-usb/description
+ Kernel support for TI USB 3410/5052 devices
+endef
+
+$(eval $(call KernelPackage,usb-serial-ti-usb))
+
+
+define KernelPackage/usb-serial-ipw
+ TITLE:=Support for IPWireless 3G devices
+ KCONFIG:=CONFIG_USB_SERIAL_IPW
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/ipw.ko
+ AUTOLOAD:=$(call AutoLoad,65,ipw)
+ $(call AddDepends/usb-serial)
+endef
+
+$(eval $(call KernelPackage,usb-serial-ipw))
+
+
+define KernelPackage/usb-serial-mct
+ TITLE:=Support for Magic Control Tech. devices
+ KCONFIG:=CONFIG_USB_SERIAL_MCT_U232
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/mct_u232.ko
+ AUTOLOAD:=$(call AutoLoad,65,mct_u232)
+ $(call AddDepends/usb-serial)
+endef
+
+define KernelPackage/usb-serial-mct/description
+ Kernel support for Magic Control Technology USB-to-Serial converters
+endef
+
+$(eval $(call KernelPackage,usb-serial-mct))
+
+
+define KernelPackage/usb-serial-mos7720
+ TITLE:=Support for Moschip MOS7720 devices
+ KCONFIG:=CONFIG_USB_SERIAL_MOS7720
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/mos7720.ko
+ AUTOLOAD:=$(call AutoLoad,65,mos7720)
+ $(call AddDepends/usb-serial)
+endef
+
+define KernelPackage/usb-serial-mos7720/description
+ Kernel support for Moschip MOS7720 USB-to-Serial converters
+endef
+
+$(eval $(call KernelPackage,usb-serial-mos7720))
+
+
+define KernelPackage/usb-serial-pl2303
+ TITLE:=Support for Prolific PL2303 devices
+ KCONFIG:=CONFIG_USB_SERIAL_PL2303
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/pl2303.ko
+ AUTOLOAD:=$(call AutoLoad,65,pl2303)
+ $(call AddDepends/usb-serial)
+endef
+
+define KernelPackage/usb-serial-pl2303/description
+ Kernel support for Prolific PL2303 USB-to-Serial converters
+endef
+
+$(eval $(call KernelPackage,usb-serial-pl2303))
+
+
+define KernelPackage/usb-serial-cp210x
+ TITLE:=Support for Silicon Labs cp210x devices
+ KCONFIG:=CONFIG_USB_SERIAL_CP210X
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/cp210x.ko
+ AUTOLOAD:=$(call AutoLoad,65,cp210x)
+ $(call AddDepends/usb-serial)
+endef
+
+define KernelPackage/usb-serial-cp210x/description
+ Kernel support for Silicon Labs cp210x USB-to-Serial converters
+endef
+
+$(eval $(call KernelPackage,usb-serial-cp210x))
+
+
+define KernelPackage/usb-serial-ark3116
+ TITLE:=Support for ArkMicroChips ARK3116 devices
+ KCONFIG:=CONFIG_USB_SERIAL_ARK3116
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/ark3116.ko
+ AUTOLOAD:=$(call AutoLoad,65,ark3116)
+ $(call AddDepends/usb-serial)
+endef
+
+define KernelPackage/usb-serial-ark3116/description
+ Kernel support for ArkMicroChips ARK3116 USB-to-Serial converters
+endef
+
+$(eval $(call KernelPackage,usb-serial-ark3116))
+
+
+define KernelPackage/usb-serial-oti6858
+ TITLE:=Support for Ours Technology OTI6858 devices
+ KCONFIG:=CONFIG_USB_SERIAL_OTI6858
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/oti6858.ko
+ AUTOLOAD:=$(call AutoLoad,65,oti6858)
+ $(call AddDepends/usb-serial)
+endef
+
+define KernelPackage/usb-serial-oti6858/description
+ Kernel support for Ours Technology OTI6858 USB-to-Serial converters
+endef
+
+$(eval $(call KernelPackage,usb-serial-oti6858))
+
+
+define KernelPackage/usb-serial-sierrawireless
+ TITLE:=Support for Sierra Wireless devices
+ KCONFIG:=CONFIG_USB_SERIAL_SIERRAWIRELESS
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/sierra.ko
+ AUTOLOAD:=$(call AutoLoad,65,sierra)
+ $(call AddDepends/usb-serial)
+endef
+
+define KernelPackage/usb-serial-sierrawireless/description
+ Kernel support for Sierra Wireless devices
+endef
+
+$(eval $(call KernelPackage,usb-serial-sierrawireless))
+
+
+define KernelPackage/usb-serial-motorola-phone
+ TITLE:=Support for Motorola usb phone
+ KCONFIG:=CONFIG_USB_SERIAL_MOTOROLA
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/moto_modem.ko
+ AUTOLOAD:=$(call AutoLoad,65,moto_modem)
+ $(call AddDepends/usb-serial)
+endef
+
+define KernelPackage/usb-serial-motorola-phone/description
+ Kernel support for Motorola usb phone
+endef
+
+$(eval $(call KernelPackage,usb-serial-motorola-phone))
+
+
+define KernelPackage/usb-serial-visor
+ TITLE:=Support for Handspring Visor devices
+ KCONFIG:=CONFIG_USB_SERIAL_VISOR
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/visor.ko
+ AUTOLOAD:=$(call AutoLoad,65,visor)
+ $(call AddDepends/usb-serial)
+endef
+
+define KernelPackage/usb-serial-visor/description
+ Kernel support for Handspring Visor PDAs
+endef
+
+$(eval $(call KernelPackage,usb-serial-visor))
+
+
+define KernelPackage/usb-serial-cypress-m8
+ TITLE:=Support for CypressM8 USB-Serial
+ KCONFIG:=CONFIG_USB_SERIAL_CYPRESS_M8
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/cypress_m8.ko
+ AUTOLOAD:=$(call AutoLoad,65,cypress_m8)
+ $(call AddDepends/usb-serial)
+endef
+
+define KernelPackage/usb-serial-cypress-m8/description
+ Kernel support for devices with Cypress M8 USB to Serial chip
+ (for example, the Delorme Earthmate LT-20 GPS)
+ Supported microcontrollers in the CY4601 family are:
+ CY7C63741 CY7C63742 CY7C63743 CY7C64013
+endef
+
+$(eval $(call KernelPackage,usb-serial-cypress-m8))
+
+
+define KernelPackage/usb-serial-keyspan
+ TITLE:=Support for Keyspan USB-to-Serial devices
+ KCONFIG:= \
+ CONFIG_USB_SERIAL_KEYSPAN \
+ CONFIG_USB_SERIAL_KEYSPAN_USA28 \
+ CONFIG_USB_SERIAL_KEYSPAN_USA28X \
+ CONFIG_USB_SERIAL_KEYSPAN_USA28XA \
+ CONFIG_USB_SERIAL_KEYSPAN_USA28XB \
+ CONFIG_USB_SERIAL_KEYSPAN_USA19 \
+ CONFIG_USB_SERIAL_KEYSPAN_USA18X \
+ CONFIG_USB_SERIAL_KEYSPAN_USA19W \
+ CONFIG_USB_SERIAL_KEYSPAN_USA19QW \
+ CONFIG_USB_SERIAL_KEYSPAN_USA19QI \
+ CONFIG_USB_SERIAL_KEYSPAN_MPR \
+ CONFIG_USB_SERIAL_KEYSPAN_USA49W \
+ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/keyspan.ko
+ AUTOLOAD:=$(call AutoLoad,65,keyspan)
+ $(call AddDepends/usb-serial)
+endef
+
+define KernelPackage/usb-serial-keyspan/description
+ Kernel support for Keyspan USB-to-Serial devices
+endef
+
+$(eval $(call KernelPackage,usb-serial-keyspan))
+
+
+define KernelPackage/usb-serial-wwan
+ TITLE:=Support for GSM and CDMA modems
+ KCONFIG:=CONFIG_USB_SERIAL_WWAN
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/usb_wwan.ko
+ AUTOLOAD:=$(call AutoLoad,61,usb_wwan)
+ $(call AddDepends/usb-serial)
+endef
+
+define KernelPackage/usb-serial-wwan/description
+ Kernel support for USB GSM and CDMA modems
+endef
+
+$(eval $(call KernelPackage,usb-serial-wwan))
+
+
+define KernelPackage/usb-serial-option
+ TITLE:=Support for Option HSDPA modems
+ DEPENDS:=+kmod-usb-serial-wwan
+ KCONFIG:=CONFIG_USB_SERIAL_OPTION
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/option.ko
+ AUTOLOAD:=$(call AutoLoad,65,option)
+ $(call AddDepends/usb-serial)
+endef
+
+define KernelPackage/usb-serial-option/description
+ Kernel support for Option HSDPA modems
+endef
+
+$(eval $(call KernelPackage,usb-serial-option))
+
+
+define KernelPackage/usb-serial-qualcomm
+ TITLE:=Support for Qualcomm USB serial
+ KCONFIG:=CONFIG_USB_SERIAL_QUALCOMM
+ FILES:=$(LINUX_DIR)/drivers/usb/serial/qcserial.ko
+ AUTOLOAD:=$(call AutoLoad,65,qcserial)
+ $(call AddDepends/usb-serial)
+endef
+
+define KernelPackage/usb-serial-qualcomm/description
+ Kernel support for Qualcomm USB Serial devices (Gobi)
+endef
+
+$(eval $(call KernelPackage,usb-serial-qualcomm))
+
+
+define KernelPackage/usb-storage
+ TITLE:=USB Storage support
+ DEPENDS:= +kmod-scsi-core
+ KCONFIG:=CONFIG_USB_STORAGE
+ FILES:=$(LINUX_DIR)/drivers/usb/storage/usb-storage.ko
+ AUTOLOAD:=$(call AutoLoad,60,usb-storage,1)
+ $(call AddDepends/usb)
+endef
+
+define KernelPackage/usb-storage/description
+ Kernel support for USB Mass Storage devices
+endef
+
+$(eval $(call KernelPackage,usb-storage))
+
+
+define KernelPackage/usb-storage-extras
+ SUBMENU:=$(USB_MENU)
+ TITLE:=Extra drivers for usb-storage
+ DEPENDS:=+kmod-usb-storage
+ KCONFIG:= \
+ CONFIG_USB_STORAGE_ALAUDA \
+ CONFIG_USB_STORAGE_CYPRESS_ATACB \
+ CONFIG_USB_STORAGE_DATAFAB \
+ CONFIG_USB_STORAGE_FREECOM \
+ CONFIG_USB_STORAGE_ISD200 \
+ CONFIG_USB_STORAGE_JUMPSHOT \
+ CONFIG_USB_STORAGE_KARMA \
+ CONFIG_USB_STORAGE_SDDR09 \
+ CONFIG_USB_STORAGE_SDDR55 \
+ CONFIG_USB_STORAGE_USBAT
+ FILES:= \
+ $(LINUX_DIR)/drivers/usb/storage/ums-alauda.ko \
+ $(LINUX_DIR)/drivers/usb/storage/ums-cypress.ko \
+ $(LINUX_DIR)/drivers/usb/storage/ums-datafab.ko \
+ $(LINUX_DIR)/drivers/usb/storage/ums-freecom.ko \
+ $(LINUX_DIR)/drivers/usb/storage/ums-isd200.ko \
+ $(LINUX_DIR)/drivers/usb/storage/ums-jumpshot.ko \
+ $(LINUX_DIR)/drivers/usb/storage/ums-karma.ko \
+ $(LINUX_DIR)/drivers/usb/storage/ums-sddr09.ko \
+ $(LINUX_DIR)/drivers/usb/storage/ums-sddr55.ko \
+ $(LINUX_DIR)/drivers/usb/storage/ums-usbat.ko
+ AUTOLOAD:=$(call AutoLoad,60,ums-alauda ums-cypress ums-datafab \
+ ums-freecom ums-isd200 ums-jumpshot \
+ ums-karma ums-sddr09 ums-sddr55 ums-usbat)
+endef
+
+define KernelPackage/usb-storage-extras/description
+ Say Y here if you want to have some more drivers,
+ such as for SmartMedia card readers.
+endef
+
+$(eval $(call KernelPackage,usb-storage-extras))
+
+
+define KernelPackage/usb-atm
+ TITLE:=Support for ATM on USB bus
+ DEPENDS:=+kmod-atm
+ KCONFIG:=CONFIG_USB_ATM
+ FILES:=$(LINUX_DIR)/drivers/usb/atm/usbatm.ko
+ AUTOLOAD:=$(call AutoLoad,60,usbatm)
+ $(call AddDepends/usb)
+endef
+
+define KernelPackage/usb-atm/description
+ Kernel support for USB DSL modems
+endef
+
+$(eval $(call KernelPackage,usb-atm))
+
+
+define AddDepends/usb-atm
+ SUBMENU:=$(USB_MENU)
+ DEPENDS+=kmod-usb-atm $(1)
+endef
+
+
+define KernelPackage/usb-atm-speedtouch
+ TITLE:=SpeedTouch USB ADSL modems support
+ KCONFIG:=CONFIG_USB_SPEEDTOUCH
+ FILES:=$(LINUX_DIR)/drivers/usb/atm/speedtch.ko
+ AUTOLOAD:=$(call AutoLoad,70,speedtch)
+ $(call AddDepends/usb-atm)
+endef
+
+define KernelPackage/usb-atm-speedtouch/description
+ Kernel support for SpeedTouch USB ADSL modems
+endef
+
+$(eval $(call KernelPackage,usb-atm-speedtouch))
+
+
+define KernelPackage/usb-atm-ueagle
+ TITLE:=Eagle 8051 based USB ADSL modems support
+ FILES:=$(LINUX_DIR)/drivers/usb/atm/ueagle-atm.ko
+ KCONFIG:=CONFIG_USB_UEAGLEATM
+ AUTOLOAD:=$(call AutoLoad,70,ueagle-atm)
+ $(call AddDepends/usb-atm)
+endef
+
+define KernelPackage/usb-atm-ueagle/description
+ Kernel support for Eagle 8051 based USB ADSL modems
+endef
+
+$(eval $(call KernelPackage,usb-atm-ueagle))
+
+
+define KernelPackage/usb-atm-cxacru
+ TITLE:=cxacru
+ FILES:=$(LINUX_DIR)/drivers/usb/atm/cxacru.ko
+ KCONFIG:=CONFIG_USB_CXACRU
+ AUTOLOAD:=$(call AutoLoad,70,cxacru)
+ $(call AddDepends/usb-atm)
+endef
+
+define KernelPackage/usb-atm-cxacru/description
+ Kernel support for cxacru based USB ADSL modems
+endef
+
+$(eval $(call KernelPackage,usb-atm-cxacru))
+
+
+define KernelPackage/usb-net
+ TITLE:=Kernel modules for USB-to-Ethernet convertors
+ KCONFIG:=CONFIG_USB_USBNET CONFIG_MII=y
+ AUTOLOAD:=$(call AutoLoad,60,usbnet)
+ FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/usbnet.ko
+ $(call AddDepends/usb)
+endef
+
+define KernelPackage/usb-net/description
+ Kernel modules for USB-to-Ethernet convertors
+endef
+
+$(eval $(call KernelPackage,usb-net))
+
+
+define AddDepends/usb-net
+ SUBMENU:=$(USB_MENU)
+ DEPENDS+=kmod-usb-net $(1)
+endef
+
+
+define KernelPackage/usb-net-asix
+ TITLE:=Kernel module for USB-to-Ethernet Asix convertors
+ KCONFIG:=CONFIG_USB_NET_AX8817X
+ FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/asix.ko
+ AUTOLOAD:=$(call AutoLoad,61,asix)
+ $(call AddDepends/usb-net)
+endef
+
+define KernelPackage/usb-net-asix/description
+ Kernel module for USB-to-Ethernet Asix convertors
+endef
+
+$(eval $(call KernelPackage,usb-net-asix))
+
+
+define KernelPackage/usb-net-hso
+ TITLE:=Kernel module for Option USB High Speed Mobile Devices
+ KCONFIG:=CONFIG_USB_HSO
+ FILES:= \
+ $(LINUX_DIR)/drivers/$(USBNET_DIR)/hso.ko
+ AUTOLOAD:=$(call AutoLoad,61,hso)
+ $(call AddDepends/usb-net)
+ $(call AddDepends/rfkill)
+endef
+
+define KernelPackage/usb-net-hso/description
+ Kernel module for Option USB High Speed Mobile Devices
+endef
+
+$(eval $(call KernelPackage,usb-net-hso))
+
+
+define KernelPackage/usb-net-kaweth
+ TITLE:=Kernel module for USB-to-Ethernet Kaweth convertors
+ KCONFIG:=CONFIG_USB_KAWETH
+ FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/kaweth.ko
+ AUTOLOAD:=$(call AutoLoad,61,kaweth)
+ $(call AddDepends/usb-net)
+endef
+
+define KernelPackage/usb-net-kaweth/description
+ Kernel module for USB-to-Ethernet Kaweth convertors
+endef
+
+$(eval $(call KernelPackage,usb-net-kaweth))
+
+
+define KernelPackage/usb-net-pegasus
+ TITLE:=Kernel module for USB-to-Ethernet Pegasus convertors
+ KCONFIG:=CONFIG_USB_PEGASUS
+ FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/pegasus.ko
+ AUTOLOAD:=$(call AutoLoad,61,pegasus)
+ $(call AddDepends/usb-net)
+endef
+
+define KernelPackage/usb-net-pegasus/description
+ Kernel module for USB-to-Ethernet Pegasus convertors
+endef
+
+$(eval $(call KernelPackage,usb-net-pegasus))
+
+
+define KernelPackage/usb-net-mcs7830
+ TITLE:=Kernel module for USB-to-Ethernet MCS7830 convertors
+ KCONFIG:=CONFIG_USB_NET_MCS7830
+ FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/mcs7830.ko
+ AUTOLOAD:=$(call AutoLoad,61,mcs7830)
+ $(call AddDepends/usb-net)
+endef
+
+define KernelPackage/usb-net-mcs7830/description
+ Kernel module for USB-to-Ethernet MCS7830 convertors
+endef
+
+$(eval $(call KernelPackage,usb-net-mcs7830))
+
+
+define KernelPackage/usb-net-dm9601-ether
+ TITLE:=Support for DM9601 ethernet connections
+ KCONFIG:=CONFIG_USB_NET_DM9601
+ FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/dm9601.ko
+ AUTOLOAD:=$(call AutoLoad,61,dm9601)
+ $(call AddDepends/usb-net)
+endef
+
+define KernelPackage/usb-net-dm9601-ether/description
+ Kernel support for USB DM9601 devices
+endef
+
+$(eval $(call KernelPackage,usb-net-dm9601-ether))
+
+define KernelPackage/usb-net-cdc-ether
+ TITLE:=Support for cdc ethernet connections
+ KCONFIG:=CONFIG_USB_NET_CDCETHER
+ FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/cdc_ether.ko
+ AUTOLOAD:=$(call AutoLoad,61,cdc_ether)
+ $(call AddDepends/usb-net)
+endef
+
+define KernelPackage/usb-net-cdc-ether/description
+ Kernel support for USB CDC Ethernet devices
+endef
+
+$(eval $(call KernelPackage,usb-net-cdc-ether))
+
+
+define KernelPackage/usb-net-rndis
+ TITLE:=Support for RNDIS connections
+ KCONFIG:=CONFIG_USB_NET_RNDIS_HOST
+ FILES:= $(LINUX_DIR)/drivers/$(USBNET_DIR)/rndis_host.ko
+ AUTOLOAD:=$(call AutoLoad,62,rndis_host)
+ $(call AddDepends/usb-net,+kmod-usb-net-cdc-ether)
+endef
+
+define KernelPackage/usb-net-rndis/description
+ Kernel support for RNDIS connections
+endef
+
+$(eval $(call KernelPackage,usb-net-rndis))
+
+define KernelPackage/usb-net-sierrawireless
+ TITLE:=Support for Sierra Wireless devices
+ KCONFIG:=CONFIG_USB_SIERRA_NET
+ FILES:=$(LINUX_DIR)/drivers/net/usb/sierra_net.ko
+ AUTOLOAD:=$(call AutoLoad,65,sierra_net)
+ $(call AddDepends/usb-net)
+endef
+
+define KernelPackage/usb-net-sierrawireless/description
+ Kernel support for Sierra Wireless devices
+endef
+
+$(eval $(call KernelPackage,usb-net-sierrawireless))
+
+
+define KernelPackage/usb-net-ipheth
+ TITLE:=Apple iPhone USB Ethernet driver
+ KCONFIG:=CONFIG_USB_IPHETH
+ FILES:=$(LINUX_DIR)/drivers/net/usb/ipheth.ko
+ AUTOLOAD:=$(call AutoLoad,64,ipheth)
+ $(call AddDepends/usb-net)
+endef
+
+define KernelPackage/usb-net-ipheth/description
+ Kernel support for Apple iPhone USB Ethernet driver
+endef
+
+$(eval $(call KernelPackage,usb-net-ipheth))
+
+
+define KernelPackage/usb-hid
+ TITLE:=Support for USB Human Input Devices
+ KCONFIG:=CONFIG_HID_SUPPORT=y CONFIG_USB_HID CONFIG_USB_HIDDEV=y
+ FILES:=$(LINUX_DIR)/drivers/$(USBHID_DIR)/usbhid.ko
+ AUTOLOAD:=$(call AutoLoad,70,usbhid)
+ $(call AddDepends/usb)
+ $(call AddDepends/hid)
+ $(call AddDepends/input,+kmod-input-evdev)
+endef
+
+
+define KernelPackage/usb-hid/description
+ Kernel support for USB HID devices such as keyboards and mice
+endef
+
+$(eval $(call KernelPackage,usb-hid))
+
+
+define KernelPackage/usb-yealink
+ TITLE:=USB Yealink VOIP phone
+ KCONFIG:=CONFIG_USB_YEALINK CONFIG_INPUT_YEALINK CONFIG_INPUT=m CONFIG_INPUT_MISC=y
+ FILES:=$(LINUX_DIR)/drivers/$(USBINPUT_DIR)/yealink.ko
+ AUTOLOAD:=$(call AutoLoad,70,yealink)
+ $(call AddDepends/usb)
+ $(call AddDepends/input,+kmod-input-evdev)
+endef
+
+define KernelPackage/usb-yealink/description
+ Kernel support for Yealink VOIP phone
+endef
+
+$(eval $(call KernelPackage,usb-yealink))
+
+
+define KernelPackage/usb-cm109
+ TITLE:=Support for CM109 device
+ KCONFIG:=CONFIG_USB_CM109 CONFIG_INPUT_CM109 CONFIG_INPUT=m CONFIG_INPUT_MISC=y
+ FILES:=$(LINUX_DIR)/drivers/$(USBINPUT_DIR)/cm109.ko
+ AUTOLOAD:=$(call AutoLoad,70,cm109)
+ $(call AddDepends/usb)
+ $(call AddDepends/input,+kmod-input-evdev)
+endef
+
+define KernelPackage/usb-cm109/description
+ Kernel support for CM109 VOIP phone
+endef
+
+$(eval $(call KernelPackage,usb-cm109))
+
+
+define KernelPackage/usb-test
+ TITLE:=USB Testing Driver
+ DEPENDS:=@DEVEL
+ KCONFIG:=CONFIG_USB_TEST
+ FILES:=$(LINUX_DIR)/drivers/usb/misc/usbtest.ko
+ $(call AddDepends/usb)
+endef
+
+define KernelPackage/usb-test/description
+ Kernel support for testing USB Host Controller software.
+endef
+
+$(eval $(call KernelPackage,usb-test))
+
+
+define KernelPackage/usbip
+ TITLE := USB-over-IP kernel support
+ KCONFIG:= \
+ CONFIG_USBIP_CORE \
+ CONFIG_USBIP_DEBUG=n
+ FILES:=$(LINUX_DIR)/drivers/staging/usbip/usbip-core.ko
+ AUTOLOAD:=$(call AutoLoad,90,usbip-core)
+ $(call AddDepends/usb)
+endef
+$(eval $(call KernelPackage,usbip))
+
+define KernelPackage/usbip-client
+ TITLE := USB-over-IP client driver
+ DEPENDS := +kmod-usbip
+ KCONFIG := CONFIG_USBIP_VHCI_HCD
+ FILES := $(LINUX_DIR)/drivers/staging/usbip/vhci-hcd.$(LINUX_KMOD_SUFFIX)
+ AUTOLOAD := $(call AutoLoad,95,vhci-hcd)
+ $(call AddDepends/usb)
+endef
+$(eval $(call KernelPackage,usbip-client))
+
+define KernelPackage/usbip-server
+$(call KernelPackage/usbip/Default)
+ TITLE := USB-over-IP host driver
+ DEPENDS := +kmod-usbip
+ KCONFIG := CONFIG_USBIP_HOST
+ FILES := $(LINUX_DIR)/drivers/staging/usbip/usbip-host.ko
+ AUTOLOAD := $(call AutoLoad,95,usbip-host)
+ $(call AddDepends/usb)
+endef
+$(eval $(call KernelPackage,usbip-server))
diff --git a/package/kernel/modules/video.mk b/package/kernel/modules/video.mk
new file mode 100644
index 000000000..94ea2616a
--- /dev/null
+++ b/package/kernel/modules/video.mk
@@ -0,0 +1,714 @@
+#
+# Copyright (C) 2009 David Cooper <dave@kupesoft.com>
+# Copyright (C) 2006-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+VIDEO_MENU:=Video Support
+
+
+define KernelPackage/fb
+ SUBMENU:=$(VIDEO_MENU)
+ TITLE:=Framebuffer support
+ DEPENDS:=@DISPLAY_SUPPORT
+ KCONFIG:=CONFIG_FB
+ FILES:=$(LINUX_DIR)/drivers/video/fb.ko
+ AUTOLOAD:=$(call AutoLoad,06,fb)
+endef
+
+define KernelPackage/fb/description
+ Kernel support for framebuffers
+endef
+
+$(eval $(call KernelPackage,fb))
+
+define KernelPackage/fb-cfb-fillrect
+ SUBMENU:=$(VIDEO_MENU)
+ TITLE:=Framebuffer software rectangle filling support
+ DEPENDS:=+kmod-fb
+ KCONFIG:=CONFIG_FB_CFB_FILLRECT
+ FILES:=$(LINUX_DIR)/drivers/video/cfbfillrect.ko
+ AUTOLOAD:=$(call AutoLoad,07,cfbfillrect)
+endef
+
+define KernelPackage/fb-cfb-fillrect/description
+ Kernel support for software rectangle filling
+endef
+
+$(eval $(call KernelPackage,fb-cfb-fillrect))
+
+
+define KernelPackage/fb-cfb-copyarea
+ SUBMENU:=$(VIDEO_MENU)
+ TITLE:=Framebuffer software copy area support
+ DEPENDS:=+kmod-fb
+ KCONFIG:=CONFIG_FB_CFB_COPYAREA
+ FILES:=$(LINUX_DIR)/drivers/video/cfbcopyarea.ko
+ AUTOLOAD:=$(call AutoLoad,07,cfbcopyarea)
+endef
+
+define KernelPackage/fb-cfb-copyarea/description
+ Kernel support for software copy area
+endef
+
+$(eval $(call KernelPackage,fb-cfb-copyarea))
+
+define KernelPackage/fb-cfb-imgblt
+ SUBMENU:=$(VIDEO_MENU)
+ TITLE:=Framebuffer software image blit support
+ DEPENDS:=+kmod-fb
+ KCONFIG:=CONFIG_FB_CFB_IMAGEBLIT
+ FILES:=$(LINUX_DIR)/drivers/video/cfbimgblt.ko
+ AUTOLOAD:=$(call AutoLoad,07,cfbimgblt)
+endef
+
+define KernelPackage/fb-cfb-imgblt/description
+ Kernel support for software image blitting
+endef
+
+$(eval $(call KernelPackage,fb-cfb-imgblt))
+
+
+define KernelPackage/video-core
+ SUBMENU:=$(VIDEO_MENU)
+ TITLE=Video4Linux support
+ DEPENDS:=@PCI_SUPPORT||USB_SUPPORT +!TARGET_etrax:kmod-i2c-core
+ KCONFIG:= \
+ CONFIG_MEDIA_SUPPORT=m \
+ CONFIG_VIDEO_DEV \
+ CONFIG_VIDEO_V4L1=y \
+ CONFIG_VIDEO_ALLOW_V4L1=y \
+ CONFIG_VIDEO_CAPTURE_DRIVERS=y \
+ CONFIG_V4L_USB_DRIVERS=y \
+ CONFIG_V4L_PCI_DRIVERS=y \
+ CONFIG_V4L_PLATFORM_DRIVERS=y \
+ CONFIG_V4L_ISA_PARPORT_DRIVERS=y
+ FILES:= \
+ $(LINUX_DIR)/drivers/media/video/v4l2-common.ko \
+ $(LINUX_DIR)/drivers/media/video/videodev.ko
+ AUTOLOAD:=$(call AutoLoad,60, videodev v4l2-common)
+endef
+
+define KernelPackage/video-core/description
+ Kernel modules for Video4Linux support
+endef
+
+$(eval $(call KernelPackage,video-core))
+
+
+define AddDepends/video
+ SUBMENU:=$(VIDEO_MENU)
+ DEPENDS+=kmod-video-core $(1)
+endef
+
+
+define KernelPackage/video-videobuf2
+ TITLE:=videobuf2 lib
+ KCONFIG:= \
+ CONFIG_VIDEOBUF2_CORE \
+ CONFIG_VIDEOBUF2_MEMOPS \
+ CONFIG_VIDEOBUF2_VMALLOC
+ FILES:= \
+ $(LINUX_DIR)/drivers/media/video/videobuf2-core.ko \
+ $(LINUX_DIR)/drivers/media/video/videobuf2-memops.ko \
+ $(LINUX_DIR)/drivers/media/video/videobuf2-vmalloc.ko
+ AUTOLOAD:=$(call AutoLoad,65,videobuf2-core videobuf2-memops videobuf2-vmalloc)
+ $(call AddDepends/video)
+endef
+
+define KernelPackage/video-videobuf2/description
+ Kernel modules that implements three basic types of media buffers.
+endef
+
+$(eval $(call KernelPackage,video-videobuf2))
+
+
+define KernelPackage/video-cpia2
+ TITLE:=CPIA2 video driver
+ DEPENDS:=@USB_SUPPORT +kmod-usb-core
+ KCONFIG:=CONFIG_VIDEO_CPIA2
+ FILES:=$(LINUX_DIR)/drivers/media/video/cpia2/cpia2.ko
+ AUTOLOAD:=$(call AutoLoad,70,cpia2)
+ $(call AddDepends/video)
+endef
+
+define KernelPackage/video-cpia2/description
+ Kernel modules for supporting CPIA2 USB based cameras.
+endef
+
+$(eval $(call KernelPackage,video-cpia2))
+
+
+define KernelPackage/video-sn9c102
+ TITLE:=SN9C102 Camera Chip support
+ DEPENDS:=@USB_SUPPORT +kmod-usb-core
+ KCONFIG:=CONFIG_USB_SN9C102
+ FILES:=$(LINUX_DIR)/drivers/media/video/sn9c102/sn9c102.ko
+ AUTOLOAD:=$(call AutoLoad,70,gspca_sn9c20x)
+ $(call AddDepends/video)
+endef
+
+
+define KernelPackage/video-sn9c102/description
+ Kernel modules for supporting SN9C102
+ camera chips.
+endef
+
+$(eval $(call KernelPackage,video-sn9c102))
+
+
+define KernelPackage/video-pwc
+ TITLE:=Philips USB webcam support
+ DEPENDS:=@USB_SUPPORT +kmod-usb-core +!LINUX_2_6_39:kmod-video-videobuf2
+ KCONFIG:= \
+ CONFIG_USB_PWC \
+ CONFIG_USB_PWC_DEBUG=n
+ FILES:=$(LINUX_DIR)/drivers/media/video/pwc/pwc.ko
+ AUTOLOAD:=$(call AutoLoad,70,pwc)
+ $(call AddDepends/video)
+endef
+
+
+define KernelPackage/video-pwc/description
+ Kernel modules for supporting Philips USB based cameras.
+endef
+
+$(eval $(call KernelPackage,video-pwc))
+
+define KernelPackage/video-uvc
+ TITLE:=USB Video Class (UVC) support
+ DEPENDS:=@USB_SUPPORT +kmod-usb-core +kmod-video-videobuf2
+ KCONFIG:= CONFIG_USB_VIDEO_CLASS
+ FILES:=$(LINUX_DIR)/drivers/media/video/uvc/uvcvideo.ko
+ AUTOLOAD:=$(call AutoLoad,90,uvcvideo)
+ $(call AddDepends/video)
+ $(call AddDepends/input)
+endef
+
+
+define KernelPackage/video-uvc/description
+ Kernel modules for supporting USB Video Class (UVC) devices.
+endef
+
+$(eval $(call KernelPackage,video-uvc))
+
+
+define KernelPackage/video-gspca-core
+ MENU:=1
+ TITLE:=GSPCA webcam core support framework
+ DEPENDS:=@USB_SUPPORT +kmod-usb-core +kmod-input-core
+ KCONFIG:=CONFIG_USB_GSPCA
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_main.ko
+ AUTOLOAD:=$(call AutoLoad,70,gspca_main)
+ $(call AddDepends/video)
+endef
+
+define KernelPackage/video-gspca-core/description
+ Kernel modules for supporting GSPCA based webcam devices. Note this is just
+ the core of the driver, please select a submodule that supports your webcam.
+endef
+
+$(eval $(call KernelPackage,video-gspca-core))
+
+
+define AddDepends/video-gspca
+ SUBMENU:=$(VIDEO_MENU)
+ DEPENDS+=kmod-video-gspca-core $(1)
+endef
+
+
+define KernelPackage/video-gspca-conex
+ TITLE:=conex webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_CONEX
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_conex.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_conex)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-conex/description
+ The Conexant Camera Driver (conex) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-conex))
+
+
+define KernelPackage/video-gspca-etoms
+ TITLE:=etoms webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_ETOMS
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_etoms.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_etoms)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-etoms/description
+ The Etoms USB Camera Driver (etoms) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-etoms))
+
+
+define KernelPackage/video-gspca-finepix
+ TITLE:=finepix webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_FINEPIX
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_finepix.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_finepix)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-finepix/description
+ The Fujifilm FinePix USB V4L2 driver (finepix) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-finepix))
+
+
+define KernelPackage/video-gspca-mars
+ TITLE:=mars webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_MARS
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_mars.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_mars)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-mars/description
+ The Mars USB Camera Driver (mars) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-mars))
+
+
+define KernelPackage/video-gspca-mr97310a
+ TITLE:=mr97310a webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_MR97310A
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_mr97310a.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_mr97310a)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-mr97310a/description
+ The Mars-Semi MR97310A USB Camera Driver (mr97310a) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-mr97310a))
+
+
+define KernelPackage/video-gspca-ov519
+ TITLE:=ov519 webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_OV519
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_ov519.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_ov519)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-ov519/description
+ The OV519 USB Camera Driver (ov519) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-ov519))
+
+
+define KernelPackage/video-gspca-ov534
+ TITLE:=ov534 webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_OV534
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_ov534.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_ov534)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-ov534/description
+ The OV534 USB Camera Driver (ov534) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-ov534))
+
+
+define KernelPackage/video-gspca-ov534-9
+ TITLE:=ov534-9 webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_OV534_9
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_ov534_9.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_ov534_9)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-ov534-9/description
+ The OV534-9 USB Camera Driver (ov534_9) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-ov534-9))
+
+
+define KernelPackage/video-gspca-pac207
+ TITLE:=pac207 webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_PAC207
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_pac207.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_pac207)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-pac207/description
+ The Pixart PAC207 USB Camera Driver (pac207) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-pac207))
+
+
+define KernelPackage/video-gspca-pac7311
+ TITLE:=pac7311 webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_PAC7311
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_pac7311.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_pac7311)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-pac7311/description
+ The Pixart PAC7311 USB Camera Driver (pac7311) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-pac7311))
+
+
+define KernelPackage/video-gspca-se401
+ TITLE:=se401 webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_SE401
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_se401.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_se401)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-se401/description
+ The SE401 USB Camera Driver kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-se401))
+
+
+define KernelPackage/video-gspca-sn9c20x
+ TITLE:=sn9c20x webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_SN9C20X
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_sn9c20x.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_sn9c20x)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-sn9c20x/description
+ The SN9C20X USB Camera Driver (sn9c20x) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-sn9c20x))
+
+
+define KernelPackage/video-gspca-sonixb
+ TITLE:=sonixb webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_SONIXB
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_sonixb.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_sonixb)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-sonixb/description
+ The SONIX Bayer USB Camera Driver (sonixb) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-sonixb))
+
+
+define KernelPackage/video-gspca-sonixj
+ TITLE:=sonixj webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_SONIXJ
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_sonixj.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_sonixj)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-sonixj/description
+ The SONIX JPEG USB Camera Driver (sonixj) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-sonixj))
+
+
+define KernelPackage/video-gspca-spca500
+ TITLE:=spca500 webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_SPCA500
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_spca500.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_spca500)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-spca500/description
+ The SPCA500 USB Camera Driver (spca500) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-spca500))
+
+
+define KernelPackage/video-gspca-spca501
+ TITLE:=spca501 webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_SPCA501
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_spca501.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_spca501)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-spca501/description
+ The SPCA501 USB Camera Driver (spca501) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-spca501))
+
+
+define KernelPackage/video-gspca-spca505
+ TITLE:=spca505 webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_SPCA505
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_spca505.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_spca505)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-spca505/description
+ The SPCA505 USB Camera Driver (spca505) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-spca505))
+
+
+define KernelPackage/video-gspca-spca506
+ TITLE:=spca506 webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_SPCA506
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_spca506.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_spca506)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-spca506/description
+ The SPCA506 USB Camera Driver (spca506) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-spca506))
+
+
+define KernelPackage/video-gspca-spca508
+ TITLE:=spca508 webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_SPCA508
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_spca508.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_spca508)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-spca508/description
+ The SPCA508 USB Camera Driver (spca508) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-spca508))
+
+
+define KernelPackage/video-gspca-spca561
+ TITLE:=spca561 webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_SPCA561
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_spca561.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_spca561)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-spca561/description
+ The SPCA561 USB Camera Driver (spca561) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-spca561))
+
+
+define KernelPackage/video-gspca-sq905
+ TITLE:=sq905 webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_SQ905
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_sq905.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_sq905)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-sq905/description
+ The SQ Technologies SQ905 based USB Camera Driver (sq905) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-sq905))
+
+
+define KernelPackage/video-gspca-sq905c
+ TITLE:=sq905c webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_SQ905C
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_sq905c.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_sq905c)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-sq905c/description
+ The SQ Technologies SQ905C based USB Camera Driver (sq905c) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-sq905c))
+
+
+define KernelPackage/video-gspca-stk014
+ TITLE:=stk014 webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_STK014
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_stk014.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_stk014)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-stk014/description
+ The Syntek DV4000 (STK014) USB Camera Driver (stk014) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-stk014))
+
+
+define KernelPackage/video-gspca-sunplus
+ TITLE:=sunplus webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_SUNPLUS
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_sunplus.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_sunplus)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-sunplus/description
+ The SUNPLUS USB Camera Driver (sunplus) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-sunplus))
+
+
+define KernelPackage/video-gspca-t613
+ TITLE:=t613 webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_T613
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_t613.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_t613)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-t613/description
+ The T613 (JPEG Compliance) USB Camera Driver (t613) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-t613))
+
+
+define KernelPackage/video-gspca-tv8532
+ TITLE:=tv8532 webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_TV8532
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_tv8532.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_tv8532)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-tv8532/description
+ The TV8532 USB Camera Driver (tv8532) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-tv8532))
+
+
+define KernelPackage/video-gspca-vc032x
+ TITLE:=vc032x webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_VC032X
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_vc032x.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_vc032x)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-vc032x/description
+ The VC032X USB Camera Driver (vc032x) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-vc032x))
+
+
+define KernelPackage/video-gspca-zc3xx
+ TITLE:=zc3xx webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_ZC3XX
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_zc3xx.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_zc3xx)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-zc3xx/description
+ The ZC3XX USB Camera Driver (zc3xx) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-zc3xx))
+
+
+define KernelPackage/video-gspca-m5602
+ TITLE:=m5602 webcam support
+ KCONFIG:=CONFIG_USB_M5602
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/m5602/gspca_m5602.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_m5602)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-m5602/description
+ The ALi USB m5602 Camera Driver (m5602) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-m5602))
+
+
+define KernelPackage/video-gspca-stv06xx
+ TITLE:=stv06xx webcam support
+ KCONFIG:=CONFIG_USB_STV06XX
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/stv06xx/gspca_stv06xx.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_stv06xx)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-stv06xx/description
+ The STV06XX USB Camera Driver (stv06xx) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-stv06xx))
+
+
+define KernelPackage/video-gspca-gl860
+ TITLE:=gl860 webcam support
+ KCONFIG:=CONFIG_USB_GL860
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gl860/gspca_gl860.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_gl860)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-gl800/description
+ The GL860 USB Camera Driver (gl860) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-gl860))
+
+
+define KernelPackage/video-gspca-jeilinj
+ TITLE:=jeilinj webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_JEILINJ
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_jeilinj.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_jeilinj)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-jeilinj/description
+ The JEILINJ USB Camera Driver (jeilinj) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-jeilinj))
+
+
+define KernelPackage/video-gspca-konica
+ TITLE:=konica webcam support
+ KCONFIG:=CONFIG_USB_GSPCA_KONICA
+ FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_konica.ko
+ AUTOLOAD:=$(call AutoLoad,75,gspca_konica)
+ $(call AddDepends/video-gspca)
+endef
+
+define KernelPackage/video-gspca-konica/description
+ The Konica USB Camera Driver (konica) kernel module.
+endef
+
+$(eval $(call KernelPackage,video-gspca-konica))
diff --git a/package/kernel/modules/virtual.mk b/package/kernel/modules/virtual.mk
new file mode 100644
index 000000000..b7313e11d
--- /dev/null
+++ b/package/kernel/modules/virtual.mk
@@ -0,0 +1,171 @@
+#
+# Copyright (C) 2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+VIRTUAL_MENU:=Virtualization Support
+
+
+define KernelPackage/virtio-balloon
+ SUBMENU:=$(VIRTUAL_MENU)
+ TITLE:=VirtIO balloon driver
+ DEPENDS:=@TARGET_x86_kvm_guest
+ KCONFIG:=CONFIG_VIRTIO_BALLOON
+ FILES:=$(LINUX_DIR)/drivers/virtio/virtio_balloon.ko
+ AUTOLOAD:=$(call AutoLoad,06,virtio-balloon)
+endef
+
+define KernelPackage/virtio-balloon/description
+ Kernel module for VirtIO memory ballooning support
+endef
+
+$(eval $(call KernelPackage,virtio-balloon))
+
+
+define KernelPackage/virtio-net
+ SUBMENU:=$(VIRTUAL_MENU)
+ TITLE:=VirtIO network driver
+ DEPENDS:=@TARGET_x86_kvm_guest
+ KCONFIG:=CONFIG_VIRTIO_NET
+ FILES:=$(LINUX_DIR)/drivers/net/virtio_net.ko
+ AUTOLOAD:=$(call AutoLoad,50,virtio_net)
+endef
+
+define KernelPackage/virtio-net/description
+ Kernel module for the VirtIO paravirtualized network device
+endef
+
+$(eval $(call KernelPackage,virtio-net))
+
+
+define KernelPackage/virtio-random
+ SUBMENU:=$(VIRTUAL_MENU)
+ TITLE:=VirtIO Random Number Generator support
+ DEPENDS:=@TARGET_x86_kvm_guest
+ KCONFIG:=CONFIG_HW_RANDOM_VIRTIO
+ FILES:=$(LINUX_DIR)/drivers/char/hw_random/virtio-rng.ko
+ AUTOLOAD:=$(call AutoLoad,09,virtio-rng)
+endef
+
+define KernelPackage/virtio-random/description
+ Kernel module for the VirtIO Random Number Generator
+endef
+
+$(eval $(call KernelPackage,virtio-random))
+
+define KernelPackage/xen-fs
+ SUBMENU:=$(VIRTUAL_MENU)
+ TITLE:=Xen filesystem
+ DEPENDS:=@TARGET_x86_xen_domu
+ KCONFIG:= \
+ CONFIG_XENFS \
+ CONFIG_XEN_COMPAT_XENFS=y
+ FILES:=$(LINUX_DIR)/drivers/xen/xenfs/xenfs.ko
+ AUTOLOAD:=$(call AutoLoad,05,xenfs)
+endef
+
+define KernelPackage/xen-fs/description
+ Kernel module for the Xen filesystem
+endef
+
+$(eval $(call KernelPackage,xen-fs))
+
+
+define KernelPackage/xen-evtchn
+ SUBMENU:=$(VIRTUAL_MENU)
+ TITLE:=Xen event channels
+ DEPENDS:=@TARGET_x86_xen_domu
+ KCONFIG:=CONFIG_XEN_DEV_EVTCHN
+ FILES:=$(LINUX_DIR)/drivers/xen/xen-evtchn.ko
+ AUTOLOAD:=$(call AutoLoad,06,xen-evtchn)
+endef
+
+define KernelPackage/xen-evtchn/description
+ Kernel module for the /dev/xen/evtchn device
+endef
+
+$(eval $(call KernelPackage,xen-evtchn))
+
+define KernelPackage/xen-fbdev
+ SUBMENU:=$(VIRTUAL_MENU)
+ TITLE:=Xen virtual frame buffer
+ DEPENDS:=@TARGET_x86_xen_domu +kmod-fb
+ KCONFIG:= \
+ CONFIG_XEN_FBDEV_FRONTEND \
+ CONFIG_FB_DEFERRED_IO=y \
+ CONFIG_FB_SYS_COPYAREA \
+ CONFIG_FB_SYS_FILLRECT \
+ CONFIG_FB_SYS_FOPS \
+ CONFIG_FB_SYS_IMAGEBLIT \
+ CONFIG_FIRMWARE_EDID=n
+ FILES:= \
+ $(LINUX_DIR)/drivers/video/xen-fbfront.ko \
+ $(LINUX_DIR)/drivers/video/syscopyarea.ko \
+ $(LINUX_DIR)/drivers/video/sysfillrect.ko \
+ $(LINUX_DIR)/drivers/video/fb_sys_fops.ko \
+ $(LINUX_DIR)/drivers/video/sysimgblt.ko
+ AUTOLOAD:=$(call AutoLoad,07, \
+ fb \
+ syscopyarea \
+ sysfillrect \
+ fb_sys_fops \
+ sysimgblt \
+ xen-fbfront \
+ )
+endef
+
+define KernelPackage/xen-fbdev/description
+ Kernel module for the Xen virtual frame buffer
+endef
+
+$(eval $(call KernelPackage,xen-fbdev))
+
+
+define KernelPackage/xen-kbddev
+ SUBMENU:=$(VIRTUAL_MENU)
+ TITLE:=Xen virtual keyboard and mouse
+ DEPENDS:=@TARGET_x86_xen_domu
+ KCONFIG:=CONFIG_XEN_KBDDEV_FRONTEND
+ FILES:=$(LINUX_DIR)/drivers/input/xen-kbdfront.ko
+ AUTOLOAD:=$(call AutoLoad,08,xen-kbdfront)
+endef
+
+define KernelPackage/xen-kbddev/description
+ Kernel module for the Xen virtual keyboard and mouse
+endef
+
+$(eval $(call KernelPackage,xen-kbddev))
+
+
+define KernelPackage/xen-netdev
+ SUBMENU:=$(VIRTUAL_MENU)
+ TITLE:=Xen network device frontend
+ DEPENDS:=@TARGET_x86_xen_domu
+ KCONFIG:=CONFIG_XEN_NETDEV_FRONTEND
+ FILES:=$(LINUX_DIR)/drivers/net/xen-netfront.ko
+ AUTOLOAD:=$(call AutoLoad,09,xen-netfront)
+endef
+
+define KernelPackage/xen-netdev/description
+ Kernel module for the Xen network device frontend
+endef
+
+$(eval $(call KernelPackage,xen-netdev))
+
+
+define KernelPackage/xen-pcidev
+ SUBMENU:=$(VIRTUAL_MENU)
+ TITLE:=Xen PCI device frontend
+ DEPENDS:=@TARGET_x86_xen_domu
+ KCONFIG:=CONFIG_XEN_PCIDEV_FRONTEND
+ FILES:=$(LINUX_DIR)/drivers/pci/xen-pcifront.ko
+ AUTOLOAD:=$(call AutoLoad,10,xen-pcifront)
+endef
+
+define KernelPackage/xen-pcidev/description
+ Kernel module for the Xen network device frontend
+endef
+
+$(eval $(call KernelPackage,xen-pcidev))
diff --git a/package/kernel/modules/w1.mk b/package/kernel/modules/w1.mk
new file mode 100644
index 000000000..e0e9e576c
--- /dev/null
+++ b/package/kernel/modules/w1.mk
@@ -0,0 +1,160 @@
+#
+# Copyright (C) 2008-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+W1_MENU:=W1 support
+W1_MASTERS_DIR:=$(LINUX_DIR)/drivers/w1/masters
+W1_SLAVES_DIR:=$(LINUX_DIR)/drivers/w1/slaves
+
+define KernelPackage/w1
+ SUBMENU:=$(W1_MENU)
+ TITLE:=Dallas's 1-wire support
+ KCONFIG:=CONFIG_W1
+ FILES:=$(LINUX_DIR)/drivers/w1/wire.ko
+ AUTOLOAD:=$(call AutoLoad,50,wire)
+endef
+
+define KernelPackage/w1/description
+ Kernel module for Dallas's 1-wire support
+endef
+
+$(eval $(call KernelPackage,w1))
+
+
+define AddDepends/w1
+ SUBMENU:=$(W1_MENU)
+ DEPENDS+=kmod-w1 $(1)
+endef
+
+
+#
+# 1-wire masters
+#
+define KernelPackage/w1-master-gpio
+ TITLE:=GPIO 1-wire bus master driver
+ DEPENDS:=@GPIO_SUPPORT
+ KCONFIG:=CONFIG_W1_MASTER_GPIO
+ FILES:=$(W1_MASTERS_DIR)/w1-gpio.ko
+ AUTOLOAD:=$(call AutoLoad,60,w1-gpio)
+ $(call AddDepends/w1)
+endef
+
+define KernelPackage/w1-master-gpio/description
+ Kernel module for the GPIO 1-wire bus master driver
+endef
+
+$(eval $(call KernelPackage,w1-master-gpio))
+
+define KernelPackage/w1-master-ds2482
+ TITLE:=DS2482 1-wire i2c bus master driver
+ KCONFIG:=CONFIG_W1_MASTER_DS2482
+ FILES:=$(W1_MASTERS_DIR)/ds2482.ko
+ AUTOLOAD:=$(call AutoLoad,60,ds2482)
+ $(call AddDepends/w1,+kmod-i2c-core)
+endef
+
+define KernelPackage/w1-master-ds2482/description
+ Kernel module for the DS2482 i2c 1-wire bus master driver
+ NOTE: Init with: echo ds2482 0x18 > /sys/bus/i2c/devices/i2c-0/new_device
+ or use owfs
+endef
+
+$(eval $(call KernelPackage,w1-master-ds2482))
+
+
+define KernelPackage/w1-master-ds2490
+ TITLE:=DS2490 1-wire usb bus master driver
+ DEPENDS:=@USB_SUPPORT +kmod-usb-core
+ KCONFIG:=CONFIG_W1_MASTER_DS2490
+ FILES:=$(W1_MASTERS_DIR)/ds2490.ko
+ AUTOLOAD:=$(call AutoLoad,60,ds2490)
+ $(call AddDepends/w1)
+endef
+
+define KernelPackage/w1-master-ds2490/description
+ Kernel module for the DS2490 usb 1-wire bus master driver
+endef
+
+$(eval $(call KernelPackage,w1-master-ds2490))
+
+#
+# 1-wire slaves
+#
+define KernelPackage/w1-slave-therm
+ TITLE:=Thermal family implementation
+ KCONFIG:=CONFIG_W1_SLAVE_THERM
+ FILES:=$(W1_SLAVES_DIR)/w1_therm.ko
+ AUTOLOAD:=$(call AutoLoad,70,w1_therm)
+ $(call AddDepends/w1)
+endef
+
+define KernelPackage/w1-slave-therm/description
+ Kernel module for 1-wire thermal sensors
+endef
+
+$(eval $(call KernelPackage,w1-slave-therm))
+
+
+define KernelPackage/w1-slave-smem
+ TITLE:=Simple 64bit memory family implementation
+ KCONFIG:=CONFIG_W1_SLAVE_SMEM
+ FILES:=$(W1_SLAVES_DIR)/w1_smem.ko
+ AUTOLOAD:=$(call AutoLoad,70,w1_smem)
+ $(call AddDepends/w1)
+endef
+
+define KernelPackage/w1-slave-smem/description
+ Kernel module for 1-wire simple 64bit memory rom(ds2401/ds2411/ds1990*)
+endef
+
+$(eval $(call KernelPackage,w1-slave-smem))
+
+define KernelPackage/w1-slave-ds2431
+ TITLE:=DS2431 1kb EEPROM driver
+ KCONFIG:= CONFIG_W1_SLAVE_DS2431
+ FILES:=$(W1_SLAVES_DIR)/w1_ds2431.ko
+ AUTOLOAD:=$(call AutoLoad,70,w1_ds2431)
+ $(call AddDepends/w1)
+endef
+
+define KernelPackage/w1-slave-ds2431/description
+ Kernel module for 1-wire 1kb EEPROM (DS2431)
+endef
+
+$(eval $(call KernelPackage,w1-slave-ds2431))
+
+define KernelPackage/w1-slave-ds2433
+ TITLE:=DS2433 4kb EEPROM driver
+ KCONFIG:= \
+ CONFIG_W1_SLAVE_DS2433 \
+ CONFIG_W1_SLAVE_DS2433_CRC=n
+ FILES:=$(W1_SLAVES_DIR)/w1_ds2433.ko
+ AUTOLOAD:=$(call AutoLoad,70,w1_ds2433)
+ $(call AddDepends/w1)
+endef
+
+define KernelPackage/w1-slave-ds2433/description
+ Kernel module for 1-wire 4kb EEPROM (DS2433)
+endef
+
+$(eval $(call KernelPackage,w1-slave-ds2433))
+
+
+define KernelPackage/w1-slave-ds2760
+ TITLE:=Dallas 2760 battery monitor chip (HP iPAQ & others)
+ KCONFIG:= \
+ CONFIG_W1_SLAVE_DS2760 \
+ CONFIG_W1_SLAVE_DS2433_CRC=n
+ FILES:=$(W1_SLAVES_DIR)/w1_ds2760.ko
+ AUTOLOAD:=$(call AutoLoad,70,w1_ds2760)
+ $(call AddDepends/w1)
+endef
+
+define KernelPackage/w1-slave-ds2760/description
+ Kernel module for 1-wire DS2760 battery monitor chip support
+endef
+
+$(eval $(call KernelPackage,w1-slave-ds2760))
diff --git a/package/kernel/modules/wireless.mk b/package/kernel/modules/wireless.mk
new file mode 100644
index 000000000..ee0f96594
--- /dev/null
+++ b/package/kernel/modules/wireless.mk
@@ -0,0 +1,109 @@
+#
+# Copyright (C) 2006-2008 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+WIRELESS_MENU:=Wireless Drivers
+
+define KernelPackage/net-airo
+ SUBMENU:=$(WIRELESS_MENU)
+ TITLE:=Cisco Aironet driver
+ DEPENDS:=@PCI_SUPPORT +@DRIVER_WEXT_SUPPORT
+ KCONFIG:=CONFIG_AIRO
+ FILES:=$(LINUX_DIR)/drivers/net/wireless/airo.ko
+ AUTOLOAD:=$(call AutoLoad,50,airo)
+endef
+
+define KernelPackage/net-airo/description
+ Kernel support for Cisco Aironet cards
+endef
+
+$(eval $(call KernelPackage,net-airo))
+
+
+define KernelPackage/net-zd1201
+ SUBMENU:=$(WIRELESS_MENU)
+ TITLE:=Zydas ZD1201 support
+ DEPENDS:=@USB_SUPPORT +@DRIVER_WEXT_SUPPORT
+ KCONFIG:=CONFIG_USB_ZD1201
+ FILES:=$(LINUX_DIR)/drivers/net/wireless/zd1201.ko
+ AUTOLOAD:=$(call AutoLoad,60,zd1201)
+endef
+
+define KernelPackage/net-zd1201/description
+ Kernel modules for Zydas ZD1201 support
+ Devices using this chip:
+ * Sweex LC100020
+ * Zyxel ZyAir B-220
+ * Peabird USB
+ * Gigafast WF741-UIC
+ * E-Tech Wireless USB Adapter
+ * DSE 802.11b USB wireless LAN adapter
+ * CC and C WLAN USB Adapter (WL 1202)
+ * Edimax EW-7117U
+ * X-Micro WLAN 11b USB Adapter
+ * Belkin F5D6051
+ * Topcom SKYR@CER WIRELESS USB STICK 11
+ * Surecom EP-9001
+ * JAHT WN-1011U
+ * BeWAN Wi-Fi USB 11
+ * NorthQ NQ9000
+ * MSI UB11B
+ * Origo WLL-1610
+ * Longshine LCS-8131R
+ * Gigabyte GN-WLBZ201
+endef
+
+ZD1201FW_NAME:=zd1201
+ZD1201FW_VERSION:=0.14
+ZD1201FW_DIR:=$(ZD1201FW_NAME)-$(ZD1201FW_VERSION)-fw
+ZD1201FW_FILE:=$(ZD1201FW_DIR).tar.gz
+
+define Download/net-zd1201
+ FILE:=$(ZD1201FW_FILE)
+ #http://downloads.sourceforge.net/project/linux-lc100020/%28NEW%29%20zd1201%20driver/zd1201.%20Version%200.14/zd1201-0.14-fw.tar.gz
+ URL:=@SF/linux-lc100020/\(NEW\)\ $(ZD1201FW_NAME)\ driver/$(ZD1201FW_NAME).\ Version\ $(ZD1201FW_VERSION)/
+ MD5SUM:=07a4febc365121f975e2c5e59791d55d
+endef
+
+define KernelPackage/net-zd1201/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(TAR) -C $(1)/lib/firmware -zxf $(DL_DIR)/$(ZD1201FW_FILE) --strip-components=1 $(ZD1201FW_DIR)/$(ZD1201FW_NAME).fw $(ZD1201FW_DIR)/$(ZD1201FW_NAME)-ap.fw
+endef
+
+$(eval $(call Download,net-zd1201))
+$(eval $(call KernelPackage,net-zd1201))
+
+
+define KernelPackage/net-prism54
+ SUBMENU:=$(WIRELESS_MENU)
+ TITLE:=Intersil Prism54 support
+ DEPENDS:=@PCI_SUPPORT +@DRIVER_WEXT_SUPPORT
+ KCONFIG:=CONFIG_PRISM54
+ FILES:=$(LINUX_DIR)/drivers/net/wireless/prism54/prism54.ko
+ AUTOLOAD:=$(call AutoLoad,60,prism54)
+endef
+
+define KernelPackage/net-prism54/description
+ Kernel modules for Intersil Prism54 support
+endef
+
+# Prism54 FullMAC firmware (jbnore.free.fr seems to be rather slow, so we use daemonizer.de)
+PRISM54_FW:=1.0.4.3.arm
+
+define Download/net-prism54
+ FILE:=$(PRISM54_FW)
+ URL:=http://daemonizer.de/prism54/prism54-fw/fw-fullmac/
+ MD5SUM:=8bd4310971772a486b9784c77f8a6df9
+endef
+
+define KernelPackage/net-prism54/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(DL_DIR)/$(PRISM54_FW) $(1)/lib/firmware/isl3890
+endef
+
+$(eval $(call Download,net-prism54))
+$(eval $(call KernelPackage,net-prism54))
+
diff --git a/package/kexec-tools/Config.in b/package/kexec-tools/Config.in
new file mode 100644
index 000000000..60c819d79
--- /dev/null
+++ b/package/kexec-tools/Config.in
@@ -0,0 +1,21 @@
+menu "Configuration"
+ depends on PACKAGE_kexec-tools
+
+config KEXEC_TOOLS_TARGET_NAME
+ string
+ prompt "Target name for kexec kernel"
+ default EXTRA_TARGET_ARCH_NAME if powerpc64
+ default ARCH
+ help
+ Defines the target type of the kernels that kexec deals
+ with. This should be the target specification of
+ the kernel you're booting.
+
+config KEXEC_TOOLS_kdump
+ bool
+ prompt "kdump support"
+ default n
+ help
+ Include the kdump utility.
+
+endmenu
diff --git a/package/kexec-tools/Makefile b/package/kexec-tools/Makefile
new file mode 100644
index 000000000..87ad808e7
--- /dev/null
+++ b/package/kexec-tools/Makefile
@@ -0,0 +1,79 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=kexec-tools
+PKG_VERSION:=2.0.3
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=@KERNEL/linux/utils/kernel/kexec
+PKG_MD5SUM:=b3ced2097ce3981abba38ceedc84f939
+
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/kexec-tools
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=@armeb||@arm||@i386||@powerpc64||@mipsel||@mips +zlib
+ TITLE:=Kernel boots kernel
+ URL:=http://kernel.org/pub/linux/kernel/people/horms/kexec-tools/
+ MENU:=1
+endef
+
+define Package/kexec-tools/description
+ kexec is a set of systems call that allows you to load
+ another kernel from the currently executing Linux kernel.
+endef
+
+define Package/kexec-tools/config
+ source "$(SOURCE)/Config.in"
+endef
+
+KEXEC_TARGET_NAME:=$(call qstrip,$(CONFIG_KEXEC_TOOLS_TARGET_NAME))-linux-$(TARGET_SUFFIX)
+
+CONFIGURE_ARGS = \
+ --target=$(KEXEC_TARGET_NAME) \
+ --host=$(REAL_GNU_TARGET_NAME) \
+ --build=$(GNU_HOST_NAME) \
+ --program-prefix="" \
+ --program-suffix="" \
+ --prefix=/usr \
+ --exec-prefix=/usr \
+ --bindir=/usr/bin \
+ --sbindir=/usr/sbin \
+ --libexecdir=/usr/lib \
+ --sysconfdir=/etc
+
+CONFIGURE_VARS += \
+ BUILD_CC="$(HOSTCC)" \
+ TARGET_CC="$(TARGET_CC)"
+
+kexec-extra-sbin-$(CONFIG_KEXEC_TOOLS_kdump) += kdump
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) DESTDIR="$(PKG_INSTALL_DIR)" all install
+endef
+
+define Package/kexec-tools/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) \
+ $(addprefix $(PKG_INSTALL_DIR)/usr/sbin/, \
+ $(kexec-extra-sbin-y)) \
+ $(kexec-extra-bin-y) \
+ $(PKG_INSTALL_DIR)/usr/sbin/kexec \
+ $(1)/usr/sbin
+
+# make a link for compatability with other distros
+ $(INSTALL_DIR) $(1)/sbin
+ ln -s /usr/sbin/kexec $(1)/sbin/kexec
+endef
+
+$(eval $(call BuildPackage,kexec-tools))
diff --git a/package/kexec-tools/patches/0004-mips_regdefs.patch b/package/kexec-tools/patches/0004-mips_regdefs.patch
new file mode 100644
index 000000000..7e21349aa
--- /dev/null
+++ b/package/kexec-tools/patches/0004-mips_regdefs.patch
@@ -0,0 +1,103 @@
+--- /dev/null
++++ b/kexec/arch/mips/regdef.h
+@@ -0,0 +1,100 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 1985 MIPS Computer Systems, Inc.
++ * Copyright (C) 1994, 95, 99, 2003 by Ralf Baechle
++ * Copyright (C) 1990 - 1992, 1999 Silicon Graphics, Inc.
++ */
++#ifndef _ASM_REGDEF_H
++#define _ASM_REGDEF_H
++
++#include <asm/sgidefs.h>
++
++#if _MIPS_SIM == _MIPS_SIM_ABI32
++
++/*
++ * Symbolic register names for 32 bit ABI
++ */
++#define zero $0 /* wired zero */
++#define AT $1 /* assembler temp - uppercase because of ".set at" */
++#define v0 $2 /* return value */
++#define v1 $3
++#define a0 $4 /* argument registers */
++#define a1 $5
++#define a2 $6
++#define a3 $7
++#define t0 $8 /* caller saved */
++#define t1 $9
++#define t2 $10
++#define t3 $11
++#define t4 $12
++#define t5 $13
++#define t6 $14
++#define t7 $15
++#define s0 $16 /* callee saved */
++#define s1 $17
++#define s2 $18
++#define s3 $19
++#define s4 $20
++#define s5 $21
++#define s6 $22
++#define s7 $23
++#define t8 $24 /* caller saved */
++#define t9 $25
++#define jp $25 /* PIC jump register */
++#define k0 $26 /* kernel scratch */
++#define k1 $27
++#define gp $28 /* global pointer */
++#define sp $29 /* stack pointer */
++#define fp $30 /* frame pointer */
++#define s8 $30 /* same like fp! */
++#define ra $31 /* return address */
++
++#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
++
++#if _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32
++
++#define zero $0 /* wired zero */
++#define AT $at /* assembler temp - uppercase because of ".set at" */
++#define v0 $2 /* return value - caller saved */
++#define v1 $3
++#define a0 $4 /* argument registers */
++#define a1 $5
++#define a2 $6
++#define a3 $7
++#define a4 $8 /* arg reg 64 bit; caller saved in 32 bit */
++#define ta0 $8
++#define a5 $9
++#define ta1 $9
++#define a6 $10
++#define ta2 $10
++#define a7 $11
++#define ta3 $11
++#define t0 $12 /* caller saved */
++#define t1 $13
++#define t2 $14
++#define t3 $15
++#define s0 $16 /* callee saved */
++#define s1 $17
++#define s2 $18
++#define s3 $19
++#define s4 $20
++#define s5 $21
++#define s6 $22
++#define s7 $23
++#define t8 $24 /* caller saved */
++#define t9 $25 /* callee address for PIC/temp */
++#define jp $25 /* PIC jump register */
++#define k0 $26 /* kernel temporary */
++#define k1 $27
++#define gp $28 /* global pointer - caller saved for PIC */
++#define sp $29 /* stack pointer */
++#define fp $30 /* frame pointer */
++#define s8 $30 /* callee saved */
++#define ra $31 /* return address */
++
++#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32 */
++
++#endif /* _ASM_REGDEF_H */
diff --git a/package/libbsd/Makefile b/package/libbsd/Makefile
new file mode 100644
index 000000000..4fef04a23
--- /dev/null
+++ b/package/libbsd/Makefile
@@ -0,0 +1,54 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=libbsd
+PKG_VERSION:=0.3.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://libbsd.freedesktop.org/releases
+#PKG_MD5SUM:=d0870f2de55d59c1c8419f36e8fac150
+
+include $(INCLUDE_DIR)/package.mk
+
+PKG_INSTALL:=1
+
+define Package/libbsd
+ SECTION:=libs
+ CATEGORY:=Libraries
+ DEPENDS:=@!USE_UCLIBC
+ TITLE:=common BSD library
+endef
+
+define Package/libbsd/description
+ This library provides useful functions commonly found on BSD systems, and lacking on others like GNU systems, thus making it easier to port projects with strong BSD origins, without needing to embed the same code over and over again on each project.
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) \
+ $(1)/lib \
+ $(1)/usr/include
+
+ $(CP) \
+ $(PKG_INSTALL_DIR)/lib/libbsd.so* \
+ $(1)/lib/
+
+ $(CP) \
+ $(PKG_INSTALL_DIR)/usr/include/* \
+ $(1)/usr/include/
+
+ ( cd $(1)/lib ; ln -s libbsd.so.$(PKG_VERSION) libbsd.so )
+endef
+
+define Package/libbsd/install
+ $(INSTALL_DIR) \
+ $(1)/lib
+
+ $(CP) \
+ $(PKG_INSTALL_DIR)/lib/libbsd.so* \
+ $(1)/lib/
+
+ ( cd $(1)/lib ; ln -s libbsd.so.$(PKG_VERSION) libbsd.so )
+endef
+
+$(eval $(call BuildPackage,libbsd))
+
diff --git a/package/libipfix/Makefile b/package/libipfix/Makefile
new file mode 100644
index 000000000..e4c931591
--- /dev/null
+++ b/package/libipfix/Makefile
@@ -0,0 +1,47 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=libipfix
+PKG_VERSION:=r51
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME).$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
+PKG_MD5SUM:=0e5b2871ea20ac48eda3f6006c5dba28
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME).$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/libipfix
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=IP Flow Information Export Library
+ URL:=http://www.fokus.fraunhofer.de/de/net/more_about/download/ipfixlib.html
+ BUILDONLY:=1
+endef
+
+TARGET_CFLAGS += \
+ -ffunction-sections -fdata-sections
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CCOPT="$(TARGET_CFLAGS) -I$(BUILD_DIR)/linux/include" \
+ prefix="$(PKG_INSTALL_DIR)/usr" \
+ exec_prefix="$(PKG_INSTALL_DIR)/usr" \
+ all install
+ $(TARGET_CROSS)ranlib $(PKG_INSTALL_DIR)/usr/lib/libipfix.a
+ $(TARGET_CROSS)ranlib $(PKG_INSTALL_DIR)/usr/lib/libipfixmisc.a
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)
+ $(CP) $(PKG_INSTALL_DIR)/* $(1)/
+endef
+
+$(eval $(call BuildPackage,libipfix))
diff --git a/package/libipfix/extra/append-wprobe-ie.pl b/package/libipfix/extra/append-wprobe-ie.pl
new file mode 100644
index 000000000..8bb658bbb
--- /dev/null
+++ b/package/libipfix/extra/append-wprobe-ie.pl
@@ -0,0 +1,38 @@
+use strict;
+
+my @fields = (
+ [ "_n", "UINT", " - Number of samples", 4 ],
+ [ "_s", "UINT", " - Sum of samples", 8 ],
+ [ "_ss", "UINT", " - Sum of squared samples", 8 ],
+);
+
+my $file = $ARGV[0] or die "Syntax: $0 <file> <start>\n";
+-f $file or die "File not found\n";
+my $start = $ARGV[1];
+$start =~ /^\d+$/ or die "Invalid start number";
+open FILE, "<$file" or die "Can't open file";
+while (<FILE>) {
+ /^(%?)(\w+),\s*(\w+),\s*(.+)$/ and do {
+ my $counter = $1;
+ my $rfield = $2;
+ my $nfield = $3;
+ my $descr = $4;
+ my @f;
+ if ($counter) {
+ @f = [ "", "UINT", "", 4];
+ } else {
+ @f = @fields;
+ }
+ foreach my $f (@f) {
+ my $nr = $start++;
+ my $n = $f->[0];
+ my $N = uc $n;
+ my $ftype = $f->[1];
+ my $fdesc = $f->[2];
+ my $size = $f->[3];
+ print "$nr, IPFIX_FT_WPROBE_$rfield$N, $size, IPFIX_CODING_$ftype, \"$nfield$n\", \"$descr$fdesc\"\n";
+ }
+ };
+}
+close FILE;
+
diff --git a/package/libipfix/extra/wprobe-ie.txt b/package/libipfix/extra/wprobe-ie.txt
new file mode 100644
index 000000000..26d64d213
--- /dev/null
+++ b/package/libipfix/extra/wprobe-ie.txt
@@ -0,0 +1,14 @@
+NOISE, global_noise, wprobe global noice floor
+PHY_BUSY, global_phy_busy, wprobe global airtime total
+PHY_RX, global_phy_rx, wprobe global airtime total from rx-frame
+PHY_TX, global_phy_tx, wprobe global airtime total from tx-frame
+RSSI, link_rssi, wprobe link received signal strength indication
+SIGNAL, link_signal, wprobe link signal strength in dB
+IEEE_RX_RATE, link_ieee_rx_rate, wprobe link IEEE 802.11 RX data rate
+IEEE_TX_RATE, link_ieee_tx_rate, wprobe link IEEE 802.11 TX data rate
+RETRANSMIT_200, link_retransmit_200, wprobe link total retransmissions per packet - <200 bytes
+RETRANSMIT_400, link_retransmit_400, wprobe link total retransmissions per packet - <400 bytes
+RETRANSMIT_800, link_retransmit_800, wprobe link total retransmissions per packet - <800 bytes
+RETRANSMIT_1600, link_retransmit_1600, wprobe link total retransmissions per packet - >800 bytes
+%FRAMES, global_frames, wprobe global number of 802.11 frames seen
+%PROBEREQ, global_probereq, wprobe global number of 802.11 probe requests seen
diff --git a/package/libipfix/patches/100-openimp_sync.patch b/package/libipfix/patches/100-openimp_sync.patch
new file mode 100644
index 000000000..5b6e2e379
--- /dev/null
+++ b/package/libipfix/patches/100-openimp_sync.patch
@@ -0,0 +1,474 @@
+--- a/lib/ipfix.c
++++ b/lib/ipfix.c
+@@ -37,6 +37,9 @@ $$LIC$$
+ #ifdef SCTPSUPPORT
+ #include <netinet/sctp.h>
+ #endif
++#ifndef NOTHREADS
++#include <pthread.h>
++#endif
+ #include <fcntl.h>
+ #include <netdb.h>
+
+@@ -123,6 +126,18 @@ static uint16_t g_lasttid;
+ static ipfix_datarecord_t g_data = { NULL, NULL, 0 }; /* ipfix_export */
+
+ static ipfix_field_t *g_ipfix_fields;
++#ifndef NOTHREADS
++static pthread_mutex_t g_mutex;
++#define mod_lock() { \
++ if ( pthread_mutex_lock( &g_mutex ) !=0 ) \
++ mlogf( 0, "[ipfix] mutex_lock() failed: %s\n", \
++ strerror( errno ) ); \
++ }
++#define mod_unlock() { pthread_mutex_unlock( &g_mutex ); }
++#else
++#define mod_lock()
++#define mod_unlock()
++#endif
+
+ /*----- prototypes -------------------------------------------------------*/
+
+@@ -133,6 +148,7 @@ int _ipfix_send_message( ipfix_t *ifh,
+ ipfix_message_t *message );
+ int _ipfix_write_msghdr( ipfix_t *ifh, ipfix_message_t *msg, iobuf_t *buf );
+ void _ipfix_disconnect( ipfix_collector_t *col );
++int _ipfix_export_flush( ipfix_t *ifh );
+
+
+ /* name : do_writeselect
+@@ -576,16 +592,18 @@ int ipfix_decode_float( void *in, void *
+
+ int ipfix_snprint_float( char *str, size_t size, void *data, size_t len )
+ {
+- float tmp32;
+- double tmp64;
++ uint32_t tmp32;
++ uint64_t tmp64;
+
+ switch ( len ) {
+ case 4:
+- ipfix_decode_float( data, &tmp32, 4);
+- return snprintf( str, size, "%f", tmp32 );
++ memcpy( &tmp32, data, len );
++ tmp32 = htonl( tmp32 );
++ return snprintf( str, size, "%f", (float)tmp32 );
+ case 8:
+- ipfix_decode_float( data, &tmp64, 8);
+- return snprintf( str, size, "%lf", tmp64);
++ memcpy( &tmp64, data, len );
++ tmp64 = HTONLL( tmp64 );
++ return snprintf( str, size, "%lf", (double)tmp64 );
+ default:
+ break;
+ }
+@@ -682,12 +700,19 @@ int ipfix_get_eno_ieid( char *field, int
+ * parameters:
+ * remarks: init module, read field type info.
+ */
+-int ipfix_init ( void )
++int ipfix_init( void )
+ {
+ if ( g_tstart ) {
+ ipfix_cleanup();
+ }
+
++#ifndef NOTHREADS
++ if ( pthread_mutex_init( &g_mutex, NULL ) !=0 ) {
++ mlogf( 0, "[ipfix] pthread_mutex_init() failed: %s\n",
++ strerror(errno) );
++ return -1;
++ }
++#endif
+ g_tstart = time(NULL);
+ signal( SIGPIPE, SIG_IGN );
+ g_lasttid = 255;
+@@ -806,6 +831,9 @@ void ipfix_cleanup ( void )
+ g_data.maxfields = 0;
+ g_data.lens = NULL;
+ g_data.addrs = NULL;
++#ifndef NOTHREADS
++ (void)pthread_mutex_destroy( &g_mutex );
++#endif
+ }
+
+ int _ipfix_connect ( ipfix_collector_t *col )
+@@ -1465,7 +1493,7 @@ int _ipfix_write_template( ipfix_t
+ default:
+ /* check space */
+ if ( tsize+ifh->offset > IPFIX_DEFAULT_BUFLEN ) {
+- if ( ipfix_export_flush( ifh ) < 0 )
++ if ( _ipfix_export_flush( ifh ) < 0 )
+ return -1;
+ if ( tsize+ifh->offset > IPFIX_DEFAULT_BUFLEN )
+ return -1;
+@@ -1474,6 +1502,8 @@ int _ipfix_write_template( ipfix_t
+ /* write template prior to data */
+ if ( ifh->offset > 0 ) {
+ memmove( ifh->buffer + tsize, ifh->buffer, ifh->offset );
++ if ( ifh->cs_tid )
++ ifh->cs_header += tsize;
+ }
+
+ buf = ifh->buffer;
+@@ -1615,8 +1645,11 @@ int ipfix_open( ipfix_t **ipfixh, int so
+ return -1;
+ }
+ node->ifh = i;
++
++ mod_lock();
+ node->next = g_ipfixlist;
+ g_ipfixlist = node;
++ mod_unlock();
+
+ *ipfixh = i;
+ return 0;
+@@ -1633,7 +1666,8 @@ void ipfix_close( ipfix_t *h )
+ {
+ ipfix_node_t *l, *n;
+
+- ipfix_export_flush( h );
++ mod_lock();
++ _ipfix_export_flush( h );
+
+ while( h->collectors )
+ _ipfix_drop_collector( (ipfix_collector_t**)&h->collectors );
+@@ -1659,6 +1693,7 @@ void ipfix_close( ipfix_t *h )
+ #endif
+ free(h->buffer);
+ free(h);
++ mod_unlock();
+ }
+ }
+
+@@ -2156,6 +2191,22 @@ void ipfix_release_template( ipfix_t *if
+ ipfix_delete_template( ifh, templ );
+ }
+
++static void _finish_cs( ipfix_t *ifh )
++{
++ size_t buflen;
++ uint8_t *buf;
++
++ /* finish current dataset */
++ if ( (buf=ifh->cs_header) ==NULL )
++ return;
++ buflen = 0;
++ INSERTU16( buf+buflen, buflen, ifh->cs_tid );
++ INSERTU16( buf+buflen, buflen, ifh->cs_bytes );
++ ifh->cs_bytes = 0;
++ ifh->cs_header = NULL;
++ ifh->cs_tid = 0;
++}
++
+ int ipfix_export( ipfix_t *ifh, ipfix_template_t *templ, ... )
+ {
+ int i;
+@@ -2199,13 +2250,14 @@ int ipfix_export( ipfix_t *ifh, ipfix_te
+ g_data.addrs, g_data.lens );
+ }
+
+-int ipfix_export_array( ipfix_t *ifh,
+- ipfix_template_t *templ,
+- int nfields,
+- void **fields,
+- uint16_t *lengths )
++static int
++_ipfix_export_array( ipfix_t *ifh,
++ ipfix_template_t *templ,
++ int nfields,
++ void **fields,
++ uint16_t *lengths )
+ {
+- int i;
++ int i, newset_f=0;
+ size_t buflen, datasetlen;
+ uint8_t *p, *buf;
+
+@@ -2249,7 +2301,19 @@ int ipfix_export_array( ipfix_t
+
+ /** get size of data set, check space
+ */
+- for ( i=0, datasetlen=4; i<nfields; i++ ) {
++ if ( templ->tid == ifh->cs_tid ) {
++ newset_f = 0;
++ datasetlen = 0;
++ }
++ else {
++ if ( ifh->cs_tid > 0 ) {
++ _finish_cs( ifh );
++ }
++ newset_f = 1;
++ datasetlen = 4;
++ }
++
++ for ( i=0; i<nfields; i++ ) {
+ if ( templ->fields[i].flength == IPFIX_FT_VARLEN ) {
+ if ( lengths[i]>254 )
+ datasetlen += 3;
+@@ -2263,21 +2327,29 @@ int ipfix_export_array( ipfix_t
+ }
+ datasetlen += lengths[i];
+ }
+- if ( ((ifh->offset + datasetlen) > IPFIX_DEFAULT_BUFLEN )
+- && (ipfix_export_flush( ifh ) <0) ) {
+- return -1;
++
++ if ( (ifh->offset + datasetlen) > IPFIX_DEFAULT_BUFLEN ) {
++ if ( ifh->cs_tid )
++ _finish_cs( ifh );
++ newset_f = 1;
++
++ if ( _ipfix_export_flush( ifh ) <0 )
++ return -1;
+ }
+
+- /* fill buffer
+- */
++ /* fill buffer */
+ buf = (uint8_t*)(ifh->buffer) + ifh->offset;
+ buflen = 0;
+
+- /* insert data set
+- */
+- ifh->nrecords ++;
+- INSERTU16( buf+buflen, buflen, templ->tid );
+- INSERTU16( buf+buflen, buflen, datasetlen );
++ if ( newset_f ) {
++ /* insert data set
++ */
++ ifh->cs_bytes = 0;
++ ifh->cs_header = buf;
++ ifh->cs_tid = templ->tid;
++ INSERTU16( buf+buflen, buflen, templ->tid );
++ INSERTU16( buf+buflen, buflen, 4 );
++ }
+
+ /* insert data record
+ */
+@@ -2303,7 +2375,9 @@ int ipfix_export_array( ipfix_t
+ buflen += lengths[i];
+ }
+
++ ifh->nrecords ++;
+ ifh->offset += buflen;
++ ifh->cs_bytes += buflen;
+ if ( ifh->version == IPFIX_VERSION )
+ ifh->seqno ++;
+ return 0;
+@@ -2313,7 +2387,7 @@ int ipfix_export_array( ipfix_t
+ * parameters:
+ * remarks: rewrite this func!
+ */
+-int ipfix_export_flush( ipfix_t *ifh )
++int _ipfix_export_flush( ipfix_t *ifh )
+ {
+ iobuf_t *buf;
+ ipfix_collector_t *col;
+@@ -2322,8 +2396,14 @@ int ipfix_export_flush( ipfix_t *ifh )
+ if ( (ifh==NULL) || (ifh->offset==0) )
+ return 0;
+
+- if ( (buf=_ipfix_getbuf()) ==NULL )
++ if ( ifh->cs_tid > 0 ) {
++ /* finish current dataset */
++ _finish_cs( ifh );
++ }
++
++ if ( (buf=_ipfix_getbuf()) ==NULL ) {
+ return -1;
++ }
+
+ #ifdef DEBUG
+ mlogf( 0, "[ipfix_export_flush] msg has %d records, %d bytes\n",
+@@ -2350,3 +2430,30 @@ int ipfix_export_flush( ipfix_t *ifh )
+ _ipfix_freebuf( buf );
+ return ret;
+ }
++
++int ipfix_export_array( ipfix_t *ifh,
++ ipfix_template_t *templ,
++ int nfields,
++ void **fields,
++ uint16_t *lengths )
++{
++ int ret;
++
++ mod_lock();
++ ret = _ipfix_export_array( ifh, templ, nfields, fields, lengths );
++ mod_unlock();
++
++ return ret;
++}
++
++int ipfix_export_flush( ipfix_t *ifh )
++{
++ int ret;
++
++ mod_lock();
++ ret = _ipfix_export_flush( ifh );
++ mod_unlock();
++
++ return ret;
++}
++
+--- a/lib/ipfix.h
++++ b/lib/ipfix.h
+@@ -142,6 +142,12 @@ typedef struct
+ int nrecords; /* no. of records in buffer */
+ size_t offset; /* output buffer fill level */
+ uint32_t seqno; /* sequence no. of next message */
++
++ /* experimental */
++ int cs_tid; /* template id of current dataset */
++ int cs_bytes; /* size of current set */
++ uint8_t *cs_header; /* start of current set */
++
+ } ipfix_t;
+
+ /** exporter funcs
+--- a/lib/ipfix_col.c
++++ b/lib/ipfix_col.c
+@@ -897,6 +897,8 @@ int ipfix_decode_datarecord( ipfixt_node
+ return -1;
+ }
+
++ n->ipfixt->fields[i].elem->decode(p,p,len);
++
+ data->lens[i] = len;
+ data->addrs[i] = p;
+
+@@ -907,7 +909,7 @@ int ipfix_decode_datarecord( ipfixt_node
+ return 0;
+ }
+
+-static void do_free_datarecord( ipfix_datarecord_t *data )
++void ipfix_free_datarecord( ipfix_datarecord_t *data )
+ {
+ if ( data ) {
+ if ( data->addrs )
+@@ -925,6 +927,7 @@ int ipfix_parse_msg( ipfix_input_t *inpu
+ ipfix_hdr_t hdr; /* ipfix packet header */
+ ipfixs_node_t *s;
+ ipfix_datarecord_t data = { NULL, NULL, 0 };
++ ipfixe_node_t *e;
+ uint8_t *buf; /* ipfix payload */
+ uint16_t setid, setlen; /* set id, set lenght */
+ int i, nread, offset; /* counter */
+@@ -1042,6 +1045,12 @@ int ipfix_parse_msg( ipfix_input_t *inpu
+ err_flag = 1;
+ }
+ else {
++ for ( e=g_exporter; e!=NULL; e=e->next ) {
++ if ( e->elem->export_dset )
++ (void) e->elem->export_dset( t, buf+nread, setlen,
++ e->elem->data );
++ }
++
+ /** read data records
+ */
+ for ( offset=nread, bytesleft=setlen; bytesleft>4; ) {
+@@ -1076,11 +1085,11 @@ int ipfix_parse_msg( ipfix_input_t *inpu
+ goto errend;
+
+ end:
+- do_free_datarecord( &data );
++ ipfix_free_datarecord( &data );
+ return nread;
+
+ errend:
+- do_free_datarecord( &data );
++ ipfix_free_datarecord( &data );
+ return -1;
+ }
+
+@@ -1093,7 +1102,7 @@ void process_client_tcp( int fd, int mas
+ tcp_conn_t *tcon = (tcp_conn_t*)data;
+ char *func = "process_client_tcp";
+
+- mlogf( 3, "[%s] fd %d mask %d called.\n", func, fd, mask );
++ mlogf( 4, "[%s] fd %d mask %d called.\n", func, fd, mask );
+
+ /** read ipfix header
+ */
+--- a/lib/ipfix_col.h
++++ b/lib/ipfix_col.h
+@@ -88,6 +88,7 @@ typedef struct ipfix_col_info
+ int (*export_newsource)(ipfixs_node_t*,void*);
+ int (*export_newmsg)(ipfixs_node_t*,ipfix_hdr_t*,void*);
+ int (*export_trecord)(ipfixs_node_t*,ipfixt_node_t*,void*);
++ int (*export_dset)(ipfixt_node_t*,uint8_t*,size_t,void*);
+ int (*export_drecord)(ipfixs_node_t*,ipfixt_node_t*,
+ ipfix_datarecord_t*,void*);
+ void (*export_cleanup)(void*);
+--- a/lib/ipfix_col_files.c
++++ b/lib/ipfix_col_files.c
+@@ -68,7 +68,7 @@ static int export_newsource_file( ipfixs
+ return -1;
+ }
+ snprintf( s->fname+strlen(s->fname), PATH_MAX-strlen(s->fname),
+- "/%u", s->odid );
++ "/%u", (unsigned int)s->odid );
+ if ( (access( s->fname, R_OK ) <0 )
+ && (mkdir( s->fname, S_IRWXU ) <0) ) {
+ mlogf( 0, "[%s] cannot access dir '%s': %s\n",
+--- a/lib/ipfix_FOKUS_IEs.txt
++++ b/lib/ipfix_FOKUS_IEs.txt
+@@ -24,6 +24,8 @@
+ 196, IPFIX_FT_PKTID, 4, IPFIX_CODING_UINT, "pktId", "FOKUS packet id"
+ 197, IPFIX_FT_STARTTIME, 4, IPFIX_CODING_INT, "startTime", "FOKUS interval start"
+ 198, IPFIX_FT_ENDTIME, 4, IPFIX_CODING_INT, "endTime", "FOKUS interval end"
++199, IPFIX_FT_RTT_USEC, 8, IPFIX_CODING_UINT, "rtt_usec", "FOKUS rtt in us"
++
+ 300, IPFIX_FT_FLOWCREATIONTIMEUSEC, 4, IPFIX_CODING_INT, "flowCreationTimeUsec", "FOKUS flow start usec fraction"
+ 301, IPFIX_FT_FLOWENDTIMEUSEC, 4, IPFIX_CODING_INT, "flowEndTimeUsec", "FOKUS flow end usec fraction"
+ 303, IPFIX_FT_TC_PACKETS, 4, IPFIX_CODING_UINT, "tcPackets", "DAIDALOS Packets seen"
+@@ -39,3 +41,48 @@
+ 313, IPFIX_FT_OWDVARMIN_NSEC, 4, IPFIX_CODING_INT, "owdvarmin_nsec", "FOKUS minimum owd variance in ns"
+ 314, IPFIX_FT_OWDVARMAX_NSEC, 4, IPFIX_CODING_INT, "owdvarmax_nsec", "FOKUS maximum ow variance in ns"
+
++# Project INTERSECTION
++315, IPFIX_FT_SOURCEIPV4FANOUT, 4, IPFIX_CODING_UINT,"sourceIPv4FanOut", "FOKUS IPv4 fanout"
++316, IPFIX_FT_DESTINATIONIPV4FANIN, 4, IPFIX_CODING_UINT,"destinationIPv4FanIn", "FOKUS IPv4 fanin"
++
++# Project PRISM
++
++330, IPFIX_FT_PR_SESSIONID, 4, IPFIX_CODING_UINT, "sessionId", "PRISM Session ID"
++331, IPFIX_FT_PR_TRANSACTIONID, 4, IPFIX_CODING_UINT, "transactionId", "PRISM Transaction ID"
++332, IPFIX_FT_PR_ENCRYPTEDDATA, 65535, IPFIX_CODING_STRING, "encryptedData", "PRISM encrypted data"
++333, IPFIX_FT_PR_DECRYPTIONKEY, 65535, IPFIX_CODING_STRING, "decryptionKey", "PRISM decryption key"
++334, IPFIX_FT_PR_KEYSHARE, 65535, IPFIX_CODING_STRING, "keyShare", "PRISM key share"
++335, IPFIX_FT_PR_KEYSHAREADP, 65535, IPFIX_CODING_STRING, "keyShareAdp", "PRISM key share ADP"
++336, IPFIX_FT_PR_INITVECTOR, 65535, IPFIX_CODING_STRING, "cryptoInitVector", "PRISM crypto init vector"
++
++
++# these information elements have been defined by FOKUS for the Oracle project
++
++402, IPFIX_FT_ORsignalBandwidth, 4, IPFIX_CODING_UINT, "ORsignalBandwidth", "signal bandwidth"
++403, IPFIX_FT_ORsignalPower, 2, IPFIX_CODING_UINT, "ORsignalPower", "ERIP"
++404, IPFIX_FT_ORmodulationType, 2, IPFIX_CODING_UINT, "ORmodulationType", "AM/FM,.."
++405, IPFIX_FT_ORsymbolRate, 2, IPFIX_CODING_UINT, "ORsymbolRate", "symbol rate"
++406, IPFIX_FT_ORmodulationOrder, 1, IPFIX_CODING_UINT, "ORmodulationOrder", "number of levels"
++407, IPFIX_FT_ORrolloffFactor, 2, IPFIX_CODING_UINT, "ORrolloffFactor", "roll of factor"
++408, IPFIX_FT_ORgeopositionLon, 4, IPFIX_CODING_UINT, "ORgeopositionLon", "GPS coordinate, resolution 1 cm"
++409, IPFIX_FT_ORgeopositionLat, 4, IPFIX_CODING_UINT, "ORgeopositionLat", "GPS coordinate, resolution 1 cm"
++410, IPFIX_FT_ORgeopositionElev, 4, IPFIX_CODING_UINT, "ORgeopositionElev", "GPS coordinate, resolution 1 cm"
++411, IPFIX_FT_ORpolicyRecord, 65535, IPFIX_CODING_STRING, "ORpolicyRecord", "policy record has variable length, First 8 bits in data describe the length (in bytes) of the field"
++420, IPFIX_FT_channel_status, 1, IPFIX_CODING_UINT, "channel_status", vacancy of the scanned channel (1: channel busy, 0: channel idle)"
++421, IPFIX_FT_sensing_value, 2, IPFIX_CODING_UINT, "sensing_value", "Cost function output"
++422, IPFIX_FT_sensing_threshold, 2, IPFIX_CODING_UINT, "sensing_threshold", "Decision threshold"
++423, IPFIX_FT_OR_terminal_id, 1, IPFIX_CODING_UINT, "OR_terminal_id", "terminal identifier"
++424, IPFIX_FT_OR_terminal_id_list, 65535, IPFIX_CODING_STRING, "OR_terminal_id_list", "terminal identifier list"
++425, IPFIX_FT_Infrastructure_network_id, 1, IPFIX_CODING_UINT, "Infrastructure_network_id", "network identifier"
++426, IPFIX_FT_Infrastructure_network_type, 1, IPFIX_CODING_UINT, "Infrastructure_network_type", "network type (GSM - 1, UMTS - 2, WiMAX - 3, WiFi - 4)"
++427, IPFIX_FT_Battery_lifetime_min, 1, IPFIX_CODING_UINT, "Battery_lifetime_min", "expected battery lifetime to provide requested services or functionalities, in minutes"
++428, IPFIX_FT_Battery_lifetime_h, 1, IPFIX_CODING_UINT, "Battery_lifetime_h", "expected battery lifetime to provide requested services or functionalities, in hours"
++429, IPFIX_FT_Battery_status, 1, IPFIX_CODING_UINT, "Battery_status", "expected battery lifetime to provide requested services or functionalities, 1 bit status flag, values 1 or 0"
++430, IPFIX_FT_Cell_id_number, 4, IPFIX_CODING_UINT, "Cell_id_number", "16-32 bit cell id number, identifier"
++431, IPFIX_FT_Spectral_allocation_vector, 1, IPFIX_CODING_UINT, "Spectral_allocation_vector", "binary vector to indicate whether a band is free 1 bit 0 or not 1 bit 1"
++432, IPFIX_FT_Spectral_allocation_profile, 2, IPFIX_CODING_UINT, "Spectral_allocation_profile", "received power spectral density vs. frequency to indicate spectral activity in the band of interest (8-16 bits per discrete frequency value)"
++433, IPFIX_FT_Center_frequency, 2, IPFIX_CODING_UINT, "Center_frequency", "Center frequency of the sensed band"
++434, IPFIX_FT_Bandwidth_of_CAP, 2, IPFIX_CODING_UINT, "Bandwidth_of_CAP", "Bandwidth of the spectral allocation profile"
++435, IPFIX_FT_ORmodulation, 1, IPFIX_CODING_UINT, "ORmodulation", "CREST factor"
++436, IPFIX_FT_ORprofileRecord, 65535, IPFIX_CODING_STRING, "ORprofileRecord", "profile record has variable length, First 8 bits in data describe the length (in bytes) of the field"
++
diff --git a/package/libipfix/patches/110-wprobe_ie.patch b/package/libipfix/patches/110-wprobe_ie.patch
new file mode 100644
index 000000000..5e3728081
--- /dev/null
+++ b/package/libipfix/patches/110-wprobe_ie.patch
@@ -0,0 +1,44 @@
+--- a/lib/ipfix_FOKUS_IEs.txt
++++ b/lib/ipfix_FOKUS_IEs.txt
+@@ -86,3 +86,41 @@
+ 435, IPFIX_FT_ORmodulation, 1, IPFIX_CODING_UINT, "ORmodulation", "CREST factor"
+ 436, IPFIX_FT_ORprofileRecord, 65535, IPFIX_CODING_STRING, "ORprofileRecord", "profile record has variable length, First 8 bits in data describe the length (in bytes) of the field"
+
++500, IPFIX_FT_WPROBE_NOISE_N, 4, IPFIX_CODING_UINT, "global_noise_n", "wprobe global noice floor - Number of samples"
++501, IPFIX_FT_WPROBE_NOISE_S, 8, IPFIX_CODING_UINT, "global_noise_s", "wprobe global noice floor - Sum of samples"
++502, IPFIX_FT_WPROBE_NOISE_SS, 8, IPFIX_CODING_UINT, "global_noise_ss", "wprobe global noice floor - Sum of squared samples"
++503, IPFIX_FT_WPROBE_PHY_BUSY_N, 4, IPFIX_CODING_UINT, "global_phy_busy_n", "wprobe global airtime total - Number of samples"
++504, IPFIX_FT_WPROBE_PHY_BUSY_S, 8, IPFIX_CODING_UINT, "global_phy_busy_s", "wprobe global airtime total - Sum of samples"
++505, IPFIX_FT_WPROBE_PHY_BUSY_SS, 8, IPFIX_CODING_UINT, "global_phy_busy_ss", "wprobe global airtime total - Sum of squared samples"
++506, IPFIX_FT_WPROBE_PHY_RX_N, 4, IPFIX_CODING_UINT, "global_phy_rx_n", "wprobe global airtime total from rx-frame - Number of samples"
++507, IPFIX_FT_WPROBE_PHY_RX_S, 8, IPFIX_CODING_UINT, "global_phy_rx_s", "wprobe global airtime total from rx-frame - Sum of samples"
++508, IPFIX_FT_WPROBE_PHY_RX_SS, 8, IPFIX_CODING_UINT, "global_phy_rx_ss", "wprobe global airtime total from rx-frame - Sum of squared samples"
++509, IPFIX_FT_WPROBE_PHY_TX_N, 4, IPFIX_CODING_UINT, "global_phy_tx_n", "wprobe global airtime total from tx-frame - Number of samples"
++510, IPFIX_FT_WPROBE_PHY_TX_S, 8, IPFIX_CODING_UINT, "global_phy_tx_s", "wprobe global airtime total from tx-frame - Sum of samples"
++511, IPFIX_FT_WPROBE_PHY_TX_SS, 8, IPFIX_CODING_UINT, "global_phy_tx_ss", "wprobe global airtime total from tx-frame - Sum of squared samples"
++512, IPFIX_FT_WPROBE_RSSI_N, 4, IPFIX_CODING_UINT, "link_rssi_n", "wprobe link received signal strength indication - Number of samples"
++513, IPFIX_FT_WPROBE_RSSI_S, 8, IPFIX_CODING_UINT, "link_rssi_s", "wprobe link received signal strength indication - Sum of samples"
++514, IPFIX_FT_WPROBE_RSSI_SS, 8, IPFIX_CODING_UINT, "link_rssi_ss", "wprobe link received signal strength indication - Sum of squared samples"
++515, IPFIX_FT_WPROBE_SIGNAL_N, 4, IPFIX_CODING_UINT, "link_signal_n", "wprobe link signal strength in dB - Number of samples"
++516, IPFIX_FT_WPROBE_SIGNAL_S, 8, IPFIX_CODING_UINT, "link_signal_s", "wprobe link signal strength in dB - Sum of samples"
++517, IPFIX_FT_WPROBE_SIGNAL_SS, 8, IPFIX_CODING_UINT, "link_signal_ss", "wprobe link signal strength in dB - Sum of squared samples"
++518, IPFIX_FT_WPROBE_IEEE_RX_RATE_N, 4, IPFIX_CODING_UINT, "link_ieee_rx_rate_n", "wprobe link IEEE 802.11 RX data rate - Number of samples"
++519, IPFIX_FT_WPROBE_IEEE_RX_RATE_S, 8, IPFIX_CODING_UINT, "link_ieee_rx_rate_s", "wprobe link IEEE 802.11 RX data rate - Sum of samples"
++520, IPFIX_FT_WPROBE_IEEE_RX_RATE_SS, 8, IPFIX_CODING_UINT, "link_ieee_rx_rate_ss", "wprobe link IEEE 802.11 RX data rate - Sum of squared samples"
++521, IPFIX_FT_WPROBE_IEEE_TX_RATE_N, 4, IPFIX_CODING_UINT, "link_ieee_tx_rate_n", "wprobe link IEEE 802.11 TX data rate - Number of samples"
++522, IPFIX_FT_WPROBE_IEEE_TX_RATE_S, 8, IPFIX_CODING_UINT, "link_ieee_tx_rate_s", "wprobe link IEEE 802.11 TX data rate - Sum of samples"
++523, IPFIX_FT_WPROBE_IEEE_TX_RATE_SS, 8, IPFIX_CODING_UINT, "link_ieee_tx_rate_ss", "wprobe link IEEE 802.11 TX data rate - Sum of squared samples"
++524, IPFIX_FT_WPROBE_RETRANSMIT_200_N, 4, IPFIX_CODING_UINT, "link_retransmit_200_n", "wprobe link total retransmissions per packet - <200 bytes - Number of samples"
++525, IPFIX_FT_WPROBE_RETRANSMIT_200_S, 8, IPFIX_CODING_UINT, "link_retransmit_200_s", "wprobe link total retransmissions per packet - <200 bytes - Sum of samples"
++526, IPFIX_FT_WPROBE_RETRANSMIT_200_SS, 8, IPFIX_CODING_UINT, "link_retransmit_200_ss", "wprobe link total retransmissions per packet - <200 bytes - Sum of squared samples"
++527, IPFIX_FT_WPROBE_RETRANSMIT_400_N, 4, IPFIX_CODING_UINT, "link_retransmit_400_n", "wprobe link total retransmissions per packet - <400 bytes - Number of samples"
++528, IPFIX_FT_WPROBE_RETRANSMIT_400_S, 8, IPFIX_CODING_UINT, "link_retransmit_400_s", "wprobe link total retransmissions per packet - <400 bytes - Sum of samples"
++529, IPFIX_FT_WPROBE_RETRANSMIT_400_SS, 8, IPFIX_CODING_UINT, "link_retransmit_400_ss", "wprobe link total retransmissions per packet - <400 bytes - Sum of squared samples"
++530, IPFIX_FT_WPROBE_RETRANSMIT_800_N, 4, IPFIX_CODING_UINT, "link_retransmit_800_n", "wprobe link total retransmissions per packet - <800 bytes - Number of samples"
++531, IPFIX_FT_WPROBE_RETRANSMIT_800_S, 8, IPFIX_CODING_UINT, "link_retransmit_800_s", "wprobe link total retransmissions per packet - <800 bytes - Sum of samples"
++532, IPFIX_FT_WPROBE_RETRANSMIT_800_SS, 8, IPFIX_CODING_UINT, "link_retransmit_800_ss", "wprobe link total retransmissions per packet - <800 bytes - Sum of squared samples"
++533, IPFIX_FT_WPROBE_RETRANSMIT_1600_N, 4, IPFIX_CODING_UINT, "link_retransmit_1600_n", "wprobe link total retransmissions per packet - >800 bytes - Number of samples"
++534, IPFIX_FT_WPROBE_RETRANSMIT_1600_S, 8, IPFIX_CODING_UINT, "link_retransmit_1600_s", "wprobe link total retransmissions per packet - >800 bytes - Sum of samples"
++535, IPFIX_FT_WPROBE_RETRANSMIT_1600_SS, 8, IPFIX_CODING_UINT, "link_retransmit_1600_ss", "wprobe link total retransmissions per packet - >800 bytes - Sum of squared samples"
++536, IPFIX_FT_WPROBE_FRAMES, 4, IPFIX_CODING_UINT, "global_frames", "wprobe global number of 802.11 frames seen"
++537, IPFIX_FT_WPROBE_PROBEREQ, 4, IPFIX_CODING_UINT, "global_probereq", "wprobe global number of 802.11 probe requests seen"
diff --git a/package/libipfix/patches/120-ipfixmisc.patch b/package/libipfix/patches/120-ipfixmisc.patch
new file mode 100644
index 000000000..e3f5a05c6
--- /dev/null
+++ b/package/libipfix/patches/120-ipfixmisc.patch
@@ -0,0 +1,27 @@
+Index: libipfix.r51/lib/Makefile.in
+===================================================================
+--- libipfix.r51.orig/lib/Makefile.in 2008-08-05 15:15:23.000000000 +0200
++++ libipfix.r51/lib/Makefile.in 2012-06-05 19:26:34.061692890 +0200
+@@ -41,7 +41,7 @@
+ INCLS = -I. -I..
+ CFLAGS = $(CCOPT) $(INCLS) $(DEFS)
+
+-TARGETS = libmisc.a libipfix.a
++TARGETS = libipfixmisc.a libipfix.a
+ OBJS = ipfix.o ipfix_col.o ipfix_print.o \
+ ipfix_col_files.o ipfix_col_db.o @IPFIX_DB_OBJ@ @IPFIX_SSL_OBJ@
+ DEPHDR = ipfix.h ipfix_def.h ipfix_fields.h ipfix_def_fokus.h ipfix_fields_fokus.h
+@@ -60,11 +60,11 @@
+ install:
+ @[ -d ${libdir} ] || (mkdir -p ${libdir}; chmod 755 ${libdir})
+ $(INSTALL_DATA) libipfix.a ${libdir}/
+- $(INSTALL_DATA) libmisc.a ${libdir}/
++ $(INSTALL_DATA) libipfixmisc.a ${libdir}/
+ @[ -d ${includedir} ] || (mkdir -p ${includedir}; chmod 755 ${includedir})
+ $(INSTALL_HEADER) ipfix*.h mlog.h mpoll.h ${includedir}/
+
+-libmisc.a: $(MISCOBJS) Makefile
++libipfixmisc.a: $(MISCOBJS) Makefile
+ @rm -f $@
+ $(AR) rc $@ $(MISCOBJS)
+
diff --git a/package/libjson-c/Makefile b/package/libjson-c/Makefile
new file mode 100644
index 000000000..afd409b8e
--- /dev/null
+++ b/package/libjson-c/Makefile
@@ -0,0 +1,50 @@
+#
+# Copyright (C) 2006-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=json-c
+PKG_VERSION:=0.9
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://oss.metaparadigm.com/json-c/
+PKG_MD5SUM:=3a13d264528dcbaf3931b0cede24abae
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+TARGET_CFLAGS += $(FPIC)
+
+define Package/libjson
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=javascript object notation
+ URL:=http://oss.metaparadigm.com/json-c/
+endef
+
+define Package/libjson/description
+ This package contains a library for javascript object notation backends.
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/json $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libjson.{a,so*} $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/json.pc $(1)/usr/lib/pkgconfig/
+endef
+
+define Package/libjson/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libjson.so.* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,libjson))
diff --git a/package/libnl-tiny/Makefile b/package/libnl-tiny/Makefile
new file mode 100644
index 000000000..37ac26fe9
--- /dev/null
+++ b/package/libnl-tiny/Makefile
@@ -0,0 +1,52 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=libnl-tiny
+PKG_VERSION:=0.1
+PKG_RELEASE:=3
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/libnl-tiny
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=netlink socket library
+endef
+
+define Package/libnl-tiny/description
+ This package contains a stripped down version of libnl
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+TARGET_CFLAGS += $(FPIC)
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ all
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig $(1)/usr/include/libnl-tiny
+ $(CP) $(PKG_BUILD_DIR)/include/* $(1)/usr/include/libnl-tiny
+ $(CP) $(PKG_BUILD_DIR)/libnl-tiny.so $(1)/usr/lib/
+ $(CP) ./files/libnl-tiny.pc $(1)/usr/lib/pkgconfig
+endef
+
+define Package/libnl-tiny/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/libnl-tiny.so $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,libnl-tiny))
diff --git a/package/libnl-tiny/files/libnl-tiny.pc b/package/libnl-tiny/files/libnl-tiny.pc
new file mode 100644
index 000000000..8c1bf6f2b
--- /dev/null
+++ b/package/libnl-tiny/files/libnl-tiny.pc
@@ -0,0 +1,10 @@
+prefix=/usr
+exec_prefix=/usr
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include/libnl-tiny
+
+Name: libnl-tiny
+Description: Convenience library for netlink sockets
+Version: 2.0
+Libs: -L${libdir} -lnl-tiny
+Cflags:
diff --git a/package/libnl-tiny/src/Makefile b/package/libnl-tiny/src/Makefile
new file mode 100644
index 000000000..f6f90ec7f
--- /dev/null
+++ b/package/libnl-tiny/src/Makefile
@@ -0,0 +1,17 @@
+CC=gcc
+WFLAGS=-Wall
+CFLAGS=-O2
+INCLUDES=-Iinclude
+
+LIBNAME=libnl-tiny.so
+
+all: $(LIBNAME)
+
+%.o: %.c
+ $(CC) $(WFLAGS) -c -o $@ $(INCLUDES) $(CFLAGS) $<
+
+LIBNL_OBJ=nl.o handlers.o msg.o attr.o cache.o cache_mngt.o object.o socket.o error.o
+GENL_OBJ=genl.o genl_family.o genl_ctrl.o genl_mngt.o unl.o
+
+$(LIBNAME): $(LIBNL_OBJ) $(GENL_OBJ)
+ $(CC) -shared -o $@ $^
diff --git a/package/libnl-tiny/src/attr.c b/package/libnl-tiny/src/attr.c
new file mode 100644
index 000000000..e0f50611c
--- /dev/null
+++ b/package/libnl-tiny/src/attr.c
@@ -0,0 +1,668 @@
+/*
+ * lib/attr.c Netlink Attributes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+#include <netlink-local.h>
+#include <netlink/netlink.h>
+#include <netlink/utils.h>
+#include <netlink/addr.h>
+#include <netlink/attr.h>
+#include <netlink/msg.h>
+#include <linux/socket.h>
+
+/**
+ * @ingroup msg
+ * @defgroup attr Attributes
+ * Netlink Attributes Construction/Parsing Interface
+ *
+ * \section attr_sec Netlink Attributes
+ * Netlink attributes allow for data chunks of arbitary length to be
+ * attached to a netlink message. Each attribute is encoded with a
+ * type and length field, both 16 bits, stored in the attribute header
+ * preceding the attribute data. The main advantage of using attributes
+ * over packing everything into the family header is that the interface
+ * stays extendable as new attributes can supersede old attributes while
+ * remaining backwards compatible. Also attributes can be defined optional
+ * thus avoiding the transmission of unnecessary empty data blocks.
+ * Special nested attributes allow for more complex data structures to
+ * be transmitted, e.g. trees, lists, etc.
+ *
+ * While not required, netlink attributes typically follow the family
+ * header of a netlink message and must be properly aligned to NLA_ALIGNTO:
+ * @code
+ * +----------------+- - -+---------------+- - -+------------+- - -+
+ * | Netlink Header | Pad | Family Header | Pad | Attributes | Pad |
+ * +----------------+- - -+---------------+- - -+------------+- - -+
+ * @endcode
+ *
+ * The actual attributes are chained together each separately aligned to
+ * NLA_ALIGNTO. The position of an attribute is defined based on the
+ * length field of the preceding attributes:
+ * @code
+ * +-------------+- - -+-------------+- - -+------
+ * | Attribute 1 | Pad | Attribute 2 | Pad | ...
+ * +-------------+- - -+-------------+- - -+------
+ * nla_next(attr1)------^
+ * @endcode
+ *
+ * The attribute itself consists of the attribute header followed by
+ * the actual payload also aligned to NLA_ALIGNTO. The function nla_data()
+ * returns a pointer to the start of the payload while nla_len() returns
+ * the length of the payload in bytes.
+ *
+ * \b Note: Be aware, NLA_ALIGNTO equals to 4 bytes, therefore it is not
+ * safe to dereference any 64 bit data types directly.
+ *
+ * @code
+ * <----------- nla_total_size(payload) ----------->
+ * <-------- nla_attr_size(payload) --------->
+ * +------------------+- - -+- - - - - - - - - +- - -+
+ * | Attribute Header | Pad | Payload | Pad |
+ * +------------------+- - -+- - - - - - - - - +- - -+
+ * nla_data(nla)-------------^
+ * <- nla_len(nla) ->
+ * @endcode
+ *
+ * @subsection attr_datatypes Attribute Data Types
+ * A number of basic data types are supported to simplify access and
+ * validation of netlink attributes. This data type information is
+ * not encoded in the attribute, both the kernel and userspace part
+ * are required to share this information on their own.
+ *
+ * One of the major advantages of these basic types is the automatic
+ * validation of each attribute based on an attribute policy. The
+ * validation covers most of the checks required to safely use
+ * attributes and thus keeps the individual sanity check to a minimum.
+ *
+ * Never access attribute payload without ensuring basic validation
+ * first, attributes may:
+ * - not be present even though required
+ * - contain less actual payload than expected
+ * - fake a attribute length which exceeds the end of the message
+ * - contain unterminated character strings
+ *
+ * Policies are defined as array of the struct nla_policy. The array is
+ * indexed with the attribute type, therefore the array must be sized
+ * accordingly.
+ * @code
+ * static struct nla_policy my_policy[ATTR_MAX+1] = {
+ * [ATTR_FOO] = { .type = ..., .minlen = ..., .maxlen = ... },
+ * };
+ *
+ * err = nla_validate(attrs, attrlen, ATTR_MAX, &my_policy);
+ * @endcode
+ *
+ * Some basic validations are performed on every attribute, regardless of type.
+ * - If the attribute type exceeds the maximum attribute type specified or
+ * the attribute type is lesser-or-equal than zero, the attribute will
+ * be silently ignored.
+ * - If the payload length falls below the \a minlen value the attribute
+ * will be rejected.
+ * - If \a maxlen is non-zero and the payload length exceeds the \a maxlen
+ * value the attribute will be rejected.
+ *
+ *
+ * @par Unspecific Attribute (NLA_UNSPEC)
+ * This is the standard type if no type is specified. It is used for
+ * binary data of arbitary length. Typically this attribute carries
+ * a binary structure or a stream of bytes.
+ * @par
+ * @code
+ * // In this example, we will assume a binary structure requires to
+ * // be transmitted. The definition of the structure will typically
+ * // go into a header file available to both the kernel and userspace
+ * // side.
+ * //
+ * // Note: Be careful when putting 64 bit data types into a structure.
+ * // The attribute payload is only aligned to 4 bytes, dereferencing
+ * // the member may fail.
+ * struct my_struct {
+ * int a;
+ * int b;
+ * };
+ *
+ * // The validation function will not enforce an exact length match to
+ * // allow structures to grow as required. Note: While it is allowed
+ * // to add members to the end of the structure, changing the order or
+ * // inserting members in the middle of the structure will break your
+ * // binary interface.
+ * static struct nla_policy my_policy[ATTR_MAX+1] = {
+ * [ATTR_MY_STRICT] = { .type = NLA_UNSPEC,
+ * .minlen = sizeof(struct my_struct) },
+ *
+ * // The binary structure is appened to the message using nla_put()
+ * struct my_struct foo = { .a = 1, .b = 2 };
+ * nla_put(msg, ATTR_MY_STRUCT, sizeof(foo), &foo);
+ *
+ * // On the receiving side, a pointer to the structure pointing inside
+ * // the message payload is returned by nla_get().
+ * if (attrs[ATTR_MY_STRUCT])
+ * struct my_struct *foo = nla_get(attrs[ATTR_MY_STRUCT]);
+ * @endcode
+ *
+ * @par Integers (NLA_U8, NLA_U16, NLA_U32, NLA_U64)
+ * Integers come in different sizes from 8 bit to 64 bit. However, since the
+ * payload length is aligned to 4 bytes, integers smaller than 32 bit are
+ * only useful to enforce the maximum range of values.
+ * @par
+ * \b Note: There is no difference made between signed and unsigned integers.
+ * The validation only enforces the minimal payload length required to store
+ * an integer of specified type.
+ * @par
+ * @code
+ * // Even though possible, it does not make sense to specify .minlen or
+ * // .maxlen for integer types. The data types implies the corresponding
+ * // minimal payload length.
+ * static struct nla_policy my_policy[ATTR_MAX+1] = {
+ * [ATTR_FOO] = { .type = NLA_U32 },
+ *
+ * // Numeric values can be appended directly using the respective
+ * // nla_put_uxxx() function
+ * nla_put_u32(msg, ATTR_FOO, 123);
+ *
+ * // Same for the receiving side.
+ * if (attrs[ATTR_FOO])
+ * uint32_t foo = nla_get_u32(attrs[ATTR_FOO]);
+ * @endcode
+ *
+ * @par Character string (NLA_STRING)
+ * This data type represents a NUL terminated character string of variable
+ * length. For binary data streams the type NLA_UNSPEC is recommended.
+ * @par
+ * @code
+ * // Enforce a NUL terminated character string of at most 4 characters
+ * // including the NUL termination.
+ * static struct nla_policy my_policy[ATTR_MAX+1] = {
+ * [ATTR_BAR] = { .type = NLA_STRING, maxlen = 4 },
+ *
+ * // nla_put_string() creates a string attribute of the necessary length
+ * // and appends it to the message including the NUL termination.
+ * nla_put_string(msg, ATTR_BAR, "some text");
+ *
+ * // It is safe to use the returned character string directly if the
+ * // attribute has been validated as the validation enforces the proper
+ * // termination of the string.
+ * if (attrs[ATTR_BAR])
+ * char *text = nla_get_string(attrs[ATTR_BAR]);
+ * @endcode
+ *
+ * @par Flag (NLA_FLAG)
+ * This attribute type may be used to indicate the presence of a flag. The
+ * attribute is only valid if the payload length is zero. The presence of
+ * the attribute header indicates the presence of the flag.
+ * @par
+ * @code
+ * // This attribute type is special as .minlen and .maxlen have no effect.
+ * static struct nla_policy my_policy[ATTR_MAX+1] = {
+ * [ATTR_FLAG] = { .type = NLA_FLAG },
+ *
+ * // nla_put_flag() appends a zero sized attribute to the message.
+ * nla_put_flag(msg, ATTR_FLAG);
+ *
+ * // There is no need for a receival function, the presence is the value.
+ * if (attrs[ATTR_FLAG])
+ * // flag is present
+ * @endcode
+ *
+ * @par Micro Seconds (NLA_MSECS)
+ *
+ * @par Nested Attribute (NLA_NESTED)
+ * Attributes can be nested and put into a container to create groups, lists
+ * or to construct trees of attributes. Nested attributes are often used to
+ * pass attributes to a subsystem where the top layer has no knowledge of the
+ * configuration possibilities of each subsystem.
+ * @par
+ * \b Note: When validating the attributes using nlmsg_validate() or
+ * nlmsg_parse() it will only affect the top level attributes. Each
+ * level of nested attributes must be validated seperately using
+ * nla_parse_nested() or nla_validate().
+ * @par
+ * @code
+ * // The minimal length policy may be used to enforce the presence of at
+ * // least one attribute.
+ * static struct nla_policy my_policy[ATTR_MAX+1] = {
+ * [ATTR_OPTS] = { .type = NLA_NESTED, minlen = NLA_HDRLEN },
+ *
+ * // Nested attributes are constructed by enclosing the attributes
+ * // to be nested with calls to nla_nest_start() respetively nla_nest_end().
+ * struct nlattr *opts = nla_nest_start(msg, ATTR_OPTS);
+ * nla_put_u32(msg, ATTR_FOO, 123);
+ * nla_put_string(msg, ATTR_BAR, "some text");
+ * nla_nest_end(msg, opts);
+ *
+ * // Various methods exist to parse nested attributes, the easiest being
+ * // nla_parse_nested() which also allows validation in the same step.
+ * if (attrs[ATTR_OPTS]) {
+ * struct nlattr *nested[ATTR_MAX+1];
+ *
+ * nla_parse_nested(nested, ATTR_MAX, attrs[ATTR_OPTS], &policy);
+ *
+ * if (nested[ATTR_FOO])
+ * uint32_t foo = nla_get_u32(nested[ATTR_FOO]);
+ * }
+ * @endcode
+ *
+ * @subsection attr_exceptions Exception Based Attribute Construction
+ * Often a large number of attributes are added to a message in a single
+ * function. In order to simplify error handling, a second set of
+ * construction functions exist which jump to a error label when they
+ * fail instead of returning an error code. This second set consists
+ * of macros which are named after their error code based counterpart
+ * except that the name is written all uppercase.
+ *
+ * All of the macros jump to the target \c nla_put_failure if they fail.
+ * @code
+ * void my_func(struct nl_msg *msg)
+ * {
+ * NLA_PUT_U32(msg, ATTR_FOO, 10);
+ * NLA_PUT_STRING(msg, ATTR_BAR, "bar");
+ *
+ * return 0;
+ *
+ * nla_put_failure:
+ * return -NLE_NOMEM;
+ * }
+ * @endcode
+ *
+ * @subsection attr_examples Examples
+ * @par Example 1.1 Constructing a netlink message with attributes.
+ * @code
+ * struct nl_msg *build_msg(int ifindex, struct nl_addr *lladdr, int mtu)
+ * {
+ * struct nl_msg *msg;
+ * struct nlattr *info, *vlan;
+ * struct ifinfomsg ifi = {
+ * .ifi_family = AF_INET,
+ * .ifi_index = ifindex,
+ * };
+ *
+ * // Allocate a new netlink message, type=RTM_SETLINK, flags=NLM_F_ECHO
+ * if (!(msg = nlmsg_alloc_simple(RTM_SETLINK, NLM_F_ECHO)))
+ * return NULL;
+ *
+ * // Append the family specific header (struct ifinfomsg)
+ * if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0)
+ * goto nla_put_failure
+ *
+ * // Append a 32 bit integer attribute to carry the MTU
+ * NLA_PUT_U32(msg, IFLA_MTU, mtu);
+ *
+ * // Append a unspecific attribute to carry the link layer address
+ * NLA_PUT_ADDR(msg, IFLA_ADDRESS, lladdr);
+ *
+ * // Append a container for nested attributes to carry link information
+ * if (!(info = nla_nest_start(msg, IFLA_LINKINFO)))
+ * goto nla_put_failure;
+ *
+ * // Put a string attribute into the container
+ * NLA_PUT_STRING(msg, IFLA_INFO_KIND, "vlan");
+ *
+ * // Append another container inside the open container to carry
+ * // vlan specific attributes
+ * if (!(vlan = nla_nest_start(msg, IFLA_INFO_DATA)))
+ * goto nla_put_failure;
+ *
+ * // add vlan specific info attributes here...
+ *
+ * // Finish nesting the vlan attributes and close the second container.
+ * nla_nest_end(msg, vlan);
+ *
+ * // Finish nesting the link info attribute and close the first container.
+ * nla_nest_end(msg, info);
+ *
+ * return msg;
+ *
+ * // If any of the construction macros fails, we end up here.
+ * nla_put_failure:
+ * nlmsg_free(msg);
+ * return NULL;
+ * }
+ * @endcode
+ *
+ * @par Example 2.1 Parsing a netlink message with attributes.
+ * @code
+ * int parse_message(struct nl_msg *msg)
+ * {
+ * // The policy defines two attributes: a 32 bit integer and a container
+ * // for nested attributes.
+ * struct nla_policy attr_policy[ATTR_MAX+1] = {
+ * [ATTR_FOO] = { .type = NLA_U32 },
+ * [ATTR_BAR] = { .type = NLA_NESTED },
+ * };
+ * struct nlattr *attrs[ATTR_MAX+1];
+ * int err;
+ *
+ * // The nlmsg_parse() function will make sure that the message contains
+ * // enough payload to hold the header (struct my_hdr), validates any
+ * // attributes attached to the messages and stores a pointer to each
+ * // attribute in the attrs[] array accessable by attribute type.
+ * if ((err = nlmsg_parse(nlmsg_hdr(msg), sizeof(struct my_hdr), attrs,
+ * ATTR_MAX, attr_policy)) < 0)
+ * goto errout;
+ *
+ * if (attrs[ATTR_FOO]) {
+ * // It is safe to directly access the attribute payload without
+ * // any further checks since nlmsg_parse() enforced the policy.
+ * uint32_t foo = nla_get_u32(attrs[ATTR_FOO]);
+ * }
+ *
+ * if (attrs[ATTR_BAR]) {
+ * struct nlattr *nested[NESTED_MAX+1];
+ *
+ * // Attributes nested in a container can be parsed the same way
+ * // as top level attributes.
+ * if ((err = nla_parse_nested(nested, NESTED_MAX, attrs[ATTR_BAR],
+ * nested_policy)) < 0)
+ * goto errout;
+ *
+ * // Process nested attributes here.
+ * }
+ *
+ * err = 0;
+ * errout:
+ * return err;
+ * }
+ * @endcode
+ *
+ * @{
+ */
+
+/**
+ * @name Attribute Size Calculation
+ * @{
+ */
+
+/** @} */
+
+/**
+ * @name Parsing Attributes
+ * @{
+ */
+
+/**
+ * Check if the attribute header and payload can be accessed safely.
+ * @arg nla Attribute of any kind.
+ * @arg remaining Number of bytes remaining in attribute stream.
+ *
+ * Verifies that the header and payload do not exceed the number of
+ * bytes left in the attribute stream. This function must be called
+ * before access the attribute header or payload when iterating over
+ * the attribute stream using nla_next().
+ *
+ * @return True if the attribute can be accessed safely, false otherwise.
+ */
+int nla_ok(const struct nlattr *nla, int remaining)
+{
+ return remaining >= sizeof(*nla) &&
+ nla->nla_len >= sizeof(*nla) &&
+ nla->nla_len <= remaining;
+}
+
+/**
+ * Return next attribute in a stream of attributes.
+ * @arg nla Attribute of any kind.
+ * @arg remaining Variable to count remaining bytes in stream.
+ *
+ * Calculates the offset to the next attribute based on the attribute
+ * given. The attribute provided is assumed to be accessible, the
+ * caller is responsible to use nla_ok() beforehand. The offset (length
+ * of specified attribute including padding) is then subtracted from
+ * the remaining bytes variable and a pointer to the next attribute is
+ * returned.
+ *
+ * nla_next() can be called as long as remainig is >0.
+ *
+ * @return Pointer to next attribute.
+ */
+struct nlattr *nla_next(const struct nlattr *nla, int *remaining)
+{
+ int totlen = NLA_ALIGN(nla->nla_len);
+
+ *remaining -= totlen;
+ return (struct nlattr *) ((char *) nla + totlen);
+}
+
+static uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = {
+ [NLA_U8] = sizeof(uint8_t),
+ [NLA_U16] = sizeof(uint16_t),
+ [NLA_U32] = sizeof(uint32_t),
+ [NLA_U64] = sizeof(uint64_t),
+ [NLA_STRING] = 1,
+};
+
+static int validate_nla(struct nlattr *nla, int maxtype,
+ struct nla_policy *policy)
+{
+ struct nla_policy *pt;
+ int minlen = 0, type = nla_type(nla);
+
+ if (type <= 0 || type > maxtype)
+ return 0;
+
+ pt = &policy[type];
+
+ if (pt->type > NLA_TYPE_MAX)
+ BUG();
+
+ if (pt->minlen)
+ minlen = pt->minlen;
+ else if (pt->type != NLA_UNSPEC)
+ minlen = nla_attr_minlen[pt->type];
+
+ if (pt->type == NLA_FLAG && nla_len(nla) > 0)
+ return -NLE_RANGE;
+
+ if (nla_len(nla) < minlen)
+ return -NLE_RANGE;
+
+ if (pt->maxlen && nla_len(nla) > pt->maxlen)
+ return -NLE_RANGE;
+
+ if (pt->type == NLA_STRING) {
+ char *data = nla_data(nla);
+ if (data[nla_len(nla) - 1] != '\0')
+ return -NLE_INVAL;
+ }
+
+ return 0;
+}
+
+
+/**
+ * Create attribute index based on a stream of attributes.
+ * @arg tb Index array to be filled (maxtype+1 elements).
+ * @arg maxtype Maximum attribute type expected and accepted.
+ * @arg head Head of attribute stream.
+ * @arg len Length of attribute stream.
+ * @arg policy Attribute validation policy.
+ *
+ * Iterates over the stream of attributes and stores a pointer to each
+ * attribute in the index array using the attribute type as index to
+ * the array. Attribute with a type greater than the maximum type
+ * specified will be silently ignored in order to maintain backwards
+ * compatibility. If \a policy is not NULL, the attribute will be
+ * validated using the specified policy.
+ *
+ * @see nla_validate
+ * @return 0 on success or a negative error code.
+ */
+int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
+ struct nla_policy *policy)
+{
+ struct nlattr *nla;
+ int rem, err;
+
+ memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
+
+ nla_for_each_attr(nla, head, len, rem) {
+ int type = nla_type(nla);
+
+ if (type == 0) {
+ fprintf(stderr, "Illegal nla->nla_type == 0\n");
+ continue;
+ }
+
+ if (type <= maxtype) {
+ if (policy) {
+ err = validate_nla(nla, maxtype, policy);
+ if (err < 0)
+ goto errout;
+ }
+
+ tb[type] = nla;
+ }
+ }
+
+ if (rem > 0)
+ fprintf(stderr, "netlink: %d bytes leftover after parsing "
+ "attributes.\n", rem);
+
+ err = 0;
+errout:
+ return err;
+}
+
+/**
+ * Validate a stream of attributes.
+ * @arg head Head of attributes stream.
+ * @arg len Length of attributes stream.
+ * @arg maxtype Maximum attribute type expected and accepted.
+ * @arg policy Validation policy.
+ *
+ * Iterates over the stream of attributes and validates each attribute
+ * one by one using the specified policy. Attributes with a type greater
+ * than the maximum type specified will be silently ignored in order to
+ * maintain backwards compatibility.
+ *
+ * See \ref attr_datatypes for more details on what kind of validation
+ * checks are performed on each attribute data type.
+ *
+ * @return 0 on success or a negative error code.
+ */
+int nla_validate(struct nlattr *head, int len, int maxtype,
+ struct nla_policy *policy)
+{
+ struct nlattr *nla;
+ int rem, err;
+
+ nla_for_each_attr(nla, head, len, rem) {
+ err = validate_nla(nla, maxtype, policy);
+ if (err < 0)
+ goto errout;
+ }
+
+ err = 0;
+errout:
+ return err;
+}
+
+/**
+ * Find a single attribute in a stream of attributes.
+ * @arg head Head of attributes stream.
+ * @arg len Length of attributes stream.
+ * @arg attrtype Attribute type to look for.
+ *
+ * Iterates over the stream of attributes and compares each type with
+ * the type specified. Returns the first attribute which matches the
+ * type.
+ *
+ * @return Pointer to attribute found or NULL.
+ */
+struct nlattr *nla_find(struct nlattr *head, int len, int attrtype)
+{
+ struct nlattr *nla;
+ int rem;
+
+ nla_for_each_attr(nla, head, len, rem)
+ if (nla_type(nla) == attrtype)
+ return nla;
+
+ return NULL;
+}
+
+/** @} */
+
+/**
+ * @name Unspecific Attribute
+ * @{
+ */
+
+/**
+ * Reserve space for a attribute.
+ * @arg msg Netlink Message.
+ * @arg attrtype Attribute Type.
+ * @arg attrlen Length of payload.
+ *
+ * Reserves room for a attribute in the specified netlink message and
+ * fills in the attribute header (type, length). Returns NULL if there
+ * is unsuficient space for the attribute.
+ *
+ * Any padding between payload and the start of the next attribute is
+ * zeroed out.
+ *
+ * @return Pointer to start of attribute or NULL on failure.
+ */
+struct nlattr *nla_reserve(struct nl_msg *msg, int attrtype, int attrlen)
+{
+ struct nlattr *nla;
+ int tlen;
+
+ tlen = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) + nla_total_size(attrlen);
+
+ if ((tlen + msg->nm_nlh->nlmsg_len) > msg->nm_size)
+ return NULL;
+
+ nla = (struct nlattr *) nlmsg_tail(msg->nm_nlh);
+ nla->nla_type = attrtype;
+ nla->nla_len = nla_attr_size(attrlen);
+
+ memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen));
+ msg->nm_nlh->nlmsg_len = tlen;
+
+ NL_DBG(2, "msg %p: Reserved %d bytes at offset +%td for attr %d "
+ "nlmsg_len=%d\n", msg, attrlen,
+ (void *) nla - nlmsg_data(msg->nm_nlh),
+ attrtype, msg->nm_nlh->nlmsg_len);
+
+ return nla;
+}
+
+/**
+ * Add a unspecific attribute to netlink message.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type.
+ * @arg datalen Length of data to be used as payload.
+ * @arg data Pointer to data to be used as attribute payload.
+ *
+ * Reserves room for a unspecific attribute and copies the provided data
+ * into the message as payload of the attribute. Returns an error if there
+ * is insufficient space for the attribute.
+ *
+ * @see nla_reserve
+ * @return 0 on success or a negative error code.
+ */
+int nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data)
+{
+ struct nlattr *nla;
+
+ nla = nla_reserve(msg, attrtype, datalen);
+ if (!nla)
+ return -NLE_NOMEM;
+
+ memcpy(nla_data(nla), data, datalen);
+ NL_DBG(2, "msg %p: Wrote %d bytes at offset +%td for attr %d\n",
+ msg, datalen, (void *) nla - nlmsg_data(msg->nm_nlh), attrtype);
+
+ return 0;
+}
+
+
+
+/** @} */
diff --git a/package/libnl-tiny/src/cache.c b/package/libnl-tiny/src/cache.c
new file mode 100644
index 000000000..0e1457434
--- /dev/null
+++ b/package/libnl-tiny/src/cache.c
@@ -0,0 +1,839 @@
+/*
+ * lib/cache.c Caching Module
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+/**
+ * @ingroup cache_mngt
+ * @defgroup cache Cache
+ *
+ * @code
+ * Cache Management | | Type Specific Cache Operations
+ *
+ * | | +----------------+ +------------+
+ * | request update | | msg_parser |
+ * | | +----------------+ +------------+
+ * +- - - - -^- - - - - - - -^- -|- - - -
+ * nl_cache_update: | | | |
+ * 1) --------- co_request_update ------+ | |
+ * | | |
+ * 2) destroy old cache +----------- pp_cb ---------|---+
+ * | | |
+ * 3) ---------- nl_recvmsgs ----------+ +- cb_valid -+
+ * +--------------+ | | | |
+ * | nl_cache_add |<-----+ + - - -v- -|- - - - - - - - - - -
+ * +--------------+ | | +-------------+
+ * | nl_recvmsgs |
+ * | | +-----|-^-----+
+ * +---v-|---+
+ * | | | nl_recv |
+ * +---------+
+ * | | Core Netlink
+ * @endcode
+ *
+ * @{
+ */
+
+#include <netlink-local.h>
+#include <netlink/netlink.h>
+#include <netlink/cache.h>
+#include <netlink/object.h>
+#include <netlink/utils.h>
+
+/**
+ * @name Access Functions
+ * @{
+ */
+
+#ifdef disabled
+/**
+ * Return the number of items in the cache
+ * @arg cache cache handle
+ */
+int nl_cache_nitems(struct nl_cache *cache)
+{
+ return cache->c_nitems;
+}
+
+/**
+ * Return the number of items matching a filter in the cache
+ * @arg cache Cache object.
+ * @arg filter Filter object.
+ */
+int nl_cache_nitems_filter(struct nl_cache *cache, struct nl_object *filter)
+{
+ struct nl_object_ops *ops;
+ struct nl_object *obj;
+ int nitems = 0;
+
+ if (cache->c_ops == NULL)
+ BUG();
+
+ ops = cache->c_ops->co_obj_ops;
+
+ nl_list_for_each_entry(obj, &cache->c_items, ce_list) {
+ if (filter && !nl_object_match_filter(obj, filter))
+ continue;
+
+ nitems++;
+ }
+
+ return nitems;
+}
+
+/**
+ * Returns \b true if the cache is empty.
+ * @arg cache Cache to check
+ * @return \a true if the cache is empty, otherwise \b false is returned.
+ */
+int nl_cache_is_empty(struct nl_cache *cache)
+{
+ return nl_list_empty(&cache->c_items);
+}
+
+/**
+ * Return the operations set of the cache
+ * @arg cache cache handle
+ */
+struct nl_cache_ops *nl_cache_get_ops(struct nl_cache *cache)
+{
+ return cache->c_ops;
+}
+
+/**
+ * Return the first element in the cache
+ * @arg cache cache handle
+ */
+struct nl_object *nl_cache_get_first(struct nl_cache *cache)
+{
+ if (nl_list_empty(&cache->c_items))
+ return NULL;
+
+ return nl_list_entry(cache->c_items.next,
+ struct nl_object, ce_list);
+}
+
+/**
+ * Return the last element in the cache
+ * @arg cache cache handle
+ */
+struct nl_object *nl_cache_get_last(struct nl_cache *cache)
+{
+ if (nl_list_empty(&cache->c_items))
+ return NULL;
+
+ return nl_list_entry(cache->c_items.prev,
+ struct nl_object, ce_list);
+}
+
+/**
+ * Return the next element in the cache
+ * @arg obj current object
+ */
+struct nl_object *nl_cache_get_next(struct nl_object *obj)
+{
+ if (nl_list_at_tail(obj, &obj->ce_cache->c_items, ce_list))
+ return NULL;
+ else
+ return nl_list_entry(obj->ce_list.next,
+ struct nl_object, ce_list);
+}
+
+/**
+ * Return the previous element in the cache
+ * @arg obj current object
+ */
+struct nl_object *nl_cache_get_prev(struct nl_object *obj)
+{
+ if (nl_list_at_head(obj, &obj->ce_cache->c_items, ce_list))
+ return NULL;
+ else
+ return nl_list_entry(obj->ce_list.prev,
+ struct nl_object, ce_list);
+}
+#endif
+
+/** @} */
+
+/**
+ * @name Cache Creation/Deletion
+ * @{
+ */
+
+/**
+ * Allocate an empty cache
+ * @arg ops cache operations to base the cache on
+ *
+ * @return A newly allocated and initialized cache.
+ */
+struct nl_cache *nl_cache_alloc(struct nl_cache_ops *ops)
+{
+ struct nl_cache *cache;
+
+ cache = calloc(1, sizeof(*cache));
+ if (!cache)
+ return NULL;
+
+ nl_init_list_head(&cache->c_items);
+ cache->c_ops = ops;
+
+ NL_DBG(2, "Allocated cache %p <%s>.\n", cache, nl_cache_name(cache));
+
+ return cache;
+}
+
+int nl_cache_alloc_and_fill(struct nl_cache_ops *ops, struct nl_sock *sock,
+ struct nl_cache **result)
+{
+ struct nl_cache *cache;
+ int err;
+
+ if (!(cache = nl_cache_alloc(ops)))
+ return -NLE_NOMEM;
+
+ if (sock && (err = nl_cache_refill(sock, cache)) < 0) {
+ nl_cache_free(cache);
+ return err;
+ }
+
+ *result = cache;
+ return 0;
+}
+
+#ifdef disabled
+/**
+ * Allocate an empty cache based on type name
+ * @arg kind Name of cache type
+ * @return A newly allocated and initialized cache.
+ */
+int nl_cache_alloc_name(const char *kind, struct nl_cache **result)
+{
+ struct nl_cache_ops *ops;
+ struct nl_cache *cache;
+
+ ops = nl_cache_ops_lookup(kind);
+ if (!ops)
+ return -NLE_NOCACHE;
+
+ if (!(cache = nl_cache_alloc(ops)))
+ return -NLE_NOMEM;
+
+ *result = cache;
+ return 0;
+}
+
+/**
+ * Allocate a new cache containing a subset of a cache
+ * @arg orig Original cache to be based on
+ * @arg filter Filter defining the subset to be filled into new cache
+ * @return A newly allocated cache or NULL.
+ */
+struct nl_cache *nl_cache_subset(struct nl_cache *orig,
+ struct nl_object *filter)
+{
+ struct nl_cache *cache;
+ struct nl_object_ops *ops;
+ struct nl_object *obj;
+
+ if (!filter)
+ BUG();
+
+ cache = nl_cache_alloc(orig->c_ops);
+ if (!cache)
+ return NULL;
+
+ ops = orig->c_ops->co_obj_ops;
+
+ nl_list_for_each_entry(obj, &orig->c_items, ce_list) {
+ if (!nl_object_match_filter(obj, filter))
+ continue;
+
+ nl_cache_add(cache, obj);
+ }
+
+ return cache;
+}
+#endif
+
+/**
+ * Clear a cache.
+ * @arg cache cache to clear
+ *
+ * Removes all elements of a cache.
+ */
+void nl_cache_clear(struct nl_cache *cache)
+{
+ struct nl_object *obj, *tmp;
+
+ NL_DBG(1, "Clearing cache %p <%s>...\n", cache, nl_cache_name(cache));
+
+ nl_list_for_each_entry_safe(obj, tmp, &cache->c_items, ce_list)
+ nl_cache_remove(obj);
+}
+
+/**
+ * Free a cache.
+ * @arg cache Cache to free.
+ *
+ * Removes all elements of a cache and frees all memory.
+ *
+ * @note Use this function if you are working with allocated caches.
+ */
+void nl_cache_free(struct nl_cache *cache)
+{
+ if (!cache)
+ return;
+
+ nl_cache_clear(cache);
+ NL_DBG(1, "Freeing cache %p <%s>...\n", cache, nl_cache_name(cache));
+ free(cache);
+}
+
+/** @} */
+
+/**
+ * @name Cache Modifications
+ * @{
+ */
+
+static int __cache_add(struct nl_cache *cache, struct nl_object *obj)
+{
+ obj->ce_cache = cache;
+
+ nl_list_add_tail(&obj->ce_list, &cache->c_items);
+ cache->c_nitems++;
+
+ NL_DBG(1, "Added %p to cache %p <%s>.\n",
+ obj, cache, nl_cache_name(cache));
+
+ return 0;
+}
+
+/**
+ * Add object to a cache.
+ * @arg cache Cache to add object to
+ * @arg obj Object to be added to the cache
+ *
+ * Adds the given object to the specified cache. The object is cloned
+ * if it has been added to another cache already.
+ *
+ * @return 0 or a negative error code.
+ */
+int nl_cache_add(struct nl_cache *cache, struct nl_object *obj)
+{
+ struct nl_object *new;
+
+ if (cache->c_ops->co_obj_ops != obj->ce_ops)
+ return -NLE_OBJ_MISMATCH;
+
+ if (!nl_list_empty(&obj->ce_list)) {
+ new = nl_object_clone(obj);
+ if (!new)
+ return -NLE_NOMEM;
+ } else {
+ nl_object_get(obj);
+ new = obj;
+ }
+
+ return __cache_add(cache, new);
+}
+
+#ifdef disabled
+/**
+ * Move object from one cache to another
+ * @arg cache Cache to move object to.
+ * @arg obj Object subject to be moved
+ *
+ * Removes the given object from its associated cache if needed
+ * and adds it to the new cache.
+ *
+ * @return 0 on success or a negative error code.
+ */
+int nl_cache_move(struct nl_cache *cache, struct nl_object *obj)
+{
+ if (cache->c_ops->co_obj_ops != obj->ce_ops)
+ return -NLE_OBJ_MISMATCH;
+
+ NL_DBG(3, "Moving object %p to cache %p\n", obj, cache);
+
+ /* Acquire reference, if already in a cache this will be
+ * reverted during removal */
+ nl_object_get(obj);
+
+ if (!nl_list_empty(&obj->ce_list))
+ nl_cache_remove(obj);
+
+ return __cache_add(cache, obj);
+}
+#endif
+
+/**
+ * Removes an object from a cache.
+ * @arg obj Object to remove from its cache
+ *
+ * Removes the object \c obj from the cache it is assigned to, since
+ * an object can only be assigned to one cache at a time, the cache
+ * must ne be passed along with it.
+ */
+void nl_cache_remove(struct nl_object *obj)
+{
+ struct nl_cache *cache = obj->ce_cache;
+
+ if (cache == NULL)
+ return;
+
+ nl_list_del(&obj->ce_list);
+ obj->ce_cache = NULL;
+ nl_object_put(obj);
+ cache->c_nitems--;
+
+ NL_DBG(1, "Deleted %p from cache %p <%s>.\n",
+ obj, cache, nl_cache_name(cache));
+}
+
+#ifdef disabled
+/**
+ * Search for an object in a cache
+ * @arg cache Cache to search in.
+ * @arg needle Object to look for.
+ *
+ * Iterates over the cache and looks for an object with identical
+ * identifiers as the needle.
+ *
+ * @return Reference to object or NULL if not found.
+ * @note The returned object must be returned via nl_object_put().
+ */
+struct nl_object *nl_cache_search(struct nl_cache *cache,
+ struct nl_object *needle)
+{
+ struct nl_object *obj;
+
+ nl_list_for_each_entry(obj, &cache->c_items, ce_list) {
+ if (nl_object_identical(obj, needle)) {
+ nl_object_get(obj);
+ return obj;
+ }
+ }
+
+ return NULL;
+}
+#endif
+
+/** @} */
+
+/**
+ * @name Synchronization
+ * @{
+ */
+
+/**
+ * Request a full dump from the kernel to fill a cache
+ * @arg sk Netlink socket.
+ * @arg cache Cache subjected to be filled.
+ *
+ * Send a dumping request to the kernel causing it to dump all objects
+ * related to the specified cache to the netlink socket.
+ *
+ * Use nl_cache_pickup() to read the objects from the socket and fill them
+ * into a cache.
+ */
+int nl_cache_request_full_dump(struct nl_sock *sk, struct nl_cache *cache)
+{
+ NL_DBG(2, "Requesting dump from kernel for cache %p <%s>...\n",
+ cache, nl_cache_name(cache));
+
+ if (cache->c_ops->co_request_update == NULL)
+ return -NLE_OPNOTSUPP;
+
+ return cache->c_ops->co_request_update(cache, sk);
+}
+
+/** @cond SKIP */
+struct update_xdata {
+ struct nl_cache_ops *ops;
+ struct nl_parser_param *params;
+};
+
+static int update_msg_parser(struct nl_msg *msg, void *arg)
+{
+ struct update_xdata *x = arg;
+
+ return nl_cache_parse(x->ops, &msg->nm_src, msg->nm_nlh, x->params);
+}
+/** @endcond */
+
+int __cache_pickup(struct nl_sock *sk, struct nl_cache *cache,
+ struct nl_parser_param *param)
+{
+ int err;
+ struct nl_cb *cb;
+ struct update_xdata x = {
+ .ops = cache->c_ops,
+ .params = param,
+ };
+
+ NL_DBG(1, "Picking up answer for cache %p <%s>...\n",
+ cache, nl_cache_name(cache));
+
+ cb = nl_cb_clone(sk->s_cb);
+ if (cb == NULL)
+ return -NLE_NOMEM;
+
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, update_msg_parser, &x);
+
+ err = nl_recvmsgs(sk, cb);
+ if (err < 0)
+ NL_DBG(2, "While picking up for %p <%s>, recvmsgs() returned " \
+ "%d: %s", cache, nl_cache_name(cache),
+ err, nl_geterror(err));
+
+ nl_cb_put(cb);
+
+ return err;
+}
+
+static int pickup_cb(struct nl_object *c, struct nl_parser_param *p)
+{
+ return nl_cache_add((struct nl_cache *) p->pp_arg, c);
+}
+
+/**
+ * Pickup a netlink dump response and put it into a cache.
+ * @arg sk Netlink socket.
+ * @arg cache Cache to put items into.
+ *
+ * Waits for netlink messages to arrive, parses them and puts them into
+ * the specified cache.
+ *
+ * @return 0 on success or a negative error code.
+ */
+int nl_cache_pickup(struct nl_sock *sk, struct nl_cache *cache)
+{
+ struct nl_parser_param p = {
+ .pp_cb = pickup_cb,
+ .pp_arg = cache,
+ };
+
+ return __cache_pickup(sk, cache, &p);
+}
+
+#ifdef disabled
+static int cache_include(struct nl_cache *cache, struct nl_object *obj,
+ struct nl_msgtype *type, change_func_t cb)
+{
+ struct nl_object *old;
+
+ switch (type->mt_act) {
+ case NL_ACT_NEW:
+ case NL_ACT_DEL:
+ old = nl_cache_search(cache, obj);
+ if (old) {
+ nl_cache_remove(old);
+ if (type->mt_act == NL_ACT_DEL) {
+ if (cb)
+ cb(cache, old, NL_ACT_DEL);
+ nl_object_put(old);
+ }
+ }
+
+ if (type->mt_act == NL_ACT_NEW) {
+ nl_cache_move(cache, obj);
+ if (old == NULL && cb)
+ cb(cache, obj, NL_ACT_NEW);
+ else if (old) {
+ if (nl_object_diff(old, obj) && cb)
+ cb(cache, obj, NL_ACT_CHANGE);
+
+ nl_object_put(old);
+ }
+ }
+ break;
+ default:
+ NL_DBG(2, "Unknown action associated to object %p\n", obj);
+ return 0;
+ }
+
+ return 0;
+}
+
+int nl_cache_include(struct nl_cache *cache, struct nl_object *obj,
+ change_func_t change_cb)
+{
+ struct nl_cache_ops *ops = cache->c_ops;
+ int i;
+
+ if (ops->co_obj_ops != obj->ce_ops)
+ return -NLE_OBJ_MISMATCH;
+
+ for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++)
+ if (ops->co_msgtypes[i].mt_id == obj->ce_msgtype)
+ return cache_include(cache, obj, &ops->co_msgtypes[i],
+ change_cb);
+
+ return -NLE_MSGTYPE_NOSUPPORT;
+}
+
+static int resync_cb(struct nl_object *c, struct nl_parser_param *p)
+{
+ struct nl_cache_assoc *ca = p->pp_arg;
+
+ return nl_cache_include(ca->ca_cache, c, ca->ca_change);
+}
+
+int nl_cache_resync(struct nl_sock *sk, struct nl_cache *cache,
+ change_func_t change_cb)
+{
+ struct nl_object *obj, *next;
+ struct nl_cache_assoc ca = {
+ .ca_cache = cache,
+ .ca_change = change_cb,
+ };
+ struct nl_parser_param p = {
+ .pp_cb = resync_cb,
+ .pp_arg = &ca,
+ };
+ int err;
+
+ NL_DBG(1, "Resyncing cache %p <%s>...\n", cache, nl_cache_name(cache));
+
+ /* Mark all objects so we can see if some of them are obsolete */
+ nl_cache_mark_all(cache);
+
+ err = nl_cache_request_full_dump(sk, cache);
+ if (err < 0)
+ goto errout;
+
+ err = __cache_pickup(sk, cache, &p);
+ if (err < 0)
+ goto errout;
+
+ nl_list_for_each_entry_safe(obj, next, &cache->c_items, ce_list)
+ if (nl_object_is_marked(obj))
+ nl_cache_remove(obj);
+
+ NL_DBG(1, "Finished resyncing %p <%s>\n", cache, nl_cache_name(cache));
+
+ err = 0;
+errout:
+ return err;
+}
+#endif
+
+/** @} */
+
+/**
+ * @name Parsing
+ * @{
+ */
+
+/** @cond SKIP */
+int nl_cache_parse(struct nl_cache_ops *ops, struct sockaddr_nl *who,
+ struct nlmsghdr *nlh, struct nl_parser_param *params)
+{
+ int i, err;
+
+ if (!nlmsg_valid_hdr(nlh, ops->co_hdrsize))
+ return -NLE_MSG_TOOSHORT;
+
+ for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) {
+ if (ops->co_msgtypes[i].mt_id == nlh->nlmsg_type) {
+ err = ops->co_msg_parser(ops, who, nlh, params);
+ if (err != -NLE_OPNOTSUPP)
+ goto errout;
+ }
+ }
+
+
+ err = -NLE_MSGTYPE_NOSUPPORT;
+errout:
+ return err;
+}
+/** @endcond */
+
+/**
+ * Parse a netlink message and add it to the cache.
+ * @arg cache cache to add element to
+ * @arg msg netlink message
+ *
+ * Parses a netlink message by calling the cache specific message parser
+ * and adds the new element to the cache.
+ *
+ * @return 0 or a negative error code.
+ */
+int nl_cache_parse_and_add(struct nl_cache *cache, struct nl_msg *msg)
+{
+ struct nl_parser_param p = {
+ .pp_cb = pickup_cb,
+ .pp_arg = cache,
+ };
+
+ return nl_cache_parse(cache->c_ops, NULL, nlmsg_hdr(msg), &p);
+}
+
+/**
+ * (Re)fill a cache with the contents in the kernel.
+ * @arg sk Netlink socket.
+ * @arg cache cache to update
+ *
+ * Clears the specified cache and fills it with the current state in
+ * the kernel.
+ *
+ * @return 0 or a negative error code.
+ */
+int nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache)
+{
+ int err;
+
+ err = nl_cache_request_full_dump(sk, cache);
+ if (err < 0)
+ return err;
+
+ NL_DBG(2, "Upading cache %p <%s>, request sent, waiting for dump...\n",
+ cache, nl_cache_name(cache));
+ nl_cache_clear(cache);
+
+ return nl_cache_pickup(sk, cache);
+}
+
+/** @} */
+#ifdef disabled
+
+/**
+ * @name Utillities
+ * @{
+ */
+
+/**
+ * Mark all objects in a cache
+ * @arg cache Cache to mark all objects in
+ */
+void nl_cache_mark_all(struct nl_cache *cache)
+{
+ struct nl_object *obj;
+
+ NL_DBG(2, "Marking all objects in cache %p <%s>...\n",
+ cache, nl_cache_name(cache));
+
+ nl_list_for_each_entry(obj, &cache->c_items, ce_list)
+ nl_object_mark(obj);
+}
+
+/** @} */
+
+/**
+ * @name Dumping
+ * @{
+ */
+/**
+ * Dump all elements of a cache.
+ * @arg cache cache to dump
+ * @arg params dumping parameters
+ *
+ * Dumps all elements of the \a cache to the file descriptor \a fd.
+ */
+void nl_cache_dump(struct nl_cache *cache, struct nl_dump_params *params)
+{
+ nl_cache_dump_filter(cache, params, NULL);
+}
+
+/**
+ * Dump all elements of a cache (filtered).
+ * @arg cache cache to dump
+ * @arg params dumping parameters (optional)
+ * @arg filter filter object
+ *
+ * Dumps all elements of the \a cache to the file descriptor \a fd
+ * given they match the given filter \a filter.
+ */
+void nl_cache_dump_filter(struct nl_cache *cache,
+ struct nl_dump_params *params,
+ struct nl_object *filter)
+{
+ int type = params ? params->dp_type : NL_DUMP_DETAILS;
+ struct nl_object_ops *ops;
+ struct nl_object *obj;
+
+ NL_DBG(2, "Dumping cache %p <%s> filter %p\n",
+ cache, nl_cache_name(cache), filter);
+
+ if (type > NL_DUMP_MAX || type < 0)
+ BUG();
+
+ if (cache->c_ops == NULL)
+ BUG();
+
+ ops = cache->c_ops->co_obj_ops;
+ if (!ops->oo_dump[type])
+ return;
+
+ nl_list_for_each_entry(obj, &cache->c_items, ce_list) {
+ if (filter && !nl_object_match_filter(obj, filter))
+ continue;
+
+ NL_DBG(4, "Dumping object %p...\n", obj);
+ dump_from_ops(obj, params);
+ }
+}
+
+/** @} */
+
+/**
+ * @name Iterators
+ * @{
+ */
+
+/**
+ * Call a callback on each element of the cache.
+ * @arg cache cache to iterate on
+ * @arg cb callback function
+ * @arg arg argument passed to callback function
+ *
+ * Calls a callback function \a cb on each element of the \a cache.
+ * The argument \a arg is passed on the callback function.
+ */
+void nl_cache_foreach(struct nl_cache *cache,
+ void (*cb)(struct nl_object *, void *), void *arg)
+{
+ nl_cache_foreach_filter(cache, NULL, cb, arg);
+}
+
+/**
+ * Call a callback on each element of the cache (filtered).
+ * @arg cache cache to iterate on
+ * @arg filter filter object
+ * @arg cb callback function
+ * @arg arg argument passed to callback function
+ *
+ * Calls a callback function \a cb on each element of the \a cache
+ * that matches the \a filter. The argument \a arg is passed on
+ * to the callback function.
+ */
+void nl_cache_foreach_filter(struct nl_cache *cache, struct nl_object *filter,
+ void (*cb)(struct nl_object *, void *), void *arg)
+{
+ struct nl_object *obj, *tmp;
+ struct nl_object_ops *ops;
+
+ if (cache->c_ops == NULL)
+ BUG();
+
+ ops = cache->c_ops->co_obj_ops;
+
+ nl_list_for_each_entry_safe(obj, tmp, &cache->c_items, ce_list) {
+ if (filter && !nl_object_match_filter(obj, filter))
+ continue;
+
+ cb(obj, arg);
+ }
+}
+
+/** @} */
+#endif
+
+/** @} */
diff --git a/package/libnl-tiny/src/cache_mngt.c b/package/libnl-tiny/src/cache_mngt.c
new file mode 100644
index 000000000..5c32d2a1f
--- /dev/null
+++ b/package/libnl-tiny/src/cache_mngt.c
@@ -0,0 +1,253 @@
+/*
+ * lib/cache_mngt.c Cache Management
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+/**
+ * @ingroup core
+ * @defgroup cache_mngt Caching
+ * @{
+ */
+
+#include <netlink-local.h>
+#include <netlink/netlink.h>
+#include <netlink/cache.h>
+#include <netlink/utils.h>
+
+static struct nl_cache_ops *cache_ops;
+
+/**
+ * @name Cache Operations Sets
+ * @{
+ */
+
+/**
+ * Lookup the set cache operations of a certain cache type
+ * @arg name name of the cache type
+ *
+ * @return The cache operations or NULL if no operations
+ * have been registered under the specified name.
+ */
+struct nl_cache_ops *nl_cache_ops_lookup(const char *name)
+{
+ struct nl_cache_ops *ops;
+
+ for (ops = cache_ops; ops; ops = ops->co_next)
+ if (!strcmp(ops->co_name, name))
+ return ops;
+
+ return NULL;
+}
+
+/**
+ * Associate a message type to a set of cache operations
+ * @arg protocol netlink protocol
+ * @arg msgtype netlink message type
+ *
+ * Associates the specified netlink message type with
+ * a registered set of cache operations.
+ *
+ * @return The cache operations or NULL if no association
+ * could be made.
+ */
+struct nl_cache_ops *nl_cache_ops_associate(int protocol, int msgtype)
+{
+ int i;
+ struct nl_cache_ops *ops;
+
+ for (ops = cache_ops; ops; ops = ops->co_next) {
+ if (ops->co_protocol != protocol)
+ continue;
+
+ for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++)
+ if (ops->co_msgtypes[i].mt_id == msgtype)
+ return ops;
+ }
+
+ return NULL;
+}
+
+#ifdef disabled
+
+/**
+ * Lookup message type cache association
+ * @arg ops cache operations
+ * @arg msgtype netlink message type
+ *
+ * Searches for a matching message type association ing the specified
+ * cache operations.
+ *
+ * @return A message type association or NULL.
+ */
+struct nl_msgtype *nl_msgtype_lookup(struct nl_cache_ops *ops, int msgtype)
+{
+ int i;
+
+ for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++)
+ if (ops->co_msgtypes[i].mt_id == msgtype)
+ return &ops->co_msgtypes[i];
+
+ return NULL;
+}
+
+static struct nl_cache_ops *cache_ops_lookup_for_obj(struct nl_object_ops *obj_ops)
+{
+ struct nl_cache_ops *ops;
+
+ for (ops = cache_ops; ops; ops = ops->co_next)
+ if (ops->co_obj_ops == obj_ops)
+ return ops;
+
+ return NULL;
+
+}
+
+/**
+ * Call a function for each registered cache operation
+ * @arg cb Callback function to be called
+ * @arg arg User specific argument.
+ */
+void nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *arg)
+{
+ struct nl_cache_ops *ops;
+
+ for (ops = cache_ops; ops; ops = ops->co_next)
+ cb(ops, arg);
+}
+#endif
+
+/**
+ * Register a set of cache operations
+ * @arg ops cache operations
+ *
+ * Called by users of caches to announce the avaibility of
+ * a certain cache type.
+ *
+ * @return 0 on success or a negative error code.
+ */
+int nl_cache_mngt_register(struct nl_cache_ops *ops)
+{
+ if (!ops->co_name || !ops->co_obj_ops)
+ return -NLE_INVAL;
+
+ if (nl_cache_ops_lookup(ops->co_name))
+ return -NLE_EXIST;
+
+ ops->co_next = cache_ops;
+ cache_ops = ops;
+
+ NL_DBG(1, "Registered cache operations %s\n", ops->co_name);
+
+ return 0;
+}
+
+/**
+ * Unregister a set of cache operations
+ * @arg ops cache operations
+ *
+ * Called by users of caches to announce a set of
+ * cache operations is no longer available. The
+ * specified cache operations must have been registered
+ * previously using nl_cache_mngt_register()
+ *
+ * @return 0 on success or a negative error code
+ */
+int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
+{
+ struct nl_cache_ops *t, **tp;
+
+ for (tp = &cache_ops; (t=*tp) != NULL; tp = &t->co_next)
+ if (t == ops)
+ break;
+
+ if (!t)
+ return -NLE_NOCACHE;
+
+ NL_DBG(1, "Unregistered cache operations %s\n", ops->co_name);
+
+ *tp = t->co_next;
+ return 0;
+}
+
+/** @} */
+
+/**
+ * @name Global Cache Provisioning/Requiring
+ * @{
+ */
+#ifdef disabled
+/**
+ * Provide a cache for global use
+ * @arg cache cache to provide
+ *
+ * Offers the specified cache to be used by other modules.
+ * Only one cache per type may be shared at a time,
+ * a previsouly provided caches will be overwritten.
+ */
+void nl_cache_mngt_provide(struct nl_cache *cache)
+{
+ struct nl_cache_ops *ops;
+
+ ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops);
+ if (!ops)
+ BUG();
+ else
+ ops->co_major_cache = cache;
+}
+
+/**
+ * Unprovide a cache for global use
+ * @arg cache cache to unprovide
+ *
+ * Cancels the offer to use a cache globally. The
+ * cache will no longer be returned via lookups but
+ * may still be in use.
+ */
+void nl_cache_mngt_unprovide(struct nl_cache *cache)
+{
+ struct nl_cache_ops *ops;
+
+ ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops);
+ if (!ops)
+ BUG();
+ else if (ops->co_major_cache == cache)
+ ops->co_major_cache = NULL;
+}
+
+/**
+ * Demand the use of a global cache
+ * @arg name name of the required object type
+ *
+ * Trys to find a cache of the specified type for global
+ * use.
+ *
+ * @return A cache provided by another subsystem of the
+ * specified type marked to be available.
+ */
+struct nl_cache *nl_cache_mngt_require(const char *name)
+{
+ struct nl_cache_ops *ops;
+
+ ops = nl_cache_ops_lookup(name);
+ if (!ops || !ops->co_major_cache) {
+ fprintf(stderr, "Application BUG: Your application must "
+ "call nl_cache_mngt_provide() and\nprovide a valid "
+ "%s cache to be used for internal lookups.\nSee the "
+ " API documentation for more details.\n", name);
+
+ return NULL;
+ }
+
+ return ops->co_major_cache;
+}
+
+#endif
+/** @} */
+
+/** @} */
diff --git a/package/libnl-tiny/src/error.c b/package/libnl-tiny/src/error.c
new file mode 100644
index 000000000..71ae7220e
--- /dev/null
+++ b/package/libnl-tiny/src/error.c
@@ -0,0 +1,108 @@
+/*
+ * lib/error.c Error Handling
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+#include <netlink-local.h>
+#include <netlink/netlink.h>
+
+static const char *errmsg[NLE_MAX+1] = {
+[NLE_SUCCESS] = "Success",
+[NLE_FAILURE] = "Unspecific failure",
+[NLE_INTR] = "Interrupted system call",
+[NLE_BAD_SOCK] = "Bad socket",
+[NLE_AGAIN] = "Try again",
+[NLE_NOMEM] = "Out of memory",
+[NLE_EXIST] = "Object exists",
+[NLE_INVAL] = "Invalid input data or parameter",
+[NLE_RANGE] = "Input data out of range",
+[NLE_MSGSIZE] = "Message size not sufficient",
+[NLE_OPNOTSUPP] = "Operation not supported",
+[NLE_AF_NOSUPPORT] = "Address family not supported",
+[NLE_OBJ_NOTFOUND] = "Object not found",
+[NLE_NOATTR] = "Attribute not available",
+[NLE_MISSING_ATTR] = "Missing attribute",
+[NLE_AF_MISMATCH] = "Address family mismatch",
+[NLE_SEQ_MISMATCH] = "Message sequence number mismatch",
+[NLE_MSG_OVERFLOW] = "Kernel reported message overflow",
+[NLE_MSG_TRUNC] = "Kernel reported truncated message",
+[NLE_NOADDR] = "Invalid address for specified address family",
+[NLE_SRCRT_NOSUPPORT] = "Source based routing not supported",
+[NLE_MSG_TOOSHORT] = "Netlink message is too short",
+[NLE_MSGTYPE_NOSUPPORT] = "Netlink message type is not supported",
+[NLE_OBJ_MISMATCH] = "Object type does not match cache",
+[NLE_NOCACHE] = "Unknown or invalid cache type",
+[NLE_BUSY] = "Object busy",
+[NLE_PROTO_MISMATCH] = "Protocol mismatch",
+[NLE_NOACCESS] = "No Access",
+[NLE_PERM] = "Operation not permitted",
+};
+
+/**
+ * Return error message for an error code
+ * @return error message
+ */
+const char *nl_geterror(int error)
+{
+ error = abs(error);
+
+ if (error > NLE_MAX)
+ error = NLE_FAILURE;
+
+ return errmsg[error];
+}
+
+/**
+ * Print a libnl error message
+ * @arg s error message prefix
+ *
+ * Prints the error message of the call that failed last.
+ *
+ * If s is not NULL and *s is not a null byte the argument
+ * string is printed, followed by a colon and a blank. Then
+ * the error message and a new-line.
+ */
+void nl_perror(int error, const char *s)
+{
+ if (s && *s)
+ fprintf(stderr, "%s: %s\n", s, nl_geterror(error));
+ else
+ fprintf(stderr, "%s\n", nl_geterror(error));
+}
+
+int nl_syserr2nlerr(int error)
+{
+ error = abs(error);
+
+ switch (error) {
+ case EBADF: return NLE_BAD_SOCK;
+ case EADDRINUSE: return NLE_EXIST;
+ case EEXIST: return NLE_EXIST;
+ case EADDRNOTAVAIL: return NLE_NOADDR;
+ case ENOENT: return NLE_OBJ_NOTFOUND;
+ case EINTR: return NLE_INTR;
+ case EAGAIN: return NLE_AGAIN;
+ case ENOTSOCK: return NLE_BAD_SOCK;
+ case ENOPROTOOPT: return NLE_INVAL;
+ case EFAULT: return NLE_INVAL;
+ case EACCES: return NLE_NOACCESS;
+ case EINVAL: return NLE_INVAL;
+ case ENOBUFS: return NLE_NOMEM;
+ case ENOMEM: return NLE_NOMEM;
+ case EAFNOSUPPORT: return NLE_AF_NOSUPPORT;
+ case EPROTONOSUPPORT: return NLE_PROTO_MISMATCH;
+ case EOPNOTSUPP: return NLE_OPNOTSUPP;
+ case EPERM: return NLE_PERM;
+ case EBUSY: return NLE_BUSY;
+ default: return NLE_FAILURE;
+ }
+}
+
+/** @} */
+
diff --git a/package/libnl-tiny/src/genl.c b/package/libnl-tiny/src/genl.c
new file mode 100644
index 000000000..055be919e
--- /dev/null
+++ b/package/libnl-tiny/src/genl.c
@@ -0,0 +1,268 @@
+/*
+ * lib/genl/genl.c Generic Netlink
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+/**
+ * @defgroup genl Generic Netlink
+ *
+ * @par Message Format
+ * @code
+ * <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) --->
+ * +----------------------------+- - -+- - - - - - - - - - -+- - -+
+ * | Header | Pad | Payload | Pad |
+ * | struct nlmsghdr | | | |
+ * +----------------------------+- - -+- - - - - - - - - - -+- - -+
+ * @endcode
+ * @code
+ * <-------- GENL_HDRLEN -------> <--- hdrlen -->
+ * <------- genlmsg_len(ghdr) ------>
+ * +------------------------+- - -+---------------+- - -+------------+
+ * | Generic Netlink Header | Pad | Family Header | Pad | Attributes |
+ * | struct genlmsghdr | | | | |
+ * +------------------------+- - -+---------------+- - -+------------+
+ * genlmsg_data(ghdr)--------------^ ^
+ * genlmsg_attrdata(ghdr, hdrlen)-------------------------
+ * @endcode
+ *
+ * @par Example
+ * @code
+ * #include <netlink/netlink.h>
+ * #include <netlink/genl/genl.h>
+ * #include <netlink/genl/ctrl.h>
+ *
+ * struct nl_sock *sock;
+ * struct nl_msg *msg;
+ * int family;
+ *
+ * // Allocate a new netlink socket
+ * sock = nl_socket_alloc();
+ *
+ * // Connect to generic netlink socket on kernel side
+ * genl_connect(sock);
+ *
+ * // Ask kernel to resolve family name to family id
+ * family = genl_ctrl_resolve(sock, "generic_netlink_family_name");
+ *
+ * // Construct a generic netlink by allocating a new message, fill in
+ * // the header and append a simple integer attribute.
+ * msg = nlmsg_alloc();
+ * genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_ECHO,
+ * CMD_FOO_GET, FOO_VERSION);
+ * nla_put_u32(msg, ATTR_FOO, 123);
+ *
+ * // Send message over netlink socket
+ * nl_send_auto_complete(sock, msg);
+ *
+ * // Free message
+ * nlmsg_free(msg);
+ *
+ * // Prepare socket to receive the answer by specifying the callback
+ * // function to be called for valid messages.
+ * nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, parse_cb, NULL);
+ *
+ * // Wait for the answer and receive it
+ * nl_recvmsgs_default(sock);
+ *
+ * static int parse_cb(struct nl_msg *msg, void *arg)
+ * {
+ * struct nlmsghdr *nlh = nlmsg_hdr(msg);
+ * struct nlattr *attrs[ATTR_MAX+1];
+ *
+ * // Validate message and parse attributes
+ * genlmsg_parse(nlh, 0, attrs, ATTR_MAX, policy);
+ *
+ * if (attrs[ATTR_FOO]) {
+ * uint32_t value = nla_get_u32(attrs[ATTR_FOO]);
+ * ...
+ * }
+ *
+ * return 0;
+ * }
+ * @endcode
+ * @{
+ */
+
+#include <netlink-generic.h>
+#include <netlink/netlink.h>
+#include <netlink/genl/genl.h>
+#include <netlink/utils.h>
+
+/**
+ * @name Socket Creating
+ * @{
+ */
+
+int genl_connect(struct nl_sock *sk)
+{
+ return nl_connect(sk, NETLINK_GENERIC);
+}
+
+/** @} */
+
+/**
+ * @name Sending
+ * @{
+ */
+
+/**
+ * Send trivial generic netlink message
+ * @arg sk Netlink socket.
+ * @arg family Generic netlink family
+ * @arg cmd Command
+ * @arg version Version
+ * @arg flags Additional netlink message flags.
+ *
+ * Fills out a routing netlink request message and sends it out
+ * using nl_send_simple().
+ *
+ * @return 0 on success or a negative error code.
+ */
+int genl_send_simple(struct nl_sock *sk, int family, int cmd,
+ int version, int flags)
+{
+ struct genlmsghdr hdr = {
+ .cmd = cmd,
+ .version = version,
+ };
+
+ return nl_send_simple(sk, family, flags, &hdr, sizeof(hdr));
+}
+
+/** @} */
+
+
+/**
+ * @name Message Parsing
+ * @{
+ */
+
+int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen)
+{
+ struct genlmsghdr *ghdr;
+
+ if (!nlmsg_valid_hdr(nlh, GENL_HDRLEN))
+ return 0;
+
+ ghdr = nlmsg_data(nlh);
+ if (genlmsg_len(ghdr) < NLMSG_ALIGN(hdrlen))
+ return 0;
+
+ return 1;
+}
+
+int genlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype,
+ struct nla_policy *policy)
+{
+ struct genlmsghdr *ghdr;
+
+ if (!genlmsg_valid_hdr(nlh, hdrlen))
+ return -NLE_MSG_TOOSHORT;
+
+ ghdr = nlmsg_data(nlh);
+ return nla_validate(genlmsg_attrdata(ghdr, hdrlen),
+ genlmsg_attrlen(ghdr, hdrlen), maxtype, policy);
+}
+
+int genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
+ int maxtype, struct nla_policy *policy)
+{
+ struct genlmsghdr *ghdr;
+
+ if (!genlmsg_valid_hdr(nlh, hdrlen))
+ return -NLE_MSG_TOOSHORT;
+
+ ghdr = nlmsg_data(nlh);
+ return nla_parse(tb, maxtype, genlmsg_attrdata(ghdr, hdrlen),
+ genlmsg_attrlen(ghdr, hdrlen), policy);
+}
+
+/**
+ * Get head of message payload
+ * @arg gnlh genetlink messsage header
+ */
+void *genlmsg_data(const struct genlmsghdr *gnlh)
+{
+ return ((unsigned char *) gnlh + GENL_HDRLEN);
+}
+
+/**
+ * Get lenght of message payload
+ * @arg gnlh genetlink message header
+ */
+int genlmsg_len(const struct genlmsghdr *gnlh)
+{
+ struct nlmsghdr *nlh = (struct nlmsghdr *)((unsigned char *)gnlh -
+ NLMSG_HDRLEN);
+ return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN);
+}
+
+/**
+ * Get head of attribute data
+ * @arg gnlh generic netlink message header
+ * @arg hdrlen length of family specific header
+ */
+struct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen)
+{
+ return genlmsg_data(gnlh) + NLMSG_ALIGN(hdrlen);
+}
+
+/**
+ * Get length of attribute data
+ * @arg gnlh generic netlink message header
+ * @arg hdrlen length of family specific header
+ */
+int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen)
+{
+ return genlmsg_len(gnlh) - NLMSG_ALIGN(hdrlen);
+}
+
+/** @} */
+
+/**
+ * @name Message Building
+ * @{
+ */
+
+/**
+ * Add generic netlink header to netlink message
+ * @arg msg netlink message
+ * @arg pid netlink process id or NL_AUTO_PID
+ * @arg seq sequence number of message or NL_AUTO_SEQ
+ * @arg family generic netlink family
+ * @arg hdrlen length of user specific header
+ * @arg flags message flags
+ * @arg cmd generic netlink command
+ * @arg version protocol version
+ *
+ * Returns pointer to user specific header.
+ */
+void *genlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, int family,
+ int hdrlen, int flags, uint8_t cmd, uint8_t version)
+{
+ struct nlmsghdr *nlh;
+ struct genlmsghdr hdr = {
+ .cmd = cmd,
+ .version = version,
+ };
+
+ nlh = nlmsg_put(msg, pid, seq, family, GENL_HDRLEN + hdrlen, flags);
+ if (nlh == NULL)
+ return NULL;
+
+ memcpy(nlmsg_data(nlh), &hdr, sizeof(hdr));
+ NL_DBG(2, "msg %p: Added generic netlink header cmd=%d version=%d\n",
+ msg, cmd, version);
+
+ return nlmsg_data(nlh) + GENL_HDRLEN;
+}
+
+/** @} */
+
+/** @} */
diff --git a/package/libnl-tiny/src/genl_ctrl.c b/package/libnl-tiny/src/genl_ctrl.c
new file mode 100644
index 000000000..13016420d
--- /dev/null
+++ b/package/libnl-tiny/src/genl_ctrl.c
@@ -0,0 +1,302 @@
+/*
+ * lib/genl/ctrl.c Generic Netlink Controller
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+/**
+ * @ingroup genl_mngt
+ * @defgroup ctrl Controller
+ * @brief
+ *
+ * @{
+ */
+
+#include <netlink-generic.h>
+#include <netlink/netlink.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/mngt.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/utils.h>
+
+/** @cond SKIP */
+#define CTRL_VERSION 0x0001
+
+static struct nl_cache_ops genl_ctrl_ops;
+/** @endcond */
+
+static int ctrl_request_update(struct nl_cache *c, struct nl_sock *h)
+{
+ return genl_send_simple(h, GENL_ID_CTRL, CTRL_CMD_GETFAMILY,
+ CTRL_VERSION, NLM_F_DUMP);
+}
+
+static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
+ [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
+ [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_STRING,
+ .maxlen = GENL_NAMSIZ },
+ [CTRL_ATTR_VERSION] = { .type = NLA_U32 },
+ [CTRL_ATTR_HDRSIZE] = { .type = NLA_U32 },
+ [CTRL_ATTR_MAXATTR] = { .type = NLA_U32 },
+ [CTRL_ATTR_OPS] = { .type = NLA_NESTED },
+};
+
+static struct nla_policy family_op_policy[CTRL_ATTR_OP_MAX+1] = {
+ [CTRL_ATTR_OP_ID] = { .type = NLA_U32 },
+ [CTRL_ATTR_OP_FLAGS] = { .type = NLA_U32 },
+};
+
+static int ctrl_msg_parser(struct nl_cache_ops *ops, struct genl_cmd *cmd,
+ struct genl_info *info, void *arg)
+{
+ struct genl_family *family;
+ struct nl_parser_param *pp = arg;
+ int err;
+
+ family = genl_family_alloc();
+ if (family == NULL) {
+ err = -NLE_NOMEM;
+ goto errout;
+ }
+
+ if (info->attrs[CTRL_ATTR_FAMILY_NAME] == NULL) {
+ err = -NLE_MISSING_ATTR;
+ goto errout;
+ }
+
+ if (info->attrs[CTRL_ATTR_FAMILY_ID] == NULL) {
+ err = -NLE_MISSING_ATTR;
+ goto errout;
+ }
+
+ family->ce_msgtype = info->nlh->nlmsg_type;
+ genl_family_set_id(family,
+ nla_get_u16(info->attrs[CTRL_ATTR_FAMILY_ID]));
+ genl_family_set_name(family,
+ nla_get_string(info->attrs[CTRL_ATTR_FAMILY_NAME]));
+
+ if (info->attrs[CTRL_ATTR_VERSION]) {
+ uint32_t version = nla_get_u32(info->attrs[CTRL_ATTR_VERSION]);
+ genl_family_set_version(family, version);
+ }
+
+ if (info->attrs[CTRL_ATTR_HDRSIZE]) {
+ uint32_t hdrsize = nla_get_u32(info->attrs[CTRL_ATTR_HDRSIZE]);
+ genl_family_set_hdrsize(family, hdrsize);
+ }
+
+ if (info->attrs[CTRL_ATTR_MAXATTR]) {
+ uint32_t maxattr = nla_get_u32(info->attrs[CTRL_ATTR_MAXATTR]);
+ genl_family_set_maxattr(family, maxattr);
+ }
+
+ if (info->attrs[CTRL_ATTR_OPS]) {
+ struct nlattr *nla, *nla_ops;
+ int remaining;
+
+ nla_ops = info->attrs[CTRL_ATTR_OPS];
+ nla_for_each_nested(nla, nla_ops, remaining) {
+ struct nlattr *tb[CTRL_ATTR_OP_MAX+1];
+ int flags = 0, id;
+
+ err = nla_parse_nested(tb, CTRL_ATTR_OP_MAX, nla,
+ family_op_policy);
+ if (err < 0)
+ goto errout;
+
+ if (tb[CTRL_ATTR_OP_ID] == NULL) {
+ err = -NLE_MISSING_ATTR;
+ goto errout;
+ }
+
+ id = nla_get_u32(tb[CTRL_ATTR_OP_ID]);
+
+ if (tb[CTRL_ATTR_OP_FLAGS])
+ flags = nla_get_u32(tb[CTRL_ATTR_OP_FLAGS]);
+
+ err = genl_family_add_op(family, id, flags);
+ if (err < 0)
+ goto errout;
+
+ }
+ }
+
+ err = pp->pp_cb((struct nl_object *) family, pp);
+errout:
+ genl_family_put(family);
+ return err;
+}
+
+/**
+ * @name Cache Management
+ * @{
+ */
+
+int genl_ctrl_alloc_cache(struct nl_sock *sock, struct nl_cache **result)
+{
+ return nl_cache_alloc_and_fill(&genl_ctrl_ops, sock, result);
+}
+
+/**
+ * Look up generic netlink family by id in the provided cache.
+ * @arg cache Generic netlink family cache.
+ * @arg id Family identifier.
+ *
+ * Searches through the cache looking for a registered family
+ * matching the specified identifier. The caller will own a
+ * reference on the returned object which needs to be given
+ * back after usage using genl_family_put().
+ *
+ * @return Generic netlink family object or NULL if no match was found.
+ */
+struct genl_family *genl_ctrl_search(struct nl_cache *cache, int id)
+{
+ struct genl_family *fam;
+
+ if (cache->c_ops != &genl_ctrl_ops)
+ BUG();
+
+ nl_list_for_each_entry(fam, &cache->c_items, ce_list) {
+ if (fam->gf_id == id) {
+ nl_object_get((struct nl_object *) fam);
+ return fam;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * @name Resolver
+ * @{
+ */
+
+/**
+ * Look up generic netlink family by family name in the provided cache.
+ * @arg cache Generic netlink family cache.
+ * @arg name Family name.
+ *
+ * Searches through the cache looking for a registered family
+ * matching the specified name. The caller will own a reference
+ * on the returned object which needs to be given back after
+ * usage using genl_family_put().
+ *
+ * @return Generic netlink family object or NULL if no match was found.
+ */
+struct genl_family *genl_ctrl_search_by_name(struct nl_cache *cache,
+ const char *name)
+{
+ struct genl_family *fam;
+
+ if (cache->c_ops != &genl_ctrl_ops)
+ BUG();
+
+ nl_list_for_each_entry(fam, &cache->c_items, ce_list) {
+ if (!strcmp(name, fam->gf_name)) {
+ nl_object_get((struct nl_object *) fam);
+ return fam;
+ }
+ }
+
+ return NULL;
+}
+
+/** @} */
+
+/**
+ * Resolve generic netlink family name to its identifier
+ * @arg sk Netlink socket.
+ * @arg name Name of generic netlink family
+ *
+ * Resolves the generic netlink family name to its identifer and returns
+ * it.
+ *
+ * @return A positive identifier or a negative error code.
+ */
+int genl_ctrl_resolve(struct nl_sock *sk, const char *name)
+{
+ struct nl_cache *cache;
+ struct genl_family *family;
+ int err;
+
+ if ((err = genl_ctrl_alloc_cache(sk, &cache)) < 0)
+ return err;
+
+ family = genl_ctrl_search_by_name(cache, name);
+ if (family == NULL) {
+ err = -NLE_OBJ_NOTFOUND;
+ goto errout;
+ }
+
+ err = genl_family_get_id(family);
+ genl_family_put(family);
+errout:
+ nl_cache_free(cache);
+
+ return err;
+}
+
+/** @} */
+
+static struct genl_cmd genl_cmds[] = {
+ {
+ .c_id = CTRL_CMD_NEWFAMILY,
+ .c_name = "NEWFAMILY" ,
+ .c_maxattr = CTRL_ATTR_MAX,
+ .c_attr_policy = ctrl_policy,
+ .c_msg_parser = ctrl_msg_parser,
+ },
+ {
+ .c_id = CTRL_CMD_DELFAMILY,
+ .c_name = "DELFAMILY" ,
+ },
+ {
+ .c_id = CTRL_CMD_GETFAMILY,
+ .c_name = "GETFAMILY" ,
+ },
+ {
+ .c_id = CTRL_CMD_NEWOPS,
+ .c_name = "NEWOPS" ,
+ },
+ {
+ .c_id = CTRL_CMD_DELOPS,
+ .c_name = "DELOPS" ,
+ },
+};
+
+static struct genl_ops genl_ops = {
+ .o_cmds = genl_cmds,
+ .o_ncmds = ARRAY_SIZE(genl_cmds),
+};
+
+/** @cond SKIP */
+extern struct nl_object_ops genl_family_ops;
+/** @endcond */
+
+static struct nl_cache_ops genl_ctrl_ops = {
+ .co_name = "genl/family",
+ .co_hdrsize = GENL_HDRSIZE(0),
+ .co_msgtypes = GENL_FAMILY(GENL_ID_CTRL, "nlctrl"),
+ .co_genl = &genl_ops,
+ .co_protocol = NETLINK_GENERIC,
+ .co_request_update = ctrl_request_update,
+ .co_obj_ops = &genl_family_ops,
+};
+
+static void __init ctrl_init(void)
+{
+ genl_register(&genl_ctrl_ops);
+}
+
+static void __exit ctrl_exit(void)
+{
+ genl_unregister(&genl_ctrl_ops);
+}
+
+/** @} */
diff --git a/package/libnl-tiny/src/genl_family.c b/package/libnl-tiny/src/genl_family.c
new file mode 100644
index 000000000..88aaad9b7
--- /dev/null
+++ b/package/libnl-tiny/src/genl_family.c
@@ -0,0 +1,136 @@
+/*
+ * lib/genl/family.c Generic Netlink Family
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
+ */
+
+/**
+ * @ingroup genl
+ * @defgroup genl_family Generic Netlink Family
+ * @brief
+ *
+ * @{
+ */
+
+#include <netlink-generic.h>
+#include <netlink/netlink.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/utils.h>
+
+struct nl_object_ops genl_family_ops;
+/** @endcond */
+
+static void family_constructor(struct nl_object *c)
+{
+ struct genl_family *family = (struct genl_family *) c;
+
+ nl_init_list_head(&family->gf_ops);
+}
+
+static void family_free_data(struct nl_object *c)
+{
+ struct genl_family *family = (struct genl_family *) c;
+ struct genl_family_op *ops, *tmp;
+
+ if (family == NULL)
+ return;
+
+ nl_list_for_each_entry_safe(ops, tmp, &family->gf_ops, o_list) {
+ nl_list_del(&ops->o_list);
+ free(ops);
+ }
+}
+
+static int family_clone(struct nl_object *_dst, struct nl_object *_src)
+{
+ struct genl_family *dst = nl_object_priv(_dst);
+ struct genl_family *src = nl_object_priv(_src);
+ struct genl_family_op *ops;
+ int err;
+
+ nl_list_for_each_entry(ops, &src->gf_ops, o_list) {
+ err = genl_family_add_op(dst, ops->o_id, ops->o_flags);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int family_compare(struct nl_object *_a, struct nl_object *_b,
+ uint32_t attrs, int flags)
+{
+ struct genl_family *a = (struct genl_family *) _a;
+ struct genl_family *b = (struct genl_family *) _b;
+ int diff = 0;
+
+#define FAM_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, FAMILY_ATTR_##ATTR, a, b, EXPR)
+
+ diff |= FAM_DIFF(ID, a->gf_id != b->gf_id);
+ diff |= FAM_DIFF(VERSION, a->gf_version != b->gf_version);
+ diff |= FAM_DIFF(HDRSIZE, a->gf_hdrsize != b->gf_hdrsize);
+ diff |= FAM_DIFF(MAXATTR, a->gf_maxattr != b->gf_maxattr);
+ diff |= FAM_DIFF(NAME, strcmp(a->gf_name, b->gf_name));
+
+#undef FAM_DIFF
+
+ return diff;
+}
+
+
+/**
+ * @name Family Object
+ * @{
+ */
+
+struct genl_family *genl_family_alloc(void)
+{
+ return (struct genl_family *) nl_object_alloc(&genl_family_ops);
+}
+
+void genl_family_put(struct genl_family *family)
+{
+ nl_object_put((struct nl_object *) family);
+}
+
+/** @} */
+
+
+int genl_family_add_op(struct genl_family *family, int id, int flags)
+{
+ struct genl_family_op *op;
+
+ op = calloc(1, sizeof(*op));
+ if (op == NULL)
+ return -NLE_NOMEM;
+
+ op->o_id = id;
+ op->o_flags = flags;
+
+ nl_list_add_tail(&op->o_list, &family->gf_ops);
+ family->ce_mask |= FAMILY_ATTR_OPS;
+
+ return 0;
+}
+
+/** @} */
+
+/** @cond SKIP */
+struct nl_object_ops genl_family_ops = {
+ .oo_name = "genl/family",
+ .oo_size = sizeof(struct genl_family),
+ .oo_constructor = family_constructor,
+ .oo_free_data = family_free_data,
+ .oo_clone = family_clone,
+ .oo_compare = family_compare,
+ .oo_id_attrs = FAMILY_ATTR_ID,
+};
+/** @endcond */
+
+/** @} */
diff --git a/package/libnl-tiny/src/genl_mngt.c b/package/libnl-tiny/src/genl_mngt.c
new file mode 100644
index 000000000..6c651796c
--- /dev/null
+++ b/package/libnl-tiny/src/genl_mngt.c
@@ -0,0 +1,274 @@
+/*
+ * lib/genl/mngt.c Generic Netlink Management
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+/**
+ * @ingroup genl
+ * @defgroup genl_mngt Management
+ *
+ * @par 1) Registering a generic netlink module
+ * @code
+ * #include <netlink/genl/mngt.h>
+ *
+ * // First step is to define all the commands being used in
+ * // particular generic netlink family. The ID and name are
+ * // mandatory to be filled out. A callback function and
+ * // most the attribute policy that comes with it must be
+ * // defined for commands expected to be issued towards
+ * // userspace.
+ * static struct genl_cmd foo_cmds[] = {
+ * {
+ * .c_id = FOO_CMD_NEW,
+ * .c_name = "NEWFOO" ,
+ * .c_maxattr = FOO_ATTR_MAX,
+ * .c_attr_policy = foo_policy,
+ * .c_msg_parser = foo_msg_parser,
+ * },
+ * {
+ * .c_id = FOO_CMD_DEL,
+ * .c_name = "DELFOO" ,
+ * },
+ * };
+ *
+ * // The list of commands must then be integrated into a
+ * // struct genl_ops serving as handle for this particular
+ * // family.
+ * static struct genl_ops my_genl_ops = {
+ * .o_cmds = foo_cmds,
+ * .o_ncmds = ARRAY_SIZE(foo_cmds),
+ * };
+ *
+ * // Using the above struct genl_ops an arbitary number of
+ * // cache handles can be associated to it.
+ * //
+ * // The macro GENL_HDRSIZE() must be used to specify the
+ * // length of the header to automatically take headers on
+ * // generic layers into account.
+ * //
+ * // The macro GENL_FAMILY() is used to represent the generic
+ * // netlink family id.
+ * static struct nl_cache_ops genl_foo_ops = {
+ * .co_name = "genl/foo",
+ * .co_hdrsize = GENL_HDRSIZE(sizeof(struct my_hdr)),
+ * .co_msgtypes = GENL_FAMILY(GENL_ID_GENERATE, "foo"),
+ * .co_genl = &my_genl_ops,
+ * .co_protocol = NETLINK_GENERIC,
+ * .co_request_update = foo_request_update,
+ * .co_obj_ops = &genl_foo_ops,
+ * };
+ *
+ * // Finally each cache handle for a generic netlink family
+ * // must be registered using genl_register().
+ * static void __init foo_init(void)
+ * {
+ * genl_register(&genl_foo_ops);
+ * }
+ *
+ * // ... respectively unregsted again.
+ * static void __exit foo_exit(void)
+ * {
+ * genl_unregister(&genl_foo_ops);
+ * }
+ * @endcode
+ * @{
+ */
+
+#include <netlink-generic.h>
+#include <netlink/netlink.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/mngt.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/utils.h>
+
+static NL_LIST_HEAD(genl_ops_list);
+
+static int genl_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
+ struct nlmsghdr *nlh, struct nl_parser_param *pp)
+{
+ int i, err;
+ struct genlmsghdr *ghdr;
+ struct genl_cmd *cmd;
+
+ ghdr = nlmsg_data(nlh);
+
+ if (ops->co_genl == NULL)
+ BUG();
+
+ for (i = 0; i < ops->co_genl->o_ncmds; i++) {
+ cmd = &ops->co_genl->o_cmds[i];
+ if (cmd->c_id == ghdr->cmd)
+ goto found;
+ }
+
+ err = -NLE_MSGTYPE_NOSUPPORT;
+ goto errout;
+
+found:
+ if (cmd->c_msg_parser == NULL)
+ err = -NLE_OPNOTSUPP;
+ else {
+ struct nlattr *tb[cmd->c_maxattr + 1];
+ struct genl_info info = {
+ .who = who,
+ .nlh = nlh,
+ .genlhdr = ghdr,
+ .userhdr = genlmsg_data(ghdr),
+ .attrs = tb,
+ };
+
+ err = nlmsg_parse(nlh, ops->co_hdrsize, tb, cmd->c_maxattr,
+ cmd->c_attr_policy);
+ if (err < 0)
+ goto errout;
+
+ err = cmd->c_msg_parser(ops, cmd, &info, pp);
+ }
+errout:
+ return err;
+
+}
+
+#ifdef disabled
+char *genl_op2name(int family, int op, char *buf, size_t len)
+{
+ struct genl_ops *ops;
+ int i;
+
+ nl_list_for_each_entry(ops, &genl_ops_list, o_list) {
+ if (ops->o_family == family) {
+ for (i = 0; i < ops->o_ncmds; i++) {
+ struct genl_cmd *cmd;
+ cmd = &ops->o_cmds[i];
+
+ if (cmd->c_id == op) {
+ strncpy(buf, cmd->c_name, len - 1);
+ return buf;
+ }
+ }
+ }
+ }
+
+ strncpy(buf, "unknown", len - 1);
+ return NULL;
+}
+#endif
+
+/**
+ * @name Register/Unregister
+ * @{
+ */
+
+/**
+ * Register generic netlink operations
+ * @arg ops cache operations
+ */
+int genl_register(struct nl_cache_ops *ops)
+{
+ int err;
+
+ if (ops->co_protocol != NETLINK_GENERIC) {
+ err = -NLE_PROTO_MISMATCH;
+ goto errout;
+ }
+
+ if (ops->co_hdrsize < GENL_HDRSIZE(0)) {
+ err = -NLE_INVAL;
+ goto errout;
+ }
+
+ if (ops->co_genl == NULL) {
+ err = -NLE_INVAL;
+ goto errout;
+ }
+
+ ops->co_genl->o_cache_ops = ops;
+ ops->co_genl->o_name = ops->co_msgtypes[0].mt_name;
+ ops->co_genl->o_family = ops->co_msgtypes[0].mt_id;
+ ops->co_msg_parser = genl_msg_parser;
+
+ /* FIXME: check for dup */
+
+ nl_list_add_tail(&ops->co_genl->o_list, &genl_ops_list);
+
+ err = nl_cache_mngt_register(ops);
+errout:
+ return err;
+}
+
+/**
+ * Unregister generic netlink operations
+ * @arg ops cache operations
+ */
+void genl_unregister(struct nl_cache_ops *ops)
+{
+ nl_cache_mngt_unregister(ops);
+ nl_list_del(&ops->co_genl->o_list);
+}
+
+/** @} */
+
+/**
+ * @name Resolving ID/Name
+ * @{
+ */
+#ifdef disabled
+static int __genl_ops_resolve(struct nl_cache *ctrl, struct genl_ops *ops)
+{
+ struct genl_family *family;
+
+ family = genl_ctrl_search_by_name(ctrl, ops->o_name);
+ if (family != NULL) {
+ ops->o_id = genl_family_get_id(family);
+ genl_family_put(family);
+
+ return 0;
+ }
+
+ return -NLE_OBJ_NOTFOUND;
+}
+
+int genl_ops_resolve(struct nl_sock *sk, struct genl_ops *ops)
+{
+ struct nl_cache *ctrl;
+ int err;
+
+ if ((err = genl_ctrl_alloc_cache(sk, &ctrl)) < 0)
+ goto errout;
+
+ err = __genl_ops_resolve(ctrl, ops);
+
+ nl_cache_free(ctrl);
+errout:
+ return err;
+}
+
+int genl_mngt_resolve(struct nl_sock *sk)
+{
+ struct nl_cache *ctrl;
+ struct genl_ops *ops;
+ int err = 0;
+
+ if ((err = genl_ctrl_alloc_cache(sk, &ctrl)) < 0)
+ goto errout;
+
+ nl_list_for_each_entry(ops, &genl_ops_list, o_list) {
+ err = __genl_ops_resolve(ctrl, ops);
+ }
+
+ nl_cache_free(ctrl);
+errout:
+ return err;
+}
+#endif
+/** @} */
+
+
+/** @} */
diff --git a/package/libnl-tiny/src/handlers.c b/package/libnl-tiny/src/handlers.c
new file mode 100644
index 000000000..12ebda520
--- /dev/null
+++ b/package/libnl-tiny/src/handlers.c
@@ -0,0 +1,162 @@
+/*
+ * lib/handlers.c default netlink message handlers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+/**
+ * @ingroup core
+ * @defgroup cb Callbacks/Customization
+ *
+ * @details
+ * @par 1) Setting up a callback set
+ * @code
+ * // Allocate a callback set and initialize it to the verbose default set
+ * struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE);
+ *
+ * // Modify the set to call my_func() for all valid messages
+ * nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL);
+ *
+ * // Set the error message handler to the verbose default implementation
+ * // and direct it to print all errors to the given file descriptor.
+ * FILE *file = fopen(...);
+ * nl_cb_err(cb, NL_CB_VERBOSE, NULL, file);
+ * @endcode
+ * @{
+ */
+
+#include <netlink-local.h>
+#include <netlink/netlink.h>
+#include <netlink/utils.h>
+#include <netlink/msg.h>
+#include <netlink/handlers.h>
+
+/**
+ * @name Callback Handle Management
+ * @{
+ */
+
+/**
+ * Allocate a new callback handle
+ * @arg kind callback kind to be used for initialization
+ * @return Newly allocated callback handle or NULL
+ */
+struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind)
+{
+ int i;
+ struct nl_cb *cb;
+
+ if (kind < 0 || kind > NL_CB_KIND_MAX)
+ return NULL;
+
+ cb = calloc(1, sizeof(*cb));
+ if (!cb)
+ return NULL;
+
+ cb->cb_refcnt = 1;
+
+ for (i = 0; i <= NL_CB_TYPE_MAX; i++)
+ nl_cb_set(cb, i, kind, NULL, NULL);
+
+ nl_cb_err(cb, kind, NULL, NULL);
+
+ return cb;
+}
+
+/**
+ * Clone an existing callback handle
+ * @arg orig original callback handle
+ * @return Newly allocated callback handle being a duplicate of
+ * orig or NULL
+ */
+struct nl_cb *nl_cb_clone(struct nl_cb *orig)
+{
+ struct nl_cb *cb;
+
+ cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!cb)
+ return NULL;
+
+ memcpy(cb, orig, sizeof(*orig));
+ cb->cb_refcnt = 1;
+
+ return cb;
+}
+
+void nl_cb_put(struct nl_cb *cb)
+{
+ if (!cb)
+ return;
+
+ cb->cb_refcnt--;
+
+ if (cb->cb_refcnt < 0)
+ BUG();
+
+ if (cb->cb_refcnt <= 0)
+ free(cb);
+}
+
+/** @} */
+
+/**
+ * @name Callback Setup
+ * @{
+ */
+
+/**
+ * Set up a callback
+ * @arg cb callback set
+ * @arg type callback to modify
+ * @arg kind kind of implementation
+ * @arg func callback function (NL_CB_CUSTOM)
+ * @arg arg argument passed to callback
+ *
+ * @return 0 on success or a negative error code
+ */
+int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,
+ nl_recvmsg_msg_cb_t func, void *arg)
+{
+ if (type < 0 || type > NL_CB_TYPE_MAX)
+ return -NLE_RANGE;
+
+ if (kind < 0 || kind > NL_CB_KIND_MAX)
+ return -NLE_RANGE;
+
+ if (kind == NL_CB_CUSTOM) {
+ cb->cb_set[type] = func;
+ cb->cb_args[type] = arg;
+ }
+
+ return 0;
+}
+
+/**
+ * Set up an error callback
+ * @arg cb callback set
+ * @arg kind kind of callback
+ * @arg func callback function
+ * @arg arg argument to be passed to callback function
+ */
+int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind,
+ nl_recvmsg_err_cb_t func, void *arg)
+{
+ if (kind < 0 || kind > NL_CB_KIND_MAX)
+ return -NLE_RANGE;
+
+ if (kind == NL_CB_CUSTOM) {
+ cb->cb_err = func;
+ cb->cb_err_arg = arg;
+ }
+
+ return 0;
+}
+
+/** @} */
+
+/** @} */
diff --git a/package/libnl-tiny/src/include/linux/gen_stats.h b/package/libnl-tiny/src/include/linux/gen_stats.h
new file mode 100644
index 000000000..13f4e7460
--- /dev/null
+++ b/package/libnl-tiny/src/include/linux/gen_stats.h
@@ -0,0 +1,67 @@
+#ifndef __LINUX_GEN_STATS_H
+#define __LINUX_GEN_STATS_H
+
+#include <linux/types.h>
+
+enum {
+ TCA_STATS_UNSPEC,
+ TCA_STATS_BASIC,
+ TCA_STATS_RATE_EST,
+ TCA_STATS_QUEUE,
+ TCA_STATS_APP,
+ __TCA_STATS_MAX,
+};
+#define TCA_STATS_MAX (__TCA_STATS_MAX - 1)
+
+/**
+ * struct gnet_stats_basic - byte/packet throughput statistics
+ * @bytes: number of seen bytes
+ * @packets: number of seen packets
+ */
+struct gnet_stats_basic
+{
+ __u64 bytes;
+ __u32 packets;
+};
+
+/**
+ * struct gnet_stats_rate_est - rate estimator
+ * @bps: current byte rate
+ * @pps: current packet rate
+ */
+struct gnet_stats_rate_est
+{
+ __u32 bps;
+ __u32 pps;
+};
+
+/**
+ * struct gnet_stats_queue - queuing statistics
+ * @qlen: queue length
+ * @backlog: backlog size of queue
+ * @drops: number of dropped packets
+ * @requeues: number of requeues
+ * @overlimits: number of enqueues over the limit
+ */
+struct gnet_stats_queue
+{
+ __u32 qlen;
+ __u32 backlog;
+ __u32 drops;
+ __u32 requeues;
+ __u32 overlimits;
+};
+
+/**
+ * struct gnet_estimator - rate estimator configuration
+ * @interval: sampling period
+ * @ewma_log: the log of measurement window weight
+ */
+struct gnet_estimator
+{
+ signed char interval;
+ unsigned char ewma_log;
+};
+
+
+#endif /* __LINUX_GEN_STATS_H */
diff --git a/package/libnl-tiny/src/include/linux/genetlink.h b/package/libnl-tiny/src/include/linux/genetlink.h
new file mode 100644
index 000000000..b834ef6d5
--- /dev/null
+++ b/package/libnl-tiny/src/include/linux/genetlink.h
@@ -0,0 +1,83 @@
+#ifndef __LINUX_GENERIC_NETLINK_H
+#define __LINUX_GENERIC_NETLINK_H
+
+#include <linux/types.h>
+#include <linux/netlink.h>
+
+#define GENL_NAMSIZ 16 /* length of family name */
+
+#define GENL_MIN_ID NLMSG_MIN_TYPE
+#define GENL_MAX_ID 1023
+
+struct genlmsghdr {
+ __u8 cmd;
+ __u8 version;
+ __u16 reserved;
+};
+
+#define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr))
+
+#define GENL_ADMIN_PERM 0x01
+#define GENL_CMD_CAP_DO 0x02
+#define GENL_CMD_CAP_DUMP 0x04
+#define GENL_CMD_CAP_HASPOL 0x08
+
+/*
+ * List of reserved static generic netlink identifiers:
+ */
+#define GENL_ID_GENERATE 0
+#define GENL_ID_CTRL NLMSG_MIN_TYPE
+
+/**************************************************************************
+ * Controller
+ **************************************************************************/
+
+enum {
+ CTRL_CMD_UNSPEC,
+ CTRL_CMD_NEWFAMILY,
+ CTRL_CMD_DELFAMILY,
+ CTRL_CMD_GETFAMILY,
+ CTRL_CMD_NEWOPS,
+ CTRL_CMD_DELOPS,
+ CTRL_CMD_GETOPS,
+ CTRL_CMD_NEWMCAST_GRP,
+ CTRL_CMD_DELMCAST_GRP,
+ CTRL_CMD_GETMCAST_GRP, /* unused */
+ __CTRL_CMD_MAX,
+};
+
+#define CTRL_CMD_MAX (__CTRL_CMD_MAX - 1)
+
+enum {
+ CTRL_ATTR_UNSPEC,
+ CTRL_ATTR_FAMILY_ID,
+ CTRL_ATTR_FAMILY_NAME,
+ CTRL_ATTR_VERSION,
+ CTRL_ATTR_HDRSIZE,
+ CTRL_ATTR_MAXATTR,
+ CTRL_ATTR_OPS,
+ CTRL_ATTR_MCAST_GROUPS,
+ __CTRL_ATTR_MAX,
+};
+
+#define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1)
+
+enum {
+ CTRL_ATTR_OP_UNSPEC,
+ CTRL_ATTR_OP_ID,
+ CTRL_ATTR_OP_FLAGS,
+ __CTRL_ATTR_OP_MAX,
+};
+
+#define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1)
+
+enum {
+ CTRL_ATTR_MCAST_GRP_UNSPEC,
+ CTRL_ATTR_MCAST_GRP_NAME,
+ CTRL_ATTR_MCAST_GRP_ID,
+ __CTRL_ATTR_MCAST_GRP_MAX,
+};
+
+#define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1)
+
+#endif /* __LINUX_GENERIC_NETLINK_H */
diff --git a/package/libnl-tiny/src/include/linux/if.h b/package/libnl-tiny/src/include/linux/if.h
new file mode 100644
index 000000000..4c1bcfec7
--- /dev/null
+++ b/package/libnl-tiny/src/include/linux/if.h
@@ -0,0 +1,131 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Global definitions for the INET interface module.
+ *
+ * Version: @(#)if.h 1.0.2 04/18/93
+ *
+ * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1982-1988
+ * Ross Biro
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_IF_H
+#define _LINUX_IF_H
+
+#include <linux/types.h> /* for "__kernel_caddr_t" et al */
+
+#define IFNAMSIZ 16
+
+/* Standard interface flags (netdevice->flags). */
+#define IFF_UP 0x1 /* interface is up */
+#define IFF_BROADCAST 0x2 /* broadcast address valid */
+#define IFF_DEBUG 0x4 /* turn on debugging */
+#define IFF_LOOPBACK 0x8 /* is a loopback net */
+#define IFF_POINTOPOINT 0x10 /* interface is has p-p link */
+#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */
+#define IFF_RUNNING 0x40 /* interface RFC2863 OPER_UP */
+#define IFF_NOARP 0x80 /* no ARP protocol */
+#define IFF_PROMISC 0x100 /* receive all packets */
+#define IFF_ALLMULTI 0x200 /* receive all multicast packets*/
+
+#define IFF_MASTER 0x400 /* master of a load balancer */
+#define IFF_SLAVE 0x800 /* slave of a load balancer */
+
+#define IFF_MULTICAST 0x1000 /* Supports multicast */
+
+#define IFF_PORTSEL 0x2000 /* can set media type */
+#define IFF_AUTOMEDIA 0x4000 /* auto media select active */
+#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/
+
+#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */
+#define IFF_DORMANT 0x20000 /* driver signals dormant */
+
+#define IFF_ECHO 0x40000 /* echo sent packets */
+
+#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\
+ IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT)
+
+/* Private (from user) interface flags (netdevice->priv_flags). */
+#define IFF_802_1Q_VLAN 0x1 /* 802.1Q VLAN device. */
+#define IFF_EBRIDGE 0x2 /* Ethernet bridging device. */
+#define IFF_SLAVE_INACTIVE 0x4 /* bonding slave not the curr. active */
+#define IFF_MASTER_8023AD 0x8 /* bonding master, 802.3ad. */
+#define IFF_MASTER_ALB 0x10 /* bonding master, balance-alb. */
+#define IFF_BONDING 0x20 /* bonding master or slave */
+#define IFF_SLAVE_NEEDARP 0x40 /* need ARPs for validation */
+#define IFF_ISATAP 0x80 /* ISATAP interface (RFC4214) */
+
+#define IF_GET_IFACE 0x0001 /* for querying only */
+#define IF_GET_PROTO 0x0002
+
+/* For definitions see hdlc.h */
+#define IF_IFACE_V35 0x1000 /* V.35 serial interface */
+#define IF_IFACE_V24 0x1001 /* V.24 serial interface */
+#define IF_IFACE_X21 0x1002 /* X.21 serial interface */
+#define IF_IFACE_T1 0x1003 /* T1 telco serial interface */
+#define IF_IFACE_E1 0x1004 /* E1 telco serial interface */
+#define IF_IFACE_SYNC_SERIAL 0x1005 /* can't be set by software */
+#define IF_IFACE_X21D 0x1006 /* X.21 Dual Clocking (FarSite) */
+
+/* For definitions see hdlc.h */
+#define IF_PROTO_HDLC 0x2000 /* raw HDLC protocol */
+#define IF_PROTO_PPP 0x2001 /* PPP protocol */
+#define IF_PROTO_CISCO 0x2002 /* Cisco HDLC protocol */
+#define IF_PROTO_FR 0x2003 /* Frame Relay protocol */
+#define IF_PROTO_FR_ADD_PVC 0x2004 /* Create FR PVC */
+#define IF_PROTO_FR_DEL_PVC 0x2005 /* Delete FR PVC */
+#define IF_PROTO_X25 0x2006 /* X.25 */
+#define IF_PROTO_HDLC_ETH 0x2007 /* raw HDLC, Ethernet emulation */
+#define IF_PROTO_FR_ADD_ETH_PVC 0x2008 /* Create FR Ethernet-bridged PVC */
+#define IF_PROTO_FR_DEL_ETH_PVC 0x2009 /* Delete FR Ethernet-bridged PVC */
+#define IF_PROTO_FR_PVC 0x200A /* for reading PVC status */
+#define IF_PROTO_FR_ETH_PVC 0x200B
+#define IF_PROTO_RAW 0x200C /* RAW Socket */
+
+/* RFC 2863 operational status */
+enum {
+ IF_OPER_UNKNOWN,
+ IF_OPER_NOTPRESENT,
+ IF_OPER_DOWN,
+ IF_OPER_LOWERLAYERDOWN,
+ IF_OPER_TESTING,
+ IF_OPER_DORMANT,
+ IF_OPER_UP,
+};
+
+/* link modes */
+enum {
+ IF_LINK_MODE_DEFAULT,
+ IF_LINK_MODE_DORMANT, /* limit upward transition to dormant */
+};
+
+/*
+ * Device mapping structure. I'd just gone off and designed a
+ * beautiful scheme using only loadable modules with arguments
+ * for driver options and along come the PCMCIA people 8)
+ *
+ * Ah well. The get() side of this is good for WDSETUP, and it'll
+ * be handy for debugging things. The set side is fine for now and
+ * being very small might be worth keeping for clean configuration.
+ */
+
+struct ifmap
+{
+ unsigned long mem_start;
+ unsigned long mem_end;
+ unsigned short base_addr;
+ unsigned char irq;
+ unsigned char dma;
+ unsigned char port;
+ /* 3 bytes spare */
+};
+
+
+#endif /* _LINUX_IF_H */
diff --git a/package/libnl-tiny/src/include/linux/if_addr.h b/package/libnl-tiny/src/include/linux/if_addr.h
new file mode 100644
index 000000000..43f3bedaa
--- /dev/null
+++ b/package/libnl-tiny/src/include/linux/if_addr.h
@@ -0,0 +1,62 @@
+#ifndef __LINUX_IF_ADDR_H
+#define __LINUX_IF_ADDR_H
+
+#include <linux/netlink.h>
+
+struct ifaddrmsg
+{
+ __u8 ifa_family;
+ __u8 ifa_prefixlen; /* The prefix length */
+ __u8 ifa_flags; /* Flags */
+ __u8 ifa_scope; /* Address scope */
+ __u32 ifa_index; /* Link index */
+};
+
+/*
+ * Important comment:
+ * IFA_ADDRESS is prefix address, rather than local interface address.
+ * It makes no difference for normally configured broadcast interfaces,
+ * but for point-to-point IFA_ADDRESS is DESTINATION address,
+ * local address is supplied in IFA_LOCAL attribute.
+ */
+enum
+{
+ IFA_UNSPEC,
+ IFA_ADDRESS,
+ IFA_LOCAL,
+ IFA_LABEL,
+ IFA_BROADCAST,
+ IFA_ANYCAST,
+ IFA_CACHEINFO,
+ IFA_MULTICAST,
+ __IFA_MAX,
+};
+
+#define IFA_MAX (__IFA_MAX - 1)
+
+/* ifa_flags */
+#define IFA_F_SECONDARY 0x01
+#define IFA_F_TEMPORARY IFA_F_SECONDARY
+
+#define IFA_F_NODAD 0x02
+#define IFA_F_OPTIMISTIC 0x04
+#define IFA_F_HOMEADDRESS 0x10
+#define IFA_F_DEPRECATED 0x20
+#define IFA_F_TENTATIVE 0x40
+#define IFA_F_PERMANENT 0x80
+
+struct ifa_cacheinfo
+{
+ __u32 ifa_prefered;
+ __u32 ifa_valid;
+ __u32 cstamp; /* created timestamp, hundredths of seconds */
+ __u32 tstamp; /* updated timestamp, hundredths of seconds */
+};
+
+/* backwards compatibility for userspace */
+#ifndef __KERNEL__
+#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
+#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
+#endif
+
+#endif
diff --git a/package/libnl-tiny/src/include/linux/netlink.h b/package/libnl-tiny/src/include/linux/netlink.h
new file mode 100644
index 000000000..d252103d2
--- /dev/null
+++ b/package/libnl-tiny/src/include/linux/netlink.h
@@ -0,0 +1,150 @@
+#ifndef __LINUX_NETLINK_H
+#define __LINUX_NETLINK_H
+
+#include <linux/socket.h> /* for sa_family_t */
+#include <linux/types.h>
+
+#define NETLINK_ROUTE 0 /* Routing/device hook */
+#define NETLINK_UNUSED 1 /* Unused number */
+#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */
+#define NETLINK_FIREWALL 3 /* Firewalling hook */
+#define NETLINK_INET_DIAG 4 /* INET socket monitoring */
+#define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */
+#define NETLINK_XFRM 6 /* ipsec */
+#define NETLINK_SELINUX 7 /* SELinux event notifications */
+#define NETLINK_ISCSI 8 /* Open-iSCSI */
+#define NETLINK_AUDIT 9 /* auditing */
+#define NETLINK_FIB_LOOKUP 10
+#define NETLINK_CONNECTOR 11
+#define NETLINK_NETFILTER 12 /* netfilter subsystem */
+#define NETLINK_IP6_FW 13
+#define NETLINK_DNRTMSG 14 /* DECnet routing messages */
+#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */
+#define NETLINK_GENERIC 16
+/* leave room for NETLINK_DM (DM Events) */
+#define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */
+#define NETLINK_ECRYPTFS 19
+
+#define MAX_LINKS 32
+
+struct sockaddr_nl
+{
+ sa_family_t nl_family; /* AF_NETLINK */
+ unsigned short nl_pad; /* zero */
+ __u32 nl_pid; /* port ID */
+ __u32 nl_groups; /* multicast groups mask */
+};
+
+struct nlmsghdr
+{
+ __u32 nlmsg_len; /* Length of message including header */
+ __u16 nlmsg_type; /* Message content */
+ __u16 nlmsg_flags; /* Additional flags */
+ __u32 nlmsg_seq; /* Sequence number */
+ __u32 nlmsg_pid; /* Sending process port ID */
+};
+
+/* Flags values */
+
+#define NLM_F_REQUEST 1 /* It is request message. */
+#define NLM_F_MULTI 2 /* Multipart message, terminated by NLMSG_DONE */
+#define NLM_F_ACK 4 /* Reply with ack, with zero or error code */
+#define NLM_F_ECHO 8 /* Echo this request */
+
+/* Modifiers to GET request */
+#define NLM_F_ROOT 0x100 /* specify tree root */
+#define NLM_F_MATCH 0x200 /* return all matching */
+#define NLM_F_ATOMIC 0x400 /* atomic GET */
+#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
+
+/* Modifiers to NEW request */
+#define NLM_F_REPLACE 0x100 /* Override existing */
+#define NLM_F_EXCL 0x200 /* Do not touch, if it exists */
+#define NLM_F_CREATE 0x400 /* Create, if it does not exist */
+#define NLM_F_APPEND 0x800 /* Add to end of list */
+
+/*
+ 4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL
+ 4.4BSD CHANGE NLM_F_REPLACE
+
+ True CHANGE NLM_F_CREATE|NLM_F_REPLACE
+ Append NLM_F_CREATE
+ Check NLM_F_EXCL
+ */
+
+#define NLMSG_ALIGNTO 4
+#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
+#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
+#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(NLMSG_HDRLEN))
+#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
+#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
+#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
+ (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
+#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \
+ (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
+ (nlh)->nlmsg_len <= (len))
+#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
+
+#define NLMSG_NOOP 0x1 /* Nothing. */
+#define NLMSG_ERROR 0x2 /* Error */
+#define NLMSG_DONE 0x3 /* End of a dump */
+#define NLMSG_OVERRUN 0x4 /* Data lost */
+
+#define NLMSG_MIN_TYPE 0x10 /* < 0x10: reserved control messages */
+
+struct nlmsgerr
+{
+ int error;
+ struct nlmsghdr msg;
+};
+
+#define NETLINK_ADD_MEMBERSHIP 1
+#define NETLINK_DROP_MEMBERSHIP 2
+#define NETLINK_PKTINFO 3
+
+struct nl_pktinfo
+{
+ __u32 group;
+};
+
+#define NET_MAJOR 36 /* Major 36 is reserved for networking */
+
+enum {
+ NETLINK_UNCONNECTED = 0,
+ NETLINK_CONNECTED,
+};
+
+/*
+ * <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
+ * +---------------------+- - -+- - - - - - - - - -+- - -+
+ * | Header | Pad | Payload | Pad |
+ * | (struct nlattr) | ing | | ing |
+ * +---------------------+- - -+- - - - - - - - - -+- - -+
+ * <-------------- nlattr->nla_len -------------->
+ */
+
+struct nlattr
+{
+ __u16 nla_len;
+ __u16 nla_type;
+};
+
+/*
+ * nla_type (16 bits)
+ * +---+---+-------------------------------+
+ * | N | O | Attribute Type |
+ * +---+---+-------------------------------+
+ * N := Carries nested attributes
+ * O := Payload stored in network byte order
+ *
+ * Note: The N and O flag are mutually exclusive.
+ */
+#define NLA_F_NESTED (1 << 15)
+#define NLA_F_NET_BYTEORDER (1 << 14)
+#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
+
+#define NLA_ALIGNTO 4
+#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
+#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr)))
+
+#endif /* __LINUX_NETLINK_H */
diff --git a/package/libnl-tiny/src/include/netlink-generic.h b/package/libnl-tiny/src/include/netlink-generic.h
new file mode 100644
index 000000000..10aa2f01b
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink-generic.h
@@ -0,0 +1,20 @@
+/*
+ * netlink-generic.h Local Generic Netlink Interface
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_GENL_PRIV_H_
+#define NETLINK_GENL_PRIV_H_
+
+#include <netlink-local.h>
+#include <netlink/netlink.h>
+
+#define GENL_HDRSIZE(hdrlen) (GENL_HDRLEN + (hdrlen))
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink-local.h b/package/libnl-tiny/src/include/netlink-local.h
new file mode 100644
index 000000000..330100e80
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink-local.h
@@ -0,0 +1,158 @@
+/*
+ * netlink-local.h Local Netlink Interface
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_LOCAL_H_
+#define NETLINK_LOCAL_H_
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <math.h>
+#include <time.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <inttypes.h>
+#include <assert.h>
+#include <limits.h>
+
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#ifndef SOL_NETLINK
+#define SOL_NETLINK 270
+#endif
+
+#include <linux/types.h>
+
+/* local header copies */
+#include <linux/if.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/pkt_sched.h>
+#include <linux/pkt_cls.h>
+#include <linux/gen_stats.h>
+
+#include <netlink/netlink.h>
+#include <netlink/handlers.h>
+#include <netlink/cache.h>
+#include <netlink/object-api.h>
+#include <netlink/cache-api.h>
+#include <netlink-types.h>
+
+struct trans_tbl {
+ int i;
+ const char *a;
+};
+
+#define __ADD(id, name) { .i = id, .a = #name },
+
+struct trans_list {
+ int i;
+ char *a;
+ struct nl_list_head list;
+};
+
+#define NL_DEBUG 1
+
+#define NL_DBG(LVL,FMT,ARG...) \
+ do {} while (0)
+
+#define BUG() \
+ do { \
+ fprintf(stderr, "BUG: %s:%d\n", \
+ __FILE__, __LINE__); \
+ assert(0); \
+ } while (0)
+
+extern int __nl_read_num_str_file(const char *path,
+ int (*cb)(long, const char *));
+
+extern int __trans_list_add(int, const char *, struct nl_list_head *);
+extern void __trans_list_clear(struct nl_list_head *);
+
+extern char *__type2str(int, char *, size_t, struct trans_tbl *, size_t);
+extern int __str2type(const char *, struct trans_tbl *, size_t);
+
+extern char *__list_type2str(int, char *, size_t, struct nl_list_head *);
+extern int __list_str2type(const char *, struct nl_list_head *);
+
+extern char *__flags2str(int, char *, size_t, struct trans_tbl *, size_t);
+extern int __str2flags(const char *, struct trans_tbl *, size_t);
+
+extern void dump_from_ops(struct nl_object *, struct nl_dump_params *);
+
+#ifdef disabled
+static inline struct nl_cache *dp_cache(struct nl_object *obj)
+{
+ if (obj->ce_cache == NULL)
+ return nl_cache_mngt_require(obj->ce_ops->oo_name);
+
+ return obj->ce_cache;
+}
+#endif
+
+static inline int nl_cb_call(struct nl_cb *cb, int type, struct nl_msg *msg)
+{
+ return cb->cb_set[type](msg, cb->cb_args[type]);
+}
+
+#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0]))
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+#define __init __attribute__ ((constructor))
+#define __exit __attribute__ ((destructor))
+#undef __deprecated
+#define __deprecated __attribute__ ((deprecated))
+
+#define min(x,y) ({ \
+ typeof(x) _x = (x); \
+ typeof(y) _y = (y); \
+ (void) (&_x == &_y); \
+ _x < _y ? _x : _y; })
+
+#define max(x,y) ({ \
+ typeof(x) _x = (x); \
+ typeof(y) _y = (y); \
+ (void) (&_x == &_y); \
+ _x > _y ? _x : _y; })
+
+extern int nl_cache_parse(struct nl_cache_ops *, struct sockaddr_nl *,
+ struct nlmsghdr *, struct nl_parser_param *);
+
+
+static inline char *nl_cache_name(struct nl_cache *cache)
+{
+ return cache->c_ops ? cache->c_ops->co_name : "unknown";
+}
+
+#define GENL_FAMILY(id, name) \
+ { \
+ { id, NL_ACT_UNSPEC, name }, \
+ END_OF_MSGTYPES_LIST, \
+ }
+
+static inline int wait_for_ack(struct nl_sock *sk)
+{
+ if (sk->s_flags & NL_NO_AUTO_ACK)
+ return 0;
+ else
+ return nl_wait_for_ack(sk);
+}
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink-types.h b/package/libnl-tiny/src/include/netlink-types.h
new file mode 100644
index 000000000..0d005935c
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink-types.h
@@ -0,0 +1,81 @@
+/*
+ * netlink-types.h Netlink Types (Private)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_LOCAL_TYPES_H_
+#define NETLINK_LOCAL_TYPES_H_
+
+#include <netlink/list.h>
+
+struct nl_cache_ops;
+struct nl_sock;
+struct nl_object;
+
+struct nl_cache
+{
+ struct nl_list_head c_items;
+ int c_nitems;
+ int c_iarg1;
+ int c_iarg2;
+ struct nl_cache_ops * c_ops;
+};
+
+struct nl_cache_assoc
+{
+ struct nl_cache * ca_cache;
+ change_func_t ca_change;
+};
+
+struct nl_cache_mngr
+{
+ int cm_protocol;
+ int cm_flags;
+ int cm_nassocs;
+ struct nl_sock * cm_handle;
+ struct nl_cache_assoc * cm_assocs;
+};
+
+struct nl_parser_param;
+
+#define LOOSE_COMPARISON 1
+
+
+struct nl_data
+{
+ size_t d_size;
+ void * d_data;
+};
+
+struct nl_addr
+{
+ int a_family;
+ unsigned int a_maxsize;
+ unsigned int a_len;
+ int a_prefixlen;
+ int a_refcnt;
+ char a_addr[0];
+};
+
+#define IFQDISCSIZ 32
+
+#define GENL_OP_HAS_POLICY 1
+#define GENL_OP_HAS_DOIT 2
+#define GENL_OP_HAS_DUMPIT 4
+
+struct genl_family_op
+{
+ uint32_t o_id;
+ uint32_t o_flags;
+
+ struct nl_list_head o_list;
+};
+
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/addr.h b/package/libnl-tiny/src/include/netlink/addr.h
new file mode 100644
index 000000000..cc3d201f9
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/addr.h
@@ -0,0 +1,69 @@
+/*
+ * netlink/addr.h Abstract Address
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_ADDR_H_
+#define NETLINK_ADDR_H_
+
+#include <netlink/netlink.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct nl_addr;
+
+/* Creation */
+extern struct nl_addr * nl_addr_alloc(size_t);
+extern struct nl_addr * nl_addr_alloc_attr(struct nlattr *, int);
+extern struct nl_addr * nl_addr_build(int, void *, size_t);
+extern int nl_addr_parse(const char *, int, struct nl_addr **);
+extern struct nl_addr * nl_addr_clone(struct nl_addr *);
+
+/* Destroyage */
+extern void nl_addr_destroy(struct nl_addr *);
+
+/* Usage Management */
+extern struct nl_addr * nl_addr_get(struct nl_addr *);
+extern void nl_addr_put(struct nl_addr *);
+extern int nl_addr_shared(struct nl_addr *);
+
+extern int nl_addr_cmp(struct nl_addr *, struct nl_addr *);
+extern int nl_addr_cmp_prefix(struct nl_addr *, struct nl_addr *);
+extern int nl_addr_iszero(struct nl_addr *);
+extern int nl_addr_valid(char *, int);
+extern int nl_addr_guess_family(struct nl_addr *);
+extern int nl_addr_fill_sockaddr(struct nl_addr *,
+ struct sockaddr *, socklen_t *);
+extern int nl_addr_info(struct nl_addr *, struct addrinfo **);
+extern int nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen);
+
+/* Access Functions */
+extern void nl_addr_set_family(struct nl_addr *, int);
+extern int nl_addr_get_family(struct nl_addr *);
+extern int nl_addr_set_binary_addr(struct nl_addr *, void *,
+ size_t);
+extern void * nl_addr_get_binary_addr(struct nl_addr *);
+extern unsigned int nl_addr_get_len(struct nl_addr *);
+extern void nl_addr_set_prefixlen(struct nl_addr *, int);
+extern unsigned int nl_addr_get_prefixlen(struct nl_addr *);
+
+/* Address Family Translations */
+extern char * nl_af2str(int, char *, size_t);
+extern int nl_str2af(const char *);
+
+/* Translations to Strings */
+extern char * nl_addr2str(struct nl_addr *, char *, size_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/attr.h b/package/libnl-tiny/src/include/netlink/attr.h
new file mode 100644
index 000000000..3b56a82dc
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/attr.h
@@ -0,0 +1,726 @@
+/*
+ * netlink/attr.h Netlink Attributes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_ATTR_H_
+#define NETLINK_ATTR_H_
+
+#include <netlink/netlink.h>
+#include <netlink/object.h>
+#include <netlink/addr.h>
+#include <netlink/data.h>
+#include <netlink/msg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct nl_msg;
+
+/**
+ * @name Basic Attribute Data Types
+ * @{
+ */
+
+ /**
+ * @ingroup attr
+ * Basic attribute data types
+ *
+ * See \ref attr_datatypes for more details.
+ */
+enum {
+ NLA_UNSPEC, /**< Unspecified type, binary data chunk */
+ NLA_U8, /**< 8 bit integer */
+ NLA_U16, /**< 16 bit integer */
+ NLA_U32, /**< 32 bit integer */
+ NLA_U64, /**< 64 bit integer */
+ NLA_STRING, /**< NUL terminated character string */
+ NLA_FLAG, /**< Flag */
+ NLA_MSECS, /**< Micro seconds (64bit) */
+ NLA_NESTED, /**< Nested attributes */
+ __NLA_TYPE_MAX,
+};
+
+#define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1)
+
+/** @} */
+
+/**
+ * @ingroup attr
+ * Attribute validation policy.
+ *
+ * See \ref attr_datatypes for more details.
+ */
+struct nla_policy {
+ /** Type of attribute or NLA_UNSPEC */
+ uint16_t type;
+
+ /** Minimal length of payload required */
+ uint16_t minlen;
+
+ /** Maximal length of payload allowed */
+ uint16_t maxlen;
+};
+
+/* Attribute parsing */
+extern int nla_ok(const struct nlattr *, int);
+extern struct nlattr * nla_next(const struct nlattr *, int *);
+extern int nla_parse(struct nlattr **, int, struct nlattr *,
+ int, struct nla_policy *);
+extern int nla_validate(struct nlattr *, int, int,
+ struct nla_policy *);
+extern struct nlattr * nla_find(struct nlattr *, int, int);
+
+/* Unspecific attribute */
+extern struct nlattr * nla_reserve(struct nl_msg *, int, int);
+extern int nla_put(struct nl_msg *, int, int, const void *);
+
+/**
+ * nlmsg_find_attr - find a specific attribute in a netlink message
+ * @arg nlh netlink message header
+ * @arg hdrlen length of familiy specific header
+ * @arg attrtype type of attribute to look for
+ *
+ * Returns the first attribute which matches the specified type.
+ */
+static inline struct nlattr *nlmsg_find_attr(struct nlmsghdr *nlh, int hdrlen, int attrtype)
+{
+ return nla_find(nlmsg_attrdata(nlh, hdrlen),
+ nlmsg_attrlen(nlh, hdrlen), attrtype);
+}
+
+
+/**
+ * Return size of attribute whithout padding.
+ * @arg payload Payload length of attribute.
+ *
+ * @code
+ * <-------- nla_attr_size(payload) --------->
+ * +------------------+- - -+- - - - - - - - - +- - -+
+ * | Attribute Header | Pad | Payload | Pad |
+ * +------------------+- - -+- - - - - - - - - +- - -+
+ * @endcode
+ *
+ * @return Size of attribute in bytes without padding.
+ */
+static inline int nla_attr_size(int payload)
+{
+ return NLA_HDRLEN + payload;
+}
+
+/**
+ * Return size of attribute including padding.
+ * @arg payload Payload length of attribute.
+ *
+ * @code
+ * <----------- nla_total_size(payload) ----------->
+ * +------------------+- - -+- - - - - - - - - +- - -+
+ * | Attribute Header | Pad | Payload | Pad |
+ * +------------------+- - -+- - - - - - - - - +- - -+
+ * @endcode
+ *
+ * @return Size of attribute in bytes.
+ */
+static inline int nla_total_size(int payload)
+{
+ return NLA_ALIGN(nla_attr_size(payload));
+}
+
+/**
+ * Return length of padding at the tail of the attribute.
+ * @arg payload Payload length of attribute.
+ *
+ * @code
+ * +------------------+- - -+- - - - - - - - - +- - -+
+ * | Attribute Header | Pad | Payload | Pad |
+ * +------------------+- - -+- - - - - - - - - +- - -+
+ * <--->
+ * @endcode
+ *
+ * @return Length of padding in bytes.
+ */
+static inline int nla_padlen(int payload)
+{
+ return nla_total_size(payload) - nla_attr_size(payload);
+}
+
+/**
+ * Return type of the attribute.
+ * @arg nla Attribute.
+ *
+ * @return Type of attribute.
+ */
+static inline int nla_type(const struct nlattr *nla)
+{
+ return nla->nla_type & NLA_TYPE_MASK;
+}
+
+/**
+ * Return pointer to the payload section.
+ * @arg nla Attribute.
+ *
+ * @return Pointer to start of payload section.
+ */
+static inline void *nla_data(const struct nlattr *nla)
+{
+ return (char *) nla + NLA_HDRLEN;
+}
+
+/**
+ * Return length of the payload .
+ * @arg nla Attribute
+ *
+ * @return Length of payload in bytes.
+ */
+static inline int nla_len(const struct nlattr *nla)
+{
+ return nla->nla_len - NLA_HDRLEN;
+}
+
+/**
+ * Copy attribute payload to another memory area.
+ * @arg dest Pointer to destination memory area.
+ * @arg src Attribute
+ * @arg count Number of bytes to copy at most.
+ *
+ * Note: The number of bytes copied is limited by the length of
+ * the attribute payload.
+ *
+ * @return The number of bytes copied to dest.
+ */
+static inline int nla_memcpy(void *dest, struct nlattr *src, int count)
+{
+ int minlen;
+
+ if (!src)
+ return 0;
+
+ minlen = min_t(int, count, nla_len(src));
+ memcpy(dest, nla_data(src), minlen);
+
+ return minlen;
+}
+
+
+/**
+ * Add abstract data as unspecific attribute to netlink message.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type.
+ * @arg data Abstract data object.
+ *
+ * Equivalent to nla_put() except that the length of the payload is
+ * derived from the abstract data object.
+ *
+ * @see nla_put
+ * @return 0 on success or a negative error code.
+ */
+static inline int nla_put_data(struct nl_msg *msg, int attrtype, struct nl_data *data)
+{
+ return nla_put(msg, attrtype, nl_data_get_size(data),
+ nl_data_get(data));
+}
+
+/**
+ * Add abstract address as unspecific attribute to netlink message.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type.
+ * @arg addr Abstract address object.
+ *
+ * @see nla_put
+ * @return 0 on success or a negative error code.
+ */
+static inline int nla_put_addr(struct nl_msg *msg, int attrtype, struct nl_addr *addr)
+{
+ return nla_put(msg, attrtype, nl_addr_get_len(addr),
+ nl_addr_get_binary_addr(addr));
+}
+
+/** @} */
+
+/**
+ * @name Integer Attributes
+ */
+
+/**
+ * Add 8 bit integer attribute to netlink message.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type.
+ * @arg value Numeric value to store as payload.
+ *
+ * @see nla_put
+ * @return 0 on success or a negative error code.
+ */
+static inline int nla_put_u8(struct nl_msg *msg, int attrtype, uint8_t value)
+{
+ return nla_put(msg, attrtype, sizeof(uint8_t), &value);
+}
+
+/**
+ * Return value of 8 bit integer attribute.
+ * @arg nla 8 bit integer attribute
+ *
+ * @return Payload as 8 bit integer.
+ */
+static inline uint8_t nla_get_u8(struct nlattr *nla)
+{
+ return *(uint8_t *) nla_data(nla);
+}
+
+/**
+ * Add 16 bit integer attribute to netlink message.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type.
+ * @arg value Numeric value to store as payload.
+ *
+ * @see nla_put
+ * @return 0 on success or a negative error code.
+ */
+static inline int nla_put_u16(struct nl_msg *msg, int attrtype, uint16_t value)
+{
+ return nla_put(msg, attrtype, sizeof(uint16_t), &value);
+}
+
+/**
+ * Return payload of 16 bit integer attribute.
+ * @arg nla 16 bit integer attribute
+ *
+ * @return Payload as 16 bit integer.
+ */
+static inline uint16_t nla_get_u16(struct nlattr *nla)
+{
+ return *(uint16_t *) nla_data(nla);
+}
+
+/**
+ * Add 32 bit integer attribute to netlink message.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type.
+ * @arg value Numeric value to store as payload.
+ *
+ * @see nla_put
+ * @return 0 on success or a negative error code.
+ */
+static inline int nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value)
+{
+ return nla_put(msg, attrtype, sizeof(uint32_t), &value);
+}
+
+/**
+ * Return payload of 32 bit integer attribute.
+ * @arg nla 32 bit integer attribute.
+ *
+ * @return Payload as 32 bit integer.
+ */
+static inline uint32_t nla_get_u32(struct nlattr *nla)
+{
+ return *(uint32_t *) nla_data(nla);
+}
+
+/**
+ * Add 64 bit integer attribute to netlink message.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type.
+ * @arg value Numeric value to store as payload.
+ *
+ * @see nla_put
+ * @return 0 on success or a negative error code.
+ */
+static inline int nla_put_u64(struct nl_msg *msg, int attrtype, uint64_t value)
+{
+ return nla_put(msg, attrtype, sizeof(uint64_t), &value);
+}
+
+/**
+ * Return payload of u64 attribute
+ * @arg nla u64 netlink attribute
+ *
+ * @return Payload as 64 bit integer.
+ */
+static inline uint64_t nla_get_u64(struct nlattr *nla)
+{
+ uint64_t tmp;
+
+ nla_memcpy(&tmp, nla, sizeof(tmp));
+
+ return tmp;
+}
+
+/**
+ * Add string attribute to netlink message.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type.
+ * @arg str NUL terminated string.
+ *
+ * @see nla_put
+ * @return 0 on success or a negative error code.
+ */
+static inline int nla_put_string(struct nl_msg *msg, int attrtype, const char *str)
+{
+ return nla_put(msg, attrtype, strlen(str) + 1, str);
+}
+
+/**
+ * Return payload of string attribute.
+ * @arg nla String attribute.
+ *
+ * @return Pointer to attribute payload.
+ */
+static inline char *nla_get_string(struct nlattr *nla)
+{
+ return (char *) nla_data(nla);
+}
+
+static inline char *nla_strdup(struct nlattr *nla)
+{
+ return strdup(nla_get_string(nla));
+}
+
+/** @} */
+
+/**
+ * @name Flag Attribute
+ */
+
+/**
+ * Add flag netlink attribute to netlink message.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type.
+ *
+ * @see nla_put
+ * @return 0 on success or a negative error code.
+ */
+static inline int nla_put_flag(struct nl_msg *msg, int attrtype)
+{
+ return nla_put(msg, attrtype, 0, NULL);
+}
+
+/**
+ * Return true if flag attribute is set.
+ * @arg nla Flag netlink attribute.
+ *
+ * @return True if flag is set, otherwise false.
+ */
+static inline int nla_get_flag(struct nlattr *nla)
+{
+ return !!nla;
+}
+
+/** @} */
+
+/**
+ * @name Microseconds Attribute
+ */
+
+/**
+ * Add a msecs netlink attribute to a netlink message
+ * @arg n netlink message
+ * @arg attrtype attribute type
+ * @arg msecs number of msecs
+ */
+static inline int nla_put_msecs(struct nl_msg *n, int attrtype, unsigned long msecs)
+{
+ return nla_put_u64(n, attrtype, msecs);
+}
+
+/**
+ * Return payload of msecs attribute
+ * @arg nla msecs netlink attribute
+ *
+ * @return the number of milliseconds.
+ */
+static inline unsigned long nla_get_msecs(struct nlattr *nla)
+{
+ return nla_get_u64(nla);
+}
+
+/**
+ * Add nested attributes to netlink message.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type.
+ * @arg nested Message containing attributes to be nested.
+ *
+ * Takes the attributes found in the \a nested message and appends them
+ * to the message \a msg nested in a container of the type \a attrtype.
+ * The \a nested message may not have a family specific header.
+ *
+ * @see nla_put
+ * @return 0 on success or a negative error code.
+ */
+static inline int nla_put_nested(struct nl_msg *msg, int attrtype, struct nl_msg *nested)
+{
+ return nla_put(msg, attrtype, nlmsg_len(nested->nm_nlh),
+ nlmsg_data(nested->nm_nlh));
+}
+
+/**
+ * Start a new level of nested attributes.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type of container.
+ *
+ * @return Pointer to container attribute.
+ */
+static inline struct nlattr *nla_nest_start(struct nl_msg *msg, int attrtype)
+{
+ struct nlattr *start = (struct nlattr *) nlmsg_tail(msg->nm_nlh);
+
+ if (nla_put(msg, attrtype, 0, NULL) < 0)
+ return NULL;
+
+ return start;
+}
+
+/**
+ * Finalize nesting of attributes.
+ * @arg msg Netlink message.
+ * @arg start Container attribute as returned from nla_nest_start().
+ *
+ * Corrects the container attribute header to include the appeneded attributes.
+ *
+ * @return 0
+ */
+static inline int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
+{
+ start->nla_len = (unsigned char *) nlmsg_tail(msg->nm_nlh) -
+ (unsigned char *) start;
+ return 0;
+}
+
+/**
+ * Create attribute index based on nested attribute
+ * @arg tb Index array to be filled (maxtype+1 elements).
+ * @arg maxtype Maximum attribute type expected and accepted.
+ * @arg nla Nested Attribute.
+ * @arg policy Attribute validation policy.
+ *
+ * Feeds the stream of attributes nested into the specified attribute
+ * to nla_parse().
+ *
+ * @see nla_parse
+ * @return 0 on success or a negative error code.
+ */
+static inline int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla,
+ struct nla_policy *policy)
+{
+ return nla_parse(tb, maxtype, (struct nlattr *)nla_data(nla), nla_len(nla), policy);
+}
+
+/**
+ * Compare attribute payload with memory area.
+ * @arg nla Attribute.
+ * @arg data Memory area to compare to.
+ * @arg size Number of bytes to compare.
+ *
+ * @see memcmp(3)
+ * @return An integer less than, equal to, or greater than zero.
+ */
+static inline int nla_memcmp(const struct nlattr *nla, const void *data, size_t size)
+{
+ int d = nla_len(nla) - size;
+
+ if (d == 0)
+ d = memcmp(nla_data(nla), data, size);
+
+ return d;
+}
+
+/**
+ * Compare string attribute payload with string
+ * @arg nla Attribute of type NLA_STRING.
+ * @arg str NUL terminated string.
+ *
+ * @see strcmp(3)
+ * @return An integer less than, equal to, or greater than zero.
+ */
+static inline int nla_strcmp(const struct nlattr *nla, const char *str)
+{
+ int len = strlen(str) + 1;
+ int d = nla_len(nla) - len;
+
+ if (d == 0)
+ d = memcmp(nla_data(nla), str, len);
+
+ return d;
+}
+
+/**
+ * Copy string attribute payload to a buffer.
+ * @arg dst Pointer to destination buffer.
+ * @arg nla Attribute of type NLA_STRING.
+ * @arg dstsize Size of destination buffer in bytes.
+ *
+ * Copies at most dstsize - 1 bytes to the destination buffer.
+ * The result is always a valid NUL terminated string. Unlike
+ * strlcpy the destination buffer is always padded out.
+ *
+ * @return The length of string attribute without the terminating NUL.
+ */
+static inline size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
+{
+ size_t srclen = (size_t)nla_len(nla);
+ char *src = (char*)nla_data(nla);
+
+ if (srclen > 0 && src[srclen - 1] == '\0')
+ srclen--;
+
+ if (dstsize > 0) {
+ size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
+
+ memset(dst, 0, dstsize);
+ memcpy(dst, src, len);
+ }
+
+ return srclen;
+}
+
+
+/**
+ * @name Attribute Construction (Exception Based)
+ * @{
+ */
+
+/**
+ * @ingroup attr
+ * Add unspecific attribute to netlink message.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type.
+ * @arg attrlen Length of attribute payload.
+ * @arg data Head of attribute payload.
+ */
+#define NLA_PUT(msg, attrtype, attrlen, data) \
+ do { \
+ if (nla_put(msg, attrtype, attrlen, data) < 0) \
+ goto nla_put_failure; \
+ } while(0)
+
+/**
+ * @ingroup attr
+ * Add atomic type attribute to netlink message.
+ * @arg msg Netlink message.
+ * @arg type Atomic type.
+ * @arg attrtype Attribute type.
+ * @arg value Head of attribute payload.
+ */
+#define NLA_PUT_TYPE(msg, type, attrtype, value) \
+ do { \
+ type __tmp = value; \
+ NLA_PUT(msg, attrtype, sizeof(type), &__tmp); \
+ } while(0)
+
+/**
+ * Add 8 bit integer attribute to netlink message.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type.
+ * @arg value Numeric value.
+ */
+#define NLA_PUT_U8(msg, attrtype, value) \
+ NLA_PUT_TYPE(msg, uint8_t, attrtype, value)
+
+/**
+ * Add 16 bit integer attribute to netlink message.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type.
+ * @arg value Numeric value.
+ */
+#define NLA_PUT_U16(msg, attrtype, value) \
+ NLA_PUT_TYPE(msg, uint16_t, attrtype, value)
+
+/**
+ * Add 32 bit integer attribute to netlink message.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type.
+ * @arg value Numeric value.
+ */
+#define NLA_PUT_U32(msg, attrtype, value) \
+ NLA_PUT_TYPE(msg, uint32_t, attrtype, value)
+
+/**
+ * Add 64 bit integer attribute to netlink message.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type.
+ * @arg value Numeric value.
+ */
+#define NLA_PUT_U64(msg, attrtype, value) \
+ NLA_PUT_TYPE(msg, uint64_t, attrtype, value)
+
+/**
+ * Add string attribute to netlink message.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type.
+ * @arg value NUL terminated character string.
+ */
+#define NLA_PUT_STRING(msg, attrtype, value) \
+ NLA_PUT(msg, attrtype, strlen(value) + 1, value)
+
+/**
+ * Add flag attribute to netlink message.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type.
+ */
+#define NLA_PUT_FLAG(msg, attrtype) \
+ NLA_PUT(msg, attrtype, 0, NULL)
+
+/**
+ * Add msecs attribute to netlink message.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type.
+ * @arg msecs Numeric value in micro seconds.
+ */
+#define NLA_PUT_MSECS(msg, attrtype, msecs) \
+ NLA_PUT_U64(msg, attrtype, msecs)
+
+/**
+ * Add address attribute to netlink message.
+ * @arg msg Netlink message.
+ * @arg attrtype Attribute type.
+ * @arg addr Abstract address object.
+ */
+#define NLA_PUT_ADDR(msg, attrtype, addr) \
+ NLA_PUT(msg, attrtype, nl_addr_get_len(addr), \
+ nl_addr_get_binary_addr(addr))
+
+/** @} */
+
+/**
+ * @name Iterators
+ * @{
+ */
+
+/**
+ * @ingroup attr
+ * Iterate over a stream of attributes
+ * @arg pos loop counter, set to current attribute
+ * @arg head head of attribute stream
+ * @arg len length of attribute stream
+ * @arg rem initialized to len, holds bytes currently remaining in stream
+ */
+#define nla_for_each_attr(pos, head, len, rem) \
+ for (pos = head, rem = len; \
+ nla_ok(pos, rem); \
+ pos = nla_next(pos, &(rem)))
+
+/**
+ * @ingroup attr
+ * Iterate over a stream of nested attributes
+ * @arg pos loop counter, set to current attribute
+ * @arg nla attribute containing the nested attributes
+ * @arg rem initialized to len, holds bytes currently remaining in stream
+ */
+#define nla_for_each_nested(pos, nla, rem) \
+ for (pos = (struct nlattr *)nla_data(nla), rem = nla_len(nla); \
+ nla_ok(pos, rem); \
+ pos = nla_next(pos, &(rem)))
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/cache-api.h b/package/libnl-tiny/src/include/netlink/cache-api.h
new file mode 100644
index 000000000..22fc449d1
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/cache-api.h
@@ -0,0 +1,199 @@
+/*
+ * netlink/cache-api.h Caching API
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_CACHE_API_H_
+#define NETLINK_CACHE_API_H_
+
+#include <netlink/netlink.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @ingroup cache
+ * @defgroup cache_api Cache Implementation
+ * @brief
+ *
+ * @par 1) Cache Definition
+ * @code
+ * struct nl_cache_ops my_cache_ops = {
+ * .co_name = "route/link",
+ * .co_protocol = NETLINK_ROUTE,
+ * .co_hdrsize = sizeof(struct ifinfomsg),
+ * .co_obj_ops = &my_obj_ops,
+ * };
+ * @endcode
+ *
+ * @par 2)
+ * @code
+ * // The simplest way to fill a cache is by providing a request-update
+ * // function which must trigger a complete dump on the kernel-side of
+ * // whatever the cache covers.
+ * static int my_request_update(struct nl_cache *cache,
+ * struct nl_sock *socket)
+ * {
+ * // In this example, we request a full dump of the interface table
+ * return nl_rtgen_request(socket, RTM_GETLINK, AF_UNSPEC, NLM_F_DUMP);
+ * }
+ *
+ * // The resulting netlink messages sent back will be fed into a message
+ * // parser one at a time. The message parser has to extract all relevant
+ * // information from the message and create an object reflecting the
+ * // contents of the message and pass it on to the parser callback function
+ * // provide which will add the object to the cache.
+ * static int my_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
+ * struct nlmsghdr *nlh, struct nl_parser_param *pp)
+ * {
+ * struct my_obj *obj;
+ *
+ * obj = my_obj_alloc();
+ * obj->ce_msgtype = nlh->nlmsg_type;
+ *
+ * // Parse the netlink message and continue creating the object.
+ *
+ * err = pp->pp_cb((struct nl_object *) obj, pp);
+ * if (err < 0)
+ * goto errout;
+ * }
+ *
+ * struct nl_cache_ops my_cache_ops = {
+ * ...
+ * .co_request_update = my_request_update,
+ * .co_msg_parser = my_msg_parser,
+ * };
+ * @endcode
+ *
+ * @par 3) Notification based Updates
+ * @code
+ * // Caches can be kept up-to-date based on notifications if the kernel
+ * // sends out notifications whenever an object is added/removed/changed.
+ * //
+ * // It is trivial to support this, first a list of groups needs to be
+ * // defined which are required to join in order to receive all necessary
+ * // notifications. The groups are separated by address family to support
+ * // the common situation where a separate group is used for each address
+ * // family. If there is only one group, simply specify AF_UNSPEC.
+ * static struct nl_af_group addr_groups[] = {
+ * { AF_INET, RTNLGRP_IPV4_IFADDR },
+ * { AF_INET6, RTNLGRP_IPV6_IFADDR },
+ * { END_OF_GROUP_LIST },
+ * };
+ *
+ * // In order for the caching system to know the meaning of each message
+ * // type it requires a table which maps each supported message type to
+ * // a cache action, e.g. RTM_NEWADDR means address has been added or
+ * // updated, RTM_DELADDR means address has been removed.
+ * static struct nl_cache_ops rtnl_addr_ops = {
+ * ...
+ * .co_msgtypes = {
+ * { RTM_NEWADDR, NL_ACT_NEW, "new" },
+ * { RTM_DELADDR, NL_ACT_DEL, "del" },
+ * { RTM_GETADDR, NL_ACT_GET, "get" },
+ * END_OF_MSGTYPES_LIST,
+ * },
+ * .co_groups = addr_groups,
+ * };
+ *
+ * // It is now possible to keep the cache up-to-date using the cache manager.
+ * @endcode
+ * @{
+ */
+
+enum {
+ NL_ACT_UNSPEC,
+ NL_ACT_NEW,
+ NL_ACT_DEL,
+ NL_ACT_GET,
+ NL_ACT_SET,
+ NL_ACT_CHANGE,
+ __NL_ACT_MAX,
+};
+
+#define NL_ACT_MAX (__NL_ACT_MAX - 1)
+
+#define END_OF_MSGTYPES_LIST { -1, -1, NULL }
+
+/**
+ * Message type to cache action association
+ */
+struct nl_msgtype
+{
+ /** Netlink message type */
+ int mt_id;
+
+ /** Cache action to take */
+ int mt_act;
+
+ /** Name of operation for human-readable printing */
+ char * mt_name;
+};
+
+/**
+ * Address family to netlink group association
+ */
+struct nl_af_group
+{
+ /** Address family */
+ int ag_family;
+
+ /** Netlink group identifier */
+ int ag_group;
+};
+
+#define END_OF_GROUP_LIST AF_UNSPEC, 0
+
+struct nl_parser_param
+{
+ int (*pp_cb)(struct nl_object *, struct nl_parser_param *);
+ void * pp_arg;
+};
+
+/**
+ * Cache Operations
+ */
+struct nl_cache_ops
+{
+ char * co_name;
+
+ int co_hdrsize;
+ int co_protocol;
+ struct nl_af_group * co_groups;
+
+ /**
+ * Called whenever an update of the cache is required. Must send
+ * a request message to the kernel requesting a complete dump.
+ */
+ int (*co_request_update)(struct nl_cache *, struct nl_sock *);
+
+ /**
+ * Called whenever a message was received that needs to be parsed.
+ * Must parse the message and call the paser callback function
+ * (nl_parser_param) provided via the argument.
+ */
+ int (*co_msg_parser)(struct nl_cache_ops *, struct sockaddr_nl *,
+ struct nlmsghdr *, struct nl_parser_param *);
+
+ struct nl_object_ops * co_obj_ops;
+
+ struct nl_cache_ops *co_next;
+ struct nl_cache *co_major_cache;
+ struct genl_ops * co_genl;
+ struct nl_msgtype co_msgtypes[];
+};
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/cache.h b/package/libnl-tiny/src/include/netlink/cache.h
new file mode 100644
index 000000000..09719f3a7
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/cache.h
@@ -0,0 +1,128 @@
+/*
+ * netlink/cache.h Caching Module
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_CACHE_H_
+#define NETLINK_CACHE_H_
+
+#include <netlink/netlink.h>
+#include <netlink/msg.h>
+#include <netlink/utils.h>
+#include <netlink/object.h>
+#include <netlink/cache-api.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct nl_cache;
+
+typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int);
+
+/* Access Functions */
+extern int nl_cache_nitems(struct nl_cache *);
+extern int nl_cache_nitems_filter(struct nl_cache *,
+ struct nl_object *);
+extern struct nl_cache_ops * nl_cache_get_ops(struct nl_cache *);
+extern struct nl_object * nl_cache_get_first(struct nl_cache *);
+extern struct nl_object * nl_cache_get_last(struct nl_cache *);
+extern struct nl_object * nl_cache_get_next(struct nl_object *);
+extern struct nl_object * nl_cache_get_prev(struct nl_object *);
+
+extern struct nl_cache * nl_cache_alloc(struct nl_cache_ops *);
+extern int nl_cache_alloc_and_fill(struct nl_cache_ops *,
+ struct nl_sock *,
+ struct nl_cache **);
+extern int nl_cache_alloc_name(const char *,
+ struct nl_cache **);
+extern struct nl_cache * nl_cache_subset(struct nl_cache *,
+ struct nl_object *);
+extern void nl_cache_clear(struct nl_cache *);
+extern void nl_cache_free(struct nl_cache *);
+
+/* Cache modification */
+extern int nl_cache_add(struct nl_cache *,
+ struct nl_object *);
+extern int nl_cache_parse_and_add(struct nl_cache *,
+ struct nl_msg *);
+extern void nl_cache_remove(struct nl_object *);
+extern int nl_cache_refill(struct nl_sock *,
+ struct nl_cache *);
+extern int nl_cache_pickup(struct nl_sock *,
+ struct nl_cache *);
+extern int nl_cache_resync(struct nl_sock *,
+ struct nl_cache *,
+ change_func_t);
+extern int nl_cache_include(struct nl_cache *,
+ struct nl_object *,
+ change_func_t);
+
+/* General */
+extern int nl_cache_is_empty(struct nl_cache *);
+extern void nl_cache_mark_all(struct nl_cache *);
+
+/* Dumping */
+extern void nl_cache_dump(struct nl_cache *,
+ struct nl_dump_params *);
+extern void nl_cache_dump_filter(struct nl_cache *,
+ struct nl_dump_params *,
+ struct nl_object *);
+
+/* Iterators */
+#ifdef disabled
+extern void nl_cache_foreach(struct nl_cache *,
+ void (*cb)(struct nl_object *,
+ void *),
+ void *arg);
+extern void nl_cache_foreach_filter(struct nl_cache *,
+ struct nl_object *,
+ void (*cb)(struct
+ nl_object *,
+ void *),
+ void *arg);
+#endif
+
+/* --- cache management --- */
+
+/* Cache type management */
+extern struct nl_cache_ops * nl_cache_ops_lookup(const char *);
+extern struct nl_cache_ops * nl_cache_ops_associate(int, int);
+extern struct nl_msgtype * nl_msgtype_lookup(struct nl_cache_ops *, int);
+extern void nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *);
+extern int nl_cache_mngt_register(struct nl_cache_ops *);
+extern int nl_cache_mngt_unregister(struct nl_cache_ops *);
+
+/* Global cache provisioning/requiring */
+extern void nl_cache_mngt_provide(struct nl_cache *);
+extern void nl_cache_mngt_unprovide(struct nl_cache *);
+extern struct nl_cache * nl_cache_mngt_require(const char *);
+
+struct nl_cache_mngr;
+
+#define NL_AUTO_PROVIDE 1
+
+extern int nl_cache_mngr_alloc(struct nl_sock *,
+ int, int,
+ struct nl_cache_mngr **);
+extern int nl_cache_mngr_add(struct nl_cache_mngr *,
+ const char *,
+ change_func_t,
+ struct nl_cache **);
+extern int nl_cache_mngr_get_fd(struct nl_cache_mngr *);
+extern int nl_cache_mngr_poll(struct nl_cache_mngr *,
+ int);
+extern int nl_cache_mngr_data_ready(struct nl_cache_mngr *);
+extern void nl_cache_mngr_free(struct nl_cache_mngr *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/data.h b/package/libnl-tiny/src/include/netlink/data.h
new file mode 100644
index 000000000..071159ee5
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/data.h
@@ -0,0 +1,41 @@
+/*
+ * netlink/data.h Abstract Data
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_DATA_H_
+#define NETLINK_DATA_H_
+
+#include <netlink/netlink.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct nl_data;
+
+/* General */
+extern struct nl_data * nl_data_alloc(void *, size_t);
+extern struct nl_data * nl_data_alloc_attr(struct nlattr *);
+extern struct nl_data * nl_data_clone(struct nl_data *);
+extern int nl_data_append(struct nl_data *, void *, size_t);
+extern void nl_data_free(struct nl_data *);
+
+/* Access Functions */
+extern void * nl_data_get(struct nl_data *);
+extern size_t nl_data_get_size(struct nl_data *);
+
+/* Misc */
+extern int nl_data_cmp(struct nl_data *, struct nl_data *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/errno.h b/package/libnl-tiny/src/include/netlink/errno.h
new file mode 100644
index 000000000..0b43da02a
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/errno.h
@@ -0,0 +1,59 @@
+/*
+ * netlink/errno.h Error Numbers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_ERRNO_H_
+#define NETLINK_ERRNO_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NLE_SUCCESS 0
+#define NLE_FAILURE 1
+#define NLE_INTR 2
+#define NLE_BAD_SOCK 3
+#define NLE_AGAIN 4
+#define NLE_NOMEM 5
+#define NLE_EXIST 6
+#define NLE_INVAL 7
+#define NLE_RANGE 8
+#define NLE_MSGSIZE 9
+#define NLE_OPNOTSUPP 10
+#define NLE_AF_NOSUPPORT 11
+#define NLE_OBJ_NOTFOUND 12
+#define NLE_NOATTR 13
+#define NLE_MISSING_ATTR 14
+#define NLE_AF_MISMATCH 15
+#define NLE_SEQ_MISMATCH 16
+#define NLE_MSG_OVERFLOW 17
+#define NLE_MSG_TRUNC 18
+#define NLE_NOADDR 19
+#define NLE_SRCRT_NOSUPPORT 20
+#define NLE_MSG_TOOSHORT 21
+#define NLE_MSGTYPE_NOSUPPORT 22
+#define NLE_OBJ_MISMATCH 23
+#define NLE_NOCACHE 24
+#define NLE_BUSY 25
+#define NLE_PROTO_MISMATCH 26
+#define NLE_NOACCESS 27
+#define NLE_PERM 28
+
+#define NLE_MAX NLE_PERM
+
+extern const char * nl_geterror(int);
+extern void nl_perror(int, const char *);
+extern int nl_syserr2nlerr(int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/genl/ctrl.h b/package/libnl-tiny/src/include/netlink/genl/ctrl.h
new file mode 100644
index 000000000..1ae62f448
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/genl/ctrl.h
@@ -0,0 +1,37 @@
+/*
+ * netlink/genl/ctrl.h Generic Netlink Controller
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_GENL_CTRL_H_
+#define NETLINK_GENL_CTRL_H_
+
+#include <netlink/netlink.h>
+#include <netlink/cache.h>
+#include <netlink/addr.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct genl_family;
+
+extern int genl_ctrl_alloc_cache(struct nl_sock *,
+ struct nl_cache **);
+extern struct genl_family * genl_ctrl_search(struct nl_cache *, int);
+extern struct genl_family * genl_ctrl_search_by_name(struct nl_cache *,
+ const char *);
+extern int genl_ctrl_resolve(struct nl_sock *,
+ const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/genl/family.h b/package/libnl-tiny/src/include/netlink/genl/family.h
new file mode 100644
index 000000000..0257cbe27
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/genl/family.h
@@ -0,0 +1,130 @@
+/*
+ * netlink/genl/family.h Generic Netlink Family
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_GENL_FAMILY_H_
+#define NETLINK_GENL_FAMILY_H_
+
+#include <netlink/netlink.h>
+#include <netlink/cache.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @cond SKIP */
+#define FAMILY_ATTR_ID 0x01
+#define FAMILY_ATTR_NAME 0x02
+#define FAMILY_ATTR_VERSION 0x04
+#define FAMILY_ATTR_HDRSIZE 0x08
+#define FAMILY_ATTR_MAXATTR 0x10
+#define FAMILY_ATTR_OPS 0x20
+
+
+struct genl_family
+{
+ NLHDR_COMMON
+
+ uint16_t gf_id;
+ char gf_name[GENL_NAMSIZ];
+ uint32_t gf_version;
+ uint32_t gf_hdrsize;
+ uint32_t gf_maxattr;
+
+ struct nl_list_head gf_ops;
+};
+
+
+extern struct genl_family * genl_family_alloc(void);
+extern void genl_family_put(struct genl_family *);
+
+extern int genl_family_add_op(struct genl_family *,
+ int, int);
+
+/**
+ * @name Attributes
+ * @{
+ */
+
+static inline unsigned int genl_family_get_id(struct genl_family *family)
+{
+ if (family->ce_mask & FAMILY_ATTR_ID)
+ return family->gf_id;
+ else
+ return GENL_ID_GENERATE;
+}
+
+static inline void genl_family_set_id(struct genl_family *family, unsigned int id)
+{
+ family->gf_id = id;
+ family->ce_mask |= FAMILY_ATTR_ID;
+}
+
+static inline char *genl_family_get_name(struct genl_family *family)
+{
+ if (family->ce_mask & FAMILY_ATTR_NAME)
+ return family->gf_name;
+ else
+ return NULL;
+}
+
+static inline void genl_family_set_name(struct genl_family *family, const char *name)
+{
+ strncpy(family->gf_name, name, GENL_NAMSIZ-1);
+ family->ce_mask |= FAMILY_ATTR_NAME;
+}
+
+static inline uint8_t genl_family_get_version(struct genl_family *family)
+{
+ if (family->ce_mask & FAMILY_ATTR_VERSION)
+ return family->gf_version;
+ else
+ return 0;
+}
+
+static inline void genl_family_set_version(struct genl_family *family, uint8_t version)
+{
+ family->gf_version = version;
+ family->ce_mask |= FAMILY_ATTR_VERSION;
+}
+
+static inline uint32_t genl_family_get_hdrsize(struct genl_family *family)
+{
+ if (family->ce_mask & FAMILY_ATTR_HDRSIZE)
+ return family->gf_hdrsize;
+ else
+ return 0;
+}
+
+static inline void genl_family_set_hdrsize(struct genl_family *family, uint32_t hdrsize)
+{
+ family->gf_hdrsize = hdrsize;
+ family->ce_mask |= FAMILY_ATTR_HDRSIZE;
+}
+
+static inline uint32_t genl_family_get_maxattr(struct genl_family *family)
+{
+ if (family->ce_mask & FAMILY_ATTR_MAXATTR)
+ return family->gf_maxattr;
+ else
+ return family->gf_maxattr;
+}
+
+static inline void genl_family_set_maxattr(struct genl_family *family, uint32_t maxattr)
+{
+ family->gf_maxattr = maxattr;
+ family->ce_mask |= FAMILY_ATTR_MAXATTR;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/genl/genl.h b/package/libnl-tiny/src/include/netlink/genl/genl.h
new file mode 100644
index 000000000..3f3340cfd
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/genl/genl.h
@@ -0,0 +1,47 @@
+/*
+ * netlink/genl/genl.h Generic Netlink
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_GENL_H_
+#define NETLINK_GENL_H_
+
+#include <netlink/netlink.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int genl_connect(struct nl_sock *);
+
+extern int genl_send_simple(struct nl_sock *, int, int,
+ int, int);
+
+extern void * genlmsg_put(struct nl_msg *, uint32_t, uint32_t,
+ int, int, int, uint8_t, uint8_t);
+
+extern int genlmsg_valid_hdr(struct nlmsghdr *, int);
+extern int genlmsg_validate(struct nlmsghdr *, int, int,
+ struct nla_policy *);
+extern int genlmsg_parse(struct nlmsghdr *, int, struct nlattr **,
+ int, struct nla_policy *);
+extern void * genlmsg_data(const struct genlmsghdr *);
+extern int genlmsg_len(const struct genlmsghdr *);
+extern struct nlattr * genlmsg_attrdata(const struct genlmsghdr *, int);
+extern int genlmsg_attrlen(const struct genlmsghdr *, int);
+
+extern char * genl_op2name(int, int, char *, size_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/genl/mngt.h b/package/libnl-tiny/src/include/netlink/genl/mngt.h
new file mode 100644
index 000000000..8b0244f2c
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/genl/mngt.h
@@ -0,0 +1,87 @@
+/*
+ * netlink/genl/mngt.h Generic Netlink Management
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_GENL_MNGT_H_
+#define NETLINK_GENL_MNGT_H_
+
+#include <netlink/netlink.h>
+#include <netlink/attr.h>
+#include <netlink/list.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct nl_cache_ops;
+
+struct genl_info
+{
+ struct sockaddr_nl * who;
+ struct nlmsghdr * nlh;
+ struct genlmsghdr * genlhdr;
+ void * userhdr;
+ struct nlattr ** attrs;
+};
+
+/**
+ * @ingroup genl_mngt
+ * Generic Netlink Command
+ */
+struct genl_cmd
+{
+ /** Unique command identifier */
+ int c_id;
+
+ /** Name/description of command */
+ char * c_name;
+
+ /**
+ * Maximum attribute identifier, must be provided if
+ * a message parser is available.
+ */
+ int c_maxattr;
+
+ int (*c_msg_parser)(struct nl_cache_ops *,
+ struct genl_cmd *,
+ struct genl_info *, void *);
+
+ /**
+ * Attribute validation policy (optional)
+ */
+ struct nla_policy * c_attr_policy;
+};
+
+/**
+ * @ingroup genl_mngt
+ * Generic Netlink Operations
+ */
+struct genl_ops
+{
+ int o_family;
+ int o_id;
+ char * o_name;
+ struct nl_cache_ops * o_cache_ops;
+ struct genl_cmd * o_cmds;
+ int o_ncmds;
+
+ /* linked list of all genl cache operations */
+ struct nl_list_head o_list;
+};
+
+
+extern int genl_register(struct nl_cache_ops *);
+extern void genl_unregister(struct nl_cache_ops *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/handlers.h b/package/libnl-tiny/src/include/netlink/handlers.h
new file mode 100644
index 000000000..7fb53b4ee
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/handlers.h
@@ -0,0 +1,230 @@
+/*
+ * netlink/handlers.c default netlink message handlers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_HANDLERS_H_
+#define NETLINK_HANDLERS_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <netlink/netlink-compat.h>
+#include <netlink/netlink-kernel.h>
+#include <netlink/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct nl_sock;
+struct nl_msg;
+struct nl_cb;
+/**
+ * @name Callback Typedefs
+ * @{
+ */
+
+/**
+ * nl_recvmsgs() callback for message processing customization
+ * @ingroup cb
+ * @arg msg netlink message being processed
+ * @arg arg argument passwd on through caller
+ */
+typedef int (*nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg);
+
+/**
+ * nl_recvmsgs() callback for error message processing customization
+ * @ingroup cb
+ * @arg nla netlink address of the peer
+ * @arg nlerr netlink error message being processed
+ * @arg arg argument passed on through caller
+ */
+typedef int (*nl_recvmsg_err_cb_t)(struct sockaddr_nl *nla,
+ struct nlmsgerr *nlerr, void *arg);
+
+/** @} */
+
+/**
+ * Callback actions
+ * @ingroup cb
+ */
+enum nl_cb_action {
+ /** Proceed with wathever would come next */
+ NL_OK,
+ /** Skip this message */
+ NL_SKIP,
+ /** Stop parsing altogether and discard remaining messages */
+ NL_STOP,
+};
+
+/**
+ * Callback kinds
+ * @ingroup cb
+ */
+enum nl_cb_kind {
+ /** Default handlers (quiet) */
+ NL_CB_DEFAULT,
+ /** Verbose default handlers (error messages printed) */
+ NL_CB_VERBOSE,
+ /** Debug handlers for debugging */
+ NL_CB_DEBUG,
+ /** Customized handler specified by the user */
+ NL_CB_CUSTOM,
+ __NL_CB_KIND_MAX,
+};
+
+#define NL_CB_KIND_MAX (__NL_CB_KIND_MAX - 1)
+
+/**
+ * Callback types
+ * @ingroup cb
+ */
+enum nl_cb_type {
+ /** Message is valid */
+ NL_CB_VALID,
+ /** Last message in a series of multi part messages received */
+ NL_CB_FINISH,
+ /** Report received that data was lost */
+ NL_CB_OVERRUN,
+ /** Message wants to be skipped */
+ NL_CB_SKIPPED,
+ /** Message is an acknowledge */
+ NL_CB_ACK,
+ /** Called for every message received */
+ NL_CB_MSG_IN,
+ /** Called for every message sent out except for nl_sendto() */
+ NL_CB_MSG_OUT,
+ /** Message is malformed and invalid */
+ NL_CB_INVALID,
+ /** Called instead of internal sequence number checking */
+ NL_CB_SEQ_CHECK,
+ /** Sending of an acknowledge message has been requested */
+ NL_CB_SEND_ACK,
+ __NL_CB_TYPE_MAX,
+};
+
+#define NL_CB_TYPE_MAX (__NL_CB_TYPE_MAX - 1)
+
+struct nl_cb
+{
+ nl_recvmsg_msg_cb_t cb_set[NL_CB_TYPE_MAX+1];
+ void * cb_args[NL_CB_TYPE_MAX+1];
+
+ nl_recvmsg_err_cb_t cb_err;
+ void * cb_err_arg;
+
+ /** May be used to replace nl_recvmsgs with your own implementation
+ * in all internal calls to nl_recvmsgs. */
+ int (*cb_recvmsgs_ow)(struct nl_sock *,
+ struct nl_cb *);
+
+ /** Overwrite internal calls to nl_recv, must return the number of
+ * octets read and allocate a buffer for the received data. */
+ int (*cb_recv_ow)(struct nl_sock *,
+ struct sockaddr_nl *,
+ unsigned char **,
+ struct ucred **);
+
+ /** Overwrites internal calls to nl_send, must send the netlink
+ * message. */
+ int (*cb_send_ow)(struct nl_sock *,
+ struct nl_msg *);
+
+ int cb_refcnt;
+};
+
+
+extern struct nl_cb * nl_cb_alloc(enum nl_cb_kind);
+extern struct nl_cb * nl_cb_clone(struct nl_cb *);
+extern void nl_cb_put(struct nl_cb *);
+
+extern int nl_cb_set(struct nl_cb *, enum nl_cb_type, enum nl_cb_kind,
+ nl_recvmsg_msg_cb_t, void *);
+extern int nl_cb_err(struct nl_cb *, enum nl_cb_kind, nl_recvmsg_err_cb_t,
+ void *);
+
+static inline struct nl_cb *nl_cb_get(struct nl_cb *cb)
+{
+ cb->cb_refcnt++;
+
+ return cb;
+}
+
+/**
+ * Set up a all callbacks
+ * @arg cb callback set
+ * @arg kind kind of callback
+ * @arg func callback function
+ * @arg arg argument to be passwd to callback function
+ *
+ * @return 0 on success or a negative error code
+ */
+static inline int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind,
+ nl_recvmsg_msg_cb_t func, void *arg)
+{
+ int i, err;
+
+ for (i = 0; i <= NL_CB_TYPE_MAX; i++) {
+ err = nl_cb_set(cb,(enum nl_cb_type)i, kind, func, arg);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+
+/**
+ * @name Overwriting
+ * @{
+ */
+
+/**
+ * Overwrite internal calls to nl_recvmsgs()
+ * @arg cb callback set
+ * @arg func replacement callback for nl_recvmsgs()
+ */
+static inline void nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
+ int (*func)(struct nl_sock *, struct nl_cb *))
+{
+ cb->cb_recvmsgs_ow = func;
+}
+
+/**
+ * Overwrite internal calls to nl_recv()
+ * @arg cb callback set
+ * @arg func replacement callback for nl_recv()
+ */
+static inline void nl_cb_overwrite_recv(struct nl_cb *cb,
+ int (*func)(struct nl_sock *, struct sockaddr_nl *,
+ unsigned char **, struct ucred **))
+{
+ cb->cb_recv_ow = func;
+}
+
+/**
+ * Overwrite internal calls to nl_send()
+ * @arg cb callback set
+ * @arg func replacement callback for nl_send()
+ */
+static inline void nl_cb_overwrite_send(struct nl_cb *cb,
+ int (*func)(struct nl_sock *, struct nl_msg *))
+{
+ cb->cb_send_ow = func;
+}
+
+/** @} */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/list.h b/package/libnl-tiny/src/include/netlink/list.h
new file mode 100644
index 000000000..c6876a77f
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/list.h
@@ -0,0 +1,88 @@
+/*
+ * netlink/list.h Netlink List Utilities
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_LIST_H_
+#define NETLINK_LIST_H_
+
+struct nl_list_head
+{
+ struct nl_list_head * next;
+ struct nl_list_head * prev;
+};
+
+
+static inline void __nl_list_add(struct nl_list_head *obj,
+ struct nl_list_head *prev,
+ struct nl_list_head *next)
+{
+ prev->next = obj;
+ obj->prev = prev;
+ next->prev = obj;
+ obj->next = next;
+}
+
+static inline void nl_list_add_tail(struct nl_list_head *obj,
+ struct nl_list_head *head)
+{
+ __nl_list_add(obj, head->prev, head);
+}
+
+static inline void nl_list_add_head(struct nl_list_head *obj,
+ struct nl_list_head *head)
+{
+ __nl_list_add(obj, head, head->next);
+}
+
+static inline void nl_list_del(struct nl_list_head *obj)
+{
+ obj->next->prev = obj->prev;
+ obj->prev->next = obj->next;
+}
+
+static inline int nl_list_empty(struct nl_list_head *head)
+{
+ return head->next == head;
+}
+
+#define nl_container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - ((size_t) &((type *)0)->member));})
+
+#define nl_list_entry(ptr, type, member) \
+ nl_container_of(ptr, type, member)
+
+#define nl_list_at_tail(pos, head, member) \
+ ((pos)->member.next == (head))
+
+#define nl_list_at_head(pos, head, member) \
+ ((pos)->member.prev == (head))
+
+#define NL_LIST_HEAD(name) \
+ struct nl_list_head name = { &(name), &(name) }
+
+#define nl_list_first_entry(head, type, member) \
+ nl_list_entry((head)->next, type, member)
+
+#define nl_list_for_each_entry(pos, head, member) \
+ for (pos = nl_list_entry((head)->next, typeof(*pos), member); \
+ &(pos)->member != (head); \
+ (pos) = nl_list_entry((pos)->member.next, typeof(*(pos)), member))
+
+#define nl_list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = nl_list_entry((head)->next, typeof(*pos), member), \
+ n = nl_list_entry(pos->member.next, typeof(*pos), member); \
+ &(pos)->member != (head); \
+ pos = n, n = nl_list_entry(n->member.next, typeof(*n), member))
+
+#define nl_init_list_head(head) \
+ do { (head)->next = (head); (head)->prev = (head); } while (0)
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/msg.h b/package/libnl-tiny/src/include/netlink/msg.h
new file mode 100644
index 000000000..b3e2b0b2b
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/msg.h
@@ -0,0 +1,308 @@
+/*
+ * netlink/msg.c Netlink Messages Interface
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_MSG_H_
+#define NETLINK_MSG_H_
+
+#include <netlink/netlink.h>
+#include <netlink/object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct nla_policy;
+
+#define NL_DONTPAD 0
+
+/**
+ * @ingroup msg
+ * @brief
+ * Will cause the netlink pid to be set to the pid assigned to
+ * the netlink handle (socket) just before sending the message off.
+ * @note Requires the use of nl_send_auto_complete()!
+ */
+#define NL_AUTO_PID 0
+
+/**
+ * @ingroup msg
+ * @brief
+ * May be used to refer to a sequence number which should be
+ * automatically set just before sending the message off.
+ * @note Requires the use of nl_send_auto_complete()!
+ */
+#define NL_AUTO_SEQ 0
+
+#define NL_MSG_CRED_PRESENT 1
+
+struct nl_msg
+{
+ int nm_protocol;
+ int nm_flags;
+ struct sockaddr_nl nm_src;
+ struct sockaddr_nl nm_dst;
+ struct ucred nm_creds;
+ struct nlmsghdr * nm_nlh;
+ size_t nm_size;
+ int nm_refcnt;
+};
+
+
+struct nl_msg;
+struct nl_tree;
+struct ucred;
+
+/* message parsing */
+extern int nlmsg_ok(const struct nlmsghdr *, int);
+extern struct nlmsghdr * nlmsg_next(struct nlmsghdr *, int *);
+extern int nlmsg_parse(struct nlmsghdr *, int, struct nlattr **,
+ int, struct nla_policy *);
+extern int nlmsg_validate(struct nlmsghdr *, int, int,
+ struct nla_policy *);
+
+extern struct nl_msg * nlmsg_alloc(void);
+extern struct nl_msg * nlmsg_alloc_size(size_t);
+extern struct nl_msg * nlmsg_alloc_simple(int, int);
+extern void nlmsg_set_default_size(size_t);
+extern struct nl_msg * nlmsg_inherit(struct nlmsghdr *);
+extern struct nl_msg * nlmsg_convert(struct nlmsghdr *);
+extern void * nlmsg_reserve(struct nl_msg *, size_t, int);
+extern int nlmsg_append(struct nl_msg *, void *, size_t, int);
+
+extern struct nlmsghdr * nlmsg_put(struct nl_msg *, uint32_t, uint32_t,
+ int, int, int);
+extern void nlmsg_free(struct nl_msg *);
+
+extern int nl_msg_parse(struct nl_msg *,
+ void (*cb)(struct nl_object *, void *),
+ void *);
+
+extern void nl_msg_dump(struct nl_msg *, FILE *);
+
+/**
+ * length of netlink message not including padding
+ * @arg payload length of message payload
+ */
+static inline int nlmsg_msg_size(int payload)
+{
+ return NLMSG_HDRLEN + payload;
+}
+
+/**
+ * length of netlink message including padding
+ * @arg payload length of message payload
+ */
+static inline int nlmsg_total_size(int payload)
+{
+ return NLMSG_ALIGN(nlmsg_msg_size(payload));
+}
+
+/**
+ * length of padding at the message's tail
+ * @arg payload length of message payload
+ */
+static inline int nlmsg_padlen(int payload)
+{
+ return nlmsg_total_size(payload) - nlmsg_msg_size(payload);
+}
+
+/**
+ * head of message payload
+ * @arg nlh netlink messsage header
+ */
+static inline void *nlmsg_data(const struct nlmsghdr *nlh)
+{
+ return (unsigned char *) nlh + NLMSG_HDRLEN;
+}
+
+static inline void *nlmsg_tail(const struct nlmsghdr *nlh)
+{
+ return (unsigned char *) nlh + NLMSG_ALIGN(nlh->nlmsg_len);
+}
+
+/**
+ * length of message payload
+ * @arg nlh netlink message header
+ */
+static inline int nlmsg_len(const struct nlmsghdr *nlh)
+{
+ return nlh->nlmsg_len - NLMSG_HDRLEN;
+}
+
+/**
+ * head of attributes data
+ * @arg nlh netlink message header
+ * @arg hdrlen length of family specific header
+ */
+static inline struct nlattr *nlmsg_attrdata(const struct nlmsghdr *nlh, int hdrlen)
+{
+ unsigned char *data = (unsigned char*)nlmsg_data(nlh);
+ return (struct nlattr *) (data + NLMSG_ALIGN(hdrlen));
+}
+
+/**
+ * length of attributes data
+ * @arg nlh netlink message header
+ * @arg hdrlen length of family specific header
+ */
+static inline int nlmsg_attrlen(const struct nlmsghdr *nlh, int hdrlen)
+{
+ return nlmsg_len(nlh) - NLMSG_ALIGN(hdrlen);
+}
+
+static inline int nlmsg_valid_hdr(const struct nlmsghdr *nlh, int hdrlen)
+{
+ if (nlh->nlmsg_len < (uint)nlmsg_msg_size(hdrlen))
+ return 0;
+
+ return 1;
+}
+
+
+static inline void nlmsg_set_proto(struct nl_msg *msg, int protocol)
+{
+ msg->nm_protocol = protocol;
+}
+
+static inline int nlmsg_get_proto(struct nl_msg *msg)
+{
+ return msg->nm_protocol;
+}
+
+static inline size_t nlmsg_get_max_size(struct nl_msg *msg)
+{
+ return msg->nm_size;
+}
+
+static inline void nlmsg_set_src(struct nl_msg *msg, struct sockaddr_nl *addr)
+{
+ memcpy(&msg->nm_src, addr, sizeof(*addr));
+}
+
+static inline struct sockaddr_nl *nlmsg_get_src(struct nl_msg *msg)
+{
+ return &msg->nm_src;
+}
+
+static inline void nlmsg_set_dst(struct nl_msg *msg, struct sockaddr_nl *addr)
+{
+ memcpy(&msg->nm_dst, addr, sizeof(*addr));
+}
+
+static inline struct sockaddr_nl *nlmsg_get_dst(struct nl_msg *msg)
+{
+ return &msg->nm_dst;
+}
+
+static inline void nlmsg_set_creds(struct nl_msg *msg, struct ucred *creds)
+{
+ memcpy(&msg->nm_creds, creds, sizeof(*creds));
+ msg->nm_flags |= NL_MSG_CRED_PRESENT;
+}
+
+static inline struct ucred *nlmsg_get_creds(struct nl_msg *msg)
+{
+ if (msg->nm_flags & NL_MSG_CRED_PRESENT)
+ return &msg->nm_creds;
+ return NULL;
+}
+
+/**
+ * Return actual netlink message
+ * @arg n netlink message
+ *
+ * Returns the actual netlink message casted to the type of the netlink
+ * message header.
+ *
+ * @return A pointer to the netlink message.
+ */
+static inline struct nlmsghdr *nlmsg_hdr(struct nl_msg *n)
+{
+ return n->nm_nlh;
+}
+
+/**
+ * Acquire a reference on a netlink message
+ * @arg msg message to acquire reference from
+ */
+static inline void nlmsg_get(struct nl_msg *msg)
+{
+ msg->nm_refcnt++;
+}
+
+/**
+ * Expand maximum payload size of a netlink message
+ * @arg n Netlink message.
+ * @arg newlen New maximum payload size.
+ *
+ * Reallocates the payload section of a netlink message and increases
+ * the maximum payload size of the message.
+ *
+ * @note Any pointers pointing to old payload block will be stale and
+ * need to be refetched. Therfore, do not expand while constructing
+ * nested attributes or while reserved data blocks are held.
+ *
+ * @return 0 on success or a negative error code.
+ */
+static inline int nlmsg_expand(struct nl_msg *n, size_t newlen)
+{
+ void *tmp;
+
+ if (newlen <= n->nm_size)
+ return -NLE_INVAL;
+
+ tmp = realloc(n->nm_nlh, newlen);
+ if (tmp == NULL)
+ return -NLE_NOMEM;
+
+ n->nm_nlh = (struct nlmsghdr*)tmp;
+ n->nm_size = newlen;
+
+ return 0;
+}
+
+
+/**
+ * @name Iterators
+ * @{
+ */
+
+/**
+ * @ingroup msg
+ * Iterate over a stream of attributes in a message
+ * @arg pos loop counter, set to current attribute
+ * @arg nlh netlink message header
+ * @arg hdrlen length of family header
+ * @arg rem initialized to len, holds bytes currently remaining in stream
+ */
+#define nlmsg_for_each_attr(pos, nlh, hdrlen, rem) \
+ nla_for_each_attr(pos, nlmsg_attrdata(nlh, hdrlen), \
+ nlmsg_attrlen(nlh, hdrlen), rem)
+
+/**
+ * Iterate over a stream of messages
+ * @arg pos loop counter, set to current message
+ * @arg head head of message stream
+ * @arg len length of message stream
+ * @arg rem initialized to len, holds bytes currently remaining in stream
+ */
+#define nlmsg_for_each_msg(pos, head, len, rem) \
+ for (pos = head, rem = len; \
+ nlmsg_ok(pos, rem); \
+ pos = nlmsg_next(pos, &(rem)))
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/netlink-compat.h b/package/libnl-tiny/src/include/netlink/netlink-compat.h
new file mode 100644
index 000000000..17ec9fc8d
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/netlink-compat.h
@@ -0,0 +1,50 @@
+/*
+ * netlink/netlink-compat.h Netlink Compatability
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_COMPAT_H_
+#define NETLINK_COMPAT_H_
+
+#if !defined _LINUX_SOCKET_H && !defined _BITS_SOCKADDR_H
+typedef unsigned short sa_family_t;
+#endif
+
+#ifndef IFNAMSIZ
+/** Maximum length of a interface name */
+#define IFNAMSIZ 16
+#endif
+
+/* patch 2.4.x if_arp */
+#ifndef ARPHRD_INFINIBAND
+#define ARPHRD_INFINIBAND 32
+#endif
+
+/* patch 2.4.x eth header file */
+#ifndef ETH_P_MPLS_UC
+#define ETH_P_MPLS_UC 0x8847
+#endif
+
+#ifndef ETH_P_MPLS_MC
+#define ETH_P_MPLS_MC 0x8848
+#endif
+
+#ifndef ETH_P_EDP2
+#define ETH_P_EDP2 0x88A2
+#endif
+
+#ifndef ETH_P_HDLC
+#define ETH_P_HDLC 0x0019
+#endif
+
+#ifndef AF_LLC
+#define AF_LLC 26
+#endif
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/netlink-kernel.h b/package/libnl-tiny/src/include/netlink/netlink-kernel.h
new file mode 100644
index 000000000..a0f553566
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/netlink-kernel.h
@@ -0,0 +1,196 @@
+#ifndef __LINUX_NETLINK_H
+#define __LINUX_NETLINK_H
+
+/**
+ * Netlink socket address
+ * @ingroup nl
+ */
+struct sockaddr_nl
+{
+ /** socket family (AF_NETLINK) */
+ sa_family_t nl_family;
+
+ /** Padding (unused) */
+ unsigned short nl_pad;
+
+ /** Unique process ID */
+ uint32_t nl_pid;
+
+ /** Multicast group subscriptions */
+ uint32_t nl_groups;
+};
+
+/**
+ * Netlink message header
+ * @ingroup msg
+ */
+struct nlmsghdr
+{
+ /**
+ * Length of message including header.
+ */
+ uint32_t nlmsg_len;
+
+ /**
+ * Message type (content type)
+ */
+ uint16_t nlmsg_type;
+
+ /**
+ * Message flags
+ */
+ uint16_t nlmsg_flags;
+
+ /**
+ * Sequence number
+ */
+ uint32_t nlmsg_seq;
+
+ /**
+ * Netlink PID of the proccess sending the message.
+ */
+ uint32_t nlmsg_pid;
+};
+
+/**
+ * @name Standard message flags
+ * @{
+ */
+
+/**
+ * Must be set on all request messages (typically from user space to
+ * kernel space).
+ * @ingroup msg
+ */
+#define NLM_F_REQUEST 1
+
+/**
+ * Indicates the message is part of a multipart message terminated
+ * by NLMSG_DONE.
+ */
+#define NLM_F_MULTI 2
+
+/**
+ * Request for an acknowledgment on success.
+ */
+#define NLM_F_ACK 4
+
+/**
+ * Echo this request
+ */
+#define NLM_F_ECHO 8
+
+/** @} */
+
+/**
+ * @name Additional message flags for GET requests
+ * @{
+ */
+
+/**
+ * Return the complete table instead of a single entry.
+ * @ingroup msg
+ */
+#define NLM_F_ROOT 0x100
+
+/**
+ * Return all entries matching criteria passed in message content.
+ */
+#define NLM_F_MATCH 0x200
+
+/**
+ * Return an atomic snapshot of the table being referenced. This
+ * may require special privileges because it has the potential to
+ * interrupt service in the FE for a longer time.
+ */
+#define NLM_F_ATOMIC 0x400
+
+/**
+ * Dump all entries
+ */
+#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
+
+/** @} */
+
+/**
+ * @name Additional messsage flags for NEW requests
+ * @{
+ */
+
+/**
+ * Replace existing matching config object with this request.
+ * @ingroup msg
+ */
+#define NLM_F_REPLACE 0x100
+
+/**
+ * Don't replace the config object if it already exists.
+ */
+#define NLM_F_EXCL 0x200
+
+/**
+ * Create config object if it doesn't already exist.
+ */
+#define NLM_F_CREATE 0x400
+
+/**
+ * Add to the end of the object list.
+ */
+#define NLM_F_APPEND 0x800
+
+/** @} */
+
+/**
+ * @name Standard Message types
+ * @{
+ */
+
+/**
+ * No operation, message must be ignored
+ * @ingroup msg
+ */
+#define NLMSG_NOOP 0x1
+
+/**
+ * The message signals an error and the payload contains a nlmsgerr
+ * structure. This can be looked at as a NACK and typically it is
+ * from FEC to CPC.
+ */
+#define NLMSG_ERROR 0x2
+
+/**
+ * Message terminates a multipart message.
+ */
+#define NLMSG_DONE 0x3
+
+/**
+ * The message signals that data got lost
+ */
+#define NLMSG_OVERRUN 0x4
+
+/**
+ * Lower limit of reserved message types
+ */
+#define NLMSG_MIN_TYPE 0x10
+
+/** @} */
+
+/**
+ * Netlink error message
+ * @ingroup msg
+ */
+struct nlmsgerr
+{
+ /** Error code (errno number) */
+ int error;
+
+ /** Original netlink message causing the error */
+ struct nlmsghdr msg;
+};
+
+struct nl_pktinfo
+{
+ __u32 group;
+};
+
+#endif /* __LINUX_NETLINK_H */
diff --git a/package/libnl-tiny/src/include/netlink/netlink.h b/package/libnl-tiny/src/include/netlink/netlink.h
new file mode 100644
index 000000000..e06fb7f11
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/netlink.h
@@ -0,0 +1,82 @@
+/*
+ * netlink/netlink.h Netlink Interface
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_NETLINK_H_
+#define NETLINK_NETLINK_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <netdb.h>
+#include <netlink/netlink-compat.h>
+#include <linux/netlink.h>
+#include <linux/genetlink.h>
+#include <netlink/version.h>
+#include <netlink/errno.h>
+#include <netlink/types.h>
+#include <netlink/handlers.h>
+#include <netlink/socket.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int nl_debug;
+extern struct nl_dump_params nl_debug_dp;
+
+/* Connection Management */
+extern int nl_connect(struct nl_sock *, int);
+extern void nl_close(struct nl_sock *);
+
+/* Send */
+extern int nl_sendto(struct nl_sock *, void *, size_t);
+extern int nl_sendmsg(struct nl_sock *, struct nl_msg *,
+ struct msghdr *);
+extern int nl_send(struct nl_sock *, struct nl_msg *);
+extern int nl_send_auto_complete(struct nl_sock *,
+ struct nl_msg *);
+extern int nl_send_simple(struct nl_sock *, int, int,
+ void *, size_t);
+
+/* Receive */
+extern int nl_recv(struct nl_sock *,
+ struct sockaddr_nl *, unsigned char **,
+ struct ucred **);
+extern int nl_recvmsgs(struct nl_sock *sk, struct nl_cb *cb);
+
+extern int nl_wait_for_ack(struct nl_sock *);
+
+/* Netlink Family Translations */
+extern char * nl_nlfamily2str(int, char *, size_t);
+extern int nl_str2nlfamily(const char *);
+
+/**
+ * Receive a set of message from a netlink socket using handlers in nl_sock.
+ * @arg sk Netlink socket.
+ *
+ * Calls nl_recvmsgs() with the handlers configured in the netlink socket.
+ */
+static inline int nl_recvmsgs_default(struct nl_sock *sk)
+{
+ return nl_recvmsgs(sk, sk->s_cb);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/object-api.h b/package/libnl-tiny/src/include/netlink/object-api.h
new file mode 100644
index 000000000..8a44fe901
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/object-api.h
@@ -0,0 +1,331 @@
+/*
+ * netlink/object-api.c Object API
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2007 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_OBJECT_API_H_
+#define NETLINK_OBJECT_API_H_
+
+#include <netlink/netlink.h>
+#include <netlink/utils.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @ingroup object
+ * @defgroup object_api Object API
+ * @brief
+ *
+ * @par 1) Object Definition
+ * @code
+ * // Define your object starting with the common object header
+ * struct my_obj {
+ * NLHDR_COMMON
+ * int my_data;
+ * };
+ *
+ * // Fill out the object operations structure
+ * struct nl_object_ops my_ops = {
+ * .oo_name = "my_obj",
+ * .oo_size = sizeof(struct my_obj),
+ * };
+ *
+ * // At this point the object can be allocated, you may want to provide a
+ * // separate _alloc() function to ease allocting objects of this kind.
+ * struct nl_object *obj = nl_object_alloc(&my_ops);
+ *
+ * // And release it again...
+ * nl_object_put(obj);
+ * @endcode
+ *
+ * @par 2) Allocating additional data
+ * @code
+ * // You may require to allocate additional data and store it inside
+ * // object, f.e. assuming there is a field `ptr'.
+ * struct my_obj {
+ * NLHDR_COMMON
+ * void * ptr;
+ * };
+ *
+ * // And at some point you may assign allocated data to this field:
+ * my_obj->ptr = calloc(1, ...);
+ *
+ * // In order to not introduce any memory leaks you have to release
+ * // this data again when the last reference is given back.
+ * static void my_obj_free_data(struct nl_object *obj)
+ * {
+ * struct my_obj *my_obj = nl_object_priv(obj);
+ *
+ * free(my_obj->ptr);
+ * }
+ *
+ * // Also when the object is cloned, you must ensure for your pointer
+ * // stay valid even if one of the clones is freed by either making
+ * // a clone as well or increase the reference count.
+ * static int my_obj_clone(struct nl_object *src, struct nl_object *dst)
+ * {
+ * struct my_obj *my_src = nl_object_priv(src);
+ * struct my_obj *my_dst = nl_object_priv(dst);
+ *
+ * if (src->ptr) {
+ * dst->ptr = calloc(1, ...);
+ * memcpy(dst->ptr, src->ptr, ...);
+ * }
+ * }
+ *
+ * struct nl_object_ops my_ops = {
+ * ...
+ * .oo_free_data = my_obj_free_data,
+ * .oo_clone = my_obj_clone,
+ * };
+ * @endcode
+ *
+ * @par 3) Object Dumping
+ * @code
+ * static int my_obj_dump_detailed(struct nl_object *obj,
+ * struct nl_dump_params *params)
+ * {
+ * struct my_obj *my_obj = nl_object_priv(obj);
+ *
+ * // It is absolutely essential to use nl_dump() when printing
+ * // any text to make sure the dumping parameters are respected.
+ * nl_dump(params, "Obj Integer: %d\n", my_obj->my_int);
+ *
+ * // Before we can dump the next line, make sure to prefix
+ * // this line correctly.
+ * nl_new_line(params);
+ *
+ * // You may also split a line into multiple nl_dump() calls.
+ * nl_dump(params, "String: %s ", my_obj->my_string);
+ * nl_dump(params, "String-2: %s\n", my_obj->another_string);
+ * }
+ *
+ * struct nl_object_ops my_ops = {
+ * ...
+ * .oo_dump[NL_DUMP_FULL] = my_obj_dump_detailed,
+ * };
+ * @endcode
+ *
+ * @par 4) Object Attributes
+ * @code
+ * // The concept of object attributes is optional but can ease the typical
+ * // case of objects that have optional attributes, e.g. a route may have a
+ * // nexthop assigned but it is not required to.
+ *
+ * // The first step to define your object specific bitmask listing all
+ * // attributes
+ * #define MY_ATTR_FOO (1<<0)
+ * #define MY_ATTR_BAR (1<<1)
+ *
+ * // When assigning an optional attribute to the object, make sure
+ * // to mark its availability.
+ * my_obj->foo = 123123;
+ * my_obj->ce_mask |= MY_ATTR_FOO;
+ *
+ * // At any time you may use this mask to check for the availability
+ * // of the attribute, e.g. while dumping
+ * if (my_obj->ce_mask & MY_ATTR_FOO)
+ * nl_dump(params, "foo %d ", my_obj->foo);
+ *
+ * // One of the big advantages of this concept is that it allows for
+ * // standardized comparisons which make it trivial for caches to
+ * // identify unique objects by use of unified comparison functions.
+ * // In order for it to work, your object implementation must provide
+ * // a comparison function and define a list of attributes which
+ * // combined together make an object unique.
+ *
+ * static int my_obj_compare(struct nl_object *_a, struct nl_object *_b,
+ * uint32_t attrs, int flags)
+ * {
+ * struct my_obj *a = nl_object_priv(_a):
+ * struct my_obj *b = nl_object_priv(_b):
+ * int diff = 0;
+ *
+ * // We help ourselves in defining our own DIFF macro which will
+ * // call ATTR_DIFF() on both objects which will make sure to only
+ * // compare the attributes if required.
+ * #define MY_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MY_ATTR_##ATTR, a, b, EXPR)
+ *
+ * // Call our own diff macro for each attribute to build a bitmask
+ * // representing the attributes which mismatch.
+ * diff |= MY_DIFF(FOO, a->foo != b->foo)
+ * diff |= MY_DIFF(BAR, strcmp(a->bar, b->bar))
+ *
+ * return diff;
+ * }
+ *
+ * // In order to identify identical objects with differing attributes
+ * // you must specify the attributes required to uniquely identify
+ * // your object. Make sure to not include too many attributes, this
+ * // list is used when caches look for an old version of an object.
+ * struct nl_object_ops my_ops = {
+ * ...
+ * .oo_id_attrs = MY_ATTR_FOO,
+ * .oo_compare = my_obj_compare,
+ * };
+ * @endcode
+ * @{
+ */
+
+/**
+ * Common Object Header
+ *
+ * This macro must be included as first member in every object
+ * definition to allow objects to be cached.
+ */
+#define NLHDR_COMMON \
+ int ce_refcnt; \
+ struct nl_object_ops * ce_ops; \
+ struct nl_cache * ce_cache; \
+ struct nl_list_head ce_list; \
+ int ce_msgtype; \
+ int ce_flags; \
+ uint32_t ce_mask;
+
+/**
+ * Return true if attribute is available in both objects
+ * @arg A an object
+ * @arg B another object
+ * @arg ATTR attribute bit
+ *
+ * @return True if the attribute is available, otherwise false is returned.
+ */
+#define AVAILABLE(A, B, ATTR) (((A)->ce_mask & (B)->ce_mask) & (ATTR))
+
+/**
+ * Return true if attributes mismatch
+ * @arg A an object
+ * @arg B another object
+ * @arg ATTR attribute bit
+ * @arg EXPR Comparison expression
+ *
+ * This function will check if the attribute in question is available
+ * in both objects, if not this will count as a mismatch.
+ *
+ * If available the function will execute the expression which must
+ * return true if the attributes mismatch.
+ *
+ * @return True if the attribute mismatch, or false if they match.
+ */
+#define ATTR_MISMATCH(A, B, ATTR, EXPR) (!AVAILABLE(A, B, ATTR) || (EXPR))
+
+/**
+ * Return attribute bit if attribute does not match
+ * @arg LIST list of attributes to be compared
+ * @arg ATTR attribute bit
+ * @arg A an object
+ * @arg B another object
+ * @arg EXPR Comparison expression
+ *
+ * This function will check if the attribute in question is available
+ * in both objects, if not this will count as a mismatch.
+ *
+ * If available the function will execute the expression which must
+ * return true if the attributes mismatch.
+ *
+ * In case the attributes mismatch, the attribute is returned, otherwise
+ * 0 is returned.
+ *
+ * @code
+ * diff |= ATTR_DIFF(attrs, MY_ATTR_FOO, a, b, a->foo != b->foo);
+ * @endcode
+ */
+#define ATTR_DIFF(LIST, ATTR, A, B, EXPR) \
+({ int diff = 0; \
+ if (((LIST) & (ATTR)) && ATTR_MISMATCH(A, B, ATTR, EXPR)) \
+ diff = ATTR; \
+ diff; })
+
+/**
+ * Object Operations
+ */
+struct nl_object;
+struct nl_object_ops
+{
+ /**
+ * Unique name of object type
+ *
+ * Must be in the form family/name, e.g. "route/addr"
+ */
+ char * oo_name;
+
+ /** Size of object including its header */
+ size_t oo_size;
+
+ /* List of attributes needed to uniquely identify the object */
+ uint32_t oo_id_attrs;
+
+ /**
+ * Constructor function
+ *
+ * Will be called when a new object of this type is allocated.
+ * Can be used to initialize members such as lists etc.
+ */
+ void (*oo_constructor)(struct nl_object *);
+
+ /**
+ * Destructor function
+ *
+ * Will be called when an object is freed. Must free all
+ * resources which may have been allocated as part of this
+ * object.
+ */
+ void (*oo_free_data)(struct nl_object *);
+
+ /**
+ * Cloning function
+ *
+ * Will be called when an object needs to be cloned. Please
+ * note that the generic object code will make an exact
+ * copy of the object first, therefore you only need to take
+ * care of members which require reference counting etc.
+ *
+ * May return a negative error code to abort cloning.
+ */
+ int (*oo_clone)(struct nl_object *, struct nl_object *);
+
+ /**
+ * Dumping functions
+ *
+ * Will be called when an object is dumped. The implementations
+ * have to use nl_dump(), nl_dump_line(), and nl_new_line() to
+ * dump objects.
+ *
+ * The functions must return the number of lines printed.
+ */
+ void (*oo_dump[NL_DUMP_MAX+1])(struct nl_object *,
+ struct nl_dump_params *);
+
+ /**
+ * Comparison function
+ *
+ * Will be called when two objects of the same type are
+ * compared. It takes the two objects in question, an object
+ * specific bitmask defining which attributes should be
+ * compared and flags to control the behaviour.
+ *
+ * The function must return a bitmask with the relevant bit
+ * set for each attribute that mismatches.
+ */
+ int (*oo_compare)(struct nl_object *, struct nl_object *,
+ uint32_t, int);
+
+
+ char *(*oo_attrs2str)(int, char *, size_t);
+};
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/object.h b/package/libnl-tiny/src/include/netlink/object.h
new file mode 100644
index 000000000..8aabe7bb1
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/object.h
@@ -0,0 +1,164 @@
+/*
+ * netlink/object.c Generic Cacheable Object
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_OBJECT_H_
+#define NETLINK_OBJECT_H_
+
+#include <netlink/netlink.h>
+#include <netlink/utils.h>
+#include <netlink/object-api.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NL_OBJ_MARK 1
+
+struct nl_cache;
+struct nl_object;
+struct nl_object_ops;
+
+struct nl_object
+{
+ NLHDR_COMMON
+};
+
+#define OBJ_CAST(ptr) ((struct nl_object *) (ptr))
+
+/* General */
+extern struct nl_object * nl_object_alloc(struct nl_object_ops *);
+extern void nl_object_free(struct nl_object *);
+extern struct nl_object * nl_object_clone(struct nl_object *obj);
+
+#ifdef disabled
+
+extern int nl_object_alloc_name(const char *,
+ struct nl_object **);
+extern void nl_object_dump(struct nl_object *,
+ struct nl_dump_params *);
+
+extern uint32_t nl_object_diff(struct nl_object *,
+ struct nl_object *);
+extern int nl_object_match_filter(struct nl_object *,
+ struct nl_object *);
+extern int nl_object_identical(struct nl_object *,
+ struct nl_object *);
+extern char * nl_object_attrs2str(struct nl_object *,
+ uint32_t attrs, char *buf,
+ size_t);
+#endif
+/**
+ * Check whether this object is used by multiple users
+ * @arg obj object to check
+ * @return true or false
+ */
+static inline int nl_object_shared(struct nl_object *obj)
+{
+ return obj->ce_refcnt > 1;
+}
+
+
+static inline void nl_object_get(struct nl_object *obj)
+{
+ obj->ce_refcnt++;
+}
+
+static inline void nl_object_put(struct nl_object *obj)
+{
+ if (!obj)
+ return;
+
+ obj->ce_refcnt--;
+
+ if (obj->ce_refcnt <= 0)
+ nl_object_free(obj);
+}
+
+
+/**
+ * @name Marks
+ * @{
+ */
+
+/**
+ * Add mark to object
+ * @arg obj Object to mark
+ */
+static inline void nl_object_mark(struct nl_object *obj)
+{
+ obj->ce_flags |= NL_OBJ_MARK;
+}
+
+/**
+ * Remove mark from object
+ * @arg obj Object to unmark
+ */
+static inline void nl_object_unmark(struct nl_object *obj)
+{
+ obj->ce_flags &= ~NL_OBJ_MARK;
+}
+
+/**
+ * Return true if object is marked
+ * @arg obj Object to check
+ * @return true if object is marked, otherwise false
+ */
+static inline int nl_object_is_marked(struct nl_object *obj)
+{
+ return (obj->ce_flags & NL_OBJ_MARK);
+}
+
+/** @} */
+
+#ifdef disabled
+/**
+ * Return list of attributes present in an object
+ * @arg obj an object
+ * @arg buf destination buffer
+ * @arg len length of destination buffer
+ *
+ * @return destination buffer.
+ */
+static inline char *nl_object_attr_list(struct nl_object *obj, char *buf, size_t len)
+{
+ return nl_object_attrs2str(obj, obj->ce_mask, buf, len);
+}
+#endif
+
+/**
+ * @name Attributes
+ * @{
+ */
+
+static inline int nl_object_get_refcnt(struct nl_object *obj)
+{
+ return obj->ce_refcnt;
+}
+
+static inline struct nl_cache *nl_object_get_cache(struct nl_object *obj)
+{
+ return obj->ce_cache;
+}
+
+static inline void * nl_object_priv(struct nl_object *obj)
+{
+ return obj;
+}
+
+
+/** @} */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/socket.h b/package/libnl-tiny/src/include/netlink/socket.h
new file mode 100644
index 000000000..9f7f4220a
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/socket.h
@@ -0,0 +1,221 @@
+/*
+ * netlink/socket.h Netlink Socket
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_SOCKET_H_
+#define NETLINK_SOCKET_H_
+
+#include <netlink/types.h>
+#include <netlink/handlers.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NL_SOCK_BUFSIZE_SET (1<<0)
+#define NL_SOCK_PASSCRED (1<<1)
+#define NL_OWN_PORT (1<<2)
+#define NL_MSG_PEEK (1<<3)
+#define NL_NO_AUTO_ACK (1<<4)
+
+struct nl_cb;
+struct nl_sock
+{
+ struct sockaddr_nl s_local;
+ struct sockaddr_nl s_peer;
+ int s_fd;
+ int s_proto;
+ unsigned int s_seq_next;
+ unsigned int s_seq_expect;
+ int s_flags;
+ struct nl_cb * s_cb;
+};
+
+
+extern struct nl_sock * nl_socket_alloc(void);
+extern struct nl_sock * nl_socket_alloc_cb(struct nl_cb *);
+extern void nl_socket_free(struct nl_sock *);
+
+extern void nl_socket_set_local_port(struct nl_sock *, uint32_t);
+
+extern int nl_socket_add_memberships(struct nl_sock *, int, ...);
+extern int nl_socket_drop_memberships(struct nl_sock *, int, ...);
+
+extern int nl_socket_set_buffer_size(struct nl_sock *, int, int);
+extern int nl_socket_set_passcred(struct nl_sock *, int);
+extern int nl_socket_recv_pktinfo(struct nl_sock *, int);
+
+extern void nl_socket_disable_seq_check(struct nl_sock *);
+
+extern int nl_socket_set_nonblocking(struct nl_sock *);
+
+/**
+ * Use next sequence number
+ * @arg sk Netlink socket.
+ *
+ * Uses the next available sequence number and increases the counter
+ * by one for subsequent calls.
+ *
+ * @return Unique serial sequence number
+ */
+static inline unsigned int nl_socket_use_seq(struct nl_sock *sk)
+{
+ return sk->s_seq_next++;
+}
+
+/**
+ * Disable automatic request for ACK
+ * @arg sk Netlink socket.
+ *
+ * The default behaviour of a socket is to request an ACK for
+ * each message sent to allow for the caller to synchronize to
+ * the completion of the netlink operation. This function
+ * disables this behaviour and will result in requests being
+ * sent which will not have the NLM_F_ACK flag set automatically.
+ * However, it is still possible for the caller to set the
+ * NLM_F_ACK flag explicitely.
+ */
+static inline void nl_socket_disable_auto_ack(struct nl_sock *sk)
+{
+ sk->s_flags |= NL_NO_AUTO_ACK;
+}
+
+/**
+ * Enable automatic request for ACK (default)
+ * @arg sk Netlink socket.
+ * @see nl_socket_disable_auto_ack
+ */
+static inline void nl_socket_enable_auto_ack(struct nl_sock *sk)
+{
+ sk->s_flags &= ~NL_NO_AUTO_ACK;
+}
+
+/**
+ * @name Source Idenficiation
+ * @{
+ */
+
+static inline uint32_t nl_socket_get_local_port(struct nl_sock *sk)
+{
+ return sk->s_local.nl_pid;
+}
+
+/**
+ * Join multicast groups (deprecated)
+ * @arg sk Netlink socket.
+ * @arg groups Bitmask of groups to join.
+ *
+ * This function defines the old way of joining multicast group which
+ * has to be done prior to calling nl_connect(). It works on any kernel
+ * version but is very limited as only 32 groups can be joined.
+ */
+static inline void nl_join_groups(struct nl_sock *sk, int groups)
+{
+ sk->s_local.nl_groups |= groups;
+}
+
+/**
+ * @name Peer Identfication
+ * @{
+ */
+
+static inline uint32_t nl_socket_get_peer_port(struct nl_sock *sk)
+{
+ return sk->s_peer.nl_pid;
+}
+
+static inline void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port)
+{
+ sk->s_peer.nl_pid = port;
+}
+
+/** @} */
+
+/**
+ * @name File Descriptor
+ * @{
+ */
+
+static inline int nl_socket_get_fd(struct nl_sock *sk)
+{
+ return sk->s_fd;
+}
+
+/**
+ * Enable use of MSG_PEEK when reading from socket
+ * @arg sk Netlink socket.
+ */
+static inline void nl_socket_enable_msg_peek(struct nl_sock *sk)
+{
+ sk->s_flags |= NL_MSG_PEEK;
+}
+
+/**
+ * Disable use of MSG_PEEK when reading from socket
+ * @arg sk Netlink socket.
+ */
+static inline void nl_socket_disable_msg_peek(struct nl_sock *sk)
+{
+ sk->s_flags &= ~NL_MSG_PEEK;
+}
+
+/**
+ * @name Callback Handler
+ * @{
+ */
+
+static inline struct nl_cb *nl_socket_get_cb(struct nl_sock *sk)
+{
+ return nl_cb_get(sk->s_cb);
+}
+
+static inline void nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb)
+{
+ nl_cb_put(sk->s_cb);
+ sk->s_cb = nl_cb_get(cb);
+}
+
+/**
+ * Modify the callback handler associated to the socket
+ * @arg sk Netlink socket.
+ * @arg type which type callback to set
+ * @arg kind kind of callback
+ * @arg func callback function
+ * @arg arg argument to be passwd to callback function
+ *
+ * @see nl_cb_set
+ */
+static inline int nl_socket_modify_cb(struct nl_sock *sk, enum nl_cb_type type,
+ enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func,
+ void *arg)
+{
+ return nl_cb_set(sk->s_cb, type, kind, func, arg);
+}
+
+/** @} */
+
+static inline int nl_socket_add_membership(struct nl_sock *sk, int group)
+{
+ return nl_socket_add_memberships(sk, group, 0);
+}
+
+
+static inline int nl_socket_drop_membership(struct nl_sock *sk, int group)
+{
+ return nl_socket_drop_memberships(sk, group, 0);
+}
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/types.h b/package/libnl-tiny/src/include/netlink/types.h
new file mode 100644
index 000000000..de81ace11
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/types.h
@@ -0,0 +1,121 @@
+/*
+ * netlink/netlink-types.h Netlink Types
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef __NETLINK_TYPES_H_
+#define __NETLINK_TYPES_H_
+
+#include <stdio.h>
+
+/**
+ * Dumping types (dp_type)
+ * @ingroup utils
+ */
+enum nl_dump_type {
+ NL_DUMP_LINE, /**< Dump object briefly on one line */
+ NL_DUMP_DETAILS, /**< Dump all attributes but no statistics */
+ NL_DUMP_STATS, /**< Dump all attributes including statistics */
+ NL_DUMP_ENV, /**< Dump all attribtues as env variables */
+ __NL_DUMP_MAX,
+};
+#define NL_DUMP_MAX (__NL_DUMP_MAX - 1)
+
+/**
+ * Dumping parameters
+ * @ingroup utils
+ */
+struct nl_dump_params
+{
+ /**
+ * Specifies the type of dump that is requested.
+ */
+ enum nl_dump_type dp_type;
+
+ /**
+ * Specifies the number of whitespaces to be put in front
+ * of every new line (indentation).
+ */
+ int dp_prefix;
+
+ /**
+ * Causes the cache index to be printed for each element.
+ */
+ int dp_print_index;
+
+ /**
+ * Causes each element to be prefixed with the message type.
+ */
+ int dp_dump_msgtype;
+
+ /**
+ * A callback invoked for output
+ *
+ * Passed arguments are:
+ * - dumping parameters
+ * - string to append to the output
+ */
+ void (*dp_cb)(struct nl_dump_params *, char *);
+
+ /**
+ * A callback invoked for every new line, can be used to
+ * customize the indentation.
+ *
+ * Passed arguments are:
+ * - dumping parameters
+ * - line number starting from 0
+ */
+ void (*dp_nl_cb)(struct nl_dump_params *, int);
+
+ /**
+ * User data pointer, can be used to pass data to callbacks.
+ */
+ void *dp_data;
+
+ /**
+ * File descriptor the dumping output should go to
+ */
+ FILE * dp_fd;
+
+ /**
+ * Alternatively the output may be redirected into a buffer
+ */
+ char * dp_buf;
+
+ /**
+ * Length of the buffer dp_buf
+ */
+ size_t dp_buflen;
+
+ /**
+ * PRIVATE
+ * Set if a dump was performed prior to the actual dump handler.
+ */
+ int dp_pre_dump;
+
+ /**
+ * PRIVATE
+ * Owned by the current caller
+ */
+ int dp_ivar;
+
+ unsigned int dp_line;
+};
+
+#ifndef __GNUC__
+#define __extension__
+#endif
+
+#define min_t(type,x,y) \
+ __extension__({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
+#define max_t(type,x,y) \
+ __extension__({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
+
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/utils.h b/package/libnl-tiny/src/include/netlink/utils.h
new file mode 100644
index 000000000..480bab618
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/utils.h
@@ -0,0 +1,78 @@
+/*
+ * netlink/utils.h Utility Functions
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_UTILS_H_
+#define NETLINK_UTILS_H_
+
+#include <netlink/netlink.h>
+#include <netlink/list.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @name Probability Constants
+ * @{
+ */
+
+/**
+ * Lower probability limit
+ * @ingroup utils
+ */
+#define NL_PROB_MIN 0x0
+
+/**
+ * Upper probability limit
+ * @ingroup utils
+ */
+#define NL_PROB_MAX 0xffffffff
+
+/** @} */
+
+/* unit pretty-printing */
+extern double nl_cancel_down_bytes(unsigned long long, char **);
+extern double nl_cancel_down_bits(unsigned long long, char **);
+extern double nl_cancel_down_us(uint32_t, char **);
+
+/* generic unit translations */
+extern long nl_size2int(const char *);
+extern long nl_prob2int(const char *);
+
+/* time translations */
+extern int nl_get_hz(void);
+extern uint32_t nl_us2ticks(uint32_t);
+extern uint32_t nl_ticks2us(uint32_t);
+extern int nl_str2msec(const char *, uint64_t *);
+extern char * nl_msec2str(uint64_t, char *, size_t);
+
+/* link layer protocol translations */
+extern char * nl_llproto2str(int, char *, size_t);
+extern int nl_str2llproto(const char *);
+
+/* ethernet protocol translations */
+extern char * nl_ether_proto2str(int, char *, size_t);
+extern int nl_str2ether_proto(const char *);
+
+/* IP protocol translations */
+extern char * nl_ip_proto2str(int, char *, size_t);
+extern int nl_str2ip_proto(const char *);
+
+/* Dumping helpers */
+extern void nl_new_line(struct nl_dump_params *);
+extern void nl_dump(struct nl_dump_params *, const char *, ...);
+extern void nl_dump_line(struct nl_dump_params *, const char *, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/package/libnl-tiny/src/include/netlink/version.h b/package/libnl-tiny/src/include/netlink/version.h
new file mode 100644
index 000000000..6a316d493
--- /dev/null
+++ b/package/libnl-tiny/src/include/netlink/version.h
@@ -0,0 +1,18 @@
+/*
+ * netlink/version.h Compile Time Versioning Information
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_VERSION_H_
+#define NETLINK_VERSION_H_
+
+#define LIBNL_STRING "libnl"
+#define LIBNL_VERSION "2.0"
+
+#endif
diff --git a/package/libnl-tiny/src/include/unl.h b/package/libnl-tiny/src/include/unl.h
new file mode 100644
index 000000000..4fe7dc745
--- /dev/null
+++ b/package/libnl-tiny/src/include/unl.h
@@ -0,0 +1,47 @@
+#ifndef __UNL_H
+#define __UNL_H
+
+#include <netlink/netlink.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <stdbool.h>
+
+struct unl {
+ struct nl_sock *sock;
+ struct nl_cache *cache;
+ struct genl_family *family;
+ char *family_name;
+ int hdrlen;
+ bool loop_done;
+};
+
+int unl_genl_init(struct unl *unl, const char *family);
+void unl_free(struct unl *unl);
+
+typedef int (*unl_cb)(struct nl_msg *, void *);
+
+struct nl_msg *unl_genl_msg(struct unl *unl, int cmd, bool dump);
+int unl_genl_request(struct unl *unl, struct nl_msg *msg, unl_cb handler, void *arg);
+int unl_genl_request_single(struct unl *unl, struct nl_msg *msg, struct nl_msg **dest);
+void unl_genl_loop(struct unl *unl, unl_cb handler, void *arg);
+
+int unl_genl_multicast_id(struct unl *unl, const char *name);
+int unl_genl_subscribe(struct unl *unl, const char *name);
+int unl_genl_unsubscribe(struct unl *unl, const char *name);
+
+int unl_nl80211_phy_lookup(const char *name);
+int unl_nl80211_wdev_to_phy(struct unl *unl, int wdev);
+struct nl_msg *unl_nl80211_phy_msg(struct unl *unl, int phy, int cmd, bool dump);
+struct nl_msg *unl_nl80211_vif_msg(struct unl *unl, int dev, int cmd, bool dump);
+
+static inline void unl_loop_done(struct unl *unl)
+{
+ unl->loop_done = true;
+}
+
+static inline struct nlattr *unl_find_attr(struct unl *unl, struct nl_msg *msg, int attr)
+{
+ return nlmsg_find_attr(nlmsg_hdr(msg), unl->hdrlen, attr);
+}
+
+#endif
diff --git a/package/libnl-tiny/src/msg.c b/package/libnl-tiny/src/msg.c
new file mode 100644
index 000000000..e84c281fc
--- /dev/null
+++ b/package/libnl-tiny/src/msg.c
@@ -0,0 +1,566 @@
+/*
+ * lib/msg.c Netlink Messages Interface
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+/**
+ * @ingroup core
+ * @defgroup msg Messages
+ * Netlink Message Construction/Parsing Interface
+ *
+ * The following information is partly extracted from RFC3549
+ * (ftp://ftp.rfc-editor.org/in-notes/rfc3549.txt)
+ *
+ * @par Message Format
+ * Netlink messages consist of a byte stream with one or multiple
+ * Netlink headers and an associated payload. If the payload is too big
+ * to fit into a single message it, can be split over multiple Netlink
+ * messages, collectively called a multipart message. For multipart
+ * messages, the first and all following headers have the \c NLM_F_MULTI
+ * Netlink header flag set, except for the last header which has the
+ * Netlink header type \c NLMSG_DONE.
+ *
+ * @par
+ * The Netlink message header (\link nlmsghdr struct nlmsghdr\endlink) is shown below.
+ * @code
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Type | Flags |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Sequence Number |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Process ID (PID) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * @endcode
+ *
+ * @par
+ * The netlink message header and payload must be aligned properly:
+ * @code
+ * <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) --->
+ * +----------------------------+- - -+- - - - - - - - - - -+- - -+
+ * | Header | Pad | Payload | Pad |
+ * | struct nlmsghdr | | | |
+ * +----------------------------+- - -+- - - - - - - - - - -+- - -+
+ * @endcode
+ * @par
+ * Message Format:
+ * @code
+ * <--- nlmsg_total_size(payload) --->
+ * <-- nlmsg_msg_size(payload) ->
+ * +----------+- - -+-------------+- - -+-------- - -
+ * | nlmsghdr | Pad | Payload | Pad | nlmsghdr
+ * +----------+- - -+-------------+- - -+-------- - -
+ * nlmsg_data(nlh)---^ ^
+ * nlmsg_next(nlh)-----------------------+
+ * @endcode
+ * @par
+ * The payload may consist of arbitary data but may have strict
+ * alignment and formatting rules depening on the specific netlink
+ * families.
+ * @par
+ * @code
+ * <---------------------- nlmsg_len(nlh) --------------------->
+ * <------ hdrlen ------> <- nlmsg_attrlen(nlh, hdrlen) ->
+ * +----------------------+- - -+--------------------------------+
+ * | Family Header | Pad | Attributes |
+ * +----------------------+- - -+--------------------------------+
+ * nlmsg_attrdata(nlh, hdrlen)---^
+ * @endcode
+ * @par The ACK Netlink Message
+ * This message is actually used to denote both an ACK and a NACK.
+ * Typically, the direction is from FEC to CPC (in response to an ACK
+ * request message). However, the CPC should be able to send ACKs back
+ * to FEC when requested.
+ * @code
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Netlink message header |
+ * | type = NLMSG_ERROR |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Error code |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | OLD Netlink message header |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * @endcode
+ *
+ * @par Example
+ * @code
+ * // Various methods exist to create/allocate a new netlink
+ * // message.
+ * //
+ * // nlmsg_alloc() will allocate an empty netlink message with
+ * // a maximum payload size which defaults to the page size of
+ * // the system. This default size can be modified using the
+ * // function nlmsg_set_default_size().
+ * struct nl_msg *msg = nlmsg_alloc();
+ *
+ * // Very often, the message type and message flags are known
+ * // at allocation time while the other fields are auto generated:
+ * struct nl_msg *msg = nlmsg_alloc_simple(MY_TYPE, MY_FLAGS);
+ *
+ * // Alternatively an existing netlink message header can be used
+ * // to inherit the header values:
+ * struct nlmsghdr hdr = {
+ * .nlmsg_type = MY_TYPE,
+ * .nlmsg_flags = MY_FLAGS,
+ * };
+ * struct nl_msg *msg = nlmsg_inherit(&hdr);
+ *
+ * // Last but not least, netlink messages received from netlink sockets
+ * // can be converted into nl_msg objects using nlmsg_convert(). This
+ * // will create a message with a maximum payload size which equals the
+ * // length of the existing netlink message, therefore no more data can
+ * // be appened without calling nlmsg_expand() first.
+ * struct nl_msg *msg = nlmsg_convert(nlh_from_nl_sock);
+ *
+ * // Payload may be added to the message via nlmsg_append(). The fourth
+ * // parameter specifies the number of alignment bytes the data should
+ * // be padding with at the end. Common values are 0 to disable it or
+ * // NLMSG_ALIGNTO to ensure proper netlink message padding.
+ * nlmsg_append(msg, &mydata, sizeof(mydata), 0);
+ *
+ * // Sometimes it may be necessary to reserve room for data but defer
+ * // the actual copying to a later point, nlmsg_reserve() can be used
+ * // for this purpose:
+ * void *data = nlmsg_reserve(msg, sizeof(mydata), NLMSG_ALIGNTO);
+ *
+ * // Attributes may be added using the attributes interface.
+ *
+ * // After successful use of the message, the memory must be freed
+ * // using nlmsg_free()
+ * nlmsg_free(msg);
+ * @endcode
+ *
+ * @par 4) Parsing messages
+ * @code
+ * int n;
+ * unsigned char *buf;
+ * struct nlmsghdr *hdr;
+ *
+ * n = nl_recv(handle, NULL, &buf);
+ *
+ * hdr = (struct nlmsghdr *) buf;
+ * while (nlmsg_ok(hdr, n)) {
+ * // Process message here...
+ * hdr = nlmsg_next(hdr, &n);
+ * }
+ * @endcode
+ * @{
+ */
+
+#include <netlink-local.h>
+#include <netlink/netlink.h>
+#include <netlink/utils.h>
+#include <netlink/cache.h>
+#include <netlink/attr.h>
+#include <netlink/msg.h>
+#include <linux/socket.h>
+
+static size_t default_msg_size;
+
+static void __init init_msg_size(void)
+{
+ default_msg_size = getpagesize();
+}
+
+/**
+ * @name Attribute Access
+ * @{
+ */
+
+//** @} */
+
+/**
+ * @name Message Parsing
+ * @{
+ */
+
+/**
+ * check if the netlink message fits into the remaining bytes
+ * @arg nlh netlink message header
+ * @arg remaining number of bytes remaining in message stream
+ */
+int nlmsg_ok(const struct nlmsghdr *nlh, int remaining)
+{
+ return (remaining >= sizeof(struct nlmsghdr) &&
+ nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
+ nlh->nlmsg_len <= remaining);
+}
+
+/**
+ * next netlink message in message stream
+ * @arg nlh netlink message header
+ * @arg remaining number of bytes remaining in message stream
+ *
+ * @returns the next netlink message in the message stream and
+ * decrements remaining by the size of the current message.
+ */
+struct nlmsghdr *nlmsg_next(struct nlmsghdr *nlh, int *remaining)
+{
+ int totlen = NLMSG_ALIGN(nlh->nlmsg_len);
+
+ *remaining -= totlen;
+
+ return (struct nlmsghdr *) ((unsigned char *) nlh + totlen);
+}
+
+/**
+ * parse attributes of a netlink message
+ * @arg nlh netlink message header
+ * @arg hdrlen length of family specific header
+ * @arg tb destination array with maxtype+1 elements
+ * @arg maxtype maximum attribute type to be expected
+ * @arg policy validation policy
+ *
+ * See nla_parse()
+ */
+int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
+ int maxtype, struct nla_policy *policy)
+{
+ if (!nlmsg_valid_hdr(nlh, hdrlen))
+ return -NLE_MSG_TOOSHORT;
+
+ return nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen),
+ nlmsg_attrlen(nlh, hdrlen), policy);
+}
+
+/**
+ * nlmsg_validate - validate a netlink message including attributes
+ * @arg nlh netlinket message header
+ * @arg hdrlen length of familiy specific header
+ * @arg maxtype maximum attribute type to be expected
+ * @arg policy validation policy
+ */
+int nlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype,
+ struct nla_policy *policy)
+{
+ if (!nlmsg_valid_hdr(nlh, hdrlen))
+ return -NLE_MSG_TOOSHORT;
+
+ return nla_validate(nlmsg_attrdata(nlh, hdrlen),
+ nlmsg_attrlen(nlh, hdrlen), maxtype, policy);
+}
+
+/** @} */
+
+/**
+ * @name Message Building/Access
+ * @{
+ */
+
+static struct nl_msg *__nlmsg_alloc(size_t len)
+{
+ struct nl_msg *nm;
+
+ nm = calloc(1, sizeof(*nm));
+ if (!nm)
+ goto errout;
+
+ nm->nm_refcnt = 1;
+
+ nm->nm_nlh = malloc(len);
+ if (!nm->nm_nlh)
+ goto errout;
+
+ memset(nm->nm_nlh, 0, sizeof(struct nlmsghdr));
+
+ nm->nm_protocol = -1;
+ nm->nm_size = len;
+ nm->nm_nlh->nlmsg_len = nlmsg_total_size(0);
+
+ NL_DBG(2, "msg %p: Allocated new message, maxlen=%zu\n", nm, len);
+
+ return nm;
+errout:
+ free(nm);
+ return NULL;
+}
+
+/**
+ * Allocate a new netlink message with the default maximum payload size.
+ *
+ * Allocates a new netlink message without any further payload. The
+ * maximum payload size defaults to PAGESIZE or as otherwise specified
+ * with nlmsg_set_default_size().
+ *
+ * @return Newly allocated netlink message or NULL.
+ */
+struct nl_msg *nlmsg_alloc(void)
+{
+ return __nlmsg_alloc(default_msg_size);
+}
+
+/**
+ * Allocate a new netlink message with maximum payload size specified.
+ */
+struct nl_msg *nlmsg_alloc_size(size_t max)
+{
+ return __nlmsg_alloc(max);
+}
+
+/**
+ * Allocate a new netlink message and inherit netlink message header
+ * @arg hdr Netlink message header template
+ *
+ * Allocates a new netlink message and inherits the original message
+ * header. If \a hdr is not NULL it will be used as a template for
+ * the netlink message header, otherwise the header is left blank.
+ *
+ * @return Newly allocated netlink message or NULL
+ */
+struct nl_msg *nlmsg_inherit(struct nlmsghdr *hdr)
+{
+ struct nl_msg *nm;
+
+ nm = nlmsg_alloc();
+ if (nm && hdr) {
+ struct nlmsghdr *new = nm->nm_nlh;
+
+ new->nlmsg_type = hdr->nlmsg_type;
+ new->nlmsg_flags = hdr->nlmsg_flags;
+ new->nlmsg_seq = hdr->nlmsg_seq;
+ new->nlmsg_pid = hdr->nlmsg_pid;
+ }
+
+ return nm;
+}
+
+/**
+ * Allocate a new netlink message
+ * @arg nlmsgtype Netlink message type
+ * @arg flags Message flags.
+ *
+ * @return Newly allocated netlink message or NULL.
+ */
+struct nl_msg *nlmsg_alloc_simple(int nlmsgtype, int flags)
+{
+ struct nl_msg *msg;
+ struct nlmsghdr nlh = {
+ .nlmsg_type = nlmsgtype,
+ .nlmsg_flags = flags,
+ };
+
+ msg = nlmsg_inherit(&nlh);
+ if (msg)
+ NL_DBG(2, "msg %p: Allocated new simple message\n", msg);
+
+ return msg;
+}
+
+/**
+ * Set the default maximum message payload size for allocated messages
+ * @arg max Size of payload in bytes.
+ */
+void nlmsg_set_default_size(size_t max)
+{
+ if (max < nlmsg_total_size(0))
+ max = nlmsg_total_size(0);
+
+ default_msg_size = max;
+}
+
+/**
+ * Convert a netlink message received from a netlink socket to a nl_msg
+ * @arg hdr Netlink message received from netlink socket.
+ *
+ * Allocates a new netlink message and copies all of the data pointed to
+ * by \a hdr into the new message object.
+ *
+ * @return Newly allocated netlink message or NULL.
+ */
+struct nl_msg *nlmsg_convert(struct nlmsghdr *hdr)
+{
+ struct nl_msg *nm;
+
+ nm = __nlmsg_alloc(NLMSG_ALIGN(hdr->nlmsg_len));
+ if (!nm)
+ goto errout;
+
+ memcpy(nm->nm_nlh, hdr, hdr->nlmsg_len);
+
+ return nm;
+errout:
+ nlmsg_free(nm);
+ return NULL;
+}
+
+/**
+ * Reserve room for additional data in a netlink message
+ * @arg n netlink message
+ * @arg len length of additional data to reserve room for
+ * @arg pad number of bytes to align data to
+ *
+ * Reserves room for additional data at the tail of the an
+ * existing netlink message. Eventual padding required will
+ * be zeroed out.
+ *
+ * @return Pointer to start of additional data tailroom or NULL.
+ */
+void *nlmsg_reserve(struct nl_msg *n, size_t len, int pad)
+{
+ void *buf = n->nm_nlh;
+ size_t nlmsg_len = n->nm_nlh->nlmsg_len;
+ size_t tlen;
+
+ tlen = pad ? ((len + (pad - 1)) & ~(pad - 1)) : len;
+
+ if ((tlen + nlmsg_len) > n->nm_size)
+ return NULL;
+
+ buf += nlmsg_len;
+ n->nm_nlh->nlmsg_len += tlen;
+
+ if (tlen > len)
+ memset(buf + len, 0, tlen - len);
+
+ NL_DBG(2, "msg %p: Reserved %zu bytes, pad=%d, nlmsg_len=%d\n",
+ n, len, pad, n->nm_nlh->nlmsg_len);
+
+ return buf;
+}
+
+/**
+ * Append data to tail of a netlink message
+ * @arg n netlink message
+ * @arg data data to add
+ * @arg len length of data
+ * @arg pad Number of bytes to align data to.
+ *
+ * Extends the netlink message as needed and appends the data of given
+ * length to the message.
+ *
+ * @return 0 on success or a negative error code
+ */
+int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
+{
+ void *tmp;
+
+ tmp = nlmsg_reserve(n, len, pad);
+ if (tmp == NULL)
+ return -NLE_NOMEM;
+
+ memcpy(tmp, data, len);
+ NL_DBG(2, "msg %p: Appended %zu bytes with padding %d\n", n, len, pad);
+
+ return 0;
+}
+
+/**
+ * Add a netlink message header to a netlink message
+ * @arg n netlink message
+ * @arg pid netlink process id or NL_AUTO_PID
+ * @arg seq sequence number of message or NL_AUTO_SEQ
+ * @arg type message type
+ * @arg payload length of message payload
+ * @arg flags message flags
+ *
+ * Adds or overwrites the netlink message header in an existing message
+ * object. If \a payload is greater-than zero additional room will be
+ * reserved, f.e. for family specific headers. It can be accesed via
+ * nlmsg_data().
+ *
+ * @return A pointer to the netlink message header or NULL.
+ */
+struct nlmsghdr *nlmsg_put(struct nl_msg *n, uint32_t pid, uint32_t seq,
+ int type, int payload, int flags)
+{
+ struct nlmsghdr *nlh;
+
+ if (n->nm_nlh->nlmsg_len < NLMSG_HDRLEN)
+ BUG();
+
+ nlh = (struct nlmsghdr *) n->nm_nlh;
+ nlh->nlmsg_type = type;
+ nlh->nlmsg_flags = flags;
+ nlh->nlmsg_pid = pid;
+ nlh->nlmsg_seq = seq;
+
+ NL_DBG(2, "msg %p: Added netlink header type=%d, flags=%d, pid=%d, "
+ "seq=%d\n", n, type, flags, pid, seq);
+
+ if (payload > 0 &&
+ nlmsg_reserve(n, payload, NLMSG_ALIGNTO) == NULL)
+ return NULL;
+
+ return nlh;
+}
+
+/**
+ * Release a reference from an netlink message
+ * @arg msg message to release reference from
+ *
+ * Frees memory after the last reference has been released.
+ */
+void nlmsg_free(struct nl_msg *msg)
+{
+ if (!msg)
+ return;
+
+ msg->nm_refcnt--;
+ NL_DBG(4, "Returned message reference %p, %d remaining\n",
+ msg, msg->nm_refcnt);
+
+ if (msg->nm_refcnt < 0)
+ BUG();
+
+ if (msg->nm_refcnt <= 0) {
+ free(msg->nm_nlh);
+ free(msg);
+ NL_DBG(2, "msg %p: Freed\n", msg);
+ }
+}
+
+/** @} */
+
+/**
+ * @name Direct Parsing
+ * @{
+ */
+
+/** @cond SKIP */
+struct dp_xdata {
+ void (*cb)(struct nl_object *, void *);
+ void *arg;
+};
+/** @endcond */
+
+static int parse_cb(struct nl_object *obj, struct nl_parser_param *p)
+{
+ struct dp_xdata *x = p->pp_arg;
+
+ x->cb(obj, x->arg);
+ return 0;
+}
+
+int nl_msg_parse(struct nl_msg *msg, void (*cb)(struct nl_object *, void *),
+ void *arg)
+{
+ struct nl_cache_ops *ops;
+ struct nl_parser_param p = {
+ .pp_cb = parse_cb
+ };
+ struct dp_xdata x = {
+ .cb = cb,
+ .arg = arg,
+ };
+
+ ops = nl_cache_ops_associate(nlmsg_get_proto(msg),
+ nlmsg_hdr(msg)->nlmsg_type);
+ if (ops == NULL)
+ return -NLE_MSGTYPE_NOSUPPORT;
+ p.pp_arg = &x;
+
+ return nl_cache_parse(ops, NULL, nlmsg_hdr(msg), &p);
+}
+
+/** @} */
diff --git a/package/libnl-tiny/src/nl.c b/package/libnl-tiny/src/nl.c
new file mode 100644
index 000000000..99e9aebeb
--- /dev/null
+++ b/package/libnl-tiny/src/nl.c
@@ -0,0 +1,720 @@
+/*
+ * lib/nl.c Core Netlink Interface
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+/**
+ * @defgroup core Core
+ *
+ * @details
+ * @par 1) Connecting the socket
+ * @code
+ * // Bind and connect the socket to a protocol, NETLINK_ROUTE in this example.
+ * nl_connect(sk, NETLINK_ROUTE);
+ * @endcode
+ *
+ * @par 2) Sending data
+ * @code
+ * // The most rudimentary method is to use nl_sendto() simply pushing
+ * // a piece of data to the other netlink peer. This method is not
+ * // recommended.
+ * const char buf[] = { 0x01, 0x02, 0x03, 0x04 };
+ * nl_sendto(sk, buf, sizeof(buf));
+ *
+ * // A more comfortable interface is nl_send() taking a pointer to
+ * // a netlink message.
+ * struct nl_msg *msg = my_msg_builder();
+ * nl_send(sk, nlmsg_hdr(msg));
+ *
+ * // nl_sendmsg() provides additional control over the sendmsg() message
+ * // header in order to allow more specific addressing of multiple peers etc.
+ * struct msghdr hdr = { ... };
+ * nl_sendmsg(sk, nlmsg_hdr(msg), &hdr);
+ *
+ * // You're probably too lazy to fill out the netlink pid, sequence number
+ * // and message flags all the time. nl_send_auto_complete() automatically
+ * // extends your message header as needed with an appropriate sequence
+ * // number, the netlink pid stored in the netlink socket and the message
+ * // flags NLM_F_REQUEST and NLM_F_ACK (if not disabled in the socket)
+ * nl_send_auto_complete(sk, nlmsg_hdr(msg));
+ *
+ * // Simple protocols don't require the complex message construction interface
+ * // and may favour nl_send_simple() to easly send a bunch of payload
+ * // encapsulated in a netlink message header.
+ * nl_send_simple(sk, MY_MSG_TYPE, 0, buf, sizeof(buf));
+ * @endcode
+ *
+ * @par 3) Receiving data
+ * @code
+ * // nl_recv() receives a single message allocating a buffer for the message
+ * // content and gives back the pointer to you.
+ * struct sockaddr_nl peer;
+ * unsigned char *msg;
+ * nl_recv(sk, &peer, &msg);
+ *
+ * // nl_recvmsgs() receives a bunch of messages until the callback system
+ * // orders it to state, usually after receving a compolete multi part
+ * // message series.
+ * nl_recvmsgs(sk, my_callback_configuration);
+ *
+ * // nl_recvmsgs_default() acts just like nl_recvmsg() but uses the callback
+ * // configuration stored in the socket.
+ * nl_recvmsgs_default(sk);
+ *
+ * // In case you want to wait for the ACK to be recieved that you requested
+ * // with your latest message, you can call nl_wait_for_ack()
+ * nl_wait_for_ack(sk);
+ * @endcode
+ *
+ * @par 4) Closing
+ * @code
+ * // Close the socket first to release kernel memory
+ * nl_close(sk);
+ * @endcode
+ *
+ * @{
+ */
+
+#include <netlink-local.h>
+#include <netlink/netlink.h>
+#include <netlink/utils.h>
+#include <netlink/handlers.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+
+/**
+ * @name Connection Management
+ * @{
+ */
+
+/**
+ * Create and connect netlink socket.
+ * @arg sk Netlink socket.
+ * @arg protocol Netlink protocol to use.
+ *
+ * Creates a netlink socket using the specified protocol, binds the socket
+ * and issues a connection attempt.
+ *
+ * @return 0 on success or a negative error code.
+ */
+int nl_connect(struct nl_sock *sk, int protocol)
+{
+ int err;
+ socklen_t addrlen;
+
+ sk->s_fd = socket(AF_NETLINK, SOCK_RAW, protocol);
+ if (sk->s_fd < 0) {
+ err = -nl_syserr2nlerr(errno);
+ goto errout;
+ }
+
+ if (!(sk->s_flags & NL_SOCK_BUFSIZE_SET)) {
+ err = nl_socket_set_buffer_size(sk, 0, 0);
+ if (err < 0)
+ goto errout;
+ }
+
+ err = bind(sk->s_fd, (struct sockaddr*) &sk->s_local,
+ sizeof(sk->s_local));
+ if (err < 0) {
+ err = -nl_syserr2nlerr(errno);
+ goto errout;
+ }
+
+ addrlen = sizeof(sk->s_local);
+ err = getsockname(sk->s_fd, (struct sockaddr *) &sk->s_local,
+ &addrlen);
+ if (err < 0) {
+ err = -nl_syserr2nlerr(errno);
+ goto errout;
+ }
+
+ if (addrlen != sizeof(sk->s_local)) {
+ err = -NLE_NOADDR;
+ goto errout;
+ }
+
+ if (sk->s_local.nl_family != AF_NETLINK) {
+ err = -NLE_AF_NOSUPPORT;
+ goto errout;
+ }
+
+ sk->s_proto = protocol;
+
+ return 0;
+errout:
+ close(sk->s_fd);
+ sk->s_fd = -1;
+
+ return err;
+}
+
+/**
+ * Close/Disconnect netlink socket.
+ * @arg sk Netlink socket.
+ */
+void nl_close(struct nl_sock *sk)
+{
+ if (sk->s_fd >= 0) {
+ close(sk->s_fd);
+ sk->s_fd = -1;
+ }
+
+ sk->s_proto = 0;
+}
+
+/** @} */
+
+/**
+ * @name Send
+ * @{
+ */
+
+/**
+ * Send raw data over netlink socket.
+ * @arg sk Netlink socket.
+ * @arg buf Data buffer.
+ * @arg size Size of data buffer.
+ * @return Number of characters written on success or a negative error code.
+ */
+int nl_sendto(struct nl_sock *sk, void *buf, size_t size)
+{
+ int ret;
+
+ ret = sendto(sk->s_fd, buf, size, 0, (struct sockaddr *)
+ &sk->s_peer, sizeof(sk->s_peer));
+ if (ret < 0)
+ return -nl_syserr2nlerr(errno);
+
+ return ret;
+}
+
+/**
+ * Send netlink message with control over sendmsg() message header.
+ * @arg sk Netlink socket.
+ * @arg msg Netlink message to be sent.
+ * @arg hdr Sendmsg() message header.
+ * @return Number of characters sent on sucess or a negative error code.
+ */
+int nl_sendmsg(struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr)
+{
+ struct nl_cb *cb;
+ int ret;
+
+ struct iovec iov = {
+ .iov_base = (void *) nlmsg_hdr(msg),
+ .iov_len = nlmsg_hdr(msg)->nlmsg_len,
+ };
+
+ hdr->msg_iov = &iov;
+ hdr->msg_iovlen = 1;
+
+ nlmsg_set_src(msg, &sk->s_local);
+
+ cb = sk->s_cb;
+ if (cb->cb_set[NL_CB_MSG_OUT])
+ if (nl_cb_call(cb, NL_CB_MSG_OUT, msg) != NL_OK)
+ return 0;
+
+ ret = sendmsg(sk->s_fd, hdr, 0);
+ if (ret < 0)
+ return -nl_syserr2nlerr(errno);
+
+ return ret;
+}
+
+
+/**
+ * Send netlink message.
+ * @arg sk Netlink socket.
+ * @arg msg Netlink message to be sent.
+ * @see nl_sendmsg()
+ * @return Number of characters sent on success or a negative error code.
+ */
+int nl_send(struct nl_sock *sk, struct nl_msg *msg)
+{
+ struct sockaddr_nl *dst;
+ struct ucred *creds;
+
+ struct msghdr hdr = {
+ .msg_name = (void *) &sk->s_peer,
+ .msg_namelen = sizeof(struct sockaddr_nl),
+ };
+
+ /* Overwrite destination if specified in the message itself, defaults
+ * to the peer address of the socket.
+ */
+ dst = nlmsg_get_dst(msg);
+ if (dst->nl_family == AF_NETLINK)
+ hdr.msg_name = dst;
+
+ /* Add credentials if present. */
+ creds = nlmsg_get_creds(msg);
+ if (creds != NULL) {
+ char buf[CMSG_SPACE(sizeof(struct ucred))];
+ struct cmsghdr *cmsg;
+
+ hdr.msg_control = buf;
+ hdr.msg_controllen = sizeof(buf);
+
+ cmsg = CMSG_FIRSTHDR(&hdr);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_CREDENTIALS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
+ memcpy(CMSG_DATA(cmsg), creds, sizeof(struct ucred));
+ }
+
+ return nl_sendmsg(sk, msg, &hdr);
+}
+
+/**
+ * Send netlink message and check & extend header values as needed.
+ * @arg sk Netlink socket.
+ * @arg msg Netlink message to be sent.
+ *
+ * Checks the netlink message \c nlh for completness and extends it
+ * as required before sending it out. Checked fields include pid,
+ * sequence nr, and flags.
+ *
+ * @see nl_send()
+ * @return Number of characters sent or a negative error code.
+ */
+int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
+{
+ struct nlmsghdr *nlh;
+ struct nl_cb *cb = sk->s_cb;
+
+ nlh = nlmsg_hdr(msg);
+ if (nlh->nlmsg_pid == 0)
+ nlh->nlmsg_pid = sk->s_local.nl_pid;
+
+ if (nlh->nlmsg_seq == 0)
+ nlh->nlmsg_seq = sk->s_seq_next++;
+
+ if (msg->nm_protocol == -1)
+ msg->nm_protocol = sk->s_proto;
+
+ nlh->nlmsg_flags |= NLM_F_REQUEST;
+
+ if (!(sk->s_flags & NL_NO_AUTO_ACK))
+ nlh->nlmsg_flags |= NLM_F_ACK;
+
+ if (cb->cb_send_ow)
+ return cb->cb_send_ow(sk, msg);
+ else
+ return nl_send(sk, msg);
+}
+
+/**
+ * Send simple netlink message using nl_send_auto_complete()
+ * @arg sk Netlink socket.
+ * @arg type Netlink message type.
+ * @arg flags Netlink message flags.
+ * @arg buf Data buffer.
+ * @arg size Size of data buffer.
+ *
+ * Builds a netlink message with the specified type and flags and
+ * appends the specified data as payload to the message.
+ *
+ * @see nl_send_auto_complete()
+ * @return Number of characters sent on success or a negative error code.
+ */
+int nl_send_simple(struct nl_sock *sk, int type, int flags, void *buf,
+ size_t size)
+{
+ int err;
+ struct nl_msg *msg;
+
+ msg = nlmsg_alloc_simple(type, flags);
+ if (!msg)
+ return -NLE_NOMEM;
+
+ if (buf && size) {
+ err = nlmsg_append(msg, buf, size, NLMSG_ALIGNTO);
+ if (err < 0)
+ goto errout;
+ }
+
+
+ err = nl_send_auto_complete(sk, msg);
+errout:
+ nlmsg_free(msg);
+
+ return err;
+}
+
+/** @} */
+
+/**
+ * @name Receive
+ * @{
+ */
+
+/**
+ * Receive data from netlink socket
+ * @arg sk Netlink socket.
+ * @arg nla Destination pointer for peer's netlink address.
+ * @arg buf Destination pointer for message content.
+ * @arg creds Destination pointer for credentials.
+ *
+ * Receives a netlink message, allocates a buffer in \c *buf and
+ * stores the message content. The peer's netlink address is stored
+ * in \c *nla. The caller is responsible for freeing the buffer allocated
+ * in \c *buf if a positive value is returned. Interruped system calls
+ * are handled by repeating the read. The input buffer size is determined
+ * by peeking before the actual read is done.
+ *
+ * A non-blocking sockets causes the function to return immediately with
+ * a return value of 0 if no data is available.
+ *
+ * @return Number of octets read, 0 on EOF or a negative error code.
+ */
+int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla,
+ unsigned char **buf, struct ucred **creds)
+{
+ int n;
+ int flags = 0;
+ static int page_size = 0;
+ struct iovec iov;
+ struct msghdr msg = {
+ .msg_name = (void *) nla,
+ .msg_namelen = sizeof(struct sockaddr_nl),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ .msg_control = NULL,
+ .msg_controllen = 0,
+ .msg_flags = 0,
+ };
+ struct cmsghdr *cmsg;
+
+ if (sk->s_flags & NL_MSG_PEEK)
+ flags |= MSG_PEEK;
+
+ if (page_size == 0)
+ page_size = getpagesize();
+
+ iov.iov_len = page_size;
+ iov.iov_base = *buf = malloc(iov.iov_len);
+
+ if (sk->s_flags & NL_SOCK_PASSCRED) {
+ msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
+ msg.msg_control = calloc(1, msg.msg_controllen);
+ }
+retry:
+
+ n = recvmsg(sk->s_fd, &msg, flags);
+ if (!n)
+ goto abort;
+ else if (n < 0) {
+ if (errno == EINTR) {
+ NL_DBG(3, "recvmsg() returned EINTR, retrying\n");
+ goto retry;
+ } else if (errno == EAGAIN) {
+ NL_DBG(3, "recvmsg() returned EAGAIN, aborting\n");
+ goto abort;
+ } else {
+ free(msg.msg_control);
+ free(*buf);
+ return -nl_syserr2nlerr(errno);
+ }
+ }
+
+ if (iov.iov_len < n ||
+ msg.msg_flags & MSG_TRUNC) {
+ /* Provided buffer is not long enough, enlarge it
+ * and try again. */
+ iov.iov_len *= 2;
+ iov.iov_base = *buf = realloc(*buf, iov.iov_len);
+ goto retry;
+ } else if (msg.msg_flags & MSG_CTRUNC) {
+ msg.msg_controllen *= 2;
+ msg.msg_control = realloc(msg.msg_control, msg.msg_controllen);
+ goto retry;
+ } else if (flags != 0) {
+ /* Buffer is big enough, do the actual reading */
+ flags = 0;
+ goto retry;
+ }
+
+ if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
+ free(msg.msg_control);
+ free(*buf);
+ return -NLE_NOADDR;
+ }
+
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+ if (cmsg->cmsg_level == SOL_SOCKET &&
+ cmsg->cmsg_type == SCM_CREDENTIALS) {
+ *creds = calloc(1, sizeof(struct ucred));
+ memcpy(*creds, CMSG_DATA(cmsg), sizeof(struct ucred));
+ break;
+ }
+ }
+
+ free(msg.msg_control);
+ return n;
+
+abort:
+ free(msg.msg_control);
+ free(*buf);
+ return 0;
+}
+
+#define NL_CB_CALL(cb, type, msg) \
+do { \
+ err = nl_cb_call(cb, type, msg); \
+ switch (err) { \
+ case NL_OK: \
+ err = 0; \
+ break; \
+ case NL_SKIP: \
+ goto skip; \
+ case NL_STOP: \
+ goto stop; \
+ default: \
+ goto out; \
+ } \
+} while (0)
+
+static int recvmsgs(struct nl_sock *sk, struct nl_cb *cb)
+{
+ int n, err = 0, multipart = 0;
+ unsigned char *buf = NULL;
+ struct nlmsghdr *hdr;
+ struct sockaddr_nl nla = {0};
+ struct nl_msg *msg = NULL;
+ struct ucred *creds = NULL;
+
+continue_reading:
+ NL_DBG(3, "Attempting to read from %p\n", sk);
+ if (cb->cb_recv_ow)
+ n = cb->cb_recv_ow(sk, &nla, &buf, &creds);
+ else
+ n = nl_recv(sk, &nla, &buf, &creds);
+
+ if (n <= 0)
+ return n;
+
+ NL_DBG(3, "recvmsgs(%p): Read %d bytes\n", sk, n);
+
+ hdr = (struct nlmsghdr *) buf;
+ while (nlmsg_ok(hdr, n)) {
+ NL_DBG(3, "recgmsgs(%p): Processing valid message...\n", sk);
+
+ nlmsg_free(msg);
+ msg = nlmsg_convert(hdr);
+ if (!msg) {
+ err = -NLE_NOMEM;
+ goto out;
+ }
+
+ nlmsg_set_proto(msg, sk->s_proto);
+ nlmsg_set_src(msg, &nla);
+ if (creds)
+ nlmsg_set_creds(msg, creds);
+
+ /* Raw callback is the first, it gives the most control
+ * to the user and he can do his very own parsing. */
+ if (cb->cb_set[NL_CB_MSG_IN])
+ NL_CB_CALL(cb, NL_CB_MSG_IN, msg);
+
+ /* Sequence number checking. The check may be done by
+ * the user, otherwise a very simple check is applied
+ * enforcing strict ordering */
+ if (cb->cb_set[NL_CB_SEQ_CHECK])
+ NL_CB_CALL(cb, NL_CB_SEQ_CHECK, msg);
+ else if (hdr->nlmsg_seq != sk->s_seq_expect) {
+ if (cb->cb_set[NL_CB_INVALID])
+ NL_CB_CALL(cb, NL_CB_INVALID, msg);
+ else {
+ err = -NLE_SEQ_MISMATCH;
+ goto out;
+ }
+ }
+
+ if (hdr->nlmsg_type == NLMSG_DONE ||
+ hdr->nlmsg_type == NLMSG_ERROR ||
+ hdr->nlmsg_type == NLMSG_NOOP ||
+ hdr->nlmsg_type == NLMSG_OVERRUN) {
+ /* We can't check for !NLM_F_MULTI since some netlink
+ * users in the kernel are broken. */
+ sk->s_seq_expect++;
+ NL_DBG(3, "recvmsgs(%p): Increased expected " \
+ "sequence number to %d\n",
+ sk, sk->s_seq_expect);
+ }
+
+ if (hdr->nlmsg_flags & NLM_F_MULTI)
+ multipart = 1;
+
+ /* Other side wishes to see an ack for this message */
+ if (hdr->nlmsg_flags & NLM_F_ACK) {
+ if (cb->cb_set[NL_CB_SEND_ACK])
+ NL_CB_CALL(cb, NL_CB_SEND_ACK, msg);
+ else {
+ /* FIXME: implement */
+ }
+ }
+
+ /* messages terminates a multpart message, this is
+ * usually the end of a message and therefore we slip
+ * out of the loop by default. the user may overrule
+ * this action by skipping this packet. */
+ if (hdr->nlmsg_type == NLMSG_DONE) {
+ multipart = 0;
+ if (cb->cb_set[NL_CB_FINISH])
+ NL_CB_CALL(cb, NL_CB_FINISH, msg);
+ }
+
+ /* Message to be ignored, the default action is to
+ * skip this message if no callback is specified. The
+ * user may overrule this action by returning
+ * NL_PROCEED. */
+ else if (hdr->nlmsg_type == NLMSG_NOOP) {
+ if (cb->cb_set[NL_CB_SKIPPED])
+ NL_CB_CALL(cb, NL_CB_SKIPPED, msg);
+ else
+ goto skip;
+ }
+
+ /* Data got lost, report back to user. The default action is to
+ * quit parsing. The user may overrule this action by retuning
+ * NL_SKIP or NL_PROCEED (dangerous) */
+ else if (hdr->nlmsg_type == NLMSG_OVERRUN) {
+ if (cb->cb_set[NL_CB_OVERRUN])
+ NL_CB_CALL(cb, NL_CB_OVERRUN, msg);
+ else {
+ err = -NLE_MSG_OVERFLOW;
+ goto out;
+ }
+ }
+
+ /* Message carries a nlmsgerr */
+ else if (hdr->nlmsg_type == NLMSG_ERROR) {
+ struct nlmsgerr *e = nlmsg_data(hdr);
+
+ if (hdr->nlmsg_len < nlmsg_msg_size(sizeof(*e))) {
+ /* Truncated error message, the default action
+ * is to stop parsing. The user may overrule
+ * this action by returning NL_SKIP or
+ * NL_PROCEED (dangerous) */
+ if (cb->cb_set[NL_CB_INVALID])
+ NL_CB_CALL(cb, NL_CB_INVALID, msg);
+ else {
+ err = -NLE_MSG_TRUNC;
+ goto out;
+ }
+ } else if (e->error) {
+ /* Error message reported back from kernel. */
+ if (cb->cb_err) {
+ err = cb->cb_err(&nla, e,
+ cb->cb_err_arg);
+ if (err < 0)
+ goto out;
+ else if (err == NL_SKIP)
+ goto skip;
+ else if (err == NL_STOP) {
+ err = -nl_syserr2nlerr(e->error);
+ goto out;
+ }
+ } else {
+ err = -nl_syserr2nlerr(e->error);
+ goto out;
+ }
+ } else if (cb->cb_set[NL_CB_ACK])
+ NL_CB_CALL(cb, NL_CB_ACK, msg);
+ } else {
+ /* Valid message (not checking for MULTIPART bit to
+ * get along with broken kernels. NL_SKIP has no
+ * effect on this. */
+ if (cb->cb_set[NL_CB_VALID])
+ NL_CB_CALL(cb, NL_CB_VALID, msg);
+ }
+skip:
+ err = 0;
+ hdr = nlmsg_next(hdr, &n);
+ }
+
+ nlmsg_free(msg);
+ free(buf);
+ free(creds);
+ buf = NULL;
+ msg = NULL;
+ creds = NULL;
+
+ if (multipart) {
+ /* Multipart message not yet complete, continue reading */
+ goto continue_reading;
+ }
+stop:
+ err = 0;
+out:
+ nlmsg_free(msg);
+ free(buf);
+ free(creds);
+
+ return err;
+}
+
+/**
+ * Receive a set of messages from a netlink socket.
+ * @arg sk Netlink socket.
+ * @arg cb set of callbacks to control behaviour.
+ *
+ * Repeatedly calls nl_recv() or the respective replacement if provided
+ * by the application (see nl_cb_overwrite_recv()) and parses the
+ * received data as netlink messages. Stops reading if one of the
+ * callbacks returns NL_STOP or nl_recv returns either 0 or a negative error code.
+ *
+ * A non-blocking sockets causes the function to return immediately if
+ * no data is available.
+ *
+ * @return 0 on success or a negative error code from nl_recv().
+ */
+int nl_recvmsgs(struct nl_sock *sk, struct nl_cb *cb)
+{
+ if (cb->cb_recvmsgs_ow)
+ return cb->cb_recvmsgs_ow(sk, cb);
+ else
+ return recvmsgs(sk, cb);
+}
+
+
+static int ack_wait_handler(struct nl_msg *msg, void *arg)
+{
+ return NL_STOP;
+}
+
+/**
+ * Wait for ACK.
+ * @arg sk Netlink socket.
+ * @pre The netlink socket must be in blocking state.
+ *
+ * Waits until an ACK is received for the latest not yet acknowledged
+ * netlink message.
+ */
+int nl_wait_for_ack(struct nl_sock *sk)
+{
+ int err;
+ struct nl_cb *cb;
+
+ cb = nl_cb_clone(sk->s_cb);
+ if (cb == NULL)
+ return -NLE_NOMEM;
+
+ nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, NULL);
+ err = nl_recvmsgs(sk, cb);
+ nl_cb_put(cb);
+
+ return err;
+}
+
+/** @} */
+
+/** @} */
diff --git a/package/libnl-tiny/src/object.c b/package/libnl-tiny/src/object.c
new file mode 100644
index 000000000..f91555137
--- /dev/null
+++ b/package/libnl-tiny/src/object.c
@@ -0,0 +1,279 @@
+/*
+ * lib/object.c Generic Cacheable Object
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+/**
+ * @ingroup cache
+ * @defgroup object Object
+ * @{
+ */
+
+#include <netlink-local.h>
+#include <netlink/netlink.h>
+#include <netlink/cache.h>
+#include <netlink/object.h>
+#include <netlink/utils.h>
+
+static inline struct nl_object_ops *obj_ops(struct nl_object *obj)
+{
+ if (!obj->ce_ops)
+ BUG();
+
+ return obj->ce_ops;
+}
+
+/**
+ * @name Object Creation/Deletion
+ * @{
+ */
+
+/**
+ * Allocate a new object of kind specified by the operations handle
+ * @arg ops cache operations handle
+ * @return The new object or NULL
+ */
+struct nl_object *nl_object_alloc(struct nl_object_ops *ops)
+{
+ struct nl_object *new;
+
+ if (ops->oo_size < sizeof(*new))
+ BUG();
+
+ new = calloc(1, ops->oo_size);
+ if (!new)
+ return NULL;
+
+ new->ce_refcnt = 1;
+ nl_init_list_head(&new->ce_list);
+
+ new->ce_ops = ops;
+ if (ops->oo_constructor)
+ ops->oo_constructor(new);
+
+ NL_DBG(4, "Allocated new object %p\n", new);
+
+ return new;
+}
+
+#ifdef disabled
+/**
+ * Allocate a new object of kind specified by the name
+ * @arg kind name of object type
+ * @return The new object or nULL
+ */
+int nl_object_alloc_name(const char *kind, struct nl_object **result)
+{
+ struct nl_cache_ops *ops;
+
+ ops = nl_cache_ops_lookup(kind);
+ if (!ops)
+ return -NLE_OPNOTSUPP;
+
+ if (!(*result = nl_object_alloc(ops->co_obj_ops)))
+ return -NLE_NOMEM;
+
+ return 0;
+}
+#endif
+
+struct nl_derived_object {
+ NLHDR_COMMON
+ char data;
+};
+
+/**
+ * Allocate a new object and copy all data from an existing object
+ * @arg obj object to inherite data from
+ * @return The new object or NULL.
+ */
+struct nl_object *nl_object_clone(struct nl_object *obj)
+{
+ struct nl_object *new;
+ struct nl_object_ops *ops = obj_ops(obj);
+ int doff = offsetof(struct nl_derived_object, data);
+ int size;
+
+ new = nl_object_alloc(ops);
+ if (!new)
+ return NULL;
+
+ size = ops->oo_size - doff;
+ if (size < 0)
+ BUG();
+
+ new->ce_ops = obj->ce_ops;
+ new->ce_msgtype = obj->ce_msgtype;
+
+ if (size)
+ memcpy((void *)new + doff, (void *)obj + doff, size);
+
+ if (ops->oo_clone) {
+ if (ops->oo_clone(new, obj) < 0) {
+ nl_object_free(new);
+ return NULL;
+ }
+ } else if (size && ops->oo_free_data)
+ BUG();
+
+ return new;
+}
+
+/**
+ * Free a cacheable object
+ * @arg obj object to free
+ *
+ * @return 0 or a negative error code.
+ */
+void nl_object_free(struct nl_object *obj)
+{
+ struct nl_object_ops *ops = obj_ops(obj);
+
+ if (obj->ce_refcnt > 0)
+ NL_DBG(1, "Warning: Freeing object in use...\n");
+
+ if (obj->ce_cache)
+ nl_cache_remove(obj);
+
+ if (ops->oo_free_data)
+ ops->oo_free_data(obj);
+
+ free(obj);
+
+ NL_DBG(4, "Freed object %p\n", obj);
+}
+
+/** @} */
+
+/**
+ * @name Reference Management
+ * @{
+ */
+
+/** @} */
+
+/**
+ * @name Utillities
+ * @{
+ */
+
+#ifdef disabled
+/**
+ * Dump this object according to the specified parameters
+ * @arg obj object to dump
+ * @arg params dumping parameters
+ */
+void nl_object_dump(struct nl_object *obj, struct nl_dump_params *params)
+{
+ dump_from_ops(obj, params);
+}
+
+/**
+ * Check if the identifiers of two objects are identical
+ * @arg a an object
+ * @arg b another object of same type
+ *
+ * @return true if both objects have equal identifiers, otherwise false.
+ */
+int nl_object_identical(struct nl_object *a, struct nl_object *b)
+{
+ struct nl_object_ops *ops = obj_ops(a);
+ int req_attrs;
+
+ /* Both objects must be of same type */
+ if (ops != obj_ops(b))
+ return 0;
+
+ req_attrs = ops->oo_id_attrs;
+
+ /* Both objects must provide all required attributes to uniquely
+ * identify an object */
+ if ((a->ce_mask & req_attrs) != req_attrs ||
+ (b->ce_mask & req_attrs) != req_attrs)
+ return 0;
+
+ /* Can't judge unless we can compare */
+ if (ops->oo_compare == NULL)
+ return 0;
+
+ return !(ops->oo_compare(a, b, req_attrs, 0));
+}
+
+/**
+ * Compute bitmask representing difference in attribute values
+ * @arg a an object
+ * @arg b another object of same type
+ *
+ * The bitmask returned is specific to an object type, each bit set represents
+ * an attribute which mismatches in either of the two objects. Unavailability
+ * of an attribute in one object and presence in the other is regarded a
+ * mismatch as well.
+ *
+ * @return Bitmask describing differences or 0 if they are completely identical.
+ */
+uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b)
+{
+ struct nl_object_ops *ops = obj_ops(a);
+
+ if (ops != obj_ops(b) || ops->oo_compare == NULL)
+ return UINT_MAX;
+
+ return ops->oo_compare(a, b, ~0, 0);
+}
+
+/**
+ * Match a filter against an object
+ * @arg obj object to check
+ * @arg filter object of same type acting as filter
+ *
+ * @return 1 if the object matches the filter or 0
+ * if no filter procedure is available or if the
+ * filter does not match.
+ */
+int nl_object_match_filter(struct nl_object *obj, struct nl_object *filter)
+{
+ struct nl_object_ops *ops = obj_ops(obj);
+
+ if (ops != obj_ops(filter) || ops->oo_compare == NULL)
+ return 0;
+
+ return !(ops->oo_compare(obj, filter, filter->ce_mask,
+ LOOSE_COMPARISON));
+}
+
+/**
+ * Convert bitmask of attributes to a character string
+ * @arg obj object of same type as attribute bitmask
+ * @arg attrs bitmask of attribute types
+ * @arg buf destination buffer
+ * @arg len length of destination buffer
+ *
+ * Converts the bitmask of attribute types into a list of attribute
+ * names separated by comas.
+ *
+ * @return destination buffer.
+ */
+char *nl_object_attrs2str(struct nl_object *obj, uint32_t attrs,
+ char *buf, size_t len)
+{
+ struct nl_object_ops *ops = obj_ops(obj);
+
+ if (ops->oo_attrs2str != NULL)
+ return ops->oo_attrs2str(attrs, buf, len);
+ else {
+ memset(buf, 0, len);
+ return buf;
+ }
+}
+
+#endif
+
+/** @} */
+
+/** @} */
diff --git a/package/libnl-tiny/src/socket.c b/package/libnl-tiny/src/socket.c
new file mode 100644
index 000000000..1429825e6
--- /dev/null
+++ b/package/libnl-tiny/src/socket.c
@@ -0,0 +1,406 @@
+/*
+ * lib/socket.c Netlink Socket
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ */
+
+/**
+ * @ingroup core
+ * @defgroup socket Socket
+ * @{
+ */
+
+#include <netlink-local.h>
+#include <netlink/netlink.h>
+#include <netlink/utils.h>
+#include <netlink/handlers.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+
+static uint32_t used_ports_map[32];
+
+static uint32_t generate_local_port(void)
+{
+ int i, n;
+ uint32_t pid = getpid() & 0x3FFFFF;
+
+ for (i = 0; i < 32; i++) {
+ if (used_ports_map[i] == 0xFFFFFFFF)
+ continue;
+
+ for (n = 0; n < 32; n++) {
+ if (1UL & (used_ports_map[i] >> n))
+ continue;
+
+ used_ports_map[i] |= (1UL << n);
+ n += (i * 32);
+
+ /* PID_MAX_LIMIT is currently at 2^22, leaving 10 bit
+ * to, i.e. 1024 unique ports per application. */
+ return pid + (n << 22);
+
+ }
+ }
+
+ /* Out of sockets in our own PID namespace, what to do? FIXME */
+ return UINT_MAX;
+}
+
+static void release_local_port(uint32_t port)
+{
+ int nr;
+
+ if (port == UINT_MAX)
+ return;
+
+ nr = port >> 22;
+ used_ports_map[nr / 32] &= ~(1 << nr % 32);
+}
+
+/**
+ * @name Allocation
+ * @{
+ */
+
+static struct nl_sock *__alloc_socket(struct nl_cb *cb)
+{
+ struct nl_sock *sk;
+
+ sk = calloc(1, sizeof(*sk));
+ if (!sk)
+ return NULL;
+
+ sk->s_fd = -1;
+ sk->s_cb = cb;
+ sk->s_local.nl_family = AF_NETLINK;
+ sk->s_peer.nl_family = AF_NETLINK;
+ sk->s_seq_expect = sk->s_seq_next = time(0);
+ sk->s_local.nl_pid = generate_local_port();
+ if (sk->s_local.nl_pid == UINT_MAX) {
+ nl_socket_free(sk);
+ return NULL;
+ }
+
+ return sk;
+}
+
+/**
+ * Allocate new netlink socket
+ *
+ * @return Newly allocated netlink socket or NULL.
+ */
+struct nl_sock *nl_socket_alloc(void)
+{
+ struct nl_cb *cb;
+
+ cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!cb)
+ return NULL;
+
+ return __alloc_socket(cb);
+}
+
+/**
+ * Allocate new socket with custom callbacks
+ * @arg cb Callback handler
+ *
+ * The reference to the callback handler is taken into account
+ * automatically, it is released again upon calling nl_socket_free().
+ *
+ *@return Newly allocted socket handle or NULL.
+ */
+struct nl_sock *nl_socket_alloc_cb(struct nl_cb *cb)
+{
+ if (cb == NULL)
+ BUG();
+
+ return __alloc_socket(nl_cb_get(cb));
+}
+
+/**
+ * Free a netlink socket.
+ * @arg sk Netlink socket.
+ */
+void nl_socket_free(struct nl_sock *sk)
+{
+ if (!sk)
+ return;
+
+ if (sk->s_fd >= 0)
+ close(sk->s_fd);
+
+ if (!(sk->s_flags & NL_OWN_PORT))
+ release_local_port(sk->s_local.nl_pid);
+
+ nl_cb_put(sk->s_cb);
+ free(sk);
+}
+
+/** @} */
+
+/**
+ * @name Sequence Numbers
+ * @{
+ */
+
+static int noop_seq_check(struct nl_msg *msg, void *arg)
+{
+ return NL_OK;
+}
+
+
+/**
+ * Disable sequence number checking.
+ * @arg sk Netlink socket.
+ *
+ * Disables checking of sequence numbers on the netlink socket This is
+ * required to allow messages to be processed which were not requested by
+ * a preceding request message, e.g. netlink events.
+ *
+ * @note This function modifies the NL_CB_SEQ_CHECK configuration in
+ * the callback handle associated with the socket.
+ */
+void nl_socket_disable_seq_check(struct nl_sock *sk)
+{
+ nl_cb_set(sk->s_cb, NL_CB_SEQ_CHECK,
+ NL_CB_CUSTOM, noop_seq_check, NULL);
+}
+
+/** @} */
+
+/**
+ * Set local port of socket
+ * @arg sk Netlink socket.
+ * @arg port Local port identifier
+ *
+ * Assigns a local port identifier to the socket. If port is 0
+ * a unique port identifier will be generated automatically.
+ */
+void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port)
+{
+ if (port == 0) {
+ port = generate_local_port();
+ sk->s_flags &= ~NL_OWN_PORT;
+ } else {
+ if (!(sk->s_flags & NL_OWN_PORT))
+ release_local_port(sk->s_local.nl_pid);
+ sk->s_flags |= NL_OWN_PORT;
+ }
+
+ sk->s_local.nl_pid = port;
+}
+
+/** @} */
+
+/**
+ * @name Group Subscriptions
+ * @{
+ */
+
+/**
+ * Join groups
+ * @arg sk Netlink socket
+ * @arg group Group identifier
+ *
+ * Joins the specified groups using the modern socket option which
+ * is available since kernel version 2.6.14. It allows joining an
+ * almost arbitary number of groups without limitation. The list
+ * of groups has to be terminated by 0 (%NFNLGRP_NONE).
+ *
+ * Make sure to use the correct group definitions as the older
+ * bitmask definitions for nl_join_groups() are likely to still
+ * be present for backward compatibility reasons.
+ *
+ * @return 0 on sucess or a negative error code.
+ */
+int nl_socket_add_memberships(struct nl_sock *sk, int group, ...)
+{
+ int err;
+ va_list ap;
+
+ if (sk->s_fd == -1)
+ return -NLE_BAD_SOCK;
+
+ va_start(ap, group);
+
+ while (group != 0) {
+ if (group < 0)
+ return -NLE_INVAL;
+
+ err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
+ &group, sizeof(group));
+ if (err < 0)
+ return -nl_syserr2nlerr(errno);
+
+ group = va_arg(ap, int);
+ }
+
+ va_end(ap);
+
+ return 0;
+}
+
+/**
+ * Leave groups
+ * @arg sk Netlink socket
+ * @arg group Group identifier
+ *
+ * Leaves the specified groups using the modern socket option
+ * which is available since kernel version 2.6.14. The list of groups
+ * has to terminated by 0 (%NFNLGRP_NONE).
+ *
+ * @see nl_socket_add_membership
+ * @return 0 on success or a negative error code.
+ */
+int nl_socket_drop_memberships(struct nl_sock *sk, int group, ...)
+{
+ int err;
+ va_list ap;
+
+ if (sk->s_fd == -1)
+ return -NLE_BAD_SOCK;
+
+ va_start(ap, group);
+
+ while (group != 0) {
+ if (group < 0)
+ return -NLE_INVAL;
+
+ err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
+ &group, sizeof(group));
+ if (err < 0)
+ return -nl_syserr2nlerr(errno);
+
+ group = va_arg(ap, int);
+ }
+
+ va_end(ap);
+
+ return 0;
+}
+
+
+/** @} */
+
+/**
+ * Set file descriptor of socket to non-blocking state
+ * @arg sk Netlink socket.
+ *
+ * @return 0 on success or a negative error code.
+ */
+int nl_socket_set_nonblocking(struct nl_sock *sk)
+{
+ if (sk->s_fd == -1)
+ return -NLE_BAD_SOCK;
+
+ if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0)
+ return -nl_syserr2nlerr(errno);
+
+ return 0;
+}
+
+/** @} */
+
+/**
+ * @name Utilities
+ * @{
+ */
+
+/**
+ * Set socket buffer size of netlink socket.
+ * @arg sk Netlink socket.
+ * @arg rxbuf New receive socket buffer size in bytes.
+ * @arg txbuf New transmit socket buffer size in bytes.
+ *
+ * Sets the socket buffer size of a netlink socket to the specified
+ * values \c rxbuf and \c txbuf. Providing a value of \c 0 assumes a
+ * good default value.
+ *
+ * @note It is not required to call this function prior to nl_connect().
+ * @return 0 on sucess or a negative error code.
+ */
+int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf)
+{
+ int err;
+
+ if (rxbuf <= 0)
+ rxbuf = 32768;
+
+ if (txbuf <= 0)
+ txbuf = 32768;
+
+ if (sk->s_fd == -1)
+ return -NLE_BAD_SOCK;
+
+ err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF,
+ &txbuf, sizeof(txbuf));
+ if (err < 0)
+ return -nl_syserr2nlerr(errno);
+
+ err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF,
+ &rxbuf, sizeof(rxbuf));
+ if (err < 0)
+ return -nl_syserr2nlerr(errno);
+
+ sk->s_flags |= NL_SOCK_BUFSIZE_SET;
+
+ return 0;
+}
+
+/**
+ * Enable/disable credential passing on netlink socket.
+ * @arg sk Netlink socket.
+ * @arg state New state (0 - disabled, 1 - enabled)
+ *
+ * @return 0 on success or a negative error code
+ */
+int nl_socket_set_passcred(struct nl_sock *sk, int state)
+{
+ int err;
+
+ if (sk->s_fd == -1)
+ return -NLE_BAD_SOCK;
+
+ err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED,
+ &state, sizeof(state));
+ if (err < 0)
+ return -nl_syserr2nlerr(errno);
+
+ if (state)
+ sk->s_flags |= NL_SOCK_PASSCRED;
+ else
+ sk->s_flags &= ~NL_SOCK_PASSCRED;
+
+ return 0;
+}
+
+/**
+ * Enable/disable receival of additional packet information
+ * @arg sk Netlink socket.
+ * @arg state New state (0 - disabled, 1 - enabled)
+ *
+ * @return 0 on success or a negative error code
+ */
+int nl_socket_recv_pktinfo(struct nl_sock *sk, int state)
+{
+ int err;
+
+ if (sk->s_fd == -1)
+ return -NLE_BAD_SOCK;
+
+ err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_PKTINFO,
+ &state, sizeof(state));
+ if (err < 0)
+ return -nl_syserr2nlerr(errno);
+
+ return 0;
+}
+
+/** @} */
+
+/** @} */
diff --git a/package/libnl-tiny/src/unl.c b/package/libnl-tiny/src/unl.c
new file mode 100644
index 000000000..b38dab839
--- /dev/null
+++ b/package/libnl-tiny/src/unl.c
@@ -0,0 +1,290 @@
+#define _GNU_SOURCE
+#include <netlink/netlink.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/genl/family.h>
+#include <sys/types.h>
+#include <net/if.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <linux/nl80211.h>
+
+#include "unl.h"
+
+static int unl_init(struct unl *unl)
+{
+ unl->sock = nl_socket_alloc();
+ if (!unl->sock)
+ return -1;
+
+ return 0;
+}
+
+int unl_genl_init(struct unl *unl, const char *family)
+{
+ memset(unl, 0, sizeof(*unl));
+
+ if (unl_init(unl))
+ goto error_out;
+
+ unl->hdrlen = NLMSG_ALIGN(sizeof(struct genlmsghdr));
+ unl->family_name = strdup(family);
+ if (!unl->family_name)
+ goto error;
+
+ if (genl_connect(unl->sock))
+ goto error;
+
+ if (genl_ctrl_alloc_cache(unl->sock, &unl->cache))
+ goto error;
+
+ unl->family = genl_ctrl_search_by_name(unl->cache, family);
+ if (!unl->family)
+ goto error;
+
+ return 0;
+
+error:
+ unl_free(unl);
+error_out:
+ return -1;
+}
+
+void unl_free(struct unl *unl)
+{
+ if (unl->family_name)
+ free(unl->family_name);
+
+ if (unl->sock)
+ nl_socket_free(unl->sock);
+
+ if (unl->cache)
+ nl_cache_free(unl->cache);
+
+ memset(unl, 0, sizeof(*unl));
+}
+
+static int
+ack_handler(struct nl_msg *msg, void *arg)
+{
+ int *err = arg;
+ *err = 0;
+ return NL_STOP;
+}
+
+static int
+finish_handler(struct nl_msg *msg, void *arg)
+{
+ int *err = arg;
+ *err = 0;
+ return NL_SKIP;
+}
+
+static int
+error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
+{
+ int *ret = arg;
+ *ret = err->error;
+ return NL_SKIP;
+}
+
+struct nl_msg *unl_genl_msg(struct unl *unl, int cmd, bool dump)
+{
+ struct nl_msg *msg;
+ int flags = 0;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ goto out;
+
+ if (dump)
+ flags |= NLM_F_DUMP;
+
+ genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ,
+ genl_family_get_id(unl->family), 0, flags, cmd, 0);
+
+out:
+ return msg;
+}
+
+int unl_genl_request(struct unl *unl, struct nl_msg *msg, unl_cb handler, void *arg)
+{
+ struct nlmsghdr *nlh;
+ struct nl_cb *cb;
+ int err;
+
+ cb = nl_cb_alloc(NL_CB_CUSTOM);
+ nlh = nlmsg_hdr(msg);
+
+ err = nl_send_auto_complete(unl->sock, msg);
+ if (err < 0)
+ goto out;
+
+ err = 1;
+ nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
+ nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
+ nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
+ if (handler)
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, handler, arg);
+
+ while (err > 0)
+ nl_recvmsgs(unl->sock, cb);
+
+out:
+ nlmsg_free(msg);
+ nl_cb_put(cb);
+ return err;
+}
+
+static int request_single_cb(struct nl_msg *msg, void *arg)
+{
+ struct nl_msg **dest = arg;
+
+ if (!*dest) {
+ nlmsg_get(msg);
+ *dest = msg;
+ }
+ return NL_SKIP;
+}
+
+int unl_genl_request_single(struct unl *unl, struct nl_msg *msg, struct nl_msg **dest)
+{
+ *dest = NULL;
+ return unl_genl_request(unl, msg, request_single_cb, dest);
+}
+
+static int no_seq_check(struct nl_msg *msg, void *arg)
+{
+ return NL_OK;
+}
+
+void unl_genl_loop(struct unl *unl, unl_cb handler, void *arg)
+{
+ struct nl_cb *cb;
+
+ cb = nl_cb_alloc(NL_CB_CUSTOM);
+ unl->loop_done = false;
+ nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, handler, arg);
+
+ while (!unl->loop_done)
+ nl_recvmsgs(unl->sock, cb);
+
+ nl_cb_put(cb);
+}
+
+int unl_genl_multicast_id(struct unl *unl, const char *name)
+{
+ struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX + 1];
+ struct nlattr *groups, *group;
+ struct nl_msg *msg;
+ int ctrlid;
+ int ret = -1;
+ int rem;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -1;
+
+ ctrlid = genl_ctrl_resolve(unl->sock, "nlctrl");
+ genlmsg_put(msg, 0, 0, ctrlid, 0, 0, CTRL_CMD_GETFAMILY, 0);
+ NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, unl->family_name);
+ unl_genl_request_single(unl, msg, &msg);
+ if (!msg)
+ return -1;
+
+ groups = unl_find_attr(unl, msg, CTRL_ATTR_MCAST_GROUPS);
+ if (!groups)
+ goto nla_put_failure;
+
+ nla_for_each_nested(group, groups, rem) {
+ const char *gn;
+
+ nla_parse(tb, CTRL_ATTR_MCAST_GRP_MAX, nla_data(group),
+ nla_len(group), NULL);
+
+ if (!tb[CTRL_ATTR_MCAST_GRP_NAME] ||
+ !tb[CTRL_ATTR_MCAST_GRP_ID])
+ continue;
+
+ gn = nla_data(tb[CTRL_ATTR_MCAST_GRP_NAME]);
+ if (strcmp(gn, name) != 0)
+ continue;
+
+ ret = nla_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID]);
+ break;
+ }
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return ret;
+}
+
+int unl_genl_subscribe(struct unl *unl, const char *name)
+{
+ int mcid;
+
+ mcid = unl_genl_multicast_id(unl, name);
+ if (mcid < 0)
+ return mcid;
+
+ return nl_socket_add_membership(unl->sock, mcid);
+}
+
+int unl_genl_unsubscribe(struct unl *unl, const char *name)
+{
+ int mcid;
+
+ mcid = unl_genl_multicast_id(unl, name);
+ if (mcid < 0)
+ return mcid;
+
+ return nl_socket_drop_membership(unl->sock, mcid);
+}
+
+int unl_nl80211_phy_lookup(const char *name)
+{
+ char buf[32];
+ int fd, pos;
+
+ snprintf(buf, sizeof(buf), "/sys/class/ieee80211/%s/index", name);
+
+ fd = open(buf, O_RDONLY);
+ if (fd < 0)
+ return -1;
+ pos = read(fd, buf, sizeof(buf) - 1);
+ if (pos < 0) {
+ close(fd);
+ return -1;
+ }
+ buf[pos] = '\0';
+ close(fd);
+ return atoi(buf);
+}
+
+int unl_nl80211_wdev_to_phy(struct unl *unl, int wdev)
+{
+ struct nl_msg *msg;
+ struct nlattr *attr;
+ int ret = -1;
+
+ msg = unl_genl_msg(unl, NL80211_CMD_GET_INTERFACE, false);
+ if (!msg)
+ return -1;
+
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wdev);
+ if (unl_genl_request_single(unl, msg, &msg) < 0)
+ return -1;
+
+ attr = unl_find_attr(unl, msg, NL80211_ATTR_WIPHY);
+ if (!attr)
+ goto out;
+
+ ret = nla_get_u32(attr);
+out:
+nla_put_failure:
+ nlmsg_free(msg);
+ return ret;
+}
+
+
diff --git a/package/libnl/Makefile b/package/libnl/Makefile
new file mode 100644
index 000000000..13756995f
--- /dev/null
+++ b/package/libnl/Makefile
@@ -0,0 +1,56 @@
+#
+# Copyright (C) 2006-2009 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=libnl
+PKG_VERSION:=2.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://www.infradead.org/~tgr/libnl/files/
+PKG_MD5SUM:=6aaf1e9802a17a7d702bb0638044ffa7
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/libnl
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=netlink socket library
+ URL:=http://people.suug.ch/~tgr/libnl/
+endef
+
+define Package/libnl/description
+ This package contains a library for applications dealing with netlink sockets
+endef
+
+TARGET_CFLAGS += -ffunction-sections $(FPIC)
+
+define Build/Compile
+ $(call Build/Compile/Default)
+ make -C $(PKG_BUILD_DIR) \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ install
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)
+ $(CP) $(PKG_INSTALL_DIR)/* $(1)/
+ mkdir -p $(1)/usr/include/libnl
+ $(CP) $(PKG_BUILD_DIR)/include/linux $(1)/usr/include/libnl/
+endef
+
+define Package/libnl/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libnl-route.so.* $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libnl-genl.so.* $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libnl-nf.so.* $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libnl-route.so.* $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libnl.so.* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,libnl))
diff --git a/package/libnl/patches/110-offsetof.patch b/package/libnl/patches/110-offsetof.patch
new file mode 100644
index 000000000..fa944a9c4
--- /dev/null
+++ b/package/libnl/patches/110-offsetof.patch
@@ -0,0 +1,12 @@
+--- a/include/netlink-local.h
++++ b/include/netlink-local.h
+@@ -337,7 +337,9 @@ static inline int nl_cb_call(struct nl_c
+ }
+
+ #define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0]))
++#ifndef offsetof
+ #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
++#endif
+
+ #define __init __attribute__ ((constructor))
+ #define __exit __attribute__ ((destructor))
diff --git a/package/libnl/patches/160-update_includes_for_iw.patch b/package/libnl/patches/160-update_includes_for_iw.patch
new file mode 100644
index 000000000..ad36dab4b
--- /dev/null
+++ b/package/libnl/patches/160-update_includes_for_iw.patch
@@ -0,0 +1,34 @@
+--- a/include/linux/genetlink.h
++++ b/include/linux/genetlink.h
+@@ -39,6 +39,9 @@ enum {
+ CTRL_CMD_NEWOPS,
+ CTRL_CMD_DELOPS,
+ CTRL_CMD_GETOPS,
++ CTRL_CMD_NEWMCAST_GRP,
++ CTRL_CMD_DELMCAST_GRP,
++ CTRL_CMD_GETMCAST_GRP, /* unused */
+ __CTRL_CMD_MAX,
+ };
+
+@@ -52,6 +55,7 @@ enum {
+ CTRL_ATTR_HDRSIZE,
+ CTRL_ATTR_MAXATTR,
+ CTRL_ATTR_OPS,
++ CTRL_ATTR_MCAST_GROUPS,
+ __CTRL_ATTR_MAX,
+ };
+
+@@ -66,4 +70,13 @@ enum {
+
+ #define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1)
+
++enum {
++ CTRL_ATTR_MCAST_GRP_UNSPEC,
++ CTRL_ATTR_MCAST_GRP_NAME,
++ CTRL_ATTR_MCAST_GRP_ID,
++ __CTRL_ATTR_MCAST_GRP_MAX,
++};
++
++#define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1)
++
+ #endif /* __LINUX_GENERIC_NETLINK_H */
diff --git a/package/libpcap/Config.in b/package/libpcap/Config.in
new file mode 100644
index 000000000..ef32c1bc0
--- /dev/null
+++ b/package/libpcap/Config.in
@@ -0,0 +1,15 @@
+menu "Configuration"
+ depends PACKAGE_libpcap
+
+config PCAP_HAS_USB
+ bool "Include USB support"
+ depends PACKAGE_kmod-usb-core
+ default n
+
+config PCAP_HAS_BT
+ bool "Include bluetooth support"
+ depends PACKAGE_kmod-bluetooth
+ depends BROKEN
+ default n
+
+endmenu
diff --git a/package/libpcap/Makefile b/package/libpcap/Makefile
new file mode 100644
index 000000000..ba6549856
--- /dev/null
+++ b/package/libpcap/Makefile
@@ -0,0 +1,83 @@
+#
+# Copyright (C) 2006-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=libpcap
+PKG_VERSION:=1.1.1
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://www.tcpdump.org/release/
+PKG_MD5SUM:=1bca27d206970badae248cfa471bbb47
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+define Package/libpcap
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=Low-level packet capture library
+ URL:=http://www.tcpdump.org/
+ MENU:=1
+endef
+
+define Package/libpcap/description
+This package contains a system-independent library for user-level network packet
+capture.
+endef
+
+define Package/libpcap/config
+ source "$(SOURCE)/Config.in"
+endef
+
+TARGET_CFLAGS += \
+ -ffunction-sections \
+ -fdata-sections
+
+CONFIGURE_VARS += \
+ ac_cv_linux_vers=$(LINUX_VERSION)
+
+CONFIGURE_ARGS += \
+ --enable-shared \
+ --enable-static \
+ --disable-yydebug \
+ --enable-ipv6 \
+ --with-build-cc="$(HOSTCC)" \
+ --with-pcap=linux \
+ --without-septel \
+ --without-dag \
+ --without-libnl
+
+MAKE_FLAGS += \
+ CCOPT="$(TARGET_CFLAGS) -I$(BUILD_DIR)/linux/include"
+
+define Build/Configure
+ $(call Build/Configure/Default)
+ $(if $(CONFIG_PCAP_HAS_USB),,$(SED) '/^#define PCAP_SUPPORT_USB/D' $(PKG_BUILD_DIR)/config.h)
+ $(if $(CONFIG_PCAP_HAS_USB),,$(SED) 's/pcap-usb-linux.c *//' $(PKG_BUILD_DIR)/Makefile)
+ $(if $(CONFIG_PCAP_HAS_BT),,$(SED) '/^#define PCAP_SUPPORT_BT/D' $(PKG_BUILD_DIR)/config.h)
+ $(if $(CONFIG_PCAP_HAS_BT),,$(SED) 's/pcap-bt-linux.c *//' $(PKG_BUILD_DIR)/Makefile)
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/pcap* $(1)/usr/include/
+
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libpcap.{a,so*} $(1)/usr/lib/
+endef
+
+define Package/libpcap/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libpcap.so* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,libpcap))
diff --git a/package/libpcap/patches/100-debian_shared_lib.patch b/package/libpcap/patches/100-debian_shared_lib.patch
new file mode 100644
index 000000000..5be33b0c6
--- /dev/null
+++ b/package/libpcap/patches/100-debian_shared_lib.patch
@@ -0,0 +1,178 @@
+Debian-specific modifications to the upstream Makefile.in to
+build a shared library.
+---
+ Makefile.in | 45 ++++++++++++++++++++++++++++++++++++++++++---
+ configure | 2 +-
+ configure.in | 2 +-
+ 3 files changed, 44 insertions(+), 5 deletions(-)
+
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -40,6 +40,14 @@ mandir = @mandir@
+ srcdir = @srcdir@
+ VPATH = @srcdir@
+
++# some defines for shared library compilation
++MAJ=1.1
++LIBVERSION=$(MAJ).1
++LIBNAME=pcap
++LIBRARY=lib$(LIBNAME).a
++SOLIBRARY=lib$(LIBNAME).so
++SHAREDLIB=$(SOLIBRARY).$(LIBVERSION)
++
+ #
+ # You shouldn't need to edit anything below.
+ #
+@@ -59,6 +67,7 @@ PROG=libpcap
+
+ # Standard CFLAGS
+ CFLAGS = $(CCOPT) $(INCLS) $(DEFS)
++CFLAGS_SHARED = -shared -Wl,-soname,$(SOLIBRARY).$(MAJ)
+
+ INSTALL = @INSTALL@
+ INSTALL_PROGRAM = @INSTALL_PROGRAM@
+@@ -78,7 +87,11 @@ YACC = @V_YACC@
+ # problem if you don't own the file but can write to the directory.
+ .c.o:
+ @rm -f $@
+- $(CC) $(CFLAGS) -c $(srcdir)/$*.c
++ $(CC) $(CFLAGS) -c -o $@ $(srcdir)/$*.c
++
++%_pic.o: %.c
++ @rm -f $@
++ $(CC) -fPIC $(CFLAGS) -c -o $@ $(srcdir)/$*.c
+
+ PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ @CAN_SRC@
+ FSRC = fad-@V_FINDALLDEVS@.c
+@@ -94,6 +107,7 @@ SRC = $(PSRC) $(FSRC) $(CSRC) $(SSRC) $(
+ # We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot
+ # hack the extra indirection
+ OBJ = $(PSRC:.c=.o) $(FSRC:.c=.o) $(CSRC:.c=.o) $(SSRC:.c=.o) $(GENSRC:.c=.o) $(LIBOBJS)
++OBJ_PIC = $(PSRC:.c=_pic.o) $(FSRC:.c=_pic.o) $(CSRC:.c=_pic.o) $(SSRC:.c=_pic.o) $(GENSRC:.c=_pic.o)
+ PUBHDR = \
+ pcap.h \
+ pcap-bpf.h \
+@@ -131,7 +145,7 @@ TAGFILES = \
+
+ CLEANFILES = $(OBJ) libpcap.* filtertest findalldevstest selpolltest \
+ opentest $(PROG)-`cat $(srcdir)/VERSION`.tar.gz $(GENSRC) $(GENHDR) \
+- lex.yy.c pcap-config
++ lex.yy.c pcap-config $(OBJ_PIC)
+
+ MAN1 = pcap-config.1
+
+@@ -324,21 +338,14 @@ EXTRA_DIST = \
+ Win32/Src/inet_net.c \
+ Win32/Src/inet_pton.c
+
+-all: libpcap.a shared pcap-config
++all: libpcap.a shared pcap-config $(SHAREDLIB)
+
+ libpcap.a: $(OBJ)
+ @rm -f $@
+ ar rc $@ $(OBJ) $(ADDLARCHIVEOBJS)
+ $(RANLIB) $@
+
+-shared: libpcap.$(DYEXT)
+-
+-libpcap.so: $(OBJ)
+- @rm -f $@
+- VER=`cat $(srcdir)/VERSION`; \
+- MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+- @V_SHLIB_CMD@ @V_SHLIB_OPT@ @V_SONAME_OPT@$@.$$MAJOR_VER $(LDFLAGS) \
+- -o $@.$$VER $(OBJ) $(ADDLOBJS) $(LIBS)
++shared: $(SHAREDLIB)
+
+ #
+ # The following rule succeeds, but the result is untested.
+@@ -409,6 +416,13 @@ libpcap.shareda: $(OBJ)
+ #
+ libpcap.none:
+
++$(SHAREDLIB): $(OBJ_PIC)
++ -@rm -f $@
++ -@rm -f $(SOLIBRARY) $(SOLIBRARY).$(MAJ)
++ $(CC) $(CFLAGS_SHARED) -o $(SHAREDLIB) $(OBJ_PIC) -lc
++ ln -s $(SHAREDLIB) $(SOLIBRARY).$(MAJ)
++ ln -s $(SOLIBRARY).$(MAJ) $(SOLIBRARY)
++
+ scanner.c: $(srcdir)/scanner.l
+ @rm -f $@
+ $(srcdir)/runlex.sh $(LEX) -o$@ $<
+@@ -416,6 +430,9 @@ scanner.c: $(srcdir)/scanner.l
+ scanner.o: scanner.c tokdefs.h
+ $(CC) $(CFLAGS) -c scanner.c
+
++scanner_pic.o: scanner.c tokdefs.h
++ $(CC) -fPIC $(CFLAGS) -o $@ -c scanner.c
++
+ pcap.o: version.h
+
+ tokdefs.h: grammar.c
+@@ -429,9 +446,17 @@ grammar.o: grammar.c
+ @rm -f $@
+ $(CC) $(CFLAGS) -Dyylval=pcap_lval -c grammar.c
+
++grammar_pic.o: grammar.c
++ @rm -f $@
++ $(CC) -fPIC $(CFLAGS) -Dyylval=pcap_lval -o $@ -c grammar.c
++
+ version.o: version.c
+ $(CC) $(CFLAGS) -c version.c
+
++version_pic.o: version.c
++ $(CC) -fPIC $(CFLAGS) -c version.c -o $@
++
++
+ snprintf.o: $(srcdir)/missing/snprintf.c
+ $(CC) $(CFLAGS) -o $@ -c $(srcdir)/missing/snprintf.c
+
+@@ -469,6 +494,9 @@ bpf_filter.c: $(srcdir)/bpf/net/bpf_filt
+ bpf_filter.o: bpf_filter.c
+ $(CC) $(CFLAGS) -c bpf_filter.c
+
++bpf_filter_pic.o: bpf_filter.c
++ $(CC) -fPIC $(CFLAGS) -c bpf_filter.c -o $@
++
+ #
+ # Generate the pcap-config script.
+ #
+@@ -562,14 +590,12 @@ install: install-shared install-archive
+ $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@/`echo $$i | sed 's/.manmisc.in/.@MAN_MISC_INFO@/'`; done
+
+ install-shared: install-shared-$(DYEXT)
+-install-shared-so: libpcap.so
++install-shared-so: $(SHAREDLIB)
+ [ -d $(DESTDIR)$(libdir) ] || \
+ (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+- VER=`cat $(srcdir)/VERSION`; \
+- MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+- $(INSTALL_PROGRAM) libpcap.so.$$VER $(DESTDIR)$(libdir)/libpcap.so.$$VER; \
+- ln -sf libpcap.so.$$VER $(DESTDIR)$(libdir)/libpcap.so.$$MAJOR_VER; \
+- ln -sf libpcap.so.$$MAJOR_VER $(DESTDIR)$(libdir)/libpcap.so
++ $(INSTALL_DATA) $(SHAREDLIB) $(DESTDIR)$(libdir)/
++ ln -sf $(SHAREDLIB) $(DESTDIR)$(libdir)/$(SOLIBRARY).$(MAJ)
++ ln -sf $(SOLIBRARY).$(MAJ) $(DESTDIR)$(libdir)/$(SOLIBRARY)
+ install-shared-dylib: libpcap.dylib
+ [ -d $(DESTDIR)$(libdir) ] || \
+ (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+--- a/configure
++++ b/configure
+@@ -3229,7 +3229,7 @@ _ACEOF
+ # or accepts command-line arguments like
+ # those the GNU linker accepts.
+ #
+- V_CCOPT="$V_CCOPT -fpic"
++ V_CCOPT="$V_CCOPT"
+ V_SONAME_OPT="-Wl,-soname,"
+ V_RPATH_OPT="-Wl,-rpath,"
+ ;;
+@@ -3292,7 +3292,7 @@ _ACEOF
+ #
+ # "cc" is GCC.
+ #
+- V_CCOPT="$V_CCOPT -fpic"
++ V_CCOPT="$V_CCOPT"
+ V_SHLIB_CMD="\$(CC)"
+ V_SHLIB_OPT="-shared"
+ V_SONAME_OPT="-Wl,-soname,"
diff --git a/package/libpcap/patches/102-makefile_disable_manpages.patch b/package/libpcap/patches/102-makefile_disable_manpages.patch
new file mode 100644
index 000000000..4674df51e
--- /dev/null
+++ b/package/libpcap/patches/102-makefile_disable_manpages.patch
@@ -0,0 +1,89 @@
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -532,62 +532,12 @@ install: install-shared install-archive
+ (mkdir -p $(DESTDIR)$(includedir); chmod 755 $(DESTDIR)$(includedir))
+ [ -d $(DESTDIR)$(includedir)/pcap ] || \
+ (mkdir -p $(DESTDIR)$(includedir)/pcap; chmod 755 $(DESTDIR)$(includedir)/pcap)
+- [ -d $(DESTDIR)$(mandir)/man1 ] || \
+- (mkdir -p $(DESTDIR)$(mandir)/man1; chmod 755 $(DESTDIR)$(mandir)/man1)
+- [ -d $(DESTDIR)$(mandir)/man3 ] || \
+- (mkdir -p $(DESTDIR)$(mandir)/man3; chmod 755 $(DESTDIR)$(mandir)/man3)
+- [ -d $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@ ] || \
+- (mkdir -p $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@; chmod 755 $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@)
+- [ -d $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@ ] || \
+- (mkdir -p $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@; chmod 755 $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@)
+ for i in $(PUBHDR); do \
+ $(INSTALL_DATA) $(srcdir)/$$i \
+ $(DESTDIR)$(includedir)/$$i; done
+ [ -d $(DESTDIR)$(bindir) ] || \
+ (mkdir -p $(DESTDIR)$(bindir); chmod 755 $(DESTDIR)$(bindir))
+ $(INSTALL_PROGRAM) pcap-config $(DESTDIR)$(bindir)/pcap-config
+- for i in $(MAN1); do \
+- $(INSTALL_DATA) $(srcdir)/$$i \
+- $(DESTDIR)$(mandir)/man1/$$i; done
+- for i in $(MAN3PCAP_NOEXPAND); do \
+- $(INSTALL_DATA) $(srcdir)/$$i \
+- $(DESTDIR)$(mandir)/man3/$$i; done
+- for i in $(MAN3PCAP_EXPAND:.in=); do \
+- $(INSTALL_DATA) $$i \
+- $(DESTDIR)$(mandir)/man3/$$i; done
+- rm -f $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_description.3pcap
+- ln $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_name.3pcap \
+- $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_description.3pcap
+- rm -f $(DESTDIR)$(mandir)/man3/pcap_dump_fopen.3pcap
+- ln $(DESTDIR)$(mandir)/man3/pcap_dump_open.3pcap \
+- $(DESTDIR)$(mandir)/man3/pcap_dump_fopen.3pcap
+- rm -f $(DESTDIR)$(mandir)/man3/pcap_perror.3pcap
+- ln $(DESTDIR)$(mandir)/man3/pcap_geterr.3pcap \
+- $(DESTDIR)$(mandir)/man3/pcap_perror.3pcap
+- rm -f $(DESTDIR)$(mandir)/man3/pcap_sendpacket.3pcap
+- ln $(DESTDIR)$(mandir)/man3/pcap_inject.3pcap \
+- $(DESTDIR)$(mandir)/man3/pcap_sendpacket.3pcap
+- rm -f $(DESTDIR)$(mandir)/man3/pcap_dispatch.3pcap
+- ln $(DESTDIR)$(mandir)/man3/pcap_loop.3pcap \
+- $(DESTDIR)$(mandir)/man3/pcap_dispatch.3pcap
+- rm -f $(DESTDIR)$(mandir)/man3/pcap_minor_version.3pcap
+- ln $(DESTDIR)$(mandir)/man3/pcap_major_version.3pcap \
+- $(DESTDIR)$(mandir)/man3/pcap_minor_version.3pcap
+- rm -f $(DESTDIR)$(mandir)/man3/pcap_next.3pcap
+- ln $(DESTDIR)$(mandir)/man3/pcap_next_ex.3pcap \
+- $(DESTDIR)$(mandir)/man3/pcap_next.3pcap
+- rm -f $(DESTDIR)$(mandir)/man3/pcap_fopen_offline.3pcap
+- ln $(DESTDIR)$(mandir)/man3/pcap_open_offline.3pcap \
+- $(DESTDIR)$(mandir)/man3/pcap_fopen_offline.3pcap
+- rm -f $(DESTDIR)$(mandir)/man3/pcap_getnonblock.3pcap
+- ln $(DESTDIR)$(mandir)/man3/pcap_setnonblock.3pcap \
+- $(DESTDIR)$(mandir)/man3/pcap_getnonblock.3pcap
+- for i in $(MANFILE); do \
+- $(INSTALL_DATA) `echo $$i | sed 's/.manfile.in/.manfile/'` \
+- $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@/`echo $$i | sed 's/.manfile.in/.@MAN_FILE_FORMATS@/'`; done
+- for i in $(MANMISC); do \
+- $(INSTALL_DATA) `echo $$i | sed 's/.manmisc.in/.manmisc/'` \
+- $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@/`echo $$i | sed 's/.manmisc.in/.@MAN_MISC_INFO@/'`; done
+
+ install-shared: install-shared-$(DYEXT)
+ install-shared-so: $(SHAREDLIB)
+@@ -642,23 +592,6 @@ uninstall: uninstall-shared
+ rm -f $(DESTDIR)$(includedir)/$$i; done
+ -rmdir $(DESTDIR)$(includedir)/pcap
+ rm -f $(DESTDIR)/$(bindir)/pcap-config
+- for i in $(MAN1); do \
+- rm -f $(DESTDIR)$(mandir)/man1/$$i; done
+- for i in $(MAN3PCAP); do \
+- rm -f $(DESTDIR)$(mandir)/man3/$$i; done
+- rm -f $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_description.3pcap
+- rm -f $(DESTDIR)$(mandir)/man3/pcap_dump_fopen.3pcap
+- rm -f $(DESTDIR)$(mandir)/man3/pcap_perror.3pcap
+- rm -f $(DESTDIR)$(mandir)/man3/pcap_sendpacket.3pcap
+- rm -f $(DESTDIR)$(mandir)/man3/pcap_dispatch.3pcap
+- rm -f $(DESTDIR)$(mandir)/man3/pcap_minor_version.3pcap
+- rm -f $(DESTDIR)$(mandir)/man3/pcap_next.3pcap
+- rm -f $(DESTDIR)$(mandir)/man3/pcap_fopen_offline.3pcap
+- rm -f $(DESTDIR)$(mandir)/man3/pcap_getnonblock.3pcap
+- for i in $(MANFILE); do \
+- rm -f $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@/`echo $$i | sed 's/.manfile.in/.@MAN_FILE_FORMATS@/'`; done
+- for i in $(MANMISC); do \
+- rm -f $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@/`echo $$i | sed 's/.manmisc.in/.@MAN_MISC_INFO@/'`; done
+
+ uninstall-shared: uninstall-shared-$(DYEXT)
+ uninstall-shared-so:
diff --git a/package/libpcap/patches/103-makefile_flex_workaround.patch b/package/libpcap/patches/103-makefile_flex_workaround.patch
new file mode 100644
index 000000000..a90e0ce1a
--- /dev/null
+++ b/package/libpcap/patches/103-makefile_flex_workaround.patch
@@ -0,0 +1,14 @@
+
+ Copyright (C) 2006 Markus Wigge
+
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -56,7 +56,7 @@ LD = /usr/bin/ld
+ CC = @CC@
+ CCOPT = @V_CCOPT@
+ INCLS = -I. @V_INCLS@
+-DEFS = @DEFS@ @V_DEFS@
++DEFS = -D_BSD_SOURCE @DEFS@ @V_DEFS@
+ ADDLOBJS = @ADDLOBJS@
+ ADDLARCHIVEOBJS = @ADDLARCHIVEOBJS@
+ LIBS = @LIBS@
diff --git a/package/libpcap/patches/201-space_optimization.patch b/package/libpcap/patches/201-space_optimization.patch
new file mode 100644
index 000000000..f3eec4c83
--- /dev/null
+++ b/package/libpcap/patches/201-space_optimization.patch
@@ -0,0 +1,133 @@
+--- a/gencode.c
++++ b/gencode.c
+@@ -491,20 +491,6 @@ pcap_compile_nopcap(int snaplen_arg, int
+ }
+
+ /*
+- * Clean up a "struct bpf_program" by freeing all the memory allocated
+- * in it.
+- */
+-void
+-pcap_freecode(struct bpf_program *program)
+-{
+- program->bf_len = 0;
+- if (program->bf_insns != NULL) {
+- free((char *)program->bf_insns);
+- program->bf_insns = NULL;
+- }
+-}
+-
+-/*
+ * Backpatch the blocks in 'list' to 'target'. The 'sense' field indicates
+ * which of the jt and jf fields has been resolved and which is a pointer
+ * back to another unresolved block (or nil). At least one of the fields
+--- a/pcap.c
++++ b/pcap.c
+@@ -748,6 +748,59 @@ static const u_char charmap[] = {
+ (u_char)'\374', (u_char)'\375', (u_char)'\376', (u_char)'\377',
+ };
+
++/*
++ * Clean up a "struct bpf_program" by freeing all the memory allocated
++ * in it.
++ */
++void
++pcap_freecode(struct bpf_program *program)
++{
++ program->bf_len = 0;
++ if (program->bf_insns != NULL) {
++ free((char *)program->bf_insns);
++ program->bf_insns = NULL;
++ }
++}
++
++/*
++ * Make a copy of a BPF program and put it in the "fcode" member of
++ * a "pcap_t".
++ *
++ * If we fail to allocate memory for the copy, fill in the "errbuf"
++ * member of the "pcap_t" with an error message, and return -1;
++ * otherwise, return 0.
++ */
++int
++install_bpf_program(pcap_t *p, struct bpf_program *fp)
++{
++ size_t prog_size;
++
++ /*
++ * Validate the program.
++ */
++ if (!bpf_validate(fp->bf_insns, fp->bf_len)) {
++ snprintf(p->errbuf, sizeof(p->errbuf),
++ "BPF program is not valid");
++ return (-1);
++ }
++
++ /*
++ * Free up any already installed program.
++ */
++ pcap_freecode(&p->fcode);
++
++ prog_size = sizeof(*fp->bf_insns) * fp->bf_len;
++ p->fcode.bf_len = fp->bf_len;
++ p->fcode.bf_insns = (struct bpf_insn *)malloc(prog_size);
++ if (p->fcode.bf_insns == NULL) {
++ snprintf(p->errbuf, sizeof(p->errbuf),
++ "malloc: %s", pcap_strerror(errno));
++ return (-1);
++ }
++ memcpy(p->fcode.bf_insns, fp->bf_insns, prog_size);
++ return (0);
++}
++
+ int
+ pcap_strcasecmp(const char *s1, const char *s2)
+ {
+--- a/optimize.c
++++ b/optimize.c
+@@ -2292,45 +2292,6 @@ icode_to_fcode(root, lenp)
+ return fp;
+ }
+
+-/*
+- * Make a copy of a BPF program and put it in the "fcode" member of
+- * a "pcap_t".
+- *
+- * If we fail to allocate memory for the copy, fill in the "errbuf"
+- * member of the "pcap_t" with an error message, and return -1;
+- * otherwise, return 0.
+- */
+-int
+-install_bpf_program(pcap_t *p, struct bpf_program *fp)
+-{
+- size_t prog_size;
+-
+- /*
+- * Validate the program.
+- */
+- if (!bpf_validate(fp->bf_insns, fp->bf_len)) {
+- snprintf(p->errbuf, sizeof(p->errbuf),
+- "BPF program is not valid");
+- return (-1);
+- }
+-
+- /*
+- * Free up any already installed program.
+- */
+- pcap_freecode(&p->fcode);
+-
+- prog_size = sizeof(*fp->bf_insns) * fp->bf_len;
+- p->fcode.bf_len = fp->bf_len;
+- p->fcode.bf_insns = (struct bpf_insn *)malloc(prog_size);
+- if (p->fcode.bf_insns == NULL) {
+- snprintf(p->errbuf, sizeof(p->errbuf),
+- "malloc: %s", pcap_strerror(errno));
+- return (-1);
+- }
+- memcpy(p->fcode.bf_insns, fp->bf_insns, prog_size);
+- return (0);
+-}
+-
+ #ifdef BDEBUG
+ static void
+ opt_dump(root)
diff --git a/package/libpcap/patches/202-protocol_api.patch b/package/libpcap/patches/202-protocol_api.patch
new file mode 100644
index 000000000..892aeb7e0
--- /dev/null
+++ b/package/libpcap/patches/202-protocol_api.patch
@@ -0,0 +1,141 @@
+--- a/pcap-int.h
++++ b/pcap-int.h
+@@ -209,6 +209,7 @@ struct pcap_opt {
+ char *source;
+ int promisc;
+ int rfmon;
++ int proto; /* protocol for packet socket (linux) */
+ };
+
+ /*
+--- a/pcap-linux.c
++++ b/pcap-linux.c
+@@ -335,7 +335,7 @@ static int iface_get_id(int fd, const ch
+ static int iface_get_mtu(int fd, const char *device, char *ebuf);
+ static int iface_get_arptype(int fd, const char *device, char *ebuf);
+ #ifdef HAVE_PF_PACKET_SOCKETS
+-static int iface_bind(int fd, int ifindex, char *ebuf);
++static int iface_bind(int fd, int ifindex, char *ebuf, unsigned short proto);
+ #ifdef IW_MODE_MONITOR
+ static int has_wext(int sock_fd, const char *device, char *ebuf);
+ #endif /* IW_MODE_MONITOR */
+@@ -881,7 +881,7 @@ pcap_can_set_rfmon_linux(pcap_t *handle)
+ * (We assume that if we have Wireless Extensions support
+ * we also have PF_PACKET support.)
+ */
+- sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
++ sock_fd = socket(PF_PACKET, SOCK_RAW, p->opt.proto);
+ if (sock_fd == -1) {
+ (void)snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "socket: %s", pcap_strerror(errno));
+@@ -1128,6 +1128,9 @@ pcap_activate_linux(pcap_t *handle)
+ handle->read_op = pcap_read_linux;
+ handle->stats_op = pcap_stats_linux;
+
++ if (handle->opt.proto < 0)
++ handle->opt.proto = (int) htons(ETH_P_ALL);
++
+ /*
+ * The "any" device is a special device which causes us not
+ * to bind to a particular device and thus to look at all
+@@ -2684,8 +2687,8 @@ activate_new(pcap_t *handle)
+ * try a SOCK_RAW socket for the raw interface.
+ */
+ sock_fd = is_any_device ?
+- socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)) :
+- socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
++ socket(PF_PACKET, SOCK_DGRAM, handle->opt.proto) :
++ socket(PF_PACKET, SOCK_RAW, handle->opt.proto);
+
+ if (sock_fd == -1) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
+@@ -2783,7 +2786,7 @@ activate_new(pcap_t *handle)
+ return PCAP_ERROR;
+ }
+ sock_fd = socket(PF_PACKET, SOCK_DGRAM,
+- htons(ETH_P_ALL));
++ handle->opt.proto);
+ if (sock_fd == -1) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "socket: %s", pcap_strerror(errno));
+@@ -2835,7 +2838,7 @@ activate_new(pcap_t *handle)
+ }
+
+ if ((err = iface_bind(sock_fd, handle->md.ifindex,
+- handle->errbuf)) != 1) {
++ handle->errbuf, handle->opt.proto)) != 1) {
+ close(sock_fd);
+ if (err < 0)
+ return err;
+@@ -3640,7 +3643,7 @@ iface_get_id(int fd, const char *device,
+ * or a PCAP_ERROR_ value on a hard error.
+ */
+ static int
+-iface_bind(int fd, int ifindex, char *ebuf)
++iface_bind(int fd, int ifindex, char *ebuf, unsigned short proto)
+ {
+ struct sockaddr_ll sll;
+ int err;
+@@ -3649,7 +3652,7 @@ iface_bind(int fd, int ifindex, char *eb
+ memset(&sll, 0, sizeof(sll));
+ sll.sll_family = AF_PACKET;
+ sll.sll_ifindex = ifindex;
+- sll.sll_protocol = htons(ETH_P_ALL);
++ sll.sll_protocol = proto;
+
+ if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -1) {
+ if (errno == ENETDOWN) {
+@@ -4359,7 +4362,7 @@ activate_old(pcap_t *handle)
+
+ /* Open the socket */
+
+- handle->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
++ handle->fd = socket(PF_INET, SOCK_PACKET, handle->opt.proto);
+ if (handle->fd == -1) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "socket: %s", pcap_strerror(errno));
+--- a/pcap.c
++++ b/pcap.c
+@@ -258,6 +258,8 @@ pcap_create_common(const char *source, c
+ pcap_set_snaplen(p, 65535); /* max packet size */
+ p->opt.promisc = 0;
+ p->opt.buffer_size = 0;
++ p->opt.proto = -1;
++
+ return (p);
+ }
+
+@@ -317,6 +319,15 @@ pcap_set_buffer_size(pcap_t *p, int buff
+ return 0;
+ }
+
++int
++pcap_set_protocol(pcap_t *p, unsigned short proto)
++{
++ if (pcap_check_activated(p))
++ return PCAP_ERROR_ACTIVATED;
++ p->opt.proto = proto;
++ return 0;
++}
++
+ int
+ pcap_activate(pcap_t *p)
+ {
+--- a/pcap/pcap.h
++++ b/pcap/pcap.h
+@@ -68,6 +68,7 @@ extern "C" {
+ #define PCAP_VERSION_MINOR 4
+
+ #define PCAP_ERRBUF_SIZE 256
++#define HAS_PROTO_EXTENSION
+
+ /*
+ * Compatibility for systems that have a bpf.h that
+@@ -276,6 +277,7 @@ int pcap_can_set_rfmon(pcap_t *);
+ int pcap_set_rfmon(pcap_t *, int);
+ int pcap_set_timeout(pcap_t *, int);
+ int pcap_set_buffer_size(pcap_t *, int);
++int pcap_set_protocol(pcap_t *, unsigned short);
+ int pcap_activate(pcap_t *);
+
+ pcap_t *pcap_open_live(const char *, int, int, int, char *);
diff --git a/package/libpcap/patches/203-undef_iw_mode_monitor.patch b/package/libpcap/patches/203-undef_iw_mode_monitor.patch
new file mode 100644
index 000000000..508c6590a
--- /dev/null
+++ b/package/libpcap/patches/203-undef_iw_mode_monitor.patch
@@ -0,0 +1,11 @@
+--- a/pcap-linux.c
++++ b/pcap-linux.c
+@@ -254,6 +254,8 @@ static const char rcsid[] _U_ =
+ typedef int socklen_t;
+ #endif
+
++#undef IW_MODE_MONITOR
++
+ #ifndef MSG_TRUNC
+ /*
+ * This is being compiled on a system that lacks MSG_TRUNC; define it
diff --git a/package/libreadline/Makefile b/package/libreadline/Makefile
new file mode 100644
index 000000000..90219e55b
--- /dev/null
+++ b/package/libreadline/Makefile
@@ -0,0 +1,66 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=readline
+PKG_VERSION:=5.2
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@GNU/readline
+PKG_MD5SUM:=e39331f32ad14009b9ff49cc10c5e751
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/libreadline
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=Command lines edition library
+ URL:=http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html
+endef
+
+define Package/libreadline/description
+ The Readline library provides a set of functions for use by applications
+ that allow users to edit command lines as they are typed in. Both Emacs
+ and vi editing modes are available. The Readline library includes
+ additional functions to maintain a list of previously-entered command
+ lines, to recall and perhaps reedit those lines, and perform csh-like
+ history expansion on previous commands.
+endef
+
+define Build/Configure
+ $(call Build/Configure/Default, \
+ --enable-shared \
+ --enable-static \
+ --without-curses \
+ )
+endef
+
+TARGET_CPPFLAGS:=-I. -I.. $(TARGET_CPPFLAGS)
+
+TARGET_CFLAGS += $(FPIC)
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ all install
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/readline $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/lib{history,readline}.{a,so,so.5,so.5.2} $(1)/usr/lib/
+endef
+
+define Package/libreadline/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/lib{history,readline}.{so,so.5,so.5.2} $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,libreadline))
diff --git a/package/libreadline/patches/100-fix_avr32_compile b/package/libreadline/patches/100-fix_avr32_compile
new file mode 100644
index 000000000..4d55b8035
--- /dev/null
+++ b/package/libreadline/patches/100-fix_avr32_compile
@@ -0,0 +1,20 @@
+--- a/support/config.sub
++++ b/support/config.sub
+@@ -228,7 +228,7 @@ case $basic_machine in
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+- | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
++ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+@@ -293,7 +293,7 @@ case $basic_machine in
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | amd64-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+- | avr-* \
++ | avr-* | avr32-* \
+ | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* \
+ | clipper-* | cydra-* \
diff --git a/package/librpc/Makefile b/package/librpc/Makefile
new file mode 100644
index 000000000..34cedbb4e
--- /dev/null
+++ b/package/librpc/Makefile
@@ -0,0 +1,28 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=librpc
+PKG_VERSION:=0.9.32-rc2
+PKG_RELEASE=$(PKG_SOURCE_VERSION)
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=git://nbd.name/uclibc-rpc.git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=0a2179bbc0844928f2a0ec01dba93d9b5d6d41a7
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
+CMAKE_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/librpc
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=uClibc RPC library
+endef
+
+define Package/librpc/install
+ $(INSTALL_DIR) $(1)/lib/
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/librpc.so $(1)/lib/
+endef
+
+$(eval $(call BuildPackage,librpc))
diff --git a/package/librpc/patches/100-compat_fix.patch b/package/librpc/patches/100-compat_fix.patch
new file mode 100644
index 000000000..a0f03f6e5
--- /dev/null
+++ b/package/librpc/patches/100-compat_fix.patch
@@ -0,0 +1,214 @@
+--- a/compat.h
++++ /dev/null
+@@ -1,32 +0,0 @@
+-#ifndef __UCLIBC_COMPAT_H
+-#define __UCLIBC_COMPAT_H
+-
+-#define _XOPEN_SOURCE
+-#define _GNU_SOURCE
+-
+-#include <features.h>
+-#include <errno.h>
+-
+-#undef __UCLIBC_HAS_THREADS__
+-#include <bits/uClibc_mutex.h>
+-#include <sys/poll.h>
+-
+-#if 0
+-#undef __UCLIBC_MUTEX_LOCK
+-#undef __UCLIBC_MUTEX_UNLOCK
+-#define __UCLIBC_MUTEX_LOCK(M) pthread_mutex_lock(&(M))
+-#define __UCLIBC_MUTEX_UNLOCK(M) pthread_mutex_unlock(&(M))
+-#endif
+-
+-#define smallint int
+-
+-#define _(...) __VA_ARGS__
+-#define internal_function
+-#define attribute_hidden
+-#define attribute_unused
+-#define attribute_noreturn
+-#define libc_hidden_def(...)
+-
+-#define __set_errno(_val) errno = _val
+-
+-#endif
+--- a/rcmd.c
++++ b/rcmd.c
+@@ -85,7 +85,6 @@ static char sccsid[] = "@(#)rcmd.c 8.3 (
+ #include <wchar.h>
+ #endif
+ #include <sys/uio.h>
+-#include <bits/uClibc_alloc.h>
+
+
+ /* some forward declarations */
+--- a/create_xid.c
++++ b/create_xid.c
+@@ -28,7 +28,6 @@
+
+ /* The RPC code is not threadsafe, but new code should be threadsafe. */
+
+-#include <bits/uClibc_mutex.h>
+ __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
+
+ static smallint is_initialized;
+--- a/getrpcent.c
++++ b/getrpcent.c
+@@ -257,7 +257,6 @@ static struct rpcent *interpret(register
+
+ #if defined(__UCLIBC_HAS_REENTRANT_RPC__)
+
+-#include <bits/uClibc_mutex.h>
+ __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
+
+
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -1,7 +1,7 @@
+ cmake_minimum_required(VERSION 2.6)
+
+ PROJECT(rpc C)
+-ADD_DEFINITIONS(-Os -Wall --std=gnu99 -g3 -I. -include compat.h)
++ADD_DEFINITIONS(-Os -Wall --std=gnu99 -g3 -I. -include rpc/compat.h)
+
+ FILE(GLOB SOURCES *.c)
+
+--- a/rpc/types.h
++++ b/rpc/types.h
+@@ -33,6 +33,8 @@
+ #ifndef _RPC_TYPES_H
+ #define _RPC_TYPES_H 1
+
++#include "compat.h"
++
+ #ifdef _LIBC
+ /* Some adjustments to make the libc source from glibc
+ * compile more easily with uClibc... */
+--- a/clnt_perror.c
++++ b/clnt_perror.c
+@@ -246,7 +246,7 @@ clnt_sperror (CLIENT * rpch, const char
+
+ case RPC_CANTSEND:
+ case RPC_CANTRECV:
+- __glibc_strerror_r (e.re_errno, chrbuf, sizeof chrbuf);
++ strerror_r (e.re_errno, chrbuf, sizeof chrbuf);
+ len = sprintf (str, "; errno = %s", chrbuf);
+ str += len;
+ break;
+@@ -336,7 +336,7 @@ clnt_spcreateerror (const char *msg)
+ (void) strcpy(cp, " - ");
+ cp += strlen(cp);
+
+- __glibc_strerror_r (ce->cf_error.re_errno, chrbuf, sizeof chrbuf);
++ strerror_r (ce->cf_error.re_errno, chrbuf, sizeof chrbuf);
+ (void) strcpy(cp, chrbuf);
+ cp += strlen(cp);
+ break;
+--- a/rpc_thread.c
++++ b/rpc_thread.c
+@@ -13,9 +13,6 @@
+
+ #ifdef __UCLIBC_HAS_THREADS__
+
+-#include <bits/libc-tsd.h>
+-#include <bits/libc-lock.h>
+-
+ /* Variable used in non-threaded applications or for the first thread. */
+ static struct rpc_thread_variables __libc_tsd_RPC_VARS_mem;
+ __libc_tsd_define (, RPC_VARS)
+@@ -52,16 +49,17 @@ rpc_thread_multi (void)
+ __libc_tsd_set (RPC_VARS, &__libc_tsd_RPC_VARS_mem);
+ }
+
++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
+
+ struct rpc_thread_variables attribute_hidden *
+ __rpc_thread_variables (void)
+ {
+- __libc_once_define (static, once);
+ struct rpc_thread_variables *tvp;
+
++ __UCLIBC_MUTEX_LOCK(mylock);
+ tvp = __libc_tsd_get (RPC_VARS);
+ if (tvp == NULL) {
+- __libc_once (once, rpc_thread_multi);
++ rpc_thread_multi();
+ tvp = __libc_tsd_get (RPC_VARS);
+ if (tvp == NULL) {
+ tvp = calloc (1, sizeof *tvp);
+@@ -71,6 +69,7 @@ __rpc_thread_variables (void)
+ tvp = __libc_tsd_get (RPC_VARS);
+ }
+ }
++ __UCLIBC_MUTEX_UNLOCK(mylock);
+ return tvp;
+ }
+
+--- /dev/null
++++ b/rpc/compat.h
+@@ -0,0 +1,53 @@
++#ifndef __UCLIBC_COMPAT_H
++#define __UCLIBC_COMPAT_H
++
++#define _XOPEN_SOURCE
++#define _GNU_SOURCE
++
++#include <features.h>
++#include <errno.h>
++
++#ifndef __UCLIBC_HAS_THREADS__
++#define __UCLIBC_HAS_THREADS__
++#endif
++
++#include <sys/poll.h>
++#include <pthread.h>
++
++#ifdef __UCLIBC__
++#include <bits/libc-lock.h>
++#else
++#undef __UCLIBC_MUTEX_STATIC
++#undef __UCLIBC_MUTEX_LOCK
++#undef __UCLIBC_MUTEX_UNLOCK
++#define __UCLIBC_MUTEX_STATIC(M,I) static pthread_mutex_t M = I
++#define __UCLIBC_MUTEX_LOCK(M) pthread_mutex_lock(&(M))
++#define __UCLIBC_MUTEX_UNLOCK(M) pthread_mutex_unlock(&(M))
++#endif
++
++#define smallint int
++
++#define _(...) __VA_ARGS__
++#define internal_function
++#define attribute_hidden
++#define attribute_unused
++#define attribute_noreturn
++#define libc_hidden_def(...)
++
++#ifndef libc_hidden_proto
++#define libc_hidden_proto(name, attrs...)
++#endif
++
++#define __set_errno(_val) errno = _val
++
++# define attribute_tls_model_ie __attribute__ ((tls_model ("initial-exec")))
++
++# define __libc_tsd_define(CLASS, KEY) \
++ CLASS __thread void *__libc_tsd_##KEY attribute_tls_model_ie;
++
++# define __libc_tsd_address(KEY) (&__libc_tsd_##KEY)
++# define __libc_tsd_get(KEY) (__libc_tsd_##KEY)
++# define __libc_tsd_set(KEY, VALUE) (__libc_tsd_##KEY = (VALUE))
++
++
++#endif
+--- a/rpc/netdb.h
++++ b/rpc/netdb.h
+@@ -41,6 +41,8 @@
+ #define __need_size_t
+ #include <stddef.h>
+
++#include "types.h"
++
+ __BEGIN_DECLS
+
+ struct rpcent
diff --git a/package/libtool/Makefile b/package/libtool/Makefile
new file mode 100644
index 000000000..b33eda14a
--- /dev/null
+++ b/package/libtool/Makefile
@@ -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.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=libtool
+PKG_VERSION:=2.4
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@GNU/libtool
+PKG_MD5SUM:=b32b04148ecdd7344abc6fe8bd1bb021
+
+PKG_BUILD_PARALLEL:=0
+
+include $(INCLUDE_DIR)/package.mk
+
+CONFIGURE_PREFIX=$(STAGING_DIR)/host
+export GLOBAL_LIBDIR=$(STAGING_DIR)/usr/lib
+
+define Package/libltdl
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=A generic dynamic object loading library
+ URL:=http://www.gnu.org/software/libtool/
+endef
+
+define Build/InstallDev
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ bindir="$(2)/bin" \
+ datadir="$(2)/share" \
+ prefix="$(2)" \
+ exec_prefix="$(2)" \
+ install
+ $(INSTALL_DIR) $(1)/usr/lib $(1)/usr/include
+ mv $(2)/lib/* $(1)/usr/lib/
+ mv $(2)/include/* $(1)/usr/include/
+endef
+
+define Package/libltdl/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/libltdl/.libs/libltdl.so.* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,libltdl))
diff --git a/package/libubox/Makefile b/package/libubox/Makefile
new file mode 100644
index 000000000..845f38070
--- /dev/null
+++ b/package/libubox/Makefile
@@ -0,0 +1,64 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=libubox
+PKG_VERSION:=2012-07-08
+PKG_RELEASE=$(PKG_SOURCE_VERSION)
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=git://nbd.name/luci2/libubox.git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=cca2ed6c8cdb3555fea43ff63ba1c9905dd7a164
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
+PKG_MIRROR_MD5SUM:=dfd44c10b4aeccbdab9ae22774fb02e3
+CMAKE_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/libubox
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=Basic utility library
+ DEPENDS:=
+endef
+
+define Package/libblobmsg-json
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=blobmsg <-> json conversion library
+ DEPENDS:=+libjson +libubox
+endef
+
+define Package/jshn
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libjson
+ TITLE:=JSON SHell Notation
+endef
+
+define Package/jshn/description
+ Library for parsing and generating JSON from shell scripts
+endef
+
+TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include
+
+define Package/libubox/install
+ $(INSTALL_DIR) $(1)/lib/
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libubox.so $(1)/lib/
+endef
+
+define Package/libblobmsg-json/install
+ $(INSTALL_DIR) $(1)/lib/
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libblobmsg_json.so $(1)/lib/
+endef
+
+define Package/jshn/install
+ $(INSTALL_DIR) $(1)/usr/bin $(1)/usr/share/libubox
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/jshn $(1)/usr/bin
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/libubox/jshn.sh $(1)/usr/share/libubox
+endef
+
+$(eval $(call BuildPackage,libubox))
+$(eval $(call BuildPackage,libblobmsg-json))
+$(eval $(call BuildPackage,jshn))
+
diff --git a/package/linux-atm/Makefile b/package/linux-atm/Makefile
new file mode 100644
index 000000000..f829b709e
--- /dev/null
+++ b/package/linux-atm/Makefile
@@ -0,0 +1,153 @@
+#
+# Copyright (C) 2006-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=linux-atm
+PKG_VERSION:=2.5.2
+PKG_RELEASE:=4
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/$(PKG_NAME)
+PKG_MD5SUM:=d49499368c3cf15f73a05d9bce8824a8
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/linux-atm
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=Linux ATM library
+ URL:=http://linux-atm.sourceforge.net/
+endef
+
+define Package/linux-atm/description
+ This package contains a library for accessing the Linux ATM subsystem.
+endef
+
+define Package/atm-tools
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS:=linux-atm
+ TITLE:=Linux ATM tools
+ URL:=http://linux-atm.sourceforge.net/
+endef
+
+define Package/atm-tools/description
+ This package contains the Linux ATM tools.
+endef
+
+define Package/atm-diagnostics
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS:=linux-atm
+ TITLE:=Linux ATM Diagnostics
+ URL:=http://linux-atm.sourceforge.net/
+endef
+
+define Package/atm-diagnostics/description
+ This package contains the Linux ATM diagnostics.
+endef
+
+define Package/br2684ctl
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS:=linux-atm
+ TITLE:=ATM Ethernet bridging configuration utility
+ URL:=http://linux-atm.sourceforge.net/
+endef
+
+define Package/br2684ctl/description
+ Support for AAL5 encapsulation (RFC-1483/RFC-2684) over ATM.
+endef
+
+define Build/Configure
+ $(call Build/Configure/Default)
+ # prevent autoheader invocation
+ touch $(PKG_BUILD_DIR)/stamp-h.in
+endef
+
+TARGET_CFLAGS += -I$(LINUX_DIR)/include -I$(LINUX_DIR)/arch/$(LINUX_KARCH)/include
+unexport PREFIX
+
+define Build/Compile
+ # src/qgen is built with HOSTCC, which does not really like our LDFLAGS
+ +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/src/qgen \
+ LDFLAGS="" \
+ all
+ +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) OBJCOPY=$(TARGET_CROSS)objcopy all
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr
+ $(CP) \
+ $(PKG_INSTALL_DIR)/usr/include \
+ $(PKG_INSTALL_DIR)/usr/lib \
+ $(1)/usr/
+endef
+
+define Package/linux-atm/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libatm.so* $(1)/usr/lib/
+endef
+
+define Package/atm-tools/install
+ $(INSTALL_DIR) $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/arpd/atmarp{,d} $(1)/usr/sbin/
+
+#
+#The following is disabled by default but still useful for some debugging
+#
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/atmaddr $(1)/usr/sbin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/atmloop $(1)/usr/sbin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/atmtcp $(1)/usr/sbin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/esi $(1)/usr/sbin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/aread $(1)/usr/bin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/awrite $(1)/usr/bin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/atmdiag $(1)/usr/bin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/atmdump $(1)/usr/bin/
+#
+# The following is really for some specific application, and obsolete for most of it
+#
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/atmsigd $(1)/usr/sbin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/bus $(1)/usr/sbin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ilmid $(1)/usr/sbin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ilmidiag $(1)/usr/sbin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/lecs $(1)/usr/sbin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/les $(1)/usr/sbin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/mpcd $(1)/usr/sbin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/zeppelin $(1)/usr/sbin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/atmswitch $(1)/usr/bin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/saaldump $(1)/usr/bin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/sonetdiag $(1)/usr/bin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/svc_recv $(1)/usr/bin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/svc_send $(1)/usr/bin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ttcp_atm $(1)/usr/bin/
+endef
+
+define Package/atm-diagnostics/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/aread $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/awrite $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/atmdiag $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/atmdump $(1)/usr/bin/
+endef
+
+define Package/br2684ctl/install
+ $(INSTALL_DIR) $(1)/etc/init.d/
+ $(INSTALL_BIN) ./files/br2684ctl $(1)/etc/init.d/
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/br2684ctl $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,linux-atm))
+$(eval $(call BuildPackage,atm-tools))
+$(eval $(call BuildPackage,atm-diagnostics))
+$(eval $(call BuildPackage,br2684ctl))
diff --git a/package/linux-atm/files/br2684ctl b/package/linux-atm/files/br2684ctl
new file mode 100755
index 000000000..cd53f0481
--- /dev/null
+++ b/package/linux-atm/files/br2684ctl
@@ -0,0 +1,90 @@
+#!/bin/sh /etc/rc.common
+
+
+. /lib/functions/network.sh
+
+START=50
+
+SERVICE_DAEMONIZE=1
+SERVICE_WRITE_PID=1
+
+start_daemon() {
+ local cfg="$1"
+
+ local atmdev
+ config_get atmdev "$cfg" atmdev 0
+
+ local unit
+ config_get unit "$cfg" unit 0
+
+ local vpi
+ config_get vpi "$cfg" vpi 8
+
+ local vci
+ config_get vci "$cfg" vci 35
+
+ local encaps
+ config_get encaps "$cfg" encaps
+
+ case "$encaps" in
+ 1|vc) encaps=1;;
+ *) encaps=0;;
+ esac
+
+ local payload
+ config_get payload "$cfg" payload
+
+ case "$payload" in
+ 0|routed) payload=0;;
+ *) payload=1;;
+ esac
+
+ local qos
+ config_get qos "$cfg" qos
+
+ local sendsize
+ config_get sendsize "$cfg" sendsize
+
+ local circuit="$atmdev.$vpi.$vci"
+
+ network_defer_device "nas$unit"
+
+ SERVICE_PID_FILE="/var/run/br2684ctl-$circuit.pid" \
+ service_start /usr/sbin/br2684ctl \
+ -c "$unit" -e "$encaps" -p "$payload" \
+ -a "$circuit" ${qos:+-q "$qos"} ${sendsize:+-s "$sendsize"}
+ sleep 1
+
+ network_ready_device "nas$unit"
+}
+
+stop_daemon() {
+ local cfg="$1"
+
+ local atmdev
+ config_get atmdev "$cfg" atmdev 0
+
+ local unit
+ config_get unit "$cfg" unit 0
+
+ local vpi
+ config_get vpi "$cfg" vpi 8
+
+ local vci
+ config_get vci "$cfg" vci 35
+
+ local circuit="$atmdev.$vpi.$vci"
+
+ SERVICE_PID_FILE="/var/run/br2684ctl-$circuit.pid" \
+ service_stop /usr/sbin/br2684ctl
+}
+
+start() {
+ config_load network
+ config_foreach start_daemon atm-bridge
+}
+
+stop() {
+ config_load network
+ config_foreach stop_daemon atm-bridge
+}
diff --git a/package/linux-atm/patches/000-debian_16.patch b/package/linux-atm/patches/000-debian_16.patch
new file mode 100644
index 000000000..4abaac07e
--- /dev/null
+++ b/package/linux-atm/patches/000-debian_16.patch
@@ -0,0 +1,270 @@
+--- a/src/arpd/io.c
++++ b/src/arpd/io.c
+@@ -277,7 +277,8 @@ static void accept_new(void)
+ struct atm_qos qos;
+ ENTRY *entry;
+ VCC *vcc;
+- int fd,len,size,error;
++ int fd,error;
++ socklen_t len,size;
+
+ len = sizeof(addr);
+ if ((fd = accept(incoming,(struct sockaddr *) &addr,&len)) < 0) {
+@@ -614,7 +615,8 @@ int ip_itf_info(int number,uint32_t *ip,
+
+ int get_local(int fd,struct sockaddr_atmsvc *addr)
+ {
+- int length,result;
++ int result;
++ size_t length;
+
+ length = sizeof(struct sockaddr_atmsvc);
+ result = getsockname(fd,(struct sockaddr *) addr,&length);
+--- a/src/arpd/table.c
++++ b/src/arpd/table.c
+@@ -101,7 +101,8 @@ static void dump_vcc(VCC *vcc)
+ char addr_buf[MAX_ATM_ADDR_LEN+1];
+ char qos_buf[MAX_ATM_QOS_LEN+1];
+ struct atm_qos qos;
+- int size,sndbuf;
++ int sndbuf;
++ socklen_t size;
+
+ size = sizeof(addr);
+ if (getpeername(vcc->fd,(struct sockaddr *) &addr,&size) < 0) {
+--- a/src/ilmid/asn1/asn_int.c
++++ b/src/ilmid/asn1/asn_int.c
+@@ -185,7 +185,7 @@ FILE* f _AND_
+ AsnInt* v _AND_
+ unsigned short int indent)
+ {
+- fprintf(f,"%d", *v);
++ fprintf(f,"%ld", *v);
+ }
+
+
+@@ -370,5 +370,5 @@ FILE* f _AND_
+ UAsnInt* v _AND_
+ unsigned short int indent)
+ {
+- fprintf(f,"%u", *v);
++ fprintf(f,"%lu", *v);
+ }
+--- a/src/ilmid/asn1/asn_oid.c
++++ b/src/ilmid/asn1/asn_oid.c
+@@ -127,7 +127,7 @@ unsigned short int indent)
+ if (firstArcNum > 2)
+ firstArcNum = 2;
+
+- fprintf(f,"%u %u", firstArcNum, arcNum - (firstArcNum * 40));
++ fprintf(f,"%d %lu", firstArcNum, arcNum - (firstArcNum * 40));
+
+ for (; i < v->octetLen ; )
+ {
+@@ -136,7 +136,7 @@ unsigned short int indent)
+
+ arcNum = (arcNum << 7) + (v->octs[i] & 0x7f);
+ i++;
+- fprintf(f," %u", arcNum);
++ fprintf(f," %lu", arcNum);
+ }
+ fprintf(f,"}");
+
+--- a/src/lane/connect.c
++++ b/src/lane/connect.c
+@@ -258,7 +258,8 @@ static int
+ data_handler(const Event_t *event, void *funcdata)
+ {
+ Conn_t *tmp, *newconn;
+- int fd, nbytes;
++ int fd;
++ socklen_t nbytes;
+ static char buffer[BUFSIZE];
+ LaneControl_t *ctmp;
+ struct sockaddr_atmsvc addr;
+--- a/src/lane/connect_bus.c
++++ b/src/lane/connect_bus.c
+@@ -170,7 +170,8 @@ static int
+ data_handler(const Event_t *event, void *funcdata)
+ {
+ Conn_t *tmp, *newconn;
+- int fd, nbytes;
++ int fd;
++ socklen_t nbytes;
+ static char buffer[BUFSIZE];
+ struct sockaddr_atmsvc addr;
+
+--- a/src/lane/lane_atm.c
++++ b/src/lane/lane_atm.c
+@@ -138,7 +138,7 @@ atm_connect_back(const AtmAddr_t *our_ad
+ struct atm_blli blli;
+ struct atm_qos qos;
+ int fd, ret;
+- int len = sizeof(address);
++ socklen_t len = sizeof(address);
+
+ fd = socket(PF_ATMSVC, SOCK_DGRAM, 0);
+ if (fd <0) {
+--- a/src/lane/lecs.c
++++ b/src/lane/lecs.c
+@@ -119,7 +119,7 @@ int main(int argc, char **argv)
+ int just_dump=0;
+ fd_set fds;
+ struct sockaddr_atmsvc client;
+- int len;
++ socklen_t len;
+ unsigned char buffer[P_SIZE];
+
+ while(i!=-1) {
+--- a/src/lib/ans.c
++++ b/src/lib/ans.c
+@@ -41,7 +41,7 @@
+ static int ans(const char *text,int wanted,void *result,int res_len)
+ {
+ unsigned char answer[MAX_ANSWER];
+- unsigned char name[MAX_NAME];
++ char name[MAX_NAME];
+ unsigned char *pos,*data,*found;
+ int answer_len,name_len,data_len,found_len;
+ int questions,answers;
+--- a/src/lib/sdu2cell.c
++++ b/src/lib/sdu2cell.c
+@@ -15,7 +15,8 @@ int sdu2cell(int s,int sizes,const int *
+ {
+ struct atm_qos qos;
+ int trailer,total,cells;
+- int size,i;
++ int i;
++ socklen_t size;
+
+ size = sizeof(qos);
+ if (getsockopt(s,SOL_AAL,SO_ATMQOS,&qos,&size) < 0) return -1;
+--- a/src/lib/unix.c
++++ b/src/lib/unix.c
+@@ -63,8 +63,8 @@ int un_attach(const char *path)
+ int un_recv_connect(int s,void *buf,int size)
+ {
+ struct sockaddr_un addr;
+- int addr_size;
+ int len;
++ socklen_t addr_size;
+
+ addr_size = sizeof(addr);
+ len = recvfrom(s,buf,size,0,(struct sockaddr *) &addr,&addr_size);
+--- a/src/maint/atmtcp.c
++++ b/src/maint/atmtcp.c
+@@ -817,7 +817,8 @@ int main(int argc,char **argv)
+ }
+ else if (!strcmp(ARG,"listen") ||
+ (do_background = !strcmp(ARG,"listen-bg"))) {
+- int fd,port,addr_len;
++ int fd,port;
++ socklen_t addr_len;
+ int *fd2 = alloc_t(int);
+
+ if ((fd = socket(PF_INET,SOCK_STREAM,0)) < 0) {
+--- a/src/maint/hediag.c
++++ b/src/maint/hediag.c
+@@ -1,6 +1,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
++#include <string.h>
+ #include <sys/ioctl.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+--- a/src/mpoad/io.c
++++ b/src/mpoad/io.c
+@@ -521,7 +521,8 @@ static int msg_from_mps(int slot)
+ static int accept_conn(int slot)
+ {
+ struct sockaddr_atmsvc sa;
+- int i, new_fd, sa_len;
++ int i, new_fd;
++ socklen_t sa_len;
+
+ sa_len = sizeof(sa);
+ new_fd = accept(fds[slot].fd, (struct sockaddr *)&sa, &sa_len);
+--- a/src/sigd/io.c
++++ b/src/sigd/io.c
+@@ -355,7 +355,7 @@ int get_pvc(int itf,int *vci)
+ error = 0;
+ if (bind(s,(struct sockaddr *) &addr,sizeof(addr)) < 0) error = errno;
+ else {
+- int size;
++ socklen_t size;
+
+ size = sizeof(addr);
+ if (getsockname(s,(struct sockaddr *) &addr,&size) < 0)
+--- a/src/test/ttcp.c
++++ b/src/test/ttcp.c
+@@ -92,7 +92,8 @@ struct sockaddr_in frominet;
+ struct sockaddr_atmsvc satm;
+ struct atm_qos qos;
+
+-int domain, fromlen;
++int domain;
++socklen_t fromlen;
+ int fd; /* fd of network socket */
+
+ int buflen = 8 * 1024; /* length of buffer */
+@@ -466,7 +467,7 @@ int no_check = 0;
+
+ {
+ struct sockaddr_atmsvc peer;
+- int peerlen = sizeof(peer);
++ socklen_t peerlen = sizeof(peer);
+ if (getpeername(fd, (struct sockaddr *) &peer,
+ &peerlen) < 0) {
+ err("getpeername");
+@@ -498,7 +499,7 @@ int no_check = 0;
+ /* set socket buffer size */
+ #if defined(SO_SNDBUF) || defined(SO_RCVBUF)
+ if (sockbufsize) {
+- int len;
++ socklen_t len;
+
+ if (trans) {
+ /* set send socket buffer if we are transmitting */
+--- a/src/mpoad/mpcd.8
++++ b/src/mpoad/mpcd.8
+@@ -28,7 +28,7 @@ mpcd \- ATM MPOA (Multi\-Protocol Over A
+ .B ]]
+ .SH DESCRIPTION
+ MPOA client
+-.SM(MPC) is responsible for creating and receiving
++.SM (MPC) is responsible for creating and receiving
+ internetwork layer shortcuts. Using these shortcuts MPCs forward
+ unicast internetwork layer packets effectively over ATM without need
+ for routing protocols.
+@@ -43,7 +43,7 @@ accepts shortcuts and packets arriving o
+ shortcuts is done with the help of
+ .SM MPOA
+ server
+-.SM(MPS).
++.SM (MPS).
+ .PP
+ Just as the Linux
+ .SM LAN
+--- a/src/led/zeppelin.8
++++ b/src/led/zeppelin.8
+@@ -99,7 +99,7 @@ Ring and ATM parts of the ELAN, so using
+ recommended. Token Ring support has received less testing than its
+ Ethernet counterpart.
+ .SH FILES
+-.IP \fI/var/run/lec[interface number].pid\fP
++.IP \fI/var/run/lec[interface\ number].pid\fP
+ The file containing the process id of zeppelin.
+ .SH BUGS
+ John Bonham died 1980 and Led Zeppelin broke.
+--- a/src/sigd/atmsigd.conf.4
++++ b/src/sigd/atmsigd.conf.4
+@@ -125,7 +125,7 @@ a comment. The `#' character cannot be e
+ .P
+ If an option is specified in \fBatmsigd.conf\fP and on the command
+ line, the command line has priority.
+-.COMPATIBILITY
++.SH COMPATIBILITY
+ Certain options used by past versions of \fBatmsigd\fP but no longer documented
+ on the man page are still recognized and supported, but they also yield a
+ warning message. Future versions of \fBatmsigd\fP will not recognize those
diff --git a/package/linux-atm/patches/200-no_libfl.patch b/package/linux-atm/patches/200-no_libfl.patch
new file mode 100644
index 000000000..6db877931
--- /dev/null
+++ b/package/linux-atm/patches/200-no_libfl.patch
@@ -0,0 +1,179 @@
+--- a/src/qgen/Makefile.am
++++ b/src/qgen/Makefile.am
+@@ -2,7 +2,7 @@ noinst_PROGRAMS = qgen
+
+ qgen_SOURCES = common.c common.h file.c file.h first.c ql_y.y ql_l.l qgen.c \
+ qgen.h second.c third.c
+-qgen_LDADD = -lfl
++qgen_LDADD =
+
+ COMPILE = @CC_FOR_BUILD@ @CFLAGS_FOR_BUILD@
+ LINK = @CC_FOR_BUILD@ @CFLAGS_FOR_BUILD@ -o $@
+--- a/src/qgen/Makefile.in
++++ b/src/qgen/Makefile.in
+@@ -204,7 +204,7 @@ top_srcdir = @top_srcdir@
+ qgen_SOURCES = common.c common.h file.c file.h first.c ql_y.y ql_l.l qgen.c \
+ qgen.h second.c third.c
+
+-qgen_LDADD = -lfl
++qgen_LDADD =
+ COMPILE = @CC_FOR_BUILD@ @CFLAGS_FOR_BUILD@
+ LINK = @CC_FOR_BUILD@ @CFLAGS_FOR_BUILD@ -o $@
+
+--- a/src/sigd/Makefile.am
++++ b/src/sigd/Makefile.am
+@@ -8,7 +8,7 @@ atmsigd_XTRAS = mess.o $(top_builddir)/s
+ $(top_builddir)/src/q2931/qd.dump.o \
+ $(top_builddir)/src/lib/libatm.la \
+ $(top_builddir)/src/saal/libsaal.a
+-atmsigd_LDADD = $(atmsigd_XTRAS) -lfl
++atmsigd_LDADD = $(atmsigd_XTRAS)
+ atmsigd_DEPENDENCIES = mess.c $(atmsigd_XTRAS)
+
+ CLEANFILES = mess.c
+--- a/src/sigd/Makefile.in
++++ b/src/sigd/Makefile.in
+@@ -245,7 +245,7 @@ atmsigd_XTRAS = mess.o $(top_builddir)/s
+ $(top_builddir)/src/lib/libatm.la \
+ $(top_builddir)/src/saal/libsaal.a
+
+-atmsigd_LDADD = $(atmsigd_XTRAS) -lfl
++atmsigd_LDADD = $(atmsigd_XTRAS)
+ atmsigd_DEPENDENCIES = mess.c $(atmsigd_XTRAS)
+ CLEANFILES = mess.c
+ sysconf_DATA = atmsigd.conf
+--- a/src/switch/debug/debug.c
++++ b/src/switch/debug/debug.c
+@@ -20,6 +20,11 @@
+
+ #define PRV(call) ((FAB *) (call)->fab)
+
++int yywrap(void)
++{
++ return 1;
++}
++
+
+ typedef struct _fab {
+ CALL *next; /* relay.c may not keep track of calls, but WE are */
+--- a/src/switch/debug/Makefile.am
++++ b/src/switch/debug/Makefile.am
+@@ -5,7 +5,7 @@ INCLUDES = -I$(srcdir)/../../q2931
+ sw_debug_SOURCES = debug.c
+ sw_debug_XTRAS = $(top_builddir)/src/switch/libsw.a \
+ $(top_builddir)/src/lib/libatm.la
+-sw_debug_LDADD = $(sw_debug_XTRAS) -lfl
++sw_debug_LDADD = $(sw_debug_XTRAS)
+
+ sw_debug_DEPENDENCIES = $(sw_debug_XTRAS)
+
+--- a/src/switch/debug/Makefile.in
++++ b/src/switch/debug/Makefile.in
+@@ -200,7 +200,8 @@ sw_debug_SOURCES = debug.c
+ sw_debug_XTRAS = $(top_builddir)/src/switch/libsw.a \
+ $(top_builddir)/src/lib/libatm.la
+
+-sw_debug_LDADD = $(sw_debug_XTRAS) -lfl
++sw_debug_LDADD = $(sw_debug_XTRAS)
++
+ sw_debug_DEPENDENCIES = $(sw_debug_XTRAS)
+ EXTRA_DIST = demo README
+ all: all-am
+--- a/src/switch/tcp/Makefile.am
++++ b/src/switch/tcp/Makefile.am
+@@ -5,7 +5,7 @@ INCLUDES = -I$(srcdir)/../../q2931
+ sw_tcp_SOURCES = tcpsw.c
+ sw_tcp_XTRAS = $(top_builddir)/src/switch/libsw.a \
+ $(top_builddir)/src/lib/libatm.la
+-sw_tcp_LDADD = $(sw_tcp_XTRAS) -lfl
++sw_tcp_LDADD = $(sw_tcp_XTRAS)
+ sw_tcp_DEPENDENCIES = $(sw_tcp_XTRAS)
+
+ EXTRA_DIST = mkfiles README
+--- a/src/switch/tcp/Makefile.in
++++ b/src/switch/tcp/Makefile.in
+@@ -200,7 +200,7 @@ sw_tcp_SOURCES = tcpsw.c
+ sw_tcp_XTRAS = $(top_builddir)/src/switch/libsw.a \
+ $(top_builddir)/src/lib/libatm.la
+
+-sw_tcp_LDADD = $(sw_tcp_XTRAS) -lfl
++sw_tcp_LDADD = $(sw_tcp_XTRAS)
+ sw_tcp_DEPENDENCIES = $(sw_tcp_XTRAS)
+ EXTRA_DIST = mkfiles README
+ all: all-am
+--- a/src/switch/tcp/tcpsw.c
++++ b/src/switch/tcp/tcpsw.c
+@@ -35,6 +35,10 @@
+ #define MAX_PACKET (ATM_MAX_AAL5_PDU+sizeof(struct atmtcp_hdr))
+ #define BUFFER_SIZE (MAX_PACKET*2)
+
++int yywrap(void)
++{
++ return 1;
++}
+
+ typedef struct _table {
+ struct _link *out; /* output port */
+--- a/src/test/Makefile.am
++++ b/src/test/Makefile.am
+@@ -20,7 +20,7 @@ br_SOURCES = br.c
+ bw_SOURCES = bw.c
+ isp_SOURCES = isp.c isp.h ispl_y.y ispl_l.l
+ isp_XTRAS = $(LDADD)
+-isp_LDADD = $(isp_XTRAS) -lfl
++isp_LDADD = $(isp_XTRAS)
+ isp_DEPENDENCIES = $(isp_XTRAS)
+ window_SOURCES = window.c
+
+--- a/src/test/Makefile.in
++++ b/src/test/Makefile.in
+@@ -283,7 +283,7 @@ br_SOURCES = br.c
+ bw_SOURCES = bw.c
+ isp_SOURCES = isp.c isp.h ispl_y.y ispl_l.l
+ isp_XTRAS = $(LDADD)
+-isp_LDADD = $(isp_XTRAS) -lfl
++isp_LDADD = $(isp_XTRAS)
+ isp_DEPENDENCIES = $(isp_XTRAS)
+ window_SOURCES = window.c
+ CLEANFILES = errnos.inc
+--- a/src/test/ispl_l.l
++++ b/src/test/ispl_l.l
+@@ -18,6 +18,11 @@
+ #include "ispl_y.h"
+
+
++int yywrap(void)
++{
++ return 1;
++}
++
+ static int lineno = 1;
+
+ %}
+--- a/src/qgen/ql_l.l
++++ b/src/qgen/ql_l.l
+@@ -11,6 +11,11 @@
+ #include "ql_y.h"
+
+
++int yywrap(void)
++{
++ return 1;
++}
++
+ typedef struct _tree {
+ struct _tree *left,*right;
+ const char str[0];
+--- a/src/sigd/cfg_l.l
++++ b/src/sigd/cfg_l.l
+@@ -16,6 +16,10 @@
+
+ #include "cfg_y.h"
+
++int yywrap(void)
++{
++ return 1;
++}
+
+ static int lineno = 1;
+ static int token; /* f@#%ing flex doesn't grok return after BEGIN */
diff --git a/package/linux-atm/patches/300-objcopy_path.patch b/package/linux-atm/patches/300-objcopy_path.patch
new file mode 100644
index 000000000..4f11516b2
--- /dev/null
+++ b/package/linux-atm/patches/300-objcopy_path.patch
@@ -0,0 +1,40 @@
+--- a/src/extra/Makefile.am
++++ b/src/extra/Makefile.am
+@@ -7,6 +7,8 @@ EXTRA_DIST = linux-atm.spec.in \
+ BUILT_SOURCES = pca200e.bin pca200e_ecd.bin2 sba200e_ecd.bin2
+ CLEANFILES = pca200e.bin pca200e_ecd.bin2 sba200e_ecd.bin2
+
++OBJCOPY = objcopy
++
+ install-exec-hook:
+ $(MKDIR_P) $(DESTDIR)/lib/firmware
+ $(INSTALL_DATA) $(srcdir)/pca200e.bin $(DESTDIR)/lib/firmware
+@@ -14,7 +16,7 @@ install-exec-hook:
+ $(INSTALL_DATA) $(srcdir)/sba200e_ecd.bin2 $(DESTDIR)/lib/firmware
+
+ %.bin %.bin2: %.data
+- objcopy -Iihex $< -Obinary $@.gz
++ $(OBJCOPY) -Iihex $< -Obinary $@.gz
+ gzip -n -df $@.gz
+
+
+--- a/src/extra/Makefile.in
++++ b/src/extra/Makefile.in
+@@ -187,6 +187,8 @@ CLEANFILES = pca200e.bin pca200e_ecd.bin
+ all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
++OBJCOPY = objcopy
++
+ .SUFFIXES:
+ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+@@ -385,7 +387,7 @@ install-exec-hook:
+ $(INSTALL_DATA) $(srcdir)/sba200e_ecd.bin2 $(DESTDIR)/lib/firmware
+
+ %.bin %.bin2: %.data
+- objcopy -Iihex $< -Obinary $@.gz
++ $(OBJCOPY) -Iihex $< -Obinary $@.gz
+ gzip -n -df $@.gz
+
+ # Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/package/ltq-dsl-app/Config.in b/package/ltq-dsl-app/Config.in
new file mode 100644
index 000000000..728fe65b3
--- /dev/null
+++ b/package/ltq-dsl-app/Config.in
@@ -0,0 +1,9 @@
+config LTQ_DSL_ENABLE_SOAP
+ bool "Enable SOAP support"
+ depends on PACKAGE_ltq-dsl-app
+ default n
+
+config LTQ_DSL_ENABLE_DSL_EVENT_POLLING
+ bool "Include Event Polling support"
+ depends on PACKAGE_ltq-dsl-app
+ default n
diff --git a/package/ltq-dsl-app/Makefile b/package/ltq-dsl-app/Makefile
new file mode 100644
index 000000000..32608236d
--- /dev/null
+++ b/package/ltq-dsl-app/Makefile
@@ -0,0 +1,97 @@
+#
+# Copyright (C) 2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=dsl_cpe_control_danube
+PKG_VERSION:=3.24.4.4
+PKG_RELEASE:=1
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_BUILD_DIR:=$(BUILD_DIR)/dsl_cpe_control-$(PKG_VERSION)
+PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources/
+PKG_MD5SUM:=ee315306626b68794d3d3636dabfe161
+
+PKG_CONFIG_DEPENDS:=\
+ CONFIG_LTQ_DSL_ENABLE_SOAP \
+ CONFIG_LTQ_DSL_ENABLE_DSL_EVENT_POLLING
+
+include $(INCLUDE_DIR)/package.mk
+
+PKG_BUILD_DEPENDS:=TARGET_lantiq_danube:kmod-ltq-dsl-danube TARGET_lantiq_ar9:kmod-ltq-dsl-ar9 \
+ TARGET_lantiq_vr9:kmod-ltq-dsl-vr9 TARGET_lantiq_ase:kmod-ltq-dsl-ase
+
+define Package/ltq-dsl-app
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=Lantiq DSL userland tool
+ URL:=http://www.lantiq.com/
+ DEPENDS:=@TARGET_lantiq&&!(TARGET_lantiq_falcon||TARGET_lantiq_falcon_stable) +libpthread
+ MAINTAINER:=John Crispin <blogic@openwrt.org>
+ MENU:=1
+endef
+
+define Package/ltq-dsl-app/description
+ Infineon DSL CPE API for Amazon SE, Danube and Vinax.
+endef
+
+define Package/ltq-dsl-app/config
+ source "$(SOURCE)/Config.in"
+endef
+
+LTQ_DSL_MAX_DEVICE=1
+LTQ_DSL_LINES_PER_DEVICE=1
+LTQ_DSL_CHANNELS_PER_LINE=1
+
+CONFIGURE_ARGS += \
+ --with-max-device="$(LTQ_DSL_MAX_DEVICE)" \
+ --with-lines-per-device="$(LTQ_DSL_LINES_PER_DEVICE)" \
+ --with-channels-per-line="$(LTQ_DSL_CHANNELS_PER_LINE)" \
+ --enable-danube \
+ --enable-driver-include="-I$(STAGING_DIR)/usr/include" \
+ --enable-debug-prints \
+ --enable-add-appl-cflags="-DMAX_CLI_PIPES=2" \
+ --enable-cli-support \
+ --enable-cmv-scripts \
+ --enable-debug-tool-interface \
+ --enable-adsl-led \
+ --enable-dsl-ceoc \
+ --enable-script-notification \
+ --enable-dsl-pm \
+ --enable-dsl-pm-total \
+ --enable-dsl-pm-history \
+ --enable-dsl-pm-showtime \
+ --enable-dsl-pm-channel-counters \
+ --enable-dsl-pm-datapath-counters \
+ --enable-dsl-pm-line-counters \
+ --enable-dsl-pm-channel-thresholds \
+ --enable-dsl-pm-datapath-thresholds \
+ --enable-dsl-pm-line-thresholds \
+ --enable-dsl-pm-optional-parameters
+
+ifeq ($(CONFIG_LTQ_DSL_ENABLE_SOAP),y)
+CONFIGURE_ARGS += \
+ --enable-soap-support
+endif
+
+ifeq ($(CONFIG_LTQ_DSL_ENABLE_DSL_EVENT_POLLING),y)
+CONFIGURE_ARGS += \
+ --enable-dsl-event-polling
+endif
+
+TARGET_CFLAGS += -I$(LINUX_DIR)/include
+
+define Package/ltq-dsl-app/install
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/dsl_control $(1)/etc/init.d/
+
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/dsl_cpe_control $(1)/sbin
+ $(INSTALL_BIN) ./files/dsl_notify.sh $(1)/sbin
+endef
+
+$(eval $(call BuildPackage,ltq-dsl-app))
diff --git a/package/ltq-dsl-app/files/dsl_control b/package/ltq-dsl-app/files/dsl_control
new file mode 100644
index 000000000..02e89a0fd
--- /dev/null
+++ b/package/ltq-dsl-app/files/dsl_control
@@ -0,0 +1,316 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2008 OpenWrt.org
+START=99
+
+. /lib/functions.sh
+
+EXTRA_COMMANDS="status lucistat"
+EXTRA_HELP=" status Get DSL status information
+ lucistat Get status information if lua friendly format"
+
+SERVICE_DAEMONIZE=1
+SERVICE_WRITE_PID=1
+
+#
+# Basic functions to send CLI commands to the dsl_cpe_control daemon
+#
+dsl_cmd() {
+ killall -0 dsl_cpe_control && (
+ echo "$@" > /tmp/pipe/dsl_cpe0_cmd
+ cat /tmp/pipe/dsl_cpe0_ack
+ )
+}
+dsl_val() {
+ echo $(expr "$1" : '.*'$2'=\([-\.[:alnum:]]*\).*')
+}
+
+#
+# Simple divide by 10 routine to cope with one decimal place
+#
+dbt() {
+ local a=$(expr $1 / 10)
+ local b=$(expr $1 % 10)
+ echo "${a}.${b}"
+}
+#
+# Take a number and convert to k or meg
+#
+scale() {
+ local val=$1
+ local a
+ local b
+
+ if [ "$val" -gt 1000000 ]; then
+ a=$(expr $val / 1000)
+ b=$(expr $a % 1000)
+ a=$(expr $a / 1000)
+ printf "%d.%03d Mb" ${a} ${b}
+ elif [ "$val" -gt 1000 ]; then
+ a=$(expr $val / 1000)
+ printf "%d Kb" ${a}
+ else
+ echo "${val} b"
+ fi
+}
+
+#
+# Read the data rates for both directions
+#
+data_rates() {
+ local csg
+ local dru
+ local drd
+ local sdru
+ local sdrd
+
+ csg=$(dsl_cmd g997csg 0 1)
+ drd=$(dsl_val "$csg" ActualDataRate)
+
+ csg=$(dsl_cmd g997csg 0 0)
+ dru=$(dsl_val "$csg" ActualDataRate)
+
+ [ -z "$drd" ] && drd=0
+ [ -z "$dru" ] && dru=0
+
+ sdrd=$(scale $drd)
+ sdru=$(scale $dru)
+
+ if [ "$action" = "lucistat" ]; then
+ echo "dsl.data_rate_down=$drd"
+ echo "dsl.data_rate_up=$dru"
+ echo "dsl.data_rate_down_s=\"$sdrd\""
+ echo "dsl.data_rate_up_s=\"$sdru\""
+ else
+ echo "Data Rate: ${sdrd}/s / ${sdru}/s"
+ fi
+}
+
+#
+# Chipset
+#
+chipset() {
+ local vig
+ local cs
+ local csv
+
+ vig=$(dsl_cmd vig)
+ cs=$(dsl_val "$vig" DSL_ChipSetType)
+ csv=$(dsl_val "$vig" DSL_ChipSetHWVersion)
+
+ if [ "$action" = "lucistat" ]; then
+ echo "dsl.chipset=\"${cs} ${csv}\""
+ else
+ echo "Chipset: ${cs} ${csv}"
+ fi
+}
+
+#
+# Work out how long the line has been up
+#
+line_uptime() {
+ local ccsg
+ local et
+ local etr
+ local d
+ local h
+ local m
+ local s
+ local rc=""
+
+ ccsg=$(dsl_cmd pmccsg 0 0 0)
+ et=$(dsl_val "$ccsg" nElapsedTime)
+
+ [ -z "$et" ] && et=0
+
+ if [ "$action" = "lucistat" ]; then
+ echo "dsl.line_uptime=${et}"
+ return
+ fi
+
+ d=$(expr $et / 86400)
+ etr=$(expr $et % 86400)
+ h=$(expr $etr / 3600)
+ etr=$(expr $etr % 3600)
+ m=$(expr $etr / 60)
+ s=$(expr $etr % 60)
+
+
+ [ "${d}${h}${m}${s}" -ne 0 ] && rc="${s}s"
+ [ "${d}${h}${m}" -ne 0 ] && rc="${m}m ${rc}"
+ [ "${d}${h}" -ne 0 ] && rc="${h}h ${rc}"
+ [ "${d}" -ne 0 ] && rc="${d}d ${rc}"
+
+ [ -z "$rc" ] && rc="down"
+ echo "Line Uptime: ${rc}"
+}
+
+#
+# Get noise and attenuation figures
+#
+line_data() {
+ local lsg
+ local latnu
+ local latnd
+ local snru
+ local snrd
+
+ lsg=$(dsl_cmd g997lsg 1 1)
+ latnd=$(dsl_val "$lsg" LATN)
+ snrd=$(dsl_val "$lsg" SNR)
+
+ lsg=$(dsl_cmd g997lsg 0 1)
+ latnu=$(dsl_val "$lsg" LATN)
+ snru=$(dsl_val "$lsg" SNR)
+
+ [ -z "$latnd" ] && latnd=0
+ [ -z "$latnu" ] && latnu=0
+ [ -z "$snrd" ] && snrd=0
+ [ -z "$snru" ] && snru=0
+
+ latnd=$(dbt $latnd)
+ latnu=$(dbt $latnu)
+ snrd=$(dbt $snrd)
+ snru=$(dbt $snru)
+
+ if [ "$action" = "lucistat" ]; then
+ echo "dsl.line_attenuation_down=$latnd"
+ echo "dsl.line_attenuation_up=$latnu"
+ echo "dsl.noise_margin_down=$snrd"
+ echo "dsl.noise_margin_up=$snru"
+ else
+ echo "Line Attenuation: ${latnd}dB / ${latnu}dB"
+ echo "Noise Margin: ${snrd}dB / ${snru}dB"
+ fi
+}
+
+#
+# Is the line up? Or what state is it in?
+#
+line_state() {
+ local lsg=$(dsl_cmd lsg)
+ local ls=$(dsl_val "$lsg" nLineState);
+ local s;
+
+ case "$ls" in
+ "0x0") s="not initialized" ;;
+ "0x1") s="exception" ;;
+ "0x10") s="not updated" ;;
+ "0xff") s="idle request" ;;
+ "0x100") s="idle" ;;
+ "0x1ff") s="silent request" ;;
+ "0x200") s="silent" ;;
+ "0x300") s="handshake" ;;
+ "0x380") s="full_init" ;;
+ "0x400") s="discovery" ;;
+ "0x500") s="training" ;;
+ "0x600") s="analysis" ;;
+ "0x700") s="exchange" ;;
+ "0x800") s="showtime_no_sync" ;;
+ "0x801") s="showtime_tc_sync" ;;
+ "0x900") s="fastretrain" ;;
+ "0xa00") s="lowpower_l2" ;;
+ "0xb00") s="loopdiagnostic active" ;;
+ "0xb10") s="loopdiagnostic data exchange" ;;
+ "0xb20") s="loopdiagnostic data request" ;;
+ "0xc00") s="loopdiagnostic complete" ;;
+ "0x1000000") s="test" ;;
+ "0xd00") s="resync" ;;
+ "0x3c0") s="short init entry" ;;
+ "") s="not running daemon"; ls="0xfff" ;;
+ *) s="unknown" ;;
+ esac
+
+ if [ $action = "lucistat" ]; then
+ echo "dsl.line_state_num=$ls"
+ echo "dsl.line_state_detail=\"$s\""
+ if [ "$ls" = "0x801" ]; then
+ echo "dsl.line_state=\"UP\""
+ else
+ echo "dsl.line_state=\"DOWN\""
+ fi
+ else
+ if [ "$ls" = "0x801" ]; then
+ echo "Line State: UP [$ls: $s]"
+ else
+ echo "Line State: DOWN [$ls: $s]"
+ fi
+ fi
+}
+
+#
+# Main status routine
+#
+status() {
+ chipset
+ line_state
+ data_rates
+ line_data
+ line_uptime
+}
+
+#
+# Luci (lua) compatible version that's easy to parse
+#
+lucistat() {
+ echo "local dsl={}"
+ status
+ echo "return dsl"
+}
+
+
+annex_b=10_00_10_00_00_04_00_00
+annex_bdmt=10_00_00_00_00_00_00_00
+annex_b2=00_00_10_00_00_00_00_00
+annex_b2p=00_00_00_00_00_04_00_00
+annex_a=04_01_04_00_00_01_00_00
+annex_at1=01_00_00_00_00_00_00_00
+annex_alite=00_01_00_00_00_00_00_00
+annex_admt=04_00_00_00_00_00_00_00
+annex_a2=00_00_04_00_00_00_00_00
+annex_a2p=00_00_00_00_00_01_00_00
+annex_l=00_00_00_00_04_00_00_00
+annex_m=00_00_00_00_40_00_04_00
+annex_m2=00_00_00_00_40_00_00_00
+annex_m2p=00_00_00_00_00_00_04_00
+
+#
+# Simple start routine
+#
+start() {
+ local annex
+ local fwannex
+ local xtu
+ config_load network
+ config_get annex adsl annex
+ config_get fwannex adsl fwannex
+
+ # get xtu
+ eval "xtu=\"\${annex_$annex}\""
+
+ # check for invalid annex mode
+ [ -n "${annex}" -a -z "${xtu}" ] &&
+ echo "unknown annex mode $annex"
+
+ # check for invalid fw annex mode
+ [[ "$fwannex" != "a" && "$fwannex" != "b" ]] &&
+ echo "invalid fwannex: $fwannex"
+
+ # start CPE dsl daemon in the background
+ service_start /sbin/dsl_cpe_control -i${xtu} \
+ -n /sbin/dsl_notify.sh \
+ -f /lib/firmware/dsl-fw-${fwannex}.bin
+}
+
+#
+# For stop we want to simulate the notification call for when
+# the line goes down, so that we can stop the ppp link before
+# we die.
+#
+stop() {
+ DSL_NOTIFICATION_TYPE="DSL_INTERFACE_STATUS" \
+ DSL_INTERFACE_STATUS="DOWN" \
+ /sbin/dsl_notify.sh
+
+ service_stop /sbin/dsl_cpe_control
+}
+
diff --git a/package/ltq-dsl-app/files/dsl_notify.sh b/package/ltq-dsl-app/files/dsl_notify.sh
new file mode 100644
index 000000000..5e9f3964e
--- /dev/null
+++ b/package/ltq-dsl-app/files/dsl_notify.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+#
+# This script is called by dsl_cpe_control whenever there is a DSL event,
+# we only actually care about the DSL_INTERFACE_STATUS events as these
+# tell us the line has either come up or gone down.
+#
+# The rest of the code is basically the same at the atm hotplug code
+#
+
+[ "$DSL_NOTIFICATION_TYPE" = "DSL_INTERFACE_STATUS" ] || exit 0
+
+. /lib/functions.sh
+
+include /lib/network
+scan_interfaces
+
+local found=0
+local ifc
+for ifc in $interfaces; do
+ local up
+ config_get_bool up "$ifc" up 0
+
+ local auto
+ config_get_bool auto "$ifc" auto 1
+
+ local proto
+ config_get proto "$ifc" proto
+
+ if [ "$DSL_INTERFACE_STATUS" = "UP" ]; then
+ if [ "$proto" = "pppoa" ] && [ "$up" != 1 ] && [ "$auto" = 1 ]; then
+ found=1
+ ( sleep 1; ifup "$ifc" ) &
+ fi
+ else
+ if [ "$proto" = "pppoa" ] && [ "$up" = 1 ] && [ "$auto" = 1 ]; then
+ found=1
+ ( sleep 1; ifdown "$ifc" ) &
+ fi
+ fi
+done
+
+if [ "$found" != 1 ]; then
+ logger "Found no matching interface for DSL notification ($DSL_INTERFACE_STATUS)"
+fi
diff --git a/package/ltq-dsl/Config.in b/package/ltq-dsl/Config.in
new file mode 100644
index 000000000..6d9caf441
--- /dev/null
+++ b/package/ltq-dsl/Config.in
@@ -0,0 +1,5 @@
+config LANTIQ_DSL_DEBUG
+ bool "verbose debugging"
+ depends on PACKAGE_kmod-ltq-dsl
+ help
+ Say Y, if you need ltq-dsl to display debug messages.
diff --git a/package/ltq-dsl/Makefile b/package/ltq-dsl/Makefile
new file mode 100644
index 000000000..0e2a9328a
--- /dev/null
+++ b/package/ltq-dsl/Makefile
@@ -0,0 +1,178 @@
+#
+# Copyright (C) 2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=ltq-dsl
+PKG_BASE_NAME:=drv_dsl_cpe_api_danube
+PKG_VERSION:=3.24.4.4
+PKG_RELEASE:=3
+PKG_SOURCE:=$(PKG_BASE_NAME)-$(PKG_VERSION).tar.gz
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/drv_dsl_cpe_api-$(PKG_VERSION)
+PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources/
+PKG_MD5SUM:=c45bc531c1ed2ac80f68fb986b63bb87
+
+FW_NAME:=ltq-dsl-fw-0.1
+FW_MD5:=4700a36b66b955b4c5544227267356f4
+
+include $(INCLUDE_DIR)/package.mk
+
+define Download/ltq-dsl-fw
+ FILE:=$(FW_NAME).tar.bz2
+ MD5SUM:=$(FW_MD5)
+ URL:=http://mirror2.openwrt.org/sources/
+endef
+$(eval $(call Download,ltq-dsl-fw))
+
+define KernelPackage/ltq-dsl-template
+ SECTION:=sys
+ CATEGORY:=Kernel modules
+ SUBMENU:=Network Devices
+ TITLE:=Lantiq dsl driver for $(1)
+ URL:=http://www.lantiq.com/
+ VARIANT:=$(1)
+ DEPENDS:=@TARGET_lantiq_$(1) +kmod-atm
+ FILES:=$(PKG_BUILD_DIR)/src/mei/lantiq_mei.ko \
+ $(PKG_BUILD_DIR)/src/drv_dsl_cpe_api.ko \
+ $(PKG_BUILD_DIR)/src/mei/lantiq_atm.ko
+ AUTOLOAD:=$(call AutoLoad,50,lantiq_mei drv_dsl_cpe_api lantiq_atm)
+ MAINTAINER:=John Crispin <blogic@openwrt.org>
+endef
+
+KernelPackage/ltq-dsl-danube=$(call KernelPackage/ltq-dsl-template,danube)
+KernelPackage/ltq-dsl-ase=$(call KernelPackage/ltq-dsl-template,ase)
+KernelPackage/ltq-dsl-ar9=$(call KernelPackage/ltq-dsl-template,ar9)
+KernelPackage/ltq-dsl-vr9=$(call KernelPackage/ltq-dsl-template,vr9)
+
+define Package/kmod-ltq-dsl-firmware-template
+ TITLE+=Firmware Annex-$(1) $(2)
+ SECTION:=sys
+ CATEGORY:=Kernel modules
+ SUBMENU:=Network Devices
+ VARIANT:= $(1)-$(2)
+ URL:=http://www.lantiq.com/
+ DEPENDS:=@TARGET_lantiq_$(2) kmod-ltq-dsl-$(2)
+ MAINTAINER:=John Crispin <blogic@openwrt.org>
+endef
+
+Package/kmod-ltq-dsl-firmware-a-danube=$(call Package/kmod-ltq-dsl-firmware-template,a,danube)
+Package/kmod-ltq-dsl-firmware-b-danube=$(call Package/kmod-ltq-dsl-firmware-template,b,danube)
+Package/kmod-ltq-dsl-firmware-a-ase=$(call Package/kmod-ltq-dsl-firmware-template,a,ase)
+Package/kmod-ltq-dsl-firmware-b-ase=$(call Package/kmod-ltq-dsl-firmware-template,b,ase)
+Package/kmod-ltq-dsl-firmware-a-ar9=$(call Package/kmod-ltq-dsl-firmware-template,a,ar9)
+Package/kmod-ltq-dsl-firmware-b-ar9=$(call Package/kmod-ltq-dsl-firmware-template,b,ar9)
+Package/kmod-ltq-dsl-firmware-a-vr9=$(call Package/kmod-ltq-dsl-firmware-template,a,vr9)
+Package/kmod-ltq-dsl-firmware-b-vr9=$(call Package/kmod-ltq-dsl-firmware-template,b,vr9)
+
+define KernelPackage/ltq-dsl/description
+ Lantiq DSL driver for AR9, Amazon SE, Danube and VR9
+endef
+
+define KernelPackage/ltq-dsl/config
+ source "$(SOURCE)/Config.in"
+endef
+
+IFX_DSL_MAX_DEVICE=1
+IFX_DSL_LINES_PER_DEVICE=1
+IFX_DSL_CHANNELS_PER_LINE=1
+
+CONFIGURE_ARGS += --enable-kernel-include="$(LINUX_DIR)/include" \
+ --with-max-device="$(IFX_DSL_MAX_DEVICE)" \
+ --with-lines-per-device="$(IFX_DSL_LINES_PER_DEVICE)" \
+ --with-channels-per-line="$(IFX_DSL_CHANNELS_PER_LINE)" \
+ --disable-dsl-delt-static \
+ --disable-adsl-led \
+ --enable-dsl-ceoc \
+ --enable-dsl-pm \
+ --enable-dsl-pm-total \
+ --enable-dsl-pm-history \
+ --enable-dsl-pm-showtime \
+ --enable-dsl-pm-channel-counters \
+ --enable-dsl-pm-datapath-counters \
+ --enable-dsl-pm-line-counters \
+ --enable-dsl-pm-channel-thresholds \
+ --enable-dsl-pm-datapath-thresholds \
+ --enable-dsl-pm-line-thresholds \
+ --enable-dsl-pm-optional-parameters \
+ --enable-linux-26 \
+ --enable-kernelbuild="$(LINUX_DIR)" \
+ ARCH=$(LINUX_KARCH)
+
+CONFIG_TAG_danube:=DANUBE
+CONFIG_TAG_ase:=AMAZON_SE
+CONFIG_TAG_ar9:=AR9
+CONFIG_TAG_vr9:=VR9
+CONFIGURE_ARGS += --enable-add-drv-cflags="-DMODULE -DCONFIG_$(CONFIG_TAG_$(BUILD_VARIANT))"
+
+ifeq ($(BUILD_VARIANT),vr9)
+CONFIGURE_ARGS += --enable-vinax
+else
+CONFIGURE_ARGS += --enable-danube
+endif
+
+ifeq ($(CONFIG_LANTIQ_DSL_DEBUG),y)
+CONFIGURE_ARGS += \
+ --enable-debug=yes \
+ --enable-debug-prints=yes
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+EXTRA_CFLAGS = -fno-pic -mno-abicalls -mlong-calls -G 0
+
+define Build/Prepare
+ $(PKG_UNPACK)
+ $(INSTALL_DIR) $(PKG_BUILD_DIR)/src/mei/
+ $(CP) ./src/* $(PKG_BUILD_DIR)/src/mei/
+ $(Build/Patch)
+ $(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(FW_NAME).tar.bz2
+endef
+
+define Build/Configure
+ (cd $(PKG_BUILD_DIR); aclocal && autoconf && automake)
+ $(call Build/Configure/Default)
+endef
+
+define Build/Compile
+ cd $(LINUX_DIR); \
+ ARCH=mips CROSS_COMPILE="$(KERNEL_CROSS)" \
+ $(MAKE) BUILD_VARIANT=$(BUILD_VARIANT) M=$(PKG_BUILD_DIR)/src/mei/ V=1 modules
+ $(call Build/Compile/Default)
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api.h $(1)/usr/include
+ $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_ioctl.h $(1)/usr/include
+ $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_adslmib.h $(1)/usr/include
+ $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_adslmib_ioctl.h $(1)/usr/include
+ $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_g997.h $(1)/usr/include
+ $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_types.h $(1)/usr/include
+ $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_pm.h $(1)/usr/include
+ $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_error.h $(1)/usr/include
+ $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_danube_ctx.h $(1)/usr/include
+ $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_cmv_danube.h $(1)/usr/include
+endef
+
+define Package/kmod-ltq-dsl-firmware-$(BUILD_VARIANT)/install
+ $(INSTALL_DIR) $(1)/lib/firmware/
+ $(CP) $(PKG_BUILD_DIR)/$(FW_NAME)/ltq-dsl-fw-$(BUILD_VARIANT).bin $(1)/lib/firmware/dsl-fw-$(word 1, $(subst -, ,$(BUILD_VARIANT))).bin
+ ln -s /lib/firmware/dsl-fw-$(word 1, $(subst -, ,$(BUILD_VARIANT))).bin $(1)/lib/firmware/ModemHWE.bin
+endef
+
+$(eval $(call BuildPackage,kmod-ltq-dsl-firmware-a-danube))
+$(eval $(call BuildPackage,kmod-ltq-dsl-firmware-b-danube))
+$(eval $(call BuildPackage,kmod-ltq-dsl-firmware-a-ase))
+$(eval $(call BuildPackage,kmod-ltq-dsl-firmware-b-ase))
+$(eval $(call BuildPackage,kmod-ltq-dsl-firmware-a-ar9))
+$(eval $(call BuildPackage,kmod-ltq-dsl-firmware-b-ar9))
+#$(eval $(call BuildPackage,kmod-ltq-dsl-firmware-a-vr9))
+#$(eval $(call BuildPackage,kmod-ltq-dsl-firmware-b-vr9))
+$(eval $(call KernelPackage,ltq-dsl-danube))
+$(eval $(call KernelPackage,ltq-dsl-ase))
+$(eval $(call KernelPackage,ltq-dsl-ar9))
+#$(eval $(call KernelPackage,ltq-dsl-vr9))
diff --git a/package/ltq-dsl/patches/100-dsl_compat.patch b/package/ltq-dsl/patches/100-dsl_compat.patch
new file mode 100644
index 000000000..f892351a6
--- /dev/null
+++ b/package/ltq-dsl/patches/100-dsl_compat.patch
@@ -0,0 +1,125 @@
+--- a/src/include/drv_dsl_cpe_device_danube.h
++++ b/src/include/drv_dsl_cpe_device_danube.h
+@@ -24,7 +24,7 @@
+ #include "drv_dsl_cpe_simulator_danube.h"
+ #else
+ /* Include for the low level driver interface header file */
+-#include "asm/ifx/ifx_mei_bsp.h"
++#include "mei/ifxmips_mei_interface.h"
+ #endif /* defined(DSL_CPE_SIMULATOR_DRIVER) && defined(WIN32)*/
+
+ #define DSL_MAX_LINE_NUMBER 1
+--- a/src/common/drv_dsl_cpe_os_linux.c
++++ b/src/common/drv_dsl_cpe_os_linux.c
+@@ -11,6 +11,7 @@
+ #ifdef __LINUX__
+
+ #define DSL_INTERN
++#include <linux/device.h>
+
+ #include "drv_dsl_cpe_api.h"
+ #include "drv_dsl_cpe_api_ioctl.h"
+@@ -34,9 +35,13 @@
+ static DSL_ssize_t DSL_DRV_Write(DSL_DRV_file_t *pFile, const DSL_char_t * pBuf,
+ DSL_DRV_size_t nSize, DSL_DRV_offset_t * pLoff);
+
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
+ static DSL_int_t DSL_DRV_Ioctls(DSL_DRV_inode_t * pINode, DSL_DRV_file_t * pFile,
+ DSL_uint_t nCommand, unsigned long nArg);
+-
++#else
++static DSL_int_t DSL_DRV_Ioctls(DSL_DRV_file_t * pFile,
++ DSL_uint_t nCommand, unsigned long nArg);
++#endif
+ static int DSL_DRV_Open(DSL_DRV_inode_t * ino, DSL_DRV_file_t * fil);
+
+ static int DSL_DRV_Release(DSL_DRV_inode_t * ino, DSL_DRV_file_t * fil);
+@@ -72,7 +77,11 @@
+ open: DSL_DRV_Open,
+ release: DSL_DRV_Release,
+ write: DSL_DRV_Write,
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
+ ioctl: DSL_DRV_Ioctls,
++#else
++ unlocked_ioctl: DSL_DRV_Ioctls,
++#endif
+ poll: DSL_DRV_Poll
+ };
+ #else
+@@ -168,10 +177,17 @@
+ \return Success or failure.
+ \ingroup Internal
+ */
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
+ static DSL_int_t DSL_DRV_Ioctls(DSL_DRV_inode_t * pINode,
+ DSL_DRV_file_t * pFile,
+ DSL_uint_t nCommand,
+ unsigned long nArg)
++#else
++static DSL_int_t DSL_DRV_Ioctls(
++ DSL_DRV_file_t * pFile,
++ DSL_uint_t nCommand,
++ unsigned long nArg)
++#endif
+ {
+ DSL_int_t nErr=0;
+ DSL_boolean_t bIsInKernel;
+@@ -216,16 +232,7 @@
+ }
+ }
+ }
+-
+- if (pINode == DSL_NULL)
+- {
+- bIsInKernel = DSL_TRUE;
+- }
+- else
+- {
+- bIsInKernel = DSL_FALSE;
+- }
+-
++ bIsInKernel = DSL_FALSE;
+ if ( (_IOC_TYPE(nCommand) == DSL_IOC_MAGIC_CPE_API) ||
+ (_IOC_TYPE(nCommand) == DSL_IOC_MAGIC_CPE_API_G997) ||
+ (_IOC_TYPE(nCommand) == DSL_IOC_MAGIC_CPE_API_PM) ||
+@@ -1058,6 +1065,7 @@
+ /* Entry point of driver */
+ int __init DSL_ModuleInit(void)
+ {
++ struct class *dsl_class;
+ DSL_int_t i;
+
+ printk(DSL_DRV_CRLF DSL_DRV_CRLF "Infineon CPE API Driver version: %s" DSL_DRV_CRLF,
+@@ -1104,7 +1112,8 @@
+ }
+
+ DSL_DRV_DevNodeInit();
+-
++ dsl_class = class_create(THIS_MODULE, "dsl_cpe_api");
++ device_create(dsl_class, NULL, MKDEV(DRV_DSL_CPE_API_DEV_MAJOR, 0), NULL, "dsl_cpe_api");
+ return 0;
+ }
+
+--- a/src/include/drv_dsl_cpe_os_linux.h
++++ b/src/include/drv_dsl_cpe_os_linux.h
+@@ -17,17 +17,17 @@
+ #endif
+
+ #include <asm/ioctl.h>
+-#include <linux/autoconf.h>
++#include <generated/autoconf.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/ctype.h>
+ #include <linux/version.h>
+ #include <linux/spinlock.h>
+-
++#include <linux/sched.h>
+
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+- #include <linux/utsrelease.h>
++ #include <generated/utsrelease.h>
+ #endif
+
+ #include <linux/types.h>
diff --git a/package/ltq-dsl/patches/110-fix_status_polling_loop.patch b/package/ltq-dsl/patches/110-fix_status_polling_loop.patch
new file mode 100644
index 000000000..870943d95
--- /dev/null
+++ b/package/ltq-dsl/patches/110-fix_status_polling_loop.patch
@@ -0,0 +1,11 @@
+--- a/src/device/drv_dsl_cpe_device_danube.c
++++ b/src/device/drv_dsl_cpe_device_danube.c
+@@ -4069,7 +4069,7 @@ static DSL_Error_t DSL_DRV_DANUBE_XTUSys
+
+ DSL_CTX_WRITE(pContext, nErrCode, xtseCurr, xtseCurr);
+
+- for (nRetry = 0; nRetry < 20; nRetry++)
++ for (nRetry = 0; nRetry < 20 && bStatusUpdated == DSL_FALSE; nRetry++)
+ {
+ /* Get STAT1 info*/
+ nErrCode = DSL_DRV_DANUBE_CmvRead(pContext, DSL_CMV_GROUP_STAT,
diff --git a/package/ltq-dsl/patches/500-portability.patch b/package/ltq-dsl/patches/500-portability.patch
new file mode 100644
index 000000000..d74314c77
--- /dev/null
+++ b/package/ltq-dsl/patches/500-portability.patch
@@ -0,0 +1,227 @@
+--- a/configure.in
++++ b/configure.in
+@@ -310,7 +310,7 @@
+ AC_ARG_ENABLE(kernelbuild,
+ AC_HELP_STRING(--enable-kernel-build=x,Set the target kernel build path),
+ [
+- if test -e $enableval/include/linux/autoconf.h; then
++ if test -e $enableval/include/linux/autoconf.h -o -e $enableval/include/generated/autoconf.h; then
+ AC_SUBST([KERNEL_BUILD_PATH],[$enableval])
+ else
+ AC_MSG_ERROR([The kernel build directory is not valid or not configured!])
+@@ -333,12 +333,12 @@
+ echo Set the lib_ifxos include path $enableval
+ AC_SUBST([IFXOS_INCLUDE_PATH],[$enableval])
+ else
+- echo -e Set the default lib_ifxos include path $DEFAULT_IFXOS_INCLUDE_PATH
++ echo Set the default lib_ifxos include path $DEFAULT_IFXOS_INCLUDE_PATH
+ AC_SUBST([IFXOS_INCLUDE_PATH],[$DEFAULT_IFXOS_INCLUDE_PATH])
+ fi
+ ],
+ [
+- echo -e Set the default lib_ifxos include path $DEFAULT_IFXOS_INCLUDE_PATH
++ echo Set the default lib_ifxos include path $DEFAULT_IFXOS_INCLUDE_PATH
+ AC_SUBST([IFXOS_INCLUDE_PATH],[$DEFAULT_IFXOS_INCLUDE_PATH])
+ ]
+ )
+@@ -1702,73 +1702,73 @@
+ AC_SUBST([DISTCHECK_CONFIGURE_PARAMS],[$CONFIGURE_OPTIONS])
+
+ AC_CONFIG_COMMANDS_PRE([
+-echo -e "------------------------------------------------------------------------"
+-echo -e " Configuration for drv_dsl_cpe_api:"
+-echo -e " Configure model type: $DSL_CONFIG_MODEL_TYPE"
+-echo -e " Source code location: $srcdir"
+-echo -e " Compiler: $CC"
+-echo -e " Compiler c-flags: $CFLAGS"
+-echo -e " Extra compiler c-flags: $EXTRA_DRV_CFLAGS"
+-echo -e " Host System Type: $host"
+-echo -e " Install path: $prefix"
+-echo -e " Linux kernel include path: $KERNEL_INCL_PATH"
+-echo -e " Linux kernel build path: $KERNEL_BUILD_PATH"
+-echo -e " Linux kernel architecture: $KERNEL_ARCH"
+-echo -e " Include IFXOS: $INCLUDE_DSL_CPE_API_IFXOS_SUPPORT"
+-echo -e " IFXOS include path: $IFXOS_INCLUDE_PATH"
+-echo -e " Driver Include Path $DSL_DRIVER_INCL_PATH"
+-echo -e " DSL device: $DSL_DEVICE_NAME"
+-echo -e " Max device number: $DSL_DRV_MAX_DEVICE_NUMBER"
+-echo -e " Channels per line: $DSL_CHANNELS_PER_LINE"
+-echo -e " Build lib (only for kernel 2.6) $DSL_CPE_API_LIBRARY_BUILD_2_6"
+-echo -e " DSL data led flash frequency: $DSL_DATA_LED_FLASH_FREQUENCY Hz"
+-echo -e " Disable debug prints: $DSL_DEBUG_DISABLE"
+-echo -e " Preselection of max. debug level: $DSL_DBG_MAX_LEVEL_SET"
+-echo -e " Preselected max. debug level: $DSL_DBG_MAX_LEVEL_PRE"
+-echo -e " Include deprecated functions: $INCLUDE_DEPRECATED"
+-echo -e " Include Device Exception Codes: $INCLUDE_DEVICE_EXCEPTION_CODES"
+-echo -e " Include FW request support: $INCLUDE_FW_REQUEST_SUPPORT"
+-echo -e " Include ADSL trace buffer: $INCLUDE_DSL_CPE_TRACE_BUFFER"
+-echo -e " Include ADSL MIB: $INCLUDE_DSL_ADSL_MIB"
+-echo -e " Include ADSL LED: $INCLUDE_ADSL_LED"
+-echo -e " Include CEOC: $INCLUDE_DSL_CEOC"
+-echo -e " Include config get support: $INCLUDE_DSL_CONFIG_GET"
+-echo -e " Include System i/f configuration: $INCLUDE_DSL_SYSTEM_INTERFACE"
+-echo -e " Include Resource Statistics: $INCLUDE_DSL_RESOURCE_STATISTICS"
+-echo -e " Include Framing Parameters: $INCLUDE_DSL_FRAMING_PARAMETERS"
+-echo -e " Include G997 Line Inventory: $INCLUDE_DSL_G997_LINE_INVENTORY"
+-echo -e " Include G997 Framing Parameters: $INCLUDE_DSL_G997_FRAMING_PARAMETERS"
+-echo -e " Include G997 per tone data: $INCLUDE_DSL_G997_PER_TONE"
+-echo -e " Include G997 status: $INCLUDE_DSL_G997_STATUS"
+-echo -e " Include G997 alarm: $INCLUDE_DSL_G997_ALARM"
+-echo -e " Include DSL Bonding: $INCLUDE_DSL_BONDING"
+-echo -e " Include Misc Line Status $INCLUDE_DSL_CPE_MISC_LINE_STATUS"
+-echo -e " Include DELT: $INCLUDE_DSL_DELT"
+-echo -e " Include DELT data static storage: $DSL_CPE_STATIC_DELT_DATA"
+-echo -e " Include PM: $INCLUDE_DSL_PM"
+-echo -e " Include PM config: $INCLUDE_DSL_CPE_PM_CONFIG"
+-echo -e " Include PM total: $INCLUDE_DSL_CPE_PM_TOTAL_COUNTERS"
+-echo -e " Include PM history: $INCLUDE_DSL_CPE_PM_HISTORY"
+-echo -e " Include PM showtime: $INCLUDE_DSL_CPE_PM_SHOWTIME_COUNTERS"
+-echo -e " Include PM optional: $INCLUDE_DSL_CPE_PM_OPTIONAL_PARAMETERS"
+-echo -e " Include PM line: $INCLUDE_DSL_CPE_PM_LINE_COUNTERS"
+-echo -e " Include PM line event showtime: $INCLUDE_DSL_CPE_PM_LINE_EVENT_SHOWTIME_COUNTERS"
+-echo -e " Include PM channel: $INCLUDE_DSL_CPE_PM_CHANNEL_COUNTERS"
+-echo -e " Include PM channel extended: $INCLUDE_DSL_CPE_PM_CHANNEL_EXT_COUNTERS"
+-echo -e " Include PM data path: $INCLUDE_DSL_CPE_PM_DATA_PATH_COUNTERS"
+-echo -e " Include PM data path failure: $INCLUDE_DSL_CPE_PM_DATA_PATH_FAILURE_COUNTERS"
+-echo -e " Include PM ReTx: $INCLUDE_DSL_CPE_PM_RETX_COUNTERS"
+-echo -e " Include PM line threshold: $INCLUDE_DSL_CPE_PM_LINE_THRESHOLDS"
+-echo -e " Include PM channel threshold: $INCLUDE_DSL_CPE_PM_CHANNEL_THRESHOLDS"
+-echo -e " Include PM data path threshold: $INCLUDE_DSL_CPE_PM_DATA_PATH_THRESHOLDS"
+-echo -e " Include PM ReTx threshold: $INCLUDE_DSL_CPE_PM_RETX_THRESHOLDS"
+-echo -e " Include FW memory free support: $INCLUDE_DSL_FIRMWARE_MEMORY_FREE"
+-echo -e "----------------------- deprectated ! ----------------------------------"
+-echo -e " Include PM line failure: $INCLUDE_DSL_CPE_PM_LINE_FAILURE_COUNTERS"
+-echo -e ""
+-echo -e " Settings:"
+-echo -e " Configure options: $CONFIGURE_OPTIONS"
+-echo -e "------------------------------------------------------------------------"
++echo "------------------------------------------------------------------------"
++echo " Configuration for drv_dsl_cpe_api:"
++echo " Configure model type: $DSL_CONFIG_MODEL_TYPE"
++echo " Source code location: $srcdir"
++echo " Compiler: $CC"
++echo " Compiler c-flags: $CFLAGS"
++echo " Extra compiler c-flags: $EXTRA_DRV_CFLAGS"
++echo " Host System Type: $host"
++echo " Install path: $prefix"
++echo " Linux kernel include path: $KERNEL_INCL_PATH"
++echo " Linux kernel build path: $KERNEL_BUILD_PATH"
++echo " Linux kernel architecture: $KERNEL_ARCH"
++echo " Include IFXOS: $INCLUDE_DSL_CPE_API_IFXOS_SUPPORT"
++echo " IFXOS include path: $IFXOS_INCLUDE_PATH"
++echo " Driver Include Path $DSL_DRIVER_INCL_PATH"
++echo " DSL device: $DSL_DEVICE_NAME"
++echo " Max device number: $DSL_DRV_MAX_DEVICE_NUMBER"
++echo " Channels per line: $DSL_CHANNELS_PER_LINE"
++echo " Build lib (only for kernel 2.6) $DSL_CPE_API_LIBRARY_BUILD_2_6"
++echo " DSL data led flash frequency: $DSL_DATA_LED_FLASH_FREQUENCY Hz"
++echo " Disable debug prints: $DSL_DEBUG_DISABLE"
++echo " Preselection of max. debug level: $DSL_DBG_MAX_LEVEL_SET"
++echo " Preselected max. debug level: $DSL_DBG_MAX_LEVEL_PRE"
++echo " Include deprecated functions: $INCLUDE_DEPRECATED"
++echo " Include Device Exception Codes: $INCLUDE_DEVICE_EXCEPTION_CODES"
++echo " Include FW request support: $INCLUDE_FW_REQUEST_SUPPORT"
++echo " Include ADSL trace buffer: $INCLUDE_DSL_CPE_TRACE_BUFFER"
++echo " Include ADSL MIB: $INCLUDE_DSL_ADSL_MIB"
++echo " Include ADSL LED: $INCLUDE_ADSL_LED"
++echo " Include CEOC: $INCLUDE_DSL_CEOC"
++echo " Include config get support: $INCLUDE_DSL_CONFIG_GET"
++echo " Include System i/f configuration: $INCLUDE_DSL_SYSTEM_INTERFACE"
++echo " Include Resource Statistics: $INCLUDE_DSL_RESOURCE_STATISTICS"
++echo " Include Framing Parameters: $INCLUDE_DSL_FRAMING_PARAMETERS"
++echo " Include G997 Line Inventory: $INCLUDE_DSL_G997_LINE_INVENTORY"
++echo " Include G997 Framing Parameters: $INCLUDE_DSL_G997_FRAMING_PARAMETERS"
++echo " Include G997 per tone data: $INCLUDE_DSL_G997_PER_TONE"
++echo " Include G997 status: $INCLUDE_DSL_G997_STATUS"
++echo " Include G997 alarm: $INCLUDE_DSL_G997_ALARM"
++echo " Include DSL Bonding: $INCLUDE_DSL_BONDING"
++echo " Include Misc Line Status $INCLUDE_DSL_CPE_MISC_LINE_STATUS"
++echo " Include DELT: $INCLUDE_DSL_DELT"
++echo " Include DELT data static storage: $DSL_CPE_STATIC_DELT_DATA"
++echo " Include PM: $INCLUDE_DSL_PM"
++echo " Include PM config: $INCLUDE_DSL_CPE_PM_CONFIG"
++echo " Include PM total: $INCLUDE_DSL_CPE_PM_TOTAL_COUNTERS"
++echo " Include PM history: $INCLUDE_DSL_CPE_PM_HISTORY"
++echo " Include PM showtime: $INCLUDE_DSL_CPE_PM_SHOWTIME_COUNTERS"
++echo " Include PM optional: $INCLUDE_DSL_CPE_PM_OPTIONAL_PARAMETERS"
++echo " Include PM line: $INCLUDE_DSL_CPE_PM_LINE_COUNTERS"
++echo " Include PM line event showtime: $INCLUDE_DSL_CPE_PM_LINE_EVENT_SHOWTIME_COUNTERS"
++echo " Include PM channel: $INCLUDE_DSL_CPE_PM_CHANNEL_COUNTERS"
++echo " Include PM channel extended: $INCLUDE_DSL_CPE_PM_CHANNEL_EXT_COUNTERS"
++echo " Include PM data path: $INCLUDE_DSL_CPE_PM_DATA_PATH_COUNTERS"
++echo " Include PM data path failure: $INCLUDE_DSL_CPE_PM_DATA_PATH_FAILURE_COUNTERS"
++echo " Include PM ReTx: $INCLUDE_DSL_CPE_PM_RETX_COUNTERS"
++echo " Include PM line threshold: $INCLUDE_DSL_CPE_PM_LINE_THRESHOLDS"
++echo " Include PM channel threshold: $INCLUDE_DSL_CPE_PM_CHANNEL_THRESHOLDS"
++echo " Include PM data path threshold: $INCLUDE_DSL_CPE_PM_DATA_PATH_THRESHOLDS"
++echo " Include PM ReTx threshold: $INCLUDE_DSL_CPE_PM_RETX_THRESHOLDS"
++echo " Include FW memory free support: $INCLUDE_DSL_FIRMWARE_MEMORY_FREE"
++echo "----------------------- deprectated ! ----------------------------------"
++echo " Include PM line failure: $INCLUDE_DSL_CPE_PM_LINE_FAILURE_COUNTERS"
++echo ""
++echo " Settings:"
++echo " Configure options: $CONFIGURE_OPTIONS"
++echo "------------------------------------------------------------------------"
+ ])
+
+ AC_CONFIG_FILES([Makefile src/Makefile])
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -303,7 +303,7 @@
+ drv_dsl_cpe_api_OBJS = "$(subst .c,.o,$(filter %.c,$(drv_dsl_cpe_api_SOURCES)))"
+
+ drv_dsl_cpe_api.ko: $(drv_dsl_cpe_api_SOURCES)
+- @echo -e "drv_dsl_cpe_api: Making Linux 2.6.x kernel object"
++ @echo "drv_dsl_cpe_api: Making Linux 2.6.x kernel object"
+ if test ! -e common/drv_dsl_cpe_api.c ; then \
+ echo "copy source files (as links only!)"; \
+ for f in $(filter %.c,$(drv_dsl_cpe_api_SOURCES)); do \
+@@ -311,10 +311,10 @@
+ cp -s $(addprefix @abs_srcdir@/,$$f) $(PWD)/`dirname $$f`/ ; \
+ done \
+ fi
+- @echo -e "# drv_dsl_cpe_api: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild
+- @echo -e "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild
+- @echo -e "$(subst .ko,,$@)-y := $(drv_dsl_cpe_api_OBJS)" >> $(PWD)/Kbuild
+- @echo -e "EXTRA_CFLAGS := $(CFLAGS) -DHAVE_CONFIG_H $(drv_dsl_cpe_api_CFLAGS) $(DSL_DRIVER_INCL_PATH) $(IFXOS_INCLUDE_PATH) -I@abs_srcdir@/include -I$(PWD)/include" >> $(PWD)/Kbuild
++ @echo "# drv_dsl_cpe_api: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild
++ @echo "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild
++ @echo "$(subst .ko,,$@)-y := $(drv_dsl_cpe_api_OBJS)" >> $(PWD)/Kbuild
++ @echo "EXTRA_CFLAGS := $(CFLAGS) -DHAVE_CONFIG_H $(drv_dsl_cpe_api_CFLAGS) $(DSL_DRIVER_INCL_PATH) $(IFXOS_INCLUDE_PATH) -I@abs_srcdir@/include -I$(PWD)/include" >> $(PWD)/Kbuild
+ $(MAKE) ARCH=@KERNEL_ARCH@ -C @KERNEL_BUILD_PATH@ O=@KERNEL_BUILD_PATH@ M=$(PWD) modules
+
+ clean-generic:
+--- a/src/include/drv_dsl_cpe_os_linux.h
++++ b/src/include/drv_dsl_cpe_os_linux.h
+@@ -16,8 +16,6 @@
+ extern "C" {
+ #endif
+
+-#include <asm/ioctl.h>
+-#include <generated/autoconf.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+@@ -26,8 +24,10 @@
+ #include <linux/spinlock.h>
+ #include <linux/sched.h>
+
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+- #include <generated/utsrelease.h>
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
++#include <linux/utsrelease.h>
++#else
++#include <generated/utsrelease.h>
+ #endif
+
+ #include <linux/types.h>
+@@ -39,7 +39,8 @@
+ #include <linux/delay.h>
+ #include <linux/poll.h>
+ #include <asm/uaccess.h>
+-#include <linux/smp_lock.h>
++//#include <linux/smp_lock.h>
++#include <asm/ioctl.h>
+
+ #ifdef INCLUDE_DSL_CPE_API_IFXOS_SUPPORT
+ /** IFXOS includes*/
diff --git a/package/ltq-dsl/src/Makefile b/package/ltq-dsl/src/Makefile
new file mode 100644
index 000000000..44d2efbc0
--- /dev/null
+++ b/package/ltq-dsl/src/Makefile
@@ -0,0 +1,23 @@
+obj-m = lantiq_mei.o lantiq_atm.o
+lantiq_atm-objs := ifxmips_atm_core.o
+
+ifeq ($(BUILD_VARIANT),danube)
+ CFLAGS_MODULE+=-DCONFIG_DANUBE
+ EXTRA_CFLAGS+=-DCONFIG_DANUBE
+ lantiq_atm-objs += ifxmips_atm_danube.o
+endif
+ifeq ($(BUILD_VARIANT),ase)
+ CFLAGS_MODULE+=-DCONFIG_AMAZON_SE
+ EXTRA_CFLAGS+=-DCONFIG_AMAZON_SE
+ lantiq_atm-objs += ifxmips_atm_amazon_se.o
+endif
+ifeq ($(BUILD_VARIANT),ar9)
+ CFLAGS_MODULE+=-DCONFIG_AR9
+ EXTRA_CFLAGS+=-DCONFIG_AR9
+ lantiq_atm-objs += ifxmips_atm_ar9.o
+endif
+ifeq ($(BUILD_VARIANT),vr9)
+ CFLAGS_MODULE+=-DCONFIG_VR9
+ EXTRA_CFLAGS+=-DCONFIG_VR9
+ lantiq_atm-objs += ifxmips_atm_vr9.o
+endif
diff --git a/package/ltq-dsl/src/ifx_atm.h b/package/ltq-dsl/src/ifx_atm.h
new file mode 100644
index 000000000..bf045a975
--- /dev/null
+++ b/package/ltq-dsl/src/ifx_atm.h
@@ -0,0 +1,196 @@
+/******************************************************************************
+**
+** FILE NAME : ifx_atm.h
+** PROJECT : UEIP
+** MODULES : ATM
+**
+** DATE : 17 Jun 2009
+** AUTHOR : Xu Liang
+** DESCRIPTION : Global ATM driver header file
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 07 JUL 2009 Xu Liang Init Version
+*******************************************************************************/
+
+#ifndef IFX_ATM_H
+#define IFX_ATM_H
+
+
+
+/*!
+ \defgroup IFX_ATM UEIP Project - ATM driver module
+ \brief UEIP Project - ATM driver module, support Danube, Amazon-SE, AR9, VR9.
+ */
+
+/*!
+ \defgroup IFX_ATM_IOCTL IOCTL Commands
+ \ingroup IFX_ATM
+ \brief IOCTL Commands used by user application.
+ */
+
+/*!
+ \defgroup IFX_ATM_STRUCT Structures
+ \ingroup IFX_ATM
+ \brief Structures used by user application.
+ */
+
+/*!
+ \file ifx_atm.h
+ \ingroup IFX_ATM
+ \brief ATM driver header file
+ */
+
+
+
+/*
+ * ####################################
+ * Definition
+ * ####################################
+ */
+
+/*!
+ \addtogroup IFX_ATM_STRUCT
+ */
+/*@{*/
+
+/*
+ * ATM MIB
+ */
+
+/*!
+ \struct atm_cell_ifEntry_t
+ \brief Structure used for Cell Level MIB Counters.
+
+ User application use this structure to call IOCTL command "PPE_ATM_MIB_CELL".
+ */
+typedef struct {
+ __u32 ifHCInOctets_h; /*!< byte counter of ingress cells (upper 32 bits, total 64 bits) */
+ __u32 ifHCInOctets_l; /*!< byte counter of ingress cells (lower 32 bits, total 64 bits) */
+ __u32 ifHCOutOctets_h; /*!< byte counter of egress cells (upper 32 bits, total 64 bits) */
+ __u32 ifHCOutOctets_l; /*!< byte counter of egress cells (lower 32 bits, total 64 bits) */
+ __u32 ifInErrors; /*!< counter of error ingress cells */
+ __u32 ifInUnknownProtos; /*!< counter of unknown ingress cells */
+ __u32 ifOutErrors; /*!< counter of error egress cells */
+} atm_cell_ifEntry_t;
+
+/*!
+ \struct atm_aal5_ifEntry_t
+ \brief Structure used for AAL5 Frame Level MIB Counters.
+
+ User application use this structure to call IOCTL command "PPE_ATM_MIB_AAL5".
+ */
+typedef struct {
+ __u32 ifHCInOctets_h; /*!< byte counter of ingress packets (upper 32 bits, total 64 bits) */
+ __u32 ifHCInOctets_l; /*!< byte counter of ingress packets (lower 32 bits, total 64 bits) */
+ __u32 ifHCOutOctets_h; /*!< byte counter of egress packets (upper 32 bits, total 64 bits) */
+ __u32 ifHCOutOctets_l; /*!< byte counter of egress packets (lower 32 bits, total 64 bits) */
+ __u32 ifInUcastPkts; /*!< counter of ingress packets */
+ __u32 ifOutUcastPkts; /*!< counter of egress packets */
+ __u32 ifInErrors; /*!< counter of error ingress packets */
+ __u32 ifInDiscards; /*!< counter of dropped ingress packets */
+ __u32 ifOutErros; /*!< counter of error egress packets */
+ __u32 ifOutDiscards; /*!< counter of dropped egress packets */
+} atm_aal5_ifEntry_t;
+
+/*!
+ \struct atm_aal5_vcc_t
+ \brief Structure used for per PVC AAL5 Frame Level MIB Counters.
+
+ This structure is a part of structure "atm_aal5_vcc_x_t".
+ */
+typedef struct {
+ __u32 aal5VccCrcErrors; /*!< counter of ingress packets with CRC error */
+ __u32 aal5VccSarTimeOuts; /*!< counter of ingress packets with Re-assemble timeout */ //no timer support yet
+ __u32 aal5VccOverSizedSDUs; /*!< counter of oversized ingress packets */
+} atm_aal5_vcc_t;
+
+/*!
+ \struct atm_aal5_vcc_x_t
+ \brief Structure used for per PVC AAL5 Frame Level MIB Counters.
+
+ User application use this structure to call IOCTL command "PPE_ATM_MIB_VCC".
+ */
+typedef struct {
+ int vpi; /*!< VPI of the VCC to get MIB counters */
+ int vci; /*!< VCI of the VCC to get MIB counters */
+ atm_aal5_vcc_t mib_vcc; /*!< structure to get MIB counters */
+} atm_aal5_vcc_x_t;
+
+/*@}*/
+
+
+
+/*
+ * ####################################
+ * IOCTL
+ * ####################################
+ */
+
+/*!
+ \addtogroup IFX_ATM_IOCTL
+ */
+/*@{*/
+
+/*
+ * ioctl Command
+ */
+/*!
+ \brief ATM IOCTL Magic Number
+ */
+#define PPE_ATM_IOC_MAGIC 'o'
+/*!
+ \brief ATM IOCTL Command - Get Cell Level MIB Counters
+
+ This command is obsolete. User can get cell level MIB from DSL API.
+ This command uses structure "atm_cell_ifEntry_t" as parameter for output of MIB counters.
+ */
+#define PPE_ATM_MIB_CELL _IOW(PPE_ATM_IOC_MAGIC, 0, atm_cell_ifEntry_t)
+/*!
+ \brief ATM IOCTL Command - Get AAL5 Level MIB Counters
+
+ Get AAL5 packet counters.
+ This command uses structure "atm_aal5_ifEntry_t" as parameter for output of MIB counters.
+ */
+#define PPE_ATM_MIB_AAL5 _IOW(PPE_ATM_IOC_MAGIC, 1, atm_aal5_ifEntry_t)
+/*!
+ \brief ATM IOCTL Command - Get Per PVC MIB Counters
+
+ Get AAL5 packet counters for each PVC.
+ This command uses structure "atm_aal5_vcc_x_t" as parameter for input of VPI/VCI information and output of MIB counters.
+ */
+#define PPE_ATM_MIB_VCC _IOWR(PPE_ATM_IOC_MAGIC, 2, atm_aal5_vcc_x_t)
+/*!
+ \brief Total Number of ATM IOCTL Commands
+ */
+#define PPE_ATM_IOC_MAXNR 3
+
+/*@}*/
+
+
+
+/*
+ * ####################################
+ * API
+ * ####################################
+ */
+
+#ifdef __KERNEL__
+struct port_cell_info {
+ unsigned int port_num;
+ unsigned int tx_link_rate[2];
+};
+#endif
+
+
+
+#endif // IFX_ATM_H
+
diff --git a/package/ltq-dsl/src/ifxmips_atm.h b/package/ltq-dsl/src/ifxmips_atm.h
new file mode 100644
index 000000000..ed90b5d4d
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm.h
@@ -0,0 +1,172 @@
+/******************************************************************************
+**
+** FILE NAME : ifx_atm.h
+** PROJECT : UEIP
+** MODULES : ATM
+**
+** DATE : 17 Jun 2009
+** AUTHOR : Xu Liang
+** DESCRIPTION : Global ATM driver header file
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 07 JUL 2009 Xu Liang Init Version
+*******************************************************************************/
+
+#ifndef IFX_ATM_H
+#define IFX_ATM_H
+
+
+
+/*!
+ \defgroup IFX_ATM UEIP Project - ATM driver module
+ \brief UEIP Project - ATM driver module, support Danube, Amazon-SE, AR9, VR9.
+ */
+
+/*!
+ \defgroup IFX_ATM_IOCTL IOCTL Commands
+ \ingroup IFX_ATM
+ \brief IOCTL Commands used by user application.
+ */
+
+/*!
+ \defgroup IFX_ATM_STRUCT Structures
+ \ingroup IFX_ATM
+ \brief Structures used by user application.
+ */
+
+/*!
+ \file ifx_atm.h
+ \ingroup IFX_ATM
+ \brief ATM driver header file
+ */
+
+
+
+/*
+ * ####################################
+ * Definition
+ * ####################################
+ */
+
+/*!
+ \addtogroup IFX_ATM_STRUCT
+ */
+/*@{*/
+
+/*
+ * ATM MIB
+ */
+
+typedef struct {
+ __u32 ifHCInOctets_h; /*!< byte counter of ingress cells (upper 32 bits, total 64 bits) */
+ __u32 ifHCInOctets_l; /*!< byte counter of ingress cells (lower 32 bits, total 64 bits) */
+ __u32 ifHCOutOctets_h; /*!< byte counter of egress cells (upper 32 bits, total 64 bits) */
+ __u32 ifHCOutOctets_l; /*!< byte counter of egress cells (lower 32 bits, total 64 bits) */
+ __u32 ifInErrors; /*!< counter of error ingress cells */
+ __u32 ifInUnknownProtos; /*!< counter of unknown ingress cells */
+ __u32 ifOutErrors; /*!< counter of error egress cells */
+} atm_cell_ifEntry_t;
+
+typedef struct {
+ __u32 ifHCInOctets_h; /*!< byte counter of ingress packets (upper 32 bits, total 64 bits) */
+ __u32 ifHCInOctets_l; /*!< byte counter of ingress packets (lower 32 bits, total 64 bits) */
+ __u32 ifHCOutOctets_h; /*!< byte counter of egress packets (upper 32 bits, total 64 bits) */
+ __u32 ifHCOutOctets_l; /*!< byte counter of egress packets (lower 32 bits, total 64 bits) */
+ __u32 ifInUcastPkts; /*!< counter of ingress packets */
+ __u32 ifOutUcastPkts; /*!< counter of egress packets */
+ __u32 ifInErrors; /*!< counter of error ingress packets */
+ __u32 ifInDiscards; /*!< counter of dropped ingress packets */
+ __u32 ifOutErros; /*!< counter of error egress packets */
+ __u32 ifOutDiscards; /*!< counter of dropped egress packets */
+} atm_aal5_ifEntry_t;
+
+typedef struct {
+ __u32 aal5VccCrcErrors; /*!< counter of ingress packets with CRC error */
+ __u32 aal5VccSarTimeOuts; /*!< counter of ingress packets with Re-assemble timeout */ //no timer support yet
+ __u32 aal5VccOverSizedSDUs; /*!< counter of oversized ingress packets */
+} atm_aal5_vcc_t;
+
+typedef struct {
+ int vpi; /*!< VPI of the VCC to get MIB counters */
+ int vci; /*!< VCI of the VCC to get MIB counters */
+ atm_aal5_vcc_t mib_vcc; /*!< structure to get MIB counters */
+} atm_aal5_vcc_x_t;
+
+/*@}*/
+
+
+
+/*
+ * ####################################
+ * IOCTL
+ * ####################################
+ */
+
+/*!
+ \addtogroup IFX_ATM_IOCTL
+ */
+/*@{*/
+
+/*
+ * ioctl Command
+ */
+/*!
+ \brief ATM IOCTL Magic Number
+ */
+#define PPE_ATM_IOC_MAGIC 'o'
+/*!
+ \brief ATM IOCTL Command - Get Cell Level MIB Counters
+
+ This command is obsolete. User can get cell level MIB from DSL API.
+ This command uses structure "atm_cell_ifEntry_t" as parameter for output of MIB counters.
+ */
+#define PPE_ATM_MIB_CELL _IOW(PPE_ATM_IOC_MAGIC, 0, atm_cell_ifEntry_t)
+/*!
+ \brief ATM IOCTL Command - Get AAL5 Level MIB Counters
+
+ Get AAL5 packet counters.
+ This command uses structure "atm_aal5_ifEntry_t" as parameter for output of MIB counters.
+ */
+#define PPE_ATM_MIB_AAL5 _IOW(PPE_ATM_IOC_MAGIC, 1, atm_aal5_ifEntry_t)
+/*!
+ \brief ATM IOCTL Command - Get Per PVC MIB Counters
+
+ Get AAL5 packet counters for each PVC.
+ This command uses structure "atm_aal5_vcc_x_t" as parameter for input of VPI/VCI information and output of MIB counters.
+ */
+#define PPE_ATM_MIB_VCC _IOWR(PPE_ATM_IOC_MAGIC, 2, atm_aal5_vcc_x_t)
+/*!
+ \brief Total Number of ATM IOCTL Commands
+ */
+#define PPE_ATM_IOC_MAXNR 3
+
+/*@}*/
+
+
+
+/*
+ * ####################################
+ * API
+ * ####################################
+ */
+
+#ifdef __KERNEL__
+struct port_cell_info {
+ unsigned int port_num;
+ unsigned int tx_link_rate[2];
+};
+#endif
+
+
+
+#endif // IFX_ATM_H
+
diff --git a/package/ltq-dsl/src/ifxmips_atm_amazon_se.c b/package/ltq-dsl/src/ifxmips_atm_amazon_se.c
new file mode 100644
index 000000000..102881592
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_amazon_se.c
@@ -0,0 +1,324 @@
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_amazon_se.c
+** PROJECT : UEIP
+** MODULES : ATM
+**
+** DATE : 7 Jul 2009
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM driver common source file (core functions)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 07 JUL 2009 Xu Liang Init Version
+*******************************************************************************/
+
+
+
+/*
+ * ####################################
+ * Head File
+ * ####################################
+ */
+
+/*
+ * Common Head File
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/clk.h>
+#include <asm/delay.h>
+
+/*
+ * Chip Specific Head File
+ */
+#include <lantiq_soc.h>
+#include "ifxmips_compat.h"
+#include "ifxmips_atm_core.h"
+#include "ifxmips_atm_fw_amazon_se.h"
+
+
+
+/*
+ * ####################################
+ * Definition
+ * ####################################
+ */
+
+/*
+ * EMA Settings
+ */
+#define EMA_CMD_BUF_LEN 0x0040
+#define EMA_CMD_BASE_ADDR (0x00001580 << 2)
+#define EMA_DATA_BUF_LEN 0x0100
+#define EMA_DATA_BASE_ADDR (0x00000B00 << 2)
+#define EMA_WRITE_BURST 0x2
+#define EMA_READ_BURST 0x2
+
+
+
+/*
+ * ####################################
+ * Declaration
+ * ####################################
+ */
+
+/*
+ * Hardware Init/Uninit Functions
+ */
+static inline void init_pmu(void);
+static inline void uninit_pmu(void);
+static inline void reset_ppe(void);
+static inline void init_ema(void);
+static inline void init_mailbox(void);
+static inline void init_atm_tc(void);
+static inline void clear_share_buffer(void);
+
+
+
+/*
+ * ####################################
+ * Local Variable
+ * ####################################
+ */
+
+
+
+/*
+ * ####################################
+ * Local Function
+ * ####################################
+ */
+
+static inline void init_pmu(void)
+{
+ //*(unsigned long *)0xBF10201C &= ~((1 << 15) | (1 << 13) | (1 << 9));
+ //PPE_TOP_PMU_SETUP(IFX_PMU_ENABLE);
+/* PPE_SLL01_PMU_SETUP(IFX_PMU_ENABLE);
+ PPE_TC_PMU_SETUP(IFX_PMU_ENABLE);
+ PPE_EMA_PMU_SETUP(IFX_PMU_ENABLE);
+ //PPE_QSB_PMU_SETUP(IFX_PMU_ENABLE);
+ PPE_TPE_PMU_SETUP(IFX_PMU_ENABLE);
+ DSL_DFE_PMU_SETUP(IFX_PMU_ENABLE);*/
+ struct clk *clk = clk_get_sys("ltq_dsl", NULL);
+ clk_enable(clk);
+}
+
+static inline void uninit_pmu(void)
+{
+/* PPE_SLL01_PMU_SETUP(IFX_PMU_DISABLE);
+ PPE_TC_PMU_SETUP(IFX_PMU_DISABLE);
+ PPE_EMA_PMU_SETUP(IFX_PMU_DISABLE);
+ //PPE_QSB_PMU_SETUP(IFX_PMU_DISABLE);
+ PPE_TPE_PMU_SETUP(IFX_PMU_DISABLE);
+ DSL_DFE_PMU_SETUP(IFX_PMU_DISABLE);
+ //PPE_TOP_PMU_SETUP(IFX_PMU_DISABLE);*/
+ struct clk *clk = clk_get_sys("ltq_dsl", NULL);
+ clk_disable(clk);
+}
+
+static inline void reset_ppe(void)
+{
+#ifdef MODULE
+/* unsigned int etop_cfg;
+ unsigned int etop_mdio_cfg;
+ unsigned int etop_ig_plen_ctrl;
+ unsigned int enet_mac_cfg;
+
+ etop_cfg = *IFX_PP32_ETOP_CFG;
+ etop_mdio_cfg = *IFX_PP32_ETOP_MDIO_CFG;
+ etop_ig_plen_ctrl = *IFX_PP32_ETOP_IG_PLEN_CTRL;
+ enet_mac_cfg = *IFX_PP32_ENET_MAC_CFG;
+
+ *IFX_PP32_ETOP_CFG = (*IFX_PP32_ETOP_CFG & ~0x03C0) | 0x0001;
+
+ // reset PPE
+ ifx_rcu_rst(IFX_RCU_DOMAIN_PPE, IFX_RCU_MODULE_ATM);
+
+ *IFX_PP32_ETOP_MDIO_CFG = etop_mdio_cfg;
+ *IFX_PP32_ETOP_IG_PLEN_CTRL = etop_ig_plen_ctrl;
+ *IFX_PP32_ENET_MAC_CFG = enet_mac_cfg;
+ *IFX_PP32_ETOP_CFG = etop_cfg;*/
+#endif
+}
+
+static inline void init_ema(void)
+{
+ IFX_REG_W32((EMA_CMD_BUF_LEN << 16) | (EMA_CMD_BASE_ADDR >> 2), EMA_CMDCFG);
+ IFX_REG_W32((EMA_DATA_BUF_LEN << 16) | (EMA_DATA_BASE_ADDR >> 2), EMA_DATACFG);
+ IFX_REG_W32(0x000000FF, EMA_IER);
+ IFX_REG_W32(EMA_READ_BURST | (EMA_WRITE_BURST << 2), EMA_CFG);
+}
+
+static inline void init_mailbox(void)
+{
+ IFX_REG_W32(0xFFFFFFFF, MBOX_IGU1_ISRC);
+ IFX_REG_W32(0x00000000, MBOX_IGU1_IER);
+ IFX_REG_W32(0xFFFFFFFF, MBOX_IGU3_ISRC);
+ IFX_REG_W32(0x00000000, MBOX_IGU3_IER);
+}
+
+static inline void init_atm_tc(void)
+{
+ IFX_REG_W32(0x0000, DREG_AT_CTRL);
+ IFX_REG_W32(0x0000, DREG_AR_CTRL);
+ IFX_REG_W32(0x0, DREG_AT_IDLE0);
+ IFX_REG_W32(0x0, DREG_AT_IDLE1);
+ IFX_REG_W32(0x0, DREG_AR_IDLE0);
+ IFX_REG_W32(0x0, DREG_AR_IDLE1);
+ IFX_REG_W32(0x40, RFBI_CFG);
+ IFX_REG_W32(0x0700, SFSM_DBA0);
+ IFX_REG_W32(0x0818, SFSM_DBA1);
+ IFX_REG_W32(0x0930, SFSM_CBA0);
+ IFX_REG_W32(0x0944, SFSM_CBA1);
+ IFX_REG_W32(0x14014, SFSM_CFG0);
+ IFX_REG_W32(0x14014, SFSM_CFG1);
+ IFX_REG_W32(0x0958, FFSM_DBA0);
+ IFX_REG_W32(0x09AC, FFSM_DBA1);
+ IFX_REG_W32(0x10006, FFSM_CFG0);
+ IFX_REG_W32(0x10006, FFSM_CFG1);
+ IFX_REG_W32(0x00000001, FFSM_IDLE_HEAD_BC0);
+ IFX_REG_W32(0x00000001, FFSM_IDLE_HEAD_BC1);
+}
+
+static inline void clear_share_buffer(void)
+{
+ volatile u32 *p = SB_RAM0_ADDR(0);
+ unsigned int i;
+
+ for ( i = 0; i < SB_RAM0_DWLEN + SB_RAM1_DWLEN; i++ )
+ IFX_REG_W32(0, p++);
+}
+
+/*
+ * Description:
+ * Download PPE firmware binary code.
+ * Input:
+ * src --- u32 *, binary code buffer
+ * dword_len --- unsigned int, binary code length in DWORD (32-bit)
+ * Output:
+ * int --- IFX_SUCCESS: Success
+ * else: Error Code
+ */
+static inline int pp32_download_code(u32 *code_src, unsigned int code_dword_len, u32 *data_src, unsigned int data_dword_len)
+{
+ volatile u32 *dest;
+
+ if ( code_src == 0 || ((unsigned long)code_src & 0x03) != 0
+ || data_src == 0 || ((unsigned long)data_src & 0x03) != 0 )
+ return IFX_ERROR;
+
+ if ( code_dword_len <= CDM_CODE_MEMORYn_DWLEN(0) )
+ IFX_REG_W32(0x00, CDM_CFG);
+ else
+ IFX_REG_W32(0x04, CDM_CFG);
+
+ /* copy code */
+ dest = CDM_CODE_MEMORY(0, 0);
+ while ( code_dword_len-- > 0 )
+ IFX_REG_W32(*code_src++, dest++);
+
+ /* copy data */
+ dest = CDM_DATA_MEMORY(0, 0);
+ while ( data_dword_len-- > 0 )
+ IFX_REG_W32(*data_src++, dest++);
+
+ return IFX_SUCCESS;
+}
+
+
+
+/*
+ * ####################################
+ * Global Function
+ * ####################################
+ */
+
+extern void ifx_atm_get_fw_ver(unsigned int *major, unsigned int *minor)
+{
+ ASSERT(major != NULL, "pointer is NULL");
+ ASSERT(minor != NULL, "pointer is NULL");
+
+#ifdef VER_IN_FIRMWARE
+ *major = FW_VER_ID->major;
+ *minor = FW_VER_ID->minor;
+#else
+ *major = ATM_FW_VER_MAJOR;
+ *minor = ATM_FW_VER_MINOR;
+#endif
+}
+
+void ifx_atm_init_chip(void)
+{
+ init_pmu();
+
+ reset_ppe();
+
+ init_ema();
+
+ init_mailbox();
+
+ init_atm_tc();
+
+ clear_share_buffer();
+}
+
+void ifx_atm_uninit_chip(void)
+{
+ uninit_pmu();
+}
+
+/*
+ * Description:
+ * Initialize and start up PP32.
+ * Input:
+ * none
+ * Output:
+ * int --- IFX_SUCCESS: Success
+ * else: Error Code
+ */
+int ifx_pp32_start(int pp32)
+{
+ int ret;
+
+ /* download firmware */
+ ret = pp32_download_code(firmware_binary_code, sizeof(firmware_binary_code) / sizeof(*firmware_binary_code), firmware_binary_data, sizeof(firmware_binary_data) / sizeof(*firmware_binary_data));
+ if ( ret != IFX_SUCCESS )
+ return ret;
+
+ /* run PP32 */
+ IFX_REG_W32(DBG_CTRL_RESTART, PP32_DBG_CTRL);
+
+ /* idle for a while to let PP32 init itself */
+ udelay(10);
+
+ return IFX_SUCCESS;
+}
+
+/*
+ * Description:
+ * Halt PP32.
+ * Input:
+ * none
+ * Output:
+ * none
+ */
+void ifx_pp32_stop(int pp32)
+{
+ /* halt PP32 */
+ IFX_REG_W32(DBG_CTRL_STOP, PP32_DBG_CTRL);
+}
diff --git a/package/ltq-dsl/src/ifxmips_atm_ar9.c b/package/ltq-dsl/src/ifxmips_atm_ar9.c
new file mode 100644
index 000000000..31b89f5c8
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_ar9.c
@@ -0,0 +1,295 @@
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_ar9.c
+** PROJECT : UEIP
+** MODULES : ATM
+**
+** DATE : 7 Jul 2009
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM driver common source file (core functions)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 07 JUL 2009 Xu Liang Init Version
+*******************************************************************************/
+
+
+
+/*
+ * ####################################
+ * Head File
+ * ####################################
+ */
+
+/*
+ * Common Head File
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/clk.h>
+#include <asm/delay.h>
+
+/*
+ * Chip Specific Head File
+ */
+#include <lantiq_soc.h>
+#include "ifxmips_compat.h"
+#define IFX_MEI_BSP 1
+#include "ifxmips_mei_interface.h"
+#include "ifxmips_atm_core.h"
+#include "ifxmips_atm_ppe_common.h"
+ #if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ #include "ifxmips_atm_fw_ar9_retx.h"
+#else
+ #include "ifxmips_atm_fw_ar9.h"
+#endif
+
+
+
+/*
+ * ####################################
+ * Definition
+ * ####################################
+ */
+
+/*
+ * EMA Settings
+ */
+#define EMA_CMD_BUF_LEN 0x0040
+#define EMA_CMD_BASE_ADDR (0x00003B80 << 2)
+#define EMA_DATA_BUF_LEN 0x0100
+#define EMA_DATA_BASE_ADDR (0x00003C00 << 2)
+#define EMA_WRITE_BURST 0x2
+#define EMA_READ_BURST 0x2
+
+
+
+/*
+ * ####################################
+ * Declaration
+ * ####################################
+ */
+
+/*
+ * Hardware Init/Uninit Functions
+ */
+static inline void init_pmu(void);
+static inline void uninit_pmu(void);
+static inline void reset_ppe(void);
+static inline void init_ema(void);
+static inline void init_mailbox(void);
+static inline void init_atm_tc(void);
+static inline void clear_share_buffer(void);
+
+
+
+/*
+ * ####################################
+ * Local Variable
+ * ####################################
+ */
+
+
+
+/*
+ * ####################################
+ * Local Function
+ * ####################################
+ */
+
+static inline void init_pmu(void)
+{
+ //*(unsigned long *)0xBF10201C &= ~((1 << 15) | (1 << 13) | (1 << 9));
+ //PPE_TOP_PMU_SETUP(IFX_PMU_ENABLE);
+/* PPE_SLL01_PMU_SETUP(IFX_PMU_ENABLE);
+ PPE_TC_PMU_SETUP(IFX_PMU_ENABLE);
+ PPE_EMA_PMU_SETUP(IFX_PMU_ENABLE);
+ PPE_QSB_PMU_SETUP(IFX_PMU_ENABLE);
+ PPE_TPE_PMU_SETUP(IFX_PMU_ENABLE);
+ DSL_DFE_PMU_SETUP(IFX_PMU_ENABLE);*/
+ struct clk *clk = clk_get_sys("ltq_dsl", NULL);
+ clk_enable(clk);
+}
+
+static inline void uninit_pmu(void)
+{
+ /* PPE_SLL01_PMU_SETUP(IFX_PMU_DISABLE);
+ PPE_TC_PMU_SETUP(IFX_PMU_DISABLE);
+ PPE_EMA_PMU_SETUP(IFX_PMU_DISABLE);
+ PPE_QSB_PMU_SETUP(IFX_PMU_DISABLE);
+ PPE_TPE_PMU_SETUP(IFX_PMU_DISABLE);
+ DSL_DFE_PMU_SETUP(IFX_PMU_DISABLE);*/
+ //PPE_TOP_PMU_SETUP(IFX_PMU_DISABLE);
+ struct clk *clk = clk_get_sys("ltq_dsl", NULL);
+ clk_disable(clk);
+}
+
+static inline void reset_ppe(void)
+{
+#ifdef MODULE
+ // reset PPE
+ //ifx_rcu_rst(IFX_RCU_DOMAIN_PPE, IFX_RCU_MODULE_ATM);
+#endif
+}
+
+static inline void init_ema(void)
+{
+ IFX_REG_W32((EMA_CMD_BUF_LEN << 16) | (EMA_CMD_BASE_ADDR >> 2), EMA_CMDCFG);
+ IFX_REG_W32((EMA_DATA_BUF_LEN << 16) | (EMA_DATA_BASE_ADDR >> 2), EMA_DATACFG);
+ IFX_REG_W32(0x000000FF, EMA_IER);
+ IFX_REG_W32(EMA_READ_BURST | (EMA_WRITE_BURST << 2), EMA_CFG);
+}
+
+static inline void init_mailbox(void)
+{
+ IFX_REG_W32(0xFFFFFFFF, MBOX_IGU1_ISRC);
+ IFX_REG_W32(0x00000000, MBOX_IGU1_IER);
+ IFX_REG_W32(0xFFFFFFFF, MBOX_IGU3_ISRC);
+ IFX_REG_W32(0x00000000, MBOX_IGU3_IER);
+}
+
+static inline void init_atm_tc(void)
+{
+}
+
+static inline void clear_share_buffer(void)
+{
+ volatile u32 *p = SB_RAM0_ADDR(0);
+ unsigned int i;
+
+ for ( i = 0; i < SB_RAM0_DWLEN + SB_RAM1_DWLEN + SB_RAM2_DWLEN + SB_RAM3_DWLEN + SB_RAM4_DWLEN; i++ )
+ IFX_REG_W32(0, p++);
+}
+
+/*
+ * Description:
+ * Download PPE firmware binary code.
+ * Input:
+ * src --- u32 *, binary code buffer
+ * dword_len --- unsigned int, binary code length in DWORD (32-bit)
+ * Output:
+ * int --- IFX_SUCCESS: Success
+ * else: Error Code
+ */
+static inline int pp32_download_code(u32 *code_src, unsigned int code_dword_len, u32 *data_src, unsigned int data_dword_len)
+{
+ volatile u32 *dest;
+
+ if ( code_src == 0 || ((unsigned long)code_src & 0x03) != 0
+ || data_src == 0 || ((unsigned long)data_src & 0x03) != 0 )
+ return IFX_ERROR;
+
+ if ( code_dword_len <= CDM_CODE_MEMORYn_DWLEN(0) )
+ IFX_REG_W32(0x00, CDM_CFG);
+ else
+ IFX_REG_W32(0x04, CDM_CFG);
+
+ /* copy code */
+ dest = CDM_CODE_MEMORY(0, 0);
+ while ( code_dword_len-- > 0 )
+ IFX_REG_W32(*code_src++, dest++);
+
+ /* copy data */
+ dest = CDM_DATA_MEMORY(0, 0);
+ while ( data_dword_len-- > 0 )
+ IFX_REG_W32(*data_src++, dest++);
+
+ return IFX_SUCCESS;
+}
+
+
+
+/*
+ * ####################################
+ * Global Function
+ * ####################################
+ */
+
+extern void ifx_atm_get_fw_ver(unsigned int *major, unsigned int *minor)
+{
+ ASSERT(major != NULL, "pointer is NULL");
+ ASSERT(minor != NULL, "pointer is NULL");
+
+#if (defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX) || defined(VER_IN_FIRMWARE)
+ *major = FW_VER_ID->major;
+ *minor = FW_VER_ID->minor;
+#else
+ *major = ATM_FW_VER_MAJOR;
+ *minor = ATM_FW_VER_MINOR;
+#endif
+}
+
+void ifx_atm_init_chip(void)
+{
+ init_pmu();
+
+ reset_ppe();
+
+ init_ema();
+
+ init_mailbox();
+
+ init_atm_tc();
+
+ clear_share_buffer();
+}
+
+void ifx_atm_uninit_chip(void)
+{
+ uninit_pmu();
+}
+
+/*
+ * Description:
+ * Initialize and start up PP32.
+ * Input:
+ * none
+ * Output:
+ * int --- IFX_SUCCESS: Success
+ * else: Error Code
+ */
+int ifx_pp32_start(int pp32)
+{
+ int ret;
+
+ /* download firmware */
+ ret = pp32_download_code(firmware_binary_code, sizeof(firmware_binary_code) / sizeof(*firmware_binary_code), firmware_binary_data, sizeof(firmware_binary_data) / sizeof(*firmware_binary_data));
+ if ( ret != IFX_SUCCESS )
+ return ret;
+
+ /* run PP32 */
+ IFX_REG_W32(DBG_CTRL_RESTART, PP32_DBG_CTRL(0));
+
+ /* idle for a while to let PP32 init itself */
+ udelay(10);
+
+ return IFX_SUCCESS;
+}
+
+/*
+ * Description:
+ * Halt PP32.
+ * Input:
+ * none
+ * Output:
+ * none
+ */
+void ifx_pp32_stop(int pp32)
+{
+ /* halt PP32 */
+ IFX_REG_W32(DBG_CTRL_STOP, PP32_DBG_CTRL(0));
+}
diff --git a/package/ltq-dsl/src/ifxmips_atm_core.c b/package/ltq-dsl/src/ifxmips_atm_core.c
new file mode 100644
index 000000000..92853bb88
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_core.c
@@ -0,0 +1,4770 @@
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_core.c
+** PROJECT : UEIP
+** MODULES : ATM
+**
+** DATE : 7 Jul 2009
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM driver common source file (core functions)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 07 JUL 2009 Xu Liang Init Version
+*******************************************************************************/
+
+
+
+/*
+ * ####################################
+ * Version No.
+ * ####################################
+ */
+
+#define IFX_ATM_VER_MAJOR 1
+#define IFX_ATM_VER_MID 0
+#define IFX_ATM_VER_MINOR 19
+
+
+
+/*
+ * ####################################
+ * Head File
+ * ####################################
+ */
+
+/*
+ * Common Head File
+ */
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/atmdev.h>
+#include <linux/atm.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+
+/*
+ * Chip Specific Head File
+ */
+#include <lantiq_soc.h>
+#include "ifxmips_compat.h"
+#define IFX_MEI_BSP 1
+#include "ifxmips_mei_interface.h"
+#include "ifxmips_atm_core.h"
+
+
+
+/*
+ * ####################################
+ * Kernel Version Adaption
+ * ####################################
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
+ #define MODULE_PARM_ARRAY(a, b) module_param_array(a, int, NULL, 0)
+ #define MODULE_PARM(a, b) module_param(a, int, 0)
+#else
+ #define MODULE_PARM_ARRAY(a, b) MODULE_PARM(a, b)
+#endif
+
+
+
+/*!
+ \addtogroup IFXMIPS_ATM_MODULE_PARAMS
+ */
+/*@{*/
+/*
+ * ####################################
+ * Parameters to Configure PPE
+ * ####################################
+ */
+/*!
+ \brief QSB cell delay variation due to concurrency
+ */
+static int qsb_tau = 1; /* QSB cell delay variation due to concurrency */
+/*!
+ \brief QSB scheduler burst length
+ */
+static int qsb_srvm = 0x0F; /* QSB scheduler burst length */
+/*!
+ \brief QSB time step, all legal values are 1, 2, 4
+ */
+static int qsb_tstep = 4 ; /* QSB time step, all legal values are 1, 2, 4 */
+
+/*!
+ \brief Write descriptor delay
+ */
+static int write_descriptor_delay = 0x20; /* Write descriptor delay */
+
+/*!
+ \brief AAL5 padding byte ('~')
+ */
+static int aal5_fill_pattern = 0x007E; /* AAL5 padding byte ('~') */
+/*!
+ \brief Max frame size for RX
+ */
+static int aal5r_max_packet_size = 0x0700; /* Max frame size for RX */
+/*!
+ \brief Min frame size for RX
+ */
+static int aal5r_min_packet_size = 0x0000; /* Min frame size for RX */
+/*!
+ \brief Max frame size for TX
+ */
+static int aal5s_max_packet_size = 0x0700; /* Max frame size for TX */
+/*!
+ \brief Min frame size for TX
+ */
+static int aal5s_min_packet_size = 0x0000; /* Min frame size for TX */
+/*!
+ \brief Drop error packet in RX path
+ */
+static int aal5r_drop_error_packet = 1; /* Drop error packet in RX path */
+
+/*!
+ \brief Number of descriptors per DMA RX channel
+ */
+static int dma_rx_descriptor_length = 128; /* Number of descriptors per DMA RX channel */
+/*!
+ \brief Number of descriptors per DMA TX channel
+ */
+static int dma_tx_descriptor_length = 64; /* Number of descriptors per DMA TX channel */
+/*!
+ \brief PPE core clock cycles between descriptor write and effectiveness in external RAM
+ */
+static int dma_rx_clp1_descriptor_threshold = 38;
+/*@}*/
+
+MODULE_PARM(qsb_tau, "i");
+MODULE_PARM_DESC(qsb_tau, "Cell delay variation. Value must be > 0");
+MODULE_PARM(qsb_srvm, "i");
+MODULE_PARM_DESC(qsb_srvm, "Maximum burst size");
+MODULE_PARM(qsb_tstep, "i");
+MODULE_PARM_DESC(qsb_tstep, "n*32 cycles per sbs cycles n=1,2,4");
+
+MODULE_PARM(write_descriptor_delay, "i");
+MODULE_PARM_DESC(write_descriptor_delay, "PPE core clock cycles between descriptor write and effectiveness in external RAM");
+
+MODULE_PARM(aal5_fill_pattern, "i");
+MODULE_PARM_DESC(aal5_fill_pattern, "Filling pattern (PAD) for AAL5 frames");
+MODULE_PARM(aal5r_max_packet_size, "i");
+MODULE_PARM_DESC(aal5r_max_packet_size, "Max packet size in byte for downstream AAL5 frames");
+MODULE_PARM(aal5r_min_packet_size, "i");
+MODULE_PARM_DESC(aal5r_min_packet_size, "Min packet size in byte for downstream AAL5 frames");
+MODULE_PARM(aal5s_max_packet_size, "i");
+MODULE_PARM_DESC(aal5s_max_packet_size, "Max packet size in byte for upstream AAL5 frames");
+MODULE_PARM(aal5s_min_packet_size, "i");
+MODULE_PARM_DESC(aal5s_min_packet_size, "Min packet size in byte for upstream AAL5 frames");
+MODULE_PARM(aal5r_drop_error_packet, "i");
+MODULE_PARM_DESC(aal5r_drop_error_packet, "Non-zero value to drop error packet for downstream");
+
+MODULE_PARM(dma_rx_descriptor_length, "i");
+MODULE_PARM_DESC(dma_rx_descriptor_length, "Number of descriptor assigned to DMA RX channel (>16)");
+MODULE_PARM(dma_tx_descriptor_length, "i");
+MODULE_PARM_DESC(dma_tx_descriptor_length, "Number of descriptor assigned to DMA TX channel (>16)");
+MODULE_PARM(dma_rx_clp1_descriptor_threshold, "i");
+MODULE_PARM_DESC(dma_rx_clp1_descriptor_threshold, "Descriptor threshold for cells with cell loss priority 1");
+
+
+
+/*
+ * ####################################
+ * Definition
+ * ####################################
+ */
+
+#define ENABLE_LED_FRAMEWORK 1
+
+#define DUMP_SKB_LEN ~0
+
+
+
+/*
+ * ####################################
+ * Declaration
+ * ####################################
+ */
+
+/*
+ * Network Operations
+ */
+static int ppe_ioctl(struct atm_dev *, unsigned int, void *);
+static int ppe_open(struct atm_vcc *);
+static void ppe_close(struct atm_vcc *);
+static int ppe_send(struct atm_vcc *, struct sk_buff *);
+static int ppe_send_oam(struct atm_vcc *, void *, int);
+static int ppe_change_qos(struct atm_vcc *, struct atm_qos *, int);
+
+/*
+ * ADSL LED
+ */
+static INLINE void adsl_led_flash(void);
+
+/*
+ * 64-bit operation used by MIB calculation
+ */
+static INLINE void u64_add_u32(ppe_u64_t, unsigned int, ppe_u64_t *);
+
+/*
+ * buffer manage functions
+ */
+static INLINE struct sk_buff* alloc_skb_rx(void);
+static INLINE struct sk_buff* alloc_skb_tx(unsigned int);
+struct sk_buff* atm_alloc_tx(struct atm_vcc *, unsigned int);
+static INLINE void atm_free_tx_skb_vcc(struct sk_buff *, struct atm_vcc *);
+static INLINE struct sk_buff *get_skb_rx_pointer(unsigned int);
+static INLINE int get_tx_desc(unsigned int);
+
+/*
+ * mailbox handler and signal function
+ */
+static INLINE void mailbox_oam_rx_handler(void);
+static INLINE void mailbox_aal_rx_handler(void);
+#if defined(ENABLE_TASKLET) && ENABLE_TASKLET
+ static void do_ppe_tasklet(unsigned long);
+#endif
+static irqreturn_t mailbox_irq_handler(int, void *);
+static INLINE void mailbox_signal(unsigned int, int);
+
+/*
+ * QSB & HTU setting functions
+ */
+static void set_qsb(struct atm_vcc *, struct atm_qos *, unsigned int);
+static void qsb_global_set(void);
+static INLINE void set_htu_entry(unsigned int, unsigned int, unsigned int, int, int);
+static INLINE void clear_htu_entry(unsigned int);
+static void validate_oam_htu_entry(void);
+static void invalidate_oam_htu_entry(void);
+
+/*
+ * look up for connection ID
+ */
+static INLINE int find_vpi(unsigned int);
+static INLINE int find_vpivci(unsigned int, unsigned int);
+static INLINE int find_vcc(struct atm_vcc *);
+
+/*
+ * ReTX functions
+ */
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ static void retx_polling_func(unsigned long);
+ static int init_atm_tc_retrans_param(void);
+ static void clear_atm_tc_retrans_param(void);
+#endif
+
+
+/*
+ * Debug Functions
+ */
+#if defined(DEBUG_DUMP_SKB) && DEBUG_DUMP_SKB
+ static void dump_skb(struct sk_buff *, unsigned int, char *, int, int, int);
+#else
+ #define dump_skb(skb, len, title, port, ch, is_tx) do {} while (0)
+#endif
+#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC
+ static void skb_swap(struct sk_buff *, unsigned int);
+#else
+ #define skb_swap(skb, byteoff) do {} while (0)
+#endif
+
+/*
+ * Proc File Functions
+ */
+static INLINE void proc_file_create(void);
+static INLINE void proc_file_delete(void);
+static int proc_read_version(char *, char **, off_t, int, int *, void *);
+static int proc_read_mib(char *, char **, off_t, int, int *, void *);
+static int proc_write_mib(struct file *, const char *, unsigned long, void *);
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ static int proc_read_retx_mib(char *, char **, off_t, int, int *, void *);
+ static int proc_write_retx_mib(struct file *, const char *, unsigned long, void *);
+#endif
+#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC
+ static int proc_read_dbg(char *, char **, off_t, int, int *, void *);
+ static int proc_write_dbg(struct file *, const char *, unsigned long, void *);
+ static int proc_write_mem(struct file *, const char *, unsigned long, void *);
+ #if defined(CONFIG_AR9) || defined(CONFIG_VR9) || defined(CONFIG_DANUBE) || defined(CONFIG_AMAZON_SE)
+ static int proc_read_pp32(char *, char **, off_t, int, int *, void *);
+ static int proc_write_pp32(struct file *, const char *, unsigned long, void *);
+ #endif
+#endif
+#if defined(ENABLE_FW_PROC) && ENABLE_FW_PROC
+ static int proc_read_htu(char *, char **, off_t, int, int *, void *);
+ static int proc_read_txq(char *, char **, off_t, int, int *, void *);
+ #if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ static int proc_read_retx_fw(char *, char **, off_t, int, int *, void *);
+ static int proc_read_retx_stats(char *, char **, off_t, int, int *, void *);
+ static int proc_write_retx_stats(struct file *, const char *, unsigned long, void *);
+ static int proc_read_retx_cfg(char *, char **, off_t, int, int *, void *);
+ static int proc_write_retx_cfg(struct file *, const char *, unsigned long, void *);
+ static int proc_read_retx_dsl_param(char *, char **, off_t, int, int *, void *);
+ #endif
+#endif
+
+/*
+ * Proc Help Functions
+ */
+static int stricmp(const char *, const char *);
+#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC
+ static int strincmp(const char *, const char *, int);
+ static int get_token(char **, char **, int *, int *);
+ static unsigned int get_number(char **, int *, int);
+ static void ignore_space(char **, int *);
+#endif
+static INLINE int ifx_atm_version(char *);
+
+/*
+ * Init & clean-up functions
+ */
+static INLINE void check_parameters(void);
+static INLINE int init_priv_data(void);
+static INLINE void clear_priv_data(void);
+static INLINE void init_rx_tables(void);
+static INLINE void init_tx_tables(void);
+
+/*
+ * Exteranl Function
+ */
+#if defined(CONFIG_IFX_OAM) || defined(CONFIG_IFX_OAM_MODULE)
+ extern void ifx_push_oam(unsigned char *);
+#else
+ static inline void ifx_push_oam(unsigned char *dummy) {}
+#endif
+#if defined(CONFIG_IFXMIPS_DSL_CPE_MEI) || defined(CONFIG_IFXMIPS_DSL_CPE_MEI_MODULE)
+ #if !defined(ENABLE_LED_FRAMEWORK) || !ENABLE_LED_FRAMEWORK
+ extern int ifx_mei_atm_led_blink(void) __attribute__ ((weak));
+ #endif
+ extern int ifx_mei_atm_showtime_check(int *is_showtime, struct port_cell_info *port_cell, void **xdata_addr) __attribute__ ((weak));
+#else
+ #if !defined(ENABLE_LED_FRAMEWORK) || !ENABLE_LED_FRAMEWORK
+ static inline int ifx_mei_atm_led_blink(void) { return IFX_SUCCESS; }
+ #endif
+ static inline int ifx_mei_atm_showtime_check(int *is_showtime, struct port_cell_info *port_cell, void **xdata_addr)
+ {
+ if ( is_showtime != NULL )
+ *is_showtime = 0;
+ return IFX_SUCCESS;
+ }
+#endif
+
+/*
+ * External variable
+ */
+struct sk_buff* (*ifx_atm_alloc_tx)(struct atm_vcc *, unsigned int) = NULL;
+
+
+//extern struct sk_buff* (*ifx_atm_alloc_tx)(struct atm_vcc *, unsigned int);
+#if defined(CONFIG_IFXMIPS_DSL_CPE_MEI) || defined(CONFIG_IFXMIPS_DSL_CPE_MEI_MODULE)
+ extern int (*ifx_mei_atm_showtime_enter)(struct port_cell_info *, void *) __attribute__ ((weak));
+ extern int (*ifx_mei_atm_showtime_exit)(void) __attribute__ ((weak));
+#else
+ int (*ifx_mei_atm_showtime_enter)(struct port_cell_info *, void *) = NULL;
+ EXPORT_SYMBOL(ifx_mei_atm_showtime_enter);
+ int (*ifx_mei_atm_showtime_exit)(void) = NULL;
+ EXPORT_SYMBOL(ifx_mei_atm_showtime_exit);
+#endif
+
+
+
+/*
+ * ####################################
+ * Local Variable
+ * ####################################
+ */
+
+static struct atm_priv_data g_atm_priv_data;
+
+static struct atmdev_ops g_ifx_atm_ops = {
+ .open = ppe_open,
+ .close = ppe_close,
+ .ioctl = ppe_ioctl,
+ .send = ppe_send,
+ .send_oam = ppe_send_oam,
+ .change_qos = ppe_change_qos,
+ .owner = THIS_MODULE,
+};
+
+#if defined(ENABLE_TASKLET) && ENABLE_TASKLET
+ DECLARE_TASKLET(g_dma_tasklet, do_ppe_tasklet, 0);
+#endif
+
+static int g_showtime = 0;
+static void *g_xdata_addr = NULL;
+
+#if 0 /*--- defined(ENABLE_LED_FRAMEWORK) && ENABLE_LED_FRAMEWORK ---*/
+ static void *g_data_led_trigger = NULL;
+#endif
+
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ static unsigned long g_retx_playout_buffer = 0;
+
+ static volatile int g_retx_htu = 1;
+ static struct dsl_param g_dsl_param = {0};
+ static int g_retx_polling_cnt = HZ;
+ static struct timeval g_retx_polling_start = {0}, g_retx_polling_end = {0};
+ static struct timer_list g_retx_polling_timer;
+#endif
+
+unsigned int ifx_atm_dbg_enable = 0;
+
+static struct proc_dir_entry* g_atm_dir = NULL;
+
+
+
+/*
+ * ####################################
+ * Local Function
+ * ####################################
+ */
+
+static int ppe_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg)
+{
+ int ret = 0;
+ atm_cell_ifEntry_t mib_cell;
+ atm_aal5_ifEntry_t mib_aal5;
+ atm_aal5_vcc_x_t mib_vcc;
+ unsigned int value;
+ int conn;
+
+ if ( _IOC_TYPE(cmd) != PPE_ATM_IOC_MAGIC
+ || _IOC_NR(cmd) >= PPE_ATM_IOC_MAXNR )
+ return -ENOTTY;
+
+ if ( _IOC_DIR(cmd) & _IOC_READ )
+ ret = !access_ok(VERIFY_WRITE, arg, _IOC_SIZE(cmd));
+ else if ( _IOC_DIR(cmd) & _IOC_WRITE )
+ ret = !access_ok(VERIFY_READ, arg, _IOC_SIZE(cmd));
+ if ( ret )
+ return -EFAULT;
+
+ switch ( cmd )
+ {
+ case PPE_ATM_MIB_CELL: /* cell level MIB */
+ /* These MIB should be read at ARC side, now put zero only. */
+ mib_cell.ifHCInOctets_h = 0;
+ mib_cell.ifHCInOctets_l = 0;
+ mib_cell.ifHCOutOctets_h = 0;
+ mib_cell.ifHCOutOctets_l = 0;
+ mib_cell.ifInErrors = 0;
+ mib_cell.ifInUnknownProtos = WAN_MIB_TABLE->wrx_drophtu_cell;
+ mib_cell.ifOutErrors = 0;
+
+ ret = sizeof(mib_cell) - copy_to_user(arg, &mib_cell, sizeof(mib_cell));
+ break;
+
+ case PPE_ATM_MIB_AAL5: /* AAL5 MIB */
+ value = WAN_MIB_TABLE->wrx_total_byte;
+ u64_add_u32(g_atm_priv_data.wrx_total_byte, value - g_atm_priv_data.prev_wrx_total_byte, &g_atm_priv_data.wrx_total_byte);
+ g_atm_priv_data.prev_wrx_total_byte = value;
+ mib_aal5.ifHCInOctets_h = g_atm_priv_data.wrx_total_byte.h;
+ mib_aal5.ifHCInOctets_l = g_atm_priv_data.wrx_total_byte.l;
+
+ value = WAN_MIB_TABLE->wtx_total_byte;
+ u64_add_u32(g_atm_priv_data.wtx_total_byte, value - g_atm_priv_data.prev_wtx_total_byte, &g_atm_priv_data.wtx_total_byte);
+ g_atm_priv_data.prev_wtx_total_byte = value;
+ mib_aal5.ifHCOutOctets_h = g_atm_priv_data.wtx_total_byte.h;
+ mib_aal5.ifHCOutOctets_l = g_atm_priv_data.wtx_total_byte.l;
+
+ mib_aal5.ifInUcastPkts = g_atm_priv_data.wrx_pdu;
+ mib_aal5.ifOutUcastPkts = WAN_MIB_TABLE->wtx_total_pdu;
+ mib_aal5.ifInErrors = WAN_MIB_TABLE->wrx_err_pdu;
+ mib_aal5.ifInDiscards = WAN_MIB_TABLE->wrx_dropdes_pdu + g_atm_priv_data.wrx_drop_pdu;
+ mib_aal5.ifOutErros = g_atm_priv_data.wtx_err_pdu;
+ mib_aal5.ifOutDiscards = g_atm_priv_data.wtx_drop_pdu;
+
+ ret = sizeof(mib_aal5) - copy_to_user(arg, &mib_aal5, sizeof(mib_aal5));
+ break;
+
+ case PPE_ATM_MIB_VCC: /* VCC related MIB */
+ copy_from_user(&mib_vcc, arg, sizeof(mib_vcc));
+ conn = find_vpivci(mib_vcc.vpi, mib_vcc.vci);
+ if ( conn >= 0 )
+ {
+ mib_vcc.mib_vcc.aal5VccCrcErrors = g_atm_priv_data.conn[conn].aal5_vcc_crc_err;
+ mib_vcc.mib_vcc.aal5VccOverSizedSDUs = g_atm_priv_data.conn[conn].aal5_vcc_oversize_sdu;
+ mib_vcc.mib_vcc.aal5VccSarTimeOuts = 0; /* no timer support */
+ ret = sizeof(mib_vcc) - copy_to_user(arg, &mib_vcc, sizeof(mib_vcc));
+ }
+ else
+ ret = -EINVAL;
+ break;
+
+ default:
+ ret = -ENOIOCTLCMD;
+ }
+
+ return ret;
+}
+
+static int ppe_open(struct atm_vcc *vcc)
+{
+ int ret;
+ short vpi = vcc->vpi;
+ int vci = vcc->vci;
+ struct port *port = &g_atm_priv_data.port[(int)vcc->dev->dev_data];
+ int conn;
+ int f_enable_irq = 0;
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ int sys_flag;
+#endif
+
+ if ( vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0 )
+ return -EPROTONOSUPPORT;
+
+#if !defined(DISABLE_QOS_WORKAROUND) || !DISABLE_QOS_WORKAROUND
+ /* check bandwidth */
+
+ if (vcc->qos.txtp.traffic_class == ATM_CBR &&
+ vcc->qos.txtp.max_pcr > (port->tx_max_cell_rate - port->tx_current_cell_rate))
+ {
+ printk("CBR set. %s, line %d returns EINVAL\n", __FUNCTION__, __LINE__);
+ ret = -EINVAL;
+ goto PPE_OPEN_EXIT;
+ }
+ if(vcc->qos.txtp.traffic_class == ATM_VBR_RT &&
+ vcc->qos.txtp.max_pcr > (port->tx_max_cell_rate - port->tx_current_cell_rate))
+ {
+ printk("VBR RT set. %s, line %d returns EINVAL\n", __FUNCTION__, __LINE__);
+ ret = -EINVAL;
+ goto PPE_OPEN_EXIT;
+ }
+
+ if (vcc->qos.txtp.traffic_class == ATM_VBR_NRT &&
+ vcc->qos.txtp.scr > (port->tx_max_cell_rate - port->tx_current_cell_rate))
+ {
+ printk("VBR NRT set. %s, line %d returns EINVAL\n", __FUNCTION__, __LINE__);
+ ret = -EINVAL;
+ goto PPE_OPEN_EXIT;
+ }
+
+ if (vcc->qos.txtp.traffic_class == ATM_UBR_PLUS &&
+ vcc->qos.txtp.min_pcr > (port->tx_max_cell_rate - port->tx_current_cell_rate))
+ {
+ printk("UBR PLUS set. %s, line %d returns EINVAL\n", __FUNCTION__, __LINE__);
+ ret = -EINVAL;
+ goto PPE_OPEN_EXIT;
+ }
+
+#endif
+
+ /* check existing vpi,vci */
+ conn = find_vpivci(vpi, vci);
+ if ( conn >= 0 ) {
+ ret = -EADDRINUSE;
+ goto PPE_OPEN_EXIT;
+ }
+
+ /* check whether it need to enable irq */
+ if ( g_atm_priv_data.conn_table == 0 )
+ f_enable_irq = 1;
+
+ /* allocate connection */
+ for ( conn = 0; conn < MAX_PVC_NUMBER; conn++ ) {
+ if ( test_and_set_bit(conn, &g_atm_priv_data.conn_table) == 0 ) {
+ g_atm_priv_data.conn[conn].vcc = vcc;
+ break;
+ }
+ }
+ if ( conn == MAX_PVC_NUMBER )
+ {
+ printk("max_pvc_number reached\n");
+ ret = -EINVAL;
+ goto PPE_OPEN_EXIT;
+ }
+
+ /* reserve bandwidth */
+ switch ( vcc->qos.txtp.traffic_class ) {
+ case ATM_CBR:
+ case ATM_VBR_RT:
+ port->tx_current_cell_rate += vcc->qos.txtp.max_pcr;
+ break;
+ case ATM_VBR_NRT:
+ port->tx_current_cell_rate += vcc->qos.txtp.scr;
+ break;
+ case ATM_UBR_PLUS:
+ port->tx_current_cell_rate += vcc->qos.txtp.min_pcr;
+ break;
+ }
+
+ /* set qsb */
+ set_qsb(vcc, &vcc->qos, conn);
+
+ /* update atm_vcc structure */
+ vcc->itf = (int)vcc->dev->dev_data;
+ vcc->vpi = vpi;
+ vcc->vci = vci;
+ set_bit(ATM_VF_READY, &vcc->flags);
+
+ /* enable irq */
+ if (f_enable_irq ) {
+ ifx_atm_alloc_tx = atm_alloc_tx;
+
+ *MBOX_IGU1_ISRC = (1 << RX_DMA_CH_AAL) | (1 << RX_DMA_CH_OAM);
+ *MBOX_IGU1_IER = (1 << RX_DMA_CH_AAL) | (1 << RX_DMA_CH_OAM);
+
+ enable_irq(PPE_MAILBOX_IGU1_INT);
+ }
+
+ /* set port */
+ WTX_QUEUE_CONFIG(conn + FIRST_QSB_QID)->sbid = (int)vcc->dev->dev_data;
+
+ /* set htu entry */
+ set_htu_entry(vpi, vci, conn, vcc->qos.aal == ATM_AAL5 ? 1 : 0, 0);
+
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ // ReTX: occupy second QID
+ local_irq_save(sys_flag);
+ if ( g_retx_htu && vcc->qos.aal == ATM_AAL5 )
+ {
+ int retx_conn = (conn + 8) % 16; // ReTX queue
+
+ if ( retx_conn < MAX_PVC_NUMBER && test_and_set_bit(retx_conn, &g_atm_priv_data.conn_table) == 0 ) {
+ g_atm_priv_data.conn[retx_conn].vcc = vcc;
+ set_htu_entry(vpi, vci, retx_conn, vcc->qos.aal == ATM_AAL5 ? 1 : 0, 1);
+ }
+ }
+ local_irq_restore(sys_flag);
+#endif
+
+ ret = 0;
+
+PPE_OPEN_EXIT:
+ return ret;
+}
+
+static void ppe_close(struct atm_vcc *vcc)
+{
+ int conn;
+ struct port *port;
+ struct connection *connection;
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ int sys_flag;
+#endif
+
+ if ( vcc == NULL )
+ return;
+
+ /* get connection id */
+ conn = find_vcc(vcc);
+ if ( conn < 0 ) {
+ err("can't find vcc");
+ goto PPE_CLOSE_EXIT;
+ }
+ connection = &g_atm_priv_data.conn[conn];
+ port = &g_atm_priv_data.port[connection->port];
+
+ /* clear htu */
+ clear_htu_entry(conn);
+
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ // ReTX: release second QID
+ local_irq_save(sys_flag);
+ if ( g_retx_htu && vcc->qos.aal == ATM_AAL5 )
+ {
+ int retx_conn = (conn + 8) % 16; // ReTX queue
+
+ if ( retx_conn < MAX_PVC_NUMBER && g_atm_priv_data.conn[retx_conn].vcc == vcc ) {
+ clear_htu_entry(retx_conn);
+ g_atm_priv_data.conn[retx_conn].vcc = NULL;
+ g_atm_priv_data.conn[retx_conn].aal5_vcc_crc_err = 0;
+ g_atm_priv_data.conn[retx_conn].aal5_vcc_oversize_sdu = 0;
+ clear_bit(retx_conn, &g_atm_priv_data.conn_table);
+ }
+ }
+ local_irq_restore(sys_flag);
+#endif
+
+ /* release connection */
+ connection->vcc = NULL;
+ connection->aal5_vcc_crc_err = 0;
+ connection->aal5_vcc_oversize_sdu = 0;
+ clear_bit(conn, &g_atm_priv_data.conn_table);
+
+ /* disable irq */
+ if ( g_atm_priv_data.conn_table == 0 ) {
+ disable_irq(PPE_MAILBOX_IGU1_INT);
+ ifx_atm_alloc_tx = NULL;
+ }
+
+ /* release bandwidth */
+ switch ( vcc->qos.txtp.traffic_class )
+ {
+ case ATM_CBR:
+ case ATM_VBR_RT:
+ port->tx_current_cell_rate -= vcc->qos.txtp.max_pcr;
+ break;
+ case ATM_VBR_NRT:
+ port->tx_current_cell_rate -= vcc->qos.txtp.scr;
+ break;
+ case ATM_UBR_PLUS:
+ port->tx_current_cell_rate -= vcc->qos.txtp.min_pcr;
+ break;
+ }
+
+PPE_CLOSE_EXIT:
+ return;
+}
+
+static int ppe_send(struct atm_vcc *vcc, struct sk_buff *skb)
+{
+ int ret;
+ int conn;
+ int desc_base;
+ struct tx_descriptor reg_desc = {0};
+
+ if ( vcc == NULL || skb == NULL )
+ return -EINVAL;
+
+ skb_orphan(skb);
+ skb_get(skb);
+ atm_free_tx_skb_vcc(skb, vcc);
+
+ conn = find_vcc(vcc);
+ if ( conn < 0 ) {
+ ret = -EINVAL;
+ goto FIND_VCC_FAIL;
+ }
+
+ if ( !g_showtime ) {
+ err("not in showtime");
+ ret = -EIO;
+ goto PPE_SEND_FAIL;
+ }
+
+ if ( vcc->qos.aal == ATM_AAL5 ) {
+ int byteoff;
+ int datalen;
+ struct tx_inband_header *header;
+
+ datalen = skb->len;
+ byteoff = (unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1);
+
+ if ( skb_headroom(skb) < byteoff + TX_INBAND_HEADER_LENGTH ) {
+ struct sk_buff *new_skb;
+
+ new_skb = alloc_skb_tx(datalen);
+ if ( new_skb == NULL ) {
+ err("ALLOC_SKB_TX_FAIL");
+ ret = -ENOMEM;
+ goto PPE_SEND_FAIL;
+ }
+ skb_put(new_skb, datalen);
+ memcpy(new_skb->data, skb->data, datalen);
+ dev_kfree_skb_any(skb);
+ skb = new_skb;
+ byteoff = (unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1);
+ }
+
+ skb_push(skb, byteoff + TX_INBAND_HEADER_LENGTH);
+
+ header = (struct tx_inband_header *)skb->data;
+
+ /* setup inband trailer */
+ header->uu = 0;
+ header->cpi = 0;
+ header->pad = aal5_fill_pattern;
+ header->res1 = 0;
+
+ /* setup cell header */
+ header->clp = (vcc->atm_options & ATM_ATMOPT_CLP) ? 1 : 0;
+ header->pti = ATM_PTI_US0;
+ header->vci = vcc->vci;
+ header->vpi = vcc->vpi;
+ header->gfc = 0;
+
+ /* setup descriptor */
+ reg_desc.dataptr = (unsigned int)skb->data >> 2;
+ reg_desc.datalen = datalen;
+ reg_desc.byteoff = byteoff;
+ reg_desc.iscell = 0;
+ }
+ else {
+ /* if data pointer is not aligned, allocate new sk_buff */
+ if ( ((unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1)) != 0 ) {
+ struct sk_buff *new_skb;
+
+ err("skb->data not aligned");
+
+ new_skb = alloc_skb_tx(skb->len);
+ if ( new_skb == NULL ) {
+ err("ALLOC_SKB_TX_FAIL");
+ ret = -ENOMEM;
+ goto PPE_SEND_FAIL;
+ }
+ skb_put(new_skb, skb->len);
+ memcpy(new_skb->data, skb->data, skb->len);
+ dev_kfree_skb_any(skb);
+ skb = new_skb;
+ }
+
+ reg_desc.dataptr = (unsigned int)skb->data >> 2;
+ reg_desc.datalen = skb->len;
+ reg_desc.byteoff = 0;
+ reg_desc.iscell = 1;
+ }
+
+ reg_desc.own = 1;
+ reg_desc.c = 1;
+ reg_desc.sop = reg_desc.eop = 1;
+
+ desc_base = get_tx_desc(conn);
+ if ( desc_base < 0 ) {
+ err("ALLOC_TX_CONNECTION_FAIL");
+ ret = -EIO;
+ goto PPE_SEND_FAIL;
+ }
+
+ if ( vcc->stats )
+ atomic_inc(&vcc->stats->tx);
+ if ( vcc->qos.aal == ATM_AAL5 )
+ g_atm_priv_data.wtx_pdu++;
+
+ /* update descriptor send pointer */
+ if ( g_atm_priv_data.conn[conn].tx_skb[desc_base] != NULL )
+ dev_kfree_skb_any(g_atm_priv_data.conn[conn].tx_skb[desc_base]);
+ g_atm_priv_data.conn[conn].tx_skb[desc_base] = skb;
+
+ /* write discriptor to memory and write back cache */
+#ifdef CONFIG_DEBUG_SLAB
+ /* be sure that "redzone 1" is written back to memory */
+ dma_cache_wback((unsigned long)skb->head, 32);
+#endif
+ dma_cache_wback((unsigned long)skb_shinfo(skb), sizeof(struct skb_shared_info));
+ dma_cache_wback((unsigned long)skb->data, skb->len);
+ g_atm_priv_data.conn[conn].tx_desc[desc_base] = reg_desc;
+
+ dump_skb(skb, DUMP_SKB_LEN, (char *)__func__, 0, conn, 1);
+
+ mailbox_signal(conn, 1);
+
+ adsl_led_flash();
+
+ return 0;
+
+FIND_VCC_FAIL:
+ err("FIND_VCC_FAIL");
+ g_atm_priv_data.wtx_err_pdu++;
+ dev_kfree_skb_any(skb);
+ return ret;
+
+PPE_SEND_FAIL:
+ if ( vcc->qos.aal == ATM_AAL5 )
+ g_atm_priv_data.wtx_drop_pdu++;
+ if ( vcc->stats )
+ atomic_inc(&vcc->stats->tx_err);
+ dev_kfree_skb_any(skb);
+ return ret;
+}
+
+static int ppe_send_oam(struct atm_vcc *vcc, void *cell, int flags)
+{
+ int conn;
+ struct uni_cell_header *uni_cell_header = (struct uni_cell_header *)cell;
+ int desc_base;
+ struct sk_buff *skb;
+ struct tx_descriptor reg_desc = {0};
+
+ if ( ((uni_cell_header->pti == ATM_PTI_SEGF5 || uni_cell_header->pti == ATM_PTI_E2EF5)
+ && find_vpivci(uni_cell_header->vpi, uni_cell_header->vci) < 0)
+ || ((uni_cell_header->vci == 0x03 || uni_cell_header->vci == 0x04)
+ && find_vpi(uni_cell_header->vpi) < 0) )
+ return -EINVAL;
+
+ if ( !g_showtime ) {
+ err("not in showtime");
+ return -EIO;
+ }
+
+ conn = find_vcc(vcc);
+ if ( conn < 0 ) {
+ err("FIND_VCC_FAIL");
+ return -EINVAL;
+ }
+
+ skb = alloc_skb_tx(CELL_SIZE);
+ if ( skb == NULL ) {
+ err("ALLOC_SKB_TX_FAIL");
+ return -ENOMEM;
+ }
+ memcpy(skb->data, cell, CELL_SIZE);
+
+ reg_desc.dataptr = (unsigned int)skb->data >> 2;
+ reg_desc.datalen = CELL_SIZE;
+ reg_desc.byteoff = 0;
+ reg_desc.iscell = 1;
+
+ reg_desc.own = 1;
+ reg_desc.c = 1;
+ reg_desc.sop = reg_desc.eop = 1;
+
+ desc_base = get_tx_desc(conn);
+ if ( desc_base < 0 ) {
+ dev_kfree_skb_any(skb);
+ err("ALLOC_TX_CONNECTION_FAIL");
+ return -EIO;
+ }
+
+ if ( vcc->stats )
+ atomic_inc(&vcc->stats->tx);
+
+ /* update descriptor send pointer */
+ if ( g_atm_priv_data.conn[conn].tx_skb[desc_base] != NULL )
+ dev_kfree_skb_any(g_atm_priv_data.conn[conn].tx_skb[desc_base]);
+ g_atm_priv_data.conn[conn].tx_skb[desc_base] = skb;
+
+ /* write discriptor to memory and write back cache */
+ g_atm_priv_data.conn[conn].tx_desc[desc_base] = reg_desc;
+ dma_cache_wback((unsigned long)skb->data, CELL_SIZE);
+
+ dump_skb(skb, DUMP_SKB_LEN, (char *)__func__, 0, conn, 1);
+
+ if ( vcc->qos.aal == ATM_AAL5 && (ifx_atm_dbg_enable & DBG_ENABLE_MASK_MAC_SWAP) ) {
+ skb_swap(skb, reg_desc.byteoff);
+ }
+
+ mailbox_signal(conn, 1);
+
+ adsl_led_flash();
+
+ return 0;
+}
+
+static int ppe_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flags)
+{
+ int conn;
+
+ if ( vcc == NULL || qos == NULL )
+ return -EINVAL;
+
+ conn = find_vcc(vcc);
+ if ( conn < 0 )
+ return -EINVAL;
+
+ set_qsb(vcc, qos, conn);
+
+ return 0;
+}
+
+static INLINE void adsl_led_flash(void)
+{
+#if 0
+#if defined(ENABLE_LED_FRAMEWORK) && ENABLE_LED_FRAMEWORK
+ if ( g_data_led_trigger != NULL )
+ ifx_led_trigger_activate(g_data_led_trigger);
+#else
+ if (!IS_ERR(&ifx_mei_atm_led_blink) && &ifx_mei_atm_led_blink )
+ ifx_mei_atm_led_blink();
+#endif
+#endif
+}
+
+/*
+ * Description:
+ * Add a 32-bit value to 64-bit value, and put result in a 64-bit variable.
+ * Input:
+ * opt1 --- ppe_u64_t, first operand, a 64-bit unsigned integer value
+ * opt2 --- unsigned int, second operand, a 32-bit unsigned integer value
+ * ret --- ppe_u64_t, pointer to a variable to hold result
+ * Output:
+ * none
+ */
+static INLINE void u64_add_u32(ppe_u64_t opt1, unsigned int opt2, ppe_u64_t *ret)
+{
+ ret->l = opt1.l + opt2;
+ if ( ret->l < opt1.l || ret->l < opt2 )
+ ret->h++;
+}
+
+static INLINE struct sk_buff* alloc_skb_rx(void)
+{
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(RX_DMA_CH_AAL_BUF_SIZE + DATA_BUFFER_ALIGNMENT);
+ if ( skb != NULL ) {
+ /* must be burst length alignment */
+ if ( ((unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1)) != 0 )
+ skb_reserve(skb, ~((unsigned int)skb->data + (DATA_BUFFER_ALIGNMENT - 1)) & (DATA_BUFFER_ALIGNMENT - 1));
+ /* pub skb in reserved area "skb->data - 4" */
+ *((struct sk_buff **)skb->data - 1) = skb;
+ /* write back and invalidate cache */
+ dma_cache_wback_inv((unsigned long)skb->data - sizeof(skb), sizeof(skb));
+ /* invalidate cache */
+ dma_cache_inv((unsigned long)skb->data, (unsigned int)skb->end - (unsigned int)skb->data);
+ }
+
+ return skb;
+}
+
+static INLINE struct sk_buff* alloc_skb_tx(unsigned int size)
+{
+ struct sk_buff *skb;
+
+ /* allocate memory including header and padding */
+ size += TX_INBAND_HEADER_LENGTH + MAX_TX_PACKET_ALIGN_BYTES + MAX_TX_PACKET_PADDING_BYTES;
+ size &= ~(DATA_BUFFER_ALIGNMENT - 1);
+ skb = dev_alloc_skb(size + DATA_BUFFER_ALIGNMENT);
+ /* must be burst length alignment */
+ if ( skb != NULL )
+ skb_reserve(skb, (~((unsigned int)skb->data + (DATA_BUFFER_ALIGNMENT - 1)) & (DATA_BUFFER_ALIGNMENT - 1)) + TX_INBAND_HEADER_LENGTH);
+ return skb;
+}
+
+struct sk_buff* atm_alloc_tx(struct atm_vcc *vcc, unsigned int size)
+{
+ int conn;
+ struct sk_buff *skb;
+
+ /* oversize packet */
+ if ( size > aal5s_max_packet_size ) {
+ err("atm_alloc_tx: oversize packet");
+ return NULL;
+ }
+ /* send buffer overflow */
+ if ( atomic_read(&sk_atm(vcc)->sk_wmem_alloc) && !atm_may_send(vcc, size) ) {
+ err("atm_alloc_tx: send buffer overflow");
+ return NULL;
+ }
+ conn = find_vcc(vcc);
+ if ( conn < 0 ) {
+ err("atm_alloc_tx: unknown VCC");
+ return NULL;
+ }
+
+ skb = dev_alloc_skb(size);
+ if ( skb == NULL ) {
+ err("atm_alloc_tx: sk buffer is used up");
+ return NULL;
+ }
+
+ atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
+
+ return skb;
+}
+
+static INLINE void atm_free_tx_skb_vcc(struct sk_buff *skb, struct atm_vcc *vcc)
+{
+ if ( vcc->pop != NULL )
+ vcc->pop(vcc, skb);
+ else
+ dev_kfree_skb_any(skb);
+}
+
+static INLINE struct sk_buff *get_skb_rx_pointer(unsigned int dataptr)
+{
+ unsigned int skb_dataptr;
+ struct sk_buff *skb;
+
+ skb_dataptr = ((dataptr - 1) << 2) | KSEG1;
+ skb = *(struct sk_buff **)skb_dataptr;
+
+ ASSERT((unsigned int)skb >= KSEG0, "invalid skb - skb = %#08x, dataptr = %#08x", (unsigned int)skb, dataptr);
+ ASSERT(((unsigned int)skb->data | KSEG1) == ((dataptr << 2) | KSEG1), "invalid skb - skb = %#08x, skb->data = %#08x, dataptr = %#08x", (unsigned int)skb, (unsigned int)skb->data, dataptr);
+
+ return skb;
+}
+
+static INLINE int get_tx_desc(unsigned int conn)
+{
+ int desc_base = -1;
+ struct connection *p_conn = &g_atm_priv_data.conn[conn];
+
+ if ( p_conn->tx_desc[p_conn->tx_desc_pos].own == 0 ) {
+ desc_base = p_conn->tx_desc_pos;
+ if ( ++(p_conn->tx_desc_pos) == dma_tx_descriptor_length )
+ p_conn->tx_desc_pos = 0;
+ }
+
+ return desc_base;
+}
+
+static INLINE void mailbox_oam_rx_handler(void)
+{
+ unsigned int vlddes = WRX_DMA_CHANNEL_CONFIG(RX_DMA_CH_OAM)->vlddes;
+ struct rx_descriptor reg_desc;
+ struct uni_cell_header *header;
+ int conn;
+ struct atm_vcc *vcc;
+ unsigned int i;
+
+ for ( i = 0; i < vlddes; i++ ) {
+ do {
+ reg_desc = g_atm_priv_data.oam_desc[g_atm_priv_data.oam_desc_pos];
+ } while ( reg_desc.own || !reg_desc.c ); // keep test OWN and C bit until data is ready
+
+ header = (struct uni_cell_header *)&g_atm_priv_data.oam_buf[g_atm_priv_data.oam_desc_pos * RX_DMA_CH_OAM_BUF_SIZE];
+
+ if ( header->pti == ATM_PTI_SEGF5 || header->pti == ATM_PTI_E2EF5 )
+ conn = find_vpivci(header->vpi, header->vci);
+ else if ( header->vci == 0x03 || header->vci == 0x04 )
+ conn = find_vpi(header->vpi);
+ else
+ conn = -1;
+
+ if ( conn >= 0 && g_atm_priv_data.conn[conn].vcc != NULL ) {
+ vcc = g_atm_priv_data.conn[conn].vcc;
+
+ if ( vcc->push_oam != NULL )
+ vcc->push_oam(vcc, header);
+ else
+ ifx_push_oam((unsigned char *)header);
+ adsl_led_flash();
+ }
+
+ reg_desc.byteoff = 0;
+ reg_desc.datalen = RX_DMA_CH_OAM_BUF_SIZE;
+ reg_desc.own = 1;
+ reg_desc.c = 0;
+
+ g_atm_priv_data.oam_desc[g_atm_priv_data.oam_desc_pos] = reg_desc;
+ if ( ++g_atm_priv_data.oam_desc_pos == RX_DMA_CH_OAM_DESC_LEN )
+ g_atm_priv_data.oam_desc_pos = 0;
+
+ mailbox_signal(RX_DMA_CH_OAM, 0);
+ }
+}
+
+static INLINE void mailbox_aal_rx_handler(void)
+{
+ unsigned int vlddes = WRX_DMA_CHANNEL_CONFIG(RX_DMA_CH_AAL)->vlddes;
+ struct rx_descriptor reg_desc;
+ int conn;
+ struct atm_vcc *vcc;
+ struct sk_buff *skb, *new_skb;
+ struct rx_inband_trailer *trailer;
+ unsigned int i;
+
+ for ( i = 0; i < vlddes; i++ ) {
+ do {
+ reg_desc = g_atm_priv_data.aal_desc[g_atm_priv_data.aal_desc_pos];
+ } while ( reg_desc.own || !reg_desc.c ); // keep test OWN and C bit until data is ready
+
+ conn = reg_desc.id;
+
+ if ( g_atm_priv_data.conn[conn].vcc != NULL ) {
+ vcc = g_atm_priv_data.conn[conn].vcc;
+
+ skb = get_skb_rx_pointer(reg_desc.dataptr);
+
+ if ( reg_desc.err ) {
+ if ( vcc->qos.aal == ATM_AAL5 ) {
+ trailer = (struct rx_inband_trailer *)((unsigned int)skb->data + ((reg_desc.byteoff + reg_desc.datalen + MAX_RX_PACKET_PADDING_BYTES) & ~MAX_RX_PACKET_PADDING_BYTES));
+ if ( trailer->stw_crc )
+ g_atm_priv_data.conn[conn].aal5_vcc_crc_err++;
+ if ( trailer->stw_ovz )
+ g_atm_priv_data.conn[conn].aal5_vcc_oversize_sdu++;
+ g_atm_priv_data.wrx_drop_pdu++;
+ }
+ if ( vcc->stats ) {
+ atomic_inc(&vcc->stats->rx_drop);
+ atomic_inc(&vcc->stats->rx_err);
+ }
+ }
+ else if ( atm_charge(vcc, skb->truesize) ) {
+ new_skb = alloc_skb_rx();
+ if ( new_skb != NULL ) {
+ skb_reserve(skb, reg_desc.byteoff);
+ skb_put(skb, reg_desc.datalen);
+ ATM_SKB(skb)->vcc = vcc;
+
+ dump_skb(skb, DUMP_SKB_LEN, (char *)__func__, 0, conn, 0);
+
+ vcc->push(vcc, skb);
+
+ if ( vcc->qos.aal == ATM_AAL5 )
+ g_atm_priv_data.wrx_pdu++;
+ if ( vcc->stats )
+ atomic_inc(&vcc->stats->rx);
+ adsl_led_flash();
+
+ reg_desc.dataptr = (unsigned int)new_skb->data >> 2;
+ }
+ else {
+ atm_return(vcc, skb->truesize);
+ if ( vcc->qos.aal == ATM_AAL5 )
+ g_atm_priv_data.wrx_drop_pdu++;
+ if ( vcc->stats )
+ atomic_inc(&vcc->stats->rx_drop);
+ }
+ }
+ else {
+ if ( vcc->qos.aal == ATM_AAL5 )
+ g_atm_priv_data.wrx_drop_pdu++;
+ if ( vcc->stats )
+ atomic_inc(&vcc->stats->rx_drop);
+ }
+ }
+ else {
+ g_atm_priv_data.wrx_drop_pdu++;
+ }
+
+ reg_desc.byteoff = 0;
+ reg_desc.datalen = RX_DMA_CH_AAL_BUF_SIZE;
+ reg_desc.own = 1;
+ reg_desc.c = 0;
+
+ g_atm_priv_data.aal_desc[g_atm_priv_data.aal_desc_pos] = reg_desc;
+ if ( ++g_atm_priv_data.aal_desc_pos == dma_rx_descriptor_length )
+ g_atm_priv_data.aal_desc_pos = 0;
+
+ mailbox_signal(RX_DMA_CH_AAL, 0);
+ }
+}
+
+#if defined(ENABLE_TASKLET) && ENABLE_TASKLET
+static void do_ppe_tasklet(unsigned long arg)
+{
+ *MBOX_IGU1_ISRC = *MBOX_IGU1_ISR;
+ mailbox_oam_rx_handler();
+ mailbox_aal_rx_handler();
+ if ( (*MBOX_IGU1_ISR & ((1 << RX_DMA_CH_AAL) | (1 << RX_DMA_CH_OAM))) != 0 )
+ tasklet_schedule(&g_dma_tasklet);
+ else
+ enable_irq(PPE_MAILBOX_IGU1_INT);
+}
+#endif
+
+static irqreturn_t mailbox_irq_handler(int irq, void *dev_id)
+{
+ if ( !*MBOX_IGU1_ISR )
+ return IRQ_HANDLED;
+
+#if defined(ENABLE_TASKLET) && ENABLE_TASKLET
+ disable_irq(PPE_MAILBOX_IGU1_INT);
+ tasklet_schedule(&g_dma_tasklet);
+#else
+ *MBOX_IGU1_ISRC = *MBOX_IGU1_ISR;
+ mailbox_oam_rx_handler();
+ mailbox_aal_rx_handler();
+#endif
+
+ return IRQ_HANDLED;
+}
+
+static INLINE void mailbox_signal(unsigned int queue, int is_tx)
+{
+ int count = 1000;
+
+ if ( is_tx ) {
+ while ( MBOX_IGU3_ISR_ISR(queue + FIRST_QSB_QID + 16) && count)
+ count--;
+ *MBOX_IGU3_ISRS = MBOX_IGU3_ISRS_SET(queue + FIRST_QSB_QID + 16);
+ }
+ else {
+ while ( MBOX_IGU3_ISR_ISR(queue) && count)
+ count--;
+ *MBOX_IGU3_ISRS = MBOX_IGU3_ISRS_SET(queue);
+ }
+ ASSERT(count != 0, "MBOX_IGU3_ISR = 0x%08x", ltq_r32(MBOX_IGU3_ISR));
+}
+
+static void set_qsb(struct atm_vcc *vcc, struct atm_qos *qos, unsigned int queue)
+{
+ struct clk *clk = clk_get(0, "fpi");
+ unsigned int qsb_clk = clk_get_rate(clk);
+ unsigned int qsb_qid = queue + FIRST_QSB_QID;
+ union qsb_queue_parameter_table qsb_queue_parameter_table = {{0}};
+ union qsb_queue_vbr_parameter_table qsb_queue_vbr_parameter_table = {{0}};
+ unsigned int tmp;
+
+#if defined(DEBUG_QOS) && DEBUG_QOS
+ if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) ) {
+ static char *str_traffic_class[9] = {
+ "ATM_NONE",
+ "ATM_UBR",
+ "ATM_CBR",
+ "ATM_VBR",
+ "ATM_ABR",
+ "ATM_ANYCLASS",
+ "ATM_VBR_RT",
+ "ATM_UBR_PLUS",
+ "ATM_MAX_PCR"
+ };
+ printk(KERN_INFO "QoS Parameters:\n");
+ printk(KERN_INFO "\tAAL : %d\n", qos->aal);
+ printk(KERN_INFO "\tTX Traffic Class: %s\n", str_traffic_class[qos->txtp.traffic_class]);
+ printk(KERN_INFO "\tTX Max PCR : %d\n", qos->txtp.max_pcr);
+ printk(KERN_INFO "\tTX Min PCR : %d\n", qos->txtp.min_pcr);
+ printk(KERN_INFO "\tTX PCR : %d\n", qos->txtp.pcr);
+ printk(KERN_INFO "\tTX Max CDV : %d\n", qos->txtp.max_cdv);
+ printk(KERN_INFO "\tTX Max SDU : %d\n", qos->txtp.max_sdu);
+ printk(KERN_INFO "\tTX SCR : %d\n", qos->txtp.scr);
+ printk(KERN_INFO "\tTX MBS : %d\n", qos->txtp.mbs);
+ printk(KERN_INFO "\tTX CDV : %d\n", qos->txtp.cdv);
+ printk(KERN_INFO "\tRX Traffic Class: %s\n", str_traffic_class[qos->rxtp.traffic_class]);
+ printk(KERN_INFO "\tRX Max PCR : %d\n", qos->rxtp.max_pcr);
+ printk(KERN_INFO "\tRX Min PCR : %d\n", qos->rxtp.min_pcr);
+ printk(KERN_INFO "\tRX PCR : %d\n", qos->rxtp.pcr);
+ printk(KERN_INFO "\tRX Max CDV : %d\n", qos->rxtp.max_cdv);
+ printk(KERN_INFO "\tRX Max SDU : %d\n", qos->rxtp.max_sdu);
+ printk(KERN_INFO "\tRX SCR : %d\n", qos->rxtp.scr);
+ printk(KERN_INFO "\tRX MBS : %d\n", qos->rxtp.mbs);
+ printk(KERN_INFO "\tRX CDV : %d\n", qos->rxtp.cdv);
+ }
+#endif // defined(DEBUG_QOS) && DEBUG_QOS
+
+ /*
+ * Peak Cell Rate (PCR) Limiter
+ */
+ if ( qos->txtp.max_pcr == 0 )
+ qsb_queue_parameter_table.bit.tp = 0; /* disable PCR limiter */
+ else {
+ /* peak cell rate would be slightly lower than requested [maximum_rate / pcr = (qsb_clock / 8) * (time_step / 4) / pcr] */
+ tmp = ((qsb_clk * qsb_tstep) >> 5) / qos->txtp.max_pcr + 1;
+ /* check if overflow takes place */
+ qsb_queue_parameter_table.bit.tp = tmp > QSB_TP_TS_MAX ? QSB_TP_TS_MAX : tmp;
+ }
+
+ // A funny issue. Create two PVCs, one UBR and one UBR with max_pcr.
+ // Send packets to these two PVCs at same time, it trigger strange behavior.
+ // In A1, RAM from 0x80000000 to 0x0x8007FFFF was corrupted with fixed pattern 0x00000000 0x40000000.
+ // In A4, PPE firmware keep emiting unknown cell and do not respond to driver.
+ // To work around, create UBR always with max_pcr.
+ // If user want to create UBR without max_pcr, we give a default one larger than line-rate.
+ if ( qos->txtp.traffic_class == ATM_UBR && qsb_queue_parameter_table.bit.tp == 0 ) {
+ int port = g_atm_priv_data.conn[queue].port;
+ unsigned int max_pcr = g_atm_priv_data.port[port].tx_max_cell_rate + 1000;
+
+ tmp = ((qsb_clk * qsb_tstep) >> 5) / max_pcr + 1;
+ if ( tmp > QSB_TP_TS_MAX )
+ tmp = QSB_TP_TS_MAX;
+ else if ( tmp < 1 )
+ tmp = 1;
+ qsb_queue_parameter_table.bit.tp = tmp;
+ }
+
+ /*
+ * Weighted Fair Queueing Factor (WFQF)
+ */
+ switch ( qos->txtp.traffic_class ) {
+ case ATM_CBR:
+ case ATM_VBR_RT:
+ /* real time queue gets weighted fair queueing bypass */
+ qsb_queue_parameter_table.bit.wfqf = 0;
+ break;
+ case ATM_VBR_NRT:
+ case ATM_UBR_PLUS:
+ /* WFQF calculation here is based on virtual cell rates, to reduce granularity for high rates */
+ /* WFQF is maximum cell rate / garenteed cell rate */
+ /* wfqf = qsb_minimum_cell_rate * QSB_WFQ_NONUBR_MAX / requested_minimum_peak_cell_rate */
+ if ( qos->txtp.min_pcr == 0 )
+ qsb_queue_parameter_table.bit.wfqf = QSB_WFQ_NONUBR_MAX;
+ else
+ {
+ tmp = QSB_GCR_MIN * QSB_WFQ_NONUBR_MAX / qos->txtp.min_pcr;
+ if ( tmp == 0 )
+ qsb_queue_parameter_table.bit.wfqf = 1;
+ else if ( tmp > QSB_WFQ_NONUBR_MAX )
+ qsb_queue_parameter_table.bit.wfqf = QSB_WFQ_NONUBR_MAX;
+ else
+ qsb_queue_parameter_table.bit.wfqf = tmp;
+ }
+ break;
+ default:
+ case ATM_UBR:
+ qsb_queue_parameter_table.bit.wfqf = QSB_WFQ_UBR_BYPASS;
+ }
+
+ /*
+ * Sustained Cell Rate (SCR) Leaky Bucket Shaper VBR.0/VBR.1
+ */
+ if ( qos->txtp.traffic_class == ATM_VBR_RT || qos->txtp.traffic_class == ATM_VBR_NRT ) {
+ if ( qos->txtp.scr == 0 ) {
+ /* disable shaper */
+ qsb_queue_vbr_parameter_table.bit.taus = 0;
+ qsb_queue_vbr_parameter_table.bit.ts = 0;
+ }
+ else {
+ /* Cell Loss Priority (CLP) */
+ if ( (vcc->atm_options & ATM_ATMOPT_CLP) )
+ /* CLP1 */
+ qsb_queue_parameter_table.bit.vbr = 1;
+ else
+ /* CLP0 */
+ qsb_queue_parameter_table.bit.vbr = 0;
+ /* Rate Shaper Parameter (TS) and Burst Tolerance Parameter for SCR (tauS) */
+ tmp = ((qsb_clk * qsb_tstep) >> 5) / qos->txtp.scr + 1;
+ qsb_queue_vbr_parameter_table.bit.ts = tmp > QSB_TP_TS_MAX ? QSB_TP_TS_MAX : tmp;
+ tmp = (qos->txtp.mbs - 1) * (qsb_queue_vbr_parameter_table.bit.ts - qsb_queue_parameter_table.bit.tp) / 64;
+ if ( tmp == 0 )
+ qsb_queue_vbr_parameter_table.bit.taus = 1;
+ else if ( tmp > QSB_TAUS_MAX )
+ qsb_queue_vbr_parameter_table.bit.taus = QSB_TAUS_MAX;
+ else
+ qsb_queue_vbr_parameter_table.bit.taus = tmp;
+ }
+ }
+ else {
+ qsb_queue_vbr_parameter_table.bit.taus = 0;
+ qsb_queue_vbr_parameter_table.bit.ts = 0;
+ }
+
+ /* Queue Parameter Table (QPT) */
+ *QSB_RTM = QSB_RTM_DM_SET(QSB_QPT_SET_MASK);
+ *QSB_RTD = QSB_RTD_TTV_SET(qsb_queue_parameter_table.dword);
+ *QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_QPT) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(qsb_qid);
+#if defined(DEBUG_QOS) && DEBUG_QOS
+ if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) )
+ printk("QPT: QSB_RTM (%08X) = 0x%08X, QSB_RTD (%08X) = 0x%08X, QSB_RAMAC (%08X) = 0x%08X\n", (unsigned int)QSB_RTM, *QSB_RTM, (unsigned int)QSB_RTD, *QSB_RTD, (unsigned int)QSB_RAMAC, *QSB_RAMAC);
+#endif
+ /* Queue VBR Paramter Table (QVPT) */
+ *QSB_RTM = QSB_RTM_DM_SET(QSB_QVPT_SET_MASK);
+ *QSB_RTD = QSB_RTD_TTV_SET(qsb_queue_vbr_parameter_table.dword);
+ *QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_VBR) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(qsb_qid);
+#if defined(DEBUG_QOS) && DEBUG_QOS
+ if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) )
+ printk("QVPT: QSB_RTM (%08X) = 0x%08X, QSB_RTD (%08X) = 0x%08X, QSB_RAMAC (%08X) = 0x%08X\n", (unsigned int)QSB_RTM, *QSB_RTM, (unsigned int)QSB_RTD, *QSB_RTD, (unsigned int)QSB_RAMAC, *QSB_RAMAC);
+#endif
+
+#if defined(DEBUG_QOS) && DEBUG_QOS
+ if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) ) {
+ printk("set_qsb\n");
+ printk(" qsb_clk = %lu\n", (unsigned long)qsb_clk);
+ printk(" qsb_queue_parameter_table.bit.tp = %d\n", (int)qsb_queue_parameter_table.bit.tp);
+ printk(" qsb_queue_parameter_table.bit.wfqf = %d (0x%08X)\n", (int)qsb_queue_parameter_table.bit.wfqf, (int)qsb_queue_parameter_table.bit.wfqf);
+ printk(" qsb_queue_parameter_table.bit.vbr = %d\n", (int)qsb_queue_parameter_table.bit.vbr);
+ printk(" qsb_queue_parameter_table.dword = 0x%08X\n", (int)qsb_queue_parameter_table.dword);
+ printk(" qsb_queue_vbr_parameter_table.bit.ts = %d\n", (int)qsb_queue_vbr_parameter_table.bit.ts);
+ printk(" qsb_queue_vbr_parameter_table.bit.taus = %d\n", (int)qsb_queue_vbr_parameter_table.bit.taus);
+ printk(" qsb_queue_vbr_parameter_table.dword = 0x%08X\n", (int)qsb_queue_vbr_parameter_table.dword);
+ }
+#endif
+}
+
+static void qsb_global_set(void)
+{
+ struct clk *clk = clk_get(0, "fpi");
+ unsigned int qsb_clk = clk_get_rate(clk);
+ int i;
+ unsigned int tmp1, tmp2, tmp3;
+
+ *QSB_ICDV = QSB_ICDV_TAU_SET(qsb_tau);
+ *QSB_SBL = QSB_SBL_SBL_SET(qsb_srvm);
+ *QSB_CFG = QSB_CFG_TSTEPC_SET(qsb_tstep >> 1);
+#if defined(DEBUG_QOS) && DEBUG_QOS
+ if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) ) {
+ printk("qsb_clk = %u\n", qsb_clk);
+ printk("QSB_ICDV (%08X) = %d (%d), QSB_SBL (%08X) = %d (%d), QSB_CFG (%08X) = %d (%d)\n", (unsigned int)QSB_ICDV, *QSB_ICDV, QSB_ICDV_TAU_SET(qsb_tau), (unsigned int)QSB_SBL, *QSB_SBL, QSB_SBL_SBL_SET(qsb_srvm), (unsigned int)QSB_CFG, *QSB_CFG, QSB_CFG_TSTEPC_SET(qsb_tstep >> 1));
+ }
+#endif
+
+ /*
+ * set SCT and SPT per port
+ */
+ for ( i = 0; i < ATM_PORT_NUMBER; i++ ) {
+ if ( g_atm_priv_data.port[i].tx_max_cell_rate != 0 ) {
+ tmp1 = ((qsb_clk * qsb_tstep) >> 1) / g_atm_priv_data.port[i].tx_max_cell_rate;
+ tmp2 = tmp1 >> 6; /* integer value of Tsb */
+ tmp3 = (tmp1 & ((1 << 6) - 1)) + 1; /* fractional part of Tsb */
+ /* carry over to integer part (?) */
+ if ( tmp3 == (1 << 6) )
+ {
+ tmp3 = 0;
+ tmp2++;
+ }
+ if ( tmp2 == 0 )
+ tmp2 = tmp3 = 1;
+ /* 1. set mask */
+ /* 2. write value to data transfer register */
+ /* 3. start the tranfer */
+ /* SCT (FracRate) */
+ *QSB_RTM = QSB_RTM_DM_SET(QSB_SET_SCT_MASK);
+ *QSB_RTD = QSB_RTD_TTV_SET(tmp3);
+ *QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_SCT) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(i & 0x01);
+#if defined(DEBUG_QOS) && DEBUG_QOS
+ if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) )
+ printk("SCT: QSB_RTM (%08X) = 0x%08X, QSB_RTD (%08X) = 0x%08X, QSB_RAMAC (%08X) = 0x%08X\n", (unsigned int)QSB_RTM, *QSB_RTM, (unsigned int)QSB_RTD, *QSB_RTD, (unsigned int)QSB_RAMAC, *QSB_RAMAC);
+#endif
+ /* SPT (SBV + PN + IntRage) */
+ *QSB_RTM = QSB_RTM_DM_SET(QSB_SET_SPT_MASK);
+ *QSB_RTD = QSB_RTD_TTV_SET(QSB_SPT_SBV_VALID | QSB_SPT_PN_SET(i & 0x01) | QSB_SPT_INTRATE_SET(tmp2));
+ *QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_SPT) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(i & 0x01);
+#if defined(DEBUG_QOS) && DEBUG_QOS
+ if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) )
+ printk("SPT: QSB_RTM (%08X) = 0x%08X, QSB_RTD (%08X) = 0x%08X, QSB_RAMAC (%08X) = 0x%08X\n", (unsigned int)QSB_RTM, *QSB_RTM, (unsigned int)QSB_RTD, *QSB_RTD, (unsigned int)QSB_RAMAC, *QSB_RAMAC);
+#endif
+ }
+ }
+}
+
+static INLINE void set_htu_entry(unsigned int vpi, unsigned int vci, unsigned int queue, int aal5, int is_retx)
+{
+ struct htu_entry htu_entry = { res1: 0x00,
+ clp: is_retx ? 0x01 : 0x00,
+ pid: g_atm_priv_data.conn[queue].port & 0x01,
+ vpi: vpi,
+ vci: vci,
+ pti: 0x00,
+ vld: 0x01};
+
+ struct htu_mask htu_mask = { set: 0x01,
+#if !defined(ENABLE_ATM_RETX) || !ENABLE_ATM_RETX
+ clp: 0x01,
+ pid_mask: 0x02,
+#else
+ clp: g_retx_htu ? 0x00 : 0x01,
+ pid_mask: RETX_MODE_CFG->retx_en ? 0x03 : 0x02,
+#endif
+ vpi_mask: 0x00,
+#if !defined(ENABLE_ATM_RETX) || !ENABLE_ATM_RETX
+ vci_mask: 0x0000,
+#else
+ vci_mask: RETX_MODE_CFG->retx_en ? 0xFF00 : 0x0000,
+#endif
+ pti_mask: 0x03, // 0xx, user data
+ clear: 0x00};
+
+ struct htu_result htu_result = {res1: 0x00,
+ cellid: queue,
+ res2: 0x00,
+ type: aal5 ? 0x00 : 0x01,
+ ven: 0x01,
+ res3: 0x00,
+ qid: queue};
+
+ *HTU_RESULT(queue + OAM_HTU_ENTRY_NUMBER) = htu_result;
+ *HTU_MASK(queue + OAM_HTU_ENTRY_NUMBER) = htu_mask;
+ *HTU_ENTRY(queue + OAM_HTU_ENTRY_NUMBER) = htu_entry;
+}
+
+static INLINE void clear_htu_entry(unsigned int queue)
+{
+ HTU_ENTRY(queue + OAM_HTU_ENTRY_NUMBER)->vld = 0;
+}
+
+static void validate_oam_htu_entry(void)
+{
+ HTU_ENTRY(OAM_F4_SEG_HTU_ENTRY)->vld = 1;
+ HTU_ENTRY(OAM_F4_TOT_HTU_ENTRY)->vld = 1;
+ HTU_ENTRY(OAM_F5_HTU_ENTRY)->vld = 1;
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ HTU_ENTRY(OAM_ARQ_HTU_ENTRY)->vld = 1;
+#endif
+}
+
+static void invalidate_oam_htu_entry(void)
+{
+ HTU_ENTRY(OAM_F4_SEG_HTU_ENTRY)->vld = 0;
+ HTU_ENTRY(OAM_F4_TOT_HTU_ENTRY)->vld = 0;
+ HTU_ENTRY(OAM_F5_HTU_ENTRY)->vld = 0;
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ HTU_ENTRY(OAM_ARQ_HTU_ENTRY)->vld = 0;
+#endif
+}
+
+static INLINE int find_vpi(unsigned int vpi)
+{
+ int i;
+ unsigned int bit;
+
+ for ( i = 0, bit = 1; i < MAX_PVC_NUMBER; i++, bit <<= 1 ) {
+ if ( (g_atm_priv_data.conn_table & bit) != 0
+ && g_atm_priv_data.conn[i].vcc != NULL
+ && vpi == g_atm_priv_data.conn[i].vcc->vpi )
+ return i;
+ }
+
+ return -1;
+}
+
+static INLINE int find_vpivci(unsigned int vpi, unsigned int vci)
+{
+ int i;
+ unsigned int bit;
+
+ for ( i = 0, bit = 1; i < MAX_PVC_NUMBER; i++, bit <<= 1 ) {
+ if ( (g_atm_priv_data.conn_table & bit) != 0
+ && g_atm_priv_data.conn[i].vcc != NULL
+ && vpi == g_atm_priv_data.conn[i].vcc->vpi
+ && vci == g_atm_priv_data.conn[i].vcc->vci )
+ return i;
+ }
+
+ return -1;
+}
+
+static INLINE int find_vcc(struct atm_vcc *vcc)
+{
+ int i;
+ unsigned int bit;
+
+ for ( i = 0, bit = 1; i < MAX_PVC_NUMBER; i++, bit <<= 1 ) {
+ if ( (g_atm_priv_data.conn_table & bit) != 0
+ && g_atm_priv_data.conn[i].vcc == vcc )
+ return i;
+ }
+
+ return -1;
+}
+
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+
+static void retx_polling_func(unsigned long arg)
+{
+ int sys_flag;
+ volatile struct dsl_param *p_dsl_param;
+ int new_retx_htu;
+ int retx_en;
+ int i, max_htu;
+
+ local_irq_save(sys_flag);
+ if ( g_retx_playout_buffer == 0 && g_xdata_addr != NULL && (((volatile struct dsl_param *)g_xdata_addr)->RetxEnable || ((volatile struct dsl_param *)g_xdata_addr)->ServiceSpecificReTx) ) {
+ local_irq_restore(sys_flag);
+ g_retx_playout_buffer = __get_free_pages(GFP_KERNEL, RETX_PLAYOUT_BUFFER_ORDER);
+ if ( g_retx_playout_buffer == 0 )
+ panic("no memory for g_retx_playout_buffer\n");
+ memset((void *)g_retx_playout_buffer, 0, RETX_PLAYOUT_BUFFER_SIZE);
+ dma_cache_inv(g_retx_playout_buffer, RETX_PLAYOUT_BUFFER_SIZE);
+ }
+ else
+ local_irq_restore(sys_flag);
+
+
+ local_irq_save(sys_flag);
+ if ( g_xdata_addr != NULL ) {
+ p_dsl_param = (volatile struct dsl_param *)g_xdata_addr;
+ g_retx_polling_cnt += RETX_POLLING_INTERVAL;
+
+ if ( p_dsl_param->update_flag ) {
+ do_gettimeofday(&g_retx_polling_start);
+
+ g_dsl_param = *p_dsl_param;
+
+ // we always enable retx (just for test purpose)
+ //g_dsl_param.RetxEnable = 1;
+ //RETX_TSYNC_CFG->fw_alpha = 0;
+
+ if ( g_dsl_param.RetxEnable || g_dsl_param.ServiceSpecificReTx ) {
+ // ReTX enabled
+ // MIB counter updated for each polling
+ p_dsl_param->RxDtuCorruptedCNT = *RxDTUCorruptedCNT;
+ p_dsl_param->RxRetxDtuUnCorrectedCNT = *RxRetxDTUUncorrectedCNT;
+ p_dsl_param->RxLastEFB = *RxLastEFBCNT;
+ p_dsl_param->RxDtuCorrectedCNT = *RxDTUCorrectedCNT;
+
+ // for RETX paramters, we check only once for every second
+ if ( g_retx_polling_cnt < HZ )
+ goto _clear_update_flag;
+
+ g_retx_polling_cnt -= HZ;
+
+ if ( g_dsl_param.ServiceSpecificReTx && g_dsl_param.ReTxPVC == 0 )
+ new_retx_htu = 1;
+ else
+ new_retx_htu = 0;
+
+ // default fw_alpha equals to default hardware alpha
+ RETX_TSYNC_CFG->fw_alpha = 0;
+
+ RETX_TD_CFG->td_max = g_dsl_param.MaxDelayrt;
+ RETX_TD_CFG->td_min = g_dsl_param.MinDelayrt;
+
+ *RETX_PLAYOUT_BUFFER_BASE = ((((unsigned int)g_retx_playout_buffer | KSEG1) + 15) & 0xFFFFFFF0) >> 2;
+
+ if ( g_dsl_param.ServiceSpecificReTx ) {
+ *RETX_SERVICE_HEADER_CFG= g_dsl_param.ReTxPVC << 4;
+ if ( g_dsl_param.ReTxPVC == 0 )
+ *RETX_MASK_HEADER_CFG = 1;
+ else
+ *RETX_MASK_HEADER_CFG = 0;
+ }
+ else {
+ *RETX_SERVICE_HEADER_CFG= 0;
+ *RETX_MASK_HEADER_CFG = 0;
+ }
+
+ retx_en = 1;
+ }
+ else {
+ // ReTX disabled
+
+ new_retx_htu = 0;
+
+ RETX_TSYNC_CFG->fw_alpha = 7;
+
+ *RETX_SERVICE_HEADER_CFG = 0;
+ *RETX_MASK_HEADER_CFG = 0;
+
+ retx_en = 0;
+ }
+
+
+ if ( retx_en != RETX_MODE_CFG->retx_en ) {
+ unsigned int pid_mask, vci_mask;
+
+ if ( retx_en ) {
+ pid_mask = 0x03;
+ vci_mask = 0xFF00;
+ }
+ else {
+ pid_mask = 0x02;
+ vci_mask = 0x0000;
+ }
+
+ max_htu = *CFG_WRX_HTUTS;
+ for ( i = OAM_HTU_ENTRY_NUMBER; i < max_htu; i++ )
+ if ( HTU_ENTRY(i)->vld ) {
+ HTU_MASK(i)->pid_mask = pid_mask;
+ HTU_MASK(i)->vci_mask = vci_mask;
+ }
+ }
+
+ if ( new_retx_htu != g_retx_htu ) {
+ int conn, retx_conn;
+
+ g_retx_htu = new_retx_htu;
+
+ if ( g_retx_htu ) {
+ max_htu = *CFG_WRX_HTUTS;
+ for ( i = OAM_HTU_ENTRY_NUMBER; i < max_htu; i++ )
+ if ( HTU_ENTRY(i)->vld )
+ HTU_MASK(i)->clp = 0;
+
+ for ( conn = 0; conn < MAX_PVC_NUMBER; conn++ )
+ if ( g_atm_priv_data.conn[conn].vcc && g_atm_priv_data.conn[conn].vcc->qos.aal == ATM_AAL5 && !HTU_ENTRY(conn + OAM_HTU_ENTRY_NUMBER)->clp ) {
+ retx_conn = (conn + 8) % 16; // ReTX queue
+
+ if ( retx_conn < MAX_PVC_NUMBER && test_and_set_bit(retx_conn, &g_atm_priv_data.conn_table) == 0 ) {
+ g_atm_priv_data.conn[retx_conn].vcc = g_atm_priv_data.conn[conn].vcc;
+ set_htu_entry(g_atm_priv_data.conn[conn].vcc->vpi, g_atm_priv_data.conn[conn].vcc->vci, retx_conn, g_atm_priv_data.conn[conn].vcc->qos.aal == ATM_AAL5 ? 1 : 0, 1);
+ }
+ else {
+ err("Queue number %d for ReTX queue of PVC(%d.%d) is not available!", retx_conn, g_atm_priv_data.conn[conn].vcc->vpi, g_atm_priv_data.conn[conn].vcc->vci);
+ }
+ }
+ }
+ else
+ {
+ for ( retx_conn = 0; retx_conn < MAX_PVC_NUMBER; retx_conn++ )
+ if ( g_atm_priv_data.conn[retx_conn].vcc && HTU_ENTRY(retx_conn + OAM_HTU_ENTRY_NUMBER)->clp ) {
+ clear_htu_entry(retx_conn);
+ g_atm_priv_data.conn[retx_conn].vcc = NULL;
+ g_atm_priv_data.conn[retx_conn].aal5_vcc_crc_err = 0;
+ g_atm_priv_data.conn[retx_conn].aal5_vcc_oversize_sdu = 0;
+ clear_bit(retx_conn, &g_atm_priv_data.conn_table);
+ }
+
+ max_htu = *CFG_WRX_HTUTS;
+ for ( i = OAM_HTU_ENTRY_NUMBER; i < max_htu; i++ )
+ if ( HTU_ENTRY(i)->vld )
+ HTU_MASK(i)->clp = 1;
+ }
+ }
+
+ RETX_MODE_CFG->retx_en = retx_en;
+
+_clear_update_flag:
+ p_dsl_param->update_flag = 0;
+
+ do_gettimeofday(&g_retx_polling_end);
+ }
+
+ g_retx_polling_timer.expires = jiffies + RETX_POLLING_INTERVAL;
+ add_timer(&g_retx_polling_timer);
+ }
+ local_irq_restore(sys_flag);
+}
+
+static int init_atm_tc_retrans_param(void)
+{
+ int i = 0;
+ struct DTU_stat_info reset_val;
+
+ RETX_MODE_CFG->invld_range = 128;
+ RETX_MODE_CFG->buff_size = RETX_PLAYOUT_FW_BUFF_SIZE > 4096/32 ? 4096/32 : RETX_PLAYOUT_FW_BUFF_SIZE ;
+ RETX_MODE_CFG->retx_en = 1;
+
+ // default fw_alpha equals to default hardware alpha
+ RETX_TSYNC_CFG->fw_alpha = 7;
+ RETX_TSYNC_CFG->sync_inp = 0;
+
+ RETX_TD_CFG->td_max = 0;
+ RETX_TD_CFG->td_min = 0;
+
+ // *RETX_PLAYOUT_BUFFER_BASE = KSEG1ADDR(g_retx_playout_buffer); // need " >> 2 " ?
+ *RETX_PLAYOUT_BUFFER_BASE = ((((unsigned int)g_retx_playout_buffer | KSEG1) + 15) & 0xFFFFFFF0) >> 2;
+
+ *RETX_SERVICE_HEADER_CFG = 0;
+ *RETX_MASK_HEADER_CFG = 0;
+
+ // 20us
+ RETX_MIB_TIMER_CFG->tick_cycle = 4800;
+ RETX_MIB_TIMER_CFG->ticks_per_sec = 50000;
+
+ *LAST_DTU_SID_IN = 255;
+ *RFBI_FIRST_CW = 1;
+ // init DTU_STAT_INFO
+
+ memset(&reset_val, 0, sizeof(reset_val));
+ reset_val.dtu_rd_ptr = reset_val.dtu_wr_ptr = 0xffff;
+
+ for(i = 0 ; i < 256; i ++) {
+ DTU_STAT_INFO[i] = reset_val;
+ }
+ return 0;
+}
+
+static void clear_atm_tc_retrans_param(void)
+{
+ if ( g_retx_playout_buffer ) {
+ free_pages(g_retx_playout_buffer, RETX_PLAYOUT_BUFFER_ORDER);
+ g_retx_playout_buffer = 0;
+ }
+}
+
+#endif
+
+#if defined(DEBUG_DUMP_SKB) && DEBUG_DUMP_SKB
+static void dump_skb(struct sk_buff *skb, unsigned int len, char *title, int port, int ch, int is_tx)
+{
+ int i;
+
+ if ( !(ifx_atm_dbg_enable & (is_tx ? DBG_ENABLE_MASK_DUMP_SKB_TX : DBG_ENABLE_MASK_DUMP_SKB_RX)) )
+ return;
+
+ if ( skb->len < len )
+ len = skb->len;
+
+ if ( len > RX_DMA_CH_AAL_BUF_SIZE ) {
+ printk("too big data length: skb = %08x, skb->data = %08x, skb->len = %d\n", (unsigned int)skb, (unsigned int)skb->data, skb->len);
+ return;
+ }
+
+ if ( ch >= 0 )
+ printk("%s (port %d, ch %d)\n", title, port, ch);
+ else
+ printk("%s\n", title);
+ printk(" skb->data = %08X, skb->tail = %08X, skb->len = %d\n", (unsigned int)skb->data, (unsigned int)skb->tail, (int)skb->len);
+ for ( i = 1; i <= len; i++ ) {
+ if ( i % 16 == 1 )
+ printk(" %4d:", i - 1);
+ printk(" %02X", (int)(*((char*)skb->data + i - 1) & 0xFF));
+ if ( i % 16 == 0 )
+ printk("\n");
+ }
+ if ( (i - 1) % 16 != 0 )
+ printk("\n");
+}
+#endif
+
+#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC
+static void skb_swap(struct sk_buff *skb, unsigned int byteoff)
+{
+ unsigned int mac_offset = ~0;
+ unsigned int ip_offset = ~0;
+ unsigned char tmp[8];
+ unsigned char *p = NULL;
+
+ skb_pull(skb, byteoff + TX_INBAND_HEADER_LENGTH);
+
+ if ( skb->data[0] == 0xAA && skb->data[1] == 0xAA && skb->data[2] == 0x03 ) {
+ // LLC
+ if ( skb->data[3] == 0x00 && skb->data[4] == 0x80 && skb->data[5] == 0xC2 ) {
+ // EoA
+ if ( skb->data[22] == 0x08 && skb->data[23] == 0x00 ) {
+ // IPv4
+ mac_offset = 10;
+ ip_offset = 24;
+ }
+ else if ( skb->data[31] == 0x21 ) {
+ // PPPoE IPv4
+ mac_offset = 10;
+ ip_offset = 32;
+ }
+ }
+ else {
+ // IPoA
+ if ( skb->data[6] == 0x08 && skb->data[7] == 0x00 ) {
+ // IPv4
+ ip_offset = 8;
+ }
+ }
+ }
+ else if ( skb->data[0] == 0xFE && skb->data[1] == 0xFE && skb->data[2] == 0x03 ) {
+ // LLC PPPoA
+ if ( skb->data[4] == 0x00 && skb->data[5] == 0x21 ) {
+ // IPv4
+ ip_offset = 6;
+ }
+ }
+ else {
+ // VC-mux
+ if ( skb->data[0] == 0x00 && skb->data[1] == 0x21 ) {
+ // PPPoA IPv4
+ ip_offset = 2;
+ }
+ else if ( skb->data[0] == 0x00 && skb->data[1] == 0x00 ) {
+ // EoA
+ if ( skb->data[14] == 0x08 && skb->data[15] ==0x00 ) {
+ // IPv4
+ mac_offset = 2;
+ ip_offset = 16;
+ }
+ else if ( skb->data[23] == 0x21 ) {
+ // PPPoE IPv4
+ mac_offset = 2;
+ ip_offset = 26;
+ }
+ }
+ else {
+ // IPoA
+ ip_offset = 0;
+ }
+ }
+
+ if ( mac_offset != ~0 && !(skb->data[mac_offset] & 0x01) ) {
+ p = skb->data + mac_offset;
+ // swap MAC
+ memcpy(tmp, p, 6);
+ memcpy(p, p + 6, 6);
+ memcpy(p + 6, tmp, 6);
+ p += 12;
+ }
+
+ if ( ip_offset != ~0 ) {
+ p = skb->data + ip_offset + 12;
+ // swap IP
+ memcpy(tmp, p, 4);
+ memcpy(p, p + 4, 4);
+ memcpy(p + 4, tmp, 4);
+ p += 8;
+ }
+
+ if ( p != NULL ) {
+ dma_cache_wback((unsigned long)skb->data, (unsigned long)p - (unsigned long)skb->data);
+ }
+
+ skb_push(skb, byteoff + TX_INBAND_HEADER_LENGTH);
+}
+#endif
+
+static INLINE void proc_file_create(void)
+{
+ struct proc_dir_entry *res;
+
+ g_atm_dir = proc_mkdir("driver/ifx_atm", NULL);
+
+ create_proc_read_entry("version",
+ 0,
+ g_atm_dir,
+ proc_read_version,
+ NULL);
+
+ res = create_proc_entry("mib",
+ 0,
+ g_atm_dir);
+ if ( res != NULL ) {
+ res->read_proc = proc_read_mib;
+ res->write_proc = proc_write_mib;
+ }
+
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ res = create_proc_entry("retx_mib",
+ 0,
+ g_atm_dir);
+ if ( res != NULL ) {
+ res->read_proc = proc_read_retx_mib;
+ res->write_proc = proc_write_retx_mib;
+ }
+#endif
+
+#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC
+ res = create_proc_entry("dbg",
+ 0,
+ g_atm_dir);
+ if ( res != NULL ) {
+ res->read_proc = proc_read_dbg;
+ res->write_proc = proc_write_dbg;
+ }
+
+ res = create_proc_entry("mem",
+ 0,
+ g_atm_dir);
+ if ( res != NULL )
+ res->write_proc = proc_write_mem;
+
+ #if defined(CONFIG_AR9) || defined(CONFIG_VR9) || defined(CONFIG_DANUBE) || defined(CONFIG_AMAZON_SE)
+ res = create_proc_entry("pp32",
+ 0,
+ g_atm_dir);
+ if ( res != NULL ) {
+ res->read_proc = proc_read_pp32;
+ res->write_proc = proc_write_pp32;
+ }
+ #endif
+#endif
+
+#if defined(ENABLE_FW_PROC) && ENABLE_FW_PROC
+ create_proc_read_entry("htu",
+ 0,
+ g_atm_dir,
+ proc_read_htu,
+ NULL);
+
+ create_proc_read_entry("txq",
+ 0,
+ g_atm_dir,
+ proc_read_txq,
+ NULL);
+
+ #if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ create_proc_read_entry("retx_fw",
+ 0,
+ g_atm_dir,
+ proc_read_retx_fw,
+ NULL);
+
+ res = create_proc_entry("retx_stats",
+ 0,
+ g_atm_dir);
+ if ( res != NULL ) {
+ res->read_proc = proc_read_retx_stats;
+ res->write_proc = proc_write_retx_stats;
+ }
+
+ res = create_proc_entry("retx_cfg",
+ 0,
+ g_atm_dir);
+ if ( res != NULL ) {
+ res->read_proc = proc_read_retx_cfg;
+ res->write_proc = proc_write_retx_cfg;
+ }
+
+ create_proc_read_entry("retx_dsl_param",
+ 0,
+ g_atm_dir,
+ proc_read_retx_dsl_param,
+ NULL);
+ #endif
+#endif
+}
+
+static INLINE void proc_file_delete(void)
+{
+#if defined(ENABLE_FW_PROC) && ENABLE_FW_PROC
+ #if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ remove_proc_entry("retx_dsl_param", g_atm_dir);
+
+ remove_proc_entry("retx_cfg", g_atm_dir);
+
+ remove_proc_entry("retx_stats", g_atm_dir);
+
+ remove_proc_entry("retx_fw", g_atm_dir);
+ #endif
+
+ remove_proc_entry("txq", g_atm_dir);
+
+ remove_proc_entry("htu", g_atm_dir);
+#endif
+
+#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC
+ #if defined(CONFIG_AR9) || defined(CONFIG_VR9) || defined(CONFIG_DANUBE) || defined(CONFIG_AMAZON_SE)
+ remove_proc_entry("pp32", g_atm_dir);
+ #endif
+
+ remove_proc_entry("mem", g_atm_dir);
+
+ remove_proc_entry("dbg", g_atm_dir);
+#endif
+
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ remove_proc_entry("retx_mib", g_atm_dir);
+#endif
+
+ remove_proc_entry("mib", g_atm_dir);
+
+ remove_proc_entry("version", g_atm_dir);
+
+ remove_proc_entry("driver/ifx_atm", NULL);
+}
+
+static int proc_read_version(char *buf, char **start, off_t offset, int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len += ifx_atm_version(buf + len);
+
+ if ( offset >= len ) {
+ *start = buf;
+ *eof = 1;
+ return 0;
+ }
+ *start = buf + offset;
+ if ( (len -= offset) > count )
+ return count;
+ *eof = 1;
+ return len;
+}
+
+static int proc_read_mib(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len += sprintf(page + off + len, "Firmware\n");
+ len += sprintf(page + off + len, " wrx_drophtu_cell = %u\n", WAN_MIB_TABLE->wrx_drophtu_cell);
+ len += sprintf(page + off + len, " wrx_dropdes_pdu = %u\n", WAN_MIB_TABLE->wrx_dropdes_pdu);
+ len += sprintf(page + off + len, " wrx_correct_pdu = %u\n", WAN_MIB_TABLE->wrx_correct_pdu);
+ len += sprintf(page + off + len, " wrx_err_pdu = %u\n", WAN_MIB_TABLE->wrx_err_pdu);
+ len += sprintf(page + off + len, " wrx_dropdes_cell = %u\n", WAN_MIB_TABLE->wrx_dropdes_cell);
+ len += sprintf(page + off + len, " wrx_correct_cell = %u\n", WAN_MIB_TABLE->wrx_correct_cell);
+ len += sprintf(page + off + len, " wrx_err_cell = %u\n", WAN_MIB_TABLE->wrx_err_cell);
+ len += sprintf(page + off + len, " wrx_total_byte = %u\n", WAN_MIB_TABLE->wrx_total_byte);
+ len += sprintf(page + off + len, " wtx_total_pdu = %u\n", WAN_MIB_TABLE->wtx_total_pdu);
+ len += sprintf(page + off + len, " wtx_total_cell = %u\n", WAN_MIB_TABLE->wtx_total_cell);
+ len += sprintf(page + off + len, " wtx_total_byte = %u\n", WAN_MIB_TABLE->wtx_total_byte);
+ len += sprintf(page + off + len, "Driver\n");
+ len += sprintf(page + off + len, " wrx_pdu = %u\n", g_atm_priv_data.wrx_pdu);
+ len += sprintf(page + off + len, " wrx_drop_pdu = %u\n", g_atm_priv_data.wrx_drop_pdu);
+ len += sprintf(page + off + len, " wtx_pdu = %u\n", g_atm_priv_data.wtx_pdu);
+ len += sprintf(page + off + len, " wtx_err_pdu = %u\n", g_atm_priv_data.wtx_err_pdu);
+ len += sprintf(page + off + len, " wtx_drop_pdu = %u\n", g_atm_priv_data.wtx_drop_pdu);
+
+ *eof = 1;
+
+ return len;
+}
+
+static int proc_write_mib(struct file *file, const char *buf, unsigned long count, void *data)
+{
+ char str[1024];
+ char *p;
+ int len, rlen;
+
+ len = count < sizeof(str) ? count : sizeof(str) - 1;
+ rlen = len - copy_from_user(str, buf, len);
+ while ( rlen && str[rlen - 1] <= ' ' )
+ rlen--;
+ str[rlen] = 0;
+ for ( p = str; *p && *p <= ' '; p++, rlen-- );
+ if ( !*p )
+ return 0;
+
+ if ( stricmp(p, "clear") == 0 || stricmp(p, "clear all") == 0
+ || stricmp(p, "clean") == 0 || stricmp(p, "clean all") == 0 ) {
+ memset(WAN_MIB_TABLE, 0, sizeof(*WAN_MIB_TABLE));
+ g_atm_priv_data.wrx_pdu = 0;
+ g_atm_priv_data.wrx_drop_pdu = 0;
+ g_atm_priv_data.wtx_pdu = 0;
+ g_atm_priv_data.wtx_err_pdu = 0;
+ g_atm_priv_data.wtx_drop_pdu = 0;
+ }
+
+ return count;
+}
+
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+
+static int proc_read_retx_mib(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ int len = 0;
+
+ printk("Retx FW DTU MIB :\n");
+ printk(" rx_total_dtu = %u\n", *URETX_RX_TOTAL_DTU);
+ printk(" rx_bad_dtu = %u\n", *URETX_RX_BAD_DTU);
+ printk(" rx_good_dtu = %u\n", *URETX_RX_GOOD_DTU);
+ printk(" rx_corrected_dtu = %u\n", *URETX_RX_CORRECTED_DTU);
+ printk(" rx_outofdate_dtu = %u\n", *URETX_RX_OUTOFDATE_DTU);
+ printk(" rx_duplicate_dtu = %u\n", *URETX_RX_DUPLICATE_DTU);
+ printk(" rx_timeout_dtu = %u\n", *URETX_RX_TIMEOUT_DTU);
+ printk(" RxDTURetransmittedCNT = %u\n", *RxDTURetransmittedCNT);
+ printk("\n");
+
+ printk("Retx Standard DTU MIB:\n");
+ printk(" RxLastEFB = %u\n", *RxLastEFBCNT);
+ printk(" RxDTUCorrectedCNT = %u\n", *RxDTUCorrectedCNT);
+ printk(" RxDTUCorruptedCNT = %u\n", *RxDTUCorruptedCNT);
+ printk(" RxRetxDTUUncorrectedCNT = %u\n", *RxRetxDTUUncorrectedCNT);
+ printk("\n");
+
+ printk("Retx FW Cell MIB :\n");
+ printk(" bc0_total_cell = %u\n", *WRX_BC0_CELL_NUM);
+ printk(" bc0_drop_cell = %u\n", *WRX_BC0_DROP_CELL_NUM);
+ printk(" bc0_nonretx_cell = %u\n", *WRX_BC0_NONRETX_CELL_NUM);
+ printk(" bc0_retx_cell = %u\n", *WRX_BC0_RETX_CELL_NUM);
+ printk(" bc0_outofdate_cell = %u\n", *WRX_BC0_OUTOFDATE_CELL_NUM);
+ printk(" bc0_directup_cell = %u\n", *WRX_BC0_DIRECTUP_NUM);
+ printk(" bc0_to_pb_total_cell = %u\n", *WRX_BC0_PBW_TOTAL_NUM);
+ printk(" bc0_to_pb_succ_cell = %u\n", *WRX_BC0_PBW_SUCC_NUM);
+ printk(" bc0_to_pb_fail_cell = %u\n", *WRX_BC0_PBW_FAIL_NUM);
+ printk(" bc1_total_cell = %u\n", *WRX_BC1_CELL_NUM);
+
+ printk("\n");
+
+ printk("ATM Rx AAL5/OAM MIB:\n");
+ printk(" wrx_drophtu_cell = %u\n", WAN_MIB_TABLE->wrx_drophtu_cell);
+ printk(" wrx_dropdes_pdu = %u\n", WAN_MIB_TABLE->wrx_dropdes_pdu);
+
+ printk(" wrx_correct_pdu = %-10u ", WAN_MIB_TABLE->wrx_correct_pdu);
+ if ( WAN_MIB_TABLE->wrx_correct_pdu == 0 )
+ printk("\n");
+ else {
+ int i = 0;
+
+ printk("[ ");
+ for ( i = 0; i < 16; ++i ) {
+ if ( WRX_PER_PVC_CORRECT_PDU_BASE[i] )
+ printk("q%-2d = %-10u , ", i, WRX_PER_PVC_CORRECT_PDU_BASE[i]);
+ }
+ printk("]\n");
+ }
+
+ printk(" wrx_err_pdu = %-10u ", WAN_MIB_TABLE->wrx_err_pdu);
+ if ( WAN_MIB_TABLE->wrx_err_pdu == 0 )
+ printk("\n");
+ else {
+ int i = 0;
+
+ printk("[ ");
+ for ( i = 0; i < 16; ++i ) {
+ if ( WRX_PER_PVC_ERROR_PDU_BASE[i] )
+ printk("q%-2d = %-10u , ", i, WRX_PER_PVC_ERROR_PDU_BASE[i] );
+ }
+ printk("]\n");
+ }
+
+ printk(" wrx_dropdes_cell = %u\n", WAN_MIB_TABLE->wrx_dropdes_cell);
+ printk(" wrx_correct_cell = %u\n", WAN_MIB_TABLE->wrx_correct_cell);
+ printk(" wrx_err_cell = %u\n", WAN_MIB_TABLE->wrx_err_cell);
+ printk(" wrx_total_byte = %u\n", WAN_MIB_TABLE->wrx_total_byte);
+ printk("\n");
+
+ printk("ATM Tx MIB:\n");
+ printk(" wtx_total_pdu = %u\n", WAN_MIB_TABLE->wtx_total_pdu);
+ printk(" wtx_total_cell = %u\n", WAN_MIB_TABLE->wtx_total_cell);
+ printk(" wtx_total_byte = %u\n", WAN_MIB_TABLE->wtx_total_byte);
+ printk("\n");
+
+ printk("Debugging Info:\n");
+ printk(" Firmware version = %d.%d.%d.%d.%d.%d\n",
+ (int)FW_VER_ID->family, (int)FW_VER_ID->fwtype, (int)FW_VER_ID->interface,
+ (int)FW_VER_ID->fwmode, (int)FW_VER_ID->major, (int)FW_VER_ID->minor);
+
+ printk(" retx_alpha_switch_to_hunt_times = %u\n", *URETX_ALPHA_SWITCH_TO_HUNT_TIMES);
+
+ printk("\n");
+
+ *eof = 1;
+
+ return len;
+}
+
+static int proc_write_retx_mib(struct file *file, const char *buf, unsigned long count, void *data)
+{
+ char str[2048];
+ char *p;
+ int len, rlen;
+ int i;
+
+ len = count < sizeof(str) ? count : sizeof(str) - 1;
+ rlen = len - copy_from_user(str, buf, len);
+ while ( rlen && str[rlen - 1] <= ' ' )
+ rlen--;
+ str[rlen] = 0;
+ for ( p = str; *p && *p <= ' '; p++, rlen-- );
+ if ( !*p )
+ return 0;
+
+ if ( stricmp(p, "clean") == 0 || stricmp(p, "clear") == 0 || stricmp(p, "clear_all") == 0) {
+ *URETX_RX_TOTAL_DTU = 0;
+ *URETX_RX_BAD_DTU = 0;
+ *URETX_RX_GOOD_DTU = 0;
+ *URETX_RX_CORRECTED_DTU = 0;
+ *URETX_RX_OUTOFDATE_DTU = 0;
+ *URETX_RX_DUPLICATE_DTU = 0;
+ *URETX_RX_TIMEOUT_DTU = 0;
+ *RxDTURetransmittedCNT = 0;
+
+ *WRX_BC0_CELL_NUM = 0;
+ *WRX_BC0_DROP_CELL_NUM = 0;
+ *WRX_BC0_NONRETX_CELL_NUM = 0;
+ *WRX_BC0_RETX_CELL_NUM = 0;
+ *WRX_BC0_OUTOFDATE_CELL_NUM = 0;
+ *WRX_BC0_DIRECTUP_NUM = 0;
+ *WRX_BC0_PBW_TOTAL_NUM = 0;
+ *WRX_BC0_PBW_SUCC_NUM = 0;
+ *WRX_BC0_PBW_FAIL_NUM = 0;
+ *WRX_BC1_CELL_NUM = 0;
+
+ for ( i = 0; i < 16; ++i ) {
+ WRX_PER_PVC_CORRECT_PDU_BASE[i] = 0;
+ WRX_PER_PVC_ERROR_PDU_BASE[i] = 0;
+ }
+
+ WAN_MIB_TABLE->wrx_drophtu_cell = 0;
+ WAN_MIB_TABLE->wrx_dropdes_pdu = 0;
+ WAN_MIB_TABLE->wrx_correct_pdu = 0;
+ WAN_MIB_TABLE->wrx_err_pdu = 0;
+ WAN_MIB_TABLE->wrx_dropdes_cell = 0;
+ WAN_MIB_TABLE->wrx_correct_cell = 0;
+ WAN_MIB_TABLE->wrx_err_cell = 0;
+ WAN_MIB_TABLE->wrx_total_byte = 0;
+
+ WAN_MIB_TABLE->wtx_total_pdu = 0;
+ WAN_MIB_TABLE->wtx_total_cell = 0;
+ WAN_MIB_TABLE->wtx_total_byte = 0;
+
+ *URETX_ALPHA_SWITCH_TO_HUNT_TIMES = 0;
+
+ if (stricmp(p, "clear_all") == 0) {
+ *RxLastEFBCNT = 0;
+ *RxDTUCorrectedCNT = 0;
+ *RxDTUCorruptedCNT = 0;
+ *RxRetxDTUUncorrectedCNT = 0;
+ }
+ }
+
+ return count;
+}
+
+#endif
+
+#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC
+
+static int proc_read_dbg(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len += sprintf(page + off + len, "error print - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_ERR) ? "enabled" : "disabled");
+ len += sprintf(page + off + len, "debug print - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DEBUG_PRINT) ? "enabled" : "disabled");
+ len += sprintf(page + off + len, "assert - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_ASSERT) ? "enabled" : "disabled");
+ len += sprintf(page + off + len, "dump rx skb - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_SKB_RX) ? "enabled" : "disabled");
+ len += sprintf(page + off + len, "dump tx skb - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_SKB_TX) ? "enabled" : "disabled");
+ len += sprintf(page + off + len, "qos - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) ? "enabled" : "disabled");
+ len += sprintf(page + off + len, "dump init - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_INIT) ? "enabled" : "disabled");
+ len += sprintf(page + off + len, "mac swap - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_MAC_SWAP) ? "enabled" : "disabled");
+
+ *eof = 1;
+
+ return len;
+}
+
+static int proc_write_dbg(struct file *file, const char *buf, unsigned long count, void *data)
+{
+ static const char *dbg_enable_mask_str[] = {
+ " error print",
+ " err",
+ " debug print",
+ " dbg",
+ " assert",
+ " assert",
+ " dump rx skb",
+ " rx",
+ " dump tx skb",
+ " tx",
+ " dump qos",
+ " qos",
+ " dump init",
+ " init",
+ " mac swap",
+ " swap",
+ " all"
+ };
+ static const int dbg_enable_mask_str_len[] = {
+ 12, 4,
+ 12, 4,
+ 7, 7,
+ 12, 3,
+ 12, 3,
+ 9, 4,
+ 10, 5,
+ 9, 5,
+ 4
+ };
+ unsigned int dbg_enable_mask[] = {
+ DBG_ENABLE_MASK_ERR,
+ DBG_ENABLE_MASK_DEBUG_PRINT,
+ DBG_ENABLE_MASK_ASSERT,
+ DBG_ENABLE_MASK_DUMP_SKB_RX,
+ DBG_ENABLE_MASK_DUMP_SKB_TX,
+ DBG_ENABLE_MASK_DUMP_QOS,
+ DBG_ENABLE_MASK_DUMP_INIT,
+ DBG_ENABLE_MASK_MAC_SWAP,
+ DBG_ENABLE_MASK_ALL
+ };
+
+ char *str;
+ int str_buff_len = 1024;
+ char *p;
+
+ int len, rlen;
+
+ int f_enable = 0;
+ int i;
+
+ str = vmalloc(str_buff_len);
+ if(!str){
+ return 0;
+ }
+
+ len = count < str_buff_len ? count : str_buff_len - 1;
+ rlen = len - copy_from_user(str, buf, len);
+ while ( rlen && str[rlen - 1] <= ' ' )
+ rlen--;
+ str[rlen] = 0;
+ for ( p = str; *p && *p <= ' '; p++, rlen-- );
+ if ( !*p ){
+ vfree(str);
+ return 0;
+ }
+
+ if ( strincmp(p, "enable", 6) == 0 ) {
+ p += 6;
+ f_enable = 1;
+ }
+ else if ( strincmp(p, "disable", 7) == 0 ) {
+ p += 7;
+ f_enable = -1;
+ }
+ else if ( strincmp(p, "help", 4) == 0 || *p == '?' ) {
+ printk("echo <enable/disable> [err/dbg/assert/rx/tx/init/all] > /proc/eth/dbg\n");
+ }
+
+ if ( f_enable ) {
+ if ( *p == 0 ) {
+ if ( f_enable > 0 )
+ ifx_atm_dbg_enable |= DBG_ENABLE_MASK_ALL & ~DBG_ENABLE_MASK_MAC_SWAP;
+ else
+ ifx_atm_dbg_enable &= ~DBG_ENABLE_MASK_ALL | DBG_ENABLE_MASK_MAC_SWAP;
+ }
+ else {
+ do {
+ for ( i = 0; i < NUM_ENTITY(dbg_enable_mask_str); i++ )
+ if ( strincmp(p, dbg_enable_mask_str[i], dbg_enable_mask_str_len[i]) == 0 ) {
+ if ( f_enable > 0 )
+ ifx_atm_dbg_enable |= dbg_enable_mask[i >> 1];
+ else
+ ifx_atm_dbg_enable &= ~dbg_enable_mask[i >> 1];
+ p += dbg_enable_mask_str_len[i];
+ break;
+ }
+ } while ( i < NUM_ENTITY(dbg_enable_mask_str) );
+ }
+ }
+
+ vfree(str);
+ return count;
+}
+
+static inline unsigned long sb_addr_to_fpi_addr_convert(unsigned long sb_addr)
+{
+ #define PP32_SB_ADDR_END 0xFFFF
+
+ if ( sb_addr < PP32_SB_ADDR_END )
+ return (unsigned long)SB_BUFFER(sb_addr);
+ else
+ return sb_addr;
+}
+
+static int proc_write_mem(struct file *file, const char *buf, unsigned long count, void *data)
+{
+ char *p1, *p2;
+ int len;
+ int colon;
+ unsigned long *p;
+ int i, n, l;
+ int local_buf_size = 1024;
+ char *local_buf = NULL;
+
+ local_buf = vmalloc(local_buf_size);
+ if ( !local_buf ){
+ return 0;
+ }
+
+ len = local_buf_size < count ? local_buf_size - 1 : count;
+ len = len - copy_from_user(local_buf, buf, len);
+ local_buf[len] = 0;
+
+ p1 = local_buf;
+ colon = 1;
+ while ( get_token(&p1, &p2, &len, &colon) ) {
+ if ( stricmp(p1, "w") == 0 || stricmp(p1, "write") == 0 || stricmp(p1, "r") == 0 || stricmp(p1, "read") == 0 )
+ break;
+
+ p1 = p2;
+ colon = 1;
+ }
+
+ if ( *p1 == 'w' ) {
+ ignore_space(&p2, &len);
+ p = (unsigned long *)get_number(&p2, &len, 1);
+ p = (unsigned long *)sb_addr_to_fpi_addr_convert((unsigned long)p);
+
+ if ( (unsigned int)p >= KSEG0 )
+ while ( 1 ) {
+ ignore_space(&p2, &len);
+ if ( !len || !((*p2 >= '0' && *p2 <= '9') || (*p2 >= 'a' && *p2 <= 'f') || (*p2 >= 'A' && *p2 <= 'F')) )
+ break;
+
+ *p++ = (unsigned int)get_number(&p2, &len, 1);
+ }
+ }
+ else if ( *p1 == 'r' ) {
+ ignore_space(&p2, &len);
+ p = (unsigned long *)get_number(&p2, &len, 1);
+ p = (unsigned long *)sb_addr_to_fpi_addr_convert((unsigned long)p);
+
+ if ( (unsigned int)p >= KSEG0 ) {
+ ignore_space(&p2, &len);
+ n = (int)get_number(&p2, &len, 0);
+ if ( n ) {
+ char str[32] = {0};
+ char *pch = str;
+ int k;
+ unsigned int data;
+ char c;
+
+ n += (l = ((int)p >> 2) & 0x03);
+ p = (unsigned long *)((unsigned int)p & ~0x0F);
+ for ( i = 0; i < n; i++ ) {
+ if ( (i & 0x03) == 0 ) {
+ printk("%08X:", (unsigned int)p);
+ pch = str;
+ }
+ if ( i < l ) {
+ printk(" ");
+ sprintf(pch, " ");
+ }
+ else {
+ data = (unsigned int)*p;
+ printk(" %08X", data);
+ for ( k = 0; k < 4; k++ ) {
+ c = ((char*)&data)[k];
+ pch[k] = c < ' ' ? '.' : c;
+ }
+ }
+ p++;
+ pch += 4;
+ if ( (i & 0x03) == 0x03 ) {
+ pch[0] = 0;
+ printk(" ; %s\n", str);
+ }
+ }
+ if ( (n & 0x03) != 0x00 ) {
+ for ( k = 4 - (n & 0x03); k > 0; k-- )
+ printk(" ");
+ pch[0] = 0;
+ printk(" ; %s\n", str);
+ }
+ }
+ }
+ }
+
+ vfree(local_buf);
+ return count;
+}
+
+ #if defined(CONFIG_AR9) || defined(CONFIG_VR9)
+
+static int proc_read_pp32(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ static const char *stron = " on";
+ static const char *stroff = "off";
+
+ int len = 0;
+ int cur_context;
+ int f_stopped;
+ char str[256];
+ char strlength;
+ int i, j;
+
+ int pp32;
+
+ for ( pp32 = 0; pp32 < NUM_OF_PP32; pp32++ ) {
+ f_stopped = 0;
+
+ len += sprintf(page + off + len, "===== pp32 core %d =====\n", pp32);
+
+ #ifdef CONFIG_VR9
+ if ( (*PP32_FREEZE & (1 << (pp32 << 4))) != 0 ) {
+ sprintf(str, "freezed");
+ f_stopped = 1;
+ }
+ #else
+ if ( 0 ) {
+ }
+ #endif
+ else if ( PP32_CPU_USER_STOPPED(pp32) || PP32_CPU_USER_BREAKIN_RCV(pp32) || PP32_CPU_USER_BREAKPOINT_MET(pp32) ) {
+ strlength = 0;
+ if ( PP32_CPU_USER_STOPPED(pp32) )
+ strlength += sprintf(str + strlength, "stopped");
+ if ( PP32_CPU_USER_BREAKPOINT_MET(pp32) )
+ strlength += sprintf(str + strlength, strlength ? " | breakpoint" : "breakpoint");
+ if ( PP32_CPU_USER_BREAKIN_RCV(pp32) )
+ strlength += sprintf(str + strlength, strlength ? " | breakin" : "breakin");
+ f_stopped = 1;
+ }
+ #if 0
+ else if ( PP32_CPU_CUR_PC(pp32) == PP32_CPU_CUR_PC(pp32) ) {
+ sprintf(str, "hang");
+ f_stopped = 1;
+ }
+ #endif
+ else
+ sprintf(str, "running");
+ cur_context = PP32_BRK_CUR_CONTEXT(pp32);
+ len += sprintf(page + off + len, "Context: %d, PC: 0x%04x, %s\n", cur_context, PP32_CPU_CUR_PC(pp32), str);
+
+ if ( PP32_CPU_USER_BREAKPOINT_MET(pp32) ) {
+ strlength = 0;
+ if ( PP32_BRK_PC_MET(pp32, 0) )
+ strlength += sprintf(str + strlength, "pc0");
+ if ( PP32_BRK_PC_MET(pp32, 1) )
+ strlength += sprintf(str + strlength, strlength ? " | pc1" : "pc1");
+ if ( PP32_BRK_DATA_ADDR_MET(pp32, 0) )
+ strlength += sprintf(str + strlength, strlength ? " | daddr0" : "daddr0");
+ if ( PP32_BRK_DATA_ADDR_MET(pp32, 1) )
+ strlength += sprintf(str + strlength, strlength ? " | daddr1" : "daddr1");
+ if ( PP32_BRK_DATA_VALUE_RD_MET(pp32, 0) ) {
+ strlength += sprintf(str + strlength, strlength ? " | rdval0" : "rdval0");
+ if ( PP32_BRK_DATA_VALUE_RD_LO_EQ(pp32, 0) ) {
+ if ( PP32_BRK_DATA_VALUE_RD_GT_EQ(pp32, 0) )
+ strlength += sprintf(str + strlength, " ==");
+ else
+ strlength += sprintf(str + strlength, " <=");
+ }
+ else if ( PP32_BRK_DATA_VALUE_RD_GT_EQ(pp32, 0) )
+ strlength += sprintf(str + strlength, " >=");
+ }
+ if ( PP32_BRK_DATA_VALUE_RD_MET(pp32, 1) ) {
+ strlength += sprintf(str + strlength, strlength ? " | rdval1" : "rdval1");
+ if ( PP32_BRK_DATA_VALUE_RD_LO_EQ(pp32, 1) ) {
+ if ( PP32_BRK_DATA_VALUE_RD_GT_EQ(pp32, 1) )
+ strlength += sprintf(str + strlength, " ==");
+ else
+ strlength += sprintf(str + strlength, " <=");
+ }
+ else if ( PP32_BRK_DATA_VALUE_RD_GT_EQ(pp32, 1) )
+ strlength += sprintf(str + strlength, " >=");
+ }
+ if ( PP32_BRK_DATA_VALUE_WR_MET(pp32, 0) ) {
+ strlength += sprintf(str + strlength, strlength ? " | wtval0" : "wtval0");
+ if ( PP32_BRK_DATA_VALUE_WR_LO_EQ(pp32, 0) ) {
+ if ( PP32_BRK_DATA_VALUE_WR_GT_EQ(pp32, 0) )
+ strlength += sprintf(str + strlength, " ==");
+ else
+ strlength += sprintf(str + strlength, " <=");
+ }
+ else if ( PP32_BRK_DATA_VALUE_WR_GT_EQ(pp32, 0) )
+ strlength += sprintf(str + strlength, " >=");
+ }
+ if ( PP32_BRK_DATA_VALUE_WR_MET(pp32, 1) ) {
+ strlength += sprintf(str + strlength, strlength ? " | wtval1" : "wtval1");
+ if ( PP32_BRK_DATA_VALUE_WR_LO_EQ(pp32, 1) ) {
+ if ( PP32_BRK_DATA_VALUE_WR_GT_EQ(pp32, 1) )
+ strlength += sprintf(str + strlength, " ==");
+ else
+ strlength += sprintf(str + strlength, " <=");
+ }
+ else if ( PP32_BRK_DATA_VALUE_WR_GT_EQ(pp32, 1) )
+ strlength += sprintf(str + strlength, " >=");
+ }
+ len += sprintf(page + off + len, "break reason: %s\n", str);
+ }
+
+ if ( f_stopped )
+ {
+ len += sprintf(page + off + len, "General Purpose Register (Context %d):\n", cur_context);
+ for ( i = 0; i < 4; i++ ) {
+ for ( j = 0; j < 4; j++ )
+ len += sprintf(page + off + len, " %2d: %08x", i + j * 4, *PP32_GP_CONTEXTi_REGn(pp32, cur_context, i + j * 4));
+ len += sprintf(page + off + len, "\n");
+ }
+ }
+
+ len += sprintf(page + off + len, "break out on: break in - %s, stop - %s\n",
+ PP32_CTRL_OPT_BREAKOUT_ON_BREAKIN(pp32) ? stron : stroff,
+ PP32_CTRL_OPT_BREAKOUT_ON_STOP(pp32) ? stron : stroff);
+ len += sprintf(page + off + len, " stop on: break in - %s, break point - %s\n",
+ PP32_CTRL_OPT_STOP_ON_BREAKIN(pp32) ? stron : stroff,
+ PP32_CTRL_OPT_STOP_ON_BREAKPOINT(pp32) ? stron : stroff);
+ len += sprintf(page + off + len, "breakpoint:\n");
+ len += sprintf(page + off + len, " pc0: 0x%08x, %s\n", *PP32_BRK_PC(pp32, 0), PP32_BRK_GRPi_PCn(pp32, 0, 0) ? "group 0" : "off");
+ len += sprintf(page + off + len, " pc1: 0x%08x, %s\n", *PP32_BRK_PC(pp32, 1), PP32_BRK_GRPi_PCn(pp32, 1, 1) ? "group 1" : "off");
+ len += sprintf(page + off + len, " daddr0: 0x%08x, %s\n", *PP32_BRK_DATA_ADDR(pp32, 0), PP32_BRK_GRPi_DATA_ADDRn(pp32, 0, 0) ? "group 0" : "off");
+ len += sprintf(page + off + len, " daddr1: 0x%08x, %s\n", *PP32_BRK_DATA_ADDR(pp32, 1), PP32_BRK_GRPi_DATA_ADDRn(pp32, 1, 1) ? "group 1" : "off");
+ len += sprintf(page + off + len, " rdval0: 0x%08x\n", *PP32_BRK_DATA_VALUE_RD(pp32, 0));
+ len += sprintf(page + off + len, " rdval1: 0x%08x\n", *PP32_BRK_DATA_VALUE_RD(pp32, 1));
+ len += sprintf(page + off + len, " wrval0: 0x%08x\n", *PP32_BRK_DATA_VALUE_WR(pp32, 0));
+ len += sprintf(page + off + len, " wrval1: 0x%08x\n", *PP32_BRK_DATA_VALUE_WR(pp32, 1));
+ }
+
+ *eof = 1;
+
+ return len;
+}
+
+static int proc_write_pp32(struct file *file, const char *buf, unsigned long count, void *data)
+{
+ char *str = NULL;
+ char *p;
+ unsigned int addr;
+ int str_buff_len = 1024;
+
+ int len, rlen;
+
+ int pp32 = 0;
+
+ str = vmalloc(str_buff_len);
+ if (!str) {
+ return 0;
+ }
+
+ len = count < str_buff_len ? count : str_buff_len - 1;
+ rlen = len - copy_from_user(str, buf, len);
+ while ( rlen && str[rlen - 1] <= ' ' )
+ rlen--;
+ str[rlen] = 0;
+ for ( p = str; *p && *p <= ' '; p++, rlen-- );
+ if ( !*p ){
+ vfree(str);
+ return 0;
+ }
+
+ if ( strincmp(p, "pp32 ", 5) == 0 ) {
+ p += 5;
+ rlen -= 5;
+
+ while ( rlen > 0 && *p >= '0' && *p <= '9' ) {
+ pp32 += *p - '0';
+ p++;
+ rlen--;
+ }
+ while ( rlen > 0 && *p && *p <= ' ' ) {
+ p++;
+ rlen--;
+ }
+
+ if ( pp32 >= NUM_OF_PP32 ) {
+ err("incorrect pp32 index - %d", pp32);
+ vfree(str);
+ return count;
+ }
+ }
+
+ if ( stricmp(p, "start") == 0 )
+ *PP32_CTRL_CMD(pp32) = PP32_CTRL_CMD_RESTART;
+ else if ( stricmp(p, "stop") == 0 )
+ *PP32_CTRL_CMD(pp32) = PP32_CTRL_CMD_STOP;
+ else if ( stricmp(p, "step") == 0 )
+ *PP32_CTRL_CMD(pp32) = PP32_CTRL_CMD_STEP;
+ #ifdef CONFIG_VR9
+ else if ( stricmp(p, "restart") == 0 )
+ *PP32_FREEZE &= ~(1 << (pp32 << 4));
+ else if ( stricmp(p, "freeze") == 0 )
+ *PP32_FREEZE |= 1 << (pp32 << 4);
+ #endif
+ else if ( strincmp(p, "pc0 ", 4) == 0 ) {
+ p += 4;
+ rlen -= 4;
+ if ( stricmp(p, "off") == 0 ) {
+ *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_PCn_OFF(0, 0);
+ *PP32_BRK_PC_MASK(pp32, 0) = PP32_BRK_CONTEXT_MASK_EN;
+ *PP32_BRK_PC(pp32, 0) = 0;
+ }
+ else {
+ addr = get_number(&p, &rlen, 1);
+ *PP32_BRK_PC(pp32, 0) = addr;
+ *PP32_BRK_PC_MASK(pp32, 0) = PP32_BRK_CONTEXT_MASK_EN | PP32_BRK_CONTEXT_MASK(0) | PP32_BRK_CONTEXT_MASK(1) | PP32_BRK_CONTEXT_MASK(2) | PP32_BRK_CONTEXT_MASK(3);
+ *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_PCn_ON(0, 0);
+ }
+ }
+ else if ( strincmp(p, "pc1 ", 4) == 0 ) {
+ p += 4;
+ rlen -= 4;
+ if ( stricmp(p, "off") == 0 ) {
+ *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_PCn_OFF(1, 1);
+ *PP32_BRK_PC_MASK(pp32, 1) = PP32_BRK_CONTEXT_MASK_EN;
+ *PP32_BRK_PC(pp32, 1) = 0;
+ }
+ else {
+ addr = get_number(&p, &rlen, 1);
+ *PP32_BRK_PC(pp32, 1) = addr;
+ *PP32_BRK_PC_MASK(pp32, 1) = PP32_BRK_CONTEXT_MASK_EN | PP32_BRK_CONTEXT_MASK(0) | PP32_BRK_CONTEXT_MASK(1) | PP32_BRK_CONTEXT_MASK(2) | PP32_BRK_CONTEXT_MASK(3);
+ *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_PCn_ON(1, 1);
+ }
+ }
+ else if ( strincmp(p, "daddr0 ", 7) == 0 ) {
+ p += 7;
+ rlen -= 7;
+ if ( stricmp(p, "off") == 0 ) {
+ *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_DATA_ADDRn_OFF(0, 0);
+ *PP32_BRK_DATA_ADDR_MASK(pp32, 0) = PP32_BRK_CONTEXT_MASK_EN;
+ *PP32_BRK_DATA_ADDR(pp32, 0) = 0;
+ }
+ else {
+ addr = get_number(&p, &rlen, 1);
+ *PP32_BRK_DATA_ADDR(pp32, 0) = addr;
+ *PP32_BRK_DATA_ADDR_MASK(pp32, 0) = PP32_BRK_CONTEXT_MASK_EN | PP32_BRK_CONTEXT_MASK(0) | PP32_BRK_CONTEXT_MASK(1) | PP32_BRK_CONTEXT_MASK(2) | PP32_BRK_CONTEXT_MASK(3);
+ *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_DATA_ADDRn_ON(0, 0);
+ }
+ }
+ else if ( strincmp(p, "daddr1 ", 7) == 0 ) {
+ p += 7;
+ rlen -= 7;
+ if ( stricmp(p, "off") == 0 ) {
+ *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_DATA_ADDRn_OFF(1, 1);
+ *PP32_BRK_DATA_ADDR_MASK(pp32, 1) = PP32_BRK_CONTEXT_MASK_EN;
+ *PP32_BRK_DATA_ADDR(pp32, 1) = 0;
+ }
+ else {
+ addr = get_number(&p, &rlen, 1);
+ *PP32_BRK_DATA_ADDR(pp32, 1) = addr;
+ *PP32_BRK_DATA_ADDR_MASK(pp32, 1) = PP32_BRK_CONTEXT_MASK_EN | PP32_BRK_CONTEXT_MASK(0) | PP32_BRK_CONTEXT_MASK(1) | PP32_BRK_CONTEXT_MASK(2) | PP32_BRK_CONTEXT_MASK(3);
+ *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_DATA_ADDRn_ON(1, 1);
+ }
+ }
+ else {
+
+ printk("echo \"<command>\" > /proc/driver/ifx_ptm/pp32\n");
+ printk(" command:\n");
+ printk(" start - run pp32\n");
+ printk(" stop - stop pp32\n");
+ printk(" step - run pp32 with one step only\n");
+ printk(" pc0 - pc0 <addr>/off, set break point PC0\n");
+ printk(" pc1 - pc1 <addr>/off, set break point PC1\n");
+ printk(" daddr0 - daddr0 <addr>/off, set break point data address 0\n");
+ printk(" daddr0 - daddr1 <addr>/off, set break point data address 1\n");
+ printk(" help - print this screen\n");
+ }
+
+ if ( *PP32_BRK_TRIG(pp32) )
+ *PP32_CTRL_OPT(pp32) = PP32_CTRL_OPT_STOP_ON_BREAKPOINT_ON;
+ else
+ *PP32_CTRL_OPT(pp32) = PP32_CTRL_OPT_STOP_ON_BREAKPOINT_OFF;
+ vfree(str);
+ return count;
+}
+
+#elif defined(CONFIG_DANUBE)
+
+static int proc_read_pp32(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ static const char *halt_stat[] = {
+ "reset",
+ "break in line",
+ "stop",
+ "step",
+ "code",
+ "data0",
+ "data1"
+ };
+ static const char *brk_src_data[] = {
+ "off",
+ "read",
+ "write",
+ "read/write",
+ "write_equal",
+ "N/A",
+ "N/A",
+ "N/A"
+ };
+ static const char *brk_src_code[] = {
+ "off",
+ "on"
+ };
+
+ int len = 0;
+ int i;
+ int k;
+ unsigned long bit;
+ int tsk;
+
+ tsk = *PP32_DBG_TASK_NO & 0x03;
+ len += sprintf(page + off + len, "Task No %d, PC %04x\n", tsk, *PP32_DBG_CUR_PC & 0xFFFF);
+
+ if ( !(*PP32_HALT_STAT & 0x01) )
+ len += sprintf(page + off + len, " Halt State: Running\n");
+ else {
+ len += sprintf(page + off + len, " Halt State: Stopped");
+ k = 0;
+ for ( bit = 2, i = 0; bit <= (1 << 7); bit <<= 1, i++ )
+ if ( (*PP32_HALT_STAT & bit) ) {
+ if ( !k ) {
+ len += sprintf(page + off + len, ", ");
+ k++;
+ }
+ else
+ len += sprintf(page + off + len, " | ");
+ len += sprintf(page + off + len, halt_stat[i]);
+ }
+
+ len += sprintf(page + off + len, "\n");
+
+ len += sprintf(page + off + len, " Regs (Task %d):\n", tsk);
+ for ( i = 0; i < 8; i++ )
+ len += sprintf(page + off + len, " %2d. %08x %2d. %08x\n", i, *PP32_DBG_REG_BASE(tsk, i), i + 8, *PP32_DBG_REG_BASE(tsk, i + 8));
+ }
+
+ len += sprintf(page + off + len, " Break Src: data1 - %s, data0 - %s, pc3 - %s, pc2 - %s, pc1 - %s, pc0 - %s\n",
+ brk_src_data[(*PP32_BRK_SRC >> 11) & 0x07],
+ brk_src_data[(*PP32_BRK_SRC >> 8) & 0x07],
+ brk_src_code[(*PP32_BRK_SRC >> 3) & 0x01],
+ brk_src_code[(*PP32_BRK_SRC >> 2) & 0x01],
+ brk_src_code[(*PP32_BRK_SRC >> 1) & 0x01],
+ brk_src_code[*PP32_BRK_SRC & 0x01]);
+
+ for ( i = 0; i < 4; i++ )
+ len += sprintf(page + off + len, " pc%d: %04x - %04x\n", i, *PP32_DBG_PC_MIN(i), *PP32_DBG_PC_MAX(i));
+
+ for ( i = 0; i < 2; i++ )
+ len += sprintf(page + off + len, " data%d: %04x - %04x (%08x)\n", i, *PP32_DBG_DATA_MIN(i), *PP32_DBG_DATA_MAX(i), *PP32_DBG_DATA_VAL(i));
+
+ *eof = 1;
+
+ return len;
+}
+
+static int proc_write_pp32(struct file *file, const char *buf, unsigned long count, void *data)
+{
+ char *str;
+ char *p;
+
+ int len, rlen;
+ int str_buff_len = 2048;
+ str = vmalloc(str_buff_len);
+ if (!str){
+ return 0;
+ }
+ len = count < str_buff_len ? count : str_buff_len - 1;
+ rlen = len - copy_from_user(str, buf, len);
+ while ( rlen && str[rlen - 1] <= ' ' )
+ rlen--;
+ str[rlen] = 0;
+ for ( p = str; *p && *p <= ' '; p++, rlen-- );
+ if ( !*p )
+ vfree(str);
+ return 0;
+
+ if ( stricmp(p, "start") == 0 )
+ *PP32_DBG_CTRL = DBG_CTRL_START_SET(1);
+ else if ( stricmp(p, "stop") == 0 )
+ *PP32_DBG_CTRL = DBG_CTRL_STOP_SET(1);
+ else if ( stricmp(p, "step") == 0 )
+ *PP32_DBG_CTRL = DBG_CTRL_STEP_SET(1);
+ else if ( strincmp(p, "pc", 2) == 0 && p[2] >= '0' && p[2] <= '3' && p[3] <= ' ' ) {
+ int n = p[2] - '0';
+ int on_off_flag = -1;
+ int addr_min, addr_max;
+
+ p += 4;
+ rlen -= 4;
+ ignore_space(&p, &rlen);
+
+ if ( strincmp(p, "off", 3) == 0 && p[3] <= ' ' ) {
+ p += 3;
+ rlen -= 3;
+ on_off_flag = 0;
+ }
+ else if ( strincmp(p, "on", 2) == 0 && p[2] <= ' ' ) {
+ p += 2;
+ rlen -= 2;
+ on_off_flag = 1;
+ }
+ ignore_space(&p, &rlen);
+
+ if ( rlen ) {
+ addr_min = get_number(&p, &rlen, 1);
+ ignore_space(&p, &rlen);
+ if ( rlen )
+ addr_max = get_number(&p, &rlen, 1);
+ else
+ addr_max = addr_min;
+
+ *PP32_DBG_PC_MIN(n) = addr_min;
+ *PP32_DBG_PC_MAX(n) = addr_max;
+ }
+
+ if ( on_off_flag == 0 )
+ *PP32_BRK_SRC &= ~(1 << n);
+ else if ( on_off_flag > 0 )
+ *PP32_BRK_SRC |= 1 << n;
+ }
+ else if ( strincmp(p, "data", 4) == 0 && p[4] >= '0' && p[4] <= '1' && p[5] <= ' ' ) {
+ const static char *data_cmd_str[] = {"r", "w", "rw", "w=", "off", "min", "min addr", "max", "max addr", "val", "value"};
+ const static int data_cmd_len[] = {1, 1, 2, 2, 3, 3, 8, 3, 8, 3, 5};
+ const static int data_cmd_idx[] = {1, 2, 3, 4, 0, 5, 5, 6, 6, 7, 7};
+ int n = p[4] - '0';
+ int on_off_flag = -1, on_off_mask = 0;
+ int addr_min = -1, addr_max = -1;
+ int value = 0, f_got_value = 0;
+ int stat = 0;
+ int i;
+ int tmp;
+
+ p += 6;
+ rlen -= 6;
+
+ while ( 1 ) {
+ ignore_space(&p, &rlen);
+ if ( rlen <= 0 )
+ break;
+ for ( i = 0; i < NUM_ENTITY(data_cmd_str); i++ )
+ if ( strincmp(p, data_cmd_str[i], data_cmd_len[i]) == 0 && p[data_cmd_len[i]] <= ' ' ) {
+ p += data_cmd_len[i];
+ rlen -= data_cmd_len[i];
+ stat = data_cmd_idx[i];
+ if ( stat <= 4 ) {
+ on_off_mask = 7;
+ on_off_flag = stat;
+ }
+ break;
+ }
+ if ( i == NUM_ENTITY(data_cmd_str) ) {
+ if ( (*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F') ) {
+ tmp = get_number(&p, &rlen, 1);
+ if ( stat <= 5 ) {
+ addr_min = tmp;
+ stat = 6;
+ }
+ else if ( stat >= 7 ) {
+ value = tmp;
+ f_got_value = 1;
+ }
+ else {
+ addr_max = tmp;
+ stat = 7;
+ }
+ }
+ else
+ for ( ; rlen && *p > ' '; rlen--, p++ );
+ }
+ }
+
+ if ( addr_min >= 0 )
+ *PP32_DBG_DATA_MIN(n) = *PP32_DBG_DATA_MAX(n) = addr_min;
+ if ( addr_max >= 0 )
+ *PP32_DBG_DATA_MAX(n) = addr_max;
+ if ( f_got_value )
+ *PP32_DBG_DATA_VAL(n) = value;
+ if ( on_off_mask && on_off_flag >= 0 ) {
+ on_off_flag <<= n ? 11 : 8;
+ on_off_mask <<= n ? 11 : 8;
+ *PP32_BRK_SRC = (*PP32_BRK_SRC & ~on_off_mask) | on_off_flag;
+ }
+ }
+ else {
+ printk("echo \"<command>\" > /proc/eth/etop\n");
+ printk(" command:\n");
+ printk(" start - run pp32\n");
+ printk(" stop - stop pp32\n");
+ printk(" step - run pp32 with one step only\n");
+ printk(" pc - pc? [on/off] [min addr] [max addr], set PC break point\n");
+ printk(" data - data? [r/w/rw/w=/off] [min <addr>] [max <addr>] [val <value>], set data break point\n");
+ printk(" help - print this screen\n");
+ }
+
+ vfree(str);
+ return count;
+}
+
+ #elif defined(CONFIG_AMAZON_SE)
+
+static int proc_read_pp32(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ static const char *halt_stat[] = {
+ "reset",
+ "break in line",
+ "stop",
+ "step",
+ "code",
+ "data0",
+ "data1"
+ };
+ static const char *brk_src_data[] = {
+ "off",
+ "read",
+ "write",
+ "read/write",
+ "write_equal",
+ "N/A",
+ "N/A",
+ "N/A"
+ };
+ static const char *brk_src_code[] = {
+ "off",
+ "on"
+ };
+
+ int len = 0;
+ int i;
+ int k;
+ unsigned long bit;
+
+ len += sprintf(page + off + len, "Task No %d, PC %04x\n", *PP32_DBG_TASK_NO & 0x03, *PP32_DBG_CUR_PC & 0xFFFF);
+
+ if ( !(*PP32_HALT_STAT & 0x01) )
+ len += sprintf(page + off + len, " Halt State: Running\n");
+ else
+ {
+ len += sprintf(page + off + len, " Halt State: Stopped");
+ k = 0;
+ for ( bit = 2, i = 0; bit <= (1 << 7); bit <<= 1, i++ )
+ if ( (*PP32_HALT_STAT & bit) )
+ {
+ if ( !k )
+ {
+ len += sprintf(page + off + len, ", ");
+ k++;
+ }
+ else
+ len += sprintf(page + off + len, " | ");
+ len += sprintf(page + off + len, halt_stat[i]);
+ }
+
+ len += sprintf(page + off + len, "\n");
+ }
+
+ len += sprintf(page + off + len, " Break Src: data1 - %s, data0 - %s, pc3 - %s, pc2 - %s, pc1 - %s, pc0 - %s\n",
+ brk_src_data[(*PP32_BRK_SRC >> 11) & 0x07], brk_src_data[(*PP32_BRK_SRC >> 8) & 0x07], brk_src_code[(*PP32_BRK_SRC >> 3) & 0x01], brk_src_code[(*PP32_BRK_SRC >> 2) & 0x01], brk_src_code[(*PP32_BRK_SRC >> 1) & 0x01], brk_src_code[*PP32_BRK_SRC & 0x01]);
+
+// for ( i = 0; i < 4; i++ )
+// len += sprintf(page + off + len, " pc%d: %04x - %04x\n", i, *PP32_DBG_PC_MIN(i), *PP32_DBG_PC_MAX(i));
+
+// for ( i = 0; i < 2; i++ )
+// len += sprintf(page + off + len, " data%d: %04x - %04x (%08x)\n", i, *PP32_DBG_DATA_MIN(i), *PP32_DBG_DATA_MAX(i), *PP32_DBG_DATA_VAL(i));
+
+ *eof = 1;
+
+ return len;
+}
+
+static int proc_write_pp32(struct file *file, const char *buf, unsigned long count, void *data)
+{
+ char str[2048];
+ char *p;
+
+ int len, rlen;
+
+ len = count < sizeof(str) ? count : sizeof(str) - 1;
+ rlen = len - copy_from_user(str, buf, len);
+ while ( rlen && str[rlen - 1] <= ' ' )
+ rlen--;
+ str[rlen] = 0;
+ for ( p = str; *p && *p <= ' '; p++, rlen-- );
+ if ( !*p )
+ return 0;
+
+ if ( stricmp(str, "start") == 0 )
+ *PP32_DBG_CTRL = DBG_CTRL_RESTART;
+ else if ( stricmp(str, "stop") == 0 )
+ *PP32_DBG_CTRL = DBG_CTRL_STOP;
+// else if ( stricmp(str, "step") == 0 )
+// *PP32_DBG_CTRL = DBG_CTRL_STEP_SET(1);
+ else
+ {
+ printk("echo \"<command>\" > /proc/eth/etop\n");
+ printk(" command:\n");
+ printk(" start - run pp32\n");
+ printk(" stop - stop pp32\n");
+// printk(" step - run pp32 with one step only\n");
+ printk(" help - print this screen\n");
+ }
+
+ return count;
+}
+
+ #endif
+
+#endif
+
+#if defined(ENABLE_FW_PROC) && ENABLE_FW_PROC
+
+static INLINE int print_htu(char *buf, int i)
+{
+ int len = 0;
+
+ if ( HTU_ENTRY(i)->vld ) {
+ len += sprintf(buf + len, "%2d. valid\n", i);
+ len += sprintf(buf + len, " entry 0x%08x - pid %01x vpi %02x vci %04x pti %01x\n", *(unsigned int*)HTU_ENTRY(i), HTU_ENTRY(i)->pid, HTU_ENTRY(i)->vpi, HTU_ENTRY(i)->vci, HTU_ENTRY(i)->pti);
+ len += sprintf(buf + len, " mask 0x%08x - pid %01x vpi %02x vci %04x pti %01x\n", *(unsigned int*)HTU_MASK(i), HTU_MASK(i)->pid_mask, HTU_MASK(i)->vpi_mask, HTU_MASK(i)->vci_mask, HTU_MASK(i)->pti_mask);
+ len += sprintf(buf + len, " result 0x%08x - type: %s, qid: %d", *(unsigned int*)HTU_RESULT(i), HTU_RESULT(i)->type ? "cell" : "AAL5", HTU_RESULT(i)->qid);
+ if ( HTU_RESULT(i)->type )
+ len += sprintf(buf + len, ", cell id: %d, verification: %s", HTU_RESULT(i)->cellid, HTU_RESULT(i)->ven ? "on" : "off");
+ len += sprintf(buf + len, "\n");
+ }
+ else
+ len += sprintf(buf + len, "%2d. invalid\n", i);
+
+ return len;
+}
+
+static int proc_read_htu(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ int len = 0;
+ int len_max = off + count;
+ char *pstr;
+ int llen;
+ char *str;
+ int htuts = *CFG_WRX_HTUTS;
+ int i;
+
+ str = vmalloc (1024);
+ if (!str)
+ return 0;
+
+ pstr = *start = page;
+
+ llen = sprintf(pstr, "HTU Table (Max %d):\n", htuts);
+ pstr += llen;
+ len += llen;
+
+ for ( i = 0; i < htuts; i++ ) {
+ llen = print_htu(str, i);
+ if ( len <= off && len + llen > off ) {
+ memcpy(pstr, str + off - len, len + llen - off);
+ pstr += len + llen - off;
+ }
+ else if ( len > off ) {
+ memcpy(pstr, str, llen);
+ pstr += llen;
+ }
+ len += llen;
+ if ( len >= len_max )
+ goto PROC_READ_HTU_OVERRUN_END;
+ }
+
+ *eof = 1;
+ vfree(str);
+ return len - off;
+
+PROC_READ_HTU_OVERRUN_END:
+
+ return len - llen - off;
+}
+
+static INLINE int print_tx_queue(char *buf, int i)
+{
+ int len = 0;
+
+ if ( (*WTX_DMACH_ON & (1 << i)) ) {
+ len += sprintf(buf + len, "%2d. valid\n", i);
+ len += sprintf(buf + len, " queue 0x%08x - sbid %u, qsb vcid %u, qsb %s\n", (unsigned int)WTX_QUEUE_CONFIG(i), (unsigned int)WTX_QUEUE_CONFIG(i)->sbid, (unsigned int)WTX_QUEUE_CONFIG(i)->qsb_vcid, WTX_QUEUE_CONFIG(i)->qsben ? "enable" : "disable");
+ len += sprintf(buf + len, " dma 0x%08x - base %08x, len %u, vlddes %u\n", (unsigned int)WTX_DMA_CHANNEL_CONFIG(i), WTX_DMA_CHANNEL_CONFIG(i)->desba, WTX_DMA_CHANNEL_CONFIG(i)->deslen, WTX_DMA_CHANNEL_CONFIG(i)->vlddes);
+ }
+ else
+ len += sprintf(buf + len, "%2d. invalid\n", i);
+
+ return len;
+}
+
+static int proc_read_txq(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ int len = 0;
+ int len_max = off + count;
+ char *pstr;
+ int llen;
+ int str_buff_len = 1024;
+ char *str;
+
+ int i;
+
+ str = vmalloc(str_buff_len);
+ if (!str){
+ return 0;
+ }
+ pstr = *start = page;
+
+ llen = sprintf(pstr, "TX Queue Config (Max %d):\n", *CFG_WTX_DCHNUM);
+ pstr += llen;
+ len += llen;
+
+ for ( i = 0; i < 16; i++ ) {
+ llen = print_tx_queue(str, i);
+ if ( len <= off && len + llen > off ) {
+ memcpy(pstr, str + off - len, len + llen - off);
+ pstr += len + llen - off;
+ }
+ else if ( len > off ) {
+ memcpy(pstr, str, llen);
+ pstr += llen;
+ }
+ len += llen;
+ if ( len >= len_max )
+ goto PROC_READ_HTU_OVERRUN_END;
+ }
+
+
+ *eof = 1;
+
+ vfree(str);
+ return len - off;
+
+PROC_READ_HTU_OVERRUN_END:
+
+ return len - llen - off;
+}
+
+ #if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+
+static int proc_read_retx_fw(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ int len = 0;
+
+ unsigned int next_dtu_sid_out, last_dtu_sid_in, next_cell_sid_out, isr_cell_id;
+ unsigned int curr_time, sec_counter, curr_efb;
+ struct Retx_adsl_ppe_intf adsl_ppe_intf;
+
+ adsl_ppe_intf = *RETX_ADSL_PPE_INTF;
+ next_dtu_sid_out = *NEXT_DTU_SID_OUT;
+ last_dtu_sid_in = *LAST_DTU_SID_IN;
+ next_cell_sid_out = *NEXT_CELL_SID_OUT;
+ isr_cell_id = *ISR_CELL_ID;
+
+ curr_time = *URetx_curr_time;
+ sec_counter = *URetx_sec_counter;
+ curr_efb = *RxCURR_EFB;
+
+
+ len += sprintf(page + off + len, "Adsl-PPE Interface:\n");
+ len += sprintf(page + off + len, " dtu_sid = 0x%02x [%3u]\n", adsl_ppe_intf.dtu_sid, adsl_ppe_intf.dtu_sid);
+ len += sprintf(page + off + len, " dtu_timestamp = 0x%02x\n", adsl_ppe_intf.dtu_timestamp);
+ len += sprintf(page + off + len, " local_time = 0x%02x\n", adsl_ppe_intf.local_time);
+ len += sprintf(page + off + len, " is_last_cw = %u\n", adsl_ppe_intf.is_last_cw);
+ len += sprintf(page + off + len, " reinit_flag = %u\n", adsl_ppe_intf.reinit_flag);
+ len += sprintf(page + off + len, " is_bad_cw = %u\n", adsl_ppe_intf.is_bad_cw);
+ len += sprintf(page + off + len, "\n");
+
+
+ len += sprintf(page + off + len, "Retx Firmware Context:\n");
+ len += sprintf(page + off + len, " next_dtu_sid_out (0x%08x) = 0x%02x [%3u]\n", (unsigned int )NEXT_DTU_SID_OUT, next_dtu_sid_out, next_dtu_sid_out);
+ len += sprintf(page + off + len, " last_dtu_sid_in (0x%08x) = 0x%02x [%3u]\n", (unsigned int )LAST_DTU_SID_IN, last_dtu_sid_in, last_dtu_sid_in);
+ len += sprintf(page + off + len, " next_cell_sid_out (0x%08x) = %u\n", (unsigned int )NEXT_CELL_SID_OUT, next_cell_sid_out);
+ len += sprintf(page + off + len, " isr_cell_id (0x%08x) = %u\n", (unsigned int )ISR_CELL_ID, isr_cell_id);
+ len += sprintf(page + off + len, " pb_cell_search_idx (0x%08x) = %u\n", (unsigned int )PB_CELL_SEARCH_IDX, *PB_CELL_SEARCH_IDX);
+ len += sprintf(page + off + len, " pb_read_pend_flag (0x%08x) = %u\n", (unsigned int )PB_READ_PEND_FLAG, *PB_READ_PEND_FLAG);
+ len += sprintf(page + off + len, " rfbi_first_cw (0x%08x) = %u\n", (unsigned int )RFBI_FIRST_CW, *RFBI_FIRST_CW);
+ len += sprintf(page + off + len, " rfbi_bad_cw (0x%08x) = %u\n", (unsigned int )RFBI_BAD_CW, *RFBI_BAD_CW);
+ len += sprintf(page + off + len, " rfbi_invalid_cw (0x%08x) = %u\n", (unsigned int )RFBI_INVALID_CW, *RFBI_INVALID_CW);
+ len += sprintf(page + off + len, " rfbi_retx_cw (0x%08x) = %u\n", (unsigned int )RFBI_RETX_CW, *RFBI_RETX_CW);
+ len += sprintf(page + off + len, " rfbi_chk_dtu_status (0x%08x) = %u\n", (unsigned int )RFBI_CHK_DTU_STATUS,*RFBI_CHK_DTU_STATUS);
+ len += sprintf(page + off + len, "\n");
+
+
+ len += sprintf(page + off + len, "SFSM Status: bc0 bc1 \n\n");
+ len += sprintf(page + off + len, " state = %-22s , %s\n",
+ (*__WRXCTXT_PortState(0) & 3) == 0 ? "Hunt" :
+ (*__WRXCTXT_PortState(0) & 3) == 1 ? "Pre_sync" :
+ (*__WRXCTXT_PortState(0) & 3) == 2 ? "Sync" :
+ "Unknown(error)",
+ (*__WRXCTXT_PortState(1) & 3) == 0 ? "Hunt" :
+ (*__WRXCTXT_PortState(1) & 3) == 1 ? "Pre_sync" :
+ (*__WRXCTXT_PortState(1) & 3) == 2 ? "Sync" :
+ "Unknown(error)" );
+ len += sprintf(page + off + len, " dbase = 0x%04x ( 0x%08x ) , 0x%04x ( 0x%08x )\n",
+ SFSM_DBA(0)->dbase, (unsigned int)PPM_INT_UNIT_ADDR(SFSM_DBA(0)->dbase + 0x2000),
+ SFSM_DBA(1)->dbase, (unsigned int)PPM_INT_UNIT_ADDR(SFSM_DBA(1)->dbase + 0x2000));
+ len += sprintf(page + off + len, " cbase = 0x%04x ( 0x%08x ) , 0x%04x ( 0x%08x )\n",
+ SFSM_CBA(0)->cbase, (unsigned int)PPM_INT_UNIT_ADDR(SFSM_CBA(0)->cbase + 0x2000),
+ SFSM_CBA(1)->cbase, (unsigned int)PPM_INT_UNIT_ADDR(SFSM_CBA(1)->cbase + 0x2000));
+ len += sprintf(page + off + len, " sen = %-22d , %d\n", SFSM_CFG(0)->sen, SFSM_CFG(1)->sen );
+ len += sprintf(page + off + len, " idlekeep = %-22d , %d\n", SFSM_CFG(0)->idlekeep, SFSM_CFG(1)->idlekeep );
+ len += sprintf(page + off + len, " pnum = %-22d , %d\n", SFSM_CFG(0)->pnum, SFSM_CFG(1)->pnum );
+ len += sprintf(page + off + len, " pptr = %-22d , %d\n", SFSM_PGCNT(0)->pptr, SFSM_PGCNT(1)->pptr);
+ len += sprintf(page + off + len, " upage = %-22d , %d\n", SFSM_PGCNT(0)->upage, SFSM_PGCNT(1)->upage);
+ len += sprintf(page + off + len, " l2_rdptr = %-22d , %d\n", *__WRXCTXT_L2_RdPtr(0), *__WRXCTXT_L2_RdPtr(1) );
+ len += sprintf(page + off + len, " l2_page = %-22d , %d\n", *__WRXCTXT_L2Pages(0), *__WRXCTXT_L2Pages(1) );
+ len += sprintf(page + off + len, "\n");
+
+
+ len += sprintf(page + off + len, "FFSM Status: bc0 bc1 \n\n");
+ len += sprintf(page + off + len, " dbase = 0x%04x ( 0x%08x ) , 0x%04x ( 0x%08x )\n",
+ FFSM_DBA(0)->dbase, (unsigned int)PPM_INT_UNIT_ADDR(FFSM_DBA(0)->dbase + 0x2000),
+ FFSM_DBA(1)->dbase, (unsigned int)PPM_INT_UNIT_ADDR(FFSM_DBA(1)->dbase + 0x2000));
+ len += sprintf(page + off + len, " pnum = %-22d , %d\n", FFSM_CFG(0)->pnum, FFSM_CFG(1)->pnum);
+ len += sprintf(page + off + len, " vpage = %-22d , %d\n", FFSM_PGCNT(0)->vpage, FFSM_PGCNT(1)->vpage);
+ len += sprintf(page + off + len, " ival = %-22d , %d\n", FFSM_PGCNT(0)->ival, FFSM_PGCNT(1)->ival);
+ len += sprintf(page + off + len, " tc_wrptr = %-22d , %d\n", *__WTXCTXT_TC_WRPTR(0), *__WTXCTXT_TC_WRPTR(1));
+ len += sprintf(page + off + len, "\n");
+
+
+ len += sprintf(page + off + len, "Misc: \n\n");
+ len += sprintf(page + off + len, " curr_time = %08x\n", curr_time );
+ len += sprintf(page + off + len, " sec_counter = %d\n", sec_counter );
+ len += sprintf(page + off + len, " curr_efb = %d\n", curr_efb );
+ len += sprintf(page + off + len, "\n");
+
+ *eof = 1;
+
+ return len;
+}
+
+static inline int is_valid(unsigned int * dtu_vld_stat, int dtu_sid)
+{
+ int dw_idx = (dtu_sid / 32) & 7;
+ int bit_pos = dtu_sid % 32;
+
+ return dtu_vld_stat[dw_idx] & (0x80000000 >> bit_pos);
+}
+
+static int proc_read_retx_stats(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ int i;
+ int len = 0;
+ int len_max = off + count;
+ char *pstr;
+ char str[2048];
+ int llen = 0;
+
+ unsigned int next_dtu_sid_out, last_dtu_sid_in, next_cell_sid_out;
+ unsigned int dtu_vld_stat[8];
+ struct DTU_stat_info dtu_stat_info[256];
+ struct Retx_adsl_ppe_intf adsl_ppe_intf;
+
+ pstr = *start = page;
+
+ __sync();
+
+ // capture a snapshot of internal status
+ next_dtu_sid_out = *NEXT_DTU_SID_OUT;
+ last_dtu_sid_in = *LAST_DTU_SID_IN;
+ next_cell_sid_out = *NEXT_CELL_SID_OUT;
+ adsl_ppe_intf = *RETX_ADSL_PPE_INTF;
+
+ memcpy(&dtu_vld_stat, (void *)DTU_VLD_STAT, sizeof(dtu_vld_stat));
+ memcpy(&dtu_stat_info, (void *)DTU_STAT_INFO, sizeof(dtu_stat_info));
+
+
+ llen += sprintf(str + llen, "Adsl-PPE Interface:\n");
+ llen += sprintf(str + llen, " dtu_sid = 0x%02x [%3u]\n", adsl_ppe_intf.dtu_sid, adsl_ppe_intf.dtu_sid);
+ llen += sprintf(str + llen, " dtu_timestamp = 0x%02x\n", adsl_ppe_intf.dtu_timestamp);
+ llen += sprintf(str + llen, " local_time = 0x%02x\n", adsl_ppe_intf.local_time);
+ llen += sprintf(str + llen, " is_last_cw = %u\n", adsl_ppe_intf.is_last_cw);
+ llen += sprintf(str + llen, " reinit_flag = %u\n", adsl_ppe_intf.reinit_flag);
+ llen += sprintf(str + llen, " is_bad_cw = %u\n", adsl_ppe_intf.is_bad_cw);
+ llen += sprintf(str + llen, "\n");
+
+ llen += sprintf(str + llen, "Retx Internal State:\n");
+ llen += sprintf(str + llen, " next_dtu_sid_out (0x%08x) = 0x%02x [%3u]\n", (unsigned int )NEXT_DTU_SID_OUT, next_dtu_sid_out, next_dtu_sid_out);
+ llen += sprintf(str + llen, " last_dtu_sid_in (0x%08x) = 0x%02x [%3u]\n", (unsigned int )LAST_DTU_SID_IN, last_dtu_sid_in, last_dtu_sid_in);
+ llen += sprintf(str + llen, " next_cell_sid_out (0x%08x) = %u\n", (unsigned int )NEXT_CELL_SID_OUT, next_cell_sid_out);
+ llen += sprintf(str + llen, " dtu_valid_stat (0x%08x)\n", (unsigned int )DTU_VLD_STAT);
+ llen += sprintf(str + llen, " dtu_stat_info (0x%08x)\n", (unsigned int )DTU_STAT_INFO);
+ llen += sprintf(str + llen, " pb_buffer_usage (0x%08x)\n", (unsigned int )PB_BUFFER_USAGE);
+
+ if ( len <= off && len + llen > off ) {
+ memcpy(pstr, str + off - len, len + llen - off);
+ pstr += len + llen - off;
+ }
+ else if ( len > off ) {
+ memcpy(pstr, str, llen);
+ pstr += llen;
+ }
+ len += llen;
+ if ( len >= len_max )
+ goto PROC_READ_RETX_STATS_OVERRUN_END;
+ llen = 0;
+
+
+ llen += sprintf(str + llen, "\n");
+ llen += sprintf(str + llen, "DTU_VALID_STAT: [0x%08x]:\n", (unsigned int)DTU_VLD_STAT);
+ llen += sprintf(str + llen, "%08X: %08X %08X %08X %08X %08X %08X %08X %08X\n",
+ (unsigned int)DTU_VLD_STAT,
+ dtu_vld_stat[0], dtu_vld_stat[1], dtu_vld_stat[2], dtu_vld_stat[3],
+ dtu_vld_stat[4], dtu_vld_stat[5], dtu_vld_stat[6], dtu_vld_stat[7]);
+
+ if ( len <= off && len + llen > off ) {
+ memcpy(pstr, str + off - len, len + llen - off);
+ pstr += len + llen - off;
+ }
+ else if ( len > off ) {
+ memcpy(pstr, str, llen);
+ pstr += llen;
+ }
+ len += llen;
+ if ( len >= len_max )
+ goto PROC_READ_RETX_STATS_OVERRUN_END;
+ llen = 0;
+
+
+ llen += sprintf(str + llen, "\n");
+ llen += sprintf(str + llen, "DTU_STAT_INFO: [0x%08x]:\n", (unsigned int)DTU_STAT_INFO);
+ llen += sprintf(str + llen, "dtu_id ts complete bad cell_cnt dtu_rd_ptr dtu_wr_ptr\n");
+ llen += sprintf(str + llen, "---------------------------------------------------------------------\n");
+ for ( i = 0; i < 256; i++ ) {
+ if ( !is_valid(dtu_vld_stat, i) )
+ continue;
+
+ llen += sprintf(str + llen, "0x%02x [%3u] 0x%02x %d %d %3d %5d %5d\n",
+ i, i,
+ DTU_STAT_INFO[i].time_stamp,
+ DTU_STAT_INFO[i].complete,
+ DTU_STAT_INFO[i].bad,
+ DTU_STAT_INFO[i].cell_cnt,
+ DTU_STAT_INFO[i].dtu_rd_ptr,
+ DTU_STAT_INFO[i].dtu_wr_ptr );
+
+ if ( len <= off && len + llen > off ) {
+ memcpy(pstr, str + off - len, len + llen - off);
+ pstr += len + llen - off;
+ }
+ else if ( len > off )
+ {
+ memcpy(pstr, str, llen);
+ pstr += llen;
+ }
+ len += llen;
+ if ( len >= len_max )
+ goto PROC_READ_RETX_STATS_OVERRUN_END;
+ llen = 0;
+ }
+
+
+ llen += sprintf(str + llen, "\n");
+ llen += sprintf(str + llen, "Playout buffer status --- valid status [0x%08x]:\n", (unsigned int)PB_BUFFER_USAGE);
+ for( i = 0; i < RETX_MODE_CFG->buff_size; i += 8 ) {
+ llen += sprintf(str + llen, "%08X: %08X %08X %08X %08X %08X %08X %08X %08X\n",
+ (unsigned int)PB_BUFFER_USAGE + i * sizeof(unsigned int),
+ PB_BUFFER_USAGE[i], PB_BUFFER_USAGE[i+1], PB_BUFFER_USAGE[i+2], PB_BUFFER_USAGE[i+3],
+ PB_BUFFER_USAGE[i+4], PB_BUFFER_USAGE[i+5], PB_BUFFER_USAGE[i+6], PB_BUFFER_USAGE[i+7]);
+ }
+
+ if ( len <= off && len + llen > off ) {
+ memcpy(pstr, str + off - len, len + llen - off);
+ pstr += len + llen - off;
+ }
+ else if ( len > off ) {
+ memcpy(pstr, str, llen);
+ pstr += llen;
+ }
+ len += llen;
+ if ( len >= len_max )
+ goto PROC_READ_RETX_STATS_OVERRUN_END;
+ llen = 0;
+
+
+ *eof = 1;
+
+ return len - off;
+
+PROC_READ_RETX_STATS_OVERRUN_END:
+ return len - llen - off;
+}
+
+static int proc_write_retx_stats(struct file *file, const char *buf, unsigned long count, void *data)
+{
+ char str[2048];
+ char *p;
+
+ int len, rlen;
+
+ len = count < sizeof(str) ? count : sizeof(str) - 1;
+ rlen = len - copy_from_user(str, buf, len);
+ while ( rlen && str[rlen - 1] <= ' ' )
+ rlen--;
+ str[rlen] = 0;
+ for ( p = str; *p && *p <= ' '; p++, rlen-- );
+ if ( !*p )
+ return 0;
+
+ if ( stricmp(p, "help") == 0 ) {
+ printk("echo clear_pb > /proc/driver/ifx_atm/retx_stats \n");
+ printk(" :clear context in playout buffer\n\n");
+ printk("echo read_pb <pb_index> <cell_num> > /proc/driver/ifx_atm/retx_stats\n");
+ printk(" : read playout buffer contents\n\n");
+ printk("echo read_[r|t]x_cb > /proc/driver/ifx_atm/retx_stats\n");
+ printk(" : read cell buffer\n\n");
+ printk("echo clear_[r|t]x_cb > /proc/driver/ifx_atm/retx_stats\n");
+ printk(" : clear cell buffer\n\n");
+ printk("echo read_bad_dtu_intf_rec > /proc/driver/ifx_atm/retx_stats\n");
+ printk(" : read bad dtu intrface information record\n\n");
+ printk("echo clear_bad_dtu_intf_rec > /proc/driver/ifx_atm/retx_stats\n");
+ printk(" : clear bad dtu interface information record\n\n");
+ printk("echo read_wrx_context [i] > /proc/driver/ifx_atm/retx_stats\n");
+ printk(" : clear bad dtu interface information record\n\n");
+ printk("echo read_intf_rec > /proc/driver/ifx_atm/retx_stats\n");
+ printk(" : read interface info record buffer\n\n");
+ printk("echo reinit_intf_rec > /proc/driver/ifx_atm/retx_stats\n");
+ printk(" : reinit intf record, must be called before showtime\n\n");
+ }
+ else if ( stricmp(p, "reinit_intf_rec") == 0 ) {
+ int i = 0;
+ struct Retx_adsl_ppe_intf_rec rec[16];
+
+ *DBG_DTU_INTF_WRPTR = 0;
+ *DBG_INTF_FCW_DUP_CNT = 0;
+ *DBG_INTF_SID_CHANGE_IN_DTU_CNT = 0;
+ *DBG_INTF_LCW_DUP_CNT = 0;
+
+ *DBG_RFBI_DONE_INT_CNT = 0;
+ *DBG_RFBI_INTV0 = 0;
+ *DBG_RFBI_INTV1 = 0;
+ *DBG_RFBI_BC0_INVALID_CNT = 0;
+ *DBG_RFBI_LAST_T = 0;
+ *DBG_DREG_BEG_END = 0;
+
+ memset((void *) DBG_INTF_INFO(0), 0, sizeof(rec));
+ for( i = 0; i < 16; i++ )
+ DBG_INTF_INFO(i)->res1_1 = 1;
+ DBG_INTF_INFO(15)->dtu_sid = 255;
+ }
+ else if ( stricmp(p, "read_intf_rec") == 0 ) {
+ int i, cnt;
+ unsigned int dtu_intf_wrptr, fcw_dup_cnt, sid_change_in_dtu_cnt, lcw_dup_cnt ;
+ unsigned int rfbi_done_int_cnt, rfbi_intv0, rfbi_intv1, rfbi_bc0_invalid_cnt, dreg_beg_end;
+ struct Retx_adsl_ppe_intf_rec rec[16];
+
+ memcpy((void *) rec, (void *) DBG_INTF_INFO(0), sizeof(rec));
+
+ dtu_intf_wrptr = *DBG_DTU_INTF_WRPTR;
+ fcw_dup_cnt = *DBG_INTF_FCW_DUP_CNT;
+ sid_change_in_dtu_cnt = *DBG_INTF_SID_CHANGE_IN_DTU_CNT;
+ lcw_dup_cnt = *DBG_INTF_LCW_DUP_CNT;
+
+ rfbi_done_int_cnt = *DBG_RFBI_DONE_INT_CNT;
+ rfbi_intv0 = *DBG_RFBI_INTV0;
+ rfbi_intv1 = *DBG_RFBI_INTV1;
+ rfbi_bc0_invalid_cnt = *DBG_RFBI_BC0_INVALID_CNT;
+ dreg_beg_end = *DBG_DREG_BEG_END;
+
+ printk("PPE-Adsl Interface recrod [addr 0x23F0]:\n\n");
+
+ printk(" rfbi_done_int_cnt = %d [0x%x] \n", rfbi_done_int_cnt, rfbi_done_int_cnt);
+ printk(" rfbi_intv = 0x%08x 0x%08x [%d, %d, %d, %d, %d, %d, %d, %d]\n",
+ rfbi_intv0, rfbi_intv1,
+ rfbi_intv0 >> 24, (rfbi_intv0>>16) & 0xff, (rfbi_intv0>>8) & 0xff, rfbi_intv0 & 0xff,
+ rfbi_intv1 >> 24, (rfbi_intv1>>16) & 0xff, (rfbi_intv1>>8) & 0xff, rfbi_intv1 & 0xff
+ );
+ printk(" rfbi_bc0_invld_cnt = %d\n", rfbi_bc0_invalid_cnt);
+ printk(" dreg_beg_end = %d, %d\n\n", dreg_beg_end >> 16, dreg_beg_end & 0xffff);
+
+ printk(" wrptr = %d [0x%x] \n", dtu_intf_wrptr, dtu_intf_wrptr);
+ printk(" fcw_dup_cnt = %d\n", fcw_dup_cnt);
+ printk(" sid_chg_cnt = %d\n", sid_change_in_dtu_cnt);
+ printk(" lcw_dup_cnt = %d\n\n", lcw_dup_cnt);
+
+
+ printk(" idx itf_dw0 itf_dw1 dtu_sid timestamp local_time res1 last_cw bad_flag reinit\n");
+ printk(" -------------------------------------------------------------------------------------\n");
+ for ( i = (dtu_intf_wrptr + 1) % 16, cnt = 0; cnt < 16; cnt ++, i = (i + 1) % 16 ) {
+ if(cnt < 15)
+ printk(" ");
+ else
+ printk(" *");
+ printk("%3d %04x %04x %3d[%02x] %3d[%02x] %3d[%02x] 0x%02x %d %d %d\n",
+ i,
+ (*(unsigned int *)&rec[i]) & 0xffff,
+ (*(unsigned int *)&rec[i]) >> 16,
+ rec[i].dtu_sid, rec[i].dtu_sid,
+ rec[i].dtu_timestamp, rec[i].dtu_timestamp,
+ rec[i].local_time, rec[i].local_time,
+ rec[i].res1_1,
+ rec[i].is_last_cw,
+ rec[i].is_bad_cw,
+ rec[i].reinit_flag );
+ }
+ }
+ else if ( stricmp(p, "read_wrx_context") == 0 ) {
+ int i = 0;
+ int flag = 0;
+ for( i = 0; i < 8; ++i ) {
+ if ( !WRX_QUEUE_CONTEXT(i)->curr_des0 || !WRX_QUEUE_CONTEXT(i)->curr_des1 )
+ continue;
+
+ flag = 1;
+ printk("WRX queue context [ %d ]: \n", i);
+ printk(" curr_len = %4d, mfs = %d, ec = %d, clp1 = %d, aal5dp = %d\n",
+ WRX_QUEUE_CONTEXT(i)->curr_len, WRX_QUEUE_CONTEXT(i)->mfs,
+ WRX_QUEUE_CONTEXT(i)->ec, WRX_QUEUE_CONTEXT(i)->clp1,
+ WRX_QUEUE_CONTEXT(i)->aal5dp);
+ printk(" initcrc = %08x\n", WRX_QUEUE_CONTEXT(i)->intcrc);
+ printk(" currdes = %08x %08x\n",
+ WRX_QUEUE_CONTEXT(i)->curr_des0, WRX_QUEUE_CONTEXT(i)->curr_des1);
+ printk(" last_dw = %08x\n\n", WRX_QUEUE_CONTEXT(i)->last_dword);
+ if( WRX_QUEUE_CONTEXT(i)->curr_len ) {
+ int j = 0;
+ unsigned char *p_char;
+ struct rx_descriptor *desc = (struct rx_descriptor *)&(WRX_QUEUE_CONTEXT(i)->curr_des0);
+ p_char = (unsigned char *)(((unsigned int)desc->dataptr << 2) | KSEG1);
+ printk(" Data in SDRAM:\n ");
+
+ for ( j = 0 ; j < WRX_QUEUE_CONTEXT(i)->curr_len; ++j ) {
+ printk ("%02x", p_char[j]);
+ if ( j % 16 == 15 )
+ printk("\n ");
+ else if ( j % 4 == 3 )
+ printk (" ");
+ }
+ printk("\n\n");
+ }
+ }
+ if ( !flag ) {
+ printk("No active wrx queue context\n");
+ }
+ }
+ else if ( stricmp(p, "clear_pb") == 0 ) {
+ if ( g_retx_playout_buffer )
+ memset((void *)g_retx_playout_buffer, 0, RETX_PLAYOUT_BUFFER_SIZE);
+ }
+ else if ( stricmp(p, "read_bad_dtu_intf_rec") == 0 ) {
+ struct Retx_adsl_ppe_intf first_dtu_intf, last_dtu_intf;
+ first_dtu_intf = *FIRST_BAD_REC_RETX_ADSL_PPE_INTF;
+ last_dtu_intf = *BAD_REC_RETX_ADSL_PPE_INTF;
+
+ printk("\nAdsl-PPE Interface for first and last DTU of recent noise:\n\n");
+ printk(" dtu_sid = 0x%02x [%3u], 0x%02x [%3u]\n",
+ first_dtu_intf.dtu_sid, first_dtu_intf.dtu_sid,
+ last_dtu_intf.dtu_sid, last_dtu_intf.dtu_sid);
+ printk(" dtu_timestamp = 0x%02x , 0x%02x\n",
+ first_dtu_intf.dtu_timestamp, last_dtu_intf.dtu_timestamp);
+ printk(" local_time = 0x%02x , 0x%02x\n",
+ first_dtu_intf.local_time, last_dtu_intf.local_time);
+ printk(" is_last_cw = %u , %u\n",
+ first_dtu_intf.is_last_cw, last_dtu_intf.is_last_cw);
+ printk(" reinit_flag = %u , %u\n",
+ first_dtu_intf.reinit_flag, last_dtu_intf.reinit_flag);
+ printk(" is_bad_cw = %u , %u\n\n",
+ first_dtu_intf.is_bad_cw, last_dtu_intf.is_bad_cw);
+ }
+ else if ( stricmp(p, "clear_bad_dtu_intf_rec") == 0 ) {
+ memset((void *)BAD_REC_RETX_ADSL_PPE_INTF, 0, sizeof(struct Retx_adsl_ppe_intf));
+ memset((void *)FIRST_BAD_REC_RETX_ADSL_PPE_INTF, 0, sizeof(struct Retx_adsl_ppe_intf));
+ }
+ else if ( stricmp(p, "clear_tx_cb") == 0 ) {
+ unsigned int *dbase0;
+ unsigned int pnum0;
+
+ dbase0 = (unsigned int *)PPM_INT_UNIT_ADDR( FFSM_DBA(0)->dbase + 0x2000);
+ pnum0 = FFSM_CFG(0)->pnum;
+ memset(dbase0, 0, 14 * sizeof(unsigned int ) * pnum0);
+ }
+ else if ( stricmp(p, "clear_rx_cb") == 0 ) {
+ unsigned int *dbase0, *cbase0, *dbase1, *cbase1;
+ unsigned int pnum0;
+
+ dbase0 = (unsigned int *)PPM_INT_UNIT_ADDR( SFSM_DBA(0)->dbase + 0x2000);
+ cbase0 = (unsigned int *)PPM_INT_UNIT_ADDR( SFSM_CBA(0)->cbase + 0x2000);
+
+ dbase1 = (unsigned int *)PPM_INT_UNIT_ADDR( SFSM_DBA(1)->dbase + 0x2000);
+ cbase1 = (unsigned int *)PPM_INT_UNIT_ADDR( SFSM_CBA(1)->cbase + 0x2000);
+
+ pnum0 = SFSM_CFG(0)->pnum;
+
+ memset(dbase0, 0, 14 * sizeof(unsigned int ) * pnum0);
+ memset(cbase0, 0, sizeof(unsigned int ) * pnum0);
+
+ memset(dbase1, 0, 14 * sizeof(unsigned int ));
+ memset(cbase1, 0, sizeof(unsigned int ));
+ }
+ else if ( strnicmp(p, "read_tx_cb", 10) == 0 ) {
+ unsigned int *dbase0;
+ unsigned int pnum0, i;
+ unsigned int * cell;
+
+ dbase0 = (unsigned int *)PPM_INT_UNIT_ADDR( FFSM_DBA(0)->dbase + 0x2000);
+ pnum0 = FFSM_CFG(0)->pnum;
+
+ printk("ATM TX BC 0 CELL data/ctrl buffer:\n\n");
+ for(i = 0; i < pnum0 ; ++ i) {
+ cell = dbase0 + i * 14;
+ printk("cell %2d: %08x %08x\n", i, cell[0], cell[1]);
+ printk(" %08x %08x %08x %08x\n", cell[2], cell[3], cell[4], cell[5]);
+ printk(" %08x %08x %08x %08x\n", cell[6], cell[7], cell[8], cell[9]);
+ printk(" %08x %08x %08x %08x\n", cell[10], cell[11], cell[12], cell[13]);
+ }
+ }
+ else if ( strnicmp(p, "read_rx_cb", 10) == 0 ) {
+ unsigned int *dbase0, *cbase0, *dbase1, *cbase1;
+ unsigned int pnum0, i;
+ unsigned int * cell;
+
+ dbase0 = (unsigned int *)PPM_INT_UNIT_ADDR( SFSM_DBA(0)->dbase + 0x2000);
+ cbase0 = (unsigned int *)PPM_INT_UNIT_ADDR( SFSM_CBA(0)->cbase + 0x2000);
+
+ dbase1 = (unsigned int *)PPM_INT_UNIT_ADDR( SFSM_DBA(1)->dbase + 0x2000);
+ cbase1 = (unsigned int *)PPM_INT_UNIT_ADDR( SFSM_CBA(1)->cbase + 0x2000);
+
+ pnum0 = SFSM_CFG(0)->pnum;
+
+ printk("ATM RX BC 0 CELL data/ctrl buffer:\n\n");
+ for(i = 0; i < pnum0 ; ++ i) {
+ struct Retx_ctrl_field * p_ctrl;
+
+ cell = dbase0 + i * 14;
+ p_ctrl = (struct Retx_ctrl_field *) ( &cbase0[i]);
+ printk("cell %2d: %08x %08x -- [%08x]:", i, cell[0], cell[1], cbase0[i]);
+
+ printk("l2_drop: %d, retx: %d", p_ctrl->l2_drop, p_ctrl->retx);
+ if ( p_ctrl->retx ) {
+ printk(", dtu_sid = %u, cell_sid = %u", p_ctrl->dtu_sid, p_ctrl->cell_sid);
+ }
+
+ printk("\n");
+
+ printk(" %08x %08x %08x %08x\n", cell[2], cell[3], cell[4], cell[5]);
+ printk(" %08x %08x %08x %08x\n", cell[6], cell[7], cell[8], cell[9]);
+ printk(" %08x %08x %08x %08x\n", cell[10], cell[11], cell[12], cell[13]);
+ }
+
+ printk("\n");
+ printk("ATM RX BC 1 CELL data/ctrl buffer:\n\n");
+ cell = dbase1;
+ printk("cell %2d: %08x %08x -- [%08x]: dtu_sid:%3d, cell_sid:%3d, next_ptr: %4d\n",
+ 0, cell[0], cell[1], cbase0[i], ( cell[1] >> 16) & 0xff, (cell[1] >> 24) & 0xff, cell[1] & 0xffff );
+ printk(" %08x %08x %08x %08x\n", cell[2], cell[3], cell[4], cell[5]);
+ printk(" %08x %08x %08x %08x\n", cell[6], cell[7], cell[8], cell[9]);
+ printk(" %08x %08x %08x %08x\n", cell[10], cell[11], cell[12], cell[13]);
+ }
+ else if ( strnicmp(p, "read_pb ", 8) == 0 )
+ {
+ int start_cell_idx = 0;
+ int cell_num = 0;
+ unsigned int *cell;
+ unsigned int pb_buff_size = RETX_MODE_CFG->buff_size * 32;
+
+ p += 8;
+ rlen -= 8;
+ ignore_space(&p, &rlen);
+
+ start_cell_idx = get_number(&p, &rlen, 0);
+ ignore_space(&p, &rlen);
+ cell_num = get_number(&p, &rlen, 0);
+
+ if ( start_cell_idx >= pb_buff_size ) {
+ printk(" Invalid cell index\n");
+ }
+ else {
+ int i;
+ if ( cell_num < 0 )
+ cell_num = 1;
+
+ if ( cell_num + start_cell_idx > pb_buff_size )
+ cell_num = pb_buff_size - start_cell_idx;
+
+ for ( i = 0; i < cell_num ; ++i ) {
+ cell = (unsigned int *)((unsigned int *)g_retx_playout_buffer + (14 * (start_cell_idx + i)));
+ printk("cell %4d: %08x %08x [next_ptr = %4u, dtu_sid = %3u, cell_sid = %3u]\n",
+ start_cell_idx + i, cell[0], cell[1], cell[1] & 0xffff, (cell[1] >> 16) & 0xff, (cell[1] >> 24) & 0xff);
+ printk(" %08x %08x %08x %08x\n", cell[2], cell[3], cell[4], cell[5]);
+ printk(" %08x %08x %08x %08x\n", cell[6], cell[7], cell[8], cell[9]);
+ printk(" %08x %08x %08x %08x\n", cell[10], cell[11], cell[12], cell[13]);
+ }
+ }
+ }
+
+ return count;
+}
+
+static int proc_read_retx_cfg(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len += sprintf(page + off + len, "ReTX FW Config:\n");
+ len += sprintf(page + off + len, " RETX_MODE_CFG = 0x%08x, invld_range=%u, buff_size=%u, retx=%u\n", *(volatile unsigned int *)RETX_MODE_CFG, (unsigned int)RETX_MODE_CFG->invld_range, (unsigned int)RETX_MODE_CFG->buff_size * 32, (unsigned int)RETX_MODE_CFG->retx_en);
+ len += sprintf(page + off + len, " RETX_TSYNC_CFG = 0x%08x, fw_alpha=%u, sync_inp=%u\n", *(volatile unsigned int *)RETX_TSYNC_CFG, (unsigned int)RETX_TSYNC_CFG->fw_alpha, (unsigned int)RETX_TSYNC_CFG->sync_inp);
+ len += sprintf(page + off + len, " RETX_TD_CFG = 0x%08x, td_max=%u, td_min=%u\n", *(volatile unsigned int *)RETX_TD_CFG, (unsigned int)RETX_TD_CFG->td_max, (unsigned int)RETX_TD_CFG->td_min);
+ len += sprintf(page + off + len, " RETX_PLAYOUT_BUFFER_BASE = 0x%08x\n", *RETX_PLAYOUT_BUFFER_BASE);
+ len += sprintf(page + off + len, " RETX_SERVICE_HEADER_CFG = 0x%08x\n", *RETX_SERVICE_HEADER_CFG);
+ len += sprintf(page + off + len, " RETX_MASK_HEADER_CFG = 0x%08x\n", *RETX_MASK_HEADER_CFG);
+ len += sprintf(page + off + len, " RETX_MIB_TIMER_CFG = 0x%08x, tick_cycle = %d, ticks_per_sec = %d\n",
+ *(unsigned int *)RETX_MIB_TIMER_CFG, RETX_MIB_TIMER_CFG->tick_cycle, RETX_MIB_TIMER_CFG->ticks_per_sec);
+
+ *eof = 1;
+
+ return len;
+}
+
+static int proc_write_retx_cfg(struct file *file, const char *buf, unsigned long count, void *data)
+{
+ char *p1, *p2;
+ int len;
+ int colon;
+ char local_buf[1024];
+ char *tokens[4] = {0};
+ unsigned int token_num = 0;
+
+ len = sizeof(local_buf) < count ? sizeof(local_buf) - 1 : count;
+ len = len - copy_from_user(local_buf, buf, len);
+ local_buf[len] = 0;
+
+ p1 = local_buf;
+ colon = 0;
+ while ( token_num < NUM_ENTITY(tokens) && get_token(&p1, &p2, &len, &colon) ) {
+ tokens[token_num++] = p1;
+
+ p1 = p2;
+ }
+
+ if ( token_num > 0 ) {
+ if ( stricmp(tokens[0], "help") == 0 ) {
+ printk("echo help > /proc/driver/ifx_atm/retx_cfg ==> \n\tprint this help message\n\n");
+
+ printk("echo set retx <enable|disable|0|1|on|off> > /proc/driver/ifx_atm/retx_cfg\n");
+ printk("\t:enable or disable retx feature\n\n");
+
+ printk("echo set <td_max|td_min|fw_alpha|sync_inp|invld_range|buff_size> <number> > /proc/driver/ifx_atm/retx_cfg\n");
+ printk("\t: set td_max, td_min, fw_alpha, sync_inp, invalid_range, buff_size\n\n");
+
+ printk("echo set <service_header|service_mask> <hex_number> /proc/driver/ifx_atm/retx_cfg \n");
+ printk("\t: set service_header, service_mask\n\n");
+ }
+ else if ( stricmp(tokens[0], "set") == 0 && token_num >= 3 ) {
+
+ if ( stricmp(tokens[1], "retx") == 0 ) {
+ if ( stricmp(tokens[2], "enable") == 0 ||
+ stricmp(tokens[2], "on") == 0 ||
+ stricmp(tokens[2], "1") == 0 )
+ RETX_MODE_CFG->retx_en = 1;
+ else if ( stricmp(tokens[2], "disable") == 0 ||
+ stricmp(tokens[2], "off") == 0 ||
+ stricmp(tokens[2], "0") == 0 )
+ RETX_MODE_CFG->retx_en = 0;
+ printk("RETX_MODE_CFG->retx_en - %d\n", RETX_MODE_CFG->retx_en);
+ }
+ else {
+ unsigned int dec_val, hex_val;
+
+ p1 = tokens[2];
+ dec_val = (unsigned int)get_number(&p1, NULL, 0);
+ p2 = tokens[2];
+ hex_val = (unsigned int)get_number(&p2, NULL, 1);
+
+ if ( *p2 == 0 ) {
+ if ( stricmp(tokens[1], "service_header") == 0 ) {
+ *RETX_SERVICE_HEADER_CFG = hex_val;
+ printk("RETX_SERVICE_HEADER_CFG - 0x%08x\n", *RETX_SERVICE_HEADER_CFG);
+ }
+ else if ( stricmp(tokens[1], "service_mask") == 0 ) {
+ *RETX_MASK_HEADER_CFG = hex_val;
+ printk("RETX_MASK_HEADER_CFG - 0x%08x\n", *RETX_MASK_HEADER_CFG);
+ }
+ }
+ if ( *p1 == 0 ) {
+ if ( stricmp(tokens[1], "td_max") == 0 ) {
+ (unsigned int)RETX_TD_CFG->td_max = (dec_val >= 0xff ? 0Xff : dec_val);
+ printk("RETX_TD_CFG->td_max - %d\n", RETX_TD_CFG->td_max);
+ }
+ else if ( stricmp(tokens[1], "td_min") == 0 ) {
+ (unsigned int)RETX_TD_CFG->td_min = (dec_val >= 0xff ? 0Xff : dec_val);
+ printk("RETX_TD_CFG->td_min - %d\n", RETX_TD_CFG->td_min);
+ }
+ else if ( stricmp(tokens[1], "fw_alpha") == 0 ) {
+ RETX_TSYNC_CFG->fw_alpha = dec_val >= 0x7FFE ? 0X7EEE : dec_val;
+ printk("RETX_TSYNC_CFG->fw_alpha - %d\n", RETX_TSYNC_CFG->fw_alpha);
+ }
+ else if ( stricmp(tokens[1], "sync_inp") == 0 ) {
+ RETX_TSYNC_CFG->sync_inp = dec_val >= 0x7FFE ? 0X7EEE : dec_val;
+ printk("RETX_TSYNC_CFG->sync_inp - %d\n", RETX_TSYNC_CFG->sync_inp);
+ }
+ else if ( stricmp(tokens[1], "invld_range") == 0 ) {
+ RETX_MODE_CFG->invld_range = dec_val >= 250 ? 250 : dec_val;
+ printk("RETX_MODE_CFG->invld_range - %d\n", RETX_MODE_CFG->invld_range);
+ }
+ else if ( stricmp(tokens[1], "buff_size") == 0 ) {
+ dec_val = (dec_val + 31) / 32;
+ RETX_MODE_CFG->buff_size = dec_val >= 4096 / 32 ? 4096 / 32 : dec_val;
+ printk("RETX_MODE_CFG->buff_size - %d\n", RETX_MODE_CFG->buff_size);
+ }
+ }
+ }
+
+ }
+ }
+
+ return count;
+}
+
+static int proc_read_retx_dsl_param(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len += sprintf(page + off + len, "DSL Param [timestamp %ld.%ld]:\n", g_retx_polling_start.tv_sec, g_retx_polling_start.tv_usec);
+
+ if ( g_xdata_addr == NULL )
+ len += sprintf(page + off + len, " DSL parameters not available !\n");
+ else {
+ volatile struct dsl_param *p_dsl_param = (volatile struct dsl_param *)g_xdata_addr;
+
+ len += sprintf(page + off + len, " update_flag = %u\n", p_dsl_param->update_flag);
+ len += sprintf(page + off + len, " MinDelayrt = %u\n", p_dsl_param->MinDelayrt);
+ len += sprintf(page + off + len, " MaxDelayrt = %u\n", p_dsl_param->MaxDelayrt);
+ len += sprintf(page + off + len, " RetxEnable = %u\n", p_dsl_param->RetxEnable);
+ len += sprintf(page + off + len, " ServiceSpecificReTx = %u\n", p_dsl_param->ServiceSpecificReTx);
+ len += sprintf(page + off + len, " ReTxPVC = 0x%08x\n", p_dsl_param->ReTxPVC);
+ len += sprintf(page + off + len, " RxDtuCorruptedCNT = %u\n", p_dsl_param->RxDtuCorruptedCNT);
+ len += sprintf(page + off + len, " RxRetxDtuUnCorrectedCNT = %u\n", p_dsl_param->RxRetxDtuUnCorrectedCNT);
+ len += sprintf(page + off + len, " RxLastEFB = %u\n", p_dsl_param->RxLastEFB);
+ len += sprintf(page + off + len, " RxDtuCorrectedCNT = %u\n", p_dsl_param->RxDtuCorrectedCNT);
+ }
+ if ( g_retx_polling_end.tv_sec != 0 || g_retx_polling_end.tv_usec != 0 ) {
+ unsigned long polling_time_usec;
+
+ polling_time_usec = (g_retx_polling_end.tv_sec - g_retx_polling_start.tv_sec) * 1000000 + (g_retx_polling_end.tv_usec - g_retx_polling_start.tv_usec);
+ len += sprintf(page + off + len, "DSL Param Update Time: %lu.%03lums\n", polling_time_usec / 1000, polling_time_usec % 1000);
+ }
+
+ return len;
+}
+
+ #endif
+
+#endif
+
+static int stricmp(const char *p1, const char *p2)
+{
+ int c1, c2;
+
+ while ( *p1 && *p2 ) {
+ c1 = *p1 >= 'A' && *p1 <= 'Z' ? *p1 + 'a' - 'A' : *p1;
+ c2 = *p2 >= 'A' && *p2 <= 'Z' ? *p2 + 'a' - 'A' : *p2;
+ if ( (c1 -= c2) )
+ return c1;
+ p1++;
+ p2++;
+ }
+
+ return *p1 - *p2;
+}
+
+#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC
+
+static int strincmp(const char *p1, const char *p2, int n)
+{
+ int c1 = 0, c2;
+
+ while ( n && *p1 && *p2 ) {
+ c1 = *p1 >= 'A' && *p1 <= 'Z' ? *p1 + 'a' - 'A' : *p1;
+ c2 = *p2 >= 'A' && *p2 <= 'Z' ? *p2 + 'a' - 'A' : *p2;
+ if ( (c1 -= c2) )
+ return c1;
+ p1++;
+ p2++;
+ n--;
+ }
+
+ return n ? *p1 - *p2 : c1;
+}
+
+static int get_token(char **p1, char **p2, int *len, int *colon)
+{
+ int tlen = 0;
+
+ while ( *len && !((**p1 >= 'A' && **p1 <= 'Z') || (**p1 >= 'a' && **p1<= 'z') || (**p1 >= '0' && **p1<= '9')) )
+ {
+ (*p1)++;
+ (*len)--;
+ }
+ if ( !*len )
+ return 0;
+
+ if ( *colon )
+ {
+ *colon = 0;
+ *p2 = *p1;
+ while ( *len && **p2 > ' ' && **p2 != ',' )
+ {
+ if ( **p2 == ':' )
+ {
+ *colon = 1;
+ break;
+ }
+ (*p2)++;
+ (*len)--;
+ tlen++;
+ }
+ **p2 = 0;
+ }
+ else
+ {
+ *p2 = *p1;
+ while ( *len && **p2 > ' ' && **p2 != ',' )
+ {
+ (*p2)++;
+ (*len)--;
+ tlen++;
+ }
+ **p2 = 0;
+ }
+
+ return tlen;
+}
+
+static unsigned int get_number(char **p, int *len, int is_hex)
+{
+ unsigned int ret = 0;
+ unsigned int n = 0;
+
+ if ( (*p)[0] == '0' && (*p)[1] == 'x' )
+ {
+ is_hex = 1;
+ (*p) += 2;
+ if ( len )
+ (*len) -= 2;
+ }
+
+ if ( is_hex )
+ {
+ while ( (!len || *len) && ((**p >= '0' && **p <= '9') || (**p >= 'a' && **p <= 'f') || (**p >= 'A' && **p <= 'F')) )
+ {
+ if ( **p >= '0' && **p <= '9' )
+ n = **p - '0';
+ else if ( **p >= 'a' && **p <= 'f' )
+ n = **p - 'a' + 10;
+ else if ( **p >= 'A' && **p <= 'F' )
+ n = **p - 'A' + 10;
+ ret = (ret << 4) | n;
+ (*p)++;
+ if ( len )
+ (*len)--;
+ }
+ }
+ else
+ {
+ while ( (!len || *len) && **p >= '0' && **p <= '9' )
+ {
+ n = **p - '0';
+ ret = ret * 10 + n;
+ (*p)++;
+ if ( len )
+ (*len)--;
+ }
+ }
+
+ return ret;
+}
+
+static void ignore_space(char **p, int *len)
+{
+ while ( *len && (**p <= ' ' || **p == ':' || **p == '.' || **p == ',') )
+ {
+ (*p)++;
+ (*len)--;
+ }
+}
+
+#endif
+
+static INLINE int ifx_atm_version(char *buf)
+{
+ int len = 0;
+ unsigned int major, minor;
+
+ ifx_atm_get_fw_ver(&major, &minor);
+
+ len += sprintf(buf + len, " ATM (A1) firmware version %d.%d.%d\n", IFX_ATM_VER_MAJOR, IFX_ATM_VER_MID,IFX_ATM_VER_MINOR);
+
+ return len;
+}
+
+static INLINE void check_parameters(void)
+{
+ /* Please refer to Amazon spec 15.4 for setting these values. */
+ if ( qsb_tau < 1 )
+ qsb_tau = 1;
+ if ( qsb_tstep < 1 )
+ qsb_tstep = 1;
+ else if ( qsb_tstep > 4 )
+ qsb_tstep = 4;
+ else if ( qsb_tstep == 3 )
+ qsb_tstep = 2;
+
+ /* There is a delay between PPE write descriptor and descriptor is */
+ /* really stored in memory. Host also has this delay when writing */
+ /* descriptor. So PPE will use this value to determine if the write */
+ /* operation makes effect. */
+ if ( write_descriptor_delay < 0 )
+ write_descriptor_delay = 0;
+
+ if ( aal5_fill_pattern < 0 )
+ aal5_fill_pattern = 0;
+ else
+ aal5_fill_pattern &= 0xFF;
+
+ /* Because of the limitation of length field in descriptors, the packet */
+ /* size could not be larger than 64K minus overhead size. */
+ if ( aal5r_max_packet_size < 0 )
+ aal5r_max_packet_size = 0;
+ else if ( aal5r_max_packet_size >= 65535 - MAX_RX_FRAME_EXTRA_BYTES )
+ aal5r_max_packet_size = 65535 - MAX_RX_FRAME_EXTRA_BYTES;
+ if ( aal5r_min_packet_size < 0 )
+ aal5r_min_packet_size = 0;
+ else if ( aal5r_min_packet_size > aal5r_max_packet_size )
+ aal5r_min_packet_size = aal5r_max_packet_size;
+ if ( aal5s_max_packet_size < 0 )
+ aal5s_max_packet_size = 0;
+ else if ( aal5s_max_packet_size >= 65535 - MAX_TX_FRAME_EXTRA_BYTES )
+ aal5s_max_packet_size = 65535 - MAX_TX_FRAME_EXTRA_BYTES;
+ if ( aal5s_min_packet_size < 0 )
+ aal5s_min_packet_size = 0;
+ else if ( aal5s_min_packet_size > aal5s_max_packet_size )
+ aal5s_min_packet_size = aal5s_max_packet_size;
+
+ if ( dma_rx_descriptor_length < 2 )
+ dma_rx_descriptor_length = 2;
+ if ( dma_tx_descriptor_length < 2 )
+ dma_tx_descriptor_length = 2;
+ if ( dma_rx_clp1_descriptor_threshold < 0 )
+ dma_rx_clp1_descriptor_threshold = 0;
+ else if ( dma_rx_clp1_descriptor_threshold > dma_rx_descriptor_length )
+ dma_rx_clp1_descriptor_threshold = dma_rx_descriptor_length;
+
+ if ( dma_tx_descriptor_length < 2 )
+ dma_tx_descriptor_length = 2;
+}
+
+static INLINE int init_priv_data(void)
+{
+ void *p;
+ int i;
+ struct rx_descriptor rx_desc = {0};
+ struct sk_buff *skb;
+ volatile struct tx_descriptor *p_tx_desc;
+ struct sk_buff **ppskb;
+
+ // clear atm private data structure
+ memset(&g_atm_priv_data, 0, sizeof(g_atm_priv_data));
+
+ // allocate memory for RX (AAL) descriptors
+ p = kzalloc(dma_rx_descriptor_length * sizeof(struct rx_descriptor) + DESC_ALIGNMENT, GFP_KERNEL);
+ if ( p == NULL )
+ return IFX_ERROR;
+ dma_cache_wback_inv((unsigned long)p, dma_rx_descriptor_length * sizeof(struct rx_descriptor) + DESC_ALIGNMENT);
+ g_atm_priv_data.aal_desc_base = p;
+ p = (void *)((((unsigned int)p + DESC_ALIGNMENT - 1) & ~(DESC_ALIGNMENT - 1)) | KSEG1);
+ g_atm_priv_data.aal_desc = (volatile struct rx_descriptor *)p;
+
+ // allocate memory for RX (OAM) descriptors
+ p = kzalloc(RX_DMA_CH_OAM_DESC_LEN * sizeof(struct rx_descriptor) + DESC_ALIGNMENT, GFP_KERNEL);
+ if ( p == NULL )
+ return IFX_ERROR;
+ dma_cache_wback_inv((unsigned long)p, RX_DMA_CH_OAM_DESC_LEN * sizeof(struct rx_descriptor) + DESC_ALIGNMENT);
+ g_atm_priv_data.oam_desc_base = p;
+ p = (void *)((((unsigned int)p + DESC_ALIGNMENT - 1) & ~(DESC_ALIGNMENT - 1)) | KSEG1);
+ g_atm_priv_data.oam_desc = (volatile struct rx_descriptor *)p;
+
+ // allocate memory for RX (OAM) buffer
+ p = kzalloc(RX_DMA_CH_OAM_DESC_LEN * RX_DMA_CH_OAM_BUF_SIZE + DATA_BUFFER_ALIGNMENT, GFP_KERNEL);
+ if ( p == NULL )
+ return IFX_ERROR;
+ dma_cache_wback_inv((unsigned long)p, RX_DMA_CH_OAM_DESC_LEN * RX_DMA_CH_OAM_BUF_SIZE + DATA_BUFFER_ALIGNMENT);
+ g_atm_priv_data.oam_buf_base = p;
+ p = (void *)(((unsigned int)p + DATA_BUFFER_ALIGNMENT - 1) & ~(DATA_BUFFER_ALIGNMENT - 1));
+ g_atm_priv_data.oam_buf = p;
+
+ // allocate memory for TX descriptors
+ p = kzalloc(MAX_PVC_NUMBER * dma_tx_descriptor_length * sizeof(struct tx_descriptor) + DESC_ALIGNMENT, GFP_KERNEL);
+ if ( p == NULL )
+ return IFX_ERROR;
+ dma_cache_wback_inv((unsigned long)p, MAX_PVC_NUMBER * dma_tx_descriptor_length * sizeof(struct tx_descriptor) + DESC_ALIGNMENT);
+ g_atm_priv_data.tx_desc_base = p;
+
+ // allocate memory for TX skb pointers
+ p = kzalloc(MAX_PVC_NUMBER * dma_tx_descriptor_length * sizeof(struct sk_buff *) + 4, GFP_KERNEL);
+ if ( p == NULL )
+ return IFX_ERROR;
+ dma_cache_wback_inv((unsigned long)p, MAX_PVC_NUMBER * dma_tx_descriptor_length * sizeof(struct sk_buff *) + 4);
+ g_atm_priv_data.tx_skb_base = p;
+
+ // setup RX (AAL) descriptors
+ rx_desc.own = 1;
+ rx_desc.c = 0;
+ rx_desc.sop = 1;
+ rx_desc.eop = 1;
+ rx_desc.byteoff = 0;
+ rx_desc.id = 0;
+ rx_desc.err = 0;
+ rx_desc.datalen = RX_DMA_CH_AAL_BUF_SIZE;
+ for ( i = 0; i < dma_rx_descriptor_length; i++ ) {
+ skb = alloc_skb_rx();
+ if ( skb == NULL )
+ return IFX_ERROR;
+ rx_desc.dataptr = ((unsigned int)skb->data >> 2) & 0x0FFFFFFF;
+ g_atm_priv_data.aal_desc[i] = rx_desc;
+ }
+
+ // setup RX (OAM) descriptors
+ p = (void *)((unsigned int)g_atm_priv_data.oam_buf | KSEG1);
+ rx_desc.own = 1;
+ rx_desc.c = 0;
+ rx_desc.sop = 1;
+ rx_desc.eop = 1;
+ rx_desc.byteoff = 0;
+ rx_desc.id = 0;
+ rx_desc.err = 0;
+ rx_desc.datalen = RX_DMA_CH_OAM_BUF_SIZE;
+ for ( i = 0; i < RX_DMA_CH_OAM_DESC_LEN; i++ ) {
+ rx_desc.dataptr = ((unsigned int)p >> 2) & 0x0FFFFFFF;
+ g_atm_priv_data.oam_desc[i] = rx_desc;
+ p = (void *)((unsigned int)p + RX_DMA_CH_OAM_BUF_SIZE);
+ }
+
+ // setup TX descriptors and skb pointers
+ p_tx_desc = (volatile struct tx_descriptor *)((((unsigned int)g_atm_priv_data.tx_desc_base + DESC_ALIGNMENT - 1) & ~(DESC_ALIGNMENT - 1)) | KSEG1);
+ ppskb = (struct sk_buff **)(((unsigned int)g_atm_priv_data.tx_skb_base + 3) & ~3);
+ for ( i = 0; i < MAX_PVC_NUMBER; i++ ) {
+ g_atm_priv_data.conn[i].tx_desc = &p_tx_desc[i * dma_tx_descriptor_length];
+ g_atm_priv_data.conn[i].tx_skb = &ppskb[i * dma_tx_descriptor_length];
+ }
+
+ for ( i = 0; i < ATM_PORT_NUMBER; i++ )
+ g_atm_priv_data.port[i].tx_max_cell_rate = DEFAULT_TX_LINK_RATE;
+
+ return IFX_SUCCESS;
+}
+
+static INLINE void clear_priv_data(void)
+{
+ int i, j;
+ struct sk_buff *skb;
+
+ for ( i = 0; i < MAX_PVC_NUMBER; i++ ) {
+ if ( g_atm_priv_data.conn[i].tx_skb != NULL ) {
+ for ( j = 0; j < dma_tx_descriptor_length; j++ )
+ if ( g_atm_priv_data.conn[i].tx_skb[j] != NULL )
+ dev_kfree_skb_any(g_atm_priv_data.conn[i].tx_skb[j]);
+ }
+ }
+
+ if ( g_atm_priv_data.tx_skb_base != NULL )
+ kfree(g_atm_priv_data.tx_skb_base);
+
+ if ( g_atm_priv_data.tx_desc_base != NULL )
+ kfree(g_atm_priv_data.tx_desc_base);
+
+ if ( g_atm_priv_data.oam_buf_base != NULL )
+ kfree(g_atm_priv_data.oam_buf_base);
+
+ if ( g_atm_priv_data.oam_desc_base != NULL )
+ kfree(g_atm_priv_data.oam_desc_base);
+
+ if ( g_atm_priv_data.aal_desc_base != NULL ) {
+ for ( i = 0; i < dma_rx_descriptor_length; i++ ) {
+ if ( g_atm_priv_data.aal_desc[i].sop || g_atm_priv_data.aal_desc[i].eop ) { // descriptor initialized
+ skb = get_skb_rx_pointer(g_atm_priv_data.aal_desc[i].dataptr);
+ dev_kfree_skb_any(skb);
+ }
+ }
+ kfree(g_atm_priv_data.aal_desc_base);
+ }
+}
+
+static INLINE void init_rx_tables(void)
+{
+ int i;
+ struct wrx_queue_config wrx_queue_config = {0};
+ struct wrx_dma_channel_config wrx_dma_channel_config = {0};
+ struct htu_entry htu_entry = {0};
+ struct htu_result htu_result = {0};
+ struct htu_mask htu_mask = { set: 0x01,
+ clp: 0x01,
+ pid_mask: 0x00,
+ vpi_mask: 0x00,
+ vci_mask: 0x00,
+ pti_mask: 0x00,
+ clear: 0x00};
+
+ /*
+ * General Registers
+ */
+ *CFG_WRX_HTUTS = MAX_PVC_NUMBER + OAM_HTU_ENTRY_NUMBER;
+#ifndef CONFIG_AMAZON_SE
+ *CFG_WRX_QNUM = MAX_QUEUE_NUMBER;
+#endif
+ *CFG_WRX_DCHNUM = RX_DMA_CH_TOTAL;
+ *WRX_DMACH_ON = (1 << RX_DMA_CH_TOTAL) - 1;
+ *WRX_HUNT_BITTH = DEFAULT_RX_HUNT_BITTH;
+
+ /*
+ * WRX Queue Configuration Table
+ */
+ wrx_queue_config.uumask = 0;
+ wrx_queue_config.cpimask = 0;
+ wrx_queue_config.uuexp = 0;
+ wrx_queue_config.cpiexp = 0;
+ wrx_queue_config.mfs = aal5r_max_packet_size;
+ wrx_queue_config.oversize = aal5r_max_packet_size;
+ wrx_queue_config.undersize = aal5r_min_packet_size;
+ wrx_queue_config.errdp = aal5r_drop_error_packet;
+ wrx_queue_config.dmach = RX_DMA_CH_AAL;
+ for ( i = 0; i < MAX_QUEUE_NUMBER; i++ )
+ *WRX_QUEUE_CONFIG(i) = wrx_queue_config;
+ WRX_QUEUE_CONFIG(OAM_RX_QUEUE)->dmach = RX_DMA_CH_OAM;
+
+ /*
+ * WRX DMA Channel Configuration Table
+ */
+ wrx_dma_channel_config.chrl = 0;
+ wrx_dma_channel_config.clp1th = dma_rx_clp1_descriptor_threshold;
+ wrx_dma_channel_config.mode = 0;
+ wrx_dma_channel_config.rlcfg = 0;
+
+ wrx_dma_channel_config.deslen = RX_DMA_CH_OAM_DESC_LEN;
+ wrx_dma_channel_config.desba = ((unsigned int)g_atm_priv_data.oam_desc >> 2) & 0x0FFFFFFF;
+ *WRX_DMA_CHANNEL_CONFIG(RX_DMA_CH_OAM) = wrx_dma_channel_config;
+
+ wrx_dma_channel_config.deslen = dma_rx_descriptor_length;
+ wrx_dma_channel_config.desba = ((unsigned int)g_atm_priv_data.aal_desc >> 2) & 0x0FFFFFFF;
+ *WRX_DMA_CHANNEL_CONFIG(RX_DMA_CH_AAL) = wrx_dma_channel_config;
+
+ /*
+ * HTU Tables
+ */
+ for ( i = 0; i < MAX_PVC_NUMBER; i++ )
+ {
+ htu_result.qid = (unsigned int)i;
+
+ *HTU_ENTRY(i + OAM_HTU_ENTRY_NUMBER) = htu_entry;
+ *HTU_MASK(i + OAM_HTU_ENTRY_NUMBER) = htu_mask;
+ *HTU_RESULT(i + OAM_HTU_ENTRY_NUMBER) = htu_result;
+ }
+ /* OAM HTU Entry */
+ htu_entry.vci = 0x03;
+ htu_mask.pid_mask = 0x03;
+ htu_mask.vpi_mask = 0xFF;
+ htu_mask.vci_mask = 0x0000;
+ htu_mask.pti_mask = 0x07;
+ htu_result.cellid = OAM_RX_QUEUE;
+ htu_result.type = 1;
+ htu_result.ven = 1;
+ htu_result.qid = OAM_RX_QUEUE;
+ *HTU_RESULT(OAM_F4_SEG_HTU_ENTRY) = htu_result;
+ *HTU_MASK(OAM_F4_SEG_HTU_ENTRY) = htu_mask;
+ *HTU_ENTRY(OAM_F4_SEG_HTU_ENTRY) = htu_entry;
+ htu_entry.vci = 0x04;
+ htu_result.cellid = OAM_RX_QUEUE;
+ htu_result.type = 1;
+ htu_result.ven = 1;
+ htu_result.qid = OAM_RX_QUEUE;
+ *HTU_RESULT(OAM_F4_TOT_HTU_ENTRY) = htu_result;
+ *HTU_MASK(OAM_F4_TOT_HTU_ENTRY) = htu_mask;
+ *HTU_ENTRY(OAM_F4_TOT_HTU_ENTRY) = htu_entry;
+ htu_entry.vci = 0x00;
+ htu_entry.pti = 0x04;
+ htu_mask.vci_mask = 0xFFFF;
+ htu_mask.pti_mask = 0x01;
+ htu_result.cellid = OAM_RX_QUEUE;
+ htu_result.type = 1;
+ htu_result.ven = 1;
+ htu_result.qid = OAM_RX_QUEUE;
+ *HTU_RESULT(OAM_F5_HTU_ENTRY) = htu_result;
+ *HTU_MASK(OAM_F5_HTU_ENTRY) = htu_mask;
+ *HTU_ENTRY(OAM_F5_HTU_ENTRY) = htu_entry;
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ htu_entry.pid = 0x0;
+ htu_entry.vpi = 0x01;
+ htu_entry.vci = 0x0001;
+ htu_entry.pti = 0x00;
+ htu_mask.pid_mask = 0x0;
+ htu_mask.vpi_mask = 0x00;
+ htu_mask.vci_mask = 0x0000;
+ htu_mask.pti_mask = 0x3;
+ htu_result.cellid = OAM_RX_QUEUE;
+ htu_result.type = 1;
+ htu_result.ven = 1;
+ htu_result.qid = OAM_RX_QUEUE;
+ *HTU_RESULT(OAM_ARQ_HTU_ENTRY) = htu_result;
+ *HTU_MASK(OAM_ARQ_HTU_ENTRY) = htu_mask;
+ *HTU_ENTRY(OAM_ARQ_HTU_ENTRY) = htu_entry;
+#endif
+}
+
+static INLINE void init_tx_tables(void)
+{
+ int i;
+ struct wtx_queue_config wtx_queue_config = {0};
+ struct wtx_dma_channel_config wtx_dma_channel_config = {0};
+ struct wtx_port_config wtx_port_config = { res1: 0,
+ qid: 0,
+ qsben: 1};
+
+ /*
+ * General Registers
+ */
+ *CFG_WTX_DCHNUM = MAX_TX_DMA_CHANNEL_NUMBER;
+ *WTX_DMACH_ON = ((1 << MAX_TX_DMA_CHANNEL_NUMBER) - 1) ^ ((1 << FIRST_QSB_QID) - 1);
+ *CFG_WRDES_DELAY = write_descriptor_delay;
+
+ /*
+ * WTX Port Configuration Table
+ */
+ for ( i = 0; i < ATM_PORT_NUMBER; i++ )
+ *WTX_PORT_CONFIG(i) = wtx_port_config;
+
+ /*
+ * WTX Queue Configuration Table
+ */
+ wtx_queue_config.qsben = 1;
+ wtx_queue_config.sbid = 0;
+ for ( i = 0; i < MAX_TX_DMA_CHANNEL_NUMBER; i++ ) {
+ wtx_queue_config.qsb_vcid = i;
+ *WTX_QUEUE_CONFIG(i) = wtx_queue_config;
+ }
+
+ /*
+ * WTX DMA Channel Configuration Table
+ */
+ wtx_dma_channel_config.mode = 0;
+ wtx_dma_channel_config.deslen = 0;
+ wtx_dma_channel_config.desba = 0;
+ for ( i = 0; i < FIRST_QSB_QID; i++ )
+ *WTX_DMA_CHANNEL_CONFIG(i) = wtx_dma_channel_config;
+ /* normal connection */
+ wtx_dma_channel_config.deslen = dma_tx_descriptor_length;
+ for ( ; i < MAX_TX_DMA_CHANNEL_NUMBER ; i++ ) {
+ wtx_dma_channel_config.desba = ((unsigned int)g_atm_priv_data.conn[i - FIRST_QSB_QID].tx_desc >> 2) & 0x0FFFFFFF;
+ *WTX_DMA_CHANNEL_CONFIG(i) = wtx_dma_channel_config;
+ }
+}
+
+
+
+/*
+ * ####################################
+ * Global Function
+ * ####################################
+ */
+
+static int atm_showtime_enter(struct port_cell_info *port_cell, void *xdata_addr)
+{
+ int i, j;
+
+ ASSERT(port_cell != NULL, "port_cell is NULL");
+ ASSERT(xdata_addr != NULL, "xdata_addr is NULL");
+
+ for ( j = 0; j < ATM_PORT_NUMBER && j < port_cell->port_num; j++ )
+ if ( port_cell->tx_link_rate[j] > 0 )
+ break;
+ for ( i = 0; i < ATM_PORT_NUMBER && i < port_cell->port_num; i++ )
+ g_atm_priv_data.port[i].tx_max_cell_rate = port_cell->tx_link_rate[i] > 0 ? port_cell->tx_link_rate[i] : port_cell->tx_link_rate[j];
+
+ qsb_global_set();
+
+ for ( i = 0; i < MAX_PVC_NUMBER; i++ )
+ if ( g_atm_priv_data.conn[i].vcc != NULL )
+ set_qsb(g_atm_priv_data.conn[i].vcc, &g_atm_priv_data.conn[i].vcc->qos, i);
+
+ // TODO: ReTX set xdata_addr
+ g_xdata_addr = xdata_addr;
+
+ g_showtime = 1;
+
+#if defined(CONFIG_VR9)
+ IFX_REG_W32(0x0F, UTP_CFG);
+#endif
+
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ if ( !timer_pending(&g_retx_polling_timer) ) {
+ g_retx_polling_cnt = HZ;
+ g_retx_polling_timer.expires = jiffies + RETX_POLLING_INTERVAL;
+ add_timer(&g_retx_polling_timer);
+ }
+#endif
+
+ //printk("enter showtime, cell rate: 0 - %d, 1 - %d, xdata addr: 0x%08x\n", g_atm_priv_data.port[0].tx_max_cell_rate, g_atm_priv_data.port[1].tx_max_cell_rate, (unsigned int)g_xdata_addr);
+
+ return IFX_SUCCESS;
+}
+
+static int atm_showtime_exit(void)
+{
+ if ( !g_showtime )
+ return IFX_ERROR;
+
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ RETX_MODE_CFG->retx_en = 0; // disable ReTX
+ del_timer(&g_retx_polling_timer);
+#endif
+
+#if defined(CONFIG_VR9)
+ IFX_REG_W32(0x00, UTP_CFG);
+#endif
+
+ g_showtime = 0;
+
+ // TODO: ReTX clean state
+ g_xdata_addr = NULL;
+
+ printk("leave showtime\n");
+
+ return IFX_SUCCESS;
+}
+
+
+
+/*
+ * ####################################
+ * Init/Cleanup API
+ * ####################################
+ */
+
+/*
+ * Description:
+ * Initialize global variables, PP32, comunication structures, register IRQ
+ * and register device.
+ * Input:
+ * none
+ * Output:
+ * 0 --- successful
+ * else --- failure, usually it is negative value of error code
+ */
+static int __devinit ifx_atm_init(void)
+{
+ int ret;
+ int port_num;
+ struct port_cell_info port_cell = {0};
+ int i, j;
+ char ver_str[256];
+
+ check_parameters();
+
+ ret = init_priv_data();
+ if ( ret != IFX_SUCCESS ) {
+ err("INIT_PRIV_DATA_FAIL");
+ goto INIT_PRIV_DATA_FAIL;
+ }
+
+ ifx_atm_init_chip();
+ init_rx_tables();
+ init_tx_tables();
+
+ /* create devices */
+ for ( port_num = 0; port_num < ATM_PORT_NUMBER; port_num++ ) {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
+ g_atm_priv_data.port[port_num].dev = atm_dev_register("ifxmips_atm", &g_ifx_atm_ops, -1, NULL);
+#else
+ g_atm_priv_data.port[port_num].dev = atm_dev_register("ifxmips_atm", NULL, &g_ifx_atm_ops, -1, NULL);
+#endif
+
+ if ( !g_atm_priv_data.port[port_num].dev ) {
+ err("failed to register atm device %d!", port_num);
+ ret = -EIO;
+ goto ATM_DEV_REGISTER_FAIL;
+ }
+ else {
+ g_atm_priv_data.port[port_num].dev->ci_range.vpi_bits = 8;
+ g_atm_priv_data.port[port_num].dev->ci_range.vci_bits = 16;
+ g_atm_priv_data.port[port_num].dev->link_rate = g_atm_priv_data.port[port_num].tx_max_cell_rate;
+ g_atm_priv_data.port[port_num].dev->dev_data = (void*)port_num;
+ }
+ }
+
+ /* register interrupt handler */
+ ret = request_irq(PPE_MAILBOX_IGU1_INT, mailbox_irq_handler, IRQF_DISABLED, "atm_mailbox_isr", &g_atm_priv_data);
+ if ( ret ) {
+ if ( ret == -EBUSY ) {
+ err("IRQ may be occupied by other driver, please reconfig to disable it.");
+ }
+ else {
+ err("request_irq fail");
+ }
+ goto REQUEST_IRQ_PPE_MAILBOX_IGU1_INT_FAIL;
+ }
+ disable_irq(PPE_MAILBOX_IGU1_INT);
+
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ init_atm_tc_retrans_param();
+
+ init_timer(&g_retx_polling_timer);
+ g_retx_polling_timer.function = retx_polling_func;
+#endif
+
+ ret = ifx_pp32_start(0);
+ if ( ret ) {
+ err("ifx_pp32_start fail!");
+ goto PP32_START_FAIL;
+ }
+
+ port_cell.port_num = ATM_PORT_NUMBER;
+ if( !IS_ERR(&ifx_mei_atm_showtime_check) && &ifx_mei_atm_showtime_check)
+ ifx_mei_atm_showtime_check(&g_showtime, &port_cell, &g_xdata_addr);
+ if ( g_showtime ) {
+ for ( i = 0; i < ATM_PORT_NUMBER; i++ )
+ if ( port_cell.tx_link_rate[i] != 0 )
+ break;
+ for ( j = 0; j < ATM_PORT_NUMBER; j++ )
+ g_atm_priv_data.port[j].tx_max_cell_rate = port_cell.tx_link_rate[j] != 0 ? port_cell.tx_link_rate[j] : port_cell.tx_link_rate[i];
+ }
+
+ qsb_global_set();
+ validate_oam_htu_entry();
+
+#if 0 /*defined(ENABLE_LED_FRAMEWORK) && ENABLE_LED_FRAMEWORK*/
+ ifx_led_trigger_register("dsl_data", &g_data_led_trigger);
+#endif
+
+ /* create proc file */
+ proc_file_create();
+
+ if( !IS_ERR(&ifx_mei_atm_showtime_enter) && &ifx_mei_atm_showtime_enter )
+ ifx_mei_atm_showtime_enter = atm_showtime_enter;
+
+ if( !IS_ERR(&ifx_mei_atm_showtime_exit) && !ifx_mei_atm_showtime_exit )
+ ifx_mei_atm_showtime_exit = atm_showtime_exit;
+
+ ifx_atm_version(ver_str);
+ printk(KERN_INFO "%s", ver_str);
+
+ printk("ifxmips_atm: ATM init succeed\n");
+
+ return IFX_SUCCESS;
+
+PP32_START_FAIL:
+ free_irq(PPE_MAILBOX_IGU1_INT, &g_atm_priv_data);
+REQUEST_IRQ_PPE_MAILBOX_IGU1_INT_FAIL:
+ATM_DEV_REGISTER_FAIL:
+ while ( port_num-- > 0 )
+ atm_dev_deregister(g_atm_priv_data.port[port_num].dev);
+INIT_PRIV_DATA_FAIL:
+ clear_priv_data();
+ printk("ifxmips_atm: ATM init failed\n");
+ return ret;
+}
+
+/*
+ * Description:
+ * Release memory, free IRQ, and deregister device.
+ * Input:
+ * none
+ * Output:
+ * none
+ */
+static void __exit ifx_atm_exit(void)
+{
+ int port_num;
+
+ if( !IS_ERR(&ifx_mei_atm_showtime_enter) && &ifx_mei_atm_showtime_enter )
+ ifx_mei_atm_showtime_enter = NULL;
+ if( !IS_ERR(&ifx_mei_atm_showtime_exit) && !ifx_mei_atm_showtime_exit )
+ ifx_mei_atm_showtime_exit = NULL;
+
+ proc_file_delete();
+
+#if 0 /*defined(ENABLE_LED_FRAMEWORK) && ENABLE_LED_FRAMEWORK*/
+ ifx_led_trigger_deregister(g_data_led_trigger);
+ g_data_led_trigger = NULL;
+#endif
+
+ invalidate_oam_htu_entry();
+
+ ifx_pp32_stop(0);
+
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ del_timer(&g_retx_polling_timer);
+ clear_atm_tc_retrans_param();
+#endif
+
+ free_irq(PPE_MAILBOX_IGU1_INT, &g_atm_priv_data);
+
+ for ( port_num = 0; port_num < ATM_PORT_NUMBER; port_num++ )
+ atm_dev_deregister(g_atm_priv_data.port[port_num].dev);
+
+ ifx_atm_uninit_chip();
+
+ clear_priv_data();
+}
+
+module_init(ifx_atm_init);
+module_exit(ifx_atm_exit);
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/package/ltq-dsl/src/ifxmips_atm_core.h b/package/ltq-dsl/src/ifxmips_atm_core.h
new file mode 100644
index 000000000..e56603955
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_core.h
@@ -0,0 +1,271 @@
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_core.h
+** PROJECT : UEIP
+** MODULES : ATM
+**
+** DATE : 7 Jul 2009
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM driver header file (core functions)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 17 JUN 2009 Xu Liang Init Version
+*******************************************************************************/
+
+#ifndef IFXMIPS_ATM_CORE_H
+#define IFXMIPS_ATM_CORE_H
+
+
+#include "ifxmips_compat.h"
+#include "ifx_atm.h"
+#include "ifxmips_atm_ppe_common.h"
+#include "ifxmips_atm_fw_regs_common.h"
+
+
+
+/*
+ * ####################################
+ * Definition
+ * ####################################
+ */
+
+/*
+ * Compile Options
+ */
+
+#define ENABLE_DEBUG 1
+
+#define ENABLE_ASSERT 1
+
+#define INLINE
+
+#define DEBUG_DUMP_SKB 1
+
+#define DEBUG_QOS 1
+
+#define DISABLE_QOS_WORKAROUND 0
+
+#define ENABLE_DBG_PROC 1
+
+#define ENABLE_FW_PROC 1
+
+#ifdef CONFIG_IFX_ATM_TASKLET
+ #define ENABLE_TASKLET 1
+#endif
+
+#ifdef CONFIG_IFX_ATM_RETX
+ #define ENABLE_ATM_RETX 1
+#endif
+
+#if defined(CONFIG_DSL_MEI_CPE_DRV) && !defined(CONFIG_IFXMIPS_DSL_CPE_MEI)
+ #define CONFIG_IFXMIPS_DSL_CPE_MEI 1
+#endif
+
+/*
+ * Debug/Assert/Error Message
+ */
+
+#define DBG_ENABLE_MASK_ERR (1 << 0)
+#define DBG_ENABLE_MASK_DEBUG_PRINT (1 << 1)
+#define DBG_ENABLE_MASK_ASSERT (1 << 2)
+#define DBG_ENABLE_MASK_DUMP_SKB_RX (1 << 8)
+#define DBG_ENABLE_MASK_DUMP_SKB_TX (1 << 9)
+#define DBG_ENABLE_MASK_DUMP_QOS (1 << 10)
+#define DBG_ENABLE_MASK_DUMP_INIT (1 << 11)
+#define DBG_ENABLE_MASK_MAC_SWAP (1 << 12)
+#define DBG_ENABLE_MASK_ALL (DBG_ENABLE_MASK_ERR | DBG_ENABLE_MASK_DEBUG_PRINT | DBG_ENABLE_MASK_ASSERT | DBG_ENABLE_MASK_DUMP_SKB_RX | DBG_ENABLE_MASK_DUMP_SKB_TX | DBG_ENABLE_MASK_DUMP_QOS | DBG_ENABLE_MASK_DUMP_INIT | DBG_ENABLE_MASK_MAC_SWAP)
+
+#define err(format, arg...) do { if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_ERR) ) printk(KERN_ERR __FILE__ ":%d:%s: " format "\n", __LINE__, __FUNCTION__, ##arg); } while ( 0 )
+
+#if defined(ENABLE_DEBUG) && ENABLE_DEBUG
+ #undef dbg
+ #define dbg(format, arg...) do { if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DEBUG_PRINT) ) printk(KERN_WARNING __FILE__ ":%d:%s: " format "\n", __LINE__, __FUNCTION__, ##arg); } while ( 0 )
+#else
+ #if !defined(dbg)
+ #define dbg(format, arg...)
+ #endif
+#endif
+
+#if defined(ENABLE_ASSERT) && ENABLE_ASSERT
+ #define ASSERT(cond, format, arg...) do { if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_ASSERT) && !(cond) ) printk(KERN_ERR __FILE__ ":%d:%s: " format "\n", __LINE__, __FUNCTION__, ##arg); } while ( 0 )
+#else
+ #define ASSERT(cond, format, arg...)
+#endif
+
+
+/*
+ * Constants
+ */
+#define DEFAULT_TX_LINK_RATE 3200 // in cells
+
+/*
+ * ATM Port, QSB Queue, DMA RX/TX Channel Parameters
+ */
+#define ATM_PORT_NUMBER 2
+#define MAX_QUEUE_NUMBER 16
+#define OAM_RX_QUEUE 15
+#define QSB_RESERVE_TX_QUEUE 0
+#define FIRST_QSB_QID 1
+#define MAX_PVC_NUMBER (MAX_QUEUE_NUMBER - FIRST_QSB_QID)
+#define MAX_RX_DMA_CHANNEL_NUMBER 8
+#define MAX_TX_DMA_CHANNEL_NUMBER 16
+#define DATA_BUFFER_ALIGNMENT EMA_ALIGNMENT
+#define DESC_ALIGNMENT 8
+#define DEFAULT_RX_HUNT_BITTH 4
+
+/*
+ * RX DMA Channel Allocation
+ */
+#define RX_DMA_CH_OAM 0
+#define RX_DMA_CH_AAL 1
+#define RX_DMA_CH_TOTAL 2
+#define RX_DMA_CH_OAM_DESC_LEN 32
+#define RX_DMA_CH_OAM_BUF_SIZE (CELL_SIZE & ~15)
+#define RX_DMA_CH_AAL_BUF_SIZE (2048 - 48)
+
+/*
+ * OAM Constants
+ */
+#define OAM_HTU_ENTRY_NUMBER 3
+#define OAM_F4_SEG_HTU_ENTRY 0
+#define OAM_F4_TOT_HTU_ENTRY 1
+#define OAM_F5_HTU_ENTRY 2
+#define OAM_F4_CELL_ID 0
+#define OAM_F5_CELL_ID 15
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ #undef OAM_HTU_ENTRY_NUMBER
+ #define OAM_HTU_ENTRY_NUMBER 4
+ #define OAM_ARQ_HTU_ENTRY 3
+#endif
+
+/*
+ * RX Frame Definitions
+ */
+#define MAX_RX_PACKET_ALIGN_BYTES 3
+#define MAX_RX_PACKET_PADDING_BYTES 3
+#define RX_INBAND_TRAILER_LENGTH 8
+#define MAX_RX_FRAME_EXTRA_BYTES (RX_INBAND_TRAILER_LENGTH + MAX_RX_PACKET_ALIGN_BYTES + MAX_RX_PACKET_PADDING_BYTES)
+
+/*
+ * TX Frame Definitions
+ */
+#define MAX_TX_HEADER_ALIGN_BYTES 12
+#define MAX_TX_PACKET_ALIGN_BYTES 3
+#define MAX_TX_PACKET_PADDING_BYTES 3
+#define TX_INBAND_HEADER_LENGTH 8
+#define MAX_TX_FRAME_EXTRA_BYTES (TX_INBAND_HEADER_LENGTH + MAX_TX_HEADER_ALIGN_BYTES + MAX_TX_PACKET_ALIGN_BYTES + MAX_TX_PACKET_PADDING_BYTES)
+
+/*
+ * Cell Constant
+ */
+#define CELL_SIZE ATM_AAL0_SDU
+
+/*
+ * ReTX Constant
+ */
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ #define RETX_PLAYOUT_BUFFER_ORDER 6
+ #define RETX_PLAYOUT_BUFFER_SIZE (PAGE_SIZE * (1 << RETX_PLAYOUT_BUFFER_ORDER))
+ #define RETX_PLAYOUT_FW_BUFF_SIZE (RETX_PLAYOUT_BUFFER_SIZE / (32 * 56 /* cell size */))
+ #define RETX_POLLING_INTERVAL (HZ / 100 > 0 ? HZ / 100 : 1)
+#endif
+
+
+
+/*
+ * ####################################
+ * Data Type
+ * ####################################
+ */
+
+typedef struct {
+ unsigned int h;
+ unsigned int l;
+} ppe_u64_t;
+
+struct port {
+ unsigned int tx_max_cell_rate;
+ unsigned int tx_current_cell_rate;
+
+ struct atm_dev *dev;
+};
+
+struct connection {
+ struct atm_vcc *vcc;
+
+ volatile struct tx_descriptor
+ *tx_desc;
+ unsigned int tx_desc_pos;
+ struct sk_buff **tx_skb;
+
+ unsigned int aal5_vcc_crc_err; /* number of packets with CRC error */
+ unsigned int aal5_vcc_oversize_sdu; /* number of packets with oversize error */
+
+ unsigned int port;
+};
+
+struct atm_priv_data {
+ unsigned long conn_table;
+ struct connection conn[MAX_PVC_NUMBER];
+
+ volatile struct rx_descriptor
+ *aal_desc;
+ unsigned int aal_desc_pos;
+
+ volatile struct rx_descriptor
+ *oam_desc;
+ unsigned char *oam_buf;
+ unsigned int oam_desc_pos;
+
+ struct port port[ATM_PORT_NUMBER];
+
+ unsigned int wrx_pdu; /* successfully received AAL5 packet */
+ unsigned int wrx_drop_pdu; /* AAL5 packet dropped by driver on RX */
+ unsigned int wtx_pdu; /* successfully tranmitted AAL5 packet */
+ unsigned int wtx_err_pdu; /* error AAL5 packet */
+ unsigned int wtx_drop_pdu; /* AAL5 packet dropped by driver on TX */
+
+ ppe_u64_t wrx_total_byte;
+ ppe_u64_t wtx_total_byte;
+ unsigned int prev_wrx_total_byte;
+ unsigned int prev_wtx_total_byte;
+
+ void *aal_desc_base;
+ void *oam_desc_base;
+ void *oam_buf_base;
+ void *tx_desc_base;
+ void *tx_skb_base;
+};
+
+
+
+/*
+ * ####################################
+ * Declaration
+ * ####################################
+ */
+
+extern unsigned int ifx_atm_dbg_enable;
+
+extern void ifx_atm_get_fw_ver(unsigned int *major, unsigned int *minor);
+
+extern void ifx_atm_init_chip(void);
+extern void ifx_atm_uninit_chip(void);
+
+extern int ifx_pp32_start(int pp32);
+extern void ifx_pp32_stop(int pp32);
+
+extern void ifx_reset_ppe(void);
+
+
+
+#endif // IFXMIPS_ATM_CORE_H
diff --git a/package/ltq-dsl/src/ifxmips_atm_danube.c b/package/ltq-dsl/src/ifxmips_atm_danube.c
new file mode 100644
index 000000000..64698b879
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_danube.c
@@ -0,0 +1,326 @@
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_danube.c
+** PROJECT : UEIP
+** MODULES : ATM
+**
+** DATE : 7 Jul 2009
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM driver common source file (core functions)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 07 JUL 2009 Xu Liang Init Version
+*******************************************************************************/
+
+
+
+/*
+ * ####################################
+ * Head File
+ * ####################################
+ */
+
+/*
+ * Common Head File
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/clk.h>
+#include <asm/delay.h>
+
+/*
+ * Chip Specific Head File
+ */
+#include <lantiq_soc.h>
+#include "ifxmips_compat.h"
+#include "ifxmips_atm_core.h"
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ #include "ifxmips_atm_fw_danube_retx.h"
+#else
+ #include "ifxmips_atm_fw_danube.h"
+#endif
+
+/*
+ * ####################################
+ * Definition
+ * ####################################
+ */
+
+/*
+ * EMA Settings
+ */
+#define EMA_CMD_BUF_LEN 0x0040
+#define EMA_CMD_BASE_ADDR (0x00001580 << 2)
+#define EMA_DATA_BUF_LEN 0x0100
+#define EMA_DATA_BASE_ADDR (0x00001900 << 2)
+#define EMA_WRITE_BURST 0x2
+#define EMA_READ_BURST 0x2
+
+
+
+/*
+ * ####################################
+ * Declaration
+ * ####################################
+ */
+
+/*
+ * Hardware Init/Uninit Functions
+ */
+static inline void init_pmu(void);
+static inline void uninit_pmu(void);
+static inline void reset_ppe(void);
+static inline void init_ema(void);
+static inline void init_mailbox(void);
+static inline void init_atm_tc(void);
+static inline void clear_share_buffer(void);
+
+
+
+/*
+ * ####################################
+ * Local Variable
+ * ####################################
+ */
+
+
+
+/*
+ * ####################################
+ * Local Function
+ * ####################################
+ */
+
+static inline void init_pmu(void)
+{
+ //*(unsigned long *)0xBF10201C &= ~((1 << 15) | (1 << 13) | (1 << 9));
+ //PPE_TOP_PMU_SETUP(IFX_PMU_ENABLE);
+/* PPE_SLL01_PMU_SETUP(IFX_PMU_ENABLE);
+ PPE_TC_PMU_SETUP(IFX_PMU_ENABLE);
+ PPE_EMA_PMU_SETUP(IFX_PMU_ENABLE);
+ PPE_QSB_PMU_SETUP(IFX_PMU_ENABLE);
+ PPE_TPE_PMU_SETUP(IFX_PMU_ENABLE);
+ DSL_DFE_PMU_SETUP(IFX_PMU_ENABLE);*/
+ struct clk *clk = clk_get_sys("ltq_dsl", NULL);
+ clk_enable(clk);
+}
+
+static inline void uninit_pmu(void)
+{
+/* PPE_SLL01_PMU_SETUP(IFX_PMU_DISABLE);
+ PPE_TC_PMU_SETUP(IFX_PMU_DISABLE);
+ PPE_EMA_PMU_SETUP(IFX_PMU_DISABLE);
+ PPE_QSB_PMU_SETUP(IFX_PMU_DISABLE);
+ PPE_TPE_PMU_SETUP(IFX_PMU_DISABLE);
+ DSL_DFE_PMU_SETUP(IFX_PMU_DISABLE);*/
+ //PPE_TOP_PMU_SETUP(IFX_PMU_DISABLE);
+ struct clk *clk = clk_get_sys("ltq_dsl", NULL);
+ clk_disable(clk);
+}
+
+static inline void reset_ppe(void)
+{
+#if 0 //def MODULE
+ unsigned int etop_cfg;
+ unsigned int etop_mdio_cfg;
+ unsigned int etop_ig_plen_ctrl;
+ unsigned int enet_mac_cfg;
+
+ etop_cfg = *IFX_PP32_ETOP_CFG;
+ etop_mdio_cfg = *IFX_PP32_ETOP_MDIO_CFG;
+ etop_ig_plen_ctrl = *IFX_PP32_ETOP_IG_PLEN_CTRL;
+ enet_mac_cfg = *IFX_PP32_ENET_MAC_CFG;
+
+ *IFX_PP32_ETOP_CFG &= ~0x03C0;
+
+ // reset PPE
+ ifx_rcu_rst(IFX_RCU_DOMAIN_PPE, IFX_RCU_MODULE_ATM);
+
+ *IFX_PP32_ETOP_MDIO_CFG = etop_mdio_cfg;
+ *IFX_PP32_ETOP_IG_PLEN_CTRL = etop_ig_plen_ctrl;
+ *IFX_PP32_ENET_MAC_CFG = enet_mac_cfg;
+ *IFX_PP32_ETOP_CFG = etop_cfg;
+#endif
+}
+
+static inline void init_ema(void)
+{
+ IFX_REG_W32((EMA_CMD_BUF_LEN << 16) | (EMA_CMD_BASE_ADDR >> 2), EMA_CMDCFG);
+ IFX_REG_W32((EMA_DATA_BUF_LEN << 16) | (EMA_DATA_BASE_ADDR >> 2), EMA_DATACFG);
+ IFX_REG_W32(0x000000FF, EMA_IER);
+ IFX_REG_W32(EMA_READ_BURST | (EMA_WRITE_BURST << 2), EMA_CFG);
+}
+
+static inline void init_mailbox(void)
+{
+ IFX_REG_W32(0xFFFFFFFF, MBOX_IGU1_ISRC);
+ IFX_REG_W32(0x00000000, MBOX_IGU1_IER);
+ IFX_REG_W32(0xFFFFFFFF, MBOX_IGU3_ISRC);
+ IFX_REG_W32(0x00000000, MBOX_IGU3_IER);
+}
+
+static inline void init_atm_tc(void)
+{
+ IFX_REG_W32(0x0000, DREG_AT_CTRL);
+ IFX_REG_W32(0x0000, DREG_AR_CTRL);
+ IFX_REG_W32(0x0, DREG_AT_IDLE0);
+ IFX_REG_W32(0x0, DREG_AT_IDLE1);
+ IFX_REG_W32(0x0, DREG_AR_IDLE0);
+ IFX_REG_W32(0x0, DREG_AR_IDLE1);
+ IFX_REG_W32(0x40, RFBI_CFG);
+ IFX_REG_W32(0x1600, SFSM_DBA0);
+ IFX_REG_W32(0x1718, SFSM_DBA1);
+ IFX_REG_W32(0x1830, SFSM_CBA0);
+ IFX_REG_W32(0x1844, SFSM_CBA1);
+ IFX_REG_W32(0x14014, SFSM_CFG0);
+ IFX_REG_W32(0x14014, SFSM_CFG1);
+ IFX_REG_W32(0x1858, FFSM_DBA0);
+ IFX_REG_W32(0x18AC, FFSM_DBA1);
+ IFX_REG_W32(0x10006, FFSM_CFG0);
+ IFX_REG_W32(0x10006, FFSM_CFG1);
+ IFX_REG_W32(0x00000001, FFSM_IDLE_HEAD_BC0);
+ IFX_REG_W32(0x00000001, FFSM_IDLE_HEAD_BC1);
+}
+
+static inline void clear_share_buffer(void)
+{
+ volatile u32 *p = SB_RAM0_ADDR(0);
+ unsigned int i;
+
+ for ( i = 0; i < SB_RAM0_DWLEN + SB_RAM1_DWLEN + SB_RAM2_DWLEN + SB_RAM3_DWLEN; i++ )
+ IFX_REG_W32(0, p++);
+}
+
+/*
+ * Description:
+ * Download PPE firmware binary code.
+ * Input:
+ * src --- u32 *, binary code buffer
+ * dword_len --- unsigned int, binary code length in DWORD (32-bit)
+ * Output:
+ * int --- IFX_SUCCESS: Success
+ * else: Error Code
+ */
+static inline int pp32_download_code(u32 *code_src, unsigned int code_dword_len, u32 *data_src, unsigned int data_dword_len)
+{
+ volatile u32 *dest;
+
+ if ( code_src == 0 || ((unsigned long)code_src & 0x03) != 0
+ || data_src == 0 || ((unsigned long)data_src & 0x03) != 0 )
+ return IFX_ERROR;
+
+ if ( code_dword_len <= CDM_CODE_MEMORYn_DWLEN(0) )
+ IFX_REG_W32(0x00, CDM_CFG);
+ else
+ IFX_REG_W32(0x04, CDM_CFG);
+
+ /* copy code */
+ dest = CDM_CODE_MEMORY(0, 0);
+ while ( code_dword_len-- > 0 )
+ IFX_REG_W32(*code_src++, dest++);
+
+ /* copy data */
+ dest = CDM_DATA_MEMORY(0, 0);
+ while ( data_dword_len-- > 0 )
+ IFX_REG_W32(*data_src++, dest++);
+
+ return IFX_SUCCESS;
+}
+
+
+
+/*
+ * ####################################
+ * Global Function
+ * ####################################
+ */
+
+extern void ifx_atm_get_fw_ver(unsigned int *major, unsigned int *minor)
+{
+ ASSERT(major != NULL, "pointer is NULL");
+ ASSERT(minor != NULL, "pointer is NULL");
+
+#if (defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX) || defined(VER_IN_FIRMWARE)
+ *major = FW_VER_ID->major;
+ *minor = FW_VER_ID->minor;
+#else
+ *major = ATM_FW_VER_MAJOR;
+ *minor = ATM_FW_VER_MINOR;
+#endif
+}
+
+void ifx_atm_init_chip(void)
+{
+ init_pmu();
+
+ reset_ppe();
+
+ init_ema();
+
+ init_mailbox();
+
+ init_atm_tc();
+
+ clear_share_buffer();
+}
+
+void ifx_atm_uninit_chip(void)
+{
+ uninit_pmu();
+}
+
+/*
+ * Description:
+ * Initialize and start up PP32.
+ * Input:
+ * none
+ * Output:
+ * int --- IFX_SUCCESS: Success
+ * else: Error Code
+ */
+int ifx_pp32_start(int pp32)
+{
+ int ret;
+
+ /* download firmware */
+ ret = pp32_download_code(firmware_binary_code, sizeof(firmware_binary_code) / sizeof(*firmware_binary_code), firmware_binary_data, sizeof(firmware_binary_data) / sizeof(*firmware_binary_data));
+ if ( ret != IFX_SUCCESS )
+ return ret;
+
+ /* run PP32 */
+ IFX_REG_W32(DBG_CTRL_START_SET(1), PP32_DBG_CTRL);
+
+ /* idle for a while to let PP32 init itself */
+ udelay(10);
+
+ return IFX_SUCCESS;
+}
+
+/*
+ * Description:
+ * Halt PP32.
+ * Input:
+ * none
+ * Output:
+ * none
+ */
+void ifx_pp32_stop(int pp32)
+{
+ /* halt PP32 */
+ IFX_REG_W32(DBG_CTRL_STOP_SET(1), PP32_DBG_CTRL);
+}
diff --git a/package/ltq-dsl/src/ifxmips_atm_fw_amazon_se.h b/package/ltq-dsl/src/ifxmips_atm_fw_amazon_se.h
new file mode 100644
index 000000000..4daef9fd8
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_fw_amazon_se.h
@@ -0,0 +1,3335 @@
+#ifndef IFXMIPS_ATM_FW_AMAZON_SE_H
+#define IFXMIPS_ATM_FW_AMAZON_SE_H
+
+
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_fw_amazon_se.h
+** PROJECT : UEIP
+** MODULES : ATM (ADSL)
+**
+** DATE : 1 AUG 2005
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM Driver (PP32 Firmware)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 4 AUG 2005 Xu Liang Initiate Version
+** 23 OCT 2006 Xu Liang Add GPL header.
+** 9 JAN 2007 Xu Liang First version got from Anand (IC designer)
+*******************************************************************************/
+
+
+#define ATM_FW_VER_MAJOR 0
+#define ATM_FW_VER_MINOR 1
+
+
+static unsigned int firmware_binary_code[] = {
+0x80000ac0,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x8000ffe0,
+0x00000000,
+0x00000000,
+0x00000000,
+0xc1000002,
+0xd90c00f8,
+0xc2000002,
+0xda0800f9,
+0x80004d48,
+0xc2000000,
+0xda0800f9,
+0x800043b8,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x80004370,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x80005550,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x80004270,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0xc0400000,
+0xc0004840,
+0xc88400f8,
+0x80004a08,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0xc0400002,
+0xc0004840,
+0xc88400f8,
+0x80004988,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0xc3c00004,
+0xdbc800f9,
+0xc10c0002,
+0xd90c00f8,
+0x8000fee0,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0xc10e0002,
+0xd90c00f8,
+0xc0004808,
+0xc84000f8,
+0x800049b8,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x80003ff0,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x80003f70,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x80003ef0,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x80003e70,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x80003df0,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x80003d70,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x80003cf0,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x80003c70,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x80003bf0,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x80003b70,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x80003af0,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0xc0000000,
+0xc1260002,
+0xd90c00f8,
+0xc2801af0,
+0xc201757c,
+0xc2417dde,
+0x00000000,
+0x00000000,
+0xce2800f8,
+0x00000000,
+0x5aa80002,
+0x00000000,
+0xce6800f8,
+0x00000000,
+0x80003a00,
+0x00000000,
+0x00000000,
+0xc3e1fffe,
+0x597dffee,
+0x593dfe14,
+0x90000ae1,
+0x00000000,
+0x00000000,
+0x00000000,
+0x90cc0a89,
+0x00000000,
+0x00000000,
+0x00000000,
+0xc3c00000,
+0xdbc800f9,
+0xc1400008,
+0xc1900000,
+0x71588000,
+0x14100100,
+0xc140000a,
+0xc1900002,
+0x71588000,
+0x14100100,
+0xc140000c,
+0xc1900004,
+0x71588000,
+0x14100100,
+0xc1400004,
+0xc1900006,
+0x71588000,
+0x14100100,
+0xc1400006,
+0xc1900008,
+0x71588000,
+0x14100100,
+0xc140000e,
+0xc190000a,
+0x71588000,
+0x14100100,
+0xc1400000,
+0xc190000c,
+0x71588000,
+0x14100100,
+0xc1400002,
+0xc190000e,
+0x71588000,
+0x14100100,
+0xc0400000,
+0xc11c0000,
+0xc000082c,
+0xcd05ce00,
+0xc11c0002,
+0xc000082c,
+0xcd05ce00,
+0xc0400002,
+0xc11c0000,
+0xc000082c,
+0xcd05ce00,
+0xc11c0002,
+0xc000082c,
+0xcd05ce00,
+0xc0000824,
+0x00000000,
+0xcbc000f9,
+0xcb8000f9,
+0xcb4000f9,
+0xcb0000f8,
+0xc0004878,
+0x5bfc4000,
+0xcfc000f9,
+0x5bb84000,
+0xcf8000f9,
+0x5b744000,
+0xcf4000f9,
+0x5b304000,
+0xcf0000f8,
+0xc0000a10,
+0x00000000,
+0xcbc000f9,
+0xcb8000f8,
+0xc0004874,
+0x5bfc4000,
+0xcfc000f9,
+0x5bb84000,
+0xcf8000f8,
+0xc30001fe,
+0xc000140a,
+0xcf0000f8,
+0xc3000000,
+0x7f018000,
+0xc000042e,
+0xcf0000f8,
+0xc000040e,
+0xcf0000f8,
+0xc3c1fffe,
+0xc000490e,
+0xcfc00078,
+0xc000492c,
+0xcfc00078,
+0xc0004924,
+0xcfc00038,
+0xc0004912,
+0xcfc00038,
+0xc0004966,
+0xcfc00038,
+0xc0004968,
+0xcfc00078,
+0xc000496a,
+0xcfc00078,
+0xc3c00000,
+0xc2800020,
+0xc3000000,
+0x7f018000,
+0x6ff88000,
+0x6fd44000,
+0x4395c000,
+0x5bb84a00,
+0x5838000a,
+0xcf0000f8,
+0x5bfc0002,
+0xb7e8ffc8,
+0x00000000,
+0xc3c00000,
+0xc2800010,
+0x6ff86000,
+0x47bdc000,
+0x5bb84c80,
+0xc3400000,
+0x58380004,
+0xcb420078,
+0x00000000,
+0x58380008,
+0xcf400078,
+0x5bfc0002,
+0xb7e8ffb0,
+0x00000000,
+0xc3c00000,
+0xc2800020,
+0xc348001e,
+0xc3000000,
+0x7f018000,
+0x6ff8a000,
+0x6fd44000,
+0x4795c000,
+0x47bdc000,
+0x5bb85e00,
+0x58380008,
+0xcf408418,
+0x5838000a,
+0xcf0000f8,
+0x5bfc0002,
+0xb7e8ffb0,
+0x00000000,
+0x00000000,
+0x00000000,
+0xc121ffee,
+0x5911fe14,
+0x14100000,
+0x80000530,
+0x00000000,
+0x80002130,
+0x00000000,
+0x8000ffe0,
+0xc0004958,
+0xc84000f8,
+0x00000000,
+0xc3c00002,
+0x787c2000,
+0xcc4000f8,
+0xc0004848,
+0xcb8400f8,
+0xc000495c,
+0xcac400f8,
+0xc0004844,
+0xc88400f8,
+0x47ad0000,
+0x8400ff82,
+0xc000487c,
+0xc80400f8,
+0x00000000,
+0x00000000,
+0x40080000,
+0xca0000f8,
+0xc0001624,
+0xcb0400f8,
+0xa63c007a,
+0x00000000,
+0x00000000,
+0xa71eff22,
+0x00000000,
+0xc0000824,
+0xca8400f8,
+0x6ca08000,
+0x6ca42000,
+0x46250000,
+0x42290000,
+0xc35e0002,
+0xc6340060,
+0xc0001624,
+0xcf440078,
+0xc2000000,
+0xc161fffe,
+0x5955fffe,
+0x14140000,
+0x00000000,
+0xc0004844,
+0xc88400f8,
+0xc000082c,
+0xca040038,
+0x00000000,
+0x00000000,
+0x58880002,
+0xb6080018,
+0x00000000,
+0xc0800000,
+0xc0004844,
+0xcc840038,
+0x5aec0002,
+0xc000495c,
+0xcec400f8,
+0x5e6c0006,
+0x84000060,
+0xc0004848,
+0xcb8400f8,
+0xc0000838,
+0xc2500002,
+0xce450800,
+0x5fb80002,
+0xc0004848,
+0xcf8400f8,
+0x5eec0002,
+0xc000495c,
+0xcec400f8,
+0x00000000,
+0xc121ffee,
+0x5911fe14,
+0x14100000,
+0x8000fd98,
+0xc000495a,
+0xc84000f8,
+0x00000000,
+0xc3c00002,
+0x787c2000,
+0xcc4000f8,
+0xc0004960,
+0xcac400f8,
+0x00000000,
+0x00000000,
+0x5eec0000,
+0x8400010a,
+0x00000000,
+0xb6fc0050,
+0xc0001600,
+0xca0400f8,
+0x00000000,
+0x00000000,
+0xa61e00d2,
+0x6fe90000,
+0xc0000a28,
+0xce850800,
+0xc2c00000,
+0xc2800004,
+0xb6e800a0,
+0xc0001604,
+0xca8400f8,
+0xc0004960,
+0xcec400f8,
+0xa69efcc2,
+0x00000000,
+0x6fe90000,
+0xc0000a28,
+0xce850800,
+0xc2c00002,
+0xc0001600,
+0xca0400f8,
+0x00000000,
+0x00000000,
+0xa61e002a,
+0x6fe90000,
+0xc0000a28,
+0xce850800,
+0xc2c00000,
+0xc0001604,
+0xca8400f8,
+0xc0004960,
+0xcec400f8,
+0xa69efc2a,
+0xc2400000,
+0xc0000a14,
+0xca440028,
+0x00000000,
+0x00000000,
+0x466d2000,
+0xa4400020,
+0xc2800000,
+0xdfeb0029,
+0x80000010,
+0xdfea0029,
+0xb668fba2,
+0x00000000,
+0xc00048a0,
+0xcb0400f8,
+0xc0000a10,
+0xca8400f8,
+0x6f208000,
+0x6f242000,
+0x46250000,
+0x42a10000,
+0xc2400000,
+0xc0000a14,
+0xca440028,
+0xc35e0002,
+0xc6340060,
+0xc0001604,
+0xcf440078,
+0x5b300002,
+0xb6700018,
+0x5aec0002,
+0xc3000000,
+0xc00048a0,
+0xcf0400f8,
+0xc0004960,
+0xcec400f8,
+0x8000fad8,
+0xc0004918,
+0xd28000f8,
+0xc2000000,
+0xdf600038,
+0x5e600080,
+0x84000272,
+0x00000000,
+0xc161fffe,
+0x5955fffe,
+0x14140000,
+0x00000000,
+0xc000480a,
+0xca0000f8,
+0xc0004912,
+0xca4000f8,
+0xc0004924,
+0xca8000f8,
+0xc0004966,
+0xcac000f8,
+0x00000000,
+0xc121ffee,
+0x5911fe14,
+0x14100000,
+0x76250000,
+0x76290000,
+0x762d0000,
+0x840001ca,
+0xc0004918,
+0xca4000f8,
+0xc28001fe,
+0x76290000,
+0x5a640002,
+0x6a254010,
+0x5ee80000,
+0x8400001a,
+0x6aa54000,
+0x80000010,
+0xc62800f8,
+0x62818008,
+0xc0004918,
+0xcf0000f8,
+0xc161fffe,
+0x5955fffe,
+0x14140000,
+0x00000000,
+0xc0004966,
+0xca4000f8,
+0xc2000002,
+0x6a310000,
+0x7e010000,
+0x76612000,
+0xce4000f8,
+0x00000000,
+0xc121ffee,
+0x5911fe14,
+0x14100000,
+0x6f346000,
+0x4771a000,
+0x5b744c80,
+0xc2800000,
+0x58340006,
+0xca800078,
+0xc2c00000,
+0x58340000,
+0xcac000d8,
+0xc2400000,
+0x5834000a,
+0xca420078,
+0x6ea82000,
+0x42e9e000,
+0x6f2ca000,
+0x42e56000,
+0x5aec1400,
+0xc3990040,
+0xc7381c18,
+0xc6f80060,
+0x99005f50,
+0xdb9800f8,
+0xdbd800f9,
+0x00000000,
+0xdea000f8,
+0x46310000,
+0x8400fd80,
+0xc0004958,
+0xc84000f8,
+0x00000000,
+0xc3c00002,
+0x787c2000,
+0xcc4000f8,
+0xc0004848,
+0xcb8400f8,
+0xc0004844,
+0xc88400f8,
+0x5fb80000,
+0x8400f7f2,
+0xc0001a1c,
+0xca0000f8,
+0xc2400002,
+0x6a452000,
+0x76250000,
+0x8400f7c2,
+0xc000487c,
+0xc80400f8,
+0x00000000,
+0x00000000,
+0x40080000,
+0xca0000f8,
+0xc42400f8,
+0x00000000,
+0xa63c17da,
+0x00000000,
+0xc0004878,
+0xc80400f8,
+0x6c908000,
+0x45088000,
+0x45088000,
+0x40100000,
+0xca0000f8,
+0xc42400f8,
+0x00000000,
+0xc0004934,
+0xce0000f8,
+0xc2800002,
+0xc4681c08,
+0xc62821d0,
+0xc2600010,
+0x5a652440,
+0xc0004800,
+0xcb4000f8,
+0xc2200400,
+0x5a202400,
+0xc7601040,
+0xc0001220,
+0xce8000f8,
+0xc0001200,
+0xce4000f8,
+0xc0001202,
+0xce0000f8,
+0xc0001240,
+0xcb4000f8,
+0x00000000,
+0x00000000,
+0xa754ffe0,
+0xc2000000,
+0xc7600040,
+0xa7520042,
+0x00000000,
+0x00000000,
+0x990066c8,
+0xc0004822,
+0xc94000f8,
+0xc1800002,
+0x80001680,
+0x58206480,
+0xc2000000,
+0xca000018,
+0xc2400000,
+0xca414000,
+0xc2800000,
+0xca812000,
+0xc2c00000,
+0xcac20018,
+0xc0004938,
+0xce0000f8,
+0xc0004920,
+0xce4000f8,
+0xc0004916,
+0xce8000f8,
+0xc0004922,
+0xcec000f8,
+0xa6400540,
+0x00000000,
+0xc0004938,
+0xcbc000f8,
+0x00000000,
+0xc3800000,
+0x6ff48000,
+0x6fd44000,
+0x4355a000,
+0x5b744a00,
+0x58340000,
+0xcb802010,
+0x00000000,
+0xc2000000,
+0x6fb46000,
+0x4779a000,
+0x5b744c80,
+0x5834000c,
+0xca000020,
+0xc000491a,
+0xcf8000f8,
+0x5e200000,
+0x8400046a,
+0xc2000000,
+0xdf610048,
+0x5e6001e8,
+0x8800ffe8,
+0xc2000002,
+0xc2400466,
+0xc2a00000,
+0x5aa80000,
+0xc0001006,
+0xce0000f8,
+0xc0001008,
+0xce4000f8,
+0xc000100a,
+0xce8000f8,
+0x99005990,
+0xc1a0fffe,
+0xc0000824,
+0xc9840060,
+0xc0004934,
+0xca4000f8,
+0xc2000000,
+0xc2800002,
+0x990059d0,
+0xda9800f8,
+0xc61400f8,
+0xc65800f8,
+0xc161fffe,
+0x5955fffe,
+0x14140000,
+0x00000000,
+0x99005ab8,
+0xc000491a,
+0xc94000f8,
+0x00000000,
+0x00000000,
+0xc121ffee,
+0x5911fe14,
+0x14100000,
+0xc0004922,
+0xca001118,
+0xc3c00000,
+0xc3800000,
+0xc0004930,
+0xce023118,
+0xc0004932,
+0xcbc000d8,
+0xc2800000,
+0xc000491e,
+0xcfc000f8,
+0xc0004862,
+0xca800060,
+0xc3a0001a,
+0x5bb94000,
+0xc6b80060,
+0xc000491c,
+0xcf8000f8,
+0x99005d28,
+0xc000491c,
+0xc1400000,
+0xc9420048,
+0x00000000,
+0x00000000,
+0x00000000,
+0xa8e2ffe8,
+0xc2000000,
+0xc1220002,
+0xd90c00f8,
+0xdf600038,
+0x5e600080,
+0x8400fff2,
+0xc000491c,
+0xca0000f8,
+0xc000491e,
+0xca4000f8,
+0x00000000,
+0x00000000,
+0x99005f50,
+0xda1800f8,
+0xda5800f9,
+0x00000000,
+0xc2000000,
+0xdf610048,
+0x5e6001fe,
+0x8800ffe8,
+0xc0004916,
+0xca8000f8,
+0xc2c00000,
+0xdfec0048,
+0xc2400000,
+0x466d2000,
+0x8400004a,
+0x5ea80000,
+0x8400003a,
+0xc2600002,
+0x990066c8,
+0xc000482e,
+0xc94000f8,
+0xc1800002,
+0x80000030,
+0xc2600000,
+0x990066c8,
+0xc000482c,
+0xc94000f8,
+0xc1800002,
+0xc2000068,
+0xc6240078,
+0xc0004930,
+0xce400080,
+0xc000491a,
+0xc98000f8,
+0xc0004862,
+0xc94000f8,
+0x6d9c6000,
+0x45d8e000,
+0x59dc4c80,
+0x99005db0,
+0xd95800f8,
+0xd99800f9,
+0xd9d400f8,
+0x99005d28,
+0xc000491c,
+0xc1400000,
+0xc9420048,
+0xc2000000,
+0xdf600038,
+0x5e600080,
+0x8400ffea,
+0x00000000,
+0xc000491c,
+0xca0000f8,
+0xc000491e,
+0xca4000f8,
+0x00000000,
+0x00000000,
+0x99005f50,
+0xda1800f8,
+0xda5800f9,
+0x00000000,
+0x800010e8,
+0x00000000,
+0x990066c8,
+0xc000482a,
+0xc94000f8,
+0xc1800002,
+0x800010b8,
+0xc0004938,
+0xcbc000f8,
+0x00000000,
+0x00000000,
+0x6ff88000,
+0x6fd44000,
+0x4395c000,
+0x5bb84a00,
+0x58380008,
+0xca0000f8,
+0x00000000,
+0x00000000,
+0xa6000382,
+0x00000000,
+0xc0004938,
+0xcbc000f8,
+0xc3000000,
+0x00000000,
+0x6ff88000,
+0x6fd44000,
+0x4395c000,
+0x5bb84a00,
+0x58380000,
+0xcb002010,
+0xc2000000,
+0x58380008,
+0xca020078,
+0x5838000c,
+0xcac000f8,
+0x5838000e,
+0xca4000f8,
+0xc000491a,
+0xcf0000f8,
+0xc0004930,
+0xcec000f8,
+0xc000493c,
+0xce0000f8,
+0xc0004932,
+0xce4000f8,
+0x5e200000,
+0x84000120,
+0xc2800000,
+0xa6fe00ba,
+0x6f206000,
+0x46310000,
+0x5a204c80,
+0x5820000c,
+0xca800020,
+0x00000000,
+0x00000000,
+0x5ea80000,
+0x840001f2,
+0x00000000,
+0xc161fffe,
+0x5955fffe,
+0x14140000,
+0x00000000,
+0x99005ab8,
+0xc000491a,
+0xc94000f8,
+0x00000000,
+0x00000000,
+0xc121ffee,
+0x5911fe14,
+0x14100000,
+0xc0004930,
+0xcac000f8,
+0xc0004932,
+0xca4000f8,
+0xc7ec1118,
+0xc0004930,
+0xcec000f8,
+0x5838000c,
+0xcec000f8,
+0x58000002,
+0xce4000f8,
+0xc0004934,
+0xca0000f8,
+0xc2400002,
+0x6e642000,
+0x6e642000,
+0x76612000,
+0x8400002a,
+0xc2400002,
+0x6e684000,
+0x58380008,
+0xce804200,
+0xa6000020,
+0x6e682000,
+0x58380008,
+0xce802100,
+0xc2400002,
+0x6e642000,
+0x76612000,
+0x840000ea,
+0x58380008,
+0xca0000f8,
+0xc2800000,
+0xc2400000,
+0xa60200c0,
+0xdba800f8,
+0x6f386000,
+0x47b1c000,
+0x5bb84c80,
+0x58380004,
+0xca400078,
+0x58380002,
+0xca800078,
+0x00000000,
+0xdeb800f8,
+0x46a54000,
+0x88000060,
+0x00000000,
+0xc0004824,
+0xca0000f8,
+0xc2400002,
+0x6e640000,
+0x5a200002,
+0xce0000f8,
+0x58380008,
+0xce400000,
+0x80000018,
+0x00000000,
+0x80000048,
+0xc0004934,
+0xca0000f8,
+0x00000000,
+0x00000000,
+0xa6020c6a,
+0x00000000,
+0x00000000,
+0x80000c98,
+0xc2800000,
+0xc2000200,
+0xc240001a,
+0xdf690048,
+0x46294000,
+0x46a54000,
+0x8800ffd2,
+0xc2000006,
+0xc2600982,
+0x5a643b6e,
+0x5838000a,
+0xca8000f8,
+0xc0001006,
+0xce0000f8,
+0xc0001008,
+0xce4000f8,
+0xc000100a,
+0xce8000f8,
+0x99005990,
+0xc1a0fffe,
+0xc0000824,
+0xc9840060,
+0xc2000000,
+0xc0004930,
+0xca02e008,
+0x58380026,
+0xca4000f8,
+0x00000000,
+0xc2800000,
+0x990059d0,
+0xda9800f8,
+0xc61400f8,
+0xc65800f8,
+0xc0004934,
+0xca0000f8,
+0x00000000,
+0x00000000,
+0xa6020022,
+0x00000000,
+0x00000000,
+0x80000318,
+0xc0004938,
+0xcbc000f8,
+0xc0004878,
+0xc80400f8,
+0x6c908000,
+0x45088000,
+0x45088000,
+0x40100000,
+0xca0000f8,
+0xc42400f8,
+0x00000000,
+0x58240018,
+0xca0000f8,
+0x6ff88000,
+0x6fd44000,
+0x4395c000,
+0x5bb84a00,
+0xc3000000,
+0xc3400002,
+0xc2c00000,
+0xc62c0078,
+0xc6270038,
+0xc0004940,
+0xce400038,
+0xc6260038,
+0xc0004942,
+0xce400038,
+0xc000493c,
+0xca0000f8,
+0x5eec0000,
+0x8400018a,
+0x5a6c0010,
+0x46254000,
+0x88000190,
+0x5a600052,
+0x46e54000,
+0x88000178,
+0x58380006,
+0xca8000f8,
+0xc0004940,
+0xca0000f8,
+0xc2400000,
+0xc6a70038,
+0x7e412000,
+0x76612000,
+0xc2000000,
+0xc6a10038,
+0x46250000,
+0x84000138,
+0xc0004942,
+0xca0000f8,
+0xc2400000,
+0xc6a60038,
+0x7e412000,
+0x76612000,
+0xc2000000,
+0xc6a00038,
+0x58380002,
+0xca8000f8,
+0x46250000,
+0x840000e8,
+0xc2400000,
+0xc6a60078,
+0x466d0000,
+0x880000da,
+0xc2400000,
+0xc6a40078,
+0x58380008,
+0xca8000f8,
+0x46e50000,
+0x880000ba,
+0x00000000,
+0xa6820018,
+0x00000000,
+0xc7700b00,
+0xa6840098,
+0x00000000,
+0xc7700a00,
+0x80000080,
+0xc7700200,
+0xc000493c,
+0xcac000f8,
+0x80000060,
+0xc7700300,
+0xc000493c,
+0xcac000f8,
+0x80000040,
+0xc7700900,
+0x80000030,
+0xc7700800,
+0x80000020,
+0xc7700700,
+0x80000010,
+0xc7700500,
+0xc0004944,
+0xcf0000f8,
+0xc000493e,
+0xcec000f8,
+0xc0004938,
+0xca4000f8,
+0xc000493c,
+0xcb8000f8,
+0xc000493e,
+0xcb4000f8,
+0xc3000000,
+0x6e608000,
+0x6e544000,
+0x42150000,
+0x5a204a00,
+0x5aa00008,
+0x58200004,
+0xcb000078,
+0xc0004934,
+0xca0000f8,
+0xc2400000,
+0xc0004930,
+0xca42e008,
+0xc3c00018,
+0xa6020098,
+0x00000000,
+0x43656000,
+0x47ad0000,
+0x88000050,
+0x46f96000,
+0x6ee04010,
+0x5be00004,
+0xc2000000,
+0xc6e00008,
+0x5e200000,
+0x84000042,
+0x5bfc0002,
+0x80000030,
+0xc3c00004,
+0x5a2c0008,
+0x47a10000,
+0x88000012,
+0x5fb80008,
+0x6fe04000,
+0x42390000,
+0x47212000,
+0x88000068,
+0xc2400000,
+0xc0004930,
+0xca42e008,
+0xc2060002,
+0xc68000f8,
+0xce006300,
+0x6fe04000,
+0x4721c000,
+0x5f700010,
+0x4765a000,
+0xc2000000,
+0xc6340008,
+0xc25a000a,
+0xc000491a,
+0xca401c18,
+0xc2800000,
+0xc0004932,
+0xca8000d8,
+0xc0004862,
+0xca400060,
+0x6fa04010,
+0x42290000,
+0xc000491e,
+0xce0000f8,
+0xc7e41048,
+0xc000491c,
+0xce4000f8,
+0x6fe04000,
+0x43a1c000,
+0xc000493c,
+0xcf8000f8,
+0xc000493e,
+0xcf4000f8,
+0xc000493a,
+0xcfc000f8,
+0x80000008,
+0x00000000,
+0x00000000,
+0x00000000,
+0xc2000000,
+0xdce000f8,
+0xa622ffd8,
+0xc1220002,
+0xd90c00f8,
+0xc0004938,
+0xcbc000f8,
+0xc0004944,
+0xcb4000f8,
+0xc0004862,
+0xcb0000f8,
+0xc0004934,
+0xca0000f8,
+0x6ff88000,
+0x6fd44000,
+0x4395c000,
+0x5bb84a00,
+0xa6020268,
+0xc2400000,
+0x58380008,
+0xca406000,
+0xdfe800f8,
+0xc2218e08,
+0x5a21baf6,
+0x46a14000,
+0x84000022,
+0xc2080002,
+0x7361a000,
+0x80000058,
+0x5e640000,
+0x84000022,
+0xc20c0002,
+0x7361a000,
+0x80000030,
+0xc2000000,
+0xc760e710,
+0xc7604218,
+0x5e200000,
+0x84000272,
+0xc2200002,
+0xc0004930,
+0xce021000,
+0x990066c8,
+0xc0004828,
+0xc94000f8,
+0xc1800002,
+0x58380000,
+0xca0000f8,
+0x00000000,
+0x00000000,
+0xa6000132,
+0xc0004940,
+0xca8000f8,
+0xc0004942,
+0xca4000f8,
+0xc7600078,
+0xc6a01838,
+0xc6601038,
+0xc000493a,
+0xca4000f8,
+0xc0004934,
+0xca8000f8,
+0xc0005600,
+0x40300000,
+0x40240000,
+0x5c000004,
+0x5ec05800,
+0x88000012,
+0x5c000200,
+0xce0000f8,
+0x58000002,
+0x5ec05800,
+0x88000012,
+0x5c000200,
+0xce8000f8,
+0xc000493e,
+0xca0000f8,
+0xc2400000,
+0x5838000c,
+0xce4000f8,
+0x990066c8,
+0xc0004830,
+0xc94000f8,
+0xc61800f8,
+0xc0004930,
+0xc6100078,
+0xcd000078,
+0x800000a8,
+0xc2400002,
+0x58380008,
+0xce400000,
+0xc0004944,
+0xcf4000f8,
+0x80000278,
+0xc000493c,
+0xca4000f8,
+0xdfe800f8,
+0x5a300018,
+0xc0005600,
+0x40200000,
+0xca0000f8,
+0x58380008,
+0xc6501078,
+0xcd021078,
+0x5838000a,
+0xce8000f8,
+0x58380026,
+0xce0000f8,
+0xc0004944,
+0xcf4000f8,
+0x99005d28,
+0xc000491c,
+0xc1400000,
+0xc9420048,
+0x80000038,
+0x00000000,
+0x990066c8,
+0xc0004826,
+0xc94000f8,
+0xc1800002,
+0x8000fdd8,
+0xc2000000,
+0xc2400200,
+0xdf600038,
+0xb624ffea,
+0xc000491c,
+0xca4000f8,
+0xc000491e,
+0xca8000f8,
+0x99005f50,
+0xda5800f8,
+0xda9800f9,
+0x00000000,
+0xc0004934,
+0xca0000f8,
+0x00000000,
+0xc2800000,
+0xa6020160,
+0xc2400004,
+0xc2000200,
+0xdf690048,
+0x46294000,
+0x46a54000,
+0x8800ffda,
+0x00000000,
+0xc000491a,
+0xc98000f8,
+0xc0004862,
+0xc94000f8,
+0x6d9c6000,
+0x45d8e000,
+0x59dc4c80,
+0x99005db0,
+0xd95800f8,
+0xd99800f9,
+0xd9d400f8,
+0x99005d28,
+0xc000491c,
+0xc1400000,
+0xc9420048,
+0xc2000000,
+0xc2400200,
+0xdf600038,
+0xb624ffea,
+0xc000491c,
+0xca4000f8,
+0xc000491e,
+0xca8000f8,
+0x99005f50,
+0xda5800f8,
+0xda9800f9,
+0x00000000,
+0x58380008,
+0xca4000f8,
+0xc2000000,
+0xce000018,
+0xc2a1fffe,
+0x5aa9fffe,
+0xce021078,
+0x5838000a,
+0xce8000f8,
+0xc161fffe,
+0x5955fffe,
+0x14140000,
+0x00000000,
+0xc0000838,
+0xc2500002,
+0xce450800,
+0xc0004848,
+0xcb8400f8,
+0xc2000000,
+0xc000082c,
+0xca040028,
+0x5fb80002,
+0xc0004848,
+0xcf8400f8,
+0x58880002,
+0xb6080018,
+0x00000000,
+0xc0800000,
+0xc0004844,
+0xcc8400f8,
+0x00000000,
+0xc121ffee,
+0x5911fe14,
+0x14100000,
+0x8000ded8,
+0xc2000000,
+0xdf600038,
+0x5e200080,
+0x8400026a,
+0x00000000,
+0xc161fffe,
+0x5955fffe,
+0x14140000,
+0x00000000,
+0xc000480c,
+0xca0000f8,
+0xc0004910,
+0xca4000f8,
+0xc000492c,
+0xca8000f8,
+0xc0004968,
+0xcac000f8,
+0x00000000,
+0xc121ffee,
+0x5911fe14,
+0x14100000,
+0x76250000,
+0x76290000,
+0x76e16000,
+0x840001c2,
+0xc0004926,
+0xca4000f8,
+0xc201fffe,
+0x76e16000,
+0x5a640002,
+0x6ae50010,
+0x5f200000,
+0x8400001a,
+0x6a250000,
+0x80000010,
+0xc6e000f8,
+0x62014008,
+0xc0004926,
+0xce8000f8,
+0xc161fffe,
+0x5955fffe,
+0x14140000,
+0x00000000,
+0xc0004968,
+0xca4000f8,
+0xc2000002,
+0x6a290000,
+0x7e010000,
+0x76612000,
+0xce4000f8,
+0x00000000,
+0xc121ffee,
+0x5911fe14,
+0x14100000,
+0x6eb4a000,
+0x6e944000,
+0x4755a000,
+0x4769a000,
+0x5b745e00,
+0x58340002,
+0xc2000000,
+0xca0000d8,
+0x5834002e,
+0xc2400000,
+0xca400078,
+0x6eb0a000,
+0x6ebc4000,
+0x473d8000,
+0x47298000,
+0x5b301e2e,
+0x5b300004,
+0x6e642000,
+0x4225e000,
+0xc39a8024,
+0xc7380060,
+0xc6b81c18,
+0x99005f50,
+0xdb9800f8,
+0xdbd800f9,
+0x00000000,
+0xc2000000,
+0xdf600038,
+0x5e200080,
+0x840002a2,
+0x00000000,
+0xc161fffe,
+0x5955fffe,
+0x14140000,
+0x00000000,
+0xc000490e,
+0xca0000f8,
+0xc000492a,
+0xca4000f8,
+0xc000496a,
+0xcb0000f8,
+0xc0004956,
+0xcac000f8,
+0x00000000,
+0xc121ffee,
+0x5911fe14,
+0x14100000,
+0x77218000,
+0x77258000,
+0x84000202,
+0xc201fffe,
+0x77218000,
+0x5aec0002,
+0x6b2d0010,
+0x5ea00000,
+0x8400001a,
+0x6a2d0000,
+0x80000010,
+0xc72000f8,
+0x62016008,
+0xc0004956,
+0xcec000f8,
+0xc161fffe,
+0x5955fffe,
+0x14140000,
+0x00000000,
+0xc000496a,
+0xca4000f8,
+0xc2000002,
+0x6a2d0000,
+0x7e010000,
+0x76612000,
+0xce4000f8,
+0x00000000,
+0xc121ffee,
+0x5911fe14,
+0x14100000,
+0x6ef4a000,
+0x6ed44000,
+0x4755a000,
+0x476da000,
+0x5b745e00,
+0x5834000e,
+0xc2000000,
+0xca0000d8,
+0x58340008,
+0xc2400000,
+0xca420078,
+0x5834000c,
+0xc2800000,
+0xca832010,
+0x6e644010,
+0x42250000,
+0x4229e000,
+0xc39a8008,
+0x58340008,
+0xcb809018,
+0x58340008,
+0xc2800000,
+0xca810010,
+0x6ee0a000,
+0x6ee44000,
+0x46250000,
+0x462d0000,
+0x5a200008,
+0x5a201e08,
+0x42290000,
+0xc6380060,
+0xc6f81c18,
+0x99005f50,
+0xdb9800f8,
+0xdbd800f9,
+0x00000000,
+0xc000495a,
+0xc84000f8,
+0x00000000,
+0xc3c00002,
+0x787c2000,
+0xcc4000f8,
+0xc0001a1c,
+0xca0000f8,
+0xc2400008,
+0x6a452000,
+0x76250000,
+0x8400d932,
+0xc0000a28,
+0xc3800000,
+0xcb840028,
+0xc0000a14,
+0xc3400000,
+0xcb440028,
+0xc0004880,
+0xcb0400f8,
+0xb7b4d8ea,
+0x58041802,
+0xcac000f8,
+0xa7000038,
+0x00000000,
+0x00000000,
+0xa6c8d8b8,
+0xc2800000,
+0xc6e80018,
+0x80000048,
+0xc2800000,
+0xc7282018,
+0xc000490e,
+0xca4000f8,
+0x6be9e000,
+0x00000000,
+0x767d2000,
+0x8400d860,
+0x6ea0a000,
+0x6e944000,
+0x46150000,
+0x46290000,
+0x5a205e00,
+0x5820000c,
+0xca0000f8,
+0xc0004946,
+0xce8000f8,
+0xa6220368,
+0x00000000,
+0xc2200060,
+0xc0004948,
+0xce000008,
+0xce021038,
+0xc240000a,
+0xc000494a,
+0xce4000f8,
+0xc2b60002,
+0xc0004964,
+0xce837b00,
+0x99006220,
+0xc00048a0,
+0xc88400f8,
+0x00000000,
+0xc0004946,
+0xcbc000f8,
+0x00000000,
+0x00000000,
+0x6ff8a000,
+0x6fd44000,
+0x4795c000,
+0x47bdc000,
+0x5bb85e00,
+0x99005fe0,
+0xdbd800f8,
+0xdb9800f9,
+0x00000000,
+0x99005d28,
+0xc000491c,
+0xc1400000,
+0xc9420048,
+0xc000491c,
+0x990061d8,
+0xc94000f9,
+0xc98000f8,
+0x00000000,
+0x99005f50,
+0xd95800f8,
+0xd99800f9,
+0x00000000,
+0xc161fffe,
+0x5955fffe,
+0x14140000,
+0x00000000,
+0x99005c18,
+0xdbd800f8,
+0xdb9800f9,
+0xc7d800f8,
+0x00000000,
+0xc121ffee,
+0x5911fe14,
+0x14100000,
+0x6ff8a000,
+0x6fd44000,
+0x4795c000,
+0x47bdc000,
+0x5bb85e00,
+0x58380010,
+0xca0000f8,
+0xc0004874,
+0xc80400f8,
+0x6c908000,
+0x45088000,
+0x45088000,
+0x40100000,
+0xca4000f8,
+0xc43400f8,
+0x00000000,
+0xc74000f8,
+0xce0000f8,
+0xc161fffe,
+0x5955fffe,
+0x14140000,
+0x00000000,
+0xc000490e,
+0xca4000f8,
+0xc2800002,
+0x6abd4000,
+0x72692000,
+0xce4000f8,
+0x00000000,
+0xc121ffee,
+0x5911fe14,
+0x14100000,
+0x990066c8,
+0xc0004836,
+0xc94000f8,
+0xc1800002,
+0x00000000,
+0x00000000,
+0x00000000,
+0xa8e2ffe8,
+0x00000000,
+0xc1220002,
+0xd90c00f8,
+0xc2000000,
+0xc0000a14,
+0xca040028,
+0xc0000a28,
+0xc2500002,
+0xce450800,
+0x58880002,
+0xb6080018,
+0xc00048a0,
+0xc0800000,
+0xcc8400f8,
+0x8000d4b0,
+0xc0004946,
+0xcbc000f8,
+0xc161fffe,
+0x5955fffe,
+0x14140000,
+0x00000000,
+0xc000490e,
+0xca4000f8,
+0xc2800002,
+0x6abd4000,
+0x72692000,
+0xce4000f8,
+0x00000000,
+0xc121ffee,
+0x5911fe14,
+0x14100000,
+0x6ff8a000,
+0x6fd44000,
+0x4795c000,
+0x47bdc000,
+0x5bb85e00,
+0x58380008,
+0xca0000f8,
+0x5838000c,
+0xca4000f8,
+0xc3400000,
+0xc6340000,
+0xc000494e,
+0xcf4000f8,
+0xc2800000,
+0xc62a0078,
+0xc3000000,
+0xc6308018,
+0x6f304000,
+0x43298000,
+0xc000493c,
+0xcf0000f8,
+0xc2c00000,
+0xc66c0078,
+0xc0004950,
+0xcec000f8,
+0xc2800000,
+0xc66ae020,
+0xc0004954,
+0xce8000f8,
+0x5f740000,
+0x840001a0,
+0x5e300028,
+0x46e12000,
+0x8400016a,
+0x46e12000,
+0x88000132,
+0x5e300018,
+0x46e12000,
+0x8800002a,
+0x46e12000,
+0x84000042,
+0x00000000,
+0x800000c0,
+0x00000000,
+0x99006360,
+0xdbd800f8,
+0xdb9800f9,
+0xc78000f8,
+0xc3400002,
+0xc000494e,
+0xcf4000f8,
+0xc161fffe,
+0x5955fffe,
+0x14140000,
+0x00000000,
+0xc000490e,
+0xca4000f8,
+0xc2800002,
+0x6abd4000,
+0x7e814000,
+0x76692000,
+0xce4000f8,
+0x00000000,
+0xc121ffee,
+0x5911fe14,
+0x14100000,
+0xc2200060,
+0xc0004948,
+0xce021038,
+0xc2000000,
+0xc000494c,
+0xce0000f8,
+0x80000080,
+0x00000000,
+0x99006360,
+0xdbd800f8,
+0xdb9800f9,
+0xc78000f8,
+0x99006560,
+0xdbd800f8,
+0xdb9800f9,
+0xc78000f8,
+0xc2200058,
+0xc0004948,
+0xce021038,
+0xc2000002,
+0xc000494c,
+0xce0000f8,
+0xc2000006,
+0xc0001006,
+0xce0000f8,
+0x5838000a,
+0xca4000f8,
+0xc2200982,
+0x5a203b6e,
+0xc0001008,
+0xce0000f8,
+0xc000100a,
+0xce4000f8,
+0xc0004954,
+0xca8000f8,
+0xc200000c,
+0xc000494a,
+0xce0000f8,
+0xc0004948,
+0xce800008,
+0xc2b60000,
+0xc0004964,
+0xce8000f8,
+0x99006220,
+0xc00048a0,
+0xc88400f8,
+0x00000000,
+0xc0004946,
+0xcbc000f8,
+0xc000494c,
+0xca0000f8,
+0x6ff8a000,
+0x6fd44000,
+0x4795c000,
+0x47bdc000,
+0x5bb85e00,
+0x5e200000,
+0x840000fa,
+0x00000000,
+0x99005fe0,
+0xdbd800f8,
+0xdb9800f9,
+0x00000000,
+0x99005d28,
+0xc000491c,
+0xc1400000,
+0xc9420048,
+0xc000491c,
+0x990061d8,
+0xc94000f9,
+0xc98000f8,
+0x00000000,
+0x99005f50,
+0xd95800f8,
+0xd99800f9,
+0x00000000,
+0xc161fffe,
+0x5955fffe,
+0x14140000,
+0x00000000,
+0x99005c18,
+0xdbd800f8,
+0xdb9800f9,
+0xc7d800f8,
+0x00000000,
+0xc121ffee,
+0x5911fe14,
+0x14100000,
+0xc000493c,
+0xca8000f8,
+0xc000494e,
+0xcac000f8,
+0xc3000018,
+0xc3400006,
+0x5e200000,
+0x8400002a,
+0xc2800000,
+0xc2c00000,
+0xc300001e,
+0xc3400000,
+0xc6ac1078,
+0xc72c0418,
+0xc76c0810,
+0x58380010,
+0xca8000f8,
+0x58380008,
+0xcec000f8,
+0xc6280100,
+0xc0004874,
+0xc80400f8,
+0x6c908000,
+0x45088000,
+0x45088000,
+0x40100000,
+0xcb0000f8,
+0xc43400f8,
+0x00000000,
+0xc74000f8,
+0xce8000f8,
+0xc0004952,
+0xce8000f8,
+0x00000000,
+0x00000000,
+0x00000000,
+0xa8e2ffe8,
+0x00000000,
+0xc000494c,
+0xca0000f8,
+0xc0004950,
+0xcac000f8,
+0x5e200000,
+0x8400006a,
+0xdfe800f8,
+0x7e814000,
+0x5834001a,
+0xce8000f8,
+0x990066c8,
+0xc0004834,
+0xc94000f8,
+0xc1800002,
+0x990066c8,
+0xc0004838,
+0xc94000f8,
+0xc6d800f8,
+0xc1220002,
+0xd90c00f8,
+0x5e200000,
+0x84000040,
+0x5838002c,
+0xcb0000f8,
+0xdfe800f8,
+0x00000000,
+0x58380014,
+0xcf0000f8,
+0x80000018,
+0xc2a1fffe,
+0x5aa9fffe,
+0x5838000a,
+0xce8000f8,
+0xc3000000,
+0xc0000a14,
+0xcb040028,
+0xc2d00002,
+0xc0000a28,
+0xcec50800,
+0xc000494e,
+0xca8000f8,
+0x58880002,
+0xb4b00018,
+0xc00048a0,
+0xc0800000,
+0xcc8400f8,
+0x5ea80000,
+0x84000152,
+0x5e200000,
+0x84000140,
+0xc000493c,
+0xca8000f8,
+0x00000000,
+0x00000000,
+0x5aa80060,
+0xce8000f8,
+0x99006360,
+0xdbd800f8,
+0xdb9800f9,
+0xc78000f8,
+0x99006560,
+0xdbd800f8,
+0xdb9800f9,
+0xc78000f8,
+0xc0004952,
+0xcac000f8,
+0x58380000,
+0xca8000f8,
+0xc30c0002,
+0xc7f00018,
+0xa6800098,
+0x00000000,
+0x00000000,
+0xc161fffe,
+0x5955fffe,
+0x14140000,
+0x00000000,
+0xc0001800,
+0xca0000f8,
+0x00000000,
+0x00000000,
+0xa60cffea,
+0xc6f00500,
+0xc6b0c400,
+0xcf0000f8,
+0x00000000,
+0xc121ffee,
+0x5911fe14,
+0x14100000,
+0x8000cb60,
+0xdcbc00f9,
+0x5ffc0000,
+0x84000052,
+0xc3800002,
+0xdb8800f9,
+0x5ffc0004,
+0x8400bec0,
+0xc3800000,
+0xdb8800f9,
+0xc3ce0002,
+0xc0000800,
+0xcfc0e700,
+0xc3e1fffe,
+0x597dffee,
+0x593dfe14,
+0x00000000,
+0x00000000,
+0x00000000,
+0x94000001,
+0x00000000,
+0x00000000,
+0x00000000,
+0xc000487c,
+0xc80400f8,
+0x00000000,
+0x00000000,
+0x40080000,
+0xcbc000f8,
+0xc43800f8,
+0x00000000,
+0xc000480e,
+0xca0000f8,
+0xc0004858,
+0xcb4400f8,
+0x00000000,
+0x00000000,
+0x47610000,
+0x880000b0,
+0x00000000,
+0xa7c00048,
+0xc0004854,
+0xc1000002,
+0xcd0400f8,
+0xc11c0000,
+0xc000082c,
+0xcd05ce00,
+0x800000d8,
+0x00000000,
+0xa7d20138,
+0x00000000,
+0xc7e14040,
+0xc2400000,
+0xc6246028,
+0xc200006a,
+0x46250000,
+0xc6240030,
+0xc0000810,
+0xce440030,
+0x8000ff70,
+0xc2000000,
+0xc0000808,
+0xca040010,
+0xc11c0000,
+0xc000082c,
+0xcd05ce00,
+0x5a200002,
+0x5e600010,
+0x84000010,
+0xc2000000,
+0xc0000808,
+0xce040010,
+0xc3400000,
+0x80000028,
+0xc1200002,
+0xc0000818,
+0xcd061000,
+0x5b740002,
+0xc0004858,
+0xcf4400f8,
+0x99005968,
+0xc0004848,
+0xc94400f8,
+0xc1800000,
+0xc11c0002,
+0xc000082c,
+0xcd05ce00,
+0x800005e0,
+0x5b740002,
+0xc0004858,
+0xcf4400f8,
+0xc78000f8,
+0xc13c0002,
+0xcd03de00,
+0xc0004848,
+0xc94400f8,
+0xc1800000,
+0xc000082c,
+0xc9840028,
+0x59540002,
+0xc0004848,
+0xcd4400f8,
+0x58880002,
+0xb4980560,
+0x00000000,
+0xc0800000,
+0x80000548,
+0xc000487c,
+0xc80400f8,
+0x00000000,
+0x00000000,
+0x40080000,
+0xcbc000f8,
+0xc42800f8,
+0x00000000,
+0xa7c00130,
+0xc000484c,
+0xca0400f8,
+0xc2400000,
+0xc0001aec,
+0xca440018,
+0x5a200002,
+0xc000484c,
+0xce0400f8,
+0xb624008a,
+0xc68000f8,
+0xc13c0002,
+0xcd03de00,
+0xc0004848,
+0xc94400f8,
+0xc1800000,
+0xc000082c,
+0xc9840028,
+0x59540002,
+0xc0004848,
+0xcd4400f8,
+0x58880002,
+0xb4980450,
+0x00000000,
+0xc0800000,
+0x80000438,
+0xc0004854,
+0xc1000004,
+0xcd0400f8,
+0xc0000820,
+0xc2000002,
+0xce0400f8,
+0xc2000000,
+0xc000484c,
+0xce0400f8,
+0xc0004858,
+0xce0400f8,
+0x8000ff28,
+0xc0004854,
+0xc1000000,
+0xcd0400f8,
+0xc11c0000,
+0xc000082c,
+0xcd05ce00,
+0x99005968,
+0xc0004848,
+0xc94400f8,
+0xc1800000,
+0xc1200000,
+0xc0000818,
+0xcd061000,
+0xc11c0002,
+0xc000082c,
+0xcd05ce00,
+0xc2000000,
+0xc000484c,
+0xce0400f8,
+0x80000338,
+0xc0001ac0,
+0xcb8400f8,
+0xc000487c,
+0xc80400f8,
+0x00000000,
+0x00000000,
+0x40080000,
+0xcbc000f8,
+0xc42800f8,
+0x00000000,
+0xa780024a,
+0x00000000,
+0x00000000,
+0xa7c0020a,
+0x00000000,
+0xc0001b00,
+0xc2060006,
+0xce046308,
+0xa7e801c2,
+0x00000000,
+0xc0004850,
+0xca0400f8,
+0xc2400000,
+0xc0001aec,
+0xca448018,
+0x5a200002,
+0xc0004850,
+0xce0400f8,
+0xb62400aa,
+0x00000000,
+0xc68000f8,
+0xc13c0002,
+0xcd03de00,
+0xc0001acc,
+0xc2000002,
+0xce040000,
+0xc0004848,
+0xc94400f8,
+0xc1800000,
+0xc000082c,
+0xc9840028,
+0x59540002,
+0xc0004848,
+0xcd4400f8,
+0x58880002,
+0xb49801c8,
+0x00000000,
+0xc0800000,
+0x800001b0,
+0xc0004854,
+0xc1000000,
+0xcd0400f8,
+0xc11c0000,
+0xc000082c,
+0xcd05ce00,
+0x99005968,
+0xc0004848,
+0xc94400f8,
+0xc1800000,
+0xc2000000,
+0xc0000820,
+0xce0400f8,
+0xc1200000,
+0xc0000818,
+0xcd061000,
+0xc11c0002,
+0xc000082c,
+0xcd05ce00,
+0xc0004850,
+0xce0400f8,
+0xc2000002,
+0xc0001acc,
+0xce040008,
+0x800000e8,
+0xc2000002,
+0xc0004850,
+0xce0400f8,
+0x8000fe88,
+0xc2000000,
+0xc0004850,
+0xce0400f8,
+0xa7e60032,
+0x00000000,
+0xc2000002,
+0xc0001b00,
+0xce040000,
+0x8000fe70,
+0x00000000,
+0xa7860052,
+0x00000000,
+0xc68000f8,
+0xc13c0002,
+0xcd03de00,
+0xc2020002,
+0xc7e2a540,
+0xc0001b00,
+0xce0400f8,
+0x8000fe18,
+0xc2040002,
+0xc0001b00,
+0xce044200,
+0x8000fdf8,
+0xc2c80002,
+0x6ac56000,
+0xdacc00f8,
+0xc0004854,
+0xcb4400f8,
+0xc0004848,
+0xcb8400f8,
+0xc0000838,
+0xc3c00000,
+0xcbc40028,
+0x5ef40004,
+0x84000022,
+0xc3000000,
+0xc0001acc,
+0xcf042100,
+0x47f98000,
+0x8400002a,
+0x47f98000,
+0x88000030,
+0xc1006e8c,
+0x8000b300,
+0xc0004840,
+0xcc8400f8,
+0x8000f6b8,
+0xc0001ac0,
+0xcac400f8,
+0xc0004854,
+0xcb4400f8,
+0xa6c0fbf2,
+0x00000000,
+0x5ef40000,
+0x8400f72a,
+0x5ef40002,
+0x8400f9ba,
+0x5ef40004,
+0x8400fbba,
+0xc1006ce8,
+0x8000b278,
+0x00000000,
+0xc0800000,
+0xdf4b0038,
+0xc0004900,
+0xcb8000f8,
+0xc2000000,
+0xc000490a,
+0xa78000d0,
+0xcbc000f8,
+0xc1000000,
+0xd90000f9,
+0xc1000002,
+0xd90c00f8,
+0x6ff46000,
+0x477da000,
+0x5b744c80,
+0xc2400000,
+0x58340004,
+0xca400078,
+0xc0004900,
+0xce000000,
+0x5a640002,
+0x58340004,
+0xc6500078,
+0xcd000078,
+0xc0004914,
+0xca4000f8,
+0xc2000002,
+0x6a3d0000,
+0x72612000,
+0xce4000f8,
+0xc0000408,
+0xce0000f8,
+0xa78200d8,
+0xc0004908,
+0xcbc000f8,
+0xc1000000,
+0xd90000f9,
+0xc1000002,
+0xd90c00f8,
+0x6ff4a000,
+0x6fd44000,
+0x4755a000,
+0x477da000,
+0x5b745e00,
+0xc2800000,
+0x58340006,
+0xca800078,
+0xc2000000,
+0xc0004900,
+0xce002100,
+0x5ea80002,
+0x58340006,
+0xc6900078,
+0xcd000078,
+0x5a7c0020,
+0xc2000002,
+0x6a250000,
+0xc0000408,
+0xce0000f8,
+0xdca800f9,
+0x5ea80000,
+0x8400b0e8,
+0x00000000,
+0xa4800230,
+0x00000000,
+0xc3c00000,
+0xc000140e,
+0xcbc00018,
+0xc3400000,
+0xc2400000,
+0x6ff86000,
+0x47bdc000,
+0x5bb84c80,
+0x58380008,
+0xcb400078,
+0x58380006,
+0xca400078,
+0x5f740002,
+0x58380008,
+0xc7500078,
+0xcd000078,
+0xc2000000,
+0x58380004,
+0xca020078,
+0xc3000000,
+0x5838000c,
+0xcb000020,
+0x5a640002,
+0x46610000,
+0x84000010,
+0xc2400000,
+0x58380006,
+0xc6500078,
+0xcd000078,
+0xc2000000,
+0x5838000a,
+0xca020078,
+0x5b300002,
+0x5838000c,
+0xc7100020,
+0xcd000020,
+0xc2420020,
+0x5a200004,
+0x46252000,
+0x84000010,
+0xc2000000,
+0x5838000a,
+0xc6101078,
+0xcd021078,
+0xc0004966,
+0xca4000f8,
+0xc2000002,
+0x6a3d0000,
+0x72612000,
+0xce4000f8,
+0x5f740000,
+0x84000040,
+0xc0004912,
+0xca0000f8,
+0xc2c00002,
+0x6afd6000,
+0x7ec16000,
+0x762d0000,
+0xce0000f8,
+0x5f300020,
+0x84000040,
+0xc0004924,
+0xca0000f8,
+0xc2c00002,
+0x6afd6000,
+0x7ec16000,
+0x762d0000,
+0xce0000f8,
+0xa4820070,
+0xc2400000,
+0xc000140e,
+0xca408018,
+0xc2000002,
+0xc0004900,
+0xce000000,
+0xc000490a,
+0xce4000f8,
+0xc1000000,
+0xd90000f9,
+0xd8400078,
+0xc1000004,
+0xd90000f9,
+0xa48402a8,
+0x00000000,
+0xc3c00000,
+0xc000140e,
+0xcbc10018,
+0xc2800000,
+0xc2000000,
+0x6ff8a000,
+0x6fd44000,
+0x4795c000,
+0x47bdc000,
+0x5bb85e00,
+0x5838002e,
+0xca800078,
+0x58380006,
+0xca020078,
+0xc3400000,
+0x5838002e,
+0xcb420078,
+0x5aa80002,
+0x46a10000,
+0x84000010,
+0xc2800000,
+0x5838002e,
+0xc6900078,
+0xcd000078,
+0x5f740002,
+0x5838002e,
+0xc7501078,
+0xcd021078,
+0xc0004968,
+0xca4000f8,
+0xc2000002,
+0x6a3d0000,
+0x72612000,
+0xce4000f8,
+0xc000492a,
+0xca8000f8,
+0x5e740000,
+0x84000040,
+0xc0004910,
+0xca0000f8,
+0xc2c00002,
+0x6afd6000,
+0x7ec16000,
+0x762d0000,
+0xce0000f8,
+0x6abd4010,
+0xa68000f2,
+0x00000000,
+0xc0004910,
+0xca0000f8,
+0xc2c00002,
+0x6afd6000,
+0x7ec16000,
+0x762d0000,
+0xce0000f8,
+0x58380032,
+0xca0000f8,
+0x58000002,
+0xca4000f8,
+0x5838000c,
+0x00000000,
+0xce0000f9,
+0xce4000f8,
+0xc000492a,
+0xca0000f8,
+0xc2c00002,
+0x6afd6000,
+0x722d0000,
+0xce0000f8,
+0xc000492c,
+0xca0000f8,
+0xc2c00002,
+0x6afd6000,
+0x722d0000,
+0xce0000f8,
+0x80000040,
+0xc000492c,
+0xca0000f8,
+0xc2c00002,
+0x6afd6000,
+0x7ec16000,
+0x762d0000,
+0xce0000f8,
+0xa4880120,
+0xc2c00000,
+0xc000140e,
+0xcac20018,
+0xc000490e,
+0xca4000f8,
+0xc2000002,
+0x6a2d0000,
+0x7e010000,
+0x76612000,
+0xce4000f8,
+0xc000496a,
+0xca4000f8,
+0xc2000002,
+0x6a2d0000,
+0x72612000,
+0xce4000f8,
+0x6ef0a000,
+0x6ed44000,
+0x47158000,
+0x472d8000,
+0x5b305e00,
+0x58300000,
+0xca0000f8,
+0x00000000,
+0xc2400002,
+0x76612000,
+0x8400004a,
+0xc24c0002,
+0xc6e40018,
+0xc624c400,
+0x58300010,
+0xca400500,
+0x00000000,
+0xc0001800,
+0xce4000f8,
+0xa4860070,
+0xc2400000,
+0xc000140e,
+0xca418018,
+0xc2020002,
+0xc0004900,
+0xce002100,
+0xc0004908,
+0xce4000f8,
+0xc1000000,
+0xd90000f9,
+0xd8400078,
+0xc1000004,
+0xd90000f9,
+0xc0001408,
+0xcc8000f8,
+0xc10e0002,
+0xd90c00f8,
+0x8000eda8,
+0xdfbc00f9,
+0xc000496e,
+0x99006670,
+0xc94000f8,
+0xc7d800f8,
+0x00000000,
+0xc57000f8,
+0x5ef00020,
+0x88000148,
+0x6f346000,
+0x4771a000,
+0x5b744c80,
+0x58340008,
+0xc2400000,
+0xca400078,
+0x00000000,
+0xc2000000,
+0x5a640002,
+0xce400078,
+0x58340004,
+0xca000078,
+0x00000000,
+0x00000000,
+0x5e200002,
+0xce000078,
+0xc0004912,
+0xca8000f8,
+0xc2400002,
+0x6a712000,
+0x72a54000,
+0xce8000f8,
+0x5e200000,
+0x84000052,
+0xc000480a,
+0xca0000f8,
+0xc0000408,
+0xca8000f8,
+0x76250000,
+0x00000000,
+0x72a14000,
+0xce8000f8,
+0x80000038,
+0xc0004914,
+0xca0000f8,
+0x7e412000,
+0x00000000,
+0x76250000,
+0xce0000f8,
+0x800000d0,
+0x6ef4a000,
+0x6ed44000,
+0x4755a000,
+0x476da000,
+0x5b745e00,
+0x5834002e,
+0xc2400000,
+0xca420078,
+0x00000000,
+0xc2000000,
+0x5a640002,
+0xc6501078,
+0xcd021078,
+0x58340006,
+0xca000078,
+0x00000000,
+0x00000000,
+0x5a200002,
+0xce000078,
+0xc0004910,
+0xca4000f8,
+0xc2000002,
+0x6a2d0000,
+0x72612000,
+0xce4000f8,
+0xc2000002,
+0x6a310000,
+0xc000042a,
+0xce0000f8,
+0xc1040002,
+0xd90c00f8,
+0x00000000,
+0x8000eb18,
+0x00000000,
+0xc4980928,
+0x9d000000,
+0xc5580028,
+0xc0000838,
+0xcd8400f8,
+0xc1440200,
+0xc1c01600,
+0xc55c1070,
+0xc000100e,
+0x9d000000,
+0xcd8000f8,
+0xc000100c,
+0xcdc000f8,
+0xc0004862,
+0xc9c000f8,
+0x00000000,
+0x00000000,
+0xd9d800f9,
+0xc0005600,
+0x401c0000,
+0x5dc05800,
+0x88000012,
+0x5c000200,
+0xcd8000f8,
+0xc1f0000a,
+0x715ca000,
+0xdd9800f8,
+0xdd9c00f9,
+0x41d8e000,
+0xc5d40260,
+0xc0001010,
+0xcd4000f8,
+0x6c9c8000,
+0x45c8e000,
+0x45c8e000,
+0x59dc0004,
+0xc1601260,
+0xc5d40260,
+0x9d000000,
+0xc0001012,
+0xcd4000f8,
+0x00000000,
+0x00000000,
+0xd95800f8,
+0x6d586000,
+0x4594c000,
+0x59984c80,
+0xd99800f9,
+0x5818000a,
+0xc1800000,
+0xc9800078,
+0xc0005400,
+0x6d5ca000,
+0x401c0000,
+0x40180000,
+0xc94000f8,
+0x58000002,
+0x00000000,
+0xc9c000f8,
+0xc0004930,
+0xcd4000f8,
+0xc0004932,
+0xcdc000f8,
+0x59980004,
+0xc1c20020,
+0xb59c0018,
+0x00000000,
+0xc1800000,
+0xdd9c00f9,
+0x581c000a,
+0xcd800078,
+0x581c000c,
+0xc1800000,
+0xc9800020,
+0xc1c00002,
+0xdd9400f8,
+0x69d4e000,
+0x5d980002,
+0xcd800020,
+0xc0004924,
+0xc98000f8,
+0x00000000,
+0x9d000000,
+0x00000000,
+0x719cc000,
+0xcd8000f8,
+0xc000492a,
+0xc94000f8,
+0xc1c00002,
+0x69d8e000,
+0x7dc0c000,
+0x7558a000,
+0xcd4000f8,
+0xc000492c,
+0xc94000f8,
+0xdd8000f9,
+0x58000032,
+0x755ca000,
+0x84000090,
+0xc94000f9,
+0xc98000f8,
+0xdd8000f9,
+0x5800000c,
+0x00000000,
+0xcd4000f9,
+0xcd8000f8,
+0xc000492c,
+0xc94000f8,
+0xc000492a,
+0xc98000f8,
+0x715ca000,
+0xc000492c,
+0xcd4000f8,
+0x719cc000,
+0xc000492a,
+0xcd8000f8,
+0x9d000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0xc0004862,
+0xc98000f8,
+0x00000000,
+0xc1c00200,
+0x4194c000,
+0x459ce000,
+0x88000012,
+0xc5d800f8,
+0xc0004862,
+0xcd8000f8,
+0xc0001406,
+0xc98000f8,
+0xc1c00002,
+0x9d000000,
+0xc5d80a00,
+0xc5581048,
+0xcd8000f8,
+0xc0004930,
+0xc98000f8,
+0xc0004932,
+0xc9c000f8,
+0xc140000e,
+0xc5581c18,
+0xdd9400f8,
+0xc0005600,
+0x40140000,
+0x5d405800,
+0x88000012,
+0x5c000200,
+0xcd8000f8,
+0x58000002,
+0x5d405800,
+0x88000012,
+0x5c000200,
+0xcdc000f8,
+0xdd5400f8,
+0xc1c00000,
+0x58140006,
+0xc9c20078,
+0xc1800000,
+0x58140000,
+0xc98000d8,
+0x6ddc2000,
+0xc000491e,
+0x41d8e000,
+0xcdc000f8,
+0xdd9800f8,
+0xc1c00022,
+0xc5d80d70,
+0xdd9400f9,
+0xc5581c18,
+0xc000491c,
+0xcd8000f8,
+0xdd5400f8,
+0xc1c00000,
+0x58140006,
+0xc9c20078,
+0xc1800000,
+0x58140004,
+0xc9820078,
+0x00000000,
+0x59dc0002,
+0x45d8c000,
+0x84000010,
+0xc1c00000,
+0x9d000000,
+0x58140006,
+0xc5d81078,
+0xcd821078,
+0xc0004860,
+0xc94000f8,
+0xc1800100,
+0xc1d00002,
+0x58146b00,
+0xd58000f8,
+0x58000002,
+0xd58000f9,
+0x59540004,
+0xb5580018,
+0xc0004860,
+0xc1400000,
+0xcd4000f8,
+0xdd9800f9,
+0x9d000000,
+0xdd9400f8,
+0xc0001404,
+0xcdc10800,
+0xc1c00000,
+0xc1800200,
+0x5d980004,
+0xdf5d0048,
+0x459ca000,
+0x8800fff2,
+0xdd8000f9,
+0x5800000c,
+0x00000000,
+0xc94000f9,
+0xc98000f8,
+0xc1c00002,
+0xc5d43f00,
+0xc5d81e00,
+0xc0004862,
+0xc9c000f8,
+0x00000000,
+0x00000000,
+0x581c5600,
+0x5dc05800,
+0x88000012,
+0x5c000200,
+0xcd4000f8,
+0x58000002,
+0x5dc05800,
+0x88000012,
+0x5c000200,
+0xcd8000f8,
+0xc0004862,
+0xc9c000f8,
+0x00000000,
+0xc15004c0,
+0xc5d40060,
+0xdd9c00f8,
+0xc5d41c18,
+0xc1c00000,
+0xdd8000f9,
+0x58000030,
+0xc9c00078,
+0xdd8000f9,
+0x58000002,
+0xc98000f8,
+0x6ddc2000,
+0xc000491c,
+0x41d8e000,
+0xcd4000f9,
+0xcdc000f8,
+0xdd9400f9,
+0xc1c00000,
+0x58140030,
+0xc9c00078,
+0xc1800000,
+0x58140006,
+0xc9820078,
+0x00000000,
+0x59dc0002,
+0x45d8c000,
+0x84000010,
+0xc1c00000,
+0x9d000000,
+0x58140030,
+0xc5d80078,
+0xcd800078,
+0xc1c00000,
+0xdf5c0038,
+0x5ddc0080,
+0x8400ffea,
+0x00000000,
+0x9d000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0xc160fffe,
+0xc0000a10,
+0xc9440060,
+0xc1a0fffe,
+0x59981e08,
+0xc000100c,
+0xcd4000f8,
+0xc000100e,
+0xcd8000f8,
+0xc0004964,
+0xc98000f8,
+0x00000000,
+0xc170000a,
+0x7158a000,
+0x6c988000,
+0x4588c000,
+0x4588c000,
+0x59980004,
+0xc5940270,
+0xc0001010,
+0xcd4000f8,
+0xc0004946,
+0xc94000f8,
+0x00000000,
+0x00000000,
+0x6d58a000,
+0x6d5c4000,
+0x459cc000,
+0x4594c000,
+0xc000494a,
+0xc94000f8,
+0xc0004948,
+0xc9c000f8,
+0x4194c000,
+0xc1400012,
+0xc55c1818,
+0x9d000000,
+0xc59c0268,
+0xc0001012,
+0xcdc000f8,
+0xc1400000,
+0x58000012,
+0xc9410038,
+0xc0004950,
+0xc9c000f8,
+0xc55800f8,
+0xc5940838,
+0xc5581078,
+0xd99400f8,
+0xc000493c,
+0xc94000f8,
+0xc0004954,
+0xc98000f8,
+0x59dc00a8,
+0x45d4e000,
+0x41d8e000,
+0x5d5c0030,
+0x88000010,
+0xc1c00030,
+0xc1800000,
+0xc5d84028,
+0xc1400000,
+0xc5d40008,
+0x5dd40002,
+0x84000072,
+0x5dd40004,
+0x8400009a,
+0x5dd40006,
+0x840000c2,
+0x5dd80026,
+0x840000ea,
+0xdd5400f8,
+0xdd8000f9,
+0x58000008,
+0x40180000,
+0xcd4000f8,
+0x59980002,
+0x8000ffc0,
+0xdd5400f8,
+0xdd8000f9,
+0x58000008,
+0x40180000,
+0xcd4000b8,
+0x59980002,
+0x8000ff88,
+0xdd5400f8,
+0xdd8000f9,
+0x58000008,
+0x40180000,
+0xcd400078,
+0x59980002,
+0x8000ff50,
+0xdd5400f8,
+0xdd8000f9,
+0x58000008,
+0x40180000,
+0xcd400038,
+0x59980002,
+0x8000ff18,
+0x00000000,
+0x9d000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x58000012,
+0xc94000f8,
+0xc0004954,
+0xc9c000f8,
+0xc0004950,
+0xc9400078,
+0xdd8000f9,
+0x58000028,
+0x5d9c0000,
+0x84000052,
+0x5d9c0002,
+0x84000052,
+0x5d9c0004,
+0x8400006a,
+0xc55b0038,
+0xc55c08b8,
+0xcd800039,
+0xcdc108b8,
+0x80000060,
+0xcd4000f8,
+0x80000050,
+0xc55900b8,
+0xc55c1838,
+0xcd8000b9,
+0xcdc31838,
+0x80000028,
+0xc55a0078,
+0xc55c1078,
+0xcd800079,
+0xcdc21078,
+0x9d000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x59540002,
+0x6994e018,
+0x61c0c008,
+0x4194a000,
+0x5d940040,
+0x88000012,
+0xc59400f8,
+0x9d000000,
+0xcd4000f8,
+0x00000000,
+0x00000000,
+0x9d000000,
+0x4158a000,
+0xcd4000f8,
+0x00000000
+};
+
+static unsigned int firmware_binary_data[] = {
+};
+
+
+#endif // IFXMIPS_ATM_FW_AMAZON_SE_H
diff --git a/package/ltq-dsl/src/ifxmips_atm_fw_ar9.h b/package/ltq-dsl/src/ifxmips_atm_fw_ar9.h
new file mode 100644
index 000000000..b22bcccca
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_fw_ar9.h
@@ -0,0 +1,439 @@
+#ifndef IFXMIPS_ATM_FW_AR9_H
+#define IFXMIPS_ATM_FW_AR9_H
+
+
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_fw_ar9.h
+** PROJECT : UEIP
+** MODULES : ATM (ADSL)
+**
+** DATE : 22 OCT 2007
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM Driver (PP32 Firmware)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 22 OCT 2007 Xu Liang Initiate Version, v00.01
+*******************************************************************************/
+
+
+#define VER_IN_FIRMWARE 1
+
+#define ATM_FW_VER_MAJOR 0
+#define ATM_FW_VER_MINOR 16
+
+
+static unsigned int firmware_binary_code[] = {
+ 0x800004b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000ffe0, 0x00000000, 0x00000000, 0x00000000,
+ 0xc1000002, 0xd90c00f8, 0xc2000002, 0xda0800f9, 0x80004980, 0xc2000000, 0xda0800f9, 0x80003fe8,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x80003fa0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x80005178, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x80003ea0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xc0400000, 0xc0004840, 0xc88400f8, 0x80004640, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xc0400002, 0xc0004840, 0xc88400f8, 0x800045c0, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xc3c00004, 0xdbc800f9, 0xc10c0002, 0xd90c00f8, 0x8000fee0, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xc10e0002, 0xd90c00f8, 0xc0004808, 0xc84000f8, 0x800045f0, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xc3e1fffe, 0x597dfffe, 0x593dfe14, 0x900004d9, 0x00000000, 0x00000000, 0x00000000, 0x90cc0481,
+ 0x00000000, 0x00000000, 0x00000000, 0xc3c00000, 0xdbc800f9, 0xc1400008, 0xc1900000, 0x71588000,
+ 0x14100100, 0xc140000a, 0xc1900002, 0x71588000, 0x14100100, 0xc140000c, 0xc1900004, 0x71588000,
+ 0x14100100, 0xc1400004, 0xc1900006, 0x71588000, 0x14100100, 0xc1400006, 0xc1900008, 0x71588000,
+ 0x14100100, 0xc140000e, 0xc190000a, 0x71588000, 0x14100100, 0xc1400000, 0xc190000c, 0x71588000,
+ 0x14100100, 0xc1400002, 0xc190000e, 0x71588000, 0x14100100, 0xc0400000, 0xc11c0000, 0xc000082c,
+ 0xcd05ce00, 0xc11c0002, 0xc000082c, 0xcd05ce00, 0xc0400002, 0xc11c0000, 0xc000082c, 0xcd05ce00,
+ 0xc11c0002, 0xc000082c, 0xcd05ce00, 0xc0000824, 0x00000000, 0xcbc000f9, 0xcb8000f9, 0xcb4000f9,
+ 0xcb0000f8, 0xc0004878, 0x5bfc4000, 0xcfc000f9, 0x5bb84000, 0xcf8000f9, 0x5b744000, 0xcf4000f9,
+ 0x5b304000, 0xcf0000f8, 0xc0000a10, 0x00000000, 0xcbc000f9, 0xcb8000f8, 0xc0004874, 0x5bfc4000,
+ 0xcfc000f9, 0x5bb84000, 0xcf8000f8, 0xc30001fe, 0xc000140a, 0xcf0000f8, 0xc3000000, 0x7f018000,
+ 0xc000042e, 0xcf0000f8, 0xc000040e, 0xcf0000f8, 0xc3c1fffe, 0xc000490e, 0xcfc00078, 0xc000492c,
+ 0xcfc00078, 0xc0004924, 0xcfc00038, 0xc0004912, 0xcfc00038, 0xc0004966, 0xcfc00038, 0xc0004968,
+ 0xcfc00078, 0xc000496a, 0xcfc00078, 0xc3c1fffe, 0xc00049a0, 0xcfc000f8, 0xc3c00000, 0xc2800020,
+ 0xc3000000, 0x7f018000, 0x6ff88000, 0x6fd44000, 0x4395c000, 0x5bb84a00, 0x5838000a, 0xcf0000f8,
+ 0x5bfc0002, 0xb7e8ffc8, 0x00000000, 0xc3c00000, 0xc2800010, 0x6ff86000, 0x47bdc000, 0x5bb84c80,
+ 0xc3400000, 0x58380004, 0xcb420078, 0x00000000, 0x58380008, 0xcf400078, 0x5bfc0002, 0xb7e8ffb0,
+ 0x00000000, 0xc3c00000, 0xc2800020, 0xc348001e, 0xc3000000, 0x7f018000, 0x6ff8a000, 0x6fd44000,
+ 0x4795c000, 0x47bdc000, 0x5bb87000, 0x58380008, 0xcf408418, 0x5838000a, 0xcf0000f8, 0x5bfc0002,
+ 0xb7e8ffb0, 0x00000000, 0x00000000, 0xc3e0a242, 0x5bfc0020, 0xc0004002, 0xcfc000f8, 0x00000000,
+ 0xc121fffe, 0x5911fe14, 0x14100000, 0x80000530, 0x00000000, 0x80002130, 0x00000000, 0x8000ffe0,
+ 0xc0004958, 0xc84000f8, 0x00000000, 0xc3c00002, 0x787c2000, 0xcc4000f8, 0xc0004848, 0xcb8400f8,
+ 0xc000495c, 0xcac400f8, 0xc0004844, 0xc88400f8, 0x47ad0000, 0x8400ff82, 0xc000487c, 0xc80400f8,
+ 0x00000000, 0x00000000, 0x40080000, 0xca0000f8, 0xc0001624, 0xcb0400f8, 0xa63c007a, 0x00000000,
+ 0x00000000, 0xa71eff22, 0x00000000, 0xc0000824, 0xca8400f8, 0x6ca08000, 0x6ca42000, 0x46250000,
+ 0x42290000, 0xc35e0002, 0xc6340060, 0xc0001624, 0xcf440078, 0xc2000000, 0xc161fffe, 0x5955fffe,
+ 0x14140000, 0x00000000, 0xc0004844, 0xc88400f8, 0xc000082c, 0xca040038, 0x00000000, 0x00000000,
+ 0x58880002, 0xb6080018, 0x00000000, 0xc0800000, 0xc0004844, 0xcc840038, 0x5aec0002, 0xc000495c,
+ 0xcec400f8, 0x5e6c0006, 0x84000060, 0xc0004848, 0xcb8400f8, 0xc0000838, 0xc2500002, 0xce450800,
+ 0x5fb80002, 0xc0004848, 0xcf8400f8, 0x5eec0002, 0xc000495c, 0xcec400f8, 0x00000000, 0xc121fffe,
+ 0x5911fe14, 0x14100000, 0x8000fd98, 0xc000495a, 0xc84000f8, 0x00000000, 0xc3c00002, 0x787c2000,
+ 0xcc4000f8, 0xc0004960, 0xcac400f8, 0x00000000, 0x00000000, 0x5eec0000, 0x8400010a, 0x00000000,
+ 0xb6fc0050, 0xc0001600, 0xca0400f8, 0x00000000, 0x00000000, 0xa61e00d2, 0x6fe90000, 0xc0000a28,
+ 0xce850800, 0xc2c00000, 0xc2800004, 0xb6e800a0, 0xc0001604, 0xca8400f8, 0xc0004960, 0xcec400f8,
+ 0xa69efcc2, 0x00000000, 0x6fe90000, 0xc0000a28, 0xce850800, 0xc2c00002, 0xc0001600, 0xca0400f8,
+ 0x00000000, 0x00000000, 0xa61e002a, 0x6fe90000, 0xc0000a28, 0xce850800, 0xc2c00000, 0xc0001604,
+ 0xca8400f8, 0xc0004960, 0xcec400f8, 0xa69efc2a, 0xc2400000, 0xc0000a14, 0xca440028, 0x00000000,
+ 0x00000000, 0x466d2000, 0xa4400020, 0xc2800000, 0xdfeb0029, 0x80000010, 0xdfea0029, 0xb668fba2,
+ 0x00000000, 0xc00048a0, 0xcb0400f8, 0xc0000a10, 0xca8400f8, 0x6f208000, 0x6f242000, 0x46250000,
+ 0x42a10000, 0xc2400000, 0xc0000a14, 0xca440028, 0xc35e0002, 0xc6340060, 0xc0001604, 0xcf440078,
+ 0x5b300002, 0xb6700018, 0x5aec0002, 0xc3000000, 0xc00048a0, 0xcf0400f8, 0xc0004960, 0xcec400f8,
+ 0x8000fad8, 0xc0004918, 0xd28000f8, 0xc2000000, 0xdf600038, 0x5e600080, 0x84000272, 0x00000000,
+ 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0xc000480a, 0xca0000f8, 0xc0004912, 0xca4000f8,
+ 0xc0004924, 0xca8000f8, 0xc0004966, 0xcac000f8, 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000,
+ 0x76250000, 0x76290000, 0x762d0000, 0x840001ca, 0xc0004918, 0xca4000f8, 0xc28001fe, 0x76290000,
+ 0x5a640002, 0x6a254010, 0x5ee80000, 0x8400001a, 0x6aa54000, 0x80000010, 0xc62800f8, 0x62818008,
+ 0xc0004918, 0xcf0000f8, 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0xc0004966, 0xca4000f8,
+ 0xc2000002, 0x6a310000, 0x7e010000, 0x76612000, 0xce4000f8, 0x00000000, 0xc121fffe, 0x5911fe14,
+ 0x14100000, 0x6f346000, 0x4771a000, 0x5b744c80, 0xc2800000, 0x58340006, 0xca800078, 0xc2c00000,
+ 0x58340000, 0xcac000d8, 0xc2400000, 0x5834000a, 0xca420078, 0x6ea82000, 0x42e9e000, 0x6f2ca000,
+ 0x42e56000, 0x5aec2e00, 0xc3990040, 0xc7381c18, 0xc6f80060, 0x99005b78, 0xdb9800f8, 0xdbd800f9,
+ 0x00000000, 0xdea000f8, 0x46310000, 0x8400fd80, 0xc0004958, 0xc84000f8, 0x00000000, 0xc3c00002,
+ 0x787c2000, 0xcc4000f8, 0xc0004848, 0xcb8400f8, 0xc0004844, 0xc88400f8, 0x5fb80000, 0x8400f7f2,
+ 0xc0001a1c, 0xca0000f8, 0xc2400002, 0x6a452000, 0x76250000, 0x8400f7c2, 0xc000487c, 0xc80400f8,
+ 0x00000000, 0x00000000, 0x40080000, 0xca0000f8, 0xc42400f8, 0x00000000, 0xa63c17da, 0x00000000,
+ 0xc0004878, 0xc80400f8, 0x6c908000, 0x45088000, 0x45088000, 0x40100000, 0xca0000f8, 0xc42400f8,
+ 0x00000000, 0xc0004934, 0xce0000f8, 0xc2800002, 0xc4681c08, 0xc62821d0, 0xc2600010, 0x5a650060,
+ 0xc0004800, 0xcb4000f8, 0xc2200400, 0x5a200020, 0xc7601040, 0xc0001220, 0xce8000f8, 0xc0001200,
+ 0xce4000f8, 0xc0001202, 0xce0000f8, 0xc0001240, 0xcb4000f8, 0x00000000, 0x00000000, 0xa754ffe0,
+ 0xc2000000, 0xc7600040, 0xa7520042, 0x00000000, 0x00000000, 0x990062f0, 0xc0004822, 0xc94000f8,
+ 0xc1800002, 0x80001680, 0x582040a0, 0xc2000000, 0xca000018, 0xc2400000, 0xca414000, 0xc2800000,
+ 0xca812000, 0xc2c00000, 0xcac20018, 0xc0004938, 0xce0000f8, 0xc0004920, 0xce4000f8, 0xc0004916,
+ 0xce8000f8, 0xc0004922, 0xcec000f8, 0xa6400540, 0x00000000, 0xc0004938, 0xcbc000f8, 0x00000000,
+ 0xc3800000, 0x6ff48000, 0x6fd44000, 0x4355a000, 0x5b744a00, 0x58340000, 0xcb802010, 0x00000000,
+ 0xc2000000, 0x6fb46000, 0x4779a000, 0x5b744c80, 0x5834000c, 0xca000020, 0xc000491a, 0xcf8000f8,
+ 0x5e200000, 0x8400046a, 0xc2000000, 0xdf610048, 0x5e6001e8, 0x8800ffe8, 0xc2000002, 0xc2400466,
+ 0xc2a00000, 0x5aa80000, 0xc0001006, 0xce0000f8, 0xc0001008, 0xce4000f8, 0xc000100a, 0xce8000f8,
+ 0x990055b8, 0xc1a0fffe, 0xc0000824, 0xc9840060, 0xc0004934, 0xca4000f8, 0xc2000000, 0xc2800002,
+ 0x990055f8, 0xda9800f8, 0xc61400f8, 0xc65800f8, 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000,
+ 0x990056e0, 0xc000491a, 0xc94000f8, 0x00000000, 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000,
+ 0xc0004922, 0xca001118, 0xc3c00000, 0xc3800000, 0xc0004930, 0xce023118, 0xc0004932, 0xcbc000d8,
+ 0xc2800000, 0xc000491e, 0xcfc000f8, 0xc0004862, 0xca800060, 0xc3a0001a, 0x5bb94000, 0xc6b80060,
+ 0xc000491c, 0xcf8000f8, 0x99005950, 0xc000491c, 0xc1400000, 0xc9420048, 0x00000000, 0x00000000,
+ 0x00000000, 0xa8e2ffe8, 0xc2000000, 0xc1220002, 0xd90c00f8, 0xdf600038, 0x5e600080, 0x8400fff2,
+ 0xc000491c, 0xca0000f8, 0xc000491e, 0xca4000f8, 0x00000000, 0x00000000, 0x99005b78, 0xda1800f8,
+ 0xda5800f9, 0x00000000, 0xc2000000, 0xdf610048, 0x5e6001fe, 0x8800ffe8, 0xc0004916, 0xca8000f8,
+ 0xc2c00000, 0xdfec0048, 0xc2400000, 0x466d2000, 0x8400004a, 0x5ea80000, 0x8400003a, 0xc2600002,
+ 0x990062f0, 0xc000482e, 0xc94000f8, 0xc1800002, 0x80000030, 0xc2600000, 0x990062f0, 0xc000482c,
+ 0xc94000f8, 0xc1800002, 0xc2000068, 0xc6240078, 0xc0004930, 0xce400080, 0xc000491a, 0xc98000f8,
+ 0xc0004862, 0xc94000f8, 0x6d9c6000, 0x45d8e000, 0x59dc4c80, 0x990059d8, 0xd95800f8, 0xd99800f9,
+ 0xd9d400f8, 0x99005950, 0xc000491c, 0xc1400000, 0xc9420048, 0xc2000000, 0xdf600038, 0x5e600080,
+ 0x8400ffea, 0x00000000, 0xc000491c, 0xca0000f8, 0xc000491e, 0xca4000f8, 0x00000000, 0x00000000,
+ 0x99005b78, 0xda1800f8, 0xda5800f9, 0x00000000, 0x800010e8, 0x00000000, 0x990062f0, 0xc000482a,
+ 0xc94000f8, 0xc1800002, 0x800010b8, 0xc0004938, 0xcbc000f8, 0x00000000, 0x00000000, 0x6ff88000,
+ 0x6fd44000, 0x4395c000, 0x5bb84a00, 0x58380008, 0xca0000f8, 0x00000000, 0x00000000, 0xa6000382,
+ 0x00000000, 0xc0004938, 0xcbc000f8, 0xc3000000, 0x00000000, 0x6ff88000, 0x6fd44000, 0x4395c000,
+ 0x5bb84a00, 0x58380000, 0xcb002010, 0xc2000000, 0x58380008, 0xca020078, 0x5838000c, 0xcac000f8,
+ 0x5838000e, 0xca4000f8, 0xc000491a, 0xcf0000f8, 0xc0004930, 0xcec000f8, 0xc000493c, 0xce0000f8,
+ 0xc0004932, 0xce4000f8, 0x5e200000, 0x84000120, 0xc2800000, 0xa6fe00ba, 0x6f206000, 0x46310000,
+ 0x5a204c80, 0x5820000c, 0xca800020, 0x00000000, 0x00000000, 0x5ea80000, 0x840001f2, 0x00000000,
+ 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0x990056e0, 0xc000491a, 0xc94000f8, 0x00000000,
+ 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000, 0xc0004930, 0xcac000f8, 0xc0004932, 0xca4000f8,
+ 0xc7ec1118, 0xc0004930, 0xcec000f8, 0x5838000c, 0xcec000f8, 0x58000002, 0xce4000f8, 0xc0004934,
+ 0xca0000f8, 0xc2400002, 0x6e642000, 0x6e642000, 0x76612000, 0x8400002a, 0xc2400002, 0x6e684000,
+ 0x58380008, 0xce804200, 0xa6000020, 0x6e682000, 0x58380008, 0xce802100, 0xc2400002, 0x6e642000,
+ 0x76612000, 0x840000ea, 0x58380008, 0xca0000f8, 0xc2800000, 0xc2400000, 0xa60200c0, 0xdba800f8,
+ 0x6f386000, 0x47b1c000, 0x5bb84c80, 0x58380004, 0xca400078, 0x58380002, 0xca800078, 0x00000000,
+ 0xdeb800f8, 0x46a54000, 0x88000060, 0x00000000, 0xc0004824, 0xca0000f8, 0xc2400002, 0x6e640000,
+ 0x5a200002, 0xce0000f8, 0x58380008, 0xce400000, 0x80000018, 0x00000000, 0x80000048, 0xc0004934,
+ 0xca0000f8, 0x00000000, 0x00000000, 0xa6020c6a, 0x00000000, 0x00000000, 0x80000c98, 0xc2800000,
+ 0xc2000200, 0xc240001a, 0xdf690048, 0x46294000, 0x46a54000, 0x8800ffd2, 0xc2000006, 0xc2600982,
+ 0x5a643b6e, 0x5838000a, 0xca8000f8, 0xc0001006, 0xce0000f8, 0xc0001008, 0xce4000f8, 0xc000100a,
+ 0xce8000f8, 0x990055b8, 0xc1a0fffe, 0xc0000824, 0xc9840060, 0xc2000000, 0xc0004930, 0xca02e008,
+ 0x58380026, 0xca4000f8, 0x00000000, 0xc2800000, 0x990055f8, 0xda9800f8, 0xc61400f8, 0xc65800f8,
+ 0xc0004934, 0xca0000f8, 0x00000000, 0x00000000, 0xa6020022, 0x00000000, 0x00000000, 0x80000318,
+ 0xc0004938, 0xcbc000f8, 0xc0004878, 0xc80400f8, 0x6c908000, 0x45088000, 0x45088000, 0x40100000,
+ 0xca0000f8, 0xc42400f8, 0x00000000, 0x58240018, 0xca0000f8, 0x6ff88000, 0x6fd44000, 0x4395c000,
+ 0x5bb84a00, 0xc3000000, 0xc3400002, 0xc2c00000, 0xc62c0078, 0xc6270038, 0xc0004940, 0xce400038,
+ 0xc6260038, 0xc0004942, 0xce400038, 0xc000493c, 0xca0000f8, 0x5eec0000, 0x8400018a, 0x5a6c0010,
+ 0x46254000, 0x88000190, 0x5a600052, 0x46e54000, 0x88000178, 0x58380006, 0xca8000f8, 0xc0004940,
+ 0xca0000f8, 0xc2400000, 0xc6a70038, 0x7e412000, 0x76612000, 0xc2000000, 0xc6a10038, 0x46250000,
+ 0x84000138, 0xc0004942, 0xca0000f8, 0xc2400000, 0xc6a60038, 0x7e412000, 0x76612000, 0xc2000000,
+ 0xc6a00038, 0x58380002, 0xca8000f8, 0x46250000, 0x840000e8, 0xc2400000, 0xc6a60078, 0x466d0000,
+ 0x880000da, 0xc2400000, 0xc6a40078, 0x58380008, 0xca8000f8, 0x46e50000, 0x880000ba, 0x00000000,
+ 0xa6820018, 0x00000000, 0xc7700b00, 0xa6840098, 0x00000000, 0xc7700a00, 0x80000080, 0xc7700200,
+ 0xc000493c, 0xcac000f8, 0x80000060, 0xc7700300, 0xc000493c, 0xcac000f8, 0x80000040, 0xc7700900,
+ 0x80000030, 0xc7700800, 0x80000020, 0xc7700700, 0x80000010, 0xc7700500, 0xc0004944, 0xcf0000f8,
+ 0xc000493e, 0xcec000f8, 0xc0004938, 0xca4000f8, 0xc000493c, 0xcb8000f8, 0xc000493e, 0xcb4000f8,
+ 0xc3000000, 0x6e608000, 0x6e544000, 0x42150000, 0x5a204a00, 0x5aa00008, 0x58200004, 0xcb000078,
+ 0xc0004934, 0xca0000f8, 0xc2400000, 0xc0004930, 0xca42e008, 0xc3c00018, 0xa6020098, 0x00000000,
+ 0x43656000, 0x47ad0000, 0x88000050, 0x46f96000, 0x6ee04010, 0x5be00004, 0xc2000000, 0xc6e00008,
+ 0x5e200000, 0x84000042, 0x5bfc0002, 0x80000030, 0xc3c00004, 0x5a2c0008, 0x47a10000, 0x88000012,
+ 0x5fb80008, 0x6fe04000, 0x42390000, 0x47212000, 0x88000068, 0xc2400000, 0xc0004930, 0xca42e008,
+ 0xc2060002, 0xc68000f8, 0xce006300, 0x6fe04000, 0x4721c000, 0x5f700010, 0x4765a000, 0xc2000000,
+ 0xc6340008, 0xc25a000a, 0xc000491a, 0xca401c18, 0xc2800000, 0xc0004932, 0xca8000d8, 0xc0004862,
+ 0xca400060, 0x6fa04010, 0x42290000, 0xc000491e, 0xce0000f8, 0xc7e41048, 0xc000491c, 0xce4000f8,
+ 0x6fe04000, 0x43a1c000, 0xc000493c, 0xcf8000f8, 0xc000493e, 0xcf4000f8, 0xc000493a, 0xcfc000f8,
+ 0x80000008, 0x00000000, 0x00000000, 0x00000000, 0xc2000000, 0xdce000f8, 0xa622ffd8, 0xc1220002,
+ 0xd90c00f8, 0xc0004938, 0xcbc000f8, 0xc0004944, 0xcb4000f8, 0xc0004862, 0xcb0000f8, 0xc0004934,
+ 0xca0000f8, 0x6ff88000, 0x6fd44000, 0x4395c000, 0x5bb84a00, 0xa6020268, 0xc2400000, 0x58380008,
+ 0xca406000, 0xdfe800f8, 0xc2218e08, 0x5a21baf6, 0x46a14000, 0x84000022, 0xc2080002, 0x7361a000,
+ 0x80000058, 0x5e640000, 0x84000022, 0xc20c0002, 0x7361a000, 0x80000030, 0xc2000000, 0xc760e710,
+ 0xc7604218, 0x5e200000, 0x84000272, 0xc2200002, 0xc0004930, 0xce021000, 0x990062f0, 0xc0004828,
+ 0xc94000f8, 0xc1800002, 0x58380000, 0xca0000f8, 0x00000000, 0x00000000, 0xa6000132, 0xc0004940,
+ 0xca8000f8, 0xc0004942, 0xca4000f8, 0xc7600078, 0xc6a01838, 0xc6601038, 0xc000493a, 0xca4000f8,
+ 0xc0004934, 0xca8000f8, 0xc0007800, 0x40300000, 0x40240000, 0x5c000004, 0x5ec07a00, 0x88000012,
+ 0x5c000200, 0xce0000f8, 0x58000002, 0x5ec07a00, 0x88000012, 0x5c000200, 0xce8000f8, 0xc000493e,
+ 0xca0000f8, 0xc2400000, 0x5838000c, 0xce4000f8, 0x990062f0, 0xc0004830, 0xc94000f8, 0xc61800f8,
+ 0xc0004930, 0xc6100078, 0xcd000078, 0x800000a8, 0xc2400002, 0x58380008, 0xce400000, 0xc0004944,
+ 0xcf4000f8, 0x80000278, 0xc000493c, 0xca4000f8, 0xdfe800f8, 0x5a300018, 0xc0007800, 0x40200000,
+ 0xca0000f8, 0x58380008, 0xc6501078, 0xcd021078, 0x5838000a, 0xce8000f8, 0x58380026, 0xce0000f8,
+ 0xc0004944, 0xcf4000f8, 0x99005950, 0xc000491c, 0xc1400000, 0xc9420048, 0x80000038, 0x00000000,
+ 0x990062f0, 0xc0004826, 0xc94000f8, 0xc1800002, 0x8000fdd8, 0xc2000000, 0xc2400080, 0xdf600038,
+ 0xb624ffea, 0xc000491c, 0xca4000f8, 0xc000491e, 0xca8000f8, 0x99005b78, 0xda5800f8, 0xda9800f9,
+ 0x00000000, 0xc0004934, 0xca0000f8, 0x00000000, 0xc2800000, 0xa6020160, 0xc2400004, 0xc2000200,
+ 0xdf690048, 0x46294000, 0x46a54000, 0x8800ffda, 0x00000000, 0xc000491a, 0xc98000f8, 0xc0004862,
+ 0xc94000f8, 0x6d9c6000, 0x45d8e000, 0x59dc4c80, 0x990059d8, 0xd95800f8, 0xd99800f9, 0xd9d400f8,
+ 0x99005950, 0xc000491c, 0xc1400000, 0xc9420048, 0xc2000000, 0xc2400080, 0xdf600038, 0xb624ffea,
+ 0xc000491c, 0xca4000f8, 0xc000491e, 0xca8000f8, 0x99005b78, 0xda5800f8, 0xda9800f9, 0x00000000,
+ 0x58380008, 0xca4000f8, 0xc2000000, 0xce000018, 0xc2a1fffe, 0x5aa9fffe, 0xce021078, 0x5838000a,
+ 0xce8000f8, 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0xc0000838, 0xc2500002, 0xce450800,
+ 0xc0004848, 0xcb8400f8, 0xc2000000, 0xc000082c, 0xca040028, 0x5fb80002, 0xc0004848, 0xcf8400f8,
+ 0x58880002, 0xb6080018, 0x00000000, 0xc0800000, 0xc0004844, 0xcc8400f8, 0x00000000, 0xc121fffe,
+ 0x5911fe14, 0x14100000, 0x8000ded8, 0xc2000000, 0xdf600038, 0x5e200080, 0x8400026a, 0x00000000,
+ 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0xc000480c, 0xca0000f8, 0xc0004910, 0xca4000f8,
+ 0xc000492c, 0xca8000f8, 0xc0004968, 0xcac000f8, 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000,
+ 0x76250000, 0x76290000, 0x76e16000, 0x840001c2, 0xc0004926, 0xca4000f8, 0xc201fffe, 0x76e16000,
+ 0x5a640002, 0x6ae50010, 0x5f200000, 0x8400001a, 0x6a250000, 0x80000010, 0xc6e000f8, 0x62014008,
+ 0xc0004926, 0xce8000f8, 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0xc0004968, 0xca4000f8,
+ 0xc2000002, 0x6a290000, 0x7e010000, 0x76612000, 0xce4000f8, 0x00000000, 0xc121fffe, 0x5911fe14,
+ 0x14100000, 0x6eb4a000, 0x6e944000, 0x4755a000, 0x4769a000, 0x5b747000, 0x58340002, 0xc2000000,
+ 0xca0000d8, 0x5834002e, 0xc2400000, 0xca400078, 0x6eb0a000, 0x6ebc4000, 0x473d8000, 0x47298000,
+ 0x5b30302e, 0x5b300004, 0x6e642000, 0x4225e000, 0xc39a8024, 0xc7380060, 0xc6b81c18, 0x99005b78,
+ 0xdb9800f8, 0xdbd800f9, 0x00000000, 0xc2000000, 0xdf600038, 0x5e200080, 0x84000352, 0x00000000,
+ 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0xc000490e, 0xca0000f8, 0xc00049a0, 0xca8000f8,
+ 0xc000492a, 0xca4000f8, 0xc000496a, 0xcb0000f8, 0xc0004956, 0xcac000f8, 0x00000000, 0xc121fffe,
+ 0x5911fe14, 0x14100000, 0x77218000, 0x77258000, 0x77298000, 0x8400029a, 0xc201fffe, 0x77218000,
+ 0x5aec0002, 0x6b2d0010, 0x5ea00000, 0x8400001a, 0x6a2d0000, 0x80000010, 0xc72000f8, 0x62016008,
+ 0xc0004956, 0xcec000f8, 0x6ef4a000, 0x6ed44000, 0x4755a000, 0x476da000, 0x5b747000, 0x58340000,
+ 0xc9c000f8, 0xc00049a0, 0xca0000f8, 0xc3000000, 0xc5f04018, 0xc2400000, 0xc5e50038, 0x7e412000,
+ 0x76250000, 0xce0000f8, 0xc0004980, 0x40300000, 0xcec000f8, 0xc161fffe, 0x5955fffe, 0x14140000,
+ 0x00000000, 0xc000496a, 0xca4000f8, 0xc2000002, 0x6a2d0000, 0x7e010000, 0x76612000, 0xce4000f8,
+ 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000, 0x6ef4a000, 0x6ed44000, 0x4755a000, 0x476da000,
+ 0x5b747000, 0x5834000e, 0xc2000000, 0xca0000d8, 0x58340008, 0xc2400000, 0xca420078, 0x5834000c,
+ 0xc2800000, 0xca832010, 0x6e644010, 0x42250000, 0x4229e000, 0xc39a8008, 0x58340008, 0xcb809018,
+ 0x58340008, 0xc2800000, 0xca810010, 0x6ee0a000, 0x6ee44000, 0x46250000, 0x462d0000, 0x5a200008,
+ 0x5a203008, 0x42290000, 0xc6380060, 0xc6f81c18, 0x99005b78, 0xdb9800f8, 0xdbd800f9, 0x00000000,
+ 0xc000495a, 0xc84000f8, 0x00000000, 0xc3c00002, 0x787c2000, 0xcc4000f8, 0xc0001a1c, 0xca0000f8,
+ 0xc2400008, 0x6a452000, 0x76250000, 0x84000ec2, 0xc0000a28, 0xc3800000, 0xcb840028, 0xc0000a14,
+ 0xc3400000, 0xcb440028, 0xc0004880, 0xcb0400f8, 0xb7b40072, 0x58041802, 0xcac000f8, 0xa7000078,
+ 0x00000000, 0x00000000, 0xa6c8d808, 0xc1000000, 0xc6d00018, 0xc0004980, 0x40100000, 0xca8000f8,
+ 0x80000070, 0x00000000, 0x00000000, 0x00000000, 0x8000d7b8, 0x00000000, 0xc2800000, 0xc7282018,
+ 0xc000490e, 0xca4000f8, 0x6be9e000, 0x00000000, 0x767d2000, 0x8400d770, 0x6ea0a000, 0x6e944000,
+ 0x46150000, 0x46290000, 0x5a207000, 0x5820000c, 0xca0000f8, 0xc0004946, 0xce8000f8, 0xa62203a8,
+ 0x00000000, 0xc2200060, 0xc0004948, 0xce000008, 0xce021038, 0xc240000a, 0xc000494a, 0xce4000f8,
+ 0xc2b60002, 0xc0004964, 0xce837b00, 0x99005e48, 0xc00048a0, 0xc88400f8, 0x00000000, 0xc0004946,
+ 0xcbc000f8, 0x00000000, 0x00000000, 0x6ff8a000, 0x6fd44000, 0x4795c000, 0x47bdc000, 0x5bb87000,
+ 0x99005c08, 0xdbd800f8, 0xdb9800f9, 0x00000000, 0x99005950, 0xc000491c, 0xc1400000, 0xc9420048,
+ 0xc000491c, 0x99005e00, 0xc94000f9, 0xc98000f8, 0x00000000, 0x99005b78, 0xd95800f8, 0xd99800f9,
+ 0x00000000, 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0x99005840, 0xdbd800f8, 0xdb9800f9,
+ 0xc7d800f8, 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000, 0x6ff8a000, 0x6fd44000, 0x4795c000,
+ 0x47bdc000, 0x5bb87000, 0x58380010, 0xca0000f8, 0xc0004874, 0xc80400f8, 0x6c908000, 0x45088000,
+ 0x45088000, 0x40100000, 0xca4000f8, 0xc43400f8, 0x00000000, 0xc74000f8, 0xce0000f8, 0xc161fffe,
+ 0x5955fffe, 0x14140000, 0x00000000, 0xc000490e, 0xca4000f8, 0xc2800002, 0x6abd4000, 0x72692000,
+ 0xce4000f8, 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000, 0x990062f0, 0xc0004836, 0xc94000f8,
+ 0xc1800002, 0x00000000, 0x00000000, 0x00000000, 0xa8e2ffe8, 0x00000000, 0x58380000, 0xc90000f8,
+ 0xc00049a0, 0xca0000f8, 0xc2800000, 0xc5290038, 0x72290000, 0xce0000f8, 0xc1220002, 0xd90c00f8,
+ 0xc2000000, 0xc0000a14, 0xca040028, 0xc0000a28, 0xc2500002, 0xce450800, 0x58880002, 0xb6080018,
+ 0xc00048a0, 0xc0800000, 0xcc8400f8, 0x8000d380, 0xc0004946, 0xcbc000f8, 0xc161fffe, 0x5955fffe,
+ 0x14140000, 0x00000000, 0xc000490e, 0xca4000f8, 0xc2800002, 0x6abd4000, 0x72692000, 0xce4000f8,
+ 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000, 0x6ff8a000, 0x6fd44000, 0x4795c000, 0x47bdc000,
+ 0x5bb87000, 0x58380008, 0xca0000f8, 0x5838000c, 0xca4000f8, 0xc3400000, 0xc6340000, 0xc000494e,
+ 0xcf4000f8, 0xc2800000, 0xc62a0078, 0xc3000000, 0xc6308018, 0x6f304000, 0x43298000, 0xc000493c,
+ 0xcf0000f8, 0xc2c00000, 0xc66c0078, 0xc0004950, 0xcec000f8, 0xc2800000, 0xc66ae020, 0xc0004954,
+ 0xce8000f8, 0x5f740000, 0x840001a0, 0x5e300028, 0x46e12000, 0x8400016a, 0x46e12000, 0x88000132,
+ 0x5e300018, 0x46e12000, 0x8800002a, 0x46e12000, 0x84000042, 0x00000000, 0x800000c0, 0x00000000,
+ 0x99005f88, 0xdbd800f8, 0xdb9800f9, 0xc78000f8, 0xc3400002, 0xc000494e, 0xcf4000f8, 0xc161fffe,
+ 0x5955fffe, 0x14140000, 0x00000000, 0xc000490e, 0xca4000f8, 0xc2800002, 0x6abd4000, 0x7e814000,
+ 0x76692000, 0xce4000f8, 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000, 0xc2200060, 0xc0004948,
+ 0xce021038, 0xc2000000, 0xc000494c, 0xce0000f8, 0x80000080, 0x00000000, 0x99005f88, 0xdbd800f8,
+ 0xdb9800f9, 0xc78000f8, 0x99006188, 0xdbd800f8, 0xdb9800f9, 0xc78000f8, 0xc2200058, 0xc0004948,
+ 0xce021038, 0xc2000002, 0xc000494c, 0xce0000f8, 0xc2000006, 0xc0001006, 0xce0000f8, 0x5838000a,
+ 0xca4000f8, 0xc2200982, 0x5a203b6e, 0xc0001008, 0xce0000f8, 0xc000100a, 0xce4000f8, 0xc0004954,
+ 0xca8000f8, 0xc200000c, 0xc000494a, 0xce0000f8, 0xc0004948, 0xce800008, 0xc2b60000, 0xc0004964,
+ 0xce8000f8, 0x99005e48, 0xc00048a0, 0xc88400f8, 0x00000000, 0xc0004946, 0xcbc000f8, 0xc000494c,
+ 0xca0000f8, 0x6ff8a000, 0x6fd44000, 0x4795c000, 0x47bdc000, 0x5bb87000, 0x5e200000, 0x840000fa,
+ 0x00000000, 0x99005c08, 0xdbd800f8, 0xdb9800f9, 0x00000000, 0x99005950, 0xc000491c, 0xc1400000,
+ 0xc9420048, 0xc000491c, 0x99005e00, 0xc94000f9, 0xc98000f8, 0x00000000, 0x99005b78, 0xd95800f8,
+ 0xd99800f9, 0x00000000, 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0x99005840, 0xdbd800f8,
+ 0xdb9800f9, 0xc7d800f8, 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000, 0xc000493c, 0xca8000f8,
+ 0xc000494e, 0xcac000f8, 0xc3000018, 0xc3400006, 0x5e200000, 0x8400002a, 0xc2800000, 0xc2c00000,
+ 0xc300001e, 0xc3400000, 0xc6ac1078, 0xc72c0418, 0xc76c0810, 0x58380010, 0xca8000f8, 0x58380008,
+ 0xcec000f8, 0xc6280100, 0xc0004874, 0xc80400f8, 0x6c908000, 0x45088000, 0x45088000, 0x40100000,
+ 0xcb0000f8, 0xc43400f8, 0x00000000, 0xc74000f8, 0xce8000f8, 0xc0004952, 0xce8000f8, 0x00000000,
+ 0x00000000, 0x00000000, 0xa8e2ffe8, 0x00000000, 0xc000494c, 0xca0000f8, 0xc0004950, 0xcac000f8,
+ 0x5e200000, 0x8400006a, 0xdfe800f8, 0x7e814000, 0x5834001a, 0xce8000f8, 0x990062f0, 0xc0004834,
+ 0xc94000f8, 0xc1800002, 0x990062f0, 0xc0004838, 0xc94000f8, 0xc6d800f8, 0xc1220002, 0xd90c00f8,
+ 0x5e200000, 0x84000040, 0x5838002c, 0xcb0000f8, 0xdfe800f8, 0x00000000, 0x58380014, 0xcf0000f8,
+ 0x80000058, 0xc2a1fffe, 0x5aa9fffe, 0x58380000, 0xc90000f8, 0xc00049a0, 0xcb0000f8, 0xc2c00000,
+ 0xc52d0038, 0x732d8000, 0xcf0000f8, 0x5838000a, 0xce8000f8, 0xc3000000, 0xc0000a14, 0xcb040028,
+ 0xc2d00002, 0xc0000a28, 0xcec50800, 0xc000494e, 0xca8000f8, 0x58880002, 0xb4b00018, 0xc00048a0,
+ 0xc0800000, 0xcc8400f8, 0x5ea80000, 0x8400017a, 0x5e200000, 0x84000168, 0xc000493c, 0xca8000f8,
+ 0x00000000, 0x00000000, 0x5aa80060, 0xce8000f8, 0x99005f88, 0xdbd800f8, 0xdb9800f9, 0xc78000f8,
+ 0x99006188, 0xdbd800f8, 0xdb9800f9, 0xc78000f8, 0x58380000, 0xcac000f8, 0x00000000, 0xc2000000,
+ 0xc6e04018, 0xc0004952, 0xcac000f8, 0x58380000, 0xca8000f8, 0xc30c0002, 0xc6300018, 0xa6800098,
+ 0x00000000, 0x00000000, 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0xc0001800, 0xca0000f8,
+ 0x00000000, 0x00000000, 0xa60cffea, 0xc6f00500, 0xc6b0c400, 0xcf0000f8, 0x00000000, 0xc121fffe,
+ 0x5911fe14, 0x14100000, 0x8000c9c8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000c960,
+ 0xdcbc00f9, 0x5ffc0000, 0x84000052, 0xc3800002, 0xdb8800f9, 0x5ffc0004, 0x8400c292, 0xc3800000,
+ 0xdb8800f9, 0xc3ce0002, 0xc0000800, 0xcfc0e700, 0xc3e1fffe, 0x597dfffe, 0x593dfe14, 0x94000001,
+ 0x00000000, 0x00000000, 0x00000000, 0xc000487c, 0xc80400f8, 0x00000000, 0x00000000, 0x40080000,
+ 0xcbc000f8, 0xc43800f8, 0x00000000, 0xc000480e, 0xca0000f8, 0xc0004858, 0xcb4400f8, 0x00000000,
+ 0x00000000, 0x47610000, 0x880000b0, 0x00000000, 0xa7c00048, 0xc0004854, 0xc1000002, 0xcd0400f8,
+ 0xc11c0000, 0xc000082c, 0xcd05ce00, 0x800000d8, 0x00000000, 0xa7d20138, 0x00000000, 0xc7e14040,
+ 0xc2400000, 0xc6246028, 0xc200006a, 0x46250000, 0xc6240030, 0xc0000810, 0xce440030, 0x8000ff70,
+ 0xc2000000, 0xc0000808, 0xca040010, 0xc11c0000, 0xc000082c, 0xcd05ce00, 0x5a200002, 0x5e600010,
+ 0x84000010, 0xc2000000, 0xc0000808, 0xce040010, 0xc3400000, 0x80000028, 0xc1200002, 0xc0000818,
+ 0xcd061000, 0x5b740002, 0xc0004858, 0xcf4400f8, 0x99005590, 0xc0004848, 0xc94400f8, 0xc1800000,
+ 0xc11c0002, 0xc000082c, 0xcd05ce00, 0x80000600, 0x5b740002, 0xc0004858, 0xcf4400f8, 0xc78000f8,
+ 0xc13c0002, 0xcd03de00, 0xc0004848, 0xc94400f8, 0xc1800000, 0xc000082c, 0xc9840028, 0x59540002,
+ 0xc0004848, 0xcd4400f8, 0x58880002, 0xb4980580, 0x00000000, 0xc0800000, 0x80000568, 0xc000487c,
+ 0xc80400f8, 0x00000000, 0x00000000, 0x40080000, 0xcbc000f8, 0xc42800f8, 0x00000000, 0xa7c00130,
+ 0xc000484c, 0xca0400f8, 0xc2400000, 0xc0001aec, 0xca440018, 0x5a200002, 0xc000484c, 0xce0400f8,
+ 0xb624008a, 0xc68000f8, 0xc13c0002, 0xcd03de00, 0xc0004848, 0xc94400f8, 0xc1800000, 0xc000082c,
+ 0xc9840028, 0x59540002, 0xc0004848, 0xcd4400f8, 0x58880002, 0xb4980470, 0x00000000, 0xc0800000,
+ 0x80000458, 0xc0004854, 0xc1000004, 0xcd0400f8, 0xc0000820, 0xc2000002, 0xce0400f8, 0xc2000000,
+ 0xc000484c, 0xce0400f8, 0xc0004858, 0xce0400f8, 0x8000ff28, 0xc0004854, 0xc1000000, 0xcd0400f8,
+ 0xc11c0000, 0xc000082c, 0xcd05ce00, 0x99005590, 0xc0004848, 0xc94400f8, 0xc1800000, 0xc1200000,
+ 0xc0000818, 0xcd061000, 0xc11c0002, 0xc000082c, 0xcd05ce00, 0xc2000000, 0xc000484c, 0xce0400f8,
+ 0x80000358, 0xc0001ac0, 0xcb8400f8, 0xc000487c, 0xc80400f8, 0x00000000, 0x00000000, 0x40080000,
+ 0xcbc000f8, 0xc42800f8, 0x00000000, 0x00000000, 0xc68000f8, 0xc13c0000, 0xcd03de00, 0xa780024a,
+ 0x00000000, 0x00000000, 0xa7c0020a, 0x00000000, 0xc0001b00, 0xc2060006, 0xce046308, 0xa7e801c2,
+ 0x00000000, 0xc0004850, 0xca0400f8, 0xc2400000, 0xc0001aec, 0xca448018, 0x5a200002, 0xc0004850,
+ 0xce0400f8, 0xb62400aa, 0x00000000, 0xc68000f8, 0xc13c0002, 0xcd03de00, 0xc0001acc, 0xc2000002,
+ 0xce040000, 0xc0004848, 0xc94400f8, 0xc1800000, 0xc000082c, 0xc9840028, 0x59540002, 0xc0004848,
+ 0xcd4400f8, 0x58880002, 0xb49801c8, 0x00000000, 0xc0800000, 0x800001b0, 0xc0004854, 0xc1000000,
+ 0xcd0400f8, 0xc11c0000, 0xc000082c, 0xcd05ce00, 0x99005590, 0xc0004848, 0xc94400f8, 0xc1800000,
+ 0xc2000000, 0xc0000820, 0xce0400f8, 0xc1200000, 0xc0000818, 0xcd061000, 0xc11c0002, 0xc000082c,
+ 0xcd05ce00, 0xc0004850, 0xce0400f8, 0xc2000002, 0xc0001acc, 0xce040008, 0x800000e8, 0xc2000002,
+ 0xc0004850, 0xce0400f8, 0x8000fe88, 0xc2000000, 0xc0004850, 0xce0400f8, 0xa7e60032, 0x00000000,
+ 0xc2000002, 0xc0001b00, 0xce040000, 0x8000fe70, 0x00000000, 0xa7860052, 0x00000000, 0xc68000f8,
+ 0xc13c0002, 0xcd03de00, 0xc2020002, 0xc7e2a540, 0xc0001b00, 0xce0400f8, 0x8000fe18, 0xc2040002,
+ 0xc0001b00, 0xce044200, 0x8000fdf8, 0xc2c80002, 0x6ac56000, 0xdacc00f8, 0xc0004854, 0xcb4400f8,
+ 0xc0004848, 0xcb8400f8, 0xc0000838, 0xc3c00000, 0xcbc40028, 0x5ef40004, 0x84000022, 0xc3000000,
+ 0xc0001acc, 0xcf042100, 0x47f98000, 0x8400002a, 0x47f98000, 0x88000030, 0xc1006e8c, 0x8000b6c8,
+ 0xc0004840, 0xcc8400f8, 0x8000f6b0, 0xc0001ac0, 0xcac400f8, 0xc0004854, 0xcb4400f8, 0xa6c0fbd2,
+ 0x00000000, 0x5ef40000, 0x8400f70a, 0x5ef40002, 0x8400f99a, 0x5ef40004, 0x8400fb9a, 0xc1006ce8,
+ 0x8000b640, 0x00000000, 0xc0800000, 0xdf4b0038, 0xc0004900, 0xcb8000f8, 0xc2000000, 0xc000490a,
+ 0xa78000d0, 0xcbc000f8, 0xc1000000, 0xd90000f9, 0xc1000002, 0xd90c00f8, 0x6ff46000, 0x477da000,
+ 0x5b744c80, 0xc2400000, 0x58340004, 0xca400078, 0xc0004900, 0xce000000, 0x5a640002, 0x58340004,
+ 0xc6500078, 0xcd000078, 0xc0004914, 0xca4000f8, 0xc2000002, 0x6a3d0000, 0x72612000, 0xce4000f8,
+ 0xc0000408, 0xce0000f8, 0xa78200d8, 0xc0004908, 0xcbc000f8, 0xc1000000, 0xd90000f9, 0xc1000002,
+ 0xd90c00f8, 0x6ff4a000, 0x6fd44000, 0x4755a000, 0x477da000, 0x5b747000, 0xc2800000, 0x58340006,
+ 0xca800078, 0xc2000000, 0xc0004900, 0xce002100, 0x5ea80002, 0x58340006, 0xc6900078, 0xcd000078,
+ 0x5a7c0020, 0xc2000002, 0x6a250000, 0xc0000408, 0xce0000f8, 0xdca800f9, 0x5ea80000, 0x8400b4b0,
+ 0x00000000, 0xa4800230, 0x00000000, 0xc3c00000, 0xc000140e, 0xcbc00018, 0xc3400000, 0xc2400000,
+ 0x6ff86000, 0x47bdc000, 0x5bb84c80, 0x58380008, 0xcb400078, 0x58380006, 0xca400078, 0x5f740002,
+ 0x58380008, 0xc7500078, 0xcd000078, 0xc2000000, 0x58380004, 0xca020078, 0xc3000000, 0x5838000c,
+ 0xcb000020, 0x5a640002, 0x46610000, 0x84000010, 0xc2400000, 0x58380006, 0xc6500078, 0xcd000078,
+ 0xc2000000, 0x5838000a, 0xca020078, 0x5b300002, 0x5838000c, 0xc7100020, 0xcd000020, 0xc2420020,
+ 0x5a200004, 0x46252000, 0x84000010, 0xc2000000, 0x5838000a, 0xc6101078, 0xcd021078, 0xc0004966,
+ 0xca4000f8, 0xc2000002, 0x6a3d0000, 0x72612000, 0xce4000f8, 0x5f740000, 0x84000040, 0xc0004912,
+ 0xca0000f8, 0xc2c00002, 0x6afd6000, 0x7ec16000, 0x762d0000, 0xce0000f8, 0x5f300020, 0x84000040,
+ 0xc0004924, 0xca0000f8, 0xc2c00002, 0x6afd6000, 0x7ec16000, 0x762d0000, 0xce0000f8, 0xa4820070,
+ 0xc2400000, 0xc000140e, 0xca408018, 0xc2000002, 0xc0004900, 0xce000000, 0xc000490a, 0xce4000f8,
+ 0xc1000000, 0xd90000f9, 0xd8400078, 0xc1000004, 0xd90000f9, 0xa4840270, 0x00000000, 0xc3c00000,
+ 0xc000140e, 0xcbc10018, 0xc2800000, 0xc2000000, 0x6ff8a000, 0x6fd44000, 0x4795c000, 0x47bdc000,
+ 0x5bb87000, 0x5838002e, 0xca800078, 0x58380006, 0xca020078, 0xc3400000, 0x5838002e, 0xcb420078,
+ 0x5aa80002, 0x46a10000, 0x84000010, 0xc2800000, 0x5838002e, 0xc6900078, 0xcd000078, 0x5f740002,
+ 0x5838002e, 0xc7501078, 0xcd021078, 0xc0004968, 0xca4000f8, 0xc2000002, 0x6a3d0000, 0x72612000,
+ 0xce4000f8, 0xc000492a, 0xca8000f8, 0x5e740000, 0x84000040, 0xc0004910, 0xca0000f8, 0xc2c00002,
+ 0x6afd6000, 0x7ec16000, 0x762d0000, 0xce0000f8, 0x6abd4010, 0xa68000ba, 0x00000000, 0x58380032,
+ 0xca0000f8, 0x58000002, 0xca4000f8, 0x5838000c, 0x00000000, 0xce0000f9, 0xce4000f8, 0xc000492a,
+ 0xca0000f8, 0xc2c00002, 0x6afd6000, 0x722d0000, 0xce0000f8, 0xc000492c, 0xca0000f8, 0xc2c00002,
+ 0x6afd6000, 0x722d0000, 0xce0000f8, 0x80000040, 0xc000492c, 0xca0000f8, 0xc2c00002, 0x6afd6000,
+ 0x7ec16000, 0x762d0000, 0xce0000f8, 0xa4880148, 0xc2c00000, 0xc000140e, 0xcac20018, 0xc000490e,
+ 0xca4000f8, 0xc2000002, 0x6a2d0000, 0x7e010000, 0x76612000, 0xce4000f8, 0xc000496a, 0xca4000f8,
+ 0xc2000002, 0x6a2d0000, 0x72612000, 0xce4000f8, 0x6ef0a000, 0x6ed44000, 0x47158000, 0x472d8000,
+ 0x5b307000, 0x58300000, 0xca0000f8, 0x00000000, 0xc2400002, 0x76612000, 0x84000072, 0x58300000,
+ 0xca4000f8, 0xc2800000, 0x00000000, 0xc6684018, 0xc24c0002, 0xc6a40018, 0xc624c400, 0x58300010,
+ 0xca400500, 0x00000000, 0xc0001800, 0xce4000f8, 0xa4860070, 0xc2400000, 0xc000140e, 0xca418018,
+ 0xc2020002, 0xc0004900, 0xce002100, 0xc0004908, 0xce4000f8, 0xc1000000, 0xd90000f9, 0xd8400078,
+ 0xc1000004, 0xd90000f9, 0xc0001408, 0xcc8000f8, 0xc10e0002, 0xd90c00f8, 0x8000edb0, 0xdfbc00f9,
+ 0xc000496e, 0x99006298, 0xc94000f8, 0xc7d800f8, 0x00000000, 0xc57000f8, 0x5ef00020, 0x88000148,
+ 0x6f346000, 0x4771a000, 0x5b744c80, 0x58340008, 0xc2400000, 0xca400078, 0x00000000, 0xc2000000,
+ 0x5a640002, 0xce400078, 0x58340004, 0xca000078, 0x00000000, 0x00000000, 0x5e200002, 0xce000078,
+ 0xc0004912, 0xca8000f8, 0xc2400002, 0x6a712000, 0x72a54000, 0xce8000f8, 0x5e200000, 0x84000052,
+ 0xc000480a, 0xca0000f8, 0xc0000408, 0xca8000f8, 0x76250000, 0x00000000, 0x72a14000, 0xce8000f8,
+ 0x80000038, 0xc0004914, 0xca0000f8, 0x7e412000, 0x00000000, 0x76250000, 0xce0000f8, 0x800000d0,
+ 0x6ef4a000, 0x6ed44000, 0x4755a000, 0x476da000, 0x5b747000, 0x5834002e, 0xc2400000, 0xca420078,
+ 0x00000000, 0xc2000000, 0x5a640002, 0xc6501078, 0xcd021078, 0x58340006, 0xca000078, 0x00000000,
+ 0x00000000, 0x5a200002, 0xce000078, 0xc0004910, 0xca4000f8, 0xc2000002, 0x6a2d0000, 0x72612000,
+ 0xce4000f8, 0xc2000002, 0x6a310000, 0xc000042a, 0xce0000f8, 0xc1040002, 0xd90c00f8, 0x00000000,
+ 0x8000eb20, 0x00000000, 0xc4980928, 0x9d000000, 0xc5580028, 0xc0000838, 0xcd8400f8, 0xc1440200,
+ 0xc1c03800, 0xc55c1070, 0xc000100e, 0x9d000000, 0xcd8000f8, 0xc000100c, 0xcdc000f8, 0xc0004862,
+ 0xc9c000f8, 0x00000000, 0x00000000, 0xd9d800f9, 0xc0007800, 0x401c0000, 0x5dc07a00, 0x88000012,
+ 0x5c000200, 0xcd8000f8, 0xc1f0000a, 0x715ca000, 0xdd9800f8, 0xdd9c00f9, 0x41d8e000, 0xc5d40260,
+ 0xc0001010, 0xcd4000f8, 0x6c9c8000, 0x45c8e000, 0x45c8e000, 0x59dc0004, 0xc1601260, 0xc5d40260,
+ 0x9d000000, 0xc0001012, 0xcd4000f8, 0x00000000, 0x00000000, 0xd95800f8, 0x6d586000, 0x4594c000,
+ 0x59984c80, 0xd99800f9, 0x5818000a, 0xc1800000, 0xc9800078, 0xc0006e00, 0x6d5ca000, 0x401c0000,
+ 0x40180000, 0xc94000f8, 0x58000002, 0x00000000, 0xc9c000f8, 0xc0004930, 0xcd4000f8, 0xc0004932,
+ 0xcdc000f8, 0x59980004, 0xc1c20020, 0xb59c0018, 0x00000000, 0xc1800000, 0xdd9c00f9, 0x581c000a,
+ 0xcd800078, 0x581c000c, 0xc1800000, 0xc9800020, 0xc1c00002, 0xdd9400f8, 0x69d4e000, 0x5d980002,
+ 0xcd800020, 0xc0004924, 0xc98000f8, 0x00000000, 0x9d000000, 0x00000000, 0x719cc000, 0xcd8000f8,
+ 0xc000492a, 0xc94000f8, 0xc1c00002, 0x69d8e000, 0x7dc0c000, 0x7558a000, 0xcd4000f8, 0xc000492c,
+ 0xc94000f8, 0xdd8000f9, 0x58000032, 0x755ca000, 0x84000090, 0xc94000f9, 0xc98000f8, 0xdd8000f9,
+ 0x5800000c, 0x00000000, 0xcd4000f9, 0xcd8000f8, 0xc000492c, 0xc94000f8, 0xc000492a, 0xc98000f8,
+ 0x715ca000, 0xc000492c, 0xcd4000f8, 0x719cc000, 0xc000492a, 0xcd8000f8, 0x9d000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xc0004862, 0xc98000f8, 0x00000000, 0xc1c00200, 0x4194c000, 0x459ce000,
+ 0x88000012, 0xc5d800f8, 0xc0004862, 0xcd8000f8, 0xc0001406, 0xc98000f8, 0xc1c00002, 0x9d000000,
+ 0xc5d80a00, 0xc5581048, 0xcd8000f8, 0xc0004930, 0xc98000f8, 0xc0004932, 0xc9c000f8, 0xc140000e,
+ 0xc5581c18, 0xdd9400f8, 0xc0007800, 0x40140000, 0x5d407a00, 0x88000012, 0x5c000200, 0xcd8000f8,
+ 0x58000002, 0x5d407a00, 0x88000012, 0x5c000200, 0xcdc000f8, 0xdd5400f8, 0xc1c00000, 0x58140006,
+ 0xc9c20078, 0xc1800000, 0x58140000, 0xc98000d8, 0x6ddc2000, 0xc000491e, 0x41d8e000, 0xcdc000f8,
+ 0xdd9800f8, 0xc1c00022, 0xc5d80d70, 0xdd9400f9, 0xc5581c18, 0xc000491c, 0xcd8000f8, 0xdd5400f8,
+ 0xc1c00000, 0x58140006, 0xc9c20078, 0xc1800000, 0x58140004, 0xc9820078, 0x00000000, 0x59dc0002,
+ 0x45d8c000, 0x84000010, 0xc1c00000, 0x9d000000, 0x58140006, 0xc5d81078, 0xcd821078, 0xc0004860,
+ 0xc94000f8, 0xc1820080, 0xc1d00002, 0x58147700, 0xd58000f8, 0x58000002, 0xd58000f9, 0x59540004,
+ 0xb5580018, 0xc0004860, 0xc1400000, 0xcd4000f8, 0xdd9800f9, 0x9d000000, 0xdd9400f8, 0xc0001404,
+ 0xcdc10800, 0xc1c00000, 0xc1800200, 0x5d980004, 0xdf5d0048, 0x459ca000, 0x8800fff2, 0xdd8000f9,
+ 0x5800000c, 0x00000000, 0xc94000f9, 0xc98000f8, 0xc1c00002, 0xc5d43f00, 0xc5d81e00, 0xc0004862,
+ 0xc9c000f8, 0x00000000, 0x00000000, 0x581c7800, 0x5dc07a00, 0x88000012, 0x5c000200, 0xcd4000f8,
+ 0x58000002, 0x5dc07a00, 0x88000012, 0x5c000200, 0xcd8000f8, 0xc0004862, 0xc9c000f8, 0x00000000,
+ 0xc15004c0, 0xc5d40060, 0xdd9c00f8, 0xc5d41c18, 0xc1c00000, 0xdd8000f9, 0x58000030, 0xc9c00078,
+ 0xdd8000f9, 0x58000002, 0xc98000f8, 0x6ddc2000, 0xc000491c, 0x41d8e000, 0xcd4000f9, 0xcdc000f8,
+ 0xdd9400f9, 0xc1c00000, 0x58140030, 0xc9c00078, 0xc1800000, 0x58140006, 0xc9820078, 0x00000000,
+ 0x59dc0002, 0x45d8c000, 0x84000010, 0xc1c00000, 0x9d000000, 0x58140030, 0xc5d80078, 0xcd800078,
+ 0xc1c00000, 0xdf5c0038, 0x5ddc0080, 0x8400ffea, 0x00000000, 0x9d000000, 0x00000000, 0x00000000,
+ 0x00000000, 0xc160fffe, 0xc0000a10, 0xc9440060, 0xc1a0fffe, 0x59983008, 0xc000100c, 0xcd4000f8,
+ 0xc000100e, 0xcd8000f8, 0xc0004964, 0xc98000f8, 0x00000000, 0xc170000a, 0x7158a000, 0x6c988000,
+ 0x4588c000, 0x4588c000, 0x59980004, 0xc5940270, 0xc0001010, 0xcd4000f8, 0xc0004946, 0xc94000f8,
+ 0x00000000, 0x00000000, 0x6d58a000, 0x6d5c4000, 0x459cc000, 0x4594c000, 0xc000494a, 0xc94000f8,
+ 0xc0004948, 0xc9c000f8, 0x4194c000, 0xc1400012, 0xc55c1818, 0x9d000000, 0xc59c0268, 0xc0001012,
+ 0xcdc000f8, 0xc1400000, 0x58000012, 0xc9410038, 0xc0004950, 0xc9c000f8, 0xc55800f8, 0xc5940838,
+ 0xc5581078, 0xd99400f8, 0xc000493c, 0xc94000f8, 0xc0004954, 0xc98000f8, 0x59dc00a8, 0x45d4e000,
+ 0x41d8e000, 0x5d5c0030, 0x88000010, 0xc1c00030, 0xc1800000, 0xc5d84028, 0xc1400000, 0xc5d40008,
+ 0x5dd40002, 0x84000072, 0x5dd40004, 0x8400009a, 0x5dd40006, 0x840000c2, 0x5dd80026, 0x840000ea,
+ 0xdd5400f8, 0xdd8000f9, 0x58000008, 0x40180000, 0xcd4000f8, 0x59980002, 0x8000ffc0, 0xdd5400f8,
+ 0xdd8000f9, 0x58000008, 0x40180000, 0xcd4000b8, 0x59980002, 0x8000ff88, 0xdd5400f8, 0xdd8000f9,
+ 0x58000008, 0x40180000, 0xcd400078, 0x59980002, 0x8000ff50, 0xdd5400f8, 0xdd8000f9, 0x58000008,
+ 0x40180000, 0xcd400038, 0x59980002, 0x8000ff18, 0x00000000, 0x9d000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x58000012, 0xc94000f8, 0xc0004954, 0xc9c000f8, 0xc0004950, 0xc9400078, 0xdd8000f9,
+ 0x58000028, 0x5d9c0000, 0x84000052, 0x5d9c0002, 0x84000052, 0x5d9c0004, 0x8400006a, 0xc55b0038,
+ 0xc55c08b8, 0xcd800039, 0xcdc108b8, 0x80000060, 0xcd4000f8, 0x80000050, 0xc55900b8, 0xc55c1838,
+ 0xcd8000b9, 0xcdc31838, 0x80000028, 0xc55a0078, 0xc55c1078, 0xcd800079, 0xcdc21078, 0x9d000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x59540002, 0x6994e018, 0x61c0c008, 0x4194a000, 0x5d940040,
+ 0x88000012, 0xc59400f8, 0x9d000000, 0xcd4000f8, 0x00000000, 0x00000000, 0x9d000000, 0x4158a000,
+ 0xcd4000f8, 0x00000000,
+};
+
+static unsigned int firmware_binary_data[] = {
+};
+
+
+#endif // IFXMIPS_ATM_FW_AR9_H
diff --git a/package/ltq-dsl/src/ifxmips_atm_fw_ar9_retx.h b/package/ltq-dsl/src/ifxmips_atm_fw_ar9_retx.h
new file mode 100644
index 000000000..0fc478935
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_fw_ar9_retx.h
@@ -0,0 +1,611 @@
+#ifndef IFXMIPS_ATM_FW_AR9_H
+#define IFXMIPS_ATM_FW_AR9_H
+
+
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_fw_ar9.h
+** PROJECT : UEIP
+** MODULES : ATM (ADSL)
+**
+** DATE : 22 OCT 2007
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM Driver (PP32 Firmware)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 22 OCT 2007 Xu Liang Initiate Version, v00.01
+*******************************************************************************/
+
+
+#define VER_IN_FIRMWARE 1
+
+#define ATM_FW_VER_MAJOR 0
+#define ATM_FW_VER_MINOR 15
+
+
+static unsigned int firmware_binary_code[] = {
+ 0x800004B8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000FFE0, 0x00000000, 0x00000000, 0x00000000,
+ 0xC1000002, 0xD90C00F8, 0xC2000002, 0xDA0800F9, 0xC0001B50, 0x8C100000, 0x00000000, 0x00000000,
+ 0x00000000, 0xC2000000, 0xDA0800F9, 0x80006030, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x80006008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC1001DA6, 0x8D3C0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x80005F08, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0400000, 0xC0004840, 0xC88400F8, 0xC2001AEE, 0x8E100000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0400002, 0xC0004840, 0xC88400F8, 0xC2001AEE, 0x8E100000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC3C00004, 0xDBC800F9, 0xC10C0002, 0xD90C00F8, 0x8000FEE0, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC10E0002, 0xD90C00F8, 0xC0004808, 0xC84000F8, 0xC2001B4C, 0x8E100000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC3E1FFFE, 0x597DFFFE, 0x593DFE14, 0x900004D9, 0x00000000, 0x00000000, 0x00000000, 0x90CC0481,
+ 0x00000000, 0x00000000, 0x00000000, 0xC3E0A252, 0x5BFC001E, 0xC0004002, 0xCFC000F8, 0xC3C00000,
+ 0xDBC800F9, 0xC1400008, 0xC1900000, 0x71588000, 0x14100100, 0xC140000A, 0xC1900002, 0x71588000,
+ 0x14100100, 0xC140000C, 0xC1900004, 0x71588000, 0x14100100, 0xC1400004, 0xC1900006, 0x71588000,
+ 0x14100100, 0xC1400006, 0xC1900008, 0x71588000, 0x14100100, 0xC140000E, 0xC190000A, 0x71588000,
+ 0x14100100, 0xC1400000, 0xC190000C, 0x71588000, 0x14100100, 0xC1400002, 0xC190000E, 0x71588000,
+ 0x14100100, 0xC0400000, 0xC11C0000, 0xC000082C, 0xCD05CE00, 0xC11C0002, 0xC000082C, 0xCD05CE00,
+ 0xC0400002, 0xC11C0000, 0xC000082C, 0xCD05CE00, 0xC0000824, 0x00000000, 0xCBC000F9, 0xCB8000F9,
+ 0xCB4000F9, 0xCB0000F8, 0xC0004878, 0x5BFC4000, 0xCFC000F9, 0x5BB84000, 0xCF8000F9, 0x5B744000,
+ 0xCF4000F9, 0x5B304000, 0xCF0000F8, 0xC0000A10, 0x00000000, 0xCBC000F9, 0xCB8000F8, 0xC0004874,
+ 0x5BFC4000, 0xCFC000F9, 0x5BB84000, 0xCF8000F8, 0xC30001FE, 0xC000140A, 0xCF0000F8, 0xC3000000,
+ 0x7F018000, 0xC000042E, 0xCF0000F8, 0xC000040E, 0xCF0000F8, 0xC3C1FFFE, 0xC000490E, 0xCFC00078,
+ 0xC000492C, 0xCFC00078, 0xC0004924, 0xCFC00038, 0xC0004912, 0xCFC00038, 0xC0004966, 0xCFC00038,
+ 0xC0004968, 0xCFC00078, 0xC000496A, 0xCFC00078, 0xC3C00000, 0xC2800020, 0xC3000000, 0x7F018000,
+ 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB84A00, 0x5838000A, 0xCF0000F8, 0x5BFC0002, 0xB7E8FFC8,
+ 0x00000000, 0xC3C00000, 0xC2800010, 0x6FF86000, 0x47BDC000, 0x5BB84C80, 0xC3400000, 0x58380004,
+ 0xCB420078, 0x00000000, 0x58380008, 0xCF400078, 0x5BFC0002, 0xB7E8FFB0, 0x00000000, 0xC3C00000,
+ 0xC2800020, 0xC348001E, 0xC3000000, 0x7F018000, 0x6FF8A000, 0x6FD44000, 0x4795C000, 0x47BDC000,
+ 0x5BB87000, 0x58380008, 0xCF408418, 0x5838000A, 0xCF0000F8, 0x5BFC0002, 0xB7E8FFB0, 0x00000000,
+ 0x00000000, 0xC0004816, 0xC3C00000, 0xCBC00078, 0x00000000, 0x00000000, 0xC1000000, 0xD90400F9,
+ 0xDBC40078, 0xC1000006, 0xD90400F9, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0xC3C00000,
+ 0xDCFC2000, 0x5FFC0002, 0x00000000, 0x98C08D62, 0xC0004730, 0xC94000F8, 0xC0004732, 0xC0001AF2,
+ 0xCBC000F8, 0x00000000, 0x00000000, 0xA7C20470, 0xC000474A, 0xCA8000F8, 0x00000000, 0x00000000,
+ 0x5D280000, 0x8400FFE0, 0x00000000, 0xC121FFFE, 0x5911FEF4, 0x14100000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC2802000, 0x6EA8E010, 0xC0004200, 0xC2400000, 0x7E410000, 0xC1000000, 0xCE4000F9, 0xCE4000F9,
+ 0xCE4000F9, 0xCE4000F9, 0x5EA80002, 0x8400FFD8, 0xC0004300, 0xC2800200, 0x6EA84010, 0xCE4000F9,
+ 0xCE0000F9, 0xCE4000F9, 0xCE0000F9, 0xCE4000F9, 0xCE0000F9, 0xCE4000F9, 0xCE0000F9, 0x5EA80002,
+ 0x8400FFB8, 0xC0004700, 0xC2800200, 0x6EA8E010, 0xCE4000F9, 0xCE4000F9, 0xCE4000F9, 0xCE4000F9,
+ 0x5EA80002, 0x8400FFD8, 0xC0004740, 0xCE4000F8, 0xC0004742, 0xC1000200, 0x5D100002, 0xCD0000F8,
+ 0xC0004744, 0xCE4000F8, 0xC0004746, 0xCE4000F8, 0xC0004748, 0xCE4000F8, 0xC000474A, 0xCE4000F8,
+ 0xC000474C, 0xC1000002, 0xCD0000F8, 0xC000474E, 0xCE4000F8, 0xC0004750, 0xCE4000F8, 0xC0004752,
+ 0xCE4000F8, 0xC0004754, 0xCE4000F8, 0xC0400000, 0xC11C0000, 0xC000082C, 0xCD05CE00, 0xC0000838,
+ 0xCE4000F8, 0xC0000818, 0xCE4000F8, 0xC0000820, 0xCE4000F8, 0xC2804840, 0xC240485A, 0x98C086B0,
+ 0xC68000F8, 0xC65400F8, 0xC1800000, 0xC11C0002, 0xC000082C, 0xCD05CE00, 0x00000000, 0xC121FFFE,
+ 0x5911FE54, 0x14100000, 0xC0000A10, 0xCB8000F8, 0xC0000A12, 0xCB4000F8, 0xC0000A14, 0xCB0000F8,
+ 0xC0000A16, 0xCAC000F8, 0xC0000040, 0xC2800000, 0xCE800000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC2800002,
+ 0xCE800000, 0xC0000A10, 0xCF8000F8, 0xC0000A12, 0xCF4000F8, 0xC0000A14, 0xCF0000F8, 0xC0000A16,
+ 0xCEC000F8, 0xC1000000, 0xC00048A0, 0xCD0000F8, 0xC00048A2, 0xCD0000F8, 0xC0001AF2, 0xC1000000,
+ 0xCD002100, 0x80001038, 0x00000000, 0xC3C00000, 0xDCFC2000, 0x5FFC0002, 0x00000000, 0x98C08D62,
+ 0xC0004730, 0xC94000F8, 0xC0004732, 0x800033D8, 0x00000000, 0xC3C00000, 0xDCFC2000, 0x5FFC0002,
+ 0x00000000, 0x98C08D62, 0xC0004730, 0xC94000F8, 0xC0004732, 0xC0004810, 0xC90000F8, 0xC000474A,
+ 0xC94000F8, 0xA50007E8, 0x00000000, 0x5D140002, 0x840007D2, 0xC1000000, 0xC000484A, 0xC90000F8,
+ 0xC0004740, 0xC84000F8, 0x5D100000, 0x84000798, 0x00000000, 0x00000000, 0xC121FFFE, 0x5911FEF4,
+ 0x14100000, 0xC0004744, 0xC88000F8, 0xC0001AF0, 0xC3000000, 0x58000002, 0xCB010038, 0x6C7C2000,
+ 0x5BFC4300, 0x98C08A88, 0xC1400000, 0xC4540020, 0x6C40A010, 0x5D240002, 0x8400021A, 0x00000000,
+ 0xC0004742, 0xCA8000F8, 0x00000000, 0x00000000, 0x59280002, 0x6D130000, 0x6D130010, 0x45048000,
+ 0x84000692, 0x00000000, 0x98C08870, 0xC45400F8, 0xC69800F8, 0xC241FFFE, 0xC67400F8, 0x5D35FFFE,
+ 0x84000652, 0x47448000, 0x84000642, 0xC1000000, 0x6F502000, 0xC0004300, 0x40100000, 0xC1400000,
+ 0x58000000, 0xC9410038, 0xC1800000, 0xC0004814, 0xC9820038, 0x4714A000, 0xC10001FE, 0x4150A004,
+ 0x45588000, 0x880005CA, 0x4744C000, 0xC1000200, 0x4190C004, 0xC000473E, 0xC90000F8, 0x00000000,
+ 0x00000000, 0x41188000, 0xCD0000F8, 0xC000471C, 0xC90000F8, 0x00000000, 0x00000000, 0x41188000,
+ 0xCD0000F8, 0x98C087E8, 0xC45400F8, 0x6C58A010, 0xC0004700, 0x58440002, 0x6C470000, 0x6C470010,
+ 0x44748000, 0x8400FFC0, 0xC74400F8, 0xC0004740, 0xCC4000F8, 0xC0800000, 0xC0004744, 0xCC8000F8,
+ 0x800004D0, 0xC1000000, 0x583C0000, 0xC9000038, 0x00000000, 0x00000000, 0x44908000, 0x88000280,
+ 0xC1400000, 0x583C0000, 0xC9410038, 0xC1800000, 0xC0004814, 0xC9800038, 0x4714A000, 0xC10001FE,
+ 0x4150A004, 0x45588000, 0x88000442, 0xC3800000, 0x583C0002, 0xCB820078, 0xC1000000, 0x583C0002,
+ 0xC9000078, 0x00000000, 0x00000000, 0x47908000, 0x8400024A, 0xC0400002, 0xC0800000, 0xC3C00000,
+ 0xC000481A, 0xC80000F8, 0x6F908000, 0x45388000, 0x45388000, 0x4011E000, 0xC000491E, 0xCFC000F8,
+ 0xC3400000, 0xC0004878, 0xC80400F8, 0x6C908000, 0x45088000, 0x45088000, 0x40100000, 0xCAC000F8,
+ 0xC43000F8, 0x00000000, 0xC7340060, 0xC1000002, 0xC5341B00, 0xC100001C, 0xC5341048, 0xC100000C,
+ 0xC5340D10, 0xC000491C, 0xCF4000F8, 0xC3000000, 0xDF700038, 0x5D300080, 0x8800FFE8, 0xC000474A,
+ 0xC1000002, 0xCD0000F8, 0xC000491C, 0xCB4000F8, 0xC000491E, 0xCBC000F8, 0x99007F18, 0xDB5800F8,
+ 0xDBD800F9, 0x00000000, 0xC1400000, 0xC794A030, 0xC1800000, 0xC7980020, 0x58144200, 0xC9C000F8,
+ 0xC1210000, 0x69188010, 0x7D008000, 0x75D0E000, 0xCDC000F8, 0x80000228, 0x00000000, 0xC1000000,
+ 0x583C0000, 0xC903E000, 0x00000000, 0x00000000, 0x5D100000, 0x84000042, 0xC0004734, 0xC90000F8,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x800000C0, 0xC1400000, 0x583C0000, 0xC9410038,
+ 0xC1800000, 0xC0004814, 0xC9820038, 0x4714A000, 0xC10001FE, 0x4150A004, 0x45588000, 0x8800015A,
+ 0xC000473E, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0xC000471C, 0xC90000F8,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0xC3800000, 0x583C0002, 0xCB820078, 0x00000000,
+ 0x00000000, 0x5D39FFFE, 0x84000062, 0xC1400000, 0xC794A030, 0xC1800000, 0xC7980020, 0x58144200,
+ 0xC9C000F8, 0xC1210000, 0x69188010, 0x7D008000, 0x75D0E000, 0xCDC000F8, 0x98C087E8, 0xC45400F8,
+ 0x6C58A010, 0xC0004700, 0x58440002, 0x6C470000, 0x6C470010, 0xC0004740, 0xCC4000F8, 0xC0800000,
+ 0xC0004744, 0xCC8000F8, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0x8000F288, 0x00000000,
+ 0x00000000, 0x98C086F0, 0xC0004748, 0xC98000F8, 0xC2000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xC1400000, 0xC7D4A030, 0xC1800000, 0xC7D80020, 0x58144200,
+ 0xC9C000F8, 0xC1210000, 0x69188010, 0x7D008000, 0x75D0E000, 0xCDC000F8, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x98C087E8, 0xC7D400F8, 0x6FD8A010, 0xC0004700, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x98C08870, 0xC7D400F8, 0xC79800F8, 0xC241FFFE, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x98C08A88, 0xC1400000, 0xC7D40020, 0x6FC0A010,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x98C08AB8, 0xC1400000, 0xC7D40020, 0x6FC0A010,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x98C08AF0, 0xC7D400F8, 0xC0004740, 0xC9C000F8,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x98C08BE0, 0xC7D400F8, 0xC0004742, 0xC98000F8,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC0004958, 0xC84000F8, 0x00000000, 0xC3C00002,
+ 0x787C2000, 0xCC4000F8, 0xC0004848, 0xCB8400F8, 0xC000495C, 0xCAC400F8, 0xC0004844, 0xC88400F8,
+ 0x47AD0000, 0x8400F492, 0xC000487C, 0xC80400F8, 0x00000000, 0x00000000, 0x40080000, 0xCA0000F8,
+ 0xC0001624, 0xCB0400F8, 0xA63C007A, 0x00000000, 0x00000000, 0xA71EF432, 0x00000000, 0xC0000824,
+ 0xCA8400F8, 0x6CA08000, 0x6CA42000, 0x46250000, 0x42290000, 0xC35E0002, 0xC6340060, 0xC0001624,
+ 0xCF440078, 0xC2000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0xC0004844, 0xC88400F8, 0xC000082C, 0xCA040038, 0x00000000, 0x00000000, 0x58880002,
+ 0xB6080018, 0x00000000, 0xC0800000, 0xC0004844, 0xCC840038, 0x5AEC0002, 0xC000495C, 0xCEC400F8,
+ 0x5E6C0006, 0x84000060, 0xC0004848, 0xCB8400F8, 0xC0000838, 0xC2500002, 0xCE450800, 0x5FB80002,
+ 0xC0004848, 0xCF8400F8, 0x5EEC0002, 0xC000495C, 0xCEC400F8, 0x00000000, 0xC121FFFE, 0x5911FE54,
+ 0x14100000, 0x8000F290, 0xC000495A, 0xC84000F8, 0x00000000, 0xC3C00002, 0x787C2000, 0xCC4000F8,
+ 0xC0004960, 0xCAC400F8, 0x00000000, 0x00000000, 0x5EEC0000, 0x8400010A, 0x00000000, 0xB6FC0050,
+ 0xC0001600, 0xCA0400F8, 0x00000000, 0x00000000, 0xA61E00D2, 0x6FE90000, 0xC0000A28, 0xCE850800,
+ 0xC2C00000, 0xC2800004, 0xB6E800A0, 0xC0001604, 0xCA8400F8, 0xC0004960, 0xCEC400F8, 0xA69EFCAA,
+ 0x00000000, 0x6FE90000, 0xC0000A28, 0xCE850800, 0xC2C00002, 0xC0001600, 0xCA0400F8, 0x00000000,
+ 0x00000000, 0xA61E002A, 0x6FE90000, 0xC0000A28, 0xCE850800, 0xC2C00000, 0xC0001604, 0xCA8400F8,
+ 0xC0004960, 0xCEC400F8, 0xA69EFC12, 0xC2400000, 0xC0000A14, 0xCA440028, 0x00000000, 0x00000000,
+ 0x466D2000, 0xA4400020, 0xC2800000, 0xDFEB0029, 0x80000010, 0xDFEA0029, 0xB668EC0A, 0x00000000,
+ 0xC00048A0, 0xCB0400F8, 0xC0000A10, 0xCA8400F8, 0x6F208000, 0x6F242000, 0x46250000, 0x42A10000,
+ 0xC2400000, 0xC0000A14, 0xCA440028, 0xC35E0002, 0xC6340060, 0xC0001604, 0xCF440078, 0x5B300002,
+ 0xB6700018, 0x5AEC0002, 0xC3000000, 0xC00048A0, 0xCF0400F8, 0xC0004960, 0xCEC400F8, 0x8000F030,
+ 0xC0004918, 0xD28000F8, 0xC2000000, 0xDF600038, 0x5E600080, 0x840002A2, 0x00000000, 0xC161FFFE,
+ 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC000480A, 0xCA0000F8,
+ 0xC0004912, 0xCA4000F8, 0xC0004924, 0xCA8000F8, 0xC0004966, 0xCAC000F8, 0x00000000, 0xC121FFFE,
+ 0x5911FE54, 0x14100000, 0x76250000, 0x76290000, 0x762D0000, 0x840001E2, 0xC0004918, 0xCA4000F8,
+ 0xC28001FE, 0x76290000, 0x5A640002, 0x6A254010, 0x5EE80000, 0x8400001A, 0x6AA54000, 0x80000010,
+ 0xC62800F8, 0x62818008, 0xC0004918, 0xCF0000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xC0004966, 0xCA4000F8, 0xC2000002, 0x6A310000, 0x7E010000,
+ 0x76612000, 0xCE4000F8, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0x6F346000, 0x4771A000,
+ 0x5B744C80, 0xC2800000, 0x58340006, 0xCA800078, 0xC2C00000, 0x58340000, 0xCAC000D8, 0xC2400000,
+ 0x5834000A, 0xCA420078, 0x6EA82000, 0x42E9E000, 0x6F2CA000, 0x42E56000, 0x5AEC2E00, 0xC3990040,
+ 0xC7381C18, 0xC6F80060, 0x99007F18, 0xDB9800F8, 0xDBD800F9, 0x00000000, 0xDEA000F8, 0x46310000,
+ 0x8400FD50, 0xC0004958, 0xC84000F8, 0x00000000, 0xC1000002, 0x78502000, 0xCC4000F8, 0xC0004848,
+ 0xCBC400F8, 0xC0004844, 0xC88400F8, 0x5FFC0000, 0x8400ECBA, 0xC0004740, 0xCB0000F8, 0xC0004744,
+ 0xCAC000F8, 0x6F282000, 0x5AA84300, 0xC000487C, 0xC80400F8, 0x00000000, 0x00000000, 0x40080000,
+ 0xCA4000F8, 0xC40000F8, 0x00000000, 0xC0004878, 0xC80400F8, 0x6C908000, 0x45088000, 0x45088000,
+ 0x40100000, 0xC90000F8, 0xC43400F8, 0x00000000, 0x5C440000, 0x840000A2, 0x00000000, 0xC00047D2,
+ 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x58340002, 0xC9000078, 0x00000000,
+ 0x00000000, 0x58280002, 0x6D120000, 0xCD021078, 0x5AEC0002, 0xC0004744, 0xCEC000F8, 0x80000630,
+ 0x00000000, 0xC00047C0, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0xA67C0048,
+ 0xC00047C2, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x80001E18, 0x00000000,
+ 0xA6600042, 0xC00047C4, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x80000570,
+ 0xC00047C6, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0xC3C00000, 0xC67D0038,
+ 0xC3800000, 0xC6780038, 0x47F08000, 0x840000A8, 0x47AC8000, 0x84000098, 0xC1000000, 0xC0004814,
+ 0xC9000038, 0x00000000, 0x00000000, 0x5D100000, 0x840000F0, 0x5AEC0002, 0xC0004744, 0xCEC000F8,
+ 0xC00047CA, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x80000478, 0x00000000,
+ 0x98C08AF0, 0xC7D400F8, 0xC0004740, 0xC9C000F8, 0x5D240000, 0x8400006A, 0x00000000, 0x98C087E8,
+ 0xC7D400F8, 0x6FD8A010, 0xC0004700, 0xC00047C8, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002,
+ 0xCD0000F8, 0x80001C40, 0xC00047CC, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8,
+ 0x6FE82000, 0x5AA84300, 0x5D380000, 0x840000A0, 0x00000000, 0x98C086F0, 0xC0004748, 0xC98000F8,
+ 0xC2000000, 0x58280002, 0x6E520000, 0xCD021078, 0x58280002, 0xCE400078, 0x5D25FFFE, 0x84000040,
+ 0xC00047D0, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x800002D0, 0xC3000000,
+ 0x58280002, 0xCB000078, 0x00000000, 0x00000000, 0x5D31FFFE, 0x84000048, 0xC00047D0, 0xC90000F8,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x80000260, 0x00000000, 0x98C086F0, 0xC0004748,
+ 0xC98000F8, 0xC2000000, 0x58340002, 0xC6500078, 0xC7D01038, 0xC7901838, 0xCD0000F8, 0x58280002,
+ 0xCE400078, 0xC3C00200, 0x5FFC001C, 0xC3800000, 0xDF790048, 0x00000000, 0x00000000, 0x47F88000,
+ 0x8800FFDA, 0xC0004862, 0xCBC000F8, 0xC0000000, 0xC76C00F8, 0x5BBC7800, 0xC280001C, 0xCA6C00F9,
+ 0x00000000, 0x00000000, 0xCE7800F9, 0xC1007A00, 0x45388000, 0xC1007800, 0xC53800FE, 0x5EA80002,
+ 0x8400FFB8, 0xC3800000, 0xC000481A, 0xC80000F8, 0x6F108000, 0x45308000, 0x45308000, 0x4011C000,
+ 0xC000491E, 0xCF8000F8, 0xC2C00000, 0xC7EC0060, 0xC100001C, 0xC52C1048, 0xC100000A, 0xC52C0D10,
+ 0xC000491C, 0xCEC000F8, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420048, 0xC2800000, 0xDF680038,
+ 0x5D280080, 0x8800FFE8, 0xC000491C, 0xCAC000F8, 0xC000491E, 0xCB8000F8, 0x99007F18, 0xDAD800F8,
+ 0xDB9800F9, 0x00000000, 0xC00047CE, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8,
+ 0x00000000, 0x80001880, 0x00000000, 0x00000000, 0x00000000, 0xC0004878, 0xC80400F8, 0x6C908000,
+ 0x45088000, 0x45088000, 0x40100000, 0xCA0000F8, 0xC42400F8, 0x00000000, 0xC0004934, 0xCE0000F8,
+ 0xC2800002, 0xC4681C08, 0xC62821D0, 0xC6281E00, 0xC2600010, 0x5A650060, 0xC0004800, 0xCB4000F8,
+ 0xC2200400, 0x5A200020, 0xC7601040, 0xC0001220, 0xCE8000F8, 0xC0001200, 0xCE4000F8, 0xC0001202,
+ 0xCE0000F8, 0xC0001240, 0xCB4000F8, 0x00000000, 0x00000000, 0xA754FFE0, 0xC2000000, 0xC7600040,
+ 0xA7520042, 0x00000000, 0x00000000, 0x99008690, 0xC0004822, 0xC94000F8, 0xC1800002, 0x80001710,
+ 0x582040A0, 0xC2000000, 0xCA000018, 0xC2400000, 0xCA414000, 0xC2800000, 0xCA812000, 0xC2C00000,
+ 0xCAC20018, 0xC0004938, 0xCE0000F8, 0xC0004920, 0xCE4000F8, 0xC0004916, 0xCE8000F8, 0xC0004922,
+ 0xCEC000F8, 0xA6400558, 0x00000000, 0xC0004938, 0xCBC000F8, 0x00000000, 0xC3800000, 0x6FF48000,
+ 0x6FD44000, 0x4355A000, 0x5B744A00, 0x58340000, 0xCB802010, 0x00000000, 0xC2000000, 0x6FB46000,
+ 0x4779A000, 0x5B744C80, 0x5834000C, 0xCA000020, 0xC000491A, 0xCF8000F8, 0x5E200000, 0x84000482,
+ 0xC2000000, 0xDF610048, 0x5E6001E8, 0x8800FFE8, 0xC2000002, 0xC2400466, 0xC2A00000, 0x5AA80000,
+ 0xC0001006, 0xCE0000F8, 0xC0001008, 0xCE4000F8, 0xC000100A, 0xCE8000F8, 0x99007958, 0xC1A0FFFE,
+ 0xC0000824, 0xC9840060, 0xC0004934, 0xCA4000F8, 0xC2000000, 0xC2800002, 0x99007998, 0xDA9800F8,
+ 0xC61400F8, 0xC65800F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x99007A80, 0xC000491A, 0xC94000F8, 0x00000000, 0x00000000, 0xC121FFFE, 0x5911FE54,
+ 0x14100000, 0xC0004922, 0xCA001118, 0xC3C00000, 0xC3800000, 0xC0004930, 0xCE023118, 0xC0004932,
+ 0xCBC000D8, 0xC2800000, 0xC000491E, 0xCFC000F8, 0xC0004862, 0xCA800060, 0xC3A0001A, 0x5BB94000,
+ 0xC6B80060, 0xC000491C, 0xCF8000F8, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420048, 0x00000000,
+ 0x00000000, 0x00000000, 0xA8E2FFE8, 0xC2000000, 0xC1220002, 0xD90C00F8, 0xDF600038, 0x5E600080,
+ 0x8400FFF2, 0xC000491C, 0xCA0000F8, 0xC000491E, 0xCA4000F8, 0x00000000, 0x00000000, 0x99007F18,
+ 0xDA1800F8, 0xDA5800F9, 0x00000000, 0xC2000000, 0xDF610048, 0x5E6001FE, 0x8800FFE8, 0xC0004916,
+ 0xCA8000F8, 0xC2C00000, 0xDFEC0048, 0xC2400000, 0x466D2000, 0x8400004A, 0x5EA80000, 0x8400003A,
+ 0xC2600002, 0x99008690, 0xC000482E, 0xC94000F8, 0xC1800002, 0x80000030, 0xC2600000, 0x99008690,
+ 0xC000482C, 0xC94000F8, 0xC1800002, 0xC2000068, 0xC6240078, 0xC0004930, 0xCE400080, 0xC000491A,
+ 0xC98000F8, 0xC0004862, 0xC94000F8, 0x6D9C6000, 0x45D8E000, 0x59DC4C80, 0x99007D78, 0xD95800F8,
+ 0xD99800F9, 0xD9D400F8, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420048, 0xC2000000, 0xDF600038,
+ 0x5E600080, 0x8400FFEA, 0x00000000, 0xC000491C, 0xCA0000F8, 0xC000491E, 0xCA4000F8, 0x00000000,
+ 0x00000000, 0x99007F18, 0xDA1800F8, 0xDA5800F9, 0x00000000, 0x80001160, 0x00000000, 0x99008690,
+ 0xC000482A, 0xC94000F8, 0xC1800002, 0x80001130, 0xC0004938, 0xCBC000F8, 0x00000000, 0x00000000,
+ 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB84A00, 0x58380008, 0xCA0000F8, 0x00000000, 0x00000000,
+ 0xA600039A, 0x00000000, 0xC0004938, 0xCBC000F8, 0xC3000000, 0x00000000, 0x6FF88000, 0x6FD44000,
+ 0x4395C000, 0x5BB84A00, 0x58380000, 0xCB002010, 0xC2000000, 0x58380008, 0xCA020078, 0x5838000C,
+ 0xCAC000F8, 0x5838000E, 0xCA4000F8, 0xC000491A, 0xCF0000F8, 0xC0004930, 0xCEC000F8, 0xC000493C,
+ 0xCE0000F8, 0xC0004932, 0xCE4000F8, 0x5E200000, 0x84000138, 0xC2800000, 0xA6FE00D2, 0x6F206000,
+ 0x46310000, 0x5A204C80, 0x5820000C, 0xCA800020, 0x00000000, 0x00000000, 0x5EA80000, 0x8400020A,
+ 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x99007A80, 0xC000491A, 0xC94000F8, 0x00000000, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000,
+ 0xC0004930, 0xCAC000F8, 0xC0004932, 0xCA4000F8, 0xC7EC1118, 0xC0004930, 0xCEC000F8, 0x5838000C,
+ 0xCEC000F8, 0x58000002, 0xCE4000F8, 0xC0004934, 0xCA0000F8, 0xC2400002, 0x6E642000, 0x6E642000,
+ 0x76612000, 0x8400002A, 0xC2400002, 0x6E684000, 0x58380008, 0xCE804200, 0xA6000020, 0x6E682000,
+ 0x58380008, 0xCE802100, 0xC2400002, 0x6E642000, 0x76612000, 0x840000EA, 0x58380008, 0xCA0000F8,
+ 0xC2800000, 0xC2400000, 0xA60200C0, 0xDBA800F8, 0x6F386000, 0x47B1C000, 0x5BB84C80, 0x58380004,
+ 0xCA400078, 0x58380002, 0xCA800078, 0x00000000, 0xDEB800F8, 0x46A54000, 0x88000060, 0x00000000,
+ 0xC0004824, 0xCA0000F8, 0xC2400002, 0x6E640000, 0x5A200002, 0xCE0000F8, 0x58380008, 0xCE400000,
+ 0x80000018, 0x00000000, 0x80000048, 0xC0004934, 0xCA0000F8, 0x00000000, 0x00000000, 0xA6020CCA,
+ 0x00000000, 0x00000000, 0x80000CF8, 0xC2800000, 0xC2000200, 0xC240001A, 0xDF690048, 0x46294000,
+ 0x46A54000, 0x8800FFD2, 0xC2000006, 0xC2600982, 0x5A643B6E, 0x5838000A, 0xCA8000F8, 0xC0001006,
+ 0xCE0000F8, 0xC0001008, 0xCE4000F8, 0xC000100A, 0xCE8000F8, 0x99007958, 0xC1A0FFFE, 0xC0000824,
+ 0xC9840060, 0xC2000000, 0xC0004930, 0xCA02E008, 0x58380026, 0xCA4000F8, 0x00000000, 0xC2800000,
+ 0x99007998, 0xDA9800F8, 0xC61400F8, 0xC65800F8, 0xC0004934, 0xCA0000F8, 0x00000000, 0x00000000,
+ 0xA6020022, 0x00000000, 0x00000000, 0x80000318, 0xC0004938, 0xCBC000F8, 0xC0004878, 0xC80400F8,
+ 0x6C908000, 0x45088000, 0x45088000, 0x40100000, 0xCA0000F8, 0xC42400F8, 0x00000000, 0x58240018,
+ 0xCA0000F8, 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB84A00, 0xC3000000, 0xC3400002, 0xC2C00000,
+ 0xC62C0078, 0xC6270038, 0xC0004940, 0xCE400038, 0xC6260038, 0xC0004942, 0xCE400038, 0xC000493C,
+ 0xCA0000F8, 0x5EEC0000, 0x8400018A, 0x5A6C0010, 0x46254000, 0x88000190, 0x5A600052, 0x46E54000,
+ 0x88000178, 0x58380006, 0xCA8000F8, 0xC0004940, 0xCA0000F8, 0xC2400000, 0xC6A70038, 0x7E412000,
+ 0x76612000, 0xC2000000, 0xC6A10038, 0x46250000, 0x84000138, 0xC0004942, 0xCA0000F8, 0xC2400000,
+ 0xC6A60038, 0x7E412000, 0x76612000, 0xC2000000, 0xC6A00038, 0x58380002, 0xCA8000F8, 0x46250000,
+ 0x840000E8, 0xC2400000, 0xC6A60078, 0x466D0000, 0x880000DA, 0xC2400000, 0xC6A40078, 0x58380008,
+ 0xCA8000F8, 0x46E50000, 0x880000BA, 0x00000000, 0xA6820018, 0x00000000, 0xC7700B00, 0xA6840098,
+ 0x00000000, 0xC7700A00, 0x80000080, 0xC7700200, 0xC000493C, 0xCAC000F8, 0x80000060, 0xC7700300,
+ 0xC000493C, 0xCAC000F8, 0x80000040, 0xC7700900, 0x80000030, 0xC7700800, 0x80000020, 0xC7700700,
+ 0x80000010, 0xC7700500, 0xC0004944, 0xCF0000F8, 0xC000493E, 0xCEC000F8, 0xC0004938, 0xCA4000F8,
+ 0xC000493C, 0xCB8000F8, 0xC000493E, 0xCB4000F8, 0xC3000000, 0x6E608000, 0x6E544000, 0x42150000,
+ 0x5A204A00, 0x5AA00008, 0x58200004, 0xCB000078, 0xC0004934, 0xCA0000F8, 0xC2400000, 0xC0004930,
+ 0xCA42E008, 0xC3C00018, 0xA6020098, 0x00000000, 0x43656000, 0x47AD0000, 0x88000050, 0x46F96000,
+ 0x6EE04010, 0x5BE00004, 0xC2000000, 0xC6E00008, 0x5E200000, 0x84000042, 0x5BFC0002, 0x80000030,
+ 0xC3C00004, 0x5A2C0008, 0x47A10000, 0x88000012, 0x5FB80008, 0x6FE04000, 0x42390000, 0x47212000,
+ 0x88000068, 0xC2400000, 0xC0004930, 0xCA42E008, 0xC2060002, 0xC68000F8, 0xCE006300, 0x6FE04000,
+ 0x4721C000, 0x5F700010, 0x4765A000, 0xC2000000, 0xC6340008, 0xC25A000A, 0xC000491A, 0xCA401C18,
+ 0xC2800000, 0xC0004932, 0xCA8000D8, 0xC0004862, 0xCA400060, 0x6FA04010, 0x42290000, 0xC000491E,
+ 0xCE0000F8, 0xC7E41048, 0xC000491C, 0xCE4000F8, 0x6FE04000, 0x43A1C000, 0xC000493C, 0xCF8000F8,
+ 0xC000493E, 0xCF4000F8, 0xC000493A, 0xCFC000F8, 0x80000008, 0x00000000, 0x00000000, 0x00000000,
+ 0xC2000000, 0xDCE000F8, 0xA622FFD8, 0xC1220002, 0xD90C00F8, 0xC0004938, 0xCBC000F8, 0xC0004944,
+ 0xCB4000F8, 0xC0004862, 0xCB0000F8, 0xC0004934, 0xCA0000F8, 0x6FF88000, 0x6FD44000, 0x4395C000,
+ 0x5BB84A00, 0xA6020298, 0xC2400000, 0x58380008, 0xCA406000, 0xDFE800F8, 0xC2218E08, 0x5A21BAF6,
+ 0x46A14000, 0x84000022, 0xC2080002, 0x7361A000, 0x80000058, 0x5E640000, 0x84000022, 0xC20C0002,
+ 0x7361A000, 0x80000030, 0xC2000000, 0xC760E710, 0xC7604218, 0x5E200000, 0x840002A2, 0xC2200002,
+ 0xC0004930, 0xCE021000, 0x99008690, 0xC0004828, 0xC94000F8, 0xC1800002, 0xC0004780, 0xC93C00F8,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD3C00F8, 0x58380000, 0xCA0000F8, 0x00000000, 0x00000000,
+ 0xA6000132, 0xC0004940, 0xCA8000F8, 0xC0004942, 0xCA4000F8, 0xC7600078, 0xC6A01838, 0xC6601038,
+ 0xC000493A, 0xCA4000F8, 0xC0004934, 0xCA8000F8, 0xC0007800, 0x40300000, 0x40240000, 0x5C000004,
+ 0x5EC07A00, 0x88000012, 0x5C000200, 0xCE0000F8, 0x58000002, 0x5EC07A00, 0x88000012, 0x5C000200,
+ 0xCE8000F8, 0xC000493E, 0xCA0000F8, 0xC2400000, 0x5838000C, 0xCE4000F8, 0x99008690, 0xC0004830,
+ 0xC94000F8, 0xC61800F8, 0xC0004930, 0xC6100078, 0xCD000078, 0x800000A8, 0xC2400002, 0x58380008,
+ 0xCE400000, 0xC0004944, 0xCF4000F8, 0x800002A8, 0xC000493C, 0xCA4000F8, 0xDFE800F8, 0x5A300018,
+ 0xC0007800, 0x40200000, 0xCA0000F8, 0x58380008, 0xC6501078, 0xCD021078, 0x5838000A, 0xCE8000F8,
+ 0x58380026, 0xCE0000F8, 0xC0004944, 0xCF4000F8, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420048,
+ 0x80000068, 0x00000000, 0x99008690, 0xC0004826, 0xC94000F8, 0xC1800002, 0xC0004760, 0xC93C00F8,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD3C00F8, 0x8000FDA8, 0xC2000000, 0xC2400080, 0xDF600038,
+ 0xB624FFEA, 0xC000491C, 0xCA4000F8, 0xC000491E, 0xCA8000F8, 0x99007F18, 0xDA5800F8, 0xDA9800F9,
+ 0x00000000, 0xC0004934, 0xCA0000F8, 0x00000000, 0xC2800000, 0xA6020160, 0xC2400004, 0xC2000200,
+ 0xDF690048, 0x46294000, 0x46A54000, 0x8800FFDA, 0x00000000, 0xC000491A, 0xC98000F8, 0xC0004862,
+ 0xC94000F8, 0x6D9C6000, 0x45D8E000, 0x59DC4C80, 0x99007D78, 0xD95800F8, 0xD99800F9, 0xD9D400F8,
+ 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420048, 0xC2000000, 0xC2400080, 0xDF600038, 0xB624FFEA,
+ 0xC000491C, 0xCA4000F8, 0xC000491E, 0xCA8000F8, 0x99007F18, 0xDA5800F8, 0xDA9800F9, 0x00000000,
+ 0x58380008, 0xCA4000F8, 0xC2000000, 0xCE000018, 0xC2A1FFFE, 0x5AA9FFFE, 0xCE021078, 0x5838000A,
+ 0xCE8000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0000838, 0xC2500002, 0xCE450800, 0xC0004848, 0xCBC400F8, 0xC3800000, 0xC000082C, 0xCB840028,
+ 0x5FFC0002, 0xC0004848, 0xCFC400F8, 0x58880002, 0x47888000, 0xC1000000, 0xC50800FE, 0xC0004844,
+ 0xCC8400F8, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0x8000CBF0, 0xC2000000, 0xDF600038,
+ 0x5E200080, 0x8400029A, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xC000480C, 0xCA0000F8, 0xC0004910, 0xCA4000F8, 0xC000492C, 0xCA8000F8,
+ 0xC0004968, 0xCAC000F8, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0x76250000, 0x76290000,
+ 0x76E16000, 0x840001DA, 0xC0004926, 0xCA4000F8, 0xC201FFFE, 0x76E16000, 0x5A640002, 0x6AE50010,
+ 0x5F200000, 0x8400001A, 0x6A250000, 0x80000010, 0xC6E000F8, 0x62014008, 0xC0004926, 0xCE8000F8,
+ 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC0004968,
+ 0xCA4000F8, 0xC2000002, 0x6A290000, 0x7E010000, 0x76612000, 0xCE4000F8, 0x00000000, 0xC121FFFE,
+ 0x5911FE54, 0x14100000, 0x6EB4A000, 0x6E944000, 0x4755A000, 0x4769A000, 0x5B747000, 0x58340002,
+ 0xC2000000, 0xCA0000D8, 0x5834002E, 0xC2400000, 0xCA400078, 0x6EB0A000, 0x6EBC4000, 0x473D8000,
+ 0x47298000, 0x5B30302E, 0x5B300004, 0x6E642000, 0x4225E000, 0xC39A8024, 0xC7380060, 0xC6B81C18,
+ 0x99007F18, 0xDB9800F8, 0xDBD800F9, 0x00000000, 0xC2000000, 0xDF600038, 0x5E200080, 0x840002D2,
+ 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC000490E, 0xCA0000F8, 0xC000492A, 0xCA4000F8, 0xC000496A, 0xCB0000F8, 0xC0004956, 0xCAC000F8,
+ 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0x77218000, 0x77258000, 0x8400021A, 0xC201FFFE,
+ 0x77218000, 0x5AEC0002, 0x6B2D0010, 0x5EA00000, 0x8400001A, 0x6A2D0000, 0x80000010, 0xC72000F8,
+ 0x62016008, 0xC0004956, 0xCEC000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xC000496A, 0xCA4000F8, 0xC2000002, 0x6A2D0000, 0x7E010000, 0x76612000,
+ 0xCE4000F8, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0x6EF4A000, 0x6ED44000, 0x4755A000,
+ 0x476DA000, 0x5B747000, 0x5834000E, 0xC2000000, 0xCA0000D8, 0x58340008, 0xC2400000, 0xCA420078,
+ 0x5834000C, 0xC2800000, 0xCA832010, 0x6E644010, 0x42250000, 0x4229E000, 0xC39A8008, 0x58340008,
+ 0xCB809018, 0x58340008, 0xC2800000, 0xCA810010, 0x6EE0A000, 0x6EE44000, 0x46250000, 0x462D0000,
+ 0x5A200008, 0x5A203008, 0x42290000, 0xC6380060, 0xC6F81C18, 0x99007F18, 0xDB9800F8, 0xDBD800F9,
+ 0x00000000, 0xC000495A, 0xC84000F8, 0x00000000, 0xC3C00002, 0x787C2000, 0xCC4000F8, 0xC0001A1C,
+ 0xCA0000F8, 0xC2400008, 0x6A452000, 0x76250000, 0x84000E9A, 0xC0000A28, 0xC3800000, 0xCB840028,
+ 0xC0000A14, 0xC3400000, 0xCB440028, 0xC0004880, 0xCB0400F8, 0x47B48000, 0x88000E48, 0x58041802,
+ 0xCAC000F8, 0xA7000060, 0x00000000, 0x00000000, 0xA6C8C5C8, 0xC2800000, 0xC6E80018, 0x80000070,
+ 0x00000000, 0x00000000, 0x00000000, 0x8000C590, 0x00000000, 0xC2800000, 0xC7282018, 0xC000490E,
+ 0xCA4000F8, 0x6BE9E000, 0x00000000, 0x767D2000, 0x8400C548, 0x6EA0A000, 0x6E944000, 0x46150000,
+ 0x46290000, 0x5A207000, 0x5820000C, 0xCA0000F8, 0xC0004946, 0xCE8000F8, 0xA6220398, 0x00000000,
+ 0xC2200060, 0xC0004948, 0xCE000008, 0xCE021038, 0xC240000A, 0xC000494A, 0xCE4000F8, 0xC2B60002,
+ 0xC0004964, 0xCE837B00, 0x990081E8, 0xC00048A0, 0xC88400F8, 0x00000000, 0xC0004946, 0xCBC000F8,
+ 0x00000000, 0x00000000, 0x6FF8A000, 0x6FD44000, 0x4795C000, 0x47BDC000, 0x5BB87000, 0x99007FA8,
+ 0xDBD800F8, 0xDB9800F9, 0x00000000, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420048, 0xC000491C,
+ 0x990081A0, 0xC94000F9, 0xC98000F8, 0x00000000, 0x99007F18, 0xD95800F8, 0xD99800F9, 0x00000000,
+ 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x99007BE0,
+ 0xDBD800F8, 0xDB9800F9, 0xC7D800F8, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0x6FF8A000,
+ 0x6FD44000, 0x4795C000, 0x47BDC000, 0x5BB87000, 0x58380010, 0xCA0000F8, 0xC0004874, 0xC80400F8,
+ 0x6C908000, 0x45088000, 0x45088000, 0x40100000, 0xCA4000F8, 0xC43400F8, 0x00000000, 0xC74000F8,
+ 0xCE0000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC000490E, 0xCA4000F8, 0xC2800002, 0x6ABD4000, 0x72692000, 0xCE4000F8, 0x00000000, 0xC121FFFE,
+ 0x5911FE54, 0x14100000, 0x99008690, 0xC0004836, 0xC94000F8, 0xC1800002, 0x00000000, 0x00000000,
+ 0x00000000, 0xA8E2FFE8, 0x00000000, 0xC1220002, 0xD90C00F8, 0xC2000000, 0xC0000A14, 0xCA040028,
+ 0xC0000A28, 0xC2500002, 0xCE450800, 0x58880002, 0xB6080018, 0xC00048A0, 0xC0800000, 0xCC8400F8,
+ 0x8000C168, 0xC0004946, 0xCBC000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xC000490E, 0xCA4000F8, 0xC2800002, 0x6ABD4000, 0x72692000, 0xCE4000F8,
+ 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0x6FF8A000, 0x6FD44000, 0x4795C000, 0x47BDC000,
+ 0x5BB87000, 0x58380008, 0xCA0000F8, 0x5838000C, 0xCA4000F8, 0xC3400000, 0xC6340000, 0xC000494E,
+ 0xCF4000F8, 0xC2800000, 0xC62A0078, 0xC3000000, 0xC6308018, 0x6F304000, 0x43298000, 0xC000493C,
+ 0xCF0000F8, 0xC2C00000, 0xC66C0078, 0xC0004950, 0xCEC000F8, 0xC2800000, 0xC66AE020, 0xC0004954,
+ 0xCE8000F8, 0x5F740000, 0x840001B8, 0x5E300028, 0x46E12000, 0x84000182, 0x46E12000, 0x8800014A,
+ 0x5E300018, 0x46E12000, 0x8800002A, 0x46E12000, 0x84000042, 0x00000000, 0x800000D8, 0x00000000,
+ 0x99008328, 0xDBD800F8, 0xDB9800F9, 0xC78000F8, 0xC3400002, 0xC000494E, 0xCF4000F8, 0xC161FFFE,
+ 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC000490E, 0xCA4000F8,
+ 0xC2800002, 0x6ABD4000, 0x7E814000, 0x76692000, 0xCE4000F8, 0x00000000, 0xC121FFFE, 0x5911FE54,
+ 0x14100000, 0xC2200060, 0xC0004948, 0xCE021038, 0xC2000000, 0xC000494C, 0xCE0000F8, 0x80000080,
+ 0x00000000, 0x99008328, 0xDBD800F8, 0xDB9800F9, 0xC78000F8, 0x99008528, 0xDBD800F8, 0xDB9800F9,
+ 0xC78000F8, 0xC2200058, 0xC0004948, 0xCE021038, 0xC2000002, 0xC000494C, 0xCE0000F8, 0xC2000006,
+ 0xC0001006, 0xCE0000F8, 0x5838000A, 0xCA4000F8, 0xC2200982, 0x5A203B6E, 0xC0001008, 0xCE0000F8,
+ 0xC000100A, 0xCE4000F8, 0xC0004954, 0xCA8000F8, 0xC200000C, 0xC000494A, 0xCE0000F8, 0xC0004948,
+ 0xCE800008, 0xC2B60000, 0xC0004964, 0xCE8000F8, 0x990081E8, 0xC00048A0, 0xC88400F8, 0x00000000,
+ 0xC0004946, 0xCBC000F8, 0xC000494C, 0xCA0000F8, 0x6FF8A000, 0x6FD44000, 0x4795C000, 0x47BDC000,
+ 0x5BB87000, 0x5E200000, 0x84000112, 0x00000000, 0x99007FA8, 0xDBD800F8, 0xDB9800F9, 0x00000000,
+ 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420048, 0xC000491C, 0x990081A0, 0xC94000F9, 0xC98000F8,
+ 0x00000000, 0x99007F18, 0xD95800F8, 0xD99800F9, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x99007BE0, 0xDBD800F8, 0xDB9800F9, 0xC7D800F8,
+ 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0xC000493C, 0xCA8000F8, 0xC000494E, 0xCAC000F8,
+ 0xC3000018, 0xC3400006, 0x5E200000, 0x8400002A, 0xC2800000, 0xC2C00000, 0xC300001E, 0xC3400000,
+ 0xC6AC1078, 0xC72C0418, 0xC76C0810, 0x58380010, 0xCA8000F8, 0x58380008, 0xCEC000F8, 0xC6280100,
+ 0xC0004874, 0xC80400F8, 0x6C908000, 0x45088000, 0x45088000, 0x40100000, 0xCB0000F8, 0xC43400F8,
+ 0x00000000, 0xC74000F8, 0xCE8000F8, 0xC0004952, 0xCE8000F8, 0x00000000, 0x00000000, 0x00000000,
+ 0xA8E2FFE8, 0x00000000, 0xC000494C, 0xCA0000F8, 0xC0004950, 0xCAC000F8, 0x5E200000, 0x8400006A,
+ 0xDFE800F8, 0x7E814000, 0x5834001A, 0xCE8000F8, 0x99008690, 0xC0004834, 0xC94000F8, 0xC1800002,
+ 0x99008690, 0xC0004838, 0xC94000F8, 0xC6D800F8, 0xC1220002, 0xD90C00F8, 0x5E200000, 0x84000040,
+ 0x5838002C, 0xCB0000F8, 0xDFE800F8, 0x00000000, 0x58380014, 0xCF0000F8, 0x80000018, 0xC2A1FFFE,
+ 0x5AA9FFFE, 0x5838000A, 0xCE8000F8, 0xC3000000, 0xC0000A14, 0xCB040028, 0xC2D00002, 0xC0000A28,
+ 0xCEC50800, 0xC000494E, 0xCA8000F8, 0x58880002, 0xB4B00018, 0xC00048A0, 0xC0800000, 0xCC8400F8,
+ 0x5EA80000, 0x8400016A, 0x5E200000, 0x84000158, 0xC000493C, 0xCA8000F8, 0x00000000, 0x00000000,
+ 0x5AA80060, 0xCE8000F8, 0x99008328, 0xDBD800F8, 0xDB9800F9, 0xC78000F8, 0x99008528, 0xDBD800F8,
+ 0xDB9800F9, 0xC78000F8, 0xC0004952, 0xCAC000F8, 0x58380000, 0xCA8000F8, 0xC30C0002, 0xC7F00018,
+ 0xA68000B0, 0x00000000, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xC0001800, 0xCA0000F8, 0x00000000, 0x00000000, 0xA60CFFEA, 0xC6F00500,
+ 0xC6B0C400, 0xCF0000F8, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0x8000B7B8, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x8000B750, 0xDCBC00F9, 0x5FFC0000, 0x8400095A, 0xC3800002,
+ 0xDB8800F9, 0xC3800000, 0xDB8800F9, 0xC0004728, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002,
+ 0xCD0000F8, 0xC0004730, 0xC98000F8, 0xC000472E, 0xC94000F8, 0xC00047DC, 0xC90000F8, 0xC00047DE,
+ 0xC9C000F8, 0xC000472E, 0xCD8000F8, 0x6D110000, 0xC5D30038, 0xC00047DC, 0xCD0000F8, 0x4594A000,
+ 0x6DDD0000, 0xC55C0038, 0xC00047DE, 0xCDC000F8, 0xC0001AC4, 0xC94000F8, 0xC0001AC8, 0xC98000F8,
+ 0xC000472C, 0xC9C000F8, 0x45948000, 0xC1000002, 0x41D0E004, 0xCDC000F8, 0xC5501078, 0xC5900078,
+ 0xC000472A, 0xCD0000F8, 0xC0001AF0, 0xCBC000F8, 0x58000002, 0xCB8000F8, 0xC3400000, 0xC7F50038,
+ 0x6F702000, 0x5B304300, 0xC000474C, 0xCAC000F8, 0xC0004720, 0xC94000F8, 0x00000000, 0x00000000,
+ 0x5D940002, 0x6D9B8000, 0x6D9B8010, 0x581847E0, 0xC98000F8, 0x581447E0, 0xC9C000F8, 0x5D2C0000,
+ 0x8400007A, 0xC7901078, 0xC7D00078, 0xCD0000F8, 0xC1000000, 0xC5910038, 0x45348000, 0x84000090,
+ 0xC0004722, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x80000058, 0xC1000000,
+ 0xC5D10038, 0x45348000, 0x8400003A, 0xC0004724, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002,
+ 0xCD0000F8, 0xA7840080, 0x59540002, 0x6D578000, 0x6D578010, 0xC0004720, 0xCD4000F8, 0xC1000000,
+ 0xC5910038, 0x45348000, 0x84000038, 0xC0004726, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002,
+ 0xCD0000F8, 0xA78000B8, 0xC2800002, 0xC000474E, 0xCE8000F8, 0xC2C00000, 0xC000474C, 0xCEC000F8,
+ 0xC0004758, 0xCFC000F8, 0x58000002, 0xCF8000F8, 0xC000475C, 0xC90000F8, 0x00000000, 0x00000000,
+ 0xA53E003A, 0x00000000, 0xC13E0002, 0xCFC000F8, 0xCD03DE08, 0x58000002, 0xCF8000F8, 0x800001A0,
+ 0xC000475C, 0xC13C0002, 0xCD03DE08, 0x5D2C0000, 0x8400017A, 0xC2C00000, 0xC000474C, 0xCEC000F8,
+ 0x98C08AF0, 0xC75400F8, 0xC0004740, 0xC9C000F8, 0x5D240000, 0x84000042, 0xC1000002, 0xC0004750,
+ 0xCD0000F8, 0xC0004752, 0xCD0000F8, 0x80000100, 0x00000000, 0x98C08BE0, 0xC75400F8, 0xC0004742,
+ 0xC98000F8, 0x5D240000, 0x8400002A, 0xC1000002, 0xC0004752, 0xCD0000F8, 0x80000060, 0xC0004742,
+ 0xC94000F8, 0xC0004754, 0xC1000002, 0xCD0000F8, 0x98C08CF0, 0xC55400F8, 0xC75800F8, 0x00000000,
+ 0xC0004742, 0xCF4000F8, 0x98C08AB8, 0xC1400000, 0xC7540020, 0x6F40A010, 0xC1000000, 0xC7D00038,
+ 0x58300000, 0x6D110000, 0xCD010838, 0xA7840398, 0xC000474C, 0xCAC000F8, 0xC000474E, 0xCA8000F8,
+ 0xC0004750, 0xCBC000F8, 0xC0004752, 0xCB8000F8, 0xC0004710, 0xC90000F8, 0x00000000, 0x00000000,
+ 0x59100002, 0xCD0000F8, 0x5D280002, 0x840000B8, 0xC000473C, 0xC90000F8, 0x00000000, 0x00000000,
+ 0x59100002, 0xCD0000F8, 0xC0004712, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8,
+ 0xC0004754, 0xC90000F8, 0x00000000, 0x00000000, 0x5D100000, 0x8400021A, 0x58300000, 0xC13C0002,
+ 0xCD03DE00, 0x800001F8, 0xC0004714, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8,
+ 0x5D380000, 0x8400003A, 0xC0004736, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8,
+ 0x5D3C0000, 0x84000042, 0xC0004718, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8,
+ 0x80000140, 0xC1000000, 0x58300000, 0xC903E000, 0x00000000, 0x00000000, 0x5D100000, 0x84000042,
+ 0xC000471A, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x800000D0, 0x58300000,
+ 0xC13E0002, 0xCD03FF00, 0xC1000000, 0x58300000, 0xC903C000, 0x00000000, 0x00000000, 0x5D100000,
+ 0x84000082, 0xC0004716, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0xC000473A,
+ 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x58300000, 0xC13C0000, 0xCD03DE00,
+ 0xC1000000, 0xC0004746, 0xCD0000F8, 0xC0004750, 0xCD0000F8, 0xC0004752, 0xCD0000F8, 0xC000474E,
+ 0xCD0000F8, 0xC2C00002, 0xC000474C, 0xCEC000F8, 0xC0004754, 0xCD0000F8, 0xC3CE0002, 0xC0000800,
+ 0xCFC0E700, 0xC3E1FFFE, 0x597DFFFE, 0x593DFE14, 0x94000001, 0x00000000, 0x00000000, 0x00000000,
+ 0xC000487C, 0xC80400F8, 0x00000000, 0x00000000, 0x40080000, 0xCBC000F8, 0xC43800F8, 0x00000000,
+ 0xC000480E, 0xCA0000F8, 0xC0004858, 0xCB4400F8, 0x00000000, 0x00000000, 0x47610000, 0x880000B0,
+ 0x00000000, 0xA7C00048, 0xC0004854, 0xC1000002, 0xCD0400F8, 0xC11C0000, 0xC000082C, 0xCD05CE00,
+ 0x800000D8, 0x00000000, 0xA7D20138, 0x00000000, 0xC7E14040, 0xC2400000, 0xC6246028, 0xC200006A,
+ 0x46250000, 0xC6240030, 0xC0000810, 0xCE440030, 0x8000FF70, 0xC2000000, 0xC0000808, 0xCA040010,
+ 0xC11C0000, 0xC000082C, 0xCD05CE00, 0x5A200002, 0x5E600010, 0x84000010, 0xC2000000, 0xC0000808,
+ 0xCE040010, 0xC3400000, 0x80000028, 0xC1200002, 0xC0000818, 0xCD061000, 0x5B740002, 0xC0004858,
+ 0xCF4400F8, 0x99007930, 0xC0004848, 0xC94400F8, 0xC1800000, 0xC11C0002, 0xC000082C, 0xCD05CE00,
+ 0x80000878, 0x5B740002, 0xC0004858, 0xCF4400F8, 0xC78000F8, 0xC13C0002, 0xCD03DE00, 0xC0004848,
+ 0xC94400F8, 0xC1800000, 0xC000082C, 0xC9840028, 0x59540002, 0xC0004848, 0xCD4400F8, 0x58880002,
+ 0xB49807F8, 0x00000000, 0xC0800000, 0x800007E0, 0xC000487C, 0xC80400F8, 0x00000000, 0x00000000,
+ 0x40080000, 0xCBC000F8, 0xC42800F8, 0x00000000, 0xA7C00130, 0xC000484C, 0xCA0400F8, 0xC2400000,
+ 0xC0001AEC, 0xCA440018, 0x5A200002, 0xC000484C, 0xCE0400F8, 0xB624008A, 0xC68000F8, 0xC13C0002,
+ 0xCD03DE00, 0xC0004848, 0xC94400F8, 0xC1800000, 0xC000082C, 0xC9840028, 0x59540002, 0xC0004848,
+ 0xCD4400F8, 0x58880002, 0xB49806E8, 0x00000000, 0xC0800000, 0x800006D0, 0xC0004854, 0xC1000004,
+ 0xCD0400F8, 0xC0000820, 0xC2000002, 0xCE0400F8, 0xC2000000, 0xC000484C, 0xCE0400F8, 0xC0004858,
+ 0xCE0400F8, 0x8000FF28, 0xC0004854, 0xC1000000, 0xCD0400F8, 0xC11C0000, 0xC000082C, 0xCD05CE00,
+ 0x99007930, 0xC0004848, 0xC94400F8, 0xC1800000, 0xC1200000, 0xC0000818, 0xCD061000, 0xC11C0002,
+ 0xC000082C, 0xCD05CE00, 0xC2000000, 0xC000484C, 0xCE0400F8, 0x800005D0, 0xC0001AC0, 0xCB8400F8,
+ 0xC000487C, 0xC80400F8, 0x00000000, 0x00000000, 0x40080000, 0xCBC000F8, 0xC42800F8, 0x00000000,
+ 0xA78004E2, 0x00000000, 0x00000000, 0xA7C004A2, 0x00000000, 0xC0001B00, 0xC2060006, 0xCE046308,
+ 0xA7E8045A, 0x00000000, 0xC0004850, 0xCA0400F8, 0xC2400000, 0xC0004812, 0xCA420078, 0x5A200002,
+ 0xC0004850, 0xCE0400F8, 0x5E640000, 0x8400001A, 0x46250000, 0x880002F8, 0xC68000F8, 0xC13C0002,
+ 0xCD03DE00, 0xC0001ACC, 0xC2000002, 0xCE040000, 0x5C440000, 0x84000250, 0xC0004810, 0xC94000F8,
+ 0xC68000F8, 0xCBC000F8, 0x00000000, 0xC1000000, 0xA5400208, 0xC53C1000, 0x00000000, 0xA7FC01F2,
+ 0xC0001AF0, 0xC1000000, 0x58000002, 0xC9000000, 0xC000474E, 0xC98000F8, 0x5D100000, 0x84000022,
+ 0xC1000002, 0xC53C1E00, 0x80000198, 0x5D180000, 0x84000022, 0xC1000002, 0xC53C1E00, 0x80000170,
+ 0xC0004878, 0xC80400F8, 0x6C908000, 0x45088000, 0x45088000, 0x40100000, 0xC98000F8, 0xC43800F8,
+ 0x00000000, 0xC000481E, 0xC9C000F8, 0xC000481C, 0xCA0000F8, 0x00000000, 0x759CC000, 0x45A08000,
+ 0x840000E8, 0xC0001AF0, 0xC3400000, 0x58000000, 0xCB410038, 0xC0004746, 0xC94000F8, 0x6F702000,
+ 0x5B304300, 0xC2C00000, 0x58300000, 0xCAC00038, 0x00000000, 0x00000000, 0x456C8000, 0x88000020,
+ 0xC1000002, 0xC53C1E00, 0x80000040, 0x5AEC0002, 0x58300000, 0xCEC00038, 0xC1000002, 0xC53C1000,
+ 0xC77C0838, 0xC57C0038, 0x59540002, 0xC0004746, 0xCD4000F8, 0xC68000F8, 0xCFC000F8, 0xC0004848,
+ 0xC94400F8, 0xC1800000, 0xC000082C, 0xC9840028, 0x59540002, 0xC0004848, 0xCD4400F8, 0x58880002,
+ 0xB49801F8, 0x00000000, 0xC0800000, 0x800001E0, 0xC000471E, 0xC90000F8, 0x00000000, 0x00000000,
+ 0x59100002, 0xCD0000F8, 0xC0004854, 0xC1000000, 0xCD0400F8, 0xC11C0000, 0xC000082C, 0xCD05CE00,
+ 0x99007930, 0xC0004848, 0xC94400F8, 0xC1800000, 0xC2000000, 0xC0000820, 0xCE0400F8, 0xC1200000,
+ 0xC0000818, 0xCD061000, 0xC11C0002, 0xC000082C, 0xCD05CE00, 0xC0004850, 0xCE0400F8, 0xC2000002,
+ 0xC0001ACC, 0xCE040008, 0x800000E8, 0xC2000002, 0xC0004850, 0xCE0400F8, 0x8000FC00, 0xC2000000,
+ 0xC0004850, 0xCE0400F8, 0xA7E60032, 0x00000000, 0xC2000002, 0xC0001B00, 0xCE040000, 0x8000FBE8,
+ 0x00000000, 0xA7860052, 0x00000000, 0xC68000F8, 0xC13C0002, 0xCD03DE00, 0xC2020002, 0xC7E2A540,
+ 0xC0001B00, 0xCE0400F8, 0x8000FB90, 0xC2040002, 0xC0001B00, 0xCE044200, 0x8000FB70, 0xC2C80002,
+ 0x6AC56000, 0xDACC00F8, 0xC0004854, 0xCB4400F8, 0xC0004848, 0xCB8400F8, 0xC0000838, 0xC3C00000,
+ 0xCBC40028, 0x5EF40004, 0x84000022, 0xC3000000, 0xC0001ACC, 0xCF042100, 0x47F98000, 0x8400004A,
+ 0x47F98000, 0x88000050, 0xC1006E8C, 0xC1400010, 0x8D580000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0004840, 0xCC8400F8, 0x8000EB10, 0xC0001AC0, 0xCAC400F8, 0xC0004854, 0xCB4400F8, 0xA6C0F93A,
+ 0x00000000, 0x5EF40000, 0x8400F472, 0x5EF40002, 0x8400F702, 0x5EF40004, 0x8400F902, 0xC1006CE8,
+ 0xC1400010, 0x8D580000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC0800000, 0xDF4B0038,
+ 0xC0004900, 0xCB8000F8, 0xC2000000, 0xC000490A, 0xA78000D0, 0xCBC000F8, 0xC1000000, 0xD90000F9,
+ 0xC1000002, 0xD90C00F8, 0x6FF46000, 0x477DA000, 0x5B744C80, 0xC2400000, 0x58340004, 0xCA400078,
+ 0xC0004900, 0xCE000000, 0x5A640002, 0x58340004, 0xC6500078, 0xCD000078, 0xC0004914, 0xCA4000F8,
+ 0xC2000002, 0x6A3D0000, 0x72612000, 0xCE4000F8, 0xC0000408, 0xCE0000F8, 0xA78200D8, 0xC0004908,
+ 0xCBC000F8, 0xC1000000, 0xD90000F9, 0xC1000002, 0xD90C00F8, 0x6FF4A000, 0x6FD44000, 0x4755A000,
+ 0x477DA000, 0x5B747000, 0xC2800000, 0x58340006, 0xCA800078, 0xC2000000, 0xC0004900, 0xCE002100,
+ 0x5EA80002, 0x58340006, 0xC6900078, 0xCD000078, 0x5A7C0020, 0xC2000002, 0x6A250000, 0xC0000408,
+ 0xCE0000F8, 0xC0000032, 0xDCA800F9, 0xC1000002, 0x45294000, 0x00000000, 0x8C100006, 0x00000000,
+ 0x00000000, 0x00000000, 0xA4800230, 0x00000000, 0xC3C00000, 0xC000140E, 0xCBC00018, 0xC3400000,
+ 0xC2400000, 0x6FF86000, 0x47BDC000, 0x5BB84C80, 0x58380008, 0xCB400078, 0x58380006, 0xCA400078,
+ 0x5F740002, 0x58380008, 0xC7500078, 0xCD000078, 0xC2000000, 0x58380004, 0xCA020078, 0xC3000000,
+ 0x5838000C, 0xCB000020, 0x5A640002, 0x46610000, 0x84000010, 0xC2400000, 0x58380006, 0xC6500078,
+ 0xCD000078, 0xC2000000, 0x5838000A, 0xCA020078, 0x5B300002, 0x5838000C, 0xC7100020, 0xCD000020,
+ 0xC2420020, 0x5A200004, 0x46252000, 0x84000010, 0xC2000000, 0x5838000A, 0xC6101078, 0xCD021078,
+ 0xC0004966, 0xCA4000F8, 0xC2000002, 0x6A3D0000, 0x72612000, 0xCE4000F8, 0x5F740000, 0x84000040,
+ 0xC0004912, 0xCA0000F8, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x762D0000, 0xCE0000F8, 0x5F300020,
+ 0x84000040, 0xC0004924, 0xCA0000F8, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x762D0000, 0xCE0000F8,
+ 0xA4820070, 0xC2400000, 0xC000140E, 0xCA408018, 0xC2000002, 0xC0004900, 0xCE000000, 0xC000490A,
+ 0xCE4000F8, 0xC1000000, 0xD90000F9, 0xD8400078, 0xC1000004, 0xD90000F9, 0xA48402A8, 0x00000000,
+ 0xC3C00000, 0xC000140E, 0xCBC10018, 0xC2800000, 0xC2000000, 0x6FF8A000, 0x6FD44000, 0x4795C000,
+ 0x47BDC000, 0x5BB87000, 0x5838002E, 0xCA800078, 0x58380006, 0xCA020078, 0xC3400000, 0x5838002E,
+ 0xCB420078, 0x5AA80002, 0x46A10000, 0x84000010, 0xC2800000, 0x5838002E, 0xC6900078, 0xCD000078,
+ 0x5F740002, 0x5838002E, 0xC7501078, 0xCD021078, 0xC0004968, 0xCA4000F8, 0xC2000002, 0x6A3D0000,
+ 0x72612000, 0xCE4000F8, 0xC000492A, 0xCA8000F8, 0x5E740000, 0x84000040, 0xC0004910, 0xCA0000F8,
+ 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x762D0000, 0xCE0000F8, 0x6ABD4010, 0xA68000F2, 0x00000000,
+ 0xC0004910, 0xCA0000F8, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x762D0000, 0xCE0000F8, 0x58380032,
+ 0xCA0000F8, 0x58000002, 0xCA4000F8, 0x5838000C, 0x00000000, 0xCE0000F9, 0xCE4000F8, 0xC000492A,
+ 0xCA0000F8, 0xC2C00002, 0x6AFD6000, 0x722D0000, 0xCE0000F8, 0xC000492C, 0xCA0000F8, 0xC2C00002,
+ 0x6AFD6000, 0x722D0000, 0xCE0000F8, 0x80000040, 0xC000492C, 0xCA0000F8, 0xC2C00002, 0x6AFD6000,
+ 0x7EC16000, 0x762D0000, 0xCE0000F8, 0xA4880120, 0xC2C00000, 0xC000140E, 0xCAC20018, 0xC000490E,
+ 0xCA4000F8, 0xC2000002, 0x6A2D0000, 0x7E010000, 0x76612000, 0xCE4000F8, 0xC000496A, 0xCA4000F8,
+ 0xC2000002, 0x6A2D0000, 0x72612000, 0xCE4000F8, 0x6EF0A000, 0x6ED44000, 0x47158000, 0x472D8000,
+ 0x5B307000, 0x58300000, 0xCA0000F8, 0x00000000, 0xC2400002, 0x76612000, 0x8400004A, 0xC24C0002,
+ 0xC6E40018, 0xC624C400, 0x58300010, 0xCA400500, 0x00000000, 0xC0001800, 0xCE4000F8, 0xA4860070,
+ 0xC2400000, 0xC000140E, 0xCA418018, 0xC2020002, 0xC0004900, 0xCE002100, 0xC0004908, 0xCE4000F8,
+ 0xC1000000, 0xD90000F9, 0xD8400078, 0xC1000004, 0xD90000F9, 0xA48C0048, 0xC2800002, 0xC000484A,
+ 0xCE8000F8, 0xC2800000, 0xC000474A, 0xCE8000F8, 0xC0004846, 0xCE8000F8, 0xC0001408, 0xCC8000F8,
+ 0xC10E0002, 0xD90C00F8, 0x8000EA78, 0xDFBC00F9, 0xC000496E, 0x99008638, 0xC94000F8, 0xC7D800F8,
+ 0x00000000, 0xC57000F8, 0x5EF00020, 0x88000148, 0x6F346000, 0x4771A000, 0x5B744C80, 0x58340008,
+ 0xC2400000, 0xCA400078, 0x00000000, 0xC2000000, 0x5A640002, 0xCE400078, 0x58340004, 0xCA000078,
+ 0x00000000, 0x00000000, 0x5E200002, 0xCE000078, 0xC0004912, 0xCA8000F8, 0xC2400002, 0x6A712000,
+ 0x72A54000, 0xCE8000F8, 0x5E200000, 0x84000052, 0xC000480A, 0xCA0000F8, 0xC0000408, 0xCA8000F8,
+ 0x76250000, 0x00000000, 0x72A14000, 0xCE8000F8, 0x80000038, 0xC0004914, 0xCA0000F8, 0x7E412000,
+ 0x00000000, 0x76250000, 0xCE0000F8, 0x800000D0, 0x6EF4A000, 0x6ED44000, 0x4755A000, 0x476DA000,
+ 0x5B747000, 0x5834002E, 0xC2400000, 0xCA420078, 0x00000000, 0xC2000000, 0x5A640002, 0xC6501078,
+ 0xCD021078, 0x58340006, 0xCA000078, 0x00000000, 0x00000000, 0x5A200002, 0xCE000078, 0xC0004910,
+ 0xCA4000F8, 0xC2000002, 0x6A2D0000, 0x72612000, 0xCE4000F8, 0xC2000002, 0x6A310000, 0xC000042A,
+ 0xCE0000F8, 0xC1040002, 0xD90C00F8, 0x00000000, 0x8000E7E8, 0x00000000, 0xC4980928, 0x9D000000,
+ 0xC5580028, 0xC0000838, 0xCD8400F8, 0xC1440200, 0xC1C03800, 0xC55C1070, 0xC000100E, 0x9D000000,
+ 0xCD8000F8, 0xC000100C, 0xCDC000F8, 0xC0004862, 0xC9C000F8, 0x00000000, 0x00000000, 0xD9D800F9,
+ 0xC0007800, 0x401C0000, 0x5DC07A00, 0x88000012, 0x5C000200, 0xCD8000F8, 0xC1F0000A, 0x715CA000,
+ 0xDD9800F8, 0xDD9C00F9, 0x41D8E000, 0xC5D40260, 0xC0001010, 0xCD4000F8, 0x6C9C8000, 0x45C8E000,
+ 0x45C8E000, 0x59DC0004, 0xC1601260, 0xC5D40260, 0x9D000000, 0xC0001012, 0xCD4000F8, 0x00000000,
+ 0x00000000, 0xD95800F8, 0x6D586000, 0x4594C000, 0x59984C80, 0xD99800F9, 0x5818000A, 0xC1800000,
+ 0xC9800078, 0xC0006E00, 0x6D5CA000, 0x401C0000, 0x40180000, 0xC94000F8, 0x58000002, 0x00000000,
+ 0xC9C000F8, 0xC0004930, 0xCD4000F8, 0xC0004932, 0xCDC000F8, 0x59980004, 0xC1C20020, 0xB59C0018,
+ 0x00000000, 0xC1800000, 0xDD9C00F9, 0x581C000A, 0xCD800078, 0x581C000C, 0xC1800000, 0xC9800020,
+ 0xC1C00002, 0xDD9400F8, 0x69D4E000, 0x5D980002, 0xCD800020, 0xC0004924, 0xC98000F8, 0x00000000,
+ 0x9D000000, 0x00000000, 0x719CC000, 0xCD8000F8, 0xC000492A, 0xC94000F8, 0xC1C00002, 0x69D8E000,
+ 0x7DC0C000, 0x7558A000, 0xCD4000F8, 0xC000492C, 0xC94000F8, 0xDD8000F9, 0x58000032, 0x755CA000,
+ 0x84000090, 0xC94000F9, 0xC98000F8, 0xDD8000F9, 0x5800000C, 0x00000000, 0xCD4000F9, 0xCD8000F8,
+ 0xC000492C, 0xC94000F8, 0xC000492A, 0xC98000F8, 0x715CA000, 0xC000492C, 0xCD4000F8, 0x719CC000,
+ 0xC000492A, 0xCD8000F8, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0xC0004862, 0xC98000F8,
+ 0x00000000, 0xC1C00200, 0x4194C000, 0x459CE000, 0x88000012, 0xC5D800F8, 0xC0004862, 0xCD8000F8,
+ 0xC0001406, 0xC98000F8, 0xC1C00002, 0x9D000000, 0xC5D80A00, 0xC5581048, 0xCD8000F8, 0xC0004930,
+ 0xC98000F8, 0xC0004932, 0xC9C000F8, 0xC140000E, 0xC5581C18, 0xDD9400F8, 0xC0007800, 0x40140000,
+ 0x5D407A00, 0x88000012, 0x5C000200, 0xCD8000F8, 0x58000002, 0x5D407A00, 0x88000012, 0x5C000200,
+ 0xCDC000F8, 0xDD5400F8, 0xC1C00000, 0x58140006, 0xC9C20078, 0xC1800000, 0x58140000, 0xC98000D8,
+ 0x6DDC2000, 0xC000491E, 0x41D8E000, 0xCDC000F8, 0xDD9800F8, 0xC1C00022, 0xC5D80D70, 0xDD9400F9,
+ 0xC5581C18, 0xC000491C, 0xCD8000F8, 0xDD5400F8, 0xC1C00000, 0x58140006, 0xC9C20078, 0xC1800000,
+ 0x58140004, 0xC9820078, 0x00000000, 0x59DC0002, 0x45D8C000, 0x84000010, 0xC1C00000, 0x9D000000,
+ 0x58140006, 0xC5D81078, 0xCD821078, 0xC0004860, 0xC94000F8, 0xC1820080, 0xC1D00002, 0x58147700,
+ 0xD58000F8, 0x58000002, 0xD58000F9, 0x59540004, 0xB5580018, 0xC0004860, 0xC1400000, 0xCD4000F8,
+ 0xDD9800F9, 0x9D000000, 0xDD9400F8, 0xC0001404, 0xCDC10800, 0xC1C00000, 0xC1800200, 0x5D980004,
+ 0xDF5D0048, 0x459CA000, 0x8800FFF2, 0xDD8000F9, 0x5800000C, 0x00000000, 0xC94000F9, 0xC98000F8,
+ 0xC1C00002, 0xC5D43F00, 0xC5D81E00, 0xC0004862, 0xC9C000F8, 0x00000000, 0x00000000, 0x581C7800,
+ 0x5DC07A00, 0x88000012, 0x5C000200, 0xCD4000F8, 0x58000002, 0x5DC07A00, 0x88000012, 0x5C000200,
+ 0xCD8000F8, 0xC0004862, 0xC9C000F8, 0x00000000, 0xC15004C0, 0xC5D40060, 0xDD9C00F8, 0xC5D41C18,
+ 0xC1C00000, 0xDD8000F9, 0x58000030, 0xC9C00078, 0xDD8000F9, 0x58000002, 0xC98000F8, 0x6DDC2000,
+ 0xC000491C, 0x41D8E000, 0xCD4000F9, 0xCDC000F8, 0xDD9400F9, 0xC1C00000, 0x58140030, 0xC9C00078,
+ 0xC1800000, 0x58140006, 0xC9820078, 0x00000000, 0x59DC0002, 0x45D8C000, 0x84000010, 0xC1C00000,
+ 0x9D000000, 0x58140030, 0xC5D80078, 0xCD800078, 0xC1C00000, 0xDF5C0038, 0x5DDC0080, 0x8400FFEA,
+ 0x00000000, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0xC160FFFE, 0xC0000A10, 0xC9440060,
+ 0xC1A0FFFE, 0x59983008, 0xC000100C, 0xCD4000F8, 0xC000100E, 0xCD8000F8, 0xC0004964, 0xC98000F8,
+ 0x00000000, 0xC170000A, 0x7158A000, 0x6C988000, 0x4588C000, 0x4588C000, 0x59980004, 0xC5940270,
+ 0xC0001010, 0xCD4000F8, 0xC0004946, 0xC94000F8, 0x00000000, 0x00000000, 0x6D58A000, 0x6D5C4000,
+ 0x459CC000, 0x4594C000, 0xC000494A, 0xC94000F8, 0xC0004948, 0xC9C000F8, 0x4194C000, 0xC1400012,
+ 0xC55C1818, 0x9D000000, 0xC59C0268, 0xC0001012, 0xCDC000F8, 0xC1400000, 0x58000012, 0xC9410038,
+ 0xC0004950, 0xC9C000F8, 0xC55800F8, 0xC5940838, 0xC5581078, 0xD99400F8, 0xC000493C, 0xC94000F8,
+ 0xC0004954, 0xC98000F8, 0x59DC00A8, 0x45D4E000, 0x41D8E000, 0x5D5C0030, 0x88000010, 0xC1C00030,
+ 0xC1800000, 0xC5D84028, 0xC1400000, 0xC5D40008, 0x5DD40002, 0x84000072, 0x5DD40004, 0x8400009A,
+ 0x5DD40006, 0x840000C2, 0x5DD80026, 0x840000EA, 0xDD5400F8, 0xDD8000F9, 0x58000008, 0x40180000,
+ 0xCD4000F8, 0x59980002, 0x8000FFC0, 0xDD5400F8, 0xDD8000F9, 0x58000008, 0x40180000, 0xCD4000B8,
+ 0x59980002, 0x8000FF88, 0xDD5400F8, 0xDD8000F9, 0x58000008, 0x40180000, 0xCD400078, 0x59980002,
+ 0x8000FF50, 0xDD5400F8, 0xDD8000F9, 0x58000008, 0x40180000, 0xCD400038, 0x59980002, 0x8000FF18,
+ 0x00000000, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0x58000012, 0xC94000F8, 0xC0004954,
+ 0xC9C000F8, 0xC0004950, 0xC9400078, 0xDD8000F9, 0x58000028, 0x5D9C0000, 0x84000052, 0x5D9C0002,
+ 0x84000052, 0x5D9C0004, 0x8400006A, 0xC55B0038, 0xC55C08B8, 0xCD800039, 0xCDC108B8, 0x80000060,
+ 0xCD4000F8, 0x80000050, 0xC55900B8, 0xC55C1838, 0xCD8000B9, 0xCDC31838, 0x80000028, 0xC55A0078,
+ 0xC55C1078, 0xCD800079, 0xCDC21078, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0x59540002,
+ 0x6994E018, 0x61C0C008, 0x4194A000, 0x5D940040, 0x88000012, 0xC59400F8, 0x9D000000, 0xCD4000F8,
+ 0x00000000, 0x00000000, 0x9D000000, 0x4158A000, 0xCD4000F8, 0x00000000, 0xCD8000F9, 0x45408000,
+ 0x8800FFF0, 0x00000000, 0x9CC00000, 0x00000000, 0x00000000, 0x00000000, 0xC0004810, 0xCA010038,
+ 0xC241FFFE, 0xC1400000, 0x46148000, 0x00000000, 0x9CC00006, 0xC0004200, 0x40180000, 0xC9C000F8,
+ 0x00000000, 0x00000000, 0x61C08010, 0x8400005A, 0xC2400002, 0x6A512000, 0x71E4E000, 0xCDC000F8,
+ 0xC0004748, 0xCD8000F8, 0x9CC00000, 0x6D98A000, 0x5998003E, 0x45912000, 0x59540002, 0x59980002,
+ 0x46188000, 0xC1000000, 0xC51800FE, 0x8000FF38, 0x00000000, 0x40180000, 0xC9C000F8, 0xC2000000,
+ 0xC5600020, 0xC1210000, 0x69208010, 0x7D008000, 0x75D0E000, 0xCDC000F8, 0x6D542000, 0x58144300,
+ 0xC1000000, 0xCD0000F9, 0x9CC00000, 0xC121FFFE, 0x5911FFFE, 0xCD0000F9, 0x79588000, 0x6D10A010,
+ 0x5D100000, 0x840000C0, 0x45948000, 0x880000B0, 0x6D536000, 0x6D136010, 0x6D54A010, 0xC0004700,
+ 0x40140000, 0xCA0000F8, 0x00000000, 0x00000000, 0x6A110000, 0x6A110010, 0x62008018, 0x84000032,
+ 0x00000000, 0x9CC00000, 0x6D54A000, 0x5954003E, 0x45512000, 0x59540002, 0x6D57A000, 0x6D57A010,
+ 0x6D54A000, 0x6D936000, 0x6D136010, 0xC1E10000, 0x69D0E010, 0x5DDC0002, 0x7DC0E000, 0x6D98A010,
+ 0x6D536000, 0x6D136010, 0x6D54A010, 0xC0004700, 0x40140000, 0xCA0000F8, 0x00000000, 0x00000000,
+ 0x6A110000, 0x6A110010, 0x45588000, 0x00000000, 0x761D0002, 0x62008018, 0x84000032, 0x00000000,
+ 0x9CC00000, 0x6D54A000, 0x5954003E, 0x45512000, 0x45588000, 0x00000000, 0x9CC00002, 0x59540002,
+ 0x6D57A000, 0x6D57A010, 0xC0004700, 0x40140000, 0xCA0000F8, 0x8000FF68, 0x00000000, 0x00000000,
+ 0x00000000, 0x58004700, 0xC98000F8, 0x9CC00000, 0x00000000, 0x6994C000, 0x6DA7E010, 0x58004700,
+ 0xC98000F8, 0xC1210000, 0x9CC00000, 0x69148010, 0x7190C000, 0xCD8000F8, 0xC1000000, 0xC0004810,
+ 0xC9020038, 0x00000000, 0x00000000, 0x45D0C000, 0x88000062, 0xC2400002, 0x45588000, 0xC1000000,
+ 0xC52400FC, 0x45D48000, 0xC1000000, 0xC52400FE, 0x9CC00000, 0x00000000, 0x00000000, 0x00000000,
+ 0x59980200, 0xC2400000, 0x455C8000, 0xC1000002, 0xC52400FC, 0x45948000, 0xC1000002, 0xC52400FE,
+ 0x9CC00000, 0x00000000, 0x00000000, 0x00000000, 0xC0004740, 0xC9C000F8, 0x59180002, 0x6D130000,
+ 0x6D130010, 0x451C8000, 0xC2400000, 0x9CC00002, 0x00000000, 0x00000000, 0x459C8000, 0x88000062,
+ 0xC2400002, 0x455C8000, 0xC1000000, 0xC52400FC, 0x45948000, 0xC1000000, 0xC52400FC, 0x9CC00000,
+ 0x00000000, 0x00000000, 0x00000000, 0xC2400000, 0x45588000, 0xC1000002, 0xC52400FE, 0x45D48000,
+ 0xC1000002, 0xC52400FE, 0x9CC00000, 0x00000000, 0x00000000, 0x00000000, 0x59540002, 0x6D570000,
+ 0x6D570010, 0x45588000, 0x6D402000, 0x9CC00002, 0x58004300, 0x58000000, 0xC13C0002, 0xCD03DE00,
+ 0x8000FFB0, 0x00000000, 0x00000000, 0x00000000, 0xC1020002, 0xD90C00F8, 0xC98000F8, 0x59540002,
+ 0xC0004730, 0xCD4000F8, 0x5D980002, 0x00000000, 0x80000036, 0x00000000, 0x9CC00000, 0xC0004732,
+ 0xCD8000F8, 0x00000000, 0xC0004734, 0xC9C000F8, 0xC1800000, 0xC0004816, 0xC9820078, 0xC0004738,
+ 0xCDC000F8, 0xC1C00000, 0xC0004734, 0x9CC00000, 0xCDC000F8, 0xC0004732, 0xCD8000F8,
+};
+
+static unsigned int firmware_binary_data[] = {
+};
+
+
+#endif // IFXMIPS_ATM_FW_AR9_H
diff --git a/package/ltq-dsl/src/ifxmips_atm_fw_danube.h b/package/ltq-dsl/src/ifxmips_atm_fw_danube.h
new file mode 100644
index 000000000..fff0d31e5
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_fw_danube.h
@@ -0,0 +1,440 @@
+#ifndef IFXMIPS_ATM_FW_DANUBE_H
+#define IFXMIPS_ATM_FW_DANUBE_H
+
+
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_fw_danube.h
+** PROJECT : Danube
+** MODULES : ATM (ADSL)
+**
+** DATE : 1 AUG 2005
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM Driver (PP32 Firmware)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 4 AUG 2005 Xu Liang Initiate Version
+** 23 OCT 2006 Xu Liang Add GPL header.
+*******************************************************************************/
+
+
+#define VER_IN_FIRMWARE 1
+
+#define ATM_FW_VER_MAJOR 0
+#define ATM_FW_VER_MINOR 17
+
+
+static unsigned int firmware_binary_code[] = {
+ 0x800004A0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000FFC8, 0x00000000, 0x00000000, 0x00000000,
+ 0xC1000002, 0xD90C0000, 0xC2000002, 0xDA080001, 0x80004968, 0xC2000000, 0xDA080001, 0x80003FD0,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x80003F88, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x80005160, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x80003E88, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0400000, 0xC0004840, 0xC8840000, 0x80004628, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0400002, 0xC0004840, 0xC8840000, 0x800045A8, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC3C00004, 0xDBC80001, 0xC10C0002, 0xD90C0000, 0x8000FEC8, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC10E0002, 0xD90C0000, 0xC0004808, 0xC8400000, 0x800045D8, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC3E1FFFE, 0x597DFFFE, 0x593DFE14, 0x900004D9, 0x00000000, 0x00000000, 0x00000000, 0x90CC0481,
+ 0x00000000, 0x00000000, 0x00000000, 0xC3C00000, 0xDBC80001, 0xC1400008, 0xC1900000, 0x71948000,
+ 0x15000100, 0xC140000A, 0xC1900002, 0x71948000, 0x15000100, 0xC140000C, 0xC1900004, 0x71948000,
+ 0x15000100, 0xC1400004, 0xC1900006, 0x71948000, 0x15000100, 0xC1400006, 0xC1900008, 0x71948000,
+ 0x15000100, 0xC140000E, 0xC190000A, 0x71948000, 0x15000100, 0xC1400000, 0xC190000C, 0x71948000,
+ 0x15000100, 0xC1400002, 0xC190000E, 0x71948000, 0x15000100, 0xC0400000, 0xC11C0000, 0xC000082C,
+ 0xCD040E08, 0xC11C0002, 0xC000082C, 0xCD040E08, 0xC0400002, 0xC11C0000, 0xC000082C, 0xCD040E08,
+ 0xC11C0002, 0xC000082C, 0xCD040E08, 0xC0000824, 0x00000000, 0xCBC00001, 0xCB800001, 0xCB400001,
+ 0xCB000000, 0xC0004878, 0x5BFC4000, 0xCFC00001, 0x5BB84000, 0xCF800001, 0x5B744000, 0xCF400001,
+ 0x5B304000, 0xCF000000, 0xC0000A10, 0x00000000, 0xCBC00001, 0xCB800000, 0xC0004874, 0x5BFC4000,
+ 0xCFC00001, 0x5BB84000, 0xCF800000, 0xC30001FE, 0xC000140A, 0xCF000000, 0xC3000000, 0x7F018000,
+ 0xC000042E, 0xCF000000, 0xC000040E, 0xCF000000, 0xC3C1FFFE, 0xC000490E, 0xCFC00080, 0xC000492C,
+ 0xCFC00080, 0xC0004924, 0xCFC00040, 0xC0004912, 0xCFC00040, 0xC0004966, 0xCFC00040, 0xC0004968,
+ 0xCFC00080, 0xC000496A, 0xCFC00080, 0xC3C1FFFE, 0xC00049A0, 0xCFC00000, 0xC3C00000, 0xC2800020,
+ 0xC3000000, 0x7F018000, 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB84A00, 0x5838000A, 0xCF000000,
+ 0x5BFC0002, 0xB7E8FFA8, 0x00000000, 0xC3C00000, 0xC2800010, 0x6FF86000, 0x47F9C000, 0x5BB84C80,
+ 0xC3400000, 0x58380004, 0xCB420080, 0x00000000, 0x58380008, 0xCF400080, 0x5BFC0002, 0xB7E8FF90,
+ 0x00000000, 0xC3C00000, 0xC2800020, 0xC348001E, 0xC3000000, 0x7F018000, 0x6FF8A000, 0x6FD44000,
+ 0x4579C000, 0x47F9C000, 0x5BB84E20, 0x58380008, 0xCF400420, 0x5838000A, 0xCF000000, 0x5BFC0002,
+ 0xB7E8FF90, 0x00000000, 0x00000000, 0xC3E02242, 0x5BFC0022, 0xC0004002, 0xCFC00000, 0x00000000,
+ 0xC121FFFE, 0x5911FE14, 0x15000000, 0x80000518, 0x00000000, 0x80002118, 0x00000000, 0x8000FFC8,
+ 0xC0004958, 0xC8400000, 0x00000000, 0xC3C00002, 0x7BC42000, 0xCC400000, 0xC0004848, 0xCB840000,
+ 0xC000495C, 0xCAC40000, 0xC0004844, 0xC8840000, 0x46F90000, 0x8400FF6A, 0xC000487C, 0xC8040000,
+ 0x00000000, 0x00000000, 0x40080000, 0xCA000000, 0xC0001624, 0xCB040000, 0xA63C005A, 0x00000000,
+ 0x00000000, 0xA71EFF02, 0x00000000, 0xC0000824, 0xCA840000, 0x6CA08000, 0x6CA42000, 0x46610000,
+ 0x42290000, 0xC35E0002, 0xC6340068, 0xC0001624, 0xCF440080, 0xC2000000, 0xC161FFFE, 0x5955FFFE,
+ 0x15400000, 0x00000000, 0xC0004844, 0xC8840000, 0xC000082C, 0xCA040040, 0x00000000, 0x00000000,
+ 0x58880002, 0xB608FFF8, 0x00000000, 0xC0800000, 0xC0004844, 0xCC840040, 0x5AEC0002, 0xC000495C,
+ 0xCEC40000, 0x5E6C0006, 0x84000048, 0xC0004848, 0xCB840000, 0xC0000838, 0xC2500002, 0xCE440808,
+ 0x5FB80002, 0xC0004848, 0xCF840000, 0x5EEC0002, 0xC000495C, 0xCEC40000, 0x00000000, 0xC121FFFE,
+ 0x5911FE14, 0x15000000, 0x8000FD80, 0xC000495A, 0xC8400000, 0x00000000, 0xC3C00002, 0x7BC42000,
+ 0xCC400000, 0xC0004960, 0xCAC40000, 0x00000000, 0x00000000, 0x5EEC0000, 0x840000F2, 0x00000000,
+ 0xB6FC0030, 0xC0001600, 0xCA040000, 0x00000000, 0x00000000, 0xA61E00B2, 0x6FE90000, 0xC0000A28,
+ 0xCE840808, 0xC2C00000, 0xC2800004, 0xB6E80080, 0xC0001604, 0xCA840000, 0xC0004960, 0xCEC40000,
+ 0xA69EFCA2, 0x00000000, 0x6FE90000, 0xC0000A28, 0xCE840808, 0xC2C00002, 0xC0001600, 0xCA040000,
+ 0x00000000, 0x00000000, 0xA61E000A, 0x6FE90000, 0xC0000A28, 0xCE840808, 0xC2C00000, 0xC0001604,
+ 0xCA840000, 0xC0004960, 0xCEC40000, 0xA69EFC0A, 0xC2400000, 0xC0000A14, 0xCA440030, 0x00000000,
+ 0x00000000, 0x46E52000, 0xA4400000, 0xC2800000, 0xDFEB0031, 0x8000FFF8, 0xDFEA0031, 0xB668FB82,
+ 0x00000000, 0xC00048A0, 0xCB040000, 0xC0000A10, 0xCA840000, 0x6F208000, 0x6F242000, 0x46610000,
+ 0x42A10000, 0xC2400000, 0xC0000A14, 0xCA440030, 0xC35E0002, 0xC6340068, 0xC0001604, 0xCF440080,
+ 0x5B300002, 0xB670FFF8, 0x5AEC0002, 0xC3000000, 0xC00048A0, 0xCF040000, 0xC0004960, 0xCEC40000,
+ 0x8000FAC0, 0xC0004918, 0xD2800000, 0xC2000000, 0xDF600040, 0x5E600080, 0x8400025A, 0x00000000,
+ 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0xC000480A, 0xCA000000, 0xC0004912, 0xCA400000,
+ 0xC0004924, 0xCA800000, 0xC0004966, 0xCAC00000, 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000,
+ 0x76610000, 0x76A10000, 0x76E10000, 0x840001B2, 0xC0004918, 0xCA400000, 0xC28001FE, 0x76A10000,
+ 0x5A640002, 0x6A254010, 0x5EE80000, 0x84000002, 0x6AA54000, 0x8000FFF8, 0xC6280000, 0x62818008,
+ 0xC0004918, 0xCF000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0xC0004966, 0xCA400000,
+ 0xC2000002, 0x6A310000, 0x7E010000, 0x76252000, 0xCE400000, 0x00000000, 0xC121FFFE, 0x5911FE14,
+ 0x15000000, 0x6F346000, 0x4735A000, 0x5B744C80, 0xC2800000, 0x58340006, 0xCA800080, 0xC2C00000,
+ 0x58340000, 0xCAC000E0, 0xC2400000, 0x5834000A, 0xCA420080, 0x6EA82000, 0x42E9E000, 0x6F2CA000,
+ 0x42E56000, 0x5AEC1400, 0xC3990040, 0xC7381C20, 0xC6F80068, 0x99005B78, 0xDB980000, 0xDBD80001,
+ 0x00000000, 0xDEA00000, 0x47210000, 0x8400FD68, 0xC0004958, 0xC8400000, 0x00000000, 0xC3C00002,
+ 0x7BC42000, 0xCC400000, 0xC0004848, 0xCB840000, 0xC0004844, 0xC8840000, 0x5FB80000, 0x8400F7DA,
+ 0xC0001A1C, 0xCA000000, 0xC2400002, 0x6A452000, 0x76610000, 0x8400F7AA, 0xC000487C, 0xC8040000,
+ 0x00000000, 0x00000000, 0x40080000, 0xCA000000, 0xC4240000, 0x00000000, 0xA63C17BA, 0x00000000,
+ 0xC0004878, 0xC8040000, 0x6C908000, 0x44908000, 0x44908000, 0x40100000, 0xCA000000, 0xC4240000,
+ 0x00000000, 0xC0004934, 0xCE000000, 0xC2800002, 0xC4681C10, 0xC62821D8, 0xC2600010, 0x5A650040,
+ 0xC0004800, 0xCB400000, 0xC2200400, 0x5A200000, 0xC7601048, 0xC0001220, 0xCE800000, 0xC0001200,
+ 0xCE400000, 0xC0001202, 0xCE000000, 0xC0001240, 0xCB400000, 0x00000000, 0x00000000, 0xA754FFC0,
+ 0xC2000000, 0xC7600048, 0xA7520022, 0x00000000, 0x00000000, 0x990062F0, 0xC0004822, 0xC9400000,
+ 0xC1800002, 0x80001668, 0x58204080, 0xC2000000, 0xCA000020, 0xC2400000, 0xCA414008, 0xC2800000,
+ 0xCA812008, 0xC2C00000, 0xCAC20020, 0xC0004938, 0xCE000000, 0xC0004920, 0xCE400000, 0xC0004916,
+ 0xCE800000, 0xC0004922, 0xCEC00000, 0xA6400520, 0x00000000, 0xC0004938, 0xCBC00000, 0x00000000,
+ 0xC3800000, 0x6FF48000, 0x6FD44000, 0x4355A000, 0x5B744A00, 0x58340000, 0xCB802018, 0x00000000,
+ 0xC2000000, 0x6FB46000, 0x47B5A000, 0x5B744C80, 0x5834000C, 0xCA000028, 0xC000491A, 0xCF800000,
+ 0x5E200000, 0x84000452, 0xC2000000, 0xDF610050, 0x5E6001E8, 0x8800FFD0, 0xC2000002, 0xC2400466,
+ 0xC2A00000, 0x5AA80000, 0xC0001006, 0xCE000000, 0xC0001008, 0xCE400000, 0xC000100A, 0xCE800000,
+ 0x990055B8, 0xC1A0FFFE, 0xC0000824, 0xC9840068, 0xC0004934, 0xCA400000, 0xC2000000, 0xC2800002,
+ 0x990055F8, 0xDA980000, 0xC6140000, 0xC6580000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000,
+ 0x990056E0, 0xC000491A, 0xC9400000, 0x00000000, 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000,
+ 0xC0004922, 0xCA001120, 0xC3C00000, 0xC3800000, 0xC0004930, 0xCE001120, 0xC0004932, 0xCBC000E0,
+ 0xC2800000, 0xC000491E, 0xCFC00000, 0xC0004862, 0xCA800068, 0xC3A0001A, 0x5BB94000, 0xC6B80068,
+ 0xC000491C, 0xCF800000, 0x99005950, 0xC000491C, 0xC1400000, 0xC9420050, 0x00000000, 0x00000000,
+ 0x00000000, 0xA8E2FFC8, 0xC2000000, 0xC1220002, 0xD90C0000, 0xDF600040, 0x5E600080, 0x8400FFDA,
+ 0xC000491C, 0xCA000000, 0xC000491E, 0xCA400000, 0x00000000, 0x00000000, 0x99005B78, 0xDA180000,
+ 0xDA580001, 0x00000000, 0xC2000000, 0xDF610050, 0x5E6001FE, 0x8800FFD0, 0xC0004916, 0xCA800000,
+ 0xC2C00000, 0xDFEC0050, 0xC2400000, 0x46E52000, 0x84000032, 0x5EA80000, 0x84000022, 0xC2600002,
+ 0x990062F0, 0xC000482E, 0xC9400000, 0xC1800002, 0x80000018, 0xC2600000, 0x990062F0, 0xC000482C,
+ 0xC9400000, 0xC1800002, 0xC2000068, 0xC6240080, 0xC0004930, 0xCE400088, 0xC000491A, 0xC9800000,
+ 0xC0004862, 0xC9400000, 0x6D9C6000, 0x459CE000, 0x59DC4C80, 0x990059D8, 0xD9580000, 0xD9980001,
+ 0xD9D40000, 0x99005950, 0xC000491C, 0xC1400000, 0xC9420050, 0xC2000000, 0xDF600040, 0x5E600080,
+ 0x8400FFD2, 0x00000000, 0xC000491C, 0xCA000000, 0xC000491E, 0xCA400000, 0x00000000, 0x00000000,
+ 0x99005B78, 0xDA180000, 0xDA580001, 0x00000000, 0x800010D0, 0x00000000, 0x990062F0, 0xC000482A,
+ 0xC9400000, 0xC1800002, 0x800010A0, 0xC0004938, 0xCBC00000, 0x00000000, 0x00000000, 0x6FF88000,
+ 0x6FD44000, 0x4395C000, 0x5BB84A00, 0x58380008, 0xCA000000, 0x00000000, 0x00000000, 0xA6000362,
+ 0x00000000, 0xC0004938, 0xCBC00000, 0xC3000000, 0x00000000, 0x6FF88000, 0x6FD44000, 0x4395C000,
+ 0x5BB84A00, 0x58380000, 0xCB002018, 0xC2000000, 0x58380008, 0xCA020080, 0x5838000C, 0xCAC00000,
+ 0x5838000E, 0xCA400000, 0xC000491A, 0xCF000000, 0xC0004930, 0xCEC00000, 0xC000493C, 0xCE000000,
+ 0xC0004932, 0xCE400000, 0x5E200000, 0x84000108, 0xC2800000, 0xA6FE009A, 0x6F206000, 0x47210000,
+ 0x5A204C80, 0x5820000C, 0xCA800028, 0x00000000, 0x00000000, 0x5EA80000, 0x840001DA, 0x00000000,
+ 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x990056E0, 0xC000491A, 0xC9400000, 0x00000000,
+ 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000, 0xC0004930, 0xCAC00000, 0xC0004932, 0xCA400000,
+ 0xC7EC1120, 0xC0004930, 0xCEC00000, 0x5838000C, 0xCEC00000, 0x58000002, 0xCE400000, 0xC0004934,
+ 0xCA000000, 0xC2400002, 0x6E642000, 0x6E642000, 0x76252000, 0x84000012, 0xC2400002, 0x6E684000,
+ 0x58380008, 0xCE800208, 0xA6000000, 0x6E682000, 0x58380008, 0xCE800108, 0xC2400002, 0x6E642000,
+ 0x76252000, 0x840000D2, 0x58380008, 0xCA000000, 0xC2800000, 0xC2400000, 0xA60200A0, 0xDBA80000,
+ 0x6F386000, 0x4739C000, 0x5BB84C80, 0x58380004, 0xCA400080, 0x58380002, 0xCA800080, 0x00000000,
+ 0xDEB80000, 0x46694000, 0x88000048, 0x00000000, 0xC0004824, 0xCA000000, 0xC2400002, 0x6E640000,
+ 0x5A200002, 0xCE000000, 0x58380008, 0xCE400008, 0x80000000, 0x00000000, 0x80000030, 0xC0004934,
+ 0xCA000000, 0x00000000, 0x00000000, 0xA6020C4A, 0x00000000, 0x00000000, 0x80000C80, 0xC2800000,
+ 0xC2000200, 0xC240001A, 0xDF690050, 0x46A14000, 0x46694000, 0x8800FFBA, 0xC2000006, 0xC2600982,
+ 0x5A643B6E, 0x5838000A, 0xCA800000, 0xC0001006, 0xCE000000, 0xC0001008, 0xCE400000, 0xC000100A,
+ 0xCE800000, 0x990055B8, 0xC1A0FFFE, 0xC0000824, 0xC9840068, 0xC2000000, 0xC0004930, 0xCA02E010,
+ 0x58380026, 0xCA400000, 0x00000000, 0xC2800000, 0x990055F8, 0xDA980000, 0xC6140000, 0xC6580000,
+ 0xC0004934, 0xCA000000, 0x00000000, 0x00000000, 0xA6020002, 0x00000000, 0x00000000, 0x80000300,
+ 0xC0004938, 0xCBC00000, 0xC0004878, 0xC8040000, 0x6C908000, 0x44908000, 0x44908000, 0x40100000,
+ 0xCA000000, 0xC4240000, 0x00000000, 0x58240018, 0xCA000000, 0x6FF88000, 0x6FD44000, 0x4395C000,
+ 0x5BB84A00, 0xC3000000, 0xC3400002, 0xC2C00000, 0xC62C0080, 0xC6270040, 0xC0004940, 0xCE400040,
+ 0xC6260040, 0xC0004942, 0xCE400040, 0xC000493C, 0xCA000000, 0x5EEC0000, 0x84000172, 0x5A6C0010,
+ 0x46614000, 0x88000178, 0x5A600052, 0x466D4000, 0x88000160, 0x58380006, 0xCA800000, 0xC0004940,
+ 0xCA000000, 0xC2400000, 0xC6A70040, 0x7E412000, 0x76252000, 0xC2000000, 0xC6A10040, 0x46610000,
+ 0x84000120, 0xC0004942, 0xCA000000, 0xC2400000, 0xC6A60040, 0x7E412000, 0x76252000, 0xC2000000,
+ 0xC6A00040, 0x58380002, 0xCA800000, 0x46610000, 0x840000D0, 0xC2400000, 0xC6A60080, 0x46E50000,
+ 0x880000C2, 0xC2400000, 0xC6A40080, 0x58380008, 0xCA800000, 0x466D0000, 0x880000A2, 0x00000000,
+ 0xA682FFF8, 0x00000000, 0xC7700B08, 0xA6840078, 0x00000000, 0xC7700A08, 0x80000068, 0xC7700208,
+ 0xC000493C, 0xCAC00000, 0x80000048, 0xC7700308, 0xC000493C, 0xCAC00000, 0x80000028, 0xC7700908,
+ 0x80000018, 0xC7700808, 0x80000008, 0xC7700708, 0x8000FFF8, 0xC7700508, 0xC0004944, 0xCF000000,
+ 0xC000493E, 0xCEC00000, 0xC0004938, 0xCA400000, 0xC000493C, 0xCB800000, 0xC000493E, 0xCB400000,
+ 0xC3000000, 0x6E608000, 0x6E544000, 0x42150000, 0x5A204A00, 0x5AA00008, 0x58200004, 0xCB000080,
+ 0xC0004934, 0xCA000000, 0xC2400000, 0xC0004930, 0xCA42E010, 0xC3C00018, 0xA6020078, 0x00000000,
+ 0x43656000, 0x46F90000, 0x88000038, 0x47AD6000, 0x6EE04010, 0x5BE00004, 0xC2000000, 0xC6E00010,
+ 0x5E200000, 0x8400002A, 0x5BFC0002, 0x80000018, 0xC3C00004, 0x5A2C0008, 0x46390000, 0x8800FFFA,
+ 0x5FB80008, 0x6FE04000, 0x42390000, 0x46312000, 0x88000050, 0xC2400000, 0xC0004930, 0xCA42E010,
+ 0xC2060002, 0xC6800000, 0xCE000308, 0x6FE04000, 0x4631C000, 0x5F700010, 0x4675A000, 0xC2000000,
+ 0xC6340010, 0xC25A000A, 0xC000491A, 0xCA401C20, 0xC2800000, 0xC0004932, 0xCA8000E0, 0xC0004862,
+ 0xCA400068, 0x6FA04010, 0x42290000, 0xC000491E, 0xCE000000, 0xC7E41050, 0xC000491C, 0xCE400000,
+ 0x6FE04000, 0x43A1C000, 0xC000493C, 0xCF800000, 0xC000493E, 0xCF400000, 0xC000493A, 0xCFC00000,
+ 0x8000FFF0, 0x00000000, 0x00000000, 0x00000000, 0xC2000000, 0xDCE00000, 0xA622FFB8, 0xC1220002,
+ 0xD90C0000, 0xC0004938, 0xCBC00000, 0xC0004944, 0xCB400000, 0xC0004862, 0xCB000000, 0xC0004934,
+ 0xCA000000, 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB84A00, 0xA6020248, 0xC2400000, 0x58380008,
+ 0xCA406008, 0xDFE80000, 0xC2218E08, 0x5A21BAF6, 0x46294000, 0x8400000A, 0xC2080002, 0x7235A000,
+ 0x80000040, 0x5E640000, 0x8400000A, 0xC20C0002, 0x7235A000, 0x80000018, 0xC2000000, 0xC760E718,
+ 0xC7604220, 0x5E200000, 0x8400025A, 0xC2200002, 0xC0004930, 0xCE001008, 0x990062F0, 0xC0004828,
+ 0xC9400000, 0xC1800002, 0x58380000, 0xCA000000, 0x00000000, 0x00000000, 0xA6000112, 0xC0004940,
+ 0xCA800000, 0xC0004942, 0xCA400000, 0xC7600080, 0xC6A01840, 0xC6601040, 0xC000493A, 0xCA400000,
+ 0xC0004934, 0xCA800000, 0xC0007200, 0x40300000, 0x40240000, 0x5C000004, 0x5EC07400, 0x8800FFFA,
+ 0x5C000200, 0xCE000000, 0x58000002, 0x5EC07400, 0x8800FFFA, 0x5C000200, 0xCE800000, 0xC000493E,
+ 0xCA000000, 0xC2400000, 0x5838000C, 0xCE400000, 0x990062F0, 0xC0004830, 0xC9400000, 0xC6180000,
+ 0xC0004930, 0xC6100080, 0xCD000080, 0x80000090, 0xC2400002, 0x58380008, 0xCE400008, 0xC0004944,
+ 0xCF400000, 0x80000260, 0xC000493C, 0xCA400000, 0xDFE80000, 0x5A300018, 0xC0007200, 0x40200000,
+ 0xCA000000, 0x58380008, 0xC6501080, 0xCD001080, 0x5838000A, 0xCE800000, 0x58380026, 0xCE000000,
+ 0xC0004944, 0xCF400000, 0x99005950, 0xC000491C, 0xC1400000, 0xC9420050, 0x80000020, 0x00000000,
+ 0x990062F0, 0xC0004826, 0xC9400000, 0xC1800002, 0x8000FDC0, 0xC2000000, 0xC2400080, 0xDF600040,
+ 0xB624FFCA, 0xC000491C, 0xCA400000, 0xC000491E, 0xCA800000, 0x99005B78, 0xDA580000, 0xDA980001,
+ 0x00000000, 0xC0004934, 0xCA000000, 0x00000000, 0xC2800000, 0xA6020140, 0xC2400004, 0xC2000200,
+ 0xDF690050, 0x46A14000, 0x46694000, 0x8800FFC2, 0x00000000, 0xC000491A, 0xC9800000, 0xC0004862,
+ 0xC9400000, 0x6D9C6000, 0x459CE000, 0x59DC4C80, 0x990059D8, 0xD9580000, 0xD9980001, 0xD9D40000,
+ 0x99005950, 0xC000491C, 0xC1400000, 0xC9420050, 0xC2000000, 0xC2400080, 0xDF600040, 0xB624FFCA,
+ 0xC000491C, 0xCA400000, 0xC000491E, 0xCA800000, 0x99005B78, 0xDA580000, 0xDA980001, 0x00000000,
+ 0x58380008, 0xCA400000, 0xC2000000, 0xCE000020, 0xC2A1FFFE, 0x5AA9FFFE, 0xCE001080, 0x5838000A,
+ 0xCE800000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0xC0000838, 0xC2500002, 0xCE440808,
+ 0xC0004848, 0xCB840000, 0xC2000000, 0xC000082C, 0xCA040030, 0x5FB80002, 0xC0004848, 0xCF840000,
+ 0x58880002, 0xB608FFF8, 0x00000000, 0xC0800000, 0xC0004844, 0xCC840000, 0x00000000, 0xC121FFFE,
+ 0x5911FE14, 0x15000000, 0x8000DEC0, 0xC2000000, 0xDF600040, 0x5E200080, 0x84000252, 0x00000000,
+ 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0xC000480C, 0xCA000000, 0xC0004910, 0xCA400000,
+ 0xC000492C, 0xCA800000, 0xC0004968, 0xCAC00000, 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000,
+ 0x76610000, 0x76A10000, 0x762D6000, 0x840001AA, 0xC0004926, 0xCA400000, 0xC201FFFE, 0x762D6000,
+ 0x5A640002, 0x6AE50010, 0x5F200000, 0x84000002, 0x6A250000, 0x8000FFF8, 0xC6E00000, 0x62014008,
+ 0xC0004926, 0xCE800000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0xC0004968, 0xCA400000,
+ 0xC2000002, 0x6A290000, 0x7E010000, 0x76252000, 0xCE400000, 0x00000000, 0xC121FFFE, 0x5911FE14,
+ 0x15000000, 0x6EB4A000, 0x6E944000, 0x4575A000, 0x46B5A000, 0x5B744E20, 0x58340002, 0xC2000000,
+ 0xCA0000E0, 0x5834002E, 0xC2400000, 0xCA400080, 0x6EB0A000, 0x6EBC4000, 0x47F18000, 0x46B18000,
+ 0x5B300E4E, 0x5B300004, 0x6E642000, 0x4225E000, 0xC39A8024, 0xC7380068, 0xC6B81C20, 0x99005B78,
+ 0xDB980000, 0xDBD80001, 0x00000000, 0xC2000000, 0xDF600040, 0x5E200080, 0x8400033A, 0x00000000,
+ 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0xC000490E, 0xCA000000, 0xC00049A0, 0xCA800000,
+ 0xC000492A, 0xCA400000, 0xC000496A, 0xCB000000, 0xC0004956, 0xCAC00000, 0x00000000, 0xC121FFFE,
+ 0x5911FE14, 0x15000000, 0x76318000, 0x76718000, 0x76B18000, 0x84000282, 0xC201FFFE, 0x76318000,
+ 0x5AEC0002, 0x6B2D0010, 0x5EA00000, 0x84000002, 0x6A2D0000, 0x8000FFF8, 0xC7200000, 0x62016008,
+ 0xC0004956, 0xCEC00000, 0x6EF4A000, 0x6ED44000, 0x4575A000, 0x46F5A000, 0x5B744E20, 0x58340000,
+ 0xC9C00000, 0xC00049A0, 0xCA000000, 0xC3000000, 0xC5F04020, 0xC2400000, 0xC5E50040, 0x7E412000,
+ 0x76610000, 0xCE000000, 0xC0004980, 0x40300000, 0xCEC00000, 0xC161FFFE, 0x5955FFFE, 0x15400000,
+ 0x00000000, 0xC000496A, 0xCA400000, 0xC2000002, 0x6A2D0000, 0x7E010000, 0x76252000, 0xCE400000,
+ 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000, 0x6EF4A000, 0x6ED44000, 0x4575A000, 0x46F5A000,
+ 0x5B744E20, 0x5834000E, 0xC2000000, 0xCA0000E0, 0x58340008, 0xC2400000, 0xCA420080, 0x5834000C,
+ 0xC2800000, 0xCA832018, 0x6E644010, 0x42250000, 0x4229E000, 0xC39A8008, 0x58340008, 0xCB809020,
+ 0x58340008, 0xC2800000, 0xCA810018, 0x6EE0A000, 0x6EE44000, 0x46610000, 0x46E10000, 0x5A200008,
+ 0x5A200E28, 0x42290000, 0xC6380068, 0xC6F81C20, 0x99005B78, 0xDB980000, 0xDBD80001, 0x00000000,
+ 0xC000495A, 0xC8400000, 0x00000000, 0xC3C00002, 0x7BC42000, 0xCC400000, 0xC0001A1C, 0xCA000000,
+ 0xC2400008, 0x6A452000, 0x76610000, 0x84000EAA, 0xC0000A28, 0xC3800000, 0xCB840030, 0xC0000A14,
+ 0xC3400000, 0xCB440030, 0xC0004880, 0xCB040000, 0xB7B40052, 0x58041802, 0xCAC00000, 0xA7000058,
+ 0x00000000, 0x00000000, 0xA6C8D7E8, 0xC1000000, 0xC6D00020, 0xC0004980, 0x40100000, 0xCA800000,
+ 0x80000058, 0x00000000, 0x00000000, 0x00000000, 0x8000D7A0, 0x00000000, 0xC2800000, 0xC7282020,
+ 0xC000490E, 0xCA400000, 0x6BE9E000, 0x00000000, 0x77E52000, 0x8400D758, 0x6EA0A000, 0x6E944000,
+ 0x45610000, 0x46A10000, 0x5A204E20, 0x5820000C, 0xCA000000, 0xC0004946, 0xCE800000, 0xA6220388,
+ 0x00000000, 0xC2200060, 0xC0004948, 0xCE000010, 0xCE001040, 0xC240000A, 0xC000494A, 0xCE400000,
+ 0xC2B60002, 0xC0004964, 0xCE801B08, 0x99005E48, 0xC00048A0, 0xC8840000, 0x00000000, 0xC0004946,
+ 0xCBC00000, 0x00000000, 0x00000000, 0x6FF8A000, 0x6FD44000, 0x4579C000, 0x47F9C000, 0x5BB84E20,
+ 0x99005C08, 0xDBD80000, 0xDB980001, 0x00000000, 0x99005950, 0xC000491C, 0xC1400000, 0xC9420050,
+ 0xC000491C, 0x99005E00, 0xC9400001, 0xC9800000, 0x00000000, 0x99005B78, 0xD9580000, 0xD9980001,
+ 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x99005840, 0xDBD80000, 0xDB980001,
+ 0xC7D80000, 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000, 0x6FF8A000, 0x6FD44000, 0x4579C000,
+ 0x47F9C000, 0x5BB84E20, 0x58380010, 0xCA000000, 0xC0004874, 0xC8040000, 0x6C908000, 0x44908000,
+ 0x44908000, 0x40100000, 0xCA400000, 0xC4340000, 0x00000000, 0xC7400000, 0xCE000000, 0xC161FFFE,
+ 0x5955FFFE, 0x15400000, 0x00000000, 0xC000490E, 0xCA400000, 0xC2800002, 0x6ABD4000, 0x72A52000,
+ 0xCE400000, 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000, 0x990062F0, 0xC0004836, 0xC9400000,
+ 0xC1800002, 0x00000000, 0x00000000, 0x00000000, 0xA8E2FFC8, 0x00000000, 0x58380000, 0xC9000000,
+ 0xC00049A0, 0xCA000000, 0xC2800000, 0xC5290040, 0x72A10000, 0xCE000000, 0xC1220002, 0xD90C0000,
+ 0xC2000000, 0xC0000A14, 0xCA040030, 0xC0000A28, 0xC2500002, 0xCE440808, 0x58880002, 0xB608FFF8,
+ 0xC00048A0, 0xC0800000, 0xCC840000, 0x8000D368, 0xC0004946, 0xCBC00000, 0xC161FFFE, 0x5955FFFE,
+ 0x15400000, 0x00000000, 0xC000490E, 0xCA400000, 0xC2800002, 0x6ABD4000, 0x72A52000, 0xCE400000,
+ 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000, 0x6FF8A000, 0x6FD44000, 0x4579C000, 0x47F9C000,
+ 0x5BB84E20, 0x58380008, 0xCA000000, 0x5838000C, 0xCA400000, 0xC3400000, 0xC6340008, 0xC000494E,
+ 0xCF400000, 0xC2800000, 0xC62A0080, 0xC3000000, 0xC6308020, 0x6F304000, 0x43298000, 0xC000493C,
+ 0xCF000000, 0xC2C00000, 0xC66C0080, 0xC0004950, 0xCEC00000, 0xC2800000, 0xC66AE028, 0xC0004954,
+ 0xCE800000, 0x5F740000, 0x84000188, 0x5E300028, 0x462D2000, 0x84000152, 0x462D2000, 0x8800011A,
+ 0x5E300018, 0x462D2000, 0x88000012, 0x462D2000, 0x8400002A, 0x00000000, 0x800000A8, 0x00000000,
+ 0x99005F88, 0xDBD80000, 0xDB980001, 0xC7800000, 0xC3400002, 0xC000494E, 0xCF400000, 0xC161FFFE,
+ 0x5955FFFE, 0x15400000, 0x00000000, 0xC000490E, 0xCA400000, 0xC2800002, 0x6ABD4000, 0x7E814000,
+ 0x76A52000, 0xCE400000, 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000, 0xC2200060, 0xC0004948,
+ 0xCE001040, 0xC2000000, 0xC000494C, 0xCE000000, 0x80000068, 0x00000000, 0x99005F88, 0xDBD80000,
+ 0xDB980001, 0xC7800000, 0x99006188, 0xDBD80000, 0xDB980001, 0xC7800000, 0xC2200058, 0xC0004948,
+ 0xCE001040, 0xC2000002, 0xC000494C, 0xCE000000, 0xC2000006, 0xC0001006, 0xCE000000, 0x5838000A,
+ 0xCA400000, 0xC2200982, 0x5A203B6E, 0xC0001008, 0xCE000000, 0xC000100A, 0xCE400000, 0xC0004954,
+ 0xCA800000, 0xC200000C, 0xC000494A, 0xCE000000, 0xC0004948, 0xCE800010, 0xC2B60000, 0xC0004964,
+ 0xCE800000, 0x99005E48, 0xC00048A0, 0xC8840000, 0x00000000, 0xC0004946, 0xCBC00000, 0xC000494C,
+ 0xCA000000, 0x6FF8A000, 0x6FD44000, 0x4579C000, 0x47F9C000, 0x5BB84E20, 0x5E200000, 0x840000E2,
+ 0x00000000, 0x99005C08, 0xDBD80000, 0xDB980001, 0x00000000, 0x99005950, 0xC000491C, 0xC1400000,
+ 0xC9420050, 0xC000491C, 0x99005E00, 0xC9400001, 0xC9800000, 0x00000000, 0x99005B78, 0xD9580000,
+ 0xD9980001, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x99005840, 0xDBD80000,
+ 0xDB980001, 0xC7D80000, 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000, 0xC000493C, 0xCA800000,
+ 0xC000494E, 0xCAC00000, 0xC3000018, 0xC3400006, 0x5E200000, 0x84000012, 0xC2800000, 0xC2C00000,
+ 0xC300001E, 0xC3400000, 0xC6AC1080, 0xC72C0420, 0xC76C0818, 0x58380010, 0xCA800000, 0x58380008,
+ 0xCEC00000, 0xC6280108, 0xC0004874, 0xC8040000, 0x6C908000, 0x44908000, 0x44908000, 0x40100000,
+ 0xCB000000, 0xC4340000, 0x00000000, 0xC7400000, 0xCE800000, 0xC0004952, 0xCE800000, 0x00000000,
+ 0x00000000, 0x00000000, 0xA8E2FFC8, 0x00000000, 0xC000494C, 0xCA000000, 0xC0004950, 0xCAC00000,
+ 0x5E200000, 0x84000052, 0xDFE80000, 0x7E814000, 0x5834001A, 0xCE800000, 0x990062F0, 0xC0004834,
+ 0xC9400000, 0xC1800002, 0x990062F0, 0xC0004838, 0xC9400000, 0xC6D80000, 0xC1220002, 0xD90C0000,
+ 0x5E200000, 0x84000028, 0x5838002C, 0xCB000000, 0xDFE80000, 0x00000000, 0x58380014, 0xCF000000,
+ 0x80000040, 0xC2A1FFFE, 0x5AA9FFFE, 0x58380000, 0xC9000000, 0xC00049A0, 0xCB000000, 0xC2C00000,
+ 0xC52D0040, 0x72F18000, 0xCF000000, 0x5838000A, 0xCE800000, 0xC3000000, 0xC0000A14, 0xCB040030,
+ 0xC2D00002, 0xC0000A28, 0xCEC40808, 0xC000494E, 0xCA800000, 0x58880002, 0xB4B0FFF8, 0xC00048A0,
+ 0xC0800000, 0xCC840000, 0x5EA80000, 0x84000162, 0x5E200000, 0x84000150, 0xC000493C, 0xCA800000,
+ 0x00000000, 0x00000000, 0x5AA80060, 0xCE800000, 0x99005F88, 0xDBD80000, 0xDB980001, 0xC7800000,
+ 0x99006188, 0xDBD80000, 0xDB980001, 0xC7800000, 0x58380000, 0xCAC00000, 0x00000000, 0xC2000000,
+ 0xC6E04020, 0xC0004952, 0xCAC00000, 0x58380000, 0xCA800000, 0xC30C0002, 0xC6300020, 0xA6800078,
+ 0x00000000, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0xC0001800, 0xCA000000,
+ 0x00000000, 0x00000000, 0xA60CFFCA, 0xC6F00508, 0xC6B0C408, 0xCF000000, 0x00000000, 0xC121FFFE,
+ 0x5911FE14, 0x15000000, 0x8000C9B0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000C948,
+ 0xDCBC0001, 0x5FFC0000, 0x8400003A, 0xC3800002, 0xDB880001, 0x5FFC0004, 0x8400C27A, 0xC3800000,
+ 0xDB880001, 0xC3CE0002, 0xC0000800, 0xCFC00708, 0xC3E1FFFE, 0x597DFFFE, 0x593DFE14, 0x94000001,
+ 0x00000000, 0x00000000, 0x00000000, 0xC000487C, 0xC8040000, 0x00000000, 0x00000000, 0x40080000,
+ 0xCBC00000, 0xC4380000, 0x00000000, 0xC000480E, 0xCA000000, 0xC0004858, 0xCB440000, 0x00000000,
+ 0x00000000, 0x46350000, 0x88000098, 0x00000000, 0xA7C00028, 0xC0004854, 0xC1000002, 0xCD040000,
+ 0xC11C0000, 0xC000082C, 0xCD040E08, 0x800000C0, 0x00000000, 0xA7D20118, 0x00000000, 0xC7E14048,
+ 0xC2400000, 0xC6246030, 0xC200006A, 0x46610000, 0xC6240038, 0xC0000810, 0xCE440038, 0x8000FF58,
+ 0xC2000000, 0xC0000808, 0xCA040018, 0xC11C0000, 0xC000082C, 0xCD040E08, 0x5A200002, 0x5E600010,
+ 0x8400FFF8, 0xC2000000, 0xC0000808, 0xCE040018, 0xC3400000, 0x80000010, 0xC1200002, 0xC0000818,
+ 0xCD041008, 0x5B740002, 0xC0004858, 0xCF440000, 0x99005590, 0xC0004848, 0xC9440000, 0xC1800000,
+ 0xC11C0002, 0xC000082C, 0xCD040E08, 0x800005E8, 0x5B740002, 0xC0004858, 0xCF440000, 0xC7800000,
+ 0xC13C0002, 0xCD001E08, 0xC0004848, 0xC9440000, 0xC1800000, 0xC000082C, 0xC9840030, 0x59540002,
+ 0xC0004848, 0xCD440000, 0x58880002, 0xB4980560, 0x00000000, 0xC0800000, 0x80000550, 0xC000487C,
+ 0xC8040000, 0x00000000, 0x00000000, 0x40080000, 0xCBC00000, 0xC4280000, 0x00000000, 0xA7C00110,
+ 0xC000484C, 0xCA040000, 0xC2400000, 0xC0001AEC, 0xCA440020, 0x5A200002, 0xC000484C, 0xCE040000,
+ 0xB624006A, 0xC6800000, 0xC13C0002, 0xCD001E08, 0xC0004848, 0xC9440000, 0xC1800000, 0xC000082C,
+ 0xC9840030, 0x59540002, 0xC0004848, 0xCD440000, 0x58880002, 0xB4980450, 0x00000000, 0xC0800000,
+ 0x80000440, 0xC0004854, 0xC1000004, 0xCD040000, 0xC0000820, 0xC2000002, 0xCE040000, 0xC2000000,
+ 0xC000484C, 0xCE040000, 0xC0004858, 0xCE040000, 0x8000FF10, 0xC0004854, 0xC1000000, 0xCD040000,
+ 0xC11C0000, 0xC000082C, 0xCD040E08, 0x99005590, 0xC0004848, 0xC9440000, 0xC1800000, 0xC1200000,
+ 0xC0000818, 0xCD041008, 0xC11C0002, 0xC000082C, 0xCD040E08, 0xC2000000, 0xC000484C, 0xCE040000,
+ 0x80000340, 0xC0001AC0, 0xCB840000, 0xC000487C, 0xC8040000, 0x00000000, 0x00000000, 0x40080000,
+ 0xCBC00000, 0xC4280000, 0x00000000, 0x00000000, 0xC6800000, 0xC13C0000, 0xCD001E08, 0xA780022A,
+ 0x00000000, 0x00000000, 0xA7C001EA, 0x00000000, 0xC0001B00, 0xC2060006, 0xCE040310, 0xA7E801A2,
+ 0x00000000, 0xC0004850, 0xCA040000, 0xC2400000, 0xC0001AEC, 0xCA448020, 0x5A200002, 0xC0004850,
+ 0xCE040000, 0xB624008A, 0x00000000, 0xC6800000, 0xC13C0002, 0xCD001E08, 0xC0001ACC, 0xC2000002,
+ 0xCE040008, 0xC0004848, 0xC9440000, 0xC1800000, 0xC000082C, 0xC9840030, 0x59540002, 0xC0004848,
+ 0xCD440000, 0x58880002, 0xB49801A8, 0x00000000, 0xC0800000, 0x80000198, 0xC0004854, 0xC1000000,
+ 0xCD040000, 0xC11C0000, 0xC000082C, 0xCD040E08, 0x99005590, 0xC0004848, 0xC9440000, 0xC1800000,
+ 0xC2000000, 0xC0000820, 0xCE040000, 0xC1200000, 0xC0000818, 0xCD041008, 0xC11C0002, 0xC000082C,
+ 0xCD040E08, 0xC0004850, 0xCE040000, 0xC2000002, 0xC0001ACC, 0xCE040010, 0x800000D0, 0xC2000002,
+ 0xC0004850, 0xCE040000, 0x8000FE70, 0xC2000000, 0xC0004850, 0xCE040000, 0xA7E60012, 0x00000000,
+ 0xC2000002, 0xC0001B00, 0xCE040008, 0x8000FE58, 0x00000000, 0xA7860032, 0x00000000, 0xC6800000,
+ 0xC13C0002, 0xCD001E08, 0xC2020002, 0xC7E2A548, 0xC0001B00, 0xCE040000, 0x8000FE00, 0xC2040002,
+ 0xC0001B00, 0xCE040208, 0x8000FDE0, 0xC2C80002, 0x6AC56000, 0xDACC0000, 0xC0004854, 0xCB440000,
+ 0xC0004848, 0xCB840000, 0xC0000838, 0xC3C00000, 0xCBC40030, 0x5EF40004, 0x8400000A, 0xC3000000,
+ 0xC0001ACC, 0xCF040108, 0x47BD8000, 0x84000012, 0x47BD8000, 0x88000018, 0xC1006E8C, 0x8000B6B0,
+ 0xC0004840, 0xCC840000, 0x8000F698, 0xC0001AC0, 0xCAC40000, 0xC0004854, 0xCB440000, 0xA6C0FBB2,
+ 0x00000000, 0x5EF40000, 0x8400F6F2, 0x5EF40002, 0x8400F982, 0x5EF40004, 0x8400FB82, 0xC1006CE8,
+ 0x8000B628, 0x00000000, 0xC0800000, 0xDF4B0040, 0xC0004900, 0xCB800000, 0xC2000000, 0xC000490A,
+ 0xA78000B0, 0xCBC00000, 0xC1000000, 0xD9000001, 0xC1000002, 0xD90C0000, 0x6FF46000, 0x47F5A000,
+ 0x5B744C80, 0xC2400000, 0x58340004, 0xCA400080, 0xC0004900, 0xCE000008, 0x5A640002, 0x58340004,
+ 0xC6500080, 0xCD000080, 0xC0004914, 0xCA400000, 0xC2000002, 0x6A3D0000, 0x72252000, 0xCE400000,
+ 0xC0000408, 0xCE000000, 0xA78200B8, 0xC0004908, 0xCBC00000, 0xC1000000, 0xD9000001, 0xC1000002,
+ 0xD90C0000, 0x6FF4A000, 0x6FD44000, 0x4575A000, 0x47F5A000, 0x5B744E20, 0xC2800000, 0x58340006,
+ 0xCA800080, 0xC2000000, 0xC0004900, 0xCE000108, 0x5EA80002, 0x58340006, 0xC6900080, 0xCD000080,
+ 0x5A7C0020, 0xC2000002, 0x6A250000, 0xC0000408, 0xCE000000, 0xDCA80001, 0x5EA80000, 0x8400B498,
+ 0x00000000, 0xA4800210, 0x00000000, 0xC3C00000, 0xC000140E, 0xCBC00020, 0xC3400000, 0xC2400000,
+ 0x6FF86000, 0x47F9C000, 0x5BB84C80, 0x58380008, 0xCB400080, 0x58380006, 0xCA400080, 0x5F740002,
+ 0x58380008, 0xC7500080, 0xCD000080, 0xC2000000, 0x58380004, 0xCA020080, 0xC3000000, 0x5838000C,
+ 0xCB000028, 0x5A640002, 0x46250000, 0x8400FFF8, 0xC2400000, 0x58380006, 0xC6500080, 0xCD000080,
+ 0xC2000000, 0x5838000A, 0xCA020080, 0x5B300002, 0x5838000C, 0xC7100028, 0xCD000028, 0xC2420020,
+ 0x5A200004, 0x46612000, 0x8400FFF8, 0xC2000000, 0x5838000A, 0xC6101080, 0xCD001080, 0xC0004966,
+ 0xCA400000, 0xC2000002, 0x6A3D0000, 0x72252000, 0xCE400000, 0x5F740000, 0x84000028, 0xC0004912,
+ 0xCA000000, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x76E10000, 0xCE000000, 0x5F300020, 0x84000028,
+ 0xC0004924, 0xCA000000, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x76E10000, 0xCE000000, 0xA4820050,
+ 0xC2400000, 0xC000140E, 0xCA408020, 0xC2000002, 0xC0004900, 0xCE000008, 0xC000490A, 0xCE400000,
+ 0xC1000000, 0xD9000001, 0xD8400080, 0xC1000004, 0xD9000001, 0xA4840250, 0x00000000, 0xC3C00000,
+ 0xC000140E, 0xCBC10020, 0xC2800000, 0xC2000000, 0x6FF8A000, 0x6FD44000, 0x4579C000, 0x47F9C000,
+ 0x5BB84E20, 0x5838002E, 0xCA800080, 0x58380006, 0xCA020080, 0xC3400000, 0x5838002E, 0xCB420080,
+ 0x5AA80002, 0x46290000, 0x8400FFF8, 0xC2800000, 0x5838002E, 0xC6900080, 0xCD000080, 0x5F740002,
+ 0x5838002E, 0xC7501080, 0xCD001080, 0xC0004968, 0xCA400000, 0xC2000002, 0x6A3D0000, 0x72252000,
+ 0xCE400000, 0xC000492A, 0xCA800000, 0x5E740000, 0x84000028, 0xC0004910, 0xCA000000, 0xC2C00002,
+ 0x6AFD6000, 0x7EC16000, 0x76E10000, 0xCE000000, 0x6ABD4010, 0xA680009A, 0x00000000, 0x58380032,
+ 0xCA000000, 0x58000002, 0xCA400000, 0x5838000C, 0x00000000, 0xCE000001, 0xCE400000, 0xC000492A,
+ 0xCA000000, 0xC2C00002, 0x6AFD6000, 0x72E10000, 0xCE000000, 0xC000492C, 0xCA000000, 0xC2C00002,
+ 0x6AFD6000, 0x72E10000, 0xCE000000, 0x80000028, 0xC000492C, 0xCA000000, 0xC2C00002, 0x6AFD6000,
+ 0x7EC16000, 0x76E10000, 0xCE000000, 0xA4880128, 0xC2C00000, 0xC000140E, 0xCAC20020, 0xC000490E,
+ 0xCA400000, 0xC2000002, 0x6A2D0000, 0x7E010000, 0x76252000, 0xCE400000, 0xC000496A, 0xCA400000,
+ 0xC2000002, 0x6A2D0000, 0x72252000, 0xCE400000, 0x6EF0A000, 0x6ED44000, 0x45718000, 0x46F18000,
+ 0x5B304E20, 0x58300000, 0xCA000000, 0x00000000, 0xC2400002, 0x76252000, 0x8400005A, 0x58300000,
+ 0xCA400000, 0xC2800000, 0x00000000, 0xC6684020, 0xC24C0002, 0xC6A40020, 0xC624C408, 0x58300010,
+ 0xCA400508, 0x00000000, 0xC0001800, 0xCE400000, 0xA4860050, 0xC2400000, 0xC000140E, 0xCA418020,
+ 0xC2020002, 0xC0004900, 0xCE000108, 0xC0004908, 0xCE400000, 0xC1000000, 0xD9000001, 0xD8400080,
+ 0xC1000004, 0xD9000001, 0xC0001408, 0xCC800000, 0xC10E0002, 0xD90C0000, 0x8000ED98, 0xDFBC0001,
+ 0xC000496E, 0x99006298, 0xC9400000, 0xC7D80000, 0x00000000, 0xC5700000, 0x5EF00020, 0x88000130,
+ 0x6F346000, 0x4735A000, 0x5B744C80, 0x58340008, 0xC2400000, 0xCA400080, 0x00000000, 0xC2000000,
+ 0x5A640002, 0xCE400080, 0x58340004, 0xCA000080, 0x00000000, 0x00000000, 0x5E200002, 0xCE000080,
+ 0xC0004912, 0xCA800000, 0xC2400002, 0x6A712000, 0x72694000, 0xCE800000, 0x5E200000, 0x8400003A,
+ 0xC000480A, 0xCA000000, 0xC0000408, 0xCA800000, 0x76610000, 0x00000000, 0x72294000, 0xCE800000,
+ 0x80000020, 0xC0004914, 0xCA000000, 0x7E412000, 0x00000000, 0x76610000, 0xCE000000, 0x800000B8,
+ 0x6EF4A000, 0x6ED44000, 0x4575A000, 0x46F5A000, 0x5B744E20, 0x5834002E, 0xC2400000, 0xCA420080,
+ 0x00000000, 0xC2000000, 0x5A640002, 0xC6501080, 0xCD001080, 0x58340006, 0xCA000080, 0x00000000,
+ 0x00000000, 0x5A200002, 0xCE000080, 0xC0004910, 0xCA400000, 0xC2000002, 0x6A2D0000, 0x72252000,
+ 0xCE400000, 0xC2000002, 0x6A310000, 0xC000042A, 0xCE000000, 0xC1040002, 0xD90C0000, 0x00000000,
+ 0x8000EB08, 0x00000000, 0xC4980930, 0x9D000000, 0xC5580030, 0xC0000838, 0xCD840000, 0xC1440200,
+ 0xC1C03200, 0xC55C1078, 0xC000100E, 0x9D000000, 0xCD800000, 0xC000100C, 0xCDC00000, 0xC0004862,
+ 0xC9C00000, 0x00000000, 0x00000000, 0xD9D80001, 0xC0007200, 0x401C0000, 0x5DC07400, 0x8800FFFA,
+ 0x5C000200, 0xCD800000, 0xC1F0000A, 0x71D4A000, 0xDD980000, 0xDD9C0001, 0x41D8E000, 0xC5D40268,
+ 0xC0001010, 0xCD400000, 0x6C9C8000, 0x449CE000, 0x449CE000, 0x59DC0004, 0xC1601260, 0xC5D40268,
+ 0x9D000000, 0xC0001012, 0xCD400000, 0x00000000, 0x00000000, 0xD9580000, 0x6D586000, 0x4558C000,
+ 0x59984C80, 0xD9980001, 0x5818000A, 0xC1800000, 0xC9800080, 0xC0005400, 0x6D5CA000, 0x401C0000,
+ 0x40180000, 0xC9400000, 0x58000002, 0x00000000, 0xC9C00000, 0xC0004930, 0xCD400000, 0xC0004932,
+ 0xCDC00000, 0x59980004, 0xC1C20020, 0xB59CFFF8, 0x00000000, 0xC1800000, 0xDD9C0001, 0x581C000A,
+ 0xCD800080, 0x581C000C, 0xC1800000, 0xC9800028, 0xC1C00002, 0xDD940000, 0x69D4E000, 0x5D980002,
+ 0xCD800028, 0xC0004924, 0xC9800000, 0x00000000, 0x9D000000, 0x00000000, 0x71D8C000, 0xCD800000,
+ 0xC000492A, 0xC9400000, 0xC1C00002, 0x69D8E000, 0x7DC0C000, 0x7594A000, 0xCD400000, 0xC000492C,
+ 0xC9400000, 0xDD800001, 0x58000032, 0x75D4A000, 0x84000078, 0xC9400001, 0xC9800000, 0xDD800001,
+ 0x5800000C, 0x00000000, 0xCD400001, 0xCD800000, 0xC000492C, 0xC9400000, 0xC000492A, 0xC9800000,
+ 0x71D4A000, 0xC000492C, 0xCD400000, 0x71D8C000, 0xC000492A, 0xCD800000, 0x9D000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xC0004862, 0xC9800000, 0x00000000, 0xC1C00200, 0x4194C000, 0x45D8E000,
+ 0x8800FFFA, 0xC5D80000, 0xC0004862, 0xCD800000, 0xC0001406, 0xC9800000, 0xC1C00002, 0x9D000000,
+ 0xC5D80A08, 0xC5581050, 0xCD800000, 0xC0004930, 0xC9800000, 0xC0004932, 0xC9C00000, 0xC140000E,
+ 0xC5581C20, 0xDD940000, 0xC0007200, 0x40140000, 0x5D407400, 0x8800FFFA, 0x5C000200, 0xCD800000,
+ 0x58000002, 0x5D407400, 0x8800FFFA, 0x5C000200, 0xCDC00000, 0xDD540000, 0xC1C00000, 0x58140006,
+ 0xC9C20080, 0xC1800000, 0x58140000, 0xC98000E0, 0x6DDC2000, 0xC000491E, 0x41D8E000, 0xCDC00000,
+ 0xDD980000, 0xC1C00022, 0xC5D80D78, 0xDD940001, 0xC5581C20, 0xC000491C, 0xCD800000, 0xDD540000,
+ 0xC1C00000, 0x58140006, 0xC9C20080, 0xC1800000, 0x58140004, 0xC9820080, 0x00000000, 0x59DC0002,
+ 0x459CC000, 0x8400FFF8, 0xC1C00000, 0x9D000000, 0x58140006, 0xC5D81080, 0xCD801080, 0xC0004860,
+ 0xC9400000, 0xC1820080, 0xC1D00002, 0x58146B00, 0xD5800000, 0x58000002, 0xD5800001, 0x59540004,
+ 0xB558FFF8, 0xC0004860, 0xC1400000, 0xCD400000, 0xDD980001, 0x9D000000, 0xDD940000, 0xC0001404,
+ 0xCDC00808, 0xC1C00000, 0xC1800200, 0x5D980004, 0xDF5D0050, 0x45D8A000, 0x8800FFDA, 0xDD800001,
+ 0x5800000C, 0x00000000, 0xC9400001, 0xC9800000, 0xC1C00002, 0xC5D43F08, 0xC5D81E08, 0xC0004862,
+ 0xC9C00000, 0x00000000, 0x00000000, 0x581C7200, 0x5DC07400, 0x8800FFFA, 0x5C000200, 0xCD400000,
+ 0x58000002, 0x5DC07400, 0x8800FFFA, 0x5C000200, 0xCD800000, 0xC0004862, 0xC9C00000, 0x00000000,
+ 0xC15004C0, 0xC5D40068, 0xDD9C0000, 0xC5D41C20, 0xC1C00000, 0xDD800001, 0x58000030, 0xC9C00080,
+ 0xDD800001, 0x58000002, 0xC9800000, 0x6DDC2000, 0xC000491C, 0x41D8E000, 0xCD400001, 0xCDC00000,
+ 0xDD940001, 0xC1C00000, 0x58140030, 0xC9C00080, 0xC1800000, 0x58140006, 0xC9820080, 0x00000000,
+ 0x59DC0002, 0x459CC000, 0x8400FFF8, 0xC1C00000, 0x9D000000, 0x58140030, 0xC5D80080, 0xCD800080,
+ 0xC1C00000, 0xDF5C0040, 0x5DDC0080, 0x8400FFD2, 0x00000000, 0x9D000000, 0x00000000, 0x00000000,
+ 0x00000000, 0xC160FFFE, 0xC0000A10, 0xC9440068, 0xC1A0FFFE, 0x59980E28, 0xC000100C, 0xCD400000,
+ 0xC000100E, 0xCD800000, 0xC0004964, 0xC9800000, 0x00000000, 0xC170000A, 0x7194A000, 0x6C988000,
+ 0x4498C000, 0x4498C000, 0x59980004, 0xC5940278, 0xC0001010, 0xCD400000, 0xC0004946, 0xC9400000,
+ 0x00000000, 0x00000000, 0x6D58A000, 0x6D5C4000, 0x45D8C000, 0x4558C000, 0xC000494A, 0xC9400000,
+ 0xC0004948, 0xC9C00000, 0x4194C000, 0xC1400012, 0xC55C1820, 0x9D000000, 0xC59C0270, 0xC0001012,
+ 0xCDC00000, 0xC1400000, 0x58000012, 0xC9410040, 0xC0004950, 0xC9C00000, 0xC5580000, 0xC5940840,
+ 0xC5581080, 0xD9940000, 0xC000493C, 0xC9400000, 0xC0004954, 0xC9800000, 0x59DC00A8, 0x455CE000,
+ 0x41D8E000, 0x5D5C0030, 0x8800FFF8, 0xC1C00030, 0xC1800000, 0xC5D84030, 0xC1400000, 0xC5D40010,
+ 0x5DD40002, 0x8400005A, 0x5DD40004, 0x84000082, 0x5DD40006, 0x840000AA, 0x5DD80026, 0x840000D2,
+ 0xDD540000, 0xDD800001, 0x58000008, 0x40180000, 0xCD400000, 0x59980002, 0x8000FFA8, 0xDD540000,
+ 0xDD800001, 0x58000008, 0x40180000, 0xCD4000C0, 0x59980002, 0x8000FF70, 0xDD540000, 0xDD800001,
+ 0x58000008, 0x40180000, 0xCD400080, 0x59980002, 0x8000FF38, 0xDD540000, 0xDD800001, 0x58000008,
+ 0x40180000, 0xCD400040, 0x59980002, 0x8000FF00, 0x00000000, 0x9D000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x58000012, 0xC9400000, 0xC0004954, 0xC9C00000, 0xC0004950, 0xC9400080, 0xDD800001,
+ 0x58000028, 0x5D9C0000, 0x8400003A, 0x5D9C0002, 0x8400003A, 0x5D9C0004, 0x84000052, 0xC55B0040,
+ 0xC55C08C0, 0xCD800041, 0xCDC008C0, 0x80000048, 0xCD400000, 0x80000038, 0xC55900C0, 0xC55C1840,
+ 0xCD8000C1, 0xCDC01840, 0x80000010, 0xC55A0080, 0xC55C1080, 0xCD800081, 0xCDC01080, 0x9D000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x59540002, 0x6994E018, 0x61C0C008, 0x4194A000, 0x5D940040,
+ 0x8800FFFA, 0xC5940000, 0x9D000000, 0xCD400000, 0x00000000, 0x00000000, 0x9D000000, 0x4158A000,
+ 0xCD400000, 0x00000000,
+};
+
+static unsigned int firmware_binary_data[] = {
+};
+
+
+#endif // IFXMIPS_ATM_FW_DANUBE_H
diff --git a/package/ltq-dsl/src/ifxmips_atm_fw_danube_retx.h b/package/ltq-dsl/src/ifxmips_atm_fw_danube_retx.h
new file mode 100644
index 000000000..ff4e500d5
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_fw_danube_retx.h
@@ -0,0 +1,612 @@
+#ifndef IFXMIPS_ATM_FW_DANUBE_H
+#define IFXMIPS_ATM_FW_DANUBE_H
+
+
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_fw_danube.h
+** PROJECT : Danube
+** MODULES : ATM (ADSL)
+**
+** DATE : 1 AUG 2005
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM Driver (PP32 Firmware)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 4 AUG 2005 Xu Liang Initiate Version
+** 23 OCT 2006 Xu Liang Add GPL header.
+*******************************************************************************/
+
+
+#define VER_IN_FIRMWARE 1
+
+#define ATM_FW_VER_MAJOR 0
+#define ATM_FW_VER_MINOR 15
+
+
+static unsigned int firmware_binary_code[] = {
+ 0x800004A0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000FFC8, 0x00000000, 0x00000000, 0x00000000,
+ 0xC1000002, 0xD90C0000, 0xC2000002, 0xDA080001, 0xC0001B50, 0x8C100000, 0x00000000, 0x00000000,
+ 0x00000000, 0xC2000000, 0xDA080001, 0x80006018, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x80005FF0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC1001DA6, 0x8D3C0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x80005EF0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0400000, 0xC0004840, 0xC8840000, 0xC2001AEE, 0x8E100000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0400002, 0xC0004840, 0xC8840000, 0xC2001AEE, 0x8E100000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC3C00004, 0xDBC80001, 0xC10C0002, 0xD90C0000, 0x8000FEC8, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC10E0002, 0xD90C0000, 0xC0004808, 0xC8400000, 0xC2001B4C, 0x8E100000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC3E1FFFE, 0x597DFFFE, 0x593DFE14, 0x900004D9, 0x00000000, 0x00000000, 0x00000000, 0x90CC0481,
+ 0x00000000, 0x00000000, 0x00000000, 0xC3E02252, 0x5BFC001E, 0xC0004002, 0xCFC00000, 0xC3C00000,
+ 0xDBC80001, 0xC1400008, 0xC1900000, 0x71948000, 0x15000100, 0xC140000A, 0xC1900002, 0x71948000,
+ 0x15000100, 0xC140000C, 0xC1900004, 0x71948000, 0x15000100, 0xC1400004, 0xC1900006, 0x71948000,
+ 0x15000100, 0xC1400006, 0xC1900008, 0x71948000, 0x15000100, 0xC140000E, 0xC190000A, 0x71948000,
+ 0x15000100, 0xC1400000, 0xC190000C, 0x71948000, 0x15000100, 0xC1400002, 0xC190000E, 0x71948000,
+ 0x15000100, 0xC0400000, 0xC11C0000, 0xC000082C, 0xCD040E08, 0xC11C0002, 0xC000082C, 0xCD040E08,
+ 0xC0400002, 0xC11C0000, 0xC000082C, 0xCD040E08, 0xC0000824, 0x00000000, 0xCBC00001, 0xCB800001,
+ 0xCB400001, 0xCB000000, 0xC0004878, 0x5BFC4000, 0xCFC00001, 0x5BB84000, 0xCF800001, 0x5B744000,
+ 0xCF400001, 0x5B304000, 0xCF000000, 0xC0000A10, 0x00000000, 0xCBC00001, 0xCB800000, 0xC0004874,
+ 0x5BFC4000, 0xCFC00001, 0x5BB84000, 0xCF800000, 0xC30001FE, 0xC000140A, 0xCF000000, 0xC3000000,
+ 0x7F018000, 0xC000042E, 0xCF000000, 0xC000040E, 0xCF000000, 0xC3C1FFFE, 0xC000490E, 0xCFC00080,
+ 0xC000492C, 0xCFC00080, 0xC0004924, 0xCFC00040, 0xC0004912, 0xCFC00040, 0xC0004966, 0xCFC00040,
+ 0xC0004968, 0xCFC00080, 0xC000496A, 0xCFC00080, 0xC3C00000, 0xC2800020, 0xC3000000, 0x7F018000,
+ 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB84A00, 0x5838000A, 0xCF000000, 0x5BFC0002, 0xB7E8FFA8,
+ 0x00000000, 0xC3C00000, 0xC2800010, 0x6FF86000, 0x47F9C000, 0x5BB84C80, 0xC3400000, 0x58380004,
+ 0xCB420080, 0x00000000, 0x58380008, 0xCF400080, 0x5BFC0002, 0xB7E8FF90, 0x00000000, 0xC3C00000,
+ 0xC2800020, 0xC348001E, 0xC3000000, 0x7F018000, 0x6FF8A000, 0x6FD44000, 0x4579C000, 0x47F9C000,
+ 0x5BB84E20, 0x58380008, 0xCF400420, 0x5838000A, 0xCF000000, 0x5BFC0002, 0xB7E8FF90, 0x00000000,
+ 0x00000000, 0xC0004816, 0xC3C00000, 0xCBC00080, 0x00000000, 0x00000000, 0xC1000000, 0xD9040001,
+ 0xDBC40080, 0xC1000006, 0xD9040001, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0xC3C00000,
+ 0xDCFC2008, 0x5FFC0002, 0x00000000, 0x98C08D62, 0xC0004730, 0xC9400000, 0xC0004732, 0xC0001AF2,
+ 0xCBC00000, 0x00000000, 0x00000000, 0xA7C20450, 0xC000474A, 0xCA800000, 0x00000000, 0x00000000,
+ 0x5D280000, 0x8400FFC8, 0x00000000, 0xC121FFFE, 0x5911FEF4, 0x15000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC2802000, 0x6EA8E010, 0xC0004200, 0xC2400000, 0x7E410000, 0xC1000000, 0xCE400001, 0xCE400001,
+ 0xCE400001, 0xCE400001, 0x5EA80002, 0x8400FFC0, 0xC0004300, 0xC2800200, 0x6EA84010, 0xCE400001,
+ 0xCE000001, 0xCE400001, 0xCE000001, 0xCE400001, 0xCE000001, 0xCE400001, 0xCE000001, 0x5EA80002,
+ 0x8400FFA0, 0xC0004700, 0xC2800200, 0x6EA8E010, 0xCE400001, 0xCE400001, 0xCE400001, 0xCE400001,
+ 0x5EA80002, 0x8400FFC0, 0xC0004740, 0xCE400000, 0xC0004742, 0xC1000200, 0x5D100002, 0xCD000000,
+ 0xC0004744, 0xCE400000, 0xC0004746, 0xCE400000, 0xC0004748, 0xCE400000, 0xC000474A, 0xCE400000,
+ 0xC000474C, 0xC1000002, 0xCD000000, 0xC000474E, 0xCE400000, 0xC0004750, 0xCE400000, 0xC0004752,
+ 0xCE400000, 0xC0004754, 0xCE400000, 0xC0400000, 0xC11C0000, 0xC000082C, 0xCD040E08, 0xC0000838,
+ 0xCE400000, 0xC0000818, 0xCE400000, 0xC0000820, 0xCE400000, 0xC2804840, 0xC240485A, 0x98C086B0,
+ 0xC6800000, 0xC6540000, 0xC1800000, 0xC11C0002, 0xC000082C, 0xCD040E08, 0x00000000, 0xC121FFFE,
+ 0x5911FE54, 0x15000000, 0xC0000A10, 0xCB800000, 0xC0000A12, 0xCB400000, 0xC0000A14, 0xCB000000,
+ 0xC0000A16, 0xCAC00000, 0xC0000040, 0xC2800000, 0xCE800008, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC2800002,
+ 0xCE800008, 0xC0000A10, 0xCF800000, 0xC0000A12, 0xCF400000, 0xC0000A14, 0xCF000000, 0xC0000A16,
+ 0xCEC00000, 0xC1000000, 0xC00048A0, 0xCD000000, 0xC00048A2, 0xCD000000, 0xC0001AF2, 0xC1000000,
+ 0xCD000108, 0x80001020, 0x00000000, 0xC3C00000, 0xDCFC2008, 0x5FFC0002, 0x00000000, 0x98C08D62,
+ 0xC0004730, 0xC9400000, 0xC0004732, 0x800033C0, 0x00000000, 0xC3C00000, 0xDCFC2008, 0x5FFC0002,
+ 0x00000000, 0x98C08D62, 0xC0004730, 0xC9400000, 0xC0004732, 0xC0004810, 0xC9000000, 0xC000474A,
+ 0xC9400000, 0xA50007C8, 0x00000000, 0x5D140002, 0x840007BA, 0xC1000000, 0xC000484A, 0xC9000000,
+ 0xC0004740, 0xC8400000, 0x5D100000, 0x84000780, 0x00000000, 0x00000000, 0xC121FFFE, 0x5911FEF4,
+ 0x15000000, 0xC0004744, 0xC8800000, 0xC0001AF0, 0xC3000000, 0x58000002, 0xCB010040, 0x6C7C2000,
+ 0x5BFC4300, 0x98C08A88, 0xC1400000, 0xC4540028, 0x6C40A010, 0x5D240002, 0x84000202, 0x00000000,
+ 0xC0004742, 0xCA800000, 0x00000000, 0x00000000, 0x59280002, 0x6D130000, 0x6D130010, 0x44508000,
+ 0x8400067A, 0x00000000, 0x98C08870, 0xC4540000, 0xC6980000, 0xC241FFFE, 0xC6740000, 0x5D35FFFE,
+ 0x8400063A, 0x44748000, 0x8400062A, 0xC1000000, 0x6F502000, 0xC0004300, 0x40100000, 0xC1400000,
+ 0x58000000, 0xC9410040, 0xC1800000, 0xC0004814, 0xC9820040, 0x4570A000, 0xC10001FE, 0x4150A004,
+ 0x45948000, 0x880005B2, 0x4474C000, 0xC1000200, 0x4190C004, 0xC000473E, 0xC9000000, 0x00000000,
+ 0x00000000, 0x41188000, 0xCD000000, 0xC000471C, 0xC9000000, 0x00000000, 0x00000000, 0x41188000,
+ 0xCD000000, 0x98C087E8, 0xC4540000, 0x6C58A010, 0xC0004700, 0x58440002, 0x6C470000, 0x6C470010,
+ 0x47448000, 0x8400FFA8, 0xC7440000, 0xC0004740, 0xCC400000, 0xC0800000, 0xC0004744, 0xCC800000,
+ 0x800004B8, 0xC1000000, 0x583C0000, 0xC9000040, 0x00000000, 0x00000000, 0x45088000, 0x88000268,
+ 0xC1400000, 0x583C0000, 0xC9410040, 0xC1800000, 0xC0004814, 0xC9800040, 0x4570A000, 0xC10001FE,
+ 0x4150A004, 0x45948000, 0x8800042A, 0xC3800000, 0x583C0002, 0xCB820080, 0xC1000000, 0x583C0002,
+ 0xC9000080, 0x00000000, 0x00000000, 0x45388000, 0x84000232, 0xC0400002, 0xC0800000, 0xC3C00000,
+ 0xC000481A, 0xC8000000, 0x6F908000, 0x47908000, 0x47908000, 0x4011E000, 0xC000491E, 0xCFC00000,
+ 0xC3400000, 0xC0004878, 0xC8040000, 0x6C908000, 0x44908000, 0x44908000, 0x40100000, 0xCAC00000,
+ 0xC4300000, 0x00000000, 0xC7340068, 0xC1000002, 0xC5341B08, 0xC100001C, 0xC5341050, 0xC100000C,
+ 0xC5340D18, 0xC000491C, 0xCF400000, 0xC3000000, 0xDF700040, 0x5D300080, 0x8800FFD0, 0xC000474A,
+ 0xC1000002, 0xCD000000, 0xC000491C, 0xCB400000, 0xC000491E, 0xCBC00000, 0x99007F18, 0xDB580000,
+ 0xDBD80001, 0x00000000, 0xC1400000, 0xC794A038, 0xC1800000, 0xC7980028, 0x58144200, 0xC9C00000,
+ 0xC1210000, 0x69188010, 0x7D008000, 0x751CE000, 0xCDC00000, 0x80000210, 0x00000000, 0xC1000000,
+ 0x583C0000, 0xC903E008, 0x00000000, 0x00000000, 0x5D100000, 0x8400002A, 0xC0004734, 0xC9000000,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x800000A8, 0xC1400000, 0x583C0000, 0xC9410040,
+ 0xC1800000, 0xC0004814, 0xC9820040, 0x4570A000, 0xC10001FE, 0x4150A004, 0x45948000, 0x88000142,
+ 0xC000473E, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0xC000471C, 0xC9000000,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0xC3800000, 0x583C0002, 0xCB820080, 0x00000000,
+ 0x00000000, 0x5D39FFFE, 0x8400004A, 0xC1400000, 0xC794A038, 0xC1800000, 0xC7980028, 0x58144200,
+ 0xC9C00000, 0xC1210000, 0x69188010, 0x7D008000, 0x751CE000, 0xCDC00000, 0x98C087E8, 0xC4540000,
+ 0x6C58A010, 0xC0004700, 0x58440002, 0x6C470000, 0x6C470010, 0xC0004740, 0xCC400000, 0xC0800000,
+ 0xC0004744, 0xCC800000, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0x8000F270, 0x00000000,
+ 0x00000000, 0x98C086F0, 0xC0004748, 0xC9800000, 0xC2000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xC1400000, 0xC7D4A038, 0xC1800000, 0xC7D80028, 0x58144200,
+ 0xC9C00000, 0xC1210000, 0x69188010, 0x7D008000, 0x751CE000, 0xCDC00000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x98C087E8, 0xC7D40000, 0x6FD8A010, 0xC0004700, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x98C08870, 0xC7D40000, 0xC7980000, 0xC241FFFE, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x98C08A88, 0xC1400000, 0xC7D40028, 0x6FC0A010,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x98C08AB8, 0xC1400000, 0xC7D40028, 0x6FC0A010,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x98C08AF0, 0xC7D40000, 0xC0004740, 0xC9C00000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x98C08BE0, 0xC7D40000, 0xC0004742, 0xC9800000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC0004958, 0xC8400000, 0x00000000, 0xC3C00002,
+ 0x7BC42000, 0xCC400000, 0xC0004848, 0xCB840000, 0xC000495C, 0xCAC40000, 0xC0004844, 0xC8840000,
+ 0x46F90000, 0x8400F47A, 0xC000487C, 0xC8040000, 0x00000000, 0x00000000, 0x40080000, 0xCA000000,
+ 0xC0001624, 0xCB040000, 0xA63C005A, 0x00000000, 0x00000000, 0xA71EF412, 0x00000000, 0xC0000824,
+ 0xCA840000, 0x6CA08000, 0x6CA42000, 0x46610000, 0x42290000, 0xC35E0002, 0xC6340068, 0xC0001624,
+ 0xCF440080, 0xC2000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0xC0004844, 0xC8840000, 0xC000082C, 0xCA040040, 0x00000000, 0x00000000, 0x58880002,
+ 0xB608FFF8, 0x00000000, 0xC0800000, 0xC0004844, 0xCC840040, 0x5AEC0002, 0xC000495C, 0xCEC40000,
+ 0x5E6C0006, 0x84000048, 0xC0004848, 0xCB840000, 0xC0000838, 0xC2500002, 0xCE440808, 0x5FB80002,
+ 0xC0004848, 0xCF840000, 0x5EEC0002, 0xC000495C, 0xCEC40000, 0x00000000, 0xC121FFFE, 0x5911FE54,
+ 0x15000000, 0x8000F278, 0xC000495A, 0xC8400000, 0x00000000, 0xC3C00002, 0x7BC42000, 0xCC400000,
+ 0xC0004960, 0xCAC40000, 0x00000000, 0x00000000, 0x5EEC0000, 0x840000F2, 0x00000000, 0xB6FC0030,
+ 0xC0001600, 0xCA040000, 0x00000000, 0x00000000, 0xA61E00B2, 0x6FE90000, 0xC0000A28, 0xCE840808,
+ 0xC2C00000, 0xC2800004, 0xB6E80080, 0xC0001604, 0xCA840000, 0xC0004960, 0xCEC40000, 0xA69EFC8A,
+ 0x00000000, 0x6FE90000, 0xC0000A28, 0xCE840808, 0xC2C00002, 0xC0001600, 0xCA040000, 0x00000000,
+ 0x00000000, 0xA61E000A, 0x6FE90000, 0xC0000A28, 0xCE840808, 0xC2C00000, 0xC0001604, 0xCA840000,
+ 0xC0004960, 0xCEC40000, 0xA69EFBF2, 0xC2400000, 0xC0000A14, 0xCA440030, 0x00000000, 0x00000000,
+ 0x46E52000, 0xA4400000, 0xC2800000, 0xDFEB0031, 0x8000FFF8, 0xDFEA0031, 0xB668EBEA, 0x00000000,
+ 0xC00048A0, 0xCB040000, 0xC0000A10, 0xCA840000, 0x6F208000, 0x6F242000, 0x46610000, 0x42A10000,
+ 0xC2400000, 0xC0000A14, 0xCA440030, 0xC35E0002, 0xC6340068, 0xC0001604, 0xCF440080, 0x5B300002,
+ 0xB670FFF8, 0x5AEC0002, 0xC3000000, 0xC00048A0, 0xCF040000, 0xC0004960, 0xCEC40000, 0x8000F018,
+ 0xC0004918, 0xD2800000, 0xC2000000, 0xDF600040, 0x5E600080, 0x8400028A, 0x00000000, 0xC161FFFE,
+ 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC000480A, 0xCA000000,
+ 0xC0004912, 0xCA400000, 0xC0004924, 0xCA800000, 0xC0004966, 0xCAC00000, 0x00000000, 0xC121FFFE,
+ 0x5911FE54, 0x15000000, 0x76610000, 0x76A10000, 0x76E10000, 0x840001CA, 0xC0004918, 0xCA400000,
+ 0xC28001FE, 0x76A10000, 0x5A640002, 0x6A254010, 0x5EE80000, 0x84000002, 0x6AA54000, 0x8000FFF8,
+ 0xC6280000, 0x62818008, 0xC0004918, 0xCF000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xC0004966, 0xCA400000, 0xC2000002, 0x6A310000, 0x7E010000,
+ 0x76252000, 0xCE400000, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0x6F346000, 0x4735A000,
+ 0x5B744C80, 0xC2800000, 0x58340006, 0xCA800080, 0xC2C00000, 0x58340000, 0xCAC000E0, 0xC2400000,
+ 0x5834000A, 0xCA420080, 0x6EA82000, 0x42E9E000, 0x6F2CA000, 0x42E56000, 0x5AEC1400, 0xC3990040,
+ 0xC7381C20, 0xC6F80068, 0x99007F18, 0xDB980000, 0xDBD80001, 0x00000000, 0xDEA00000, 0x47210000,
+ 0x8400FD38, 0xC0004958, 0xC8400000, 0x00000000, 0xC1000002, 0x79042000, 0xCC400000, 0xC0004848,
+ 0xCBC40000, 0xC0004844, 0xC8840000, 0x5FFC0000, 0x8400ECA2, 0xC0004740, 0xCB000000, 0xC0004744,
+ 0xCAC00000, 0x6F282000, 0x5AA84300, 0xC000487C, 0xC8040000, 0x00000000, 0x00000000, 0x40080000,
+ 0xCA400000, 0xC4000000, 0x00000000, 0xC0004878, 0xC8040000, 0x6C908000, 0x44908000, 0x44908000,
+ 0x40100000, 0xC9000000, 0xC4340000, 0x00000000, 0x5C440000, 0x8400008A, 0x00000000, 0xC00047D2,
+ 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x58340002, 0xC9000080, 0x00000000,
+ 0x00000000, 0x58280002, 0x6D120000, 0xCD001080, 0x5AEC0002, 0xC0004744, 0xCEC00000, 0x80000618,
+ 0x00000000, 0xC00047C0, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0xA67C0028,
+ 0xC00047C2, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x80001E00, 0x00000000,
+ 0xA6600022, 0xC00047C4, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x80000558,
+ 0xC00047C6, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0xC3C00000, 0xC67D0040,
+ 0xC3800000, 0xC6780040, 0x473C8000, 0x84000090, 0x46F88000, 0x84000080, 0xC1000000, 0xC0004814,
+ 0xC9000040, 0x00000000, 0x00000000, 0x5D100000, 0x840000D8, 0x5AEC0002, 0xC0004744, 0xCEC00000,
+ 0xC00047CA, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x80000460, 0x00000000,
+ 0x98C08AF0, 0xC7D40000, 0xC0004740, 0xC9C00000, 0x5D240000, 0x84000052, 0x00000000, 0x98C087E8,
+ 0xC7D40000, 0x6FD8A010, 0xC0004700, 0xC00047C8, 0xC9000000, 0x00000000, 0x00000000, 0x59100002,
+ 0xCD000000, 0x80001C28, 0xC00047CC, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000,
+ 0x6FE82000, 0x5AA84300, 0x5D380000, 0x84000088, 0x00000000, 0x98C086F0, 0xC0004748, 0xC9800000,
+ 0xC2000000, 0x58280002, 0x6E520000, 0xCD001080, 0x58280002, 0xCE400080, 0x5D25FFFE, 0x84000028,
+ 0xC00047D0, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x800002B8, 0xC3000000,
+ 0x58280002, 0xCB000080, 0x00000000, 0x00000000, 0x5D31FFFE, 0x84000030, 0xC00047D0, 0xC9000000,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x80000248, 0x00000000, 0x98C086F0, 0xC0004748,
+ 0xC9800000, 0xC2000000, 0x58340002, 0xC6500080, 0xC7D01040, 0xC7901840, 0xCD000000, 0x58280002,
+ 0xCE400080, 0xC3C00200, 0x5FFC001C, 0xC3800000, 0xDF790050, 0x00000000, 0x00000000, 0x47BC8000,
+ 0x8800FFC2, 0xC0004862, 0xCBC00000, 0xC0000000, 0xC76C0000, 0x5BBC7200, 0xC280001C, 0xCA6C0001,
+ 0x00000000, 0x00000000, 0xCE780001, 0xC1007400, 0x47908000, 0xC1007200, 0xC5380006, 0x5EA80002,
+ 0x8400FFA0, 0xC3800000, 0xC000481A, 0xC8000000, 0x6F108000, 0x47108000, 0x47108000, 0x4011C000,
+ 0xC000491E, 0xCF800000, 0xC2C00000, 0xC7EC0068, 0xC100001C, 0xC52C1050, 0xC100000A, 0xC52C0D18,
+ 0xC000491C, 0xCEC00000, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420050, 0xC2800000, 0xDF680040,
+ 0x5D280080, 0x8800FFD0, 0xC000491C, 0xCAC00000, 0xC000491E, 0xCB800000, 0x99007F18, 0xDAD80000,
+ 0xDB980001, 0x00000000, 0xC00047CE, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000,
+ 0x00000000, 0x80001868, 0x00000000, 0x00000000, 0x00000000, 0xC0004878, 0xC8040000, 0x6C908000,
+ 0x44908000, 0x44908000, 0x40100000, 0xCA000000, 0xC4240000, 0x00000000, 0xC0004934, 0xCE000000,
+ 0xC2800002, 0xC4681C10, 0xC62821D8, 0xC6281E08, 0xC2600010, 0x5A650080, 0xC0004800, 0xCB400000,
+ 0xC2200400, 0x5A200040, 0xC7601048, 0xC0001220, 0xCE800000, 0xC0001200, 0xCE400000, 0xC0001202,
+ 0xCE000000, 0xC0001240, 0xCB400000, 0x00000000, 0x00000000, 0xA754FFC0, 0xC2000000, 0xC7600048,
+ 0xA7520022, 0x00000000, 0x00000000, 0x99008690, 0xC0004822, 0xC9400000, 0xC1800002, 0x800016F8,
+ 0x582040C0, 0xC2000000, 0xCA000020, 0xC2400000, 0xCA414008, 0xC2800000, 0xCA812008, 0xC2C00000,
+ 0xCAC20020, 0xC0004938, 0xCE000000, 0xC0004920, 0xCE400000, 0xC0004916, 0xCE800000, 0xC0004922,
+ 0xCEC00000, 0xA6400538, 0x00000000, 0xC0004938, 0xCBC00000, 0x00000000, 0xC3800000, 0x6FF48000,
+ 0x6FD44000, 0x4355A000, 0x5B744A00, 0x58340000, 0xCB802018, 0x00000000, 0xC2000000, 0x6FB46000,
+ 0x47B5A000, 0x5B744C80, 0x5834000C, 0xCA000028, 0xC000491A, 0xCF800000, 0x5E200000, 0x8400046A,
+ 0xC2000000, 0xDF610050, 0x5E6001E8, 0x8800FFD0, 0xC2000002, 0xC2400466, 0xC2A00000, 0x5AA80000,
+ 0xC0001006, 0xCE000000, 0xC0001008, 0xCE400000, 0xC000100A, 0xCE800000, 0x99007958, 0xC1A0FFFE,
+ 0xC0000824, 0xC9840068, 0xC0004934, 0xCA400000, 0xC2000000, 0xC2800002, 0x99007998, 0xDA980000,
+ 0xC6140000, 0xC6580000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x99007A80, 0xC000491A, 0xC9400000, 0x00000000, 0x00000000, 0xC121FFFE, 0x5911FE54,
+ 0x15000000, 0xC0004922, 0xCA001120, 0xC3C00000, 0xC3800000, 0xC0004930, 0xCE001120, 0xC0004932,
+ 0xCBC000E0, 0xC2800000, 0xC000491E, 0xCFC00000, 0xC0004862, 0xCA800068, 0xC3A0001A, 0x5BB94000,
+ 0xC6B80068, 0xC000491C, 0xCF800000, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420050, 0x00000000,
+ 0x00000000, 0x00000000, 0xA8E2FFC8, 0xC2000000, 0xC1220002, 0xD90C0000, 0xDF600040, 0x5E600080,
+ 0x8400FFDA, 0xC000491C, 0xCA000000, 0xC000491E, 0xCA400000, 0x00000000, 0x00000000, 0x99007F18,
+ 0xDA180000, 0xDA580001, 0x00000000, 0xC2000000, 0xDF610050, 0x5E6001FE, 0x8800FFD0, 0xC0004916,
+ 0xCA800000, 0xC2C00000, 0xDFEC0050, 0xC2400000, 0x46E52000, 0x84000032, 0x5EA80000, 0x84000022,
+ 0xC2600002, 0x99008690, 0xC000482E, 0xC9400000, 0xC1800002, 0x80000018, 0xC2600000, 0x99008690,
+ 0xC000482C, 0xC9400000, 0xC1800002, 0xC2000068, 0xC6240080, 0xC0004930, 0xCE400088, 0xC000491A,
+ 0xC9800000, 0xC0004862, 0xC9400000, 0x6D9C6000, 0x459CE000, 0x59DC4C80, 0x99007D78, 0xD9580000,
+ 0xD9980001, 0xD9D40000, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420050, 0xC2000000, 0xDF600040,
+ 0x5E600080, 0x8400FFD2, 0x00000000, 0xC000491C, 0xCA000000, 0xC000491E, 0xCA400000, 0x00000000,
+ 0x00000000, 0x99007F18, 0xDA180000, 0xDA580001, 0x00000000, 0x80001148, 0x00000000, 0x99008690,
+ 0xC000482A, 0xC9400000, 0xC1800002, 0x80001118, 0xC0004938, 0xCBC00000, 0x00000000, 0x00000000,
+ 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB84A00, 0x58380008, 0xCA000000, 0x00000000, 0x00000000,
+ 0xA600037A, 0x00000000, 0xC0004938, 0xCBC00000, 0xC3000000, 0x00000000, 0x6FF88000, 0x6FD44000,
+ 0x4395C000, 0x5BB84A00, 0x58380000, 0xCB002018, 0xC2000000, 0x58380008, 0xCA020080, 0x5838000C,
+ 0xCAC00000, 0x5838000E, 0xCA400000, 0xC000491A, 0xCF000000, 0xC0004930, 0xCEC00000, 0xC000493C,
+ 0xCE000000, 0xC0004932, 0xCE400000, 0x5E200000, 0x84000120, 0xC2800000, 0xA6FE00B2, 0x6F206000,
+ 0x47210000, 0x5A204C80, 0x5820000C, 0xCA800028, 0x00000000, 0x00000000, 0x5EA80000, 0x840001F2,
+ 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x99007A80, 0xC000491A, 0xC9400000, 0x00000000, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000,
+ 0xC0004930, 0xCAC00000, 0xC0004932, 0xCA400000, 0xC7EC1120, 0xC0004930, 0xCEC00000, 0x5838000C,
+ 0xCEC00000, 0x58000002, 0xCE400000, 0xC0004934, 0xCA000000, 0xC2400002, 0x6E642000, 0x6E642000,
+ 0x76252000, 0x84000012, 0xC2400002, 0x6E684000, 0x58380008, 0xCE800208, 0xA6000000, 0x6E682000,
+ 0x58380008, 0xCE800108, 0xC2400002, 0x6E642000, 0x76252000, 0x840000D2, 0x58380008, 0xCA000000,
+ 0xC2800000, 0xC2400000, 0xA60200A0, 0xDBA80000, 0x6F386000, 0x4739C000, 0x5BB84C80, 0x58380004,
+ 0xCA400080, 0x58380002, 0xCA800080, 0x00000000, 0xDEB80000, 0x46694000, 0x88000048, 0x00000000,
+ 0xC0004824, 0xCA000000, 0xC2400002, 0x6E640000, 0x5A200002, 0xCE000000, 0x58380008, 0xCE400008,
+ 0x80000000, 0x00000000, 0x80000030, 0xC0004934, 0xCA000000, 0x00000000, 0x00000000, 0xA6020CAA,
+ 0x00000000, 0x00000000, 0x80000CE0, 0xC2800000, 0xC2000200, 0xC240001A, 0xDF690050, 0x46A14000,
+ 0x46694000, 0x8800FFBA, 0xC2000006, 0xC2600982, 0x5A643B6E, 0x5838000A, 0xCA800000, 0xC0001006,
+ 0xCE000000, 0xC0001008, 0xCE400000, 0xC000100A, 0xCE800000, 0x99007958, 0xC1A0FFFE, 0xC0000824,
+ 0xC9840068, 0xC2000000, 0xC0004930, 0xCA02E010, 0x58380026, 0xCA400000, 0x00000000, 0xC2800000,
+ 0x99007998, 0xDA980000, 0xC6140000, 0xC6580000, 0xC0004934, 0xCA000000, 0x00000000, 0x00000000,
+ 0xA6020002, 0x00000000, 0x00000000, 0x80000300, 0xC0004938, 0xCBC00000, 0xC0004878, 0xC8040000,
+ 0x6C908000, 0x44908000, 0x44908000, 0x40100000, 0xCA000000, 0xC4240000, 0x00000000, 0x58240018,
+ 0xCA000000, 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB84A00, 0xC3000000, 0xC3400002, 0xC2C00000,
+ 0xC62C0080, 0xC6270040, 0xC0004940, 0xCE400040, 0xC6260040, 0xC0004942, 0xCE400040, 0xC000493C,
+ 0xCA000000, 0x5EEC0000, 0x84000172, 0x5A6C0010, 0x46614000, 0x88000178, 0x5A600052, 0x466D4000,
+ 0x88000160, 0x58380006, 0xCA800000, 0xC0004940, 0xCA000000, 0xC2400000, 0xC6A70040, 0x7E412000,
+ 0x76252000, 0xC2000000, 0xC6A10040, 0x46610000, 0x84000120, 0xC0004942, 0xCA000000, 0xC2400000,
+ 0xC6A60040, 0x7E412000, 0x76252000, 0xC2000000, 0xC6A00040, 0x58380002, 0xCA800000, 0x46610000,
+ 0x840000D0, 0xC2400000, 0xC6A60080, 0x46E50000, 0x880000C2, 0xC2400000, 0xC6A40080, 0x58380008,
+ 0xCA800000, 0x466D0000, 0x880000A2, 0x00000000, 0xA682FFF8, 0x00000000, 0xC7700B08, 0xA6840078,
+ 0x00000000, 0xC7700A08, 0x80000068, 0xC7700208, 0xC000493C, 0xCAC00000, 0x80000048, 0xC7700308,
+ 0xC000493C, 0xCAC00000, 0x80000028, 0xC7700908, 0x80000018, 0xC7700808, 0x80000008, 0xC7700708,
+ 0x8000FFF8, 0xC7700508, 0xC0004944, 0xCF000000, 0xC000493E, 0xCEC00000, 0xC0004938, 0xCA400000,
+ 0xC000493C, 0xCB800000, 0xC000493E, 0xCB400000, 0xC3000000, 0x6E608000, 0x6E544000, 0x42150000,
+ 0x5A204A00, 0x5AA00008, 0x58200004, 0xCB000080, 0xC0004934, 0xCA000000, 0xC2400000, 0xC0004930,
+ 0xCA42E010, 0xC3C00018, 0xA6020078, 0x00000000, 0x43656000, 0x46F90000, 0x88000038, 0x47AD6000,
+ 0x6EE04010, 0x5BE00004, 0xC2000000, 0xC6E00010, 0x5E200000, 0x8400002A, 0x5BFC0002, 0x80000018,
+ 0xC3C00004, 0x5A2C0008, 0x46390000, 0x8800FFFA, 0x5FB80008, 0x6FE04000, 0x42390000, 0x46312000,
+ 0x88000050, 0xC2400000, 0xC0004930, 0xCA42E010, 0xC2060002, 0xC6800000, 0xCE000308, 0x6FE04000,
+ 0x4631C000, 0x5F700010, 0x4675A000, 0xC2000000, 0xC6340010, 0xC25A000A, 0xC000491A, 0xCA401C20,
+ 0xC2800000, 0xC0004932, 0xCA8000E0, 0xC0004862, 0xCA400068, 0x6FA04010, 0x42290000, 0xC000491E,
+ 0xCE000000, 0xC7E41050, 0xC000491C, 0xCE400000, 0x6FE04000, 0x43A1C000, 0xC000493C, 0xCF800000,
+ 0xC000493E, 0xCF400000, 0xC000493A, 0xCFC00000, 0x8000FFF0, 0x00000000, 0x00000000, 0x00000000,
+ 0xC2000000, 0xDCE00000, 0xA622FFB8, 0xC1220002, 0xD90C0000, 0xC0004938, 0xCBC00000, 0xC0004944,
+ 0xCB400000, 0xC0004862, 0xCB000000, 0xC0004934, 0xCA000000, 0x6FF88000, 0x6FD44000, 0x4395C000,
+ 0x5BB84A00, 0xA6020278, 0xC2400000, 0x58380008, 0xCA406008, 0xDFE80000, 0xC2218E08, 0x5A21BAF6,
+ 0x46294000, 0x8400000A, 0xC2080002, 0x7235A000, 0x80000040, 0x5E640000, 0x8400000A, 0xC20C0002,
+ 0x7235A000, 0x80000018, 0xC2000000, 0xC760E718, 0xC7604220, 0x5E200000, 0x8400028A, 0xC2200002,
+ 0xC0004930, 0xCE001008, 0x99008690, 0xC0004828, 0xC9400000, 0xC1800002, 0xC0004780, 0xC93C0000,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD3C0000, 0x58380000, 0xCA000000, 0x00000000, 0x00000000,
+ 0xA6000112, 0xC0004940, 0xCA800000, 0xC0004942, 0xCA400000, 0xC7600080, 0xC6A01840, 0xC6601040,
+ 0xC000493A, 0xCA400000, 0xC0004934, 0xCA800000, 0xC0007200, 0x40300000, 0x40240000, 0x5C000004,
+ 0x5EC07400, 0x8800FFFA, 0x5C000200, 0xCE000000, 0x58000002, 0x5EC07400, 0x8800FFFA, 0x5C000200,
+ 0xCE800000, 0xC000493E, 0xCA000000, 0xC2400000, 0x5838000C, 0xCE400000, 0x99008690, 0xC0004830,
+ 0xC9400000, 0xC6180000, 0xC0004930, 0xC6100080, 0xCD000080, 0x80000090, 0xC2400002, 0x58380008,
+ 0xCE400008, 0xC0004944, 0xCF400000, 0x80000290, 0xC000493C, 0xCA400000, 0xDFE80000, 0x5A300018,
+ 0xC0007200, 0x40200000, 0xCA000000, 0x58380008, 0xC6501080, 0xCD001080, 0x5838000A, 0xCE800000,
+ 0x58380026, 0xCE000000, 0xC0004944, 0xCF400000, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420050,
+ 0x80000050, 0x00000000, 0x99008690, 0xC0004826, 0xC9400000, 0xC1800002, 0xC0004760, 0xC93C0000,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD3C0000, 0x8000FD90, 0xC2000000, 0xC2400080, 0xDF600040,
+ 0xB624FFCA, 0xC000491C, 0xCA400000, 0xC000491E, 0xCA800000, 0x99007F18, 0xDA580000, 0xDA980001,
+ 0x00000000, 0xC0004934, 0xCA000000, 0x00000000, 0xC2800000, 0xA6020140, 0xC2400004, 0xC2000200,
+ 0xDF690050, 0x46A14000, 0x46694000, 0x8800FFC2, 0x00000000, 0xC000491A, 0xC9800000, 0xC0004862,
+ 0xC9400000, 0x6D9C6000, 0x459CE000, 0x59DC4C80, 0x99007D78, 0xD9580000, 0xD9980001, 0xD9D40000,
+ 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420050, 0xC2000000, 0xC2400080, 0xDF600040, 0xB624FFCA,
+ 0xC000491C, 0xCA400000, 0xC000491E, 0xCA800000, 0x99007F18, 0xDA580000, 0xDA980001, 0x00000000,
+ 0x58380008, 0xCA400000, 0xC2000000, 0xCE000020, 0xC2A1FFFE, 0x5AA9FFFE, 0xCE001080, 0x5838000A,
+ 0xCE800000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0000838, 0xC2500002, 0xCE440808, 0xC0004848, 0xCBC40000, 0xC3800000, 0xC000082C, 0xCB840030,
+ 0x5FFC0002, 0xC0004848, 0xCFC40000, 0x58880002, 0x44B88000, 0xC1000000, 0xC5080006, 0xC0004844,
+ 0xCC840000, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0x8000CBD8, 0xC2000000, 0xDF600040,
+ 0x5E200080, 0x84000282, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xC000480C, 0xCA000000, 0xC0004910, 0xCA400000, 0xC000492C, 0xCA800000,
+ 0xC0004968, 0xCAC00000, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0x76610000, 0x76A10000,
+ 0x762D6000, 0x840001C2, 0xC0004926, 0xCA400000, 0xC201FFFE, 0x762D6000, 0x5A640002, 0x6AE50010,
+ 0x5F200000, 0x84000002, 0x6A250000, 0x8000FFF8, 0xC6E00000, 0x62014008, 0xC0004926, 0xCE800000,
+ 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC0004968,
+ 0xCA400000, 0xC2000002, 0x6A290000, 0x7E010000, 0x76252000, 0xCE400000, 0x00000000, 0xC121FFFE,
+ 0x5911FE54, 0x15000000, 0x6EB4A000, 0x6E944000, 0x4575A000, 0x46B5A000, 0x5B744E20, 0x58340002,
+ 0xC2000000, 0xCA0000E0, 0x5834002E, 0xC2400000, 0xCA400080, 0x6EB0A000, 0x6EBC4000, 0x47F18000,
+ 0x46B18000, 0x5B300E4E, 0x5B300004, 0x6E642000, 0x4225E000, 0xC39A8024, 0xC7380068, 0xC6B81C20,
+ 0x99007F18, 0xDB980000, 0xDBD80001, 0x00000000, 0xC2000000, 0xDF600040, 0x5E200080, 0x840002BA,
+ 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC000490E, 0xCA000000, 0xC000492A, 0xCA400000, 0xC000496A, 0xCB000000, 0xC0004956, 0xCAC00000,
+ 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0x76318000, 0x76718000, 0x84000202, 0xC201FFFE,
+ 0x76318000, 0x5AEC0002, 0x6B2D0010, 0x5EA00000, 0x84000002, 0x6A2D0000, 0x8000FFF8, 0xC7200000,
+ 0x62016008, 0xC0004956, 0xCEC00000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xC000496A, 0xCA400000, 0xC2000002, 0x6A2D0000, 0x7E010000, 0x76252000,
+ 0xCE400000, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0x6EF4A000, 0x6ED44000, 0x4575A000,
+ 0x46F5A000, 0x5B744E20, 0x5834000E, 0xC2000000, 0xCA0000E0, 0x58340008, 0xC2400000, 0xCA420080,
+ 0x5834000C, 0xC2800000, 0xCA832018, 0x6E644010, 0x42250000, 0x4229E000, 0xC39A8008, 0x58340008,
+ 0xCB809020, 0x58340008, 0xC2800000, 0xCA810018, 0x6EE0A000, 0x6EE44000, 0x46610000, 0x46E10000,
+ 0x5A200008, 0x5A200E28, 0x42290000, 0xC6380068, 0xC6F81C20, 0x99007F18, 0xDB980000, 0xDBD80001,
+ 0x00000000, 0xC000495A, 0xC8400000, 0x00000000, 0xC3C00002, 0x7BC42000, 0xCC400000, 0xC0001A1C,
+ 0xCA000000, 0xC2400008, 0x6A452000, 0x76610000, 0x84000E82, 0xC0000A28, 0xC3800000, 0xCB840030,
+ 0xC0000A14, 0xC3400000, 0xCB440030, 0xC0004880, 0xCB040000, 0x47788000, 0x88000E30, 0x58041802,
+ 0xCAC00000, 0xA7000040, 0x00000000, 0x00000000, 0xA6C8C5A8, 0xC2800000, 0xC6E80020, 0x80000058,
+ 0x00000000, 0x00000000, 0x00000000, 0x8000C578, 0x00000000, 0xC2800000, 0xC7282020, 0xC000490E,
+ 0xCA400000, 0x6BE9E000, 0x00000000, 0x77E52000, 0x8400C530, 0x6EA0A000, 0x6E944000, 0x45610000,
+ 0x46A10000, 0x5A204E20, 0x5820000C, 0xCA000000, 0xC0004946, 0xCE800000, 0xA6220378, 0x00000000,
+ 0xC2200060, 0xC0004948, 0xCE000010, 0xCE001040, 0xC240000A, 0xC000494A, 0xCE400000, 0xC2B60002,
+ 0xC0004964, 0xCE801B08, 0x990081E8, 0xC00048A0, 0xC8840000, 0x00000000, 0xC0004946, 0xCBC00000,
+ 0x00000000, 0x00000000, 0x6FF8A000, 0x6FD44000, 0x4579C000, 0x47F9C000, 0x5BB84E20, 0x99007FA8,
+ 0xDBD80000, 0xDB980001, 0x00000000, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420050, 0xC000491C,
+ 0x990081A0, 0xC9400001, 0xC9800000, 0x00000000, 0x99007F18, 0xD9580000, 0xD9980001, 0x00000000,
+ 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x99007BE0,
+ 0xDBD80000, 0xDB980001, 0xC7D80000, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0x6FF8A000,
+ 0x6FD44000, 0x4579C000, 0x47F9C000, 0x5BB84E20, 0x58380010, 0xCA000000, 0xC0004874, 0xC8040000,
+ 0x6C908000, 0x44908000, 0x44908000, 0x40100000, 0xCA400000, 0xC4340000, 0x00000000, 0xC7400000,
+ 0xCE000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC000490E, 0xCA400000, 0xC2800002, 0x6ABD4000, 0x72A52000, 0xCE400000, 0x00000000, 0xC121FFFE,
+ 0x5911FE54, 0x15000000, 0x99008690, 0xC0004836, 0xC9400000, 0xC1800002, 0x00000000, 0x00000000,
+ 0x00000000, 0xA8E2FFC8, 0x00000000, 0xC1220002, 0xD90C0000, 0xC2000000, 0xC0000A14, 0xCA040030,
+ 0xC0000A28, 0xC2500002, 0xCE440808, 0x58880002, 0xB608FFF8, 0xC00048A0, 0xC0800000, 0xCC840000,
+ 0x8000C150, 0xC0004946, 0xCBC00000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xC000490E, 0xCA400000, 0xC2800002, 0x6ABD4000, 0x72A52000, 0xCE400000,
+ 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0x6FF8A000, 0x6FD44000, 0x4579C000, 0x47F9C000,
+ 0x5BB84E20, 0x58380008, 0xCA000000, 0x5838000C, 0xCA400000, 0xC3400000, 0xC6340008, 0xC000494E,
+ 0xCF400000, 0xC2800000, 0xC62A0080, 0xC3000000, 0xC6308020, 0x6F304000, 0x43298000, 0xC000493C,
+ 0xCF000000, 0xC2C00000, 0xC66C0080, 0xC0004950, 0xCEC00000, 0xC2800000, 0xC66AE028, 0xC0004954,
+ 0xCE800000, 0x5F740000, 0x840001A0, 0x5E300028, 0x462D2000, 0x8400016A, 0x462D2000, 0x88000132,
+ 0x5E300018, 0x462D2000, 0x88000012, 0x462D2000, 0x8400002A, 0x00000000, 0x800000C0, 0x00000000,
+ 0x99008328, 0xDBD80000, 0xDB980001, 0xC7800000, 0xC3400002, 0xC000494E, 0xCF400000, 0xC161FFFE,
+ 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC000490E, 0xCA400000,
+ 0xC2800002, 0x6ABD4000, 0x7E814000, 0x76A52000, 0xCE400000, 0x00000000, 0xC121FFFE, 0x5911FE54,
+ 0x15000000, 0xC2200060, 0xC0004948, 0xCE001040, 0xC2000000, 0xC000494C, 0xCE000000, 0x80000068,
+ 0x00000000, 0x99008328, 0xDBD80000, 0xDB980001, 0xC7800000, 0x99008528, 0xDBD80000, 0xDB980001,
+ 0xC7800000, 0xC2200058, 0xC0004948, 0xCE001040, 0xC2000002, 0xC000494C, 0xCE000000, 0xC2000006,
+ 0xC0001006, 0xCE000000, 0x5838000A, 0xCA400000, 0xC2200982, 0x5A203B6E, 0xC0001008, 0xCE000000,
+ 0xC000100A, 0xCE400000, 0xC0004954, 0xCA800000, 0xC200000C, 0xC000494A, 0xCE000000, 0xC0004948,
+ 0xCE800010, 0xC2B60000, 0xC0004964, 0xCE800000, 0x990081E8, 0xC00048A0, 0xC8840000, 0x00000000,
+ 0xC0004946, 0xCBC00000, 0xC000494C, 0xCA000000, 0x6FF8A000, 0x6FD44000, 0x4579C000, 0x47F9C000,
+ 0x5BB84E20, 0x5E200000, 0x840000FA, 0x00000000, 0x99007FA8, 0xDBD80000, 0xDB980001, 0x00000000,
+ 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420050, 0xC000491C, 0x990081A0, 0xC9400001, 0xC9800000,
+ 0x00000000, 0x99007F18, 0xD9580000, 0xD9980001, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x15400000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x99007BE0, 0xDBD80000, 0xDB980001, 0xC7D80000,
+ 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0xC000493C, 0xCA800000, 0xC000494E, 0xCAC00000,
+ 0xC3000018, 0xC3400006, 0x5E200000, 0x84000012, 0xC2800000, 0xC2C00000, 0xC300001E, 0xC3400000,
+ 0xC6AC1080, 0xC72C0420, 0xC76C0818, 0x58380010, 0xCA800000, 0x58380008, 0xCEC00000, 0xC6280108,
+ 0xC0004874, 0xC8040000, 0x6C908000, 0x44908000, 0x44908000, 0x40100000, 0xCB000000, 0xC4340000,
+ 0x00000000, 0xC7400000, 0xCE800000, 0xC0004952, 0xCE800000, 0x00000000, 0x00000000, 0x00000000,
+ 0xA8E2FFC8, 0x00000000, 0xC000494C, 0xCA000000, 0xC0004950, 0xCAC00000, 0x5E200000, 0x84000052,
+ 0xDFE80000, 0x7E814000, 0x5834001A, 0xCE800000, 0x99008690, 0xC0004834, 0xC9400000, 0xC1800002,
+ 0x99008690, 0xC0004838, 0xC9400000, 0xC6D80000, 0xC1220002, 0xD90C0000, 0x5E200000, 0x84000028,
+ 0x5838002C, 0xCB000000, 0xDFE80000, 0x00000000, 0x58380014, 0xCF000000, 0x80000000, 0xC2A1FFFE,
+ 0x5AA9FFFE, 0x5838000A, 0xCE800000, 0xC3000000, 0xC0000A14, 0xCB040030, 0xC2D00002, 0xC0000A28,
+ 0xCEC40808, 0xC000494E, 0xCA800000, 0x58880002, 0xB4B0FFF8, 0xC00048A0, 0xC0800000, 0xCC840000,
+ 0x5EA80000, 0x84000152, 0x5E200000, 0x84000140, 0xC000493C, 0xCA800000, 0x00000000, 0x00000000,
+ 0x5AA80060, 0xCE800000, 0x99008328, 0xDBD80000, 0xDB980001, 0xC7800000, 0x99008528, 0xDBD80000,
+ 0xDB980001, 0xC7800000, 0xC0004952, 0xCAC00000, 0x58380000, 0xCA800000, 0xC30C0002, 0xC7F00020,
+ 0xA6800090, 0x00000000, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xC0001800, 0xCA000000, 0x00000000, 0x00000000, 0xA60CFFCA, 0xC6F00508,
+ 0xC6B0C408, 0xCF000000, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0x8000B7A0, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x8000B738, 0xDCBC0001, 0x5FFC0000, 0x84000942, 0xC3800002,
+ 0xDB880001, 0xC3800000, 0xDB880001, 0xC0004728, 0xC9000000, 0x00000000, 0x00000000, 0x59100002,
+ 0xCD000000, 0xC0004730, 0xC9800000, 0xC000472E, 0xC9400000, 0xC00047DC, 0xC9000000, 0xC00047DE,
+ 0xC9C00000, 0xC000472E, 0xCD800000, 0x6D110000, 0xC5D30040, 0xC00047DC, 0xCD000000, 0x4558A000,
+ 0x6DDD0000, 0xC55C0040, 0xC00047DE, 0xCDC00000, 0xC0001AC4, 0xC9400000, 0xC0001AC8, 0xC9800000,
+ 0xC000472C, 0xC9C00000, 0x45588000, 0xC1000002, 0x41D0E004, 0xCDC00000, 0xC5501080, 0xC5900080,
+ 0xC000472A, 0xCD000000, 0xC0001AF0, 0xCBC00000, 0x58000002, 0xCB800000, 0xC3400000, 0xC7F50040,
+ 0x6F702000, 0x5B304300, 0xC000474C, 0xCAC00000, 0xC0004720, 0xC9400000, 0x00000000, 0x00000000,
+ 0x5D940002, 0x6D9B8000, 0x6D9B8010, 0x581847E0, 0xC9800000, 0x581447E0, 0xC9C00000, 0x5D2C0000,
+ 0x84000062, 0xC7901080, 0xC7D00080, 0xCD000000, 0xC1000000, 0xC5910040, 0x47508000, 0x84000078,
+ 0xC0004722, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x80000040, 0xC1000000,
+ 0xC5D10040, 0x47508000, 0x84000022, 0xC0004724, 0xC9000000, 0x00000000, 0x00000000, 0x59100002,
+ 0xCD000000, 0xA7840060, 0x59540002, 0x6D578000, 0x6D578010, 0xC0004720, 0xCD400000, 0xC1000000,
+ 0xC5910040, 0x47508000, 0x84000020, 0xC0004726, 0xC9000000, 0x00000000, 0x00000000, 0x59100002,
+ 0xCD000000, 0xA7800098, 0xC2800002, 0xC000474E, 0xCE800000, 0xC2C00000, 0xC000474C, 0xCEC00000,
+ 0xC0004758, 0xCFC00000, 0x58000002, 0xCF800000, 0xC000475C, 0xC9000000, 0x00000000, 0x00000000,
+ 0xA53E001A, 0x00000000, 0xC13E0002, 0xCFC00000, 0xCD001E10, 0x58000002, 0xCF800000, 0x80000188,
+ 0xC000475C, 0xC13C0002, 0xCD001E10, 0x5D2C0000, 0x84000162, 0xC2C00000, 0xC000474C, 0xCEC00000,
+ 0x98C08AF0, 0xC7540000, 0xC0004740, 0xC9C00000, 0x5D240000, 0x8400002A, 0xC1000002, 0xC0004750,
+ 0xCD000000, 0xC0004752, 0xCD000000, 0x800000E8, 0x00000000, 0x98C08BE0, 0xC7540000, 0xC0004742,
+ 0xC9800000, 0x5D240000, 0x84000012, 0xC1000002, 0xC0004752, 0xCD000000, 0x80000048, 0xC0004742,
+ 0xC9400000, 0xC0004754, 0xC1000002, 0xCD000000, 0x98C08CF0, 0xC5540000, 0xC7580000, 0x00000000,
+ 0xC0004742, 0xCF400000, 0x98C08AB8, 0xC1400000, 0xC7540028, 0x6F40A010, 0xC1000000, 0xC7D00040,
+ 0x58300000, 0x6D110000, 0xCD000840, 0xA7840378, 0xC000474C, 0xCAC00000, 0xC000474E, 0xCA800000,
+ 0xC0004750, 0xCBC00000, 0xC0004752, 0xCB800000, 0xC0004710, 0xC9000000, 0x00000000, 0x00000000,
+ 0x59100002, 0xCD000000, 0x5D280002, 0x840000A0, 0xC000473C, 0xC9000000, 0x00000000, 0x00000000,
+ 0x59100002, 0xCD000000, 0xC0004712, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000,
+ 0xC0004754, 0xC9000000, 0x00000000, 0x00000000, 0x5D100000, 0x84000202, 0x58300000, 0xC13C0002,
+ 0xCD001E08, 0x800001E0, 0xC0004714, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000,
+ 0x5D380000, 0x84000022, 0xC0004736, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000,
+ 0x5D3C0000, 0x8400002A, 0xC0004718, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000,
+ 0x80000128, 0xC1000000, 0x58300000, 0xC903E008, 0x00000000, 0x00000000, 0x5D100000, 0x8400002A,
+ 0xC000471A, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x800000B8, 0x58300000,
+ 0xC13E0002, 0xCD001F08, 0xC1000000, 0x58300000, 0xC903C008, 0x00000000, 0x00000000, 0x5D100000,
+ 0x8400006A, 0xC0004716, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0xC000473A,
+ 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x58300000, 0xC13C0000, 0xCD001E08,
+ 0xC1000000, 0xC0004746, 0xCD000000, 0xC0004750, 0xCD000000, 0xC0004752, 0xCD000000, 0xC000474E,
+ 0xCD000000, 0xC2C00002, 0xC000474C, 0xCEC00000, 0xC0004754, 0xCD000000, 0xC3CE0002, 0xC0000800,
+ 0xCFC00708, 0xC3E1FFFE, 0x597DFFFE, 0x593DFE14, 0x94000001, 0x00000000, 0x00000000, 0x00000000,
+ 0xC000487C, 0xC8040000, 0x00000000, 0x00000000, 0x40080000, 0xCBC00000, 0xC4380000, 0x00000000,
+ 0xC000480E, 0xCA000000, 0xC0004858, 0xCB440000, 0x00000000, 0x00000000, 0x46350000, 0x88000098,
+ 0x00000000, 0xA7C00028, 0xC0004854, 0xC1000002, 0xCD040000, 0xC11C0000, 0xC000082C, 0xCD040E08,
+ 0x800000C0, 0x00000000, 0xA7D20118, 0x00000000, 0xC7E14048, 0xC2400000, 0xC6246030, 0xC200006A,
+ 0x46610000, 0xC6240038, 0xC0000810, 0xCE440038, 0x8000FF58, 0xC2000000, 0xC0000808, 0xCA040018,
+ 0xC11C0000, 0xC000082C, 0xCD040E08, 0x5A200002, 0x5E600010, 0x8400FFF8, 0xC2000000, 0xC0000808,
+ 0xCE040018, 0xC3400000, 0x80000010, 0xC1200002, 0xC0000818, 0xCD041008, 0x5B740002, 0xC0004858,
+ 0xCF440000, 0x99007930, 0xC0004848, 0xC9440000, 0xC1800000, 0xC11C0002, 0xC000082C, 0xCD040E08,
+ 0x80000860, 0x5B740002, 0xC0004858, 0xCF440000, 0xC7800000, 0xC13C0002, 0xCD001E08, 0xC0004848,
+ 0xC9440000, 0xC1800000, 0xC000082C, 0xC9840030, 0x59540002, 0xC0004848, 0xCD440000, 0x58880002,
+ 0xB49807D8, 0x00000000, 0xC0800000, 0x800007C8, 0xC000487C, 0xC8040000, 0x00000000, 0x00000000,
+ 0x40080000, 0xCBC00000, 0xC4280000, 0x00000000, 0xA7C00110, 0xC000484C, 0xCA040000, 0xC2400000,
+ 0xC0001AEC, 0xCA440020, 0x5A200002, 0xC000484C, 0xCE040000, 0xB624006A, 0xC6800000, 0xC13C0002,
+ 0xCD001E08, 0xC0004848, 0xC9440000, 0xC1800000, 0xC000082C, 0xC9840030, 0x59540002, 0xC0004848,
+ 0xCD440000, 0x58880002, 0xB49806C8, 0x00000000, 0xC0800000, 0x800006B8, 0xC0004854, 0xC1000004,
+ 0xCD040000, 0xC0000820, 0xC2000002, 0xCE040000, 0xC2000000, 0xC000484C, 0xCE040000, 0xC0004858,
+ 0xCE040000, 0x8000FF10, 0xC0004854, 0xC1000000, 0xCD040000, 0xC11C0000, 0xC000082C, 0xCD040E08,
+ 0x99007930, 0xC0004848, 0xC9440000, 0xC1800000, 0xC1200000, 0xC0000818, 0xCD041008, 0xC11C0002,
+ 0xC000082C, 0xCD040E08, 0xC2000000, 0xC000484C, 0xCE040000, 0x800005B8, 0xC0001AC0, 0xCB840000,
+ 0xC000487C, 0xC8040000, 0x00000000, 0x00000000, 0x40080000, 0xCBC00000, 0xC4280000, 0x00000000,
+ 0xA78004C2, 0x00000000, 0x00000000, 0xA7C00482, 0x00000000, 0xC0001B00, 0xC2060006, 0xCE040310,
+ 0xA7E8043A, 0x00000000, 0xC0004850, 0xCA040000, 0xC2400000, 0xC0004812, 0xCA420080, 0x5A200002,
+ 0xC0004850, 0xCE040000, 0x5E640000, 0x84000002, 0x46610000, 0x880002E0, 0xC6800000, 0xC13C0002,
+ 0xCD001E08, 0xC0001ACC, 0xC2000002, 0xCE040008, 0x5C440000, 0x84000238, 0xC0004810, 0xC9400000,
+ 0xC6800000, 0xCBC00000, 0x00000000, 0xC1000000, 0xA54001E8, 0xC53C1008, 0x00000000, 0xA7FC01D2,
+ 0xC0001AF0, 0xC1000000, 0x58000002, 0xC9000008, 0xC000474E, 0xC9800000, 0x5D100000, 0x8400000A,
+ 0xC1000002, 0xC53C1E08, 0x80000180, 0x5D180000, 0x8400000A, 0xC1000002, 0xC53C1E08, 0x80000158,
+ 0xC0004878, 0xC8040000, 0x6C908000, 0x44908000, 0x44908000, 0x40100000, 0xC9800000, 0xC4380000,
+ 0x00000000, 0xC000481E, 0xC9C00000, 0xC000481C, 0xCA000000, 0x00000000, 0x75D8C000, 0x46188000,
+ 0x840000D0, 0xC0001AF0, 0xC3400000, 0x58000000, 0xCB410040, 0xC0004746, 0xC9400000, 0x6F702000,
+ 0x5B304300, 0xC2C00000, 0x58300000, 0xCAC00040, 0x00000000, 0x00000000, 0x46D48000, 0x88000008,
+ 0xC1000002, 0xC53C1E08, 0x80000028, 0x5AEC0002, 0x58300000, 0xCEC00040, 0xC1000002, 0xC53C1008,
+ 0xC77C0840, 0xC57C0040, 0x59540002, 0xC0004746, 0xCD400000, 0xC6800000, 0xCFC00000, 0xC0004848,
+ 0xC9440000, 0xC1800000, 0xC000082C, 0xC9840030, 0x59540002, 0xC0004848, 0xCD440000, 0x58880002,
+ 0xB49801D8, 0x00000000, 0xC0800000, 0x800001C8, 0xC000471E, 0xC9000000, 0x00000000, 0x00000000,
+ 0x59100002, 0xCD000000, 0xC0004854, 0xC1000000, 0xCD040000, 0xC11C0000, 0xC000082C, 0xCD040E08,
+ 0x99007930, 0xC0004848, 0xC9440000, 0xC1800000, 0xC2000000, 0xC0000820, 0xCE040000, 0xC1200000,
+ 0xC0000818, 0xCD041008, 0xC11C0002, 0xC000082C, 0xCD040E08, 0xC0004850, 0xCE040000, 0xC2000002,
+ 0xC0001ACC, 0xCE040010, 0x800000D0, 0xC2000002, 0xC0004850, 0xCE040000, 0x8000FBE8, 0xC2000000,
+ 0xC0004850, 0xCE040000, 0xA7E60012, 0x00000000, 0xC2000002, 0xC0001B00, 0xCE040008, 0x8000FBD0,
+ 0x00000000, 0xA7860032, 0x00000000, 0xC6800000, 0xC13C0002, 0xCD001E08, 0xC2020002, 0xC7E2A548,
+ 0xC0001B00, 0xCE040000, 0x8000FB78, 0xC2040002, 0xC0001B00, 0xCE040208, 0x8000FB58, 0xC2C80002,
+ 0x6AC56000, 0xDACC0000, 0xC0004854, 0xCB440000, 0xC0004848, 0xCB840000, 0xC0000838, 0xC3C00000,
+ 0xCBC40030, 0x5EF40004, 0x8400000A, 0xC3000000, 0xC0001ACC, 0xCF040108, 0x47BD8000, 0x84000032,
+ 0x47BD8000, 0x88000038, 0xC1006E8C, 0xC1400010, 0x8D580000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0004840, 0xCC840000, 0x8000EAF8, 0xC0001AC0, 0xCAC40000, 0xC0004854, 0xCB440000, 0xA6C0F91A,
+ 0x00000000, 0x5EF40000, 0x8400F45A, 0x5EF40002, 0x8400F6EA, 0x5EF40004, 0x8400F8EA, 0xC1006CE8,
+ 0xC1400010, 0x8D580000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC0800000, 0xDF4B0040,
+ 0xC0004900, 0xCB800000, 0xC2000000, 0xC000490A, 0xA78000B0, 0xCBC00000, 0xC1000000, 0xD9000001,
+ 0xC1000002, 0xD90C0000, 0x6FF46000, 0x47F5A000, 0x5B744C80, 0xC2400000, 0x58340004, 0xCA400080,
+ 0xC0004900, 0xCE000008, 0x5A640002, 0x58340004, 0xC6500080, 0xCD000080, 0xC0004914, 0xCA400000,
+ 0xC2000002, 0x6A3D0000, 0x72252000, 0xCE400000, 0xC0000408, 0xCE000000, 0xA78200B8, 0xC0004908,
+ 0xCBC00000, 0xC1000000, 0xD9000001, 0xC1000002, 0xD90C0000, 0x6FF4A000, 0x6FD44000, 0x4575A000,
+ 0x47F5A000, 0x5B744E20, 0xC2800000, 0x58340006, 0xCA800080, 0xC2000000, 0xC0004900, 0xCE000108,
+ 0x5EA80002, 0x58340006, 0xC6900080, 0xCD000080, 0x5A7C0020, 0xC2000002, 0x6A250000, 0xC0000408,
+ 0xCE000000, 0xC0000032, 0xDCA80001, 0xC1000002, 0x46914000, 0x00000000, 0x8C100006, 0x00000000,
+ 0x00000000, 0x00000000, 0xA4800210, 0x00000000, 0xC3C00000, 0xC000140E, 0xCBC00020, 0xC3400000,
+ 0xC2400000, 0x6FF86000, 0x47F9C000, 0x5BB84C80, 0x58380008, 0xCB400080, 0x58380006, 0xCA400080,
+ 0x5F740002, 0x58380008, 0xC7500080, 0xCD000080, 0xC2000000, 0x58380004, 0xCA020080, 0xC3000000,
+ 0x5838000C, 0xCB000028, 0x5A640002, 0x46250000, 0x8400FFF8, 0xC2400000, 0x58380006, 0xC6500080,
+ 0xCD000080, 0xC2000000, 0x5838000A, 0xCA020080, 0x5B300002, 0x5838000C, 0xC7100028, 0xCD000028,
+ 0xC2420020, 0x5A200004, 0x46612000, 0x8400FFF8, 0xC2000000, 0x5838000A, 0xC6101080, 0xCD001080,
+ 0xC0004966, 0xCA400000, 0xC2000002, 0x6A3D0000, 0x72252000, 0xCE400000, 0x5F740000, 0x84000028,
+ 0xC0004912, 0xCA000000, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x76E10000, 0xCE000000, 0x5F300020,
+ 0x84000028, 0xC0004924, 0xCA000000, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x76E10000, 0xCE000000,
+ 0xA4820050, 0xC2400000, 0xC000140E, 0xCA408020, 0xC2000002, 0xC0004900, 0xCE000008, 0xC000490A,
+ 0xCE400000, 0xC1000000, 0xD9000001, 0xD8400080, 0xC1000004, 0xD9000001, 0xA4840288, 0x00000000,
+ 0xC3C00000, 0xC000140E, 0xCBC10020, 0xC2800000, 0xC2000000, 0x6FF8A000, 0x6FD44000, 0x4579C000,
+ 0x47F9C000, 0x5BB84E20, 0x5838002E, 0xCA800080, 0x58380006, 0xCA020080, 0xC3400000, 0x5838002E,
+ 0xCB420080, 0x5AA80002, 0x46290000, 0x8400FFF8, 0xC2800000, 0x5838002E, 0xC6900080, 0xCD000080,
+ 0x5F740002, 0x5838002E, 0xC7501080, 0xCD001080, 0xC0004968, 0xCA400000, 0xC2000002, 0x6A3D0000,
+ 0x72252000, 0xCE400000, 0xC000492A, 0xCA800000, 0x5E740000, 0x84000028, 0xC0004910, 0xCA000000,
+ 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x76E10000, 0xCE000000, 0x6ABD4010, 0xA68000D2, 0x00000000,
+ 0xC0004910, 0xCA000000, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x76E10000, 0xCE000000, 0x58380032,
+ 0xCA000000, 0x58000002, 0xCA400000, 0x5838000C, 0x00000000, 0xCE000001, 0xCE400000, 0xC000492A,
+ 0xCA000000, 0xC2C00002, 0x6AFD6000, 0x72E10000, 0xCE000000, 0xC000492C, 0xCA000000, 0xC2C00002,
+ 0x6AFD6000, 0x72E10000, 0xCE000000, 0x80000028, 0xC000492C, 0xCA000000, 0xC2C00002, 0x6AFD6000,
+ 0x7EC16000, 0x76E10000, 0xCE000000, 0xA4880100, 0xC2C00000, 0xC000140E, 0xCAC20020, 0xC000490E,
+ 0xCA400000, 0xC2000002, 0x6A2D0000, 0x7E010000, 0x76252000, 0xCE400000, 0xC000496A, 0xCA400000,
+ 0xC2000002, 0x6A2D0000, 0x72252000, 0xCE400000, 0x6EF0A000, 0x6ED44000, 0x45718000, 0x46F18000,
+ 0x5B304E20, 0x58300000, 0xCA000000, 0x00000000, 0xC2400002, 0x76252000, 0x84000032, 0xC24C0002,
+ 0xC6E40020, 0xC624C408, 0x58300010, 0xCA400508, 0x00000000, 0xC0001800, 0xCE400000, 0xA4860050,
+ 0xC2400000, 0xC000140E, 0xCA418020, 0xC2020002, 0xC0004900, 0xCE000108, 0xC0004908, 0xCE400000,
+ 0xC1000000, 0xD9000001, 0xD8400080, 0xC1000004, 0xD9000001, 0xA48C0028, 0xC2800002, 0xC000484A,
+ 0xCE800000, 0xC2800000, 0xC000474A, 0xCE800000, 0xC0004846, 0xCE800000, 0xC0001408, 0xCC800000,
+ 0xC10E0002, 0xD90C0000, 0x8000EA60, 0xDFBC0001, 0xC000496E, 0x99008638, 0xC9400000, 0xC7D80000,
+ 0x00000000, 0xC5700000, 0x5EF00020, 0x88000130, 0x6F346000, 0x4735A000, 0x5B744C80, 0x58340008,
+ 0xC2400000, 0xCA400080, 0x00000000, 0xC2000000, 0x5A640002, 0xCE400080, 0x58340004, 0xCA000080,
+ 0x00000000, 0x00000000, 0x5E200002, 0xCE000080, 0xC0004912, 0xCA800000, 0xC2400002, 0x6A712000,
+ 0x72694000, 0xCE800000, 0x5E200000, 0x8400003A, 0xC000480A, 0xCA000000, 0xC0000408, 0xCA800000,
+ 0x76610000, 0x00000000, 0x72294000, 0xCE800000, 0x80000020, 0xC0004914, 0xCA000000, 0x7E412000,
+ 0x00000000, 0x76610000, 0xCE000000, 0x800000B8, 0x6EF4A000, 0x6ED44000, 0x4575A000, 0x46F5A000,
+ 0x5B744E20, 0x5834002E, 0xC2400000, 0xCA420080, 0x00000000, 0xC2000000, 0x5A640002, 0xC6501080,
+ 0xCD001080, 0x58340006, 0xCA000080, 0x00000000, 0x00000000, 0x5A200002, 0xCE000080, 0xC0004910,
+ 0xCA400000, 0xC2000002, 0x6A2D0000, 0x72252000, 0xCE400000, 0xC2000002, 0x6A310000, 0xC000042A,
+ 0xCE000000, 0xC1040002, 0xD90C0000, 0x00000000, 0x8000E7D0, 0x00000000, 0xC4980930, 0x9D000000,
+ 0xC5580030, 0xC0000838, 0xCD840000, 0xC1440200, 0xC1C03200, 0xC55C1078, 0xC000100E, 0x9D000000,
+ 0xCD800000, 0xC000100C, 0xCDC00000, 0xC0004862, 0xC9C00000, 0x00000000, 0x00000000, 0xD9D80001,
+ 0xC0007200, 0x401C0000, 0x5DC07400, 0x8800FFFA, 0x5C000200, 0xCD800000, 0xC1F0000A, 0x71D4A000,
+ 0xDD980000, 0xDD9C0001, 0x41D8E000, 0xC5D40268, 0xC0001010, 0xCD400000, 0x6C9C8000, 0x449CE000,
+ 0x449CE000, 0x59DC0004, 0xC1601260, 0xC5D40268, 0x9D000000, 0xC0001012, 0xCD400000, 0x00000000,
+ 0x00000000, 0xD9580000, 0x6D586000, 0x4558C000, 0x59984C80, 0xD9980001, 0x5818000A, 0xC1800000,
+ 0xC9800080, 0xC0005400, 0x6D5CA000, 0x401C0000, 0x40180000, 0xC9400000, 0x58000002, 0x00000000,
+ 0xC9C00000, 0xC0004930, 0xCD400000, 0xC0004932, 0xCDC00000, 0x59980004, 0xC1C20020, 0xB59CFFF8,
+ 0x00000000, 0xC1800000, 0xDD9C0001, 0x581C000A, 0xCD800080, 0x581C000C, 0xC1800000, 0xC9800028,
+ 0xC1C00002, 0xDD940000, 0x69D4E000, 0x5D980002, 0xCD800028, 0xC0004924, 0xC9800000, 0x00000000,
+ 0x9D000000, 0x00000000, 0x71D8C000, 0xCD800000, 0xC000492A, 0xC9400000, 0xC1C00002, 0x69D8E000,
+ 0x7DC0C000, 0x7594A000, 0xCD400000, 0xC000492C, 0xC9400000, 0xDD800001, 0x58000032, 0x75D4A000,
+ 0x84000078, 0xC9400001, 0xC9800000, 0xDD800001, 0x5800000C, 0x00000000, 0xCD400001, 0xCD800000,
+ 0xC000492C, 0xC9400000, 0xC000492A, 0xC9800000, 0x71D4A000, 0xC000492C, 0xCD400000, 0x71D8C000,
+ 0xC000492A, 0xCD800000, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0xC0004862, 0xC9800000,
+ 0x00000000, 0xC1C00200, 0x4194C000, 0x45D8E000, 0x8800FFFA, 0xC5D80000, 0xC0004862, 0xCD800000,
+ 0xC0001406, 0xC9800000, 0xC1C00002, 0x9D000000, 0xC5D80A08, 0xC5581050, 0xCD800000, 0xC0004930,
+ 0xC9800000, 0xC0004932, 0xC9C00000, 0xC140000E, 0xC5581C20, 0xDD940000, 0xC0007200, 0x40140000,
+ 0x5D407400, 0x8800FFFA, 0x5C000200, 0xCD800000, 0x58000002, 0x5D407400, 0x8800FFFA, 0x5C000200,
+ 0xCDC00000, 0xDD540000, 0xC1C00000, 0x58140006, 0xC9C20080, 0xC1800000, 0x58140000, 0xC98000E0,
+ 0x6DDC2000, 0xC000491E, 0x41D8E000, 0xCDC00000, 0xDD980000, 0xC1C00022, 0xC5D80D78, 0xDD940001,
+ 0xC5581C20, 0xC000491C, 0xCD800000, 0xDD540000, 0xC1C00000, 0x58140006, 0xC9C20080, 0xC1800000,
+ 0x58140004, 0xC9820080, 0x00000000, 0x59DC0002, 0x459CC000, 0x8400FFF8, 0xC1C00000, 0x9D000000,
+ 0x58140006, 0xC5D81080, 0xCD801080, 0xC0004860, 0xC9400000, 0xC1820080, 0xC1D00002, 0x58146B00,
+ 0xD5800000, 0x58000002, 0xD5800001, 0x59540004, 0xB558FFF8, 0xC0004860, 0xC1400000, 0xCD400000,
+ 0xDD980001, 0x9D000000, 0xDD940000, 0xC0001404, 0xCDC00808, 0xC1C00000, 0xC1800200, 0x5D980004,
+ 0xDF5D0050, 0x45D8A000, 0x8800FFDA, 0xDD800001, 0x5800000C, 0x00000000, 0xC9400001, 0xC9800000,
+ 0xC1C00002, 0xC5D43F08, 0xC5D81E08, 0xC0004862, 0xC9C00000, 0x00000000, 0x00000000, 0x581C7200,
+ 0x5DC07400, 0x8800FFFA, 0x5C000200, 0xCD400000, 0x58000002, 0x5DC07400, 0x8800FFFA, 0x5C000200,
+ 0xCD800000, 0xC0004862, 0xC9C00000, 0x00000000, 0xC15004C0, 0xC5D40068, 0xDD9C0000, 0xC5D41C20,
+ 0xC1C00000, 0xDD800001, 0x58000030, 0xC9C00080, 0xDD800001, 0x58000002, 0xC9800000, 0x6DDC2000,
+ 0xC000491C, 0x41D8E000, 0xCD400001, 0xCDC00000, 0xDD940001, 0xC1C00000, 0x58140030, 0xC9C00080,
+ 0xC1800000, 0x58140006, 0xC9820080, 0x00000000, 0x59DC0002, 0x459CC000, 0x8400FFF8, 0xC1C00000,
+ 0x9D000000, 0x58140030, 0xC5D80080, 0xCD800080, 0xC1C00000, 0xDF5C0040, 0x5DDC0080, 0x8400FFD2,
+ 0x00000000, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0xC160FFFE, 0xC0000A10, 0xC9440068,
+ 0xC1A0FFFE, 0x59980E28, 0xC000100C, 0xCD400000, 0xC000100E, 0xCD800000, 0xC0004964, 0xC9800000,
+ 0x00000000, 0xC170000A, 0x7194A000, 0x6C988000, 0x4498C000, 0x4498C000, 0x59980004, 0xC5940278,
+ 0xC0001010, 0xCD400000, 0xC0004946, 0xC9400000, 0x00000000, 0x00000000, 0x6D58A000, 0x6D5C4000,
+ 0x45D8C000, 0x4558C000, 0xC000494A, 0xC9400000, 0xC0004948, 0xC9C00000, 0x4194C000, 0xC1400012,
+ 0xC55C1820, 0x9D000000, 0xC59C0270, 0xC0001012, 0xCDC00000, 0xC1400000, 0x58000012, 0xC9410040,
+ 0xC0004950, 0xC9C00000, 0xC5580000, 0xC5940840, 0xC5581080, 0xD9940000, 0xC000493C, 0xC9400000,
+ 0xC0004954, 0xC9800000, 0x59DC00A8, 0x455CE000, 0x41D8E000, 0x5D5C0030, 0x8800FFF8, 0xC1C00030,
+ 0xC1800000, 0xC5D84030, 0xC1400000, 0xC5D40010, 0x5DD40002, 0x8400005A, 0x5DD40004, 0x84000082,
+ 0x5DD40006, 0x840000AA, 0x5DD80026, 0x840000D2, 0xDD540000, 0xDD800001, 0x58000008, 0x40180000,
+ 0xCD400000, 0x59980002, 0x8000FFA8, 0xDD540000, 0xDD800001, 0x58000008, 0x40180000, 0xCD4000C0,
+ 0x59980002, 0x8000FF70, 0xDD540000, 0xDD800001, 0x58000008, 0x40180000, 0xCD400080, 0x59980002,
+ 0x8000FF38, 0xDD540000, 0xDD800001, 0x58000008, 0x40180000, 0xCD400040, 0x59980002, 0x8000FF00,
+ 0x00000000, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0x58000012, 0xC9400000, 0xC0004954,
+ 0xC9C00000, 0xC0004950, 0xC9400080, 0xDD800001, 0x58000028, 0x5D9C0000, 0x8400003A, 0x5D9C0002,
+ 0x8400003A, 0x5D9C0004, 0x84000052, 0xC55B0040, 0xC55C08C0, 0xCD800041, 0xCDC008C0, 0x80000048,
+ 0xCD400000, 0x80000038, 0xC55900C0, 0xC55C1840, 0xCD8000C1, 0xCDC01840, 0x80000010, 0xC55A0080,
+ 0xC55C1080, 0xCD800081, 0xCDC01080, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0x59540002,
+ 0x6994E018, 0x61C0C008, 0x4194A000, 0x5D940040, 0x8800FFFA, 0xC5940000, 0x9D000000, 0xCD400000,
+ 0x00000000, 0x00000000, 0x9D000000, 0x4158A000, 0xCD400000, 0x00000000, 0xCD800001, 0x44148000,
+ 0x8800FFD8, 0x00000000, 0x9CC00000, 0x00000000, 0x00000000, 0x00000000, 0xC0004810, 0xCA010040,
+ 0xC241FFFE, 0xC1400000, 0x45608000, 0x00000000, 0x9CC00006, 0xC0004200, 0x40180000, 0xC9C00000,
+ 0x00000000, 0x00000000, 0x61C08010, 0x84000042, 0xC2400002, 0x6A512000, 0x725CE000, 0xCDC00000,
+ 0xC0004748, 0xCD800000, 0x9CC00000, 0x6D98A000, 0x5998003E, 0x45192000, 0x59540002, 0x59980002,
+ 0x45A08000, 0xC1000000, 0xC5180006, 0x8000FF20, 0x00000000, 0x40180000, 0xC9C00000, 0xC2000000,
+ 0xC5600028, 0xC1210000, 0x69208010, 0x7D008000, 0x751CE000, 0xCDC00000, 0x6D542000, 0x58144300,
+ 0xC1000000, 0xCD000001, 0x9CC00000, 0xC121FFFE, 0x5911FFFE, 0xCD000001, 0x79948000, 0x6D10A010,
+ 0x5D100000, 0x840000A8, 0x45588000, 0x88000098, 0x6D536000, 0x6D136010, 0x6D54A010, 0xC0004700,
+ 0x40140000, 0xCA000000, 0x00000000, 0x00000000, 0x6A110000, 0x6A110010, 0x62008018, 0x8400001A,
+ 0x00000000, 0x9CC00000, 0x6D54A000, 0x5954003E, 0x45152000, 0x59540002, 0x6D57A000, 0x6D57A010,
+ 0x6D54A000, 0x6D936000, 0x6D136010, 0xC1E10000, 0x69D0E010, 0x5DDC0002, 0x7DC0E000, 0x6D98A010,
+ 0x6D536000, 0x6D136010, 0x6D54A010, 0xC0004700, 0x40140000, 0xCA000000, 0x00000000, 0x00000000,
+ 0x6A110000, 0x6A110010, 0x45948000, 0x00000000, 0x75E10002, 0x62008018, 0x8400001A, 0x00000000,
+ 0x9CC00000, 0x6D54A000, 0x5954003E, 0x45152000, 0x45948000, 0x00000000, 0x9CC00002, 0x59540002,
+ 0x6D57A000, 0x6D57A010, 0xC0004700, 0x40140000, 0xCA000000, 0x8000FF50, 0x00000000, 0x00000000,
+ 0x00000000, 0x58004700, 0xC9800000, 0x9CC00000, 0x00000000, 0x6994C000, 0x6DA7E010, 0x58004700,
+ 0xC9800000, 0xC1210000, 0x9CC00000, 0x69148010, 0x7118C000, 0xCD800000, 0xC1000000, 0xC0004810,
+ 0xC9020040, 0x00000000, 0x00000000, 0x451CC000, 0x8800004A, 0xC2400002, 0x45948000, 0xC1000000,
+ 0xC5240004, 0x455C8000, 0xC1000000, 0xC5240006, 0x9CC00000, 0x00000000, 0x00000000, 0x00000000,
+ 0x59980200, 0xC2400000, 0x45D48000, 0xC1000002, 0xC5240004, 0x45588000, 0xC1000002, 0xC5240006,
+ 0x9CC00000, 0x00000000, 0x00000000, 0x00000000, 0xC0004740, 0xC9C00000, 0x59180002, 0x6D130000,
+ 0x6D130010, 0x45D08000, 0xC2400000, 0x9CC00002, 0x00000000, 0x00000000, 0x45D88000, 0x8800004A,
+ 0xC2400002, 0x45D48000, 0xC1000000, 0xC5240004, 0x45588000, 0xC1000000, 0xC5240004, 0x9CC00000,
+ 0x00000000, 0x00000000, 0x00000000, 0xC2400000, 0x45948000, 0xC1000002, 0xC5240006, 0x455C8000,
+ 0xC1000002, 0xC5240006, 0x9CC00000, 0x00000000, 0x00000000, 0x00000000, 0x59540002, 0x6D570000,
+ 0x6D570010, 0x45948000, 0x6D402000, 0x9CC00002, 0x58004300, 0x58000000, 0xC13C0002, 0xCD001E08,
+ 0x8000FF98, 0x00000000, 0x00000000, 0x00000000, 0xC1020002, 0xD90C0000, 0xC9800000, 0x59540002,
+ 0xC0004730, 0xCD400000, 0x5D980002, 0x00000000, 0x8000001E, 0x00000000, 0x9CC00000, 0xC0004732,
+ 0xCD800000, 0x00000000, 0xC0004734, 0xC9C00000, 0xC1800000, 0xC0004816, 0xC9820080, 0xC0004738,
+ 0xCDC00000, 0xC1C00000, 0xC0004734, 0x9CC00000, 0xCDC00000, 0xC0004732, 0xCD800000,
+};
+
+static unsigned int firmware_binary_data[] = {
+};
+
+
+#endif // IFXMIPS_ATM_FW_DANUBE_H
diff --git a/package/ltq-dsl/src/ifxmips_atm_fw_regs_amazon_se.h b/package/ltq-dsl/src/ifxmips_atm_fw_regs_amazon_se.h
new file mode 100644
index 000000000..af2b55086
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_fw_regs_amazon_se.h
@@ -0,0 +1,30 @@
+#ifndef IFXMIPS_ATM_FW_REGS_AMAZON_SE_H
+#define IFXMIPS_ATM_FW_REGS_AMAZON_SE_H
+
+
+
+/*
+ * Host-PPE Communication Data Address Mapping
+ */
+#define FW_VER_ID SB_BUFFER(0x2001) /* Firmware Version ID */
+#define CFG_WRX_HTUTS SB_BUFFER(0x2400) /* WAN RX HTU Table Size, must be configured before enable PPE firmware. */
+#define CFG_WRX_QNUM SB_BUFFER(0x2401) /* WAN RX Queue Number */
+#define CFG_WRX_DCHNUM SB_BUFFER(0x2402) /* WAN RX DMA Channel Number, no more than 8, must be configured before enable PPE firmware. */
+#define CFG_WTX_DCHNUM SB_BUFFER(0x2403) /* WAN TX DMA Channel Number, no more than 16, must be configured before enable PPE firmware. */
+#define CFG_WRDES_DELAY SB_BUFFER(0x2404) /* WAN Descriptor Write Delay, must be configured before enable PPE firmware. */
+#define WRX_DMACH_ON SB_BUFFER(0x2405) /* WAN RX DMA Channel Enable, must be configured before enable PPE firmware. */
+#define WTX_DMACH_ON SB_BUFFER(0x2406) /* WAN TX DMA Channel Enable, must be configured before enable PPE firmware. */
+#define WRX_HUNT_BITTH SB_BUFFER(0x2407) /* WAN RX HUNT Threshold, must be between 2 to 8. */
+#define WRX_QUEUE_CONFIG(i) ((struct wrx_queue_config*) SB_BUFFER(0x2500 + (i) * 20))
+#define WRX_DMA_CHANNEL_CONFIG(i) ((struct wrx_dma_channel_config*) SB_BUFFER(0x2640 + (i) * 7))
+#define WTX_PORT_CONFIG(i) ((struct wtx_port_config*) SB_BUFFER(0x2440 + (i)))
+#define WTX_QUEUE_CONFIG(i) ((struct wtx_queue_config*) SB_BUFFER(0x2F00 + (i) * 27))
+#define WTX_DMA_CHANNEL_CONFIG(i) ((struct wtx_dma_channel_config*) SB_BUFFER(0x2F01 + (i) * 27))
+#define WAN_MIB_TABLE ((struct wan_mib_table*) SB_BUFFER(0x2410))
+#define HTU_ENTRY(i) ((struct htu_entry*) SB_BUFFER(0x3200 + (i)))
+#define HTU_MASK(i) ((struct htu_mask*) SB_BUFFER(0x3220 + (i)))
+#define HTU_RESULT(i) ((struct htu_result*) SB_BUFFER(0x3240 + (i)))
+
+
+
+#endif // IFXMIPS_ATM_FW_REGS_AMAZON_SE_H
diff --git a/package/ltq-dsl/src/ifxmips_atm_fw_regs_ar9.h b/package/ltq-dsl/src/ifxmips_atm_fw_regs_ar9.h
new file mode 100644
index 000000000..dd010f54f
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_fw_regs_ar9.h
@@ -0,0 +1,172 @@
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_fw_regs_ar9.h
+** PROJECT : UEIP
+** MODULES : ATM (ADSL)
+**
+** DATE : 1 AUG 2005
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM Driver (Firmware Registers)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 4 AUG 2005 Xu Liang Initiate Version
+** 23 OCT 2006 Xu Liang Add GPL header.
+** 9 JAN 2007 Xu Liang First version got from Anand (IC designer)
+*******************************************************************************/
+
+
+
+#ifndef IFXMIPS_ATM_FW_REGS_AR9_H
+#define IFXMIPS_ATM_FW_REGS_AR9_H
+
+
+
+/*
+ * Host-PPE Communication Data Address Mapping
+ */
+#define FW_VER_ID ((volatile struct fw_ver_id *) SB_BUFFER(0x2001))
+#define CFG_WRX_HTUTS SB_BUFFER(0x2400) /* WAN RX HTU Table Size, must be configured before enable PPE firmware. */
+#define CFG_WRX_QNUM SB_BUFFER(0x2401) /* WAN RX Queue Number */
+#define CFG_WRX_DCHNUM SB_BUFFER(0x2402) /* WAN RX DMA Channel Number, no more than 8, must be configured before enable PPE firmware. */
+#define CFG_WTX_DCHNUM SB_BUFFER(0x2403) /* WAN TX DMA Channel Number, no more than 16, must be configured before enable PPE firmware. */
+#define CFG_WRDES_DELAY SB_BUFFER(0x2404) /* WAN Descriptor Write Delay, must be configured before enable PPE firmware. */
+#define WRX_DMACH_ON SB_BUFFER(0x2405) /* WAN RX DMA Channel Enable, must be configured before enable PPE firmware. */
+#define WTX_DMACH_ON SB_BUFFER(0x2406) /* WAN TX DMA Channel Enable, must be configured before enable PPE firmware. */
+#define WRX_HUNT_BITTH SB_BUFFER(0x2407) /* WAN RX HUNT Threshold, must be between 2 to 8. */
+#define WRX_QUEUE_CONFIG(i) ((struct wrx_queue_config*) SB_BUFFER(0x2500 + (i) * 20))
+#define WRX_QUEUE_CONTEXT(i) ((struct wrx_queue_context*) SB_BUFFER(0x2504 + (i) * 20))
+#define WRX_DMA_CHANNEL_CONFIG(i) ((struct wrx_dma_channel_config*) SB_BUFFER(0x2640 + (i) * 7))
+#define WRX_DESC_CONTEXT(i) ((struct wrx_desc_context*) SB_BUFFER(0x2643 + (i) * 7))
+#define WTX_PORT_CONFIG(i) ((struct wtx_port_config*) SB_BUFFER(0x2440 + (i)))
+#define WTX_QUEUE_CONFIG(i) ((struct wtx_queue_config*) SB_BUFFER(0x3800 + (i) * 27))
+#define WTX_DMA_CHANNEL_CONFIG(i) ((struct wtx_dma_channel_config*) SB_BUFFER(0x3801 + (i) * 27))
+#define WAN_MIB_TABLE ((struct wan_mib_table*) SB_BUFFER(0x2410))
+#define HTU_ENTRY(i) ((struct htu_entry*) SB_BUFFER(0x2010 + (i)))
+#define HTU_MASK(i) ((struct htu_mask*) SB_BUFFER(0x2030 + (i)))
+#define HTU_RESULT(i) ((struct htu_result*) SB_BUFFER(0x2050 + (i)))
+
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+
+ #define RETX_MODE_CFG ((volatile struct Retx_mode_cfg *) SB_BUFFER(0x2408))
+ #define RETX_TSYNC_CFG ((volatile struct Retx_Tsync_cfg *) SB_BUFFER(0x2409))
+ #define RETX_TD_CFG ((volatile struct Retx_Td_cfg *) SB_BUFFER(0x240A))
+ #define RETX_MIB_TIMER_CFG ((volatile struct Retx_MIB_Timer_cfg *) SB_BUFFER(0x240B))
+ #define RETX_PLAYOUT_BUFFER_BASE SB_BUFFER(0x240D)
+ #define RETX_SERVICE_HEADER_CFG SB_BUFFER(0x240E)
+ #define RETX_MASK_HEADER_CFG SB_BUFFER(0x240F)
+
+ #define RETX_ADSL_PPE_INTF ((volatile struct Retx_adsl_ppe_intf *) PPE_REG_ADDR(0x0D78))
+ #define BAD_REC_RETX_ADSL_PPE_INTF ((volatile struct Retx_adsl_ppe_intf *) SB_BUFFER(0x23AC))
+ #define FIRST_BAD_REC_RETX_ADSL_PPE_INTF ((volatile struct Retx_adsl_ppe_intf *) SB_BUFFER(0x23AE))
+
+ #define PB_BUFFER_USAGE SB_BUFFER(0x2100)
+ #define DTU_STAT_INFO ((volatile struct DTU_stat_info *) SB_BUFFER(0x2180))
+ #define DTU_VLD_STAT SB_BUFFER(0x2380)
+
+
+ //=====================================================================
+ // retx firmware mib, for debug purpose
+ // address : 0x2388 - 0x238F
+ // size : 8
+ //=====================================================================
+ #define URETX_RX_TOTAL_DTU SB_BUFFER(0x2388)
+ #define URETX_RX_BAD_DTU SB_BUFFER(0x2389)
+ #define URETX_RX_GOOD_DTU SB_BUFFER(0x238A)
+ #define URETX_RX_CORRECTED_DTU SB_BUFFER(0x238B)
+ #define URETX_RX_OUTOFDATE_DTU SB_BUFFER(0x238C)
+ #define URETX_RX_DUPLICATE_DTU SB_BUFFER(0x238D)
+ #define URETX_RX_TIMEOUT_DTU SB_BUFFER(0x238E)
+
+ #define URETX_ALPHA_SWITCH_TO_HUNT_TIMES SB_BUFFER(0x238F)
+
+ // cell counter for debug purpose
+ #define WRX_BC0_CELL_NUM SB_BUFFER(0x23E0)
+ #define WRX_BC0_DROP_CELL_NUM SB_BUFFER(0x23E1)
+ #define WRX_BC0_NONRETX_CELL_NUM SB_BUFFER(0x23E2)
+ #define WRX_BC0_RETX_CELL_NUM SB_BUFFER(0x23E3)
+ #define WRX_BC0_OUTOFDATE_CELL_NUM SB_BUFFER(0x23E4)
+ #define WRX_BC0_DIRECTUP_NUM SB_BUFFER(0x23E5)
+ #define WRX_BC0_PBW_TOTAL_NUM SB_BUFFER(0x23E6)
+ #define WRX_BC0_PBW_SUCC_NUM SB_BUFFER(0x23E7)
+ #define WRX_BC0_PBW_FAIL_NUM SB_BUFFER(0x23E8)
+ #define WRX_BC1_CELL_NUM SB_BUFFER(0x23E9)
+
+ // debug info (interface)
+
+ #define DBG_DTU_INTF_WRPTR SB_BUFFER(0x2390)
+ #define DBG_INTF_FCW_DUP_CNT SB_BUFFER(0x2391)
+ #define DBG_INTF_SID_CHANGE_IN_DTU_CNT SB_BUFFER(0x2392)
+ #define DBG_INTF_LCW_DUP_CNT SB_BUFFER(0x2393)
+
+ #define DBG_RFBI_DONE_INT_CNT SB_BUFFER(0x2394)
+ #define DBG_DREG_BEG_END SB_BUFFER(0x2395)
+ #define DBG_RFBI_BC0_INVALID_CNT SB_BUFFER(0x2396)
+ #define DBG_RFBI_LAST_T SB_BUFFER(0x2397)
+
+ #define DBG_RFBI_INTV0 SB_BUFFER(0x23EE)
+ #define DBG_RFBI_INTV1 SB_BUFFER(0x23EF)
+
+ #define DBG_INTF_INFO(i) ((volatile struct Retx_adsl_ppe_intf_rec *) SB_BUFFER(0x23F0 + i))
+
+ // Internal status
+ #define URetx_curr_time SB_BUFFER(0x2398)
+ #define URetx_sec_counter SB_BUFFER(0x2399)
+ #define RxCURR_EFB SB_BUFFER(0x239A)
+ #define RxDTURetransmittedCNT SB_BUFFER(0x239B)
+
+ //=====================================================================
+ // standardized MIB counter
+ // address : 0x239C - 0x239F
+ // size : 4
+ //=====================================================================
+ #define RxLastEFBCNT SB_BUFFER(0x239C)
+ #define RxDTUCorrectedCNT SB_BUFFER(0x239D)
+ #define RxDTUCorruptedCNT SB_BUFFER(0x239E)
+ #define RxRetxDTUUncorrectedCNT SB_BUFFER(0x239F)
+
+
+ //=====================================================================
+ // General URetx Context
+ // address : 0x23A0 - 0x23AF
+ // size : 16
+ //=====================================================================
+ #define NEXT_DTU_SID_OUT SB_BUFFER(0x23A0)
+ #define LAST_DTU_SID_IN SB_BUFFER(0x23A1)
+ #define NEXT_CELL_SID_OUT SB_BUFFER(0x23A2)
+ #define ISR_CELL_ID SB_BUFFER(0x23A3)
+ #define PB_CELL_SEARCH_IDX SB_BUFFER(0x23A4)
+ #define PB_READ_PEND_FLAG SB_BUFFER(0x23A5)
+ #define RFBI_FIRST_CW SB_BUFFER(0x23A6)
+ #define RFBI_BAD_CW SB_BUFFER(0x23A7)
+ #define RFBI_INVALID_CW SB_BUFFER(0x23A8)
+ #define RFBI_RETX_CW SB_BUFFER(0x23A9)
+ #define RFBI_CHK_DTU_STATUS SB_BUFFER(0x23AA)
+
+ //=====================================================================
+ // per PVC counter for RX error_pdu and correct_pdu
+ // address : 0x23B0 - 0x23CF
+ // size : 32
+ //=====================================================================
+ #define WRX_PER_PVC_CORRECT_PDU_BASE SB_BUFFER(0x23B0)
+ #define WRX_PER_PVC_ERROR_PDU_BASE SB_BUFFER(0x23C0)
+
+ #define __WRXCTXT_L2_RdPtr(i) SB_BUFFER(0x2422 + (i))
+ #define __WRXCTXT_L2Pages(i) SB_BUFFER(0x2424 + (i))
+
+ #define __WTXCTXT_TC_WRPTR(i) SB_BUFFER(0x2450 + (i))
+ #define __WRXCTXT_PortState(i) SB_BUFFER(0x242A + (i))
+
+#endif
+
+
+
+#endif // IFXMIPS_ATM_FW_REGS_AR9_H
diff --git a/package/ltq-dsl/src/ifxmips_atm_fw_regs_common.h b/package/ltq-dsl/src/ifxmips_atm_fw_regs_common.h
new file mode 100644
index 000000000..432969b93
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_fw_regs_common.h
@@ -0,0 +1,546 @@
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_fw_regs_common.h
+** PROJECT : UEIP
+** MODULES : ATM (ADSL)
+**
+** DATE : 1 AUG 2005
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM Driver (Firmware Register Structures)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 4 AUG 2005 Xu Liang Initiate Version
+** 23 OCT 2006 Xu Liang Add GPL header.
+** 9 JAN 2007 Xu Liang First version got from Anand (IC designer)
+*******************************************************************************/
+
+
+
+#ifndef IFXMIPS_ATM_FW_REGS_COMMON_H
+#define IFXMIPS_ATM_FW_REGS_COMMON_H
+
+
+
+#if defined(CONFIG_DANUBE)
+ #include "ifxmips_atm_fw_regs_danube.h"
+#elif defined(CONFIG_AMAZON_SE)
+ #include "ifxmips_atm_fw_regs_amazon_se.h"
+#elif defined(CONFIG_AR9)
+ #include "ifxmips_atm_fw_regs_ar9.h"
+#elif defined(CONFIG_VR9)
+ #include "ifxmips_atm_fw_regs_vr9.h"
+#else
+ #error Platform is not specified!
+#endif
+
+
+
+/*
+ * PPE ATM Cell Header
+ */
+#if defined(__BIG_ENDIAN)
+ struct uni_cell_header {
+ unsigned int gfc :4;
+ unsigned int vpi :8;
+ unsigned int vci :16;
+ unsigned int pti :3;
+ unsigned int clp :1;
+ };
+#else
+ struct uni_cell_header {
+ unsigned int clp :1;
+ unsigned int pti :3;
+ unsigned int vci :16;
+ unsigned int vpi :8;
+ unsigned int gfc :4;
+ };
+#endif // defined(__BIG_ENDIAN)
+
+/*
+ * Inband Header and Trailer
+ */
+#if defined(__BIG_ENDIAN)
+ struct rx_inband_trailer {
+ /* 0 - 3h */
+ unsigned int uu :8;
+ unsigned int cpi :8;
+ unsigned int stw_res1:4;
+ unsigned int stw_clp :1;
+ unsigned int stw_ec :1;
+ unsigned int stw_uu :1;
+ unsigned int stw_cpi :1;
+ unsigned int stw_ovz :1;
+ unsigned int stw_mfl :1;
+ unsigned int stw_usz :1;
+ unsigned int stw_crc :1;
+ unsigned int stw_il :1;
+ unsigned int stw_ra :1;
+ unsigned int stw_res2:2;
+ /* 4 - 7h */
+ unsigned int gfc :4;
+ unsigned int vpi :8;
+ unsigned int vci :16;
+ unsigned int pti :3;
+ unsigned int clp :1;
+ };
+
+ struct tx_inband_header {
+ /* 0 - 3h */
+ unsigned int gfc :4;
+ unsigned int vpi :8;
+ unsigned int vci :16;
+ unsigned int pti :3;
+ unsigned int clp :1;
+ /* 4 - 7h */
+ unsigned int uu :8;
+ unsigned int cpi :8;
+ unsigned int pad :8;
+ unsigned int res1 :8;
+ };
+#else
+ struct rx_inband_trailer {
+ /* 0 - 3h */
+ unsigned int stw_res2:2;
+ unsigned int stw_ra :1;
+ unsigned int stw_il :1;
+ unsigned int stw_crc :1;
+ unsigned int stw_usz :1;
+ unsigned int stw_mfl :1;
+ unsigned int stw_ovz :1;
+ unsigned int stw_cpi :1;
+ unsigned int stw_uu :1;
+ unsigned int stw_ec :1;
+ unsigned int stw_clp :1;
+ unsigned int stw_res1:4;
+ unsigned int cpi :8;
+ unsigned int uu :8;
+ /* 4 - 7h */
+ unsigned int clp :1;
+ unsigned int pti :3;
+ unsigned int vci :16;
+ unsigned int vpi :8;
+ unsigned int gfc :4;
+ };
+
+ struct tx_inband_header {
+ /* 0 - 3h */
+ unsigned int clp :1;
+ unsigned int pti :3;
+ unsigned int vci :16;
+ unsigned int vpi :8;
+ unsigned int gfc :4;
+ /* 4 - 7h */
+ unsigned int res1 :8;
+ unsigned int pad :8;
+ unsigned int cpi :8;
+ unsigned int uu :8;
+ };
+#endif // defined(__BIG_ENDIAN)
+
+/*
+ * MIB Table Maintained by Firmware
+ */
+struct wan_mib_table {
+ u32 res1;
+ u32 wrx_drophtu_cell;
+ u32 wrx_dropdes_pdu;
+ u32 wrx_correct_pdu;
+ u32 wrx_err_pdu;
+ u32 wrx_dropdes_cell;
+ u32 wrx_correct_cell;
+ u32 wrx_err_cell;
+ u32 wrx_total_byte;
+ u32 res2;
+ u32 wtx_total_pdu;
+ u32 wtx_total_cell;
+ u32 wtx_total_byte;
+};
+
+/*
+ * Host-PPE Communication Data Structure
+ */
+
+#if defined(__BIG_ENDIAN)
+ struct fw_ver_id {
+ unsigned int family :4;
+ unsigned int fwtype :4;
+ unsigned int interface :4;
+ unsigned int fwmode :4;
+ unsigned int major :8;
+ unsigned int minor :8;
+ };
+
+ struct wrx_queue_config {
+ /* 0h */
+ unsigned int res2 :27;
+ unsigned int dmach :4;
+ unsigned int errdp :1;
+ /* 1h */
+ unsigned int oversize :16;
+ unsigned int undersize :16;
+ /* 2h */
+ unsigned int res1 :16;
+ unsigned int mfs :16;
+ /* 3h */
+ unsigned int uumask :8;
+ unsigned int cpimask :8;
+ unsigned int uuexp :8;
+ unsigned int cpiexp :8;
+ };
+
+ struct wrx_queue_context {
+ /* 0h */
+ unsigned int curr_len :16;
+ unsigned int res0 :12;
+ unsigned int mfs :1;
+ unsigned int ec :1;
+ unsigned int clp1 :1;
+ unsigned int aal5dp :1;
+
+ /* 1h */
+ unsigned int intcrc;
+
+ /* 2h, 3h */
+ unsigned int curr_des0;
+ unsigned int curr_des1;
+
+ /* 4h - 0xE */
+ unsigned int res1[11];
+
+ unsigned int last_dword;
+ };
+
+ struct wtx_port_config {
+ unsigned int res1 :27;
+ unsigned int qid :4;
+ unsigned int qsben :1;
+ };
+
+ struct wtx_queue_config {
+ unsigned int res1 :25;
+ unsigned int sbid :1;
+ unsigned int qsb_vcid :4; // Which QSB queue (VCID) does this TX queue map to.
+ unsigned int res2 :1;
+ unsigned int qsben :1;
+ };
+
+ struct wrx_desc_context {
+ unsigned int dmach_wrptr : 16;
+ unsigned int dmach_rdptr : 16;
+
+ unsigned int res0 : 16;
+ unsigned int dmach_fcnt : 16;
+
+ unsigned int res1 : 11;
+ unsigned int desbuf_wrptr : 5;
+ unsigned int res2 : 11;
+ unsigned int desbuf_rdptr : 5;
+
+ unsigned int res3 : 27;
+ unsigned int desbuf_vcnt : 5;
+ };
+
+ struct wrx_dma_channel_config {
+ /* 0h */
+ unsigned int res1 :1;
+ unsigned int mode :2;
+ unsigned int rlcfg :1;
+ unsigned int desba :28;
+ /* 1h */
+ unsigned int chrl :16;
+ unsigned int clp1th :16;
+ /* 2h */
+ unsigned int deslen :16;
+ unsigned int vlddes :16;
+ };
+
+ struct wtx_dma_channel_config {
+ /* 0h */
+ unsigned int res2 :1;
+ unsigned int mode :2;
+ unsigned int res3 :1;
+ unsigned int desba :28;
+ /* 1h */
+ unsigned int res1 :32;
+ /* 2h */
+ unsigned int deslen :16;
+ unsigned int vlddes :16;
+ };
+
+ struct htu_entry {
+ unsigned int res1 :1;
+ unsigned int clp :1;
+ unsigned int pid :2;
+ unsigned int vpi :8;
+ unsigned int vci :16;
+ unsigned int pti :3;
+ unsigned int vld :1;
+ };
+
+ struct htu_mask {
+ unsigned int set :1;
+ unsigned int clp :1;
+ unsigned int pid_mask :2;
+ unsigned int vpi_mask :8;
+ unsigned int vci_mask :16;
+ unsigned int pti_mask :3;
+ unsigned int clear :1;
+ };
+
+ struct htu_result {
+ unsigned int res1 :12;
+ unsigned int cellid :4;
+ unsigned int res2 :5;
+ unsigned int type :1;
+ unsigned int ven :1;
+ unsigned int res3 :5;
+ unsigned int qid :4;
+ };
+
+ struct rx_descriptor {
+ /* 0 - 3h */
+ unsigned int own :1;
+ unsigned int c :1;
+ unsigned int sop :1;
+ unsigned int eop :1;
+ unsigned int res1 :3;
+ unsigned int byteoff :2;
+ unsigned int res2 :2;
+ unsigned int id :4;
+ unsigned int err :1;
+ unsigned int datalen :16;
+ /* 4 - 7h */
+ unsigned int res3 :4;
+ unsigned int dataptr :28;
+ };
+
+ struct tx_descriptor {
+ /* 0 - 3h */
+ unsigned int own :1;
+ unsigned int c :1;
+ unsigned int sop :1;
+ unsigned int eop :1;
+ unsigned int byteoff :5;
+ unsigned int res1 :5;
+ unsigned int iscell :1;
+ unsigned int clp :1;
+ unsigned int datalen :16;
+ /* 4 - 7h */
+ unsigned int res2 :4;
+ unsigned int dataptr :28;
+ };
+#else
+ struct wrx_queue_config {
+ /* 0h */
+ unsigned int errdp :1;
+ unsigned int dmach :4;
+ unsigned int res2 :27;
+ /* 1h */
+ unsigned int undersize :16;
+ unsigned int oversize :16;
+ /* 2h */
+ unsigned int mfs :16;
+ unsigned int res1 :16;
+ /* 3h */
+ unsigned int cpiexp :8;
+ unsigned int uuexp :8;
+ unsigned int cpimask :8;
+ unsigned int uumask :8;
+ };
+
+ struct wtx_port_config {
+ unsigned int qsben :1;
+ unsigned int qid :4;
+ unsigned int res1 :27;
+ };
+
+ struct wtx_queue_config {
+ unsigned int qsben :1;
+ unsigned int res2 :1;
+ unsigned int qsb_vcid :4; // Which QSB queue (VCID) does this TX queue map to.
+ unsigned int sbid :1;
+ unsigned int res1 :25;
+ };
+
+ struct wrx_dma_channel_config
+ {
+ /* 0h */
+ unsigned int desba :28;
+ unsigned int rlcfg :1;
+ unsigned int mode :2;
+ unsigned int res1 :1;
+ /* 1h */
+ unsigned int clp1th :16;
+ unsigned int chrl :16;
+ /* 2h */
+ unsigned int vlddes :16;
+ unsigned int deslen :16;
+ };
+
+ struct wtx_dma_channel_config {
+ /* 0h */
+ unsigned int desba :28;
+ unsigned int res3 :1;
+ unsigned int mode :2;
+ unsigned int res2 :1;
+ /* 1h */
+ unsigned int res1 :32;
+ /* 2h */
+ unsigned int vlddes :16;
+ unsigned int deslen :16;
+ };
+
+ struct rx_descriptor {
+ /* 4 - 7h */
+ unsigned int dataptr :28;
+ unsigned int res3 :4;
+ /* 0 - 3h */
+ unsigned int datalen :16;
+ unsigned int err :1;
+ unsigned int id :4;
+ unsigned int res2 :2;
+ unsigned int byteoff :2;
+ unsigned int res1 :3;
+ unsigned int eop :1;
+ unsigned int sop :1;
+ unsigned int c :1;
+ unsigned int own :1;
+ };
+
+ struct tx_descriptor {
+ /* 4 - 7h */
+ unsigned int dataptr :28;
+ unsigned int res2 :4;
+ /* 0 - 3h */
+ unsigned int datalen :16;
+ unsigned int clp :1;
+ unsigned int iscell :1;
+ unsigned int res1 :5;
+ unsigned int byteoff :5;
+ unsigned int eop :1;
+ unsigned int sop :1;
+ unsigned int c :1;
+ unsigned int own :1;
+ };
+#endif // defined(__BIG_ENDIAN)
+
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+ #if defined(__BIG_ENDIAN)
+
+ struct Retx_adsl_ppe_intf {
+ unsigned int res0_0 : 16;
+ unsigned int dtu_sid : 8;
+ unsigned int dtu_timestamp : 8;
+
+ unsigned int res1_0 : 16;
+ unsigned int local_time : 8;
+ unsigned int res1_1 : 5;
+ unsigned int is_last_cw : 1;
+ unsigned int reinit_flag : 1;
+ unsigned int is_bad_cw : 1;
+ };
+
+ struct Retx_adsl_ppe_intf_rec {
+
+ unsigned int local_time : 8;
+ unsigned int res1_1 : 5;
+ unsigned int is_last_cw : 1;
+ unsigned int reinit_flag : 1;
+ unsigned int is_bad_cw : 1;
+
+ unsigned int dtu_sid : 8;
+ unsigned int dtu_timestamp : 8;
+
+ };
+
+ struct Retx_mode_cfg {
+ unsigned int res0 :8;
+ unsigned int invld_range :8; // used for rejecting the too late arrival of the retransmitted DTU
+ unsigned int buff_size :8; // the total number of cells in playout buffer is 32 * buff_size
+ unsigned int res1 :7;
+ unsigned int retx_en :1;
+ };
+
+ struct Retx_Tsync_cfg {
+ unsigned int fw_alpha :16; // number of consecutive HEC error cell causes that the cell delineation state machine transit from SYNC to HUNT (0 means never)
+ unsigned int sync_inp :16; // reserved
+ };
+
+ struct Retx_Td_cfg {
+ unsigned int res0 :8;
+ unsigned int td_max :8; // maximum delay between the time a DTU is first created at transmitter and the time the DTU is sent out of ReTX layer at receiver
+ unsigned int res1 :8;
+ unsigned int td_min :8; // minimum delay between the time a DTU is first created at transmitter and the time the DTU is sent out of ReTX layer at receiver
+ };
+
+ struct Retx_MIB_Timer_cfg {
+ unsigned int ticks_per_sec : 16;
+ unsigned int tick_cycle : 16;
+ };
+
+ struct DTU_stat_info {
+ unsigned int complete : 1;
+ unsigned int bad : 1;
+ unsigned int res0_0 : 14;
+ unsigned int time_stamp : 8;
+ unsigned int cell_cnt : 8;
+
+ unsigned int dtu_rd_ptr : 16;
+ unsigned int dtu_wr_ptr : 16;
+ };
+
+ struct Retx_ctrl_field {
+ unsigned int res0 : 1;
+
+ unsigned int l2_drop : 1;
+ unsigned int res1 : 13;
+ unsigned int retx : 1;
+
+ unsigned int dtu_sid : 8;
+ unsigned int cell_sid : 8;
+ };
+
+ #else
+ #error Little Endian is not supported yet.
+ #endif
+
+ struct dsl_param {
+ unsigned int update_flag; // 00
+ unsigned int res0; // 04
+ unsigned int MinDelayrt; // 08
+ unsigned int MaxDelayrt; // 0C
+ unsigned int res1; // 10
+ unsigned int res2; // 14
+ unsigned int RetxEnable; // 18
+ unsigned int ServiceSpecificReTx; // 1C
+ unsigned int res3; // 20
+ unsigned int ReTxPVC; // 24
+ unsigned int res4; // 28
+ unsigned int res5; // 2C
+ unsigned int res6; // 30
+ unsigned int res7; // 34
+ unsigned int res8; // 38
+ unsigned int res9; // 3C
+ unsigned int res10; // 40
+ unsigned int res11; // 44
+ unsigned int res12; // 48
+ unsigned int res13; // 4C
+ unsigned int RxDtuCorruptedCNT; // 50
+ unsigned int RxRetxDtuUnCorrectedCNT;// 54
+ unsigned int RxLastEFB; // 58
+ unsigned int RxDtuCorrectedCNT; // 5C
+ };
+#endif
+
+
+
+#endif // IFXMIPS_ATM_FW_REGS_COMMON_H
diff --git a/package/ltq-dsl/src/ifxmips_atm_fw_regs_danube.h b/package/ltq-dsl/src/ifxmips_atm_fw_regs_danube.h
new file mode 100644
index 000000000..5239fce8c
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_fw_regs_danube.h
@@ -0,0 +1,178 @@
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_fw_regs_danube.h
+** PROJECT : UEIP
+** MODULES : ATM (ADSL)
+**
+** DATE : 1 AUG 2005
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM Driver (Firmware Registers)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 4 AUG 2005 Xu Liang Initiate Version
+** 23 OCT 2006 Xu Liang Add GPL header.
+** 9 JAN 2007 Xu Liang First version got from Anand (IC designer)
+*******************************************************************************/
+
+
+
+#ifndef IFXMIPS_ATM_FW_REGS_DANUBE_H
+#define IFXMIPS_ATM_FW_REGS_DANUBE_H
+
+
+
+/*
+ * Host-PPE Communication Data Address Mapping
+ */
+#define FW_VER_ID ((volatile struct fw_ver_id *) SB_BUFFER(0x2001))
+#define CFG_WRX_HTUTS SB_BUFFER(0x2400) /* WAN RX HTU Table Size, must be configured before enable PPE firmware. */
+#define CFG_WRX_QNUM SB_BUFFER(0x2401) /* WAN RX Queue Number */
+#define CFG_WRX_DCHNUM SB_BUFFER(0x2402) /* WAN RX DMA Channel Number, no more than 8, must be configured before enable PPE firmware. */
+#define CFG_WTX_DCHNUM SB_BUFFER(0x2403) /* WAN TX DMA Channel Number, no more than 16, must be configured before enable PPE firmware. */
+#define CFG_WRDES_DELAY SB_BUFFER(0x2404) /* WAN Descriptor Write Delay, must be configured before enable PPE firmware. */
+#define WRX_DMACH_ON SB_BUFFER(0x2405) /* WAN RX DMA Channel Enable, must be configured before enable PPE firmware. */
+#define WTX_DMACH_ON SB_BUFFER(0x2406) /* WAN TX DMA Channel Enable, must be configured before enable PPE firmware. */
+#define WRX_HUNT_BITTH SB_BUFFER(0x2407) /* WAN RX HUNT Threshold, must be between 2 to 8. */
+#define WRX_QUEUE_CONFIG(i) ((struct wrx_queue_config*) SB_BUFFER(0x2500 + (i) * 20))
+#define WRX_QUEUE_CONTEXT(i) ((struct wrx_queue_context*) SB_BUFFER(0x2504 + (i) * 20))
+#define WRX_DMA_CHANNEL_CONFIG(i) ((struct wrx_dma_channel_config*) SB_BUFFER(0x2640 + (i) * 7))
+#define WRX_DESC_CONTEXT(i) ((struct wrx_desc_context*) SB_BUFFER(0x2643 + (i) * 7))
+#define WTX_PORT_CONFIG(i) ((struct wtx_port_config*) SB_BUFFER(0x2440 + (i)))
+#define WTX_QUEUE_CONFIG(i) ((struct wtx_queue_config*) SB_BUFFER(0x2710 + (i) * 27))
+#define WTX_DMA_CHANNEL_CONFIG(i) ((struct wtx_dma_channel_config*) SB_BUFFER(0x2711 + (i) * 27))
+#define WAN_MIB_TABLE ((struct wan_mib_table*) SB_BUFFER(0x2410))
+#if !defined(ENABLE_ATM_RETX) || !ENABLE_ATM_RETX
+ #define HTU_ENTRY(i) ((struct htu_entry*) SB_BUFFER(0x2000 + (i)))
+ #define HTU_MASK(i) ((struct htu_mask*) SB_BUFFER(0x2020 + (i)))
+ #define HTU_RESULT(i) ((struct htu_result*) SB_BUFFER(0x2040 + (i)))
+#else
+ #define HTU_ENTRY(i) ((struct htu_entry*) SB_BUFFER(0x2020 + (i)))
+ #define HTU_MASK(i) ((struct htu_mask*) SB_BUFFER(0x2040 + (i)))
+ #define HTU_RESULT(i) ((struct htu_result*) SB_BUFFER(0x2060 + (i)))
+#endif
+
+#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
+
+ #define RETX_MODE_CFG ((volatile struct Retx_mode_cfg *) SB_BUFFER(0x2408))
+ #define RETX_TSYNC_CFG ((volatile struct Retx_Tsync_cfg *) SB_BUFFER(0x2409))
+ #define RETX_TD_CFG ((volatile struct Retx_Td_cfg *) SB_BUFFER(0x240A))
+ #define RETX_MIB_TIMER_CFG ((volatile struct Retx_MIB_Timer_cfg *) SB_BUFFER(0x240B))
+ #define RETX_PLAYOUT_BUFFER_BASE SB_BUFFER(0x240D)
+ #define RETX_SERVICE_HEADER_CFG SB_BUFFER(0x240E)
+ #define RETX_MASK_HEADER_CFG SB_BUFFER(0x240F)
+
+ #define RETX_ADSL_PPE_INTF ((volatile struct Retx_adsl_ppe_intf *) PPE_REG_ADDR(0x0D78))
+ #define BAD_REC_RETX_ADSL_PPE_INTF ((volatile struct Retx_adsl_ppe_intf *) SB_BUFFER(0x23AC))
+ #define FIRST_BAD_REC_RETX_ADSL_PPE_INTF ((volatile struct Retx_adsl_ppe_intf *) SB_BUFFER(0x23AE))
+
+ #define PB_BUFFER_USAGE SB_BUFFER(0x2100)
+ #define DTU_STAT_INFO ((volatile struct DTU_stat_info *) SB_BUFFER(0x2180))
+ #define DTU_VLD_STAT SB_BUFFER(0x2380)
+
+
+ //=====================================================================
+ // retx firmware mib, for debug purpose
+ // address : 0x2388 - 0x238F
+ // size : 8
+ //=====================================================================
+ #define URETX_RX_TOTAL_DTU SB_BUFFER(0x2388)
+ #define URETX_RX_BAD_DTU SB_BUFFER(0x2389)
+ #define URETX_RX_GOOD_DTU SB_BUFFER(0x238A)
+ #define URETX_RX_CORRECTED_DTU SB_BUFFER(0x238B)
+ #define URETX_RX_OUTOFDATE_DTU SB_BUFFER(0x238C)
+ #define URETX_RX_DUPLICATE_DTU SB_BUFFER(0x238D)
+ #define URETX_RX_TIMEOUT_DTU SB_BUFFER(0x238E)
+
+ #define URETX_ALPHA_SWITCH_TO_HUNT_TIMES SB_BUFFER(0x238F)
+
+ // cell counter for debug purpose
+ #define WRX_BC0_CELL_NUM SB_BUFFER(0x23E0)
+ #define WRX_BC0_DROP_CELL_NUM SB_BUFFER(0x23E1)
+ #define WRX_BC0_NONRETX_CELL_NUM SB_BUFFER(0x23E2)
+ #define WRX_BC0_RETX_CELL_NUM SB_BUFFER(0x23E3)
+ #define WRX_BC0_OUTOFDATE_CELL_NUM SB_BUFFER(0x23E4)
+ #define WRX_BC0_DIRECTUP_NUM SB_BUFFER(0x23E5)
+ #define WRX_BC0_PBW_TOTAL_NUM SB_BUFFER(0x23E6)
+ #define WRX_BC0_PBW_SUCC_NUM SB_BUFFER(0x23E7)
+ #define WRX_BC0_PBW_FAIL_NUM SB_BUFFER(0x23E8)
+ #define WRX_BC1_CELL_NUM SB_BUFFER(0x23E9)
+
+ // debug info (interface)
+
+ #define DBG_DTU_INTF_WRPTR SB_BUFFER(0x2390)
+ #define DBG_INTF_FCW_DUP_CNT SB_BUFFER(0x2391)
+ #define DBG_INTF_SID_CHANGE_IN_DTU_CNT SB_BUFFER(0x2392)
+ #define DBG_INTF_LCW_DUP_CNT SB_BUFFER(0x2393)
+
+ #define DBG_RFBI_DONE_INT_CNT SB_BUFFER(0x2394)
+ #define DBG_DREG_BEG_END SB_BUFFER(0x2395)
+ #define DBG_RFBI_BC0_INVALID_CNT SB_BUFFER(0x2396)
+ #define DBG_RFBI_LAST_T SB_BUFFER(0x2397)
+
+ #define DBG_RFBI_INTV0 SB_BUFFER(0x23EE)
+ #define DBG_RFBI_INTV1 SB_BUFFER(0x23EF)
+
+ #define DBG_INTF_INFO(i) ((volatile struct Retx_adsl_ppe_intf_rec *) SB_BUFFER(0x23F0 + i))
+
+ // Internal status
+ #define URetx_curr_time SB_BUFFER(0x2398)
+ #define URetx_sec_counter SB_BUFFER(0x2399)
+ #define RxCURR_EFB SB_BUFFER(0x239A)
+ #define RxDTURetransmittedCNT SB_BUFFER(0x239B)
+
+ //=====================================================================
+ // standardized MIB counter
+ // address : 0x239C - 0x239F
+ // size : 4
+ //=====================================================================
+ #define RxLastEFBCNT SB_BUFFER(0x239C)
+ #define RxDTUCorrectedCNT SB_BUFFER(0x239D)
+ #define RxDTUCorruptedCNT SB_BUFFER(0x239E)
+ #define RxRetxDTUUncorrectedCNT SB_BUFFER(0x239F)
+
+
+ //=====================================================================
+ // General URetx Context
+ // address : 0x23A0 - 0x23AF
+ // size : 16
+ //=====================================================================
+ #define NEXT_DTU_SID_OUT SB_BUFFER(0x23A0)
+ #define LAST_DTU_SID_IN SB_BUFFER(0x23A1)
+ #define NEXT_CELL_SID_OUT SB_BUFFER(0x23A2)
+ #define ISR_CELL_ID SB_BUFFER(0x23A3)
+ #define PB_CELL_SEARCH_IDX SB_BUFFER(0x23A4)
+ #define PB_READ_PEND_FLAG SB_BUFFER(0x23A5)
+ #define RFBI_FIRST_CW SB_BUFFER(0x23A6)
+ #define RFBI_BAD_CW SB_BUFFER(0x23A7)
+ #define RFBI_INVALID_CW SB_BUFFER(0x23A8)
+ #define RFBI_RETX_CW SB_BUFFER(0x23A9)
+ #define RFBI_CHK_DTU_STATUS SB_BUFFER(0x23AA)
+
+ //=====================================================================
+ // per PVC counter for RX error_pdu and correct_pdu
+ // address : 0x23B0 - 0x23CF
+ // size : 32
+ //=====================================================================
+ #define WRX_PER_PVC_CORRECT_PDU_BASE SB_BUFFER(0x23B0)
+ #define WRX_PER_PVC_ERROR_PDU_BASE SB_BUFFER(0x23C0)
+
+ #define __WRXCTXT_L2_RdPtr(i) SB_BUFFER(0x2422 + (i))
+ #define __WRXCTXT_L2Pages(i) SB_BUFFER(0x2424 + (i))
+
+ #define __WTXCTXT_TC_WRPTR(i) SB_BUFFER(0x2450 + (i))
+ #define __WRXCTXT_PortState(i) SB_BUFFER(0x242A + (i))
+
+#endif
+
+
+
+#endif // IFXMIPS_ATM_FW_REGS_DANUBE_H
diff --git a/package/ltq-dsl/src/ifxmips_atm_fw_regs_vr9.h b/package/ltq-dsl/src/ifxmips_atm_fw_regs_vr9.h
new file mode 100644
index 000000000..edefe92d2
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_fw_regs_vr9.h
@@ -0,0 +1,59 @@
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_fw_regs_vr9.h
+** PROJECT : UEIP
+** MODULES : ATM (ADSL)
+**
+** DATE : 1 AUG 2005
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM Driver (Firmware Registers)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 4 AUG 2005 Xu Liang Initiate Version
+** 23 OCT 2006 Xu Liang Add GPL header.
+** 9 JAN 2007 Xu Liang First version got from Anand (IC designer)
+*******************************************************************************/
+
+
+
+#ifndef IFXMIPS_ATM_FW_REGS_VR9_H
+#define IFXMIPS_ATM_FW_REGS_VR9_H
+
+
+
+/*
+ * Host-PPE Communication Data Address Mapping
+ */
+#define FW_VER_ID ((volatile struct fw_ver_id *) SB_BUFFER(0x2001))
+#define CFG_WRX_HTUTS SB_BUFFER(0x2010) /* WAN RX HTU Table Size, must be configured before enable PPE firmware. */
+#define CFG_WRX_QNUM SB_BUFFER(0x2011) /* WAN RX Queue Number */
+#define CFG_WRX_DCHNUM SB_BUFFER(0x2012) /* WAN RX DMA Channel Number, no more than 8, must be configured before enable PPE firmware. */
+#define CFG_WTX_DCHNUM SB_BUFFER(0x2013) /* WAN TX DMA Channel Number, no more than 16, must be configured before enable PPE firmware. */
+#define CFG_WRDES_DELAY SB_BUFFER(0x2014) /* WAN Descriptor Write Delay, must be configured before enable PPE firmware. */
+#define WRX_DMACH_ON SB_BUFFER(0x2015) /* WAN RX DMA Channel Enable, must be configured before enable PPE firmware. */
+#define WTX_DMACH_ON SB_BUFFER(0x2016) /* WAN TX DMA Channel Enable, must be configured before enable PPE firmware. */
+#define WRX_HUNT_BITTH SB_BUFFER(0x2017) /* WAN RX HUNT Threshold, must be between 2 to 8. */
+#define WRX_QUEUE_CONFIG(i) ((struct wrx_queue_config*) SB_BUFFER(0x4C00 + (i) * 20)) /* i < 16 */
+#define WRX_DMA_CHANNEL_CONFIG(i) ((struct wrx_dma_channel_config*) SB_BUFFER(0x4F80 + (i) * 7)) /* i < 8 */
+#define WTX_PORT_CONFIG(i) ((struct wtx_port_config*) SB_BUFFER(0x4FB8 + (i))) /* i < 2 */
+#define WTX_QUEUE_CONFIG(i) ((struct wtx_queue_config*) SB_BUFFER(0x3A00 + (i) * 27)) /* i < 16 */
+#define WTX_DMA_CHANNEL_CONFIG(i) ((struct wtx_dma_channel_config*) SB_BUFFER(0x3A01 + (i) * 27)) /* i < 16 */
+#define WAN_MIB_TABLE ((struct wan_mib_table*) SB_BUFFER(0x4EF0))
+#define HTU_ENTRY(i) ((struct htu_entry*) SB_BUFFER(0x26A0 + (i))) /* i < 32 */
+#define HTU_MASK(i) ((struct htu_mask*) SB_BUFFER(0x26C0 + (i))) /* i < 32 */
+#define HTU_RESULT(i) ((struct htu_result*) SB_BUFFER(0x26E0 + (i))) /* i < 32 */
+
+#define UTP_CFG SB_BUFFER(0x2018) // bit 0~3 - 0x0F: in showtime, 0x00: not in showtime
+
+
+
+#endif // IFXMIPS_ATM_FW_REGS_VR9_H
diff --git a/package/ltq-dsl/src/ifxmips_atm_fw_vr9.h b/package/ltq-dsl/src/ifxmips_atm_fw_vr9.h
new file mode 100644
index 000000000..5627a5099
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_fw_vr9.h
@@ -0,0 +1,427 @@
+#ifndef IFXMIPS_ATM_FW_VR9_H
+#define IFXMIPS_ATM_FW_VR9_H
+
+
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_fw_vr9.h
+** PROJECT : UEIP
+** MODULES : ATM (ADSL)
+**
+** DATE : 22 OCT 2007
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM Driver (PP32 Firmware)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 22 OCT 2007 Xu Liang Initial Version, v00.01
+*******************************************************************************/
+
+
+#define VER_IN_FIRMWARE 1
+
+#define ATM_FW_VER_MAJOR 0
+#define ATM_FW_VER_MINOR 24
+
+
+static u32 firmware_binary_code[] = {
+ 0x800004B8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000FFE0, 0x00000000, 0x00000000, 0x00000000,
+ 0xC1000002, 0xD90C00F8, 0xC2000002, 0xDA0800F9, 0x80004390, 0xC2000000, 0xDA0800F9, 0x80003A10,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x800039C8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x80004B60, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x800038C8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0400000, 0xC000ABC0, 0xC88400F8, 0x80004050, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0400002, 0xC000ABC0, 0xC88400F8, 0x80003FD0, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC3C00004, 0xDBC800F9, 0xC10C0002, 0xD90C00F8, 0x8000FEE0, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC10E0002, 0xD90C00F8, 0xC0004028, 0xC84000F8, 0x80004000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC3E1FFFE, 0x597DFFFE, 0x593DFE14, 0x900004D9, 0x00000000, 0x00000000, 0x00000000, 0x90CC0481,
+ 0x00000000, 0x00000000, 0x00000000, 0xC3C00000, 0xDBC800F9, 0xC1400008, 0xC1900000, 0x71588000,
+ 0x14100100, 0xC140000A, 0xC1900002, 0x71588000, 0x14100100, 0xC140000C, 0xC1900004, 0x71588000,
+ 0x14100100, 0xC1400004, 0xC1900006, 0x71588000, 0x14100100, 0xC1400006, 0xC1900008, 0x71588000,
+ 0x14100100, 0xC140000E, 0xC190000A, 0x71588000, 0x14100100, 0xC1400000, 0xC190000C, 0x71588000,
+ 0x14100100, 0xC1400002, 0xC190000E, 0x71588000, 0x14100100, 0xC0400000, 0xC11C0000, 0xC000E82C,
+ 0xCD05CE00, 0xC11C0002, 0xC000E82C, 0xCD05CE00, 0xC0400002, 0xC11C0000, 0xC000E82C, 0xCD05CE00,
+ 0xC11C0002, 0xC000E82C, 0xCD05CE00, 0xC000E824, 0x00000000, 0xCBC000F9, 0xCB8000F9, 0xCB4000F9,
+ 0xCB0000F8, 0xC000ABE4, 0x5BFC4000, 0xCFC000F9, 0x5BB84000, 0xCF8000F9, 0x5B744000, 0xCF4000F9,
+ 0x5B304000, 0xCF0000F8, 0xC000EA10, 0x00000000, 0xCBC000F9, 0xCB8000F8, 0xC000ABE0, 0x5BFC4000,
+ 0xCFC000F9, 0x5BB84000, 0xCF8000F8, 0xC30001FE, 0xC000F416, 0xCF0000F8, 0xC3000000, 0x7F018000,
+ 0xC000E42E, 0xCF0000F8, 0xC000E40E, 0xCF0000F8, 0xC3C1FFFE, 0xC000690E, 0xCFC00078, 0xC000692C,
+ 0xCFC00078, 0xC0006924, 0xCFC00038, 0xC0006912, 0xCFC00038, 0xC0006966, 0xCFC00038, 0xC0006968,
+ 0xCFC00078, 0xC000696A, 0xCFC00078, 0xC3C00000, 0xC2800020, 0xC3000000, 0x7F018000, 0x6FF88000,
+ 0x6FD44000, 0x4395C000, 0x5BB89800, 0x5838000A, 0xCF0000F8, 0x5BFC0002, 0xB7E8FFC8, 0x00000000,
+ 0xC3C00000, 0xC2800010, 0x6FF86000, 0x47BDC000, 0x5BB89F00, 0xC3400000, 0x58380004, 0xCB420078,
+ 0x00000000, 0x58380008, 0xCF400078, 0x5BFC0002, 0xB7E8FFB0, 0x00000000, 0xC3C00000, 0xC2800020,
+ 0xC348001E, 0xC3000000, 0x7F018000, 0x6FF8A000, 0x6FD44000, 0x4795C000, 0x47BDC000, 0x5BB87400,
+ 0x58380008, 0xCF408418, 0x5838000A, 0xCF0000F8, 0x5BFC0002, 0xB7E8FFB0, 0x00000000, 0x00000000,
+ 0xC3E0E282, 0x5BFC0030, 0xC0004002, 0xCFC000F8, 0xC000E82C, 0xC11E0002, 0xCD01EF00, 0xC000E82E,
+ 0xCD01EF00, 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000, 0x80000028, 0x00000000, 0x80001CB8,
+ 0x00000000, 0x8000FFE0, 0xC0006918, 0xD28000F8, 0xC2000000, 0xDF600038, 0x5E600020, 0x84000272,
+ 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0xC000402A, 0xCA0000F8, 0xC0006912,
+ 0xCA4000F8, 0xC0006924, 0xCA8000F8, 0xC0006966, 0xCAC000F8, 0x00000000, 0xC121FFFE, 0x5911FE94,
+ 0x14100000, 0x76250000, 0x76290000, 0x762D0000, 0x840001CA, 0xC0006918, 0xCA4000F8, 0xC28001FE,
+ 0x76290000, 0x5A640002, 0x6A254010, 0x5EE80000, 0x8400001A, 0x6AA54000, 0x80000010, 0xC62800F8,
+ 0x62818008, 0xC0006918, 0xCF0000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0xC0006966,
+ 0xCA4000F8, 0xC2000002, 0x6A310000, 0x7E010000, 0x76612000, 0xCE4000F8, 0x00000000, 0xC121FFFE,
+ 0x5911FE94, 0x14100000, 0x6F346000, 0x4771A000, 0x5B749F00, 0xC2800000, 0x58340006, 0xCA800078,
+ 0xC2C00000, 0x58340000, 0xCAC000D8, 0xC2400000, 0x5834000A, 0xCA420078, 0x6EA82000, 0x42E9E000,
+ 0x6F2CA000, 0x42E56000, 0x5AEC3200, 0xC3990040, 0xC7381C18, 0xC6F80060, 0x99005560, 0xDB9800F8,
+ 0xDBD800F9, 0x00000000, 0xDEA000F8, 0x46310000, 0x8400FD80, 0xC0006958, 0xC84000F8, 0x00000000,
+ 0xC3C00002, 0x787C2000, 0xCC4000F8, 0xC000ABC8, 0xCB8400F8, 0xC000ABC4, 0xC88400F8, 0x5FB80000,
+ 0x8400FCFA, 0xC000FAC0, 0xCA0400F8, 0x00000000, 0x00000000, 0xA6040070, 0xC000ABE4, 0xC80400F8,
+ 0x6C908000, 0x45088000, 0x45088000, 0x40100000, 0xCA0000F8, 0xC42400F8, 0x00000000, 0x98C05CD8,
+ 0xC000697C, 0xCA0000F8, 0x59640004, 0xC0004030, 0xCA0000F8, 0xC2400002, 0x6A452000, 0x76250000,
+ 0x8400FC3A, 0xC000ABE8, 0xC80400F8, 0x00000000, 0x00000000, 0x40080000, 0xCA0000F8, 0xC42400F8,
+ 0x00000000, 0xA63C17DA, 0x00000000, 0xC000ABE4, 0xC80400F8, 0x6C908000, 0x45088000, 0x45088000,
+ 0x40100000, 0xCA0000F8, 0xC42400F8, 0x00000000, 0xC0006934, 0xCE0000F8, 0xC2800002, 0xC4681C08,
+ 0xC62821D0, 0xC2600010, 0x5A650D80, 0xC0004020, 0xCB4000F8, 0xC2200400, 0x5A200D40, 0xC7601040,
+ 0xC000F220, 0xCE8000F8, 0xC000F200, 0xCE4000F8, 0xC000F202, 0xCE0000F8, 0xC000F240, 0xCB4000F8,
+ 0x00000000, 0x00000000, 0xA754FFE0, 0xC2000000, 0xC7600040, 0xA7520042, 0x00000000, 0x00000000,
+ 0x99005FD8, 0xC0009DE2, 0xC94000F8, 0xC1800002, 0x80001680, 0x58204DC0, 0xC2000000, 0xCA000018,
+ 0xC2400000, 0xCA414000, 0xC2800000, 0xCA812000, 0xC2C00000, 0xCAC20018, 0xC0006938, 0xCE0000F8,
+ 0xC0006920, 0xCE4000F8, 0xC0006916, 0xCE8000F8, 0xC0006922, 0xCEC000F8, 0xA6400540, 0x00000000,
+ 0xC0006938, 0xCBC000F8, 0x00000000, 0xC3800000, 0x6FF48000, 0x6FD44000, 0x4355A000, 0x5B749800,
+ 0x58340000, 0xCB802010, 0x00000000, 0xC2000000, 0x6FB46000, 0x4779A000, 0x5B749F00, 0x5834000C,
+ 0xCA000020, 0xC000691A, 0xCF8000F8, 0x5E200000, 0x8400046A, 0xC2000000, 0xDF610048, 0x5E6001E8,
+ 0x8800FFE8, 0xC2000002, 0xC2400466, 0xC2A00000, 0x5AA80000, 0xC000F006, 0xCE0000F8, 0xC000F008,
+ 0xCE4000F8, 0xC000F00A, 0xCE8000F8, 0x99004FA0, 0xC1A0FFFE, 0xC000E824, 0xC9840070, 0xC0006934,
+ 0xCA4000F8, 0xC2000000, 0xC2800002, 0x99004FE0, 0xDA9800F8, 0xC61400F8, 0xC65800F8, 0xC161FFFE,
+ 0x5955FFFE, 0x14140000, 0x00000000, 0x990050C8, 0xC000691A, 0xC94000F8, 0x00000000, 0x00000000,
+ 0xC121FFFE, 0x5911FE94, 0x14100000, 0xC0006922, 0xCA001118, 0xC3C00000, 0xC3800000, 0xC0006930,
+ 0xCE023118, 0xC0006932, 0xCBC000D8, 0xC2800000, 0xC000691E, 0xCFC000F8, 0xC000ABDE, 0xCA800060,
+ 0xC3A0001A, 0x5BB94000, 0xC6B80060, 0xC000691C, 0xCF8000F8, 0x99005338, 0xC000691C, 0xC1400000,
+ 0xC9420048, 0x00000000, 0x00000000, 0x00000000, 0xA8E2FFE8, 0xC2000000, 0xC1220002, 0xD90C00F8,
+ 0xDF600038, 0x5E600020, 0x8400FFF2, 0xC000691C, 0xCA0000F8, 0xC000691E, 0xCA4000F8, 0x00000000,
+ 0x00000000, 0x99005560, 0xDA1800F8, 0xDA5800F9, 0x00000000, 0xC2000000, 0xDF610048, 0x5E6001FE,
+ 0x8800FFE8, 0xC0006916, 0xCA8000F8, 0xC2C00000, 0xDFEC0048, 0xC2400000, 0x466D2000, 0x8400004A,
+ 0x5EA80000, 0x8400003A, 0xC2600002, 0x99005FD8, 0xC0009DEE, 0xC94000F8, 0xC1800002, 0x80000030,
+ 0xC2600000, 0x99005FD8, 0xC0009DEC, 0xC94000F8, 0xC1800002, 0xC2000068, 0xC6240078, 0xC0006930,
+ 0xCE400080, 0xC000691A, 0xC98000F8, 0xC000ABDE, 0xC94000F8, 0x6D9C6000, 0x45D8E000, 0x59DC9F00,
+ 0x990053C0, 0xD95800F8, 0xD99800F9, 0xD9D400F8, 0x99005338, 0xC000691C, 0xC1400000, 0xC9420048,
+ 0xC2000000, 0xDF600038, 0x5E600020, 0x8400FFEA, 0x00000000, 0xC000691C, 0xCA0000F8, 0xC000691E,
+ 0xCA4000F8, 0x00000000, 0x00000000, 0x99005560, 0xDA1800F8, 0xDA5800F9, 0x00000000, 0x800010E8,
+ 0x00000000, 0x99005FD8, 0xC0009DEA, 0xC94000F8, 0xC1800002, 0x800010B8, 0xC0006938, 0xCBC000F8,
+ 0x00000000, 0x00000000, 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB89800, 0x58380008, 0xCA0000F8,
+ 0x00000000, 0x00000000, 0xA6000382, 0x00000000, 0xC0006938, 0xCBC000F8, 0xC3000000, 0x00000000,
+ 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB89800, 0x58380000, 0xCB002010, 0xC2000000, 0x58380008,
+ 0xCA020078, 0x5838000C, 0xCAC000F8, 0x5838000E, 0xCA4000F8, 0xC000691A, 0xCF0000F8, 0xC0006930,
+ 0xCEC000F8, 0xC000693C, 0xCE0000F8, 0xC0006932, 0xCE4000F8, 0x5E200000, 0x84000120, 0xC2800000,
+ 0xA6FE00BA, 0x6F206000, 0x46310000, 0x5A209F00, 0x5820000C, 0xCA800020, 0x00000000, 0x00000000,
+ 0x5EA80000, 0x840001F2, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x990050C8,
+ 0xC000691A, 0xC94000F8, 0x00000000, 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000, 0xC0006930,
+ 0xCAC000F8, 0xC0006932, 0xCA4000F8, 0xC7EC1118, 0xC0006930, 0xCEC000F8, 0x5838000C, 0xCEC000F8,
+ 0x58000002, 0xCE4000F8, 0xC0006934, 0xCA0000F8, 0xC2400002, 0x6E642000, 0x6E642000, 0x76612000,
+ 0x8400002A, 0xC2400002, 0x6E684000, 0x58380008, 0xCE804200, 0xA6000020, 0x6E682000, 0x58380008,
+ 0xCE802100, 0xC2400002, 0x6E642000, 0x76612000, 0x840000EA, 0x58380008, 0xCA0000F8, 0xC2800000,
+ 0xC2400000, 0xA60200C0, 0xDBA800F8, 0x6F386000, 0x47B1C000, 0x5BB89F00, 0x58380004, 0xCA400078,
+ 0x58380002, 0xCA800078, 0x00000000, 0xDEB800F8, 0x46A54000, 0x88000060, 0x00000000, 0xC0009DE4,
+ 0xCA0000F8, 0xC2400002, 0x6E640000, 0x5A200002, 0xCE0000F8, 0x58380008, 0xCE400000, 0x80000018,
+ 0x00000000, 0x80000048, 0xC0006934, 0xCA0000F8, 0x00000000, 0x00000000, 0xA6020C6A, 0x00000000,
+ 0x00000000, 0x80000C98, 0xC2800000, 0xC2000080, 0xC240001A, 0xDF690048, 0x46294000, 0x46A54000,
+ 0x8800FFD2, 0xC2000006, 0xC2600982, 0x5A643B6E, 0x5838000A, 0xCA8000F8, 0xC000F006, 0xCE0000F8,
+ 0xC000F008, 0xCE4000F8, 0xC000F00A, 0xCE8000F8, 0x99004FA0, 0xC1A0FFFE, 0xC000E824, 0xC9840070,
+ 0xC2000000, 0xC0006930, 0xCA02E008, 0x58380026, 0xCA4000F8, 0x00000000, 0xC2800000, 0x99004FE0,
+ 0xDA9800F8, 0xC61400F8, 0xC65800F8, 0xC0006934, 0xCA0000F8, 0x00000000, 0x00000000, 0xA6020022,
+ 0x00000000, 0x00000000, 0x80000318, 0xC0006938, 0xCBC000F8, 0xC000ABE4, 0xC80400F8, 0x6C908000,
+ 0x45088000, 0x45088000, 0x40100000, 0xCA0000F8, 0xC42400F8, 0x00000000, 0x58240018, 0xCA0000F8,
+ 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB89800, 0xC3000000, 0xC3400002, 0xC2C00000, 0xC62C0078,
+ 0xC6270038, 0xC0006940, 0xCE400038, 0xC6260038, 0xC0006942, 0xCE400038, 0xC000693C, 0xCA0000F8,
+ 0x5EEC0000, 0x8400018A, 0x5A6C0010, 0x46254000, 0x88000190, 0x5A600052, 0x46E54000, 0x88000178,
+ 0x58380006, 0xCA8000F8, 0xC0006940, 0xCA0000F8, 0xC2400000, 0xC6A70038, 0x7E412000, 0x76612000,
+ 0xC2000000, 0xC6A10038, 0x46250000, 0x84000138, 0xC0006942, 0xCA0000F8, 0xC2400000, 0xC6A60038,
+ 0x7E412000, 0x76612000, 0xC2000000, 0xC6A00038, 0x58380002, 0xCA8000F8, 0x46250000, 0x840000E8,
+ 0xC2400000, 0xC6A60078, 0x466D0000, 0x880000DA, 0xC2400000, 0xC6A40078, 0x58380008, 0xCA8000F8,
+ 0x46E50000, 0x880000BA, 0x00000000, 0xA6820018, 0x00000000, 0xC7700B00, 0xA6840098, 0x00000000,
+ 0xC7700A00, 0x80000080, 0xC7700200, 0xC000693C, 0xCAC000F8, 0x80000060, 0xC7700300, 0xC000693C,
+ 0xCAC000F8, 0x80000040, 0xC7700900, 0x80000030, 0xC7700800, 0x80000020, 0xC7700700, 0x80000010,
+ 0xC7700500, 0xC0006944, 0xCF0000F8, 0xC000693E, 0xCEC000F8, 0xC0006938, 0xCA4000F8, 0xC000693C,
+ 0xCB8000F8, 0xC000693E, 0xCB4000F8, 0xC3000000, 0x6E608000, 0x6E544000, 0x42150000, 0x5A209800,
+ 0x5AA00008, 0x58200004, 0xCB000078, 0xC0006934, 0xCA0000F8, 0xC2400000, 0xC0006930, 0xCA42E008,
+ 0xC3C00018, 0xA6020098, 0x00000000, 0x43656000, 0x47AD0000, 0x88000050, 0x46F96000, 0x6EE04010,
+ 0x5BE00004, 0xC2000000, 0xC6E00008, 0x5E200000, 0x84000042, 0x5BFC0002, 0x80000030, 0xC3C00004,
+ 0x5A2C0008, 0x47A10000, 0x88000012, 0x5FB80008, 0x6FE04000, 0x42390000, 0x47212000, 0x88000068,
+ 0xC2400000, 0xC0006930, 0xCA42E008, 0xC2060002, 0xC68000F8, 0xCE006300, 0x6FE04000, 0x4721C000,
+ 0x5F700010, 0x4765A000, 0xC2000000, 0xC6340008, 0xC25A000A, 0xC000691A, 0xCA401C18, 0xC2800000,
+ 0xC0006932, 0xCA8000D8, 0xC000ABDE, 0xCA400060, 0x6FA04010, 0x42290000, 0xC000691E, 0xCE0000F8,
+ 0xC7E41048, 0xC000691C, 0xCE4000F8, 0x6FE04000, 0x43A1C000, 0xC000693C, 0xCF8000F8, 0xC000693E,
+ 0xCF4000F8, 0xC000693A, 0xCFC000F8, 0x80000008, 0x00000000, 0x00000000, 0x00000000, 0xC2000000,
+ 0xDCE000F8, 0xA622FFD8, 0xC1220002, 0xD90C00F8, 0xC0006938, 0xCBC000F8, 0xC0006944, 0xCB4000F8,
+ 0xC000ABDE, 0xCB0000F8, 0xC0006934, 0xCA0000F8, 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB89800,
+ 0xA6020268, 0xC2400000, 0x58380008, 0xCA406000, 0xDFE800F8, 0xC2218E08, 0x5A21BAF6, 0x46A14000,
+ 0x84000022, 0xC2080002, 0x7361A000, 0x80000058, 0x5E640000, 0x84000022, 0xC20C0002, 0x7361A000,
+ 0x80000030, 0xC2000000, 0xC760E710, 0xC7604218, 0x5E200000, 0x84000272, 0xC2200002, 0xC0006930,
+ 0xCE021000, 0x99005FD8, 0xC0009DE8, 0xC94000F8, 0xC1800002, 0x58380000, 0xCA0000F8, 0x00000000,
+ 0x00000000, 0xA6000132, 0xC0006940, 0xCA8000F8, 0xC0006942, 0xCA4000F8, 0xC7600078, 0xC6A01838,
+ 0xC6601038, 0xC000693A, 0xCA4000F8, 0xC0006934, 0xCA8000F8, 0xC000AB40, 0x40300000, 0x40240000,
+ 0x5C000004, 0x5EC0ABC0, 0x88000012, 0x5C000080, 0xCE0000F8, 0x58000002, 0x5EC0ABC0, 0x88000012,
+ 0x5C000080, 0xCE8000F8, 0xC000693E, 0xCA0000F8, 0xC2400000, 0x5838000C, 0xCE4000F8, 0x99005FD8,
+ 0xC0009DF0, 0xC94000F8, 0xC61800F8, 0xC0006930, 0xC6100078, 0xCD000078, 0x800000A8, 0xC2400002,
+ 0x58380008, 0xCE400000, 0xC0006944, 0xCF4000F8, 0x80000278, 0xC000693C, 0xCA4000F8, 0xDFE800F8,
+ 0x5A300018, 0xC000AB40, 0x40200000, 0xCA0000F8, 0x58380008, 0xC6501078, 0xCD021078, 0x5838000A,
+ 0xCE8000F8, 0x58380026, 0xCE0000F8, 0xC0006944, 0xCF4000F8, 0x99005338, 0xC000691C, 0xC1400000,
+ 0xC9420048, 0x80000038, 0x00000000, 0x99005FD8, 0xC0009DE6, 0xC94000F8, 0xC1800002, 0x8000FDD8,
+ 0xC2000000, 0xC2400020, 0xDF600038, 0xB624FFEA, 0xC000691C, 0xCA4000F8, 0xC000691E, 0xCA8000F8,
+ 0x99005560, 0xDA5800F8, 0xDA9800F9, 0x00000000, 0xC0006934, 0xCA0000F8, 0x00000000, 0xC2800000,
+ 0xA6020160, 0xC2400004, 0xC2000080, 0xDF690048, 0x46294000, 0x46A54000, 0x8800FFDA, 0x00000000,
+ 0xC000691A, 0xC98000F8, 0xC000ABDE, 0xC94000F8, 0x6D9C6000, 0x45D8E000, 0x59DC9F00, 0x990053C0,
+ 0xD95800F8, 0xD99800F9, 0xD9D400F8, 0x99005338, 0xC000691C, 0xC1400000, 0xC9420048, 0xC2000000,
+ 0xC2400020, 0xDF600038, 0xB624FFEA, 0xC000691C, 0xCA4000F8, 0xC000691E, 0xCA8000F8, 0x99005560,
+ 0xDA5800F8, 0xDA9800F9, 0x00000000, 0x58380008, 0xCA4000F8, 0xC2000000, 0xCE000018, 0xC2A1FFFE,
+ 0x5AA9FFFE, 0xCE021078, 0x5838000A, 0xCE8000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000,
+ 0xC000E838, 0xC2500002, 0xCE450800, 0xC000ABC8, 0xCB8400F8, 0xC2000000, 0xC000E82C, 0xCA040038,
+ 0x5FB80002, 0xC000ABC8, 0xCF8400F8, 0x58880002, 0xB6080018, 0x00000000, 0xC0800000, 0xC000ABC4,
+ 0xCC8400F8, 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000, 0x8000E350, 0xC2000000, 0xDF600038,
+ 0x5E200020, 0x8400026A, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0xC000402C,
+ 0xCA0000F8, 0xC0006910, 0xCA4000F8, 0xC000692C, 0xCA8000F8, 0xC0006968, 0xCAC000F8, 0x00000000,
+ 0xC121FFFE, 0x5911FE94, 0x14100000, 0x76250000, 0x76290000, 0x76E16000, 0x840001C2, 0xC0006926,
+ 0xCA4000F8, 0xC201FFFE, 0x76E16000, 0x5A640002, 0x6AE50010, 0x5F200000, 0x8400001A, 0x6A250000,
+ 0x80000010, 0xC6E000F8, 0x62014008, 0xC0006926, 0xCE8000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000,
+ 0x00000000, 0xC0006968, 0xCA4000F8, 0xC2000002, 0x6A290000, 0x7E010000, 0x76612000, 0xCE4000F8,
+ 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000, 0x6EB4A000, 0x6E944000, 0x4755A000, 0x4769A000,
+ 0x5B747400, 0x58340002, 0xC2000000, 0xCA0000D8, 0x5834002E, 0xC2400000, 0xCA400078, 0x6EB0A000,
+ 0x6EBC4000, 0x473D8000, 0x47298000, 0x5B30342E, 0x5B300004, 0x6E642000, 0x4225E000, 0xC39A8024,
+ 0xC7380060, 0xC6B81C18, 0x99005560, 0xDB9800F8, 0xDBD800F9, 0x00000000, 0xC2000000, 0xDF600038,
+ 0x5E200020, 0x840002A2, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0xC000690E,
+ 0xCA0000F8, 0xC000692A, 0xCA4000F8, 0xC000696A, 0xCB0000F8, 0xC0006956, 0xCAC000F8, 0x00000000,
+ 0xC121FFFE, 0x5911FE94, 0x14100000, 0x77218000, 0x77258000, 0x84000202, 0xC201FFFE, 0x77218000,
+ 0x5AEC0002, 0x6B2D0010, 0x5EA00000, 0x8400001A, 0x6A2D0000, 0x80000010, 0xC72000F8, 0x62016008,
+ 0xC0006956, 0xCEC000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0xC000696A, 0xCA4000F8,
+ 0xC2000002, 0x6A2D0000, 0x7E010000, 0x76612000, 0xCE4000F8, 0x00000000, 0xC121FFFE, 0x5911FE94,
+ 0x14100000, 0x6EF4A000, 0x6ED44000, 0x4755A000, 0x476DA000, 0x5B747400, 0x5834000E, 0xC2000000,
+ 0xCA0000D8, 0x58340008, 0xC2400000, 0xCA420078, 0x5834000C, 0xC2800000, 0xCA832010, 0x6E644010,
+ 0x42250000, 0x4229E000, 0xC39A8008, 0x58340008, 0xCB809018, 0x58340008, 0xC2800000, 0xCA810010,
+ 0x6EE0A000, 0x6EE44000, 0x46250000, 0x462D0000, 0x5A200008, 0x5A203408, 0x42290000, 0xC6380060,
+ 0xC6F81C18, 0x99005560, 0xDB9800F8, 0xDBD800F9, 0x00000000, 0xC000695A, 0xC84000F8, 0x00000000,
+ 0xC3C00002, 0x787C2000, 0xCC4000F8, 0xC0004030, 0xCA0000F8, 0xC2400008, 0x6A452000, 0x76250000,
+ 0x84000E02, 0xC000EA28, 0xC3800000, 0xCB840038, 0xC000EA14, 0xC3400000, 0xCB440038, 0xC0009F70,
+ 0xCB0400F8, 0xB7B4005A, 0x5804F802, 0xCAC000F8, 0xA7000060, 0x00000000, 0x00000000, 0xA6C8DD30,
+ 0xC2800000, 0xC6E80018, 0x80000070, 0x00000000, 0x00000000, 0x00000000, 0x8000DCF8, 0x00000000,
+ 0xC2800000, 0xC7282018, 0xC000690E, 0xCA4000F8, 0x6BE9E000, 0x00000000, 0x767D2000, 0x8400DCB0,
+ 0x6EA0A000, 0x6E944000, 0x46150000, 0x46290000, 0x5A207400, 0x5820000C, 0xCA0000F8, 0xC0006946,
+ 0xCE8000F8, 0xA6220368, 0x00000000, 0xC2200060, 0xC0006948, 0xCE000008, 0xCE021038, 0xC240000A,
+ 0xC000694A, 0xCE4000F8, 0xC2B60002, 0xC0006964, 0xCE837B00, 0x99005830, 0xC0009F74, 0xC88400F8,
+ 0x00000000, 0xC0006946, 0xCBC000F8, 0x00000000, 0x00000000, 0x6FF8A000, 0x6FD44000, 0x4795C000,
+ 0x47BDC000, 0x5BB87400, 0x990055F0, 0xDBD800F8, 0xDB9800F9, 0x00000000, 0x99005338, 0xC000691C,
+ 0xC1400000, 0xC9420048, 0xC000691C, 0x990057E8, 0xC94000F9, 0xC98000F8, 0x00000000, 0x99005560,
+ 0xD95800F8, 0xD99800F9, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x99005228,
+ 0xDBD800F8, 0xDB9800F9, 0xC7D800F8, 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000, 0x6FF8A000,
+ 0x6FD44000, 0x4795C000, 0x47BDC000, 0x5BB87400, 0x58380010, 0xCA0000F8, 0xC000ABE0, 0xC80400F8,
+ 0x6C908000, 0x45088000, 0x45088000, 0x40100000, 0xCA4000F8, 0xC43400F8, 0x00000000, 0xC74000F8,
+ 0xCE0000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0xC000690E, 0xCA4000F8, 0xC2800002,
+ 0x6ABD4000, 0x72692000, 0xCE4000F8, 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000, 0x99005FD8,
+ 0xC0009DF6, 0xC94000F8, 0xC1800002, 0x00000000, 0x00000000, 0x00000000, 0xA8E2FFE8, 0x00000000,
+ 0xC1220002, 0xD90C00F8, 0xC2000000, 0xC000EA14, 0xCA040038, 0xC000EA28, 0xC2500002, 0xCE450800,
+ 0x58880002, 0xB6080018, 0xC0009F74, 0xC0800000, 0xCC8400F8, 0x8000D900, 0xC0006946, 0xCBC000F8,
+ 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0xC000690E, 0xCA4000F8, 0xC2800002, 0x6ABD4000,
+ 0x72692000, 0xCE4000F8, 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000, 0x6FF8A000, 0x6FD44000,
+ 0x4795C000, 0x47BDC000, 0x5BB87400, 0x58380008, 0xCA0000F8, 0x5838000C, 0xCA4000F8, 0xC3400000,
+ 0xC6340000, 0xC000694E, 0xCF4000F8, 0xC2800000, 0xC62A0078, 0xC3000000, 0xC6308018, 0x6F304000,
+ 0x43298000, 0xC000693C, 0xCF0000F8, 0xC2C00000, 0xC66C0078, 0xC0006950, 0xCEC000F8, 0xC2800000,
+ 0xC66AE020, 0xC0006954, 0xCE8000F8, 0x5F740000, 0x840001A0, 0x5E300028, 0x46E12000, 0x8400016A,
+ 0x46E12000, 0x88000132, 0x5E300018, 0x46E12000, 0x8800002A, 0x46E12000, 0x84000042, 0x00000000,
+ 0x800000C0, 0x00000000, 0x99005970, 0xDBD800F8, 0xDB9800F9, 0xC78000F8, 0xC3400002, 0xC000694E,
+ 0xCF4000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0xC000690E, 0xCA4000F8, 0xC2800002,
+ 0x6ABD4000, 0x7E814000, 0x76692000, 0xCE4000F8, 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000,
+ 0xC2200060, 0xC0006948, 0xCE021038, 0xC2000000, 0xC000694C, 0xCE0000F8, 0x80000080, 0x00000000,
+ 0x99005970, 0xDBD800F8, 0xDB9800F9, 0xC78000F8, 0x99005B70, 0xDBD800F8, 0xDB9800F9, 0xC78000F8,
+ 0xC2200058, 0xC0006948, 0xCE021038, 0xC2000002, 0xC000694C, 0xCE0000F8, 0xC2000006, 0xC000F006,
+ 0xCE0000F8, 0x5838000A, 0xCA4000F8, 0xC2200982, 0x5A203B6E, 0xC000F008, 0xCE0000F8, 0xC000F00A,
+ 0xCE4000F8, 0xC0006954, 0xCA8000F8, 0xC200000C, 0xC000694A, 0xCE0000F8, 0xC0006948, 0xCE800008,
+ 0xC2B60000, 0xC0006964, 0xCE8000F8, 0x99005830, 0xC0009F74, 0xC88400F8, 0x00000000, 0xC0006946,
+ 0xCBC000F8, 0xC000694C, 0xCA0000F8, 0x6FF8A000, 0x6FD44000, 0x4795C000, 0x47BDC000, 0x5BB87400,
+ 0x5E200000, 0x840000FA, 0x00000000, 0x990055F0, 0xDBD800F8, 0xDB9800F9, 0x00000000, 0x99005338,
+ 0xC000691C, 0xC1400000, 0xC9420048, 0xC000691C, 0x990057E8, 0xC94000F9, 0xC98000F8, 0x00000000,
+ 0x99005560, 0xD95800F8, 0xD99800F9, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000,
+ 0x99005228, 0xDBD800F8, 0xDB9800F9, 0xC7D800F8, 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000,
+ 0xC000693C, 0xCA8000F8, 0xC000694E, 0xCAC000F8, 0xC3000018, 0xC3400006, 0x5E200000, 0x8400002A,
+ 0xC2800000, 0xC2C00000, 0xC300001E, 0xC3400000, 0xC6AC1078, 0xC72C0418, 0xC76C0810, 0x58380010,
+ 0xCA8000F8, 0x58380008, 0xCEC000F8, 0xC6280100, 0xC000ABE0, 0xC80400F8, 0x6C908000, 0x45088000,
+ 0x45088000, 0x40100000, 0xCB0000F8, 0xC43400F8, 0x00000000, 0xC74000F8, 0xCE8000F8, 0xC0006952,
+ 0xCE8000F8, 0x00000000, 0x00000000, 0x00000000, 0xA8E2FFE8, 0x00000000, 0xC000694C, 0xCA0000F8,
+ 0xC0006950, 0xCAC000F8, 0x5E200000, 0x8400006A, 0xDFE800F8, 0x7E814000, 0x5834001A, 0xCE8000F8,
+ 0x99005FD8, 0xC0009DF4, 0xC94000F8, 0xC1800002, 0x99005FD8, 0xC0009DF8, 0xC94000F8, 0xC6D800F8,
+ 0xC1220002, 0xD90C00F8, 0x5E200000, 0x84000040, 0x5838002C, 0xCB0000F8, 0xDFE800F8, 0x00000000,
+ 0x58380014, 0xCF0000F8, 0x80000018, 0xC2A1FFFE, 0x5AA9FFFE, 0x5838000A, 0xCE8000F8, 0xC3000000,
+ 0xC000EA14, 0xCB040038, 0xC2D00002, 0xC000EA28, 0xCEC50800, 0xC000694E, 0xCA8000F8, 0x58880002,
+ 0xB4B00018, 0xC0009F74, 0xC0800000, 0xCC8400F8, 0x5EA80000, 0x84000152, 0x5E200000, 0x84000140,
+ 0xC000693C, 0xCA8000F8, 0x00000000, 0x00000000, 0x5AA80060, 0xCE8000F8, 0x99005970, 0xDBD800F8,
+ 0xDB9800F9, 0xC78000F8, 0x99005B70, 0xDBD800F8, 0xDB9800F9, 0xC78000F8, 0xC0006952, 0xCAC000F8,
+ 0x58380000, 0xCA8000F8, 0xC30C0002, 0xC7F00018, 0xA6800098, 0x00000000, 0x00000000, 0xC161FFFE,
+ 0x5955FFFE, 0x14140000, 0x00000000, 0xC000F800, 0xCA0000F8, 0x00000000, 0x00000000, 0xA60CFFEA,
+ 0xC6F00500, 0xC6B0C400, 0xCF0000F8, 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000, 0x8000CFB0,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000CF48, 0xDCBC00F9, 0x5FFC0000, 0x84000052,
+ 0xC3800002, 0xDB8800F9, 0x5FFC0004, 0x8400C86A, 0xC3800000, 0xDB8800F9, 0xC3CE0002, 0xC000E800,
+ 0xCFC0E700, 0xC3E1FFFE, 0x597DFFFE, 0x593DFE14, 0x94000001, 0x00000000, 0x00000000, 0x00000000,
+ 0xC000ABE8, 0xC80400F8, 0x00000000, 0x00000000, 0x40080000, 0xCBC000F8, 0xC43800F8, 0x00000000,
+ 0xC000402E, 0xCA0000F8, 0xC000ABD8, 0xCB4400F8, 0x00000000, 0x00000000, 0x47610000, 0x880000B0,
+ 0x00000000, 0xA7C00048, 0xC000ABD4, 0xC1000002, 0xCD0400F8, 0xC11C0000, 0xC000E82C, 0xCD05CE00,
+ 0x800000D8, 0x00000000, 0xA7D20120, 0x00000000, 0xC7E14040, 0xC2400000, 0xC6246028, 0xC200006A,
+ 0x46250000, 0xC6240030, 0xC000E810, 0xCE440030, 0x8000FF70, 0xC2000000, 0xC000E808, 0xCA040010,
+ 0xC11C0000, 0xC000E82C, 0xCD05CE00, 0x5A200002, 0x5E600010, 0x84000010, 0xC2000000, 0xC000E808,
+ 0xCE040010, 0xC3400000, 0x80000010, 0x5B740002, 0xC000ABD8, 0xCF4400F8, 0x99004F78, 0xC000ABC8,
+ 0xC94400F8, 0xC1800000, 0xC11C0002, 0xC000E82C, 0xCD05CE00, 0x80000600, 0x5B740002, 0xC000ABD8,
+ 0xCF4400F8, 0xC78000F8, 0xC13C0002, 0xCD03DE00, 0xC000ABC8, 0xC94400F8, 0xC1800000, 0xC000E82C,
+ 0xC9840038, 0x59540002, 0xC000ABC8, 0xCD4400F8, 0x58880002, 0xB4980580, 0x00000000, 0xC0800000,
+ 0x80000568, 0xC000ABE8, 0xC80400F8, 0x00000000, 0x00000000, 0x40080000, 0xCBC000F8, 0xC42800F8,
+ 0x00000000, 0xA7C00130, 0xC000ABCC, 0xCA0400F8, 0xC2400000, 0xC000FAEC, 0xCA440018, 0x5A200002,
+ 0xC000ABCC, 0xCE0400F8, 0xB624008A, 0xC68000F8, 0xC13C0002, 0xCD03DE00, 0xC000ABC8, 0xC94400F8,
+ 0xC1800000, 0xC000E82C, 0xC9840038, 0x59540002, 0xC000ABC8, 0xCD4400F8, 0x58880002, 0xB4980470,
+ 0x00000000, 0xC0800000, 0x80000458, 0xC000ABD4, 0xC1000004, 0xCD0400F8, 0xC000E820, 0xC2000002,
+ 0xCE0400F8, 0xC2000000, 0xC000ABCC, 0xCE0400F8, 0xC000ABD8, 0xCE0400F8, 0x8000FF28, 0xC000ABD4,
+ 0xC1000000, 0xCD0400F8, 0xC11C0000, 0xC000E82C, 0xCD05CE00, 0x99004F78, 0xC000ABC8, 0xC94400F8,
+ 0xC1800000, 0xC1200000, 0xC000E818, 0xCD061000, 0xC11C0002, 0xC000E82C, 0xCD05CE00, 0xC2000000,
+ 0xC000ABCC, 0xCE0400F8, 0x80000358, 0xC000FAC0, 0xCB8400F8, 0xC000ABE8, 0xC80400F8, 0x00000000,
+ 0x00000000, 0x40080000, 0xCBC000F8, 0xC42800F8, 0x00000000, 0x00000000, 0xC68000F8, 0xC13C0000,
+ 0xCD03DE00, 0xA780024A, 0x00000000, 0x00000000, 0xA7C0020A, 0x00000000, 0xC000FB60, 0xC2060006,
+ 0xCE046308, 0xA7E801C2, 0x00000000, 0xC000ABD0, 0xCA0400F8, 0xC2400000, 0xC000FAEC, 0xCA448018,
+ 0x5A200002, 0xC000ABD0, 0xCE0400F8, 0xB62400AA, 0x00000000, 0xC68000F8, 0xC13C0002, 0xCD03DE00,
+ 0xC000FACC, 0xC2000002, 0xCE040000, 0xC000ABC8, 0xC94400F8, 0xC1800000, 0xC000E82C, 0xC9840038,
+ 0x59540002, 0xC000ABC8, 0xCD4400F8, 0x58880002, 0xB49801C8, 0x00000000, 0xC0800000, 0x800001B0,
+ 0xC000ABD4, 0xC1000000, 0xCD0400F8, 0xC11C0000, 0xC000E82C, 0xCD05CE00, 0x99004F78, 0xC000ABC8,
+ 0xC94400F8, 0xC1800000, 0xC2000000, 0xC000E820, 0xCE0400F8, 0xC1200000, 0xC000E818, 0xCD061000,
+ 0xC11C0002, 0xC000E82C, 0xCD05CE00, 0xC000ABD0, 0xCE0400F8, 0xC2000002, 0xC000FACC, 0xCE040008,
+ 0x800000E8, 0xC2000002, 0xC000ABD0, 0xCE0400F8, 0x8000FE88, 0xC2000000, 0xC000ABD0, 0xCE0400F8,
+ 0xA7E60032, 0x00000000, 0xC2000002, 0xC000FB60, 0xCE040000, 0x8000FE70, 0x00000000, 0xA7860052,
+ 0x00000000, 0xC68000F8, 0xC13C0002, 0xCD03DE00, 0xC2020002, 0xC7E2A540, 0xC000FB60, 0xCE0400F8,
+ 0x8000FE18, 0xC2040002, 0xC000FB60, 0xCE044200, 0x8000FDF8, 0xC2C80002, 0x6AC56000, 0xDACC00F8,
+ 0xC000ABD4, 0xCB4400F8, 0xC000ABC8, 0xCB8400F8, 0xC000E838, 0xC3C00000, 0xCBC40038, 0x5EF40004,
+ 0x84000022, 0xC3000000, 0xC000FACC, 0xCF042100, 0x47F98000, 0x8400002A, 0x47F98000, 0x88000030,
+ 0xC1006E8C, 0x8000BCB8, 0xC000ABC0, 0xCC8400F8, 0x8000F6C8, 0xC000FAC0, 0xCAC400F8, 0xC000ABD4,
+ 0xCB4400F8, 0xA6C0FBD2, 0x00000000, 0x5EF40000, 0x8400F722, 0x5EF40002, 0x8400F99A, 0x5EF40004,
+ 0x8400FB9A, 0xC1006CE8, 0x8000BC30, 0x00000000, 0xC0800000, 0xDF4B0038, 0xC0006900, 0xCB8000F8,
+ 0xC2000000, 0xC000690A, 0xA78000D0, 0xCBC000F8, 0xC1000000, 0xD90000F9, 0xC1000002, 0xD90C00F8,
+ 0x6FF46000, 0x477DA000, 0x5B749F00, 0xC2400000, 0x58340004, 0xCA400078, 0xC0006900, 0xCE000000,
+ 0x5A640002, 0x58340004, 0xC6500078, 0xCD000078, 0xC0006914, 0xCA4000F8, 0xC2000002, 0x6A3D0000,
+ 0x72612000, 0xCE4000F8, 0xC000E408, 0xCE0000F8, 0xA78200D8, 0xC0006908, 0xCBC000F8, 0xC1000000,
+ 0xD90000F9, 0xC1000002, 0xD90C00F8, 0x6FF4A000, 0x6FD44000, 0x4755A000, 0x477DA000, 0x5B747400,
+ 0xC2800000, 0x58340006, 0xCA800078, 0xC2000000, 0xC0006900, 0xCE002100, 0x5EA80002, 0x58340006,
+ 0xC6900078, 0xCD000078, 0x5A7C0020, 0xC2000002, 0x6A250000, 0xC000E408, 0xCE0000F8, 0xDCA800F9,
+ 0x5EA80000, 0x8400BAA0, 0x00000000, 0xA4800230, 0x00000000, 0xC3C00000, 0xC000F418, 0xCBC00018,
+ 0xC3400000, 0xC2400000, 0x6FF86000, 0x47BDC000, 0x5BB89F00, 0x58380008, 0xCB400078, 0x58380006,
+ 0xCA400078, 0x5F740002, 0x58380008, 0xC7500078, 0xCD000078, 0xC2000000, 0x58380004, 0xCA020078,
+ 0xC3000000, 0x5838000C, 0xCB000020, 0x5A640002, 0x46610000, 0x84000010, 0xC2400000, 0x58380006,
+ 0xC6500078, 0xCD000078, 0xC2000000, 0x5838000A, 0xCA020078, 0x5B300002, 0x5838000C, 0xC7100020,
+ 0xCD000020, 0xC2420020, 0x5A200004, 0x46252000, 0x84000010, 0xC2000000, 0x5838000A, 0xC6101078,
+ 0xCD021078, 0xC0006966, 0xCA4000F8, 0xC2000002, 0x6A3D0000, 0x72612000, 0xCE4000F8, 0x5F740000,
+ 0x84000040, 0xC0006912, 0xCA0000F8, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x762D0000, 0xCE0000F8,
+ 0x5F300020, 0x84000040, 0xC0006924, 0xCA0000F8, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x762D0000,
+ 0xCE0000F8, 0xA4820070, 0xC2400000, 0xC000F418, 0xCA408018, 0xC2000002, 0xC0006900, 0xCE000000,
+ 0xC000690A, 0xCE4000F8, 0xC1000000, 0xD90000F9, 0xD8400078, 0xC1000004, 0xD90000F9, 0xA4840270,
+ 0x00000000, 0xC3C00000, 0xC000F418, 0xCBC10018, 0xC2800000, 0xC2000000, 0x6FF8A000, 0x6FD44000,
+ 0x4795C000, 0x47BDC000, 0x5BB87400, 0x5838002E, 0xCA800078, 0x58380006, 0xCA020078, 0xC3400000,
+ 0x5838002E, 0xCB420078, 0x5AA80002, 0x46A10000, 0x84000010, 0xC2800000, 0x5838002E, 0xC6900078,
+ 0xCD000078, 0x5F740002, 0x5838002E, 0xC7501078, 0xCD021078, 0xC0006968, 0xCA4000F8, 0xC2000002,
+ 0x6A3D0000, 0x72612000, 0xCE4000F8, 0xC000692A, 0xCA8000F8, 0x5E740000, 0x84000040, 0xC0006910,
+ 0xCA0000F8, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x762D0000, 0xCE0000F8, 0x6ABD4010, 0xA68000BA,
+ 0x00000000, 0x58380032, 0xCA0000F8, 0x58000002, 0xCA4000F8, 0x5838000C, 0x00000000, 0xCE0000F9,
+ 0xCE4000F8, 0xC000692A, 0xCA0000F8, 0xC2C00002, 0x6AFD6000, 0x722D0000, 0xCE0000F8, 0xC000692C,
+ 0xCA0000F8, 0xC2C00002, 0x6AFD6000, 0x722D0000, 0xCE0000F8, 0x80000040, 0xC000692C, 0xCA0000F8,
+ 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x762D0000, 0xCE0000F8, 0xA4880120, 0xC2C00000, 0xC000F418,
+ 0xCAC20018, 0xC000690E, 0xCA4000F8, 0xC2000002, 0x6A2D0000, 0x7E010000, 0x76612000, 0xCE4000F8,
+ 0xC000696A, 0xCA4000F8, 0xC2000002, 0x6A2D0000, 0x72612000, 0xCE4000F8, 0x6EF0A000, 0x6ED44000,
+ 0x47158000, 0x472D8000, 0x5B307400, 0x58300000, 0xCA0000F8, 0x00000000, 0xC2400002, 0x76612000,
+ 0x8400004A, 0xC24C0002, 0xC6E40018, 0xC624C400, 0x58300010, 0xCA400500, 0x00000000, 0xC000F800,
+ 0xCE4000F8, 0xA4860070, 0xC2400000, 0xC000F418, 0xCA418018, 0xC2020002, 0xC0006900, 0xCE002100,
+ 0xC0006908, 0xCE4000F8, 0xC1000000, 0xD90000F9, 0xD8400078, 0xC1000004, 0xD90000F9, 0xC000F414,
+ 0xCC8000F8, 0xC10E0002, 0xD90C00F8, 0x8000EDF0, 0xDFBC00F9, 0xC000696E, 0x99005C80, 0xC94000F8,
+ 0xC7D800F8, 0x00000000, 0xC57000F8, 0x5EF00020, 0x88000148, 0x6F346000, 0x4771A000, 0x5B749F00,
+ 0x58340008, 0xC2400000, 0xCA400078, 0x00000000, 0xC2000000, 0x5A640002, 0xCE400078, 0x58340004,
+ 0xCA000078, 0x00000000, 0x00000000, 0x5E200002, 0xCE000078, 0xC0006912, 0xCA8000F8, 0xC2400002,
+ 0x6A712000, 0x72A54000, 0xCE8000F8, 0x5E200000, 0x84000052, 0xC000402A, 0xCA0000F8, 0xC000E408,
+ 0xCA8000F8, 0x76250000, 0x00000000, 0x72A14000, 0xCE8000F8, 0x80000038, 0xC0006914, 0xCA0000F8,
+ 0x7E412000, 0x00000000, 0x76250000, 0xCE0000F8, 0x800000D0, 0x6EF4A000, 0x6ED44000, 0x4755A000,
+ 0x476DA000, 0x5B747400, 0x5834002E, 0xC2400000, 0xCA420078, 0x00000000, 0xC2000000, 0x5A640002,
+ 0xC6501078, 0xCD021078, 0x58340006, 0xCA000078, 0x00000000, 0x00000000, 0x5A200002, 0xCE000078,
+ 0xC0006910, 0xCA4000F8, 0xC2000002, 0x6A2D0000, 0x72612000, 0xCE4000F8, 0xC2000002, 0x6A310000,
+ 0xC000E42A, 0xCE0000F8, 0xC1040002, 0xD90C00F8, 0x00000000, 0x8000EB60, 0x00000000, 0xC4980928,
+ 0x9D000000, 0xC5580038, 0xC000E838, 0xCD8400F8, 0xC1440080, 0xC1C06B40, 0xC55C0F80, 0xC000F00E,
+ 0x9D000000, 0xCD8000F8, 0xC000F00C, 0xCDC000F8, 0xC000ABDE, 0xC9C000F8, 0x00000000, 0x00000000,
+ 0xD9D800F9, 0xC000AB40, 0x401C0000, 0x5DC0ABC0, 0x88000012, 0x5C000080, 0xCD8000F8, 0xC1F0000A,
+ 0x715CA000, 0xDD9800F8, 0xDD9C00F9, 0x41D8E000, 0xC5D40260, 0xC000F010, 0xCD4000F8, 0x6C9C8000,
+ 0x45C8E000, 0x45C8E000, 0x59DC0004, 0xC1601260, 0xC5D40260, 0x9D000000, 0xC000F012, 0xCD4000F8,
+ 0x00000000, 0x00000000, 0xD95800F8, 0x6D586000, 0x4594C000, 0x59989F00, 0xD99800F9, 0x5818000A,
+ 0xC1800000, 0xC9800078, 0xC0007200, 0x6D5CA000, 0x401C0000, 0x40180000, 0xC94000F8, 0x58000002,
+ 0x00000000, 0xC9C000F8, 0xC0006930, 0xCD4000F8, 0xC0006932, 0xCDC000F8, 0x59980004, 0xC1C20020,
+ 0xB59C0018, 0x00000000, 0xC1800000, 0xDD9C00F9, 0x581C000A, 0xCD800078, 0x581C000C, 0xC1800000,
+ 0xC9800020, 0xC1C00002, 0xDD9400F8, 0x69D4E000, 0x5D980002, 0xCD800020, 0xC0006924, 0xC98000F8,
+ 0x00000000, 0x9D000000, 0x00000000, 0x719CC000, 0xCD8000F8, 0xC000692A, 0xC94000F8, 0xC1C00002,
+ 0x69D8E000, 0x7DC0C000, 0x7558A000, 0xCD4000F8, 0xC000692C, 0xC94000F8, 0xDD8000F9, 0x58000032,
+ 0x755CA000, 0x84000090, 0xC94000F9, 0xC98000F8, 0xDD8000F9, 0x5800000C, 0x00000000, 0xCD4000F9,
+ 0xCD8000F8, 0xC000692C, 0xC94000F8, 0xC000692A, 0xC98000F8, 0x715CA000, 0xC000692C, 0xCD4000F8,
+ 0x719CC000, 0xC000692A, 0xCD8000F8, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0xC000ABDE,
+ 0xC98000F8, 0x00000000, 0xC1C00080, 0x4194C000, 0x459CE000, 0x88000012, 0xC5D800F8, 0xC000ABDE,
+ 0xCD8000F8, 0xC000F406, 0xC98000F8, 0xC1C00002, 0x9D000000, 0xC5D80A00, 0xC5581048, 0xCD8000F8,
+ 0xC0006930, 0xC98000F8, 0xC0006932, 0xC9C000F8, 0xC140000E, 0xC5581C18, 0xDD9400F8, 0xC000AB40,
+ 0x40140000, 0x5D40ABC0, 0x88000012, 0x5C000080, 0xCD8000F8, 0x58000002, 0x5D40ABC0, 0x88000012,
+ 0x5C000080, 0xCDC000F8, 0xDD5400F8, 0xC1C00000, 0x58140006, 0xC9C20078, 0xC1800000, 0x58140000,
+ 0xC98000D8, 0x6DDC2000, 0xC000691E, 0x41D8E000, 0xCDC000F8, 0xDD9800F8, 0xC1C00022, 0xC5D80D70,
+ 0xDD9400F9, 0xC5581C18, 0xC000691C, 0xCD8000F8, 0xDD5400F8, 0xC1C00000, 0x58140006, 0xC9C20078,
+ 0xC1800000, 0x58140004, 0xC9820078, 0x00000000, 0x59DC0002, 0x45D8C000, 0x84000010, 0xC1C00000,
+ 0x9D000000, 0x58140006, 0xC5D81078, 0xCD821078, 0xC000ABDC, 0xC94000F8, 0xC1820020, 0xC1D00002,
+ 0x5814AB00, 0xD58000F8, 0x58000002, 0xD58000F9, 0x59540004, 0xB5580018, 0xC000ABDC, 0xC1400000,
+ 0xCD4000F8, 0xDD9800F9, 0x9D000000, 0xDD9400F8, 0xC000F402, 0xCDC10800, 0xC1C00000, 0xC1800080,
+ 0x5D980004, 0xDF5D0048, 0x459CA000, 0x8800FFF2, 0xDD8000F9, 0x5800000C, 0x00000000, 0xC94000F9,
+ 0xC98000F8, 0xC1C00002, 0xC5D43F00, 0xC5D81E00, 0xC000ABDE, 0xC9C000F8, 0x00000000, 0x00000000,
+ 0x581CAB40, 0x5DC0ABC0, 0x88000012, 0x5C000080, 0xCD4000F8, 0x58000002, 0x5DC0ABC0, 0x88000012,
+ 0x5C000080, 0xCD8000F8, 0xC000ABDE, 0xC9C000F8, 0x00000000, 0xC15004C0, 0xC5D40060, 0xDD9C00F8,
+ 0xC5D41C18, 0xC1C00000, 0xDD8000F9, 0x58000030, 0xC9C00078, 0xDD8000F9, 0x58000002, 0xC98000F8,
+ 0x6DDC2000, 0xC000691C, 0x41D8E000, 0xCD4000F9, 0xCDC000F8, 0xDD9400F9, 0xC1C00000, 0x58140030,
+ 0xC9C00078, 0xC1800000, 0x58140006, 0xC9820078, 0x00000000, 0x59DC0002, 0x45D8C000, 0x84000010,
+ 0xC1C00000, 0x9D000000, 0x58140030, 0xC5D80078, 0xCD800078, 0xC1C00000, 0xDF5C0038, 0x5DDC0020,
+ 0x8400FFEA, 0x00000000, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0xC160FFFE, 0xC000EA10,
+ 0xC9440070, 0xC1A0FFFE, 0x59983408, 0xC000F00C, 0xCD4000F8, 0xC000F00E, 0xCD8000F8, 0xC0006964,
+ 0xC98000F8, 0x00000000, 0xC170000A, 0x7158A000, 0x6C988000, 0x4588C000, 0x4588C000, 0x59980004,
+ 0xC5940270, 0xC000F010, 0xCD4000F8, 0xC0006946, 0xC94000F8, 0x00000000, 0x00000000, 0x6D58A000,
+ 0x6D5C4000, 0x459CC000, 0x4594C000, 0xC000694A, 0xC94000F8, 0xC0006948, 0xC9C000F8, 0x4194C000,
+ 0xC1400012, 0xC55C1818, 0x9D000000, 0xC59C0268, 0xC000F012, 0xCDC000F8, 0xC1400000, 0x58000012,
+ 0xC9410038, 0xC0006950, 0xC9C000F8, 0xC55800F8, 0xC5940838, 0xC5581078, 0xD99400F8, 0xC000693C,
+ 0xC94000F8, 0xC0006954, 0xC98000F8, 0x59DC00A8, 0x45D4E000, 0x41D8E000, 0x5D5C0030, 0x88000010,
+ 0xC1C00030, 0xC1800000, 0xC5D84028, 0xC1400000, 0xC5D40008, 0x5DD40002, 0x84000072, 0x5DD40004,
+ 0x8400009A, 0x5DD40006, 0x840000C2, 0x5DD80026, 0x840000EA, 0xDD5400F8, 0xDD8000F9, 0x58000008,
+ 0x40180000, 0xCD4000F8, 0x59980002, 0x8000FFC0, 0xDD5400F8, 0xDD8000F9, 0x58000008, 0x40180000,
+ 0xCD4000B8, 0x59980002, 0x8000FF88, 0xDD5400F8, 0xDD8000F9, 0x58000008, 0x40180000, 0xCD400078,
+ 0x59980002, 0x8000FF50, 0xDD5400F8, 0xDD8000F9, 0x58000008, 0x40180000, 0xCD400038, 0x59980002,
+ 0x8000FF18, 0x00000000, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0x58000012, 0xC94000F8,
+ 0xC0006954, 0xC9C000F8, 0xC0006950, 0xC9400078, 0xDD8000F9, 0x58000028, 0x5D9C0000, 0x84000052,
+ 0x5D9C0002, 0x84000052, 0x5D9C0004, 0x8400006A, 0xC55B0038, 0xC55C08B8, 0xCD800039, 0xCDC108B8,
+ 0x80000060, 0xCD4000F8, 0x80000050, 0xC55900B8, 0xC55C1838, 0xCD8000B9, 0xCDC31838, 0x80000028,
+ 0xC55A0078, 0xC55C1078, 0xCD800079, 0xCDC21078, 0x9D000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x59540002, 0x6994E018, 0x61C0C008, 0x4194A000, 0x5D940040, 0x88000012, 0xC59400F8, 0x9D000000,
+ 0xCD4000F8, 0x00000000, 0x00000000, 0xC000697E, 0xCA4000F8, 0xC0000000, 0xC55800F8, 0xC9D400F9,
+ 0x00000000, 0x00000000, 0x79E08000, 0xCD1800F9, 0xC5D000F8, 0xC9D400F9, 0xC66000F8, 0xC52160A0,
+ 0xC5241550, 0x79E08000, 0xCD1800F9, 0xC5D000F8, 0xC9D400F9, 0xC66000F8, 0xC52160A0, 0xC5241550,
+ 0x79E08000, 0xCD1800F9, 0xC5D000F8, 0xC9D400F9, 0xC66000F8, 0xC52160A0, 0xC5241550, 0x79E08000,
+ 0xCD1800F9, 0xC5D000F8, 0xC9D400F9, 0xC66000F8, 0xC52160A0, 0xC5241550, 0x79E08000, 0xCD1800F9,
+ 0xC5D000F8, 0xC9D400F9, 0xC66000F8, 0xC52160A0, 0xC5241550, 0x79E08000, 0xCD1800F9, 0xC5D000F8,
+ 0xC9D400F9, 0xC66000F8, 0xC52160A0, 0xC5241550, 0x79E08000, 0xCD1800F9, 0xC5D000F8, 0xC9D400F9,
+ 0xC66000F8, 0xC52160A0, 0xC5241550, 0x79E08000, 0xCD1800F9, 0xC5D000F8, 0xC9D400F9, 0xC66000F8,
+ 0xC52160A0, 0xC5241550, 0x79E08000, 0xCD1800F9, 0xC5D000F8, 0xC9D400F9, 0xC66000F8, 0xC52160A0,
+ 0xC5241550, 0x79E08000, 0xCD1800F9, 0xC5D000F8, 0xC9D400F9, 0xC66000F8, 0xC52160A0, 0xC5241550,
+ 0x79E08000, 0xCD1800F9, 0xC5D000F8, 0xC9D400F9, 0xC66000F8, 0xC52160A0, 0xC5241550, 0x79E08000,
+ 0xCD1800F9, 0xC5D000F8, 0xC9D400F9, 0xC66000F8, 0xC52160A0, 0xC5241550, 0xC000697C, 0x9CC00000,
+ 0xCE0000F8, 0xC000697E, 0xCE4000F8, 0x9D000000, 0x4158A000, 0xCD4000F8, 0x00000000,
+};
+
+static u32 firmware_binary_data[] = {
+};
+
+
+#endif // IFXMIPS_ATM_FW_VR9_H
+
diff --git a/package/ltq-dsl/src/ifxmips_atm_ppe_amazon_se.h b/package/ltq-dsl/src/ifxmips_atm_ppe_amazon_se.h
new file mode 100644
index 000000000..b9ba2c7eb
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_ppe_amazon_se.h
@@ -0,0 +1,94 @@
+#ifndef IFXMIPS_ATM_PPE_AMAZON_SE_H
+#define IFXMIPS_ATM_PPE_AMAZON_SE_H
+
+
+
+/*
+ * FPI Configuration Bus Register and Memory Address Mapping
+ */
+#define IFX_PPE (KSEG1 | 0x1E180000)
+#define PP32_DEBUG_REG_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0000) << 2)))
+#define PPM_INT_REG_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0030) << 2)))
+#define PP32_INTERNAL_RES_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0040) << 2)))
+#define CDM_CODE_MEMORY(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x1000) << 2)))
+#define PPE_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x4000) << 2)))
+#define CDM_DATA_MEMORY(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x5000) << 2)))
+#define PPM_INT_UNIT_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6000) << 2)))
+#define PPM_TIMER0_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6100) << 2)))
+#define PPM_TASK_IND_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6200) << 2)))
+#define PPS_BRK_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6300) << 2)))
+#define PPM_TIMER1_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6400) << 2)))
+#define SB_RAM0_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x8200) << 2)))
+#define SB_RAM1_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x8C00) << 2)))
+#define QSB_CONF_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0xC000) << 2)))
+
+/*
+ * DWORD-Length of Memory Blocks
+ */
+#define PP32_DEBUG_REG_DWLEN 0x0030
+#define PPM_INT_REG_DWLEN 0x0010
+#define PP32_INTERNAL_RES_DWLEN 0x00C0
+#define CDM_CODE_MEMORYn_DWLEN(n) ((n) == 0 ? 0x1000 : 0x0800)
+#define PPE_REG_DWLEN 0x1000
+#define CDM_DATA_MEMORY_DWLEN CDM_CODE_MEMORYn_DWLEN(1)
+#define PPM_INT_UNIT_DWLEN 0x0100
+#define PPM_TIMER0_DWLEN 0x0100
+#define PPM_TASK_IND_REG_DWLEN 0x0100
+#define PPS_BRK_DWLEN 0x0100
+#define PPM_TIMER1_DWLEN 0x0100
+#define SB_RAM0_DWLEN 0x0A00
+#define SB_RAM1_DWLEN 0x0A00
+#define QSB_CONF_REG_DWLEN 0x0100
+
+/*
+ * PP32 to FPI Address Mapping
+ */
+#define SB_BUFFER(__sb_addr) ((volatile unsigned int *)((((__sb_addr) >= 0x2200) && ((__sb_addr) <= 0x2BFF)) ? SB_RAM0_ADDR((__sb_addr) - 0x2200) : \
+ (((__sb_addr) >= 0x2C00) && ((__sb_addr) <= 0x35FF)) ? SB_RAM1_ADDR((__sb_addr) - 0x2C00) : \
+ 0))
+
+/*
+ * PP32 Debug Control Register
+ */
+#define PP32_DBG_CTRL PP32_DEBUG_REG_ADDR(0, 0x0000)
+
+#define DBG_CTRL_RESTART 0
+#define DBG_CTRL_STOP 1
+
+#define PP32_HALT_STAT PP32_DEBUG_REG_ADDR(0, 0x0D00)
+#define PP32_BREAKPOINT_REASONS PP32_DEBUG_REG_ADDR(0, 0x0A00)
+
+#define PP32_BRK_SRC PP32_DEBUG_REG_ADDR(0, 0x0F00)
+
+#define PP32_DBG_CUR_PC PP32_DEBUG_REG_ADDR(0, 0x0F80)
+
+#define PP32_DBG_TASK_NO PP32_DEBUG_REG_ADDR(0, 0x0F81)
+
+/*
+ * Share Buffer
+ */
+#define SB_MST_PRI0 PPE_REG_ADDR(0x0300)
+#define SB_MST_PRI1 PPE_REG_ADDR(0x0301)
+
+/*
+ * EMA Registers
+ */
+#define EMA_CMDCFG PPE_REG_ADDR(0x0A00)
+#define EMA_DATACFG PPE_REG_ADDR(0x0A01)
+#define EMA_CMDCNT PPE_REG_ADDR(0x0A02)
+#define EMA_DATACNT PPE_REG_ADDR(0x0A03)
+#define EMA_ISR PPE_REG_ADDR(0x0A04)
+#define EMA_IER PPE_REG_ADDR(0x0A05)
+#define EMA_CFG PPE_REG_ADDR(0x0A06)
+#define EMA_SUBID PPE_REG_ADDR(0x0A07)
+
+#define EMA_ALIGNMENT 4
+
+/*
+ * Mailbox IGU1 Interrupt
+ */
+#define PPE_MAILBOX_IGU1_INT (INT_NUM_IM2_IRL0 + 13)
+
+
+
+#endif // IFXMIPS_ATM_PPE_AMAZON_SE_H
diff --git a/package/ltq-dsl/src/ifxmips_atm_ppe_ar9.h b/package/ltq-dsl/src/ifxmips_atm_ppe_ar9.h
new file mode 100644
index 000000000..5c5bfa826
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_ppe_ar9.h
@@ -0,0 +1,188 @@
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_ppe_ar9.h
+** PROJECT : UEIP
+** MODULES : ATM (ADSL)
+**
+** DATE : 1 AUG 2005
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM Driver (PPE Registers)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 4 AUG 2005 Xu Liang Initiate Version
+** 23 OCT 2006 Xu Liang Add GPL header.
+** 9 JAN 2007 Xu Liang First version got from Anand (IC designer)
+*******************************************************************************/
+
+
+
+#ifndef IFXMIPS_ATM_PPE_AR9_H
+#define IFXMIPS_ATM_PPE_AR9_H
+
+
+
+/*
+ * FPI Configuration Bus Register and Memory Address Mapping
+ */
+#define IFX_PPE (KSEG1 | 0x1E180000)
+#define PP32_DEBUG_REG_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0000) << 2)))
+#define PPM_INT_REG_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0030) << 2)))
+#define PP32_INTERNAL_RES_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0040) << 2)))
+#define CDM_CODE_MEMORY(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x1000) << 2)))
+#define PPE_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x4000) << 2)))
+#define CDM_DATA_MEMORY(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x5000) << 2)))
+#define PPM_INT_UNIT_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6000) << 2)))
+#define PPM_TIMER0_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6100) << 2)))
+#define PPM_TASK_IND_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6200) << 2)))
+#define PPS_BRK_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6300) << 2)))
+#define PPM_TIMER1_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6400) << 2)))
+#define SB_RAM0_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x8000) << 2)))
+#define SB_RAM1_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x8800) << 2)))
+#define SB_RAM2_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x9000) << 2)))
+#define SB_RAM3_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x9800) << 2)))
+#define SB_RAM4_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0xA000) << 2)))
+#define QSB_CONF_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0xC000) << 2)))
+
+/*
+ * DWORD-Length of Memory Blocks
+ */
+#define PP32_DEBUG_REG_DWLEN 0x0030
+#define PPM_INT_REG_DWLEN 0x0010
+#define PP32_INTERNAL_RES_DWLEN 0x00C0
+#define CDM_CODE_MEMORYn_DWLEN(n) 0x1000
+#define PPE_REG_DWLEN 0x1000
+#define CDM_DATA_MEMORY_DWLEN CDM_CODE_MEMORYn_DWLEN(1)
+#define PPM_INT_UNIT_DWLEN 0x0100
+#define PPM_TIMER0_DWLEN 0x0100
+#define PPM_TASK_IND_REG_DWLEN 0x0100
+#define PPS_BRK_DWLEN 0x0100
+#define PPM_TIMER1_DWLEN 0x0100
+#define SB_RAM0_DWLEN 0x0800
+#define SB_RAM1_DWLEN 0x0800
+#define SB_RAM2_DWLEN 0x0800
+#define SB_RAM3_DWLEN 0x0800
+#define SB_RAM4_DWLEN 0x0C00
+#define QSB_CONF_REG_DWLEN 0x0100
+
+/*
+ * PP32 to FPI Address Mapping
+ */
+#define SB_BUFFER(__sb_addr) ((volatile unsigned int *)((((__sb_addr) >= 0x0000) && ((__sb_addr) <= 0x0FFF)) ? PPE_REG_ADDR((__sb_addr)): \
+ (((__sb_addr) >= 0x2000) && ((__sb_addr) <= 0x27FF)) ? SB_RAM0_ADDR((__sb_addr) - 0x2000) : \
+ (((__sb_addr) >= 0x2800) && ((__sb_addr) <= 0x2FFF)) ? SB_RAM1_ADDR((__sb_addr) - 0x2800) : \
+ (((__sb_addr) >= 0x3000) && ((__sb_addr) <= 0x37FF)) ? SB_RAM2_ADDR((__sb_addr) - 0x3000) : \
+ (((__sb_addr) >= 0x3800) && ((__sb_addr) <= 0x3FFF)) ? SB_RAM3_ADDR((__sb_addr) - 0x3800) : \
+ (((__sb_addr) >= 0x4000) && ((__sb_addr) <= 0x4BFF)) ? SB_RAM4_ADDR((__sb_addr) - 0x4000) : \
+ 0))
+
+/*
+ * PP32 Debug Control Register
+ */
+#define NUM_OF_PP32 1
+
+#define PP32_DBG_CTRL(n) PP32_DEBUG_REG_ADDR(n, 0x0000)
+
+#define DBG_CTRL_RESTART 0
+#define DBG_CTRL_STOP 1
+
+#define PP32_CTRL_CMD(n) PP32_DEBUG_REG_ADDR(n, 0x0B00)
+ #define PP32_CTRL_CMD_RESTART (1 << 0)
+ #define PP32_CTRL_CMD_STOP (1 << 1)
+ #define PP32_CTRL_CMD_STEP (1 << 2)
+ #define PP32_CTRL_CMD_BREAKOUT (1 << 3)
+
+#define PP32_CTRL_OPT(n) PP32_DEBUG_REG_ADDR(n, 0x0C00)
+ #define PP32_CTRL_OPT_BREAKOUT_ON_STOP_ON (3 << 0)
+ #define PP32_CTRL_OPT_BREAKOUT_ON_STOP_OFF (2 << 0)
+ #define PP32_CTRL_OPT_BREAKOUT_ON_BREAKIN_ON (3 << 2)
+ #define PP32_CTRL_OPT_BREAKOUT_ON_BREAKIN_OFF (2 << 2)
+ #define PP32_CTRL_OPT_STOP_ON_BREAKIN_ON (3 << 4)
+ #define PP32_CTRL_OPT_STOP_ON_BREAKIN_OFF (2 << 4)
+ #define PP32_CTRL_OPT_STOP_ON_BREAKPOINT_ON (3 << 6)
+ #define PP32_CTRL_OPT_STOP_ON_BREAKPOINT_OFF (2 << 6)
+ #define PP32_CTRL_OPT_BREAKOUT_ON_STOP(n) (*PP32_CTRL_OPT(n) & (1 << 0))
+ #define PP32_CTRL_OPT_BREAKOUT_ON_BREAKIN(n) (*PP32_CTRL_OPT(n) & (1 << 2))
+ #define PP32_CTRL_OPT_STOP_ON_BREAKIN(n) (*PP32_CTRL_OPT(n) & (1 << 4))
+ #define PP32_CTRL_OPT_STOP_ON_BREAKPOINT(n) (*PP32_CTRL_OPT(n) & (1 << 6))
+
+#define PP32_BRK_PC(n, i) PP32_DEBUG_REG_ADDR(n, 0x0900 + (i) * 2)
+#define PP32_BRK_PC_MASK(n, i) PP32_DEBUG_REG_ADDR(n, 0x0901 + (i) * 2)
+#define PP32_BRK_DATA_ADDR(n, i) PP32_DEBUG_REG_ADDR(n, 0x0904 + (i) * 2)
+#define PP32_BRK_DATA_ADDR_MASK(n, i) PP32_DEBUG_REG_ADDR(n, 0x0905 + (i) * 2)
+#define PP32_BRK_DATA_VALUE_RD(n, i) PP32_DEBUG_REG_ADDR(n, 0x0908 + (i) * 2)
+#define PP32_BRK_DATA_VALUE_RD_MASK(n, i) PP32_DEBUG_REG_ADDR(n, 0x0909 + (i) * 2)
+#define PP32_BRK_DATA_VALUE_WR(n, i) PP32_DEBUG_REG_ADDR(n, 0x090C + (i) * 2)
+#define PP32_BRK_DATA_VALUE_WR_MASK(n, i) PP32_DEBUG_REG_ADDR(n, 0x090D + (i) * 2)
+ #define PP32_BRK_CONTEXT_MASK(i) (1 << (i))
+ #define PP32_BRK_CONTEXT_MASK_EN (1 << 4)
+ #define PP32_BRK_COMPARE_GREATER_EQUAL (1 << 5) // valid for break data value rd/wr only
+ #define PP32_BRK_COMPARE_LOWER_EQUAL (1 << 6)
+ #define PP32_BRK_COMPARE_EN (1 << 7)
+
+#define PP32_BRK_TRIG(n) PP32_DEBUG_REG_ADDR(n, 0x0F00)
+ #define PP32_BRK_GRPi_PCn_ON(i, n) ((3 << ((n) * 2)) << ((i) * 16))
+ #define PP32_BRK_GRPi_PCn_OFF(i, n) ((2 << ((n) * 2)) << ((i) * 16))
+ #define PP32_BRK_GRPi_DATA_ADDRn_ON(i, n) ((3 << ((n) * 2 + 4)) << ((i) * 16))
+ #define PP32_BRK_GRPi_DATA_ADDRn_OFF(i, n) ((2 << ((n) * 2 + 4)) << ((i) * 16))
+ #define PP32_BRK_GRPi_DATA_VALUE_RDn_ON(i, n) ((3 << ((n) * 2 + 8)) << ((i) * 16))
+ #define PP32_BRK_GRPi_DATA_VALUE_RDn_OFF(i, n)((2 << ((n) * 2 + 8)) << ((i) * 16))
+ #define PP32_BRK_GRPi_DATA_VALUE_WRn_ON(i, n) ((3 << ((n) * 2 + 12)) << ((i) * 16))
+ #define PP32_BRK_GRPi_DATA_VALUE_WRn_OFF(i, n)((2 << ((n) * 2 + 12)) << ((i) * 16))
+ #define PP32_BRK_GRPi_PCn(k, i, n) (*PP32_BRK_TRIG(k) & ((1 << ((n))) << ((i) * 8)))
+ #define PP32_BRK_GRPi_DATA_ADDRn(k, i, n) (*PP32_BRK_TRIG(k) & ((1 << ((n) + 2)) << ((i) * 8)))
+ #define PP32_BRK_GRPi_DATA_VALUE_RDn(k, i, n) (*PP32_BRK_TRIG(k) & ((1 << ((n) + 4)) << ((i) * 8)))
+ #define PP32_BRK_GRPi_DATA_VALUE_WRn(k, i, n) (*PP32_BRK_TRIG(k) & ((1 << ((n) + 6)) << ((i) * 8)))
+
+#define PP32_CPU_STATUS(n) PP32_DEBUG_REG_ADDR(n, 0x0D00)
+#define PP32_HALT_STAT(n) PP32_CPU_STATUS(n)
+#define PP32_DBG_CUR_PC(n) PP32_CPU_STATUS(n)
+ #define PP32_CPU_USER_STOPPED(n) (*PP32_CPU_STATUS(n) & (1 << 0))
+ #define PP32_CPU_USER_BREAKIN_RCV(n) (*PP32_CPU_STATUS(n) & (1 << 1))
+ #define PP32_CPU_USER_BREAKPOINT_MET(n) (*PP32_CPU_STATUS(n) & (1 << 2))
+ #define PP32_CPU_CUR_PC(n) (*PP32_CPU_STATUS(n) >> 16)
+
+#define PP32_BREAKPOINT_REASONS(n) PP32_DEBUG_REG_ADDR(n, 0x0A00)
+ #define PP32_BRK_PC_MET(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << (i)))
+ #define PP32_BRK_DATA_ADDR_MET(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) + 2)))
+ #define PP32_BRK_DATA_VALUE_RD_MET(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) + 4)))
+ #define PP32_BRK_DATA_VALUE_WR_MET(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) + 6)))
+ #define PP32_BRK_DATA_VALUE_RD_LO_EQ(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) * 2 + 8)))
+ #define PP32_BRK_DATA_VALUE_RD_GT_EQ(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) * 2 + 9)))
+ #define PP32_BRK_DATA_VALUE_WR_LO_EQ(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) * 2 + 12)))
+ #define PP32_BRK_DATA_VALUE_WR_GT_EQ(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) * 2 + 13)))
+ #define PP32_BRK_CUR_CONTEXT(n) ((*PP32_BREAKPOINT_REASONS(n) >> 16) & 0x03)
+
+#define PP32_GP_REG_BASE(n) PP32_DEBUG_REG_ADDR(n, 0x0E00)
+#define PP32_GP_CONTEXTi_REGn(n, i, j) PP32_DEBUG_REG_ADDR(n, 0x0E00 + (i) * 16 + (j))
+
+/*
+ * EMA Registers
+ */
+#define EMA_CMDCFG PPE_REG_ADDR(0x0A00)
+#define EMA_DATACFG PPE_REG_ADDR(0x0A01)
+#define EMA_CMDCNT PPE_REG_ADDR(0x0A02)
+#define EMA_DATACNT PPE_REG_ADDR(0x0A03)
+#define EMA_ISR PPE_REG_ADDR(0x0A04)
+#define EMA_IER PPE_REG_ADDR(0x0A05)
+#define EMA_CFG PPE_REG_ADDR(0x0A06)
+#define EMA_SUBID PPE_REG_ADDR(0x0A07)
+
+#define EMA_ALIGNMENT 4
+
+/*
+ * Mailbox IGU1 Interrupt
+ */
+#define PPE_MAILBOX_IGU1_INT INT_NUM_IM2_IRL0 + 24
+
+
+
+#endif // IFXMIPS_ATM_PPE_AR9_H
diff --git a/package/ltq-dsl/src/ifxmips_atm_ppe_common.h b/package/ltq-dsl/src/ifxmips_atm_ppe_common.h
new file mode 100644
index 000000000..30b12c80d
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_ppe_common.h
@@ -0,0 +1,365 @@
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_ppe_common.h
+** PROJECT : UEIP
+** MODULES : ATM (ADSL)
+**
+** DATE : 1 AUG 2005
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM Driver (PPE Registers)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 4 AUG 2005 Xu Liang Initiate Version
+** 23 OCT 2006 Xu Liang Add GPL header.
+** 9 JAN 2007 Xu Liang First version got from Anand (IC designer)
+*******************************************************************************/
+
+
+
+#ifndef IFXMIPS_ATM_PPE_COMMON_H
+#define IFXMIPS_ATM_PPE_COMMON_H
+#if defined(CONFIG_DANUBE)
+ #include "ifxmips_atm_ppe_danube.h"
+#elif defined(CONFIG_AMAZON_SE)
+ #include "ifxmips_atm_ppe_amazon_se.h"
+#elif defined(CONFIG_AR9)
+ #include "ifxmips_atm_ppe_ar9.h"
+#elif defined(CONFIG_VR9)
+ #include "ifxmips_atm_ppe_vr9.h"
+#else
+ #error Platform is not specified!
+#endif
+
+
+
+/*
+ * Code/Data Memory (CDM) Interface Configuration Register
+ */
+#define CDM_CFG PPE_REG_ADDR(0x0100)
+
+#define CDM_CFG_RAM1 GET_BITS(*CDM_CFG, 3, 2)
+#define CDM_CFG_RAM0 (*CDM_CFG & (1 << 1))
+
+#define CDM_CFG_RAM1_SET(value) SET_BITS(0, 3, 2, value)
+#define CDM_CFG_RAM0_SET(value) ((value) ? (1 << 1) : 0)
+
+/*
+ * QSB Internal Cell Delay Variation Register
+ */
+#define QSB_ICDV QSB_CONF_REG_ADDR(0x0007)
+
+#define QSB_ICDV_TAU GET_BITS(*QSB_ICDV, 5, 0)
+
+#define QSB_ICDV_TAU_SET(value) SET_BITS(0, 5, 0, value)
+
+/*
+ * QSB Scheduler Burst Limit Register
+ */
+#define QSB_SBL QSB_CONF_REG_ADDR(0x0009)
+
+#define QSB_SBL_SBL GET_BITS(*QSB_SBL, 3, 0)
+
+#define QSB_SBL_SBL_SET(value) SET_BITS(0, 3, 0, value)
+
+/*
+ * QSB Configuration Register
+ */
+#define QSB_CFG QSB_CONF_REG_ADDR(0x000A)
+
+#define QSB_CFG_TSTEPC GET_BITS(*QSB_CFG, 1, 0)
+
+#define QSB_CFG_TSTEPC_SET(value) SET_BITS(0, 1, 0, value)
+
+/*
+ * QSB RAM Transfer Table Register
+ */
+#define QSB_RTM QSB_CONF_REG_ADDR(0x000B)
+
+#define QSB_RTM_DM (*QSB_RTM)
+
+#define QSB_RTM_DM_SET(value) ((value) & 0xFFFFFFFF)
+
+/*
+ * QSB RAM Transfer Data Register
+ */
+#define QSB_RTD QSB_CONF_REG_ADDR(0x000C)
+
+#define QSB_RTD_TTV (*QSB_RTD)
+
+#define QSB_RTD_TTV_SET(value) ((value) & 0xFFFFFFFF)
+
+/*
+ * QSB RAM Access Register
+ */
+#define QSB_RAMAC QSB_CONF_REG_ADDR(0x000D)
+
+#define QSB_RAMAC_RW (*QSB_RAMAC & (1 << 31))
+#define QSB_RAMAC_TSEL GET_BITS(*QSB_RAMAC, 27, 24)
+#define QSB_RAMAC_LH (*QSB_RAMAC & (1 << 16))
+#define QSB_RAMAC_TESEL GET_BITS(*QSB_RAMAC, 9, 0)
+
+#define QSB_RAMAC_RW_SET(value) ((value) ? (1 << 31) : 0)
+#define QSB_RAMAC_TSEL_SET(value) SET_BITS(0, 27, 24, value)
+#define QSB_RAMAC_LH_SET(value) ((value) ? (1 << 16) : 0)
+#define QSB_RAMAC_TESEL_SET(value) SET_BITS(0, 9, 0, value)
+
+/*
+ * QSB Queue Scheduling and Shaping Definitions
+ */
+#define QSB_WFQ_NONUBR_MAX 0x3f00
+#define QSB_WFQ_UBR_BYPASS 0x3fff
+#define QSB_TP_TS_MAX 65472
+#define QSB_TAUS_MAX 64512
+#define QSB_GCR_MIN 18
+
+/*
+ * QSB Constant
+ */
+#define QSB_RAMAC_RW_READ 0
+#define QSB_RAMAC_RW_WRITE 1
+
+#define QSB_RAMAC_TSEL_QPT 0x01
+#define QSB_RAMAC_TSEL_SCT 0x02
+#define QSB_RAMAC_TSEL_SPT 0x03
+#define QSB_RAMAC_TSEL_VBR 0x08
+
+#define QSB_RAMAC_LH_LOW 0
+#define QSB_RAMAC_LH_HIGH 1
+
+#define QSB_QPT_SET_MASK 0x0
+#define QSB_QVPT_SET_MASK 0x0
+#define QSB_SET_SCT_MASK 0x0
+#define QSB_SET_SPT_MASK 0x0
+#define QSB_SET_SPT_SBVALID_MASK 0x7FFFFFFF
+
+#define QSB_SPT_SBV_VALID (1 << 31)
+#define QSB_SPT_PN_SET(value) (((value) & 0x01) ? (1 << 16) : 0)
+#define QSB_SPT_INTRATE_SET(value) SET_BITS(0, 13, 0, value)
+
+/*
+ * QSB Queue Parameter Table Entry and Queue VBR Parameter Table Entry
+ */
+#if defined(__BIG_ENDIAN)
+ union qsb_queue_parameter_table {
+ struct {
+ unsigned int res1 :1;
+ unsigned int vbr :1;
+ unsigned int wfqf :14;
+ unsigned int tp :16;
+ } bit;
+ u32 dword;
+ };
+
+ union qsb_queue_vbr_parameter_table {
+ struct {
+ unsigned int taus :16;
+ unsigned int ts :16;
+ } bit;
+ u32 dword;
+ };
+#else
+ union qsb_queue_parameter_table {
+ struct {
+ unsigned int tp :16;
+ unsigned int wfqf :14;
+ unsigned int vbr :1;
+ unsigned int res1 :1;
+ } bit;
+ u32 dword;
+ };
+
+ union qsb_queue_vbr_parameter_table {
+ struct {
+ unsigned int ts :16;
+ unsigned int taus :16;
+ } bit;
+ u32 dword;
+ };
+#endif // defined(__BIG_ENDIAN)
+
+/*
+ * Mailbox IGU0 Registers
+ */
+#define MBOX_IGU0_ISRS PPE_REG_ADDR(0x0200)
+#define MBOX_IGU0_ISRC PPE_REG_ADDR(0x0201)
+#define MBOX_IGU0_ISR PPE_REG_ADDR(0x0202)
+#define MBOX_IGU0_IER PPE_REG_ADDR(0x0203)
+
+#define MBOX_IGU0_ISRS_SET(n) (1 << (n))
+#define MBOX_IGU0_ISRC_CLEAR(n) (1 << (n))
+#define MBOX_IGU0_ISR_ISR(n) (*MBOX_IGU0_ISR & (1 << (n)))
+#define MBOX_IGU0_IER_EN(n) (*MBOX_IGU0_IER & (1 << (n)))
+#define MBOX_IGU0_IER_EN_SET(n) (1 << (n))
+
+/*
+ * Mailbox IGU1 Registers
+ */
+#define MBOX_IGU1_ISRS PPE_REG_ADDR(0x0204)
+#define MBOX_IGU1_ISRC PPE_REG_ADDR(0x0205)
+#define MBOX_IGU1_ISR PPE_REG_ADDR(0x0206)
+#define MBOX_IGU1_IER PPE_REG_ADDR(0x0207)
+
+#define MBOX_IGU1_ISRS_SET(n) (1 << (n))
+#define MBOX_IGU1_ISRC_CLEAR(n) (1 << (n))
+#define MBOX_IGU1_ISR_ISR(n) (*MBOX_IGU1_ISR & (1 << (n)))
+#define MBOX_IGU1_IER_EN(n) (*MBOX_IGU1_IER & (1 << (n)))
+#define MBOX_IGU1_IER_EN_SET(n) (1 << (n))
+
+/*
+ * Mailbox IGU3 Registers
+ */
+#define MBOX_IGU3_ISRS PPE_REG_ADDR(0x0214)
+#define MBOX_IGU3_ISRC PPE_REG_ADDR(0x0215)
+#define MBOX_IGU3_ISR PPE_REG_ADDR(0x0216)
+#define MBOX_IGU3_IER PPE_REG_ADDR(0x0217)
+
+#define MBOX_IGU3_ISRS_SET(n) (1 << (n))
+#define MBOX_IGU3_ISRC_CLEAR(n) (1 << (n))
+#define MBOX_IGU3_ISR_ISR(n) (*MBOX_IGU3_ISR & (1 << (n)))
+#define MBOX_IGU3_IER_EN(n) (*MBOX_IGU3_IER & (1 << (n)))
+#define MBOX_IGU3_IER_EN_SET(n) (1 << (n))
+
+/*
+ * RTHA/TTHA Registers
+ */
+#define RFBI_CFG PPE_REG_ADDR(0x0400)
+#define RBA_CFG0 PPE_REG_ADDR(0x0404)
+#define RBA_CFG1 PPE_REG_ADDR(0x0405)
+#define RCA_CFG0 PPE_REG_ADDR(0x0408)
+#define RCA_CFG1 PPE_REG_ADDR(0x0409)
+#define RDES_CFG0 PPE_REG_ADDR(0x040C)
+#define RDES_CFG1 PPE_REG_ADDR(0x040D)
+#define SFSM_STATE0 PPE_REG_ADDR(0x0410)
+#define SFSM_STATE1 PPE_REG_ADDR(0x0411)
+#define SFSM_DBA0 PPE_REG_ADDR(0x0412)
+#define SFSM_DBA1 PPE_REG_ADDR(0x0413)
+#define SFSM_CBA0 PPE_REG_ADDR(0x0414)
+#define SFSM_CBA1 PPE_REG_ADDR(0x0415)
+#define SFSM_CFG0 PPE_REG_ADDR(0x0416)
+#define SFSM_CFG1 PPE_REG_ADDR(0x0417)
+#define SFSM_PGCNT0 PPE_REG_ADDR(0x041C)
+#define SFSM_PGCNT1 PPE_REG_ADDR(0x041D)
+#define FFSM_DBA0 PPE_REG_ADDR(0x0508)
+#define FFSM_DBA1 PPE_REG_ADDR(0x0509)
+#define FFSM_CFG0 PPE_REG_ADDR(0x050A)
+#define FFSM_CFG1 PPE_REG_ADDR(0x050B)
+#define FFSM_IDLE_HEAD_BC0 PPE_REG_ADDR(0x050E)
+#define FFSM_IDLE_HEAD_BC1 PPE_REG_ADDR(0x050F)
+#define FFSM_PGCNT0 PPE_REG_ADDR(0x0514)
+#define FFSM_PGCNT1 PPE_REG_ADDR(0x0515)
+
+/*
+ * PPE TC Logic Registers (partial)
+ */
+#define DREG_A_VERSION PPE_REG_ADDR(0x0D00)
+#define DREG_A_CFG PPE_REG_ADDR(0x0D01)
+#define DREG_AT_CTRL PPE_REG_ADDR(0x0D02)
+#define DREG_AT_CB_CFG0 PPE_REG_ADDR(0x0D03)
+#define DREG_AT_CB_CFG1 PPE_REG_ADDR(0x0D04)
+#define DREG_AR_CTRL PPE_REG_ADDR(0x0D08)
+#define DREG_AR_CB_CFG0 PPE_REG_ADDR(0x0D09)
+#define DREG_AR_CB_CFG1 PPE_REG_ADDR(0x0D0A)
+#define DREG_A_UTPCFG PPE_REG_ADDR(0x0D0E)
+#define DREG_A_STATUS PPE_REG_ADDR(0x0D0F)
+#define DREG_AT_CFG0 PPE_REG_ADDR(0x0D20)
+#define DREG_AT_CFG1 PPE_REG_ADDR(0x0D21)
+#define DREG_AT_FB_SIZE0 PPE_REG_ADDR(0x0D22)
+#define DREG_AT_FB_SIZE1 PPE_REG_ADDR(0x0D23)
+#define DREG_AT_CELL0 PPE_REG_ADDR(0x0D24)
+#define DREG_AT_CELL1 PPE_REG_ADDR(0x0D25)
+#define DREG_AT_IDLE_CNT0 PPE_REG_ADDR(0x0D26)
+#define DREG_AT_IDLE_CNT1 PPE_REG_ADDR(0x0D27)
+#define DREG_AT_IDLE0 PPE_REG_ADDR(0x0D28)
+#define DREG_AT_IDLE1 PPE_REG_ADDR(0x0D29)
+#define DREG_AR_CFG0 PPE_REG_ADDR(0x0D60)
+#define DREG_AR_CFG1 PPE_REG_ADDR(0x0D61)
+#define DREG_AR_CELL0 PPE_REG_ADDR(0x0D68)
+#define DREG_AR_CELL1 PPE_REG_ADDR(0x0D69)
+#define DREG_AR_IDLE_CNT0 PPE_REG_ADDR(0x0D6A)
+#define DREG_AR_IDLE_CNT1 PPE_REG_ADDR(0x0D6B)
+#define DREG_AR_AIIDLE_CNT0 PPE_REG_ADDR(0x0D6C)
+#define DREG_AR_AIIDLE_CNT1 PPE_REG_ADDR(0x0D6D)
+#define DREG_AR_BE_CNT0 PPE_REG_ADDR(0x0D6E)
+#define DREG_AR_BE_CNT1 PPE_REG_ADDR(0x0D6F)
+#define DREG_AR_HEC_CNT0 PPE_REG_ADDR(0x0D70)
+#define DREG_AR_HEC_CNT1 PPE_REG_ADDR(0x0D71)
+#define DREG_AR_IDLE0 PPE_REG_ADDR(0x0D74)
+#define DREG_AR_IDLE1 PPE_REG_ADDR(0x0D75)
+#define DREG_AR_CVN_CNT0 PPE_REG_ADDR(0x0DA4)
+#define DREG_AR_CVN_CNT1 PPE_REG_ADDR(0x0DA5)
+#define DREG_AR_CVNP_CNT0 PPE_REG_ADDR(0x0DA6)
+#define DREG_AR_CVNP_CNT1 PPE_REG_ADDR(0x0DA7)
+#define DREG_B0_LADR PPE_REG_ADDR(0x0DA8)
+#define DREG_B1_LADR PPE_REG_ADDR(0x0DA9)
+
+#define SFSM_DBA(i) ( (SFSM_dba * ) PPE_REG_ADDR(0x0412 + (i)))
+#define SFSM_CBA(i) ( (SFSM_cba * ) PPE_REG_ADDR(0x0414 + (i)))
+#define SFSM_CFG(i) ( (SFSM_cfg * ) PPE_REG_ADDR(0x0416 + (i)))
+#define SFSM_PGCNT(i) ( (SFSM_pgcnt * ) PPE_REG_ADDR(0x041C + (i)))
+
+#define FFSM_DBA(i) ( (FFSM_dba * ) PPE_REG_ADDR(0x0508 + (i)))
+#define FFSM_CFG(i) ( (FFSM_cfg * ) PPE_REG_ADDR(0x050A + (i)))
+#define FFSM_PGCNT(i) ( (FFSM_pgcnt * ) PPE_REG_ADDR(0x0514 + (i)))
+
+typedef struct {
+ unsigned int res : 19;
+ unsigned int dbase : 13;
+} SFSM_dba;
+
+typedef struct {
+ unsigned int res : 19;
+ unsigned int cbase : 13;
+} SFSM_cba;
+
+typedef struct {
+ unsigned int res : 15;
+ unsigned int endian : 1;
+ unsigned int idlekeep: 1;
+ unsigned int sen : 1;
+ unsigned int res1 : 8;
+ unsigned int pnum : 6;
+} SFSM_cfg;
+
+typedef struct {
+ unsigned int res : 17;
+ unsigned int pptr : 6;
+ unsigned int dcmd : 1;
+ unsigned int res1 : 2;
+ unsigned int upage : 6;
+} SFSM_pgcnt;
+
+typedef struct {
+ unsigned int res : 19;
+ unsigned int dbase : 13;
+} FFSM_dba;
+
+typedef struct {
+ unsigned int res : 12;
+ unsigned int rstptr : 1;
+ unsigned int clvpage : 1;
+ unsigned int fidle : 1;
+ unsigned int endian : 1;
+ unsigned int res1 : 10;
+ unsigned int pnum : 6;
+} FFSM_cfg;
+
+typedef struct {
+ unsigned int res : 17;
+ unsigned int ival : 6;
+ unsigned int icmd : 1;
+ unsigned int res1 : 2;
+ unsigned int vpage : 6;
+} FFSM_pgcnt;
+
+
+
+#endif // IFXMIPS_ATM_PPE_COMMON_H
diff --git a/package/ltq-dsl/src/ifxmips_atm_ppe_danube.h b/package/ltq-dsl/src/ifxmips_atm_ppe_danube.h
new file mode 100644
index 000000000..7e46cc183
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_ppe_danube.h
@@ -0,0 +1,129 @@
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_ppe_danube.h
+** PROJECT : UEIP
+** MODULES : ATM (ADSL)
+**
+** DATE : 1 AUG 2005
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM Driver (PPE Registers)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 4 AUG 2005 Xu Liang Initiate Version
+** 23 OCT 2006 Xu Liang Add GPL header.
+** 9 JAN 2007 Xu Liang First version got from Anand (IC designer)
+*******************************************************************************/
+
+
+
+#ifndef IFXMIPS_ATM_PPE_DANUBE_H
+#define IFXMIPS_ATM_PPE_DANUBE_H
+
+#include <lantiq.h>
+
+/*
+ * FPI Configuration Bus Register and Memory Address Mapping
+ */
+#define IFX_PPE (KSEG1 | 0x1E180000)
+#define PP32_DEBUG_REG_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0000) << 2)))
+#define PPM_INT_REG_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0030) << 2)))
+#define PP32_INTERNAL_RES_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0040) << 2)))
+#define CDM_CODE_MEMORY(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x1000) << 2)))
+#define PPE_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x4000) << 2)))
+#define CDM_DATA_MEMORY(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x5000) << 2)))
+#define PPM_INT_UNIT_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6000) << 2)))
+#define PPM_TIMER0_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6100) << 2)))
+#define PPM_TASK_IND_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6200) << 2)))
+#define PPS_BRK_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6300) << 2)))
+#define PPM_TIMER1_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6400) << 2)))
+#define SB_RAM0_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x8000) << 2)))
+#define SB_RAM1_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x8400) << 2)))
+#define SB_RAM2_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x8C00) << 2)))
+#define SB_RAM3_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x9600) << 2)))
+#define QSB_CONF_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0xC000) << 2)))
+
+/*
+ * DWORD-Length of Memory Blocks
+ */
+#define PP32_DEBUG_REG_DWLEN 0x0030
+#define PPM_INT_REG_DWLEN 0x0010
+#define PP32_INTERNAL_RES_DWLEN 0x00C0
+#define CDM_CODE_MEMORYn_DWLEN(n) ((n) == 0 ? 0x1000 : 0x0800)
+#define PPE_REG_DWLEN 0x1000
+#define CDM_DATA_MEMORY_DWLEN CDM_CODE_MEMORYn_DWLEN(1)
+#define PPM_INT_UNIT_DWLEN 0x0100
+#define PPM_TIMER0_DWLEN 0x0100
+#define PPM_TASK_IND_REG_DWLEN 0x0100
+#define PPS_BRK_DWLEN 0x0100
+#define PPM_TIMER1_DWLEN 0x0100
+#define SB_RAM0_DWLEN 0x0400
+#define SB_RAM1_DWLEN 0x0800
+#define SB_RAM2_DWLEN 0x0A00
+#define SB_RAM3_DWLEN 0x0400
+#define QSB_CONF_REG_DWLEN 0x0100
+
+/*
+ * PP32 to FPI Address Mapping
+ */
+#define SB_BUFFER(__sb_addr) ((volatile unsigned int *)((((__sb_addr) >= 0x2000) && ((__sb_addr) <= 0x23FF)) ? SB_RAM0_ADDR((__sb_addr) - 0x2000) : \
+ (((__sb_addr) >= 0x2400) && ((__sb_addr) <= 0x2BFF)) ? SB_RAM1_ADDR((__sb_addr) - 0x2400) : \
+ (((__sb_addr) >= 0x2C00) && ((__sb_addr) <= 0x35FF)) ? SB_RAM2_ADDR((__sb_addr) - 0x2C00) : \
+ (((__sb_addr) >= 0x3600) && ((__sb_addr) <= 0x39FF)) ? SB_RAM3_ADDR((__sb_addr) - 0x3600) : \
+ 0))
+
+/*
+ * PP32 Debug Control Register
+ */
+#define PP32_DBG_CTRL PP32_DEBUG_REG_ADDR(0, 0x0000)
+
+#define DBG_CTRL_START_SET(value) ((value) ? (1 << 0) : 0)
+#define DBG_CTRL_STOP_SET(value) ((value) ? (1 << 1) : 0)
+#define DBG_CTRL_STEP_SET(value) ((value) ? (1 << 2) : 0)
+
+#define PP32_HALT_STAT PP32_DEBUG_REG_ADDR(0, 0x0001)
+
+#define PP32_BRK_SRC PP32_DEBUG_REG_ADDR(0, 0x0002)
+
+#define PP32_DBG_PC_MIN(i) PP32_DEBUG_REG_ADDR(0, 0x0010 + (i))
+#define PP32_DBG_PC_MAX(i) PP32_DEBUG_REG_ADDR(0, 0x0014 + (i))
+#define PP32_DBG_DATA_MIN(i) PP32_DEBUG_REG_ADDR(0, 0x0018 + (i))
+#define PP32_DBG_DATA_MAX(i) PP32_DEBUG_REG_ADDR(0, 0x001A + (i))
+#define PP32_DBG_DATA_VAL(i) PP32_DEBUG_REG_ADDR(0, 0x001C + (i))
+
+#define PP32_DBG_CUR_PC PP32_DEBUG_REG_ADDR(0, 0x0080)
+
+#define PP32_DBG_TASK_NO PP32_DEBUG_REG_ADDR(0, 0x0081)
+
+#define PP32_DBG_REG_BASE(tsk, i) PP32_DEBUG_REG_ADDR(0, 0x0100 + (tsk) * 16 + (i))
+
+/*
+ * EMA Registers
+ */
+#define EMA_CMDCFG PPE_REG_ADDR(0x0A00)
+#define EMA_DATACFG PPE_REG_ADDR(0x0A01)
+#define EMA_CMDCNT PPE_REG_ADDR(0x0A02)
+#define EMA_DATACNT PPE_REG_ADDR(0x0A03)
+#define EMA_ISR PPE_REG_ADDR(0x0A04)
+#define EMA_IER PPE_REG_ADDR(0x0A05)
+#define EMA_CFG PPE_REG_ADDR(0x0A06)
+#define EMA_SUBID PPE_REG_ADDR(0x0A07)
+
+#define EMA_ALIGNMENT 4
+
+/*
+ * Mailbox IGU1 Interrupt
+ */
+#define PPE_MAILBOX_IGU1_INT LTQ_PPE_MBOX_INT
+
+
+
+#endif // IFXMIPS_ATM_PPE_DANUBE_H
diff --git a/package/ltq-dsl/src/ifxmips_atm_ppe_vr9.h b/package/ltq-dsl/src/ifxmips_atm_ppe_vr9.h
new file mode 100644
index 000000000..316a77285
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_ppe_vr9.h
@@ -0,0 +1,192 @@
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_ppe_vr9.h
+** PROJECT : UEIP
+** MODULES : ATM (ADSL)
+**
+** DATE : 1 AUG 2005
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM Driver (PPE Registers)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 4 AUG 2005 Xu Liang Initiate Version
+** 23 OCT 2006 Xu Liang Add GPL header.
+** 9 JAN 2007 Xu Liang First version got from Anand (IC designer)
+*******************************************************************************/
+
+
+
+#ifndef IFXMIPS_ATM_PPE_VR9_H
+#define IFXMIPS_ATM_PPE_VR9_H
+
+
+
+/*
+ * FPI Configuration Bus Register and Memory Address Mapping
+ */
+#define IFX_PPE (KSEG1 | 0x1E200000)
+#define PP32_DEBUG_REG_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x000000 + (i) * 0x00010000) << 2)))
+#define CDM_CODE_MEMORY(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x001000 + (i) * 0x00010000) << 2)))
+#define CDM_DATA_MEMORY(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x004000 + (i) * 0x00010000) << 2)))
+#define SB_RAM0_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x008000) << 2)))
+#define SB_RAM1_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x009000) << 2)))
+#define SB_RAM2_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x00A000) << 2)))
+#define SB_RAM3_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x00B000) << 2)))
+#define PPE_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x00D000) << 2)))
+#define QSB_CONF_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x00E000) << 2)))
+#define SB_RAM6_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x018000) << 2)))
+
+/*
+ * DWORD-Length of Memory Blocks
+ */
+#define PP32_DEBUG_REG_DWLEN 0x0030
+#define CDM_CODE_MEMORYn_DWLEN(n) ((n) == 0 ? 0x1000 : 0x0800)
+#define CDM_DATA_MEMORY_DWLEN CDM_CODE_MEMORYn_DWLEN(1)
+#define SB_RAM0_DWLEN 0x1000
+#define SB_RAM1_DWLEN 0x1000
+#define SB_RAM2_DWLEN 0x1000
+#define SB_RAM3_DWLEN 0x1000
+#define SB_RAM6_DWLEN 0x8000
+#define QSB_CONF_REG_DWLEN 0x0100
+
+/*
+ * PP32 to FPI Address Mapping
+ */
+#define SB_BUFFER(__sb_addr) ((volatile unsigned int *)((((__sb_addr) >= 0x0000) && ((__sb_addr) <= 0x1FFF)) ? PPE_REG_ADDR((__sb_addr)) : \
+ (((__sb_addr) >= 0x2000) && ((__sb_addr) <= 0x2FFF)) ? SB_RAM0_ADDR((__sb_addr) - 0x2000) : \
+ (((__sb_addr) >= 0x3000) && ((__sb_addr) <= 0x3FFF)) ? SB_RAM1_ADDR((__sb_addr) - 0x3000) : \
+ (((__sb_addr) >= 0x4000) && ((__sb_addr) <= 0x4FFF)) ? SB_RAM2_ADDR((__sb_addr) - 0x4000) : \
+ (((__sb_addr) >= 0x5000) && ((__sb_addr) <= 0x5FFF)) ? SB_RAM3_ADDR((__sb_addr) - 0x5000) : \
+ (((__sb_addr) >= 0x7000) && ((__sb_addr) <= 0x7FFF)) ? PPE_REG_ADDR((__sb_addr) - 0x7000) : \
+ (((__sb_addr) >= 0x8000) && ((__sb_addr) <= 0xFFFF)) ? SB_RAM6_ADDR((__sb_addr) - 0x8000) : \
+ 0))
+
+/*
+ * PP32 Debug Control Register
+ */
+#define NUM_OF_PP32 2
+
+#define PP32_FREEZE PPE_REG_ADDR(0x0000)
+#define PP32_SRST PPE_REG_ADDR(0x0020)
+
+#define PP32_DBG_CTRL(n) PP32_DEBUG_REG_ADDR(n, 0x0000)
+
+#define DBG_CTRL_RESTART 0
+#define DBG_CTRL_STOP 1
+
+#define PP32_CTRL_CMD(n) PP32_DEBUG_REG_ADDR(n, 0x0B00)
+ #define PP32_CTRL_CMD_RESTART (1 << 0)
+ #define PP32_CTRL_CMD_STOP (1 << 1)
+ #define PP32_CTRL_CMD_STEP (1 << 2)
+ #define PP32_CTRL_CMD_BREAKOUT (1 << 3)
+
+#define PP32_CTRL_OPT(n) PP32_DEBUG_REG_ADDR(n, 0x0C00)
+ #define PP32_CTRL_OPT_BREAKOUT_ON_STOP_ON (3 << 0)
+ #define PP32_CTRL_OPT_BREAKOUT_ON_STOP_OFF (2 << 0)
+ #define PP32_CTRL_OPT_BREAKOUT_ON_BREAKIN_ON (3 << 2)
+ #define PP32_CTRL_OPT_BREAKOUT_ON_BREAKIN_OFF (2 << 2)
+ #define PP32_CTRL_OPT_STOP_ON_BREAKIN_ON (3 << 4)
+ #define PP32_CTRL_OPT_STOP_ON_BREAKIN_OFF (2 << 4)
+ #define PP32_CTRL_OPT_STOP_ON_BREAKPOINT_ON (3 << 6)
+ #define PP32_CTRL_OPT_STOP_ON_BREAKPOINT_OFF (2 << 6)
+ #define PP32_CTRL_OPT_BREAKOUT_ON_STOP(n) (*PP32_CTRL_OPT(n) & (1 << 0))
+ #define PP32_CTRL_OPT_BREAKOUT_ON_BREAKIN(n) (*PP32_CTRL_OPT(n) & (1 << 2))
+ #define PP32_CTRL_OPT_STOP_ON_BREAKIN(n) (*PP32_CTRL_OPT(n) & (1 << 4))
+ #define PP32_CTRL_OPT_STOP_ON_BREAKPOINT(n) (*PP32_CTRL_OPT(n) & (1 << 6))
+
+#define PP32_BRK_PC(n, i) PP32_DEBUG_REG_ADDR(n, 0x0900 + (i) * 2)
+#define PP32_BRK_PC_MASK(n, i) PP32_DEBUG_REG_ADDR(n, 0x0901 + (i) * 2)
+#define PP32_BRK_DATA_ADDR(n, i) PP32_DEBUG_REG_ADDR(n, 0x0904 + (i) * 2)
+#define PP32_BRK_DATA_ADDR_MASK(n, i) PP32_DEBUG_REG_ADDR(n, 0x0905 + (i) * 2)
+#define PP32_BRK_DATA_VALUE_RD(n, i) PP32_DEBUG_REG_ADDR(n, 0x0908 + (i) * 2)
+#define PP32_BRK_DATA_VALUE_RD_MASK(n, i) PP32_DEBUG_REG_ADDR(n, 0x0909 + (i) * 2)
+#define PP32_BRK_DATA_VALUE_WR(n, i) PP32_DEBUG_REG_ADDR(n, 0x090C + (i) * 2)
+#define PP32_BRK_DATA_VALUE_WR_MASK(n, i) PP32_DEBUG_REG_ADDR(n, 0x090D + (i) * 2)
+ #define PP32_BRK_CONTEXT_MASK(i) (1 << (i))
+ #define PP32_BRK_CONTEXT_MASK_EN (1 << 4)
+ #define PP32_BRK_COMPARE_GREATER_EQUAL (1 << 5) // valid for break data value rd/wr only
+ #define PP32_BRK_COMPARE_LOWER_EQUAL (1 << 6)
+ #define PP32_BRK_COMPARE_EN (1 << 7)
+
+#define PP32_BRK_TRIG(n) PP32_DEBUG_REG_ADDR(n, 0x0F00)
+ #define PP32_BRK_GRPi_PCn_ON(i, n) ((3 << ((n) * 2)) << ((i) * 16))
+ #define PP32_BRK_GRPi_PCn_OFF(i, n) ((2 << ((n) * 2)) << ((i) * 16))
+ #define PP32_BRK_GRPi_DATA_ADDRn_ON(i, n) ((3 << ((n) * 2 + 4)) << ((i) * 16))
+ #define PP32_BRK_GRPi_DATA_ADDRn_OFF(i, n) ((2 << ((n) * 2 + 4)) << ((i) * 16))
+ #define PP32_BRK_GRPi_DATA_VALUE_RDn_ON(i, n) ((3 << ((n) * 2 + 8)) << ((i) * 16))
+ #define PP32_BRK_GRPi_DATA_VALUE_RDn_OFF(i, n)((2 << ((n) * 2 + 8)) << ((i) * 16))
+ #define PP32_BRK_GRPi_DATA_VALUE_WRn_ON(i, n) ((3 << ((n) * 2 + 12)) << ((i) * 16))
+ #define PP32_BRK_GRPi_DATA_VALUE_WRn_OFF(i, n)((2 << ((n) * 2 + 12)) << ((i) * 16))
+ #define PP32_BRK_GRPi_PCn(k, i, n) (*PP32_BRK_TRIG(k) & ((1 << ((n))) << ((i) * 8)))
+ #define PP32_BRK_GRPi_DATA_ADDRn(k, i, n) (*PP32_BRK_TRIG(k) & ((1 << ((n) + 2)) << ((i) * 8)))
+ #define PP32_BRK_GRPi_DATA_VALUE_RDn(k, i, n) (*PP32_BRK_TRIG(k) & ((1 << ((n) + 4)) << ((i) * 8)))
+ #define PP32_BRK_GRPi_DATA_VALUE_WRn(k, i, n) (*PP32_BRK_TRIG(k) & ((1 << ((n) + 6)) << ((i) * 8)))
+
+#define PP32_CPU_STATUS(n) PP32_DEBUG_REG_ADDR(n, 0x0D00)
+#define PP32_HALT_STAT(n) PP32_CPU_STATUS(n)
+#define PP32_DBG_CUR_PC(n) PP32_CPU_STATUS(n)
+ #define PP32_CPU_USER_STOPPED(n) (*PP32_CPU_STATUS(n) & (1 << 0))
+ #define PP32_CPU_USER_BREAKIN_RCV(n) (*PP32_CPU_STATUS(n) & (1 << 1))
+ #define PP32_CPU_USER_BREAKPOINT_MET(n) (*PP32_CPU_STATUS(n) & (1 << 2))
+ #define PP32_CPU_CUR_PC(n) (*PP32_CPU_STATUS(n) >> 16)
+
+#define PP32_BREAKPOINT_REASONS(n) PP32_DEBUG_REG_ADDR(n, 0x0A00)
+ #define PP32_BRK_PC_MET(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << (i)))
+ #define PP32_BRK_DATA_ADDR_MET(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) + 2)))
+ #define PP32_BRK_DATA_VALUE_RD_MET(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) + 4)))
+ #define PP32_BRK_DATA_VALUE_WR_MET(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) + 6)))
+ #define PP32_BRK_DATA_VALUE_RD_LO_EQ(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) * 2 + 8)))
+ #define PP32_BRK_DATA_VALUE_RD_GT_EQ(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) * 2 + 9)))
+ #define PP32_BRK_DATA_VALUE_WR_LO_EQ(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) * 2 + 12)))
+ #define PP32_BRK_DATA_VALUE_WR_GT_EQ(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) * 2 + 13)))
+ #define PP32_BRK_CUR_CONTEXT(n) ((*PP32_BREAKPOINT_REASONS(n) >> 16) & 0x03)
+
+#define PP32_GP_REG_BASE(n) PP32_DEBUG_REG_ADDR(n, 0x0E00)
+#define PP32_GP_CONTEXTi_REGn(n, i, j) PP32_DEBUG_REG_ADDR(n, 0x0E00 + (i) * 16 + (j))
+
+/*
+ * PDMA/EMA Registers
+ */
+#define PDMA_CFG PPE_REG_ADDR(0x0A00)
+#define PDMA_RX_CMDCNT PPE_REG_ADDR(0x0A01)
+#define PDMA_TX_CMDCNT PPE_REG_ADDR(0x0A02)
+#define PDMA_RX_FWDATACNT PPE_REG_ADDR(0x0A03)
+#define PDMA_TX_FWDATACNT PPE_REG_ADDR(0x0A04)
+#define PDMA_RX_CTX_CFG PPE_REG_ADDR(0x0A05)
+#define PDMA_TX_CTX_CFG PPE_REG_ADDR(0x0A06)
+#define PDMA_RX_MAX_LEN_REG PPE_REG_ADDR(0x0A07)
+#define PDMA_RX_DELAY_CFG PPE_REG_ADDR(0x0A08)
+#define PDMA_INT_FIFO_RD PPE_REG_ADDR(0x0A09)
+#define PDMA_ISR PPE_REG_ADDR(0x0A0A)
+#define PDMA_IER PPE_REG_ADDR(0x0A0B)
+#define PDMA_SUBID PPE_REG_ADDR(0x0A0C)
+#define PDMA_BAR0 PPE_REG_ADDR(0x0A0D)
+#define PDMA_BAR1 PPE_REG_ADDR(0x0A0E)
+
+#define SAR_PDMA_RX_CMDBUF_CFG PPE_REG_ADDR(0x0F00)
+#define SAR_PDMA_TX_CMDBUF_CFG PPE_REG_ADDR(0x0F01)
+#define SAR_PDMA_RX_FW_CMDBUF_CFG PPE_REG_ADDR(0x0F02)
+#define SAR_PDMA_TX_FW_CMDBUF_CFG PPE_REG_ADDR(0x0F03)
+#define SAR_PDMA_RX_CMDBUF_STATUS PPE_REG_ADDR(0x0F04)
+#define SAR_PDMA_TX_CMDBUF_STATUS PPE_REG_ADDR(0x0F05)
+
+#define PDMA_ALIGNMENT 4
+#define EMA_ALIGNMENT PDMA_ALIGNMENT
+
+/*
+ * Mailbox IGU1 Interrupt
+ */
+#define PPE_MAILBOX_IGU1_INT INT_NUM_IM2_IRL0 + 24
+
+
+
+#endif // IFXMIPS_ATM_PPE_VR9_H
diff --git a/package/ltq-dsl/src/ifxmips_atm_vr9.c b/package/ltq-dsl/src/ifxmips_atm_vr9.c
new file mode 100644
index 000000000..ea84c4c83
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_atm_vr9.c
@@ -0,0 +1,303 @@
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_vr9.c
+** PROJECT : UEIP
+** MODULES : ATM
+**
+** DATE : 7 Jul 2009
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM driver common source file (core functions)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 07 JUL 2009 Xu Liang Init Version
+*******************************************************************************/
+
+
+
+/*
+ * ####################################
+ * Head File
+ * ####################################
+ */
+
+/*
+ * Common Head File
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <asm/delay.h>
+
+/*
+ * Chip Specific Head File
+ */
+#include <ifx_types.h>
+#include <ifx_regs.h>
+#include <common_routines.h>
+#include <ifx_pmu.h>
+#include <ifx_rcu.h>
+#include "ifxmips_atm_core.h"
+#include "ifxmips_atm_fw_vr9.h"
+
+
+
+/*
+ * ####################################
+ * Definition
+ * ####################################
+ */
+
+
+
+/*
+ * ####################################
+ * Declaration
+ * ####################################
+ */
+
+/*
+ * Hardware Init/Uninit Functions
+ */
+static inline void init_pmu(void);
+static inline void uninit_pmu(void);
+static inline void reset_ppe(void);
+static inline void init_pdma(void);
+static inline void init_mailbox(void);
+static inline void init_atm_tc(void);
+static inline void clear_share_buffer(void);
+
+
+
+/*
+ * ####################################
+ * Local Variable
+ * ####################################
+ */
+
+
+
+/*
+ * ####################################
+ * Local Function
+ * ####################################
+ */
+
+static inline void init_pmu(void)
+{
+ //*PMU_PWDCR &= ~((1 << 29) | (1 << 22) | (1 << 21) | (1 << 19) | (1 << 18));
+ //PPE_TOP_PMU_SETUP(IFX_PMU_ENABLE);
+ PPE_SLL01_PMU_SETUP(IFX_PMU_ENABLE);
+ PPE_TC_PMU_SETUP(IFX_PMU_ENABLE);
+ PPE_EMA_PMU_SETUP(IFX_PMU_ENABLE);
+ PPE_QSB_PMU_SETUP(IFX_PMU_ENABLE);
+ PPE_TPE_PMU_SETUP(IFX_PMU_ENABLE);
+ DSL_DFE_PMU_SETUP(IFX_PMU_ENABLE);
+}
+
+static inline void uninit_pmu(void)
+{
+ PPE_SLL01_PMU_SETUP(IFX_PMU_DISABLE);
+ PPE_TC_PMU_SETUP(IFX_PMU_DISABLE);
+ PPE_EMA_PMU_SETUP(IFX_PMU_DISABLE);
+ PPE_QSB_PMU_SETUP(IFX_PMU_DISABLE);
+ PPE_TPE_PMU_SETUP(IFX_PMU_DISABLE);
+ DSL_DFE_PMU_SETUP(IFX_PMU_DISABLE);
+ //PPE_TOP_PMU_SETUP(IFX_PMU_DISABLE);
+}
+
+static inline void reset_ppe(void)
+{
+#ifdef MODULE
+ // reset PPE
+ ifx_rcu_rst(IFX_RCU_DOMAIN_DSLDFE, IFX_RCU_MODULE_ATM);
+ udelay(1000);
+ ifx_rcu_rst(IFX_RCU_DOMAIN_DSLTC, IFX_RCU_MODULE_ATM);
+ udelay(1000);
+ ifx_rcu_rst(IFX_RCU_DOMAIN_PPE, IFX_RCU_MODULE_ATM);
+ udelay(1000);
+ *PP32_SRST &= ~0x000303CF;
+ udelay(1000);
+ *PP32_SRST |= 0x000303CF;
+ udelay(1000);
+#endif
+}
+
+static inline void init_pdma(void)
+{
+ IFX_REG_W32(0x08, PDMA_CFG);
+ IFX_REG_W32(0x00203580, SAR_PDMA_RX_CMDBUF_CFG);
+ IFX_REG_W32(0x004035A0, SAR_PDMA_RX_FW_CMDBUF_CFG);
+}
+
+static inline void init_mailbox(void)
+{
+ IFX_REG_W32(0xFFFFFFFF, MBOX_IGU1_ISRC);
+ IFX_REG_W32(0x00000000, MBOX_IGU1_IER);
+ IFX_REG_W32(0xFFFFFFFF, MBOX_IGU3_ISRC);
+ IFX_REG_W32(0x00000000, MBOX_IGU3_IER);
+}
+
+static inline void init_atm_tc(void)
+{
+ /* clear sync state */
+ *SFSM_STATE0 = 0;
+ *SFSM_STATE1 = 0;
+
+ /* enable keep IDLE */
+// *SFSM_CFG0 |= 1 << 15;
+// *SFSM_CFG1 |= 1 << 15;
+}
+
+static inline void clear_share_buffer(void)
+{
+ volatile u32 *p;
+ unsigned int i;
+
+ p = SB_RAM0_ADDR(0);
+ for ( i = 0; i < SB_RAM0_DWLEN + SB_RAM1_DWLEN + SB_RAM2_DWLEN + SB_RAM3_DWLEN; i++ )
+ IFX_REG_W32(0, p++);
+
+ p = SB_RAM6_ADDR(0);
+ for ( i = 0; i < SB_RAM6_DWLEN; i++ )
+ IFX_REG_W32(0, p++);
+}
+
+/*
+ * Description:
+ * Download PPE firmware binary code.
+ * Input:
+ * pp32 --- int, which pp32 core
+ * src --- u32 *, binary code buffer
+ * dword_len --- unsigned int, binary code length in DWORD (32-bit)
+ * Output:
+ * int --- IFX_SUCCESS: Success
+ * else: Error Code
+ */
+static inline int pp32_download_code(int pp32, u32 *code_src, unsigned int code_dword_len, u32 *data_src, unsigned int data_dword_len)
+{
+ unsigned int clr, set;
+ volatile u32 *dest;
+
+ if ( code_src == 0 || ((unsigned long)code_src & 0x03) != 0
+ || data_src == 0 || ((unsigned long)data_src & 0x03) != 0 )
+ return IFX_ERROR;
+
+ clr = pp32 ? 0xF0 : 0x0F;
+ if ( code_dword_len <= CDM_CODE_MEMORYn_DWLEN(0) )
+ set = pp32 ? (3 << 6): (2 << 2);
+ else
+ set = 0x00;
+ IFX_REG_W32_MASK(clr, set, CDM_CFG);
+
+ /* copy code */
+ dest = CDM_CODE_MEMORY(pp32, 0);
+ while ( code_dword_len-- > 0 )
+ IFX_REG_W32(*code_src++, dest++);
+
+ /* copy data */
+ dest = CDM_DATA_MEMORY(pp32, 0);
+ while ( data_dword_len-- > 0 )
+ IFX_REG_W32(*data_src++, dest++);
+
+ return IFX_SUCCESS;
+}
+
+
+
+/*
+ * ####################################
+ * Global Function
+ * ####################################
+ */
+
+extern void ifx_atm_get_fw_ver(unsigned int *major, unsigned int *minor)
+{
+ ASSERT(major != NULL, "pointer is NULL");
+ ASSERT(minor != NULL, "pointer is NULL");
+
+#ifdef VER_IN_FIRMWARE
+ *major = FW_VER_ID->major;
+ *minor = FW_VER_ID->minor;
+#else
+ *major = ATM_FW_VER_MAJOR;
+ *minor = ATM_FW_VER_MINOR;
+#endif
+}
+
+void ifx_atm_init_chip(void)
+{
+ init_pmu();
+
+ reset_ppe();
+
+ init_pdma();
+
+ init_mailbox();
+
+ init_atm_tc();
+
+ clear_share_buffer();
+}
+
+void ifx_atm_uninit_chip(void)
+{
+ uninit_pmu();
+}
+
+/*
+ * Description:
+ * Initialize and start up PP32.
+ * Input:
+ * none
+ * Output:
+ * int --- IFX_SUCCESS: Success
+ * else: Error Code
+ */
+int ifx_pp32_start(int pp32)
+{
+ unsigned int mask = 1 << (pp32 << 4);
+ int ret;
+
+ /* download firmware */
+ ret = pp32_download_code(pp32, firmware_binary_code, sizeof(firmware_binary_code) / sizeof(*firmware_binary_code), firmware_binary_data, sizeof(firmware_binary_data) / sizeof(*firmware_binary_data));
+ if ( ret != IFX_SUCCESS )
+ return ret;
+
+ /* run PP32 */
+ IFX_REG_W32_MASK(mask, 0, PP32_FREEZE);
+
+ /* idle for a while to let PP32 init itself */
+ udelay(10);
+
+ return IFX_SUCCESS;
+}
+
+/*
+ * Description:
+ * Halt PP32.
+ * Input:
+ * none
+ * Output:
+ * none
+ */
+void ifx_pp32_stop(int pp32)
+{
+ unsigned int mask = 1 << (pp32 << 4);
+
+ /* halt PP32 */
+ IFX_REG_W32_MASK(0, mask, PP32_FREEZE);
+}
diff --git a/package/ltq-dsl/src/ifxmips_compat.h b/package/ltq-dsl/src/ifxmips_compat.h
new file mode 100644
index 000000000..b0c9f25f4
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_compat.h
@@ -0,0 +1,56 @@
+#ifndef _IFXMIPS_COMPAT_H__
+#define _IFXMIPS_COMPAT_H__
+
+#define IFX_SUCCESS 0
+#define IFX_ERROR (-1)
+
+#define ATM_VBR_NRT ATM_VBR
+#define ATM_VBR_RT 6
+#define ATM_UBR_PLUS 7
+#define ATM_GFR 8
+
+#define NUM_ENTITY(x) (sizeof(x) / sizeof(*(x)))
+
+#define SET_BITS(x, msb, lsb, value) \
+ (((x) & ~(((1 << ((msb) + 1)) - 1) ^ ((1 << (lsb)) - 1))) | (((value) & ((1 << (1 + (msb) - (lsb))) - 1)) << (lsb)))
+
+
+#define IFX_PP32_ETOP_CFG 0x16020
+#define IFX_PP32_ETOP_MDIO_CFG 0x11804
+#define IFX_PP32_ETOP_IG_PLEN_CTRL 0x16080
+#define IFX_PP32_ENET_MAC_CFG 0x1840
+
+#define IFX_RCU_DOMAIN_PPE (1 << 8)
+#define IFX_RCU_MODULE_ATM
+
+#define IFX_PMU_ENABLE 1
+#define IFX_PMU_DISABLE 0
+
+#define IFX_PMU_MODULE_DSL_DFE (1 << 9)
+#define IFX_PMU_MODULE_AHBS (1 << 13)
+#define IFX_PMU_MODULE_PPE_QSB (1 << 18)
+#define IFX_PMU_MODULE_PPE_SLL01 (1 << 19)
+#define IFX_PMU_MODULE_PPE_TC (1 << 21)
+#define IFX_PMU_MODULE_PPE_EMA (1 << 22)
+#define IFX_PMU_MODULE_PPE_TOP (1 << 29)
+
+extern void ltq_pmu_enable(unsigned int module);
+extern void ltq_pmu_disable(unsigned int module);
+
+#define ifx_pmu_set(a,b) {if(a == IFX_PMU_ENABLE) ltq_pmu_enable(b); else ltq_pmu_disable(b);}
+
+#define PPE_TOP_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_PPE_TOP, (__x))
+#define PPE_SLL01_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_PPE_SLL01, (__x))
+#define PPE_TC_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_PPE_TC, (__x))
+#define PPE_EMA_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_PPE_EMA, (__x))
+#define PPE_QSB_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_PPE_QSB, (__x))
+#define PPE_TPE_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_AHBS, (__x))
+#define DSL_DFE_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_DSL_DFE, (__x))
+
+#define IFX_REG_W32(_v, _r) __raw_writel((_v), (_r))
+
+#define CONFIG_IFXMIPS_DSL_CPE_MEI y
+
+#define INT_NUM_IM2_IRL24 (INT_NUM_IM2_IRL0 + 24)
+
+#endif
diff --git a/package/ltq-dsl/src/ifxmips_mei_interface.h b/package/ltq-dsl/src/ifxmips_mei_interface.h
new file mode 100644
index 000000000..4ddc4c6ae
--- /dev/null
+++ b/package/ltq-dsl/src/ifxmips_mei_interface.h
@@ -0,0 +1,702 @@
+/******************************************************************************
+
+ Copyright (c) 2009
+ Infineon Technologies AG
+ Am Campeon 1-12; 81726 Munich, Germany
+
+ For licensing information, see the file 'LICENSE' in the root folder of
+ this software module.
+
+******************************************************************************/
+
+#ifndef IFXMIPS_MEI_H
+#define IFXMIPS_MEI_H
+
+//#define CONFIG_AMAZON_SE 1
+//#define CONFIG_DANUBE 1
+//#define CONFIG_AR9 1
+
+#if !defined(CONFIG_DANUBE) && !defined(CONFIG_AMAZON_SE) && !defined(CONFIG_AR9) && !defined(CONFIG_VR9)
+#error Platform undefined!!!
+#endif
+
+#ifdef IFX_MEI_BSP
+/** This is the character datatype. */
+typedef char DSL_char_t;
+/** This is the unsigned 8-bit datatype. */
+typedef unsigned char DSL_uint8_t;
+/** This is the signed 8-bit datatype. */
+typedef signed char DSL_int8_t;
+/** This is the unsigned 16-bit datatype. */
+typedef unsigned short DSL_uint16_t;
+/** This is the signed 16-bit datatype. */
+typedef signed short DSL_int16_t;
+/** This is the unsigned 32-bit datatype. */
+typedef unsigned long DSL_uint32_t;
+/** This is the signed 32-bit datatype. */
+typedef signed long DSL_int32_t;
+/** This is the float datatype. */
+typedef float DSL_float_t;
+/** This is the void datatype. */
+typedef void DSL_void_t;
+/** integer type, width is depending on processor arch */
+typedef int DSL_int_t;
+/** unsigned integer type, width is depending on processor arch */
+typedef unsigned int DSL_uint_t;
+typedef struct file DSL_DRV_file_t;
+typedef struct inode DSL_DRV_inode_t;
+
+/**
+ * Defines all possible CMV groups
+ * */
+typedef enum {
+ DSL_CMV_GROUP_CNTL = 1,
+ DSL_CMV_GROUP_STAT = 2,
+ DSL_CMV_GROUP_INFO = 3,
+ DSL_CMV_GROUP_TEST = 4,
+ DSL_CMV_GROUP_OPTN = 5,
+ DSL_CMV_GROUP_RATE = 6,
+ DSL_CMV_GROUP_PLAM = 7,
+ DSL_CMV_GROUP_CNFG = 8
+} DSL_CmvGroup_t;
+/**
+ * Defines all opcode types
+ * */
+typedef enum {
+ H2D_CMV_READ = 0x00,
+ H2D_CMV_WRITE = 0x04,
+ H2D_CMV_INDICATE_REPLY = 0x10,
+ H2D_ERROR_OPCODE_UNKNOWN =0x20,
+ H2D_ERROR_CMV_UNKNOWN =0x30,
+
+ D2H_CMV_READ_REPLY =0x01,
+ D2H_CMV_WRITE_REPLY = 0x05,
+ D2H_CMV_INDICATE = 0x11,
+ D2H_ERROR_OPCODE_UNKNOWN = 0x21,
+ D2H_ERROR_CMV_UNKNOWN = 0x31,
+ D2H_ERROR_CMV_READ_NOT_AVAILABLE = 0x41,
+ D2H_ERROR_CMV_WRITE_ONLY = 0x51,
+ D2H_ERROR_CMV_READ_ONLY = 0x61,
+
+ H2D_DEBUG_READ_DM = 0x02,
+ H2D_DEBUG_READ_PM = 0x06,
+ H2D_DEBUG_WRITE_DM = 0x0a,
+ H2D_DEBUG_WRITE_PM = 0x0e,
+
+ D2H_DEBUG_READ_DM_REPLY = 0x03,
+ D2H_DEBUG_READ_FM_REPLY = 0x07,
+ D2H_DEBUG_WRITE_DM_REPLY = 0x0b,
+ D2H_DEBUG_WRITE_FM_REPLY = 0x0f,
+ D2H_ERROR_ADDR_UNKNOWN = 0x33,
+
+ D2H_AUTONOMOUS_MODEM_READY_MSG = 0xf1
+} DSL_CmvOpcode_t;
+
+/* mutex macros */
+#define MEI_MUTEX_INIT(id,flag) \
+ sema_init(&id,flag)
+#define MEI_MUTEX_LOCK(id) \
+ down_interruptible(&id)
+#define MEI_MUTEX_UNLOCK(id) \
+ up(&id)
+#define MEI_WAIT(ms) \
+ {\
+ set_current_state(TASK_INTERRUPTIBLE);\
+ schedule_timeout(ms);\
+ }
+#define MEI_INIT_WAKELIST(name,queue) \
+ init_waitqueue_head(&queue)
+
+/* wait for an event, timeout is measured in ms */
+#define MEI_WAIT_EVENT_TIMEOUT(ev,timeout)\
+ interruptible_sleep_on_timeout(&ev,timeout * HZ / 1000)
+#define MEI_WAKEUP_EVENT(ev)\
+ wake_up_interruptible(&ev)
+#endif /* IFX_MEI_BSP */
+
+/*** Register address offsets, relative to MEI_SPACE_ADDRESS ***/
+#define ME_DX_DATA (0x0000)
+#define ME_VERSION (0x0004)
+#define ME_ARC_GP_STAT (0x0008)
+#define ME_DX_STAT (0x000C)
+#define ME_DX_AD (0x0010)
+#define ME_DX_MWS (0x0014)
+#define ME_ME2ARC_INT (0x0018)
+#define ME_ARC2ME_STAT (0x001C)
+#define ME_ARC2ME_MASK (0x0020)
+#define ME_DBG_WR_AD (0x0024)
+#define ME_DBG_RD_AD (0x0028)
+#define ME_DBG_DATA (0x002C)
+#define ME_DBG_DECODE (0x0030)
+#define ME_CONFIG (0x0034)
+#define ME_RST_CTRL (0x0038)
+#define ME_DBG_MASTER (0x003C)
+#define ME_CLK_CTRL (0x0040)
+#define ME_BIST_CTRL (0x0044)
+#define ME_BIST_STAT (0x0048)
+#define ME_XDATA_BASE_SH (0x004c)
+#define ME_XDATA_BASE (0x0050)
+#define ME_XMEM_BAR_BASE (0x0054)
+#define ME_XMEM_BAR0 (0x0054)
+#define ME_XMEM_BAR1 (0x0058)
+#define ME_XMEM_BAR2 (0x005C)
+#define ME_XMEM_BAR3 (0x0060)
+#define ME_XMEM_BAR4 (0x0064)
+#define ME_XMEM_BAR5 (0x0068)
+#define ME_XMEM_BAR6 (0x006C)
+#define ME_XMEM_BAR7 (0x0070)
+#define ME_XMEM_BAR8 (0x0074)
+#define ME_XMEM_BAR9 (0x0078)
+#define ME_XMEM_BAR10 (0x007C)
+#define ME_XMEM_BAR11 (0x0080)
+#define ME_XMEM_BAR12 (0x0084)
+#define ME_XMEM_BAR13 (0x0088)
+#define ME_XMEM_BAR14 (0x008C)
+#define ME_XMEM_BAR15 (0x0090)
+#define ME_XMEM_BAR16 (0x0094)
+
+#define WHILE_DELAY 20000
+/*
+** Define where in ME Processor's memory map the Stratify chip lives
+*/
+
+#define MAXSWAPSIZE (8 * 1024) //8k *(32bits)
+
+// Mailboxes
+#define MSG_LENGTH 16 // x16 bits
+#define YES_REPLY 1
+#define NO_REPLY 0
+
+#define CMV_TIMEOUT 1000 //jiffies
+
+// Block size per BAR
+#define SDRAM_SEGMENT_SIZE (64*1024)
+// Number of Bar registers
+#define MAX_BAR_REGISTERS (17)
+
+#define XDATA_REGISTER (15)
+
+// ARC register addresss
+#define ARC_STATUS 0x0
+#define ARC_LP_START 0x2
+#define ARC_LP_END 0x3
+#define ARC_DEBUG 0x5
+#define ARC_INT_MASK 0x10A
+
+#define IRAM0_BASE (0x00000)
+#define IRAM1_BASE (0x04000)
+#if defined(CONFIG_DANUBE)
+#define BRAM_BASE (0x0A000)
+#elif defined(CONFIG_AMAZON_SE) || defined(CONFIG_AR9) || defined(CONFIG_VR9)
+#define BRAM_BASE (0x08000)
+#endif
+#define XRAM_BASE (0x18000)
+#define YRAM_BASE (0x1A000)
+#define EXT_MEM_BASE (0x80000)
+#define ARC_GPIO_CTRL (0xC030)
+#define ARC_GPIO_DATA (0xC034)
+
+#define IRAM0_SIZE (16*1024)
+#define IRAM1_SIZE (16*1024)
+#define BRAM_SIZE (12*1024)
+#define XRAM_SIZE (8*1024)
+#define YRAM_SIZE (8*1024)
+#define EXT_MEM_SIZE (1536*1024)
+
+#define ADSL_BASE (0x20000)
+#define CRI_BASE (ADSL_BASE + 0x11F00)
+#define CRI_CCR0 (CRI_BASE + 0x00)
+#define CRI_RST (CRI_BASE + 0x04*4)
+#define ADSL_DILV_BASE (ADSL_BASE+0x20000)
+
+//
+#define IRAM0_ADDR_BIT_MASK 0xFFF
+#define IRAM1_ADDR_BIT_MASK 0xFFF
+#define BRAM_ADDR_BIT_MASK 0xFFF
+#define RX_DILV_ADDR_BIT_MASK 0x1FFF
+
+/*** Bit definitions ***/
+#define ARC_AUX_HALT (1 << 25)
+#define ARC_DEBUG_HALT (1 << 1)
+#define FALSE 0
+#define TRUE 1
+#define BIT0 (1<<0)
+#define BIT1 (1<<1)
+#define BIT2 (1<<2)
+#define BIT3 (1<<3)
+#define BIT4 (1<<4)
+#define BIT5 (1<<5)
+#define BIT6 (1<<6)
+#define BIT7 (1<<7)
+#define BIT8 (1<<8)
+#define BIT9 (1<<9)
+#define BIT10 (1<<10)
+#define BIT11 (1<<11)
+#define BIT12 (1<<12)
+#define BIT13 (1<<13)
+#define BIT14 (1<<14)
+#define BIT15 (1<<15)
+#define BIT16 (1<<16)
+#define BIT17 (1<<17)
+#define BIT18 (1<<18)
+#define BIT19 (1<<19)
+#define BIT20 (1<<20)
+#define BIT21 (1<<21)
+#define BIT22 (1<<22)
+#define BIT23 (1<<23)
+#define BIT24 (1<<24)
+#define BIT25 (1<<25)
+#define BIT26 (1<<26)
+#define BIT27 (1<<27)
+#define BIT28 (1<<28)
+#define BIT29 (1<<29)
+#define BIT30 (1<<30)
+#define BIT31 (1<<31)
+
+// CRI_CCR0 Register definitions
+#define CLK_2M_MODE_ENABLE BIT6
+#define ACL_CLK_MODE_ENABLE BIT4
+#define FDF_CLK_MODE_ENABLE BIT2
+#define STM_CLK_MODE_ENABLE BIT0
+
+// CRI_RST Register definitions
+#define FDF_SRST BIT3
+#define MTE_SRST BIT2
+#define FCI_SRST BIT1
+#define AAI_SRST BIT0
+
+// MEI_TO_ARC_INTERRUPT Register definitions
+#define MEI_TO_ARC_INT1 BIT3
+#define MEI_TO_ARC_INT0 BIT2
+#define MEI_TO_ARC_CS_DONE BIT1 //need to check
+#define MEI_TO_ARC_MSGAV BIT0
+
+// ARC_TO_MEI_INTERRUPT Register definitions
+#define ARC_TO_MEI_INT1 BIT8
+#define ARC_TO_MEI_INT0 BIT7
+#define ARC_TO_MEI_CS_REQ BIT6
+#define ARC_TO_MEI_DBG_DONE BIT5
+#define ARC_TO_MEI_MSGACK BIT4
+#define ARC_TO_MEI_NO_ACCESS BIT3
+#define ARC_TO_MEI_CHECK_AAITX BIT2
+#define ARC_TO_MEI_CHECK_AAIRX BIT1
+#define ARC_TO_MEI_MSGAV BIT0
+
+// ARC_TO_MEI_INTERRUPT_MASK Register definitions
+#define GP_INT1_EN BIT8
+#define GP_INT0_EN BIT7
+#define CS_REQ_EN BIT6
+#define DBG_DONE_EN BIT5
+#define MSGACK_EN BIT4
+#define NO_ACC_EN BIT3
+#define AAITX_EN BIT2
+#define AAIRX_EN BIT1
+#define MSGAV_EN BIT0
+
+#define MEI_SOFT_RESET BIT0
+
+#define HOST_MSTR BIT0
+
+#define JTAG_MASTER_MODE 0x0
+#define MEI_MASTER_MODE HOST_MSTR
+
+// MEI_DEBUG_DECODE Register definitions
+#define MEI_DEBUG_DEC_MASK (0x3)
+#define MEI_DEBUG_DEC_AUX_MASK (0x0)
+#define ME_DBG_DECODE_DMP1_MASK (0x1)
+#define MEI_DEBUG_DEC_DMP2_MASK (0x2)
+#define MEI_DEBUG_DEC_CORE_MASK (0x3)
+
+#define AUX_STATUS (0x0)
+#define AUX_ARC_GPIO_CTRL (0x10C)
+#define AUX_ARC_GPIO_DATA (0x10D)
+// ARC_TO_MEI_MAILBOX[11] is a special location used to indicate
+// page swap requests.
+#if defined(CONFIG_DANUBE)
+#define OMBOX_BASE 0xDF80
+#define ARC_TO_MEI_MAILBOX 0xDFA0
+#define IMBOX_BASE 0xDFC0
+#define MEI_TO_ARC_MAILBOX 0xDFD0
+#elif defined(CONFIG_AMAZON_SE) || defined(CONFIG_AR9) || defined(CONFIG_VR9)
+#define OMBOX_BASE 0xAF80
+#define ARC_TO_MEI_MAILBOX 0xAFA0
+#define IMBOX_BASE 0xAFC0
+#define MEI_TO_ARC_MAILBOX 0xAFD0
+#endif
+
+#define MEI_TO_ARC_MAILBOXR (MEI_TO_ARC_MAILBOX + 0x2C)
+#define ARC_MEI_MAILBOXR (ARC_TO_MEI_MAILBOX + 0x2C)
+#define OMBOX1 (OMBOX_BASE+0x4)
+
+// Codeswap request messages are indicated by setting BIT31
+#define OMB_CODESWAP_MESSAGE_MSG_TYPE_MASK (0x80000000)
+
+// Clear Eoc messages received are indicated by setting BIT17
+#define OMB_CLEAREOC_INTERRUPT_CODE (0x00020000)
+#define OMB_REBOOT_INTERRUPT_CODE (1 << 18)
+
+/*
+** Swap page header
+*/
+// Page must be loaded at boot time if size field has BIT31 set
+#define BOOT_FLAG (BIT31)
+#define BOOT_FLAG_MASK ~BOOT_FLAG
+
+#define FREE_RELOAD 1
+#define FREE_SHOWTIME 2
+#define FREE_ALL 3
+
+// marcos
+#define IFX_MEI_WRITE_REGISTER_L(data,addr) *((volatile u32*)(addr)) = (u32)(data)
+#define IFX_MEI_READ_REGISTER_L(addr) (*((volatile u32*)(addr)))
+#define SET_BIT(reg, mask) reg |= (mask)
+#define CLEAR_BIT(reg, mask) reg &= (~mask)
+#define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask)
+//#define SET_BITS(reg, mask) SET_BIT(reg, mask)
+#define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);}
+
+#define ALIGN_SIZE ( 1L<<10 ) //1K size align
+#define MEM_ALIGN(addr) (((addr) + ALIGN_SIZE - 1) & ~ (ALIGN_SIZE -1) )
+
+// swap marco
+#define MEI_HALF_WORD_SWAP(data) {data = ((data & 0xffff)<<16) + ((data & 0xffff0000)>>16);}
+#define MEI_BYTE_SWAP(data) {data = ((data & 0xff)<<24) + ((data & 0xff00)<<8)+ ((data & 0xff0000)>>8)+ ((data & 0xff000000)>>24);}
+
+
+#ifdef CONFIG_PROC_FS
+typedef struct reg_entry
+{
+ int *flag;
+ char name[30]; /* big enough to hold names */
+ char description[100]; /* big enough to hold description */
+ unsigned short low_ino;
+} reg_entry_t;
+#endif
+// Swap page header describes size in 32-bit words, load location, and image offset
+// for program and/or data segments
+typedef struct _arc_swp_page_hdr {
+ u32 p_offset; //Offset bytes of progseg from beginning of image
+ u32 p_dest; //Destination addr of progseg on processor
+ u32 p_size; //Size in 32-bitwords of program segment
+ u32 d_offset; //Offset bytes of dataseg from beginning of image
+ u32 d_dest; //Destination addr of dataseg on processor
+ u32 d_size; //Size in 32-bitwords of data segment
+} ARC_SWP_PAGE_HDR;
+
+/*
+** Swap image header
+*/
+#define GET_PROG 0 // Flag used for program mem segment
+#define GET_DATA 1 // Flag used for data mem segment
+
+// Image header contains size of image, checksum for image, and count of
+// page headers. Following that are 'count' page headers followed by
+// the code and/or data segments to be loaded
+typedef struct _arc_img_hdr {
+ u32 size; // Size of binary image in bytes
+ u32 checksum; // Checksum for image
+ u32 count; // Count of swp pages in image
+ ARC_SWP_PAGE_HDR page[1]; // Should be "count" pages - '1' to make compiler happy
+} ARC_IMG_HDR;
+
+typedef struct smmu_mem_info {
+ int type;
+ int boot;
+ unsigned long nCopy;
+ unsigned long size;
+ unsigned char *address;
+ unsigned char *org_address;
+} smmu_mem_info_t;
+
+#ifdef __KERNEL__
+typedef struct ifx_mei_device_private {
+ int modem_ready;
+ int arcmsgav;
+ int cmv_reply;
+ int cmv_waiting;
+ // Mei to ARC CMV count, reply count, ARC Indicator count
+ int modem_ready_cnt;
+ int cmv_count;
+ int reply_count;
+ unsigned long image_size;
+ int nBar;
+ u16 Recent_indicator[MSG_LENGTH];
+
+ u16 CMV_RxMsg[MSG_LENGTH] __attribute__ ((aligned (4)));
+
+ smmu_mem_info_t adsl_mem_info[MAX_BAR_REGISTERS];
+ ARC_IMG_HDR *img_hdr;
+ // to wait for arc cmv reply, sleep on wait_queue_arcmsgav;
+ wait_queue_head_t wait_queue_arcmsgav;
+ wait_queue_head_t wait_queue_modemready;
+ struct semaphore mei_cmv_sema;
+} ifx_mei_device_private_t;
+#endif
+typedef struct winhost_message {
+ union {
+ u16 RxMessage[MSG_LENGTH] __attribute__ ((aligned (4)));
+ u16 TxMessage[MSG_LENGTH] __attribute__ ((aligned (4)));
+ } msg;
+} DSL_DEV_WinHost_Message_t;
+/********************************************************************************************************
+ * DSL CPE API Driver Stack Interface Definitions
+ * *****************************************************************************************************/
+/** IOCTL codes for bsp driver */
+#define DSL_IOC_MEI_BSP_MAGIC 's'
+
+#define DSL_FIO_BSP_DSL_START _IO (DSL_IOC_MEI_BSP_MAGIC, 0)
+#define DSL_FIO_BSP_RUN _IO (DSL_IOC_MEI_BSP_MAGIC, 1)
+#define DSL_FIO_BSP_FREE_RESOURCE _IO (DSL_IOC_MEI_BSP_MAGIC, 2)
+#define DSL_FIO_BSP_RESET _IO (DSL_IOC_MEI_BSP_MAGIC, 3)
+#define DSL_FIO_BSP_REBOOT _IO (DSL_IOC_MEI_BSP_MAGIC, 4)
+#define DSL_FIO_BSP_HALT _IO (DSL_IOC_MEI_BSP_MAGIC, 5)
+#define DSL_FIO_BSP_BOOTDOWNLOAD _IO (DSL_IOC_MEI_BSP_MAGIC, 6)
+#define DSL_FIO_BSP_JTAG_ENABLE _IO (DSL_IOC_MEI_BSP_MAGIC, 7)
+#define DSL_FIO_FREE_RESOURCE _IO (DSL_IOC_MEI_BSP_MAGIC, 8)
+#define DSL_FIO_ARC_MUX_TEST _IO (DSL_IOC_MEI_BSP_MAGIC, 9)
+#define DSL_FIO_BSP_REMOTE _IOW (DSL_IOC_MEI_BSP_MAGIC, 10, u32)
+#define DSL_FIO_BSP_GET_BASE_ADDRESS _IOR (DSL_IOC_MEI_BSP_MAGIC, 11, u32)
+#define DSL_FIO_BSP_IS_MODEM_READY _IOR (DSL_IOC_MEI_BSP_MAGIC, 12, u32)
+#define DSL_FIO_BSP_GET_VERSION _IOR (DSL_IOC_MEI_BSP_MAGIC, 13, DSL_DEV_Version_t)
+#define DSL_FIO_BSP_CMV_WINHOST _IOWR(DSL_IOC_MEI_BSP_MAGIC, 14, DSL_DEV_WinHost_Message_t)
+#define DSL_FIO_BSP_CMV_READ _IOWR(DSL_IOC_MEI_BSP_MAGIC, 15, DSL_DEV_MeiReg_t)
+#define DSL_FIO_BSP_CMV_WRITE _IOW (DSL_IOC_MEI_BSP_MAGIC, 16, DSL_DEV_MeiReg_t)
+#define DSL_FIO_BSP_DEBUG_READ _IOWR(DSL_IOC_MEI_BSP_MAGIC, 17, DSL_DEV_MeiDebug_t)
+#define DSL_FIO_BSP_DEBUG_WRITE _IOWR(DSL_IOC_MEI_BSP_MAGIC, 18, DSL_DEV_MeiDebug_t)
+#define DSL_FIO_BSP_GET_CHIP_INFO _IOR (DSL_IOC_MEI_BSP_MAGIC, 19, DSL_DEV_HwVersion_t)
+
+#define DSL_DEV_MEIDEBUG_BUFFER_SIZES 512
+
+typedef struct DSL_DEV_MeiDebug
+{
+ DSL_uint32_t iAddress;
+ DSL_uint32_t iCount;
+ DSL_uint32_t buffer[DSL_DEV_MEIDEBUG_BUFFER_SIZES];
+} DSL_DEV_MeiDebug_t; /* meidebug */
+
+/**
+ * Structure is used for debug access only.
+ * Refer to configure option INCLUDE_ADSL_WINHOST_DEBUG */
+typedef struct struct_meireg
+{
+ /*
+ * Specifies that address for debug access */
+ unsigned long iAddress;
+ /*
+ * Specifies the pointer to the data that has to be written or returns a
+ * pointer to the data that has been read out*/
+ unsigned long iData;
+} DSL_DEV_MeiReg_t; /* meireg */
+
+typedef struct DSL_DEV_Device
+{
+ DSL_int_t nInUse; /* modem state, update by bsp driver, */
+ DSL_void_t *pPriv;
+ DSL_uint32_t base_address; /* mei base address */
+ DSL_int_t nIrq[2]; /* irq number */
+#define IFX_DFEIR 0
+#define IFX_DYING_GASP 1
+ DSL_DEV_MeiDebug_t lop_debugwr; /* dying gasp */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+ struct module *owner;
+#endif
+} DSL_DEV_Device_t; /* ifx_adsl_device_t */
+
+#define DSL_DEV_PRIVATE(dev) ((ifx_mei_device_private_t*)(dev->pPriv))
+
+typedef struct DSL_DEV_Version /* ifx_adsl_bsp_version */
+{
+ unsigned long major;
+ unsigned long minor;
+ unsigned long revision;
+} DSL_DEV_Version_t; /* ifx_adsl_bsp_version_t */
+
+typedef struct DSL_DEV_ChipInfo
+{
+ unsigned long major;
+ unsigned long minor;
+} DSL_DEV_HwVersion_t;
+
+typedef struct
+{
+ DSL_uint8_t dummy;
+} DSL_DEV_DeviceConfig_t;
+
+/** error code definitions */
+typedef enum DSL_DEV_MeiError
+{
+ DSL_DEV_MEI_ERR_SUCCESS = 0,
+ DSL_DEV_MEI_ERR_FAILURE = -1,
+ DSL_DEV_MEI_ERR_MAILBOX_FULL = -2,
+ DSL_DEV_MEI_ERR_MAILBOX_EMPTY = -3,
+ DSL_DEV_MEI_ERR_MAILBOX_TIMEOUT = -4
+} DSL_DEV_MeiError_t; /* MEI_ERROR */
+
+typedef enum {
+ DSL_BSP_MEMORY_READ=0,
+ DSL_BSP_MEMORY_WRITE,
+} DSL_BSP_MemoryAccessType_t; /* ifx_adsl_memory_access_type_t */
+
+typedef enum
+{
+ DSL_LED_LINK_ID=0,
+ DSL_LED_DATA_ID
+} DSL_DEV_LedId_t; /* ifx_adsl_led_id_t */
+
+typedef enum
+{
+ DSL_LED_LINK_TYPE=0,
+ DSL_LED_DATA_TYPE
+} DSL_DEV_LedType_t; /* ifx_adsl_led_type_t */
+
+typedef enum
+{
+ DSL_LED_HD_CPU=0,
+ DSL_LED_HD_FW
+} DSL_DEV_LedHandler_t; /* ifx_adsl_led_handler_t */
+
+typedef enum {
+ DSL_LED_ON=0,
+ DSL_LED_OFF,
+ DSL_LED_FLASH,
+} DSL_DEV_LedMode_t; /* ifx_adsl_led_mode_t */
+
+typedef enum {
+ DSL_CPU_HALT=0,
+ DSL_CPU_RUN,
+ DSL_CPU_RESET,
+} DSL_DEV_CpuMode_t; /* ifx_adsl_cpu_mode_t */
+
+#if 0
+typedef enum {
+ DSL_BSP_EVENT_DYING_GASP = 0,
+ DSL_BSP_EVENT_CEOC_IRQ,
+} DSL_BSP_Event_id_t; /* ifx_adsl_event_id_t */
+
+typedef union DSL_BSP_CB_Param
+{
+ DSL_uint32_t nIrqMessage;
+} DSL_BSP_CB_Param_t; /* ifx_adsl_cbparam_t */
+
+typedef struct DSL_BSP_CB_Event
+{
+ DSL_BSP_Event_id_t nID;
+ DSL_DEV_Device_t *pDev;
+ DSL_BSP_CB_Param_t *pParam;
+} DSL_BSP_CB_Event_t; /* ifx_adsl_cb_event_t */
+#endif
+
+/* external functions (from the BSP Driver) */
+extern DSL_DEV_Device_t* DSL_BSP_DriverHandleGet(int, int);
+extern DSL_int_t DSL_BSP_DriverHandleDelete(DSL_DEV_Device_t *);
+extern DSL_DEV_MeiError_t DSL_BSP_FWDownload(DSL_DEV_Device_t *, const DSL_char_t *, DSL_uint32_t, DSL_int32_t *, DSL_int32_t *);
+extern int DSL_BSP_KernelIoctls(DSL_DEV_Device_t *, unsigned int, unsigned long);
+extern DSL_DEV_MeiError_t DSL_BSP_SendCMV(DSL_DEV_Device_t *, DSL_uint16_t *, DSL_int_t, DSL_uint16_t *);
+extern DSL_DEV_MeiError_t DSL_BSP_AdslLedInit(DSL_DEV_Device_t *, DSL_DEV_LedId_t, DSL_DEV_LedType_t, DSL_DEV_LedHandler_t);
+extern DSL_DEV_MeiError_t DSL_BSP_Showtime(DSL_DEV_Device_t *, DSL_uint32_t, DSL_uint32_t);
+extern int DSL_BSP_ATMLedCBRegister( int (*ifx_adsl_ledcallback)(void));
+extern DSL_DEV_MeiError_t DSL_BSP_MemoryDebugAccess(DSL_DEV_Device_t *, DSL_BSP_MemoryAccessType_t, DSL_uint32_t, DSL_uint32_t *, DSL_uint32_t);
+extern volatile DSL_DEV_Device_t *adsl_dev;
+
+/**
+ * Dummy structure by now to show mechanism of extended data that will be
+ * provided within event callback itself.
+ * */
+typedef struct
+{
+ /**
+ * Dummy value */
+ DSL_uint32_t nDummy1;
+} DSL_BSP_CB_Event1DataDummy_t;
+
+/**
+ * Dummy structure by now to show mechanism of extended data that will be
+ * provided within event callback itself.
+ * */
+typedef struct
+{
+ /**
+ * Dummy value */
+ DSL_uint32_t nDummy2;
+} DSL_BSP_CB_Event2DataDummy_t;
+
+/**
+ * encapsulate all data structures that are necessary for status event
+ * callbacks.
+ * */
+typedef union
+{
+ DSL_BSP_CB_Event1DataDummy_t dataEvent1;
+ DSL_BSP_CB_Event2DataDummy_t dataEvent2;
+} DSL_BSP_CB_DATA_Union_t;
+
+
+typedef enum
+{
+ /**
+ * Informs the upper layer driver (DSL CPE API) about a reboot request from the
+ * firmware.
+ * \note This event does NOT include any additional data.
+ * More detailed information upon reboot reason has to be requested from
+ * upper layer software via CMV (INFO 109) if necessary. */
+ DSL_BSP_CB_FIRST = 0,
+ DSL_BSP_CB_DYING_GASP,
+ DSL_BSP_CB_CEOC_IRQ,
+ DSL_BSP_CB_FIRMWARE_REBOOT,
+ /**
+ * Delimiter only */
+ DSL_BSP_CB_LAST
+} DSL_BSP_CB_Type_t;
+
+/**
+ * Specifies the common event type that has to be used for registering and
+ * signalling of interrupts/autonomous status events from MEI BSP Driver.
+ *
+ * \param pDev
+ * Context pointer from MEI BSP Driver.
+ *
+ * \param IFX_ADSL_BSP_CallbackType_t
+ * Specifies the event callback type (reason of callback). Regrading to the
+ * setting of this value the data which is included in the following union
+ * might have different meanings.
+ * Please refer to the description of the union to get information about the
+ * meaning of the included data.
+ *
+ * \param pData
+ * Data according to \ref DSL_BSP_CB_DATA_Union_t.
+ * If this pointer is NULL there is no additional data available.
+ *
+ * \return depending on event
+ */
+typedef int (*DSL_BSP_EventCallback_t)
+(
+ DSL_DEV_Device_t *pDev,
+ DSL_BSP_CB_Type_t nCallbackType,
+ DSL_BSP_CB_DATA_Union_t *pData
+);
+
+typedef struct {
+ DSL_BSP_EventCallback_t function;
+ DSL_BSP_CB_Type_t event;
+ DSL_BSP_CB_DATA_Union_t *pData;
+} DSL_BSP_EventCallBack_t;
+
+extern int DSL_BSP_EventCBRegister(DSL_BSP_EventCallBack_t *);
+extern int DSL_BSP_EventCBUnregister(DSL_BSP_EventCallBack_t *);
+
+/** Modem states */
+#define DSL_DEV_STAT_InitState 0x0000
+#define DSL_DEV_STAT_ReadyState 0x0001
+#define DSL_DEV_STAT_FailState 0x0002
+#define DSL_DEV_STAT_IdleState 0x0003
+#define DSL_DEV_STAT_QuietState 0x0004
+#define DSL_DEV_STAT_GhsState 0x0005
+#define DSL_DEV_STAT_FullInitState 0x0006
+#define DSL_DEV_STAT_ShowTimeState 0x0007
+#define DSL_DEV_STAT_FastRetrainState 0x0008
+#define DSL_DEV_STAT_LoopDiagMode 0x0009
+#define DSL_DEV_STAT_ShortInit 0x000A /* Bis short initialization */
+
+#define DSL_DEV_STAT_CODESWAP_COMPLETE 0x0002
+
+#endif //IFXMIPS_MEI_H
diff --git a/package/ltq-dsl/src/lantiq_mei.c b/package/ltq-dsl/src/lantiq_mei.c
new file mode 100644
index 000000000..aadb098c6
--- /dev/null
+++ b/package/ltq-dsl/src/lantiq_mei.c
@@ -0,0 +1,3038 @@
+/******************************************************************************
+
+ Copyright (c) 2009
+ Infineon Technologies AG
+ Am Campeon 1-12; 81726 Munich, Germany
+
+ For licensing information, see the file 'LICENSE' in the root folder of
+ this software module.
+
+******************************************************************************/
+
+/*!
+ \defgroup AMAZON_S_MEI Amazon-S MEI Driver Module
+ \brief Amazon-S MEI driver module
+ */
+
+/*!
+ \defgroup Internal Compile Parametere
+ \ingroup AMAZON_S_MEI
+ \brief exported functions for other driver use
+ */
+
+/*!
+ \file amazon_s_mei_bsp.c
+ \ingroup AMAZON_S_MEI
+ \brief Amazon-S MEI driver file
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
+#include <linux/utsrelease.h>
+#else
+#include <generated/utsrelease.h>
+#endif
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+#include <asm/hardirq.h>
+
+#include <lantiq_soc.h>
+#include "ifxmips_atm.h"
+#define IFX_MEI_BSP
+#include "ifxmips_mei_interface.h"
+
+/*#define LTQ_RCU_RST IFX_RCU_RST_REQ
+#define LTQ_RCU_RST_REQ_ARC_JTAG IFX_RCU_RST_REQ_ARC_JTAG
+#define LTQ_RCU_RST_REQ_DFE IFX_RCU_RST_REQ_DFE
+#define LTQ_RCU_RST_REQ_AFE IFX_RCU_RST_REQ_AFE
+#define IFXMIPS_FUSE_BASE_ADDR IFX_FUSE_BASE_ADDR
+#define IFXMIPS_ICU_IM0_IER IFX_ICU_IM0_IER
+#define IFXMIPS_ICU_IM2_IER IFX_ICU_IM2_IER
+#define LTQ_MEI_INT IFX_MEI_INT
+#define LTQ_MEI_DYING_GASP_INT IFX_MEI_DYING_GASP_INT
+#define LTQ_MEI_BASE_ADDR IFX_MEI_SPACE_ACCESS
+#define IFXMIPS_PMU_PWDCR IFX_PMU_PWDCR
+#define IFXMIPS_MPS_CHIPID IFX_MPS_CHIPID
+
+#define ifxmips_port_reserve_pin ifx_gpio_pin_reserve
+#define ifxmips_port_set_dir_in ifx_gpio_dir_in_set
+#define ifxmips_port_clear_altsel0 ifx_gpio_altsel0_set
+#define ifxmips_port_clear_altsel1 ifx_gpio_altsel1_clear
+#define ifxmips_port_set_open_drain ifx_gpio_open_drain_clear
+#define ifxmips_port_free_pin ifx_gpio_pin_free
+#define ifxmips_mask_and_ack_irq bsp_mask_and_ack_irq
+#define IFXMIPS_MPS_CHIPID_VERSION_GET IFX_MCD_CHIPID_VERSION_GET
+#define ltq_r32(reg) __raw_readl(reg)
+#define ltq_w32(val, reg) __raw_writel(val, reg)
+#define ltq_w32_mask(clear, set, reg) ltq_w32((ltq_r32(reg) & ~clear) | set, reg)
+*/
+
+#define LTQ_RCU_RST_REQ_DFE (1 << 7)
+#define LTQ_RCU_RST_REQ_AFE (1 << 11)
+
+#define LTQ_PMU_BASE (KSEG1 + LTQ_PMU_BASE_ADDR)
+#define LTQ_RCU_BASE (KSEG1 + LTQ_RCU_BASE_ADDR)
+#define LTQ_ICU_BASE (KSEG1 + LTQ_ICU_BASE_ADDR)
+
+#define LTQ_PMU_PWDCR ((u32 *)(LTQ_PMU_BASE + 0x001C))
+#define LTQ_PMU_PWDSR ((u32 *)(LTQ_PMU_BASE + 0x0020))
+#define LTQ_RCU_RST ((u32 *)(LTQ_RCU_BASE + 0x0010))
+#define LTQ_RCU_RST_ALL 0x40000000
+
+#define LTQ_ICU_IM0_ISR ((u32 *)(LTQ_ICU_BASE + 0x0000))
+#define LTQ_ICU_IM0_IER ((u32 *)(LTQ_ICU_BASE + 0x0008))
+#define LTQ_ICU_IM0_IOSR ((u32 *)(LTQ_ICU_BASE + 0x0010))
+#define LTQ_ICU_IM0_IRSR ((u32 *)(LTQ_ICU_BASE + 0x0018))
+#define LTQ_ICU_IM0_IMR ((u32 *)(LTQ_ICU_BASE + 0x0020))
+
+
+#define LTQ_ICU_IM1_ISR ((u32 *)(LTQ_ICU_BASE + 0x0028))
+#define LTQ_ICU_IM2_ISR ((u32 *)(LTQ_ICU_BASE + 0x0050))
+#define LTQ_ICU_IM3_ISR ((u32 *)(LTQ_ICU_BASE + 0x0078))
+#define LTQ_ICU_IM4_ISR ((u32 *)(LTQ_ICU_BASE + 0x00A0))
+
+#define LTQ_ICU_OFFSET (LTQ_ICU_IM1_ISR - LTQ_ICU_IM0_ISR)
+#define LTQ_ICU_IM2_IER (LTQ_ICU_IM0_IER + LTQ_ICU_OFFSET)
+
+#define IFX_MEI_EMSG(fmt, args...) pr_err("[%s %d]: " fmt,__FUNCTION__, __LINE__, ## args)
+#define IFX_MEI_DMSG(fmt, args...) pr_debug("[%s %d]: " fmt,__FUNCTION__, __LINE__, ## args)
+
+#define LTQ_FUSE_BASE (KSEG1 + 0x1F107354)
+
+#ifdef CONFIG_LTQ_MEI_FW_LOOPBACK
+//#define DFE_MEM_TEST
+//#define DFE_PING_TEST
+#define DFE_ATM_LOOPBACK
+
+
+#ifdef DFE_ATM_LOOPBACK
+#include <asm/ifxmips/ifxmips_mei_fw_loopback.h>
+#endif
+
+void dfe_loopback_irq_handler (DSL_DEV_Device_t *pDev);
+
+#endif //CONFIG_AMAZON_S_MEI_FW_LOOPBACK
+
+DSL_DEV_Version_t bsp_mei_version = {
+ major: 5,
+ minor: 0,
+ revision:0
+};
+DSL_DEV_HwVersion_t bsp_chip_info;
+
+#define IFX_MEI_DEVNAME "ifx_mei"
+#define BSP_MAX_DEVICES 1
+
+DSL_DEV_MeiError_t DSL_BSP_FWDownload (DSL_DEV_Device_t *, const char *, unsigned long, long *, long *);
+DSL_DEV_MeiError_t DSL_BSP_Showtime (DSL_DEV_Device_t *, DSL_uint32_t, DSL_uint32_t);
+DSL_DEV_MeiError_t DSL_BSP_AdslLedInit (DSL_DEV_Device_t *, DSL_DEV_LedId_t, DSL_DEV_LedType_t, DSL_DEV_LedHandler_t);
+//DSL_DEV_MeiError_t DSL_BSP_AdslLedSet (DSL_DEV_Device_t *, DSL_DEV_LedId_t, DSL_DEV_LedMode_t);
+DSL_DEV_MeiError_t DSL_BSP_MemoryDebugAccess (DSL_DEV_Device_t *, DSL_BSP_MemoryAccessType_t, DSL_uint32_t, DSL_uint32_t*, DSL_uint32_t);
+DSL_DEV_MeiError_t DSL_BSP_SendCMV (DSL_DEV_Device_t *, u16 *, int, u16 *);
+
+int DSL_BSP_KernelIoctls (DSL_DEV_Device_t *, unsigned int, unsigned long);
+
+static DSL_DEV_MeiError_t IFX_MEI_RunAdslModem (DSL_DEV_Device_t *);
+static DSL_DEV_MeiError_t IFX_MEI_CpuModeSet (DSL_DEV_Device_t *, DSL_DEV_CpuMode_t);
+static DSL_DEV_MeiError_t IFX_MEI_DownloadBootCode (DSL_DEV_Device_t *);
+static DSL_DEV_MeiError_t IFX_MEI_ArcJtagEnable (DSL_DEV_Device_t *, int);
+static DSL_DEV_MeiError_t IFX_MEI_AdslMailboxIRQEnable (DSL_DEV_Device_t *, int);
+
+static int IFX_MEI_GetPage (DSL_DEV_Device_t *, u32, u32, u32, u32 *, u32 *);
+static int IFX_MEI_BarUpdate (DSL_DEV_Device_t *, int);
+
+static ssize_t IFX_MEI_Write (DSL_DRV_file_t *, const char *, size_t, loff_t *);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
+static int IFX_MEI_UserIoctls (DSL_DRV_inode_t *, DSL_DRV_file_t *, unsigned int, unsigned long);
+#else
+static int IFX_MEI_UserIoctls (DSL_DRV_file_t *, unsigned int, unsigned long);
+#endif
+static int IFX_MEI_Open (DSL_DRV_inode_t *, DSL_DRV_file_t *);
+static int IFX_MEI_Release (DSL_DRV_inode_t *, DSL_DRV_file_t *);
+
+void AMAZON_SE_MEI_ARC_MUX_Test(void);
+
+#ifdef CONFIG_PROC_FS
+static int IFX_MEI_ProcRead (struct file *, char *, size_t, loff_t *);
+static ssize_t IFX_MEI_ProcWrite (struct file *, const char *, size_t, loff_t *);
+
+#define PROC_ITEMS 11
+#define MEI_DIRNAME "ifxmips_mei"
+
+static struct proc_dir_entry *meidir;
+static struct file_operations IFX_MEI_ProcOperations = {
+ read:IFX_MEI_ProcRead,
+ write:IFX_MEI_ProcWrite,
+};
+static reg_entry_t regs[BSP_MAX_DEVICES][PROC_ITEMS]; //total items to be monitored by /proc/mei
+#define NUM_OF_REG_ENTRY (sizeof(regs[0])/sizeof(reg_entry_t))
+#endif //CONFIG_PROC_FS
+
+void IFX_MEI_ARC_MUX_Test(void);
+
+static int adsl_dummy_ledcallback(void);
+
+int (*ifx_mei_atm_showtime_enter)(struct port_cell_info *, void *) = NULL;
+EXPORT_SYMBOL(ifx_mei_atm_showtime_enter);
+
+int (*ifx_mei_atm_showtime_exit)(void) = NULL;
+EXPORT_SYMBOL(ifx_mei_atm_showtime_exit);
+
+static int (*g_adsl_ledcallback)(void) = adsl_dummy_ledcallback;
+
+static unsigned int g_tx_link_rate[2] = {0};
+
+static void *g_xdata_addr = NULL;
+
+static u32 *mei_arc_swap_buff = NULL; // holding swap pages
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
+extern void ltq_mask_and_ack_irq(unsigned int irq_nr);
+#define MEI_MASK_AND_ACK_IRQ ltq_mask_and_ack_irq
+#else
+extern void ltq_mask_and_ack_irq(struct irq_data *d);
+static void inline MEI_MASK_AND_ACK_IRQ(int x)
+{
+ struct irq_data d;
+ d.irq = x;
+ ltq_mask_and_ack_irq(&d);
+}
+#endif
+#define MEI_MAJOR 105
+static int dev_major = MEI_MAJOR;
+
+static struct file_operations bsp_mei_operations = {
+ owner:THIS_MODULE,
+ open:IFX_MEI_Open,
+ release:IFX_MEI_Release,
+ write:IFX_MEI_Write,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
+ ioctl:IFX_MEI_UserIoctls,
+#else
+ unlocked_ioctl:IFX_MEI_UserIoctls,
+#endif
+};
+
+static DSL_DEV_Device_t dsl_devices[BSP_MAX_DEVICES];
+
+static ifx_mei_device_private_t
+ sDanube_Mei_Private[BSP_MAX_DEVICES];
+
+static DSL_BSP_EventCallBack_t dsl_bsp_event_callback[DSL_BSP_CB_LAST + 1];
+
+/**
+ * Write a value to register
+ * This function writes a value to danube register
+ *
+ * \param ul_address The address to write
+ * \param ul_data The value to write
+ * \ingroup Internal
+ */
+static void
+IFX_MEI_LongWordWrite (u32 ul_address, u32 ul_data)
+{
+ IFX_MEI_WRITE_REGISTER_L (ul_data, ul_address);
+ wmb();
+ return;
+}
+
+/**
+ * Write a value to register
+ * This function writes a value to danube register
+ *
+ * \param pDev the device pointer
+ * \param ul_address The address to write
+ * \param ul_data The value to write
+ * \ingroup Internal
+ */
+static void
+IFX_MEI_LongWordWriteOffset (DSL_DEV_Device_t * pDev, u32 ul_address,
+ u32 ul_data)
+{
+ IFX_MEI_WRITE_REGISTER_L (ul_data, pDev->base_address + ul_address);
+ wmb();
+ return;
+}
+
+/**
+ * Read the danube register
+ * This function read the value from danube register
+ *
+ * \param ul_address The address to write
+ * \param pul_data Pointer to the data
+ * \ingroup Internal
+ */
+static void
+IFX_MEI_LongWordRead (u32 ul_address, u32 * pul_data)
+{
+ *pul_data = IFX_MEI_READ_REGISTER_L (ul_address);
+ rmb();
+ return;
+}
+
+/**
+ * Read the danube register
+ * This function read the value from danube register
+ *
+ * \param pDev the device pointer
+ * \param ul_address The address to write
+ * \param pul_data Pointer to the data
+ * \ingroup Internal
+ */
+static void
+IFX_MEI_LongWordReadOffset (DSL_DEV_Device_t * pDev, u32 ul_address,
+ u32 * pul_data)
+{
+ *pul_data = IFX_MEI_READ_REGISTER_L (pDev->base_address + ul_address);
+ rmb();
+ return;
+}
+
+/**
+ * Write several DWORD datas to ARC memory via ARC DMA interface
+ * This function writes several DWORD datas to ARC memory via DMA interface.
+ *
+ * \param pDev the device pointer
+ * \param destaddr The address to write
+ * \param databuff Pointer to the data buffer
+ * \param databuffsize Number of DWORDs to write
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+static DSL_DEV_MeiError_t
+IFX_MEI_DMAWrite (DSL_DEV_Device_t * pDev, u32 destaddr,
+ u32 * databuff, u32 databuffsize)
+{
+ u32 *p = databuff;
+ u32 temp;
+
+ if (destaddr & 3)
+ return DSL_DEV_MEI_ERR_FAILURE;
+
+ // Set the write transfer address
+ IFX_MEI_LongWordWriteOffset (pDev, ME_DX_AD, destaddr);
+
+ // Write the data pushed across DMA
+ while (databuffsize--) {
+ temp = *p;
+ if (destaddr == MEI_TO_ARC_MAILBOX)
+ MEI_HALF_WORD_SWAP (temp);
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DX_DATA, temp);
+ p++;
+ }
+
+ return DSL_DEV_MEI_ERR_SUCCESS;
+
+}
+
+/**
+ * Read several DWORD datas from ARC memory via ARC DMA interface
+ * This function reads several DWORD datas from ARC memory via DMA interface.
+ *
+ * \param pDev the device pointer
+ * \param srcaddr The address to read
+ * \param databuff Pointer to the data buffer
+ * \param databuffsize Number of DWORDs to read
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+static DSL_DEV_MeiError_t
+IFX_MEI_DMARead (DSL_DEV_Device_t * pDev, u32 srcaddr, u32 * databuff,
+ u32 databuffsize)
+{
+ u32 *p = databuff;
+ u32 temp;
+
+ if (srcaddr & 3)
+ return DSL_DEV_MEI_ERR_FAILURE;
+
+ // Set the read transfer address
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DX_AD, srcaddr);
+
+ // Read the data popped across DMA
+ while (databuffsize--) {
+ IFX_MEI_LongWordReadOffset (pDev, (u32) ME_DX_DATA, &temp);
+ if (databuff == (u32 *) DSL_DEV_PRIVATE(pDev)->CMV_RxMsg) // swap half word
+ MEI_HALF_WORD_SWAP (temp);
+ *p = temp;
+ p++;
+ }
+
+ return DSL_DEV_MEI_ERR_SUCCESS;
+
+}
+
+/**
+ * Switch the ARC control mode
+ * This function switchs the ARC control mode to JTAG mode or MEI mode
+ *
+ * \param pDev the device pointer
+ * \param mode The mode want to switch: JTAG_MASTER_MODE or MEI_MASTER_MODE.
+ * \ingroup Internal
+ */
+static void
+IFX_MEI_ControlModeSet (DSL_DEV_Device_t * pDev, int mode)
+{
+ u32 temp = 0x0;
+
+ IFX_MEI_LongWordReadOffset (pDev, (u32) ME_DBG_MASTER, &temp);
+ switch (mode) {
+ case JTAG_MASTER_MODE:
+ temp &= ~(HOST_MSTR);
+ break;
+ case MEI_MASTER_MODE:
+ temp |= (HOST_MSTR);
+ break;
+ default:
+ IFX_MEI_EMSG ("IFX_MEI_ControlModeSet: unkonwn mode [%d]\n", mode);
+ return;
+ }
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_MASTER, temp);
+}
+
+/**
+ * Disable ARC to MEI interrupt
+ *
+ * \param pDev the device pointer
+ * \ingroup Internal
+ */
+static void
+IFX_MEI_IRQDisable (DSL_DEV_Device_t * pDev)
+{
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_MASK, 0x0);
+}
+
+/**
+ * Eable ARC to MEI interrupt
+ *
+ * \param pDev the device pointer
+ * \ingroup Internal
+ */
+static void
+IFX_MEI_IRQEnable (DSL_DEV_Device_t * pDev)
+{
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_MASK, MSGAV_EN);
+}
+
+/**
+ * Poll for transaction complete signal
+ * This function polls and waits for transaction complete signal.
+ *
+ * \param pDev the device pointer
+ * \ingroup Internal
+ */
+static void
+meiPollForDbgDone (DSL_DEV_Device_t * pDev)
+{
+ u32 query = 0;
+ int i = 0;
+
+ while (i < WHILE_DELAY) {
+ IFX_MEI_LongWordReadOffset (pDev, (u32) ME_ARC2ME_STAT, &query);
+ query &= (ARC_TO_MEI_DBG_DONE);
+ if (query)
+ break;
+ i++;
+ if (i == WHILE_DELAY) {
+ IFX_MEI_EMSG ("PollforDbg fail!\n");
+ }
+ }
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_STAT, ARC_TO_MEI_DBG_DONE); // to clear this interrupt
+}
+
+/**
+ * ARC Debug Memory Access for a single DWORD reading.
+ * This function used for direct, address-based access to ARC memory.
+ *
+ * \param pDev the device pointer
+ * \param DEC_mode ARC memory space to used
+ * \param address Address to read
+ * \param data Pointer to data
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+static DSL_DEV_MeiError_t
+_IFX_MEI_DBGLongWordRead (DSL_DEV_Device_t * pDev, u32 DEC_mode,
+ u32 address, u32 * data)
+{
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_DECODE, DEC_mode);
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_RD_AD, address);
+ meiPollForDbgDone (pDev);
+ IFX_MEI_LongWordReadOffset (pDev, (u32) ME_DBG_DATA, data);
+ return DSL_DEV_MEI_ERR_SUCCESS;
+}
+
+/**
+ * ARC Debug Memory Access for a single DWORD writing.
+ * This function used for direct, address-based access to ARC memory.
+ *
+ * \param pDev the device pointer
+ * \param DEC_mode ARC memory space to used
+ * \param address The address to write
+ * \param data The data to write
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+static DSL_DEV_MeiError_t
+_IFX_MEI_DBGLongWordWrite (DSL_DEV_Device_t * pDev, u32 DEC_mode,
+ u32 address, u32 data)
+{
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_DECODE, DEC_mode);
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_WR_AD, address);
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_DATA, data);
+ meiPollForDbgDone (pDev);
+ return DSL_DEV_MEI_ERR_SUCCESS;
+}
+
+/**
+ * ARC Debug Memory Access for writing.
+ * This function used for direct, address-based access to ARC memory.
+ *
+ * \param pDev the device pointer
+ * \param destaddr The address to read
+ * \param databuffer Pointer to data
+ * \param databuffsize The number of DWORDs to read
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+
+static DSL_DEV_MeiError_t
+IFX_MEI_DebugWrite (DSL_DEV_Device_t * pDev, u32 destaddr,
+ u32 * databuff, u32 databuffsize)
+{
+ u32 i;
+ u32 temp = 0x0;
+ u32 address = 0x0;
+ u32 *buffer = 0x0;
+
+ // Open the debug port before DMP memory write
+ IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
+
+ // For the requested length, write the address and write the data
+ address = destaddr;
+ buffer = databuff;
+ for (i = 0; i < databuffsize; i++) {
+ temp = *buffer;
+ _IFX_MEI_DBGLongWordWrite (pDev, ME_DBG_DECODE_DMP1_MASK, address, temp);
+ address += 4;
+ buffer++;
+ }
+
+ // Close the debug port after DMP memory write
+ IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
+
+ return DSL_DEV_MEI_ERR_SUCCESS;
+}
+
+/**
+ * ARC Debug Memory Access for reading.
+ * This function used for direct, address-based access to ARC memory.
+ *
+ * \param pDev the device pointer
+ * \param srcaddr The address to read
+ * \param databuffer Pointer to data
+ * \param databuffsize The number of DWORDs to read
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+static DSL_DEV_MeiError_t
+IFX_MEI_DebugRead (DSL_DEV_Device_t * pDev, u32 srcaddr, u32 * databuff, u32 databuffsize)
+{
+ u32 i;
+ u32 temp = 0x0;
+ u32 address = 0x0;
+ u32 *buffer = 0x0;
+
+ // Open the debug port before DMP memory read
+ IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
+
+ // For the requested length, write the address and read the data
+ address = srcaddr;
+ buffer = databuff;
+ for (i = 0; i < databuffsize; i++) {
+ _IFX_MEI_DBGLongWordRead (pDev, ME_DBG_DECODE_DMP1_MASK, address, &temp);
+ *buffer = temp;
+ address += 4;
+ buffer++;
+ }
+
+ // Close the debug port after DMP memory read
+ IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
+
+ return DSL_DEV_MEI_ERR_SUCCESS;
+}
+
+/**
+ * Send a message to ARC MailBox.
+ * This function sends a message to ARC Mailbox via ARC DMA interface.
+ *
+ * \param pDev the device pointer
+ * \param msgsrcbuffer Pointer to message.
+ * \param msgsize The number of words to write.
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+static DSL_DEV_MeiError_t
+IFX_MEI_MailboxWrite (DSL_DEV_Device_t * pDev, u16 * msgsrcbuffer,
+ u16 msgsize)
+{
+ int i;
+ u32 arc_mailbox_status = 0x0;
+ u32 temp = 0;
+ DSL_DEV_MeiError_t meiMailboxError = DSL_DEV_MEI_ERR_SUCCESS;
+
+ // Write to mailbox
+ meiMailboxError =
+ IFX_MEI_DMAWrite (pDev, MEI_TO_ARC_MAILBOX, (u32 *) msgsrcbuffer, msgsize / 2);
+ meiMailboxError =
+ IFX_MEI_DMAWrite (pDev, MEI_TO_ARC_MAILBOXR, (u32 *) (&temp), 1);
+
+ // Notify arc that mailbox write completed
+ DSL_DEV_PRIVATE(pDev)->cmv_waiting = 1;
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ME2ARC_INT, MEI_TO_ARC_MSGAV);
+
+ i = 0;
+ while (i < WHILE_DELAY) { // wait for ARC to clear the bit
+ IFX_MEI_LongWordReadOffset (pDev, (u32) ME_ME2ARC_INT, &arc_mailbox_status);
+ if ((arc_mailbox_status & MEI_TO_ARC_MSGAV) != MEI_TO_ARC_MSGAV)
+ break;
+ i++;
+ if (i == WHILE_DELAY) {
+ IFX_MEI_EMSG (">>> Timeout waiting for ARC to clear MEI_TO_ARC_MSGAV!!!"
+ " MEI_TO_ARC message size = %d DWORDs <<<\n", msgsize/2);
+ meiMailboxError = DSL_DEV_MEI_ERR_FAILURE;
+ }
+ }
+
+ return meiMailboxError;
+}
+
+/**
+ * Read a message from ARC MailBox.
+ * This function reads a message from ARC Mailbox via ARC DMA interface.
+ *
+ * \param pDev the device pointer
+ * \param msgsrcbuffer Pointer to message.
+ * \param msgsize The number of words to read
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+static DSL_DEV_MeiError_t
+IFX_MEI_MailboxRead (DSL_DEV_Device_t * pDev, u16 * msgdestbuffer,
+ u16 msgsize)
+{
+ DSL_DEV_MeiError_t meiMailboxError = DSL_DEV_MEI_ERR_SUCCESS;
+ // Read from mailbox
+ meiMailboxError =
+ IFX_MEI_DMARead (pDev, ARC_TO_MEI_MAILBOX, (u32 *) msgdestbuffer, msgsize / 2);
+
+ // Notify arc that mailbox read completed
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_STAT, ARC_TO_MEI_MSGAV);
+
+ return meiMailboxError;
+}
+
+/**
+ * Download boot pages to ARC.
+ * This function downloads boot pages to ARC.
+ *
+ * \param pDev the device pointer
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+static DSL_DEV_MeiError_t
+IFX_MEI_DownloadBootPages (DSL_DEV_Device_t * pDev)
+{
+ int boot_loop;
+ int page_size;
+ u32 dest_addr;
+
+ /*
+ ** DMA the boot code page(s)
+ */
+
+ for (boot_loop = 1;
+ boot_loop <
+ (DSL_DEV_PRIVATE(pDev)->img_hdr-> count); boot_loop++) {
+ if ((DSL_DEV_PRIVATE(pDev)-> img_hdr->page[boot_loop].p_size) & BOOT_FLAG) {
+ page_size = IFX_MEI_GetPage (pDev, boot_loop,
+ GET_PROG, MAXSWAPSIZE,
+ mei_arc_swap_buff,
+ &dest_addr);
+ if (page_size > 0) {
+ IFX_MEI_DMAWrite (pDev, dest_addr,
+ mei_arc_swap_buff,
+ page_size);
+ }
+ }
+ if ((DSL_DEV_PRIVATE(pDev)-> img_hdr->page[boot_loop].d_size) & BOOT_FLAG) {
+ page_size = IFX_MEI_GetPage (pDev, boot_loop,
+ GET_DATA, MAXSWAPSIZE,
+ mei_arc_swap_buff,
+ &dest_addr);
+ if (page_size > 0) {
+ IFX_MEI_DMAWrite (pDev, dest_addr,
+ mei_arc_swap_buff,
+ page_size);
+ }
+ }
+ }
+ return DSL_DEV_MEI_ERR_SUCCESS;
+}
+
+/**
+ * Initial efuse rar.
+ **/
+static void
+IFX_MEI_FuseInit (DSL_DEV_Device_t * pDev)
+{
+ u32 data = 0;
+ IFX_MEI_DMAWrite (pDev, IRAM0_BASE, &data, 1);
+ IFX_MEI_DMAWrite (pDev, IRAM0_BASE + 4, &data, 1);
+ IFX_MEI_DMAWrite (pDev, IRAM1_BASE, &data, 1);
+ IFX_MEI_DMAWrite (pDev, IRAM1_BASE + 4, &data, 1);
+ IFX_MEI_DMAWrite (pDev, BRAM_BASE, &data, 1);
+ IFX_MEI_DMAWrite (pDev, BRAM_BASE + 4, &data, 1);
+ IFX_MEI_DMAWrite (pDev, ADSL_DILV_BASE, &data, 1);
+ IFX_MEI_DMAWrite (pDev, ADSL_DILV_BASE + 4, &data, 1);
+}
+
+/**
+ * efuse rar program
+ **/
+static void
+IFX_MEI_FuseProg (DSL_DEV_Device_t * pDev)
+{
+ u32 reg_data, fuse_value;
+ int i = 0;
+
+ IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &reg_data);
+ while ((reg_data & 0x10000000) == 0) {
+ IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &reg_data);
+ i++;
+ /* 0x4000 translate to about 16 ms@111M, so should be enough */
+ if (i == 0x4000)
+ return;
+ }
+ // STEP a: Prepare memory for external accesses
+ // Write fuse_en bit24
+ IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &reg_data);
+ IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST, reg_data | (1 << 24));
+
+ IFX_MEI_FuseInit (pDev);
+ for (i = 0; i < 4; i++) {
+ IFX_MEI_LongWordRead ((u32) (LTQ_FUSE_BASE) + i * 4, &fuse_value);
+ switch (fuse_value & 0xF0000) {
+ case 0x80000:
+ reg_data = ((fuse_value & RX_DILV_ADDR_BIT_MASK) |
+ (RX_DILV_ADDR_BIT_MASK + 0x1));
+ IFX_MEI_DMAWrite (pDev, ADSL_DILV_BASE, &reg_data, 1);
+ break;
+ case 0x90000:
+ reg_data = ((fuse_value & RX_DILV_ADDR_BIT_MASK) |
+ (RX_DILV_ADDR_BIT_MASK + 0x1));
+ IFX_MEI_DMAWrite (pDev, ADSL_DILV_BASE + 4, &reg_data, 1);
+ break;
+ case 0xA0000:
+ reg_data = ((fuse_value & IRAM0_ADDR_BIT_MASK) |
+ (IRAM0_ADDR_BIT_MASK + 0x1));
+ IFX_MEI_DMAWrite (pDev, IRAM0_BASE, &reg_data, 1);
+ break;
+ case 0xB0000:
+ reg_data = ((fuse_value & IRAM0_ADDR_BIT_MASK) |
+ (IRAM0_ADDR_BIT_MASK + 0x1));
+ IFX_MEI_DMAWrite (pDev, IRAM0_BASE + 4, &reg_data, 1);
+ break;
+ case 0xC0000:
+ reg_data = ((fuse_value & IRAM1_ADDR_BIT_MASK) |
+ (IRAM1_ADDR_BIT_MASK + 0x1));
+ IFX_MEI_DMAWrite (pDev, IRAM1_BASE, &reg_data, 1);
+ break;
+ case 0xD0000:
+ reg_data = ((fuse_value & IRAM1_ADDR_BIT_MASK) |
+ (IRAM1_ADDR_BIT_MASK + 0x1));
+ IFX_MEI_DMAWrite (pDev, IRAM1_BASE + 4, &reg_data, 1);
+ break;
+ case 0xE0000:
+ reg_data = ((fuse_value & BRAM_ADDR_BIT_MASK) |
+ (BRAM_ADDR_BIT_MASK + 0x1));
+ IFX_MEI_DMAWrite (pDev, BRAM_BASE, &reg_data, 1);
+ break;
+ case 0xF0000:
+ reg_data = ((fuse_value & BRAM_ADDR_BIT_MASK) |
+ (BRAM_ADDR_BIT_MASK + 0x1));
+ IFX_MEI_DMAWrite (pDev, BRAM_BASE + 4, &reg_data, 1);
+ break;
+ default: // PPE efuse
+ break;
+ }
+ }
+ IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &reg_data);
+ IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST, reg_data & ~(1 << 24));
+ IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &reg_data);
+}
+
+/**
+ * Enable DFE Clock
+ * This function enables DFE Clock
+ *
+ * \param pDev the device pointer
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+static DSL_DEV_MeiError_t
+IFX_MEI_EnableCLK (DSL_DEV_Device_t * pDev)
+{
+ u32 arc_debug_data = 0;
+ IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
+ //enable ac_clk signal
+ _IFX_MEI_DBGLongWordRead (pDev, ME_DBG_DECODE_DMP1_MASK,
+ CRI_CCR0, &arc_debug_data);
+ arc_debug_data |= ACL_CLK_MODE_ENABLE;
+ _IFX_MEI_DBGLongWordWrite (pDev, ME_DBG_DECODE_DMP1_MASK,
+ CRI_CCR0, arc_debug_data);
+ IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
+ return DSL_DEV_MEI_ERR_SUCCESS;
+}
+
+/**
+ * Halt the ARC.
+ * This function halts the ARC.
+ *
+ * \param pDev the device pointer
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+static DSL_DEV_MeiError_t
+IFX_MEI_HaltArc (DSL_DEV_Device_t * pDev)
+{
+ u32 arc_debug_data = 0x0;
+
+ // Switch arc control from JTAG mode to MEI mode
+ IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
+ _IFX_MEI_DBGLongWordRead (pDev, MEI_DEBUG_DEC_AUX_MASK,
+ ARC_DEBUG, &arc_debug_data);
+ arc_debug_data |= ARC_DEBUG_HALT;
+ _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK,
+ ARC_DEBUG, arc_debug_data);
+ // Switch arc control from MEI mode to JTAG mode
+ IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
+
+ MEI_WAIT (10);
+
+ return DSL_DEV_MEI_ERR_SUCCESS;
+}
+
+/**
+ * Run the ARC.
+ * This function runs the ARC.
+ *
+ * \param pDev the device pointer
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+static DSL_DEV_MeiError_t
+IFX_MEI_RunArc (DSL_DEV_Device_t * pDev)
+{
+ u32 arc_debug_data = 0x0;
+
+ // Switch arc control from JTAG mode to MEI mode- write '1' to bit0
+ IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
+ _IFX_MEI_DBGLongWordRead (pDev, MEI_DEBUG_DEC_AUX_MASK,
+ AUX_STATUS, &arc_debug_data);
+
+ // Write debug data reg with content ANDd with 0xFDFFFFFF (halt bit cleared)
+ arc_debug_data &= ~ARC_AUX_HALT;
+ _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK,
+ AUX_STATUS, arc_debug_data);
+
+ // Switch arc control from MEI mode to JTAG mode- write '0' to bit0
+ IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
+ // Enable mask for arc codeswap interrupts
+ IFX_MEI_IRQEnable (pDev);
+
+ return DSL_DEV_MEI_ERR_SUCCESS;
+
+}
+
+/**
+ * Reset the ARC.
+ * This function resets the ARC.
+ *
+ * \param pDev the device pointer
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+static DSL_DEV_MeiError_t
+IFX_MEI_ResetARC (DSL_DEV_Device_t * pDev)
+{
+ u32 arc_debug_data = 0;
+
+ IFX_MEI_HaltArc (pDev);
+
+ IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &arc_debug_data);
+ IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST,
+ arc_debug_data | LTQ_RCU_RST_REQ_DFE | LTQ_RCU_RST_REQ_AFE);
+
+ // reset ARC
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_RST_CTRL, MEI_SOFT_RESET);
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_RST_CTRL, 0);
+
+ IFX_MEI_IRQDisable (pDev);
+
+ IFX_MEI_EnableCLK (pDev);
+
+#if 0
+ // reset part of PPE
+ *(unsigned long *) (BSP_PPE32_SRST) = 0xC30;
+ *(unsigned long *) (BSP_PPE32_SRST) = 0xFFF;
+#endif
+
+ DSL_DEV_PRIVATE(pDev)->modem_ready = 0;
+
+ return DSL_DEV_MEI_ERR_SUCCESS;
+}
+
+DSL_DEV_MeiError_t
+DSL_BSP_Showtime (DSL_DEV_Device_t * dev, DSL_uint32_t rate_fast, DSL_uint32_t rate_intl)
+{
+ struct port_cell_info port_cell = {0};
+
+ IFX_MEI_EMSG ("Datarate US intl = %d, fast = %d\n", (int)rate_intl,
+ (int)rate_fast);
+
+ if ( rate_fast )
+ g_tx_link_rate[0] = rate_fast / (53 * 8);
+ if ( rate_intl )
+ g_tx_link_rate[1] = rate_intl / (53 * 8);
+
+ if ( g_tx_link_rate[0] == 0 && g_tx_link_rate[1] == 0 ) {
+ IFX_MEI_EMSG ("Got rate fail.\n");
+ }
+
+ if ( ifx_mei_atm_showtime_enter )
+ {
+ port_cell.port_num = 2;
+ port_cell.tx_link_rate[0] = g_tx_link_rate[0];
+ port_cell.tx_link_rate[1] = g_tx_link_rate[1];
+ ifx_mei_atm_showtime_enter(&port_cell, g_xdata_addr);
+ }
+ else
+ {
+ IFX_MEI_EMSG("no hookup from ATM driver to set cell rate\n");
+ }
+
+ return DSL_DEV_MEI_ERR_SUCCESS;
+};
+
+/**
+ * Reset/halt/run the DFE.
+ * This function provide operations to reset/halt/run the DFE.
+ *
+ * \param pDev the device pointer
+ * \param mode which operation want to do
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+static DSL_DEV_MeiError_t
+IFX_MEI_CpuModeSet (DSL_DEV_Device_t *pDev,
+ DSL_DEV_CpuMode_t mode)
+{
+ DSL_DEV_MeiError_t err_ret = DSL_DEV_MEI_ERR_FAILURE;
+ switch (mode) {
+ case DSL_CPU_HALT:
+ err_ret = IFX_MEI_HaltArc (pDev);
+ break;
+ case DSL_CPU_RUN:
+ err_ret = IFX_MEI_RunArc (pDev);
+ break;
+ case DSL_CPU_RESET:
+ err_ret = IFX_MEI_ResetARC (pDev);
+ break;
+ default:
+ break;
+ }
+ return err_ret;
+}
+
+/**
+ * Accress DFE memory.
+ * This function provide a way to access DFE memory;
+ *
+ * \param pDev the device pointer
+ * \param type read or write
+ * \param destaddr destination address
+ * \param databuff pointer to hold data
+ * \param databuffsize size want to read/write
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+DSL_DEV_MeiError_t
+DSL_BSP_MemoryDebugAccess (DSL_DEV_Device_t * pDev,
+ DSL_BSP_MemoryAccessType_t type,
+ DSL_uint32_t destaddr, DSL_uint32_t *databuff,
+ DSL_uint32_t databuffsize)
+{
+ DSL_DEV_MeiError_t meierr = DSL_DEV_MEI_ERR_SUCCESS;
+ switch (type) {
+ case DSL_BSP_MEMORY_READ:
+ meierr = IFX_MEI_DebugRead (pDev, (u32)destaddr, (u32*)databuff, (u32)databuffsize);
+ break;
+ case DSL_BSP_MEMORY_WRITE:
+ meierr = IFX_MEI_DebugWrite (pDev, (u32)destaddr, (u32*)databuff, (u32)databuffsize);
+ break;
+ }
+ return DSL_DEV_MEI_ERR_SUCCESS;
+};
+
+/**
+ * Download boot code to ARC.
+ * This function downloads boot code to ARC.
+ *
+ * \param pDev the device pointer
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+static DSL_DEV_MeiError_t
+IFX_MEI_DownloadBootCode (DSL_DEV_Device_t *pDev)
+{
+ IFX_MEI_IRQDisable (pDev);
+
+ IFX_MEI_EnableCLK (pDev);
+
+ IFX_MEI_FuseProg (pDev); //program fuse rar
+
+ IFX_MEI_DownloadBootPages (pDev);
+
+ return DSL_DEV_MEI_ERR_SUCCESS;
+};
+
+/**
+ * Enable Jtag debugger interface
+ * This function setups mips gpio to enable jtag debugger
+ *
+ * \param pDev the device pointer
+ * \param enable enable or disable
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+static DSL_DEV_MeiError_t
+IFX_MEI_ArcJtagEnable (DSL_DEV_Device_t *dev, int enable)
+{
+ /*
+ int meierr=0;
+ u32 reg_data;
+ switch (enable) {
+ case 1:
+ //reserve gpio 9, 10, 11, 14, 19 for ARC JTAG
+ ifxmips_port_reserve_pin (0, 9);
+ ifxmips_port_reserve_pin (0, 10);
+ ifxmips_port_reserve_pin (0, 11);
+ ifxmips_port_reserve_pin (0, 14);
+ ifxmips_port_reserve_pin (1, 3);
+
+ ifxmips_port_set_dir_in(0, 11);
+ ifxmips_port_clear_altsel0(0, 11);
+ ifxmips_port_clear_altsel1(0, 11);
+ ifxmips_port_set_open_drain(0, 11);
+ //enable ARC JTAG
+ IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &reg_data);
+ IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST, reg_data | LTQ_RCU_RST_REQ_ARC_JTAG);
+ break;
+ case 0:
+ default:
+ break;
+ }
+jtag_end:
+ if (meierr)
+ return DSL_DEV_MEI_ERR_FAILURE;
+*/
+
+ return DSL_DEV_MEI_ERR_SUCCESS;
+};
+
+/**
+ * Enable DFE to MIPS interrupt
+ * This function enable DFE to MIPS interrupt
+ *
+ * \param pDev the device pointer
+ * \param enable enable or disable
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+static DSL_DEV_MeiError_t
+IFX_MEI_AdslMailboxIRQEnable (DSL_DEV_Device_t *pDev, int enable)
+{
+ DSL_DEV_MeiError_t meierr;
+ switch (enable) {
+ case 0:
+ meierr = DSL_DEV_MEI_ERR_SUCCESS;
+ IFX_MEI_IRQDisable (pDev);
+ break;
+ case 1:
+ IFX_MEI_IRQEnable (pDev);
+ meierr = DSL_DEV_MEI_ERR_SUCCESS;
+ break;
+ default:
+ meierr = DSL_DEV_MEI_ERR_FAILURE;
+ break;
+
+ }
+ return meierr;
+}
+
+/**
+ * Get the modem status
+ * This function return the modem status
+ *
+ * \param pDev the device pointer
+ * \return 1: modem ready 0: not ready
+ * \ingroup Internal
+ */
+static int
+IFX_MEI_IsModemReady (DSL_DEV_Device_t * pDev)
+{
+ return DSL_DEV_PRIVATE(pDev)->modem_ready;
+}
+
+DSL_DEV_MeiError_t
+DSL_BSP_AdslLedInit (DSL_DEV_Device_t * dev,
+ DSL_DEV_LedId_t led_number,
+ DSL_DEV_LedType_t type,
+ DSL_DEV_LedHandler_t handler)
+{
+#if 0
+ struct led_config_param param;
+ if (led_number == DSL_LED_LINK_ID && type == DSL_LED_LINK_TYPE && handler == /*DSL_LED_HD_CPU*/DSL_LED_HD_FW) {
+ param.operation_mask = CONFIG_OPERATION_UPDATE_SOURCE;
+ param.led = 0x01;
+ param.source = 0x01;
+// bsp_led_config (&param);
+
+ } else if (led_number == DSL_LED_DATA_ID && type == DSL_LED_DATA_TYPE && (handler == DSL_LED_HD_FW)) {
+ param.operation_mask = CONFIG_OPERATION_UPDATE_SOURCE;
+ param.led = 0x02;
+ param.source = 0x02;
+// bsp_led_config (&param);
+ }
+#endif
+ return DSL_DEV_MEI_ERR_SUCCESS;
+};
+#if 0
+DSL_DEV_MeiError_t
+DSL_BSP_AdslLedSet (DSL_DEV_Device_t * dev, DSL_DEV_LedId_t led_number, DSL_DEV_LedMode_t mode)
+{
+ printk(KERN_INFO "[%s %d]: mode = %#x, led_number = %d\n", __func__, __LINE__, mode, led_number);
+ switch (mode) {
+ case DSL_LED_OFF:
+ switch (led_number) {
+ case DSL_LED_LINK_ID:
+#ifdef CONFIG_BSP_LED
+ bsp_led_set_blink (1, 0);
+ bsp_led_set_data (1, 0);
+#endif
+ break;
+ case DSL_LED_DATA_ID:
+#ifdef CONFIG_BSP_LED
+ bsp_led_set_blink (0, 0);
+ bsp_led_set_data (0, 0);
+#endif
+ break;
+ }
+ break;
+ case DSL_LED_FLASH:
+ switch (led_number) {
+ case DSL_LED_LINK_ID:
+#ifdef CONFIG_BSP_LED
+ bsp_led_set_blink (1, 1); // data
+#endif
+ break;
+ case DSL_LED_DATA_ID:
+#ifdef CONFIG_BSP_LED
+ bsp_led_set_blink (0, 1); // data
+#endif
+ break;
+ }
+ break;
+ case DSL_LED_ON:
+ switch (led_number) {
+ case DSL_LED_LINK_ID:
+#ifdef CONFIG_BSP_LED
+ bsp_led_set_blink (1, 0);
+ bsp_led_set_data (1, 1);
+#endif
+ break;
+ case DSL_LED_DATA_ID:
+#ifdef CONFIG_BSP_LED
+ bsp_led_set_blink (0, 0);
+ bsp_led_set_data (0, 1);
+#endif
+ break;
+ }
+ break;
+ }
+ return DSL_DEV_MEI_ERR_SUCCESS;
+};
+
+#endif
+
+/**
+* Compose a message.
+* This function compose a message from opcode, group, address, index, size, and data
+*
+* \param opcode The message opcode
+* \param group The message group number
+* \param address The message address.
+* \param index The message index.
+* \param size The number of words to read/write.
+* \param data The pointer to data.
+* \param CMVMSG The pointer to message buffer.
+* \ingroup Internal
+*/
+void
+makeCMV (u8 opcode, u8 group, u16 address, u16 index, int size, u16 * data, u16 *CMVMSG)
+{
+ memset (CMVMSG, 0, MSG_LENGTH * 2);
+ CMVMSG[0] = (opcode << 4) + (size & 0xf);
+ CMVMSG[1] = (((index == 0) ? 0 : 1) << 7) + (group & 0x7f);
+ CMVMSG[2] = address;
+ CMVMSG[3] = index;
+ if (opcode == H2D_CMV_WRITE)
+ memcpy (CMVMSG + 4, data, size * 2);
+ return;
+}
+
+/**
+ * Send a message to ARC and read the response
+ * This function sends a message to arc, waits the response, and reads the responses.
+ *
+ * \param pDev the device pointer
+ * \param request Pointer to the request
+ * \param reply Wait reply or not.
+ * \param response Pointer to the response
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+DSL_DEV_MeiError_t
+DSL_BSP_SendCMV (DSL_DEV_Device_t * pDev, u16 * request, int reply, u16 * response) // write cmv to arc, if reply needed, wait for reply
+{
+ DSL_DEV_MeiError_t meierror;
+#if defined(BSP_PORT_RTEMS)
+ int delay_counter = 0;
+#endif
+
+ if (MEI_MUTEX_LOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema))
+ return -ERESTARTSYS;
+
+ DSL_DEV_PRIVATE(pDev)->cmv_reply = reply;
+ memset (DSL_DEV_PRIVATE(pDev)->CMV_RxMsg, 0,
+ sizeof (DSL_DEV_PRIVATE(pDev)->
+ CMV_RxMsg));
+ DSL_DEV_PRIVATE(pDev)->arcmsgav = 0;
+
+ meierror = IFX_MEI_MailboxWrite (pDev, request, MSG_LENGTH);
+
+ if (meierror != DSL_DEV_MEI_ERR_SUCCESS) {
+ DSL_DEV_PRIVATE(pDev)->cmv_waiting = 0;
+ DSL_DEV_PRIVATE(pDev)->arcmsgav = 0;
+ IFX_MEI_EMSG ("MailboxWrite Fail!\n");
+ IFX_MEI_EMSG ("Resetting ARC...\n");
+ IFX_MEI_ResetARC(pDev);
+ MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema);
+ return meierror;
+ }
+ else {
+ DSL_DEV_PRIVATE(pDev)->cmv_count++;
+ }
+
+ if (DSL_DEV_PRIVATE(pDev)->cmv_reply ==
+ NO_REPLY) {
+ MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema);
+ return DSL_DEV_MEI_ERR_SUCCESS;
+ }
+
+#if !defined(BSP_PORT_RTEMS)
+ if (DSL_DEV_PRIVATE(pDev)->arcmsgav == 0)
+ MEI_WAIT_EVENT_TIMEOUT (DSL_DEV_PRIVATE(pDev)->wait_queue_arcmsgav, CMV_TIMEOUT);
+#else
+ while (DSL_DEV_PRIVATE(pDev)->arcmsgav == 0 && delay_counter < CMV_TIMEOUT / 5) {
+ MEI_WAIT (5);
+ delay_counter++;
+ }
+#endif
+
+ DSL_DEV_PRIVATE(pDev)->cmv_waiting = 0;
+ if (DSL_DEV_PRIVATE(pDev)->arcmsgav == 0) { //CMV_timeout
+ DSL_DEV_PRIVATE(pDev)->arcmsgav = 0;
+ IFX_MEI_EMSG ("\%s: DSL_DEV_MEI_ERR_MAILBOX_TIMEOUT\n",
+ __FUNCTION__);
+ MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema);
+ return DSL_DEV_MEI_ERR_MAILBOX_TIMEOUT;
+ }
+ else {
+ DSL_DEV_PRIVATE(pDev)->arcmsgav = 0;
+ DSL_DEV_PRIVATE(pDev)->
+ reply_count++;
+ memcpy (response, DSL_DEV_PRIVATE(pDev)->CMV_RxMsg, MSG_LENGTH * 2);
+ MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema);
+ return DSL_DEV_MEI_ERR_SUCCESS;
+ }
+ MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema);
+ return DSL_DEV_MEI_ERR_SUCCESS;
+}
+
+/**
+ * Reset the ARC, download boot codes, and run the ARC.
+ * This function resets the ARC, downloads boot codes to ARC, and runs the ARC.
+ *
+ * \param pDev the device pointer
+ * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE
+ * \ingroup Internal
+ */
+static DSL_DEV_MeiError_t
+IFX_MEI_RunAdslModem (DSL_DEV_Device_t *pDev)
+{
+ int nSize = 0, idx = 0;
+ uint32_t im0_register, im2_register;
+// DSL_DEV_WinHost_Message_t m;
+
+ if (mei_arc_swap_buff == NULL) {
+ mei_arc_swap_buff =
+ (u32 *) kmalloc (MAXSWAPSIZE * 4, GFP_KERNEL);
+ if (mei_arc_swap_buff == NULL) {
+ IFX_MEI_EMSG (">>> malloc fail for codeswap buff!!! <<<\n");
+ return DSL_DEV_MEI_ERR_FAILURE;
+ }
+ IFX_MEI_DMSG("allocate %dKB swap buff memory at: 0x%p\n", ksize(mei_arc_swap_buff)/1024, mei_arc_swap_buff);
+ }
+
+ DSL_DEV_PRIVATE(pDev)->img_hdr =
+ (ARC_IMG_HDR *) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[0].address;
+ if ((DSL_DEV_PRIVATE(pDev)->img_hdr->
+ count) * sizeof (ARC_SWP_PAGE_HDR) > SDRAM_SEGMENT_SIZE) {
+ IFX_MEI_EMSG ("firmware header size is bigger than 64K segment size\n");
+ return DSL_DEV_MEI_ERR_FAILURE;
+ }
+ // check image size
+ for (idx = 0; idx < MAX_BAR_REGISTERS; idx++) {
+ nSize += DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].nCopy;
+ }
+ if (nSize !=
+ DSL_DEV_PRIVATE(pDev)->image_size) {
+ IFX_MEI_EMSG ("Firmware download is not completed. Please download firmware again!\n");
+ return DSL_DEV_MEI_ERR_FAILURE;
+ }
+ // TODO: check crc
+ ///
+
+ IFX_MEI_ResetARC (pDev);
+ IFX_MEI_HaltArc (pDev);
+ IFX_MEI_BarUpdate (pDev, DSL_DEV_PRIVATE(pDev)->nBar);
+
+ //IFX_MEI_DMSG("Starting to meiDownloadBootCode\n");
+
+ IFX_MEI_DownloadBootCode (pDev);
+
+ im0_register = (*LTQ_ICU_IM0_IER) & (1 << 20);
+ im2_register = (*LTQ_ICU_IM2_IER) & (1 << 20);
+ /* Turn off irq */
+ #ifdef CONFIG_SOC_AMAZON_SE
+#define IFXMIPS_USB_OC_INT0 (INT_NUM_IM4_IRL0 + 23)
+ disable_irq (IFXMIPS_USB_OC_INT0);
+// disable_irq (IFXMIPS_USB_OC_INT2);
+ #elif defined(CONFIG_SOC_AR9)
+#define IFXMIPS_USB_OC_INT0 (INT_NUM_IM4_IRL1 + 28)
+ disable_irq (IFXMIPS_USB_OC_INT0);
+// disable_irq (IFXMIPS_USB_OC_INT2);
+ #elif defined(CONFIG_SOC_XWAY)
+ disable_irq (LTQ_USB_OC_INT);
+ #else
+ #error unkonwn arch
+ #endif
+ disable_irq (pDev->nIrq[IFX_DYING_GASP]);
+
+ IFX_MEI_RunArc (pDev);
+
+ MEI_WAIT_EVENT_TIMEOUT (DSL_DEV_PRIVATE(pDev)->wait_queue_modemready, 1000);
+
+ #ifdef CONFIG_SOC_AMAZON_SE
+ MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT0);
+// MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT2);
+ #elif defined(CONFIG_SOC_AR9)
+ MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT0);
+// MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT2);
+ #elif defined(CONFIG_SOC_XWAY)
+ MEI_MASK_AND_ACK_IRQ (LTQ_USB_OC_INT);
+ #else
+ #error unkonwn arch
+ #endif
+ MEI_MASK_AND_ACK_IRQ (pDev->nIrq[IFX_DYING_GASP]);
+
+ /* Re-enable irq */
+ enable_irq(pDev->nIrq[IFX_DYING_GASP]);
+ *LTQ_ICU_IM0_IER |= im0_register;
+ *LTQ_ICU_IM2_IER |= im2_register;
+
+ if (DSL_DEV_PRIVATE(pDev)->modem_ready != 1) {
+ IFX_MEI_EMSG ("Modem failed to be ready!\n");
+ return DSL_DEV_MEI_ERR_FAILURE;
+ } else {
+ IFX_MEI_DMSG("Modem is ready.\n");
+ return DSL_DEV_MEI_ERR_SUCCESS;
+ }
+}
+
+/**
+ * Get the page's data pointer
+ * This function caculats the data address from the firmware header.
+ *
+ * \param pDev the device pointer
+ * \param Page The page number.
+ * \param data Data page or program page.
+ * \param MaxSize The maximum size to read.
+ * \param Buffer Pointer to data.
+ * \param Dest Pointer to the destination address.
+ * \return The number of bytes to read.
+ * \ingroup Internal
+ */
+static int
+IFX_MEI_GetPage (DSL_DEV_Device_t * pDev, u32 Page, u32 data,
+ u32 MaxSize, u32 * Buffer, u32 * Dest)
+{
+ u32 size;
+ u32 i;
+ u32 *p;
+ u32 idx, offset, nBar = 0;
+
+ if (Page > DSL_DEV_PRIVATE(pDev)->img_hdr->count)
+ return -2;
+ /*
+ ** Get program or data size, depending on "data" flag
+ */
+ size = (data == GET_DATA) ? (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].d_size) :
+ (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].p_size);
+ size &= BOOT_FLAG_MASK; // Clear boot bit!
+ if (size > MaxSize)
+ return -1;
+
+ if (size == 0)
+ return 0;
+ /*
+ ** Get program or data offset, depending on "data" flag
+ */
+ i = data ? (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].d_offset) :
+ (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].p_offset);
+
+ /*
+ ** Copy data/program to buffer
+ */
+
+ idx = i / SDRAM_SEGMENT_SIZE;
+ offset = i % SDRAM_SEGMENT_SIZE;
+ p = (u32 *) ((u8 *) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].address + offset);
+
+ for (i = 0; i < size; i++) {
+ if (offset + i * 4 - (nBar * SDRAM_SEGMENT_SIZE) >= SDRAM_SEGMENT_SIZE) {
+ idx++;
+ nBar++;
+ p = (u32 *) ((u8 *) KSEG1ADDR ((u32)DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].address));
+ }
+ Buffer[i] = *p++;
+ }
+
+ /*
+ ** Pass back data/program destination address
+ */
+ *Dest = data ? (DSL_DEV_PRIVATE(pDev)-> img_hdr->page[Page].d_dest) :
+ (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].p_dest);
+
+ return size;
+}
+
+/**
+ * Free the memory for ARC firmware
+ *
+ * \param pDev the device pointer
+ * \param type Free all memory or free the unused memory after showtime
+ * \ingroup Internal
+ */
+const char *free_str[4] = {"Invalid", "Free_Reload", "Free_Showtime", "Free_All"};
+static int
+IFX_MEI_DFEMemoryFree (DSL_DEV_Device_t * pDev, int type)
+{
+ int idx = 0;
+ smmu_mem_info_t *adsl_mem_info =
+ DSL_DEV_PRIVATE(pDev)->adsl_mem_info;
+
+ for (idx = 0; idx < MAX_BAR_REGISTERS; idx++) {
+ if (type == FREE_ALL ||adsl_mem_info[idx].type == type) {
+ if (adsl_mem_info[idx].size > 0) {
+ IFX_MEI_DMSG ("Freeing memory %p (%s)\n", adsl_mem_info[idx].org_address, free_str[adsl_mem_info[idx].type]);
+ if ( idx == XDATA_REGISTER ) {
+ g_xdata_addr = NULL;
+ if ( ifx_mei_atm_showtime_exit )
+ ifx_mei_atm_showtime_exit();
+ }
+ kfree (adsl_mem_info[idx].org_address);
+ adsl_mem_info[idx].org_address = 0;
+ adsl_mem_info[idx].address = 0;
+ adsl_mem_info[idx].size = 0;
+ adsl_mem_info[idx].type = 0;
+ adsl_mem_info[idx].nCopy = 0;
+ }
+ }
+ }
+
+ if(mei_arc_swap_buff != NULL){
+ IFX_MEI_DMSG("free %dKB swap buff memory at: 0x%p\n", ksize(mei_arc_swap_buff)/1024, mei_arc_swap_buff);
+ kfree(mei_arc_swap_buff);
+ mei_arc_swap_buff=NULL;
+ }
+
+ return 0;
+}
+static int
+IFX_MEI_DFEMemoryAlloc (DSL_DEV_Device_t * pDev, long size)
+{
+ unsigned long mem_ptr;
+ char *org_mem_ptr = NULL;
+ int idx = 0;
+ long total_size = 0;
+ int err = 0;
+ smmu_mem_info_t *adsl_mem_info =
+ ((ifx_mei_device_private_t *) pDev->pPriv)->adsl_mem_info;
+// DSL_DEV_PRIVATE(pDev)->adsl_mem_info;
+ int allocate_size = SDRAM_SEGMENT_SIZE;
+
+ IFX_MEI_DMSG("image_size = %ld\n", size);
+ // Alloc Swap Pages
+ for (idx = 0; size > 0 && idx < MAX_BAR_REGISTERS; idx++) {
+ // skip bar15 for XDATA usage.
+ if (idx == XDATA_REGISTER)
+ continue;
+#if 0
+ if (size < SDRAM_SEGMENT_SIZE) {
+ allocate_size = size;
+ if (allocate_size < 1024)
+ allocate_size = 1024;
+ }
+#endif
+ if (idx == (MAX_BAR_REGISTERS - 1))
+ allocate_size = size;
+ else
+ allocate_size = SDRAM_SEGMENT_SIZE;
+ org_mem_ptr = kmalloc (allocate_size + 1024, GFP_KERNEL);
+ if (org_mem_ptr == NULL) {
+ IFX_MEI_EMSG ("%d: kmalloc %d bytes memory fail!\n", idx, allocate_size);
+ err = -ENOMEM;
+ goto allocate_error;
+ }
+ mem_ptr = (unsigned long) (org_mem_ptr + 1023) & ~(1024 -1);
+ adsl_mem_info[idx].address = (char *) mem_ptr;
+ adsl_mem_info[idx].org_address = org_mem_ptr;
+ adsl_mem_info[idx].size = allocate_size;
+ size -= allocate_size;
+ total_size += allocate_size;
+ }
+ if (size > 0) {
+ IFX_MEI_EMSG ("Image size is too large!\n");
+ err = -EFBIG;
+ goto allocate_error;
+ }
+ err = idx;
+ return err;
+
+ allocate_error:
+ IFX_MEI_DFEMemoryFree (pDev, FREE_ALL);
+ return err;
+}
+
+/**
+ * Program the BAR registers
+ *
+ * \param pDev the device pointer
+ * \param nTotalBar The number of bar to program.
+ * \ingroup Internal
+ */
+static int
+IFX_MEI_BarUpdate (DSL_DEV_Device_t * pDev, int nTotalBar)
+{
+ int idx = 0;
+ smmu_mem_info_t *adsl_mem_info =
+ DSL_DEV_PRIVATE(pDev)->adsl_mem_info;
+
+ for (idx = 0; idx < nTotalBar; idx++) {
+ //skip XDATA register
+ if (idx == XDATA_REGISTER)
+ continue;
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XMEM_BAR_BASE + idx * 4,
+ (((uint32_t) adsl_mem_info[idx].address) & 0x0FFFFFFF));
+ }
+ for (idx = nTotalBar; idx < MAX_BAR_REGISTERS; idx++) {
+ if (idx == XDATA_REGISTER)
+ continue;
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XMEM_BAR_BASE + idx * 4,
+ (((uint32_t)adsl_mem_info[nTotalBar - 1].address) & 0x0FFFFFFF));
+ /* These are for /proc/danube_mei/meminfo purpose */
+ adsl_mem_info[idx].address = adsl_mem_info[nTotalBar - 1].address;
+ adsl_mem_info[idx].org_address = adsl_mem_info[nTotalBar - 1].org_address;
+ adsl_mem_info[idx].size = 0; /* Prevent it from being freed */
+ }
+
+ g_xdata_addr = adsl_mem_info[XDATA_REGISTER].address;
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XMEM_BAR_BASE + XDATA_REGISTER * 4,
+ (((uint32_t) adsl_mem_info [XDATA_REGISTER].address) & 0x0FFFFFFF));
+ // update MEI_XDATA_BASE_SH
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XDATA_BASE_SH,
+ ((unsigned long)adsl_mem_info[XDATA_REGISTER].address) & 0x0FFFFFFF);
+
+ return DSL_DEV_MEI_ERR_SUCCESS;
+}
+
+/* This copies the firmware from secondary storage to 64k memory segment in SDRAM */
+DSL_DEV_MeiError_t
+DSL_BSP_FWDownload (DSL_DEV_Device_t * pDev, const char *buf,
+ unsigned long size, long *loff, long *current_offset)
+{
+ ARC_IMG_HDR img_hdr_tmp;
+ smmu_mem_info_t *adsl_mem_info = DSL_DEV_PRIVATE(pDev)->adsl_mem_info;
+
+ size_t nRead = 0, nCopy = 0;
+ char *mem_ptr;
+ ssize_t retval = -ENOMEM;
+ int idx = 0;
+
+ IFX_MEI_DMSG("\n");
+
+ if (*loff == 0) {
+ if (size < sizeof (img_hdr_tmp)) {
+ IFX_MEI_EMSG ("Firmware size is too small!\n");
+ return retval;
+ }
+ copy_from_user ((char *) &img_hdr_tmp, buf, sizeof (img_hdr_tmp));
+ // header of image_size and crc are not included.
+ DSL_DEV_PRIVATE(pDev)->image_size = le32_to_cpu (img_hdr_tmp.size) + 8;
+
+ if (DSL_DEV_PRIVATE(pDev)->image_size > 1024 * 1024) {
+ IFX_MEI_EMSG ("Firmware size is too large!\n");
+ return retval;
+ }
+ // check if arc is halt
+ IFX_MEI_ResetARC (pDev);
+ IFX_MEI_HaltArc (pDev);
+
+ IFX_MEI_DFEMemoryFree (pDev, FREE_ALL); //free all
+
+ retval = IFX_MEI_DFEMemoryAlloc (pDev, DSL_DEV_PRIVATE(pDev)->image_size);
+ if (retval < 0) {
+ IFX_MEI_EMSG ("Error: No memory space left.\n");
+ goto error;
+ }
+ for (idx = 0; idx < retval; idx++) {
+ //skip XDATA register
+ if (idx == XDATA_REGISTER)
+ continue;
+ if (idx * SDRAM_SEGMENT_SIZE < le32_to_cpu (img_hdr_tmp.page[0].p_offset))
+ adsl_mem_info[idx].type = FREE_RELOAD;
+ else
+ adsl_mem_info[idx].type = FREE_SHOWTIME;
+ }
+ DSL_DEV_PRIVATE(pDev)->nBar = retval;
+
+ DSL_DEV_PRIVATE(pDev)->img_hdr =
+ (ARC_IMG_HDR *) adsl_mem_info[0].address;
+
+ adsl_mem_info[XDATA_REGISTER].org_address = kmalloc (SDRAM_SEGMENT_SIZE + 1024, GFP_KERNEL);
+ adsl_mem_info[XDATA_REGISTER].address =
+ (char *) ((unsigned long) (adsl_mem_info[XDATA_REGISTER].org_address + 1023) & 0xFFFFFC00);
+
+ adsl_mem_info[XDATA_REGISTER].size = SDRAM_SEGMENT_SIZE;
+
+ if (adsl_mem_info[XDATA_REGISTER].address == NULL) {
+ IFX_MEI_EMSG ("kmalloc memory fail!\n");
+ retval = -ENOMEM;
+ goto error;
+ }
+ adsl_mem_info[XDATA_REGISTER].type = FREE_RELOAD;
+ IFX_MEI_DMSG("-> IFX_MEI_BarUpdate()\n");
+ IFX_MEI_BarUpdate (pDev, (DSL_DEV_PRIVATE(pDev)->nBar));
+ }
+ else if (DSL_DEV_PRIVATE(pDev)-> image_size == 0) {
+ IFX_MEI_EMSG ("Error: Firmware size=0! \n");
+ goto error;
+ }
+
+ nRead = 0;
+ while (nRead < size) {
+ long offset = ((long) (*loff) + nRead) % SDRAM_SEGMENT_SIZE;
+ idx = (((long) (*loff)) + nRead) / SDRAM_SEGMENT_SIZE;
+ mem_ptr = (char *) KSEG1ADDR ((unsigned long) (adsl_mem_info[idx].address) + offset);
+ if ((size - nRead + offset) > SDRAM_SEGMENT_SIZE)
+ nCopy = SDRAM_SEGMENT_SIZE - offset;
+ else
+ nCopy = size - nRead;
+ copy_from_user (mem_ptr, buf + nRead, nCopy);
+ for (offset = 0; offset < (nCopy / 4); offset++) {
+ ((unsigned long *) mem_ptr)[offset] = le32_to_cpu (((unsigned long *) mem_ptr)[offset]);
+ }
+ nRead += nCopy;
+ adsl_mem_info[idx].nCopy += nCopy;
+ }
+
+ *loff += size;
+ *current_offset = size;
+ return DSL_DEV_MEI_ERR_SUCCESS;
+error:
+ IFX_MEI_DFEMemoryFree (pDev, FREE_ALL);
+ return DSL_DEV_MEI_ERR_FAILURE;
+}
+/*
+ * Register a callback event.
+ * Return:
+ * -1 if the event already has a callback function registered.
+ * 0 success
+ */
+int DSL_BSP_EventCBRegister(DSL_BSP_EventCallBack_t *p)
+{
+ if (!p) {
+ IFX_MEI_EMSG("Invalid parameter!\n");
+ return -EINVAL;
+ }
+ if (p->event > DSL_BSP_CB_LAST || p->event < DSL_BSP_CB_FIRST) {
+ IFX_MEI_EMSG("Invalid Event %d\n", p->event);
+ return -EINVAL;
+ }
+ if (dsl_bsp_event_callback[p->event].function) {
+ IFX_MEI_EMSG("Event %d already has a callback function registered!\n", p->event);
+ return -1;
+ } else {
+ dsl_bsp_event_callback[p->event].function = p->function;
+ dsl_bsp_event_callback[p->event].event = p->event;
+ dsl_bsp_event_callback[p->event].pData = p->pData;
+ }
+ return 0;
+}
+int DSL_BSP_EventCBUnregister(DSL_BSP_EventCallBack_t *p)
+{
+ if (!p) {
+ IFX_MEI_EMSG("Invalid parameter!\n");
+ return -EINVAL;
+ }
+ if (p->event > DSL_BSP_CB_LAST || p->event < DSL_BSP_CB_FIRST) {
+ IFX_MEI_EMSG("Invalid Event %d\n", p->event);
+ return -EINVAL;
+ }
+ if (dsl_bsp_event_callback[p->event].function) {
+ IFX_MEI_EMSG("Unregistering Event %d...\n", p->event);
+ dsl_bsp_event_callback[p->event].function = NULL;
+ dsl_bsp_event_callback[p->event].pData = NULL;
+ } else {
+ IFX_MEI_EMSG("Event %d is not registered!\n", p->event);
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * MEI Dying Gasp interrupt handler
+ *
+ * \param int1
+ * \param void0
+ * \param regs Pointer to the structure of danube mips registers
+ * \ingroup Internal
+ */
+static irqreturn_t IFX_MEI_Dying_Gasp_IrqHandle (int int1, void *void0)
+{
+ DSL_DEV_Device_t *pDev = (DSL_DEV_Device_t *) void0;
+ DSL_BSP_CB_Type_t event;
+
+ if (pDev == NULL)
+ IFX_MEI_EMSG("Error: Got Interrupt but pDev is NULL!!!!\n");
+
+#ifndef CONFIG_SMP
+ disable_irq (pDev->nIrq[IFX_DYING_GASP]);
+#else
+ disable_irq_nosync(pDev->nIrq[IFX_DYING_GASP]);
+#endif
+ event = DSL_BSP_CB_DYING_GASP;
+
+ if (dsl_bsp_event_callback[event].function)
+ (*dsl_bsp_event_callback[event].function)(pDev, event, dsl_bsp_event_callback[event].pData);
+
+#ifdef CONFIG_USE_EMULATOR
+ IFX_MEI_EMSG("Dying Gasp! Shutting Down... (Work around for Amazon-S Venus emulator)\n");
+#else
+ IFX_MEI_EMSG("Dying Gasp! Shutting Down...\n");
+// kill_proc (1, SIGINT, 1); /* Ask init to reboot us */
+#endif
+ return IRQ_HANDLED;
+}
+
+extern void ifx_usb_enable_afe_oc(void);
+
+/**
+ * MEI interrupt handler
+ *
+ * \param int1
+ * \param void0
+ * \param regs Pointer to the structure of danube mips registers
+ * \ingroup Internal
+ */
+static irqreturn_t IFX_MEI_IrqHandle (int int1, void *void0)
+{
+ u32 scratch;
+ DSL_DEV_Device_t *pDev = (DSL_DEV_Device_t *) void0;
+#if defined(CONFIG_LTQ_MEI_FW_LOOPBACK) && defined(DFE_PING_TEST)
+ dfe_loopback_irq_handler (pDev);
+ return IRQ_HANDLED;
+#endif //CONFIG_AMAZON_S_MEI_FW_LOOPBACK
+ DSL_BSP_CB_Type_t event;
+
+ if (pDev == NULL)
+ IFX_MEI_EMSG("Error: Got Interrupt but pDev is NULL!!!!\n");
+
+ IFX_MEI_DebugRead (pDev, ARC_MEI_MAILBOXR, &scratch, 1);
+ if (scratch & OMB_CODESWAP_MESSAGE_MSG_TYPE_MASK) {
+ IFX_MEI_EMSG("Receive Code Swap Request interrupt!!!\n");
+ return IRQ_HANDLED;
+ }
+ else if (scratch & OMB_CLEAREOC_INTERRUPT_CODE) {
+ // clear eoc message interrupt
+ IFX_MEI_DMSG("OMB_CLEAREOC_INTERRUPT_CODE\n");
+ event = DSL_BSP_CB_CEOC_IRQ;
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_STAT, ARC_TO_MEI_MSGAV);
+ if (dsl_bsp_event_callback[event].function)
+ (*dsl_bsp_event_callback[event].function)(pDev, event, dsl_bsp_event_callback[event].pData);
+ } else if (scratch & OMB_REBOOT_INTERRUPT_CODE) {
+ // Reboot
+ IFX_MEI_DMSG("OMB_REBOOT_INTERRUPT_CODE\n");
+ event = DSL_BSP_CB_FIRMWARE_REBOOT;
+
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_STAT, ARC_TO_MEI_MSGAV);
+
+ if (dsl_bsp_event_callback[event].function)
+ (*dsl_bsp_event_callback[event].function)(pDev, event, dsl_bsp_event_callback[event].pData);
+ } else { // normal message
+ IFX_MEI_MailboxRead (pDev, DSL_DEV_PRIVATE(pDev)->CMV_RxMsg, MSG_LENGTH);
+ if (DSL_DEV_PRIVATE(pDev)-> cmv_waiting == 1) {
+ DSL_DEV_PRIVATE(pDev)-> arcmsgav = 1;
+ DSL_DEV_PRIVATE(pDev)-> cmv_waiting = 0;
+#if !defined(BSP_PORT_RTEMS)
+ MEI_WAKEUP_EVENT (DSL_DEV_PRIVATE(pDev)->wait_queue_arcmsgav);
+#endif
+ }
+ else {
+ DSL_DEV_PRIVATE(pDev)-> modem_ready_cnt++;
+ memcpy ((char *) DSL_DEV_PRIVATE(pDev)->Recent_indicator,
+ (char *) DSL_DEV_PRIVATE(pDev)->CMV_RxMsg, MSG_LENGTH * 2);
+ if (((DSL_DEV_PRIVATE(pDev)->CMV_RxMsg[0] & 0xff0) >> 4) == D2H_AUTONOMOUS_MODEM_READY_MSG) {
+ //check ARC ready message
+ IFX_MEI_DMSG ("Got MODEM_READY_MSG\n");
+ DSL_DEV_PRIVATE(pDev)->modem_ready = 1;
+ MEI_WAKEUP_EVENT (DSL_DEV_PRIVATE(pDev)->wait_queue_modemready);
+ }
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+int
+DSL_BSP_ATMLedCBRegister (int (*ifx_adsl_ledcallback) (void))
+{
+ g_adsl_ledcallback = ifx_adsl_ledcallback;
+ return 0;
+}
+
+int
+DSL_BSP_ATMLedCBUnregister (int (*ifx_adsl_ledcallback) (void))
+{
+ g_adsl_ledcallback = adsl_dummy_ledcallback;
+ return 0;
+}
+
+#if 0
+int
+DSL_BSP_EventCBRegister (int (*ifx_adsl_callback)
+ (DSL_BSP_CB_Event_t * param))
+{
+ int error = 0;
+
+ if (DSL_EventCB == NULL) {
+ DSL_EventCB = ifx_adsl_callback;
+ }
+ else {
+ error = -EIO;
+ }
+ return error;
+}
+
+int
+DSL_BSP_EventCBUnregister (int (*ifx_adsl_callback)
+ (DSL_BSP_CB_Event_t * param))
+{
+ int error = 0;
+
+ if (DSL_EventCB == ifx_adsl_callback) {
+ DSL_EventCB = NULL;
+ }
+ else {
+ error = -EIO;
+ }
+ return error;
+}
+
+static int
+DSL_BSP_GetEventCB (int (**ifx_adsl_callback)
+ (DSL_BSP_CB_Event_t * param))
+{
+ *ifx_adsl_callback = DSL_EventCB;
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_LTQ_MEI_FW_LOOPBACK
+#define mte_reg_base (0x4800*4+0x20000)
+
+/* Iridia Registers Address Constants */
+#define MTE_Reg(r) (int)(mte_reg_base + (r*4))
+
+#define IT_AMODE MTE_Reg(0x0004)
+
+#define TIMER_DELAY (1024)
+#define BC0_BYTES (32)
+#define BC1_BYTES (30)
+#define NUM_MB (12)
+#define TIMEOUT_VALUE 2000
+
+static void
+BFMWait (u32 cycle)
+{
+ u32 i;
+ for (i = 0; i < cycle; i++);
+}
+
+static void
+WriteRegLong (u32 addr, u32 data)
+{
+ //*((volatile u32 *)(addr)) = data;
+ IFX_MEI_WRITE_REGISTER_L (data, addr);
+}
+
+static u32
+ReadRegLong (u32 addr)
+{
+ // u32 rd_val;
+ //rd_val = *((volatile u32 *)(addr));
+ // return rd_val;
+ return IFX_MEI_READ_REGISTER_L (addr);
+}
+
+/* This routine writes the mailbox with the data in an input array */
+static void
+WriteMbox (u32 * mboxarray, u32 size)
+{
+ IFX_MEI_DebugWrite (&dsl_devices[0], IMBOX_BASE, mboxarray, size);
+ IFX_MEI_DMSG("write to %X\n", IMBOX_BASE);
+ IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_ME2ARC_INT, MEI_TO_ARC_MSGAV);
+}
+
+/* This routine reads the output mailbox and places the results into an array */
+static void
+ReadMbox (u32 * mboxarray, u32 size)
+{
+ IFX_MEI_DebugRead (&dsl_devices[0], OMBOX_BASE, mboxarray, size);
+ IFX_MEI_DMSG("read from %X\n", OMBOX_BASE);
+}
+
+static void
+MEIWriteARCValue (u32 address, u32 value)
+{
+ u32 i, check = 0;
+
+ /* Write address register */
+ IFX_MEI_WRITE_REGISTER_L (address, ME_DBG_WR_AD + LTQ_MEI_BASE_ADDR);
+
+ /* Write data register */
+ IFX_MEI_WRITE_REGISTER_L (value, ME_DBG_DATA + LTQ_MEI_BASE_ADDR);
+
+ /* wait until complete - timeout at 40 */
+ for (i = 0; i < 40; i++) {
+ check = IFX_MEI_READ_REGISTER_L (ME_ARC2ME_STAT + LTQ_MEI_BASE_ADDR);
+
+ if ((check & ARC_TO_MEI_DBG_DONE))
+ break;
+ }
+ /* clear the flag */
+ IFX_MEI_WRITE_REGISTER_L (ARC_TO_MEI_DBG_DONE, ME_ARC2ME_STAT + LTQ_MEI_BASE_ADDR);
+}
+
+void
+arc_code_page_download (uint32_t arc_code_length, uint32_t * start_address)
+{
+ int count;
+
+ IFX_MEI_DMSG("try to download pages,size=%d\n", arc_code_length);
+ IFX_MEI_ControlModeSet (&dsl_devices[0], MEI_MASTER_MODE);
+ IFX_MEI_HaltArc (&dsl_devices[0]);
+ IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_DX_AD, 0);
+ for (count = 0; count < arc_code_length; count++) {
+ IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_DX_DATA,
+ *(start_address + count));
+ }
+ IFX_MEI_ControlModeSet (&dsl_devices[0], JTAG_MASTER_MODE);
+}
+static int
+load_jump_table (unsigned long addr)
+{
+ int i;
+ uint32_t addr_le, addr_be;
+ uint32_t jump_table[32];
+
+ for (i = 0; i < 16; i++) {
+ addr_le = i * 8 + addr;
+ addr_be = ((addr_le >> 16) & 0xffff);
+ addr_be |= ((addr_le & 0xffff) << 16);
+ jump_table[i * 2 + 0] = 0x0f802020;
+ jump_table[i * 2 + 1] = addr_be;
+ //printk("jt %X %08X %08X\n",i,jump_table[i*2+0],jump_table[i*2+1]);
+ }
+ arc_code_page_download (32, &jump_table[0]);
+return 0;
+}
+
+int got_int = 0;
+
+void
+dfe_loopback_irq_handler (DSL_DEV_Device_t *pDev)
+{
+ uint32_t rd_mbox[10];
+
+ memset (&rd_mbox[0], 0, 10 * 4);
+ ReadMbox (&rd_mbox[0], 6);
+ if (rd_mbox[0] == 0x0) {
+ FX_MEI_DMSG("Get ARC_ACK\n");
+ got_int = 1;
+ }
+ else if (rd_mbox[0] == 0x5) {
+ IFX_MEI_DMSG("Get ARC_BUSY\n");
+ got_int = 2;
+ }
+ else if (rd_mbox[0] == 0x3) {
+ IFX_MEI_DMSG("Get ARC_EDONE\n");
+ if (rd_mbox[1] == 0x0) {
+ got_int = 3;
+ IFX_MEI_DMSG("Get E_MEMTEST\n");
+ if (rd_mbox[2] != 0x1) {
+ got_int = 4;
+ IFX_MEI_DMSG("Get Result %X\n", rd_mbox[2]);
+ }
+ }
+ }
+ IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_ARC2ME_STAT,
+ ARC_TO_MEI_DBG_DONE);
+ MEI_MASK_AND_ACK_IRQ (pDev->nIrq[IFX_DFEIR]);
+ disable_irq (pDev->nIrq[IFX_DFEIR]);
+ //got_int = 1;
+ return;
+}
+
+static void
+wait_mem_test_result (void)
+{
+ uint32_t mbox[5];
+ mbox[0] = 0;
+
+ IFX_MEI_DMSG("Waiting Starting\n");
+ while (mbox[0] == 0) {
+ ReadMbox (&mbox[0], 5);
+ }
+ IFX_MEI_DMSG("Try to get mem test result.\n");
+ ReadMbox (&mbox[0], 5);
+ if (mbox[0] == 0xA) {
+ IFX_MEI_DMSG("Success.\n");
+ }
+ else if (mbox[0] == 0xA) {
+ IFX_MEI_EMSG("Fail,address %X,except data %X,receive data %X\n",
+ mbox[1], mbox[2], mbox[3]);
+ }
+ else {
+ IFX_MEI_EMSG("Fail\n");
+ }
+}
+
+static int
+arc_ping_testing (DSL_DEV_Device_t *pDev)
+{
+#define MEI_PING 0x00000001
+ uint32_t wr_mbox[10], rd_mbox[10];
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ wr_mbox[i] = 0;
+ rd_mbox[i] = 0;
+ }
+
+ FX_MEI_DMSG("send ping msg\n");
+ wr_mbox[0] = MEI_PING;
+ WriteMbox (&wr_mbox[0], 10);
+
+ while (got_int == 0) {
+ MEI_WAIT (100);
+ }
+
+ IFX_MEI_DMSG("send start event\n");
+ got_int = 0;
+
+ wr_mbox[0] = 0x4;
+ wr_mbox[1] = 0;
+ wr_mbox[2] = 0;
+ wr_mbox[3] = (uint32_t) 0xf5acc307e;
+ wr_mbox[4] = 5;
+ wr_mbox[5] = 2;
+ wr_mbox[6] = 0x1c000;
+ wr_mbox[7] = 64;
+ wr_mbox[8] = 0;
+ wr_mbox[9] = 0;
+ WriteMbox (&wr_mbox[0], 10);
+ DSL_ENABLE_IRQ (pDev->nIrq[IFX_DFEIR]);
+ //printk("IFX_MEI_MailboxWrite ret=%d\n",i);
+ IFX_MEI_LongWordWriteOffset (&dsl_devices[0],
+ (u32) ME_ME2ARC_INT,
+ MEI_TO_ARC_MSGAV);
+ IFX_MEI_DMSG("sleeping\n");
+ while (1) {
+ if (got_int > 0) {
+
+ if (got_int > 3)
+ IFX_MEI_DMSG("got_int >>>> 3\n");
+ else
+ IFX_MEI_DMSG("got int = %d\n", got_int);
+ got_int = 0;
+ //schedule();
+ DSL_ENABLE_IRQ (pDev->nIrq[IFX_DFEIR]);
+ }
+ //mbox_read(&rd_mbox[0],6);
+ MEI_WAIT (100);
+ }
+ return 0;
+}
+
+static DSL_DEV_MeiError_t
+DFE_Loopback_Test (void)
+{
+ int i = 0;
+ u32 arc_debug_data = 0, temp;
+ DSL_DEV_Device_t *pDev = &dsl_devices[0];
+ uint32_t wr_mbox[10];
+
+ IFX_MEI_ResetARC (pDev);
+ // start the clock
+ arc_debug_data = ACL_CLK_MODE_ENABLE;
+ IFX_MEI_DebugWrite (pDev, CRI_CCR0, &arc_debug_data, 1);
+
+#if defined( DFE_PING_TEST )|| defined( DFE_ATM_LOOPBACK)
+ // WriteARCreg(AUX_XMEM_LTEST,0);
+ IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
+#define AUX_XMEM_LTEST 0x128
+ _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK, AUX_XMEM_LTEST, 0);
+ IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
+
+ // WriteARCreg(AUX_XDMA_GAP,0);
+ IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
+#define AUX_XDMA_GAP 0x114
+ _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK, AUX_XDMA_GAP, 0);
+ IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
+
+ IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
+ temp = 0;
+ _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK,
+ (u32) ME_XDATA_BASE_SH + LTQ_MEI_BASE_ADDR, temp);
+ IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
+
+ i = IFX_MEI_DFEMemoryAlloc (pDev, SDRAM_SEGMENT_SIZE * 16);
+ if (i >= 0) {
+ int idx;
+
+ for (idx = 0; idx < i; idx++) {
+ DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].type = FREE_RELOAD;
+ IFX_MEI_WRITE_REGISTER_L ((((uint32_t) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].address) & 0x0fffffff),
+ LTQ_MEI_BASE_ADDR + ME_XMEM_BAR_BASE + idx * 4);
+ IFX_MEI_DMSG("bar%d(%X)=%X\n", idx,
+ LTQ_MEI_BASE_ADDR + ME_XMEM_BAR_BASE +
+ idx * 4, (((uint32_t)
+ ((ifx_mei_device_private_t *)
+ pDev->pPriv)->adsl_mem_info[idx].
+ address) & 0x0fffffff));
+ memset ((u8 *) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].address, 0, SDRAM_SEGMENT_SIZE);
+ }
+
+ IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XDATA_BASE_SH,
+ ((unsigned long) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[XDATA_REGISTER].address) & 0x0FFFFFFF);
+ }
+ else {
+ IFX_MEI_EMSG ("cannot load image: no memory\n");
+ return DSL_DEV_MEI_ERR_FAILURE;
+ }
+ //WriteARCreg(AUX_IC_CTRL,2);
+ IFX_MEI_DMSG("Setting MEI_MASTER_MODE..\n");
+ IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
+#define AUX_IC_CTRL 0x11
+ _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK,
+ AUX_IC_CTRL, 2);
+ IFX_MEI_DMSG("Setting JTAG_MASTER_MODE..\n");
+ IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
+
+ IFX_MEI_DMSG("Halting ARC...\n");
+ IFX_MEI_HaltArc (&dsl_devices[0]);
+
+#ifdef DFE_PING_TEST
+
+ IFX_MEI_DMSG("ping test image size=%d\n", sizeof (arc_ahb_access_code));
+ memcpy ((u8 *) (DSL_DEV_PRIVATE(pDev)->
+ adsl_mem_info[0].address + 0x1004),
+ &arc_ahb_access_code[0], sizeof (arc_ahb_access_code));
+ load_jump_table (0x80000 + 0x1004);
+
+#endif //DFE_PING_TEST
+
+ IFX_MEI_DMSG("ARC ping test code download complete\n");
+#endif //defined( DFE_PING_TEST )|| defined( DFE_ATM_LOOPBACK)
+#ifdef DFE_MEM_TEST
+ IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_ARC2ME_MASK, MSGAV_EN);
+
+ arc_code_page_download (1537, &code_array[0]);
+ IFX_MEI_DMSG("ARC mem test code download complete\n");
+#endif //DFE_MEM_TEST
+#ifdef DFE_ATM_LOOPBACK
+ arc_debug_data = 0xf;
+ arc_code_page_download (sizeof(code_array) / sizeof(*code_array), &code_array[0]);
+ wr_mbox[0] = 0; //TIMER_DELAY - org: 1024
+ wr_mbox[1] = 0; //TXFB_START0
+ wr_mbox[2] = 0x7f; //TXFB_END0 - org: 49
+ wr_mbox[3] = 0x80; //TXFB_START1 - org: 80
+ wr_mbox[4] = 0xff; //TXFB_END1 - org: 109
+ wr_mbox[5] = 0x100; //RXFB_START0 - org: 0
+ wr_mbox[6] = 0x17f; //RXFB_END0 - org: 49
+ wr_mbox[7] = 0x180; //RXFB_START1 - org: 256
+ wr_mbox[8] = 0x1ff; //RXFB_END1 - org: 315
+ WriteMbox (&wr_mbox[0], 9);
+ // Start Iridia IT_AMODE (in dmp access) why is it required?
+ IFX_MEI_DebugWrite (&dsl_devices[0], 0x32010, &arc_debug_data, 1);
+#endif //DFE_ATM_LOOPBACK
+ IFX_MEI_IRQEnable (pDev);
+ IFX_MEI_DMSG("run ARC...\n");
+ IFX_MEI_RunArc (&dsl_devices[0]);
+
+#ifdef DFE_PING_TEST
+ arc_ping_testing (pDev);
+#endif //DFE_PING_TEST
+#ifdef DFE_MEM_TEST
+ wait_mem_test_result ();
+#endif //DFE_MEM_TEST
+
+ IFX_MEI_DFEMemoryFree (pDev, FREE_ALL);
+ return DSL_DEV_MEI_ERR_SUCCESS;
+}
+
+#endif //CONFIG_AMAZON_S_MEI_FW_LOOPBACK
+
+static int
+IFX_MEI_InitDevNode (int num)
+{
+ if (num == 0) {
+ if ((dev_major = register_chrdev (dev_major, IFX_MEI_DEVNAME, &bsp_mei_operations)) < 0) {
+ IFX_MEI_EMSG ("register_chrdev(%d %s) failed!\n", dev_major, IFX_MEI_DEVNAME);
+ return -ENODEV;
+ }
+ }
+ return 0;
+}
+
+static int
+IFX_MEI_CleanUpDevNode (int num)
+{
+ if (num == 0)
+ unregister_chrdev (dev_major, MEI_DIRNAME);
+ return 0;
+}
+
+static int
+IFX_MEI_InitDevice (int num)
+{
+ DSL_DEV_Device_t *pDev;
+ u32 temp;
+ pDev = &dsl_devices[num];
+ if (pDev == NULL)
+ return -ENOMEM;
+ pDev->pPriv = &sDanube_Mei_Private[num];
+ memset (pDev->pPriv, 0, sizeof (ifx_mei_device_private_t));
+
+ memset (&DSL_DEV_PRIVATE(pDev)->
+ adsl_mem_info[0], 0,
+ sizeof (smmu_mem_info_t) * MAX_BAR_REGISTERS);
+
+ if (num == 0) {
+ pDev->nIrq[IFX_DFEIR] = LTQ_MEI_INT;
+ pDev->nIrq[IFX_DYING_GASP] = LTQ_MEI_DYING_GASP_INT;
+ pDev->base_address = KSEG1 + LTQ_MEI_BASE_ADDR;
+
+ /* Power up MEI */
+#ifdef CONFIG_LANTIQ_AMAZON_SE
+ *LTQ_PMU_PWDCR &= ~(1 << 9); // enable dsl
+ *LTQ_PMU_PWDCR &= ~(1 << 15); // enable AHB base
+#else
+ temp = ltq_r32(LTQ_PMU_PWDCR);
+ temp &= 0xffff7dbe;
+ ltq_w32(temp, LTQ_PMU_PWDCR);
+#endif
+ }
+ pDev->nInUse = 0;
+ DSL_DEV_PRIVATE(pDev)->modem_ready = 0;
+ DSL_DEV_PRIVATE(pDev)->arcmsgav = 0;
+
+ MEI_INIT_WAKELIST ("arcq", DSL_DEV_PRIVATE(pDev)->wait_queue_arcmsgav); // for ARCMSGAV
+ MEI_INIT_WAKELIST ("arcr", DSL_DEV_PRIVATE(pDev)->wait_queue_modemready); // for arc modem ready
+
+ MEI_MUTEX_INIT (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema, 1); // semaphore initialization, mutex
+#if 0
+ MEI_MASK_AND_ACK_IRQ (pDev->nIrq[IFX_DFEIR]);
+ MEI_MASK_AND_ACK_IRQ (pDev->nIrq[IFX_DYING_GASP]);
+#endif
+ if (request_irq (pDev->nIrq[IFX_DFEIR], IFX_MEI_IrqHandle, 0, "DFEIR", pDev) != 0) {
+ IFX_MEI_EMSG ("request_irq %d failed!\n", pDev->nIrq[IFX_DFEIR]);
+ return -1;
+ }
+ /*if (request_irq (pDev->nIrq[IFX_DYING_GASP], IFX_MEI_Dying_Gasp_IrqHandle, 0, "DYING_GASP", pDev) != 0) {
+ IFX_MEI_EMSG ("request_irq %d failed!\n", pDev->nIrq[IFX_DYING_GASP]);
+ return -1;
+ }*/
+// IFX_MEI_DMSG("Device %d initialized. IER %#x\n", num, bsp_get_irq_ier(pDev->nIrq[IFX_DYING_GASP]));
+ return 0;
+}
+
+static int
+IFX_MEI_ExitDevice (int num)
+{
+ DSL_DEV_Device_t *pDev;
+ pDev = &dsl_devices[num];
+
+ if (pDev == NULL)
+ return -EIO;
+
+ disable_irq (pDev->nIrq[IFX_DFEIR]);
+ disable_irq (pDev->nIrq[IFX_DYING_GASP]);
+
+ free_irq(pDev->nIrq[IFX_DFEIR], pDev);
+ free_irq(pDev->nIrq[IFX_DYING_GASP], pDev);
+
+ return 0;
+}
+
+static DSL_DEV_Device_t *
+IFX_BSP_HandleGet (int maj, int num)
+{
+ if (num > BSP_MAX_DEVICES)
+ return NULL;
+ return &dsl_devices[num];
+}
+
+DSL_DEV_Device_t *
+DSL_BSP_DriverHandleGet (int maj, int num)
+{
+ DSL_DEV_Device_t *pDev;
+
+ if (num > BSP_MAX_DEVICES)
+ return NULL;
+
+ pDev = &dsl_devices[num];
+ if (!try_module_get(pDev->owner))
+ return NULL;
+
+ pDev->nInUse++;
+ return pDev;
+}
+
+int
+DSL_BSP_DriverHandleDelete (DSL_DEV_Device_t * nHandle)
+{
+ DSL_DEV_Device_t *pDev = (DSL_DEV_Device_t *) nHandle;
+ if (pDev->nInUse)
+ pDev->nInUse--;
+ module_put(pDev->owner);
+ return 0;
+}
+
+static int
+IFX_MEI_Open (DSL_DRV_inode_t * ino, DSL_DRV_file_t * fil)
+{
+ int maj = MAJOR (ino->i_rdev);
+ int num = MINOR (ino->i_rdev);
+
+ DSL_DEV_Device_t *pDev = NULL;
+ if ((pDev = DSL_BSP_DriverHandleGet (maj, num)) == NULL) {
+ IFX_MEI_EMSG("open(%d:%d) fail!\n", maj, num);
+ return -EIO;
+ }
+ fil->private_data = pDev;
+ return 0;
+}
+
+static int
+IFX_MEI_Release (DSL_DRV_inode_t * ino, DSL_DRV_file_t * fil)
+{
+ //int maj = MAJOR(ino->i_rdev);
+ int num = MINOR (ino->i_rdev);
+ DSL_DEV_Device_t *pDev;
+
+ pDev = &dsl_devices[num];
+ if (pDev == NULL)
+ return -EIO;
+ DSL_BSP_DriverHandleDelete (pDev);
+ return 0;
+}
+
+/**
+ * Callback function for linux userspace program writing
+ */
+static ssize_t
+IFX_MEI_Write (DSL_DRV_file_t * filp, const char *buf, size_t size, loff_t * loff)
+{
+ DSL_DEV_MeiError_t mei_error = DSL_DEV_MEI_ERR_FAILURE;
+ long offset = 0;
+ DSL_DEV_Device_t *pDev = (DSL_DEV_Device_t *) filp->private_data;
+
+ if (pDev == NULL)
+ return -EIO;
+
+ mei_error =
+ DSL_BSP_FWDownload (pDev, buf, size, (long *) loff, &offset);
+
+ if (mei_error == DSL_DEV_MEI_ERR_FAILURE)
+ return -EIO;
+ return (ssize_t) offset;
+}
+
+/**
+ * Callback function for linux userspace program ioctling
+ */
+static int
+IFX_MEI_IoctlCopyFrom (int from_kernel, char *dest, char *from, int size)
+{
+ int ret = 0;
+
+ if (!from_kernel)
+ ret = copy_from_user ((char *) dest, (char *) from, size);
+ else
+ ret = (int)memcpy ((char *) dest, (char *) from, size);
+ return ret;
+}
+
+static int
+IFX_MEI_IoctlCopyTo (int from_kernel, char *dest, char *from, int size)
+{
+ int ret = 0;
+
+ if (!from_kernel)
+ ret = copy_to_user ((char *) dest, (char *) from, size);
+ else
+ ret = (int)memcpy ((char *) dest, (char *) from, size);
+ return ret;
+}
+
+static int
+IFX_MEI_Ioctls (DSL_DEV_Device_t * pDev, int from_kernel, unsigned int command, unsigned long lon)
+{
+ int i = 0;
+ int meierr = DSL_DEV_MEI_ERR_SUCCESS;
+ u32 base_address = LTQ_MEI_BASE_ADDR;
+ DSL_DEV_WinHost_Message_t winhost_msg, m;
+ DSL_DEV_MeiDebug_t debugrdwr;
+ DSL_DEV_MeiReg_t regrdwr;
+
+ switch (command) {
+
+ case DSL_FIO_BSP_CMV_WINHOST:
+ IFX_MEI_IoctlCopyFrom (from_kernel, (char *) winhost_msg.msg.TxMessage,
+ (char *) lon, MSG_LENGTH * 2);
+
+ if ((meierr = DSL_BSP_SendCMV (pDev, winhost_msg.msg.TxMessage, YES_REPLY,
+ winhost_msg.msg.RxMessage)) != DSL_DEV_MEI_ERR_SUCCESS) {
+ IFX_MEI_EMSG ("WINHOST CMV fail :TxMessage:%X %X %X %X, RxMessage:%X %X %X %X %X\n",
+ winhost_msg.msg.TxMessage[0], winhost_msg.msg.TxMessage[1], winhost_msg.msg.TxMessage[2], winhost_msg.msg.TxMessage[3],
+ winhost_msg.msg.RxMessage[0], winhost_msg.msg.RxMessage[1], winhost_msg.msg.RxMessage[2], winhost_msg.msg.RxMessage[3],
+ winhost_msg.msg.RxMessage[4]);
+ meierr = DSL_DEV_MEI_ERR_FAILURE;
+ }
+ else {
+ IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon,
+ (char *) winhost_msg.msg.RxMessage,
+ MSG_LENGTH * 2);
+ }
+ break;
+
+ case DSL_FIO_BSP_CMV_READ:
+ IFX_MEI_IoctlCopyFrom (from_kernel, (char *) (&regrdwr),
+ (char *) lon, sizeof (DSL_DEV_MeiReg_t));
+
+ IFX_MEI_LongWordRead ((u32) regrdwr.iAddress,
+ (u32 *) & (regrdwr.iData));
+
+ IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon,
+ (char *) (&regrdwr),
+ sizeof (DSL_DEV_MeiReg_t));
+
+ break;
+
+ case DSL_FIO_BSP_CMV_WRITE:
+ IFX_MEI_IoctlCopyFrom (from_kernel, (char *) (&regrdwr),
+ (char *) lon, sizeof (DSL_DEV_MeiReg_t));
+
+ IFX_MEI_LongWordWrite ((u32) regrdwr.iAddress,
+ regrdwr.iData);
+ break;
+
+ case DSL_FIO_BSP_GET_BASE_ADDRESS:
+ IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon,
+ (char *) (&base_address),
+ sizeof (base_address));
+ break;
+
+ case DSL_FIO_BSP_IS_MODEM_READY:
+ i = IFX_MEI_IsModemReady (pDev);
+ IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon,
+ (char *) (&i), sizeof (int));
+ meierr = DSL_DEV_MEI_ERR_SUCCESS;
+ break;
+ case DSL_FIO_BSP_RESET:
+ case DSL_FIO_BSP_REBOOT:
+ meierr = IFX_MEI_CpuModeSet (pDev, DSL_CPU_RESET);
+ meierr = IFX_MEI_CpuModeSet (pDev, DSL_CPU_HALT);
+ break;
+
+ case DSL_FIO_BSP_HALT:
+ meierr = IFX_MEI_CpuModeSet (pDev, DSL_CPU_HALT);
+ break;
+
+ case DSL_FIO_BSP_RUN:
+ meierr = IFX_MEI_CpuModeSet (pDev, DSL_CPU_RUN);
+ break;
+ case DSL_FIO_BSP_BOOTDOWNLOAD:
+ meierr = IFX_MEI_DownloadBootCode (pDev);
+ break;
+ case DSL_FIO_BSP_JTAG_ENABLE:
+ meierr = IFX_MEI_ArcJtagEnable (pDev, 1);
+ break;
+
+ case DSL_FIO_BSP_REMOTE:
+ IFX_MEI_IoctlCopyFrom (from_kernel, (char *) (&i),
+ (char *) lon, sizeof (int));
+
+ meierr = IFX_MEI_AdslMailboxIRQEnable (pDev, i);
+ break;
+
+ case DSL_FIO_BSP_DSL_START:
+ IFX_MEI_DMSG("DSL_FIO_BSP_DSL_START\n");
+ if ((meierr = IFX_MEI_RunAdslModem (pDev)) != DSL_DEV_MEI_ERR_SUCCESS) {
+ IFX_MEI_EMSG ("IFX_MEI_RunAdslModem() error...");
+ meierr = DSL_DEV_MEI_ERR_FAILURE;
+ }
+ break;
+
+ case DSL_FIO_BSP_DEBUG_READ:
+ case DSL_FIO_BSP_DEBUG_WRITE:
+ IFX_MEI_IoctlCopyFrom (from_kernel,
+ (char *) (&debugrdwr),
+ (char *) lon,
+ sizeof (debugrdwr));
+
+ if (command == DSL_FIO_BSP_DEBUG_READ)
+ meierr = DSL_BSP_MemoryDebugAccess (pDev,
+ DSL_BSP_MEMORY_READ,
+ debugrdwr.
+ iAddress,
+ debugrdwr.
+ buffer,
+ debugrdwr.
+ iCount);
+ else
+ meierr = DSL_BSP_MemoryDebugAccess (pDev,
+ DSL_BSP_MEMORY_WRITE,
+ debugrdwr.
+ iAddress,
+ debugrdwr.
+ buffer,
+ debugrdwr.
+ iCount);
+
+ IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, (char *) (&debugrdwr), sizeof (debugrdwr));
+ break;
+ case DSL_FIO_BSP_GET_VERSION:
+ IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, (char *) (&bsp_mei_version), sizeof (DSL_DEV_Version_t));
+ break;
+
+#define LTQ_MPS_CHIPID_VERSION_GET(value) (((value) >> 28) & ((1 << 4) - 1))
+ case DSL_FIO_BSP_GET_CHIP_INFO:
+ bsp_chip_info.major = 1;
+ bsp_chip_info.minor = LTQ_MPS_CHIPID_VERSION_GET(*LTQ_MPS_CHIPID);
+ IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, (char *) (&bsp_chip_info), sizeof (DSL_DEV_HwVersion_t));
+ meierr = DSL_DEV_MEI_ERR_SUCCESS;
+ break;
+
+ case DSL_FIO_BSP_FREE_RESOURCE:
+ makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_STAT, 4, 0, 1, NULL, m.msg.TxMessage);
+ if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS) {
+ meierr = DSL_DEV_MEI_ERR_FAILURE;
+ return -EIO;
+ }
+ IFX_MEI_DMSG("RxMessage[4] = %#x\n", m.msg.RxMessage[4]);
+ if (!(m.msg.RxMessage[4] & DSL_DEV_STAT_CODESWAP_COMPLETE)) {
+ meierr = DSL_DEV_MEI_ERR_FAILURE;
+ return -EAGAIN;
+ }
+ IFX_MEI_DMSG("Freeing all memories marked FREE_SHOWTIME\n");
+ IFX_MEI_DFEMemoryFree (pDev, FREE_SHOWTIME);
+ meierr = DSL_DEV_MEI_ERR_SUCCESS;
+ break;
+#ifdef CONFIG_IFXMIPS_AMAZON_SE
+ case DSL_FIO_ARC_MUX_TEST:
+ AMAZON_SE_MEI_ARC_MUX_Test();
+ break;
+#endif
+ default:
+// IFX_MEI_EMSG("Invalid IOCTL command: %d\n");
+ break;
+ }
+ return meierr;
+}
+
+#ifdef CONFIG_IFXMIPS_AMAZON_SE
+void AMAZON_SE_MEI_ARC_MUX_Test(void)
+{
+ u32 *p, i;
+ *LTQ_RCU_RST |= LTQ_RCU_RST_REQ_MUX_ARC;
+
+ p = (u32*)(DFE_LDST_BASE_ADDR + IRAM0_BASE);
+ IFX_MEI_EMSG("Writing to IRAM0(%p)...\n", p);
+ for (i = 0; i < IRAM0_SIZE/sizeof(u32); i++, p++) {
+ *p = 0xdeadbeef;
+ if (*p != 0xdeadbeef)
+ IFX_MEI_EMSG("%p: %#x\n", p, *p);
+ }
+
+ p = (u32*)(DFE_LDST_BASE_ADDR + IRAM1_BASE);
+ IFX_MEI_EMSG("Writing to IRAM1(%p)...\n", p);
+ for (i = 0; i < IRAM1_SIZE/sizeof(u32); i++, p++) {
+ *p = 0xdeadbeef;
+ if (*p != 0xdeadbeef)
+ IFX_MEI_EMSG("%p: %#x\n", p, *p);
+ }
+
+ p = (u32*)(DFE_LDST_BASE_ADDR + BRAM_BASE);
+ IFX_MEI_EMSG("Writing to BRAM(%p)...\n", p);
+ for (i = 0; i < BRAM_SIZE/sizeof(u32); i++, p++) {
+ *p = 0xdeadbeef;
+ if (*p != 0xdeadbeef)
+ IFX_MEI_EMSG("%p: %#x\n", p, *p);
+ }
+
+ p = (u32*)(DFE_LDST_BASE_ADDR + XRAM_BASE);
+ IFX_MEI_EMSG("Writing to XRAM(%p)...\n", p);
+ for (i = 0; i < XRAM_SIZE/sizeof(u32); i++, p++) {
+ *p = 0xdeadbeef;
+ if (*p != 0xdeadbeef)
+ IFX_MEI_EMSG("%p: %#x\n", p, *p);
+ }
+
+ p = (u32*)(DFE_LDST_BASE_ADDR + YRAM_BASE);
+ IFX_MEI_EMSG("Writing to YRAM(%p)...\n", p);
+ for (i = 0; i < YRAM_SIZE/sizeof(u32); i++, p++) {
+ *p = 0xdeadbeef;
+ if (*p != 0xdeadbeef)
+ IFX_MEI_EMSG("%p: %#x\n", p, *p);
+ }
+
+ p = (u32*)(DFE_LDST_BASE_ADDR + EXT_MEM_BASE);
+ IFX_MEI_EMSG("Writing to EXT_MEM(%p)...\n", p);
+ for (i = 0; i < EXT_MEM_SIZE/sizeof(u32); i++, p++) {
+ *p = 0xdeadbeef;
+ if (*p != 0xdeadbeef)
+ IFX_MEI_EMSG("%p: %#x\n", p, *p);
+ }
+ *LTQ_RCU_RST &= ~LTQ_RCU_RST_REQ_MUX_ARC;
+}
+#endif
+int
+DSL_BSP_KernelIoctls (DSL_DEV_Device_t * pDev, unsigned int command,
+ unsigned long lon)
+{
+ int error = 0;
+
+ error = IFX_MEI_Ioctls (pDev, 1, command, lon);
+ return error;
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
+static int
+IFX_MEI_UserIoctls (DSL_DRV_inode_t * ino, DSL_DRV_file_t * fil,
+ unsigned int command, unsigned long lon)
+#else
+static int
+IFX_MEI_UserIoctls (DSL_DRV_file_t * fil,
+ unsigned int command, unsigned long lon)
+#endif
+{
+ int error = 0;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
+ int maj = MAJOR (ino->i_rdev);
+ int num = MINOR (ino->i_rdev);
+#endif
+ DSL_DEV_Device_t *pDev;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
+ pDev = IFX_BSP_HandleGet (maj, num);
+#else
+ pDev = IFX_BSP_HandleGet (0, 0);
+#endif
+ if (pDev == NULL)
+ return -EIO;
+
+ error = IFX_MEI_Ioctls (pDev, 0, command, lon);
+ return error;
+}
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Register a callback function for linux proc filesystem
+ */
+static int
+IFX_MEI_InitProcFS (int num)
+{
+ struct proc_dir_entry *entry;
+ int i ;
+ DSL_DEV_Device_t *pDev;
+ reg_entry_t regs_temp[PROC_ITEMS] = {
+ /* flag, name, description } */
+ {NULL, "arcmsgav", "arc to mei message ", 0},
+ {NULL, "cmv_reply", "cmv needs reply", 0},
+ {NULL, "cmv_waiting", "waiting for cmv reply from arc", 0},
+ {NULL, "modem_ready_cnt", "ARC to MEI indicator count", 0},
+ {NULL, "cmv_count", "MEI to ARC CMVs", 0},
+ {NULL, "reply_count", "ARC to MEI Reply", 0},
+ {NULL, "Recent_indicator", "most recent indicator", 0},
+ {NULL, "fw_version", "Firmware Version", 0},
+ {NULL, "fw_date", "Firmware Date", 0},
+ {NULL, "meminfo", "Memory Allocation Information", 0},
+ {NULL, "version", "MEI version information", 0},
+ };
+
+ pDev = &dsl_devices[num];
+ if (pDev == NULL)
+ return -ENOMEM;
+
+ regs_temp[0].flag = &(DSL_DEV_PRIVATE(pDev)->arcmsgav);
+ regs_temp[1].flag = &(DSL_DEV_PRIVATE(pDev)->cmv_reply);
+ regs_temp[2].flag = &(DSL_DEV_PRIVATE(pDev)->cmv_waiting);
+ regs_temp[3].flag = &(DSL_DEV_PRIVATE(pDev)->modem_ready_cnt);
+ regs_temp[4].flag = &(DSL_DEV_PRIVATE(pDev)->cmv_count);
+ regs_temp[5].flag = &(DSL_DEV_PRIVATE(pDev)->reply_count);
+ regs_temp[6].flag = (int *) &(DSL_DEV_PRIVATE(pDev)->Recent_indicator);
+
+ memcpy ((char *) regs[num], (char *) regs_temp, sizeof (regs_temp));
+ // procfs
+ meidir = proc_mkdir (MEI_DIRNAME, NULL);
+ if (meidir == NULL) {
+ IFX_MEI_EMSG ("Failed to create /proc/%s\n", MEI_DIRNAME);
+ return (-ENOMEM);
+ }
+
+ for (i = 0; i < NUM_OF_REG_ENTRY; i++) {
+ entry = create_proc_entry (regs[num][i].name,
+ S_IWUSR | S_IRUSR | S_IRGRP |
+ S_IROTH, meidir);
+ if (entry) {
+ regs[num][i].low_ino = entry->low_ino;
+ entry->proc_fops = &IFX_MEI_ProcOperations;
+ }
+ else {
+ IFX_MEI_EMSG ("Failed to create /proc/%s/%s\n", MEI_DIRNAME, regs[num][i].name);
+ return (-ENOMEM);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Reading function for linux proc filesystem
+ */
+static int
+IFX_MEI_ProcRead (struct file *file, char *buf, size_t nbytes, loff_t * ppos)
+{
+ int i_ino = (file->f_dentry->d_inode)->i_ino;
+ char *p = buf;
+ int i;
+ int num;
+ reg_entry_t *entry = NULL;
+ DSL_DEV_Device_t *pDev = NULL;
+ DSL_DEV_WinHost_Message_t m;
+
+ for (num = 0; num < BSP_MAX_DEVICES; num++) {
+ for (i = 0; i < NUM_OF_REG_ENTRY; i++) {
+ if (regs[num][i].low_ino == (unsigned short)i_ino) {
+ entry = &regs[num][i];
+ pDev = &dsl_devices[num];
+ break;
+ }
+ }
+ }
+ if (entry == NULL)
+ return -EINVAL;
+ else if (strcmp(entry->name, "meminfo") == 0) {
+ if (*ppos > 0) /* Assume reading completed in previous read */
+ return 0;
+ p += sprintf (p, "No Address Size\n");
+ for (i = 0; i < MAX_BAR_REGISTERS; i++) {
+ p += sprintf (p, "BAR[%02d] Addr:0x%08X Size:%lu\n",
+ i, (u32) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[i].address,
+ DSL_DEV_PRIVATE(pDev)-> adsl_mem_info[i].size);
+ //printk( "BAR[%02d] Addr:0x%08X Size:%d\n",i,adsl_mem_info[i].address,adsl_mem_info[i].size);
+ }
+ *ppos += (p - buf);
+ } else if (strcmp(entry->name, "fw_version") == 0) {
+ if (*ppos > 0) /* Assume reading completed in previous read */
+ return 0;
+ if (DSL_DEV_PRIVATE(pDev)->modem_ready_cnt < 1)
+ return -EAGAIN;
+ //major:bits 0-7
+ //minor:bits 8-15
+ makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 54, 0, 1, NULL, m.msg.TxMessage);
+ if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS)
+ return -EIO;
+ p += sprintf(p, "FW Version: %d.%d.", m.msg.RxMessage[4] & 0xFF, (m.msg.RxMessage[4] >> 8) & 0xFF);
+ //sub_version:bits 4-7
+ //int_version:bits 0-3
+ //spl_appl:bits 8-13
+ //rel_state:bits 14-15
+ makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 54, 1, 1, NULL, m.msg.TxMessage);
+ if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS)
+ return -EIO;
+ p += sprintf(p, "%d.%d.%d.%d\n",
+ (m.msg.RxMessage[4] >> 4) & 0xF, m.msg.RxMessage[4] & 0xF,
+ (m.msg.RxMessage[4] >> 14) & 3, (m.msg.RxMessage[4] >> 8) & 0x3F);
+ *ppos += (p - buf);
+ } else if (strcmp(entry->name, "fw_date") == 0) {
+ if (*ppos > 0) /* Assume reading completed in previous read */
+ return 0;
+ if (DSL_DEV_PRIVATE(pDev)->modem_ready_cnt < 1)
+ return -EAGAIN;
+
+ makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 55, 0, 1, NULL, m.msg.TxMessage);
+ if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS)
+ return -EIO;
+ /* Day/Month */
+ p += sprintf(p, "FW Date: %d.%d.", m.msg.RxMessage[4] & 0xFF, (m.msg.RxMessage[4] >> 8) & 0xFF);
+
+ makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 55, 2, 1, NULL, m.msg.TxMessage);
+ if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS)
+ return -EIO;
+ /* Year */
+ p += sprintf(p, "%d ", m.msg.RxMessage[4]);
+
+ makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 55, 1, 1, NULL, m.msg.TxMessage);
+ if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS)
+ return -EIO;
+ /* Hour:Minute */
+ p += sprintf(p, "%d:%d\n", (m.msg.RxMessage[4] >> 8) & 0xFF, m.msg.RxMessage[4] & 0xFF);
+
+ *ppos += (p - buf);
+ } else if (strcmp(entry->name, "version") == 0) {
+ if (*ppos > 0) /* Assume reading completed in previous read */
+ return 0;
+ p += sprintf (p, "IFX MEI V%ld.%ld.%ld\n", bsp_mei_version.major, bsp_mei_version.minor, bsp_mei_version.revision);
+
+ *ppos += (p - buf);
+ } else if (entry->flag != (int *) DSL_DEV_PRIVATE(pDev)->Recent_indicator) {
+ if (*ppos > 0) /* Assume reading completed in previous read */
+ return 0; // indicates end of file
+ p += sprintf (p, "0x%08X\n\n", *(entry->flag));
+ *ppos += (p - buf);
+ if ((p - buf) > nbytes) /* Assume output can be read at one time */
+ return -EINVAL;
+ } else {
+ if ((int) (*ppos) / ((int) 7) == 16)
+ return 0; // indicate end of the message
+ p += sprintf (p, "0x%04X\n\n", *(((u16 *) (entry->flag)) + (int) (*ppos) / ((int) 7)));
+ *ppos += (p - buf);
+ }
+ return p - buf;
+}
+
+/*
+ * Writing function for linux proc filesystem
+ */
+static ssize_t
+IFX_MEI_ProcWrite (struct file *file, const char *buffer, size_t count, loff_t * ppos)
+{
+ int i_ino = (file->f_dentry->d_inode)->i_ino;
+ reg_entry_t *current_reg = NULL;
+ int i = 0;
+ int num = 0;
+ unsigned long newRegValue = 0;
+ char *endp = NULL;
+ DSL_DEV_Device_t *pDev = NULL;
+
+ for (num = 0; num < BSP_MAX_DEVICES; num++) {
+ for (i = 0; i < NUM_OF_REG_ENTRY; i++) {
+ if (regs[num][i].low_ino == i_ino) {
+ current_reg = &regs[num][i];
+ pDev = &dsl_devices[num];
+ break;
+ }
+ }
+ }
+ if ((current_reg == NULL)
+ || (current_reg->flag ==
+ (int *) DSL_DEV_PRIVATE(pDev)->
+ Recent_indicator))
+ return -EINVAL;
+
+ newRegValue = simple_strtoul (buffer, &endp, 0);
+ *(current_reg->flag) = (int) newRegValue;
+ return (count + endp - buffer);
+}
+#endif //CONFIG_PROC_FS
+
+static int adsl_dummy_ledcallback(void)
+{
+ return 0;
+}
+
+int ifx_mei_atm_led_blink(void)
+{
+ return g_adsl_ledcallback();
+}
+EXPORT_SYMBOL(ifx_mei_atm_led_blink);
+
+int ifx_mei_atm_showtime_check(int *is_showtime, struct port_cell_info *port_cell, void **xdata_addr)
+{
+ int i;
+
+ if ( is_showtime ) {
+ *is_showtime = g_tx_link_rate[0] == 0 && g_tx_link_rate[1] == 0 ? 0 : 1;
+ }
+
+ if ( port_cell ) {
+ for ( i = 0; i < port_cell->port_num && i < 2; i++ )
+ port_cell->tx_link_rate[i] = g_tx_link_rate[i];
+ }
+
+ if ( xdata_addr ) {
+ if ( g_tx_link_rate[0] == 0 && g_tx_link_rate[1] == 0 )
+ *xdata_addr = NULL;
+ else
+ *xdata_addr = g_xdata_addr;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(ifx_mei_atm_showtime_check);
+
+/*
+ * Writing function for linux proc filesystem
+ */
+int __init
+IFX_MEI_ModuleInit (void)
+{
+ int i = 0;
+ static struct class *dsl_class;
+
+ pr_info("IFX MEI Version %ld.%02ld.%02ld", bsp_mei_version.major, bsp_mei_version.minor, bsp_mei_version.revision);
+
+ for (i = 0; i < BSP_MAX_DEVICES; i++) {
+ if (IFX_MEI_InitDevice (i) != 0) {
+ IFX_MEI_EMSG("Init device fail!\n");
+ return -EIO;
+ }
+ IFX_MEI_InitDevNode (i);
+#ifdef CONFIG_PROC_FS
+ IFX_MEI_InitProcFS (i);
+#endif
+ }
+ for (i = 0; i <= DSL_BSP_CB_LAST ; i++)
+ dsl_bsp_event_callback[i].function = NULL;
+
+#ifdef CONFIG_LTQ_MEI_FW_LOOPBACK
+ IFX_MEI_DMSG("Start loopback test...\n");
+ DFE_Loopback_Test ();
+#endif
+ dsl_class = class_create(THIS_MODULE, "ifx_mei");
+ device_create(dsl_class, NULL, MKDEV(MEI_MAJOR, 0), NULL, "ifx_mei");
+ return 0;
+}
+
+void __exit
+IFX_MEI_ModuleExit (void)
+{
+ int i = 0;
+ int num;
+
+ for (num = 0; num < BSP_MAX_DEVICES; num++) {
+ IFX_MEI_CleanUpDevNode (num);
+#ifdef CONFIG_PROC_FS
+ for (i = 0; i < NUM_OF_REG_ENTRY; i++) {
+ remove_proc_entry (regs[num][i].name, meidir);
+ }
+#endif
+ }
+
+ remove_proc_entry (MEI_DIRNAME, NULL);
+ for (i = 0; i < BSP_MAX_DEVICES; i++) {
+ for (i = 0; i < BSP_MAX_DEVICES; i++) {
+ IFX_MEI_ExitDevice (i);
+ }
+ }
+}
+
+/* export function for DSL Driver */
+
+/* The functions of MEI_DriverHandleGet and MEI_DriverHandleDelete are
+something like open/close in kernel space , where the open could be used
+to register a callback for autonomous messages and returns a mei driver context pointer (comparable to the file descriptor in user space)
+ The context will be required for the multi line chips future! */
+
+EXPORT_SYMBOL (DSL_BSP_DriverHandleGet);
+EXPORT_SYMBOL (DSL_BSP_DriverHandleDelete);
+
+EXPORT_SYMBOL (DSL_BSP_ATMLedCBRegister);
+EXPORT_SYMBOL (DSL_BSP_ATMLedCBUnregister);
+EXPORT_SYMBOL (DSL_BSP_KernelIoctls);
+EXPORT_SYMBOL (DSL_BSP_AdslLedInit);
+//EXPORT_SYMBOL (DSL_BSP_AdslLedSet);
+EXPORT_SYMBOL (DSL_BSP_FWDownload);
+EXPORT_SYMBOL (DSL_BSP_Showtime);
+
+EXPORT_SYMBOL (DSL_BSP_MemoryDebugAccess);
+EXPORT_SYMBOL (DSL_BSP_SendCMV);
+
+// provide a register/unregister function for DSL driver to register a event callback function
+EXPORT_SYMBOL (DSL_BSP_EventCBRegister);
+EXPORT_SYMBOL (DSL_BSP_EventCBUnregister);
+
+module_init (IFX_MEI_ModuleInit);
+module_exit (IFX_MEI_ModuleExit);
+
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/package/ltq-ifxos/Makefile b/package/ltq-ifxos/Makefile
new file mode 100644
index 000000000..a43a10be3
--- /dev/null
+++ b/package/ltq-ifxos/Makefile
@@ -0,0 +1,51 @@
+#
+# Copyright (C) 2009-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=lib_ifxos
+PKG_VERSION:=1.5.14
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_RELEASE:=3
+PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
+PKG_MD5SUM:=bc107f9d8ff6bed4c2760a2817bbb029
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/ltq-ifxos
+ SUBMENU:=Voice over IP
+ TITLE:=Lantiq OS abstraction library
+ URL:=http://www.lantiq.com/
+ MAINTAINER:=Lantiq
+ DEPENDS:=@TARGET_lantiq
+ FILES:=$(PKG_BUILD_DIR)/src/drv_ifxos.ko
+ AUTOLOAD:=$(call AutoLoad,10,drv_ifxos)
+endef
+
+CONFIGURE_ARGS += \
+ ARCH=$(LINUX_KARCH) \
+ --enable-linux-26 \
+ --enable-kernelbuild="$(LINUX_DIR)" \
+ --enable-kernelincl="$(LINUX_DIR)/include" \
+ --enable-add_drv_cflags="-fno-pic -mno-abicalls -mlong-calls -G 0"
+
+define Build/Configure
+ (cd $(PKG_BUILD_DIR); aclocal && autoconf && automake)
+ $(call Build/Configure/Default)
+endef
+
+ifdef CONFIG_TARGET_lantiq
+ define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/{lib,include/ifxos}
+ $(CP) $(PKG_BUILD_DIR)/src/include/* $(1)/usr/include/ifxos
+ mkdir -p $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/src/libifxos.a $(1)/usr/lib/libifxos.a
+ endef
+endif
+
+$(eval $(call KernelPackage,ltq-ifxos))
diff --git a/package/ltq-ifxos/patches/100-portability.patch b/package/ltq-ifxos/patches/100-portability.patch
new file mode 100644
index 000000000..d1ce7503a
--- /dev/null
+++ b/package/ltq-ifxos/patches/100-portability.patch
@@ -0,0 +1,11 @@
+--- a/configure.in
++++ b/configure.in
+@@ -64,7 +64,7 @@ dnl Set kernel build path
+ AC_ARG_ENABLE(kernelbuild,
+ AS_HELP_STRING(--enable-kernelbuild=x,Set the target kernel build path (only for kernel 2.6.x)),
+ [
+- if test -e $enableval/include/linux/autoconf.h; then
++ if test -e $enableval/include/linux/autoconf.h -o -e $enableval/include/generated/autoconf.h; then
+ AC_SUBST([KERNEL_BUILD_PATH],[$enableval])
+ else
+ AC_MSG_ERROR([The kernel build directory is not valid or not configured!])
diff --git a/package/ltq-ifxos/patches/120-fix_smp_lock.patch b/package/ltq-ifxos/patches/120-fix_smp_lock.patch
new file mode 100644
index 000000000..aea4305a9
--- /dev/null
+++ b/package/ltq-ifxos/patches/120-fix_smp_lock.patch
@@ -0,0 +1,12 @@
+--- a/src/linux/ifxos_linux_thread_drv.c
++++ b/src/linux/ifxos_linux_thread_drv.c
+@@ -34,7 +34,9 @@
+ #include <linux/sched.h>
+ #include <linux/version.h>
+ #include <linux/completion.h>
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
+ #include <linux/smp_lock.h>
++#endif
+ #include <linux/signal.h>
+
+
diff --git a/package/ltq-kpi2udp/Makefile b/package/ltq-kpi2udp/Makefile
new file mode 100644
index 000000000..497f743e0
--- /dev/null
+++ b/package/ltq-kpi2udp/Makefile
@@ -0,0 +1,48 @@
+#
+# Copyright (C) 2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=drv_kpi2udp
+PKG_VERSION:=2.2.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=drv_kpi2udp-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
+PKG_MD5SUM:=af3855609554c7f3d2c3df8c597f50a7
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/ltq-kpi2udp
+ SUBMENU:=Voice over IP
+ TITLE:=TAPI KPI2UDP plug-in
+ URL:=http://www.lantiq.com/
+ DEPENDS:=+kmod-ltq-tapi @TARGET_lantiq
+ FILES:=$(PKG_BUILD_DIR)/drv_kpi2udp.ko
+ AUTOLOAD:=$(call AutoLoad,26,drv_kpi2udp)
+ MAINTAINER:=John Crispin <blogic@openwrt.org>
+endef
+
+define KernelPackage/ltq-kpi2udp/description
+ RTP packet path accelleration into IP stack (strongly recommended)
+endef
+
+CONFIGURE_ARGS += --enable-kernelincl="$(LINUX_DIR)/include" \
+ --enable-tapiincl="$(STAGING_DIR)/usr/include/drv_tapi" \
+ --with-ifxos-incl=$(STAGING_DIR)/usr/include/ifxos \
+ --enable-warning \
+ --enable-linux-26 \
+ --enable-kernelbuild="$(LINUX_DIR)" \
+ ARCH=$(LINUX_KARCH)
+
+define Build/Configure
+ (cd $(PKG_BUILD_DIR); aclocal && autoconf && automake)
+ $(call Build/Configure/Default)
+endef
+
+$(eval $(call KernelPackage,ltq-kpi2udp))
diff --git a/package/ltq-kpi2udp/patches/100-configure.patch b/package/ltq-kpi2udp/patches/100-configure.patch
new file mode 100644
index 000000000..8f6704e9e
--- /dev/null
+++ b/package/ltq-kpi2udp/patches/100-configure.patch
@@ -0,0 +1,11 @@
+--- a/configure.in
++++ b/configure.in
+@@ -113,7 +113,7 @@
+ AC_ARG_ENABLE(kernelbuild,
+ AS_HELP_STRING(--enable-kernelbuild=x,Set the target kernel build path),
+ [
+- if test -r $enableval/include/linux/autoconf.h; then
++ if test -r $enableval/include/generated/autoconf.h; then
+ AC_SUBST([KERNEL_BUILD_PATH],[$enableval])
+ else
+ AC_MSG_ERROR([The kernel build directory is not valid or not configured!])
diff --git a/package/ltq-kpi2udp/patches/110-ifx_udp_redirect.patch b/package/ltq-kpi2udp/patches/110-ifx_udp_redirect.patch
new file mode 100644
index 000000000..abb3d353a
--- /dev/null
+++ b/package/ltq-kpi2udp/patches/110-ifx_udp_redirect.patch
@@ -0,0 +1,29 @@
+--- a/ifx_udp_redirect.c
++++ b/ifx_udp_redirect.c
+@@ -256,7 +256,7 @@
+ {
+ if (redtab.channels[i].in_use == IFX_TRUE)
+ {
+- if (redtab.channels[i].sk->sk_lock.owner != 0)
++ if (redtab.channels[i].sk->sk_lock.owned != 0)
+ return IFX_TRUE;
+ }
+ }
+@@ -545,7 +545,7 @@
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+ if (sk->num != htons(sport))
+ #else
+- if (((struct inet_sock *)sk)->num != htons(sport))
++ if (((struct inet_sock *)sk)->inet_num != htons(sport))
+ #endif
+ {
+ return CALL_MK_SESSION_ERR;
+@@ -628,7 +628,7 @@
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+ if((vsock != NULL)&&(vsk != NULL)&&(vsk->num > 0))
+ #else
+- if((vsock != NULL)&&(vsk != NULL)&&(((struct inet_sock *)vsk)->num > 0))
++ if((vsock != NULL)&&(vsk != NULL)&&(((struct inet_sock *)vsk)->inet_num > 0))
+ #endif
+ {
+ /*printk("[KPI2UDP] releasing vsock...%p, ops %p\n", vsock, vsock->ops);*/
diff --git a/package/ltq-tapi/Config.in b/package/ltq-tapi/Config.in
new file mode 100644
index 000000000..84dbef239
--- /dev/null
+++ b/package/ltq-tapi/Config.in
@@ -0,0 +1,88 @@
+config VOICE_CPE_TAPI_FAX
+ bool "fax relay and modem support"
+ depends on PACKAGE_kmod-ltq-tapi
+ default n
+ help
+ Option to enable fax/modem support in TAPI.
+ Note: Newer platforms as AR9 and VR9 support a T.38 fax relay stack
+ in FW while older platforms like Danube or VINETIC-CPE require a
+ separate SW stack executed as an application.
+
+config VOICE_CPE_TAPI_CID
+ bool "CID support"
+ depends on PACKAGE_kmod-ltq-tapi
+ default y
+ help
+ Option to enable Caller ID support.
+
+config VOICE_CPE_TAPI_LT_GR909
+ bool "Linetesting GR-909 support"
+ depends on PACKAGE_kmod-ltq-tapi
+ default y
+ help
+ Option to enable linetesting GR-909.
+
+config VOICE_CPE_TAPI_DECT
+ bool "DECT encoding for COSIC modem"
+ depends on PACKAGE_kmod-ltq-tapi
+ default n
+ help
+ Option to enable DECT encoding for COSIC modem.
+
+config VOICE_CPE_TAPI_KPI
+ bool "KPI (Kernel Packet Interface)"
+ depends on PACKAGE_kmod-ltq-tapi
+ default y
+ help
+ Option to enable the generic kernel level packet interface
+ which allows accelerated packet transfer for various purposes.
+ The most important example is the QOS option, which allows
+ to redirect RTP packets directly into the IP stack.
+ Other options relying on KPI are DECT and HDLC.
+
+config VOICE_CPE_TAPI_QOS
+ bool "QOS for accelerated RTP packet handling"
+ depends on PACKAGE_kmod-ltq-tapi
+ default y
+ help
+ Option to enable an accelerated RTP packet transfer inside
+ the LINUX kernel space. This option requires the KPI2UDP
+ packet, which actually provides the OS specific hooks in
+ the IP stack.
+
+config VOICE_CPE_TAPI_STATISTICS
+ bool "TAPI statistics via /proc fs"
+ depends on PACKAGE_kmod-ltq-tapi
+ default y
+ help
+ Option to enable /proc fs statistics for packet counts etc.
+
+config VOICE_CPE_TAPI_METERING
+ bool "Metering (TTX) support"
+ depends on PACKAGE_kmod-ltq-tapi
+ default n
+ help
+ Option to enable metering (TTX) support.
+
+config VOICE_CPE_TAPI_HDLC
+ bool "PCM HDLC support, evaluation"
+ depends on PACKAGE_kmod-ltq-tapi
+ default n
+ help
+ Option to enable PCM HDLC framing inside the firmware, e.g. for
+ ISDN D-Channel access.
+
+config VOICE_CPE_TAPI_TRACES
+ bool "enable driver traces"
+ depends on PACKAGE_kmod-ltq-tapi
+ default y
+ help
+ enable driver traces with different trace levels to be
+ configured dynamically from the application or during insmod
+
+config VOICE_CPE_TAPI_LINUX_HOTPLUG
+ bool "enable driver Linux hotplug events"
+ depends on PACKAGE_kmod-ltq-tapi
+ default y
+ help
+ enable driver Linux hotplug events generation
diff --git a/package/ltq-tapi/Makefile b/package/ltq-tapi/Makefile
new file mode 100644
index 000000000..79b77b75d
--- /dev/null
+++ b/package/ltq-tapi/Makefile
@@ -0,0 +1,70 @@
+#
+# Copyright (C) 2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=drv_tapi
+PKG_VERSION:=3.13.0
+PKG_RELEASE:=3
+
+PKG_SOURCE:=drv_tapi-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
+PKG_MD5SUM:=edb43b494832c540cc035493d18db58f
+
+include $(INCLUDE_DIR)/ltqtapi.mk
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/ltq-tapi
+ SUBMENU:=Voice over IP
+ TITLE:=Lantiq TAPI subsystem
+ URL:=http://www.lantiq.com/
+ DEPENDS:=$(LTQ_TAPI_TARGET) +kmod-ltq-ifxos
+ FILES:=$(PKG_BUILD_DIR)/src/drv_tapi.ko
+ AUTOLOAD:=$(call AutoLoad,20,drv_tapi)
+ MAINTAINER:=John Crispin <blogic@openwrt.org>
+endef
+
+define KernelPackage/ltq-tapi/description
+ Voice Subsystem Telephony API High Level Driver
+endef
+
+define KernelPackage/ltq-tapi/config
+ source "$(SOURCE)/Config.in"
+endef
+
+CONFIGURE_ARGS += \
+ ARCH=$(LINUX_KARCH) \
+ --enable-linux-26 \
+ --enable-kernelbuild="$(LINUX_DIR)" \
+ --enable-kernelincl="$(LINUX_DIR)/include" \
+ --with-ifxos-incl=$(STAGING_DIR)/usr/include/ifxos \
+ $(call autoconf_bool,CONFIG_IFX_DRV_TAPI_EVENT_LOGGER,el-debug) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_FAX,fax t38) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_CID,cid) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_DECT,dect) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_KPI,kpi) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_QOS,qos) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_LT_GR909,lt) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_STATISTICS,statistics) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_METERING,metering) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_HDLC,hdlc) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_TRACES,trace) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_LINUX_HOTPLUG,hotplug)
+
+define Build/Configure
+ (cd $(PKG_BUILD_DIR); aclocal && autoconf && automake)
+ $(call Build/Configure/Default)
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include/drv_tapi
+ $(CP) --dereference $(PKG_BUILD_DIR)/include/* $(1)/usr/include/drv_tapi
+ (cd $(1)/usr/include/drv_tapi && ln -s . include && ln -s ../ifxos/ifx_types.h .)
+endef
+
+$(eval $(call KernelPackage,ltq-tapi))
diff --git a/package/ltq-tapi/patches/000-portability.patch b/package/ltq-tapi/patches/000-portability.patch
new file mode 100644
index 000000000..78fcbad66
--- /dev/null
+++ b/package/ltq-tapi/patches/000-portability.patch
@@ -0,0 +1,82 @@
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -154,7 +154,7 @@ if KERNEL_2_6
+ drv_tapi_OBJS = "$(subst .c,.o, $(drv_tapi_SOURCES))"
+
+ drv_tapi.ko: $(drv_tapi_SOURCES) $(EXTRA_DIST)
+- @echo -e "Making Linux 2.6.x kernel object"
++ @echo "Making Linux 2.6.x kernel object"
+ @for f in $(drv_tapi_SOURCES) ; do \
+ if test ! -e $(PWD)/$$f; then \
+ echo " LN $$f" ; \
+@@ -162,10 +162,10 @@ drv_tapi.ko: $(drv_tapi_SOURCES) $(EXTRA
+ ln -s @abs_srcdir@/$$f $(PWD)/$$f; \
+ fi; \
+ done;
+- @echo -e "# drv_tapi: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild
+- @echo -e "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild
+- @echo -e "$(subst .ko,,$@)-y := $(drv_tapi_OBJS)" >> $(PWD)/Kbuild
+- @echo -e "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(CFLAGS) $(drv_tapi_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild
++ @echo "# drv_tapi: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild
++ @echo "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild
++ @echo "$(subst .ko,,$@)-y := $(drv_tapi_OBJS)" >> $(PWD)/Kbuild
++ @echo "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(CFLAGS) $(drv_tapi_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild
+ $(MAKE) ARCH=@KERNEL_ARCH@ -C @KERNEL_BUILD_PATH@ O=@KERNEL_BUILD_PATH@ M=$(PWD) modules
+
+ clean-generic:
+--- a/configure.in
++++ b/configure.in
+@@ -128,7 +128,7 @@ dnl Set kernel build path
+ AC_ARG_ENABLE(kernelbuild,
+ AS_HELP_STRING(--enable-kernelbuild=x,Set the target kernel build path),
+ [
+- if test -r $enableval/include/linux/autoconf.h; then
++ if test -e $enableval/include/linux/autoconf.h -o -e $enableval/include/generated/autoconf.h; then
+ AC_SUBST([KERNEL_BUILD_PATH],[$enableval])
+ else
+ AC_MSG_ERROR([The kernel build directory is not valid or not configured!])
+--- a/src/drv_tapi_linux.h
++++ b/src/drv_tapi_linux.h
+@@ -24,6 +24,7 @@
+ #include <linux/version.h>
+ #include <linux/interrupt.h> /* in_interrupt() */
+ #include <linux/delay.h> /* mdelay - udelay */
++#include <linux/workqueue.h> /* work_struct */
+ #include <asm/poll.h> /* POLLIN, POLLOUT */
+
+ #include "ifx_types.h" /* ifx type definitions */
+--- a/src/drv_tapi_linux.c
++++ b/src/drv_tapi_linux.c
+@@ -47,6 +47,7 @@
+ #include <linux/errno.h>
+ #include <asm/uaccess.h> /* copy_from_user(), ... */
+ #include <asm/byteorder.h>
++#include <linux/smp_lock.h> /* lock_kernel() */
+ #include <asm/io.h>
+
+ #ifdef LINUX_2_6
+@@ -55,7 +56,11 @@
+ #include <linux/sched.h>
+ #undef CONFIG_DEVFS_FS
+ #ifndef UTS_RELEASE
+- #include "linux/utsrelease.h"
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
++# include <linux/utsrelease.h>
++#else
++# include <generated/utsrelease.h>
++#endif
+ #endif /* UTC_RELEASE */
+ #else
+ #include <linux/tqueue.h>
+@@ -3718,7 +3723,11 @@ IFX_void_t TAPI_OS_ThreadKill(IFXOS_Thre
+ flag and released after the down() call. */
+ lock_kernel();
+ mb();
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+ kill_proc(pThrCntrl->tid, SIGKILL, 1);
++#else
++ kill_pid(find_vpid(pThrCntrl->tid), SIGKILL, 1);
++#endif
+ /* release the big kernel lock */
+ unlock_kernel();
+ wait_for_completion (&pThrCntrl->thrCompletion);
diff --git a/package/ltq-tapi/patches/100-ifxmips.patch b/package/ltq-tapi/patches/100-ifxmips.patch
new file mode 100644
index 000000000..a9c0d8116
--- /dev/null
+++ b/package/ltq-tapi/patches/100-ifxmips.patch
@@ -0,0 +1,96 @@
+--- a/src/drv_tapi_linux.c
++++ b/src/drv_tapi_linux.c
+@@ -552,7 +552,7 @@ static ssize_t ifx_tapi_write (struct fi
+ IFX_uint8_t *pData;
+ IFX_size_t buf_size;
+ #endif /* TAPI_PACKET */
+- IFX_ssize_t size = 0;
++ ssize_t size = 0;
+
+ #ifdef TAPI_PACKET
+ if (pTapiDev->bInitialized == IFX_FALSE)
+--- a/src/drv_tapi_osmap.h
++++ b/src/drv_tapi_osmap.h
+@@ -17,39 +17,6 @@
+ */
+
+ #include "ifx_types.h" /* ifx type definitions */
+-
+-#ifndef HAVE_IFX_ULONG_T
+- #warning please update your ifx_types.h, using local definition of IFX_ulong_t
+- /* unsigned long type - valid for 32bit systems only */
+- typedef unsigned long IFX_ulong_t;
+- #define HAVE_IFX_ULONG_T
+-#endif /* HAVE_IFX_ULONG_T */
+-
+-#ifndef HAVE_IFX_LONG_T
+- #warning please update your ifx_types.h, using local definition of IFX_long_t
+- /* long type - valid for 32bit systems only */
+- typedef long IFX_long_t;
+- #define HAVE_IFX_LONG_T
+-#endif /* HAVE_IFX_LONG_T */
+-
+-#ifndef HAVE_IFX_INTPTR_T
+- #warning please update your ifx_types.h, using local definition of IFX_intptr_t
+- typedef IFX_long_t IFX_intptr_t;
+- #define HAVE_IFX_INTPTR_T
+-#endif /* HAVE_IFX_INTPTR_T */
+-
+-#ifndef HAVE_IFX_SIZE_T
+- #warning please update your ifx_types.h, using local definition of IFX_size_t
+- typedef IFX_ulong_t IFX_size_t;
+- #define HAVE_IFX_SIZE_T
+-#endif /* HAVE_IFX_SIZE_T */
+-
+-#ifndef HAVE_IFX_SSIZE_T
+- #warning please update your ifx_types.h, using local definition of IFX_ssize_t
+- typedef IFX_long_t IFX_ssize_t;
+- #define HAVE_IFX_SSIZE_T
+-#endif /* HAVE_IFX_SSIZE_T */
+-
+ #include "ifxos_interrupt.h"
+ #include "ifxos_memory_alloc.h"
+ #include "ifxos_copy_user_space.h"
+--- a/include/drv_tapi_ll_interface.h
++++ b/include/drv_tapi_ll_interface.h
+@@ -40,13 +40,6 @@
+ #include "ifxos_select.h"
+ #endif /* TAPI_PACKET */
+
+-#ifndef HAVE_IFX_ULONG_T
+- #warning please update your ifx_types.h, using local definition of IFX_ulong_t
+- /* unsigned long type - valid for 32bit systems only */
+- typedef unsigned long IFX_ulong_t;
+- #define HAVE_IFX_ULONG_T
+-#endif /* HAVE_IFX_ULONG_T */
+-
+ /* ============================= */
+ /* Local Macros Definitions */
+ /* ============================= */
+--- a/src/lib/lib_bufferpool/lib_bufferpool.c
++++ b/src/lib/lib_bufferpool/lib_bufferpool.c
+@@ -85,24 +85,6 @@
+ #include <stdlib.h>
+ #endif /*VXWORKS*/
+
+-
+-/* ============================= */
+-/* Extra type definitions */
+-/* ============================= */
+-#ifndef HAVE_IFX_ULONG_T
+- #warning please update your ifx_types.h, using local definition of IFX_ulong_t
+- /* unsigned long type - valid for 32bit systems only */
+- typedef unsigned long IFX_ulong_t;
+- #define HAVE_IFX_ULONG_T
+-#endif /* HAVE_IFX_ULONG_T */
+-
+-#ifndef HAVE_IFX_UINTPTR_T
+- #warning please update your ifx_types.h, using local definition of IFX_uintptr_t
+- typedef IFX_ulong_t IFX_uintptr_t;
+- #define HAVE_IFX_UINTPTR_T
+-#endif /* HAVE_IFX_UINTPTR_T */
+-
+-
+ /* ============================= */
+ /* Local Macros & Definitions */
+ /* ============================= */
diff --git a/package/ltq-tapi/patches/200-linux-37.patch b/package/ltq-tapi/patches/200-linux-37.patch
new file mode 100644
index 000000000..9d7428df0
--- /dev/null
+++ b/package/ltq-tapi/patches/200-linux-37.patch
@@ -0,0 +1,108 @@
+--- a/src/drv_tapi_linux.c
++++ b/src/drv_tapi_linux.c
+@@ -47,7 +47,9 @@
+ #include <linux/errno.h>
+ #include <asm/uaccess.h> /* copy_from_user(), ... */
+ #include <asm/byteorder.h>
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
+ #include <linux/smp_lock.h> /* lock_kernel() */
++#endif
+ #include <asm/io.h>
+
+ #ifdef LINUX_2_6
+@@ -65,7 +67,9 @@
+ #else
+ #include <linux/tqueue.h>
+ #include <linux/sched.h>
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
+ #include <linux/smp_lock.h> /* lock_kernel() */
++#endif
+ #endif /* LINUX_2_6 */
+
+ #include "drv_tapi.h"
+@@ -133,8 +137,13 @@
+ size_t count, loff_t * ppos);
+ static ssize_t ifx_tapi_read(struct file * filp, char *buf,
+ size_t length, loff_t * ppos);
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
+ static int ifx_tapi_ioctl(struct inode *inode, struct file *filp,
+ unsigned int nCmd, unsigned long nArgument);
++#else
++static long ifx_tapi_ioctl(struct file *filp,
++ unsigned int nCmd, unsigned long nArgument);
++#endif
+ static unsigned int ifx_tapi_poll (struct file *filp, poll_table *table);
+
+ #ifdef CONFIG_PROC_FS
+@@ -218,7 +227,11 @@
+ IFX_char_t *pRegDrvName = IFX_NULL;
+ IFX_int32_t ret = 0;
+
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
+ if (tapi_fops.ioctl == IFX_NULL)
++#else
++ if (tapi_fops.unlocked_ioctl == IFX_NULL)
++#endif
+ {
+ #ifdef MODULE
+ tapi_fops.owner = THIS_MODULE;
+@@ -226,7 +239,11 @@
+ tapi_fops.read = ifx_tapi_read;
+ tapi_fops.write = ifx_tapi_write;
+ tapi_fops.poll = ifx_tapi_poll;
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
+ tapi_fops.ioctl = ifx_tapi_ioctl;
++#else
++ tapi_fops.unlocked_ioctl = ifx_tapi_ioctl;
++#endif
+ tapi_fops.open = ifx_tapi_open;
+ tapi_fops.release = ifx_tapi_release;
+ }
+@@ -881,8 +898,13 @@
+ - 0 and positive values - success
+ - negative value - ioctl failed
+ */
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
+ static int ifx_tapi_ioctl(struct inode *inode, struct file *filp,
+ unsigned int nCmd, unsigned long nArg)
++#else
++static long ifx_tapi_ioctl(struct file *filp,
++ unsigned int nCmd, unsigned long nArg)
++#endif
+ {
+ TAPI_FD_PRIV_DATA_t *pTapiPriv;
+ IFX_TAPI_ioctlCtx_t ctx;
+@@ -3721,7 +3743,9 @@
+ kernel lock (lock_kernel()). The lock must be
+ grabbed before changing the terminate
+ flag and released after the down() call. */
+- lock_kernel();
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
++ lock_kernel();
++#endif
+ mb();
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+ kill_proc(pThrCntrl->tid, SIGKILL, 1);
+@@ -3729,8 +3753,10 @@
+ kill_pid(find_vpid(pThrCntrl->tid), SIGKILL, 1);
+ #endif
+ /* release the big kernel lock */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
+ unlock_kernel();
+- wait_for_completion (&pThrCntrl->thrCompletion);
++#endif
++ wait_for_completion (&pThrCntrl->thrCompletion);
+
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+ /* Now we are sure the thread is in zombie state.
+--- a/src/lib/lib_fifo/lib_fifo.c
++++ b/src/lib/lib_fifo/lib_fifo.c
+@@ -41,7 +41,7 @@
+ #ifdef LINUX
+ /* if linux/slab.h is not available, use the precessor linux/malloc.h */
+ #include <linux/slab.h>
+-#elif VXWORKS
++#elif defined(VXWORKS)
+ #include <sys_drv_debug.h>
+ #endif /* LINUX */
+
diff --git a/package/ltq-tapidemo/Config.in b/package/ltq-tapidemo/Config.in
new file mode 100644
index 000000000..a799eddd0
--- /dev/null
+++ b/package/ltq-tapidemo/Config.in
@@ -0,0 +1,47 @@
+choice
+ prompt "board selection"
+ depends on PACKAGE_ltq-tapidemo
+ default VOICE_CPE_TAPIDEMO_BOARD_EASY50712_V3 if TARGET_lantiq_danube
+ default VOICE_CPE_TAPIDEMO_BOARD_EASY508xx if TARGET_lantiq_ar9
+ default VOICE_CPE_TAPIDEMO_BOARD_EASY80910 if TARGET_lantiq_vr9
+ help
+ Select the target platform.
+
+ config VOICE_CPE_TAPIDEMO_BOARD_EASY50712
+ bool "Danube reference board"
+
+ config VOICE_CPE_TAPIDEMO_BOARD_EASY50712_V3
+ bool "Danube reference board V3"
+
+ config VOICE_CPE_TAPIDEMO_BOARD_EASY508xx
+ bool "AR9/GR9 reference board"
+
+ config VOICE_CPE_TAPIDEMO_BOARD_EASY80910
+ bool "VR9 reference board"
+endchoice
+
+config VOICE_CPE_TAPIDEMO_QOS
+ bool "enable QOS support"
+ depends on PACKAGE_ltq-tapidemo
+ select PACKAGE_kmod-ltq-kpi2udp
+ default y
+ help
+ Option to enable the KPI2UDP RTP packet acceleration path
+ (highly recommended for VoIP).
+
+config VOICE_CPE_TAPIDEMO_FAX_T.38_FW
+ bool "enable T.38 fax relay"
+ depends on (TARGET_lantiq_ar9 || TARGET_lantiq_vr9) && PACKAGE_ltq-tapidemo
+ default n
+ help
+ enable T.38 fax relay demo.
+
+config VOICE_CPE_TAPIDEMO_FW_FILE
+ string "override default firmware file"
+ depends on PACKAGE_ltq-tapidemo
+ default "falcon_voip_fw.bin" if TARGET_lantiq_falcon
+
+config VOICE_CPE_TAPIDEMO_BBD_FILE
+ string "override default coefficient file"
+ depends on PACKAGE_ltq-tapidemo
+ default "falcon_bbd.bin" if TARGET_lantiq_falcon
diff --git a/package/ltq-tapidemo/Makefile b/package/ltq-tapidemo/Makefile
new file mode 100644
index 000000000..f4ac64601
--- /dev/null
+++ b/package/ltq-tapidemo/Makefile
@@ -0,0 +1,82 @@
+#
+# Copyright (C) 2008-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=tapidemo
+PKG_VERSION:=5.1.0.53
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
+PKG_MD5SUM:=c970becc46b2935fb9e18f795d4e8469
+
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/ltqtapi.mk
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ltq-tapidemo
+ SUBMENU:=Telephony
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=TAPIdemo application for Lantiq boards
+ URL:=http://www.lantiq.com/
+ DEPENDS:=$(LTQ_TAPI_DEPENDS) +libpthread
+ MAINTAINER:=John Crispin <blogic@openwrt.org>
+ MENU:=1
+endef
+
+define Package/ltq-tapidemo/description
+ Voice Access mini-PBX Demo Application
+endef
+
+define Package/ltq-tapidemo/config
+ source "$(SOURCE)/Config.in"
+endef
+
+TARGET_LDFLAGS+=-lpthread
+
+CONFIGURE_ARGS += \
+ ARCH=$(LINUX_KARCH) \
+ --enable-linux-26 \
+ --enable-kernelincl="$(LINUX_DIR)/include" \
+ --with-drvincl="$(STAGING_DIR)/usr/include" \
+ --with-ifxos-incl=$(STAGING_DIR)/usr/include/ifxos \
+ --with-ifxos-lib=$(STAGING_DIR)/usr/lib \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_QOS,qos) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPIDEMO_FAX_T,fax-t38) \
+ --enable-trace \
+ --enable-fs
+
+ifeq ($(CONFIG_VOICE_CPE_TAPIDEMO_BOARD_EASY50712),y)
+ CONFIGURE_ARGS += --enable-boardname=EASY50712
+endif
+ifeq ($(CONFIG_VOICE_CPE_TAPIDEMO_BOARD_EASY50712_V3),y)
+ CONFIGURE_ARGS += --enable-boardname=EASY50712_V3
+endif
+ifeq ($(CONFIG_VOICE_CPE_TAPIDEMO_BOARD_EASY508xx),y)
+ CONFIGURE_ARGS += --enable-boardname=EASY508XX
+endif
+ifeq ($(CONFIG_VOICE_CPE_TAPIDEMO_BOARD_EASY80910),y)
+ CONFIGURE_ARGS += --enable-boardname=EASY508XX
+endif
+ifneq ($(CONFIG_VOICE_CPE_TAPIDEMO_FW_FILE),)
+ CONFIGURE_ARGS += --with-fw-file="$(strip $(subst ",, $(CONFIG_VOICE_CPE_TAPIDEMO_FW_FILE)))"
+endif
+ifneq ($(CONFIG_VOICE_CPE_TAPIDEMO_BBD_FILE), "")
+CONFIGURE_ARGS += --with-bbd-file="$(strip $(subst ",, $(CONFIG_VOICE_CPE_TAPIDEMO_BBD_FILE)))"
+endif
+
+define Package/ltq-tapidemo/install
+ $(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/init.d/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/tapidemo $(1)/usr/sbin
+ $(INSTALL_BIN) ./files/bringup_tapidemo $(1)/etc/init.d/tapidemo
+endef
+
+$(eval $(call BuildPackage,ltq-tapidemo))
diff --git a/package/ltq-tapidemo/files/bringup_tapidemo b/package/ltq-tapidemo/files/bringup_tapidemo
new file mode 100644
index 000000000..6eb13d25f
--- /dev/null
+++ b/package/ltq-tapidemo/files/bringup_tapidemo
@@ -0,0 +1,89 @@
+#!/bin/sh /etc/rc.common
+# (C) 2008 openwrt.org
+
+START=96
+
+[ ! -f /dev/vmmc10 ] && {
+ mknod /dev/vmmc10 c 122 10
+ mknod /dev/vmmc11 c 122 11
+ mknod /dev/vmmc12 c 122 12
+ mknod /dev/vmmc13 c 122 13
+ mknod /dev/vmmc14 c 122 14
+ mknod /dev/vmmc15 c 122 15
+ mknod /dev/vmmc16 c 122 16
+ mknod /dev/vmmc17 c 122 17
+ mknod /dev/vmmc18 c 122 18
+}
+
+TD_EXTRA_FLAGS_FXO=
+TD_EXTRA_FLAGS_KPI2UDP=
+TD_DOWNLOAD_PATH=/lib/firmware/
+DEV_NODE_TERIDIAN=ter10
+
+ # Show help
+help()
+{
+ echo "Usage:"
+ echo " - $0 WAN-IF-NAME - start TAPIDEMO without FXO support"
+ echo " - $0 WAN-IF-NAME fxo - start TAPIDEMO with FXO support."
+ echo " - $0 stop - stop TAPIDEMO"
+}
+
+# Check if device node for Teridian exists
+checkFxoSupport()
+{
+ if [ ! -e /dev/$DEV_NODE_TERIDIAN ];then
+ echo "FXO support is disabled. Can not find required driver's device node."
+ else
+ TD_EXTRA_FLAGS_FXO="-x"
+ fi
+}
+
+# Check if module drv_kpi2udp is loaded
+checkKpi2UdpSupport()
+{
+ tmp=`cat /proc/modules | grep 'drv_kpi2udp '`
+ if [ "$tmp" != "" ]; then
+ TD_EXTRA_FLAGS_KPI2UDP="-q"
+ fi
+}
+
+start()
+{
+ TD_WANIF=$1
+
+ TD_WANIF_IP=`ifconfig $TD_WANIF | grep 'inet addr:' | cut -f2 -d: | cut -f1 -d' '`
+ if [ "$TD_WANIF_IP" = "" ]; then
+ echo "Error, getting IP address for network device $TD_WANIF failed."
+ exit 1
+ fi
+
+ if [ "$2" = "" ];then
+ # FXO support is disabled.
+ continue
+ elif [ "$2" = "fxo" ];then
+ checkFxoSupport
+ else
+ echo "Error, unknown second parameter."
+ help
+ exit 1
+ fi
+
+ checkKpi2UdpSupport
+
+ if [ -r /etc/rc.conf ]; then
+ . /etc/rc.conf
+ fi
+
+ TD_DEBUG_LEVEL=$tapiDebugLevel
+ if [ "$TD_DEBUG_LEVEL" = "" ]; then
+ TD_DEBUG_LEVEL=3
+ fi
+
+ /usr/sbin/tapidemo -d $TD_DEBUG_LEVEL $TD_EXTRA_FLAGS_FXO $TD_EXTRA_FLAGS_KPI2UDP -i $TD_WANIF_IP -l $TD_DOWNLOAD_PATH &
+}
+
+stop()
+{
+ killall tapidemo > /dev/null 2> /dev/null
+}
diff --git a/package/ltq-tapidemo/patches/100-ifxmips.patch b/package/ltq-tapidemo/patches/100-ifxmips.patch
new file mode 100644
index 000000000..3dde8304f
--- /dev/null
+++ b/package/ltq-tapidemo/patches/100-ifxmips.patch
@@ -0,0 +1,61 @@
+--- a/src/board_easy50712.c
++++ b/src/board_easy50712.c
+@@ -32,7 +32,9 @@
+ #ifdef OLD_BSP
+ #include "asm/danube/port.h"
+ #else
+- #include "asm/ifx/ifx_gpio.h"
++#ifdef FXO
++# include "asm/ifx/ifx_gpio.h"
++#endif
+ #endif
+
+ /* ============================= */
+--- a/src/board_easy508xx.c
++++ b/src/board_easy508xx.c
+@@ -32,8 +32,6 @@
+ #endif /* FXO */
+ #include "pcm.h"
+
+-#include "asm/ifx/ifx_gpio.h"
+-
+ #ifdef TD_DECT
+ #include "td_dect.h"
+ #endif /* TD_DECT */
+--- a/src/common.c
++++ b/src/common.c
+@@ -7117,7 +7117,7 @@ IFX_return_t Common_GPIO_ClosePort(IFX_c
+ IFX_return_t Common_GPIO_ReservePin(IFX_int32_t nFd, IFX_int32_t nPort,
+ IFX_int32_t nPin, IFX_int32_t nModule)
+ {
+-#ifndef OLD_BSP
++#if !defined(OLD_BSP) && defined(IFX_GPIO_IOC_PIN_RESERVE)
+ TD_PARAMETER_CHECK((NO_GPIO_FD >= nFd), nFd, IFX_ERROR);
+
+ IFX_return_t nRet;
+@@ -7155,7 +7155,7 @@ IFX_return_t Common_GPIO_ReservePin(IFX_
+ IFX_return_t Common_GPIO_FreePin(IFX_int32_t nFd, IFX_int32_t nPort,
+ IFX_int32_t nPin, IFX_int32_t nModule)
+ {
+-#ifndef OLD_BSP
++#if !defined(OLD_BSP) && defined(IFX_GPIO_IOC_PIN_RESERVE)
+ TD_PARAMETER_CHECK((NO_GPIO_FD >= nFd), nFd, IFX_ERROR);
+
+ IFX_return_t nRet;
+--- a/src/common.h
++++ b/src/common.h
+@@ -79,12 +79,12 @@
+ #ifdef OLD_BSP
+ #include "asm/danube/port.h"
+ #else
+- #include "asm/ifx/ifx_gpio.h"
++ /*#include "asm/ifx/ifx_gpio.h"*/
+ #endif
+ #endif
+
+ #if (defined(AR9) || defined(VR9))
+- #include "asm/ifx/ifx_gpio.h"
++ /*#include "asm/ifx/ifx_gpio.h"*/
+ #endif
+
+ #ifdef TD_DECT
diff --git a/package/ltq-tapidemo/patches/110-filename.patch b/package/ltq-tapidemo/patches/110-filename.patch
new file mode 100644
index 000000000..73c2e977b
--- /dev/null
+++ b/package/ltq-tapidemo/patches/110-filename.patch
@@ -0,0 +1,141 @@
+--- a/configure.in
++++ b/configure.in
+@@ -1665,6 +1665,30 @@ AC_ARG_WITH(cflags,
+ ]
+ )
+
++dnl overwrite default FW file name
++AC_ARG_WITH(fw-file,
++ AS_HELP_STRING(
++ [--with-fw-file=val],
++ [overwrite default FW file name]
++ ),
++ [
++ AC_MSG_RESULT([using firmware file $withval])
++ AC_DEFINE_UNQUOTED([TD_FW_FILE], ["$withval"], [using firmware file])
++ ]
++)
++
++dnl overwrite default BBD file name
++AC_ARG_WITH(bbd-file,
++ AS_HELP_STRING(
++ [--with-bbd-file=val],
++ [overwrite default BBD file name]
++ ),
++ [
++ AC_MSG_RESULT([using BBD file $withval])
++ AC_DEFINE_UNQUOTED([TD_BBD_FILE], ["$withval"], [using BBD file])
++ ]
++)
++
+ AC_CONFIG_FILES([Makefile])
+ AC_CONFIG_FILES([src/Makefile])
+
+--- a/src/device_vmmc.c
++++ b/src/device_vmmc.c
+@@ -49,40 +49,55 @@
+
+
+ #ifdef USE_FILESYSTEM
++#ifdef TD_BBD_FILE
++ IFX_char_t* sBBD_CRAM_File_VMMC = TD_BBD_FILE;
++ IFX_char_t* sBBD_CRAM_File_VMMC_Old = TD_BBD_FILE;
++#else
++ /** File holding coefficients. */
++#ifdef DANUBE
++ /** Prepare file names for DANUBE */
++ IFX_char_t* sBBD_CRAM_File_VMMC = "danube_bbd.bin";
++ IFX_char_t* sBBD_CRAM_File_VMMC_Old = "danube_bbd_fxs.bin";
++#elif AR9
++ IFX_char_t* sBBD_CRAM_File_VMMC = "ar9_bbd.bin";
++ IFX_char_t* sBBD_CRAM_File_VMMC_Old = "ar9_bbd_fxs.bin";
++#elif VINAX
++ IFX_char_t* sBBD_CRAM_File_VMMC = "bbd.bin";
++ IFX_char_t* sBBD_CRAM_File_VMMC_Old = "";
++#elif VR9
++ IFX_char_t* sBBD_CRAM_File_VMMC = "vr9_bbd.bin";
++ IFX_char_t* sBBD_CRAM_File_VMMC_Old = "vr9_bbd_fxs.bin";
++#else
++#endif
++#endif /* TD_BBD_FILE */
++#ifdef TD_FW_FILE
++ IFX_char_t* sPRAMFile_VMMC = TD_FW_FILE;
++ IFX_char_t* sPRAMFile_VMMC_Old = TD_FW_FILE;
++ IFX_char_t* sDRAMFile_VMMC = "";
++#else
+ #ifdef DANUBE
+ /** Prepare file names for DANUBE */
+ IFX_char_t* sPRAMFile_VMMC = "voice_danube_firmware.bin";
+ IFX_char_t* sPRAMFile_VMMC_Old = "danube_firmware.bin";
+ IFX_char_t* sDRAMFile_VMMC = "";
+- /** File holding coefficients. */
+- IFX_char_t* sBBD_CRAM_File_VMMC = "danube_bbd.bin";
+- IFX_char_t* sBBD_CRAM_File_VMMC_Old = "danube_bbd_fxs.bin";
+ #elif AR9
+ /** Prepare file names for AR9 */
+ IFX_char_t* sPRAMFile_VMMC = "voice_ar9_firmware.bin";
+ IFX_char_t* sPRAMFile_VMMC_Old = "ar9_firmware.bin";
+ IFX_char_t* sDRAMFile_VMMC = "";
+- /** File holding coefficients. */
+- IFX_char_t* sBBD_CRAM_File_VMMC = "ar9_bbd.bin";
+- IFX_char_t* sBBD_CRAM_File_VMMC_Old = "ar9_bbd_fxs.bin";
+ #elif VINAX
+ /** Prepare file names for VINAX */
+ IFX_char_t* sPRAMFile_VMMC = "voice_vinax_firmware.bin";
+ IFX_char_t* sPRAMFile_VMMC_Old = "firmware.bin";
+ IFX_char_t* sDRAMFile_VMMC = "";
+- /** File holding coefficients. */
+- IFX_char_t* sBBD_CRAM_File_VMMC = "bbd.bin";
+- IFX_char_t* sBBD_CRAM_File_VMMC_Old = "";
+ #elif VR9
+ /** Prepare file names for VR9 */
+ IFX_char_t* sPRAMFile_VMMC = "voice_vr9_firmware.bin";
+ IFX_char_t* sPRAMFile_VMMC_Old = "vr9_firmware.bin";
+ IFX_char_t* sDRAMFile_VMMC = "";
+- /** File holding coefficients. */
+- IFX_char_t* sBBD_CRAM_File_VMMC = "vr9_bbd.bin";
+- IFX_char_t* sBBD_CRAM_File_VMMC_Old = "vr9_bbd_fxs.bin";
+ #else
+ #endif
++#endif /* TD_FW_FILE */
+ #endif /* USE_FILESYSTEM */
+
+ /** Device names */
+--- a/src/common.c
++++ b/src/common.c
+@@ -509,6 +509,10 @@ IFX_return_t Common_CheckDownloadPath(IF
+ if (IFX_TRUE != Common_FindBBD_CRAM(pCpuDevice, psPath, psFile))
+ {
+ ret = IFX_ERROR;
++ if(bPrintTrace)
++ TRACE(TAPIDEMO, DBG_LEVEL_LOW,
++ ("Download path %s does not contain the required file %s.\n",
++ psPath, psFile));
+ }
+
+ if ((IFX_SUCCESS == ret) &&
+@@ -521,6 +525,10 @@ IFX_return_t Common_CheckDownloadPath(IF
+ {
+ ret = Common_CheckFileExists(psFile);
+ }
++ if(bPrintTrace && ret != IFX_SUCCESS)
++ TRACE(TAPIDEMO, DBG_LEVEL_LOW,
++ ("Download path %s does not contain the required file %s.\n",
++ psPath, psFile));
+ }
+ #ifndef TAPI_VERSION4
+ if (IFX_SUCCESS == ret)
+@@ -532,13 +540,6 @@ IFX_return_t Common_CheckDownloadPath(IF
+ }
+ #endif
+
+- if (IFX_ERROR == ret)
+- {
+- if(bPrintTrace)
+- TRACE(TAPIDEMO, DBG_LEVEL_LOW,
+- ("Download path %s does not contain the required files.\n",
+- psPath));
+- }
+
+ return ret;
+ } /* Common_CheckDownloadPath */
diff --git a/package/ltq-vmmc/Config.in b/package/ltq-vmmc/Config.in
new file mode 100644
index 000000000..3a5e0145c
--- /dev/null
+++ b/package/ltq-vmmc/Config.in
@@ -0,0 +1,95 @@
+choice
+ prompt "device selection"
+ depends on PACKAGE_kmod-ltq-vmmc
+ default VOICE_CPE_VMMC_WITH_DEVICE_DANUBE
+ help
+ Select the target device.
+
+ config VOICE_CPE_VMMC_WITH_DEVICE_DANUBE
+ bool "Danube, Twinpass, Vinax"
+ depends on TARGET_lantiq_danube
+
+ config VOICE_CPE_VMMC_WITH_DEVICE_AR9
+ bool "AR9 family"
+ depends on TARGET_lantiq_ar9
+
+ config VOICE_CPE_VMMC_WITH_DEVICE_VR9
+ bool "VR9 family"
+ depends on TARGET_lantiq_vr9
+
+ config VOICE_VMMC_WITH_DEVICE_FALCON
+ bool "FALC-ON"
+ depends on (TARGET_lantiq_falcon||TARGET_lantiq_falcon_stable)
+
+endchoice
+
+choice
+ depends on PACKAGE_kmod-ltq-vmmc
+ prompt "FXS coefficients"
+ default LTQ_VOICE_CPE_VMMC_COEF_FALCON_ETSI
+ help
+ Select country specific FXS coefficient file.
+
+ config LTQ_VOICE_CPE_VMMC_COEF_FALCON_ETSI
+ bool "ETSI_T3R10: Vl:40V, Ic:25mA, Vid:25V, Vri:45Vrms, f:25Hz"
+ help
+ These coefficents contains a parameter set with line impedance Zr according to ETSI.
+
+ T: gain in transmit direction (attenuation 3dBr) [dBr]
+ R: gain in receive direction (attenuation 10dBr) [dBr]
+ Vl: on-hook voltage limit [V]
+ Ic: off-hook loop current [mA]
+ Vid: low-power-standby voltage [V]
+ Vri: ring voltage [v]
+ f: ring frequency [V]
+
+ config LTQ_VOICE_CPE_VMMC_COEF_FALCON_US600R
+ bool "USA_600R_T3R10: Vl:40V, Ic:25mA, Vid:25V, Vri:45V, f:20Hz"
+ help
+ These coefficents contains a parameter set with line impedance e.g. for USA.
+
+ T: gain in transmit direction (attenuation 3dBr) [dBr]
+ R: gain in receive direction (attenuation 10dBr) [dBr]
+ Vl: on-hook voltage limit [V]
+ Ic: off-hook loop current [mA]
+ Vid: low-power-standby voltage [V]
+ Vri: ring voltage [v]
+ f: ring frequency [V]
+
+ config LTQ_VOICE_CPE_VMMC_COEF_FALCON_USE_CUSTOM_FILE
+ bool "Select own FXS coefficient file"
+endchoice
+
+config VOICE_CPE_VMMC_PMC
+ depends on (VOICE_CPE_VMMC_WITH_DEVICE_AR9 || VOICE_CPE_VMMC_WITH_DEVICE_VR9)
+ bool "Power Management Control support"
+ default n
+ help
+ Option to enable Power Management Control on AR9, VR9. Not supported for Danube.
+
+config VOICE_CPE_VMMC_DISABLE_DECT_NIBBLE_SWAP
+ bool "Disable DECT nibble swap"
+ depends on PACKAGE_kmod-ltq-vmmc
+ default n
+ help
+ Option to disable DECT nibble swap for COSIC modem (for backward compatibility only).
+
+config VOICE_CPE_VMMC_EVENT_LOGGER
+ depends on BROKEN
+ bool "Event logger support"
+ depends on PACKAGE_kmod-ltq-vmmc
+ default n
+ help
+ Option to enable details traces between drv_vmmc and the voice FW
+ - for debugging only
+ - requires package ifx-evtlog
+
+config VOICE_CPE_VMMC_MPS_HISTORY_SIZE
+ int "MPS history buffer in words (0<=size<=512)"
+ depends on PACKAGE_kmod-ltq-vmmc
+ default "128"
+ help
+ MPS history buffer (default=128 words, maximum=512 words, 0=disable)
+ To opimize the memory footprint in RAM, you might want to set the
+ buffer size to 0.
+
diff --git a/package/ltq-vmmc/Makefile b/package/ltq-vmmc/Makefile
new file mode 100644
index 000000000..98b5df0ec
--- /dev/null
+++ b/package/ltq-vmmc/Makefile
@@ -0,0 +1,166 @@
+#
+# Copyright (C) 2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=drv_vmmc
+PKG_VERSION:=1.9.0
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_MD5SUM:=d8eee8cba0edb28974cc1f8532e3bd18
+PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
+
+include $(INCLUDE_DIR)/ltqtapi.mk
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/ltq-vmmc
+ SUBMENU:=Voice over IP
+ TITLE:=TAPI LL driver for Voice Macro
+ URL:=http://www.lantiq.com/
+ DEPENDS:=$(LTQ_TAPI_TARGET) +kmod-ltq-tapi
+ FILES:=$(PKG_BUILD_DIR)/src/drv_vmmc.ko
+ AUTOLOAD:=$(call AutoLoad,25,drv_vmmc)
+ MAINTAINER:=John Crispin <blogic@openwrt.org>
+endef
+
+define KernelPackage/ltq-vmmc/description
+ Voice Subsystem Low Level Driver for Danube, AR9, VR9 device families
+endef
+
+define KernelPackage/ltq-vmmc/config
+ source "$(SOURCE)/Config.in"
+endef
+
+CONFIGURE_ARGS += \
+ ARCH=$(LINUX_KARCH) \
+ --enable-linux-26 \
+ --enable-kernelbuild="$(LINUX_DIR)" \
+ --enable-kernelincl="$(LINUX_DIR)/include" \
+ --enable-tapiincl="$(STAGING_DIR)/usr/include/drv_tapi" \
+ --with-ifxos-incl=$(STAGING_DIR)/usr/include/ifxos \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_VMMC_EVENT_LOGGER,el-debug) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_VMMC_PMC,pmc) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_VMMC_DISABLE_DECT_NIBBLE_SWAP,dect-nibble-swap) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_FAX,fax t38) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_CID,cid) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_DECT,dect) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_KPI,kpi) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_LT_GR909,lt calibration) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_HDLC,hdlc) \
+ $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_TRACES,trace)
+
+ifneq ($(CONFIG_VOICE_CPE_VMMC_MPS_HISTORY_SIZE),128)
+ CONFIGURE_ARGS += --enable-history-buf=$(CONFIG_VOICE_CPE_VMMC_MPS_HISTORY_SIZE)
+endif
+
+#defaults
+FW_URL:=http://localhost/
+FW_TARGET:=ifx_firmware.bin
+FW_FILE:=fw_voip_ifx.tar.gz
+COEF_TARGET:=ifx_bbd_fxs.bin
+COEF_FILE:=coef_voip_ifx.tar.gz
+
+FW_DIR:=lib/firmware
+
+FW_TARGET_GENERIC:=$(FW_TARGET)
+COEF_TARGET_GENERIC:=$(COEF_TARGET)
+
+ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_DANUBE)$(CONFIG_LTQ_VOICE_CPE_VMMC_WITH_DEVICE_DANUBE),y)
+ CONFIGURE_ARGS += --with-device=DANUBE
+ FW_SOURCE:=voip_R12.1.0.1.0-enc.bin
+ FW_TARGET:=danube_firmware.bin
+ FW_FILE=fw_voip_danube-12.1.0.1.0.tar.gz
+ FW_MD5SUM:=51868b88dee9dbc65d3dbba355ded91c
+ FW_DOWNLOAD:=1
+ COEF_SRC:=danube_bbd_fxs.bin
+ COEF_TARGET:=danube_bbd_fxs.bin
+ COEF_FILE:=coef_voip_danube-0.9.0.tar.gz
+ COEF_MD5SUM:=c8ac6592b304b03829a8123560e15710
+ COEF_DOWNLOAD:=1
+endif
+
+ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_AR9),y)
+ CONFIGURE_ARGS += --with-device=AR9
+ # TODO: add fw/coef
+endif
+
+COEF_SRC:=$(COEF_TARGET)
+
+ifeq ($(CONFIG_VOICE_VMMC_WITH_DEVICE_FALCON),y)
+ CONFIGURE_ARGS += --with-device=FALCON
+ FW_SOURCE:=voip_R1.1.0.6.0-enc.bin
+ FW_MD5SUM:=cd4366a52a8010b76793e3810a4f14b3
+ FW_TARGET:=falcon_voip_fw.bin
+ FW_FILE=fw_voip_falcon-1.1.0.6.0.tar.gz
+ FW_DOWNLOAD:=1
+ COEF_TARGET:=falcon_bbd.bin
+# FXS part
+ifeq ($(CONFIG_LTQ_VOICE_CPE_VMMC_COEF_FALCON_ETSI),y)
+ COEF_SRC:=ETSI_3_10.BIN
+endif
+ifeq ($(CONFIG_LTQ_VOICE_CPE_VMMC_COEF_FALCON_US600R),y)
+ COEF_SRC:=R600_3_10.BIN
+endif
+ifeq ($(CONFIG_LTQ_VOICE_CPE_VMMC_COEF_FALCON_USE_CUSTOM_FILE),y)
+ COEF_SRC:=$(CONFIG_LTQ_VOICE_CPE_VMMC_COEF_FALCON_CUSTOM_FILE)
+endif
+ COEF_FILE:=coef_voip_falcon.tar.gz
+ COEF_MD5SUM:=56c5a838f2bb9bd87d0e8dce271f810b
+ COEF_DOWNLOAD:=1
+endif
+
+ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_VR9),y)
+ CONFIGURE_ARGS += --with-device=VR9
+ # TODO: add fw/coef
+endif
+
+define Download/firmware
+ FILE:=$(FW_FILE)
+ URL:=$(FW_URL)
+ MD5SUM:=$(FW_MD5SUM)
+endef
+$(eval $(if $(FW_DOWNLOAD),$(call Download,firmware)))
+
+define Download/coef
+ FILE:=$(COEF_FILE)
+ URL:=$(FW_URL)
+ MD5SUM:=$(COEF_MD5SUM)
+endef
+$(eval $(if $(COEF_DOWNLOAD),$(call Download,coef)))
+
+define Build/Configure
+ rm -rf \
+ $(PKG_BUILD_DIR)/coef \
+ $(PKG_BUILD_DIR)/firmware
+ mkdir -p \
+ $(PKG_BUILD_DIR)/coef \
+ $(PKG_BUILD_DIR)/firmware
+ $(TAR) -C $(PKG_BUILD_DIR)/firmware -xvzf $(DL_DIR)/$(FW_FILE)
+ $(TAR) -C $(PKG_BUILD_DIR)/coef -xvzf $(DL_DIR)/$(COEF_FILE)
+ (cd $(PKG_BUILD_DIR); aclocal && autoconf && automake)
+ $(call Build/Configure/Default)
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ mkdir -p $(1)/usr/include/drv_vmmc
+ $(CP) -v --dereference $(PKG_BUILD_DIR)/include/* $(1)/usr/include/drv_vmmc
+ (cd $(1)/usr/include/drv_vmmc && ln -snf . include)
+endef
+
+define KernelPackage/ltq-vmmc/install
+ $(INSTALL_DIR) $(1)/etc/init.d $(1)/$(FW_DIR)
+ $(INSTALL_BIN) ./files/vmmc.init $(1)/etc/init.d/vmmc
+ $(CP) $(PKG_BUILD_DIR)/firmware/$(FW_SOURCE) $(1)/$(FW_DIR)/$(FW_TARGET)
+ ln -s /$(FW_DIR)/$(FW_TARGET) $(1)/$(FW_DIR)/$(FW_TARGET_GENERIC)
+ $(CP) $(PKG_BUILD_DIR)/coef/$(COEF_SRC) $(1)/$(FW_DIR)/$(COEF_TARGET)
+ ln -s /$(FW_DIR)/$(COEF_TARGET) $(1)/$(FW_DIR)/$(COEF_TARGET_GENERIC)
+endef
+
+$(eval $(call KernelPackage,ltq-vmmc))
diff --git a/package/ltq-vmmc/files/vmmc.init b/package/ltq-vmmc/files/vmmc.init
new file mode 100644
index 000000000..100a97dc4
--- /dev/null
+++ b/package/ltq-vmmc/files/vmmc.init
@@ -0,0 +1,19 @@
+#!/bin/sh /etc/rc.common
+#
+# Activate Voice CPE TAPI subsystem LL driver for VMMC
+
+START=31
+
+start() {
+ [ ! -c /dev/vmmc10 ] && {
+ mknod /dev/vmmc10 c 122 10
+ mknod /dev/vmmc11 c 122 11
+ mknod /dev/vmmc12 c 122 12
+ mknod /dev/vmmc13 c 122 13
+ mknod /dev/vmmc14 c 122 14
+ mknod /dev/vmmc15 c 122 15
+ mknod /dev/vmmc16 c 122 16
+ mknod /dev/vmmc17 c 122 17
+ mknod /dev/vmmc18 c 122 18
+ }
+}
diff --git a/package/ltq-vmmc/patches/000-portability.patch b/package/ltq-vmmc/patches/000-portability.patch
new file mode 100644
index 000000000..48602476f
--- /dev/null
+++ b/package/ltq-vmmc/patches/000-portability.patch
@@ -0,0 +1,287 @@
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -228,7 +228,7 @@ drv_vmmc_CFLAGS += -fno-common
+ drv_vmmc_OBJS = "$(subst .c,.o, $(drv_vmmc_SOURCES) $(nodist_drv_vmmc_SOURCES))"
+
+ drv_vmmc.ko: $(drv_vmmc_SOURCES) $(EXTRA_DIST)
+- @echo -e "Making Linux 2.6.x kernel object"
++ @echo "Making Linux 2.6.x kernel object"
+ @for f in $(drv_vmmc_SOURCES) $(nodist_drv_vmmc_SOURCES) ; do \
+ if test ! -e $(PWD)/$$f; then \
+ echo " LN $$f" ; \
+@@ -236,10 +236,10 @@ drv_vmmc.ko: $(drv_vmmc_SOURCES) $(EXTRA
+ ln -s @abs_srcdir@/$$f $(PWD)/$$f; \
+ fi; \
+ done;
+- @echo -e "# drv_vmmc: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild
+- @echo -e "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild
+- @echo -e "$(subst .ko,,$@)-y := $(drv_vmmc_OBJS)" >> $(PWD)/Kbuild
+- @echo -e "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(CFLAGS) $(drv_vmmc_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild
++ @echo "# drv_vmmc: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild
++ @echo "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild
++ @echo "$(subst .ko,,$@)-y := $(drv_vmmc_OBJS)" >> $(PWD)/Kbuild
++ @echo "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(CFLAGS) $(drv_vmmc_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild
+ $(MAKE) ARCH=@KERNEL_ARCH@ -C @KERNEL_BUILD_PATH@ O=@KERNEL_BUILD_PATH@ M=$(PWD) modules
+
+ clean-generic:
+--- a/src/drv_vmmc_linux.c
++++ b/src/drv_vmmc_linux.c
+@@ -27,11 +27,18 @@
+ #include <linux/proc_fs.h>
+ #include <linux/wait.h>
+ #include <linux/vmalloc.h>
++#include <linux/sched.h>
+
+ #ifdef LINUX_2_6
+ #include <linux/version.h>
+ #ifndef UTS_RELEASE
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
++#include <linux/autoconf.h>
+ #include <linux/utsrelease.h>
++#else
++#include <generated/autoconf.h>
++#include <generated/utsrelease.h>
++#endif
+ #endif /* UTC_RELEASE */
+ #undef CONFIG_DEVFS_FS
+ #endif /* LINUX_2_6 */
+--- a/src/mps/drv_mps_vmmc_linux.c
++++ b/src/mps/drv_mps_vmmc_linux.c
+@@ -19,11 +19,22 @@
+ #include "drv_config.h"
+
+ #include "drv_mps_version.h"
++#include <linux/version.h>
+
+ #ifdef CONFIG_DEBUG_MINI_BOOT
+ #define IKOS_MINI_BOOT
+ #endif /* */
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
+ #include <linux/autoconf.h>
++#ifndef UTS_RELEASE
++#include <linux/utsrelease.h>
++#endif
++#else
++#include <generated/autoconf.h>
++#ifndef UTS_RELEASE
++#include <generated/utsrelease.h>
++#endif
++#endif
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/poll.h>
+@@ -34,7 +45,13 @@
+ #include <linux/delay.h>
+ #include <linux/interrupt.h>
+ #ifdef LINUX_2_6
++#ifndef UTS_RELEASE
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
+ #include <linux/utsrelease.h>
++#else
++#include <generated/utsrelease.h>
++#endif
++#endif /* UTC_RELEASE */
+ #else /* */
+ #include <linux/uts.h>
+ #include <linux/moduleparam.h>
+@@ -94,8 +111,13 @@ IFX_int32_t ifx_mps_get_status_proc (IFX
+ #ifndef __KERNEL__
+ IFX_int32_t ifx_mps_open (struct inode *inode, struct file *file_p);
+ IFX_int32_t ifx_mps_close (struct inode *inode, struct file *file_p);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+ IFX_int32_t ifx_mps_ioctl (struct inode *inode, struct file *file_p,
+ IFX_uint32_t nCmd, IFX_ulong_t arg);
++#else
++long ifx_mps_ioctl (struct file *file_p,
++ IFX_uint32_t nCmd, IFX_ulong_t arg);
++#endif
+ IFX_int32_t ifx_mps_read_mailbox (mps_devices type, mps_message * rw);
+ IFX_int32_t ifx_mps_write_mailbox (mps_devices type, mps_message * rw);
+ IFX_int32_t ifx_mps_register_data_callback (mps_devices type, IFX_uint32_t dir,
+@@ -155,7 +177,11 @@ IFX_char_t voice_channel_int_name[NUM_VO
+ static struct file_operations ifx_mps_fops = {
+ owner:THIS_MODULE,
+ poll:ifx_mps_poll,
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+ ioctl:ifx_mps_ioctl,
++#else
++ unlocked_ioctl:ifx_mps_ioctl,
++#endif
+ open:ifx_mps_open,
+ release:ifx_mps_close
+ };
+@@ -598,8 +624,13 @@ static IFX_uint32_t ifx_mps_poll (struct
+ * \return -ENOIOCTLCMD Invalid command
+ * \ingroup API
+ */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+ IFX_int32_t ifx_mps_ioctl (struct inode * inode, struct file * file_p,
+ IFX_uint32_t nCmd, IFX_ulong_t arg)
++#else
++long ifx_mps_ioctl (struct file *file_p,
++ IFX_uint32_t nCmd, IFX_ulong_t arg)
++#endif
+ {
+ IFX_int32_t retvalue = -EINVAL;
+ mps_message rw_struct;
+@@ -613,17 +644,30 @@ IFX_int32_t ifx_mps_ioctl (struct inode
+ 'mps_devices' enum type, which in fact is [0..8]; So, if inode value is
+ [0..NUM_VOICE_CHANNEL+1], then we make sure that we are calling from
+ kernel space. */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+ if (((IFX_int32_t) inode >= 0) &&
+ ((IFX_int32_t) inode < NUM_VOICE_CHANNEL + 1))
++#else
++ if (((IFX_int32_t) file_p >= 0) &&
++ ((IFX_int32_t) file_p < NUM_VOICE_CHANNEL + 1))
++#endif
+ {
+ from_kernel = 1;
+
+ /* Get corresponding mailbox device structure */
+ if ((pMBDev =
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+ ifx_mps_get_device ((mps_devices) ((IFX_int32_t) inode))) == 0)
++#else
++ ifx_mps_get_device ((mps_devices) ((IFX_int32_t) file_p))) == 0)
++#endif
+ {
+ return (-EINVAL);
+ }
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
++#else
++ file_p = NULL;
++#endif
+ }
+ else
+ {
+--- a/src/mps/drv_mps_vmmc_common.c
++++ b/src/mps/drv_mps_vmmc_common.c
+@@ -21,7 +21,11 @@
+ #undef USE_PLAIN_VOICE_FIRMWARE
+ #undef PRINT_ON_ERR_INTERRUPT
+ #undef FAIL_ON_ERR_INTERRUPT
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
+ #include <linux/autoconf.h>
++#else
++#include <generated/autoconf.h>
++#endif
+ #include <linux/interrupt.h>
+ #include <linux/delay.h>
+
+@@ -92,7 +96,9 @@ extern IFX_uint32_t danube_get_cpu_ver (
+ extern mps_mbx_dev *ifx_mps_get_device (mps_devices type);
+
+ #ifdef LINUX_2_6
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
+ extern IFX_void_t bsp_mask_and_ack_irq (IFX_uint32_t irq_nr);
++#endif
+
+ #else /* */
+ extern IFX_void_t mask_and_ack_danube_irq (IFX_uint32_t irq_nr);
+--- a/src/mps/drv_mps_vmmc_danube.c
++++ b/src/mps/drv_mps_vmmc_danube.c
+@@ -20,7 +20,11 @@
+
+ #ifdef SYSTEM_DANUBE /* defined in drv_mps_vmmc_config.h */
+
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
+ #include <linux/autoconf.h>
++#else
++#include <generated/autoconf.h>
++#endif
+
+ /* lib_ifxos headers */
+ #include "ifx_types.h"
+--- a/configure.in
++++ b/configure.in
+@@ -112,7 +112,7 @@ dnl Set kernel build path
+ AC_ARG_ENABLE(kernelbuild,
+ AS_HELP_STRING(--enable-kernelbuild=x,Set the target kernel build path),
+ [
+- if test -r $enableval/include/linux/autoconf.h; then
++ if test -e $enableval/include/linux/autoconf.h -o -e $enableval/include/generated/autoconf.h; then
+ AC_SUBST([KERNEL_BUILD_PATH],[$enableval])
+ else
+ AC_MSG_ERROR([The kernel build directory is not valid or not configured!])
+--- a/src/drv_vmmc_bbd.c
++++ b/src/drv_vmmc_bbd.c
+@@ -1072,7 +1072,11 @@ static IFX_int32_t vmmc_BBD_DownloadChCr
+ IFX_uint8_t padBytes = 0;
+ #endif
+ IFX_uint16_t cram_offset, cram_crc,
+- pCmd [MAX_CMD_WORD] = {0};
++ pCmd [MAX_CMD_WORD]
++#if defined (__GNUC__) || defined (__GNUG__)
++ __attribute__ ((aligned(4)))
++#endif
++ = {0};
+
+ /* read offset */
+ cpb2w (&cram_offset, &bbd_cram->pData[0], sizeof (IFX_uint16_t));
+--- a/src/drv_vmmc_init.c
++++ b/src/drv_vmmc_init.c
+@@ -776,8 +776,13 @@ IFX_int32_t VMMC_TAPI_LL_FW_Start(IFX_TA
+ dwld.fwDwld.length = IoInit.pram_size;
+
+ /* download firmware */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+ ret = ifx_mps_ioctl((IFX_void_t *) command, IFX_NULL, FIO_MPS_DOWNLOAD,
+ (IFX_uint32_t) &dwld.fwDwld);
++#else
++ ret = ifx_mps_ioctl((IFX_void_t *) command, FIO_MPS_DOWNLOAD,
++ (IFX_uint32_t) &dwld.fwDwld);
++#endif
+ }
+
+ if (VMMC_SUCCESS(ret))
+--- a/src/drv_vmmc_ioctl.c
++++ b/src/drv_vmmc_ioctl.c
+@@ -426,18 +426,31 @@ IFX_int32_t VMMC_Dev_Spec_Ioctl (IFX_TAP
+ /* MPS driver will do the USR2KERN so just pass on the pointer. */
+ dwnld_struct.data = (IFX_void_t *)IoInit.pPRAMfw;
+
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+ ret = ifx_mps_ioctl((IFX_void_t *)command, IFX_NULL,
+ FIO_MPS_DOWNLOAD, (IFX_uint32_t) &dwnld_struct);
++#else
++ ret = ifx_mps_ioctl((IFX_void_t *)command,
++ FIO_MPS_DOWNLOAD, (IFX_uint32_t) &dwnld_struct);
++#endif
+ break;
+ }
+ case FIO_DEV_RESET:
+ {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+ ret = ifx_mps_ioctl((IFX_void_t *)command, IFX_NULL, FIO_MPS_RESET, 0);
++#else
++ ret = ifx_mps_ioctl((IFX_void_t *)command, FIO_MPS_RESET, 0);
++#endif
+ break;
+ }
+ case FIO_DEV_RESTART:
+ {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+ ret = ifx_mps_ioctl((IFX_void_t *)command, IFX_NULL, FIO_MPS_RESTART, 0);
++#else
++ ret = ifx_mps_ioctl((IFX_void_t *)command, FIO_MPS_RESTART, 0);
++#endif
+ break;
+ }
+ case FIO_LASTERR:
+--- a/src/mps/drv_mps_vmmc.h
++++ b/src/mps/drv_mps_vmmc.h
+@@ -279,8 +279,13 @@ typedef struct
+ #include <linux/fs.h>
+ IFX_int32_t ifx_mps_open (struct inode *inode, struct file *file_p);
+ IFX_int32_t ifx_mps_close (struct inode *inode, struct file *filp);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+ IFX_int32_t ifx_mps_ioctl (struct inode *inode, struct file *file_p,
+ IFX_uint32_t nCmd, unsigned long arg);
++#else
++long ifx_mps_ioctl (struct file *filp,
++ IFX_uint32_t nCmd, unsigned long arg);
++#endif
+ IFX_int32_t ifx_mps_register_data_callback (mps_devices type, IFX_uint32_t dir,
+ IFX_void_t (*callback) (mps_devices
+ type));
diff --git a/package/ltq-vmmc/patches/100-target.patch b/package/ltq-vmmc/patches/100-target.patch
new file mode 100644
index 000000000..eae621eaf
--- /dev/null
+++ b/package/ltq-vmmc/patches/100-target.patch
@@ -0,0 +1,738 @@
+--- a/src/drv_vmmc_access.h
++++ b/src/drv_vmmc_access.h
+@@ -24,6 +24,10 @@
+ #include "drv_mps_vmmc.h"
+ #endif
+
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28))
++# define IFX_MPS IFXMIPS_MPS_BASE_ADDR
++#endif
++
+ /* ============================= */
+ /* Global Defines */
+ /* ============================= */
+--- a/src/drv_vmmc_danube.h
++++ b/src/drv_vmmc_danube.h
+@@ -15,56 +15,18 @@
+ */
+
+ #if defined SYSTEM_DANUBE
+-#include <asm/ifx/ifx_gpio.h>
++#include <lantiq_soc.h>
++
+ #else
+ #error no system selected
+ #endif
+
+-#define VMMC_TAPI_GPIO_MODULE_ID IFX_GPIO_MODULE_TAPI_VMMC
++#define VMMC_TAPI_GPIO_MODULE_ID IFX_GPIO_MODULE_TAPI_VMMC
+ /**
+
+ */
+ #define VMMC_PCM_IF_CFG_HOOK(mode, GPIOreserved, ret) \
+ do { \
+- ret = VMMC_statusOk; \
+- /* Reserve P0.0 as TDM/FSC */ \
+- if (!GPIOreserved) \
+- ret |= ifx_gpio_pin_reserve(IFX_GPIO_PIN_ID(0, 0), VMMC_TAPI_GPIO_MODULE_ID); \
+- ret |= ifx_gpio_altsel0_set(IFX_GPIO_PIN_ID(0, 0), VMMC_TAPI_GPIO_MODULE_ID); \
+- ret |= ifx_gpio_altsel1_set(IFX_GPIO_PIN_ID(0, 0), VMMC_TAPI_GPIO_MODULE_ID); \
+- ret |= ifx_gpio_open_drain_set(IFX_GPIO_PIN_ID(0, 0), VMMC_TAPI_GPIO_MODULE_ID);\
+- \
+- /* Reserve P1.9 as TDM/DO */ \
+- if (!GPIOreserved) \
+- ret |= ifx_gpio_pin_reserve(IFX_GPIO_PIN_ID(1, 9), VMMC_TAPI_GPIO_MODULE_ID); \
+- ret |= ifx_gpio_altsel0_set(IFX_GPIO_PIN_ID(1, 9), VMMC_TAPI_GPIO_MODULE_ID); \
+- ret |= ifx_gpio_altsel1_clear(IFX_GPIO_PIN_ID(1, 9), VMMC_TAPI_GPIO_MODULE_ID); \
+- ret |= ifx_gpio_dir_out_set(IFX_GPIO_PIN_ID(1, 9), VMMC_TAPI_GPIO_MODULE_ID); \
+- ret |= ifx_gpio_open_drain_set(IFX_GPIO_PIN_ID(1, 9), VMMC_TAPI_GPIO_MODULE_ID); \
+- \
+- /* Reserve P1.10 as TDM/DI */ \
+- if (!GPIOreserved) \
+- ret |= ifx_gpio_pin_reserve(IFX_GPIO_PIN_ID(1,10), VMMC_TAPI_GPIO_MODULE_ID); \
+- ret |= ifx_gpio_altsel0_clear(IFX_GPIO_PIN_ID(1,10), VMMC_TAPI_GPIO_MODULE_ID); \
+- ret |= ifx_gpio_altsel1_set(IFX_GPIO_PIN_ID(1,10), VMMC_TAPI_GPIO_MODULE_ID);\
+- ret |= ifx_gpio_dir_in_set(IFX_GPIO_PIN_ID(1,10), VMMC_TAPI_GPIO_MODULE_ID); \
+- \
+- /* Reserve P1.11 as TDM/DCL */ \
+- if (!GPIOreserved) \
+- ret |= ifx_gpio_pin_reserve(IFX_GPIO_PIN_ID(1,11), VMMC_TAPI_GPIO_MODULE_ID); \
+- ret |= ifx_gpio_altsel0_set(IFX_GPIO_PIN_ID(1,11), VMMC_TAPI_GPIO_MODULE_ID); \
+- ret |= ifx_gpio_altsel1_clear(IFX_GPIO_PIN_ID(1,11), VMMC_TAPI_GPIO_MODULE_ID); \
+- ret |= ifx_gpio_open_drain_set(IFX_GPIO_PIN_ID(1,11), VMMC_TAPI_GPIO_MODULE_ID); \
+- \
+- if (mode == 2) { \
+- /* TDM/FSC+DCL Master */ \
+- ret |= ifx_gpio_dir_out_set(IFX_GPIO_PIN_ID(0, 0), VMMC_TAPI_GPIO_MODULE_ID); \
+- ret |= ifx_gpio_dir_out_set(IFX_GPIO_PIN_ID(1,11), VMMC_TAPI_GPIO_MODULE_ID); \
+- } else { \
+- /* TDM/FSC+DCL Slave */ \
+- ret |= ifx_gpio_dir_in_set(IFX_GPIO_PIN_ID(0, 0), VMMC_TAPI_GPIO_MODULE_ID); \
+- ret |= ifx_gpio_dir_in_set(IFX_GPIO_PIN_ID(1,11), VMMC_TAPI_GPIO_MODULE_ID); \
+- } \
+ } while(0);
+
+ /**
+@@ -72,11 +34,6 @@
+ */
+ #define VMMC_DRIVER_UNLOAD_HOOK(ret) \
+ do { \
+- ret = VMMC_statusOk; \
+- ret |= ifx_gpio_pin_free(IFX_GPIO_PIN_ID(0, 0), VMMC_TAPI_GPIO_MODULE_ID); \
+- ret |= ifx_gpio_pin_free(IFX_GPIO_PIN_ID(1, 9), VMMC_TAPI_GPIO_MODULE_ID); \
+- ret |= ifx_gpio_pin_free(IFX_GPIO_PIN_ID(1,10), VMMC_TAPI_GPIO_MODULE_ID); \
+- ret |= ifx_gpio_pin_free(IFX_GPIO_PIN_ID(1,11), VMMC_TAPI_GPIO_MODULE_ID); \
+ } while (0)
+
+ #endif /* _DRV_VMMC_AMAZON_S_H */
+--- a/src/drv_vmmc_init.c
++++ b/src/drv_vmmc_init.c
+@@ -52,6 +52,14 @@
+ #include "ifx_pmu.h"
+ #endif /* PMU_SUPPORTED */
+
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28))
++# define IFX_MPS_CAD0SR IFXMIPS_MPS_CAD0SR
++# define IFX_MPS_CAD1SR IFXMIPS_MPS_CAD1SR
++# define IFX_MPS_CVC0SR IFXMIPS_MPS_CVC0SR
++# define IFX_MPS_CVC1SR IFXMIPS_MPS_CVC1SR
++# define IFX_MPS_CVC2SR IFXMIPS_MPS_CVC2SR
++# define IFX_MPS_CVC3SR IFXMIPS_MPS_CVC3SR
++#endif
+
+ /* ============================= */
+ /* Local Macros & Definitions */
+@@ -1591,7 +1599,7 @@
+ #ifdef VMMC_DRIVER_UNLOAD_HOOK
+ if (VDevices[0].nDevState & DS_GPIO_RESERVED)
+ {
+- IFX_int32_t ret;
++ IFX_int32_t ret = 0;
+ VMMC_DRIVER_UNLOAD_HOOK(ret);
+ if (!VMMC_SUCCESS(ret))
+ {
+--- a/src/drv_vmmc_init_cap.c
++++ b/src/drv_vmmc_init_cap.c
+@@ -22,6 +22,11 @@
+ #include "drv_mps_vmmc.h"
+ #include "drv_mps_vmmc_device.h"
+
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28))
++# define IFX_MPS_CHIPID_VERSION_GET IFXMIPS_MPS_CHIPID_VERSION_GET
++# define IFX_MPS_CHIPID IFXMIPS_MPS_CHIPID
++#endif
++
+ /* ============================= */
+ /* Configuration defintions */
+ /* ============================= */
+--- a/src/mps/drv_mps_vmmc_common.c
++++ b/src/mps/drv_mps_vmmc_common.c
+@@ -17,6 +17,7 @@
+ /* Includes */
+ /* ============================= */
+ #include "drv_config.h"
++#include "drv_vmmc_init.h"
+
+ #undef USE_PLAIN_VOICE_FIRMWARE
+ #undef PRINT_ON_ERR_INTERRUPT
+@@ -39,8 +40,32 @@
+ #include "ifxos_interrupt.h"
+ #include "ifxos_time.h"
+
+-#include <asm/ifx/ifx_regs.h>
+-#include <asm/ifx/ifx_gptu.h>
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28))
++# include <lantiq.h>
++# include <irq.h>
++# include <lantiq_timer.h>
++
++# define ifx_gptu_timer_request lq_request_timer
++# define ifx_gptu_timer_start lq_start_timer
++# define ifx_gptu_countvalue_get lq_get_count_value
++# define ifx_gptu_timer_free lq_free_timer
++
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
++# define bsp_mask_and_ack_irq ltq_mask_and_ack_irq
++#else
++extern void ltq_mask_and_ack_irq(struct irq_data *d);
++static void inline bsp_mask_and_ack_irq(int x)
++{
++ struct irq_data d;
++ d.irq = x;
++ ltq_mask_and_ack_irq(&d);
++}
++#endif
++#else
++# include <asm/ifx/ifx_regs.h>
++# include <asm/ifx/ifx_gptu.h>
++#endif
+
+ #include "drv_mps_vmmc.h"
+ #include "drv_mps_vmmc_dbg.h"
+@@ -104,6 +129,9 @@
+ extern IFX_void_t mask_and_ack_danube_irq (IFX_uint32_t irq_nr);
+
+ #endif /* */
++
++extern void sys_hw_setup (void);
++
+ extern IFXOS_event_t fw_ready_evt;
+ /* callback function to free all data buffers currently used by voice FW */
+ IFX_void_t (*ifx_mps_bufman_freeall)(IFX_void_t) = IFX_NULL;
+@@ -207,7 +235,8 @@
+ */
+ IFX_void_t *ifx_mps_fastbuf_malloc (IFX_size_t size, IFX_int32_t priority)
+ {
+- IFX_uint32_t ptr, flags;
++ IFXOS_INTSTAT flags;
++ IFX_uint32_t ptr;
+ IFX_int32_t index = fastbuf_index;
+
+ if (fastbuf_initialized == 0)
+@@ -261,7 +290,7 @@
+ */
+ IFX_void_t ifx_mps_fastbuf_free (const IFX_void_t * ptr)
+ {
+- IFX_uint32_t flags;
++ IFXOS_INTSTAT flags;
+ IFX_int32_t index = fastbuf_index;
+
+ IFXOS_LOCKINT (flags);
+@@ -457,7 +486,7 @@
+ */
+ static IFX_int32_t ifx_mps_bufman_inc_level (IFX_uint32_t value)
+ {
+- IFX_uint32_t flags;
++ IFXOS_INTSTAT flags;
+
+ if (mps_buffer.buf_level + value > MPS_BUFFER_MAX_LEVEL)
+ {
+@@ -484,7 +513,7 @@
+ */
+ static IFX_int32_t ifx_mps_bufman_dec_level (IFX_uint32_t value)
+ {
+- IFX_uint32_t flags;
++ IFXOS_INTSTAT flags;
+
+ if (mps_buffer.buf_level < value)
+ {
+@@ -636,7 +665,7 @@
+ mem_seg_ptr[i] =
+ (IFX_uint32_t *) CPHYSADDR ((IFX_uint32_t) mps_buffer.
+ malloc (segment_size, FASTBUF_FW_OWNED));
+- if (mem_seg_ptr[i] == CPHYSADDR (IFX_NULL))
++ if (mem_seg_ptr[i] == (IFX_uint32_t *)CPHYSADDR (IFX_NULL))
+ {
+ TRACE (MPS, DBG_LEVEL_HIGH,
+ ("%s(): cannot allocate buffer\n", __FUNCTION__));
+@@ -952,7 +981,7 @@
+ mps_mbx_dev * pMBDev, IFX_int32_t bcommand,
+ IFX_boolean_t from_kernel)
+ {
+- IFX_uint32_t flags;
++ IFXOS_INTSTAT flags;
+
+ IFXOS_LOCKINT (flags);
+
+@@ -1068,7 +1097,7 @@
+ IFX_void_t ifx_mps_release_structures (mps_comm_dev * pDev)
+ {
+ IFX_int32_t count;
+- IFX_uint32_t flags;
++ IFXOS_INTSTAT flags;
+
+ IFXOS_LOCKINT (flags);
+ IFXOS_BlockFree (pFW_img_data);
+@@ -1117,7 +1146,7 @@
+
+ /* Initialize MPS main structure */
+ memset ((IFX_void_t *) pDev, 0, sizeof (mps_comm_dev));
+- pDev->base_global = (mps_mbx_reg *) IFX_MPS_SRAM;
++ pDev->base_global = (mps_mbx_reg *) IFXMIPS_MPS_SRAM;
+ pDev->flags = 0x00000000;
+ MBX_Memory = pDev->base_global;
+
+@@ -1125,9 +1154,11 @@
+ for MBX communication. These are: mailbox base address, mailbox size, *
+ mailbox read index and mailbox write index. for command and voice
+ mailbox, * upstream and downstream direction. */
+- memset ((IFX_void_t *) MBX_Memory, /* avoid to overwrite CPU boot
+- registers */
+- 0, sizeof (mps_mbx_reg) - 2 * sizeof (mps_boot_cfg_reg));
++ memset (
++ /* avoid to overwrite CPU boot registers */
++ (IFX_void_t *) MBX_Memory,
++ 0,
++ sizeof (mps_mbx_reg) - 2 * sizeof (mps_boot_cfg_reg));
+ MBX_Memory->MBX_UPSTR_CMD_BASE =
+ (IFX_uint32_t *) CPHYSADDR ((IFX_uint32_t) MBX_UPSTRM_CMD_FIFO_BASE);
+ MBX_Memory->MBX_UPSTR_CMD_SIZE = MBX_CMD_FIFO_SIZE;
+@@ -1564,7 +1595,7 @@
+ IFX_uint32_t * bytes)
+ {
+ IFX_int32_t i, ret;
+- IFX_uint32_t flags;
++ IFXOS_INTSTAT flags;
+
+ IFXOS_LOCKINT (flags);
+
+@@ -1774,7 +1805,7 @@
+ {
+ mps_fifo *mbx;
+ IFX_uint32_t i;
+- IFX_uint32_t flags;
++ IFXOS_INTSTAT flags;
+ IFX_int32_t retval = -EAGAIN;
+ IFX_int32_t retries = 0;
+ IFX_uint32_t word = 0;
+@@ -2169,6 +2200,7 @@
+ TRACE (MPS, DBG_LEVEL_HIGH,
+ ("%s(): Invalid device ID %d !\n", __FUNCTION__, pMBDev->devID));
+ }
++
+ return retval;
+ }
+
+@@ -2192,7 +2224,7 @@
+ mps_mbx_dev *mbx_dev;
+ MbxMsg_s msg;
+ IFX_uint32_t bytes_read = 0;
+- IFX_uint32_t flags;
++ IFXOS_INTSTAT flags;
+ IFX_int32_t ret;
+
+ /* set pointer to data upstream mailbox, no matter if 0,1,2 or 3 because
+@@ -2283,7 +2315,7 @@
+ {
+ ifx_mps_bufman_dec_level (1);
+ if ((ifx_mps_bufman_get_level () <= mps_buffer.buf_threshold) &&
+- (atomic_read (&pMPSDev->provide_buffer->object.count) == 0))
++ ((volatile unsigned int)pMPSDev->provide_buffer->object.count == 0))
+ {
+ IFXOS_LockRelease (pMPSDev->provide_buffer);
+ }
+@@ -2326,7 +2358,7 @@
+ #endif /* CONFIG_PROC_FS */
+ ifx_mps_bufman_dec_level (1);
+ if ((ifx_mps_bufman_get_level () <= mps_buffer.buf_threshold) &&
+- (atomic_read (&pMPSDev->provide_buffer->object.count) == 0))
++ ((volatile unsigned int)pMPSDev->provide_buffer->object.count == 0))
+ {
+ IFXOS_LockRelease (pMPSDev->provide_buffer);
+ }
+@@ -2356,7 +2388,7 @@
+ IFX_void_t ifx_mps_mbx_cmd_upstream (IFX_ulong_t dummy)
+ {
+ mps_fifo *mbx;
+- IFX_uint32_t flags;
++ IFXOS_INTSTAT flags;
+
+ /* set pointer to upstream command mailbox */
+ mbx = &(pMPSDev->cmd_upstrm_fifo);
+@@ -2404,7 +2436,7 @@
+ mps_event_msg msg;
+ IFX_int32_t length = 0;
+ IFX_int32_t read_length = 0;
+- IFX_uint32_t flags;
++ IFXOS_INTSTAT flags;
+
+ /* set pointer to upstream event mailbox */
+ mbx = &(pMPSDev->event_upstrm_fifo);
+@@ -2619,6 +2651,7 @@
+ #endif
+
+ *IFX_MPS_AD0ENR = Ad0Reg.val;
++
+ }
+
+ /**
+@@ -2647,7 +2680,7 @@
+ */
+ IFX_void_t ifx_mps_dd_mbx_int_enable (IFX_void_t)
+ {
+- IFX_uint32_t flags;
++ IFXOS_INTSTAT flags;
+ MPS_Ad0Reg_u Ad0Reg;
+
+ IFXOS_LOCKINT (flags);
+@@ -2673,7 +2706,7 @@
+ */
+ IFX_void_t ifx_mps_dd_mbx_int_disable (IFX_void_t)
+ {
+- IFX_uint32_t flags;
++ IFXOS_INTSTAT flags;
+ MPS_Ad0Reg_u Ad0Reg;
+
+ IFXOS_LOCKINT (flags);
+@@ -2738,7 +2771,6 @@
+ #else /* */
+ mask_and_ack_danube_irq (irq);
+ #endif /* */
+-
+ /* FW is up and ready to process commands */
+ if (MPS_Ad0StatusReg.fld.dl_end)
+ {
+@@ -2800,6 +2832,7 @@
+ }
+ }
+
++
+ if (MPS_Ad0StatusReg.fld.du_mbx)
+ {
+ #ifdef CONFIG_PROC_FS
+@@ -2944,12 +2977,12 @@
+ IFX_MPS_CVC0SR[chan] = MPS_VCStatusReg.val;
+ /* handle only enabled interrupts */
+ MPS_VCStatusReg.val &= IFX_MPS_VC0ENR[chan];
+-
+ #ifdef LINUX_2_6
+ bsp_mask_and_ack_irq (irq);
+ #else /* */
+ mask_and_ack_danube_irq (irq);
+ #endif /* */
++
+ pMPSDev->event.MPS_VCStatReg[chan].val = MPS_VCStatusReg.val;
+ #ifdef PRINT_ON_ERR_INTERRUPT
+ if (MPS_VCStatusReg.fld.rcv_ov)
+@@ -3093,7 +3126,8 @@
+ */
+ IFX_return_t ifx_mps_init_gpt ()
+ {
+- IFX_uint32_t flags, timer_flags, timer, loops = 0;
++ unsigned long flags;
++ IFX_uint32_t timer_flags, timer, loops = 0;
+ IFX_ulong_t count;
+ #if defined(SYSTEM_AR9) || defined(SYSTEM_VR9)
+ timer = TIMER1A;
+@@ -3166,6 +3200,7 @@
+ #else /* Danube */
+ timer = TIMER1B;
+ #endif /* SYSTEM_AR9 || SYSTEM_VR9 */
++
+ ifx_gptu_timer_free (timer);
+ }
+
+--- a/src/mps/drv_mps_vmmc_danube.c
++++ b/src/mps/drv_mps_vmmc_danube.c
+@@ -16,6 +16,7 @@
+ /* ============================= */
+ /* Includes */
+ /* ============================= */
++#include "linux/version.h"
+ #include "drv_config.h"
+
+ #ifdef SYSTEM_DANUBE /* defined in drv_mps_vmmc_config.h */
+@@ -36,9 +37,22 @@
+ #include "ifxos_select.h"
+ #include "ifxos_interrupt.h"
+
+-#include <asm/ifx/ifx_regs.h>
+-#include <asm/ifx/ifx_gpio.h>
+-#include <asm/ifx/common_routines.h>
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28))
++# include <lantiq.h>
++# include <irq.h>
++# include <lantiq_timer.h>
++# include <linux/dma-mapping.h>
++
++
++#define LQ_RCU_BASE_ADDR (KSEG1 + LTQ_RCU_BASE_ADDR)
++# define LQ_RCU_RST ((u32 *)(LQ_RCU_BASE_ADDR + 0x0010))
++#define IFX_RCU_RST_REQ_CPU1 (1 << 3)
++# define IFX_RCU_RST_REQ LQ_RCU_RST
++#else
++# include <asm/ifx/ifx_regs.h>
++# include <asm/ifx_vpe.h>
++# include <asm/ifx/ifx_gpio.h>
++#endif
+
+ #include "drv_mps_vmmc.h"
+ #include "drv_mps_vmmc_dbg.h"
+@@ -75,6 +89,20 @@
+ /* Local function definition */
+ /* ============================= */
+
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28))
++IFX_uint32_t ifx_get_cp1_size(IFX_void_t)
++{
++ return 1;
++}
++
++unsigned int *ltq_get_cp1_base(void);
++
++IFX_uint32_t *ifx_get_cp1_base(IFX_void_t)
++{
++ return ltq_get_cp1_base();
++}
++#endif
++
+ /******************************************************************************
+ * DANUBE Specific Routines
+ ******************************************************************************/
+@@ -134,6 +162,15 @@
+ }
+
+ /* check if FW image fits in available memory space */
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28))
++ if (mem > ifx_get_cp1_size()<<20)
++ {
++ TRACE (MPS, DBG_LEVEL_HIGH,
++ ("[%s %s %d]: error, firmware memory exceeds reserved space (%i > %i)!\n",
++ __FILE__, __func__, __LINE__, mem, ifx_get_cp1_size()<<20));
++ return IFX_ERROR;
++ }
++#else
+ if (mem > ifx_get_cp1_size())
+ {
+ TRACE (MPS, DBG_LEVEL_HIGH,
+@@ -141,6 +178,7 @@
+ __FILE__, __func__, __LINE__, mem, ifx_get_cp1_size()));
+ return IFX_ERROR;
+ }
++#endif
+
+ /* reset the driver */
+ ifx_mps_reset ();
+@@ -361,7 +399,7 @@
+ */
+ IFX_void_t ifx_mps_wdog_expiry()
+ {
+- IFX_uint32_t flags;
++ unsigned long flags;
+
+ IFXOS_LOCKINT (flags);
+ /* recalculate and compare the firmware checksum */
+--- a/src/mps/drv_mps_vmmc_device.h
++++ b/src/mps/drv_mps_vmmc_device.h
+@@ -16,8 +16,58 @@
+ declarations.
+ *******************************************************************************/
+
+-#include <asm/ifx/ifx_regs.h>
+-#include <asm/ifx_vpe.h>
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28))
++# include <lantiq.h>
++# include <irq.h>
++# include <lantiq_soc.h>
++# include <gpio.h>
++#define IFXMIPS_MPS_SRAM ((u32 *)(KSEG1 + 0x1F200000))
++#define IFXMIPS_MPS_BASE_ADDR (KSEG1 + 0x1F107000)
++#define IFXMIPS_MPS_CHIPID ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0344))
++#define IFXMIPS_MPS_VC0ENR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0000))
++#define IFXMIPS_MPS_RVC0SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0010))
++#define IFXMIPS_MPS_CVC0SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0030))
++#define IFXMIPS_MPS_CVC1SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0034))
++#define IFXMIPS_MPS_CVC2SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0038))
++#define IFXMIPS_MPS_CVC3SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x003C))
++#define IFXMIPS_MPS_RAD0SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0040))
++#define IFXMIPS_MPS_RAD1SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0044))
++#define IFXMIPS_MPS_SAD0SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0048))
++#define IFXMIPS_MPS_SAD1SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x004C))
++#define IFXMIPS_MPS_CAD0SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0050))
++#define IFXMIPS_MPS_CAD1SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0054))
++#define IFXMIPS_MPS_AD0ENR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0058))
++#define IFXMIPS_MPS_AD1ENR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x005C))
++
++#define IFXMIPS_MPS_CHIPID_VERSION_GET(value) (((value) >> 28) & ((1 << 4) - 1))
++#define IFXMIPS_MPS_CHIPID_VERSION_SET(value) ((((1 << 4) - 1) & (value)) << 28)
++#define IFXMIPS_MPS_CHIPID_PARTNUM_GET(value) (((value) >> 12) & ((1 << 16) - 1))
++#define IFXMIPS_MPS_CHIPID_PARTNUM_SET(value) ((((1 << 16) - 1) & (value)) << 12)
++#define IFXMIPS_MPS_CHIPID_MANID_GET(value) (((value) >> 1) & ((1 << 10) - 1))
++#define IFXMIPS_MPS_CHIPID_MANID_SET(value) ((((1 << 10) - 1) & (value)) << 1)
++#else
++# include <asm/ifx/ifx_regs.h>
++# include <asm/ifx_vpe.h>
++#endif
++/* MPS register */
++# define IFX_MPS_AD0ENR IFXMIPS_MPS_AD0ENR
++# define IFX_MPS_AD1ENR IFXMIPS_MPS_AD1ENR
++# define IFX_MPS_RAD0SR IFXMIPS_MPS_RAD0SR
++# define IFX_MPS_RAD1SR IFXMIPS_MPS_RAD1SR
++# define IFX_MPS_VC0ENR IFXMIPS_MPS_VC0ENR
++# define IFX_MPS_RVC0SR IFXMIPS_MPS_RVC0SR
++# define IFX_MPS_CVC0SR IFXMIPS_MPS_CVC0SR
++# define IFX_MPS_CAD0SR IFXMIPS_MPS_CAD0SR
++# define IFX_MPS_CAD1SR IFXMIPS_MPS_CAD1SR
++# define IFX_MPS_CVC1SR IFXMIPS_MPS_CVC1SR
++# define IFX_MPS_CVC2SR IFXMIPS_MPS_CVC2SR
++# define IFX_MPS_CVC3SR IFXMIPS_MPS_CVC3SR
++# define IFX_MPS_SAD0SR IFXMIPS_MPS_SAD0SR
++/* interrupt vectors */
++# define INT_NUM_IM4_IRL14 (INT_NUM_IM4_IRL0 + 14)
++# define INT_NUM_IM4_IRL18 (INT_NUM_IM4_IRL0 + 18)
++# define INT_NUM_IM4_IRL19 (INT_NUM_IM4_IRL0 + 19)
++# define IFX_ICU_IM4_IER IFXMIPS_ICU_IM4_IER
+
+ /* ============================= */
+ /* MPS Common defines */
+@@ -26,32 +76,28 @@
+ #define MPS_BASEADDRESS 0xBF107000
+ #define MPS_RAD0SR MPS_BASEADDRESS + 0x0004
+
+-#define MPS_RAD0SR_DU (1<<0)
+-#define MPS_RAD0SR_CU (1<<1)
+-
+ #define MBX_BASEADDRESS 0xBF200000
+ #define VCPU_BASEADDRESS 0xBF208000 /* 0xBF108000 */
+ /*---------------------------------------------------------------------------*/
++#if !defined(CONFIG_LANTIQ)
++/* enabling interrupts is done with request_irq by the BSP
++ The related code should not be needed anymore */
+ #if defined(SYSTEM_AR9) || defined(SYSTEM_VR9)
+ /* TODO: doublecheck - IM4 or different! */
+ #define MPS_INTERRUPTS_ENABLE(X) *((volatile IFX_uint32_t*) IFX_ICU_IM4_IER) |= X;
+ #define MPS_INTERRUPTS_DISABLE(X) *((volatile IFX_uint32_t*) IFX_ICU_IM4_IER) &= ~X;
+-#define MPS_INTERRUPTS_CLEAR(X) *((volatile IFX_uint32_t*) IFX_ICU_IM4_ISR) = X;
+-#define MPS_INTERRUPTS_SET(X) *((volatile IFX_uint32_t*) IFX_ICU_IM4_IRSR) = X;/* |= ? */
+ #else /* Danube */
+ /* TODO: possibly needs to be changed to IM4 !!!!!! */
+ #ifdef LINUX_2_6
+ #define MPS_INTERRUPTS_ENABLE(X) *((volatile IFX_uint32_t*) IFX_ICU_IM4_IER) |= X;
+ #define MPS_INTERRUPTS_DISABLE(X) *((volatile IFX_uint32_t*) IFX_ICU_IM4_IER) &= ~X;
+-#define MPS_INTERRUPTS_CLEAR(X) *((volatile IFX_uint32_t*) IFX_ICU_IM4_ISR) = X;
+-#define MPS_INTERRUPTS_SET(X) *((volatile IFX_uint32_t*) IFX_ICU_IM4_IRSR) = X;/* |= ? */
+ #else /* */
+ #define MPS_INTERRUPTS_ENABLE(X) *((volatile IFX_uint32_t*) DANUBE_ICU_IM5_IER) |= X;
+ #define MPS_INTERRUPTS_DISABLE(X) *((volatile IFX_uint32_t*) DANUBE_ICU_IM5_IER) &= ~X;
+-#define MPS_INTERRUPTS_CLEAR(X) *((volatile IFX_uint32_t*) DANUBE_ICU_IM5_ISR) = X;
+-#define MPS_INTERRUPTS_SET(X) *((volatile IFX_uint32_t*) DANUBE_ICU_IM5_IRSR) = X;/* |= ? */
+ #endif /* LINUX_2_6 */
+ #endif /* SYSTEM_AR9 || SYSTEM_VR9 */
++#endif /* !defined(CONFIG_LANTIQ) */
++
+ /*---------------------------------------------------------------------------*/
+
+ /*---------------------------------------------------------------------------*/
+@@ -142,53 +188,9 @@
+ #if defined(SYSTEM_AR9) || defined(SYSTEM_VR9)
+ /* ***** Amazon-S specific defines ***** */
+ #define IFX_MPS_Base AMAZON_S_MPS
+-
+-//#define IFX_MPS_CHIPID AMAZON_S_MPS_CHIPID
+-//#define IFX_MPS_CHIPID_VERSION_GET AMAZON_S_MPS_CHIPID_VERSION_GET
+-
+-//#define IFX_MPS_AD0ENR AMAZON_S_MPS_AD0ENR
+-//#define IFX_MPS_AD1ENR AMAZON_S_MPS_AD1ENR
+-//#define IFX_MPS_VC0ENR AMAZON_S_MPS_VC0ENR
+-//#define IFX_MPS_SAD0SR AMAZON_S_MPS_SAD0SR
+-//#define IFX_MPS_RAD0SR AMAZON_S_MPS_RAD0SR
+-//#define IFX_MPS_CAD0SR AMAZON_S_MPS_CAD0SR
+-//#define IFX_MPS_RAD1SR AMAZON_S_MPS_RAD1SR
+-//#define IFX_MPS_CAD1SR AMAZON_S_MPS_CAD1SR
+-//#define IFX_MPS_RVC0SR AMAZON_S_MPS_RVC0SR
+-//#define IFX_MPS_CVC0SR AMAZON_S_MPS_CVC0SR
+-//#define IFX_MPS_CVC1SR AMAZON_S_MPS_CVC1SR
+-//#define IFX_MPS_CVC2SR AMAZON_S_MPS_CVC2SR
+-//#define IFX_MPS_CVC3SR AMAZON_S_MPS_CVC3SR
+-
+-//#define IFX_MPS_SRAM AMAZON_S_MPS_SRAM
+ #else /* */
+ /* ***** DANUBE specific defines ***** */
+ #define IFX_MPS_Base DANUBE_MPS
+-
+-//#define IFX_MPS_CHIPID DANUBE_MPS_CHIPID
+-//#define IFX_MPS_CHIPID_VERSION_GET DANUBE_MPS_CHIPID_VERSION_GET
+-//#define IFX_MPS_CHIPID_VERSION_SET DANUBE_MPS_CHIPID_VERSION_SET
+-//#define IFX_MPS_CHIPID_PARTNUM_GET DANUBE_MPS_CHIPID_PARTNUM_GET
+-//#define IFX_MPS_CHIPID_PARTNUM_SET DANUBE_MPS_CHIPID_PARTNUM_SET
+-//#define IFX_MPS_CHIPID_MANID_GET DANUBE_MPS_CHIPID_MANID_GET
+-//#define IFX_MPS_CHIPID_MANID_SET DANUBE_MPS_CHIPID_MANID_SET
+-//#define IFX_MPS_SUBVER DANUBE_MPS_SUBVER
+-
+-//#define IFX_MPS_AD0ENR DANUBE_MPS_AD0ENR
+-//#define IFX_MPS_AD1ENR DANUBE_MPS_AD1ENR
+-//#define IFX_MPS_VC0ENR DANUBE_MPS_VC0ENR
+-//#define IFX_MPS_SAD0SR DANUBE_MPS_SAD0SR
+-//#define IFX_MPS_RAD0SR DANUBE_MPS_RAD0SR
+-//#define IFX_MPS_CAD0SR DANUBE_MPS_CAD0SR
+-//#define IFX_MPS_RAD1SR DANUBE_MPS_RAD1SR
+-//#define IFX_MPS_CAD1SR DANUBE_MPS_CAD1SR
+-//#define IFX_MPS_RVC0SR DANUBE_MPS_RVC0SR
+-//#define IFX_MPS_CVC0SR DANUBE_MPS_CVC0SR
+-//#define IFX_MPS_CVC1SR DANUBE_MPS_CVC1SR
+-//#define IFX_MPS_CVC2SR DANUBE_MPS_CVC2SR
+-//#define IFX_MPS_CVC3SR DANUBE_MPS_CVC3SR
+-
+-//#define IFX_MPS_SRAM DANUBE_MPS_SRAM
+ #endif /* SYSTEM_AR9 || SYSTEM_VR9 */
+ typedef enum
+ {
+--- a/src/mps/drv_mps_vmmc_linux.c
++++ b/src/mps/drv_mps_vmmc_linux.c
+@@ -57,10 +57,11 @@
+ #include <linux/moduleparam.h>
+ #endif /* */
+
+-
++#if !defined CONFIG_LANTIQ
+ #include <asm/ifx/irq.h>
+ #include <asm/ifx/ifx_regs.h>
+ #include <asm/ifx_vpe.h>
++#endif
+
+ /* lib_ifxos headers */
+ #include "ifx_types.h"
+@@ -959,7 +960,7 @@
+ #endif /* MPS_FIFO_BLOCKING_WRITE */
+ case FIO_MPS_GET_STATUS:
+ {
+- IFX_uint32_t flags;
++ unsigned long flags;
+
+ /* get the status of the channel */
+ if (!from_kernel)
+@@ -993,7 +994,7 @@
+ #if CONFIG_MPS_HISTORY_SIZE > 0
+ case FIO_MPS_GET_CMD_HISTORY:
+ {
+- IFX_uint32_t flags;
++ unsigned long flags;
+
+ if (from_kernel)
+ {
+@@ -1685,6 +1686,7 @@
+ sprintf (buf + len, " minLv: \t %8d\n",
+ ifx_mps_dev.voice_mb[i].upstrm_fifo->min_space);
+ }
++
+ return len;
+ }
+
+@@ -2291,9 +2293,11 @@
+ return result;
+ }
+
++#if !defined(CONFIG_LANTIQ)
++ /** \todo This is handled already with request_irq, remove */
+ /* Enable all MPS Interrupts at ICU0 */
+ MPS_INTERRUPTS_ENABLE (0x0000FF80);
+-
++#endif
+ /* enable mailbox interrupts */
+ ifx_mps_enable_mailbox_int ();
+ /* init FW ready event */
+@@ -2421,9 +2425,11 @@
+ /* disable mailbox interrupts */
+ ifx_mps_disable_mailbox_int ();
+
++#if !defined(CONFIG_LANTIQ)
+ /* disable Interrupts at ICU0 */
+- MPS_INTERRUPTS_DISABLE (DANUBE_MPS_AD0_IR4); /* Disable DFE/AFE 0 Interrupts
+- */
++ /* Disable DFE/AFE 0 Interrupts*/
++ MPS_INTERRUPTS_DISABLE (DANUBE_MPS_AD0_IR4);
++#endif
+
+ /* disable all MPS interrupts */
+ ifx_mps_disable_all_int ();
+--- a/src/drv_vmmc_ioctl.c
++++ b/src/drv_vmmc_ioctl.c
+@@ -18,6 +18,7 @@
+ /* Includes */
+ /* ============================= */
+ #include "drv_api.h"
++#include "drv_vmmc_init.h"
+ #include "drv_vmmc_api.h"
+ #include "drv_vmmc_bbd.h"
+
diff --git a/package/ltq-vmmc/patches/400-falcon.patch b/package/ltq-vmmc/patches/400-falcon.patch
new file mode 100644
index 000000000..490d6e5dc
--- /dev/null
+++ b/package/ltq-vmmc/patches/400-falcon.patch
@@ -0,0 +1,968 @@
+--- a/configure.in
++++ b/configure.in
+@@ -956,14 +956,15 @@ AC_DEFINE([VMMC],[1],[enable VMMC suppor
+ AM_CONDITIONAL(DANUBE, false)
+ AM_CONDITIONAL(AR9, false)
+ AM_CONDITIONAL(VR9, false)
++AM_CONDITIONAL(FALCON, false)
+ AC_ARG_WITH(device,
+ AC_HELP_STRING(
+- [--with-device=DANUBE|TWINPASS|AR9|VR9],
++ [--with-device=DANUBE|TWINPASS|AR9|VR9|FALCON],
+ [Set device type, default is DANUBE]
+ ),
+ [
+ if test "$withval" = yes; then
+- AC_MSG_ERROR([Set device type! Valid choices are DANUBE|TWINPASS|AR9|VR9]);
++ AC_MSG_ERROR([Set device type! Valid choices are DANUBE|TWINPASS|AR9|VR9|FALCON]);
+ else
+ case $withval in
+ DANUBE)
+@@ -986,8 +987,13 @@ AC_ARG_WITH(device,
+ AC_DEFINE([SYSTEM_VR9],[1],[enable VR9 specific code])
+ AM_CONDITIONAL(VR9, true)
+ ;;
++ FALCON)
++ AC_MSG_RESULT(FALCON device is used);
++ AC_DEFINE([SYSTEM_FALCON],[1],[enable FALCON specific code])
++ AM_CONDITIONAL(FALCON, true)
++ ;;
+ *)
+- AC_MSG_ERROR([Set device type! Valid choices are DANUBE|TWINPASS|AR9|VR9]);
++ AC_MSG_ERROR([Set device type! Valid choices are DANUBE|TWINPASS|AR9|VR9|FALCON]);
+ ;;
+ esac
+ fi
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -70,6 +70,11 @@ drv_vmmc_SOURCES +=\
+ mps/drv_mps_vmmc_ar9.c
+ endif
+
++if FALCON
++drv_vmmc_SOURCES +=\
++ mps/drv_mps_vmmc_falcon.c
++endif
++
+ endif
+
+ if PMC_SUPPORT
+--- a/drv_version.h
++++ b/drv_version.h
+@@ -36,6 +36,10 @@
+ #define MIN_FW_MAJORSTEP 2
+ #define MIN_FW_MINORSTEP 1
+ #define MIN_FW_HOTFIXSTEP 0
++#elif defined(SYSTEM_FALCON)
++#define MIN_FW_MAJORSTEP 0
++#define MIN_FW_MINORSTEP 1
++#define MIN_FW_HOTFIXSTEP 0
+ #else
+ #error unknown system
+ #endif
+--- a/src/drv_vmmc_bbd.c
++++ b/src/drv_vmmc_bbd.c
+@@ -34,6 +34,7 @@
+ #define VMMC_WL_SDD_BASIC_CFG 0x04000400
+ #define VMMC_WL_SDD_RING_CFG 0x04000500
+ #define VMMC_WL_SDD_DCDC_CFG 0x04000C00
++#define VMMC_WL_SDD_MWI_CFG 0x04000600
+
+ #define IDLE_EXT_TOGGLE_SLEEP_MS 5
+
+@@ -52,6 +53,8 @@
+ #define BBD_VMMC_MAGIC 0x41523921 /* "AR9" */
+ #elif defined(SYSTEM_VR9)
+ #define BBD_VMMC_MAGIC 0x56523921 /* "VR9" */
++#elif defined(SYSTEM_FALCON)
++#define BBD_VMMC_MAGIC 0x46414C43 /* "FALC" */
+ #else
+ #error system undefined
+ #endif
+@@ -525,9 +528,6 @@ static IFX_int32_t VMMC_BBD_BlockHandler
+ IFX_uint16_t slic_val;
+ IFX_int32_t ret = IFX_SUCCESS;
+
+- TRACE(VMMC, DBG_LEVEL_LOW,
+- ("bbd block with tag 0x%04X passed\n", pBBDblock->tag));
+-
+ /* for FXO line allowed blocks are FXO_CRAM and TRANSPARENT */
+ if (pCh->pALM->line_type_fxs != IFX_TRUE)
+ {
+@@ -686,6 +686,7 @@ static IFX_int32_t VMMC_BBD_BlockHandler
+ break;
+ }
+ } /* if */
++
+ return ret;
+ }
+
+@@ -1026,6 +1027,7 @@ static IFX_int32_t vmmc_BBD_WhiteListedC
+ }
+ case VMMC_WL_SDD_RING_CFG:
+ case VMMC_WL_SDD_DCDC_CFG:
++ case VMMC_WL_SDD_MWI_CFG:
+ ret = CmdWrite (pCh->pParent, Msg.val, Msg.cmd.LENGTH);
+ break;
+
+@@ -1068,7 +1070,7 @@ static IFX_int32_t vmmc_BBD_DownloadChCr
+ IFX_uint32_t countWords;
+ IFX_uint32_t posBytes = 0;
+ IFX_uint8_t lenBytes, *pByte;
+-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9)
++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON)
+ IFX_uint8_t padBytes = 0;
+ #endif
+ IFX_uint16_t cram_offset, cram_crc,
+@@ -1088,7 +1090,7 @@ static IFX_int32_t vmmc_BBD_DownloadChCr
+ #ifdef SYSTEM_DANUBE
+ /* CMD1 is a COP command */
+ pCmd[0] = (0x0200) | (pCh->nChannel - 1);
+-#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9)
++#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON)
+ /* SDD_Coef command */
+ pCmd[0] = (0x0400) | (pCh->nChannel - 1);
+ pCmd[1] = (0x0D00);
+@@ -1111,7 +1113,7 @@ static IFX_int32_t vmmc_BBD_DownloadChCr
+ pCmd[1] = ((cram_offset + (posBytes >> 1)) << 8);
+ /* set CRAM data while taking care of endianess */
+ cpb2w (&pCmd[2], &pByte[posBytes], lenBytes);
+-#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9)
++#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON)
+ /* calculate length to download (in words = 16bit),
+ maximum allowed length for this message is 56 Bytes = 28 Words */
+ if (countWords > ((MAX_CMD_WORD - CMD_HDR_CNT - 1)))
+@@ -1140,7 +1142,7 @@ static IFX_int32_t vmmc_BBD_DownloadChCr
+ /* write Data */
+ #if defined SYSTEM_DANUBE
+ ret = CmdWrite (pCh->pParent, (IFX_uint32_t *) pCmd, lenBytes);
+-#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9)
++#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON)
+ #if 1
+ /* lenBytes + 2 bytes for block offset/length which are not calculated
+ in the download progress */
+--- a/src/mps/drv_mps_version.h
++++ b/src/mps/drv_mps_version.h
+@@ -17,7 +17,7 @@
+ #define VERSIONSTEP 2
+ #define VERS_TYPE 5
+
+-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9)
++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON)
+ #define IFX_MPS_PLATFORM_NAME "MIPS34KEc"
+ #elif defined(SYSTEM_DANUBE)
+ #define IFX_MPS_PLATFORM_NAME "MIPS24KEc"
+--- a/src/mps/drv_mps_vmmc_linux.c
++++ b/src/mps/drv_mps_vmmc_linux.c
+@@ -2225,7 +2225,7 @@ IFX_int32_t __init ifx_mps_init_module (
+ #if defined(CONFIG_MIPS) && !defined(CONFIG_MIPS_UNCACHED)
+ #if defined(SYSTEM_DANUBE)
+ bDoCacheOps = IFX_TRUE; /* on Danube always perform cache ops */
+-#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9)
++#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON)
+ /* on AR9/VR9 cache is configured by BSP;
+ here we check whether the D-cache is shared or partitioned;
+ 1) in case of shared D-cache all cache operations are omitted;
+@@ -2255,7 +2255,8 @@ IFX_int32_t __init ifx_mps_init_module (
+
+ /* reset the device before initializing the device driver */
+ ifx_mps_reset ();
+- result = request_irq (INT_NUM_IM4_IRL18,
++
++ result = request_irq (INT_NUM_IM4_IRL18,
+ #ifdef LINUX_2_6
+ ifx_mps_ad0_irq, IRQF_DISABLED
+ #else /* */
+@@ -2396,7 +2397,7 @@ IFX_int32_t __init ifx_mps_init_module (
+ if (result = ifx_mps_init_gpt_danube ())
+ return result;
+ #endif /*DANUBE*/
+- TRACE (MPS, DBG_LEVEL_HIGH, ("Downloading Firmware...\n"));
++ TRACE (MPS, DBG_LEVEL_HIGH, ("Downloading Firmware...\n"));
+ ifx_mps_download_firmware (IFX_NULL, (mps_fw *) 0xa0a00000);
+ udelay (500);
+ TRACE (MPS, DBG_LEVEL_HIGH, ("Providing Buffers...\n"));
+--- /dev/null
++++ b/src/mps/drv_mps_vmmc_falcon.c
+@@ -0,0 +1,463 @@
++/******************************************************************************
++
++ Copyright (c) 2009
++ Lantiq Deutschland GmbH
++ Am Campeon 3; 85579 Neubiberg, Germany
++
++ For licensing information, see the file 'LICENSE' in the root folder of
++ this software module.
++
++****************************************************************************
++ Module : drv_mps_vmmc_falcon.c
++ Description : This file contains the implementation of the FALC-ON specific
++ driver functions.
++*******************************************************************************/
++
++/* ============================= */
++/* Includes */
++/* ============================= */
++#include "drv_config.h"
++
++#if defined(SYSTEM_FALCON) /* defined in drv_config.h */
++
++/* lib_ifxos headers */
++#include "ifx_types.h"
++#include "ifxos_linux_drv.h"
++#include "ifxos_copy_user_space.h"
++#include "ifxos_event.h"
++#include "ifxos_lock.h"
++#include "ifxos_select.h"
++#include "ifxos_interrupt.h"
++#include <linux/gpio.h>
++#include <sys1_reg.h>
++#include <falcon.h>
++#include <falcon_irq.h>
++#include <vpe.h>
++#include <sysctrl.h>
++void (*ifx_bsp_basic_mps_decrypt)(unsigned int addr, int n) = (void (*)(unsigned int, int))0xbf000290;
++
++#define IFX_MPS_SRAM IFXMIPS_MPS_SRAM
++
++/*#define USE_PLAIN_VOICE_FIRMWARE*/
++/* board specific headers */
++
++/* device specific headers */
++#include "drv_mps_vmmc.h"
++#include "drv_mps_vmmc_dbg.h"
++#include "drv_mps_vmmc_device.h"
++
++/* ============================= */
++/* Local Macros & Definitions */
++/* ============================= */
++/* Firmware watchdog timer counter address */
++#define VPE1_WDOG_CTR_ADDR ((IFX_uint32_t)((IFX_uint8_t* )IFX_MPS_SRAM + 432))
++
++/* Firmware watchdog timeout range, values in ms */
++#define VPE1_WDOG_TMOUT_MIN 20
++#define VPE1_WDOG_TMOUT_MAX 5000
++
++/* ============================= */
++/* Global variable definition */
++/* ============================= */
++extern mps_comm_dev *pMPSDev;
++
++/* ============================= */
++/* Global function declaration */
++/* ============================= */
++IFX_void_t ifx_mps_release (IFX_void_t);
++extern IFX_uint32_t ifx_mps_reset_structures (mps_comm_dev * pMPSDev);
++extern IFX_int32_t ifx_mps_bufman_close (IFX_void_t);
++IFX_int32_t ifx_mps_wdog_callback (IFX_uint32_t wdog_cleared_ok_count);
++extern IFXOS_event_t fw_ready_evt;
++/* ============================= */
++/* Local function declaration */
++/* ============================= */
++static IFX_int32_t ifx_mps_fw_wdog_start_ar9(IFX_void_t);
++
++/* ============================= */
++/* Local variable definition */
++/* ============================= */
++static IFX_int32_t vpe1_started = 0;
++/* VMMC watchdog timer callback */
++IFX_int32_t (*ifx_wdog_callback) (IFX_uint32_t flags) = IFX_NULL;
++
++/* ============================= */
++/* Local function definition */
++/* ============================= */
++
++/******************************************************************************
++ * AR9 Specific Routines
++ ******************************************************************************/
++
++/**
++ * Start AR9 EDSP firmware watchdog mechanism.
++ * Called after download and startup of VPE1.
++ *
++ * \param none
++ * \return 0 IFX_SUCCESS
++ * \return -1 IFX_ERROR
++ * \ingroup Internal
++ */
++IFX_int32_t ifx_mps_fw_wdog_start_ar9()
++{
++ return IFX_SUCCESS;
++}
++
++/**
++ * Firmware download to Voice CPU
++ * This function performs a firmware download to the coprocessor.
++ *
++ * \param pMBDev Pointer to mailbox device structure
++ * \param pFWDwnld Pointer to firmware structure
++ * \return 0 IFX_SUCCESS, firmware ready
++ * \return -1 IFX_ERROR, firmware not downloaded.
++ * \ingroup Internal
++ */
++IFX_int32_t ifx_mps_download_firmware (mps_mbx_dev *pMBDev, mps_fw *pFWDwnld)
++{
++ IFX_uint32_t mem, cksum;
++ IFX_uint8_t crc;
++ IFX_boolean_t bMemReqNotPresent = IFX_FALSE;
++
++ /* VCC register */
++ /* dummy accesss on GTC for GPONC-55, otherwise upper bits are random on read */
++ ltq_r32 ((u32 *)((KSEG1 | 0x1DC000B0)));
++ /* NTR Frequency Select 1536 kHz per default or take existing,
++ NTR Output Enable and NTR8K Output Enable */
++ if ((ltq_r32 ((u32 *)(GPON_SYS_BASE + 0xBC)) & 7) == 0)
++ ltq_w32_mask (0x10187, 0x183, (u32 *)(GPON_SYS_BASE + 0xBC));
++ else
++ ltq_w32_mask (0x10180, 0x180, (u32 *)(GPON_SYS_BASE + 0xBC));
++#if 0
++ /* BIU-ICU1-IM1_ISR - IM1:FSCT_CMP1=1 and FSC_ROOT=1
++ (0x1f880328 = 0x00002800) */
++ ltq_w32 (0x00002800, (u32 *)(GPON_ICU1_BASE + 0x30));
++#endif
++ /* copy FW footer from user space */
++ if (IFX_NULL == IFXOS_CpyFromUser(pFW_img_data,
++ pFWDwnld->data+pFWDwnld->length/4-sizeof(*pFW_img_data)/4,
++ sizeof(*pFW_img_data)))
++ {
++ TRACE (MPS, DBG_LEVEL_HIGH,
++ (KERN_ERR "[%s %s %d]: copy_from_user error\r\n",
++ __FILE__, __func__, __LINE__));
++ return IFX_ERROR;
++ }
++
++ mem = pFW_img_data->mem;
++
++ /* memory requirement sanity check */
++ if ((crc = ~((mem >> 16) + (mem >> 8) + mem)) != (mem >> 24))
++ {
++ TRACE (MPS, DBG_LEVEL_HIGH,
++ ("[%s %s %d]: warning, image does not contain size - assuming 1MB!\n",
++ __FILE__, __func__, __LINE__));
++ mem = 1 * 1024 * 1024;
++ bMemReqNotPresent = IFX_TRUE;
++ }
++ else
++ {
++ mem &= 0x00FFFFFF;
++ }
++
++ /* check if FW image fits in available memory space */
++ if (mem > vpe1_get_max_mem(0))
++ {
++ TRACE (MPS, DBG_LEVEL_HIGH,
++ ("[%s %s %d]: error, firmware memory exceeds reserved space (%i > %i)!\n",
++ __FILE__, __func__, __LINE__, mem, vpe1_get_max_mem(0)));
++ return IFX_ERROR;
++ }
++
++ /* reset the driver */
++ ifx_mps_reset ();
++
++ /* call BSP to get cpu1 base address */
++ cpu1_base_addr = (IFX_uint32_t *)vpe1_get_load_addr(0);
++
++ /* check if CPU1 base address is sane
++ \todo: check if address is 1MB aligned,
++ also make it visible in a /proc fs */
++ if (!cpu1_base_addr)
++ {
++ TRACE (MPS, DBG_LEVEL_HIGH,
++ (KERN_ERR "IFX_MPS: CPU1 base address is invalid!\r\n"));
++ return IFX_ERROR;
++ }
++ /* further use uncached value */
++ cpu1_base_addr = (IFX_uint32_t *)KSEG1ADDR(cpu1_base_addr);
++
++ /* free all data buffers that might be currently used by FW */
++ if (IFX_NULL != ifx_mps_bufman_freeall)
++ {
++ ifx_mps_bufman_freeall();
++ }
++
++ if(FW_FORMAT_NEW)
++ {
++ /* adjust download length */
++ pFWDwnld->length -= (sizeof(*pFW_img_data)-sizeof(IFX_uint32_t));
++ }
++ else
++ {
++ pFWDwnld->length -= sizeof(IFX_uint32_t);
++
++ /* handle unlikely case if FW image does not contain memory requirement -
++ assumed for old format only */
++ if (IFX_TRUE == bMemReqNotPresent)
++ pFWDwnld->length += sizeof(IFX_uint32_t);
++
++ /* in case of old FW format always assume that FW is encrypted;
++ use compile switch USE_PLAIN_VOICE_FIRMWARE for plain FW */
++#ifndef USE_PLAIN_VOICE_FIRMWARE
++ pFW_img_data->enc = 1;
++#else
++#warning Using unencrypted firmware!
++ pFW_img_data->enc = 0;
++#endif /* USE_PLAIN_VOICE_FIRMWARE */
++ /* initializations for the old format */
++ pFW_img_data->st_addr_crc = 2*sizeof(IFX_uint32_t) +
++ FW_AR9_OLD_FMT_XCPT_AREA_SZ;
++ pFW_img_data->en_addr_crc = pFWDwnld->length;
++ pFW_img_data->fw_vers = 0;
++ pFW_img_data->magic = 0;
++ }
++
++ /* copy FW image to base address of CPU1 */
++ if (IFX_NULL ==
++ IFXOS_CpyFromUser ((IFX_void_t *)cpu1_base_addr,
++ (IFX_void_t *)pFWDwnld->data, pFWDwnld->length))
++ {
++ TRACE (MPS, DBG_LEVEL_HIGH,
++ (KERN_ERR "[%s %s %d]: copy_from_user error\r\n", __FILE__,
++ __func__, __LINE__));
++ return IFX_ERROR;
++ }
++
++ /* process firmware decryption */
++ if (pFW_img_data->enc == 1)
++ {
++ if(FW_FORMAT_NEW)
++ {
++ /* adjust decryption length (avoid decrypting CRC32 checksum) */
++ pFWDwnld->length -= sizeof(IFX_uint32_t);
++ }
++ /* BootROM actually decrypts n+4 bytes if n bytes were passed for
++ decryption. Subtract sizeof(u32) from length to avoid decryption
++ of data beyond the FW image code */
++ pFWDwnld->length -= sizeof(IFX_uint32_t);
++ ifx_bsp_basic_mps_decrypt((unsigned int)cpu1_base_addr, pFWDwnld->length);
++ }
++
++ /* calculate CRC32 checksum over downloaded image */
++ cksum = ifx_mps_fw_crc32(cpu1_base_addr, pFW_img_data);
++
++ /* verify the checksum */
++ if(FW_FORMAT_NEW)
++ {
++ if (cksum != pFW_img_data->crc32)
++ {
++ TRACE (MPS, DBG_LEVEL_HIGH,
++ ("MPS: FW checksum error: img=0x%08x calc=0x%08x\r\n",
++ pFW_img_data->crc32, cksum));
++ /*return IFX_ERROR;*/
++ }
++ }
++ else
++ {
++ /* just store self-calculated checksum */
++ pFW_img_data->crc32 = cksum;
++ }
++
++ /* start VPE1 */
++ ifx_mps_release ();
++#if 0
++ /* start FW watchdog mechanism */
++ ifx_mps_fw_wdog_start_ar9();
++#endif
++ /* get FW version */
++ return ifx_mps_get_fw_version (0);
++}
++
++
++/**
++ * Restart CPU1
++ * This function restarts CPU1 by accessing the reset request register and
++ * reinitializes the mailbox.
++ *
++ * \return 0 IFX_SUCCESS, successful restart
++ * \return -1 IFX_ERROR, if reset failed
++ * \ingroup Internal
++ */
++IFX_int32_t ifx_mps_restart (IFX_void_t)
++{
++ /* raise reset request for CPU1 and reset driver structures */
++ ifx_mps_reset ();
++ /* Disable GPTC Interrupt to CPU1 */
++ ifx_mps_shutdown_gpt ();
++ /* re-configure GPTC */
++ ifx_mps_init_gpt ();
++ /* let CPU1 run */
++ ifx_mps_release ();
++ /* start FW watchdog mechanism */
++ ifx_mps_fw_wdog_start_ar9();
++ TRACE (MPS, DBG_LEVEL_HIGH, ("IFX_MPS: Restarting firmware..."));
++ return ifx_mps_get_fw_version (0);
++}
++
++/**
++ * Shutdown MPS - stop VPE1
++ * This function stops VPE1
++ *
++ * \ingroup Internal
++ */
++IFX_void_t ifx_mps_shutdown (IFX_void_t)
++{
++ if (vpe1_started)
++ {
++ /* stop software watchdog timer */
++ vpe1_sw_wdog_stop (0);
++ /* clean up the BSP callback function */
++ vpe1_sw_wdog_register_reset_handler (IFX_NULL);
++ /* stop VPE1 */
++ vpe1_sw_stop (0);
++ vpe1_started = 0;
++ }
++ /* free GPTC */
++ ifx_mps_shutdown_gpt ();
++}
++
++/**
++ * Reset CPU1
++ * This function causes a reset of CPU1 by clearing the CPU0 boot ready bit
++ * in the reset request register RCU_RST_REQ.
++ * It does not change the boot configuration registers for CPU0 or CPU1.
++ *
++ * \return 0 IFX_SUCCESS, cannot fail
++ * \ingroup Internal
++ */
++IFX_void_t ifx_mps_reset (IFX_void_t)
++{
++ /* if VPE1 is already started, stop it */
++ if (vpe1_started)
++ {
++ /* stop software watchdog timer first */
++ vpe1_sw_wdog_stop (0);
++ vpe1_sw_stop (0);
++ vpe1_started = 0;
++ }
++
++ /* reset driver */
++ ifx_mps_reset_structures (pMPSDev);
++ ifx_mps_bufman_close ();
++ return;
++}
++
++/**
++ * Let CPU1 run
++ * This function starts VPE1
++ *
++ * \return none
++ * \ingroup Internal
++ */
++IFX_void_t ifx_mps_release (IFX_void_t)
++{
++ IFX_int_t ret;
++ IFX_int32_t RetCode = 0;
++
++ /* Start VPE1 */
++ if (IFX_SUCCESS !=
++ vpe1_sw_start ((IFX_void_t *)cpu1_base_addr, 0, 0))
++ {
++ TRACE (MPS, DBG_LEVEL_HIGH, (KERN_ERR "Error starting VPE1\r\n"));
++ return;
++ }
++ vpe1_started = 1;
++
++ /* sleep 3 seconds until FW is ready */
++ ret = IFXOS_EventWait (&fw_ready_evt, 3000, &RetCode);
++ if ((ret == IFX_ERROR) && (RetCode == 1))
++ {
++ /* timeout */
++ TRACE (MPS, DBG_LEVEL_HIGH,
++ (KERN_ERR "[%s %s %d]: Timeout waiting for firmware ready.\r\n",
++ __FILE__, __func__, __LINE__));
++ /* recalculate and compare the firmware checksum */
++ ifx_mps_fw_crc_compare(cpu1_base_addr, pFW_img_data);
++ /* dump exception area on a console */
++ ifx_mps_dump_fw_xcpt(cpu1_base_addr, pFW_img_data);
++ }
++}
++
++/**
++ * WDT callback.
++ * This function is called by BSP (module softdog_vpe) in case if software
++ * watchdog timer expiration is detected by BSP.
++ * This function needs to be registered at BSP as WDT callback using
++ * vpe1_sw_wdog_register_reset_handler() API.
++ *
++ * \return 0 IFX_SUCCESS, cannot fail
++ * \ingroup Internal
++ */
++IFX_int32_t ifx_mps_wdog_callback (IFX_uint32_t wdog_cleared_ok_count)
++{
++#ifdef DEBUG
++ TRACE (MPS, DBG_LEVEL_HIGH,
++ ("MPS: watchdog callback! arg=0x%08x\r\n", wdog_cleared_ok_count));
++#endif /* DEBUG */
++
++ /* reset SmartSLIC is done by FW */
++ /* recalculate and compare the firmware checksum */
++ ifx_mps_fw_crc_compare(cpu1_base_addr, pFW_img_data);
++
++ /* dump exception area on a console */
++ ifx_mps_dump_fw_xcpt(cpu1_base_addr, pFW_img_data);
++
++ if (IFX_NULL != ifx_wdog_callback)
++ {
++ /* call VMMC driver */
++ ifx_wdog_callback (wdog_cleared_ok_count);
++ }
++ else
++ {
++ TRACE (MPS, DBG_LEVEL_HIGH,
++ (KERN_WARNING "MPS: VMMC watchdog timer callback is NULL.\r\n"));
++ }
++ return 0;
++}
++
++/**
++ * Register WDT callback.
++ * This function is called by VMMC driver to register its callback in
++ * the MPS driver.
++ *
++ * \return 0 IFX_SUCCESS, cannot fail
++ * \ingroup Internal
++ */
++IFX_int32_t
++ifx_mps_register_wdog_callback (IFX_int32_t (*pfn) (IFX_uint32_t flags))
++{
++ ifx_wdog_callback = pfn;
++ return 0;
++}
++
++/**
++ Hardware setup on FALC ON
++*/
++void sys_hw_setup (void)
++{
++ /* Set INFRAC register bit 1: clock enable of the GPE primary clock. */
++ sys_gpe_hw_activate (0);
++ /* enable 1.5 V */
++ ltq_w32_mask (0xf, 0x0b, (u32 *)(GPON_SYS1_BASE | 0xbc));
++ /* SYS1-CLKEN:GPTC = 1 and MPS, no longer FSCT = 1 */
++ sys1_hw_activate (ACTS_MPS | ACTS_GPTC);
++ /* GPTC:CLC:RMC = 1 */
++ ltq_w32 (0x00000100, (u32 *)(KSEG1 | 0x1E100E00));
++}
++
++#ifndef VMMC_WITH_MPS
++EXPORT_SYMBOL (ifx_mps_register_wdog_callback);
++#endif /* !VMMC_WITH_MPS */
++
++#endif /* SYSTEM_FALCON */
+--- a/src/mps/drv_mps_vmmc_common.c
++++ b/src/mps/drv_mps_vmmc_common.c
+@@ -66,6 +66,10 @@ static void inline bsp_mask_and_ack_irq(
+ # include <asm/ifx/ifx_regs.h>
+ # include <asm/ifx/ifx_gptu.h>
+ #endif
++#if defined(SYSTEM_FALCON)
++#include <sys1_reg.h>
++#include <sysctrl.h>
++#endif
+
+ #include "drv_mps_vmmc.h"
+ #include "drv_mps_vmmc_dbg.h"
+@@ -1156,7 +1160,12 @@ IFX_uint32_t ifx_mps_init_structures (mp
+ mailbox, * upstream and downstream direction. */
+ memset (
+ /* avoid to overwrite CPU boot registers */
++#if defined(SYSTEM_FALCON)
++ (IFX_void_t *) MBX_Memory +
++ 2 * sizeof (mps_boot_cfg_reg),
++#else
+ (IFX_void_t *) MBX_Memory,
++#endif
+ 0,
+ sizeof (mps_mbx_reg) - 2 * sizeof (mps_boot_cfg_reg));
+ MBX_Memory->MBX_UPSTR_CMD_BASE =
+@@ -2651,7 +2660,6 @@ IFX_void_t ifx_mps_enable_mailbox_int ()
+ #endif
+
+ *IFX_MPS_AD0ENR = Ad0Reg.val;
+-
+ }
+
+ /**
+@@ -2669,6 +2677,7 @@ IFX_void_t ifx_mps_disable_mailbox_int (
+ Ad0Reg.fld.cu_mbx = 0;
+ Ad0Reg.fld.du_mbx = 0;
+ *IFX_MPS_AD0ENR = Ad0Reg.val;
++
+ }
+
+ /**
+@@ -2766,11 +2775,13 @@ irqreturn_t ifx_mps_ad0_irq (IFX_int32_t
+ /* handle only enabled interrupts */
+ MPS_Ad0StatusReg.val &= *IFX_MPS_AD0ENR;
+
++#if !defined(SYSTEM_FALCON)
+ #ifdef LINUX_2_6
+ bsp_mask_and_ack_irq (irq);
+ #else /* */
+ mask_and_ack_danube_irq (irq);
+ #endif /* */
++#endif /* !defined(SYSTEM_FALCON) */
+ /* FW is up and ready to process commands */
+ if (MPS_Ad0StatusReg.fld.dl_end)
+ {
+@@ -2919,11 +2930,13 @@ irqreturn_t ifx_mps_ad1_irq (IFX_int32_t
+ /* handle only enabled interrupts */
+ MPS_Ad1StatusReg.val &= *IFX_MPS_AD1ENR;
+
++#if !defined(SYSTEM_FALCON)
+ #ifdef LINUX_2_6
+ bsp_mask_and_ack_irq (irq);
+ #else /* */
+ mask_and_ack_danube_irq (irq);
+ #endif /* */
++#endif /* !defined(SYSTEM_FALCON) */
+ pMPSDev->event.MPS_Ad1Reg.val = MPS_Ad1StatusReg.val;
+
+ /* use callback function or queue wake up to notify about data reception */
+@@ -2977,11 +2990,13 @@ irqreturn_t ifx_mps_vc_irq (IFX_int32_t
+ IFX_MPS_CVC0SR[chan] = MPS_VCStatusReg.val;
+ /* handle only enabled interrupts */
+ MPS_VCStatusReg.val &= IFX_MPS_VC0ENR[chan];
++#if !defined(SYSTEM_FALCON)
+ #ifdef LINUX_2_6
+ bsp_mask_and_ack_irq (irq);
+ #else /* */
+ mask_and_ack_danube_irq (irq);
+ #endif /* */
++#endif /* !defined(SYSTEM_FALCON) */
+
+ pMPSDev->event.MPS_VCStatReg[chan].val = MPS_VCStatusReg.val;
+ #ifdef PRINT_ON_ERR_INTERRUPT
+@@ -3126,6 +3141,7 @@ IFX_int32_t ifx_mps_get_fw_version (IFX_
+ */
+ IFX_return_t ifx_mps_init_gpt ()
+ {
++#if !defined(SYSTEM_FALCON)
+ unsigned long flags;
+ IFX_uint32_t timer_flags, timer, loops = 0;
+ IFX_ulong_t count;
+@@ -3134,7 +3150,11 @@ IFX_return_t ifx_mps_init_gpt ()
+ #else /* Danube */
+ timer = TIMER1B;
+ #endif /* SYSTEM_AR9 || SYSTEM_VR9 */
++#endif
+
++#if defined(SYSTEM_FALCON)
++ sys_hw_setup ();
++#else
+ /* calibration loop - required to syncronize GPTC interrupt with falling
+ edge of FSC clock */
+ timer_flags =
+@@ -3179,7 +3199,7 @@ Probably already in use.\r\n", __FILE__,
+ #endif /* DEBUG */
+
+ IFXOS_UNLOCKINT (flags);
+-
++#endif
+ return IFX_SUCCESS;
+ }
+
+@@ -3194,6 +3214,9 @@ Probably already in use.\r\n", __FILE__,
+ */
+ IFX_void_t ifx_mps_shutdown_gpt (IFX_void_t)
+ {
++#if defined(SYSTEM_FALCON)
++ sys1_hw_deactivate (ACTS_MPS);
++#else
+ IFX_uint32_t timer;
+ #if defined(SYSTEM_AR9) || defined(SYSTEM_VR9)
+ timer = TIMER1A;
+@@ -3202,6 +3225,7 @@ IFX_void_t ifx_mps_shutdown_gpt (IFX_voi
+ #endif /* SYSTEM_AR9 || SYSTEM_VR9 */
+
+ ifx_gptu_timer_free (timer);
++#endif
+ }
+
+ /**
+--- a/src/mps/drv_mps_vmmc_device.h
++++ b/src/mps/drv_mps_vmmc_device.h
+@@ -22,7 +22,12 @@
+ # include <lantiq_soc.h>
+ # include <gpio.h>
+ #define IFXMIPS_MPS_SRAM ((u32 *)(KSEG1 + 0x1F200000))
++#if defined(SYSTEM_FALCON)
++#define IFXMIPS_MPS_BASE_ADDR (KSEG1 + 0x1D004000)
++#else
+ #define IFXMIPS_MPS_BASE_ADDR (KSEG1 + 0x1F107000)
++#endif
++
+ #define IFXMIPS_MPS_CHIPID ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0344))
+ #define IFXMIPS_MPS_VC0ENR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0000))
+ #define IFXMIPS_MPS_RVC0SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0010))
+@@ -73,10 +78,11 @@
+ /* MPS Common defines */
+ /* ============================= */
+
+-#define MPS_BASEADDRESS 0xBF107000
+-#define MPS_RAD0SR MPS_BASEADDRESS + 0x0004
+-
++#if defined(SYSTEM_FALCON)
++#define MBX_BASEADDRESS 0xBF200040
++#else
+ #define MBX_BASEADDRESS 0xBF200000
++#endif
+ #define VCPU_BASEADDRESS 0xBF208000 /* 0xBF108000 */
+ /*---------------------------------------------------------------------------*/
+ #if !defined(CONFIG_LANTIQ)
+@@ -118,7 +124,6 @@
+ /*---------------------------------------------------------------------------*/
+
+ #ifdef CONFIG_MPS_EVENT_MBX
+-
+ #define MBX_CMD_FIFO_SIZE 64 /**< Size of command FIFO in bytes */
+ #define MBX_DATA_UPSTRM_FIFO_SIZE 64
+ #define MBX_DATA_DNSTRM_FIFO_SIZE 128
+@@ -294,6 +299,10 @@ typedef struct
+ #ifdef CONFIG_MPS_EVENT_MBX
+ typedef struct
+ {
++#if defined(SYSTEM_FALCON)
++ mps_boot_cfg_reg MBX_CPU0_BOOT_CFG; /**< CPU0 Boot Configuration */
++ mps_boot_cfg_reg MBX_CPU1_BOOT_CFG; /**< CPU1 Boot Configuration */
++#endif
+ volatile IFX_uint32_t *MBX_UPSTR_CMD_BASE; /**< Upstream Command FIFO Base Address */
+ volatile IFX_uint32_t MBX_UPSTR_CMD_SIZE; /**< Upstream Command FIFO size in byte */
+ volatile IFX_uint32_t *MBX_DNSTR_CMD_BASE; /**< Downstream Command FIFO Base Address */
+@@ -317,13 +326,19 @@ typedef struct
+ volatile IFX_uint32_t MBX_UPSTR_EVENT_WRITE; /**< Upstream Event FIFO Write Index */
+ volatile IFX_uint32_t MBX_EVENT[MBX_EVENT_DATA_WORDS];
+ volatile IFX_uint32_t reserved[4];
++#if !defined(SYSTEM_FALCON)
+ mps_boot_cfg_reg MBX_CPU0_BOOT_CFG; /**< CPU0 Boot Configuration */
+ mps_boot_cfg_reg MBX_CPU1_BOOT_CFG; /**< CPU1 Boot Configuration */
++#endif
+ } mps_mbx_reg;
+
+ #else /* */
+ typedef struct
+ {
++#if defined(SYSTEM_FALCON)
++ mps_boot_cfg_reg MBX_CPU0_BOOT_CFG; /**< CPU0 Boot Configuration */
++ mps_boot_cfg_reg MBX_CPU1_BOOT_CFG; /**< CPU1 Boot Configuration */
++#endif
+ volatile IFX_uint32_t *MBX_UPSTR_CMD_BASE; /**< Upstream Command FIFO Base Address */
+ volatile IFX_uint32_t MBX_UPSTR_CMD_SIZE; /**< Upstream Command FIFO size in byte */
+ volatile IFX_uint32_t *MBX_DNSTR_CMD_BASE; /**< Downstream Command FIFO Base Address */
+@@ -341,8 +356,10 @@ typedef struct
+ volatile IFX_uint32_t MBX_DNSTR_DATA_READ; /**< Downstream Data FIFO Read Index */
+ volatile IFX_uint32_t MBX_DNSTR_DATA_WRITE; /**< Downstream Data FIFO Write Index */
+ volatile IFX_uint32_t MBX_DATA[MBX_DATA_WORDS];
++#if !defined(SYSTEM_FALCON)
+ mps_boot_cfg_reg MBX_CPU0_BOOT_CFG; /**< CPU0 Boot Configuration */
+ mps_boot_cfg_reg MBX_CPU1_BOOT_CFG; /**< CPU1 Boot Configuration */
++#endif
+ } mps_mbx_reg;
+ #endif /* CONFIG_MPS_EVENT_MBX */
+
+--- a/src/drv_api.h
++++ b/src/drv_api.h
+@@ -183,7 +183,7 @@
+ #endif
+
+ /* TAPI FXS Phone Detection feature is not available for Danube platform */
+-#if defined(TAPI_PHONE_DETECTION) && (defined(SYSTEM_AR9) || defined(SYSTEM_VR9))
++#if defined(TAPI_PHONE_DETECTION) && (defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON))
+ #define VMMC_CFG_ADD_FEAT_PHONE_DETECTION VMMC_FEAT_PHONE_DETECTION
+ #else
+ #define VMMC_CFG_ADD_FEAT_PHONE_DETECTION 0
+--- a/src/drv_vmmc_alm.c
++++ b/src/drv_vmmc_alm.c
+@@ -800,7 +800,7 @@ IFX_void_t VMMC_ALM_Free_Ch_Structures (
+ }
+
+
+-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9)
++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON)
+ /**
+ Check whether SmartSLIC is connected
+
+@@ -836,7 +836,7 @@ IFX_boolean_t VMMC_ALM_SmartSLIC_IsConne
+ #endif /*SYSTEM_AR9 || SYSTEM_VR9*/
+
+
+-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9)
++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON)
+ /**
+ Read the number of channels on the SmartSLIC.
+
+@@ -1876,7 +1876,7 @@ IFX_int32_t VMMC_TAPI_LL_ALM_VMMC_Test_L
+ /* write updated message contents */
+ ret = CmdWrite (pDev, (IFX_uint32_t *)((IFX_void_t *)&debugCfg),
+ DCCTL_CMD_LEN);
+-#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9)
++#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON)
+ IFX_uint32_t dcctrlLoop[2];
+ IFX_uint32_t ch = (IFX_uint32_t)(pCh->nChannel - 1);
+
+--- a/src/drv_vmmc_alm.h
++++ b/src/drv_vmmc_alm.h
+@@ -65,7 +65,7 @@ extern IFX_void_t irq_VMMC_ALM_LineDisab
+ extern IFX_void_t VMMC_ALM_CorrectLinemodeCache (VMMC_CHANNEL *pCh,
+ IFX_uint16_t lm);
+
+-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9)
++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON)
+ extern IFX_boolean_t VMMC_ALM_SmartSLIC_IsConnected (
+ VMMC_DEVICE *pDev);
+
+--- a/src/drv_vmmc_init.c
++++ b/src/drv_vmmc_init.c
+@@ -52,15 +52,6 @@
+ #include "ifx_pmu.h"
+ #endif /* PMU_SUPPORTED */
+
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28))
+-# define IFX_MPS_CAD0SR IFXMIPS_MPS_CAD0SR
+-# define IFX_MPS_CAD1SR IFXMIPS_MPS_CAD1SR
+-# define IFX_MPS_CVC0SR IFXMIPS_MPS_CVC0SR
+-# define IFX_MPS_CVC1SR IFXMIPS_MPS_CVC1SR
+-# define IFX_MPS_CVC2SR IFXMIPS_MPS_CVC2SR
+-# define IFX_MPS_CVC3SR IFXMIPS_MPS_CVC3SR
+-#endif
+-
+ /* ============================= */
+ /* Local Macros & Definitions */
+ /* ============================= */
+@@ -820,7 +811,7 @@ static IFX_int32_t VMMC_TAPI_LL_FW_Init(
+ MIN_FW_HOTFIXSTEP};
+ IFX_uint8_t tmp1, tmp2;
+ IFX_TAPI_RESOURCE nResource;
+-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9)
++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON)
+ IFX_uint8_t nChannels, nFXOChannels;
+ #endif /*SYSTEM_AR9 || SYSTEM_VR9*/
+ IFX_int32_t ret = VMMC_statusOk;
+@@ -874,7 +865,7 @@ static IFX_int32_t VMMC_TAPI_LL_FW_Init(
+ pDev->bSmartSlic = IFX_FALSE;
+ pDev->bSlicSupportsIdleMode = IFX_FALSE;
+
+-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9)
++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON)
+ if (VMMC_SUCCESS(ret))
+ {
+ /* Reduce the number of ALM channels in the capabilities if the SLIC
+--- a/src/drv_vmmc_ioctl.c
++++ b/src/drv_vmmc_ioctl.c
+@@ -273,7 +273,7 @@ IFX_int32_t VMMC_Dev_Spec_Ioctl (IFX_TAP
+ case FIO_GET_VERS:
+ {
+ VMMC_IO_VERSION *pVers;
+-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9)
++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON)
+ VMMC_SDD_REVISION_READ_t *pSDDVersCmd = IFX_NULL;
+ #endif /*SYSTEM_AR9 || SYSTEM_VR9*/
+ SYS_VER_t *pCmd;
+@@ -322,7 +322,7 @@ IFX_int32_t VMMC_Dev_Spec_Ioctl (IFX_TAP
+ pVers->nTapiVers = 3;
+ pVers->nDrvVers = MAJORSTEP << 24 | MINORSTEP << 16 |
+ VERSIONSTEP << 8 | VERS_TYPE;
+-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9)
++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON)
+ /* in case of SmartSLIC based systems, we can give some more
+ versions.*/
+ if (VMMC_ALM_SmartSLIC_IsConnected(pDev))
diff --git a/package/lua/Makefile b/package/lua/Makefile
new file mode 100644
index 000000000..96fa57eaa
--- /dev/null
+++ b/package/lua/Makefile
@@ -0,0 +1,178 @@
+#
+# Copyright (C) 2006-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=lua
+PKG_VERSION:=5.1.4
+PKG_RELEASE:=8
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://www.lua.org/ftp/ \
+ http://ftp.gwdg.de/pub/languages/lua/ \
+ http://mirrors.dotsrc.org/lua/ \
+ http://www.tecgraf.puc-rio.br/lua/ftp/
+PKG_MD5SUM:=d0870f2de55d59c1c8419f36e8fac150
+
+HOST_PATCH_DIR := ./patches-host
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/host-build.mk
+
+define Package/lua/Default
+ SUBMENU:=Lua
+ SECTION:=lang
+ CATEGORY:=Languages
+ TITLE:=Lua programming language
+ URL:=http://www.lua.org/
+endef
+
+define Package/lua/Default/description
+ Lua is a powerful light-weight programming language designed for extending
+ applications. Lua is also frequently used as a general-purpose, stand-alone
+ language. Lua is free software.
+endef
+
+define Package/liblua
+$(call Package/lua/Default)
+ SUBMENU:=
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE+= (libraries)
+endef
+
+define Package/liblua/description
+$(call Package/lua/Default/description)
+ This package contains the Lua shared libraries, needed by other programs.
+endef
+
+define Package/lua
+$(call Package/lua/Default)
+ DEPENDS:=+liblua
+ TITLE+= (interpreter)
+endef
+
+define Package/lua/description
+$(call Package/lua/Default/description)
+ This package contains the Lua language interpreter.
+endef
+
+define Package/luac
+$(call Package/lua/Default)
+ DEPENDS:=+liblua
+ TITLE+= (compiler)
+endef
+
+define Package/luac/description
+$(call Package/lua/Default/description)
+ This package contains the Lua language compiler.
+endef
+
+define Package/lua-examples
+$(call Package/lua/Default)
+ DEPENDS:=lua
+ TITLE+= (examples)
+endef
+
+define Package/lua-examples/description
+$(call Package/lua/Default/description)
+ This package contains Lua language examples.
+endef
+
+define Build/Configure
+endef
+
+TARGET_CFLAGS += -DLUA_USE_LINUX $(FPIC) -std=gnu99
+
+ifneq ($(CONFIG_USE_EGLIBC),)
+ ifeq ($(CONFIG_EGLIBC_OPTION_EGLIBC_UTMP),)
+ TARGET_CFLAGS += -DNO_GETLOGIN
+ endif
+endif
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CROSS)gcc" \
+ AR="$(TARGET_CROSS)ar rcu" \
+ RANLIB="$(TARGET_CROSS)ranlib" \
+ INSTALL_ROOT=/usr \
+ CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \
+ MYLDFLAGS="$(TARGET_LDFLAGS)" \
+ PKG_VERSION=$(PKG_VERSION) \
+ linux
+ rm -rf $(PKG_INSTALL_DIR)
+ mkdir -p $(PKG_INSTALL_DIR)
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ INSTALL_TOP="$(PKG_INSTALL_DIR)/usr" \
+ install
+endef
+
+define Host/Configure
+ $(SED) 's,"/usr/local/","$(STAGING_DIR_HOST)/",' $(HOST_BUILD_DIR)/src/luaconf.h
+endef
+
+ifeq ($(HOST_OS),Darwin)
+ LUA_OS:=macosx
+else
+ ifeq ($(HOST_OS),FreeBSD)
+ LUA_OS:=freebsd
+ else
+ LUA_OS:=linux
+ endif
+endif
+
+define Host/Compile
+ $(MAKE) -C $(HOST_BUILD_DIR) \
+ CC="$(HOSTCC) -std=gnu99" \
+ $(LUA_OS)
+endef
+
+define Host/Install
+ $(MAKE) -C $(HOST_BUILD_DIR) \
+ INSTALL_TOP="$(STAGING_DIR_HOST)" \
+ install
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/lua{,lib,conf}.h $(1)/usr/include/
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/lauxlib.h $(1)/usr/include/
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/lnum_config.h $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/liblua.{a,so*} $(1)/usr/lib/
+ ln -sf liblua.so.$(PKG_VERSION) $(1)/usr/lib/liblualib.so
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_BUILD_DIR)/etc/lua.pc $(1)/usr/lib/pkgconfig/
+endef
+
+define Package/liblua/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/liblua.so.* $(1)/usr/lib/
+endef
+
+define Package/lua/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/lua $(1)/usr/bin/
+endef
+
+define Package/luac/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/luac $(1)/usr/bin/
+endef
+
+define Package/lua-examples/install
+ $(INSTALL_DIR) $(1)/usr/share/lua/examples
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/test/*.lua \
+ $(1)/usr/share/lua/examples/
+endef
+
+$(eval $(call BuildPackage,liblua))
+$(eval $(call BuildPackage,lua))
+$(eval $(call BuildPackage,luac))
+$(eval $(call BuildPackage,lua-examples))
+$(eval $(call HostBuild))
+
diff --git a/package/lua/patches-host/010-lua-5.1.3-lnum-full-260308.patch b/package/lua/patches-host/010-lua-5.1.3-lnum-full-260308.patch
new file mode 100644
index 000000000..f8d8fc7f1
--- /dev/null
+++ b/package/lua/patches-host/010-lua-5.1.3-lnum-full-260308.patch
@@ -0,0 +1,3806 @@
+Index: lua-5.1.4/src/Makefile
+===================================================================
+--- lua-5.1.4.orig/src/Makefile 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/Makefile 2008-08-24 16:48:20.000000000 +0200
+@@ -25,7 +25,7 @@
+ LUA_A= liblua.a
+ CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
+ lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \
+- lundump.o lvm.o lzio.o
++ lundump.o lvm.o lzio.o lnum.o
+ LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \
+ lstrlib.o loadlib.o linit.o
+
+@@ -148,6 +148,7 @@
+ lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h
+ lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
+ ltm.h lzio.h lmem.h ldo.h
++lnum.o: lnum.c lua.h llex.h lnum.h
+ loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h
+ lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \
+ ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h
+@@ -179,4 +180,18 @@
+ print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \
+ ltm.h lzio.h lmem.h lopcodes.h lundump.h
+
++luaconf.h: lnum_config.h
++lapi.c: lnum.h
++lauxlib.c: llimits.h
++lbaselib.c: llimits.h lobject.h lapi.h
++lcode.c: lnum.h
++liolib.c: lnum.h llex.h
++llex.c: lnum.h
++lnum.h: lobject.h
++lobject.c: llex.h lnum.h
++ltable.c: lnum.h
++lua.c: llimits.h
++lvm.c: llex.h lnum.h
++print.c: lnum.h
++
+ # (end of Makefile)
+Index: lua-5.1.4/src/lapi.c
+===================================================================
+--- lua-5.1.4.orig/src/lapi.c 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/lapi.c 2008-08-24 16:48:20.000000000 +0200
+@@ -28,7 +28,7 @@
+ #include "ltm.h"
+ #include "lundump.h"
+ #include "lvm.h"
+-
++#include "lnum.h"
+
+
+ const char lua_ident[] =
+@@ -241,12 +241,13 @@
+
+ LUA_API int lua_type (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+- return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);
++ return (o == luaO_nilobject) ? LUA_TNONE : ttype_ext(o);
+ }
+
+
+ LUA_API const char *lua_typename (lua_State *L, int t) {
+ UNUSED(L);
++ lua_assert( t!= LUA_TINT );
+ return (t == LUA_TNONE) ? "no value" : luaT_typenames[t];
+ }
+
+@@ -264,6 +265,14 @@
+ }
+
+
++LUA_API int lua_isinteger (lua_State *L, int idx) {
++ TValue tmp;
++ lua_Integer dum;
++ const TValue *o = index2adr(L, idx);
++ return tonumber(o,&tmp) && (ttisint(o) || tt_integer_valued(o,&dum));
++}
++
++
+ LUA_API int lua_isstring (lua_State *L, int idx) {
+ int t = lua_type(L, idx);
+ return (t == LUA_TSTRING || t == LUA_TNUMBER);
+@@ -309,31 +318,66 @@
+ }
+
+
+-
+ LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
+ TValue n;
+ const TValue *o = index2adr(L, idx);
+- if (tonumber(o, &n))
++ if (tonumber(o, &n)) {
++#ifdef LNUM_COMPLEX
++ if (nvalue_img(o) != 0)
++ luaG_runerror(L, "expecting a real number");
++#endif
+ return nvalue(o);
+- else
+- return 0;
++ }
++ return 0;
+ }
+
+
+ LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) {
+ TValue n;
++ /* Lua 5.1 documented behaviour is to return nonzero for non-integer:
++ * "If the number is not an integer, it is truncated in some non-specified way."
++ * I would suggest to change this, to return 0 for anything that would
++ * not fit in 'lua_Integer'.
++ */
++#ifdef LUA_COMPAT_TOINTEGER
++ /* Lua 5.1 compatible */
+ const TValue *o = index2adr(L, idx);
+ if (tonumber(o, &n)) {
+- lua_Integer res;
+- lua_Number num = nvalue(o);
+- lua_number2integer(res, num);
+- return res;
++ lua_Integer i;
++ lua_Number d;
++ if (ttisint(o)) return ivalue(o);
++ d= nvalue_fast(o);
++# ifdef LNUM_COMPLEX
++ if (nvalue_img_fast(o) != 0)
++ luaG_runerror(L, "expecting a real number");
++# endif
++ lua_number2integer(i, d);
++ return i;
+ }
+- else
+- return 0;
++#else
++ /* New suggestion */
++ const TValue *o = index2adr(L, idx);
++ if (tonumber(o, &n)) {
++ lua_Integer i;
++ if (ttisint(o)) return ivalue(o);
++ if (tt_integer_valued(o,&i)) return i;
++ }
++#endif
++ return 0;
+ }
+
+
++#ifdef LNUM_COMPLEX
++LUA_API lua_Complex lua_tocomplex (lua_State *L, int idx) {
++ TValue tmp;
++ const TValue *o = index2adr(L, idx);
++ if (tonumber(o, &tmp))
++ return nvalue_complex(o);
++ return 0;
++}
++#endif
++
++
+ LUA_API int lua_toboolean (lua_State *L, int idx) {
+ const TValue *o = index2adr(L, idx);
+ return !l_isfalse(o);
+@@ -364,6 +408,7 @@
+ case LUA_TSTRING: return tsvalue(o)->len;
+ case LUA_TUSERDATA: return uvalue(o)->len;
+ case LUA_TTABLE: return luaH_getn(hvalue(o));
++ case LUA_TINT:
+ case LUA_TNUMBER: {
+ size_t l;
+ lua_lock(L); /* `luaV_tostring' may create a new string */
+@@ -426,6 +471,8 @@
+ }
+
+
++/* 'lua_pushnumber()' may lose accuracy on integers, 'lua_pushinteger' will not.
++ */
+ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
+ lua_lock(L);
+ setnvalue(L->top, n);
+@@ -434,12 +481,22 @@
+ }
+
+
+-LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
++LUA_API void lua_pushinteger (lua_State *L, lua_Integer i) {
++ lua_lock(L);
++ setivalue(L->top, i);
++ api_incr_top(L);
++ lua_unlock(L);
++}
++
++
++#ifdef LNUM_COMPLEX
++LUA_API void lua_pushcomplex (lua_State *L, lua_Complex v) {
+ lua_lock(L);
+- setnvalue(L->top, cast_num(n));
++ setnvalue_complex( L->top, v );
+ api_incr_top(L);
+ lua_unlock(L);
+ }
++#endif
+
+
+ LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
+@@ -569,7 +626,7 @@
+ lua_lock(L);
+ o = index2adr(L, idx);
+ api_check(L, ttistable(o));
+- setobj2s(L, L->top, luaH_getnum(hvalue(o), n));
++ setobj2s(L, L->top, luaH_getint(hvalue(o), n));
+ api_incr_top(L);
+ lua_unlock(L);
+ }
+@@ -597,6 +654,9 @@
+ case LUA_TUSERDATA:
+ mt = uvalue(obj)->metatable;
+ break;
++ case LUA_TINT:
++ mt = G(L)->mt[LUA_TNUMBER];
++ break;
+ default:
+ mt = G(L)->mt[ttype(obj)];
+ break;
+@@ -687,7 +747,7 @@
+ api_checknelems(L, 1);
+ o = index2adr(L, idx);
+ api_check(L, ttistable(o));
+- setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);
++ setobj2t(L, luaH_setint(L, hvalue(o), n), L->top-1);
+ luaC_barriert(L, hvalue(o), L->top-1);
+ L->top--;
+ lua_unlock(L);
+@@ -721,7 +781,7 @@
+ break;
+ }
+ default: {
+- G(L)->mt[ttype(obj)] = mt;
++ G(L)->mt[ttype_ext(obj)] = mt;
+ break;
+ }
+ }
+@@ -1085,3 +1145,32 @@
+ return name;
+ }
+
++
++/* Help function for 'luaB_tonumber()', avoids multiple str->number
++ * conversions for Lua "tonumber()".
++ *
++ * Also pushes floating point numbers with integer value as integer, which
++ * can be used by 'tonumber()' in scripts to bring values back to integer
++ * realm.
++ *
++ * Note: The 'back to integer realm' is _not_ to affect string conversions:
++ * 'tonumber("4294967295.1")' should give a floating point value, although
++ * the value would be 4294967296 (and storable in int64 realm).
++ */
++int lua_pushvalue_as_number (lua_State *L, int idx)
++{
++ const TValue *o = index2adr(L, idx);
++ TValue tmp;
++ lua_Integer i;
++ if (ttisnumber(o)) {
++ if ( (!ttisint(o)) && tt_integer_valued(o,&i)) {
++ lua_pushinteger( L, i );
++ return 1;
++ }
++ } else if (!tonumber(o, &tmp)) {
++ return 0;
++ }
++ if (ttisint(o)) lua_pushinteger( L, ivalue(o) );
++ else lua_pushnumber( L, nvalue_fast(o) );
++ return 1;
++}
+Index: lua-5.1.4/src/lapi.h
+===================================================================
+--- lua-5.1.4.orig/src/lapi.h 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/lapi.h 2008-08-24 16:48:20.000000000 +0200
+@@ -13,4 +13,6 @@
+
+ LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o);
+
++int lua_pushvalue_as_number (lua_State *L, int idx);
++
+ #endif
+Index: lua-5.1.4/src/lauxlib.c
+===================================================================
+--- lua-5.1.4.orig/src/lauxlib.c 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/lauxlib.c 2008-08-24 16:48:20.000000000 +0200
+@@ -23,7 +23,7 @@
+ #include "lua.h"
+
+ #include "lauxlib.h"
+-
++#include "llimits.h"
+
+ #define FREELIST_REF 0 /* free list of references */
+
+@@ -66,7 +66,7 @@
+
+
+ static void tag_error (lua_State *L, int narg, int tag) {
+- luaL_typerror(L, narg, lua_typename(L, tag));
++ luaL_typerror(L, narg, tag==LUA_TINT ? "integer" : lua_typename(L, tag));
+ }
+
+
+@@ -188,8 +188,8 @@
+
+ LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
+ lua_Integer d = lua_tointeger(L, narg);
+- if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
+- tag_error(L, narg, LUA_TNUMBER);
++ if (d == 0 && !lua_isinteger(L, narg)) /* avoid extra test when d is not 0 */
++ tag_error(L, narg, LUA_TINT);
+ return d;
+ }
+
+@@ -200,6 +200,16 @@
+ }
+
+
++#ifdef LNUM_COMPLEX
++LUALIB_API lua_Complex luaL_checkcomplex (lua_State *L, int narg) {
++ lua_Complex c = lua_tocomplex(L, narg);
++ if (c == 0 && !lua_isnumber(L, narg)) /* avoid extra test when c is not 0 */
++ tag_error(L, narg, LUA_TNUMBER);
++ return c;
++}
++#endif
++
++
+ LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
+ if (!lua_getmetatable(L, obj)) /* no metatable? */
+ return 0;
+Index: lua-5.1.4/src/lauxlib.h
+===================================================================
+--- lua-5.1.4.orig/src/lauxlib.h 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/lauxlib.h 2008-08-24 16:48:20.000000000 +0200
+@@ -57,6 +57,12 @@
+ LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
+ LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
+ lua_Integer def);
++#define luaL_checkint32(L,narg) ((int)luaL_checkinteger(L,narg))
++#define luaL_optint32(L,narg,def) ((int)luaL_optinteger(L,narg,def))
++
++#ifdef LNUM_COMPLEX
++ LUALIB_API lua_Complex (luaL_checkcomplex) (lua_State *L, int narg);
++#endif
+
+ LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
+ LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
+Index: lua-5.1.4/src/lbaselib.c
+===================================================================
+--- lua-5.1.4.orig/src/lbaselib.c 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/lbaselib.c 2008-08-24 16:48:20.000000000 +0200
+@@ -18,7 +18,9 @@
+
+ #include "lauxlib.h"
+ #include "lualib.h"
+-
++#include "llimits.h"
++#include "lobject.h"
++#include "lapi.h"
+
+
+
+@@ -54,20 +56,25 @@
+ int base = luaL_optint(L, 2, 10);
+ if (base == 10) { /* standard conversion */
+ luaL_checkany(L, 1);
+- if (lua_isnumber(L, 1)) {
+- lua_pushnumber(L, lua_tonumber(L, 1));
++ if (lua_isnumber(L, 1)) { /* numeric string, or a number */
++ lua_pushvalue_as_number(L,1); /* API extension (not to lose accuracy here) */
+ return 1;
+- }
++ }
+ }
+ else {
+ const char *s1 = luaL_checkstring(L, 1);
+ char *s2;
+- unsigned long n;
++ unsigned LUA_INTEGER n;
+ luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
+- n = strtoul(s1, &s2, base);
++ n = lua_str2ul(s1, &s2, base);
+ if (s1 != s2) { /* at least one valid digit? */
+ while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */
+ if (*s2 == '\0') { /* no invalid trailing characters? */
++
++ /* Push as number, there needs to be separate 'luaB_tointeger' for
++ * when the caller wants to preserve the bits (matters if unsigned
++ * values are used).
++ */
+ lua_pushnumber(L, (lua_Number)n);
+ return 1;
+ }
+@@ -144,7 +151,7 @@
+ luaL_checktype(L, 2, LUA_TTABLE);
+ getfunc(L, 0);
+ lua_pushvalue(L, 2);
+- if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
++ if (lua_isnumber(L, 1) && lua_tointeger(L, 1) == 0) {
+ /* change environment of current thread */
+ lua_pushthread(L);
+ lua_insert(L, -2);
+@@ -209,7 +216,7 @@
+ return 1;
+ }
+ default: {
+- lua_pushnumber(L, res);
++ lua_pushinteger(L, res);
+ return 1;
+ }
+ }
+@@ -631,6 +638,8 @@
+ luaL_register(L, "_G", base_funcs);
+ lua_pushliteral(L, LUA_VERSION);
+ lua_setglobal(L, "_VERSION"); /* set global _VERSION */
++ lua_pushliteral(L, LUA_LNUM);
++ lua_setglobal(L, "_LNUM"); /* "[complex] double|float|ldouble int32|int64" */
+ /* `ipairs' and `pairs' need auxliliary functions as upvalues */
+ auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
+ auxopen(L, "pairs", luaB_pairs, luaB_next);
+Index: lua-5.1.4/src/lcode.c
+===================================================================
+--- lua-5.1.4.orig/src/lcode.c 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/lcode.c 2008-08-24 16:48:20.000000000 +0200
+@@ -22,13 +22,18 @@
+ #include "lopcodes.h"
+ #include "lparser.h"
+ #include "ltable.h"
++#include "lnum.h"
+
+
+ #define hasjumps(e) ((e)->t != (e)->f)
+
+-
+ static int isnumeral(expdesc *e) {
+- return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
++ int ek=
++#ifdef LNUM_COMPLEX
++ (e->k == VKNUM2) ||
++#endif
++ (e->k == VKINT) || (e->k == VKNUM);
++ return (ek && e->t == NO_JUMP && e->f == NO_JUMP);
+ }
+
+
+@@ -231,12 +236,16 @@
+ TValue *idx = luaH_set(L, fs->h, k);
+ Proto *f = fs->f;
+ int oldsize = f->sizek;
+- if (ttisnumber(idx)) {
+- lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));
+- return cast_int(nvalue(idx));
++ if (ttype(idx)==LUA_TNUMBER) {
++ luai_normalize(idx);
++ lua_assert( ttype(idx)==LUA_TINT ); /* had no fraction */
++ }
++ if (ttisint(idx)) {
++ lua_assert(luaO_rawequalObj(&fs->f->k[ivalue(idx)], v));
++ return cast_int(ivalue(idx));
+ }
+ else { /* constant not found; create a new entry */
+- setnvalue(idx, cast_num(fs->nk));
++ setivalue(idx, fs->nk);
+ luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
+ MAXARG_Bx, "constant table overflow");
+ while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
+@@ -261,6 +270,21 @@
+ }
+
+
++int luaK_integerK (FuncState *fs, lua_Integer r) {
++ TValue o;
++ setivalue(&o, r);
++ return addk(fs, &o, &o);
++}
++
++
++#ifdef LNUM_COMPLEX
++static int luaK_imagK (FuncState *fs, lua_Number r) {
++ TValue o;
++ setnvalue_complex(&o, r*I);
++ return addk(fs, &o, &o);
++}
++#endif
++
+ static int boolK (FuncState *fs, int b) {
+ TValue o;
+ setbvalue(&o, b);
+@@ -359,6 +383,16 @@
+ luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));
+ break;
+ }
++ case VKINT: {
++ luaK_codeABx(fs, OP_LOADK, reg, luaK_integerK(fs, e->u.ival));
++ break;
++ }
++#ifdef LNUM_COMPLEX
++ case VKNUM2: {
++ luaK_codeABx(fs, OP_LOADK, reg, luaK_imagK(fs, e->u.nval));
++ break;
++ }
++#endif
+ case VRELOCABLE: {
+ Instruction *pc = &getcode(fs, e);
+ SETARG_A(*pc, reg);
+@@ -444,6 +478,10 @@
+ int luaK_exp2RK (FuncState *fs, expdesc *e) {
+ luaK_exp2val(fs, e);
+ switch (e->k) {
++#ifdef LNUM_COMPLEX
++ case VKNUM2:
++#endif
++ case VKINT:
+ case VKNUM:
+ case VTRUE:
+ case VFALSE:
+@@ -451,6 +489,10 @@
+ if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */
+ e->u.s.info = (e->k == VNIL) ? nilK(fs) :
+ (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :
++ (e->k == VKINT) ? luaK_integerK(fs, e->u.ival) :
++#ifdef LNUM_COMPLEX
++ (e->k == VKNUM2) ? luaK_imagK(fs, e->u.nval) :
++#endif
+ boolK(fs, (e->k == VTRUE));
+ e->k = VK;
+ return RKASK(e->u.s.info);
+@@ -540,7 +582,10 @@
+ int pc; /* pc of last jump */
+ luaK_dischargevars(fs, e);
+ switch (e->k) {
+- case VK: case VKNUM: case VTRUE: {
++#ifdef LNUM_COMPLEX
++ case VKNUM2:
++#endif
++ case VKINT: case VK: case VKNUM: case VTRUE: {
+ pc = NO_JUMP; /* always true; do nothing */
+ break;
+ }
+@@ -598,7 +643,10 @@
+ e->k = VTRUE;
+ break;
+ }
+- case VK: case VKNUM: case VTRUE: {
++#ifdef LNUM_COMPLEX
++ case VKNUM2:
++#endif
++ case VKINT: case VK: case VKNUM: case VTRUE: {
+ e->k = VFALSE;
+ break;
+ }
+@@ -634,25 +682,70 @@
+
+ static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
+ lua_Number v1, v2, r;
++ int vkres= VKNUM;
+ if (!isnumeral(e1) || !isnumeral(e2)) return 0;
+- v1 = e1->u.nval;
+- v2 = e2->u.nval;
++
++ /* real and imaginary parts don't mix. */
++#ifdef LNUM_COMPLEX
++ if (e1->k == VKNUM2) {
++ if ((op != OP_UNM) && (e2->k != VKNUM2)) return 0;
++ vkres= VKNUM2; }
++ else if (e2->k == VKNUM2) { return 0; }
++#endif
++ if ((e1->k == VKINT) && (e2->k == VKINT)) {
++ lua_Integer i1= e1->u.ival, i2= e2->u.ival;
++ lua_Integer rr;
++ int done= 0;
++ /* Integer/integer calculations (may end up producing floating point) */
++ switch (op) {
++ case OP_ADD: done= try_addint( &rr, i1, i2 ); break;
++ case OP_SUB: done= try_subint( &rr, i1, i2 ); break;
++ case OP_MUL: done= try_mulint( &rr, i1, i2 ); break;
++ case OP_DIV: done= try_divint( &rr, i1, i2 ); break;
++ case OP_MOD: done= try_modint( &rr, i1, i2 ); break;
++ case OP_POW: done= try_powint( &rr, i1, i2 ); break;
++ case OP_UNM: done= try_unmint( &rr, i1 ); break;
++ default: done= 0; break;
++ }
++ if (done) {
++ e1->u.ival = rr; /* remained within integer range */
++ return 1;
++ }
++ }
++ v1 = (e1->k == VKINT) ? ((lua_Number)e1->u.ival) : e1->u.nval;
++ v2 = (e2->k == VKINT) ? ((lua_Number)e2->u.ival) : e2->u.nval;
++
+ switch (op) {
+ case OP_ADD: r = luai_numadd(v1, v2); break;
+ case OP_SUB: r = luai_numsub(v1, v2); break;
+- case OP_MUL: r = luai_nummul(v1, v2); break;
++ case OP_MUL:
++#ifdef LNUM_COMPLEX
++ if (vkres==VKNUM2) return 0; /* leave to runtime (could do here, but not worth it?) */
++#endif
++ r = luai_nummul(v1, v2); break;
+ case OP_DIV:
+ if (v2 == 0) return 0; /* do not attempt to divide by 0 */
+- r = luai_numdiv(v1, v2); break;
++#ifdef LNUM_COMPLEX
++ if (vkres==VKNUM2) return 0; /* leave to runtime */
++#endif
++ r = luai_numdiv(v1, v2); break;
+ case OP_MOD:
+ if (v2 == 0) return 0; /* do not attempt to divide by 0 */
++#ifdef LNUM_COMPLEX
++ if (vkres==VKNUM2) return 0; /* leave to runtime */
++#endif
+ r = luai_nummod(v1, v2); break;
+- case OP_POW: r = luai_numpow(v1, v2); break;
++ case OP_POW:
++#ifdef LNUM_COMPLEX
++ if (vkres==VKNUM2) return 0; /* leave to runtime */
++#endif
++ r = luai_numpow(v1, v2); break;
+ case OP_UNM: r = luai_numunm(v1); break;
+ case OP_LEN: return 0; /* no constant folding for 'len' */
+ default: lua_assert(0); r = 0; break;
+ }
+ if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */
++ e1->k = cast(expkind,vkres);
+ e1->u.nval = r;
+ return 1;
+ }
+@@ -696,7 +789,8 @@
+
+ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
+ expdesc e2;
+- e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
++ e2.t = e2.f = NO_JUMP; e2.k = VKINT; e2.u.ival = 0;
++
+ switch (op) {
+ case OPR_MINUS: {
+ if (!isnumeral(e))
+Index: lua-5.1.4/src/lcode.h
+===================================================================
+--- lua-5.1.4.orig/src/lcode.h 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/lcode.h 2008-08-24 16:48:20.000000000 +0200
+@@ -71,6 +71,6 @@
+ LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
+ LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2);
+ LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
+-
++LUAI_FUNC int luaK_integerK (FuncState *fs, lua_Integer r);
+
+ #endif
+Index: lua-5.1.4/src/ldebug.c
+===================================================================
+--- lua-5.1.4.orig/src/ldebug.c 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/ldebug.c 2008-08-24 16:48:20.000000000 +0200
+@@ -183,7 +183,7 @@
+ int *lineinfo = f->l.p->lineinfo;
+ int i;
+ for (i=0; i<f->l.p->sizelineinfo; i++)
+- setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
++ setbvalue(luaH_setint(L, t, lineinfo[i]), 1);
+ sethvalue(L, L->top, t);
+ }
+ incr_top(L);
+@@ -566,7 +566,7 @@
+
+ void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
+ const char *name = NULL;
+- const char *t = luaT_typenames[ttype(o)];
++ const char *t = luaT_typenames[ttype_ext(o)];
+ const char *kind = (isinstack(L->ci, o)) ?
+ getobjname(L, L->ci, cast_int(o - L->base), &name) :
+ NULL;
+@@ -594,8 +594,8 @@
+
+
+ int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
+- const char *t1 = luaT_typenames[ttype(p1)];
+- const char *t2 = luaT_typenames[ttype(p2)];
++ const char *t1 = luaT_typenames[ttype_ext(p1)];
++ const char *t2 = luaT_typenames[ttype_ext(p2)];
+ if (t1[2] == t2[2])
+ luaG_runerror(L, "attempt to compare two %s values", t1);
+ else
+Index: lua-5.1.4/src/ldo.c
+===================================================================
+--- lua-5.1.4.orig/src/ldo.c 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/ldo.c 2008-08-24 16:48:20.000000000 +0200
+@@ -219,9 +219,9 @@
+ luaC_checkGC(L);
+ htab = luaH_new(L, nvar, 1); /* create `arg' table */
+ for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */
+- setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
++ setobj2n(L, luaH_setint(L, htab, i+1), L->top - nvar + i);
+ /* store counter in field `n' */
+- setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
++ setivalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), nvar);
+ }
+ #endif
+ /* move fixed parameters to final position */
+Index: lua-5.1.4/src/ldump.c
+===================================================================
+--- lua-5.1.4.orig/src/ldump.c 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/ldump.c 2008-08-24 16:48:20.000000000 +0200
+@@ -52,6 +52,11 @@
+ DumpVar(x,D);
+ }
+
++static void DumpInteger(lua_Integer x, DumpState* D)
++{
++ DumpVar(x,D);
++}
++
+ static void DumpVector(const void* b, int n, size_t size, DumpState* D)
+ {
+ DumpInt(n,D);
+@@ -93,8 +98,11 @@
+ DumpChar(bvalue(o),D);
+ break;
+ case LUA_TNUMBER:
+- DumpNumber(nvalue(o),D);
++ DumpNumber(nvalue_fast(o),D);
+ break;
++ case LUA_TINT:
++ DumpInteger(ivalue(o),D);
++ break;
+ case LUA_TSTRING:
+ DumpString(rawtsvalue(o),D);
+ break;
+Index: lua-5.1.4/src/liolib.c
+===================================================================
+--- lua-5.1.4.orig/src/liolib.c 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/liolib.c 2008-08-24 16:48:20.000000000 +0200
+@@ -9,6 +9,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <ctype.h>
+
+ #define liolib_c
+ #define LUA_LIB
+@@ -18,7 +19,8 @@
+ #include "lauxlib.h"
+ #include "lualib.h"
+
+-
++#include "lnum.h"
++#include "llex.h"
+
+ #define IO_INPUT 1
+ #define IO_OUTPUT 2
+@@ -269,6 +271,13 @@
+ ** =======================================================
+ */
+
++/*
++* Many problems if we intend the same 'n' format specifier (see 'file:read()')
++* to work for both FP and integer numbers, without losing their accuracy. So
++* we don't. 'n' reads numbers as floating points, 'i' as integers. Old code
++* remains valid, but won't provide full integer accuracy (this only matters
++* with float FP and/or 64-bit integers).
++*/
+
+ static int read_number (lua_State *L, FILE *f) {
+ lua_Number d;
+@@ -279,6 +288,43 @@
+ else return 0; /* read fails */
+ }
+
++static int read_integer (lua_State *L, FILE *f) {
++ lua_Integer i;
++ if (fscanf(f, LUA_INTEGER_SCAN, &i) == 1) {
++ lua_pushinteger(L, i);
++ return 1;
++ }
++ else return 0; /* read fails */
++}
++
++#ifdef LNUM_COMPLEX
++static int read_complex (lua_State *L, FILE *f) {
++ /* NNN / NNNi / NNN+MMMi / NNN-MMMi */
++ lua_Number a,b;
++ if (fscanf(f, LUA_NUMBER_SCAN, &a) == 1) {
++ int c=fgetc(f);
++ switch(c) {
++ case 'i':
++ lua_pushcomplex(L, a*I);
++ return 1;
++ case '+':
++ case '-':
++ /* "i" is consumed if at the end; just 'NNN+MMM' will most likely
++ * behave as if "i" was there? (TBD: test)
++ */
++ if (fscanf(f, LUA_NUMBER_SCAN "i", &b) == 1) {
++ lua_pushcomplex(L, a+ (c=='+' ? b:-b)*I);
++ return 1;
++ }
++ }
++ ungetc( c,f );
++ lua_pushnumber(L,a); /*real part only*/
++ return 1;
++ }
++ return 0; /* read fails */
++}
++#endif
++
+
+ static int test_eof (lua_State *L, FILE *f) {
+ int c = getc(f);
+@@ -352,6 +398,14 @@
+ case 'n': /* number */
+ success = read_number(L, f);
+ break;
++ case 'i': /* integer (full accuracy) */
++ success = read_integer(L, f);
++ break;
++#ifdef LNUM_COMPLEX
++ case 'c': /* complex */
++ success = read_complex(L, f);
++ break;
++#endif
+ case 'l': /* line */
+ success = read_line(L, f);
+ break;
+@@ -412,9 +466,10 @@
+ int status = 1;
+ for (; nargs--; arg++) {
+ if (lua_type(L, arg) == LUA_TNUMBER) {
+- /* optimization: could be done exactly as for strings */
+- status = status &&
+- fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
++ if (lua_isinteger(L,arg))
++ status = status && fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg)) > 0;
++ else
++ status = status && fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
+ }
+ else {
+ size_t l;
+@@ -457,7 +512,7 @@
+ static const char *const modenames[] = {"no", "full", "line", NULL};
+ FILE *f = tofile(L);
+ int op = luaL_checkoption(L, 2, NULL, modenames);
+- lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
++ size_t sz = luaL_optint32(L, 3, LUAL_BUFFERSIZE);
+ int res = setvbuf(f, NULL, mode[op], sz);
+ return pushresult(L, res == 0, NULL);
+ }
+Index: lua-5.1.4/src/llex.c
+===================================================================
+--- lua-5.1.4.orig/src/llex.c 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/llex.c 2008-08-24 16:48:20.000000000 +0200
+@@ -22,6 +22,7 @@
+ #include "lstring.h"
+ #include "ltable.h"
+ #include "lzio.h"
++#include "lnum.h"
+
+
+
+@@ -34,13 +35,17 @@
+
+
+ /* ORDER RESERVED */
+-const char *const luaX_tokens [] = {
++static const char *const luaX_tokens [] = {
+ "and", "break", "do", "else", "elseif",
+ "end", "false", "for", "function", "if",
+ "in", "local", "nil", "not", "or", "repeat",
+ "return", "then", "true", "until", "while",
+ "..", "...", "==", ">=", "<=", "~=",
+ "<number>", "<name>", "<string>", "<eof>",
++ "<integer>",
++#ifdef LNUM_COMPLEX
++ "<number2>",
++#endif
+ NULL
+ };
+
+@@ -90,7 +95,11 @@
+ switch (token) {
+ case TK_NAME:
+ case TK_STRING:
++ case TK_INT:
+ case TK_NUMBER:
++#ifdef LNUM_COMPLEX
++ case TK_NUMBER2:
++#endif
+ save(ls, '\0');
+ return luaZ_buffer(ls->buff);
+ default:
+@@ -173,23 +182,27 @@
+ if (p[n] == from) p[n] = to;
+ }
+
+-
+-static void trydecpoint (LexState *ls, SemInfo *seminfo) {
++/* TK_NUMBER (/ TK_NUMBER2) */
++static int trydecpoint (LexState *ls, SemInfo *seminfo) {
+ /* format error: try to update decimal point separator */
+ struct lconv *cv = localeconv();
+ char old = ls->decpoint;
++ int ret;
+ ls->decpoint = (cv ? cv->decimal_point[0] : '.');
+ buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */
+- if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {
++ ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, NULL);
++ if (!ret) {
+ /* format error with correct decimal point: no more options */
+ buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */
+ luaX_lexerror(ls, "malformed number", TK_NUMBER);
+ }
++ return ret;
+ }
+
+
+-/* LUA_NUMBER */
+-static void read_numeral (LexState *ls, SemInfo *seminfo) {
++/* TK_NUMBER / TK_INT (/TK_NUMBER2) */
++static int read_numeral (LexState *ls, SemInfo *seminfo) {
++ int ret;
+ lua_assert(isdigit(ls->current));
+ do {
+ save_and_next(ls);
+@@ -200,8 +213,9 @@
+ save_and_next(ls);
+ save(ls, '\0');
+ buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
+- if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */
+- trydecpoint(ls, seminfo); /* try to update decimal point separator */
++ ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, &seminfo->i );
++ if (!ret) return trydecpoint(ls, seminfo); /* try to update decimal point separator */
++ return ret;
+ }
+
+
+@@ -329,6 +343,7 @@
+ }
+
+
++/* char / TK_* */
+ static int llex (LexState *ls, SemInfo *seminfo) {
+ luaZ_resetbuffer(ls->buff);
+ for (;;) {
+@@ -400,8 +415,7 @@
+ }
+ else if (!isdigit(ls->current)) return '.';
+ else {
+- read_numeral(ls, seminfo);
+- return TK_NUMBER;
++ return read_numeral(ls, seminfo);
+ }
+ }
+ case EOZ: {
+@@ -414,8 +428,7 @@
+ continue;
+ }
+ else if (isdigit(ls->current)) {
+- read_numeral(ls, seminfo);
+- return TK_NUMBER;
++ return read_numeral(ls, seminfo);
+ }
+ else if (isalpha(ls->current) || ls->current == '_') {
+ /* identifier or reserved word */
+Index: lua-5.1.4/src/llex.h
+===================================================================
+--- lua-5.1.4.orig/src/llex.h 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/llex.h 2008-08-24 16:48:20.000000000 +0200
+@@ -29,19 +29,22 @@
+ TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
+ /* other terminal symbols */
+ TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,
+- TK_NAME, TK_STRING, TK_EOS
++ TK_NAME, TK_STRING, TK_EOS, TK_INT
++#ifdef LNUM_COMPLEX
++ , TK_NUMBER2 /* imaginary constants: Ni */
++#endif
+ };
+
+ /* number of reserved words */
+ #define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1))
+
+
+-/* array with token `names' */
+-LUAI_DATA const char *const luaX_tokens [];
+-
+-
++/* SemInfo is a local data structure of 'llex.c', used for carrying a string
++ * or a number. A separate token (TK_*) will tell, how to interpret the data.
++ */
+ typedef union {
+ lua_Number r;
++ lua_Integer i;
+ TString *ts;
+ } SemInfo; /* semantics information */
+
+Index: lua-5.1.4/src/llimits.h
+===================================================================
+--- lua-5.1.4.orig/src/llimits.h 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/llimits.h 2008-08-24 16:48:20.000000000 +0200
+@@ -49,6 +49,7 @@
+
+ /* result of a `usual argument conversion' over lua_Number */
+ typedef LUAI_UACNUMBER l_uacNumber;
++typedef LUAI_UACINTEGER l_uacInteger;
+
+
+ /* internal assertions for in-house debugging */
+@@ -80,7 +81,6 @@
+ #define cast_int(i) cast(int, (i))
+
+
+-
+ /*
+ ** type for virtual-machine instructions
+ ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
+Index: lua-5.1.4/src/lmathlib.c
+===================================================================
+--- lua-5.1.4.orig/src/lmathlib.c 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/lmathlib.c 2008-08-24 16:48:20.000000000 +0200
+@@ -4,7 +4,6 @@
+ ** See Copyright Notice in lua.h
+ */
+
+-
+ #include <stdlib.h>
+ #include <math.h>
+
+@@ -16,113 +15,210 @@
+ #include "lauxlib.h"
+ #include "lualib.h"
+
++/* 'luai_vectpow()' as a replacement for 'cpow()'. Defined in the header; we
++ * don't intrude the code libs internal functions.
++ */
++#ifdef LNUM_COMPLEX
++# include "lnum.h"
++#endif
+
+ #undef PI
+-#define PI (3.14159265358979323846)
+-#define RADIANS_PER_DEGREE (PI/180.0)
+-
++#ifdef LNUM_FLOAT
++# define PI (3.14159265358979323846F)
++#elif defined(M_PI)
++# define PI M_PI
++#else
++# define PI (3.14159265358979323846264338327950288)
++#endif
++#define RADIANS_PER_DEGREE (PI/180)
+
++#undef HUGE
++#ifdef LNUM_FLOAT
++# define HUGE HUGE_VALF
++#elif defined(LNUM_LDOUBLE)
++# define HUGE HUGE_VALL
++#else
++# define HUGE HUGE_VAL
++#endif
+
+ static int math_abs (lua_State *L) {
+- lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushnumber(L, _LF(cabs) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(fabs) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_sin (lua_State *L) {
+- lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(csin) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(sin) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_sinh (lua_State *L) {
+- lua_pushnumber(L, sinh(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(csinh) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(sinh) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_cos (lua_State *L) {
+- lua_pushnumber(L, cos(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(ccos) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(cos) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_cosh (lua_State *L) {
+- lua_pushnumber(L, cosh(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(ccosh) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(cosh) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_tan (lua_State *L) {
+- lua_pushnumber(L, tan(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(ctan) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(tan) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_tanh (lua_State *L) {
+- lua_pushnumber(L, tanh(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(ctanh) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(tanh) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_asin (lua_State *L) {
+- lua_pushnumber(L, asin(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(casin) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(asin) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_acos (lua_State *L) {
+- lua_pushnumber(L, acos(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(cacos) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(acos) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_atan (lua_State *L) {
+- lua_pushnumber(L, atan(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(catan) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(atan) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_atan2 (lua_State *L) {
+- lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++ /* scalars only */
++ lua_pushnumber(L, _LF(atan2) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+ }
+
+ static int math_ceil (lua_State *L) {
+- lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_Complex v= luaL_checkcomplex(L, 1);
++ lua_pushcomplex(L, _LF(ceil) (_LF(creal)(v)) + _LF(ceil) (_LF(cimag)(v))*I);
++#else
++ lua_pushnumber(L, _LF(ceil) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_floor (lua_State *L) {
+- lua_pushnumber(L, floor(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_Complex v= luaL_checkcomplex(L, 1);
++ lua_pushcomplex(L, _LF(floor) (_LF(creal)(v)) + _LF(floor) (_LF(cimag)(v))*I);
++#else
++ lua_pushnumber(L, _LF(floor) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+-static int math_fmod (lua_State *L) {
+- lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++static int math_fmod (lua_State *L) {
++ /* scalars only */
++ lua_pushnumber(L, _LF(fmod) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+ }
+
+ static int math_modf (lua_State *L) {
+- double ip;
+- double fp = modf(luaL_checknumber(L, 1), &ip);
++ /* scalars only */
++ lua_Number ip;
++ lua_Number fp = _LF(modf) (luaL_checknumber(L, 1), &ip);
+ lua_pushnumber(L, ip);
+ lua_pushnumber(L, fp);
+ return 2;
+ }
+
+ static int math_sqrt (lua_State *L) {
+- lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(csqrt) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(sqrt) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_pow (lua_State *L) {
+- lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++#ifdef LNUM_COMPLEX
++ /* C99 'cpow' gives somewhat inaccurate results (i.e. (-1)^2 = -1+1.2246467991474e-16i).
++ * 'luai_vectpow' smoothens such, reusing it is the reason we need to #include "lnum.h".
++ */
++ lua_pushcomplex(L, luai_vectpow(luaL_checkcomplex(L,1), luaL_checkcomplex(L,2)));
++#else
++ lua_pushnumber(L, _LF(pow) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++#endif
+ return 1;
+ }
+
+ static int math_log (lua_State *L) {
+- lua_pushnumber(L, log(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(log) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_log10 (lua_State *L) {
+- lua_pushnumber(L, log10(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ /* Not in standard <complex.h> , but easy to calculate: log_a(x) = log_b(x) / log_b(a)
++ */
++ lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1)) / _LF(log) (10));
++#else
++ lua_pushnumber(L, _LF(log10) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_exp (lua_State *L) {
+- lua_pushnumber(L, exp(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(cexp) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(exp) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+@@ -138,19 +234,20 @@
+
+ static int math_frexp (lua_State *L) {
+ int e;
+- lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));
++ lua_pushnumber(L, _LF(frexp) (luaL_checknumber(L, 1), &e));
+ lua_pushinteger(L, e);
+ return 2;
+ }
+
+ static int math_ldexp (lua_State *L) {
+- lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));
++ lua_pushnumber(L, _LF(ldexp) (luaL_checknumber(L, 1), luaL_checkint(L, 2)));
+ return 1;
+ }
+
+
+
+ static int math_min (lua_State *L) {
++ /* scalars only */
+ int n = lua_gettop(L); /* number of arguments */
+ lua_Number dmin = luaL_checknumber(L, 1);
+ int i;
+@@ -165,6 +262,7 @@
+
+
+ static int math_max (lua_State *L) {
++ /* scalars only */
+ int n = lua_gettop(L); /* number of arguments */
+ lua_Number dmax = luaL_checknumber(L, 1);
+ int i;
+@@ -182,25 +280,20 @@
+ /* the `%' avoids the (rare) case of r==1, and is needed also because on
+ some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
+ lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
+- switch (lua_gettop(L)) { /* check number of arguments */
+- case 0: { /* no arguments */
+- lua_pushnumber(L, r); /* Number between 0 and 1 */
+- break;
+- }
+- case 1: { /* only upper limit */
+- int u = luaL_checkint(L, 1);
+- luaL_argcheck(L, 1<=u, 1, "interval is empty");
+- lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */
+- break;
+- }
+- case 2: { /* lower and upper limits */
+- int l = luaL_checkint(L, 1);
+- int u = luaL_checkint(L, 2);
+- luaL_argcheck(L, l<=u, 2, "interval is empty");
+- lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */
+- break;
+- }
+- default: return luaL_error(L, "wrong number of arguments");
++ int n= lua_gettop(L); /* number of arguments */
++ if (n==0) { /* no arguments: range [0,1) */
++ lua_pushnumber(L, r);
++ } else if (n<=2) { /* int range [1,u] or [l,u] */
++ int l= n==1 ? 1 : luaL_checkint(L, 1);
++ int u = luaL_checkint(L, n);
++ int tmp;
++ lua_Number d;
++ luaL_argcheck(L, l<=u, n, "interval is empty");
++ d= _LF(floor)(r*(u-l+1));
++ lua_number2int(tmp,d);
++ lua_pushinteger(L, l+tmp);
++ } else {
++ return luaL_error(L, "wrong number of arguments");
+ }
+ return 1;
+ }
+@@ -211,6 +304,66 @@
+ return 0;
+ }
+
++/*
++* Lua 5.1 does not have acosh, asinh, atanh for scalars (not ANSI C)
++*/
++#if __STDC_VERSION__ >= 199901L
++static int math_acosh (lua_State *L) {
++# ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(cacosh) (luaL_checkcomplex(L,1)));
++# else
++ lua_pushnumber(L, _LF(acosh) (luaL_checknumber(L,1)));
++# endif
++ return 1;
++}
++static int math_asinh (lua_State *L) {
++# ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(casinh) (luaL_checkcomplex(L,1)));
++# else
++ lua_pushnumber(L, _LF(asinh) (luaL_checknumber(L,1)));
++# endif
++ return 1;
++}
++static int math_atanh (lua_State *L) {
++# ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(catanh) (luaL_checkcomplex(L,1)));
++# else
++ lua_pushnumber(L, _LF(atanh) (luaL_checknumber(L,1)));
++# endif
++ return 1;
++}
++#endif
++
++/*
++ * C99 complex functions, not covered above.
++*/
++#ifdef LNUM_COMPLEX
++static int math_arg (lua_State *L) {
++ lua_pushnumber(L, _LF(carg) (luaL_checkcomplex(L,1)));
++ return 1;
++}
++
++static int math_imag (lua_State *L) {
++ lua_pushnumber(L, _LF(cimag) (luaL_checkcomplex(L,1)));
++ return 1;
++}
++
++static int math_real (lua_State *L) {
++ lua_pushnumber(L, _LF(creal) (luaL_checkcomplex(L,1)));
++ return 1;
++}
++
++static int math_conj (lua_State *L) {
++ lua_pushcomplex(L, _LF(conj) (luaL_checkcomplex(L,1)));
++ return 1;
++}
++
++static int math_proj (lua_State *L) {
++ lua_pushcomplex(L, _LF(cproj) (luaL_checkcomplex(L,1)));
++ return 1;
++}
++#endif
++
+
+ static const luaL_Reg mathlib[] = {
+ {"abs", math_abs},
+@@ -241,6 +394,18 @@
+ {"sqrt", math_sqrt},
+ {"tanh", math_tanh},
+ {"tan", math_tan},
++#if __STDC_VERSION__ >= 199901L
++ {"acosh", math_acosh},
++ {"asinh", math_asinh},
++ {"atanh", math_atanh},
++#endif
++#ifdef LNUM_COMPLEX
++ {"arg", math_arg},
++ {"imag", math_imag},
++ {"real", math_real},
++ {"conj", math_conj},
++ {"proj", math_proj},
++#endif
+ {NULL, NULL}
+ };
+
+@@ -252,8 +417,10 @@
+ luaL_register(L, LUA_MATHLIBNAME, mathlib);
+ lua_pushnumber(L, PI);
+ lua_setfield(L, -2, "pi");
+- lua_pushnumber(L, HUGE_VAL);
++ lua_pushnumber(L, HUGE);
+ lua_setfield(L, -2, "huge");
++ lua_pushinteger(L, LUA_INTEGER_MAX );
++ lua_setfield(L, -2, "hugeint");
+ #if defined(LUA_COMPAT_MOD)
+ lua_getfield(L, -1, "fmod");
+ lua_setfield(L, -2, "mod");
+Index: lua-5.1.4/src/lnum.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ lua-5.1.4/src/lnum.c 2008-08-24 16:48:20.000000000 +0200
+@@ -0,0 +1,312 @@
++/*
++** $Id: lnum.c,v ... $
++** Internal number model
++** See Copyright Notice in lua.h
++*/
++
++#include <stdlib.h>
++#include <math.h>
++#include <ctype.h>
++#include <string.h>
++#include <stdio.h>
++#include <errno.h>
++
++#define lnum_c
++#define LUA_CORE
++
++#include "lua.h"
++#include "llex.h"
++#include "lnum.h"
++
++/*
++** lua_real2str converts a (non-complex) number to a string.
++** lua_str2real converts a string to a (non-complex) number.
++*/
++#define lua_real2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
++
++/*
++* Note: Only 'strtod()' is part of ANSI C; others are C99 and
++* may need '--std=c99' compiler setting (at least on Ubuntu 7.10).
++*
++* Visual C++ 2008 Express does not have 'strtof()', nor 'strtold()'.
++* References to '_strtold()' exist but don't compile. It seems best
++* to leave Windows users with DOUBLE only (or compile with MinGW).
++*
++* In practise, using '(long double)strtod' is a risky thing, since
++* it will cause accuracy loss in reading in numbers, and such losses
++* will pile up in later processing. Get a real 'strtold()' or don't
++* use that mode at all.
++*/
++#ifdef LNUM_DOUBLE
++# define lua_str2real strtod
++#elif defined(LNUM_FLOAT)
++# define lua_str2real strtof
++#elif defined(LNUM_LDOUBLE)
++# define lua_str2real strtold
++#endif
++
++#define lua_integer2str(s,v) sprintf((s), LUA_INTEGER_FMT, (v))
++
++/* 's' is expected to be LUAI_MAXNUMBER2STR long (enough for any number)
++*/
++void luaO_num2buf( char *s, const TValue *o )
++{
++ lua_Number n;
++ lua_assert( ttisnumber(o) );
++
++ /* Reason to handle integers differently is not only speed, but accuracy as
++ * well. We want to make any integer tostring() without roundings, at all.
++ */
++ if (ttisint(o)) {
++ lua_integer2str( s, ivalue(o) );
++ return;
++ }
++ n= nvalue_fast(o);
++ lua_real2str(s, n);
++
++#ifdef LNUM_COMPLEX
++ lua_Number n2= nvalue_img_fast(o);
++ if (n2!=0) { /* Postfix with +-Ni */
++ int re0= (n == 0);
++ char *s2= re0 ? s : strchr(s,'\0');
++ if ((!re0) && (n2>0)) *s2++= '+';
++ lua_real2str( s2, n2 );
++ strcat(s2,"i");
++ }
++#endif
++}
++
++/*
++* If a LUA_TNUMBER has integer value, give it.
++*/
++int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref ) {
++ lua_Number d;
++ lua_Integer i;
++
++ lua_assert( ttype(o)==LUA_TNUMBER );
++ lua_assert( ref );
++#ifdef LNUM_COMPLEX
++ if (nvalue_img_fast(o)!=0) return 0;
++#endif
++ d= nvalue_fast(o);
++ lua_number2integer(i, d);
++ if (cast_num(i) == d) {
++ *ref= i; return 1;
++ }
++ return 0;
++}
++
++/*
++ * Lua 5.1.3 (using 'strtod()') allows 0x+hex but not 0+octal. This is good,
++ * and we should NOT use 'autobase' 0 with 'strtoul[l]()' for this reason.
++ *
++ * Lua 5.1.3 allows '0x...' numbers to overflow and lose precision; this is not
++ * good. On Visual C++ 2008, 'strtod()' does not even take them in. Better to
++ * require hex values to fit 'lua_Integer' or give an error that they don't?
++ *
++ * Full hex range (0 .. 0xff..ff) is stored as integers, not to lose any bits.
++ * Numerical value of 0xff..ff will be -1, if used in calculations.
++ *
++ * Returns: TK_INT for a valid integer, '*endptr_ref' updated
++ * TK_NUMBER for seemingly numeric, to be parsed as floating point
++ * 0 for bad characters, not a number (or '0x' out of range)
++ */
++static int luaO_str2i (const char *s, lua_Integer *res, char **endptr_ref) {
++ char *endptr;
++ /* 'v' gets ULONG_MAX on possible overflow (which is > LUA_INTEGER_MAX);
++ * we don't have to check 'errno' here.
++ */
++ unsigned LUA_INTEGER v= lua_str2ul(s, &endptr, 10);
++ if (endptr == s) return 0; /* nothing numeric */
++ if (v==0 && *endptr=='x') {
++ errno= 0; /* needs to be set, 'strtoul[l]' does not clear it */
++ v= lua_str2ul(endptr+1, &endptr, 16); /* retry as hex, unsigned range */
++ if (errno==ERANGE) { /* clamped to 0xff..ff */
++#if (defined(LNUM_INT32) && !defined(LNUM_FLOAT)) || defined(LNUM_LDOUBLE)
++ return TK_NUMBER; /* Allow to be read as floating point (has more integer range) */
++#else
++ return 0; /* Reject the number */
++#endif
++ }
++ } else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) {
++ return TK_NUMBER; /* not in signed range, or has '.', 'e' etc. trailing */
++ }
++ *res= (lua_Integer)v;
++ *endptr_ref= endptr;
++ return TK_INT;
++}
++
++/* 0 / TK_NUMBER / TK_INT (/ TK_NUMBER2) */
++int luaO_str2d (const char *s, lua_Number *res_n, lua_Integer *res_i) {
++ char *endptr;
++ int ret= TK_NUMBER;
++ /* Check integers first, if caller is allowing.
++ * If 'res2'==NULL, they're only looking for floating point.
++ */
++ if (res_i) {
++ ret= luaO_str2i(s,res_i,&endptr);
++ if (ret==0) return 0;
++ }
++ if (ret==TK_NUMBER) {
++ lua_assert(res_n);
++ /* Note: Visual C++ 2008 Express 'strtod()' does not read in "0x..."
++ * numbers; it will read '0' and spit 'x' as endptr.
++ * This means hex constants not fitting in 'lua_Integer' won't
++ * be read in at all. What to do?
++ */
++ *res_n = lua_str2real(s, &endptr);
++ if (endptr == s) return 0; /* conversion failed */
++ /* Visual C++ 2008 'strtod()' does not allow "0x..." input. */
++#if defined(_MSC_VER) && !defined(LNUM_FLOAT) && !defined(LNUM_INT64)
++ if (*res_n==0 && *endptr=='x') {
++ /* Hex constant too big for 'lua_Integer' but that could fit in 'lua_Number'
++ * integer bits
++ */
++ unsigned __int64 v= _strtoui64( s, &endptr, 16 );
++ /* We just let > 64 bit values be clamped to _UI64_MAX (MSDN does not say 'errno'==ERANGE would be set) */
++ *res_n= cast_num(v);
++ if (*res_n != v) return 0; /* Would have lost accuracy */
++ }
++#endif
++#ifdef LNUM_COMPLEX
++ if (*endptr == 'i') { endptr++; ret= TK_NUMBER2; }
++#endif
++ }
++ if (*endptr) {
++ while (isspace(cast(unsigned char, *endptr))) endptr++;
++ if (*endptr) return 0; /* invalid trail */
++ }
++ return ret;
++}
++
++
++/* Functions for finding out, when integer operations remain in range
++ * (and doing them).
++ */
++int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++ lua_Integer v= ib+ic; /* may overflow */
++ if (ib>0 && ic>0) { if (v < 0) return 0; /*overflow, use floats*/ }
++ else if (ib<0 && ic<0) { if (v >= 0) return 0; }
++ *r= v;
++ return 1;
++}
++
++int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++ lua_Integer v= ib-ic; /* may overflow */
++ if (ib>=0 && ic<0) { if (v < 0) return 0; /*overflow, use floats*/ }
++ else if (ib<0 && ic>0) { if (v >= 0) return 0; }
++ *r= v;
++ return 1;
++}
++
++int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++ if (ib!=LUA_INTEGER_MIN && ic!=LUA_INTEGER_MIN) {
++ lua_Integer b= luai_abs(ib), c= luai_abs(ic);
++ if ( (ib==0) || (LUA_INTEGER_MAX/b >= c) ) {
++ *r= ib*ic; /* no overflow */
++ return 1;
++ }
++ } else if (ib==0 || ic==0) {
++ *r= 0; return 1;
++ }
++
++ /* Result can be LUA_INTEGER_MIN; if it is, calculating it using floating
++ * point will not cause accuracy loss.
++ */
++ if ( luai_nummul( cast_num(ib), cast_num(ic) ) == LUA_INTEGER_MIN ) {
++ *r= LUA_INTEGER_MIN;
++ return 1;
++ }
++ return 0;
++}
++
++int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++ /* N/0: leave to float side, to give an error
++ */
++ if (ic==0) return 0;
++
++ /* N/LUA_INTEGER_MIN: always non-integer results, or 0 or +1
++ */
++ if (ic==LUA_INTEGER_MIN) {
++ if (ib==LUA_INTEGER_MIN) { *r=1; return 1; }
++ if (ib==0) { *r=0; return 1; }
++
++ /* LUA_INTEGER_MIN (-2^31|63)/N: calculate using float side (either the division
++ * causes non-integer results, or there is no accuracy loss in int->fp->int
++ * conversions (N=2,4,8,..,256 and N=2^30,2^29,..2^23).
++ */
++ } else if (ib==LUA_INTEGER_MIN) {
++ lua_Number d= luai_numdiv( cast_num(LUA_INTEGER_MIN), cast_num(ic) );
++ lua_Integer i; lua_number2integer(i,d);
++ if (cast_num(i)==d) { *r= i; return 1; }
++
++ } else {
++ /* Note: We _can_ use ANSI C mod here, even on negative values, since
++ * we only test for == 0 (the sign would be implementation dependent).
++ */
++ if (ib%ic == 0) { *r= ib/ic; return 1; }
++ }
++
++ return 0;
++}
++
++int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++ if (ic!=0) {
++ /* ANSI C can be trusted when b%c==0, or when values are non-negative.
++ * b - (floor(b/c) * c)
++ * -->
++ * + +: b - (b/c) * c (b % c can be used)
++ * - -: b - (b/c) * c (b % c could work, but not defined by ANSI C)
++ * 0 -: b - (b/c) * c (=0, b % c could work, but not defined by ANSI C)
++ * - +: b - (b/c-1) * c (when b!=-c)
++ * + -: b - (b/c-1) * c (when b!=-c)
++ *
++ * o MIN%MIN ends up 0, via overflow in calcs but that does not matter.
++ * o MIN%MAX ends up MAX-1 (and other such numbers), also after overflow,
++ * but that does not matter, results do.
++ */
++ lua_Integer v= ib % ic;
++ if ( v!=0 && (ib<0 || ic<0) ) {
++ v= ib - ((ib/ic) - ((ib<=0 && ic<0) ? 0:1)) * ic;
++ }
++ /* Result should always have same sign as 2nd argument. (PIL2) */
++ lua_assert( (v<0) ? (ic<0) : (v>0) ? (ic>0) : 1 );
++ *r= v;
++ return 1;
++ }
++ return 0; /* let float side return NaN */
++}
++
++int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++
++ /* In FLOAT/INT32 or FLOAT|DOUBLE/INT64 modes, calculating integer powers
++ * via FP realm may lose accuracy (i.e. 7^11 = 1977326743, which fits int32
++ * but not 23-bit float mantissa).
++ *
++ * The current solution is dumb, but it works and uses little code. Use of
++ * integer powers is not anticipated to be very frequent (apart from 2^x,
++ * which is separately optimized).
++ */
++ if (ib==0) *r=0;
++ else if (ic<0) return 0; /* FP realm */
++ else if (ib==2 && ic < (int)sizeof(lua_Integer)*8-1) *r= ((lua_Integer)1)<<ic; /* 1,2,4,...2^30 | 2^62 optimization */
++ else if (ic==0) *r=1;
++ else if (luai_abs(ib)==1) *r= (ic%2) ? ib:1;
++ else {
++ lua_Integer x= ib;
++ while( --ic ) {
++ if (!try_mulint( &x, x, ib ))
++ return 0; /* FP realm */
++ }
++ *r= x;
++ }
++ return 1;
++}
++
++int try_unmint( lua_Integer *r, lua_Integer ib ) {
++ /* Negating LUA_INTEGER_MIN leaves the range. */
++ if ( ib != LUA_INTEGER_MIN )
++ { *r= -ib; return 1; }
++ return 0;
++}
++
+Index: lua-5.1.4/src/lnum.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ lua-5.1.4/src/lnum.h 2008-08-24 16:48:20.000000000 +0200
+@@ -0,0 +1,116 @@
++/*
++** $Id: lnum.h,v ... $
++** Internal Number model
++** See Copyright Notice in lua.h
++*/
++
++#ifndef lnum_h
++#define lnum_h
++
++#include <math.h>
++
++#include "lobject.h"
++
++/*
++** The luai_num* macros define the primitive operations over 'lua_Number's
++** (not 'lua_Integer's, not 'lua_Complex').
++*/
++#define luai_numadd(a,b) ((a)+(b))
++#define luai_numsub(a,b) ((a)-(b))
++#define luai_nummul(a,b) ((a)*(b))
++#define luai_numdiv(a,b) ((a)/(b))
++#define luai_nummod(a,b) ((a) - _LF(floor)((a)/(b))*(b))
++#define luai_numpow(a,b) (_LF(pow)(a,b))
++#define luai_numunm(a) (-(a))
++#define luai_numeq(a,b) ((a)==(b))
++#define luai_numlt(a,b) ((a)<(b))
++#define luai_numle(a,b) ((a)<=(b))
++#define luai_numisnan(a) (!luai_numeq((a), (a)))
++
++int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_unmint( lua_Integer *r, lua_Integer ib );
++
++#ifdef LNUM_COMPLEX
++ static inline lua_Complex luai_vectunm( lua_Complex a ) { return -a; }
++ static inline lua_Complex luai_vectadd( lua_Complex a, lua_Complex b ) { return a+b; }
++ static inline lua_Complex luai_vectsub( lua_Complex a, lua_Complex b ) { return a-b; }
++ static inline lua_Complex luai_vectmul( lua_Complex a, lua_Complex b ) { return a*b; }
++ static inline lua_Complex luai_vectdiv( lua_Complex a, lua_Complex b ) { return a/b; }
++
++/*
++ * C99 does not provide modulus for complex numbers. It most likely is not
++ * meaningful at all.
++ */
++
++/*
++ * Complex power
++ *
++ * C99 'cpow' gives inaccurate results for many common cases s.a. (1i)^2 ->
++ * -1+1.2246467991474e-16i (OS X 10.4, gcc 4.0.1 build 5367)
++ *
++ * [(a+bi)^(c+di)] = (r^c) * exp(-d*t) * cos(c*t + d*ln(r)) +
++ * = (r^c) * exp(-d*t) * sin(c*t + d*ln(r)) *i
++ * r = sqrt(a^2+b^2), t = arctan( b/a )
++ *
++ * Reference: <http://home.att.net/~srschmitt/complexnumbers.html>
++ * Could also be calculated using: x^y = exp(ln(x)*y)
++ *
++ * Note: Defined here (and not in .c) so 'lmathlib.c' can share the
++ * implementation.
++ */
++ static inline
++ lua_Complex luai_vectpow( lua_Complex a, lua_Complex b )
++ {
++# if 1
++ lua_Number ar= _LF(creal)(a), ai= _LF(cimag)(a);
++ lua_Number br= _LF(creal)(b), bi= _LF(cimag)(b);
++
++ if (ai==0 && bi==0) { /* a^c (real) */
++ return luai_numpow( ar, br );
++ }
++
++ int br_int= (int)br;
++
++ if ( ai!=0 && bi==0 && br_int==br && br_int!=0 && br_int!=INT_MIN ) {
++ /* (a+bi)^N, N = { +-1,+-2, ... +-INT_MAX }
++ */
++ lua_Number k= luai_numpow( _LF(sqrt) (ar*ar + ai*ai), br );
++ lua_Number cos_z, sin_z;
++
++ /* Situation depends upon c (N) in the following manner:
++ *
++ * N%4==0 => cos(c*t)=1, sin(c*t)=0
++ * (N*sign(b))%4==1 or (N*sign(b))%4==-3 => cos(c*t)=0, sin(c*t)=1
++ * N%4==2 or N%4==-2 => cos(c*t)=-1, sin(c*t)=0
++ * (N*sign(b))%4==-1 or (N*sign(b))%4==3 => cos(c*t)=0, sin(c*t)=-1
++ */
++ int br_int_abs = br_int<0 ? -br_int:br_int;
++
++ switch( (br_int_abs%4) * (br_int<0 ? -1:1) * (ai<0 ? -1:1) ) {
++ case 0: cos_z=1, sin_z=0; break;
++ case 2: case -2: cos_z=-1, sin_z=0; break;
++ case 1: case -3: cos_z=0, sin_z=1; break;
++ case 3: case -1: cos_z=0, sin_z=-1; break;
++ default: lua_assert(0); return 0;
++ }
++ return k*cos_z + (k*sin_z)*I;
++ }
++# endif
++ return _LF(cpow) ( a, b );
++ }
++#endif
++
++LUAI_FUNC int luaO_str2d (const char *s, lua_Number *res1, lua_Integer *res2);
++LUAI_FUNC void luaO_num2buf( char *s, const TValue *o );
++
++LUAI_FUNC int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref );
++
++#define luai_normalize(o) \
++{ lua_Integer _i; if (tt_integer_valued(o,&_i)) setivalue(o,_i); }
++
++#endif
+Index: lua-5.1.4/src/lnum_config.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ lua-5.1.4/src/lnum_config.h 2008-08-24 16:48:20.000000000 +0200
+@@ -0,0 +1,221 @@
++/*
++** $Id: lnum_config.h,v ... $
++** Internal Number model
++** See Copyright Notice in lua.h
++*/
++
++#ifndef lnum_config_h
++#define lnum_config_h
++
++/*
++** Default number modes
++*/
++#if (!defined LNUM_DOUBLE) && (!defined LNUM_FLOAT) && (!defined LNUM_LDOUBLE)
++# define LNUM_FLOAT
++#endif
++#if (!defined LNUM_INT16) && (!defined LNUM_INT32) && (!defined LNUM_INT64)
++# define LNUM_INT32
++#endif
++
++/*
++** Require C99 mode for COMPLEX, FLOAT and LDOUBLE (only DOUBLE is ANSI C).
++*/
++#if defined(LNUM_COMPLEX) && (__STDC_VERSION__ < 199901L)
++# error "Need C99 for complex (use '--std=c99' or similar)"
++#elif defined(LNUM_LDOUBLE) && (__STDC_VERSION__ < 199901L) && !defined(_MSC_VER)
++# error "Need C99 for 'long double' (use '--std=c99' or similar)"
++#elif defined(LNUM_FLOAT) && (__STDC_VERSION__ < 199901L)
++/* LNUM_FLOAT not supported on Windows */
++# error "Need C99 for 'float' (use '--std=c99' or similar)"
++#endif
++
++/*
++** Number mode identifier to accompany the version string.
++*/
++#ifdef LNUM_COMPLEX
++# define _LNUM1 "complex "
++#else
++# define _LNUM1 ""
++#endif
++#ifdef LNUM_DOUBLE
++# define _LNUM2 "double"
++#elif defined(LNUM_FLOAT)
++# define _LNUM2 "float"
++#elif defined(LNUM_LDOUBLE)
++# define _LNUM2 "ldouble"
++#endif
++#ifdef LNUM_INT32
++# define _LNUM3 "int32"
++#elif defined(LNUM_INT64)
++# define _LNUM3 "int64"
++#elif defined(LNUM_INT16)
++# define _LNUM3 "int16"
++#endif
++#define LUA_LNUM _LNUM1 _LNUM2 " " _LNUM3
++
++/*
++** LUA_NUMBER is the type of floating point number in Lua
++** LUA_NUMBER_SCAN is the format for reading numbers.
++** LUA_NUMBER_FMT is the format for writing numbers.
++*/
++#ifdef LNUM_FLOAT
++# define LUA_NUMBER float
++# define LUA_NUMBER_SCAN "%f"
++# define LUA_NUMBER_FMT "%g"
++#elif (defined LNUM_DOUBLE)
++# define LUA_NUMBER double
++# define LUA_NUMBER_SCAN "%lf"
++# define LUA_NUMBER_FMT "%.14g"
++#elif (defined LNUM_LDOUBLE)
++# define LUA_NUMBER long double
++# define LUA_NUMBER_SCAN "%Lg"
++# define LUA_NUMBER_FMT "%.20Lg"
++#endif
++
++
++/*
++** LUAI_MAXNUMBER2STR: size of a buffer fitting any number->string result.
++**
++** double: 24 (sign, x.xxxxxxxxxxxxxxe+nnnn, and \0)
++** int64: 21 (19 digits, sign, and \0)
++** long double: 43 for 128-bit (sign, x.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxe+nnnn, and \0)
++** 30 for 80-bit (sign, x.xxxxxxxxxxxxxxxxxxxxe+nnnn, and \0)
++*/
++#ifdef LNUM_LDOUBLE
++# define _LUAI_MN2S 44
++#else
++# define _LUAI_MN2S 24
++#endif
++
++#ifdef LNUM_COMPLEX
++# define LUAI_MAXNUMBER2STR (2*_LUAI_MN2S)
++#else
++# define LUAI_MAXNUMBER2STR _LUAI_MN2S
++#endif
++
++/*
++** LUA_INTEGER is the integer type used by lua_pushinteger/lua_tointeger/lua_isinteger.
++** LUA_INTEGER_SCAN is the format for reading integers
++** LUA_INTEGER_FMT is the format for writing integers
++**
++** Note: Visual C++ 2005 does not have 'strtoull()', use '_strtoui64()' instead.
++*/
++#ifdef LNUM_INT32
++# if LUAI_BITSINT > 16
++# define LUA_INTEGER int
++# define LUA_INTEGER_SCAN "%d"
++# define LUA_INTEGER_FMT "%d"
++# else
++/* Note: 'LUA_INTEGER' being 'ptrdiff_t' (as in Lua 5.1) causes problems with
++ * 'printf()' operations. Also 'unsigned ptrdiff_t' is invalid.
++ */
++# define LUA_INTEGER long
++# define LUA_INTEGER_SCAN "%ld"
++# define LUA_INTEGER_FMT "%ld"
++# endif
++# define LUA_INTEGER_MAX 0x7FFFFFFF /* 2^31-1 */
++/* */
++#elif defined(LNUM_INT64)
++# define LUA_INTEGER long long
++# ifdef _MSC_VER
++# define lua_str2ul _strtoui64
++# else
++# define lua_str2ul strtoull
++# endif
++# define LUA_INTEGER_SCAN "%lld"
++# define LUA_INTEGER_FMT "%lld"
++# define LUA_INTEGER_MAX 0x7fffffffffffffffLL /* 2^63-1 */
++# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX - 1LL) /* -2^63 */
++/* */
++#elif defined(LNUM_INT16)
++# if LUAI_BITSINT > 16
++# define LUA_INTEGER short
++# define LUA_INTEGER_SCAN "%hd"
++# define LUA_INTEGER_FMT "%hd"
++# else
++# define LUA_INTEGER int
++# define LUA_INTEGER_SCAN "%d"
++# define LUA_INTEGER_FMT "%d"
++# endif
++# define LUA_INTEGER_MAX 0x7FFF /* 2^16-1 */
++#endif
++
++#ifndef lua_str2ul
++# define lua_str2ul (unsigned LUA_INTEGER)strtoul
++#endif
++#ifndef LUA_INTEGER_MIN
++# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX -1) /* -2^16|32 */
++#endif
++
++/*
++@@ lua_number2int is a macro to convert lua_Number to int.
++@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
++** CHANGE them if you know a faster way to convert a lua_Number to
++** int (with any rounding method and without throwing errors) in your
++** system. In Pentium machines, a naive typecast from double to int
++** in C is extremely slow, so any alternative is worth trying.
++*/
++
++/* On a Pentium, resort to a trick */
++#if defined(LNUM_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \
++ (defined(__i386) || defined (_M_IX86) || defined(__i386__))
++
++/* On a Microsoft compiler, use assembler */
++# if defined(_MSC_VER)
++# define lua_number2int(i,d) __asm fld d __asm fistp i
++# else
++
++/* the next trick should work on any Pentium, but sometimes clashes
++ with a DirectX idiosyncrasy */
++union luai_Cast { double l_d; long l_l; };
++# define lua_number2int(i,d) \
++ { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
++# endif
++
++# ifndef LNUM_INT64
++# define lua_number2integer lua_number2int
++# endif
++
++/* this option always works, but may be slow */
++#else
++# define lua_number2int(i,d) ((i)=(int)(d))
++#endif
++
++/* Note: Some compilers (OS X gcc 4.0?) may choke on double->long long conversion
++ * since it can lose precision. Others do require 'long long' there.
++ */
++#ifndef lua_number2integer
++# define lua_number2integer(i,d) ((i)=(lua_Integer)(d))
++#endif
++
++/*
++** 'luai_abs()' to give absolute value of 'lua_Integer'
++*/
++#ifdef LNUM_INT32
++# define luai_abs abs
++#elif defined(LNUM_INT64) && (__STDC_VERSION__ >= 199901L)
++# define luai_abs llabs
++#else
++# define luai_abs(v) ((v) >= 0 ? (v) : -(v))
++#endif
++
++/*
++** LUAI_UACNUMBER is the result of an 'usual argument conversion' over a number.
++** LUAI_UACINTEGER the same, over an integer.
++*/
++#define LUAI_UACNUMBER double
++#define LUAI_UACINTEGER long
++
++/* ANSI C only has math funcs for 'double. C99 required for float and long double
++ * variants.
++ */
++#ifdef LNUM_DOUBLE
++# define _LF(name) name
++#elif defined(LNUM_FLOAT)
++# define _LF(name) name ## f
++#elif defined(LNUM_LDOUBLE)
++# define _LF(name) name ## l
++#endif
++
++#endif
++
+Index: lua-5.1.4/src/lobject.c
+===================================================================
+--- lua-5.1.4.orig/src/lobject.c 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/lobject.c 2008-08-24 16:48:20.000000000 +0200
+@@ -21,7 +21,8 @@
+ #include "lstate.h"
+ #include "lstring.h"
+ #include "lvm.h"
+-
++#include "llex.h"
++#include "lnum.h"
+
+
+ const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};
+@@ -70,12 +71,31 @@
+
+
+ int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
+- if (ttype(t1) != ttype(t2)) return 0;
++ if (!ttype_ext_same(t1,t2)) return 0;
+ else switch (ttype(t1)) {
+ case LUA_TNIL:
+ return 1;
++ case LUA_TINT:
++ if (ttype(t2)==LUA_TINT)
++ return ivalue(t1) == ivalue(t2);
++ else { /* t1:int, t2:num */
++#ifdef LNUM_COMPLEX
++ if (nvalue_img_fast(t2) != 0) return 0;
++#endif
++ /* Avoid doing accuracy losing cast, if possible. */
++ lua_Integer tmp;
++ if (tt_integer_valued(t2,&tmp))
++ return ivalue(t1) == tmp;
++ else
++ return luai_numeq( cast_num(ivalue(t1)), nvalue_fast(t2) );
++ }
+ case LUA_TNUMBER:
+- return luai_numeq(nvalue(t1), nvalue(t2));
++ if (ttype(t2)==LUA_TINT)
++ return luaO_rawequalObj(t2, t1); /* swap LUA_TINT to left */
++#ifdef LNUM_COMPLEX
++ if (!luai_numeq(nvalue_img_fast(t1), nvalue_img_fast(t2))) return 0;
++#endif
++ return luai_numeq(nvalue_fast(t1), nvalue_fast(t2));
+ case LUA_TBOOLEAN:
+ return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */
+ case LUA_TLIGHTUSERDATA:
+@@ -86,21 +106,6 @@
+ }
+ }
+
+-
+-int luaO_str2d (const char *s, lua_Number *result) {
+- char *endptr;
+- *result = lua_str2number(s, &endptr);
+- if (endptr == s) return 0; /* conversion failed */
+- if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */
+- *result = cast_num(strtoul(s, &endptr, 16));
+- if (*endptr == '\0') return 1; /* most common case */
+- while (isspace(cast(unsigned char, *endptr))) endptr++;
+- if (*endptr != '\0') return 0; /* invalid trailing characters? */
+- return 1;
+-}
+-
+-
+-
+ static void pushstr (lua_State *L, const char *str) {
+ setsvalue2s(L, L->top, luaS_new(L, str));
+ incr_top(L);
+@@ -131,7 +136,11 @@
+ break;
+ }
+ case 'd': {
+- setnvalue(L->top, cast_num(va_arg(argp, int)));
++ /* This is tricky for 64-bit integers; maybe they even cannot be
++ * supported on all compilers; depends on the conversions applied to
++ * variable argument lists. TBD: test!
++ */
++ setivalue(L->top, (lua_Integer) va_arg(argp, l_uacInteger));
+ incr_top(L);
+ break;
+ }
+@@ -212,3 +221,4 @@
+ }
+ }
+ }
++
+Index: lua-5.1.4/src/lobject.h
+===================================================================
+--- lua-5.1.4.orig/src/lobject.h 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/lobject.h 2008-08-24 16:48:20.000000000 +0200
+@@ -17,7 +17,11 @@
+
+
+ /* tags for values visible from Lua */
+-#define LAST_TAG LUA_TTHREAD
++#if LUA_TINT > LUA_TTHREAD
++# define LAST_TAG LUA_TINT
++#else
++# define LAST_TAG LUA_TTHREAD
++#endif
+
+ #define NUM_TAGS (LAST_TAG+1)
+
+@@ -59,7 +63,12 @@
+ typedef union {
+ GCObject *gc;
+ void *p;
++#ifdef LNUM_COMPLEX
++ lua_Complex n;
++#else
+ lua_Number n;
++#endif
++ lua_Integer i;
+ int b;
+ } Value;
+
+@@ -77,7 +86,11 @@
+
+ /* Macros to test type */
+ #define ttisnil(o) (ttype(o) == LUA_TNIL)
+-#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
++#define ttisint(o) (ttype(o) == LUA_TINT)
++#define ttisnumber(o) ((ttype(o) == LUA_TINT) || (ttype(o) == LUA_TNUMBER))
++#ifdef LNUM_COMPLEX
++# define ttiscomplex(o) ((ttype(o) == LUA_TNUMBER) && (nvalue_img_fast(o)!=0))
++#endif
+ #define ttisstring(o) (ttype(o) == LUA_TSTRING)
+ #define ttistable(o) (ttype(o) == LUA_TTABLE)
+ #define ttisfunction(o) (ttype(o) == LUA_TFUNCTION)
+@@ -90,7 +103,25 @@
+ #define ttype(o) ((o)->tt)
+ #define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc)
+ #define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
+-#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n)
++
++#define ttype_ext(o) ( ttype(o) == LUA_TINT ? LUA_TNUMBER : ttype(o) )
++#define ttype_ext_same(o1,o2) ( (ttype(o1)==ttype(o2)) || (ttisnumber(o1) && ttisnumber(o2)) )
++
++/* '_fast' variants are for cases where 'ttype(o)' is known to be LUA_TNUMBER.
++ */
++#ifdef LNUM_COMPLEX
++# define nvalue_complex_fast(o) check_exp( ttype(o)==LUA_TNUMBER, (o)->value.n )
++# define nvalue_fast(o) ( _LF(creal) ( nvalue_complex_fast(o) ) )
++# define nvalue_img_fast(o) ( _LF(cimag) ( nvalue_complex_fast(o) ) )
++# define nvalue_complex(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? (o)->value.i : (o)->value.n )
++# define nvalue_img(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? 0 : _LF(cimag)( (o)->value.n ) )
++# define nvalue(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? cast_num((o)->value.i) : _LF(creal)((o)->value.n) )
++#else
++# define nvalue(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? cast_num((o)->value.i) : (o)->value.n )
++# define nvalue_fast(o) check_exp( ttype(o)==LUA_TNUMBER, (o)->value.n )
++#endif
++#define ivalue(o) check_exp( ttype(o)==LUA_TINT, (o)->value.i )
++
+ #define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts)
+ #define tsvalue(o) (&rawtsvalue(o)->tsv)
+ #define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u)
+@@ -116,8 +147,27 @@
+ /* Macros to set values */
+ #define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
+
+-#define setnvalue(obj,x) \
+- { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }
++/* Must not have side effects, 'x' may be expression.
++*/
++#define setivalue(obj,x) \
++ { TValue *i_o=(obj); i_o->value.i=(x); i_o->tt=LUA_TINT; }
++
++# define setnvalue(obj,x) \
++ { TValue *i_o=(obj); i_o->value.n= (x); i_o->tt=LUA_TNUMBER; }
++
++/* Note: Complex always has "inline", both are C99.
++*/
++#ifdef LNUM_COMPLEX
++ static inline void setnvalue_complex_fast( TValue *obj, lua_Complex x ) {
++ lua_assert( _LF(cimag)(x) != 0 );
++ obj->value.n= x; obj->tt= LUA_TNUMBER;
++ }
++ static inline void setnvalue_complex( TValue *obj, lua_Complex x ) {
++ if (_LF(cimag)(x) == 0) { setnvalue(obj, _LF(creal)(x)); }
++ else { obj->value.n= x; obj->tt= LUA_TNUMBER; }
++ }
++#endif
++
+
+ #define setpvalue(obj,x) \
+ { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; }
+@@ -155,9 +205,6 @@
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \
+ checkliveness(G(L),i_o); }
+
+-
+-
+-
+ #define setobj(L,obj1,obj2) \
+ { const TValue *o2=(obj2); TValue *o1=(obj1); \
+ o1->value = o2->value; o1->tt=o2->tt; \
+@@ -185,8 +232,11 @@
+
+ #define setttype(obj, tt) (ttype(obj) = (tt))
+
+-
+-#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
++#if LUA_TINT >= LUA_TSTRING
++# define iscollectable(o) ((ttype(o) >= LUA_TSTRING) && (ttype(o) != LUA_TINT))
++#else
++# define iscollectable(o) (ttype(o) >= LUA_TSTRING)
++#endif
+
+
+
+@@ -370,12 +420,10 @@
+ LUAI_FUNC int luaO_int2fb (unsigned int x);
+ LUAI_FUNC int luaO_fb2int (int x);
+ LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);
+-LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result);
+ LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
+ va_list argp);
+ LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
+ LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);
+
+-
+ #endif
+
+Index: lua-5.1.4/src/loslib.c
+===================================================================
+--- lua-5.1.4.orig/src/loslib.c 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/loslib.c 2008-08-24 16:48:20.000000000 +0200
+@@ -186,15 +186,30 @@
+ }
+ if (t == (time_t)(-1))
+ lua_pushnil(L);
+- else
+- lua_pushnumber(L, (lua_Number)t);
++ else {
++ /* On float systems the pushed value must be an integer, NOT a number.
++ * Otherwise, accuracy is lost in the time_t->float conversion.
++ */
++#ifdef LNUM_FLOAT
++ lua_pushinteger(L, (lua_Integer) t);
++#else
++ lua_pushnumber(L, (lua_Number) t);
++#endif
++ }
+ return 1;
+ }
+
+
+ static int os_difftime (lua_State *L) {
++#ifdef LNUM_FLOAT
++ lua_Integer i= (lua_Integer)
++ difftime( (time_t)(luaL_checkinteger(L, 1)),
++ (time_t)(luaL_optinteger(L, 2, 0)));
++ lua_pushinteger(L, i);
++#else
+ lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
+ (time_t)(luaL_optnumber(L, 2, 0))));
++#endif
+ return 1;
+ }
+
+Index: lua-5.1.4/src/lparser.c
+===================================================================
+--- lua-5.1.4.orig/src/lparser.c 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/lparser.c 2008-08-24 16:48:20.000000000 +0200
+@@ -33,7 +33,6 @@
+
+ #define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m)
+
+-
+ /*
+ ** nodes for block list (list of active blocks)
+ */
+@@ -72,7 +71,7 @@
+ const char *msg = (fs->f->linedefined == 0) ?
+ luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) :
+ luaO_pushfstring(fs->L, "function at line %d has more than %d %s",
+- fs->f->linedefined, limit, what);
++ (fs->f->linedefined), limit, what);
+ luaX_lexerror(fs->ls, msg, 0);
+ }
+
+@@ -733,6 +732,18 @@
+ v->u.nval = ls->t.seminfo.r;
+ break;
+ }
++ case TK_INT: {
++ init_exp(v, VKINT, 0);
++ v->u.ival = ls->t.seminfo.i;
++ break;
++ }
++#ifdef LNUM_COMPLEX
++ case TK_NUMBER2: {
++ init_exp(v, VKNUM2, 0);
++ v->u.nval = ls->t.seminfo.r;
++ break;
++ }
++#endif
+ case TK_STRING: {
+ codestring(ls, v, ls->t.seminfo.ts);
+ break;
+@@ -1079,7 +1090,7 @@
+ if (testnext(ls, ','))
+ exp1(ls); /* optional step */
+ else { /* default step = 1 */
+- luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
++ luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_integerK(fs, 1));
+ luaK_reserveregs(fs, 1);
+ }
+ forbody(ls, base, line, 1, 1);
+Index: lua-5.1.4/src/lparser.h
+===================================================================
+--- lua-5.1.4.orig/src/lparser.h 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/lparser.h 2008-08-24 16:48:20.000000000 +0200
+@@ -31,7 +31,11 @@
+ VRELOCABLE, /* info = instruction pc */
+ VNONRELOC, /* info = result register */
+ VCALL, /* info = instruction pc */
+- VVARARG /* info = instruction pc */
++ VVARARG, /* info = instruction pc */
++ VKINT /* ival = integer value */
++#ifdef LNUM_COMPLEX
++ ,VKNUM2 /* nval = imaginary value */
++#endif
+ } expkind;
+
+ typedef struct expdesc {
+@@ -39,6 +43,7 @@
+ union {
+ struct { int info, aux; } s;
+ lua_Number nval;
++ lua_Integer ival;
+ } u;
+ int t; /* patch list of `exit when true' */
+ int f; /* patch list of `exit when false' */
+Index: lua-5.1.4/src/lstrlib.c
+===================================================================
+--- lua-5.1.4.orig/src/lstrlib.c 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/lstrlib.c 2008-08-24 16:48:20.000000000 +0200
+@@ -43,8 +43,8 @@
+ static int str_sub (lua_State *L) {
+ size_t l;
+ const char *s = luaL_checklstring(L, 1, &l);
+- ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l);
+- ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l);
++ ptrdiff_t start = posrelat(luaL_checkint32(L, 2), l);
++ ptrdiff_t end = posrelat(luaL_optint32(L, 3, -1), l);
+ if (start < 1) start = 1;
+ if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;
+ if (start <= end)
+@@ -106,8 +106,8 @@
+ static int str_byte (lua_State *L) {
+ size_t l;
+ const char *s = luaL_checklstring(L, 1, &l);
+- ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l);
+- ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l);
++ ptrdiff_t posi = posrelat(luaL_optint32(L, 2, 1), l);
++ ptrdiff_t pose = posrelat(luaL_optint32(L, 3, posi), l);
+ int n, i;
+ if (posi <= 0) posi = 1;
+ if ((size_t)pose > l) pose = l;
+@@ -496,7 +496,7 @@
+ size_t l1, l2;
+ const char *s = luaL_checklstring(L, 1, &l1);
+ const char *p = luaL_checklstring(L, 2, &l2);
+- ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
++ ptrdiff_t init = posrelat(luaL_optint32(L, 3, 1), l1) - 1;
+ if (init < 0) init = 0;
+ else if ((size_t)(init) > l1) init = (ptrdiff_t)l1;
+ if (find && (lua_toboolean(L, 4) || /* explicit request? */
+@@ -690,7 +690,7 @@
+ ** maximum size of each format specification (such as '%-099.99d')
+ ** (+10 accounts for %99.99x plus margin of error)
+ */
+-#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
++#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTEGER_FMT)-2 + 10)
+
+
+ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
+@@ -747,9 +747,9 @@
+ static void addintlen (char *form) {
+ size_t l = strlen(form);
+ char spec = form[l - 1];
+- strcpy(form + l - 1, LUA_INTFRMLEN);
+- form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;
+- form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0';
++ const char *tmp= LUA_INTEGER_FMT; /* "%lld" or "%ld" */
++ strcpy(form + l - 1, tmp+1);
++ form[l + sizeof(LUA_INTEGER_FMT)-4] = spec;
+ }
+
+
+@@ -777,12 +777,12 @@
+ }
+ case 'd': case 'i': {
+ addintlen(form);
+- sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));
++ sprintf(buff, form, luaL_checkinteger(L, arg));
+ break;
+ }
+ case 'o': case 'u': case 'x': case 'X': {
+ addintlen(form);
+- sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
++ sprintf(buff, form, (unsigned LUA_INTEGER)luaL_checkinteger(L, arg));
+ break;
+ }
+ case 'e': case 'E': case 'f':
+Index: lua-5.1.4/src/ltable.c
+===================================================================
+--- lua-5.1.4.orig/src/ltable.c 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/ltable.c 2008-08-24 16:48:20.000000000 +0200
+@@ -33,6 +33,7 @@
+ #include "lobject.h"
+ #include "lstate.h"
+ #include "ltable.h"
++#include "lnum.h"
+
+
+ /*
+@@ -51,25 +52,15 @@
+
+ #define hashstr(t,str) hashpow2(t, (str)->tsv.hash)
+ #define hashboolean(t,p) hashpow2(t, p)
+-
++#define hashint(t,i) hashpow2(t,i)
+
+ /*
+ ** for some types, it is better to avoid modulus by power of 2, as
+ ** they tend to have many 2 factors.
+ */
+ #define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1))))
+-
+-
+ #define hashpointer(t,p) hashmod(t, IntPoint(p))
+
+-
+-/*
+-** number of ints inside a lua_Number
+-*/
+-#define numints cast_int(sizeof(lua_Number)/sizeof(int))
+-
+-
+-
+ #define dummynode (&dummynode_)
+
+ static const Node dummynode_ = {
+@@ -80,27 +71,46 @@
+
+ /*
+ ** hash for lua_Numbers
++**
++** for non-complex modes, never called with 'lua_Integer' value range (s.a. 0)
+ */
+ static Node *hashnum (const Table *t, lua_Number n) {
+- unsigned int a[numints];
+- int i;
+- if (luai_numeq(n, 0)) /* avoid problems with -0 */
+- return gnode(t, 0);
+- memcpy(a, &n, sizeof(a));
+- for (i = 1; i < numints; i++) a[0] += a[i];
+- return hashmod(t, a[0]);
++ const unsigned int *p= cast(const unsigned int *,&n);
++ unsigned int sum= *p;
++ unsigned int m= sizeof(lua_Number)/sizeof(int);
++ unsigned int i;
++ /* OS X Intel has 'm'==4 and gives "Bus error" if the last integer of
++ * 'n' is read; the actual size of long double is only 80 bits = 10 bytes.
++ * Linux x86 has 'm'==3, and does not require reduction.
++ */
++#if defined(LNUM_LDOUBLE) && defined(__i386__)
++ if (m>3) m--;
++#endif
++ for (i = 1; i < m; i++) sum += p[i];
++ return hashmod(t, sum);
+ }
+
+
+-
+ /*
+ ** returns the `main' position of an element in a table (that is, the index
+ ** of its hash value)
++**
++** Floating point numbers with integer value give the hash position of the
++** integer (so they use the same table position).
+ */
+ static Node *mainposition (const Table *t, const TValue *key) {
++ lua_Integer i;
+ switch (ttype(key)) {
+ case LUA_TNUMBER:
+- return hashnum(t, nvalue(key));
++ if (tt_integer_valued(key,&i))
++ return hashint(t, i);
++#ifdef LNUM_COMPLEX
++ if (nvalue_img_fast(key)!=0 && luai_numeq(nvalue_fast(key),0))
++ return gnode(t, 0); /* 0 and -0 to give same hash */
++#endif
++ return hashnum(t, nvalue_fast(key));
++ case LUA_TINT:
++ return hashint(t, ivalue(key));
+ case LUA_TSTRING:
+ return hashstr(t, rawtsvalue(key));
+ case LUA_TBOOLEAN:
+@@ -116,16 +126,20 @@
+ /*
+ ** returns the index for `key' if `key' is an appropriate key to live in
+ ** the array part of the table, -1 otherwise.
++**
++** Anything <=0 is taken as not being in the array part.
+ */
+-static int arrayindex (const TValue *key) {
+- if (ttisnumber(key)) {
+- lua_Number n = nvalue(key);
+- int k;
+- lua_number2int(k, n);
+- if (luai_numeq(cast_num(k), n))
+- return k;
++static int arrayindex (const TValue *key, int max) {
++ lua_Integer k;
++ switch( ttype(key) ) {
++ case LUA_TINT:
++ k= ivalue(key); break;
++ case LUA_TNUMBER:
++ if (tt_integer_valued(key,&k)) break;
++ default:
++ return -1; /* not to be used as array index */
+ }
+- return -1; /* `key' did not match some condition */
++ return ((k>0) && (k <= max)) ? cast_int(k) : -1;
+ }
+
+
+@@ -137,8 +151,8 @@
+ static int findindex (lua_State *L, Table *t, StkId key) {
+ int i;
+ if (ttisnil(key)) return -1; /* first iteration */
+- i = arrayindex(key);
+- if (0 < i && i <= t->sizearray) /* is `key' inside array part? */
++ i = arrayindex(key, t->sizearray);
++ if (i>0) /* inside array part? */
+ return i-1; /* yes; that's the index (corrected to C) */
+ else {
+ Node *n = mainposition(t, key);
+@@ -163,7 +177,7 @@
+ int i = findindex(L, t, key); /* find original element */
+ for (i++; i < t->sizearray; i++) { /* try first array part */
+ if (!ttisnil(&t->array[i])) { /* a non-nil value? */
+- setnvalue(key, cast_num(i+1));
++ setivalue(key, i+1);
+ setobj2s(L, key+1, &t->array[i]);
+ return 1;
+ }
+@@ -209,8 +223,8 @@
+
+
+ static int countint (const TValue *key, int *nums) {
+- int k = arrayindex(key);
+- if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */
++ int k = arrayindex(key,MAXASIZE);
++ if (k>0) { /* appropriate array index? */
+ nums[ceillog2(k)]++; /* count as such */
+ return 1;
+ }
+@@ -308,7 +322,7 @@
+ /* re-insert elements from vanishing slice */
+ for (i=nasize; i<oldasize; i++) {
+ if (!ttisnil(&t->array[i]))
+- setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);
++ setobjt2t(L, luaH_setint(L, t, i+1), &t->array[i]);
+ }
+ /* shrink array */
+ luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
+@@ -409,7 +423,9 @@
+ othern = mainposition(t, key2tval(mp));
+ if (othern != mp) { /* is colliding node out of its main position? */
+ /* yes; move colliding node into free position */
+- while (gnext(othern) != mp) othern = gnext(othern); /* find previous */
++ while (gnext(othern) != mp) {
++ othern = gnext(othern); /* find previous */
++ }
+ gnext(othern) = n; /* redo the chain with `n' in place of `mp' */
+ *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */
+ gnext(mp) = NULL; /* now `mp' is free */
+@@ -432,17 +448,18 @@
+ /*
+ ** search function for integers
+ */
+-const TValue *luaH_getnum (Table *t, int key) {
++const TValue *luaH_getint (Table *t, lua_Integer key) {
+ /* (1 <= key && key <= t->sizearray) */
+ if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
+ return &t->array[key-1];
+ else {
+- lua_Number nk = cast_num(key);
+- Node *n = hashnum(t, nk);
++ Node *n = hashint(t, key);
+ do { /* check whether `key' is somewhere in the chain */
+- if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))
++ if (ttisint(gkey(n)) && (ivalue(gkey(n)) == key)) {
+ return gval(n); /* that's it */
+- else n = gnext(n);
++ } else {
++ n = gnext(n);
++ }
+ } while (n);
+ return luaO_nilobject;
+ }
+@@ -470,14 +487,12 @@
+ switch (ttype(key)) {
+ case LUA_TNIL: return luaO_nilobject;
+ case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
++ case LUA_TINT: return luaH_getint(t, ivalue(key));
+ case LUA_TNUMBER: {
+- int k;
+- lua_Number n = nvalue(key);
+- lua_number2int(k, n);
+- if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
+- return luaH_getnum(t, k); /* use specialized version */
+- /* else go through */
+- }
++ lua_Integer i;
++ if (tt_integer_valued(key,&i))
++ return luaH_getint(t,i);
++ } /* pass through */
+ default: {
+ Node *n = mainposition(t, key);
+ do { /* check whether `key' is somewhere in the chain */
+@@ -498,20 +513,25 @@
+ return cast(TValue *, p);
+ else {
+ if (ttisnil(key)) luaG_runerror(L, "table index is nil");
+- else if (ttisnumber(key) && luai_numisnan(nvalue(key)))
+- luaG_runerror(L, "table index is NaN");
++ else if (ttype(key)==LUA_TNUMBER) {
++ lua_Integer k;
++ if (luai_numisnan(nvalue_fast(key)))
++ luaG_runerror(L, "table index is NaN");
++ if (tt_integer_valued(key,&k))
++ return luaH_setint(L, t, k);
++ }
+ return newkey(L, t, key);
+ }
+ }
+
+
+-TValue *luaH_setnum (lua_State *L, Table *t, int key) {
+- const TValue *p = luaH_getnum(t, key);
++TValue *luaH_setint (lua_State *L, Table *t, lua_Integer key) {
++ const TValue *p = luaH_getint(t, key);
+ if (p != luaO_nilobject)
+ return cast(TValue *, p);
+ else {
+ TValue k;
+- setnvalue(&k, cast_num(key));
++ setivalue(&k, key);
+ return newkey(L, t, &k);
+ }
+ }
+@@ -533,20 +553,21 @@
+ unsigned int i = j; /* i is zero or a present index */
+ j++;
+ /* find `i' and `j' such that i is present and j is not */
+- while (!ttisnil(luaH_getnum(t, j))) {
++ while (!ttisnil(luaH_getint(t, j))) {
+ i = j;
+ j *= 2;
+ if (j > cast(unsigned int, MAX_INT)) { /* overflow? */
+ /* table was built with bad purposes: resort to linear search */
+- i = 1;
+- while (!ttisnil(luaH_getnum(t, i))) i++;
+- return i - 1;
++ for( i = 1; i<MAX_INT+1; i++ ) {
++ if (ttisnil(luaH_getint(t, i))) break;
++ }
++ return i - 1; /* up to MAX_INT */
+ }
+ }
+ /* now do a binary search between them */
+ while (j - i > 1) {
+ unsigned int m = (i+j)/2;
+- if (ttisnil(luaH_getnum(t, m))) j = m;
++ if (ttisnil(luaH_getint(t, m))) j = m;
+ else i = m;
+ }
+ return i;
+Index: lua-5.1.4/src/ltable.h
+===================================================================
+--- lua-5.1.4.orig/src/ltable.h 2008-08-24 16:46:37.000000000 +0200
++++ lua-5.1.4/src/ltable.h 2008-08-24 16:48:20.000000000 +0200
+@@ -18,8 +18,8 @@
+ #define key2tval(n) (&(n)->i_key.tvk)
+
+
+-LUAI_FUNC const TValue *luaH_getnum (Table *t, int key);
+-LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key);
++LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
++LUAI_FUNC TValue *luaH_setint (lua_State *L, Table *t, lua_Integer key);
+ LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
+ LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);
+ LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
+Index: lua-5.1.4/src/ltm.c
+===================================================================
+--- lua-5.1.4.orig/src/ltm.c 2008-08-24 16:46:38.000000000 +0200
++++ lua-5.1.4/src/ltm.c 2008-08-24 16:48:20.000000000 +0200
+@@ -19,7 +19,6 @@
+ #include "ltm.h"
+
+
+-
+ const char *const luaT_typenames[] = {
+ "nil", "boolean", "userdata", "number",
+ "string", "table", "function", "userdata", "thread",
+@@ -67,6 +66,9 @@
+ case LUA_TUSERDATA:
+ mt = uvalue(o)->metatable;
+ break;
++ case LUA_TINT:
++ mt = G(L)->mt[LUA_TNUMBER];
++ break;
+ default:
+ mt = G(L)->mt[ttype(o)];
+ }
+Index: lua-5.1.4/src/lua.c
+===================================================================
+--- lua-5.1.4.orig/src/lua.c 2008-08-24 16:46:38.000000000 +0200
++++ lua-5.1.4/src/lua.c 2008-08-24 16:48:20.000000000 +0200
+@@ -16,7 +16,7 @@
+
+ #include "lauxlib.h"
+ #include "lualib.h"
+-
++#include "llimits.h"
+
+
+ static lua_State *globalL = NULL;
+@@ -382,6 +382,15 @@
+ l_message(argv[0], "cannot create state: not enough memory");
+ return EXIT_FAILURE;
+ }
++ /* Checking 'sizeof(lua_Integer)' cannot be made in preprocessor on all compilers.
++ */
++#ifdef LNUM_INT16
++ lua_assert( sizeof(lua_Integer) == 2 );
++#elif defined(LNUM_INT32)
++ lua_assert( sizeof(lua_Integer) == 4 );
++#elif defined(LNUM_INT64)
++ lua_assert( sizeof(lua_Integer) == 8 );
++#endif
+ s.argc = argc;
+ s.argv = argv;
+ status = lua_cpcall(L, &pmain, &s);
+Index: lua-5.1.4/src/lua.h
+===================================================================
+--- lua-5.1.4.orig/src/lua.h 2008-08-24 16:46:38.000000000 +0200
++++ lua-5.1.4/src/lua.h 2008-08-24 16:48:20.000000000 +0200
+@@ -19,7 +19,7 @@
+ #define LUA_VERSION "Lua 5.1"
+ #define LUA_RELEASE "Lua 5.1.4"
+ #define LUA_VERSION_NUM 501
+-#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio"
++#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" " (" LUA_LNUM ")"
+ #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
+
+
+@@ -71,6 +71,16 @@
+ */
+ #define LUA_TNONE (-1)
+
++/* LUA_TINT is an internal type, not visible to applications. There are three
++ * potential values where it can be tweaked to (code autoadjusts to these):
++ *
++ * -2: not 'usual' type value; good since 'LUA_TINT' is not part of the API
++ * LUA_TNUMBER+1: shifts other type values upwards, breaking binary compatibility
++ * not acceptable for 5.1, maybe 5.2 onwards?
++ * 9: greater than existing (5.1) type values.
++*/
++#define LUA_TINT (-2)
++
+ #define LUA_TNIL 0
+ #define LUA_TBOOLEAN 1
+ #define LUA_TLIGHTUSERDATA 2
+@@ -139,6 +149,8 @@
+ LUA_API int (lua_type) (lua_State *L, int idx);
+ LUA_API const char *(lua_typename) (lua_State *L, int tp);
+
++LUA_API int (lua_isinteger) (lua_State *L, int idx);
++
+ LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2);
+ LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
+ LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2);
+@@ -244,6 +256,19 @@
+ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
+
+
++/*
++* It is unnecessary to break Lua C API 'lua_tonumber()' compatibility, just
++* because the Lua number type is complex. Most C modules would use scalars
++* only. We'll introduce new 'lua_tocomplex' and 'lua_pushcomplex' for when
++* the module really wants to use them.
++*/
++#ifdef LNUM_COMPLEX
++ #include <complex.h>
++ typedef LUA_NUMBER complex lua_Complex;
++ LUA_API lua_Complex (lua_tocomplex) (lua_State *L, int idx);
++ LUA_API void (lua_pushcomplex) (lua_State *L, lua_Complex v);
++#endif
++
+
+ /*
+ ** ===============================================================
+@@ -268,7 +293,12 @@
+ #define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
+ #define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
+ #define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
+-#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
++
++#if LUA_TINT < 0
++# define lua_isnoneornil(L, n) ( (lua_type(L,(n)) <= 0) && (lua_type(L,(n)) != LUA_TINT) )
++#else
++# define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
++#endif
+
+ #define lua_pushliteral(L, s) \
+ lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
+@@ -386,3 +416,4 @@
+
+
+ #endif
++
+Index: lua-5.1.4/src/luaconf.h
+===================================================================
+--- lua-5.1.4.orig/src/luaconf.h 2008-08-24 16:46:38.000000000 +0200
++++ lua-5.1.4/src/luaconf.h 2008-08-24 16:48:20.000000000 +0200
+@@ -10,7 +10,9 @@
+
+ #include <limits.h>
+ #include <stddef.h>
+-
++#ifdef lua_assert
++# include <assert.h>
++#endif
+
+ /*
+ ** ==================================================================
+@@ -136,14 +138,38 @@
+
+
+ /*
+-@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.
+-** CHANGE that if ptrdiff_t is not adequate on your machine. (On most
+-** machines, ptrdiff_t gives a good choice between int or long.)
++@@ LUAI_BITSINT defines the number of bits in an int.
++** CHANGE here if Lua cannot automatically detect the number of bits of
++** your machine. Probably you do not need to change this.
+ */
+-#define LUA_INTEGER ptrdiff_t
++/* avoid overflows in comparison */
++#if INT_MAX-20 < 32760
++#define LUAI_BITSINT 16
++#elif INT_MAX > 2147483640L
++/* int has at least 32 bits */
++#define LUAI_BITSINT 32
++#else
++#error "you must define LUA_BITSINT with number of bits in an integer"
++#endif
+
+
+ /*
++@@ LNUM_DOUBLE | LNUM_FLOAT | LNUM_LDOUBLE: Generic Lua number mode
++@@ LNUM_INT32 | LNUM_INT64: Integer type
++@@ LNUM_COMPLEX: Define for using 'a+bi' numbers
++@@
++@@ You can combine LNUM_xxx but only one of each group. I.e. '-DLNUM_FLOAT
++@@ -DLNUM_INT32 -DLNUM_COMPLEX' gives float range complex numbers, with
++@@ 32-bit scalar integer range optimized.
++**
++** These are kept in a separate configuration file mainly for ease of patching
++** (can be changed if integerated to Lua proper).
++*/
++/*#define LNUM_DOUBLE*/
++/*#define LNUM_INT32*/
++#include "lnum_config.h"
++
++/*
+ @@ LUA_API is a mark for all core API functions.
+ @@ LUALIB_API is a mark for all standard library functions.
+ ** CHANGE them if you need to define those functions in some special way.
+@@ -383,22 +409,6 @@
+
+
+ /*
+-@@ LUAI_BITSINT defines the number of bits in an int.
+-** CHANGE here if Lua cannot automatically detect the number of bits of
+-** your machine. Probably you do not need to change this.
+-*/
+-/* avoid overflows in comparison */
+-#if INT_MAX-20 < 32760
+-#define LUAI_BITSINT 16
+-#elif INT_MAX > 2147483640L
+-/* int has at least 32 bits */
+-#define LUAI_BITSINT 32
+-#else
+-#error "you must define LUA_BITSINT with number of bits in an integer"
+-#endif
+-
+-
+-/*
+ @@ LUAI_UINT32 is an unsigned integer with at least 32 bits.
+ @@ LUAI_INT32 is an signed integer with at least 32 bits.
+ @@ LUAI_UMEM is an unsigned integer big enough to count the total
+@@ -425,6 +435,15 @@
+ #define LUAI_MEM long
+ #endif
+
++/*
++@@ LUAI_BOOL carries 0 and nonzero (normally 1). It may be defined as 'char'
++** (to save memory), 'int' (for speed), 'bool' (for C++) or '_Bool' (C99)
++*/
++#ifdef __cplusplus
++# define LUAI_BOOL bool
++#else
++# define LUAI_BOOL int
++#endif
+
+ /*
+ @@ LUAI_MAXCALLS limits the number of nested calls.
+@@ -490,101 +509,6 @@
+ /* }================================================================== */
+
+
+-
+-
+-/*
+-** {==================================================================
+-@@ LUA_NUMBER is the type of numbers in Lua.
+-** CHANGE the following definitions only if you want to build Lua
+-** with a number type different from double. You may also need to
+-** change lua_number2int & lua_number2integer.
+-** ===================================================================
+-*/
+-
+-#define LUA_NUMBER_DOUBLE
+-#define LUA_NUMBER double
+-
+-/*
+-@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
+-@* over a number.
+-*/
+-#define LUAI_UACNUMBER double
+-
+-
+-/*
+-@@ LUA_NUMBER_SCAN is the format for reading numbers.
+-@@ LUA_NUMBER_FMT is the format for writing numbers.
+-@@ lua_number2str converts a number to a string.
+-@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.
+-@@ lua_str2number converts a string to a number.
+-*/
+-#define LUA_NUMBER_SCAN "%lf"
+-#define LUA_NUMBER_FMT "%.14g"
+-#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
+-#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */
+-#define lua_str2number(s,p) strtod((s), (p))
+-
+-
+-/*
+-@@ The luai_num* macros define the primitive operations over numbers.
+-*/
+-#if defined(LUA_CORE)
+-#include <math.h>
+-#define luai_numadd(a,b) ((a)+(b))
+-#define luai_numsub(a,b) ((a)-(b))
+-#define luai_nummul(a,b) ((a)*(b))
+-#define luai_numdiv(a,b) ((a)/(b))
+-#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b))
+-#define luai_numpow(a,b) (pow(a,b))
+-#define luai_numunm(a) (-(a))
+-#define luai_numeq(a,b) ((a)==(b))
+-#define luai_numlt(a,b) ((a)<(b))
+-#define luai_numle(a,b) ((a)<=(b))
+-#define luai_numisnan(a) (!luai_numeq((a), (a)))
+-#endif
+-
+-
+-/*
+-@@ lua_number2int is a macro to convert lua_Number to int.
+-@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
+-** CHANGE them if you know a faster way to convert a lua_Number to
+-** int (with any rounding method and without throwing errors) in your
+-** system. In Pentium machines, a naive typecast from double to int
+-** in C is extremely slow, so any alternative is worth trying.
+-*/
+-
+-/* On a Pentium, resort to a trick */
+-#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \
+- (defined(__i386) || defined (_M_IX86) || defined(__i386__))
+-
+-/* On a Microsoft compiler, use assembler */
+-#if defined(_MSC_VER)
+-
+-#define lua_number2int(i,d) __asm fld d __asm fistp i
+-#define lua_number2integer(i,n) lua_number2int(i, n)
+-
+-/* the next trick should work on any Pentium, but sometimes clashes
+- with a DirectX idiosyncrasy */
+-#else
+-
+-union luai_Cast { double l_d; long l_l; };
+-#define lua_number2int(i,d) \
+- { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
+-#define lua_number2integer(i,n) lua_number2int(i, n)
+-
+-#endif
+-
+-
+-/* this option always works, but may be slow */
+-#else
+-#define lua_number2int(i,d) ((i)=(int)(d))
+-#define lua_number2integer(i,d) ((i)=(lua_Integer)(d))
+-
+-#endif
+-
+-/* }================================================================== */
+-
+-
+ /*
+ @@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment.
+ ** CHANGE it if your system requires alignments larger than double. (For
+@@ -728,28 +652,6 @@
+ #define luai_userstateyield(L,n) ((void)L)
+
+
+-/*
+-@@ LUA_INTFRMLEN is the length modifier for integer conversions
+-@* in 'string.format'.
+-@@ LUA_INTFRM_T is the integer type correspoding to the previous length
+-@* modifier.
+-** CHANGE them if your system supports long long or does not support long.
+-*/
+-
+-#if defined(LUA_USELONGLONG)
+-
+-#define LUA_INTFRMLEN "ll"
+-#define LUA_INTFRM_T long long
+-
+-#else
+-
+-#define LUA_INTFRMLEN "l"
+-#define LUA_INTFRM_T long
+-
+-#endif
+-
+-
+-
+ /* =================================================================== */
+
+ /*
+Index: lua-5.1.4/src/lundump.c
+===================================================================
+--- lua-5.1.4.orig/src/lundump.c 2008-08-24 16:46:38.000000000 +0200
++++ lua-5.1.4/src/lundump.c 2008-08-24 16:48:20.000000000 +0200
+@@ -73,6 +73,13 @@
+ return x;
+ }
+
++static lua_Integer LoadInteger(LoadState* S)
++{
++ lua_Integer x;
++ LoadVar(S,x);
++ return x;
++}
++
+ static TString* LoadString(LoadState* S)
+ {
+ size_t size;
+@@ -119,6 +126,9 @@
+ case LUA_TNUMBER:
+ setnvalue(o,LoadNumber(S));
+ break;
++ case LUA_TINT: /* Integer type saved in bytecode (see lcode.c) */
++ setivalue(o,LoadInteger(S));
++ break;
+ case LUA_TSTRING:
+ setsvalue2n(S->L,o,LoadString(S));
+ break;
+@@ -223,5 +233,22 @@
+ *h++=(char)sizeof(size_t);
+ *h++=(char)sizeof(Instruction);
+ *h++=(char)sizeof(lua_Number);
+- *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */
++
++ /*
++ * Last byte of header (0/1 in unpatched Lua 5.1.3):
++ *
++ * 0: lua_Number is float or double, lua_Integer not used. (nonpatched only)
++ * 1: lua_Number is integer (nonpatched only)
++ *
++ * +2: LNUM_INT16: sizeof(lua_Integer)
++ * +4: LNUM_INT32: sizeof(lua_Integer)
++ * +8: LNUM_INT64: sizeof(lua_Integer)
++ *
++ * +0x80: LNUM_COMPLEX
++ */
++ *h++ = (char)(sizeof(lua_Integer)
++#ifdef LNUM_COMPLEX
++ | 0x80
++#endif
++ );
+ }
+Index: lua-5.1.4/src/lvm.c
+===================================================================
+--- lua-5.1.4.orig/src/lvm.c 2008-08-24 16:46:38.000000000 +0200
++++ lua-5.1.4/src/lvm.c 2008-08-24 16:48:20.000000000 +0200
+@@ -25,22 +25,35 @@
+ #include "ltable.h"
+ #include "ltm.h"
+ #include "lvm.h"
+-
+-
++#include "llex.h"
++#include "lnum.h"
+
+ /* limit for table tag-method chains (to avoid loops) */
+ #define MAXTAGLOOP 100
+
+
+-const TValue *luaV_tonumber (const TValue *obj, TValue *n) {
+- lua_Number num;
++/*
++ * If 'obj' is a string, it is tried to be interpreted as a number.
++ */
++const TValue *luaV_tonumber ( const TValue *obj, TValue *n) {
++ lua_Number d;
++ lua_Integer i;
++
+ if (ttisnumber(obj)) return obj;
+- if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
+- setnvalue(n, num);
+- return n;
+- }
+- else
+- return NULL;
++
++ if (ttisstring(obj)) {
++ switch( luaO_str2d( svalue(obj), &d, &i ) ) {
++ case TK_INT:
++ setivalue(n,i); return n;
++ case TK_NUMBER:
++ setnvalue(n,d); return n;
++#ifdef LNUM_COMPLEX
++ case TK_NUMBER2: /* "N.NNNi", != 0 */
++ setnvalue_complex_fast(n, d*I); return n;
++#endif
++ }
++ }
++ return NULL;
+ }
+
+
+@@ -49,8 +62,7 @@
+ return 0;
+ else {
+ char s[LUAI_MAXNUMBER2STR];
+- lua_Number n = nvalue(obj);
+- lua_number2str(s, n);
++ luaO_num2buf(s,obj);
+ setsvalue2s(L, obj, luaS_new(L, s));
+ return 1;
+ }
+@@ -218,59 +230,127 @@
+ }
+
+
++#ifdef LNUM_COMPLEX
++void error_complex( lua_State *L, const TValue *l, const TValue *r )
++{
++ char buf1[ LUAI_MAXNUMBER2STR ];
++ char buf2[ LUAI_MAXNUMBER2STR ];
++ luaO_num2buf( buf1, l );
++ luaO_num2buf( buf2, r );
++ luaG_runerror( L, "unable to compare: %s with %s", buf1, buf2 );
++ /* no return */
++}
++#endif
++
++
+ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
+ int res;
+- if (ttype(l) != ttype(r))
++ int tl,tr;
++ lua_Integer tmp;
++
++ if (!ttype_ext_same(l,r))
+ return luaG_ordererror(L, l, r);
+- else if (ttisnumber(l))
+- return luai_numlt(nvalue(l), nvalue(r));
+- else if (ttisstring(l))
+- return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
+- else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
++#ifdef LNUM_COMPLEX
++ if ( (nvalue_img(l)!=0) || (nvalue_img(r)!=0) )
++ error_complex( L, l, r );
++#endif
++ tl= ttype(l); tr= ttype(r);
++ if (tl==tr) { /* clear arithmetics */
++ switch(tl) {
++ case LUA_TINT: return ivalue(l) < ivalue(r);
++ case LUA_TNUMBER: return luai_numlt(nvalue_fast(l), nvalue_fast(r));
++ case LUA_TSTRING: return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
++ }
++ } else if (tl==LUA_TINT) { /* l:int, r:num */
++ /* Avoid accuracy losing casts: if 'r' is integer by value, do comparisons
++ * in integer realm. Only otherwise cast 'l' to FP (which might change its
++ * value).
++ */
++ if (tt_integer_valued(r,&tmp))
++ return ivalue(l) < tmp;
++ else
++ return luai_numlt( cast_num(ivalue(l)), nvalue_fast(r) );
++
++ } else if (tl==LUA_TNUMBER) { /* l:num, r:int */
++ if (tt_integer_valued(l,&tmp))
++ return tmp < ivalue(r);
++ else
++ return luai_numlt( nvalue_fast(l), cast_num(ivalue(r)) );
++
++ } else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
+ return res;
++
+ return luaG_ordererror(L, l, r);
+ }
+
+
+ static int lessequal (lua_State *L, const TValue *l, const TValue *r) {
+ int res;
+- if (ttype(l) != ttype(r))
++ int tl, tr;
++ lua_Integer tmp;
++
++ if (!ttype_ext_same(l,r))
+ return luaG_ordererror(L, l, r);
+- else if (ttisnumber(l))
+- return luai_numle(nvalue(l), nvalue(r));
+- else if (ttisstring(l))
+- return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
+- else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */
++#ifdef LNUM_COMPLEX
++ if ( (nvalue_img(l)!=0) || (nvalue_img(r)!=0) )
++ error_complex( L, l, r );
++#endif
++ tl= ttype(l); tr= ttype(r);
++ if (tl==tr) { /* clear arithmetics */
++ switch(tl) {
++ case LUA_TINT: return ivalue(l) <= ivalue(r);
++ case LUA_TNUMBER: return luai_numle(nvalue_fast(l), nvalue_fast(r));
++ case LUA_TSTRING: return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
++ }
++ }
++ if (tl==LUA_TINT) { /* l:int, r:num */
++ if (tt_integer_valued(r,&tmp))
++ return ivalue(l) <= tmp;
++ else
++ return luai_numle( cast_num(ivalue(l)), nvalue_fast(r) );
++
++ } else if (tl==LUA_TNUMBER) { /* l:num, r:int */
++ if (tt_integer_valued(l,&tmp))
++ return tmp <= ivalue(r);
++ else
++ return luai_numle( nvalue_fast(l), cast_num(ivalue(r)) );
++
++ } else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */
+ return res;
+ else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */
+ return !res;
++
+ return luaG_ordererror(L, l, r);
+ }
+
+
+-int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {
++/* Note: 'luaV_equalval()' and 'luaO_rawequalObj()' have largely overlapping
++ * implementation. LUA_TNIL..LUA_TLIGHTUSERDATA cases could be handled
++ * simply by the 'default' case here.
++ */
++int luaV_equalval (lua_State *L, const TValue *l, const TValue *r) {
+ const TValue *tm;
+- lua_assert(ttype(t1) == ttype(t2));
+- switch (ttype(t1)) {
++ lua_assert(ttype_ext_same(l,r));
++ switch (ttype(l)) {
+ case LUA_TNIL: return 1;
+- case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
+- case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
+- case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
++ case LUA_TINT:
++ case LUA_TNUMBER: return luaO_rawequalObj(l,r);
++ case LUA_TBOOLEAN: return bvalue(l) == bvalue(r); /* true must be 1 !! */
++ case LUA_TLIGHTUSERDATA: return pvalue(l) == pvalue(r);
+ case LUA_TUSERDATA: {
+- if (uvalue(t1) == uvalue(t2)) return 1;
+- tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable,
+- TM_EQ);
++ if (uvalue(l) == uvalue(r)) return 1;
++ tm = get_compTM(L, uvalue(l)->metatable, uvalue(r)->metatable, TM_EQ);
+ break; /* will try TM */
+ }
+ case LUA_TTABLE: {
+- if (hvalue(t1) == hvalue(t2)) return 1;
+- tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
++ if (hvalue(l) == hvalue(r)) return 1;
++ tm = get_compTM(L, hvalue(l)->metatable, hvalue(r)->metatable, TM_EQ);
+ break; /* will try TM */
+ }
+- default: return gcvalue(t1) == gcvalue(t2);
++ default: return gcvalue(l) == gcvalue(r);
+ }
+ if (tm == NULL) return 0; /* no TM? */
+- callTMres(L, L->top, tm, t1, t2); /* call TM */
++ callTMres(L, L->top, tm, l, r); /* call TM */
+ return !l_isfalse(L->top);
+ }
+
+@@ -310,30 +390,6 @@
+ }
+
+
+-static void Arith (lua_State *L, StkId ra, const TValue *rb,
+- const TValue *rc, TMS op) {
+- TValue tempb, tempc;
+- const TValue *b, *c;
+- if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
+- (c = luaV_tonumber(rc, &tempc)) != NULL) {
+- lua_Number nb = nvalue(b), nc = nvalue(c);
+- switch (op) {
+- case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break;
+- case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;
+- case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;
+- case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break;
+- case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break;
+- case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;
+- case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;
+- default: lua_assert(0); break;
+- }
+- }
+- else if (!call_binTM(L, rb, rc, ra, op))
+- luaG_aritherror(L, rb, rc);
+-}
+-
+-
+-
+ /*
+ ** some macros for common tasks in `luaV_execute'
+ */
+@@ -357,17 +413,154 @@
+ #define Protect(x) { L->savedpc = pc; {x;}; base = L->base; }
+
+
+-#define arith_op(op,tm) { \
+- TValue *rb = RKB(i); \
+- TValue *rc = RKC(i); \
+- if (ttisnumber(rb) && ttisnumber(rc)) { \
+- lua_Number nb = nvalue(rb), nc = nvalue(rc); \
+- setnvalue(ra, op(nb, nc)); \
+- } \
+- else \
+- Protect(Arith(L, ra, rb, rc, tm)); \
++/* Note: if called for unary operations, 'rc'=='rb'.
++ */
++static void Arith (lua_State *L, StkId ra, const TValue *rb,
++ const TValue *rc, TMS op) {
++ TValue tempb, tempc;
++ const TValue *b, *c;
++ lua_Number nb,nc;
++
++ if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
++ (c = luaV_tonumber(rc, &tempc)) != NULL) {
++
++ /* Keep integer arithmetics in the integer realm, if possible.
++ */
++ if (ttisint(b) && ttisint(c)) {
++ lua_Integer ib = ivalue(b), ic = ivalue(c);
++ lua_Integer *ri = &ra->value.i;
++ ra->tt= LUA_TINT; /* part of 'setivalue(ra)' */
++ switch (op) {
++ case TM_ADD: if (try_addint( ri, ib, ic)) return; break;
++ case TM_SUB: if (try_subint( ri, ib, ic)) return; break;
++ case TM_MUL: if (try_mulint( ri, ib, ic)) return; break;
++ case TM_DIV: if (try_divint( ri, ib, ic)) return; break;
++ case TM_MOD: if (try_modint( ri, ib, ic)) return; break;
++ case TM_POW: if (try_powint( ri, ib, ic)) return; break;
++ case TM_UNM: if (try_unmint( ri, ib)) return; break;
++ default: lua_assert(0);
++ }
++ }
++ /* Fallback to floating point, when leaving range. */
++
++#ifdef LNUM_COMPLEX
++ if ((nvalue_img(b)!=0) || (nvalue_img(c)!=0)) {
++ lua_Complex r;
++ if (op==TM_UNM) {
++ r= -nvalue_complex_fast(b); /* never an integer (or scalar) */
++ setnvalue_complex_fast( ra, r );
++ } else {
++ lua_Complex bb= nvalue_complex(b), cc= nvalue_complex(c);
++ switch (op) {
++ case TM_ADD: r= bb + cc; break;
++ case TM_SUB: r= bb - cc; break;
++ case TM_MUL: r= bb * cc; break;
++ case TM_DIV: r= bb / cc; break;
++ case TM_MOD:
++ luaG_runerror(L, "attempt to use %% on complex numbers"); /* no return */
++ case TM_POW: r= luai_vectpow( bb, cc ); break;
++ default: lua_assert(0); r=0;
++ }
++ setnvalue_complex( ra, r );
+ }
++ return;
++ }
++#endif
++ nb = nvalue(b); nc = nvalue(c);
++ switch (op) {
++ case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); return;
++ case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); return;
++ case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); return;
++ case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); return;
++ case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); return;
++ case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); return;
++ case TM_UNM: setnvalue(ra, luai_numunm(nb)); return;
++ default: lua_assert(0);
++ }
++ }
++
++ /* Either operand not a number */
++ if (!call_binTM(L, rb, rc, ra, op))
++ luaG_aritherror(L, rb, rc);
++}
+
++/* Helper macro to sort arithmetic operations into four categories:
++ * TK_INT: integer - integer operands
++ * TK_NUMBER: number - number (non complex, either may be integer)
++ * TK_NUMBER2: complex numbers (at least the other)
++ * 0: non-numeric (at least the other)
++*/
++#ifdef LNUM_COMPLEX
++static inline int arith_mode( const TValue *rb, const TValue *rc ) {
++ if (ttisint(rb) && ttisint(rc)) return TK_INT;
++ if (ttiscomplex(rb) || ttiscomplex(rc)) return TK_NUMBER2;
++ if (ttisnumber(rb) && ttisnumber(rc)) return TK_NUMBER;
++ return 0;
++}
++#else
++# define arith_mode(rb,rc) \
++ ( (ttisint(rb) && ttisint(rc)) ? TK_INT : \
++ (ttisnumber(rb) && ttisnumber(rc)) ? TK_NUMBER : 0 )
++#endif
++
++/* arith_op macro for two operators:
++ * automatically chooses, which function (number, integer, complex) to use
++ */
++#define ARITH_OP2_START( op_num, op_int ) \
++ int failed= 0; \
++ switch( arith_mode(rb,rc) ) { \
++ case TK_INT: \
++ if (op_int ( &(ra)->value.i, ivalue(rb), ivalue(rc) )) \
++ { ra->tt= LUA_TINT; break; } /* else flow through */ \
++ case TK_NUMBER: \
++ setnvalue(ra, op_num ( nvalue(rb), nvalue(rc) )); break;
++
++#define ARITH_OP2_END \
++ default: \
++ failed= 1; break; \
++ } if (!failed) continue;
++
++#define arith_op_continue_scalar( op_num, op_int ) \
++ ARITH_OP2_START( op_num, op_int ) \
++ ARITH_OP2_END
++
++#ifdef LNUM_COMPLEX
++# define arith_op_continue( op_num, op_int, op_complex ) \
++ ARITH_OP2_START( op_num, op_int ) \
++ case TK_NUMBER2: \
++ setnvalue_complex( ra, op_complex ( nvalue_complex(rb), nvalue_complex(rc) ) ); break; \
++ ARITH_OP2_END
++#else
++# define arith_op_continue(op_num,op_int,_) arith_op_continue_scalar(op_num,op_int)
++#endif
++
++/* arith_op macro for one operator:
++ */
++#define ARITH_OP1_START( op_num, op_int ) \
++ int failed= 0; \
++ switch( arith_mode(rb,rb) ) { \
++ case TK_INT: \
++ if (op_int ( &(ra)->value.i, ivalue(rb) )) \
++ { ra->tt= LUA_TINT; break; } /* else flow through */ \
++ case TK_NUMBER: \
++ setnvalue(ra, op_num (nvalue(rb))); break; \
++
++#define ARITH_OP1_END \
++ default: \
++ failed= 1; break; \
++ } if (!failed) continue;
++
++#ifdef LNUM_COMPLEX
++# define arith_op1_continue( op_num, op_int, op_complex ) \
++ ARITH_OP1_START( op_num, op_int ) \
++ case TK_NUMBER2: \
++ setnvalue_complex( ra, op_complex ( nvalue_complex_fast(rb) )); break; \
++ ARITH_OP1_END
++#else
++# define arith_op1_continue( op_num, op_int, _ ) \
++ ARITH_OP1_START( op_num, op_int ) \
++ ARITH_OP1_END
++#endif
+
+
+ void luaV_execute (lua_State *L, int nexeccalls) {
+@@ -468,38 +661,45 @@
+ continue;
+ }
+ case OP_ADD: {
+- arith_op(luai_numadd, TM_ADD);
++ TValue *rb = RKB(i), *rc= RKC(i);
++ arith_op_continue( luai_numadd, try_addint, luai_vectadd );
++ Protect(Arith(L, ra, rb, rc, TM_ADD)); \
+ continue;
+ }
+ case OP_SUB: {
+- arith_op(luai_numsub, TM_SUB);
++ TValue *rb = RKB(i), *rc= RKC(i);
++ arith_op_continue( luai_numsub, try_subint, luai_vectsub );
++ Protect(Arith(L, ra, rb, rc, TM_SUB));
+ continue;
+ }
+ case OP_MUL: {
+- arith_op(luai_nummul, TM_MUL);
++ TValue *rb = RKB(i), *rc= RKC(i);
++ arith_op_continue(luai_nummul, try_mulint, luai_vectmul);
++ Protect(Arith(L, ra, rb, rc, TM_MUL));
+ continue;
+ }
+ case OP_DIV: {
+- arith_op(luai_numdiv, TM_DIV);
++ TValue *rb = RKB(i), *rc= RKC(i);
++ arith_op_continue(luai_numdiv, try_divint, luai_vectdiv);
++ Protect(Arith(L, ra, rb, rc, TM_DIV));
+ continue;
+ }
+ case OP_MOD: {
+- arith_op(luai_nummod, TM_MOD);
++ TValue *rb = RKB(i), *rc= RKC(i);
++ arith_op_continue_scalar(luai_nummod, try_modint); /* scalars only */
++ Protect(Arith(L, ra, rb, rc, TM_MOD));
+ continue;
+ }
+ case OP_POW: {
+- arith_op(luai_numpow, TM_POW);
++ TValue *rb = RKB(i), *rc= RKC(i);
++ arith_op_continue(luai_numpow, try_powint, luai_vectpow);
++ Protect(Arith(L, ra, rb, rc, TM_POW));
+ continue;
+ }
+ case OP_UNM: {
+ TValue *rb = RB(i);
+- if (ttisnumber(rb)) {
+- lua_Number nb = nvalue(rb);
+- setnvalue(ra, luai_numunm(nb));
+- }
+- else {
+- Protect(Arith(L, ra, rb, rb, TM_UNM));
+- }
++ arith_op1_continue(luai_numunm, try_unmint, luai_vectunm);
++ Protect(Arith(L, ra, rb, rb, TM_UNM));
+ continue;
+ }
+ case OP_NOT: {
+@@ -511,11 +711,11 @@
+ const TValue *rb = RB(i);
+ switch (ttype(rb)) {
+ case LUA_TTABLE: {
+- setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
++ setivalue(ra, luaH_getn(hvalue(rb)));
+ break;
+ }
+ case LUA_TSTRING: {
+- setnvalue(ra, cast_num(tsvalue(rb)->len));
++ setivalue(ra, tsvalue(rb)->len);
+ break;
+ }
+ default: { /* try metamethod */
+@@ -648,14 +848,30 @@
+ }
+ }
+ case OP_FORLOOP: {
+- lua_Number step = nvalue(ra+2);
+- lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */
+- lua_Number limit = nvalue(ra+1);
+- if (luai_numlt(0, step) ? luai_numle(idx, limit)
+- : luai_numle(limit, idx)) {
+- dojump(L, pc, GETARG_sBx(i)); /* jump back */
+- setnvalue(ra, idx); /* update internal index... */
+- setnvalue(ra+3, idx); /* ...and external index */
++ /* If start,step and limit are all integers, we don't need to check
++ * against overflow in the looping.
++ */
++ if (ttisint(ra) && ttisint(ra+1) && ttisint(ra+2)) {
++ lua_Integer step = ivalue(ra+2);
++ lua_Integer idx = ivalue(ra) + step; /* increment index */
++ lua_Integer limit = ivalue(ra+1);
++ if (step > 0 ? (idx <= limit) : (limit <= idx)) {
++ dojump(L, pc, GETARG_sBx(i)); /* jump back */
++ setivalue(ra, idx); /* update internal index... */
++ setivalue(ra+3, idx); /* ...and external index */
++ }
++ } else {
++ /* non-integer looping (don't use 'nvalue_fast', some may be integer!)
++ */
++ lua_Number step = nvalue(ra+2);
++ lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */
++ lua_Number limit = nvalue(ra+1);
++ if (luai_numlt(0, step) ? luai_numle(idx, limit)
++ : luai_numle(limit, idx)) {
++ dojump(L, pc, GETARG_sBx(i)); /* jump back */
++ setnvalue(ra, idx); /* update internal index... */
++ setnvalue(ra+3, idx); /* ...and external index */
++ }
+ }
+ continue;
+ }
+@@ -664,13 +880,21 @@
+ const TValue *plimit = ra+1;
+ const TValue *pstep = ra+2;
+ L->savedpc = pc; /* next steps may throw errors */
++ /* Using same location for tonumber's both arguments, effectively does
++ * in-place modification (string->number). */
+ if (!tonumber(init, ra))
+ luaG_runerror(L, LUA_QL("for") " initial value must be a number");
+ else if (!tonumber(plimit, ra+1))
+ luaG_runerror(L, LUA_QL("for") " limit must be a number");
+ else if (!tonumber(pstep, ra+2))
+ luaG_runerror(L, LUA_QL("for") " step must be a number");
+- setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));
++ /* Step back one value (keep within integers if we can)
++ */
++ if (!( ttisint(ra) && ttisint(pstep) &&
++ try_subint( &ra->value.i, ivalue(ra), ivalue(pstep) ) )) {
++ /* don't use 'nvalue_fast()', values may be integer */
++ setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));
++ }
+ dojump(L, pc, GETARG_sBx(i));
+ continue;
+ }
+@@ -707,7 +931,7 @@
+ luaH_resizearray(L, h, last); /* pre-alloc it at once */
+ for (; n > 0; n--) {
+ TValue *val = ra+n;
+- setobj2t(L, luaH_setnum(L, h, last--), val);
++ setobj2t(L, luaH_setint(L, h, last--), val);
+ luaC_barriert(L, h, val);
+ }
+ continue;
+Index: lua-5.1.4/src/lvm.h
+===================================================================
+--- lua-5.1.4.orig/src/lvm.h 2008-08-24 16:46:38.000000000 +0200
++++ lua-5.1.4/src/lvm.h 2008-08-24 16:48:20.000000000 +0200
+@@ -15,11 +15,9 @@
+
+ #define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o)))
+
+-#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \
+- (((o) = luaV_tonumber(o,n)) != NULL))
++#define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL))
+
+-#define equalobj(L,o1,o2) \
+- (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
++#define equalobj(L,o1,o2) (ttype_ext_same(o1,o2) && luaV_equalval(L, o1, o2))
+
+
+ LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
+Index: lua-5.1.4/src/print.c
+===================================================================
+--- lua-5.1.4.orig/src/print.c 2008-08-24 16:46:38.000000000 +0200
++++ lua-5.1.4/src/print.c 2008-08-24 16:48:20.000000000 +0200
+@@ -14,6 +14,7 @@
+ #include "lobject.h"
+ #include "lopcodes.h"
+ #include "lundump.h"
++#include "lnum.h"
+
+ #define PrintFunction luaU_print
+
+@@ -59,8 +60,16 @@
+ case LUA_TBOOLEAN:
+ printf(bvalue(o) ? "true" : "false");
+ break;
++ case LUA_TINT:
++ printf(LUA_INTEGER_FMT,ivalue(o));
++ break;
+ case LUA_TNUMBER:
+- printf(LUA_NUMBER_FMT,nvalue(o));
++#ifdef LNUM_COMPLEX
++ // TBD: Do we get complex values here?
++ { lua_Number b= nvalue_img_fast(o);
++ printf( LUA_NUMBER_FMT "%s" LUA_NUMBER_FMT "i", nvalue_fast(o), b>=0 ? "+":"", b ); }
++#endif
++ printf(LUA_NUMBER_FMT,nvalue_fast(o));
+ break;
+ case LUA_TSTRING:
+ PrintString(rawtsvalue(o));
diff --git a/package/lua/patches-host/011-lnum-use-double.patch b/package/lua/patches-host/011-lnum-use-double.patch
new file mode 100644
index 000000000..14c720bf1
--- /dev/null
+++ b/package/lua/patches-host/011-lnum-use-double.patch
@@ -0,0 +1,11 @@
+--- a/src/lnum_config.h
++++ b/src/lnum_config.h
+@@ -11,7 +11,7 @@
+ ** Default number modes
+ */
+ #if (!defined LNUM_DOUBLE) && (!defined LNUM_FLOAT) && (!defined LNUM_LDOUBLE)
+-# define LNUM_FLOAT
++# define LNUM_DOUBLE
+ #endif
+ #if (!defined LNUM_INT16) && (!defined LNUM_INT32) && (!defined LNUM_INT64)
+ # define LNUM_INT32
diff --git a/package/lua/patches-host/015-lnum-ppc-compat.patch b/package/lua/patches-host/015-lnum-ppc-compat.patch
new file mode 100644
index 000000000..d6c48a775
--- /dev/null
+++ b/package/lua/patches-host/015-lnum-ppc-compat.patch
@@ -0,0 +1,13 @@
+Index: lua-5.1.3/src/lua.h
+===================================================================
+--- lua-5.1.3.orig/src/lua.h 2008-06-29 11:45:55.000000000 +0200
++++ lua-5.1.3/src/lua.h 2008-06-29 11:46:28.000000000 +0200
+@@ -79,7 +79,7 @@
+ * not acceptable for 5.1, maybe 5.2 onwards?
+ * 9: greater than existing (5.1) type values.
+ */
+-#define LUA_TINT (-2)
++#define LUA_TINT 9
+
+ #define LUA_TNIL 0
+ #define LUA_TBOOLEAN 1
diff --git a/package/lua/patches-host/030-archindependent-bytecode.patch b/package/lua/patches-host/030-archindependent-bytecode.patch
new file mode 100644
index 000000000..b27592fbd
--- /dev/null
+++ b/package/lua/patches-host/030-archindependent-bytecode.patch
@@ -0,0 +1,115 @@
+Index: lua-5.1.4/src/ldump.c
+===================================================================
+--- lua-5.1.4.orig/src/ldump.c 2008-08-24 16:48:20.000000000 +0200
++++ lua-5.1.4/src/ldump.c 2008-08-24 16:48:52.000000000 +0200
+@@ -67,12 +67,12 @@
+ {
+ if (s==NULL || getstr(s)==NULL)
+ {
+- size_t size=0;
++ unsigned int size=0;
+ DumpVar(size,D);
+ }
+ else
+ {
+- size_t size=s->tsv.len+1; /* include trailing '\0' */
++ unsigned int size=s->tsv.len+1; /* include trailing '\0' */
+ DumpVar(size,D);
+ DumpBlock(getstr(s),size,D);
+ }
+Index: lua-5.1.4/src/lundump.c
+===================================================================
+--- lua-5.1.4.orig/src/lundump.c 2008-08-24 16:48:20.000000000 +0200
++++ lua-5.1.4/src/lundump.c 2008-08-24 16:48:52.000000000 +0200
+@@ -25,6 +25,7 @@
+ ZIO* Z;
+ Mbuffer* b;
+ const char* name;
++ int swap;
+ } LoadState;
+
+ #ifdef LUAC_TRUST_BINARIES
+@@ -40,7 +41,6 @@
+ }
+ #endif
+
+-#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size))
+ #define LoadByte(S) (lu_byte)LoadChar(S)
+ #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
+ #define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
+@@ -51,6 +51,49 @@
+ IF (r!=0, "unexpected end");
+ }
+
++static void LoadMem (LoadState* S, void* b, int n, size_t size)
++{
++ LoadBlock(S,b,n*size);
++ if (S->swap)
++ {
++ char* p=(char*) b;
++ char c;
++ switch (size)
++ {
++ case 1:
++ break;
++ case 2:
++ while (n--)
++ {
++ c=p[0]; p[0]=p[1]; p[1]=c;
++ p+=2;
++ }
++ break;
++ case 4:
++ while (n--)
++ {
++ c=p[0]; p[0]=p[3]; p[3]=c;
++ c=p[1]; p[1]=p[2]; p[2]=c;
++ p+=4;
++ }
++ break;
++ case 8:
++ while (n--)
++ {
++ c=p[0]; p[0]=p[7]; p[7]=c;
++ c=p[1]; p[1]=p[6]; p[6]=c;
++ c=p[2]; p[2]=p[5]; p[5]=c;
++ c=p[3]; p[3]=p[4]; p[4]=c;
++ p+=8;
++ }
++ break;
++ default:
++ IF(1, "bad size");
++ break;
++ }
++ }
++}
++
+ static int LoadChar(LoadState* S)
+ {
+ char x;
+@@ -82,7 +125,7 @@
+
+ static TString* LoadString(LoadState* S)
+ {
+- size_t size;
++ unsigned int size;
+ LoadVar(S,size);
+ if (size==0)
+ return NULL;
+@@ -196,6 +239,7 @@
+ char s[LUAC_HEADERSIZE];
+ luaU_header(h);
+ LoadBlock(S,s,LUAC_HEADERSIZE);
++ S->swap=(s[6]!=h[6]); s[6]=h[6];
+ IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
+ }
+
+@@ -230,7 +274,7 @@
+ *h++=(char)LUAC_FORMAT;
+ *h++=(char)*(char*)&x; /* endianness */
+ *h++=(char)sizeof(int);
+- *h++=(char)sizeof(size_t);
++ *h++=(char)sizeof(unsigned int);
+ *h++=(char)sizeof(Instruction);
+ *h++=(char)sizeof(lua_Number);
+
diff --git a/package/lua/patches-host/100-no_readline.patch b/package/lua/patches-host/100-no_readline.patch
new file mode 100644
index 000000000..209c302bb
--- /dev/null
+++ b/package/lua/patches-host/100-no_readline.patch
@@ -0,0 +1,49 @@
+--- a/src/luaconf.h
++++ b/src/luaconf.h
+@@ -38,7 +38,6 @@
+ #if defined(LUA_USE_LINUX)
+ #define LUA_USE_POSIX
+ #define LUA_USE_DLOPEN /* needs an extra library: -ldl */
+-#define LUA_USE_READLINE /* needs some extra libraries */
+ #endif
+
+ #if defined(LUA_USE_MACOSX)
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -17,6 +17,7 @@
+ MYCFLAGS=
+ MYLDFLAGS=
+ MYLIBS=
++# USE_READLINE=1
+
+ # == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
+
+@@ -75,7 +76,7 @@
+ @echo "MYLIBS = $(MYLIBS)"
+
+ # convenience targets for popular platforms
+-
++RFLAG=$(if $(USE_READLINE),-DLUA_USE_READLINE)
+ none:
+ @echo "Please choose a platform:"
+ @echo " $(PLATS)"
+@@ -90,16 +91,16 @@
+ $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E"
+
+ freebsd:
+- $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX" MYLIBS="-Wl,-E -lreadline"
++ $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX" $(RFLAG)" MYLIBS="-Wl,-E$(if $(USE_READLINE), -lreadline)"
+
+ generic:
+ $(MAKE) all MYCFLAGS=
+
+ linux:
+- $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
++ $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX $(RFLAG)" MYLIBS="-Wl,-E -ldl $(if $(USE_READLINE), -lreadline -lhistory -lncurses)"
+
+ macosx:
+- $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline"
++ $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX $(if $(USE_READLINE), MYLIBS="-lreadline")
+ # use this on Mac OS X 10.3-
+ # $(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX
+
diff --git a/package/lua/patches/010-lua-5.1.3-lnum-full-260308.patch b/package/lua/patches/010-lua-5.1.3-lnum-full-260308.patch
new file mode 100644
index 000000000..619094540
--- /dev/null
+++ b/package/lua/patches/010-lua-5.1.3-lnum-full-260308.patch
@@ -0,0 +1,3736 @@
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -25,7 +25,7 @@ PLATS= aix ansi bsd freebsd generic linu
+ LUA_A= liblua.a
+ CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
+ lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \
+- lundump.o lvm.o lzio.o
++ lundump.o lvm.o lzio.o lnum.o
+ LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \
+ lstrlib.o loadlib.o linit.o
+
+@@ -148,6 +148,7 @@ llex.o: llex.c lua.h luaconf.h ldo.h lob
+ lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h
+ lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
+ ltm.h lzio.h lmem.h ldo.h
++lnum.o: lnum.c lua.h llex.h lnum.h
+ loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h
+ lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \
+ ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h
+@@ -179,4 +180,18 @@ lzio.o: lzio.c lua.h luaconf.h llimits.h
+ print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \
+ ltm.h lzio.h lmem.h lopcodes.h lundump.h
+
++luaconf.h: lnum_config.h
++lapi.c: lnum.h
++lauxlib.c: llimits.h
++lbaselib.c: llimits.h lobject.h lapi.h
++lcode.c: lnum.h
++liolib.c: lnum.h llex.h
++llex.c: lnum.h
++lnum.h: lobject.h
++lobject.c: llex.h lnum.h
++ltable.c: lnum.h
++lua.c: llimits.h
++lvm.c: llex.h lnum.h
++print.c: lnum.h
++
+ # (end of Makefile)
+--- a/src/lapi.c
++++ b/src/lapi.c
+@@ -28,7 +28,7 @@
+ #include "ltm.h"
+ #include "lundump.h"
+ #include "lvm.h"
+-
++#include "lnum.h"
+
+
+ const char lua_ident[] =
+@@ -241,12 +241,13 @@ LUA_API void lua_pushvalue (lua_State *L
+
+ LUA_API int lua_type (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+- return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);
++ return (o == luaO_nilobject) ? LUA_TNONE : ttype_ext(o);
+ }
+
+
+ LUA_API const char *lua_typename (lua_State *L, int t) {
+ UNUSED(L);
++ lua_assert( t!= LUA_TINT );
+ return (t == LUA_TNONE) ? "no value" : luaT_typenames[t];
+ }
+
+@@ -264,6 +265,14 @@ LUA_API int lua_isnumber (lua_State *L,
+ }
+
+
++LUA_API int lua_isinteger (lua_State *L, int idx) {
++ TValue tmp;
++ lua_Integer dum;
++ const TValue *o = index2adr(L, idx);
++ return tonumber(o,&tmp) && (ttisint(o) || tt_integer_valued(o,&dum));
++}
++
++
+ LUA_API int lua_isstring (lua_State *L, int idx) {
+ int t = lua_type(L, idx);
+ return (t == LUA_TSTRING || t == LUA_TNUMBER);
+@@ -309,31 +318,66 @@ LUA_API int lua_lessthan (lua_State *L,
+ }
+
+
+-
+ LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
+ TValue n;
+ const TValue *o = index2adr(L, idx);
+- if (tonumber(o, &n))
++ if (tonumber(o, &n)) {
++#ifdef LNUM_COMPLEX
++ if (nvalue_img(o) != 0)
++ luaG_runerror(L, "expecting a real number");
++#endif
+ return nvalue(o);
+- else
+- return 0;
++ }
++ return 0;
+ }
+
+
+ LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) {
+ TValue n;
++ /* Lua 5.1 documented behaviour is to return nonzero for non-integer:
++ * "If the number is not an integer, it is truncated in some non-specified way."
++ * I would suggest to change this, to return 0 for anything that would
++ * not fit in 'lua_Integer'.
++ */
++#ifdef LUA_COMPAT_TOINTEGER
++ /* Lua 5.1 compatible */
+ const TValue *o = index2adr(L, idx);
+ if (tonumber(o, &n)) {
+- lua_Integer res;
+- lua_Number num = nvalue(o);
+- lua_number2integer(res, num);
+- return res;
++ lua_Integer i;
++ lua_Number d;
++ if (ttisint(o)) return ivalue(o);
++ d= nvalue_fast(o);
++# ifdef LNUM_COMPLEX
++ if (nvalue_img_fast(o) != 0)
++ luaG_runerror(L, "expecting a real number");
++# endif
++ lua_number2integer(i, d);
++ return i;
+ }
+- else
+- return 0;
++#else
++ /* New suggestion */
++ const TValue *o = index2adr(L, idx);
++ if (tonumber(o, &n)) {
++ lua_Integer i;
++ if (ttisint(o)) return ivalue(o);
++ if (tt_integer_valued(o,&i)) return i;
++ }
++#endif
++ return 0;
+ }
+
+
++#ifdef LNUM_COMPLEX
++LUA_API lua_Complex lua_tocomplex (lua_State *L, int idx) {
++ TValue tmp;
++ const TValue *o = index2adr(L, idx);
++ if (tonumber(o, &tmp))
++ return nvalue_complex(o);
++ return 0;
++}
++#endif
++
++
+ LUA_API int lua_toboolean (lua_State *L, int idx) {
+ const TValue *o = index2adr(L, idx);
+ return !l_isfalse(o);
+@@ -364,6 +408,7 @@ LUA_API size_t lua_objlen (lua_State *L,
+ case LUA_TSTRING: return tsvalue(o)->len;
+ case LUA_TUSERDATA: return uvalue(o)->len;
+ case LUA_TTABLE: return luaH_getn(hvalue(o));
++ case LUA_TINT:
+ case LUA_TNUMBER: {
+ size_t l;
+ lua_lock(L); /* `luaV_tostring' may create a new string */
+@@ -426,6 +471,8 @@ LUA_API void lua_pushnil (lua_State *L)
+ }
+
+
++/* 'lua_pushnumber()' may lose accuracy on integers, 'lua_pushinteger' will not.
++ */
+ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
+ lua_lock(L);
+ setnvalue(L->top, n);
+@@ -434,12 +481,22 @@ LUA_API void lua_pushnumber (lua_State *
+ }
+
+
+-LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
++LUA_API void lua_pushinteger (lua_State *L, lua_Integer i) {
++ lua_lock(L);
++ setivalue(L->top, i);
++ api_incr_top(L);
++ lua_unlock(L);
++}
++
++
++#ifdef LNUM_COMPLEX
++LUA_API void lua_pushcomplex (lua_State *L, lua_Complex v) {
+ lua_lock(L);
+- setnvalue(L->top, cast_num(n));
++ setnvalue_complex( L->top, v );
+ api_incr_top(L);
+ lua_unlock(L);
+ }
++#endif
+
+
+ LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
+@@ -569,7 +626,7 @@ LUA_API void lua_rawgeti (lua_State *L,
+ lua_lock(L);
+ o = index2adr(L, idx);
+ api_check(L, ttistable(o));
+- setobj2s(L, L->top, luaH_getnum(hvalue(o), n));
++ setobj2s(L, L->top, luaH_getint(hvalue(o), n));
+ api_incr_top(L);
+ lua_unlock(L);
+ }
+@@ -597,6 +654,9 @@ LUA_API int lua_getmetatable (lua_State
+ case LUA_TUSERDATA:
+ mt = uvalue(obj)->metatable;
+ break;
++ case LUA_TINT:
++ mt = G(L)->mt[LUA_TNUMBER];
++ break;
+ default:
+ mt = G(L)->mt[ttype(obj)];
+ break;
+@@ -687,7 +747,7 @@ LUA_API void lua_rawseti (lua_State *L,
+ api_checknelems(L, 1);
+ o = index2adr(L, idx);
+ api_check(L, ttistable(o));
+- setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);
++ setobj2t(L, luaH_setint(L, hvalue(o), n), L->top-1);
+ luaC_barriert(L, hvalue(o), L->top-1);
+ L->top--;
+ lua_unlock(L);
+@@ -721,7 +781,7 @@ LUA_API int lua_setmetatable (lua_State
+ break;
+ }
+ default: {
+- G(L)->mt[ttype(obj)] = mt;
++ G(L)->mt[ttype_ext(obj)] = mt;
+ break;
+ }
+ }
+@@ -1085,3 +1145,32 @@ LUA_API const char *lua_setupvalue (lua_
+ return name;
+ }
+
++
++/* Help function for 'luaB_tonumber()', avoids multiple str->number
++ * conversions for Lua "tonumber()".
++ *
++ * Also pushes floating point numbers with integer value as integer, which
++ * can be used by 'tonumber()' in scripts to bring values back to integer
++ * realm.
++ *
++ * Note: The 'back to integer realm' is _not_ to affect string conversions:
++ * 'tonumber("4294967295.1")' should give a floating point value, although
++ * the value would be 4294967296 (and storable in int64 realm).
++ */
++int lua_pushvalue_as_number (lua_State *L, int idx)
++{
++ const TValue *o = index2adr(L, idx);
++ TValue tmp;
++ lua_Integer i;
++ if (ttisnumber(o)) {
++ if ( (!ttisint(o)) && tt_integer_valued(o,&i)) {
++ lua_pushinteger( L, i );
++ return 1;
++ }
++ } else if (!tonumber(o, &tmp)) {
++ return 0;
++ }
++ if (ttisint(o)) lua_pushinteger( L, ivalue(o) );
++ else lua_pushnumber( L, nvalue_fast(o) );
++ return 1;
++}
+--- a/src/lapi.h
++++ b/src/lapi.h
+@@ -13,4 +13,6 @@
+
+ LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o);
+
++int lua_pushvalue_as_number (lua_State *L, int idx);
++
+ #endif
+--- a/src/lauxlib.c
++++ b/src/lauxlib.c
+@@ -23,7 +23,7 @@
+ #include "lua.h"
+
+ #include "lauxlib.h"
+-
++#include "llimits.h"
+
+ #define FREELIST_REF 0 /* free list of references */
+
+@@ -66,7 +66,7 @@ LUALIB_API int luaL_typerror (lua_State
+
+
+ static void tag_error (lua_State *L, int narg, int tag) {
+- luaL_typerror(L, narg, lua_typename(L, tag));
++ luaL_typerror(L, narg, tag==LUA_TINT ? "integer" : lua_typename(L, tag));
+ }
+
+
+@@ -188,8 +188,8 @@ LUALIB_API lua_Number luaL_optnumber (lu
+
+ LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
+ lua_Integer d = lua_tointeger(L, narg);
+- if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
+- tag_error(L, narg, LUA_TNUMBER);
++ if (d == 0 && !lua_isinteger(L, narg)) /* avoid extra test when d is not 0 */
++ tag_error(L, narg, LUA_TINT);
+ return d;
+ }
+
+@@ -200,6 +200,16 @@ LUALIB_API lua_Integer luaL_optinteger (
+ }
+
+
++#ifdef LNUM_COMPLEX
++LUALIB_API lua_Complex luaL_checkcomplex (lua_State *L, int narg) {
++ lua_Complex c = lua_tocomplex(L, narg);
++ if (c == 0 && !lua_isnumber(L, narg)) /* avoid extra test when c is not 0 */
++ tag_error(L, narg, LUA_TNUMBER);
++ return c;
++}
++#endif
++
++
+ LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
+ if (!lua_getmetatable(L, obj)) /* no metatable? */
+ return 0;
+--- a/src/lauxlib.h
++++ b/src/lauxlib.h
+@@ -57,6 +57,12 @@ LUALIB_API lua_Number (luaL_optnumber) (
+ LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
+ LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
+ lua_Integer def);
++#define luaL_checkint32(L,narg) ((int)luaL_checkinteger(L,narg))
++#define luaL_optint32(L,narg,def) ((int)luaL_optinteger(L,narg,def))
++
++#ifdef LNUM_COMPLEX
++ LUALIB_API lua_Complex (luaL_checkcomplex) (lua_State *L, int narg);
++#endif
+
+ LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
+ LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
+--- a/src/lbaselib.c
++++ b/src/lbaselib.c
+@@ -18,7 +18,9 @@
+
+ #include "lauxlib.h"
+ #include "lualib.h"
+-
++#include "llimits.h"
++#include "lobject.h"
++#include "lapi.h"
+
+
+
+@@ -54,20 +56,25 @@ static int luaB_tonumber (lua_State *L)
+ int base = luaL_optint(L, 2, 10);
+ if (base == 10) { /* standard conversion */
+ luaL_checkany(L, 1);
+- if (lua_isnumber(L, 1)) {
+- lua_pushnumber(L, lua_tonumber(L, 1));
++ if (lua_isnumber(L, 1)) { /* numeric string, or a number */
++ lua_pushvalue_as_number(L,1); /* API extension (not to lose accuracy here) */
+ return 1;
+- }
++ }
+ }
+ else {
+ const char *s1 = luaL_checkstring(L, 1);
+ char *s2;
+- unsigned long n;
++ unsigned LUA_INTEGER n;
+ luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
+- n = strtoul(s1, &s2, base);
++ n = lua_str2ul(s1, &s2, base);
+ if (s1 != s2) { /* at least one valid digit? */
+ while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */
+ if (*s2 == '\0') { /* no invalid trailing characters? */
++
++ /* Push as number, there needs to be separate 'luaB_tointeger' for
++ * when the caller wants to preserve the bits (matters if unsigned
++ * values are used).
++ */
+ lua_pushnumber(L, (lua_Number)n);
+ return 1;
+ }
+@@ -144,7 +151,7 @@ static int luaB_setfenv (lua_State *L) {
+ luaL_checktype(L, 2, LUA_TTABLE);
+ getfunc(L, 0);
+ lua_pushvalue(L, 2);
+- if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
++ if (lua_isnumber(L, 1) && lua_tointeger(L, 1) == 0) {
+ /* change environment of current thread */
+ lua_pushthread(L);
+ lua_insert(L, -2);
+@@ -209,7 +216,7 @@ static int luaB_collectgarbage (lua_Stat
+ return 1;
+ }
+ default: {
+- lua_pushnumber(L, res);
++ lua_pushinteger(L, res);
+ return 1;
+ }
+ }
+@@ -631,6 +638,8 @@ static void base_open (lua_State *L) {
+ luaL_register(L, "_G", base_funcs);
+ lua_pushliteral(L, LUA_VERSION);
+ lua_setglobal(L, "_VERSION"); /* set global _VERSION */
++ lua_pushliteral(L, LUA_LNUM);
++ lua_setglobal(L, "_LNUM"); /* "[complex] double|float|ldouble int32|int64" */
+ /* `ipairs' and `pairs' need auxliliary functions as upvalues */
+ auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
+ auxopen(L, "pairs", luaB_pairs, luaB_next);
+--- a/src/lcode.c
++++ b/src/lcode.c
+@@ -22,13 +22,18 @@
+ #include "lopcodes.h"
+ #include "lparser.h"
+ #include "ltable.h"
++#include "lnum.h"
+
+
+ #define hasjumps(e) ((e)->t != (e)->f)
+
+-
+ static int isnumeral(expdesc *e) {
+- return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
++ int ek=
++#ifdef LNUM_COMPLEX
++ (e->k == VKNUM2) ||
++#endif
++ (e->k == VKINT) || (e->k == VKNUM);
++ return (ek && e->t == NO_JUMP && e->f == NO_JUMP);
+ }
+
+
+@@ -231,12 +236,16 @@ static int addk (FuncState *fs, TValue *
+ TValue *idx = luaH_set(L, fs->h, k);
+ Proto *f = fs->f;
+ int oldsize = f->sizek;
+- if (ttisnumber(idx)) {
+- lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));
+- return cast_int(nvalue(idx));
++ if (ttype(idx)==LUA_TNUMBER) {
++ luai_normalize(idx);
++ lua_assert( ttype(idx)==LUA_TINT ); /* had no fraction */
++ }
++ if (ttisint(idx)) {
++ lua_assert(luaO_rawequalObj(&fs->f->k[ivalue(idx)], v));
++ return cast_int(ivalue(idx));
+ }
+ else { /* constant not found; create a new entry */
+- setnvalue(idx, cast_num(fs->nk));
++ setivalue(idx, fs->nk);
+ luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
+ MAXARG_Bx, "constant table overflow");
+ while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
+@@ -261,6 +270,21 @@ int luaK_numberK (FuncState *fs, lua_Num
+ }
+
+
++int luaK_integerK (FuncState *fs, lua_Integer r) {
++ TValue o;
++ setivalue(&o, r);
++ return addk(fs, &o, &o);
++}
++
++
++#ifdef LNUM_COMPLEX
++static int luaK_imagK (FuncState *fs, lua_Number r) {
++ TValue o;
++ setnvalue_complex(&o, r*I);
++ return addk(fs, &o, &o);
++}
++#endif
++
+ static int boolK (FuncState *fs, int b) {
+ TValue o;
+ setbvalue(&o, b);
+@@ -359,6 +383,16 @@ static void discharge2reg (FuncState *fs
+ luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));
+ break;
+ }
++ case VKINT: {
++ luaK_codeABx(fs, OP_LOADK, reg, luaK_integerK(fs, e->u.ival));
++ break;
++ }
++#ifdef LNUM_COMPLEX
++ case VKNUM2: {
++ luaK_codeABx(fs, OP_LOADK, reg, luaK_imagK(fs, e->u.nval));
++ break;
++ }
++#endif
+ case VRELOCABLE: {
+ Instruction *pc = &getcode(fs, e);
+ SETARG_A(*pc, reg);
+@@ -444,6 +478,10 @@ void luaK_exp2val (FuncState *fs, expdes
+ int luaK_exp2RK (FuncState *fs, expdesc *e) {
+ luaK_exp2val(fs, e);
+ switch (e->k) {
++#ifdef LNUM_COMPLEX
++ case VKNUM2:
++#endif
++ case VKINT:
+ case VKNUM:
+ case VTRUE:
+ case VFALSE:
+@@ -451,6 +489,10 @@ int luaK_exp2RK (FuncState *fs, expdesc
+ if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */
+ e->u.s.info = (e->k == VNIL) ? nilK(fs) :
+ (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :
++ (e->k == VKINT) ? luaK_integerK(fs, e->u.ival) :
++#ifdef LNUM_COMPLEX
++ (e->k == VKNUM2) ? luaK_imagK(fs, e->u.nval) :
++#endif
+ boolK(fs, (e->k == VTRUE));
+ e->k = VK;
+ return RKASK(e->u.s.info);
+@@ -540,7 +582,10 @@ void luaK_goiftrue (FuncState *fs, expde
+ int pc; /* pc of last jump */
+ luaK_dischargevars(fs, e);
+ switch (e->k) {
+- case VK: case VKNUM: case VTRUE: {
++#ifdef LNUM_COMPLEX
++ case VKNUM2:
++#endif
++ case VKINT: case VK: case VKNUM: case VTRUE: {
+ pc = NO_JUMP; /* always true; do nothing */
+ break;
+ }
+@@ -598,7 +643,10 @@ static void codenot (FuncState *fs, expd
+ e->k = VTRUE;
+ break;
+ }
+- case VK: case VKNUM: case VTRUE: {
++#ifdef LNUM_COMPLEX
++ case VKNUM2:
++#endif
++ case VKINT: case VK: case VKNUM: case VTRUE: {
+ e->k = VFALSE;
+ break;
+ }
+@@ -634,25 +682,70 @@ void luaK_indexed (FuncState *fs, expdes
+
+ static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
+ lua_Number v1, v2, r;
++ int vkres= VKNUM;
+ if (!isnumeral(e1) || !isnumeral(e2)) return 0;
+- v1 = e1->u.nval;
+- v2 = e2->u.nval;
++
++ /* real and imaginary parts don't mix. */
++#ifdef LNUM_COMPLEX
++ if (e1->k == VKNUM2) {
++ if ((op != OP_UNM) && (e2->k != VKNUM2)) return 0;
++ vkres= VKNUM2; }
++ else if (e2->k == VKNUM2) { return 0; }
++#endif
++ if ((e1->k == VKINT) && (e2->k == VKINT)) {
++ lua_Integer i1= e1->u.ival, i2= e2->u.ival;
++ lua_Integer rr;
++ int done= 0;
++ /* Integer/integer calculations (may end up producing floating point) */
++ switch (op) {
++ case OP_ADD: done= try_addint( &rr, i1, i2 ); break;
++ case OP_SUB: done= try_subint( &rr, i1, i2 ); break;
++ case OP_MUL: done= try_mulint( &rr, i1, i2 ); break;
++ case OP_DIV: done= try_divint( &rr, i1, i2 ); break;
++ case OP_MOD: done= try_modint( &rr, i1, i2 ); break;
++ case OP_POW: done= try_powint( &rr, i1, i2 ); break;
++ case OP_UNM: done= try_unmint( &rr, i1 ); break;
++ default: done= 0; break;
++ }
++ if (done) {
++ e1->u.ival = rr; /* remained within integer range */
++ return 1;
++ }
++ }
++ v1 = (e1->k == VKINT) ? ((lua_Number)e1->u.ival) : e1->u.nval;
++ v2 = (e2->k == VKINT) ? ((lua_Number)e2->u.ival) : e2->u.nval;
++
+ switch (op) {
+ case OP_ADD: r = luai_numadd(v1, v2); break;
+ case OP_SUB: r = luai_numsub(v1, v2); break;
+- case OP_MUL: r = luai_nummul(v1, v2); break;
++ case OP_MUL:
++#ifdef LNUM_COMPLEX
++ if (vkres==VKNUM2) return 0; /* leave to runtime (could do here, but not worth it?) */
++#endif
++ r = luai_nummul(v1, v2); break;
+ case OP_DIV:
+ if (v2 == 0) return 0; /* do not attempt to divide by 0 */
+- r = luai_numdiv(v1, v2); break;
++#ifdef LNUM_COMPLEX
++ if (vkres==VKNUM2) return 0; /* leave to runtime */
++#endif
++ r = luai_numdiv(v1, v2); break;
+ case OP_MOD:
+ if (v2 == 0) return 0; /* do not attempt to divide by 0 */
++#ifdef LNUM_COMPLEX
++ if (vkres==VKNUM2) return 0; /* leave to runtime */
++#endif
+ r = luai_nummod(v1, v2); break;
+- case OP_POW: r = luai_numpow(v1, v2); break;
++ case OP_POW:
++#ifdef LNUM_COMPLEX
++ if (vkres==VKNUM2) return 0; /* leave to runtime */
++#endif
++ r = luai_numpow(v1, v2); break;
+ case OP_UNM: r = luai_numunm(v1); break;
+ case OP_LEN: return 0; /* no constant folding for 'len' */
+ default: lua_assert(0); r = 0; break;
+ }
+ if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */
++ e1->k = cast(expkind,vkres);
+ e1->u.nval = r;
+ return 1;
+ }
+@@ -696,7 +789,8 @@ static void codecomp (FuncState *fs, OpC
+
+ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
+ expdesc e2;
+- e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
++ e2.t = e2.f = NO_JUMP; e2.k = VKINT; e2.u.ival = 0;
++
+ switch (op) {
+ case OPR_MINUS: {
+ if (!isnumeral(e))
+--- a/src/lcode.h
++++ b/src/lcode.h
+@@ -71,6 +71,6 @@ LUAI_FUNC void luaK_prefix (FuncState *f
+ LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
+ LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2);
+ LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
+-
++LUAI_FUNC int luaK_integerK (FuncState *fs, lua_Integer r);
+
+ #endif
+--- a/src/ldebug.c
++++ b/src/ldebug.c
+@@ -183,7 +183,7 @@ static void collectvalidlines (lua_State
+ int *lineinfo = f->l.p->lineinfo;
+ int i;
+ for (i=0; i<f->l.p->sizelineinfo; i++)
+- setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
++ setbvalue(luaH_setint(L, t, lineinfo[i]), 1);
+ sethvalue(L, L->top, t);
+ }
+ incr_top(L);
+@@ -566,7 +566,7 @@ static int isinstack (CallInfo *ci, cons
+
+ void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
+ const char *name = NULL;
+- const char *t = luaT_typenames[ttype(o)];
++ const char *t = luaT_typenames[ttype_ext(o)];
+ const char *kind = (isinstack(L->ci, o)) ?
+ getobjname(L, L->ci, cast_int(o - L->base), &name) :
+ NULL;
+@@ -594,8 +594,8 @@ void luaG_aritherror (lua_State *L, cons
+
+
+ int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
+- const char *t1 = luaT_typenames[ttype(p1)];
+- const char *t2 = luaT_typenames[ttype(p2)];
++ const char *t1 = luaT_typenames[ttype_ext(p1)];
++ const char *t2 = luaT_typenames[ttype_ext(p2)];
+ if (t1[2] == t2[2])
+ luaG_runerror(L, "attempt to compare two %s values", t1);
+ else
+--- a/src/ldo.c
++++ b/src/ldo.c
+@@ -219,9 +219,9 @@ static StkId adjust_varargs (lua_State *
+ luaC_checkGC(L);
+ htab = luaH_new(L, nvar, 1); /* create `arg' table */
+ for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */
+- setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
++ setobj2n(L, luaH_setint(L, htab, i+1), L->top - nvar + i);
+ /* store counter in field `n' */
+- setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
++ setivalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), nvar);
+ }
+ #endif
+ /* move fixed parameters to final position */
+--- a/src/ldump.c
++++ b/src/ldump.c
+@@ -52,6 +52,11 @@ static void DumpNumber(lua_Number x, Dum
+ DumpVar(x,D);
+ }
+
++static void DumpInteger(lua_Integer x, DumpState* D)
++{
++ DumpVar(x,D);
++}
++
+ static void DumpVector(const void* b, int n, size_t size, DumpState* D)
+ {
+ DumpInt(n,D);
+@@ -93,8 +98,11 @@ static void DumpConstants(const Proto* f
+ DumpChar(bvalue(o),D);
+ break;
+ case LUA_TNUMBER:
+- DumpNumber(nvalue(o),D);
++ DumpNumber(nvalue_fast(o),D);
+ break;
++ case LUA_TINT:
++ DumpInteger(ivalue(o),D);
++ break;
+ case LUA_TSTRING:
+ DumpString(rawtsvalue(o),D);
+ break;
+--- a/src/liolib.c
++++ b/src/liolib.c
+@@ -9,6 +9,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <ctype.h>
+
+ #define liolib_c
+ #define LUA_LIB
+@@ -18,7 +19,8 @@
+ #include "lauxlib.h"
+ #include "lualib.h"
+
+-
++#include "lnum.h"
++#include "llex.h"
+
+ #define IO_INPUT 1
+ #define IO_OUTPUT 2
+@@ -269,6 +271,13 @@ static int io_lines (lua_State *L) {
+ ** =======================================================
+ */
+
++/*
++* Many problems if we intend the same 'n' format specifier (see 'file:read()')
++* to work for both FP and integer numbers, without losing their accuracy. So
++* we don't. 'n' reads numbers as floating points, 'i' as integers. Old code
++* remains valid, but won't provide full integer accuracy (this only matters
++* with float FP and/or 64-bit integers).
++*/
+
+ static int read_number (lua_State *L, FILE *f) {
+ lua_Number d;
+@@ -279,6 +288,43 @@ static int read_number (lua_State *L, FI
+ else return 0; /* read fails */
+ }
+
++static int read_integer (lua_State *L, FILE *f) {
++ lua_Integer i;
++ if (fscanf(f, LUA_INTEGER_SCAN, &i) == 1) {
++ lua_pushinteger(L, i);
++ return 1;
++ }
++ else return 0; /* read fails */
++}
++
++#ifdef LNUM_COMPLEX
++static int read_complex (lua_State *L, FILE *f) {
++ /* NNN / NNNi / NNN+MMMi / NNN-MMMi */
++ lua_Number a,b;
++ if (fscanf(f, LUA_NUMBER_SCAN, &a) == 1) {
++ int c=fgetc(f);
++ switch(c) {
++ case 'i':
++ lua_pushcomplex(L, a*I);
++ return 1;
++ case '+':
++ case '-':
++ /* "i" is consumed if at the end; just 'NNN+MMM' will most likely
++ * behave as if "i" was there? (TBD: test)
++ */
++ if (fscanf(f, LUA_NUMBER_SCAN "i", &b) == 1) {
++ lua_pushcomplex(L, a+ (c=='+' ? b:-b)*I);
++ return 1;
++ }
++ }
++ ungetc( c,f );
++ lua_pushnumber(L,a); /*real part only*/
++ return 1;
++ }
++ return 0; /* read fails */
++}
++#endif
++
+
+ static int test_eof (lua_State *L, FILE *f) {
+ int c = getc(f);
+@@ -352,6 +398,14 @@ static int g_read (lua_State *L, FILE *f
+ case 'n': /* number */
+ success = read_number(L, f);
+ break;
++ case 'i': /* integer (full accuracy) */
++ success = read_integer(L, f);
++ break;
++#ifdef LNUM_COMPLEX
++ case 'c': /* complex */
++ success = read_complex(L, f);
++ break;
++#endif
+ case 'l': /* line */
+ success = read_line(L, f);
+ break;
+@@ -412,9 +466,10 @@ static int g_write (lua_State *L, FILE *
+ int status = 1;
+ for (; nargs--; arg++) {
+ if (lua_type(L, arg) == LUA_TNUMBER) {
+- /* optimization: could be done exactly as for strings */
+- status = status &&
+- fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
++ if (lua_isinteger(L,arg))
++ status = status && fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg)) > 0;
++ else
++ status = status && fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
+ }
+ else {
+ size_t l;
+@@ -457,7 +512,7 @@ static int f_setvbuf (lua_State *L) {
+ static const char *const modenames[] = {"no", "full", "line", NULL};
+ FILE *f = tofile(L);
+ int op = luaL_checkoption(L, 2, NULL, modenames);
+- lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
++ size_t sz = luaL_optint32(L, 3, LUAL_BUFFERSIZE);
+ int res = setvbuf(f, NULL, mode[op], sz);
+ return pushresult(L, res == 0, NULL);
+ }
+--- a/src/llex.c
++++ b/src/llex.c
+@@ -22,6 +22,7 @@
+ #include "lstring.h"
+ #include "ltable.h"
+ #include "lzio.h"
++#include "lnum.h"
+
+
+
+@@ -34,13 +35,17 @@
+
+
+ /* ORDER RESERVED */
+-const char *const luaX_tokens [] = {
++static const char *const luaX_tokens [] = {
+ "and", "break", "do", "else", "elseif",
+ "end", "false", "for", "function", "if",
+ "in", "local", "nil", "not", "or", "repeat",
+ "return", "then", "true", "until", "while",
+ "..", "...", "==", ">=", "<=", "~=",
+ "<number>", "<name>", "<string>", "<eof>",
++ "<integer>",
++#ifdef LNUM_COMPLEX
++ "<number2>",
++#endif
+ NULL
+ };
+
+@@ -90,7 +95,11 @@ static const char *txtToken (LexState *l
+ switch (token) {
+ case TK_NAME:
+ case TK_STRING:
++ case TK_INT:
+ case TK_NUMBER:
++#ifdef LNUM_COMPLEX
++ case TK_NUMBER2:
++#endif
+ save(ls, '\0');
+ return luaZ_buffer(ls->buff);
+ default:
+@@ -173,23 +182,27 @@ static void buffreplace (LexState *ls, c
+ if (p[n] == from) p[n] = to;
+ }
+
+-
+-static void trydecpoint (LexState *ls, SemInfo *seminfo) {
++/* TK_NUMBER (/ TK_NUMBER2) */
++static int trydecpoint (LexState *ls, SemInfo *seminfo) {
+ /* format error: try to update decimal point separator */
+ struct lconv *cv = localeconv();
+ char old = ls->decpoint;
++ int ret;
+ ls->decpoint = (cv ? cv->decimal_point[0] : '.');
+ buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */
+- if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {
++ ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, NULL);
++ if (!ret) {
+ /* format error with correct decimal point: no more options */
+ buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */
+ luaX_lexerror(ls, "malformed number", TK_NUMBER);
+ }
++ return ret;
+ }
+
+
+-/* LUA_NUMBER */
+-static void read_numeral (LexState *ls, SemInfo *seminfo) {
++/* TK_NUMBER / TK_INT (/TK_NUMBER2) */
++static int read_numeral (LexState *ls, SemInfo *seminfo) {
++ int ret;
+ lua_assert(isdigit(ls->current));
+ do {
+ save_and_next(ls);
+@@ -200,8 +213,9 @@ static void read_numeral (LexState *ls,
+ save_and_next(ls);
+ save(ls, '\0');
+ buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
+- if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */
+- trydecpoint(ls, seminfo); /* try to update decimal point separator */
++ ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, &seminfo->i );
++ if (!ret) return trydecpoint(ls, seminfo); /* try to update decimal point separator */
++ return ret;
+ }
+
+
+@@ -329,6 +343,7 @@ static void read_string (LexState *ls, i
+ }
+
+
++/* char / TK_* */
+ static int llex (LexState *ls, SemInfo *seminfo) {
+ luaZ_resetbuffer(ls->buff);
+ for (;;) {
+@@ -400,8 +415,7 @@ static int llex (LexState *ls, SemInfo *
+ }
+ else if (!isdigit(ls->current)) return '.';
+ else {
+- read_numeral(ls, seminfo);
+- return TK_NUMBER;
++ return read_numeral(ls, seminfo);
+ }
+ }
+ case EOZ: {
+@@ -414,8 +428,7 @@ static int llex (LexState *ls, SemInfo *
+ continue;
+ }
+ else if (isdigit(ls->current)) {
+- read_numeral(ls, seminfo);
+- return TK_NUMBER;
++ return read_numeral(ls, seminfo);
+ }
+ else if (isalpha(ls->current) || ls->current == '_') {
+ /* identifier or reserved word */
+--- a/src/llex.h
++++ b/src/llex.h
+@@ -29,19 +29,22 @@ enum RESERVED {
+ TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
+ /* other terminal symbols */
+ TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,
+- TK_NAME, TK_STRING, TK_EOS
++ TK_NAME, TK_STRING, TK_EOS, TK_INT
++#ifdef LNUM_COMPLEX
++ , TK_NUMBER2 /* imaginary constants: Ni */
++#endif
+ };
+
+ /* number of reserved words */
+ #define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1))
+
+
+-/* array with token `names' */
+-LUAI_DATA const char *const luaX_tokens [];
+-
+-
++/* SemInfo is a local data structure of 'llex.c', used for carrying a string
++ * or a number. A separate token (TK_*) will tell, how to interpret the data.
++ */
+ typedef union {
+ lua_Number r;
++ lua_Integer i;
+ TString *ts;
+ } SemInfo; /* semantics information */
+
+--- a/src/llimits.h
++++ b/src/llimits.h
+@@ -49,6 +49,7 @@ typedef LUAI_USER_ALIGNMENT_T L_Umaxalig
+
+ /* result of a `usual argument conversion' over lua_Number */
+ typedef LUAI_UACNUMBER l_uacNumber;
++typedef LUAI_UACINTEGER l_uacInteger;
+
+
+ /* internal assertions for in-house debugging */
+@@ -80,7 +81,6 @@ typedef LUAI_UACNUMBER l_uacNumber;
+ #define cast_int(i) cast(int, (i))
+
+
+-
+ /*
+ ** type for virtual-machine instructions
+ ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
+--- a/src/lmathlib.c
++++ b/src/lmathlib.c
+@@ -4,7 +4,6 @@
+ ** See Copyright Notice in lua.h
+ */
+
+-
+ #include <stdlib.h>
+ #include <math.h>
+
+@@ -16,113 +15,210 @@
+ #include "lauxlib.h"
+ #include "lualib.h"
+
++/* 'luai_vectpow()' as a replacement for 'cpow()'. Defined in the header; we
++ * don't intrude the code libs internal functions.
++ */
++#ifdef LNUM_COMPLEX
++# include "lnum.h"
++#endif
+
+ #undef PI
+-#define PI (3.14159265358979323846)
+-#define RADIANS_PER_DEGREE (PI/180.0)
+-
++#ifdef LNUM_FLOAT
++# define PI (3.14159265358979323846F)
++#elif defined(M_PI)
++# define PI M_PI
++#else
++# define PI (3.14159265358979323846264338327950288)
++#endif
++#define RADIANS_PER_DEGREE (PI/180)
+
++#undef HUGE
++#ifdef LNUM_FLOAT
++# define HUGE HUGE_VALF
++#elif defined(LNUM_LDOUBLE)
++# define HUGE HUGE_VALL
++#else
++# define HUGE HUGE_VAL
++#endif
+
+ static int math_abs (lua_State *L) {
+- lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushnumber(L, _LF(cabs) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(fabs) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_sin (lua_State *L) {
+- lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(csin) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(sin) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_sinh (lua_State *L) {
+- lua_pushnumber(L, sinh(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(csinh) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(sinh) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_cos (lua_State *L) {
+- lua_pushnumber(L, cos(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(ccos) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(cos) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_cosh (lua_State *L) {
+- lua_pushnumber(L, cosh(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(ccosh) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(cosh) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_tan (lua_State *L) {
+- lua_pushnumber(L, tan(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(ctan) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(tan) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_tanh (lua_State *L) {
+- lua_pushnumber(L, tanh(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(ctanh) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(tanh) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_asin (lua_State *L) {
+- lua_pushnumber(L, asin(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(casin) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(asin) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_acos (lua_State *L) {
+- lua_pushnumber(L, acos(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(cacos) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(acos) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_atan (lua_State *L) {
+- lua_pushnumber(L, atan(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(catan) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(atan) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_atan2 (lua_State *L) {
+- lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++ /* scalars only */
++ lua_pushnumber(L, _LF(atan2) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+ }
+
+ static int math_ceil (lua_State *L) {
+- lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_Complex v= luaL_checkcomplex(L, 1);
++ lua_pushcomplex(L, _LF(ceil) (_LF(creal)(v)) + _LF(ceil) (_LF(cimag)(v))*I);
++#else
++ lua_pushnumber(L, _LF(ceil) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_floor (lua_State *L) {
+- lua_pushnumber(L, floor(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_Complex v= luaL_checkcomplex(L, 1);
++ lua_pushcomplex(L, _LF(floor) (_LF(creal)(v)) + _LF(floor) (_LF(cimag)(v))*I);
++#else
++ lua_pushnumber(L, _LF(floor) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+-static int math_fmod (lua_State *L) {
+- lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++static int math_fmod (lua_State *L) {
++ /* scalars only */
++ lua_pushnumber(L, _LF(fmod) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+ }
+
+ static int math_modf (lua_State *L) {
+- double ip;
+- double fp = modf(luaL_checknumber(L, 1), &ip);
++ /* scalars only */
++ lua_Number ip;
++ lua_Number fp = _LF(modf) (luaL_checknumber(L, 1), &ip);
+ lua_pushnumber(L, ip);
+ lua_pushnumber(L, fp);
+ return 2;
+ }
+
+ static int math_sqrt (lua_State *L) {
+- lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(csqrt) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(sqrt) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_pow (lua_State *L) {
+- lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++#ifdef LNUM_COMPLEX
++ /* C99 'cpow' gives somewhat inaccurate results (i.e. (-1)^2 = -1+1.2246467991474e-16i).
++ * 'luai_vectpow' smoothens such, reusing it is the reason we need to #include "lnum.h".
++ */
++ lua_pushcomplex(L, luai_vectpow(luaL_checkcomplex(L,1), luaL_checkcomplex(L,2)));
++#else
++ lua_pushnumber(L, _LF(pow) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++#endif
+ return 1;
+ }
+
+ static int math_log (lua_State *L) {
+- lua_pushnumber(L, log(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(log) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_log10 (lua_State *L) {
+- lua_pushnumber(L, log10(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ /* Not in standard <complex.h> , but easy to calculate: log_a(x) = log_b(x) / log_b(a)
++ */
++ lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1)) / _LF(log) (10));
++#else
++ lua_pushnumber(L, _LF(log10) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_exp (lua_State *L) {
+- lua_pushnumber(L, exp(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(cexp) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(exp) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+@@ -138,19 +234,20 @@ static int math_rad (lua_State *L) {
+
+ static int math_frexp (lua_State *L) {
+ int e;
+- lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));
++ lua_pushnumber(L, _LF(frexp) (luaL_checknumber(L, 1), &e));
+ lua_pushinteger(L, e);
+ return 2;
+ }
+
+ static int math_ldexp (lua_State *L) {
+- lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));
++ lua_pushnumber(L, _LF(ldexp) (luaL_checknumber(L, 1), luaL_checkint(L, 2)));
+ return 1;
+ }
+
+
+
+ static int math_min (lua_State *L) {
++ /* scalars only */
+ int n = lua_gettop(L); /* number of arguments */
+ lua_Number dmin = luaL_checknumber(L, 1);
+ int i;
+@@ -165,6 +262,7 @@ static int math_min (lua_State *L) {
+
+
+ static int math_max (lua_State *L) {
++ /* scalars only */
+ int n = lua_gettop(L); /* number of arguments */
+ lua_Number dmax = luaL_checknumber(L, 1);
+ int i;
+@@ -182,25 +280,20 @@ static int math_random (lua_State *L) {
+ /* the `%' avoids the (rare) case of r==1, and is needed also because on
+ some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
+ lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
+- switch (lua_gettop(L)) { /* check number of arguments */
+- case 0: { /* no arguments */
+- lua_pushnumber(L, r); /* Number between 0 and 1 */
+- break;
+- }
+- case 1: { /* only upper limit */
+- int u = luaL_checkint(L, 1);
+- luaL_argcheck(L, 1<=u, 1, "interval is empty");
+- lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */
+- break;
+- }
+- case 2: { /* lower and upper limits */
+- int l = luaL_checkint(L, 1);
+- int u = luaL_checkint(L, 2);
+- luaL_argcheck(L, l<=u, 2, "interval is empty");
+- lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */
+- break;
+- }
+- default: return luaL_error(L, "wrong number of arguments");
++ int n= lua_gettop(L); /* number of arguments */
++ if (n==0) { /* no arguments: range [0,1) */
++ lua_pushnumber(L, r);
++ } else if (n<=2) { /* int range [1,u] or [l,u] */
++ int l= n==1 ? 1 : luaL_checkint(L, 1);
++ int u = luaL_checkint(L, n);
++ int tmp;
++ lua_Number d;
++ luaL_argcheck(L, l<=u, n, "interval is empty");
++ d= _LF(floor)(r*(u-l+1));
++ lua_number2int(tmp,d);
++ lua_pushinteger(L, l+tmp);
++ } else {
++ return luaL_error(L, "wrong number of arguments");
+ }
+ return 1;
+ }
+@@ -211,6 +304,66 @@ static int math_randomseed (lua_State *L
+ return 0;
+ }
+
++/*
++* Lua 5.1 does not have acosh, asinh, atanh for scalars (not ANSI C)
++*/
++#if __STDC_VERSION__ >= 199901L
++static int math_acosh (lua_State *L) {
++# ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(cacosh) (luaL_checkcomplex(L,1)));
++# else
++ lua_pushnumber(L, _LF(acosh) (luaL_checknumber(L,1)));
++# endif
++ return 1;
++}
++static int math_asinh (lua_State *L) {
++# ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(casinh) (luaL_checkcomplex(L,1)));
++# else
++ lua_pushnumber(L, _LF(asinh) (luaL_checknumber(L,1)));
++# endif
++ return 1;
++}
++static int math_atanh (lua_State *L) {
++# ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(catanh) (luaL_checkcomplex(L,1)));
++# else
++ lua_pushnumber(L, _LF(atanh) (luaL_checknumber(L,1)));
++# endif
++ return 1;
++}
++#endif
++
++/*
++ * C99 complex functions, not covered above.
++*/
++#ifdef LNUM_COMPLEX
++static int math_arg (lua_State *L) {
++ lua_pushnumber(L, _LF(carg) (luaL_checkcomplex(L,1)));
++ return 1;
++}
++
++static int math_imag (lua_State *L) {
++ lua_pushnumber(L, _LF(cimag) (luaL_checkcomplex(L,1)));
++ return 1;
++}
++
++static int math_real (lua_State *L) {
++ lua_pushnumber(L, _LF(creal) (luaL_checkcomplex(L,1)));
++ return 1;
++}
++
++static int math_conj (lua_State *L) {
++ lua_pushcomplex(L, _LF(conj) (luaL_checkcomplex(L,1)));
++ return 1;
++}
++
++static int math_proj (lua_State *L) {
++ lua_pushcomplex(L, _LF(cproj) (luaL_checkcomplex(L,1)));
++ return 1;
++}
++#endif
++
+
+ static const luaL_Reg mathlib[] = {
+ {"abs", math_abs},
+@@ -241,6 +394,18 @@ static const luaL_Reg mathlib[] = {
+ {"sqrt", math_sqrt},
+ {"tanh", math_tanh},
+ {"tan", math_tan},
++#if __STDC_VERSION__ >= 199901L
++ {"acosh", math_acosh},
++ {"asinh", math_asinh},
++ {"atanh", math_atanh},
++#endif
++#ifdef LNUM_COMPLEX
++ {"arg", math_arg},
++ {"imag", math_imag},
++ {"real", math_real},
++ {"conj", math_conj},
++ {"proj", math_proj},
++#endif
+ {NULL, NULL}
+ };
+
+@@ -252,8 +417,10 @@ LUALIB_API int luaopen_math (lua_State *
+ luaL_register(L, LUA_MATHLIBNAME, mathlib);
+ lua_pushnumber(L, PI);
+ lua_setfield(L, -2, "pi");
+- lua_pushnumber(L, HUGE_VAL);
++ lua_pushnumber(L, HUGE);
+ lua_setfield(L, -2, "huge");
++ lua_pushinteger(L, LUA_INTEGER_MAX );
++ lua_setfield(L, -2, "hugeint");
+ #if defined(LUA_COMPAT_MOD)
+ lua_getfield(L, -1, "fmod");
+ lua_setfield(L, -2, "mod");
+--- /dev/null
++++ b/src/lnum.c
+@@ -0,0 +1,312 @@
++/*
++** $Id: lnum.c,v ... $
++** Internal number model
++** See Copyright Notice in lua.h
++*/
++
++#include <stdlib.h>
++#include <math.h>
++#include <ctype.h>
++#include <string.h>
++#include <stdio.h>
++#include <errno.h>
++
++#define lnum_c
++#define LUA_CORE
++
++#include "lua.h"
++#include "llex.h"
++#include "lnum.h"
++
++/*
++** lua_real2str converts a (non-complex) number to a string.
++** lua_str2real converts a string to a (non-complex) number.
++*/
++#define lua_real2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
++
++/*
++* Note: Only 'strtod()' is part of ANSI C; others are C99 and
++* may need '--std=c99' compiler setting (at least on Ubuntu 7.10).
++*
++* Visual C++ 2008 Express does not have 'strtof()', nor 'strtold()'.
++* References to '_strtold()' exist but don't compile. It seems best
++* to leave Windows users with DOUBLE only (or compile with MinGW).
++*
++* In practise, using '(long double)strtod' is a risky thing, since
++* it will cause accuracy loss in reading in numbers, and such losses
++* will pile up in later processing. Get a real 'strtold()' or don't
++* use that mode at all.
++*/
++#ifdef LNUM_DOUBLE
++# define lua_str2real strtod
++#elif defined(LNUM_FLOAT)
++# define lua_str2real strtof
++#elif defined(LNUM_LDOUBLE)
++# define lua_str2real strtold
++#endif
++
++#define lua_integer2str(s,v) sprintf((s), LUA_INTEGER_FMT, (v))
++
++/* 's' is expected to be LUAI_MAXNUMBER2STR long (enough for any number)
++*/
++void luaO_num2buf( char *s, const TValue *o )
++{
++ lua_Number n;
++ lua_assert( ttisnumber(o) );
++
++ /* Reason to handle integers differently is not only speed, but accuracy as
++ * well. We want to make any integer tostring() without roundings, at all.
++ */
++ if (ttisint(o)) {
++ lua_integer2str( s, ivalue(o) );
++ return;
++ }
++ n= nvalue_fast(o);
++ lua_real2str(s, n);
++
++#ifdef LNUM_COMPLEX
++ lua_Number n2= nvalue_img_fast(o);
++ if (n2!=0) { /* Postfix with +-Ni */
++ int re0= (n == 0);
++ char *s2= re0 ? s : strchr(s,'\0');
++ if ((!re0) && (n2>0)) *s2++= '+';
++ lua_real2str( s2, n2 );
++ strcat(s2,"i");
++ }
++#endif
++}
++
++/*
++* If a LUA_TNUMBER has integer value, give it.
++*/
++int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref ) {
++ lua_Number d;
++ lua_Integer i;
++
++ lua_assert( ttype(o)==LUA_TNUMBER );
++ lua_assert( ref );
++#ifdef LNUM_COMPLEX
++ if (nvalue_img_fast(o)!=0) return 0;
++#endif
++ d= nvalue_fast(o);
++ lua_number2integer(i, d);
++ if (cast_num(i) == d) {
++ *ref= i; return 1;
++ }
++ return 0;
++}
++
++/*
++ * Lua 5.1.3 (using 'strtod()') allows 0x+hex but not 0+octal. This is good,
++ * and we should NOT use 'autobase' 0 with 'strtoul[l]()' for this reason.
++ *
++ * Lua 5.1.3 allows '0x...' numbers to overflow and lose precision; this is not
++ * good. On Visual C++ 2008, 'strtod()' does not even take them in. Better to
++ * require hex values to fit 'lua_Integer' or give an error that they don't?
++ *
++ * Full hex range (0 .. 0xff..ff) is stored as integers, not to lose any bits.
++ * Numerical value of 0xff..ff will be -1, if used in calculations.
++ *
++ * Returns: TK_INT for a valid integer, '*endptr_ref' updated
++ * TK_NUMBER for seemingly numeric, to be parsed as floating point
++ * 0 for bad characters, not a number (or '0x' out of range)
++ */
++static int luaO_str2i (const char *s, lua_Integer *res, char **endptr_ref) {
++ char *endptr;
++ /* 'v' gets ULONG_MAX on possible overflow (which is > LUA_INTEGER_MAX);
++ * we don't have to check 'errno' here.
++ */
++ unsigned LUA_INTEGER v= lua_str2ul(s, &endptr, 10);
++ if (endptr == s) return 0; /* nothing numeric */
++ if (v==0 && *endptr=='x') {
++ errno= 0; /* needs to be set, 'strtoul[l]' does not clear it */
++ v= lua_str2ul(endptr+1, &endptr, 16); /* retry as hex, unsigned range */
++ if (errno==ERANGE) { /* clamped to 0xff..ff */
++#if (defined(LNUM_INT32) && !defined(LNUM_FLOAT)) || defined(LNUM_LDOUBLE)
++ return TK_NUMBER; /* Allow to be read as floating point (has more integer range) */
++#else
++ return 0; /* Reject the number */
++#endif
++ }
++ } else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) {
++ return TK_NUMBER; /* not in signed range, or has '.', 'e' etc. trailing */
++ }
++ *res= (lua_Integer)v;
++ *endptr_ref= endptr;
++ return TK_INT;
++}
++
++/* 0 / TK_NUMBER / TK_INT (/ TK_NUMBER2) */
++int luaO_str2d (const char *s, lua_Number *res_n, lua_Integer *res_i) {
++ char *endptr;
++ int ret= TK_NUMBER;
++ /* Check integers first, if caller is allowing.
++ * If 'res2'==NULL, they're only looking for floating point.
++ */
++ if (res_i) {
++ ret= luaO_str2i(s,res_i,&endptr);
++ if (ret==0) return 0;
++ }
++ if (ret==TK_NUMBER) {
++ lua_assert(res_n);
++ /* Note: Visual C++ 2008 Express 'strtod()' does not read in "0x..."
++ * numbers; it will read '0' and spit 'x' as endptr.
++ * This means hex constants not fitting in 'lua_Integer' won't
++ * be read in at all. What to do?
++ */
++ *res_n = lua_str2real(s, &endptr);
++ if (endptr == s) return 0; /* conversion failed */
++ /* Visual C++ 2008 'strtod()' does not allow "0x..." input. */
++#if defined(_MSC_VER) && !defined(LNUM_FLOAT) && !defined(LNUM_INT64)
++ if (*res_n==0 && *endptr=='x') {
++ /* Hex constant too big for 'lua_Integer' but that could fit in 'lua_Number'
++ * integer bits
++ */
++ unsigned __int64 v= _strtoui64( s, &endptr, 16 );
++ /* We just let > 64 bit values be clamped to _UI64_MAX (MSDN does not say 'errno'==ERANGE would be set) */
++ *res_n= cast_num(v);
++ if (*res_n != v) return 0; /* Would have lost accuracy */
++ }
++#endif
++#ifdef LNUM_COMPLEX
++ if (*endptr == 'i') { endptr++; ret= TK_NUMBER2; }
++#endif
++ }
++ if (*endptr) {
++ while (isspace(cast(unsigned char, *endptr))) endptr++;
++ if (*endptr) return 0; /* invalid trail */
++ }
++ return ret;
++}
++
++
++/* Functions for finding out, when integer operations remain in range
++ * (and doing them).
++ */
++int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++ lua_Integer v= ib+ic; /* may overflow */
++ if (ib>0 && ic>0) { if (v < 0) return 0; /*overflow, use floats*/ }
++ else if (ib<0 && ic<0) { if (v >= 0) return 0; }
++ *r= v;
++ return 1;
++}
++
++int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++ lua_Integer v= ib-ic; /* may overflow */
++ if (ib>=0 && ic<0) { if (v < 0) return 0; /*overflow, use floats*/ }
++ else if (ib<0 && ic>0) { if (v >= 0) return 0; }
++ *r= v;
++ return 1;
++}
++
++int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++ if (ib!=LUA_INTEGER_MIN && ic!=LUA_INTEGER_MIN) {
++ lua_Integer b= luai_abs(ib), c= luai_abs(ic);
++ if ( (ib==0) || (LUA_INTEGER_MAX/b >= c) ) {
++ *r= ib*ic; /* no overflow */
++ return 1;
++ }
++ } else if (ib==0 || ic==0) {
++ *r= 0; return 1;
++ }
++
++ /* Result can be LUA_INTEGER_MIN; if it is, calculating it using floating
++ * point will not cause accuracy loss.
++ */
++ if ( luai_nummul( cast_num(ib), cast_num(ic) ) == LUA_INTEGER_MIN ) {
++ *r= LUA_INTEGER_MIN;
++ return 1;
++ }
++ return 0;
++}
++
++int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++ /* N/0: leave to float side, to give an error
++ */
++ if (ic==0) return 0;
++
++ /* N/LUA_INTEGER_MIN: always non-integer results, or 0 or +1
++ */
++ if (ic==LUA_INTEGER_MIN) {
++ if (ib==LUA_INTEGER_MIN) { *r=1; return 1; }
++ if (ib==0) { *r=0; return 1; }
++
++ /* LUA_INTEGER_MIN (-2^31|63)/N: calculate using float side (either the division
++ * causes non-integer results, or there is no accuracy loss in int->fp->int
++ * conversions (N=2,4,8,..,256 and N=2^30,2^29,..2^23).
++ */
++ } else if (ib==LUA_INTEGER_MIN) {
++ lua_Number d= luai_numdiv( cast_num(LUA_INTEGER_MIN), cast_num(ic) );
++ lua_Integer i; lua_number2integer(i,d);
++ if (cast_num(i)==d) { *r= i; return 1; }
++
++ } else {
++ /* Note: We _can_ use ANSI C mod here, even on negative values, since
++ * we only test for == 0 (the sign would be implementation dependent).
++ */
++ if (ib%ic == 0) { *r= ib/ic; return 1; }
++ }
++
++ return 0;
++}
++
++int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++ if (ic!=0) {
++ /* ANSI C can be trusted when b%c==0, or when values are non-negative.
++ * b - (floor(b/c) * c)
++ * -->
++ * + +: b - (b/c) * c (b % c can be used)
++ * - -: b - (b/c) * c (b % c could work, but not defined by ANSI C)
++ * 0 -: b - (b/c) * c (=0, b % c could work, but not defined by ANSI C)
++ * - +: b - (b/c-1) * c (when b!=-c)
++ * + -: b - (b/c-1) * c (when b!=-c)
++ *
++ * o MIN%MIN ends up 0, via overflow in calcs but that does not matter.
++ * o MIN%MAX ends up MAX-1 (and other such numbers), also after overflow,
++ * but that does not matter, results do.
++ */
++ lua_Integer v= ib % ic;
++ if ( v!=0 && (ib<0 || ic<0) ) {
++ v= ib - ((ib/ic) - ((ib<=0 && ic<0) ? 0:1)) * ic;
++ }
++ /* Result should always have same sign as 2nd argument. (PIL2) */
++ lua_assert( (v<0) ? (ic<0) : (v>0) ? (ic>0) : 1 );
++ *r= v;
++ return 1;
++ }
++ return 0; /* let float side return NaN */
++}
++
++int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++
++ /* In FLOAT/INT32 or FLOAT|DOUBLE/INT64 modes, calculating integer powers
++ * via FP realm may lose accuracy (i.e. 7^11 = 1977326743, which fits int32
++ * but not 23-bit float mantissa).
++ *
++ * The current solution is dumb, but it works and uses little code. Use of
++ * integer powers is not anticipated to be very frequent (apart from 2^x,
++ * which is separately optimized).
++ */
++ if (ib==0) *r=0;
++ else if (ic<0) return 0; /* FP realm */
++ else if (ib==2 && ic < (int)sizeof(lua_Integer)*8-1) *r= ((lua_Integer)1)<<ic; /* 1,2,4,...2^30 | 2^62 optimization */
++ else if (ic==0) *r=1;
++ else if (luai_abs(ib)==1) *r= (ic%2) ? ib:1;
++ else {
++ lua_Integer x= ib;
++ while( --ic ) {
++ if (!try_mulint( &x, x, ib ))
++ return 0; /* FP realm */
++ }
++ *r= x;
++ }
++ return 1;
++}
++
++int try_unmint( lua_Integer *r, lua_Integer ib ) {
++ /* Negating LUA_INTEGER_MIN leaves the range. */
++ if ( ib != LUA_INTEGER_MIN )
++ { *r= -ib; return 1; }
++ return 0;
++}
++
+--- /dev/null
++++ b/src/lnum.h
+@@ -0,0 +1,116 @@
++/*
++** $Id: lnum.h,v ... $
++** Internal Number model
++** See Copyright Notice in lua.h
++*/
++
++#ifndef lnum_h
++#define lnum_h
++
++#include <math.h>
++
++#include "lobject.h"
++
++/*
++** The luai_num* macros define the primitive operations over 'lua_Number's
++** (not 'lua_Integer's, not 'lua_Complex').
++*/
++#define luai_numadd(a,b) ((a)+(b))
++#define luai_numsub(a,b) ((a)-(b))
++#define luai_nummul(a,b) ((a)*(b))
++#define luai_numdiv(a,b) ((a)/(b))
++#define luai_nummod(a,b) ((a) - _LF(floor)((a)/(b))*(b))
++#define luai_numpow(a,b) (_LF(pow)(a,b))
++#define luai_numunm(a) (-(a))
++#define luai_numeq(a,b) ((a)==(b))
++#define luai_numlt(a,b) ((a)<(b))
++#define luai_numle(a,b) ((a)<=(b))
++#define luai_numisnan(a) (!luai_numeq((a), (a)))
++
++int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_unmint( lua_Integer *r, lua_Integer ib );
++
++#ifdef LNUM_COMPLEX
++ static inline lua_Complex luai_vectunm( lua_Complex a ) { return -a; }
++ static inline lua_Complex luai_vectadd( lua_Complex a, lua_Complex b ) { return a+b; }
++ static inline lua_Complex luai_vectsub( lua_Complex a, lua_Complex b ) { return a-b; }
++ static inline lua_Complex luai_vectmul( lua_Complex a, lua_Complex b ) { return a*b; }
++ static inline lua_Complex luai_vectdiv( lua_Complex a, lua_Complex b ) { return a/b; }
++
++/*
++ * C99 does not provide modulus for complex numbers. It most likely is not
++ * meaningful at all.
++ */
++
++/*
++ * Complex power
++ *
++ * C99 'cpow' gives inaccurate results for many common cases s.a. (1i)^2 ->
++ * -1+1.2246467991474e-16i (OS X 10.4, gcc 4.0.1 build 5367)
++ *
++ * [(a+bi)^(c+di)] = (r^c) * exp(-d*t) * cos(c*t + d*ln(r)) +
++ * = (r^c) * exp(-d*t) * sin(c*t + d*ln(r)) *i
++ * r = sqrt(a^2+b^2), t = arctan( b/a )
++ *
++ * Reference: <http://home.att.net/~srschmitt/complexnumbers.html>
++ * Could also be calculated using: x^y = exp(ln(x)*y)
++ *
++ * Note: Defined here (and not in .c) so 'lmathlib.c' can share the
++ * implementation.
++ */
++ static inline
++ lua_Complex luai_vectpow( lua_Complex a, lua_Complex b )
++ {
++# if 1
++ lua_Number ar= _LF(creal)(a), ai= _LF(cimag)(a);
++ lua_Number br= _LF(creal)(b), bi= _LF(cimag)(b);
++
++ if (ai==0 && bi==0) { /* a^c (real) */
++ return luai_numpow( ar, br );
++ }
++
++ int br_int= (int)br;
++
++ if ( ai!=0 && bi==0 && br_int==br && br_int!=0 && br_int!=INT_MIN ) {
++ /* (a+bi)^N, N = { +-1,+-2, ... +-INT_MAX }
++ */
++ lua_Number k= luai_numpow( _LF(sqrt) (ar*ar + ai*ai), br );
++ lua_Number cos_z, sin_z;
++
++ /* Situation depends upon c (N) in the following manner:
++ *
++ * N%4==0 => cos(c*t)=1, sin(c*t)=0
++ * (N*sign(b))%4==1 or (N*sign(b))%4==-3 => cos(c*t)=0, sin(c*t)=1
++ * N%4==2 or N%4==-2 => cos(c*t)=-1, sin(c*t)=0
++ * (N*sign(b))%4==-1 or (N*sign(b))%4==3 => cos(c*t)=0, sin(c*t)=-1
++ */
++ int br_int_abs = br_int<0 ? -br_int:br_int;
++
++ switch( (br_int_abs%4) * (br_int<0 ? -1:1) * (ai<0 ? -1:1) ) {
++ case 0: cos_z=1, sin_z=0; break;
++ case 2: case -2: cos_z=-1, sin_z=0; break;
++ case 1: case -3: cos_z=0, sin_z=1; break;
++ case 3: case -1: cos_z=0, sin_z=-1; break;
++ default: lua_assert(0); return 0;
++ }
++ return k*cos_z + (k*sin_z)*I;
++ }
++# endif
++ return _LF(cpow) ( a, b );
++ }
++#endif
++
++LUAI_FUNC int luaO_str2d (const char *s, lua_Number *res1, lua_Integer *res2);
++LUAI_FUNC void luaO_num2buf( char *s, const TValue *o );
++
++LUAI_FUNC int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref );
++
++#define luai_normalize(o) \
++{ lua_Integer _i; if (tt_integer_valued(o,&_i)) setivalue(o,_i); }
++
++#endif
+--- /dev/null
++++ b/src/lnum_config.h
+@@ -0,0 +1,221 @@
++/*
++** $Id: lnum_config.h,v ... $
++** Internal Number model
++** See Copyright Notice in lua.h
++*/
++
++#ifndef lnum_config_h
++#define lnum_config_h
++
++/*
++** Default number modes
++*/
++#if (!defined LNUM_DOUBLE) && (!defined LNUM_FLOAT) && (!defined LNUM_LDOUBLE)
++# define LNUM_FLOAT
++#endif
++#if (!defined LNUM_INT16) && (!defined LNUM_INT32) && (!defined LNUM_INT64)
++# define LNUM_INT32
++#endif
++
++/*
++** Require C99 mode for COMPLEX, FLOAT and LDOUBLE (only DOUBLE is ANSI C).
++*/
++#if defined(LNUM_COMPLEX) && (__STDC_VERSION__ < 199901L)
++# error "Need C99 for complex (use '--std=c99' or similar)"
++#elif defined(LNUM_LDOUBLE) && (__STDC_VERSION__ < 199901L) && !defined(_MSC_VER)
++# error "Need C99 for 'long double' (use '--std=c99' or similar)"
++#elif defined(LNUM_FLOAT) && (__STDC_VERSION__ < 199901L)
++/* LNUM_FLOAT not supported on Windows */
++# error "Need C99 for 'float' (use '--std=c99' or similar)"
++#endif
++
++/*
++** Number mode identifier to accompany the version string.
++*/
++#ifdef LNUM_COMPLEX
++# define _LNUM1 "complex "
++#else
++# define _LNUM1 ""
++#endif
++#ifdef LNUM_DOUBLE
++# define _LNUM2 "double"
++#elif defined(LNUM_FLOAT)
++# define _LNUM2 "float"
++#elif defined(LNUM_LDOUBLE)
++# define _LNUM2 "ldouble"
++#endif
++#ifdef LNUM_INT32
++# define _LNUM3 "int32"
++#elif defined(LNUM_INT64)
++# define _LNUM3 "int64"
++#elif defined(LNUM_INT16)
++# define _LNUM3 "int16"
++#endif
++#define LUA_LNUM _LNUM1 _LNUM2 " " _LNUM3
++
++/*
++** LUA_NUMBER is the type of floating point number in Lua
++** LUA_NUMBER_SCAN is the format for reading numbers.
++** LUA_NUMBER_FMT is the format for writing numbers.
++*/
++#ifdef LNUM_FLOAT
++# define LUA_NUMBER float
++# define LUA_NUMBER_SCAN "%f"
++# define LUA_NUMBER_FMT "%g"
++#elif (defined LNUM_DOUBLE)
++# define LUA_NUMBER double
++# define LUA_NUMBER_SCAN "%lf"
++# define LUA_NUMBER_FMT "%.14g"
++#elif (defined LNUM_LDOUBLE)
++# define LUA_NUMBER long double
++# define LUA_NUMBER_SCAN "%Lg"
++# define LUA_NUMBER_FMT "%.20Lg"
++#endif
++
++
++/*
++** LUAI_MAXNUMBER2STR: size of a buffer fitting any number->string result.
++**
++** double: 24 (sign, x.xxxxxxxxxxxxxxe+nnnn, and \0)
++** int64: 21 (19 digits, sign, and \0)
++** long double: 43 for 128-bit (sign, x.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxe+nnnn, and \0)
++** 30 for 80-bit (sign, x.xxxxxxxxxxxxxxxxxxxxe+nnnn, and \0)
++*/
++#ifdef LNUM_LDOUBLE
++# define _LUAI_MN2S 44
++#else
++# define _LUAI_MN2S 24
++#endif
++
++#ifdef LNUM_COMPLEX
++# define LUAI_MAXNUMBER2STR (2*_LUAI_MN2S)
++#else
++# define LUAI_MAXNUMBER2STR _LUAI_MN2S
++#endif
++
++/*
++** LUA_INTEGER is the integer type used by lua_pushinteger/lua_tointeger/lua_isinteger.
++** LUA_INTEGER_SCAN is the format for reading integers
++** LUA_INTEGER_FMT is the format for writing integers
++**
++** Note: Visual C++ 2005 does not have 'strtoull()', use '_strtoui64()' instead.
++*/
++#ifdef LNUM_INT32
++# if LUAI_BITSINT > 16
++# define LUA_INTEGER int
++# define LUA_INTEGER_SCAN "%d"
++# define LUA_INTEGER_FMT "%d"
++# else
++/* Note: 'LUA_INTEGER' being 'ptrdiff_t' (as in Lua 5.1) causes problems with
++ * 'printf()' operations. Also 'unsigned ptrdiff_t' is invalid.
++ */
++# define LUA_INTEGER long
++# define LUA_INTEGER_SCAN "%ld"
++# define LUA_INTEGER_FMT "%ld"
++# endif
++# define LUA_INTEGER_MAX 0x7FFFFFFF /* 2^31-1 */
++/* */
++#elif defined(LNUM_INT64)
++# define LUA_INTEGER long long
++# ifdef _MSC_VER
++# define lua_str2ul _strtoui64
++# else
++# define lua_str2ul strtoull
++# endif
++# define LUA_INTEGER_SCAN "%lld"
++# define LUA_INTEGER_FMT "%lld"
++# define LUA_INTEGER_MAX 0x7fffffffffffffffLL /* 2^63-1 */
++# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX - 1LL) /* -2^63 */
++/* */
++#elif defined(LNUM_INT16)
++# if LUAI_BITSINT > 16
++# define LUA_INTEGER short
++# define LUA_INTEGER_SCAN "%hd"
++# define LUA_INTEGER_FMT "%hd"
++# else
++# define LUA_INTEGER int
++# define LUA_INTEGER_SCAN "%d"
++# define LUA_INTEGER_FMT "%d"
++# endif
++# define LUA_INTEGER_MAX 0x7FFF /* 2^16-1 */
++#endif
++
++#ifndef lua_str2ul
++# define lua_str2ul (unsigned LUA_INTEGER)strtoul
++#endif
++#ifndef LUA_INTEGER_MIN
++# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX -1) /* -2^16|32 */
++#endif
++
++/*
++@@ lua_number2int is a macro to convert lua_Number to int.
++@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
++** CHANGE them if you know a faster way to convert a lua_Number to
++** int (with any rounding method and without throwing errors) in your
++** system. In Pentium machines, a naive typecast from double to int
++** in C is extremely slow, so any alternative is worth trying.
++*/
++
++/* On a Pentium, resort to a trick */
++#if defined(LNUM_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \
++ (defined(__i386) || defined (_M_IX86) || defined(__i386__))
++
++/* On a Microsoft compiler, use assembler */
++# if defined(_MSC_VER)
++# define lua_number2int(i,d) __asm fld d __asm fistp i
++# else
++
++/* the next trick should work on any Pentium, but sometimes clashes
++ with a DirectX idiosyncrasy */
++union luai_Cast { double l_d; long l_l; };
++# define lua_number2int(i,d) \
++ { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
++# endif
++
++# ifndef LNUM_INT64
++# define lua_number2integer lua_number2int
++# endif
++
++/* this option always works, but may be slow */
++#else
++# define lua_number2int(i,d) ((i)=(int)(d))
++#endif
++
++/* Note: Some compilers (OS X gcc 4.0?) may choke on double->long long conversion
++ * since it can lose precision. Others do require 'long long' there.
++ */
++#ifndef lua_number2integer
++# define lua_number2integer(i,d) ((i)=(lua_Integer)(d))
++#endif
++
++/*
++** 'luai_abs()' to give absolute value of 'lua_Integer'
++*/
++#ifdef LNUM_INT32
++# define luai_abs abs
++#elif defined(LNUM_INT64) && (__STDC_VERSION__ >= 199901L)
++# define luai_abs llabs
++#else
++# define luai_abs(v) ((v) >= 0 ? (v) : -(v))
++#endif
++
++/*
++** LUAI_UACNUMBER is the result of an 'usual argument conversion' over a number.
++** LUAI_UACINTEGER the same, over an integer.
++*/
++#define LUAI_UACNUMBER double
++#define LUAI_UACINTEGER long
++
++/* ANSI C only has math funcs for 'double. C99 required for float and long double
++ * variants.
++ */
++#ifdef LNUM_DOUBLE
++# define _LF(name) name
++#elif defined(LNUM_FLOAT)
++# define _LF(name) name ## f
++#elif defined(LNUM_LDOUBLE)
++# define _LF(name) name ## l
++#endif
++
++#endif
++
+--- a/src/lobject.c
++++ b/src/lobject.c
+@@ -21,7 +21,8 @@
+ #include "lstate.h"
+ #include "lstring.h"
+ #include "lvm.h"
+-
++#include "llex.h"
++#include "lnum.h"
+
+
+ const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};
+@@ -70,12 +71,31 @@ int luaO_log2 (unsigned int x) {
+
+
+ int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
+- if (ttype(t1) != ttype(t2)) return 0;
++ if (!ttype_ext_same(t1,t2)) return 0;
+ else switch (ttype(t1)) {
+ case LUA_TNIL:
+ return 1;
++ case LUA_TINT:
++ if (ttype(t2)==LUA_TINT)
++ return ivalue(t1) == ivalue(t2);
++ else { /* t1:int, t2:num */
++#ifdef LNUM_COMPLEX
++ if (nvalue_img_fast(t2) != 0) return 0;
++#endif
++ /* Avoid doing accuracy losing cast, if possible. */
++ lua_Integer tmp;
++ if (tt_integer_valued(t2,&tmp))
++ return ivalue(t1) == tmp;
++ else
++ return luai_numeq( cast_num(ivalue(t1)), nvalue_fast(t2) );
++ }
+ case LUA_TNUMBER:
+- return luai_numeq(nvalue(t1), nvalue(t2));
++ if (ttype(t2)==LUA_TINT)
++ return luaO_rawequalObj(t2, t1); /* swap LUA_TINT to left */
++#ifdef LNUM_COMPLEX
++ if (!luai_numeq(nvalue_img_fast(t1), nvalue_img_fast(t2))) return 0;
++#endif
++ return luai_numeq(nvalue_fast(t1), nvalue_fast(t2));
+ case LUA_TBOOLEAN:
+ return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */
+ case LUA_TLIGHTUSERDATA:
+@@ -86,21 +106,6 @@ int luaO_rawequalObj (const TValue *t1,
+ }
+ }
+
+-
+-int luaO_str2d (const char *s, lua_Number *result) {
+- char *endptr;
+- *result = lua_str2number(s, &endptr);
+- if (endptr == s) return 0; /* conversion failed */
+- if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */
+- *result = cast_num(strtoul(s, &endptr, 16));
+- if (*endptr == '\0') return 1; /* most common case */
+- while (isspace(cast(unsigned char, *endptr))) endptr++;
+- if (*endptr != '\0') return 0; /* invalid trailing characters? */
+- return 1;
+-}
+-
+-
+-
+ static void pushstr (lua_State *L, const char *str) {
+ setsvalue2s(L, L->top, luaS_new(L, str));
+ incr_top(L);
+@@ -131,7 +136,11 @@ const char *luaO_pushvfstring (lua_State
+ break;
+ }
+ case 'd': {
+- setnvalue(L->top, cast_num(va_arg(argp, int)));
++ /* This is tricky for 64-bit integers; maybe they even cannot be
++ * supported on all compilers; depends on the conversions applied to
++ * variable argument lists. TBD: test!
++ */
++ setivalue(L->top, (lua_Integer) va_arg(argp, l_uacInteger));
+ incr_top(L);
+ break;
+ }
+@@ -212,3 +221,4 @@ void luaO_chunkid (char *out, const char
+ }
+ }
+ }
++
+--- a/src/lobject.h
++++ b/src/lobject.h
+@@ -17,7 +17,11 @@
+
+
+ /* tags for values visible from Lua */
+-#define LAST_TAG LUA_TTHREAD
++#if LUA_TINT > LUA_TTHREAD
++# define LAST_TAG LUA_TINT
++#else
++# define LAST_TAG LUA_TTHREAD
++#endif
+
+ #define NUM_TAGS (LAST_TAG+1)
+
+@@ -59,7 +63,12 @@ typedef struct GCheader {
+ typedef union {
+ GCObject *gc;
+ void *p;
++#ifdef LNUM_COMPLEX
++ lua_Complex n;
++#else
+ lua_Number n;
++#endif
++ lua_Integer i;
+ int b;
+ } Value;
+
+@@ -77,7 +86,11 @@ typedef struct lua_TValue {
+
+ /* Macros to test type */
+ #define ttisnil(o) (ttype(o) == LUA_TNIL)
+-#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
++#define ttisint(o) (ttype(o) == LUA_TINT)
++#define ttisnumber(o) ((ttype(o) == LUA_TINT) || (ttype(o) == LUA_TNUMBER))
++#ifdef LNUM_COMPLEX
++# define ttiscomplex(o) ((ttype(o) == LUA_TNUMBER) && (nvalue_img_fast(o)!=0))
++#endif
+ #define ttisstring(o) (ttype(o) == LUA_TSTRING)
+ #define ttistable(o) (ttype(o) == LUA_TTABLE)
+ #define ttisfunction(o) (ttype(o) == LUA_TFUNCTION)
+@@ -90,7 +103,25 @@ typedef struct lua_TValue {
+ #define ttype(o) ((o)->tt)
+ #define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc)
+ #define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
+-#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n)
++
++#define ttype_ext(o) ( ttype(o) == LUA_TINT ? LUA_TNUMBER : ttype(o) )
++#define ttype_ext_same(o1,o2) ( (ttype(o1)==ttype(o2)) || (ttisnumber(o1) && ttisnumber(o2)) )
++
++/* '_fast' variants are for cases where 'ttype(o)' is known to be LUA_TNUMBER.
++ */
++#ifdef LNUM_COMPLEX
++# define nvalue_complex_fast(o) check_exp( ttype(o)==LUA_TNUMBER, (o)->value.n )
++# define nvalue_fast(o) ( _LF(creal) ( nvalue_complex_fast(o) ) )
++# define nvalue_img_fast(o) ( _LF(cimag) ( nvalue_complex_fast(o) ) )
++# define nvalue_complex(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? (o)->value.i : (o)->value.n )
++# define nvalue_img(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? 0 : _LF(cimag)( (o)->value.n ) )
++# define nvalue(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? cast_num((o)->value.i) : _LF(creal)((o)->value.n) )
++#else
++# define nvalue(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? cast_num((o)->value.i) : (o)->value.n )
++# define nvalue_fast(o) check_exp( ttype(o)==LUA_TNUMBER, (o)->value.n )
++#endif
++#define ivalue(o) check_exp( ttype(o)==LUA_TINT, (o)->value.i )
++
+ #define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts)
+ #define tsvalue(o) (&rawtsvalue(o)->tsv)
+ #define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u)
+@@ -116,8 +147,27 @@ typedef struct lua_TValue {
+ /* Macros to set values */
+ #define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
+
+-#define setnvalue(obj,x) \
+- { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }
++/* Must not have side effects, 'x' may be expression.
++*/
++#define setivalue(obj,x) \
++ { TValue *i_o=(obj); i_o->value.i=(x); i_o->tt=LUA_TINT; }
++
++# define setnvalue(obj,x) \
++ { TValue *i_o=(obj); i_o->value.n= (x); i_o->tt=LUA_TNUMBER; }
++
++/* Note: Complex always has "inline", both are C99.
++*/
++#ifdef LNUM_COMPLEX
++ static inline void setnvalue_complex_fast( TValue *obj, lua_Complex x ) {
++ lua_assert( _LF(cimag)(x) != 0 );
++ obj->value.n= x; obj->tt= LUA_TNUMBER;
++ }
++ static inline void setnvalue_complex( TValue *obj, lua_Complex x ) {
++ if (_LF(cimag)(x) == 0) { setnvalue(obj, _LF(creal)(x)); }
++ else { obj->value.n= x; obj->tt= LUA_TNUMBER; }
++ }
++#endif
++
+
+ #define setpvalue(obj,x) \
+ { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; }
+@@ -155,9 +205,6 @@ typedef struct lua_TValue {
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \
+ checkliveness(G(L),i_o); }
+
+-
+-
+-
+ #define setobj(L,obj1,obj2) \
+ { const TValue *o2=(obj2); TValue *o1=(obj1); \
+ o1->value = o2->value; o1->tt=o2->tt; \
+@@ -185,8 +232,11 @@ typedef struct lua_TValue {
+
+ #define setttype(obj, tt) (ttype(obj) = (tt))
+
+-
+-#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
++#if LUA_TINT >= LUA_TSTRING
++# define iscollectable(o) ((ttype(o) >= LUA_TSTRING) && (ttype(o) != LUA_TINT))
++#else
++# define iscollectable(o) (ttype(o) >= LUA_TSTRING)
++#endif
+
+
+
+@@ -370,12 +420,10 @@ LUAI_FUNC int luaO_log2 (unsigned int x)
+ LUAI_FUNC int luaO_int2fb (unsigned int x);
+ LUAI_FUNC int luaO_fb2int (int x);
+ LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);
+-LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result);
+ LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
+ va_list argp);
+ LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
+ LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);
+
+-
+ #endif
+
+--- a/src/loslib.c
++++ b/src/loslib.c
+@@ -186,15 +186,30 @@ static int os_time (lua_State *L) {
+ }
+ if (t == (time_t)(-1))
+ lua_pushnil(L);
+- else
+- lua_pushnumber(L, (lua_Number)t);
++ else {
++ /* On float systems the pushed value must be an integer, NOT a number.
++ * Otherwise, accuracy is lost in the time_t->float conversion.
++ */
++#ifdef LNUM_FLOAT
++ lua_pushinteger(L, (lua_Integer) t);
++#else
++ lua_pushnumber(L, (lua_Number) t);
++#endif
++ }
+ return 1;
+ }
+
+
+ static int os_difftime (lua_State *L) {
++#ifdef LNUM_FLOAT
++ lua_Integer i= (lua_Integer)
++ difftime( (time_t)(luaL_checkinteger(L, 1)),
++ (time_t)(luaL_optinteger(L, 2, 0)));
++ lua_pushinteger(L, i);
++#else
+ lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
+ (time_t)(luaL_optnumber(L, 2, 0))));
++#endif
+ return 1;
+ }
+
+--- a/src/lparser.c
++++ b/src/lparser.c
+@@ -33,7 +33,6 @@
+
+ #define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m)
+
+-
+ /*
+ ** nodes for block list (list of active blocks)
+ */
+@@ -72,7 +71,7 @@ static void errorlimit (FuncState *fs, i
+ const char *msg = (fs->f->linedefined == 0) ?
+ luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) :
+ luaO_pushfstring(fs->L, "function at line %d has more than %d %s",
+- fs->f->linedefined, limit, what);
++ (fs->f->linedefined), limit, what);
+ luaX_lexerror(fs->ls, msg, 0);
+ }
+
+@@ -733,6 +732,18 @@ static void simpleexp (LexState *ls, exp
+ v->u.nval = ls->t.seminfo.r;
+ break;
+ }
++ case TK_INT: {
++ init_exp(v, VKINT, 0);
++ v->u.ival = ls->t.seminfo.i;
++ break;
++ }
++#ifdef LNUM_COMPLEX
++ case TK_NUMBER2: {
++ init_exp(v, VKNUM2, 0);
++ v->u.nval = ls->t.seminfo.r;
++ break;
++ }
++#endif
+ case TK_STRING: {
+ codestring(ls, v, ls->t.seminfo.ts);
+ break;
+@@ -1079,7 +1090,7 @@ static void fornum (LexState *ls, TStrin
+ if (testnext(ls, ','))
+ exp1(ls); /* optional step */
+ else { /* default step = 1 */
+- luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
++ luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_integerK(fs, 1));
+ luaK_reserveregs(fs, 1);
+ }
+ forbody(ls, base, line, 1, 1);
+--- a/src/lparser.h
++++ b/src/lparser.h
+@@ -31,7 +31,11 @@ typedef enum {
+ VRELOCABLE, /* info = instruction pc */
+ VNONRELOC, /* info = result register */
+ VCALL, /* info = instruction pc */
+- VVARARG /* info = instruction pc */
++ VVARARG, /* info = instruction pc */
++ VKINT /* ival = integer value */
++#ifdef LNUM_COMPLEX
++ ,VKNUM2 /* nval = imaginary value */
++#endif
+ } expkind;
+
+ typedef struct expdesc {
+@@ -39,6 +43,7 @@ typedef struct expdesc {
+ union {
+ struct { int info, aux; } s;
+ lua_Number nval;
++ lua_Integer ival;
+ } u;
+ int t; /* patch list of `exit when true' */
+ int f; /* patch list of `exit when false' */
+--- a/src/lstrlib.c
++++ b/src/lstrlib.c
+@@ -43,8 +43,8 @@ static ptrdiff_t posrelat (ptrdiff_t pos
+ static int str_sub (lua_State *L) {
+ size_t l;
+ const char *s = luaL_checklstring(L, 1, &l);
+- ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l);
+- ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l);
++ ptrdiff_t start = posrelat(luaL_checkint32(L, 2), l);
++ ptrdiff_t end = posrelat(luaL_optint32(L, 3, -1), l);
+ if (start < 1) start = 1;
+ if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;
+ if (start <= end)
+@@ -106,8 +106,8 @@ static int str_rep (lua_State *L) {
+ static int str_byte (lua_State *L) {
+ size_t l;
+ const char *s = luaL_checklstring(L, 1, &l);
+- ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l);
+- ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l);
++ ptrdiff_t posi = posrelat(luaL_optint32(L, 2, 1), l);
++ ptrdiff_t pose = posrelat(luaL_optint32(L, 3, posi), l);
+ int n, i;
+ if (posi <= 0) posi = 1;
+ if ((size_t)pose > l) pose = l;
+@@ -496,7 +496,7 @@ static int str_find_aux (lua_State *L, i
+ size_t l1, l2;
+ const char *s = luaL_checklstring(L, 1, &l1);
+ const char *p = luaL_checklstring(L, 2, &l2);
+- ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
++ ptrdiff_t init = posrelat(luaL_optint32(L, 3, 1), l1) - 1;
+ if (init < 0) init = 0;
+ else if ((size_t)(init) > l1) init = (ptrdiff_t)l1;
+ if (find && (lua_toboolean(L, 4) || /* explicit request? */
+@@ -690,7 +690,7 @@ static int str_gsub (lua_State *L) {
+ ** maximum size of each format specification (such as '%-099.99d')
+ ** (+10 accounts for %99.99x plus margin of error)
+ */
+-#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
++#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTEGER_FMT)-2 + 10)
+
+
+ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
+@@ -747,9 +747,9 @@ static const char *scanformat (lua_State
+ static void addintlen (char *form) {
+ size_t l = strlen(form);
+ char spec = form[l - 1];
+- strcpy(form + l - 1, LUA_INTFRMLEN);
+- form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;
+- form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0';
++ const char *tmp= LUA_INTEGER_FMT; /* "%lld" or "%ld" */
++ strcpy(form + l - 1, tmp+1);
++ form[l + sizeof(LUA_INTEGER_FMT)-4] = spec;
+ }
+
+
+@@ -777,12 +777,12 @@ static int str_format (lua_State *L) {
+ }
+ case 'd': case 'i': {
+ addintlen(form);
+- sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));
++ sprintf(buff, form, luaL_checkinteger(L, arg));
+ break;
+ }
+ case 'o': case 'u': case 'x': case 'X': {
+ addintlen(form);
+- sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
++ sprintf(buff, form, (unsigned LUA_INTEGER)luaL_checkinteger(L, arg));
+ break;
+ }
+ case 'e': case 'E': case 'f':
+--- a/src/ltable.c
++++ b/src/ltable.c
+@@ -33,6 +33,7 @@
+ #include "lobject.h"
+ #include "lstate.h"
+ #include "ltable.h"
++#include "lnum.h"
+
+
+ /*
+@@ -51,25 +52,15 @@
+
+ #define hashstr(t,str) hashpow2(t, (str)->tsv.hash)
+ #define hashboolean(t,p) hashpow2(t, p)
+-
++#define hashint(t,i) hashpow2(t,i)
+
+ /*
+ ** for some types, it is better to avoid modulus by power of 2, as
+ ** they tend to have many 2 factors.
+ */
+ #define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1))))
+-
+-
+ #define hashpointer(t,p) hashmod(t, IntPoint(p))
+
+-
+-/*
+-** number of ints inside a lua_Number
+-*/
+-#define numints cast_int(sizeof(lua_Number)/sizeof(int))
+-
+-
+-
+ #define dummynode (&dummynode_)
+
+ static const Node dummynode_ = {
+@@ -80,27 +71,46 @@ static const Node dummynode_ = {
+
+ /*
+ ** hash for lua_Numbers
++**
++** for non-complex modes, never called with 'lua_Integer' value range (s.a. 0)
+ */
+ static Node *hashnum (const Table *t, lua_Number n) {
+- unsigned int a[numints];
+- int i;
+- if (luai_numeq(n, 0)) /* avoid problems with -0 */
+- return gnode(t, 0);
+- memcpy(a, &n, sizeof(a));
+- for (i = 1; i < numints; i++) a[0] += a[i];
+- return hashmod(t, a[0]);
++ const unsigned int *p= cast(const unsigned int *,&n);
++ unsigned int sum= *p;
++ unsigned int m= sizeof(lua_Number)/sizeof(int);
++ unsigned int i;
++ /* OS X Intel has 'm'==4 and gives "Bus error" if the last integer of
++ * 'n' is read; the actual size of long double is only 80 bits = 10 bytes.
++ * Linux x86 has 'm'==3, and does not require reduction.
++ */
++#if defined(LNUM_LDOUBLE) && defined(__i386__)
++ if (m>3) m--;
++#endif
++ for (i = 1; i < m; i++) sum += p[i];
++ return hashmod(t, sum);
+ }
+
+
+-
+ /*
+ ** returns the `main' position of an element in a table (that is, the index
+ ** of its hash value)
++**
++** Floating point numbers with integer value give the hash position of the
++** integer (so they use the same table position).
+ */
+ static Node *mainposition (const Table *t, const TValue *key) {
++ lua_Integer i;
+ switch (ttype(key)) {
+ case LUA_TNUMBER:
+- return hashnum(t, nvalue(key));
++ if (tt_integer_valued(key,&i))
++ return hashint(t, i);
++#ifdef LNUM_COMPLEX
++ if (nvalue_img_fast(key)!=0 && luai_numeq(nvalue_fast(key),0))
++ return gnode(t, 0); /* 0 and -0 to give same hash */
++#endif
++ return hashnum(t, nvalue_fast(key));
++ case LUA_TINT:
++ return hashint(t, ivalue(key));
+ case LUA_TSTRING:
+ return hashstr(t, rawtsvalue(key));
+ case LUA_TBOOLEAN:
+@@ -116,16 +126,20 @@ static Node *mainposition (const Table *
+ /*
+ ** returns the index for `key' if `key' is an appropriate key to live in
+ ** the array part of the table, -1 otherwise.
++**
++** Anything <=0 is taken as not being in the array part.
+ */
+-static int arrayindex (const TValue *key) {
+- if (ttisnumber(key)) {
+- lua_Number n = nvalue(key);
+- int k;
+- lua_number2int(k, n);
+- if (luai_numeq(cast_num(k), n))
+- return k;
++static int arrayindex (const TValue *key, int max) {
++ lua_Integer k;
++ switch( ttype(key) ) {
++ case LUA_TINT:
++ k= ivalue(key); break;
++ case LUA_TNUMBER:
++ if (tt_integer_valued(key,&k)) break;
++ default:
++ return -1; /* not to be used as array index */
+ }
+- return -1; /* `key' did not match some condition */
++ return ((k>0) && (k <= max)) ? cast_int(k) : -1;
+ }
+
+
+@@ -137,8 +151,8 @@ static int arrayindex (const TValue *key
+ static int findindex (lua_State *L, Table *t, StkId key) {
+ int i;
+ if (ttisnil(key)) return -1; /* first iteration */
+- i = arrayindex(key);
+- if (0 < i && i <= t->sizearray) /* is `key' inside array part? */
++ i = arrayindex(key, t->sizearray);
++ if (i>0) /* inside array part? */
+ return i-1; /* yes; that's the index (corrected to C) */
+ else {
+ Node *n = mainposition(t, key);
+@@ -163,7 +177,7 @@ int luaH_next (lua_State *L, Table *t, S
+ int i = findindex(L, t, key); /* find original element */
+ for (i++; i < t->sizearray; i++) { /* try first array part */
+ if (!ttisnil(&t->array[i])) { /* a non-nil value? */
+- setnvalue(key, cast_num(i+1));
++ setivalue(key, i+1);
+ setobj2s(L, key+1, &t->array[i]);
+ return 1;
+ }
+@@ -209,8 +223,8 @@ static int computesizes (int nums[], int
+
+
+ static int countint (const TValue *key, int *nums) {
+- int k = arrayindex(key);
+- if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */
++ int k = arrayindex(key,MAXASIZE);
++ if (k>0) { /* appropriate array index? */
+ nums[ceillog2(k)]++; /* count as such */
+ return 1;
+ }
+@@ -308,7 +322,7 @@ static void resize (lua_State *L, Table
+ /* re-insert elements from vanishing slice */
+ for (i=nasize; i<oldasize; i++) {
+ if (!ttisnil(&t->array[i]))
+- setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);
++ setobjt2t(L, luaH_setint(L, t, i+1), &t->array[i]);
+ }
+ /* shrink array */
+ luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
+@@ -409,7 +423,9 @@ static TValue *newkey (lua_State *L, Tab
+ othern = mainposition(t, key2tval(mp));
+ if (othern != mp) { /* is colliding node out of its main position? */
+ /* yes; move colliding node into free position */
+- while (gnext(othern) != mp) othern = gnext(othern); /* find previous */
++ while (gnext(othern) != mp) {
++ othern = gnext(othern); /* find previous */
++ }
+ gnext(othern) = n; /* redo the chain with `n' in place of `mp' */
+ *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */
+ gnext(mp) = NULL; /* now `mp' is free */
+@@ -432,17 +448,18 @@ static TValue *newkey (lua_State *L, Tab
+ /*
+ ** search function for integers
+ */
+-const TValue *luaH_getnum (Table *t, int key) {
++const TValue *luaH_getint (Table *t, lua_Integer key) {
+ /* (1 <= key && key <= t->sizearray) */
+ if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
+ return &t->array[key-1];
+ else {
+- lua_Number nk = cast_num(key);
+- Node *n = hashnum(t, nk);
++ Node *n = hashint(t, key);
+ do { /* check whether `key' is somewhere in the chain */
+- if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))
++ if (ttisint(gkey(n)) && (ivalue(gkey(n)) == key)) {
+ return gval(n); /* that's it */
+- else n = gnext(n);
++ } else {
++ n = gnext(n);
++ }
+ } while (n);
+ return luaO_nilobject;
+ }
+@@ -470,14 +487,12 @@ const TValue *luaH_get (Table *t, const
+ switch (ttype(key)) {
+ case LUA_TNIL: return luaO_nilobject;
+ case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
++ case LUA_TINT: return luaH_getint(t, ivalue(key));
+ case LUA_TNUMBER: {
+- int k;
+- lua_Number n = nvalue(key);
+- lua_number2int(k, n);
+- if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
+- return luaH_getnum(t, k); /* use specialized version */
+- /* else go through */
+- }
++ lua_Integer i;
++ if (tt_integer_valued(key,&i))
++ return luaH_getint(t,i);
++ } /* pass through */
+ default: {
+ Node *n = mainposition(t, key);
+ do { /* check whether `key' is somewhere in the chain */
+@@ -498,20 +513,25 @@ TValue *luaH_set (lua_State *L, Table *t
+ return cast(TValue *, p);
+ else {
+ if (ttisnil(key)) luaG_runerror(L, "table index is nil");
+- else if (ttisnumber(key) && luai_numisnan(nvalue(key)))
+- luaG_runerror(L, "table index is NaN");
++ else if (ttype(key)==LUA_TNUMBER) {
++ lua_Integer k;
++ if (luai_numisnan(nvalue_fast(key)))
++ luaG_runerror(L, "table index is NaN");
++ if (tt_integer_valued(key,&k))
++ return luaH_setint(L, t, k);
++ }
+ return newkey(L, t, key);
+ }
+ }
+
+
+-TValue *luaH_setnum (lua_State *L, Table *t, int key) {
+- const TValue *p = luaH_getnum(t, key);
++TValue *luaH_setint (lua_State *L, Table *t, lua_Integer key) {
++ const TValue *p = luaH_getint(t, key);
+ if (p != luaO_nilobject)
+ return cast(TValue *, p);
+ else {
+ TValue k;
+- setnvalue(&k, cast_num(key));
++ setivalue(&k, key);
+ return newkey(L, t, &k);
+ }
+ }
+@@ -533,20 +553,21 @@ static int unbound_search (Table *t, uns
+ unsigned int i = j; /* i is zero or a present index */
+ j++;
+ /* find `i' and `j' such that i is present and j is not */
+- while (!ttisnil(luaH_getnum(t, j))) {
++ while (!ttisnil(luaH_getint(t, j))) {
+ i = j;
+ j *= 2;
+ if (j > cast(unsigned int, MAX_INT)) { /* overflow? */
+ /* table was built with bad purposes: resort to linear search */
+- i = 1;
+- while (!ttisnil(luaH_getnum(t, i))) i++;
+- return i - 1;
++ for( i = 1; i<MAX_INT+1; i++ ) {
++ if (ttisnil(luaH_getint(t, i))) break;
++ }
++ return i - 1; /* up to MAX_INT */
+ }
+ }
+ /* now do a binary search between them */
+ while (j - i > 1) {
+ unsigned int m = (i+j)/2;
+- if (ttisnil(luaH_getnum(t, m))) j = m;
++ if (ttisnil(luaH_getint(t, m))) j = m;
+ else i = m;
+ }
+ return i;
+--- a/src/ltable.h
++++ b/src/ltable.h
+@@ -18,8 +18,8 @@
+ #define key2tval(n) (&(n)->i_key.tvk)
+
+
+-LUAI_FUNC const TValue *luaH_getnum (Table *t, int key);
+-LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key);
++LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
++LUAI_FUNC TValue *luaH_setint (lua_State *L, Table *t, lua_Integer key);
+ LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
+ LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);
+ LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
+--- a/src/ltm.c
++++ b/src/ltm.c
+@@ -19,7 +19,6 @@
+ #include "ltm.h"
+
+
+-
+ const char *const luaT_typenames[] = {
+ "nil", "boolean", "userdata", "number",
+ "string", "table", "function", "userdata", "thread",
+@@ -67,6 +66,9 @@ const TValue *luaT_gettmbyobj (lua_State
+ case LUA_TUSERDATA:
+ mt = uvalue(o)->metatable;
+ break;
++ case LUA_TINT:
++ mt = G(L)->mt[LUA_TNUMBER];
++ break;
+ default:
+ mt = G(L)->mt[ttype(o)];
+ }
+--- a/src/lua.c
++++ b/src/lua.c
+@@ -16,7 +16,7 @@
+
+ #include "lauxlib.h"
+ #include "lualib.h"
+-
++#include "llimits.h"
+
+
+ static lua_State *globalL = NULL;
+@@ -382,6 +382,15 @@ int main (int argc, char **argv) {
+ l_message(argv[0], "cannot create state: not enough memory");
+ return EXIT_FAILURE;
+ }
++ /* Checking 'sizeof(lua_Integer)' cannot be made in preprocessor on all compilers.
++ */
++#ifdef LNUM_INT16
++ lua_assert( sizeof(lua_Integer) == 2 );
++#elif defined(LNUM_INT32)
++ lua_assert( sizeof(lua_Integer) == 4 );
++#elif defined(LNUM_INT64)
++ lua_assert( sizeof(lua_Integer) == 8 );
++#endif
+ s.argc = argc;
+ s.argv = argv;
+ status = lua_cpcall(L, &pmain, &s);
+--- a/src/lua.h
++++ b/src/lua.h
+@@ -19,7 +19,7 @@
+ #define LUA_VERSION "Lua 5.1"
+ #define LUA_RELEASE "Lua 5.1.4"
+ #define LUA_VERSION_NUM 501
+-#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio"
++#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" " (" LUA_LNUM ")"
+ #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
+
+
+@@ -71,6 +71,16 @@ typedef void * (*lua_Alloc) (void *ud, v
+ */
+ #define LUA_TNONE (-1)
+
++/* LUA_TINT is an internal type, not visible to applications. There are three
++ * potential values where it can be tweaked to (code autoadjusts to these):
++ *
++ * -2: not 'usual' type value; good since 'LUA_TINT' is not part of the API
++ * LUA_TNUMBER+1: shifts other type values upwards, breaking binary compatibility
++ * not acceptable for 5.1, maybe 5.2 onwards?
++ * 9: greater than existing (5.1) type values.
++*/
++#define LUA_TINT (-2)
++
+ #define LUA_TNIL 0
+ #define LUA_TBOOLEAN 1
+ #define LUA_TLIGHTUSERDATA 2
+@@ -139,6 +149,8 @@ LUA_API int (lua_isuserdata)
+ LUA_API int (lua_type) (lua_State *L, int idx);
+ LUA_API const char *(lua_typename) (lua_State *L, int tp);
+
++LUA_API int (lua_isinteger) (lua_State *L, int idx);
++
+ LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2);
+ LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
+ LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2);
+@@ -244,6 +256,19 @@ LUA_API lua_Alloc (lua_getallocf) (lua_S
+ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
+
+
++/*
++* It is unnecessary to break Lua C API 'lua_tonumber()' compatibility, just
++* because the Lua number type is complex. Most C modules would use scalars
++* only. We'll introduce new 'lua_tocomplex' and 'lua_pushcomplex' for when
++* the module really wants to use them.
++*/
++#ifdef LNUM_COMPLEX
++ #include <complex.h>
++ typedef LUA_NUMBER complex lua_Complex;
++ LUA_API lua_Complex (lua_tocomplex) (lua_State *L, int idx);
++ LUA_API void (lua_pushcomplex) (lua_State *L, lua_Complex v);
++#endif
++
+
+ /*
+ ** ===============================================================
+@@ -268,7 +293,12 @@ LUA_API void lua_setallocf (lua_State *L
+ #define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
+ #define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
+ #define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
+-#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
++
++#if LUA_TINT < 0
++# define lua_isnoneornil(L, n) ( (lua_type(L,(n)) <= 0) && (lua_type(L,(n)) != LUA_TINT) )
++#else
++# define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
++#endif
+
+ #define lua_pushliteral(L, s) \
+ lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
+@@ -386,3 +416,4 @@ struct lua_Debug {
+
+
+ #endif
++
+--- a/src/luaconf.h
++++ b/src/luaconf.h
+@@ -10,7 +10,9 @@
+
+ #include <limits.h>
+ #include <stddef.h>
+-
++#ifdef lua_assert
++# include <assert.h>
++#endif
+
+ /*
+ ** ==================================================================
+@@ -136,14 +138,38 @@
+
+
+ /*
+-@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.
+-** CHANGE that if ptrdiff_t is not adequate on your machine. (On most
+-** machines, ptrdiff_t gives a good choice between int or long.)
++@@ LUAI_BITSINT defines the number of bits in an int.
++** CHANGE here if Lua cannot automatically detect the number of bits of
++** your machine. Probably you do not need to change this.
+ */
+-#define LUA_INTEGER ptrdiff_t
++/* avoid overflows in comparison */
++#if INT_MAX-20 < 32760
++#define LUAI_BITSINT 16
++#elif INT_MAX > 2147483640L
++/* int has at least 32 bits */
++#define LUAI_BITSINT 32
++#else
++#error "you must define LUA_BITSINT with number of bits in an integer"
++#endif
+
+
+ /*
++@@ LNUM_DOUBLE | LNUM_FLOAT | LNUM_LDOUBLE: Generic Lua number mode
++@@ LNUM_INT32 | LNUM_INT64: Integer type
++@@ LNUM_COMPLEX: Define for using 'a+bi' numbers
++@@
++@@ You can combine LNUM_xxx but only one of each group. I.e. '-DLNUM_FLOAT
++@@ -DLNUM_INT32 -DLNUM_COMPLEX' gives float range complex numbers, with
++@@ 32-bit scalar integer range optimized.
++**
++** These are kept in a separate configuration file mainly for ease of patching
++** (can be changed if integerated to Lua proper).
++*/
++/*#define LNUM_DOUBLE*/
++/*#define LNUM_INT32*/
++#include "lnum_config.h"
++
++/*
+ @@ LUA_API is a mark for all core API functions.
+ @@ LUALIB_API is a mark for all standard library functions.
+ ** CHANGE them if you need to define those functions in some special way.
+@@ -383,22 +409,6 @@
+
+
+ /*
+-@@ LUAI_BITSINT defines the number of bits in an int.
+-** CHANGE here if Lua cannot automatically detect the number of bits of
+-** your machine. Probably you do not need to change this.
+-*/
+-/* avoid overflows in comparison */
+-#if INT_MAX-20 < 32760
+-#define LUAI_BITSINT 16
+-#elif INT_MAX > 2147483640L
+-/* int has at least 32 bits */
+-#define LUAI_BITSINT 32
+-#else
+-#error "you must define LUA_BITSINT with number of bits in an integer"
+-#endif
+-
+-
+-/*
+ @@ LUAI_UINT32 is an unsigned integer with at least 32 bits.
+ @@ LUAI_INT32 is an signed integer with at least 32 bits.
+ @@ LUAI_UMEM is an unsigned integer big enough to count the total
+@@ -425,6 +435,15 @@
+ #define LUAI_MEM long
+ #endif
+
++/*
++@@ LUAI_BOOL carries 0 and nonzero (normally 1). It may be defined as 'char'
++** (to save memory), 'int' (for speed), 'bool' (for C++) or '_Bool' (C99)
++*/
++#ifdef __cplusplus
++# define LUAI_BOOL bool
++#else
++# define LUAI_BOOL int
++#endif
+
+ /*
+ @@ LUAI_MAXCALLS limits the number of nested calls.
+@@ -490,101 +509,6 @@
+ /* }================================================================== */
+
+
+-
+-
+-/*
+-** {==================================================================
+-@@ LUA_NUMBER is the type of numbers in Lua.
+-** CHANGE the following definitions only if you want to build Lua
+-** with a number type different from double. You may also need to
+-** change lua_number2int & lua_number2integer.
+-** ===================================================================
+-*/
+-
+-#define LUA_NUMBER_DOUBLE
+-#define LUA_NUMBER double
+-
+-/*
+-@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
+-@* over a number.
+-*/
+-#define LUAI_UACNUMBER double
+-
+-
+-/*
+-@@ LUA_NUMBER_SCAN is the format for reading numbers.
+-@@ LUA_NUMBER_FMT is the format for writing numbers.
+-@@ lua_number2str converts a number to a string.
+-@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.
+-@@ lua_str2number converts a string to a number.
+-*/
+-#define LUA_NUMBER_SCAN "%lf"
+-#define LUA_NUMBER_FMT "%.14g"
+-#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
+-#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */
+-#define lua_str2number(s,p) strtod((s), (p))
+-
+-
+-/*
+-@@ The luai_num* macros define the primitive operations over numbers.
+-*/
+-#if defined(LUA_CORE)
+-#include <math.h>
+-#define luai_numadd(a,b) ((a)+(b))
+-#define luai_numsub(a,b) ((a)-(b))
+-#define luai_nummul(a,b) ((a)*(b))
+-#define luai_numdiv(a,b) ((a)/(b))
+-#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b))
+-#define luai_numpow(a,b) (pow(a,b))
+-#define luai_numunm(a) (-(a))
+-#define luai_numeq(a,b) ((a)==(b))
+-#define luai_numlt(a,b) ((a)<(b))
+-#define luai_numle(a,b) ((a)<=(b))
+-#define luai_numisnan(a) (!luai_numeq((a), (a)))
+-#endif
+-
+-
+-/*
+-@@ lua_number2int is a macro to convert lua_Number to int.
+-@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
+-** CHANGE them if you know a faster way to convert a lua_Number to
+-** int (with any rounding method and without throwing errors) in your
+-** system. In Pentium machines, a naive typecast from double to int
+-** in C is extremely slow, so any alternative is worth trying.
+-*/
+-
+-/* On a Pentium, resort to a trick */
+-#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \
+- (defined(__i386) || defined (_M_IX86) || defined(__i386__))
+-
+-/* On a Microsoft compiler, use assembler */
+-#if defined(_MSC_VER)
+-
+-#define lua_number2int(i,d) __asm fld d __asm fistp i
+-#define lua_number2integer(i,n) lua_number2int(i, n)
+-
+-/* the next trick should work on any Pentium, but sometimes clashes
+- with a DirectX idiosyncrasy */
+-#else
+-
+-union luai_Cast { double l_d; long l_l; };
+-#define lua_number2int(i,d) \
+- { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
+-#define lua_number2integer(i,n) lua_number2int(i, n)
+-
+-#endif
+-
+-
+-/* this option always works, but may be slow */
+-#else
+-#define lua_number2int(i,d) ((i)=(int)(d))
+-#define lua_number2integer(i,d) ((i)=(lua_Integer)(d))
+-
+-#endif
+-
+-/* }================================================================== */
+-
+-
+ /*
+ @@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment.
+ ** CHANGE it if your system requires alignments larger than double. (For
+@@ -728,28 +652,6 @@ union luai_Cast { double l_d; long l_l;
+ #define luai_userstateyield(L,n) ((void)L)
+
+
+-/*
+-@@ LUA_INTFRMLEN is the length modifier for integer conversions
+-@* in 'string.format'.
+-@@ LUA_INTFRM_T is the integer type correspoding to the previous length
+-@* modifier.
+-** CHANGE them if your system supports long long or does not support long.
+-*/
+-
+-#if defined(LUA_USELONGLONG)
+-
+-#define LUA_INTFRMLEN "ll"
+-#define LUA_INTFRM_T long long
+-
+-#else
+-
+-#define LUA_INTFRMLEN "l"
+-#define LUA_INTFRM_T long
+-
+-#endif
+-
+-
+-
+ /* =================================================================== */
+
+ /*
+--- a/src/lundump.c
++++ b/src/lundump.c
+@@ -73,6 +73,13 @@ static lua_Number LoadNumber(LoadState*
+ return x;
+ }
+
++static lua_Integer LoadInteger(LoadState* S)
++{
++ lua_Integer x;
++ LoadVar(S,x);
++ return x;
++}
++
+ static TString* LoadString(LoadState* S)
+ {
+ size_t size;
+@@ -119,6 +126,9 @@ static void LoadConstants(LoadState* S,
+ case LUA_TNUMBER:
+ setnvalue(o,LoadNumber(S));
+ break;
++ case LUA_TINT: /* Integer type saved in bytecode (see lcode.c) */
++ setivalue(o,LoadInteger(S));
++ break;
+ case LUA_TSTRING:
+ setsvalue2n(S->L,o,LoadString(S));
+ break;
+@@ -223,5 +233,22 @@ void luaU_header (char* h)
+ *h++=(char)sizeof(size_t);
+ *h++=(char)sizeof(Instruction);
+ *h++=(char)sizeof(lua_Number);
+- *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */
++
++ /*
++ * Last byte of header (0/1 in unpatched Lua 5.1.3):
++ *
++ * 0: lua_Number is float or double, lua_Integer not used. (nonpatched only)
++ * 1: lua_Number is integer (nonpatched only)
++ *
++ * +2: LNUM_INT16: sizeof(lua_Integer)
++ * +4: LNUM_INT32: sizeof(lua_Integer)
++ * +8: LNUM_INT64: sizeof(lua_Integer)
++ *
++ * +0x80: LNUM_COMPLEX
++ */
++ *h++ = (char)(sizeof(lua_Integer)
++#ifdef LNUM_COMPLEX
++ | 0x80
++#endif
++ );
+ }
+--- a/src/lvm.c
++++ b/src/lvm.c
+@@ -25,22 +25,35 @@
+ #include "ltable.h"
+ #include "ltm.h"
+ #include "lvm.h"
+-
+-
++#include "llex.h"
++#include "lnum.h"
+
+ /* limit for table tag-method chains (to avoid loops) */
+ #define MAXTAGLOOP 100
+
+
+-const TValue *luaV_tonumber (const TValue *obj, TValue *n) {
+- lua_Number num;
++/*
++ * If 'obj' is a string, it is tried to be interpreted as a number.
++ */
++const TValue *luaV_tonumber ( const TValue *obj, TValue *n) {
++ lua_Number d;
++ lua_Integer i;
++
+ if (ttisnumber(obj)) return obj;
+- if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
+- setnvalue(n, num);
+- return n;
+- }
+- else
+- return NULL;
++
++ if (ttisstring(obj)) {
++ switch( luaO_str2d( svalue(obj), &d, &i ) ) {
++ case TK_INT:
++ setivalue(n,i); return n;
++ case TK_NUMBER:
++ setnvalue(n,d); return n;
++#ifdef LNUM_COMPLEX
++ case TK_NUMBER2: /* "N.NNNi", != 0 */
++ setnvalue_complex_fast(n, d*I); return n;
++#endif
++ }
++ }
++ return NULL;
+ }
+
+
+@@ -49,8 +62,7 @@ int luaV_tostring (lua_State *L, StkId o
+ return 0;
+ else {
+ char s[LUAI_MAXNUMBER2STR];
+- lua_Number n = nvalue(obj);
+- lua_number2str(s, n);
++ luaO_num2buf(s,obj);
+ setsvalue2s(L, obj, luaS_new(L, s));
+ return 1;
+ }
+@@ -218,59 +230,127 @@ static int l_strcmp (const TString *ls,
+ }
+
+
++#ifdef LNUM_COMPLEX
++void error_complex( lua_State *L, const TValue *l, const TValue *r )
++{
++ char buf1[ LUAI_MAXNUMBER2STR ];
++ char buf2[ LUAI_MAXNUMBER2STR ];
++ luaO_num2buf( buf1, l );
++ luaO_num2buf( buf2, r );
++ luaG_runerror( L, "unable to compare: %s with %s", buf1, buf2 );
++ /* no return */
++}
++#endif
++
++
+ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
+ int res;
+- if (ttype(l) != ttype(r))
++ int tl,tr;
++ lua_Integer tmp;
++
++ if (!ttype_ext_same(l,r))
+ return luaG_ordererror(L, l, r);
+- else if (ttisnumber(l))
+- return luai_numlt(nvalue(l), nvalue(r));
+- else if (ttisstring(l))
+- return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
+- else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
++#ifdef LNUM_COMPLEX
++ if ( (nvalue_img(l)!=0) || (nvalue_img(r)!=0) )
++ error_complex( L, l, r );
++#endif
++ tl= ttype(l); tr= ttype(r);
++ if (tl==tr) { /* clear arithmetics */
++ switch(tl) {
++ case LUA_TINT: return ivalue(l) < ivalue(r);
++ case LUA_TNUMBER: return luai_numlt(nvalue_fast(l), nvalue_fast(r));
++ case LUA_TSTRING: return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
++ }
++ } else if (tl==LUA_TINT) { /* l:int, r:num */
++ /* Avoid accuracy losing casts: if 'r' is integer by value, do comparisons
++ * in integer realm. Only otherwise cast 'l' to FP (which might change its
++ * value).
++ */
++ if (tt_integer_valued(r,&tmp))
++ return ivalue(l) < tmp;
++ else
++ return luai_numlt( cast_num(ivalue(l)), nvalue_fast(r) );
++
++ } else if (tl==LUA_TNUMBER) { /* l:num, r:int */
++ if (tt_integer_valued(l,&tmp))
++ return tmp < ivalue(r);
++ else
++ return luai_numlt( nvalue_fast(l), cast_num(ivalue(r)) );
++
++ } else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
+ return res;
++
+ return luaG_ordererror(L, l, r);
+ }
+
+
+ static int lessequal (lua_State *L, const TValue *l, const TValue *r) {
+ int res;
+- if (ttype(l) != ttype(r))
++ int tl, tr;
++ lua_Integer tmp;
++
++ if (!ttype_ext_same(l,r))
+ return luaG_ordererror(L, l, r);
+- else if (ttisnumber(l))
+- return luai_numle(nvalue(l), nvalue(r));
+- else if (ttisstring(l))
+- return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
+- else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */
++#ifdef LNUM_COMPLEX
++ if ( (nvalue_img(l)!=0) || (nvalue_img(r)!=0) )
++ error_complex( L, l, r );
++#endif
++ tl= ttype(l); tr= ttype(r);
++ if (tl==tr) { /* clear arithmetics */
++ switch(tl) {
++ case LUA_TINT: return ivalue(l) <= ivalue(r);
++ case LUA_TNUMBER: return luai_numle(nvalue_fast(l), nvalue_fast(r));
++ case LUA_TSTRING: return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
++ }
++ }
++ if (tl==LUA_TINT) { /* l:int, r:num */
++ if (tt_integer_valued(r,&tmp))
++ return ivalue(l) <= tmp;
++ else
++ return luai_numle( cast_num(ivalue(l)), nvalue_fast(r) );
++
++ } else if (tl==LUA_TNUMBER) { /* l:num, r:int */
++ if (tt_integer_valued(l,&tmp))
++ return tmp <= ivalue(r);
++ else
++ return luai_numle( nvalue_fast(l), cast_num(ivalue(r)) );
++
++ } else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */
+ return res;
+ else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */
+ return !res;
++
+ return luaG_ordererror(L, l, r);
+ }
+
+
+-int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {
++/* Note: 'luaV_equalval()' and 'luaO_rawequalObj()' have largely overlapping
++ * implementation. LUA_TNIL..LUA_TLIGHTUSERDATA cases could be handled
++ * simply by the 'default' case here.
++ */
++int luaV_equalval (lua_State *L, const TValue *l, const TValue *r) {
+ const TValue *tm;
+- lua_assert(ttype(t1) == ttype(t2));
+- switch (ttype(t1)) {
++ lua_assert(ttype_ext_same(l,r));
++ switch (ttype(l)) {
+ case LUA_TNIL: return 1;
+- case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
+- case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
+- case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
++ case LUA_TINT:
++ case LUA_TNUMBER: return luaO_rawequalObj(l,r);
++ case LUA_TBOOLEAN: return bvalue(l) == bvalue(r); /* true must be 1 !! */
++ case LUA_TLIGHTUSERDATA: return pvalue(l) == pvalue(r);
+ case LUA_TUSERDATA: {
+- if (uvalue(t1) == uvalue(t2)) return 1;
+- tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable,
+- TM_EQ);
++ if (uvalue(l) == uvalue(r)) return 1;
++ tm = get_compTM(L, uvalue(l)->metatable, uvalue(r)->metatable, TM_EQ);
+ break; /* will try TM */
+ }
+ case LUA_TTABLE: {
+- if (hvalue(t1) == hvalue(t2)) return 1;
+- tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
++ if (hvalue(l) == hvalue(r)) return 1;
++ tm = get_compTM(L, hvalue(l)->metatable, hvalue(r)->metatable, TM_EQ);
+ break; /* will try TM */
+ }
+- default: return gcvalue(t1) == gcvalue(t2);
++ default: return gcvalue(l) == gcvalue(r);
+ }
+ if (tm == NULL) return 0; /* no TM? */
+- callTMres(L, L->top, tm, t1, t2); /* call TM */
++ callTMres(L, L->top, tm, l, r); /* call TM */
+ return !l_isfalse(L->top);
+ }
+
+@@ -310,30 +390,6 @@ void luaV_concat (lua_State *L, int tota
+ }
+
+
+-static void Arith (lua_State *L, StkId ra, const TValue *rb,
+- const TValue *rc, TMS op) {
+- TValue tempb, tempc;
+- const TValue *b, *c;
+- if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
+- (c = luaV_tonumber(rc, &tempc)) != NULL) {
+- lua_Number nb = nvalue(b), nc = nvalue(c);
+- switch (op) {
+- case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break;
+- case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;
+- case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;
+- case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break;
+- case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break;
+- case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;
+- case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;
+- default: lua_assert(0); break;
+- }
+- }
+- else if (!call_binTM(L, rb, rc, ra, op))
+- luaG_aritherror(L, rb, rc);
+-}
+-
+-
+-
+ /*
+ ** some macros for common tasks in `luaV_execute'
+ */
+@@ -357,17 +413,154 @@ static void Arith (lua_State *L, StkId r
+ #define Protect(x) { L->savedpc = pc; {x;}; base = L->base; }
+
+
+-#define arith_op(op,tm) { \
+- TValue *rb = RKB(i); \
+- TValue *rc = RKC(i); \
+- if (ttisnumber(rb) && ttisnumber(rc)) { \
+- lua_Number nb = nvalue(rb), nc = nvalue(rc); \
+- setnvalue(ra, op(nb, nc)); \
+- } \
+- else \
+- Protect(Arith(L, ra, rb, rc, tm)); \
++/* Note: if called for unary operations, 'rc'=='rb'.
++ */
++static void Arith (lua_State *L, StkId ra, const TValue *rb,
++ const TValue *rc, TMS op) {
++ TValue tempb, tempc;
++ const TValue *b, *c;
++ lua_Number nb,nc;
++
++ if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
++ (c = luaV_tonumber(rc, &tempc)) != NULL) {
++
++ /* Keep integer arithmetics in the integer realm, if possible.
++ */
++ if (ttisint(b) && ttisint(c)) {
++ lua_Integer ib = ivalue(b), ic = ivalue(c);
++ lua_Integer *ri = &ra->value.i;
++ ra->tt= LUA_TINT; /* part of 'setivalue(ra)' */
++ switch (op) {
++ case TM_ADD: if (try_addint( ri, ib, ic)) return; break;
++ case TM_SUB: if (try_subint( ri, ib, ic)) return; break;
++ case TM_MUL: if (try_mulint( ri, ib, ic)) return; break;
++ case TM_DIV: if (try_divint( ri, ib, ic)) return; break;
++ case TM_MOD: if (try_modint( ri, ib, ic)) return; break;
++ case TM_POW: if (try_powint( ri, ib, ic)) return; break;
++ case TM_UNM: if (try_unmint( ri, ib)) return; break;
++ default: lua_assert(0);
++ }
++ }
++ /* Fallback to floating point, when leaving range. */
++
++#ifdef LNUM_COMPLEX
++ if ((nvalue_img(b)!=0) || (nvalue_img(c)!=0)) {
++ lua_Complex r;
++ if (op==TM_UNM) {
++ r= -nvalue_complex_fast(b); /* never an integer (or scalar) */
++ setnvalue_complex_fast( ra, r );
++ } else {
++ lua_Complex bb= nvalue_complex(b), cc= nvalue_complex(c);
++ switch (op) {
++ case TM_ADD: r= bb + cc; break;
++ case TM_SUB: r= bb - cc; break;
++ case TM_MUL: r= bb * cc; break;
++ case TM_DIV: r= bb / cc; break;
++ case TM_MOD:
++ luaG_runerror(L, "attempt to use %% on complex numbers"); /* no return */
++ case TM_POW: r= luai_vectpow( bb, cc ); break;
++ default: lua_assert(0); r=0;
++ }
++ setnvalue_complex( ra, r );
+ }
++ return;
++ }
++#endif
++ nb = nvalue(b); nc = nvalue(c);
++ switch (op) {
++ case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); return;
++ case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); return;
++ case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); return;
++ case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); return;
++ case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); return;
++ case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); return;
++ case TM_UNM: setnvalue(ra, luai_numunm(nb)); return;
++ default: lua_assert(0);
++ }
++ }
++
++ /* Either operand not a number */
++ if (!call_binTM(L, rb, rc, ra, op))
++ luaG_aritherror(L, rb, rc);
++}
+
++/* Helper macro to sort arithmetic operations into four categories:
++ * TK_INT: integer - integer operands
++ * TK_NUMBER: number - number (non complex, either may be integer)
++ * TK_NUMBER2: complex numbers (at least the other)
++ * 0: non-numeric (at least the other)
++*/
++#ifdef LNUM_COMPLEX
++static inline int arith_mode( const TValue *rb, const TValue *rc ) {
++ if (ttisint(rb) && ttisint(rc)) return TK_INT;
++ if (ttiscomplex(rb) || ttiscomplex(rc)) return TK_NUMBER2;
++ if (ttisnumber(rb) && ttisnumber(rc)) return TK_NUMBER;
++ return 0;
++}
++#else
++# define arith_mode(rb,rc) \
++ ( (ttisint(rb) && ttisint(rc)) ? TK_INT : \
++ (ttisnumber(rb) && ttisnumber(rc)) ? TK_NUMBER : 0 )
++#endif
++
++/* arith_op macro for two operators:
++ * automatically chooses, which function (number, integer, complex) to use
++ */
++#define ARITH_OP2_START( op_num, op_int ) \
++ int failed= 0; \
++ switch( arith_mode(rb,rc) ) { \
++ case TK_INT: \
++ if (op_int ( &(ra)->value.i, ivalue(rb), ivalue(rc) )) \
++ { ra->tt= LUA_TINT; break; } /* else flow through */ \
++ case TK_NUMBER: \
++ setnvalue(ra, op_num ( nvalue(rb), nvalue(rc) )); break;
++
++#define ARITH_OP2_END \
++ default: \
++ failed= 1; break; \
++ } if (!failed) continue;
++
++#define arith_op_continue_scalar( op_num, op_int ) \
++ ARITH_OP2_START( op_num, op_int ) \
++ ARITH_OP2_END
++
++#ifdef LNUM_COMPLEX
++# define arith_op_continue( op_num, op_int, op_complex ) \
++ ARITH_OP2_START( op_num, op_int ) \
++ case TK_NUMBER2: \
++ setnvalue_complex( ra, op_complex ( nvalue_complex(rb), nvalue_complex(rc) ) ); break; \
++ ARITH_OP2_END
++#else
++# define arith_op_continue(op_num,op_int,_) arith_op_continue_scalar(op_num,op_int)
++#endif
++
++/* arith_op macro for one operator:
++ */
++#define ARITH_OP1_START( op_num, op_int ) \
++ int failed= 0; \
++ switch( arith_mode(rb,rb) ) { \
++ case TK_INT: \
++ if (op_int ( &(ra)->value.i, ivalue(rb) )) \
++ { ra->tt= LUA_TINT; break; } /* else flow through */ \
++ case TK_NUMBER: \
++ setnvalue(ra, op_num (nvalue(rb))); break; \
++
++#define ARITH_OP1_END \
++ default: \
++ failed= 1; break; \
++ } if (!failed) continue;
++
++#ifdef LNUM_COMPLEX
++# define arith_op1_continue( op_num, op_int, op_complex ) \
++ ARITH_OP1_START( op_num, op_int ) \
++ case TK_NUMBER2: \
++ setnvalue_complex( ra, op_complex ( nvalue_complex_fast(rb) )); break; \
++ ARITH_OP1_END
++#else
++# define arith_op1_continue( op_num, op_int, _ ) \
++ ARITH_OP1_START( op_num, op_int ) \
++ ARITH_OP1_END
++#endif
+
+
+ void luaV_execute (lua_State *L, int nexeccalls) {
+@@ -468,38 +661,45 @@ void luaV_execute (lua_State *L, int nex
+ continue;
+ }
+ case OP_ADD: {
+- arith_op(luai_numadd, TM_ADD);
++ TValue *rb = RKB(i), *rc= RKC(i);
++ arith_op_continue( luai_numadd, try_addint, luai_vectadd );
++ Protect(Arith(L, ra, rb, rc, TM_ADD)); \
+ continue;
+ }
+ case OP_SUB: {
+- arith_op(luai_numsub, TM_SUB);
++ TValue *rb = RKB(i), *rc= RKC(i);
++ arith_op_continue( luai_numsub, try_subint, luai_vectsub );
++ Protect(Arith(L, ra, rb, rc, TM_SUB));
+ continue;
+ }
+ case OP_MUL: {
+- arith_op(luai_nummul, TM_MUL);
++ TValue *rb = RKB(i), *rc= RKC(i);
++ arith_op_continue(luai_nummul, try_mulint, luai_vectmul);
++ Protect(Arith(L, ra, rb, rc, TM_MUL));
+ continue;
+ }
+ case OP_DIV: {
+- arith_op(luai_numdiv, TM_DIV);
++ TValue *rb = RKB(i), *rc= RKC(i);
++ arith_op_continue(luai_numdiv, try_divint, luai_vectdiv);
++ Protect(Arith(L, ra, rb, rc, TM_DIV));
+ continue;
+ }
+ case OP_MOD: {
+- arith_op(luai_nummod, TM_MOD);
++ TValue *rb = RKB(i), *rc= RKC(i);
++ arith_op_continue_scalar(luai_nummod, try_modint); /* scalars only */
++ Protect(Arith(L, ra, rb, rc, TM_MOD));
+ continue;
+ }
+ case OP_POW: {
+- arith_op(luai_numpow, TM_POW);
++ TValue *rb = RKB(i), *rc= RKC(i);
++ arith_op_continue(luai_numpow, try_powint, luai_vectpow);
++ Protect(Arith(L, ra, rb, rc, TM_POW));
+ continue;
+ }
+ case OP_UNM: {
+ TValue *rb = RB(i);
+- if (ttisnumber(rb)) {
+- lua_Number nb = nvalue(rb);
+- setnvalue(ra, luai_numunm(nb));
+- }
+- else {
+- Protect(Arith(L, ra, rb, rb, TM_UNM));
+- }
++ arith_op1_continue(luai_numunm, try_unmint, luai_vectunm);
++ Protect(Arith(L, ra, rb, rb, TM_UNM));
+ continue;
+ }
+ case OP_NOT: {
+@@ -511,11 +711,11 @@ void luaV_execute (lua_State *L, int nex
+ const TValue *rb = RB(i);
+ switch (ttype(rb)) {
+ case LUA_TTABLE: {
+- setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
++ setivalue(ra, luaH_getn(hvalue(rb)));
+ break;
+ }
+ case LUA_TSTRING: {
+- setnvalue(ra, cast_num(tsvalue(rb)->len));
++ setivalue(ra, tsvalue(rb)->len);
+ break;
+ }
+ default: { /* try metamethod */
+@@ -648,14 +848,30 @@ void luaV_execute (lua_State *L, int nex
+ }
+ }
+ case OP_FORLOOP: {
+- lua_Number step = nvalue(ra+2);
+- lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */
+- lua_Number limit = nvalue(ra+1);
+- if (luai_numlt(0, step) ? luai_numle(idx, limit)
+- : luai_numle(limit, idx)) {
+- dojump(L, pc, GETARG_sBx(i)); /* jump back */
+- setnvalue(ra, idx); /* update internal index... */
+- setnvalue(ra+3, idx); /* ...and external index */
++ /* If start,step and limit are all integers, we don't need to check
++ * against overflow in the looping.
++ */
++ if (ttisint(ra) && ttisint(ra+1) && ttisint(ra+2)) {
++ lua_Integer step = ivalue(ra+2);
++ lua_Integer idx = ivalue(ra) + step; /* increment index */
++ lua_Integer limit = ivalue(ra+1);
++ if (step > 0 ? (idx <= limit) : (limit <= idx)) {
++ dojump(L, pc, GETARG_sBx(i)); /* jump back */
++ setivalue(ra, idx); /* update internal index... */
++ setivalue(ra+3, idx); /* ...and external index */
++ }
++ } else {
++ /* non-integer looping (don't use 'nvalue_fast', some may be integer!)
++ */
++ lua_Number step = nvalue(ra+2);
++ lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */
++ lua_Number limit = nvalue(ra+1);
++ if (luai_numlt(0, step) ? luai_numle(idx, limit)
++ : luai_numle(limit, idx)) {
++ dojump(L, pc, GETARG_sBx(i)); /* jump back */
++ setnvalue(ra, idx); /* update internal index... */
++ setnvalue(ra+3, idx); /* ...and external index */
++ }
+ }
+ continue;
+ }
+@@ -664,13 +880,21 @@ void luaV_execute (lua_State *L, int nex
+ const TValue *plimit = ra+1;
+ const TValue *pstep = ra+2;
+ L->savedpc = pc; /* next steps may throw errors */
++ /* Using same location for tonumber's both arguments, effectively does
++ * in-place modification (string->number). */
+ if (!tonumber(init, ra))
+ luaG_runerror(L, LUA_QL("for") " initial value must be a number");
+ else if (!tonumber(plimit, ra+1))
+ luaG_runerror(L, LUA_QL("for") " limit must be a number");
+ else if (!tonumber(pstep, ra+2))
+ luaG_runerror(L, LUA_QL("for") " step must be a number");
+- setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));
++ /* Step back one value (keep within integers if we can)
++ */
++ if (!( ttisint(ra) && ttisint(pstep) &&
++ try_subint( &ra->value.i, ivalue(ra), ivalue(pstep) ) )) {
++ /* don't use 'nvalue_fast()', values may be integer */
++ setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));
++ }
+ dojump(L, pc, GETARG_sBx(i));
+ continue;
+ }
+@@ -707,7 +931,7 @@ void luaV_execute (lua_State *L, int nex
+ luaH_resizearray(L, h, last); /* pre-alloc it at once */
+ for (; n > 0; n--) {
+ TValue *val = ra+n;
+- setobj2t(L, luaH_setnum(L, h, last--), val);
++ setobj2t(L, luaH_setint(L, h, last--), val);
+ luaC_barriert(L, h, val);
+ }
+ continue;
+--- a/src/lvm.h
++++ b/src/lvm.h
+@@ -15,11 +15,9 @@
+
+ #define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o)))
+
+-#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \
+- (((o) = luaV_tonumber(o,n)) != NULL))
++#define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL))
+
+-#define equalobj(L,o1,o2) \
+- (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
++#define equalobj(L,o1,o2) (ttype_ext_same(o1,o2) && luaV_equalval(L, o1, o2))
+
+
+ LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
+--- a/src/print.c
++++ b/src/print.c
+@@ -14,6 +14,7 @@
+ #include "lobject.h"
+ #include "lopcodes.h"
+ #include "lundump.h"
++#include "lnum.h"
+
+ #define PrintFunction luaU_print
+
+@@ -59,8 +60,16 @@ static void PrintConstant(const Proto* f
+ case LUA_TBOOLEAN:
+ printf(bvalue(o) ? "true" : "false");
+ break;
++ case LUA_TINT:
++ printf(LUA_INTEGER_FMT,ivalue(o));
++ break;
+ case LUA_TNUMBER:
+- printf(LUA_NUMBER_FMT,nvalue(o));
++#ifdef LNUM_COMPLEX
++ // TBD: Do we get complex values here?
++ { lua_Number b= nvalue_img_fast(o);
++ printf( LUA_NUMBER_FMT "%s" LUA_NUMBER_FMT "i", nvalue_fast(o), b>=0 ? "+":"", b ); }
++#endif
++ printf(LUA_NUMBER_FMT,nvalue_fast(o));
+ break;
+ case LUA_TSTRING:
+ PrintString(rawtsvalue(o));
diff --git a/package/lua/patches/011-lnum-use-double.patch b/package/lua/patches/011-lnum-use-double.patch
new file mode 100644
index 000000000..14c720bf1
--- /dev/null
+++ b/package/lua/patches/011-lnum-use-double.patch
@@ -0,0 +1,11 @@
+--- a/src/lnum_config.h
++++ b/src/lnum_config.h
+@@ -11,7 +11,7 @@
+ ** Default number modes
+ */
+ #if (!defined LNUM_DOUBLE) && (!defined LNUM_FLOAT) && (!defined LNUM_LDOUBLE)
+-# define LNUM_FLOAT
++# define LNUM_DOUBLE
+ #endif
+ #if (!defined LNUM_INT16) && (!defined LNUM_INT32) && (!defined LNUM_INT64)
+ # define LNUM_INT32
diff --git a/package/lua/patches/015-lnum-ppc-compat.patch b/package/lua/patches/015-lnum-ppc-compat.patch
new file mode 100644
index 000000000..2ea59f176
--- /dev/null
+++ b/package/lua/patches/015-lnum-ppc-compat.patch
@@ -0,0 +1,11 @@
+--- a/src/lua.h
++++ b/src/lua.h
+@@ -79,7 +79,7 @@ typedef void * (*lua_Alloc) (void *ud, v
+ * not acceptable for 5.1, maybe 5.2 onwards?
+ * 9: greater than existing (5.1) type values.
+ */
+-#define LUA_TINT (-2)
++#define LUA_TINT 9
+
+ #define LUA_TNIL 0
+ #define LUA_TBOOLEAN 1
diff --git a/package/lua/patches/020-shared_liblua.patch b/package/lua/patches/020-shared_liblua.patch
new file mode 100644
index 000000000..18078ccc1
--- /dev/null
+++ b/package/lua/patches/020-shared_liblua.patch
@@ -0,0 +1,140 @@
+--- a/Makefile
++++ b/Makefile
+@@ -42,8 +42,8 @@ PLATS= aix ansi bsd freebsd generic linu
+
+ # What to install.
+ TO_BIN= lua luac
+-TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp
+-TO_LIB= liblua.a
++TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp lnum_config.h
++TO_LIB= liblua.a liblua.so.$R
+ TO_MAN= lua.1 luac.1
+
+ # Lua version and release.
+@@ -63,6 +63,7 @@ install: dummy
+ cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN)
+ cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC)
+ cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB)
++ ln -s liblua.so.$R $(INSTALL_LIB)/liblua.so
+ cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN)
+
+ ranlib:
+--- a/src/ldo.h
++++ b/src/ldo.h
+@@ -46,7 +46,7 @@ LUAI_FUNC int luaD_pcall (lua_State *L,
+ LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult);
+ LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize);
+ LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
+-LUAI_FUNC void luaD_growstack (lua_State *L, int n);
++LUA_API void luaD_growstack (lua_State *L, int n);
+
+ LUAI_FUNC void luaD_throw (lua_State *L, int errcode);
+ LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
+--- a/src/lfunc.h
++++ b/src/lfunc.h
+@@ -18,7 +18,7 @@
+ cast(int, sizeof(TValue *)*((n)-1)))
+
+
+-LUAI_FUNC Proto *luaF_newproto (lua_State *L);
++LUA_API Proto *luaF_newproto (lua_State *L);
+ LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);
+ LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);
+ LUAI_FUNC UpVal *luaF_newupval (lua_State *L);
+--- a/src/lmem.h
++++ b/src/lmem.h
+@@ -38,9 +38,9 @@
+ ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t))))
+
+
+-LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
++LUA_API void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
+ size_t size);
+-LUAI_FUNC void *luaM_toobig (lua_State *L);
++LUA_API void *luaM_toobig (lua_State *L);
+ LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size,
+ size_t size_elem, int limit,
+ const char *errormsg);
+--- a/src/lstring.h
++++ b/src/lstring.h
+@@ -25,7 +25,7 @@
+
+ LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
+ LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
+-LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
++LUA_API TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
+
+
+ #endif
+--- a/src/lundump.h
++++ b/src/lundump.h
+@@ -17,7 +17,7 @@ LUAI_FUNC Proto* luaU_undump (lua_State*
+ LUAI_FUNC void luaU_header (char* h);
+
+ /* dump one chunk; from ldump.c */
+-LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);
++LUA_API int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);
+
+ #ifdef luac_c
+ /* print one chunk; from print.c */
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -23,6 +23,7 @@ MYLIBS=
+ PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris
+
+ LUA_A= liblua.a
++LUA_SO= liblua.so
+ CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
+ lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \
+ lundump.o lvm.o lzio.o lnum.o
+@@ -33,11 +34,12 @@ LUA_T= lua
+ LUA_O= lua.o
+
+ LUAC_T= luac
+-LUAC_O= luac.o print.o
++LUAC_O= luac.o print.o lopcodes.o
+
+ ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O)
+-ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)
++ALL_T= $(LUA_A) $(LUA_SO) $(LUA_T) $(LUAC_T)
+ ALL_A= $(LUA_A)
++ALL_SO= $(LUA_SO)
+
+ default: $(PLAT)
+
+@@ -47,14 +49,23 @@ o: $(ALL_O)
+
+ a: $(ALL_A)
+
++so: $(ALL_SO)
++
+ $(LUA_A): $(CORE_O) $(LIB_O)
+ $(AR) $@ $?
+ $(RANLIB) $@
+
+-$(LUA_T): $(LUA_O) $(LUA_A)
+- $(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
++$(LUA_SO): $(CORE_O) $(LIB_O)
++ $(CC) -o $@.$(PKG_VERSION) -shared -Wl,-soname="$@.$(PKG_VERSION)" $?
++ ln -fs $@.$(PKG_VERSION) $@
++
++$(LUA_T): $(LUA_O) $(LUA_SO)
++ $(CC) -o $@ -L. -llua $(MYLDFLAGS) $(LUA_O) $(LIBS)
++
++$(LUAC_T): $(LUAC_O) $(LUA_SO)
++ $(CC) -o $@ -L. -llua $(MYLDFLAGS) $(LUAC_O) $(LIBS)
+
+-$(LUAC_T): $(LUAC_O) $(LUA_A)
++$(LUAC_T)-host: $(LUAC_O) $(LUA_A)
+ $(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)
+
+ clean:
+@@ -96,7 +107,7 @@ generic:
+ $(MAKE) all MYCFLAGS=
+
+ linux:
+- $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
++ $(MAKE) all MYCFLAGS+=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
+
+ macosx:
+ $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline"
diff --git a/package/lua/patches/030-archindependent-bytecode.patch b/package/lua/patches/030-archindependent-bytecode.patch
new file mode 100644
index 000000000..8dfef85d0
--- /dev/null
+++ b/package/lua/patches/030-archindependent-bytecode.patch
@@ -0,0 +1,111 @@
+--- a/src/ldump.c
++++ b/src/ldump.c
+@@ -67,12 +67,12 @@ static void DumpString(const TString* s,
+ {
+ if (s==NULL || getstr(s)==NULL)
+ {
+- size_t size=0;
++ unsigned int size=0;
+ DumpVar(size,D);
+ }
+ else
+ {
+- size_t size=s->tsv.len+1; /* include trailing '\0' */
++ unsigned int size=s->tsv.len+1; /* include trailing '\0' */
+ DumpVar(size,D);
+ DumpBlock(getstr(s),size,D);
+ }
+--- a/src/lundump.c
++++ b/src/lundump.c
+@@ -25,6 +25,7 @@ typedef struct {
+ ZIO* Z;
+ Mbuffer* b;
+ const char* name;
++ int swap;
+ } LoadState;
+
+ #ifdef LUAC_TRUST_BINARIES
+@@ -40,7 +41,6 @@ static void error(LoadState* S, const ch
+ }
+ #endif
+
+-#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size))
+ #define LoadByte(S) (lu_byte)LoadChar(S)
+ #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
+ #define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
+@@ -51,6 +51,49 @@ static void LoadBlock(LoadState* S, void
+ IF (r!=0, "unexpected end");
+ }
+
++static void LoadMem (LoadState* S, void* b, int n, size_t size)
++{
++ LoadBlock(S,b,n*size);
++ if (S->swap)
++ {
++ char* p=(char*) b;
++ char c;
++ switch (size)
++ {
++ case 1:
++ break;
++ case 2:
++ while (n--)
++ {
++ c=p[0]; p[0]=p[1]; p[1]=c;
++ p+=2;
++ }
++ break;
++ case 4:
++ while (n--)
++ {
++ c=p[0]; p[0]=p[3]; p[3]=c;
++ c=p[1]; p[1]=p[2]; p[2]=c;
++ p+=4;
++ }
++ break;
++ case 8:
++ while (n--)
++ {
++ c=p[0]; p[0]=p[7]; p[7]=c;
++ c=p[1]; p[1]=p[6]; p[6]=c;
++ c=p[2]; p[2]=p[5]; p[5]=c;
++ c=p[3]; p[3]=p[4]; p[4]=c;
++ p+=8;
++ }
++ break;
++ default:
++ IF(1, "bad size");
++ break;
++ }
++ }
++}
++
+ static int LoadChar(LoadState* S)
+ {
+ char x;
+@@ -82,7 +125,7 @@ static lua_Integer LoadInteger(LoadState
+
+ static TString* LoadString(LoadState* S)
+ {
+- size_t size;
++ unsigned int size;
+ LoadVar(S,size);
+ if (size==0)
+ return NULL;
+@@ -196,6 +239,7 @@ static void LoadHeader(LoadState* S)
+ char s[LUAC_HEADERSIZE];
+ luaU_header(h);
+ LoadBlock(S,s,LUAC_HEADERSIZE);
++ S->swap=(s[6]!=h[6]); s[6]=h[6];
+ IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
+ }
+
+@@ -230,7 +274,7 @@ void luaU_header (char* h)
+ *h++=(char)LUAC_FORMAT;
+ *h++=(char)*(char*)&x; /* endianness */
+ *h++=(char)sizeof(int);
+- *h++=(char)sizeof(size_t);
++ *h++=(char)sizeof(unsigned int);
+ *h++=(char)sizeof(Instruction);
+ *h++=(char)sizeof(lua_Number);
+
diff --git a/package/lua/patches/100-no_readline.patch b/package/lua/patches/100-no_readline.patch
new file mode 100644
index 000000000..0350e470a
--- /dev/null
+++ b/package/lua/patches/100-no_readline.patch
@@ -0,0 +1,49 @@
+--- a/src/luaconf.h
++++ b/src/luaconf.h
+@@ -38,7 +38,6 @@
+ #if defined(LUA_USE_LINUX)
+ #define LUA_USE_POSIX
+ #define LUA_USE_DLOPEN /* needs an extra library: -ldl */
+-#define LUA_USE_READLINE /* needs some extra libraries */
+ #endif
+
+ #if defined(LUA_USE_MACOSX)
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -17,6 +17,7 @@ LIBS= -lm $(MYLIBS)
+ MYCFLAGS=
+ MYLDFLAGS=
+ MYLIBS=
++# USE_READLINE=1
+
+ # == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
+
+@@ -86,7 +87,7 @@ echo:
+ @echo "MYLIBS = $(MYLIBS)"
+
+ # convenience targets for popular platforms
+-
++RFLAG=$(if $(USE_READLINE),-DLUA_USE_READLINE)
+ none:
+ @echo "Please choose a platform:"
+ @echo " $(PLATS)"
+@@ -101,16 +102,16 @@ bsd:
+ $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E"
+
+ freebsd:
+- $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX" MYLIBS="-Wl,-E -lreadline"
++ $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX $(RFLAG)" MYLIBS="-Wl,-E$(if $(USE_READLINE), -lreadline)"
+
+ generic:
+ $(MAKE) all MYCFLAGS=
+
+ linux:
+- $(MAKE) all MYCFLAGS+=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
++ $(MAKE) all MYCFLAGS+="-DLUA_USE_LINUX $(RFLAG)" MYLIBS="-Wl,-E -ldl $(if $(USE_READLINE), -lreadline -lhistory -lncurses)"
+
+ macosx:
+- $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline"
++ $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX $(if $(USE_READLINE), MYLIBS="-lreadline")
+ # use this on Mac OS X 10.3-
+ # $(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX
+
diff --git a/package/lua/patches/200-lua-path.patch b/package/lua/patches/200-lua-path.patch
new file mode 100644
index 000000000..054457744
--- /dev/null
+++ b/package/lua/patches/200-lua-path.patch
@@ -0,0 +1,15 @@
+--- a/src/luaconf.h
++++ b/src/luaconf.h
+@@ -95,9 +95,9 @@
+ ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll"
+
+ #else
+-#define LUA_ROOT "/usr/local/"
+-#define LUA_LDIR LUA_ROOT "share/lua/5.1/"
+-#define LUA_CDIR LUA_ROOT "lib/lua/5.1/"
++#define LUA_ROOT "/usr/"
++#define LUA_LDIR LUA_ROOT "share/lua/"
++#define LUA_CDIR LUA_ROOT "lib/lua/"
+ #define LUA_PATH_DEFAULT \
+ "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
+ LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua"
diff --git a/package/lua/patches/300-opcode_performance.patch b/package/lua/patches/300-opcode_performance.patch
new file mode 100644
index 000000000..e870a25f4
--- /dev/null
+++ b/package/lua/patches/300-opcode_performance.patch
@@ -0,0 +1,363 @@
+--- a/src/lvm.c
++++ b/src/lvm.c
+@@ -31,6 +31,9 @@
+ /* limit for table tag-method chains (to avoid loops) */
+ #define MAXTAGLOOP 100
+
++#ifdef __GNUC__
++#define COMPUTED_GOTO 1
++#endif
+
+ /*
+ * If 'obj' is a string, it is tried to be interpreted as a number.
+@@ -562,12 +565,63 @@ static inline int arith_mode( const TVal
+ ARITH_OP1_END
+ #endif
+
++#ifdef COMPUTED_GOTO
++#define OPCODE_TARGET(op) DO_OP_##op:
++#define CALL_OPCODE(op) goto *opcodes[op];
++#define OPCODE_PTR(op) [OP_##op] = &&DO_OP_##op
++#else
++#define OPCODE_TARGET(op) case OP_##op:
++#define CALL_OPCODE(op) switch (op)
++#endif
++
+
+ void luaV_execute (lua_State *L, int nexeccalls) {
+ LClosure *cl;
+ StkId base;
+ TValue *k;
+ const Instruction *pc;
++#ifdef COMPUTED_GOTO
++ static const void *opcodes[] = {
++ OPCODE_PTR(MOVE),
++ OPCODE_PTR(LOADK),
++ OPCODE_PTR(LOADBOOL),
++ OPCODE_PTR(LOADNIL),
++ OPCODE_PTR(GETUPVAL),
++ OPCODE_PTR(GETGLOBAL),
++ OPCODE_PTR(GETTABLE),
++ OPCODE_PTR(SETGLOBAL),
++ OPCODE_PTR(SETUPVAL),
++ OPCODE_PTR(SETTABLE),
++ OPCODE_PTR(NEWTABLE),
++ OPCODE_PTR(SELF),
++ OPCODE_PTR(ADD),
++ OPCODE_PTR(SUB),
++ OPCODE_PTR(MUL),
++ OPCODE_PTR(DIV),
++ OPCODE_PTR(MOD),
++ OPCODE_PTR(POW),
++ OPCODE_PTR(UNM),
++ OPCODE_PTR(NOT),
++ OPCODE_PTR(LEN),
++ OPCODE_PTR(CONCAT),
++ OPCODE_PTR(JMP),
++ OPCODE_PTR(EQ),
++ OPCODE_PTR(LT),
++ OPCODE_PTR(LE),
++ OPCODE_PTR(TEST),
++ OPCODE_PTR(TESTSET),
++ OPCODE_PTR(CALL),
++ OPCODE_PTR(TAILCALL),
++ OPCODE_PTR(RETURN),
++ OPCODE_PTR(FORLOOP),
++ OPCODE_PTR(FORPREP),
++ OPCODE_PTR(TFORLOOP),
++ OPCODE_PTR(SETLIST),
++ OPCODE_PTR(CLOSE),
++ OPCODE_PTR(CLOSURE),
++ OPCODE_PTR(VARARG)
++ };
++#endif
+ reentry: /* entry point */
+ lua_assert(isLua(L->ci));
+ pc = L->savedpc;
+@@ -592,33 +646,33 @@ void luaV_execute (lua_State *L, int nex
+ lua_assert(base == L->base && L->base == L->ci->base);
+ lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);
+ lua_assert(L->top == L->ci->top || luaG_checkopenop(i));
+- switch (GET_OPCODE(i)) {
+- case OP_MOVE: {
++ CALL_OPCODE(GET_OPCODE(i)) {
++ OPCODE_TARGET(MOVE) {
+ setobjs2s(L, ra, RB(i));
+ continue;
+ }
+- case OP_LOADK: {
++ OPCODE_TARGET(LOADK) {
+ setobj2s(L, ra, KBx(i));
+ continue;
+ }
+- case OP_LOADBOOL: {
++ OPCODE_TARGET(LOADBOOL) {
+ setbvalue(ra, GETARG_B(i));
+ if (GETARG_C(i)) pc++; /* skip next instruction (if C) */
+ continue;
+ }
+- case OP_LOADNIL: {
++ OPCODE_TARGET(LOADNIL) {
+ TValue *rb = RB(i);
+ do {
+ setnilvalue(rb--);
+ } while (rb >= ra);
+ continue;
+ }
+- case OP_GETUPVAL: {
++ OPCODE_TARGET(GETUPVAL) {
+ int b = GETARG_B(i);
+ setobj2s(L, ra, cl->upvals[b]->v);
+ continue;
+ }
+- case OP_GETGLOBAL: {
++ OPCODE_TARGET(GETGLOBAL) {
+ TValue g;
+ TValue *rb = KBx(i);
+ sethvalue(L, &g, cl->env);
+@@ -626,88 +680,88 @@ void luaV_execute (lua_State *L, int nex
+ Protect(luaV_gettable(L, &g, rb, ra));
+ continue;
+ }
+- case OP_GETTABLE: {
++ OPCODE_TARGET(GETTABLE) {
+ Protect(luaV_gettable(L, RB(i), RKC(i), ra));
+ continue;
+ }
+- case OP_SETGLOBAL: {
++ OPCODE_TARGET(SETGLOBAL) {
+ TValue g;
+ sethvalue(L, &g, cl->env);
+ lua_assert(ttisstring(KBx(i)));
+ Protect(luaV_settable(L, &g, KBx(i), ra));
+ continue;
+ }
+- case OP_SETUPVAL: {
++ OPCODE_TARGET(SETUPVAL) {
+ UpVal *uv = cl->upvals[GETARG_B(i)];
+ setobj(L, uv->v, ra);
+ luaC_barrier(L, uv, ra);
+ continue;
+ }
+- case OP_SETTABLE: {
++ OPCODE_TARGET(SETTABLE) {
+ Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
+ continue;
+ }
+- case OP_NEWTABLE: {
++ OPCODE_TARGET(NEWTABLE) {
+ int b = GETARG_B(i);
+ int c = GETARG_C(i);
+ sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));
+ Protect(luaC_checkGC(L));
+ continue;
+ }
+- case OP_SELF: {
++ OPCODE_TARGET(SELF) {
+ StkId rb = RB(i);
+ setobjs2s(L, ra+1, rb);
+ Protect(luaV_gettable(L, rb, RKC(i), ra));
+ continue;
+ }
+- case OP_ADD: {
++ OPCODE_TARGET(ADD) {
+ TValue *rb = RKB(i), *rc= RKC(i);
+ arith_op_continue( luai_numadd, try_addint, luai_vectadd );
+ Protect(Arith(L, ra, rb, rc, TM_ADD)); \
+ continue;
+ }
+- case OP_SUB: {
++ OPCODE_TARGET(SUB) {
+ TValue *rb = RKB(i), *rc= RKC(i);
+ arith_op_continue( luai_numsub, try_subint, luai_vectsub );
+ Protect(Arith(L, ra, rb, rc, TM_SUB));
+ continue;
+ }
+- case OP_MUL: {
++ OPCODE_TARGET(MUL) {
+ TValue *rb = RKB(i), *rc= RKC(i);
+ arith_op_continue(luai_nummul, try_mulint, luai_vectmul);
+ Protect(Arith(L, ra, rb, rc, TM_MUL));
+ continue;
+ }
+- case OP_DIV: {
++ OPCODE_TARGET(DIV) {
+ TValue *rb = RKB(i), *rc= RKC(i);
+ arith_op_continue(luai_numdiv, try_divint, luai_vectdiv);
+ Protect(Arith(L, ra, rb, rc, TM_DIV));
+ continue;
+ }
+- case OP_MOD: {
++ OPCODE_TARGET(MOD) {
+ TValue *rb = RKB(i), *rc= RKC(i);
+ arith_op_continue_scalar(luai_nummod, try_modint); /* scalars only */
+ Protect(Arith(L, ra, rb, rc, TM_MOD));
+ continue;
+ }
+- case OP_POW: {
++ OPCODE_TARGET(POW) {
+ TValue *rb = RKB(i), *rc= RKC(i);
+ arith_op_continue(luai_numpow, try_powint, luai_vectpow);
+ Protect(Arith(L, ra, rb, rc, TM_POW));
+ continue;
+ }
+- case OP_UNM: {
++ OPCODE_TARGET(UNM) {
+ TValue *rb = RB(i);
+ arith_op1_continue(luai_numunm, try_unmint, luai_vectunm);
+ Protect(Arith(L, ra, rb, rb, TM_UNM));
+ continue;
+ }
+- case OP_NOT: {
++ OPCODE_TARGET(NOT) {
+ int res = l_isfalse(RB(i)); /* next assignment may change this value */
+ setbvalue(ra, res);
+ continue;
+ }
+- case OP_LEN: {
++ OPCODE_TARGET(LEN) {
+ const TValue *rb = RB(i);
+ switch (ttype(rb)) {
+ case LUA_TTABLE: {
+@@ -727,18 +781,18 @@ void luaV_execute (lua_State *L, int nex
+ }
+ continue;
+ }
+- case OP_CONCAT: {
++ OPCODE_TARGET(CONCAT) {
+ int b = GETARG_B(i);
+ int c = GETARG_C(i);
+ Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L));
+ setobjs2s(L, RA(i), base+b);
+ continue;
+ }
+- case OP_JMP: {
++ OPCODE_TARGET(JMP) {
+ dojump(L, pc, GETARG_sBx(i));
+ continue;
+ }
+- case OP_EQ: {
++ OPCODE_TARGET(EQ) {
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ Protect(
+@@ -748,7 +802,7 @@ void luaV_execute (lua_State *L, int nex
+ pc++;
+ continue;
+ }
+- case OP_LT: {
++ OPCODE_TARGET(LT) {
+ Protect(
+ if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))
+ dojump(L, pc, GETARG_sBx(*pc));
+@@ -756,7 +810,7 @@ void luaV_execute (lua_State *L, int nex
+ pc++;
+ continue;
+ }
+- case OP_LE: {
++ OPCODE_TARGET(LE) {
+ Protect(
+ if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))
+ dojump(L, pc, GETARG_sBx(*pc));
+@@ -764,13 +818,13 @@ void luaV_execute (lua_State *L, int nex
+ pc++;
+ continue;
+ }
+- case OP_TEST: {
++ OPCODE_TARGET(TEST) {
+ if (l_isfalse(ra) != GETARG_C(i))
+ dojump(L, pc, GETARG_sBx(*pc));
+ pc++;
+ continue;
+ }
+- case OP_TESTSET: {
++ OPCODE_TARGET(TESTSET) {
+ TValue *rb = RB(i);
+ if (l_isfalse(rb) != GETARG_C(i)) {
+ setobjs2s(L, ra, rb);
+@@ -779,7 +833,7 @@ void luaV_execute (lua_State *L, int nex
+ pc++;
+ continue;
+ }
+- case OP_CALL: {
++ OPCODE_TARGET(CALL) {
+ int b = GETARG_B(i);
+ int nresults = GETARG_C(i) - 1;
+ if (b != 0) L->top = ra+b; /* else previous instruction set top */
+@@ -800,7 +854,7 @@ void luaV_execute (lua_State *L, int nex
+ }
+ }
+ }
+- case OP_TAILCALL: {
++ OPCODE_TARGET(TAILCALL) {
+ int b = GETARG_B(i);
+ if (b != 0) L->top = ra+b; /* else previous instruction set top */
+ L->savedpc = pc;
+@@ -832,7 +886,7 @@ void luaV_execute (lua_State *L, int nex
+ }
+ }
+ }
+- case OP_RETURN: {
++ OPCODE_TARGET(RETURN) {
+ int b = GETARG_B(i);
+ if (b != 0) L->top = ra+b-1;
+ if (L->openupval) luaF_close(L, base);
+@@ -847,7 +901,7 @@ void luaV_execute (lua_State *L, int nex
+ goto reentry;
+ }
+ }
+- case OP_FORLOOP: {
++ OPCODE_TARGET(FORLOOP) {
+ /* If start,step and limit are all integers, we don't need to check
+ * against overflow in the looping.
+ */
+@@ -875,7 +929,7 @@ void luaV_execute (lua_State *L, int nex
+ }
+ continue;
+ }
+- case OP_FORPREP: {
++ OPCODE_TARGET(FORPREP) {
+ const TValue *init = ra;
+ const TValue *plimit = ra+1;
+ const TValue *pstep = ra+2;
+@@ -898,7 +952,7 @@ void luaV_execute (lua_State *L, int nex
+ dojump(L, pc, GETARG_sBx(i));
+ continue;
+ }
+- case OP_TFORLOOP: {
++ OPCODE_TARGET(TFORLOOP) {
+ StkId cb = ra + 3; /* call base */
+ setobjs2s(L, cb+2, ra+2);
+ setobjs2s(L, cb+1, ra+1);
+@@ -914,7 +968,7 @@ void luaV_execute (lua_State *L, int nex
+ pc++;
+ continue;
+ }
+- case OP_SETLIST: {
++ OPCODE_TARGET(SETLIST) {
+ int n = GETARG_B(i);
+ int c = GETARG_C(i);
+ int last;
+@@ -936,11 +990,11 @@ void luaV_execute (lua_State *L, int nex
+ }
+ continue;
+ }
+- case OP_CLOSE: {
++ OPCODE_TARGET(CLOSE) {
+ luaF_close(L, ra);
+ continue;
+ }
+- case OP_CLOSURE: {
++ OPCODE_TARGET(CLOSURE) {
+ Proto *p;
+ Closure *ncl;
+ int nup, j;
+@@ -960,7 +1014,7 @@ void luaV_execute (lua_State *L, int nex
+ Protect(luaC_checkGC(L));
+ continue;
+ }
+- case OP_VARARG: {
++ OPCODE_TARGET(VARARG) {
+ int b = GETARG_B(i) - 1;
+ int j;
+ CallInfo *ci = L->ci;
diff --git a/package/mac80211/Makefile b/package/mac80211/Makefile
new file mode 100644
index 000000000..36598bde0
--- /dev/null
+++ b/package/mac80211/Makefile
@@ -0,0 +1,1632 @@
+#
+# Copyright (C) 2007-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=mac80211
+
+PKG_VERSION:=2012-09-07
+PKG_RELEASE:=3
+PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
+PKG_MD5SUM:=59e0a114ee4b755a6e47cb6cd0f32ebc
+
+PKG_SOURCE:=compat-wireless-$(PKG_VERSION).tar.bz2
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
+PKG_BUILD_PARALLEL:=1
+
+PKG_DRIVERS = \
+ ath5k libertas-usb libertas-sd p54-common p54-pci p54-usb p54-spi \
+ rt2x00-lib rt2x00-pci rt2x00-usb rt2x00-soc rt2800-lib rt2400-pci \
+ rt2500-pci rt2500-usb rt61-pci rt73-usb rt2800-pci rt2800-usb \
+ rtl8180 rtl8187 zd1211rw mac80211-hwsim carl9170 b43 b43legacy \
+ ath9k-common ath9k ath9k-htc ath net-libipw net-ipw2100 net-ipw2200 \
+ mwl8k net-hermes net-hermes-pci net-hermes-plx net-hermes-pcmcia \
+ iwl-legacy iwl3945 iwl4965 iwlagn wl12xx lib80211
+
+PKG_CONFIG_DEPENDS:= \
+ CONFIG_PACKAGE_kmod-mac80211 \
+ $(patsubst %,CONFIG_PACKAGE_kmod-%,$(PKG_DRIVERS)) \
+ CONFIG_PACKAGE_MAC80211_DEBUGFS \
+ CONFIG_PACKAGE_MAC80211_MESH \
+ CONFIG_PACKAGE_ATH_DEBUG \
+ CONFIG_PACKAGE_B43_DEBUG \
+ CONFIG_PACKAGE_B43_PIO \
+ CONFIG_PACKAGE_B43_N_PHY \
+ CONFIG_ATH_USER_REGD \
+
+CARL9170_FW_VERSION:=1.9.4
+
+include $(INCLUDE_DIR)/package.mk
+
+WMENU:=Wireless Drivers
+
+define KernelPackage/mac80211/Default
+ SUBMENU:=$(WMENU)
+ URL:=http://linuxwireless.org/
+ MAINTAINER:=Felix Fietkau <nbd@openwrt.org>
+ DEPENDS:=@(!(TARGET_avr32||TARGET_ps3||TARGET_pxcab)||BROKEN)
+endef
+
+define KernelPackage/cfg80211
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=cfg80211 - wireless configuration API
+ DEPENDS+= +iw
+ FILES:= \
+ $(PKG_BUILD_DIR)/compat/compat.ko \
+ $(PKG_BUILD_DIR)/net/wireless/cfg80211.ko
+ AUTOLOAD:=$(call AutoLoad,20,compat cfg80211)
+endef
+
+define KernelPackage/cfg80211/description
+cfg80211 is the Linux wireless LAN (802.11) configuration API.
+endef
+
+define KernelPackage/mac80211
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Linux 802.11 Wireless Networking Stack
+ DEPENDS+= +kmod-crypto-core +kmod-crypto-arc4 +kmod-crypto-aes +kmod-cfg80211
+ KCONFIG:=\
+ CONFIG_AVERAGE=y
+ FILES:= $(PKG_BUILD_DIR)/net/mac80211/mac80211.ko
+ AUTOLOAD:=$(call AutoLoad,21,mac80211)
+ MENU:=1
+endef
+
+define KernelPackage/mac80211/config
+ menu "Configuration"
+ depends on PACKAGE_kmod-mac80211
+
+ config PACKAGE_MAC80211_DEBUGFS
+ bool "Export mac80211 internals in DebugFS"
+ default y
+ help
+ Select this to see extensive information about
+ the internal state of mac80211 in debugfs.
+
+ Say N unless you know you need this.
+
+ config PACKAGE_MAC80211_MESH
+ bool "Enable 802.11s mesh support"
+ default y
+
+ endmenu
+endef
+
+define KernelPackage/mac80211/description
+Generic IEEE 802.11 Networking Stack (mac80211)
+endef
+
+PKG_LINUX_FIRMWARE_NAME:=linux-firmware
+PKG_LINUX_FIRMWARE_VERSION:=375e9548bf75a5664256d47a2f9e14b79181e02d
+PKG_LINUX_FIRMWARE_SOURCE:=$(PKG_LINUX_FIRMWARE_NAME)-$(PKG_LINUX_FIRMWARE_VERSION).tar.bz2
+PKG_LINUX_FIRMWARE_PROTO:=git
+# PKG_LINUX_FIRMWARE_SOURCE_URL:=git://git.infradead.org/users/dwmw2/linux-firmware.git
+PKG_LINUX_FIRMWARE_SOURCE_URL:=git://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git
+PKG_LINUX_FIRMWARE_SUBDIR:=$(PKG_LINUX_FIRMWARE_NAME)-$(PKG_LINUX_FIRMWARE_VERSION)
+
+define Download/linux-firmware
+ FILE:=$(PKG_LINUX_FIRMWARE_SOURCE)
+ URL:=$(PKG_LINUX_FIRMWARE_SOURCE_URL)
+ MD5SUM:=$(PKG_LINUX_FIRMWARE_MD5SUM)
+ PROTO:=$(PKG_LINUX_FIRMWARE_PROTO)
+ VERSION:=$(PKG_LINUX_FIRMWARE_VERSION)
+ SUBDIR:=$(PKG_LINUX_FIRMWARE_SUBDIR)
+endef
+$(eval $(call Download,linux-firmware))
+
+# Prism54 drivers
+P54PCIFW:=2.13.12.0.arm
+P54USBFW:=2.13.24.0.lm87.arm
+P54SPIFW:=2.13.0.0.a.13.14.arm
+CARL9170_FW:=carl9170-1.fw
+
+define Download/p54usb
+ FILE:=$(P54USBFW)
+ URL:=http://daemonizer.de/prism54/prism54-fw/fw-usb
+ MD5SUM:=8e8ab005a4f8f0123bcdc51bc25b47f6
+endef
+$(eval $(call Download,p54usb))
+
+define Download/p54pci
+ FILE:=$(P54PCIFW)
+ URL:=http://daemonizer.de/prism54/prism54-fw/fw-softmac
+ MD5SUM:=ff7536af2092b1c4b21315bd103ef4c4
+endef
+$(eval $(call Download,p54pci))
+
+define Download/p54spi
+ FILE:=$(P54SPIFW)
+ URL:=http://daemonizer.de/prism54/prism54-fw/stlc4560
+ MD5SUM:=42661f8ecbadd88012807493f596081d
+endef
+$(eval $(call Download,p54spi))
+
+define Download/carl9170
+ FILE:=$(CARL9170_FW)-$(CARL9170_FW_VERSION)
+ URL:=http://downloads.openwrt.org/sources/
+ MD5SUM:=30e2ae80c33b3008d271556d1a14e3ea
+endef
+$(eval $(call Download,carl9170))
+
+define KernelPackage/p54/Default
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Prism54 Drivers
+endef
+
+define KernelPackage/p54/description
+ Kernel module for Prism54 chipsets (mac80211)
+endef
+
+define KernelPackage/p54-common
+ $(call KernelPackage/p54/Default)
+ DEPENDS+= @PCI_SUPPORT||@USB_SUPPORT||@TARGET_omap24xx +kmod-mac80211 +kmod-lib-crc-ccitt
+ TITLE+= (COMMON)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/p54/p54common.ko
+ AUTOLOAD:=$(call AutoLoad,30,p54common)
+endef
+
+define KernelPackage/p54-pci
+ $(call KernelPackage/p54/Default)
+ TITLE+= (PCI)
+ DEPENDS+= @PCI_SUPPORT +kmod-p54-common
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/p54/p54pci.ko
+ AUTOLOAD:=$(call AutoLoad,31,p54pci)
+endef
+
+define KernelPackage/p54-usb
+ $(call KernelPackage/p54/Default)
+ TITLE+= (USB)
+ DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-p54-common
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/p54/p54usb.ko
+ AUTOLOAD:=$(call AutoLoad,31,p54usb)
+endef
+
+define KernelPackage/p54-spi
+ $(call KernelPackage/p54/Default)
+ TITLE+= (SPI)
+ DEPENDS+= @TARGET_omap24xx +kmod-p54-common
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/p54/p54spi.ko
+ AUTOLOAD:=$(call AutoLoad,31,p54spi)
+endef
+
+NEED_RT2X00_LIB_CRYPTO:=y
+NEED_RT2X00_LIB_FIRMWARE:=y
+NEED_RT2X00_LIB_EEPROM:=y
+NEED_RT2X00_LIB_HT:=y
+NEED_RT2X00_LIB_LEDS:=y
+
+define KernelPackage/rt2x00/Default
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Ralink Drivers for RT2x00 cards
+endef
+
+define KernelPackage/rt2x00-lib
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-mac80211 +kmod-lib-crc-itu-t
+ TITLE+= (LIB)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00lib.ko
+ AUTOLOAD:=$(call AutoLoad,25,rt2x00lib)
+ MENU:=1
+endef
+
+define KernelPackage/rt2x00-lib/config
+ menu "Configuration"
+ depends PACKAGE_kmod-rt2x00-lib
+
+ config PACKAGE_RT2X00_LIB_DEBUGFS
+ bool "Enable rt2x00 debugfs support"
+ depends PACKAGE_MAC80211_DEBUGFS
+ help
+ Enable creation of debugfs files for the rt2x00 drivers.
+ These debugfs files support both reading and writing of the
+ most important register types of the rt2x00 hardware.
+
+ config PACKAGE_RT2X00_DEBUG
+ bool "Enable rt2x00 debug output"
+ help
+ Enable debugging output for all rt2x00 modules
+
+ endmenu
+endef
+
+define KernelPackage/rt2x00-pci
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @(PCI_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib +kmod-eeprom-93cx6
+ TITLE+= (PCI)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00pci.ko
+ AUTOLOAD:=$(call AutoLoad,26,rt2x00pci)
+endef
+
+define KernelPackage/rt2x00-usb
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @USB_SUPPORT +kmod-rt2x00-lib +kmod-usb-core
+ TITLE+= (USB)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00usb.ko
+ AUTOLOAD:=$(call AutoLoad,26,rt2x00usb)
+endef
+
+define KernelPackage/rt2x00-soc
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @TARGET_ramips +kmod-rt2x00-lib
+ TITLE+= (SoC)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00soc.ko
+ AUTOLOAD:=$(call AutoLoad,26,rt2x00soc)
+endef
+
+define KernelPackage/rt2800-lib
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib +TARGET_ramips:kmod-rt2x00-soc +@DRIVER_11N_SUPPORT
+ TITLE+= (rt2800 LIB)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800lib.ko
+ AUTOLOAD:=$(call AutoLoad,27,rt2800lib)
+endef
+
+define KernelPackage/rt2400-pci
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci
+ TITLE+= (RT2400 PCI)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2400pci.ko
+ AUTOLOAD:=$(call AutoLoad,27,rt2400pci)
+endef
+
+define KernelPackage/rt2500-pci
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci
+ TITLE+= (RT2500 PCI)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2500pci.ko
+ AUTOLOAD:=$(call AutoLoad,27,rt2500pci)
+endef
+
+define KernelPackage/rt2500-usb
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @USB_SUPPORT +kmod-rt2x00-usb
+ TITLE+= (RT2500 USB)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2500usb.ko
+ AUTOLOAD:=$(call AutoLoad,27,rt2500usb)
+endef
+
+define KernelPackage/rt61-pci
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci
+ TITLE+= (RT2x61 PCI)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt61pci.ko
+ AUTOLOAD:=$(call AutoLoad,27,rt61pci)
+endef
+
+define KernelPackage/rt73-usb
+ $(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @USB_SUPPORT +kmod-rt2x00-usb
+ TITLE+= (RT73 USB)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt73usb.ko
+ AUTOLOAD:=$(call AutoLoad,27,rt73usb)
+endef
+
+define KernelPackage/rt2800-pci
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @(PCI_SUPPORT||TARGET_ramips) +kmod-rt2x00-pci +kmod-rt2800-lib +kmod-lib-crc-ccitt +TARGET_ramips:kmod-rt2x00-soc
+ TITLE+= (RT2860 PCI)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800pci.ko
+ AUTOLOAD:=$(call AutoLoad,28,rt2800pci)
+endef
+
+define KernelPackage/rt2800-usb
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @USB_SUPPORT +kmod-rt2x00-usb +kmod-rt2800-lib +kmod-lib-crc-ccitt
+ TITLE+= (RT2870 USB)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800usb.ko
+ AUTOLOAD:=$(call AutoLoad,28,rt2800usb)
+endef
+
+define KernelPackage/rtl818x/Default
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Realtek Drivers for RTL818x devices
+ URL:=http://wireless.kernel.org/en/users/Drivers/rtl8187
+ DEPENDS+= +kmod-eeprom-93cx6 +kmod-mac80211
+endef
+
+define KernelPackage/rtl8180
+ $(call KernelPackage/rtl818x/Default)
+ DEPENDS+= @PCI_SUPPORT
+ TITLE+= (RTL8180 PCI)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtl818x/rtl8180/rtl8180.ko
+ AUTOLOAD:=$(call AutoLoad,27,rtl8180)
+endef
+
+define KernelPackage/rtl8187
+$(call KernelPackage/rtl818x/Default)
+ DEPENDS+= @USB_SUPPORT +kmod-usb-core
+ TITLE+= (RTL8187 USB)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtl818x/rtl8187/rtl8187.ko
+ AUTOLOAD:=$(call AutoLoad,27,rtl8187)
+endef
+
+ZD1211FW_NAME:=zd1211-firmware
+ZD1211FW_VERSION:=1.4
+define Download/zd1211rw
+ FILE:=$(ZD1211FW_NAME)-$(ZD1211FW_VERSION).tar.bz2
+ URL:=@SF/zd1211/
+ MD5SUM:=19f28781d76569af8551c9d11294c870
+endef
+$(eval $(call Download,zd1211rw))
+
+define KernelPackage/zd1211rw
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Zydas ZD1211 support
+ DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-mac80211
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/zd1211rw/zd1211rw.ko
+ AUTOLOAD:=$(call AutoLoad,60,zd1211rw)
+endef
+
+define KernelPackage/ath/config
+ menu "Configuration"
+ depends on PACKAGE_kmod-ath
+
+ config ATH_USER_REGD
+ bool "Force Atheros drivers to respect the user's regdomain settings"
+ help
+ Atheros' idea of regulatory handling is that the EEPROM of the card defines
+ the regulatory limits and the user is only allowed to restrict the settings
+ even further, even if the country allows frequencies or power levels that
+ are forbidden by the EEPROM settings.
+
+ Select this option if you want the driver to respect the user's decision about
+ regulatory settings.
+
+ config PACKAGE_ATH_DEBUG
+ bool "Atheros wireless debugging"
+ help
+ Say Y, if you want to debug atheros wireless drivers.
+ Right now only ath9k makes use of this.
+
+ endmenu
+endef
+
+define KernelPackage/ath
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Atheros common driver part
+ DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ar71xx||TARGET_atheros +kmod-mac80211
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath.ko
+ AUTOLOAD:=$(call AutoLoad,26,ath)
+ MENU:=1
+endef
+
+define KernelPackage/ath/description
+ This module contains some common parts needed by Atheros Wireless drivers.
+endef
+
+define KernelPackage/ath5k
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Atheros 5xxx wireless cards support
+ URL:=http://linuxwireless.org/en/users/Drivers/ath5k
+ DEPENDS+= @PCI_SUPPORT||@TARGET_atheros +kmod-ath
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath5k/ath5k.ko
+ AUTOLOAD:=$(call AutoLoad,27,ath5k)
+endef
+
+define KernelPackage/ath5k/description
+ This module adds support for wireless adapters based on
+ Atheros 5xxx chipset.
+endef
+
+define KernelPackage/ath9k-common
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Atheros 802.11n wireless devices (common code for ath9k and ath9k_htc)
+ URL:=http://linuxwireless.org/en/users/Drivers/ath9k
+ DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ar71xx +kmod-ath +@DRIVER_11N_SUPPORT
+ FILES:= \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_common.ko \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_hw.ko
+ AUTOLOAD:=$(call AutoLoad,27,ath9k_hw ath9k_common)
+endef
+
+define KernelPackage/ath9k
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Atheros 802.11n PCI wireless cards support
+ URL:=http://linuxwireless.org/en/users/Drivers/ath9k
+ DEPENDS+= @PCI_SUPPORT||TARGET_ar71xx +kmod-ath9k-common
+ FILES:= \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k.ko
+ AUTOLOAD:=$(call AutoLoad,28,ath9k)
+endef
+
+define KernelPackage/ath9k/description
+This module adds support for wireless adapters based on
+Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets.
+endef
+
+define KernelPackage/ath9k-htc
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Atheros 802.11n USB device support
+ URL:=http://linuxwireless.org/en/users/Drivers/ath9k
+ DEPENDS+= @USB_SUPPORT +kmod-ath9k-common +kmod-usb-core
+ FILES:= \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_htc.ko
+ AUTOLOAD:=$(call AutoLoad,55,ath9k_htc)
+endef
+
+define KernelPackage/ath9k-htc/description
+This module adds support for wireless adapters based on
+Atheros USB AR9271 and AR7010 family of chipsets.
+endef
+
+define KernelPackage/carl9170
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Driver for Atheros AR9170 USB sticks
+ DEPENDS:=@USB_SUPPORT +kmod-mac80211 +kmod-ath +kmod-usb-core +kmod-input-core +@DRIVER_11N_SUPPORT
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/carl9170/carl9170.ko
+ AUTOLOAD:=$(call AutoLoad,60,carl9170)
+endef
+
+define KernelPackage/carl9170/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(DL_DIR)/$(CARL9170_FW)-$(CARL9170_FW_VERSION) $(1)/lib/firmware/$(CARL9170_FW)
+endef
+
+define KernelPackage/lib80211
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=802.11 Networking stack
+ FILES:= \
+ $(PKG_BUILD_DIR)/net/wireless/lib80211.ko \
+ $(PKG_BUILD_DIR)/net/wireless/lib80211_crypt_wep.ko \
+ $(PKG_BUILD_DIR)/net/wireless/lib80211_crypt_ccmp.ko \
+ $(PKG_BUILD_DIR)/net/wireless/lib80211_crypt_tkip.ko
+ AUTOLOAD:=$(call AutoLoad,21, \
+ lib80211 \
+ lib80211_crypt_wep \
+ lib80211_crypt_ccmp \
+ lib80211_crypt_tkip \
+ )
+endef
+
+define KernelPackage/lib80211/description
+ Kernel modules for 802.11 Networking stack
+ Includes:
+ - lib80211
+ - lib80211_crypt_wep
+ - lib80211_crypt_tkip
+ - lib80211_crytp_ccmp
+endef
+
+define KernelPackage/libertas-usb
+ $(call KernelPackage/mac80211/Default)
+ DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +kmod-usb-core +kmod-lib80211 +@DRIVER_WEXT_SUPPORT
+ TITLE:=Marvell 88W8015 Wireless Driver
+ FILES:= \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/libertas/libertas.ko \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/libertas/usb8xxx.ko
+ AUTOLOAD:=$(call AutoLoad,27,libertas usb8xxx)
+endef
+
+define KernelPackage/libertas-sd
+ $(call KernelPackage/mac80211/Default)
+ DEPENDS+= +kmod-cfg80211 +kmod-lib80211 +@DRIVER_WEXT_SUPPORT
+ TITLE:=Marvell 88W8686 Wireless Driver
+ FILES:= \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/libertas/libertas.ko \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/libertas/libertas_sdio.ko
+ AUTOLOAD:=$(call AutoLoad,91,libertas libertas_sdio)
+endef
+
+define KernelPackage/mac80211-hwsim
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=mac80211 HW simulation device
+ DEPENDS+= +kmod-mac80211
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/mac80211_hwsim.ko
+ AUTOLOAD:=$(call AutoLoad,60,mac80211_hwsim)
+endef
+
+define KernelPackage/net-libipw
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=libipw for ipw2100 and ipw2200
+ DEPENDS:=@PCI_SUPPORT +kmod-crypto-core +kmod-crypto-arc4 +kmod-crypto-aes +kmod-crypto-michael-mic +kmod-lib80211 +kmod-cfg80211 +@DRIVER_WEXT_SUPPORT
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ipw2x00/libipw.ko
+ AUTOLOAD:=$(call AutoLoad,49,libipw)
+endef
+
+define KernelPackage/net-libipw/description
+ Hardware independent IEEE 802.11 networking stack for ipw2100 and ipw2200.
+endef
+
+IPW2100_NAME:=ipw2100-fw
+IPW2100_VERSION:=1.3
+
+define Download/net-ipw2100
+ URL:=http://bughost.org/firmware/
+ FILE:=$(IPW2100_NAME)-$(IPW2100_VERSION).tgz
+ MD5SUM=46aa75bcda1a00efa841f9707bbbd113
+endef
+$(eval $(call Download,net-ipw2100))
+
+define KernelPackage/net-ipw2100
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Intel IPW2100 driver
+ DEPENDS:=@PCI_SUPPORT +kmod-net-libipw
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ipw2x00/ipw2100.ko
+ AUTOLOAD:=$(call AutoLoad,50,ipw2100)
+endef
+
+define KernelPackage/net-ipw2100/description
+ Kernel support for Intel IPW2100
+ Includes:
+ - ipw2100
+endef
+
+IPW2200_NAME:=ipw2200-fw
+IPW2200_VERSION:=3.1
+
+define Download/net-ipw2200
+ URL:=http://bughost.org/firmware/
+ FILE:=$(IPW2200_NAME)-$(IPW2200_VERSION).tgz
+ MD5SUM=eaba788643c7cc7483dd67ace70f6e99
+endef
+$(eval $(call Download,net-ipw2200))
+
+define KernelPackage/net-ipw2200
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Intel IPW2200 driver
+ DEPENDS:=@PCI_SUPPORT +kmod-net-libipw
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ipw2x00/ipw2200.ko
+ AUTOLOAD:=$(call AutoLoad,50,ipw2200)
+endef
+
+define KernelPackage/net-ipw2200/description
+ Kernel support for Intel IPW2200
+ Includes:
+ - ipw2200
+endef
+
+
+define KernelPackage/net-hermes
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Hermes 802.11b chipset support
+ DEPENDS:=@PCI_SUPPORT||PCMCIA_SUPPORT +kmod-cfg80211 +@DRIVER_WEXT_SUPPORT
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/orinoco/orinoco.ko
+ AUTOLOAD:=$(call AutoLoad,50,orinoco)
+endef
+
+define KernelPackage/net-hermes/description
+ Kernel support for Hermes 802.11b chipsets
+endef
+
+define KernelPackage/net-hermes-pci
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Intersil Prism 2.5 PCI support
+ DEPENDS:=@PCI_SUPPORT +kmod-net-hermes
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/orinoco/orinoco_pci.ko
+ AUTOLOAD:=$(call AutoLoad,55,orinoco_pci)
+endef
+
+define KernelPackage/net-hermes-pci/description
+ Kernel modules for Intersil Prism 2.5 PCI support
+endef
+
+define KernelPackage/net-hermes-plx
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=PLX9052 based PCI adaptor
+ DEPENDS:=@PCI_SUPPORT +kmod-net-hermes
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/orinoco/orinoco_plx.ko
+ AUTOLOAD:=$(call AutoLoad,55,orinoco_plx)
+endef
+
+define KernelPackage/net-hermes-plx/description
+ Kernel modules for Hermes in PLX9052 based PCI adaptors
+endef
+
+define KernelPackage/net-hermes-pcmcia
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Hermes based PCMCIA adaptors
+ DEPENDS:=@PCMCIA_SUPPORT +kmod-net-hermes @BROKEN
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/orinoco/orinoco_cs.ko
+ AUTOLOAD:=$(call AutoLoad,55,orinoco_cs)
+endef
+
+define KernelPackage/net-hermes-pcmcia/description
+ Kernel modules for Hermes based PCMCIA adaptors
+endef
+
+define KernelPackage/iwlagn
+ $(call KernelPackage/mac80211/Default)
+ DEPENDS:= +kmod-mac80211 @PCI_SUPPORT
+ TITLE:=Intel AGN Wireless support
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlwifi/iwlwifi.ko
+ AUTOLOAD:=$(call AutoLoad,60,iwlagn)
+ MENU:=1
+endef
+
+define KernelPackage/iwlagn/description
+ iwlagn kernel module for Intel 5000/5150/1000/6000/6050/6005/6030/100 support
+endef
+
+define KernelPackage/iwlagn/config
+ menu "Configuration"
+ depends on PACKAGE_kmod-iwlagn
+
+ config IWL5000_FW
+ bool "Intel 5000 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel 5000 wireless card into /lib/firmware.
+
+ config IWL5150_FW
+ bool "Intel 5150 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel 5150 wireless card into /lib/firmware.
+
+ config IWL1000_FW
+ bool "Intel 1000 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel 1000 wireless card into /lib/firmware.
+
+ config IWL6000_FW
+ bool "Intel 6000 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel 6000 wireless card into /lib/firmware.
+
+ config IWL6050_FW
+ bool "Intel 6050 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel 6050 wireless card into /lib/firmware.
+
+ config IWL6005_FW
+ bool "Intel 6005 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel 6005 wireless card into /lib/firmware.
+
+ config IWL6030_FW
+ bool "Intel 6030 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel 6030 wireless card into /lib/firmware.
+
+ config IWL100_FW
+ bool "Intel 100 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel 100 wireless card into /lib/firmware.
+
+ endmenu
+endef
+
+define KernelPackage/iwl-legacy
+ $(call KernelPackage/mac80211/Default)
+ DEPENDS:= +kmod-mac80211 @PCI_SUPPORT
+ TITLE:=Intel legacy Wireless support
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlegacy/iwlegacy.ko
+ AUTOLOAD:=$(call AutoLoad,60,iwl-legacy)
+endef
+
+define KernelPackage/iwl-legacy/description
+ iwl-legacy kernel module for legacy Intel wireless support
+endef
+
+define KernelPackage/iwl3945
+ $(call KernelPackage/mac80211/Default)
+ DEPENDS:= +kmod-mac80211 +kmod-iwl-legacy
+ TITLE:=Intel iwl3945 Wireless support
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlegacy/iwl3945.ko
+ AUTOLOAD:=$(call AutoLoad,61,iwl3945)
+endef
+
+define KernelPackage/iwl3945/description
+ iwl3945 kernel module for Intel 3945 support
+endef
+
+define KernelPackage/iwl4965
+ $(call KernelPackage/mac80211/Default)
+ DEPENDS:= +kmod-mac80211 +kmod-iwl-legacy
+ TITLE:=Intel iwl4965 Wireless support
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlegacy/iwl4965.ko
+ AUTOLOAD:=$(call AutoLoad,61,iwl4965)
+endef
+
+define KernelPackage/iwl4965/description
+ iwl4965 kernel module for Intel 4965 support
+endef
+
+
+define KernelPackage/mwl8k
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Driver for Marvell TOPDOG 802.11 Wireless cards
+ URL:=http://wireless.kernel.org/en/users/Drivers/mwl8k
+ DEPENDS+= @PCI_SUPPORT +kmod-mac80211
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/mwl8k.ko
+ AUTOLOAD:=$(call AutoLoad,27,mwl8k)
+endef
+
+define KernelPackage/mwl8k/description
+ Kernel modules for Marvell TOPDOG 802.11 Wireless cards
+endef
+
+
+define KernelPackage/wl12xx
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Driver for TI WL12xx
+ URL:=http://wireless.kernel.org/en/users/Drivers/wl12xx
+ DEPENDS+= @TARGET_omap4 +kmod-mac80211
+ FILES:= \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/ti/wl12xx/wl12xx.ko \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/ti/wlcore/wlcore.ko \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/ti/wlcore/wlcore_sdio.ko
+ AUTOLOAD:=$(call AutoLoad,61,wlcore wlcore_sdio wl12xx)
+endef
+
+define KernelPackage/wl12xx/description
+ Kernel modules for TI WL12xx
+endef
+
+#Broadcom firmware
+ifneq ($(CONFIG_B43_FW_5_10),)
+ PKG_B43_FWV4_NAME:=broadcom-wl
+ PKG_B43_FWV4_VERSION:=5.10.56.27.3
+ PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/driver/wl_apsta/wl_prebuilt.o
+ PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)_mipsel.tar.bz2
+ PKG_B43_FWV4_SOURCE_URL:=http://mirror2.openwrt.org/sources/
+ PKG_B43_FWV4_MD5SUM:=3363e3a6b3d9d73c49dea870c7834eac
+else
+ifneq ($(CONFIG_B43_FW_4_178),)
+ PKG_B43_FWV4_NAME:=broadcom-wl
+ PKG_B43_FWV4_VERSION:=4.178.10.4
+ PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/linux/wl_apsta.o
+ PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2
+ PKG_B43_FWV4_SOURCE_URL:=http://mirror2.openwrt.org/sources/
+ PKG_B43_FWV4_MD5SUM:=14477e8cbbb91b11896affac9b219fdb
+else
+ifneq ($(CONFIG_B43_FW_5_100_138),)
+ PKG_B43_FWV4_NAME:=broadcom-wl
+ PKG_B43_FWV4_VERSION:=5.100.138
+ PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/linux/wl_apsta.o
+ PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2
+ PKG_B43_FWV4_SOURCE_URL:=http://www.lwfinger.com/b43-firmware/
+ PKG_B43_FWV4_MD5SUM:=f4e357b09eaf5d8b1f1920cf3493a555
+else
+ PKG_B43_FWV4_NAME:=broadcom-wl
+ PKG_B43_FWV4_VERSION:=4.150.10.5
+ PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/driver/wl_apsta_mimo.o
+ PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2
+ PKG_B43_FWV4_SOURCE_URL:=http://mirror2.openwrt.org/sources/
+ PKG_B43_FWV4_MD5SUM:=0c6ba9687114c6b598e8019e262d9a60
+endif
+endif
+endif
+ifneq ($(CONFIG_B43_OPENFIRMWARE),)
+ PKG_B43_FWV4_NAME:=broadcom-wl
+ PKG_B43_FWV4_VERSION:=5.2
+ PKG_B43_FWV4_OBJECT:=openfwwf-$(PKG_B43_FWV4_VERSION)
+ PKG_B43_FWV4_SOURCE:=openfwwf-$(PKG_B43_FWV4_VERSION).tar.gz
+ PKG_B43_FWV4_SOURCE_URL:=http://www.ing.unibs.it/openfwwf/firmware/
+ PKG_B43_FWV4_MD5SUM:=e045a135453274e439ae183f8498b0fa
+endif
+
+
+PKG_B43_FWV3_NAME:=wl_apsta
+PKG_B43_FWV3_VERSION:=3.130.20.0
+PKG_B43_FWV3_SOURCE:=$(PKG_B43_FWV3_NAME)-$(PKG_B43_FWV3_VERSION).o
+PKG_B43_FWV3_SOURCE_URL:=http://downloads.openwrt.org/sources/
+PKG_B43_FWV3_MD5SUM:=e08665c5c5b66beb9c3b2dd54aa80cb3
+
+ifeq ($(CONFIG_B43_OPENFIRMWARE),y)
+ PKG_B43_FWCUTTER_NAME:=b43-fwcutter
+ PKG_B43_FWCUTTER_VERSION:=3e69531aa65b8f664a0ab00dfc3e2eefeb0cb417
+ PKG_B43_FWCUTTER_SOURCE:=$(PKG_B43_FWCUTTER_NAME)-$(PKG_B43_FWCUTTER_VERSION).tar.bz2
+ PKG_B43_FWCUTTER_PROTO:=git
+ PKG_B43_FWCUTTER_SOURCE_URL:=http://git.bu3sch.de/git/b43-tools.git
+ PKG_B43_FWCUTTER_SUBDIR:=$(PKG_B43_FWCUTTER_NAME)-$(PKG_B43_FWCUTTER_VERSION)
+ PKG_B43_FWCUTTER_OBJECT:=$(PKG_B43_FWCUTTER_NAME)-$(PKG_B43_FWCUTTER_VERSION)/fwcutter/
+else
+ PKG_B43_FWCUTTER_NAME:=b43-fwcutter
+ PKG_B43_FWCUTTER_VERSION:=015
+ PKG_B43_FWCUTTER_SOURCE:=$(PKG_B43_FWCUTTER_NAME)-$(PKG_B43_FWCUTTER_VERSION).tar.bz2
+ PKG_B43_FWCUTTER_PROTO:=default
+ PKG_B43_FWCUTTER_SOURCE_URL:=http://bu3sch.de/b43/fwcutter/
+ PKG_B43_FWCUTTER_MD5SUM:=628e030565222a107bc40300313cbe76
+ PKG_B43_FWCUTTER_SUBDIR:=b43-fwcutter-$(PKG_B43_FWCUTTER_VERSION)
+ PKG_B43_FWCUTTER_OBJECT:=$(PKG_B43_FWCUTTER_NAME)-$(PKG_B43_FWCUTTER_VERSION)/
+endif
+
+define Download/b43-common
+ FILE:=$(PKG_B43_FWCUTTER_SOURCE)
+ URL:=$(PKG_B43_FWCUTTER_SOURCE_URL)
+ MD5SUM:=$(PKG_B43_FWCUTTER_MD5SUM)
+ PROTO:=$(PKG_B43_FWCUTTER_PROTO)
+ VERSION:=$(PKG_B43_FWCUTTER_VERSION)
+ SUBDIR:=$(PKG_B43_FWCUTTER_SUBDIR)
+endef
+$(eval $(call Download,b43-common))
+
+define Download/b43
+ FILE:=$(PKG_B43_FWV4_SOURCE)
+ URL:=$(PKG_B43_FWV4_SOURCE_URL)
+ MD5SUM:=$(PKG_B43_FWV4_MD5SUM)
+endef
+$(eval $(call Download,b43))
+
+define Download/b43legacy
+ FILE:=$(PKG_B43_FWV3_SOURCE)
+ URL:=$(PKG_B43_FWV3_SOURCE_URL)
+ MD5SUM:=$(PKG_B43_FWV3_MD5SUM)
+endef
+$(eval $(call Download,b43legacy))
+
+define KernelPackage/b43-common
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Generic stuff for Broadcom wireless devices
+ URL:=http://linuxwireless.org/en/users/Drivers/b43
+ KCONFIG:= \
+ CONFIG_HW_RANDOM=y
+ DEPENDS+= +kmod-mac80211 +!(TARGET_brcm47xx||TARGET_brcm63xx):kmod-ssb
+endef
+
+define KernelPackage/b43
+$(call KernelPackage/b43-common)
+ DEPENDS+= +@DRIVER_11N_SUPPORT +!TARGET_brcm47xx:kmod-bcma
+ TITLE:=Broadcom 43xx wireless support
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/b43/b43.ko
+ AUTOLOAD:=$(call AutoLoad,30,b43)
+ MENU:=1
+endef
+
+define KernelPackage/b43/config
+ menu "Configuration"
+ depends on PACKAGE_kmod-b43
+
+ choice
+ prompt "b43 firmware version"
+ default B43_FW_5_100_138
+ help
+ This option allows you to select the version of the b43 firmware.
+
+ config B43_FW_4_150
+ bool "Firmware 410.2160 from driver 4.150.10.5 (old stable)"
+ help
+ Stable firmware for BCM43xx devices.
+
+ If unsure, select this.
+
+ config B43_FW_4_178
+ bool "Firmware 478.104 from driver 4.178.10.4"
+ help
+ Experimental firmware for BCM43xx devices.
+
+ This firmware is not tested as much as the "stable" firmware.
+
+ If unsure, select the "stable" firmware.
+
+ config B43_FW_5_10
+ bool "Firmware 508.1084 from driver 5.10.56.27"
+ help
+ Newer experimental firmware for BCM43xx devices.
+
+ This firmware is mostly untested. It is needed for some N-PHY devices.
+
+ If unsure, select the "stable" firmware.
+
+ config B43_FW_5_100_138
+ bool "Firmware 666.2 from driver 5.100.138 (stable)"
+ help
+ Newer experimental firmware for BCM43xx devices.
+
+ This firmware is mostly untested. It is needed for some N-PHY devices.
+
+ If unsure, select the "stable" firmware.
+
+ config B43_OPENFIRMWARE
+ bool "Open FirmWare for WiFi networks"
+ help
+ Opensource firmware for BCM43xx devices.
+
+ Do _not_ select this, unless you know what you are doing.
+ The Opensource firmware is not suitable for embedded devices, yet.
+ It does not support QoS, which is bad for AccessPoints.
+ It does not support hardware crypto acceleration, which is a showstopper
+ for embedded devices with low CPU resources.
+
+ If unsure, select the "stable" firmware.
+
+ endchoice
+
+ config B43_FW_SQUASH
+ bool "Remove unnecessary firmware files"
+ depends on !B43_OPENFIRMWARE
+ default y
+ help
+ This options allows you to remove unnecessary b43 firmware files
+ from the final rootfs image. This can reduce the rootfs size by
+ up to 200k.
+
+ If unsure, say Y.
+
+ config B43_FW_SQUASH_COREREVS
+ string "Core revisions to include"
+ depends on B43_FW_SQUASH
+ default "5,6,7,8,9,10,11,13,14,15,16"
+ help
+ This is a comma seperated list of core revision numbers.
+
+ Example (keep files for rev5 only):
+ 5
+
+ Example (keep files for rev5 and rev11):
+ 5,11
+
+ config B43_FW_SQUASH_PHYTYPES
+ string "PHY types to include"
+ depends on B43_FW_SQUASH
+ default "G,LP,N"
+ help
+ This is a comma seperated list of PHY types:
+ A => A-PHY
+ AG => Dual A-PHY G-PHY
+ G => G-PHY
+ LP => LP-PHY
+ N => N-PHY
+ HT => HT-PHY
+ LCN => LCN-PHY
+
+ Example (keep files for G-PHY only):
+ G
+
+ Example (keep files for G-PHY and N-PHY):
+ G,N
+
+ config PACKAGE_B43_DEBUG
+ bool "Enable debug output and debugfs for b43"
+ default n
+ help
+ Enable additional debug output and runtime sanity checks for b43
+ and enables the debugfs interface.
+
+ If unsure, say N.
+
+ config PACKAGE_B43_PIO
+ bool "Enable support for PIO transfer mode"
+ default n
+ help
+ Enable support for using PIO instead of DMA. Unless you have DMA
+ transfer problems you don't need this.
+
+ If unsure, say N.
+
+ config PACKAGE_B43_PHY_N
+ bool "Enable support for N-PHYs"
+ default y
+ help
+ Enable support for BCM4321 and BCM4322.
+
+ Currently only 11g speed is available.
+
+ If unsure, say Y.
+
+ config PACKAGE_B43_PHY_HT
+ bool "Enable support for HT-PHYs"
+ default n
+ help
+ Currently broken.
+
+ If unsure, say N.
+
+ config PACKAGE_B43_PHY_LCN
+ bool "Enable support for LCN-PHYs"
+ depends on BROKEN
+ default n
+ help
+ Currently broken.
+
+ If unsure, say N.
+
+ endmenu
+endef
+
+define KernelPackage/b43/description
+Kernel module for Broadcom 43xx wireless support (mac80211 stack) new
+endef
+
+define KernelPackage/b43legacy
+$(call KernelPackage/b43-common)
+ TITLE:=Broadcom 43xx-legacy wireless support
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/b43legacy/b43legacy.ko
+ AUTOLOAD:=$(call AutoLoad,30,b43legacy)
+ MENU:=1
+endef
+
+define KernelPackage/b43legacy/config
+ menu "Configuration"
+ depends on PACKAGE_kmod-b43legacy
+
+ config B43LEGACY_FW_SQUASH
+ bool "Remove unnecessary firmware files"
+ default y
+ help
+ This options allows you to remove unnecessary b43legacy firmware files
+ from the final rootfs image. This can reduce the rootfs size by
+ up to 50k.
+
+ If unsure, say Y.
+
+ config B43LEGACY_FW_SQUASH_COREREVS
+ string "Core revisions to include"
+ depends on B43LEGACY_FW_SQUASH
+ default "1,2,3,4"
+ help
+ This is a comma seperated list of core revision numbers.
+
+ Example (keep files for rev4 only):
+ 4
+
+ Example (keep files for rev2 and rev4):
+ 2,4
+
+ endmenu
+endef
+
+define KernelPackage/b43legacy/description
+Kernel module for Broadcom 43xx-legacy wireless support (mac80211 stack) new
+endef
+
+
+define KernelPackage/brcmutil
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Broadcom IEEE802.11n common driver parts
+ URL:=http://linuxwireless.org/en/users/Drivers/brcm80211
+ DEPENDS+=@PCI_SUPPORT||USB_SUPPORT
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/brcm80211/brcmutil/brcmutil.ko
+ AUTOLOAD:=$(call AutoLoad,30,brcmutil)
+ MENU:=1
+endef
+
+define KernelPackage/brcmutil/description
+ This module contains some common parts needed by Broadcom Wireless drivers brcmsmac and brcmfmac.
+endef
+
+define KernelPackage/brcmutil/config
+ menu "Configuration"
+ depends on PACKAGE_kmod-brcmutil
+
+ config PACKAGE_BRCM80211_DEBUG
+ bool "Broadcom wireless driver debugging"
+ help
+ Say Y, if you want to debug brcmsmac and brcmfmac wireless driver.
+
+ endmenu
+endef
+
+define KernelPackage/brcmsmac
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Broadcom IEEE802.11n PCIe SoftMAC WLAN driver
+ URL:=http://linuxwireless.org/en/users/Drivers/brcm80211
+ DEPENDS+= +kmod-mac80211 +@DRIVER_11N_SUPPORT +!TARGET_brcm47xx:kmod-bcma +kmod-lib-cordic +kmod-lib-crc8 +kmod-brcmutil
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/brcm80211/brcmsmac/brcmsmac.ko
+ AUTOLOAD:=$(call AutoLoad,31,brcmsmac)
+endef
+
+define KernelPackage/brcmsmac/description
+ Kernel module for Broadcom IEEE802.11n PCIe Wireless cards
+endef
+
+define KernelPackage/brcmfmac
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Broadcom IEEE802.11n USB FullMAC WLAN driver
+ URL:=http://linuxwireless.org/en/users/Drivers/brcm80211
+ DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-cfg80211 +@DRIVER_11N_SUPPORT +kmod-brcmutil
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/brcm80211/brcmfmac/brcmfmac.ko
+ AUTOLOAD:=$(call AutoLoad,60,brcmfmac)
+endef
+
+define KernelPackage/brcmfmac/description
+ Kernel module for Broadcom IEEE802.11n USB Wireless cards
+endef
+
+BUILDFLAGS:= \
+ -I$(PKG_BUILD_DIR)/include \
+ -DCONFIG_CFG80211_INTERNAL_REGDB=y \
+ $(foreach opt,$(CONFOPTS),-DCONFIG_$(opt)) \
+ $(if $(CONFIG_PCI),-DCONFIG_B43_PCI_AUTOSELECT -DCONFIG_B43_PCICORE_AUTOSELECT) \
+ $(if $(CONFIG_LEDS_TRIGGERS), -DCONFIG_MAC80211_LEDS -DCONFIG_LEDS_TRIGGERS -DCONFIG_B43_LEDS -DCONFIG_B43LEGACY_LEDS) \
+ -DCONFIG_B43_HWRNG -DCONFIG_B43LEGACY_HWRNG \
+ $(if $(CONFIG_PCI),-DCONFIG_ATH9K_PCI) \
+ $(if $(CONFIG_TARGET_ar71xx),-DCONFIG_ATH9K_AHB) \
+ $(if $(CONFIG_PACKAGE_MAC80211_DEBUGFS), -DCONFIG_CFG80211_DEBUGFS -DCONFIG_MAC80211_DEBUGFS -DCONFIG_ATH9K_DEBUGFS -DCONFIG_CARL9170_DEBUGFS -DCONFIG_ATH9K_HTC_DEBUGFS -DCONFIG_ATH5K_DEBUG) \
+ $(if $(CONFIG_PACKAGE_MAC80211_MESH),-DCONFIG_MAC80211_MESH) \
+ $(if $(CONFIG_PACKAGE_ATH_DEBUG),-DCONFIG_ATH_DEBUG -DCONFIG_ATH9K_PKTLOG) \
+ -D__CONFIG_MAC80211_RC_DEFAULT=minstrel \
+ -DCONFIG_MAC80211_RC_MINSTREL_HT \
+ $(if $(CONFIG_ATH_USER_REGD),-DATH_USER_REGD=1) \
+ $(if $(CONFIG_PACKAGE_B43_DEBUG),-DCONFIG_B43_DEBUG) \
+ $(if $(CONFIG_PACKAGE_B43_PIO),-DCONFIG_B43_PIO) \
+ $(if $(CONFIG_PACKAGE_B43_PIO),-DCONFIG_B43_BCMA_PIO) \
+ $(if $(CONFIG_PACKAGE_B43_PHY_N),-DCONFIG_B43_PHY_N) \
+ $(if $(CONFIG_PACKAGE_B43_PHY_HT),-DCONFIG_B43_PHY_HT) \
+ $(if $(CONFIG_PACKAGE_B43_PHY_LCN),-DCONFIG_B43_PHY_LCN) \
+ -DCONFIG_B43_BCMA -DCONFIG_B43_BCMA_EXTRA \
+ -DCONFIG_B43_SSB \
+ $(if $(CONFIG_PACKAGE_RT2X00_LIB_DEBUGFS),-DCONFIG_RT2X00_LIB_DEBUGFS) \
+ $(if $(CONFIG_PACKAGE_RT2X00_DEBUG),-DCONFIG_RT2X00_DEBUG) \
+ $(if $(NEED_RT2X00_LIB_HT),-DCONFIG_RT2X00_LIB_HT) \
+ $(if $(NEED_RT2X00_LIB_CRYPTO),-DCONFIG_RT2X00_LIB_CRYPTO) \
+ $(if $(NEED_RT2X00_LIB_FIRMWARE),-DCONFIG_RT2X00_LIB_FIRMWARE) \
+ $(if $(NEED_RT2X00_LIB_EEPROM),-DCONFIG_RT2X00_LIB_EEPROM) \
+ $(if $(NEED_RT2X00_LIB_LEDS),-DCONFIG_RT2X00_LIB_LEDS) \
+ $(if $(CONFIG_PACKAGE_kmod-rt2x00-pci),-DCONFIG_RT2X00_LIB_PCI) \
+ $(if $(CONFIG_PACKAGE_kmod-rt2x00-usb),-DCONFIG_RT2X00_LIB_USB) \
+ $(if $(CONFIG_PACKAGE_kmod-rt2x00-usb),-DCONFIG_RT2800USB_RT53XX) \
+ $(if $(CONFIG_PACKAGE_kmod-rt2x00-soc),-DCONFIG_RT2X00_LIB_SOC) \
+ $(if $(CONFIG_TARGET_atheros),-DCONFIG_ATH5K_AHB,-DCONFIG_ATH5K_PCI) \
+ $(if $(CONFIG_PACKAGE_kmod-iwl3945),-DCONFIG_IWL3945) \
+ $(if $(CONFIG_PACKAGE_kmod-iwl4965),-DCONFIG_COMPAT_IWL4965) \
+ $(if $(CONFIG_PACKAGE_kmod-wl12xx),-DCONFIG_WL12XX -DCONFIG_COMPAT_WL12XX_SDIO) \
+ $(if $(CONFIG_PACKAGE_BRCM80211_DEBUG),-DCONFIG_BRCMDBG) \
+ $(if $(CONFIG_PACKAGE_kmod-brcmfmac),-DCONFIG_BRCMFMAC_USB)
+
+MAKE_OPTS:= \
+ CROSS_COMPILE="$(KERNEL_CROSS)" \
+ ARCH="$(LINUX_KARCH)" \
+ EXTRA_CFLAGS="$(BUILDFLAGS)" \
+ $(foreach opt,$(CONFOPTS),CONFIG_$(opt)=m) \
+ CONFIG_CFG80211_INTERNAL_REGDB=y \
+ CONFIG_CFG80211=$(if $(CONFIG_PACKAGE_kmod-cfg80211),m) \
+ CONFIG_MAC80211=$(if $(CONFIG_PACKAGE_kmod-mac80211),m) \
+ CONFIG_MAC80211_RC_MINSTREL=y \
+ CONFIG_MAC80211_MESH=$(CONFIG_PACKAGE_MAC80211_MESH) \
+ CONFIG_MAC80211_LEDS=$(CONFIG_LEDS_TRIGGERS) \
+ CONFIG_CFG80211_DEBUGFS=$(if $(CONFIG_PACKAGE_MAC80211_DEBUGFS),y) \
+ CONFIG_MAC80211_DEBUGFS=$(if $(CONFIG_PACKAGE_MAC80211_DEBUGFS),y) \
+ CONFIG_B43_PCMCIA=n CONFIG_B43_PIO=n \
+ CONFIG_B43_PCI_AUTOSELECT=$(if $(CONFIG_PCI),y) \
+ CONFIG_B43_PCICORE_AUTOSELECT=$(if $(CONFIG_PCI),y) \
+ CONFIG_B43LEGACY_LEDS=$(CONFIG_LEDS_TRIGGERS) \
+ CONFIG_B43_LEDS=$(CONFIG_LEDS_TRIGGERS) \
+ CONFIG_B43_HWRNG=$(if $(CONFIG_HW_RANDOM),y) \
+ CONFIG_B43LEGACY_HWRNG=$(if $(CONFIG_HW_RANDOM),y) \
+ CONFIG_B43=$(if $(CONFIG_PACKAGE_kmod-b43),m) \
+ CONFIG_B43LEGACY=$(if $(CONFIG_PACKAGE_kmod-b43legacy),m) \
+ CONFIG_B43_DEBUG=$(if $(CONFIG_PACKAGE_B43_DEBUG),y) \
+ CONFIG_B43_PIO=$(if $(CONFIG_PACKAGE_B43_PIO),y) \
+ CONFIG_B43_BCMA_PIO=$(if $(CONFIG_PACKAGE_B43_PIO),y) \
+ CONFIG_B43_PHY_N=$(if $(CONFIG_PACKAGE_B43_PHY_N),y) \
+ CONFIG_B43_PHY_HT=$(if $(CONFIG_PACKAGE_B43_PHY_HT),y) \
+ CONFIG_B43_PHY_LCN=$(if $(CONFIG_PACKAGE_B43_PHY_LCN),y) \
+ CONFIG_B43_BCMA=y \
+ CONFIG_B43_SSB=y \
+ CONFIG_ATH_COMMON=$(if $(CONFIG_PACKAGE_kmod-ath),m) \
+ CONFIG_ATH_DEBUG=$(if $(CONFIG_PACKAGE_ATH_DEBUG),y) \
+ CONFIG_ATH9K_PKTLOG=$(if $(CONFIG_PACKAGE_ATH_DEBUG),y) \
+ CONFIG_ATH5K=$(if $(CONFIG_PACKAGE_kmod-ath5k),m) \
+ CONFIG_ATH5K_PCI=$(if $(CONFIG_TARGET_atheros),,y) \
+ CONFIG_ATH5K_AHB=$(if $(CONFIG_TARGET_atheros),y) \
+ CONFIG_ATH5K_DEBUG=$(if $(CONFIG_PACKAGE_MAC80211_DEBUGFS),y) \
+ CONFIG_ATH9K=$(if $(CONFIG_PACKAGE_kmod-ath9k),m) \
+ CONFIG_ATH9K_PCI=$(CONFIG_PCI) \
+ CONFIG_ATH9K_AHB=$(if $(CONFIG_TARGET_ar71xx),y) \
+ CONFIG_ATH9K_HTC=$(if $(CONFIG_PACKAGE_kmod-ath9k-htc),m) \
+ CONFIG_ATH9K_HTC_DEBUGFS=$(if $(CONFIG_PACKAGE_MAC80211_DEBUGFS),y) \
+ CONFIG_ATH9K_HW=$(if $(CONFIG_PACKAGE_kmod-ath9k-common),m) \
+ CONFIG_ATH9K_COMMON=$(if $(CONFIG_PACKAGE_kmod-ath9k-common),m) \
+ CONFIG_ATH9K_DEBUGFS=$(if $(CONFIG_PACKAGE_MAC80211_DEBUGFS),y) \
+ CONFIG_CARL9170=$(if $(CONFIG_PACKAGE_kmod-carl9170),m) \
+ CONFIG_CARL9170_DEBUGFS=$(if $(CONFIG_PACKAGE_MAC80211_DEBUGFS),y) \
+ CONFIG_COMPAT_ZD1211RW=$(if $(CONFIG_PACKAGE_kmod-zd1211rw),m) \
+ CONFIG_P54_COMMON=$(if $(CONFIG_PACKAGE_kmod-p54-common),m) \
+ CONFIG_P54_PCI=$(if $(CONFIG_PACKAGE_kmod-p54-pci),m) \
+ CONFIG_P54_USB=$(if $(CONFIG_PACKAGE_kmod-p54-usb),m) \
+ CONFIG_P54_SPI=$(if $(CONFIG_PACKAGE_kmod-p54-spi),m) \
+ CONFIG_P54_SPI_DEFAULT_EEPROM=n \
+ CONFIG_RT2X00=$(if $(CONFIG_PACKAGE_kmod-rt2x00-lib),m) \
+ CONFIG_RT2X00_LIB=$(if $(CONFIG_PACKAGE_kmod-rt2x00-lib),m) \
+ CONFIG_RT2X00_LIB_PCI=$(if $(CONFIG_PACKAGE_kmod-rt2x00-pci),m) \
+ CONFIG_RT2X00_LIB_USB=$(if $(CONFIG_PACKAGE_kmod-rt2x00-usb),m) \
+ CONFIG_RT2X00_LIB_SOC=$(if $(CONFIG_PACKAGE_kmod-rt2x00-soc),m) \
+ CONFIG_RT2X00_LIB_DEBUGFS=$(CONFIG_PACKAGE_RT2X00_LIB_DEBUGFS) \
+ CONFIG_RT2X00_LIB_CRYPTO=$(NEED_RT2X00_LIB_CRYPTO) \
+ CONFIG_RT2X00_LIB_FIRMWARE=$(NEED_RT2X00_LIB_FIRMWARE) \
+ CONFIG_RT2X00_LIB_EEPROM=$(NEED_RT2X00_LIB_EEPROM) \
+ CONFIG_RT2X00_LIB_HT=$(NEED_RT2X00_LIB_HT) \
+ CONFIG_RT2X00_LIB_LEDS=$(NEED_RT2X00_LIB_LEDS) \
+ CONFIG_RT2400PCI=$(if $(CONFIG_PACKAGE_kmod-rt2400-pci),m) \
+ CONFIG_RT2500PCI=$(if $(CONFIG_PACKAGE_kmod-rt2500-pci),m) \
+ CONFIG_RT2500USB=$(if $(CONFIG_PACKAGE_kmod-rt2500-usb),m) \
+ CONFIG_RT61PCI=$(if $(CONFIG_PACKAGE_kmod-rt61-pci),m) \
+ CONFIG_RT73USB=$(if $(CONFIG_PACKAGE_kmod-rt73-usb),m) \
+ CONFIG_RT2800_LIB=$(if $(CONFIG_PACKAGE_kmod-rt2800-lib),m) \
+ CONFIG_RT2800PCI=$(if $(CONFIG_PACKAGE_kmod-rt2800-pci),m) \
+ CONFIG_RT2800USB=$(if $(CONFIG_PACKAGE_kmod-rt2800-usb),m) \
+ CONFIG_RTL8180=$(if $(CONFIG_PACKAGE_kmod-rtl8180),m) \
+ CONFIG_RTL8187=$(if $(CONFIG_PACKAGE_kmod-rtl8187),m) \
+ CONFIG_RTL8192CE= \
+ CONFIG_RTLWIFI= \
+ CONFIG_MAC80211_HWSIM=$(if $(CONFIG_PACKAGE_kmod-mac80211-hwsim),m) \
+ CONFIG_PCMCIA= \
+ CONFIG_LIBIPW=$(if $(CONFIG_PACKAGE_kmod-net-libipw),m) \
+ CONFIG_LIBERTAS=$(if $(CONFIG_PACKAGE_kmod-libertas-sd)$(CONFIG_PACKAGE_kmod-libertas-usb),m) \
+ CONFIG_LIBERTAS_CS= \
+ CONFIG_LIBERTAS_SPI= \
+ CONFIG_COMPAT_LIBERTAS_SDIO=$(if $(CONFIG_PACKAGE_kmod-libertas-sd),m) \
+ CONFIG_LIBERTAS_THINFIRM= \
+ CONFIG_LIBERTAS_USB=$(if $(CONFIG_PACKAGE_kmod-libertas-usb),m) \
+ CONFIG_IPW2100=$(if $(CONFIG_PACKAGE_kmod-net-ipw2100),m) \
+ CONFIG_IPW2200=$(if $(CONFIG_PACKAGE_kmod-net-ipw2200),m) \
+ CONFIG_NL80211=y \
+ CONFIG_LIB80211=$(if $(CONFIG_PACKAGE_kmod-lib80211),m) \
+ CONFIG_LIB80211_CRYPT_WEP=$(if $(CONFIG_PACKAGE_kmod-lib80211),m) \
+ CONFIG_LIB80211_CRYPT_CCMP=$(if $(CONFIG_PACKAGE_kmod-lib80211),m) \
+ CONFIG_LIB80211_CRYPT_TKIP=$(if $(CONFIG_PACKAGE_kmod-lib80211),m) \
+ CONFIG_IWLWIFI=$(if $(CONFIG_PACKAGE_kmod-iwlagn),m) \
+ CONFIG_IWLEGACY=$(if $(CONFIG_PACKAGE_kmod-iwl-legacy),m) \
+ CONFIG_COMPAT_IWL4965=$(if $(CONFIG_PACKAGE_kmod-iwl4965),m) \
+ CONFIG_IWL3945=$(if $(CONFIG_PACKAGE_kmod-iwl3945),m) \
+ CONFIG_MWL8K=$(if $(CONFIG_PACKAGE_kmod-mwl8k),m) \
+ CONFIG_ATMEL= \
+ CONFIG_PCMCIA_ATMEL= \
+ CONFIG_ADM8211= \
+ CONFIG_USB_NET_RNDIS_HOST= \
+ CONFIG_USB_NET_RNDIS_WLAN= \
+ CONFIG_USB_NET_CDCETHER= \
+ CONFIG_USB_USBNET= \
+ CONFIG_AT76C50X_USB= \
+ CONFIG_WL_TI=$(if $(CONFIG_PACKAGE_kmod-wl12xx),m) \
+ CONFIG_WLCORE=$(if $(CONFIG_PACKAGE_kmod-wl12xx),m) \
+ CONFIG_WL12XX=$(if $(CONFIG_PACKAGE_kmod-wl12xx),m) \
+ CONFIG_WLCORE_SDIO=$(if $(CONFIG_PACKAGE_kmod-wl12xx),m) \
+ CONFIG_EEPROM_93CX6= \
+ CONFIG_HERMES=$(if $(CONFIG_PACKAGE_kmod-net-hermes),m) \
+ CONFIG_HERMES_CACHE_FW_ON_INIT= \
+ CONFIG_PCI_HERMES=$(if $(CONFIG_PACKAGE_kmod-net-hermes-pci),m) \
+ CONFIG_PLX_HERMES=$(if $(CONFIG_PACKAGE_kmod-net-hermes-plx),m) \
+ CONFIG_PCMCIA_HERMES=$(if $(CONFIG_PACKAGE_kmod-net-hermes-pcmcia),m) \
+ CONFIG_HERMES_PRISM= \
+ CONFIG_APPLE_AIRPORT= \
+ CONFIG_TMD_HERMES= \
+ CONFIG_NORTEL_HERMES= \
+ CONFIG_PCMCIA_SPECTRUM= \
+ CONFIG_ORINOCO_USB= \
+ CONFIG_IWM= \
+ CONFIG_MWIFIEX= \
+ CONFIG_ATH6KL= \
+ CONFIG_MAC80211_RC_MINSTREL_HT=y \
+ MADWIFI= \
+ CONFIG_B44= \
+ CONFIG_ATL1= \
+ CONFIG_ATL2= \
+ CONFIG_ATL1E= \
+ CONFIG_ATL1C= \
+ CONFIG_BRCMUTIL=$(if $(CONFIG_PACKAGE_kmod-brcmutil),m) \
+ CONFIG_BRCMSMAC=$(if $(CONFIG_PACKAGE_kmod-brcmsmac),m) \
+ CONFIG_BRCMFMAC=$(if $(CONFIG_PACKAGE_kmod-brcmfmac),m) \
+ CONFIG_BRCMFMAC_USB=$(if $(CONFIG_PACKAGE_kmod-brcmfmac),y) \
+ CONFIG_BRCMDBG=$(if $(CONFIG_PACKAGE_BRCM80211_DEBUG),y) \
+ KLIB_BUILD="$(LINUX_DIR)" \
+ MODPROBE=true \
+ KLIB=$(TARGET_MODULES_DIR) \
+ KERNEL_SUBLEVEL=$(lastword $(subst ., ,$(KERNEL_PATCHVER))) \
+ KBUILD_LDFLAGS_MODULE_PREREQ=
+
+ifeq ($(CONFIG_PACKAGE_kmod-libertas-sd)$(CONFIG_PACKAGE_kmod-libertas-usb)$(CONFIG_PACKAGE_kmod-rt2x00-lib),)
+ MAKE_OPTS += CONFIG_COMPAT_KFIFO=
+endif
+
+define Build/Prepare
+ rm -rf $(PKG_BUILD_DIR)
+ mkdir -p $(PKG_BUILD_DIR)
+ $(PKG_UNPACK)
+ $(Build/Patch)
+ $(TAR) -C $(PKG_BUILD_DIR) -xzf $(DL_DIR)/$(IPW2100_NAME)-$(IPW2100_VERSION).tgz
+ $(TAR) -C $(PKG_BUILD_DIR) -xzf $(DL_DIR)/$(IPW2200_NAME)-$(IPW2200_VERSION).tgz
+ $(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(ZD1211FW_NAME)-$(ZD1211FW_VERSION).tar.bz2
+ $(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(PKG_LINUX_FIRMWARE_SOURCE)
+ rm -rf $(PKG_BUILD_DIR)/include/linux/ssb
+ rm -rf $(PKG_BUILD_DIR)/include/linux/bcma
+ rm -rf $(PKG_BUILD_DIR)/include/net/bluetooth/
+ rm -f $(PKG_BUILD_DIR)/include/linux/eeprom_93cx6.h
+ rm -f $(PKG_BUILD_DIR)/include/linux/wl12xx.h
+ rm -f $(PKG_BUILD_DIR)/include/linux/spi/libertas_spi.h
+ rm -f $(PKG_BUILD_DIR)/include/net/ieee80211.h
+ echo 'compat-wireless-$(PKG_VERSION)-$(PKG_RELEASE)-$(REVISION)' > $(PKG_BUILD_DIR)/compat_version
+ $(CP) ./files/regdb.txt $(PKG_BUILD_DIR)/net/wireless/db.txt
+endef
+
+ifneq ($(CONFIG_PACKAGE_kmod-cfg80211)$(CONFIG_PACKAGE_kmod-lib80211),)
+ define Build/Compile/kmod
+ rm -rf $(PKG_BUILD_DIR)/modules
+ +$(MAKE) $(PKG_JOBS) -C "$(PKG_BUILD_DIR)" $(MAKE_OPTS) modules
+ endef
+endif
+
+define Build/Configure
+ cmp $(PKG_BUILD_DIR)/include/linux/ath9k_platform.h $(LINUX_DIR)/include/linux/ath9k_platform.h
+ cmp $(PKG_BUILD_DIR)/include/linux/ath5k_platform.h $(LINUX_DIR)/include/linux/ath5k_platform.h
+ cmp $(PKG_BUILD_DIR)/include/linux/rt2x00_platform.h $(LINUX_DIR)/include/linux/rt2x00_platform.h
+endef
+
+define Build/Compile
+ $(call Build/Compile/kmod)
+endef
+
+define Build/InstallDev
+ mkdir -p \
+ $(1)/usr/include/mac80211 \
+ $(1)/usr/include/mac80211/ath \
+ $(1)/usr/include/net/mac80211
+ $(CP) $(PKG_BUILD_DIR)/net/mac80211/*.h $(PKG_BUILD_DIR)/include/* $(1)/usr/include/mac80211/
+ $(CP) $(PKG_BUILD_DIR)/net/mac80211/rate.h $(1)/usr/include/net/mac80211/
+ $(CP) $(PKG_BUILD_DIR)/drivers/net/wireless/ath/*.h $(1)/usr/include/mac80211/ath/
+endef
+
+define KernelPackage/libertas-usb/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/usb8388_v9.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/usb8388_v5.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/usb8682.bin \
+ $(1)/lib/firmware/
+endef
+
+define KernelPackage/libertas-sd/install
+ $(INSTALL_DIR) $(1)/lib/firmware/libertas
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8385_helper.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8385.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8686_v9_helper.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8686_v9.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8686_v8_helper.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8686_v8.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8688_helper.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8688.bin \
+ $(1)/lib/firmware/libertas
+endef
+
+define KernelPackage/cfg80211/install
+ $(INSTALL_DIR) $(1)/lib/wifi
+ $(INSTALL_DATA) ./files/lib/wifi/mac80211.sh $(1)/lib/wifi
+endef
+
+define KernelPackage/p54-pci/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(DL_DIR)/$(P54PCIFW) $(1)/lib/firmware/isl3886pci
+endef
+
+define KernelPackage/p54-usb/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(DL_DIR)/$(P54USBFW) $(1)/lib/firmware/isl3887usb
+endef
+
+define KernelPackage/p54-spi/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(DL_DIR)/$(P54SPIFW) $(1)/lib/firmware/3826.arm
+endef
+
+define KernelPackage/rt61-pci/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2561.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2561s.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2661.bin \
+ $(1)/lib/firmware/
+endef
+
+define KernelPackage/rt73-usb/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt73.bin $(1)/lib/firmware/
+endef
+
+define KernelPackage/rt2800-pci/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2860.bin $(1)/lib/firmware/
+endef
+
+define KernelPackage/rt2800-usb/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2870.bin $(1)/lib/firmware/
+endef
+
+define KernelPackage/wl12xx/install
+ $(INSTALL_DIR) $(1)/lib/firmware/ti-connectivity
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl127x-fw-4-mr.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl127x-fw-4-plt.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl127x-fw-4-sr.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl1271-nvs.bin \
+ $(1)/lib/firmware/ti-connectivity
+endef
+
+
+define KernelPackage/zd1211rw/install
+ $(INSTALL_DIR) $(1)/lib/firmware/zd1211
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(ZD1211FW_NAME)/zd1211* $(1)/lib/firmware/zd1211
+endef
+
+define KernelPackage/ath9k-htc/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/htc_9271.fw \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/htc_7010.fw \
+ $(1)/lib/firmware/
+endef
+
+define KernelPackage/mwl8k/install
+ $(INSTALL_DIR) $(1)/lib/firmware/mwl8k
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/fmimage_8366_ap-2.fw \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/fmimage_8366.fw \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/helper_8366.fw \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/fmimage_8687.fw \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/helper_8687.fw \
+ $(1)/lib/firmware/mwl8k/
+endef
+
+define KernelPackage/net-ipw2100/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/ipw2100-$(IPW2100_VERSION)*.fw $(1)/lib/firmware
+endef
+
+define KernelPackage/net-ipw2200/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(IPW2200_NAME)-$(IPW2200_VERSION)/ipw2200*.fw $(1)/lib/firmware
+endef
+
+define KernelPackage/iwlagn/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ifneq ($(CONFIG_IWL5000_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-5000-5.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL5150_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-5150-2.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL1000_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-1000-5.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL6000_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-6000-4.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL6050_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-6050-5.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL6005_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-6000g2a-5.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL6030_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-6000g2b-5.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL100_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-100-5.ucode $(1)/lib/firmware
+endif
+endef
+
+define KernelPackage/iwl3945/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-3945-2.ucode $(1)/lib/firmware
+endef
+
+define KernelPackage/iwl4965/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-4965-2.ucode $(1)/lib/firmware
+endef
+
+define Build/b43-common
+ tar xjf "$(DL_DIR)/$(PKG_B43_FWCUTTER_SOURCE)" -C "$(PKG_BUILD_DIR)"
+ patch -p1 -d "$(PKG_BUILD_DIR)/$(PKG_B43_FWCUTTER_OBJECT)" < ./files/b43-fwcutter-fw-dirname.patch
+ $(MAKE) -C "$(PKG_BUILD_DIR)/$(PKG_B43_FWCUTTER_OBJECT)" \
+ CFLAGS="-I$(STAGING_DIR_HOST)/include -include endian.h" \
+ QUIET_SPARSE=:
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/$(PKG_B43_FWCUTTER_OBJECT)/b43-fwcutter $(STAGING_DIR_HOST)/bin/
+ifeq ($(CONFIG_B43_OPENFIRMWARE),y)
+ $(INSTALL_DIR) $(STAGING_DIR_HOST)/bin/
+ $(MAKE) -C "$(PKG_BUILD_DIR)/$(PKG_B43_FWCUTTER_SUBDIR)/assembler/"
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/$(PKG_B43_FWCUTTER_SUBDIR)/assembler/b43-asm $(STAGING_DIR_HOST)/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/$(PKG_B43_FWCUTTER_SUBDIR)/assembler/b43-asm.bin $(STAGING_DIR_HOST)/bin/
+endif
+ $(INSTALL_BIN) ./files/host_bin/b43-fwsquash.py $(STAGING_DIR_HOST)/bin/
+endef
+
+define KernelPackage/b43/install
+ rm -rf $(1)/lib/firmware/
+ $(call Build/b43-common)
+ifeq ($(CONFIG_B43_OPENFIRMWARE),y)
+ tar xzf "$(DL_DIR)/$(PKG_B43_FWV4_SOURCE)" -C "$(PKG_BUILD_DIR)"
+else
+ tar xjf "$(DL_DIR)/$(PKG_B43_FWV4_SOURCE)" -C "$(PKG_BUILD_DIR)"
+endif
+ $(INSTALL_DIR) $(1)/lib/firmware/
+ifeq ($(CONFIG_B43_OPENFIRMWARE),y)
+ $(MAKE) -C "$(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT)/"
+ $(INSTALL_DIR) $(1)/lib/firmware/b43-open/
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT)/ucode5.fw $(1)/lib/firmware/b43-open/ucode5.fw
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT)/b0g0bsinitvals5.fw $(1)/lib/firmware/b43-open/b0g0bsinitvals5.fw
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT)/b0g0initvals5.fw $(1)/lib/firmware/b43-open/b0g0initvals5.fw
+else
+ b43-fwcutter -w $(1)/lib/firmware/ $(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT)
+endif
+ifneq ($(CONFIG_B43_FW_SQUASH),)
+ b43-fwsquash.py "$(CONFIG_B43_FW_SQUASH_PHYTYPES)" "$(CONFIG_B43_FW_SQUASH_COREREVS)" "$(1)/lib/firmware/b43"
+endif
+endef
+
+define KernelPackage/b43legacy/install
+ $(call Build/b43-common)
+ $(INSTALL_DIR) $(1)/lib/firmware/
+
+ b43-fwcutter --unsupported -w $(1)/lib/firmware/ $(DL_DIR)/$(PKG_B43_FWV3_SOURCE)
+ifneq ($(CONFIG_B43LEGACY_FW_SQUASH),)
+ b43-fwsquash.py "G" "$(CONFIG_B43LEGACY_FW_SQUASH_COREREVS)" "$(1)/lib/firmware/b43legacy"
+endif
+endef
+
+define KernelPackage/brcmsmac/install
+ $(INSTALL_DIR) $(1)/lib/firmware/brcm
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/brcm/bcm43xx-0.fw \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/brcm/bcm43xx_hdr-0.fw \
+ $(1)/lib/firmware/brcm/
+endef
+
+define KernelPackage/brcmfmac/install
+ $(INSTALL_DIR) $(1)/lib/firmware/brcm
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/brcm/brcmfmac43236b.bin \
+ $(1)/lib/firmware/brcm/
+endef
+
+$(eval $(call KernelPackage,ath5k))
+$(eval $(call KernelPackage,lib80211))
+$(eval $(call KernelPackage,libertas-usb))
+$(eval $(call KernelPackage,libertas-sd))
+$(eval $(call KernelPackage,cfg80211))
+$(eval $(call KernelPackage,mac80211))
+$(eval $(call KernelPackage,p54-common))
+$(eval $(call KernelPackage,p54-pci))
+$(eval $(call KernelPackage,p54-usb))
+$(eval $(call KernelPackage,p54-spi))
+$(eval $(call KernelPackage,rt2x00-lib))
+$(eval $(call KernelPackage,rt2x00-pci))
+$(eval $(call KernelPackage,rt2x00-usb))
+$(eval $(call KernelPackage,rt2x00-soc))
+$(eval $(call KernelPackage,rt2800-lib))
+$(eval $(call KernelPackage,rt2400-pci))
+$(eval $(call KernelPackage,rt2500-pci))
+$(eval $(call KernelPackage,rt2500-usb))
+$(eval $(call KernelPackage,rt61-pci))
+$(eval $(call KernelPackage,rt73-usb))
+$(eval $(call KernelPackage,rt2800-pci))
+$(eval $(call KernelPackage,rt2800-usb))
+$(eval $(call KernelPackage,rtl8180))
+$(eval $(call KernelPackage,rtl8187))
+$(eval $(call KernelPackage,zd1211rw))
+$(eval $(call KernelPackage,mac80211-hwsim))
+$(eval $(call KernelPackage,ath9k-common))
+$(eval $(call KernelPackage,ath9k))
+$(eval $(call KernelPackage,ath9k-htc))
+$(eval $(call KernelPackage,ath))
+$(eval $(call KernelPackage,carl9170))
+$(eval $(call KernelPackage,b43))
+$(eval $(call KernelPackage,b43legacy))
+$(eval $(call KernelPackage,brcmutil))
+$(eval $(call KernelPackage,brcmsmac))
+$(eval $(call KernelPackage,brcmfmac))
+$(eval $(call KernelPackage,net-libipw))
+$(eval $(call KernelPackage,net-ipw2100))
+$(eval $(call KernelPackage,net-ipw2200))
+$(eval $(call KernelPackage,iwlagn))
+$(eval $(call KernelPackage,iwl-legacy))
+$(eval $(call KernelPackage,iwl4965))
+$(eval $(call KernelPackage,iwl3945))
+$(eval $(call KernelPackage,mwl8k))
+$(eval $(call KernelPackage,net-hermes))
+$(eval $(call KernelPackage,net-hermes-pci))
+$(eval $(call KernelPackage,net-hermes-plx))
+$(eval $(call KernelPackage,net-hermes-pcmcia))
+$(eval $(call KernelPackage,wl12xx))
diff --git a/package/mac80211/files/b43-fwcutter-fw-dirname.patch b/package/mac80211/files/b43-fwcutter-fw-dirname.patch
new file mode 100644
index 000000000..c2f49ab78
--- /dev/null
+++ b/package/mac80211/files/b43-fwcutter-fw-dirname.patch
@@ -0,0 +1,16 @@
+--- a/fwcutter.c
++++ b/fwcutter.c
+@@ -48,13 +48,8 @@
+ #include "fwcutter.h"
+ #include "fwcutter_list.h"
+
+-#if defined(__DragonFly__) || defined(__FreeBSD__)
+-#define V3_FW_DIRNAME "v3"
+-#define V4_FW_DIRNAME "v4"
+-#else
+ #define V3_FW_DIRNAME "b43legacy"
+ #define V4_FW_DIRNAME "b43"
+-#endif
+
+ static struct cmdline_args cmdargs;
+
diff --git a/package/mac80211/files/host_bin/b43-fwsquash.py b/package/mac80211/files/host_bin/b43-fwsquash.py
new file mode 100755
index 000000000..cd8818167
--- /dev/null
+++ b/package/mac80211/files/host_bin/b43-fwsquash.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+#
+# b43 firmware file squasher
+# Removes unnecessary firmware files
+#
+# Copyright (c) 2009 Michael Buesch <mb@bu3sch.de>
+#
+# Licensed under the GNU/GPL version 2 or (at your option) any later version.
+#
+
+import sys
+import os
+
+def usage():
+ print("Usage: %s PHYTYPES COREREVS /path/to/extracted/firmware" % sys.argv[0])
+ print("")
+ print("PHYTYPES is a comma separated list of:")
+ print("A => A-PHY")
+ print("AG => Dual A-PHY G-PHY")
+ print("G => G-PHY")
+ print("LP => LP-PHY")
+ print("N => N-PHY")
+ print("HT => HT-PHY")
+ print("LCN => LCN-PHY")
+ print("")
+ print("COREREVS is a comma separated list of core revision numbers.")
+
+if len(sys.argv) != 4:
+ usage()
+ sys.exit(1)
+
+phytypes = sys.argv[1]
+corerevs = sys.argv[2]
+fwpath = sys.argv[3]
+
+phytypes = phytypes.split(',')
+try:
+ corerevs = map(lambda r: int(r), corerevs.split(','))
+except ValueError:
+ print("ERROR: \"%s\" is not a valid COREREVS string\n" % corerevs)
+ usage()
+ sys.exit(1)
+
+
+fwfiles = os.listdir(fwpath)
+fwfiles = filter(lambda str: str.endswith(".fw"), fwfiles)
+if not fwfiles:
+ print("ERROR: No firmware files found in %s" % fwpath)
+ sys.exit(1)
+
+required_fwfiles = []
+
+def revs_match(revs_a, revs_b):
+ for rev in revs_a:
+ if rev in revs_b:
+ return True
+ return False
+
+def phytypes_match(types_a, types_b):
+ for type in types_a:
+ type = type.strip().upper()
+ if type in types_b:
+ return True
+ return False
+
+revmapping = {
+ "ucode2.fw" : (2,3,),
+ "ucode4.fw" : (4,),
+ "ucode5.fw" : (5,6,7,8,9,10,),
+ "ucode11.fw" : (11,12,),
+ "ucode13.fw" : (13,),
+ "ucode14.fw" : (14,),
+ "ucode15.fw" : (15,),
+ "ucode16_mimo.fw" : (16,),
+ "ucode24_mimo.fw" : (24,),
+ "ucode29_mimo.fw" : (29,),
+ "pcm4.fw" : (1,2,3,4,),
+ "pcm5.fw" : (5,6,7,8,9,10,),
+}
+
+initvalmapping = {
+ "a0g1initvals5.fw" : ( (5,6,7,8,9,10,), ("AG",), ),
+ "a0g0initvals5.fw" : ( (5,6,7,8,9,10,), ("A", "AG",), ),
+ "b0g0initvals2.fw" : ( (2,4,), ("G",), ),
+ "b0g0initvals5.fw" : ( (5,6,7,8,9,10,), ("G",), ),
+ "b0g0initvals13.fw" : ( (13,), ("G",), ),
+ "n0initvals11.fw" : ( (11,12,), ("N",), ),
+ "n0initvals16.fw" : ( (16,), ("N",), ),
+ "lp0initvals13.fw" : ( (13,), ("LP",), ),
+ "lp0initvals14.fw" : ( (14,), ("LP",), ),
+ "lp0initvals15.fw" : ( (15,), ("LP",), ),
+ "lcn0initvals24.fw" : ( (24,), ("LCN",), ),
+ "ht0initvals29.fw" : ( (29,), ("HT",), ),
+ "a0g1bsinitvals5.fw" : ( (5,6,7,8,9,10,), ("AG",), ),
+ "a0g0bsinitvals5.fw" : ( (5,6,7,8,9,10,), ("A", "AG"), ),
+ "b0g0bsinitvals5.fw" : ( (5,6,7,8,9,10,), ("G",), ),
+ "n0bsinitvals11.fw" : ( (11,12,), ("N",), ),
+ "n0bsinitvals16.fw" : ( (16,), ("N",), ),
+ "lp0bsinitvals13.fw" : ( (13,), ("LP",), ),
+ "lp0bsinitvals14.fw" : ( (14,), ("LP",), ),
+ "lp0bsinitvals15.fw" : ( (15,), ("LP",), ),
+ "lcn0bsinitvals24.fw" : ( (24,), ("LCN",), ),
+ "ht0bsinitvals29.fw" : ( (29,), ("HT",), ),
+}
+
+for f in fwfiles:
+ if f in revmapping:
+ if revs_match(corerevs, revmapping[f]):
+ required_fwfiles += [f]
+ continue
+ if f in initvalmapping:
+ if revs_match(corerevs, initvalmapping[f][0]) and\
+ phytypes_match(phytypes, initvalmapping[f][1]):
+ required_fwfiles += [f]
+ continue
+ print("WARNING: Firmware file %s not found in the mapping lists" % f)
+
+for f in fwfiles:
+ if f not in required_fwfiles:
+ print("Deleting %s" % f)
+ os.unlink(fwpath + '/' + f)
+
diff --git a/package/mac80211/files/lib/wifi/mac80211.sh b/package/mac80211/files/lib/wifi/mac80211.sh
new file mode 100644
index 000000000..1b0bea70e
--- /dev/null
+++ b/package/mac80211/files/lib/wifi/mac80211.sh
@@ -0,0 +1,599 @@
+#!/bin/sh
+append DRIVERS "mac80211"
+
+mac80211_hostapd_setup_base() {
+ local phy="$1"
+ local ifname="$2"
+
+ cfgfile="/var/run/hostapd-$phy.conf"
+ macfile="/var/run/hostapd-$phy.maclist"
+ [ -e "$macfile" ] && rm -f "$macfile"
+
+ config_get device "$vif" device
+ config_get country "$device" country
+ config_get hwmode "$device" hwmode
+ config_get channel "$device" channel
+ config_get beacon_int "$device" beacon_int
+ config_get basic_rate_list "$device" basic_rate
+ config_get_bool noscan "$device" noscan
+ config_get_bool short_preamble "$device" short_preamble "0"
+
+ hostapd_set_log_options base_cfg "$device"
+
+ [ -n "$channel" -a -z "$hwmode" ] && wifi_fixup_hwmode "$device"
+
+ [ "$channel" = auto ] && {
+ channel=$(iw phy "$phy" info | \
+ sed -ne '/MHz/ { /disabled\|passive\|radar/d; s/.*\[//; s/\].*//; p; q }')
+ config_set "$device" channel "$channel"
+ }
+
+ [ -n "$hwmode" ] && {
+ config_get hwmode_11n "$device" hwmode_11n
+ [ -n "$hwmode_11n" ] && {
+ hwmode="$hwmode_11n"
+ append base_cfg "ieee80211n=1" "$N"
+ config_get htmode "$device" htmode
+ config_get ht_capab_list "$device" ht_capab
+ case "$htmode" in
+ HT20|HT40+|HT40-) ht_capab="[$htmode]";;
+ *)ht_capab=;;
+ esac
+ for cap in $ht_capab_list; do
+ ht_capab="$ht_capab[$cap]"
+ done
+ [ -n "$ht_capab" ] && append base_cfg "ht_capab=$ht_capab" "$N"
+ }
+ }
+
+ local country_ie=0
+ [ -n "$country" ] && country_ie=1
+ config_get_bool country_ie "$device" country_ie "$country_ie"
+ [ "$country_ie" -gt 0 ] && append base_cfg "ieee80211d=1" "$N"
+
+ config_get macfilter "$vif" macfilter
+ case "$macfilter" in
+ allow)
+ append base_cfg "macaddr_acl=1" "$N"
+ append base_cfg "accept_mac_file=$macfile" "$N"
+ ;;
+ deny)
+ append base_cfg "macaddr_acl=0" "$N"
+ append base_cfg "deny_mac_file=$macfile" "$N"
+ ;;
+ esac
+ config_get maclist "$vif" maclist
+ [ -n "$maclist" ] && {
+ for mac in $maclist; do
+ echo "$mac" >> $macfile
+ done
+ }
+
+ local br brval brstr
+ [ -n "$basic_rate_list" ] && {
+ for br in $basic_rate_list; do
+ brval="$(($br / 100))"
+ [ -n "$brstr" ] && brstr="$brstr "
+ brstr="$brstr$brval"
+ done
+ }
+
+ append base_cfg "preamble=$short_preamble" "$N"
+
+ cat >> "$cfgfile" <<EOF
+ctrl_interface=/var/run/hostapd-$phy
+driver=nl80211
+wmm_ac_bk_cwmin=4
+wmm_ac_bk_cwmax=10
+wmm_ac_bk_aifs=7
+wmm_ac_bk_txop_limit=0
+wmm_ac_bk_acm=0
+wmm_ac_be_aifs=3
+wmm_ac_be_cwmin=4
+wmm_ac_be_cwmax=10
+wmm_ac_be_txop_limit=0
+wmm_ac_be_acm=0
+wmm_ac_vi_aifs=2
+wmm_ac_vi_cwmin=3
+wmm_ac_vi_cwmax=4
+wmm_ac_vi_txop_limit=94
+wmm_ac_vi_acm=0
+wmm_ac_vo_aifs=2
+wmm_ac_vo_cwmin=2
+wmm_ac_vo_cwmax=3
+wmm_ac_vo_txop_limit=47
+wmm_ac_vo_acm=0
+tx_queue_data3_aifs=7
+tx_queue_data3_cwmin=15
+tx_queue_data3_cwmax=1023
+tx_queue_data3_burst=0
+tx_queue_data2_aifs=3
+tx_queue_data2_cwmin=15
+tx_queue_data2_cwmax=63
+tx_queue_data2_burst=0
+tx_queue_data1_aifs=1
+tx_queue_data1_cwmin=7
+tx_queue_data1_cwmax=15
+tx_queue_data1_burst=3.0
+tx_queue_data0_aifs=1
+tx_queue_data0_cwmin=3
+tx_queue_data0_cwmax=7
+tx_queue_data0_burst=1.5
+${hwmode:+hw_mode=$hwmode}
+${channel:+channel=$channel}
+${beacon_int:+beacon_int=$beacon_int}
+${country:+country_code=$country}
+${noscan:+noscan=$noscan}
+${brstr:+basic_rates=$brstr}
+$base_cfg
+
+EOF
+}
+
+mac80211_hostapd_setup_bss() {
+ local phy="$1"
+ local vif="$2"
+
+ hostapd_cfg=
+ cfgfile="/var/run/hostapd-$phy.conf"
+ config_get ifname "$vif" ifname
+
+ if [ -f "$cfgfile" ]; then
+ append hostapd_cfg "bss=$ifname" "$N"
+ else
+ mac80211_hostapd_setup_base "$phy" "$ifname"
+ append hostapd_cfg "interface=$ifname" "$N"
+ fi
+
+ local net_cfg bridge
+ net_cfg="$(find_net_config "$vif")"
+ [ -z "$net_cfg" ] || bridge="$(bridge_interface "$net_cfg")"
+ config_set "$vif" bridge "$bridge"
+
+ hostapd_set_bss_options hostapd_cfg "$vif"
+
+ config_get_bool wds "$vif" wds 0
+ [ "$wds" -gt 0 ] && append hostapd_cfg "wds_sta=1" "$N"
+
+ local macaddr hidden maxassoc wmm
+ config_get macaddr "$vif" macaddr
+ config_get maxassoc "$vif" maxassoc
+ config_get dtim_period "$vif" dtim_period
+ config_get max_listen_int "$vif" max_listen_int
+ config_get_bool hidden "$vif" hidden 0
+ config_get_bool wmm "$vif" wmm 1
+ cat >> /var/run/hostapd-$phy.conf <<EOF
+$hostapd_cfg
+wmm_enabled=$wmm
+bssid=$macaddr
+ignore_broadcast_ssid=$hidden
+${dtim_period:+dtim_period=$dtim_period}
+${max_listen_int:+max_listen_interval=$max_listen_int}
+${maxassoc:+max_num_sta=$maxassoc}
+EOF
+}
+
+mac80211_start_vif() {
+ local vif="$1"
+ local ifname="$2"
+
+ local net_cfg
+ net_cfg="$(find_net_config "$vif")"
+ [ -z "$net_cfg" ] || start_net "$ifname" "$net_cfg"
+
+ set_wifi_up "$vif" "$ifname"
+}
+
+find_mac80211_phy() {
+ local device="$1"
+
+ local macaddr="$(config_get "$device" macaddr | tr 'A-Z' 'a-z')"
+ config_get phy "$device" phy
+ [ -z "$phy" -a -n "$macaddr" ] && {
+ for phy in $(ls /sys/class/ieee80211 2>/dev/null); do
+ [ "$macaddr" = "$(cat /sys/class/ieee80211/${phy}/macaddress)" ] || continue
+ config_set "$device" phy "$phy"
+ break
+ done
+ config_get phy "$device" phy
+ }
+ [ -n "$phy" -a -d "/sys/class/ieee80211/$phy" ] || {
+ echo "PHY for wifi device $1 not found"
+ return 1
+ }
+ [ -z "$macaddr" ] && {
+ config_set "$device" macaddr "$(cat /sys/class/ieee80211/${phy}/macaddress)"
+ }
+ return 0
+}
+
+scan_mac80211() {
+ local device="$1"
+ local adhoc sta ap monitor mesh disabled
+
+ config_get vifs "$device" vifs
+ for vif in $vifs; do
+ config_get_bool disabled "$vif" disabled 0
+ [ $disabled = 0 ] || continue
+
+ config_get mode "$vif" mode
+ case "$mode" in
+ adhoc|sta|ap|monitor|mesh)
+ append $mode "$vif"
+ ;;
+ *) echo "$device($vif): Invalid mode, ignored."; continue;;
+ esac
+ done
+
+ config_set "$device" vifs "${ap:+$ap }${adhoc:+$adhoc }${sta:+$sta }${monitor:+$monitor }${mesh:+$mesh}"
+}
+
+list_phy_interfaces() {
+ local phy="$1"
+ if [ -d "/sys/class/ieee80211/${phy}/device/net" ]; then
+ ls "/sys/class/ieee80211/${phy}/device/net" 2>/dev/null;
+ else
+ ls "/sys/class/ieee80211/${phy}/device" 2>/dev/null | grep net: | sed -e 's,net:,,g'
+ fi
+}
+
+disable_mac80211() (
+ local device="$1"
+
+ find_mac80211_phy "$device" || return 0
+ config_get phy "$device" phy
+
+ set_wifi_down "$device"
+ # kill all running hostapd and wpa_supplicant processes that
+ # are running on atheros/mac80211 vifs
+ for pid in `pidof hostapd`; do
+ grep -E "$phy" /proc/$pid/cmdline >/dev/null && \
+ kill $pid
+ done
+
+ include /lib/network
+ for wdev in $(list_phy_interfaces "$phy"); do
+ [ -f "/var/run/$wdev.pid" ] && kill $(cat /var/run/$wdev.pid) >&/dev/null 2>&1
+ for pid in `pidof wpa_supplicant`; do
+ grep "$wdev" /proc/$pid/cmdline >/dev/null && \
+ kill $pid
+ done
+ ifconfig "$wdev" down 2>/dev/null
+ unbridge "$dev"
+ iw dev "$wdev" del
+ done
+
+ return 0
+)
+
+get_freq() {
+ local phy="$1"
+ local chan="$2"
+ iw "$phy" info | grep -E -m1 "(\* ${chan:-....} MHz${chan:+|\\[$chan\\]})" | grep MHz | awk '{print $2}'
+}
+
+mac80211_generate_mac() {
+ local off="$1"
+ local mac="$2"
+ local oIFS="$IFS"; IFS=":"; set -- $mac; IFS="$oIFS"
+
+ local b2mask=0x00
+ [ $off -gt 0 ] && b2mask=0x02
+
+ printf "%02x:%s:%s:%s:%02x:%02x" \
+ $(( 0x$1 | $b2mask )) $2 $3 $4 \
+ $(( (0x$5 + ($off / 0x100)) % 0x100 )) \
+ $(( (0x$6 + $off) % 0x100 ))
+}
+
+enable_mac80211() {
+ local device="$1"
+ config_get channel "$device" channel
+ config_get vifs "$device" vifs
+ config_get txpower "$device" txpower
+ config_get country "$device" country
+ config_get distance "$device" distance
+ config_get txantenna "$device" txantenna all
+ config_get rxantenna "$device" rxantenna all
+ config_get antenna_gain "$device" antenna_gain 0
+ config_get frag "$device" frag
+ config_get rts "$device" rts
+ find_mac80211_phy "$device" || return 0
+ config_get phy "$device" phy
+ local i=0
+ local macidx=0
+ local apidx=0
+ fixed=""
+ local hostapd_ctrl=""
+
+ [ -n "$country" ] && {
+ iw reg get | grep -q "^country $country:" || {
+ iw reg set "$country"
+ sleep 1
+ }
+ }
+
+ config_get chanbw "$device" chanbw
+ [ -n "$chanbw" -a -d /sys/kernel/debug/ieee80211/$phy/ath9k ] && echo "$chanbw" > /sys/kernel/debug/ieee80211/$phy/ath9k/chanbw
+ [ -n "$chanbw" -a -d /sys/kernel/debug/ieee80211/$phy/ath5k ] && echo "$chanbw" > /sys/kernel/debug/ieee80211/$phy/ath5k/bwmode
+
+ [ "$channel" = "auto" -o "$channel" = "0" ] || {
+ fixed=1
+ }
+
+ iw phy "$phy" set antenna $txantenna $rxantenna >/dev/null 2>&1
+ iw phy "$phy" set antenna_gain $antenna_gain
+
+ [ -n "$distance" ] && iw phy "$phy" set distance "$distance"
+ [ -n "$frag" ] && iw phy "$phy" set frag "${frag%%.*}"
+ [ -n "$rts" ] && iw phy "$phy" set rts "${rts%%.*}"
+
+ export channel fixed
+ # convert channel to frequency
+ local freq="$(get_freq "$phy" "${fixed:+$channel}")"
+
+ wifi_fixup_hwmode "$device" "g"
+ for vif in $vifs; do
+ config_get ifname "$vif" ifname
+ [ -n "$ifname" ] || {
+ [ $i -gt 0 ] && ifname="wlan${phy#phy}-$i" || ifname="wlan${phy#phy}"
+ }
+ config_set "$vif" ifname "$ifname"
+
+ config_get mode "$vif" mode
+ config_get ssid "$vif" ssid
+
+ # It is far easier to delete and create the desired interface
+ case "$mode" in
+ adhoc)
+ iw phy "$phy" interface add "$ifname" type adhoc
+ ;;
+ ap)
+ # Hostapd will handle recreating the interface and
+ # it's accompanying monitor
+ apidx="$(($apidx + 1))"
+ [ "$apidx" -gt 1 ] || iw phy "$phy" interface add "$ifname" type managed
+ ;;
+ mesh)
+ config_get mesh_id "$vif" mesh_id
+ iw phy "$phy" interface add "$ifname" type mp mesh_id "$mesh_id"
+ ;;
+ monitor)
+ iw phy "$phy" interface add "$ifname" type monitor
+ ;;
+ sta)
+ local wdsflag
+ config_get_bool wds "$vif" wds 0
+ [ "$wds" -gt 0 ] && wdsflag="4addr on"
+ iw phy "$phy" interface add "$ifname" type managed $wdsflag
+ config_get_bool powersave "$vif" powersave 0
+ [ "$powersave" -gt 0 ] && powersave="on" || powersave="off"
+ iw "$ifname" set power_save "$powersave"
+ ;;
+ esac
+
+ # All interfaces must have unique mac addresses
+ # which can either be explicitly set in the device
+ # section, or automatically generated
+ config_get macaddr "$device" macaddr
+ config_get vif_mac "$vif" macaddr
+ [ -n "$vif_mac" ] || {
+ vif_mac="$(mac80211_generate_mac $macidx $macaddr)"
+ macidx="$(($macidx + 1))"
+ }
+ [ "$mode" = "ap" ] || ifconfig "$ifname" hw ether "$vif_mac"
+ config_set "$vif" macaddr "$vif_mac"
+
+ # !! ap !!
+ #
+ # ALL ap functionality will be passed to hostapd
+ #
+ # !! station !!
+ #
+ # ALL station functionality will be passed to wpa_supplicant
+ #
+ if [ ! "$mode" = "ap" ]; then
+ # We attempt to set the channel for all interfaces, although
+ # mac80211 may not support it or the driver might not yet
+ # for ap mode this is handled by hostapd
+ [ -n "$fixed" -a -n "$channel" ] && iw dev "$ifname" set channel "$channel"
+ fi
+
+ i=$(($i + 1))
+ done
+
+ local start_hostapd=
+ rm -f /var/run/hostapd-$phy.conf
+ for vif in $vifs; do
+ config_get mode "$vif" mode
+ [ "$mode" = "ap" ] || continue
+ mac80211_hostapd_setup_bss "$phy" "$vif"
+ start_hostapd=1
+ done
+
+ [ -n "$start_hostapd" ] && {
+ hostapd -P /var/run/wifi-$phy.pid -B /var/run/hostapd-$phy.conf || {
+ echo "Failed to start hostapd for $phy"
+ return
+ }
+ sleep 2
+
+ for vif in $vifs; do
+ config_get mode "$vif" mode
+ config_get ifname "$vif" ifname
+ [ "$mode" = "ap" ] || continue
+ hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd-$phy/$ifname}"
+ mac80211_start_vif "$vif" "$ifname"
+ done
+ }
+
+ for vif in $vifs; do
+ config_get mode "$vif" mode
+ config_get ifname "$vif" ifname
+ [ "$mode" = "ap" ] || ifconfig "$ifname" up
+
+ config_get vif_txpower "$vif" txpower
+ # use vif_txpower (from wifi-iface) to override txpower (from
+ # wifi-device) if the latter doesn't exist
+ txpower="${txpower:-$vif_txpower}"
+ [ -z "$txpower" ] || iw dev "$ifname" set txpower fixed "${txpower%%.*}00"
+
+ case "$mode" in
+ adhoc)
+ config_get bssid "$vif" bssid
+ config_get ssid "$vif" ssid
+ config_get beacon_int "$device" beacon_int
+ config_get basic_rate_list "$device" basic_rate
+ config_get encryption "$vif" encryption
+ config_get key "$vif" key 1
+ config_get mcast_rate "$vif" mcast_rate
+ config_get htmode "$device" htmode
+ case "$htmode" in
+ HT20|HT40+|HT40-) ;;
+ *) htmode= ;;
+ esac
+
+
+ local keyspec=""
+ [ "$encryption" == "psk" -o "$encryption" == "psk2" ] && {
+ if eval "type wpa_supplicant_setup_vif" 2>/dev/null >/dev/null; then
+ wpa_supplicant_setup_vif "$vif" nl80211 "${hostapd_ctrl:+-H $hostapd_ctrl}" $freq $htmode || {
+ echo "enable_mac80211($device): Failed to set up wpa_supplicant for interface $ifname" >&2
+ # make sure this wifi interface won't accidentally stay open without encryption
+ ifconfig "$ifname" down
+ }
+ # wpa_supplicant will bring the iface up
+ continue
+ fi
+ }
+
+ [ "$encryption" == "wep" ] && {
+ case "$key" in
+ [1234])
+ local idx
+ for idx in 1 2 3 4; do
+ local ikey
+ config_get ikey "$vif" "key$idx"
+
+ [ -n "$ikey" ] && {
+ ikey="$(($idx - 1)):$(prepare_key_wep "$ikey")"
+ [ $idx -eq $key ] && ikey="d:$ikey"
+ append keyspec "$ikey"
+ }
+ done
+ ;;
+ *) append keyspec "d:0:$(prepare_key_wep "$key")" ;;
+ esac
+ }
+
+ local br brval brsub brstr
+ [ -n "$basic_rate_list" ] && {
+ for br in $basic_rate_list; do
+ brval="$(($br / 1000))"
+ brsub="$((($br / 100) % 10))"
+ [ "$brsub" -gt 0 ] && brval="$brval.$brsub"
+ [ -n "$brstr" ] && brstr="$brstr,"
+ brstr="$brstr$brval"
+ done
+ }
+
+ local mcval=""
+ [ -n "$mcast_rate" ] && {
+ mcval="$(($mcast_rate / 1000))"
+ mcsub="$(( ($mcast_rate / 100) % 10 ))"
+ [ "$mcsub" -gt 0 ] && mcval="$mcval.$mcsub"
+ }
+
+ iw dev "$ifname" ibss join "$ssid" $freq $htmode \
+ ${fixed:+fixed-freq} $bssid \
+ ${beacon_int:+beacon-interval $beacon_int} \
+ ${brstr:+basic-rates $brstr} \
+ ${mcval:+mcast-rate $mcval} \
+ ${keyspec:+keys $keyspec}
+ ;;
+ sta)
+ if eval "type wpa_supplicant_setup_vif" 2>/dev/null >/dev/null; then
+ wpa_supplicant_setup_vif "$vif" nl80211 "${hostapd_ctrl:+-H $hostapd_ctrl}" || {
+ echo "enable_mac80211($device): Failed to set up wpa_supplicant for interface $ifname" >&2
+ # make sure this wifi interface won't accidentally stay open without encryption
+ ifconfig "$ifname" down
+ continue
+ }
+ fi
+ ;;
+ esac
+ [ "$mode" = "ap" ] || mac80211_start_vif "$vif" "$ifname"
+ done
+
+}
+
+
+check_mac80211_device() {
+ config_get phy "$1" phy
+ [ -z "$phy" ] && {
+ find_mac80211_phy "$1" >/dev/null || return 0
+ config_get phy "$1" phy
+ }
+ [ "$phy" = "$dev" ] && found=1
+}
+
+detect_mac80211() {
+ devidx=0
+ config_load wireless
+ while :; do
+ config_get type "radio$devidx" type
+ [ -n "$type" ] || break
+ devidx=$(($devidx + 1))
+ done
+ for dev in $(ls /sys/class/ieee80211); do
+ found=0
+ config_foreach check_mac80211_device wifi-device
+ [ "$found" -gt 0 ] && continue
+
+ mode_11n=""
+ mode_band="g"
+ channel="11"
+ ht_cap=0
+ for cap in $(iw phy "$dev" info | grep 'Capabilities:' | cut -d: -f2); do
+ ht_cap="$(($ht_cap | $cap))"
+ done
+ ht_capab="";
+ [ "$ht_cap" -gt 0 ] && {
+ mode_11n="n"
+ append ht_capab " option htmode HT20" "$N"
+
+ list=" list ht_capab"
+ [ "$(($ht_cap & 1))" -eq 1 ] && append ht_capab "$list LDPC" "$N"
+ [ "$(($ht_cap & 16))" -eq 16 ] && append ht_capab "$list GF" "$N"
+ [ "$(($ht_cap & 32))" -eq 32 ] && append ht_capab "$list SHORT-GI-20" "$N"
+ [ "$(($ht_cap & 64))" -eq 64 ] && append ht_capab "$list SHORT-GI-40" "$N"
+ [ "$(($ht_cap & 128))" -eq 128 ] && append ht_capab "$list TX-STBC" "$N"
+ [ "$(($ht_cap & 768))" -eq 256 ] && append ht_capab "$list RX-STBC1" "$N"
+ [ "$(($ht_cap & 768))" -eq 512 ] && append ht_capab "$list RX-STBC12" "$N"
+ [ "$(($ht_cap & 768))" -eq 768 ] && append ht_capab "$list RX-STBC123" "$N"
+ [ "$(($ht_cap & 4096))" -eq 4096 ] && append ht_capab "$list DSSS_CCK-40" "$N"
+ }
+ iw phy "$dev" info | grep -q '2412 MHz' || { mode_band="a"; channel="36"; }
+
+ cat <<EOF
+config wifi-device radio$devidx
+ option type mac80211
+ option channel ${channel}
+ option macaddr $(cat /sys/class/ieee80211/${dev}/macaddress)
+ option hwmode 11${mode_11n}${mode_band}
+$ht_capab
+ # REMOVE THIS LINE TO ENABLE WIFI:
+ option disabled 1
+
+config wifi-iface
+ option device radio$devidx
+ option network lan
+ option mode ap
+ option ssid OpenWrt
+ option encryption none
+
+EOF
+ devidx=$(($devidx + 1))
+ done
+}
+
diff --git a/package/mac80211/files/regdb.txt b/package/mac80211/files/regdb.txt
new file mode 100644
index 000000000..b250e6926
--- /dev/null
+++ b/package/mac80211/files/regdb.txt
@@ -0,0 +1,697 @@
+# This is the world regulatory domain
+country 00:
+ (2402 - 2472 @ 40), (3, 20)
+ # Channel 12 - 13. No HT40 channel fits here
+ (2457 - 2482 @ 20), (3, 20), PASSIVE-SCAN, NO-IBSS
+ # Channel 14. Only JP enables this and for 802.11b only
+ (2474 - 2494 @ 20), (3, 20), PASSIVE-SCAN, NO-IBSS, NO-OFDM
+ # Channel 36 - 48
+ (5170 - 5250 @ 40), (3, 20)
+ # NB: 5260 MHz - 5700 MHz requies DFS
+ # Channel 149 - 165
+ (5735 - 5835 @ 40), (3, 20), PASSIVE-SCAN, NO-IBSS
+
+
+country AE:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country AL:
+ (2402 - 2482 @ 20), (N/A, 20)
+
+country AM:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 20), (N/A, 18)
+ (5250 - 5330 @ 20), (N/A, 18), DFS
+
+country AN:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country AR:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 20), DFS
+ (5490 - 5710 @ 40), (3, 20), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country AT: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country AU:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (3, 23)
+ (5250 - 5330 @ 40), (3, 23), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country AW:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country AZ:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 18)
+ (5250 - 5330 @ 40), (N/A, 18), DFS
+
+country BA: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country BB:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (3, 23)
+ (5250 - 5330 @ 40), (3, 23), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country BD:
+ (2402 - 2482 @ 40), (N/A, 20)
+
+country BE: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country BG: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 23)
+ (5250 - 5290 @ 40), (N/A, 23), DFS
+ (5490 - 5710 @ 40), (N/A, 30), DFS
+
+country BH:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 20), (N/A, 20)
+ (5250 - 5330 @ 20), (N/A, 20), DFS
+ (5735 - 5835 @ 20), (N/A, 20)
+
+country BL:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 18)
+ (5250 - 5330 @ 40), (N/A, 18), DFS
+
+country BN:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5735 - 5835 @ 40), (N/A, 30)
+
+country BO:
+ (2402 - 2482 @ 40), (N/A, 30)
+ (5735 - 5835 @ 40), (N/A, 30)
+
+country BR:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 20), DFS
+ (5490 - 5710 @ 40), (3, 20), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country BY:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country BZ:
+ (2402 - 2482 @ 40), (N/A, 30)
+ (5735 - 5835 @ 40), (N/A, 30)
+
+country CA:
+ (2402 - 2472 @ 40), (3, 27)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 20), DFS
+ (5490 - 5710 @ 40), (3, 20), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country CH: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country CL:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5735 - 5835 @ 40), (N/A, 20)
+
+country CN:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5735 - 5835 @ 40), (N/A, 30)
+
+country CO:
+ (2402 - 2472 @ 40), (3, 27)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 23), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country CR:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 20), (3, 17)
+ (5250 - 5330 @ 20), (3, 23), DFS
+ (5735 - 5835 @ 20), (3, 30)
+
+country CS:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country CY: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+# Data from http://www.ctu.eu/164/download/VOR/VOR-12-08-2005-34.pdf
+# and http://www.ctu.eu/164/download/VOR/VOR-12-05-2007-6-AN.pdf
+# Power at 5250 - 5350 MHz and 5470 - 5725 MHz can be doubled if TPC is
+# implemented.
+country CZ: DFS-ETSI
+ (2400 - 2483.5 @ 40), (N/A, 100 mW)
+ (5150 - 5250 @ 40), (N/A, 200 mW), NO-OUTDOOR
+ (5250 - 5350 @ 40), (N/A, 100 mW), NO-OUTDOOR, DFS
+ (5470 - 5725 @ 40), (N/A, 500 mW), DFS
+
+# Data from "Frequenznutzungsplan" (as published in April 2008), downloaded from
+# http://www.bundesnetzagentur.de/cae/servlet/contentblob/38448/publicationFile/2659/Frequenznutzungsplan2008_Id17448pdf.pdf
+# For the 5GHz range also see
+# http://www.bundesnetzagentur.de/cae/servlet/contentblob/38216/publicationFile/6579/WLAN5GHzVfg7_2010_28042010pdf.pdf
+# The values have been reduced by a factor of 2 (3db) for non TPC devices
+# (in other words: devices with TPC can use twice the tx power of this table).
+# Note that the docs do not require TPC for 5150--5250; the reduction to
+# 100mW thus is not strictly required -- however the conservative 100mW
+# limit is used here as the non-interference with radar and satellite
+# apps relies on the attenuation by the building walls only in the
+# absence of DFS; the neighbour countries have 100mW limit here as well.
+
+country DE: DFS-ETSI
+ # entries 279004 and 280006
+ (2400 - 2483.5 @ 40), (N/A, 100 mW)
+ # entry 303005
+ (5150 - 5250 @ 40), (N/A, 100 mW), NO-OUTDOOR
+ # entries 304002 and 305002
+ (5250 - 5350 @ 40), (N/A, 100 mW), NO-OUTDOOR, DFS
+ # entries 308002, 309001 and 310003
+ (5470 - 5725 @ 40), (N/A, 500 mW), DFS
+
+country DK: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country DO:
+ (2402 - 2472 @ 40), (3, 27)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 23), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country DZ:
+ (2402 - 2482 @ 40), (N/A, 20)
+
+country EC:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 20), (3, 17)
+ (5250 - 5330 @ 20), (3, 23), DFS
+ (5735 - 5835 @ 20), (3, 30)
+
+country EE: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country EG:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 20), (N/A, 20)
+ (5250 - 5330 @ 20), (N/A, 20), DFS
+
+country ES: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country FI: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country FR: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country GE:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 18)
+ (5250 - 5330 @ 40), (N/A, 18), DFS
+
+country GB: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country GD:
+ (2402 - 2472 @ 40), (3, 27)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 20), DFS
+ (5490 - 5710 @ 40), (3, 20), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country GR: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country GL: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 20), (N/A, 20)
+ (5250 - 5330 @ 20), (N/A, 20), DFS
+ (5490 - 5710 @ 20), (N/A, 27), DFS
+
+country GT:
+ (2402 - 2472 @ 40), (3, 27)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 23), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country GU:
+ (2402 - 2472 @ 40), (3, 27)
+ (5170 - 5250 @ 20), (3, 17)
+ (5250 - 5330 @ 20), (3, 23), DFS
+ (5735 - 5835 @ 20), (3, 30)
+
+country HN:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 20), DFS
+ (5490 - 5710 @ 40), (3, 20), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country HK:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 20), DFS
+ (5490 - 5710 @ 40), (3, 20), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country HR: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country HT:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country HU: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country ID:
+ (2402 - 2482 @ 40), (N/A, 20)
+
+country IE: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country IL:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5150 - 5250 @ 40), (N/A, 200 mW), NO-OUTDOOR
+ (5250 - 5350 @ 40), (N/A, 200 mW), NO-OUTDOOR, DFS
+
+country IN:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5735 - 5835 @ 40), (N/A, 20)
+
+country IS: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country IR:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5735 - 5835 @ 40), (N/A, 30)
+
+country IT: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country JM:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 20), DFS
+ (5490 - 5710 @ 40), (3, 20), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country JP:
+ (2402 - 2472 @ 40), (N/A, 20)
+ (2457 - 2482 @ 20), (N/A, 20)
+ (2474 - 2494 @ 20), (N/A, 20), NO-OFDM
+ (4910 - 4930 @ 10), (N/A, 23)
+ (4910 - 4990 @ 40), (N/A, 23)
+ (4930 - 4950 @ 10), (N/A, 23)
+ (5030 - 5045 @ 10), (N/A, 23)
+ (5030 - 5090 @ 40), (N/A, 23)
+ (5050 - 5060 @ 10), (N/A, 23)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 23), DFS
+
+country JO:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 18)
+
+country KE:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5735 - 5835 @ 40), (N/A, 30)
+
+country KH:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country KP:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5330 @ 40), (3, 20)
+ (5160 - 5250 @ 40), (3, 20), DFS
+ (5490 - 5630 @ 40), (3, 30), DFS
+ (5735 - 5815 @ 40), (3, 30)
+
+country KR:
+ (2402 - 2482 @ 20), (N/A, 20)
+ (5170 - 5250 @ 20), (3, 20)
+ (5250 - 5330 @ 20), (3, 20), DFS
+ (5490 - 5630 @ 20), (3, 30), DFS
+ (5735 - 5815 @ 20), (3, 30)
+
+country KW:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+
+country KZ:
+ (2402 - 2482 @ 40), (N/A, 20)
+
+country LB:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5735 - 5835 @ 40), (N/A, 30)
+
+country LI: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country LK:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 20), (3, 17)
+ (5250 - 5330 @ 20), (3, 20), DFS
+ (5490 - 5710 @ 20), (3, 20), DFS
+ (5735 - 5835 @ 20), (3, 30)
+
+country LT: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country LU: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country LV: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country MC: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 18)
+ (5250 - 5330 @ 40), (N/A, 18), DFS
+
+country MA:
+ (2402 - 2482 @ 40), (N/A, 20)
+
+country MO:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (3, 23)
+ (5250 - 5330 @ 40), (3, 23), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country MK: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country MT: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country MY:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 30), DFS
+ (5735 - 5835 @ 40), (N/A, 30)
+
+country MX:
+ (2402 - 2472 @ 40), (3, 27)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 23), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country NL: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20), NO-OUTDOOR
+ (5250 - 5330 @ 40), (N/A, 20), NO-OUTDOOR, DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country NO: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country NP:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5735 - 5835 @ 40), (N/A, 30)
+
+country NZ:
+ (2402 - 2482 @ 40), (N/A, 30)
+ (5170 - 5250 @ 20), (3, 23)
+ (5250 - 5330 @ 20), (3, 23), DFS
+ (5735 - 5835 @ 20), (3, 30)
+
+country OM:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 20), DFS
+ (5490 - 5710 @ 40), (3, 20), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country PA:
+ (2402 - 2472 @ 40), (3, 27)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 23), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country PE:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5735 - 5835 @ 40), (N/A, 30)
+
+country PG:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 23), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country PH:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5735 - 5835 @ 40), (N/A, 30)
+
+country PK:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5735 - 5835 @ 40), (N/A, 30)
+
+country PL: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country PT: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country PR:
+ (2402 - 2472 @ 40), (3, 27)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 23), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country QA:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5735 - 5835 @ 40), (N/A, 30)
+
+country RO: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country RU:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5735 - 5835 @ 20), (N/A, 30)
+
+country SA:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 20), (3, 23)
+ (5250 - 5330 @ 20), (3, 23), DFS
+ (5735 - 5835 @ 20), (3, 30)
+
+country SE: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country SG:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5735 - 5835 @ 40), (N/A, 20)
+
+country SI: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country SK: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+ (5490 - 5710 @ 40), (N/A, 27), DFS
+
+country SV:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 20), (3, 17)
+ (5250 - 5330 @ 20), (3, 23), DFS
+ (5735 - 5835 @ 20), (3, 30)
+
+country SY:
+ (2402 - 2482 @ 40), (N/A, 20)
+
+country TW:
+ (2402 - 2472 @ 40), (3, 27)
+ (5270 - 5330 @ 40), (3, 17), DFS
+ (5735 - 5815 @ 40), (3, 30)
+
+country TH:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 20), DFS
+ (5490 - 5710 @ 40), (3, 20), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country TT:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 20), DFS
+ (5490 - 5710 @ 40), (3, 20), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country TN:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 20), (N/A, 20)
+ (5250 - 5330 @ 20), (N/A, 20), DFS
+
+country TR: DFS-ETSI
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 20), (N/A, 20)
+ (5250 - 5330 @ 20), (N/A, 20), DFS
+
+country UA:
+ (2402 - 2482 @ 40), (N/A, 20)
+
+country US: DFS-FCC
+ (2402 - 2472 @ 40), (3, 27)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 20), DFS
+ (5490 - 5600 @ 40), (3, 20), DFS
+ (5650 - 5710 @ 40), (3, 20), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country UY:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 20), DFS
+ (5490 - 5710 @ 40), (3, 20), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country UZ:
+ (2402 - 2472 @ 40), (3, 27)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 20), DFS
+ (5490 - 5710 @ 40), (3, 20), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country VE:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5735 - 5815 @ 40), (N/A, 23)
+
+country VN:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (N/A, 20)
+ (5250 - 5330 @ 40), (N/A, 20), DFS
+
+country YE:
+ (2402 - 2482 @ 40), (N/A, 20)
+
+country ZA:
+ (2402 - 2482 @ 40), (N/A, 20)
+ (5170 - 5250 @ 40), (3, 17)
+ (5250 - 5330 @ 40), (3, 20), DFS
+ (5490 - 5710 @ 40), (3, 20), DFS
+ (5735 - 5835 @ 40), (3, 30)
+
+country ZW:
+ (2402 - 2482 @ 40), (N/A, 20)
+
diff --git a/package/mac80211/patches/000-disable_ethernet.patch b/package/mac80211/patches/000-disable_ethernet.patch
new file mode 100644
index 000000000..08f908b10
--- /dev/null
+++ b/package/mac80211/patches/000-disable_ethernet.patch
@@ -0,0 +1,12 @@
+--- a/Makefile
++++ b/Makefile
+@@ -45,9 +45,6 @@ obj-$(CONFIG_COMPAT_WIRELESS_MODULES) +=
+
+ obj-$(CONFIG_COMPAT_NET_USB_MODULES) += drivers/net/usb/
+
+-obj-$(CONFIG_COMPAT_NETWORK_MODULES) += drivers/net/ethernet/atheros/
+-obj-$(CONFIG_COMPAT_NETWORK_MODULES) += drivers/net/ethernet/broadcom/
+-
+ obj-$(CONFIG_COMPAT_VAR_MODULES) += drivers/ssb/
+ obj-$(CONFIG_COMPAT_VAR_MODULES) += drivers/bcma/
+ obj-$(CONFIG_COMPAT_VAR_MODULES) += drivers/misc/eeprom/
diff --git a/package/mac80211/patches/001-disable_b44.patch b/package/mac80211/patches/001-disable_b44.patch
new file mode 100644
index 000000000..389dac1ae
--- /dev/null
+++ b/package/mac80211/patches/001-disable_b44.patch
@@ -0,0 +1,13 @@
+--- a/config.mk
++++ b/config.mk
+@@ -377,8 +377,8 @@ export CONFIG_B43_BCMA_EXTRA=y
+
+ export CONFIG_P54_PCI=m
+
+-export CONFIG_B44=m
+-export CONFIG_B44_PCI=y
++# export CONFIG_B44=m
++# export CONFIG_B44_PCI=y
+
+ export CONFIG_RTL8180=m
+
diff --git a/package/mac80211/patches/002-disable_rfkill.patch b/package/mac80211/patches/002-disable_rfkill.patch
new file mode 100644
index 000000000..685006bd5
--- /dev/null
+++ b/package/mac80211/patches/002-disable_rfkill.patch
@@ -0,0 +1,38 @@
+--- a/config.mk
++++ b/config.mk
+@@ -78,7 +78,7 @@ endif # build check
+ endif # kernel Makefile check
+
+ # These both are needed by 802.11 and bluetooth so enable
+- export CONFIG_COMPAT_RFKILL=y
++# export CONFIG_COMPAT_RFKILL=y
+
+ ifeq ($(CONFIG_MAC80211),y)
+ $(error "ERROR: you have MAC80211 compiled into the kernel, CONFIG_MAC80211=y, as such you cannot replace its mac80211 driver. You need this set to CONFIG_MAC80211=m. If you are using Fedora upgrade your kernel as later version should this set as modular. For further information on Fedora see https://bugzilla.redhat.com/show_bug.cgi?id=470143. If you are using your own kernel recompile it and make mac80211 modular")
+@@ -690,10 +690,10 @@ endif #CONFIG_COMPAT_KERNEL_2_6_27
+ # We need the backported rfkill module on kernel < 2.6.31.
+ # In more recent kernel versions use the in kernel rfkill module.
+ ifdef CONFIG_COMPAT_KERNEL_2_6_31
+-export CONFIG_RFKILL_BACKPORT=m
++#export CONFIG_RFKILL_BACKPORT=m
+ ifdef CONFIG_LEDS_TRIGGERS
+-export CONFIG_RFKILL_BACKPORT_LEDS=y
++#export CONFIG_RFKILL_BACKPORT_LEDS=y
+ endif #CONFIG_LEDS_TRIGGERS
+-export CONFIG_RFKILL_BACKPORT_INPUT=y
++#export CONFIG_RFKILL_BACKPORT_INPUT=y
+ endif #CONFIG_COMPAT_KERNEL_2_6_31
+
+--- a/include/linux/rfkill.h
++++ b/include/linux/rfkill.h
+@@ -3,6 +3,10 @@
+
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31))
+
++#undef CONFIG_RFKILL
++#undef CONFIG_RFKILL_LEDS
++#undef CONFIG_RFKILL_MODULE
++
+ #include_next <linux/rfkill.h>
+
+ #else
diff --git a/package/mac80211/patches/003-disable_bt.patch b/package/mac80211/patches/003-disable_bt.patch
new file mode 100644
index 000000000..b56ccbdc6
--- /dev/null
+++ b/package/mac80211/patches/003-disable_bt.patch
@@ -0,0 +1,15 @@
+--- a/config.mk
++++ b/config.mk
+@@ -100,9 +100,9 @@ ifndef CONFIG_COMPAT_KERNEL_2_6_27
+ ifeq ($(CONFIG_BT),y)
+ # we'll ignore compiling bluetooth
+ else
+- export CONFIG_COMPAT_BLUETOOTH=y
+- export CONFIG_COMPAT_BLUETOOTH_MODULES=m
+- export CONFIG_HID_GENERIC=m
++# export CONFIG_COMPAT_BLUETOOTH=y
++# export CONFIG_COMPAT_BLUETOOTH_MODULES=m
++# export CONFIG_HID_GENERIC=m
+ endif
+ endif #CONFIG_COMPAT_KERNEL_2_6_27
+
diff --git a/package/mac80211/patches/005-disable_ssb_build.patch b/package/mac80211/patches/005-disable_ssb_build.patch
new file mode 100644
index 000000000..d42a6121d
--- /dev/null
+++ b/package/mac80211/patches/005-disable_ssb_build.patch
@@ -0,0 +1,49 @@
+--- a/Makefile
++++ b/Makefile
+@@ -45,7 +45,6 @@ obj-$(CONFIG_COMPAT_WIRELESS_MODULES) +=
+
+ obj-$(CONFIG_COMPAT_NET_USB_MODULES) += drivers/net/usb/
+
+-obj-$(CONFIG_COMPAT_VAR_MODULES) += drivers/ssb/
+ obj-$(CONFIG_COMPAT_VAR_MODULES) += drivers/bcma/
+ obj-$(CONFIG_COMPAT_VAR_MODULES) += drivers/misc/eeprom/
+
+--- a/config.mk
++++ b/config.mk
+@@ -3,7 +3,7 @@ ifeq ($(wildcard $(KLIB_BUILD)/.config),
+ export CONFIG_PCI=y
+ export CONFIG_USB=y
+ export CONFIG_PCMCIA=y
+- export CONFIG_SSB=m
++# export CONFIG_SSB=m
+ else
+ include $(KLIB_BUILD)/.config
+ endif
+@@ -353,7 +353,8 @@ export CONFIG_IPW2200_QOS=y
+ # % echo 1 > /sys/bus/pci/drivers/ipw2200/*/rtap_iface
+ endif #CONFIG_WIRELESS_EXT
+
+-ifdef CONFIG_SSB
++# disabled
++ifdef __CONFIG_SSB
+ # Sonics Silicon Backplane
+ export CONFIG_SSB_SPROM=y
+
+@@ -366,7 +367,7 @@ endif #CONFIG_PCMCIA
+ # export CONFIG_SSB_DEBUG=y
+ export CONFIG_SSB_DRIVER_PCICORE=y
+ export CONFIG_B43_SSB=y
+-endif #CONFIG_SSB
++endif #__CONFIG_SSB
+
+ export CONFIG_BCMA=m
+ export CONFIG_BCMA_BLOCKIO=y
+@@ -580,7 +581,7 @@ endif #CONFIG_SPI_MASTER end of SPI driv
+
+ ifdef CONFIG_MMC
+
+-export CONFIG_SSB_SDIOHOST=y
++# export CONFIG_SSB_SDIOHOST=y
+ export CONFIG_B43_SDIO=y
+
+ ifdef CONFIG_CRC7
diff --git a/package/mac80211/patches/006-disable_bcma_build.patch b/package/mac80211/patches/006-disable_bcma_build.patch
new file mode 100644
index 000000000..da11ad455
--- /dev/null
+++ b/package/mac80211/patches/006-disable_bcma_build.patch
@@ -0,0 +1,30 @@
+--- a/Makefile
++++ b/Makefile
+@@ -45,7 +45,6 @@ obj-$(CONFIG_COMPAT_WIRELESS_MODULES) +=
+
+ obj-$(CONFIG_COMPAT_NET_USB_MODULES) += drivers/net/usb/
+
+-obj-$(CONFIG_COMPAT_VAR_MODULES) += drivers/bcma/
+ obj-$(CONFIG_COMPAT_VAR_MODULES) += drivers/misc/eeprom/
+
+ ifeq ($(CONFIG_STAGING_EXCLUDE_BUILD),)
+--- a/config.mk
++++ b/config.mk
+@@ -369,12 +369,12 @@ export CONFIG_SSB_DRIVER_PCICORE=y
+ export CONFIG_B43_SSB=y
+ endif #__CONFIG_SSB
+
+-export CONFIG_BCMA=m
+-export CONFIG_BCMA_BLOCKIO=y
+-export CONFIG_BCMA_HOST_PCI=y
++# export CONFIG_BCMA=m
++# export CONFIG_BCMA_BLOCKIO=y
++# export CONFIG_BCMA_HOST_PCI=y
+ # export CONFIG_BCMA_DEBUG=y
+-export CONFIG_B43_BCMA=y
+-export CONFIG_B43_BCMA_EXTRA=y
++# export CONFIG_B43_BCMA=y
++# export CONFIG_B43_BCMA_EXTRA=y
+
+ export CONFIG_P54_PCI=m
+
diff --git a/package/mac80211/patches/007-remove_misc_drivers.patch b/package/mac80211/patches/007-remove_misc_drivers.patch
new file mode 100644
index 000000000..9e7f65166
--- /dev/null
+++ b/package/mac80211/patches/007-remove_misc_drivers.patch
@@ -0,0 +1,61 @@
+--- a/config.mk
++++ b/config.mk
+@@ -241,7 +241,7 @@ $(warning "WARNING: CONFIG_CFG80211_WEXT
+ endif #CONFIG_WIRELESS_EXT
+
+ ifdef CONFIG_STAGING
+-export CONFIG_COMPAT_STAGING=m
++# export CONFIG_COMPAT_STAGING=m
+ endif #CONFIG_STAGING
+
+ # mac80211 test driver
+@@ -406,12 +406,12 @@ endif #CONFIG_CRC_ITU_T
+ export CONFIG_MWL8K=m
+
+ # Ethernet drivers go here
+-export CONFIG_ATL1=m
+-export CONFIG_ATL2=m
+-export CONFIG_ATL1E=m
++# export CONFIG_ATL1=m
++# export CONFIG_ATL2=m
++# export CONFIG_ATL1E=m
+ ifndef CONFIG_COMPAT_KERNEL_2_6_28
+-export CONFIG_ATL1C=m
+-export CONFIG_ALX=m
++# export CONFIG_ATL1C=m
++# export CONFIG_ALX=m
+ endif #CONFIG_COMPAT_KERNEL_2_6_28
+
+ ifdef CONFIG_WIRELESS_EXT
+@@ -472,21 +472,21 @@ endif #CONFIG_COMPAT_KERNEL_2_6_29
+ # Note: this depends on CONFIG_USB_NET_RNDIS_HOST and CONFIG_USB_NET_CDCETHER
+ # it also requires new RNDIS_HOST and CDC_ETHER modules which we add
+ ifdef CONFIG_COMPAT_KERNEL_2_6_29
+-export CONFIG_USB_COMPAT_USBNET=n
+-export CONFIG_USB_NET_COMPAT_RNDIS_HOST=n
+-export CONFIG_USB_NET_COMPAT_RNDIS_WLAN=n
+-export CONFIG_USB_NET_COMPAT_CDCETHER=n
++# export CONFIG_USB_COMPAT_USBNET=n
++# export CONFIG_USB_NET_COMPAT_RNDIS_HOST=n
++# export CONFIG_USB_NET_COMPAT_RNDIS_WLAN=n
++# export CONFIG_USB_NET_COMPAT_CDCETHER=n
+ else #CONFIG_COMPAT_KERNEL_2_6_29
+-export CONFIG_USB_COMPAT_USBNET=m
++# export CONFIG_USB_COMPAT_USBNET=m
+ ifdef CONFIG_USB_NET_CDCETHER
+-export CONFIG_USB_NET_COMPAT_RNDIS_HOST=m
+-export CONFIG_USB_NET_COMPAT_RNDIS_WLAN=m
++# export CONFIG_USB_NET_COMPAT_RNDIS_HOST=m
++# export CONFIG_USB_NET_COMPAT_RNDIS_WLAN=m
+ endif #CONFIG_USB_NET_CDCETHER
+ ifdef CONFIG_USB_NET_CDCETHER_MODULE
+-export CONFIG_USB_NET_COMPAT_RNDIS_HOST=m
+-export CONFIG_USB_NET_COMPAT_RNDIS_WLAN=m
++# export CONFIG_USB_NET_COMPAT_RNDIS_HOST=m
++# export CONFIG_USB_NET_COMPAT_RNDIS_WLAN=m
+ endif #CONFIG_USB_NET_CDCETHER
+-export CONFIG_USB_NET_COMPAT_CDCETHER=m
++# export CONFIG_USB_NET_COMPAT_CDCETHER=m
+ endif #CONFIG_COMPAT_KERNEL_2_6_29
+
+
diff --git a/package/mac80211/patches/008-disable_mesh.patch b/package/mac80211/patches/008-disable_mesh.patch
new file mode 100644
index 000000000..d5a0ac8e6
--- /dev/null
+++ b/package/mac80211/patches/008-disable_mesh.patch
@@ -0,0 +1,11 @@
+--- a/config.mk
++++ b/config.mk
+@@ -177,7 +177,7 @@ export CONFIG_MAC80211_LEDS=y
+ endif #CONFIG_LEDS_TRIGGERS
+
+ # enable mesh networking too
+-export CONFIG_MAC80211_MESH=y
++# export CONFIG_MAC80211_MESH=y
+
+ export CONFIG_CFG80211=m
+ export CONFIG_CFG80211_DEFAULT_PS=y
diff --git a/package/mac80211/patches/009-remove_mac80211_module_dependence.patch b/package/mac80211/patches/009-remove_mac80211_module_dependence.patch
new file mode 100644
index 000000000..2bc46c4ed
--- /dev/null
+++ b/package/mac80211/patches/009-remove_mac80211_module_dependence.patch
@@ -0,0 +1,11 @@
+--- a/config.mk
++++ b/config.mk
+@@ -54,7 +54,7 @@ endif
+ ifeq ($(KERNEL_VERSION),2)
+ ifeq ($(shell test $(KERNEL_VERSION) -eq 2 -a $(KERNEL_26SUBLEVEL) -ge 27 -a $(KERNEL_26SUBLEVEL) -le 31 && echo yes),yes)
+ ifeq ($(CONFIG_MAC80211),)
+-$(error "ERROR: Your >=2.6.27 and <= 2.6.31 kernel has CONFIG_MAC80211 disabled, you should have it CONFIG_MAC80211=m if you want to use this thing.")
++# $(error "ERROR: Your >=2.6.27 and <= 2.6.31 kernel has CONFIG_MAC80211 disabled, you should have it CONFIG_MAC80211=m if you want to use this thing.")
+ endif
+ endif
+ endif
diff --git a/package/mac80211/patches/010-no_pcmcia.patch b/package/mac80211/patches/010-no_pcmcia.patch
new file mode 100644
index 000000000..af6a7545b
--- /dev/null
+++ b/package/mac80211/patches/010-no_pcmcia.patch
@@ -0,0 +1,20 @@
+--- a/config.mk
++++ b/config.mk
+@@ -2,7 +2,7 @@ ifeq ($(wildcard $(KLIB_BUILD)/.config),
+ # These will be ignored by compat autoconf
+ export CONFIG_PCI=y
+ export CONFIG_USB=y
+- export CONFIG_PCMCIA=y
++# export CONFIG_PCMCIA=y
+ # export CONFIG_SSB=m
+ else
+ include $(KLIB_BUILD)/.config
+@@ -304,7 +304,7 @@ export CONFIG_B43=m
+ export CONFIG_B43_HWRNG=y
+ export CONFIG_B43_PCI_AUTOSELECT=y
+ ifdef CONFIG_PCMCIA
+-export CONFIG_B43_PCMCIA=y
++# export CONFIG_B43_PCMCIA=y
+ endif #CONFIG_PCMCIA
+ ifdef CONFIG_MAC80211_LEDS
+ export CONFIG_B43_LEDS=y
diff --git a/package/mac80211/patches/011-no_sdio.patch b/package/mac80211/patches/011-no_sdio.patch
new file mode 100644
index 000000000..4d364e045
--- /dev/null
+++ b/package/mac80211/patches/011-no_sdio.patch
@@ -0,0 +1,11 @@
+--- a/config.mk
++++ b/config.mk
+@@ -582,7 +582,7 @@ endif #CONFIG_SPI_MASTER end of SPI driv
+ ifdef CONFIG_MMC
+
+ # export CONFIG_SSB_SDIOHOST=y
+-export CONFIG_B43_SDIO=y
++# export CONFIG_B43_SDIO=y
+
+ ifdef CONFIG_CRC7
+ ifdef CONFIG_WL12XX_PLATFORM_DATA
diff --git a/package/mac80211/patches/013-disable_b43_nphy.patch b/package/mac80211/patches/013-disable_b43_nphy.patch
new file mode 100644
index 000000000..ba37bad95
--- /dev/null
+++ b/package/mac80211/patches/013-disable_b43_nphy.patch
@@ -0,0 +1,13 @@
+--- a/config.mk
++++ b/config.mk
+@@ -310,8 +310,8 @@ ifdef CONFIG_MAC80211_LEDS
+ export CONFIG_B43_LEDS=y
+ endif #CONFIG_MAC80211_LEDS
+ export CONFIG_B43_PHY_LP=y
+-export CONFIG_B43_PHY_N=y
+-export CONFIG_B43_PHY_HT=y
++# export CONFIG_B43_PHY_N=y
++# export CONFIG_B43_PHY_HT=y
+ # export CONFIG_B43_PHY_LCN=y
+ # export CONFIG_B43_DEBUG=y
+
diff --git a/package/mac80211/patches/015-remove-rt2x00-options.patch b/package/mac80211/patches/015-remove-rt2x00-options.patch
new file mode 100644
index 000000000..66c0d67a5
--- /dev/null
+++ b/package/mac80211/patches/015-remove-rt2x00-options.patch
@@ -0,0 +1,20 @@
+--- a/config.mk
++++ b/config.mk
+@@ -385,7 +385,7 @@ export CONFIG_RTL8180=m
+
+ export CONFIG_ADM8211=m
+
+-export CONFIG_RT2X00_LIB_PCI=m
++# export CONFIG_RT2X00_LIB_PCI=m
+ export CONFIG_RT2400PCI=m
+ export CONFIG_RT2500PCI=m
+ ifdef CONFIG_CRC_CCITT
+@@ -528,7 +528,7 @@ export CONFIG_RT2800USB_RT35XX=y
+ export CONFIG_RT2800USB_RT53XX=y
+ export CONFIG_RT2800USB_UNKNOWN=y
+ endif #CONFIG_CRC_CCITT
+-export CONFIG_RT2X00_LIB_USB=m
++# export CONFIG_RT2X00_LIB_USB=m
+ NEED_RT2X00=y
+ # RT73USB requires firmware
+ ifdef CONFIG_CRC_ITU_T
diff --git a/package/mac80211/patches/016-remove_pid_algo.patch b/package/mac80211/patches/016-remove_pid_algo.patch
new file mode 100644
index 000000000..7180a63ce
--- /dev/null
+++ b/package/mac80211/patches/016-remove_pid_algo.patch
@@ -0,0 +1,11 @@
+--- a/config.mk
++++ b/config.mk
+@@ -169,7 +169,7 @@ export CONFIG_MAC80211_RC_DEFAULT_MINSTR
+ # This is the one used by our compat-drivers net/mac80211/rate.c
+ # in case you have and old kernel which is overriding this to pid.
+ export CONFIG_COMPAT_MAC80211_RC_DEFAULT=minstrel_ht
+-export CONFIG_MAC80211_RC_PID=y
++# export CONFIG_MAC80211_RC_PID=y
+ export CONFIG_MAC80211_RC_MINSTREL=y
+ export CONFIG_MAC80211_RC_MINSTREL_HT=y
+ ifdef CONFIG_LEDS_TRIGGERS
diff --git a/package/mac80211/patches/017-remove_ath9k_rc.patch b/package/mac80211/patches/017-remove_ath9k_rc.patch
new file mode 100644
index 000000000..99b520911
--- /dev/null
+++ b/package/mac80211/patches/017-remove_ath9k_rc.patch
@@ -0,0 +1,11 @@
+--- a/config.mk
++++ b/config.mk
+@@ -265,7 +265,7 @@ export CONFIG_ATH9K_COMMON=m
+ # as default once we get minstrel properly tested and blessed by
+ # our systems engineering team. CCK rates also need to be used
+ # for long range considerations.
+-export CONFIG_COMPAT_ATH9K_RATE_CONTROL=y
++# export CONFIG_COMPAT_ATH9K_RATE_CONTROL=y
+
+ export CONFIG_ATH9K_BTCOEX_SUPPORT=y
+
diff --git a/package/mac80211/patches/018-revert_printk_va_format.patch b/package/mac80211/patches/018-revert_printk_va_format.patch
new file mode 100644
index 000000000..fa2237c95
--- /dev/null
+++ b/package/mac80211/patches/018-revert_printk_va_format.patch
@@ -0,0 +1,188 @@
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -341,83 +341,59 @@ static int b43_ratelimit(struct b43_wl *
+
+ void b43info(struct b43_wl *wl, const char *fmt, ...)
+ {
+- struct va_format vaf;
+ va_list args;
+
+ if (b43_modparam_verbose < B43_VERBOSITY_INFO)
+ return;
+ if (!b43_ratelimit(wl))
+ return;
+-
+ va_start(args, fmt);
+-
+- vaf.fmt = fmt;
+- vaf.va = &args;
+-
+- printk(KERN_INFO "b43-%s: %pV",
+- (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+-
++ printk(KERN_INFO "b43-%s: ",
++ (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
++ vprintk(fmt, args);
+ va_end(args);
+ }
+
+ void b43err(struct b43_wl *wl, const char *fmt, ...)
+ {
+- struct va_format vaf;
+ va_list args;
+
+ if (b43_modparam_verbose < B43_VERBOSITY_ERROR)
+ return;
+ if (!b43_ratelimit(wl))
+ return;
+-
+ va_start(args, fmt);
+-
+- vaf.fmt = fmt;
+- vaf.va = &args;
+-
+- printk(KERN_ERR "b43-%s ERROR: %pV",
+- (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+-
++ printk(KERN_ERR "b43-%s ERROR: ",
++ (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
++ vprintk(fmt, args);
+ va_end(args);
+ }
+
+ void b43warn(struct b43_wl *wl, const char *fmt, ...)
+ {
+- struct va_format vaf;
+ va_list args;
+
+ if (b43_modparam_verbose < B43_VERBOSITY_WARN)
+ return;
+ if (!b43_ratelimit(wl))
+ return;
+-
+ va_start(args, fmt);
+-
+- vaf.fmt = fmt;
+- vaf.va = &args;
+-
+- printk(KERN_WARNING "b43-%s warning: %pV",
+- (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+-
++ printk(KERN_WARNING "b43-%s warning: ",
++ (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
++ vprintk(fmt, args);
+ va_end(args);
+ }
+
+ void b43dbg(struct b43_wl *wl, const char *fmt, ...)
+ {
+- struct va_format vaf;
+ va_list args;
+
+ if (b43_modparam_verbose < B43_VERBOSITY_DEBUG)
+ return;
+-
+ va_start(args, fmt);
+-
+- vaf.fmt = fmt;
+- vaf.va = &args;
+-
+- printk(KERN_DEBUG "b43-%s debug: %pV",
+- (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+-
++ printk(KERN_DEBUG "b43-%s debug: ",
++ (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
++ vprintk(fmt, args);
+ va_end(args);
+ }
+
+--- a/drivers/net/wireless/b43legacy/main.c
++++ b/drivers/net/wireless/b43legacy/main.c
+@@ -179,75 +179,52 @@ static int b43legacy_ratelimit(struct b4
+
+ void b43legacyinfo(struct b43legacy_wl *wl, const char *fmt, ...)
+ {
+- struct va_format vaf;
+ va_list args;
+
+ if (!b43legacy_ratelimit(wl))
+ return;
+-
+ va_start(args, fmt);
+-
+- vaf.fmt = fmt;
+- vaf.va = &args;
+-
+- printk(KERN_INFO "b43legacy-%s: %pV",
+- (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+-
++ printk(KERN_INFO "b43legacy-%s: ",
++ (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
++ vprintk(fmt, args);
+ va_end(args);
+ }
+
+ void b43legacyerr(struct b43legacy_wl *wl, const char *fmt, ...)
+ {
+- struct va_format vaf;
+ va_list args;
+
+ if (!b43legacy_ratelimit(wl))
+ return;
+-
+ va_start(args, fmt);
+-
+- vaf.fmt = fmt;
+- vaf.va = &args;
+-
+- printk(KERN_ERR "b43legacy-%s ERROR: %pV",
+- (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+-
++ printk(KERN_ERR "b43legacy-%s ERROR: ",
++ (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
++ vprintk(fmt, args);
+ va_end(args);
+ }
+
+ void b43legacywarn(struct b43legacy_wl *wl, const char *fmt, ...)
+ {
+- struct va_format vaf;
+ va_list args;
+
+ if (!b43legacy_ratelimit(wl))
+ return;
+-
+ va_start(args, fmt);
+-
+- vaf.fmt = fmt;
+- vaf.va = &args;
+-
+- printk(KERN_WARNING "b43legacy-%s warning: %pV",
+- (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+-
++ printk(KERN_WARNING "b43legacy-%s warning: ",
++ (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
++ vprintk(fmt, args);
+ va_end(args);
+ }
+
+ #if B43legacy_DEBUG
+ void b43legacydbg(struct b43legacy_wl *wl, const char *fmt, ...)
+ {
+- struct va_format vaf;
+ va_list args;
+
+ va_start(args, fmt);
+-
+- vaf.fmt = fmt;
+- vaf.va = &args;
+-
+- printk(KERN_DEBUG "b43legacy-%s debug: %pV",
+- (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+-
++ printk(KERN_DEBUG "b43legacy-%s debug: ",
++ (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
++ vprintk(fmt, args);
+ va_end(args);
+ }
+ #endif /* DEBUG */
diff --git a/package/mac80211/patches/019-remove_ath5k_pci_option.patch b/package/mac80211/patches/019-remove_ath5k_pci_option.patch
new file mode 100644
index 000000000..d0149d39c
--- /dev/null
+++ b/package/mac80211/patches/019-remove_ath5k_pci_option.patch
@@ -0,0 +1,11 @@
+--- a/config.mk
++++ b/config.mk
+@@ -282,7 +282,7 @@ endif #CONFIG_COMPAT_KERNEL_2_6_27
+ # PCI Drivers
+ ifdef CONFIG_PCI
+
+-export CONFIG_ATH5K_PCI=y
++# export CONFIG_ATH5K_PCI=y
+ export CONFIG_ATH9K_PCI=y
+
+ export CONFIG_IWLWIFI=m
diff --git a/package/mac80211/patches/021-add_include_for_bcma.patch b/package/mac80211/patches/021-add_include_for_bcma.patch
new file mode 100644
index 000000000..e2e856eb0
--- /dev/null
+++ b/package/mac80211/patches/021-add_include_for_bcma.patch
@@ -0,0 +1,11 @@
+--- a/include/linux/compat-3.0.h
++++ b/include/linux/compat-3.0.h
+@@ -36,6 +36,8 @@ static inline struct page *shmem_read_ma
+ #endif
+
+
++#include <linux/mod_devicetable.h>
++
+ /*
+ * since commit 1c5cae815d19ffe02bdfda1260949ef2b1806171
+ * "net: call dev_alloc_name from register_netdevice" dev_alloc_name is
diff --git a/package/mac80211/patches/022-remove_crc8_and_cordic.patch b/package/mac80211/patches/022-remove_crc8_and_cordic.patch
new file mode 100644
index 000000000..13ad2c895
--- /dev/null
+++ b/package/mac80211/patches/022-remove_crc8_and_cordic.patch
@@ -0,0 +1,166 @@
+--- a/compat/Makefile
++++ b/compat/Makefile
+@@ -47,8 +47,6 @@ compat-$(CONFIG_COMPAT_KERNEL_3_3) += \
+ compat-$(CONFIG_COMPAT_KERNEL_3_4) += compat-3.4.o
+ compat-$(CONFIG_COMPAT_KERNEL_3_7) += compat-3.7.o
+
+-compat-$(CONFIG_COMPAT_CORDIC) += cordic.o
+-compat-$(CONFIG_COMPAT_CRC8) += crc8.o
+
+ ifndef CONFIG_64BIT
+ ifndef CONFIG_GENERIC_ATOMIC64
+--- a/include/linux/cordic.h
++++ /dev/null
+@@ -1,48 +0,0 @@
+-/*
+- * Copyright (c) 2011 Broadcom Corporation
+- *
+- * Permission to use, copy, modify, and/or distribute this software for any
+- * purpose with or without fee is hereby granted, provided that the above
+- * copyright notice and this permission notice appear in all copies.
+- *
+- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+- */
+-#ifndef __CORDIC_H_
+-#define __CORDIC_H_
+-
+-#include <linux/types.h>
+-
+-/**
+- * struct cordic_iq - i/q coordinate.
+- *
+- * @i: real part of coordinate (in phase).
+- * @q: imaginary part of coordinate (quadrature).
+- */
+-struct cordic_iq {
+- s32 i;
+- s32 q;
+-};
+-
+-/**
+- * cordic_calc_iq() - calculates the i/q coordinate for given angle.
+- *
+- * @theta: angle in degrees for which i/q coordinate is to be calculated.
+- * @coord: function output parameter holding the i/q coordinate.
+- *
+- * The function calculates the i/q coordinate for a given angle using
+- * cordic algorithm. The coordinate consists of a real (i) and an
+- * imaginary (q) part. The real part is essentially the cosine of the
+- * angle and the imaginary part is the sine of the angle. The returned
+- * values are scaled by 2^16 for precision. The range for theta is
+- * for -180 degrees to +180 degrees. Passed values outside this range are
+- * converted before doing the actual calculation.
+- */
+-struct cordic_iq cordic_calc_iq(s32 theta);
+-
+-#endif /* __CORDIC_H_ */
+--- a/include/linux/crc8.h
++++ /dev/null
+@@ -1,101 +0,0 @@
+-/*
+- * Copyright (c) 2011 Broadcom Corporation
+- *
+- * Permission to use, copy, modify, and/or distribute this software for any
+- * purpose with or without fee is hereby granted, provided that the above
+- * copyright notice and this permission notice appear in all copies.
+- *
+- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+- */
+-#ifndef __CRC8_H_
+-#define __CRC8_H_
+-
+-#include <linux/types.h>
+-
+-/* see usage of this value in crc8() description */
+-#define CRC8_INIT_VALUE 0xFF
+-
+-/*
+- * Return value of crc8() indicating valid message+crc. This is true
+- * if a CRC is inverted before transmission. The CRC computed over the
+- * whole received bitstream is _table[x], where x is the bit pattern
+- * of the modification (almost always 0xff).
+- */
+-#define CRC8_GOOD_VALUE(_table) (_table[0xFF])
+-
+-/* required table size for crc8 algorithm */
+-#define CRC8_TABLE_SIZE 256
+-
+-/* helper macro assuring right table size is used */
+-#define DECLARE_CRC8_TABLE(_table) \
+- static u8 _table[CRC8_TABLE_SIZE]
+-
+-/**
+- * crc8_populate_lsb - fill crc table for given polynomial in regular bit order.
+- *
+- * @table: table to be filled.
+- * @polynomial: polynomial for which table is to be filled.
+- *
+- * This function fills the provided table according the polynomial provided for
+- * regular bit order (lsb first). Polynomials in CRC algorithms are typically
+- * represented as shown below.
+- *
+- * poly = x^8 + x^7 + x^6 + x^4 + x^2 + 1
+- *
+- * For lsb first direction x^7 maps to the lsb. So the polynomial is as below.
+- *
+- * - lsb first: poly = 10101011(1) = 0xAB
+- */
+-void crc8_populate_lsb(u8 table[CRC8_TABLE_SIZE], u8 polynomial);
+-
+-/**
+- * crc8_populate_msb - fill crc table for given polynomial in reverse bit order.
+- *
+- * @table: table to be filled.
+- * @polynomial: polynomial for which table is to be filled.
+- *
+- * This function fills the provided table according the polynomial provided for
+- * reverse bit order (msb first). Polynomials in CRC algorithms are typically
+- * represented as shown below.
+- *
+- * poly = x^8 + x^7 + x^6 + x^4 + x^2 + 1
+- *
+- * For msb first direction x^7 maps to the msb. So the polynomial is as below.
+- *
+- * - msb first: poly = (1)11010101 = 0xD5
+- */
+-void crc8_populate_msb(u8 table[CRC8_TABLE_SIZE], u8 polynomial);
+-
+-/**
+- * crc8() - calculate a crc8 over the given input data.
+- *
+- * @table: crc table used for calculation.
+- * @pdata: pointer to data buffer.
+- * @nbytes: number of bytes in data buffer.
+- * @crc: previous returned crc8 value.
+- *
+- * The CRC8 is calculated using the polynomial given in crc8_populate_msb()
+- * or crc8_populate_lsb().
+- *
+- * The caller provides the initial value (either %CRC8_INIT_VALUE
+- * or the previous returned value) to allow for processing of
+- * discontiguous blocks of data. When generating the CRC the
+- * caller is responsible for complementing the final return value
+- * and inserting it into the byte stream. When validating a byte
+- * stream (including CRC8), a final return value of %CRC8_GOOD_VALUE
+- * indicates the byte stream data can be considered valid.
+- *
+- * Reference:
+- * "A Painless Guide to CRC Error Detection Algorithms", ver 3, Aug 1993
+- * Williams, Ross N., ross<at>ross.net
+- * (see URL http://www.ross.net/crc/download/crc_v3.txt).
+- */
+-u8 crc8(const u8 table[CRC8_TABLE_SIZE], u8 *pdata, size_t nbytes, u8 crc);
+-
+-#endif /* __CRC8_H_ */
diff --git a/package/mac80211/patches/023-ath9k_disable_btcoex.patch b/package/mac80211/patches/023-ath9k_disable_btcoex.patch
new file mode 100644
index 000000000..37ae2d5d7
--- /dev/null
+++ b/package/mac80211/patches/023-ath9k_disable_btcoex.patch
@@ -0,0 +1,11 @@
+--- a/config.mk
++++ b/config.mk
+@@ -267,7 +267,7 @@ export CONFIG_ATH9K_COMMON=m
+ # for long range considerations.
+ # export CONFIG_COMPAT_ATH9K_RATE_CONTROL=y
+
+-export CONFIG_ATH9K_BTCOEX_SUPPORT=y
++# export CONFIG_ATH9K_BTCOEX_SUPPORT=y
+
+ # WIL6210 requires MSI only available >= 2.6.30
+ ifndef CONFIG_COMPAT_KERNEL_2_6_30
diff --git a/package/mac80211/patches/030-disable_tty_set_termios.patch b/package/mac80211/patches/030-disable_tty_set_termios.patch
new file mode 100644
index 000000000..fc5d4d63f
--- /dev/null
+++ b/package/mac80211/patches/030-disable_tty_set_termios.patch
@@ -0,0 +1,16 @@
+--- a/compat/compat-2.6.39.c
++++ b/compat/compat-2.6.39.c
+@@ -12,6 +12,7 @@
+ #include <linux/tty.h>
+ #include <linux/sched.h>
+
++#ifdef CONFIG_COMPAT_BLUETOOTH
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
+ /*
+ * Termios Helper Methods
+@@ -111,4 +112,4 @@ int tty_set_termios(struct tty_struct *t
+ }
+ EXPORT_SYMBOL_GPL(tty_set_termios);
+ #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)) */
+-
++#endif
diff --git a/package/mac80211/patches/050-compat_firmware.patch b/package/mac80211/patches/050-compat_firmware.patch
new file mode 100644
index 000000000..e4b91a316
--- /dev/null
+++ b/package/mac80211/patches/050-compat_firmware.patch
@@ -0,0 +1,78 @@
+--- a/compat/Makefile
++++ b/compat/Makefile
+@@ -1,7 +1,10 @@
+ obj-m += compat.o
+ #compat-objs :=
+
+-obj-$(CONFIG_COMPAT_FIRMWARE_CLASS) += compat_firmware_class.o
++ifdef CONFIG_COMPAT_FIRMWARE_CLASS
++ compat-y += compat_firmware_class.o
++endif
++
+ obj-$(CONFIG_COMPAT_NET_SCH_CODEL) += sch_codel.o
+
+ sch_fq_codel-y = sch_fq_codel_core.o flow_dissector.o
+--- a/compat/compat_firmware_class.c
++++ b/compat/compat_firmware_class.c
+@@ -741,19 +741,16 @@ compat_request_firmware_nowait(
+ return 0;
+ }
+
+-static int __init firmware_class_init(void)
++int __init firmware_class_init(void)
+ {
+ return class_register(&firmware_class);
+ }
+
+-static void __exit firmware_class_exit(void)
++void __exit firmware_class_exit(void)
+ {
+ class_unregister(&firmware_class);
+ }
+
+-fs_initcall(firmware_class_init);
+-module_exit(firmware_class_exit);
+-
+ EXPORT_SYMBOL_GPL(release_firmware);
+ EXPORT_SYMBOL_GPL(request_firmware);
+ EXPORT_SYMBOL_GPL(request_firmware_nowait);
+--- a/compat/main.c
++++ b/compat/main.c
+@@ -47,6 +47,17 @@ void compat_dependency_symbol(void)
+ EXPORT_SYMBOL_GPL(compat_dependency_symbol);
+
+
++#if defined(CONFIG_FW_LOADER) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
++int __init firmware_class_init(void);
++void __exit firmware_class_exit(void);
++#else
++static inline int firmware_class_init(void)
++{
++ return 0;
++}
++static inline void firmware_class_exit(void) {}
++#endif
++
+ static int __init compat_init(void)
+ {
+ compat_pm_qos_power_init();
+@@ -63,7 +74,8 @@ static int __init compat_init(void)
+ printk(KERN_INFO "compat.git: "
+ COMPAT_BASE_TREE "\n");
+
+- return 0;
++ firmware_class_init();
++ return 0;
+ }
+ module_init(compat_init);
+
+@@ -72,7 +84,8 @@ static void __exit compat_exit(void)
+ compat_pm_qos_power_deinit();
+ compat_system_workqueue_destroy();
+
+- return;
++ firmware_class_exit();
++ return;
+ }
+ module_exit(compat_exit);
+
diff --git a/package/mac80211/patches/060-compat_add_module_pci_driver.patch b/package/mac80211/patches/060-compat_add_module_pci_driver.patch
new file mode 100644
index 000000000..277ca3d37
--- /dev/null
+++ b/package/mac80211/patches/060-compat_add_module_pci_driver.patch
@@ -0,0 +1,22 @@
+--- a/include/linux/compat-3.4.h
++++ b/include/linux/compat-3.4.h
+@@ -112,6 +112,19 @@ static inline void eth_hw_addr_random(st
+ module_driver(__pci_driver, pci_register_driver, \
+ pci_unregister_driver)
+
++/* source include/linux/pci.h */
++/**
++ * module_pci_driver() - Helper macro for registering a PCI driver
++ * @__pci_driver: pci_driver struct
++ *
++ * Helper macro for PCI drivers which do not do anything special in module
++ * init/exit. This eliminates a lot of boilerplate. Each module may only
++ * use this macro once, and calling it replaces module_init() and module_exit()
++ */
++#define module_pci_driver(__pci_driver) \
++ module_driver(__pci_driver, pci_register_driver, \
++ pci_unregister_driver)
++
+ #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) */
+
+ #endif /* LINUX_5_4_COMPAT_H */
diff --git a/package/mac80211/patches/070-disable_codel.patch b/package/mac80211/patches/070-disable_codel.patch
new file mode 100644
index 000000000..0d6d74911
--- /dev/null
+++ b/package/mac80211/patches/070-disable_codel.patch
@@ -0,0 +1,19 @@
+--- a/compat/scripts/gen-compat-config.sh
++++ b/compat/scripts/gen-compat-config.sh
+@@ -66,16 +66,3 @@ if [[ ${CONFIG_COMPAT_KERNEL_2_6_36} = "
+ echo "export CONFIG_COMPAT_KFIFO=y"
+ fi
+ fi
+-
+-if [[ ${CONFIG_COMPAT_KERNEL_3_5} = "y" ]]; then
+- # We don't have 2.6.24 backport support yet for Codel / FQ CoDel
+- # For those who want to try this is what is required that I can tell
+- # so far:
+- # * struct Qdisc_ops
+- # - init and change callback ops use a different argument dataype
+- # - you need to parse data received from userspace differently
+- if [[ ${CONFIG_COMPAT_KERNEL_2_6_25} != "y" ]]; then
+- echo "export CONFIG_COMPAT_NET_SCH_CODEL=m"
+- echo "export CONFIG_COMPAT_NET_SCH_FQ_CODEL=m"
+- fi
+-fi
diff --git a/package/mac80211/patches/071-add_codel_ifdef.patch b/package/mac80211/patches/071-add_codel_ifdef.patch
new file mode 100644
index 000000000..86b415170
--- /dev/null
+++ b/package/mac80211/patches/071-add_codel_ifdef.patch
@@ -0,0 +1,19 @@
+--- a/include/linux/compat-3.5.h
++++ b/include/linux/compat-3.5.h
+@@ -8,6 +8,8 @@
+
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0))
+
++#ifndef TCA_CODEL_MAX
++
+ /*
+ * This backports:
+ *
+@@ -135,6 +137,7 @@ static inline int compat_vga_switcheroo_
+
+ #define SIZE_MAX (~(size_t)0)
+
++#endif /* TCA_CODEL_MAX */
+
+ #include <linux/pkt_sched.h>
+
diff --git a/package/mac80211/patches/100-disable_pcmcia_compat.patch b/package/mac80211/patches/100-disable_pcmcia_compat.patch
new file mode 100644
index 000000000..60927555b
--- /dev/null
+++ b/package/mac80211/patches/100-disable_pcmcia_compat.patch
@@ -0,0 +1,65 @@
+--- a/compat/compat-2.6.28.c
++++ b/compat/compat-2.6.28.c
+@@ -86,7 +86,7 @@ EXPORT_SYMBOL_GPL(usb_poison_urb);
+ #endif
+ #endif /* CONFIG_USB */
+
+-#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
++#if 0
+
+ #include <pcmcia/ds.h>
+ struct pcmcia_cfg_mem {
+--- a/compat/compat-2.6.33.c
++++ b/compat/compat-2.6.33.c
+@@ -10,7 +10,7 @@
+
+ #include <linux/compat.h>
+
+-#if defined(CONFIG_PCCARD) || defined(CONFIG_PCCARD_MODULE)
++#if 0
+
+ /**
+ * pccard_loop_tuple() - loop over tuples in the CIS
+@@ -72,7 +72,7 @@ next_entry:
+ EXPORT_SYMBOL_GPL(pccard_loop_tuple);
+ /* Source: drivers/pcmcia/cistpl.c */
+
+-#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
++#if 0
+
+ struct pcmcia_loop_mem {
+ struct pcmcia_device *p_dev;
+--- a/include/linux/compat-2.6.28.h
++++ b/include/linux/compat-2.6.28.h
+@@ -49,7 +49,7 @@ typedef u32 phys_addr_t;
+ })
+ #endif /* From include/asm-generic/bug.h */
+
+-#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
++#if 0
+
+ #include <pcmcia/cs_types.h>
+ #include <pcmcia/cs.h>
+--- a/include/linux/compat-2.6.33.h
++++ b/include/linux/compat-2.6.33.h
+@@ -7,7 +7,7 @@
+
+ #include <linux/skbuff.h>
+ #include <linux/pci.h>
+-#if defined(CONFIG_PCCARD) || defined(CONFIG_PCCARD_MODULE)
++#if 0
+ #include <pcmcia/cs_types.h>
+ #include <pcmcia/cistpl.h>
+ #include <pcmcia/ds.h>
+@@ -82,9 +82,9 @@ static inline struct sk_buff *netdev_all
+ return skb;
+ }
+
+-#if defined(CONFIG_PCCARD) || defined(CONFIG_PCCARD_MODULE)
++#if 0
+
+-#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
++#if 0
+
+ #define pcmcia_request_window(a, b, c) pcmcia_request_window(&a, b, c)
+
diff --git a/package/mac80211/patches/110-disable_usb_compat.patch b/package/mac80211/patches/110-disable_usb_compat.patch
new file mode 100644
index 000000000..d6287fd04
--- /dev/null
+++ b/package/mac80211/patches/110-disable_usb_compat.patch
@@ -0,0 +1,44 @@
+--- a/compat/compat-2.6.28.c
++++ b/compat/compat-2.6.28.c
+@@ -165,7 +165,7 @@ EXPORT_SYMBOL_GPL(pcmcia_loop_config);
+
+ #endif /* CONFIG_PCMCIA */
+
+-#if defined(CONFIG_USB) || defined(CONFIG_USB_MODULE)
++#if 0
+
+ void usb_unpoison_urb(struct urb *urb)
+ {
+--- a/compat/compat-2.6.29.c
++++ b/compat/compat-2.6.29.c
+@@ -49,7 +49,7 @@ void netdev_attach_ops(struct net_device
+ EXPORT_SYMBOL_GPL(netdev_attach_ops);
+
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23))
+-#if defined(CONFIG_USB) || defined(CONFIG_USB_MODULE)
++#if 0
+ /**
+ * usb_unpoison_anchored_urbs - let an anchor be used successfully again
+ * @anchor: anchor the requests are bound to
+--- a/include/linux/compat-2.6.28.h
++++ b/include/linux/compat-2.6.28.h
+@@ -74,7 +74,7 @@ int pcmcia_loop_config(struct pcmcia_dev
+ /* USB anchors were added as of 2.6.23 */
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23))
+
+-#if defined(CONFIG_USB) || defined(CONFIG_USB_MODULE)
++#if 0
+ #if 0
+ extern void usb_poison_urb(struct urb *urb);
+ #endif
+--- a/config.mk
++++ b/config.mk
+@@ -510,7 +510,7 @@ endif #CONFIG_COMPAT_KERNEL_2_6_29
+ # This activates a threading fix for usb urb.
+ # this is mainline commit: b3e670443b7fb8a2d29831b62b44a039c283e351
+ # This fix will be included in some stable releases.
+-export CONFIG_COMPAT_USB_URB_THREAD_FIX=y
++# export CONFIG_COMPAT_USB_URB_THREAD_FIX=y
+
+ export CONFIG_ATH9K_HTC=m
+ # export CONFIG_ATH9K_HTC_DEBUGFS=y
diff --git a/package/mac80211/patches/130-mesh_pathtbl_backport.patch b/package/mac80211/patches/130-mesh_pathtbl_backport.patch
new file mode 100644
index 000000000..15ad03ced
--- /dev/null
+++ b/package/mac80211/patches/130-mesh_pathtbl_backport.patch
@@ -0,0 +1,10 @@
+--- a/net/mac80211/mesh_pathtbl.c
++++ b/net/mac80211/mesh_pathtbl.c
+@@ -813,7 +813,6 @@ static void table_flush_by_iface(struct
+ struct hlist_node *p;
+ int i;
+
+- WARN_ON(!rcu_read_lock_held());
+ for_each_mesh_entry(tbl, p, node, i) {
+ mpath = node->mpath;
+ if (mpath->sdata != sdata)
diff --git a/package/mac80211/patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch b/package/mac80211/patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch
new file mode 100644
index 000000000..9e08a0897
--- /dev/null
+++ b/package/mac80211/patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch
@@ -0,0 +1,38 @@
+--- a/drivers/net/wireless/ath/ath5k/initvals.c
++++ b/drivers/net/wireless/ath/ath5k/initvals.c
+@@ -65,8 +65,14 @@ static const struct ath5k_ini ar5210_ini
+ { AR5K_IMR, 0 },
+ { AR5K_IER, AR5K_IER_DISABLE },
+ { AR5K_BSR, 0, AR5K_INI_READ },
++#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79)
+ { AR5K_TXCFG, AR5K_DMASIZE_128B },
+ { AR5K_RXCFG, AR5K_DMASIZE_128B },
++#else
++ /* WAR for AR71xx PCI bug */
++ { AR5K_TXCFG, AR5K_DMASIZE_128B },
++ { AR5K_RXCFG, AR5K_DMASIZE_4B },
++#endif
+ { AR5K_CFG, AR5K_INIT_CFG },
+ { AR5K_TOPS, 8 },
+ { AR5K_RXNOFRM, 8 },
+--- a/drivers/net/wireless/ath/ath5k/dma.c
++++ b/drivers/net/wireless/ath/ath5k/dma.c
+@@ -863,10 +863,18 @@ ath5k_hw_dma_init(struct ath5k_hw *ah)
+ * guess we can tweak it and see how it goes ;-)
+ */
+ if (ah->ah_version != AR5K_AR5210) {
++#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79)
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
+ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
++#else
++ /* WAR for AR71xx PCI bug */
++ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
++ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
++ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
++ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_4B);
++#endif
+ }
+
+ /* Pre-enable interrupts on 5211/5212*/
diff --git a/package/mac80211/patches/300-pending_work.patch b/package/mac80211/patches/300-pending_work.patch
new file mode 100644
index 000000000..f7a0aede5
--- /dev/null
+++ b/package/mac80211/patches/300-pending_work.patch
@@ -0,0 +1,592 @@
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -325,6 +325,8 @@ ath5k_setup_channels(struct ath5k_hw *ah
+ if (!ath5k_is_standard_channel(ch, band))
+ continue;
+
++ channels[count].max_power = AR5K_TUNE_MAX_TXPOWER/2;
++
+ count++;
+ }
+
+--- a/net/mac80211/agg-rx.c
++++ b/net/mac80211/agg-rx.c
+@@ -203,6 +203,8 @@ static void ieee80211_send_addba_resp(st
+ memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
+ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
+ memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
++ else if (sdata->vif.type == NL80211_IFTYPE_WDS)
++ memcpy(mgmt->bssid, da, ETH_ALEN);
+
+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_ACTION);
+--- a/net/mac80211/agg-tx.c
++++ b/net/mac80211/agg-tx.c
+@@ -81,7 +81,8 @@ static void ieee80211_send_addba_request
+ memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
+ if (sdata->vif.type == NL80211_IFTYPE_AP ||
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+- sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
++ sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
++ sdata->vif.type == NL80211_IFTYPE_WDS)
+ memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
+ else if (sdata->vif.type == NL80211_IFTYPE_STATION)
+ memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
+@@ -460,6 +461,7 @@ int ieee80211_start_tx_ba_session(struct
+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
+ sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+ sdata->vif.type != NL80211_IFTYPE_AP &&
++ sdata->vif.type != NL80211_IFTYPE_WDS &&
+ sdata->vif.type != NL80211_IFTYPE_ADHOC)
+ return -EINVAL;
+
+@@ -869,7 +871,7 @@ void ieee80211_process_addba_resp(struct
+
+ } else {
+ ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR,
+- true);
++ false);
+ }
+
+ out:
+--- a/net/mac80211/debugfs_sta.c
++++ b/net/mac80211/debugfs_sta.c
+@@ -63,11 +63,11 @@ static ssize_t sta_flags_read(struct fil
+ test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : ""
+
+ int res = scnprintf(buf, sizeof(buf),
+- "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
++ "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ TEST(AUTH), TEST(ASSOC), TEST(PS_STA),
+ TEST(PS_DRIVER), TEST(AUTHORIZED),
+ TEST(SHORT_PREAMBLE),
+- TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT),
++ TEST(WME), TEST(CLEAR_PS_FILT),
+ TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL),
+ TEST(UAPSD), TEST(SP), TEST(TDLS_PEER),
+ TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT),
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -420,7 +420,6 @@ int ieee80211_do_open(struct wireless_de
+ struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+ struct net_device *dev = wdev->netdev;
+ struct ieee80211_local *local = sdata->local;
+- struct sta_info *sta;
+ u32 changed = 0;
+ int res;
+ u32 hw_reconf_flags = 0;
+@@ -575,30 +574,8 @@ int ieee80211_do_open(struct wireless_de
+
+ set_bit(SDATA_STATE_RUNNING, &sdata->state);
+
+- if (sdata->vif.type == NL80211_IFTYPE_WDS) {
+- /* Create STA entry for the WDS peer */
+- sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
+- GFP_KERNEL);
+- if (!sta) {
+- res = -ENOMEM;
+- goto err_del_interface;
+- }
+-
+- sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
+- sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
+- sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
+-
+- res = sta_info_insert(sta);
+- if (res) {
+- /* STA has been freed */
+- goto err_del_interface;
+- }
+-
+- rate_control_rate_init(sta);
+- netif_carrier_on(dev);
+- } else if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) {
++ if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE)
+ rcu_assign_pointer(local->p2p_sdata, sdata);
+- }
+
+ /*
+ * set_multicast_list will be invoked by the networking core
+@@ -997,6 +974,72 @@ static void ieee80211_if_setup(struct ne
+ dev->destructor = free_netdev;
+ }
+
++static void ieee80211_wds_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
++ struct sk_buff *skb)
++{
++ struct ieee80211_local *local = sdata->local;
++ struct ieee80211_rx_status *rx_status;
++ struct ieee802_11_elems elems;
++ struct ieee80211_mgmt *mgmt;
++ struct sta_info *sta;
++ size_t baselen;
++ u32 rates = 0;
++ u16 stype;
++ bool new = false;
++ enum ieee80211_band band = local->hw.conf.channel->band;
++ struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
++
++ rx_status = IEEE80211_SKB_RXCB(skb);
++ mgmt = (struct ieee80211_mgmt *) skb->data;
++ stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
++
++ if (stype != IEEE80211_STYPE_BEACON)
++ return;
++
++ baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
++ if (baselen > skb->len)
++ return;
++
++ ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
++ skb->len - baselen, &elems);
++
++ rates = ieee80211_sta_get_rates(local, &elems, band, NULL);
++
++ rcu_read_lock();
++
++ sta = sta_info_get(sdata, sdata->u.wds.remote_addr);
++
++ if (!sta) {
++ rcu_read_unlock();
++ sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
++ GFP_KERNEL);
++ if (!sta)
++ return;
++
++ new = true;
++ }
++
++ sta->last_rx = jiffies;
++ sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
++
++ if (elems.ht_cap_elem)
++ ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
++ elems.ht_cap_elem, &sta->sta.ht_cap);
++
++ if (elems.wmm_param)
++ set_sta_flag(sta, WLAN_STA_WME);
++
++ if (new) {
++ sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
++ sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
++ sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
++ rate_control_rate_init(sta);
++ sta_info_insert_rcu(sta);
++ }
++
++ rcu_read_unlock();
++}
++
+ static void ieee80211_iface_work(struct work_struct *work)
+ {
+ struct ieee80211_sub_if_data *sdata =
+@@ -1101,6 +1144,9 @@ static void ieee80211_iface_work(struct
+ break;
+ ieee80211_mesh_rx_queued_mgmt(sdata, skb);
+ break;
++ case NL80211_IFTYPE_WDS:
++ ieee80211_wds_rx_queued_mgmt(sdata, skb);
++ break;
+ default:
+ WARN(1, "frame for unexpected interface type");
+ break;
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2279,6 +2279,7 @@ ieee80211_rx_h_action(struct ieee80211_r
+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
+ sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+ sdata->vif.type != NL80211_IFTYPE_AP &&
++ sdata->vif.type != NL80211_IFTYPE_WDS &&
+ sdata->vif.type != NL80211_IFTYPE_ADHOC)
+ break;
+
+@@ -2496,14 +2497,15 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
+
+ if (!ieee80211_vif_is_mesh(&sdata->vif) &&
+ sdata->vif.type != NL80211_IFTYPE_ADHOC &&
+- sdata->vif.type != NL80211_IFTYPE_STATION)
++ sdata->vif.type != NL80211_IFTYPE_STATION &&
++ sdata->vif.type != NL80211_IFTYPE_WDS)
+ return RX_DROP_MONITOR;
+
+ switch (stype) {
+ case cpu_to_le16(IEEE80211_STYPE_AUTH):
+ case cpu_to_le16(IEEE80211_STYPE_BEACON):
+ case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
+- /* process for all: mesh, mlme, ibss */
++ /* process for all: mesh, mlme, ibss, wds */
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
+ case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
+@@ -2827,10 +2829,16 @@ static int prepare_for_handlers(struct i
+ }
+ break;
+ case NL80211_IFTYPE_WDS:
+- if (bssid || !ieee80211_is_data(hdr->frame_control))
+- return 0;
+ if (!ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2))
+ return 0;
++
++ if (ieee80211_is_data(hdr->frame_control) ||
++ ieee80211_is_action(hdr->frame_control)) {
++ if (compare_ether_addr(sdata->vif.addr, hdr->addr1))
++ return 0;
++ } else if (!ieee80211_is_beacon(hdr->frame_control))
++ return 0;
++
+ break;
+ case NL80211_IFTYPE_P2P_DEVICE:
+ if (!ieee80211_is_public_action(hdr, skb->len) &&
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -32,7 +32,6 @@
+ * @WLAN_STA_SHORT_PREAMBLE: Station is capable of receiving short-preamble
+ * frames.
+ * @WLAN_STA_WME: Station is a QoS-STA.
+- * @WLAN_STA_WDS: Station is one of our WDS peers.
+ * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
+ * IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next
+ * frame to this station is transmitted.
+@@ -64,7 +63,6 @@ enum ieee80211_sta_info_flags {
+ WLAN_STA_AUTHORIZED,
+ WLAN_STA_SHORT_PREAMBLE,
+ WLAN_STA_WME,
+- WLAN_STA_WDS,
+ WLAN_STA_CLEAR_PS_FILT,
+ WLAN_STA_MFP,
+ WLAN_STA_BLOCK_BA,
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -517,29 +517,41 @@ void ieee80211_tx_status(struct ieee8021
+
+ if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) {
+ u64 cookie = (unsigned long)skb;
++ bool found = false;
++
+ acked = info->flags & IEEE80211_TX_STAT_ACK;
+
+- if (ieee80211_is_nullfunc(hdr->frame_control) ||
+- ieee80211_is_qos_nullfunc(hdr->frame_control)) {
+- cfg80211_probe_status(skb->dev, hdr->addr1,
+- cookie, acked, GFP_ATOMIC);
+- } else if (skb->dev) {
+- cfg80211_mgmt_tx_status(
+- skb->dev->ieee80211_ptr, cookie, skb->data,
+- skb->len, acked, GFP_ATOMIC);
+- } else {
+- struct ieee80211_sub_if_data *p2p_sdata;
++ rcu_read_lock();
+
+- rcu_read_lock();
++ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
++ if (!sdata->dev)
++ continue;
+
+- p2p_sdata = rcu_dereference(local->p2p_sdata);
+- if (p2p_sdata) {
+- cfg80211_mgmt_tx_status(
+- &p2p_sdata->wdev, cookie, skb->data,
+- skb->len, acked, GFP_ATOMIC);
+- }
+- rcu_read_unlock();
++ if (skb->dev != sdata->dev)
++ continue;
++
++ found = true;
++ break;
+ }
++
++ if (!skb->dev) {
++ sdata = rcu_dereference(local->p2p_sdata);
++ if (sdata)
++ found = true;
++ }
++
++ if (!found)
++ skb->dev = NULL;
++ else if (ieee80211_is_nullfunc(hdr->frame_control) ||
++ ieee80211_is_qos_nullfunc(hdr->frame_control)) {
++ cfg80211_probe_status(sdata->dev, hdr->addr1,
++ cookie, acked, GFP_ATOMIC);
++ } else {
++ cfg80211_mgmt_tx_status(&sdata->wdev, cookie, skb->data,
++ skb->len, acked, GFP_ATOMIC);
++ }
++
++ rcu_read_unlock();
+ }
+
+ if (unlikely(info->ack_frame_id)) {
+--- a/drivers/net/wireless/p54/main.c
++++ b/drivers/net/wireless/p54/main.c
+@@ -139,6 +139,7 @@ static int p54_beacon_format_ie_tim(stru
+ static int p54_beacon_update(struct p54_common *priv,
+ struct ieee80211_vif *vif)
+ {
++ struct ieee80211_tx_control control = { };
+ struct sk_buff *beacon;
+ int ret;
+
+@@ -158,7 +159,7 @@ static int p54_beacon_update(struct p54_
+ * to cancel the old beacon template by hand, instead the firmware
+ * will release the previous one through the feedback mechanism.
+ */
+- p54_tx_80211(priv->hw, NULL, beacon);
++ p54_tx_80211(priv->hw, &control, beacon);
+ priv->tsf_high32 = 0;
+ priv->tsf_low32 = 0;
+
+--- a/net/wireless/reg.c
++++ b/net/wireless/reg.c
+@@ -352,6 +352,9 @@ static void reg_regdb_search(struct work
+ struct reg_regdb_search_request *request;
+ const struct ieee80211_regdomain *curdom, *regdom;
+ int i, r;
++ bool set_reg = false;
++
++ mutex_lock(&cfg80211_mutex);
+
+ mutex_lock(&reg_regdb_search_mutex);
+ while (!list_empty(&reg_regdb_search_list)) {
+@@ -367,9 +370,7 @@ static void reg_regdb_search(struct work
+ r = reg_copy_regd(&regdom, curdom);
+ if (r)
+ break;
+- mutex_lock(&cfg80211_mutex);
+- set_regdom(regdom);
+- mutex_unlock(&cfg80211_mutex);
++ set_reg = true;
+ break;
+ }
+ }
+@@ -377,6 +378,11 @@ static void reg_regdb_search(struct work
+ kfree(request);
+ }
+ mutex_unlock(&reg_regdb_search_mutex);
++
++ if (set_reg)
++ set_regdom(regdom);
++
++ mutex_unlock(&cfg80211_mutex);
+ }
+
+ static DECLARE_WORK(reg_regdb_work, reg_regdb_search);
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -424,8 +424,8 @@ u32 ath_calcrxfilter(struct ath_softc *s
+ rfilt |= ATH9K_RX_FILTER_COMP_BAR;
+
+ if (sc->nvifs > 1 || (sc->rx.rxfilter & FIF_OTHER_BSS)) {
+- /* The following may also be needed for other older chips */
+- if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160)
++ /* This is needed for older chips */
++ if (sc->sc_ah->hw_version.macVersion <= AR_SREV_VERSION_9160)
+ rfilt |= ATH9K_RX_FILTER_PROM;
+ rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL;
+ }
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -818,23 +818,71 @@ void ieee80211_sta_process_chanswitch(st
+ }
+
+ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
+- u16 capab_info, u8 *pwr_constr_elem,
+- u8 pwr_constr_elem_len)
++ struct ieee80211_channel *channel,
++ const u8 *country_ie, u8 country_ie_len,
++ const u8 *pwr_constr_elem)
+ {
+- struct ieee80211_conf *conf = &sdata->local->hw.conf;
++ struct ieee80211_country_ie_triplet *triplet;
++ int chan = ieee80211_frequency_to_channel(channel->center_freq);
++ int i, chan_pwr, chan_increment, new_ap_level;
++ bool have_chan_pwr = false;
+
+- if (!(capab_info & WLAN_CAPABILITY_SPECTRUM_MGMT))
++ /* Invalid IE */
++ if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
+ return;
+
+- /* Power constraint IE length should be 1 octet */
+- if (pwr_constr_elem_len != 1)
+- return;
++ triplet = (void *)(country_ie + 3);
++ country_ie_len -= 3;
+
+- if ((*pwr_constr_elem <= conf->channel->max_reg_power) &&
+- (*pwr_constr_elem != sdata->local->power_constr_level)) {
+- sdata->local->power_constr_level = *pwr_constr_elem;
+- ieee80211_hw_config(sdata->local, 0);
++ switch (channel->band) {
++ default:
++ WARN_ON_ONCE(1);
++ /* fall through */
++ case IEEE80211_BAND_2GHZ:
++ case IEEE80211_BAND_60GHZ:
++ chan_increment = 1;
++ break;
++ case IEEE80211_BAND_5GHZ:
++ chan_increment = 4;
++ break;
+ }
++
++ /* find channel */
++ while (country_ie_len >= 3) {
++ u8 first_channel = triplet->chans.first_channel;
++
++ if (first_channel >= IEEE80211_COUNTRY_EXTENSION_ID)
++ goto next;
++
++ for (i = 0; i < triplet->chans.num_channels; i++) {
++ if (first_channel + i * chan_increment == chan) {
++ have_chan_pwr = true;
++ chan_pwr = triplet->chans.max_power;
++ break;
++ }
++ }
++ if (have_chan_pwr)
++ break;
++
++ next:
++ triplet++;
++ country_ie_len -= 3;
++ }
++
++ if (!have_chan_pwr)
++ return;
++
++ new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem);
++
++ if (sdata->local->ap_power_level == new_ap_level)
++ return;
++
++ sdata_info(sdata,
++ "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
++ new_ap_level, chan_pwr, *pwr_constr_elem,
++ sdata->u.mgd.bssid);
++ sdata->local->ap_power_level = new_ap_level;
++ ieee80211_hw_config(sdata->local, 0);
+ }
+
+ void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif)
+@@ -1390,7 +1438,7 @@ static void ieee80211_set_disassoc(struc
+ sta = sta_info_get(sdata, ifmgd->bssid);
+ if (sta) {
+ set_sta_flag(sta, WLAN_STA_BLOCK_BA);
+- ieee80211_sta_tear_down_BA_sessions(sta, tx);
++ ieee80211_sta_tear_down_BA_sessions(sta, false);
+ }
+ mutex_unlock(&local->sta_mtx);
+
+@@ -1438,7 +1486,7 @@ static void ieee80211_set_disassoc(struc
+ memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
+ memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
+
+- local->power_constr_level = 0;
++ local->ap_power_level = 0;
+
+ del_timer_sync(&local->dynamic_ps_timer);
+ cancel_work_sync(&local->dynamic_ps_enable_work);
+@@ -2530,15 +2578,13 @@ static void ieee80211_rx_mgmt_beacon(str
+ bssid, true);
+ }
+
+- /* Note: country IE parsing is done for us by cfg80211 */
+- if (elems.country_elem) {
+- /* TODO: IBSS also needs this */
+- if (elems.pwr_constr_elem)
+- ieee80211_handle_pwr_constr(sdata,
+- le16_to_cpu(mgmt->u.probe_resp.capab_info),
+- elems.pwr_constr_elem,
+- elems.pwr_constr_elem_len);
+- }
++ if (elems.country_elem && elems.pwr_constr_elem &&
++ mgmt->u.probe_resp.capab_info &
++ cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT))
++ ieee80211_handle_pwr_constr(sdata, local->oper_channel,
++ elems.country_elem,
++ elems.country_elem_len,
++ elems.pwr_constr_elem);
+
+ ieee80211_bss_info_change_notify(sdata, changed);
+ }
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -674,7 +674,7 @@ int __must_check __sta_info_destroy(stru
+ * will be sufficient.
+ */
+ set_sta_flag(sta, WLAN_STA_BLOCK_BA);
+- ieee80211_sta_tear_down_BA_sessions(sta, true);
++ ieee80211_sta_tear_down_BA_sessions(sta, false);
+
+ ret = sta_info_hash_del(local, sta);
+ if (ret)
+--- a/drivers/net/wireless/ath/ath5k/phy.c
++++ b/drivers/net/wireless/ath/ath5k/phy.c
+@@ -1977,11 +1977,13 @@ ath5k_hw_set_spur_mitigation_filter(stru
+ spur_delta_phase = (spur_offset << 18) / 25;
+ spur_freq_sigma_delta = (spur_delta_phase >> 10);
+ symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 2;
++ break;
+ case AR5K_BWMODE_5MHZ:
+ /* Both sample_freq and chip_freq are 10MHz (?) */
+ spur_delta_phase = (spur_offset << 19) / 25;
+ spur_freq_sigma_delta = (spur_delta_phase >> 10);
+ symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 4;
++ break;
+ default:
+ if (channel->band == IEEE80211_BAND_5GHZ) {
+ /* Both sample_freq and chip_freq are 40MHz */
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1062,7 +1062,7 @@ struct ieee80211_local {
+ bool disable_dynamic_ps;
+
+ int user_power_level; /* in dBm */
+- int power_constr_level; /* in dBm */
++ int ap_power_level; /* in dBm */
+
+ enum ieee80211_smps_mode smps_mode;
+
+@@ -1170,7 +1170,6 @@ struct ieee802_11_elems {
+ u8 prep_len;
+ u8 perr_len;
+ u8 country_elem_len;
+- u8 pwr_constr_elem_len;
+ u8 quiet_elem_len;
+ u8 num_of_quiet_elem; /* can be more the one */
+ u8 timeout_int_len;
+--- a/net/mac80211/util.c
++++ b/net/mac80211/util.c
+@@ -792,8 +792,11 @@ u32 ieee802_11_parse_elems_crc(u8 *start
+ elems->country_elem_len = elen;
+ break;
+ case WLAN_EID_PWR_CONSTRAINT:
++ if (elen != 1) {
++ elem_parse_failed = true;
++ break;
++ }
+ elems->pwr_constr_elem = pos;
+- elems->pwr_constr_elem_len = elen;
+ break;
+ case WLAN_EID_TIMEOUT_INTERVAL:
+ elems->timeout_int = pos;
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -154,13 +154,11 @@ int ieee80211_hw_config(struct ieee80211
+
+ if (test_bit(SCAN_SW_SCANNING, &local->scanning) ||
+ test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) ||
+- test_bit(SCAN_HW_SCANNING, &local->scanning))
++ test_bit(SCAN_HW_SCANNING, &local->scanning) ||
++ !local->ap_power_level)
+ power = chan->max_power;
+ else
+- power = local->power_constr_level ?
+- min(chan->max_power,
+- (chan->max_reg_power - local->power_constr_level)) :
+- chan->max_power;
++ power = min(chan->max_power, local->ap_power_level);
+
+ if (local->user_power_level >= 0)
+ power = min(power, local->user_power_level);
diff --git a/package/mac80211/patches/310-ap_scan.patch b/package/mac80211/patches/310-ap_scan.patch
new file mode 100644
index 000000000..67a9dcaba
--- /dev/null
+++ b/package/mac80211/patches/310-ap_scan.patch
@@ -0,0 +1,11 @@
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -1796,8 +1796,6 @@ static int ieee80211_scan(struct wiphy *
+ * beaconing hasn't been configured yet
+ */
+ case NL80211_IFTYPE_AP:
+- if (sdata->u.ap.beacon)
+- return -EOPNOTSUPP;
+ break;
+ default:
+ return -EOPNOTSUPP;
diff --git a/package/mac80211/patches/400-ath_move_debug_code.patch b/package/mac80211/patches/400-ath_move_debug_code.patch
new file mode 100644
index 000000000..256da42de
--- /dev/null
+++ b/package/mac80211/patches/400-ath_move_debug_code.patch
@@ -0,0 +1,28 @@
+--- a/drivers/net/wireless/ath/Makefile
++++ b/drivers/net/wireless/ath/Makefile
+@@ -8,7 +8,7 @@ obj-$(CONFIG_ATH_COMMON) += ath.o
+ ath-objs := main.o \
+ regd.o \
+ hw.o \
+- key.o
++ key.o \
++ debug.o
+
+-ath-$(CONFIG_ATH_DEBUG) += debug.o
+ ccflags-y += -D__CHECK_ENDIAN__
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -280,13 +280,6 @@ void _ath_dbg(struct ath_common *common,
+ #endif /* CONFIG_ATH_DEBUG */
+
+ /** Returns string describing opmode, or NULL if unknown mode. */
+-#ifdef CONFIG_ATH_DEBUG
+ const char *ath_opmode_to_string(enum nl80211_iftype opmode);
+-#else
+-static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode)
+-{
+- return "UNKNOWN";
+-}
+-#endif
+
+ #endif /* ATH_H */
diff --git a/package/mac80211/patches/401-ath9k_blink_default.patch b/package/mac80211/patches/401-ath9k_blink_default.patch
new file mode 100644
index 000000000..10c763696
--- /dev/null
+++ b/package/mac80211/patches/401-ath9k_blink_default.patch
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -40,7 +40,7 @@ int ath9k_modparam_nohwcrypt;
+ module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444);
+ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
+
+-int led_blink;
++int led_blink = 1;
+ module_param_named(blink, led_blink, int, 0444);
+ MODULE_PARM_DESC(blink, "Enable LED blink on activity");
+
diff --git a/package/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch b/package/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch
new file mode 100644
index 000000000..7c59e1f10
--- /dev/null
+++ b/package/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch
@@ -0,0 +1,29 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -17,6 +17,7 @@
+ #include <linux/io.h>
+ #include <linux/slab.h>
+ #include <linux/module.h>
++#include <linux/etherdevice.h>
+ #include <asm/unaligned.h>
+
+ #include "hw.h"
+@@ -523,8 +524,16 @@ static int ath9k_hw_init_macaddr(struct
+ common->macaddr[2 * i] = eeval >> 8;
+ common->macaddr[2 * i + 1] = eeval & 0xff;
+ }
+- if (sum == 0 || sum == 0xffff * 3)
+- return -EADDRNOTAVAIL;
++ if (!is_valid_ether_addr(common->macaddr)) {
++ ath_err(common,
++ "eeprom contains invalid mac address: %pM\n",
++ common->macaddr);
++
++ random_ether_addr(common->macaddr);
++ ath_err(common,
++ "random mac address will be used: %pM\n",
++ common->macaddr);
++ }
+
+ return 0;
+ }
diff --git a/package/mac80211/patches/403-ath_regd_optional.patch b/package/mac80211/patches/403-ath_regd_optional.patch
new file mode 100644
index 000000000..1854c271e
--- /dev/null
+++ b/package/mac80211/patches/403-ath_regd_optional.patch
@@ -0,0 +1,46 @@
+--- a/drivers/net/wireless/ath/regd.c
++++ b/drivers/net/wireless/ath/regd.c
+@@ -200,6 +200,10 @@ ath_reg_apply_beaconing_flags(struct wip
+ u32 bandwidth = 0;
+ int r;
+
++#ifdef ATH_USER_REGD
++ return;
++#endif
++
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+
+ if (!wiphy->bands[band])
+@@ -259,6 +263,10 @@ ath_reg_apply_active_scan_flags(struct w
+ u32 bandwidth = 0;
+ int r;
+
++#ifdef ATH_USER_REGD
++ return;
++#endif
++
+ sband = wiphy->bands[IEEE80211_BAND_2GHZ];
+ if (!sband)
+ return;
+@@ -308,6 +316,10 @@ static void ath_reg_apply_radar_flags(st
+ struct ieee80211_channel *ch;
+ unsigned int i;
+
++#ifdef ATH_USER_REGD
++ return;
++#endif
++
+ if (!wiphy->bands[IEEE80211_BAND_5GHZ])
+ return;
+
+@@ -514,6 +526,10 @@ ath_regd_init_wiphy(struct ath_regulator
+ {
+ const struct ieee80211_regdomain *regd;
+
++#ifdef ATH_USER_REGD
++ return 0;
++#endif
++
+ wiphy->reg_notifier = reg_notifier;
+ wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
+
diff --git a/package/mac80211/patches/404-world_regd_fixup.patch b/package/mac80211/patches/404-world_regd_fixup.patch
new file mode 100644
index 000000000..d609b55e0
--- /dev/null
+++ b/package/mac80211/patches/404-world_regd_fixup.patch
@@ -0,0 +1,84 @@
+--- a/drivers/net/wireless/ath/regd.c
++++ b/drivers/net/wireless/ath/regd.c
+@@ -44,7 +44,8 @@ static int __ath_regd_init(struct ath_re
+ NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
+
+ /* We allow IBSS on these on a case by case basis by regulatory domain */
+-#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 40, 0, 30,\
++#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5250, 40, 0, 30, 0), \
++ REG_RULE(5250, 5350+10, 40, 0, 30,\
+ NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+ #define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 40, 0, 30,\
+ NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+@@ -62,57 +63,56 @@ static int __ath_regd_init(struct ath_re
+ #define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \
+ ATH9K_5GHZ_5725_5850
+
++#define REGD_RULES(...) \
++ .reg_rules = { __VA_ARGS__ }, \
++ .n_reg_rules = ARRAY_SIZE(((struct ieee80211_reg_rule[]) { __VA_ARGS__ }))
++
+ /* Can be used for:
+ * 0x60, 0x61, 0x62 */
+ static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = {
+- .n_reg_rules = 5,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH9K_2GHZ_ALL,
+ ATH9K_5GHZ_ALL,
+- }
++ )
+ };
+
+ /* Can be used by 0x63 and 0x65 */
+ static const struct ieee80211_regdomain ath_world_regdom_63_65 = {
+- .n_reg_rules = 4,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH9K_2GHZ_CH01_11,
+ ATH9K_2GHZ_CH12_13,
+ ATH9K_5GHZ_NO_MIDBAND,
+- }
++ )
+ };
+
+ /* Can be used by 0x64 only */
+ static const struct ieee80211_regdomain ath_world_regdom_64 = {
+- .n_reg_rules = 3,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH9K_2GHZ_CH01_11,
+ ATH9K_5GHZ_NO_MIDBAND,
+- }
++ )
+ };
+
+ /* Can be used by 0x66 and 0x69 */
+ static const struct ieee80211_regdomain ath_world_regdom_66_69 = {
+- .n_reg_rules = 3,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH9K_2GHZ_CH01_11,
+ ATH9K_5GHZ_ALL,
+- }
++ )
+ };
+
+ /* Can be used by 0x67, 0x68, 0x6A and 0x6C */
+ static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = {
+- .n_reg_rules = 4,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH9K_2GHZ_CH01_11,
+ ATH9K_2GHZ_CH12_13,
+ ATH9K_5GHZ_ALL,
+- }
++ )
+ };
+
+ static inline bool is_wwr_sku(u16 regd)
diff --git a/package/mac80211/patches/405-regd_no_assoc_hints.patch b/package/mac80211/patches/405-regd_no_assoc_hints.patch
new file mode 100644
index 000000000..8a5c2a2e3
--- /dev/null
+++ b/package/mac80211/patches/405-regd_no_assoc_hints.patch
@@ -0,0 +1,20 @@
+--- a/net/wireless/reg.c
++++ b/net/wireless/reg.c
+@@ -1796,6 +1796,8 @@ void regulatory_hint_11d(struct wiphy *w
+ enum environment_cap env = ENVIRON_ANY;
+ struct regulatory_request *request;
+
++ return;
++
+ mutex_lock(&reg_mutex);
+
+ if (unlikely(!last_request))
+@@ -2030,6 +2032,8 @@ static void restore_regulatory_settings(
+
+ void regulatory_hint_disconnect(void)
+ {
++ return;
++
+ REG_DBG_PRINT("All devices are disconnected, going to "
+ "restore regulatory settings\n");
+ restore_regulatory_settings(false);
diff --git a/package/mac80211/patches/406-ath_regd_us.patch b/package/mac80211/patches/406-ath_regd_us.patch
new file mode 100644
index 000000000..cc5587780
--- /dev/null
+++ b/package/mac80211/patches/406-ath_regd_us.patch
@@ -0,0 +1,26 @@
+--- a/drivers/net/wireless/ath/regd_common.h
++++ b/drivers/net/wireless/ath/regd_common.h
+@@ -32,6 +32,7 @@ enum EnumRd {
+ FCC2_WORLD = 0x21,
+ FCC2_ETSIC = 0x22,
+ FCC6_WORLD = 0x23,
++ FCC3_FCCA_2 = 0x2A,
+ FRANCE_RES = 0x31,
+ FCC3_FCCA = 0x3A,
+ FCC3_WORLD = 0x3B,
+@@ -167,6 +168,7 @@ static struct reg_dmn_pair_mapping regDo
+ {FCC2_WORLD, CTL_FCC, CTL_ETSI},
+ {FCC2_ETSIC, CTL_FCC, CTL_ETSI},
+ {FCC3_FCCA, CTL_FCC, CTL_FCC},
++ {FCC3_FCCA_2, CTL_FCC, CTL_FCC},
+ {FCC3_WORLD, CTL_FCC, CTL_ETSI},
+ {FCC4_FCCA, CTL_FCC, CTL_FCC},
+ {FCC5_FCCA, CTL_FCC, CTL_FCC},
+@@ -463,6 +465,7 @@ static struct country_code_to_enum_rd al
+ {CTRY_UAE, NULL1_WORLD, "AE"},
+ {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"},
+ {CTRY_UNITED_STATES, FCC3_FCCA, "US"},
++ {CTRY_UNITED_STATES, FCC3_FCCA_2, "US"},
+ /* This "PS" is for US public safety actually... to support this we
+ * would need to assign new special alpha2 to CRDA db as with the world
+ * regdomain and use another alpha2 */
diff --git a/package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch b/package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
new file mode 100644
index 000000000..aabf3c3f4
--- /dev/null
+++ b/package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
@@ -0,0 +1,10 @@
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -667,6 +667,7 @@ static const struct ieee80211_iface_limi
+ #ifdef CONFIG_MAC80211_MESH
+ BIT(NL80211_IFTYPE_MESH_POINT) |
+ #endif
++ BIT(NL80211_IFTYPE_ADHOC) |
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_P2P_GO) },
+ };
diff --git a/package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch b/package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch
new file mode 100644
index 000000000..8e02950e4
--- /dev/null
+++ b/package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch
@@ -0,0 +1,46 @@
+--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
++++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+@@ -89,13 +89,8 @@ ath5k_add_interface(struct ieee80211_hw
+ goto end;
+ }
+
+- /* Don't allow other interfaces if one ad-hoc is configured.
+- * TODO: Fix the problems with ad-hoc and multiple other interfaces.
+- * We would need to operate the HW in ad-hoc mode to allow TSF updates
+- * for the IBSS, but this breaks with additional AP or STA interfaces
+- * at the moment. */
+- if (ah->num_adhoc_vifs ||
+- (ah->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
++ /* Don't allow more than one ad-hoc interface */
++ if (ah->num_adhoc_vifs && vif->type == NL80211_IFTYPE_ADHOC) {
+ ATH5K_ERR(ah, "Only one single ad-hoc interface is allowed.\n");
+ ret = -ELNRNG;
+ goto end;
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -1878,7 +1878,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
+ }
+
+ if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs +
+- ah->num_mesh_vifs > 1) ||
++ ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) ||
+ ah->opmode == NL80211_IFTYPE_MESH_POINT) {
+ u64 tsf = ath5k_hw_get_tsf64(ah);
+ u32 tsftu = TSF_TO_TU(tsf);
+@@ -1964,7 +1964,7 @@ ath5k_beacon_update_timers(struct ath5k_
+
+ intval = ah->bintval & AR5K_BEACON_PERIOD;
+ if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs
+- + ah->num_mesh_vifs > 1) {
++ + ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) {
+ intval /= ATH_BCBUF; /* staggered multi-bss beacons */
+ if (intval < 15)
+ ATH5K_WARN(ah, "intval %u is too low, min 15\n",
+@@ -2427,6 +2427,7 @@ static const struct ieee80211_iface_limi
+ #ifdef CONFIG_MAC80211_MESH
+ BIT(NL80211_IFTYPE_MESH_POINT) |
+ #endif
++ BIT(NL80211_IFTYPE_ADHOC) |
+ BIT(NL80211_IFTYPE_AP) },
+ };
+
diff --git a/package/mac80211/patches/412-mac80211_allow_adhoc_and_ap.patch b/package/mac80211/patches/412-mac80211_allow_adhoc_and_ap.patch
new file mode 100644
index 000000000..93f35567e
--- /dev/null
+++ b/package/mac80211/patches/412-mac80211_allow_adhoc_and_ap.patch
@@ -0,0 +1,20 @@
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -792,17 +792,11 @@ int ieee80211_register_hw(struct ieee802
+ */
+ for (i = 0; i < hw->wiphy->n_iface_combinations; i++) {
+ const struct ieee80211_iface_combination *c;
+- int j;
+
+ c = &hw->wiphy->iface_combinations[i];
+
+ if (c->num_different_channels > 1)
+ return -EINVAL;
+-
+- for (j = 0; j < c->n_limits; j++)
+- if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) &&
+- c->limits[j].max > 1)
+- return -EINVAL;
+ }
+
+ #ifndef CONFIG_MAC80211_MESH
diff --git a/package/mac80211/patches/420-ath5k_disable_fast_cc.patch b/package/mac80211/patches/420-ath5k_disable_fast_cc.patch
new file mode 100644
index 000000000..bd661c6fb
--- /dev/null
+++ b/package/mac80211/patches/420-ath5k_disable_fast_cc.patch
@@ -0,0 +1,18 @@
+--- a/drivers/net/wireless/ath/ath5k/reset.c
++++ b/drivers/net/wireless/ath/ath5k/reset.c
+@@ -1156,6 +1156,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum
+ tsf_lo = 0;
+ mode = 0;
+
++#if 0
+ /*
+ * Sanity check for fast flag
+ * Fast channel change only available
+@@ -1163,6 +1164,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum
+ */
+ if (fast && (ah->ah_radio != AR5K_RF2413) &&
+ (ah->ah_radio != AR5K_RF5413))
++#endif
+ fast = false;
+
+ /* Disable sleep clock operation
diff --git a/package/mac80211/patches/430-add_ath5k_platform.patch b/package/mac80211/patches/430-add_ath5k_platform.patch
new file mode 100644
index 000000000..b213e2a81
--- /dev/null
+++ b/package/mac80211/patches/430-add_ath5k_platform.patch
@@ -0,0 +1,33 @@
+--- /dev/null
++++ b/include/linux/ath5k_platform.h
+@@ -0,0 +1,30 @@
++/*
++ * Copyright (c) 2008 Atheros Communications Inc.
++ * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
++ * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
++ * Copyright (c) 2010 Daniel Golle <daniel.golle@gmail.com>
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#ifndef _LINUX_ATH5K_PLATFORM_H
++#define _LINUX_ATH5K_PLATFORM_H
++
++#define ATH5K_PLAT_EEP_MAX_WORDS 2048
++
++struct ath5k_platform_data {
++ u16 *eeprom_data;
++ u8 *macaddr;
++};
++
++#endif /* _LINUX_ATH5K_PLATFORM_H */
diff --git a/package/mac80211/patches/431-add_platform_eeprom_support_to_ath5k.patch b/package/mac80211/patches/431-add_platform_eeprom_support_to_ath5k.patch
new file mode 100644
index 000000000..6cafa236a
--- /dev/null
+++ b/package/mac80211/patches/431-add_platform_eeprom_support_to_ath5k.patch
@@ -0,0 +1,56 @@
+--- a/drivers/net/wireless/ath/ath5k/pci.c
++++ b/drivers/net/wireless/ath/ath5k/pci.c
+@@ -23,6 +23,7 @@
+ #include <linux/pci-aspm.h>
+ #include <linux/etherdevice.h>
+ #include <linux/module.h>
++#include <linux/ath5k_platform.h>
+ #include "../ath.h"
+ #include "ath5k.h"
+ #include "debug.h"
+@@ -74,7 +75,7 @@ static void ath5k_pci_read_cachesize(str
+ }
+
+ /*
+- * Read from eeprom
++ * Read from eeprom or platform_data
+ */
+ static bool
+ ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data)
+@@ -82,6 +83,19 @@ ath5k_pci_eeprom_read(struct ath_common
+ struct ath5k_hw *ah = (struct ath5k_hw *) common->ah;
+ u32 status, timeout;
+
++ struct ath5k_platform_data *pdata = NULL;
++
++ if (ah->pdev)
++ pdata = ah->pdev->dev.platform_data;
++
++ if (pdata && pdata->eeprom_data && pdata->eeprom_data[61] == AR5K_EEPROM_MAGIC_VALUE) {
++ if (offset >= ATH5K_PLAT_EEP_MAX_WORDS)
++ return false;
++
++ *data = pdata->eeprom_data[offset];
++ return true;
++ }
++
+ /*
+ * Initialize EEPROM access
+ */
+@@ -125,6 +139,16 @@ static int ath5k_pci_eeprom_read_mac(str
+ u16 data;
+ int octet;
+
++ struct ath5k_platform_data *pdata = NULL;
++
++ if (ah->pdev)
++ pdata = ah->pdev->dev.platform_data;
++
++ if (pdata && pdata->macaddr) {
++ memcpy(mac, pdata->macaddr, ETH_ALEN);
++ return 0;
++ }
++
+ AR5K_EEPROM_READ(0x20, data);
+
+ for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
diff --git a/package/mac80211/patches/432-ath5k_add_pciids.patch b/package/mac80211/patches/432-ath5k_add_pciids.patch
new file mode 100644
index 000000000..8db5e1b3f
--- /dev/null
+++ b/package/mac80211/patches/432-ath5k_add_pciids.patch
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/ath/ath5k/pci.c
++++ b/drivers/net/wireless/ath/ath5k/pci.c
+@@ -50,6 +50,8 @@ static DEFINE_PCI_DEVICE_TABLE(ath5k_pci
+ { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */
+ { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */
+ { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */
++ { PCI_VDEVICE(ATHEROS, 0xff16) }, /* 2413,2414 sx76x on lantiq_danube */
++ { PCI_VDEVICE(ATHEROS, 0xff1a) }, /* 2417 arv45xx on lantiq_danube */
+ { PCI_VDEVICE(ATHEROS, 0xff1b) }, /* AR5BXB63 */
+ { 0 }
+ };
diff --git a/package/mac80211/patches/440-ath5k_channel_bw_debugfs.patch b/package/mac80211/patches/440-ath5k_channel_bw_debugfs.patch
new file mode 100644
index 000000000..a2141ab24
--- /dev/null
+++ b/package/mac80211/patches/440-ath5k_channel_bw_debugfs.patch
@@ -0,0 +1,113 @@
+This adds a bwmode debugfs file which can be used to set alternate
+channel operating bandwidths. Only tested with AR5413 and only at
+5 and 20 mhz channels.
+
+Signed-off-by: Pat Erley <pat-lkml at erley.org>
+---
+Other devices will need to be added to the switch in write_file_bwmode
+
+drivers/net/wireless/ath/ath5k/debug.c | 86 ++++++++++++++++++++++++++++++++
+ 1 files changed, 86 insertions(+), 0 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath5k/debug.c
++++ b/drivers/net/wireless/ath/ath5k/debug.c
+@@ -813,6 +813,89 @@ static const struct file_operations fops
+ .llseek = default_llseek,
+ };
+
++/* debugfs: bwmode */
++
++static ssize_t read_file_bwmode(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath5k_hw *ah = file->private_data;
++ char buf[15];
++ unsigned int len = 0;
++
++ int cur_ah_bwmode = ah->ah_bwmode;
++
++#define print_selected(MODE, LABEL) \
++ if (cur_ah_bwmode == MODE) \
++ len += snprintf(buf+len, sizeof(buf)-len, "[%s]", LABEL); \
++ else \
++ len += snprintf(buf+len, sizeof(buf)-len, "%s", LABEL); \
++ len += snprintf(buf+len, sizeof(buf)-len, " ");
++
++ print_selected(AR5K_BWMODE_5MHZ, "5");
++ print_selected(AR5K_BWMODE_10MHZ, "10");
++ print_selected(AR5K_BWMODE_DEFAULT, "20");
++ print_selected(AR5K_BWMODE_40MHZ, "40");
++#undef print_selected
++
++ len += snprintf(buf+len, sizeof(buf)-len, "\n");
++
++ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
++}
++
++static ssize_t write_file_bwmode(struct file *file,
++ const char __user *userbuf,
++ size_t count, loff_t *ppos)
++{
++ struct ath5k_hw *ah = file->private_data;
++ char buf[3];
++ int bw = 20;
++ int tobwmode = AR5K_BWMODE_DEFAULT;
++
++ if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
++ return -EFAULT;
++
++ /* TODO: Add check for active interface */
++
++ if(strncmp(buf, "5", 1) == 0 ) {
++ tobwmode = AR5K_BWMODE_5MHZ;
++ bw = 5;
++ } else if ( strncmp(buf, "10", 2) == 0 ) {
++ tobwmode = AR5K_BWMODE_10MHZ;
++ bw = 10;
++ } else if ( strncmp(buf, "20", 2) == 0 ) {
++ tobwmode = AR5K_BWMODE_DEFAULT;
++ bw = 20;
++ } else if ( strncmp(buf, "40", 2) == 0 ) {
++ tobwmode = AR5K_BWMODE_40MHZ;
++ bw = 40;
++ } else
++ return -EINVAL;
++
++ ATH5K_INFO(ah, "Changing to %imhz channel width[%i]\n",
++ bw, tobwmode);
++
++ switch (ah->ah_radio) {
++ /* TODO: only define radios that actually support 5/10mhz channels */
++ case AR5K_RF5413: case AR5K_RF5110: case AR5K_RF5111: case AR5K_RF5112: case AR5K_RF2413: case AR5K_RF2316: case AR5K_RF2317: case AR5K_RF2425:
++ if(ah->ah_bwmode != tobwmode) {
++ mutex_lock(&ah->lock);
++ ah->ah_bwmode = tobwmode;
++ mutex_unlock(&ah->lock);
++ }
++ break;
++ default:
++ return -EOPNOTSUPP;
++ }
++ return count;
++}
++
++static const struct file_operations fops_bwmode = {
++ .read = read_file_bwmode,
++ .write = write_file_bwmode,
++ .open = simple_open,
++ .owner = THIS_MODULE,
++ .llseek = default_llseek,
++};
+
+ /* debugfs: queues etc */
+
+@@ -904,6 +987,9 @@ ath5k_debug_init_device(struct ath5k_hw
+ debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, ah,
+ &fops_beacon);
+
++ debugfs_create_file("bwmode", S_IWUSR | S_IRUSR, phydir, ah,
++ &fops_bwmode);
++
+ debugfs_create_file("reset", S_IWUSR, phydir, ah, &fops_reset);
+
+ debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, ah,
diff --git a/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch b/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch
new file mode 100644
index 000000000..11272b96e
--- /dev/null
+++ b/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch
@@ -0,0 +1,65 @@
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1532,6 +1532,53 @@ static const struct file_operations fops
+
+ #endif
+
++static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ struct ath_hw *ah = sc->sc_ah;
++ struct ath_common *common = ath9k_hw_common(ah);
++ int bytes = 0;
++ int pos = *ppos;
++ int size = 4096;
++ u16 val;
++ int i;
++
++ if (AR_SREV_9300_20_OR_LATER(ah))
++ size = 16384;
++
++ if (*ppos < 0)
++ return -EINVAL;
++
++ if (count > size - *ppos)
++ count = size - *ppos;
++
++ for (i = *ppos / 2; count > 0; count -= bytes, *ppos += bytes, i++) {
++ void *from = &val;
++
++ if (!common->bus_ops->eeprom_read(common, i, &val))
++ val = 0xffff;
++
++ if (*ppos % 2) {
++ from++;
++ bytes = 1;
++ } else if (count == 1) {
++ bytes = 1;
++ } else {
++ bytes = 2;
++ }
++ copy_to_user(user_buf, from, bytes);
++ user_buf += bytes;
++ }
++ return *ppos - pos;
++}
++
++static const struct file_operations fops_eeprom = {
++ .read = read_file_eeprom,
++ .open = simple_open,
++ .owner = THIS_MODULE
++};
++
+ int ath9k_init_debug(struct ath_hw *ah)
+ {
+ struct ath_common *common = ath9k_hw_common(ah);
+@@ -1603,5 +1650,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+ debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR,
+ sc->debug.debugfs_phy, &sc->sc_ah->gpio_val);
+
++ debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
++ &fops_eeprom);
++
+ return 0;
+ }
diff --git a/package/mac80211/patches/501-ath9k-eeprom_endianess.patch b/package/mac80211/patches/501-ath9k-eeprom_endianess.patch
new file mode 100644
index 000000000..52ae70fc6
--- /dev/null
+++ b/package/mac80211/patches/501-ath9k-eeprom_endianess.patch
@@ -0,0 +1,102 @@
+--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
+@@ -266,7 +266,7 @@ static int ath9k_hw_def_check_eeprom(str
+ {
+ struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+ struct ath_common *common = ath9k_hw_common(ah);
+- u16 *eepdata, temp, magic, magic2;
++ u16 *eepdata, temp, magic;
+ u32 sum = 0, el;
+ bool need_swap = false;
+ int i, addr, size;
+@@ -276,27 +276,16 @@ static int ath9k_hw_def_check_eeprom(str
+ return false;
+ }
+
+- if (!ath9k_hw_use_flash(ah)) {
+- ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic);
+-
+- if (magic != AR5416_EEPROM_MAGIC) {
+- magic2 = swab16(magic);
+-
+- if (magic2 == AR5416_EEPROM_MAGIC) {
+- size = sizeof(struct ar5416_eeprom_def);
+- need_swap = true;
+- eepdata = (u16 *) (&ah->eeprom);
+-
+- for (addr = 0; addr < size / sizeof(u16); addr++) {
+- temp = swab16(*eepdata);
+- *eepdata = temp;
+- eepdata++;
+- }
+- } else {
+- ath_err(common,
+- "Invalid EEPROM Magic. Endianness mismatch.\n");
+- return -EINVAL;
+- }
++ if (swab16(magic) == AR5416_EEPROM_MAGIC &&
++ !(ah->ah_flags & AH_NO_EEP_SWAP)) {
++ size = sizeof(struct ar5416_eeprom_def);
++ need_swap = true;
++ eepdata = (u16 *) (&ah->eeprom);
++
++ for (addr = 0; addr < size / sizeof(u16); addr++) {
++ temp = swab16(*eepdata);
++ *eepdata = temp;
++ eepdata++;
+ }
+ }
+
+--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+@@ -195,7 +195,7 @@ static int ath9k_hw_4k_check_eeprom(stru
+ int i, addr;
+
+
+- if (!ath9k_hw_use_flash(ah)) {
++ if (!(ah->ah_flags & AH_NO_EEP_SWAP)) {
+ if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET,
+ &magic)) {
+ ath_err(common, "Reading Magic # failed\n");
+--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+@@ -189,7 +189,7 @@ static int ath9k_hw_ar9287_check_eeprom(
+ struct ar9287_eeprom *eep = &ah->eeprom.map9287;
+ struct ath_common *common = ath9k_hw_common(ah);
+
+- if (!ath9k_hw_use_flash(ah)) {
++ if (!(ah->ah_flags & AH_NO_EEP_SWAP)) {
+ if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET,
+ &magic)) {
+ ath_err(common, "Reading Magic # failed\n");
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -705,6 +705,7 @@ enum ath_cal_list {
+ #define AH_USE_EEPROM 0x1
+ #define AH_UNPLUGGED 0x2 /* The card has been physically removed. */
+ #define AH_FASTCC 0x4
++#define AH_NO_EEP_SWAP 0x8 /* Do not swap EEPROM data */
+
+ struct ath_hw {
+ struct ath_ops reg_ops;
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -537,6 +537,8 @@ static int ath9k_init_softc(u16 devid, s
+ ah->is_clk_25mhz = pdata->is_clk_25mhz;
+ ah->get_mac_revision = pdata->get_mac_revision;
+ ah->external_reset = pdata->external_reset;
++ if (!pdata->endian_check)
++ ah->ah_flags |= AH_NO_EEP_SWAP;
+ }
+
+ common = ath9k_hw_common(ah);
+--- a/include/linux/ath9k_platform.h
++++ b/include/linux/ath9k_platform.h
+@@ -29,6 +29,7 @@ struct ath9k_platform_data {
+ u32 gpio_mask;
+ u32 gpio_val;
+
++ bool endian_check;
+ bool is_clk_25mhz;
+ int (*get_mac_revision)(void);
+ int (*external_reset)(void);
diff --git a/package/mac80211/patches/502-ath9k_ahb_init.patch b/package/mac80211/patches/502-ath9k_ahb_init.patch
new file mode 100644
index 000000000..7d3df6b20
--- /dev/null
+++ b/package/mac80211/patches/502-ath9k_ahb_init.patch
@@ -0,0 +1,32 @@
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -926,23 +926,23 @@ static int __init ath9k_init(void)
+ goto err_out;
+ }
+
+- error = ath_pci_init();
++ error = ath_ahb_init();
+ if (error < 0) {
+- pr_err("No PCI devices found, driver not installed\n");
+ error = -ENODEV;
+ goto err_rate_unregister;
+ }
+
+- error = ath_ahb_init();
++ error = ath_pci_init();
+ if (error < 0) {
++ pr_err("No PCI devices found, driver not installed\n");
+ error = -ENODEV;
+- goto err_pci_exit;
++ goto err_ahb_exit;
+ }
+
+ return 0;
+
+- err_pci_exit:
+- ath_pci_exit();
++ err_ahb_exit:
++ ath_ahb_exit();
+
+ err_rate_unregister:
+ ath_rate_control_unregister();
diff --git a/package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch b/package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch
new file mode 100644
index 000000000..3b78afae3
--- /dev/null
+++ b/package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch
@@ -0,0 +1,13 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1949,8 +1949,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+ REG_WRITE(ah, AR_OBS, 8);
+
+ if (ah->config.rx_intr_mitigation) {
+- REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
+- REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
++ REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 250);
++ REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 500);
+ }
+
+ if (ah->config.tx_intr_mitigation) {
diff --git a/package/mac80211/patches/511-ath9k_reduce_rxbuf.patch b/package/mac80211/patches/511-ath9k_reduce_rxbuf.patch
new file mode 100644
index 000000000..db13fea1b
--- /dev/null
+++ b/package/mac80211/patches/511-ath9k_reduce_rxbuf.patch
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -122,7 +122,7 @@ void ath_descdma_cleanup(struct ath_soft
+ /* RX / TX */
+ /***********/
+
+-#define ATH_RXBUF 512
++#define ATH_RXBUF 256
+ #define ATH_TXBUF 512
+ #define ATH_TXBUF_RESERVE 5
+ #define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE)
diff --git a/package/mac80211/patches/512-ath9k_channelbw_debugfs.patch b/package/mac80211/patches/512-ath9k_channelbw_debugfs.patch
new file mode 100644
index 000000000..d4087a0b2
--- /dev/null
+++ b/package/mac80211/patches/512-ath9k_channelbw_debugfs.patch
@@ -0,0 +1,128 @@
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -659,6 +659,7 @@ struct ath_softc {
+ struct ieee80211_hw *hw;
+ struct device *dev;
+
++ u32 chan_bw;
+ struct survey_info *cur_survey;
+ struct survey_info survey[ATH9K_NUM_CHANNELS];
+
+@@ -734,6 +735,7 @@ struct ath_softc {
+ #endif
+ };
+
++int ath9k_config(struct ieee80211_hw *hw, u32 changed);
+ void ath9k_tasklet(unsigned long data);
+ int ath_cabq_update(struct ath_softc *);
+
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1579,6 +1579,50 @@ static const struct file_operations fops
+ .owner = THIS_MODULE
+ };
+
++
++static ssize_t read_file_chan_bw(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ char buf[32];
++ unsigned int len;
++
++ len = sprintf(buf, "0x%08x\n", sc->chan_bw);
++ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
++}
++
++static ssize_t write_file_chan_bw(struct file *file, const char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ unsigned long chan_bw;
++ char buf[32];
++ ssize_t len;
++
++ len = min(count, sizeof(buf) - 1);
++ if (copy_from_user(buf, user_buf, len))
++ return -EFAULT;
++
++ buf[len] = '\0';
++ if (strict_strtoul(buf, 0, &chan_bw))
++ return -EINVAL;
++
++ sc->chan_bw = chan_bw;
++ if (!(sc->sc_flags & SC_OP_INVALID))
++ ath9k_config(sc->hw, IEEE80211_CONF_CHANGE_CHANNEL);
++
++ return count;
++}
++
++static const struct file_operations fops_chanbw = {
++ .read = read_file_chan_bw,
++ .write = write_file_chan_bw,
++ .open = simple_open,
++ .owner = THIS_MODULE,
++ .llseek = default_llseek,
++};
++
++
+ int ath9k_init_debug(struct ath_hw *ah)
+ {
+ struct ath_common *common = ath9k_hw_common(ah);
+@@ -1653,5 +1697,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+ debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
+ &fops_eeprom);
+
++ debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
++ sc, &fops_chanbw);
++
+ return 0;
+ }
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1127,7 +1127,7 @@ static void ath9k_disable_ps(struct ath_
+ ath_dbg(common, PS, "PowerSave disabled\n");
+ }
+
+-static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
++int ath9k_config(struct ieee80211_hw *hw, u32 changed)
+ {
+ struct ath_softc *sc = hw->priv;
+ struct ath_hw *ah = sc->sc_ah;
+@@ -1181,9 +1181,11 @@ static int ath9k_config(struct ieee80211
+
+ if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) {
+ struct ieee80211_channel *curchan = hw->conf.channel;
++ struct ath9k_channel *hchan;
+ int pos = curchan->hw_value;
+ int old_pos = -1;
+ unsigned long flags;
++ u32 oldflags;
+
+ if (ah->curchan)
+ old_pos = ah->curchan - &ah->channels[0];
+@@ -1226,7 +1228,23 @@ static int ath9k_config(struct ieee80211
+ memset(&sc->survey[pos], 0, sizeof(struct survey_info));
+ }
+
+- if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) {
++ hchan = &sc->sc_ah->channels[pos];
++ oldflags = hchan->channelFlags;
++ switch (sc->chan_bw) {
++ case 5:
++ hchan->channelFlags &= ~CHANNEL_HALF;
++ hchan->channelFlags |= CHANNEL_QUARTER;
++ break;
++ case 10:
++ hchan->channelFlags &= ~CHANNEL_QUARTER;
++ hchan->channelFlags |= CHANNEL_HALF;
++ break;
++ default:
++ hchan->channelFlags &= ~(CHANNEL_HALF | CHANNEL_QUARTER);
++ break;
++ }
++
++ if (ath_set_channel(sc, hw, hchan) < 0) {
+ ath_err(common, "Unable to set channel\n");
+ mutex_unlock(&sc->mutex);
+ ath9k_ps_restore(sc);
diff --git a/package/mac80211/patches/513-mac80211_reduce_txqueuelen.patch b/package/mac80211/patches/513-mac80211_reduce_txqueuelen.patch
new file mode 100644
index 000000000..25f4fdd40
--- /dev/null
+++ b/package/mac80211/patches/513-mac80211_reduce_txqueuelen.patch
@@ -0,0 +1,10 @@
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -964,6 +964,7 @@ static const struct net_device_ops ieee8
+ static void ieee80211_if_setup(struct net_device *dev)
+ {
+ ether_setup(dev);
++ dev->tx_queue_len = 32;
+ dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+ netdev_attach_ops(dev, &ieee80211_dataif_ops);
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29))
diff --git a/package/mac80211/patches/520-mac80211_cur_txpower.patch b/package/mac80211/patches/520-mac80211_cur_txpower.patch
new file mode 100644
index 000000000..54f2e5040
--- /dev/null
+++ b/package/mac80211/patches/520-mac80211_cur_txpower.patch
@@ -0,0 +1,31 @@
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -1372,6 +1372,7 @@ struct ieee80211_hw {
+ u8 max_tx_aggregation_subframes;
+ u8 offchannel_tx_hw_queue;
+ u8 radiotap_mcs_details;
++ s8 cur_power_level;
+ netdev_features_t netdev_features;
+ };
+
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -1967,7 +1967,7 @@ static int ieee80211_get_tx_power(struct
+ {
+ struct ieee80211_local *local = wiphy_priv(wiphy);
+
+- *dbm = local->hw.conf.power_level;
++ *dbm = local->hw.cur_power_level;
+
+ return 0;
+ }
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -165,6 +165,7 @@ int ieee80211_hw_config(struct ieee80211
+
+ if (local->hw.conf.power_level != power) {
+ changed |= IEEE80211_CONF_CHANGE_POWER;
++ local->hw.cur_power_level = power;
+ local->hw.conf.power_level = power;
+ }
+
diff --git a/package/mac80211/patches/521-ath9k_cur_txpower.patch b/package/mac80211/patches/521-ath9k_cur_txpower.patch
new file mode 100644
index 000000000..1133cfa6b
--- /dev/null
+++ b/package/mac80211/patches/521-ath9k_cur_txpower.patch
@@ -0,0 +1,19 @@
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1251,6 +1251,8 @@ int ath9k_config(struct ieee80211_hw *hw
+ return -EINVAL;
+ }
+
++ hw->cur_power_level = sc->curtxpow / 2;
++
+ /*
+ * The most recent snapshot of channel->noisefloor for the old
+ * channel is only available after the hardware reset. Copy it to
+@@ -1265,6 +1267,7 @@ int ath9k_config(struct ieee80211_hw *hw
+ sc->config.txpowlimit = 2 * conf->power_level;
+ ath9k_cmn_update_txpow(ah, sc->curtxpow,
+ sc->config.txpowlimit, &sc->curtxpow);
++ hw->cur_power_level = sc->curtxpow / 2;
+ }
+
+ mutex_unlock(&sc->mutex);
diff --git a/package/mac80211/patches/522-ath9k_per_chain_signal_strength.patch b/package/mac80211/patches/522-ath9k_per_chain_signal_strength.patch
new file mode 100644
index 000000000..8b26a50b3
--- /dev/null
+++ b/package/mac80211/patches/522-ath9k_per_chain_signal_strength.patch
@@ -0,0 +1,384 @@
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -729,6 +729,9 @@ enum mac80211_rx_flags {
+ * @signal: signal strength when receiving this frame, either in dBm, in dB or
+ * unspecified depending on the hardware capabilities flags
+ * @IEEE80211_HW_SIGNAL_*
++ * @chains: bitmask of receive chains for which separate signal strength
++ * values were filled.
++ * @chain_signal: per-chain signal strength, same format as @signal
+ * @antenna: antenna used
+ * @rate_idx: index of data rate into band's supported rates or MCS index if
+ * HT rates are use (RX_FLAG_HT)
+@@ -749,6 +752,8 @@ struct ieee80211_rx_status {
+ u8 band;
+ u8 antenna;
+ s8 signal;
++ u8 chains;
++ s8 chain_signal[4];
+ u8 ampdu_delimiter_crc;
+ };
+
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -325,6 +325,11 @@ struct sta_info {
+ unsigned long rx_dropped;
+ int last_signal;
+ struct ewma avg_signal;
++
++ u8 chains;
++ s8 chain_signal_last[4];
++ struct ewma chain_signal_avg[4];
++
+ /* Plus 1 for non-QoS frames */
+ __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES + 1];
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -1271,6 +1271,7 @@ ieee80211_rx_h_sta_process(struct ieee80
+ struct sk_buff *skb = rx->skb;
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
++ int i;
+
+ if (!sta)
+ return RX_CONTINUE;
+@@ -1315,6 +1316,19 @@ ieee80211_rx_h_sta_process(struct ieee80
+ ewma_add(&sta->avg_signal, -status->signal);
+ }
+
++ if (status->chains) {
++ sta->chains = status->chains;
++ for (i = 0; i < 4; i++) {
++ int signal = status->chain_signal[i];
++
++ if (!(status->chains & BIT(i)))
++ continue;
++
++ sta->chain_signal_last[i] = signal;
++ ewma_add(&sta->chain_signal_avg[i], -signal);
++ }
++ }
++
+ /*
+ * Change STA power saving mode only at the end of a frame
+ * exchange sequence.
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -254,6 +254,8 @@ struct sta_info *sta_info_alloc(struct i
+ do_posix_clock_monotonic_gettime(&uptime);
+ sta->last_connected = uptime.tv_sec;
+ ewma_init(&sta->avg_signal, 1024, 8);
++ for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++)
++ ewma_init(&sta->chain_signal_avg[i], 1024, 8);
+
+ if (sta_prepare_rate_control(local, sta, gfp)) {
+ kfree(sta);
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -549,6 +549,8 @@ struct station_parameters {
+ * @STATION_INFO_STA_FLAGS: @sta_flags filled
+ * @STATION_INFO_BEACON_LOSS_COUNT: @beacon_loss_count filled
+ * @STATION_INFO_T_OFFSET: @t_offset filled
++ * @STATION_INFO_CHAIN_SIGNAL: @chain_signal filled
++ * @STATION_INFO_CHAIN_SIGNAL_AVG: @chain_signal_avg filled
+ */
+ enum station_info_flags {
+ STATION_INFO_INACTIVE_TIME = 1<<0,
+@@ -572,6 +574,8 @@ enum station_info_flags {
+ STATION_INFO_STA_FLAGS = 1<<18,
+ STATION_INFO_BEACON_LOSS_COUNT = 1<<19,
+ STATION_INFO_T_OFFSET = 1<<20,
++ STATION_INFO_CHAIN_SIGNAL = 1<<21,
++ STATION_INFO_CHAIN_SIGNAL_AVG = 1<<22,
+ };
+
+ /**
+@@ -655,6 +659,9 @@ struct sta_bss_parameters {
+ * For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
+ * @signal_avg: Average signal strength, type depends on the wiphy's signal_type.
+ * For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
++ * @chains: bitmask for filled values in @chain_signal, @chain_signal_avg
++ * @chain_signal: per-chain signal strength of last received packet in dBm
++ * @chain_signal_avg: per-chain signal strength average in dBm
+ * @txrate: current unicast bitrate from this station
+ * @rxrate: current unicast bitrate to this station
+ * @rx_packets: packets received from this station
+@@ -687,6 +694,11 @@ struct station_info {
+ u8 plink_state;
+ s8 signal;
+ s8 signal_avg;
++
++ u8 chains;
++ s8 chain_signal[4];
++ s8 chain_signal_avg[4];
++
+ struct rate_info txrate;
+ struct rate_info rxrate;
+ u32 rx_packets;
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -133,12 +133,8 @@ struct ath_rx_status {
+ u8 rs_rate;
+ u8 rs_antenna;
+ u8 rs_more;
+- int8_t rs_rssi_ctl0;
+- int8_t rs_rssi_ctl1;
+- int8_t rs_rssi_ctl2;
+- int8_t rs_rssi_ext0;
+- int8_t rs_rssi_ext1;
+- int8_t rs_rssi_ext2;
++ int8_t rs_rssi_ctl[3];
++ int8_t rs_rssi_ext[3];
+ u8 rs_isaggr;
+ u8 rs_moreaggr;
+ u8 rs_num_delims;
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -955,6 +955,7 @@ static int ath9k_rx_skb_preprocess(struc
+ bool *decrypt_error)
+ {
+ struct ath_hw *ah = common->ah;
++ int i, j;
+
+ /*
+ * everything but the rate is checked here, the rate check is done
+@@ -980,6 +981,20 @@ static int ath9k_rx_skb_preprocess(struc
+ if (rx_stats->rs_moreaggr)
+ rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
+
++ for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
++ s8 rssi;
++
++ if (!(ah->rxchainmask & BIT(i)))
++ continue;
++
++ rssi = rx_stats->rs_rssi_ctl[i];
++ if (rssi != ATH9K_RSSI_BAD) {
++ rx_status->chains |= BIT(j);
++ rx_status->chain_signal[j] = ah->noise + rssi;
++ }
++ j++;
++ }
++
+ return 0;
+ }
+
+--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+@@ -458,12 +458,12 @@ int ath9k_hw_process_rxdesc_edma(struct
+
+ /* XXX: Keycache */
+ rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined);
+- rxs->rs_rssi_ctl0 = MS(rxsp->status1, AR_RxRSSIAnt00);
+- rxs->rs_rssi_ctl1 = MS(rxsp->status1, AR_RxRSSIAnt01);
+- rxs->rs_rssi_ctl2 = MS(rxsp->status1, AR_RxRSSIAnt02);
+- rxs->rs_rssi_ext0 = MS(rxsp->status5, AR_RxRSSIAnt10);
+- rxs->rs_rssi_ext1 = MS(rxsp->status5, AR_RxRSSIAnt11);
+- rxs->rs_rssi_ext2 = MS(rxsp->status5, AR_RxRSSIAnt12);
++ rxs->rs_rssi_ctl[0] = MS(rxsp->status1, AR_RxRSSIAnt00);
++ rxs->rs_rssi_ctl[1] = MS(rxsp->status1, AR_RxRSSIAnt01);
++ rxs->rs_rssi_ctl[2] = MS(rxsp->status1, AR_RxRSSIAnt02);
++ rxs->rs_rssi_ext[0] = MS(rxsp->status5, AR_RxRSSIAnt10);
++ rxs->rs_rssi_ext[1] = MS(rxsp->status5, AR_RxRSSIAnt11);
++ rxs->rs_rssi_ext[2] = MS(rxsp->status5, AR_RxRSSIAnt12);
+
+ if (rxsp->status11 & AR_RxKeyIdxValid)
+ rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx);
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -553,25 +553,25 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a
+
+ if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) {
+ rs->rs_rssi = ATH9K_RSSI_BAD;
+- rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD;
+- rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD;
+- rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD;
+- rs->rs_rssi_ext0 = ATH9K_RSSI_BAD;
+- rs->rs_rssi_ext1 = ATH9K_RSSI_BAD;
+- rs->rs_rssi_ext2 = ATH9K_RSSI_BAD;
++ rs->rs_rssi_ctl[0] = ATH9K_RSSI_BAD;
++ rs->rs_rssi_ctl[1] = ATH9K_RSSI_BAD;
++ rs->rs_rssi_ctl[2] = ATH9K_RSSI_BAD;
++ rs->rs_rssi_ext[0] = ATH9K_RSSI_BAD;
++ rs->rs_rssi_ext[1] = ATH9K_RSSI_BAD;
++ rs->rs_rssi_ext[2] = ATH9K_RSSI_BAD;
+ } else {
+ rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
+- rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0,
++ rs->rs_rssi_ctl[0] = MS(ads.ds_rxstatus0,
+ AR_RxRSSIAnt00);
+- rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0,
++ rs->rs_rssi_ctl[1] = MS(ads.ds_rxstatus0,
+ AR_RxRSSIAnt01);
+- rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0,
++ rs->rs_rssi_ctl[2] = MS(ads.ds_rxstatus0,
+ AR_RxRSSIAnt02);
+- rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4,
++ rs->rs_rssi_ext[0] = MS(ads.ds_rxstatus4,
+ AR_RxRSSIAnt10);
+- rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4,
++ rs->rs_rssi_ext[1] = MS(ads.ds_rxstatus4,
+ AR_RxRSSIAnt11);
+- rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4,
++ rs->rs_rssi_ext[2] = MS(ads.ds_rxstatus4,
+ AR_RxRSSIAnt12);
+ }
+ if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -997,12 +997,12 @@ void ath_debug_stat_rx(struct ath_softc
+ #ifdef CONFIG_ATH9K_MAC_DEBUG
+ spin_lock(&sc->debug.samp_lock);
+ RX_SAMP_DBG(jiffies) = jiffies;
+- RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl0;
+- RX_SAMP_DBG(rssi_ctl1) = rs->rs_rssi_ctl1;
+- RX_SAMP_DBG(rssi_ctl2) = rs->rs_rssi_ctl2;
+- RX_SAMP_DBG(rssi_ext0) = rs->rs_rssi_ext0;
+- RX_SAMP_DBG(rssi_ext1) = rs->rs_rssi_ext1;
+- RX_SAMP_DBG(rssi_ext2) = rs->rs_rssi_ext2;
++ RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl[0];
++ RX_SAMP_DBG(rssi_ctl1) = rs->rs_rssi_ctl[1];
++ RX_SAMP_DBG(rssi_ctl2) = rs->rs_rssi_ctl[2];
++ RX_SAMP_DBG(rssi_ext0) = rs->rs_rssi_ext[0];
++ RX_SAMP_DBG(rssi_ext1) = rs->rs_rssi_ext[1];
++ RX_SAMP_DBG(rssi_ext2) = rs->rs_rssi_ext[2];
+ RX_SAMP_DBG(antenna) = rs->rs_antenna;
+ RX_SAMP_DBG(rssi) = rs->rs_rssi;
+ RX_SAMP_DBG(rate) = rs->rs_rate;
+--- a/include/linux/nl80211.h
++++ b/include/linux/nl80211.h
+@@ -1760,6 +1760,8 @@ enum nl80211_sta_bss_param {
+ * @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update.
+ * @NL80211_STA_INFO_BEACON_LOSS: count of times beacon loss was detected (u32)
+ * @NL80211_STA_INFO_T_OFFSET: timing offset with respect to this STA (s64)
++ * @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU
++ * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average
+ * @__NL80211_STA_INFO_AFTER_LAST: internal
+ * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ */
+@@ -1784,6 +1786,8 @@ enum nl80211_sta_info {
+ NL80211_STA_INFO_STA_FLAGS,
+ NL80211_STA_INFO_BEACON_LOSS,
+ NL80211_STA_INFO_T_OFFSET,
++ NL80211_STA_INFO_CHAIN_SIGNAL,
++ NL80211_STA_INFO_CHAIN_SIGNAL_AVG,
+
+ /* keep last */
+ __NL80211_STA_INFO_AFTER_LAST,
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -2769,6 +2769,32 @@ nla_put_failure:
+ return false;
+ }
+
++static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,
++ int id)
++{
++ void *attr;
++ int i = 0;
++
++ if (!mask)
++ return true;
++
++ attr = nla_nest_start(msg, id);
++ if (!attr)
++ return false;
++
++ for (i = 0; i < 4; i++) {
++ if (!(mask & BIT(i)))
++ continue;
++
++ if (nla_put_u8(msg, i, signal[i]))
++ return false;
++ }
++
++ nla_nest_end(msg, attr);
++
++ return true;
++}
++
+ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
+ int flags,
+ struct cfg80211_registered_device *rdev,
+@@ -2830,6 +2856,18 @@ static int nl80211_send_station(struct s
+ default:
+ break;
+ }
++ if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL) {
++ if (!nl80211_put_signal(msg, sinfo->chains,
++ sinfo->chain_signal,
++ NL80211_STA_INFO_CHAIN_SIGNAL))
++ goto nla_put_failure;
++ }
++ if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL_AVG) {
++ if (!nl80211_put_signal(msg, sinfo->chains,
++ sinfo->chain_signal_avg,
++ NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
++ goto nla_put_failure;
++ }
+ if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+ if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
+ NL80211_STA_INFO_TX_BITRATE))
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -367,6 +367,7 @@ static void sta_set_sinfo(struct sta_inf
+ struct ieee80211_sub_if_data *sdata = sta->sdata;
+ struct ieee80211_local *local = sdata->local;
+ struct timespec uptime;
++ int i;
+
+ sinfo->generation = sdata->local->sta_generation;
+
+@@ -406,6 +407,17 @@ static void sta_set_sinfo(struct sta_inf
+ sinfo->signal = (s8)sta->last_signal;
+ sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
+ }
++ if (sta->chains) {
++ sinfo->filled |= STATION_INFO_CHAIN_SIGNAL |
++ STATION_INFO_CHAIN_SIGNAL_AVG;
++
++ sinfo->chains = sta->chains;
++ for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
++ sinfo->chain_signal[i] = sta->chain_signal_last[i];
++ sinfo->chain_signal_avg[i] =
++ (s8) -ewma_read(&sta->chain_signal_avg[i]);
++ }
++ }
+
+ sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
+
+--- a/drivers/net/wireless/ath/ath9k/dfs.c
++++ b/drivers/net/wireless/ath/ath9k/dfs.c
+@@ -164,8 +164,8 @@ void ath9k_dfs_process_phyerr(struct ath
+ return;
+ }
+
+- ard.rssi = rs->rs_rssi_ctl0;
+- ard.ext_rssi = rs->rs_rssi_ext0;
++ ard.rssi = rs->rs_rssi_ctl[0];
++ ard.ext_rssi = rs->rs_rssi_ext[0];
+
+ /*
+ * hardware stores this as 8 bit signed value.
+--- a/drivers/net/wireless/ath/ath9k/antenna.c
++++ b/drivers/net/wireless/ath/ath9k/antenna.c
+@@ -529,14 +529,14 @@ void ath_ant_comb_scan(struct ath_softc
+ struct ath_ant_comb *antcomb = &sc->ant_comb;
+ int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set;
+ int curr_main_set;
+- int main_rssi = rs->rs_rssi_ctl0;
+- int alt_rssi = rs->rs_rssi_ctl1;
++ int main_rssi = rs->rs_rssi_ctl[0];
++ int alt_rssi = rs->rs_rssi_ctl[1];
+ int rx_ant_conf, main_ant_conf;
+ bool short_scan = false;
+
+- rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) &
++ rx_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_CURRENT_SHIFT) &
+ ATH_ANT_RX_MASK;
+- main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) &
++ main_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_MAIN_SHIFT) &
+ ATH_ANT_RX_MASK;
+
+ /* Record packet only when both main_rssi and alt_rssi is positive */
diff --git a/package/mac80211/patches/523-cfg80211_fix_antenna_gain.patch b/package/mac80211/patches/523-cfg80211_fix_antenna_gain.patch
new file mode 100644
index 000000000..98f3d9675
--- /dev/null
+++ b/package/mac80211/patches/523-cfg80211_fix_antenna_gain.patch
@@ -0,0 +1,12 @@
+--- a/net/wireless/reg.c
++++ b/net/wireless/reg.c
+@@ -908,8 +908,7 @@ static void handle_channel(struct wiphy
+
+ chan->beacon_found = false;
+ chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags);
+- chan->max_antenna_gain = min(chan->orig_mag,
+- (int) MBI_TO_DBI(power_rule->max_antenna_gain));
++ chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
+ chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp);
+ if (chan->orig_mpwr) {
+ /*
diff --git a/package/mac80211/patches/524-mac80211_configure_antenna_gain.patch b/package/mac80211/patches/524-mac80211_configure_antenna_gain.patch
new file mode 100644
index 000000000..b2870a8aa
--- /dev/null
+++ b/package/mac80211/patches/524-mac80211_configure_antenna_gain.patch
@@ -0,0 +1,179 @@
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -851,6 +851,7 @@ enum ieee80211_smps_mode {
+ * the CONF_PS flag is set.
+ *
+ * @power_level: requested transmit power (in dBm)
++ * @max_antenna_gain: maximum antenna gain adjusted by user config (in dBi)
+ *
+ * @channel: the channel to tune to
+ * @channel_type: the channel (HT) type
+@@ -870,6 +871,7 @@ struct ieee80211_conf {
+ u32 flags;
+ int power_level, dynamic_ps_timeout;
+ int max_sleep_period;
++ int max_antenna_gain;
+
+ u16 listen_interval;
+ u8 ps_dtim_period;
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -101,7 +101,7 @@ int ieee80211_hw_config(struct ieee80211
+ {
+ struct ieee80211_channel *chan;
+ int ret = 0;
+- int power;
++ int power, ant_gain, max_power;
+ enum nl80211_channel_type channel_type;
+ u32 offchannel_flag;
+
+@@ -152,19 +152,31 @@ int ieee80211_hw_config(struct ieee80211
+ changed |= IEEE80211_CONF_CHANGE_SMPS;
+ }
+
+- if (test_bit(SCAN_SW_SCANNING, &local->scanning) ||
+- test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) ||
+- test_bit(SCAN_HW_SCANNING, &local->scanning) ||
+- !local->ap_power_level)
+- power = chan->max_power;
+- else
+- power = min(chan->max_power, local->ap_power_level);
++ max_power = chan->max_reg_power;
++ if (!test_bit(SCAN_SW_SCANNING, &local->scanning) &&
++ !test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) &&
++ !test_bit(SCAN_HW_SCANNING, &local->scanning) &&
++ local->ap_power_level)
++ max_power = min(max_power, local->ap_power_level);
++
++ ant_gain = chan->max_antenna_gain;
++ if (local->user_antenna_gain > 0) {
++ if (local->user_antenna_gain > ant_gain) {
++ max_power -= local->user_antenna_gain - ant_gain;
++ ant_gain = 0;
++ } else
++ ant_gain -= local->user_antenna_gain;
++ }
++
++ power = min(chan->max_power, max_power);
+
+ if (local->user_power_level >= 0)
+ power = min(power, local->user_power_level);
+
+- if (local->hw.conf.power_level != power) {
++ if (local->hw.conf.power_level != power ||
++ local->hw.conf.max_antenna_gain != ant_gain) {
+ changed |= IEEE80211_CONF_CHANGE_POWER;
++ local->hw.conf.max_antenna_gain = ant_gain;
+ local->hw.cur_power_level = power;
+ local->hw.conf.power_level = power;
+ }
+@@ -620,6 +632,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(
+ IEEE80211_RADIOTAP_MCS_HAVE_GI |
+ IEEE80211_RADIOTAP_MCS_HAVE_BW;
+ local->user_power_level = -1;
++ local->user_antenna_gain = -1;
+ wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
+
+ INIT_LIST_HEAD(&local->interfaces);
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1063,6 +1063,7 @@ struct ieee80211_local {
+
+ int user_power_level; /* in dBm */
+ int ap_power_level; /* in dBm */
++ int user_antenna_gain; /* in dBi */
+
+ enum ieee80211_smps_mode smps_mode;
+
+--- a/include/linux/nl80211.h
++++ b/include/linux/nl80211.h
+@@ -1517,6 +1517,8 @@ enum nl80211_attrs {
+
+ NL80211_ATTR_USER_REG_HINT_TYPE,
+
++ NL80211_ATTR_WIPHY_ANTENNA_GAIN,
++
+ /* add attributes here, update the policy in nl80211.c */
+
+ __NL80211_ATTR_AFTER_LAST,
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -355,6 +355,7 @@ static const struct nla_policy nl80211_p
+ [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
+ [NL80211_ATTR_WDEV] = { .type = NLA_U64 },
+ [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
++ [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 },
+ };
+
+ /* policy for the key attributes */
+@@ -1604,6 +1605,22 @@ static int nl80211_set_wiphy(struct sk_b
+ goto bad_res;
+ }
+
++ if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) {
++ int idx, dbi = 0;
++
++ if (!rdev->ops->set_antenna_gain) {
++ result = -EOPNOTSUPP;
++ goto bad_res;
++ }
++
++ idx = NL80211_ATTR_WIPHY_ANTENNA_GAIN;
++ dbi = nla_get_u32(info->attrs[idx]);
++
++ result = rdev->ops->set_antenna_gain(&rdev->wiphy, dbi);
++ if (result)
++ goto bad_res;
++ }
++
+ if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
+ info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
+ u32 tx_ant, rx_ant;
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -1984,6 +1984,19 @@ static int ieee80211_get_tx_power(struct
+ return 0;
+ }
+
++static int ieee80211_set_antenna_gain(struct wiphy *wiphy, int dbi)
++{
++ struct ieee80211_local *local = wiphy_priv(wiphy);
++
++ if (dbi < 0)
++ return -EINVAL;
++
++ local->user_antenna_gain = dbi;
++ ieee80211_hw_config(local, 0);
++
++ return 0;
++}
++
+ static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *addr)
+ {
+@@ -3082,6 +3095,7 @@ struct cfg80211_ops mac80211_config_ops
+ .set_wiphy_params = ieee80211_set_wiphy_params,
+ .set_tx_power = ieee80211_set_tx_power,
+ .get_tx_power = ieee80211_get_tx_power,
++ .set_antenna_gain = ieee80211_set_antenna_gain,
+ .set_wds_peer = ieee80211_set_wds_peer,
+ .rfkill_poll = ieee80211_rfkill_poll,
+ CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -1551,6 +1551,7 @@ struct cfg80211_gtk_rekey_data {
+ * the power passed is in mBm, to get dBm use MBM_TO_DBM().
+ * @get_tx_power: store the current TX power into the dbm variable;
+ * return 0 if successful
++ * @set_antenna_gain: set antenna gain to reduce maximum tx power if necessary
+ *
+ * @set_wds_peer: set the WDS peer for a WDS interface
+ *
+@@ -1750,6 +1751,7 @@ struct cfg80211_ops {
+ int (*set_tx_power)(struct wiphy *wiphy,
+ enum nl80211_tx_power_setting type, int mbm);
+ int (*get_tx_power)(struct wiphy *wiphy, int *dbm);
++ int (*set_antenna_gain)(struct wiphy *wiphy, int dbi);
+
+ int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *addr);
diff --git a/package/mac80211/patches/525-ath9k_use_configured_antenna_gain.patch b/package/mac80211/patches/525-ath9k_use_configured_antenna_gain.patch
new file mode 100644
index 000000000..35096b255
--- /dev/null
+++ b/package/mac80211/patches/525-ath9k_use_configured_antenna_gain.patch
@@ -0,0 +1,34 @@
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -73,6 +73,7 @@ struct ath_regulatory {
+ u16 max_power_level;
+ u16 current_rd;
+ int16_t power_limit;
++ int16_t max_antenna_gain;
+ struct reg_dmn_pair_mapping *regpair;
+ };
+
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -2828,7 +2828,7 @@ void ath9k_hw_apply_txpower(struct ath_h
+ channel = chan->chan;
+ chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
+ new_pwr = min_t(int, chan_pwr, reg->power_limit);
+- max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2;
++ max_gain = chan_pwr - new_pwr + reg->max_antenna_gain * 2;
+
+ ant_gain = get_antenna_gain(ah, chan);
+ if (ant_gain > max_gain)
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1263,7 +1263,10 @@ int ath9k_config(struct ieee80211_hw *hw
+ }
+
+ if (changed & IEEE80211_CONF_CHANGE_POWER) {
++ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
++
+ ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level);
++ reg->max_antenna_gain = conf->max_antenna_gain;
+ sc->config.txpowlimit = 2 * conf->power_level;
+ ath9k_cmn_update_txpow(ah, sc->curtxpow,
+ sc->config.txpowlimit, &sc->curtxpow);
diff --git a/package/mac80211/patches/526-cfg80211_fix_max_reg_power.patch b/package/mac80211/patches/526-cfg80211_fix_max_reg_power.patch
new file mode 100644
index 000000000..6f8d53f95
--- /dev/null
+++ b/package/mac80211/patches/526-cfg80211_fix_max_reg_power.patch
@@ -0,0 +1,21 @@
+--- a/net/wireless/reg.c
++++ b/net/wireless/reg.c
+@@ -901,7 +901,7 @@ static void handle_channel(struct wiphy
+ map_regdom_flags(reg_rule->flags) | bw_flags;
+ chan->max_antenna_gain = chan->orig_mag =
+ (int) MBI_TO_DBI(power_rule->max_antenna_gain);
+- chan->max_power = chan->orig_mpwr =
++ chan->max_reg_power = chan->max_power = chan->orig_mpwr =
+ (int) MBM_TO_DBM(power_rule->max_eirp);
+ return;
+ }
+@@ -1323,7 +1323,8 @@ static void handle_channel_custom(struct
+
+ chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
+ chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
+- chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp);
++ chan->max_reg_power = chan->max_power =
++ (int) MBM_TO_DBM(power_rule->max_eirp);
+ }
+
+ static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band,
diff --git a/package/mac80211/patches/530-ath9k_fix_initvals.patch b/package/mac80211/patches/530-ath9k_fix_initvals.patch
new file mode 100644
index 000000000..d86e718f0
--- /dev/null
+++ b/package/mac80211/patches/530-ath9k_fix_initvals.patch
@@ -0,0 +1,208 @@
+--- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
++++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
+@@ -534,108 +534,108 @@ static const u32 ar9300_2p2_baseband_cor
+
+ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+- {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
+- {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
+- {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
++ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
++ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
++ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+- {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+- {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+- {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+- {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+- {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202},
+- {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400},
+- {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402},
+- {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404},
+- {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603},
+- {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02},
+- {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04},
+- {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20},
+- {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20},
+- {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22},
+- {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24},
+- {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640},
+- {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660},
+- {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861},
+- {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81},
+- {0x0000a54c, 0x5a08442e, 0x5a08442e, 0x47001a83, 0x47001a83},
+- {0x0000a550, 0x5e0a4431, 0x5e0a4431, 0x4a001c84, 0x4a001c84},
+- {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3},
+- {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5},
+- {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9},
+- {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb},
+- {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+- {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+- {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+- {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+- {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+- {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+- {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+- {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+- {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+- {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+- {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+- {0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202},
+- {0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400},
+- {0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402},
+- {0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404},
+- {0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603},
+- {0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02},
+- {0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04},
+- {0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20},
+- {0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20},
+- {0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22},
+- {0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24},
+- {0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640},
+- {0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660},
+- {0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861},
+- {0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81},
+- {0x0000a5cc, 0x5a88442e, 0x5a88442e, 0x47801a83, 0x47801a83},
+- {0x0000a5d0, 0x5e8a4431, 0x5e8a4431, 0x4a801c84, 0x4a801c84},
+- {0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3},
+- {0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5},
+- {0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9},
+- {0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb},
+- {0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+- {0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+- {0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+- {0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+- {0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+- {0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+- {0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
++ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
++ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
++ {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
++ {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
++ {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
++ {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
++ {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
++ {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
++ {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
++ {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
++ {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
++ {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
++ {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
++ {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
++ {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
++ {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
++ {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
++ {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
++ {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
++ {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
++ {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
++ {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
++ {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
++ {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
++ {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
++ {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
++ {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
++ {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
++ {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
++ {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
++ {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
++ {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
++ {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
++ {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
++ {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
++ {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
++ {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
++ {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
++ {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
++ {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
++ {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
++ {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
++ {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
++ {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
++ {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
++ {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
++ {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
++ {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
++ {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
++ {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
++ {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
++ {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
++ {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
++ {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
++ {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
++ {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
++ {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
++ {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
++ {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
++ {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
++ {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
++ {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
++ {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
++ {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
++ {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+- {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
+- {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
+- {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
+- {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000},
+- {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501},
+- {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501},
+- {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03},
+- {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+- {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04},
+- {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+- {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+- {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+- {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+- {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+- {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
+- {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
+- {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
++ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
++ {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
++ {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
++ {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
++ {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
++ {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
++ {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
++ {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
++ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
++ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+- {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
+- {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
+- {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
++ {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
++ {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
++ {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+ {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+- {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+- {0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+- {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+- {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+- {0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+- {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+- {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+- {0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+- {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
++ {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
++ {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
++ {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
++ {0x00016444, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
++ {0x00016448, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
++ {0x00016468, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
++ {0x00016844, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
++ {0x00016848, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
++ {0x00016868, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
+ };
+
+ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = {
diff --git a/package/mac80211/patches/540-ath9k_extra_leds.patch b/package/mac80211/patches/540-ath9k_extra_leds.patch
new file mode 100644
index 000000000..86dc51856
--- /dev/null
+++ b/package/mac80211/patches/540-ath9k_extra_leds.patch
@@ -0,0 +1,258 @@
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -538,6 +538,9 @@ struct ath9k_wow_pattern {
+ #ifdef CONFIG_MAC80211_LEDS
+ void ath_init_leds(struct ath_softc *sc);
+ void ath_deinit_leds(struct ath_softc *sc);
++int ath_create_gpio_led(struct ath_softc *sc, int gpio, const char *name,
++ const char *trigger, bool active_low);
++
+ #else
+ static inline void ath_init_leds(struct ath_softc *sc)
+ {
+@@ -655,6 +658,13 @@ struct ath9k_vif_iter_data {
+ int nadhocs; /* number of adhoc vifs */
+ };
+
++struct ath_led {
++ struct list_head list;
++ struct ath_softc *sc;
++ const struct gpio_led *gpio;
++ struct led_classdev cdev;
++};
++
+ struct ath_softc {
+ struct ieee80211_hw *hw;
+ struct device *dev;
+@@ -696,9 +706,8 @@ struct ath_softc {
+ struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
+
+ #ifdef CONFIG_MAC80211_LEDS
+- bool led_registered;
+- char led_name[32];
+- struct led_classdev led_cdev;
++ const char *led_default_trigger;
++ struct list_head leds;
+ #endif
+
+ struct ath9k_hw_cal_data caldata;
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -24,22 +24,89 @@
+ static void ath_led_brightness(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+ {
+- struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev);
+- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, (brightness == LED_OFF));
++ struct ath_led *led = container_of(led_cdev, struct ath_led, cdev);
++ struct ath_softc *sc = led->sc;
++
++ ath9k_ps_wakeup(sc);
++ ath9k_hw_set_gpio(sc->sc_ah, led->gpio->gpio,
++ (brightness != LED_OFF) ^ led->gpio->active_low);
++ ath9k_ps_restore(sc);
++}
++
++static int ath_add_led(struct ath_softc *sc, struct ath_led *led)
++{
++ const struct gpio_led *gpio = led->gpio;
++ int ret;
++
++ led->cdev.name = gpio->name;
++ led->cdev.default_trigger = gpio->default_trigger;
++ led->cdev.brightness_set = ath_led_brightness;
++
++ ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->cdev);
++ if (ret < 0)
++ return ret;
++
++ led->sc = sc;
++ list_add(&led->list, &sc->leds);
++
++ /* Configure gpio for output */
++ ath9k_hw_cfg_output(sc->sc_ah, gpio->gpio,
++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
++
++ /* LED off */
++ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
++
++ return 0;
++}
++
++int ath_create_gpio_led(struct ath_softc *sc, int gpio_num, const char *name,
++ const char *trigger, bool active_low)
++{
++ struct ath_led *led;
++ struct gpio_led *gpio;
++ char *_name;
++ int ret;
++
++ led = kzalloc(sizeof(*led) + sizeof(*gpio) + strlen(name) + 1,
++ GFP_KERNEL);
++ if (!led)
++ return -ENOMEM;
++
++ led->gpio = gpio = (struct gpio_led *) (led + 1);
++ _name = (char *) (led->gpio + 1);
++
++ strcpy(_name, name);
++ gpio->name = _name;
++ gpio->gpio = gpio_num;
++ gpio->active_low = active_low;
++ gpio->default_trigger = trigger;
++
++ ret = ath_add_led(sc, led);
++ if (unlikely(ret < 0))
++ kfree(led);
++
++ return ret;
+ }
+
+ void ath_deinit_leds(struct ath_softc *sc)
+ {
+- if (!sc->led_registered)
+- return;
++ struct ath_led *led;
+
+- ath_led_brightness(&sc->led_cdev, LED_OFF);
+- led_classdev_unregister(&sc->led_cdev);
++ while (!list_empty(&sc->leds)) {
++ led = list_first_entry(&sc->leds, struct ath_led, list);
++ list_del(&led->list);
++ ath_led_brightness(&led->cdev, LED_OFF);
++ led_classdev_unregister(&led->cdev);
++ kfree(led);
++ }
+ }
+
+ void ath_init_leds(struct ath_softc *sc)
+ {
+- int ret;
++ char led_name[32];
++ const char *trigger;
++
++ INIT_LIST_HEAD(&sc->leds);
+
+ if (AR_SREV_9100(sc->sc_ah))
+ return;
+@@ -57,26 +124,15 @@ void ath_init_leds(struct ath_softc *sc)
+ sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
+ }
+
+- /* Configure gpio 1 for output */
+- ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin,
+- AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+- /* LED off, active low */
+- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
+-
+- if (!led_blink)
+- sc->led_cdev.default_trigger =
+- ieee80211_get_radio_led_name(sc->hw);
+-
+- snprintf(sc->led_name, sizeof(sc->led_name),
+- "ath9k-%s", wiphy_name(sc->hw->wiphy));
+- sc->led_cdev.name = sc->led_name;
+- sc->led_cdev.brightness_set = ath_led_brightness;
++ snprintf(led_name, sizeof(led_name), "ath9k-%s",
++ wiphy_name(sc->hw->wiphy));
+
+- ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev);
+- if (ret < 0)
+- return;
++ if (led_blink)
++ trigger = sc->led_default_trigger;
++ else
++ trigger = ieee80211_get_radio_led_name(sc->hw);
+
+- sc->led_registered = true;
++ ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger, 1);
+ }
+ #endif
+
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -811,7 +811,7 @@ int ath9k_init_device(u16 devid, struct
+
+ #ifdef CONFIG_MAC80211_LEDS
+ /* must be initialized before ieee80211_register_hw */
+- sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
++ sc->led_default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
+ IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink,
+ ARRAY_SIZE(ath9k_tpt_blink));
+ #endif
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1255,6 +1255,61 @@ static const struct file_operations fops
+ .llseek = default_llseek,
+ };
+
++#ifdef CONFIG_MAC80211_LEDS
++
++static ssize_t write_file_gpio_led(struct file *file, const char __user *ubuf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ char buf[32], *str, *name, *c;
++ ssize_t len;
++ unsigned int gpio;
++ bool active_low = false;
++
++ len = min(count, sizeof(buf) - 1);
++ if (copy_from_user(buf, ubuf, len))
++ return -EFAULT;
++
++ buf[len] = '\0';
++ name = strchr(buf, ',');
++ if (!name)
++ return -EINVAL;
++
++ *(name++) = 0;
++ if (!*name)
++ return -EINVAL;
++
++ c = strchr(name, '\n');
++ if (c)
++ *c = 0;
++
++ str = buf;
++ if (*str == '!') {
++ str++;
++ active_low = true;
++ }
++
++ if (kstrtouint(str, 0, &gpio) < 0)
++ return -EINVAL;
++
++ if (gpio >= sc->sc_ah->caps.num_gpio_pins)
++ return -EINVAL;
++
++ if (ath_create_gpio_led(sc, gpio, name, NULL, active_low) < 0)
++ return -EINVAL;
++
++ return count;
++}
++
++static const struct file_operations fops_gpio_led = {
++ .write = write_file_gpio_led,
++ .open = simple_open,
++ .owner = THIS_MODULE,
++ .llseek = default_llseek,
++};
++
++#endif
++
+ #ifdef CONFIG_ATH9K_MAC_DEBUG
+
+ void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
+@@ -1688,6 +1743,11 @@ int ath9k_init_debug(struct ath_hw *ah)
+ &fops_samps);
+ #endif
+
++#ifdef CONFIG_MAC80211_LEDS
++ debugfs_create_file("gpio_led", S_IWUSR,
++ sc->debug.debugfs_phy, sc, &fops_gpio_led);
++#endif
++
+ debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR,
+ sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);
+
diff --git a/package/mac80211/patches/541-ath9k_extra_platform_leds.patch b/package/mac80211/patches/541-ath9k_extra_platform_leds.patch
new file mode 100644
index 000000000..ac8ee533d
--- /dev/null
+++ b/package/mac80211/patches/541-ath9k_extra_platform_leds.patch
@@ -0,0 +1,71 @@
+--- a/include/linux/ath9k_platform.h
++++ b/include/linux/ath9k_platform.h
+@@ -33,6 +33,9 @@ struct ath9k_platform_data {
+ bool is_clk_25mhz;
+ int (*get_mac_revision)(void);
+ int (*external_reset)(void);
++
++ int num_leds;
++ const struct gpio_led *leds;
+ };
+
+ #endif /* _LINUX_ATH9K_PLATFORM_H */
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -14,6 +14,7 @@
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
++#include <linux/ath9k_platform.h>
+ #include "ath9k.h"
+
+ /********************************/
+@@ -88,6 +89,24 @@ int ath_create_gpio_led(struct ath_softc
+ return ret;
+ }
+
++static int ath_create_platform_led(struct ath_softc *sc,
++ const struct gpio_led *gpio)
++{
++ struct ath_led *led;
++ int ret;
++
++ led = kzalloc(sizeof(*led), GFP_KERNEL);
++ if (!led)
++ return -ENOMEM;
++
++ led->gpio = gpio;
++ ret = ath_add_led(sc, led);
++ if (ret < 0)
++ kfree(led);
++
++ return ret;
++}
++
+ void ath_deinit_leds(struct ath_softc *sc)
+ {
+ struct ath_led *led;
+@@ -103,8 +122,10 @@ void ath_deinit_leds(struct ath_softc *s
+
+ void ath_init_leds(struct ath_softc *sc)
+ {
++ struct ath9k_platform_data *pdata = sc->dev->platform_data;
+ char led_name[32];
+ const char *trigger;
++ int i;
+
+ INIT_LIST_HEAD(&sc->leds);
+
+@@ -133,6 +154,12 @@ void ath_init_leds(struct ath_softc *sc)
+ trigger = ieee80211_get_radio_led_name(sc->hw);
+
+ ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger, 1);
++
++ if (!pdata)
++ return;
++
++ for (i = 0; i < pdata->num_leds; i++)
++ ath_create_platform_led(sc, &pdata->leds[i]);
+ }
+ #endif
+
diff --git a/package/mac80211/patches/550-mac80211_optimize_mcs_rate_mask.patch b/package/mac80211/patches/550-mac80211_optimize_mcs_rate_mask.patch
new file mode 100644
index 000000000..53889d19c
--- /dev/null
+++ b/package/mac80211/patches/550-mac80211_optimize_mcs_rate_mask.patch
@@ -0,0 +1,98 @@
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -715,6 +715,8 @@ struct ieee80211_sub_if_data {
+
+ /* bitmap of allowed (non-MCS) rate indexes for rate control */
+ u32 rc_rateidx_mask[IEEE80211_NUM_BANDS];
++
++ bool rc_has_mcs_mask[IEEE80211_NUM_BANDS];
+ u8 rc_rateidx_mcs_mask[IEEE80211_NUM_BANDS][IEEE80211_HT_MCS_MASK_LEN];
+
+ union {
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -2160,9 +2160,20 @@ static int ieee80211_set_bitrate_mask(st
+ }
+
+ for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
++ struct ieee80211_supported_band *sband = wiphy->bands[i];
++
+ sdata->rc_rateidx_mask[i] = mask->control[i].legacy;
+ memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].mcs,
+ sizeof(mask->control[i].mcs));
++
++ sdata->rc_has_mcs_mask[i] = false;
++ if (!sband)
++ continue;
++
++ if (memcmp(sdata->rc_rateidx_mcs_mask[i],
++ sband->ht_cap.mcs.rx_mask,
++ sizeof(sband->ht_cap.mcs.rx_mask)) != 0)
++ sdata->rc_has_mcs_mask[i] = true;
+ }
+
+ return 0;
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -3721,7 +3721,7 @@ void ieee80211_send_bar(struct ieee80211
+ * (deprecated; this will be removed once drivers get updated to use
+ * rate_idx_mask)
+ * @rate_idx_mask: user-requested (legacy) rate mask
+- * @rate_idx_mcs_mask: user-requested MCS rate mask
++ * @rate_idx_mcs_mask: user-requested MCS rate mask (NULL if not in use)
+ * @bss: whether this frame is sent out in AP or IBSS mode
+ */
+ struct ieee80211_tx_rate_control {
+@@ -3733,7 +3733,7 @@ struct ieee80211_tx_rate_control {
+ bool rts, short_preamble;
+ u8 max_rate_idx;
+ u32 rate_idx_mask;
+- u8 rate_idx_mcs_mask[IEEE80211_HT_MCS_MASK_LEN];
++ u8 *rate_idx_mcs_mask;
+ bool bss;
+ };
+
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -631,9 +631,11 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021
+ txrc.max_rate_idx = -1;
+ else
+ txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
+- memcpy(txrc.rate_idx_mcs_mask,
+- tx->sdata->rc_rateidx_mcs_mask[info->band],
+- sizeof(txrc.rate_idx_mcs_mask));
++
++ if (tx->sdata->rc_has_mcs_mask[info->band])
++ txrc.rate_idx_mcs_mask =
++ tx->sdata->rc_rateidx_mcs_mask[info->band];
++
+ txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
+ tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
+ tx->sdata->vif.type == NL80211_IFTYPE_ADHOC);
+@@ -2447,8 +2449,6 @@ struct sk_buff *ieee80211_beacon_get_tim
+ txrc.max_rate_idx = -1;
+ else
+ txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
+- memcpy(txrc.rate_idx_mcs_mask, sdata->rc_rateidx_mcs_mask[band],
+- sizeof(txrc.rate_idx_mcs_mask));
+ txrc.bss = true;
+ rate_control_get_rate(sdata, NULL, &txrc);
+
+--- a/net/mac80211/rate.c
++++ b/net/mac80211/rate.c
+@@ -461,9 +461,12 @@ void rate_control_get_rate(struct ieee80
+ * the common case.
+ */
+ mask = sdata->rc_rateidx_mask[info->band];
+- memcpy(mcs_mask, sdata->rc_rateidx_mcs_mask[info->band],
+- sizeof(mcs_mask));
+- if (mask != (1 << txrc->sband->n_bitrates) - 1) {
++ if (mask != (1 << txrc->sband->n_bitrates) - 1 || txrc->rate_idx_mcs_mask) {
++ if (txrc->rate_idx_mcs_mask)
++ memcpy(mcs_mask, txrc->rate_idx_mcs_mask, sizeof(mcs_mask));
++ else
++ memset(mcs_mask, 0xff, sizeof(mcs_mask));
++
+ if (sta) {
+ /* Filter out rates that the STA does not support */
+ mask &= sta->sta.supp_rates[info->band];
diff --git a/package/mac80211/patches/551-ath9k_optimize_interrupt_mitigation.patch b/package/mac80211/patches/551-ath9k_optimize_interrupt_mitigation.patch
new file mode 100644
index 000000000..2afc4deb4
--- /dev/null
+++ b/package/mac80211/patches/551-ath9k_optimize_interrupt_mitigation.patch
@@ -0,0 +1,30 @@
+--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+@@ -240,21 +240,19 @@ static bool ar9003_hw_get_isr(struct ath
+
+ *masked = isr & ATH9K_INT_COMMON;
+
+- if (ah->config.rx_intr_mitigation)
++ if (ah->config.rx_intr_mitigation) {
+ if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
+ *masked |= ATH9K_INT_RXLP;
+-
+- if (ah->config.tx_intr_mitigation)
+- if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM))
+- *masked |= ATH9K_INT_TX;
+-
+- if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR))
++ } else if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR))
+ *masked |= ATH9K_INT_RXLP;
+
+ if (isr & AR_ISR_HP_RXOK)
+ *masked |= ATH9K_INT_RXHP;
+
+- if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) {
++ if (ah->config.tx_intr_mitigation) {
++ if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM))
++ *masked |= ATH9K_INT_TX;
++ } else if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) {
+ *masked |= ATH9K_INT_TX;
+
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
diff --git a/package/mac80211/patches/560-ath9k_reduce_ani_interval.patch b/package/mac80211/patches/560-ath9k_reduce_ani_interval.patch
new file mode 100644
index 000000000..e2a0d124a
--- /dev/null
+++ b/package/mac80211/patches/560-ath9k_reduce_ani_interval.patch
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/ath/ath9k/ani.h
++++ b/drivers/net/wireless/ath/ath9k/ani.h
+@@ -51,7 +51,7 @@
+ #define ATH9K_ANI_PERIOD 300
+
+ /* in ms */
+-#define ATH9K_ANI_POLLINTERVAL 1000
++#define ATH9K_ANI_POLLINTERVAL 100
+
+ #define HAL_NOISE_IMMUNE_MAX 4
+ #define HAL_SPUR_IMMUNE_MAX 7
diff --git a/package/mac80211/patches/561-ath9k_revert_initval_change.patch b/package/mac80211/patches/561-ath9k_revert_initval_change.patch
new file mode 100644
index 000000000..49aea350c
--- /dev/null
+++ b/package/mac80211/patches/561-ath9k_revert_initval_change.patch
@@ -0,0 +1,19 @@
+--- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
++++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
+@@ -778,11 +778,11 @@ static const u32 ar9300Common_rx_gain_ta
+ {0x0000a074, 0x00000000},
+ {0x0000a078, 0x00000000},
+ {0x0000a07c, 0x00000000},
+- {0x0000a080, 0x1a1a1a1a},
+- {0x0000a084, 0x1a1a1a1a},
+- {0x0000a088, 0x1a1a1a1a},
+- {0x0000a08c, 0x1a1a1a1a},
+- {0x0000a090, 0x171a1a1a},
++ {0x0000a080, 0x22222229},
++ {0x0000a084, 0x1d1d1d1d},
++ {0x0000a088, 0x1d1d1d1d},
++ {0x0000a08c, 0x1d1d1d1d},
++ {0x0000a090, 0x171d1d1d},
+ {0x0000a094, 0x11111717},
+ {0x0000a098, 0x00030311},
+ {0x0000a09c, 0x00000000},
diff --git a/package/mac80211/patches/562-ath9k_add_idle_hack.patch b/package/mac80211/patches/562-ath9k_add_idle_hack.patch
new file mode 100644
index 000000000..10fac17bd
--- /dev/null
+++ b/package/mac80211/patches/562-ath9k_add_idle_hack.patch
@@ -0,0 +1,20 @@
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1087,6 +1087,7 @@ static void ath9k_remove_interface(struc
+ ath9k_calculate_summary_state(hw, NULL);
+
+ mutex_unlock(&sc->mutex);
++ ath9k_config(hw, IEEE80211_CONF_CHANGE_IDLE);
+ ath9k_ps_restore(sc);
+ }
+
+@@ -1139,7 +1140,8 @@ int ath9k_config(struct ieee80211_hw *hw
+ mutex_lock(&sc->mutex);
+
+ if (changed & IEEE80211_CONF_CHANGE_IDLE) {
+- sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
++ sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE) &&
++ !sc->nvifs;
+ if (sc->ps_idle) {
+ ath_cancel_work(sc);
+ ath9k_stop_btcoex(sc);
diff --git a/package/mac80211/patches/563-ath9k_rx_dma_stop_check.patch b/package/mac80211/patches/563-ath9k_rx_dma_stop_check.patch
new file mode 100644
index 000000000..606eb1c63
--- /dev/null
+++ b/package/mac80211/patches/563-ath9k_rx_dma_stop_check.patch
@@ -0,0 +1,28 @@
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -689,7 +689,7 @@ bool ath9k_hw_stopdmarecv(struct ath_hw
+ {
+ #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */
+ struct ath_common *common = ath9k_hw_common(ah);
+- u32 mac_status, last_mac_status = 0;
++ u32 mac_status = 0, last_mac_status = 0;
+ int i;
+
+ /* Enable access to the DMA observation bus */
+@@ -719,6 +719,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw
+ }
+
+ if (i == 0) {
++ if (!AR_SREV_9300_20_OR_LATER(ah) &&
++ (mac_status & 0x700) == 0) {
++ /*
++ * DMA is idle but the MAC is still stuck
++ * processing events
++ */
++ *reset = true;
++ return true;
++ }
++
+ ath_err(common,
+ "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n",
+ AH_RX_STOP_DMA_TIMEOUT / 1000,
diff --git a/package/mac80211/patches/564-ath9k_debugfs_diag.patch b/package/mac80211/patches/564-ath9k_debugfs_diag.patch
new file mode 100644
index 000000000..2cf2a73e0
--- /dev/null
+++ b/package/mac80211/patches/564-ath9k_debugfs_diag.patch
@@ -0,0 +1,139 @@
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1678,6 +1678,50 @@ static const struct file_operations fops
+ };
+
+
++static ssize_t read_file_diag(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ struct ath_hw *ah = sc->sc_ah;
++ char buf[32];
++ unsigned int len;
++
++ len = sprintf(buf, "0x%08lx\n", ah->diag);
++ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
++}
++
++static ssize_t write_file_diag(struct file *file, const char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ struct ath_hw *ah = sc->sc_ah;
++ unsigned long diag;
++ char buf[32];
++ ssize_t len;
++
++ len = min(count, sizeof(buf) - 1);
++ if (copy_from_user(buf, user_buf, len))
++ return -EFAULT;
++
++ buf[len] = '\0';
++ if (strict_strtoul(buf, 0, &diag))
++ return -EINVAL;
++
++ ah->diag = diag;
++ ath9k_hw_update_diag(ah);
++
++ return count;
++}
++
++static const struct file_operations fops_diag = {
++ .read = read_file_diag,
++ .write = write_file_diag,
++ .open = simple_open,
++ .owner = THIS_MODULE,
++ .llseek = default_llseek,
++};
++
++
+ int ath9k_init_debug(struct ath_hw *ah)
+ {
+ struct ath_common *common = ath9k_hw_common(ah);
+@@ -1760,5 +1804,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+ debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
+ sc, &fops_chanbw);
+
++ debugfs_create_file("diag", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
++ sc, &fops_diag);
++
+ return 0;
+ }
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -498,6 +498,12 @@ enum {
+ ATH9K_RESET_COLD,
+ };
+
++enum {
++ ATH_DIAG_DISABLE_RX,
++ ATH_DIAG_DISABLE_TX,
++ ATH_DIAG_TRIGGER_ERROR,
++};
++
+ struct ath9k_hw_version {
+ u32 magic;
+ u16 devid;
+@@ -741,6 +747,8 @@ struct ath_hw {
+ u32 rfkill_polarity;
+ u32 ah_flags;
+
++ unsigned long diag;
++
+ bool htc_reset_init;
+
+ enum nl80211_iftype opmode;
+@@ -1007,6 +1015,7 @@ void ath9k_hw_set_sta_beacon_timers(stru
+ bool ath9k_hw_check_alive(struct ath_hw *ah);
+
+ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
++void ath9k_hw_update_diag(struct ath_hw *ah);
+
+ #ifdef CONFIG_ATH9K_DEBUGFS
+ void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause);
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1749,6 +1749,20 @@ fail:
+ return -EINVAL;
+ }
+
++void ath9k_hw_update_diag(struct ath_hw *ah)
++{
++ if (test_bit(ATH_DIAG_DISABLE_RX, &ah->diag))
++ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
++ else
++ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
++
++ if (test_bit(ATH_DIAG_DISABLE_TX, &ah->diag))
++ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK);
++ else
++ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK);
++}
++EXPORT_SYMBOL(ath9k_hw_update_diag);
++
+ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
+ struct ath9k_hw_cal_data *caldata, bool fastcc)
+ {
+@@ -2026,6 +2040,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+ }
+
+ ath9k_hw_apply_gpio_override(ah);
++ ath9k_hw_update_diag(ah);
+
+ return 0;
+ }
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -476,6 +476,11 @@ irqreturn_t ath_isr(int irq, void *dev)
+ ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */
+ status &= ah->imask; /* discard unasked-for bits */
+
++ if (test_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag)) {
++ status |= ATH9K_INT_FATAL;
++ clear_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag);
++ }
++
+ /*
+ * If there are no status bits set, then this interrupt was not
+ * for me (should have been caught above).
diff --git a/package/mac80211/patches/565-ath9k_disable_paprd.patch b/package/mac80211/patches/565-ath9k_disable_paprd.patch
new file mode 100644
index 000000000..079986d60
--- /dev/null
+++ b/package/mac80211/patches/565-ath9k_disable_paprd.patch
@@ -0,0 +1,72 @@
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1767,6 +1767,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+ sc->debug.debugfs_phy, sc, &fops_tx_chainmask);
+ debugfs_create_file("disable_ani", S_IRUSR | S_IWUSR,
+ sc->debug.debugfs_phy, sc, &fops_disable_ani);
++ debugfs_create_bool("paprd", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
++ &sc->sc_ah->config.enable_paprd);
+ debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
+ sc, &fops_regidx);
+ debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -2521,10 +2521,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw
+ pCap->rx_status_len = sizeof(struct ar9003_rxs);
+ pCap->tx_desc_len = sizeof(struct ar9003_txc);
+ pCap->txs_len = sizeof(struct ar9003_txs);
+- if (!ah->config.paprd_disable &&
+- ah->eep_ops->get_eeprom(ah, EEP_PAPRD) &&
+- !AR_SREV_9462(ah))
+- pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
+ } else {
+ pCap->tx_desc_len = sizeof(struct ath_desc);
+ if (AR_SREV_9280_20(ah))
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -236,7 +236,6 @@ enum ath9k_hw_caps {
+ ATH9K_HW_CAP_LDPC = BIT(6),
+ ATH9K_HW_CAP_FASTCLOCK = BIT(7),
+ ATH9K_HW_CAP_SGI_20 = BIT(8),
+- ATH9K_HW_CAP_PAPRD = BIT(9),
+ ATH9K_HW_CAP_ANT_DIV_COMB = BIT(10),
+ ATH9K_HW_CAP_2GHZ = BIT(11),
+ ATH9K_HW_CAP_5GHZ = BIT(12),
+@@ -287,12 +286,12 @@ struct ath9k_ops_config {
+ u8 pcie_clock_req;
+ u32 pcie_waen;
+ u8 analog_shiftreg;
+- u8 paprd_disable;
+ u32 ofdm_trig_low;
+ u32 ofdm_trig_high;
+ u32 cck_trig_high;
+ u32 cck_trig_low;
+ u32 enable_ani;
++ u32 enable_paprd;
+ int serialize_regmode;
+ bool rx_intr_mitigation;
+ bool tx_intr_mitigation;
+--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+@@ -2982,6 +2982,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(st
+ case EEP_RX_MASK:
+ return pBase->txrxMask & 0xf;
+ case EEP_PAPRD:
++ if (AR_SREV_9462(ah))
++ return false;
++ if (!ah->config.enable_paprd);
++ return false;
+ return !!(pBase->featureEnable & BIT(5));
+ case EEP_CHAIN_MASK_REDUCE:
+ return (pBase->miscConfiguration >> 0x3) & 0x1;
+--- a/drivers/net/wireless/ath/ath9k/link.c
++++ b/drivers/net/wireless/ath/ath9k/link.c
+@@ -423,7 +423,7 @@ set_timer:
+ cal_interval = min(cal_interval, (u32)short_cal_interval);
+
+ mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
+- if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) {
++ if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD) && ah->caldata) {
+ if (!ah->caldata->paprd_done)
+ ieee80211_queue_work(sc->hw, &sc->paprd_work);
+ else if (!ah->paprd_table_write_done)
diff --git a/package/mac80211/patches/566-ath9k_use_ieee80211_free_txskb.patch b/package/mac80211/patches/566-ath9k_use_ieee80211_free_txskb.patch
new file mode 100644
index 000000000..dd484662b
--- /dev/null
+++ b/package/mac80211/patches/566-ath9k_use_ieee80211_free_txskb.patch
@@ -0,0 +1,149 @@
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -66,8 +66,7 @@ static void ath_tx_update_baw(struct ath
+ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
+ struct ath_txq *txq,
+ struct ath_atx_tid *tid,
+- struct sk_buff *skb,
+- bool dequeue);
++ struct sk_buff *skb);
+
+ enum {
+ MCS_HT20,
+@@ -176,7 +175,15 @@ static void ath_tx_flush_tid(struct ath_
+ fi = get_frame_info(skb);
+ bf = fi->bf;
+
+- if (bf && fi->retries) {
++ if (!bf) {
++ bf = ath_tx_setup_buffer(sc, txq, tid, skb);
++ if (!bf) {
++ ieee80211_free_txskb(sc->hw, skb);
++ continue;
++ }
++ }
++
++ if (fi->retries) {
+ list_add_tail(&bf->list, &bf_head);
+ ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
+@@ -785,10 +792,13 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+ fi = get_frame_info(skb);
+ bf = fi->bf;
+ if (!fi->bf)
+- bf = ath_tx_setup_buffer(sc, txq, tid, skb, true);
++ bf = ath_tx_setup_buffer(sc, txq, tid, skb);
+
+- if (!bf)
++ if (!bf) {
++ __skb_unlink(skb, &tid->buf_q);
++ ieee80211_free_txskb(sc->hw, skb);
+ continue;
++ }
+
+ bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
+ seqno = bf->bf_state.seqno;
+@@ -1731,9 +1741,11 @@ static void ath_tx_send_ampdu(struct ath
+ return;
+ }
+
+- bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false);
+- if (!bf)
++ bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
++ if (!bf) {
++ ieee80211_free_txskb(sc->hw, skb);
+ return;
++ }
+
+ bf->bf_state.bf_type = BUF_AMPDU;
+ INIT_LIST_HEAD(&bf_head);
+@@ -1757,11 +1769,6 @@ static void ath_tx_send_normal(struct at
+ struct ath_buf *bf;
+
+ bf = fi->bf;
+- if (!bf)
+- bf = ath_tx_setup_buffer(sc, txq, tid, skb, false);
+-
+- if (!bf)
+- return;
+
+ INIT_LIST_HEAD(&bf_head);
+ list_add_tail(&bf->list, &bf_head);
+@@ -1835,8 +1842,7 @@ u8 ath_txchainmask_reduction(struct ath_
+ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
+ struct ath_txq *txq,
+ struct ath_atx_tid *tid,
+- struct sk_buff *skb,
+- bool dequeue)
++ struct sk_buff *skb)
+ {
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_frame_info *fi = get_frame_info(skb);
+@@ -1848,7 +1854,7 @@ static struct ath_buf *ath_tx_setup_buff
+ bf = ath_tx_get_buffer(sc);
+ if (!bf) {
+ ath_dbg(common, XMIT, "TX buffers are full\n");
+- goto error;
++ return NULL;
+ }
+
+ ATH_TXBUF_RESET(bf);
+@@ -1877,18 +1883,12 @@ static struct ath_buf *ath_tx_setup_buff
+ ath_err(ath9k_hw_common(sc->sc_ah),
+ "dma_mapping_error() on TX\n");
+ ath_tx_return_buffer(sc, bf);
+- goto error;
++ return NULL;
+ }
+
+ fi->bf = bf;
+
+ return bf;
+-
+-error:
+- if (dequeue)
+- __skb_unlink(skb, &tid->buf_q);
+- dev_kfree_skb_any(skb);
+- return NULL;
+ }
+
+ /* FIXME: tx power */
+@@ -1917,9 +1917,14 @@ static void ath_tx_start_dma(struct ath_
+ */
+ ath_tx_send_ampdu(sc, tid, skb, txctl);
+ } else {
+- bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false);
+- if (!bf)
++ bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
++ if (!bf) {
++ if (txctl->paprd)
++ dev_kfree_skb_any(skb);
++ else
++ ieee80211_free_txskb(sc->hw, skb);
+ return;
++ }
+
+ bf->bf_state.bfs_paprd = txctl->paprd;
+
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -775,7 +775,7 @@ static void ath9k_tx(struct ieee80211_hw
+
+ return;
+ exit:
+- dev_kfree_skb_any(skb);
++ ieee80211_free_txskb(hw, skb);
+ }
+
+ static void ath9k_stop(struct ieee80211_hw *hw)
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -120,7 +120,7 @@ static void ath9k_tx_cabq(struct ieee802
+
+ if (ath_tx_start(hw, skb, &txctl) != 0) {
+ ath_dbg(common, XMIT, "CABQ TX failed\n");
+- dev_kfree_skb_any(skb);
++ ieee80211_free_txskb(hw, skb);
+ }
+ }
+
diff --git a/package/mac80211/patches/600-rt2x00-disable-pci-code-if-CONFIG_PCI-not-defined.patch b/package/mac80211/patches/600-rt2x00-disable-pci-code-if-CONFIG_PCI-not-defined.patch
new file mode 100644
index 000000000..a7609ede4
--- /dev/null
+++ b/package/mac80211/patches/600-rt2x00-disable-pci-code-if-CONFIG_PCI-not-defined.patch
@@ -0,0 +1,18 @@
+--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
++++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
+@@ -208,6 +208,7 @@ void rt2x00pci_uninitialize(struct rt2x0
+ }
+ EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize);
+
++#ifdef CONFIG_PCI
+ /*
+ * PCI driver handlers.
+ */
+@@ -392,6 +393,7 @@ int rt2x00pci_resume(struct pci_dev *pci
+ }
+ EXPORT_SYMBOL_GPL(rt2x00pci_resume);
+ #endif /* CONFIG_PM */
++#endif /* CONFIG_PCI */
+
+ /*
+ * rt2x00pci module information.
diff --git a/package/mac80211/patches/601-rt2x00-set_pci_mwi.patch b/package/mac80211/patches/601-rt2x00-set_pci_mwi.patch
new file mode 100644
index 000000000..9ff50b7bf
--- /dev/null
+++ b/package/mac80211/patches/601-rt2x00-set_pci_mwi.patch
@@ -0,0 +1,13 @@
+--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
++++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
+@@ -273,8 +273,10 @@ int rt2x00pci_probe(struct pci_dev *pci_
+
+ pci_set_master(pci_dev);
+
++#ifdef CONFIG_PCI_SET_MWI
+ if (pci_set_mwi(pci_dev))
+ ERROR_PROBE("MWI not available.\n");
++#endif
+
+ if (dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32))) {
+ ERROR_PROBE("PCI DMA not supported.\n");
diff --git a/package/mac80211/patches/602-rt2x00-introduce-rt2x00_platform_h.patch b/package/mac80211/patches/602-rt2x00-introduce-rt2x00_platform_h.patch
new file mode 100644
index 000000000..6c80c3dfa
--- /dev/null
+++ b/package/mac80211/patches/602-rt2x00-introduce-rt2x00_platform_h.patch
@@ -0,0 +1,32 @@
+--- /dev/null
++++ b/include/linux/rt2x00_platform.h
+@@ -0,0 +1,19 @@
++/*
++ * Platform data definition for the rt2x00 driver
++ *
++ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
++ *
++ * 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.
++ *
++ */
++
++#ifndef _RT2X00_PLATFORM_H
++#define _RT2X00_PLATFORM_H
++
++struct rt2x00_platform_data {
++ char *eeprom_file_name;
++};
++
++#endif /* _RT2X00_PLATFORM_H */
+--- a/drivers/net/wireless/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/rt2x00/rt2x00.h
+@@ -39,6 +39,7 @@
+ #include <linux/input-polldev.h>
+ #include <linux/kfifo.h>
+ #include <linux/hrtimer.h>
++#include <linux/rt2x00_platform.h>
+
+ #include <net/mac80211.h>
+
diff --git a/package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch b/package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch
new file mode 100644
index 000000000..4f35ae899
--- /dev/null
+++ b/package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch
@@ -0,0 +1,274 @@
+--- /dev/null
++++ b/drivers/net/wireless/rt2x00/rt2x00eeprom.c
+@@ -0,0 +1,98 @@
++/*
++ Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
++ Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
++ <http://rt2x00.serialmonkey.com>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ 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.
++ */
++
++/*
++ Module: rt2x00lib
++ Abstract: rt2x00 eeprom file loading routines.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++
++#include "rt2x00.h"
++#include "rt2x00lib.h"
++
++static int rt2x00lib_request_eeprom_file(struct rt2x00_dev *rt2x00dev)
++{
++ const struct firmware *ee;
++ char *ee_name;
++ int retval;
++
++ ee_name = rt2x00dev->ops->lib->get_eeprom_file_name(rt2x00dev);
++ if (!ee_name) {
++ ERROR(rt2x00dev,
++ "Invalid EEPROM filename.\n"
++ "Please file bug report to %s.\n", DRV_PROJECT);
++ return -EINVAL;
++ }
++
++ INFO(rt2x00dev, "Loading EEPROM data from '%s'.\n", ee_name);
++
++ retval = request_firmware(&ee, ee_name, rt2x00dev->dev);
++ if (retval) {
++ ERROR(rt2x00dev, "Failed to request EEPROM.\n");
++ return retval;
++ }
++
++ if (!ee || !ee->size || !ee->data) {
++ ERROR(rt2x00dev, "Failed to read EEPROM file.\n");
++ retval = -ENOENT;
++ goto err_exit;
++ }
++
++ if (ee->size != rt2x00dev->ops->eeprom_size) {
++ ERROR(rt2x00dev,
++ "EEPROM file size is invalid, it should be %d bytes\n",
++ rt2x00dev->ops->eeprom_size);
++ retval = -EINVAL;
++ goto err_release_ee;
++ }
++
++ rt2x00dev->eeprom_file = ee;
++ return 0;
++
++err_release_ee:
++ release_firmware(ee);
++err_exit:
++ return retval;
++}
++
++int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev)
++{
++ int retval;
++
++ if (!test_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags))
++ return 0;
++
++ if (!rt2x00dev->eeprom_file) {
++ retval = rt2x00lib_request_eeprom_file(rt2x00dev);
++ if (retval)
++ return retval;
++ }
++
++ return 0;
++}
++
++void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev)
++{
++ release_firmware(rt2x00dev->eeprom_file);
++ rt2x00dev->eeprom_file = NULL;
++}
+--- a/drivers/net/wireless/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/rt2x00/rt2x00.h
+@@ -560,6 +560,7 @@ struct rt2x00lib_ops {
+ const u8 *data, const size_t len);
+ int (*load_firmware) (struct rt2x00_dev *rt2x00dev,
+ const u8 *data, const size_t len);
++ char *(*get_eeprom_file_name) (struct rt2x00_dev *rt2x00dev);
+
+ /*
+ * Device initialization/deinitialization handlers.
+@@ -721,6 +722,7 @@ enum rt2x00_capability_flags {
+ REQUIRE_SW_SEQNO,
+ REQUIRE_HT_TX_DESC,
+ REQUIRE_PS_AUTOWAKE,
++ REQUIRE_EEPROM_FILE,
+
+ /*
+ * Capabilities
+@@ -976,6 +978,11 @@ struct rt2x00_dev {
+ const struct firmware *fw;
+
+ /*
++ * EEPROM image.
++ */
++ const struct firmware *eeprom_file;
++
++ /*
+ * FIFO for storing tx status reports between isr and tasklet.
+ */
+ DECLARE_KFIFO_PTR(txstatus_fifo, u32);
+--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
++++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
+@@ -322,6 +322,22 @@ static inline void rt2x00lib_free_firmwa
+ #endif /* CONFIG_RT2X00_LIB_FIRMWARE */
+
+ /*
++ * EEPROM file handlers.
++ */
++#ifdef CONFIG_RT2X00_LIB_EEPROM
++int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev);
++void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev);
++#else
++static inline int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev)
++{
++ return 0;
++}
++static inline void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev)
++{
++}
++#endif /* CONFIG_RT2X00_LIB_EEPROM_FILE */
++
++/*
+ * Debugfs handlers.
+ */
+ #ifdef CONFIG_RT2X00_LIB_DEBUGFS
+--- a/drivers/net/wireless/rt2x00/Kconfig
++++ b/drivers/net/wireless/rt2x00/Kconfig
+@@ -60,6 +60,7 @@ config RT2800PCI
+ select RT2X00_LIB_PCI if PCI
+ select RT2X00_LIB_SOC if RALINK_RT288X || RALINK_RT305X
+ select RT2X00_LIB_FIRMWARE
++ select RT2X00_LIB_EEPROM
+ select RT2X00_LIB_CRYPTO
+ select CRC_CCITT
+ select EEPROM_93CX6
+@@ -212,6 +213,9 @@ config RT2X00_LIB_FIRMWARE
+ config RT2X00_LIB_CRYPTO
+ boolean
+
++config RT2X00_LIB_EEPROM
++ boolean
++
+ config RT2X00_LIB_LEDS
+ boolean
+ default y if (RT2X00_LIB=y && LEDS_CLASS=y) || (RT2X00_LIB=m && LEDS_CLASS!=n)
+--- a/drivers/net/wireless/rt2x00/Makefile
++++ b/drivers/net/wireless/rt2x00/Makefile
+@@ -7,6 +7,7 @@ rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS) +
+ rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o
+ rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o
+ rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o
++rt2x00lib-$(CONFIG_RT2X00_LIB_EEPROM) += rt2x00eeprom.o
+
+ obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o
+ obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o
+--- a/drivers/net/wireless/rt2x00/rt2800pci.c
++++ b/drivers/net/wireless/rt2x00/rt2800pci.c
+@@ -89,20 +89,10 @@ static void rt2800pci_mcu_status(struct
+ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+ }
+
+-#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X)
+ static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
+ {
+- void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE);
+-
+- memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE);
+-
+- iounmap(base_addr);
++ memcpy(rt2x00dev->eeprom, rt2x00dev->eeprom_file->data, EEPROM_SIZE);
+ }
+-#else
+-static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
+-{
+-}
+-#endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */
+
+ #ifdef CONFIG_PCI
+ static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
+@@ -322,6 +312,20 @@ static int rt2800pci_write_firmware(stru
+ }
+
+ /*
++ * EEPROM file functions.
++ */
++static char *rt2800pci_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
++{
++ struct rt2x00_platform_data *pdata;
++
++ pdata = rt2x00dev->dev->platform_data;
++ if (pdata)
++ return pdata->eeprom_file_name;
++
++ return NULL;
++}
++
++/*
+ * Initialization functions.
+ */
+ static bool rt2800pci_get_entry_state(struct queue_entry *entry)
+@@ -1033,6 +1037,7 @@ static const struct rt2x00lib_ops rt2800
+ .get_firmware_name = rt2800pci_get_firmware_name,
+ .check_firmware = rt2800_check_firmware,
+ .load_firmware = rt2800_load_firmware,
++ .get_eeprom_file_name = rt2800pci_get_eeprom_file_name,
+ .initialize = rt2x00pci_initialize,
+ .uninitialize = rt2x00pci_uninitialize,
+ .get_entry_state = rt2800pci_get_entry_state,
+--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+@@ -1163,6 +1163,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de
+
+ rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+
++ retval = rt2x00lib_load_eeprom_file(rt2x00dev);
++ if (retval)
++ goto exit;
++
+ /*
+ * Initialize work.
+ */
+@@ -1287,6 +1291,11 @@ void rt2x00lib_remove_dev(struct rt2x00_
+ */
+ if (rt2x00dev->drv_data)
+ kfree(rt2x00dev->drv_data);
++
++ /*
++ * Free EEPROM image.
++ */
++ rt2x00lib_free_eeprom_file(rt2x00dev);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
+
+--- a/drivers/net/wireless/rt2x00/rt2x00soc.c
++++ b/drivers/net/wireless/rt2x00/rt2x00soc.c
+@@ -94,6 +94,7 @@ int rt2x00soc_probe(struct platform_devi
+ rt2x00dev->hw = hw;
+ rt2x00dev->irq = platform_get_irq(pdev, 0);
+ rt2x00dev->name = pdev->dev.driver->name;
++ set_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags);
+
+ rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
+
diff --git a/package/mac80211/patches/604-rt2x00-add-CONFIG_RT2X00_LIB_EEPROM-option.patch b/package/mac80211/patches/604-rt2x00-add-CONFIG_RT2X00_LIB_EEPROM-option.patch
new file mode 100644
index 000000000..5331b2678
--- /dev/null
+++ b/package/mac80211/patches/604-rt2x00-add-CONFIG_RT2X00_LIB_EEPROM-option.patch
@@ -0,0 +1,10 @@
+--- a/config.mk
++++ b/config.mk
+@@ -624,6 +624,7 @@ export CONFIG_RT2X00=y
+ export CONFIG_RT2X00_LIB=m
+ export CONFIG_RT2800_LIB=m
+ export CONFIG_RT2X00_LIB_FIRMWARE=y
++export CONFIG_RT2X00_LIB_EEPROM=y
+ export CONFIG_RT2X00_LIB_CRYPTO=y
+ # export CONFIG_RT2X00_LIB_SOC=y
+ ifdef CONFIG_COMPAT_KERNEL_2_6_25
diff --git a/package/mac80211/patches/605-rt2x00-pci-eeprom.patch b/package/mac80211/patches/605-rt2x00-pci-eeprom.patch
new file mode 100644
index 000000000..fbc86199a
--- /dev/null
+++ b/package/mac80211/patches/605-rt2x00-pci-eeprom.patch
@@ -0,0 +1,46 @@
+--- a/drivers/net/wireless/rt2x00/rt2800pci.c
++++ b/drivers/net/wireless/rt2x00/rt2800pci.c
+@@ -89,7 +89,7 @@ static void rt2800pci_mcu_status(struct
+ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+ }
+
+-static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
++static void rt2800pci_read_eeprom_file(struct rt2x00_dev *rt2x00dev)
+ {
+ memcpy(rt2x00dev->eeprom, rt2x00dev->eeprom_file->data, EEPROM_SIZE);
+ }
+@@ -976,8 +976,9 @@ static irqreturn_t rt2800pci_interrupt(i
+ */
+ static void rt2800pci_read_eeprom(struct rt2x00_dev *rt2x00dev)
+ {
+- if (rt2x00_is_soc(rt2x00dev))
+- rt2800pci_read_eeprom_soc(rt2x00dev);
++ if (rt2x00_is_soc(rt2x00dev) ||
++ test_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags))
++ rt2800pci_read_eeprom_file(rt2x00dev);
+ else if (rt2800pci_efuse_detect(rt2x00dev))
+ rt2800pci_read_eeprom_efuse(rt2x00dev);
+ else
+--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
++++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
+@@ -255,6 +255,7 @@ exit:
+ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
+ {
+ struct ieee80211_hw *hw;
++ struct rt2x00_platform_data *pdata;
+ struct rt2x00_dev *rt2x00dev;
+ int retval;
+ u16 chip;
+@@ -300,6 +301,12 @@ int rt2x00pci_probe(struct pci_dev *pci_
+ rt2x00dev->irq = pci_dev->irq;
+ rt2x00dev->name = pci_name(pci_dev);
+
++ /* if we get passed the name of a eeprom_file_name, then use this in
++ favour of the eeprom */
++ pdata = rt2x00dev->dev->platform_data;
++ if (pdata && pdata->eeprom_file_name)
++ set_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags);
++
+ if (pci_is_pcie(pci_dev))
+ rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE);
+ else
diff --git a/package/mac80211/patches/606-rt2x00_no_realign.patch b/package/mac80211/patches/606-rt2x00_no_realign.patch
new file mode 100644
index 000000000..e0a920a58
--- /dev/null
+++ b/package/mac80211/patches/606-rt2x00_no_realign.patch
@@ -0,0 +1,67 @@
+[RFC] rt2x00: For drivers that only need L2 padding don't realign frames
+
+Signed-off-by: Helmut Schaa <helmut.schaa@...>
+---
+
+Ivo, Gertjan, do you remeber by any chance why this alignment stuff was added
+in the first place? Was it because of DMA restrictions?
+
+While doing some profiling on the rt3052 SoC I noticed that 30-40% time was
+spent in memmove calls. And the culprit is the memmove aligning the payload
+to a 4byte boundary since that has to move a whole bunch of data.
+
+Interesstingly the legacy drivers insert an l2pad between the header and the
+payload but doesn't realign the payload itself to a 4-byte boundary. Hence,
+I came up with this patch and indeed CPU usage improves impressively.
+
+Only tested on rt2800pci!
+
+Thanks,
+Helmut
+
+ drivers/net/wireless/rt2x00/rt2x00queue.c | 30 +++-------------------------
+ 1 files changed, 4 insertions(+), 26 deletions(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
++++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
+@@ -151,36 +151,14 @@ void rt2x00queue_align_frame(struct sk_b
+ void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length)
+ {
+ unsigned int payload_length = skb->len - header_length;
+- unsigned int header_align = ALIGN_SIZE(skb, 0);
+- unsigned int payload_align = ALIGN_SIZE(skb, header_length);
+ unsigned int l2pad = payload_length ? L2PAD_SIZE(header_length) : 0;
+
+- /*
+- * Adjust the header alignment if the payload needs to be moved more
+- * than the header.
+- */
+- if (payload_align > header_align)
+- header_align += 4;
+-
+- /* There is nothing to do if no alignment is needed */
+- if (!header_align)
++ if (!l2pad)
+ return;
+
+- /* Reserve the amount of space needed in front of the frame */
+- skb_push(skb, header_align);
+-
+- /*
+- * Move the header.
+- */
+- memmove(skb->data, skb->data + header_align, header_length);
+-
+- /* Move the payload, if present and if required */
+- if (payload_length && payload_align)
+- memmove(skb->data + header_length + l2pad,
+- skb->data + header_length + l2pad + payload_align,
+- payload_length);
+-
+- /* Trim the skb to the correct size */
++ /* insert l2pad -> Move header */
++ skb_push(skb, l2pad);
++ memmove(skb->data, skb->data + l2pad, header_length);
+ skb_trim(skb, header_length + l2pad + payload_length);
+ }
+
diff --git a/package/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch b/package/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch
new file mode 100644
index 000000000..57abb07ab
--- /dev/null
+++ b/package/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch
@@ -0,0 +1,47 @@
+--- a/include/linux/rt2x00_platform.h
++++ b/include/linux/rt2x00_platform.h
+@@ -14,6 +14,9 @@
+
+ struct rt2x00_platform_data {
+ char *eeprom_file_name;
++
++ int disable_2ghz;
++ int disable_5ghz;
+ };
+
+ #endif /* _RT2X00_PLATFORM_H */
+--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+@@ -834,6 +834,22 @@ static int rt2x00lib_probe_hw_modes(stru
+ unsigned int num_rates;
+ unsigned int i;
+
++ if (rt2x00dev->dev->platform_data) {
++ struct rt2x00_platform_data *pdata;
++
++ pdata = rt2x00dev->dev->platform_data;
++ if (pdata->disable_2ghz)
++ spec->supported_bands &= ~SUPPORT_BAND_2GHZ;
++ if (pdata->disable_5ghz)
++ spec->supported_bands &= ~SUPPORT_BAND_5GHZ;
++ }
++
++ if ((spec->supported_bands & SUPPORT_BAND_BOTH) == 0) {
++ ERROR(rt2x00dev, "No supported bands\n");
++ return -EINVAL;
++ }
++
++
+ num_rates = 0;
+ if (spec->supported_rates & SUPPORT_RATE_CCK)
+ num_rates += 4;
+--- a/drivers/net/wireless/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/rt2x00/rt2x00.h
+@@ -425,6 +425,7 @@ struct hw_mode_spec {
+ unsigned int supported_bands;
+ #define SUPPORT_BAND_2GHZ 0x00000001
+ #define SUPPORT_BAND_5GHZ 0x00000002
++#define SUPPORT_BAND_BOTH (SUPPORT_BAND_2GHZ | SUPPORT_BAND_5GHZ)
+
+ unsigned int supported_rates;
+ #define SUPPORT_RATE_CCK 0x00000001
diff --git a/package/mac80211/patches/608-add_platform_data_mac_addr.patch b/package/mac80211/patches/608-add_platform_data_mac_addr.patch
new file mode 100644
index 000000000..c1b22e7a2
--- /dev/null
+++ b/package/mac80211/patches/608-add_platform_data_mac_addr.patch
@@ -0,0 +1,63 @@
+--- a/include/linux/rt2x00_platform.h
++++ b/include/linux/rt2x00_platform.h
+@@ -14,6 +14,7 @@
+
+ struct rt2x00_platform_data {
+ char *eeprom_file_name;
++ const u8 *mac_address;
+
+ int disable_2ghz;
+ int disable_5ghz;
+--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+@@ -825,6 +825,18 @@ static void rt2x00lib_rate(struct ieee80
+ entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE;
+ }
+
++const u8 *rt2x00lib_get_mac_address(struct rt2x00_dev *rt2x00dev)
++{
++ struct rt2x00_platform_data *pdata;
++
++ pdata = rt2x00dev->dev->platform_data;
++ if (!pdata)
++ return NULL;
++
++ return pdata->mac_address;
++}
++EXPORT_SYMBOL_GPL(rt2x00lib_get_mac_address);
++
+ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
+ struct hw_mode_spec *spec)
+ {
+--- a/drivers/net/wireless/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/rt2x00/rt2x00.h
+@@ -1280,6 +1280,7 @@ static inline void rt2x00debug_dump_fram
+ */
+ u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_vif *vif);
++const u8 *rt2x00lib_get_mac_address(struct rt2x00_dev *rt2x00dev);
+
+ /*
+ * Interrupt context handlers.
+--- a/drivers/net/wireless/rt2x00/rt61pci.c
++++ b/drivers/net/wireless/rt2x00/rt61pci.c
+@@ -2392,6 +2392,7 @@ static int rt61pci_validate_eeprom(struc
+ u32 reg;
+ u16 word;
+ u8 *mac;
++ const u8 *pdata_mac;
+ s8 value;
+
+ rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);
+@@ -2412,7 +2413,11 @@ static int rt61pci_validate_eeprom(struc
+ /*
+ * Start validation of the data that has been read.
+ */
++ pdata_mac = rt2x00lib_get_mac_address(rt2x00dev);
+ mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
++ if (pdata_mac)
++ memcpy(mac, pdata_mac, 6);
++
+ if (!is_valid_ether_addr(mac)) {
+ eth_random_addr(mac);
+ EEPROM(rt2x00dev, "MAC: %pM\n", mac);
diff --git a/package/mac80211/patches/620-rt2x00-support-rt3352.patch b/package/mac80211/patches/620-rt2x00-support-rt3352.patch
new file mode 100644
index 000000000..bb2086daa
--- /dev/null
+++ b/package/mac80211/patches/620-rt2x00-support-rt3352.patch
@@ -0,0 +1,464 @@
+From 03839951515b0ea2b21d649b1fe7b63f9817d0c8 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <dgolle@allnet.de>
+Date: Sun, 9 Sep 2012 14:24:39 +0300
+Subject: [PATCH] rt2x00: add MediaTek/RaLink Rt3352 WiSoC
+
+Support for the RT3352 WiSoC was developed for and tested with the ALL5002
+devboard running OpenWrt. For now, this supports only devices with internal
+TXALC. Corrections were made according to the remarks of Stanislaw Gruszka and
+Gertjan van Wingerde, thank you guys for reviewing!
+
+Signed-off-by: Daniel Golle <dgolle@allnet.de>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+---
+ drivers/net/wireless/rt2x00/rt2800.h | 5 +
+ drivers/net/wireless/rt2x00/rt2800lib.c | 211 +++++++++++++++++++++++++++++++-
+ drivers/net/wireless/rt2x00/rt2x00.h | 1 +
+ 3 files changed, 212 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
+index e13916f..6d67c3e 100644
+--- a/drivers/net/wireless/rt2x00/rt2800.h
++++ b/drivers/net/wireless/rt2x00/rt2800.h
+@@ -1943,6 +1943,11 @@ struct mac_iveiv_entry {
+ #define BBP47_TSSI_ADC6 FIELD8(0x80)
+
+ /*
++ * BBP 49
++ */
++#define BBP49_UPDATE_FLAG FIELD8(0x01)
++
++/*
+ * BBP 109
+ */
+ #define BBP109_TX0_POWER FIELD8(0x0f)
+diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
+index a04e222..9e09367 100644
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -1615,6 +1615,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
+ case 1:
+ if (rt2x00_rt(rt2x00dev, RT3070) ||
+ rt2x00_rt(rt2x00dev, RT3090) ||
++ rt2x00_rt(rt2x00dev, RT3352) ||
+ rt2x00_rt(rt2x00dev, RT3390)) {
+ rt2x00_eeprom_read(rt2x00dev,
+ EEPROM_NIC_CONF1, &eeprom);
+@@ -2053,6 +2054,60 @@ static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
+ }
+ }
+
++static void rt2800_config_channel_rf3322(struct rt2x00_dev *rt2x00dev,
++ struct ieee80211_conf *conf,
++ struct rf_channel *rf,
++ struct channel_info *info)
++{
++ u8 rfcsr;
++
++ rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
++ rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
++
++ rt2800_rfcsr_write(rt2x00dev, 11, 0x42);
++ rt2800_rfcsr_write(rt2x00dev, 12, 0x1c);
++ rt2800_rfcsr_write(rt2x00dev, 13, 0x00);
++
++ if (info->default_power1 > POWER_BOUND)
++ rt2800_rfcsr_write(rt2x00dev, 47, POWER_BOUND);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 47, info->default_power1);
++
++ if (info->default_power2 > POWER_BOUND)
++ rt2800_rfcsr_write(rt2x00dev, 48, POWER_BOUND);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 48, info->default_power2);
++
++ rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
++ if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND)
++ rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND);
++ else
++ rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
++
++ rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
++
++ rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
++ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
++ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
++
++ if ( rt2x00dev->default_ant.tx_chain_num == 2 )
++ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
++ else
++ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0);
++
++ if ( rt2x00dev->default_ant.rx_chain_num == 2 )
++ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
++ else
++ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
++
++ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0);
++ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0);
++
++ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
++
++ rt2800_rfcsr_write(rt2x00dev, 31, 80);
++}
++
+ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_conf *conf,
+ struct rf_channel *rf,
+@@ -2182,6 +2237,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
+ case RF3290:
+ rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info);
+ break;
++ case RF3322:
++ rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);
++ break;
+ case RF5360:
+ case RF5370:
+ case RF5372:
+@@ -2194,6 +2252,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
+ }
+
+ if (rt2x00_rf(rt2x00dev, RF3290) ||
++ rt2x00_rf(rt2x00dev, RF3322) ||
+ rt2x00_rf(rt2x00dev, RF5360) ||
+ rt2x00_rf(rt2x00dev, RF5370) ||
+ rt2x00_rf(rt2x00dev, RF5372) ||
+@@ -2212,10 +2271,17 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
+ /*
+ * Change BBP settings
+ */
+- rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
+- rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
+- rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
+- rt2800_bbp_write(rt2x00dev, 86, 0);
++ if (rt2x00_rt(rt2x00dev, RT3352)) {
++ rt2800_bbp_write(rt2x00dev, 27, 0x0);
++ rt2800_bbp_write(rt2x00dev, 62, 0x26 + rt2x00dev->lna_gain);
++ rt2800_bbp_write(rt2x00dev, 27, 0x20);
++ rt2800_bbp_write(rt2x00dev, 62, 0x26 + rt2x00dev->lna_gain);
++ } else {
++ rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
++ rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
++ rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
++ rt2800_bbp_write(rt2x00dev, 86, 0);
++ }
+
+ if (rf->channel <= 14) {
+ if (!rt2x00_rt(rt2x00dev, RT5390) &&
+@@ -2310,6 +2376,15 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
+ rt2800_register_read(rt2x00dev, CH_IDLE_STA, &reg);
+ rt2800_register_read(rt2x00dev, CH_BUSY_STA, &reg);
+ rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &reg);
++
++ /*
++ * Clear update flag
++ */
++ if (rt2x00_rt(rt2x00dev, RT3352)) {
++ rt2800_bbp_read(rt2x00dev, 49, &bbp);
++ rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0);
++ rt2800_bbp_write(rt2x00dev, 49, bbp);
++ }
+ }
+
+ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
+@@ -2998,6 +3073,10 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
+ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
+ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
+ rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030);
++ } else if (rt2x00_rt(rt2x00dev, RT3352)) {
++ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402);
++ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
++ rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
+ } else if (rt2x00_rt(rt2x00dev, RT3572)) {
+ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
+ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+@@ -3378,6 +3457,11 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
+ rt2800_wait_bbp_ready(rt2x00dev)))
+ return -EACCES;
+
++ if (rt2x00_rt(rt2x00dev, RT3352)) {
++ rt2800_bbp_write(rt2x00dev, 3, 0x00);
++ rt2800_bbp_write(rt2x00dev, 4, 0x50);
++ }
++
+ if (rt2x00_rt(rt2x00dev, RT3290) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392)) {
+@@ -3388,15 +3472,20 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
+
+ if (rt2800_is_305x_soc(rt2x00dev) ||
+ rt2x00_rt(rt2x00dev, RT3290) ||
++ rt2x00_rt(rt2x00dev, RT3352) ||
+ rt2x00_rt(rt2x00dev, RT3572) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392))
+ rt2800_bbp_write(rt2x00dev, 31, 0x08);
+
++ if (rt2x00_rt(rt2x00dev, RT3352))
++ rt2800_bbp_write(rt2x00dev, 47, 0x48);
++
+ rt2800_bbp_write(rt2x00dev, 65, 0x2c);
+ rt2800_bbp_write(rt2x00dev, 66, 0x38);
+
+ if (rt2x00_rt(rt2x00dev, RT3290) ||
++ rt2x00_rt(rt2x00dev, RT3352) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392))
+ rt2800_bbp_write(rt2x00dev, 68, 0x0b);
+@@ -3405,6 +3494,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
+ rt2800_bbp_write(rt2x00dev, 69, 0x16);
+ rt2800_bbp_write(rt2x00dev, 73, 0x12);
+ } else if (rt2x00_rt(rt2x00dev, RT3290) ||
++ rt2x00_rt(rt2x00dev, RT3352) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392)) {
+ rt2800_bbp_write(rt2x00dev, 69, 0x12);
+@@ -3436,6 +3526,10 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
+ } else if (rt2800_is_305x_soc(rt2x00dev)) {
+ rt2800_bbp_write(rt2x00dev, 78, 0x0e);
+ rt2800_bbp_write(rt2x00dev, 80, 0x08);
++ } else if (rt2x00_rt(rt2x00dev, RT3352)) {
++ rt2800_bbp_write(rt2x00dev, 78, 0x0e);
++ rt2800_bbp_write(rt2x00dev, 80, 0x08);
++ rt2800_bbp_write(rt2x00dev, 81, 0x37);
+ } else {
+ rt2800_bbp_write(rt2x00dev, 81, 0x37);
+ }
+@@ -3465,18 +3559,21 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
+ rt2800_bbp_write(rt2x00dev, 84, 0x99);
+
+ if (rt2x00_rt(rt2x00dev, RT3290) ||
++ rt2x00_rt(rt2x00dev, RT3352) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392))
+ rt2800_bbp_write(rt2x00dev, 86, 0x38);
+ else
+ rt2800_bbp_write(rt2x00dev, 86, 0x00);
+
+- if (rt2x00_rt(rt2x00dev, RT5392))
++ if (rt2x00_rt(rt2x00dev, RT3352) ||
++ rt2x00_rt(rt2x00dev, RT5392))
+ rt2800_bbp_write(rt2x00dev, 88, 0x90);
+
+ rt2800_bbp_write(rt2x00dev, 91, 0x04);
+
+ if (rt2x00_rt(rt2x00dev, RT3290) ||
++ rt2x00_rt(rt2x00dev, RT3352) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392))
+ rt2800_bbp_write(rt2x00dev, 92, 0x02);
+@@ -3493,6 +3590,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
+ rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) ||
+ rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) ||
+ rt2x00_rt(rt2x00dev, RT3290) ||
++ rt2x00_rt(rt2x00dev, RT3352) ||
+ rt2x00_rt(rt2x00dev, RT3572) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392) ||
+@@ -3502,6 +3600,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
+ rt2800_bbp_write(rt2x00dev, 103, 0x00);
+
+ if (rt2x00_rt(rt2x00dev, RT3290) ||
++ rt2x00_rt(rt2x00dev, RT3352) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392))
+ rt2800_bbp_write(rt2x00dev, 104, 0x92);
+@@ -3510,6 +3609,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
+ rt2800_bbp_write(rt2x00dev, 105, 0x01);
+ else if (rt2x00_rt(rt2x00dev, RT3290))
+ rt2800_bbp_write(rt2x00dev, 105, 0x1c);
++ else if (rt2x00_rt(rt2x00dev, RT3352))
++ rt2800_bbp_write(rt2x00dev, 105, 0x34);
+ else if (rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392))
+ rt2800_bbp_write(rt2x00dev, 105, 0x3c);
+@@ -3519,11 +3620,16 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
+ if (rt2x00_rt(rt2x00dev, RT3290) ||
+ rt2x00_rt(rt2x00dev, RT5390))
+ rt2800_bbp_write(rt2x00dev, 106, 0x03);
++ else if (rt2x00_rt(rt2x00dev, RT3352))
++ rt2800_bbp_write(rt2x00dev, 106, 0x05);
+ else if (rt2x00_rt(rt2x00dev, RT5392))
+ rt2800_bbp_write(rt2x00dev, 106, 0x12);
+ else
+ rt2800_bbp_write(rt2x00dev, 106, 0x35);
+
++ if (rt2x00_rt(rt2x00dev, RT3352))
++ rt2800_bbp_write(rt2x00dev, 120, 0x50);
++
+ if (rt2x00_rt(rt2x00dev, RT3290) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392))
+@@ -3534,6 +3640,9 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
+ rt2800_bbp_write(rt2x00dev, 135, 0xf6);
+ }
+
++ if (rt2x00_rt(rt2x00dev, RT3352))
++ rt2800_bbp_write(rt2x00dev, 137, 0x0f);
++
+ if (rt2x00_rt(rt2x00dev, RT3071) ||
+ rt2x00_rt(rt2x00dev, RT3090) ||
+ rt2x00_rt(rt2x00dev, RT3390) ||
+@@ -3574,6 +3683,28 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
+ rt2800_bbp_write(rt2x00dev, 3, value);
+ }
+
++ if (rt2x00_rt(rt2x00dev, RT3352)) {
++ rt2800_bbp_write(rt2x00dev, 163, 0xbd);
++ /* Set ITxBF timeout to 0x9c40=1000msec */
++ rt2800_bbp_write(rt2x00dev, 179, 0x02);
++ rt2800_bbp_write(rt2x00dev, 180, 0x00);
++ rt2800_bbp_write(rt2x00dev, 182, 0x40);
++ rt2800_bbp_write(rt2x00dev, 180, 0x01);
++ rt2800_bbp_write(rt2x00dev, 182, 0x9c);
++ rt2800_bbp_write(rt2x00dev, 179, 0x00);
++ /* Reprogram the inband interface to put right values in RXWI */
++ rt2800_bbp_write(rt2x00dev, 142, 0x04);
++ rt2800_bbp_write(rt2x00dev, 143, 0x3b);
++ rt2800_bbp_write(rt2x00dev, 142, 0x06);
++ rt2800_bbp_write(rt2x00dev, 143, 0xa0);
++ rt2800_bbp_write(rt2x00dev, 142, 0x07);
++ rt2800_bbp_write(rt2x00dev, 143, 0xa1);
++ rt2800_bbp_write(rt2x00dev, 142, 0x08);
++ rt2800_bbp_write(rt2x00dev, 143, 0xa2);
++
++ rt2800_bbp_write(rt2x00dev, 148, 0xc8);
++ }
++
+ if (rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392)) {
+ int ant, div_mode;
+@@ -3707,6 +3838,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
+ !rt2x00_rt(rt2x00dev, RT3071) &&
+ !rt2x00_rt(rt2x00dev, RT3090) &&
+ !rt2x00_rt(rt2x00dev, RT3290) &&
++ !rt2x00_rt(rt2x00dev, RT3352) &&
+ !rt2x00_rt(rt2x00dev, RT3390) &&
+ !rt2x00_rt(rt2x00dev, RT3572) &&
+ !rt2x00_rt(rt2x00dev, RT5390) &&
+@@ -3903,6 +4035,70 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
+ rt2800_rfcsr_write(rt2x00dev, 30, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 31, 0x00);
+ return 0;
++ } else if (rt2x00_rt(rt2x00dev, RT3352)) {
++ rt2800_rfcsr_write(rt2x00dev, 0, 0xf0);
++ rt2800_rfcsr_write(rt2x00dev, 1, 0x23);
++ rt2800_rfcsr_write(rt2x00dev, 2, 0x50);
++ rt2800_rfcsr_write(rt2x00dev, 3, 0x18);
++ rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 5, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 6, 0x33);
++ rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 8, 0xf1);
++ rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
++ rt2800_rfcsr_write(rt2x00dev, 10, 0xd2);
++ rt2800_rfcsr_write(rt2x00dev, 11, 0x42);
++ rt2800_rfcsr_write(rt2x00dev, 12, 0x1c);
++ rt2800_rfcsr_write(rt2x00dev, 13, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 14, 0x5a);
++ rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 16, 0x01);
++ rt2800_rfcsr_write(rt2x00dev, 18, 0x45);
++ rt2800_rfcsr_write(rt2x00dev, 19, 0x02);
++ rt2800_rfcsr_write(rt2x00dev, 20, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 21, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 23, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 24, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 25, 0x80);
++ rt2800_rfcsr_write(rt2x00dev, 26, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
++ rt2800_rfcsr_write(rt2x00dev, 28, 0x03);
++ rt2800_rfcsr_write(rt2x00dev, 29, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
++ rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
++ rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
++ rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 34, 0x01);
++ rt2800_rfcsr_write(rt2x00dev, 35, 0x03);
++ rt2800_rfcsr_write(rt2x00dev, 36, 0xbd);
++ rt2800_rfcsr_write(rt2x00dev, 37, 0x3c);
++ rt2800_rfcsr_write(rt2x00dev, 38, 0x5f);
++ rt2800_rfcsr_write(rt2x00dev, 39, 0xc5);
++ rt2800_rfcsr_write(rt2x00dev, 40, 0x33);
++ rt2800_rfcsr_write(rt2x00dev, 41, 0x5b);
++ rt2800_rfcsr_write(rt2x00dev, 42, 0x5b);
++ rt2800_rfcsr_write(rt2x00dev, 43, 0xdb);
++ rt2800_rfcsr_write(rt2x00dev, 44, 0xdb);
++ rt2800_rfcsr_write(rt2x00dev, 45, 0xdb);
++ rt2800_rfcsr_write(rt2x00dev, 46, 0xdd);
++ rt2800_rfcsr_write(rt2x00dev, 47, 0x0d);
++ rt2800_rfcsr_write(rt2x00dev, 48, 0x14);
++ rt2800_rfcsr_write(rt2x00dev, 49, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 50, 0x2d);
++ rt2800_rfcsr_write(rt2x00dev, 51, 0x7f);
++ rt2800_rfcsr_write(rt2x00dev, 52, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 53, 0x52);
++ rt2800_rfcsr_write(rt2x00dev, 54, 0x1b);
++ rt2800_rfcsr_write(rt2x00dev, 55, 0x7f);
++ rt2800_rfcsr_write(rt2x00dev, 56, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 57, 0x52);
++ rt2800_rfcsr_write(rt2x00dev, 58, 0x1b);
++ rt2800_rfcsr_write(rt2x00dev, 59, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 60, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 61, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 62, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
+ } else if (rt2x00_rt(rt2x00dev, RT5390)) {
+ rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
+ rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
+@@ -4104,6 +4300,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
+ rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19);
+ } else if (rt2x00_rt(rt2x00dev, RT3071) ||
+ rt2x00_rt(rt2x00dev, RT3090) ||
++ rt2x00_rt(rt2x00dev, RT3352) ||
+ rt2x00_rt(rt2x00dev, RT3390) ||
+ rt2x00_rt(rt2x00dev, RT3572)) {
+ drv_data->calibration_bw20 =
+@@ -4566,6 +4763,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
+ case RT3071:
+ case RT3090:
+ case RT3290:
++ case RT3352:
+ case RT3390:
+ case RT3572:
+ case RT5390:
+@@ -4588,6 +4786,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
+ case RF3052:
+ case RF3290:
+ case RF3320:
++ case RF3322:
+ case RF5360:
+ case RF5370:
+ case RF5372:
+@@ -4612,6 +4811,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
+
+ if (rt2x00_rt(rt2x00dev, RT3070) ||
+ rt2x00_rt(rt2x00dev, RT3090) ||
++ rt2x00_rt(rt2x00dev, RT3352) ||
+ rt2x00_rt(rt2x00dev, RT3390)) {
+ value = rt2x00_get_field16(eeprom,
+ EEPROM_NIC_CONF1_ANT_DIVERSITY);
+@@ -4904,6 +5104,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ rt2x00_rf(rt2x00dev, RF3022) ||
+ rt2x00_rf(rt2x00dev, RF3290) ||
+ rt2x00_rf(rt2x00dev, RF3320) ||
++ rt2x00_rf(rt2x00dev, RF3322) ||
+ rt2x00_rf(rt2x00dev, RF5360) ||
+ rt2x00_rf(rt2x00dev, RF5370) ||
+ rt2x00_rf(rt2x00dev, RF5372) ||
+diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
+index f991e8b..49375c8 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/rt2x00/rt2x00.h
+@@ -188,6 +188,7 @@ struct rt2x00_chip {
+ #define RT3071 0x3071
+ #define RT3090 0x3090 /* 2.4GHz PCIe */
+ #define RT3290 0x3290
++#define RT3352 0x3352 /* WSOC */
+ #define RT3390 0x3390
+ #define RT3572 0x3572
+ #define RT3593 0x3593
+--
+1.7.12.2
+
diff --git a/package/mac80211/patches/621-rt2x00-fix-rt3352-lnagain.patch b/package/mac80211/patches/621-rt2x00-fix-rt3352-lnagain.patch
new file mode 100644
index 000000000..824c3810d
--- /dev/null
+++ b/package/mac80211/patches/621-rt2x00-fix-rt3352-lnagain.patch
@@ -0,0 +1,30 @@
+From d0ae5f33c0221339a50bd1005c569934417003a5 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <dgolle@allnet.de>
+Date: Thu, 4 Oct 2012 00:34:01 +0200
+Subject: [PATCH] rt2x00/rt3352: Fix lnagain assignment to use register 66.
+To: users@rt2x00.serialmonkey.com
+Cc: gwingerde@gmail.com
+
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
+index 540c94f..01dc889 100644
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -2252,9 +2252,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
+ */
+ if (rt2x00_rt(rt2x00dev, RT3352)) {
+ rt2800_bbp_write(rt2x00dev, 27, 0x0);
+- rt2800_bbp_write(rt2x00dev, 62, 0x26 + rt2x00dev->lna_gain);
++ rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain);
+ rt2800_bbp_write(rt2x00dev, 27, 0x20);
+- rt2800_bbp_write(rt2x00dev, 62, 0x26 + rt2x00dev->lna_gain);
++ rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain);
+ } else {
+ rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
+ rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
+--
+1.7.12.2
+
diff --git a/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch b/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch
new file mode 100644
index 000000000..7ebc4f12d
--- /dev/null
+++ b/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch
@@ -0,0 +1,10 @@
+--- a/drivers/net/wireless/mwl8k.c
++++ b/drivers/net/wireless/mwl8k.c
+@@ -5302,6 +5302,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
+ MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
+
+ static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
++ { PCI_VDEVICE(MARVELL, 0x2a02), .driver_data = MWL8363, },
+ { PCI_VDEVICE(MARVELL, 0x2a0a), .driver_data = MWL8363, },
+ { PCI_VDEVICE(MARVELL, 0x2a0c), .driver_data = MWL8363, },
+ { PCI_VDEVICE(MARVELL, 0x2a24), .driver_data = MWL8363, },
diff --git a/package/mac80211/patches/800-b43-gpio-mask-module-option.patch b/package/mac80211/patches/800-b43-gpio-mask-module-option.patch
new file mode 100644
index 000000000..55ab0aa3a
--- /dev/null
+++ b/package/mac80211/patches/800-b43-gpio-mask-module-option.patch
@@ -0,0 +1,37 @@
+--- a/drivers/net/wireless/b43/b43.h
++++ b/drivers/net/wireless/b43/b43.h
+@@ -807,6 +807,7 @@ struct b43_wldev {
+ bool qos_enabled; /* TRUE, if QoS is used. */
+ bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */
+ bool use_pio; /* TRUE if next init should use PIO */
++ int gpiomask; /* GPIO LED mask as a module parameter */
+
+ /* PHY/Radio device. */
+ struct b43_phy phy;
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -76,6 +76,11 @@ MODULE_FIRMWARE("b43/ucode16_mimo.fw");
+ MODULE_FIRMWARE("b43/ucode5.fw");
+ MODULE_FIRMWARE("b43/ucode9.fw");
+
++static int modparam_gpiomask = 0x000F;
++module_param_named(gpiomask, modparam_gpiomask, int, 0444);
++MODULE_PARM_DESC(gpiomask,
++ "GPIO mask for LED control (default 0x000F)");
++
+ static int modparam_bad_frames_preempt;
+ module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
+ MODULE_PARM_DESC(bad_frames_preempt,
+@@ -2688,10 +2693,10 @@ static int b43_gpio_init(struct b43_wlde
+ u32 mask, set;
+
+ b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0);
+- b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, 0xF);
++ b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, modparam_gpiomask);
+
+ mask = 0x0000001F;
+- set = 0x0000000F;
++ set = modparam_gpiomask;
+ if (dev->dev->chip_id == 0x4301) {
+ mask |= 0x0060;
+ set |= 0x0060;
diff --git a/package/mac80211/patches/810-b43_no_pio.patch b/package/mac80211/patches/810-b43_no_pio.patch
new file mode 100644
index 000000000..f511795b1
--- /dev/null
+++ b/package/mac80211/patches/810-b43_no_pio.patch
@@ -0,0 +1,75 @@
+--- a/drivers/net/wireless/b43/Makefile
++++ b/drivers/net/wireless/b43/Makefile
+@@ -20,7 +20,7 @@ b43-y += xmit.o
+ b43-y += lo.o
+ b43-y += wa.o
+ b43-y += dma.o
+-b43-y += pio.o
++b43-$(CONFIG_B43_PIO) += pio.o
+ b43-y += rfkill.o
+ b43-$(CONFIG_B43_LEDS) += leds.o
+ b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -1885,10 +1885,12 @@ static void b43_do_interrupt_thread(stru
+ dma_reason[0], dma_reason[1],
+ dma_reason[2], dma_reason[3],
+ dma_reason[4], dma_reason[5]);
++#ifdef CONFIG_B43_PIO
+ b43err(dev->wl, "This device does not support DMA "
+ "on your system. It will now be switched to PIO.\n");
+ /* Fall back to PIO transfers if we get fatal DMA errors! */
+ dev->use_pio = true;
++#endif
+ b43_controller_restart(dev, "DMA error");
+ return;
+ }
+--- a/drivers/net/wireless/b43/pio.h
++++ b/drivers/net/wireless/b43/pio.h
+@@ -150,7 +150,7 @@ static inline void b43_piorx_write32(str
+ b43_write32(q->dev, q->mmio_base + offset, value);
+ }
+
+-
++#ifdef CONFIG_B43_PIO
+ int b43_pio_init(struct b43_wldev *dev);
+ void b43_pio_free(struct b43_wldev *dev);
+
+@@ -161,5 +161,37 @@ void b43_pio_rx(struct b43_pio_rxqueue *
+
+ void b43_pio_tx_suspend(struct b43_wldev *dev);
+ void b43_pio_tx_resume(struct b43_wldev *dev);
++#else
++static inline int b43_pio_init(struct b43_wldev *dev)
++{
++ return 0;
++}
++
++static inline void b43_pio_free(struct b43_wldev *dev)
++{
++}
++
++static inline int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
++{
++ return 0;
++}
++
++static inline void b43_pio_handle_txstatus(struct b43_wldev *dev,
++ const struct b43_txstatus *status)
++{
++}
++
++static inline void b43_pio_rx(struct b43_pio_rxqueue *q)
++{
++}
++
++static inline void b43_pio_tx_suspend(struct b43_wldev *dev)
++{
++}
++
++static inline void b43_pio_tx_resume(struct b43_wldev *dev)
++{
++}
++#endif /* CONFIG_B43_PIO */
+
+ #endif /* B43_PIO_H_ */
diff --git a/package/mac80211/patches/820-b43-add-antenna-control.patch b/package/mac80211/patches/820-b43-add-antenna-control.patch
new file mode 100644
index 000000000..551213d5f
--- /dev/null
+++ b/package/mac80211/patches/820-b43-add-antenna-control.patch
@@ -0,0 +1,131 @@
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -1529,7 +1529,7 @@ static void b43_write_beacon_template(st
+ len, ram_offset, shm_size_offset, rate);
+
+ /* Write the PHY TX control parameters. */
+- antenna = B43_ANTENNA_DEFAULT;
++ antenna = dev->tx_antenna;
+ antenna = b43_antenna_to_phyctl(antenna);
+ ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
+ /* We can't send beacons with short preamble. Would get PHY errors. */
+@@ -3049,8 +3049,8 @@ static int b43_chip_init(struct b43_wlde
+
+ /* Select the antennae */
+ if (phy->ops->set_rx_antenna)
+- phy->ops->set_rx_antenna(dev, B43_ANTENNA_DEFAULT);
+- b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT);
++ phy->ops->set_rx_antenna(dev, dev->rx_antenna);
++ b43_mgmtframe_txantenna(dev, dev->tx_antenna);
+
+ if (phy->type == B43_PHYTYPE_B) {
+ value16 = b43_read16(dev, 0x005E);
+@@ -3794,7 +3794,6 @@ static int b43_op_config(struct ieee8021
+ struct b43_wldev *dev;
+ struct b43_phy *phy;
+ struct ieee80211_conf *conf = &hw->conf;
+- int antenna;
+ int err = 0;
+ bool reload_bss = false;
+
+@@ -3848,11 +3847,9 @@ static int b43_op_config(struct ieee8021
+ }
+
+ /* Antennas for RX and management frame TX. */
+- antenna = B43_ANTENNA_DEFAULT;
+- b43_mgmtframe_txantenna(dev, antenna);
+- antenna = B43_ANTENNA_DEFAULT;
++ b43_mgmtframe_txantenna(dev, dev->tx_antenna);
+ if (phy->ops->set_rx_antenna)
+- phy->ops->set_rx_antenna(dev, antenna);
++ phy->ops->set_rx_antenna(dev, dev->rx_antenna);
+
+ if (wl->radio_enabled != phy->radio_on) {
+ if (wl->radio_enabled) {
+@@ -4974,6 +4971,47 @@ static int b43_op_get_survey(struct ieee
+ return 0;
+ }
+
++static int b43_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
++{
++ struct b43_wl *wl = hw_to_b43_wl(hw);
++ struct b43_wldev *dev = wl->current_dev;
++
++ if (tx_ant == 1 && rx_ant == 1) {
++ dev->tx_antenna = B43_ANTENNA0;
++ dev->rx_antenna = B43_ANTENNA0;
++ }
++ else if (tx_ant == 2 && rx_ant == 2) {
++ dev->tx_antenna = B43_ANTENNA1;
++ dev->rx_antenna = B43_ANTENNA1;
++ }
++ else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3) {
++ dev->tx_antenna = B43_ANTENNA_DEFAULT;
++ dev->rx_antenna = B43_ANTENNA_DEFAULT;
++ }
++ else {
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++
++static int b43_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
++{
++ struct b43_wl *wl = hw_to_b43_wl(hw);
++ struct b43_wldev *dev = wl->current_dev;
++
++ switch (dev->tx_antenna) {
++ case B43_ANTENNA0:
++ *tx_ant = 1; *rx_ant = 1; break;
++ case B43_ANTENNA1:
++ *tx_ant = 2; *rx_ant = 2; break;
++ case B43_ANTENNA_DEFAULT:
++ *tx_ant = 3; *rx_ant = 3; break;
++ }
++ return 0;
++}
++
+ static const struct ieee80211_ops b43_hw_ops = {
+ .tx = b43_op_tx,
+ .conf_tx = b43_op_conf_tx,
+@@ -4995,6 +5033,8 @@ static const struct ieee80211_ops b43_hw
+ .sw_scan_complete = b43_op_sw_scan_complete_notifier,
+ .get_survey = b43_op_get_survey,
+ .rfkill_poll = b43_rfkill_poll,
++ .set_antenna = b43_op_set_antenna,
++ .get_antenna = b43_op_get_antenna,
+ };
+
+ /* Hard-reset the chip. Do not call this directly.
+@@ -5241,6 +5281,8 @@ static int b43_one_core_attach(struct b4
+ if (!wldev)
+ goto out;
+
++ wldev->rx_antenna = B43_ANTENNA_DEFAULT;
++ wldev->tx_antenna = B43_ANTENNA_DEFAULT;
+ wldev->use_pio = b43_modparam_pio;
+ wldev->dev = dev;
+ wldev->wl = wl;
+@@ -5331,6 +5373,9 @@ static struct b43_wl *b43_wireless_init(
+
+ hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+
++ hw->wiphy->available_antennas_rx = 0x3;
++ hw->wiphy->available_antennas_tx = 0x3;
++
+ wl->hw_registred = false;
+ hw->max_rates = 2;
+ SET_IEEE80211_DEV(hw, dev->dev);
+--- a/drivers/net/wireless/b43/b43.h
++++ b/drivers/net/wireless/b43/b43.h
+@@ -808,6 +808,8 @@ struct b43_wldev {
+ bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */
+ bool use_pio; /* TRUE if next init should use PIO */
+ int gpiomask; /* GPIO LED mask as a module parameter */
++ int rx_antenna; /* Used RX antenna (B43_ANTENNAxxx) */
++ int tx_antenna; /* Used TX antenna (B43_ANTENNAxxx) */
+
+ /* PHY/Radio device. */
+ struct b43_phy phy;
diff --git a/package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch b/package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch
new file mode 100644
index 000000000..ce9ad7d5c
--- /dev/null
+++ b/package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch
@@ -0,0 +1,134 @@
+From 4f214b1ead0af7439921637645cb63f378516175 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sat, 21 Jan 2012 18:48:38 +0100
+Subject: [PATCH 33/34] b43: add workaround for b43 on pcie bus of bcm4716.
+
+bcm4716 (which includes 4717 & 4718), plus 4706 on PCIe can reorder
+transactions. As a fix, a read after write is performed on certain
+places in the code. Older chips and the newer 5357 family don't require
+this fix.
+This code is based on the brcmsmac driver.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ drivers/net/wireless/b43/b43.h | 26 ++++++++++++++++++++++++++
+ drivers/net/wireless/b43/bus.h | 10 ++++++++++
+ drivers/net/wireless/b43/phy_common.c | 6 ++++++
+ drivers/net/wireless/b43/phy_n.c | 10 +++++-----
+ 4 files changed, 47 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/wireless/b43/b43.h
++++ b/drivers/net/wireless/b43/b43.h
+@@ -1048,6 +1048,32 @@ static inline bool b43_using_pio_transfe
+ return dev->__using_pio_transfers;
+ }
+
++/*
++ * bcm4716 (which includes 4717 & 4718), plus 4706 on PCIe can reorder
++ * transactions. As a fix, a read after write is performed on certain places
++ * in the code. Older chips and the newer 5357 family don't require this fix.
++ */
++#ifdef CONFIG_BCM47XX_BCMA
++#include <asm/mach-bcm47xx/bcm47xx.h>
++static inline void b43_wflush16(struct b43_wldev *dev, u16 offset, u16 value)
++{
++ if (b43_bus_host_is_pci(dev->dev) &&
++ bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA &&
++ (bcm47xx_bus.bcma.bus.chipinfo.id == 0x4716 ||
++ bcm47xx_bus.bcma.bus.chipinfo.id == 0x5300)) {
++ b43_write16(dev, offset, value);
++ b43_read16(dev, offset);
++ } else {
++ b43_write16(dev, offset, value);
++ }
++}
++#else
++static inline void b43_wflush16(struct b43_wldev *dev, u16 offset, u16 value)
++{
++ b43_write16(dev, offset, value);
++}
++#endif
++
+ /* Message printing */
+ __printf(2, 3) void b43info(struct b43_wl *wl, const char *fmt, ...);
+ __printf(2, 3) void b43err(struct b43_wl *wl, const char *fmt, ...);
+--- a/drivers/net/wireless/b43/bus.h
++++ b/drivers/net/wireless/b43/bus.h
+@@ -60,6 +60,16 @@ static inline bool b43_bus_host_is_sdio(
+ return (dev->bus_type == B43_BUS_SSB &&
+ dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO);
+ }
++static inline bool b43_bus_host_is_pci(struct b43_bus_dev *dev)
++{
++ if (dev->bus_type == B43_BUS_SSB)
++ return (dev->sdev->bus->bustype == SSB_BUSTYPE_PCI);
++#ifdef CONFIG_B43_BCMA
++ if (dev->bus_type == B43_BUS_BCMA)
++ return (dev->bdev->bus->hosttype == BCMA_HOSTTYPE_PCI);
++#endif
++ return false;
++}
+
+ struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core);
+ struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev);
+--- a/drivers/net/wireless/b43/phy_common.c
++++ b/drivers/net/wireless/b43/phy_common.c
+@@ -266,6 +266,12 @@ void b43_phy_write(struct b43_wldev *dev
+ {
+ assert_mac_suspended(dev);
+ dev->phy.ops->phy_write(dev, reg, value);
++#ifdef CONFIG_BCM47XX
++ if (b43_bus_host_is_pci(dev->dev) && reg == 0x72) {
++ b43_read16(dev, B43_MMIO_PHY_VER);
++ return;
++ }
++#endif
+ if (++dev->phy.writes_counter == B43_MAX_WRITES_IN_ROW) {
+ b43_read16(dev, B43_MMIO_PHY_VER);
+ dev->phy.writes_counter = 0;
+--- a/drivers/net/wireless/b43/phy_n.c
++++ b/drivers/net/wireless/b43/phy_n.c
+@@ -5423,14 +5423,14 @@ static inline void check_phyreg(struct b
+ static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg)
+ {
+ check_phyreg(dev, reg);
+- b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
++ b43_wflush16(dev, B43_MMIO_PHY_CONTROL, reg);
+ return b43_read16(dev, B43_MMIO_PHY_DATA);
+ }
+
+ static void b43_nphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
+ {
+ check_phyreg(dev, reg);
+- b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
++ b43_wflush16(dev, B43_MMIO_PHY_CONTROL, reg);
+ b43_write16(dev, B43_MMIO_PHY_DATA, value);
+ }
+
+@@ -5438,7 +5438,7 @@ static void b43_nphy_op_maskset(struct b
+ u16 set)
+ {
+ check_phyreg(dev, reg);
+- b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
++ b43_wflush16(dev, B43_MMIO_PHY_CONTROL, reg);
+ b43_maskset16(dev, B43_MMIO_PHY_DATA, mask, set);
+ }
+
+@@ -5449,7 +5449,7 @@ static u16 b43_nphy_op_radio_read(struct
+ /* N-PHY needs 0x100 for read access */
+ reg |= 0x100;
+
+- b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
++ b43_wflush16(dev, B43_MMIO_RADIO_CONTROL, reg);
+ return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
+ }
+
+@@ -5458,7 +5458,7 @@ static void b43_nphy_op_radio_write(stru
+ /* Register 1 is a 32-bit register. */
+ B43_WARN_ON(reg == 1);
+
+- b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
++ b43_wflush16(dev, B43_MMIO_RADIO_CONTROL, reg);
+ b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
+ }
+
diff --git a/package/mac80211/patches/849-brcmsmac-add-device-found-on-some-SoCs-like-the-bcm4.patch b/package/mac80211/patches/849-brcmsmac-add-device-found-on-some-SoCs-like-the-bcm4.patch
new file mode 100644
index 000000000..f70a261f0
--- /dev/null
+++ b/package/mac80211/patches/849-brcmsmac-add-device-found-on-some-SoCs-like-the-bcm4.patch
@@ -0,0 +1,39 @@
+--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
++++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+@@ -94,6 +94,7 @@ MODULE_FIRMWARE("brcm/bcm43xx_hdr-0.fw")
+
+ /* recognized BCMA Core IDs */
+ static struct bcma_device_id brcms_coreid_table[] = {
++// BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 17, BCMA_ANY_CLASS),
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 23, BCMA_ANY_CLASS),
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 24, BCMA_ANY_CLASS),
+ BCMA_CORETABLE_END
+--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
+@@ -734,7 +734,7 @@ static void brcms_c_ucode_bsinit(struct
+ brcms_c_write_mhf(wlc_hw, wlc_hw->band->mhfs);
+
+ /* do band-specific ucode IHR, SHM, and SCR inits */
+- if (D11REV_IS(wlc_hw->corerev, 23)) {
++ if (D11REV_IS(wlc_hw->corerev, 17) || D11REV_IS(wlc_hw->corerev, 23)) {
+ if (BRCMS_ISNPHY(wlc_hw->band))
+ brcms_c_write_inits(wlc_hw, ucode->d11n0bsinitvals16);
+ else
+@@ -2259,7 +2259,7 @@ static void brcms_ucode_download(struct
+ if (wlc_hw->ucode_loaded)
+ return;
+
+- if (D11REV_IS(wlc_hw->corerev, 23)) {
++ if (D11REV_IS(wlc_hw->corerev, 17) || D11REV_IS(wlc_hw->corerev, 23)) {
+ if (BRCMS_ISNPHY(wlc_hw->band)) {
+ brcms_ucode_write(wlc_hw, ucode->bcm43xx_16_mimo,
+ ucode->bcm43xx_16_mimosz);
+@@ -3221,7 +3221,7 @@ static void brcms_b_coreinit(struct brcm
+
+ sflags = bcma_aread32(core, BCMA_IOST);
+
+- if (D11REV_IS(wlc_hw->corerev, 23)) {
++ if (D11REV_IS(wlc_hw->corerev, 17) || D11REV_IS(wlc_hw->corerev, 23)) {
+ if (BRCMS_ISNPHY(wlc_hw->band))
+ brcms_c_write_inits(wlc_hw, ucode->d11n0initvals16);
+ else
diff --git a/package/mac80211/patches/850-brcmsmac-add-support-for-BCM43224.patch b/package/mac80211/patches/850-brcmsmac-add-support-for-BCM43224.patch
new file mode 100644
index 000000000..b135c7d3f
--- /dev/null
+++ b/package/mac80211/patches/850-brcmsmac-add-support-for-BCM43224.patch
@@ -0,0 +1,29 @@
+--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
+@@ -4135,6 +4135,7 @@ void brcms_c_wme_setparams(struct brcms_
+ M_EDCF_QINFO +
+ wme_ac2fifo[aci] * M_EDCF_QLEN + i,
+ *shm_entry++);
++ printk("dummy\n");
+ }
+
+ if (suspend) {
+@@ -4537,7 +4538,8 @@ static int brcms_b_attach(struct brcms_c
+
+ /* check device id(srom, nvram etc.) to set bands */
+ if (wlc_hw->deviceid == BCM43224_D11N_ID ||
+- wlc_hw->deviceid == BCM43224_D11N_ID_VEN1)
++ wlc_hw->deviceid == BCM43224_D11N_ID_VEN1 ||
++ wlc_hw->deviceid == BCM43224_CHIP_ID)
+ /* Dualband boards */
+ wlc_hw->_nbands = 2;
+ else
+@@ -5797,7 +5799,7 @@ static bool brcms_c_chipmatch_pci(struct
+ return false;
+ }
+
+- if (device == BCM43224_D11N_ID_VEN1)
++ if (device == BCM43224_D11N_ID_VEN1 || device == BCM43224_CHIP_ID)
+ return true;
+ if ((device == BCM43224_D11N_ID) || (device == BCM43225_D11N2G_ID))
+ return true;
diff --git a/package/mac80211/patches/851-brcmsmac-start-adding-support-for-core-rev-28.patch b/package/mac80211/patches/851-brcmsmac-start-adding-support-for-core-rev-28.patch
new file mode 100644
index 000000000..198af613c
--- /dev/null
+++ b/package/mac80211/patches/851-brcmsmac-start-adding-support-for-core-rev-28.patch
@@ -0,0 +1,75 @@
+--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
++++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+@@ -97,6 +97,7 @@ static struct bcma_device_id brcms_corei
+ // BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 17, BCMA_ANY_CLASS),
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 23, BCMA_ANY_CLASS),
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 24, BCMA_ANY_CLASS),
++// BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 28, BCMA_ANY_CLASS),
+ BCMA_CORETABLE_END
+ };
+ MODULE_DEVICE_TABLE(bcma, brcms_coreid_table);
+--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
+@@ -734,7 +734,7 @@ static void brcms_c_ucode_bsinit(struct
+ brcms_c_write_mhf(wlc_hw, wlc_hw->band->mhfs);
+
+ /* do band-specific ucode IHR, SHM, and SCR inits */
+- if (D11REV_IS(wlc_hw->corerev, 17) || D11REV_IS(wlc_hw->corerev, 23)) {
++ if (D11REV_IS(wlc_hw->corerev, 17) || D11REV_IS(wlc_hw->corerev, 23) || D11REV_IS(wlc_hw->corerev, 28)) {
+ if (BRCMS_ISNPHY(wlc_hw->band))
+ brcms_c_write_inits(wlc_hw, ucode->d11n0bsinitvals16);
+ else
+@@ -2259,7 +2259,7 @@ static void brcms_ucode_download(struct
+ if (wlc_hw->ucode_loaded)
+ return;
+
+- if (D11REV_IS(wlc_hw->corerev, 17) || D11REV_IS(wlc_hw->corerev, 23)) {
++ if (D11REV_IS(wlc_hw->corerev, 17) || D11REV_IS(wlc_hw->corerev, 23) || D11REV_IS(wlc_hw->corerev, 28)) {
+ if (BRCMS_ISNPHY(wlc_hw->band)) {
+ brcms_ucode_write(wlc_hw, ucode->bcm43xx_16_mimo,
+ ucode->bcm43xx_16_mimosz);
+@@ -3221,7 +3221,7 @@ static void brcms_b_coreinit(struct brcm
+
+ sflags = bcma_aread32(core, BCMA_IOST);
+
+- if (D11REV_IS(wlc_hw->corerev, 17) || D11REV_IS(wlc_hw->corerev, 23)) {
++ if (D11REV_IS(wlc_hw->corerev, 17) || D11REV_IS(wlc_hw->corerev, 23) || D11REV_IS(wlc_hw->corerev, 28)) {
+ if (BRCMS_ISNPHY(wlc_hw->band))
+ brcms_c_write_inits(wlc_hw, ucode->d11n0initvals16);
+ else
+@@ -5818,6 +5818,8 @@ static bool brcms_c_chipmatch_soc(struct
+
+ if (chipinfo->id == BCMA_CHIP_ID_BCM4716)
+ return true;
++ if (chipinfo->id == BCMA_CHIP_ID_BCM5357)
++ return true;
+
+ pr_err("unknown chip id %04x\n", chipinfo->id);
+ return false;
+--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h
++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h
+@@ -65,7 +65,7 @@
+ #define SW_TIMER_MAC_STAT_UPD 30 /* periodic MAC stats update */
+
+ /* max # supported core revisions (0 .. MAXCOREREV - 1) */
+-#define MAXCOREREV 28
++#define MAXCOREREV 29
+
+ /* Double check that unsupported cores are not enabled */
+ #if CONF_MSK(D11CONF, 0x4f) || CONF_GE(D11CONF, MAXCOREREV)
+--- a/drivers/net/wireless/brcm80211/brcmsmac/types.h
++++ b/drivers/net/wireless/brcm80211/brcmsmac/types.h
+@@ -93,11 +93,11 @@
+ #define BOARD_GPIO_13 0x2000
+
+ /* **** Core type/rev defaults **** */
+-#define D11CONF 0x0fffffb0 /* Supported D11 revs: 4, 5, 7-27
++#define D11CONF 0x1fffffb0 /* Supported D11 revs: 4, 5, 7-27
+ * also need to update wlc.h MAXCOREREV
+ */
+
+-#define NCONF 0x000001ff /* Supported nphy revs:
++#define NCONF 0x000002ff /* Supported nphy revs:
+ * 0 4321a0
+ * 1 4321a1
+ * 2 4321b0/b1/c0/c1
diff --git a/package/maccalc/Makefile b/package/maccalc/Makefile
new file mode 100644
index 000000000..09cdfc8c2
--- /dev/null
+++ b/package/maccalc/Makefile
@@ -0,0 +1,47 @@
+#
+# Copyright (C) 2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=maccalc
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/maccalc
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=MAC address calculation
+endef
+
+define Package/maccalc/description
+ This package contains a MAC address manipulation utility.
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CC)" \
+ CFLAGS="$(TARGET_CFLAGS) -Wall" \
+ LDFLAGS="$(TARGET_LDFLAGS)"
+endef
+
+define Package/maccalc/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/maccalc $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,maccalc))
diff --git a/package/maccalc/src/Makefile b/package/maccalc/src/Makefile
new file mode 100644
index 000000000..486badb25
--- /dev/null
+++ b/package/maccalc/src/Makefile
@@ -0,0 +1,14 @@
+CC = gcc
+CFLAGS = -Wall
+OBJS = main.o
+
+all: maccalc
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+maccalc: $(OBJS)
+ $(CC) -o $@ $(OBJS)
+
+clean:
+ rm -f maccalc *.o
diff --git a/package/maccalc/src/main.c b/package/maccalc/src/main.c
new file mode 100644
index 000000000..dcb5f55c5
--- /dev/null
+++ b/package/maccalc/src/main.c
@@ -0,0 +1,256 @@
+/*
+ * MAC address manupulation utility
+ *
+ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * 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 <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#define MAC_ADDRESS_LEN 6
+
+#define ERR_INVALID 1
+#define ERR_IO 2
+
+static void usage(void);
+
+char *maccalc_name;
+
+static int parse_mac(const char *mac_str, unsigned char *buf)
+{
+ int t;
+
+ t = sscanf(mac_str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+ &buf[0], &buf[1], &buf[2], &buf[3], &buf[4], &buf[5]);
+
+ if (t != MAC_ADDRESS_LEN)
+ return ERR_INVALID;
+
+ return 0;
+}
+
+static void print_mac(unsigned char *buf)
+{
+ printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
+ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
+}
+
+static int maccalc_do_add(int argc, const char *argv[])
+{
+ unsigned char mac[MAC_ADDRESS_LEN];
+ uint32_t t;
+ int err;
+ int i;
+
+ if (argc != 2) {
+ usage();
+ return ERR_INVALID;
+ }
+
+ err = parse_mac(argv[0], mac);
+ if (err)
+ return err;
+
+ i = atoi(argv[1]);
+
+ t = (mac[3] << 16) | (mac[4] << 8) | mac[5];
+ t += i;
+ mac[3] = (t >> 16) & 0xff;
+ mac[4] = (t >> 8) & 0xff;
+ mac[5] = t & 0xff;
+
+ print_mac(mac);
+ return 0;
+}
+
+static int maccalc_do_logical(int argc, const char *argv[],
+ unsigned char (*op)(unsigned char n1,
+ unsigned char n2))
+{
+ unsigned char mac1[MAC_ADDRESS_LEN];
+ unsigned char mac2[MAC_ADDRESS_LEN];
+ int err;
+ int i;
+
+ if (argc != 2) {
+ usage();
+ return ERR_INVALID;
+ }
+
+ err = parse_mac(argv[0], mac1);
+ if (err)
+ return err;
+
+ err = parse_mac(argv[1], mac2);
+ if (err)
+ return err;
+
+ for (i = 0; i < MAC_ADDRESS_LEN; i++)
+ mac1[i] = op(mac1[i],mac2[i]);
+
+ print_mac(mac1);
+ return 0;
+}
+
+static int maccalc_do_mac2bin(int argc, const char *argv[])
+{
+ unsigned char mac[MAC_ADDRESS_LEN];
+ ssize_t c;
+ int err;
+
+ if (argc != 1) {
+ usage();
+ return ERR_INVALID;
+ }
+
+ err = parse_mac(argv[0], mac);
+ if (err)
+ return err;
+
+ c = write(STDOUT_FILENO, mac, sizeof(mac));
+ if (c != sizeof(mac)) {
+ fprintf(stderr, "failed to write to stdout\n");
+ return ERR_IO;
+ }
+
+ return 0;
+}
+
+static ssize_t read_safe(int fd, void *buf, size_t count)
+{
+ ssize_t total = 0;
+ ssize_t r;
+
+ while(count > 0) {
+ r = read(fd, buf, count);
+ if (r == 0)
+ /* EOF */
+ break;
+ if (r < 0) {
+ if (errno == EINTR)
+ /* interrupted by a signal, restart */
+ continue;
+ /* error */
+ total = -1;
+ break;
+ }
+
+ /* ok */
+ total += r;
+ count -= r;
+ buf += r;
+ }
+
+ return total;
+}
+
+static int maccalc_do_bin2mac(int argc, const char *argv[])
+{
+ unsigned char mac[MAC_ADDRESS_LEN];
+ ssize_t c;
+
+ if (argc != 0) {
+ usage();
+ return ERR_INVALID;
+ }
+
+ c = read_safe(STDIN_FILENO, mac, sizeof(mac));
+ if (c != sizeof(mac)) {
+ fprintf(stderr, "failed to read from stdin\n");
+ return ERR_IO;
+ }
+
+ print_mac(mac);
+ return 0;
+}
+
+static unsigned char op_or(unsigned char n1, unsigned char n2)
+{
+ return n1 | n2;
+}
+
+static int maccalc_do_or(int argc, const char *argv[])
+{
+ return maccalc_do_logical(argc, argv, op_or);
+}
+
+static unsigned char op_and(unsigned char n1, unsigned char n2)
+{
+ return n1 & n2;
+}
+
+static int maccalc_do_and(int argc, const char *argv[])
+{
+ return maccalc_do_logical(argc, argv, op_and);
+}
+
+static unsigned char op_xor(unsigned char n1, unsigned char n2)
+{
+ return n1 ^ n2;
+}
+
+static int maccalc_do_xor(int argc, const char *argv[])
+{
+ return maccalc_do_logical(argc, argv, op_xor);
+}
+
+static void usage(void)
+{
+ fprintf(stderr,
+ "Usage: %s <command>\n"
+ "valid commands:\n"
+ " add <mac> <number>\n"
+ " and|or|xor <mac1> <mac2>\n"
+ " mac2bin <mac>\n"
+ " bin2mac\n",
+ maccalc_name);
+}
+
+int main(int argc, const char *argv[])
+{
+ int (*op)(int argc, const char *argv[]);
+ int ret;
+
+ maccalc_name = (char *) argv[0];
+
+ if (argc < 2) {
+ usage();
+ return EXIT_FAILURE;
+ }
+
+ if (strcmp(argv[1], "add") == 0) {
+ op = maccalc_do_add;
+ } else if (strcmp(argv[1], "and") == 0) {
+ op = maccalc_do_and;
+ } else if (strcmp(argv[1], "or") == 0) {
+ op = maccalc_do_or;
+ } else if (strcmp(argv[1], "xor") == 0) {
+ op = maccalc_do_xor;
+ } else if (strcmp(argv[1], "mac2bin") == 0) {
+ op = maccalc_do_mac2bin;
+ } else if (strcmp(argv[1], "bin2mac") == 0) {
+ op = maccalc_do_bin2mac;
+ } else {
+ fprintf(stderr, "unknown command '%s'\n", argv[1]);
+ usage();
+ return EXIT_FAILURE;
+ }
+
+ argc -= 2;
+ argv += 2;
+
+ ret = op(argc, argv);
+ if (ret)
+ return EXIT_FAILURE;
+
+ return EXIT_SUCCESS;
+}
diff --git a/package/madwifi/Config.in b/package/madwifi/Config.in
new file mode 100644
index 000000000..7b72eb854
--- /dev/null
+++ b/package/madwifi/Config.in
@@ -0,0 +1,55 @@
+menu "Configuration"
+ depends on PACKAGE_kmod-madwifi
+
+config MADWIFI_DEBUG
+ bool "Enable compilation of debugging features"
+ depends on DEVEL
+ default n
+
+config MADWIFI_COMPRESSION
+ bool "Enable Atheros Super A/G Compression"
+ depends !TARGET_ar71xx
+ default n
+ help
+ Enables Atheros Super A/G Hardware Compression Engine.
+
+config MADWIFI_SINGLE_MODULE
+ bool "Combine driver and net80211 into a single module"
+ default y
+ help
+ This option combines all driver and stack related code (except for HAL)
+ into a single module, thus saving space and removing unnecessary kernel
+ exports
+
+choice
+ prompt "Rate control algorithm selection"
+ 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_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
+
+endmenu
diff --git a/package/madwifi/Makefile b/package/madwifi/Makefile
new file mode 100644
index 000000000..f915f56f9
--- /dev/null
+++ b/package/madwifi/Makefile
@@ -0,0 +1,266 @@
+#
+# Copyright (C) 2006-2009 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=madwifi
+
+PKG_REV:=3314
+PKG_VERSION:=r$(PKG_REV)
+PKG_RELEASE:=6
+
+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://madwifi-project.org/svn/madwifi/$(if $(PKG_BRANCH),branches/$(PKG_BRANCH),trunk)
+PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.gz
+PKG_MIRROR_MD5SUM:=086b026d1c1561be8a949b79b0931404
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(if $(PKG_BRANCH),$(PKG_BRANCH),madwifi-trunk)-$(PKG_VERSION)
+
+HAL_VERSION:=20090508
+HAL_FILE:=ath_hal-$(HAL_VERSION).tgz
+HAL_MD5SUM:=4ab7ae8bdb96c0be388c98bf8f92d5ca
+
+PKG_BUILD_DEPENDS:=wprobe
+
+include $(INCLUDE_DIR)/package.mk
+
+ifdef CONFIG_MADWIFI_COMPRESSION
+ COMPRESSION:=1
+else
+ COMPRESSION:=0
+endif
+
+define Download/hal
+ FILE:=$(HAL_FILE)
+ URL:=http://mirror2.openwrt.org/sources
+ MD5SUM:=$(HAL_MD5SUM)
+endef
+$(eval $(call Download,hal))
+
+
+ifneq ($(CONFIG_TARGET_atheros),)
+ BUS:=AHB
+else
+ ifneq ($(CONFIG_PCI_SUPPORT),)
+ BUS:=PCI
+ endif
+endif
+
+ifneq ($(CONFIG_CPU_MIPS32_R2),)
+ ifeq ($(ARCH),mips)
+ HAL_TARGET:=mips32r2-be-elf
+ endif
+ ifeq ($(ARCH),mipsel)
+ HAL_TARGET:=mips32r2-le-elf
+ endif
+else
+ ifeq ($(ARCH),mips)
+ HAL_TARGET:=mips32-be-elf
+ endif
+ ifeq ($(ARCH),mipsel)
+ HAL_TARGET:=mips32-le-elf
+ endif
+endif
+ifeq ($(ARCH),i386)
+ HAL_TARGET:=i386-elf
+endif
+ifeq ($(ARCH),i686)
+ HAL_TARGET:=i386-elf
+endif
+ifeq ($(ARCH),armeb)
+ HAL_TARGET:=xscale-be-elfgnueabi
+endif
+ifeq ($(ARCH),arm)
+ HAL_TARGET:=xscale-le-elfgnueabi
+ ifeq ($(BOARD),cns21xx)
+ HAL_TARGET:=armv4-le-elfgnueabi
+ endif
+ ifeq ($(BOARD),cns3xxx)
+ HAL_TARGET:=arm11-le-elfgnueabi
+ endif
+ ifeq ($(BOARD),gemini)
+ HAL_TARGET:=armv4-le-elfgnueabi
+ endif
+endif
+ifeq ($(ARCH),powerpc)
+ HAL_TARGET:=powerpc-be-elf
+endif
+ifneq ($(CONFIG_TARGET_atheros),)
+ HAL_TARGET:=wisoc
+endif
+
+ifdef CONFIG_MADWIFI_RCA_MINSTREL
+ RATE_CONTROL:=minstrel
+endif
+
+ifdef CONFIG_MADWIFI_RCA_ONOE
+ RATE_CONTROL:=onoe
+endif
+
+ifdef CONFIG_MADWIFI_RCA_AMRR
+ RATE_CONTROL:=amrr
+endif
+
+ifdef CONFIG_MADWIFI_RCA_SAMPLERATE
+ RATE_CONTROL:=sample
+endif
+
+ifneq ($(CONFIG_MADWIFI_SINGLE_MODULE),)
+MADWIFI_FILES:= $(PKG_BUILD_DIR)/ath_hal/ath_hal.ko
+else
+MADWIFI_FILES:= \
+ $(PKG_BUILD_DIR)/net80211/wlan.ko \
+ $(PKG_BUILD_DIR)/net80211/wlan_scan_ap.ko \
+ $(PKG_BUILD_DIR)/net80211/wlan_scan_sta.ko \
+ $(PKG_BUILD_DIR)/ath_hal/ath_hal.ko \
+ $(PKG_BUILD_DIR)/ath_rate/$(RATE_CONTROL)/ath_rate_$(RATE_CONTROL).ko \
+ $(PKG_BUILD_DIR)/net80211/wlan_acl.ko \
+ $(PKG_BUILD_DIR)/net80211/wlan_ccmp.ko \
+ $(PKG_BUILD_DIR)/net80211/wlan_tkip.ko \
+ $(PKG_BUILD_DIR)/net80211/wlan_wep.ko \
+ $(PKG_BUILD_DIR)/net80211/wlan_xauth.ko
+endif
+
+ifneq ($(CONFIG_MADWIFI_SINGLE_MODULE),)
+ MADWIFI_AUTOLOAD:= ath_hal
+else
+ MADWIFI_AUTOLOAD:= \
+ wlan \
+ wlan_scan_ap \
+ wlan_scan_sta \
+ ath_hal \
+ ath_rate_$(RATE_CONTROL) \
+ wlan_acl \
+ wlan_ccmp \
+ wlan_tkip \
+ wlan_wep \
+ wlan_xauth
+endif
+
+ifeq ($(findstring AHB,$(BUS)),AHB)
+ MADWIFI_FILES+= $(PKG_BUILD_DIR)/ath/ath_ahb.ko
+ MADWIFI_AUTOLOAD+= ath_ahb
+endif
+ifeq ($(findstring PCI,$(BUS)),PCI)
+ MADWIFI_FILES+= $(PKG_BUILD_DIR)/ath/ath_pci.ko
+ MADWIFI_AUTOLOAD+= ath_pci
+endif
+
+MADWIFI_APPLETS:=80211stats athchans athkey athstats wlanconfig ath_info madwifi_multi
+ifdef CONFIG_MADWIFI_DEBUG
+ MADWIFI_APPLETS += athdebug 80211debug
+endif
+
+define KernelPackage/madwifi
+ SUBMENU:=Wireless Drivers
+ TITLE:=Driver for Atheros wireless chipsets
+ URL:=http://madwifi-project.org/
+ DEPENDS:=+wireless-tools @PCI_SUPPORT @(!(TARGET_avr32||TARGET_cobalt||TARGET_ep93xx||TARGET_etrax||TARGET_octeon||TARGET_pxcab||TARGET_sibyte)||BROKEN) +@DRIVER_WEXT_SUPPORT
+ FILES:=$(MADWIFI_FILES)
+ AUTOLOAD:=$(call AutoLoad,50,$(MADWIFI_AUTOLOAD))
+ MENU:=1
+endef
+
+define KernelPackage/madwifi/description
+ This package contains a driver for Atheros 802.11a/b/g chipsets.
+endef
+
+define KernelPackage/madwifi/config
+ source "$(SOURCE)/Config.in"
+endef
+
+MADWIFI_INC = \
+ -I$(PKG_BUILD_DIR) \
+ -I$(PKG_BUILD_DIR)/include \
+ -I$(PKG_BUILD_DIR)/hal \
+ -I$(PKG_BUILD_DIR)/ath \
+ -I$(PKG_BUILD_DIR)/ath_hal \
+ -I$(PKG_BUILD_DIR)/net80211 \
+ -I$(STAGING_DIR)/usr/include/wprobe \
+ -include $(PKG_BUILD_DIR)/include/compat.h
+
+MAKE_ARGS:= \
+ PATH="$(TARGET_PATH)" \
+ ARCH="$(LINUX_KARCH)" \
+ ARCH-y="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ TARGET="$(HAL_TARGET)" \
+ TOOLPREFIX="$(KERNEL_CROSS)" \
+ TOOLPATH="$(KERNEL_CROSS)" \
+ KERNELPATH="$(LINUX_DIR)" \
+ LDOPTS="--no-warn-mismatch " \
+ ATH_RATE="$(RATE_CONTROL)" \
+ ATH_CAP_SUPERG_COMP="$(COMPRESSION)" \
+ DO_MULTI=1 \
+ SINGLE_MODULE=$(if $(CONFIG_MADWIFI_SINGLE_MODULE),1) \
+ INCS="$(MADWIFI_INC)" \
+ $(if $(CONFIG_MADWIFI_DEBUG),,DEBUG=) WARNINGS="-Wno-unused"
+
+MAKE_VARS:= \
+ COPTS="-DATH_REVERSE_ENGINEERING=1" \
+
+define Build/Prepare/HAL
+ rm -rf $(PKG_BUILD_DIR)/tmp
+ mkdir -p $(PKG_BUILD_DIR)/tmp
+ tar xvzf $(DL_DIR)/$(HAL_FILE) -C $(PKG_BUILD_DIR)/tmp
+ $(CP) $(PKG_BUILD_DIR)/tmp/ath_hal*/* $(PKG_BUILD_DIR)/hal/
+ rm -rf $(PKG_BUILD_DIR)/tmp
+endef
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ $(call Build/Prepare/HAL)
+ # patch cflags
+ $(SED) 's, -E[LB],,' \
+ -e 's, -mips2,,' \
+ -e 's, -mapcs-32,,' \
+ -e 's, -mlong-calls,,' \
+ $(PKG_BUILD_DIR)/hal/public/*.inc
+ $(SED) 's,march=armv4,march=armv5te,' \
+ $(PKG_BUILD_DIR)/hal/public/xscale*.inc
+endef
+
+ifeq ($(findstring AHB,$(BUS)),AHB)
+ define Build/Compile/ahb
+ $(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
+ $(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
+
+define Build/Configure
+ $(SED) 's,-E[LB] ,,g' $(PKG_BUILD_DIR)/hal/public/*.inc
+endef
+
+define Build/Compile
+ $(call Build/Compile/ahb)
+ $(call Build/Compile/pci)
+endef
+
+define Build/InstallDev
+ 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)/usr/sbin
+ $(CP) ./files/* $(1)/
+ $(CP) $(foreach applet,$(MADWIFI_APPLETS),$(PKG_BUILD_DIR)/tools/$(applet)) $(1)/usr/sbin/
+endef
+
+$(eval $(call KernelPackage,madwifi))
diff --git a/package/madwifi/files/etc/hotplug.d/net/10-madwifi b/package/madwifi/files/etc/hotplug.d/net/10-madwifi
new file mode 100644
index 000000000..f5afce3f2
--- /dev/null
+++ b/package/madwifi/files/etc/hotplug.d/net/10-madwifi
@@ -0,0 +1,12 @@
+if [ "$ACTION" = "add" -o "$ACTION" = "register" ]; then
+ case "$INTERFACE" in
+ ath*.sta*)
+ local BASEIF="${INTERFACE%%\.*}"
+
+ include /lib/network
+ scan_interfaces
+ local CONFIG="$(find_config "$BASEIF")"
+ [ -n "$CONFIG" ] && setup_interface "$INTERFACE" "$CONFIG"
+ ;;
+ esac
+fi
diff --git a/package/madwifi/files/lib/wifi/madwifi.sh b/package/madwifi/files/lib/wifi/madwifi.sh
new file mode 100755
index 000000000..2e3732551
--- /dev/null
+++ b/package/madwifi/files/lib/wifi/madwifi.sh
@@ -0,0 +1,498 @@
+#!/bin/sh
+append DRIVERS "atheros"
+
+find_atheros_phy() {
+ local device="$1"
+
+ local macaddr="$(config_get "$device" macaddr | tr 'A-Z' 'a-z')"
+ config_get phy "$device" phy
+ [ -z "$phy" -a -n "$macaddr" ] && {
+ cd /proc/sys/dev
+ for phy in $(ls -d wifi* 2>&-); do
+ [ "$macaddr" = "$(cat /sys/class/net/${phy}/address)" ] || continue
+ config_set "$device" phy "$phy"
+ break
+ done
+ config_get phy "$device" phy
+ }
+ [ -n "$phy" -a -d "/proc/sys/dev/$phy" ] || {
+ echo "phy for wifi device $1 not found"
+ return 1
+ }
+ [ -z "$macaddr" ] && {
+ config_set "$device" macaddr "$(cat /sys/class/net/${phy}/address)"
+ }
+ return 0
+}
+
+scan_atheros() {
+ local device="$1"
+ local wds
+ local adhoc ahdemo sta ap monitor disabled
+
+ [ ${device%[0-9]} = "wifi" ] && config_set "$device" phy "$device"
+
+ local ifidx=0
+
+ config_get vifs "$device" vifs
+ for vif in $vifs; do
+ config_get_bool disabled "$vif" disabled 0
+ [ $disabled = 0 ] || continue
+
+ local vifname
+ [ $ifidx -gt 0 ] && vifname="ath${device#radio}-$ifidx" || vifname="ath${device#radio}"
+
+ config_get ifname "$vif" ifname
+ config_set "$vif" ifname "${ifname:-$vifname}"
+
+ config_get mode "$vif" mode
+ case "$mode" in
+ adhoc|ahdemo|sta|ap|monitor)
+ append $mode "$vif"
+ ;;
+ wds)
+ config_get ssid "$vif" ssid
+ [ -z "$ssid" ] && continue
+
+ config_set "$vif" wds 1
+ config_set "$vif" mode sta
+ mode="sta"
+ addr="$ssid"
+ ${addr:+append $mode "$vif"}
+ ;;
+ *) echo "$device($vif): Invalid mode, ignored."; continue;;
+ esac
+
+ ifidx=$(($ifidx + 1))
+ done
+
+ case "${adhoc:+1}:${sta:+1}:${ap:+1}" in
+ # valid mode combinations
+ 1::) wds="";;
+ 1::1);;
+ :1:1)config_set "$device" nosbeacon 1;; # AP+STA, can't use beacon timers for STA
+ :1:);;
+ ::1);;
+ ::);;
+ *) echo "$device: Invalid mode combination in config"; return 1;;
+ esac
+
+ config_set "$device" vifs "${sta:+$sta }${ap:+$ap }${adhoc:+$adhoc }${ahdemo:+$ahdemo }${wds:+$wds }${monitor:+$monitor}"
+}
+
+
+disable_atheros() (
+ local device="$1"
+
+ find_atheros_phy "$device" || return 0
+ config_get phy "$device" phy
+
+ set_wifi_down "$device"
+
+ include /lib/network
+ cd /proc/sys/net
+ for dev in *; do
+ grep "$phy" "$dev/%parent" >/dev/null 2>/dev/null && {
+ [ -f "/var/run/wifi-${dev}.pid" ] &&
+ kill "$(cat "/var/run/wifi-${dev}.pid")"
+ ifconfig "$dev" down
+ unbridge "$dev"
+ wlanconfig "$dev" destroy
+ }
+ done
+ return 0
+)
+
+enable_atheros() {
+ local device="$1"
+
+ find_atheros_phy "$device" || return 0
+ config_get phy "$device" phy
+
+ config_get regdomain "$device" regdomain
+ [ -n "$regdomain" ] && echo "$regdomain" > /proc/sys/dev/$phy/regdomain
+
+ config_get country "$device" country
+ case "$country" in
+ [A-Za-z]*) country=`grep -i "$country" /lib/wifi/madwifi_countrycodes.txt |cut -d " " -f 2`;;
+ [0-9]*) ;;
+ *) country="" ;;
+ esac
+ [ -n "$country" ] && echo "$country" > /proc/sys/dev/$phy/countrycode
+
+ config_get_bool outdoor "$device" outdoor "0"
+ echo "$outdoor" > /proc/sys/dev/$phy/outdoor
+
+ config_get channel "$device" channel
+ config_get vifs "$device" vifs
+ config_get txpower "$device" txpower
+
+ [ auto = "$channel" ] && channel=0
+
+ config_get_bool antdiv "$device" diversity
+ config_get antrx "$device" rxantenna
+ config_get anttx "$device" txantenna
+ config_get_bool softled "$device" softled
+ config_get antenna "$device" antenna
+
+ devname="$(cat /proc/sys/dev/$phy/dev_name)"
+ local antgpio=
+ local invert=
+ case "$devname" in
+ NanoStation2) antgpio=7; invert=1;;
+ NanoStation5) antgpio=1; invert=1;;
+ "NanoStation Loco2") antgpio=2;;
+ "NanoStation Loco5")
+ case "$antenna" in
+ horizontal) antdiv=0; anttx=1; antrx=1;;
+ vertical) antdiv=0; anttx=2; antrx=2;;
+ *) antdiv=1; anttx=0; antrx=0;;
+ esac
+ ;;
+ esac
+ if [ -n "$invert" ]; then
+ _set="clear"
+ _clear="set"
+ else
+ _set="set"
+ _clear="clear"
+ fi
+ if [ -n "$antgpio" ]; then
+ softled=0
+ case "$devname" in
+ "NanoStation Loco2")
+ antdiv=0
+ antrx=1
+ anttx=1
+ case "$antenna" in
+ horizontal) gpioval=0;;
+ *) gpioval=1;;
+ esac
+ ;;
+ *)
+ case "$antenna" in
+ external) antdiv=0; antrx=1; anttx=1; gpioval=1;;
+ horizontal) antdiv=0; antrx=1; anttx=1; gpioval=0;;
+ vertical) antdiv=0; antrx=2; anttx=2; gpioval=0;;
+ auto) antdiv=1; antrx=0; anttx=0; gpioval=0;;
+ esac
+ ;;
+ esac
+
+ [ -x "$(which gpioctl 2>/dev/null)" ] || antenna=
+ gpioctl "dirout" "$antgpio" >/dev/null 2>&1
+ case "$gpioval" in
+ 0)
+ gpioctl "$_clear" "$antgpio" >/dev/null 2>&1
+ ;;
+ 1)
+ gpioctl "$_set" "$antgpio" >/dev/null 2>&1
+ ;;
+ esac
+ fi
+
+ [ -n "$antdiv" ] && sysctl -w dev."$phy".diversity="$antdiv" >&-
+ [ -n "$antrx" ] && sysctl -w dev."$phy".rxantenna="$antrx" >&-
+ [ -n "$anttx" ] && sysctl -w dev."$phy".txantenna="$anttx" >&-
+ [ -n "$softled" ] && sysctl -w dev."$phy".softled="$softled" >&-
+
+ config_get distance "$device" distance
+ [ -n "$distance" ] && sysctl -w dev."$phy".distance="$distance" >&-
+
+ for vif in $vifs; do
+ local start_hostapd= vif_txpower= nosbeacon=
+ config_get ifname "$vif" ifname
+ config_get enc "$vif" encryption
+ config_get eap_type "$vif" eap_type
+ config_get mode "$vif" mode
+
+ case "$mode" in
+ sta) config_get_bool nosbeacon "$device" nosbeacon;;
+ adhoc) config_get_bool nosbeacon "$vif" sw_merge 1;;
+ esac
+
+ [ "$nosbeacon" = 1 ] || nosbeacon=""
+ ifname=$(wlanconfig "$ifname" create nounit wlandev "$phy" wlanmode "$mode" ${nosbeacon:+nosbeacon})
+ [ $? -ne 0 ] && {
+ echo "enable_atheros($device): Failed to set up $mode vif $ifname" >&2
+ continue
+ }
+ config_set "$vif" ifname "$ifname"
+
+ config_get hwmode "$device" hwmode
+ [ -z "$hwmode" ] && config_get hwmode "$device" mode
+
+ pureg=0
+ case "$hwmode" in
+ *b) hwmode=11b;;
+ *bg) hwmode=11g;;
+ *g) hwmode=11g; pureg=1;;
+ *gdt) hwmode=11gdt;;
+ *a) hwmode=11a;;
+ *adt) hwmode=11adt;;
+ *ast) hwmode=11ast;;
+ *fh) hwmode=fh;;
+ *) hwmode=auto;;
+ esac
+ iwpriv "$ifname" mode "$hwmode"
+ iwpriv "$ifname" pureg "$pureg"
+
+ iwconfig "$ifname" channel "$channel" >/dev/null 2>/dev/null
+
+ config_get_bool hidden "$vif" hidden 0
+ iwpriv "$ifname" hide_ssid "$hidden"
+
+ config_get ff "$vif" ff
+ if [ -n "$ff" ]; then
+ iwpriv "$ifname" ff "$ff"
+ fi
+
+ config_get wds "$vif" wds
+ case "$wds" in
+ 1|on|enabled) wds=1;;
+ *) wds=0;;
+ esac
+ iwpriv "$ifname" wds "$wds" >/dev/null 2>&1
+
+ [ "$mode" = ap -a "$wds" = 1 ] && {
+ config_get_bool wdssep "$vif" wdssep 1
+ [ -n "$wdssep" ] && iwpriv "$ifname" wdssep "$wdssep"
+ }
+
+ case "$enc" in
+ wep*)
+ case "$enc" in
+ *shared*) iwpriv "$ifname" authmode 2;;
+ *) iwpriv "$ifname" authmode 1;;
+ esac
+ for idx in 1 2 3 4; do
+ config_get key "$vif" "key${idx}"
+ iwconfig "$ifname" enc "[$idx]" "${key:-off}"
+ done
+ config_get key "$vif" key
+ key="${key:-1}"
+ case "$key" in
+ [1234]) iwconfig "$ifname" enc "[$key]";;
+ *) iwconfig "$ifname" enc "$key";;
+ esac
+ ;;
+ psk*|wpa*)
+ start_hostapd=1
+ config_get key "$vif" key
+ ;;
+ esac
+
+ case "$mode" in
+ sta|adhoc|ahdemo)
+ config_get addr "$vif" bssid
+ [ -z "$addr" ] || {
+ iwconfig "$ifname" ap "$addr"
+ }
+ ;;
+ esac
+
+ config_get_bool uapsd "$vif" uapsd 0
+ iwpriv "$ifname" uapsd "$uapsd"
+
+ config_get_bool bgscan "$vif" bgscan
+ [ -n "$bgscan" ] && iwpriv "$ifname" bgscan "$bgscan"
+
+ 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
+ [ -n "$frag" ] && iwconfig "$ifname" frag "${frag%%.*}"
+
+ config_get rts "$vif" rts
+ [ -n "$rts" ] && iwconfig "$ifname" rts "${rts%%.*}"
+
+ config_get_bool comp "$vif" compression 0
+ iwpriv "$ifname" compression "$comp" >/dev/null 2>&1
+
+ config_get minrate "$vif" minrate
+ [ -n "$minrate" ] && iwpriv "$ifname" minrate "$minrate"
+
+ config_get 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 beacon_power "$vif" beacon_power
+ [ -n "$beacon_power" ] && iwpriv "$ifname" beacon_pwr "$beacon_power"
+
+ config_get_bool doth "$vif" doth 0
+ [ -n "$doth" ] && iwpriv "$ifname" doth "$doth"
+
+ config_get_bool probereq "$vif" probereq
+ [ -n "$probereq" ] && iwpriv "$ifname" probereq "$probereq"
+
+ 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
+
+ local net_cfg bridge
+ net_cfg="$(find_net_config "$vif")"
+ [ -z "$net_cfg" ] || {
+ bridge="$(bridge_interface "$net_cfg")"
+ config_set "$vif" bridge "$bridge"
+ start_net "$ifname" "$net_cfg"
+ }
+
+ config_get ssid "$vif" ssid
+ [ -n "$ssid" ] && {
+ iwconfig "$ifname" essid on
+ iwconfig "$ifname" essid ${ssid:+-- }"$ssid"
+ }
+
+ set_wifi_up "$vif" "$ifname"
+
+ # TXPower settings only work if device is up already
+ # while atheros hardware theoretically is capable of per-vif (even per-packet) txpower
+ # adjustment it does not work with the current atheros hal/madwifi driver
+
+ config_get vif_txpower "$vif" txpower
+ # use vif_txpower (from wifi-iface) instead of txpower (from wifi-device) if
+ # the latter doesn't exist
+ txpower="${txpower:-$vif_txpower}"
+ [ -z "$txpower" ] || iwconfig "$ifname" txpower "${txpower%%.*}"
+
+ case "$mode" in
+ ap)
+ config_get_bool isolate "$vif" isolate 0
+ iwpriv "$ifname" ap_bridge "$((isolate^1))"
+
+ if [ -n "$start_hostapd" ] && eval "type hostapd_setup_vif" 2>/dev/null >/dev/null; then
+ hostapd_setup_vif "$vif" madwifi || {
+ echo "enable_atheros($device): Failed to set up hostapd for interface $ifname" >&2
+ # make sure this wifi interface won't accidentally stay open without encryption
+ ifconfig "$ifname" down
+ wlanconfig "$ifname" destroy
+ continue
+ }
+ fi
+ ;;
+ wds|sta)
+ if eval "type wpa_supplicant_setup_vif" 2>/dev/null >/dev/null; then
+ wpa_supplicant_setup_vif "$vif" wext || {
+ echo "enable_atheros($device): Failed to set up wpa_supplicant for interface $ifname" >&2
+ ifconfig "$ifname" down
+ wlanconfig "$ifname" destroy
+ continue
+ }
+ fi
+ ;;
+ adhoc)
+ if eval "type wpa_supplicant_setup_vif" 2>/dev/null >/dev/null; then
+ wpa_supplicant_setup_vif "$vif" madwifi || {
+ echo "enable_atheros($device): Failed to set up wpa"
+ ifconfig "$ifname" down
+ wlanconfig "$ifname" destroy
+ continue
+ }
+ fi
+ esac
+ done
+}
+
+check_atheros_device() {
+ [ ${1%[0-9]} = "wifi" ] && config_set "$1" phy "$1"
+ config_get phy "$1" phy
+ [ -z "$phy" ] && {
+ find_atheros_phy "$1" >/dev/null || return 0
+ config_get phy "$1" phy
+ }
+ [ "$phy" = "$dev" ] && found=1
+}
+
+
+detect_atheros() {
+ devidx=0
+ config_load wireless
+ while :; do
+ config_get type "radio$devidx" type
+ [ -n "$type" ] || break
+ devidx=$(($devidx + 1))
+ done
+ cd /proc/sys/dev
+ [ -d ath ] || return
+ for dev in $(ls -d wifi* 2>&-); do
+ found=0
+ config_foreach check_atheros_device wifi-device
+ [ "$found" -gt 0 ] && continue
+
+ devname="$(cat /proc/sys/dev/$dev/dev_name)"
+ case "$devname" in
+ "NanoStation Loco2")
+ EXTRA_DEV="
+# Ubiquiti NanoStation Loco2 features
+ option antenna vertical # (horizontal|vertical)
+"
+ ;;
+ "NanoStation Loco5")
+ EXTRA_DEV="
+# Ubiquiti NanoStation Loco5 features
+ option antenna auto # (auto|horizontal|vertical)
+"
+ ;;
+ NanoStation*)
+ EXTRA_DEV="
+# Ubiquiti NanoStation features
+ option antenna auto # (auto|horizontal|vertical|external)
+"
+ ;;
+ esac
+
+ cat <<EOF
+config wifi-device radio$devidx
+ option type atheros
+ option channel auto
+ option macaddr $(cat /sys/class/net/${dev}/address)
+$EXTRA_DEV
+ # REMOVE THIS LINE TO ENABLE WIFI:
+ option disabled 1
+
+config wifi-iface
+ option device radio$devidx
+ option network lan
+ option mode ap
+ option ssid OpenWrt
+ option encryption none
+
+EOF
+ devidx=$(($devidx + 1))
+ done
+}
diff --git a/package/madwifi/files/lib/wifi/madwifi_countrycodes.txt b/package/madwifi/files/lib/wifi/madwifi_countrycodes.txt
new file mode 100644
index 000000000..624048bdc
--- /dev/null
+++ b/package/madwifi/files/lib/wifi/madwifi_countrycodes.txt
@@ -0,0 +1,239 @@
+AF 4
+AL 8
+DZ 12
+AS 16
+AD 20
+AO 24
+AI 660
+AQ 10
+AG 28
+AR 32
+AM 51
+AW 533
+AU 36
+AT 40
+AZ 31
+BS 44
+BH 48
+BD 50
+BB 52
+BY 112
+BE 56
+BZ 84
+BJ 204
+BM 60
+BT 64
+BO 68
+BA 70
+BW 72
+BV 74
+BR 76
+IO 86
+VG 92
+BN 96
+BG 100
+BF 854
+BI 108
+KH 116
+CM 120
+CA 124
+CV 132
+KY 136
+CF 140
+TD 148
+CL 152
+CN 156
+CX 162
+CC 166
+CO 170
+KM 174
+CD 180
+CG 178
+CK 184
+CR 188
+CI 384
+CU 192
+CY 196
+CZ 203
+DK 208
+DJ 262
+DM 212
+DO 214
+EC 218
+EG 818
+SV 222
+GQ 226
+ER 232
+EE 233
+ET 231
+FO 234
+FK 238
+FJ 242
+FI 246
+FR 250
+GF 254
+PF 258
+TF 260
+GA 266
+GM 270
+GE 268
+DE 276
+GH 288
+GI 292
+GR 300
+GL 304
+GD 308
+GP 312
+GU 316
+GT 320
+GN 324
+GW 624
+GY 328
+HT 332
+HM 334
+VA 336
+HN 340
+HK 344
+HR 191
+HU 348
+IS 352
+IN 356
+ID 360
+IR 364
+IQ 368
+IE 372
+IL 376
+IT 380
+JM 388
+JP 392
+JO 400
+KZ 398
+KE 404
+KI 296
+KP 408
+KR 410
+KW 414
+KG 417
+LA 418
+LV 428
+LB 422
+LS 426
+LR 430
+LY 434
+LI 438
+LT 440
+LU 442
+MO 446
+MK 807
+MG 450
+MW 454
+MY 458
+MV 462
+ML 466
+MT 470
+MH 584
+MQ 474
+MR 478
+MU 480
+YT 175
+MX 484
+FM 583
+MD 498
+MC 492
+MN 496
+MS 500
+MA 504
+MZ 508
+MM 104
+NA 516
+NR 520
+NP 524
+AN 530
+NL 528
+NC 540
+NZ 554
+NI 558
+NE 562
+NG 566
+NU 570
+NF 574
+MP 580
+NO 578
+OM 512
+PK 586
+PW 585
+PS 275
+PA 591
+PG 598
+PY 600
+PE 604
+PH 608
+PN 612
+PL 616
+PT 620
+PR 630
+QA 634
+RE 638
+RO 642
+RU 643
+RW 646
+SH 654
+KN 659
+LC 662
+PM 666
+VC 670
+WS 882
+SM 674
+ST 678
+SA 682
+SN 686
+CS 891
+SC 690
+SL 694
+SG 702
+SK 703
+SI 705
+SB 90
+SO 706
+ZA 710
+GS 239
+ES 724
+LK 144
+SD 736
+SR 740
+SJ 744
+SZ 748
+SE 752
+CH 756
+SY 760
+TW 158
+TJ 762
+TZ 834
+TH 764
+TL 626
+TG 768
+TK 772
+TO 776
+TT 780
+TN 788
+TR 792
+TM 795
+TC 796
+TV 798
+VI 850
+UG 800
+UA 804
+AE 784
+GB 826
+UM 581
+US 840
+UY 858
+UZ 860
+VU 548
+VE 862
+VN 704
+WF 876
+EH 732
+YE 887
+ZM 894
+ZW 716
diff --git a/package/madwifi/patches/102-multicall_binary.patch b/package/madwifi/patches/102-multicall_binary.patch
new file mode 100644
index 000000000..887a462e9
--- /dev/null
+++ b/package/madwifi/patches/102-multicall_binary.patch
@@ -0,0 +1,315 @@
+--- a/tools/80211debug.c
++++ b/tools/80211debug.c
+@@ -48,6 +48,7 @@
+ #include <ctype.h>
+ #include <getopt.h>
+ #include <err.h>
++#include "do_multi.h"
+
+ #undef ARRAY_SIZE
+ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+@@ -185,7 +186,7 @@ sysctlbyname(const char *oid0, void *old
+ #endif /* __linux__ */
+
+ int
+-main(int argc, char *argv[])
++CMD(a80211debug)(int argc, char *argv[])
+ {
+ const char *ifname = "ath0";
+ const char *cp, *tp;
+--- 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"
++#include "do_multi.h"
+
+ #ifndef SIOCG80211STATS
+ #define SIOCG80211STATS (SIOCDEVPRIVATE + 2)
+@@ -240,7 +241,7 @@ print_sta_stats(FILE *fd, const u_int8_t
+ }
+
+ int
+-main(int argc, char *argv[])
++CMD(a80211stats)(int argc, char *argv[])
+ {
+ int c, len;
+ struct ieee80211req_sta_info *si;
+--- 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"
++#include "do_multi.h"
+
+ static int s = -1;
+ static const char *progname;
+@@ -140,8 +141,9 @@ usage(void)
+ }
+
+ #define MAXCHAN ((int)(sizeof(struct ieee80211req_chanlist) * NBBY))
++
+ int
+-main(int argc, char *argv[])
++CMD(athchans)(int argc, char *argv[])
+ {
+ const char *ifname = "wifi0";
+ struct ieee80211req_chanlist chanlist;
+--- a/tools/athctrl.c
++++ b/tools/athctrl.c
+@@ -52,6 +52,7 @@
+ #include <err.h>
+
+ #include <net/if.h>
++#include "do_multi.h"
+
+ static int
+ setsysctrl(const char *dev, const char *control , u_long value)
+@@ -88,7 +89,7 @@ static void usage(void)
+ }
+
+ int
+-main(int argc, char *argv[])
++CMD(athctrl)(int argc, char *argv[])
+ {
+ char device[IFNAMSIZ + 1];
+ int distance = -1;
+--- a/tools/athdebug.c
++++ b/tools/athdebug.c
+@@ -51,6 +51,7 @@
+ #include <ctype.h>
+ #include <getopt.h>
+ #include <err.h>
++#include "do_multi.h"
+
+ #undef ARRAY_SIZE
+ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+@@ -194,7 +195,7 @@ sysctlbyname(const char *oid0, void *old
+ #endif /* __linux__ */
+
+ int
+-main(int argc, char *argv[])
++CMD(athdebug)(int argc, char *argv[])
+ {
+ #ifdef __linux__
+ const char *ifname = "wifi0";
+--- 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"
++#include "do_multi.h"
+
+ static int s = -1;
+ static const char *progname;
+@@ -213,8 +214,7 @@ usage(void)
+ exit(-1);
+ }
+
+-int
+-main(int argc, char *argv[])
++int CMD(athkey)(int argc, char *argv[])
+ {
+ const char *ifname = "wifi0";
+ struct ieee80211req_key setkey;
+--- a/tools/athstats.c
++++ b/tools/athstats.c
+@@ -65,6 +65,7 @@
+
+ #undef ARRAY_SIZE
+ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
++#include "do_multi.h"
+
+ static const struct {
+ u_int phyerr;
+@@ -228,7 +229,7 @@ catchalarm(int signo)
+ }
+
+ int
+-main(int argc, char *argv[])
++CMD(athstats)(int argc, char *argv[])
+ {
+ #ifdef __linux__
+ const char *ifname = "wifi0";
+--- /dev/null
++++ b/tools/do_multi.c
+@@ -0,0 +1,33 @@
++#include <string.h>
++#include <libgen.h>
++#include "do_multi.h"
++
++int
++main(int argc, char *argv[])
++{
++ char *progname;
++ int ret = 0;
++
++ progname = basename(argv[0]);
++
++ if(strcmp(progname, "80211debug") == 0)
++ ret = a80211debug_init(argc, argv);
++ if(strcmp(progname, "80211stats") == 0)
++ ret = a80211stats_init(argc, argv);
++ if(strcmp(progname, "athchans") == 0)
++ ret = athchans_init(argc, argv);
++ if(strcmp(progname, "athctrl") == 0)
++ ret = athctrl_init(argc, argv);
++ if(strcmp(progname, "athdebug") == 0)
++ ret = athdebug_init(argc, argv);
++ if(strcmp(progname, "athkey") == 0)
++ ret = athkey_init(argc, argv);
++ if(strcmp(progname, "athstats") == 0)
++ 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;
++}
+--- /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[]);
++int athctrl_init(int argc, char *argv[]);
++int athdebug_init(int argc, char *argv[]);
++int athkey_init(int argc, char *argv[]);
++int athstats_init(int argc, char *argv[]);
++int wlanconfig_init(int argc, char *argv[]);
++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 @@ ifeq ($(HAL),)
+ 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
+
+
+ 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"
++#include "do_multi.h"
+
+ /*
+ * These are taken from ieee80211_node.h
+@@ -100,7 +101,7 @@ size_t strlcat(char *, const char *, siz
+ static int verbose = 0;
+
+ int
+-main(int argc, char *argv[])
++CMD(wlanconfig)(int argc, char *argv[])
+ {
+ const char *ifname, *cmd;
+ unsigned char bnounit = 0;
+--- 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 @@ static void usage(const char *n)
+ "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 --git a/package/madwifi/patches/104-autocreate_none.patch b/package/madwifi/patches/104-autocreate_none.patch
new file mode 100644
index 000000000..b2181b68e
--- /dev/null
+++ b/package/madwifi/patches/104-autocreate_none.patch
@@ -0,0 +1,11 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -516,7 +516,7 @@ ath_attach(u_int16_t devid, struct net_d
+ HAL_STATUS status;
+ int error = 0;
+ unsigned int i;
+- int autocreatemode = IEEE80211_M_STA;
++ int autocreatemode = -1;
+ u_int8_t csz;
+
+ sc->devid = devid;
diff --git a/package/madwifi/patches/105-ratectl_attach.patch b/package/madwifi/patches/105-ratectl_attach.patch
new file mode 100644
index 000000000..80aad835e
--- /dev/null
+++ b/package/madwifi/patches/105-ratectl_attach.patch
@@ -0,0 +1,23 @@
+--- a/net80211/ieee80211_rate.c
++++ b/net80211/ieee80211_rate.c
+@@ -100,8 +100,18 @@ struct ath_ratectrl *ieee80211_rate_atta
+ ieee80211_load_module(buf);
+
+ if (!ratectls[id].attach) {
+- printk(KERN_ERR "Error loading module \"%s\"\n", buf);
+- return NULL;
++ /* pick the first available rate control module */
++ printk(KERN_INFO "Rate control module \"%s\" not available\n", buf);
++ for (id = 0; id < IEEE80211_RATE_MAX - 1; id++) {
++ if (ratectls[id].attach)
++ break;
++ }
++ if (!ratectls[id].attach) {
++ printk(KERN_ERR "No rate control module available");
++ return NULL;
++ } else {
++ printk(KERN_INFO "Using \"%s\" instead.\n", module_names[id]);
++ }
+ }
+
+ ctl = ratectls[id].attach(sc);
diff --git a/package/madwifi/patches/106-get_arch.patch b/package/madwifi/patches/106-get_arch.patch
new file mode 100644
index 000000000..3140f3679
--- /dev/null
+++ b/package/madwifi/patches/106-get_arch.patch
@@ -0,0 +1,21 @@
+--- a/scripts/get_arch.mk
++++ b/scripts/get_arch.mk
+@@ -36,11 +36,14 @@ ifeq (,$(ARCH-y))
+ $(Cannot determine ARCH)
+ endif
+
++# Allow ARCH to be x86
++ifneq (,$(CONFIG_X86))
++ifeq (x86,$(ARCH))
++ARCH-y = $(ARCH)
++endif
++endif
++
+ # Don't allow ARCH to be overridden by a different value.
+ ifeq (,$(ARCH))
+ ARCH = $(ARCH-y)
+-else
+-ifneq ($(ARCH),$(ARCH-y))
+-$(error ARCH mismatch: supplied "$(ARCH)", determined "$(ARCH-y)")
+-endif
+ endif
diff --git a/package/madwifi/patches/111-minstrel_crash.patch b/package/madwifi/patches/111-minstrel_crash.patch
new file mode 100644
index 000000000..975bc4e94
--- /dev/null
+++ b/package/madwifi/patches/111-minstrel_crash.patch
@@ -0,0 +1,12 @@
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -393,6 +393,9 @@ ath_rate_get_mrr(struct ath_softc *sc, s
+ struct minstrel_node *sn = ATH_NODE_MINSTREL(an);
+ int rc1, rc2, rc3; /* Index into the rate table, so for example, it is 0..11 */
+
++ if (sn->num_rates <= 0)
++ return;
++
+ if (sn->is_sampling) {
+ sn->is_sampling = 0;
+ if (sn->rs_sample_rate_slower)
diff --git a/package/madwifi/patches/113-no_ibss_pwrsave.patch b/package/madwifi/patches/113-no_ibss_pwrsave.patch
new file mode 100644
index 000000000..af23ceb7a
--- /dev/null
+++ b/package/madwifi/patches/113-no_ibss_pwrsave.patch
@@ -0,0 +1,12 @@
+--- a/net80211/ieee80211_scan.c
++++ b/net80211/ieee80211_scan.c
+@@ -291,7 +291,8 @@ scan_restart_pwrsav(unsigned long arg)
+ struct ieee80211com *ic = vap->iv_ic;
+ int delay;
+
+- ieee80211_sta_pwrsave(vap, 1);
++ if (vap->iv_opmode != IEEE80211_M_IBSS)
++ ieee80211_sta_pwrsave(vap, 1);
+ /*
+ * Use an initial 1ms delay to ensure the null
+ * data frame has a chance to go out.
diff --git a/package/madwifi/patches/122-replayfail_workaround.patch b/package/madwifi/patches/122-replayfail_workaround.patch
new file mode 100644
index 000000000..c4eb28c94
--- /dev/null
+++ b/package/madwifi/patches/122-replayfail_workaround.patch
@@ -0,0 +1,12 @@
+--- a/net80211/ieee80211_linux.c
++++ b/net80211/ieee80211_linux.c
+@@ -331,6 +331,9 @@ ieee80211_notify_replay_failure(struct i
+ k->wk_cipher->ic_name, k->wk_keyix,
+ (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=" MAC_FMT ")", tag,
+ k->wk_keyix,
diff --git a/package/madwifi/patches/123-ccmp_checks.patch b/package/madwifi/patches/123-ccmp_checks.patch
new file mode 100644
index 000000000..6178a3f78
--- /dev/null
+++ b/package/madwifi/patches/123-ccmp_checks.patch
@@ -0,0 +1,95 @@
+--- a/net80211/ieee80211_crypto_ccmp.c
++++ b/net80211/ieee80211_crypto_ccmp.c
+@@ -115,6 +115,7 @@ ccmp_attach(struct ieee80211vap *vap, st
+ /* This function (crypto_alloc_foo might sleep. Therefore:
+ * Context: process
+ */
++#ifdef CONFIG_CRYPTO
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+ ctx->cc_tfm = crypto_alloc_tfm("aes", 0);
+ #else
+@@ -123,7 +124,8 @@ ccmp_attach(struct ieee80211vap *vap, st
+ if (IS_ERR(ctx->cc_tfm))
+ ctx->cc_tfm = NULL;
+ #endif
+-
++#endif
++
+ if (ctx->cc_tfm == NULL) {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
+ "%s: unable to load kernel AES crypto support\n",
+@@ -138,12 +140,14 @@ ccmp_detach(struct ieee80211_key *k)
+ {
+ struct ccmp_ctx *ctx = k->wk_private;
+
++#ifdef CONFIG_CRYPTO
+ if (ctx->cc_tfm != NULL)
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+ crypto_free_tfm(ctx->cc_tfm);
+ #else
+ crypto_free_cipher(ctx->cc_tfm);
+ #endif
++#endif
+ FREE(ctx, M_DEVBUF);
+
+ _MOD_DEC_USE(THIS_MODULE);
+@@ -169,7 +173,9 @@ ccmp_setkey(struct ieee80211_key *k)
+ return 0;
+ }
+
++#ifdef CONFIG_CRYPTO
+ crypto_cipher_setkey(ctx->cc_tfm, k->wk_key, k->wk_keylen);
++#endif
+ }
+
+ return 1;
+@@ -324,6 +330,7 @@ xor_block(u8 *b, const u8 *a, size_t len
+ static void
+ rijndael_encrypt(struct crypto_cipher *tfm, const void *src, void *dst)
+ {
++#ifdef CONFIG_CRYPTO
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
+ crypto_cipher_encrypt_one(tfm, dst, src);
+ #else
+@@ -339,6 +346,7 @@ rijndael_encrypt(struct crypto_cipher *t
+ sg_dst.length = AES_BLOCK_LEN;
+ crypto_cipher_encrypt(tfm, &sg_dst, &sg_src, AES_BLOCK_LEN);
+ #endif
++#endif
+ }
+
+ /*
+@@ -475,6 +483,9 @@ ccmp_encrypt(struct ieee80211_key *key,
+ uint8_t *mic, *pos;
+ u_int space;
+
++ if (ctx->cc_tfm == NULL)
++ return 0;
++
+ ctx->cc_vap->iv_stats.is_crypto_ccmp++;
+
+ skb = skb0;
+@@ -589,6 +600,9 @@ ccmp_decrypt(struct ieee80211_key *key,
+ uint8_t *pos, *mic;
+ u_int space;
+
++ if (ctx->cc_tfm == NULL)
++ return 0;
++
+ ctx->cc_vap->iv_stats.is_crypto_ccmp++;
+
+ skb = skb0;
+--- a/Makefile
++++ b/Makefile
+@@ -192,11 +192,4 @@ endif
+ exit 1; \
+ fi
+
+- @# check crypto support is enabled
+- @if [ -z "$(CONFIG_CRYPTO)" ]; then \
+- echo "FAILED"; \
+- echo "Please enable crypto API."; \
+- exit 1; \
+- fi
+-
+ @echo "ok."
diff --git a/package/madwifi/patches/124-linux24_compat.patch b/package/madwifi/patches/124-linux24_compat.patch
new file mode 100644
index 000000000..88601a4c7
--- /dev/null
+++ b/package/madwifi/patches/124-linux24_compat.patch
@@ -0,0 +1,202 @@
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -126,6 +126,11 @@ typedef void irqreturn_t;
+ #define ATH_GET_NETDEV_DEV(ndev) ((ndev)->class_dev.dev)
+ #endif
+
++#ifndef NETDEV_TX_OK
++#define NETDEV_TX_OK 0
++#define NETDEV_TX_BUSY 1
++#endif
++
+ #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 @@ ath_beacon_setup(struct ath_softc *sc, s
+ #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 --git a/package/madwifi/patches/126-rxerr_frames.patch b/package/madwifi/patches/126-rxerr_frames.patch
new file mode 100644
index 000000000..762a7bc81
--- /dev/null
+++ b/package/madwifi/patches/126-rxerr_frames.patch
@@ -0,0 +1,13 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -6474,8 +6474,9 @@ ath_rx_tasklet(TQUEUE_ARG data)
+ /*
+ * Reject error frames if we have no vaps that
+ * are operating in monitor mode.
++ * Reject empty frames as well
+ */
+- if (sc->sc_nmonvaps == 0)
++ if ((sc->sc_nmonvaps == 0) || (rs->rs_datalen == 0))
+ goto rx_next;
+ }
+ rx_accept:
diff --git a/package/madwifi/patches/200-no_debug.patch b/package/madwifi/patches/200-no_debug.patch
new file mode 100644
index 000000000..3f46ec88b
--- /dev/null
+++ b/package/madwifi/patches/200-no_debug.patch
@@ -0,0 +1,408 @@
+--- 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
+ #include "if_ath_debug.h"
+ #include "opt_ah.h"
+
+@@ -368,8 +367,10 @@ static unsigned int ath_get_dfs_cac_time
+ 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 @@ ath_attach(u_int16_t devid, struct net_d
+ 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 @@ ath_attach(u_int16_t devid, struct net_d
+ 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 @@ ath_vap_create(struct ieee80211com *ic,
+ /* 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 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+ /* 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 @@ ath_dynamic_sysctl_register(struct ath_s
+ }
+
+ /* 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 @@ ath_test_radar(struct ieee80211com *ic)
+ }
+
+ /* 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_dump_hal_map(struct ieee80211com *ic
+ 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"
+
++#ifdef AR_DEBUG
+ #define AMRR_DEBUG
++#endif
+ #ifdef AMRR_DEBUG
+ #define DPRINTF(sc, _fmt, ...) do { \
+ if (sc->sc_debug & 0x10) \
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -117,7 +117,9 @@
+
+ #include "minstrel.h"
+
++#ifdef AR_DEBUG
+ #define MINSTREL_DEBUG
++#endif
+ #ifdef MINSTREL_DEBUG
+ enum {
+ ATH_DEBUG_RATE = 0x00000010 /* rate control */
+--- a/ath_rate/onoe/onoe.c
++++ b/ath_rate/onoe/onoe.c
+@@ -66,7 +66,9 @@
+
+ #include "onoe.h"
+
++#ifdef AR_DEBUG
+ #define ONOE_DEBUG
++#endif
+ #ifdef ONOE_DEBUG
+ enum {
+ ATH_DEBUG_RATE = 0x00000010, /* rate control */
+--- a/ath_rate/sample/sample.c
++++ b/ath_rate/sample/sample.c
+@@ -68,7 +68,9 @@
+
+ #include "sample.h"
+
+-#define SAMPLE_DEBUG
++#ifdef AR_DEBUG
++#define SAMPLE_DEBUG
++#endif
+ #ifdef SAMPLE_DEBUG
+ enum {
+ ATH_DEBUG_RATE = 0x00000010, /* rate control */
+--- a/tools/do_multi.c
++++ b/tools/do_multi.c
+@@ -10,16 +10,20 @@ main(int argc, char *argv[])
+
+ progname = basename(argv[0]);
+
++#ifdef AR_DEBUG
+ if(strcmp(progname, "80211debug") == 0)
+ ret = a80211debug_init(argc, argv);
++#endif
+ if(strcmp(progname, "80211stats") == 0)
+ ret = a80211stats_init(argc, argv);
+ if(strcmp(progname, "athchans") == 0)
+ ret = athchans_init(argc, argv);
+ if(strcmp(progname, "athctrl") == 0)
+ ret = athctrl_init(argc, argv);
++#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)
+--- a/tools/Makefile
++++ b/tools/Makefile
+@@ -48,14 +48,16 @@ endif
+
+ all: compile
+
++DEBUG = -DAR_DEBUG
++
+ ALLPROGS= athstats 80211stats athkey athchans athctrl \
+- athdebug 80211debug wlanconfig ath_info
++ $(if $(DEBUG),athdebug 80211debug) wlanconfig ath_info
+
+ OBJS= $(patsubst %,%.o,$(ALLPROGS))
+
+ 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
+@@ -147,8 +147,9 @@ ATH_RATE= $(TOP)/ath_rate
+ #
+ TOOLS= $(TOP)/tools
+
+-WARNINGS = -Werror
+-COPTS+= $(WARNINGS)
++WARNINGS = -Wno-unused
++# 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 @@ static inline HAL_BOOL ath_hal_disable(s
+
+ 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 @@ static inline void ath_hal_dump_map(stru
+ #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 @@ 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 *);
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -1548,6 +1548,7 @@ ieee80211_get_txcont_power(struct net_de
+ 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 @@ ieee80211_ioctl_hal_map(struct net_devic
+ 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 @@ static const struct iw_priv_args ieee802
+ 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 @@ static const iw_handler ieee80211_priv_h
+ 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
+@@ -54,6 +54,10 @@ enum {
+ ATH_DEBUG_GLOBAL = (ATH_DEBUG_SKB|ATH_DEBUG_SKB_REF)
+ };
+
++#define EPRINTF(_sc, _fmt, ...) \
++ printk(KERN_ERR "%s: %s: " _fmt, \
++ SC_DEV_NAME(_sc), __func__, ## __VA_ARGS__)
++
+ #ifdef AR_DEBUG
+
+ /* DEBUG-ONLY DEFINITIONS */
+@@ -68,20 +72,9 @@ enum {
+ 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))
+
+-#define EPRINTF(_sc, _fmt, ...) \
+- printk(KERN_ERR "%s: %s: " _fmt, \
+- SC_DEV_NAME(_sc), __func__, ## __VA_ARGS__)
+-
+ #define WPRINTF(_sc, _fmt, ...) \
+ printk(KERN_WARNING "%s: %s: " _fmt, \
+ SC_DEV_NAME(_sc), __func__, ## __VA_ARGS__)
+@@ -89,5 +82,14 @@ enum {
+ #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 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 @@ node_cleanup(struct ieee80211_node *ni)
+ 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 @@ static void node_print_message(
+ adjusted_refcount);
+ va_end(args);
+ }
+-EXPORT_SYMBOL(node_print_message);
++#endif
+
+ static void
+ #ifdef IEEE80211_DEBUG_REFCNT
+--- a/ath/if_ath_pci.c
++++ b/ath/if_ath_pci.c
+@@ -134,8 +134,10 @@ ath_pci_probe(struct pci_dev *pdev, cons
+ u16 vdevice;
+ int i;
+
+- if (pci_enable_device(pdev))
++ if (pci_enable_device(pdev)) {
++ printk(KERN_ERR "%s: failed to enable PCI device\n", dev_info);
+ return -EIO;
++ }
+
+ /* XXX 32-bit addressing only */
+ if (pci_set_dma_mask(pdev, 0xffffffff)) {
+@@ -244,8 +246,10 @@ ath_pci_probe(struct pci_dev *pdev, cons
+ sc->aps_sc.sc_ledpin = 1;
+ }
+
+- if (ath_attach(vdevice, dev, NULL) != 0)
++ if ((i = ath_attach(vdevice, dev, NULL)) != 0) {
++ printk(KERN_ERR "%s: ath_attach failed: %d\n", dev_info, i);
+ goto bad4;
++ }
+
+ athname = ath_hal_probe(id->vendor, vdevice);
+ printk(KERN_INFO "%s: %s: %s: mem=0x%lx, irq=%d\n",
diff --git a/package/madwifi/patches/201-debug_fix.patch b/package/madwifi/patches/201-debug_fix.patch
new file mode 100644
index 000000000..bcfbba82c
--- /dev/null
+++ b/package/madwifi/patches/201-debug_fix.patch
@@ -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 @@ EXPORT_SYMBOL(OS_MARK);
+ * useful for debugging and figuring out, which hal function sets which
+ * registers */
+ char *ath_hal_func = NULL;
++EXPORT_SYMBOL(ath_hal_func);
++
+ #endif
+
+ /*
diff --git a/package/madwifi/patches/202-debug_variables.patch b/package/madwifi/patches/202-debug_variables.patch
new file mode 100644
index 000000000..33e6efad1
--- /dev/null
+++ b/package/madwifi/patches/202-debug_variables.patch
@@ -0,0 +1,204 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -453,8 +453,8 @@ MODULE_PARM_DESC(autocreate, "Create ath
+ MODULE_PARM_DESC(ratectl, "Rate control algorithm [amrr|minstrel|onoe|sample], "
+ "defaults to '" DEF_RATE_CTL "'");
+
+-static int ath_debug = 0;
+ #ifdef AR_DEBUG
++static int ath_debug = 0;
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))
+ MODULE_PARM(ath_debug, "i");
+ #else
+@@ -465,8 +465,8 @@ static void ath_printrxbuf(const struct
+ static void ath_printtxbuf(const struct ath_buf *, int);
+ #endif /* defined(AR_DEBUG) */
+
+-static int ieee80211_debug = 0;
+ #ifdef AR_DEBUG
++static int ieee80211_debug = 0;
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))
+ MODULE_PARM(ieee80211_debug, "i");
+ #else
+@@ -1565,7 +1565,9 @@ ath_vap_delete(struct ieee80211vap *vap)
+ void
+ ath_suspend(struct net_device *dev)
+ {
++#ifdef AR_DEBUG
+ struct ath_softc *sc = dev->priv;
++#endif
+
+ DPRINTF(sc, ATH_DEBUG_ANY, "flags=%x\n", dev->flags);
+ ath_stop(dev);
+@@ -1574,7 +1576,9 @@ ath_suspend(struct net_device *dev)
+ void
+ ath_resume(struct net_device *dev)
+ {
++#ifdef AR_DEBUG
+ struct ath_softc *sc = dev->priv;
++#endif
+
+ DPRINTF(sc, ATH_DEBUG_ANY, "flags=%x\n", dev->flags);
+ ath_init(dev);
+@@ -4019,7 +4023,9 @@ static void
+ ath_key_update_begin(struct ieee80211vap *vap)
+ {
+ struct net_device *dev = vap->iv_ic->ic_dev;
++#ifdef AR_DEBUG
+ struct ath_softc *sc = dev->priv;
++#endif
+
+ DPRINTF(sc, ATH_DEBUG_KEYCACHE, "Begin\n");
+ /*
+@@ -4040,7 +4046,9 @@ static void
+ ath_key_update_end(struct ieee80211vap *vap)
+ {
+ struct net_device *dev = vap->iv_ic->ic_dev;
++#ifdef AR_DEBUG
+ struct ath_softc *sc = dev->priv;
++#endif
+
+ DPRINTF(sc, ATH_DEBUG_KEYCACHE, "End\n");
+ netif_wake_queue(dev);
+@@ -6218,7 +6226,9 @@ ath_recv_mgmt(struct ieee80211vap * vap,
+ struct sk_buff *skb, int subtype, int rssi, u_int64_t rtsf)
+ {
+ struct ath_softc *sc = vap->iv_ic->ic_dev->priv;
++#ifdef AR_DEBUG
+ struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data;
++#endif
+ struct ieee80211_node * ni = ni_or_null;
+ u_int64_t hw_tsf, beacon_tsf;
+ u_int32_t hw_tu, beacon_tu, intval;
+@@ -8382,7 +8392,9 @@ ath_tx_timeout(struct net_device *dev)
+ static void
+ ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq)
+ {
++#ifdef AR_DEBUG
+ struct ath_hal *ah = sc->sc_ah;
++#endif
+ struct ath_buf *bf;
+ /*
+ * NB: this assumes output has been stopped and
+@@ -11002,6 +11014,7 @@ ath_announce(struct net_device *dev)
+ strncat(m, b, MLEN);
+ }
+ strncat(m, "\n", MLEN);
++#ifdef AR_DEBUG
+ if (1 /* bootverbose */) {
+ unsigned int i;
+ for (i = 0; i <= WME_AC_VO; i++) {
+@@ -11014,6 +11027,7 @@ ath_announce(struct net_device *dev)
+ sc->sc_cabq->axq_qnum);
+ IPRINTF(sc, "Use hw queue %u for beacons\n", sc->sc_bhalq);
+ }
++#endif
+ #undef HAL_MODE_DUALBAND
+ }
+
+--- a/ath/if_ath_radar.c
++++ b/ath/if_ath_radar.c
+@@ -156,7 +156,9 @@ static struct radar_pattern_specificatio
+ #endif
+ };
+
++#ifdef AR_DEBUG
+ static u_int32_t interval_to_frequency(u_int32_t pri);
++#endif
+
+ /* Returns true if radar detection is enabled. */
+ int ath_radar_is_enabled(struct ath_softc *sc)
+@@ -229,7 +231,9 @@ int ath_radar_update(struct ath_softc *s
+ {
+
+ struct ath_hal *ah = sc->sc_ah;
++#ifdef AR_DEBUG
+ struct net_device *dev = sc->sc_dev;
++#endif
+ struct ieee80211com *ic = &sc->sc_ic;
+ int required = 0;
+
+@@ -366,6 +370,7 @@ static struct ath_rp *pulse_prev(struct
+ #define MR_FAIL_MIN_PERIOD 4
+ #define MR_FAIL_MAX_PERIOD 5
+
++#ifdef AR_DEBUG
+ static const char* get_match_result_desc(u_int32_t code) {
+ switch (code) {
+ case MR_MATCH:
+@@ -384,6 +389,7 @@ static const char* get_match_result_desc
+ return "unknown";
+ }
+ }
++#endif
+
+ static int32_t match_radar(
+ u_int32_t matched,
+@@ -775,7 +781,10 @@ static HAL_BOOL rp_analyse_short_pulse(
+ struct ath_softc *sc, struct ath_rp *last_pulse,
+ u_int32_t *index, u_int32_t *pri, u_int32_t *matching_pulses,
+ u_int32_t *missed_pulses, u_int32_t *noise_pulses)
+-{ struct net_device *dev = sc->sc_dev;
++{
++#ifdef AR_DEBUG
++ struct net_device *dev = sc->sc_dev;
++#endif
+ int i;
+ int best_index = -1;
+ unsigned int best_matched = 0;
+@@ -1217,6 +1226,7 @@ static HAL_BOOL rp_analyse_short_pulse(
+ return (-1 != best_index) ? AH_TRUE : AH_FALSE;
+ }
+
++#ifdef AR_DEBUG
+ static u_int32_t interval_to_frequency(u_int32_t interval)
+ {
+ /* Calculate BRI from PRI */
+@@ -1224,6 +1234,7 @@ static u_int32_t interval_to_frequency(u
+ /* Round to nearest multiple of 50 */
+ return frequency + ((frequency % 50) >= 25 ? 50 : 0) - (frequency % 50);
+ }
++#endif
+
+ #ifdef ATH_RADAR_LONG_PULSE
+ static const char* get_longpulse_desc(int lp) {
+@@ -1580,7 +1591,9 @@ void ath_rp_done(struct ath_softc *sc)
+ void ath_rp_record(struct ath_softc *sc, u_int64_t tsf, u_int8_t rssi,
+ u_int8_t width, HAL_BOOL is_simulated)
+ {
++#ifdef AR_DEBUG
+ struct net_device *dev = sc->sc_dev;
++#endif
+ struct ath_rp *pulse;
+
+ DPRINTF(sc, ATH_DEBUG_DOTHPULSES, "%s: ath_rp_record: "
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -931,7 +931,9 @@ ath_proc_read_nodes(struct ieee80211vap
+ (struct ieee80211_node_table *) &vap->iv_ic->ic_sta;
+ unsigned int x = 0;
+ unsigned int this_tp, this_prob, this_eprob;
++#ifdef AR_DEBUG
+ struct ath_softc *sc = vap->iv_ic->ic_dev->priv;;
++#endif
+
+ IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
+ TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
+--- a/net80211/ieee80211_scan_ap.c
++++ b/net80211/ieee80211_scan_ap.c
+@@ -731,6 +731,7 @@ pick_channel(struct ieee80211_scan_state
+
+ sort(chans, ss_last, sizeof(*chans), pc_cmp, pc_swap);
+
++#ifdef IEEE80211_DEBUG
+ for (i = 0; i < ss_last; i++) {
+ int chan = ieee80211_chan2ieee(ic, chans[i].chan);
+
+@@ -742,6 +743,7 @@ pick_channel(struct ieee80211_scan_state
+ !!IEEE80211_ARE_CHANS_SAME_MODE(chans[i].chan,
+ ic->ic_bsschan));
+ }
++#endif
+
+ best = NULL;
+ best_rssi = 0xff; /* If signal is bigger than 0xff, we'd be melting. */
diff --git a/package/madwifi/patches/300-napi_polling.patch b/package/madwifi/patches/300-napi_polling.patch
new file mode 100644
index 000000000..bde768494
--- /dev/null
+++ b/package/madwifi/patches/300-napi_polling.patch
@@ -0,0 +1,536 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -184,7 +184,11 @@ static void ath_recv_mgmt(struct ieee802
+ 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
+@@ -376,6 +380,9 @@ static u_int32_t ath_set_clamped_maxtxpo
+ 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 @@ ath_attach(u_int16_t devid, struct net_d
+
+ 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);
+@@ -821,6 +827,12 @@ ath_attach(u_int16_t devid, struct net_d
+ dev->set_mac_address = ath_set_mac_address;
+ 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) +
+@@ -2220,6 +2232,7 @@ ath_intr(int irq, void *dev_id, struct p
+ (status & HAL_INT_GLOBAL) ? " HAL_INT_GLOBAL" : ""
+ );
+
++ sc->sc_isr = status;
+ status &= sc->sc_imask; /* discard unasked for bits */
+ /* 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.
+@@ -2277,7 +2290,21 @@ ath_intr(int irq, void *dev_id, struct p
+ }
+ 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 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
++ {
++ sc->sc_imask &= ~HAL_INT_RX;
++ ath_hal_intrset(ah, sc->sc_imask);
++#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
+@@ -2303,6 +2330,11 @@ ath_intr(int irq, void *dev_id, struct p
+ }
+ }
+ #endif
++ /* disable transmit interrupt */
++ sc->sc_isr &= ~HAL_INT_TX;
++ ath_hal_intrset(ah, sc->sc_imask & ~HAL_INT_TX);
++ sc->sc_imask &= ~HAL_INT_TX;
++
+ ATH_SCHEDULE_TQUEUE(&sc->sc_txtq, &needmark);
+ }
+ if (status & HAL_INT_BMISS) {
+@@ -2515,6 +2547,7 @@ ath_init(struct net_device *dev)
+ if (sc->sc_tx99 != NULL)
+ sc->sc_tx99->start(sc->sc_tx99);
+ #endif
++ ath_poll_enable(dev);
+
+ done:
+ ATH_UNLOCK(sc);
+@@ -2555,6 +2588,9 @@ ath_stop_locked(struct net_device *dev)
+ 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 */
+@@ -4013,12 +4049,47 @@ ath_key_set(struct ieee80211vap *vap, co
+ 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
+ * so we only need to worry about synchronization with other
+ * uses that originate in the driver.
+ */
++#define IS_UP(_dev) \
++ (((_dev)->flags & (IFF_RUNNING|IFF_UP)) == (IFF_RUNNING|IFF_UP))
+ static void
+ ath_key_update_begin(struct ieee80211vap *vap)
+ {
+@@ -4032,14 +4103,9 @@ ath_key_update_begin(struct ieee80211vap
+ * 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())
+- tasklet_disable(&sc->sc_rxtq);
+- netif_stop_queue(dev);
++ if (IS_UP(vap->iv_dev))
++ netif_stop_queue(dev);
+ }
+
+ static void
+@@ -4051,9 +4117,9 @@ ath_key_update_end(struct ieee80211vap *
+ #endif
+
+ DPRINTF(sc, ATH_DEBUG_KEYCACHE, "End\n");
+- netif_wake_queue(dev);
+- if (!in_softirq()) /* NB: see above */
+- tasklet_enable(&sc->sc_rxtq);
++
++ if (IS_UP(vap->iv_dev))
++ netif_wake_queue(dev);
+ }
+
+ /*
+@@ -6360,15 +6426,25 @@ ath_setdefantenna(struct ath_softc *sc,
+ 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;
++#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;
+ struct ath_hal *ah = sc ? sc->sc_ah : NULL;
+ struct ath_desc *ds;
+@@ -6378,8 +6454,10 @@ ath_rx_tasklet(TQUEUE_ARG data)
+ unsigned int len;
+ int type;
+ u_int phyerr;
++ u_int processed = 0, early_stop = 0;
+
+ 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 */
+@@ -6403,6 +6481,15 @@ ath_rx_tasklet(TQUEUE_ARG data)
+ /* NB: never process the self-linked entry at the end */
+ break;
+ }
++
++ if (rx_limit-- < 2) {
++ early_stop = 1;
++ break;
++ }
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++ processed++;
++#endif
++
+ skb = bf->bf_skb;
+ if (skb == NULL) {
+ EPRINTF(sc, "Dropping; buffer contains NULL skbuff.\n");
+@@ -6450,6 +6537,7 @@ ath_rx_tasklet(TQUEUE_ARG data)
+ sc->sc_stats.ast_rx_phyerr++;
+ phyerr = rs->rs_phyerr & 0x1f;
+ sc->sc_stats.ast_rx_phy[phyerr]++;
++ goto rx_next;
+ }
+ if (rs->rs_status & HAL_RXERR_DECRYPT) {
+ /*
+@@ -6645,9 +6733,39 @@ rx_next:
+ 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.
++ */
++ 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;
++ local_irq_restore(flags);
++ ath_uapsd_processtriggers(sc, hw_tsf);
++ goto process_rx_again;
++ }
++ local_irq_restore(flags);
++ }
++
++#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
++ sc->sc_imask |= HAL_INT_RX;
++ ath_hal_intrset(ah, sc->sc_imask);
+
+ /* 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
+ }
+
+@@ -8298,12 +8416,24 @@ ath_tx_tasklet_q0(TQUEUE_ARG data)
+ {
+ 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))
+ ath_tx_processq(sc, &sc->sc_txq[0]);
+ if (txqactive(sc->sc_ah, sc->sc_cabq->axq_qnum))
+ ath_tx_processq(sc, sc->sc_cabq);
+
++ local_irq_save(flags);
++ if (sc->sc_isr & HAL_INT_TX) {
++ sc->sc_isr &= ~HAL_INT_TX;
++ local_irq_restore(flags);
++ goto process_tx_again;
++ }
++ sc->sc_imask |= HAL_INT_TX;
++ ath_hal_intrset(sc->sc_ah, sc->sc_imask);
++ local_irq_restore(flags);
++
+ netif_wake_queue(dev);
+
+ if (sc->sc_softled)
+@@ -8319,7 +8449,9 @@ ath_tx_tasklet_q0123(TQUEUE_ARG data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+ struct ath_softc *sc = dev->priv;
++ unsigned long flags;
+
++process_tx_again:
+ /*
+ * Process each active queue.
+ */
+@@ -8340,6 +8472,16 @@ ath_tx_tasklet_q0123(TQUEUE_ARG data)
+ if (sc->sc_uapsdq && txqactive(sc->sc_ah, sc->sc_uapsdq->axq_qnum))
+ ath_tx_processq(sc, sc->sc_uapsdq);
+
++ local_irq_save(flags);
++ if (sc->sc_isr & HAL_INT_TX) {
++ sc->sc_isr &= ~HAL_INT_TX;
++ local_irq_restore(flags);
++ goto process_tx_again;
++ }
++ sc->sc_imask |= HAL_INT_TX;
++ ath_hal_intrset(sc->sc_ah, sc->sc_imask);
++ local_irq_restore(flags);
++
+ netif_wake_queue(dev);
+
+ if (sc->sc_softled)
+@@ -8355,13 +8497,25 @@ ath_tx_tasklet(TQUEUE_ARG data)
+ struct net_device *dev = (struct net_device *)data;
+ struct ath_softc *sc = dev->priv;
+ unsigned int i;
++ unsigned long flags;
+
+ /* 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]);
+
++ local_irq_save(flags);
++ if (sc->sc_isr & HAL_INT_TX) {
++ sc->sc_isr &= ~HAL_INT_TX;
++ local_irq_restore(flags);
++ goto process_tx_again;
++ }
++ sc->sc_imask |= HAL_INT_TX;
++ ath_hal_intrset(sc->sc_ah, sc->sc_imask);
++ local_irq_restore(flags);
++
+ netif_wake_queue(dev);
+
+ if (sc->sc_softled)
+@@ -10296,9 +10450,9 @@ ath_change_mtu(struct net_device *dev, i
+ 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);
++ ath_poll_disable(dev);
+ error = ath_reset(dev);
+- tasklet_enable(&sc->sc_rxtq);
++ ath_poll_enable(dev);
+ }
+ ATH_UNLOCK(sc);
+
+--- 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
++#endif
++
+ /*
+ * Deduce if tasklets are available. If not then
+ * fall back to using the immediate work queue.
+@@ -616,6 +620,9 @@ struct ath_rp {
+ 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_softc {
+ struct ath_buf *sc_rxbufcur; /* current rx buffer */
+ u_int32_t *sc_rxlink; /* link ptr in last RX desc */
+ spinlock_t sc_rxbuflock;
+- struct ATH_TQ_STRUCT sc_rxtq; /* rx intr tasklet */
+ 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 */
+@@ -745,6 +751,7 @@ struct ath_softc {
+ 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 */
++ HAL_INT sc_isr; /* unmasked ISR state */
+ 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 */
+@@ -858,6 +865,8 @@ typedef void (*ath_callback) (struct ath
+ #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)
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -1198,7 +1198,7 @@ ieee80211_deliver_data(struct ieee80211_
+ /* attach vlan tag */
+ 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 @@ ieee80211_deliver_data(struct ieee80211_
+ 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 @@ forward_mgmt_to_app(struct ieee80211vap
+ 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 @@ ieee80211_input_monitor(struct ieee80211
+ 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 @@ int vlan_hwaccel_receive_skb_debug(stru
+ 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 @@ struct sk_buff * skb_copy_expand_debug(c
+ }
+
+ 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 ieee80211_skb_references(void);
+ 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 @@ struct sk_buff * skb_copy_expand_debug(c
+ #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 @@ struct sk_buff * skb_copy_expand_debug(c
+ 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 --git a/package/madwifi/patches/305-pureg_fix.patch b/package/madwifi/patches/305-pureg_fix.patch
new file mode 100644
index 000000000..8adb8a716
--- /dev/null
+++ b/package/madwifi/patches/305-pureg_fix.patch
@@ -0,0 +1,168 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -4158,7 +4158,9 @@ ath_calcrxfilter(struct ath_softc *sc)
+ rfilt |= HAL_RX_FILTER_PROM;
+ if (ic->ic_opmode == IEEE80211_M_STA ||
+ sc->sc_opmode == HAL_M_IBSS || /* NB: AHDEMO too */
+- (sc->sc_nostabeacons) || sc->sc_scanning)
++ (sc->sc_nostabeacons) || sc->sc_scanning ||
++ ((ic->ic_opmode == IEEE80211_M_HOSTAP) &&
++ (ic->ic_protmode != IEEE80211_PROT_NONE)))
+ rfilt |= HAL_RX_FILTER_BEACON;
+ if (sc->sc_nmonvaps > 0)
+ rfilt |= (HAL_RX_FILTER_CONTROL | HAL_RX_FILTER_BEACON |
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -346,11 +346,12 @@ ieee80211_input(struct ieee80211vap * va
+ 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_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
+@@ -366,18 +367,14 @@ ieee80211_input(struct ieee80211vap * va
+ vap->iv_stats.is_rx_wrongbss++;
+ goto out;
+ }
+- }
+ #else
+- if (!IEEE80211_ADDR_EQ(bssid, vap->iv_bssid) &&
+- !IEEE80211_ADDR_EQ(bssid, dev->broadcast)) {
+ /* not interested in */
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
+ bssid, NULL, "%s", "not to bss");
+ 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 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ u_int8_t *frm, *efrm;
+ 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;
+
+ if (ni_or_null == NULL)
+@@ -3096,11 +3093,15 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ * o station mode when associated (to collect state
+ * updates such as 802.11g slot time), or
+ * o adhoc mode (to discover neighbors)
++ * o ap mode in protection mode (beacons only)
+ * Frames otherwise received are discarded.
+ */
+ if (!((ic->ic_flags & IEEE80211_F_SCAN) ||
+ (vap->iv_opmode == IEEE80211_M_STA && ni->ni_associd) ||
+- vap->iv_opmode == IEEE80211_M_IBSS)) {
++ (vap->iv_opmode == IEEE80211_M_IBSS) ||
++ ((subtype == IEEE80211_FC0_SUBTYPE_BEACON) &&
++ (vap->iv_opmode == IEEE80211_M_HOSTAP) &&
++ (ic->ic_protmode != IEEE80211_PROT_NONE)))) {
+ vap->iv_stats.is_rx_mgtdiscard++;
+ return;
+ }
+@@ -3184,6 +3185,7 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ break;
+ }
+ scan.erp = frm[2];
++ has_erp = 1;
+ break;
+ case IEEE80211_ELEMID_RSN:
+ scan.rsn = frm;
+@@ -3421,6 +3423,20 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ ieee80211_bg_scan(vap);
+ return;
+ }
++
++ /* Update AP protection mode when in 11G mode */
++ if ((vap->iv_opmode == IEEE80211_M_HOSTAP) &&
++ 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)) {
++
++ ic->ic_flags |= IEEE80211_F_USEPROT;
++ ic->ic_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
++ }
++ }
++
+ /*
+ * If scanning, just pass information to the scan module.
+ */
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -383,10 +383,16 @@ ieee80211_create_ibss(struct ieee80211va
+ /* Update country ie information */
+ ieee80211_build_countryie(ic);
+
+- if (IEEE80211_IS_CHAN_HALF(chan))
++ if (IEEE80211_IS_CHAN_HALF(chan)) {
+ ni->ni_rates = ic->ic_sup_half_rates;
+- else if (IEEE80211_IS_CHAN_QUARTER(chan))
++ } else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
+ ni->ni_rates = ic->ic_sup_quarter_rates;
++ }
++
++ if ((vap->iv_flags & IEEE80211_F_PUREG) &&
++ IEEE80211_IS_CHAN_ANYG(chan)) {
++ ieee80211_setpuregbasicrates(&ni->ni_rates);
++ }
+
+ (void) ieee80211_sta_join1(PASS_NODE(ni));
+ }
+--- a/net80211/ieee80211_proto.c
++++ b/net80211/ieee80211_proto.c
+@@ -595,6 +595,28 @@ static const struct ieee80211_rateset ba
+ { 4, { 2, 4, 11, 22 } }, /* IEEE80211_MODE_TURBO_G (mixed b/g) */
+ };
+
++static const struct ieee80211_rateset basicpureg[] = {
++ { 7, {2, 4, 11, 22, 12, 24, 48 } },
++};
++
++/*
++ * Mark basic rates for the 11g rate table based on the pureg setting
++ */
++void
++ieee80211_setpuregbasicrates(struct ieee80211_rateset *rs)
++{
++ int i, j;
++
++ for (i = 0; i < rs->rs_nrates; i++) {
++ rs->rs_rates[i] &= IEEE80211_RATE_VAL;
++ for (j = 0; j < basicpureg[0].rs_nrates; j++)
++ if (basicpureg[0].rs_rates[j] == rs->rs_rates[i]) {
++ rs->rs_rates[i] |= IEEE80211_RATE_BASIC;
++ break;
++ }
++ }
++}
++
+ /*
+ * Mark the basic rates for the 11g rate table based on the
+ * specified mode. For 11b compatibility we mark only 11b
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -708,6 +708,7 @@ int ieee80211_media_setup(struct ieee802
+ 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.
diff --git a/package/madwifi/patches/309-micfail_detect.patch b/package/madwifi/patches/309-micfail_detect.patch
new file mode 100644
index 000000000..ca4103a20
--- /dev/null
+++ b/package/madwifi/patches/309-micfail_detect.patch
@@ -0,0 +1,321 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -6457,6 +6457,7 @@ ath_rx_poll(struct net_device *dev, int
+ int type;
+ u_int phyerr;
+ u_int processed = 0, early_stop = 0;
++ u_int mic_fail = 0;
+
+ DPRINTF(sc, ATH_DEBUG_RX_PROC, "invoked\n");
+ process_rx_again:
+@@ -6558,24 +6559,8 @@ process_rx_again:
+ }
+ if (rs->rs_status & HAL_RXERR_MIC) {
+ sc->sc_stats.ast_rx_badmic++;
+- /*
+- * Do minimal work required to hand off
+- * the 802.11 header for notification.
+- */
+- /* XXX frag's and QoS frames */
+- if (len >= sizeof (struct ieee80211_frame)) {
+- bus_dma_sync_single(sc->sc_bdev,
+- bf->bf_skbaddr, len,
+- BUS_DMA_FROMDEVICE);
+-#if 0
+-/* XXX revalidate MIC, lookup ni to find VAP */
+- ieee80211_notify_michael_failure(ic,
+- (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
+@@ -6614,8 +6599,9 @@ rx_accept:
+ /*
+ * Finished monitor mode handling, now reject
+ * error frames before passing to other vaps
++ * Ignore MIC failures here, as we need to recheck them
+ */
+- if (rs->rs_status != 0) {
++ if (rs->rs_status & ~(HAL_RXERR_MIC | HAL_RXERR_DECRYPT)) {
+ ieee80211_dev_kfree_skb(&skb);
+ goto rx_next;
+ }
+@@ -6623,6 +6609,26 @@ rx_accept:
+ /* remove the CRC */
+ skb_trim(skb, skb->len - IEEE80211_CRC_LEN);
+
++ if (mic_fail) {
++ /* Ignore control frames which are reported with mic error */
++ if ((((struct ieee80211_frame *)skb->data)->i_fc[0] &
++ IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
++ goto drop_micfail;
++
++ ni = ieee80211_find_rxnode(ic, (const struct ieee80211_frame_min *) skb->data);
++
++ if (ni && ni->ni_table) {
++ ieee80211_check_mic(ni, skb);
++ ieee80211_unref_node(&ni);
++ }
++
++drop_micfail:
++ dev_kfree_skb_any(skb);
++ skb = NULL;
++ mic_fail = 0;
++ goto rx_next;
++ }
++
+ /*
+ * From this point on we assume the frame is at least
+ * as large as ieee80211_frame_min; verify that.
+@@ -6635,6 +6641,7 @@ rx_accept:
+ 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_setkey(struct ieee80211_
+ static int ccmp_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t);
+ static int ccmp_decap(struct ieee80211_key *, struct sk_buff *, int);
+ static int ccmp_enmic(struct ieee80211_key *, struct sk_buff *, int);
+-static int ccmp_demic(struct ieee80211_key *, struct sk_buff *, int);
++static int ccmp_demic(struct ieee80211_key *, struct sk_buff *, int, int);
+
+ static const struct ieee80211_cipher ccmp = {
+ .ic_name = "AES-CCM",
+@@ -314,7 +314,7 @@ ccmp_decap(struct ieee80211_key *k, stru
+ * Verify and strip MIC from the frame.
+ */
+ static int
+-ccmp_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen)
++ccmp_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen, int force)
+ {
+ return 1;
+ }
+--- a/net80211/ieee80211_crypto.h
++++ b/net80211/ieee80211_crypto.h
+@@ -145,7 +145,7 @@ struct ieee80211_cipher {
+ 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 (*ic_demic)(struct ieee80211_key *, struct sk_buff *, int, int);
+ };
+ extern const struct ieee80211_cipher ieee80211_cipher_none;
+
+@@ -163,10 +163,10 @@ struct ieee80211_key *ieee80211_crypto_d
+ */
+ static __inline int
+ ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k,
+- struct sk_buff *skb, int hdrlen)
++ 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) : 1);
++ return (cip->ic_miclen > 0 ? cip->ic_demic(k, skb, hdrlen, force) : 1);
+ }
+
+ /*
+--- a/net80211/ieee80211_crypto_none.c
++++ b/net80211/ieee80211_crypto_none.c
+@@ -52,7 +52,7 @@ static int none_setkey(struct ieee80211_
+ static int none_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t);
+ static int none_decap(struct ieee80211_key *, struct sk_buff *, int);
+ static int none_enmic(struct ieee80211_key *, struct sk_buff *, int);
+-static int none_demic(struct ieee80211_key *, struct sk_buff *, int);
++static int none_demic(struct ieee80211_key *, struct sk_buff *, int, int);
+
+ const struct ieee80211_cipher ieee80211_cipher_none = {
+ .ic_name = "NONE",
+@@ -137,7 +137,7 @@ none_enmic(struct ieee80211_key *k, stru
+ }
+
+ static int
+-none_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen)
++none_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen, int force)
+ {
+ struct ieee80211vap *vap = k->wk_private;
+
+--- a/net80211/ieee80211_crypto_tkip.c
++++ b/net80211/ieee80211_crypto_tkip.c
+@@ -57,7 +57,7 @@ static int tkip_setkey(struct ieee80211_
+ static int tkip_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t);
+ static int tkip_enmic(struct ieee80211_key *, struct sk_buff *, int);
+ static int tkip_decap(struct ieee80211_key *, struct sk_buff *, int);
+-static int tkip_demic(struct ieee80211_key *, struct sk_buff *, int);
++static int tkip_demic(struct ieee80211_key *, struct sk_buff *, int, int);
+
+ static const struct ieee80211_cipher tkip = {
+ .ic_name = "TKIP",
+@@ -339,7 +339,7 @@ tkip_decap(struct ieee80211_key *k, stru
+ * Verify and strip MIC from the frame.
+ */
+ static int
+-tkip_demic(struct ieee80211_key *k, struct sk_buff *skb0, int hdrlen)
++tkip_demic(struct ieee80211_key *k, struct sk_buff *skb0, int hdrlen, int force)
+ {
+ struct tkip_ctx *ctx = k->wk_private;
+ struct sk_buff *skb;
+@@ -355,7 +355,7 @@ tkip_demic(struct ieee80211_key *k, stru
+ }
+ wh = (struct ieee80211_frame *) skb0->data;
+ /* NB: skb left pointing at last in chain */
+- if (k->wk_flags & IEEE80211_KEY_SWMIC) {
++ if ((k->wk_flags & IEEE80211_KEY_SWMIC) || force) {
+ struct ieee80211vap *vap = ctx->tc_vap;
+ u8 mic[IEEE80211_WEP_MICLEN];
+ u8 mic0[IEEE80211_WEP_MICLEN];
+--- a/net80211/ieee80211_crypto_wep.c
++++ b/net80211/ieee80211_crypto_wep.c
+@@ -54,7 +54,7 @@ static int wep_setkey(struct ieee80211_k
+ static int wep_encap(struct ieee80211_key *, struct sk_buff *, u_int8_t);
+ static int wep_decap(struct ieee80211_key *, struct sk_buff *, int);
+ static int wep_enmic(struct ieee80211_key *, struct sk_buff *, int);
+-static int wep_demic(struct ieee80211_key *, struct sk_buff *, int);
++static int wep_demic(struct ieee80211_key *, struct sk_buff *, int, int);
+
+ static const struct ieee80211_cipher wep = {
+ .ic_name = "WEP",
+@@ -244,7 +244,7 @@ wep_decap(struct ieee80211_key *k, struc
+ * Verify and strip MIC from the frame.
+ */
+ static int
+-wep_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen)
++wep_demic(struct ieee80211_key *k, struct sk_buff *skb, int hdrlen, int force)
+ {
+ return 1;
+ }
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -669,7 +669,7 @@ ieee80211_input(struct ieee80211vap * va
+ * Next strip any MSDU crypto bits.
+ */
+ if (key != NULL &&
+- !ieee80211_crypto_demic(vap, key, skb, hdrspace)) {
++ !ieee80211_crypto_demic(vap, key, skb, hdrspace, 0)) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
+ ni->ni_macaddr, "data", "%s", "demic error");
+ IEEE80211_NODE_STAT(ni, rx_demicfail);
+@@ -4293,6 +4293,47 @@ ath_eth_type_trans(struct sk_buff *skb,
+ }
+ #endif
+
++/*
++ * Process a frame w/ hw detected MIC failure.
++ * The frame will be dropped in any case.
++ */
++void
++ieee80211_check_mic(struct ieee80211_node *ni, struct sk_buff *skb)
++{
++ struct ieee80211vap *vap = ni->ni_vap;
++
++ struct ieee80211_frame *wh;
++ struct ieee80211_key *key;
++ int hdrspace;
++ struct ieee80211com *ic = vap->iv_ic;
++
++ if (skb->len < sizeof(struct ieee80211_frame_min)) {
++ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
++ ni->ni_macaddr, NULL,
++ "too short (1): len %u", skb->len);
++ vap->iv_stats.is_rx_tooshort++;
++ return;
++ }
++
++ wh = (struct ieee80211_frame *)skb->data;
++
++ hdrspace = ieee80211_hdrspace(ic, wh);
++ key = ieee80211_crypto_decap(ni, skb, hdrspace);
++ if (key == NULL) {
++ /* NB: stats+msgs handled in crypto_decap */
++ IEEE80211_NODE_STAT(ni, rx_wepfail);
++ return;
++ }
++
++ if (!ieee80211_crypto_demic(vap, key, skb, hdrspace, 1)) {
++ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
++ ni->ni_macaddr, "data", "%s", "demic error");
++ IEEE80211_NODE_STAT(ni, rx_demicfail);
++ }
++ return;
++}
++EXPORT_SYMBOL(ieee80211_check_mic);
++
+ #ifdef IEEE80211_DEBUG
+ /*
+ * Debugging support.
+--- a/net80211/ieee80211_proto.h
++++ b/net80211/ieee80211_proto.h
+@@ -90,6 +90,7 @@ int ieee80211_iserp_rateset(struct ieee8
+ 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.
+--- a/net80211/ieee80211_linux.c
++++ b/net80211/ieee80211_linux.c
+@@ -337,8 +337,8 @@ ieee80211_notify_replay_failure(struct i
+ /* TODO: needed parameters: count, keyid, key type, src address, TSC */
+ snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=" MAC_FMT ")", tag,
+ k->wk_keyix,
+- IEEE80211_IS_MULTICAST(wh->i_addr1) ? "broad" : "uni",
+- MAC_ADDR(wh->i_addr1));
++ IEEE80211_IS_MULTICAST(wh->i_addr2) ? "broad" : "uni",
++ MAC_ADDR(wh->i_addr2));
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = strlen(buf);
+ wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
+--- a/net80211/ieee80211_output.c
++++ b/net80211/ieee80211_output.c
+@@ -1074,13 +1074,16 @@ ieee80211_encap(struct ieee80211_node *n
+ cip = (struct ieee80211_cipher *) key->wk_cipher;
+ ciphdrsize = cip->ic_header;
+ tailsize += (cip->ic_trailer + cip->ic_miclen);
++
++ /* add the 8 bytes MIC length */
++ if (cip->ic_cipher == IEEE80211_CIPHER_TKIP)
++ pktlen += IEEE80211_WEP_MICLEN;
+ }
+
+ pdusize = vap->iv_fragthreshold - (hdrsize_nopad + ciphdrsize);
+ fragcnt = *framecnt =
+- ((pktlen - (hdrsize_nopad + ciphdrsize)) / pdusize) +
+- (((pktlen - (hdrsize_nopad + ciphdrsize)) %
+- pdusize == 0) ? 0 : 1);
++ ((pktlen - hdrsize_nopad) / pdusize) +
++ (((pktlen - hdrsize_nopad) % pdusize == 0) ? 0 : 1);
+
+ /*
+ * Allocate sk_buff for each subsequent fragment; First fragment
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -2264,11 +2264,13 @@ ieee80211_node_leave(struct ieee80211_no
+ /* 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_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_locked(nt, ni);
++ IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
++ }
+
+ /*
+ * If node wasn't previously associated all
diff --git a/package/madwifi/patches/310-noise_get.patch b/package/madwifi/patches/310-noise_get.patch
new file mode 100644
index 000000000..d8821583b
--- /dev/null
+++ b/package/madwifi/patches/310-noise_get.patch
@@ -0,0 +1,55 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -1699,8 +1699,6 @@ ath_uapsd_processtriggers(struct ath_sof
+ * 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);
+@@ -8975,6 +8973,7 @@ ath_calibrate(unsigned long arg)
+ 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) {
+@@ -9043,6 +9042,7 @@ ath_set_channel(struct ieee80211com *ic)
+ 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
+@@ -9311,6 +9311,7 @@ ath_newstate(struct ieee80211vap *vap, e
+ }
+
+ 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 @@ get_sta_info(void *arg, struct ieee80211
+ 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 @@ struct ieee80211req_sta_info {
+ 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 --git a/package/madwifi/patches/311-bssid_alloc.patch b/package/madwifi/patches/311-bssid_alloc.patch
new file mode 100644
index 000000000..005a67738
--- /dev/null
+++ b/package/madwifi/patches/311-bssid_alloc.patch
@@ -0,0 +1,11 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -1354,7 +1354,7 @@ ath_vap_create(struct ieee80211com *ic,
+ 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 --git a/package/madwifi/patches/312-erpupdate.patch b/package/madwifi/patches/312-erpupdate.patch
new file mode 100644
index 000000000..f878acd8f
--- /dev/null
+++ b/package/madwifi/patches/312-erpupdate.patch
@@ -0,0 +1,68 @@
+--- a/net80211/ieee80211_beacon.c
++++ b/net80211/ieee80211_beacon.c
+@@ -542,10 +542,10 @@ ieee80211_beacon_update(struct ieee80211
+ 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 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ /* 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 @@ ieee80211_node_join_11g(struct ieee80211
+ }
+
+ /* 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_node_leave_11g(struct ieee8021
+ 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 @@ ieee80211_node_leave_11g(struct ieee8021
+ 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 --git a/package/madwifi/patches/317-bmask.patch b/package/madwifi/patches/317-bmask.patch
new file mode 100644
index 000000000..3355dc722
--- /dev/null
+++ b/package/madwifi/patches/317-bmask.patch
@@ -0,0 +1,13 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -8689,6 +8689,10 @@ ath_startrecv(struct ath_softc *sc)
+
+ 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 --git a/package/madwifi/patches/323-dfs_optional.patch b/package/madwifi/patches/323-dfs_optional.patch
new file mode 100644
index 000000000..2336d7484
--- /dev/null
+++ b/package/madwifi/patches/323-dfs_optional.patch
@@ -0,0 +1,38 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -1778,17 +1778,14 @@ ath_uapsd_processtriggers(struct ath_sof
+ * 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
+@@ -265,7 +265,7 @@ int ath_radar_update(struct ath_softc *s
+ 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 --git a/package/madwifi/patches/324-alignment.patch b/package/madwifi/patches/324-alignment.patch
new file mode 100644
index 000000000..c01135f3e
--- /dev/null
+++ b/package/madwifi/patches/324-alignment.patch
@@ -0,0 +1,19 @@
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -1275,14 +1275,8 @@ ieee80211_decap(struct ieee80211vap *vap
+ 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 --git a/package/madwifi/patches/325-channel_spam.patch b/package/madwifi/patches/325-channel_spam.patch
new file mode 100644
index 000000000..e34b7a409
--- /dev/null
+++ b/package/madwifi/patches/325-channel_spam.patch
@@ -0,0 +1,28 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -9792,7 +9792,9 @@ ath_getchannels(struct net_device *dev,
+ /*
+ * 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];
+@@ -9819,6 +9821,7 @@ ath_getchannels(struct net_device *dev,
+ 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",
+@@ -9907,6 +9910,7 @@ ath_getchannels(struct net_device *dev,
+ (c->privFlags & 0x0080 ?
+ " PF & (1 << 7)" : "")
+ );
++#endif
+ }
+ ic->ic_nchans = nchan;
+ kfree(chans);
diff --git a/package/madwifi/patches/327-queue.patch b/package/madwifi/patches/327-queue.patch
new file mode 100644
index 000000000..228aae349
--- /dev/null
+++ b/package/madwifi/patches/327-queue.patch
@@ -0,0 +1,40 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -8438,8 +8438,6 @@ process_tx_again:
+ 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);
+ }
+@@ -8486,8 +8484,6 @@ process_tx_again:
+ 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);
+ }
+@@ -8520,8 +8516,6 @@ process_tx_again:
+ 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 @@ ieee80211_deliver_data(struct ieee80211_
+ (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 --git a/package/madwifi/patches/330-beaconcal.patch b/package/madwifi/patches/330-beaconcal.patch
new file mode 100644
index 000000000..a338dc743
--- /dev/null
+++ b/package/madwifi/patches/330-beaconcal.patch
@@ -0,0 +1,166 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -397,6 +397,7 @@ static int countrycode = -1;
+ 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 @@ static struct notifier_block ath_event_b
+ };
+
+ #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(autocreate, "s");
+ 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);
+@@ -2600,7 +2603,8 @@ ath_stop_locked(struct net_device *dev)
+ }
+ 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) {
+@@ -2617,6 +2621,20 @@ ath_stop_locked(struct net_device *dev)
+ 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
+@@ -2742,6 +2760,12 @@ ath_reset(struct net_device *dev)
+ 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.
+ */
+@@ -5154,6 +5178,10 @@ ath_beacon_send(struct ath_softc *sc, in
+ "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))) {
++ sc->sc_cal_ch.expires = jiffies + msecs_to_jiffies(10);
++ add_timer(&sc->sc_cal_ch);
++ }
+
+ sc->sc_stats.ast_be_xmit++; /* XXX per-VAP? */
+ }
+@@ -5403,6 +5431,7 @@ ath_beacon_config(struct ath_softc *sc,
+ 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)
+@@ -5414,8 +5443,11 @@ ath_beacon_config(struct ath_softc *sc,
+ */
+ 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));
+@@ -8879,6 +8911,9 @@ ath_chan_set(struct ath_softc *sc, struc
+ /* 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.
+@@ -8988,8 +9023,11 @@ ath_calibrate(unsigned long arg)
+ 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
+@@ -9096,7 +9134,8 @@ ath_newstate(struct ieee80211vap *vap, e
+ 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 */
+@@ -9321,7 +9360,8 @@ ath_newstate(struct ieee80211vap *vap, e
+ "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... */
+@@ -9364,7 +9404,7 @@ done:
+ 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 ath_softc {
+ 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 --git a/package/madwifi/patches/331-memory_alloc.patch b/package/madwifi/patches/331-memory_alloc.patch
new file mode 100644
index 000000000..6b01d79c0
--- /dev/null
+++ b/package/madwifi/patches/331-memory_alloc.patch
@@ -0,0 +1,36 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -3320,17 +3320,18 @@ ath_hardstart(struct sk_buff *skb, struc
+ * 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
+@@ -3601,6 +3602,8 @@ ath_mgtstart(struct ieee80211com *ic, st
+ sc->sc_stats.ast_tx_mgmt++;
+ return 0;
+ bad:
++ if (skb)
++ ieee80211_dev_kfree_skb(&skb);
+ ath_return_txbuf(sc, &bf);
+ return error;
+ }
diff --git a/package/madwifi/patches/332-reset_beacons.patch b/package/madwifi/patches/332-reset_beacons.patch
new file mode 100644
index 000000000..b776426f2
--- /dev/null
+++ b/package/madwifi/patches/332-reset_beacons.patch
@@ -0,0 +1,11 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -8922,7 +8922,7 @@ ath_chan_set(struct ath_softc *sc, struc
+ * 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 --git a/package/madwifi/patches/333-apscan_mode.patch b/package/madwifi/patches/333-apscan_mode.patch
new file mode 100644
index 000000000..877eea6ce
--- /dev/null
+++ b/package/madwifi/patches/333-apscan_mode.patch
@@ -0,0 +1,15 @@
+--- a/net80211/ieee80211_scan_ap.c
++++ b/net80211/ieee80211_scan_ap.c
+@@ -783,12 +783,6 @@ pick_channel(struct ieee80211_scan_state
+ /* 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 --git a/package/madwifi/patches/334-input.patch b/package/madwifi/patches/334-input.patch
new file mode 100644
index 000000000..7c1336701
--- /dev/null
+++ b/package/madwifi/patches/334-input.patch
@@ -0,0 +1,12 @@
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -950,6 +950,9 @@ ieee80211_input_all(struct ieee80211com
+ 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 --git a/package/madwifi/patches/340-maxrate.patch b/package/madwifi/patches/340-maxrate.patch
new file mode 100644
index 000000000..ae93f02d2
--- /dev/null
+++ b/package/madwifi/patches/340-maxrate.patch
@@ -0,0 +1,98 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -1307,6 +1307,7 @@ ath_vap_create(struct ieee80211com *ic,
+ 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 @@ ath_rate_ctl_reset(struct ath_softc *sc,
+ 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 @@ ath_rate_ctl_reset(struct ath_softc *sc,
+ }
+ 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 @@ enum {
+ 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 ieee80211vap {
+ 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 */
++ u_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 @@ ieee80211_ioctl_setparam(struct net_devi
+ 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 @@ ieee80211_ioctl_getparam(struct net_devi
+ else
+ param[0] = 0;
+ break;
++ case IEEE80211_PARAM_MAXRATE:
++ param[0] = vap->iv_maxrateindex;
++ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+@@ -5610,6 +5619,10 @@ static const struct iw_priv_args ieee802
+ 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 --git a/package/madwifi/patches/341-minrate.patch b/package/madwifi/patches/341-minrate.patch
new file mode 100644
index 000000000..cc04ae074
--- /dev/null
+++ b/package/madwifi/patches/341-minrate.patch
@@ -0,0 +1,114 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -1308,6 +1308,7 @@ ath_vap_create(struct ieee80211com *ic,
+ 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 @@ ath_rate_ctl_reset(struct ath_softc *sc,
+ 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 @@ ath_rate_ctl_reset(struct ath_softc *sc,
+ 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 @@ ath_rate_ctl_reset(struct ath_softc *sc,
+ 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 @@ enum {
+ 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, /* Minimum rate (by table index) */
+ };
+
+ #define SIOCG80211STATS (SIOCDEVPRIVATE+2)
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -282,6 +282,7 @@ struct ieee80211vap {
+ 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 */
+ u_int iv_maxrateindex;
++ u_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 @@ ieee80211_ioctl_setparam(struct net_devi
+ 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 @@ ieee80211_ioctl_getparam(struct net_devi
+ 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 @@ static const struct iw_priv_args ieee802
+ 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 --git a/package/madwifi/patches/342-performance.patch b/package/madwifi/patches/342-performance.patch
new file mode 100644
index 000000000..88cec182d
--- /dev/null
+++ b/package/madwifi/patches/342-performance.patch
@@ -0,0 +1,263 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -3239,7 +3239,6 @@ ath_hardstart(struct sk_buff *skb, struc
+ 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;
+@@ -3251,6 +3250,7 @@ ath_hardstart(struct sk_buff *skb, struc
+ */
+ int requeue = 0;
+ #ifdef ATH_SUPERG_FF
++ struct ether_header *eh;
+ unsigned int pktlen;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_node *an;
+@@ -3316,27 +3316,9 @@ ath_hardstart(struct sk_buff *skb, struc
+ 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 @@ ieee80211_hardstart(struct sk_buff *skb,
+ * 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 @@ ieee80211_skbhdr_adjust(struct ieee80211
+ 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 @@ ieee80211_skbhdr_adjust(struct ieee80211
+ 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;
+
+-#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);
++ if (skb_cloned(skb) || (need_headroom > 0) ||
++ (!isff && (need_tailroom > 0))) {
+
+- return NULL;
++ 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;
+ }
++ }
+
+- /* first skb header */
+- if (skb_headroom(skb) < need_headroom) {
+- struct sk_buff *tmp = skb;
+- skb = skb_realloc_headroom(skb, need_headroom);
+- if (skb == NULL) {
+- 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. */
+- }
++#ifdef ATH_SUPERG_FF
++ if (isff) {
++ inter_headroom -= skb_headroom(skb2);
++ if (inter_headroom < 0)
++ inter_headroom = 0;
++ if ((skb_cloned(skb2) ||
++ (inter_headroom > 0) || (need_tailroom > 0))) {
+
+- /* 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);
++ if (pskb_expand_head(skb2, inter_headroom,
++ need_tailroom, GFP_ATOMIC)) {
+ 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 @@ ieee80211_input(struct ieee80211vap * va
+ 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 @@ ieee80211_input(struct ieee80211vap * va
+ 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 @@ ieee80211_input(struct ieee80211vap * va
+ /* 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 @@ ieee80211_deliver_data(struct ieee80211_
+
+ 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 --git a/package/madwifi/patches/343-txqueue_races.patch b/package/madwifi/patches/343-txqueue_races.patch
new file mode 100644
index 000000000..a2b14d69a
--- /dev/null
+++ b/package/madwifi/patches/343-txqueue_races.patch
@@ -0,0 +1,34 @@
+Merged from madwifi trunk r3551, r3552
+
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -8253,6 +8253,17 @@ ath_tx_processq(struct ath_softc *sc, st
+ 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 @@ struct ath_vap {
+ } 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 --git a/package/madwifi/patches/344-minstrel_failcnt.patch b/package/madwifi/patches/344-minstrel_failcnt.patch
new file mode 100644
index 000000000..ea92dc4d6
--- /dev/null
+++ b/package/madwifi/patches/344-minstrel_failcnt.patch
@@ -0,0 +1,11 @@
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -475,7 +475,7 @@ ath_rate_tx_complete(struct ath_softc *s
+ /* '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 --git a/package/madwifi/patches/345-minstrel_sampling.patch b/package/madwifi/patches/345-minstrel_sampling.patch
new file mode 100644
index 000000000..63fcb8a61
--- /dev/null
+++ b/package/madwifi/patches/345-minstrel_sampling.patch
@@ -0,0 +1,80 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -8103,6 +8103,7 @@ ath_tx_start(struct net_device *dev, str
+ 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 @@ struct ath_buf {
+ 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 @@ ath_rate_findrate(struct ath_softc *sc,
+ 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 @@ ath_rate_get_mrr(struct ath_softc *sc, s
+ 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 @@ ath_rate_tx_complete(struct ath_softc *s
+ 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 @@ struct ieee80211_mrr {
+ int retries2;
+ int rate3;
+ int retries3;
++ int privflags;
+ };
+
+ struct ieee80211_rate_ops {
diff --git a/package/madwifi/patches/346-protmode_trig.patch b/package/madwifi/patches/346-protmode_trig.patch
new file mode 100644
index 000000000..5b5cec6e9
--- /dev/null
+++ b/package/madwifi/patches/346-protmode_trig.patch
@@ -0,0 +1,135 @@
+--- a/net80211/ieee80211.c
++++ b/net80211/ieee80211.c
+@@ -333,7 +333,9 @@ ieee80211_ifattach(struct ieee80211com *
+ 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_recv_mgmt(struct ieee80211vap
+ 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 @@ enum {
+ 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, /* Minimum 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 @@ struct ieee80211com {
+ 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_ioctl_setparam(struct net_devi
+ 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 @@ ieee80211_ioctl_getparam(struct net_devi
+ 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 @@ static const struct iw_priv_args ieee802
+ 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_node_timeout(unsigned long arg
+
+ 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 --git a/package/madwifi/patches/347-tuning.patch b/package/madwifi/patches/347-tuning.patch
new file mode 100644
index 000000000..1a73c4274
--- /dev/null
+++ b/package/madwifi/patches/347-tuning.patch
@@ -0,0 +1,99 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -10276,11 +10276,11 @@ ath_setcurmode(struct ath_softc *sc, enu
+ 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 @@ static inline struct net_device *_alloc_
+ #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 @@ calc_usecs_unicast_packet(struct ath_sof
+ 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 @@ calc_usecs_unicast_packet(struct ath_sof
+ 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 @@ struct minstrel_node {
+ #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 @@ calc_usecs_unicast_packet(struct ath_sof
+ 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 @@ calc_usecs_unicast_packet(struct ath_sof
+ 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 @@ struct sample_node {
+ #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 --git a/package/madwifi/patches/348-ackcts.patch b/package/madwifi/patches/348-ackcts.patch
new file mode 100644
index 000000000..42b6fe261
--- /dev/null
+++ b/package/madwifi/patches/348-ackcts.patch
@@ -0,0 +1,38 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -2723,6 +2723,9 @@ ar_device(int devid)
+ 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 */
+@@ -10791,8 +10794,13 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+ 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 @@ struct ath_softc {
+ 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 --git a/package/madwifi/patches/349-reset.patch b/package/madwifi/patches/349-reset.patch
new file mode 100644
index 000000000..06e3fa86f
--- /dev/null
+++ b/package/madwifi/patches/349-reset.patch
@@ -0,0 +1,12 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -8864,8 +8864,7 @@ ath_chan_set(struct ath_softc *sc, struc
+ * 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 --git a/package/madwifi/patches/350-wisoc_softled.patch b/package/madwifi/patches/350-wisoc_softled.patch
new file mode 100644
index 000000000..dae9f218d
--- /dev/null
+++ b/package/madwifi/patches/350-wisoc_softled.patch
@@ -0,0 +1,11 @@
+--- a/ath/if_ath_ahb.c
++++ b/ath/if_ath_ahb.c
+@@ -245,6 +245,8 @@ init_ath_wmac(u_int16_t devid, u_int16_t
+ 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 --git a/package/madwifi/patches/351-scanlist.patch b/package/madwifi/patches/351-scanlist.patch
new file mode 100644
index 000000000..c11f28e39
--- /dev/null
+++ b/package/madwifi/patches/351-scanlist.patch
@@ -0,0 +1,904 @@
+--- a/net80211/ieee80211_scan_sta.c
++++ b/net80211/ieee80211_scan_sta.c
+@@ -317,147 +317,6 @@ found:
+ #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 @@ sta_start(struct ieee80211_scan_state *s
+ {
+ 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 @@ match_bss(struct ieee80211vap *vap,
+ 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 @@ static const struct ieee80211_scanner st
+ .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 @@ static const struct ieee80211_scanner ad
+ .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 @@ ieee80211_ifattach(struct ieee80211com *
+ ("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;
+@@ -1447,10 +1452,6 @@ ieee80211_media_change(struct net_device
+ vap->iv_fixed_rate = newrate; /* fixed TX rate */
+ error = -ENETRESET;
+ }
+- if (vap->iv_des_mode != newmode) {
+- vap->iv_des_mode = newmode; /* desired PHY mode */
+- error = -ENETRESET;
+- }
+ return error;
+ }
+ EXPORT_SYMBOL(ieee80211_media_change);
+--- a/net80211/_ieee80211.h
++++ b/net80211/_ieee80211.h
+@@ -132,6 +132,11 @@ enum ieee80211_scanmode {
+ 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 @@ struct ieee80211_channel {
+ 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 @@ struct ieee80211req_scan_result {
+ #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
+@@ -105,11 +105,6 @@ struct scan_entry {
+ };
+
+ struct ap_state {
+- unsigned int as_vap_desired_mode; /* Used for channel selection,
+- * vap->iv_des_mode */
+- unsigned int as_required_mode; /* Used for channel selection,
+- * filtered version of
+- * as_vap_desired_mode */
+ int as_maxrssi[IEEE80211_CHAN_MAX]; /* Used for channel selection */
+
+ /* These fields are just for scan caching for returning responses to
+@@ -129,131 +124,7 @@ struct ap_state {
+
+ 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 +198,6 @@ saveie(u_int8_t **iep, const u_int8_t *i
+ 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,90 +206,15 @@ ap_start(struct ieee80211_scan_state *ss
+ {
+ 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;
+
+ SCAN_AP_LOCK_IRQ(as);
+ ic = vap->iv_ic;
+ /* 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;
+-
+- /* 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;
++ ieee80211_scan_add_channels(ic, ss, vap->iv_des_mode);
+
+- /* 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 */
+@@ -761,18 +534,6 @@ pick_channel(struct ieee80211_scan_state
+ 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)
+- continue;
+-
+ if ((ic->ic_bsschan != NULL) &&
+ (ic->ic_bsschan != IEEE80211_CHAN_ANYC)) {
+
+--- a/net80211/ieee80211_scan.c
++++ b/net80211/ieee80211_scan.c
+@@ -958,6 +958,80 @@ ieee80211_scan_flush(struct ieee80211com
+ }
+ }
+
++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_register(enum iee
+ 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 @@ ieee80211_ioctl_kickmac(struct net_devic
+ 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 @@ static const struct iw_priv_args ieee802
+ 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 @@ static const iw_handler ieee80211_priv_h
+ 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 --git a/package/madwifi/patches/352-ani_fix.patch b/package/madwifi/patches/352-ani_fix.patch
new file mode 100644
index 000000000..938d11c62
--- /dev/null
+++ b/package/madwifi/patches/352-ani_fix.patch
@@ -0,0 +1,265 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -1014,9 +1014,7 @@ ath_attach(u_int16_t devid, struct net_d
+ */
+ 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 @@ ath_attach(u_int16_t devid, struct net_d
+ 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);
+@@ -2428,6 +2431,43 @@ ath_chan2flags(struct ieee80211_channel
+ 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
+ */
+@@ -2493,8 +2533,7 @@ ath_init(struct net_device *dev)
+ 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
+@@ -2530,7 +2569,7 @@ ath_init(struct net_device *dev)
+ * 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);
+
+@@ -2787,9 +2826,7 @@ ath_reset(struct net_device *dev)
+ 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);
+@@ -4174,6 +4211,8 @@ ath_calcrxfilter(struct ath_softc *sc)
+ 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;
+@@ -6526,9 +6565,6 @@ process_rx_again:
+ 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) {
+ /*
+@@ -8876,9 +8912,7 @@ ath_chan_set(struct ath_softc *sc, struc
+ 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);
+@@ -10655,9 +10689,54 @@ enum {
+ 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;
+@@ -10843,6 +10922,11 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+ 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;
+@@ -10909,6 +10993,11 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+ 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;
+@@ -11086,6 +11175,24 @@ static const ctl_table ath_sysctl_templa
+ .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 }
+ };
+
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -693,6 +693,10 @@ struct ath_softc {
+ 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 */
+--- a/ath/if_ath_hal.h
++++ b/ath/if_ath_hal.h
+@@ -67,14 +67,14 @@ static inline HAL_POWER_MODE ath_hal_get
+
+ 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 --git a/package/madwifi/patches/353-devid.patch b/package/madwifi/patches/353-devid.patch
new file mode 100644
index 000000000..ee149ff0c
--- /dev/null
+++ b/package/madwifi/patches/353-devid.patch
@@ -0,0 +1,19 @@
+--- a/ath/if_ath_pci.c
++++ b/ath/if_ath_pci.c
+@@ -114,11 +114,15 @@ static struct pci_device_id ath_pci_id_t
+ { 0x168c, 0x0023, PCI_ANY_ID, PCI_ANY_ID },
+ { 0x168c, 0x0024, PCI_ANY_ID, PCI_ANY_ID },
+ { 0x168c, 0x9013, PCI_ANY_ID, PCI_ANY_ID }, /* sonicwall */
++ { 0x168c, 0xff16, PCI_ANY_ID, PCI_ANY_ID },
++ { 0x168c, 0xff1a, PCI_ANY_ID, PCI_ANY_ID },
+ { 0 }
+ };
+
+ static u16 ath_devidmap[][2] = {
+- { 0x9013, 0x0013 }
++ { 0x9013, 0x0013 },
++ { 0xff16, 0x0013 },
++ { 0xff1a, 0x001a }
+ };
+
+ static int
diff --git a/package/madwifi/patches/354-lantiq_eeprom.patch b/package/madwifi/patches/354-lantiq_eeprom.patch
new file mode 100644
index 000000000..59036b1b4
--- /dev/null
+++ b/package/madwifi/patches/354-lantiq_eeprom.patch
@@ -0,0 +1,95 @@
+--- a/ath_hal/ah_os.c
++++ b/ath_hal/ah_os.c
+@@ -343,6 +343,46 @@ EXPORT_SYMBOL(ath_hal_func);
+ * NB: see the comments in ah_osdep.h about byte-swapping register
+ * reads and writes to understand what's going on below.
+ */
++
++#ifdef CONFIG_LANTIQ
++extern int lantiq_emulate_madwifi_eep;
++extern unsigned long long lantiq_madwifi_eep_addr;
++#define EEPROM_EMULATION 1
++#endif
++
++#ifdef EEPROM_EMULATION
++static int ath_hal_eeprom(struct ath_hal *ah, unsigned long addr, int val, int write)
++{
++ static int addrsel = 0;
++ static int rc = 0;
++
++ if (write) {
++ if(addr == 0x6000) {
++ addrsel = val * 2;
++ rc = 0;
++ }
++ } else {
++ switch(addr)
++ {
++ case 0x600c:
++ if(rc++ < 2)
++ val = 0x00000000;
++ else
++ val = 0x00000002;
++ break;
++ case 0x6004:
++ val = cpu_to_le16(__raw_readw((u16 *) KSEG1ADDR(lantiq_madwifi_eep_addr + addrsel)));
++ /* this forces the regdomain to 0x00 (worldwide), as the original setting
++ * causes issues with the HAL */
++ if (addrsel == 0x17e)
++ val = 0;
++ break;
++ }
++ }
++ return val;
++}
++#endif
++
+ void __ahdecl
+ ath_hal_reg_write(struct ath_hal *ah, u_int reg, u_int32_t val)
+ {
+@@ -351,20 +391,33 @@ ath_hal_reg_write(struct ath_hal *ah, u_
+ ath_hal_printf(ah, "%s: WRITE 0x%x <= 0x%x\n",
+ (ath_hal_func ?: "unknown"), reg, val);
+ #endif
+- _OS_REG_WRITE(ah, reg, val);
++#ifdef EEPROM_EMULATION
++ if((reg >= 0x6000) && (reg <= 0x6010) && lantiq_emulate_madwifi_eep)
++ {
++ val = ath_hal_eeprom(ah, reg, val, 1);
++ } else
++#endif
++ _OS_REG_WRITE(ah, reg, val);
+ }
+ EXPORT_SYMBOL(ath_hal_reg_write);
+
++
+ /* This should only be called while holding the lock, sc->sc_hal_lock. */
+ u_int32_t __ahdecl
+ ath_hal_reg_read(struct ath_hal *ah, u_int reg)
+ {
+- u_int32_t val;
++ u_int32_t val;
++#ifdef EEPROM_EMULATION
++ if((reg >= 0x6000) && (reg <= 0x6010) && lantiq_emulate_madwifi_eep)
++ {
++ val = ath_hal_eeprom(ah, reg, 0, 0);
++ } else
++#endif
++ val = _OS_REG_READ(ah, reg);
+
+- val = _OS_REG_READ(ah, reg);
+ #ifdef AH_DEBUG
+ if (ath_hal_debug > 1)
+- ath_hal_printf(ah, "%s: READ 0x%x => 0x%x\n",
++ ath_hal_printf(ah, "%s: READ 0x%x => 0x%x\n",
+ (ath_hal_func ?: "unknown"), reg, val);
+ #endif
+ return val;
+@@ -581,7 +634,6 @@ init_ath_hal(void)
+ {
+ const char *sep;
+ int i;
+-
+ printk(KERN_INFO "%s: %s (", dev_info, ath_hal_version);
+ sep = "";
+ for (i = 0; ath_hal_buildopts[i] != NULL; i++) {
diff --git a/package/madwifi/patches/355-eap_auth_disassoc.patch b/package/madwifi/patches/355-eap_auth_disassoc.patch
new file mode 100644
index 000000000..8bb1e9323
--- /dev/null
+++ b/package/madwifi/patches/355-eap_auth_disassoc.patch
@@ -0,0 +1,77 @@
+This patch causes STA mode interfaces to disassociate if transmission of assoc/auth
+critical packets failed.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -8334,6 +8334,14 @@ ath_tx_processq(struct ath_softc *sc, st
+ #endif
+ if (ts->ts_status & HAL_TXERR_XRETRY) {
+ sc->sc_stats.ast_tx_xretries++;
++ if (SKB_CB(bf->bf_skb)->auth_pkt &&
++ (ni->ni_vap->iv_opmode == IEEE80211_M_STA)) {
++ struct ieee80211vap *vap = ni->ni_vap;
++
++ /* if roaming is enabled, try reassociating, otherwise
++ * disassociate and go back to the scan state */
++ vap->iv_mgtsend.function(vap->iv_mgtsend.data);
++ }
+ if (ni->ni_flags & IEEE80211_NODE_UAPSD_TRIG) {
+ ni->ni_stats.ns_tx_eosplost++;
+ DPRINTF(sc, ATH_DEBUG_UAPSD,
+--- a/net80211/ieee80211_linux.c
++++ b/net80211/ieee80211_linux.c
+@@ -156,6 +156,7 @@ ieee80211_getmgtframe(u_int8_t **frm, u_
+ if (off != 0)
+ skb_reserve(skb, align - off);
+
++ SKB_CB(skb)->auth_pkt = 0;
+ SKB_CB(skb)->ni = NULL;
+ SKB_CB(skb)->flags = 0;
+ SKB_CB(skb)->next = NULL;
+--- a/net80211/ieee80211_linux.h
++++ b/net80211/ieee80211_linux.h
+@@ -393,6 +393,7 @@ typedef spinlock_t acl_lock_t;
+ void (*next_destructor)(struct sk_buff *skb);
+ #endif
+ struct sk_buff *next; /* fast frame sk_buf chain */
++ u_int8_t auth_pkt;
+ };
+
+
+--- a/net80211/ieee80211_output.c
++++ b/net80211/ieee80211_output.c
+@@ -778,6 +778,8 @@ ieee80211_encap(struct ieee80211_node *n
+ else
+ hdrsize = sizeof(struct ieee80211_frame);
+
++ SKB_CB(skb)->auth_pkt = (eh.ether_type == __constant_htons(ETHERTYPE_PAE));
++
+ switch (vap->iv_opmode) {
+ case IEEE80211_M_IBSS:
+ case IEEE80211_M_AHDEMO:
+@@ -1622,6 +1624,7 @@ ieee80211_add_xr_param(u_int8_t *frm, st
+ ie->param_len = frm - &ie->param_oui[0];
+ return frm;
+ }
++
+ #endif
+ /*
+ * Send a probe request frame with the specified ssid
+@@ -1886,6 +1889,7 @@ ieee80211_send_mgmt(struct ieee80211_nod
+ sizeof(u_int16_t)+IEEE80211_CHALLENGE_LEN : 0));
+ if (skb == NULL)
+ senderr(ENOMEM, is_tx_nobuf);
++ SKB_CB(skb)->auth_pkt = 1;
+
+ ((__le16 *)frm)[0] =
+ (is_shared_key) ? htole16(IEEE80211_AUTH_ALG_SHARED)
+@@ -1960,6 +1964,7 @@ ieee80211_send_mgmt(struct ieee80211_nod
+ vap->app_ie[IEEE80211_APPIE_FRAME_ASSOC_REQ].length);
+ if (skb == NULL)
+ senderr(ENOMEM, is_tx_nobuf);
++ SKB_CB(skb)->auth_pkt = 1;
+
+ capinfo = 0;
+ if (vap->iv_opmode == IEEE80211_M_IBSS)
diff --git a/package/madwifi/patches/356-hidden_ssid.patch b/package/madwifi/patches/356-hidden_ssid.patch
new file mode 100644
index 000000000..b87569e76
--- /dev/null
+++ b/package/madwifi/patches/356-hidden_ssid.patch
@@ -0,0 +1,49 @@
+This patch fixes the detection of hidden SSIDs as transmitted
+by some cisco systems.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+--- a/net80211/ieee80211_scan_sta.c
++++ b/net80211/ieee80211_scan_sta.c
+@@ -209,6 +209,19 @@ saveie(u_int8_t **iep, const u_int8_t *i
+ ieee80211_saveie(iep, ie);
+ }
+
++
++static inline int is_empty_ssid(u_int8_t *ssid)
++{
++ if (!ssid)
++ return 1;
++ if (ssid[1] == 0)
++ return 1;
++ if ((ssid[1] == 1) && (ssid[2] == 0))
++ return 1;
++ return 0;
++}
++
++
+ /*
+ * Process a beacon or probe response frame; create an
+ * entry in the scan cache or update any previous entry.
+@@ -233,8 +246,8 @@ sta_add(struct ieee80211_scan_state *ss,
+ SCAN_STA_LOCK_IRQ(st);
+ LIST_FOREACH(se, &st->st_hash[hash], se_hash)
+ if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr) &&
+- sp->ssid[1] == se->base.se_ssid[1] &&
+- !memcmp(se->base.se_ssid+2, sp->ssid+2, se->base.se_ssid[1]))
++ (is_empty_ssid(sp->ssid) || (sp->ssid[1] == se->base.se_ssid[1] &&
++ !memcmp(se->base.se_ssid+2, sp->ssid+2, se->base.se_ssid[1]))))
+ goto found;
+
+ MALLOC(se, struct sta_entry *, sizeof(struct sta_entry),
+@@ -252,8 +265,8 @@ found:
+ ise = &se->base;
+
+ /* XXX ap beaconing multiple ssid w/ same bssid */
+- if (sp->ssid[1] != 0 &&
+- (ISPROBE(subtype) || ise->se_ssid[1] == 0))
++ if (!is_empty_ssid(sp->ssid) &&
++ (ISPROBE(subtype) || is_empty_ssid(ise->se_ssid)))
+ memcpy(ise->se_ssid, sp->ssid, 2 + sp->ssid[1]);
+
+ memcpy(ise->se_rates, sp->rates,
diff --git a/package/madwifi/patches/357-bgscan_thresh.patch b/package/madwifi/patches/357-bgscan_thresh.patch
new file mode 100644
index 000000000..bf3483776
--- /dev/null
+++ b/package/madwifi/patches/357-bgscan_thresh.patch
@@ -0,0 +1,160 @@
+Add an optional background scanning threshold triggered by low rssi
+(useful for passing updated scan results to the supplicant ahead of
+time, before losing connectivity entirely)
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+--- a/net80211/ieee80211_ioctl.h
++++ b/net80211/ieee80211_ioctl.h
+@@ -646,6 +646,7 @@ enum {
+ IEEE80211_PARAM_MINRATE = 76, /* Minimum 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 */
++ IEEE80211_PARAM_BGSCAN_THRESH = 79, /* bg scan rssi threshold */
+ };
+
+ #define SIOCG80211STATS (SIOCDEVPRIVATE+2)
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -92,6 +92,8 @@
+ #define IEEE80211_BGSCAN_IDLE_MIN 100 /* min idle time (ms) */
+ #define IEEE80211_BGSCAN_IDLE_DEFAULT 250 /* default idle time (ms) */
+
++#define IEEE80211_BGSCAN_TRIGGER_INTVL 20 /* min trigger interval for thresh based bgscan (secs) */
++
+ #define IEEE80211_COVERAGE_CLASS_MAX 31 /* max coverage class */
+ #define IEEE80211_REGCLASSIDS_MAX 10 /* max regclass id list */
+
+@@ -219,6 +221,10 @@ struct ieee80211vap {
+ 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_bgscanthr; /* bg scan rssi threshold */
++ u_int iv_bgscantrintvl; /* bg scan trigger interval */
++ unsigned long iv_bgscanthr_next; /* last trigger for bgscan */
++ unsigned long iv_lastconnect; /* time of last connect attempt */
+ u_int iv_scanvalid; /* scan cache valid threshold */
+ struct ieee80211_roam iv_roam; /* sta-mode roaming state */
+
+@@ -608,6 +614,7 @@ MALLOC_DECLARE(M_80211_VAP);
+ #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_FEXT_BGSCAN_THR 0x00002000 /* bgscan due to low rssi */
+
+ #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)
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -2744,6 +2744,9 @@ ieee80211_ioctl_setparam(struct net_devi
+ else
+ retv = EINVAL;
+ break;
++ case IEEE80211_PARAM_BGSCAN_THRESH:
++ vap->iv_bgscanthr = value;
++ break;
+ case IEEE80211_PARAM_MCAST_RATE:
+ /* units are in KILObits per second */
+ if (value >= 256 && value <= 54000)
+@@ -3144,6 +3147,9 @@ ieee80211_ioctl_getparam(struct net_devi
+ case IEEE80211_PARAM_BGSCAN_INTERVAL:
+ param[0] = vap->iv_bgscanintvl / HZ; /* seconds */
+ break;
++ case IEEE80211_PARAM_BGSCAN_THRESH:
++ param[0] = vap->iv_bgscanthr; /* rssi */
++ break;
+ case IEEE80211_PARAM_MCAST_RATE:
+ param[0] = vap->iv_mcast_rate; /* seconds */
+ break;
+@@ -5666,6 +5672,10 @@ static const struct iw_priv_args ieee802
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bgscanintvl" },
+ { IEEE80211_PARAM_BGSCAN_INTERVAL,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_bgscanintvl" },
++ { IEEE80211_PARAM_BGSCAN_THRESH,
++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bgscanthr" },
++ { IEEE80211_PARAM_BGSCAN_THRESH,
++ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_bgscanthr" },
+ { IEEE80211_PARAM_MCAST_RATE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "mcast_rate" },
+ { IEEE80211_PARAM_MCAST_RATE,
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -3013,8 +3013,10 @@ contbgscan(struct ieee80211vap *vap)
+ {
+ struct ieee80211com *ic = vap->iv_ic;
+
++ vap->iv_bgscantrintvl = (vap->iv_bgscantrintvl + 1) % 4;
+ return ((ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN) &&
+- time_after(jiffies, ic->ic_lastdata + vap->iv_bgscanidle));
++ (((ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN_THR) && !vap->iv_bgscantrintvl) ||
++ time_after(jiffies, ic->ic_lastdata + vap->iv_bgscanidle)));
+ }
+
+ static __inline int
+@@ -3258,6 +3260,25 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ /* record tsf of last beacon */
+ memcpy(ni->ni_tstamp.data, scan.tstamp,
+ sizeof(ni->ni_tstamp));
++
++ /* When rssi is low, start doing bgscans more frequently to allow
++ * the supplicant to make a better switching decision */
++ if (!(ic->ic_flags & IEEE80211_F_SCAN) && (rssi < vap->iv_bgscanthr) &&
++ (!vap->iv_bgscanthr_next ||
++ !time_before(jiffies, vap->iv_bgscanthr_next)) &&
++ (vap->iv_state == IEEE80211_S_RUN) &&
++ time_after(jiffies, vap->iv_lastconnect +
++ msecs_to_jiffies(IEEE80211_BGSCAN_INTVAL_MIN * 1000))) {
++ int ret;
++
++ ic->ic_lastdata = 0;
++ ic->ic_lastscan = 0;
++ ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN_THR;
++ ret = ieee80211_bg_scan(vap);
++ if (ret)
++ vap->iv_bgscanthr_next = jiffies + msecs_to_jiffies(IEEE80211_BGSCAN_TRIGGER_INTVL * 1000);
++ }
++
+ if (ni->ni_intval != scan.bintval) {
+ IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni,
+ "beacon interval divergence: "
+--- a/net80211/ieee80211_scan.c
++++ b/net80211/ieee80211_scan.c
+@@ -616,6 +616,7 @@ ieee80211_cancel_scan(struct ieee80211va
+
+ /* clear bg scan NOPICK and mark cancel request */
+ ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;
++ ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN_THR;
+ SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL;
+ ss->ss_ops->scan_cancel(ss, vap);
+ /* force it to fire asap */
+@@ -782,7 +783,7 @@ again:
+ ieee80211_sta_pwrsave(vap, 0);
+ if (ss->ss_next >= ss->ss_last) {
+ ieee80211_notify_scan_done(vap);
+- ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN;
++ ic->ic_flags_ext &= ~(IEEE80211_FEXT_BGSCAN|IEEE80211_FEXT_BGSCAN_THR);
+ }
+ }
+ SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_CANCEL;
+--- a/net80211/ieee80211_proto.c
++++ b/net80211/ieee80211_proto.c
+@@ -1450,6 +1450,7 @@ __ieee80211_newstate(struct ieee80211vap
+ }
+ break;
+ case IEEE80211_S_AUTH:
++ vap->iv_lastconnect = jiffies;
+ /* auth frames are possible between IBSS nodes,
+ * see 802.11-1999, chapter 5.7.6 */
+ KASSERT(vap->iv_opmode == IEEE80211_M_STA ||
+--- a/net80211/ieee80211_output.c
++++ b/net80211/ieee80211_output.c
+@@ -238,7 +238,8 @@ ieee80211_hardstart(struct sk_buff *skb,
+ }
+
+ /* Cancel any running BG scan */
+- ieee80211_cancel_scan(vap);
++ if (!(ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN_THR) && (vap->iv_state == IEEE80211_S_RUN))
++ ieee80211_cancel_scan(vap);
+
+ /*
+ * Find the node for the destination so we can do
diff --git a/package/madwifi/patches/358-ignore_broken_bssid.patch b/package/madwifi/patches/358-ignore_broken_bssid.patch
new file mode 100644
index 000000000..b54927220
--- /dev/null
+++ b/package/madwifi/patches/358-ignore_broken_bssid.patch
@@ -0,0 +1,18 @@
+Some misconfigured APs broadcast NULL BSSIDs, which can confuse the STA
+Ignore those when scanning.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+--- a/net80211/ieee80211_scan_sta.c
++++ b/net80211/ieee80211_scan_sta.c
+@@ -242,6 +242,10 @@ sta_add(struct ieee80211_scan_state *ss,
+ struct ieee80211_scan_entry *ise;
+ int hash;
+
++ /* workaround for broken APs that broadcast NULL BSSIDs */
++ if (memcmp(wh->i_addr3, "\x00\x00\x00\x00\x00\x00", 6) == 0)
++ return 0;
++
+ hash = STA_HASH(macaddr);
+ SCAN_STA_LOCK_IRQ(st);
+ LIST_FOREACH(se, &st->st_hash[hash], se_hash)
diff --git a/package/madwifi/patches/359-disable_reassoc.patch b/package/madwifi/patches/359-disable_reassoc.patch
new file mode 100644
index 000000000..8d25dc2a8
--- /dev/null
+++ b/package/madwifi/patches/359-disable_reassoc.patch
@@ -0,0 +1,31 @@
+Add a preliminary fix for the reassoc check, but disable reassoc entirely for now
+until we've figured out why it fails frequently.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -599,10 +599,9 @@ ieee80211_ibss_merge(struct ieee80211_no
+ EXPORT_SYMBOL(ieee80211_ibss_merge);
+
+ static __inline int
+-ssid_equal(const struct ieee80211_node *a, const struct ieee80211_node *b)
++bssid_equal(const struct ieee80211_node *a, const struct ieee80211_node *b)
+ {
+- return (a->ni_esslen == b->ni_esslen &&
+- memcmp(a->ni_essid, b->ni_essid, a->ni_esslen) == 0);
++ return (memcmp(a->ni_bssid, b->ni_bssid, IEEE80211_ADDR_LEN) == 0);
+ }
+
+ /*
+@@ -634,8 +633,8 @@ ieee80211_sta_join1(struct ieee80211_nod
+ * Check if old+new node have the same ssid in which
+ * case we can reassociate when operating in sta mode.
+ */
+- canreassoc = ((obss != NULL) &&
+- (vap->iv_state == IEEE80211_S_RUN) && ssid_equal(obss, selbs));
++ canreassoc = 0; /* ((obss != NULL) &&
++ (vap->iv_state == IEEE80211_S_RUN) && bssid_equal(obss, selbs)); */
+ vap->iv_bss = selbs;
+ IEEE80211_ADDR_COPY(vap->iv_bssid, selbs->ni_bssid);
+ if (obss != NULL)
diff --git a/package/madwifi/patches/360-sta_nodes.patch b/package/madwifi/patches/360-sta_nodes.patch
new file mode 100644
index 000000000..8d2dd9ddd
--- /dev/null
+++ b/package/madwifi/patches/360-sta_nodes.patch
@@ -0,0 +1,242 @@
+Drop stale AP nodes from the client list when disconnecting.
+Fixes some reassoc issues.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+--- a/net80211/ieee80211_proto.c
++++ b/net80211/ieee80211_proto.c
+@@ -1348,7 +1348,7 @@ __ieee80211_newstate(struct ieee80211vap
+ IEEE80211_SEND_MGMT(ni,
+ IEEE80211_FC0_SUBTYPE_DISASSOC,
+ IEEE80211_REASON_ASSOC_LEAVE);
+- ieee80211_sta_leave(ni);
++ ieee80211_node_leave(ni);
+ break;
+ case IEEE80211_M_HOSTAP:
+ ieee80211_iterate_nodes(&ic->ic_sta,
+@@ -1358,12 +1358,14 @@ __ieee80211_newstate(struct ieee80211vap
+ break;
+ }
+ goto reset;
++ case IEEE80211_S_AUTH:
+ case IEEE80211_S_ASSOC:
+ switch (vap->iv_opmode) {
+ case IEEE80211_M_STA:
+ IEEE80211_SEND_MGMT(ni,
+ IEEE80211_FC0_SUBTYPE_DEAUTH,
+ IEEE80211_REASON_AUTH_LEAVE);
++ ieee80211_node_leave(ni);
+ break;
+ case IEEE80211_M_HOSTAP:
+ ieee80211_iterate_nodes(&ic->ic_sta,
+@@ -1376,7 +1378,6 @@ __ieee80211_newstate(struct ieee80211vap
+ case IEEE80211_S_SCAN:
+ ieee80211_cancel_scan(vap);
+ goto reset;
+- case IEEE80211_S_AUTH:
+ reset:
+ ieee80211_reset_bss(vap);
+ break;
+@@ -1429,10 +1430,12 @@ __ieee80211_newstate(struct ieee80211vap
+ IEEE80211_SCAN_FOREVER,
+ vap->iv_des_nssid, vap->iv_des_ssid,
+ NULL);
++ else
++ ieee80211_node_leave(vap->iv_bss);
+ break;
+ case IEEE80211_S_RUN: /* beacon miss */
+ if (vap->iv_opmode == IEEE80211_M_STA) {
+- ieee80211_sta_leave(ni);
++ ieee80211_node_leave(ni);
+ vap->iv_flags &= ~IEEE80211_F_SIBSS; /* XXX */
+ if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
+ ieee80211_check_scan(vap,
+@@ -1511,7 +1514,7 @@ __ieee80211_newstate(struct ieee80211vap
+ IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
+ break;
+ case IEEE80211_S_RUN:
+- ieee80211_sta_leave(ni);
++ ieee80211_node_leave(ni);
+ if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
+ /* NB: caller specifies ASSOC/REASSOC by arg */
+ IEEE80211_SEND_MGMT(ni, arg ?
+@@ -1779,6 +1782,7 @@ ieee80211_newstate(struct ieee80211vap *
+ ieee80211_state_name[nstate],
+ ieee80211_state_name[dstate]);
+
++ ieee80211_update_link_status(vap, nstate, ostate);
+ switch (nstate) {
+ case IEEE80211_S_AUTH:
+ case IEEE80211_S_ASSOC:
+--- a/net80211/ieee80211_linux.c
++++ b/net80211/ieee80211_linux.c
+@@ -233,33 +233,59 @@ ieee80211_vlan_vdetach(struct ieee80211v
+ }
+
+ void
+-ieee80211_notify_node_join(struct ieee80211_node *ni, int newassoc)
++ieee80211_update_link_status(struct ieee80211vap *vap, int nstate, int ostate)
+ {
+- struct ieee80211vap *vap = ni->ni_vap;
+ struct net_device *dev = vap->iv_dev;
+ union iwreq_data wreq;
++ int active;
++
++ if (vap->iv_opmode != IEEE80211_M_STA)
++ return;
++
++ if (ostate == nstate)
++ return;
++
++ if (nstate == IEEE80211_S_RUN)
++ active = 1;
++ else if ((ostate >= IEEE80211_S_AUTH) && (nstate < ostate))
++ active = 0;
++ else
++ return;
++
++ if (active && !vap->iv_bss)
++ return;
++
++ memset(&wreq, 0, sizeof(wreq));
++ wreq.ap_addr.sa_family = ARPHRD_ETHER;
+
+- if (ni == vap->iv_bss) {
+- if (newassoc)
+- netif_carrier_on(dev);
+- memset(&wreq, 0, sizeof(wreq));
++ if (active) {
++ //netif_carrier_on(vap->iv_dev);
+ IEEE80211_ADDR_COPY(wreq.addr.sa_data, vap->iv_bssid);
+- wreq.addr.sa_family = ARPHRD_ETHER;
+-#ifdef ATH_SUPERG_XR
+- if (vap->iv_xrvap && vap->iv_flags & IEEE80211_F_XR)
+- dev = vap->iv_xrvap->iv_dev;
+-#endif
+- wireless_send_event(dev, SIOCGIWAP, &wreq, NULL);
+ } else {
+- memset(&wreq, 0, sizeof(wreq));
+- IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);
+- wreq.addr.sa_family = ARPHRD_ETHER;
++ //netif_carrier_off(vap->iv_dev);
++ memset(wreq.ap_addr.sa_data, 0, ETHER_ADDR_LEN);
++ }
++ wireless_send_event(dev, SIOCGIWAP, &wreq, NULL);
++}
++
++void
++ieee80211_notify_node_join(struct ieee80211_node *ni, int newassoc)
++{
++ struct ieee80211vap *vap = ni->ni_vap;
++ struct net_device *dev = vap->iv_dev;
++ union iwreq_data wreq;
++
++ if (ni == vap->iv_bss)
++ return;
++
++ memset(&wreq, 0, sizeof(wreq));
++ IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);
++ wreq.addr.sa_family = ARPHRD_ETHER;
+ #ifdef ATH_SUPERG_XR
+- if (vap->iv_xrvap && vap->iv_flags & IEEE80211_F_XR)
+- dev = vap->iv_xrvap->iv_dev;
++ if (vap->iv_xrvap && vap->iv_flags & IEEE80211_F_XR)
++ dev = vap->iv_xrvap->iv_dev;
+ #endif
+- wireless_send_event(dev, IWEVREGISTERED, &wreq, NULL);
+- }
++ wireless_send_event(dev, IWEVREGISTERED, &wreq, NULL);
+ }
+
+ void
+@@ -269,18 +295,14 @@ ieee80211_notify_node_leave(struct ieee8
+ struct net_device *dev = vap->iv_dev;
+ union iwreq_data wreq;
+
+- if (ni == vap->iv_bss) {
+- netif_carrier_off(dev);
+- memset(wreq.ap_addr.sa_data, 0, ETHER_ADDR_LEN);
+- wreq.ap_addr.sa_family = ARPHRD_ETHER;
+- wireless_send_event(dev, SIOCGIWAP, &wreq, NULL);
+- } else {
+- /* fire off wireless event station leaving */
+- memset(&wreq, 0, sizeof(wreq));
+- IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);
+- wreq.addr.sa_family = ARPHRD_ETHER;
+- wireless_send_event(dev, IWEVEXPIRED, &wreq, NULL);
+- }
++ if (ni == vap->iv_bss)
++ return;
++
++ /* fire off wireless event station leaving */
++ memset(&wreq, 0, sizeof(wreq));
++ IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);
++ wreq.addr.sa_family = ARPHRD_ETHER;
++ wireless_send_event(dev, IWEVEXPIRED, &wreq, NULL);
+ }
+
+ void
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -2332,6 +2332,7 @@ ieee80211_node_leave(struct ieee80211_no
+ count_suppchans(ic, ni, -1);
+ IEEE80211_UNLOCK_IRQ(ic);
+
++done:
+ /*
+ * Cleanup station state. In particular clear various
+ * state that might otherwise be reused if the node
+@@ -2339,7 +2340,7 @@ ieee80211_node_leave(struct ieee80211_no
+ * (and memory is reclaimed).
+ */
+ ieee80211_sta_leave(ni);
+-done:
++
+ /* Run a cleanup */
+ #ifdef IEEE80211_DEBUG_REFCNT
+ ic->ic_node_cleanup_debug(ni, __func__, __LINE__);
+--- a/net80211/ieee80211_node.h
++++ b/net80211/ieee80211_node.h
+@@ -60,7 +60,7 @@
+ #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_TRANS_WAIT 300 /* mgt frame tx timer (msecs) */
+
+ #define IEEE80211_NODE_HASHSIZE 32
+ /* simple hash is enough for variation of macaddr */
+--- a/net80211/ieee80211_output.c
++++ b/net80211/ieee80211_output.c
+@@ -2141,7 +2141,7 @@ ieee80211_send_mgmt(struct ieee80211_nod
+
+ ieee80211_mgmt_output(ieee80211_ref_node(ni), skb, type);
+ if (timer)
+- mod_timer(&vap->iv_mgtsend, jiffies + timer * HZ);
++ mod_timer(&vap->iv_mgtsend, jiffies + msecs_to_jiffies(timer));
+ return 0;
+ bad:
+ return ret;
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -514,8 +514,9 @@ ieee80211_ioctl_siwap(struct net_device
+ vap->iv_flags |= IEEE80211_F_DESBSSID;
+
+ IEEE80211_ADDR_COPY(vap->iv_des_bssid, &ap_addr->sa_data);
+- if (IS_UP_AUTO(vap))
++ if (IS_UP(vap->iv_dev)) {
+ ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
++ }
+ }
+ return 0;
+ }
+--- a/net80211/ieee80211_linux.h
++++ b/net80211/ieee80211_linux.h
+@@ -643,6 +643,7 @@ void ieee80211_vlan_vdetach(struct ieee8
+ #define free_netdev(dev) kfree(dev)
+ #endif
+
++void ieee80211_update_link_status(struct ieee80211vap *vap, int nstate, int ostate);
+ void ieee80211_ioctl_vattach(struct ieee80211vap *);
+ void ieee80211_ioctl_vdetach(struct ieee80211vap *);
+ struct ifreq;
diff --git a/package/madwifi/patches/361-bmiss_handling.patch b/package/madwifi/patches/361-bmiss_handling.patch
new file mode 100644
index 000000000..15d238f7b
--- /dev/null
+++ b/package/madwifi/patches/361-bmiss_handling.patch
@@ -0,0 +1,102 @@
+Improve the beacon miss handling. Instead of just dropping the connection,
+send a directed probe request to the AP to see if it's still responding.
+Schedule a software beacon miss timer in this case, which adds a timeout
+for the APs probe response.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -3400,12 +3400,17 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ }
+
+ /* WDS/Repeater: re-schedule software beacon timer for
+- * STA. */
+- if ((vap->iv_state == IEEE80211_S_RUN) &&
+- (vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS)) {
+- mod_timer(&vap->iv_swbmiss,
++ * STA. Reset consecutive bmiss counter as well */
++ IEEE80211_LOCK_IRQ(ic);
++ if (vap->iv_state == IEEE80211_S_RUN) {
++ vap->iv_bmiss_count = 0;
++ if (vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS)
++ mod_timer(&vap->iv_swbmiss,
+ jiffies + vap->iv_swbmiss_period);
++ else
++ del_timer(&vap->iv_swbmiss);
+ }
++ IEEE80211_UNLOCK_IRQ(ic);
+
+ /* If scanning, pass the info to the scan module.
+ * Otherwise, check if it's the right time to do
+--- a/net80211/ieee80211_proto.c
++++ b/net80211/ieee80211_proto.c
+@@ -1209,6 +1209,8 @@ ieee80211_beacon_miss(struct ieee80211co
+ }
+ /* XXX locking */
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
++ int count;
++
+ IEEE80211_DPRINTF(vap,
+ IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
+ "%s\n", "beacon miss");
+@@ -1221,6 +1223,29 @@ ieee80211_beacon_miss(struct ieee80211co
+ if (vap->iv_opmode != IEEE80211_M_STA ||
+ vap->iv_state != IEEE80211_S_RUN)
+ continue;
++
++ IEEE80211_LOCK_IRQ(ic);
++ count = vap->iv_bmiss_count++;
++ if (count) {
++ /* if the counter was already above zero, reset it
++ * here, since we're going to do the bmiss handling
++ * in any case */
++ vap->iv_bmiss_count = 0;
++ } else {
++ /* schedule the software beacon miss timer, it will be
++ * cancelled, if the probe request is acked */
++ mod_timer(&vap->iv_swbmiss, jiffies + vap->iv_swbmiss_period);
++ }
++ IEEE80211_UNLOCK_IRQ(ic);
++
++ if (!count) {
++ ieee80211_send_probereq(vap->iv_bss, vap->iv_myaddr,
++ vap->iv_bss->ni_bssid, vap->iv_bss->ni_bssid,
++ vap->iv_bss->ni_essid, vap->iv_bss->ni_esslen,
++ NULL, 0);
++ continue;
++ }
++
+ if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
+ #ifdef ATH_SUPERG_DYNTURBO
+ /*
+@@ -1621,14 +1646,14 @@ __ieee80211_newstate(struct ieee80211vap
+ }
+
+ /* WDS/Repeater: Start software beacon timer for STA */
++ vap->iv_swbmiss.function = ieee80211_sta_swbmiss;
++ vap->iv_swbmiss.data = (unsigned long) vap;
++ vap->iv_swbmiss_period = IEEE80211_TU_TO_JIFFIES(
++ vap->iv_ic->ic_bmissthreshold * ni->ni_intval);
++
+ if (ostate != IEEE80211_S_RUN &&
+ (vap->iv_opmode == IEEE80211_M_STA &&
+ vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS)) {
+- vap->iv_swbmiss.function = ieee80211_sta_swbmiss;
+- vap->iv_swbmiss.data = (unsigned long) vap;
+- vap->iv_swbmiss_period = IEEE80211_TU_TO_JIFFIES(
+- vap->iv_ic->ic_bmissthreshold * ni->ni_intval);
+-
+ mod_timer(&vap->iv_swbmiss, jiffies + vap->iv_swbmiss_period);
+ }
+
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -283,6 +283,7 @@ struct ieee80211vap {
+
+ struct timer_list iv_swbmiss; /* software beacon miss timer */
+ u_int16_t iv_swbmiss_period; /* software beacon miss timer period */
++ u_int16_t iv_bmiss_count; /* consecutive beacon miss counter */
+ 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 */
diff --git a/package/madwifi/patches/362-rssithr.patch b/package/madwifi/patches/362-rssithr.patch
new file mode 100644
index 000000000..5a86833bb
--- /dev/null
+++ b/package/madwifi/patches/362-rssithr.patch
@@ -0,0 +1,93 @@
+Add an optional threshold for low-rssi disconnection. This can be useful
+when letting wpa_supplicant control roaming.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+--- a/net80211/ieee80211_ioctl.h
++++ b/net80211/ieee80211_ioctl.h
+@@ -647,6 +647,8 @@ enum {
+ IEEE80211_PARAM_PROTMODE_RSSI = 77, /* RSSI Threshold for enabling protection mode */
+ IEEE80211_PARAM_PROTMODE_TIMEOUT = 78, /* Timeout for expiring protection mode */
+ IEEE80211_PARAM_BGSCAN_THRESH = 79, /* bg scan rssi threshold */
++ IEEE80211_PARAM_RSSI_DIS_THR = 80, /* rssi threshold for disconnection */
++ IEEE80211_PARAM_RSSI_DIS_COUNT = 81, /* counter for rssi threshold */
+ };
+
+ #define SIOCG80211STATS (SIOCDEVPRIVATE+2)
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -2799,6 +2799,12 @@ ieee80211_ioctl_setparam(struct net_devi
+ case IEEE80211_PARAM_ROAM_RATE_11G:
+ vap->iv_roam.rate11b = value;
+ break;
++ case IEEE80211_PARAM_RSSI_DIS_THR:
++ vap->iv_rssi_dis_thr = value;
++ break;
++ case IEEE80211_PARAM_RSSI_DIS_COUNT:
++ vap->iv_rssi_dis_max = value;
++ break;
+ case IEEE80211_PARAM_UAPSDINFO:
+ if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
+ if (ic->ic_caps & IEEE80211_C_UAPSD) {
+@@ -3184,6 +3190,12 @@ ieee80211_ioctl_getparam(struct net_devi
+ case IEEE80211_PARAM_ROAM_RATE_11G:
+ param[0] = vap->iv_roam.rate11b;
+ break;
++ case IEEE80211_PARAM_RSSI_DIS_THR:
++ param[0] = vap->iv_rssi_dis_thr;
++ break;
++ case IEEE80211_PARAM_RSSI_DIS_COUNT:
++ param[0] = vap->iv_rssi_dis_max;
++ break;
+ case IEEE80211_PARAM_UAPSDINFO:
+ if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
+ if (IEEE80211_VAP_UAPSD_ENABLED(vap))
+@@ -5733,6 +5745,14 @@ static const struct iw_priv_args ieee802
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rate11g" },
+ { IEEE80211_PARAM_ROAM_RATE_11G,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_rate11g" },
++ { IEEE80211_PARAM_RSSI_DIS_THR,
++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rssi_disthr" },
++ { IEEE80211_PARAM_RSSI_DIS_THR,
++ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_rssi_disthr" },
++ { IEEE80211_PARAM_RSSI_DIS_COUNT,
++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rssi_discnt" },
++ { IEEE80211_PARAM_RSSI_DIS_COUNT,
++ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_rssi_discnt" },
+ { IEEE80211_PARAM_UAPSDINFO,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "uapsd" },
+ { IEEE80211_PARAM_UAPSDINFO,
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -3261,6 +3261,19 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ memcpy(ni->ni_tstamp.data, scan.tstamp,
+ sizeof(ni->ni_tstamp));
+
++ /* when rssi falls below the disconnection threshold, drop the connection */
++ if ((vap->iv_rssi_dis_thr > 0) && (vap->iv_rssi_dis_max > 0)) {
++ if ((rssi > 0) && (rssi < vap->iv_rssi_dis_thr)) {
++ if (++vap->iv_rssi_dis_trig > vap->iv_rssi_dis_max) {
++ vap->iv_rssi_dis_trig = 0;
++ ieee80211_node_leave(ni);
++ return;
++ }
++ } else {
++ vap->iv_rssi_dis_trig = 0;
++ }
++ }
++
+ /* When rssi is low, start doing bgscans more frequently to allow
+ * the supplicant to make a better switching decision */
+ if (!(ic->ic_flags & IEEE80211_F_SCAN) && (rssi < vap->iv_bgscanthr) &&
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -223,6 +223,9 @@ struct ieee80211vap {
+ u_int iv_bgscanintvl; /* bg scan min interval */
+ u_int iv_bgscanthr; /* bg scan rssi threshold */
+ u_int iv_bgscantrintvl; /* bg scan trigger interval */
++ u_int iv_rssi_dis_thr; /* rssi disassoc threshold */
++ u_int iv_rssi_dis_max; /* max beacons below disconnect threshold */
++ u_int iv_rssi_dis_trig; /* rssi disassoc trigger count */
+ unsigned long iv_bgscanthr_next; /* last trigger for bgscan */
+ unsigned long iv_lastconnect; /* time of last connect attempt */
+ u_int iv_scanvalid; /* scan cache valid threshold */
diff --git a/package/madwifi/patches/363-fix_turbo.patch b/package/madwifi/patches/363-fix_turbo.patch
new file mode 100644
index 000000000..880f2d614
--- /dev/null
+++ b/package/madwifi/patches/363-fix_turbo.patch
@@ -0,0 +1,11 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -4925,7 +4925,7 @@ ath_beacon_generate(struct ath_softc *sc
+ * capability info and arrange for a mode change
+ * if needed.
+ */
+- if (sc->sc_dturbo) {
++ if (sc->sc_dturbo && NULL != avp->av_boff.bo_tim) {
+ u_int8_t dtim;
+ dtim = ((avp->av_boff.bo_tim[2] == 1) ||
+ (avp->av_boff.bo_tim[3] == 1));
diff --git a/package/madwifi/patches/364-memory_alloc.patch b/package/madwifi/patches/364-memory_alloc.patch
new file mode 100644
index 000000000..53fbc7709
--- /dev/null
+++ b/package/madwifi/patches/364-memory_alloc.patch
@@ -0,0 +1,13 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -539,8 +539,8 @@ ath_attach(u_int16_t devid, struct net_d
+
+ /* Allocate space for dynamically determined maximum VAP count */
+ sc->sc_bslot =
+- kmalloc(ath_maxvaps * sizeof(struct ieee80211vap), GFP_KERNEL);
+- memset(sc->sc_bslot, 0, ath_maxvaps * sizeof(struct ieee80211vap));
++ kmalloc(ath_maxvaps * sizeof(struct ieee80211vap*), GFP_KERNEL);
++ memset(sc->sc_bslot, 0, ath_maxvaps * sizeof(struct ieee80211vap*));
+
+ /*
+ * Cache line size is used to size and align various
diff --git a/package/madwifi/patches/365-turbo_channelsearch.patch b/package/madwifi/patches/365-turbo_channelsearch.patch
new file mode 100644
index 000000000..df4306b21
--- /dev/null
+++ b/package/madwifi/patches/365-turbo_channelsearch.patch
@@ -0,0 +1,10 @@
+--- a/net80211/ieee80211.c
++++ b/net80211/ieee80211.c
+@@ -684,6 +684,7 @@ ieee80211_find_channel(struct ieee80211c
+ int i;
+
+ /* Brute force search */
++ flags &= IEEE80211_CHAN_ALLTURBO;
+ for (i = 0; i < ic->ic_nchans; i++) {
+ c = &ic->ic_channels[i];
+ if (c->ic_freq == freq &&
diff --git a/package/madwifi/patches/366-bstuck_thresh.patch b/package/madwifi/patches/366-bstuck_thresh.patch
new file mode 100644
index 000000000..cde1f5c98
--- /dev/null
+++ b/package/madwifi/patches/366-bstuck_thresh.patch
@@ -0,0 +1,52 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -389,6 +389,7 @@ static int ath_countrycode = CTRY_DEFAUL
+ static int ath_outdoor = AH_FALSE; /* enable outdoor use */
+ static int ath_xchanmode = AH_TRUE; /* enable extended channels */
+ static int ath_maxvaps = ATH_MAXVAPS_DEFAULT; /* set default maximum vaps */
++static int bstuck_thresh = BSTUCK_THRESH; /* Stuck beacon count required for reset */
+ static char *autocreate = NULL;
+ static char *ratectl = DEF_RATE_CTL;
+ static int rfkill = 0;
+@@ -432,6 +433,7 @@ MODULE_PARM(rfkill, "i");
+ #ifdef ATH_CAP_TPC
+ MODULE_PARM(tpc, "i");
+ #endif
++MODULE_PARM(bstuck_thresh, "i");
+ MODULE_PARM(autocreate, "s");
+ MODULE_PARM(ratectl, "s");
+ #else
+@@ -445,6 +447,7 @@ module_param(rfkill, int, 0600);
+ #ifdef ATH_CAP_TPC
+ module_param(tpc, int, 0600);
+ #endif
++module_param(bstuck_thresh, int, 0600);
+ module_param(autocreate, charp, 0600);
+ module_param(ratectl, charp, 0600);
+ #endif
+@@ -457,6 +460,7 @@ MODULE_PARM_DESC(rfkill, "Enable/disable
+ MODULE_PARM_DESC(tpc, "Enable/disable per-packet transmit power control (TPC) "
+ "capability");
+ #endif
++MODULE_PARM_DESC(bstuck_thresh, "Override default stuck beacon threshold");
+ MODULE_PARM_DESC(autocreate, "Create ath device in "
+ "[sta|ap|wds|adhoc|ahdemo|monitor] mode. defaults to sta, use "
+ "'none' to disable");
+@@ -5072,7 +5076,7 @@ ath_beacon_send(struct ath_softc *sc, in
+ DPRINTF(sc, ATH_DEBUG_BEACON_PROC,
+ "Missed %u consecutive beacons (n_beacon=%u)\n",
+ sc->sc_bmisscount, n_beacon);
+- if (sc->sc_bmisscount > BSTUCK_THRESH)
++ if (sc->sc_bmisscount > bstuck_thresh)
+ ATH_SCHEDULE_TQUEUE(&sc->sc_bstucktq, needmark);
+ return;
+ }
+@@ -5230,7 +5234,7 @@ ath_bstuck_tasklet(TQUEUE_ARG data)
+ * check will be true, in which case return
+ * without resetting the driver.
+ */
+- if (sc->sc_bmisscount <= BSTUCK_THRESH)
++ if (sc->sc_bmisscount <= bstuck_thresh)
+ return;
+ EPRINTF(sc, "Stuck beacon; resetting (beacon miss count: %u)\n",
+ sc->sc_bmisscount);
diff --git a/package/madwifi/patches/367-roaming.patch b/package/madwifi/patches/367-roaming.patch
new file mode 100644
index 000000000..5950f9fd4
--- /dev/null
+++ b/package/madwifi/patches/367-roaming.patch
@@ -0,0 +1,77 @@
+Patch adapted from ubnt madwifi patchset
+
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -659,7 +659,7 @@ ieee80211_sta_join1(struct ieee80211_nod
+ */
+ if (canreassoc) {
+ vap->iv_nsparams.newstate = IEEE80211_S_ASSOC;
+- vap->iv_nsparams.arg = 0;
++ vap->iv_nsparams.arg = IEEE80211_FC0_SUBTYPE_REASSOC_REQ;
+ IEEE80211_SCHEDULE_TQUEUE(&vap->iv_stajoin1tq);
+ } else {
+ vap->iv_nsparams.newstate = IEEE80211_S_AUTH;
+--- a/net80211/ieee80211_scan_sta.c
++++ b/net80211/ieee80211_scan_sta.c
+@@ -748,14 +748,17 @@ notfound:
+ * a reference to an entry w/o holding the lock on the table.
+ */
+ static struct sta_entry *
+-sta_lookup(struct sta_table *st, const u_int8_t macaddr[IEEE80211_ADDR_LEN])
++sta_lookup(struct sta_table *st, const u_int8_t macaddr[IEEE80211_ADDR_LEN], struct ieee80211_scan_ssid* essid)
+ {
+ struct sta_entry *se;
+ int hash = STA_HASH(macaddr);
+
+ SCAN_STA_LOCK_IRQ(st);
+ LIST_FOREACH(se, &st->st_hash[hash], se_hash)
+- if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr))
++ if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr) &&
++ (essid->len == se->base.se_ssid[1] &&
++ !memcmp(se->base.se_ssid+2, essid->ssid,
++ se->base.se_ssid[1])))
+ break;
+ SCAN_STA_UNLOCK_IRQ(st);
+
+@@ -772,7 +775,7 @@ sta_roam_check(struct ieee80211_scan_sta
+ u_int8_t roamRate, curRate;
+ int8_t roamRssi, curRssi;
+
+- se = sta_lookup(st, ni->ni_macaddr);
++ se = sta_lookup(st, ni->ni_macaddr, ss->ss_ssid);
+ if (se == NULL) {
+ /* XXX something is wrong */
+ return;
+@@ -866,8 +869,8 @@ sta_age(struct ieee80211_scan_state *ss)
+ */
+ KASSERT(vap->iv_opmode == IEEE80211_M_STA,
+ ("wrong mode %u", vap->iv_opmode));
+- /* XXX turn this off until the ap release is cut */
+- if (0 && vap->iv_ic->ic_roaming == IEEE80211_ROAMING_AUTO &&
++ if (vap->iv_opmode == IEEE80211_M_STA &&
++ vap->iv_ic->ic_roaming == IEEE80211_ROAMING_AUTO &&
+ vap->iv_state >= IEEE80211_S_RUN)
+ /* XXX vap is implicit */
+ sta_roam_check(ss, vap);
+@@ -922,7 +925,11 @@ sta_assoc_fail(struct ieee80211_scan_sta
+ struct sta_table *st = ss->ss_priv;
+ struct sta_entry *se;
+
+- se = sta_lookup(st, macaddr);
++ /* Let outside apps to decide what peer is blacklisted */
++ if (ss->ss_vap->iv_ic->ic_roaming == IEEE80211_ROAMING_MANUAL)
++ return;
++
++ se = sta_lookup(st, macaddr, ss->ss_ssid);
+ if (se != NULL) {
+ se->se_fails++;
+ se->se_lastfail = jiffies;
+@@ -939,7 +946,7 @@ sta_assoc_success(struct ieee80211_scan_
+ struct sta_table *st = ss->ss_priv;
+ struct sta_entry *se;
+
+- se = sta_lookup(st, macaddr);
++ se = sta_lookup(st, macaddr, ss->ss_ssid);
+ if (se != NULL) {
+ #if 0
+ se->se_fails = 0;
diff --git a/package/madwifi/patches/368-sta_ie_preserve.patch b/package/madwifi/patches/368-sta_ie_preserve.patch
new file mode 100644
index 000000000..fbd779ea0
--- /dev/null
+++ b/package/madwifi/patches/368-sta_ie_preserve.patch
@@ -0,0 +1,49 @@
+--- a/net80211/ieee80211_scan_sta.c
++++ b/net80211/ieee80211_scan_sta.c
+@@ -201,8 +201,10 @@ sta_flush_table(struct sta_table *st)
+ }
+
+ static void
+-saveie(u_int8_t **iep, const u_int8_t *ie)
++saveie(u_int8_t **iep, const u_int8_t *ie, int preserve)
+ {
++ if (preserve && *iep)
++ return;
+ if (ie == NULL)
+ *iep = NULL;
+ else
+@@ -304,10 +306,10 @@ found:
+ (const struct ieee80211_tim_ie *) sp->tim;
+ ise->se_dtimperiod = tim->tim_period;
+ }
+- saveie(&ise->se_wme_ie, sp->wme);
+- saveie(&ise->se_wpa_ie, sp->wpa);
+- saveie(&ise->se_rsn_ie, sp->rsn);
+- saveie(&ise->se_ath_ie, sp->ath);
++ saveie(&ise->se_wme_ie, sp->wme, 0);
++ saveie(&ise->se_wpa_ie, sp->wpa, !sp->isprobe);
++ saveie(&ise->se_rsn_ie, sp->rsn, !sp->isprobe);
++ saveie(&ise->se_ath_ie, sp->ath, 0);
+
+ /* clear failure count after STA_FAIL_AGE passes */
+ if (se->se_fails && (jiffies - se->se_lastfail) > STA_FAILS_AGE*HZ) {
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -3106,6 +3106,7 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ */
+ IEEE80211_VERIFY_LENGTH(efrm - frm, 12);
+ memset(&scan, 0, sizeof(scan));
++ scan.isprobe = (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) && IEEE80211_ADDR_EQ(wh->i_addr2, vap->iv_myaddr);
+ scan.tstamp = frm;
+ frm += 8;
+ scan.bintval = le16toh(*(__le16 *)frm);
+--- a/net80211/ieee80211_scan.h
++++ b/net80211/ieee80211_scan.h
+@@ -133,6 +133,7 @@ struct ieee80211_scanparams {
+ u_int8_t erp;
+ u_int16_t bintval;
+ u_int8_t timoff;
++ u_int8_t isprobe;
+ u_int8_t *tim;
+ u_int8_t *tstamp;
+ u_int8_t *country;
diff --git a/package/madwifi/patches/369-mlme_assoc.patch b/package/madwifi/patches/369-mlme_assoc.patch
new file mode 100644
index 000000000..43aac668c
--- /dev/null
+++ b/package/madwifi/patches/369-mlme_assoc.patch
@@ -0,0 +1,10 @@
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -3723,6 +3723,7 @@ ieee80211_ioctl_setmlme(struct net_devic
+ if (vap->iv_opmode == IEEE80211_M_STA) {
+ struct scanlookup lookup;
+
++ preempt_scan(dev, 100, 100);
+ lookup.se = NULL;
+ lookup.mac = mlme->im_macaddr;
+ /* XXX use revised api w/ explicit ssid */
diff --git a/package/madwifi/patches/370-wdsvap.patch b/package/madwifi/patches/370-wdsvap.patch
new file mode 100644
index 000000000..8a0e823ae
--- /dev/null
+++ b/package/madwifi/patches/370-wdsvap.patch
@@ -0,0 +1,1665 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -124,7 +124,7 @@ enum {
+ };
+
+ static struct ieee80211vap *ath_vap_create(struct ieee80211com *,
+- const char *, int, int, struct net_device *);
++ const char *, int, int, struct net_device *, struct ieee80211vap *);
+ static void ath_vap_delete(struct ieee80211vap *);
+ static int ath_init(struct net_device *);
+ static int ath_set_ack_bitrate(struct ath_softc *, int);
+@@ -1123,8 +1123,6 @@ ath_attach(u_int16_t devid, struct net_d
+ autocreatemode = IEEE80211_M_IBSS;
+ else if (!strcmp(autocreate, "ahdemo"))
+ autocreatemode = IEEE80211_M_AHDEMO;
+- else if (!strcmp(autocreate, "wds"))
+- autocreatemode = IEEE80211_M_WDS;
+ else if (!strcmp(autocreate, "monitor"))
+ autocreatemode = IEEE80211_M_MONITOR;
+ else {
+@@ -1137,7 +1135,7 @@ ath_attach(u_int16_t devid, struct net_d
+ if (autocreatemode != -1) {
+ rtnl_lock();
+ vap = ieee80211_create_vap(ic, "ath%d", dev,
+- autocreatemode, 0);
++ autocreatemode, 0, NULL);
+ rtnl_unlock();
+ if (vap == NULL)
+ EPRINTF(sc, "Autocreation of %s VAP failed.", autocreate);
+@@ -1230,14 +1228,14 @@ ath_detach(struct net_device *dev)
+
+ static struct ieee80211vap *
+ ath_vap_create(struct ieee80211com *ic, const char *name,
+- int opmode, int flags, struct net_device *mdev)
++ int opmode, int flags, struct net_device *mdev, struct ieee80211vap *master)
+ {
+ struct ath_softc *sc = ic->ic_dev->priv;
+ struct ath_hal *ah = sc->sc_ah;
+ struct net_device *dev;
+ struct ath_vap *avp;
+ struct ieee80211vap *vap;
+- int ic_opmode;
++ int ic_opmode = IEEE80211_M_STA;
+
+ if (ic->ic_dev->flags & IFF_RUNNING) {
+ /* needs to disable hardware too */
+@@ -1271,8 +1269,12 @@ ath_vap_create(struct ieee80211com *ic,
+ } else
+ ic_opmode = opmode;
+ break;
+- case IEEE80211_M_HOSTAP:
+ case IEEE80211_M_WDS:
++ ic_opmode = ic->ic_opmode;
++ if (!master)
++ return NULL;
++ break;
++ case IEEE80211_M_HOSTAP:
+ /* permit multiple APs and/or WDS links */
+ /* XXX sta+ap for repeater/bridge application */
+ if ((sc->sc_nvaps != 0) && (ic->ic_opmode == IEEE80211_M_STA))
+@@ -1304,7 +1306,7 @@ ath_vap_create(struct ieee80211com *ic,
+ }
+
+ avp = dev->priv;
+- ieee80211_vap_setup(ic, dev, name, opmode, flags);
++ ieee80211_vap_setup(ic, dev, name, opmode, flags, master);
+ /* override with driver methods */
+ vap = &avp->av_vap;
+ avp->av_newstate = vap->iv_newstate;
+@@ -4209,8 +4211,7 @@ ath_calcrxfilter(struct ath_softc *sc)
+ if (ic->ic_opmode == IEEE80211_M_STA ||
+ sc->sc_opmode == HAL_M_IBSS || /* NB: AHDEMO too */
+ (sc->sc_nostabeacons) || sc->sc_scanning ||
+- ((ic->ic_opmode == IEEE80211_M_HOSTAP) &&
+- (ic->ic_protmode != IEEE80211_PROT_NONE)))
++ (ic->ic_opmode == IEEE80211_M_HOSTAP))
+ rfilt |= HAL_RX_FILTER_BEACON;
+ if (sc->sc_nmonvaps > 0)
+ rfilt |= (HAL_RX_FILTER_CONTROL | HAL_RX_FILTER_BEACON |
+@@ -9032,8 +9033,6 @@ ath_calibrate(unsigned long arg)
+ * set sc->beacons if we might need to restart
+ * them after ath_reset. */
+ if (!sc->sc_beacons &&
+- (TAILQ_FIRST(&ic->ic_vaps)->iv_opmode !=
+- IEEE80211_M_WDS) &&
+ !txcont_was_active &&
+ !sc->sc_dfs_cac) {
+ sc->sc_beacons = 1;
+--- a/net80211/ieee80211.c
++++ b/net80211/ieee80211.c
+@@ -373,10 +373,25 @@ void
+ ieee80211_ifdetach(struct ieee80211com *ic)
+ {
+ struct ieee80211vap *vap;
++ int count;
++
++ /* bring down all vaps */
++ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
++ ieee80211_stop(vap->iv_dev);
++ }
++
++ /* wait for all subifs to disappear */
++ do {
++ schedule();
++ rtnl_lock();
++ count = ic->ic_subifs;
++ rtnl_unlock();
++ } while (count > 0);
+
+ rtnl_lock();
+- while ((vap = TAILQ_FIRST(&ic->ic_vaps)) != NULL)
++ while ((vap = TAILQ_FIRST(&ic->ic_vaps)) != NULL) {
+ ic->ic_vap_delete(vap);
++ }
+ rtnl_unlock();
+
+ del_timer(&ic->ic_dfs_excl_timer);
+@@ -396,7 +411,7 @@ EXPORT_SYMBOL(ieee80211_ifdetach);
+
+ int
+ ieee80211_vap_setup(struct ieee80211com *ic, struct net_device *dev,
+- const char *name, int opmode, int flags)
++ const char *name, int opmode, int flags, struct ieee80211vap *master)
+ {
+ #define IEEE80211_C_OPMODE \
+ (IEEE80211_C_IBSS | IEEE80211_C_HOSTAP | IEEE80211_C_AHDEMO | \
+@@ -510,9 +525,18 @@ ieee80211_vap_setup(struct ieee80211com
+
+ vap->iv_monitor_crc_errors = 0;
+ vap->iv_monitor_phy_errors = 0;
++ TAILQ_INIT(&vap->iv_wdslinks);
+
+- IEEE80211_ADDR_COPY(vap->iv_myaddr, ic->ic_myaddr);
+- IEEE80211_ADDR_COPY(vap->iv_bssid, ic->ic_myaddr);
++ if (master && (vap->iv_opmode == IEEE80211_M_WDS)) {
++ vap->iv_master = master;
++ TAILQ_INSERT_TAIL(&master->iv_wdslinks, vap, iv_wdsnext);
++ /* use the same BSSID as the master interface */
++ IEEE80211_ADDR_COPY(vap->iv_myaddr, vap->iv_master->iv_myaddr);
++ IEEE80211_ADDR_COPY(vap->iv_bssid, vap->iv_master->iv_myaddr);
++ } else {
++ IEEE80211_ADDR_COPY(vap->iv_myaddr, ic->ic_myaddr);
++ IEEE80211_ADDR_COPY(vap->iv_bssid, ic->ic_myaddr);
++ }
+ /* NB: Defer setting dev_addr so driver can override */
+
+ ieee80211_crypto_vattach(vap);
+@@ -547,7 +571,8 @@ ieee80211_vap_attach(struct ieee80211vap
+ ifmedia_set(&vap->iv_media, imr.ifm_active);
+
+ IEEE80211_LOCK_IRQ(ic);
+- TAILQ_INSERT_TAIL(&ic->ic_vaps, vap, iv_next);
++ if (vap->iv_opmode != IEEE80211_M_WDS)
++ TAILQ_INSERT_TAIL(&ic->ic_vaps, vap, iv_next);
+ IEEE80211_UNLOCK_IRQ(ic);
+
+ IEEE80211_ADDR_COPY(dev->dev_addr, vap->iv_myaddr);
+@@ -579,10 +604,27 @@ ieee80211_vap_detach(struct ieee80211vap
+ {
+ struct ieee80211com *ic = vap->iv_ic;
+ struct net_device *dev = vap->iv_dev;
++ struct ieee80211vap *avp;
++
++ /* Drop all WDS links that belong to this vap */
++ while ((avp = TAILQ_FIRST(&vap->iv_wdslinks)) != NULL) {
++ if (avp->iv_state != IEEE80211_S_INIT)
++ ieee80211_stop(avp->iv_dev);
++ ic->ic_vap_delete(avp);
++ }
+
+ IEEE80211_CANCEL_TQUEUE(&vap->iv_stajoin1tq);
+ IEEE80211_LOCK_IRQ(ic);
+- TAILQ_REMOVE(&ic->ic_vaps, vap, iv_next);
++ if (vap->iv_wdsnode) {
++ vap->iv_wdsnode->ni_subif = NULL;
++ ieee80211_unref_node(&vap->iv_wdsnode);
++ }
++ if ((vap->iv_opmode == IEEE80211_M_WDS) &&
++ (vap->iv_master != NULL))
++ TAILQ_REMOVE(&vap->iv_master->iv_wdslinks, vap, iv_wdsnext);
++ else
++ TAILQ_REMOVE(&ic->ic_vaps, vap, iv_next);
++
+ if (TAILQ_EMPTY(&ic->ic_vaps)) /* reset to supported mode */
+ ic->ic_opmode = IEEE80211_M_STA;
+ IEEE80211_UNLOCK_IRQ(ic);
+--- a/net80211/ieee80211_ioctl.h
++++ b/net80211/ieee80211_ioctl.h
+@@ -474,7 +474,7 @@ struct ieee80211req {
+ #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_SETMAC 55 /* set interface wds mac addr */
+ #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 */
+@@ -552,8 +552,8 @@ struct ieee80211req_scan_result {
+ #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_WDSADDMAC (SIOCIWFIRSTPRIV+25)
++#define IEEE80211_IOCTL_WDSSETMAC (SIOCIWFIRSTPRIV+26)
+ #define IEEE80211_IOCTL_KICKMAC (SIOCIWFIRSTPRIV+30)
+ #define IEEE80211_IOCTL_SETSCANLIST (SIOCIWFIRSTPRIV+31)
+
+@@ -649,6 +649,7 @@ enum {
+ IEEE80211_PARAM_BGSCAN_THRESH = 79, /* bg scan rssi threshold */
+ IEEE80211_PARAM_RSSI_DIS_THR = 80, /* rssi threshold for disconnection */
+ IEEE80211_PARAM_RSSI_DIS_COUNT = 81, /* counter for rssi threshold */
++ IEEE80211_PARAM_WDS_SEP = 82, /* move wds stations into separate interfaces */
+ };
+
+ #define SIOCG80211STATS (SIOCDEVPRIVATE+2)
+--- a/net80211/ieee80211_linux.h
++++ b/net80211/ieee80211_linux.h
+@@ -81,6 +81,12 @@ set_quality(struct iw_quality *iq, u_int
+ #endif
+ }
+
++#ifndef container_of
++#define container_of(ptr, type, member) ({ \
++ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
++ (type *)( (char *)__mptr - offsetof(type,member) );})
++#endif
++
+ /*
+ * Task deferral
+ *
+@@ -113,6 +119,29 @@ typedef void *IEEE80211_TQUEUE_ARG;
+
+ #define IEEE80211_RESCHEDULE schedule
+
++#include <linux/sched.h>
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,41)
++#include <linux/tqueue.h>
++#define work_struct tq_struct
++#define schedule_work(t) schedule_task((t))
++#define flush_scheduled_work() flush_scheduled_tasks()
++#define IEEE80211_INIT_WORK(t, f) do { \
++ memset((t), 0, sizeof(struct tq_struct)); \
++ (t)->routine = (void (*)(void*)) (f); \
++ (t)->data=(void *) (t); \
++} while (0)
++#else
++#include <linux/workqueue.h>
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
++#define IEEE80211_INIT_WORK(_t, _f) INIT_WORK((_t), (void (*)(void *))(_f), (_t));
++#else
++#define IEEE80211_INIT_WORK(_t, _f) INIT_WORK((_t), (_f));
++#endif
++
++#endif /* KERNEL_VERSION < 2.5.41 */
++
++
+ /* Locking */
+ /* NB: beware, spin_is_locked() is not usefully defined for !(DEBUG || SMP)
+ * because spinlocks do not exist in this configuration. Instead IRQs
+@@ -167,6 +196,14 @@ typedef spinlock_t ieee80211com_lock_t;
+ IEEE80211_VAPS_LOCK_ASSERT(_ic); \
+ spin_unlock_bh(&(_ic)->ic_vapslock); \
+ } while (0)
++#define IEEE80211_VAPS_LOCK_IRQ(_ic) do { \
++ unsigned long __ilockflags; \
++ IEEE80211_VAPS_LOCK_CHECK(_ic); \
++ spin_lock_irqsave(&(_ic)->ic_vapslock, __ilockflags);
++#define IEEE80211_VAPS_UNLOCK_IRQ(_ic) \
++ IEEE80211_VAPS_LOCK_ASSERT(_ic); \
++ spin_unlock_irqrestore(&(_ic)->ic_vapslock, __ilockflags); \
++} while (0)
+
+ #if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
+ #define IEEE80211_VAPS_LOCK_ASSERT(_ic) \
+@@ -650,5 +687,5 @@ 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);
++ struct net_device *, int, int, struct ieee80211vap *);
+ #endif /* _NET80211_IEEE80211_LINUX_H_ */
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -187,6 +187,12 @@ struct ieee80211vap {
+ struct ieee80211_proc_entry *iv_proc_entries;
+ struct vlan_group *iv_vlgrp; /* vlan group state */
+
++ /* list of wds links */
++ TAILQ_HEAD(, ieee80211vap) iv_wdslinks;
++ TAILQ_ENTRY(ieee80211vap) iv_wdsnext;
++ struct ieee80211vap *iv_master;
++ struct ieee80211_node *iv_wdsnode;
++
+ 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 */
+@@ -316,6 +322,7 @@ struct ieee80211com {
+ u_int8_t ic_myaddr[IEEE80211_ADDR_LEN];
+ struct timer_list ic_inact; /* mgmt/inactivity timer */
+
++ unsigned int ic_subifs;
+ u_int32_t ic_flags; /* state flags */
+ u_int32_t ic_flags_ext; /* extension of state flags */
+ u_int32_t ic_caps; /* capabilities */
+@@ -447,7 +454,7 @@ struct ieee80211com {
+ atomic_t ic_node_counter;
+ /* Virtual AP create/delete */
+ struct ieee80211vap *(*ic_vap_create)(struct ieee80211com *,
+- const char *, int, int, struct net_device *);
++ const char *, int, int, struct net_device *, struct ieee80211vap *);
+ void (*ic_vap_delete)(struct ieee80211vap *);
+
+ /* Send/recv 802.11 management frame */
+@@ -619,6 +626,7 @@ MALLOC_DECLARE(M_80211_VAP);
+ #define IEEE80211_FEXT_DROPUNENC_EAPOL 0x00000800 /* CONF: drop unencrypted eapol frames */
+ #define IEEE80211_FEXT_APPIE_UPDATE 0x00001000 /* STATE: beacon APP IE updated */
+ #define IEEE80211_FEXT_BGSCAN_THR 0x00002000 /* bgscan due to low rssi */
++#define IEEE80211_FEXT_WDSSEP 0x00004000 /* move wds clients into separate interfaces */
+
+ #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)
+@@ -703,7 +711,7 @@ MALLOC_DECLARE(M_80211_VAP);
+ int ieee80211_ifattach(struct ieee80211com *);
+ void ieee80211_ifdetach(struct ieee80211com *);
+ int ieee80211_vap_setup(struct ieee80211com *, struct net_device *,
+- const char *, int, int);
++ const char *, int, int, struct ieee80211vap *);
+ 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 *);
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -2190,7 +2190,7 @@ ieee80211_setupxr(struct ieee80211vap *v
+ ieee80211_scan_flush(ic); /* NB: could optimize */
+
+ if (!(xrvap = ic->ic_vap_create(ic, name, IEEE80211_M_HOSTAP,
+- IEEE80211_VAP_XR | IEEE80211_CLONE_BSSID, dev)))
++ IEEE80211_VAP_XR | IEEE80211_CLONE_BSSID, dev, NULL)))
+ return;
+
+ /* We use iv_xrvap to link to the parent VAP as well */
+@@ -2867,6 +2867,14 @@ ieee80211_ioctl_setparam(struct net_devi
+ else
+ vap->iv_minrateindex = 0;
+ break;
++ case IEEE80211_PARAM_WDS_SEP:
++ if (vap->iv_opmode != IEEE80211_M_HOSTAP)
++ retv = -EINVAL;
++ else if (value)
++ vap->iv_flags_ext |= IEEE80211_FEXT_WDSSEP;
++ else
++ vap->iv_flags_ext &= ~IEEE80211_FEXT_WDSSEP;
++ break;
+ #ifdef ATH_REVERSE_ENGINEERING
+ case IEEE80211_PARAM_DUMPREGS:
+ ieee80211_dump_registers(dev, info, w, extra);
+@@ -3223,6 +3231,9 @@ ieee80211_ioctl_getparam(struct net_devi
+ case IEEE80211_PARAM_MINRATE:
+ param[0] = vap->iv_minrateindex;
+ break;
++ case IEEE80211_PARAM_WDS_SEP:
++ param[0] = !!(vap->iv_flags_ext & IEEE80211_FEXT_WDSSEP);
++ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+@@ -3801,74 +3812,54 @@ ieee80211_ioctl_setmlme(struct net_devic
+ return 0;
+ }
+
++#define WDSNAME ".wds%d"
+ static int
+-ieee80211_ioctl_wdsmac(struct net_device *dev, struct iw_request_info *info,
++ieee80211_ioctl_wdsaddmac(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+ struct ieee80211vap *vap = dev->priv;
+ struct sockaddr *sa = (struct sockaddr *)extra;
++ struct ieee80211com *ic = vap->iv_ic;
++ struct ieee80211vap *avp;
++ char *name;
+
+- if (!IEEE80211_ADDR_NULL(vap->wds_mac)) {
+- printk("%s: Failed to add WDS MAC: " MAC_FMT "\n", dev->name,
+- MAC_ADDR(sa->sa_data));
+- printk("%s: Device already has WDS mac address attached,"
+- " remove first\n", dev->name);
+- return -1;
+- }
+-
+- memcpy(vap->wds_mac, sa->sa_data, IEEE80211_ADDR_LEN);
++ if (vap->iv_opmode != IEEE80211_M_HOSTAP)
++ return -EINVAL;
+
+- printk("%s: Added WDS MAC: " MAC_FMT "\n", dev->name,
+- MAC_ADDR(vap->wds_mac));
++ name = kmalloc(strlen(vap->iv_dev->name) + sizeof(WDSNAME) + 1, GFP_KERNEL);
++ if (!name)
++ return -ENOMEM;
+
+- if (IS_UP(vap->iv_dev)) {
+- /* Force us back to scan state to force us to go back through RUN
+- * state and create/pin the WDS peer node into memory. */
+- return ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
+- }
++ strcpy(name, vap->iv_dev->name);
++ strcat(name, WDSNAME);
++ avp = ieee80211_create_vap(ic, name, ic->ic_dev, IEEE80211_M_WDS, 0, vap);
++ kfree(name);
++ if (!avp)
++ return -ENOMEM;
+
++ memcpy(avp->wds_mac, sa->sa_data, IEEE80211_ADDR_LEN);
+ return 0;
+ }
++#undef WDSNAME
+
+ static int
+-ieee80211_ioctl_wdsdelmac(struct net_device *dev, struct iw_request_info *info,
++ieee80211_ioctl_wdssetmac(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+ struct ieee80211vap *vap = dev->priv;
+ struct sockaddr *sa = (struct sockaddr *)extra;
+- struct ieee80211com *ic = vap->iv_ic;
+- struct ieee80211_node *wds_ni;
+
+- /* WDS Mac address filed already? */
+- if (IEEE80211_ADDR_NULL(vap->wds_mac))
+- return 0;
++ if (vap->iv_opmode != IEEE80211_M_WDS)
++ return -EINVAL;
+
+- /* Compare suplied MAC address with WDS MAC of this interface
+- * remove when mac address is known
+- */
+- if (memcmp(vap->wds_mac, sa->sa_data, IEEE80211_ADDR_LEN) == 0) {
+- if (IS_UP(vap->iv_dev)) {
+- wds_ni = ieee80211_find_txnode(vap, vap->wds_mac);
+- if (wds_ni != NULL) {
+- /* Release reference created by find node */
+- ieee80211_unref_node(&wds_ni);
+- /* Release reference created by transition to RUN state,
+- * [pinning peer node into the table] */
+- ieee80211_unref_node(&wds_ni);
+- }
+- }
+- memset(vap->wds_mac, 0x00, IEEE80211_ADDR_LEN);
+- if (IS_UP(vap->iv_dev)) {
+- /* This leaves a dead WDS node, until started again */
+- return ic->ic_reset(ic->ic_dev);
+- }
+- return 0;
++ memcpy(vap->wds_mac, sa->sa_data, IEEE80211_ADDR_LEN);
++ if (IS_UP(vap->iv_dev)) {
++ /* Force us back to scan state to force us to go back through RUN
++ * state and create/pin the WDS peer node into memory. */
++ return ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
+ }
+
+- printk("%s: WDS MAC address " MAC_FMT " is not known by this interface\n",
+- dev->name, MAC_ADDR(sa->sa_data));
+-
+- return -1;
++ return 0;
+ }
+
+ /*
+@@ -4470,6 +4461,8 @@ get_sta_space(void *arg, struct ieee8021
+ struct ieee80211vap *vap = ni->ni_vap;
+ size_t ielen;
+
++ if (req->vap->iv_wdsnode && ni->ni_subif)
++ vap = ni->ni_subif;
+ if (vap != req->vap && vap != req->vap->iv_xrvap) /* only entries for this vap */
+ return;
+ if ((vap->iv_opmode == IEEE80211_M_HOSTAP ||
+@@ -4489,6 +4482,8 @@ get_sta_info(void *arg, struct ieee80211
+ size_t ielen, len;
+ u_int8_t *cp;
+
++ if (req->vap->iv_wdsnode && ni->ni_subif)
++ vap = ni->ni_subif;
+ if (vap != req->vap && vap != req->vap->iv_xrvap) /* only entries for this vap (or) xrvap */
+ return;
+ if ((vap->iv_opmode == IEEE80211_M_HOSTAP ||
+@@ -5391,8 +5386,8 @@ static const struct iw_priv_args ieee802
+ IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "kickmac"},
+ { IEEE80211_IOCTL_WDSADDMAC,
+ IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0,"wds_add" },
+- { IEEE80211_IOCTL_WDSDELMAC,
+- IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0,"wds_del" },
++ { IEEE80211_IOCTL_WDSSETMAC,
++ IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0,"wds_set" },
+ { IEEE80211_IOCTL_SETCHANLIST,
+ IW_PRIV_TYPE_CHANLIST | IW_PRIV_SIZE_FIXED, 0,"setchanlist" },
+ { IEEE80211_IOCTL_GETCHANLIST,
+@@ -5790,6 +5785,10 @@ static const struct iw_priv_args ieee802
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_minrate"},
+ { IEEE80211_IOCTL_SETSCANLIST,
+ IW_PRIV_TYPE_CHAR | 255, 0, "setscanlist"},
++ { IEEE80211_PARAM_WDS_SEP,
++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wdssep"},
++ { IEEE80211_PARAM_WDS_SEP,
++ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_wdssep"},
+
+ #ifdef ATH_REVERSE_ENGINEERING
+ /*
+@@ -5884,8 +5883,8 @@ static const iw_handler ieee80211_priv_h
+ #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),
+- set_priv(IEEE80211_IOCTL_WDSDELMAC, ieee80211_ioctl_wdsdelmac),
++ set_priv(IEEE80211_IOCTL_WDSADDMAC, ieee80211_ioctl_wdsaddmac),
++ set_priv(IEEE80211_IOCTL_WDSSETMAC, ieee80211_ioctl_wdssetmac),
+ set_priv(IEEE80211_IOCTL_KICKMAC, ieee80211_ioctl_kickmac),
+ set_priv(IEEE80211_IOCTL_SETSCANLIST, ieee80211_ioctl_setscanlist),
+ #ifdef ATH_REVERSE_ENGINEERING
+@@ -5913,6 +5912,8 @@ static int
+ ieee80211_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ {
+ struct ieee80211vap *vap = dev->priv;
++ struct ieee80211com *ic = vap->iv_ic;
++ struct ieee80211_node *ni;
+
+ switch (cmd) {
+ case SIOCG80211STATS:
+@@ -5921,8 +5922,20 @@ ieee80211_ioctl(struct net_device *dev,
+ case SIOC80211IFDESTROY:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
++ /* drop all node subifs */
++ TAILQ_FOREACH(ni, &ic->ic_sta.nt_node, ni_list) {
++ struct ieee80211vap *avp = ni->ni_subif;
++
++ if (ni->ni_vap != vap)
++ continue;
++ if (!avp)
++ continue;
++ ni->ni_subif = NULL;
++ ieee80211_stop(avp->iv_dev);
++ ic->ic_vap_delete(avp);
++ }
+ ieee80211_stop(vap->iv_dev); /* force state before cleanup */
+- vap->iv_ic->ic_vap_delete(vap);
++ ic->ic_vap_delete(vap);
+ return 0;
+ case IEEE80211_IOCTL_GETKEY:
+ return ieee80211_ioctl_getkey(dev, (struct iwreq *) ifr);
+@@ -5956,7 +5969,7 @@ ieee80211_ioctl_create_vap(struct ieee80
+
+ strncpy(name, cp.icp_name, sizeof(name));
+
+- vap = ieee80211_create_vap(ic, name, mdev, cp.icp_opmode, cp.icp_flags);
++ vap = ieee80211_create_vap(ic, name, mdev, cp.icp_opmode, cp.icp_flags, NULL);
+ if (vap == NULL)
+ return -EIO;
+
+@@ -5973,9 +5986,9 @@ EXPORT_SYMBOL(ieee80211_ioctl_create_vap
+ */
+ struct ieee80211vap*
+ ieee80211_create_vap(struct ieee80211com *ic, char *name,
+- struct net_device *mdev, int opmode, int opflags)
++ struct net_device *mdev, int opmode, int opflags, struct ieee80211vap *master)
+ {
+- return ic->ic_vap_create(ic, name, opmode, opflags, mdev);
++ return ic->ic_vap_create(ic, name, opmode, opflags, mdev, master);
+ }
+ EXPORT_SYMBOL(ieee80211_create_vap);
+
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -199,8 +199,10 @@ ieee80211_input(struct ieee80211vap * va
+ {
+ #define HAS_SEQ(type) ((type & 0x4) == 0)
+ struct ieee80211_node * ni = ni_or_null;
+- struct ieee80211com *ic = vap->iv_ic;
+- struct net_device *dev = vap->iv_dev;
++ struct ieee80211com *ic;
++ struct net_device *dev;
++ struct ieee80211_node *ni_wds = NULL;
++ struct net_device_stats *stats;
+ struct ieee80211_frame *wh;
+ struct ieee80211_key *key;
+ struct ether_header *eh;
+@@ -212,6 +214,19 @@ ieee80211_input(struct ieee80211vap * va
+ u_int8_t *bssid;
+ u_int16_t rxseq;
+
++ type = -1; /* undefined */
++
++ if (!vap)
++ goto out;
++
++ ic = vap->iv_ic;
++ if (!ic)
++ goto out;
++
++ dev = vap->iv_dev;
++ if (!dev)
++ goto out;
++
+ /* initialize ni as in the previous API */
+ if (ni_or_null == NULL) {
+ /* This function does not 'own' vap->iv_bss, so we cannot
+@@ -227,7 +242,6 @@ ieee80211_input(struct ieee80211vap * va
+
+ /* XXX adjust device in sk_buff? */
+
+- type = -1; /* undefined */
+ /*
+ * In monitor mode, send everything directly to bpf.
+ * Also do not process frames w/o i_addr2 any further.
+@@ -434,7 +448,7 @@ ieee80211_input(struct ieee80211vap * va
+
+ switch (type) {
+ case IEEE80211_FC0_TYPE_DATA:
+- hdrspace = ieee80211_hdrspace(ic, wh);
++ hdrspace = ieee80211_hdrsize(wh);
+ if (skb->len < hdrspace) {
+ IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
+ wh, "data", "too short: len %u, expecting %u",
+@@ -444,16 +458,24 @@ ieee80211_input(struct ieee80211vap * va
+ }
+ switch (vap->iv_opmode) {
+ case IEEE80211_M_STA:
+- if ((dir != IEEE80211_FC1_DIR_FROMDS) &&
+- (!((vap->iv_flags_ext & IEEE80211_FEXT_WDS) &&
+- (dir == IEEE80211_FC1_DIR_DSTODS)))) {
++ switch(dir) {
++ case IEEE80211_FC1_DIR_FROMDS:
++ break;
++ case IEEE80211_FC1_DIR_DSTODS:
++ if (vap->iv_flags_ext & IEEE80211_FEXT_WDS)
++ break;
++ default:
+ IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
+ wh, "data", "invalid dir 0x%x", dir);
+ vap->iv_stats.is_rx_wrongdir++;
+ goto out;
+ }
+
+- if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
++ if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
++ /* ignore 3-addr mcast if we're WDS STA */
++ if (vap->iv_flags_ext & IEEE80211_FEXT_WDS)
++ goto out;
++
+ /* Discard multicast if IFF_MULTICAST not set */
+ if ((0 != memcmp(wh->i_addr3, dev->broadcast, ETH_ALEN)) &&
+ (0 == (dev->flags & IFF_MULTICAST))) {
+@@ -481,24 +503,10 @@ ieee80211_input(struct ieee80211vap * va
+ vap->iv_stats.is_rx_mcastecho++;
+ goto out;
+ }
+- /*
+- * if it is brodcasted by me on behalf of
+- * a station behind me, drop it.
+- */
+- if (vap->iv_flags_ext & IEEE80211_FEXT_WDS) {
+- struct ieee80211_node_table *nt;
+- struct ieee80211_node *ni_wds;
+- nt = &ic->ic_sta;
+- ni_wds = ieee80211_find_wds_node(nt, wh->i_addr3);
+- if (ni_wds) {
+- ieee80211_unref_node(&ni_wds);
+- IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
+- wh, NULL, "%s",
+- "multicast echo originated from node behind me");
+- vap->iv_stats.is_rx_mcastecho++;
+- goto out;
+- }
+- }
++ } else {
++ /* Same BSSID, but not meant for us to receive */
++ if (!IEEE80211_ADDR_EQ(wh->i_addr1, vap->iv_myaddr))
++ goto out;
+ }
+ break;
+ case IEEE80211_M_IBSS:
+@@ -540,16 +548,28 @@ ieee80211_input(struct ieee80211vap * va
+ vap->iv_stats.is_rx_notassoc++;
+ goto err;
+ }
++
+ /*
+ * If we're a 4 address packet, make sure we have an entry in
+ * the node table for the packet source address (addr4).
+ * If not, add one.
+ */
++ /* check for wds link first */
++ if ((dir == IEEE80211_FC1_DIR_DSTODS) && !ni->ni_subif) {
++ if (vap->iv_flags_ext & IEEE80211_FEXT_WDSSEP) {
++ ieee80211_wds_addif(ni);
++ /* we must drop frames here until the interface has
++ * been fully separated, otherwise a bridge might get
++ * confused */
++ goto err;
++ }
++ }
++
+ /* XXX: Useless node mgmt API; make better */
+- if (dir == IEEE80211_FC1_DIR_DSTODS) {
+- struct ieee80211_node_table *nt;
++ if ((dir == IEEE80211_FC1_DIR_DSTODS) && !vap->iv_wdsnode &&
++ !ni_wds && !ni->ni_subif) {
++ struct ieee80211_node_table *nt = &ic->ic_sta;
+ struct ieee80211_frame_addr4 *wh4;
+- struct ieee80211_node *ni_wds;
+
+ if (!(vap->iv_flags_ext & IEEE80211_FEXT_WDS)) {
+ IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
+@@ -557,7 +577,6 @@ ieee80211_input(struct ieee80211vap * va
+ goto err;
+ }
+ wh4 = (struct ieee80211_frame_addr4 *)skb->data;
+- nt = &ic->ic_sta;
+ ni_wds = ieee80211_find_wds_node(nt, wh4->i_addr4);
+ /* Last call increments ref count if !NULL */
+ if ((ni_wds != NULL) && (ni_wds != ni)) {
+@@ -608,6 +627,11 @@ ieee80211_input(struct ieee80211vap * va
+ goto out;
+ }
+
++ /* check if there is any data left */
++ hdrspace = ieee80211_hdrspace(ic, wh);
++ if (skb->len < hdrspace)
++ goto out;
++
+ /*
+ * Handle privacy requirements. Note that we
+ * must not be preempted from here until after
+@@ -680,8 +704,12 @@ ieee80211_input(struct ieee80211vap * va
+ if (! accept_data_frame(vap, ni, key, skb, eh))
+ goto out;
+
+- vap->iv_devstats.rx_packets++;
+- vap->iv_devstats.rx_bytes += skb->len;
++ if (ni->ni_subif && ((eh)->ether_type != __constant_htons(ETHERTYPE_PAE)))
++ stats = &ni->ni_subif->iv_devstats;
++ else
++ stats = &vap->iv_devstats;
++ stats->rx_packets++;
++ stats->rx_bytes += skb->len;
+ IEEE80211_NODE_STAT(ni, rx_data);
+ IEEE80211_NODE_STAT_ADD(ni, rx_bytes, skb->len);
+ ic->ic_lastdata = jiffies;
+@@ -1114,6 +1142,18 @@ ieee80211_deliver_data(struct ieee80211_
+ dev = vap->iv_xrvap->iv_dev;
+ #endif
+
++ /* if the node has a wds subif, move data frames there,
++ * but keep EAP traffic on the master */
++ if (ni->ni_subif && ((eh)->ether_type != __constant_htons(ETHERTYPE_PAE))) {
++ if (ni->ni_vap == ni->ni_subif) {
++ ieee80211_dev_kfree_skb(&skb);
++ return;
++ } else {
++ vap = ni->ni_subif;
++ dev = vap->iv_dev;
++ }
++ }
++
+ /* perform as a bridge within the vap */
+ /* XXX intra-vap bridging only */
+ if (vap->iv_opmode == IEEE80211_M_HOSTAP &&
+@@ -1139,7 +1179,16 @@ ieee80211_deliver_data(struct ieee80211_
+ if (ni1 != NULL) {
+ if (ni1->ni_vap == vap &&
+ ieee80211_node_is_authorized(ni1) &&
++ !ni1->ni_subif &&
+ ni1 != vap->iv_bss) {
++
++ /* tried to bridge to a subif, drop the packet */
++ if (ni->ni_subif) {
++ ieee80211_unref_node(&ni1);
++ ieee80211_dev_kfree_skb(&skb);
++ return;
++ }
++
+ skb1 = skb;
+ skb = NULL;
+ }
+@@ -3084,8 +3133,7 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ (vap->iv_opmode == IEEE80211_M_STA && ni->ni_associd) ||
+ (vap->iv_opmode == IEEE80211_M_IBSS) ||
+ ((subtype == IEEE80211_FC0_SUBTYPE_BEACON) &&
+- (vap->iv_opmode == IEEE80211_M_HOSTAP) &&
+- (ic->ic_protmode != IEEE80211_PROT_NONE)))) {
++ (vap->iv_opmode == IEEE80211_M_HOSTAP)))) {
+ vap->iv_stats.is_rx_mgtdiscard++;
+ return;
+ }
+@@ -3471,13 +3519,56 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ */
+ if (ic->ic_flags & IEEE80211_F_SCAN) {
+ ieee80211_add_scan(vap, &scan, wh, subtype, rssi, rtsf);
+- return;
+ }
+- if ((vap->iv_opmode == IEEE80211_M_IBSS) &&
+- (scan.capinfo & IEEE80211_CAPINFO_IBSS)) {
++ /* NB: Behavior of WDS-Link and Ad-Hoc is very similar here:
++ * When we receive a beacon that belongs to the AP that we're
++ * connected to, use it to refresh the local node info.
++ * If no node is found, go through the vap's wds link table
++ * and try to find the sub-vap that is interested in this address
++ */
++ if (((vap->iv_opmode == IEEE80211_M_IBSS) &&
++ (scan.capinfo & IEEE80211_CAPINFO_IBSS)) ||
++ (((vap->iv_opmode == IEEE80211_M_HOSTAP) ||
++ (vap->iv_opmode == IEEE80211_M_WDS)) &&
++ (scan.capinfo & IEEE80211_CAPINFO_ESS))) {
++ struct ieee80211vap *avp = NULL;
++ int found = 0;
++
++ IEEE80211_LOCK_IRQ(vap->iv_ic);
++ if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
++ TAILQ_FOREACH(avp, &vap->iv_wdslinks, iv_wdsnext) {
++ if (!memcmp(avp->wds_mac, wh->i_addr2, IEEE80211_ADDR_LEN)) {
++ if (avp->iv_state != IEEE80211_S_RUN)
++ continue;
++ if (!avp->iv_wdsnode)
++ continue;
++ found = 1;
++ break;
++ }
++ }
++ if (found)
++ ni = ni_or_null = avp->iv_wdsnode;
++ } else if ((vap->iv_opmode == IEEE80211_M_WDS) && vap->iv_wdsnode) {
++ found = 1;
++ ni = ni_or_null = vap->iv_wdsnode;
++ }
++ IEEE80211_UNLOCK_IRQ(vap->iv_ic);
++
++ if (!found)
++ break;
++
+ if (ni_or_null == NULL) {
+- /* Create a new entry in the neighbor table. */
+- ni = ieee80211_add_neighbor(vap, wh, &scan);
++ if (avp) {
++ IEEE80211_LOCK_IRQ(ic);
++ ni = ieee80211_add_neighbor(avp, wh, &scan);
++ /* force assoc */
++ ni->ni_associd |= 0xc000;
++ avp->iv_wdsnode = ieee80211_ref_node(ni);
++ IEEE80211_UNLOCK_IRQ(ic);
++ } else if (vap->iv_opmode == IEEE80211_M_IBSS) {
++ /* Create a new entry in the neighbor table. */
++ ni = ieee80211_add_neighbor(vap, wh, &scan);
++ }
+ } else {
+ /*
+ * Copy data from beacon to neighbor table.
+@@ -3490,6 +3581,7 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
+ memcpy(ni->ni_tstamp.data, scan.tstamp,
+ sizeof(ni->ni_tstamp));
++ ni->ni_inact = ni->ni_inact_reload;
+ ni->ni_intval =
+ IEEE80211_BINTVAL_SANITISE(scan.bintval);
+ ni->ni_capinfo = scan.capinfo;
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -47,6 +47,7 @@
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+ #include <linux/random.h>
++#include <linux/rtnetlink.h>
+
+ #include "if_media.h"
+
+@@ -236,7 +237,11 @@ void
+ ieee80211_node_vdetach(struct ieee80211vap *vap)
+ {
+ struct ieee80211com *ic = vap->iv_ic;
++ struct ieee80211_node *ni;
+
++ ni = vap->iv_wdsnode;
++ if (ni)
++ ni->ni_subif = NULL;
+ ieee80211_node_table_reset(&ic->ic_sta, vap);
+ if (vap->iv_bss != NULL) {
+ ieee80211_unref_node(&vap->iv_bss);
+@@ -309,7 +314,7 @@ ieee80211_create_ibss(struct ieee80211va
+ /* Check to see if we already have a node for this mac
+ * NB: we gain a node reference here
+ */
+- ni = ieee80211_find_node(&ic->ic_sta, vap->iv_myaddr);
++ ni = ieee80211_find_txnode(vap, vap->iv_myaddr);
+ if (ni == NULL) {
+ ni = ieee80211_alloc_node_table(vap, vap->iv_myaddr);
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,
+@@ -831,12 +836,18 @@ node_table_leave_locked(struct ieee80211
+ LIST_REMOVE(ni, ni_hash);
+ }
+ ni->ni_table = NULL;
++ if (ni->ni_vap->iv_wdsnode == ni) {
++#ifdef IEEE80211_DEBUG_REFCNT
++ ieee80211_unref_node_debug(&ni->ni_vap->iv_wdsnode, func, line);
++#else
++ ieee80211_unref_node(&ni->ni_vap->iv_wdsnode);
++#endif
++ }
+ #ifdef IEEE80211_DEBUG_REFCNT
+ ieee80211_unref_node_debug(&ni, func, line);
+ #else
+ ieee80211_unref_node(&ni);
+ #endif
+-
+ }
+
+ /* This is overridden by ath_node_alloc in ath/if_ath.c, and so
+@@ -1134,6 +1145,65 @@ ieee80211_alloc_node(struct ieee80211vap
+ return ni;
+ }
+
++#define WDSIFNAME ".sta%d"
++static void
++ieee80211_wds_do_addif(struct work_struct *work)
++{
++ struct ieee80211_node *ni = container_of(work, struct ieee80211_node, ni_create);
++ struct ieee80211vap *vap = ni->ni_vap;
++ struct ieee80211com *ic = vap->iv_ic;
++ struct ieee80211vap *avp = NULL;
++ char *name;
++
++ rtnl_lock();
++ /* did we get cancelled by the destroy call? */
++ if (!ni->ni_subif)
++ goto done;
++
++ ni->ni_subif = NULL;
++ name = kmalloc(strlen(vap->iv_dev->name) + sizeof(WDSIFNAME) + 1, GFP_KERNEL);
++ if (!name)
++ goto done;
++
++ strcpy(name, vap->iv_dev->name);
++ strcat(name, WDSIFNAME);
++ avp = ieee80211_create_vap(ic, name, ic->ic_dev, IEEE80211_M_WDS, 0, vap);
++ kfree(name);
++ if (!avp)
++ goto done;
++
++ memcpy(avp->wds_mac, ni->ni_bssid, IEEE80211_ADDR_LEN);
++ avp->iv_wdsnode = ieee80211_ref_node(ni);
++ ni->ni_subif = avp;
++ ic->ic_subifs++;
++
++done:
++ if (avp) {
++ IEEE80211_VAPS_LOCK_IRQ(ic);
++ avp->iv_newstate(vap, IEEE80211_S_RUN, -1);
++ IEEE80211_VAPS_UNLOCK_IRQ(ic);
++ }
++ rtnl_unlock();
++ ieee80211_unref_node(&ni);
++}
++#undef WDSIFNAME
++
++void ieee80211_wds_addif(struct ieee80211_node *ni)
++{
++ /* check if the node is split out already,
++ * or if we're in progress of setting up a new interface already */
++ if (ni->ni_subif)
++ return;
++
++ if (!ni->ni_table)
++ return;
++
++ ieee80211_ref_node(ni);
++ ni->ni_subif = ni->ni_vap;
++ IEEE80211_INIT_WORK(&ni->ni_create, ieee80211_wds_do_addif);
++ schedule_work(&ni->ni_create);
++}
++
+ /* Add wds address to the node table */
+ int
+ #ifdef IEEE80211_DEBUG_REFCNT
+@@ -1553,22 +1623,39 @@ ieee80211_find_rxnode(struct ieee80211co
+ ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_PS_POLL)
+ struct ieee80211_node_table *nt;
+ struct ieee80211_node *ni;
++ struct ieee80211vap *vap, *avp;
++ const u_int8_t *addr;
++
++ if (IS_CTL(wh) && !IS_PSPOLL(wh) /*&& !IS_RTS(ah)*/)
++ addr = wh->i_addr1;
++ else
++ addr = wh->i_addr2;
++
++ if (IEEE80211_IS_MULTICAST(addr))
++ return NULL;
+
+ /* XXX check ic_bss first in station mode */
+ /* XXX 4-address frames? */
+ nt = &ic->ic_sta;
+ IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
+- if (IS_CTL(wh) && !IS_PSPOLL(wh) /*&& !IS_RTS(ah)*/)
+-#ifdef IEEE80211_DEBUG_REFCNT
+- ni = ieee80211_find_node_locked_debug(nt, wh->i_addr1, func, line);
+-#else
+- ni = ieee80211_find_node_locked(nt, wh->i_addr1);
+-#endif
+- else
++ if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) {
++ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
++ TAILQ_FOREACH(avp, &vap->iv_wdslinks, iv_wdsnext) {
++ if (!IEEE80211_ADDR_EQ(addr, avp->wds_mac))
++ continue;
++
++ if (avp->iv_wdsnode)
++ return ieee80211_ref_node(avp->iv_wdsnode);
++ else
++ return NULL;
++ }
++ }
++ }
++
+ #ifdef IEEE80211_DEBUG_REFCNT
+- ni = ieee80211_find_node_locked_debug(nt, wh->i_addr2, func, line);
++ ni = ieee80211_find_node_locked_debug(nt, addr, func, line);
+ #else
+- ni = ieee80211_find_node_locked(nt, wh->i_addr2);
++ ni = ieee80211_find_node_locked(nt, addr);
+ #endif
+ IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
+
+@@ -1596,9 +1683,19 @@ ieee80211_find_txnode_debug(struct ieee8
+ ieee80211_find_txnode(struct ieee80211vap *vap, const u_int8_t *mac)
+ #endif
+ {
++ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_node_table *nt;
+ struct ieee80211_node *ni = NULL;
+
++ IEEE80211_LOCK_IRQ(ic);
++ if (vap->iv_opmode == IEEE80211_M_WDS) {
++ if (vap->iv_wdsnode && (vap->iv_state == IEEE80211_S_RUN))
++ return ieee80211_ref_node(vap->iv_wdsnode);
++ else
++ return NULL;
++ }
++ IEEE80211_UNLOCK_IRQ(ic);
++
+ /*
+ * The destination address should be in the node table
+ * unless we are operating in station mode or this is a
+@@ -1669,6 +1766,11 @@ ieee80211_free_node(struct ieee80211_nod
+ {
+ struct ieee80211vap *vap = ni->ni_vap;
+
++ IEEE80211_LOCK_IRQ(ni->ni_ic);
++ if (vap && ni == vap->iv_wdsnode)
++ vap->iv_wdsnode = NULL;
++ IEEE80211_UNLOCK_IRQ(ni->ni_ic);
++
+ atomic_dec(&ni->ni_ic->ic_node_counter);
+ node_print_message(IEEE80211_MSG_NODE|IEEE80211_MSG_NODE_REF,
+ 1 /* show counter */,
+@@ -1781,22 +1883,6 @@ restart:
+ jiffies > ni->ni_rxfragstamp + HZ) {
+ ieee80211_dev_kfree_skb(&ni->ni_rxfrag);
+ }
+- /*
+- * Special case ourself; we may be idle for extended periods
+- * of time and regardless reclaiming our state is wrong.
+- * Special case a WDS link: it may be dead or idle, but it is
+- * never ok to reclaim it, as this will block transmissions
+- * and nobody will recreate the node when the WDS peer is
+- * available again. */
+- if ((ni == ni->ni_vap->iv_bss) ||
+- (ni->ni_vap->iv_opmode == IEEE80211_M_WDS &&
+- !memcmp(ni->ni_macaddr, ni->ni_vap->wds_mac, ETH_ALEN)))
+- {
+- /* NB: don't permit it to go negative */
+- if (ni->ni_inact > 0)
+- ni->ni_inact--;
+- continue;
+- }
+ ni->ni_inact--;
+ if (ni->ni_associd != 0 || isadhoc) {
+ struct ieee80211vap *vap = ni->ni_vap;
+@@ -2263,6 +2349,35 @@ ieee80211_node_leave_11g(struct ieee8021
+ }
+ }
+
++static void
++ieee80211_subif_destroy(struct work_struct *work)
++{
++ struct ieee80211_node *ni = container_of(work, struct ieee80211_node, ni_destroy);
++ struct ieee80211vap *vap;
++ struct ieee80211com *ic;
++
++ /* wait for full initialization before we start the teardown
++ * otherwise we could leak interfaces */
++ while (ni->ni_subif == ni->ni_vap)
++ schedule();
++
++ rtnl_lock();
++ vap = ni->ni_subif;
++
++ if (!vap)
++ goto done;
++
++ ic = vap->iv_ic;
++ ni->ni_subif = NULL;
++ ieee80211_stop(vap->iv_dev);
++ ic->ic_vap_delete(vap);
++ ic->ic_subifs--;
++
++done:
++ ieee80211_unref_node(&ni);
++ rtnl_unlock();
++}
++
+ /*
+ * Handle bookkeeping for a station/neighbor leaving
+ * the bss when operating in ap or adhoc modes.
+@@ -2279,6 +2394,12 @@ ieee80211_node_leave(struct ieee80211_no
+ ni, "station with aid %d leaves (refcnt %u)",
+ IEEE80211_NODE_AID(ni), atomic_read(&ni->ni_refcnt));
+
++ if (ni->ni_subif) {
++ ieee80211_ref_node(ni);
++ IEEE80211_INIT_WORK(&ni->ni_destroy, ieee80211_subif_destroy);
++ schedule_work(&ni->ni_destroy);
++ }
++
+ /* From this point onwards we can no longer find the node,
+ * so no more references are generated
+ */
+--- a/net80211/ieee80211_output.c
++++ b/net80211/ieee80211_output.c
+@@ -246,15 +246,16 @@ ieee80211_hardstart(struct sk_buff *skb,
+ * things like power save.
+ */
+ eh = (struct ether_header *)skb->data;
+- if (vap->iv_opmode == IEEE80211_M_WDS)
+- ni = ieee80211_find_txnode(vap, vap->wds_mac);
+- else
+- ni = ieee80211_find_txnode(vap, eh->ether_dhost);
++ ni = ieee80211_find_txnode(vap, eh->ether_dhost);
+ if (ni == NULL) {
+ /* NB: ieee80211_find_txnode does stat+msg */
+ goto bad;
+ }
+
++ if (ni->ni_subif && (vap != ni->ni_subif) &&
++ ((eh)->ether_type != __constant_htons(ETHERTYPE_PAE)))
++ goto bad;
++
+ /* calculate priority so drivers can find the TX queue */
+ if (ieee80211_classify(ni, skb)) {
+ IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT, ni,
+@@ -334,20 +335,33 @@ void ieee80211_parent_queue_xmit(struct
+ * constructing a frame as it sets i_fc[1]; other bits can
+ * then be or'd in.
+ */
+-static void
++static struct ieee80211_frame *
+ ieee80211_send_setup(struct ieee80211vap *vap,
+ struct ieee80211_node *ni,
+- struct ieee80211_frame *wh,
++ struct sk_buff *skb,
+ int type,
+ const u_int8_t sa[IEEE80211_ADDR_LEN],
+ const u_int8_t da[IEEE80211_ADDR_LEN],
+ const u_int8_t bssid[IEEE80211_ADDR_LEN])
+ {
+ #define WH4(wh) ((struct ieee80211_frame_addr4 *)wh)
++ struct ieee80211_frame *wh;
++ int len = sizeof(struct ieee80211_frame);
++ int opmode = vap->iv_opmode;
++
++ if ((type & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) {
++ if ((opmode == IEEE80211_M_STA) &&
++ (vap->iv_flags_ext & IEEE80211_FEXT_WDS))
++ opmode = IEEE80211_M_WDS;
+
++ if (opmode == IEEE80211_M_WDS)
++ len = sizeof(struct ieee80211_frame_addr4);
++ }
++
++ wh = (struct ieee80211_frame *)skb_push(skb, len);
+ wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | type;
+ if ((type & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) {
+- switch (vap->iv_opmode) {
++ switch (opmode) {
+ case IEEE80211_M_STA:
+ wh->i_fc[1] = IEEE80211_FC1_DIR_TODS;
+ IEEE80211_ADDR_COPY(wh->i_addr1, bssid);
+@@ -389,6 +403,8 @@ ieee80211_send_setup(struct ieee80211vap
+ *(__le16 *)&wh->i_seq[0] =
+ htole16(ni->ni_txseqs[0] << IEEE80211_SEQ_SEQ_SHIFT);
+ ni->ni_txseqs[0]++;
++
++ return wh;
+ #undef WH4
+ }
+
+@@ -410,9 +426,7 @@ ieee80211_mgmt_output(struct ieee80211_n
+
+ SKB_CB(skb)->ni = ni;
+
+- wh = (struct ieee80211_frame *)
+- skb_push(skb, sizeof(struct ieee80211_frame));
+- ieee80211_send_setup(vap, ni, wh,
++ wh = ieee80211_send_setup(vap, ni, skb,
+ IEEE80211_FC0_TYPE_MGT | type,
+ vap->iv_myaddr, ni->ni_macaddr, vap->iv_bssid);
+ /* XXX power management */
+@@ -458,6 +472,9 @@ ieee80211_send_nulldata(struct ieee80211
+ struct ieee80211_frame *wh;
+ u_int8_t *frm;
+
++ if (ni->ni_subif)
++ vap = ni->ni_subif;
++
+ skb = ieee80211_getmgtframe(&frm, 0);
+ if (skb == NULL) {
+ /* XXX debug msg */
+@@ -466,9 +483,7 @@ ieee80211_send_nulldata(struct ieee80211
+ return -ENOMEM;
+ }
+
+- wh = (struct ieee80211_frame *)
+- skb_push(skb, sizeof(struct ieee80211_frame));
+- ieee80211_send_setup(vap, ni, wh,
++ wh = ieee80211_send_setup(vap, ni, skb,
+ IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_NODATA,
+ vap->iv_myaddr, ni->ni_macaddr, vap->iv_bssid);
+ /* NB: power management bit is never sent by an AP */
+@@ -506,6 +521,7 @@ ieee80211_send_qosnulldata(struct ieee80
+ struct sk_buff *skb;
+ struct ieee80211_qosframe *qwh;
+ u_int8_t *frm;
++ u_int8_t *i_qos;
+ int tid;
+
+ skb = ieee80211_getmgtframe(&frm, 2);
+@@ -517,11 +533,12 @@ ieee80211_send_qosnulldata(struct ieee80
+ SKB_CB(skb)->ni = ieee80211_ref_node(ni);
+
+ skb->priority = ac;
+- qwh = (struct ieee80211_qosframe *)skb_push(skb, sizeof(struct ieee80211_qosframe));
+
+- qwh = (struct ieee80211_qosframe *)skb->data;
++ /* grab a pointer to QoS control and also compensate for the header length
++ * difference between QoS and non-QoS frame */
++ i_qos = skb_push(skb, sizeof(struct ieee80211_qosframe) - sizeof(struct ieee80211_frame));
+
+- ieee80211_send_setup(vap, ni, (struct ieee80211_frame *)qwh,
++ qwh = (struct ieee80211_qosframe *) ieee80211_send_setup(vap, ni, skb,
+ IEEE80211_FC0_TYPE_DATA,
+ vap->iv_myaddr, /* SA */
+ ni->ni_macaddr, /* DA */
+@@ -535,10 +552,10 @@ ieee80211_send_qosnulldata(struct ieee80
+
+ /* map from access class/queue to 11e header priority value */
+ tid = WME_AC_TO_TID(ac);
+- qwh->i_qos[0] = tid & IEEE80211_QOS_TID;
++ i_qos[0] = tid & IEEE80211_QOS_TID;
+ if (ic->ic_wme.wme_wmeChanParams.cap_wmeParams[ac].wmep_noackPolicy)
+ qwh->i_qos[0] |= (1 << IEEE80211_QOS_ACKPOLICY_S) & IEEE80211_QOS_ACKPOLICY;
+- qwh->i_qos[1] = 0;
++ i_qos[1] = 0;
+
+ IEEE80211_NODE_STAT(ni, tx_data);
+
+@@ -780,6 +797,8 @@ ieee80211_encap(struct ieee80211_node *n
+ hdrsize = sizeof(struct ieee80211_frame);
+
+ SKB_CB(skb)->auth_pkt = (eh.ether_type == __constant_htons(ETHERTYPE_PAE));
++ if (ni->ni_subif)
++ vap = ni->ni_subif;
+
+ switch (vap->iv_opmode) {
+ case IEEE80211_M_IBSS:
+@@ -788,7 +807,7 @@ ieee80211_encap(struct ieee80211_node *n
+ break;
+ case IEEE80211_M_WDS:
+ use4addr = 1;
+- ismulticast = IEEE80211_IS_MULTICAST(ni->ni_macaddr);
++ ismulticast = 0;
+ break;
+ case IEEE80211_M_HOSTAP:
+ if (!IEEE80211_IS_MULTICAST(eh.ether_dhost) &&
+@@ -799,20 +818,9 @@ ieee80211_encap(struct ieee80211_node *n
+ ismulticast = IEEE80211_IS_MULTICAST(eh.ether_dhost);
+ break;
+ case IEEE80211_M_STA:
+- if ((vap->iv_flags_ext & IEEE80211_FEXT_WDS) &&
+- !IEEE80211_ADDR_EQ(eh.ether_shost, vap->iv_myaddr)) {
++ if (vap->iv_flags_ext & IEEE80211_FEXT_WDS) {
+ use4addr = 1;
+- ismulticast = IEEE80211_IS_MULTICAST(ni->ni_macaddr);
+- /* Add a WDS entry to the station VAP */
+- if (IEEE80211_IS_MULTICAST(eh.ether_dhost)) {
+- struct ieee80211_node_table *nt = &ic->ic_sta;
+- struct ieee80211_node *ni_wds
+- = ieee80211_find_wds_node(nt, eh.ether_shost);
+- if (ni_wds)
+- ieee80211_unref_node(&ni_wds);
+- else
+- ieee80211_add_wds_addr(nt, ni, eh.ether_shost, 0);
+- }
++ ismulticast = 0;
+ } else
+ ismulticast = IEEE80211_IS_MULTICAST(vap->iv_bssid);
+ break;
+@@ -973,7 +981,7 @@ ieee80211_encap(struct ieee80211_node *n
+ break;
+ case IEEE80211_M_WDS:
+ wh->i_fc[1] = IEEE80211_FC1_DIR_DSTODS;
+- IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
++ IEEE80211_ADDR_COPY(wh->i_addr1, vap->wds_mac);
+ IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr);
+ IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost);
+ IEEE80211_ADDR_COPY(WH4(wh)->i_addr4, eh.ether_shost);
+@@ -1683,9 +1691,7 @@ ieee80211_send_probereq(struct ieee80211
+
+ SKB_CB(skb)->ni = ieee80211_ref_node(ni);
+
+- wh = (struct ieee80211_frame *)
+- skb_push(skb, sizeof(struct ieee80211_frame));
+- ieee80211_send_setup(vap, ni, wh,
++ wh = ieee80211_send_setup(vap, ni, skb,
+ IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_REQ,
+ sa, da, bssid);
+ /* XXX power management? */
+--- a/tools/athkey.c
++++ b/tools/athkey.c
+@@ -118,7 +118,7 @@ set80211priv(const char *dev, int op, vo
+ IOCTL_ERR(IEEE80211_IOCTL_ADDMAC),
+ IOCTL_ERR(IEEE80211_IOCTL_DELMAC),
+ IOCTL_ERR(IEEE80211_IOCTL_WDSADDMAC),
+- IOCTL_ERR(IEEE80211_IOCTL_WDSDELMAC),
++ IOCTL_ERR(IEEE80211_IOCTL_WDSSETMAC),
+ IOCTL_ERR(IEEE80211_IOCTL_READREG),
+ IOCTL_ERR(IEEE80211_IOCTL_WRITEREG),
+ };
+--- a/tools/athchans.c
++++ b/tools/athchans.c
+@@ -118,7 +118,7 @@ set80211priv(const char *dev, int op, vo
+ IOCTL_ERR(IEEE80211_IOCTL_ADDMAC),
+ IOCTL_ERR(IEEE80211_IOCTL_DELMAC),
+ IOCTL_ERR(IEEE80211_IOCTL_WDSADDMAC),
+- IOCTL_ERR(IEEE80211_IOCTL_WDSDELMAC),
++ IOCTL_ERR(IEEE80211_IOCTL_WDSSETMAC),
+ IOCTL_ERR(IEEE80211_IOCTL_READREG),
+ IOCTL_ERR(IEEE80211_IOCTL_WRITEREG),
+ };
+--- a/tools/wlanconfig.c
++++ b/tools/wlanconfig.c
+@@ -968,7 +968,7 @@ do80211priv(struct iwreq *iwr, const cha
+ IOCTL_ERR(IEEE80211_IOCTL_ADDMAC),
+ IOCTL_ERR(IEEE80211_IOCTL_DELMAC),
+ IOCTL_ERR(IEEE80211_IOCTL_WDSADDMAC),
+- IOCTL_ERR(IEEE80211_IOCTL_WDSDELMAC),
++ IOCTL_ERR(IEEE80211_IOCTL_WDSSETMAC),
+ IOCTL_ERR(IEEE80211_IOCTL_READREG),
+ IOCTL_ERR(IEEE80211_IOCTL_WRITEREG),
+ };
+--- a/net80211/ieee80211_proto.c
++++ b/net80211/ieee80211_proto.c
+@@ -979,6 +979,12 @@ ieee80211_init(struct net_device *dev, i
+ "start running (state=%d)\n", vap->iv_state);
+
+
++ if (vap->iv_master && vap->iv_master->iv_state == IEEE80211_S_INIT) {
++ int ret = ieee80211_init(vap->iv_master->iv_dev, forcescan);
++ if (ret < 0)
++ return ret;
++ }
++
+ if ((dev->flags & IFF_RUNNING) == 0) {
+ if (ic->ic_nopened++ == 0 &&
+ (parent->flags & IFF_RUNNING) == 0)
+@@ -1081,6 +1087,8 @@ ieee80211_init(struct net_device *dev, i
+ int
+ ieee80211_open(struct net_device *dev)
+ {
++ struct ieee80211vap *vap = dev->priv;
++
+ return ieee80211_init(dev, 0);
+ }
+
+@@ -1090,7 +1098,7 @@ ieee80211_open(struct net_device *dev)
+ void
+ ieee80211_start_running(struct ieee80211com *ic)
+ {
+- struct ieee80211vap *vap;
++ struct ieee80211vap *vap, *avp;
+ struct net_device *dev;
+
+ /* XXX locking */
+@@ -1099,6 +1107,16 @@ ieee80211_start_running(struct ieee80211
+ /* NB: avoid recursion */
+ if ((dev->flags & IFF_UP) && !(dev->flags & IFF_RUNNING))
+ ieee80211_open(dev);
++
++ TAILQ_FOREACH(avp, &vap->iv_wdslinks, iv_wdsnext) {
++ if (avp->iv_wdsnode && avp->iv_wdsnode->ni_subif == avp)
++ continue;
++
++ dev = avp->iv_dev;
++ /* NB: avoid recursion */
++ if ((dev->flags & IFF_UP) && !(dev->flags & IFF_RUNNING))
++ ieee80211_open(dev);
++ }
+ }
+ }
+ EXPORT_SYMBOL(ieee80211_start_running);
+@@ -1116,11 +1134,43 @@ ieee80211_stop(struct net_device *dev)
+ struct ieee80211vap *vap = dev->priv;
+ struct ieee80211com *ic = vap->iv_ic;
+ struct net_device *parent = ic->ic_dev;
++ struct ieee80211_node *tni, *ni;
++ struct ieee80211vap *avp;
+
+ IEEE80211_DPRINTF(vap,
+ IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
+ "%s\n", "stop running");
+
++ if (vap->iv_wdsnode && !vap->iv_wdsnode->ni_subif)
++ ieee80211_unref_node(&vap->iv_wdsnode);
++
++ /* stop wds interfaces */
++ TAILQ_FOREACH(avp, &vap->iv_wdslinks, iv_next) {
++ if (avp->iv_state != IEEE80211_S_INIT)
++ ieee80211_stop(avp->iv_dev);
++ }
++
++ /* get rid of all wds nodes while we're still locked */
++ do {
++ ni = NULL;
++
++ IEEE80211_NODE_TABLE_LOCK_IRQ(&ic->ic_sta);
++ TAILQ_FOREACH(tni, &ic->ic_sta.nt_node, ni_list) {
++ if (tni->ni_vap != vap)
++ continue;
++ if (!tni->ni_subif)
++ continue;
++ ni = tni;
++ break;
++ }
++ IEEE80211_NODE_TABLE_UNLOCK_IRQ(&ic->ic_sta);
++
++ if (!ni)
++ break;
++
++ ieee80211_node_leave(ni);
++ } while (1);
++
+ ieee80211_new_state(vap, IEEE80211_S_INIT, -1);
+ if (dev->flags & IFF_RUNNING) {
+ dev->flags &= ~IFF_RUNNING; /* mark us stopped */
+@@ -1148,7 +1198,7 @@ EXPORT_SYMBOL(ieee80211_stop);
+ void
+ ieee80211_stop_running(struct ieee80211com *ic)
+ {
+- struct ieee80211vap *vap;
++ struct ieee80211vap *vap, *avp;
+ struct net_device *dev;
+
+ /* XXX locking */
+@@ -1156,6 +1206,12 @@ ieee80211_stop_running(struct ieee80211c
+ dev = vap->iv_dev;
+ if (dev->flags & IFF_RUNNING) /* NB: avoid recursion */
+ ieee80211_stop(dev);
++
++ TAILQ_FOREACH(avp, &vap->iv_wdslinks, iv_wdsnext) {
++ dev = avp->iv_dev;
++ if (dev->flags & IFF_RUNNING) /* NB: avoid recursion */
++ ieee80211_stop(dev);
++ }
+ }
+ }
+ EXPORT_SYMBOL(ieee80211_stop_running);
+@@ -1342,9 +1398,9 @@ ieee80211_new_state(struct ieee80211vap
+ struct ieee80211com *ic = vap->iv_ic;
+ int rc;
+
+- IEEE80211_VAPS_LOCK_BH(ic);
++ IEEE80211_VAPS_LOCK_IRQ(ic);
+ rc = vap->iv_newstate(vap, nstate, arg);
+- IEEE80211_VAPS_UNLOCK_BH(ic);
++ IEEE80211_VAPS_UNLOCK_IRQ(ic);
+ return rc;
+ }
+
+@@ -1557,57 +1613,12 @@ __ieee80211_newstate(struct ieee80211vap
+ switch (ostate) {
+ case IEEE80211_S_INIT:
+ if (vap->iv_opmode == IEEE80211_M_MONITOR ||
+- vap->iv_opmode == IEEE80211_M_WDS ||
+ vap->iv_opmode == IEEE80211_M_HOSTAP) {
+ /*
+ * Already have a channel; bypass the
+ * scan and startup immediately.
+ */
+ ieee80211_create_ibss(vap, ic->ic_curchan);
+-
+- /* In WDS mode, allocate and initialize peer node. */
+- if (vap->iv_opmode == IEEE80211_M_WDS) {
+- /* XXX: This is horribly non-atomic. */
+- struct ieee80211_node *wds_ni =
+- ieee80211_find_node(&ic->ic_sta,
+- vap->wds_mac);
+-
+- if (wds_ni == NULL) {
+- wds_ni = ieee80211_alloc_node_table(
+- vap,
+- vap->wds_mac);
+- if (wds_ni != NULL) {
+- ieee80211_add_wds_addr(
+- &ic->ic_sta,
+- wds_ni,
+- vap->wds_mac,
+- 1);
+- ieee80211_ref_node(wds_ni); /* pin in memory */
+- }
+- else
+- IEEE80211_DPRINTF(
+- vap,
+- IEEE80211_MSG_NODE,
+- "%s: Unable to "
+- "allocate node for "
+- "WDS: " MAC_FMT "\n",
+- __func__,
+- MAC_ADDR(
+- vap->wds_mac)
+- );
+- }
+-
+- if (wds_ni != NULL) {
+- ieee80211_node_authorize(wds_ni);
+- wds_ni->ni_chan =
+- vap->iv_bss->ni_chan;
+- wds_ni->ni_capinfo =
+- ni->ni_capinfo;
+- wds_ni->ni_associd = 1;
+- wds_ni->ni_ath_flags =
+- vap->iv_ath_cap;
+- }
+- }
+ break;
+ }
+ /* fall thru... */
+@@ -1675,6 +1686,7 @@ __ieee80211_newstate(struct ieee80211vap
+ */
+ if (ni->ni_authmode != IEEE80211_AUTH_8021X)
+ ieee80211_node_authorize(ni);
++
+ #ifdef ATH_SUPERG_XR
+ /*
+ * fire a timer to bring up XR vap if configured.
+@@ -1808,6 +1820,11 @@ ieee80211_newstate(struct ieee80211vap *
+ ieee80211_state_name[dstate]);
+
+ ieee80211_update_link_status(vap, nstate, ostate);
++
++ if ((nstate != IEEE80211_S_RUN) && vap->iv_wdsnode &&
++ !vap->iv_wdsnode->ni_subif)
++ ieee80211_unref_node(&vap->iv_wdsnode);
++
+ switch (nstate) {
+ case IEEE80211_S_AUTH:
+ case IEEE80211_S_ASSOC:
+@@ -1930,8 +1947,15 @@ ieee80211_newstate(struct ieee80211vap *
+ if (ostate == IEEE80211_S_SCAN ||
+ ostate == IEEE80211_S_AUTH ||
+ ostate == IEEE80211_S_ASSOC) {
++
+ /* Transition (S_SCAN|S_AUTH|S_ASSOC) -> S_RUN */
+ __ieee80211_newstate(vap, nstate, arg);
++
++ /* if we're in wds, let the ap know that we're doing this */
++ if ((vap->iv_opmode == IEEE80211_M_STA) &&
++ (vap->iv_flags_ext & IEEE80211_FEXT_WDS))
++ ieee80211_send_nulldata(ieee80211_ref_node(vap->iv_bss));
++
+ /* Then bring up all other vaps pending on the scan */
+ dstate = get_dominant_state(ic);
+ if (dstate == IEEE80211_S_RUN) {
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -79,28 +79,6 @@ typedef void *TQUEUE_ARG;
+ #define tasklet_enable(t) do { (void) t; local_bh_enable(); } while (0)
+ #endif /* !DECLARE_TASKLET */
+
+-#include <linux/sched.h>
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,41)
+-#include <linux/tqueue.h>
+-#define work_struct tq_struct
+-#define schedule_work(t) schedule_task((t))
+-#define flush_scheduled_work() flush_scheduled_tasks()
+-#define ATH_INIT_WORK(t, f) do { \
+- memset((t), 0, sizeof(struct tq_struct)); \
+- (t)->routine = (void (*)(void*)) (f); \
+- (t)->data=(void *) (t); \
+-} while (0)
+-#else
+-#include <linux/workqueue.h>
+-
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+-#define ATH_INIT_WORK(_t, _f) INIT_WORK((_t), (void (*)(void *))(_f), (_t));
+-#else
+-#define ATH_INIT_WORK(_t, _f) INIT_WORK((_t), (_f));
+-#endif
+-
+-#endif /* KERNEL_VERSION < 2.5.41 */
+-
+ /*
+ * Guess how the interrupt handler should work.
+ */
+--- a/net80211/ieee80211_linux.c
++++ b/net80211/ieee80211_linux.c
+@@ -145,7 +145,7 @@ ieee80211_getmgtframe(u_int8_t **frm, u_
+ struct sk_buff *skb;
+ u_int len;
+
+- len = roundup(sizeof(struct ieee80211_frame) + pktlen, 4);
++ len = roundup(sizeof(struct ieee80211_frame_addr4) + pktlen, 4);
+ #ifdef IEEE80211_DEBUG_REFCNT
+ skb = ieee80211_dev_alloc_skb_debug(len + align - 1, func, line);
+ #else
+@@ -161,7 +161,7 @@ ieee80211_getmgtframe(u_int8_t **frm, u_
+ SKB_CB(skb)->flags = 0;
+ SKB_CB(skb)->next = NULL;
+
+- skb_reserve(skb, sizeof(struct ieee80211_frame));
++ skb_reserve(skb, sizeof(struct ieee80211_frame_addr4));
+ *frm = skb_put(skb, pktlen);
+ }
+ return skb;
+--- a/net80211/ieee80211_node.h
++++ b/net80211/ieee80211_node.h
+@@ -92,11 +92,13 @@ struct ath_softc;
+ * the ieee80211com structure.
+ */
+ struct ieee80211_node {
+- struct ieee80211vap *ni_vap;
++ struct ieee80211vap *ni_vap, *ni_subif;
+ struct ieee80211com *ni_ic;
+ struct ieee80211_node_table *ni_table;
+ TAILQ_ENTRY(ieee80211_node) ni_list;
+ LIST_ENTRY(ieee80211_node) ni_hash;
++ struct work_struct ni_create; /* task for creating a subif */
++ struct work_struct ni_destroy; /* task for destroying a subif */
+ atomic_t ni_refcnt;
+ u_int ni_scangen; /* gen# for timeout scan */
+ u_int8_t ni_authmode; /* authentication algorithm */
+@@ -430,5 +432,6 @@ void ieee80211_node_join(struct ieee8021
+ void ieee80211_node_leave(struct ieee80211_node *);
+ u_int8_t ieee80211_getrssi(struct ieee80211com *);
+ int32_t ieee80211_get_node_count(struct ieee80211com *);
++void ieee80211_wds_addif(struct ieee80211_node *ni);
+ #endif /* _NET80211_IEEE80211_NODE_H_ */
+
diff --git a/package/madwifi/patches/372-queue_vif.patch b/package/madwifi/patches/372-queue_vif.patch
new file mode 100644
index 000000000..8b13abc33
--- /dev/null
+++ b/package/madwifi/patches/372-queue_vif.patch
@@ -0,0 +1,39 @@
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -1198,6 +1198,7 @@ ieee80211_deliver_data(struct ieee80211_
+ }
+ if (skb1 != NULL) {
+ struct ieee80211_node *ni_tmp;
++ int ret;
+ skb1->dev = dev;
+ skb_reset_mac_header(skb1);
+ skb_set_network_header(skb1, sizeof(struct ether_header));
+@@ -1205,7 +1206,12 @@ ieee80211_deliver_data(struct ieee80211_
+ skb1->protocol = __constant_htons(ETH_P_802_2);
+ /* XXX insert vlan tag before queue it? */
+ ni_tmp = SKB_CB(skb1)->ni; /* remember node so we can free it */
+- if (dev_queue_xmit(skb1) == NET_XMIT_DROP) {
++ ret = dev->hard_start_xmit(skb1, dev);
++
++ if (ret == NETDEV_TX_BUSY)
++ ieee80211_dev_kfree_skb(&skb1);
++
++ else if (ret != NETDEV_TX_OK) {
+ /* If queue dropped the packet because device was
+ * too busy */
+ vap->iv_devstats.tx_dropped++;
+--- a/net80211/ieee80211_output.c
++++ b/net80211/ieee80211_output.c
+@@ -324,9 +324,10 @@ void ieee80211_parent_queue_xmit(struct
+ /* Dispatch the packet to the parent device */
+ skb->dev = vap->iv_ic->ic_dev;
+
+- if (dev_queue_xmit(skb) == NET_XMIT_DROP)
++ if (netif_queue_stopped(skb->dev))
++ ieee80211_dev_kfree_skb(&skb);
++ else if (dev_queue_xmit(skb) == NET_XMIT_DROP)
+ vap->iv_devstats.tx_dropped++;
+-
+ }
+
+ /*
diff --git a/package/madwifi/patches/373-sanity_check.patch b/package/madwifi/patches/373-sanity_check.patch
new file mode 100644
index 000000000..06c6acf08
--- /dev/null
+++ b/package/madwifi/patches/373-sanity_check.patch
@@ -0,0 +1,12 @@
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -250,6 +250,9 @@ ieee80211_input(struct ieee80211vap * va
+ if (vap->iv_opmode == IEEE80211_M_MONITOR)
+ goto out;
+
++ if (!skb->data)
++ goto out;
++
+ if (skb->len < sizeof(struct ieee80211_frame_min)) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
+ ni->ni_macaddr, NULL,
diff --git a/package/madwifi/patches/374-nbtt_fix.patch b/package/madwifi/patches/374-nbtt_fix.patch
new file mode 100644
index 000000000..38a1c59d5
--- /dev/null
+++ b/package/madwifi/patches/374-nbtt_fix.patch
@@ -0,0 +1,22 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -5486,6 +5486,9 @@ ath_beacon_config(struct ath_softc *sc,
+ ath_beacon_dturbo_config(vap, intval &
+ ~(HAL_BEACON_RESET_TSF | HAL_BEACON_ENA));
+ #endif
++ if ((nexttbtt & HAL_BEACON_PERIOD) - (ath_hal_gettsf32(ah) >> 10)
++ <= ath_hal_sw_beacon_response_time)
++ nexttbtt += intval;
+ sc->sc_nexttbtt = nexttbtt;
+ ath_hal_beaconinit(ah, nexttbtt, intval);
+ if (intval & HAL_BEACON_RESET_TSF) {
+--- a/ath_hal/ah_os.c
++++ b/ath_hal/ah_os.c
+@@ -71,6 +71,7 @@ static int ath_hal_debug = 99;
+ int ath_hal_dma_beacon_response_time = 2; /* in TUs */
+ int ath_hal_sw_beacon_response_time = 10; /* in TUs */
+ int ath_hal_additional_swba_backoff = 0; /* in TUs */
++EXPORT_SYMBOL(ath_hal_sw_beacon_response_time);
+
+ struct ath_hal *
+ _ath_hal_attach(u_int16_t devid, HAL_SOFTC sc,
diff --git a/package/madwifi/patches/375-atim_tsf_update.patch b/package/madwifi/patches/375-atim_tsf_update.patch
new file mode 100644
index 000000000..d1313aa56
--- /dev/null
+++ b/package/madwifi/patches/375-atim_tsf_update.patch
@@ -0,0 +1,141 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -161,6 +161,7 @@ static void ath_beacon_send(struct ath_s
+ static void ath_beacon_return(struct ath_softc *, struct ath_buf *);
+ static void ath_beacon_free(struct ath_softc *);
+ static void ath_beacon_config(struct ath_softc *, struct ieee80211vap *);
++static void ath_hw_beacon_stop(struct ath_softc *sc);
+ static int ath_desc_alloc(struct ath_softc *);
+ static void ath_desc_free(struct ath_softc *);
+ static void ath_desc_swap(struct ath_desc *);
+@@ -2793,6 +2794,72 @@ ath_set_ack_bitrate(struct ath_softc *sc
+ return 1;
+ }
+
++static void
++ath_hw_beacon_stop(struct ath_softc *sc)
++{
++ HAL_BEACON_TIMERS btimers;
++
++ btimers.bt_intval = 0;
++ btimers.bt_nexttbtt = 0;
++ btimers.bt_nextdba = 0xffffffff;
++ btimers.bt_nextswba = 0xffffffff;
++ btimers.bt_nextatim = 0;
++
++ ath_hal_setbeacontimers(sc->sc_ah, &btimers);
++}
++
++/* Fix up the ATIM window after TSF resync */
++static int
++ath_hw_check_atim(struct ath_softc *sc, int window, int intval)
++{
++#define AR5K_TIMER0_5210 0x802c /* Next beacon time register */
++#define AR5K_TIMER0_5211 0x8028
++#define AR5K_TIMER3_5210 0x8038 /* End of ATIM window time register */
++#define AR5K_TIMER3_5211 0x8034
++ struct ath_hal *ah = sc->sc_ah;
++ int dev = sc->sc_ah->ah_macType;
++ unsigned int nbtt, atim;
++ int is_5210 = 0;
++
++ /*
++ * check if the ATIM window is still correct:
++ * 1.) usually ATIM should be NBTT + window
++ * 2.) nbtt already updated
++ * 3.) nbtt already updated and has wrapped around
++ * 4.) atim has wrapped around
++ */
++ switch(dev) {
++ case 5210:
++ nbtt = OS_REG_READ(ah, AR5K_TIMER0_5210);
++ atim = OS_REG_READ(ah, AR5K_TIMER3_5210);
++ is_5210 = 1;
++ break;
++ case 5211:
++ case 5212:
++ nbtt = OS_REG_READ(ah, AR5K_TIMER0_5211);
++ atim = OS_REG_READ(ah, AR5K_TIMER3_5211);
++ break;
++ /* NB: 5416+ doesn't do ATIM in hw */
++ case 5416:
++ default:
++ return 0;
++ }
++
++ if ((atim - nbtt != window) && /* 1.) */
++ (nbtt - atim != intval - window) && /* 2.) */
++ ((nbtt | 0x10000) - atim != intval - window) && /* 3.) */
++ ((atim | 0x10000) - nbtt != window)) { /* 4.) */
++ if (is_5210)
++ OS_REG_WRITE(ah, AR5K_TIMER3_5210, nbtt + window );
++ else
++ OS_REG_WRITE(ah, AR5K_TIMER3_5211, nbtt + window );
++ return atim - nbtt;
++ }
++
++ return 0;
++}
++
++
+ /*
+ * Reset the hardware w/o losing operational state. This is
+ * basically a more efficient way of doing ath_stop, ath_init,
+@@ -5294,6 +5361,7 @@ ath_beacon_config(struct ath_softc *sc,
+ u_int64_t tsf, hw_tsf;
+ u_int32_t tsftu, hw_tsftu;
+ u_int32_t intval, nexttbtt = 0;
++ unsigned long flags;
+ int reset_tsf = 0;
+
+ if (vap == NULL)
+@@ -5301,6 +5369,9 @@ ath_beacon_config(struct ath_softc *sc,
+
+ ni = vap->iv_bss;
+
++ /* TSF calculation is timing critical - we don't want to be interrupted here */
++ local_irq_save(flags);
++
+ hw_tsf = ath_hal_gettsf64(ah);
+ tsf = le64_to_cpu(ni->ni_tstamp.tsf);
+ hw_tsftu = hw_tsf >> 10;
+@@ -5490,15 +5561,27 @@ ath_beacon_config(struct ath_softc *sc,
+ <= ath_hal_sw_beacon_response_time)
+ nexttbtt += intval;
+ sc->sc_nexttbtt = nexttbtt;
++
++ /* stop beacons before reconfiguring the timers to avoid race
++ * conditions. ath_hal_beaconinit will start them again */
++ ath_hw_beacon_stop(sc);
++
+ ath_hal_beaconinit(ah, nexttbtt, intval);
+ if (intval & HAL_BEACON_RESET_TSF) {
+ sc->sc_last_tsf = 0;
+ }
+ sc->sc_bmisscount = 0;
+ ath_hal_intrset(ah, sc->sc_imask);
++
++ if ((sc->sc_opmode == HAL_M_IBSS) && ath_hw_check_atim(sc, 1, intval & HAL_BEACON_PERIOD)) {
++ DPRINTF(sc, ATH_DEBUG_BEACON,
++ "fixed atim window after beacon init\n");
++ }
+ }
+
+ ath_beacon_config_debug:
++ local_irq_restore(flags);
++
+ /* We print all debug messages here, in order to preserve the
+ * time critical aspect of this function */
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+@@ -6401,6 +6484,11 @@ ath_recv_mgmt(struct ieee80211vap * vap,
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+ "Updated beacon timers\n");
+ }
++ if ((sc->sc_opmode == HAL_M_IBSS) &&
++ IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid) &&
++ ath_hw_check_atim(sc, 1, vap->iv_bss->ni_intval)) {
++ DPRINTF(sc, ATH_DEBUG_ANY, "Fixed ATIM window after beacon recv\n");
++ }
+ /* NB: Fall Through */
+ case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
+ if (vap->iv_opmode == IEEE80211_M_IBSS &&
diff --git a/package/madwifi/patches/377-disable_vlan_code.patch b/package/madwifi/patches/377-disable_vlan_code.patch
new file mode 100644
index 000000000..8a132484e
--- /dev/null
+++ b/package/madwifi/patches/377-disable_vlan_code.patch
@@ -0,0 +1,25 @@
+--- a/net80211/ieee80211_linux.h
++++ b/net80211/ieee80211_linux.h
+@@ -657,22 +657,7 @@ int ieee80211_proc_vcreate(struct ieee80
+ 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 *);
+
diff --git a/package/madwifi/patches/378-adhoc_crash_fix.patch b/package/madwifi/patches/378-adhoc_crash_fix.patch
new file mode 100644
index 000000000..5b9168367
--- /dev/null
+++ b/package/madwifi/patches/378-adhoc_crash_fix.patch
@@ -0,0 +1,14 @@
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -3529,6 +3529,11 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ if (ic->ic_flags & IEEE80211_F_SCAN) {
+ ieee80211_add_scan(vap, &scan, wh, subtype, rssi, rtsf);
+ }
++
++ /* stop processing if the bss channel is not set up yet */
++ if (!ic->ic_bsschan || ic->ic_bsschan == IEEE80211_CHAN_ANYC)
++ break;
++
+ /* NB: Behavior of WDS-Link and Ad-Hoc is very similar here:
+ * When we receive a beacon that belongs to the AP that we're
+ * connected to, use it to refresh the local node info.
diff --git a/package/madwifi/patches/379-invalid_rate_fix.patch b/package/madwifi/patches/379-invalid_rate_fix.patch
new file mode 100644
index 000000000..c96c04daf
--- /dev/null
+++ b/package/madwifi/patches/379-invalid_rate_fix.patch
@@ -0,0 +1,405 @@
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -111,27 +111,13 @@
+ #include <net80211/ieee80211_var.h>
+ #include <net80211/ieee80211_rate.h>
+
++#include "if_ath_debug.h"
+ #include "if_athvar.h"
+ #include "if_ath_hal.h"
+ #include "ah_desc.h"
+
+ #include "minstrel.h"
+
+-#ifdef AR_DEBUG
+-#define MINSTREL_DEBUG
+-#endif
+-#ifdef MINSTREL_DEBUG
+-enum {
+- ATH_DEBUG_RATE = 0x00000010 /* rate control */
+-};
+-#define DPRINTF(sc, _fmt, ...) do { \
+- if (sc->sc_debug & ATH_DEBUG_RATE) \
+- printk(_fmt, __VA_ARGS__); \
+-} while (0)
+-#else
+-#define DPRINTF(sc, _fmt, ...)
+-#endif
+-
+ #define ONE_SECOND (1000 * 1000) /* 1 second, or 1000 milliseconds; eternity, in other words */
+
+ #include "release.h"
+@@ -471,11 +457,11 @@ ath_rate_tx_complete(struct ath_softc *s
+ final_rate = sc->sc_hwmap[ts->ts_rate & ~HAL_TXSTAT_ALTRATE].ieeerate;
+ final_ndx = rate_to_ndx(sn, final_rate);
+ if (final_ndx >= sn->num_rates) {
+- DPRINTF(sc, "%s: final ndx too high\n", __func__);
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s: final ndx too high\n", __func__);
+ final_ndx = 0;
+ }
+ if (final_ndx < 0) {
+- DPRINTF(sc, "%s: final ndx too low\n", __func__);
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s: final ndx too low\n", __func__);
+ final_ndx = 0;
+ }
+
+@@ -485,7 +471,7 @@ ath_rate_tx_complete(struct ath_softc *s
+ tries = ts->ts_longretry + 1;
+
+ if (sn->num_rates <= 0) {
+- DPRINTF(sc, "%s: " MAC_FMT " %s no rates yet\n", dev_info,
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s: " MAC_FMT " %s no rates yet\n", dev_info,
+ MAC_ADDR(an->an_node.ni_macaddr), __func__);
+ return;
+ }
+@@ -551,7 +537,7 @@ ath_rate_tx_complete(struct ath_softc *s
+ static void
+ ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew)
+ {
+- DPRINTF(sc, "%s: " MAC_FMT " %s\n", dev_info,
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s: " MAC_FMT " %s\n", dev_info,
+ MAC_ADDR(an->an_node.ni_macaddr), __func__);
+ if (isnew)
+ ath_rate_ctl_reset(sc, &an->an_node);
+@@ -601,7 +587,7 @@ ath_fill_sample_table(struct minstrel_no
+ p = rates + sprintf(rates, "rates :: %d ", column_index);
+ for (i = 0; i < num_sample_rates; i++)
+ p += sprintf(p, "%2u ", sn->rs_sampleTable[i][column_index]);
+- DPRINTF(sc, "%s\n", rates);
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s\n", rates);
+ };
+ #endif
+ }
+@@ -628,7 +614,7 @@ ath_rate_ctl_reset(struct ath_softc *sc,
+ sn->is_sampling = 0;
+
+ if (rt == NULL) {
+- DPRINTF(sc, "no rates yet! mode %u\n", sc->sc_curmode);
++ DPRINTF(sc, ATH_DEBUG_RATE, "no rates yet! mode %u\n", sc->sc_curmode);
+ return;
+ }
+ sn->static_rate_ndx = -1;
+@@ -658,7 +644,7 @@ ath_rate_ctl_reset(struct ath_softc *sc,
+ 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",
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s ignore bogus rix at %d\n",
+ dev_info, __func__, x);
+ continue;
+ }
+@@ -673,7 +659,7 @@ ath_rate_ctl_reset(struct ath_softc *sc,
+ ni->ni_txrate = 0;
+
+ if (sn->num_rates <= 0) {
+- DPRINTF(sc, "%s: %s " MAC_FMT " no rates (fixed %d) \n",
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s " MAC_FMT " no rates (fixed %d) \n",
+ dev_info, __func__, MAC_ADDR(ni->ni_macaddr),
+ vap->iv_fixed_rate);
+ /* There are no rates yet; we're done */
+@@ -689,23 +675,23 @@ ath_rate_ctl_reset(struct ath_softc *sc,
+ * the node. We know the rate is there because the
+ * rate set is checked when the station associates. */
+ /* NB: the rate set is assumed sorted */
+- for (; (srate >= 0) && (ni->ni_rates.rs_rates[srate] & IEEE80211_RATE_VAL) != vap->iv_fixed_rate; srate--);
+-
+- KASSERT(srate >= 0,
+- ("fixed rate %d not in rate set", vap->iv_fixed_rate));
++ for (; (srate > 0) && (ni->ni_rates.rs_rates[srate] & IEEE80211_RATE_VAL) != vap->iv_fixed_rate; srate--);
+
+ sn->static_rate_ndx = srate;
+ ni->ni_txrate = srate;
+- DPRINTF(sc, "%s: %s " MAC_FMT " fixed rate %d%sMbps\n",
+- dev_info, __func__, MAC_ADDR(ni->ni_macaddr),
+- sn->rates[srate].rate / 2,
+- (sn->rates[srate].rate % 2) ? ".5 " : " ");
++ if ((ni->ni_rates.rs_rates[srate] & IEEE80211_RATE_VAL) != vap->iv_fixed_rate)
++ EPRINTF(sc, "Invalid static rate, falling back to basic rate\n");
++ else
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s " MAC_FMT " fixed rate %d%sMbps\n",
++ dev_info, __func__, MAC_ADDR(ni->ni_macaddr),
++ sn->rates[srate].rate / 2,
++ (sn->rates[srate].rate % 2) ? ".5 " : " ");
+ return;
+ }
+
+ 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",
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s ignore bogus rix at %d\n",
+ dev_info, __func__, x);
+ continue;
+ }
+@@ -735,9 +721,9 @@ ath_rate_ctl_reset(struct ath_softc *sc,
+ }
+
+ #if 0
+- DPRINTF(sc, "%s: Retry table for this node\n", __func__);
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s: Retry table for this node\n", __func__);
+ for (x = 0; x < ni->ni_rates.rs_nrates; x++)
+- DPRINTF(sc, "%2d %2d %6d \n", x, sn->retry_count[x], sn->perfect_tx_time[x]);
++ DPRINTF(sc, ATH_DEBUG_RATE, "%2d %2d %6d \n", x, sn->retry_count[x], sn->perfect_tx_time[x]);
+ #endif
+
+ /* Set the initial rate */
+@@ -781,10 +767,10 @@ ath_timer_function(unsigned long data)
+ unsigned int interval = ath_timer_interval;
+
+ if (dev == NULL)
+- DPRINTF(sc, "%s: 'dev' is null in this timer \n", __func__);
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s: 'dev' is null in this timer \n", __func__);
+
+ if (sc == NULL)
+- DPRINTF(sc, "%s: 'sc' is null in this timer\n", __func__);
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s: 'sc' is null in this timer\n", __func__);
+
+ ic = &sc->sc_ic;
+
+@@ -808,7 +794,7 @@ ath_timer_function(unsigned long data)
+
+ timer = &(ssc->timer);
+ if (timer == NULL)
+- DPRINTF(sc, "%s: timer is null - leave it\n", __func__);
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s: timer is null - leave it\n", __func__);
+
+ timer->expires = jiffies + ((HZ * interval) / 1000);
+ add_timer(timer);
+@@ -904,7 +890,7 @@ static struct ath_ratectrl *
+ ath_rate_attach(struct ath_softc *sc)
+ {
+ struct minstrel_softc *osc;
+- DPRINTF(sc, "%s: %s\n", dev_info, __func__);
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s\n", dev_info, __func__);
+
+ _MOD_INC_USE(THIS_MODULE, return NULL);
+ osc = kmalloc(sizeof(struct minstrel_softc), GFP_ATOMIC);
+@@ -963,7 +949,7 @@ ath_proc_read_nodes(struct ieee80211vap
+ p += sprintf(p, "out of room for node " MAC_FMT "\n\n", MAC_ADDR(ni->ni_macaddr));
+ break;
+ }
+- DPRINTF(sc, "%s: out of memeory to write tall of the nodes\n", __func__);
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s: out of memeory to write tall of the nodes\n", __func__);
+ break;
+ }
+ an = ATH_NODE(ni);
+--- a/ath_rate/amrr/amrr.c
++++ b/ath_rate/amrr/amrr.c
+@@ -64,24 +64,13 @@
+ #include <net80211/ieee80211_var.h>
+ #include <net80211/ieee80211_rate.h>
+
++#include "if_ath_debug.h"
+ #include "if_athvar.h"
+ #include "if_ath_hal.h"
+ #include "ah_desc.h"
+
+ #include "amrr.h"
+
+-#ifdef AR_DEBUG
+-#define AMRR_DEBUG
+-#endif
+-#ifdef AMRR_DEBUG
+-#define DPRINTF(sc, _fmt, ...) do { \
+- if (sc->sc_debug & 0x10) \
+- printk(_fmt, __VA_ARGS__); \
+-} while (0)
+-#else
+-#define DPRINTF(sc, _fmt, ...)
+-#endif
+-
+ static int ath_rateinterval = 1000; /* rate ctl interval (ms) */
+ static int ath_rate_max_success_threshold = 10;
+ static int ath_rate_min_success_threshold = 1;
+@@ -197,7 +186,7 @@ ath_rate_update(struct ath_softc *sc, st
+
+ KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
+
+- DPRINTF(sc, "%s: set xmit rate for " MAC_FMT " to %dM\n",
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s: set xmit rate for " MAC_FMT " to %dM\n",
+ __func__, MAC_ADDR(ni->ni_macaddr),
+ ni->ni_rates.rs_nrates > 0 ?
+ (ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL) / 2 : 0);
+@@ -297,9 +286,9 @@ ath_rate_ctl_start(struct ath_softc *sc,
+ * rate set is checked when the station associates.
+ */
+ srate = ni->ni_rates.rs_nrates - 1;
+- for (; srate >= 0 && RATE(srate) != vap->iv_fixed_rate; srate--);
+- KASSERT(srate >= 0,
+- ("fixed rate %d not in rate set", vap->iv_fixed_rate));
++ for (; srate > 0 && RATE(srate) != vap->iv_fixed_rate; srate--);
++ if (RATE(srate) != vap->iv_fixed_rate)
++ EPRINTF(sc, "Invalid static rate, falling back to basic rate\n");
+ }
+ ath_rate_update(sc, ni, srate);
+ #undef RATE
+@@ -377,7 +366,7 @@ ath_rate_ctl(void *arg, struct ieee80211
+
+ old_rate = ni->ni_txrate;
+
+- DPRINTF (sc, "cnt0: %d cnt1: %d cnt2: %d cnt3: %d -- threshold: %d\n",
++ DPRINTF(sc, ATH_DEBUG_RATE, "cnt0: %d cnt1: %d cnt2: %d cnt3: %d -- threshold: %d\n",
+ amn->amn_tx_try0_cnt,
+ amn->amn_tx_try1_cnt,
+ amn->amn_tx_try2_cnt,
+@@ -390,7 +379,7 @@ ath_rate_ctl(void *arg, struct ieee80211
+ amn->amn_recovery = 1;
+ amn->amn_success = 0;
+ ni->ni_txrate++;
+- DPRINTF(sc, "increase rate to %d\n", ni->ni_txrate);
++ DPRINTF(sc, ATH_DEBUG_RATE, "increase rate to %d\n", ni->ni_txrate);
+ } else
+ amn->amn_recovery = 0;
+ } else if (is_failure(amn)) {
+@@ -401,12 +390,12 @@ ath_rate_ctl(void *arg, struct ieee80211
+ amn->amn_success_threshold *= 2;
+ amn->amn_success_threshold = min(amn->amn_success_threshold,
+ (u_int)ath_rate_max_success_threshold);
+- DPRINTF(sc, "decrease rate recovery thr: %d\n",
++ DPRINTF(sc, ATH_DEBUG_RATE, "decrease rate recovery thr: %d\n",
+ amn->amn_success_threshold);
+ } else {
+ /* simple failure. */
+ amn->amn_success_threshold = ath_rate_min_success_threshold;
+- DPRINTF(sc, "decrease rate normal thr: %d\n",
++ DPRINTF(sc, ATH_DEBUG_RATE, "decrease rate normal thr: %d\n",
+ amn->amn_success_threshold);
+ }
+ amn->amn_recovery = 0;
+--- a/ath_rate/onoe/onoe.c
++++ b/ath_rate/onoe/onoe.c
+@@ -60,27 +60,13 @@
+ #include <net80211/ieee80211_var.h>
+ #include <net80211/ieee80211_rate.h>
+
++#include "if_ath_debug.h"
+ #include "if_athvar.h"
+ #include "if_ath_hal.h"
+ #include "ah_desc.h"
+
+ #include "onoe.h"
+
+-#ifdef AR_DEBUG
+-#define ONOE_DEBUG
+-#endif
+-#ifdef ONOE_DEBUG
+-enum {
+- ATH_DEBUG_RATE = 0x00000010, /* rate control */
+-};
+-#define DPRINTF(sc, _fmt, ...) do { \
+- if (sc->sc_debug & ATH_DEBUG_RATE) \
+- printk(_fmt, __VA_ARGS__); \
+-} while (0)
+-#else
+-#define DPRINTF(sc, _fmt, ...)
+-#endif
+-
+ /*
+ * Default parameters for the rate control algorithm. These are
+ * all tunable with sysctls. The rate controller runs periodically
+@@ -186,7 +172,7 @@ ath_rate_update(struct ath_softc *sc, st
+
+ KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
+
+- DPRINTF(sc, "%s: set xmit rate for " MAC_FMT " to %dM\n",
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s: set xmit rate for " MAC_FMT " to %dM\n",
+ __func__, MAC_ADDR(ni->ni_macaddr),
+ ni->ni_rates.rs_nrates > 0 ?
+ (ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL) / 2 : 0);
+@@ -283,9 +269,9 @@ ath_rate_ctl_start(struct ath_softc *sc,
+ */
+ /* NB: the rate set is assumed sorted */
+ srate = ni->ni_rates.rs_nrates - 1;
+- for (; srate >= 0 && RATE(srate) != vap->iv_fixed_rate; srate--);
+- KASSERT(srate >= 0,
+- ("fixed rate %d not in rate set", vap->iv_fixed_rate));
++ for (; srate > 0 && RATE(srate) != vap->iv_fixed_rate; srate--);
++ if (RATE(srate) != vap->iv_fixed_rate)
++ EPRINTF(sc, "Invalid static rate, falling back to basic rate\n");
+ }
+ ath_rate_update(sc, ni, srate);
+ #undef RATE
+@@ -364,7 +350,7 @@ ath_rate_ctl(void *arg, struct ieee80211
+ on->on_tx_retr < (on->on_tx_ok * ath_rate_raise) / 100)
+ dir = 1;
+
+- DPRINTF(sc, MAC_FMT ": ok %d err %d retr %d upper %d dir %d\n",
++ DPRINTF(sc, ATH_DEBUG_RATE, MAC_FMT ": ok %d err %d retr %d upper %d dir %d\n",
+ MAC_ADDR(ni->ni_macaddr),
+ on->on_tx_ok, on->on_tx_err, on->on_tx_retr,
+ on->on_tx_upper, dir);
+@@ -395,7 +381,7 @@ ath_rate_ctl(void *arg, struct ieee80211
+ }
+
+ if (nrate != ni->ni_txrate) {
+- DPRINTF(sc, "%s: %dM -> %dM (%d ok, %d err, %d retr)\n",
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s: %dM -> %dM (%d ok, %d err, %d retr)\n",
+ __func__,
+ (rs->rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL) / 2,
+ (rs->rs_rates[nrate] & IEEE80211_RATE_VAL) / 2,
+--- a/ath_rate/sample/sample.c
++++ b/ath_rate/sample/sample.c
+@@ -62,30 +62,13 @@
+ #include <net80211/ieee80211_var.h>
+ #include <net80211/ieee80211_rate.h>
+
++#include "if_ath_debug.h"
+ #include "if_athvar.h"
+ #include "if_ath_hal.h"
+ #include "ah_desc.h"
+
+ #include "sample.h"
+
+-#ifdef AR_DEBUG
+-#define SAMPLE_DEBUG
+-#endif
+-#ifdef SAMPLE_DEBUG
+-enum {
+- ATH_DEBUG_RATE = 0x00000010, /* rate control */
+- ATH_DEBUG_ANY = 0xffffffff
+-};
+-#define DPRINTF(sc, m, fmt, ...) do { \
+- if (sc->sc_debug & (m)) \
+- printk(fmt, __VA_ARGS__); \
+-} while (0)
+-#else
+-#define DPRINTF(sc, m, fmt, ...) do { \
+- (void) sc; \
+-} while (0)
+-#endif
+-
+ /*
+ * This file is an implementation of the SampleRate algorithm
+ * in "Bit-rate Selection in Wireless Networks"
+@@ -740,7 +723,7 @@ ath_rate_tx_complete(struct ath_softc *s
+ ndx[3] = rate_to_ndx(sn, rate[3]);
+
+ #if 0
+- DPRINTF(sc, "%s: " MAC_FMT " size %u finaltsidx %u tries %u status %u rate/try %u/%u %u/%u %u/%u %u/%u\n",
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s: " MAC_FMT " size %u finaltsidx %u tries %u status %u rate/try %u/%u %u/%u %u/%u %u/%u\n",
+ dev_info, MAC_ADDR(an->an_node.ni_macaddr),
+ bin_to_size(size_to_bin(frame_size)),
+ finalTSIdx,
+@@ -886,15 +869,16 @@ ath_rate_ctl_reset(struct ath_softc *sc,
+ if ((ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL) == vap->iv_fixed_rate)
+ srate = x;
+
+- KASSERT(((ni->ni_rates.rs_rates[srate] & IEEE80211_RATE_VAL) == vap->iv_fixed_rate),
+- ("fixed rate %u not in rate set", vap->iv_fixed_rate));
+-
+ sn->static_rate_ndx = srate;
+ ni->ni_txrate = srate;
+- DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s " MAC_FMT " fixed rate %u%sMbps\n",
+- dev_info, __func__, MAC_ADDR(ni->ni_macaddr),
+- sn->rates[srate].rate / 2,
+- (sn->rates[srate].rate % 0x1) ? ".5" : " ");
++
++ if ((ni->ni_rates.rs_rates[srate] & IEEE80211_RATE_VAL) != vap->iv_fixed_rate)
++ EPRINTF(sc, "Invalid static rate, falling back to basic rate\n");
++ else
++ DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s " MAC_FMT " fixed rate %u%sMbps\n",
++ dev_info, __func__, MAC_ADDR(ni->ni_macaddr),
++ sn->rates[srate].rate / 2,
++ (sn->rates[srate].rate % 0x1) ? ".5" : " ");
+ return;
+ }
+
diff --git a/package/madwifi/patches/380-noderef_hack.patch b/package/madwifi/patches/380-noderef_hack.patch
new file mode 100644
index 000000000..7c082d414
--- /dev/null
+++ b/package/madwifi/patches/380-noderef_hack.patch
@@ -0,0 +1,13 @@
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -427,8 +427,8 @@ ieee80211_reset_bss(struct ieee80211vap
+ __func__, ni, MAC_ADDR(vap->iv_myaddr));
+ KASSERT(ni != NULL, ("unable to setup inital BSS node"));
+
+- vap->iv_bss = PASS_NODE(ni);
+- KASSERT((atomic_read(&vap->iv_bss->ni_refcnt) == 2),
++ vap->iv_bss = ieee80211_ref_node(ni);
++ KASSERT((atomic_read(&vap->iv_bss->ni_refcnt) == 3),
+ ("wrong refcount for new node."));
+
+ if (obss != NULL) {
diff --git a/package/madwifi/patches/381-ibss_modes.patch b/package/madwifi/patches/381-ibss_modes.patch
new file mode 100644
index 000000000..38969b053
--- /dev/null
+++ b/package/madwifi/patches/381-ibss_modes.patch
@@ -0,0 +1,23 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -1260,7 +1260,10 @@ ath_vap_create(struct ieee80211com *ic,
+ case IEEE80211_M_IBSS:
+ if ((sc->sc_nvaps != 0) && (ic->ic_opmode == IEEE80211_M_STA))
+ return NULL;
+- ic_opmode = opmode;
++ if (ic->ic_opmode == IEEE80211_M_HOSTAP)
++ ic_opmode = ic->ic_opmode;
++ else
++ ic_opmode = opmode;
+ break;
+ case IEEE80211_M_AHDEMO:
+ case IEEE80211_M_MONITOR:
+@@ -1455,7 +1458,7 @@ ath_vap_create(struct ieee80211com *ic,
+ * frames. Other modes carry over directly to the HAL.
+ */
+ if (ic->ic_opmode == IEEE80211_M_AHDEMO)
+- sc->sc_opmode = HAL_M_IBSS;
++ sc->sc_opmode = HAL_M_HOSTAP;
+ else
+ sc->sc_opmode = (HAL_OPMODE) ic->ic_opmode; /* NB: compatible */
+
diff --git a/package/madwifi/patches/382-relax_bintval.patch b/package/madwifi/patches/382-relax_bintval.patch
new file mode 100644
index 000000000..0901949d9
--- /dev/null
+++ b/package/madwifi/patches/382-relax_bintval.patch
@@ -0,0 +1,13 @@
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -61,8 +61,8 @@
+ #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_MAX 5000 /* max beacon interval (TUs) */
++#define IEEE80211_BINTVAL_MIN 10 /* min beacon interval (TUs) */
+ #define IEEE80211_BINTVAL_DEFAULT 100 /* default beacon interval (TUs) */
+ #define IEEE80211_BINTVAL_VALID(_bi) \
+ ((IEEE80211_BINTVAL_MIN <= (_bi)) && \
diff --git a/package/madwifi/patches/383-ibss_hostap.patch b/package/madwifi/patches/383-ibss_hostap.patch
new file mode 100644
index 000000000..d449c3037
--- /dev/null
+++ b/package/madwifi/patches/383-ibss_hostap.patch
@@ -0,0 +1,105 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -1452,6 +1452,23 @@ ath_vap_create(struct ieee80211com *ic,
+ sc->sc_nstavaps++;
+ else if (opmode == IEEE80211_M_MONITOR)
+ sc->sc_nmonvaps++;
++
++
++ /* Driving the HAL in IBSS sometimes adapts the TSF and other timing registers
++ * from received beacons/probes. If that happens, expected TX interrupts may
++ * not occur until next reset. Which triggers the "lost beacon" tasklet.
++ * Resulting effectively in not sending packets for minutes. Because that only
++ * happens in large mesh networks, this mode needs to be activated by a kernel
++ * module parameter: hostap_for_ibss=1. Note that using this mode has side
++ * effects. Such as not supressing beacons/probe answers randomly when
++ * receiving other node beacons. It's recommended to lower the beacon interval
++ * then. When using an IBSS-VAP together with an HOSTAP-VAP, you may also need
++ * to re-trigger IBSS beacon generation after creating the HOSTAP-VAP by
++ * issueing "iwpriv athX bintval 1000".
++ */
++ if ((flags & IEEE80211_NO_STABEACONS) && (ic->ic_opmode == IEEE80211_M_IBSS))
++ sc->sc_opmode = HAL_M_HOSTAP;
++ else
+ /*
+ * Adhoc demo mode is a pseudo mode; to the HAL it's
+ * just IBSS mode and the driver doesn't use management
+@@ -4279,7 +4296,8 @@ ath_calcrxfilter(struct ath_softc *sc)
+ if (ic->ic_opmode != IEEE80211_M_HOSTAP && (dev->flags & IFF_PROMISC))
+ rfilt |= HAL_RX_FILTER_PROM;
+ if (ic->ic_opmode == IEEE80211_M_STA ||
+- sc->sc_opmode == HAL_M_IBSS || /* NB: AHDEMO too */
++ ic->ic_opmode == IEEE80211_M_IBSS ||
++ ic->ic_opmode == IEEE80211_M_AHDEMO ||
+ (sc->sc_nostabeacons) || sc->sc_scanning ||
+ (ic->ic_opmode == IEEE80211_M_HOSTAP))
+ rfilt |= HAL_RX_FILTER_BEACON;
+@@ -6435,6 +6453,33 @@ ath_capture(struct net_device *dev, cons
+ }
+
+ /*
++ * Advances (forwards/adds) a microsecond value to current chip's TSF registers
++ */
++
++/* from ath_info.c */
++#define AR5K_TSF_L32_5210 0x806c /* TSF (lower 32 bits) */
++#define AR5K_TSF_L32_5211 0x804c
++#define AR5K_TSF_L32 (ar_device(ah->ah_sc->devid) == 5210 ? \
++ AR5K_TSF_L32_5210 : AR5K_TSF_L32_5211)
++
++#define AR5K_TSF_U32_5210 0x8070
++#define AR5K_TSF_U32_5211 0x8050
++#define AR5K_TSF_U32 (ar_device(ah->ah_sc->devid) == 5210 ? \
++ AR5K_TSF_U32_5210 : AR5K_TSF_U32_5211)
++
++static inline void ath_hal_settsf64(struct ath_hal *ah, u_int64_t tsf_adv)
++{
++ ATH_HAL_LOCK_IRQ(ah->ah_sc);
++ ath_hal_set_function(__func__);
++ tsf_adv += ah->ah_getTsf64(ah);
++ OS_REG_WRITE(ah, AR5K_TSF_L32, 0ll);
++ OS_REG_WRITE(ah, AR5K_TSF_U32, (tsf_adv >> 32) & 0xffffffffll);
++ OS_REG_WRITE(ah, AR5K_TSF_L32, (tsf_adv >> 00) & 0xffffffffll);
++ ath_hal_set_function(NULL);
++ ATH_HAL_UNLOCK_IRQ(ah->ah_sc);
++}
++
++/*
+ * Intercept management frames to collect beacon RSSI data and to do
+ * ibss merges. This function is called for all management frames,
+ * including those belonging to other BSS.
+@@ -6487,10 +6532,19 @@ ath_recv_mgmt(struct ieee80211vap * vap,
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+ "Updated beacon timers\n");
+ }
+- if ((sc->sc_opmode == HAL_M_IBSS) &&
+- IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid) &&
+- ath_hw_check_atim(sc, 1, vap->iv_bss->ni_intval)) {
+- DPRINTF(sc, ATH_DEBUG_ANY, "Fixed ATIM window after beacon recv\n");
++ if ((vap->iv_opmode == IEEE80211_M_IBSS) &&
++ (sc->sc_opmode == HAL_M_HOSTAP) &&
++ IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid)) {
++ /* In this mode, we drive the HAL in HOSTAP mode. Hence
++ * we do the IBSS merging in software. Also do not merge
++ * if the difference it too small. Otherwise we are playing
++ * tsf-pingpong with other vendors drivers */
++ beacon_tsf = le64_to_cpu(ni->ni_tstamp.tsf);
++ if (beacon_tsf > rtsf + 0xffff) {
++ ath_hal_settsf64(sc->sc_ah, beacon_tsf - rtsf);
++ ieee80211_ibss_merge(ni);
++ }
++ break;
+ }
+ /* NB: Fall Through */
+ case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
+@@ -6563,6 +6617,10 @@ ath_recv_mgmt(struct ieee80211vap * vap,
+ #endif
+ if (do_merge)
+ ieee80211_ibss_merge(ni);
++
++ if ((sc->sc_opmode == HAL_M_IBSS) &&
++ ath_hw_check_atim(sc, 1, vap->iv_bss->ni_intval))
++ DPRINTF(sc, ATH_DEBUG_ANY, "Fixed ATIM window after beacon recv\n");
+ }
+ break;
+ }
diff --git a/package/madwifi/patches/384-hwdetect.patch b/package/madwifi/patches/384-hwdetect.patch
new file mode 100644
index 000000000..3b67615b0
--- /dev/null
+++ b/package/madwifi/patches/384-hwdetect.patch
@@ -0,0 +1,325 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -62,6 +62,7 @@
+ #include <linux/if_arp.h>
+ #include <linux/rtnetlink.h>
+ #include <linux/time.h>
++#include <linux/pci.h>
+ #include <asm/uaccess.h>
+
+ #include "if_ethersubr.h" /* for ETHER_IS_MULTICAST */
+@@ -401,6 +402,15 @@ static int outdoor = -1;
+ static int xchanmode = -1;
+ static int beacon_cal = 1;
+
++static const struct ath_hw_detect generic_hw_info = {
++ .vendor_name = "Unknown",
++ .card_name = "Generic",
++ .vendor = PCI_ANY_ID,
++ .id = PCI_ANY_ID,
++ .subvendor = PCI_ANY_ID,
++ .subid = PCI_ANY_ID
++};
++
+ static const char *hal_status_desc[] = {
+ "No error",
+ "No hardware present or device not yet supported",
+@@ -542,6 +552,8 @@ ath_attach(u_int16_t devid, struct net_d
+ DPRINTF(sc, ATH_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid);
+ #endif
+
++ sc->sc_hwinfo = &generic_hw_info;
++
+ /* Allocate space for dynamically determined maximum VAP count */
+ sc->sc_bslot =
+ kmalloc(ath_maxvaps * sizeof(struct ieee80211vap*), GFP_KERNEL);
+@@ -1508,6 +1520,29 @@ ath_vap_create(struct ieee80211com *ic,
+ return vap;
+ }
+
++void
++ath_hw_detect(struct ath_softc *sc, const struct ath_hw_detect *cards, int n_cards, u32 vendor, u32 id, u32 subvendor, u32 subid)
++{
++ int i;
++
++ for (i = 0; i < n_cards; i++) {
++ const struct ath_hw_detect *c = &cards[i];
++
++ if ((c->vendor != PCI_ANY_ID) && c->vendor != vendor)
++ continue;
++ if ((c->id != PCI_ANY_ID) && c->id != id)
++ continue;
++ if ((c->subvendor != PCI_ANY_ID) && c->subvendor != subvendor)
++ continue;
++ if ((c->subid != PCI_ANY_ID) && c->subid != subid)
++ continue;
++
++ sc->sc_hwinfo = c;
++ sc->sc_poweroffset = c->poweroffset;
++ break;
++ }
++}
++
+ static void
+ ath_vap_delete(struct ieee80211vap *vap)
+ {
+@@ -10225,6 +10260,7 @@ static u_int32_t
+ ath_set_clamped_maxtxpower(struct ath_softc *sc,
+ u_int32_t new_clamped_maxtxpower)
+ {
++ new_clamped_maxtxpower -= sc->sc_poweroffset;
+ (void)ath_hal_settxpowlimit(sc->sc_ah, new_clamped_maxtxpower);
+ return ath_get_clamped_maxtxpower(sc);
+ }
+@@ -10238,6 +10274,7 @@ ath_get_clamped_maxtxpower(struct ath_so
+ {
+ u_int32_t clamped_maxtxpower;
+ (void)ath_hal_getmaxtxpow(sc->sc_ah, &clamped_maxtxpower);
++ clamped_maxtxpower += sc->sc_poweroffset;
+ return clamped_maxtxpower;
+ }
+
+@@ -10821,6 +10858,12 @@ ath_ioctl(struct net_device *dev, struct
+ * is to add module parameters.
+ */
+
++/* sysctls for hardware info */
++enum {
++ ATH_CARD_VENDOR,
++ ATH_CARD_NAME,
++};
++
+ /*
+ * Dynamic (i.e. per-device) sysctls. These are automatically
+ * mirrored in /proc/sys.
+@@ -10900,6 +10943,38 @@ ath_sysctl_get_intmit(struct ath_softc *
+ }
+
+ static int
++ATH_SYSCTL_DECL(ath_sysctl_hwinfo, ctl, write, filp, buffer, lenp, ppos)
++{
++ struct ath_softc *sc = ctl->extra1;
++ struct ath_hal *ah = sc->sc_ah;
++ int ret = 0;
++
++ if (write)
++ return -EINVAL;
++
++ ATH_LOCK(sc);
++ switch((long)ctl->extra2) {
++ case ATH_CARD_VENDOR:
++ ctl->data = (char *)sc->sc_hwinfo->vendor_name;
++ break;
++ case ATH_CARD_NAME:
++ ctl->data = (char *)sc->sc_hwinfo->card_name;
++ break;
++ default:
++ ret = -EINVAL;
++ break;
++ }
++ if (ret == 0) {
++ ctl->maxlen = strlen(ctl->data);
++ ret = ATH_SYSCTL_PROC_DOSTRING(ctl, write, filp,
++ buffer, lenp, ppos);
++ }
++ ATH_UNLOCK(sc);
++
++ return ret;
++}
++
++static int
+ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl, write, filp, buffer, lenp, ppos)
+ {
+ struct ath_softc *sc = ctl->extra1;
+@@ -11179,6 +11254,24 @@ static int maxint = 0x7fffffff; /* 32-b
+
+ static const ctl_table ath_sysctl_template[] = {
+ { .ctl_name = CTL_AUTO,
++ .procname = "dev_vendor",
++ .mode = 0644,
++ .proc_handler = ath_sysctl_hwinfo,
++ .strategy = &sysctl_string,
++ .data = "N/A",
++ .maxlen = 1,
++ .extra2 = (void *)ATH_CARD_VENDOR,
++ },
++ { .ctl_name = CTL_AUTO,
++ .procname = "dev_name",
++ .mode = 0644,
++ .proc_handler = ath_sysctl_hwinfo,
++ .strategy = &sysctl_string,
++ .data = "N/A",
++ .maxlen = 1,
++ .extra2 = (void *)ATH_CARD_NAME,
++ },
++ { .ctl_name = CTL_AUTO,
+ .procname = "slottime",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -168,12 +168,16 @@ static inline struct net_device *_alloc_
+ void __user *buffer, size_t *lenp)
+ #define ATH_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos) \
+ proc_dointvec(ctl, write, filp, buffer, lenp)
++#define ATH_SYSCTL_PROC_DOSTRING(ctl, write, filp, buffer, lenp, ppos) \
++ proc_dostring(ctl, write, filp, buffer, lenp)
+ #else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) */
+ #define ATH_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 ATH_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos) \
+ proc_dointvec(ctl, write, filp, buffer, lenp, ppos)
++#define ATH_SYSCTL_PROC_DOSTRING(ctl, write, filp, buffer, lenp, ppos) \
++ proc_dostring(ctl, write, filp, buffer, lenp, ppos)
+ #endif
+
+ #define ATH_TIMEOUT 1000
+@@ -469,6 +473,7 @@ struct ath_hal;
+ struct ath_desc;
+ struct ath_ratectrl;
+ struct ath_tx99;
++struct ath_hw_detect;
+ struct proc_dir_entry;
+
+ /*
+@@ -629,6 +634,7 @@ struct ath_softc {
+ struct ath_ratectrl *sc_rc; /* tx rate control support */
+ struct ath_tx99 *sc_tx99; /* tx99 support */
+ void (*sc_setdefantenna)(struct ath_softc *, u_int);
++ const struct ath_hw_detect *sc_hwinfo;
+
+ unsigned int sc_invalid:1; /* being detached */
+ unsigned int sc_mrretry:1; /* multi-rate retry support */
+@@ -683,6 +689,7 @@ struct ath_softc {
+ const HAL_RATE_TABLE *sc_quarter_rates; /* quarter rate table */
+ HAL_OPMODE sc_opmode; /* current hal operating mode */
+ enum ieee80211_phymode sc_curmode; /* current phy mode */
++ u_int sc_poweroffset; /* hardware power offset */
+ u_int16_t sc_curtxpow; /* current tx power limit */
+ u_int16_t sc_curaid; /* current association id */
+ HAL_CHANNEL sc_curchan; /* current h/w channel */
+@@ -929,4 +936,16 @@ int ar_device(int devid);
+
+ void ath_radar_detected(struct ath_softc *sc, const char* message);
+
++struct ath_hw_detect {
++ const char *vendor_name;
++ const char *card_name;
++ u32 vendor;
++ u32 id;
++ u32 subvendor;
++ u32 subid;
++ u32 poweroffset;
++};
++
++extern void ath_hw_detect(struct ath_softc *sc, const struct ath_hw_detect *cards, int n_cards, u32 vendor, u32 id, u32 subvendor, u32 subid);
++
+ #endif /* _DEV_ATH_ATHVAR_H */
+--- a/ath/if_ath_ahb.c
++++ b/ath/if_ath_ahb.c
+@@ -20,6 +20,7 @@
+ #include <linux/netdevice.h>
+ #include <linux/cache.h>
+ #include <linux/platform_device.h>
++#include <linux/pci.h>
+
+ #include <asm/io.h>
+ #include <asm/uaccess.h>
+@@ -181,12 +182,32 @@ exit_ath_wmac(u_int16_t wlanNum, struct
+ return 0;
+ }
+
++static const char ubnt[] = "Ubiquiti Networks";
++/* { vendorname, cardname, vendorid, cardid, subsys vendorid, subsys id, poweroffset } */
++static const struct ath_hw_detect cards[] = {
++ { ubnt, "PowerStation2 (18V)", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xb102 },
++ { ubnt, "PowerStation2 (16D)", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xb202 },
++ { ubnt, "PowerStation2 (EXT)", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xb302 },
++ { ubnt, "PowerStation5 (22V)", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xb105 },
++ { ubnt, "PowerStation5 (EXT)", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xb305 },
++ { ubnt, "WispStation5", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xa105 },
++ { ubnt, "LiteStation2", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xa002 },
++ { ubnt, "LiteStation5", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xa005 },
++ { ubnt, "NanoStation2", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xc002 },
++ { ubnt, "NanoStation5", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xc005 },
++ { ubnt, "NanoStation Loco2", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xc102 },
++ { ubnt, "NanoStation Loco5", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xc105 },
++ { ubnt, "Bullet2", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xc202 },
++ { ubnt, "Bullet5", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xc205 },
++};
++
+ static int
+ init_ath_wmac(u_int16_t devid, u_int16_t wlanNum, struct ar531x_config *config)
+ {
+ const char *athname;
+ struct net_device *dev;
+ struct ath_ahb_softc *sc;
++ u16 *radio_data;
+
+ if (((wlanNum != 0) && (wlanNum != 1)) ||
+ (sclist[wlanNum] != NULL))
+@@ -248,6 +269,16 @@ init_ath_wmac(u_int16_t devid, u_int16_t
+ sc->aps_sc.sc_softled = 1; /* SoftLED over GPIO */
+ sc->aps_sc.sc_ledpin = config->board->sysLedGpio;
+ sc->aps_sc.sc_invalid = 0;
++ radio_data = (u16 *) config->radio;
++ if (radio_data) {
++ u16 vendor, id, subvendor, subid;
++ vendor = radio_data[1];
++ id = radio_data[0];
++ subvendor = radio_data[8];
++ subid = radio_data[7];
++ ath_hw_detect(&sc->aps_sc, cards, ARRAY_SIZE(cards), vendor, id, subvendor, subid);
++ }
++
+ return 0;
+
+ bad4:
+--- a/ath/if_ath_pci.c
++++ b/ath/if_ath_pci.c
+@@ -123,6 +123,33 @@ static u16 ath_devidmap[][2] = {
+ { 0xff1a, 0x001a }
+ };
+
++static const char ubnt[] = "Ubiquiti Networks";
++/* { vendorname, cardname, vendorid, cardid, subsys vendorid, subsys id, poweroffset } */
++static const struct ath_hw_detect cards[] = {
++ { ubnt, "XR2", 0x168c, 0x001b, 0x0777, 0x3002, 10 },
++ { ubnt, "XR2", 0x168c, 0x001b, 0x7777, 0x3002, 10 },
++ { ubnt, "XR2.3", 0x168c, 0x001b, 0x0777, 0x3b02, 10 },
++ { ubnt, "XR2.6", 0x168c, 0x001b, 0x0777, 0x3c02, 10 },
++ { ubnt, "XR3-2.8", 0x168c, 0x001b, 0x0777, 0x3b03, 10 },
++ { ubnt, "XR3-3.6", 0x168c, 0x001b, 0x0777, 0x3c03, 10 },
++ { ubnt, "XR3", 0x168c, 0x001b, 0x0777, 0x3003, 10 },
++ { ubnt, "XR4", 0x168c, 0x001b, 0x0777, 0x3004, 10 },
++ { ubnt, "XR5", 0x168c, 0x001b, 0x0777, 0x3005, 10 },
++ { ubnt, "XR5", 0x168c, 0x001b, 0x7777, 0x3005, 10 },
++ { ubnt, "XR7", 0x168c, 0x001b, 0x0777, 0x3007, 10 },
++ { ubnt, "XR9", 0x168c, 0x001b, 0x0777, 0x3009, 10 },
++ { ubnt, "SRC", 0x168c, 0x0013, 0x168c, 0x1042, 1 },
++ { ubnt, "SR2", 0x168c, 0x0013, 0x0777, 0x2041, 10 },
++ { ubnt, "SR4", 0x168c, 0x0013, 0x0777, 0x2004, 6 },
++ { ubnt, "SR4", 0x168c, 0x0013, 0x7777, 0x2004, 6 },
++ { ubnt, "SR4C", 0x168c, 0x0013, 0x0777, 0x1004, 6 },
++ { ubnt, "SR4C", 0x168c, 0x0013, 0x7777, 0x1004, 6 },
++ { ubnt, "SR5", 0x168c, 0x0013, 0x168c, 0x2042, 7 },
++ { ubnt, "SR9", 0x168c, 0x0013, 0x7777, 0x2009, 12 },
++ { ubnt, "SR71A", 0x168c, 0x0027, 0x168c, 0x2082, 10 },
++ { ubnt, "SR71", 0x168c, 0x0027, 0x0777, 0x4082, 10 },
++};
++
+ static int
+ ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+@@ -257,6 +284,10 @@ ath_pci_probe(struct pci_dev *pdev, cons
+ printk(KERN_INFO "%s: %s: %s: mem=0x%lx, irq=%d\n",
+ dev_info, dev->name, athname ? athname : "Atheros ???", phymem, dev->irq);
+
++ ath_hw_detect(&sc->aps_sc, cards, ARRAY_SIZE(cards),
++ pdev->vendor, pdev->device,
++ pdev->subsystem_vendor, pdev->subsystem_device);
++
+ /* ready to process interrupts */
+ sc->aps_sc.sc_invalid = 0;
+
diff --git a/package/madwifi/patches/385-antenna_fix.patch b/package/madwifi/patches/385-antenna_fix.patch
new file mode 100644
index 000000000..16c7d95c7
--- /dev/null
+++ b/package/madwifi/patches/385-antenna_fix.patch
@@ -0,0 +1,10 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -6669,6 +6669,7 @@ ath_setdefantenna(struct ath_softc *sc,
+ struct ath_hal *ah = sc->sc_ah;
+
+ /* XXX block beacon interrupts */
++ ath_hal_setdiversity(ah, (sc->sc_diversity != 0));
+ ath_hal_setdefantenna(ah, antenna);
+ if (sc->sc_defant != antenna)
+ sc->sc_stats.ast_ant_defswitch++;
diff --git a/package/madwifi/patches/386-acl_crashfix.patch b/package/madwifi/patches/386-acl_crashfix.patch
new file mode 100644
index 000000000..04a1ec911
--- /dev/null
+++ b/package/madwifi/patches/386-acl_crashfix.patch
@@ -0,0 +1,116 @@
+fixes ACL race condition caused by acl list modifications at run time
+
+Signed-off-by: Sebastian Gottschall <brainslayer@dd-wrt.com>
+
+--- a/net80211/ieee80211_acl.c
++++ b/net80211/ieee80211_acl.c
+@@ -112,9 +112,9 @@ acl_detach(struct ieee80211vap *vap)
+ {
+ struct aclstate *as = vap->iv_as;
+
+- ACL_LOCK(as);
++ ACL_LOCK_IRQ(as);
+ acl_free_all_locked(as);
+- ACL_UNLOCK(as);
++ ACL_UNLOCK_IRQ(as);
+ vap->iv_as = NULL;
+ ACL_LOCK_DESTROY(as);
+ FREE(as, M_DEVBUF);
+@@ -128,11 +128,18 @@ _find_acl(struct aclstate *as, const u_i
+ struct acl *acl;
+ int hash;
+
++ /* locking needed, as inserts are not atomic */
++ ACL_LOCK_IRQ(as);
+ hash = ACL_HASH(macaddr);
+ LIST_FOREACH(acl, &as->as_hash[hash], acl_hash) {
+- if (IEEE80211_ADDR_EQ(acl->acl_macaddr, macaddr))
+- return acl;
++ if (!IEEE80211_ADDR_EQ(acl->acl_macaddr, macaddr))
++ continue;
++
++ ACL_UNLOCK_IRQ_EARLY(as);
++ return acl;
+ }
++ ACL_UNLOCK_IRQ(as);
++
+ return NULL;
+ }
+
+@@ -176,11 +183,11 @@ acl_add(struct ieee80211vap *vap, const
+ return -ENOMEM;
+ }
+
+- ACL_LOCK(as);
++ ACL_LOCK_IRQ(as);
+ hash = ACL_HASH(mac);
+ LIST_FOREACH(acl, &as->as_hash[hash], acl_hash) {
+ if (IEEE80211_ADDR_EQ(acl->acl_macaddr, mac)) {
+- ACL_UNLOCK_EARLY(as);
++ ACL_UNLOCK_IRQ_EARLY(as);
+ FREE(new, M_80211_ACL);
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL,
+ "ACL: add " MAC_FMT " failed, already present\n",
+@@ -191,7 +198,7 @@ acl_add(struct ieee80211vap *vap, const
+ IEEE80211_ADDR_COPY(new->acl_macaddr, mac);
+ TAILQ_INSERT_TAIL(&as->as_list, new, acl_list);
+ LIST_INSERT_HEAD(&as->as_hash[hash], new, acl_hash);
+- ACL_UNLOCK(as);
++ ACL_UNLOCK_IRQ(as);
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL,
+ "ACL: add " MAC_FMT "\n", MAC_ADDR(mac));
+@@ -204,11 +211,11 @@ acl_remove(struct ieee80211vap *vap, con
+ struct aclstate *as = vap->iv_as;
+ struct acl *acl;
+
+- ACL_LOCK(as);
++ ACL_LOCK_IRQ(as);
+ acl = _find_acl(as, mac);
+ if (acl != NULL)
+ _acl_free(as, acl);
+- ACL_UNLOCK(as);
++ ACL_UNLOCK_IRQ(as);
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL,
+ "ACL: remove " MAC_FMT "%s\n", MAC_ADDR(mac),
+@@ -235,9 +242,9 @@ acl_free_all(struct ieee80211vap *vap)
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL, "ACL: %s\n", "free all");
+
+- ACL_LOCK(as);
++ ACL_LOCK_IRQ(as);
+ acl_free_all_locked(vap->iv_as);
+- ACL_UNLOCK(as);
++ ACL_UNLOCK_IRQ(as);
+
+ return 0;
+ }
+--- a/net80211/ieee80211_linux.h
++++ b/net80211/ieee80211_linux.h
+@@ -319,16 +319,15 @@ typedef spinlock_t ieee80211_scan_lock_t
+ 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);
++#define ACL_LOCK_IRQ(_as) do { \
++ unsigned long __acl_lockflags; \
++ spin_lock_irqsave(&(_as)->as_lock, __acl_lockflags);
++#define ACL_UNLOCK_IRQ(_as) \
++ spin_unlock_irqrestore(&(_as)->as_lock, __acl_lockflags); \
++} while (0)
++#define ACL_UNLOCK_IRQ_EARLY(_as) do { \
++ spin_unlock_irqrestore(&(_as)->as_lock, __acl_lockflags); \
++} while (0)
+
+ #if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
+ #define ACL_LOCK_ASSERT(_as) \
diff --git a/package/madwifi/patches/387-maxassoc.patch b/package/madwifi/patches/387-maxassoc.patch
new file mode 100644
index 000000000..79e5b2f4f
--- /dev/null
+++ b/package/madwifi/patches/387-maxassoc.patch
@@ -0,0 +1,85 @@
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -198,6 +198,7 @@ struct ieee80211vap {
+ u_int32_t iv_debug; /* debug msg flags */
+ struct ieee80211_stats iv_stats; /* statistics */
+
++ int iv_max_nodes;
+ 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 */
+--- a/net80211/ieee80211_ioctl.h
++++ b/net80211/ieee80211_ioctl.h
+@@ -650,6 +650,7 @@ enum {
+ IEEE80211_PARAM_RSSI_DIS_THR = 80, /* rssi threshold for disconnection */
+ IEEE80211_PARAM_RSSI_DIS_COUNT = 81, /* counter for rssi threshold */
+ IEEE80211_PARAM_WDS_SEP = 82, /* move wds stations into separate interfaces */
++ IEEE80211_PARAM_MAXASSOC = 83, /* maximum associated stations */
+ };
+
+ #define SIOCG80211STATS (SIOCDEVPRIVATE+2)
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -2875,6 +2875,12 @@ ieee80211_ioctl_setparam(struct net_devi
+ else
+ vap->iv_flags_ext &= ~IEEE80211_FEXT_WDSSEP;
+ break;
++ case IEEE80211_PARAM_MAXASSOC:
++ if (vap->iv_opmode != IEEE80211_M_HOSTAP)
++ retv = -EINVAL;
++ else
++ vap->iv_max_nodes = value;
++ break;
+ #ifdef ATH_REVERSE_ENGINEERING
+ case IEEE80211_PARAM_DUMPREGS:
+ ieee80211_dump_registers(dev, info, w, extra);
+@@ -3234,6 +3240,9 @@ ieee80211_ioctl_getparam(struct net_devi
+ case IEEE80211_PARAM_WDS_SEP:
+ param[0] = !!(vap->iv_flags_ext & IEEE80211_FEXT_WDSSEP);
+ break;
++ case IEEE80211_PARAM_MAXASSOC:
++ param[0] = vap->iv_max_nodes;
++ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+@@ -5789,6 +5798,10 @@ static const struct iw_priv_args ieee802
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wdssep"},
+ { IEEE80211_PARAM_WDS_SEP,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_wdssep"},
++ { IEEE80211_PARAM_MAXASSOC,
++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "maxassoc"},
++ { IEEE80211_PARAM_MAXASSOC,
++ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_maxassoc"},
+
+ #ifdef ATH_REVERSE_ENGINEERING
+ /*
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -4020,7 +4020,26 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ vap->iv_stats.is_rx_assoc_norate++;
+ return;
+ }
++ if (vap->iv_max_nodes > 0) {
++ unsigned int active_nodes = 0;
++ struct ieee80211_node *tni;
+
++ IEEE80211_NODE_TABLE_LOCK_IRQ(&ic->ic_sta);
++ TAILQ_FOREACH(tni, &ic->ic_sta.nt_node, ni_list) {
++ if (tni->ni_vap != vap)
++ continue;
++ if (tni->ni_associd == 0)
++ continue;
++ active_nodes++;
++ }
++ IEEE80211_NODE_TABLE_UNLOCK_IRQ(&ic->ic_sta);
++
++ if (active_nodes >= vap->iv_max_nodes) {
++ /* too many nodes connected */
++ ieee80211_node_leave(ni);
++ return;
++ }
++ }
+ if (ni->ni_associd != 0 &&
+ IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) {
+ if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME)
diff --git a/package/madwifi/patches/388-apsta_fix.patch b/package/madwifi/patches/388-apsta_fix.patch
new file mode 100644
index 000000000..b0cb8e9df
--- /dev/null
+++ b/package/madwifi/patches/388-apsta_fix.patch
@@ -0,0 +1,60 @@
+--- a/net80211/ieee80211_proto.c
++++ b/net80211/ieee80211_proto.c
+@@ -1415,7 +1415,8 @@ __ieee80211_newstate(struct ieee80211vap
+ vap->iv_state = nstate; /* state transition */
+ del_timer(&vap->iv_mgtsend);
+ if ((vap->iv_opmode != IEEE80211_M_HOSTAP) &&
+- (ostate != IEEE80211_S_SCAN))
++ (ostate != IEEE80211_S_SCAN) &&
++ !(vap->iv_flags_ext & IEEE80211_FEXT_SCAN_PENDING))
+ ieee80211_cancel_scan(vap); /* background scan */
+ ni = vap->iv_bss; /* NB: no reference held */
+ switch (nstate) {
+@@ -1457,7 +1458,8 @@ __ieee80211_newstate(struct ieee80211vap
+ }
+ goto reset;
+ case IEEE80211_S_SCAN:
+- ieee80211_cancel_scan(vap);
++ if (!(vap->iv_flags_ext & IEEE80211_FEXT_SCAN_PENDING))
++ ieee80211_cancel_scan(vap);
+ goto reset;
+ reset:
+ ieee80211_reset_bss(vap);
+@@ -1995,7 +1997,9 @@ ieee80211_newstate(struct ieee80211vap *
+ }
+ }
+ }
+- } else if (dstate == IEEE80211_S_SCAN) {
++ } else if ((dstate == IEEE80211_S_SCAN) ||
++ (dstate == IEEE80211_S_AUTH) ||
++ (dstate == IEEE80211_S_ASSOC)) {
+ /* Force to scan pending... someone is scanning */
+ vap->iv_flags_ext |= IEEE80211_FEXT_SCAN_PENDING;
+ __ieee80211_newstate(vap, IEEE80211_S_INIT, arg);
+--- a/net80211/ieee80211_output.c
++++ b/net80211/ieee80211_output.c
+@@ -238,7 +238,9 @@ ieee80211_hardstart(struct sk_buff *skb,
+ }
+
+ /* Cancel any running BG scan */
+- if (!(ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN_THR) && (vap->iv_state == IEEE80211_S_RUN))
++ if (!(ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN_THR) &&
++ (vap->iv_state == IEEE80211_S_RUN) &&
++ (ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN))
+ ieee80211_cancel_scan(vap);
+
+ /*
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -2728,9 +2728,9 @@ ieee80211_ioctl_setparam(struct net_devi
+ return -EINVAL;
+ vap->iv_flags |= IEEE80211_F_BGSCAN;
+ } else {
+- /* XXX racey? */
++ if (ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN)
++ ieee80211_cancel_scan(vap); /* anything current */
+ vap->iv_flags &= ~IEEE80211_F_BGSCAN;
+- ieee80211_cancel_scan(vap); /* anything current */
+ }
+ break;
+ case IEEE80211_PARAM_BGSCAN_IDLE:
diff --git a/package/madwifi/patches/389-autochannel.patch b/package/madwifi/patches/389-autochannel.patch
new file mode 100644
index 000000000..548f09e7d
--- /dev/null
+++ b/package/madwifi/patches/389-autochannel.patch
@@ -0,0 +1,249 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -384,6 +384,7 @@ static u_int32_t ath_get_real_maxtxpower
+
+ static void ath_poll_disable(struct net_device *dev);
+ static void ath_poll_enable(struct net_device *dev);
++static void ath_fetch_idle_time(struct ath_softc *sc);
+
+ /* calibrate every 30 secs in steady state but check every second at first. */
+ static int ath_calinterval = ATH_SHORT_CALINTERVAL;
+@@ -2581,6 +2582,7 @@ ath_init(struct net_device *dev)
+ * be followed by initialization of the appropriate bits
+ * and then setup of the interrupt mask.
+ */
++ ath_fetch_idle_time(sc);
+ sc->sc_curchan.channel = ic->ic_curchan->ic_freq;
+ sc->sc_curchan.channelFlags = ath_chan2flags(ic->ic_curchan);
+ if (!ath_hal_reset(ah, sc->sc_opmode, &sc->sc_curchan, AH_FALSE, &status)) {
+@@ -2914,6 +2916,48 @@ ath_hw_check_atim(struct ath_softc *sc,
+ return 0;
+ }
+
++#define AR5K_MIBC 0x0040
++#define AR5K_MIBC_FREEZE (1 << 1)
++#define AR5K_TXFC 0x80ec
++#define AR5K_RXFC 0x80f0
++#define AR5K_RXCLEAR 0x80f4
++#define AR5K_CYCLES 0x80f8
++static void
++ath_fetch_idle_time(struct ath_softc *sc)
++{
++ struct ieee80211com *ic = &sc->sc_ic;
++ struct ath_hal *ah = sc->sc_ah;
++ u_int32_t cc, rx;
++ u_int32_t time = 0;
++
++ if (sc->sc_ah->ah_macType < 5212)
++ return;
++
++ if (!ic->ic_curchan || (ic->ic_curchan == IEEE80211_CHAN_ANYC))
++ return;
++
++ OS_REG_WRITE(ah, AR5K_MIBC, AR5K_MIBC_FREEZE);
++ rx = OS_REG_READ(ah, AR5K_RXCLEAR);
++ cc = OS_REG_READ(ah, AR5K_CYCLES);
++
++ if (!cc)
++ return;
++
++ if (rx > cc)
++ return; /* should not happen */
++
++ if (sc->sc_last_chan)
++ sc->sc_last_chan->ic_idletime = 100 * (cc - rx) / cc;
++ sc->sc_last_chan = ic->ic_curchan;
++
++ OS_REG_WRITE(ah, AR5K_RXCLEAR, 0);
++ OS_REG_WRITE(ah, AR5K_CYCLES, 0);
++ OS_REG_WRITE(ah, AR5K_TXFC, 0);
++ OS_REG_WRITE(ah, AR5K_RXFC, 0);
++ OS_REG_WRITE(ah, AR5K_MIBC, 0);
++}
++#undef AR5K_RXCLEAR
++#undef AR5K_CYCLES
+
+ /*
+ * Reset the hardware w/o losing operational state. This is
+@@ -2941,6 +2985,7 @@ ath_reset(struct net_device *dev)
+ * Convert to a HAL channel description with the flags
+ * constrained to reflect the current operating mode.
+ */
++ ath_fetch_idle_time(sc);
+ c = ic->ic_curchan;
+ sc->sc_curchan.channel = c->ic_freq;
+ sc->sc_curchan.channelFlags = ath_chan2flags(c);
+@@ -9023,6 +9068,7 @@ ath_chan_set(struct ath_softc *sc, struc
+ u_int8_t channel_change_required = 0;
+ struct timeval tv;
+
++
+ /*
+ * Convert to a HAL channel description with
+ * the flags constrained to reflect the current
+@@ -9031,6 +9077,14 @@ ath_chan_set(struct ath_softc *sc, struc
+ memset(&hchan, 0, sizeof(HAL_CHANNEL));
+ hchan.channel = chan->ic_freq;
+ hchan.channelFlags = ath_chan2flags(chan);
++
++ /* don't do duplicate channel changes, but do
++ * store the available idle time */
++ ath_fetch_idle_time(sc);
++ if ((sc->sc_curchan.channel == hchan.channel) &&
++ (sc->sc_curchan.channelFlags == hchan.channelFlags))
++ return 0;
++
+ KASSERT(hchan.channel != 0,
+ ("bogus channel %u/0x%x", hchan.channel, hchan.channelFlags));
+ do_gettimeofday(&tv);
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -774,6 +774,7 @@ struct ath_softc {
+ struct ieee80211vap **sc_bslot; /* beacon xmit slots */
+ int sc_bnext; /* next slot for beacon xmit */
+
++ struct ieee80211_channel *sc_last_chan;
+ 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 */
+--- a/net80211/_ieee80211.h
++++ b/net80211/_ieee80211.h
+@@ -148,6 +148,7 @@ struct ieee80211_channel {
+ int8_t ic_maxpower; /* maximum tx power in dBm */
+ int8_t ic_minpower; /* minimum tx power in dBm */
+ u_int8_t ic_scanflags;
++ u_int8_t ic_idletime; /* phy idle time in % */
+ };
+
+ #define IEEE80211_CHAN_MAX 255
+--- a/net80211/ieee80211_scan_ap.c
++++ b/net80211/ieee80211_scan_ap.c
+@@ -417,6 +417,19 @@ pc_cmp_rssi(struct ap_state *as, struct
+
+ /* This function must be invoked with locks acquired */
+ static int
++pc_cmp_idletime(struct ieee80211_channel *a,
++ struct ieee80211_channel *b)
++{
++ if (!a->ic_idletime || !b->ic_idletime)
++ return 0;
++
++ /* a is better than b (return < 0) when a has more idle time than b */
++ return b->ic_idletime - a->ic_idletime;
++}
++
++
++/* This function must be invoked with locks acquired */
++static int
+ pc_cmp_samechan(struct ieee80211com *ic, struct ieee80211_channel *a,
+ struct ieee80211_channel *b)
+ {
+@@ -451,6 +464,7 @@ pc_cmp(const void *_a, const void *_b)
+
+ EVALUATE_CRITERION(radar, a, b);
+ EVALUATE_CRITERION(keepmode, params, a, b);
++ EVALUATE_CRITERION(idletime, a, b);
+ EVALUATE_CRITERION(sc, ic, a, b);
+ /* XXX: rssi useless? pick_channel evaluates it anyway */
+ EVALUATE_CRITERION(rssi, params->ss->ss_priv, a, b);
+@@ -519,16 +533,9 @@ pick_channel(struct ieee80211_scan_state
+ #endif
+
+ best = NULL;
+- best_rssi = 0xff; /* If signal is bigger than 0xff, we'd be melting. */
+
+ for (i = 0; i < ss_last; i++) {
+ c = &chans[i];
+- benefit = best_rssi - as->as_maxrssi[c->chan->ic_ieee];
+- sta_assoc = ic->ic_sta_assoc;
+-
+- /* Don't switch... */
+- if (benefit <= 0)
+- continue;
+
+ /* Verify channel is not marked for non-occupancy */
+ if (IEEE80211_IS_CHAN_RADAR(c->chan))
+@@ -546,31 +553,8 @@ pick_channel(struct ieee80211_scan_state
+ break;
+ }
+
+- if (sta_assoc != 0) {
+- int sl = ic->ic_cn_total -
+- ic->ic_chan_nodes[c->chan->ic_ieee]; /* count */
+- if (ic->ic_sc_algorithm == IEEE80211_SC_LOOSE) {
+- int sl_max = ic->ic_sc_sldg * benefit;
+- sl = 1000 * sl / sta_assoc; /* permil */
+- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+- "%s: chan %d, dB gained: %d, "
+- "STAs lost: %d permil (max %d)\n",
+- __func__, c->chan->ic_ieee,
+- benefit, sl, sl_max);
+- if (sl > sl_max)
+- continue;
+- } else if (((ic->ic_sc_algorithm ==
+- IEEE80211_SC_TIGHT) ||
+- (ic->ic_sc_algorithm ==
+- IEEE80211_SC_STRICT)) &&
+- (sl > 0)) {
+- /* Break the loop as the subsequent chans
+- * won't be better. */
+- break;
+- }
+- }
+ best = c->chan;
+- best_rssi = as->as_maxrssi[best->ic_ieee];
++ break;
+ }
+
+ if (best != NULL) {
+@@ -599,6 +583,9 @@ ap_end(struct ieee80211_scan_state *ss,
+ ("wrong opmode %u", vap->iv_opmode));
+
+ ic = vap->iv_ic;
++
++ /* record stats for the channel that was scanned last */
++ ic->ic_set_channel(ic);
+ bestchan = pick_channel(ss, vap, flags);
+ if (bestchan == NULL) {
+ if (ss->ss_last > 0) {
+--- a/net80211/ieee80211_scan.c
++++ b/net80211/ieee80211_scan.c
+@@ -1002,20 +1002,34 @@ ieee80211_scan_add_channels(struct ieee8
+ {
+ struct ieee80211_channel *c, *cg;
+ u_int modeflags;
++ int has_non_turbo = 0;
+ 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->ic_flags & (IEEE80211_CHAN_TURBO | IEEE80211_CHAN_STURBO))
++ continue;
++
++ has_non_turbo = 1;
++ break;
++ }
++ 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 (modeflags) {
++ if ((c->ic_flags & IEEE80211_CHAN_ALLTURBO) !=
++ (modeflags & IEEE80211_CHAN_ALLTURBO))
++ continue;
++ } else if (has_non_turbo) {
++ if ((ss->ss_vap->iv_opmode == IEEE80211_M_HOSTAP) &&
++ (c->ic_flags & (IEEE80211_CHAN_TURBO | IEEE80211_CHAN_STURBO)))
++ continue;
++ }
+ if (mode == IEEE80211_MODE_AUTO) {
+ /*
+ * XXX special-case 11b/g channels so we select
diff --git a/package/madwifi/patches/390-frame_type.patch b/package/madwifi/patches/390-frame_type.patch
new file mode 100644
index 000000000..6de01102c
--- /dev/null
+++ b/package/madwifi/patches/390-frame_type.patch
@@ -0,0 +1,13 @@
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -4443,7 +4443,9 @@ ath_eth_type_trans(struct sk_buff *skb,
+ if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
+ skb->pkt_type = PACKET_OTHERHOST;
+
+- return eth->h_proto;
++ if ((ntohs(eth->h_proto) >= 1536) || (ntohs(eth->h_proto) < 38))
++ return eth->h_proto;
++ return htons(ETH_P_802_2);
+ }
+ #endif
+
diff --git a/package/madwifi/patches/391-vap_auth.patch b/package/madwifi/patches/391-vap_auth.patch
new file mode 100644
index 000000000..832f9e116
--- /dev/null
+++ b/package/madwifi/patches/391-vap_auth.patch
@@ -0,0 +1,29 @@
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -1375,7 +1375,7 @@ ieee80211_auth_open(struct ieee80211_nod
+ vap->iv_stats.is_rx_bad_auth++; /* XXX maybe a unique error? */
+ if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
+ if (ni == vap->iv_bss) {
+- ni = ieee80211_dup_bss(vap, wh->i_addr2, 0);
++ ni = ieee80211_dup_bss(vap, wh->i_addr2, 1);
+ if (ni == NULL)
+ return;
+ tmpnode = 1;
+@@ -1763,6 +1763,8 @@ ieee80211_ssid_mismatch(struct ieee80211
+ }
+
+ #define IEEE80211_VERIFY_SSID(_ni, _ssid) do { \
++ if ((_ni)->ni_esslen == 0) \
++ return; \
+ if ((_ssid)[1] != 0 && \
+ ((_ssid)[1] != (_ni)->ni_esslen || \
+ memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) { \
+@@ -1777,6 +1779,8 @@ ieee80211_ssid_mismatch(struct ieee80211
+ } while (0)
+ #else /* !IEEE80211_DEBUG */
+ #define IEEE80211_VERIFY_SSID(_ni, _ssid) do { \
++ if ((_ni)->ni_esslen == 0) \
++ return; \
+ if ((_ssid)[1] != 0 && \
+ ((_ssid)[1] != (_ni)->ni_esslen || \
+ memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) { \
diff --git a/package/madwifi/patches/392-remove_wds_nodetracking.patch b/package/madwifi/patches/392-remove_wds_nodetracking.patch
new file mode 100644
index 000000000..fb9fb6a22
--- /dev/null
+++ b/package/madwifi/patches/392-remove_wds_nodetracking.patch
@@ -0,0 +1,388 @@
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -568,36 +568,6 @@ ieee80211_input(struct ieee80211vap * va
+ }
+ }
+
+- /* XXX: Useless node mgmt API; make better */
+- if ((dir == IEEE80211_FC1_DIR_DSTODS) && !vap->iv_wdsnode &&
+- !ni_wds && !ni->ni_subif) {
+- struct ieee80211_node_table *nt = &ic->ic_sta;
+- struct ieee80211_frame_addr4 *wh4;
+-
+- if (!(vap->iv_flags_ext & IEEE80211_FEXT_WDS)) {
+- IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
+- wh, "data", "%s", "4 addr not allowed");
+- goto err;
+- }
+- wh4 = (struct ieee80211_frame_addr4 *)skb->data;
+- ni_wds = ieee80211_find_wds_node(nt, wh4->i_addr4);
+- /* Last call increments ref count if !NULL */
+- if ((ni_wds != NULL) && (ni_wds != ni)) {
+- /*
+- * node with source address (addr4) moved
+- * to another WDS capable station. remove the
+- * reference to the previous station and add
+- * reference to the new one
+- */
+- (void) ieee80211_remove_wds_addr(nt, wh4->i_addr4);
+- ieee80211_add_wds_addr(nt, ni, wh4->i_addr4, 0);
+- }
+- if (ni_wds == NULL)
+- ieee80211_add_wds_addr(nt, ni, wh4->i_addr4, 0);
+- else
+- ieee80211_unref_node(&ni_wds);
+- }
+-
+ /*
+ * Check for power save state change.
+ */
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -122,7 +122,6 @@ static void ieee80211_node_table_init(st
+ static void ieee80211_node_table_cleanup(struct ieee80211_node_table *);
+ static void ieee80211_node_table_reset(struct ieee80211_node_table *,
+ struct ieee80211vap *);
+-static void ieee80211_node_wds_ageout(unsigned long);
+
+ MALLOC_DEFINE(M_80211_NODE, "80211node", "802.11 node state");
+
+@@ -785,10 +784,6 @@ ieee80211_node_table_init(struct ieee802
+ nt->nt_name = name;
+ nt->nt_scangen = 1;
+ nt->nt_inact_init = inact;
+- init_timer(&nt->nt_wds_aging_timer);
+- nt->nt_wds_aging_timer.function = ieee80211_node_wds_ageout;
+- nt->nt_wds_aging_timer.data = (unsigned long) nt;
+- mod_timer(&nt->nt_wds_aging_timer, jiffies + HZ * WDS_AGING_TIMER_VAL);
+ }
+
+ static __inline
+@@ -1204,142 +1199,6 @@ void ieee80211_wds_addif(struct ieee8021
+ schedule_work(&ni->ni_create);
+ }
+
+-/* Add wds address to the node table */
+-int
+-#ifdef IEEE80211_DEBUG_REFCNT
+-ieee80211_add_wds_addr_debug(struct ieee80211_node_table *nt,
+- struct ieee80211_node *ni, const u_int8_t *macaddr, u_int8_t wds_static,
+- const char* func, int line)
+-#else
+-ieee80211_add_wds_addr(struct ieee80211_node_table *nt,
+- struct ieee80211_node *ni, const u_int8_t *macaddr, u_int8_t wds_static)
+-#endif
+-{
+- int hash;
+- struct ieee80211_wds_addr *wds;
+-
+- MALLOC(wds, struct ieee80211_wds_addr *, sizeof(struct ieee80211_wds_addr),
+- M_80211_WDS, M_NOWAIT | M_ZERO);
+- if (wds == NULL) {
+- /* XXX msg */
+- return 1;
+- }
+- if (wds_static)
+- wds->wds_agingcount = WDS_AGING_STATIC;
+- else
+- wds->wds_agingcount = WDS_AGING_COUNT;
+- hash = IEEE80211_NODE_HASH(macaddr);
+- IEEE80211_ADDR_COPY(wds->wds_macaddr, macaddr);
+-
+- IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
+-#ifdef IEEE80211_DEBUG_REFCNT
+- wds->wds_ni = ieee80211_ref_node_debug(ni, func, line);
+-#else
+- wds->wds_ni = ieee80211_ref_node(ni);
+-#endif
+- LIST_INSERT_HEAD(&nt->nt_wds_hash[hash], wds, wds_hash);
+- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
+- return 0;
+-}
+-#ifdef IEEE80211_DEBUG_REFCNT
+-EXPORT_SYMBOL(ieee80211_add_wds_addr_debug);
+-#else
+-EXPORT_SYMBOL(ieee80211_add_wds_addr);
+-#endif
+-
+-/* remove wds address from the wds hash table */
+-void
+-#ifdef IEEE80211_DEBUG_REFCNT
+-ieee80211_remove_wds_addr_debug(struct ieee80211_node_table *nt, const u_int8_t *macaddr,
+- const char* func, int line)
+-#else
+-ieee80211_remove_wds_addr(struct ieee80211_node_table *nt, const u_int8_t *macaddr)
+-#endif
+-{
+- int hash;
+- struct ieee80211_wds_addr *wds, *twds;
+-
+- hash = IEEE80211_NODE_HASH(macaddr);
+- IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
+- LIST_FOREACH_SAFE(wds, &nt->nt_wds_hash[hash], wds_hash, twds) {
+- if (IEEE80211_ADDR_EQ(wds->wds_macaddr, macaddr)) {
+- LIST_REMOVE(wds, wds_hash);
+-#ifdef IEEE80211_DEBUG_REFCNT
+- ieee80211_unref_node_debug(&wds->wds_ni, func, line);
+-#else
+- ieee80211_unref_node(&wds->wds_ni);
+-#endif
+- FREE(wds, M_80211_WDS);
+- break;
+- }
+- }
+- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
+-}
+-#ifdef IEEE80211_DEBUG_REFCNT
+-EXPORT_SYMBOL(ieee80211_remove_wds_addr_debug);
+-#else
+-EXPORT_SYMBOL(ieee80211_remove_wds_addr);
+-#endif
+-
+-/* Remove node references from wds table */
+-void
+-#ifdef IEEE80211_DEBUG_REFCNT
+-ieee80211_del_wds_node_debug(struct ieee80211_node_table *nt, struct ieee80211_node *ni,
+- const char* func, int line)
+-#else
+-ieee80211_del_wds_node(struct ieee80211_node_table *nt, struct ieee80211_node *ni)
+-#endif
+-{
+- int hash;
+- struct ieee80211_wds_addr *wds, *twds;
+-
+- IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
+- for (hash = 0; hash < IEEE80211_NODE_HASHSIZE; hash++) {
+- LIST_FOREACH_SAFE(wds, &nt->nt_wds_hash[hash], wds_hash, twds) {
+- if (wds->wds_ni == ni) {
+- LIST_REMOVE(wds, wds_hash);
+-#ifdef IEEE80211_DEBUG_REFCNT
+- ieee80211_unref_node_debug(&wds->wds_ni, func, line);
+-#else
+- ieee80211_unref_node(&wds->wds_ni);
+-#endif
+- FREE(wds, M_80211_WDS);
+- }
+- }
+- }
+- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
+-}
+-#ifdef IEEE80211_DEBUG_REFCNT
+-EXPORT_SYMBOL(ieee80211_del_wds_node_debug);
+-#else
+-EXPORT_SYMBOL(ieee80211_del_wds_node);
+-#endif
+-
+-static void
+-ieee80211_node_wds_ageout(unsigned long data)
+-{
+- struct ieee80211_node_table *nt = (struct ieee80211_node_table *)data;
+- int hash;
+- struct ieee80211_wds_addr *wds, *twds;
+-
+- IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
+- for (hash = 0; hash < IEEE80211_NODE_HASHSIZE; hash++) {
+- LIST_FOREACH_SAFE(wds, &nt->nt_wds_hash[hash], wds_hash, twds) {
+- if (wds->wds_agingcount != WDS_AGING_STATIC) {
+- if (!wds->wds_agingcount) {
+- LIST_REMOVE(wds, wds_hash);
+- ieee80211_unref_node(&wds->wds_ni);
+- FREE(wds, M_80211_WDS);
+- } else
+- wds->wds_agingcount--;
+- }
+- }
+- }
+- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
+- mod_timer(&nt->nt_wds_aging_timer, jiffies + HZ * WDS_AGING_TIMER_VAL);
+-}
+-
+-
+ /* Add the specified station to the station table.
+ * Allocates a new ieee80211_node* that has a reference count of one
+ * If tmp is 0, it is added to the node table and the reference is used.
+@@ -1385,34 +1244,6 @@ ieee80211_dup_bss(struct ieee80211vap *v
+ return ni;
+ }
+
+-static struct ieee80211_node *
+-#ifdef IEEE80211_DEBUG_REFCNT
+-ieee80211_find_wds_node_locked_debug(struct ieee80211_node_table *nt,
+- const u_int8_t *macaddr, const char* func, int line)
+-#else
+-ieee80211_find_wds_node_locked(struct ieee80211_node_table *nt,
+- const u_int8_t *macaddr)
+-#endif
+-{
+- struct ieee80211_wds_addr *wds;
+- int hash;
+- IEEE80211_NODE_TABLE_LOCK_ASSERT(nt);
+-
+- hash = IEEE80211_NODE_HASH(macaddr);
+- LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) {
+- if (IEEE80211_ADDR_EQ(wds->wds_macaddr, macaddr)) {
+- if (wds->wds_agingcount != WDS_AGING_STATIC)
+- wds->wds_agingcount = WDS_AGING_COUNT; /* reset the aging count */
+-#ifdef IEEE80211_DEBUG_REFCNT
+- return ieee80211_ref_node_debug(wds->wds_ni, func, line);
+-#else
+- return ieee80211_ref_node(wds->wds_ni);
+-#endif
+- }
+- }
+- return NULL;
+-}
+-
+ /* NB: A node reference is acquired here; the caller MUST release it. */
+ #ifdef IEEE80211_DEBUG_REFCNT
+ #define ieee80211_find_node_locked(nt, mac) \
+@@ -1430,7 +1261,6 @@ ieee80211_find_node_locked(struct ieee80
+ {
+ struct ieee80211_node *ni;
+ int hash;
+- struct ieee80211_wds_addr *wds;
+
+ IEEE80211_NODE_TABLE_LOCK_ASSERT(nt);
+
+@@ -1445,48 +1275,11 @@ ieee80211_find_node_locked(struct ieee80
+ return ni;
+ }
+ }
+-
+- /* Now, we look for the desired mac address in the 4 address
+- nodes. */
+- LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) {
+- if (IEEE80211_ADDR_EQ(wds->wds_macaddr, macaddr)) {
+-#ifdef IEEE80211_DEBUG_REFCNT
+- return ieee80211_ref_node_debug(wds->wds_ni, func, line);
+-#else
+- return ieee80211_ref_node(wds->wds_ni);
+-#endif
+- }
+- }
+ return NULL;
+ }
+
+ struct ieee80211_node *
+ #ifdef IEEE80211_DEBUG_REFCNT
+-ieee80211_find_wds_node_debug(struct ieee80211_node_table *nt, const u_int8_t *macaddr,
+- const char* func, int line)
+-#else
+-ieee80211_find_wds_node(struct ieee80211_node_table *nt, const u_int8_t *macaddr)
+-#endif
+-{
+- struct ieee80211_node *ni;
+-
+- IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
+-#ifdef IEEE80211_DEBUG_REFCNT
+- ni = ieee80211_find_wds_node_locked_debug(nt, macaddr, func, line);
+-#else
+- ni = ieee80211_find_wds_node_locked(nt, macaddr);
+-#endif
+- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
+- return ni;
+-}
+-#ifdef IEEE80211_DEBUG_REFCNT
+-EXPORT_SYMBOL(ieee80211_find_wds_node_debug);
+-#else
+-EXPORT_SYMBOL(ieee80211_find_wds_node);
+-#endif
+-
+-struct ieee80211_node *
+-#ifdef IEEE80211_DEBUG_REFCNT
+ ieee80211_find_node_debug(struct ieee80211_node_table *nt,
+ const u_int8_t *macaddr, const char *func, int line)
+ #else
+@@ -1838,7 +1631,6 @@ ieee80211_node_table_cleanup(struct ieee
+ ic->ic_node_cleanup(ni);
+ #endif
+ }
+- del_timer(&nt->nt_wds_aging_timer);
+ IEEE80211_SCAN_LOCK_DESTROY(nt);
+ IEEE80211_NODE_TABLE_LOCK_DESTROY(nt);
+ }
+@@ -2404,8 +2196,6 @@ ieee80211_node_leave(struct ieee80211_no
+ * so no more references are generated
+ */
+ 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_locked(nt, ni);
+ IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
+--- a/net80211/ieee80211_node.h
++++ b/net80211/ieee80211_node.h
+@@ -231,13 +231,6 @@ void ieee80211_sta_leave(struct ieee8021
+ #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.
+@@ -250,11 +243,9 @@ struct ieee80211_node_table {
+ 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
+@@ -363,47 +354,6 @@ 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 *);
diff --git a/package/madwifi/patches/393-mbss_vap_auth.patch b/package/madwifi/patches/393-mbss_vap_auth.patch
new file mode 100644
index 000000000..a2637cccb
--- /dev/null
+++ b/package/madwifi/patches/393-mbss_vap_auth.patch
@@ -0,0 +1,491 @@
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -123,6 +123,9 @@ static void ieee80211_node_table_cleanup
+ static void ieee80211_node_table_reset(struct ieee80211_node_table *,
+ struct ieee80211vap *);
+
++static struct ieee80211_node *
++lookup_rxnode(struct ieee80211com *ic, struct ieee80211vap *vap, const u_int8_t *addr);
++
+ MALLOC_DEFINE(M_80211_NODE, "80211node", "802.11 node state");
+
+ void
+@@ -697,7 +700,7 @@ ieee80211_sta_join(struct ieee80211vap *
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_node *ni;
+
+- ni = ieee80211_find_node(&ic->ic_sta, se->se_macaddr);
++ ni = lookup_rxnode(ic, vap, se->se_macaddr);
+ if (ni == NULL) {
+ ni = ieee80211_alloc_node_table(vap, se->se_macaddr);
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,
+@@ -1394,6 +1397,53 @@ ieee80211_add_neighbor(struct ieee80211v
+ return ni;
+ }
+
++struct ieee80211vap *
++ieee80211_find_rxvap(struct ieee80211com *ic, const u_int8_t *mac)
++{
++ struct ieee80211vap *vap;
++
++ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
++ if (IEEE80211_ADDR_EQ(vap->iv_myaddr, mac))
++ return vap;
++ }
++ return NULL;
++}
++EXPORT_SYMBOL(ieee80211_find_rxvap);
++
++static struct ieee80211_node *
++lookup_rxnode(struct ieee80211com *ic, struct ieee80211vap *vap,
++ const u_int8_t *addr)
++{
++ struct ieee80211_node_table *nt;
++ struct ieee80211_node *ni = NULL;
++ int use_bss = 0;
++ int hash;
++
++ nt = &ic->ic_sta;
++ IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
++ hash = IEEE80211_NODE_HASH(addr);
++ LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
++ if (IEEE80211_ADDR_EQ(ni->ni_macaddr, addr)) {
++ /* allow multiple nodes on different vaps */
++ if (vap && (ni->ni_vap != vap))
++ continue;
++
++ ieee80211_ref_node(ni);
++ goto out;
++ }
++ }
++
++ /* no match found */
++ ni = NULL;
++
++out:
++ IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
++ return ni;
++#undef IS_PSPOLL
++#undef IS_CTL
++}
++
++
+ /*
+ * Return the node for the sender of a frame; if the sender is unknown return
+ * NULL. The caller is expected to deal with this. (The frame is sent to all
+@@ -1403,10 +1453,10 @@ ieee80211_add_neighbor(struct ieee80211v
+ */
+ struct ieee80211_node *
+ #ifdef IEEE80211_DEBUG_REFCNT
+-ieee80211_find_rxnode_debug(struct ieee80211com *ic,
++ieee80211_find_rxnode_debug(struct ieee80211com *ic, struct ieee80211vap *vap,
+ const struct ieee80211_frame_min *wh, const char *func, int line)
+ #else
+-ieee80211_find_rxnode(struct ieee80211com *ic,
++ieee80211_find_rxnode(struct ieee80211com *ic, struct ieee80211vap *vap,
+ const struct ieee80211_frame_min *wh)
+ #endif
+ {
+@@ -1414,9 +1464,8 @@ ieee80211_find_rxnode(struct ieee80211co
+ ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
+ #define IS_PSPOLL(wh) \
+ ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_PS_POLL)
+- struct ieee80211_node_table *nt;
+- struct ieee80211_node *ni;
+- struct ieee80211vap *vap, *avp;
++ struct ieee80211_node *ni = NULL;
++ struct ieee80211vap *avp;
+ const u_int8_t *addr;
+
+ if (IS_CTL(wh) && !IS_PSPOLL(wh) /*&& !IS_RTS(ah)*/)
+@@ -1429,32 +1478,25 @@ ieee80211_find_rxnode(struct ieee80211co
+
+ /* XXX check ic_bss first in station mode */
+ /* XXX 4-address frames? */
+- nt = &ic->ic_sta;
+- IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
+ if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) {
+- TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
++ if (vap) { /* assume unicast if vap is set, mcast not supported for wds */
+ TAILQ_FOREACH(avp, &vap->iv_wdslinks, iv_wdsnext) {
+- if (!IEEE80211_ADDR_EQ(addr, avp->wds_mac))
++ if (!IEEE80211_ADDR_EQ(addr, avp->wds_mac) ||
++ !IEEE80211_ADDR_EQ(wh->i_addr1, avp->iv_myaddr))
+ continue;
+
+ if (avp->iv_wdsnode)
+- return ieee80211_ref_node(avp->iv_wdsnode);
+- else
+- return NULL;
++ ni = ieee80211_ref_node(avp->iv_wdsnode);
++ return ni;
+ }
++ if (!(vap->iv_flags_ext & IEEE80211_FEXT_WDS))
++ return NULL;
++ } else {
++ return NULL;
+ }
+ }
+
+-#ifdef IEEE80211_DEBUG_REFCNT
+- ni = ieee80211_find_node_locked_debug(nt, addr, func, line);
+-#else
+- ni = ieee80211_find_node_locked(nt, addr);
+-#endif
+- IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
+-
+- return ni;
+-#undef IS_PSPOLL
+-#undef IS_CTL
++ return lookup_rxnode(ic, vap, addr);
+ }
+ #ifdef IEEE80211_DEBUG_REFCNT
+ EXPORT_SYMBOL(ieee80211_find_rxnode_debug);
+@@ -1479,15 +1521,14 @@ ieee80211_find_txnode(struct ieee80211va
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_node_table *nt;
+ struct ieee80211_node *ni = NULL;
++ int hash;
+
+- IEEE80211_LOCK_IRQ(ic);
+ if (vap->iv_opmode == IEEE80211_M_WDS) {
+ if (vap->iv_wdsnode && (vap->iv_state == IEEE80211_S_RUN))
+ return ieee80211_ref_node(vap->iv_wdsnode);
+ else
+ return NULL;
+ }
+- IEEE80211_UNLOCK_IRQ(ic);
+
+ /*
+ * The destination address should be in the node table
+@@ -1505,11 +1546,22 @@ ieee80211_find_txnode(struct ieee80211va
+ /* XXX: Can't hold lock across dup_bss due to recursive locking. */
+ nt = &vap->iv_ic->ic_sta;
+ IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
++ hash = IEEE80211_NODE_HASH(mac);
++ LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
++ if (ni->ni_vap != vap)
++ continue;
++
++ if (IEEE80211_ADDR_EQ(ni->ni_macaddr, mac)) {
+ #ifdef IEEE80211_DEBUG_REFCNT
+- ni = ieee80211_find_node_locked_debug(nt, mac, func, line);
++ ieee80211_ref_node_debug(ni, func, line);
+ #else
+- ni = ieee80211_find_node_locked(nt, mac);
++ ieee80211_ref_node(ni);
+ #endif
++ goto found;
++ }
++ }
++ ni = NULL;
++found:
+ IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
+
+ if (ni == NULL) {
+@@ -1964,13 +2016,32 @@ remove_worse_nodes(void *arg, struct iee
+ }
+ }
+
++static void
++remove_duplicate_nodes(void *arg, struct ieee80211_node *ni)
++{
++ struct ieee80211_node *rni = arg;
++
++ if (ni == rni)
++ return;
++
++ if (ni->ni_vap == rni->ni_vap)
++ return;
++
++ if (!IEEE80211_ADDR_EQ(rni->ni_macaddr, ni->ni_macaddr))
++ return;
++
++ ieee80211_node_leave(ni);
++}
++
+ void
+ ieee80211_node_join(struct ieee80211_node *ni, int resp)
+ {
+ struct ieee80211com *ic = ni->ni_ic;
+ struct ieee80211vap *vap = ni->ni_vap;
++ struct ieee80211_node *tni;
+ int newassoc;
+
++ ieee80211_iterate_nodes(&ic->ic_sta, remove_duplicate_nodes, ni);
+ if (ni->ni_associd == 0) {
+ u_int16_t aid;
+
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -216,16 +216,14 @@ ieee80211_input(struct ieee80211vap * va
+
+ type = -1; /* undefined */
+
+- if (!vap)
+- goto out;
++ if (!vap || !vap->iv_bss || !vap->iv_dev || !vap->iv_ic)
++ goto discard;
+
+ ic = vap->iv_ic;
+- if (!ic)
+- goto out;
+-
+ dev = vap->iv_dev;
+- if (!dev)
+- goto out;
++
++ if ((vap->iv_dev->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
++ goto discard;
+
+ /* initialize ni as in the previous API */
+ if (ni_or_null == NULL) {
+@@ -233,9 +231,10 @@ ieee80211_input(struct ieee80211vap * va
+ * guarantee its existence during the following call, hence
+ * briefly grab our own reference. */
+ ni = ieee80211_ref_node(vap->iv_bss);
++ KASSERT(ni != NULL, ("null node"));
++ } else {
++ ni->ni_inact = ni->ni_inact_reload;
+ }
+- KASSERT(ni != NULL, ("null node"));
+- ni->ni_inact = ni->ni_inact_reload;
+
+ KASSERT(skb->len >= sizeof(struct ieee80211_frame_min),
+ ("frame length too short: %u", skb->len));
+@@ -844,10 +843,11 @@ ieee80211_input(struct ieee80211vap * va
+ err:
+ vap->iv_devstats.rx_errors++;
+ out:
+- if (skb != NULL)
+- ieee80211_dev_kfree_skb(&skb);
+ if (ni_or_null == NULL)
+ ieee80211_unref_node(&ni);
++discard:
++ if (skb != NULL)
++ ieee80211_dev_kfree_skb(&skb);
+ return type;
+ #undef HAS_SEQ
+ }
+@@ -929,16 +929,23 @@ int
+ ieee80211_input_all(struct ieee80211com *ic,
+ struct sk_buff *skb, int rssi, u_int64_t rtsf)
+ {
++ struct ieee80211_frame_min *wh = (struct ieee80211_frame_min *) skb->data;
+ struct ieee80211vap *vap;
+ int type = -1;
+
+ /* XXX locking */
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
++ struct ieee80211_node *ni = NULL;
+ struct sk_buff *skb1;
+
+ if ((vap->iv_dev->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
+ continue;
+
++ if ((vap->iv_opmode == IEEE80211_M_HOSTAP) &&
++ !IEEE80211_IS_MULTICAST(wh->i_addr1))
++ continue;
++
++ ni = ieee80211_find_rxnode(ic, vap, wh);
+ if (TAILQ_NEXT(vap, iv_next) != NULL) {
+ skb1 = skb_copy(skb, GFP_ATOMIC);
+ if (skb1 == NULL) {
+@@ -950,8 +957,12 @@ ieee80211_input_all(struct ieee80211com
+ skb1 = skb;
+ skb = NULL;
+ }
+- type = ieee80211_input(vap, NULL, skb1, rssi, rtsf);
++ type = ieee80211_input(vap, ni, skb1, rssi, rtsf);
++ if (ni)
++ ieee80211_unref_node(&ni);
+ }
++
++out:
+ if (skb != NULL) /* no vaps, reclaim skb */
+ ieee80211_dev_kfree_skb(&skb);
+ return type;
+@@ -1147,11 +1158,9 @@ ieee80211_deliver_data(struct ieee80211_
+ * sending it will not work; just let it be
+ * delivered normally.
+ */
+- struct ieee80211_node *ni1 = ieee80211_find_node(
+- &vap->iv_ic->ic_sta, eh->ether_dhost);
++ struct ieee80211_node *ni1 = ieee80211_find_txnode(vap, eh->ether_dhost);
+ if (ni1 != NULL) {
+- if (ni1->ni_vap == vap &&
+- ieee80211_node_is_authorized(ni1) &&
++ if (ieee80211_node_is_authorized(ni1) &&
+ !ni1->ni_subif &&
+ ni1 != vap->iv_bss) {
+
+@@ -3520,6 +3529,7 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ (vap->iv_opmode == IEEE80211_M_WDS)) &&
+ (scan.capinfo & IEEE80211_CAPINFO_ESS))) {
+ struct ieee80211vap *avp = NULL;
++ int do_unref = 0;
+ int found = 0;
+
+ IEEE80211_LOCK_IRQ(vap->iv_ic);
+@@ -3553,10 +3563,12 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ ni->ni_associd |= 0xc000;
+ avp->iv_wdsnode = ieee80211_ref_node(ni);
+ IEEE80211_UNLOCK_IRQ(ic);
+- } else if (vap->iv_opmode == IEEE80211_M_IBSS) {
++ } else if ((vap->iv_opmode == IEEE80211_M_IBSS) &&
++ IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid)) {
+ /* Create a new entry in the neighbor table. */
+ ni = ieee80211_add_neighbor(vap, wh, &scan);
+ }
++ do_unref = 1;
+ } else {
+ /*
+ * Copy data from beacon to neighbor table.
+@@ -3595,6 +3607,8 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ ni->ni_rssi = rssi;
+ ni->ni_rtsf = rtsf;
+ ni->ni_last_rx = jiffies;
++ if (do_unref)
++ ieee80211_unref_node(&ni);
+ }
+ }
+ break;
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -6589,9 +6589,8 @@ ath_recv_mgmt(struct ieee80211vap * vap,
+
+ sc->sc_recv_mgmt(vap, ni_or_null, skb, subtype, rssi, rtsf);
+
+-
+ /* Lookup the new node if any (this grabs a reference to it) */
+- ni = ieee80211_find_rxnode(vap->iv_ic,
++ ni = ieee80211_find_rxnode(vap->iv_ic, vap,
+ (const struct ieee80211_frame_min *)skb->data);
+ if (ni == NULL) {
+ DPRINTF(sc, ATH_DEBUG_BEACON, "Dropping; node unknown.\n");
+@@ -6746,7 +6745,9 @@ ath_rx_poll(struct net_device *dev, int
+ struct ath_desc *ds;
+ struct ath_rx_status *rs;
+ struct sk_buff *skb = NULL;
++ struct ieee80211vap *vap;
+ struct ieee80211_node *ni;
++ const struct ieee80211_frame_min *wh;
+ unsigned int len;
+ int type;
+ u_int phyerr;
+@@ -6901,12 +6902,15 @@ rx_accept:
+ skb_trim(skb, skb->len - IEEE80211_CRC_LEN);
+
+ if (mic_fail) {
++ wh = (const struct ieee80211_frame_min *) skb->data;
++
+ /* Ignore control frames which are reported with mic error */
+- if ((((struct ieee80211_frame *)skb->data)->i_fc[0] &
++ if ((wh->i_fc[0] &
+ IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
+ goto drop_micfail;
+
+- ni = ieee80211_find_rxnode(ic, (const struct ieee80211_frame_min *) skb->data);
++ vap = ieee80211_find_rxvap(ic, wh->i_addr1);
++ ni = ieee80211_find_rxnode(ic, vap, wh);
+
+ if (ni && ni->ni_table) {
+ ieee80211_check_mic(ni, skb);
+@@ -6968,11 +6972,24 @@ drop_micfail:
+ * for its use. If the sender is unknown spam the
+ * frame; it'll be dropped where it's not wanted.
+ */
+- if (rs->rs_keyix != HAL_RXKEYIX_INVALID &&
++ wh = (const struct ieee80211_frame_min *) skb->data;
++ if ((rs->rs_keyix != HAL_RXKEYIX_INVALID) &&
+ (ni = sc->sc_keyixmap[rs->rs_keyix]) != NULL) {
+ /* Fast path: node is present in the key map;
+ * grab a reference for processing the frame. */
+- ni = ieee80211_ref_node(ni);
++ ieee80211_ref_node(ni);
++ if ((ATH_GET_VAP_ID(wh->i_addr1) !=
++ ATH_GET_VAP_ID(ni->ni_vap->iv_myaddr)) ||
++ ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) ==
++ IEEE80211_FC1_DIR_DSTODS)) {
++ /* key cache node lookup is fast, but it can
++ * lead to problems in multi-bss (foreign vap
++ * node reference) or wds (wdsap node ref instead
++ * of base ap node ref).
++ * use slowpath lookup in both cases
++ */
++ goto lookup_slowpath;
++ }
+ ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi);
+ type = ieee80211_input(ni->ni_vap, ni, skb, rs->rs_rssi, bf->bf_tsf);
+ ieee80211_unref_node(&ni);
+@@ -6981,24 +6998,39 @@ drop_micfail:
+ * 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);
++
++lookup_slowpath:
++ if (IEEE80211_IS_MULTICAST(wh->i_addr1))
++ vap = NULL;
++ else
++ vap = ieee80211_find_rxvap(ic, wh->i_addr1);
++
++ if (vap)
++ ni = ieee80211_find_rxnode(ic, vap, wh);
++ else
++ ni = NULL;
++
+ if (ni != NULL) {
+ ieee80211_keyix_t keyix;
+
+ ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi);
+- type = ieee80211_input(ni->ni_vap, ni, skb, rs->rs_rssi, bf->bf_tsf);
++ type = ieee80211_input(vap, ni, skb, rs->rs_rssi, bf->bf_tsf);
+ /*
+ * If the station has a key cache slot assigned
+ * update the key->node mapping table.
+ */
+ keyix = ni->ni_ucastkey.wk_keyix;
+ if (keyix != IEEE80211_KEYIX_NONE &&
+- sc->sc_keyixmap[keyix] == NULL)
++ sc->sc_keyixmap[keyix] == NULL) {
+ sc->sc_keyixmap[keyix] = ieee80211_ref_node(ni);
++ }
+ ieee80211_unref_node(&ni);
+- } else
+- type = ieee80211_input_all(ic, skb, rs->rs_rssi, bf->bf_tsf);
++ } else {
++ if (vap)
++ type = ieee80211_input(vap, NULL, skb, rs->rs_rssi, bf->bf_tsf);
++ else
++ type = ieee80211_input_all(ic, skb, rs->rs_rssi, bf->bf_tsf);
++ }
+ }
+
+ if (sc->sc_diversity) {
+--- a/net80211/ieee80211_node.h
++++ b/net80211/ieee80211_node.h
+@@ -286,15 +286,18 @@ struct ieee80211_node *ieee80211_find_no
+ const u_int8_t *);
+ #endif /* #ifdef IEEE80211_DEBUG_REFCNT */
+
++struct ieee80211vap *
++ieee80211_find_rxvap(struct ieee80211com *ic, const u_int8_t *mac);
++
+ /* 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__)
++#define ieee80211_find_rxnode(_nt, _vap, _wh) \
++ ieee80211_find_rxnode_debug(_nt, _vap, _wh, __func__, __LINE__)
+ struct ieee80211_node *ieee80211_find_rxnode_debug(struct ieee80211com *,
+- const struct ieee80211_frame_min *, const char *, int);
++ struct ieee80211vap *, const struct ieee80211_frame_min *, const char *, int);
+ #else
+ struct ieee80211_node *ieee80211_find_rxnode(struct ieee80211com *,
+- const struct ieee80211_frame_min *);
++ struct ieee80211vap *, const struct ieee80211_frame_min *);
+ #endif /* #ifdef IEEE80211_DEBUG_REFCNT */
+
+ /* Returns a ieee80211_node* with refcount incremented, if found */
diff --git a/package/madwifi/patches/394-probereq.patch b/package/madwifi/patches/394-probereq.patch
new file mode 100644
index 000000000..706d5a5ac
--- /dev/null
+++ b/package/madwifi/patches/394-probereq.patch
@@ -0,0 +1,64 @@
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -3621,6 +3621,8 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ vap->iv_stats.is_rx_mgtdiscard++;
+ return;
+ }
++ if (vap->iv_no_probereq)
++ return;
+ if (IEEE80211_IS_MULTICAST(wh->i_addr2)) {
+ /* frame must be directed */
+ vap->iv_stats.is_rx_mgtdiscard++; /* XXX: stat */
+--- a/net80211/ieee80211_ioctl.h
++++ b/net80211/ieee80211_ioctl.h
+@@ -651,6 +651,7 @@ enum {
+ IEEE80211_PARAM_RSSI_DIS_COUNT = 81, /* counter for rssi threshold */
+ IEEE80211_PARAM_WDS_SEP = 82, /* move wds stations into separate interfaces */
+ IEEE80211_PARAM_MAXASSOC = 83, /* maximum associated stations */
++ IEEE80211_PARAM_PROBEREQ = 84, /* enable handling of probe requests */
+ };
+
+ #define SIOCG80211STATS (SIOCDEVPRIVATE+2)
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -198,6 +198,7 @@ struct ieee80211vap {
+ u_int32_t iv_debug; /* debug msg flags */
+ struct ieee80211_stats iv_stats; /* statistics */
+
++ int iv_no_probereq;
+ int iv_max_nodes;
+ int iv_monitor_nods_only; /* in monitor mode only nods traffic */
+ int iv_monitor_txf_len; /* in monitor mode, truncate tx packets */
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -2881,6 +2881,9 @@ ieee80211_ioctl_setparam(struct net_devi
+ else
+ vap->iv_max_nodes = value;
+ break;
++ case IEEE80211_PARAM_PROBEREQ:
++ vap->iv_no_probereq = !value;
++ break;
+ #ifdef ATH_REVERSE_ENGINEERING
+ case IEEE80211_PARAM_DUMPREGS:
+ ieee80211_dump_registers(dev, info, w, extra);
+@@ -3243,6 +3246,9 @@ ieee80211_ioctl_getparam(struct net_devi
+ case IEEE80211_PARAM_MAXASSOC:
+ param[0] = vap->iv_max_nodes;
+ break;
++ case IEEE80211_PARAM_PROBEREQ:
++ param[0] = !vap->iv_no_probereq;
++ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+@@ -5802,6 +5808,10 @@ static const struct iw_priv_args ieee802
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "maxassoc"},
+ { IEEE80211_PARAM_MAXASSOC,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_maxassoc"},
++ { IEEE80211_PARAM_PROBEREQ,
++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "probereq"},
++ { IEEE80211_PARAM_PROBEREQ,
++ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_probereq"},
+
+ #ifdef ATH_REVERSE_ENGINEERING
+ /*
diff --git a/package/madwifi/patches/395-ath_ff_unmap.patch b/package/madwifi/patches/395-ath_ff_unmap.patch
new file mode 100644
index 000000000..85ddc7bd9
--- /dev/null
+++ b/package/madwifi/patches/395-ath_ff_unmap.patch
@@ -0,0 +1,11 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -13534,7 +13534,7 @@ cleanup_ath_buf(struct ath_softc *sc, st
+ bus_unmap_single(
+ sc->sc_bdev,
+ bf->bf_skbaddrff[i],
+- (direction == BUS_DMA_TODEVICE ?
++ (direction == BUS_DMA_FROMDEVICE ?
+ sc->sc_rxbufsize : ffskb->len),
+ direction);
+ bf->bf_skbaddrff[i] = 0;
diff --git a/package/madwifi/patches/396-napi_ff_fix.patch b/package/madwifi/patches/396-napi_ff_fix.patch
new file mode 100644
index 000000000..ca35d4cca
--- /dev/null
+++ b/package/madwifi/patches/396-napi_ff_fix.patch
@@ -0,0 +1,65 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -6734,10 +6734,10 @@ ath_rx_poll(struct net_device *dev, int
+ #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;
++ int rx_limit = budget;
+ #else
+ struct ath_softc *sc = dev->priv;
+- u_int rx_limit = min(dev->quota, *budget);
++ int rx_limit = min(dev->quota, *budget);
+ #endif
+ struct ath_buf *bf;
+ struct ieee80211com *ic = &sc->sc_ic;
+@@ -6780,13 +6780,15 @@ process_rx_again:
+ break;
+ }
+
+- if (rx_limit-- < 2) {
++ processed += ic->ic_recv;
++ rx_limit -= ic->ic_recv;
++ ic->ic_recv = 0;
++
++ /* keep a reserve for napi */
++ if (rx_limit < 4) {
+ early_stop = 1;
+ break;
+ }
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+- processed++;
+-#endif
+
+ skb = bf->bf_skb;
+ if (skb == NULL) {
+@@ -7074,8 +7076,8 @@ rx_next:
+ if (sc->sc_isr & HAL_INT_RX) {
+ u_int64_t hw_tsf = ath_hal_gettsf64(ah);
+ sc->sc_isr &= ~HAL_INT_RX;
+- local_irq_restore(flags);
+ ath_uapsd_processtriggers(sc, hw_tsf);
++ local_irq_restore(flags);
+ goto process_rx_again;
+ }
+ local_irq_restore(flags);
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -1206,6 +1206,7 @@ ieee80211_deliver_data(struct ieee80211_
+ }
+ }
+
++ vap->iv_ic->ic_recv++;
+ if (skb != NULL) {
+ skb->dev = dev;
+
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -323,6 +323,7 @@ struct ieee80211com {
+ struct ifmedia ic_media; /* interface media config */
+ u_int8_t ic_myaddr[IEEE80211_ADDR_LEN];
+ struct timer_list ic_inact; /* mgmt/inactivity timer */
++ u_int ic_recv; /* frame received counter */
+
+ unsigned int ic_subifs;
+ u_int32_t ic_flags; /* state flags */
diff --git a/package/madwifi/patches/400-new_hal.patch b/package/madwifi/patches/400-new_hal.patch
new file mode 100644
index 000000000..12a59687b
--- /dev/null
+++ b/package/madwifi/patches/400-new_hal.patch
@@ -0,0 +1,153 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -606,6 +606,14 @@ ath_attach(u_int16_t devid, struct net_d
+ }
+ sc->sc_ah = ah;
+
++ /* WAR for AR7100 PCI bug */
++#if defined(CONFIG_ATHEROS_AR71XX) || defined(CONFIG_ATH79)
++ if ((ar_device(sc->devid) >= 5210) && (ar_device(sc->devid) < 5416)) {
++ ath_hal_setcapability(ah, HAL_CAP_DMABURST_RX, 0, HAL_DMABURST_4B, NULL);
++ ath_hal_setcapability(ah, HAL_CAP_DMABURST_TX, 0, HAL_DMABURST_4B, NULL);
++ }
++#endif
++
+ /*
+ * Check if the MAC has multi-rate retry support.
+ * We do this by trying to setup a fake extended
+@@ -7568,7 +7576,7 @@ ath_txq_setup(struct ath_softc *sc, int
+ if (qtype == HAL_TX_QUEUE_UAPSD)
+ qi.tqi_qflags = HAL_TXQ_TXDESCINT_ENABLE;
+ else
+- qi.tqi_qflags = HAL_TXQ_TXEOLINT_ENABLE |
++ qi.tqi_qflags = HAL_TXQ_TXEOLINT_ENABLE | HAL_TXQ_TXOKINT_ENABLE |
+ HAL_TXQ_TXDESCINT_ENABLE;
+ qnum = ath_hal_setuptxqueue(ah, qtype, &qi);
+ if (qnum == -1) {
+--- a/ath_hal/ah_os.c
++++ b/ath_hal/ah_os.c
+@@ -126,6 +126,13 @@ ath_hal_printf(struct ath_hal *ah, const
+ }
+ EXPORT_SYMBOL(ath_hal_printf);
+
++void __ahdecl
++ath_hal_printstr(struct ath_hal *ah, const char *str)
++{
++ printk("%s", str);
++}
++EXPORT_SYMBOL(ath_hal_printstr);
++
+ /*
+ * Format an Ethernet MAC for printing.
+ */
+--- a/ath_hal/ah_os.h
++++ b/ath_hal/ah_os.h
+@@ -156,69 +156,23 @@ extern u_int32_t __ahdecl ath_hal_getupt
+ #endif
+ #endif /* AH_BYTE_ORDER */
+
+-/*
+- * Some big-endian architectures don't set CONFIG_GENERIC_IOMAP, but fail to
+- * implement iowrite32be and ioread32be. Provide compatibility macros when
+- * it's needed.
+- *
+- * As of Linux 2.6.24, only MIPS, PARISC and PowerPC implement iowrite32be and
+- * ioread32be as functions.
+- *
+- * The downside or the replacement macros it that we may be byte-swapping data
+- * for the second time, so the native implementations should be preferred.
+- */
+-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)) && \
+- !defined(CONFIG_GENERIC_IOMAP) && (AH_BYTE_ORDER == AH_BIG_ENDIAN) && \
+- !defined(__mips__) && !defined(__hppa__) && !defined(__powerpc__)
+-# ifndef iowrite32be
+-# define iowrite32be(_val, _addr) iowrite32(swab32((_val)), (_addr))
+-# endif
+-# ifndef ioread32be
+-# define ioread32be(_addr) swab32(ioread32((_addr)))
+-# endif
+-#endif
++#define IS_SWAPPED(_ah, _reg) \
++ ((_ah)->ah_swapped && \
++ (((0x4000 <= (_reg)) && ((_reg) < 0x5000)) || \
++ ((0x7000 <= (_reg)) && ((_reg) < 0x8000))))
++
++#define SWAPREG(_ah, _reg, _val) \
++ (IS_SWAPPED(_ah, _reg) ? cpu_to_le32(_val) : (_val))
+
+ /*
+ * The register accesses are done using target-specific functions when
+ * debugging is enabled (AH_DEBUG) or it's explicitly requested for the target.
+- *
+- * The hardware registers use little-endian byte order natively. Big-endian
+- * systems are configured by HAL to enable hardware byte-swap of register reads
+- * and writes at reset. This avoid the need to byte-swap the data in software.
+- * However, the registers in a certain area from 0x4000 to 0x4fff (PCI clock
+- * domain registers) are not byte swapped!
+- *
+- * Since Linux I/O primitives default to little-endian operations, we only
+- * need to suppress byte-swapping on big-endian systems outside the area used
+- * by the PCI clock domain registers.
+ */
+-#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) ? \
+- iowrite32((_val), (_ah)->ah_sh + (_reg)) : \
+- iowrite32be((_val), (_ah)->ah_sh + (_reg)); \
+- } while (0)
+-#define _OS_REG_READ(_ah, _reg) \
+- (is_reg_le(_reg) ? \
+- ioread32((_ah)->ah_sh + (_reg)) : \
+- ioread32be((_ah)->ah_sh + (_reg)))
+-#else
+ #define _OS_REG_WRITE(_ah, _reg, _val) do { \
+- writel(is_reg_le(_reg) ? \
+- (_val) : cpu_to_le32(_val), \
+- (_ah)->ah_sh + (_reg)); \
+- } while (0)
++ __raw_writel(SWAPREG(_ah, _reg, _val), (_ah)->ah_sh + (_reg)); \
++} while (0)
+ #define _OS_REG_READ(_ah, _reg) \
+- (is_reg_le(_reg) ? \
+- readl((_ah)->ah_sh + (_reg)) : \
+- cpu_to_le32(readl((_ah)->ah_sh + (_reg))))
+-#endif /* KERNEL_VERSION(2,6,12) */
++ SWAPREG(_ah, _reg, __raw_readl((_ah)->ah_sh + (_reg)))
+
+ /*
+ * The functions in this section are not intended to be invoked by MadWifi
+--- a/ath/if_ath_hal.h
++++ b/ath/if_ath_hal.h
+@@ -778,17 +778,6 @@ static inline HAL_STATUS ath_hal_getcapa
+ return ret;
+ }
+
+-static inline HAL_BOOL ath_hal_radar_wait(struct ath_hal *ah, HAL_CHANNEL *a1)
+-{
+- HAL_BOOL ret;
+- ATH_HAL_LOCK_IRQ(ah->ah_sc);
+- ath_hal_set_function(__func__);
+- ret = ah->ah_radarWait(ah, a1);
+- ath_hal_set_function(NULL);
+- ATH_HAL_UNLOCK_IRQ(ah->ah_sc);
+- return ret;
+-}
+-
+ static inline HAL_BOOL ath_hal_setmcastfilterindex(struct ath_hal *ah,
+ u_int32_t index)
+ {
+@@ -1268,8 +1257,6 @@ static inline void ath_hal_dump_map(stru
+ /* HAL_STATUS ah_getCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE a1, u_int32_t capability, u_int32_t *result) */
+ __print_symbol("%s=ah_getCapability\n",
+ (unsigned long)ah->ah_getCapability);
+- /* HAL_BOOL ah_radarWait(struct ath_hal *ah, HAL_CHANNEL *a1) */
+- __print_symbol("%s=ah_radarWait\n", (unsigned long)ah->ah_radarWait);
+ /* HAL_BOOL ah_setMulticastFilterIndex(struct ath_hal *ah, u_int32_t index) */
+ __print_symbol("%s=ah_setMulticastFilterIndex\n",
+ (unsigned long)ah->ah_setMulticastFilterIndex);
diff --git a/package/madwifi/patches/401-changeset_r3602.patch b/package/madwifi/patches/401-changeset_r3602.patch
new file mode 100644
index 000000000..cf9c87966
--- /dev/null
+++ b/package/madwifi/patches/401-changeset_r3602.patch
@@ -0,0 +1,11 @@
+--- a/net80211/ieee80211_linux.h
++++ b/net80211/ieee80211_linux.h
+@@ -348,6 +348,8 @@ typedef spinlock_t acl_lock_t;
+ /* __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 --git a/package/madwifi/patches/402-changeset_r3603.patch b/package/madwifi/patches/402-changeset_r3603.patch
new file mode 100644
index 000000000..92f6e6ea4
--- /dev/null
+++ b/package/madwifi/patches/402-changeset_r3603.patch
@@ -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 --git a/package/madwifi/patches/403-changeset_r3605.patch b/package/madwifi/patches/403-changeset_r3605.patch
new file mode 100644
index 000000000..57ce521c1
--- /dev/null
+++ b/package/madwifi/patches/403-changeset_r3605.patch
@@ -0,0 +1,70 @@
+--- a/include/compat.h
++++ b/include/compat.h
+@@ -182,6 +182,13 @@ static inline int timeval_compare(struct
+ #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
+@@ -345,13 +345,6 @@ typedef spinlock_t acl_lock_t;
+ #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.
+@@ -395,16 +388,16 @@ typedef spinlock_t acl_lock_t;
+ _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 @@ ieee80211_pwrsave(struct sk_buff *skb)
+ 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 --git a/package/madwifi/patches/404-linux24_fix.patch b/package/madwifi/patches/404-linux24_fix.patch
new file mode 100644
index 000000000..4ea20b3cb
--- /dev/null
+++ b/package/madwifi/patches/404-linux24_fix.patch
@@ -0,0 +1,15 @@
+--- a/ath_hal/Makefile
++++ b/ath_hal/Makefile
+@@ -78,10 +78,11 @@ endif
+ 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 --git a/package/madwifi/patches/405-retransmit_check.patch b/package/madwifi/patches/405-retransmit_check.patch
new file mode 100644
index 000000000..11e78aba8
--- /dev/null
+++ b/package/madwifi/patches/405-retransmit_check.patch
@@ -0,0 +1,22 @@
+--- a/net80211/ieee80211.h
++++ b/net80211/ieee80211.h
+@@ -174,8 +174,6 @@ struct ieee80211_ctlframe_addr2 {
+ #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
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -428,7 +428,7 @@ ieee80211_input(struct ieee80211vap * va
+ tid = 0;
+ rxseq = le16toh(*(__le16 *)wh->i_seq);
+ if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
+- IEEE80211_SEQ_LEQ(rxseq, ni->ni_rxseqs[tid])) {
++ (rxseq == ni->ni_rxseqs[tid])) {
+ /* duplicate, discard */
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
+ bssid, "duplicate",
diff --git a/package/madwifi/patches/406-monitor_r3711.patch b/package/madwifi/patches/406-monitor_r3711.patch
new file mode 100644
index 000000000..4e2c6aefb
--- /dev/null
+++ b/package/madwifi/patches/406-monitor_r3711.patch
@@ -0,0 +1,20 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -6530,7 +6530,7 @@ ath_capture(struct net_device *dev, cons
+
+ /* Never copy the SKB, as it is ours on the RX side, and this is the
+ * last process on the TX side and we only modify our own headers. */
+- tskb = ath_skb_removepad(skb, 0 /* Copy SKB */);
++ tskb = ath_skb_removepad(skb, !tx /* Copy SKB */);
+ if (tskb == NULL) {
+ DPRINTF(sc, ATH_DEBUG_ANY,
+ "Dropping; ath_skb_removepad failed!\n");
+@@ -6538,6 +6538,8 @@ ath_capture(struct net_device *dev, cons
+ }
+
+ ieee80211_input_monitor(ic, tskb, bf, tx, tsf, sc);
++ if (tskb != skb)
++ ieee80211_dev_kfree_skb(&tskb);
+ }
+
+ /*
diff --git a/package/madwifi/patches/407-new_athinfo.patch b/package/madwifi/patches/407-new_athinfo.patch
new file mode 100644
index 000000000..6c512ad9e
--- /dev/null
+++ b/package/madwifi/patches/407-new_athinfo.patch
@@ -0,0 +1,2352 @@
+--- a/tools/ath_info.c
++++ b/tools/ath_info.c
+@@ -16,78 +16,8 @@
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+-/* So here is how it works:
+- *
+- * First compile...
+- *
+- * gcc ath_info.c -o ath_info
+- *
+- * then find card's physical address
+- *
+- * lspci -v
+- *
+- * 02:02.0 Ethernet controller: Atheros Communications, Inc. AR5212 802.11abg NIC (rev 01)
+- * Subsystem: Fujitsu Limited. Unknown device 1234
+- * Flags: bus master, medium devsel, latency 168, IRQ 23
+- * Memory at c2000000 (32-bit, non-prefetchable) [size=64K]
+- * Capabilities: [44] Power Management version 2
+- *
+- * address here is 0xc2000000
+- *
+- * load madwifi-ng or madwifi-old if not already loaded (be sure the
+- * interface is down!)
+- *
+- * modprobe ath_pci
+- *
+- * OR
+- *
+- * call:
+- * setpci -s 02:02.0 command=0x41f cache_line_size=0x10
+- *
+- * to enable access to the PCI device.
+- *
+- * and we run the thing...
+- *
+- * ./ath_info 0xc2000000
+- *
+- * In order to change the regdomain to 0, call:
+- *
+- * ./ath_info -w 0xc2000000 regdomain 0
+- *
+- * to change any PCI ID value, say:
+- *
+- * ./ath_info -w 0xc2000000 <name> X
+- *
+- * with <name> ::= pci_dev_id | pci_vendor_id | pci_class |
+- * pci_subsys_dev_id | pci_subsys_vendor_id
+- *
+- * With newer chipsets (>= AR5004x, i.e. MAC >= AR5213), Atheros introduced
+- * write protection on the EEPROM. On a GIGABYTE GN-WI01HT you can set GPIO 4
+- * to low to be able to write the EEPROM. This depends highly on the PCB layout,
+- * so there may be different GPIO used.
+- * This program currently sets GPIO 4 to low for a MAC >= AR5213, but you can
+- * override this with the -g option:
+- *
+- * ./ath_info -g 5:0 -w 0xc2000000 regdomain X
+- *
+- * would set GPIO 5 to low (and wouldn't touch GPIO 4). -g can be given several times.
+- *
+- * The write function is currently not tested with 5210 devices.
+- *
+- * Use at your own risk, entering a false device address will have really
+- * nasty results!
+- *
+- * Writing wrong values to the PCI id fields may prevent the driver from
+- * detecting the card!
+- *
+- * Transmitting on illegal frequencies may violate state laws. Stick to the local
+- * regulations!
+- *
+- * DISCLAIMER:
+- * The authors are in no case responsible for damaged hardware or violation of
+- * local laws by operating modified hardware.
+- *
+- */
++/* Try accepting 64-bit device address even with 32-bit userspace */
++#define _FILE_OFFSET_BITS 64
+
+ #include <stdio.h>
+ #include <stdlib.h>
+@@ -130,109 +60,103 @@ fprintf(stderr, "#ERR %s: " fmt "\n", __
+ */
+ #define AR5K_GPIODI 0x401c
+
+-/*
+- * Common silicon revision/version values
+- */
+-enum ath5k_srev_type {
+- AR5K_VERSION_VER,
+- AR5K_VERSION_REV,
+- AR5K_VERSION_RAD,
+-};
+-
+ struct ath5k_srev_name {
+ const char *sr_name;
+- enum ath5k_srev_type sr_type;
+- u_int sr_val;
++ u_int8_t sr_val;
+ };
+
+-#define AR5K_SREV_UNKNOWN 0xffff
+-
+ /* Known MAC revision numbers */
+-#define AR5K_SREV_VER_AR5210 0x00
+-#define AR5K_SREV_VER_AR5311 0x10
+-#define AR5K_SREV_VER_AR5311A 0x20
+-#define AR5K_SREV_VER_AR5311B 0x30
+-#define AR5K_SREV_VER_AR5211 0x40
+-#define AR5K_SREV_VER_AR5212 0x50
+-#define AR5K_SREV_VER_AR5213 0x55
+-#define AR5K_SREV_VER_AR5213A 0x59
+-#define AR5K_SREV_VER_AR2424 0xa0
+-#define AR5K_SREV_VER_AR5424 0xa3
+-#define AR5K_SREV_VER_AR5413 0xa4
+-#define AR5K_SREV_VER_AR5414 0xa5
+-#define AR5K_SREV_VER_AR5416 0xc0
+-#define AR5K_SREV_VER_AR5418 0xca
+-#define AR5K_SREV_VER_AR2425 0xe0
+-
+-/* Known PHY revision nymbers */
+-#define AR5K_SREV_RAD_5110 0x00
+-#define AR5K_SREV_RAD_5111 0x10
+-#define AR5K_SREV_RAD_5111A 0x15
+-#define AR5K_SREV_RAD_2111 0x20
+-#define AR5K_SREV_RAD_5112 0x30
+-#define AR5K_SREV_RAD_5112A 0x35
+-#define AR5K_SREV_RAD_2112 0x40
+-#define AR5K_SREV_RAD_2112A 0x45
+-#define AR5K_SREV_RAD_SC1 0x63 /* Found on 5413/5414 */
+-#define AR5K_SREV_RAD_SC2 0xa2 /* Found on 2424/5424 */
+-#define AR5K_SREV_RAD_5133 0xc0 /* MIMO found on 5418 */
+-
+-static const struct ath5k_srev_name ath5k_srev_names[] = {
+- {"5210", AR5K_VERSION_VER, AR5K_SREV_VER_AR5210},
+- {"5311", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311},
+- {"5311A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311A},
+- {"5311B", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311B},
+- {"5211", AR5K_VERSION_VER, AR5K_SREV_VER_AR5211},
+- {"5212", AR5K_VERSION_VER, AR5K_SREV_VER_AR5212},
+- {"5213", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213},
+- {"5213A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213A},
+- {"2424", AR5K_VERSION_VER, AR5K_SREV_VER_AR2424},
+- {"5424", AR5K_VERSION_VER, AR5K_SREV_VER_AR5424},
+- {"5413", AR5K_VERSION_VER, AR5K_SREV_VER_AR5413},
+- {"5414", AR5K_VERSION_VER, AR5K_SREV_VER_AR5414},
+- {"5416", AR5K_VERSION_VER, AR5K_SREV_VER_AR5416},
+- {"5418", AR5K_VERSION_VER, AR5K_SREV_VER_AR5418},
+- {"2425", AR5K_VERSION_VER, AR5K_SREV_VER_AR2425},
+- {"xxxxx", AR5K_VERSION_VER, AR5K_SREV_UNKNOWN},
+- {"5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110},
+- {"5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111},
+- {"2111", AR5K_VERSION_RAD, AR5K_SREV_RAD_2111},
+- {"5112", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112},
+- {"5112a", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A},
+- {"2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112},
+- {"2112a", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A},
+- {"SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC1},
+- {"SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC2},
+- {"5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133},
+- {"xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN},
++#define AR5K_SREV_MAC_AR5210 0x00
++#define AR5K_SREV_MAC_AR5311 0x10
++#define AR5K_SREV_MAC_AR5311A 0x20
++#define AR5K_SREV_MAC_AR5311B 0x30
++#define AR5K_SREV_MAC_AR5211 0x40
++#define AR5K_SREV_MAC_AR5212 0x50
++#define AR5K_SREV_MAC_AR5213 0x55
++#define AR5K_SREV_MAC_AR5213A 0x59
++#define AR5K_SREV_MAC_AR5513 0x61
++#define AR5K_SREV_MAC_AR2413 0x78
++#define AR5K_SREV_MAC_AR2414 0x79
++#define AR5K_SREV_MAC_AR2424 0xa0
++#define AR5K_SREV_MAC_AR5424 0xa3
++#define AR5K_SREV_MAC_AR5413 0xa4
++#define AR5K_SREV_MAC_AR5414 0xa5
++#define AR5K_SREV_MAC_AR5416 0xc0
++#define AR5K_SREV_MAC_AR5418 0xca
++#define AR5K_SREV_MAC_AR2425 0xe2
++
++/* Known PHY revision numbers */
++#define AR5K_SREV_PHY_5110 0x00
++#define AR5K_SREV_PHY_5111 0x10
++#define AR5K_SREV_PHY_5111A 0x15
++#define AR5K_SREV_PHY_2111 0x20
++#define AR5K_SREV_PHY_5112 0x30
++#define AR5K_SREV_PHY_5112A 0x35
++#define AR5K_SREV_PHY_2112 0x40
++#define AR5K_SREV_PHY_2112A 0x45
++#define AR5K_SREV_PHY_SC0 0x56 /* Found on 2413/2414 */
++#define AR5K_SREV_PHY_SC1 0x63 /* Found on 5413/5414 */
++#define AR5K_SREV_PHY_SC2 0xa2 /* Found on 2424/5424 */
++#define AR5K_SREV_PHY_5133 0xc0 /* MIMO found on 5418 */
++
++static const struct ath5k_srev_name ath5k_mac_names[] = {
++ {"5210", AR5K_SREV_MAC_AR5210},
++ {"5311", AR5K_SREV_MAC_AR5311},
++ {"5311A", AR5K_SREV_MAC_AR5311A},
++ {"5311B", AR5K_SREV_MAC_AR5311B},
++ {"5211", AR5K_SREV_MAC_AR5211},
++ {"5212", AR5K_SREV_MAC_AR5212},
++ {"5213", AR5K_SREV_MAC_AR5213},
++ {"5213A", AR5K_SREV_MAC_AR5213A},
++ {"2413", AR5K_SREV_MAC_AR2413},
++ {"2414", AR5K_SREV_MAC_AR2414},
++ {"2424", AR5K_SREV_MAC_AR2424},
++ {"5424", AR5K_SREV_MAC_AR5424},
++ {"5413", AR5K_SREV_MAC_AR5413},
++ {"5414", AR5K_SREV_MAC_AR5414},
++ {"5416", AR5K_SREV_MAC_AR5416},
++ {"5418", AR5K_SREV_MAC_AR5418},
++ {"2425", AR5K_SREV_MAC_AR2425},
++};
++
++static const struct ath5k_srev_name ath5k_phy_names[] = {
++ {"5110", AR5K_SREV_PHY_5110},
++ {"5111", AR5K_SREV_PHY_5111},
++ {"2111", AR5K_SREV_PHY_2111},
++ {"5112", AR5K_SREV_PHY_5112},
++ {"5112A", AR5K_SREV_PHY_5112A},
++ {"2112", AR5K_SREV_PHY_2112},
++ {"2112A", AR5K_SREV_PHY_2112A},
++ {"SChip", AR5K_SREV_PHY_SC0},
++ {"SChip", AR5K_SREV_PHY_SC1},
++ {"SChip", AR5K_SREV_PHY_SC2},
++ {"5133", AR5K_SREV_PHY_5133},
+ };
+
+ /*
+ * Silicon revision register
+ */
+ #define AR5K_SREV 0x4020 /* Register Address */
+-#define AR5K_SREV_REV 0x0000000f /* Mask for revision */
+-#define AR5K_SREV_REV_S 0
+-#define AR5K_SREV_VER 0x000000ff /* Mask for version */
+-#define AR5K_SREV_VER_S 4
++#define AR5K_SREV_VER 0x000000f0 /* Mask for version */
++#define AR5K_SREV_REV 0x000000ff /* Mask for revision */
+
+ /*
+ * PHY chip revision register
+ */
+-#define AR5K_PHY_CHIP_ID 0x9818
++#define AR5K_PHY_CHIP_ID 0x9818
+
+ /*
+ * PHY register
+ */
+-#define AR5K_PHY_BASE 0x9800
+-#define AR5K_PHY(_n) (AR5K_PHY_BASE + ((_n) << 2))
++#define AR5K_PHY_BASE 0x9800
++#define AR5K_PHY(_n) (AR5K_PHY_BASE + ((_n) << 2))
+ #define AR5K_PHY_SHIFT_2GHZ 0x00004007
+ #define AR5K_PHY_SHIFT_5GHZ 0x00000007
+
+ #define AR5K_RESET_CTL 0x4000 /* Register Address */
+ #define AR5K_RESET_CTL_PCU 0x00000001 /* Protocol Control Unit reset */
+ #define AR5K_RESET_CTL_DMA 0x00000002 /* DMA (Rx/Tx) reset -5210 only */
+-#define AR5K_RESET_CTL_BASEBAND 0x00000002 /* Baseband reset (5211/5212) */
++#define AR5K_RESET_CTL_BASEBAND 0x00000002 /* Baseband reset (5211/5212) */
+ #define AR5K_RESET_CTL_MAC 0x00000004 /* MAC reset (PCU+Baseband?) -5210 only */
+ #define AR5K_RESET_CTL_PHY 0x00000008 /* PHY reset -5210 only */
+ #define AR5K_RESET_CTL_PCI 0x00000010 /* PCI Core reset (interrupts etc) */
+@@ -253,7 +177,7 @@ static const struct ath5k_srev_name ath5
+ #define AR5K_SLEEP_CTL_SLE_UNITS 0x00000008 /* not on 5210 */
+
+ #define AR5K_PCICFG 0x4010 /* Register Address */
+-#define AR5K_PCICFG_EEAE 0x00000001 /* Eeprom access enable [5210] */
++#define AR5K_PCICFG_EEAE 0x00000001 /* EEPROM access enable [5210] */
+ #define AR5K_PCICFG_CLKRUNEN 0x00000004 /* CLKRUN enable [5211+] */
+ #define AR5K_PCICFG_EESIZE 0x00000018 /* Mask for EEPROM size [5211+] */
+ #define AR5K_PCICFG_EESIZE_S 3
+@@ -264,26 +188,118 @@ static const struct ath5k_srev_name ath5
+
+ #define AR5K_PCICFG_SPWR_DN 0x00010000 /* Mask for power status (5210) */
+
+-#define AR5K_EEPROM_BASE 0x6000
++#define AR5K_EEPROM_BASE 0x6000
+
+-#define AR5K_EEPROM_MAGIC 0x003d /* Offset for EEPROM Magic number */
++/*
++ * Common AR5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE)
++ */
++#define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */
+ #define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */
+ #define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */
+ #define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */
+ #define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */
+
++#define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */
++#define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */
++#define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */
++#define AR5K_EEPROM_PROTECT_RD_32_63 0x0004 /* 0x20 - 0x3f */
++#define AR5K_EEPROM_PROTECT_WR_32_63 0x0008
++#define AR5K_EEPROM_PROTECT_RD_64_127 0x0010 /* 0x40 - 0x7f */
++#define AR5K_EEPROM_PROTECT_WR_64_127 0x0020
++#define AR5K_EEPROM_PROTECT_RD_128_191 0x0040 /* 0x80 - 0xbf (regdom) */
++#define AR5K_EEPROM_PROTECT_WR_128_191 0x0080
++#define AR5K_EEPROM_PROTECT_RD_192_207 0x0100 /* 0xc0 - 0xcf */
++#define AR5K_EEPROM_PROTECT_WR_192_207 0x0200
++#define AR5K_EEPROM_PROTECT_RD_208_223 0x0400 /* 0xd0 - 0xdf */
++#define AR5K_EEPROM_PROTECT_WR_208_223 0x0800
++#define AR5K_EEPROM_PROTECT_RD_224_239 0x1000 /* 0xe0 - 0xef */
++#define AR5K_EEPROM_PROTECT_WR_224_239 0x2000
++#define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */
++#define AR5K_EEPROM_PROTECT_WR_240_255 0x8000
++#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */
++#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
++#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE)
++#define AR5K_EEPROM_INFO_CKSUM 0xffff
++#define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n))
++
++#define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) /* EEPROM Version */
++#define AR5K_EEPROM_VERSION_3_0 0x3000 /* No idea what's going on before this version */
++#define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2GHz (AR5211_rfregs) */
++#define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */
++#define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */
++#define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain ee_cck_ofdm_power_delta (eeprom_read_modes) */
++#define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc*, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */
++#define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */
++#define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */
++#define AR5K_EEPROM_VERSION_4_3 0x4003
++#define AR5K_EEPROM_VERSION_4_4 0x4004
++#define AR5K_EEPROM_VERSION_4_5 0x4005
++#define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */
++#define AR5K_EEPROM_VERSION_4_7 0x3007
++
++#define AR5K_EEPROM_MODE_11A 0
++#define AR5K_EEPROM_MODE_11B 1
++#define AR5K_EEPROM_MODE_11G 2
++
++#define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2) /* Header that contains the device caps */
++#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)
++#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)
++#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)
++#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2GHz (?) */
++#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */
++#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7)
++#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5GHz (?) */
++#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */
++
++/* Misc values available since EEPROM 4.0 */
++#define AR5K_EEPROM_MISC0 AR5K_EEPROM_INFO(4)
++#define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff)
++#define AR5K_EEPROM_HDR_XR2_DIS(_v) (((_v) >> 12) & 0x1)
++#define AR5K_EEPROM_HDR_XR5_DIS(_v) (((_v) >> 13) & 0x1)
++#define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3)
++#define AR5K_EEPROM_MISC1 AR5K_EEPROM_INFO(5)
++#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff)
++#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1)
++
++#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c
++#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2
++#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002
++#define AR5K_EEPROM_RFKILL_POLARITY_S 1
++
++/* Newer EEPROMs are using a different offset */
++#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \
++ (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0)
++
++#define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3)
++#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((int8_t)(((_v) >> 8) & 0xff))
++#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((int8_t)((_v) & 0xff))
++
++/* calibration settings */
++#define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4)
++#define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2)
++#define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d)
++#define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */
++#define AR5K_EEPROM_CHANNELS_5GHZ(_v) AR5K_EEPROM_OFF(_v, 0x0100, 0x0150) /* List of calibrated 5GHz chans */
++#define AR5K_EEPROM_TARGET_PWR_OFF_11A(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_CHANNELS_5GHZ(_v) + 0x0055, 0x0000)
++#define AR5K_EEPROM_TARGET_PWR_OFF_11B(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_CHANNELS_5GHZ(_v) + 0x0065, 0x0010)
++#define AR5K_EEPROM_TARGET_PWR_OFF_11G(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_CHANNELS_5GHZ(_v) + 0x0069, 0x0014)
++
++/* [3.1 - 3.3] */
++#define AR5K_EEPROM_OBDB0_2GHZ 0x00ec
++#define AR5K_EEPROM_OBDB1_2GHZ 0x00ed
++
+ /*
+ * EEPROM data register
+ */
+ #define AR5K_EEPROM_DATA_5211 0x6004
+ #define AR5K_EEPROM_DATA_5210 0x6800
+-#define AR5K_EEPROM_DATA (mac_version == AR5K_SREV_VER_AR5210 ? \
++#define AR5K_EEPROM_DATA (mac_version == AR5K_SREV_MAC_AR5210 ? \
+ AR5K_EEPROM_DATA_5210 : AR5K_EEPROM_DATA_5211)
+
+ /*
+ * EEPROM command register
+ */
+-#define AR5K_EEPROM_CMD 0x6008 /* Register Addres */
++#define AR5K_EEPROM_CMD 0x6008 /* Register Address */
+ #define AR5K_EEPROM_CMD_READ 0x00000001 /* EEPROM read */
+ #define AR5K_EEPROM_CMD_WRITE 0x00000002 /* EEPROM write */
+ #define AR5K_EEPROM_CMD_RESET 0x00000004 /* EEPROM reset */
+@@ -291,43 +307,163 @@ static const struct ath5k_srev_name ath5
+ /*
+ * EEPROM status register
+ */
+-#define AR5K_EEPROM_STAT_5210 0x6c00 /* Register Address [5210] */
+-#define AR5K_EEPROM_STAT_5211 0x600c /* Register Address [5211+] */
+-#define AR5K_EEPROM_STATUS (mac_version == AR5K_SREV_VER_AR5210 ? \
++#define AR5K_EEPROM_STAT_5210 0x6c00 /* Register Address [5210] */
++#define AR5K_EEPROM_STAT_5211 0x600c /* Register Address [5211+] */
++#define AR5K_EEPROM_STATUS (mac_version == AR5K_SREV_MAC_AR5210 ? \
+ AR5K_EEPROM_STAT_5210 : AR5K_EEPROM_STAT_5211)
+ #define AR5K_EEPROM_STAT_RDERR 0x00000001 /* EEPROM read failed */
+ #define AR5K_EEPROM_STAT_RDDONE 0x00000002 /* EEPROM read successful */
+ #define AR5K_EEPROM_STAT_WRERR 0x00000004 /* EEPROM write failed */
+ #define AR5K_EEPROM_STAT_WRDONE 0x00000008 /* EEPROM write successful */
+
+-#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* Offset for EEPROM regulatory domain */
+-#define AR5K_EEPROM_INFO_BASE 0x00c0 /* Offset for EEPROM header */
+-#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE)
+-#define AR5K_EEPROM_INFO_CKSUM 0xffff
+-#define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n))
+-#define AR5K_EEPROM_MODE_11A 0
+-#define AR5K_EEPROM_MODE_11B 1
+-#define AR5K_EEPROM_MODE_11G 2
++/*
++ * EEPROM config register (?)
++ */
++#define AR5K_EEPROM_CFG 0x6010
+
+-#define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1)
++/* Some EEPROM defines */
++#define AR5K_EEPROM_EEP_SCALE 100
++#define AR5K_EEPROM_EEP_DELTA 10
++#define AR5K_EEPROM_N_MODES 3
++#define AR5K_EEPROM_N_5GHZ_CHAN 10
++#define AR5K_EEPROM_N_2GHZ_CHAN 3
++#define AR5K_EEPROM_MAX_CHAN 10
++#define AR5K_EEPROM_N_PCDAC 11
++#define AR5K_EEPROM_N_TEST_FREQ 8
++#define AR5K_EEPROM_N_EDGES 8
++#define AR5K_EEPROM_N_INTERCEPTS 11
++#define AR5K_EEPROM_FREQ_M(_v) AR5K_EEPROM_OFF(_v, 0x7f, 0xff)
++#define AR5K_EEPROM_PCDAC_M 0x3f
++#define AR5K_EEPROM_PCDAC_START 1
++#define AR5K_EEPROM_PCDAC_STOP 63
++#define AR5K_EEPROM_PCDAC_STEP 1
++#define AR5K_EEPROM_NON_EDGE_M 0x40
++#define AR5K_EEPROM_CHANNEL_POWER 8
++#define AR5K_EEPROM_N_OBDB 4
++#define AR5K_EEPROM_OBDB_DIS 0xffff
++#define AR5K_EEPROM_CHANNEL_DIS 0xff
++#define AR5K_EEPROM_SCALE_OC_DELTA(_x) (((_x) * 2) / 10)
++#define AR5K_EEPROM_N_CTLS(_v) AR5K_EEPROM_OFF(_v, 16, 32)
++#define AR5K_EEPROM_MAX_CTLS 32
++#define AR5K_EEPROM_N_XPD_PER_CHANNEL 4
++#define AR5K_EEPROM_N_XPD0_POINTS 4
++#define AR5K_EEPROM_N_XPD3_POINTS 3
++#define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35
++#define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55
++#define AR5K_EEPROM_POWER_M 0x3f
++#define AR5K_EEPROM_POWER_MIN 0
++#define AR5K_EEPROM_POWER_MAX 3150
++#define AR5K_EEPROM_POWER_STEP 50
++#define AR5K_EEPROM_POWER_TABLE_SIZE 64
++#define AR5K_EEPROM_N_POWER_LOC_11B 4
++#define AR5K_EEPROM_N_POWER_LOC_11G 6
++#define AR5K_EEPROM_I_GAIN 10
++#define AR5K_EEPROM_CCK_OFDM_DELTA 15
++#define AR5K_EEPROM_N_IQ_CAL 2
++
++enum ath5k_ant_setting {
++ AR5K_ANT_VARIABLE = 0, /* variable by programming */
++ AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */
++ AR5K_ANT_FIXED_B = 2, /* fixed to 11b frequencies */
++ AR5K_ANT_MAX = 3,
++};
+
+-#define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2) /* Header that contains the device caps */
+-#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1) /* Device has a support */
+-#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1) /* Device has b support */
+-#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1) /* Device has g support */
+-#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */
+-#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */
+-#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7)
+-#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz (?) */
+-#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */
++/* Per channel calibration data, used for power table setup */
++struct ath5k_chan_pcal_info {
++ u_int16_t freq; /* Frequency */
++ /* Power levels in dBm * 4 units */
++ int16_t pwr_x0[AR5K_EEPROM_N_XPD0_POINTS];
++ int16_t pwr_x3[AR5K_EEPROM_N_XPD3_POINTS];
++ /* PCDAC tables in dBm * 2 units */
++ u_int16_t pcdac_x0[AR5K_EEPROM_N_XPD0_POINTS];
++ u_int16_t pcdac_x3[AR5K_EEPROM_N_XPD3_POINTS];
++ /* Max available power */
++ u_int16_t max_pwr;
++};
+
+-/* Misc values available since EEPROM 4.0 */
+-#define AR5K_EEPROM_MISC0 0x00c4
+-#define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff)
+-#define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3)
+-#define AR5K_EEPROM_MISC1 0x00c5
+-#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff)
+-#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1)
++/* Per rate calibration data for each mode, used for power table setup */
++struct ath5k_rate_pcal_info {
++ u_int16_t freq; /* Frequency */
++ /* Power level for 6-24Mbit/s rates */
++ u_int16_t target_power_6to24;
++ /* Power level for 36Mbit rate */
++ u_int16_t target_power_36;
++ /* Power level for 48Mbit rate */
++ u_int16_t target_power_48;
++ /* Power level for 54Mbit rate */
++ u_int16_t target_power_54;
++};
++
++/* EEPROM calibration data */
++struct ath5k_eeprom_info {
++
++ /* Header information */
++ u_int16_t ee_magic;
++ u_int16_t ee_protect;
++ u_int16_t ee_regdomain;
++ u_int16_t ee_version;
++ u_int16_t ee_header;
++ u_int16_t ee_ant_gain;
++ u_int16_t ee_misc0;
++ u_int16_t ee_misc1;
++ u_int16_t ee_cck_ofdm_gain_delta;
++ u_int16_t ee_cck_ofdm_power_delta;
++ u_int16_t ee_scaled_cck_delta;
++
++ /* Used for tx thermal adjustment (eeprom_init, rfregs) */
++ u_int16_t ee_tx_clip;
++ u_int16_t ee_pwd_84;
++ u_int16_t ee_pwd_90;
++ u_int16_t ee_gain_select;
++
++ /* RF Calibration settings (reset, rfregs) */
++ u_int16_t ee_i_cal[AR5K_EEPROM_N_MODES];
++ u_int16_t ee_q_cal[AR5K_EEPROM_N_MODES];
++ u_int16_t ee_fixed_bias[AR5K_EEPROM_N_MODES];
++ u_int16_t ee_turbo_max_power[AR5K_EEPROM_N_MODES];
++ u_int16_t ee_xr_power[AR5K_EEPROM_N_MODES];
++ u_int16_t ee_switch_settling[AR5K_EEPROM_N_MODES];
++ u_int16_t ee_ant_tx_rx[AR5K_EEPROM_N_MODES];
++ u_int16_t ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC];
++ u_int16_t ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
++ u_int16_t ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
++ u_int16_t ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES];
++ u_int16_t ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES];
++ u_int16_t ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES];
++ u_int16_t ee_thr_62[AR5K_EEPROM_N_MODES];
++ u_int16_t ee_xlna_gain[AR5K_EEPROM_N_MODES];
++ u_int16_t ee_xpd[AR5K_EEPROM_N_MODES];
++ u_int16_t ee_x_gain[AR5K_EEPROM_N_MODES];
++ u_int16_t ee_i_gain[AR5K_EEPROM_N_MODES];
++ u_int16_t ee_margin_tx_rx[AR5K_EEPROM_N_MODES];
++
++ /* Power calibration data */
++ u_int16_t ee_false_detect[AR5K_EEPROM_N_MODES];
++ u_int16_t ee_cal_piers_a;
++ struct ath5k_chan_pcal_info ee_pwr_cal_a[AR5K_EEPROM_N_5GHZ_CHAN];
++ u_int16_t ee_cal_piers_b;
++ struct ath5k_chan_pcal_info ee_pwr_cal_b[AR5K_EEPROM_N_2GHZ_CHAN];
++ u_int16_t ee_cal_piers_g;
++ struct ath5k_chan_pcal_info ee_pwr_cal_g[AR5K_EEPROM_N_2GHZ_CHAN];
++ /* Per rate target power levels */
++ u_int16_t ee_rate_target_pwr_num_a;
++ struct ath5k_rate_pcal_info ee_rate_tpwr_a[AR5K_EEPROM_N_5GHZ_CHAN];
++ u_int16_t ee_rate_target_pwr_num_b;
++ struct ath5k_rate_pcal_info ee_rate_tpwr_b[AR5K_EEPROM_N_2GHZ_CHAN];
++ u_int16_t ee_rate_target_pwr_num_g;
++ struct ath5k_rate_pcal_info ee_rate_tpwr_g[AR5K_EEPROM_N_2GHZ_CHAN];
++
++ /* Conformance test limits (Unused) */
++ u_int16_t ee_ctls;
++ u_int16_t ee_ctl[AR5K_EEPROM_MAX_CTLS];
++
++ /* Noise Floor Calibration settings */
++ int16_t ee_noise_floor_thr[AR5K_EEPROM_N_MODES];
++ int8_t ee_adc_desired_size[AR5K_EEPROM_N_MODES];
++ int8_t ee_pga_desired_size[AR5K_EEPROM_N_MODES];
++
++ u_int32_t ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
++};
+
+ /*
+ * Read data by masking
+@@ -350,7 +486,6 @@ static const struct ath5k_srev_name ath5
+ (*((volatile u_int32_t *)(mem + (_reg))) = (_val))
+ #endif
+
+-
+ #define AR5K_REG_ENABLE_BITS(_reg, _flags) \
+ AR5K_REG_WRITE(_reg, AR5K_REG_READ(_reg) | (_flags))
+
+@@ -359,7 +494,12 @@ static const struct ath5k_srev_name ath5
+
+ #define AR5K_TUNE_REGISTER_TIMEOUT 20000
+
+-/* names for eeprom fields */
++#define AR5K_EEPROM_READ(_o, _v) do { \
++ if ((ret = ath5k_hw_eeprom_read(mem, (_o), &(_v), mac_version)) != 0) \
++ return (ret); \
++} while (0)
++
++/* Names for EEPROM fields */
+ struct eeprom_entry {
+ const char *name;
+ int addr;
+@@ -375,8 +515,6 @@ static const struct eeprom_entry eeprom_
+ {"regdomain", AR5K_EEPROM_REG_DOMAIN},
+ };
+
+-static const int eeprom_addr_len = sizeof(eeprom_addr) / sizeof(eeprom_addr[0]);
+-
+ static int force_write = 0;
+ static int verbose = 0;
+
+@@ -398,8 +536,8 @@ static u_int32_t ath5k_hw_bitswap(u_int3
+ /*
+ * Get the PHY Chip revision
+ */
+-static u_int16_t
+-ath5k_hw_radio_revision(u_int16_t mac_version, void *mem, u_int8_t chip)
++static u_int16_t ath5k_hw_radio_revision(u_int16_t mac_version, void *mem,
++ u_int8_t chip)
+ {
+ int i;
+ u_int32_t srev;
+@@ -427,7 +565,7 @@ ath5k_hw_radio_revision(u_int16_t mac_ve
+ for (i = 0; i < 8; i++)
+ AR5K_REG_WRITE(AR5K_PHY(0x20), 0x00010000);
+
+- if (mac_version == AR5K_SREV_VER_AR5210) {
++ if (mac_version == AR5K_SREV_MAC_AR5210) {
+ srev = AR5K_REG_READ(AR5K_PHY(256) >> 28) & 0xf;
+
+ ret = (u_int16_t)ath5k_hw_bitswap(srev, 4) + 1;
+@@ -447,9 +585,8 @@ ath5k_hw_radio_revision(u_int16_t mac_ve
+ /*
+ * Write to EEPROM
+ */
+-static int
+-ath5k_hw_eeprom_write(void *mem, u_int32_t offset, u_int16_t data,
+- u_int8_t mac_version)
++static int ath5k_hw_eeprom_write(void *mem, u_int32_t offset, u_int16_t data,
++ u_int8_t mac_version)
+ {
+ u_int32_t status, timeout;
+
+@@ -457,7 +594,7 @@ ath5k_hw_eeprom_write(void *mem, u_int32
+ * Initialize EEPROM access
+ */
+
+- if (mac_version == AR5K_SREV_VER_AR5210) {
++ if (mac_version == AR5K_SREV_MAC_AR5210) {
+
+ AR5K_REG_ENABLE_BITS(AR5K_PCICFG, AR5K_PCICFG_EEAE);
+
+@@ -466,7 +603,7 @@ ath5k_hw_eeprom_write(void *mem, u_int32
+
+ } else {
+ /* not 5210 */
+- /* reset eeprom access */
++ /* reset EEPROM access */
+ AR5K_REG_WRITE(AR5K_EEPROM_CMD, AR5K_EEPROM_CMD_RESET);
+ usleep(5);
+
+@@ -484,7 +621,7 @@ ath5k_hw_eeprom_write(void *mem, u_int32
+ status = AR5K_REG_READ(AR5K_EEPROM_STATUS);
+ if (status & AR5K_EEPROM_STAT_WRDONE) {
+ if (status & AR5K_EEPROM_STAT_WRERR) {
+- err("eeprom write access to 0x%04x failed",
++ err("EEPROM write access to 0x%04x failed",
+ offset);
+ return 1;
+ }
+@@ -499,16 +636,15 @@ ath5k_hw_eeprom_write(void *mem, u_int32
+ /*
+ * Read from EEPROM
+ */
+-static int
+-ath5k_hw_eeprom_read(void *mem, u_int32_t offset, u_int16_t *data,
+- u_int8_t mac_version)
++static int ath5k_hw_eeprom_read(void *mem, u_int32_t offset, u_int16_t *data,
++ u_int8_t mac_version)
+ {
+ u_int32_t status, timeout;
+
+ /*
+ * Initialize EEPROM access
+ */
+- if (mac_version == AR5K_SREV_VER_AR5210) {
++ if (mac_version == AR5K_SREV_MAC_AR5210) {
+ AR5K_REG_ENABLE_BITS(AR5K_PCICFG, AR5K_PCICFG_EEAE);
+ (void)AR5K_REG_READ(AR5K_EEPROM_BASE + (4 * offset));
+ } else {
+@@ -531,50 +667,701 @@ ath5k_hw_eeprom_read(void *mem, u_int32_
+ return 1;
+ }
+
+-static const char *ath5k_hw_get_part_name(enum ath5k_srev_type type,
+- u_int32_t val)
++/*
++ * Translate binary channel representation in EEPROM to frequency
++ */
++static u_int16_t ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee,
++ u_int16_t bin, unsigned int mode)
+ {
+- const char *name = "xxxxx";
+- int i;
++ u_int16_t val;
+
+- for (i = 0; i < ARRAY_SIZE(ath5k_srev_names); i++) {
+- if (ath5k_srev_names[i].sr_type != type ||
+- ath5k_srev_names[i].sr_val == AR5K_SREV_UNKNOWN)
+- continue;
+- if ((val & 0xff) < ath5k_srev_names[i + 1].sr_val) {
+- name = ath5k_srev_names[i].sr_name;
++ if (bin == AR5K_EEPROM_CHANNEL_DIS)
++ return bin;
++
++ if (mode == AR5K_EEPROM_MODE_11A) {
++ if (ee->ee_version > AR5K_EEPROM_VERSION_3_2)
++ val = (5 * bin) + 4800;
++ else
++ val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 :
++ (bin * 10) + 5100;
++ } else {
++ if (ee->ee_version > AR5K_EEPROM_VERSION_3_2)
++ val = bin + 2300;
++ else
++ val = bin + 2400;
++ }
++
++ return val;
++}
++
++/*
++ * Read antenna info from EEPROM
++ */
++static int ath5k_eeprom_read_ants(void *mem, u_int8_t mac_version,
++ struct ath5k_eeprom_info *ee,
++ u_int32_t *offset, unsigned int mode)
++{
++ u_int32_t o = *offset;
++ u_int16_t val;
++ int ret, i = 0;
++
++ AR5K_EEPROM_READ(o++, val);
++ ee->ee_switch_settling[mode] = (val >> 8) & 0x7f;
++ ee->ee_ant_tx_rx[mode] = (val >> 2) & 0x3f;
++ ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
++
++ AR5K_EEPROM_READ(o++, val);
++ ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
++ ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
++ ee->ee_ant_control[mode][i++] = val & 0x3f;
++
++ AR5K_EEPROM_READ(o++, val);
++ ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f;
++ ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f;
++ ee->ee_ant_control[mode][i] = (val << 2) & 0x3f;
++
++ AR5K_EEPROM_READ(o++, val);
++ ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3;
++ ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f;
++ ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f;
++ ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
++
++ AR5K_EEPROM_READ(o++, val);
++ ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
++ ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
++ ee->ee_ant_control[mode][i++] = val & 0x3f;
++
++ /* Get antenna modes */
++ ee->ee_antenna[mode][0] =
++ (ee->ee_ant_control[mode][0] << 4) | 0x1;
++ ee->ee_antenna[mode][AR5K_ANT_FIXED_A] =
++ ee->ee_ant_control[mode][1] |
++ (ee->ee_ant_control[mode][2] << 6) |
++ (ee->ee_ant_control[mode][3] << 12) |
++ (ee->ee_ant_control[mode][4] << 18) |
++ (ee->ee_ant_control[mode][5] << 24);
++ ee->ee_antenna[mode][AR5K_ANT_FIXED_B] =
++ ee->ee_ant_control[mode][6] |
++ (ee->ee_ant_control[mode][7] << 6) |
++ (ee->ee_ant_control[mode][8] << 12) |
++ (ee->ee_ant_control[mode][9] << 18) |
++ (ee->ee_ant_control[mode][10] << 24);
++
++ /* return new offset */
++ *offset = o;
++
++ return 0;
++}
++
++/*
++ * Read supported modes from EEPROM
++ */
++static int ath5k_eeprom_read_modes(void *mem, u_int8_t mac_version,
++ struct ath5k_eeprom_info *ee,
++ u_int32_t *offset, unsigned int mode)
++{
++ u_int32_t o = *offset;
++ u_int16_t val;
++ int ret;
++
++ AR5K_EEPROM_READ(o++, val);
++ ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff;
++ ee->ee_thr_62[mode] = val & 0xff;
++
++ if (ee->ee_version <= AR5K_EEPROM_VERSION_3_2)
++ ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28;
++
++ AR5K_EEPROM_READ(o++, val);
++ ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff;
++ ee->ee_tx_frm2xpa_enable[mode] = val & 0xff;
++
++ AR5K_EEPROM_READ(o++, val);
++ ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff;
++
++ if ((val & 0xff) & 0x80)
++ ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1);
++ else
++ ee->ee_noise_floor_thr[mode] = val & 0xff;
++
++ if (ee->ee_version <= AR5K_EEPROM_VERSION_3_2)
++ ee->ee_noise_floor_thr[mode] =
++ mode == AR5K_EEPROM_MODE_11A ? -54 : -1;
++
++ AR5K_EEPROM_READ(o++, val);
++ ee->ee_xlna_gain[mode] = (val >> 5) & 0xff;
++ ee->ee_x_gain[mode] = (val >> 1) & 0xf;
++ ee->ee_xpd[mode] = val & 0x1;
++
++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0)
++ ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
++
++ if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) {
++ AR5K_EEPROM_READ(o++, val);
++ ee->ee_false_detect[mode] = (val >> 6) & 0x7f;
++
++ if (mode == AR5K_EEPROM_MODE_11A)
++ ee->ee_xr_power[mode] = val & 0x3f;
++ else {
++ ee->ee_ob[mode][0] = val & 0x7;
++ ee->ee_db[mode][0] = (val >> 3) & 0x7;
++ }
++ }
++
++ if (ee->ee_version < AR5K_EEPROM_VERSION_3_4) {
++ ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN;
++ ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA;
++ } else {
++ ee->ee_i_gain[mode] = (val >> 13) & 0x7;
++
++ AR5K_EEPROM_READ(o++, val);
++ ee->ee_i_gain[mode] |= (val << 3) & 0x38;
++
++ if (mode == AR5K_EEPROM_MODE_11G)
++ ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff;
++ }
++
++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0 &&
++ mode == AR5K_EEPROM_MODE_11A) {
++ ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
++ ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
++ }
++
++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_6 &&
++ mode == AR5K_EEPROM_MODE_11G)
++ ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
++
++ /* return new offset */
++ *offset = o;
++
++ return 0;
++}
++
++/*
++ * Read per channel calibration info from EEPROM
++ * This doesn't work on 2112+ chips (EEPROM versions >= 4.6),
++ * I only tested it on 5213 + 5112. This is still work in progress...
++ *
++ * This info is used to calibrate the baseband power table. Imagine
++ * that for each channel there is a power curve that's hw specific
++ * (depends on amplifier) and we try to "correct" this curve using offests
++ * we pass on to phy chip (baseband -> before amplifier) so that it can
++ * use acurate power values when setting tx power (takes amplifier's performance
++ * on each channel into account).
++ *
++ * EEPROM provides us with the offsets for some pre-calibrated channels
++ * and we have to scale (to create the full table for these channels) and
++ * interpolate (in order to create the table for any channel).
++ */
++static int ath5k_eeprom_read_pcal_info(void *mem, u_int8_t mac_version,
++ struct ath5k_eeprom_info *ee,
++ u_int32_t *offset, unsigned int mode)
++{
++ u_int32_t o = *offset;
++ unsigned int i, c;
++ int ret;
++ u_int16_t val;
++ struct ath5k_chan_pcal_info *chan_pcal_info;
++ u_int16_t cal_piers;
++
++ switch (mode) {
++ case AR5K_EEPROM_MODE_11A:
++ chan_pcal_info = ee->ee_pwr_cal_a;
++ cal_piers = ee->ee_cal_piers_a;
++ break;
++ case AR5K_EEPROM_MODE_11B:
++ chan_pcal_info = ee->ee_pwr_cal_b;
++ cal_piers = ee->ee_cal_piers_b;
++ break;
++ case AR5K_EEPROM_MODE_11G:
++ chan_pcal_info = ee->ee_pwr_cal_g;
++ cal_piers = ee->ee_cal_piers_g;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ for (i = 0; i < cal_piers; i++) {
++ /* Power values in dBm * 4 */
++ for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) {
++ AR5K_EEPROM_READ(o++, val);
++ chan_pcal_info[i].pwr_x0[c] = (val & 0xff);
++ chan_pcal_info[i].pwr_x0[++c] = ((val >> 8) & 0xff);
++ }
++
++ /* PCDAC steps (dBm * 2) */
++ AR5K_EEPROM_READ(o++, val);
++ chan_pcal_info[i].pcdac_x0[1] = (val & 0x1f);
++ chan_pcal_info[i].pcdac_x0[2] = ((val >> 5) & 0x1f);
++ chan_pcal_info[i].pcdac_x0[3] = ((val >> 10) & 0x1f);
++
++ /* No idea what these power levels are for (4 xpds ?)
++ I got zeroes on my card and the EEPROM info
++ dumps we found on the net also have weird values */
++ AR5K_EEPROM_READ(o++, val);
++ chan_pcal_info[i].pwr_x3[0] = (val & 0xff);
++ chan_pcal_info[i].pwr_x3[1] = ((val >> 8) & 0xff);
++
++ AR5K_EEPROM_READ(o++, val);
++ chan_pcal_info[i].pwr_x3[2] = (val & 0xff);
++ /* It's weird but they put it here, that's the
++ PCDAC starting step */
++ chan_pcal_info[i].pcdac_x0[0] = ((val >> 8) & 0xff);
++
++ /* Static values seen on EEPROM info dumps */
++ chan_pcal_info[i].pcdac_x3[0] = 20;
++ chan_pcal_info[i].pcdac_x3[1] = 35;
++ chan_pcal_info[i].pcdac_x3[2] = 63;
++
++ /* Last xpd0 power level is also channel maximum */
++ chan_pcal_info[i].max_pwr = chan_pcal_info[i].pwr_x0[3];
++
++ /* Recreate pcdac_x0 table for this channel using pcdac steps */
++ chan_pcal_info[i].pcdac_x0[1] += chan_pcal_info[i].pcdac_x0[0];
++ chan_pcal_info[i].pcdac_x0[2] += chan_pcal_info[i].pcdac_x0[1];
++ chan_pcal_info[i].pcdac_x0[3] += chan_pcal_info[i].pcdac_x0[2];
++ }
++
++ /* return new offset */
++ (*offset) = o;
++
++ return 0;
++}
++
++/*
++ * Read per rate target power (this is the maximum tx power
++ * supported by the card). This info is used when setting
++ * tx power, no matter the channel.
++ *
++ * This also works for v5 EEPROMs.
++ */
++static int ath5k_eeprom_read_target_rate_pwr_info(void *mem,
++ u_int8_t mac_version,
++ struct ath5k_eeprom_info *ee,
++ u_int32_t *offset,
++ unsigned int mode)
++{
++ u_int32_t o = *offset;
++ u_int16_t val;
++ struct ath5k_rate_pcal_info *rate_pcal_info;
++ u_int16_t *rate_target_pwr_num;
++ int ret, i;
++
++ switch (mode) {
++ case AR5K_EEPROM_MODE_11A:
++ rate_pcal_info = ee->ee_rate_tpwr_a;
++ ee->ee_rate_target_pwr_num_a = AR5K_EEPROM_N_5GHZ_CHAN;
++ rate_target_pwr_num = &ee->ee_rate_target_pwr_num_a;
++ break;
++ case AR5K_EEPROM_MODE_11B:
++ rate_pcal_info = ee->ee_rate_tpwr_b;
++ ee->ee_rate_target_pwr_num_b = 2; /* 3rd is g mode'ss 1st */
++ rate_target_pwr_num = &ee->ee_rate_target_pwr_num_b;
++ break;
++ case AR5K_EEPROM_MODE_11G:
++ rate_pcal_info = ee->ee_rate_tpwr_g;
++ ee->ee_rate_target_pwr_num_g = AR5K_EEPROM_N_2GHZ_CHAN;
++ rate_target_pwr_num = &ee->ee_rate_target_pwr_num_g;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ /* Different freq mask for older eeproms (<= v3.2) */
++ if(ee->ee_version <= 0x3002){
++ for (i = 0; i < (*rate_target_pwr_num); i++) {
++ AR5K_EEPROM_READ(o++, val);
++ rate_pcal_info[i].freq =
++ ath5k_eeprom_bin2freq(ee, (val >> 9) & 0x7f, mode);
++
++ rate_pcal_info[i].target_power_6to24 = ((val >> 3) & 0x3f);
++ rate_pcal_info[i].target_power_36 = (val << 3) & 0x3f;
++
++ AR5K_EEPROM_READ(o++, val);
++
++ if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS ||
++ val == 0) {
++ (*rate_target_pwr_num) = i;
++ break;
++ }
++
++ rate_pcal_info[i].target_power_36 |= ((val >> 13) & 0x7);
++ rate_pcal_info[i].target_power_48 = ((val >> 7) & 0x3f);
++ rate_pcal_info[i].target_power_54 = ((val >> 1) & 0x3f);
++ }
++ } else {
++ for (i = 0; i < (*rate_target_pwr_num); i++) {
++ AR5K_EEPROM_READ(o++, val);
++ rate_pcal_info[i].freq =
++ ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
++
++ rate_pcal_info[i].target_power_6to24 = ((val >> 2) & 0x3f);
++ rate_pcal_info[i].target_power_36 = (val << 4) & 0x3f;
++
++ AR5K_EEPROM_READ(o++, val);
++
++ if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS ||
++ val == 0) {
++ (*rate_target_pwr_num) = i;
++ break;
++ }
++
++ rate_pcal_info[i].target_power_36 |= (val >> 12) & 0xf;
++ rate_pcal_info[i].target_power_48 = ((val >> 6) & 0x3f);
++ rate_pcal_info[i].target_power_54 = (val & 0x3f);
++ }
++ }
++ /* return new offset */
++ (*offset) = o;
++
++ return 0;
++}
++
++/*
++ * Initialize EEPROM & capabilities data
++ */
++static int ath5k_eeprom_init(void *mem, u_int8_t mac_version,
++ struct ath5k_eeprom_info *ee)
++{
++ unsigned int mode, i;
++ int ret;
++ u_int32_t offset;
++ u_int16_t val;
++
++ /* Initial TX thermal adjustment values */
++ ee->ee_tx_clip = 4;
++ ee->ee_pwd_84 = ee->ee_pwd_90 = 1;
++ ee->ee_gain_select = 1;
++
++ /*
++ * Read values from EEPROM and store them in the capability structure
++ */
++ AR5K_EEPROM_READ(AR5K_EEPROM_MAGIC, ee->ee_magic);
++ AR5K_EEPROM_READ(AR5K_EEPROM_PROTECT, ee->ee_protect);
++ AR5K_EEPROM_READ(AR5K_EEPROM_REG_DOMAIN, ee->ee_regdomain);
++ AR5K_EEPROM_READ(AR5K_EEPROM_VERSION, ee->ee_version);
++ AR5K_EEPROM_READ(AR5K_EEPROM_HDR, ee->ee_header);
++
++ /* Return if we have an old EEPROM */
++ if (ee->ee_version < AR5K_EEPROM_VERSION_3_0)
++ return 0;
++
++#ifdef notyet
++ /*
++ * Validate the checksum of the EEPROM date. There are some
++ * devices with invalid EEPROMs.
++ */
++ for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
++ AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
++ cksum ^= val;
++ }
++ if (cksum != AR5K_EEPROM_INFO_CKSUM) {
++ AR5K_PRINTF("Invalid EEPROM checksum 0x%04x\n", cksum);
++ return -EIO;
++ }
++#endif
++
++ AR5K_EEPROM_READ(AR5K_EEPROM_ANT_GAIN(ee->ee_version), ee->ee_ant_gain);
++
++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0) {
++ AR5K_EEPROM_READ(AR5K_EEPROM_MISC0, ee->ee_misc0);
++ AR5K_EEPROM_READ(AR5K_EEPROM_MISC1, ee->ee_misc1);
++ }
++
++ if (ee->ee_version < AR5K_EEPROM_VERSION_3_3) {
++ AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val);
++ ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
++ ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
++
++ AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val);
++ ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
++ ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
++ }
++
++ /*
++ * Get conformance test limit values
++ */
++ offset = AR5K_EEPROM_CTL(ee->ee_version);
++ ee->ee_ctls = 0;
++
++ for (i = 0; i < AR5K_EEPROM_N_CTLS(ee->ee_version); i++) {
++ AR5K_EEPROM_READ(offset++, val);
++
++ if (((val >> 8) & 0xff) == 0)
++ break;
++
++ ee->ee_ctl[i] = (val >> 8) & 0xff;
++ ee->ee_ctls++;
++
++ if ((val & 0xff) == 0)
+ break;
++
++ ee->ee_ctl[i + 1] = val & 0xff;
++ ee->ee_ctls++;
++ }
++
++ /*
++ * Get values for 802.11a (5GHz)
++ */
++ mode = AR5K_EEPROM_MODE_11A;
++
++ ee->ee_turbo_max_power[mode] =
++ AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
++
++ offset = AR5K_EEPROM_MODES_11A(ee->ee_version);
++
++ ret = ath5k_eeprom_read_ants(mem, mac_version, ee, &offset, mode);
++ if (ret)
++ return ret;
++
++ AR5K_EEPROM_READ(offset++, val);
++ ee->ee_adc_desired_size[mode] = (int8_t)((val >> 8) & 0xff);
++ ee->ee_ob[mode][3] = (val >> 5) & 0x7;
++ ee->ee_db[mode][3] = (val >> 2) & 0x7;
++ ee->ee_ob[mode][2] = (val << 1) & 0x7;
++
++ AR5K_EEPROM_READ(offset++, val);
++ ee->ee_ob[mode][2] |= (val >> 15) & 0x1;
++ ee->ee_db[mode][2] = (val >> 12) & 0x7;
++ ee->ee_ob[mode][1] = (val >> 9) & 0x7;
++ ee->ee_db[mode][1] = (val >> 6) & 0x7;
++ ee->ee_ob[mode][0] = (val >> 3) & 0x7;
++ ee->ee_db[mode][0] = val & 0x7;
++
++ ret = ath5k_eeprom_read_modes(mem, mac_version, ee, &offset, mode);
++ if (ret)
++ return ret;
++
++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_1) {
++ AR5K_EEPROM_READ(offset++, val);
++ ee->ee_margin_tx_rx[mode] = val & 0x3f;
++ }
++
++ /*
++ * Get values for 802.11b (2.4GHz)
++ */
++ mode = AR5K_EEPROM_MODE_11B;
++ offset = AR5K_EEPROM_MODES_11B(ee->ee_version);
++
++ ret = ath5k_eeprom_read_ants(mem, mac_version, ee, &offset, mode);
++ if (ret)
++ return ret;
++
++ AR5K_EEPROM_READ(offset++, val);
++ ee->ee_adc_desired_size[mode] = (int8_t)((val >> 8) & 0xff);
++ ee->ee_ob[mode][1] = (val >> 4) & 0x7;
++ ee->ee_db[mode][1] = val & 0x7;
++
++ ret = ath5k_eeprom_read_modes(mem, mac_version, ee, &offset, mode);
++ if (ret)
++ return ret;
++
++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0) {
++ AR5K_EEPROM_READ(offset++, val);
++
++ ee->ee_cal_piers_b = 0;
++
++ ee->ee_pwr_cal_b[0].freq =
++ ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
++ if (ee->ee_pwr_cal_b[0].freq != AR5K_EEPROM_CHANNEL_DIS)
++ ee->ee_cal_piers_b++;
++
++ ee->ee_pwr_cal_b[1].freq =
++ ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
++ if (ee->ee_pwr_cal_b[1].freq != AR5K_EEPROM_CHANNEL_DIS)
++ ee->ee_cal_piers_b++;
++
++ AR5K_EEPROM_READ(offset++, val);
++ ee->ee_pwr_cal_b[2].freq =
++ ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
++ if (ee->ee_pwr_cal_b[2].freq != AR5K_EEPROM_CHANNEL_DIS)
++ ee->ee_cal_piers_b++;
++ }
++
++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_1)
++ ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
++
++ /*
++ * Get values for 802.11g (2.4GHz)
++ */
++ mode = AR5K_EEPROM_MODE_11G;
++ offset = AR5K_EEPROM_MODES_11G(ee->ee_version);
++
++ ret = ath5k_eeprom_read_ants(mem, mac_version, ee, &offset, mode);
++ if (ret)
++ return ret;
++
++ AR5K_EEPROM_READ(offset++, val);
++ ee->ee_adc_desired_size[mode] = (signed short int)((val >> 8) & 0xff);
++ ee->ee_ob[mode][1] = (val >> 4) & 0x7;
++ ee->ee_db[mode][1] = val & 0x7;
++
++ ret = ath5k_eeprom_read_modes(mem, mac_version, ee, &offset, mode);
++ if (ret)
++ return ret;
++
++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0) {
++ AR5K_EEPROM_READ(offset++, val);
++
++ ee->ee_cal_piers_g = 0;
++
++ ee->ee_pwr_cal_g[0].freq =
++ ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
++ if (ee->ee_pwr_cal_g[0].freq != AR5K_EEPROM_CHANNEL_DIS)
++ ee->ee_cal_piers_g++;
++
++ ee->ee_pwr_cal_g[1].freq =
++ ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
++ if (ee->ee_pwr_cal_g[1].freq != AR5K_EEPROM_CHANNEL_DIS)
++ ee->ee_cal_piers_g++;
++
++ AR5K_EEPROM_READ(offset++, val);
++ ee->ee_turbo_max_power[mode] = val & 0x7f;
++ ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
++
++ AR5K_EEPROM_READ(offset++, val);
++ ee->ee_pwr_cal_g[2].freq =
++ ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
++ if (ee->ee_pwr_cal_g[2].freq != AR5K_EEPROM_CHANNEL_DIS)
++ ee->ee_cal_piers_g++;
++
++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_1)
++ ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
++
++ AR5K_EEPROM_READ(offset++, val);
++ ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
++ ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
++
++ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_2) {
++ AR5K_EEPROM_READ(offset++, val);
++ ee->ee_cck_ofdm_gain_delta = val & 0xff;
+ }
+ }
+
+- return (name);
++ /*
++ * Read 5GHz EEPROM channels
++ */
++ offset = AR5K_EEPROM_CHANNELS_5GHZ(ee->ee_version);
++ ee->ee_cal_piers_a = 0;
++ for (i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i++) {
++ AR5K_EEPROM_READ(offset++, val);
++
++ if ((val & 0xff) == 0)
++ break;
++
++ ee->ee_pwr_cal_a[i].freq =
++ ath5k_eeprom_bin2freq(ee, val & 0xff, AR5K_EEPROM_MODE_11A);
++ ee->ee_cal_piers_a++;
++
++ if (((val >> 8) & 0xff) == 0)
++ break;
++
++ ee->ee_pwr_cal_a[++i].freq =
++ ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, AR5K_EEPROM_MODE_11A);
++ ee->ee_cal_piers_a++;
++
++ }
++
++ /*
++ * Read power calibration info
++ */
++ mode = AR5K_EEPROM_MODE_11A;
++ ret = ath5k_eeprom_read_pcal_info(mem, mac_version, ee, &offset, mode);
++ if (ret)
++ return ret;
++
++ mode = AR5K_EEPROM_MODE_11B;
++ ret = ath5k_eeprom_read_pcal_info(mem, mac_version, ee, &offset, mode);
++ if (ret)
++ return ret;
++
++ mode = AR5K_EEPROM_MODE_11G;
++ ret = ath5k_eeprom_read_pcal_info(mem, mac_version, ee, &offset, mode);
++ if (ret)
++ return ret;
++
++
++ /*
++ * Read per rate target power info
++ */
++ offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) + AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version);
++ mode = AR5K_EEPROM_MODE_11A;
++ ret = ath5k_eeprom_read_target_rate_pwr_info(mem, mac_version, ee, &offset, mode);
++ if (ret)
++ return ret;
++
++ offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) + AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version);
++ mode = AR5K_EEPROM_MODE_11B;
++ ret = ath5k_eeprom_read_target_rate_pwr_info(mem, mac_version, ee, &offset, mode);
++ if (ret)
++ return ret;
++
++ offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) + AR5K_EEPROM_TARGET_PWR_OFF_11G(ee->ee_version);
++ mode = AR5K_EEPROM_MODE_11G;
++ ret = ath5k_eeprom_read_target_rate_pwr_info(mem, mac_version, ee, &offset, mode);
++ if (ret)
++ return ret;
++
++ return 0;
++}
++
++static const char *ath5k_hw_get_mac_name(u_int8_t val)
++{
++ static char name[16];
++ unsigned int i;
++
++ for (i = 0; i < ARRAY_SIZE(ath5k_mac_names); i++) {
++ if (val <= ath5k_mac_names[i].sr_val)
++ break;
++ }
++
++ if (val == ath5k_mac_names[i].sr_val)
++ return ath5k_mac_names[i].sr_name;
++
++ snprintf(name, sizeof(name), "%s+", ath5k_mac_names[i - 1].sr_name);
++ return name;
++}
++
++static const char *ath5k_hw_get_phy_name(u_int8_t val)
++{
++ const char *name = "?????";
++ unsigned int i;
++
++ for (i = 0; i < ARRAY_SIZE(ath5k_phy_names); i++) {
++ if (val < ath5k_phy_names[i + 1].sr_val) {
++ name = ath5k_phy_names[i].sr_name;
++ break;
++ }
++ }
++
++ return name;
+ }
+
+ /* returns -1 on unknown name */
+ static int eeprom_name2addr(const char *name)
+ {
+- int i;
++ unsigned int i;
++
+ if (!name || !name[0])
+ return -1;
+- for (i = 0; i < eeprom_addr_len; i++)
++ for (i = 0; i < ARRAY_SIZE(eeprom_addr); i++)
+ if (!strcmp(name, eeprom_addr[i].name))
+ return eeprom_addr[i].addr;
+ return -1;
+-} /* eeprom_name2addr */
++}
+
+ /* returns "<unknown>" on unknown address */
+ static const char *eeprom_addr2name(int addr)
+ {
+- int i;
+- for (i = 0; i < eeprom_addr_len; i++)
++ unsigned int i;
++
++ for (i = 0; i < ARRAY_SIZE(eeprom_addr); i++)
+ if (eeprom_addr[i].addr == addr)
+ return eeprom_addr[i].name;
+ return "<unknown>";
+-} /* eeprom_addr2name */
++}
+
+-static int
+-do_write_pairs(int anr, int argc, char **argv, unsigned char *mem,
+- int mac_version)
++static int do_write_pairs(int anr, int argc, char **argv, unsigned char *mem,
++ int mac_version)
+ {
+ #define MAX_NR_WRITES 16
+ struct {
+@@ -635,7 +1422,7 @@ do_write_pairs(int anr, int argc, char *
+ }
+ anr++;
+ i++;
+- } /* while (anr < (argc-1)) */
++ }
+
+ if (!(wr_ops_len = i)) {
+ err("no (addr,val) pairs given");
+@@ -702,20 +1489,22 @@ do_write_pairs(int anr, int argc, char *
+ }
+
+ return errors ? 11 : 0;
+-} /* do_write_pairs */
++}
+
+ static void usage(const char *n)
+ {
+- int i;
++ unsigned int i;
+
+- fprintf(stderr, "%s [-w [-g N:M]] [-v] [-f] [-d] <base_address> "
++ fprintf(stderr, "%s [-w [-g N:M]] [-v] [-f] [-d] [-R addr] [-W addr val] <base_address> "
+ "[<name1> <val1> [<name2> <val2> ...]]\n\n", n);
+ fprintf(stderr,
+ "-w write values into EEPROM\n"
+ "-g N:M set GPIO N to level M (only used with -w)\n"
+ "-v verbose output\n"
+ "-f force; suppress question before writing\n"
+- "-d dump eeprom (file 'ath-eeprom-dump.bin' and screen)\n"
++ "-d dump EEPROM (file 'ath-eeprom-dump.bin' and screen)\n"
++ "-R <addr> read register at <addr> (hex)\n"
++ "-W <addr> <val> write <val> (hex) into register at <addr> (hex)\n"
+ "<base_address> device base address (see lspci output)\n\n");
+
+ fprintf(stderr,
+@@ -725,8 +1514,8 @@ static void usage(const char *n)
+ " %s -w <base_address> regdomain N\n\n"
+ "- set a PCI id field to value N:\n"
+ " %s -w <base_address> <field> N\n"
+- " where <field> is on of:\n ", n, n, n);
+- for (i = 0; i < eeprom_addr_len; i++)
++ " where <field> is one of:\n ", n, n, n);
++ for (i = 0; i < ARRAY_SIZE(eeprom_addr); i++)
+ fprintf(stderr, " %s", eeprom_addr[i].name);
+ fprintf(stderr, "\n\n");
+ fprintf(stderr,
+@@ -739,19 +1528,457 @@ static void usage(const char *n)
+ "unlawful radio transmissions!\n\n");
+ }
+
++static void dump_capabilities(struct ath5k_eeprom_info *ee)
++{
++ u_int8_t has_a, has_b, has_g, has_rfkill, turbog_dis, turboa_dis;
++ u_int8_t xr2_dis, xr5_dis, has_crystal;
++
++ has_a = AR5K_EEPROM_HDR_11A(ee->ee_header);
++ has_b = AR5K_EEPROM_HDR_11B(ee->ee_header);
++ has_g = AR5K_EEPROM_HDR_11G(ee->ee_header);
++ has_rfkill = AR5K_EEPROM_HDR_RFKILL(ee->ee_header);
++ has_crystal = AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1);
++ turbog_dis = AR5K_EEPROM_HDR_T_2GHZ_DIS(ee->ee_header);
++ turboa_dis = AR5K_EEPROM_HDR_T_5GHZ_DIS(ee->ee_header);
++ xr2_dis = AR5K_EEPROM_HDR_XR2_DIS(ee->ee_misc0);
++ xr5_dis = AR5K_EEPROM_HDR_XR5_DIS(ee->ee_misc0);
++
++ printf("|================= Capabilities ================|\n");
++
++ printf("| 802.11a Support: ");
++ if (has_a)
++ printf(" yes |");
++ else
++ printf(" no |");
++
++ printf(" Turbo-A disabled:");
++ if (turboa_dis)
++ printf(" yes |\n");
++ else
++ printf(" no |\n");
++
++ printf("| 802.11b Support: ");
++ if (has_b)
++ printf(" yes |");
++ else
++ printf(" no |");
++
++ printf(" Turbo-G disabled:");
++ if (turbog_dis)
++ printf(" yes |\n");
++ else
++ printf(" no |\n");
++
++ printf("| 802.11g Support: ");
++ if (has_g)
++ printf(" yes |");
++ else
++ printf(" no |");
++
++ printf(" 2GHz XR disabled:");
++ if (xr2_dis)
++ printf(" yes |\n");
++ else
++ printf(" no |\n");
++
++ printf("| RFKill Support: ");
++ if (has_rfkill)
++ printf(" yes |");
++ else
++ printf(" no |");
++
++ printf(" 5GHz XR disabled:");
++ if (xr5_dis)
++ printf(" yes |\n");
++ else
++ printf(" no |\n");
++
++ if (has_crystal != 2) {
++ printf("| 32kHz Crystal: ");
++ if (has_crystal)
++ printf(" yes |");
++ else
++ printf(" no |");
++
++ printf(" |\n");
++ }
++
++ printf("\\===============================================/\n");
++}
++
++static void dump_calinfo_for_mode(int mode, struct ath5k_eeprom_info *ee)
++{
++ int i;
++
++ printf("|=========================================================|\n");
++ printf("| I power: 0x%02x |", ee->ee_i_cal[mode]);
++ printf(" Q power: 0x%02x |\n", ee->ee_q_cal[mode]);
++ printf("| Use fixed bias: 0x%02x |", ee->ee_fixed_bias[mode]);
++ printf(" Max turbo power: 0x%02x |\n", ee->ee_turbo_max_power[mode]);
++ printf("| Max XR power: 0x%02x |", ee->ee_xr_power[mode]);
++ printf(" Switch Settling Time: 0x%02x |\n", ee->ee_switch_settling[mode]);
++ printf("| Tx/Rx attenuation: 0x%02x |", ee->ee_ant_tx_rx[mode]);
++ printf(" TX end to XLNA On: 0x%02x |\n", ee->ee_tx_end2xlna_enable[mode]);
++ printf("| TX end to XPA Off: 0x%02x |", ee->ee_tx_end2xpa_disable[mode]);
++ printf(" TX end to XPA On: 0x%02x |\n", ee->ee_tx_frm2xpa_enable[mode]);
++ printf("| 62db Threshold: 0x%02x |", ee->ee_thr_62[mode]);
++ printf(" XLNA gain: 0x%02x |\n", ee->ee_xlna_gain[mode]);
++ printf("| XPD: 0x%02x |", ee->ee_xpd[mode]);
++ printf(" XPD gain: 0x%02x |\n", ee->ee_x_gain[mode]);
++ printf("| I gain: 0x%02x |", ee->ee_i_gain[mode]);
++ printf(" Tx/Rx margin: 0x%02x |\n", ee->ee_margin_tx_rx[mode]);
++ printf("| False detect backoff: 0x%02x |", ee->ee_false_detect[mode]);
++ printf(" Noise Floor Threshold: %3d |\n", ee->ee_noise_floor_thr[mode]);
++ printf("| ADC desired size: %3d |", ee->ee_adc_desired_size[mode]);
++ printf(" PGA desired size: %3d |\n", ee->ee_pga_desired_size[mode]);
++ printf("|=========================================================|\n");
++ for (i = 0; i < AR5K_EEPROM_N_PCDAC; i++) {
++ printf("| Antenna control %2i: 0x%02x |", i, ee->ee_ant_control[mode][i]);
++ i++;
++ printf(" Antenna control %2i: 0x%02x |\n", i, ee->ee_ant_control[mode][i]);
++ }
++ printf("|=========================================================|\n");
++ for (i = 0; i < AR5K_EEPROM_N_OBDB; i++) {
++ printf("| Octave Band %i: %2i |", i, ee->ee_ob[mode][i]);
++ printf(" db %i: %2i |\n", i, ee->ee_db[mode][i]);
++ }
++ printf("\\=========================================================/\n");
++}
++
++static void dump_power_calinfo_for_mode(int mode, struct ath5k_eeprom_info *ee)
++{
++ struct ath5k_chan_pcal_info *chan_pcal_info;
++ u_int16_t cal_piers;
++ int i, c;
++
++ switch (mode) {
++ case AR5K_EEPROM_MODE_11A:
++ chan_pcal_info = ee->ee_pwr_cal_a;
++ cal_piers = ee->ee_cal_piers_a;
++ break;
++ case AR5K_EEPROM_MODE_11B:
++ chan_pcal_info = ee->ee_pwr_cal_b;
++ cal_piers = ee->ee_cal_piers_b;
++ break;
++ case AR5K_EEPROM_MODE_11G:
++ chan_pcal_info = ee->ee_pwr_cal_g;
++ cal_piers = ee->ee_cal_piers_g;
++ break;
++ default:
++ return;
++ }
++
++ printf("/=================== Per channel power calibration ====================\\\n");
++ printf("| Freq | pwr_0 | pwr_1 | pwr_2 | pwr_3 |pwrx3_0|pwrx3_1|pwrx3_2|max_pwr|\n");
++ printf("| | pcdac | pcdac | pcdac | pcdac | pcdac | pcdac | pcdac | |\n");
++
++ for (i = 0; i < cal_piers; i++) {
++ char buf[16];
++
++ printf("|======|=======|=======|=======|=======|=======|=======|=======|=======|\n");
++ printf("| %4i |", chan_pcal_info[i].freq);
++ for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) {
++ printf(" %2i.%02i |", chan_pcal_info[i].pwr_x0[c] / 4,
++ chan_pcal_info[i].pwr_x0[c] % 4);
++ }
++ for (c = 0; c < AR5K_EEPROM_N_XPD3_POINTS; c++) {
++ printf(" %2i.%02i |", chan_pcal_info[i].pwr_x3[c] / 4,
++ chan_pcal_info[i].pwr_x3[c] % 4);
++ }
++ printf(" %2i.%02i |\n", chan_pcal_info[i].max_pwr / 4,
++ chan_pcal_info[i].max_pwr % 4);
++
++ printf("| |");
++ for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) {
++ snprintf(buf, sizeof(buf), "[%i]",
++ chan_pcal_info[i].pcdac_x0[c]);
++ printf("%6s |", buf);
++ }
++ for (c = 0; c < AR5K_EEPROM_N_XPD3_POINTS; c++) {
++ snprintf(buf, sizeof(buf), "[%i]",
++ chan_pcal_info[i].pcdac_x3[c]);
++ printf("%6s |", buf);
++ }
++ printf(" |\n");
++
++ }
++ printf("\\======================================================================/\n");
++}
++
++static void dump_rate_calinfo_for_mode(int mode, struct ath5k_eeprom_info *ee)
++{
++ int i;
++ struct ath5k_rate_pcal_info *rate_pcal_info;
++ u_int16_t rate_target_pwr_num;
++
++ switch (mode) {
++ case AR5K_EEPROM_MODE_11A:
++ rate_pcal_info = ee->ee_rate_tpwr_a;
++ rate_target_pwr_num = ee->ee_rate_target_pwr_num_a;
++ break;
++ case AR5K_EEPROM_MODE_11B:
++ rate_pcal_info = ee->ee_rate_tpwr_b;
++ rate_target_pwr_num = ee->ee_rate_target_pwr_num_b;
++ break;
++ case AR5K_EEPROM_MODE_11G:
++ rate_pcal_info = ee->ee_rate_tpwr_g;
++ rate_target_pwr_num = ee->ee_rate_target_pwr_num_g;
++ break;
++ default:
++ return;
++ }
++
++ printf("/============== Per rate power calibration ===========\\\n");
++ if (mode == AR5K_EEPROM_MODE_11B)
++ printf("| Freq | 1Mbit/s | 2Mbit/s | 5.5Mbit/s | 11Mbit/s |\n");
++ else
++ printf("| Freq | 6-24Mbit/s | 36Mbit/s | 48Mbit/s | 54Mbit/s |\n");
++
++ for (i = 0; i < rate_target_pwr_num; i++) {
++
++ printf("|======|============|==========|===========|==========|\n");
++ printf("| %4i |", rate_pcal_info[i].freq);
++ printf(" %2i.%02i |",rate_pcal_info[i].target_power_6to24 /2,
++ rate_pcal_info[i].target_power_6to24 % 2);
++ printf(" %2i.%02i |",rate_pcal_info[i].target_power_36 /2,
++ rate_pcal_info[i].target_power_36 % 2);
++ printf(" %2i.%02i |",rate_pcal_info[i].target_power_48 /2,
++ rate_pcal_info[i].target_power_48 % 2);
++ printf(" %2i.%02i |\n",rate_pcal_info[i].target_power_54 /2,
++ rate_pcal_info[i].target_power_54 % 2);
++ }
++ printf("\\=====================================================/\n");
++}
++
++static u_int32_t extend_tu(u_int32_t base_tu, u_int32_t val, u_int32_t mask)
++{
++ u_int32_t result;
++
++ result = (base_tu & ~mask) | (val & mask);
++ if ((base_tu & mask) > (val & mask))
++ result += mask + 1;
++ return result;
++}
++
++static void dump_timers_register(void *mem, u_int16_t mac_version)
++{
++#define AR5K_TIMER0_5210 0x802c /* next TBTT */
++#define AR5K_TIMER0_5211 0x8028
++#define AR5K_TIMER0 (mac_version == AR5K_SREV_MAC_AR5210 ? \
++ AR5K_TIMER0_5210 : AR5K_TIMER0_5211)
++
++#define AR5K_TIMER1_5210 0x8030 /* next DMA beacon */
++#define AR5K_TIMER1_5211 0x802c
++#define AR5K_TIMER1 (mac_version == AR5K_SREV_MAC_AR5210 ? \
++ AR5K_TIMER1_5210 : AR5K_TIMER1_5211)
++
++#define AR5K_TIMER2_5210 0x8034 /* next SWBA interrupt */
++#define AR5K_TIMER2_5211 0x8030
++#define AR5K_TIMER2 (mac_version == AR5K_SREV_MAC_AR5210 ? \
++ AR5K_TIMER2_5210 : AR5K_TIMER2_5211)
++
++#define AR5K_TIMER3_5210 0x8038 /* next ATIM window */
++#define AR5K_TIMER3_5211 0x8034
++#define AR5K_TIMER3 (mac_version == AR5K_SREV_MAC_AR5210 ? \
++ AR5K_TIMER3_5210 : AR5K_TIMER3_5211)
++
++#define AR5K_TSF_L32_5210 0x806c /* TSF (lower 32 bits) */
++#define AR5K_TSF_L32_5211 0x804c
++#define AR5K_TSF_L32 (mac_version == AR5K_SREV_MAC_AR5210 ? \
++ AR5K_TSF_L32_5210 : AR5K_TSF_L32_5211)
++
++#define AR5K_TSF_U32_5210 0x8070
++#define AR5K_TSF_U32_5211 0x8050
++#define AR5K_TSF_U32 (mac_version == AR5K_SREV_MAC_AR5210 ? \
++ AR5K_TSF_U32_5210 : AR5K_TSF_U32_5211)
++
++#define AR5K_BEACON_5210 0x8024
++#define AR5K_BEACON_5211 0x8020
++#define AR5K_BEACON (mac_version == AR5K_SREV_MAC_AR5210 ? \
++ AR5K_BEACON_5210 : AR5K_BEACON_5211)
++
++#define AR5K_LAST_TSTP 0x8080
++
++ const int timer_mask = 0xffff;
++
++ u_int32_t timer0, timer1, timer2, timer3, now_tu;
++ u_int32_t timer0_tu, timer1_tu, timer2_tu, timer3_tu;
++ u_int64_t now_tsf;
++
++ timer0 = AR5K_REG_READ(AR5K_TIMER0); /* 0x0000ffff */
++ timer1 = AR5K_REG_READ(AR5K_TIMER1_5211); /* 0x0007ffff */
++ timer2 = AR5K_REG_READ(AR5K_TIMER2_5211); /* 0x?1ffffff */
++ timer3 = AR5K_REG_READ(AR5K_TIMER3_5211); /* 0x0000ffff */
++
++ now_tsf = ((u_int64_t)AR5K_REG_READ(AR5K_TSF_U32_5211) << 32)
++ | (u_int64_t)AR5K_REG_READ(AR5K_TSF_L32_5211);
++
++ now_tu = now_tsf >> 10;
++
++ timer0_tu = extend_tu(now_tu, timer0, 0xffff);
++ printf("TIMER0: 0x%08x, TBTT: %5u, TU: 0x%08x\n", timer0,
++ timer0 & timer_mask, timer0_tu);
++ timer1_tu = extend_tu(now_tu, timer1 >> 3, 0x7ffff >> 3);
++ printf("TIMER1: 0x%08x, DMAb: %5u, TU: 0x%08x (%+d)\n", timer1,
++ (timer1 >> 3) & timer_mask, timer1_tu, timer1_tu - timer0_tu);
++ timer2_tu = extend_tu(now_tu, timer2 >> 3, 0x1ffffff >> 3);
++ printf("TIMER2: 0x%08x, SWBA: %5u, TU: 0x%08x (%+d)\n", timer2,
++ (timer2 >> 3) & timer_mask, timer2_tu, timer2_tu - timer0_tu);
++ timer3_tu = extend_tu(now_tu, timer3, 0xffff);
++ printf("TIMER3: 0x%08x, ATIM: %5u, TU: 0x%08x (%+d)\n", timer3,
++ timer3 & timer_mask, timer3_tu, timer3_tu - timer0_tu);
++ printf("TSF: 0x%016llx, TSFTU: %5u, TU: 0x%08x\n",
++ (unsigned long long)now_tsf, now_tu & timer_mask, now_tu);
++
++ printf("BEACON: 0x%08x\n", AR5K_REG_READ(AR5K_BEACON));
++ printf("LAST_TSTP: 0x%08x\n", AR5K_REG_READ(AR5K_LAST_TSTP));
++}
++
++#define AR5K_KEYTABLE_0_5210 0x9000
++#define AR5K_KEYTABLE_0_5211 0x8800
++#define AR5K_KEYTABLE_0 (mac_version == AR5K_SREV_MAC_AR5210 ? \
++ AR5K_KEYTABLE_0_5210 : \
++ AR5K_KEYTABLE_0_5211)
++
++#define AR5K_KEYTABLE(_n) (AR5K_KEYTABLE_0_5211 + ((_n) << 5))
++#define AR5K_KEYTABLE_OFF(_n, x) (AR5K_KEYTABLE(_n) + ((x) << 2))
++#define AR5K_KEYTABLE_VALID 0x00008000
++
++#define AR5K_KEYTABLE_SIZE_5210 64
++#define AR5K_KEYTABLE_SIZE_5211 128
++#define AR5K_KEYTABLE_SIZE (mac_version == AR5K_SREV_MAC_AR5210 ? \
++ AR5K_KEYTABLE_SIZE_5210 : \
++ AR5K_KEYTABLE_SIZE_5211)
++
++static void keycache_dump(void *mem, u_int16_t mac_version)
++{
++ int i, keylen;
++ u_int32_t val0, val1, val2, val3, val4, keytype, ant, mac0, mac1;
++
++ /* dump all 128 entries */
++ printf("Dumping keycache entries...\n");
++ for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) {
++ mac1 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 7));
++ if (mac1 & AR5K_KEYTABLE_VALID) {
++ val0 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 0));
++ val1 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 1));
++ val2 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 2));
++ val3 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 3));
++ val4 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 4));
++ keytype = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 5));
++ ant = keytype & 8;
++ keytype &= ~8;
++ switch (keytype) {
++ case 0: /* WEP40 */ keylen = 40 / 8; break;
++ case 1: /* WEP104 */ keylen = 104 / 8; break;
++ case 3: /* WEP128 */ keylen = 128 / 8; break;
++ case 4: /* TKIP */ keylen = 128 / 8; break;
++ case 5: /* AES */ keylen = 128 / 8; break;
++ case 6: /* CCM */ keylen = 128 / 8; break;
++ default: keylen = 0; break;
++ }
++ mac0 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 6));
++
++ printf("[%3u] keytype %d [%s%s%s%s%s%s%s%s] mac %02x:%02x:%02x:%02x:%02x:%02x key:%08x-%08x-%08x-%08x-%08x\n",
++ i,
++ keytype,
++ keytype == 0 ? "WEP40 " : "",
++ keytype == 1 ? "WEP104" : "",
++ keytype == 3 ? "WEP128" : "",
++ keytype == 4 ? "TKIP " : "",
++ keytype == 5 ? "AES " : "",
++ keytype == 6 ? "CCM " : "",
++ keytype == 7 ? "NULL " : "",
++ ant == 8 ? "+ANT" : "",
++ ((mac0 << 1) & 0xff),
++ ((mac0 >> 7) & 0xff),
++ ((mac0 >> 15) & 0xff),
++ ((mac0 >> 23) & 0xff),
++ ((mac1 << 1) & 0xff) | (mac0 >> 31),
++ ((mac1 >> 7) & 0xff),
++ val0, val1, val2, val3, val4);
++ }
++ }
++}
++
++/* copy key index (0) to key index (idx) */
++
++static void keycache_copy(void *mem, u_int16_t mac_version, int idx)
++{
++ u_int32_t val0, val1, val2, val3, val4, keytype, mac0, mac1;
++
++ printf("Copying keycache entry 0 to %d\n", idx);
++ if (idx < 0 || idx >= AR5K_KEYTABLE_SIZE) {
++ printf("invalid keycache index\n");
++ return;
++ }
++
++ val0 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 0));
++ val1 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 1));
++ val2 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 2));
++ val3 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 3));
++ val4 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 4));
++ keytype = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 5));
++ mac0 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 6));
++ mac1 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 7));
++
++ AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 0), val0);
++ AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 1), val1);
++ AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 2), val2);
++ AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 3), val3);
++ AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 4), val4);
++ AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 5), keytype);
++ AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 6), mac0);
++ AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 7), mac1);
++}
++
++static void sta_id0_id1_dump(void *mem)
++{
++#define AR5K_STA_ID0 0x8000
++#define AR5K_STA_ID1 0x8004
++#define AR5K_STA_ID1_AP 0x00010000
++#define AR5K_STA_ID1_ADHOC 0x00020000
++#define AR5K_STA_ID1_NO_KEYSRCH 0x00080000
++
++ u_int32_t sta_id0, sta_id1;
++
++ sta_id0 = AR5K_REG_READ(AR5K_STA_ID0);
++ sta_id1 = AR5K_REG_READ(AR5K_STA_ID1);
++ printf("STA_ID0: %02x:%02x:%02x:%02x:%02x:%02x\n",
++ (sta_id0 >> 0) & 0xff,
++ (sta_id0 >> 8) & 0xff,
++ (sta_id0 >> 16) & 0xff,
++ (sta_id0 >> 24) & 0xff,
++ (sta_id1 >> 0) & 0xff,
++ (sta_id1 >> 8) & 0xff);
++ printf("STA_ID1: 0x%08x, AP: %d, IBSS: %d, KeyCache Disable: %d\n",
++ sta_id1,
++ sta_id1 & AR5K_STA_ID1_AP ? 1 : 0,
++ sta_id1 & AR5K_STA_ID1_ADHOC ? 1 : 0,
++ sta_id1 & AR5K_STA_ID1_NO_KEYSRCH ? 1 : 0);
++}
++
+ int
+ CMD(athinfo)(int argc, char *argv[])
+ {
+- u_int32_t dev_addr;
+- u_int16_t eeprom_header, srev, phy_rev_5ghz, phy_rev_2ghz;
+- u_int16_t eeprom_version, mac_version, regdomain, has_crystal, ee_magic;
+- u_int8_t error, has_a, has_b, has_g, has_rfkill, eeprom_size;
+- int byte_size = 0;
++ unsigned long long dev_addr;
++ u_int16_t srev, phy_rev_5ghz, phy_rev_2ghz, ee_magic;
++ u_int8_t mac_version, mac_revision;
++ u_int8_t error, eeprom_size, dev_type, eemap;
++ struct ath5k_eeprom_info *ee;
++ unsigned int byte_size = 0;
+ void *mem;
+ int fd;
+- int i, anr = 1;
++ unsigned int i;
++ int anr = 1;
+ int do_write = 0; /* default: read only */
+ int do_dump = 0;
++ int reg_read = 0;
++ int reg_write = 0;
++ unsigned int reg_write_val = 0;
++ unsigned int timer_count = 1;
++ int do_keycache_dump = 0;
++ int keycache_copy_idx = 0;
+
+ struct {
+ int valid;
+@@ -759,7 +1986,7 @@ CMD(athinfo)(int argc, char *argv[])
+ } gpio_set[AR5K_NUM_GPIO];
+ int nr_gpio_set = 0;
+
+- for (i = 0; i < sizeof(gpio_set) / sizeof(gpio_set[0]); i++)
++ for (i = 0; i < ARRAY_SIZE(gpio_set); i++)
+ gpio_set[i].valid = 0;
+
+ if (argc < 2) {
+@@ -769,6 +1996,15 @@ CMD(athinfo)(int argc, char *argv[])
+
+ while (anr < argc && argv[anr][0] == '-') {
+ switch (argv[anr][1]) {
++ case 't':
++ if (++anr < argc) {
++ timer_count = atoi(argv[anr]);
++ printf("timer_count:%d\n", timer_count);
++ } else {
++ usage(argv[0]);
++ return 0;
++ }
++ break;
+ case 'w':
+ do_write = 1;
+ break;
+@@ -777,7 +2013,7 @@ CMD(athinfo)(int argc, char *argv[])
+ if (strlen(argv[anr]) != 3 || argv[anr][1] != ':' ||
+ argv[anr][0] < '0' || argv[anr][0] > '5' ||
+ (argv[anr][2] != '0' && argv[anr][2] != '1')) {
+- err("invalid gpio spec. %s", argv[anr]);
++ err("invalid GPIO spec. %s", argv[anr]);
+ return 2;
+ }
+ gpio_set[argv[anr][0] - '0'].valid = 1;
+@@ -797,6 +2033,25 @@ CMD(athinfo)(int argc, char *argv[])
+ do_dump = 1;
+ break;
+
++ case 'R':
++ anr++;
++ reg_read = strtoul(argv[anr], NULL, 16);
++ break;
++
++ case 'W':
++ anr++;
++ reg_write = strtoul(argv[anr++], NULL, 16);
++ reg_write_val = strtoul(argv[anr], NULL, 16);
++ break;
++
++ case 'k':
++ do_keycache_dump = 1;
++ break;
++
++ case 'K':
++ keycache_copy_idx = atoi(argv[++anr]);
++ break;
++
+ case 'h':
+ usage(argv[0]);
+ return 0;
+@@ -805,10 +2060,10 @@ CMD(athinfo)(int argc, char *argv[])
+ default:
+ err("unknown option %s", argv[anr]);
+ return 2;
+- } /* switch (argv[anr][1]) */
++ }
+
+ anr++;
+- } /* while (anr < argc && ...) */
++ }
+
+ if (anr >= argc) {
+ err("missing device address");
+@@ -816,7 +2071,7 @@ CMD(athinfo)(int argc, char *argv[])
+ return 3;
+ }
+
+- dev_addr = strtoul(argv[anr], NULL, 16);
++ dev_addr = strtoull(argv[anr], NULL, 16);
+
+ fd = open("/dev/mem", O_RDWR);
+ if (fd < 0) {
+@@ -828,7 +2083,7 @@ CMD(athinfo)(int argc, char *argv[])
+ MAP_SHARED | MAP_FILE, fd, dev_addr);
+
+ if (mem == MAP_FAILED) {
+- printf("Mmap of device at 0x%08X for 0x%X bytes failed - "
++ printf("mmap of device at 0x%08llX for 0x%X bytes failed - "
+ "%s\n", dev_addr, AR5K_PCI_MEM_SIZE, strerror(errno));
+ return -3;
+ }
+@@ -856,10 +2111,31 @@ CMD(athinfo)(int argc, char *argv[])
+ AR5K_REG_DISABLE_BITS(AR5K_PCICFG, AR5K_PCICFG_SPWR_DN);
+ usleep(500);
+
++ if (reg_read) {
++ printf("READ %04x = %08x\n", reg_read, AR5K_REG_READ(reg_read));
++ return 0;
++ }
++
++ if (reg_write) {
++ printf("WRITE %04x = %08x\n", reg_write, reg_write_val);
++ AR5K_REG_WRITE(reg_write, reg_write_val);
++ return 0;
++ }
++
+ srev = AR5K_REG_READ(AR5K_SREV);
+- mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER) << 4;
++ if (srev >= 0x0100) {
++ printf("MAC revision 0x%04x is not supported!\n", srev);
++ return -1;
++ }
++ mac_version = srev & AR5K_SREV_VER;
++ mac_revision = srev & AR5K_SREV_REV;
+
+- /* Verify eeprom magic value first */
++ printf(" -==Device Information==-\n");
++
++ printf("MAC Revision: %-5s (0x%02x)\n",
++ ath5k_hw_get_mac_name(mac_revision), mac_revision);
++
++ /* Verify EEPROM magic value first */
+ error = ath5k_hw_eeprom_read(mem, AR5K_EEPROM_MAGIC, &ee_magic,
+ mac_version);
+
+@@ -872,157 +2148,114 @@ CMD(athinfo)(int argc, char *argv[])
+ printf("Warning: Invalid EEPROM Magic number!\n");
+ }
+
+- error = ath5k_hw_eeprom_read(mem, AR5K_EEPROM_HDR, &eeprom_header,
+- mac_version);
+-
+- if (error) {
+- printf("Unable to read EEPROM Header!\n");
+- return -1;
+- }
+-
+- error = ath5k_hw_eeprom_read(mem, AR5K_EEPROM_VERSION, &eeprom_version,
+- mac_version);
+-
+- if (error) {
+- printf("Unable to read EEPROM version!\n");
++ ee = calloc(sizeof(struct ath5k_eeprom_info), 1);
++ if (!ee) {
++ printf("Cannot allocate memory for EEPROM information\n");
+ return -1;
+ }
+
+- error = ath5k_hw_eeprom_read(mem, AR5K_EEPROM_REG_DOMAIN, &regdomain,
+- mac_version);
+-
+- if (error) {
+- printf("Unable to read Regdomain!\n");
++ if (ath5k_eeprom_init(mem, mac_version, ee)) {
++ printf("EEPROM init failed\n");
+ return -1;
+ }
+
+- if (eeprom_version >= 0x4000) {
+- error = ath5k_hw_eeprom_read(mem, AR5K_EEPROM_MISC0,
+- &has_crystal, mac_version);
+-
+- if (error) {
+- printf("Unable to read EEPROM Misc data!\n");
+- return -1;
+- }
+-
+- has_crystal = AR5K_EEPROM_HAS32KHZCRYSTAL(has_crystal);
+- } else {
+- has_crystal = 2;
+- }
+-
+ eeprom_size = AR5K_REG_MS(AR5K_REG_READ(AR5K_PCICFG),
+ AR5K_PCICFG_EESIZE);
+
+- has_a = AR5K_EEPROM_HDR_11A(eeprom_header);
+- has_b = AR5K_EEPROM_HDR_11B(eeprom_header);
+- has_g = AR5K_EEPROM_HDR_11G(eeprom_header);
+- has_rfkill = AR5K_EEPROM_HDR_RFKILL(eeprom_header);
++ dev_type = AR5K_EEPROM_HDR_DEVICE(ee->ee_header);
++ eemap = AR5K_EEPROM_EEMAP(ee->ee_misc0);
+
+- if (has_a)
++ /* 1 = ?? 2 = ?? 3 = card 4 = wmac */
++ printf("Device type: %1i\n", dev_type);
++
++ if (AR5K_EEPROM_HDR_11A(ee->ee_header))
+ phy_rev_5ghz = ath5k_hw_radio_revision(mac_version, mem, 1);
+ else
+ phy_rev_5ghz = 0;
+
+- if (has_b)
++ if (AR5K_EEPROM_HDR_11B(ee->ee_header))
+ phy_rev_2ghz = ath5k_hw_radio_revision(mac_version, mem, 0);
+ else
+ phy_rev_2ghz = 0;
+
+- printf(" -==Device Information==-\n");
+-
+- printf("MAC Version: %-5s (0x%02x)\n",
+- ath5k_hw_get_part_name(AR5K_VERSION_VER, mac_version),
+- mac_version);
+-
+- printf("MAC Revision: %-5s (0x%02x)\n",
+- ath5k_hw_get_part_name(AR5K_VERSION_VER, srev), srev);
+-
+- /* Single-chip PHY with a/b/g support */
+- if (has_b && !phy_rev_2ghz) {
+- printf("PHY Revision: %-5s (0x%02x)\n",
+- ath5k_hw_get_part_name(AR5K_VERSION_RAD, phy_rev_5ghz),
+- phy_rev_5ghz);
+- phy_rev_5ghz = 0;
+- }
+-
+- /* Single-chip PHY with b/g support */
+- if (!has_a) {
+- printf("PHY Revision: %-5s (0x%02x)\n",
+- ath5k_hw_get_part_name(AR5K_VERSION_RAD, phy_rev_2ghz),
+- phy_rev_2ghz);
+- phy_rev_2ghz = 0;
+- }
+-
+- /* Different chip for 5Ghz and 2Ghz */
+ if (phy_rev_5ghz) {
+- printf("5Ghz PHY Revision: %-5s (0x%2x)\n",
+- ath5k_hw_get_part_name(AR5K_VERSION_RAD, phy_rev_5ghz),
+- phy_rev_5ghz);
++ printf("5GHz PHY Revision: %-5s (0x%02x)\n",
++ ath5k_hw_get_phy_name(phy_rev_5ghz), phy_rev_5ghz);
+ }
+ if (phy_rev_2ghz) {
+- printf("2Ghz PHY Revision: %-5s (0x%2x)\n",
+- ath5k_hw_get_part_name(AR5K_VERSION_RAD, phy_rev_2ghz),
+- phy_rev_2ghz);
++ printf("2GHz PHY Revision: %-5s (0x%02x)\n",
++ ath5k_hw_get_phy_name(phy_rev_2ghz), phy_rev_2ghz);
+ }
+
+- printf(" -==EEPROM Information==-\n");
+-
+- printf("EEPROM Version: %x.%x\n",
+- (eeprom_version & 0xF000) >> 12, eeprom_version & 0xFFF);
++ printf("\n");
++ printf("/============== EEPROM Information =============\\\n");
++ printf("| EEPROM Version: %1x.%1x |",
++ (ee->ee_version & 0xF000) >> 12, ee->ee_version & 0xFFF);
+
+- printf("EEPROM Size: ");
++ printf(" EEPROM Size: ");
+
+ if (eeprom_size == 0) {
+- printf(" 4K\n");
+- byte_size = 4096;
++ printf(" 4 kbit |\n");
++ byte_size = 4096 / 8;
+ } else if (eeprom_size == 1) {
+- printf(" 8K\n");
+- byte_size = 8192;
++ printf(" 8 kbit |\n");
++ byte_size = 8192 / 8;
+ } else if (eeprom_size == 2) {
+- printf(" 16K\n");
+- byte_size = 16384;
++ printf(" 16 kbit |\n");
++ byte_size = 16384 / 8;
+ } else
+- printf(" ??\n");
++ printf(" unknown |\n");
+
+- printf("Regulatory Domain: 0x%X\n", regdomain);
+-
+- printf(" -==== Capabilities ====-\n");
+-
+- printf("| 802.11a Support: ");
+- if (has_a)
+- printf("yes |\n");
+- else
+- printf("no |\n");
+-
+- printf("| 802.11b Support: ");
+- if (has_b)
+- printf("yes |\n");
+- else
+- printf("no |\n");
++ printf("| EEMAP: %i |", eemap);
+
+- printf("| 802.11g Support: ");
+- if (has_g)
+- printf("yes |\n");
+- else
+- printf("no |\n");
++ printf(" Reg. Domain: 0x%02X |\n", ee->ee_regdomain);
+
+- printf("| RFKill Support: ");
+- if (has_rfkill)
+- printf("yes |\n");
+- else
+- printf("no |\n");
++ dump_capabilities(ee);
++ printf("\n");
+
+- if (has_crystal != 2) {
+- printf("| 32KHz Crystal: ");
+- if (has_crystal)
+- printf("yes |\n");
+- else
+- printf("no |\n");
++ printf("/=========================================================\\\n");
++ printf("| Calibration data common for all modes |\n");
++ printf("|=========================================================|\n");
++ printf("| CCK/OFDM gain delta: %2i |\n", ee->ee_cck_ofdm_gain_delta);
++ printf("| CCK/OFDM power delta: %2i |\n", ee->ee_cck_ofdm_power_delta);
++ printf("| Scaled CCK delta: %2i |\n", ee->ee_scaled_cck_delta);
++ printf("| 2GHz Antenna gain: %2i |\n", AR5K_EEPROM_ANT_GAIN_2GHZ(ee->ee_ant_gain));
++ printf("| 5GHz Antenna gain: %2i |\n", AR5K_EEPROM_ANT_GAIN_5GHZ(ee->ee_ant_gain));
++ printf("| Turbo 2W maximum dBm: %2i |\n", AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header));
++ printf("| Target power start: 0x%03x |\n", AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1));
++ printf("| EAR Start: 0x%03x |\n", AR5K_EEPROM_EARSTART(ee->ee_misc0));
++ printf("\\=========================================================/\n");
++
++ printf("\n");
++ if (AR5K_EEPROM_HDR_11A(ee->ee_header)) {
++ printf("/=========================================================\\\n");
++ printf("| Calibration data for 802.11a operation |\n");
++ dump_calinfo_for_mode(AR5K_EEPROM_MODE_11A, ee);
++ dump_rate_calinfo_for_mode(AR5K_EEPROM_MODE_11A, ee);
++ dump_power_calinfo_for_mode(AR5K_EEPROM_MODE_11A, ee);
++ printf("\n");
++ }
++
++ if (AR5K_EEPROM_HDR_11B(ee->ee_header)) {
++ printf("/=========================================================\\\n");
++ printf("| Calibration data for 802.11b operation |\n");
++ dump_calinfo_for_mode(AR5K_EEPROM_MODE_11B, ee);
++ dump_rate_calinfo_for_mode(AR5K_EEPROM_MODE_11B, ee);
++ dump_power_calinfo_for_mode(AR5K_EEPROM_MODE_11B, ee);
++ printf("\n");
++ }
++
++ if (AR5K_EEPROM_HDR_11G(ee->ee_header)) {
++ printf("/=========================================================\\\n");
++ printf("| Calibration data for 802.11g operation |\n");
++ dump_calinfo_for_mode(AR5K_EEPROM_MODE_11G, ee);
++ dump_rate_calinfo_for_mode(AR5K_EEPROM_MODE_11G, ee);
++ dump_power_calinfo_for_mode(AR5K_EEPROM_MODE_11G, ee);
++ printf("\n");
+ }
+- printf(" ========================\n");
+
+ /* print current GPIO settings */
+- printf("GPIO registers: CR %08x DO %08x DI %08x\n",
++ printf("GPIO registers: CR 0x%08x, DO 0x%08x, DI 0x%08x\n",
+ AR5K_REG_READ(AR5K_GPIOCR), AR5K_REG_READ(AR5K_GPIODO),
+ AR5K_REG_READ(AR5K_GPIODI));
+
+@@ -1030,18 +2263,18 @@ CMD(athinfo)(int argc, char *argv[])
+ u_int16_t data;
+ FILE *dumpfile = fopen("ath-eeprom-dump.bin", "w");
+
+- printf("\nEEPROM dump (%d byte)\n", byte_size);
++ printf("\nEEPROM dump (%d bytes)\n", byte_size);
+ printf("==============================================");
+- for (i = 1; i <= (byte_size / 2); i++) {
++ for (i = 0; i < byte_size / 2; i++) {
+ error =
+ ath5k_hw_eeprom_read(mem, i, &data, mac_version);
+ if (error) {
+ printf("\nUnable to read at %04x\n", i);
+ continue;
+ }
+- if (!((i - 1) % 8))
+- printf("\n%04x: ", i);
+- printf("%04x ", data);
++ if (!(i % 8))
++ printf("\n%04x: ", i);
++ printf(" %04x", data);
+ fwrite(&data, 2, 1, dumpfile);
+ }
+ printf("\n==============================================\n");
+@@ -1054,18 +2287,18 @@ CMD(athinfo)(int argc, char *argv[])
+ u_int32_t old_cr = rcr, old_do = rdo;
+ int rc;
+
+- if (mac_version >= AR5K_SREV_VER_AR5213 && !nr_gpio_set) {
+- dbg("new MAC %x (>= AR5213) set gpio4 to low",
++ if (mac_version >= AR5K_SREV_MAC_AR5213 && !nr_gpio_set) {
++ dbg("new MAC %x (>= AR5213) set GPIO4 to low",
+ mac_version);
+ gpio_set[4].valid = 1;
+ gpio_set[4].value = 0;
+ }
+
+- /* set gpios */
++ /* set GPIOs */
+ dbg("old GPIO CR %08x DO %08x DI %08x",
+ rcr, rdo, AR5K_REG_READ(AR5K_GPIODI));
+
+- for (i = 0; i < sizeof(gpio_set) / sizeof(gpio_set[0]); i++) {
++ for (i = 0; i < ARRAY_SIZE(gpio_set); i++) {
+ if (gpio_set[i].valid) {
+ rcr |= AR5K_GPIOCR_OUT(i); /* we use mode 3 */
+ rcr &= ~AR5K_GPIOCR_INT_SEL(i);
+@@ -1111,5 +2344,17 @@ CMD(athinfo)(int argc, char *argv[])
+
+ return rc;
+ }
++
++ sta_id0_id1_dump(mem);
++
++ for (i = 0; i < timer_count; i++)
++ dump_timers_register(mem, mac_version);
++
++ if (do_keycache_dump)
++ keycache_dump(mem, mac_version);
++
++ if (keycache_copy_idx > 0)
++ keycache_copy(mem, mac_version, keycache_copy_idx);
++
+ return 0;
+ }
diff --git a/package/madwifi/patches/408-changeset_r3337.patch b/package/madwifi/patches/408-changeset_r3337.patch
new file mode 100644
index 000000000..53e76a9e8
--- /dev/null
+++ b/package/madwifi/patches/408-changeset_r3337.patch
@@ -0,0 +1,34 @@
+--- a/THANKS
++++ b/THANKS
+@@ -129,6 +129,7 @@ Derek J Smithies
+ jhansen
+ Benoit Papillault
+ Russell Harmon
++Alessandro Erta
+
+ Apologies to anyone whose name was unintentionally left off.
+ Please let us know if you think your name should be mentioned here!
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -3147,7 +3147,7 @@ ath_tx_startraw(struct net_device *dev,
+ struct ath_softc *sc = dev->priv;
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211_phy_params *ph = (struct ieee80211_phy_params *)
+- (SKB_CB(skb) + sizeof(struct ieee80211_cb));
++ (SKB_CB(skb) + 1); /* NB: SKB_CB casts to CB struct*. */
+ const HAL_RATE_TABLE *rt;
+ unsigned int pktlen, hdrlen, try0, power;
+ HAL_PKT_TYPE atype;
+--- a/net80211/ieee80211_monitor.c
++++ b/net80211/ieee80211_monitor.c
+@@ -128,8 +128,8 @@ struct ar5212_openbsd_desc {
+ void
+ ieee80211_monitor_encap(struct ieee80211vap *vap, struct sk_buff *skb)
+ {
+- struct ieee80211_phy_params *ph =
+- (struct ieee80211_phy_params *) (SKB_CB(skb) + sizeof(struct ieee80211_cb));
++ struct ieee80211_phy_params *ph = (struct ieee80211_phy_params *)
++ (SKB_CB(skb) + 1); /* NB: SKB_CB casts to CB struct*. */
+ SKB_CB(skb)->flags = M_RAW;
+ SKB_CB(skb)->ni = NULL;
+ SKB_CB(skb)->next = NULL;
diff --git a/package/madwifi/patches/409-wext_compat.patch b/package/madwifi/patches/409-wext_compat.patch
new file mode 100644
index 000000000..449709232
--- /dev/null
+++ b/package/madwifi/patches/409-wext_compat.patch
@@ -0,0 +1,133 @@
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -73,6 +73,13 @@
+ (_vap)->iv_ic->ic_roaming == IEEE80211_ROAMING_AUTO)
+ #define RESCAN 1
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
++#define IWE(func, ...) func(&iweinfo, __VA_ARGS__)
++static struct iw_request_info iweinfo = { 0, 0 };
++#else
++#define IWE(func, ...) func(__VA_ARGS__)
++#endif
++
+ static void
+ pre_announced_chanswitch(struct net_device *dev, u_int32_t channel, u_int32_t tbtt);
+
+@@ -1800,7 +1807,7 @@ giwscan_cb(void *arg, const struct ieee8
+ IEEE80211_ADDR_COPY(iwe.u.ap_addr.sa_data, se->se_macaddr);
+ else
+ IEEE80211_ADDR_COPY(iwe.u.ap_addr.sa_data, se->se_bssid);
+- current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
++ current_ev = IWE(iwe_stream_add_event, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
+
+ /* We ran out of space in the buffer. */
+ if (last_ev == current_ev)
+@@ -1811,7 +1818,7 @@ giwscan_cb(void *arg, const struct ieee8
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+ iwe.u.data.length = se->se_ssid[1];
+- current_ev = iwe_stream_add_point(current_ev,
++ current_ev = IWE(iwe_stream_add_point, current_ev,
+ end_buf, &iwe, (char *) se->se_ssid+2);
+
+ /* We ran out of space in the buffer. */
+@@ -1824,7 +1831,7 @@ giwscan_cb(void *arg, const struct ieee8
+ iwe.cmd = SIOCGIWMODE;
+ iwe.u.mode = se->se_capinfo & IEEE80211_CAPINFO_ESS ?
+ IW_MODE_MASTER : IW_MODE_ADHOC;
+- current_ev = iwe_stream_add_event(current_ev,
++ current_ev = IWE(iwe_stream_add_event, current_ev,
+ end_buf, &iwe, IW_EV_UINT_LEN);
+
+ /* We ran out of space in the buffer. */
+@@ -1837,7 +1844,7 @@ giwscan_cb(void *arg, const struct ieee8
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = se->se_chan->ic_freq * 100000;
+ iwe.u.freq.e = 1;
+- current_ev = iwe_stream_add_event(current_ev,
++ current_ev = IWE(iwe_stream_add_event, current_ev,
+ end_buf, &iwe, IW_EV_FREQ_LEN);
+
+ /* We ran out of space in the buffer. */
+@@ -1848,7 +1855,7 @@ giwscan_cb(void *arg, const struct ieee8
+ last_ev = current_ev;
+ iwe.cmd = IWEVQUAL;
+ set_quality(&iwe.u.qual, se->se_rssi, ATH_DEFAULT_NOISE);
+- current_ev = iwe_stream_add_event(current_ev,
++ current_ev = IWE(iwe_stream_add_event, current_ev,
+ end_buf, &iwe, IW_EV_QUAL_LEN);
+
+ /* We ran out of space in the buffer */
+@@ -1863,7 +1870,7 @@ giwscan_cb(void *arg, const struct ieee8
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ iwe.u.data.length = 0;
+- current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, "");
++ current_ev = IWE(iwe_stream_add_point, current_ev, end_buf, &iwe, "");
+
+ /* We ran out of space in the buffer. */
+ if (last_ev == current_ev)
+@@ -1878,7 +1885,7 @@ giwscan_cb(void *arg, const struct ieee8
+ int r = se->se_rates[2 + j] & IEEE80211_RATE_VAL;
+ if (r != 0) {
+ iwe.u.bitrate.value = r * (1000000 / 2);
+- current_val = iwe_stream_add_value(current_ev,
++ current_val = IWE(iwe_stream_add_value, current_ev,
+ current_val, end_buf, &iwe,
+ IW_EV_PARAM_LEN);
+ }
+@@ -1887,7 +1894,7 @@ giwscan_cb(void *arg, const struct ieee8
+ int r = se->se_xrates[2+j] & IEEE80211_RATE_VAL;
+ if (r != 0) {
+ iwe.u.bitrate.value = r * (1000000 / 2);
+- current_val = iwe_stream_add_value(current_ev,
++ current_val = IWE(iwe_stream_add_value, current_ev,
+ current_val, end_buf, &iwe,
+ IW_EV_PARAM_LEN);
+ }
+@@ -1906,7 +1913,7 @@ giwscan_cb(void *arg, const struct ieee8
+ iwe.cmd = IWEVCUSTOM;
+ snprintf(buf, sizeof(buf), "bcn_int=%d", se->se_intval);
+ iwe.u.data.length = strlen(buf);
+- current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf);
++ current_ev = IWE(iwe_stream_add_point, current_ev, end_buf, &iwe, buf);
+
+ /* We ran out of space in the buffer. */
+ if (last_ev == current_ev)
+@@ -1930,7 +1937,7 @@ giwscan_cb(void *arg, const struct ieee8
+ rsn_leader, sizeof(rsn_leader) - 1);
+ #endif
+ if (iwe.u.data.length != 0) {
+- current_ev = iwe_stream_add_point(current_ev, end_buf,
++ current_ev = IWE(iwe_stream_add_point, current_ev, end_buf,
+ &iwe, buf);
+
+ /* We ran out of space in the buffer */
+@@ -1956,7 +1963,7 @@ giwscan_cb(void *arg, const struct ieee8
+ wpa_leader, sizeof(wpa_leader) - 1);
+ #endif
+ if (iwe.u.data.length != 0) {
+- current_ev = iwe_stream_add_point(current_ev, end_buf,
++ current_ev = IWE(iwe_stream_add_point, current_ev, end_buf,
+ &iwe, buf);
+
+ /* We ran out of space in the buffer. */
+@@ -1975,7 +1982,7 @@ giwscan_cb(void *arg, const struct ieee8
+ se->se_wme_ie, se->se_wme_ie[1] + 2,
+ wme_leader, sizeof(wme_leader) - 1);
+ if (iwe.u.data.length != 0) {
+- current_ev = iwe_stream_add_point(current_ev, end_buf,
++ current_ev = IWE(iwe_stream_add_point, current_ev, end_buf,
+ &iwe, buf);
+
+ /* We ran out of space in the buffer. */
+@@ -1993,7 +2000,7 @@ giwscan_cb(void *arg, const struct ieee8
+ se->se_ath_ie, se->se_ath_ie[1] + 2,
+ ath_leader, sizeof(ath_leader) - 1);
+ if (iwe.u.data.length != 0) {
+- current_ev = iwe_stream_add_point(current_ev, end_buf,
++ current_ev = IWE(iwe_stream_add_point, current_ev, end_buf,
+ &iwe, buf);
+
+ /* We ran out of space in the buffer. */
diff --git a/package/madwifi/patches/410-ar231x_2.6.28.patch b/package/madwifi/patches/410-ar231x_2.6.28.patch
new file mode 100644
index 000000000..30d1c56a4
--- /dev/null
+++ b/package/madwifi/patches/410-ar231x_2.6.28.patch
@@ -0,0 +1,281 @@
+--- a/ath/if_ath_ahb.c
++++ b/ath/if_ath_ahb.c
+@@ -33,20 +33,15 @@
+ #include "if_ath_ahb.h"
+ #include "ah_soc.h"
+
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+-#error "Kernel versions older than 2.6.19 are not supported!"
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
++#include <ar231x_platform.h>
+ #endif
+
+ struct ath_ahb_softc {
+ struct ath_softc aps_sc;
+-#ifdef CONFIG_PM
+- u32 aps_pmstate[16];
+-#endif
++ struct ar531x_config aps_config;
+ };
+
+-static struct ath_ahb_softc *sclist[2] = {NULL, NULL};
+-static u_int8_t num_activesc = 0;
+-
+ /*
+ * Module glue.
+ */
+@@ -101,13 +96,13 @@ ahb_enable_wmac(u_int16_t devid, u_int16
+ while (REG_READ(AR5315_PCI_MAC_PCICFG) & AR5315_PCI_MAC_PCICFG_SPWR_DN);
+ } else {
+ switch (wlanNum) {
+- case AR531X_WLAN0_NUM:
++ case 0:
+ reset = (AR531X_RESET_WLAN0 |
+ AR531X_RESET_WARM_WLAN0_MAC |
+ AR531X_RESET_WARM_WLAN0_BB);
+ enable = AR531X_ENABLE_WLAN0;
+ break;
+- case AR531X_WLAN1_NUM:
++ case 1:
+ reset = (AR531X_RESET_WLAN1 |
+ AR531X_RESET_WARM_WLAN1_MAC |
+ AR531X_RESET_WARM_WLAN1_BB);
+@@ -144,10 +139,10 @@ ahb_disable_wmac(u_int16_t devid, u_int1
+ *en &= ~AR5315_ARB_WLAN;
+ } else {
+ switch (wlanNum) {
+- case AR531X_WLAN0_NUM:
++ case 0:
+ enable = AR531X_ENABLE_WLAN0;
+ break;
+- case AR531X_WLAN1_NUM:
++ case 1:
+ enable = AR531X_ENABLE_WLAN1;
+ break;
+ default:
+@@ -159,29 +154,6 @@ ahb_disable_wmac(u_int16_t devid, u_int1
+ }
+
+
+-static int
+-exit_ath_wmac(u_int16_t wlanNum, struct ar531x_config *config)
+-{
+- struct ath_ahb_softc *sc = sclist[wlanNum];
+- struct net_device *dev;
+- u_int16_t devid;
+-
+- if (sc == NULL)
+- return -ENODEV; /* XXX: correct return value? */
+-
+- dev = sc->aps_sc.sc_dev;
+- ath_detach(dev);
+- if (dev->irq)
+- free_irq(dev->irq, dev);
+- devid = sc->aps_sc.devid;
+- config->tag = (void *)((unsigned long) devid);
+-
+- ahb_disable_wmac(devid, wlanNum);
+- free_netdev(dev);
+- sclist[wlanNum] = NULL;
+- return 0;
+-}
+-
+ static const char ubnt[] = "Ubiquiti Networks";
+ /* { vendorname, cardname, vendorid, cardid, subsys vendorid, subsys id, poweroffset } */
+ static const struct ath_hw_detect cards[] = {
+@@ -201,6 +173,114 @@ static const struct ath_hw_detect cards[
+ { ubnt, "Bullet5", PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0xc205 },
+ };
+
++static void
++ahb_hw_detect(struct ath_ahb_softc *sc, const char *radio)
++{
++ u16 *radio_data = (u16 *) radio;
++ if (radio_data) {
++ u16 vendor, id, subvendor, subid;
++ vendor = radio_data[1];
++ id = radio_data[0];
++ subvendor = radio_data[8];
++ subid = radio_data[7];
++ ath_hw_detect(&sc->aps_sc, cards, ARRAY_SIZE(cards), vendor, id, subvendor, subid);
++ }
++}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
++
++static int ahb_wmac_probe(struct platform_device *pdev)
++{
++ struct ar231x_board_config *bcfg = pdev->dev.platform_data;
++ struct ath_ahb_softc *sc;
++ struct net_device *dev;
++ struct resource *res;
++ const char *athname;
++ int err;
++
++ ahb_enable_wmac(bcfg->devid, pdev->id);
++ dev = alloc_netdev(sizeof(struct ath_ahb_softc), "wifi%d", ether_setup);
++ if (!dev)
++ return -ENOMEM;
++
++ sc = dev->priv;
++ sc->aps_sc.sc_dev = dev;
++
++ dev->irq = platform_get_irq(pdev, 0);
++ if (dev->irq <= 0) {
++ printk("%s: Cannot find IRQ resource\n", dev->name);
++ goto error;
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ printk("%s: Cannot find MMIO resource\n", dev->name);
++ goto error;
++ }
++
++ dev->mem_start = KSEG1ADDR(res->start);
++ dev->mem_end = KSEG1ADDR(res->end);
++ sc->aps_sc.sc_iobase = (void __iomem *) dev->mem_start;
++ sc->aps_sc.sc_bdev = NULL;
++
++ /* bus information for the HAL */
++ sc->aps_config.board = (const struct ar531x_boarddata *) bcfg->config;
++ sc->aps_config.radio = bcfg->radio;
++ sc->aps_config.unit = pdev->id;
++ sc->aps_config.tag = NULL;
++
++ err = ath_attach(bcfg->devid, dev, &sc->aps_config);
++ if (err != 0) {
++ printk("%s: ath_attach failed: %d\n", dev->name, err);
++ goto error;
++ }
++
++ athname = ath_hal_probe(ATHEROS_VENDOR_ID, bcfg->devid);
++ printk(KERN_INFO "%s: %s: %s: mem=0x%lx, irq=%d\n",
++ dev_info, dev->name, athname ? athname : "Atheros ???", dev->mem_start, dev->irq);
++
++ if (request_irq(dev->irq, ath_intr, IRQF_SHARED|IRQF_DISABLED, dev->name, dev)) {
++ printk(KERN_WARNING "%s: %s: request_irq failed\n", dev_info, dev->name);
++ goto error;
++ }
++
++ sc->aps_sc.sc_softled = 1; /* SoftLED over GPIO */
++ sc->aps_sc.sc_ledpin = bcfg->config->sysLedGpio;
++ sc->aps_sc.sc_invalid = 0;
++ ahb_hw_detect(sc, bcfg->radio);
++ platform_set_drvdata(pdev, dev);
++ return 0;
++
++error_dev:
++ free_irq(dev->irq, dev);
++error:
++ free_netdev(dev);
++
++ return -ENODEV;
++}
++
++
++static int ahb_wmac_remove(struct platform_device *pdev)
++{
++ struct ar231x_board_config *bcfg = pdev->dev.platform_data;
++ struct net_device *dev;
++
++ dev = platform_get_drvdata(pdev);
++ ath_detach(dev);
++
++ if (dev->irq)
++ free_irq(dev->irq, dev);
++
++ ahb_disable_wmac(bcfg->devid, pdev->id);
++ free_netdev(dev);
++
++ return 0;
++}
++
++#else
++
++static struct ath_ahb_softc *sclist[2] = {NULL, NULL};
++
+ static int
+ init_ath_wmac(u_int16_t devid, u_int16_t wlanNum, struct ar531x_config *config)
+ {
+@@ -253,7 +333,7 @@ init_ath_wmac(u_int16_t devid, u_int16_t
+ sc->aps_sc.sc_iobase = (void __iomem *) dev->mem_start;
+ sc->aps_sc.sc_bdev = NULL;
+
+- if (request_irq(dev->irq, ath_intr, IRQF_SHARED, dev->name, dev)) {
++ if (request_irq(dev->irq, ath_intr, IRQF_SHARED|IRQF_DISABLED, dev->name, dev)) {
+ printk(KERN_WARNING "%s: %s: request_irq failed\n", dev_info, dev->name);
+ goto bad3;
+ }
+@@ -263,21 +343,12 @@ init_ath_wmac(u_int16_t devid, u_int16_t
+ athname = ath_hal_probe(ATHEROS_VENDOR_ID, devid);
+ printk(KERN_INFO "%s: %s: %s: mem=0x%lx, irq=%d\n",
+ dev_info, dev->name, athname ? athname : "Atheros ???", dev->mem_start, dev->irq);
+- 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;
+- radio_data = (u16 *) config->radio;
+- if (radio_data) {
+- u16 vendor, id, subvendor, subid;
+- vendor = radio_data[1];
+- id = radio_data[0];
+- subvendor = radio_data[8];
+- subid = radio_data[7];
+- ath_hw_detect(&sc->aps_sc, cards, ARRAY_SIZE(cards), vendor, id, subvendor, subid);
+- }
++ ahb_hw_detect(sc, config->radio);
+
+ return 0;
+
+@@ -292,6 +363,29 @@ init_ath_wmac(u_int16_t devid, u_int16_t
+ return -ENODEV;
+ }
+
++static int
++exit_ath_wmac(u_int16_t wlanNum, struct ar531x_config *config)
++{
++ struct ath_ahb_softc *sc = sclist[wlanNum];
++ struct net_device *dev;
++ u_int16_t devid;
++
++ if (sc == NULL)
++ return -ENODEV; /* XXX: correct return value? */
++
++ dev = sc->aps_sc.sc_dev;
++ ath_detach(dev);
++ if (dev->irq)
++ free_irq(dev->irq, dev);
++ devid = sc->aps_sc.devid;
++ config->tag = (void *)((unsigned long) devid);
++
++ ahb_disable_wmac(devid, wlanNum);
++ free_netdev(dev);
++ sclist[wlanNum] = NULL;
++ return 0;
++}
++
+ static int ahb_wmac_probe(struct platform_device *pdev)
+ {
+ u_int16_t devid;
+@@ -312,11 +406,18 @@ static int ahb_wmac_remove(struct platfo
+ return 0;
+ }
+
++#endif
++
+ static struct platform_driver ahb_wmac_driver = {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
++ .driver.name = "ar231x-wmac",
++#else
+ .driver.name = "ar531x-wmac",
++#endif
+ .probe = ahb_wmac_probe,
+ .remove = ahb_wmac_remove
+ };
++
+ int
+ ath_ioctl_ethtool(struct ath_softc *sc, int cmd, void __user *addr)
+ {
diff --git a/package/madwifi/patches/411-autochannel_multi.patch b/package/madwifi/patches/411-autochannel_multi.patch
new file mode 100644
index 000000000..d05c447f7
--- /dev/null
+++ b/package/madwifi/patches/411-autochannel_multi.patch
@@ -0,0 +1,347 @@
+--- a/net80211/ieee80211_scan.c
++++ b/net80211/ieee80211_scan.c
+@@ -97,6 +97,123 @@ struct scan_state {
+ static void scan_restart_pwrsav(unsigned long);
+ static void scan_next(unsigned long);
+
++spinlock_t channel_lock = SPIN_LOCK_UNLOCKED;
++static LIST_HEAD(channels_inuse);
++
++struct channel_inuse {
++ struct list_head list;
++ struct ieee80211com *ic;
++ u16 freq;
++ u8 bw;
++};
++
++static inline u32
++get_signal(u8 bw, u8 distance)
++{
++ u32 v;
++
++ /* signal = 1 - (distance / bw)^2 [scale: 100] */
++ v = 100 * distance / bw;
++ v = (100 - ((v * v) / 100));
++ return v;
++}
++
++static u32
++get_overlap(u16 f1, u16 f2, u8 b1, u8 b2)
++{
++ u32 v;
++ u16 d, c;
++
++ /* add offsets for sidechannel interference */
++ b1 += (b1 / 5);
++ b2 += (b2 / 5);
++
++ /* use only one direction */
++ b1 /= 2;
++ b2 /= 2;
++
++ if (f1 + b1 < f2 - b2)
++ return 0;
++
++ d = f2 - f1;
++ c = d * b1 / (b1 + b2);
++ v = get_signal(b1, c);
++
++ return v * v / 100;
++}
++
++static u8
++get_channel_bw(struct ieee80211_channel *c)
++{
++ switch(c->ic_flags & (
++ IEEE80211_CHAN_HALF |
++ IEEE80211_CHAN_QUARTER |
++ IEEE80211_CHAN_TURBO |
++ IEEE80211_CHAN_STURBO)) {
++ case IEEE80211_CHAN_QUARTER:
++ return 5;
++ case IEEE80211_CHAN_HALF:
++ return 10;
++ case IEEE80211_CHAN_TURBO:
++ case IEEE80211_CHAN_STURBO:
++ return 40;
++ default:
++ return 20;
++ }
++}
++
++/* must be called with channel_lock held */
++u32
++ieee80211_scan_get_bias(struct ieee80211_channel *c)
++{
++ struct channel_inuse *ch;
++ u8 bw = get_channel_bw(c);
++ u32 bias = 0;
++
++ list_for_each_entry(ch, &channels_inuse, list) {
++ if (ch->freq == c->ic_freq) {
++ bias += 50;
++ continue;
++ }
++ if (c->ic_freq < ch->freq)
++ bias += get_overlap(c->ic_freq, ch->freq, bw, ch->bw);
++ else
++ bias += get_overlap(ch->freq, c->ic_freq, ch->bw, bw);
++ }
++ return bias;
++}
++EXPORT_SYMBOL(ieee80211_scan_get_bias);
++
++/* must be called with channel_lock held */
++void
++ieee80211_scan_set_bss_channel(struct ieee80211com *ic, struct ieee80211_channel *c)
++{
++ unsigned long flags;
++ struct channel_inuse *ch;
++
++ list_for_each_entry(ch, &channels_inuse, list) {
++ if (ch->ic == ic)
++ goto found;
++ }
++ ch = NULL;
++found:
++ if (c && (c != IEEE80211_CHAN_ANYC)) {
++ if (!ch) {
++ ch = kmalloc(sizeof(struct channel_inuse), GFP_ATOMIC);
++ ch->ic = ic;
++ INIT_LIST_HEAD(&ch->list);
++ list_add(&ch->list, &channels_inuse);
++ }
++ ch->freq = c->ic_freq;
++ ch->bw = get_channel_bw(c);
++ } else if (ch) {
++ list_del(&ch->list);
++ kfree(ch);
++ }
++}
++EXPORT_SYMBOL(ieee80211_scan_set_bss_channel);
++
++
+ void
+ ieee80211_scan_attach(struct ieee80211com *ic)
+ {
+@@ -1169,7 +1286,7 @@ ieee80211_scan_dfs_action(struct ieee802
+ IEEE80211_RADAR_CHANCHANGE_TBTT_COUNT;
+ ic->ic_flags |= IEEE80211_F_CHANSWITCH;
+ } else {
+-
++ unsigned long flags;
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
+ "%s: directly switching to channel "
+ "%3d (%4d MHz)\n", __func__,
+@@ -1180,6 +1297,9 @@ ieee80211_scan_dfs_action(struct ieee802
+ * change the channel here. */
+ change_channel(ic, new_channel);
+ ic->ic_bsschan = new_channel;
++ spin_lock_irqsave(&channel_lock, flags);
++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan);
++ spin_unlock_irqrestore(&channel_lock, flags);
+ if (vap->iv_bss)
+ vap->iv_bss->ni_chan = new_channel;
+ }
+--- a/net80211/ieee80211_scan.h
++++ b/net80211/ieee80211_scan.h
+@@ -35,6 +35,7 @@
+
+ #define IEEE80211_SCAN_MAX IEEE80211_CHAN_MAX
+
++extern spinlock_t channel_lock;
+ struct ieee80211_scanner;
+ struct ieee80211_scan_entry;
+
+@@ -116,6 +117,8 @@ void ieee80211_scan_flush(struct ieee802
+ 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 *);
++u32 ieee80211_scan_get_bias(struct ieee80211_channel *c);
++void ieee80211_scan_set_bss_channel(struct ieee80211com *ic, struct ieee80211_channel *c);
+
+ /*
+ * Parameters supplied when adding/updating an entry in a
+--- a/net80211/ieee80211.c
++++ b/net80211/ieee80211.c
+@@ -373,8 +373,16 @@ void
+ ieee80211_ifdetach(struct ieee80211com *ic)
+ {
+ struct ieee80211vap *vap;
++ unsigned long flags;
+ int count;
+
++ /* mark the channel as no longer in use */
++ ic->ic_bsschan = IEEE80211_CHAN_ANYC;
++ spin_lock_irqsave(&channel_lock, flags);
++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan);
++ spin_unlock_irqrestore(&channel_lock, flags);
++
++
+ /* bring down all vaps */
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+ ieee80211_stop(vap->iv_dev);
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -2775,6 +2775,7 @@ static void
+ ieee80211_doth_switch_channel(struct ieee80211vap *vap)
+ {
+ struct ieee80211com *ic = vap->iv_ic;
++ unsigned long flags;
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
+ "%s: Channel switch to %3d (%4d MHz) NOW!\n",
+@@ -2797,6 +2798,9 @@ ieee80211_doth_switch_channel(struct iee
+
+ ic->ic_curchan = ic->ic_bsschan = vap->iv_csa_chan;
+ ic->ic_set_channel(ic);
++ spin_lock_irqsave(&channel_lock, flags);
++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan);
++ spin_unlock_irqrestore(&channel_lock, flags);
+ }
+
+ static void
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -308,6 +308,7 @@ ieee80211_create_ibss(struct ieee80211va
+ {
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_node *ni;
++ unsigned long flags;
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: creating ibss on channel %u\n", __func__,
+@@ -386,6 +387,9 @@ ieee80211_create_ibss(struct ieee80211va
+ ic->ic_bsschan = chan;
+ ieee80211_node_set_chan(ic, ni);
+ ic->ic_curmode = ieee80211_chan2mode(chan);
++ spin_lock_irqsave(&channel_lock, flags);
++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan);
++ spin_unlock_irqrestore(&channel_lock, flags);
+
+ /* Update country ie information */
+ ieee80211_build_countryie(ic);
+@@ -622,6 +626,7 @@ ieee80211_sta_join1(struct ieee80211_nod
+ struct ieee80211vap *vap = selbs->ni_vap;
+ struct ieee80211com *ic = selbs->ni_ic;
+ struct ieee80211_node *obss;
++ unsigned long flags;
+ int canreassoc;
+
+ if (vap->iv_opmode == IEEE80211_M_IBSS) {
+@@ -650,6 +655,9 @@ ieee80211_sta_join1(struct ieee80211_nod
+ ic->ic_curchan = ic->ic_bsschan;
+ ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan);
+ ic->ic_set_channel(ic);
++ spin_lock_irqsave(&channel_lock, flags);
++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan);
++ spin_unlock_irqrestore(&channel_lock, flags);
+ /*
+ * Set the erp state (mostly the slot time) to deal with
+ * the auto-select case; this should be redundant if the
+--- a/net80211/ieee80211_proto.c
++++ b/net80211/ieee80211_proto.c
+@@ -1231,6 +1231,7 @@ ieee80211_dturbo_switch(struct ieee80211
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ #endif
+ struct ieee80211_channel *chan;
++ unsigned long flags;
+
+ chan = ieee80211_find_channel(ic, ic->ic_bsschan->ic_freq, newflags);
+ if (chan == NULL) { /* XXX should not happen */
+@@ -1249,6 +1250,9 @@ ieee80211_dturbo_switch(struct ieee80211
+ ic->ic_bsschan = chan;
+ ic->ic_curchan = chan;
+ ic->ic_set_channel(ic);
++ spin_lock_irqsave(&channel_lock, flags);
++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan);
++ spin_unlock_irqrestore(&channel_lock, flags);
+ /* NB: do not need to reset ERP state because in sta mode */
+ }
+ EXPORT_SYMBOL(ieee80211_dturbo_switch);
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -4076,8 +4076,13 @@ ieee80211_ioctl_setchanlist(struct net_d
+ if (nchan == 0) /* no valid channels, disallow */
+ return -EINVAL;
+ if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */
+- isclr(chanlist, ic->ic_bsschan->ic_ieee))
++ isclr(chanlist, ic->ic_bsschan->ic_ieee)) {
++ unsigned long flags;
+ ic->ic_bsschan = IEEE80211_CHAN_ANYC; /* invalidate */
++ spin_lock_irqsave(&channel_lock, flags);
++ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan);
++ spin_unlock_irqrestore(&channel_lock, flags);
++ }
+
+ memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active));
+ /* update Supported Channels information element */
+--- a/net80211/ieee80211_scan_ap.c
++++ b/net80211/ieee80211_scan_ap.c
+@@ -208,9 +208,15 @@ ap_start(struct ieee80211_scan_state *ss
+ struct ieee80211com *ic = NULL;
+ int i;
+ unsigned int mode = 0;
++ unsigned long sflags;
+
+ SCAN_AP_LOCK_IRQ(as);
+ ic = vap->iv_ic;
++
++ spin_lock_irqsave(&channel_lock, sflags);
++ ieee80211_scan_set_bss_channel(ic, NULL);
++ spin_unlock_irqrestore(&channel_lock, sflags);
++
+ /* Determine mode flags to match, or leave zero for auto mode */
+ ss->ss_last = 0;
+ ieee80211_scan_add_channels(ic, ss, vap->iv_des_mode);
+@@ -423,8 +429,10 @@ pc_cmp_idletime(struct ieee80211_channel
+ if (!a->ic_idletime || !b->ic_idletime)
+ return 0;
+
+- /* a is better than b (return < 0) when a has more idle time than b */
+- return b->ic_idletime - a->ic_idletime;
++ /* a is better than b (return < 0) when a has more idle and less bias time than b */
++ return
++ ((100 - (u32) a->ic_idletime) + ieee80211_scan_get_bias(a)) -
++ ((100 - (u32) b->ic_idletime) + ieee80211_scan_get_bias(b));
+ }
+
+
+@@ -575,6 +583,7 @@ ap_end(struct ieee80211_scan_state *ss,
+ struct ap_state *as = ss->ss_priv;
+ struct ieee80211_channel *bestchan = NULL;
+ struct ieee80211com *ic = NULL;
++ unsigned long sflags;
+ int res = 1;
+
+ SCAN_AP_LOCK_IRQ(as);
+@@ -586,8 +595,11 @@ ap_end(struct ieee80211_scan_state *ss,
+
+ /* record stats for the channel that was scanned last */
+ ic->ic_set_channel(ic);
++ spin_lock_irqsave(&channel_lock, sflags);
++ ieee80211_scan_set_bss_channel(ic, NULL);
+ bestchan = pick_channel(ss, vap, flags);
+ if (bestchan == NULL) {
++ spin_unlock_irqrestore(&channel_lock, sflags);
+ if (ss->ss_last > 0) {
+ /* no suitable channel, should not happen */
+ printk(KERN_ERR "%s: %s: no suitable channel! "
+@@ -606,6 +618,7 @@ ap_end(struct ieee80211_scan_state *ss,
+ bestchan->ic_freq, bestchan->ic_flags &
+ ~IEEE80211_CHAN_TURBO)) == NULL) {
+ /* should never happen ?? */
++ spin_unlock_irqrestore(&channel_lock, sflags);
+ SCAN_AP_UNLOCK_IRQ_EARLY(as);
+ return 0;
+ }
+@@ -618,6 +631,9 @@ ap_end(struct ieee80211_scan_state *ss,
+ as->as_action = action;
+ as->as_selbss = se;
+
++ ieee80211_scan_set_bss_channel(ic, bestchan);
++ spin_unlock_irqrestore(&channel_lock, sflags);
++
+ /* Must defer action to avoid possible recursive call through
+ * 80211 state machine, which would result in recursive
+ * locking. */
diff --git a/package/madwifi/patches/412-fragmentation_fix.patch b/package/madwifi/patches/412-fragmentation_fix.patch
new file mode 100644
index 000000000..92c411b2b
--- /dev/null
+++ b/package/madwifi/patches/412-fragmentation_fix.patch
@@ -0,0 +1,10 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -3684,6 +3684,7 @@ ff_bypass:
+ * already alloc'd
+ */
+ ATH_TXBUF_LOCK_IRQ(sc);
++ STAILQ_INSERT_TAIL(&bf_head, bf, bf_list);
+ for (bfcnt = 1; bfcnt < framecnt; ++bfcnt) {
+ tbf = ath_take_txbuf_locked(sc);
+ if (tbf == NULL)
diff --git a/package/madwifi/patches/413-rxorn.patch b/package/madwifi/patches/413-rxorn.patch
new file mode 100644
index 000000000..0e8d885da
--- /dev/null
+++ b/package/madwifi/patches/413-rxorn.patch
@@ -0,0 +1,31 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -2308,6 +2308,17 @@ ath_intr(int irq, void *dev_id, struct p
+
+ sc->sc_isr = status;
+ status &= sc->sc_imask; /* discard unasked for bits */
++
++ /* Treat RXORN as non-fatal. Either the bus is busy or the CPU
++ * is not fast enough to process all frames. Treat it like
++ * an Rx interrupt
++ */
++ if (status & HAL_INT_RXORN) {
++ sc->sc_stats.ast_rxorn++;
++ status &= ~HAL_INT_RXORN;
++ status |= HAL_INT_RX;
++ }
++
+ /* 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.
+ * Normally we would just populate this all the time to keep things
+@@ -2320,10 +2331,6 @@ ath_intr(int irq, void *dev_id, struct p
+ sc->sc_stats.ast_hardware++;
+ ath_hal_intrset(ah, 0); /* disable intr's until reset */
+ ATH_SCHEDULE_TQUEUE(&sc->sc_fataltq, &needmark);
+- } else if (status & HAL_INT_RXORN) {
+- sc->sc_stats.ast_rxorn++;
+- ath_hal_intrset(ah, 0); /* disable intr's until reset */
+- ATH_SCHEDULE_TQUEUE(&sc->sc_rxorntq, &needmark);
+ } else {
+ if (status & HAL_INT_SWBA) {
+ struct ieee80211vap * vap;
diff --git a/package/madwifi/patches/414-txpower.patch b/package/madwifi/patches/414-txpower.patch
new file mode 100644
index 000000000..3c18bd6fe
--- /dev/null
+++ b/package/madwifi/patches/414-txpower.patch
@@ -0,0 +1,262 @@
+--- a/net80211/ieee80211.c
++++ b/net80211/ieee80211.c
+@@ -270,6 +270,7 @@ ieee80211_ifattach(struct ieee80211com *
+ ("invalid number of channels specified: %u", ic->ic_nchans));
+ memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail));
+ ic->ic_modecaps |= 1 << IEEE80211_MODE_AUTO;
++ ic->ic_max_txpower = IEEE80211_TXPOWER_MIN;
+
+ for (i = 0; i < ic->ic_nchans; i++) {
+ c = &ic->ic_channels[i];
+@@ -277,6 +278,7 @@ ieee80211_ifattach(struct ieee80211com *
+ KASSERT(c->ic_ieee < IEEE80211_CHAN_MAX,
+ ("channel with bogus ieee number %u", c->ic_ieee));
+ setbit(ic->ic_chan_avail, c->ic_ieee);
++ ic->ic_max_txpower = max(ic->ic_max_txpower, (u16) (c->ic_maxpower * 2));
+
+ if (c->ic_scanflags & IEEE80211_NOSCAN_DEFAULT)
+ c->ic_scanflags |= IEEE80211_NOSCAN_SET;
+@@ -346,8 +348,6 @@ ieee80211_ifattach(struct ieee80211com *
+ TAILQ_INIT(&ic->ic_vaps);
+
+ ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX;
+- ic->ic_txpowlimit = IEEE80211_TXPOWER_MIN;
+- ic->ic_newtxpowlimit = IEEE80211_TXPOWER_MAX;
+
+ init_timer(&ic->ic_dfs_excl_timer);
+ ic->ic_dfs_excl_timer.function =
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -1125,7 +1125,7 @@ ieee80211_alloc_node(struct ieee80211vap
+
+ ni->ni_chan = IEEE80211_CHAN_ANYC;
+ ni->ni_authmode = IEEE80211_AUTH_OPEN;
+- ni->ni_txpower = ic->ic_txpowlimit;
++ ni->ni_txpower = IEEE80211_TXPOWER_MAX;
+
+ ieee80211_crypto_resetkey(vap, &ni->ni_ucastkey,
+ IEEE80211_KEYIX_NONE);
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -343,8 +343,8 @@ struct ieee80211com {
+ 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_txpowlimit; /* configured global tx power limit (in 0.5 dBm) */
++ u_int16_t ic_max_txpower; /* global hardware tx power limit */
+ 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 */
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -908,6 +908,21 @@ ieee80211_ioctl_giwessid(struct net_devi
+ return 0;
+ }
+
++static u16
++ieee80211_get_maxtxpow(struct ieee80211com *ic)
++{
++ u_int16_t txp = IEEE80211_TXPOWER_MAX;
++
++ if (ic->ic_bsschan && (ic->ic_bsschan != IEEE80211_CHAN_ANYC))
++ txp = min(txp, (u16) ic->ic_bsschan->ic_maxpower);
++
++ if (ic->ic_max_txpower > 0)
++ txp = min(txp, ic->ic_max_txpower);
++
++ return txp;
++}
++
++
+ static int
+ ieee80211_ioctl_giwrange(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+@@ -920,17 +935,21 @@ ieee80211_ioctl_giwrange(struct net_devi
+ u_int8_t reported[IEEE80211_CHAN_BYTES]; /* XXX stack usage? */
+ int i, r;
+ int step = 0;
++ u_int16_t power;
+
+ data->length = sizeof(struct iw_range);
+ memset(range, 0, sizeof(struct iw_range));
+
++ power = ieee80211_get_maxtxpow(ic);
++
+ /* txpower (128 values, but will print out only IW_MAX_TXPOWER) */
+- range->num_txpower = (ic->ic_txpowlimit >= 8) ? IW_MAX_TXPOWER : ic->ic_txpowlimit;
+- step = ic->ic_txpowlimit / (2 * (IW_MAX_TXPOWER - 1));
++ power /= 2; /* Unit: 0.5 dBm */
++ range->num_txpower = (power >= 8) ? IW_MAX_TXPOWER : power;
++ step = power / (IW_MAX_TXPOWER - 1);
+
+ range->txpower[0] = 0;
+ for (i = 1; i < IW_MAX_TXPOWER; i++)
+- range->txpower[i] = (ic->ic_txpowlimit/2)
++ range->txpower[i] = power
+ - (IW_MAX_TXPOWER - i - 1) * step;
+
+ range->txpower_capa = IW_TXPOW_DBM;
+@@ -1379,13 +1398,11 @@ ieee80211_ioctl_siwtxpow(struct net_devi
+ int fixed, disabled;
+
+ fixed = (ic->ic_flags & IEEE80211_F_TXPOW_FIXED);
+- disabled = (fixed && vap->iv_bss->ni_txpower == 0);
++ disabled = (fixed && ic->ic_txpowlimit == 0);
+ if (rrq->disabled) {
+ if (!disabled) {
+- if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
+- return -EOPNOTSUPP;
+ ic->ic_flags |= IEEE80211_F_TXPOW_FIXED;
+- vap->iv_bss->ni_txpower = 0;
++ ic->ic_txpowlimit = 0;
+ goto done;
+ }
+ return 0;
+@@ -1396,30 +1413,12 @@ ieee80211_ioctl_siwtxpow(struct net_devi
+ return -EOPNOTSUPP;
+ if (rrq->flags != IW_TXPOW_DBM)
+ return -EINVAL;
+- if (ic->ic_bsschan != IEEE80211_CHAN_ANYC) {
+- if ((ic->ic_bsschan->ic_maxregpower >= rrq->value) &&
+- (ic->ic_txpowlimit/2 >= rrq->value)) {
+- vap->iv_bss->ni_txpower = 2 * rrq->value;
+- ic->ic_newtxpowlimit = 2 * rrq->value;
+- ic->ic_flags |= IEEE80211_F_TXPOW_FIXED;
+- } else
+- return -EINVAL;
+- } else {
+- /*
+- * No channel set yet
+- */
+- if (ic->ic_txpowlimit/2 >= rrq->value) {
+- vap->iv_bss->ni_txpower = 2 * rrq->value;
+- ic->ic_newtxpowlimit = 2 * rrq->value;
+- ic->ic_flags |= IEEE80211_F_TXPOW_FIXED;
+- }
+- else
+- return -EINVAL;
+- }
++ ic->ic_txpowlimit = 2 * rrq->value;
++ ic->ic_flags |= IEEE80211_F_TXPOW_FIXED;
+ } else {
+ if (!fixed) /* no change */
+ return 0;
+- ic->ic_newtxpowlimit = IEEE80211_TXPOWER_MAX;
++ ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX;
+ ic->ic_flags &= ~IEEE80211_F_TXPOW_FIXED;
+ }
+ done:
+@@ -1588,9 +1587,18 @@ ieee80211_ioctl_giwtxpow(struct net_devi
+ {
+ struct ieee80211vap *vap = dev->priv;
+ struct ieee80211com *ic = vap->iv_ic;
+-
+- rrq->value = vap->iv_bss->ni_txpower / 2;
+- rrq->fixed = (ic->ic_flags & IEEE80211_F_TXPOW_FIXED) != 0;
++ unsigned int power = ic->ic_txpowlimit;
++ struct ieee80211_channel *c;
++ u_int16_t txp;
++
++ txp = ieee80211_get_maxtxpow(ic);
++ if (ic->ic_flags & IEEE80211_F_TXPOW_FIXED) {
++ txp = min(txp, ic->ic_txpowlimit);
++ rrq->fixed = 1;
++ } else {
++ rrq->fixed = 0;
++ }
++ rrq->value = txp / 2;
+ rrq->disabled = (rrq->fixed && rrq->value == 0);
+ rrq->flags = IW_TXPOW_DBM;
+ return 0;
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -380,7 +380,6 @@ static unsigned int ath_dump_hal_map(str
+ 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);
+-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);
+@@ -3168,7 +3167,7 @@ ath_tx_startraw(struct net_device *dev,
+ try0 = ph->try0;
+ rt = sc->sc_currates;
+ txrate = dot11_to_ratecode(sc, rt, ph->rate0);
+- power = ph->power > 60 ? 60 : ph->power;
++ power = ph->power > 63 ? 63 : ph->power;
+ hdrlen = ieee80211_anyhdrsize(wh);
+ pktlen = skb->len + IEEE80211_CRC_LEN;
+
+@@ -8394,7 +8393,7 @@ ath_tx_start(struct net_device *dev, str
+ pktlen, /* packet length */
+ hdrlen, /* header length */
+ atype, /* Atheros packet type */
+- MIN(ni->ni_txpower, 60), /* txpower */
++ MIN(ni->ni_txpower, 63), /* txpower */
+ txrate, try0, /* series 0 rate/tries */
+ keyix, /* key cache index */
+ antenna, /* antenna mode */
+@@ -10387,59 +10386,16 @@ ath_get_clamped_maxtxpower(struct ath_so
+
+ /* XXX: this function needs some locking to avoid being called
+ * twice/interrupted */
+-/* 1. Save the currently specified maximum txpower (as clamped by madwifi)
+- * 2. Determine the real maximum txpower the card can support by
+- * setting a value that exceeds the maximum range (by one) and
+- * finding out what it limits us to.
+- * 3. Restore the saved maxtxpower value we had previously specified */
+-static u_int32_t
+-ath_get_real_maxtxpower(struct ath_softc *sc)
+-{
+- u_int32_t saved_clamped_maxtxpower;
+- u_int32_t real_maxtxpower;
+-
+- saved_clamped_maxtxpower = ath_get_clamped_maxtxpower(sc);
+- real_maxtxpower =
+- ath_set_clamped_maxtxpower(sc, IEEE80211_TXPOWER_MAX + 1);
+- ath_set_clamped_maxtxpower(sc, saved_clamped_maxtxpower);
+- return real_maxtxpower;
+-}
+-
+-
+-/* XXX: this function needs some locking to avoid being called
+- * twice/interrupted */
+ static void
+ ath_update_txpow(struct ath_softc *sc)
+ {
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap = NULL;
+ struct ath_hal *ah = sc->sc_ah;
+- u_int32_t prev_clamped_maxtxpower = 0;
+- u_int32_t new_clamped_maxtxpower = 0;
+
+ /* Determine the previous value of maxtxpower */
+- prev_clamped_maxtxpower = ath_get_clamped_maxtxpower(sc);
+- /* Determine the real maximum txpower the card can support */
+- ic->ic_txpowlimit = ath_get_real_maxtxpower(sc);
+- /* Grab the new maxtxpower setting (which may have changed) */
+- new_clamped_maxtxpower = ic->ic_newtxpowlimit;
+- /* Make sure the change is within limits, clamp it otherwise */
+- if (ic->ic_newtxpowlimit > ic->ic_txpowlimit)
+- new_clamped_maxtxpower = ic->ic_txpowlimit;
+- /* Search for the VAP that needs a txpow change, if any */
+- TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+- if (!tpc || ic->ic_newtxpowlimit != vap->iv_bss->ni_txpower) {
+- vap->iv_bss->ni_txpower = new_clamped_maxtxpower;
+- ieee80211_iterate_nodes(&vap->iv_ic->ic_sta,
+- set_node_txpower,
+- &new_clamped_maxtxpower);
+- }
+- }
+-
+- /* Store the assigned (clamped) maximum txpower and update the HAL */
+- sc->sc_curtxpow = new_clamped_maxtxpower;
+- if (new_clamped_maxtxpower != prev_clamped_maxtxpower)
+- ath_hal_settxpowlimit(ah, new_clamped_maxtxpower);
++ ath_set_clamped_maxtxpower(sc, ic->ic_txpowlimit);
++ ic->ic_max_txpower = ath_get_clamped_maxtxpower(sc);
+ }
+
+ #ifdef ATH_SUPERG_XR
diff --git a/package/madwifi/patches/415-chan_switch.patch b/package/madwifi/patches/415-chan_switch.patch
new file mode 100644
index 000000000..6dc5da838
--- /dev/null
+++ b/package/madwifi/patches/415-chan_switch.patch
@@ -0,0 +1,187 @@
+--- a/net80211/ieee80211_beacon.c
++++ b/net80211/ieee80211_beacon.c
+@@ -224,18 +224,18 @@ ieee80211_beacon_alloc(struct ieee80211_
+ pktlen = 8 /* time stamp */
+ + sizeof(u_int16_t) /* beacon interval */
+ + sizeof(u_int16_t) /* capability information */
+- + 2 + ni->ni_esslen /* ssid */
++ + 2 + IEEE80211_NWID_LEN /* ssid */
+ + 2 + IEEE80211_RATE_SIZE /* supported rates */
+ + 7 /* FH/DS parameters max(7,3) */
+- + 2 + 4 + vap->iv_tim_len /* IBSS/TIM parameter set*/
++ + sizeof(struct ieee80211_tim_ie) + 128 /* IBSS/TIM parameter set*/
+ + ic->ic_country_ie.country_len + 2 /* country code */
+ + 3 /* power constraint */
+ + 5 /* channel switch announcement */
+ + 3 /* ERP */
+ + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE) /* Ext. Supp. Rates */
+- + (vap->iv_caps & IEEE80211_C_WME ? /* WME */
++ + (ic->ic_caps & IEEE80211_C_WME ? /* WME */
+ sizeof(struct ieee80211_wme_param) : 0)
+- + (vap->iv_caps & IEEE80211_C_WPA ? /* WPA 1+2 */
++ + (ic->ic_caps & IEEE80211_C_WPA ? /* WPA 1+2 */
+ 2 * sizeof(struct ieee80211_ie_wpa) : 0)
+ + sizeof(struct ieee80211_ie_athAdvCap)
+ #ifdef ATH_SUPERG_XR
+@@ -290,17 +290,26 @@ ieee80211_beacon_update(struct ieee80211
+ IEEE80211_LOCK_IRQ(ic);
+
+ /* Check if we need to change channel right now */
+- if ((ic->ic_flags & IEEE80211_F_DOTH) &&
+- (vap->iv_flags & IEEE80211_F_CHANSWITCH)) {
+- struct ieee80211_channel *c =
++ if (ic->ic_flags & IEEE80211_F_CHANSWITCH) {
++ struct ieee80211_channel *c =
+ ieee80211_doth_findchan(vap, ic->ic_chanchange_chan);
+-
+- if (!vap->iv_chanchange_count && !c) {
+- vap->iv_flags &= ~IEEE80211_F_CHANSWITCH;
+- ic->ic_flags &= ~IEEE80211_F_CHANSWITCH;
+- } else if (vap->iv_chanchange_count &&
+- ((!ic->ic_chanchange_tbtt) ||
+- (vap->iv_chanchange_count == ic->ic_chanchange_tbtt))) {
++ struct ieee80211vap *avp;
++ int do_switch = 1;
++
++ TAILQ_FOREACH(avp, &ic->ic_vaps, iv_next) {
++ if (!(avp->iv_flags & IEEE80211_F_CHANSWITCH))
++ continue;
++
++ do_switch = 0;
++ break;
++ }
++ if (vap->iv_flags & IEEE80211_F_CHANSWITCH) {
++ if (vap->iv_chanchange_count-- <= 1) {
++ vap->iv_flags &= ~IEEE80211_F_CHANSWITCH;
++ vap->iv_chanchange_count = 0;
++ }
++ }
++ if (do_switch) {
+ u_int8_t *frm;
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
+@@ -316,16 +325,7 @@ ieee80211_beacon_update(struct ieee80211
+ } else
+ ic->ic_bsschan = c;
+
+- skb_pull(skb, sizeof(struct ieee80211_frame));
+- skb_trim(skb, 0);
+- frm = skb->data;
+- skb_put(skb, ieee80211_beacon_init(ni, bo, frm) - frm);
+- skb_push(skb, sizeof(struct ieee80211_frame));
+-
+- vap->iv_chanchange_count = 0;
+- vap->iv_flags &= ~IEEE80211_F_CHANSWITCH;
+ ic->ic_flags &= ~IEEE80211_F_CHANSWITCH;
+-
+ /* NB: Only for the first VAP to get here, and when we
+ * have a valid channel to which to change. */
+ if (c && (ic->ic_curchan != c)) {
+@@ -488,22 +488,20 @@ ieee80211_beacon_update(struct ieee80211
+
+ if (IEEE80211_IS_MODE_BEACON(vap->iv_opmode)) {
+
+- if ((ic->ic_flags & IEEE80211_F_DOTH) &&
+- (ic->ic_flags & IEEE80211_F_CHANSWITCH)) {
++ if (ic->ic_flags & IEEE80211_F_CHANSWITCH) {
+ struct ieee80211_ie_csa *csa_ie =
+ (struct ieee80211_ie_csa *)bo->bo_chanswitch;
+
+- IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
++ if (csa_ie->csa_len == 0) {
++ IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
+ "%s: Sending 802.11h chanswitch IE: "
+ "%d/%d\n", __func__,
+ ic->ic_chanchange_chan,
+ ic->ic_chanchange_tbtt);
+- if (!vap->iv_chanchange_count) {
+- vap->iv_flags |= IEEE80211_F_CHANSWITCH;
+
+ /* copy out trailer to open up a slot */
+ memmove(bo->bo_chanswitch + sizeof(*csa_ie),
+- bo->bo_chanswitch,
++ bo->bo_chanswitch,
+ bo->bo_chanswitch_trailerlen);
+
+ /* add ie in opened slot */
+@@ -523,17 +521,15 @@ ieee80211_beacon_update(struct ieee80211
+ bo->bo_ath_caps += sizeof(*csa_ie);
+ bo->bo_xr += sizeof(*csa_ie);
+
+- /* indicate new beacon length so other layers
++ /* indicate new beacon length so other layers
+ * may manage memory */
+ skb_put(skb, sizeof(*csa_ie));
+ len_changed = 1;
+- } else if(csa_ie->csa_count)
+- csa_ie->csa_count--;
+-
+- vap->iv_chanchange_count++;
+- IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
+- "%s: CHANSWITCH IE, change in %d TBTT\n",
+- __func__, csa_ie->csa_count);
++
++ IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
++ "%s: CHANSWITCH IE, change in %d TBTT\n",
++ __func__, csa_ie->csa_count);
++ }
+ }
+ #ifdef ATH_SUPERG_XR
+ if (vap->iv_flags & IEEE80211_F_XRUPDATE) {
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -699,39 +699,11 @@ ieee80211_ioctl_siwfreq(struct net_devic
+ if (c == NULL) /* no channel */
+ return -EINVAL;
+ }
+- /*
+- * Fine tune channel selection based on desired mode:
+- * if 11b is requested, find the 11b version of any
+- * 11g channel returned,
+- * if static turbo, find the turbo version of any
+- * 11a channel return,
+- * otherwise we should be ok with what we've got.
+- */
+- switch (vap->iv_des_mode) {
+- case IEEE80211_MODE_11B:
+- if (IEEE80211_IS_CHAN_ANYG(c)) {
+- c2 = findchannel(ic, i, IEEE80211_MODE_11B);
+- /* NB: should not happen, =>'s 11g w/o 11b */
+- if (c2 != NULL)
+- c = c2;
+- }
+- break;
+- case IEEE80211_MODE_TURBO_A:
+- if (IEEE80211_IS_CHAN_A(c)) {
+- c2 = findchannel(ic, i, IEEE80211_MODE_TURBO_A);
+- if (c2 != NULL)
+- c = c2;
+- }
+- break;
+- default: /* NB: no static turboG */
+- break;
+- }
++
+ if (ieee80211_check_mode_consistency(ic, vap->iv_des_mode, c)) {
+ if (vap->iv_opmode == IEEE80211_M_HOSTAP)
+ return -EINVAL;
+ }
+- if ((vap->iv_state == IEEE80211_S_RUN) && (c == vap->iv_des_chan))
+- return 0; /* no change, return */
+
+ /* Don't allow to change to channel with radar found */
+ if (c->ic_flags & IEEE80211_CHAN_RADAR)
+@@ -4634,7 +4606,13 @@ static void
+ pre_announced_chanswitch(struct net_device *dev, u_int32_t channel, u_int32_t tbtt) {
+ struct ieee80211vap *vap = dev->priv;
+ struct ieee80211com *ic = vap->iv_ic;
++ struct ieee80211vap *avp;
++
+ /* now flag the beacon update to include the channel switch IE */
++ TAILQ_FOREACH(avp, &ic->ic_vaps, iv_next) {
++ avp->iv_flags |= IEEE80211_F_CHANSWITCH;
++ avp->iv_chanchange_count = tbtt;
++ }
+ ic->ic_flags |= IEEE80211_F_CHANSWITCH;
+ ic->ic_chanchange_chan = channel;
+ ic->ic_chanchange_tbtt = tbtt;
diff --git a/package/madwifi/patches/416-wprobe.patch b/package/madwifi/patches/416-wprobe.patch
new file mode 100644
index 000000000..0b378d7e2
--- /dev/null
+++ b/package/madwifi/patches/416-wprobe.patch
@@ -0,0 +1,549 @@
+--- /dev/null
++++ b/ath/ath_wprobe.c
+@@ -0,0 +1,433 @@
++#include <net80211/ieee80211_node.h>
++#include <linux/wprobe.h>
++
++atomic_t cleanup_tasks = ATOMIC_INIT(0);
++
++enum wp_node_val {
++ WP_NODE_RSSI,
++ WP_NODE_SIGNAL,
++ WP_NODE_RX_RATE,
++ WP_NODE_TX_RATE,
++ WP_NODE_RETRANSMIT_200,
++ WP_NODE_RETRANSMIT_400,
++ WP_NODE_RETRANSMIT_800,
++ WP_NODE_RETRANSMIT_1600,
++};
++
++enum wp_global_val {
++ WP_GLOBAL_NOISE,
++ WP_GLOBAL_PHY_BUSY,
++ WP_GLOBAL_PHY_RX,
++ WP_GLOBAL_PHY_TX,
++ WP_GLOBAL_FRAMES,
++ WP_GLOBAL_PROBEREQ,
++};
++
++static struct wprobe_item ath_wprobe_globals[] = {
++ [WP_GLOBAL_NOISE] = {
++ .name = "noise",
++ .type = WPROBE_VAL_S16,
++ .flags = WPROBE_F_KEEPSTAT
++ },
++ [WP_GLOBAL_PHY_BUSY] = {
++ .name = "phy_busy",
++ .type = WPROBE_VAL_U8,
++ .flags = WPROBE_F_KEEPSTAT
++ },
++ [WP_GLOBAL_PHY_RX] = {
++ .name = "phy_rx",
++ .type = WPROBE_VAL_U8,
++ .flags = WPROBE_F_KEEPSTAT
++ },
++ [WP_GLOBAL_PHY_TX] = {
++ .name = "phy_tx",
++ .type = WPROBE_VAL_U8,
++ .flags = WPROBE_F_KEEPSTAT
++ },
++ [WP_GLOBAL_FRAMES] = {
++ .name = "frames",
++ .type = WPROBE_VAL_U32,
++ },
++ [WP_GLOBAL_PROBEREQ] = {
++ .name = "probereq",
++ .type = WPROBE_VAL_U32,
++ },
++};
++
++static struct wprobe_item ath_wprobe_link[] = {
++ [WP_NODE_RSSI] = {
++ .name = "rssi",
++ .type = WPROBE_VAL_U8,
++ .flags = WPROBE_F_KEEPSTAT
++ },
++ [WP_NODE_SIGNAL] = {
++ .name = "signal",
++ .type = WPROBE_VAL_S16,
++ .flags = WPROBE_F_KEEPSTAT
++ },
++ [WP_NODE_RX_RATE] = {
++ .name = "rx_rate",
++ .type = WPROBE_VAL_U16,
++ .flags = WPROBE_F_KEEPSTAT
++ },
++ [WP_NODE_TX_RATE] = {
++ .name = "tx_rate",
++ .type = WPROBE_VAL_U16,
++ .flags = WPROBE_F_KEEPSTAT
++ },
++ [WP_NODE_RETRANSMIT_200] = {
++ .name = "retransmit_200",
++ .type = WPROBE_VAL_U8,
++ .flags = WPROBE_F_KEEPSTAT
++ },
++ [WP_NODE_RETRANSMIT_400] = {
++ .name = "retransmit_400",
++ .type = WPROBE_VAL_U8,
++ .flags = WPROBE_F_KEEPSTAT
++ },
++ [WP_NODE_RETRANSMIT_800] = {
++ .name = "retransmit_800",
++ .type = WPROBE_VAL_U8,
++ .flags = WPROBE_F_KEEPSTAT
++ },
++ [WP_NODE_RETRANSMIT_1600] = {
++ .name = "retransmit_1600",
++ .type = WPROBE_VAL_U8,
++ .flags = WPROBE_F_KEEPSTAT
++ },
++};
++
++#define AR5K_MIBC 0x0040
++#define AR5K_MIBC_FREEZE (1 << 1)
++#define AR5K_TXFC 0x80ec
++#define AR5K_RXFC 0x80f0
++#define AR5K_RXCLEAR 0x80f4
++#define AR5K_CYCLES 0x80f8
++
++#define READ_CLR(_ah, _reg) \
++ ({ u32 __val = OS_REG_READ(_ah, _reg); OS_REG_WRITE(_ah, _reg, 0); __val; })
++
++static bool
++wprobe_disabled(void)
++{
++ return (!wprobe_add_iface || IS_ERR(wprobe_add_iface));
++}
++
++static int
++ath_wprobe_sync(struct wprobe_iface *dev, struct wprobe_link *l, struct wprobe_value *val, bool measure)
++{
++ struct ath_vap *avp = container_of(dev, struct ath_vap, av_wpif);
++ struct ieee80211vap *vap = &avp->av_vap;
++ struct ieee80211com *ic = vap->iv_ic;
++ struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_hal *ah = sc->sc_ah;
++ u32 cc, busy, rx, tx;
++ s16 noise;
++
++ if (l)
++ goto out;
++
++ OS_REG_WRITE(ah, AR5K_MIBC, AR5K_MIBC_FREEZE);
++ cc = READ_CLR(ah, AR5K_CYCLES);
++ busy = READ_CLR(ah, AR5K_RXCLEAR);
++ rx = READ_CLR(ah, AR5K_RXFC);
++ tx = READ_CLR(ah, AR5K_TXFC);
++ OS_REG_WRITE(ah, AR5K_MIBC, 0);
++ noise = ath_hal_get_channel_noise(sc->sc_ah, &(sc->sc_curchan));
++ ic->ic_channoise = noise;
++
++ WPROBE_FILL_BEGIN(val, ath_wprobe_globals);
++ if (cc & 0xf0000000) {
++ /* scale down if the counters are near max */
++ cc >>= 8;
++ busy >>= 8;
++ rx >>= 8;
++ tx >>= 8;
++ }
++ if (ah->ah_macType < 5212)
++ goto phy_skip;
++ if (!cc)
++ goto phy_skip;
++ if (busy > cc)
++ goto phy_skip;
++ if (rx > cc)
++ goto phy_skip;
++ if (tx > cc)
++ goto phy_skip;
++ busy = (busy * 100) / cc;
++ rx = (rx * 100) / cc;
++ tx = (tx * 100) / cc;
++ WPROBE_SET(WP_GLOBAL_PHY_BUSY, U8, busy);
++ WPROBE_SET(WP_GLOBAL_PHY_RX, U8, rx);
++ WPROBE_SET(WP_GLOBAL_PHY_TX, U8, tx);
++ WPROBE_SET(WP_GLOBAL_FRAMES, U32, avp->av_rxframes);
++ WPROBE_SET(WP_GLOBAL_PROBEREQ, U32, avp->av_rxprobereq);
++
++phy_skip:
++ WPROBE_SET(WP_GLOBAL_NOISE, S16, noise);
++ WPROBE_FILL_END();
++
++out:
++ return 0;
++}
++
++#undef AR5K_TXFC
++#undef AR5K_RXFC
++#undef AR5K_RXCLEAR
++#undef AR5K_CYCLES
++#undef AR5K_MIBC
++#undef AR5K_MIBC_FREEZE
++#undef READ_CLR
++
++static const struct wprobe_iface ath_wprobe_dev = {
++ .link_items = ath_wprobe_link,
++ .n_link_items = ARRAY_SIZE(ath_wprobe_link),
++ .global_items = ath_wprobe_globals,
++ .n_global_items = ARRAY_SIZE(ath_wprobe_globals),
++ .sync_data = ath_wprobe_sync,
++};
++
++static int
++ath_lookup_rateval(struct ieee80211_node *ni, int rate)
++{
++ struct ieee80211vap *vap = ni->ni_vap;
++ struct ieee80211com *ic = vap->iv_ic;
++ struct ath_softc *sc = ic->ic_dev->priv;
++ const HAL_RATE_TABLE *rt = sc->sc_currates;
++
++ if ((!rt) || (rate < 0) || (rate >= ARRAY_SIZE(sc->sc_hwmap)))
++ return -1;
++
++ rate = sc->sc_hwmap[rate].ieeerate;
++ rate = sc->sc_rixmap[rate & IEEE80211_RATE_VAL];
++ if ((rate < 0) || (rate >= rt->rateCount))
++ return -1;
++
++ return rt->info[rate].rateKbps;
++}
++
++static void
++ath_wprobe_report_rx(struct ieee80211vap *vap, struct ath_rx_status *rs, struct sk_buff *skb)
++{
++ const struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data;
++ struct wprobe_wlan_hdr hdr;
++ struct ath_vap *avp;
++ int hdrsize;
++
++ if (wprobe_disabled())
++ return;
++
++ avp = ATH_VAP(vap);
++ avp->av_rxframes++;
++ if (wh->i_fc[0] == (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_REQ))
++ avp->av_rxprobereq++;
++
++ memset(&hdr, 0, sizeof(hdr));
++ hdr.len = skb->len;
++ hdr.snr = rs->rs_rssi;
++ hdr.type = WPROBE_PKT_RX;
++ if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
++ hdrsize = sizeof(struct ieee80211_ctlframe_addr2);
++ else
++ hdrsize = ieee80211_hdrsize(skb->data);
++ wprobe_add_frame(&avp->av_wpif, &hdr, skb->data, hdrsize + 0x42);
++}
++
++
++static void
++ath_node_sample_rx(struct ieee80211_node *ni, struct ath_rx_status *rs)
++{
++ struct ath_node *an = ATH_NODE(ni);
++ struct ieee80211vap *vap = ni->ni_vap;
++ struct ieee80211com *ic = vap->iv_ic;
++ struct wprobe_link *l = &an->an_wplink;
++ struct wprobe_value *v = l->val;
++ unsigned long flags;
++ int rate;
++
++ if (wprobe_disabled() || !an->an_wplink_active || !l->val)
++ return;
++
++ rate = ath_lookup_rateval(ni, rs->rs_rate);
++
++ spin_lock_irqsave(&l->iface->lock, flags);
++ WPROBE_FILL_BEGIN(v, ath_wprobe_link);
++ WPROBE_SET(WP_NODE_RSSI, U8, rs->rs_rssi);
++ WPROBE_SET(WP_NODE_SIGNAL, S16, ic->ic_channoise + rs->rs_rssi);
++ if ((rate > 0) && (rate <= 600000))
++ WPROBE_SET(WP_NODE_RX_RATE, U16, rate);
++ WPROBE_FILL_END();
++ wprobe_update_stats(l->iface, l);
++ spin_unlock_irqrestore(&l->iface->lock, flags);
++}
++
++static void
++ath_wprobe_report_tx(struct ieee80211vap *vap, struct ath_tx_status *ts, struct sk_buff *skb)
++{
++ const struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data;
++ struct wprobe_wlan_hdr hdr;
++ struct ath_vap *avp;
++ int hdrsize;
++
++ if (wprobe_disabled())
++ return;
++
++ avp = ATH_VAP(vap);
++
++ memset(&hdr, 0, sizeof(hdr));
++ hdr.len = skb->len;
++ hdr.snr = ts->ts_rssi;
++ hdr.type = WPROBE_PKT_TX;
++ if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
++ hdrsize = sizeof(struct ieee80211_ctlframe_addr2);
++ else
++ hdrsize = ieee80211_hdrsize(skb->data);
++ wprobe_add_frame(&avp->av_wpif, &hdr, skb->data, hdrsize + 0x42);
++}
++
++
++
++static void
++ath_node_sample_tx(struct ieee80211_node *ni, struct ath_tx_status *ts, struct sk_buff *skb)
++{
++ struct ath_node *an = ATH_NODE(ni);
++ struct ieee80211vap *vap = ni->ni_vap;
++ struct ieee80211com *ic = vap->iv_ic;
++ struct wprobe_link *l = &an->an_wplink;
++ struct wprobe_value *v = l->val;
++ unsigned long flags;
++ int rate, rexmit_counter;
++ int len = skb->len;
++
++ if (wprobe_disabled() || !an->an_wplink_active || !l->val)
++ return;
++
++ ath_wprobe_report_tx(vap, ts, skb);
++ rate = ath_lookup_rateval(ni, ts->ts_rate);
++
++ spin_lock_irqsave(&l->iface->lock, flags);
++ WPROBE_FILL_BEGIN(v, ath_wprobe_link);
++ WPROBE_SET(WP_NODE_RSSI, U8, ts->ts_rssi);
++ WPROBE_SET(WP_NODE_SIGNAL, S16, ic->ic_channoise + ts->ts_rssi);
++
++ if (len <= 200)
++ rexmit_counter = WP_NODE_RETRANSMIT_200;
++ else if (len <= 400)
++ rexmit_counter = WP_NODE_RETRANSMIT_400;
++ else if (len <= 800)
++ rexmit_counter = WP_NODE_RETRANSMIT_800;
++ else
++ rexmit_counter = WP_NODE_RETRANSMIT_1600;
++ WPROBE_SET(rexmit_counter, U8, ts->ts_longretry);
++
++ if ((rate > 0) && (rate <= 600000))
++ WPROBE_SET(WP_NODE_TX_RATE, U16, rate);
++ WPROBE_FILL_END();
++ wprobe_update_stats(l->iface, l);
++ spin_unlock_irqrestore(&l->iface->lock, flags);
++}
++
++static void
++ath_wprobe_node_join(struct ieee80211vap *vap, struct ieee80211_node *ni)
++{
++ struct wprobe_iface *dev;
++ struct wprobe_link *l;
++ struct ath_vap *avp;
++ struct ath_node *an = ATH_NODE(ni);
++
++ if (wprobe_disabled() || an->an_wplink_active)
++ return;
++
++ avp = ATH_VAP(vap);
++ dev = &avp->av_wpif;
++ l = &an->an_wplink;
++
++ ieee80211_ref_node(ni);
++ wprobe_add_link(dev, l, ni->ni_macaddr);
++ an->an_wplink_active = 1;
++}
++
++static void
++ath_wprobe_do_node_leave(struct work_struct *work)
++{
++ struct ath_node *an = container_of(work, struct ath_node, an_destroy);
++ struct ieee80211_node *ni = &an->an_node;
++ struct ieee80211vap *vap = ni->ni_vap;
++ struct wprobe_iface *dev;
++ struct wprobe_link *l;
++ struct ath_vap *avp;
++
++ avp = ATH_VAP(vap);
++ dev = &avp->av_wpif;
++ l = &an->an_wplink;
++
++ wprobe_remove_link(dev, l);
++ ieee80211_unref_node(&ni);
++ atomic_dec(&cleanup_tasks);
++}
++
++static void
++ath_wprobe_node_leave(struct ieee80211vap *vap, struct ieee80211_node *ni)
++{
++ struct ath_node *an = ATH_NODE(ni);
++
++ if (wprobe_disabled() || !an->an_wplink_active)
++ return;
++
++ atomic_inc(&cleanup_tasks);
++ an->an_wplink_active = 0;
++ IEEE80211_INIT_WORK(&an->an_destroy, ath_wprobe_do_node_leave);
++ schedule_work(&an->an_destroy);
++}
++
++static void
++ath_init_wprobe_dev(struct ath_vap *avp)
++{
++ struct ieee80211vap *vap = &avp->av_vap;
++ struct wprobe_iface *dev = &avp->av_wpif;
++
++ if (wprobe_disabled() || (vap->iv_opmode == IEEE80211_M_WDS))
++ return;
++
++ memcpy(dev, &ath_wprobe_dev, sizeof(struct wprobe_iface));
++ dev->addr = vap->iv_myaddr;
++ dev->name = vap->iv_dev->name;
++ wprobe_add_iface(dev);
++}
++
++static void
++ath_remove_wprobe_dev(struct ath_vap *avp)
++{
++ struct ieee80211vap *vap = &avp->av_vap;
++ struct ieee80211com *ic = vap->iv_ic;
++ struct ieee80211_node *ni;
++ struct wprobe_iface *dev = &avp->av_wpif;
++ struct wprobe_link *l;
++ struct ath_node *an;
++ unsigned long flags;
++
++ if (wprobe_disabled() || (vap->iv_opmode == IEEE80211_M_WDS))
++ return;
++
++restart:
++ rcu_read_lock();
++ list_for_each_entry_rcu(l, &dev->links, list) {
++ an = container_of(l, struct ath_node, an_wplink);
++
++ if (!an->an_wplink_active)
++ continue;
++
++ ni = &an->an_node;
++ ath_wprobe_node_leave(vap, ni);
++ rcu_read_unlock();
++ goto restart;
++ }
++ rcu_read_unlock();
++
++ /* wait for the cleanup tasks to finish */
++ while (atomic_read(&cleanup_tasks) != 0) {
++ schedule();
++ }
++
++ wprobe_remove_iface(dev);
++}
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -400,6 +400,7 @@ static int countrycode = -1;
+ static int maxvaps = -1;
+ static int outdoor = -1;
+ static int xchanmode = -1;
++#include "ath_wprobe.c"
+ static int beacon_cal = 1;
+
+ static const struct ath_hw_detect generic_hw_info = {
+@@ -1525,6 +1526,7 @@ ath_vap_create(struct ieee80211com *ic,
+ ath_hal_intrset(ah, sc->sc_imask);
+ }
+
++ ath_init_wprobe_dev(avp);
+ return vap;
+ }
+
+@@ -1606,6 +1608,7 @@ ath_vap_delete(struct ieee80211vap *vap)
+ decrease = 0;
+
+ ieee80211_vap_detach(vap);
++ ath_remove_wprobe_dev(ATH_VAP(vap));
+ /* NB: memory is reclaimed through dev->destructor callback */
+ if (decrease)
+ sc->sc_nvaps--;
+@@ -5940,6 +5943,7 @@ ath_node_cleanup(struct ieee80211_node *
+ /* Clean up node-specific rate things - this currently appears to
+ * always be a no-op */
+ sc->sc_rc->ops->node_cleanup(sc, ATH_NODE(ni));
++ ath_wprobe_node_leave(ni->ni_vap, ni);
+
+ ATH_NODE_UAPSD_LOCK_IRQ(an);
+ #ifdef IEEE80211_DEBUG_REFCNT
+@@ -7010,6 +7014,8 @@ drop_micfail:
+ goto lookup_slowpath;
+ }
+ ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi);
++ ath_node_sample_rx(ni, rs);
++ ath_wprobe_report_rx(ni->ni_vap, rs, skb);
+ type = ieee80211_input(ni->ni_vap, ni, skb, rs->rs_rssi, bf->bf_tsf);
+ ieee80211_unref_node(&ni);
+ } else {
+@@ -7024,15 +7030,21 @@ lookup_slowpath:
+ else
+ vap = ieee80211_find_rxvap(ic, wh->i_addr1);
+
+- if (vap)
++ if (vap) {
++ ath_wprobe_report_rx(vap, rs, skb);
+ ni = ieee80211_find_rxnode(ic, vap, wh);
+- else
++ } else {
++ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
++ ath_wprobe_report_rx(vap, rs, skb);
++ }
+ ni = NULL;
++ }
+
+ if (ni != NULL) {
+ ieee80211_keyix_t keyix;
+
+ ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi);
++ ath_node_sample_rx(ni, rs);
+ type = ieee80211_input(vap, ni, skb, rs->rs_rssi, bf->bf_tsf);
+ /*
+ * If the station has a key cache slot assigned
+@@ -8612,6 +8624,7 @@ ath_tx_processq(struct ath_softc *sc, st
+ sc->sc_stats.ast_tx_rssi = ts->ts_rssi;
+ ATH_RSSI_LPF(an->an_halstats.ns_avgtxrssi,
+ ts->ts_rssi);
++ ath_node_sample_tx(&an->an_node, ts, bf->bf_skb);
+ if (bf->bf_skb->priority == WME_AC_VO ||
+ bf->bf_skb->priority == WME_AC_VI)
+ ni->ni_ic->ic_wme.wme_hipri_traffic++;
+@@ -10111,6 +10124,7 @@ ath_newassoc(struct ieee80211_node *ni,
+ struct ath_softc *sc = ic->ic_dev->priv;
+
+ sc->sc_rc->ops->newassoc(sc, ATH_NODE(ni), isnew);
++ ath_wprobe_node_join(ni->ni_vap, ni);
+
+ /* are we supporting compression? */
+ if (!(vap->iv_ath_cap & ni->ni_ath_flags & IEEE80211_NODE_COMP))
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -46,6 +46,7 @@
+ #include "ah_desc.h"
+ #include "ah_os.h"
+ #include "if_athioctl.h"
++#include <linux/wprobe.h>
+ #include "net80211/ieee80211.h" /* XXX for WME_NUM_AC */
+ #include <asm/io.h>
+ #include <linux/list.h>
+@@ -352,6 +353,9 @@ typedef STAILQ_HEAD(, ath_buf) ath_bufhe
+ /* driver-specific node state */
+ struct ath_node {
+ struct ieee80211_node an_node; /* base class */
++ struct wprobe_link an_wplink;
++ uint8_t an_wplink_active;
++ struct work_struct an_destroy;
+ u_int16_t an_decomp_index; /* decompression mask index */
+ u_int32_t an_avgrssi; /* average rssi over all rx frames */
+ u_int8_t an_prevdatarix; /* rate ix of last data frame */
+@@ -521,6 +525,9 @@ struct ath_vap {
+ #else
+ unsigned int av_beacon_alloc;
+ #endif
++ struct wprobe_iface av_wpif;
++ u32 av_rxframes;
++ u32 av_rxprobereq;
+ };
+ #define ATH_VAP(_v) ((struct ath_vap *)(_v))
+
diff --git a/package/madwifi/patches/417-beacon_txpower.patch b/package/madwifi/patches/417-beacon_txpower.patch
new file mode 100644
index 000000000..8a59c1211
--- /dev/null
+++ b/package/madwifi/patches/417-beacon_txpower.patch
@@ -0,0 +1,81 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -395,7 +395,7 @@ static int bstuck_thresh = BSTUCK_THRESH
+ static char *autocreate = NULL;
+ static char *ratectl = DEF_RATE_CTL;
+ static int rfkill = 0;
+-static int tpc = 0;
++static int tpc = 1;
+ static int countrycode = -1;
+ static int maxvaps = -1;
+ static int outdoor = -1;
+@@ -4932,6 +4932,7 @@ ath_beacon_setup(struct ath_softc *sc, s
+ (((_ic)->ic_flags & (IEEE80211_F_SHPREAMBLE | IEEE80211_F_USEBARKER))\
+ == IEEE80211_F_SHPREAMBLE)
+ struct ieee80211com *ic = bf->bf_node->ni_ic;
++ struct ieee80211vap *vap = bf->bf_node->ni_vap;
+ struct sk_buff *skb = bf->bf_skb;
+ struct ath_hal *ah = sc->sc_ah;
+ struct ath_desc *ds;
+@@ -4999,7 +5000,7 @@ ath_beacon_setup(struct ath_softc *sc, s
+ skb->len + IEEE80211_CRC_LEN, /* frame length */
+ sizeof(struct ieee80211_frame), /* header length */
+ HAL_PKT_TYPE_BEACON, /* Atheros packet type */
+- bf->bf_node->ni_txpower, /* txpower XXX */
++ (vap->iv_beacon_txpow ? vap->iv_beacon_txpow : 63),
+ rate, 1, /* series 0 rate/tries */
+ HAL_TXKEYIX_INVALID, /* no encryption */
+ antenna, /* antenna mode */
+--- a/net80211/ieee80211_ioctl.h
++++ b/net80211/ieee80211_ioctl.h
+@@ -652,6 +652,7 @@ enum {
+ IEEE80211_PARAM_WDS_SEP = 82, /* move wds stations into separate interfaces */
+ IEEE80211_PARAM_MAXASSOC = 83, /* maximum associated stations */
+ IEEE80211_PARAM_PROBEREQ = 84, /* enable handling of probe requests */
++ IEEE80211_PARAM_BEACON_TXP = 85, /* set beacon tx power */
+ };
+
+ #define SIOCG80211STATS (SIOCDEVPRIVATE+2)
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -254,6 +254,7 @@ struct ieee80211vap {
+ u_int8_t iv_dtim_period; /* DTIM period */
+ u_int8_t iv_dtim_count; /* DTIM count from last bcn */
+ /* set/unset aid pwrsav state */
++ u_int8_t iv_beacon_txpow; /* beacon tx power */
+ 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 */
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -2871,6 +2871,9 @@ ieee80211_ioctl_setparam(struct net_devi
+ case IEEE80211_PARAM_PROBEREQ:
+ vap->iv_no_probereq = !value;
+ break;
++ case IEEE80211_PARAM_BEACON_TXP:
++ vap->iv_beacon_txpow = value;
++ break;
+ #ifdef ATH_REVERSE_ENGINEERING
+ case IEEE80211_PARAM_DUMPREGS:
+ ieee80211_dump_registers(dev, info, w, extra);
+@@ -3236,6 +3239,9 @@ ieee80211_ioctl_getparam(struct net_devi
+ case IEEE80211_PARAM_PROBEREQ:
+ param[0] = !vap->iv_no_probereq;
+ break;
++ case IEEE80211_PARAM_BEACON_TXP:
++ param[0] = vap->iv_beacon_txpow;
++ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+@@ -5810,6 +5816,10 @@ static const struct iw_priv_args ieee802
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "probereq"},
+ { IEEE80211_PARAM_PROBEREQ,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_probereq"},
++ { IEEE80211_PARAM_BEACON_TXP,
++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "beacon_pwr"},
++ { IEEE80211_PARAM_BEACON_TXP,
++ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_beacon_pwr"},
+
+ #ifdef ATH_REVERSE_ENGINEERING
+ /*
diff --git a/package/madwifi/patches/419-skb_unmap_crash.patch b/package/madwifi/patches/419-skb_unmap_crash.patch
new file mode 100644
index 000000000..37602e491
--- /dev/null
+++ b/package/madwifi/patches/419-skb_unmap_crash.patch
@@ -0,0 +1,20 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -13499,7 +13499,7 @@ cleanup_ath_buf(struct ath_softc *sc, st
+ if (bf == NULL)
+ return bf;
+
+- if (bf->bf_skbaddr) {
++ if (bf->bf_skb && bf->bf_skbaddr) {
+ bus_unmap_single(
+ sc->sc_bdev,
+ bf->bf_skbaddr,
+@@ -13507,8 +13507,6 @@ cleanup_ath_buf(struct ath_softc *sc, st
+ sc->sc_rxbufsize : bf->bf_skb->len),
+ direction);
+ bf->bf_skbaddr = 0;
+- bf->bf_desc->ds_link = 0;
+- bf->bf_desc->ds_data = 0;
+ }
+
+ #ifdef ATH_SUPERG_FF
diff --git a/package/madwifi/patches/420-diversity_fix.patch b/package/madwifi/patches/420-diversity_fix.patch
new file mode 100644
index 000000000..90bcd0e16
--- /dev/null
+++ b/package/madwifi/patches/420-diversity_fix.patch
@@ -0,0 +1,86 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -797,7 +797,6 @@ ath_attach(u_int16_t devid, struct net_d
+ break;
+ }
+
+- sc->sc_setdefantenna = ath_setdefantenna;
+ sc->sc_rc = ieee80211_rate_attach(sc, ratectl);
+ if (sc->sc_rc == NULL) {
+ error = EIO;
+@@ -2624,9 +2623,6 @@ ath_init(struct net_device *dev)
+ ath_radar_update(sc);
+ ath_rp_flush(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
+@@ -3019,7 +3015,6 @@ ath_reset(struct net_device *dev)
+ ath_setintmit(sc);
+ ath_update_txpow(sc); /* update tx power state */
+ ath_radar_update(sc);
+- ath_setdefantenna(sc, sc->sc_defant);
+ if (ath_startrecv(sc) != 0) /* restart recv */
+ EPRINTF(sc, "Unable to start receive logic.\n");
+ if (sc->sc_softled)
+@@ -5353,27 +5348,6 @@ ath_beacon_send(struct ath_softc *sc, in
+ } else if ((sc->sc_updateslot == COMMIT) && (sc->sc_slotupdate == slot))
+ ath_setslottime(sc); /* commit change to hardware */
+
+- if ((!sc->sc_stagbeacons || slot == 0) && (!sc->sc_diversity)) {
+- unsigned int otherant;
+- /*
+- * Check recent per-antenna transmit statistics and flip
+- * the default rx antenna if noticeably more frames went out
+- * on the non-default antenna. Only do this if rx diversity
+- * is off.
+- * XXX assumes 2 antennae
+- */
+- otherant = sc->sc_defant & 1 ? 2 : 1;
+- if (sc->sc_ant_tx[otherant] > sc->sc_ant_tx[sc->sc_defant] +
+- ATH_ANTENNA_DIFF) {
+- DPRINTF(sc, ATH_DEBUG_BEACON,
+- "Flip default antenna to %u, %u > %u\n",
+- otherant, sc->sc_ant_tx[otherant],
+- sc->sc_ant_tx[sc->sc_defant]);
+- ath_setdefantenna(sc, otherant);
+- }
+- sc->sc_ant_tx[1] = sc->sc_ant_tx[2] = 0;
+- }
+-
+ if (bfaddr != 0) {
+ /*
+ * Stop any current DMA and put the new frame(s) on the queue.
+@@ -6734,9 +6708,8 @@ ath_setdefantenna(struct ath_softc *sc,
+ {
+ struct ath_hal *ah = sc->sc_ah;
+
+- /* XXX block beacon interrupts */
+- ath_hal_setdiversity(ah, (sc->sc_diversity != 0));
+ ath_hal_setdefantenna(ah, antenna);
++ ath_hal_setantennaswitch(ah, sc->sc_diversity ? 0 : antenna);
+ if (sc->sc_defant != antenna)
+ sc->sc_stats.ast_ant_defswitch++;
+ sc->sc_defant = antenna;
+@@ -11160,7 +11133,7 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+ break;
+ }
+ sc->sc_diversity = val;
+- ath_hal_setdiversity(ah, val);
++ ath_setdefantenna(sc, sc->sc_defant);
+ break;
+ case ATH_TXINTRPERIOD:
+ /* XXX: validate? */
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -640,7 +640,6 @@ struct ath_softc {
+ spinlock_t sc_hal_lock; /* hardware access lock */
+ struct ath_ratectrl *sc_rc; /* tx rate control support */
+ struct ath_tx99 *sc_tx99; /* tx99 support */
+- void (*sc_setdefantenna)(struct ath_softc *, u_int);
+ const struct ath_hw_detect *sc_hwinfo;
+
+ unsigned int sc_invalid:1; /* being detached */
diff --git a/package/madwifi/patches/421-channel_handling.patch b/package/madwifi/patches/421-channel_handling.patch
new file mode 100644
index 000000000..2a8ec27ce
--- /dev/null
+++ b/package/madwifi/patches/421-channel_handling.patch
@@ -0,0 +1,1351 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -148,7 +148,6 @@ static int ath_key_set(struct ieee80211v
+ static void ath_key_update_begin(struct ieee80211vap *);
+ static void ath_key_update_end(struct ieee80211vap *);
+ static void ath_mode_init(struct net_device *);
+-static void ath_setslottime(struct ath_softc *);
+ static void ath_updateslot(struct net_device *);
+ static int ath_beaconq_setup(struct ath_softc *);
+ static int ath_beacon_alloc(struct ath_softc *, struct ieee80211_node *);
+@@ -240,7 +239,7 @@ static void ath_setup_stationkey(struct
+ static void ath_setup_stationwepkey(struct ieee80211_node *);
+ static void ath_setup_keycacheslot(struct ath_softc *, struct ieee80211_node *);
+ static void ath_newassoc(struct ieee80211_node *, int);
+-static int ath_getchannels(struct net_device *, u_int, HAL_BOOL, HAL_BOOL);
++static int ath_getchannels(struct net_device *);
+ static void ath_led_event(struct ath_softc *, int);
+ static void ath_update_txpow(struct ath_softc *);
+
+@@ -265,7 +264,6 @@ static int ath_change_mtu(struct net_dev
+ static int ath_ioctl(struct net_device *, struct ifreq *, int);
+
+ static int ath_rate_setup(struct net_device *, u_int);
+-static void ath_setup_subrates(struct net_device *);
+ #ifdef ATH_SUPERG_XR
+ static int ath_xr_rate_setup(struct net_device *);
+ static void ath_grppoll_txq_setup(struct ath_softc *, int, int);
+@@ -387,8 +385,6 @@ static void ath_fetch_idle_time(struct a
+
+ /* 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 */
+-static int ath_outdoor = AH_FALSE; /* enable outdoor use */
+ static int ath_xchanmode = AH_TRUE; /* enable extended channels */
+ static int ath_maxvaps = ATH_MAXVAPS_DEFAULT; /* set default maximum vaps */
+ static int bstuck_thresh = BSTUCK_THRESH; /* Stuck beacon count required for reset */
+@@ -396,9 +392,7 @@ static char *autocreate = NULL;
+ static char *ratectl = DEF_RATE_CTL;
+ static int rfkill = 0;
+ static int tpc = 1;
+-static int countrycode = -1;
+ static int maxvaps = -1;
+-static int outdoor = -1;
+ static int xchanmode = -1;
+ #include "ath_wprobe.c"
+ static int beacon_cal = 1;
+@@ -437,9 +431,7 @@ static struct notifier_block ath_event_b
+
+ #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");
+ MODULE_PARM(xchanmode, "i");
+ MODULE_PARM(rfkill, "i");
+ #ifdef ATH_CAP_TPC
+@@ -451,9 +443,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);
+ module_param(xchanmode, int, 0600);
+ module_param(rfkill, int, 0600);
+ #ifdef ATH_CAP_TPC
+@@ -463,9 +453,7 @@ module_param(bstuck_thresh, int, 0600);
+ module_param(autocreate, charp, 0600);
+ module_param(ratectl, charp, 0600);
+ #endif
+-MODULE_PARM_DESC(countrycode, "Override default country code");
+ MODULE_PARM_DESC(maxvaps, "Maximum VAPs");
+-MODULE_PARM_DESC(outdoor, "Enable/disable outdoor use");
+ MODULE_PARM_DESC(xchanmode, "Enable/disable extended channel mode");
+ MODULE_PARM_DESC(rfkill, "Enable/disable RFKILL capability");
+ #ifdef ATH_CAP_TPC
+@@ -531,6 +519,50 @@ MODULE_PARM_DESC(ieee80211_debug, "Load-
+ (bssid)[0] |= (((id) << 2) | 0x02); \
+ } while (0)
+
++static inline int ath_chan2mode(struct ieee80211_channel *c)
++{
++ if (IEEE80211_IS_CHAN_HALF(c))
++ return ATH_MODE_HALF;
++ else if (IEEE80211_IS_CHAN_QUARTER(c))
++ return ATH_MODE_QUARTER;
++ else
++ return ieee80211_chan2mode(c);
++}
++
++static inline int rate_hal2ieee(int dot11Rate, int f)
++{
++ int flag = dot11Rate & ~(IEEE80211_RATE_VAL);
++ dot11Rate &= IEEE80211_RATE_VAL;
++
++ if (f == 4) { /* Quarter */
++ if (dot11Rate == 4)
++ return 18 | flag;
++ }
++ return (dot11Rate * f) | flag;
++}
++
++static inline int rate_factor(int mode)
++{
++ int f;
++
++ /*
++ * NB: Fix up rates. HAL returns half or quarter dot11Rates,
++ * while the stack deals with full rates only
++ */
++ switch(mode) {
++ case ATH_MODE_HALF:
++ f = 2;
++ break;
++ case ATH_MODE_QUARTER:
++ f = 4;
++ break;
++ default:
++ f = 1;
++ break;
++ }
++ return f;
++}
++
+ /* Initialize ath_softc structure */
+
+ int
+@@ -647,14 +679,6 @@ ath_attach(u_int16_t devid, struct net_d
+ for (i = 0; i < sc->sc_keymax; i++)
+ ath_hal_keyreset(ah, i);
+
+- /*
+- * Collect the channel list using the default country
+- * code and including outdoor channels. The 802.11 layer
+- * is responsible for filtering this list based on settings
+- * like the phy mode.
+- */
+- if (countrycode != -1)
+- ath_countrycode = countrycode;
+ if (maxvaps != -1) {
+ ath_maxvaps = maxvaps;
+ if (ath_maxvaps < ATH_MAXVAPS_MIN)
+@@ -662,17 +686,14 @@ ath_attach(u_int16_t devid, struct net_d
+ else if (ath_maxvaps > ATH_MAXVAPS_MAX)
+ ath_maxvaps = ATH_MAXVAPS_MAX;
+ }
+- if (outdoor != -1)
+- ath_outdoor = outdoor;
+ if (xchanmode != -1)
+ ath_xchanmode = xchanmode;
+- error = ath_getchannels(dev, ath_countrycode,
+- ath_outdoor, ath_xchanmode);
++ error = ath_getchannels(dev);
+ if (error != 0)
+ goto bad;
+
+- ic->ic_country_code = ath_countrycode;
+- ic->ic_country_outdoor = ath_outdoor;
++ ic->ic_country_code = CTRY_DEFAULT;
++ ic->ic_country_outdoor = 0;
+
+ IPRINTF(sc, "Switching rfkill capability %s\n",
+ rfkill ? "on" : "off");
+@@ -686,9 +707,8 @@ ath_attach(u_int16_t devid, struct net_d
+ ath_rate_setup(dev, IEEE80211_MODE_11G);
+ ath_rate_setup(dev, IEEE80211_MODE_TURBO_A);
+ ath_rate_setup(dev, IEEE80211_MODE_TURBO_G);
+-
+- /* Setup for half/quarter rates */
+- ath_setup_subrates(dev);
++ ath_rate_setup(dev, ATH_MODE_HALF);
++ ath_rate_setup(dev, ATH_MODE_QUARTER);
+
+ /* NB: setup here so ath_rate_update is happy */
+ ath_setcurmode(sc, IEEE80211_MODE_11A);
+@@ -908,10 +928,6 @@ ath_attach(u_int16_t devid, struct net_d
+ IEEE80211_ATHC_COMP : 0);
+ #endif
+
+-#ifdef ATH_SUPERG_DYNTURBO
+- ic->ic_ath_cap |= (ath_hal_turboagsupported(ah, ath_countrycode) ?
+- (IEEE80211_ATHC_TURBOP | IEEE80211_ATHC_AR) : 0);
+-#endif
+ #ifdef ATH_SUPERG_XR
+ ic->ic_ath_cap |= (ath_hal_xrsupported(ah) ? IEEE80211_ATHC_XR : 0);
+ #endif
+@@ -4470,17 +4486,17 @@ ath_mode_init(struct net_device *dev)
+ * Set the slot time based on the current setting.
+ */
+ static void
+-ath_setslottime(struct ath_softc *sc)
++ath_settiming(struct ath_softc *sc)
+ {
+- struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_hal *ah = sc->sc_ah;
++ u_int offset = getTimingOffset(sc);
+
+- if (sc->sc_slottimeconf > 0) /* manual override */
+- ath_hal_setslottime(ah, sc->sc_slottimeconf);
+- else if (ic->ic_flags & IEEE80211_F_SHSLOT)
+- ath_hal_setslottime(ah, HAL_SLOT_TIME_9);
+- else
+- ath_hal_setslottime(ah, HAL_SLOT_TIME_20);
++ if (sc->sc_slottimeconf > 0)
++ ath_hal_setslottime(ah, offset + sc->sc_slottimeconf);
++ if (sc->sc_acktimeconf > 0)
++ ath_hal_setacktimeout(ah, 2 * offset + sc->sc_acktimeconf);
++ if (sc->sc_ctstimeconf > 0)
++ ath_hal_setctstimeout(ah, 2 * offset + sc->sc_ctstimeconf);
+ sc->sc_updateslot = OK;
+ }
+
+@@ -4502,7 +4518,7 @@ ath_updateslot(struct net_device *dev)
+ if (ic->ic_opmode == IEEE80211_M_HOSTAP)
+ sc->sc_updateslot = UPDATE;
+ else if (dev->flags & IFF_RUNNING)
+- ath_setslottime(sc);
++ ath_settiming(sc);
+ }
+
+ #ifdef ATH_SUPERG_DYNTURBO
+@@ -5346,7 +5362,7 @@ ath_beacon_send(struct ath_softc *sc, in
+ sc->sc_updateslot = COMMIT; /* commit next beacon */
+ sc->sc_slotupdate = slot;
+ } else if ((sc->sc_updateslot == COMMIT) && (sc->sc_slotupdate == slot))
+- ath_setslottime(sc); /* commit change to hardware */
++ ath_settiming(sc); /* commit change to hardware */
+
+ if (bfaddr != 0) {
+ /*
+@@ -7802,12 +7818,14 @@ ath_get_ivlen(struct ieee80211_key *k)
+ * Get transmit rate index using rate in Kbps
+ */
+ static __inline int
+-ath_tx_findindex(const HAL_RATE_TABLE *rt, int rate)
++ath_tx_findindex(struct ath_softc *sc, const HAL_RATE_TABLE *rt, int rate)
+ {
+ unsigned int i, ndx = 0;
++ int f;
+
++ f = rate_factor(sc->sc_curmode);
+ for (i = 0; i < rt->rateCount; i++) {
+- if (rt->info[i].rateKbps == rate) {
++ if ((rt->info[i].rateKbps * f) == rate) {
+ ndx = i;
+ break;
+ }
+@@ -8100,7 +8118,7 @@ ath_tx_start(struct net_device *dev, str
+ atype = HAL_PKT_TYPE_NORMAL; /* default */
+
+ if (ismcast) {
+- rix = ath_tx_findindex(rt, vap->iv_mcast_rate);
++ rix = ath_tx_findindex(sc, rt, vap->iv_mcast_rate);
+ txrate = rt->info[rix].rateCode;
+ if (shortPreamble)
+ txrate |= rt->info[rix].shortPreamble;
+@@ -9067,7 +9085,7 @@ ath_chan_change(struct ath_softc *sc, st
+ struct net_device *dev = sc->sc_dev;
+ enum ieee80211_phymode mode;
+
+- mode = ieee80211_chan2mode(chan);
++ mode = ath_chan2mode(chan);
+
+ ath_rate_setup(dev, mode);
+ ath_setcurmode(sc, mode);
+@@ -10124,8 +10142,7 @@ ath_newassoc(struct ieee80211_node *ni,
+ }
+
+ static int
+-ath_getchannels(struct net_device *dev, u_int cc,
+- HAL_BOOL outdoor, HAL_BOOL xchanmode)
++ath_getchannels(struct net_device *dev)
+ {
+ struct ath_softc *sc = dev->priv;
+ struct ieee80211com *ic = &sc->sc_ic;
+@@ -10139,17 +10156,31 @@ ath_getchannels(struct net_device *dev,
+ EPRINTF(sc, "Insufficient memory for channel table!\n");
+ return -ENOMEM;
+ }
++
++restart:
+ if (!ath_hal_init_channels(ah, chans, IEEE80211_CHAN_MAX, &nchan,
+ ic->ic_regclassids, IEEE80211_REGCLASSIDS_MAX, &ic->ic_nregclass,
+- cc, HAL_MODE_ALL, outdoor, xchanmode)) {
++ ic->ic_country_code, HAL_MODE_ALL, ic->ic_country_outdoor, ath_xchanmode)) {
+ u_int32_t rd;
+
+ ath_hal_getregdomain(ah, &rd);
+ EPRINTF(sc, "Unable to collect channel list from HAL; "
+- "regdomain likely %u country code %u\n", rd, cc);
++ "regdomain likely %u country code %u\n", rd, ic->ic_country_code);
++ if ((ic->ic_country_code != CTRY_DEFAULT) ||
++ (ic->ic_country_outdoor != 0)) {
++ EPRINTF(sc, "Reverting to defaults\n");
++ ic->ic_country_code = CTRY_DEFAULT;
++ ic->ic_country_outdoor = 0;
++ goto restart;
++ }
+ kfree(chans);
+ return -EINVAL;
+ }
++#ifdef ATH_SUPERG_DYNTURBO
++ ic->ic_ath_cap &= ~(IEEE80211_ATHC_TURBOP | IEEE80211_ATHC_AR);
++ ic->ic_ath_cap |= (ath_hal_turboagsupported(ah, ic->ic_country_code) ?
++ (IEEE80211_ATHC_TURBOP | IEEE80211_ATHC_AR) : 0);
++#endif
+ /*
+ * Convert HAL channels to ieee80211 ones.
+ */
+@@ -10395,7 +10426,7 @@ ath_xr_rate_setup(struct net_device *dev
+ struct ieee80211com *ic = &sc->sc_ic;
+ const HAL_RATE_TABLE *rt;
+ struct ieee80211_rateset *rs;
+- unsigned int i, maxrates;
++ unsigned int i, j, maxrates;
+ sc->sc_xr_rates = ath_hal_getratetable(ah, HAL_MODE_XR);
+ rt = sc->sc_xr_rates;
+ if (rt == NULL)
+@@ -10408,57 +10439,16 @@ ath_xr_rate_setup(struct net_device *dev
+ } else
+ maxrates = rt->rateCount;
+ rs = &ic->ic_sup_xr_rates;
+- for (i = 0; i < maxrates; i++)
+- rs->rs_rates[i] = rt->info[i].dot11Rate;
+- rs->rs_nrates = maxrates;
++ for (j = 0, i = 0; i < maxrates; i++) {
++ if (!rt->info[i].valid)
++ continue;
++ rs->rs_rates[j++] = rt->info[i].dot11Rate;
++ }
++ rs->rs_nrates = j;
+ return 1;
+ }
+ #endif
+
+-/* Setup half/quarter rate table support */
+-static void
+-ath_setup_subrates(struct net_device *dev)
+-{
+- struct ath_softc *sc = dev->priv;
+- struct ath_hal *ah = sc->sc_ah;
+- struct ieee80211com *ic = &sc->sc_ic;
+- const HAL_RATE_TABLE *rt;
+- struct ieee80211_rateset *rs;
+- unsigned int i, maxrates;
+-
+- sc->sc_half_rates = ath_hal_getratetable(ah, HAL_MODE_11A_HALF_RATE);
+- rt = sc->sc_half_rates;
+- if (rt != NULL) {
+- if (rt->rateCount > IEEE80211_RATE_MAXSIZE) {
+- DPRINTF(sc, ATH_DEBUG_ANY,
+- "The rate table is too small (%u > %u)\n",
+- rt->rateCount, IEEE80211_RATE_MAXSIZE);
+- maxrates = IEEE80211_RATE_MAXSIZE;
+- } else
+- maxrates = rt->rateCount;
+- rs = &ic->ic_sup_half_rates;
+- for (i = 0; i < maxrates; i++)
+- rs->rs_rates[i] = rt->info[i].dot11Rate;
+- rs->rs_nrates = maxrates;
+- }
+-
+- sc->sc_quarter_rates = ath_hal_getratetable(ah, HAL_MODE_11A_QUARTER_RATE);
+- rt = sc->sc_quarter_rates;
+- if (rt != NULL) {
+- if (rt->rateCount > IEEE80211_RATE_MAXSIZE) {
+- DPRINTF(sc, ATH_DEBUG_ANY,
+- "The rate table is too small (%u > %u)\n",
+- rt->rateCount, IEEE80211_RATE_MAXSIZE);
+- maxrates = IEEE80211_RATE_MAXSIZE;
+- } else
+- maxrates = rt->rateCount;
+- rs = &ic->ic_sup_quarter_rates;
+- for (i = 0; i < maxrates; i++)
+- rs->rs_rates[i] = rt->info[i].dot11Rate;
+- rs->rs_nrates = maxrates;
+- }
+-}
+-
+ static int
+ ath_rate_setup(struct net_device *dev, u_int mode)
+ {
+@@ -10467,7 +10457,7 @@ ath_rate_setup(struct net_device *dev, u
+ struct ieee80211com *ic = &sc->sc_ic;
+ const HAL_RATE_TABLE *rt;
+ struct ieee80211_rateset *rs;
+- unsigned int i, maxrates;
++ unsigned int i, j, maxrates, f;
+
+ switch (mode) {
+ case IEEE80211_MODE_11A:
+@@ -10485,6 +10475,12 @@ ath_rate_setup(struct net_device *dev, u
+ case IEEE80211_MODE_TURBO_G:
+ sc->sc_rates[mode] = ath_hal_getratetable(ah, HAL_MODE_108G);
+ break;
++ case ATH_MODE_HALF:
++ sc->sc_rates[mode] = ath_hal_getratetable(ah, HAL_MODE_11A_HALF_RATE);
++ break;
++ case ATH_MODE_QUARTER:
++ sc->sc_rates[mode] = ath_hal_getratetable(ah, HAL_MODE_11A_QUARTER_RATE);
++ break;
+ default:
+ DPRINTF(sc, ATH_DEBUG_ANY, "Invalid mode %u\n", mode);
+ return 0;
+@@ -10499,10 +10495,16 @@ ath_rate_setup(struct net_device *dev, u
+ maxrates = IEEE80211_RATE_MAXSIZE;
+ } else
+ maxrates = rt->rateCount;
++
++ /* NB: quarter/half rate channels hijack the 11A rateset */
++ if (mode >= IEEE80211_MODE_MAX)
++ return 1;
++
+ rs = &ic->ic_sup_rates[mode];
+ for (i = 0; i < maxrates; i++)
+ rs->rs_rates[i] = rt->info[i].dot11Rate;
+ rs->rs_nrates = maxrates;
++
+ return 1;
+ }
+
+@@ -10531,13 +10533,18 @@ ath_setcurmode(struct ath_softc *sc, enu
+ { 0, 500, 130 },
+ };
+ const HAL_RATE_TABLE *rt;
+- unsigned int i, j;
++ unsigned int i, j, f;
+
++ /*
++ * NB: Fix up rixmap. HAL returns half or quarter dot11Rates,
++ * while the stack deals with full rates only
++ */
++ f = rate_factor(mode);
+ memset(sc->sc_rixmap, 0xff, sizeof(sc->sc_rixmap));
+ rt = sc->sc_rates[mode];
+ KASSERT(rt != NULL, ("no h/w rate set for phy mode %u", mode));
+ for (i = 0; i < rt->rateCount; i++)
+- sc->sc_rixmap[rt->info[i].dot11Rate & IEEE80211_RATE_VAL] = i;
++ sc->sc_rixmap[rate_hal2ieee(rt->info[i].dot11Rate, f) & IEEE80211_RATE_VAL] = i;
+ memset(sc->sc_hwmap, 0, sizeof(sc->sc_hwmap));
+ for (i = 0; i < 32; i++) {
+ u_int8_t ix = rt->rateCodeToIndex[i];
+@@ -10547,7 +10554,7 @@ ath_setcurmode(struct ath_softc *sc, enu
+ continue;
+ }
+ sc->sc_hwmap[i].ieeerate =
+- rt->info[ix].dot11Rate & IEEE80211_RATE_VAL;
++ rate_hal2ieee(rt->info[ix].dot11Rate, f) & IEEE80211_RATE_VAL;
+ if (rt->info[ix].shortPreamble ||
+ rt->info[ix].phy == IEEE80211_T_OFDM)
+ sc->sc_hwmap[i].flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
+@@ -10948,9 +10955,106 @@ enum {
+ ATH_MAXVAPS = 26,
+ ATH_INTMIT = 27,
+ ATH_NOISE_IMMUNITY = 28,
+- ATH_OFDM_WEAK_DET = 29
++ ATH_OFDM_WEAK_DET = 29,
++ ATH_CHANBW = 30,
++ ATH_OUTDOOR = 31,
+ };
+
++/*
++ * perform the channel related sysctl, reload the channel list
++ * and try to stay on the current frequency
++ */
++static int ath_sysctl_setchanparam(struct ath_softc *sc, unsigned long ctl, u_int val)
++{
++ struct ieee80211com *ic = &sc->sc_ic;
++ struct ath_hal *ah = sc->sc_ah;
++ struct ieee80211_channel *c = NULL;
++ struct ieee80211vap *vap;
++ u_int16_t freq = 0;
++ struct ifreq ifr;
++
++ if (ic->ic_curchan != IEEE80211_CHAN_ANYC)
++ freq = ic->ic_curchan->ic_freq;
++
++ switch(ctl) {
++ case ATH_COUNTRYCODE:
++ ic->ic_country_code = val;
++ break;
++ case ATH_OUTDOOR:
++ ic->ic_country_outdoor = val;
++ break;
++ case ATH_CHANBW:
++ switch(val) {
++ case 0:
++ case 5:
++ case 10:
++ case 20:
++ case 40:
++ if (ath_hal_setcapability(ah, HAL_CAP_CHANBW, 1, val, NULL) == AH_TRUE) {
++ sc->sc_chanbw = val;
++ break;
++ }
++ default:
++ return -EINVAL;
++ }
++ break;
++ }
++
++ if (ic->ic_curchan != IEEE80211_CHAN_ANYC)
++ freq = ic->ic_curchan->ic_freq;
++
++ /* clear out any old state */
++ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
++ vap->iv_des_mode = IEEE80211_MODE_AUTO;
++ vap->iv_des_chan = IEEE80211_CHAN_ANYC;
++ }
++ ieee80211_scan_flush(ic);
++
++ IEEE80211_LOCK_IRQ(ic);
++ ath_getchannels(sc->sc_dev);
++ ieee80211_update_channels(ic, 0);
++ if (freq)
++ c = ieee80211_find_channel(ic, freq, IEEE80211_MODE_AUTO);
++ if (!c)
++ c = &ic->ic_channels[0];
++ ic->ic_curchan = c;
++ ic->ic_bsschan = c;
++ ic->ic_curmode = IEEE80211_MODE_AUTO;
++ IEEE80211_UNLOCK_IRQ(ic);
++
++ if (!(sc->sc_dev->flags & IFF_RUNNING)) {
++ ic->ic_bsschan = IEEE80211_CHAN_ANYC;
++ return 0;
++ }
++
++#ifndef ifr_media
++#define ifr_media ifr_ifru.ifru_ivalue
++#endif
++ memset(&ifr, 0, sizeof(ifr));
++ ifr.ifr_media = ic->ic_media.ifm_cur->ifm_media & ~IFM_MMASK;
++ ifr.ifr_media |= IFM_MAKEMODE(IEEE80211_MODE_AUTO);
++ ifmedia_ioctl(ic->ic_dev, &ifr, &ic->ic_media, SIOCSIFMEDIA);
++
++ /* apply the channel to the hw */
++ ath_set_channel(ic);
++
++ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
++ struct net_device *dev = vap->iv_dev;
++
++ /* reactivate all active vaps */
++ vap->iv_state = IEEE80211_S_SCAN;
++ if ((vap->iv_opmode == IEEE80211_M_HOSTAP) ||
++ (vap->iv_opmode == IEEE80211_M_MONITOR) ||
++ (vap->iv_opmode == IEEE80211_M_WDS))
++ ieee80211_new_state(vap, IEEE80211_S_RUN, 0);
++ else
++ ieee80211_new_state(vap, IEEE80211_S_INIT, -1);
++ }
++
++ return 0;
++}
++
++
+ static int
+ ath_sysctl_set_intmit(struct ath_softc *sc, long ctl, u_int val)
+ {
+@@ -11029,6 +11133,7 @@ static int
+ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl, write, filp, buffer, lenp, ppos)
+ {
+ struct ath_softc *sc = ctl->extra1;
++ struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_hal *ah = sc->sc_ah;
+ u_int val;
+ u_int tab_3_val[3];
+@@ -11052,25 +11157,34 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+ lenp, ppos);
+ if (ret == 0) {
+ switch ((long)ctl->extra2) {
++ case ATH_REGDOMAIN:
++ ath_hal_setregdomain(ah, val);
++ break;
++ case ATH_OUTDOOR:
++ case ATH_COUNTRYCODE:
++ case ATH_CHANBW:
++ ret = ath_sysctl_setchanparam(sc, (long) ctl->extra2, val);
++ break;
+ case ATH_SLOTTIME:
+- if (val > 0) {
+- if (!ath_hal_setslottime(ah, val))
+- ret = -EINVAL;
+- else
+- sc->sc_slottimeconf = val;
+- } else {
+- /* disable manual override */
++ if (val > 0)
++ sc->sc_slottimeconf = val;
++ else
+ sc->sc_slottimeconf = 0;
+- ath_setslottime(sc);
+- }
++ ath_settiming(sc);
+ break;
+ case ATH_ACKTIMEOUT:
+- if (!ath_hal_setacktimeout(ah, val))
+- ret = -EINVAL;
++ if (val > 0)
++ sc->sc_acktimeconf = val;
++ else
++ sc->sc_acktimeconf = 0;
++ ath_settiming(sc);
+ break;
+ case ATH_CTSTIMEOUT:
+- if (!ath_hal_setctstimeout(ah, val))
+- ret = -EINVAL;
++ if (val > 0)
++ sc->sc_ctstimeconf = val;
++ else
++ sc->sc_ctstimeconf = 0;
++ ath_settiming(sc);
+ break;
+ case ATH_SOFTLED:
+ if (val != sc->sc_softled) {
+@@ -11223,6 +11337,9 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+ }
+ } else {
+ switch ((long)ctl->extra2) {
++ case ATH_CHANBW:
++ val = sc->sc_chanbw ?: 20;
++ break;
+ case ATH_SLOTTIME:
+ val = ath_hal_getslottime(ah);
+ break;
+@@ -11241,6 +11358,9 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+ case ATH_COUNTRYCODE:
+ ath_hal_getcountrycode(ah, &val);
+ break;
++ case ATH_OUTDOOR:
++ val = ic->ic_country_outdoor;
++ break;
+ case ATH_MAXVAPS:
+ val = ath_maxvaps;
+ break;
+@@ -11354,11 +11474,17 @@ static const ctl_table ath_sysctl_templa
+ },
+ { .ctl_name = CTL_AUTO,
+ .procname = "countrycode",
+- .mode = 0444,
++ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_COUNTRYCODE,
+ },
+ { .ctl_name = CTL_AUTO,
++ .procname = "outdoor",
++ .mode = 0644,
++ .proc_handler = ath_sysctl_halparam,
++ .extra2 = (void *)ATH_OUTDOOR,
++ },
++ { .ctl_name = CTL_AUTO,
+ .procname = "maxvaps",
+ .mode = 0444,
+ .proc_handler = ath_sysctl_halparam,
+@@ -11366,7 +11492,7 @@ static const ctl_table ath_sysctl_templa
+ },
+ { .ctl_name = CTL_AUTO,
+ .procname = "regdomain",
+- .mode = 0444,
++ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_REGDOMAIN,
+ },
+@@ -11429,6 +11555,12 @@ static const ctl_table ath_sysctl_templa
+ .extra2 = (void *)ATH_ACKRATE,
+ },
+ { .ctl_name = CTL_AUTO,
++ .procname = "channelbw",
++ .mode = 0644,
++ .proc_handler = ath_sysctl_halparam,
++ .extra2 = (void *)ATH_CHANBW,
++ },
++ { .ctl_name = CTL_AUTO,
+ .procname = "rp",
+ .mode = 0200,
+ .proc_handler = ath_sysctl_halparam,
+@@ -11669,13 +11801,6 @@ static ctl_table ath_static_sysctls[] =
+ },
+ #endif
+ { .ctl_name = CTL_AUTO,
+- .procname = "countrycode",
+- .mode = 0444,
+- .data = &ath_countrycode,
+- .maxlen = sizeof(ath_countrycode),
+- .proc_handler = proc_dointvec
+- },
+- { .ctl_name = CTL_AUTO,
+ .procname = "maxvaps",
+ .mode = 0444,
+ .data = &ath_maxvaps,
+@@ -11683,13 +11808,6 @@ static ctl_table ath_static_sysctls[] =
+ .proc_handler = proc_dointvec
+ },
+ { .ctl_name = CTL_AUTO,
+- .procname = "outdoor",
+- .mode = 0444,
+- .data = &ath_outdoor,
+- .maxlen = sizeof(ath_outdoor),
+- .proc_handler = proc_dointvec
+- },
+- { .ctl_name = CTL_AUTO,
+ .procname = "xchanmode",
+ .mode = 0444,
+ .data = &ath_xchanmode,
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -688,17 +688,18 @@ struct ath_softc {
+ int8_t sc_ofdm_weak_det; /* OFDM weak frames detection, -1 == auto */
+
+ /* rate tables */
+- const HAL_RATE_TABLE *sc_rates[IEEE80211_MODE_MAX];
++#define ATH_MODE_HALF (IEEE80211_MODE_MAX)
++#define ATH_MODE_QUARTER (IEEE80211_MODE_MAX + 1)
++ const HAL_RATE_TABLE *sc_rates[IEEE80211_MODE_MAX + 2];
+ const HAL_RATE_TABLE *sc_currates; /* current rate table */
+ const HAL_RATE_TABLE *sc_xr_rates; /* XR rate table */
+- const HAL_RATE_TABLE *sc_half_rates; /* half rate table */
+- const HAL_RATE_TABLE *sc_quarter_rates; /* quarter rate table */
+ HAL_OPMODE sc_opmode; /* current hal operating mode */
+ enum ieee80211_phymode sc_curmode; /* current phy mode */
+ u_int sc_poweroffset; /* hardware power offset */
+ u_int16_t sc_curtxpow; /* current tx power limit */
+ u_int16_t sc_curaid; /* current association id */
+ HAL_CHANNEL sc_curchan; /* current h/w channel */
++ u_int8_t sc_chanbw; /* channel bandwidth */
+ u_int8_t sc_curbssid[IEEE80211_ADDR_LEN];
+ u_int8_t sc_rixmap[256]; /* IEEE to h/w rate table ix */
+ struct {
+@@ -809,6 +810,8 @@ struct ath_softc {
+ u_int32_t sc_dturbo_bw_turbo; /* bandwidth threshold */
+ #endif
+ u_int sc_slottimeconf; /* manual override for slottime */
++ u_int sc_acktimeconf; /* manual override for acktime */
++ u_int sc_ctstimeconf; /* manual override for ctstime */
+
+ struct timer_list sc_dfs_excl_timer; /* mark expiration timer task */
+ struct timer_list sc_dfs_cac_timer; /* dfs wait timer */
+@@ -827,6 +830,7 @@ struct ath_softc {
+ int sc_rp_num;
+ int sc_rp_min;
+ HAL_BOOL (*sc_rp_analyse)(struct ath_softc *sc);
++ struct ATH_TQ_STRUCT sc_refresh_tq;
+ struct ATH_TQ_STRUCT sc_rp_tq;
+
+ int sc_rp_ignored; /* if set, we ignored all
+@@ -942,6 +946,48 @@ int ar_device(int devid);
+ DEV_NAME(_v->iv_ic->ic_dev))
+
+ void ath_radar_detected(struct ath_softc *sc, const char* message);
++static inline u_int getTimingOffset(struct ath_softc *sc)
++{
++ struct ieee80211com *ic = &sc->sc_ic;
++ u_int usec = 9;
++ if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) {
++ usec = 20;
++ if (ic->ic_flags & IEEE80211_F_SHSLOT)
++ usec = 9;
++ } else if (IEEE80211_IS_CHAN_A(ic->ic_curchan))
++ usec = 9;
++
++ if (IEEE80211_IS_CHAN_TURBO(ic->ic_curchan))
++ usec = 6;
++
++ if (IEEE80211_IS_CHAN_HALF(ic->ic_curchan))
++ usec = 13;
++ else if (IEEE80211_IS_CHAN_QUARTER(ic->ic_curchan))
++ usec = 21;
++ return usec;
++}
++
++static inline void ath_get_timings(struct ath_softc *sc, u_int *t_slot, u_int *t_sifs, u_int *t_difs)
++{
++ struct ieee80211_channel *c = sc->sc_ic.ic_curchan;
++
++ *t_slot = getTimingOffset(sc) + sc->sc_slottimeconf;
++
++ if (IEEE80211_IS_CHAN_HALF(c)) {
++ *t_sifs = 32;
++ *t_difs = 56;
++ } else if (IEEE80211_IS_CHAN_QUARTER(c)) {
++ *t_sifs = 64;
++ *t_difs = 112;
++ } else if (IEEE80211_IS_CHAN_TURBO(c)) {
++ *t_sifs = 8;
++ *t_difs = 28;
++ } else {
++ *t_sifs = 16;
++ *t_difs = 28;
++ }
++}
++
+
+ struct ath_hw_detect {
+ const char *vendor_name;
+--- a/tools/athctrl.c
++++ b/tools/athctrl.c
+@@ -118,7 +118,7 @@ CMD(athctrl)(int argc, char *argv[])
+ }
+
+ if (distance >= 0) {
+- int slottime = 9 + (distance / 300) + ((distance % 300) ? 1 : 0);
++ int slottime = (distance / 300) + ((distance % 300) ? 1 : 0);
+ int acktimeout = slottime * 2 + 3;
+ int ctstimeout = slottime * 2 + 3;
+
+--- a/net80211/ieee80211.c
++++ b/net80211/ieee80211.c
+@@ -243,34 +243,17 @@ static const struct country_code_to_str
+ {CTRY_ZIMBABWE, "ZW"}
+ };
+
+-int
+-ieee80211_ifattach(struct ieee80211com *ic)
++void ieee80211_update_channels(struct ieee80211com *ic, int init)
+ {
+- struct net_device *dev = ic->ic_dev;
+ struct ieee80211_channel *c;
++ struct ieee80211vap *vap;
+ struct ifmediareq imr;
++ int ext = 0;
+ int i;
+
+- _MOD_INC_USE(THIS_MODULE, return -ENODEV);
+-
+- /*
+- * Pick an initial operating mode until we have a vap
+- * created to lock it down correctly. This is only
+- * drivers have something defined for configuring the
+- * hardware at startup.
+- */
+- ic->ic_opmode = IEEE80211_M_STA; /* everyone supports this */
+-
+- /*
+- * Fill in 802.11 available channel set, mark
+- * all available channels as active, and pick
+- * a default channel if not already specified.
+- */
+- KASSERT(0 < ic->ic_nchans && ic->ic_nchans < IEEE80211_CHAN_MAX,
+- ("invalid number of channels specified: %u", ic->ic_nchans));
+ memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail));
+- ic->ic_modecaps |= 1 << IEEE80211_MODE_AUTO;
+ ic->ic_max_txpower = IEEE80211_TXPOWER_MIN;
++ ic->ic_modecaps = 1 << IEEE80211_MODE_AUTO;
+
+ for (i = 0; i < ic->ic_nchans; i++) {
+ c = &ic->ic_channels[i];
+@@ -298,6 +281,8 @@ ieee80211_ifattach(struct ieee80211com *
+ ic->ic_modecaps |= 1 << IEEE80211_MODE_TURBO_A;
+ if (IEEE80211_IS_CHAN_108G(c))
+ ic->ic_modecaps |= 1 << IEEE80211_MODE_TURBO_G;
++ if (IEEE80211_IS_CHAN_HALF(c) || IEEE80211_IS_CHAN_QUARTER(c))
++ ext = 1;
+ }
+ /* Initialize candidate channels to all available */
+ memcpy(ic->ic_chan_active, ic->ic_chan_avail,
+@@ -311,11 +296,59 @@ ieee80211_ifattach(struct ieee80211com *
+ * When 11g is supported, force the rate set to
+ * include basic rates suitable for a mixed b/g bss.
+ */
+- if (ic->ic_modecaps & (1 << IEEE80211_MODE_11G))
++ if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11G)) && !ext)
+ ieee80211_set11gbasicrates(
+ &ic->ic_sup_rates[IEEE80211_MODE_11G],
+ IEEE80211_MODE_11G);
+
++ if (init)
++ return;
++
++ ifmedia_removeall(&ic->ic_media);
++ ieee80211_media_setup(ic, &ic->ic_media, ic->ic_caps, NULL, NULL);
++ ieee80211com_media_status(ic->ic_dev, &imr);
++ ifmedia_set(&ic->ic_media, imr.ifm_active);
++
++ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
++ struct ieee80211vap *avp;
++ TAILQ_FOREACH(avp, &vap->iv_wdslinks, iv_wdsnext) {
++ (void) ieee80211_media_setup(ic, &vap->iv_media, vap->iv_caps, NULL, NULL);
++ ieee80211_media_status(vap->iv_dev, &imr);
++ ifmedia_set(&vap->iv_media, imr.ifm_active);
++ }
++ (void) ieee80211_media_setup(ic, &vap->iv_media, vap->iv_caps, NULL, NULL);
++ ieee80211_media_status(vap->iv_dev, &imr);
++ ifmedia_set(&vap->iv_media, imr.ifm_active);
++ }
++}
++EXPORT_SYMBOL(ieee80211_update_channels);
++
++int
++ieee80211_ifattach(struct ieee80211com *ic)
++{
++ struct net_device *dev = ic->ic_dev;
++ struct ieee80211_channel *c;
++ struct ifmediareq imr;
++
++ _MOD_INC_USE(THIS_MODULE, return -ENODEV);
++
++ /*
++ * Pick an initial operating mode until we have a vap
++ * created to lock it down correctly. This is only
++ * drivers have something defined for configuring the
++ * hardware at startup.
++ */
++ ic->ic_opmode = IEEE80211_M_STA; /* everyone supports this */
++
++ /*
++ * Fill in 802.11 available channel set, mark
++ * all available channels as active, and pick
++ * a default channel if not already specified.
++ */
++ KASSERT(0 < ic->ic_nchans && ic->ic_nchans < IEEE80211_CHAN_MAX,
++ ("invalid number of channels specified: %u", ic->ic_nchans));
++ ieee80211_update_channels(ic, 1);
++
+ /* Setup initial channel settings */
+ ic->ic_bsschan = IEEE80211_CHAN_ANYC;
+ /* Arbitrarily pick the first channel */
+@@ -327,6 +360,7 @@ ieee80211_ifattach(struct ieee80211com *
+ /* Enable WME by default, if we're capable. */
+ if (ic->ic_caps & IEEE80211_C_WME)
+ ic->ic_flags |= IEEE80211_F_WME;
++
+ (void) ieee80211_setmode(ic, ic->ic_curmode);
+
+ /* Store default beacon interval, as nec. */
+@@ -763,7 +797,8 @@ ieee80211_media_setup(struct ieee80211co
+ struct ieee80211_rateset allrates;
+
+ /* Fill in media characteristics. */
+- ifmedia_init(media, 0, media_change, media_stat);
++ if (media_change || media_stat)
++ ifmedia_init(media, 0, media_change, media_stat);
+ maxrate = 0;
+ memset(&allrates, 0, sizeof(allrates));
+
+@@ -793,7 +828,7 @@ ieee80211_media_setup(struct ieee80211co
+ ADD(media, IFM_AUTO, mopt | IFM_IEEE80211_WDS);
+ if (mode == IEEE80211_MODE_AUTO)
+ continue;
+- rs = &ic->ic_sup_rates[mode];
++ rs = &ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, mode)];
+
+ for (i = 0; i < rs->rs_nrates; i++) {
+ rate = rs->rs_rates[i];
+@@ -1207,7 +1242,7 @@ ieee80211_announce(struct ieee80211com *
+ if ((ic->ic_modecaps & (1 << mode)) == 0)
+ continue;
+ if_printf(dev, "%s rates: ", ieee80211_phymode_name[mode]);
+- rs = &ic->ic_sup_rates[mode];
++ rs = &ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, mode)];
+ for (i = 0; i < rs->rs_nrates; i++) {
+ rate = rs->rs_rates[i];
+ mword = ieee80211_rate2media(ic, rate, mode);
+@@ -1417,7 +1452,7 @@ ieee80211com_media_change(struct net_dev
+ * now so drivers have a consistent state.
+ */
+ KASSERT(vap->iv_bss != NULL, ("no bss node"));
+- vap->iv_bss->ni_rates = ic->ic_sup_rates[newphymode];
++ vap->iv_bss->ni_rates = ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, newphymode)];
+ }
+ error = -ENETRESET;
+ }
+@@ -1435,7 +1470,7 @@ findrate(struct ieee80211com *ic, enum i
+ {
+ #define IEEERATE(_ic,_m,_i) \
+ ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL)
+- int i, nrates = ic->ic_sup_rates[mode].rs_nrates;
++ int i, nrates = ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, mode)].rs_nrates;
+ for (i = 0; i < nrates; i++)
+ if (IEEERATE(ic, mode, i) == rate)
+ return i;
+@@ -1877,11 +1912,6 @@ ieee80211_build_countryie(struct ieee802
+ if (ieee80211_chan2mode(c) != curmode_noturbo)
+ continue;
+
+- /* Skip half/quarter rate channels */
+- if (IEEE80211_IS_CHAN_HALF(c) ||
+- IEEE80211_IS_CHAN_QUARTER(c))
+- continue;
+-
+ if (*cur_runlen == 0) {
+ (*cur_runlen)++;
+ *cur_pow = c->ic_maxregpower;
+@@ -1915,7 +1945,7 @@ void
+ ieee80211_build_sc_ie(struct ieee80211com *ic)
+ {
+ struct ieee80211_ie_sc *ie = &ic->ic_sc_ie;
+- int i, j;
++ int i, j, k;
+ struct ieee80211_channel *c;
+ u_int8_t prevchan;
+
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -336,8 +336,6 @@ struct ieee80211com {
+ 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 */
+@@ -714,6 +712,7 @@ MALLOC_DECLARE(M_80211_VAP);
+
+ int ieee80211_ifattach(struct ieee80211com *);
+ void ieee80211_ifdetach(struct ieee80211com *);
++void ieee80211_update_channels(struct ieee80211com *ic, int);
+ int ieee80211_vap_setup(struct ieee80211com *, struct net_device *,
+ const char *, int, int, struct ieee80211vap *);
+ int ieee80211_vap_attach(struct ieee80211vap *, ifm_change_cb_t, ifm_stat_cb_t);
+@@ -793,6 +792,23 @@ ieee80211_anyhdrspace(struct ieee80211co
+ return size;
+ }
+
++static __inline int
++ieee80211_chan2ratemode(struct ieee80211_channel *c, int mode)
++{
++ if (mode == -1)
++ mode = ieee80211_chan2mode(c);
++
++ /*
++ * Use 11a rateset for half/quarter to restrict things
++ * to pure OFDM
++ */
++ if (IEEE80211_IS_CHAN_HALF(c) ||
++ IEEE80211_IS_CHAN_QUARTER(c))
++ return IEEE80211_MODE_11A;
++
++ return mode;
++}
++
+ /* Macros to print MAC address used in 802.11 headers */
+
+ #define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -287,7 +287,7 @@ ieee80211_node_set_chan(struct ieee80211
+ ni->ni_rates = ic->ic_sup_xr_rates;
+ else
+ #endif
+- ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2mode(chan)];
++ ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2ratemode(chan, -1)];
+ }
+
+ static __inline void
+@@ -387,6 +387,8 @@ ieee80211_create_ibss(struct ieee80211va
+ ic->ic_bsschan = chan;
+ ieee80211_node_set_chan(ic, ni);
+ ic->ic_curmode = ieee80211_chan2mode(chan);
++ ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2ratemode(chan, -1)];
++
+ spin_lock_irqsave(&channel_lock, flags);
+ ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan);
+ spin_unlock_irqrestore(&channel_lock, flags);
+@@ -394,14 +396,8 @@ ieee80211_create_ibss(struct ieee80211va
+ /* Update country ie information */
+ ieee80211_build_countryie(ic);
+
+- if (IEEE80211_IS_CHAN_HALF(chan)) {
+- ni->ni_rates = ic->ic_sup_half_rates;
+- } else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
+- ni->ni_rates = ic->ic_sup_quarter_rates;
+- }
+-
+- if ((vap->iv_flags & IEEE80211_F_PUREG) &&
+- IEEE80211_IS_CHAN_ANYG(chan)) {
++ if ((ieee80211_chan2ratemode(chan, -1) != IEEE80211_MODE_11A) &&
++ IEEE80211_IS_CHAN_ANYG(chan) && (vap->iv_flags & IEEE80211_F_PUREG)) {
+ ieee80211_setpuregbasicrates(&ni->ni_rates);
+ }
+
+--- a/net80211/ieee80211_scan_sta.c
++++ b/net80211/ieee80211_scan_sta.c
+@@ -490,12 +490,7 @@ check_rate(struct ieee80211vap *vap, con
+
+ okrate = badrate = fixedrate = 0;
+
+- if (IEEE80211_IS_CHAN_HALF(se->se_chan))
+- srs = &ic->ic_sup_half_rates;
+- else if (IEEE80211_IS_CHAN_QUARTER(se->se_chan))
+- srs = &ic->ic_sup_quarter_rates;
+- else
+- srs = &ic->ic_sup_rates[ieee80211_chan2mode(se->se_chan)];
++ srs = &ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, -1)];
+ nrs = se->se_rates[1];
+ rs = se->se_rates + 2;
+ fixedrate = IEEE80211_FIXED_RATE_NONE;
+--- a/net80211/ieee80211_output.c
++++ b/net80211/ieee80211_output.c
+@@ -1676,8 +1676,8 @@ ieee80211_send_probereq(struct ieee80211
+
+ frm = ieee80211_add_ssid(frm, ssid, ssidlen);
+ mode = ieee80211_chan2mode(ic->ic_curchan);
+- frm = ieee80211_add_rates(frm, &ic->ic_sup_rates[mode]);
+- frm = ieee80211_add_xrates(frm, &ic->ic_sup_rates[mode]);
++ frm = ieee80211_add_rates(frm, &ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, mode)]);
++ frm = ieee80211_add_xrates(frm, &ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, mode)]);
+
+ if (optie != NULL) {
+ memcpy(frm, optie, optielen);
+--- a/net80211/ieee80211_proto.c
++++ b/net80211/ieee80211_proto.c
+@@ -404,7 +404,7 @@ ieee80211_fix_rate(struct ieee80211_node
+
+ error = 0;
+ okrate = badrate = fixedrate = 0;
+- srs = &ic->ic_sup_rates[ieee80211_chan2mode(ni->ni_chan)];
++ srs = &ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, -1)];
+ nrs = &ni->ni_rates;
+ fixedrate = IEEE80211_FIXED_RATE_NONE;
+ for (i = 0; i < nrs->rs_nrates;) {
+@@ -1407,6 +1407,7 @@ ieee80211_new_state(struct ieee80211vap
+ IEEE80211_VAPS_UNLOCK_IRQ(ic);
+ return rc;
+ }
++EXPORT_SYMBOL(ieee80211_new_state);
+
+ static int
+ __ieee80211_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -195,31 +195,7 @@ calc_usecs_unicast_packet(struct ath_sof
+ return 0;
+ }
+
+- /* XXX: Getting MAC/PHY level timings should be fixed for turbo
+- * rates, and there is probably a way to get this from the
+- * HAL... */
+- switch (rt->info[rix].phy) {
+- case IEEE80211_T_OFDM:
+-#if 0
+- t_slot = 9;
+- t_sifs = 16;
+- t_difs = 28;
+- /* fall through */
+-#endif
+- case IEEE80211_T_TURBO:
+- t_slot = 9;
+- t_sifs = 8;
+- t_difs = 28;
+- break;
+- case IEEE80211_T_DS:
+- /* Fall through to default */
+- default:
+- /* pg. 205 ieee.802.11.pdf */
+- t_slot = 20;
+- t_difs = 50;
+- t_sifs = 10;
+- }
+-
++ ath_get_timings(sc, &t_slot, &t_sifs, &t_difs);
+ if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
+ (rt->info[rix].phy == IEEE80211_T_OFDM)) {
+ if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
+--- a/ath_rate/sample/sample.c
++++ b/ath_rate/sample/sample.c
+@@ -172,26 +172,7 @@ calc_usecs_unicast_packet(struct ath_sof
+ * rates, and there is probably a way to get this from the
+ * hal...
+ */
+- switch (rt->info[rix].phy) {
+- case IEEE80211_T_OFDM:
+- t_slot = 9;
+- t_sifs = 16;
+- t_difs = 28;
+- /* fall through */
+- case IEEE80211_T_TURBO:
+- t_slot = 9;
+- t_sifs = 8;
+- t_difs = 28;
+- break;
+- case IEEE80211_T_DS:
+- /* fall through to default */
+- default:
+- /* pg 205 ieee.802.11.pdf */
+- t_slot = 20;
+- t_difs = 50;
+- t_sifs = 10;
+- }
+-
++ ath_get_timings(sc, &t_slot, &t_sifs, &t_difs);
+ rts = cts = 0;
+
+ if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -2142,7 +2142,7 @@ ieee80211_ioctl_setmode(struct net_devic
+
+ vap->iv_des_mode = mode;
+ if (IS_UP_AUTO(vap))
+- ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
++ ieee80211_init(vap->iv_dev, 0);
+
+ retv = 0;
+ }
+@@ -4090,46 +4090,60 @@ ieee80211_ioctl_getchanlist(struct net_d
+ return 0;
+ }
+
++static int alreadyListed(struct ieee80211req_chaninfo *chans, u_int16_t mhz)
++{
++ int i;
++ for (i = 0; i < chans->ic_nchans; i++) {
++ if (chans->ic_chans[i].ic_freq == mhz)
++ return 1;
++ }
++ return 0;
++}
++
+ static int
+ ieee80211_ioctl_getchaninfo(struct net_device *dev,
+- struct iw_request_info *info, void *w, char *extra)
++ struct iw_request_info *info, void *w, char *extra)
+ {
+ struct ieee80211vap *vap = dev->priv;
+ struct ieee80211com *ic = vap->iv_ic;
+- struct ieee80211req_chaninfo chans;
++ struct ieee80211req_chaninfo *chans =
++ (struct ieee80211req_chaninfo *)extra;
++
+ u_int8_t reported[IEEE80211_CHAN_BYTES]; /* XXX stack usage? */
+ int i;
+
+- memset(&chans, 0, sizeof(chans));
+- memset(&reported, 0, sizeof(reported));
++ memset(chans, 0, sizeof(*chans));
++ memset(reported, 0, sizeof(reported));
+ for (i = 0; i < ic->ic_nchans; i++) {
+ const struct ieee80211_channel *c = &ic->ic_channels[i];
+ const struct ieee80211_channel *c1 = c;
+
+- if (isclr(reported, c->ic_ieee)) {
++ if (!alreadyListed(chans, c->ic_freq)) {
+ setbit(reported, c->ic_ieee);
+
+- /* pick turbo channel over non-turbo channel, and
+- * 11g channel over 11b channel */
+ if (IEEE80211_IS_CHAN_A(c))
+- c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_TURBO_A);
++ c1 = findchannel(ic, c->ic_freq,
++ IEEE80211_MODE_TURBO_A);
+ if (IEEE80211_IS_CHAN_ANYG(c))
+- c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_TURBO_G);
++ c1 = findchannel(ic, c->ic_freq,
++ IEEE80211_MODE_TURBO_G);
+ else if (IEEE80211_IS_CHAN_B(c)) {
+- c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_TURBO_G);
++ c1 = findchannel(ic, c->ic_freq,
++ IEEE80211_MODE_TURBO_G);
+ if (!c1)
+- c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_11G);
++ c1 = findchannel(ic, c->ic_freq,
++ IEEE80211_MODE_11G);
+ }
+
+ if (c1)
+ c = c1;
+- /* Copy the entire structure, whereas it used to just copy a few fields */
+- memcpy(&chans.ic_chans[chans.ic_nchans], c, sizeof(struct ieee80211_channel));
+- if (++chans.ic_nchans >= IEEE80211_CHAN_MAX)
++ chans->ic_chans[chans->ic_nchans].ic_ieee = c->ic_ieee;
++ chans->ic_chans[chans->ic_nchans].ic_freq = c->ic_freq;
++ chans->ic_chans[chans->ic_nchans].ic_flags = c->ic_flags;
++ if (++chans->ic_nchans >= IEEE80211_CHAN_MAX)
+ break;
+ }
+ }
+- memcpy(extra, &chans, sizeof(struct ieee80211req_chaninfo));
+ return 0;
+ }
+
+--- a/net80211/ieee80211_scan_ap.c
++++ b/net80211/ieee80211_scan_ap.c
+@@ -512,12 +512,13 @@ pick_channel(struct ieee80211_scan_state
+ int ss_last = ss->ss_last;
+ struct ieee80211_channel *best;
+ struct ap_state *as = ss->ss_priv;
+- struct channel chans[ss_last]; /* actually ss_last-1 is required */
++ struct channel *chans; /* actually ss_last-1 is required */
+ struct channel *c = NULL;
+ struct pc_params params = { vap, ss, flags };
+ int benefit = 0;
+ int sta_assoc = 0;
+
++ chans = (struct channel *)kmalloc(ss_last*sizeof(struct channel),GFP_ATOMIC);
+ for (i = 0; i < ss_last; i++) {
+ chans[i].chan = ss->ss_chans[i];
+ chans[i].orig = i;
+@@ -571,6 +572,7 @@ pick_channel(struct ieee80211_scan_state
+ "%s: best: channel %u rssi %d\n",
+ __func__, i, as->as_maxrssi[i]);
+ }
++ kfree(chans);
+ return best;
+ }
+
+@@ -609,6 +611,7 @@ ap_end(struct ieee80211_scan_state *ss,
+ res = 1; /* Do NOT restart scan */
+ } else {
+ struct ieee80211_scan_entry se;
++ int i;
+ /* XXX: notify all VAPs? */
+ /* if this is a dynamic turbo frequency , start with normal
+ * mode first */
+@@ -623,6 +626,11 @@ ap_end(struct ieee80211_scan_state *ss,
+ return 0;
+ }
+ }
++ for (i = (bestchan - &ic->ic_channels[0])/sizeof(*bestchan) + 1; i < ic->ic_nchans; i++) {
++ if ((ic->ic_channels[i].ic_freq == bestchan->ic_freq) &&
++ IEEE80211_IS_CHAN_ANYG(&ic->ic_channels[i]))
++ bestchan = &ic->ic_channels[i];
++ }
+ memset(&se, 0, sizeof(se));
+ se.se_chan = bestchan;
+
+--- a/tools/wlanconfig.c
++++ b/tools/wlanconfig.c
+@@ -737,7 +737,7 @@ list_channels(const char *ifname, int al
+ if (get80211priv(ifname, IEEE80211_IOCTL_GETCHANINFO, &chans, sizeof(chans)) < 0)
+ errx(1, "unable to get channel information");
+ if (!allchans) {
+- uint8_t active[32];
++ uint8_t active[IEEE80211_CHAN_BYTES];
+
+ if (get80211priv(ifname, IEEE80211_IOCTL_GETCHANLIST, &active, sizeof(active)) < 0)
+ errx(1, "unable to get active channel list");
+--- a/net80211/ieee80211_scan.c
++++ b/net80211/ieee80211_scan.c
+@@ -1044,6 +1044,7 @@ ieee80211_scan_assoc_fail(struct ieee802
+ ss->ss_ops->scan_assoc_fail(ss, mac, reason);
+ }
+ }
++EXPORT_SYMBOL(ieee80211_scan_flush);
+
+ /*
+ * Iterate over the contents of the scan cache.
+--- a/ath/if_ath_hal_wrappers.h
++++ b/ath/if_ath_hal_wrappers.h
+@@ -111,6 +111,11 @@ static inline HAL_BOOL ath_hal_getregdom
+ return (ath_hal_getcapability(ah, HAL_CAP_REG_DMN, 0, destination) == HAL_OK);
+ }
+
++static inline HAL_BOOL ath_hal_setregdomain(struct ath_hal *ah, u_int32_t v)
++{
++ return (ath_hal_setcapability(ah, HAL_CAP_REG_DMN, 0, v, NULL));
++}
++
+ static inline HAL_BOOL ath_hal_gettkipmic(struct ath_hal *ah)
+ {
+ return (ath_hal_getcapability(ah, HAL_CAP_TKIP_MIC, 1, NULL) == HAL_OK);
diff --git a/package/madwifi/patches/422-confchange_reset.patch b/package/madwifi/patches/422-confchange_reset.patch
new file mode 100644
index 000000000..33040ae0d
--- /dev/null
+++ b/package/madwifi/patches/422-confchange_reset.patch
@@ -0,0 +1,31 @@
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -70,7 +70,8 @@
+ (((_dev)->flags & (IFF_RUNNING|IFF_UP)) == (IFF_RUNNING|IFF_UP))
+ #define IS_UP_AUTO(_vap) \
+ (IS_UP((_vap)->iv_dev) && \
+- (_vap)->iv_ic->ic_roaming == IEEE80211_ROAMING_AUTO)
++ (((_vap)->iv_opmode == IEEE80211_M_HOSTAP) || \
++ (_vap)->iv_ic->ic_roaming == IEEE80211_ROAMING_AUTO))
+ #define RESCAN 1
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+@@ -283,7 +284,7 @@ ieee80211_ioctl_siwencode(struct net_dev
+ vap->iv_flags &= ~IEEE80211_F_DROPUNENC;
+ }
+ }
+- if ((error == 0) && IS_UP(vap->iv_dev)) {
++ if ((error == 0) && IS_UP_AUTO(vap) && wepchange) {
+ /*
+ * Device is up and running; we must kick it to
+ * effect the change. If we're enabling/disabling
+@@ -291,8 +292,7 @@ ieee80211_ioctl_siwencode(struct net_dev
+ * so the 802.11 state machine is reset. Otherwise
+ * the key state should have been updated above.
+ */
+- if (wepchange && IS_UP_AUTO(vap))
+- ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
++ ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
+ }
+ #ifdef ATH_SUPERG_XR
+ /* set the same params on the xr vap device if exists */
diff --git a/package/madwifi/patches/423-phyerr_handling.patch b/package/madwifi/patches/423-phyerr_handling.patch
new file mode 100644
index 000000000..7f3cbafe2
--- /dev/null
+++ b/package/madwifi/patches/423-phyerr_handling.patch
@@ -0,0 +1,28 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -4391,13 +4391,12 @@ ath_key_update_end(struct ieee80211vap *
+ static u_int32_t
+ ath_calcrxfilter(struct ath_softc *sc)
+ {
+-#define RX_FILTER_PRESERVE (HAL_RX_FILTER_PHYERR | HAL_RX_FILTER_PHYRADAR)
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct net_device *dev = ic->ic_dev;
+ struct ath_hal *ah = sc->sc_ah;
+ u_int32_t rfilt;
+
+- rfilt = (ath_hal_getrxfilter(ah) & RX_FILTER_PRESERVE) |
++ rfilt = ath_hal_getrxfilter(ah) |
+ HAL_RX_FILTER_UCAST | HAL_RX_FILTER_BCAST |
+ HAL_RX_FILTER_MCAST;
+ if (ic->ic_opmode != IEEE80211_M_STA)
+@@ -4416,9 +4415,8 @@ ath_calcrxfilter(struct ath_softc *sc)
+ 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);
++ rfilt |= HAL_RX_FILTER_PHYRADAR;
+ return rfilt;
+-#undef RX_FILTER_PRESERVE
+ }
+
+ /*
diff --git a/package/madwifi/patches/424-timing.patch b/package/madwifi/patches/424-timing.patch
new file mode 100644
index 000000000..8369db618
--- /dev/null
+++ b/package/madwifi/patches/424-timing.patch
@@ -0,0 +1,764 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -382,6 +382,7 @@ static u_int32_t ath_set_clamped_maxtxpo
+ static void ath_poll_disable(struct net_device *dev);
+ static void ath_poll_enable(struct net_device *dev);
+ static void ath_fetch_idle_time(struct ath_softc *sc);
++static void ath_set_timing(struct ath_softc *sc);
+
+ /* calibrate every 30 secs in steady state but check every second at first. */
+ static int ath_calinterval = ATH_SHORT_CALINTERVAL;
+@@ -1185,6 +1186,7 @@ ath_attach(u_int16_t devid, struct net_d
+ sc->sc_intmit = -1;
+ sc->sc_noise_immunity = -1;
+ sc->sc_ofdm_weak_det = -1;
++ sc->sc_coverage = 7; /* 2100 meters */
+
+ return 0;
+ bad3:
+@@ -2673,6 +2675,7 @@ ath_init(struct net_device *dev)
+ */
+ ath_chan_change(sc, ic->ic_curchan);
+ ath_set_ack_bitrate(sc, sc->sc_ackrate);
++ ath_set_timing(sc);
+ dev->flags |= IFF_RUNNING; /* we are ready to go */
+ ieee80211_start_running(ic); /* start all VAPs */
+ #ifdef ATH_TX99_DIAG
+@@ -4484,17 +4487,52 @@ ath_mode_init(struct net_device *dev)
+ * Set the slot time based on the current setting.
+ */
+ static void
+-ath_settiming(struct ath_softc *sc)
++ath_set_timing(struct ath_softc *sc)
+ {
++ struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_hal *ah = sc->sc_ah;
+- u_int offset = getTimingOffset(sc);
++ struct ath_timings *t = &sc->sc_timings;
++ u_int offset = 9;
++
++ t->sifs = 16;
++ if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) {
++ offset = 20;
++ if (ic->ic_flags & IEEE80211_F_SHSLOT)
++ offset = 9;
++ } else if (IEEE80211_IS_CHAN_A(ic->ic_curchan)) {
++ offset = 9;
++ }
++
++ if (IEEE80211_IS_CHAN_TURBO(ic->ic_curchan)) {
++ offset = 6;
++ t->sifs = 8;
++ } else if (IEEE80211_IS_CHAN_HALF(ic->ic_curchan)) {
++ offset = 13;
++ t->sifs = 32;
++ } else if (IEEE80211_IS_CHAN_QUARTER(ic->ic_curchan)) {
++ offset = 21;
++ t->sifs = 64;
++ }
++
++ t->slot = offset + sc->sc_coverage;
++ t->ack = t->slot * 2 + 3;
++ t->cts = t->slot * 2 + 3;
+
+ if (sc->sc_slottimeconf > 0)
+- ath_hal_setslottime(ah, offset + sc->sc_slottimeconf);
++ t->slot = sc->sc_slottimeconf;
+ if (sc->sc_acktimeconf > 0)
+- ath_hal_setacktimeout(ah, 2 * offset + sc->sc_acktimeconf);
++ t->ack = sc->sc_acktimeconf;
+ if (sc->sc_ctstimeconf > 0)
+- ath_hal_setctstimeout(ah, 2 * offset + sc->sc_ctstimeconf);
++ t->cts = sc->sc_ctstimeconf;
++
++ t->difs = 2 * t->sifs + t->slot;
++ t->eifs = t->sifs + t->difs + 3;
++
++ ath_hal_setslottime(ah, t->slot);
++ ath_hal_setacktimeout(ah, t->ack);
++ ath_hal_setctstimeout(ah, t->cts);
++ ath_hal_seteifstime(ah, t->eifs);
++
+ sc->sc_updateslot = OK;
+ }
+
+@@ -4516,7 +4554,7 @@ ath_updateslot(struct net_device *dev)
+ if (ic->ic_opmode == IEEE80211_M_HOSTAP)
+ sc->sc_updateslot = UPDATE;
+ else if (dev->flags & IFF_RUNNING)
+- ath_settiming(sc);
++ ath_set_timing(sc);
+ }
+
+ #ifdef ATH_SUPERG_DYNTURBO
+@@ -5360,7 +5398,7 @@ ath_beacon_send(struct ath_softc *sc, in
+ sc->sc_updateslot = COMMIT; /* commit next beacon */
+ sc->sc_slotupdate = slot;
+ } else if ((sc->sc_updateslot == COMMIT) && (sc->sc_slotupdate == slot))
+- ath_settiming(sc); /* commit change to hardware */
++ ath_set_timing(sc); /* commit change to hardware */
+
+ if (bfaddr != 0) {
+ /*
+@@ -9433,7 +9471,8 @@ ath_set_coverageclass(struct ieee80211co
+ {
+ struct ath_softc *sc = ic->ic_dev->priv;
+
+- ath_hal_setcoverageclass(sc->sc_ah, ic->ic_coverageclass, 0);
++ sc->sc_coverage = ic->ic_coverageclass * 3;
++ ath_set_timing(sc);
+
+ return;
+ }
+@@ -10956,6 +10995,7 @@ enum {
+ ATH_OFDM_WEAK_DET = 29,
+ ATH_CHANBW = 30,
+ ATH_OUTDOOR = 31,
++ ATH_DISTANCE = 32,
+ };
+
+ /*
+@@ -11168,21 +11208,31 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+ sc->sc_slottimeconf = val;
+ else
+ sc->sc_slottimeconf = 0;
+- ath_settiming(sc);
++ ath_set_timing(sc);
+ break;
+ case ATH_ACKTIMEOUT:
+ if (val > 0)
+ sc->sc_acktimeconf = val;
+ else
+ sc->sc_acktimeconf = 0;
+- ath_settiming(sc);
++ ath_set_timing(sc);
+ break;
+ case ATH_CTSTIMEOUT:
+ if (val > 0)
+ sc->sc_ctstimeconf = val;
+ else
+ sc->sc_ctstimeconf = 0;
+- ath_settiming(sc);
++ ath_set_timing(sc);
++ break;
++ case ATH_DISTANCE:
++ if (val > 0) {
++ sc->sc_coverage = ((val - 1) / 300) + 1;
++ ic->ic_coverageclass = ((sc->sc_coverage - 1) / 3) + 1;
++ } else {
++ sc->sc_coverage = 0;
++ ic->ic_coverageclass = 0;
++ }
++ ath_set_timing(sc);
+ break;
+ case ATH_SOFTLED:
+ if (val != sc->sc_softled) {
+@@ -11338,6 +11388,9 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+ case ATH_CHANBW:
+ val = sc->sc_chanbw ?: 20;
+ break;
++ case ATH_DISTANCE:
++ val = sc->sc_coverage * 300;
++ break;
+ case ATH_SLOTTIME:
+ val = ath_hal_getslottime(ah);
+ break;
+@@ -11459,6 +11512,12 @@ static const ctl_table ath_sysctl_templa
+ .extra2 = (void *)ATH_CTSTIMEOUT,
+ },
+ { .ctl_name = CTL_AUTO,
++ .procname = "distance",
++ .mode = 0644,
++ .proc_handler = ath_sysctl_halparam,
++ .extra2 = (void *)ATH_DISTANCE,
++ },
++ { .ctl_name = CTL_AUTO,
+ .procname = "softled",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+--- a/ath/if_ath_hal.h
++++ b/ath/if_ath_hal.h
+@@ -284,6 +284,17 @@ static inline u_int ath_hal_getslottime(
+ return ret;
+ }
+
++static inline u_int ath_hal_geteifstime(struct ath_hal *ah)
++{
++ u_int ret;
++ ATH_HAL_LOCK_IRQ(ah->ah_sc);
++ ath_hal_set_function(__func__);
++ ret = ah->ah_getEifsTime(ah);
++ ath_hal_set_function(NULL);
++ ATH_HAL_UNLOCK_IRQ(ah->ah_sc);
++ return ret;
++}
++
+ static inline void ath_hal_beaconinit(struct ath_hal *ah, u_int32_t nexttbtt,
+ u_int32_t intval)
+ {
+@@ -839,6 +850,17 @@ static inline HAL_BOOL ath_hal_setslotti
+ ath_hal_set_function(NULL);
+ ATH_HAL_UNLOCK_IRQ(ah->ah_sc);
+ return ret;
++}
++
++static inline HAL_BOOL ath_hal_seteifstime(struct ath_hal *ah, u_int a1)
++{
++ HAL_BOOL ret;
++ ATH_HAL_LOCK_IRQ(ah->ah_sc);
++ ath_hal_set_function(__func__);
++ ret = ah->ah_setEifsTime(ah, a1);
++ ath_hal_set_function(NULL);
++ ATH_HAL_UNLOCK_IRQ(ah->ah_sc);
++ return ret;
+ }
+
+ static inline void ath_hal_setledstate(struct ath_hal *ah, HAL_LED_STATE a1)
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -613,6 +613,15 @@ struct ath_rp {
+ int rp_analyzed;
+ };
+
++struct ath_timings {
++ u_int slot;
++ u_int ack;
++ u_int cts;
++ u_int sifs;
++ u_int difs;
++ u_int eifs;
++};
++
+ struct ath_softc {
+ struct ieee80211com sc_ic; /* NB: must be first */
+ struct net_device *sc_dev;
+@@ -839,6 +848,8 @@ struct ath_softc {
+ * detected radars */
+ u_int32_t sc_nexttbtt;
+ u_int64_t sc_last_tsf;
++ u_int sc_coverage;
++ struct ath_timings sc_timings;
+ };
+
+ typedef void (*ath_callback) (struct ath_softc *);
+@@ -946,49 +957,76 @@ int ar_device(int devid);
+ DEV_NAME(_v->iv_ic->ic_dev))
+
+ void ath_radar_detected(struct ath_softc *sc, const char* message);
+-static inline u_int getTimingOffset(struct ath_softc *sc)
+-{
+- struct ieee80211com *ic = &sc->sc_ic;
+- u_int usec = 9;
+- if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) {
+- usec = 20;
+- if (ic->ic_flags & IEEE80211_F_SHSLOT)
+- usec = 9;
+- } else if (IEEE80211_IS_CHAN_A(ic->ic_curchan))
+- usec = 9;
+-
+- if (IEEE80211_IS_CHAN_TURBO(ic->ic_curchan))
+- usec = 6;
+-
+- if (IEEE80211_IS_CHAN_HALF(ic->ic_curchan))
+- usec = 13;
+- else if (IEEE80211_IS_CHAN_QUARTER(ic->ic_curchan))
+- usec = 21;
+- return usec;
+-}
+
+-static inline void ath_get_timings(struct ath_softc *sc, u_int *t_slot, u_int *t_sifs, u_int *t_difs)
+-{
+- struct ieee80211_channel *c = sc->sc_ic.ic_curchan;
++#ifndef MIN
++#define MIN(a,b) ((a) < (b) ? (a) : (b))
++#endif
++#ifndef MAX
++#define MAX(a,b) ((a) > (b) ? (a) : (b))
++#endif
+
+- *t_slot = getTimingOffset(sc) + sc->sc_slottimeconf;
+
+- if (IEEE80211_IS_CHAN_HALF(c)) {
+- *t_sifs = 32;
+- *t_difs = 56;
+- } else if (IEEE80211_IS_CHAN_QUARTER(c)) {
+- *t_sifs = 64;
+- *t_difs = 112;
+- } else if (IEEE80211_IS_CHAN_TURBO(c)) {
+- *t_sifs = 8;
+- *t_difs = 28;
+- } else {
+- *t_sifs = 16;
+- *t_difs = 28;
+- }
++/* Calculate the transmit duration of a frame. */
++static inline unsigned
++calc_usecs_unicast_packet(struct ath_softc *sc, int length,
++ int rix, int short_retries, int long_retries)
++{
++ const HAL_RATE_TABLE *rt = sc->sc_currates;
++ struct ieee80211com *ic = &sc->sc_ic;
++ struct ath_timings *t = &sc->sc_timings;
++ unsigned int x = 0, tt = 0;
++ unsigned int cix = rt->info[rix].controlRate;
++ int rts = 0, cts = 0;
++ int cw = ATH_DEFAULT_CWMIN;
++
++ KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
++
++ if (!rt->info[rix].rateKbps) {
++ printk(KERN_WARNING "rix %d (%d) bad ratekbps %d mode %u\n",
++ rix, rt->info[rix].dot11Rate,
++ rt->info[rix].rateKbps,
++ sc->sc_curmode);
++ return 0;
++ }
++
++ if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
++ (rt->info[rix].phy == IEEE80211_T_OFDM)) {
++
++ if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
++ rts = 1;
++ else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
++ cts = 1;
++
++ cix = rt->info[sc->sc_protrix].controlRate;
++ }
++
++ if ((rts || cts) && rt->info[cix].rateKbps) {
++ int ctsrate = rt->info[cix].rateCode;
++ int ctsduration = 0;
++
++ ctsrate |= rt->info[cix].shortPreamble;
++ if (rts) /* SIFS + CTS */
++ ctsduration += rt->info[cix].spAckDuration;
++
++ ctsduration += ath_hal_computetxtime(sc->sc_ah,
++ rt, length, rix, AH_TRUE);
++
++ if (cts) /* SIFS + ACK */
++ ctsduration += rt->info[cix].spAckDuration;
++
++ tt += (short_retries + 1) * ctsduration;
++ }
++ tt += t->difs;
++ tt += (long_retries + 1) * (t->sifs + rt->info[rix].spAckDuration);
++ 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(ATH_DEFAULT_CWMAX, (cw + 1) * 2);
++ tt += (t->slot * cw / 2);
++ }
++ return tt;
+ }
+
+-
+ struct ath_hw_detect {
+ const char *vendor_name;
+ const char *card_name;
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -170,85 +170,6 @@ rate_to_ndx(struct minstrel_node *sn, in
+ return -1;
+ }
+
+-/* Calculate the transmit duration of a frame. */
+-static unsigned
+-calc_usecs_unicast_packet(struct ath_softc *sc, int length,
+- int rix, int short_retries, int long_retries)
+-{
+- const HAL_RATE_TABLE *rt = sc->sc_currates;
+- struct ieee80211com *ic = &sc->sc_ic;
+- unsigned t_slot = 20;
+- unsigned t_difs = 50;
+- unsigned t_sifs = 10;
+- unsigned int x = 0, tt = 0;
+- unsigned int cix = rt->info[rix].controlRate;
+- int rts = 0, cts = 0;
+- int cw = ATH_DEFAULT_CWMIN;
+-
+- KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
+-
+- if (!rt->info[rix].rateKbps) {
+- printk(KERN_WARNING "rix %d (%d) bad ratekbps %d mode %u\n",
+- rix, rt->info[rix].dot11Rate,
+- rt->info[rix].rateKbps,
+- sc->sc_curmode);
+- return 0;
+- }
+-
+- ath_get_timings(sc, &t_slot, &t_sifs, &t_difs);
+- if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
+- (rt->info[rix].phy == IEEE80211_T_OFDM)) {
+- if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
+- rts = 1;
+- else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
+- cts = 1;
+-
+- cix = rt->info[sc->sc_protrix].controlRate;
+- }
+-
+-#if 0
+- if (length > ic->ic_rtsthreshold)
+- rts = 1;
+-#endif
+-
+- if (rts || cts) {
+- int ctsrate = rt->info[cix].rateCode;
+- int ctsduration = 0;
+-
+- if (!rt->info[cix].rateKbps) {
+-#if 0
+- printk(KERN_WARNING "cix %d (%d) bad ratekbps %d mode %u\n",
+- cix, rt->info[cix].dot11Rate,
+- rt->info[cix].rateKbps,
+- sc->sc_curmode);
+-#endif
+- return 0;
+- }
+-
+-
+- ctsrate |= rt->info[cix].shortPreamble;
+- if (rts) /* SIFS + CTS */
+- ctsduration += rt->info[cix].spAckDuration;
+-
+- ctsduration += ath_hal_computetxtime(sc->sc_ah,
+- rt, length, rix, AH_TRUE);
+-
+- if (cts) /* SIFS + ACK */
+- ctsduration += rt->info[cix].spAckDuration;
+-
+- tt += (short_retries + 1) * ctsduration;
+- }
+- tt += t_difs;
+- tt += (long_retries + 1) * (t_sifs + rt->info[rix].spAckDuration);
+- 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(ATH_DEFAULT_CWMAX, (cw + 1) * 2);
+- tt += (t_slot * cw / 2);
+- }
+- return tt;
+-}
+-
+ static void
+ ath_rate_node_init(struct ath_softc *sc, struct ath_node *an)
+ {
+--- a/ath_rate/sample/sample.c
++++ b/ath_rate/sample/sample.c
+@@ -137,92 +137,6 @@ rate_to_ndx(struct sample_node *sn, int
+ return -1;
+ }
+
+-/*
+- * Calculate the transmit duration of a frame.
+- */
+-static unsigned
+-calc_usecs_unicast_packet(struct ath_softc *sc, int length,
+- int rix, int short_retries, int long_retries)
+-{
+- const HAL_RATE_TABLE *rt = sc->sc_currates;
+- int rts, cts;
+-
+- unsigned t_slot;
+- unsigned t_difs;
+- unsigned t_sifs;
+- struct ieee80211com *ic = &sc->sc_ic;
+- unsigned int tt = 0;
+- unsigned int x;
+- unsigned int cw = ATH_DEFAULT_CWMIN;
+- unsigned int cix = rt->info[rix].controlRate;
+- KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
+-
+- if (!rt->info[rix].rateKbps) {
+- printk(KERN_WARNING "rix %u (%u) bad ratekbps %u mode %u\n",
+- rix, rt->info[rix].dot11Rate,
+- rt->info[rix].rateKbps,
+- sc->sc_curmode);
+-
+- return 0;
+- }
+-
+- cix = rt->info[rix].controlRate;
+- /*
+- * XXX getting mac/phy level timings should be fixed for turbo
+- * rates, and there is probably a way to get this from the
+- * hal...
+- */
+- ath_get_timings(sc, &t_slot, &t_sifs, &t_difs);
+- rts = cts = 0;
+-
+- if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
+- rt->info[rix].phy == IEEE80211_T_OFDM) {
+- if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
+- rts = 1;
+- else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
+- cts = 1;
+-
+- cix = rt->info[sc->sc_protrix].controlRate;
+- }
+-
+- if (0 /*length > ic->ic_rtsthreshold */)
+- rts = 1;
+-
+- if (rts || cts) {
+- int ctsrate;
+- int ctsduration = 0;
+-
+- if (!rt->info[cix].rateKbps) {
+- printk(KERN_WARNING "cix %u (%u) bad ratekbps %u mode %u\n",
+- cix, rt->info[cix].dot11Rate,
+- rt->info[cix].rateKbps,
+- sc->sc_curmode);
+- return 0;
+- }
+-
+-
+- ctsrate = rt->info[cix].rateCode | rt->info[cix].shortPreamble;
+- if (rts) /* SIFS + CTS */
+- ctsduration += rt->info[cix].spAckDuration;
+-
+- ctsduration += ath_hal_computetxtime(sc->sc_ah,
+- rt, length, rix, AH_TRUE);
+-
+- if (cts) /* SIFS + ACK */
+- ctsduration += rt->info[cix].spAckDuration;
+-
+- tt += (short_retries + 1) * ctsduration;
+- }
+- tt += t_difs;
+- tt += (long_retries+1)*(t_sifs + rt->info[rix].spAckDuration);
+- 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(ATH_DEFAULT_CWMAX, (cw + 1) * 2);
+- tt += (t_slot * cw / 2);
+- }
+- return tt;
+-}
+
+ static void
+ ath_rate_node_init(struct ath_softc *sc, struct ath_node *an)
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -2745,6 +2745,7 @@ ieee80211_ioctl_setparam(struct net_devi
+ case IEEE80211_PARAM_COVERAGE_CLASS:
+ if (value <= IEEE80211_COVERAGE_CLASS_MAX) {
+ ic->ic_coverageclass = value;
++ ic->ic_set_coverageclass(ic);
+ if (IS_UP_AUTO(vap))
+ ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
+ retv = 0;
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -94,7 +94,7 @@
+
+ #define IEEE80211_BGSCAN_TRIGGER_INTVL 20 /* min trigger interval for thresh based bgscan (secs) */
+
+-#define IEEE80211_COVERAGE_CLASS_MAX 31 /* max coverage class */
++#define IEEE80211_COVERAGE_CLASS_MAX 255 /* max coverage class */
+ #define IEEE80211_REGCLASSIDS_MAX 10 /* max regclass id list */
+
+ #define IEEE80211_PS_SLEEP 0x1 /* STA is in power saving mode */
+--- a/tools/Makefile
++++ b/tools/Makefile
+@@ -50,7 +50,7 @@ all: compile
+
+ DEBUG = -DAR_DEBUG
+
+-ALLPROGS= athstats 80211stats athkey athchans athctrl \
++ALLPROGS= athstats 80211stats athkey athchans \
+ $(if $(DEBUG),athdebug 80211debug) wlanconfig ath_info
+
+ OBJS= $(patsubst %,%.o,$(ALLPROGS))
+--- a/tools/athctrl.c
++++ /dev/null
+@@ -1,133 +0,0 @@
+-/*-
+- * Copyright (c) 2002-2004 Gunter Burchardt, Local-Web AG
+- * 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: athctrl.c 2394 2007-05-30 01:41:18Z mtaylor $
+- */
+-
+-/*
+- * Simple Atheros-specific tool to inspect and set atheros specific values
+- * athctrl [-i interface] [-d distance]
+- * (default interface is wifi0).
+- */
+-#include <sys/types.h>
+-#include <sys/file.h>
+-
+-#include <getopt.h>
+-
+-#include <stdio.h>
+-#include <string.h>
+-#include <stdlib.h>
+-#include <err.h>
+-
+-#include <net/if.h>
+-#include "do_multi.h"
+-
+-static int
+-setsysctrl(const char *dev, const char *control , u_long value)
+-{
+- char buffer[256];
+- FILE * fd;
+-
+- snprintf(buffer, sizeof(buffer), "/proc/sys/dev/%s/%s", dev, control);
+- fd = fopen(buffer, "w");
+- if (fd != NULL) {
+- fprintf(fd, "%li", value);
+- fclose(fd);
+- } else
+- fprintf(stderr, "Could not open %s for writing!\n", buffer);
+-
+- return 0;
+-}
+-
+-static void usage(void)
+-{
+- fprintf(stderr,
+- "Atheros driver control\n"
+- "Copyright (c) 2002-2004 Gunter Burchardt, Local-Web AG\n"
+- "\n"
+- "usage: athctrl [-i interface] [-d distance]\n"
+- "\n"
+- "options:\n"
+- " -h show this usage\n"
+- " -i interface (default interface is wifi0)\n"
+- " -d specify the maximum distance of a sta or the distance\n"
+- " of the master\n");
+-
+- exit(1);
+-}
+-
+-int
+-CMD(athctrl)(int argc, char *argv[])
+-{
+- char device[IFNAMSIZ + 1];
+- int distance = -1;
+- int c;
+-
+- strncpy(device, "wifi0", sizeof (device));
+-
+- for (;;) {
+- c = getopt(argc, argv, "d:i:h");
+- if (c < 0)
+- break;
+- switch (c) {
+- case 'h':
+- usage();
+- break;
+- case 'd':
+- distance = atoi(optarg);
+- break;
+- case 'i':
+- strncpy(device, optarg, sizeof (device));
+- break;
+- default:
+- usage();
+- break;
+- }
+- }
+-
+- if (distance >= 0) {
+- int slottime = (distance / 300) + ((distance % 300) ? 1 : 0);
+- int acktimeout = slottime * 2 + 3;
+- int ctstimeout = slottime * 2 + 3;
+-
+- printf("Setting distance on interface %s to %i meters\n",
+- device, distance);
+- setsysctrl(device, "slottime", slottime);
+- setsysctrl(device, "acktimeout", acktimeout);
+- setsysctrl(device, "ctstimeout", ctstimeout);
+- } else
+- usage();
+- return 0;
+-}
+--- a/tools/do_multi.c
++++ b/tools/do_multi.c
+@@ -18,8 +18,6 @@ main(int argc, char *argv[])
+ ret = a80211stats_init(argc, argv);
+ if(strcmp(progname, "athchans") == 0)
+ ret = athchans_init(argc, argv);
+- if(strcmp(progname, "athctrl") == 0)
+- ret = athctrl_init(argc, argv);
+ #ifdef AR_DEBUG
+ if(strcmp(progname, "athdebug") == 0)
+ ret = athdebug_init(argc, argv);
+--- a/tools/do_multi.h
++++ b/tools/do_multi.h
+@@ -2,7 +2,6 @@
+ int a80211debug_init(int argc, char *argv[]);
+ int a80211stats_init(int argc, char *argv[]);
+ int athchans_init(int argc, char *argv[]);
+-int athctrl_init(int argc, char *argv[]);
+ int athdebug_init(int argc, char *argv[]);
+ int athkey_init(int argc, char *argv[]);
+ int athstats_init(int argc, char *argv[]);
+--- a/ath_rate/minstrel/minstrel.h
++++ b/ath_rate/minstrel/minstrel.h
+@@ -172,14 +172,6 @@ struct minstrel_node {
+
+ #define ATH_NODE_MINSTREL(an) ((struct minstrel_node *)&an[1])
+
+-
+-#ifndef MIN
+-#define MIN(a,b) ((a) < (b) ? (a) : (b))
+-#endif
+-#ifndef MAX
+-#define MAX(a,b) ((a) > (b) ? (a) : (b))
+-#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.h
++++ b/ath_rate/sample/sample.h
+@@ -98,14 +98,6 @@ struct sample_node {
+ };
+ #define ATH_NODE_SAMPLE(an) ((struct sample_node *)&an[1])
+
+-
+-#ifndef MIN
+-#define MIN(a,b) ((a) < (b) ? (a) : (b))
+-#endif
+-#ifndef MAX
+-#define MAX(a,b) ((a) > (b) ? (a) : (b))
+-#endif
+-
+ /*
+ * Definitions for pulling the rate and trie counts from
+ * a 5212 h/w descriptor. These Don't belong here; the
diff --git a/package/madwifi/patches/425-rc_rexmit.patch b/package/madwifi/patches/425-rc_rexmit.patch
new file mode 100644
index 000000000..252767a8c
--- /dev/null
+++ b/package/madwifi/patches/425-rc_rexmit.patch
@@ -0,0 +1,506 @@
+--- a/net80211/ieee80211_rate.h
++++ b/net80211/ieee80211_rate.h
+@@ -81,6 +81,8 @@ struct ieee80211vap;
+
+ /* Multi-rare retry: 3 additional rate/retry pairs */
+ struct ieee80211_mrr {
++ int rate0;
++ int retries0;
+ int rate1;
+ int retries1;
+ int rate2;
+@@ -142,7 +144,7 @@ struct ieee80211_rate_ops {
+ * 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);
++ const struct ath_buf *bf, const struct ieee80211_mrr *mrr);
+ };
+
+ struct ath_ratectrl {
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -8638,6 +8638,8 @@ ath_tx_processq(struct ath_softc *sc, st
+
+ ni = bf->bf_node;
+ if (ni != NULL) {
++ struct ieee80211_mrr mrr;
++
+ an = ATH_NODE(ni);
+ if (ts->ts_status == 0) {
+ u_int8_t txant = ts->ts_antenna;
+@@ -8690,15 +8692,43 @@ ath_tx_processq(struct ath_softc *sc, st
+ lr = ts->ts_longretry;
+ sc->sc_stats.ast_tx_shortretry += sr;
+ sc->sc_stats.ast_tx_longretry += lr;
++ memset(&mrr, 0, sizeof(mrr));
++
++ switch(ah->ah_macType) {
++ case 5210:
++ case 5211:
++ goto skip_mrr;
++
++ case 5212:
++ mrr.rate0 = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate0)].ieeerate;
++ mrr.rate1 = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate1)].ieeerate;
++ mrr.rate2 = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate2)].ieeerate;
++ mrr.rate3 = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate3)].ieeerate;
++ break;
++
++ case 5416:
++ mrr.rate0 = sc->sc_hwmap[MS(ds->ds_ctl3, AR5416_XmitRate0)].ieeerate;
++ mrr.rate1 = sc->sc_hwmap[MS(ds->ds_ctl3, AR5416_XmitRate1)].ieeerate;
++ mrr.rate2 = sc->sc_hwmap[MS(ds->ds_ctl3, AR5416_XmitRate2)].ieeerate;
++ mrr.rate3 = sc->sc_hwmap[MS(ds->ds_ctl3, AR5416_XmitRate3)].ieeerate;
++ break;
++ }
++
++ mrr.retries0 = MS(ds->ds_ctl2, AR_XmitDataTries0);
++ mrr.retries1 = MS(ds->ds_ctl2, AR_XmitDataTries1);
++ mrr.retries2 = MS(ds->ds_ctl2, AR_XmitDataTries2);
++ mrr.retries3 = MS(ds->ds_ctl2, AR_XmitDataTries3);
++
+ /*
+ * Hand the descriptor to the rate control algorithm
+ * if the frame wasn't dropped for filtering or sent
+ * w/o waiting for an ack. In those cases the rssi
+ * and retry counts will be meaningless.
+ */
++skip_mrr:
+ if ((ts->ts_status & HAL_TXERR_FILT) == 0 &&
+ (bf->bf_flags & HAL_TXDESC_NOACK) == 0)
+- sc->sc_rc->ops->tx_complete(sc, an, bf);
++ sc->sc_rc->ops->tx_complete(sc, an, bf, &mrr);
+ }
+
+ bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr,
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -595,6 +595,46 @@ struct ath_vap {
+ (_tqs)->axq_link = NULL; \
+ } while (0)
+
++/*
++ * Definitions for pulling the rate and trie counts from
++ * a 5212 h/w descriptor. These Don't belong here; the
++ * driver should record this information so the rate control
++ * code doesn't go groveling around in the descriptor bits.
++ */
++#define ds_ctl2 ds_hw[0]
++#define ds_ctl3 ds_hw[1]
++
++/* TX ds_ctl3 */
++#define AR_XmitDataTries0 0x000f0000 /* series 0 max attempts */
++#define AR_XmitDataTries0_S 16
++#define AR_XmitDataTries1 0x00f00000 /* series 1 max attempts */
++#define AR_XmitDataTries1_S 20
++#define AR_XmitDataTries2 0x0f000000 /* series 2 max attempts */
++#define AR_XmitDataTries2_S 24
++#define AR_XmitDataTries3 0xf0000000 /* series 3 max attempts */
++#define AR_XmitDataTries3_S 28
++
++/* TX ds_ctl3 */
++#define AR_XmitRate0 0x0000001f /* series 0 tx rate */
++#define AR_XmitRate0_S 0
++#define AR_XmitRate1 0x000003e0 /* series 1 tx rate */
++#define AR_XmitRate1_S 5
++#define AR_XmitRate2 0x00007c00 /* series 2 tx rate */
++#define AR_XmitRate2_S 10
++#define AR_XmitRate3 0x000f8000 /* series 3 tx rate */
++#define AR_XmitRate3_S 15
++
++#define AR5416_XmitRate0 0x000000ff
++#define AR5416_XmitRate0_S 0
++#define AR5416_XmitRate1 0x0000ff00
++#define AR5416_XmitRate1_S 8
++#define AR5416_XmitRate2 0x00ff0000
++#define AR5416_XmitRate2_S 16
++#define AR5416_XmitRate3 0xff000000
++#define AR5416_XmitRate3_S 24
++
++#define MS(_v, _f) (((_v) & (_f)) >> _f##_S)
++
+ /*
+ * concat buffers from one queue to other
+ */
+--- a/ath_rate/amrr/amrr.c
++++ b/ath_rate/amrr/amrr.c
+@@ -123,7 +123,8 @@ ath_rate_get_mrr(struct ath_softc *sc, s
+
+ static void
+ ath_rate_tx_complete(struct ath_softc *sc,
+- struct ath_node *an, const struct ath_buf *bf)
++ struct ath_node *an, const struct ath_buf *bf,
++ const struct ieee80211_mrr *mrr)
+ {
+ struct amrr_node *amn = ATH_NODE_AMRR(an);
+ const struct ath_tx_status *ts = &bf->bf_dsstatus.ds_txstat;
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -333,7 +333,8 @@ ath_rate_get_mrr(struct ath_softc *sc, s
+
+ static void
+ ath_rate_tx_complete(struct ath_softc *sc,
+- struct ath_node *an, const struct ath_buf *bf)
++ struct ath_node *an, const struct ath_buf *bf,
++ const struct ieee80211_mrr *mrr)
+ {
+ struct minstrel_node *sn = ATH_NODE_MINSTREL(an);
+ struct ieee80211com *ic = &sc->sc_ic;
+@@ -341,12 +342,9 @@ ath_rate_tx_complete(struct ath_softc *s
+ const struct ath_desc *ds = &bf->bf_desc[0];
+ int final_rate = 0;
+ int tries = 0;
+- int mrr;
++ int use_mrr;
+ int final_ndx;
+- int rate0, tries0, ndx0;
+- int rate1, tries1, ndx1;
+- int rate2, tries2, ndx2;
+- int rate3, tries3, ndx3;
++ int ndx0, ndx1, ndx2, ndx3;
+
+ /* This is the index in the retry chain we finish at.
+ * With no retransmits, it is always 0.
+@@ -376,9 +374,9 @@ ath_rate_tx_complete(struct ath_softc *s
+ if (!ts->ts_status) /* Success when sending a packet*/
+ sn->rs_ratesuccess[final_ndx]++;
+
+- mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT) && ENABLE_MRR;
++ use_mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT) && ENABLE_MRR;
+
+- if (!mrr) {
++ if (!use_mrr) {
+ if ((0 <= final_ndx) && (final_ndx < sn->num_rates)) {
+ sn->rs_rateattempts[final_ndx] += tries; /* only one rate was used */
+ }
+@@ -388,47 +386,36 @@ ath_rate_tx_complete(struct ath_softc *s
+ /* Now, query the hal/hardware to find out the contents of the multirate retry chain.
+ * If we have it set to 6,3,2,2, this call will always return 6,3,2,2. For some packets, we can
+ * get a mrr of 0, -1, -1, -1, which indicates there is no chain installed for that packet */
+- rate0 = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate0)].ieeerate;
+- tries0 = MS(ds->ds_ctl2, AR_XmitDataTries0);
+- ndx0 = rate_to_ndx(sn, rate0);
++ ndx0 = rate_to_ndx(sn, mrr->rate0);
++ ndx1 = rate_to_ndx(sn, mrr->rate1);
++ ndx2 = rate_to_ndx(sn, mrr->rate2);
++ ndx3 = rate_to_ndx(sn, mrr->rate3);
+
+- rate1 = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate1)].ieeerate;
+- tries1 = MS(ds->ds_ctl2, AR_XmitDataTries1);
+- ndx1 = rate_to_ndx(sn, rate1);
+-
+- rate2 = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate2)].ieeerate;
+- tries2 = MS(ds->ds_ctl2, AR_XmitDataTries2);
+- ndx2 = rate_to_ndx(sn, rate2);
+-
+- rate3 = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate3)].ieeerate;
+- tries3 = MS(ds->ds_ctl2, AR_XmitDataTries3);
+- ndx3 = rate_to_ndx(sn, rate3);
+-
+- sn->rs_rateattempts[ndx0] += MIN(tries, tries0);
+- if (tries <= tries0)
++ sn->rs_rateattempts[ndx0] += MIN(tries, mrr->retries0);
++ if (tries <= mrr->retries0)
+ return;
+
+- if (tries1 < 0)
++ if (mrr->retries1 < 0)
+ return;
+- tries = tries - tries0;
+- sn->rs_rateattempts[ndx1] += MIN(tries, tries1);
+- if (tries <= tries1)
++ tries = tries - mrr->retries0;
++ sn->rs_rateattempts[ndx1] += MIN(tries, mrr->retries1);
++ if (tries <= mrr->retries1)
+ return;
+
+ if (bf->rcflags)
+ sn->sample_count++;
+
+- if (tries2 < 0)
++ if (mrr->retries2 < 0)
+ return;
+- tries = tries - tries1;
+- sn->rs_rateattempts[ndx2] += MIN(tries, tries2);
+- if (tries <= tries2)
++ tries = tries - mrr->retries1;
++ sn->rs_rateattempts[ndx2] += MIN(tries, mrr->retries2);
++ if (tries <= mrr->retries2)
+ return;
+
+- if (tries3 < 0)
++ if (mrr->retries3 < 0)
+ return;
+- tries = tries - tries2;
+- sn->rs_rateattempts[ndx3] += MIN(tries, tries3);
++ tries = tries - mrr->retries2;
++ sn->rs_rateattempts[ndx3] += MIN(tries, mrr->retries3);
+ }
+
+ static void
+--- a/ath_rate/minstrel/minstrel.h
++++ b/ath_rate/minstrel/minstrel.h
+@@ -172,36 +172,6 @@ struct minstrel_node {
+
+ #define ATH_NODE_MINSTREL(an) ((struct minstrel_node *)&an[1])
+
+-/*
+- * Definitions for pulling the rate and trie counts from
+- * a 5212 h/w descriptor. These Don't belong here; the
+- * driver should record this information so the rate control
+- * code doesn't go groveling around in the descriptor bits.
+- */
+-#define ds_ctl2 ds_hw[0]
+-#define ds_ctl3 ds_hw[1]
+-
+-/* TX ds_ctl3 */
+-#define AR_XmitDataTries0 0x000f0000 /* series 0 max attempts */
+-#define AR_XmitDataTries0_S 16
+-#define AR_XmitDataTries1 0x00f00000 /* series 1 max attempts */
+-#define AR_XmitDataTries1_S 20
+-#define AR_XmitDataTries2 0x0f000000 /* series 2 max attempts */
+-#define AR_XmitDataTries2_S 24
+-#define AR_XmitDataTries3 0xf0000000 /* series 3 max attempts */
+-#define AR_XmitDataTries3_S 28
+-
+-/* TX ds_ctl3 */
+-#define AR_XmitRate0 0x0000001f /* series 0 tx rate */
+-#define AR_XmitRate0_S 0
+-#define AR_XmitRate1 0x000003e0 /* series 1 tx rate */
+-#define AR_XmitRate1_S 5
+-#define AR_XmitRate2 0x00007c00 /* series 2 tx rate */
+-#define AR_XmitRate2_S 10
+-#define AR_XmitRate3 0x000f8000 /* series 3 tx rate */
+-#define AR_XmitRate3_S 15
+-
+-#define MS(_v, _f) (((_v) & (_f)) >> _f##_S)
+ #endif /* _DEV_ATH_RATE_MINSTEL_H */
+
+ /* The comment below is magic for those who use emacs to edit this file. */
+--- a/ath_rate/onoe/onoe.c
++++ b/ath_rate/onoe/onoe.c
+@@ -137,7 +137,8 @@ ath_rate_get_mrr(struct ath_softc *sc, s
+
+ static void
+ ath_rate_tx_complete(struct ath_softc *sc,
+- struct ath_node *an, const struct ath_buf *bf)
++ struct ath_node *an, const struct ath_buf *bf,
++ const struct ieee80211_mrr *mrr)
+ {
+ struct onoe_node *on = ATH_NODE_ONOE(an);
+ const struct ath_tx_status *ts = &bf->bf_dsstatus.ds_txstat;
+--- a/ath_rate/sample/sample.c
++++ b/ath_rate/sample/sample.c
+@@ -178,10 +178,6 @@ static __inline int best_rate_ndx(struct
+ !sn->stats[size_bin][x].packets_acked))
+ continue;
+
+- /* 9 megabits never works better than 12 */
+- if (sn->rates[x].rate == 18)
+- continue;
+-
+ /* don't use a bit-rate that has been failing */
+ if (sn->stats[size_bin][x].successive_failures > 3)
+ continue;
+@@ -234,10 +230,6 @@ pick_sample_ndx(struct sample_node *sn,
+ if (sn->rates[ndx].rate > 22 && ndx > current_ndx + 2)
+ continue;
+
+- /* 9 megabits never works better than 12 */
+- if (sn->rates[ndx].rate == 18)
+- continue;
+-
+ /* if we're using 11 megabits, only sample up to 12 megabits
+ */
+ if (sn->rates[current_ndx].rate == 22 && ndx > current_ndx + 1)
+@@ -531,7 +523,8 @@ update_stats(struct ath_softc *sc, struc
+
+ static void
+ ath_rate_tx_complete(struct ath_softc *sc,
+- struct ath_node *an, const struct ath_buf *bf)
++ struct ath_node *an, const struct ath_buf *bf,
++ const struct ieee80211_mrr *mrr)
+ {
+ struct sample_node *sn = ATH_NODE_SAMPLE(an);
+ struct ieee80211com *ic = &sc->sc_ic;
+@@ -541,7 +534,7 @@ ath_rate_tx_complete(struct ath_softc *s
+ unsigned int short_tries;
+ unsigned int long_tries;
+ unsigned int frame_size;
+- unsigned int mrr;
++ unsigned int use_mrr;
+
+ final_rate = sc->sc_hwmap[ts->ts_rate &~ HAL_TXSTAT_ALTRATE].ieeerate;
+ short_tries = ts->ts_shortretry + 1;
+@@ -557,7 +550,7 @@ ath_rate_tx_complete(struct ath_softc *s
+ return;
+ }
+
+- mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT) && ENABLE_MRR;
++ use_mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT) && ENABLE_MRR;
+
+
+ if (sc->sc_mrretry && ts->ts_status) {
+@@ -566,22 +559,15 @@ ath_rate_tx_complete(struct ath_softc *s
+ dev_info,
+ MAC_ADDR(an->an_node.ni_macaddr),
+ bin_to_size(size_to_bin(frame_size)),
+- sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate0)].ieeerate,
+- MS(ds->ds_ctl2, AR_XmitDataTries0),
+- sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate1)].ieeerate,
+- MS(ds->ds_ctl2, AR_XmitDataTries1),
+- sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate2)].ieeerate,
+- MS(ds->ds_ctl2, AR_XmitDataTries2),
+- sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate3)].ieeerate,
+- MS(ds->ds_ctl2, AR_XmitDataTries3),
++ mrr->rate0,
++ mrr->rate1,
++ mrr->rate2,
++ mrr->rate3,
+ ts->ts_status ? "FAIL" : "OK",
+ short_tries, long_tries);
+ }
+
+- mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT) && ENABLE_MRR;
+-
+-
+- if (!mrr || !(ts->ts_rate & HAL_TXSTAT_ALTRATE)) {
++ if (!use_mrr || !(ts->ts_rate & HAL_TXSTAT_ALTRATE)) {
+ /* only one rate was used */
+ int ndx = rate_to_ndx(sn, final_rate);
+ if ((ndx >= 0) && (ndx < sn->num_rates)) {
+@@ -593,7 +579,6 @@ ath_rate_tx_complete(struct ath_softc *s
+ short_tries, long_tries, ts->ts_status);
+ }
+ } else {
+- unsigned int rate[4], tries[4];
+ int ndx[4];
+ int finalTSIdx = ts->ts_finaltsi;
+
+@@ -601,21 +586,10 @@ ath_rate_tx_complete(struct ath_softc *s
+ * Process intermediate rates that failed.
+ */
+
+- rate[0] = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate0)].ieeerate;
+- tries[0] = MS(ds->ds_ctl2, AR_XmitDataTries0);
+- ndx[0] = rate_to_ndx(sn, rate[0]);
+-
+- rate[1] = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate1)].ieeerate;
+- tries[1] = MS(ds->ds_ctl2, AR_XmitDataTries1);
+- ndx[1] = rate_to_ndx(sn, rate[1]);
+-
+- rate[2] = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate2)].ieeerate;
+- tries[2] = MS(ds->ds_ctl2, AR_XmitDataTries2);
+- ndx[2] = rate_to_ndx(sn, rate[2]);
+-
+- rate[3] = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate3)].ieeerate;
+- tries[3] = MS(ds->ds_ctl2, AR_XmitDataTries3);
+- ndx[3] = rate_to_ndx(sn, rate[3]);
++ ndx[0] = rate_to_ndx(sn, mrr->rate0);
++ ndx[1] = rate_to_ndx(sn, mrr->rate1);
++ ndx[2] = rate_to_ndx(sn, mrr->rate2);
++ ndx[3] = rate_to_ndx(sn, mrr->rate3);
+
+ #if 0
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: " MAC_FMT " size %u finaltsidx %u tries %u status %u rate/try %u/%u %u/%u %u/%u %u/%u\n",
+@@ -636,43 +610,43 @@ ath_rate_tx_complete(struct ath_softc *s
+ * sample higher rates 1 try at a time doing so
+ * may unfairly penalize them.
+ */
+- if (tries[0] && ndx[0] >= 0) {
++ if (mrr->retries0 && ndx[0] >= 0) {
+ update_stats(sc, an, frame_size,
+- ndx[0], tries[0],
+- ndx[1], tries[1],
+- ndx[2], tries[2],
+- ndx[3], tries[3],
++ ndx[0], mrr->retries0,
++ ndx[1], mrr->retries1,
++ ndx[2], mrr->retries2,
++ ndx[3], mrr->retries3,
+ short_tries, long_tries,
+- long_tries > tries[0]);
+- long_tries -= tries[0];
++ long_tries > mrr->retries0);
++ long_tries -= mrr->retries0;
+
+ }
+
+- if (tries[1] && ndx[1] >= 0 && finalTSIdx > 0) {
++ if (mrr->retries1 && ndx[1] >= 0 && finalTSIdx > 0) {
+ update_stats(sc, an, frame_size,
+- ndx[1], tries[1],
+- ndx[2], tries[2],
+- ndx[3], tries[3],
++ ndx[1], mrr->retries1,
++ ndx[2], mrr->retries2,
++ ndx[3], mrr->retries3,
+ 0, 0,
+ short_tries, long_tries,
+ ts->ts_status);
+- long_tries -= tries[1];
++ long_tries -= mrr->retries1;
+ }
+
+- if (tries[2] && ndx[2] >= 0 && finalTSIdx > 1) {
++ if (mrr->retries2 && ndx[2] >= 0 && finalTSIdx > 1) {
+ update_stats(sc, an, frame_size,
+- ndx[2], tries[2],
+- ndx[3], tries[3],
++ ndx[2], mrr->retries2,
++ ndx[3], mrr->retries3,
+ 0, 0,
+ 0, 0,
+ short_tries, long_tries,
+ ts->ts_status);
+- long_tries -= tries[2];
++ long_tries -= mrr->retries2;
+ }
+
+- if (tries[3] && ndx[3] >= 0 && finalTSIdx > 2) {
++ if (mrr->retries3 && ndx[3] >= 0 && finalTSIdx > 2) {
+ update_stats(sc, an, frame_size,
+- ndx[3], tries[3],
++ ndx[3], mrr->retries3,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+--- a/ath_rate/sample/sample.h
++++ b/ath_rate/sample/sample.h
+@@ -98,35 +98,4 @@ struct sample_node {
+ };
+ #define ATH_NODE_SAMPLE(an) ((struct sample_node *)&an[1])
+
+-/*
+- * Definitions for pulling the rate and trie counts from
+- * a 5212 h/w descriptor. These Don't belong here; the
+- * driver should record this information so the rate control
+- * code doesn't go groveling around in the descriptor bits.
+- */
+-#define ds_ctl2 ds_hw[0]
+-#define ds_ctl3 ds_hw[1]
+-
+-/* TX ds_ctl3 */
+-#define AR_XmitDataTries0 0x000f0000 /* series 0 max attempts */
+-#define AR_XmitDataTries0_S 16
+-#define AR_XmitDataTries1 0x00f00000 /* series 1 max attempts */
+-#define AR_XmitDataTries1_S 20
+-#define AR_XmitDataTries2 0x0f000000 /* series 2 max attempts */
+-#define AR_XmitDataTries2_S 24
+-#define AR_XmitDataTries3 0xf0000000 /* series 3 max attempts */
+-#define AR_XmitDataTries3_S 28
+-
+-/* TX ds_ctl3 */
+-#define AR_XmitRate0 0x0000001f /* series 0 tx rate */
+-#define AR_XmitRate0_S 0
+-#define AR_XmitRate1 0x000003e0 /* series 1 tx rate */
+-#define AR_XmitRate1_S 5
+-#define AR_XmitRate2 0x00007c00 /* series 2 tx rate */
+-#define AR_XmitRate2_S 10
+-#define AR_XmitRate3 0x000f8000 /* series 3 tx rate */
+-#define AR_XmitRate3_S 15
+-
+-#define MS(_v, _f) (((_v) & (_f)) >> _f##_S)
+-
+ #endif /* _DEV_ATH_RATE_SAMPLE_H */
diff --git a/package/madwifi/patches/426-header_len.patch b/package/madwifi/patches/426-header_len.patch
new file mode 100644
index 000000000..acfbc18c6
--- /dev/null
+++ b/package/madwifi/patches/426-header_len.patch
@@ -0,0 +1,12 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -888,9 +888,6 @@ ath_attach(u_int16_t devid, struct net_d
+ IEEE80211_ADDR_LEN +
+ IEEE80211_WEP_IVLEN +
+ IEEE80211_WEP_KIDLEN;
+-#ifdef ATH_SUPERG_FF
+- dev->hard_header_len += ATH_FF_MAX_HDR;
+-#endif
+ #endif
+ dev->type = ARPHRD_IEEE80211;
+
diff --git a/package/madwifi/patches/427-ignore_eeprom_ff.patch b/package/madwifi/patches/427-ignore_eeprom_ff.patch
new file mode 100644
index 000000000..eead70c99
--- /dev/null
+++ b/package/madwifi/patches/427-ignore_eeprom_ff.patch
@@ -0,0 +1,11 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -915,7 +915,7 @@ ath_attach(u_int16_t devid, struct net_d
+ ic->ic_ath_cap = 0;
+ sc->sc_fftxqmin = ATH_FF_TXQMIN;
+ #ifdef ATH_SUPERG_FF
+- ic->ic_ath_cap |= (ath_hal_fastframesupported(ah) ?
++ ic->ic_ath_cap |= (ah->ah_macType >= 5212 ?
+ IEEE80211_ATHC_FF : 0);
+ #endif
+ ic->ic_ath_cap |= (ath_hal_burstsupported(ah) ?
diff --git a/package/madwifi/patches/430-use_netdev_priv.patch b/package/madwifi/patches/430-use_netdev_priv.patch
new file mode 100644
index 000000000..3f65424a5
--- /dev/null
+++ b/package/madwifi/patches/430-use_netdev_priv.patch
@@ -0,0 +1,1936 @@
+--- a/ath/ath_wprobe.c
++++ b/ath/ath_wprobe.c
+@@ -119,7 +119,7 @@ ath_wprobe_sync(struct wprobe_iface *dev
+ struct ath_vap *avp = container_of(dev, struct ath_vap, av_wpif);
+ struct ieee80211vap *vap = &avp->av_vap;
+ struct ieee80211com *ic = vap->iv_ic;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ struct ath_hal *ah = sc->sc_ah;
+ u32 cc, busy, rx, tx;
+ s16 noise;
+@@ -192,7 +192,7 @@ ath_lookup_rateval(struct ieee80211_node
+ {
+ struct ieee80211vap *vap = ni->ni_vap;
+ struct ieee80211com *ic = vap->iv_ic;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ const HAL_RATE_TABLE *rt = sc->sc_currates;
+
+ if ((!rt) || (rate < 0) || (rate >= ARRAY_SIZE(sc->sc_hwmap)))
+--- a/ath/if_ath_ahb.c
++++ b/ath/if_ath_ahb.c
+@@ -203,7 +203,7 @@ static int ahb_wmac_probe(struct platfor
+ if (!dev)
+ return -ENOMEM;
+
+- sc = dev->priv;
++ sc = netdev_priv(dev);
+ sc->aps_sc.sc_dev = dev;
+
+ dev->irq = platform_get_irq(pdev, 0);
+@@ -300,7 +300,7 @@ init_ath_wmac(u_int16_t devid, u_int16_t
+ printk(KERN_ERR "%s: no memory for device state\n", dev_info);
+ goto bad2;
+ }
+- sc = dev->priv;
++ sc = netdev_priv(dev);
+ sc->aps_sc.sc_dev = dev;
+
+ /*
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -569,7 +569,7 @@ static inline int rate_factor(int mode)
+ int
+ ath_attach(u_int16_t devid, struct net_device *dev, HAL_BUS_TAG tag)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap;
+ struct ath_hal *ah;
+@@ -1206,7 +1206,7 @@ bad:
+ int
+ ath_detach(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+
+ HAL_INT tmp;
+@@ -1266,7 +1266,7 @@ static struct ieee80211vap *
+ ath_vap_create(struct ieee80211com *ic, const char *name,
+ int opmode, int flags, struct net_device *mdev, struct ieee80211vap *master)
+ {
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct net_device *dev;
+ struct ath_vap *avp;
+@@ -1344,7 +1344,7 @@ ath_vap_create(struct ieee80211com *ic,
+ return NULL;
+ }
+
+- avp = dev->priv;
++ avp = netdev_priv(dev);
+ ieee80211_vap_setup(ic, dev, name, opmode, flags, master);
+ /* override with driver methods */
+ vap = &avp->av_vap;
+@@ -1571,7 +1571,7 @@ static void
+ ath_vap_delete(struct ieee80211vap *vap)
+ {
+ struct net_device *dev = vap->iv_ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ath_vap *avp = ATH_VAP(vap);
+ int decrease = 1;
+@@ -1673,7 +1673,7 @@ void
+ ath_suspend(struct net_device *dev)
+ {
+ #ifdef AR_DEBUG
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ #endif
+
+ DPRINTF(sc, ATH_DEBUG_ANY, "flags=%x\n", dev->flags);
+@@ -1684,7 +1684,7 @@ void
+ ath_resume(struct net_device *dev)
+ {
+ #ifdef AR_DEBUG
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ #endif
+
+ DPRINTF(sc, ATH_DEBUG_ANY, "flags=%x\n", dev->flags);
+@@ -2248,7 +2248,7 @@ ath_intr(int irq, void *dev_id, struct p
+ #endif
+ {
+ struct net_device *dev = dev_id;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ u_int64_t hw_tsf = 0;
+ HAL_INT status;
+@@ -2469,7 +2469,7 @@ static void
+ ath_fatal_tasklet(TQUEUE_ARG data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ EPRINTF(sc, "Hardware error; resetting.\n");
+ ath_reset(dev);
+@@ -2479,7 +2479,7 @@ static void
+ ath_rxorn_tasklet(TQUEUE_ARG data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ EPRINTF(sc, "Receive FIFO overrun; resetting.\n");
+ ath_reset(dev);
+@@ -2489,7 +2489,7 @@ static void
+ ath_bmiss_tasklet(TQUEUE_ARG data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ if (time_before(jiffies, sc->sc_ic.ic_bmiss_guard)) {
+ /* Beacon miss interrupt occured too short after last beacon
+@@ -2568,7 +2568,7 @@ done:
+ static int
+ ath_init(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_hal *ah = sc->sc_ah;
+ HAL_STATUS status;
+@@ -2693,7 +2693,7 @@ done:
+ static int
+ ath_stop_locked(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_hal *ah = sc->sc_ah;
+
+@@ -2778,7 +2778,7 @@ static void ath_set_beacon_cal(struct at
+ static int
+ ath_stop(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ int error;
+
+ ATH_LOCK(sc);
+@@ -2998,7 +2998,7 @@ ath_fetch_idle_time(struct ath_softc *sc
+ static int
+ ath_reset(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211_channel *c;
+@@ -3164,7 +3164,7 @@ dot11_to_ratecode(struct ath_softc *sc,
+ static int
+ ath_tx_startraw(struct net_device *dev, struct ath_buf *bf, struct sk_buff *skb)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211_phy_params *ph = (struct ieee80211_phy_params *)
+ (SKB_CB(skb) + 1); /* NB: SKB_CB casts to CB struct*. */
+@@ -3477,7 +3477,7 @@ _take_txbuf(struct ath_softc *sc, int fo
+ static int
+ ath_hardstart(struct sk_buff *skb, struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211_node *ni = NULL;
+ struct ath_buf *bf = NULL;
+ ath_bufhead bf_head;
+@@ -3792,7 +3792,7 @@ static int
+ ath_mgtstart(struct ieee80211com *ic, struct sk_buff *skb)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_buf *bf = NULL;
+ int error;
+
+@@ -4151,7 +4151,7 @@ static ieee80211_keyix_t
+ ath_key_alloc(struct ieee80211vap *vap, const struct ieee80211_key *k)
+ {
+ struct net_device *dev = vap->iv_ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ /*
+ * Group key allocation must be handled specially for
+@@ -4216,7 +4216,7 @@ ath_key_delete(struct ieee80211vap *vap,
+ struct ieee80211_node *ninfo)
+ {
+ struct net_device *dev = vap->iv_ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211_node *ni = NULL;
+ const struct ieee80211_cipher *cip = k->wk_cipher;
+@@ -4292,14 +4292,14 @@ ath_key_set(struct ieee80211vap *vap, co
+ const u_int8_t mac[IEEE80211_ADDR_LEN])
+ {
+ struct net_device *dev = vap->iv_ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ return ath_keyset(sc, k, mac, vap->iv_bss);
+ }
+
+ static void ath_poll_disable(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ /*
+ * XXX Using in_softirq is not right since we might
+@@ -4317,7 +4317,7 @@ static void ath_poll_disable(struct net_
+
+ static void ath_poll_enable(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ /* NB: see above */
+ if (!in_softirq()) {
+@@ -4343,7 +4343,7 @@ ath_key_update_begin(struct ieee80211vap
+ {
+ struct net_device *dev = vap->iv_ic->ic_dev;
+ #ifdef AR_DEBUG
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ #endif
+
+ DPRINTF(sc, ATH_DEBUG_KEYCACHE, "Begin\n");
+@@ -4361,7 +4361,7 @@ ath_key_update_end(struct ieee80211vap *
+ {
+ struct net_device *dev = vap->iv_ic->ic_dev;
+ #ifdef AR_DEBUG
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ #endif
+
+ DPRINTF(sc, ATH_DEBUG_KEYCACHE, "End\n");
+@@ -4454,7 +4454,7 @@ ath_merge_mcast(struct ath_softc *sc, u_
+ static void
+ ath_mode_init(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ u_int32_t rfilt, mfilt[2];
+
+@@ -4540,7 +4540,7 @@ ath_set_timing(struct ath_softc *sc)
+ static void
+ ath_updateslot(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+
+ /*
+@@ -4570,7 +4570,7 @@ ath_beacon_dturbo_config(struct ieee8021
+ (vap->iv_bss && (vap->iv_bss->ni_ath_flags & (IEEE80211_ATHC_TURBOP)) == \
+ (IEEE80211_ATHC_TURBOP))
+ struct ieee80211com *ic = vap->iv_ic;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+
+ if (ic->ic_opmode == IEEE80211_M_HOSTAP && IS_CAPABLE(vap)) {
+
+@@ -4618,7 +4618,7 @@ static void
+ ath_beacon_dturbo_update(struct ieee80211vap *vap, int *needmark, u_int8_t dtim)
+ {
+ struct ieee80211com *ic = vap->iv_ic;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ u_int32_t bss_traffic;
+
+ if (sc->sc_ignore_ar) {
+@@ -4759,7 +4759,7 @@ static void
+ ath_turbo_switch_mode(unsigned long data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+ unsigned int newflags;
+
+@@ -5438,7 +5438,7 @@ static void
+ ath_bstuck_tasklet(TQUEUE_ARG data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ /*
+ * XXX:if the bmisscount is cleared while the
+ * tasklet execution is pending, the following
+@@ -5891,7 +5891,7 @@ ath_node_alloc_debug(struct ieee80211vap
+ ath_node_alloc(struct ieee80211vap *vap)
+ #endif
+ {
+- struct ath_softc *sc = vap->iv_ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(vap->iv_ic->ic_dev);
+ const size_t space = sizeof(struct ath_node) + sc->sc_rc->arc_space;
+ struct ath_node *an = kmalloc(space, GFP_ATOMIC);
+ if (an != NULL) {
+@@ -5927,7 +5927,7 @@ ath_node_cleanup(struct ieee80211_node *
+ #endif
+ {
+ struct ieee80211com *ic = ni->ni_ic;
+- struct ath_softc *sc = ni->ni_ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ni->ni_ic->ic_dev);
+ struct ath_node *an = ATH_NODE(ni);
+ struct ath_buf *bf;
+
+@@ -5985,7 +5985,7 @@ ath_node_free_debug(struct ieee80211_nod
+ ath_node_free(struct ieee80211_node *ni)
+ #endif
+ {
+- struct ath_softc *sc = ni->ni_ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ni->ni_ic->ic_dev);
+
+ #ifdef IEEE80211_DEBUG_REFCNT
+ sc->sc_node_free_debug(ni, func, line);
+@@ -6033,7 +6033,7 @@ ath_node_move_data(const struct ieee8021
+ #ifdef NOT_YET
+ struct ath_txq *txq = NULL;
+ struct ieee80211com *ic = ni->ni_ic;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ struct ath_buf *bf, *prev, *bf_tmp, *bf_tmp1;
+ struct ath_hal *ah = sc->sc_ah;
+ struct sk_buff *skb = NULL;
+@@ -6553,7 +6553,7 @@ static void
+ ath_capture(struct net_device *dev, const struct ath_buf *bf,
+ struct sk_buff *skb, u_int64_t tsf, unsigned int tx)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct sk_buff *tskb = NULL;
+
+@@ -6613,7 +6613,7 @@ static void
+ ath_recv_mgmt(struct ieee80211vap * vap, struct ieee80211_node *ni_or_null,
+ struct sk_buff *skb, int subtype, int rssi, u_int64_t rtsf)
+ {
+- struct ath_softc *sc = vap->iv_ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(vap->iv_ic->ic_dev);
+ #ifdef AR_DEBUG
+ struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data;
+ #endif
+@@ -6780,7 +6780,7 @@ ath_rx_poll(struct net_device *dev, int
+ struct net_device *dev = sc->sc_dev;
+ int rx_limit = budget;
+ #else
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ int rx_limit = min(dev->quota, *budget);
+ #endif
+ struct ath_buf *bf;
+@@ -7305,7 +7305,7 @@ static void ath_grppoll_start(struct iee
+ struct sk_buff *skb = NULL;
+ struct ath_buf *bf, *head = NULL;
+ struct ieee80211com *ic = vap->iv_ic;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ struct ath_hal *ah = sc->sc_ah;
+ u_int8_t rate;
+ unsigned int ctsrate = 0, ctsduration = 0;
+@@ -7523,7 +7523,7 @@ static void ath_grppoll_start(struct iee
+ static void ath_grppoll_stop(struct ieee80211vap *vap)
+ {
+ struct ieee80211com *ic = vap->iv_ic;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ath_txq *txq = &sc->sc_grpplq;
+ struct ath_buf *bf;
+@@ -7735,7 +7735,7 @@ ath_txq_update(struct ath_softc *sc, str
+ static int
+ ath_wme_update(struct ieee80211com *ic)
+ {
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+
+ if (sc->sc_uapsdq)
+ ath_txq_update(sc, sc->sc_uapsdq, WME_AC_VO);
+@@ -7754,7 +7754,7 @@ ath_uapsd_flush(struct ieee80211_node *n
+ {
+ struct ath_node *an = ATH_NODE(ni);
+ struct ath_buf *bf;
+- struct ath_softc *sc = ni->ni_ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ni->ni_ic->ic_dev);
+ struct ath_txq *txq;
+
+ ATH_NODE_UAPSD_LOCK_IRQ(an);
+@@ -7945,7 +7945,7 @@ ath_tx_start(struct net_device *dev, str
+ struct ath_buf *bf, struct sk_buff *skb, int nextfraglen)
+ {
+ #define MIN(a,b) ((a) < (b) ? (a) : (b))
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = ni->ni_ic;
+ struct ieee80211vap *vap = ni->ni_vap;
+ struct ath_hal *ah = sc->sc_ah;
+@@ -8854,7 +8854,7 @@ static void
+ ath_tx_tasklet_q0(TQUEUE_ARG data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ unsigned long flags;
+
+ process_tx_again:
+@@ -8885,7 +8885,7 @@ static void
+ ath_tx_tasklet_q0123(TQUEUE_ARG data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ unsigned long flags;
+
+ process_tx_again:
+@@ -8930,7 +8930,7 @@ static void
+ ath_tx_tasklet(TQUEUE_ARG data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ unsigned int i;
+ unsigned long flags;
+
+@@ -8958,7 +8958,7 @@ process_tx_again:
+ static void
+ ath_tx_timeout(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ if (ath_chan_unavail(sc))
+ return;
+@@ -9366,7 +9366,7 @@ static void
+ ath_calibrate(unsigned long arg)
+ {
+ struct net_device *dev = (struct net_device *)arg;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211com *ic = &sc->sc_ic;
+ /* u_int32_t nchans; */
+@@ -9441,7 +9441,7 @@ static void
+ ath_scan_start(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ u_int32_t rfilt;
+
+@@ -9461,7 +9461,7 @@ static void
+ ath_scan_end(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ u_int32_t rfilt;
+
+@@ -9479,7 +9479,7 @@ static void
+ ath_set_channel(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ (void) ath_chan_set(sc, ic->ic_curchan);
+ ic->ic_channoise = ath_hal_get_channel_noise(sc->sc_ah, &(sc->sc_curchan));
+@@ -9496,7 +9496,7 @@ ath_set_channel(struct ieee80211com *ic)
+ static void
+ ath_set_coverageclass(struct ieee80211com *ic)
+ {
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+
+ sc->sc_coverage = ic->ic_coverageclass * 3;
+ ath_set_timing(sc);
+@@ -9507,7 +9507,7 @@ ath_set_coverageclass(struct ieee80211co
+ static u_int
+ ath_mhz2ieee(struct ieee80211com *ic, u_int freq, u_int flags)
+ {
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+
+ return (ath_hal_mhz2ieee(sc->sc_ah, freq, flags));
+ }
+@@ -9522,7 +9522,7 @@ ath_newstate(struct ieee80211vap *vap, e
+ struct ath_vap *avp = ATH_VAP(vap);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211_node *ni, *wds_ni;
+ unsigned int i;
+@@ -9962,7 +9962,7 @@ ath_setup_comp(struct ieee80211_node *ni
+ {
+ #define IEEE80211_KEY_XR (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV)
+ struct ieee80211vap *vap = ni->ni_vap;
+- struct ath_softc *sc = vap->iv_ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(vap->iv_ic->ic_dev);
+ struct ath_node *an = ATH_NODE(ni);
+ ieee80211_keyix_t keyix;
+
+@@ -10016,7 +10016,7 @@ static void
+ ath_setup_stationkey(struct ieee80211_node *ni)
+ {
+ struct ieee80211vap *vap = ni->ni_vap;
+- struct ath_softc *sc = vap->iv_ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(vap->iv_ic->ic_dev);
+ ieee80211_keyix_t keyix;
+
+ keyix = ath_key_alloc(vap, &ni->ni_ucastkey);
+@@ -10177,7 +10177,7 @@ ath_newassoc(struct ieee80211_node *ni,
+ {
+ struct ieee80211com *ic = ni->ni_ic;
+ struct ieee80211vap *vap = ni->ni_vap;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+
+ sc->sc_rc->ops->newassoc(sc, ATH_NODE(ni), isnew);
+ ath_wprobe_node_join(ni->ni_vap, ni);
+@@ -10208,7 +10208,7 @@ ath_newassoc(struct ieee80211_node *ni,
+ static int
+ ath_getchannels(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_hal *ah = sc->sc_ah;
+ HAL_CHANNEL *chans;
+@@ -10485,7 +10485,7 @@ ath_update_txpow(struct ath_softc *sc)
+ static int
+ ath_xr_rate_setup(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211com *ic = &sc->sc_ic;
+ const HAL_RATE_TABLE *rt;
+@@ -10516,7 +10516,7 @@ ath_xr_rate_setup(struct net_device *dev
+ static int
+ ath_rate_setup(struct net_device *dev, u_int mode)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211com *ic = &sc->sc_ic;
+ const HAL_RATE_TABLE *rt;
+@@ -10763,7 +10763,7 @@ ath_printtxbuf(const struct ath_buf *bf,
+ {
+ const struct ath_tx_status *ts = &bf->bf_dsstatus.ds_txstat;
+ const struct ath_desc *ds = bf->bf_desc;
+- struct ath_softc *sc = bf->bf_node->ni_ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(bf->bf_node->ni_ic->ic_dev);
+ u_int8_t status = done ? ts->ts_status : 0;
+
+ DPRINTF(sc, ATH_DEBUG_ANY,
+@@ -10790,7 +10790,7 @@ ath_printtxbuf(const struct ath_buf *bf,
+ static struct net_device_stats *
+ ath_getstats(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct net_device_stats *stats = &sc->sc_devstats;
+
+ /* update according to private statistics */
+@@ -10813,7 +10813,7 @@ ath_getstats(struct net_device *dev)
+ static int
+ ath_set_mac_address(struct net_device *dev, void *addr)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_hal *ah = sc->sc_ah;
+ struct sockaddr *mac = addr;
+@@ -10842,7 +10842,7 @@ ath_set_mac_address(struct net_device *d
+ static int
+ ath_change_mtu(struct net_device *dev, int mtu)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ int error = 0;
+
+ if (!(ATH_MIN_MTU < mtu && mtu <= ATH_MAX_MTU)) {
+@@ -10929,7 +10929,7 @@ bad:
+ static int
+ ath_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+ int error;
+
+@@ -11810,7 +11810,7 @@ static void
+ ath_announce(struct net_device *dev)
+ {
+ #define HAL_MODE_DUALBAND (HAL_MODE_11A|HAL_MODE_11B)
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ u_int modes, cc;
+ static const int MLEN = 1024;
+@@ -11997,7 +11997,7 @@ static void
+ txcont_configure_radio(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211_wme_state *wme = &ic->ic_wme;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+@@ -12271,7 +12271,7 @@ static void
+ txcont_queue_packet(struct ieee80211com *ic, struct ath_txq* txq)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ath_buf *bf = NULL;
+ struct sk_buff *skb = NULL;
+@@ -12404,7 +12404,7 @@ static void
+ txcont_on(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ if (IFF_RUNNING != (ic->ic_dev->flags & IFF_RUNNING)) {
+ EPRINTF(sc, "Cannot enable txcont when"
+@@ -12425,7 +12425,7 @@ static void
+ txcont_off(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ if (TAILQ_FIRST(&ic->ic_vaps)->iv_opmode != IEEE80211_M_WDS)
+ sc->sc_beacons = 1;
+@@ -12439,7 +12439,7 @@ static int
+ ath_get_dfs_testmode(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ return sc->sc_dfs_testmode;
+ }
+
+@@ -12466,7 +12466,7 @@ static void
+ ath_set_dfs_testmode(struct ieee80211com *ic, int value)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ sc->sc_dfs_testmode = !!value;
+ }
+
+@@ -12476,7 +12476,7 @@ static int
+ ath_get_txcont(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ return sc->sc_txcont;
+ }
+
+@@ -12494,7 +12494,7 @@ static void
+ ath_set_txcont_power(struct ieee80211com *ic, unsigned int txpower)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ int new_txcont_power = txpower > IEEE80211_TXPOWER_MAX ?
+ IEEE80211_TXPOWER_MAX : txpower;
+ if (sc->sc_txcont_power != new_txcont_power) {
+@@ -12512,7 +12512,7 @@ static int
+ ath_get_txcont_power(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ /* VERY conservative default */
+ return sc->sc_txcont_power ? sc->sc_txcont_power : 0;
+ }
+@@ -12522,7 +12522,7 @@ ath_get_txcont_power(struct ieee80211com
+ ath_set_txcont_rate(struct ieee80211com *ic, unsigned int new_rate)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ if (sc->sc_txcont_rate != new_rate) {
+ /* NOTE: This value is sanity checked and dropped down to
+ * closest rate in txcont_on. */
+@@ -12539,7 +12539,7 @@ ath_set_txcont_rate(struct ieee80211com
+ ath_get_txcont_rate(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ return sc->sc_txcont_rate ? sc->sc_txcont_rate : 0;
+ }
+
+@@ -12549,7 +12549,7 @@ static void
+ ath_set_dfs_cac_time(struct ieee80211com *ic, unsigned int time_s)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ sc->sc_dfs_cac_period = time_s;
+ }
+
+@@ -12559,7 +12559,7 @@ static unsigned int
+ ath_get_dfs_cac_time(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ return sc->sc_dfs_cac_period;
+ }
+
+@@ -12579,7 +12579,7 @@ static void
+ ath_set_dfs_excl_period(struct ieee80211com *ic, unsigned int time_s)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ sc->sc_dfs_excl_period = time_s;
+ }
+
+@@ -12588,7 +12588,7 @@ static unsigned int
+ ath_get_dfs_excl_period(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ return sc->sc_dfs_excl_period;
+ }
+
+@@ -12600,7 +12600,7 @@ static unsigned int
+ ath_test_radar(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ if ((ic->ic_flags & IEEE80211_F_DOTH) && (sc->sc_curchan.privFlags & CHANNEL_DFS))
+ ath_radar_detected(sc, "ath_test_radar from user space");
+ else
+@@ -12616,7 +12616,7 @@ static unsigned int
+ ath_dump_hal_map(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ ath_hal_dump_map(sc->sc_ah);
+ return 0;
+ }
+@@ -12724,7 +12724,7 @@ ath_rcv_dev_event(struct notifier_block
+ void *ptr)
+ {
+ struct net_device *dev = (struct net_device *)ptr;
+- struct ath_softc *sc = (struct ath_softc *)dev->priv;
++ struct ath_softc *sc = (struct ath_softc *)netdev_priv(dev);
+
+ if (!dev || !sc || dev->open != &ath_init)
+ return 0;
+@@ -13459,7 +13459,7 @@ static unsigned int
+ ath_read_register(struct ieee80211com *ic, unsigned int address,
+ unsigned int* value)
+ {
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ if (address >= MAX_REGISTER_ADDRESS) {
+ IPRINTF(sc, "Illegal Atheros register access "
+ "attempted: 0x%04x >= 0x%04x\n",
+@@ -13489,7 +13489,7 @@ static unsigned int
+ ath_write_register(struct ieee80211com *ic, unsigned int address,
+ unsigned int value)
+ {
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ if (address >= MAX_REGISTER_ADDRESS) {
+ IPRINTF(sc, "Illegal Atheros register access "
+ "attempted: 0x%04x >= 0x%04x\n",
+@@ -13517,7 +13517,7 @@ static void
+ ath_registers_dump(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ ath_ar5212_registers_dump(sc);
+ }
+ #endif /* #ifdef ATH_REVERSE_ENGINEERING */
+@@ -13529,7 +13529,7 @@ static void
+ ath_registers_mark(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ ath_ar5212_registers_mark(sc);
+ }
+ #endif /* #ifdef ATH_REVERSE_ENGINEERING */
+@@ -13541,7 +13541,7 @@ static void
+ ath_registers_dump_delta(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ ath_ar5212_registers_dump_delta(sc);
+ }
+ #endif /* #ifdef ATH_REVERSE_ENGINEERING */
+--- a/ath/if_ath_pci.c
++++ b/ath/if_ath_pci.c
+@@ -226,7 +226,7 @@ ath_pci_probe(struct pci_dev *pdev, cons
+ printk(KERN_ERR "%s: no memory for device state\n", dev_info);
+ goto bad2;
+ }
+- sc = dev->priv;
++ sc = netdev_priv(dev);
+ sc->aps_sc.sc_dev = dev;
+ sc->aps_sc.sc_iobase = mem;
+
+@@ -309,7 +309,7 @@ static void
+ ath_pci_remove(struct pci_dev *pdev)
+ {
+ struct net_device *dev = pci_get_drvdata(pdev);
+- struct ath_pci_softc *sc = dev->priv;
++ struct ath_pci_softc *sc = netdev_priv(dev);
+
+ ath_detach(dev);
+ if (dev->irq)
+@@ -327,7 +327,7 @@ ath_pci_suspend(struct pci_dev *pdev, pm
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ ath_suspend(dev);
+- PCI_SAVE_STATE(pdev, ((struct ath_pci_softc *)dev->priv)->aps_pmstate);
++ PCI_SAVE_STATE(pdev, ((struct ath_pci_softc *)netdev_priv(dev))->aps_pmstate);
+ pci_disable_device(pdev);
+ return pci_set_power_state(pdev, PCI_D3hot);
+ }
+@@ -344,7 +344,7 @@ ath_pci_resume(struct pci_dev *pdev)
+ return err;
+
+ /* XXX - Should this return nonzero on fail? */
+- PCI_RESTORE_STATE(pdev, ((struct ath_pci_softc *)dev->priv)->aps_pmstate);
++ PCI_RESTORE_STATE(pdev, ((struct ath_pci_softc *)netdev_priv(dev))->aps_pmstate);
+
+ err = pci_enable_device(pdev);
+ if (err)
+--- a/ath/if_ath_radar.c
++++ b/ath/if_ath_radar.c
+@@ -1533,7 +1533,7 @@ static void ath_rp_clear(struct ath_soft
+ static void ath_rp_tasklet(TQUEUE_ARG data)
+ {
+ struct net_device *dev = (struct net_device *) data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ if (sc->sc_rp_analyse != NULL)
+ sc->sc_rp_analyse(sc);
+--- a/ath_rate/amrr/amrr.c
++++ b/ath_rate/amrr/amrr.c
+@@ -298,7 +298,7 @@ ath_rate_ctl_start(struct ath_softc *sc,
+ static void
+ ath_rate_cb(void *arg, struct ieee80211_node *ni)
+ {
+- ath_rate_update(ni->ni_ic->ic_dev->priv, ni, (long) arg);
++ ath_rate_update(netdev_priv(ni->ni_ic->ic_dev), ni, (long) arg);
+ }
+
+ /*
+@@ -308,7 +308,7 @@ static void
+ ath_rate_newstate(struct ieee80211vap *vap, enum ieee80211_state state)
+ {
+ struct ieee80211com *ic = vap->iv_ic;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ struct amrr_softc *asc = (struct amrr_softc *) sc->sc_rc;
+ struct ieee80211_node *ni;
+
+@@ -420,7 +420,7 @@ static void
+ ath_ratectl(unsigned long data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct amrr_softc *asc = (struct amrr_softc *)sc->sc_rc;
+ struct ieee80211com *ic = &sc->sc_ic;
+ int interval;
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -622,7 +622,7 @@ ath_rate_ctl_reset(struct ath_softc *sc,
+ static void
+ ath_rate_cb(void *arg, struct ieee80211_node *ni)
+ {
+- ath_rate_ctl_reset(ni->ni_ic->ic_dev->priv, ni);
++ ath_rate_ctl_reset(netdev_priv(ni->ni_ic->ic_dev), ni);
+ }
+
+ /* Reset the rate control state for each 802.11 state transition. */
+@@ -636,7 +636,7 @@ ath_rate_newstate(struct ieee80211vap *v
+ /* Sync rates for associated stations and neighbors. */
+ ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_cb, NULL);
+ }
+- ath_rate_newassoc(ic->ic_dev->priv, ATH_NODE(vap->iv_bss), 1);
++ ath_rate_newassoc(netdev_priv(ic->ic_dev), ATH_NODE(vap->iv_bss), 1);
+ }
+ }
+
+@@ -822,7 +822,7 @@ ath_proc_read_nodes(struct ieee80211vap
+ unsigned int x = 0;
+ unsigned int this_tp, this_prob, this_eprob;
+ #ifdef AR_DEBUG
+- struct ath_softc *sc = vap->iv_ic->ic_dev->priv;;
++ struct ath_softc *sc = netdev_priv(vap->iv_ic->ic_dev);
+ #endif
+
+ IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
+--- a/ath_rate/onoe/onoe.c
++++ b/ath_rate/onoe/onoe.c
+@@ -281,7 +281,7 @@ ath_rate_ctl_start(struct ath_softc *sc,
+ static void
+ ath_rate_cb(void *arg, struct ieee80211_node *ni)
+ {
+- ath_rate_update(ni->ni_ic->ic_dev->priv, ni, (long) arg);
++ ath_rate_update(netdev_priv(ni->ni_ic->ic_dev), ni, (long) arg);
+ }
+
+ /*
+@@ -291,7 +291,7 @@ static void
+ ath_rate_newstate(struct ieee80211vap *vap, enum ieee80211_state state)
+ {
+ struct ieee80211com *ic = vap->iv_ic;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ struct ieee80211_node *ni;
+
+ if (state == IEEE80211_S_INIT)
+--- a/ath_rate/sample/sample.c
++++ b/ath_rate/sample/sample.c
+@@ -803,7 +803,7 @@ ath_rate_ctl_reset(struct ath_softc *sc,
+ static void
+ ath_rate_cb(void *arg, struct ieee80211_node *ni)
+ {
+- ath_rate_ctl_reset(ni->ni_ic->ic_dev->priv, ni);
++ ath_rate_ctl_reset(netdev_priv(ni->ni_ic->ic_dev), ni);
+ }
+
+ /*
+@@ -821,7 +821,7 @@ ath_rate_newstate(struct ieee80211vap *v
+ */
+ ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_cb, NULL);
+ }
+- ath_rate_newassoc(ic->ic_dev->priv, ATH_NODE(vap->iv_bss), 1);
++ ath_rate_newassoc(netdev_priv(ic->ic_dev), ATH_NODE(vap->iv_bss), 1);
+ }
+ }
+
+--- a/include/compat.h
++++ b/include/compat.h
+@@ -162,6 +162,10 @@ static inline int timeval_compare(struct
+ #define IRQF_SHARED SA_SHIRQ
+ #endif
+
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27)
++#define netdev_priv(_netdev) ((_netdev)->priv)
++#endif
++
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+ #define skb_end_pointer(_skb) ((_skb)->end)
+ #define skb_tail_pointer(_skb) ((_skb)->tail)
+--- a/net80211/ieee80211.c
++++ b/net80211/ieee80211.c
+@@ -458,7 +458,7 @@ ieee80211_vap_setup(struct ieee80211com
+ #define IEEE80211_C_OPMODE \
+ (IEEE80211_C_IBSS | IEEE80211_C_HOSTAP | IEEE80211_C_AHDEMO | \
+ IEEE80211_C_MONITOR)
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct net_device *parent = ic->ic_dev;
+ int err;
+
+@@ -1355,7 +1355,7 @@ media_status(enum ieee80211_opmode opmod
+ static void
+ ieee80211com_media_status(struct net_device *dev, struct ifmediareq *imr)
+ {
+- struct ieee80211com *ic = dev->priv; /* XXX */
++ struct ieee80211com *ic = netdev_priv(dev); /* XXX */
+
+ imr->ifm_status = IFM_AVALID;
+ if (!TAILQ_EMPTY(&ic->ic_vaps))
+@@ -1407,7 +1407,7 @@ media2mode(const struct ifmedia_entry *i
+ static int
+ ieee80211com_media_change(struct net_device *dev)
+ {
+- struct ieee80211com *ic = dev->priv; /* XXX */
++ struct ieee80211com *ic = netdev_priv(dev); /* XXX */
+ struct ieee80211vap *vap;
+ struct ifmedia_entry *ime = ic->ic_media.ifm_cur;
+ enum ieee80211_phymode newphymode;
+@@ -1511,7 +1511,7 @@ checkrate(struct ieee80211com *ic, enum
+ int
+ ieee80211_media_change(struct net_device *dev)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ifmedia_entry *ime = vap->iv_media.ifm_cur;
+ enum ieee80211_phymode newmode;
+@@ -1545,7 +1545,7 @@ EXPORT_SYMBOL(ieee80211_media_change);
+ void
+ ieee80211_media_status(struct net_device *dev, struct ifmediareq *imr)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ enum ieee80211_phymode mode;
+ struct ieee80211_rateset *rs;
+@@ -1751,7 +1751,7 @@ EXPORT_SYMBOL(ieee80211_media2rate);
+ static struct net_device_stats *
+ ieee80211_getstats(struct net_device *dev)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct net_device_stats *stats = &vap->iv_devstats;
+
+ /* XXX: Total guess as to what to count where */
+@@ -1790,7 +1790,7 @@ ieee80211_change_mtu(struct net_device *
+ static void
+ ieee80211_set_multicast_list(struct net_device *dev)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct net_device *parent = ic->ic_dev;
+
+--- a/net80211/ieee80211_linux.c
++++ b/net80211/ieee80211_linux.c
+@@ -183,7 +183,7 @@ EXPORT_SYMBOL(ieee80211_getmgtframe);
+ static void
+ ieee80211_vlan_register(struct net_device *dev, struct vlan_group *grp)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ vap->iv_vlgrp = grp;
+ }
+@@ -194,7 +194,7 @@ ieee80211_vlan_register(struct net_devic
+ static void
+ ieee80211_vlan_add_vid(struct net_device *dev, unsigned short vid)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ if (vap->iv_vlgrp != NULL)
+ vap->iv_bss->ni_vlan = vid;
+@@ -206,7 +206,7 @@ ieee80211_vlan_add_vid(struct net_device
+ static void
+ ieee80211_vlan_kill_vid(struct net_device *dev, unsigned short vid)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ if (vap->iv_vlgrp != NULL)
+ vlan_group_set_device(vap->iv_vlgrp, vid, NULL);
+@@ -989,8 +989,8 @@ ieee80211_rcv_dev_event(struct notifier_
+
+ switch (event) {
+ case NETDEV_CHANGENAME:
+- ieee80211_virtfs_vdetach(dev->priv);
+- ieee80211_virtfs_latevattach(dev->priv);
++ ieee80211_virtfs_vdetach(netdev_priv(dev));
++ ieee80211_virtfs_latevattach(netdev_priv(dev));
+ return NOTIFY_DONE;
+ default:
+ break;
+--- a/net80211/ieee80211_output.c
++++ b/net80211/ieee80211_output.c
+@@ -201,7 +201,7 @@ ieee80211_classify(struct ieee80211_node
+ int
+ ieee80211_hardstart(struct sk_buff *skb, struct net_device *dev)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct net_device *parent = ic->ic_dev;
+ struct ieee80211_node *ni = NULL;
+@@ -317,7 +317,7 @@ bad:
+ */
+
+ void ieee80211_parent_queue_xmit(struct sk_buff *skb) {
+- struct ieee80211vap *vap = skb->dev->priv;
++ struct ieee80211vap *vap = netdev_priv(skb->dev);
+
+ vap->iv_devstats.tx_packets++;
+ vap->iv_devstats.tx_bytes += skb->len;
+--- a/net80211/ieee80211_proto.c
++++ b/net80211/ieee80211_proto.c
+@@ -970,7 +970,7 @@ ieee80211_init(struct net_device *dev, i
+ {
+ #define IS_RUNNING(_dev) \
+ ((_dev->flags & (IFF_RUNNING|IFF_UP)) == (IFF_RUNNING|IFF_UP))
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct net_device *parent = ic->ic_dev;
+
+@@ -1087,7 +1087,7 @@ ieee80211_init(struct net_device *dev, i
+ int
+ ieee80211_open(struct net_device *dev)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ return ieee80211_init(dev, 0);
+ }
+@@ -1131,7 +1131,7 @@ EXPORT_SYMBOL(ieee80211_start_running);
+ int
+ ieee80211_stop(struct net_device *dev)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct net_device *parent = ic->ic_dev;
+ struct ieee80211_node *tni, *ni;
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -87,7 +87,7 @@ pre_announced_chanswitch(struct net_devi
+ static int
+ preempt_scan(struct net_device *dev, int max_grace, int max_wait)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ int total_delay = 0;
+ int canceled = 0, ready = 0;
+@@ -122,7 +122,7 @@ preempt_scan(struct net_device *dev, int
+ static struct iw_statistics *
+ ieee80211_iw_getstats(struct net_device *dev)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct iw_statistics *is = &vap->iv_iwstats;
+ struct ieee80211com *ic = vap->iv_ic;
+
+@@ -146,7 +146,7 @@ static int
+ ieee80211_ioctl_giwname(struct net_device *dev, struct iw_request_info *info,
+ char *name, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211_channel *c = vap->iv_ic->ic_curchan;
+
+ if (IEEE80211_IS_CHAN_108G(c))
+@@ -198,7 +198,7 @@ static int
+ ieee80211_ioctl_siwencode(struct net_device *dev,
+ struct iw_request_info *info, struct iw_point *erq, char *keybuf)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ int error;
+ int wepchange = 0;
+ ieee80211_keyix_t kix;
+@@ -306,7 +306,7 @@ static int
+ ieee80211_ioctl_giwencode(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *erq, char *key)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211_key *k;
+ int error;
+ ieee80211_keyix_t kix;
+@@ -351,7 +351,7 @@ ieee80211_ioctl_siwrate(struct net_devic
+ IFM_IEEE80211_11A | IFM_IEEE80211_TURBO,
+ IFM_IEEE80211_11G | IFM_IEEE80211_TURBO,
+ };
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ifreq ifr;
+ int rate, retv;
+@@ -386,7 +386,7 @@ static int
+ ieee80211_ioctl_giwrate(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ifmediareq imr;
+ int rate;
+
+@@ -424,7 +424,7 @@ static int
+ ieee80211_ioctl_siwrts(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ u16 val;
+
+@@ -447,7 +447,7 @@ static int
+ ieee80211_ioctl_giwrts(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ rts->value = vap->iv_rtsthreshold;
+ rts->disabled = (rts->value == IEEE80211_RTS_MAX);
+@@ -460,7 +460,7 @@ static int
+ ieee80211_ioctl_siwfrag(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ u16 val;
+
+@@ -483,7 +483,7 @@ static int
+ ieee80211_ioctl_giwfrag(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ rts->value = vap->iv_fragthreshold;
+ rts->disabled = (rts->value == 2346);
+@@ -496,7 +496,7 @@ static int
+ ieee80211_ioctl_siwap(struct net_device *dev, struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ /* NB: should not be set when in AP mode */
+ if (vap->iv_opmode == IEEE80211_M_HOSTAP)
+@@ -532,7 +532,7 @@ static int
+ ieee80211_ioctl_giwap(struct net_device *dev, struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ if (vap->iv_flags & IEEE80211_F_DESBSSID)
+ IEEE80211_ADDR_COPY(&ap_addr->sa_data, vap->iv_des_bssid);
+@@ -553,7 +553,7 @@ static int
+ ieee80211_ioctl_siwnickn(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *nickname)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ if (data->length > IEEE80211_NWID_LEN)
+ return -E2BIG;
+@@ -569,7 +569,7 @@ static int
+ ieee80211_ioctl_giwnickn(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *nickname)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ if (data->length > vap->iv_nicknamelen + 1)
+ data->length = vap->iv_nicknamelen + 1;
+@@ -678,7 +678,7 @@ static int
+ ieee80211_ioctl_siwfreq(struct net_device *dev, struct iw_request_info *info,
+ struct iw_freq *freq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_channel *c, *c2;
+ int i;
+@@ -767,7 +767,7 @@ static int
+ ieee80211_ioctl_giwfreq(struct net_device *dev, struct iw_request_info *info,
+ struct iw_freq *freq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+
+ if (vap->iv_state == IEEE80211_S_RUN &&
+@@ -808,7 +808,7 @@ static int
+ ieee80211_ioctl_siwessid(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *ssid)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ if (vap->iv_opmode == IEEE80211_M_WDS)
+ return -EOPNOTSUPP;
+@@ -853,7 +853,7 @@ static int
+ ieee80211_ioctl_giwessid(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *essid)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ if (vap->iv_opmode == IEEE80211_M_WDS)
+ return -EOPNOTSUPP;
+@@ -899,7 +899,7 @@ static int
+ ieee80211_ioctl_giwrange(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_node *ni = vap->iv_bss;
+ struct iw_range *range = (struct iw_range *) extra;
+@@ -1047,7 +1047,7 @@ ieee80211_ioctl_setspy(struct net_device
+ struct iw_point *data, char *extra)
+ {
+ /* save the list of node addresses */
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct sockaddr address[IW_MAX_SPY];
+ unsigned int number = data->length;
+ int i;
+@@ -1085,7 +1085,7 @@ ieee80211_ioctl_getspy(struct net_device
+ * locate nodes by mac (ieee80211_find_node()),
+ * copy out rssi, set updated flag appropriately
+ */
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211_node_table *nt = &vap->iv_ic->ic_sta;
+ struct ieee80211_node *ni;
+ struct ieee80211com *ic = vap->iv_ic;
+@@ -1133,7 +1133,7 @@ static int
+ ieee80211_ioctl_setthrspy(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct iw_thrspy threshold;
+
+ if (data->length != 1)
+@@ -1170,7 +1170,7 @@ static int
+ ieee80211_ioctl_getthrspy(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct iw_thrspy *threshold;
+
+@@ -1191,7 +1191,7 @@ static int
+ ieee80211_ioctl_siwmode(struct net_device *dev, struct iw_request_info *info,
+ __u32 *mode, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ifmediareq imr;
+ int valid = 0;
+
+@@ -1216,7 +1216,7 @@ static int
+ ieee80211_ioctl_giwmode(struct net_device *dev, struct iw_request_info *info,
+ __u32 *mode, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ifmediareq imr;
+
+ memset(&imr, 0, sizeof(imr));
+@@ -1239,7 +1239,7 @@ static int
+ ieee80211_ioctl_siwpower(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *wrq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+
+ /* XXX: These values, flags, and caps do not seem to be used elsewhere
+@@ -1278,7 +1278,7 @@ static int
+ ieee80211_ioctl_giwpower(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+
+ rrq->disabled = (ic->ic_flags & IEEE80211_F_PMGTON) == 0;
+@@ -1302,7 +1302,7 @@ static int
+ ieee80211_ioctl_siwretry(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+
+ if (rrq->disabled) {
+@@ -1334,7 +1334,7 @@ static int
+ ieee80211_ioctl_giwretry(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ rrq->disabled = (vap->iv_flags & IEEE80211_F_SWRETRY) == 0;
+ if (!rrq->disabled) {
+@@ -1365,7 +1365,7 @@ static int
+ ieee80211_ioctl_siwtxpow(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ int fixed, disabled;
+
+@@ -1402,7 +1402,7 @@ ieee80211_get_txcont(struct net_device *
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ params[0] = ic->ic_get_txcont(ic);
+ return 0;
+@@ -1413,7 +1413,7 @@ ieee80211_get_dfs_cac_time(struct net_de
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ params[0] = ic->ic_get_dfs_cac_time(ic);
+ return 0;
+@@ -1424,7 +1424,7 @@ ieee80211_get_dfs_excl_period(struct net
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ params[0] = ic->ic_get_dfs_excl_period(ic);
+ return 0;
+@@ -1434,7 +1434,7 @@ ieee80211_set_dfs_cac_time(struct net_de
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ ic->ic_set_dfs_cac_time(ic, params[1]);
+ return 0;
+@@ -1444,7 +1444,7 @@ ieee80211_set_dfs_excl_period (struct n
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ ic->ic_set_dfs_excl_period(ic, params[1]);
+ return 0;
+@@ -1455,7 +1455,7 @@ ieee80211_get_dfs_testmode(struct net_de
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ params[0] = ic->ic_get_dfs_testmode(ic);
+ return 0;
+@@ -1466,7 +1466,7 @@ ieee80211_get_txcont_rate(struct net_dev
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ params[0] = ic->ic_get_txcont_rate(ic);
+ return 0;
+@@ -1477,7 +1477,7 @@ ieee80211_set_txcont(struct net_device *
+ void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ ic->ic_set_txcont(ic, params[1]);
+ return 0;
+@@ -1488,7 +1488,7 @@ ieee80211_set_dfs_testmode(struct net_de
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ ic->ic_set_dfs_testmode(ic, params[1]);
+ return 0;
+@@ -1499,7 +1499,7 @@ ieee80211_set_txcont_rate(struct net_dev
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ ic->ic_set_txcont_rate(ic, params[1]);
+ return 0;
+@@ -1510,7 +1510,7 @@ ieee80211_set_txcont_power(struct net_de
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ ic->ic_set_txcont_power(ic, params[1]);
+ return 0;
+@@ -1521,7 +1521,7 @@ ieee80211_get_txcont_power(struct net_de
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ params[0] = ic->ic_get_txcont_power(ic);
+ return 0;
+@@ -1533,7 +1533,7 @@ ieee80211_ioctl_hal_map(struct net_devic
+ void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ params[0] = ic->ic_dump_hal_map(ic);
+ return 0;
+@@ -1545,7 +1545,7 @@ ieee80211_ioctl_radar(struct net_device
+ void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ if (!(ic->ic_flags & IEEE80211_F_DOTH))
+ return 0;
+@@ -1557,7 +1557,7 @@ static int
+ ieee80211_ioctl_giwtxpow(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ unsigned int power = ic->ic_txpowlimit;
+ struct ieee80211_channel *c;
+@@ -1581,7 +1581,7 @@ static int
+ ieee80211_dump_registers(struct net_device *dev, struct iw_request_info *info, void *w, char *extra)
+ {
+ unsigned int *params = (unsigned int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ switch (params[1]) {
+ case 2:
+@@ -1604,7 +1604,7 @@ static int
+ ieee80211_ioctl_writereg(struct net_device *dev, struct iw_request_info *info, void *w, char *extra)
+ {
+ unsigned int *params = (unsigned int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ return ic->ic_write_register(ic, params[0], params[1]);
+ }
+@@ -1615,7 +1615,7 @@ static int
+ ieee80211_ioctl_readreg(struct net_device *dev, struct iw_request_info *info, void *w, char *extra)
+ {
+ unsigned int *params = (unsigned int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ return ic->ic_read_register(ic, params[0], &params[0]);
+ }
+@@ -1651,7 +1651,7 @@ static int
+ ieee80211_ioctl_iwaplist(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct waplistreq req; /* XXX off stack */
+
+@@ -1673,7 +1673,7 @@ static int
+ ieee80211_ioctl_siwscan(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ /*
+ * XXX don't permit a scan to be started unless we
+@@ -1997,7 +1997,7 @@ static int
+ ieee80211_ioctl_giwscan(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct iwscanreq req;
+ int res = 0;
+@@ -2098,7 +2098,7 @@ static int
+ ieee80211_ioctl_setmode(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *wri, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ifreq ifr;
+ char s[6]; /* big enough for ``11adt'' */
+@@ -2222,10 +2222,10 @@ ieee80211_setathcap(struct ieee80211vap
+ static int
+ ieee80211_set_turbo(struct net_device *dev, int flag)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ifreq ifr;
+- struct ieee80211vap *tmpvap = dev->priv;
++ struct ieee80211vap *tmpvap = netdev_priv(dev);
+ int nvap = 0;
+
+ TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next)
+@@ -2246,7 +2246,7 @@ static int
+ ieee80211_ioctl_setparam(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_rsnparms *rsn = &vap->iv_bss->ni_rsn;
+ unsigned int *i = (unsigned int *) extra;
+@@ -2926,7 +2926,7 @@ static int
+ ieee80211_ioctl_getmode(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *wri, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ifmediareq imr;
+
+@@ -2964,7 +2964,7 @@ static int
+ ieee80211_ioctl_getparam(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_rsnparms *rsn = &vap->iv_bss->ni_rsn;
+ unsigned int *param = (unsigned int *) extra;
+@@ -3309,7 +3309,7 @@ static int
+ ieee80211_ioctl_setoptie(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *wri, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ void *ie;
+
+ /*
+@@ -3343,7 +3343,7 @@ static int
+ ieee80211_ioctl_getoptie(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *wri, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ if (vap->iv_opt_ie == NULL) {
+ wri->length = 0;
+@@ -3407,7 +3407,7 @@ ieee80211_ioctl_setappiebuf(struct net_d
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211req_getset_appiebuf *iebuf =
+ (struct ieee80211req_getset_appiebuf *)extra;
+ enum ieee80211_opmode chk_opmode;
+@@ -3449,7 +3449,7 @@ static int
+ ieee80211_ioctl_getappiebuf(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211req_getset_appiebuf *iebuf =
+ (struct ieee80211req_getset_appiebuf *)extra;
+ int max_iebuf_len;
+@@ -3490,7 +3490,7 @@ static int
+ ieee80211_ioctl_setfilter(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211req_set_filter *app_filter = (struct ieee80211req_set_filter *)extra;
+
+ if ((extra == NULL) || (app_filter->app_filterype & ~IEEE80211_FILTER_TYPE_ALL))
+@@ -3505,7 +3505,7 @@ static int
+ ieee80211_ioctl_setkey(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211req_key *ik = (struct ieee80211req_key *)extra;
+ struct ieee80211_node *ni;
+@@ -3588,7 +3588,7 @@ ieee80211_ioctl_setkey(struct net_device
+ static int
+ ieee80211_ioctl_getkey(struct net_device *dev, struct iwreq *iwr)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_node *ni;
+ struct ieee80211req_key ik;
+@@ -3649,7 +3649,7 @@ static int
+ ieee80211_ioctl_delkey(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211req_del_key *dk = (struct ieee80211req_del_key *)extra;
+ ieee80211_keyix_t kix;
+@@ -3723,7 +3723,7 @@ static int
+ ieee80211_ioctl_setmlme(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211req_mlme *mlme = (struct ieee80211req_mlme *)extra;
+ struct ieee80211_node *ni;
+@@ -3826,7 +3826,7 @@ static int
+ ieee80211_ioctl_wdsaddmac(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct sockaddr *sa = (struct sockaddr *)extra;
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211vap *avp;
+@@ -3855,7 +3855,7 @@ static int
+ ieee80211_ioctl_wdssetmac(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct sockaddr *sa = (struct sockaddr *)extra;
+
+ if (vap->iv_opmode != IEEE80211_M_WDS)
+@@ -3922,7 +3922,7 @@ ieee80211_ioctl_setscanlist(struct net_d
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ char *s, *next;
+ int val = 1;
+@@ -3997,7 +3997,7 @@ static int
+ ieee80211_ioctl_addmac(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct sockaddr *sa = (struct sockaddr *)extra;
+ const struct ieee80211_aclator *acl = vap->iv_acl;
+
+@@ -4015,7 +4015,7 @@ static int
+ ieee80211_ioctl_delmac(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct sockaddr *sa = (struct sockaddr *)extra;
+ const struct ieee80211_aclator *acl = vap->iv_acl;
+
+@@ -4033,7 +4033,7 @@ static int
+ ieee80211_ioctl_setchanlist(struct net_device *dev,
+ struct iw_request_info *info, void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211req_chanlist *list =
+ (struct ieee80211req_chanlist *)extra;
+@@ -4084,7 +4084,7 @@ static int
+ ieee80211_ioctl_getchanlist(struct net_device *dev,
+ struct iw_request_info *info, void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+
+ memcpy(extra, ic->ic_chan_active, sizeof(ic->ic_chan_active));
+@@ -4105,7 +4105,7 @@ static int
+ ieee80211_ioctl_getchaninfo(struct net_device *dev,
+ struct iw_request_info *info, void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211req_chaninfo *chans =
+ (struct ieee80211req_chaninfo *)extra;
+@@ -4152,7 +4152,7 @@ static int
+ ieee80211_ioctl_setwmmparams(struct net_device *dev,
+ struct iw_request_info *info, void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ unsigned int *param = (unsigned int *) extra;
+ unsigned int ac = (param[1] < WME_NUM_AC) ? param[1] : WME_AC_BE;
+ unsigned int bss = param[2];
+@@ -4240,7 +4240,7 @@ static int
+ ieee80211_ioctl_getwmmparams(struct net_device *dev,
+ struct iw_request_info *info, void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ unsigned int *param = (unsigned int *) extra;
+ unsigned int ac = (param[1] < WME_NUM_AC) ? param[1] : WME_AC_BE;
+ struct ieee80211_wme_state *wme = &vap->iv_ic->ic_wme;
+@@ -4275,7 +4275,7 @@ ieee80211_ioctl_getwmmparams(struct net_
+ static int
+ ieee80211_ioctl_getwpaie(struct net_device *dev, struct iwreq *iwr)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_node *ni;
+ struct ieee80211req_wpaie wpaie;
+@@ -4309,7 +4309,7 @@ ieee80211_ioctl_getwpaie(struct net_devi
+ static int
+ ieee80211_ioctl_getstastats(struct net_device *dev, struct iwreq *iwr)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_node *ni;
+ u_int8_t macaddr[IEEE80211_ADDR_LEN];
+@@ -4428,7 +4428,7 @@ get_scan_result(void *arg, const struct
+ static int
+ ieee80211_ioctl_getscanresults(struct net_device *dev, struct iwreq *iwr)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct scanreq req;
+ int error;
+@@ -4591,7 +4591,7 @@ get_sta_info(void *arg, struct ieee80211
+ static int
+ ieee80211_ioctl_getstainfo(struct net_device *dev, struct iwreq *iwr)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct stainforeq req;
+ int error;
+@@ -4625,7 +4625,7 @@ ieee80211_ioctl_getstainfo(struct net_de
+
+ static void
+ pre_announced_chanswitch(struct net_device *dev, u_int32_t channel, u_int32_t tbtt) {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211vap *avp;
+
+@@ -4643,7 +4643,7 @@ static int
+ ieee80211_ioctl_chanswitch(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ unsigned int *param = (unsigned int *) extra;
+
+@@ -4688,7 +4688,7 @@ static int
+ ieee80211_ioctl_giwgenie(struct net_device *dev,
+ struct iw_request_info *info, struct iw_point *out, char *buf)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ if (out->length < vap->iv_opt_ie_len)
+ return -E2BIG;
+@@ -5221,7 +5221,7 @@ static int
+ ieee80211_ioctl_giwencodeext(struct net_device *dev,
+ struct iw_request_info *info, struct iw_point *erq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct iw_encode_ext *ext;
+ struct ieee80211_key *wk;
+ ieee80211_keyix_t kix;
+@@ -5281,7 +5281,7 @@ static int
+ ieee80211_ioctl_siwencodeext(struct net_device *dev,
+ struct iw_request_info *info, struct iw_point *erq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ struct ieee80211req_key kr;
+ ieee80211_keyix_t kix;
+@@ -5957,7 +5957,7 @@ static struct iw_handler_def ieee80211_i
+ static int
+ ieee80211_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_node *ni;
+
diff --git a/package/madwifi/patches/431-compile_fixes.patch b/package/madwifi/patches/431-compile_fixes.patch
new file mode 100644
index 000000000..b11d406a0
--- /dev/null
+++ b/package/madwifi/patches/431-compile_fixes.patch
@@ -0,0 +1,35 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -2388,7 +2388,9 @@ ath_intr(int irq, void *dev_id, struct p
+ if (status & (HAL_INT_RX | HAL_INT_RXPHY)) {
+ ath_uapsd_processtriggers(sc, hw_tsf);
+ sc->sc_isr &= ~HAL_INT_RX;
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
++ if (napi_schedule_prep(&sc->sc_napi))
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ if (netif_rx_schedule_prep(dev, &sc->sc_napi))
+ #else
+ if (netif_rx_schedule_prep(dev))
+@@ -2396,7 +2398,9 @@ ath_intr(int irq, void *dev_id, struct p
+ {
+ sc->sc_imask &= ~HAL_INT_RX;
+ ath_hal_intrset(ah, sc->sc_imask);
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
++ __napi_schedule(&sc->sc_napi);
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ __netif_rx_schedule(dev, &sc->sc_napi);
+ #else
+ __netif_rx_schedule(dev);
+@@ -7135,7 +7139,9 @@ rx_next:
+ local_irq_restore(flags);
+ }
+
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
++ napi_complete(napi);
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ netif_rx_complete(dev, napi);
+ #else
+ netif_rx_complete(dev);
diff --git a/package/madwifi/patches/432-netdev_ops.patch b/package/madwifi/patches/432-netdev_ops.patch
new file mode 100644
index 000000000..af829b164
--- /dev/null
+++ b/package/madwifi/patches/432-netdev_ops.patch
@@ -0,0 +1,184 @@
+Convert to net_device_ops for Linux 2.6.29+
+http://madwifi-project.org/changeset/4005
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -566,6 +566,20 @@ static inline int rate_factor(int mode)
+
+ /* Initialize ath_softc structure */
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
++static const struct net_device_ops ath_netdev_ops = {
++ .ndo_open = ath_init,
++ .ndo_stop = ath_stop,
++ .ndo_start_xmit = ath_hardstart,
++ .ndo_tx_timeout = ath_tx_timeout,
++ .ndo_set_multicast_list = ath_mode_init,
++ .ndo_do_ioctl = ath_ioctl,
++ .ndo_get_stats = ath_getstats,
++ .ndo_set_mac_address = ath_set_mac_address,
++ .ndo_change_mtu = ath_change_mtu,
++};
++#endif
++
+ int
+ ath_attach(u_int16_t devid, struct net_device *dev, HAL_BUS_TAG tag)
+ {
+@@ -865,16 +879,20 @@ ath_attach(u_int16_t devid, struct net_d
+ }
+
+ /* NB: ether_setup is done by bus-specific code */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
+ dev->open = ath_init;
+ dev->stop = ath_stop;
+ dev->hard_start_xmit = ath_hardstart;
+ dev->tx_timeout = ath_tx_timeout;
+- dev->watchdog_timeo = 5 * HZ;
+ dev->set_multicast_list = ath_mode_init;
+ dev->do_ioctl = ath_ioctl;
+ dev->get_stats = ath_getstats;
+ dev->set_mac_address = ath_set_mac_address;
+ dev->change_mtu = ath_change_mtu;
++#else
++ dev->netdev_ops = &ath_netdev_ops;
++#endif
++ dev->watchdog_timeo = 5 * HZ;
+ 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);
+@@ -1257,7 +1275,6 @@ ath_detach(struct net_device *dev)
+ ath_dynamic_sysctl_unregister(sc);
+ ATH_LOCK_DESTROY(sc);
+ ATH_HAL_LOCK_DESTROY(sc);
+- dev->stop = NULL; /* prevent calling ath_stop again */
+ unregister_netdev(dev);
+ return 0;
+ }
+@@ -12732,8 +12749,13 @@ ath_rcv_dev_event(struct notifier_block
+ struct net_device *dev = (struct net_device *)ptr;
+ struct ath_softc *sc = (struct ath_softc *)netdev_priv(dev);
+
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
+ if (!dev || !sc || dev->open != &ath_init)
+ return 0;
++#else
++ if (!dev || !sc || dev->netdev_ops->ndo_open != &ath_init)
++ return 0;
++#endif
+
+ switch (event) {
+ case NETDEV_CHANGENAME:
+--- a/net80211/ieee80211.c
++++ b/net80211/ieee80211.c
+@@ -451,6 +451,18 @@ ieee80211_ifdetach(struct ieee80211com *
+ }
+ EXPORT_SYMBOL(ieee80211_ifdetach);
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
++static const struct net_device_ops ieee80211_netdev_ops = {
++ .ndo_get_stats = ieee80211_getstats,
++ .ndo_open = ieee80211_open,
++ .ndo_stop = ieee80211_stop,
++ .ndo_start_xmit = ieee80211_hardstart,
++ .ndo_set_multicast_list = ieee80211_set_multicast_list,
++ .ndo_change_mtu = ieee80211_change_mtu,
++ .ndo_do_ioctl = ieee80211_ioctl,
++};
++#endif
++
+ int
+ ieee80211_vap_setup(struct ieee80211com *ic, struct net_device *dev,
+ const char *name, int opmode, int flags, struct ieee80211vap *master)
+@@ -471,16 +483,21 @@ ieee80211_vap_setup(struct ieee80211com
+ } else
+ strncpy(dev->name, name, sizeof(dev->name));
+ }
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
+
+ dev->get_stats = ieee80211_getstats;
+ dev->open = ieee80211_open;
+ dev->stop = ieee80211_stop;
+ dev->hard_start_xmit = ieee80211_hardstart;
+ dev->set_multicast_list = ieee80211_set_multicast_list;
++ dev->do_ioctl = ieee80211_ioctl;
+ #if 0
+ dev->set_mac_address = ieee80211_set_mac_address;
+ #endif
+ dev->change_mtu = ieee80211_change_mtu;
++#else
++ dev->netdev_ops = &ieee80211_netdev_ops;
++#endif
+ dev->tx_queue_len = 0; /* NB: bypass queuing */
+ dev->hard_header_len = parent->hard_header_len;
+ /*
+@@ -1824,7 +1841,11 @@ ieee80211_set_multicast_list(struct net_
+ IEEE80211_UNLOCK_IRQ(ic);
+
+ /* XXX: Merge multicast list into parent device */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
+ parent->set_multicast_list(ic->ic_dev);
++#else
++ parent->netdev_ops->ndo_set_multicast_list(ic->ic_dev);
++#endif
+ }
+
+ void
+--- a/net80211/ieee80211_linux.c
++++ b/net80211/ieee80211_linux.c
+@@ -984,8 +984,14 @@ ieee80211_rcv_dev_event(struct notifier_
+ void *ptr)
+ {
+ struct net_device *dev = (struct net_device *) ptr;
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
+ if (!dev || dev->open != &ieee80211_open)
+ return 0;
++#else
++ if (!dev || dev->netdev_ops->ndo_open != &ieee80211_open)
++ return 0;
++#endif
+
+ switch (event) {
+ case NETDEV_CHANGENAME:
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -739,6 +739,7 @@ void ieee80211_build_sc_ie(struct ieee80
+ void ieee80211_dfs_action(struct ieee80211com *);
+ void ieee80211_expire_channel_excl_restrictions(struct ieee80211com *);
+ void ieee80211_setpuregbasicrates(struct ieee80211_rateset *rs);
++int ieee80211_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+
+ /*
+ * Iterate through ic_channels to enumerate all distinct ic_ieee channel numbers.
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -5954,7 +5954,7 @@ static struct iw_handler_def ieee80211_i
+ /*
+ * Handle private ioctl requests.
+ */
+-static int
++int
+ ieee80211_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ {
+ struct ieee80211vap *vap = netdev_priv(dev);
+@@ -6044,7 +6044,6 @@ ieee80211_ioctl_vattach(struct ieee80211
+ {
+ struct net_device *dev = vap->iv_dev;
+
+- dev->do_ioctl = ieee80211_ioctl;
+ #if IW_HANDLER_VERSION < 7
+ dev->get_wireless_stats = ieee80211_iw_getstats;
+ #endif
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -1188,7 +1188,11 @@ ieee80211_deliver_data(struct ieee80211_
+ skb1->protocol = __constant_htons(ETH_P_802_2);
+ /* XXX insert vlan tag before queue it? */
+ ni_tmp = SKB_CB(skb1)->ni; /* remember node so we can free it */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
+ ret = dev->hard_start_xmit(skb1, dev);
++#else
++ ret = dev->netdev_ops->ndo_start_xmit(skb1, dev);
++#endif
+
+ if (ret == NETDEV_TX_BUSY)
+ ieee80211_dev_kfree_skb(&skb1);
diff --git a/package/madwifi/patches/433-backport_remove_irq_none.patch b/package/madwifi/patches/433-backport_remove_irq_none.patch
new file mode 100644
index 000000000..5166d9e10
--- /dev/null
+++ b/package/madwifi/patches/433-backport_remove_irq_none.patch
@@ -0,0 +1,21 @@
+Fix Linux 2.6.30 compatibility
+
+Linux 2.6.30 doesn't define IRQ_NONE as a macro. Assume irqreturn_t,
+IRQ_NONE and IRQ_HANDLED to be present on Linux 2.6.29 and newer.
+http://madwifi-project.org/changeset/3986
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -83,11 +83,13 @@ typedef void *TQUEUE_ARG;
+ /*
+ * Guess how the interrupt handler should work.
+ */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
+ #if !defined(IRQ_NONE)
+ typedef void irqreturn_t;
+ #define IRQ_NONE
+ #define IRQ_HANDLED
+ #endif /* !defined(IRQ_NONE) */
++#endif /* Linux < 2.6.29 */
+
+ #ifndef SET_MODULE_OWNER
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
diff --git a/package/madwifi/patches/434-name-alloc-fix.patch b/package/madwifi/patches/434-name-alloc-fix.patch
new file mode 100644
index 000000000..ab277630d
--- /dev/null
+++ b/package/madwifi/patches/434-name-alloc-fix.patch
@@ -0,0 +1,28 @@
+--- a/ath/if_ath_ahb.c
++++ b/ath/if_ath_ahb.c
+@@ -311,6 +311,11 @@ init_ath_wmac(u_int16_t devid, u_int16_t
+ SET_MODULE_OWNER(dev);
+ sclist[wlanNum] = sc;
+
++ if (dev_alloc_name(dev, dev->name) < 0) {
++ printk(KERN_ERR "%s: cannot allocate name\n", dev_info);
++ goto bad3;
++ }
++
+ switch (wlanNum) {
+ case AR531X_WLAN0_NUM:
+ if (((devid & AR5315_REV_MAJ_M) == AR5315_REV_MAJ) ||
+--- a/ath/if_ath_pci.c
++++ b/ath/if_ath_pci.c
+@@ -236,6 +236,11 @@ ath_pci_probe(struct pci_dev *pdev, cons
+ */
+ sc->aps_sc.sc_invalid = 1;
+
++ if (dev_alloc_name(dev, dev->name) < 0) {
++ printk(KERN_ERR "%s: cannot allocate name\n", dev_info);
++ goto bad3;
++ }
++
+ dev->irq = pdev->irq;
+
+ SET_MODULE_OWNER(dev);
diff --git a/package/madwifi/patches/435-ibss_neighbor_fix.patch b/package/madwifi/patches/435-ibss_neighbor_fix.patch
new file mode 100644
index 000000000..d66af9b24
--- /dev/null
+++ b/package/madwifi/patches/435-ibss_neighbor_fix.patch
@@ -0,0 +1,11 @@
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -313,7 +313,7 @@ ieee80211_input(struct ieee80211vap * va
+ if (type == IEEE80211_FC0_TYPE_DATA && ni == vap->iv_bss &&
+ !IEEE80211_ADDR_EQ(vap->iv_bss->ni_macaddr, wh->i_addr2)) {
+ /* Try to find sender in local node table. */
+- ni = ieee80211_find_node(vap->iv_bss->ni_table, wh->i_addr2);
++ ni = ieee80211_find_node(&ic->ic_sta, wh->i_addr2);
+ if (ni == NULL) {
+ /*
+ * Fake up a node for this newly discovered
diff --git a/package/madwifi/patches/436-injection_checks.patch b/package/madwifi/patches/436-injection_checks.patch
new file mode 100644
index 000000000..274873111
--- /dev/null
+++ b/package/madwifi/patches/436-injection_checks.patch
@@ -0,0 +1,26 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -3199,7 +3199,13 @@ ath_tx_startraw(struct net_device *dev,
+ struct ieee80211_frame *wh;
+
+ wh = (struct ieee80211_frame *)skb->data;
++
+ try0 = ph->try0;
++ if (!try0)
++ try0 = 1;
++ else if (try0 > 11)
++ try0 = 11;
++
+ rt = sc->sc_currates;
+ txrate = dot11_to_ratecode(sc, rt, ph->rate0);
+ power = ph->power > 63 ? 63 : ph->power;
+@@ -3224,7 +3230,8 @@ ath_tx_startraw(struct net_device *dev,
+ rt = sc->sc_currates;
+ KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
+
+- if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
++ if (((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA) ||
++ IEEE80211_IS_MULTICAST(wh->i_addr1)) {
+ flags |= HAL_TXDESC_NOACK; /* no ack on broad/multicast */
+ sc->sc_stats.ast_tx_noack++;
+ try0 = 1;
diff --git a/package/madwifi/patches/437-sysctl_cleanup.patch b/package/madwifi/patches/437-sysctl_cleanup.patch
new file mode 100644
index 000000000..e35ed0293
--- /dev/null
+++ b/package/madwifi/patches/437-sysctl_cleanup.patch
@@ -0,0 +1,73 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -11021,38 +11021,38 @@ enum {
+ * mirrored in /proc/sys.
+ */
+ enum {
+- ATH_SLOTTIME = 1,
+- ATH_ACKTIMEOUT = 2,
+- ATH_CTSTIMEOUT = 3,
+- ATH_SOFTLED = 4,
+- ATH_LEDPIN = 5,
+- ATH_COUNTRYCODE = 6,
+- ATH_REGDOMAIN = 7,
+- ATH_DEBUG = 8,
+- ATH_TXANTENNA = 9,
+- ATH_RXANTENNA = 10,
+- ATH_DIVERSITY = 11,
+- ATH_TXINTRPERIOD = 12,
+- ATH_FFTXQMIN = 13,
+- ATH_XR_POLL_PERIOD = 14,
+- ATH_XR_POLL_COUNT = 15,
+- ATH_ACKRATE = 16,
+- ATH_RP = 17,
+- ATH_RP_PRINT = 18,
+- ATH_RP_PRINT_ALL = 19,
+- ATH_RP_PRINT_MEM = 20,
+- ATH_RP_PRINT_MEM_ALL = 21,
+- ATH_RP_FLUSH = 22,
+- ATH_PANIC = 23,
+- ATH_RP_IGNORED = 24,
+- ATH_RADAR_IGNORED = 25,
+- ATH_MAXVAPS = 26,
+- ATH_INTMIT = 27,
+- ATH_NOISE_IMMUNITY = 28,
+- ATH_OFDM_WEAK_DET = 29,
+- ATH_CHANBW = 30,
+- ATH_OUTDOOR = 31,
+- ATH_DISTANCE = 32,
++ ATH_SLOTTIME,
++ ATH_ACKTIMEOUT,
++ ATH_CTSTIMEOUT,
++ ATH_SOFTLED,
++ ATH_LEDPIN,
++ ATH_COUNTRYCODE,
++ ATH_REGDOMAIN,
++ ATH_DEBUG,
++ ATH_TXANTENNA,
++ ATH_RXANTENNA,
++ ATH_DIVERSITY,
++ ATH_TXINTRPERIOD,
++ ATH_FFTXQMIN,
++ ATH_XR_POLL_PERIOD,
++ ATH_XR_POLL_COUNT,
++ ATH_ACKRATE,
++ ATH_RP,
++ ATH_RP_PRINT,
++ ATH_RP_PRINT_ALL,
++ ATH_RP_PRINT_MEM,
++ ATH_RP_PRINT_MEM_ALL,
++ ATH_RP_FLUSH,
++ ATH_PANIC,
++ ATH_RP_IGNORED,
++ ATH_RADAR_IGNORED,
++ ATH_MAXVAPS,
++ ATH_INTMIT,
++ ATH_NOISE_IMMUNITY,
++ ATH_OFDM_WEAK_DET,
++ ATH_CHANBW,
++ ATH_OUTDOOR,
++ ATH_DISTANCE,
+ };
+
+ /*
diff --git a/package/madwifi/patches/438-poweroffset_sysctl.patch b/package/madwifi/patches/438-poweroffset_sysctl.patch
new file mode 100644
index 000000000..e82046ec6
--- /dev/null
+++ b/package/madwifi/patches/438-poweroffset_sysctl.patch
@@ -0,0 +1,59 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -10476,11 +10476,11 @@ set_node_txpower(void *arg, struct ieee8
+ * XXX: this function needs some locking to avoid being called
+ * twice/interrupted. Returns the value actually stored. */
+ static u_int32_t
+-ath_set_clamped_maxtxpower(struct ath_softc *sc,
+- u_int32_t new_clamped_maxtxpower)
++ath_set_clamped_maxtxpower(struct ath_softc *sc, u_int32_t new_txpwr)
+ {
+- new_clamped_maxtxpower -= sc->sc_poweroffset;
+- (void)ath_hal_settxpowlimit(sc->sc_ah, new_clamped_maxtxpower);
++ new_txpwr = ((new_txpwr < sc->sc_poweroffset) ? 0 :
++ new_txpwr - sc->sc_poweroffset);
++ (void)ath_hal_settxpowlimit(sc->sc_ah, new_txpwr);
+ return ath_get_clamped_maxtxpower(sc);
+ }
+
+@@ -11031,6 +11031,7 @@ enum {
+ ATH_DEBUG,
+ ATH_TXANTENNA,
+ ATH_RXANTENNA,
++ ATH_POWEROFFSET,
+ ATH_DIVERSITY,
+ ATH_TXINTRPERIOD,
+ ATH_FFTXQMIN,
+@@ -11311,6 +11312,9 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+ ath_debug_global = (val & ATH_DEBUG_GLOBAL);
+ #endif
+ break;
++ case ATH_POWEROFFSET:
++ sc->sc_poweroffset = val;
++ break;
+ case ATH_TXANTENNA:
+ /*
+ * antenna can be:
+@@ -11478,6 +11482,9 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+ case ATH_DEBUG:
+ val = sc->sc_debug | ath_debug_global;
+ break;
++ case ATH_POWEROFFSET:
++ val = sc->sc_poweroffset;
++ break;
+ case ATH_TXANTENNA:
+ val = sc->sc_txantenna;
+ break;
+@@ -11619,6 +11626,12 @@ static const ctl_table ath_sysctl_templa
+ },
+ #endif
+ { .ctl_name = CTL_AUTO,
++ .procname = "poweroffset",
++ .mode = 0644,
++ .proc_handler = ath_sysctl_halparam,
++ .extra2 = (void *)ATH_POWEROFFSET,
++ },
++ { .ctl_name = CTL_AUTO,
+ .procname = "txantenna",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
diff --git a/package/madwifi/patches/439-wlanconfig_stack_usage.patch b/package/madwifi/patches/439-wlanconfig_stack_usage.patch
new file mode 100644
index 000000000..f346143c3
--- /dev/null
+++ b/package/madwifi/patches/439-wlanconfig_stack_usage.patch
@@ -0,0 +1,20 @@
+--- a/tools/wlanconfig.c
++++ b/tools/wlanconfig.c
+@@ -560,7 +560,7 @@ ieee80211_ntoa(const uint8_t mac[IEEE802
+ static void
+ list_stations(const char *ifname)
+ {
+- uint8_t buf[24*1024];
++ static uint8_t buf[24*1024];
+ struct iwreq iwr;
+ uint8_t *cp;
+ int s, len;
+@@ -653,7 +653,7 @@ list_stations(const char *ifname)
+ static void
+ list_scan(const char *ifname)
+ {
+- uint8_t buf[24 * 1024];
++ static uint8_t buf[24 * 1024];
+ char ssid[14];
+ uint8_t *cp;
+ int len;
diff --git a/package/madwifi/patches/440-wme_cleanup.patch b/package/madwifi/patches/440-wme_cleanup.patch
new file mode 100644
index 000000000..bb81ac7f8
--- /dev/null
+++ b/package/madwifi/patches/440-wme_cleanup.patch
@@ -0,0 +1,136 @@
+--- a/net80211/ieee80211_output.c
++++ b/net80211/ieee80211_output.c
+@@ -73,6 +73,29 @@ doprint(struct ieee80211vap *vap, int su
+ }
+ #endif
+
++static const int ieee802_1d_to_ac[8] = {
++ WME_AC_BE, WME_AC_BK, WME_AC_BK, WME_AC_BE,
++ WME_AC_VI, WME_AC_VI, WME_AC_VO, WME_AC_VO
++};
++
++/* Given a data frame determine the 802.1p/1d tag to use. */
++static unsigned int ieee80211_classify_ip(struct sk_buff *skb)
++{
++ const struct ether_header *eh = (struct ether_header *) skb->data;
++ const struct iphdr *ip = (struct iphdr *)
++ (skb->data + sizeof (struct ether_header));
++ unsigned int dscp;
++
++ switch (skb->protocol) {
++ case __constant_htons(ETH_P_IP):
++ dscp = ip->tos & 0xfc;
++ break;
++ default:
++ return 0;
++ }
++
++ return dscp >> 5;
++}
+
+ /*
+ * Determine the priority based on VLAN and/or IP TOS. Priority is
+@@ -83,90 +106,24 @@ static int
+ ieee80211_classify(struct ieee80211_node *ni, struct sk_buff *skb)
+ {
+ struct ieee80211vap *vap = ni->ni_vap;
+- struct ether_header *eh = (struct ether_header *) skb->data;
+- int v_wme_ac = 0, d_wme_ac = 0;
+
+- /* default priority */
+- skb->priority = WME_AC_BE;
+-
+- if (!(ni->ni_flags & IEEE80211_NODE_QOS))
+- return 0;
+-
+- /*
+- * If node has a vlan tag then all traffic
+- * to it must have a matching vlan id.
++ /* skb->priority values from 256->263 are magic values to
++ * directly indicate a specific 802.1d priority. This is used
++ * to allow 802.1d priority to be passed directly in from VLAN
++ * tags, etc.
+ */
+- if (ni->ni_vlan != 0 && vlan_tx_tag_present(skb)) {
+- u_int32_t tag=0;
+- int v_pri;
+-
+- if (vap->iv_vlgrp == NULL) {
+- IEEE80211_NODE_STAT(ni, tx_novlantag);
+- ni->ni_stats.ns_tx_novlantag++;
+- return 1;
+- }
+- if (((tag = vlan_tx_tag_get(skb)) & VLAN_VID_MASK) !=
+- (ni->ni_vlan & VLAN_VID_MASK)) {
+- IEEE80211_NODE_STAT(ni, tx_vlanmismatch);
+- ni->ni_stats.ns_tx_vlanmismatch++;
+- return 1;
+- }
+- if (ni->ni_flags & IEEE80211_NODE_QOS) {
+- v_pri = (tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
+- switch (v_pri) {
+- case 1:
+- case 2: /* Background (BK) */
+- v_wme_ac = WME_AC_BK;
+- break;
+- case 0:
+- case 3: /* Best Effort (BE) */
+- v_wme_ac = WME_AC_BE;
+- break;
+- case 4:
+- case 5: /* Video (VI) */
+- v_wme_ac = WME_AC_VI;
+- break;
+- case 6:
+- case 7: /* Voice (VO) */
+- v_wme_ac = WME_AC_VO;
+- break;
+- }
+- }
++ if (skb->priority >= 256 && skb->priority <= 263) {
++ skb->priority = ieee802_1d_to_ac[skb->priority - 256];
++ return 0;
+ }
+
+- if (eh->ether_type == __constant_htons(ETHERTYPE_IP)) {
+- const struct iphdr *ip = (struct iphdr *)
+- (skb->data + sizeof (struct ether_header));
+- /*
+- * IP frame, map the TOS field.
+- *
+- * XXX: fill out these mappings???
+- */
+- switch (ip->tos) {
+- case 0x08: /* Background */
+- case 0x20:
+- d_wme_ac = WME_AC_BK;
+- break;
+- case 0x28: /* Video */
+- case 0xa0:
+- d_wme_ac = WME_AC_VI;
+- break;
+- case 0x30: /* Voice */
+- case 0xe0:
+- case 0x88: /* XXX UPSD */
+- case 0xb8:
+- d_wme_ac = WME_AC_VO;
+- break;
+- default: /* All others */
+- d_wme_ac = WME_AC_BE;
+- break;
+- }
+- } else {
+- d_wme_ac = WME_AC_BE;
++ if (!(ni->ni_flags & IEEE80211_NODE_QOS)) {
++ /* default priority */
++ skb->priority = WME_AC_BE;
++ return 0;
+ }
+- skb->priority = d_wme_ac;
+- if (v_wme_ac > d_wme_ac)
+- skb->priority = v_wme_ac;
++
++ skb->priority = ieee802_1d_to_ac[ieee80211_classify_ip(skb)];
+
+ /* Applying ACM policy */
+ if (vap->iv_opmode == IEEE80211_M_STA) {
diff --git a/package/madwifi/patches/441-fix_ibss_node_handling.patch b/package/madwifi/patches/441-fix_ibss_node_handling.patch
new file mode 100644
index 000000000..20d59de26
--- /dev/null
+++ b/package/madwifi/patches/441-fix_ibss_node_handling.patch
@@ -0,0 +1,91 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -6641,10 +6641,8 @@ static void
+ ath_recv_mgmt(struct ieee80211vap * vap, struct ieee80211_node *ni_or_null,
+ struct sk_buff *skb, int subtype, int rssi, u_int64_t rtsf)
+ {
++ const struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data;
+ struct ath_softc *sc = netdev_priv(vap->iv_ic->ic_dev);
+-#ifdef AR_DEBUG
+- struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data;
+-#endif
+ struct ieee80211_node * ni = ni_or_null;
+ u_int64_t hw_tsf, beacon_tsf;
+ u_int32_t hw_tu, beacon_tu, intval;
+@@ -6686,7 +6684,7 @@ ath_recv_mgmt(struct ieee80211vap * vap,
+ }
+ if ((vap->iv_opmode == IEEE80211_M_IBSS) &&
+ (sc->sc_opmode == HAL_M_HOSTAP) &&
+- IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid)) {
++ IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid)) {
+ /* In this mode, we drive the HAL in HOSTAP mode. Hence
+ * we do the IBSS merging in software. Also do not merge
+ * if the difference it too small. Otherwise we are playing
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -311,7 +311,8 @@ ieee80211_input(struct ieee80211vap * va
+ }
+ /* Do not try to find a node reference if the packet really did come from the BSS */
+ if (type == IEEE80211_FC0_TYPE_DATA && ni == vap->iv_bss &&
+- !IEEE80211_ADDR_EQ(vap->iv_bss->ni_macaddr, wh->i_addr2)) {
++ !IEEE80211_ADDR_EQ(vap->iv_bss->ni_macaddr, wh->i_addr2) &&
++ IEEE80211_ADDR_EQ(vap->iv_bssid, wh->i_addr3)) {
+ /* Try to find sender in local node table. */
+ ni = ieee80211_find_node(&ic->ic_sta, wh->i_addr2);
+ if (ni == NULL) {
+@@ -513,6 +514,10 @@ ieee80211_input(struct ieee80211vap * va
+ break;
+ case IEEE80211_M_IBSS:
+ case IEEE80211_M_AHDEMO:
++ /* ignore foreign data frames */
++ if (ni == vap->iv_bss)
++ goto out;
++
+ if (dir != IEEE80211_FC1_DIR_NODS) {
+ IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
+ wh, "data", "invalid dir 0x%x", dir);
+@@ -3558,6 +3563,11 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ } else if ((vap->iv_opmode == IEEE80211_M_WDS) && vap->iv_wdsnode) {
+ found = 1;
+ ni = ni_or_null = vap->iv_wdsnode;
++ } else if (vap->iv_opmode == IEEE80211_M_IBSS) {
++ ni_or_null = ieee80211_find_node(&ic->ic_sta, wh->i_addr2);
++ if (ni_or_null)
++ ni = ni_or_null;
++ found = 1;
+ }
+ IEEE80211_UNLOCK_IRQ(vap->iv_ic);
+
+@@ -3686,19 +3696,8 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ vap->iv_stats.is_rx_ssidmismatch++; /*XXX*/
+ return;
+ }
+- if (ni == vap->iv_bss) {
+- 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
+- * send the response so blindly add them to the
+- * neighbor table.
+- */
+- ni = ieee80211_fakeup_adhoc_node(vap,
+- wh->i_addr2);
+- } else {
+- ni = ieee80211_dup_bss(vap, wh->i_addr2, 1);
+- }
++ if (ni == vap->iv_bss && vap->iv_opmode != IEEE80211_M_IBSS) {
++ ni = ieee80211_dup_bss(vap, wh->i_addr2, 1);
+ if (ni == NULL)
+ return;
+ allocbs = 1;
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -601,6 +601,8 @@ ieee80211_ibss_merge(struct ieee80211_no
+ ic->ic_flags & IEEE80211_F_SHPREAMBLE ? "short" : "long",
+ ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long",
+ ic->ic_flags & IEEE80211_F_USEPROT ? ", protection" : "");
++ if (!IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bssid))
++ ieee80211_node_table_reset(&vap->iv_ic->ic_sta, vap);
+ return ieee80211_sta_join1(ieee80211_ref_node(ni));
+ }
+ EXPORT_SYMBOL(ieee80211_ibss_merge);
diff --git a/package/madwifi/patches/442-ibss_rx_filter.patch b/package/madwifi/patches/442-ibss_rx_filter.patch
new file mode 100644
index 000000000..eaf807118
--- /dev/null
+++ b/package/madwifi/patches/442-ibss_rx_filter.patch
@@ -0,0 +1,20 @@
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -294,6 +294,17 @@ ieee80211_input(struct ieee80211vap * va
+ break;
+ case IEEE80211_M_IBSS:
+ case IEEE80211_M_AHDEMO:
++ if (!IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid) ||
++ (!IEEE80211_ADDR_EQ(wh->i_addr1, vap->iv_myaddr) &&
++ !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
++ (subtype != IEEE80211_FC0_SUBTYPE_BEACON))) {
++ if (!(vap->iv_dev->flags & IFF_PROMISC)) {
++ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
++ bssid, NULL, "%s", "not to bss");
++ vap->iv_stats.is_rx_wrongbss++;
++ goto out;
++ }
++ }
+ if (dir != IEEE80211_FC1_DIR_NODS)
+ bssid = wh->i_addr1;
+ else if (type == IEEE80211_FC0_TYPE_CTL)
diff --git a/package/madwifi/patches/443-tx_drop_counter.patch b/package/madwifi/patches/443-tx_drop_counter.patch
new file mode 100644
index 000000000..30630ae43
--- /dev/null
+++ b/package/madwifi/patches/443-tx_drop_counter.patch
@@ -0,0 +1,25 @@
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -1592,10 +1592,6 @@ found:
+ ieee80211_ref_node(ni);
+ #endif
+ }
+- } else {
+- IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_OUTPUT, mac,
+- "no node, discard frame (%s)", __func__);
+- vap->iv_stats.is_tx_nonode++;
+ }
+ }
+ return ni;
+--- a/net80211/ieee80211_output.c
++++ b/net80211/ieee80211_output.c
+@@ -208,6 +208,9 @@ ieee80211_hardstart(struct sk_buff *skb,
+ ni = ieee80211_find_txnode(vap, eh->ether_dhost);
+ if (ni == NULL) {
+ /* NB: ieee80211_find_txnode does stat+msg */
++ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_OUTPUT, mac,
++ "no node, discard frame (%s)", __func__);
++ vap->iv_stats.is_tx_nonode++;
+ goto bad;
+ }
+
diff --git a/package/madwifi/patches/444-beacon_update_war.patch b/package/madwifi/patches/444-beacon_update_war.patch
new file mode 100644
index 000000000..6a3178a6d
--- /dev/null
+++ b/package/madwifi/patches/444-beacon_update_war.patch
@@ -0,0 +1,17 @@
+--- a/net80211/ieee80211_beacon.c
++++ b/net80211/ieee80211_beacon.c
+@@ -476,6 +476,14 @@ ieee80211_beacon_update(struct ieee80211
+ tie->tim_bitctl |= BITCTL_BUFD_MCAST;
+ else
+ tie->tim_bitctl &= ~BITCTL_BUFD_MCAST;
++
++ /* WAR: on some platforms, a race condition between beacon
++ * contents update and beacon transmission leads to beacon
++ * data not being updated in time. For most fields this is
++ * not critical, but for powersave it is. Work around this
++ * by always remapping the beacon when the TIM IE changes.
++ */
++ len_changed = 1;
+ }
+
+ /* Whenever we want to switch to a new channel, we need to follow the
diff --git a/package/madwifi/patches/445-fix_ps_sta_count.patch b/package/madwifi/patches/445-fix_ps_sta_count.patch
new file mode 100644
index 000000000..27514650a
--- /dev/null
+++ b/package/madwifi/patches/445-fix_ps_sta_count.patch
@@ -0,0 +1,18 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -1957,6 +1957,7 @@ ath_uapsd_processtriggers(struct ath_sof
+ if (qwh->i_fc[1] & IEEE80211_FC1_PWR_MGT) {
+ ni->ni_flags |=
+ IEEE80211_NODE_UAPSD_TRIG;
++ ni->ni_vap->iv_ps_sta++;
+ ic->ic_uapsdmaxtriggers++;
+ WME_UAPSD_NODE_TRIGSEQINIT(ni);
+ DPRINTF(sc, ATH_DEBUG_UAPSD,
+@@ -1967,6 +1968,7 @@ ath_uapsd_processtriggers(struct ath_sof
+ } else {
+ ni->ni_flags &=
+ ~IEEE80211_NODE_UAPSD_TRIG;
++ ni->ni_vap->iv_ps_sta--;
+ ic->ic_uapsdmaxtriggers--;
+ DPRINTF(sc, ATH_DEBUG_UAPSD,
+ "Node (" MAC_FMT ") no longer U-APSD"
diff --git a/package/madwifi/patches/446-single_module.patch b/package/madwifi/patches/446-single_module.patch
new file mode 100644
index 000000000..b2898ca7e
--- /dev/null
+++ b/package/madwifi/patches/446-single_module.patch
@@ -0,0 +1,778 @@
+--- a/ath/Makefile
++++ b/ath/Makefile
+@@ -41,7 +41,6 @@
+ #
+
+ obj := $(firstword $(obj) $(SUBDIRS) .)
+-TOP = $(obj)/..
+
+ ifeq ($(strip $(BUS)),AHB)
+ BUSNAME=ahb
+@@ -57,7 +56,24 @@ COPTS += -DDFS_DOMAIN_ETSI -DDFS_DOMAIN_
+ include $(TOP)/Makefile.inc
+
+ obj-m += ath_$(BUSNAME).o
+-ath_$(BUSNAME)-objs := if_ath.o if_ath_radar.o if_ath_$(BUSNAME).o
++ath_objs := if_ath.o if_ath_radar.o if_ath_$(BUSNAME).o
++ath_$(BUSNAME)-objs := $(ath_objs)
++
++ifneq ($(SINGLE_MODULE),)
++include $(TOP)/net80211/Makefile
++include $(TOP)/ath_rate/sample/Makefile
++include $(TOP)/ath_rate/minstrel/Makefile
++RC_DECLARE=$(foreach R,$(ATH_RATE),extern void ath_rate_$(R)_init(void);extern void ath_rate_$(R)_exit(void);)
++RC_INIT=$(foreach R,$(ATH_RATE),ath_rate_$(R)_init();)
++RC_EXIT=$(foreach R,$(ATH_RATE),ath_rate_$(R)_exit();)
++
++ath_$(BUSNAME)-objs += $(patsubst %,../net80211/%,$(wlan-objs) $(foreach var,wep tkip ccmp acl xauth scan_sta scan_ap,$(wlan_$(var)-objs))) $(foreach RC,$(ATH_RATE),$(patsubst %,../ath_rate/$(RC)/%,$(ath_rate_$(RC)-objs)))
++ifdef LINUX24
++ ath_$(BUSNAME)-linkobjs := $(ath_objs) $(wlan-objs) $(foreach var,wep tkip ccmp acl xauth scan_sta scan_ap,$(wlan_$(var)-objs)) $(foreach RC,$(ATH_RATE),$(ath_rate_$(RC)-objs))
++endif
++
++EXTRA_CFLAGS += -DSINGLE_MODULE -DRC_INIT="$(RC_INIT)" -DRC_EXIT="$(RC_EXIT)" -DRC_DECLARE="$(RC_DECLARE)"
++endif
+
+ INCS += -I$(TOP) -I$(ATH_HAL) -I$(HAL) -I$(WLAN)
+
+@@ -72,13 +88,8 @@ install:
+ test -d $(DESTDIR)/$(KMODPATH) || mkdir -p $(DESTDIR)/$(KMODPATH)
+ install -m 0644 ath_$(BUSNAME).$(KMODSUF) $(DESTDIR)/$(KMODPATH)
+
+-clean:
+- rm -f *~ *.o *.ko *.mod.c .*.cmd
+- rm -f .depend .version .*.o.flags .*.o.d
+- rm -rf .tmp_versions
+-
+ ath_$(BUSNAME).o: $(ath_$(BUSNAME)-objs)
+- $(LD) $(LDOPTS) -o ath_$(BUSNAME).$(KMODSUF) -r $(ath_$(BUSNAME)-objs)
++ $(LD) $(LDOPTS) -o ath_$(BUSNAME).$(KMODSUF) -r $(if $(ath_$(BUSNAME)-linkobjs),$(ath_$(BUSNAME)-linkobjs),$(ath_$(BUSNAME)-objs))
+
+ if_ath_hal.h: $(HAL)/ah.h
+ $(TOP)/scripts/if_ath_hal_generator.pl $< $@
+--- a/net80211/ieee80211_acl.c
++++ b/net80211/ieee80211_acl.c
+@@ -281,16 +281,6 @@ acl_getpolicy(struct ieee80211vap *vap)
+ return as->as_policy;
+ }
+
+-/*
+- * Module glue.
+- */
+-
+-MODULE_AUTHOR("Errno Consulting, Sam Leffler");
+-MODULE_DESCRIPTION("802.11 wireless support: MAC-based ACL policy");
+-#ifdef MODULE_LICENSE
+-MODULE_LICENSE("Dual BSD/GPL");
+-#endif
+-
+ static const struct ieee80211_aclator mac = {
+ .iac_name = "mac",
+ .iac_attach = acl_attach,
+@@ -303,6 +293,18 @@ static const struct ieee80211_aclator ma
+ .iac_getpolicy = acl_getpolicy,
+ };
+
++#include "module.h"
++/*
++ * Module glue.
++ */
++
++MODULE_AUTHOR("Errno Consulting, Sam Leffler");
++MODULE_DESCRIPTION("802.11 wireless support: MAC-based ACL policy");
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("Dual BSD/GPL");
++#endif
++
++
+ static int __init
+ init_ieee80211_acl(void)
+ {
+--- a/net80211/ieee80211_crypto_ccmp.c
++++ b/net80211/ieee80211_crypto_ccmp.c
+@@ -686,6 +686,8 @@ ccmp_decrypt(struct ieee80211_key *key,
+ }
+ #undef CCMP_DECRYPT
+
++#include "module.h"
++
+ /*
+ * Module glue.
+ */
+--- a/net80211/ieee80211_crypto_tkip.c
++++ b/net80211/ieee80211_crypto_tkip.c
+@@ -1046,6 +1046,8 @@ tkip_decrypt(struct tkip_ctx *ctx, struc
+ return 1;
+ }
+
++#include "module.h"
++
+ /*
+ * Module glue.
+ */
+--- a/net80211/ieee80211_crypto_wep.c
++++ b/net80211/ieee80211_crypto_wep.c
+@@ -497,6 +497,8 @@ wep_decrypt(struct ieee80211_key *key, s
+ * Module glue.
+ */
+
++#include "module.h"
++
+ MODULE_AUTHOR("Errno Consulting, Sam Leffler");
+ MODULE_DESCRIPTION("802.11 wireless support: WEP cipher");
+ #ifdef MODULE_LICENSE
+--- a/net80211/ieee80211_linux.c
++++ b/net80211/ieee80211_linux.c
+@@ -1015,6 +1015,10 @@ static struct notifier_block ieee80211_e
+ static char *version = RELEASE_VERSION;
+ static char *dev_info = "wlan";
+
++extern void ieee80211_auth_setup(void);
++
++#include "module.h"
++
+ MODULE_AUTHOR("Errno Consulting, Sam Leffler");
+ MODULE_DESCRIPTION("802.11 wireless LAN protocol support");
+ #ifdef MODULE_VERSION
+@@ -1024,8 +1028,6 @@ MODULE_VERSION(RELEASE_VERSION);
+ MODULE_LICENSE("Dual BSD/GPL");
+ #endif
+
+-extern void ieee80211_auth_setup(void);
+-
+ static int __init
+ init_wlan(void)
+ {
+--- a/net80211/ieee80211_scan_ap.c
++++ b/net80211/ieee80211_scan_ap.c
+@@ -763,15 +763,6 @@ action_tasklet(IEEE80211_TQUEUE_ARG data
+ (*ss->ss_ops->scan_default)(vap, &as->as_selbss);
+ }
+
+-/*
+- * Module glue.
+- */
+-MODULE_AUTHOR("Errno Consulting, Sam Leffler");
+-MODULE_DESCRIPTION("802.11 wireless support: default ap scanner");
+-#ifdef MODULE_LICENSE
+-MODULE_LICENSE("Dual BSD/GPL");
+-#endif
+-
+ static const struct ieee80211_scanner ap_default = {
+ .scan_name = "default",
+ .scan_attach = ap_attach,
+@@ -789,6 +780,16 @@ static const struct ieee80211_scanner ap
+ .scan_default = ap_default_action,
+ };
+
++#include "module.h"
++
++/*
++ * Module glue.
++ */
++MODULE_AUTHOR("Errno Consulting, Sam Leffler");
++MODULE_DESCRIPTION("802.11 wireless support: default ap scanner");
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("Dual BSD/GPL");
++#endif
+
+ static int __init
+ init_scanner_ap(void)
+--- a/net80211/ieee80211_scan_sta.c
++++ b/net80211/ieee80211_scan_sta.c
+@@ -1208,6 +1208,8 @@ action_tasklet(IEEE80211_TQUEUE_ARG data
+ ieee80211_start_scan(vap, ss->ss_flags, ss->ss_duration, ss->ss_nssid, ss->ss_ssid);
+ }
+
++#include "module.h"
++
+ /*
+ * Module glue.
+ */
+@@ -1217,6 +1219,7 @@ MODULE_DESCRIPTION("802.11 wireless supp
+ MODULE_LICENSE("Dual BSD/GPL");
+ #endif
+
++
+ static int __init
+ init_scanner_sta(void)
+ {
+--- a/net80211/ieee80211_xauth.c
++++ b/net80211/ieee80211_xauth.c
+@@ -65,15 +65,6 @@
+ #include <net80211/ieee80211_var.h>
+
+ /*
+- * Module glue.
+- */
+-MODULE_AUTHOR("Errno Consulting, Sam Leffler");
+-MODULE_DESCRIPTION("802.11 wireless support: external (user mode) authenticator");
+-#ifdef MODULE_LICENSE
+-MODULE_LICENSE("Dual BSD/GPL");
+-#endif
+-
+-/*
+ * One module handles everything for now. May want
+ * to split things up for embedded applications.
+ */
+@@ -85,6 +76,18 @@ static const struct ieee80211_authentica
+ .ia_node_leave = NULL,
+ };
+
++#include "module.h"
++
++/*
++ * Module glue.
++ */
++MODULE_AUTHOR("Errno Consulting, Sam Leffler");
++MODULE_DESCRIPTION("802.11 wireless support: external (user mode) authenticator");
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("Dual BSD/GPL");
++#endif
++
++
+ static int __init
+ init_ieee80211_xauth(void)
+ {
+--- a/net80211/Makefile
++++ b/net80211/Makefile
+@@ -40,7 +40,11 @@
+ # Makefile for the 802.11 WLAN modules.
+ #
+ obj := $(firstword $(obj) $(SUBDIRS) .)
+-TOP = $(obj)/..
++
++include $(TOP)/Makefile.inc
++
++ifeq ($(SINGLE_MODULE),)
++
+ #
+ # There is one authenticator mechanism: an in-kernel implementation
+ # (wlan_xauth).
+@@ -59,29 +63,8 @@ MOD_INSTALL := wlan.o wlan_wep.o wlan_tk
+
+ obj-m += $(MOD_INSTALL)
+
+-wlan-objs := if_media.o \
+- ieee80211_skb.o \
+- ieee80211.o ieee80211_beacon.o ieee80211_crypto.o \
+- ieee80211_crypto_none.o ieee80211_input.o ieee80211_node.o \
+- ieee80211_output.o ieee80211_power.o ieee80211_proto.o \
+- ieee80211_scan.o ieee80211_wireless.o ieee80211_linux.o \
+- ieee80211_monitor.o ieee80211_rate.o
+-wlan_wep-objs := ieee80211_crypto_wep.o
+-wlan_tkip-objs := ieee80211_crypto_tkip.o
+-wlan_ccmp-objs := ieee80211_crypto_ccmp.o
+-wlan_acl-objs := ieee80211_acl.o
+-wlan_xauth-objs := ieee80211_xauth.o
+-wlan_scan_sta-objs :=ieee80211_scan_sta.o
+-wlan_scan_ap-objs := ieee80211_scan_ap.o
+-
+-include $(TOP)/Makefile.inc
+-
+ INCS += -I$(TOP) -I$(ATH_HAL) -I$(HAL)
+
+-EXTRA_CFLAGS+=$(INCS) $(COPTS) -DOPT_AH_H=\"public/$(TARGET).opt_ah.h\"
+-
+--include $(TOPDIR)/Rules.make
+-
+ all:
+ $(MAKE) -C $(KERNELPATH) SUBDIRS=$(shell pwd) modules
+
+@@ -108,8 +91,28 @@ install:
+ f=`basename $$i .o`; \
+ install -m 0644 $$f.$(KMODSUF) $(DESTDIR)/$(KMODPATH); \
+ done
++else
++all:
++endif
++
++wlan-objs := if_media.o \
++ ieee80211_skb.o \
++ ieee80211.o ieee80211_beacon.o ieee80211_crypto.o \
++ ieee80211_crypto_none.o ieee80211_input.o ieee80211_node.o \
++ ieee80211_output.o ieee80211_power.o ieee80211_proto.o \
++ ieee80211_scan.o ieee80211_wireless.o ieee80211_linux.o \
++ ieee80211_monitor.o ieee80211_rate.o
++wlan_wep-objs := ieee80211_crypto_wep.o
++wlan_tkip-objs := ieee80211_crypto_tkip.o
++wlan_ccmp-objs := ieee80211_crypto_ccmp.o
++wlan_acl-objs := ieee80211_acl.o
++wlan_xauth-objs := ieee80211_xauth.o
++wlan_scan_sta-objs :=ieee80211_scan_sta.o
++wlan_scan_ap-objs := ieee80211_scan_ap.o
++
++
++EXTRA_CFLAGS+=$(INCS) $(COPTS) -DOPT_AH_H=\"public/$(TARGET).opt_ah.h\"
++
++-include $(TOPDIR)/Rules.make
++
+
+-clean:
+- -rm -f *~ *.o *.ko *.mod.c
+- -rm -f .depend .version .*.o.flags .*.o.d .*.o.cmd .*.ko.cmd
+- -rm -rf .tmp_versions
+--- /dev/null
++++ b/net80211/module.h
+@@ -0,0 +1,19 @@
++#ifdef SINGLE_MODULE
++
++#undef static
++#define static
++#undef module_init
++#undef module_exit
++#define module_init(...)
++#define module_exit(...)
++
++#undef MODULE_AUTHOR
++#undef MODULE_LICENSE
++#undef MODULE_VERSION
++#undef MODULE_DESCRIPTION
++#define MODULE_AUTHOR(...)
++#define MODULE_LICENSE(...)
++#define MODULE_VERSION(...)
++#define MODULE_DESCRIPTION(...)
++
++#endif
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -13780,3 +13780,5 @@ cleanup_ath_buf(struct ath_softc *sc, st
+ return bf;
+ }
+
++
++
+--- a/net80211/ieee80211.c
++++ b/net80211/ieee80211.c
+@@ -42,6 +42,7 @@
+ #include <linux/config.h>
+ #endif
+ #include <linux/version.h>
++#include <linux/init.h>
+ #include <linux/module.h>
+ #include <linux/skbuff.h>
+ #include <linux/netdevice.h>
+@@ -2015,3 +2016,65 @@ ieee80211_build_sc_ie(struct ieee80211co
+ int ath_debug_global = 0;
+ EXPORT_SYMBOL(ath_debug_global);
+
++#ifdef SINGLE_MODULE
++typedef void (*initfunc)(void);
++
++extern void init_ieee80211_acl(void);
++extern void init_crypto_ccmp(void);
++extern void init_crypto_tkip(void);
++extern void init_crypto_wep(void);
++extern void init_wlan(void);
++extern void init_scanner_ap(void);
++extern void init_scanner_sta(void);
++extern void init_ieee80211_xauth(void);
++
++extern void exit_ieee80211_acl(void);
++extern void exit_crypto_ccmp(void);
++extern void exit_crypto_tkip(void);
++extern void exit_crypto_wep(void);
++extern void exit_wlan(void);
++extern void exit_scanner_ap(void);
++extern void exit_scanner_sta(void);
++extern void exit_ieee80211_xauth(void);
++
++static __initdata initfunc net80211_init[] = {
++ init_wlan,
++ init_ieee80211_acl,
++ init_crypto_ccmp,
++ init_crypto_tkip,
++ init_crypto_wep,
++ init_ieee80211_xauth,
++ init_scanner_ap,
++ init_scanner_sta,
++};
++
++static __exitdata initfunc net80211_exit[] = {
++ exit_crypto_ccmp,
++ exit_crypto_tkip,
++ exit_crypto_wep,
++ exit_scanner_ap,
++ exit_scanner_sta,
++ exit_ieee80211_xauth,
++ exit_ieee80211_acl,
++ exit_wlan,
++};
++
++void net80211_init_module(void)
++{
++ int i;
++ for (i = 0; i < sizeof(net80211_init)/sizeof(net80211_init[0]); i++) {
++ if (net80211_init[i])
++ net80211_init[i]();
++ }
++}
++
++void net80211_exit_module(void)
++{
++ int i;
++ for (i = 0; i < sizeof(net80211_exit)/sizeof(net80211_exit[0]); i++) {
++ if (net80211_exit[i])
++ net80211_exit[i]();
++ }
++}
++
++#endif
+--- a/ath/if_ath_ahb.c
++++ b/ath/if_ath_ahb.c
+@@ -447,10 +447,18 @@ MODULE_SUPPORTED_DEVICE("Atheros WLAN ca
+ MODULE_LICENSE("Dual BSD/GPL");
+ #endif
+
++#ifdef SINGLE_MODULE
++RC_DECLARE
++#endif
++
+ static int __init
+ init_ath_ahb(void)
+ {
+ printk(KERN_INFO "%s: %s\n", dev_info, version);
++#ifdef SINGLE_MODULE
++ net80211_init_module();
++ RC_INIT
++#endif
+ platform_driver_register(&ahb_wmac_driver);
+ ath_sysctl_register();
+
+@@ -463,6 +471,10 @@ exit_ath_ahb(void)
+ {
+ ath_sysctl_unregister();
+ platform_driver_unregister(&ahb_wmac_driver);
++#ifdef SINGLE_MODULE
++ RC_EXIT
++ net80211_exit_module();
++#endif
+ printk(KERN_INFO "%s: driver unloaded\n", dev_info);
+ }
+ module_exit(exit_ath_ahb);
+--- a/ath/if_ath_pci.c
++++ b/ath/if_ath_pci.c
+@@ -415,11 +415,19 @@ MODULE_SUPPORTED_DEVICE("Atheros WLAN ca
+ MODULE_LICENSE("Dual BSD/GPL");
+ #endif
+
++#ifdef SINGLE_MODULE
++RC_DECLARE
++#endif
++
+ static int __init
+ init_ath_pci(void)
+ {
+ printk(KERN_INFO "%s: %s\n", dev_info, version);
+
++#ifdef SINGLE_MODULE
++ net80211_init_module();
++ RC_INIT
++#endif
+ if (pci_register_driver(&ath_pci_driver) < 0) {
+ printk(KERN_ERR "%s: No devices found, driver not installed.\n", dev_info);
+ return (-ENODEV);
+@@ -434,6 +442,10 @@ exit_ath_pci(void)
+ {
+ ath_sysctl_unregister();
+ pci_unregister_driver(&ath_pci_driver);
++#ifdef SINGLE_MODULE
++ RC_EXIT
++ net80211_exit_module();
++#endif
+
+ printk(KERN_INFO "%s: driver unloaded\n", dev_info);
+ }
+--- a/ath_rate/minstrel/Makefile
++++ b/ath_rate/minstrel/Makefile
+@@ -39,9 +39,7 @@
+ # Makefile for the Atheros Rate Control Support.
+ #
+ obj := $(firstword $(obj) $(SUBDIRS) .)
+-TOP = $(obj)/../..
+
+-obj-m += ath_rate_minstrel.o
+ ath_rate_minstrel-objs := minstrel.o
+
+ include $(TOP)/Makefile.inc
+@@ -50,6 +48,10 @@ INCS += -I$(TOP) -I$(ATH) -I$(ATH_HAL) -
+
+ EXTRA_CFLAGS+= $(INCS) $(COPTS) -DOPT_AH_H=\"public/$(TARGET).opt_ah.h\"
+
++ifeq ($(SINGLE_MODULE),)
++
++obj-m += ath_rate_minstrel.o
++
+ -include $(TOPDIR)/Rules.make
+
+ all:
+@@ -59,10 +61,9 @@ install:
+ test -d $(DESTDIR)/$(KMODPATH) || mkdir -p $(DESTDIR)/$(KMODPATH)
+ install -m 0644 ath_rate_minstrel.$(KMODSUF) $(DESTDIR)/$(KMODPATH)
+
+-clean:
+- -rm -f *~ *.o *.ko *.mod.c
+- -rm -f .depend .version .*.o.flags .*.o.d .*.o.cmd .*.ko.cmd
+- -rm -rf .tmp_versions
+-
+ ath_rate_minstrel.o: $(ath_rate_minstrel-objs)
+ $(LD) $(LDOPTS) -o ath_rate_minstrel.$(KMODSUF) -r $(ath_rate_minstrel-objs)
++else
++all:
++install:
++endif
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -945,6 +945,8 @@ static struct ieee80211_rate_ops ath_rat
+ .dynamic_proc_register = ath_rate_dynamic_proc_register,
+ };
+
++#include <net80211/module.h>
++
+ MODULE_AUTHOR("John Bicket/Derek Smithies");
+ MODULE_DESCRIPTION("Minstrel Rate bit-rate selection algorithm for Atheros devices");
+ #ifdef MODULE_VERSION
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -47,6 +47,7 @@
+ #include <net80211/ieee80211_power.h>
+ #include <net80211/ieee80211_proto.h>
+ #include <net80211/ieee80211_scan.h>
++#include "symbol.h"
+
+ /* NB:
+ * - Atheros chips use 6 bits when power is specified in whole dBm units, with
+@@ -740,6 +741,8 @@ void ieee80211_dfs_action(struct ieee802
+ void ieee80211_expire_channel_excl_restrictions(struct ieee80211com *);
+ void ieee80211_setpuregbasicrates(struct ieee80211_rateset *rs);
+ int ieee80211_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
++void net80211_init_module(void);
++void net80211_exit_module(void);
+
+ /*
+ * Iterate through ic_channels to enumerate all distinct ic_ieee channel numbers.
+--- a/net80211/ieee80211_linux.h
++++ b/net80211/ieee80211_linux.h
+@@ -521,7 +521,10 @@ extern struct sk_buff * ieee80211_getmgt
+ #define IF_DRAIN(_q) skb_queue_drain(_q)
+ extern void skb_queue_drain(struct sk_buff_head *q);
+
+-#ifndef __MOD_INC_USE_COUNT
++#ifdef SINGLE_MODULE
++#define _MOD_DEC_USE(_m) do {} while(0)
++#define _MOD_INC_USE(_m, _err) do {} while(0)
++#elif !defined(__MOD_INC_USE_COUNT)
+ #define _MOD_INC_USE(_m, _err) \
+ if (!try_module_get(_m)) { \
+ printk(KERN_WARNING "%s: try_module_get failed\n", \
+--- a/ath_rate/sample/Makefile
++++ b/ath_rate/sample/Makefile
+@@ -39,9 +39,7 @@
+ # Makefile for the Atheros Rate Control Support.
+ #
+ obj := $(firstword $(obj) $(SUBDIRS) .)
+-TOP = $(obj)/../..
+
+-obj-m += ath_rate_sample.o
+ ath_rate_sample-objs := sample.o
+
+ include $(TOP)/Makefile.inc
+@@ -50,6 +48,9 @@ INCS += -I$(TOP) -I$(ATH) -I$(ATH_HAL) -
+
+ EXTRA_CFLAGS+= $(INCS) $(COPTS) -DOPT_AH_H=\"public/$(TARGET).opt_ah.h\"
+
++ifeq ($(SINGLE_MODULE),)
++obj-m += ath_rate_sample.o
++
+ -include $(TOPDIR)/Rules.make
+
+ all:
+@@ -59,10 +60,9 @@ install:
+ test -d $(DESTDIR)/$(KMODPATH) || mkdir -p $(DESTDIR)/$(KMODPATH)
+ install -m 0644 ath_rate_sample.$(KMODSUF) $(DESTDIR)/$(KMODPATH)
+
+-clean:
+- -rm -f *~ *.o *.ko *.mod.c
+- -rm -f .depend .version .*.o.flags .*.o.d .*.o.cmd .*.ko.cmd
+- -rm -rf .tmp_versions
+-
+ ath_rate_sample.o: $(ath_rate_sample-objs)
+ $(LD) $(LDOPTS) -o ath_rate_sample.$(KMODSUF) -r $(ath_rate_sample-objs)
++else
++all:
++install:
++endif
+--- a/Makefile
++++ b/Makefile
+@@ -41,7 +41,7 @@
+ #
+
+ obj := $(firstword $(obj) $(SUBDIRS) .)
+-TOP = $(obj)
++export TOP:=$(if $(wildcard $(firstword $(SUBDIRS))/Makefile.inc),$(firstword $(SUBDIRS)),$(CURDIR))
+
+ ifneq (svnversion.h,$(MAKECMDGOALS))
+ include $(TOP)/Makefile.inc
+@@ -54,7 +54,7 @@ all: modules tools
+ modules: configcheck svnversion.h
+ ifdef LINUX24
+ for i in $(obj-y); do \
+- $(MAKE) -C $$i || exit 1; \
++ $(MAKE) -C $$i TOP="$(TOP)" || exit 1; \
+ done
+ else
+ $(MAKE) -C $(KERNELPATH) SUBDIRS=$(shell pwd) modules
+@@ -89,7 +89,7 @@ install-modules: modules
+ sh scripts/find-madwifi-modules.sh -r $(KERNELRELEASE) $(DESTDIR)
+
+ for i in $(obj-y); do \
+- $(MAKE) -C $$i install || exit 1; \
++ $(MAKE) -C $$i install TOP="$(TOP)" || exit 1; \
+ done
+ ifeq ($(DESTDIR),)
+ (export KMODPATH=$(KMODPATH); /sbin/depmod -ae $(KERNELRELEASE))
+@@ -114,12 +114,21 @@ reinstall-tools: uninstall-tools install
+ reinstall-modules: uninstall-modules install-modules
+
+ clean:
+- for i in $(obj-y); do \
+- $(MAKE) -C $$i clean; \
+- done
+- -$(MAKE) -C $(TOOLS) clean
+- rm -rf .tmp_versions
++ -find $(obj-y) -name '*~' \
++ -or -name '*.o' \
++ -or -name '*.o.d' \
++ -or -name '*.o.cmd' \
++ -or -name '*.o.flags' \
++ -or -name '*.ko' \
++ -or -name '*.ko.cmd' \
++ -or -name '*.mod.c' \
++ -or -name '.depend' \
++ -or -name '.version' \
++ -or -name '.symvers' | \
++ xargs -r rm -f
+ rm -f *.symvers svnversion.h
++ rm -rf .tmp_versions
++ make -C tools clean
+
+ info:
+ @echo "The following settings will be used for compilation:"
+@@ -135,18 +144,6 @@ info:
+ @echo "KMODPATH : $(KMODPATH)"
+ @echo "KMODSUF : $(KMODSUF)"
+
+-sanitycheck:
+- @echo -n "Checking requirements... "
+-
+- @# check if specified rate control is available
+- @if [ ! -d $(ATH_RATE) ]; then \
+- echo "FAILED"; \
+- echo "Selected rate control $(ATH_RATE) not available."; \
+- exit 1; \
+- fi
+-
+- @echo "ok."
+-
+ .PHONY: release
+ release:
+ sh scripts/make-release.bash
+@@ -155,7 +152,7 @@ release:
+ unload:
+ bash scripts/madwifi-unload
+
+-configcheck: sanitycheck
++configcheck:
+ @echo -n "Checking kernel configuration... "
+
+ @# check version of kernel
+--- a/Makefile.inc
++++ b/Makefile.inc
+@@ -68,6 +68,9 @@ endif
+ export KERNELPATH
+ endif
+
++# build net80211 and ath_ahb/ath_pci into a single module
++export SINGLE_MODULE=1
++
+ # KERNELRELEASE is the target kernel's version. It's always taken from
+ # the kernel build tree. Kernel Makefile doesn't always know the exact
+ # kernel version (especially for vendor stock kernels), so we get it
+@@ -100,6 +103,7 @@ export ARCH
+ include $(TOP)/ath_hal/ah_target.inc
+ export TARGET
+ COPTS += -DTARGET='"$(TARGET)"'
++COPTS += -DCONFIG_ATHEROS_RATE_DEFAULT='"$(firstword $(ATH_RATE))"'
+
+ # KMODPATH nominates the directory where the modules will be
+ # installed to
+@@ -141,7 +145,7 @@ ATH= $(TOP)/ath
+ #
+ # Path to the rate control algorithms.
+ #
+-ATH_RATE= $(TOP)/ath_rate
++ATH_RATE= minstrel
+ #
+ # Path to the userspace utilities.
+ #
+--- a/ath_rate/sample/sample.c
++++ b/ath_rate/sample/sample.c
+@@ -991,6 +991,8 @@ static struct ieee80211_rate_ops ath_rat
+ .dynamic_proc_register = ath_rate_dynamic_proc_register,
+ };
+
++#include <net80211/module.h>
++
+ MODULE_AUTHOR("John Bicket");
+ MODULE_DESCRIPTION("SampleRate bit-rate selection algorithm for Atheros devices");
+ #ifdef MODULE_VERSION
+@@ -1000,18 +1002,17 @@ MODULE_VERSION(RELEASE_VERSION);
+ MODULE_LICENSE("Dual BSD/GPL");
+ #endif
+
+-static int __init
+-init_ath_rate_sample(void)
++static int __init ath_rate_sample_init(void)
+ {
+ printk(KERN_INFO "%s: %s\n", dev_info, version);
+ return ieee80211_rate_register(&ath_rate_ops);
+ }
+-module_init(init_ath_rate_sample);
++module_init(ath_rate_sample_init);
+
+ static void __exit
+-exit_ath_rate_sample(void)
++ath_rate_sample_exit(void)
+ {
+ ieee80211_rate_unregister(&ath_rate_ops);
+ printk(KERN_INFO "%s: unloaded\n", dev_info);
+ }
+-module_exit(exit_ath_rate_sample);
++module_exit(ath_rate_sample_exit);
+--- a/net80211/if_media.h
++++ b/net80211/if_media.h
+@@ -42,6 +42,7 @@
+ #define _NET_IF_MEDIA_H_
+
+ #include <net80211/ieee80211_linux.h>
++#include "symbol.h"
+
+ /*
+ * Prototypes and definitions for BSD/OS-compatible network interface
+--- /dev/null
++++ b/net80211/symbol.h
+@@ -0,0 +1,4 @@
++#ifdef SINGLE_MODULE
++#undef EXPORT_SYMBOL
++#define EXPORT_SYMBOL(...)
++#endif
+--- a/ath_rate/Makefile
++++ b/ath_rate/Makefile
+@@ -1,7 +1,7 @@
+ obj := $(firstword $(obj) $(SUBDIRS) .)
+ TOP = $(obj)/..
+
+-obj-y := amrr/ onoe/ sample/ minstrel/
++obj-y := sample/ minstrel/
+
+ include $(TOP)/Makefile.inc
+
diff --git a/package/madwifi/patches/447-sta_reconnect.patch b/package/madwifi/patches/447-sta_reconnect.patch
new file mode 100644
index 000000000..960d1b8ed
--- /dev/null
+++ b/package/madwifi/patches/447-sta_reconnect.patch
@@ -0,0 +1,25 @@
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -647,8 +647,11 @@ ieee80211_sta_join1(struct ieee80211_nod
+ (vap->iv_state == IEEE80211_S_RUN) && bssid_equal(obss, selbs)); */
+ vap->iv_bss = selbs;
+ IEEE80211_ADDR_COPY(vap->iv_bssid, selbs->ni_bssid);
+- if (obss != NULL)
++ if (obss != NULL) {
++ if (obss->ni_table)
++ ieee80211_node_leave(obss);
+ ieee80211_unref_node(&obss);
++ }
+ ic->ic_bsschan = selbs->ni_chan;
+ ic->ic_curchan = ic->ic_bsschan;
+ ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan);
+--- a/net80211/ieee80211_proto.c
++++ b/net80211/ieee80211_proto.c
+@@ -1602,7 +1602,6 @@ __ieee80211_newstate(struct ieee80211vap
+ IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
+ break;
+ case IEEE80211_S_RUN:
+- ieee80211_node_leave(ni);
+ if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
+ /* NB: caller specifies ASSOC/REASSOC by arg */
+ IEEE80211_SEND_MGMT(ni, arg ?
diff --git a/package/madwifi/patches/448-beacon_handling_fixes.patch b/package/madwifi/patches/448-beacon_handling_fixes.patch
new file mode 100644
index 000000000..9c0f912e4
--- /dev/null
+++ b/package/madwifi/patches/448-beacon_handling_fixes.patch
@@ -0,0 +1,407 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -160,7 +160,7 @@ static int ath_check_beacon_done(struct
+ static void ath_beacon_send(struct ath_softc *, int *, uint64_t hw_tsf);
+ static void ath_beacon_return(struct ath_softc *, struct ath_buf *);
+ static void ath_beacon_free(struct ath_softc *);
+-static void ath_beacon_config(struct ath_softc *, struct ieee80211vap *);
++static void ath_beacon_config(struct ath_softc *, struct ieee80211vap *, int);
+ static void ath_hw_beacon_stop(struct ath_softc *sc);
+ static int ath_desc_alloc(struct ath_softc *);
+ static void ath_desc_free(struct ath_softc *);
+@@ -387,13 +387,11 @@ static void ath_set_timing(struct ath_so
+ /* calibrate every 30 secs in steady state but check every second at first. */
+ static int ath_calinterval = ATH_SHORT_CALINTERVAL;
+ static int ath_xchanmode = AH_TRUE; /* enable extended channels */
+-static int ath_maxvaps = ATH_MAXVAPS_DEFAULT; /* set default maximum vaps */
+ static int bstuck_thresh = BSTUCK_THRESH; /* Stuck beacon count required for reset */
+ static char *autocreate = NULL;
+ static char *ratectl = DEF_RATE_CTL;
+ static int rfkill = 0;
+ static int tpc = 1;
+-static int maxvaps = -1;
+ static int xchanmode = -1;
+ #include "ath_wprobe.c"
+ static int beacon_cal = 1;
+@@ -432,7 +430,6 @@ static struct notifier_block ath_event_b
+
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))
+ MODULE_PARM(beacon_cal, "i");
+-MODULE_PARM(maxvaps, "i");
+ MODULE_PARM(xchanmode, "i");
+ MODULE_PARM(rfkill, "i");
+ #ifdef ATH_CAP_TPC
+@@ -444,7 +441,6 @@ MODULE_PARM(ratectl, "s");
+ #else
+ #include <linux/moduleparam.h>
+ module_param(beacon_cal, int, 0600);
+-module_param(maxvaps, int, 0600);
+ module_param(xchanmode, int, 0600);
+ module_param(rfkill, int, 0600);
+ #ifdef ATH_CAP_TPC
+@@ -454,7 +450,6 @@ module_param(bstuck_thresh, int, 0600);
+ module_param(autocreate, charp, 0600);
+ module_param(ratectl, charp, 0600);
+ #endif
+-MODULE_PARM_DESC(maxvaps, "Maximum VAPs");
+ MODULE_PARM_DESC(xchanmode, "Enable/disable extended channel mode");
+ MODULE_PARM_DESC(rfkill, "Enable/disable RFKILL capability");
+ #ifdef ATH_CAP_TPC
+@@ -512,7 +507,7 @@ MODULE_PARM_DESC(ieee80211_debug, "Load-
+ * and use the higher bits as the index of the VAP.
+ */
+ #define ATH_SET_VAP_BSSID_MASK(bssid_mask) \
+- ((bssid_mask)[0] &= ~(((ath_maxvaps-1) << 2) | 0x02))
++ ((bssid_mask)[0] &= ~(((ATH_MAXVAPS_BCN-1) << 2) | 0x02))
+ #define ATH_GET_VAP_ID(bssid) ((bssid)[0] >> 2)
+ #define ATH_SET_VAP_BSSID(bssid, id) \
+ do { \
+@@ -604,8 +599,8 @@ ath_attach(u_int16_t devid, struct net_d
+
+ /* Allocate space for dynamically determined maximum VAP count */
+ sc->sc_bslot =
+- kmalloc(ath_maxvaps * sizeof(struct ieee80211vap*), GFP_KERNEL);
+- memset(sc->sc_bslot, 0, ath_maxvaps * sizeof(struct ieee80211vap*));
++ kmalloc(ATH_MAXVAPS_BCN * sizeof(struct ieee80211vap*), GFP_KERNEL);
++ memset(sc->sc_bslot, 0, ATH_MAXVAPS_BCN * sizeof(struct ieee80211vap*));
+
+ /*
+ * Cache line size is used to size and align various
+@@ -694,13 +689,6 @@ ath_attach(u_int16_t devid, struct net_d
+ for (i = 0; i < sc->sc_keymax; i++)
+ ath_hal_keyreset(ah, i);
+
+- if (maxvaps != -1) {
+- ath_maxvaps = maxvaps;
+- if (ath_maxvaps < ATH_MAXVAPS_MIN)
+- ath_maxvaps = ATH_MAXVAPS_MIN;
+- else if (ath_maxvaps > ATH_MAXVAPS_MAX)
+- ath_maxvaps = ATH_MAXVAPS_MAX;
+- }
+ if (xchanmode != -1)
+ ath_xchanmode = xchanmode;
+ error = ath_getchannels(dev);
+@@ -1349,12 +1337,6 @@ ath_vap_create(struct ieee80211com *ic,
+ return NULL;
+ }
+
+- if (sc->sc_nvaps >= ath_maxvaps) {
+- EPRINTF(sc, "Too many virtual APs (%d already exist).\n",
+- sc->sc_nvaps);
+- return NULL;
+- }
+-
+ dev = alloc_etherdev(sizeof(struct ath_vap) + sc->sc_rc->arc_vap_space);
+ if (dev == NULL) {
+ /* XXX msg */
+@@ -1424,7 +1406,7 @@ ath_vap_create(struct ieee80211com *ic,
+ TAILQ_FOREACH(v, &ic->ic_vaps, iv_next)
+ id_mask |= (1 << ATH_GET_VAP_ID(v->iv_myaddr));
+
+- for (id = 0; id < ath_maxvaps; id++) {
++ for (id = 0; id < ATH_MAXVAPS_BCN; id++) {
+ /* get the first available slot */
+ if ((id_mask & (1 << id)) == 0) {
+ ATH_SET_VAP_BSSID(vap->iv_myaddr, id);
+@@ -1451,11 +1433,11 @@ ath_vap_create(struct ieee80211com *ic,
+ /* 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_maxvaps; slot++)
++ for (slot = 0; slot < ATH_MAXVAPS_BCN; slot++)
+ if (sc->sc_bslot[slot] == NULL) {
+ /* XXX: Hack, space out slots to better
+ * deal with misses. */
+- if (slot + 1 < ath_maxvaps &&
++ if (slot + 1 < ATH_MAXVAPS_BCN &&
+ sc->sc_bslot[slot+1] == NULL) {
+ avp->av_bslot = slot + 1;
+ break;
+@@ -1463,8 +1445,11 @@ ath_vap_create(struct ieee80211com *ic,
+ 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));
++ if (sc->sc_bslot[avp->av_bslot]) {
++ free_netdev(dev);
++ return NULL;
++ }
++
+ sc->sc_bslot[avp->av_bslot] = vap;
+ sc->sc_nbcnvaps++;
+
+@@ -1475,15 +1460,7 @@ ath_vap_create(struct ieee80211com *ic,
+ * of staggered beacons.
+ */
+ /* XXX check for beacon interval too small */
+- if (ath_maxvaps > 4) {
+- DPRINTF(sc, ATH_DEBUG_BEACON,
+- "Staggered beacons are not "
+- "possible with maxvaps set "
+- "to %d.\n", ath_maxvaps);
+- sc->sc_stagbeacons = 0;
+- } else {
+- sc->sc_stagbeacons = 1;
+- }
++ sc->sc_stagbeacons = 1;
+ }
+ DPRINTF(sc, ATH_DEBUG_BEACON, "sc->sc_stagbeacons %sabled\n",
+ (sc->sc_stagbeacons ? "en" : "dis"));
+@@ -1553,7 +1530,7 @@ ath_vap_create(struct ieee80211com *ic,
+ if (ath_startrecv(sc) != 0) /* restart recv */
+ EPRINTF(sc, "Unable to start receive logic.\n");
+ if (sc->sc_beacons)
+- ath_beacon_config(sc, NULL); /* restart beacons */
++ ath_beacon_config(sc, NULL, 0); /* restart beacons */
+ ath_hal_intrset(ah, sc->sc_imask);
+ }
+
+@@ -1681,7 +1658,7 @@ ath_vap_delete(struct ieee80211vap *vap)
+ if (ath_startrecv(sc) != 0) /* restart recv. */
+ EPRINTF(sc, "Unable to start receive logic.\n");
+ if (sc->sc_beacons)
+- ath_beacon_config(sc, NULL); /* restart beacons */
++ ath_beacon_config(sc, NULL, 0); /* restart beacons */
+ ath_hal_intrset(ah, sc->sc_imask);
+ }
+ }
+@@ -3066,7 +3043,7 @@ ath_reset(struct net_device *dev)
+ */
+ ath_chan_change(sc, c);
+ if (sc->sc_beacons)
+- ath_beacon_config(sc, NULL); /* restart beacons */
++ ath_beacon_config(sc, NULL, 1); /* restart beacons */
+ ath_hal_intrset(ah, sc->sc_imask);
+ ath_set_ack_bitrate(sc, sc->sc_ackrate);
+ netif_wake_queue(dev); /* restart xmit */
+@@ -4763,7 +4740,7 @@ ath_check_beacon_done(struct ath_softc *
+ /*
+ * check if the last beacon went out with the mode change flag set.
+ */
+- for (slot = 0; slot < ath_maxvaps; slot++) {
++ for (slot = 0; slot < ATH_MAXVAPS_BCN; slot++) {
+ if (sc->sc_bslot[slot]) {
+ vap = sc->sc_bslot[slot];
+ break;
+@@ -4968,7 +4945,7 @@ ath_beacon_alloc_internal(struct ath_sof
+ * has a timestamp in one beacon interval while the
+ * others get a timestamp aligned to the next interval.
+ */
+- tuadjust = (ni->ni_intval * (ath_maxvaps - avp->av_bslot)) / ath_maxvaps;
++ tuadjust = (ni->ni_intval * (ATH_MAXVAPS_BCN - avp->av_bslot)) / ATH_MAXVAPS_BCN;
+ tsfadjust = cpu_to_le64(tuadjust << 10); /* TU->TSF */
+
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+@@ -5361,8 +5338,8 @@ ath_beacon_send(struct ath_softc *sc, in
+ u_int32_t tsftu;
+
+ tsftu = hw_tsf >> 10; /* NB: 64 -> 32: See note far above. */
+- slot = ((tsftu % ic->ic_lintval) * ath_maxvaps) / ic->ic_lintval;
+- vap = sc->sc_bslot[(slot + 1) % ath_maxvaps];
++ slot = ((tsftu % ic->ic_lintval) * ATH_MAXVAPS_BCN) / ic->ic_lintval;
++ vap = sc->sc_bslot[(slot + 1) % ATH_MAXVAPS_BCN];
+ DPRINTF(sc, ATH_DEBUG_BEACON_PROC,
+ "Slot %d [tsf %llu tsftu %llu intval %u] vap %p\n",
+ slot, (unsigned long long)hw_tsf,
+@@ -5377,7 +5354,7 @@ ath_beacon_send(struct ath_softc *sc, in
+ u_int32_t *bflink = NULL;
+
+ /* XXX: rotate/randomize order? */
+- for (slot = 0; slot < ath_maxvaps; slot++) {
++ for (slot = 0; slot < ATH_MAXVAPS_BCN; slot++) {
+ if ((vap = sc->sc_bslot[slot]) != NULL) {
+ if ((bf = ath_beacon_generate(
+ sc, vap,
+@@ -5418,7 +5395,7 @@ ath_beacon_send(struct ath_softc *sc, in
+ * again. If we miss a beacon for that slot then we'll be
+ * slow to transition but we'll be sure at least one beacon
+ * interval has passed. When bursting slot is always left
+- * set to ath_maxvaps so this check is a no-op.
++ * set to ATH_MAXVAPS_BCN so this check is a no-op.
+ */
+ /* XXX locking */
+ if (sc->sc_updateslot == UPDATE) {
+@@ -5526,7 +5503,7 @@ ath_beacon_free(struct ath_softc *sc)
+ * (2^(32 + 10 - 1) - 1)us is a really long time.
+ */
+ static void
+-ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap)
++ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap, int reset)
+ {
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_hal *ah = sc->sc_ah;
+@@ -5553,7 +5530,7 @@ ath_beacon_config(struct ath_softc *sc,
+ /* We should reset hw TSF only once, so we increment
+ * ni_tstamp.tsf to avoid resetting the hw TSF multiple
+ * times */
+- if (tsf == 0) {
++ if (tsf == 0 || reset) {
+ reset_tsf = 1;
+ ni->ni_tstamp.tsf = cpu_to_le64(1);
+ }
+@@ -5567,7 +5544,7 @@ ath_beacon_config(struct ath_softc *sc,
+ /* NB: the beacon interval is kept internally in TUs */
+ intval = ic->ic_lintval & HAL_BEACON_PERIOD;
+ if (sc->sc_stagbeacons)
+- intval /= ath_maxvaps; /* for staggered beacons */
++ intval /= ATH_MAXVAPS_BCN; /* for staggered beacons */
+ if ((sc->sc_nostabeacons) &&
+ (vap->iv_opmode == IEEE80211_M_HOSTAP))
+ reset_tsf = 1;
+@@ -5583,31 +5560,24 @@ ath_beacon_config(struct ath_softc *sc,
+ * time */
+ nexttbtt = intval;
+ } else if (intval) { /* NB: can be 0 for monitor mode */
+- if (tsf == 1) {
+- /* We have not received any beacons or probe
+- * responses. 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 TUs ahead
+- * of the current TSF. Otherwise, we use the
+- * next beacon timestamp again */
+- nexttbtt = roundup(hw_tsftu + FUDGE, intval);
+- }
+- else if (ic->ic_opmode == IEEE80211_M_IBSS) {
+- if (tsf > hw_tsf) {
+- /* We received a beacon, but the HW TSF has
+- * not been updated (otherwise hw_tsf > tsf)
+- * We cannot use the hardware TSF, so we
+- * wait to synchronize beacons again. */
+- sc->sc_syncbeacon = 1;
+- goto ath_beacon_config_debug;
+- } else {
+- /* Normal case: we received a beacon to which
+- * we have synchronized. Make sure that nexttbtt
+- * is at least FUDGE TU ahead of hw_tsf */
+- nexttbtt = tsftu + roundup(hw_tsftu + FUDGE -
+- tsftu, intval);
+- }
++ if ((tsf > hw_tsf) && (ic->ic_opmode == IEEE80211_M_IBSS)) {
++ /* We received a beacon, but the HW TSF has
++ * not been updated (otherwise hw_tsf > tsf)
++ * We cannot use the hardware TSF, so we
++ * wait to synchronize beacons again. */
++ sc->sc_syncbeacon = 1;
++ goto ath_beacon_config_debug;
++ } else if ((tsftu + FUDGE) > hw_tsftu) {
++ if (tsftu > hw_tsftu + 2 * intval)
++ nexttbtt = roundup(hw_tsftu + FUDGE, intval);
++ else
++ nexttbtt = tsftu;
++ } else {
++ /* Normal case: we received a beacon to which
++ * we have synchronized. Make sure that nexttbtt
++ * is at least FUDGE TU ahead of hw_tsf */
++ nexttbtt = tsftu + roundup(hw_tsftu + FUDGE -
++ tsftu, intval);
+ }
+ }
+
+@@ -5730,9 +5700,6 @@ ath_beacon_config(struct ath_softc *sc,
+ ath_beacon_dturbo_config(vap, intval &
+ ~(HAL_BEACON_RESET_TSF | HAL_BEACON_ENA));
+ #endif
+- if ((nexttbtt & HAL_BEACON_PERIOD) - (ath_hal_gettsf32(ah) >> 10)
+- <= ath_hal_sw_beacon_response_time)
+- nexttbtt += intval;
+ sc->sc_nexttbtt = nexttbtt;
+
+ /* stop beacons before reconfiguring the timers to avoid race
+@@ -5889,7 +5856,7 @@ ath_desc_alloc(struct ath_softc *sc)
+
+ /* XXX allocate beacon state together with VAP */
+ error = ath_descdma_setup(sc, &sc->sc_bdma, &sc->sc_bbuf,
+- "beacon", ath_maxvaps, 1);
++ "beacon", ATH_MAXVAPS_BCN, 1);
+ if (error != 0) {
+ ath_descdma_cleanup(sc, &sc->sc_txdma, &sc->sc_txbuf,
+ BUS_DMA_TODEVICE);
+@@ -6680,7 +6647,7 @@ ath_recv_mgmt(struct ieee80211vap * vap,
+ /* Resync beacon timers using the tsf of the
+ * beacon frame we just received. */
+ vap->iv_flags_ext &= ~IEEE80211_FEXT_APPIE_UPDATE;
+- ath_beacon_config(sc, vap);
++ ath_beacon_config(sc, vap, 0);
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+ "Updated beacon timers\n");
+ }
+@@ -9359,7 +9326,7 @@ ath_chan_set(struct ath_softc *sc, struc
+ * HW seems to turn off beacons during turbo mode switch.
+ */
+ if (sc->sc_beacons && !sc->sc_dfs_cac)
+- ath_beacon_config(sc, NULL);
++ ath_beacon_config(sc, NULL, 0);
+ /*
+ * Re-enable interrupts.
+ */
+@@ -9813,7 +9780,7 @@ ath_newstate(struct ieee80211vap *vap, e
+ ATH_DEBUG_BEACON_PROC,
+ "Beacons reconfigured by %p[%s]!\n",
+ vap, vap->iv_nickname);
+- ath_beacon_config(sc, vap);
++ ath_beacon_config(sc, vap, 1);
+ sc->sc_beacons = 1;
+ }
+ } else {
+@@ -9948,9 +9915,6 @@ ath_dfs_cac_completed(unsigned long data
+ }
+ netif_wake_queue(dev);
+ ath_reset(dev);
+- if (sc->sc_beacons) {
+- ath_beacon_config(sc, NULL);
+- }
+ dev->watchdog_timeo = 5 * HZ; /* restore normal timeout */
+ } else {
+ do_gettimeofday(&tv);
+@@ -11473,9 +11437,6 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+ case ATH_OUTDOOR:
+ val = ic->ic_country_outdoor;
+ break;
+- case ATH_MAXVAPS:
+- val = ath_maxvaps;
+- break;
+ case ATH_REGDOMAIN:
+ ath_hal_getregdomain(ah, &val);
+ break;
+@@ -11606,12 +11567,6 @@ static const ctl_table ath_sysctl_templa
+ .extra2 = (void *)ATH_OUTDOOR,
+ },
+ { .ctl_name = CTL_AUTO,
+- .procname = "maxvaps",
+- .mode = 0444,
+- .proc_handler = ath_sysctl_halparam,
+- .extra2 = (void *)ATH_MAXVAPS,
+- },
+- { .ctl_name = CTL_AUTO,
+ .procname = "regdomain",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+@@ -11928,13 +11883,6 @@ static ctl_table ath_static_sysctls[] =
+ },
+ #endif
+ { .ctl_name = CTL_AUTO,
+- .procname = "maxvaps",
+- .mode = 0444,
+- .data = &ath_maxvaps,
+- .maxlen = sizeof(ath_maxvaps),
+- .proc_handler = proc_dointvec
+- },
+- { .ctl_name = CTL_AUTO,
+ .procname = "xchanmode",
+ .mode = 0444,
+ .data = &ath_xchanmode,
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -211,9 +211,7 @@ static inline struct net_device *_alloc_
+ #define ATH_RXBUF 40 /* number of RX buffers */
+ #define ATH_TXBUF 200 /* number of TX buffers */
+
+-#define ATH_MAXVAPS_MIN 2 /* minimum number of beacon buffers */
+-#define ATH_MAXVAPS_MAX 64 /* maximum number of beacon buffers */
+-#define ATH_MAXVAPS_DEFAULT 4 /* default number of beacon buffers */
++#define ATH_MAXVAPS_BCN 4 /* maximum number of beacon buffers */
+
+ /* free buffer threshold to restart net dev */
+ #define ATH_TXBUF_FREE_THRESHOLD (ATH_TXBUF / 20)
diff --git a/package/madwifi/patches/449-fix_txbuf_leak.patch b/package/madwifi/patches/449-fix_txbuf_leak.patch
new file mode 100644
index 000000000..31f2fef3a
--- /dev/null
+++ b/package/madwifi/patches/449-fix_txbuf_leak.patch
@@ -0,0 +1,10 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -3697,6 +3697,7 @@ ff_bypass:
+ */
+ skb = ieee80211_encap(ni, skb, &framecnt);
+ if (skb == NULL) {
++ STAILQ_INSERT_TAIL(&bf_head, bf, bf_list);
+ DPRINTF(sc, ATH_DEBUG_XMIT,
+ "Dropping; encapsulation failure\n");
+ sc->sc_stats.ast_tx_encap++;
diff --git a/package/madwifi/patches/450-calibration.patch b/package/madwifi/patches/450-calibration.patch
new file mode 100644
index 000000000..87397903d
--- /dev/null
+++ b/package/madwifi/patches/450-calibration.patch
@@ -0,0 +1,177 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -394,7 +394,6 @@ static int rfkill = 0;
+ static int tpc = 1;
+ static int xchanmode = -1;
+ #include "ath_wprobe.c"
+-static int beacon_cal = 1;
+
+ static const struct ath_hw_detect generic_hw_info = {
+ .vendor_name = "Unknown",
+@@ -429,7 +428,6 @@ static struct notifier_block ath_event_b
+ };
+
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))
+-MODULE_PARM(beacon_cal, "i");
+ MODULE_PARM(xchanmode, "i");
+ MODULE_PARM(rfkill, "i");
+ #ifdef ATH_CAP_TPC
+@@ -440,7 +438,6 @@ MODULE_PARM(autocreate, "s");
+ MODULE_PARM(ratectl, "s");
+ #else
+ #include <linux/moduleparam.h>
+-module_param(beacon_cal, int, 0600);
+ module_param(xchanmode, int, 0600);
+ module_param(rfkill, int, 0600);
+ #ifdef ATH_CAP_TPC
+@@ -825,6 +822,7 @@ ath_attach(u_int16_t devid, struct net_d
+ error = EIO;
+ goto bad2;
+ }
++ sc->sc_cal_interval = ath_calinterval;
+ init_timer(&sc->sc_cal_ch);
+ sc->sc_cal_ch.function = ath_calibrate;
+ sc->sc_cal_ch.data = (unsigned long) dev;
+@@ -2737,8 +2735,7 @@ ath_stop_locked(struct net_device *dev)
+ }
+ if (!sc->sc_invalid) {
+ del_timer_sync(&sc->sc_dfs_cac_timer);
+- if (!sc->sc_beacon_cal)
+- del_timer_sync(&sc->sc_cal_ch);
++ del_timer_sync(&sc->sc_cal_ch);
+ }
+ ath_draintxq(sc);
+ if (!sc->sc_invalid) {
+@@ -2763,10 +2760,9 @@ static void ath_set_beacon_cal(struct at
+ 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);
++ mod_timer(&sc->sc_cal_ch, jiffies + (sc->sc_cal_interval * HZ));
+ }
+- sc->sc_beacon_cal = !!val && beacon_cal;
++ sc->sc_beacon_cal = !!val;
+ }
+
+ /*
+@@ -3008,7 +3004,7 @@ ath_reset(struct net_device *dev)
+ * XXX: starting the calibration too early seems to lead to
+ * problems with the beacons.
+ */
+- sc->sc_lastcal = jiffies;
++ sc->sc_nextcal = jiffies + msecs_to_jiffies(sc->sc_cal_interval * 1000);
+
+ /*
+ * Convert to a HAL channel description with the flags
+@@ -5430,10 +5426,9 @@ ath_beacon_send(struct ath_softc *sc, in
+ "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))) {
+- sc->sc_cal_ch.expires = jiffies + msecs_to_jiffies(10);
+- add_timer(&sc->sc_cal_ch);
+- }
++ if (sc->sc_beacon_cal && ((sc->sc_bmisscount == 3) ||
++ (jiffies > sc->sc_nextcal)))
++ mod_timer(&sc->sc_cal_ch, jiffies + 1);
+
+ sc->sc_stats.ast_be_xmit++; /* XXX per-VAP? */
+ }
+@@ -9104,6 +9099,7 @@ ath_startrecv(struct ath_softc *sc)
+ dev->mtu, sc->sc_cachelsz, sc->sc_rxbufsize);
+
+ sc->sc_rxlink = NULL;
++ ath_set_beacon_cal(sc, IEEE80211_IS_MODE_BEACON(sc->sc_ic.ic_opmode));
+ STAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
+ int error = ath_rxbuf_init(sc, bf);
+ ATH_RXBUF_RESET(bf);
+@@ -9320,7 +9316,7 @@ ath_chan_set(struct ath_softc *sc, struc
+ jiffies + (sc->sc_dfs_cac_period * HZ));
+
+ /* This is a good time to start a calibration */
+- ath_set_beacon_cal(sc, 1);
++ mod_timer(&sc->sc_cal_ch, jiffies + 1);
+ }
+ /*
+ * re configure beacons when it is a turbo mode switch.
+@@ -9414,25 +9410,23 @@ ath_calibrate(unsigned long arg)
+ if (isIQdone == AH_TRUE) {
+ /* Unless user has overridden calibration interval,
+ * upgrade to less frequent calibration */
+- if (ath_calinterval == ATH_SHORT_CALINTERVAL)
+- ath_calinterval = ATH_LONG_CALINTERVAL;
++ if (sc->sc_cal_interval == ATH_SHORT_CALINTERVAL)
++ sc->sc_cal_interval = ATH_LONG_CALINTERVAL;
+ }
+ else {
+ /* Unless user has overridden calibration interval,
+ * downgrade to more frequent calibration */
+- if (ath_calinterval == ATH_LONG_CALINTERVAL)
+- ath_calinterval = ATH_SHORT_CALINTERVAL;
++ if (sc->sc_cal_interval == ATH_LONG_CALINTERVAL)
++ sc->sc_cal_interval = ATH_SHORT_CALINTERVAL;
+ }
+
+ DPRINTF(sc, ATH_DEBUG_CALIBRATE, "Channel %u/%x -- IQ %s.\n",
+ sc->sc_curchan.channel, sc->sc_curchan.channelFlags,
+ isIQdone ? "done" : "not done");
+
+- sc->sc_lastcal = jiffies;
+- if (!sc->sc_beacon_cal) {
+- sc->sc_cal_ch.expires = jiffies + (ath_calinterval * HZ);
+- add_timer(&sc->sc_cal_ch);
+- }
++ sc->sc_nextcal = jiffies + msecs_to_jiffies(sc->sc_cal_interval * 1000);
++ if (!sc->sc_beacon_cal)
++ mod_timer(&sc->sc_cal_ch, sc->sc_nextcal);
+ }
+
+ static void
+@@ -9540,9 +9534,6 @@ ath_newstate(struct ieee80211vap *vap, e
+ ieee80211_state_name[vap->iv_state],
+ ieee80211_state_name[nstate]);
+
+- 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 */
+
+@@ -9764,10 +9755,7 @@ ath_newstate(struct ieee80211vap *vap, e
+ IEEE80211_IS_MODE_DFS_MASTER(vap->iv_opmode)) {
+ DPRINTF(sc, ATH_DEBUG_STATE | ATH_DEBUG_DOTH,
+ "VAP -> DFSWAIT_PENDING \n");
+- /* start calibration timer with a really small value
+- * 1/10 sec */
+- if (!sc->sc_beacon_cal)
+- mod_timer(&sc->sc_cal_ch, jiffies + (HZ/10));
++ mod_timer(&sc->sc_cal_ch, jiffies + 1);
+ /* wake the receiver */
+ netif_wake_queue(dev);
+ /* don't do the other usual stuff... */
+@@ -9809,12 +9797,6 @@ done:
+ /* Invoke the parent method to complete the work. */
+ error = avp->av_newstate(vap, nstate, arg);
+
+- /* Finally, start any timers. */
+- if (nstate == IEEE80211_S_RUN && !sc->sc_beacon_cal) {
+- /* start periodic recalibration timer */
+- mod_timer(&sc->sc_cal_ch, jiffies + (ath_calinterval * HZ));
+- }
+-
+ #ifdef ATH_SUPERG_XR
+ if (vap->iv_flags & IEEE80211_F_XR &&
+ nstate == IEEE80211_S_RUN)
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -832,7 +832,8 @@ struct ath_softc {
+
+ struct ieee80211_channel *sc_last_chan;
+ int sc_beacon_cal; /* use beacon timer for calibration */
+- u_int64_t sc_lastcal; /* last time the calibration was performed */
++ u_int64_t sc_nextcal; /* last time the calibration was performed */
++ int sc_cal_interval; /* current calibration interval */
+ struct timer_list sc_cal_ch; /* calibration timer */
+ HAL_NODE_STATS sc_halstats; /* station-mode rssi stats */
+
diff --git a/package/madwifi/patches/451-ibss_race_fix.patch b/package/madwifi/patches/451-ibss_race_fix.patch
new file mode 100644
index 000000000..27e1b47da
--- /dev/null
+++ b/package/madwifi/patches/451-ibss_race_fix.patch
@@ -0,0 +1,342 @@
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -294,10 +294,10 @@ ieee80211_input(struct ieee80211vap * va
+ break;
+ case IEEE80211_M_IBSS:
+ case IEEE80211_M_AHDEMO:
+- if (!IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid) ||
++ if ((!IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid) ||
+ (!IEEE80211_ADDR_EQ(wh->i_addr1, vap->iv_myaddr) &&
+- !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
+- (subtype != IEEE80211_FC0_SUBTYPE_BEACON))) {
++ !IEEE80211_IS_MULTICAST(wh->i_addr1))) &&
++ (type == IEEE80211_FC0_TYPE_DATA)) {
+ if (!(vap->iv_dev->flags & IFF_PROMISC)) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
+ bssid, NULL, "%s", "not to bss");
+@@ -322,22 +322,15 @@ ieee80211_input(struct ieee80211vap * va
+ }
+ /* Do not try to find a node reference if the packet really did come from the BSS */
+ if (type == IEEE80211_FC0_TYPE_DATA && ni == vap->iv_bss &&
+- !IEEE80211_ADDR_EQ(vap->iv_bss->ni_macaddr, wh->i_addr2) &&
+ IEEE80211_ADDR_EQ(vap->iv_bssid, wh->i_addr3)) {
+ /* Try to find sender in local node table. */
+- ni = ieee80211_find_node(&ic->ic_sta, wh->i_addr2);
++ if (!ni_or_null) {
++ ieee80211_unref_node(&ni);
++ ni = ieee80211_find_txnode(vap, wh->i_addr2);
++ }
+ if (ni == NULL) {
+- /*
+- * Fake up a node for this newly discovered
+- * member of the IBSS. This should probably
+- * done after an ACL check.
+- */
+- ni = ieee80211_fakeup_adhoc_node(vap,
+- wh->i_addr2);
+- if (ni == NULL) {
+- /* NB: stat kept for alloc failure */
+- goto err;
+- }
++ /* NB: stat kept for alloc failure */
++ goto discard;
+ }
+ }
+ iwspy_event(vap, ni, rssi);
+@@ -3553,8 +3546,8 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ (((vap->iv_opmode == IEEE80211_M_HOSTAP) ||
+ (vap->iv_opmode == IEEE80211_M_WDS)) &&
+ (scan.capinfo & IEEE80211_CAPINFO_ESS))) {
++ struct ieee80211_node *tni = NULL;
+ struct ieee80211vap *avp = NULL;
+- int do_unref = 0;
+ int found = 0;
+
+ IEEE80211_LOCK_IRQ(vap->iv_ic);
+@@ -3570,14 +3563,12 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ }
+ }
+ if (found)
+- ni = ni_or_null = avp->iv_wdsnode;
++ tni = ieee80211_ref_node(avp->iv_wdsnode);
+ } else if ((vap->iv_opmode == IEEE80211_M_WDS) && vap->iv_wdsnode) {
+ found = 1;
+- ni = ni_or_null = vap->iv_wdsnode;
+- } else if (vap->iv_opmode == IEEE80211_M_IBSS) {
+- ni_or_null = ieee80211_find_node(&ic->ic_sta, wh->i_addr2);
+- if (ni_or_null)
+- ni = ni_or_null;
++ tni = ieee80211_ref_node(vap->iv_wdsnode);
++ } else if ((vap->iv_opmode == IEEE80211_M_IBSS) && (vap->iv_state == IEEE80211_S_RUN)) {
++ tni = ieee80211_find_node(&ic->ic_sta, wh->i_addr2);
+ found = 1;
+ }
+ IEEE80211_UNLOCK_IRQ(vap->iv_ic);
+@@ -3585,20 +3576,21 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ if (!found)
+ break;
+
+- if (ni_or_null == NULL) {
++ memcpy(&SKB_CB(skb)->beacon_tsf, scan.tstamp, sizeof(u_int64_t));
++
++ if (tni == NULL) {
+ if (avp) {
+ IEEE80211_LOCK_IRQ(ic);
+- ni = ieee80211_add_neighbor(avp, wh, &scan);
++ tni = ieee80211_add_neighbor(avp, wh, &scan);
+ /* force assoc */
+- ni->ni_associd |= 0xc000;
+- avp->iv_wdsnode = ieee80211_ref_node(ni);
++ tni->ni_associd |= 0xc000;
++ avp->iv_wdsnode = ieee80211_ref_node(tni);
+ IEEE80211_UNLOCK_IRQ(ic);
+ } else if ((vap->iv_opmode == IEEE80211_M_IBSS) &&
+ IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid)) {
+ /* Create a new entry in the neighbor table. */
+- ni = ieee80211_add_neighbor(vap, wh, &scan);
++ tni = ieee80211_add_neighbor(vap, wh, &scan);
+ }
+- do_unref = 1;
+ } else {
+ /*
+ * Copy data from beacon to neighbor table.
+@@ -3606,39 +3598,38 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ * ieee80211_add_neighbor(), so we just copy
+ * everything over to be safe.
+ */
+- ni->ni_esslen = scan.ssid[1];
+- memcpy(ni->ni_essid, scan.ssid + 2, scan.ssid[1]);
+- IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
+- memcpy(ni->ni_tstamp.data, scan.tstamp,
+- sizeof(ni->ni_tstamp));
+- ni->ni_inact = ni->ni_inact_reload;
+- ni->ni_intval =
++ tni->ni_esslen = scan.ssid[1];
++ memcpy(tni->ni_essid, scan.ssid + 2, scan.ssid[1]);
++ IEEE80211_ADDR_COPY(tni->ni_bssid, wh->i_addr3);
++ memcpy(tni->ni_tstamp.data, scan.tstamp,
++ sizeof(tni->ni_tstamp));
++ tni->ni_inact = tni->ni_inact_reload;
++ tni->ni_intval =
+ IEEE80211_BINTVAL_SANITISE(scan.bintval);
+- ni->ni_capinfo = scan.capinfo;
+- ni->ni_chan = ic->ic_curchan;
+- ni->ni_fhdwell = scan.fhdwell;
+- ni->ni_fhindex = scan.fhindex;
+- ni->ni_erp = scan.erp;
+- ni->ni_timoff = scan.timoff;
++ tni->ni_capinfo = scan.capinfo;
++ tni->ni_chan = ic->ic_curchan;
++ tni->ni_fhdwell = scan.fhdwell;
++ tni->ni_fhindex = scan.fhindex;
++ tni->ni_erp = scan.erp;
++ tni->ni_timoff = scan.timoff;
+ if (scan.wme != NULL)
+- ieee80211_saveie(&ni->ni_wme_ie, scan.wme);
++ ieee80211_saveie(&tni->ni_wme_ie, scan.wme);
+ if (scan.wpa != NULL)
+- ieee80211_saveie(&ni->ni_wpa_ie, scan.wpa);
++ ieee80211_saveie(&tni->ni_wpa_ie, scan.wpa);
+ if (scan.rsn != NULL)
+- ieee80211_saveie(&ni->ni_rsn_ie, scan.rsn);
++ ieee80211_saveie(&tni->ni_rsn_ie, scan.rsn);
+ if (scan.ath != NULL)
+- ieee80211_saveath(ni, scan.ath);
++ ieee80211_saveath(tni, scan.ath);
+
+ /* NB: must be after ni_chan is setup */
+- ieee80211_setup_rates(ni, scan.rates,
++ ieee80211_setup_rates(tni, scan.rates,
+ scan.xrates, IEEE80211_F_DOSORT);
+ }
+- if (ni != NULL) {
+- ni->ni_rssi = rssi;
+- ni->ni_rtsf = rtsf;
+- ni->ni_last_rx = jiffies;
+- if (do_unref)
+- ieee80211_unref_node(&ni);
++ if (tni != NULL) {
++ tni->ni_rssi = rssi;
++ tni->ni_rtsf = rtsf;
++ tni->ni_last_rx = jiffies;
++ ieee80211_unref_node(&tni);
+ }
+ }
+ break;
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -53,6 +53,7 @@
+
+ #include <net80211/ieee80211_var.h>
+ #include <net80211/if_athproto.h>
++#include <net80211/ieee80211_node.h>
+
+ /*
+ * Association IDs are managed with a bit vector.
+@@ -317,16 +318,11 @@ ieee80211_create_ibss(struct ieee80211va
+ /* Check to see if we already have a node for this mac
+ * NB: we gain a node reference here
+ */
+- ni = ieee80211_find_txnode(vap, vap->iv_myaddr);
++ ieee80211_node_table_reset(&ic->ic_sta, vap);
++ ni = ieee80211_alloc_node_table(vap, vap->iv_myaddr);
+ if (ni == NULL) {
+- ni = ieee80211_alloc_node_table(vap, vap->iv_myaddr);
+- IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,
+- "%s: ni:%p allocated for " MAC_FMT "\n",
+- __func__, ni, MAC_ADDR(vap->iv_myaddr));
+- if (ni == NULL) {
+- /* XXX recovery? */
+- return;
+- }
++ /* XXX recovery? */
++ return;
+ }
+
+ IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_myaddr);
+@@ -647,7 +643,7 @@ ieee80211_sta_join1(struct ieee80211_nod
+ (vap->iv_state == IEEE80211_S_RUN) && bssid_equal(obss, selbs)); */
+ vap->iv_bss = selbs;
+ IEEE80211_ADDR_COPY(vap->iv_bssid, selbs->ni_bssid);
+- if (obss != NULL) {
++ if ((obss != NULL) && (obss != selbs)) {
+ if (obss->ni_table)
+ ieee80211_node_leave(obss);
+ ieee80211_unref_node(&obss);
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -6625,14 +6625,6 @@ ath_recv_mgmt(struct ieee80211vap * vap,
+
+ sc->sc_recv_mgmt(vap, ni_or_null, skb, subtype, rssi, rtsf);
+
+- /* Lookup the new node if any (this grabs a reference to it) */
+- ni = ieee80211_find_rxnode(vap->iv_ic, vap,
+- (const struct ieee80211_frame_min *)skb->data);
+- if (ni == NULL) {
+- DPRINTF(sc, ATH_DEBUG_BEACON, "Dropping; node unknown.\n");
+- return;
+- }
+-
+ switch (subtype) {
+ case IEEE80211_FC0_SUBTYPE_BEACON:
+ /* update RSSI statistics for use by the HAL */
+@@ -6654,11 +6646,9 @@ ath_recv_mgmt(struct ieee80211vap * vap,
+ * we do the IBSS merging in software. Also do not merge
+ * if the difference it too small. Otherwise we are playing
+ * tsf-pingpong with other vendors drivers */
+- beacon_tsf = le64_to_cpu(ni->ni_tstamp.tsf);
+- if (beacon_tsf > rtsf + 0xffff) {
++ beacon_tsf = le64_to_cpu(SKB_CB(skb)->beacon_tsf);
++ if (beacon_tsf > rtsf + 0xffff)
+ ath_hal_settsf64(sc->sc_ah, beacon_tsf - rtsf);
+- ieee80211_ibss_merge(ni);
+- }
+ break;
+ }
+ /* NB: Fall Through */
+@@ -6680,13 +6670,21 @@ ath_recv_mgmt(struct ieee80211vap * vap,
+ hw_tsf = ath_hal_gettsf64(sc->sc_ah);
+ hw_tu = hw_tsf >> 10;
+
+- beacon_tsf = le64_to_cpu(ni->ni_tstamp.tsf);
++ beacon_tsf = le64_to_cpu(SKB_CB(skb)->beacon_tsf);
+ beacon_tu = beacon_tsf >> 10;
+
++ if (!beacon_tsf)
++ break;
++
++ if (IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid))
++ break;
++
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+- "Beacon transmitted at %10llx, "
++ "Beacon transmitted from "MAC_FMT" ("MAC_FMT") at %10llx, "
+ "received at %10llx(%lld), hw TSF "
+ "%10llx(%lld)\n",
++ MAC_ADDR(wh->i_addr3),
++ MAC_ADDR(vap->iv_bssid),
+ beacon_tsf,
+ rtsf, rtsf - beacon_tsf,
+ hw_tsf, hw_tsf - beacon_tsf);
+@@ -6699,39 +6697,13 @@ ath_recv_mgmt(struct ieee80211vap * vap,
+ do_merge = 1;
+ }
+
+- /* Check sc_nexttbtt */
+- if (sc->sc_nexttbtt < hw_tu) {
+- DPRINTF(sc, ATH_DEBUG_BEACON,
+- "sc_nexttbtt (%8x TU) is in the past "
+- "(tsf %8x TU), updating timers\n",
+- sc->sc_nexttbtt, hw_tu);
+- do_merge = 1;
+- }
+-
+- intval = ni->ni_intval & HAL_BEACON_PERIOD;
+-#if 0
+- /* This code is disabled since it would produce
+- * unwanted merge. For instance, in a two nodes network
+- * A & B, A can merge to B and at the same time, B will
+- * merge to A, still having a split */
+- if (intval != 0) {
+- if ((sc->sc_nexttbtt % intval) !=
+- (beacon_tu % intval)) {
+- DPRINTF(sc, ATH_DEBUG_BEACON,
+- "ibss merge: "
+- "sc_nexttbtt %10x TU "
+- "(%3d) beacon %10x TU "
+- "(%3d)\n",
+- sc->sc_nexttbtt,
+- sc->sc_nexttbtt % intval,
+- beacon_tu,
+- beacon_tu % intval);
+- do_merge = 1;
+- }
+- }
+-#endif
+- if (do_merge)
++ if (do_merge) {
++ /* Lookup the new node if any (this grabs a reference to it) */
++ ni = ieee80211_find_txnode(vap, wh->i_addr2);
++ memcpy(ni->ni_bssid, wh->i_addr3, IEEE80211_ADDR_LEN);
+ ieee80211_ibss_merge(ni);
++ ieee80211_unref_node(&ni);
++ }
+
+ if ((sc->sc_opmode == HAL_M_IBSS) &&
+ ath_hw_check_atim(sc, 1, vap->iv_bss->ni_intval))
+@@ -6739,8 +6711,6 @@ ath_recv_mgmt(struct ieee80211vap * vap,
+ }
+ break;
+ }
+-
+- ieee80211_unref_node(&ni);
+ }
+
+ static void
+--- a/net80211/ieee80211_linux.h
++++ b/net80211/ieee80211_linux.h
+@@ -411,7 +411,7 @@ typedef spinlock_t acl_lock_t;
+ * 8 bytes so we reserve/avoid it.
+ */
+ struct ieee80211_cb {
+- u_int8_t vlan[8]; /* reserve for vlan tag info */
++ u_int64_t beacon_tsf;
+ struct ieee80211_node *ni;
+ u_int32_t flags;
+ #define M_LINK0 0x01 /* frame needs WEP encryption */
+--- a/net80211/ieee80211_scan_sta.c
++++ b/net80211/ieee80211_scan_sta.c
+@@ -1125,11 +1125,8 @@ adhoc_default_action(struct ieee80211vap
+ u_int8_t zeroMacAddr[IEEE80211_ADDR_LEN];
+
+ memset(&zeroMacAddr, 0, IEEE80211_ADDR_LEN);
+- if (IEEE80211_ADDR_EQ(se->se_bssid, &zeroMacAddr[0])) {
+- ieee80211_create_ibss(vap, se->se_chan);
+- return 1;
+- } else
+- return ieee80211_sta_join(vap, se);
++ ieee80211_create_ibss(vap, se->se_chan);
++ return 1;
+ }
+
+ static const struct ieee80211_scanner adhoc_default = {
diff --git a/package/madwifi/patches/452-minstrel_no_timer.patch b/package/madwifi/patches/452-minstrel_no_timer.patch
new file mode 100644
index 000000000..f0f5c26f9
--- /dev/null
+++ b/package/madwifi/patches/452-minstrel_no_timer.patch
@@ -0,0 +1,134 @@
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -119,6 +119,7 @@
+ #include "minstrel.h"
+
+ #define ONE_SECOND (1000 * 1000) /* 1 second, or 1000 milliseconds; eternity, in other words */
++#define TIMER_INTERVAL 100 /* msecs */
+
+ #include "release.h"
+
+@@ -128,9 +129,6 @@ static char *dev_info = "ath_rate_minstr
+ #define STALE_FAILURE_TIMEOUT_MS 10000
+ #define ENABLE_MRR 1
+
+-static int ath_timer_interval = (1000 / 10); /* every 1/10 second, timer runs */
+-static void ath_timer_function(unsigned long data);
+-
+ /* 10% of the time, send a packet at something other than the optimal rate, which fills
+ * the statistics tables nicely. This percentage is applied to the first packet of the
+ * multi rate retry chain. */
+@@ -142,7 +140,7 @@ static void ath_rate_ctl_reset(struct at
+ /* Calculate the throughput and probability of success for each node
+ * we are talking on, based on the statistics collected during the
+ * last timer period. */
+-static void ath_rate_statistics(void *arg, struct ieee80211_node *ni);
++static void ath_rate_statistics(struct ieee80211_node *ni);
+
+
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))
+@@ -204,6 +202,11 @@ ath_rate_findrate(struct ath_softc *sc,
+ unsigned int ndx, offset;
+ int mrr;
+
++
++ if (abs(jiffies - sn->last_update) > msecs_to_jiffies(TIMER_INTERVAL)) {
++ ath_rate_statistics(&an->an_node);
++ sn->last_update = jiffies;
++ }
+ if (sn->num_rates <= 0) {
+ printk(KERN_WARNING "%s: no rates for " MAC_FMT "?\n",
+ dev_info,
+@@ -640,54 +643,11 @@ ath_rate_newstate(struct ieee80211vap *v
+ }
+ }
+
+-static void
+-ath_timer_function(unsigned long data)
+-{
+- struct minstrel_softc *ssc = (struct minstrel_softc *) data;
+- struct ath_softc *sc = ssc->sc;
+- struct ieee80211com *ic;
+- struct net_device *dev = ssc->sc_dev;
+- struct timer_list *timer;
+- unsigned int interval = ath_timer_interval;
+-
+- if (dev == NULL)
+- DPRINTF(sc, ATH_DEBUG_RATE, "%s: 'dev' is null in this timer \n", __func__);
+-
+- if (sc == NULL)
+- DPRINTF(sc, ATH_DEBUG_RATE, "%s: 'sc' is null in this timer\n", __func__);
+-
+- ic = &sc->sc_ic;
+-
+- if (ssc->close_timer_now)
+- return;
+-
+- if (dev->flags & IFF_RUNNING) {
+- sc->sc_stats.ast_rate_calls++;
+-
+- if (ic->ic_opmode == IEEE80211_M_STA) {
+- struct ieee80211vap *tmpvap;
+- TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
+- ath_rate_statistics(sc, tmpvap->iv_bss);/* NB: no reference */
+- }
+- } else
+- ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_statistics, sc);
+- }
+-
+- if (ic->ic_opmode == IEEE80211_M_STA)
+- interval = ath_timer_interval >> 1;
+-
+- timer = &(ssc->timer);
+- if (timer == NULL)
+- DPRINTF(sc, ATH_DEBUG_RATE, "%s: timer is null - leave it\n", __func__);
+-
+- timer->expires = jiffies + ((HZ * interval) / 1000);
+- add_timer(timer);
+-}
+
+ static void
+-ath_rate_statistics(void *arg, struct ieee80211_node *ni)
++ath_rate_statistics(struct ieee80211_node *ni)
+ {
+- struct ath_node *an = (struct ath_node *) ni;
++ struct ath_node *an = ATH_NODE(ni);
+ struct ieee80211_rateset *rs = &ni->ni_rates;
+ struct minstrel_node *rn = ATH_NODE_MINSTREL(an);
+ unsigned int i;
+@@ -786,15 +746,8 @@ ath_rate_attach(struct ath_softc *sc)
+ osc->arc.arc_space = sizeof(struct minstrel_node);
+ osc->arc.arc_vap_space = 0;
+
+- osc->close_timer_now = 0;
+- init_timer(&osc->timer);
+ osc->sc = sc;
+ osc->sc_dev = sc->sc_dev;
+- osc->timer.function = ath_timer_function;
+- osc->timer.data = (unsigned long)osc;
+-
+- osc->timer.expires = jiffies + HZ;
+- add_timer(&osc->timer);
+
+ return &osc->arc;
+ }
+@@ -803,8 +756,6 @@ static void
+ ath_rate_detach(struct ath_ratectrl *arc)
+ {
+ struct minstrel_softc *osc = (struct minstrel_softc *) arc;
+- osc->close_timer_now = 1;
+- del_timer(&osc->timer);
+ kfree(osc);
+ _MOD_DEC_USE(THIS_MODULE);
+ }
+--- a/ath_rate/minstrel/minstrel.h
++++ b/ath_rate/minstrel/minstrel.h
+@@ -167,6 +167,8 @@ struct minstrel_node {
+ packet, or a packet at an optimal rate.*/
+ int random_n;
+ int a, b; /**Coefficients of the random thing */
++
++ unsigned long last_update;
+ };
+
+
diff --git a/package/madwifi/patches/453-procps.patch b/package/madwifi/patches/453-procps.patch
new file mode 100644
index 000000000..5a5633b1c
--- /dev/null
+++ b/package/madwifi/patches/453-procps.patch
@@ -0,0 +1,55 @@
+--- a/net80211/ieee80211_linux.h
++++ b/net80211/ieee80211_linux.h
+@@ -640,12 +640,24 @@ static __inline unsigned long msecs_to_j
+ 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_PROC_DOSTRING(ctl, write, filp, buffer, lenp, ppos) \
++ proc_dostring(ctl, write, filp, buffer, lenp)
++#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
+ #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)
++#define IEEE80211_SYSCTL_PROC_DOSTRING(ctl, write, filp, buffer, lenp, ppos) \
++ proc_dostring(ctl, write, filp, buffer, lenp, ppos)
++#else /* Linux 2.6.32+ */
++#define IEEE80211_SYSCTL_DECL(f, ctl, write, filp, buffer, lenp, ppos) \
++ f(ctl_table *ctl, int write, \
++ void __user *buffer, size_t *lenp, loff_t *ppos)
++#define IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos) \
++ proc_dointvec(ctl, write, buffer, lenp, ppos)
++#define IEEE80211_SYSCTL_PROC_DOSTRING(ctl, write, filp, buffer, lenp, ppos) \
++ proc_dostring(ctl, write, buffer, lenp, ppos)
+ #endif
+
+ void ieee80211_virtfs_latevattach(struct ieee80211vap *);
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -173,14 +173,22 @@ static inline struct net_device *_alloc_
+ proc_dointvec(ctl, write, filp, buffer, lenp)
+ #define ATH_SYSCTL_PROC_DOSTRING(ctl, write, filp, buffer, lenp, ppos) \
+ proc_dostring(ctl, write, filp, buffer, lenp)
+-#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) */
++#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
+ #define ATH_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 ATH_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos) \
+ proc_dointvec(ctl, write, filp, buffer, lenp, ppos)
++#define ATH_SYSCTL_PROC_DOSTRING(ctl, write, filp, buffer, lenp, ppos) \
++ proc_dostring(ctl, write, filp, buffer, lenp, ppos)
++#else /* Linux 2.6.32+ */
++#define ATH_SYSCTL_DECL(f, ctl, write, filp, buffer, lenp, ppos) \
++ f(ctl_table *ctl, int write, \
++ void __user *buffer, size_t *lenp, loff_t *ppos)
++#define ATH_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos) \
++ proc_dointvec(ctl, write, buffer, lenp, ppos)
+ #define ATH_SYSCTL_PROC_DOSTRING(ctl, write, filp, buffer, lenp, ppos) \
+- proc_dostring(ctl, write, filp, buffer, lenp, ppos)
++ proc_dostring(ctl, write, buffer, lenp, ppos)
+ #endif
+
+ #define ATH_TIMEOUT 1000
diff --git a/package/madwifi/patches/454-cca.patch b/package/madwifi/patches/454-cca.patch
new file mode 100644
index 000000000..53792cc8f
--- /dev/null
+++ b/package/madwifi/patches/454-cca.patch
@@ -0,0 +1,186 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -383,6 +383,8 @@ static void ath_poll_disable(struct net_
+ static void ath_poll_enable(struct net_device *dev);
+ static void ath_fetch_idle_time(struct ath_softc *sc);
+ static void ath_set_timing(struct ath_softc *sc);
++static void ath_update_cca_thresh(struct ath_softc *sc);
++static int ath_hw_read_nf(struct ath_softc *sc);
+
+ /* calibrate every 30 secs in steady state but check every second at first. */
+ static int ath_calinterval = ATH_SHORT_CALINTERVAL;
+@@ -2623,6 +2625,10 @@ ath_init(struct net_device *dev)
+ goto done;
+ }
+
++ ath_hal_process_noisefloor(ah);
++ ic->ic_channoise = ath_hal_get_channel_noise(ah, &(sc->sc_curchan));
++ ath_update_cca_thresh(sc);
++
+ if (sc->sc_softled)
+ ath_hal_gpioCfgOutput(ah, sc->sc_ledpin);
+
+@@ -3024,6 +3030,10 @@ ath_reset(struct net_device *dev)
+ EPRINTF(sc, "Unable to reset hardware: '%s' (HAL status %u)\n",
+ ath_get_hal_status_desc(status), status);
+
++ ath_hal_process_noisefloor(ah);
++ ic->ic_channoise = ath_hal_get_channel_noise(ah, &(sc->sc_curchan));
++ ath_update_cca_thresh(sc);
++
+ ath_setintmit(sc);
+ ath_update_txpow(sc); /* update tx power state */
+ ath_radar_update(sc);
+@@ -9374,9 +9384,11 @@ ath_calibrate(unsigned long arg)
+ 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);
++ ic->ic_channoise = ath_hal_get_channel_noise(ah, &(sc->sc_curchan));
++ ath_update_cca_thresh(sc);
++
+ if (isIQdone == AH_TRUE) {
+ /* Unless user has overridden calibration interval,
+ * upgrade to less frequent calibration */
+@@ -9711,8 +9723,6 @@ ath_newstate(struct ieee80211vap *vap, e
+ break;
+ }
+
+- 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...
+ */
+@@ -10968,6 +10978,7 @@ enum {
+ ATH_INTMIT,
+ ATH_NOISE_IMMUNITY,
+ ATH_OFDM_WEAK_DET,
++ ATH_CCA_THRESH,
+ ATH_CHANBW,
+ ATH_OUTDOOR,
+ ATH_DISTANCE,
+@@ -11110,6 +11121,66 @@ ath_sysctl_get_intmit(struct ath_softc *
+ return 0;
+ }
+
++#define AR_PHY_CCA 0x9864
++#define AR_PHY_MINCCA_PWR 0x0FF80000
++#define AR_PHY_MINCCA_PWR_S 19
++#define AR_PHY_CCA_THRESH62 0x0007F000
++#define AR_PHY_CCA_THRESH62_S 12
++
++static int
++ath_nf_from_cca(u32 phy_cca)
++{
++ int nf = (phy_cca >> 19) & 0x1ff;
++ nf = -((nf ^ 0x1ff) + 1);
++ return nf;
++}
++
++static int
++ath_hw_read_nf(struct ath_softc *sc)
++{
++ return ath_nf_from_cca(OS_REG_READ(sc->sc_ah, AR_PHY_CCA));
++}
++
++static void
++ath_update_cca_thresh(struct ath_softc *sc)
++{
++ struct ath_hal *ah = sc->sc_ah;
++ int newthr = 0;
++ u32 phy_cca;
++ int nf;
++
++ phy_cca = OS_REG_READ(ah, AR_PHY_CCA);
++ if (sc->sc_cca_thresh < 0) {
++ newthr = sc->sc_cca_thresh - ath_nf_from_cca(phy_cca);
++
++ /* 0xf is a typical eeprom value for thresh62,
++ * use it as minimum for signal based thresholds
++ * to prevent complete connection drops */
++ if (newthr < 0xf)
++ newthr = 0xf;
++ } else {
++ newthr = sc->sc_cca_thresh;
++ }
++
++ if ((newthr < 4) || (newthr >= 127))
++ return;
++
++ phy_cca &= ~AR_PHY_CCA_THRESH62;
++ phy_cca |= newthr << AR_PHY_CCA_THRESH62_S;
++ OS_REG_WRITE(ah, AR_PHY_CCA, phy_cca);
++}
++
++static int
++ath_get_cca_thresh(struct ath_softc *sc)
++{
++ struct ath_hal *ah = sc->sc_ah;
++ u32 phy_cca;
++
++ phy_cca = OS_REG_READ(ah, AR_PHY_CCA);
++ return ath_nf_from_cca(phy_cca) +
++ ((phy_cca & AR_PHY_CCA_THRESH62) >> AR_PHY_CCA_THRESH62_S);
++}
++
+ static int
+ ATH_SYSCTL_DECL(ath_sysctl_hwinfo, ctl, write, filp, buffer, lenp, ppos)
+ {
+@@ -11356,6 +11427,10 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+ case ATH_OFDM_WEAK_DET:
+ ret = ath_sysctl_set_intmit(sc, (long)ctl->extra2, val);
+ break;
++ case ATH_CCA_THRESH:
++ sc->sc_cca_thresh = val;
++ ath_update_cca_thresh(sc);
++ break;
+ default:
+ ret = -EINVAL;
+ break;
+@@ -11436,6 +11511,9 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+ case ATH_OFDM_WEAK_DET:
+ ret = ath_sysctl_get_intmit(sc, (long)ctl->extra2, &val);
+ break;
++ case ATH_CCA_THRESH:
++ val = ath_get_cca_thresh(sc);
++ break;
+ default:
+ ret = -EINVAL;
+ break;
+@@ -11667,6 +11745,12 @@ static const ctl_table ath_sysctl_templa
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_OFDM_WEAK_DET,
+ },
++ { .ctl_name = CTL_AUTO,
++ .procname = "cca_thresh",
++ .mode = 0644,
++ .proc_handler = ath_sysctl_halparam,
++ .extra2 = (void *)ATH_CCA_THRESH,
++ },
+ { 0 }
+ };
+
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -844,6 +844,7 @@ struct ath_softc {
+ int sc_cal_interval; /* current calibration interval */
+ struct timer_list sc_cal_ch; /* calibration timer */
+ HAL_NODE_STATS sc_halstats; /* station-mode rssi stats */
++ int sc_cca_thresh; /* configured CCA threshold */
+
+ struct ctl_table_header *sc_sysctl_header;
+ struct ctl_table *sc_sysctls;
+--- a/ath/ath_wprobe.c
++++ b/ath/ath_wprobe.c
+@@ -133,8 +133,7 @@ ath_wprobe_sync(struct wprobe_iface *dev
+ rx = READ_CLR(ah, AR5K_RXFC);
+ tx = READ_CLR(ah, AR5K_TXFC);
+ OS_REG_WRITE(ah, AR5K_MIBC, 0);
+- noise = ath_hal_get_channel_noise(sc->sc_ah, &(sc->sc_curchan));
+- ic->ic_channoise = noise;
++ noise = ath_hw_read_nf(sc);
+
+ WPROBE_FILL_BEGIN(val, ath_wprobe_globals);
+ if (cc & 0xf0000000) {
diff --git a/package/madwifi/patches/455-beacon_watchdog.patch b/package/madwifi/patches/455-beacon_watchdog.patch
new file mode 100644
index 000000000..d0b4fa63e
--- /dev/null
+++ b/package/madwifi/patches/455-beacon_watchdog.patch
@@ -0,0 +1,95 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -379,6 +379,7 @@ static u_int32_t ath_get_clamped_maxtxpo
+ static u_int32_t ath_set_clamped_maxtxpower(struct ath_softc *sc,
+ u_int32_t new_clamped_maxtxpower);
+
++static void ath_bcn_timer(unsigned long arg);
+ static void ath_poll_disable(struct net_device *dev);
+ static void ath_poll_enable(struct net_device *dev);
+ static void ath_fetch_idle_time(struct ath_softc *sc);
+@@ -829,6 +830,10 @@ ath_attach(u_int16_t devid, struct net_d
+ sc->sc_cal_ch.function = ath_calibrate;
+ sc->sc_cal_ch.data = (unsigned long) dev;
+
++ init_timer(&sc->sc_bcntimer);
++ sc->sc_bcntimer.function = ath_bcn_timer;
++ sc->sc_bcntimer.data = (unsigned long) dev;
++
+ /* initialize DFS related variables */
+ sc->sc_dfswait = 0;
+ sc->sc_dfs_cac = 0;
+@@ -2704,6 +2709,7 @@ ath_stop_locked(struct net_device *dev)
+ DPRINTF(sc, ATH_DEBUG_RESET, "invalid=%u flags=0x%x\n",
+ sc->sc_invalid, dev->flags);
+
++ del_timer_sync(&sc->sc_bcntimer);
+ if (dev->flags & IFF_RUNNING) {
+ /*
+ * Shutdown the hardware and driver:
+@@ -3006,6 +3012,7 @@ ath_reset(struct net_device *dev)
+ struct ieee80211_channel *c;
+ HAL_STATUS status;
+
++ del_timer_sync(&sc->sc_bcntimer);
+ /*
+ * XXX: starting the calibration too early seems to lead to
+ * problems with the beacons.
+@@ -5305,6 +5312,7 @@ ath_beacon_send(struct ath_softc *sc, in
+ if (ath_chan_unavail_dbgmsg(sc))
+ return;
+
++ mod_timer(&sc->sc_bcntimer, jiffies + sc->sc_bcntimer_reload);
+ /*
+ * Check if the previous beacon has gone out. If
+ * not don't try to post another, skip this period
+@@ -5487,6 +5495,18 @@ ath_beacon_free(struct ath_softc *sc)
+ cleanup_ath_buf(sc, bf, BUS_DMA_TODEVICE);
+ }
+
++static void ath_bcn_timer(unsigned long arg)
++{
++ struct net_device *dev = (struct net_device *)arg;
++ struct ath_softc *sc = netdev_priv(dev);
++ struct ath_hal *ah = sc->sc_ah;
++
++ if (!sc->sc_beacons)
++ return;
++
++ ath_reset(dev);
++}
++
+ /*
+ * Configure the beacon and sleep timers.
+ *
+@@ -5523,6 +5543,7 @@ ath_beacon_config(struct ath_softc *sc,
+ if (vap == NULL)
+ vap = TAILQ_FIRST(&ic->ic_vaps); /* XXX */
+
++ del_timer_sync(&sc->sc_bcntimer);
+ ni = vap->iv_bss;
+
+ /* TSF calculation is timing critical - we don't want to be interrupted here */
+@@ -5699,6 +5720,9 @@ ath_beacon_config(struct ath_softc *sc,
+ sc->sc_imask |= HAL_INT_SWBA;
+ ath_set_beacon_cal(sc, 1);
+ ath_beaconq_config(sc);
++
++ sc->sc_bcntimer_reload = msecs_to_jiffies(10 * (intval & HAL_BEACON_PERIOD));
++ mod_timer(&sc->sc_bcntimer, jiffies + sc->sc_bcntimer_reload);
+ } else
+ ath_set_beacon_cal(sc, 0);
+
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -789,6 +789,10 @@ struct ath_softc {
+ u_int16_t sc_ledoff; /* off time for current blink */
+ struct timer_list sc_ledtimer; /* led off timer */
+
++ /* beacon watchdog timer */
++ u_int32_t sc_bcntimer_reload;
++ struct timer_list sc_bcntimer;
++
+ struct ATH_TQ_STRUCT sc_fataltq; /* fatal error intr tasklet */
+
+ int sc_rxbufsize; /* rx size based on mtu */
diff --git a/package/madwifi/patches/456-rfsilent.patch b/package/madwifi/patches/456-rfsilent.patch
new file mode 100644
index 000000000..21031e7ca
--- /dev/null
+++ b/package/madwifi/patches/456-rfsilent.patch
@@ -0,0 +1,85 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -2996,6 +2996,19 @@ ath_fetch_idle_time(struct ath_softc *sc
+ #undef AR5K_RXCLEAR
+ #undef AR5K_CYCLES
+
++static void
++ath_set_silent(struct ath_softc *sc)
++{
++ struct ath_hal *ah = sc->sc_ah;
++
++ if (!sc->sc_silent)
++ return;
++
++ del_timer_sync(&sc->sc_bcntimer);
++ ath_hal_intrset(ah, 0);
++ OS_REG_WRITE(ah, 0x8048, 0x60); /* set tx loopback and rx disable */
++}
++
+ /*
+ * Reset the hardware w/o losing operational state. This is
+ * basically a more efficient way of doing ath_stop, ath_init,
+@@ -3073,6 +3086,7 @@ ath_reset(struct net_device *dev)
+ ath_grppoll_start(vap, sc->sc_xrpollcount);
+ }
+ #endif
++ ath_set_silent(sc);
+ return 0;
+ }
+
+@@ -10972,6 +10986,7 @@ enum {
+ * mirrored in /proc/sys.
+ */
+ enum {
++ ATH_SILENT,
+ ATH_SLOTTIME,
+ ATH_ACKTIMEOUT,
+ ATH_CTSTIMEOUT,
+@@ -11294,6 +11309,13 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+ sc->sc_ctstimeconf = 0;
+ ath_set_timing(sc);
+ break;
++ case ATH_SILENT:
++ sc->sc_silent = !!val;
++ if (val)
++ ath_set_silent(sc);
++ else
++ ath_reset(sc->sc_dev);
++ break;
+ case ATH_DISTANCE:
+ if (val > 0) {
+ sc->sc_coverage = ((val - 1) / 300) + 1;
+@@ -11477,6 +11499,9 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+ case ATH_CTSTIMEOUT:
+ val = ath_hal_getctstimeout(ah);
+ break;
++ case ATH_SILENT:
++ val = sc->sc_silent;
++ break;
+ case ATH_SOFTLED:
+ val = sc->sc_softled;
+ break;
+@@ -11598,6 +11623,12 @@ static const ctl_table ath_sysctl_templa
+ .extra2 = (void *)ATH_DISTANCE,
+ },
+ { .ctl_name = CTL_AUTO,
++ .procname = "silent",
++ .mode = 0644,
++ .proc_handler = ath_sysctl_halparam,
++ .extra2 = (void *)ATH_SILENT,
++ },
++ { .ctl_name = CTL_AUTO,
+ .procname = "softled",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -737,6 +737,7 @@ struct ath_softc {
+ * 'channel availability check' indefinately,
+ * reporting radar and interference detections.
+ */
++ unsigned int sc_silent:1; /* Turn RF silent */
+ unsigned int sc_txcont_power; /* Continuous transmit power in 0.5dBm units */
+ unsigned int sc_txcont_rate; /* Continuous transmit rate in Mbps */
+
diff --git a/package/madwifi/patches/457-idletime.patch b/package/madwifi/patches/457-idletime.patch
new file mode 100644
index 000000000..429da8522
--- /dev/null
+++ b/package/madwifi/patches/457-idletime.patch
@@ -0,0 +1,151 @@
+--- a/net80211/ieee80211.c
++++ b/net80211/ieee80211.c
+@@ -355,6 +355,8 @@ ieee80211_ifattach(struct ieee80211com *
+ /* Arbitrarily pick the first channel */
+ ic->ic_curchan = &ic->ic_channels[0];
+
++ ic->ic_inact_tick = IEEE80211_INACT_WAIT;
++
+ /* Enable marking of dfs by default */
+ ic->ic_flags_ext |= IEEE80211_FEXT_MARKDFS;
+
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -350,6 +350,7 @@ struct ieee80211com {
+ 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 */
++ u_int16_t ic_inact_tick; /* inact timer tick interval (seconds) */
+
+ /* Channel state:
+ *
+--- a/net80211/ieee80211_ioctl.h
++++ b/net80211/ieee80211_ioctl.h
+@@ -591,6 +591,7 @@ enum {
+ 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_INACT_TICK = 27, /* station inactivity timer tick (seconds) */
+ 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 */
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -2504,13 +2504,18 @@ ieee80211_ioctl_setparam(struct net_devi
+ vap->iv_flags &= ~IEEE80211_F_NOBRIDGE;
+ break;
+ case IEEE80211_PARAM_INACT:
+- vap->iv_inact_run = value / IEEE80211_INACT_WAIT;
++ vap->iv_inact_run = value / ic->ic_inact_tick;
++ break;
++ case IEEE80211_PARAM_INACT_TICK:
++ if (value <= 0)
++ return -EINVAL;
++ ic->ic_inact_tick = value;
+ break;
+ case IEEE80211_PARAM_INACT_AUTH:
+- vap->iv_inact_auth = value / IEEE80211_INACT_WAIT;
++ vap->iv_inact_auth = value / ic->ic_inact_tick;
+ break;
+ case IEEE80211_PARAM_INACT_INIT:
+- vap->iv_inact_init = value / IEEE80211_INACT_WAIT;
++ vap->iv_inact_init = value / ic->ic_inact_tick;
+ break;
+ case IEEE80211_PARAM_ABOLT:
+ caps = 0;
+@@ -3050,13 +3055,16 @@ ieee80211_ioctl_getparam(struct net_devi
+ param[0] = (vap->iv_flags & IEEE80211_F_NOBRIDGE) == 0;
+ break;
+ case IEEE80211_PARAM_INACT:
+- param[0] = vap->iv_inact_run * IEEE80211_INACT_WAIT;
++ param[0] = vap->iv_inact_run * ic->ic_inact_tick;
+ break;
+ case IEEE80211_PARAM_INACT_AUTH:
+- param[0] = vap->iv_inact_auth * IEEE80211_INACT_WAIT;
++ param[0] = vap->iv_inact_auth * ic->ic_inact_tick;
+ break;
+ case IEEE80211_PARAM_INACT_INIT:
+- param[0] = vap->iv_inact_init * IEEE80211_INACT_WAIT;
++ param[0] = vap->iv_inact_init * ic->ic_inact_tick;
++ break;
++ case IEEE80211_PARAM_INACT_TICK:
++ param[0] = ic->ic_inact_tick;
+ break;
+ case IEEE80211_PARAM_ABOLT:
+ /*
+@@ -4557,14 +4565,7 @@ get_sta_info(void *arg, struct ieee80211
+ si->isi_opmode = IEEE80211_STA_OPMODE_XR;
+ else
+ si->isi_opmode = IEEE80211_STA_OPMODE_NORMAL;
+- /* NB: leave all cases in case we relax ni_associd == 0 check */
+- if (ieee80211_node_is_authorized(ni))
+- si->isi_inact = vap->iv_inact_run;
+- else if (ni->ni_associd != 0)
+- si->isi_inact = vap->iv_inact_auth;
+- else
+- si->isi_inact = vap->iv_inact_init;
+- si->isi_inact = (si->isi_inact - ni->ni_inact) * IEEE80211_INACT_WAIT;
++ si->isi_inact = (ni->ni_inact_reload - ni->ni_inact) * ic->ic_inact_tick;
+
+ cp = (u_int8_t *)(si+1);
+ if (ni->ni_rsn_ie != NULL) {
+@@ -5597,6 +5598,10 @@ static const struct iw_priv_args ieee802
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "inact_init" },
+ { IEEE80211_PARAM_INACT_INIT,
+ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_inact_init" },
++ { IEEE80211_PARAM_INACT_TICK,
++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "inact_tick" },
++ { IEEE80211_PARAM_INACT_TICK,
++ 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_inact_tick" },
+ { IEEE80211_PARAM_ABOLT,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "abolt" },
+ { IEEE80211_PARAM_ABOLT,
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -137,7 +137,7 @@ ieee80211_node_attach(struct ieee80211co
+ init_timer(&ic->ic_inact);
+ ic->ic_inact.function = ieee80211_node_timeout;
+ ic->ic_inact.data = (unsigned long) ic;
+- ic->ic_inact.expires = jiffies + IEEE80211_INACT_WAIT * HZ;
++ ic->ic_inact.expires = jiffies + ic->ic_inact_tick * HZ;
+ add_timer(&ic->ic_inact);
+
+ #ifdef IEEE80211_DEBUG_REFCNT
+@@ -261,7 +261,7 @@ void
+ ieee80211_node_authorize(struct ieee80211_node *ni)
+ {
+ ni->ni_flags |= IEEE80211_NODE_AUTH;
+- ni->ni_inact_reload = ni->ni_vap->iv_inact_run;
++ ni->ni_inact = ni->ni_inact_reload = ni->ni_vap->iv_inact_run;
+ }
+ EXPORT_SYMBOL(ieee80211_node_authorize);
+
+@@ -1819,7 +1819,7 @@ ieee80211_node_timeout(unsigned long arg
+ }
+ }
+
+- ic->ic_inact.expires = jiffies + IEEE80211_INACT_WAIT * HZ;
++ ic->ic_inact.expires = jiffies + ic->ic_inact_tick * HZ;
+ add_timer(&ic->ic_inact);
+ }
+
+--- a/net80211/ieee80211_power.c
++++ b/net80211/ieee80211_power.c
+@@ -148,7 +148,7 @@ ieee80211_node_saveq_age(struct ieee8021
+
+ IEEE80211_NODE_SAVEQ_LOCK_IRQ(ni);
+ while ((skb = skb_peek(&ni->ni_savedq)) != NULL &&
+- M_AGE_GET(skb) < IEEE80211_INACT_WAIT) {
++ M_AGE_GET(skb) < ni->ni_vap->iv_ic->ic_inact_tick) {
+ IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
+ "discard frame, age %u", M_AGE_GET(skb));
+
+@@ -159,7 +159,7 @@ ieee80211_node_saveq_age(struct ieee8021
+ discard++;
+ }
+ if (skb != NULL)
+- M_AGE_SUB(skb, IEEE80211_INACT_WAIT);
++ M_AGE_SUB(skb, ni->ni_vap->iv_ic->ic_inact_tick);
+ IEEE80211_NODE_SAVEQ_UNLOCK_IRQ(ni);
+
+ IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
diff --git a/package/madwifi/patches/458-ibss_wpa_none.patch b/package/madwifi/patches/458-ibss_wpa_none.patch
new file mode 100644
index 000000000..df77510b2
--- /dev/null
+++ b/package/madwifi/patches/458-ibss_wpa_none.patch
@@ -0,0 +1,13 @@
+--- a/net80211/ieee80211_crypto_ccmp.c
++++ b/net80211/ieee80211_crypto_ccmp.c
+@@ -273,7 +273,9 @@ ccmp_decap(struct ieee80211_key *k, stru
+ tid = ((struct ieee80211_qosframe *)wh)->i_qos[0] & IEEE80211_QOS_TID;
+ /* NB: assume IEEE80211_WEP_MINLEN covers the extended IV */
+ pn = READ_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]);
+- if (pn && pn <= k->wk_keyrsc[tid]) {
++ if ((vap->iv_opmode != IEEE80211_M_IBSS) &&
++ (vap->iv_opmode != IEEE80211_M_AHDEMO) &&
++ (pn && pn <= k->wk_keyrsc[tid])) {
+ /*
+ * Replay violation.
+ */
diff --git a/package/madwifi/patches/459-2.6.33_compile.patch b/package/madwifi/patches/459-2.6.33_compile.patch
new file mode 100644
index 000000000..4e08a011a
--- /dev/null
+++ b/package/madwifi/patches/459-2.6.33_compile.patch
@@ -0,0 +1,524 @@
+--- a/kernelversion.c
++++ b/kernelversion.c
+@@ -10,7 +10,11 @@
+
+ /* Linux 2.6.18+ uses <linux/utsrelease.h> */
+ #ifndef UTS_RELEASE
+-#include <linux/utsrelease.h>
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)
++ #include <generated/utsrelease.h>
++ #else
++ #include <linux/utsrelease.h>
++ #endif
+ #endif
+
+ char *uts_release = UTS_RELEASE;
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -11580,227 +11580,231 @@ static int mincalibrate = 1; /* once a
+ static int maxint = 0x7fffffff; /* 32-bit big */
+
+ static const ctl_table ath_sysctl_template[] = {
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "dev_vendor",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_hwinfo,
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
+ .strategy = &sysctl_string,
++#endif
+ .data = "N/A",
+ .maxlen = 1,
+ .extra2 = (void *)ATH_CARD_VENDOR,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "dev_name",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_hwinfo,
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
+ .strategy = &sysctl_string,
++#endif
+ .data = "N/A",
+ .maxlen = 1,
+ .extra2 = (void *)ATH_CARD_NAME,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "slottime",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_SLOTTIME,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "acktimeout",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_ACKTIMEOUT,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "ctstimeout",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_CTSTIMEOUT,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "distance",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_DISTANCE,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "silent",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_SILENT,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "softled",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_SOFTLED,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "ledpin",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_LEDPIN,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "countrycode",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_COUNTRYCODE,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "outdoor",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_OUTDOOR,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "regdomain",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_REGDOMAIN,
+ },
+ #ifdef AR_DEBUG
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "debug",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_DEBUG,
+ },
+ #endif
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "poweroffset",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_POWEROFFSET,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "txantenna",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_TXANTENNA,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "rxantenna",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_RXANTENNA,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "diversity",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_DIVERSITY,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "txintrperiod",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_TXINTRPERIOD,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "fftxqmin",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_FFTXQMIN,
+ },
+ #ifdef ATH_SUPERG_XR
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "xrpollperiod",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_XR_POLL_PERIOD,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "xrpollcount",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_XR_POLL_COUNT,
+ },
+ #endif
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "ackrate",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_ACKRATE,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "channelbw",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_CHANBW,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "rp",
+ .mode = 0200,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_RP,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "radar_print",
+ .mode = 0200,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_RP_PRINT,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "radar_print_all",
+ .mode = 0200,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_RP_PRINT_ALL,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "radar_dump",
+ .mode = 0200,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_RP_PRINT_MEM,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "radar_dump_all",
+ .mode = 0200,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_RP_PRINT_MEM_ALL,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "rp_flush",
+ .mode = 0200,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_RP_FLUSH,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "panic",
+ .mode = 0200,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_PANIC,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "rp_ignored",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_RP_IGNORED,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "radar_ignored",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_RADAR_IGNORED,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "intmit",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_INTMIT,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "noise_immunity",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_NOISE_IMMUNITY,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "ofdm_weak_det",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+ .extra2 = (void *)ATH_OFDM_WEAK_DET,
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "cca_thresh",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+@@ -11838,12 +11842,16 @@ ath_dynamic_sysctl_register(struct ath_s
+
+ /* setup the table */
+ memset(sc->sc_sysctls, 0, space);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
+ sc->sc_sysctls[0].ctl_name = CTL_DEV;
++#endif
+ sc->sc_sysctls[0].procname = "dev";
+ sc->sc_sysctls[0].mode = 0555;
+ sc->sc_sysctls[0].child = &sc->sc_sysctls[2];
+ /* [1] is NULL terminator */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
+ sc->sc_sysctls[2].ctl_name = CTL_AUTO;
++#endif
+ sc->sc_sysctls[2].procname = dev_name;
+ sc->sc_sysctls[2].mode = 0555;
+ sc->sc_sysctls[2].child = &sc->sc_sysctls[4];
+@@ -11966,7 +11974,7 @@ ath_announce(struct net_device *dev)
+ */
+ static ctl_table ath_static_sysctls[] = {
+ #ifdef AR_DEBUG
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "debug",
+ .mode = 0644,
+ .data = &ath_debug,
+@@ -11974,14 +11982,14 @@ static ctl_table ath_static_sysctls[] =
+ .proc_handler = proc_dointvec
+ },
+ #endif
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "xchanmode",
+ .mode = 0444,
+ .data = &ath_xchanmode,
+ .maxlen = sizeof(ath_xchanmode),
+ .proc_handler = proc_dointvec
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "calibrate",
+ .mode = 0644,
+ .data = &ath_calinterval,
+@@ -11993,14 +12001,14 @@ static ctl_table ath_static_sysctls[] =
+ { 0 }
+ };
+ static ctl_table ath_ath_table[] = {
+- { .ctl_name = DEV_ATH,
++ { CTLNAME(DEV_ATH)
+ .procname = "ath",
+ .mode = 0555,
+ .child = ath_static_sysctls
+ }, { 0 }
+ };
+ static ctl_table ath_root_table[] = {
+- { .ctl_name = CTL_DEV,
++ { CTLNAME(CTL_DEV)
+ .procname = "dev",
+ .mode = 0555,
+ .child = ath_ath_table
+--- a/ath/if_ath_ahb.h
++++ b/ath/if_ath_ahb.h
+@@ -112,7 +112,11 @@
+ do { (void) (start); (void) (size); } while (0)
+ #endif
+
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
++#define bus_dma_sync_single dma_sync_single_for_cpu
++#else
+ #define bus_dma_sync_single dma_sync_single
++#endif
+ #define bus_map_single dma_map_single
+ #define bus_unmap_single dma_unmap_single
+ #define bus_alloc_consistent(_hwdev, _sz, _hdma) \
+--- a/ath_hal/ah_os.c
++++ b/ath_hal/ah_os.c
+@@ -518,7 +518,7 @@ EXPORT_SYMBOL(ath_hal_memcmp);
+
+ static ctl_table ath_hal_sysctls[] = {
+ #ifdef AH_DEBUG
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "debug",
+ .mode = 0644,
+ .data = &ath_hal_debug,
+@@ -526,21 +526,21 @@ static ctl_table ath_hal_sysctls[] = {
+ .proc_handler = proc_dointvec
+ },
+ #endif
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "dma_beacon_response_time",
+ .data = &ath_hal_dma_beacon_response_time,
+ .maxlen = sizeof(ath_hal_dma_beacon_response_time),
+ .mode = 0644,
+ .proc_handler = proc_dointvec
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "sw_beacon_response_time",
+ .mode = 0644,
+ .data = &ath_hal_sw_beacon_response_time,
+ .maxlen = sizeof(ath_hal_sw_beacon_response_time),
+ .proc_handler = proc_dointvec
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "swba_backoff",
+ .mode = 0644,
+ .data = &ath_hal_additional_swba_backoff,
+@@ -548,19 +548,19 @@ static ctl_table ath_hal_sysctls[] = {
+ .proc_handler = proc_dointvec
+ },
+ #ifdef AH_DEBUG_ALQ
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "alq",
+ .mode = 0644,
+ .proc_handler = sysctl_hw_ath_hal_log
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "alq_size",
+ .mode = 0644,
+ .data = &ath_hal_alq_qsize,
+ .maxlen = sizeof(ath_hal_alq_qsize),
+ .proc_handler = proc_dointvec
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "alq_lost",
+ .mode = 0644,
+ .data = &ath_hal_alq_lost,
+@@ -571,21 +571,21 @@ static ctl_table ath_hal_sysctls[] = {
+ { 0 }
+ };
+ static ctl_table ath_hal_table[] = {
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "hal",
+ .mode = 0555,
+ .child = ath_hal_sysctls
+ }, { 0 }
+ };
+ static ctl_table ath_ath_table[] = {
+- { .ctl_name = DEV_ATH,
++ { CTLNAME(DEV_ATH)
+ .procname = "ath",
+ .mode = 0555,
+ .child = ath_hal_table
+ }, { 0 }
+ };
+ static ctl_table ath_root_table[] = {
+- { .ctl_name = CTL_DEV,
++ { CTLNAME(CTL_DEV)
+ .procname = "dev",
+ .mode = 0555,
+ .child = ath_ath_table
+--- a/include/compat.h
++++ b/include/compat.h
+@@ -193,6 +193,12 @@ static inline int timeval_compare(struct
+ #define __skb_queue_after(_list, _old, _new) __skb_append(_old, _new, _list)
+ #endif
+
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
++#define CTLNAME(x) .ctl_name = x,
++#else
++#define CTLNAME(x)
++#endif
++
+ #endif /* __KERNEL__ */
+
+ #endif /* _ATH_COMPAT_H_ */
+--- a/net80211/ieee80211_linux.c
++++ b/net80211/ieee80211_linux.c
+@@ -699,39 +699,39 @@ IEEE80211_SYSCTL_DECL(ieee80211_sysctl_m
+
+ static const ctl_table ieee80211_sysctl_template[] = {
+ #ifdef IEEE80211_DEBUG
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "debug",
+ .mode = 0644,
+ .proc_handler = ieee80211_sysctl_debug
+ },
+ #endif
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "dev_type",
+ .mode = 0644,
+ .proc_handler = ieee80211_sysctl_dev_type
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "monitor_nods_only",
+ .mode = 0644,
+ .proc_handler = ieee80211_sysctl_monitor_nods_only
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "monitor_txf_len",
+ .mode = 0644,
+ .proc_handler = ieee80211_sysctl_monitor_txf_len
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "monitor_phy_errors",
+ .mode = 0644,
+ .proc_handler = ieee80211_sysctl_monitor_phy_errors
+ },
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "monitor_crc_errors",
+ .mode = 0644,
+ .proc_handler = ieee80211_sysctl_monitor_crc_errors
+ },
+ /* NB: must be last entry before NULL */
+- { .ctl_name = CTL_AUTO,
++ { CTLNAME(CTL_AUTO)
+ .procname = "%parent",
+ .maxlen = IFNAMSIZ,
+ .mode = 0444,
+@@ -786,12 +786,16 @@ ieee80211_virtfs_latevattach(struct ieee
+
+ /* setup the table */
+ memset(vap->iv_sysctls, 0, space);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
+ vap->iv_sysctls[0].ctl_name = CTL_NET;
++#endif
+ vap->iv_sysctls[0].procname = "net";
+ vap->iv_sysctls[0].mode = 0555;
+ vap->iv_sysctls[0].child = &vap->iv_sysctls[2];
+ /* [1] is NULL terminator */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
+ vap->iv_sysctls[2].ctl_name = CTL_AUTO;
++#endif
+ vap->iv_sysctls[2].procname = devname; /* XXX bad idea? */
+ vap->iv_sysctls[2].mode = 0555;
+ vap->iv_sysctls[2].child = &vap->iv_sysctls[4];
diff --git a/package/madwifi/patches/460-pci_softled_disable.patch b/package/madwifi/patches/460-pci_softled_disable.patch
new file mode 100644
index 000000000..328e8c350
--- /dev/null
+++ b/package/madwifi/patches/460-pci_softled_disable.patch
@@ -0,0 +1,18 @@
+--- a/ath/if_ath_pci.c
++++ b/ath/if_ath_pci.c
+@@ -264,6 +264,7 @@ ath_pci_probe(struct pci_dev *pdev, cons
+ }
+ }
+
++#if 0
+ /*
+ * Auto-enable soft led processing for IBM cards and for
+ * 5211 minipci cards. Users can also manually enable/disable
+@@ -279,6 +280,7 @@ ath_pci_probe(struct pci_dev *pdev, cons
+ sc->aps_sc.sc_softled = 1;
+ sc->aps_sc.sc_ledpin = 1;
+ }
++#endif
+
+ if ((i = ath_attach(vdevice, dev, NULL)) != 0) {
+ printk(KERN_ERR "%s: ath_attach failed: %d\n", dev_info, i);
diff --git a/package/madwifi/patches/461-rx_stats_count_fix.patch b/package/madwifi/patches/461-rx_stats_count_fix.patch
new file mode 100644
index 000000000..4b5ce28cc
--- /dev/null
+++ b/package/madwifi/patches/461-rx_stats_count_fix.patch
@@ -0,0 +1,23 @@
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -202,7 +202,6 @@ ieee80211_input(struct ieee80211vap * va
+ struct ieee80211com *ic;
+ struct net_device *dev;
+ struct ieee80211_node *ni_wds = NULL;
+- struct net_device_stats *stats;
+ struct ieee80211_frame *wh;
+ struct ieee80211_key *key;
+ struct ether_header *eh;
+@@ -685,12 +684,6 @@ ieee80211_input(struct ieee80211vap * va
+ if (! accept_data_frame(vap, ni, key, skb, eh))
+ goto out;
+
+- if (ni->ni_subif && ((eh)->ether_type != __constant_htons(ETHERTYPE_PAE)))
+- stats = &ni->ni_subif->iv_devstats;
+- else
+- stats = &vap->iv_devstats;
+- stats->rx_packets++;
+- stats->rx_bytes += skb->len;
+ IEEE80211_NODE_STAT(ni, rx_data);
+ IEEE80211_NODE_STAT_ADD(ni, rx_bytes, skb->len);
+ ic->ic_lastdata = jiffies;
diff --git a/package/madwifi/patches/462-fix_ap_scan.patch b/package/madwifi/patches/462-fix_ap_scan.patch
new file mode 100644
index 000000000..8798f534e
--- /dev/null
+++ b/package/madwifi/patches/462-fix_ap_scan.patch
@@ -0,0 +1,26 @@
+--- a/net80211/ieee80211_scan_ap.c
++++ b/net80211/ieee80211_scan_ap.c
+@@ -595,6 +595,14 @@ ap_end(struct ieee80211_scan_state *ss,
+
+ ic = vap->iv_ic;
+
++ /* if we're already running, switch back to the home channel */
++ if ((vap->iv_state == IEEE80211_S_RUN) &&
++ (ic->ic_bsschan != IEEE80211_CHAN_ANYC)) {
++ ic->ic_curchan = ic->ic_bsschan;
++ ic->ic_set_channel(ic);
++ goto out;
++ }
++
+ /* record stats for the channel that was scanned last */
+ ic->ic_set_channel(ic);
+ spin_lock_irqsave(&channel_lock, sflags);
+@@ -648,6 +656,8 @@ ap_end(struct ieee80211_scan_state *ss,
+ IEEE80211_SCHEDULE_TQUEUE(&as->as_actiontq);
+ res = 1;
+ }
++
++out:
+ SCAN_AP_UNLOCK_IRQ(as);
+ return res;
+ }
diff --git a/package/madwifi/patches/463-fix_txrate_display.patch b/package/madwifi/patches/463-fix_txrate_display.patch
new file mode 100644
index 000000000..0889f78fe
--- /dev/null
+++ b/package/madwifi/patches/463-fix_txrate_display.patch
@@ -0,0 +1,10 @@
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -728,6 +728,7 @@ ath_rate_statistics(struct ieee80211_nod
+ rn->max_tp_rate2 = index_max_tp2;
+ rn->max_prob_rate = index_max_prob;
+ rn->current_rate = index_max_tp;
++ ni->ni_txrate = index_max_tp;
+ }
+
+ static struct ath_ratectrl *
diff --git a/package/madwifi/patches/464-0dbm_txpower_fix.patch b/package/madwifi/patches/464-0dbm_txpower_fix.patch
new file mode 100644
index 000000000..fbd1d7673
--- /dev/null
+++ b/package/madwifi/patches/464-0dbm_txpower_fix.patch
@@ -0,0 +1,30 @@
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -1370,15 +1370,9 @@ ieee80211_ioctl_siwtxpow(struct net_devi
+ int fixed, disabled;
+
+ fixed = (ic->ic_flags & IEEE80211_F_TXPOW_FIXED);
+- disabled = (fixed && ic->ic_txpowlimit == 0);
+- if (rrq->disabled) {
+- if (!disabled) {
+- ic->ic_flags |= IEEE80211_F_TXPOW_FIXED;
+- ic->ic_txpowlimit = 0;
+- goto done;
+- }
+- return 0;
+- }
++
++ if (rrq->disabled)
++ return -EINVAL;
+
+ if (rrq->fixed) {
+ if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
+@@ -1571,7 +1565,7 @@ ieee80211_ioctl_giwtxpow(struct net_devi
+ rrq->fixed = 0;
+ }
+ rrq->value = txp / 2;
+- rrq->disabled = (rrq->fixed && rrq->value == 0);
++ rrq->disabled = 0;
+ rrq->flags = IW_TXPOW_DBM;
+ return 0;
+ }
diff --git a/package/madwifi/patches/465-mc_list-2.6.35.patch b/package/madwifi/patches/465-mc_list-2.6.35.patch
new file mode 100644
index 000000000..4931cfb28
--- /dev/null
+++ b/package/madwifi/patches/465-mc_list-2.6.35.patch
@@ -0,0 +1,40 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -4466,7 +4466,11 @@ ath_merge_mcast(struct ath_softc *sc, u_
+ {
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap;
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
++ struct netdev_hw_addr *ha;
++ #else
+ struct dev_mc_list *mc;
++ #endif
+ u_int32_t val;
+ u_int8_t pos;
+
+@@ -4474,6 +4478,17 @@ ath_merge_mcast(struct ath_softc *sc, u_
+ /* XXX locking */
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+ struct net_device *dev = vap->iv_dev;
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
++ netdev_for_each_mc_addr(ha, dev) {
++ /* calculate XOR of eight 6-bit values */
++ val = LE_READ_4(ha->addr + 0);
++ pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
++ val = LE_READ_4(ha->addr + 3);
++ pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
++ pos &= 0x3f;
++ mfilt[pos / 32] |= (1 << (pos % 32));
++ }
++ #else
+ for (mc = dev->mc_list; mc; mc = mc->next) {
+ /* calculate XOR of eight 6-bit values */
+ val = LE_READ_4(mc->dmi_addr + 0);
+@@ -4483,6 +4498,7 @@ ath_merge_mcast(struct ath_softc *sc, u_
+ pos &= 0x3f;
+ mfilt[pos / 32] |= (1 << (pos % 32));
+ }
++ #endif
+ }
+ }
+
diff --git a/package/madwifi/patches/466-2.6.38_compile.patch b/package/madwifi/patches/466-2.6.38_compile.patch
new file mode 100644
index 000000000..10a6f0deb
--- /dev/null
+++ b/package/madwifi/patches/466-2.6.38_compile.patch
@@ -0,0 +1,14 @@
+--- a/include/compat.h
++++ b/include/compat.h
+@@ -131,6 +131,11 @@
+ #ifdef __KERNEL__
+
+ #include <linux/version.h>
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
++#define AUTOCONF_INCLUDED 1
++#endif
++
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)
+ #define ATH_REGISTER_SYSCTL_TABLE(t) register_sysctl_table(t, 1)
+ #else
diff --git a/package/madwifi/patches/470-mac_addresss_from_ath5k_platform_data.patch b/package/madwifi/patches/470-mac_addresss_from_ath5k_platform_data.patch
new file mode 100644
index 000000000..0c35050c5
--- /dev/null
+++ b/package/madwifi/patches/470-mac_addresss_from_ath5k_platform_data.patch
@@ -0,0 +1,36 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -63,6 +63,8 @@
+ #include <linux/rtnetlink.h>
+ #include <linux/time.h>
+ #include <linux/pci.h>
++#include <linux/device.h>
++#include <linux/ath5k_platform.h>
+ #include <asm/uaccess.h>
+
+ #include "if_ethersubr.h" /* for ETHER_IS_MULTICAST */
+@@ -587,6 +589,10 @@ ath_attach(u_int16_t devid, struct net_d
+ unsigned int i;
+ int autocreatemode = -1;
+ u_int8_t csz;
++#ifdef ATH_PCI
++ struct ath5k_platform_data *pdata;
++ struct pci_dev *pdev;
++#endif
+
+ sc->devid = devid;
+ #ifdef AR_DEBUG
+@@ -648,6 +654,13 @@ ath_attach(u_int16_t devid, struct net_d
+ }
+ sc->sc_ah = ah;
+
++#ifdef ATH_PCI
++ /* set MAC from ath_platform_data */
++ pdev = (struct pci_dev *)sc->sc_bdev;
++ pdata = pdev->dev.platform_data;
++ if (pdata && pdata->macaddr)
++ ath_hal_setmac(ah, pdata->macaddr);
++#endif
+ /* WAR for AR7100 PCI bug */
+ #if defined(CONFIG_ATHEROS_AR71XX) || defined(CONFIG_ATH79)
+ if ((ar_device(sc->devid) >= 5210) && (ar_device(sc->devid) < 5416)) {
diff --git a/package/madwifi/patches/471-netdev_ops_mac_mtu.patch b/package/madwifi/patches/471-netdev_ops_mac_mtu.patch
new file mode 100644
index 000000000..c7e1f404a
--- /dev/null
+++ b/package/madwifi/patches/471-netdev_ops_mac_mtu.patch
@@ -0,0 +1,30 @@
+--- a/net80211/ieee80211.c
++++ b/net80211/ieee80211.c
+@@ -47,6 +47,7 @@
+ #include <linux/skbuff.h>
+ #include <linux/netdevice.h>
+ #include <linux/rtnetlink.h> /* XXX for rtnl_lock */
++#include <linux/etherdevice.h>
+
+ #include "if_media.h"
+
+@@ -463,6 +464,8 @@ static const struct net_device_ops ieee8
+ .ndo_set_multicast_list = ieee80211_set_multicast_list,
+ .ndo_change_mtu = ieee80211_change_mtu,
+ .ndo_do_ioctl = ieee80211_ioctl,
++ .ndo_validate_addr = eth_validate_addr,
++ .ndo_set_mac_address = eth_mac_addr,
+ };
+ #endif
+
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -574,6 +574,8 @@ static const struct net_device_ops ath_n
+ .ndo_get_stats = ath_getstats,
+ .ndo_set_mac_address = ath_set_mac_address,
+ .ndo_change_mtu = ath_change_mtu,
++ .ndo_validate_addr = eth_validate_addr,
++ .ndo_set_mac_address = eth_mac_addr,
+ };
+ #endif
+
diff --git a/package/madwifi/patches/472-remove_11n_devids.patch b/package/madwifi/patches/472-remove_11n_devids.patch
new file mode 100644
index 000000000..cf80f06bf
--- /dev/null
+++ b/package/madwifi/patches/472-remove_11n_devids.patch
@@ -0,0 +1,20 @@
+--- a/ath/if_ath_pci.c
++++ b/ath/if_ath_pci.c
+@@ -111,8 +111,6 @@ static struct pci_device_id ath_pci_id_t
+ { 0x168c, 0x001b, PCI_ANY_ID, PCI_ANY_ID },
+ { 0x168c, 0x001c, PCI_ANY_ID, PCI_ANY_ID }, /* PCI Express 5424 */
+ { 0x168c, 0x001d, PCI_ANY_ID, PCI_ANY_ID }, /* PCI Express ??? */
+- { 0x168c, 0x0023, PCI_ANY_ID, PCI_ANY_ID },
+- { 0x168c, 0x0024, PCI_ANY_ID, PCI_ANY_ID },
+ { 0x168c, 0x9013, PCI_ANY_ID, PCI_ANY_ID }, /* sonicwall */
+ { 0x168c, 0xff1a, PCI_ANY_ID, PCI_ANY_ID },
+ { 0 }
+@@ -146,8 +144,6 @@ static const struct ath_hw_detect cards[
+ { ubnt, "SR4C", 0x168c, 0x0013, 0x7777, 0x1004, 6 },
+ { ubnt, "SR5", 0x168c, 0x0013, 0x168c, 0x2042, 7 },
+ { ubnt, "SR9", 0x168c, 0x0013, 0x7777, 0x2009, 12 },
+- { ubnt, "SR71A", 0x168c, 0x0027, 0x168c, 0x2082, 10 },
+- { ubnt, "SR71", 0x168c, 0x0027, 0x0777, 0x4082, 10 },
+ };
+
+ static int
diff --git a/package/madwifi/patches/473-mutex_fix.patch b/package/madwifi/patches/473-mutex_fix.patch
new file mode 100644
index 000000000..22cea46a2
--- /dev/null
+++ b/package/madwifi/patches/473-mutex_fix.patch
@@ -0,0 +1,11 @@
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -974,7 +974,7 @@ typedef void (*ath_callback) (struct ath
+ #endif
+
+ /* Protects the device from concurrent accesses */
+-#define ATH_LOCK_INIT(_sc) init_MUTEX(&(_sc)->sc_lock)
++#define ATH_LOCK_INIT(_sc) sema_init(&(_sc)->sc_lock, 1)
+ #define ATH_LOCK_DESTROY(_sc)
+ #define ATH_LOCK(_sc) down(&(_sc)->sc_lock)
+ #define ATH_UNLOCK(_sc) up(&(_sc)->sc_lock)
diff --git a/package/madwifi/patches/474_fix_ssid_scan_length.patch b/package/madwifi/patches/474_fix_ssid_scan_length.patch
new file mode 100644
index 000000000..2e85e18c6
--- /dev/null
+++ b/package/madwifi/patches/474_fix_ssid_scan_length.patch
@@ -0,0 +1,29 @@
+--- a/tools/wlanconfig.c
++++ b/tools/wlanconfig.c
+@@ -654,7 +654,7 @@ static void
+ list_scan(const char *ifname)
+ {
+ static uint8_t buf[24 * 1024];
+- char ssid[14];
++ char ssid[30];
+ uint8_t *cp;
+ int len;
+
+@@ -665,7 +665,7 @@ list_scan(const char *ifname)
+ if (len < sizeof(struct ieee80211req_scan_result))
+ return;
+
+- printf("%-14.14s %-17.17s %4s %4s %-5s %3s %4s\n",
++ printf("%-30.30s %-17.17s %4s %4s %-5s %3s %4s\n",
+ "SSID",
+ "BSSID",
+ "CHAN",
+@@ -680,7 +680,7 @@ list_scan(const char *ifname)
+
+ sr = (struct ieee80211req_scan_result *) cp;
+ vp = (u_int8_t *)(sr+1);
+- printf("%-14.*s %s %3d %3dM %2d:%-2d %3d %-4.4s",
++ printf("%-30.*s %s %3d %3dM %2d:%-2d %3d %-4.4s",
+ copy_essid(ssid, sizeof(ssid), vp, sr->isr_ssid_len),
+ ssid,
+ ieee80211_ntoa(sr->isr_bssid),
diff --git a/package/madwifi/patches/475-2.6.39-compile.patch b/package/madwifi/patches/475-2.6.39-compile.patch
new file mode 100644
index 000000000..5b8a77718
--- /dev/null
+++ b/package/madwifi/patches/475-2.6.39-compile.patch
@@ -0,0 +1,11 @@
+--- a/net80211/ieee80211_scan.c
++++ b/net80211/ieee80211_scan.c
+@@ -97,7 +97,7 @@ struct scan_state {
+ static void scan_restart_pwrsav(unsigned long);
+ static void scan_next(unsigned long);
+
+-spinlock_t channel_lock = SPIN_LOCK_UNLOCKED;
++DEFINE_SPINLOCK(channel_lock);
+ static LIST_HEAD(channels_inuse);
+
+ struct channel_inuse {
diff --git a/package/madwifi/patches/476-3.0_detection_fix.patch b/package/madwifi/patches/476-3.0_detection_fix.patch
new file mode 100644
index 000000000..2f8bfb4a5
--- /dev/null
+++ b/package/madwifi/patches/476-3.0_detection_fix.patch
@@ -0,0 +1,25 @@
+--- a/Makefile
++++ b/Makefile
+@@ -155,13 +155,15 @@ unload:
+ configcheck:
+ @echo -n "Checking kernel configuration... "
+
+- @# check version of kernel
+- @echo $(KERNELRELEASE) | grep -q -i '^[2-9]\.[4-9]\.' || { \
+- echo "FAILED"; \
+- echo "Only kernel versions 2.4.x and above are supported."; \
+- echo "You have $(KERNELRELEASE)."; \
+- exit 1; \
+- }
++ @# check kernel version
++ @case $(KERNELRELEASE) in \
++ 2.[456].*) ;; \
++ [3-9].*) ;; \
++ *) echo "FAILED"; \
++ echo "Only kernel versions 2.4.x and above are supported."; \
++ echo "You have $(KERNELRELEASE)."; \
++ exit 1 ;; \
++ esac
+
+ @# check kernel configuration
+ @if [ -z "$(CONFIG_SYSCTL)" ]; then \
diff --git a/package/madwifi/patches/477-3.2_fixes.patch b/package/madwifi/patches/477-3.2_fixes.patch
new file mode 100644
index 000000000..89cdfc649
--- /dev/null
+++ b/package/madwifi/patches/477-3.2_fixes.patch
@@ -0,0 +1,45 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -569,7 +569,11 @@ static const struct net_device_ops ath_n
+ .ndo_stop = ath_stop,
+ .ndo_start_xmit = ath_hardstart,
+ .ndo_tx_timeout = ath_tx_timeout,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)
++ .ndo_set_rx_mode = ath_mode_init,
++#else
+ .ndo_set_multicast_list = ath_mode_init,
++#endif
+ .ndo_do_ioctl = ath_ioctl,
+ .ndo_get_stats = ath_getstats,
+ .ndo_set_mac_address = ath_set_mac_address,
+--- a/net80211/ieee80211.c
++++ b/net80211/ieee80211.c
+@@ -461,7 +461,11 @@ static const struct net_device_ops ieee8
+ .ndo_open = ieee80211_open,
+ .ndo_stop = ieee80211_stop,
+ .ndo_start_xmit = ieee80211_hardstart,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)
++ .ndo_set_rx_mode = ieee80211_set_multicast_list,
++#else
+ .ndo_set_multicast_list = ieee80211_set_multicast_list,
++#endif
+ .ndo_change_mtu = ieee80211_change_mtu,
+ .ndo_do_ioctl = ieee80211_ioctl,
+ .ndo_validate_addr = eth_validate_addr,
+@@ -1847,10 +1851,14 @@ ieee80211_set_multicast_list(struct net_
+ IEEE80211_UNLOCK_IRQ(ic);
+
+ /* XXX: Merge multicast list into parent device */
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
+- parent->set_multicast_list(ic->ic_dev);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)
++ parent->netdev_ops->ndo_set_rx_mode(ic->ic_dev);
+ #else
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
+ parent->netdev_ops->ndo_set_multicast_list(ic->ic_dev);
++#else
++ parent->set_multicast_list(ic->ic_dev);
++#endif
+ #endif
+ }
+
diff --git a/package/madwifi/patches/478-remove_vlan_code.patch b/package/madwifi/patches/478-remove_vlan_code.patch
new file mode 100644
index 000000000..9ceda4aa0
--- /dev/null
+++ b/package/madwifi/patches/478-remove_vlan_code.patch
@@ -0,0 +1,21 @@
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -1223,6 +1223,7 @@ ieee80211_deliver_data(struct ieee80211_
+ #endif
+ vap->iv_devstats.rx_packets++;
+ vap->iv_devstats.rx_bytes += skb->len;
++#if IEEE80211_VLAN_TAG_USED
+ if (ni->ni_vlan != 0 && vap->iv_vlgrp != NULL) {
+ /* attach vlan tag */
+ struct ieee80211_node *ni_tmp = SKB_CB(skb)->ni;
+@@ -1236,7 +1237,9 @@ ieee80211_deliver_data(struct ieee80211_
+ vap->iv_devstats.rx_dropped++;
+ }
+ skb = NULL; /* SKB is no longer ours */
+- } else {
++ } else
++#endif
++ {
+ struct ieee80211_node *ni_tmp = SKB_CB(skb)->ni;
+ if (netif_receive_skb(skb) == NET_RX_DROP) {
+ /* If netif_receive_skb dropped the packet because
diff --git a/package/mkelfimage/Makefile b/package/mkelfimage/Makefile
new file mode 100644
index 000000000..2433c7203
--- /dev/null
+++ b/package/mkelfimage/Makefile
@@ -0,0 +1,35 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mkelfimage
+PKG_VERSION:=2.7
+
+PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).orig.tar.gz
+PKG_SOURCE_URL:=http://ftp.debian.org/debian/pool/main/m/mkelfimage/
+PKG_MD5SUM:=e505cb87e9c0cdc44cf03d2c4ea8c74b
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/mkelfimage
+ SECTION:=base
+ CATEGORY:=Base system
+ TITLE:=mkelfimage
+ HIDDEN:=1
+ DEPENDS:=@i386
+ DEFAULT:=y if TARGET_x86
+endef
+
+CONFIGURE_VARS += AS="$(TARGET_CROSS)as"
+MAKE_FLAGS += HOST_CC="$(HOSTCC)" DEFS="-I$(STAGING_DIR_HOST)/include"
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(STAGING_DIR_HOST)/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/objdir/sbin/mkelfImage $(STAGING_DIR_HOST)/bin
+endef
+
+$(eval $(call BuildPackage,mkelfimage))
diff --git a/package/mkelfimage/patches/no-stack-protector.patch b/package/mkelfimage/patches/no-stack-protector.patch
new file mode 100644
index 000000000..108583aed
--- /dev/null
+++ b/package/mkelfimage/patches/no-stack-protector.patch
@@ -0,0 +1,11 @@
+--- mkelfimage-2.7.old//Makefile 2006-03-28 02:44:59.000000000 +0300
++++ mkelfimage-2.7/Makefile 2011-01-17 14:15:13.000000000 +0200
+@@ -14,7 +14,7 @@
+ pkglibdir = $(libdir)/$(PACKAGE)
+ pkgincludedir = $(includedir)/$(PACKAGE)
+
+-CPPFLAGS=-DVERSION='"$(VERSION)"' -DRELEASE_DATE='"$(RELEASE_DATE)"' -I include
++CPPFLAGS=-DVERSION='"$(VERSION)"' -DRELEASE_DATE='"$(RELEASE_DATE)"' -I include -fno-stack-protector
+ HOST_CPPFLAGS=$(CPPFLAGS)
+ I386_CPPFLAGS=$(CPPFLAGS) -I arch/i386/include
+ IA64_CPPFLAGS=$(CPPFLAGS) -I arch/ia64/include
diff --git a/package/mmc_over_gpio/Makefile b/package/mmc_over_gpio/Makefile
new file mode 100644
index 000000000..03096ad03
--- /dev/null
+++ b/package/mmc_over_gpio/Makefile
@@ -0,0 +1,78 @@
+#
+# Copyright (C) 2008 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=mmc-over-gpio
+PKG_RELEASE:=4
+
+include $(INCLUDE_DIR)/package.mk
+
+
+define KernelPackage/mmc-over-gpio
+ SUBMENU:=Other modules
+ DEPENDS:=@GPIO_SUPPORT +kmod-mmc-spi +kmod-spi-gpio-old
+ KCONFIG:=CONFIG_GPIOMMC \
+ CONFIG_CONFIGFS_FS=y
+ TITLE:=MMC/SD card over GPIO support
+ FILES:=$(LINUX_DIR)/drivers/mmc/host/gpiommc.ko
+ AUTOLOAD:=$(call AutoLoad,93,gpiommc)
+ MENU:=1
+endef
+
+define Package/kmod-mmc-over-gpio/config
+ menu "Configuration"
+ depends PACKAGE_kmod-mmc-over-gpio
+
+ config KMOD_MMC_OVER_GPIO_DI_PIN
+ int "GPIO DI (Data-In) pin"
+ default 1
+
+ config KMOD_MMC_OVER_GPIO_DO_PIN
+ int "GPIO DO (Data-Out) pin"
+ default 3
+
+ config KMOD_MMC_OVER_GPIO_CLK_PIN
+ int "GPIO CLK (Clock) pin"
+ default 4
+
+ config KMOD_MMC_OVER_GPIO_CS_PIN
+ int "GPIO CS (Chip-Select) pin"
+ default 7
+
+ endmenu
+endef
+
+define KernelPackage/mmc-over-gpio/description
+ Support for driving an MMC/SD card over GPIO pins via SPI.
+endef
+
+define KernelPackage/mmc-over-gpio/conffiles
+/etc/config/mmc_over_gpio
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+endef
+
+define Build/Compile
+endef
+
+define KernelPackage/mmc-over-gpio/install
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/mmc_over_gpio.config $(1)/etc/config/mmc_over_gpio
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/mmc_over_gpio.init $(1)/etc/init.d/mmc_over_gpio
+
+ $(SED) 's,@GPIO_DI_PIN@,$(CONFIG_KMOD_MMC_OVER_GPIO_DI_PIN),g' \
+ -e 's,@GPIO_DO_PIN@,$(CONFIG_KMOD_MMC_OVER_GPIO_DO_PIN),g' \
+ -e 's,@GPIO_CLK_PIN@,$(CONFIG_KMOD_MMC_OVER_GPIO_CLK_PIN),g' \
+ -e 's,@GPIO_CS_PIN@,$(CONFIG_KMOD_MMC_OVER_GPIO_CS_PIN),g' \
+ $(1)/etc/config/mmc_over_gpio
+endef
+
+$(eval $(call KernelPackage,mmc-over-gpio))
diff --git a/package/mmc_over_gpio/files/mmc_over_gpio.config b/package/mmc_over_gpio/files/mmc_over_gpio.config
new file mode 100644
index 000000000..23f008485
--- /dev/null
+++ b/package/mmc_over_gpio/files/mmc_over_gpio.config
@@ -0,0 +1,8 @@
+config 'mmc_over_gpio'
+ option 'name' 'default'
+ option 'enabled' '0'
+ option 'DI_pin' '@GPIO_DI_PIN@'
+ option 'DO_pin' '@GPIO_DO_PIN@'
+ option 'CLK_pin' '@GPIO_CLK_PIN@'
+ option 'CS_pin' '@GPIO_CS_PIN@'
+ option 'mode' '0'
diff --git a/package/mmc_over_gpio/files/mmc_over_gpio.init b/package/mmc_over_gpio/files/mmc_over_gpio.init
new file mode 100644
index 000000000..121c80398
--- /dev/null
+++ b/package/mmc_over_gpio/files/mmc_over_gpio.init
@@ -0,0 +1,83 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2008 OpenWrt.org
+START=90
+
+CONFIGFS_DIR="/config/gpiommc"
+
+# add_device(name, DI_pin, DO_pin, CLK_pin, CS_pin, mode)
+add_device() {
+ local dir="$CONFIGFS_DIR/$1"
+
+ mkdir -p $dir
+ [ $? -eq 0 ] || return 1
+ echo $2 > $dir/gpio_data_in
+ [ $? -eq 0 ] || return 1
+ echo $3 > $dir/gpio_data_out
+ [ $? -eq 0 ] || return 1
+ echo $4 > $dir/gpio_clock
+ [ $? -eq 0 ] || return 1
+ echo $5 > $dir/gpio_chipselect
+ [ $? -eq 0 ] || return 1
+ echo $6 > $dir/spi_mode
+ [ $? -eq 0 ] || return 1
+ # XXX We have more config options available. Use defaults for now.
+
+ echo 1 > $dir/register
+ [ $? -eq 0 ] || return 1
+
+ return 0
+}
+
+# remove_device(name)
+remove_device() {
+ local dir="$CONFIGFS_DIR/$1"
+
+ rmdir $dir
+}
+
+mount_configfs() {
+ # FIXME: This should probably be done somewhere else.
+ mount | grep configfs
+ if [ $? -eq 0 ]; then
+ # already mounted
+ return 0
+ fi
+ mkdir -p /config
+ [ $? -eq 0 ] || return 1
+ mount configfs -t configfs /config
+ [ $? -eq 0 ] || return 1
+
+ return 0
+}
+
+start_service() {
+ local section="$1"
+ config_get "name" "$section" "name"
+ config_get "DI_pin" "$section" "DI_pin"
+ config_get "DO_pin" "$section" "DO_pin"
+ config_get "CLK_pin" "$section" "CLK_pin"
+ config_get "CS_pin" "$section" "CS_pin"
+ config_get "mode" "$section" "mode"
+ config_get_bool "enabled" "$section" "enabled" '1'
+ [ "$enabled" -gt 0 ] && add_device "$name" $DI_pin $DO_pin $CLK_pin $CS_pin $mode &
+}
+
+stop_service() {
+ local section="$1"
+ config_get "name" "$section" "name"
+ remove_device "$name"
+}
+
+start() {
+ # Make sure configfs is mounted
+ mount_configfs
+ [ $? -eq 0 ] || return 1
+
+ config_load "mmc_over_gpio"
+ config_foreach start_service "mmc_over_gpio"
+}
+
+stop() {
+ config_load "mmc_over_gpio"
+ config_foreach stop_service "mmc_over_gpio"
+}
diff --git a/package/mountd/Makefile b/package/mountd/Makefile
new file mode 100644
index 000000000..4bf881779
--- /dev/null
+++ b/package/mountd/Makefile
@@ -0,0 +1,46 @@
+# Copyright (C) 2009-2012 OpenWrt.org
+# All rights reserved.
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mountd
+PKG_VERSION:=0.1
+PKG_RELEASE:=6
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
+PKG_MD5SUM:=b77253ee4321d24d200fffc4f7ca3d15
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/mountd
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=OpenWrt automount daemon
+ DEPENDS:=@USB_SUPPORT +uci +kmod-usb-storage +kmod-fs-autofs4
+ URL:=http://www.openwrt.org
+endef
+
+define Package/mountd/description
+ openwrt automount daemon
+endef
+
+define Package/mountd/conffiles
+/etc/config/mountd
+endef
+
+define Build/Compile
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS) -I$(STAGING_DIR)/usr/include -I$(PKG_BUILD_DIR)" \
+ LDFLAGS="$(TARGET_LDFLAGS)" \
+ $(MAKE) -C $(PKG_BUILD_DIR)
+endef
+
+define Package/mountd/install
+ $(INSTALL_DIR) $(1)/sbin/ $(1)/etc/config/ $(1)/etc/init.d/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/mountd $(1)/sbin/
+ $(INSTALL_DATA) ./files/mountd.config $(1)/etc/config/mountd
+ $(INSTALL_BIN) ./files/mountd.init $(1)/etc/init.d/mountd
+endef
+
+$(eval $(call BuildPackage,mountd))
diff --git a/package/mountd/files/mountd.config b/package/mountd/files/mountd.config
new file mode 100644
index 000000000..561012950
--- /dev/null
+++ b/package/mountd/files/mountd.config
@@ -0,0 +1,3 @@
+config mountd mountd
+ option timeout 60
+ option path /tmp/mounts/
diff --git a/package/mountd/files/mountd.init b/package/mountd/files/mountd.init
new file mode 100755
index 000000000..c294c50f5
--- /dev/null
+++ b/package/mountd/files/mountd.init
@@ -0,0 +1,19 @@
+#!/bin/sh /etc/rc.common
+
+START=80
+
+SERVICE_DAEMONIZE=1
+SERVICE_WRITE_PID=1
+SERVICE_PID_FILE=/var/run/mountd.pid
+
+MOUNTD_BIN=/sbin/mountd
+
+start()
+{
+ service_start $MOUNTD_BIN -f
+}
+
+stop()
+{
+ service_stop $MOUNTD_BIN
+}
diff --git a/package/mountd/patches/010-uci_rename_history_to_delta.patch b/package/mountd/patches/010-uci_rename_history_to_delta.patch
new file mode 100644
index 000000000..65b2f8434
--- /dev/null
+++ b/package/mountd/patches/010-uci_rename_history_to_delta.patch
@@ -0,0 +1,27 @@
+---
+ lib/uci.c | 2 +-
+ lib/ucix.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/lib/uci.c
++++ b/lib/uci.c
+@@ -28,7 +28,7 @@ struct uci_package *p = NULL;
+ struct uci_context* uci_init(char *config_file)
+ {
+ struct uci_context *ctx = uci_alloc_context();
+- uci_add_history_path(ctx, "/var/state");
++ uci_add_delta_path(ctx, "/var/state");
+ if(uci_load(ctx, config_file, &p) != UCI_OK)
+ {
+ log_printf("/etc/config/%s is missing or corrupt\n", config_file);
+--- a/lib/ucix.c
++++ b/lib/ucix.c
+@@ -18,7 +18,7 @@ static inline int ucix_get_ptr(struct uc
+ struct uci_context* ucix_init(const char *config_file)
+ {
+ struct uci_context *ctx = uci_alloc_context();
+- uci_add_history_path(ctx, "/var/state");
++ uci_add_delta_path(ctx, "/var/state");
+ if(uci_load(ctx, config_file, NULL) != UCI_OK)
+ {
+ printf("%s/%s is missing or corrupt\n", ctx->savedir, config_file);
diff --git a/package/mountd/patches/020-handle_timeout.patch b/package/mountd/patches/020-handle_timeout.patch
new file mode 100644
index 000000000..badf40fe4
--- /dev/null
+++ b/package/mountd/patches/020-handle_timeout.patch
@@ -0,0 +1,32 @@
+--- a/lib/autofs.c
++++ b/lib/autofs.c
+@@ -140,6 +140,7 @@ static int fullread(void *ptr, size_t le
+
+ static int autofs_in(union autofs_v5_packet_union *pkt)
+ {
++ int res;
+ struct pollfd fds[1];
+
+ fds[0].fd = fdout;
+@@ -147,15 +148,19 @@ static int autofs_in(union autofs_v5_pac
+
+ while(1)
+ {
+- if(poll(fds, 2, 1000) == -1)
++ res = poll(fds, 1, -1);
++
++ if (res == -1)
+ {
+ if (errno == EINTR)
+ continue;
+ log_printf("failed while trying to read packet from kernel\n");
+ return -1;
+ }
+- if(fds[0].revents & POLLIN)
++ else if ((res > 0) && (fds[0].revents & POLLIN))
++ {
+ return fullread(pkt, sizeof(*pkt));
++ }
+ }
+ }
+
diff --git a/package/mountd/patches/030-ext4_support.patch b/package/mountd/patches/030-ext4_support.patch
new file mode 100644
index 000000000..7bbaf14ac
--- /dev/null
+++ b/package/mountd/patches/030-ext4_support.patch
@@ -0,0 +1,85 @@
+diff -ruN mountd-0.1.orig/include/fs.h mountd-0.1/include/fs.h
+--- mountd-0.1.orig/include/fs.h 2009-10-02 22:57:04.000000000 +0200
++++ mountd-0.1/include/fs.h 2012-07-08 18:42:32.000000000 +0200
+@@ -7,5 +7,6 @@
+ #define EFI 7
+ #define NTFS 8
+ #define EXTENDED 9
++#define EXT4 10
+
+ int detect_fs(char *device);
+diff -ruN mountd-0.1.orig/lib/fs.c mountd-0.1/lib/fs.c
+--- mountd-0.1.orig/lib/fs.c 2009-10-02 23:26:22.000000000 +0200
++++ mountd-0.1/lib/fs.c 2012-07-08 19:28:08.000000000 +0200
+@@ -91,9 +91,14 @@
+ goto out;
+ if(get_le_short(buffer + 56) == 0xEF53)
+ {
+- if((get_le_long(buffer + 96) & 0x0008)
+- || (get_le_long(buffer + 92) & 0x0004))
+- ret = EXT3;
++ if(get_le_long(buffer + 92) & 0x0004)
++ {
++ if ((get_le_long(buffer + 96) < 0x0000040)
++ && (get_le_long(buffer + 100) < 0x0000008))
++ ret = EXT3;
++ else
++ ret = EXT4;
++ }
+ else
+ ret = EXT2;
+ }
+diff -ruN mountd-0.1.orig/lib/mount.c mountd-0.1/lib/mount.c
+--- mountd-0.1.orig/lib/mount.c 2009-10-03 12:54:57.000000000 +0200
++++ mountd-0.1/lib/mount.c 2012-07-08 19:04:29.000000000 +0200
+@@ -53,7 +53,10 @@
+ "EXT3",
+ "FAT",
+ "HFSPLUS",
+- "NTFS"
++ "",
++ "NTFS",
++ "",
++ "EXT4"
+ };
+
+ #define MAX_MOUNTED 32
+@@ -93,7 +96,7 @@
+ ucix_add_option(ctx, mountd, q->serial, "rev", q->rev);
+ snprintf(t, 64, "size%d", atoi(&q->dev[3]));
+ ucix_add_option(ctx, mountd, q->serial, t, q->size);
+- if(q->fs > MBR && q->fs <= NTFS)
++ if(q->fs > MBR && q->fs <= EXT4)
+ {
+ snprintf(t, 64, "fs%d", atoi(&q->dev[3]));
+ ucix_add_option(ctx, mountd, q->serial, t, fs_names[q->fs]);
+@@ -131,7 +134,7 @@
+ {
+ struct mount *mount;
+ char tmp[64], tmp2[64];
+- if(fs <= MBR || fs > NTFS)
++ if(fs <= MBR || fs > EXT4)
+ return;
+ mount = malloc(sizeof(struct mount));
+ INIT_LIST_HEAD(&mount->list);
+@@ -147,7 +150,7 @@
+ mount->mounted = 0;
+ mount->fs = fs;
+ list_add(&mount->list, &mounts);
+- if((!mount->ignore) && (mount->fs > MBR) && (mount->fs <= NTFS))
++ if((!mount->ignore) && (mount->fs > MBR) && (mount->fs <= EXT4))
+ {
+ log_printf("new mount : %s -> %s (%s)\n", name, dev, fs_names[mount->fs]);
+ snprintf(tmp, 64, "%s%s", uci_path, name);
+@@ -226,6 +229,11 @@
+ log_printf("mount -t vfat -o rw,uid=1000,gid=1000 /dev/%s %s", mount->dev, tmp);
+ ret = system_printf("mount -t vfat -o rw,uid=1000,gid=1000 /dev/%s %s", mount->dev, tmp);
+ }
++ if(mount->fs == EXT4)
++ {
++ log_printf("mount -t ext4 -o rw,defaults /dev/%s %s", mount->dev, tmp);
++ ret = system_printf("mount -t ext4 -o rw,defaults /dev/%s %s", mount->dev, tmp);
++ }
+ if(mount->fs == EXT3)
+ {
+ log_printf("mount -t ext3 -o rw,defaults /dev/%s %s", mount->dev, tmp);
diff --git a/package/mountd/patches/040-optional-daemonize.patch b/package/mountd/patches/040-optional-daemonize.patch
new file mode 100644
index 000000000..4d159ec66
--- /dev/null
+++ b/package/mountd/patches/040-optional-daemonize.patch
@@ -0,0 +1,13 @@
+--- a/main.c
++++ b/main.c
+@@ -13,7 +13,9 @@
+
+ int main(int argc, char *argv[])
+ {
+- daemon(0,0);
++ if ((argc < 2) || strcmp(argv[1], "-f"))
++ daemon(0,0);
++
+ daemonize = 1;
+ log_start();
+ log_printf("Starting OpenWrt (auto)mountd V1\n");
diff --git a/package/mtd/Makefile b/package/mtd/Makefile
new file mode 100644
index 000000000..7ca6b0e62
--- /dev/null
+++ b/package/mtd/Makefile
@@ -0,0 +1,50 @@
+#
+# Copyright (C) 2006-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=mtd
+PKG_RELEASE:=18
+
+PKG_BUILD_DIR := $(KERNEL_BUILD_DIR)/$(PKG_NAME)
+STAMP_PREPARED := $(STAMP_PREPARED)_$(call confvar,CONFIG_MTD_REDBOOT_PARTS)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/mtd
+ SECTION:=utils
+ CATEGORY:=Base system
+ TITLE:=Update utility for trx firmware images
+endef
+
+define Package/mtd/description
+ This package contains an utility useful to upgrade from other firmware or
+ older OpenWrt releases.
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+target=$(firstword $(subst -, ,$(BOARD)))
+
+MAKE_FLAGS += TARGET="$(target)"
+TARGET_CFLAGS := -I$(LINUX_DIR)/include $(TARGET_CFLAGS) -Dtarget_$(target)=1 -Wall
+
+ifdef CONFIG_MTD_REDBOOT_PARTS
+ MAKE_FLAGS += FIS_SUPPORT=1
+ TARGET_CFLAGS += -DFIS_SUPPORT=1
+endif
+
+define Package/mtd/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/mtd $(1)/sbin/
+endef
+
+$(eval $(call BuildPackage,mtd))
diff --git a/package/mtd/src/Makefile b/package/mtd/src/Makefile
new file mode 100644
index 000000000..ca03f27a9
--- /dev/null
+++ b/package/mtd/src/Makefile
@@ -0,0 +1,16 @@
+CC = gcc
+CFLAGS += -Wall
+
+obj = mtd.o jffs2.o crc32.o
+obj.ar71xx = trx.o
+obj.brcm = trx.o
+obj.brcm47xx = $(obj.brcm)
+obj.brcm63xx = imagetag.o
+
+ifdef FIS_SUPPORT
+ obj += fis.o
+endif
+
+mtd: $(obj) $(obj.$(TARGET))
+clean:
+ rm -f *.o jffs2
diff --git a/package/mtd/src/bcm_tag.h b/package/mtd/src/bcm_tag.h
new file mode 120000
index 000000000..2e977a2d7
--- /dev/null
+++ b/package/mtd/src/bcm_tag.h
@@ -0,0 +1 @@
+../../../target/linux/brcm63xx/files/arch/mips/include/asm/mach-bcm63xx/bcm_tag.h \ No newline at end of file
diff --git a/package/mtd/src/crc32.c b/package/mtd/src/crc32.c
new file mode 100644
index 000000000..6b1e50c42
--- /dev/null
+++ b/package/mtd/src/crc32.c
@@ -0,0 +1,95 @@
+/*
+ * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
+ * code or tables extracted from it, as desired without restriction.
+ *
+ * First, the polynomial itself and its table of feedback terms. The
+ * polynomial is
+ * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
+ *
+ * Note that we take it "backwards" and put the highest-order term in
+ * the lowest-order bit. The X^32 term is "implied"; the LSB is the
+ * X^31 term, etc. The X^0 term (usually shown as "+1") results in
+ * the MSB being 1
+ *
+ * Note that the usual hardware shift register implementation, which
+ * is what we're using (we're merely optimizing it by doing eight-bit
+ * chunks at a time) shifts bits into the lowest-order term. In our
+ * implementation, that means shifting towards the right. Why do we
+ * do it this way? Because the calculated CRC must be transmitted in
+ * order from highest-order term to lowest-order term. UARTs transmit
+ * characters in order from LSB to MSB. By storing the CRC this way
+ * we hand it to the UART in the order low-byte to high-byte; the UART
+ * sends each low-bit to hight-bit; and the result is transmission bit
+ * by bit from highest- to lowest-order term without requiring any bit
+ * shuffling on our part. Reception works similarly
+ *
+ * The feedback terms table consists of 256, 32-bit entries. Notes
+ *
+ * The table can be generated at runtime if desired; code to do so
+ * is shown later. It might not be obvious, but the feedback
+ * terms simply represent the results of eight shift/xor opera
+ * tions for all combinations of data and CRC register values
+ *
+ * The values must be right-shifted by eight bits by the "updcrc
+ * logic; the shift must be unsigned (bring in zeroes). On some
+ * hardware you could probably optimize the shift in assembler by
+ * using byte-swap instructions
+ * polynomial $edb88320
+ */
+
+#include <stdint.h>
+
+const uint32_t crc32_table[256] = {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+};
diff --git a/package/mtd/src/crc32.h b/package/mtd/src/crc32.h
new file mode 100644
index 000000000..68f8ee4fe
--- /dev/null
+++ b/package/mtd/src/crc32.h
@@ -0,0 +1,26 @@
+#ifndef CRC32_H
+#define CRC32_H
+
+#include <stdint.h>
+
+extern const uint32_t crc32_table[256];
+
+/* Return a 32-bit CRC of the contents of the buffer. */
+
+static inline uint32_t
+crc32(uint32_t val, const void *ss, int len)
+{
+ const unsigned char *s = ss;
+ while (--len >= 0)
+ val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8);
+ return val;
+}
+
+static inline unsigned int crc32buf(char *buf, size_t len)
+{
+ return crc32(0xFFFFFFFF, buf, len);
+}
+
+
+
+#endif
diff --git a/package/mtd/src/fis.c b/package/mtd/src/fis.c
new file mode 100644
index 000000000..f825f590c
--- /dev/null
+++ b/package/mtd/src/fis.c
@@ -0,0 +1,262 @@
+/*
+ * FIS table updating code for mtd
+ *
+ * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License v2
+ * 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.
+ */
+#include <sys/mman.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include "crc32.h"
+#include "mtd.h"
+#include "fis.h"
+
+struct fis_image_hdr {
+ unsigned char name[16];
+ uint32_t flash_base;
+ uint32_t mem_base;
+ uint32_t size;
+ uint32_t entry_point;
+ uint32_t data_length;
+} __attribute__((packed));
+
+struct fis_image_crc {
+ uint32_t desc;
+ uint32_t file;
+} __attribute__((packed));
+
+struct fis_image_desc {
+ struct fis_image_hdr hdr;
+ char _pad[256 - sizeof(struct fis_image_hdr) - sizeof(struct fis_image_crc)];
+ struct fis_image_crc crc;
+} __attribute__((packed));
+
+static int fis_fd = -1;
+static struct fis_image_desc *fis_desc;
+static int fis_erasesize = 0;
+
+static void
+fis_close(void)
+{
+ if (fis_desc)
+ munmap(fis_desc, fis_erasesize);
+
+ if (fis_fd >= 0)
+ close(fis_fd);
+
+ fis_fd = -1;
+ fis_desc = NULL;
+}
+
+static struct fis_image_desc *
+fis_open(void)
+{
+ struct fis_image_desc *desc;
+
+ if (fis_fd >= 0)
+ fis_close();
+
+ fis_fd = mtd_check_open("FIS directory");
+ if (fis_fd < 0)
+ goto error;
+
+ close(fis_fd);
+ fis_fd = mtd_open("FIS directory", true);
+ if (fis_fd < 0)
+ goto error;
+
+ fis_erasesize = erasesize;
+ desc = mmap(NULL, erasesize, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, fis_fd, 0);
+ if (desc == MAP_FAILED)
+ goto error;
+
+ fis_desc = desc;
+ return desc;
+
+error:
+ fis_close();
+ return NULL;
+}
+
+int
+fis_validate(struct fis_part *old, int n_old, struct fis_part *new, int n_new)
+{
+ struct fis_image_desc *desc;
+ void *end;
+ int found = 0;
+ int i;
+
+ desc = fis_open();
+ if (!desc)
+ return -1;
+
+ for (i = 0; i < n_new - 1; i++) {
+ if (!new[i].size) {
+ fprintf(stderr, "FIS error: only the last partition can detect the size automatically\n");
+ i = -1;
+ goto done;
+ }
+ }
+
+ end = desc;
+ end = (char *) end + fis_erasesize;
+ while ((void *) desc < end) {
+ if (!desc->hdr.name[0] || (desc->hdr.name[0] == 0xff))
+ break;
+
+ for (i = 0; i < n_old; i++) {
+ if (!strncmp((char *) desc->hdr.name, (char *) old[i].name, sizeof(desc->hdr.name))) {
+ found++;
+ goto next;
+ }
+ }
+next:
+ desc++;
+ continue;
+ }
+
+ if (found == n_old)
+ i = 1;
+ else
+ i = -1;
+
+done:
+ fis_close();
+ return i;
+}
+
+int
+fis_remap(struct fis_part *old, int n_old, struct fis_part *new, int n_new)
+{
+ struct fis_image_desc *fisdir = NULL;
+ struct fis_image_desc *redboot = NULL;
+ struct fis_image_desc *first = NULL;
+ struct fis_image_desc *last = NULL;
+ struct fis_image_desc *first_fb = NULL;
+ struct fis_image_desc *last_fb = NULL;
+ struct fis_image_desc *desc;
+ struct fis_part *part;
+ uint32_t offset = 0, size = 0;
+ char *start, *end, *tmp;
+ int i;
+
+ desc = fis_open();
+ if (!desc)
+ return -1;
+
+ if (!quiet)
+ fprintf(stderr, "Updating FIS table... \n");
+
+ start = (char *) desc;
+ end = (char *) desc + fis_erasesize;
+ while ((char *) desc < end) {
+ if (!desc->hdr.name[0] || (desc->hdr.name[0] == 0xff))
+ break;
+
+ if (!strcmp((char *) desc->hdr.name, "FIS directory"))
+ fisdir = desc;
+
+ if (!strcmp((char *) desc->hdr.name, "RedBoot"))
+ redboot = desc;
+
+ /* update max offset */
+ if (offset < desc->hdr.flash_base)
+ offset = desc->hdr.flash_base;
+
+ for (i = 0; i < n_old; i++) {
+ if (!strncmp((char *) desc->hdr.name, (char *) old[i].name, sizeof(desc->hdr.name))) {
+ last = desc;
+ if (!first)
+ first = desc;
+ break;
+ }
+ }
+ desc++;
+ }
+ desc--;
+
+ first_fb = first;
+ last_fb = last;
+
+ if (first_fb->hdr.flash_base > last_fb->hdr.flash_base) {
+ first_fb = last;
+ last_fb = first;
+ }
+
+ /* determine size of available space */
+ desc = (struct fis_image_desc *) start;
+ while ((char *) desc < end) {
+ if (!desc->hdr.name[0] || (desc->hdr.name[0] == 0xff))
+ break;
+
+ if (desc->hdr.flash_base > last_fb->hdr.flash_base &&
+ desc->hdr.flash_base < offset)
+ offset = desc->hdr.flash_base;
+
+ desc++;
+ }
+ desc--;
+
+ size = offset - first_fb->hdr.flash_base;
+
+#ifdef notyet
+ desc = first - 1;
+ if (redboot && (desc >= redboot)) {
+ if (first->hdr.flash_base - desc->hdr.size > desc->hdr.flash_base) {
+ int delta = first->hdr.flash_base - desc->hdr.size - desc->hdr.flash_base;
+
+ offset -= delta;
+ size += delta;
+ }
+ }
+#endif
+
+ last++;
+ desc = first + n_new;
+ offset = first_fb->hdr.flash_base;
+
+ if (desc != last) {
+ if (desc > last)
+ tmp = (char *) desc;
+ else
+ tmp = (char *) last;
+
+ memmove(desc, last, end - tmp);
+ if (desc < last) {
+ tmp = end - (last - desc) * sizeof(struct fis_image_desc);
+ memset(tmp, 0xff, tmp - end);
+ }
+ }
+
+ for (part = new, desc = first; desc < first + n_new; desc++, part++) {
+ memset(desc, 0, sizeof(struct fis_image_desc));
+ memcpy(desc->hdr.name, part->name, sizeof(desc->hdr.name));
+ desc->crc.desc = 0;
+ desc->crc.file = 0;
+
+ desc->hdr.flash_base = offset;
+ desc->hdr.mem_base = part->loadaddr;
+ desc->hdr.entry_point = part->loadaddr;
+ desc->hdr.size = (part->size > 0) ? part->size : size;
+ desc->hdr.data_length = desc->hdr.size;
+
+ offset += desc->hdr.size;
+ size -= desc->hdr.size;
+ }
+
+ msync(fis_desc, fis_erasesize, MS_SYNC|MS_INVALIDATE);
+ fis_close();
+
+ return 0;
+}
diff --git a/package/mtd/src/fis.h b/package/mtd/src/fis.h
new file mode 100644
index 000000000..bdf1103d8
--- /dev/null
+++ b/package/mtd/src/fis.h
@@ -0,0 +1,14 @@
+#ifndef __FIS_H
+#define __FIS_H
+
+struct fis_part {
+ unsigned char name[16];
+ uint32_t offset;
+ uint32_t loadaddr;
+ uint32_t size;
+};
+
+int fis_validate(struct fis_part *old, int n_old, struct fis_part *new, int n_new);
+int fis_remap(struct fis_part *old, int n_old, struct fis_part *new, int n_new);
+
+#endif
diff --git a/package/mtd/src/imagetag.c b/package/mtd/src/imagetag.c
new file mode 100644
index 000000000..a4ce86d6e
--- /dev/null
+++ b/package/mtd/src/imagetag.c
@@ -0,0 +1,315 @@
+/*
+ * imagetag.c
+ *
+ * Copyright (C) 2005 Mike Baker
+ * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
+ * Copyrigth (C) 2010 Daniel Dickinson <openwrt@cshore.neomailbox.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/ioctl.h>
+#include <mtd/mtd-user.h>
+#include "mtd.h"
+#include "crc32.h"
+#include "bcm_tag.h"
+
+ssize_t pread(int fd, void *buf, size_t count, off_t offset);
+ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
+
+#define CRC_START 0xFFFFFFFF
+
+static uint32_t strntoul(char *str, char **endptr, int base, size_t len) {
+ char *newstr;
+ uint32_t res = 0;
+
+ newstr = calloc(len + 1, sizeof(char));
+ if (newstr) {
+ strncpy(newstr, str, len);
+ res = strtoul(newstr, endptr, base);
+ free(newstr);
+ }
+ return res;
+}
+
+uint32_t compute_crc32(uint32_t crc, off_t start, size_t compute_len, int fd)
+{
+ uint8_t readbuf[1024];
+ ssize_t res;
+ off_t offset = start;
+
+ /* Read a buffer's worth of bytes */
+ while (fd && (compute_len >= sizeof(readbuf))) {
+ res = pread(fd, readbuf, sizeof(readbuf), offset);
+ crc = crc32(crc, readbuf, res);
+ compute_len = compute_len - res;
+ offset += res;
+ }
+
+ /* Less than buffer-size bytes remains, read compute_len bytes */
+ if (fd && (compute_len > 0)) {
+ res = pread(fd, readbuf, compute_len, offset);
+ crc = crc32(crc, readbuf, res);
+ }
+
+ return crc;
+}
+
+int
+trx_fixup(int fd, const char *name)
+{
+ struct mtd_info_user mtdInfo;
+ unsigned long len;
+ void *ptr, *scan;
+ int bfd;
+ struct bcm_tag *tag;
+ ssize_t res;
+ uint32_t cfelen, imagelen, imagestart, rootfslen;
+ uint32_t imagecrc, rootfscrc, headercrc;
+ uint32_t offset = 0;
+ cfelen = imagelen = imagestart = imagecrc = rootfscrc = headercrc = rootfslen = 0;
+
+
+ if (ioctl(fd, MEMGETINFO, &mtdInfo) < 0) {
+ fprintf(stderr, "Failed to get mtd info\n");
+ goto err;
+ }
+
+ len = mtdInfo.size;
+ if (mtdInfo.size <= 0) {
+ fprintf(stderr, "Invalid MTD device size\n");
+ goto err;
+ }
+
+ bfd = mtd_open(name, true);
+ ptr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, bfd, 0);
+ if (!ptr || (ptr == (void *) -1)) {
+ perror("mmap");
+ goto err1;
+ }
+
+ tag = (struct bcm_tag *) (ptr);
+
+ cfelen = strntoul(&tag->cfeLength[0], NULL, 10, IMAGE_LEN);
+ if (cfelen) {
+ fprintf(stderr, "Non-zero CFE length. This is currently unsupported.\n");
+ exit(1);
+ }
+
+ headercrc = compute_crc32(CRC_START, offset, offsetof(struct bcm_tag, headerCRC), fd);
+ if (headercrc != *(uint32_t *)(&tag->headerCRC[0])) {
+ fprintf(stderr, "Tag verify failed. This may not be a valid image.\n");
+ exit(1);
+ }
+
+ sprintf(&tag->flashRootLength[0], "%lu", 0);
+ strncpy(&tag->totalLength[0], &tag->kernelLength[0], IMAGE_LEN);
+
+ imagestart = sizeof(tag);
+ memcpy(&tag->imageCRC[0], &tag->kernelCRC[0], CRC_LEN);
+ memcpy(&tag->fskernelCRC[0], &tag->kernelCRC[0], CRC_LEN);
+ rootfscrc = CRC_START;
+ memcpy(&tag->rootfsCRC[0], &rootfscrc, sizeof(uint32_t));
+ headercrc = crc32(CRC_START, tag, offsetof(struct bcm_tag, headerCRC));
+ memcpy(&tag->headerCRC[0], &headercrc, sizeof(uint32_t));
+
+ msync(ptr, sizeof(struct bcm_tag), MS_SYNC|MS_INVALIDATE);
+ munmap(ptr, len);
+ close(bfd);
+ return 0;
+
+err1:
+ close(bfd);
+err:
+ fprintf(stderr, "Error fixing up imagetag header\n");
+ return -1;
+}
+
+
+int
+trx_check(int imagefd, const char *mtd, char *buf, int *len)
+{
+ struct bcm_tag *tag = (const struct bcm_tag *) buf;
+ int fd;
+ uint32_t headerCRC;
+ uint32_t imageLen;
+
+ if (strcmp(mtd, "linux") != 0)
+ return 1;
+
+ *len = read(imagefd, buf, sizeof(struct bcm_tag));
+ if (*len < sizeof(struct bcm_tag)) {
+ fprintf(stdout, "Could not get image header, file too small (%d bytes)\n", *len);
+ return 0;
+ }
+ headerCRC = crc32buf(buf, offsetof(struct bcm_tag, headerCRC));
+ if (*(uint32_t *)(&tag->headerCRC[0]) != headerCRC) {
+
+ if (quiet < 2) {
+ fprintf(stderr, "Bad header CRC got %08lx, calculated %08lx\n",
+ *(uint32_t *)(&tag->headerCRC[0]), headerCRC);
+ fprintf(stderr, "This is not the correct file format; refusing to flash.\n"
+ "Please specify the correct file or use -f to force.\n");
+ }
+ return 0;
+ }
+
+ /* check if image fits to mtd device */
+ fd = mtd_check_open(mtd);
+ if(fd < 0) {
+ fprintf(stderr, "Could not open mtd device: %s\n", mtd);
+ exit(1);
+ }
+
+ imageLen = strntoul(&tag->totalLength[0], NULL, 10, IMAGE_LEN);
+
+ if(mtdsize < imageLen) {
+ fprintf(stderr, "Image too big for partition: %s\n", mtd);
+ close(fd);
+ return 0;
+ }
+
+ close(fd);
+ return 1;
+}
+
+int
+mtd_fixtrx(const char *mtd, size_t offset)
+{
+ int fd;
+ struct bcm_tag *tag;
+ char *buf;
+ ssize_t res;
+ size_t block_offset;
+ uint32_t cfelen, imagelen, imagestart, rootfslen;
+ uint32_t imagecrc, rootfscrc, headercrc;
+ cfelen = imagelen = imagestart = imagecrc = rootfscrc = headercrc = rootfslen = 0;
+
+ if (quiet < 2)
+ fprintf(stderr, "Trying to fix trx header in %s at 0x%x...\n", mtd, offset);
+
+ block_offset = offset & ~(erasesize - 1);
+ offset -= block_offset;
+
+ fd = mtd_check_open(mtd);
+ if(fd < 0) {
+ fprintf(stderr, "Could not open mtd device: %s\n", mtd);
+ exit(1);
+ }
+
+ if (block_offset + erasesize > mtdsize) {
+ fprintf(stderr, "Offset too large, device size 0x%x\n", mtdsize);
+ exit(1);
+ }
+
+ buf = malloc(erasesize);
+ if (!buf) {
+ perror("malloc");
+ exit(1);
+ }
+
+ res = pread(fd, buf, erasesize, block_offset);
+ if (res != erasesize) {
+ perror("pread");
+ exit(1);
+ }
+
+ tag = (struct bcm_tag *) (buf + offset);
+
+ cfelen = strntoul(&tag->cfeLength[0], NULL, 10, IMAGE_LEN);
+ if (cfelen) {
+ fprintf(stderr, "Non-zero CFE length. This is currently unsupported.\n");
+ exit(1);
+ }
+
+ if (quiet < 2) {
+ fprintf(stderr, "Verifying we actually have an imagetag.\n");
+ }
+
+ headercrc = compute_crc32(CRC_START, offset, offsetof(struct bcm_tag, headerCRC), fd);
+ if (headercrc != *(uint32_t *)(&tag->headerCRC[0])) {
+ fprintf(stderr, "Tag verify failed. This may not be a valid image.\n");
+ exit(1);
+ }
+
+ if (quiet < 2) {
+ fprintf(stderr, "Checking current fixed status.\n");
+ }
+
+ rootfslen = strntoul(&tag->flashRootLength[0], NULL, 10, IMAGE_LEN);
+ if (rootfslen == 0) {
+ if (quiet < 2)
+ fprintf(stderr, "Header already fixed, exiting\n");
+ close(fd);
+ return 0;
+ }
+
+ if (quiet < 2) {
+ fprintf(stderr, "Setting root length to 0.\n");
+ }
+
+ sprintf(&tag->flashRootLength[0], "%lu", 0);
+ strncpy(&tag->totalLength[0], &tag->kernelLength[0], IMAGE_LEN);
+
+ if (quiet < 2) {
+ fprintf(stderr, "Recalculating CRCs.\n");
+ }
+
+ imagestart = sizeof(tag);
+ memcpy(&tag->imageCRC[0], &tag->kernelCRC[0], CRC_LEN);
+ memcpy(&tag->fskernelCRC[0], &tag->kernelCRC[0], CRC_LEN);
+ rootfscrc = CRC_START;
+ memcpy(&tag->rootfsCRC[0], &rootfscrc, sizeof(uint32_t));
+ headercrc = crc32(CRC_START, tag, offsetof(struct bcm_tag, headerCRC));
+ memcpy(&tag->headerCRC[0], &headercrc, sizeof(uint32_t));
+
+ if (quiet < 2) {
+ fprintf(stderr, "Erasing imagetag block\n");
+ }
+
+ if (mtd_erase_block(fd, block_offset)) {
+ fprintf(stderr, "Can't erase block at 0x%x (%s)\n", block_offset, strerror(errno));
+ exit(1);
+ }
+
+ if (quiet < 2) {
+ fprintf(stderr, "New image crc32: 0x%x, rewriting block\n",
+ *(uint32_t *)(&tag->imageCRC[0]));
+ fprintf(stderr, "New header crc32: 0x%x, rewriting block\n", headercrc);
+ }
+
+ if (pwrite(fd, buf, erasesize, block_offset) != erasesize) {
+ fprintf(stderr, "Error writing block (%s)\n", strerror(errno));
+ exit(1);
+ }
+
+ if (quiet < 2)
+ fprintf(stderr, "Done.\n");
+
+ close (fd);
+ sync();
+ return 0;
+
+}
diff --git a/package/mtd/src/jffs2.c b/package/mtd/src/jffs2.c
new file mode 100644
index 000000000..2a83bd47f
--- /dev/null
+++ b/package/mtd/src/jffs2.c
@@ -0,0 +1,357 @@
+/*
+ * jffs2 on-disk structure generator for mtd
+ *
+ * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License v2
+ * 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.
+ * Based on:
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ * Copyright © 2001-2007 Red Hat, Inc.
+ * Created by David Woodhouse <dwmw2@infradead.org>
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <endian.h>
+#include "jffs2.h"
+#include "crc32.h"
+#include "mtd.h"
+
+#define PAD(x) (((x)+3)&~3)
+
+#if BYTE_ORDER == BIG_ENDIAN
+# define CLEANMARKER "\x19\x85\x20\x03\x00\x00\x00\x0c\xf0\x60\xdc\x98"
+#else
+# define CLEANMARKER "\x85\x19\x03\x20\x0c\x00\x00\x00\xb1\xb0\x1e\xe4"
+#endif
+
+static int last_ino = 0;
+static int last_version = 0;
+static char *buf = NULL;
+static int ofs = 0;
+static int outfd = -1;
+static int mtdofs = 0;
+static int target_ino = 0;
+
+static void prep_eraseblock(void);
+
+static void pad(int size)
+{
+ if ((ofs % size == 0) && (ofs < erasesize))
+ return;
+
+ if (ofs < erasesize) {
+ memset(buf + ofs, 0xff, (size - (ofs % size)));
+ ofs += (size - (ofs % size));
+ }
+ ofs = ofs % erasesize;
+ if (ofs == 0) {
+ mtd_erase_block(outfd, mtdofs);
+ write(outfd, buf, erasesize);
+ mtdofs += erasesize;
+ }
+}
+
+static inline int rbytes(void)
+{
+ return erasesize - (ofs % erasesize);
+}
+
+static inline void add_data(char *ptr, int len)
+{
+ if (ofs + len > erasesize) {
+ pad(erasesize);
+ prep_eraseblock();
+ }
+ memcpy(buf + ofs, ptr, len);
+ ofs += len;
+}
+
+static void prep_eraseblock(void)
+{
+ if (ofs > 0)
+ return;
+
+ add_data(CLEANMARKER, sizeof(CLEANMARKER) - 1);
+}
+
+static int add_dirent(const char *name, const char type, int parent)
+{
+ struct jffs2_raw_dirent *de;
+
+ if (ofs - erasesize < sizeof(struct jffs2_raw_dirent) + strlen(name))
+ pad(erasesize);
+
+ prep_eraseblock();
+ last_ino++;
+ memset(buf + ofs, 0, sizeof(struct jffs2_raw_dirent));
+ de = (struct jffs2_raw_dirent *) (buf + ofs);
+
+ de->magic = JFFS2_MAGIC_BITMASK;
+ de->nodetype = JFFS2_NODETYPE_DIRENT;
+ de->type = type;
+ de->name_crc = crc32(0, name, strlen(name));
+ de->ino = last_ino++;
+ de->pino = parent;
+ de->totlen = sizeof(*de) + strlen(name);
+ de->hdr_crc = crc32(0, (void *) de, sizeof(struct jffs2_unknown_node) - 4);
+ de->version = last_version++;
+ de->mctime = 0;
+ de->nsize = strlen(name);
+ de->node_crc = crc32(0, (void *) de, sizeof(*de) - 8);
+ memcpy(de->name, name, strlen(name));
+
+ ofs += sizeof(struct jffs2_raw_dirent) + de->nsize;
+ pad(4);
+
+ return de->ino;
+}
+
+static int add_dir(const char *name, int parent)
+{
+ struct jffs2_raw_inode ri;
+ int inode;
+
+ inode = add_dirent(name, IFTODT(S_IFDIR), parent);
+
+ if (rbytes() < sizeof(ri))
+ pad(erasesize);
+ prep_eraseblock();
+
+ memset(&ri, 0, sizeof(ri));
+ ri.magic = JFFS2_MAGIC_BITMASK;
+ ri.nodetype = JFFS2_NODETYPE_INODE;
+ ri.totlen = sizeof(ri);
+ ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node) - 4);
+
+ ri.ino = inode;
+ ri.mode = S_IFDIR | 0755;
+ ri.uid = ri.gid = 0;
+ ri.atime = ri.ctime = ri.mtime = 0;
+ ri.isize = ri.csize = ri.dsize = 0;
+ ri.version = 1;
+ ri.node_crc = crc32(0, &ri, sizeof(ri) - 8);
+ ri.data_crc = 0;
+
+ add_data((char *) &ri, sizeof(ri));
+ pad(4);
+ return inode;
+}
+
+static void add_file(const char *name, int parent)
+{
+ int inode, f_offset = 0, fd;
+ struct jffs2_raw_inode ri;
+ struct stat st;
+ char wbuf[4096];
+ const char *fname;
+
+ if (stat(name, &st)) {
+ fprintf(stderr, "File %s does not exist\n", name);
+ return;
+ }
+
+ fname = strrchr(name, '/');
+ if (fname)
+ fname++;
+ else
+ fname = name;
+
+ inode = add_dirent(fname, IFTODT(S_IFREG), parent);
+ memset(&ri, 0, sizeof(ri));
+ ri.magic = JFFS2_MAGIC_BITMASK;
+ ri.nodetype = JFFS2_NODETYPE_INODE;
+
+ ri.ino = inode;
+ ri.mode = st.st_mode;
+ ri.uid = ri.gid = 0;
+ ri.atime = st.st_atime;
+ ri.ctime = st.st_ctime;
+ ri.mtime = st.st_mtime;
+ ri.isize = st.st_size;
+ ri.compr = 0;
+ ri.usercompr = 0;
+
+ fd = open(name, 0);
+ if (fd < 0) {
+ fprintf(stderr, "File %s does not exist\n", name);
+ return;
+ }
+
+ for (;;) {
+ int len = 0;
+
+ for (;;) {
+ len = rbytes() - sizeof(ri);
+ if (len > 128)
+ break;
+
+ pad(erasesize);
+ prep_eraseblock();
+ }
+
+ if (len > sizeof(wbuf))
+ len = sizeof(wbuf);
+
+ len = read(fd, wbuf, len);
+ if (len <= 0)
+ break;
+
+ ri.totlen = sizeof(ri) + len;
+ ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node) - 4);
+ ri.version = ++last_version;
+ ri.offset = f_offset;
+ ri.csize = ri.dsize = len;
+ ri.node_crc = crc32(0, &ri, sizeof(ri) - 8);
+ ri.data_crc = crc32(0, wbuf, len);
+ f_offset += len;
+ add_data((char *) &ri, sizeof(ri));
+ add_data(wbuf, len);
+ pad(4);
+ prep_eraseblock();
+ }
+
+ close(fd);
+}
+
+int mtd_replace_jffs2(const char *mtd, int fd, int ofs, const char *filename)
+{
+ outfd = fd;
+ mtdofs = ofs;
+
+ buf = malloc(erasesize);
+ target_ino = 1;
+ if (!last_ino)
+ last_ino = 1;
+ add_file(filename, target_ino);
+ pad(erasesize);
+
+ /* add eof marker, pad to eraseblock size and write the data */
+ add_data(JFFS2_EOF, sizeof(JFFS2_EOF) - 1);
+ pad(erasesize);
+ free(buf);
+
+ return (mtdofs - ofs);
+}
+
+void mtd_parse_jffs2data(const char *buf, const char *dir)
+{
+ struct jffs2_unknown_node *node = (struct jffs2_unknown_node *) buf;
+ unsigned int ofs = 0;
+
+ while (ofs < erasesize) {
+ node = (struct jffs2_unknown_node *) (buf + ofs);
+ if (node->magic != 0x1985)
+ break;
+
+ ofs += PAD(node->totlen);
+ if (node->nodetype == JFFS2_NODETYPE_DIRENT) {
+ struct jffs2_raw_dirent *de = (struct jffs2_raw_dirent *) node;
+
+ /* is this the right directory name and is it a subdirectory of / */
+ if (*dir && (de->pino == 1) && !strncmp((char *) de->name, dir, de->nsize))
+ target_ino = de->ino;
+
+ /* store the last inode and version numbers for adding extra files */
+ if (last_ino < de->ino)
+ last_ino = de->ino;
+ if (last_version < de->version)
+ last_version = de->version;
+ }
+ }
+}
+
+int mtd_write_jffs2(const char *mtd, const char *filename, const char *dir)
+{
+ int err = -1, fdeof = 0;
+
+ outfd = mtd_check_open(mtd);
+ if (outfd < 0)
+ return -1;
+
+ if (quiet < 2)
+ fprintf(stderr, "Appending %s to jffs2 partition %s\n", filename, mtd);
+
+ buf = malloc(erasesize);
+ if (!buf) {
+ fprintf(stderr, "Out of memory!\n");
+ goto done;
+ }
+
+ if (!*dir)
+ target_ino = 1;
+
+ /* parse the structure of the jffs2 first
+ * locate the directory that the file is going to be placed in */
+ for(;;) {
+ struct jffs2_unknown_node *node = (struct jffs2_unknown_node *) buf;
+
+ if (read(outfd, buf, erasesize) != erasesize) {
+ fdeof = 1;
+ break;
+ }
+ mtdofs += erasesize;
+
+ if (node->magic == 0x8519) {
+ fprintf(stderr, "Error: wrong endianness filesystem\n");
+ goto done;
+ }
+
+ /* assume no magic == end of filesystem
+ * the filesystem will probably end with be32(0xdeadc0de) */
+ if (node->magic != 0x1985)
+ break;
+
+ mtd_parse_jffs2data(buf, dir);
+ }
+
+ if (fdeof) {
+ fprintf(stderr, "Error: No room for additional data\n");
+ goto done;
+ }
+
+ /* jump back one eraseblock */
+ mtdofs -= erasesize;
+ lseek(outfd, mtdofs, SEEK_SET);
+
+ ofs = 0;
+
+ if (!last_ino)
+ last_ino = 1;
+
+ if (!target_ino)
+ target_ino = add_dir(dir, 1);
+
+ add_file(filename, target_ino);
+ pad(erasesize);
+
+ /* add eof marker, pad to eraseblock size and write the data */
+ add_data(JFFS2_EOF, sizeof(JFFS2_EOF) - 1);
+ pad(erasesize);
+
+ err = 0;
+
+ if (trx_fixup) {
+ trx_fixup(outfd, mtd);
+ }
+
+done:
+ close(outfd);
+ if (buf)
+ free(buf);
+
+ return err;
+}
diff --git a/package/mtd/src/jffs2.h b/package/mtd/src/jffs2.h
new file mode 100644
index 000000000..858e77a01
--- /dev/null
+++ b/package/mtd/src/jffs2.h
@@ -0,0 +1,216 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2001-2003 Red Hat, Inc.
+ *
+ * Created by David Woodhouse <dwmw2@infradead.org>
+ *
+ * For licensing information, see the file 'LICENCE' in the
+ * jffs2 directory.
+ *
+ *
+ */
+
+#ifndef __LINUX_JFFS2_H__
+#define __LINUX_JFFS2_H__
+
+#define JFFS2_SUPER_MAGIC 0x72b6
+
+/* You must include something which defines the C99 uintXX_t types.
+ We don't do it from here because this file is used in too many
+ different environments. */
+
+/* Values we may expect to find in the 'magic' field */
+#define JFFS2_OLD_MAGIC_BITMASK 0x1984
+#define JFFS2_MAGIC_BITMASK 0x1985
+#define KSAMTIB_CIGAM_2SFFJ 0x8519 /* For detecting wrong-endian fs */
+#define JFFS2_EMPTY_BITMASK 0xffff
+#define JFFS2_DIRTY_BITMASK 0x0000
+
+/* Summary node MAGIC marker */
+#define JFFS2_SUM_MAGIC 0x02851885
+
+/* We only allow a single char for length, and 0xFF is empty flash so
+ we don't want it confused with a real length. Hence max 254.
+*/
+#define JFFS2_MAX_NAME_LEN 254
+
+/* How small can we sensibly write nodes? */
+#define JFFS2_MIN_DATA_LEN 128
+
+#define JFFS2_COMPR_NONE 0x00
+#define JFFS2_COMPR_ZERO 0x01
+#define JFFS2_COMPR_RTIME 0x02
+#define JFFS2_COMPR_RUBINMIPS 0x03
+#define JFFS2_COMPR_COPY 0x04
+#define JFFS2_COMPR_DYNRUBIN 0x05
+#define JFFS2_COMPR_ZLIB 0x06
+/* Compatibility flags. */
+#define JFFS2_COMPAT_MASK 0xc000 /* What do to if an unknown nodetype is found */
+#define JFFS2_NODE_ACCURATE 0x2000
+/* INCOMPAT: Fail to mount the filesystem */
+#define JFFS2_FEATURE_INCOMPAT 0xc000
+/* ROCOMPAT: Mount read-only */
+#define JFFS2_FEATURE_ROCOMPAT 0x8000
+/* RWCOMPAT_COPY: Mount read/write, and copy the node when it's GC'd */
+#define JFFS2_FEATURE_RWCOMPAT_COPY 0x4000
+/* RWCOMPAT_DELETE: Mount read/write, and delete the node when it's GC'd */
+#define JFFS2_FEATURE_RWCOMPAT_DELETE 0x0000
+
+#define JFFS2_NODETYPE_DIRENT (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 1)
+#define JFFS2_NODETYPE_INODE (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 2)
+#define JFFS2_NODETYPE_CLEANMARKER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)
+#define JFFS2_NODETYPE_PADDING (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 4)
+
+#define JFFS2_NODETYPE_SUMMARY (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 6)
+
+#define JFFS2_NODETYPE_XATTR (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 8)
+#define JFFS2_NODETYPE_XREF (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 9)
+
+/* XATTR Related */
+#define JFFS2_XPREFIX_USER 1 /* for "user." */
+#define JFFS2_XPREFIX_SECURITY 2 /* for "security." */
+#define JFFS2_XPREFIX_ACL_ACCESS 3 /* for "system.posix_acl_access" */
+#define JFFS2_XPREFIX_ACL_DEFAULT 4 /* for "system.posix_acl_default" */
+#define JFFS2_XPREFIX_TRUSTED 5 /* for "trusted.*" */
+
+#define JFFS2_ACL_VERSION 0x0001
+
+// Maybe later...
+//#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)
+//#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4)
+
+
+#define JFFS2_INO_FLAG_PREREAD 1 /* Do read_inode() for this one at
+ mount time, don't wait for it to
+ happen later */
+#define JFFS2_INO_FLAG_USERCOMPR 2 /* User has requested a specific
+ compression type */
+
+
+/* These can go once we've made sure we've caught all uses without
+ byteswapping */
+
+typedef uint32_t jint32_t;
+
+typedef uint32_t jmode_t;
+
+typedef uint16_t jint16_t;
+
+struct jffs2_unknown_node
+{
+ /* All start like this */
+ jint16_t magic;
+ jint16_t nodetype;
+ jint32_t totlen; /* So we can skip over nodes we don't grok */
+ jint32_t hdr_crc;
+};
+
+struct jffs2_raw_dirent
+{
+ jint16_t magic;
+ jint16_t nodetype; /* == JFFS2_NODETYPE_DIRENT */
+ jint32_t totlen;
+ jint32_t hdr_crc;
+ jint32_t pino;
+ jint32_t version;
+ jint32_t ino; /* == zero for unlink */
+ jint32_t mctime;
+ uint8_t nsize;
+ uint8_t type;
+ uint8_t unused[2];
+ jint32_t node_crc;
+ jint32_t name_crc;
+ uint8_t name[0];
+};
+
+/* The JFFS2 raw inode structure: Used for storage on physical media. */
+/* The uid, gid, atime, mtime and ctime members could be longer, but
+ are left like this for space efficiency. If and when people decide
+ they really need them extended, it's simple enough to add support for
+ a new type of raw node.
+*/
+struct jffs2_raw_inode
+{
+ jint16_t magic; /* A constant magic number. */
+ jint16_t nodetype; /* == JFFS2_NODETYPE_INODE */
+ jint32_t totlen; /* Total length of this node (inc data, etc.) */
+ jint32_t hdr_crc;
+ jint32_t ino; /* Inode number. */
+ jint32_t version; /* Version number. */
+ jmode_t mode; /* The file's type or mode. */
+ jint16_t uid; /* The file's owner. */
+ jint16_t gid; /* The file's group. */
+ jint32_t isize; /* Total resultant size of this inode (used for truncations) */
+ jint32_t atime; /* Last access time. */
+ jint32_t mtime; /* Last modification time. */
+ jint32_t ctime; /* Change time. */
+ jint32_t offset; /* Where to begin to write. */
+ jint32_t csize; /* (Compressed) data size */
+ jint32_t dsize; /* Size of the node's data. (after decompression) */
+ uint8_t compr; /* Compression algorithm used */
+ uint8_t usercompr; /* Compression algorithm requested by the user */
+ jint16_t flags; /* See JFFS2_INO_FLAG_* */
+ jint32_t data_crc; /* CRC for the (compressed) data. */
+ jint32_t node_crc; /* CRC for the raw inode (excluding data) */
+ uint8_t data[0];
+};
+
+struct jffs2_raw_xattr {
+ jint16_t magic;
+ jint16_t nodetype; /* = JFFS2_NODETYPE_XATTR */
+ jint32_t totlen;
+ jint32_t hdr_crc;
+ jint32_t xid; /* XATTR identifier number */
+ jint32_t version;
+ uint8_t xprefix;
+ uint8_t name_len;
+ jint16_t value_len;
+ jint32_t data_crc;
+ jint32_t node_crc;
+ uint8_t data[0];
+} __attribute__((packed));
+
+struct jffs2_raw_xref
+{
+ jint16_t magic;
+ jint16_t nodetype; /* = JFFS2_NODETYPE_XREF */
+ jint32_t totlen;
+ jint32_t hdr_crc;
+ jint32_t ino; /* inode number */
+ jint32_t xid; /* XATTR identifier number */
+ jint32_t xseqno; /* xref sequencial number */
+ jint32_t node_crc;
+} __attribute__((packed));
+
+struct jffs2_raw_summary
+{
+ jint16_t magic;
+ jint16_t nodetype; /* = JFFS2_NODETYPE_SUMMARY */
+ jint32_t totlen;
+ jint32_t hdr_crc;
+ jint32_t sum_num; /* number of sum entries*/
+ jint32_t cln_mkr; /* clean marker size, 0 = no cleanmarker */
+ jint32_t padded; /* sum of the size of padding nodes */
+ jint32_t sum_crc; /* summary information crc */
+ jint32_t node_crc; /* node crc */
+ jint32_t sum[0]; /* inode summary info */
+};
+
+union jffs2_node_union
+{
+ struct jffs2_raw_inode i;
+ struct jffs2_raw_dirent d;
+ struct jffs2_raw_xattr x;
+ struct jffs2_raw_xref r;
+ struct jffs2_raw_summary s;
+ struct jffs2_unknown_node u;
+};
+
+/* Data payload for device nodes. */
+union jffs2_device_node {
+ jint16_t old;
+ jint32_t new;
+};
+
+#endif /* __LINUX_JFFS2_H__ */
diff --git a/package/mtd/src/mtd.c b/package/mtd/src/mtd.c
new file mode 100644
index 000000000..18efcf57c
--- /dev/null
+++ b/package/mtd/src/mtd.c
@@ -0,0 +1,750 @@
+/*
+ * mtd - simple memory technology device manipulation tool
+ *
+ * Copyright (C) 2005 Waldemar Brodkorb <wbx@dass-it.de>,
+ * Copyright (C) 2005-2009 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License v2
+ * 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.
+ *
+ *
+ * The code is based on the linux-mtd examples.
+ */
+
+#include <limits.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/syscall.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <error.h>
+#include <time.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/reboot.h>
+#include <linux/reboot.h>
+#include <mtd/mtd-user.h>
+#include "fis.h"
+#include "mtd.h"
+
+#ifndef MTDREFRESH
+#define MTDREFRESH _IO('M', 50)
+#endif
+
+#define MAX_ARGS 8
+#define JFFS2_DEFAULT_DIR "" /* directory name without /, empty means root dir */
+
+static char *buf = NULL;
+static char *imagefile = NULL;
+static char *jffs2file = NULL, *jffs2dir = JFFS2_DEFAULT_DIR;
+static int buflen = 0;
+int quiet;
+int no_erase;
+int mtdsize = 0;
+int erasesize = 0;
+
+int mtd_open(const char *mtd, bool block)
+{
+ FILE *fp;
+ char dev[PATH_MAX];
+ int i;
+ int ret;
+ int flags = O_RDWR | O_SYNC;
+
+ if ((fp = fopen("/proc/mtd", "r"))) {
+ while (fgets(dev, sizeof(dev), fp)) {
+ if (sscanf(dev, "mtd%d:", &i) && strstr(dev, mtd)) {
+ snprintf(dev, sizeof(dev), "/dev/mtd%s/%d", (block ? "block" : ""), i);
+ if ((ret=open(dev, flags))<0) {
+ snprintf(dev, sizeof(dev), "/dev/mtd%s%d", (block ? "block" : ""), i);
+ ret=open(dev, flags);
+ }
+ fclose(fp);
+ return ret;
+ }
+ }
+ fclose(fp);
+ }
+
+ return open(mtd, flags);
+}
+
+int mtd_check_open(const char *mtd)
+{
+ struct mtd_info_user mtdInfo;
+ int fd;
+
+ fd = mtd_open(mtd, false);
+ if(fd < 0) {
+ fprintf(stderr, "Could not open mtd device: %s\n", mtd);
+ return -1;
+ }
+
+ if(ioctl(fd, MEMGETINFO, &mtdInfo)) {
+ fprintf(stderr, "Could not get MTD device info from %s\n", mtd);
+ close(fd);
+ return -1;
+ }
+ mtdsize = mtdInfo.size;
+ erasesize = mtdInfo.erasesize;
+
+ return fd;
+}
+
+int mtd_erase_block(int fd, int offset)
+{
+ struct erase_info_user mtdEraseInfo;
+
+ mtdEraseInfo.start = offset;
+ mtdEraseInfo.length = erasesize;
+ ioctl(fd, MEMUNLOCK, &mtdEraseInfo);
+ if (ioctl (fd, MEMERASE, &mtdEraseInfo) < 0)
+ return -1;
+
+ return 0;
+}
+
+int mtd_write_buffer(int fd, const char *buf, int offset, int length)
+{
+ lseek(fd, offset, SEEK_SET);
+ write(fd, buf, length);
+ return 0;
+}
+
+
+static int
+image_check(int imagefd, const char *mtd)
+{
+ int ret = 1;
+ if (trx_check) {
+ ret = trx_check(imagefd, mtd, buf, &buflen);
+ }
+ return ret;
+}
+
+static int mtd_check(const char *mtd)
+{
+ char *next = NULL;
+ char *str = NULL;
+ int fd;
+
+ if (strchr(mtd, ':')) {
+ str = strdup(mtd);
+ mtd = str;
+ }
+
+ do {
+ next = strchr(mtd, ':');
+ if (next) {
+ *next = 0;
+ next++;
+ }
+
+ fd = mtd_check_open(mtd);
+ if (fd < 0)
+ return 0;
+
+ if (!buf)
+ buf = malloc(erasesize);
+
+ close(fd);
+ mtd = next;
+ } while (next);
+
+ if (str)
+ free(str);
+
+ return 1;
+}
+
+static int
+mtd_unlock(const char *mtd)
+{
+ struct erase_info_user mtdLockInfo;
+ char *next = NULL;
+ char *str = NULL;
+ int fd;
+
+ if (strchr(mtd, ':')) {
+ str = strdup(mtd);
+ mtd = str;
+ }
+
+ do {
+ next = strchr(mtd, ':');
+ if (next) {
+ *next = 0;
+ next++;
+ }
+
+ fd = mtd_check_open(mtd);
+ if(fd < 0) {
+ fprintf(stderr, "Could not open mtd device: %s\n", mtd);
+ exit(1);
+ }
+
+ if (quiet < 2)
+ fprintf(stderr, "Unlocking %s ...\n", mtd);
+
+ mtdLockInfo.start = 0;
+ mtdLockInfo.length = mtdsize;
+ ioctl(fd, MEMUNLOCK, &mtdLockInfo);
+ close(fd);
+ mtd = next;
+ } while (next);
+
+ if (str)
+ free(str);
+
+ return 0;
+}
+
+static int
+mtd_erase(const char *mtd)
+{
+ int fd;
+ struct erase_info_user mtdEraseInfo;
+
+ if (quiet < 2)
+ fprintf(stderr, "Erasing %s ...\n", mtd);
+
+ fd = mtd_check_open(mtd);
+ if(fd < 0) {
+ fprintf(stderr, "Could not open mtd device: %s\n", mtd);
+ exit(1);
+ }
+
+ mtdEraseInfo.length = erasesize;
+
+ for (mtdEraseInfo.start = 0;
+ mtdEraseInfo.start < mtdsize;
+ mtdEraseInfo.start += erasesize) {
+
+ ioctl(fd, MEMUNLOCK, &mtdEraseInfo);
+ if(ioctl(fd, MEMERASE, &mtdEraseInfo))
+ fprintf(stderr, "Failed to erase block on %s at 0x%x\n", mtd, mtdEraseInfo.start);
+ }
+
+ close(fd);
+ return 0;
+
+}
+
+static int
+mtd_refresh(const char *mtd)
+{
+ int fd;
+
+ if (quiet < 2)
+ fprintf(stderr, "Refreshing mtd partition %s ... ", mtd);
+
+ fd = mtd_check_open(mtd);
+ if(fd < 0) {
+ fprintf(stderr, "Could not open mtd device: %s\n", mtd);
+ exit(1);
+ }
+
+ if (ioctl(fd, MTDREFRESH, NULL)) {
+ fprintf(stderr, "Failed to refresh the MTD device\n");
+ close(fd);
+ exit(1);
+ }
+ close(fd);
+
+ if (quiet < 2)
+ fprintf(stderr, "\n");
+
+ return 0;
+}
+
+static void
+indicate_writing(const char *mtd)
+{
+ if (quiet < 2)
+ fprintf(stderr, "\nWriting from %s to %s ... ", imagefile, mtd);
+
+ if (!quiet)
+ fprintf(stderr, " [ ]");
+}
+
+static int
+mtd_write(int imagefd, const char *mtd, char *fis_layout, size_t part_offset)
+{
+ char *next = NULL;
+ char *str = NULL;
+ int fd, result;
+ ssize_t r, w, e;
+ ssize_t skip = 0;
+ uint32_t offset = 0;
+ int jffs2_replaced = 0;
+
+#ifdef FIS_SUPPORT
+ static struct fis_part new_parts[MAX_ARGS];
+ static struct fis_part old_parts[MAX_ARGS];
+ int n_new = 0, n_old = 0;
+
+ if (fis_layout) {
+ const char *tmp = mtd;
+ char *word, *brkt;
+ int ret;
+
+ memset(&old_parts, 0, sizeof(old_parts));
+ memset(&new_parts, 0, sizeof(new_parts));
+
+ do {
+ next = strchr(tmp, ':');
+ if (!next)
+ next = (char *) tmp + strlen(tmp);
+
+ memcpy(old_parts[n_old].name, tmp, next - tmp);
+
+ n_old++;
+ tmp = next + 1;
+ } while(*next);
+
+ for (word = strtok_r(fis_layout, ",", &brkt);
+ word;
+ word = strtok_r(NULL, ",", &brkt)) {
+
+ tmp = strtok(word, ":");
+ strncpy((char *) new_parts[n_new].name, tmp, sizeof(new_parts[n_new].name) - 1);
+
+ tmp = strtok(NULL, ":");
+ if (!tmp)
+ goto next;
+
+ new_parts[n_new].size = strtoul(tmp, NULL, 0);
+
+ tmp = strtok(NULL, ":");
+ if (!tmp)
+ goto next;
+
+ new_parts[n_new].loadaddr = strtoul(tmp, NULL, 16);
+next:
+ n_new++;
+ }
+ ret = fis_validate(old_parts, n_old, new_parts, n_new);
+ if (ret < 0) {
+ fprintf(stderr, "Failed to validate the new FIS partition table\n");
+ exit(1);
+ }
+ if (ret == 0)
+ fis_layout = NULL;
+ }
+#endif
+
+ if (strchr(mtd, ':')) {
+ str = strdup(mtd);
+ mtd = str;
+ }
+
+ r = 0;
+
+resume:
+ next = strchr(mtd, ':');
+ if (next) {
+ *next = 0;
+ next++;
+ }
+
+ fd = mtd_check_open(mtd);
+ if(fd < 0) {
+ fprintf(stderr, "Could not open mtd device: %s\n", mtd);
+ exit(1);
+ }
+
+ if (part_offset > 0) {
+ fprintf(stderr, "Seeking on mtd device '%s' to: %u\n", mtd, part_offset);
+ lseek(fd, part_offset, SEEK_SET);
+ }
+
+ indicate_writing(mtd);
+
+ w = e = 0;
+ for (;;) {
+ /* buffer may contain data already (from trx check or last mtd partition write attempt) */
+ while (buflen < erasesize) {
+ r = read(imagefd, buf + buflen, erasesize - buflen);
+ if (r < 0) {
+ if ((errno == EINTR) || (errno == EAGAIN))
+ continue;
+ else {
+ perror("read");
+ break;
+ }
+ }
+
+ if (r == 0)
+ break;
+
+ buflen += r;
+ }
+
+ if (buflen == 0)
+ break;
+
+ if (skip > 0) {
+ skip -= buflen;
+ buflen = 0;
+ if (skip <= 0)
+ indicate_writing(mtd);
+
+ continue;
+ }
+
+ if (jffs2file) {
+ if (memcmp(buf, JFFS2_EOF, sizeof(JFFS2_EOF) - 1) == 0) {
+ if (!quiet)
+ fprintf(stderr, "\b\b\b ");
+ if (quiet < 2)
+ fprintf(stderr, "\nAppending jffs2 data from %s to %s...", jffs2file, mtd);
+ /* got an EOF marker - this is the place to add some jffs2 data */
+ skip = mtd_replace_jffs2(mtd, fd, e, jffs2file);
+ jffs2_replaced = 1;
+
+ /* don't add it again */
+ jffs2file = NULL;
+
+ w += skip;
+ e += skip;
+ skip -= buflen;
+ buflen = 0;
+ offset = 0;
+ continue;
+ }
+ /* no EOF marker, make sure we figure out the last inode number
+ * before appending some data */
+ mtd_parse_jffs2data(buf, jffs2dir);
+ }
+
+ /* need to erase the next block before writing data to it */
+ if(!no_erase)
+ {
+ while (w + buflen > e) {
+ if (!quiet)
+ fprintf(stderr, "\b\b\b[e]");
+
+
+ if (mtd_erase_block(fd, e) < 0) {
+ if (next) {
+ if (w < e) {
+ write(fd, buf + offset, e - w);
+ offset = e - w;
+ }
+ w = 0;
+ e = 0;
+ close(fd);
+ mtd = next;
+ fprintf(stderr, "\b\b\b \n");
+ goto resume;
+ } else {
+ fprintf(stderr, "Failed to erase block\n");
+ exit(1);
+ }
+ }
+
+ /* erase the chunk */
+ e += erasesize;
+ }
+ }
+
+ if (!quiet)
+ fprintf(stderr, "\b\b\b[w]");
+
+ if ((result = write(fd, buf + offset, buflen)) < buflen) {
+ if (result < 0) {
+ fprintf(stderr, "Error writing image.\n");
+ exit(1);
+ } else {
+ fprintf(stderr, "Insufficient space.\n");
+ exit(1);
+ }
+ }
+ w += buflen;
+
+ buflen = 0;
+ offset = 0;
+ }
+
+ if (jffs2_replaced && trx_fixup) {
+ trx_fixup(fd, mtd);
+ }
+
+ if (!quiet)
+ fprintf(stderr, "\b\b\b\b ");
+
+done:
+ if (quiet < 2)
+ fprintf(stderr, "\n");
+
+#ifdef FIS_SUPPORT
+ if (fis_layout) {
+ if (fis_remap(old_parts, n_old, new_parts, n_new) < 0)
+ fprintf(stderr, "Failed to update the FIS partition table\n");
+ }
+#endif
+
+ close(fd);
+ return 0;
+}
+
+static void usage(void)
+{
+ fprintf(stderr, "Usage: mtd [<options> ...] <command> [<arguments> ...] <device>[:<device>...]\n\n"
+ "The device is in the format of mtdX (eg: mtd4) or its label.\n"
+ "mtd recognizes these commands:\n"
+ " unlock unlock the device\n"
+ " refresh refresh mtd partition\n"
+ " erase erase all data on device\n"
+ " write <imagefile>|- write <imagefile> (use - for stdin) to device\n"
+ " jffs2write <file> append <file> to the jffs2 partition on the device\n");
+ if (mtd_fixtrx) {
+ fprintf(stderr,
+ " fixtrx fix the checksum in a trx header on first boot\n");
+ }
+ fprintf(stderr,
+ "Following options are available:\n"
+ " -q quiet mode (once: no [w] on writing,\n"
+ " twice: no status messages)\n"
+ " -n write without first erasing the blocks\n"
+ " -r reboot after successful command\n"
+ " -f force write without trx checks\n"
+ " -e <device> erase <device> before executing the command\n"
+ " -d <name> directory for jffs2write, defaults to \"tmp\"\n"
+ " -j <name> integrate <file> into jffs2 data when writing an image\n"
+ " -p write beginning at partition offset\n");
+ if (mtd_fixtrx) {
+ fprintf(stderr,
+ " -o offset offset of the image header in the partition(for fixtrx)\n");
+ }
+ fprintf(stderr,
+#ifdef FIS_SUPPORT
+ " -F <part>[:<size>[:<entrypoint>]][,<part>...]\n"
+ " alter the fis partition table to create new partitions replacing\n"
+ " the partitions provided as argument to the write command\n"
+ " (only valid together with the write command)\n"
+#endif
+ "\n"
+ "Example: To write linux.trx to mtd4 labeled as linux and reboot afterwards\n"
+ " mtd -r write linux.trx linux\n\n");
+ exit(1);
+}
+
+static void do_reboot(void)
+{
+ fprintf(stderr, "Rebooting ...\n");
+ fflush(stderr);
+
+ /* try regular reboot method first */
+ system("/sbin/reboot");
+ sleep(2);
+
+ /* if we're still alive at this point, force the kernel to reboot */
+ syscall(SYS_reboot,LINUX_REBOOT_MAGIC1,LINUX_REBOOT_MAGIC2,LINUX_REBOOT_CMD_RESTART,NULL);
+}
+
+int main (int argc, char **argv)
+{
+ int ch, i, boot, imagefd = 0, force, unlocked;
+ char *erase[MAX_ARGS], *device = NULL;
+ char *fis_layout = NULL;
+ size_t offset = 0, part_offset = 0;
+ enum {
+ CMD_ERASE,
+ CMD_WRITE,
+ CMD_UNLOCK,
+ CMD_REFRESH,
+ CMD_JFFS2WRITE,
+ CMD_FIXTRX,
+ } cmd = -1;
+
+ erase[0] = NULL;
+ boot = 0;
+ force = 0;
+ buflen = 0;
+ quiet = 0;
+ no_erase = 0;
+
+ while ((ch = getopt(argc, argv,
+#ifdef FIS_SUPPORT
+ "F:"
+#endif
+ "frnqe:d:j:p:o:")) != -1)
+ switch (ch) {
+ case 'f':
+ force = 1;
+ break;
+ case 'r':
+ boot = 1;
+ break;
+ case 'n':
+ no_erase = 1;
+ break;
+ case 'j':
+ jffs2file = optarg;
+ break;
+ case 'q':
+ quiet++;
+ break;
+ case 'e':
+ i = 0;
+ while ((erase[i] != NULL) && ((i + 1) < MAX_ARGS))
+ i++;
+
+ erase[i++] = optarg;
+ erase[i] = NULL;
+ break;
+ case 'd':
+ jffs2dir = optarg;
+ break;
+ case 'p':
+ errno = 0;
+ part_offset = strtoul(optarg, 0, 0);
+ if (errno) {
+ fprintf(stderr, "-p: illegal numeric string\n");
+ usage();
+ }
+ break;
+ case 'o':
+ if (!mtd_fixtrx) {
+ fprintf(stderr, "-o: is not available on this platform\n");
+ usage();
+ }
+ errno = 0;
+ offset = strtoul(optarg, 0, 0);
+ if (errno) {
+ fprintf(stderr, "-o: illegal numeric string\n");
+ usage();
+ }
+ break;
+#ifdef FIS_SUPPORT
+ case 'F':
+ fis_layout = optarg;
+ break;
+#endif
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 2)
+ usage();
+
+ if ((strcmp(argv[0], "unlock") == 0) && (argc == 2)) {
+ cmd = CMD_UNLOCK;
+ device = argv[1];
+ } else if ((strcmp(argv[0], "refresh") == 0) && (argc == 2)) {
+ cmd = CMD_REFRESH;
+ device = argv[1];
+ } else if ((strcmp(argv[0], "erase") == 0) && (argc == 2)) {
+ cmd = CMD_ERASE;
+ device = argv[1];
+ } else if (((strcmp(argv[0], "fixtrx") == 0) && (argc == 2)) && mtd_fixtrx) {
+ cmd = CMD_FIXTRX;
+ device = argv[1];
+ } else if ((strcmp(argv[0], "write") == 0) && (argc == 3)) {
+ cmd = CMD_WRITE;
+ device = argv[2];
+
+ if (strcmp(argv[1], "-") == 0) {
+ imagefile = "<stdin>";
+ imagefd = 0;
+ } else {
+ imagefile = argv[1];
+ if ((imagefd = open(argv[1], O_RDONLY)) < 0) {
+ fprintf(stderr, "Couldn't open image file: %s!\n", imagefile);
+ exit(1);
+ }
+ }
+
+ if (!mtd_check(device)) {
+ fprintf(stderr, "Can't open device for writing!\n");
+ exit(1);
+ }
+ /* check trx file before erasing or writing anything */
+ if (!image_check(imagefd, device) && !force) {
+ fprintf(stderr, "Image check failed.\n");
+ exit(1);
+ }
+ } else if ((strcmp(argv[0], "jffs2write") == 0) && (argc == 3)) {
+ cmd = CMD_JFFS2WRITE;
+ device = argv[2];
+
+ imagefile = argv[1];
+ if (!mtd_check(device)) {
+ fprintf(stderr, "Can't open device for writing!\n");
+ exit(1);
+ }
+ } else {
+ usage();
+ }
+
+ sync();
+
+ i = 0;
+ unlocked = 0;
+ while (erase[i] != NULL) {
+ mtd_unlock(erase[i]);
+ mtd_erase(erase[i]);
+ if (strcmp(erase[i], device) == 0)
+ unlocked = 1;
+ i++;
+ }
+
+ switch (cmd) {
+ case CMD_UNLOCK:
+ if (!unlocked)
+ mtd_unlock(device);
+ break;
+ case CMD_ERASE:
+ if (!unlocked)
+ mtd_unlock(device);
+ mtd_erase(device);
+ break;
+ case CMD_WRITE:
+ if (!unlocked)
+ mtd_unlock(device);
+ mtd_write(imagefd, device, fis_layout, part_offset);
+ break;
+ case CMD_JFFS2WRITE:
+ if (!unlocked)
+ mtd_unlock(device);
+ mtd_write_jffs2(device, imagefile, jffs2dir);
+ break;
+ case CMD_REFRESH:
+ mtd_refresh(device);
+ break;
+ case CMD_FIXTRX:
+ if (mtd_fixtrx) {
+ mtd_fixtrx(device, offset);
+ }
+ break;
+ }
+
+ sync();
+
+ if (boot)
+ do_reboot();
+
+ return 0;
+}
diff --git a/package/mtd/src/mtd.h b/package/mtd/src/mtd.h
new file mode 100644
index 000000000..f82552a15
--- /dev/null
+++ b/package/mtd/src/mtd.h
@@ -0,0 +1,28 @@
+#ifndef __mtd_h
+#define __mtd_h
+
+#include <stdbool.h>
+
+#ifdef target_brcm47xx
+#define target_brcm 1
+#endif
+
+#define JFFS2_EOF "\xde\xad\xc0\xde"
+
+extern int quiet;
+extern int mtdsize;
+extern int erasesize;
+
+extern int mtd_open(const char *mtd, bool block);
+extern int mtd_check_open(const char *mtd);
+extern int mtd_erase_block(int fd, int offset);
+extern int mtd_write_buffer(int fd, const char *buf, int offset, int length);
+extern int mtd_write_jffs2(const char *mtd, const char *filename, const char *dir);
+extern int mtd_replace_jffs2(const char *mtd, int fd, int ofs, const char *filename);
+extern void mtd_parse_jffs2data(const char *buf, const char *dir);
+
+/* target specific functions */
+extern int trx_fixup(int fd, const char *name) __attribute__ ((weak));
+extern int trx_check(int imagefd, const char *mtd, char *buf, int *len) __attribute__ ((weak));
+extern int mtd_fixtrx(const char *mtd, size_t offset) __attribute__ ((weak));
+#endif /* __mtd_h */
diff --git a/package/mtd/src/trx.c b/package/mtd/src/trx.c
new file mode 100644
index 000000000..65c24404c
--- /dev/null
+++ b/package/mtd/src/trx.c
@@ -0,0 +1,220 @@
+/*
+ * trx.c
+ *
+ * Copyright (C) 2005 Mike Baker
+ * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/ioctl.h>
+#include <mtd/mtd-user.h>
+#include "mtd.h"
+#include "crc32.h"
+
+#define TRX_MAGIC 0x30524448 /* "HDR0" */
+struct trx_header {
+ uint32_t magic; /* "HDR0" */
+ uint32_t len; /* Length of file including header */
+ uint32_t crc32; /* 32-bit CRC from flag_version to end of file */
+ uint32_t flag_version; /* 0:15 flags, 16:31 version */
+ uint32_t offsets[3]; /* Offsets of partitions from start of header */
+};
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define STORE32_LE(X) ((((X) & 0x000000FF) << 24) | (((X) & 0x0000FF00) << 8) | (((X) & 0x00FF0000) >> 8) | (((X) & 0xFF000000) >> 24))
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define STORE32_LE(X) (X)
+#else
+#error unknown endianness!
+#endif
+
+ssize_t pread(int fd, void *buf, size_t count, off_t offset);
+ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
+
+int
+trx_fixup(int fd, const char *name)
+{
+ struct mtd_info_user mtdInfo;
+ unsigned long len;
+ struct trx_header *trx;
+ void *ptr, *scan;
+ int bfd;
+
+ if (ioctl(fd, MEMGETINFO, &mtdInfo) < 0) {
+ fprintf(stderr, "Failed to get mtd info\n");
+ goto err;
+ }
+
+ len = mtdInfo.size;
+ if (mtdInfo.size <= 0) {
+ fprintf(stderr, "Invalid MTD device size\n");
+ goto err;
+ }
+
+ bfd = mtd_open(name, true);
+ ptr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, bfd, 0);
+ if (!ptr || (ptr == (void *) -1)) {
+ perror("mmap");
+ goto err1;
+ }
+
+ trx = ptr;
+ if (trx->magic != TRX_MAGIC) {
+ fprintf(stderr, "TRX header not found\n");
+ goto err;
+ }
+
+ scan = ptr + offsetof(struct trx_header, flag_version);
+ trx->crc32 = crc32buf(scan, trx->len - (scan - ptr));
+ msync(ptr, sizeof(struct trx_header), MS_SYNC|MS_INVALIDATE);
+ munmap(ptr, len);
+ close(bfd);
+ return 0;
+
+err1:
+ close(bfd);
+err:
+ fprintf(stderr, "Error fixing up TRX header\n");
+ return -1;
+}
+
+int
+trx_check(int imagefd, const char *mtd, char *buf, int *len)
+{
+ const struct trx_header *trx = (const struct trx_header *) buf;
+ int fd;
+
+ if (strcmp(mtd, "linux") != 0)
+ return 1;
+
+ *len = read(imagefd, buf, 32);
+ if (*len < 32) {
+ fprintf(stdout, "Could not get image header, file too small (%d bytes)\n", *len);
+ return 0;
+ }
+
+ if (trx->magic != TRX_MAGIC || trx->len < sizeof(struct trx_header)) {
+ if (quiet < 2) {
+ fprintf(stderr, "Bad trx header\n");
+ fprintf(stderr, "This is not the correct file format; refusing to flash.\n"
+ "Please specify the correct file or use -f to force.\n");
+ }
+ return 0;
+ }
+
+ /* check if image fits to mtd device */
+ fd = mtd_check_open(mtd);
+ if(fd < 0) {
+ fprintf(stderr, "Could not open mtd device: %s\n", mtd);
+ exit(1);
+ }
+
+ if(mtdsize < trx->len) {
+ fprintf(stderr, "Image too big for partition: %s\n", mtd);
+ close(fd);
+ return 0;
+ }
+
+ close(fd);
+ return 1;
+}
+
+int
+mtd_fixtrx(const char *mtd, size_t offset)
+{
+ int fd;
+ struct trx_header *trx;
+ char *buf;
+ ssize_t res;
+ size_t block_offset;
+
+ if (quiet < 2)
+ fprintf(stderr, "Trying to fix trx header in %s at 0x%x...\n", mtd, offset);
+
+ fd = mtd_check_open(mtd);
+ if(fd < 0) {
+ fprintf(stderr, "Could not open mtd device: %s\n", mtd);
+ exit(1);
+ }
+
+ block_offset = offset & ~(erasesize - 1);
+ offset -= block_offset;
+
+ if (block_offset + erasesize > mtdsize) {
+ fprintf(stderr, "Offset too large, device size 0x%x\n", mtdsize);
+ exit(1);
+ }
+
+ buf = malloc(erasesize);
+ if (!buf) {
+ perror("malloc");
+ exit(1);
+ }
+
+ res = pread(fd, buf, erasesize, block_offset);
+ if (res != erasesize) {
+ perror("pread");
+ exit(1);
+ }
+
+ trx = (struct trx_header *) (buf + offset);
+ if (trx->magic != STORE32_LE(0x30524448)) {
+ fprintf(stderr, "No trx magic found\n");
+ exit(1);
+ }
+
+ if (trx->len == STORE32_LE(erasesize - offset)) {
+ if (quiet < 2)
+ fprintf(stderr, "Header already fixed, exiting\n");
+ close(fd);
+ return 0;
+ }
+
+ trx->len = STORE32_LE(erasesize - offset);
+
+ trx->crc32 = STORE32_LE(crc32buf((char*) &trx->flag_version, erasesize - offset - 3*4));
+ if (mtd_erase_block(fd, block_offset)) {
+ fprintf(stderr, "Can't erease block at 0x%x (%s)\n", block_offset, strerror(errno));
+ exit(1);
+ }
+
+ if (quiet < 2)
+ fprintf(stderr, "New crc32: 0x%x, rewriting block\n", trx->crc32);
+
+ if (pwrite(fd, buf, erasesize, block_offset) != erasesize) {
+ fprintf(stderr, "Error writing block (%s)\n", strerror(errno));
+ exit(1);
+ }
+
+ if (quiet < 2)
+ fprintf(stderr, "Done.\n");
+
+ close (fd);
+ sync();
+ return 0;
+
+}
+
diff --git a/package/ncurses/Makefile b/package/ncurses/Makefile
new file mode 100644
index 000000000..9c682aca8
--- /dev/null
+++ b/package/ncurses/Makefile
@@ -0,0 +1,151 @@
+#
+# Copyright (C) 2006-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ncurses
+PKG_VERSION:=5.7
+PKG_RELEASE:=5
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@GNU/ncurses
+PKG_MD5SUM:=cce05daf61a64501ef6cd8da1f727ec6
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/libncurses
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=Terminal handling library
+ URL:=http://www.gnu.org/software/ncurses/
+ DEPENDS:= +terminfo
+ VARIANT:=libncurses
+endef
+
+define Package/terminfo
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=Terminal Info Database (ncurses)
+ URL:=http://www.gnu.org/software/ncurses/
+ VARIANT:=libncurses
+endef
+
+define Package/libncursesw
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=Terminal handling library (Unicode)
+ URL:=http://www.gnu.org/software/ncurses/
+ VARIANT:=libncursesw
+endef
+
+TARGET_CFLAGS += $(FPIC)
+
+CONFIGURE_ARGS += \
+ --enable-echo \
+ --enable-const \
+ --enable-overwrite \
+ --disable-rpath \
+ --without-ada \
+ --without-debug \
+ --without-profile \
+ --without-progs \
+ --disable-big-core \
+ --disable-home-terminfo \
+ --with-normal \
+ --with-shared \
+ --with-terminfo-dirs=/usr/share/terminfo \
+ --with-default-terminfo-dir=/usr/share/terminfo
+
+ifeq ($(HOST_OS),FreeBSD)
+ CONFIGURE_ARGS +=
+ --with-terminfo=/usr/share/terminfo.db
+endif
+
+ifeq ($(BUILD_VARIANT),libncursesw)
+ CONFIGURE_ARGS += \
+ --enable-widec \
+ --with-build-cppflags=-D_GNU_SOURCE
+endif
+
+MAKE_FLAGS += \
+ BUILD_CC="$(HOSTCC)" \
+ HOSTCC="$(HOSTCC)" \
+ HOSTCCFLAGS="" \
+ libs
+
+define Build/Install/Default
+ $(MAKE_VARS) \
+ $(MAKE) -C $(PKG_BUILD_DIR)/$(MAKE_PATH) \
+ $(MAKE_INSTALL_FLAGS) \
+ $(1) install.libs install.data;
+endef
+
+define Package/terminfo/install
+ echo ""
+ifneq ($(HOST_OS),FreeBSD)
+ $(INSTALL_DIR) $(1)/usr/share/terminfo
+ (cd $(PKG_INSTALL_DIR)/usr/share/terminfo; \
+ for dir in ??; do \
+ [ -d "$$$$dir" ] || continue; \
+ mv $$$$dir $$$$(echo -ne "\x$$$$dir"); \
+ done \
+ )
+ for file in a/ansi d/dumb l/linux r/rxvt r/rxvt-unicode s/screen v/vt100 v/vt102 x/xterm x/xterm-color; do \
+ $(INSTALL_DIR) $(1)/usr/share/terminfo/`dirname $$$$file`; \
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/terminfo/$$$$file \
+ $(1)/usr/share/terminfo/$$$$file; \
+ done
+endif
+endef
+
+define Package/libncurses/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/lib{curses,ncurses,panel,menu,form}.so* $(1)/usr/lib/
+endef
+
+define Package/libncursesw/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/lib{ncurses,panel,menu,form}w.so* $(1)/usr/lib/
+endef
+
+ifeq ($(BUILD_VARIANT),libncursesw)
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include/ncursesw/
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/*.h $(1)/usr/include/ncursesw/
+
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/lib{ncurses,panel,menu,form}w.{a,so*} $(1)/usr/lib/
+
+ $(INSTALL_DIR) $(1)/usr/bin $(2)/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/ncursesw5-config $(2)/bin/
+ $(SED) 's,^\(prefix\|exec_prefix\)=.*,\1=$(STAGING_DIR)/usr,g' -e 's/$$$$INCS //g' \
+ $(2)/bin/ncursesw5-config
+ ln -sf $(STAGING_DIR)/host/bin/ncursesw5-config $(1)/usr/bin/ncursesw5-config
+endef
+else
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/*.h $(1)/usr/include/
+
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/lib{curses,ncurses,panel,menu,form}.{a,so*} $(1)/usr/lib/
+
+ $(INSTALL_DIR) $(1)/usr/bin $(2)/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/ncurses5-config $(2)/bin/
+ $(SED) 's,^\(prefix\|exec_prefix\)=.*,\1=$(STAGING_DIR)/usr,g' \
+ $(2)/bin/ncurses5-config
+ ln -sf $(STAGING_DIR)/host/bin/ncurses5-config $(1)/usr/bin/ncurses5-config
+endef
+endif
+
+$(eval $(call BuildPackage,terminfo))
+$(eval $(call BuildPackage,libncurses))
+$(eval $(call BuildPackage,libncursesw))
diff --git a/package/ncurses/patches/100-ncurses-5.6-20080112-urxvt.patch b/package/ncurses/patches/100-ncurses-5.6-20080112-urxvt.patch
new file mode 100644
index 000000000..39e60ba98
--- /dev/null
+++ b/package/ncurses/patches/100-ncurses-5.6-20080112-urxvt.patch
@@ -0,0 +1,175 @@
+--- a/misc/terminfo.src
++++ b/misc/terminfo.src
+@@ -3965,6 +3965,172 @@ rxvt-cygwin-native|rxvt terminal emulato
+ rxvt-16color|xterm with 16 colors like aixterm,
+ ncv#32, use=ibm+16color, use=rxvt,
+
++# rxvt-unicode
++# http://cvs.schmorp.de/rxvt-unicode/doc/etc/rxvt-unicode.terminfo?revision=1.20
++# From: Thomas Dickey <dickey@clark.net> 04 Oct 1997
++# Updated: Özgür Kesim <kesim@math.fu-berlin.de> 02 Nov 1997
++# Updated: Marc Lehmann <pcg@goof.com>, 17 Feb 2005
++rxvt-unicode|rxvt-unicode terminal (X Window System),
++ am,
++ bce,
++ eo,
++ km,
++ msgr,
++ xenl,
++ hs,
++ cols#80,
++ it#8,
++ lines#24,
++ acsc=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~-A.B+C\,D0EhFiG,
++ bel=^G,
++ blink=\E[5m,
++ bold=\E[1m,
++ civis=\E[?25l,
++ clear=\E[H\E[2J,
++ cnorm=\E[?25h,
++ cr=^M,
++ csr=\E[%i%p1%d;%p2%dr,
++ cub=\E[%p1%dD,
++ cub1=^H,
++ cud=\E[%p1%dB,
++ cud1=^J,
++ cuf=\E[%p1%dC,
++ cuf1=\E[C,
++ cup=\E[%i%p1%d;%p2%dH,
++ cuu=\E[%p1%dA,
++ cuu1=\E[A,
++ cvvis=\E[?25h,
++ dch=\E[%p1%dP,
++ dch1=\E[P,
++ dl=\E[%p1%dM,
++ dl1=\E[M,
++ ed=\E[J,
++ el=\E[K,
++ el1=\E[1K,
++ flash=\E[?5h$<20/>\E[?5l,
++ home=\E[H,
++ hpa=\E[%i%p1%dG,
++ ht=^I,
++ hts=\EH,
++ ich=\E[%p1%d@,
++ ich1=\E[@,
++ il=\E[%p1%dL,
++ il1=\E[L,
++ ind=^J,
++ is1=\E[?47l\E=\E[?1l,
++ is2=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l\E[4l,
++ kDC=\E[3$,
++ kIC=\E2$,
++ kEND=\E[8$,
++ kHOM=\E[7$,
++ kLFT=\E[d,
++ kNXT=\E[6$,
++ kPRV=\E[5$,
++ kRIT=\E[c,
++ kbs=\177,
++ ka1=\EOw,
++ ka3=\EOy,
++ kb2=\EOu,
++ kc1=\EOq,
++ kc3=\EOs,
++ kcbt=\E[Z,
++ kcub1=\E[D,
++ kcud1=\E[B,
++ kcuf1=\E[C,
++ kcuu1=\E[A,
++ kdch1=\E[3~,
++ kel=\E[8\^,
++ kend=\E[8~,
++ kent=\EOM,
++ kf1=\E[11~,
++ kf10=\E[21~,
++ kf11=\E[23~,
++ kf12=\E[24~,
++ kf13=\E[25~,
++ kf14=\E[26~,
++ kf15=\E[28~,
++ kf16=\E[29~,
++ kf17=\E[31~,
++ kf18=\E[32~,
++ kf19=\E[33~,
++ kf2=\E[12~,
++ kf20=\E[34~,
++ kf3=\E[13~,
++ kf4=\E[14~,
++ kf5=\E[15~,
++ kf6=\E[17~,
++ kf7=\E[18~,
++ kf8=\E[19~,
++ kf9=\E[20~,
++ kfnd=\E[1~,
++ khome=\E[7~,
++ kich1=\E[2~,
++ kmous=\E[M,
++ knp=\E[6~,
++ kpp=\E[5~,
++ kslt=\E[4~,
++ rc=\E8,
++ rev=\E[7m,
++ ri=\EM,
++ rmso=\E[27m,
++ rmul=\E[24m,
++ rs1=\Ec,
++ rs2=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l\E[4l\E>,
++ sgr0=\E[m\017,
++ enacs=,
++ smacs=\E(0,
++ rmacs=\E(B,
++ smso=\E[7m,
++ smul=\E[4m,
++ tbc=\E[3g,
++ vpa=\E[%i%p1%dd,
++ colors#88,
++ pairs#256,
++ btns#5,
++ lm#0,
++ ccc,
++ npc,
++ mc5i,
++ ncv#0,
++ mir,
++ xon,
++ bw,
++ ech=\E[%p1%dX,
++ mc0=\E[i,
++ mc4=\E[4i,
++ mc5=\E[5i,
++ sitm=\E[3m,
++ ritm=\E[23m,
++ smam=\E[?7h,
++ rmam=\E[?7l,
++ smir=\E[4h,
++ rmir=\E[4l,
++ smcup=\E[?1049h,
++ rmcup=\E[r\E[?1049l,
++ smkx=\E=,
++ rmkx=\E>,
++ indn=\E[%p1%dS,
++ rin=\E[%p1%dT,
++ sgr=\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m%?%p9%t\E(0%e\E(B%;,
++ op=\E[39;49m,
++ setaf=\E[38;5;%p1%dm,
++ setab=\E[48;5;%p1%dm,
++ setf=%?%p1%{7}%>%t\E[38;5;%p1%dm%e\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m%;,
++ setb=%?%p1%{7}%>%t\E[48;5;%p1%dm%e\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m%;,
++ initc=\E]4;%p1%d;rgb\:%p2%{65535}%*%{1000}%/%4.4X/%p3%{65535}%*%{1000}%/%4.4X/%p4%{65535}%*%{1000}%/%4.4X\E\\,
++ sc=\E7,
++ s0ds=\E(B,
++ s1ds=\E(0,
++ s2ds=\E*B,
++ s3ds=\E+B,
++ u6=\E[%i%d;%dR,
++ u7=\E[6n,
++ u8=\E[?1;2c,
++ u9=\E[c,
++ tsl=\E]2;,
++ fsl=\007,
++ dsl=\E]2;\007,
++
+ # mrxvt 0.5.3
+ #
+ # mrxvt is based on rxvt 2.7.11, but has by default XTERM_FKEYS defined, which
diff --git a/package/ncurses/patches/101-ncurses-5.6-20080628-kbs.patch b/package/ncurses/patches/101-ncurses-5.6-20080628-kbs.patch
new file mode 100644
index 000000000..3b3abd7b0
--- /dev/null
+++ b/package/ncurses/patches/101-ncurses-5.6-20080628-kbs.patch
@@ -0,0 +1,52 @@
+--- a/misc/terminfo.src
++++ b/misc/terminfo.src
+@@ -3054,6 +3054,7 @@ xterm-xfree86|xterm terminal emulator (X
+ # This version reflects the current xterm features.
+ xterm-new|modern xterm terminal emulator,
+ npc,
++ kbs=\177,
+ indn=\E[%p1%dS, kDC=\E[3;2~, kEND=\E[1;2F, kHOM=\E[1;2H,
+ kIC=\E[2;2~, kNXT=\E[6;2~, kPRV=\E[5;2~, kb2=\EOE,
+ kcbt=\E[Z, kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA,
+@@ -3818,6 +3819,7 @@ mlterm+pcfkeys|fragment for PC-style fke
+ rxvt-basic|rxvt terminal base (X Window System),
+ OTbs, am, bce, eo, mir, msgr, xenl, xon,
+ cols#80, it#8, lines#24,
++ kbs=\177,
+ acsc=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
+ bel=^G, blink=\E[5m, bold=\E[1m, civis=\E[?25l,
+ clear=\E[H\E[2J, cnorm=\E[?25h, cr=^M,
+@@ -3828,7 +3830,7 @@ rxvt-basic|rxvt terminal base (X Window
+ enacs=\E(B\E)0, flash=\E[?5h\E[?5l, home=\E[H, ht=^I,
+ hts=\EH, ich=\E[%p1%d@, ich1=\E[@, il=\E[%p1%dL, il1=\E[L,
+ ind=^J, is1=\E[?47l\E=\E[?1l,
+- is2=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l\E[4l, kbs=^H,
++ is2=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l\E[4l,
+ kcbt=\E[Z, kmous=\E[M, rc=\E8, rev=\E[7m, ri=\EM, rmacs=^O,
+ rmcup=\E[2J\E[?47l\E8, rmir=\E[4l, rmkx=\E>, rmso=\E[27m,
+ rmul=\E[24m,
+@@ -4541,6 +4543,7 @@ eterm|gnu emacs term.el terminal emulati
+ screen|VT 100/ANSI X3.64 virtual terminal,
+ OTbs, OTpt, am, km, mir, msgr, xenl, G0,
+ colors#8, cols#80, it#8, lines#24, pairs#64,
++ kbs=\177,
+ acsc=++\,\,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
+ bel=^G, blink=\E[5m, bold=\E[1m, cbt=\E[Z, civis=\E[?25l,
+ clear=\E[H\E[J, cnorm=\E[34h\E[?25h, cr=^M,
+@@ -4550,7 +4553,7 @@ screen|VT 100/ANSI X3.64 virtual termina
+ cvvis=\E[34l, dch=\E[%p1%dP, dch1=\E[P, dl=\E[%p1%dM,
+ dl1=\E[M, ed=\E[J, el=\E[K, el1=\E[1K, enacs=\E(B\E)0,
+ flash=\Eg, home=\E[H, ht=^I, hts=\EH, ich=\E[%p1%d@,
+- il=\E[%p1%dL, il1=\E[L, ind=^J, is2=\E)0, kbs=^H, kcbt=\E[Z,
++ il=\E[%p1%dL, il1=\E[L, ind=^J, is2=\E)0, kcbt=\E[Z,
+ kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA,
+ kdch1=\E[3~, kend=\E[4~, kf1=\EOP, kf10=\E[21~,
+ kf11=\E[23~, kf12=\E[24~, kf2=\EOQ, kf3=\EOR, kf4=\EOS,
+@@ -4655,6 +4658,7 @@ screen.xterm-r6|screen customized for X1
+ # on Solaris because Sun's curses implementation gets confused.
+ screen.teraterm|disable ncv in teraterm,
+ ncv#127,
++ kbs=^H,
+ acsc=+\020\,\021-\030.^Y0\333`\004a\261f\370g\361h\260i\316j\331k\277l\332m\300n\305o~p\304q\304r\304s_t\303u\264v\301w\302x\263y\363z\362{\343|\330}\234~\376,
+ use=screen+fkeys, use=screen,
+ # Other terminals
diff --git a/package/ncurses/patches/500-cross.patch b/package/ncurses/patches/500-cross.patch
new file mode 100644
index 000000000..ace6252fe
--- /dev/null
+++ b/package/ncurses/patches/500-cross.patch
@@ -0,0 +1,11 @@
+--- a/aclocal.m4
++++ b/aclocal.m4
+@@ -4298,7 +4298,7 @@ CF_EOF
+ EXTRA_LDFLAGS="-Wl,-rpath,\${libdir} $EXTRA_LDFLAGS"
+ fi
+ CF_SHARED_SONAME
+- MK_SHARED_LIB='${CC} ${CFLAGS} -shared -Wl,-soname,'$cf_cv_shared_soname',-stats,-lc -o $[@]'
++ MK_SHARED_LIB='${CC} ${CFLAGS} -shared -Wl,-soname,'$cf_shared_soname',-stats,$(LDFLAGS) -lc -o $[@]'
+ ;;
+ openbsd[[2-9]].*)
+ if test "$DFT_LWR_MODEL" = "shared" ; then
diff --git a/package/ncurses/patches/900-terminfo.patch b/package/ncurses/patches/900-terminfo.patch
new file mode 100644
index 000000000..7aab3dbca
--- /dev/null
+++ b/package/ncurses/patches/900-terminfo.patch
@@ -0,0 +1,20 @@
+--- a/misc/terminfo.src
++++ b/misc/terminfo.src
+@@ -3707,12 +3707,11 @@ konsole-xf3x|KDE console window with key
+ # The value for kbs reflects local customization rather than the settings used
+ # for XFree86 xterm.
+ konsole-xf4x|KDE console window with keyboard for XFree86 4.x xterm,
+- kend=\EOF, khome=\EOH, use=konsole+pcfkeys,
+- use=konsole-vt100,
+-# Konsole does not implement shifted cursor-keys.
+-konsole+pcfkeys|konsole subset of xterm+pcfkeys,
+- kLFT@, kRIT@, kcbt=\E[Z, kind@, kri@, kDN@, kUP@, use=xterm+pcc2,
+- use=xterm+pcf0,
++ kend=\EOF, kf1=\EOP, kf13=\EO2P, kf14=\EO2Q, kf15=\EO2R,
++ kf16=\EO2S, kf17=\E[15;2~, kf18=\E[17;2~, kf19=\E[18;2~,
++ kf2=\EOQ, kf20=\E[19;2~, kf21=\E[20;2~, kf22=\E[21;2~,
++ kf23=\E[23;2~, kf24=\E[24;2~, kf3=\EOR, kf4=\EOS,
++ khome=\EOH, use=konsole-vt100,
+ # KDE's "vt100" keyboard has no relationship to any terminal that DEC made, but
+ # it is still useful for deriving the other entries.
+ konsole-vt100|KDE console window with vt100 (sic) keyboard,
diff --git a/package/netifd/Makefile b/package/netifd/Makefile
new file mode 100644
index 000000000..266cd9e3c
--- /dev/null
+++ b/package/netifd/Makefile
@@ -0,0 +1,40 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=netifd
+PKG_VERSION:=2012-09-29
+PKG_RELEASE=$(PKG_SOURCE_VERSION)
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=git://nbd.name/luci2/netifd.git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=6653b861748719ab58e21a81e01d59d4d8afe10c
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
+# PKG_MIRROR_MD5SUM:=
+# CMAKE_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/netifd
+ SECTION:=base
+ CATEGORY:=Base system
+ DEPENDS:=+libuci +libnl-tiny +libubus +ubus +ubusd +jshn
+ TITLE:=OpenWrt Network Interface Configuration Daemon
+endef
+
+TARGET_CFLAGS += \
+ -I$(STAGING_DIR)/usr/include/libnl-tiny \
+ -I$(STAGING_DIR)/usr/include
+
+CMAKE_OPTIONS += \
+ -DLIBNL_LIBS=-lnl-tiny \
+ -DDEBUG=1
+
+define Package/netifd/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/netifd $(1)/sbin/
+ $(CP) ./files/* $(1)/
+ $(CP) $(PKG_BUILD_DIR)/dummy/netifd-proto.sh $(1)/lib/netifd/
+endef
+
+$(eval $(call BuildPackage,netifd))
diff --git a/package/netifd/files/etc/hotplug.d/iface/00-netstate b/package/netifd/files/etc/hotplug.d/iface/00-netstate
new file mode 100644
index 000000000..c50cda6ea
--- /dev/null
+++ b/package/netifd/files/etc/hotplug.d/iface/00-netstate
@@ -0,0 +1,8 @@
+[ ifup = "$ACTION" ] && {
+ uci_toggle_state network "$INTERFACE" up 1
+ uci_toggle_state network "$INTERFACE" connect_time $(sed -ne 's![^0-9].*$!!p' /proc/uptime)
+ [ -n "$DEVICE" ] && {
+ uci_toggle_state network "$INTERFACE" device "$(uci -q get network.$INTERFACE.ifname)"
+ uci_toggle_state network "$INTERFACE" ifname "$DEVICE"
+ }
+}
diff --git a/package/netifd/files/etc/hotplug.d/iface/10-sysctl b/package/netifd/files/etc/hotplug.d/iface/10-sysctl
new file mode 100644
index 000000000..33ac5c329
--- /dev/null
+++ b/package/netifd/files/etc/hotplug.d/iface/10-sysctl
@@ -0,0 +1,36 @@
+# Skip fake devices (e.g. relayd)
+grep -qs "^ *$DEVICE:" /proc/net/dev || exit 0
+
+case "$ACTION" in
+ ifup)
+ include /lib/network
+ scan_interfaces
+
+ # Setup sysctls
+ local proto accept_ra send_rs
+
+ config_get proto "$INTERFACE" proto
+ if [ "$proto" = dhcp ]; then
+ accept_ra=1
+ send_rs=0
+ else
+ accept_ra=0
+ send_rs=1
+ fi
+
+ config_get_bool accept_ra "$INTERFACE" accept_ra $accept_ra
+ [ $accept_ra -eq 0 ] || {
+ logger -t ifup "Allowing Router Advertisements on $INTERFACE ($DEVICE)"
+ accept_ra=2
+ }
+ do_sysctl "net.ipv6.conf.$DEVICE.accept_ra" $accept_ra
+
+ config_get_bool send_rs "$INTERFACE" send_rs $send_rs
+ [ $send_rs -eq 0 ] || {
+ logger -t ifup "Enabling Router Solicitations on $INTERFACE ($DEVICE)"
+ send_rs=2
+ }
+ do_sysctl "net.ipv6.conf.$DEVICE.forwarding" $send_rs
+ ;;
+esac
+
diff --git a/package/netifd/files/etc/init.d/network b/package/netifd/files/etc/init.d/network
new file mode 100755
index 000000000..28b1ba3dd
--- /dev/null
+++ b/package/netifd/files/etc/init.d/network
@@ -0,0 +1,47 @@
+#!/bin/sh /etc/rc.common
+
+START=20
+STOP=90
+
+SERVICE_DAEMONIZE=1
+SERVICE_WRITE_PID=1
+
+start() {
+ stop
+ [ -e /proc/sys/kernel/core_pattern ] && {
+ ulimit -c unlimited
+ echo '/tmp/%e.%p.%s.%t.core' > /proc/sys/kernel/core_pattern
+ }
+ service_start /sbin/netifd
+
+ setup_switch() { return 0; }
+
+ include /lib/network
+ setup_switch
+
+ sleep 1
+
+ /sbin/wifi down
+ /sbin/wifi up
+}
+
+restart() {
+ ifdown -a
+ sleep 1
+ start
+}
+
+shutdown() {
+ ifdown -a
+ stop
+}
+
+stop() {
+ service_stop /sbin/netifd
+}
+
+reload() {
+ ubus call network reload
+ /sbin/wifi down
+ /sbin/wifi up
+}
diff --git a/package/netifd/files/lib/netifd/dhcp.script b/package/netifd/files/lib/netifd/dhcp.script
new file mode 100755
index 000000000..0097a96f8
--- /dev/null
+++ b/package/netifd/files/lib/netifd/dhcp.script
@@ -0,0 +1,59 @@
+#!/bin/sh
+[ -z "$1" ] && echo "Error: should be run by udhcpc" && exit 1
+
+. /lib/functions.sh
+. /lib/netifd/netifd-proto.sh
+
+set_classless_routes() {
+ local max=128
+ local type
+ while [ -n "$1" -a -n "$2" -a $max -gt 0 ]; do
+ proto_add_ipv4_route "${1%%/*}" "${1##*/}" "$2"
+ max=$(($max-1))
+ shift 2
+ done
+}
+
+setup_interface () {
+ proto_init_update "*" 1
+ proto_add_ipv4_address "$ip" "${subnet:-255.255.255.0}"
+ # TODO: apply $broadcast
+
+ for i in $router; do
+ proto_add_ipv4_route 0.0.0.0 0 "$i"
+ done
+
+ # CIDR STATIC ROUTES (rfc3442)
+ [ -n "$staticroutes" ] && set_classless_routes $staticroutes
+ [ -n "$msstaticroutes" ] && set_classless_routes $msstaticroutes
+
+ for dns in $dns; do
+ proto_add_dns_server "$dns"
+ done
+ for domain in $domain; do
+ proto_add_dns_search "$domain"
+ done
+ proto_send_update "$INTERFACE"
+
+ # TODO
+ # [ -n "$ntpsrv" ] && change_state network "$ifc" lease_ntpsrv "$ntpsrv"
+ # [ -n "$timesvr" ] && change_state network "$ifc" lease_timesrv "$timesvr"
+ # [ -n "$hostname" ] && change_state network "$ifc" lease_hostname "$hostname"
+ # [ -n "$timezone" ] && change_state network "$ifc" lease_timezone "$timezone"
+}
+
+deconfig_interface() {
+ proto_init_update "*" 0
+ proto_send_update "$INTERFACE"
+}
+
+case "$1" in
+ deconfig)
+ deconfig_interface
+ ;;
+ renew|bound)
+ setup_interface
+ ;;
+esac
+
+exit 0
diff --git a/package/netifd/files/lib/netifd/proto/dhcp.sh b/package/netifd/files/lib/netifd/proto/dhcp.sh
new file mode 100755
index 000000000..9182d58ad
--- /dev/null
+++ b/package/netifd/files/lib/netifd/proto/dhcp.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+. /lib/functions.sh
+. ../netifd-proto.sh
+init_proto "$@"
+
+proto_dhcp_init_config() {
+ proto_config_add_string "ipaddr"
+ proto_config_add_string "netmask"
+ proto_config_add_string "hostname"
+ proto_config_add_string "clientid"
+ proto_config_add_string "vendorid"
+ proto_config_add_boolean "broadcast"
+ proto_config_add_string "reqopts"
+}
+
+proto_dhcp_setup() {
+ local config="$1"
+ local iface="$2"
+
+ local ipaddr hostname clientid vendorid broadcast reqopts
+ json_get_vars ipaddr hostname clientid vendorid broadcast reqopts
+
+ local opt dhcpopts
+ for opt in $reqopts; do
+ append dhcpopts "-O $opt"
+ done
+
+ [ "$broadcast" = 1 ] && broadcast="-O broadcast" || broadcast=
+
+ proto_export "INTERFACE=$config"
+ proto_run_command "$config" udhcpc \
+ -p /var/run/udhcpc-$iface.pid \
+ -s /lib/netifd/dhcp.script \
+ -f -t 0 -i "$iface" \
+ ${ipaddr:+-r $ipaddr} \
+ ${hostname:+-H $hostname} \
+ ${clientid:+-x 0x3d:${clientid//:/}} \
+ ${vendorid:+-V $vendorid} \
+ $broadcast $dhcpopts
+}
+
+proto_dhcp_teardown() {
+ local interface="$1"
+ proto_kill_command "$interface"
+}
+
+add_protocol dhcp
+
diff --git a/package/netifd/files/lib/network/config.sh b/package/netifd/files/lib/network/config.sh
new file mode 100755
index 000000000..9128971da
--- /dev/null
+++ b/package/netifd/files/lib/network/config.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+# Copyright (C) 2011 OpenWrt.org
+
+. /usr/share/libubox/jshn.sh
+
+find_config() {
+ local device="$1"
+ local ifdev ifl3dev ifobj
+ for ifobj in `ubus list network.interface.\*`; do
+ interface="${ifobj##network.interface.}"
+ (
+ json_load "$(ifstatus $interface)"
+ json_get_var ifdev device
+ json_get_var ifl3dev l3_device
+ if [[ "$device" = "$ifdev" ]] || [[ "$device" = "$ifl3dev" ]]; then
+ echo "$interface"
+ exit 0
+ else
+ exit 1
+ fi
+ ) && return
+ done
+}
+
+unbridge() {
+ return
+}
+
+ubus_call() {
+ json_init
+ local _data="$(ubus -S call "$1" "$2")"
+ [ -z "$_data" ] && return 1
+ json_load "$_data"
+ return 0
+}
+
+
+fixup_interface() {
+ local config="$1"
+ local ifname type device l3dev
+
+ config_get type "$config" type
+ config_get ifname "$config" ifname
+ config_get device "$config" device "$ifname"
+ [ "bridge" = "$type" ] && ifname="br-$config"
+ config_set "$config" device "$ifname"
+ ubus_call "network.interface.$config" status || return 0
+ json_get_var l3dev l3_device
+ [ -n "$l3dev" ] && ifname="$l3dev"
+ json_init
+ config_set "$config" ifname "$ifname"
+ config_set "$config" device "$device"
+}
+
+scan_interfaces() {
+ config_load network
+ config_foreach fixup_interface interface
+}
+
+prepare_interface_bridge() {
+ local config="$1"
+
+ [ -n "$config" ] || return 0
+ ubus call network.interface."$config" prepare
+}
+
+setup_interface() {
+ local iface="$1"
+ local config="$2"
+
+ [ -n "$config" ] || return 0
+ ubus call network.interface."$config" add_device "{ \"name\": \"$iface\" }"
+}
+
+do_sysctl() {
+ [ -n "$2" ] && \
+ sysctl -n -e -w "$1=$2" >/dev/null || \
+ sysctl -n -e "$1"
+}
diff --git a/package/netifd/files/sbin/devstatus b/package/netifd/files/sbin/devstatus
new file mode 100755
index 000000000..3c35b26a4
--- /dev/null
+++ b/package/netifd/files/sbin/devstatus
@@ -0,0 +1,12 @@
+#!/bin/sh
+. /usr/share/libubox/jshn.sh
+DEVICE="$1"
+
+[ -n "$DEVICE" ] || {
+ echo "Usage: $0 <device>"
+ exit 1
+}
+
+json_init
+json_add_string name "$DEVICE"
+ubus call network.device status "$(json_dump)"
diff --git a/package/netifd/files/sbin/ifdown b/package/netifd/files/sbin/ifdown
new file mode 120000
index 000000000..a0e5c176a
--- /dev/null
+++ b/package/netifd/files/sbin/ifdown
@@ -0,0 +1 @@
+ifup \ No newline at end of file
diff --git a/package/netifd/files/sbin/ifstatus b/package/netifd/files/sbin/ifstatus
new file mode 100755
index 000000000..511cc1d8d
--- /dev/null
+++ b/package/netifd/files/sbin/ifstatus
@@ -0,0 +1,13 @@
+#!/bin/sh
+INTERFACE="$1"
+
+[ -n "$INTERFACE" ] || {
+ echo "Usage: $0 <interface>"
+ exit 1
+}
+
+ubus -S list "network.interface.$INTERFACE" >/dev/null || {
+ echo "Interface $INTERFACE not found"
+ exit 1
+}
+ubus call network.interface."$INTERFACE" status
diff --git a/package/netifd/files/sbin/ifup b/package/netifd/files/sbin/ifup
new file mode 100755
index 000000000..e6dbb3541
--- /dev/null
+++ b/package/netifd/files/sbin/ifup
@@ -0,0 +1,79 @@
+#!/bin/sh
+
+ifup_all=
+setup_wifi=
+
+if_call() {
+ local interface="$1"
+ for mode in $modes; do
+ ubus call $interface $mode
+ done
+}
+
+case "$0" in
+ *ifdown) modes=down;;
+ *ifup)
+ modes="down up"
+ setup_wifi=1
+ ;;
+ *) echo "Invalid command: $0";;
+esac
+
+while :; do
+ case "$1" in
+ -a)
+ ifup_all=1
+ shift
+ ;;
+ -w)
+ setup_wifi=
+ shift
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+
+[ "$modes" = "down up" ] && ubus call network reload
+if [ -n "$ifup_all" ]; then
+ for interface in `ubus -S list 'network.interface.*'`; do
+ if_call "$interface"
+ done
+ [ -n "$setup_wifi" ] && /sbin/wifi up
+ exit
+else
+ ubus -S list "network.interface.$1" > /dev/null || {
+ echo "Interface $1 not found"
+ exit
+ }
+ if_call "network.interface.$1"
+fi
+
+if [ -n "$setup_wifi" ] && grep -sq config /etc/config/wireless; then
+ . /lib/functions.sh
+
+ find_related_radios() {
+ local wdev wnet
+ config_get wdev "$1" device
+ config_get wnet "$1" network
+
+ if [ -n "$wdev" ]; then
+ for wnet in $wnet; do
+ if [ "$wnet" = "$network" ]; then
+ append radio_devs "$wdev" "$N"
+ fi
+ done
+ fi
+ }
+
+ local radio_devs
+ local network="$1"
+ config_load wireless
+ config_foreach find_related_radios wifi-iface
+
+ local dev
+ for dev in $(echo "$radio_devs" | sort -u); do
+ /sbin/wifi up "$dev"
+ done
+fi
diff --git a/package/netifd/files/usr/share/udhcpc/default.script b/package/netifd/files/usr/share/udhcpc/default.script
new file mode 100755
index 000000000..ac765a636
--- /dev/null
+++ b/package/netifd/files/usr/share/udhcpc/default.script
@@ -0,0 +1,57 @@
+#!/bin/sh
+[ -z "$1" ] && echo "Error: should be run by udhcpc" && exit 1
+
+set_classless_routes() {
+ local max=128
+ local type
+ while [ -n "$1" -a -n "$2" -a $max -gt 0 ]; do
+ [ ${1##*/} -eq 32 ] && type=host || type=net
+ echo "udhcpc: adding route for $type $1 via $2"
+ route add -$type "$1" gw "$2" dev "$interface"
+ max=$(($max-1))
+ shift 2
+ done
+}
+
+setup_interface() {
+ echo "udhcpc: ifconfig $interface $ip netmask ${subnet:-255.255.255.0} broadcast ${broadcast:-+}"
+ ifconfig $interface $ip netmask ${subnet:-255.255.255.0} broadcast ${broadcast:-+}
+
+ [ -n "$router" ] && [ "$router" != "0.0.0.0" ] && [ "$router" != "255.255.255.255" ] && {
+ echo "udhcpc: setting default routers: $router"
+
+ local valid_gw=""
+ for i in $router ; do
+ route add default gw $i dev $interface
+ valid_gw="${valid_gw:+$valid_gw|}$i"
+ done
+
+ eval $(route -n | awk '
+ /^0.0.0.0\W{9}('$valid_gw')\W/ {next}
+ /^0.0.0.0/ {print "route del -net "$1" gw "$2";"}
+ ')
+ }
+
+ # CIDR STATIC ROUTES (rfc3442)
+ [ -n "$staticroutes" ] && set_classless_routes $staticroutes
+ [ -n "$msstaticroutes" ] && set_classless_routes $msstaticroutes
+}
+
+
+applied=
+case "$1" in
+ deconfig)
+ ifconfig "$interface" 0.0.0.0
+ ;;
+ renew)
+ setup_interface update
+ ;;
+ bound)
+ setup_interface ifup
+ ;;
+esac
+
+# user rules
+[ -f /etc/udhcpc.user ] && . /etc/udhcpc.user
+
+exit 0
diff --git a/package/nvram/Makefile b/package/nvram/Makefile
new file mode 100644
index 000000000..81cff034c
--- /dev/null
+++ b/package/nvram/Makefile
@@ -0,0 +1,60 @@
+#
+# Copyright (C) 2009-2010 Jo-Philipp Wich <xm@subsignal.org>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=nvram
+PKG_RELEASE:=9
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/nvram
+ SECTION:=utils
+ CATEGORY:=Base system
+ TITLE:=Userspace port of the Broadcom NVRAM manipulation tool
+ MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org>
+ DEPENDS:=@TARGET_brcm47xx||@TARGET_ar71xx
+endef
+
+define Package/nvram/description
+ This package contains an utility to manipulate NVRAM on Broadcom based devices.
+ It works on bcm47xx (Linux 2.6) without using the kernel api.
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CC)" \
+ CFLAGS="$(TARGET_CFLAGS) -Wall" \
+ LDFLAGS="$(TARGET_LDFLAGS)"
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/libnvram.so.0.1 $(1)/usr/lib/
+ ln -s libnvram.so.0.1 $(1)/usr/lib/libnvram.so
+endef
+
+define Package/nvram/install
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/nvram.init $(1)/etc/init.d/nvram
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/nvram $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/libnvram.so.0.1 $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,nvram))
diff --git a/package/nvram/files/nvram.init b/package/nvram/files/nvram.init
new file mode 100755
index 000000000..467ab2819
--- /dev/null
+++ b/package/nvram/files/nvram.init
@@ -0,0 +1,98 @@
+#!/bin/sh /etc/rc.common
+# NVRAM setup
+#
+# This file handles the NVRAM quirks of various hardware.
+
+START=02
+alias debug=${DEBUG:-:}
+
+nvram_default() {
+ [ -z "$(nvram get $1)" ] && nvram set "$1=$2"
+}
+
+nvram_set() { # for the linksys fixup part
+ [ "$(nvram get "$1")" = "$2" -a "$2" != "" ] || {
+ COMMIT=1
+ /usr/sbin/nvram set "$1=$2"
+ }
+}
+
+fixup_linksys() {
+ # work around braindead CFE defaults in linksys routers
+ boardtype=$(nvram get boardtype)
+ boardnum=$(nvram get boardnum)
+ boardflags=$(($(nvram get boardflags)))
+ adm_switch="$(( ($boardflags & 0x80) >> 7 ))"
+
+ [ -n "$(nvram get vxkilled)" ] && boardtype=0 # don't mess with the ram settings on the hacked cfe
+ case "$(( $boardtype ))" in
+ "1800") #0x708
+ if [ "$adm_switch" = 0 ]; then
+ nvram_set sdram_init "$(printf 0x%04x $(( $(/usr/sbin/nvram get sdram_init) | 0x0100 )))"
+ [ "$COMMIT" = 1 ] && {
+ nvram_set clkfreq 216
+ nvram_set sdram_ncdl 0x0
+ nvram_set pa0itssit 62
+ nvram_set pa0b0 0x15eb
+ nvram_set pa0b1 0xfa82
+ nvram_set pa0b2 0xfe66
+ nvram_set pa0maxpwr 0x4e
+ }
+ fi
+ ;;
+ "1127") #0x467
+ nvram_set sdram_init "$(printf 0x%04x $(( $(/usr/sbin/nvram get sdram_init) | 0x0100 )))"
+ [ "$COMMIT" = 1 ] && {
+ nvram_set sdram_ncdl 0x0
+ nvram_set pa0itssit 62
+ nvram_set pa0b0 0x168b
+ nvram_set pa0b1 0xfabf
+ nvram_set pa0b2 0xfeaf
+ nvram_set pa0maxpwr 0x4e
+ }
+ ;;
+ "1071") #0x042f
+ # do sanity check first! max 0x0011 = 128mb
+ SDRAM_INIT=$(printf %d $(/usr/sbin/nvram get sdram_init))
+ [ "$SDRAM_INIT" -lt "9" -o "$SDRAM_INIT" -gt "17" ] && {
+ # set this to default: 0x09 only if value is invaild like 16MB on Asus WL-500GP
+ echo "sdram_init is invaild: $(printf 0x%04x $SDRAM_INIT), force to default!"
+ nvram_set sdram_init 0x0009
+ }
+ # on WRT54G3GV2 set flag, so checksum errors of firmware image 2 don't stop the boot process
+ noset_try_flag=$(nvram get noset_try_flag)
+ [ "$noset_try_flag" = 0 ] && {
+ echo "setting noset_try_flag to 1."
+ nvram_set noset_try_flag 1
+ }
+ [ "$COMMIT" = 1 ] && {
+ nvram_set sdram_ncdl 0x0
+ }
+ esac
+}
+
+start() {
+ # Don't do any fixups on the WGT634U
+ [ "$(cat /proc/diag/model)" = "Netgear WGT634U" ] && return
+
+ fixup_linksys
+
+ # OFDM Power Offset is set incorrectly on many boards.
+ # Setting it to 0 will increase the tx power to normal levels.
+ nvram_set opo 0x0
+
+ [ "$(nvram get il0macaddr)" = "00:90:4c:5f:00:2a" ] && {
+ # if default wifi mac, set two higher than the lan mac
+ nvram set il0macaddr=$(nvram get et0macaddr|
+ awk '{OFS=FS=":";for(x=7,y=2;--x;){$x=sprintf("%02x",(y+="0x"$x)%256);y/=256}print}')
+ }
+
+ [ "$(nvram get et0macaddr)" = "00:90:4c:c0:00:08" ] && {
+ # OvisLink WL-1600GL mac workaround
+ nvram set et0macaddr=$(hexdump -n 6 -s 130976 -e '5/1 "%02x:" "%02x" ' /dev/mtd/0)
+ nvram set il0macaddr=$(nvram get et0macaddr|
+ awk '{OFS=FS=":";for(x=7,y=2;--x;){$x=sprintf("%02x",(y+="0x"$x)%256);y/=256}print}')
+ }
+
+ [ "$COMMIT" = "1" ] && nvram commit
+}
diff --git a/package/nvram/src/Makefile b/package/nvram/src/Makefile
new file mode 100644
index 000000000..4872728ba
--- /dev/null
+++ b/package/nvram/src/Makefile
@@ -0,0 +1,33 @@
+CLI_FILENAME = nvram
+
+LIB_VERMAJOR = 0
+LIB_VERMINOR = 1
+LIB_FILENAME = libnvram.so
+
+LIB_CFLAGS = $(CFLAGS) -shared -fPIC
+LIB_LDFLAGS = $(LDFLAGS) -Wl,-soname,$(LIB_FILENAME).$(LIB_VERMAJOR).$(LIB_VERMINOR)
+
+CLI_CFLAGS = $(CFLAGS)
+CLI_LDFLAGS = $(LDFLAGS)
+
+CLI_OBJ = cli.o
+LIB_OBJ = crc.o nvram.o
+
+all: cli libnvram
+
+cli: libnvram
+ $(CC) $(CLI_CFLAGS) -c -o cli.o cli.c
+ $(CC) -o $(CLI_FILENAME) $(CLI_LDFLAGS) $(CLI_OBJ) \
+ $(LIB_FILENAME).$(LIB_VERMAJOR).$(LIB_VERMINOR)
+
+cli.o: cli.c
+ $(CC) $(CLI_CFLAGS) -c -o $@ $<
+
+libnvram:
+ $(CC) $(LIB_CFLAGS) -c -o crc.o crc.c
+ $(CC) $(LIB_CFLAGS) -c -o nvram.o nvram.c
+ $(CC) $(LIB_CFLAGS) $(LIB_LDFLAGS) \
+ -o $(LIB_FILENAME).$(LIB_VERMAJOR).$(LIB_VERMINOR) $(LIB_OBJ)
+
+clean:
+ rm -f $(CLI_FILENAME) $(LIB_FILENAME)* *.o
diff --git a/package/nvram/src/cli.c b/package/nvram/src/cli.c
new file mode 100644
index 000000000..66ef90488
--- /dev/null
+++ b/package/nvram/src/cli.c
@@ -0,0 +1,246 @@
+/*
+ * Command line interface for libnvram
+ *
+ * Copyright 2009, Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ *
+ * The libnvram code is based on Broadcom code for Linux 2.4.x .
+ *
+ */
+
+#include "nvram.h"
+
+
+static nvram_handle_t * nvram_open_rdonly(void)
+{
+ const char *file = nvram_find_staging();
+
+ if( file == NULL )
+ file = nvram_find_mtd();
+
+ if( file != NULL )
+ return nvram_open(file, NVRAM_RO);
+
+ return NULL;
+}
+
+static nvram_handle_t * nvram_open_staging(void)
+{
+ if( nvram_find_staging() != NULL || nvram_to_staging() == 0 )
+ return nvram_open(NVRAM_STAGING, NVRAM_RW);
+
+ return NULL;
+}
+
+static int do_show(nvram_handle_t *nvram)
+{
+ nvram_tuple_t *t;
+ int stat = 1;
+
+ if( (t = nvram_getall(nvram)) != NULL )
+ {
+ while( t )
+ {
+ printf("%s=%s\n", t->name, t->value);
+ t = t->next;
+ }
+
+ stat = 0;
+ }
+
+ return stat;
+}
+
+static int do_get(nvram_handle_t *nvram, const char *var)
+{
+ const char *val;
+ int stat = 1;
+
+ if( (val = nvram_get(nvram, var)) != NULL )
+ {
+ printf("%s\n", val);
+ stat = 0;
+ }
+
+ return stat;
+}
+
+static int do_unset(nvram_handle_t *nvram, const char *var)
+{
+ return nvram_unset(nvram, var);
+}
+
+static int do_set(nvram_handle_t *nvram, const char *pair)
+{
+ char *val = strstr(pair, "=");
+ char var[strlen(pair)];
+ int stat = 1;
+
+ if( val != NULL )
+ {
+ memset(var, 0, sizeof(var));
+ strncpy(var, pair, (int)(val-pair));
+ stat = nvram_set(nvram, var, (char *)(val + 1));
+ }
+
+ return stat;
+}
+
+static int do_info(nvram_handle_t *nvram)
+{
+ nvram_header_t *hdr = nvram_header(nvram);
+
+ /* CRC8 over the last 11 bytes of the header and data bytes */
+ uint8_t crc = hndcrc8((unsigned char *) &hdr[0] + NVRAM_CRC_START_POSITION,
+ hdr->len - NVRAM_CRC_START_POSITION, 0xff);
+
+ /* Show info */
+ printf("Magic: 0x%08X\n", hdr->magic);
+ printf("Length: 0x%08X\n", hdr->len);
+ printf("Offset: 0x%08X\n", nvram->offset);
+
+ printf("CRC8: 0x%02X (calculated: 0x%02X)\n",
+ hdr->crc_ver_init & 0xFF, crc);
+
+ printf("Version: 0x%02X\n", (hdr->crc_ver_init >> 8) & 0xFF);
+ printf("SDRAM init: 0x%04X\n", (hdr->crc_ver_init >> 16) & 0xFFFF);
+ printf("SDRAM config: 0x%04X\n", hdr->config_refresh & 0xFFFF);
+ printf("SDRAM refresh: 0x%04X\n", (hdr->config_refresh >> 16) & 0xFFFF);
+ printf("NCDL values: 0x%08X\n\n", hdr->config_ncdl);
+
+ printf("%i bytes used / %i bytes available (%.2f%%)\n",
+ hdr->len, NVRAM_SPACE - hdr->len,
+ (100.00 / (double)NVRAM_SPACE) * (double)hdr->len);
+
+ return 0;
+}
+
+
+int main( int argc, const char *argv[] )
+{
+ nvram_handle_t *nvram;
+ int commit = 0;
+ int write = 0;
+ int stat = 1;
+ int done = 0;
+ int i;
+
+ /* Ugly... iterate over arguments to see whether we can expect a write */
+ for( i = 1; i < argc; i++ )
+ if( ( !strcmp(argv[i], "set") && ++i < argc ) ||
+ ( !strcmp(argv[i], "unset") && ++i < argc ) ||
+ !strcmp(argv[i], "commit") )
+ {
+ write = 1;
+ break;
+ }
+
+
+ nvram = write ? nvram_open_staging() : nvram_open_rdonly();
+
+ if( nvram != NULL && argc > 1 )
+ {
+ for( i = 1; i < argc; i++ )
+ {
+ if( !strcmp(argv[i], "show") )
+ {
+ stat = do_show(nvram);
+ done++;
+ }
+ else if( !strcmp(argv[i], "info") )
+ {
+ stat = do_info(nvram);
+ done++;
+ }
+ else if( !strcmp(argv[i], "get") || !strcmp(argv[i], "unset") || !strcmp(argv[i], "set") )
+ {
+ if( (i+1) < argc )
+ {
+ switch(argv[i++][0])
+ {
+ case 'g':
+ stat = do_get(nvram, argv[i]);
+ break;
+
+ case 'u':
+ stat = do_unset(nvram, argv[i]);
+ break;
+
+ case 's':
+ stat = do_set(nvram, argv[i]);
+ break;
+ }
+ done++;
+ }
+ else
+ {
+ fprintf(stderr, "Command '%s' requires an argument!\n", argv[i]);
+ done = 0;
+ break;
+ }
+ }
+ else if( !strcmp(argv[i], "commit") )
+ {
+ commit = 1;
+ done++;
+ }
+ else
+ {
+ fprintf(stderr, "Unknown option '%s' !\n", argv[i]);
+ done = 0;
+ break;
+ }
+ }
+
+ if( write )
+ stat = nvram_commit(nvram);
+
+ nvram_close(nvram);
+
+ if( commit )
+ stat = staging_to_nvram();
+ }
+
+ if( !nvram )
+ {
+ fprintf(stderr,
+ "Could not open nvram! Possible reasons are:\n"
+ " - No device found (/proc not mounted or no nvram present)\n"
+ " - Insufficient permissions to open mtd device\n"
+ " - Insufficient memory to complete operation\n"
+ " - Memory mapping failed or not supported\n"
+ );
+
+ stat = 1;
+ }
+ else if( !done )
+ {
+ fprintf(stderr,
+ "Usage:\n"
+ " nvram show\n"
+ " nvram info\n"
+ " nvram get variable\n"
+ " nvram set variable=value [set ...]\n"
+ " nvram unset variable [unset ...]\n"
+ " nvram commit\n"
+ );
+
+ stat = 1;
+ }
+
+ return stat;
+}
diff --git a/package/nvram/src/crc.c b/package/nvram/src/crc.c
new file mode 100644
index 000000000..22a36652a
--- /dev/null
+++ b/package/nvram/src/crc.c
@@ -0,0 +1,69 @@
+#include "nvram.h"
+
+/*******************************************************************************
+ * crc8
+ *
+ * Computes a crc8 over the input data using the polynomial:
+ *
+ * x^8 + x^7 +x^6 + x^4 + x^2 + 1
+ *
+ * The caller provides the initial value (either CRC8_INIT_VALUE
+ * or the previous returned value) to allow for processing of
+ * discontiguous blocks of data. When generating the CRC the
+ * caller is responsible for complementing the final return value
+ * and inserting it into the byte stream. When checking, a final
+ * return value of CRC8_GOOD_VALUE indicates a valid CRC.
+ *
+ * Reference: Dallas Semiconductor Application Note 27
+ * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
+ * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
+ * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
+ *
+ * ****************************************************************************
+ */
+
+static const uint8_t crc8_table[256] = {
+ 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
+ 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
+ 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
+ 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
+ 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
+ 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
+ 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
+ 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
+ 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
+ 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
+ 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
+ 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
+ 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
+ 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
+ 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
+ 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
+ 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
+ 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
+ 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
+ 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
+ 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
+ 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
+ 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
+ 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
+ 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
+ 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
+ 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
+ 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
+ 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
+ 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
+ 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
+ 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F
+};
+
+uint8_t hndcrc8 (
+ uint8_t * pdata, /* pointer to array of data to process */
+ uint32_t nbytes, /* number of input data bytes to process */
+ uint8_t crc /* either CRC8_INIT_VALUE or previous return value */
+) {
+ while (nbytes-- > 0)
+ crc = crc8_table[(crc ^ *pdata++) & 0xff];
+
+ return crc;
+}
diff --git a/package/nvram/src/nvram.c b/package/nvram/src/nvram.c
new file mode 100644
index 000000000..a0bc006d1
--- /dev/null
+++ b/package/nvram/src/nvram.c
@@ -0,0 +1,556 @@
+/*
+ * NVRAM variable manipulation (common)
+ *
+ * Copyright 2004, Broadcom Corporation
+ * Copyright 2009-2010, OpenWrt.org
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ */
+
+#include "nvram.h"
+
+#define TRACE(msg) \
+ printf("%s(%i) in %s(): %s\n", \
+ __FILE__, __LINE__, __FUNCTION__, msg ? msg : "?")
+
+size_t nvram_erase_size = 0;
+
+
+/*
+ * -- Helper functions --
+ */
+
+/* String hash */
+static uint32_t hash(const char *s)
+{
+ uint32_t hash = 0;
+
+ while (*s)
+ hash = 31 * hash + *s++;
+
+ return hash;
+}
+
+/* Free all tuples. */
+static void _nvram_free(nvram_handle_t *h)
+{
+ uint32_t i;
+ nvram_tuple_t *t, *next;
+
+ /* Free hash table */
+ for (i = 0; i < NVRAM_ARRAYSIZE(h->nvram_hash); i++) {
+ for (t = h->nvram_hash[i]; t; t = next) {
+ next = t->next;
+ free(t);
+ }
+ h->nvram_hash[i] = NULL;
+ }
+
+ /* Free dead table */
+ for (t = h->nvram_dead; t; t = next) {
+ next = t->next;
+ free(t);
+ }
+
+ h->nvram_dead = NULL;
+}
+
+/* (Re)allocate NVRAM tuples. */
+static nvram_tuple_t * _nvram_realloc( nvram_handle_t *h, nvram_tuple_t *t,
+ const char *name, const char *value )
+{
+ if ((strlen(value) + 1) > NVRAM_SPACE)
+ return NULL;
+
+ if (!t) {
+ if (!(t = malloc(sizeof(nvram_tuple_t) + strlen(name) + 1)))
+ return NULL;
+
+ /* Copy name */
+ t->name = (char *) &t[1];
+ strcpy(t->name, name);
+
+ t->value = NULL;
+ }
+
+ /* Copy value */
+ if (!t->value || strcmp(t->value, value))
+ {
+ if(!(t->value = (char *) realloc(t->value, strlen(value)+1)))
+ return NULL;
+
+ strcpy(t->value, value);
+ t->value[strlen(value)] = '\0';
+ }
+
+ return t;
+}
+
+/* (Re)initialize the hash table. */
+static int _nvram_rehash(nvram_handle_t *h)
+{
+ nvram_header_t *header = nvram_header(h);
+ char buf[] = "0xXXXXXXXX", *name, *value, *eq;
+
+ /* (Re)initialize hash table */
+ _nvram_free(h);
+
+ /* Parse and set "name=value\0 ... \0\0" */
+ name = (char *) &header[1];
+
+ for (; *name; name = value + strlen(value) + 1) {
+ if (!(eq = strchr(name, '=')))
+ break;
+ *eq = '\0';
+ value = eq + 1;
+ nvram_set(h, name, value);
+ *eq = '=';
+ }
+
+ /* Set special SDRAM parameters */
+ if (!nvram_get(h, "sdram_init")) {
+ sprintf(buf, "0x%04X", (uint16_t)(header->crc_ver_init >> 16));
+ nvram_set(h, "sdram_init", buf);
+ }
+ if (!nvram_get(h, "sdram_config")) {
+ sprintf(buf, "0x%04X", (uint16_t)(header->config_refresh & 0xffff));
+ nvram_set(h, "sdram_config", buf);
+ }
+ if (!nvram_get(h, "sdram_refresh")) {
+ sprintf(buf, "0x%04X",
+ (uint16_t)((header->config_refresh >> 16) & 0xffff));
+ nvram_set(h, "sdram_refresh", buf);
+ }
+ if (!nvram_get(h, "sdram_ncdl")) {
+ sprintf(buf, "0x%08X", header->config_ncdl);
+ nvram_set(h, "sdram_ncdl", buf);
+ }
+
+ return 0;
+}
+
+
+/*
+ * -- Public functions --
+ */
+
+/* Get nvram header. */
+nvram_header_t * nvram_header(nvram_handle_t *h)
+{
+ return (nvram_header_t *) &h->mmap[h->offset];
+}
+
+/* Get the value of an NVRAM variable. */
+char * nvram_get(nvram_handle_t *h, const char *name)
+{
+ uint32_t i;
+ nvram_tuple_t *t;
+ char *value;
+
+ if (!name)
+ return NULL;
+
+ /* Hash the name */
+ i = hash(name) % NVRAM_ARRAYSIZE(h->nvram_hash);
+
+ /* Find the associated tuple in the hash table */
+ for (t = h->nvram_hash[i]; t && strcmp(t->name, name); t = t->next);
+
+ value = t ? t->value : NULL;
+
+ return value;
+}
+
+/* Set the value of an NVRAM variable. */
+int nvram_set(nvram_handle_t *h, const char *name, const char *value)
+{
+ uint32_t i;
+ nvram_tuple_t *t, *u, **prev;
+
+ /* Hash the name */
+ i = hash(name) % NVRAM_ARRAYSIZE(h->nvram_hash);
+
+ /* Find the associated tuple in the hash table */
+ for (prev = &h->nvram_hash[i], t = *prev;
+ t && strcmp(t->name, name); prev = &t->next, t = *prev);
+
+ /* (Re)allocate tuple */
+ if (!(u = _nvram_realloc(h, t, name, value)))
+ return -12; /* -ENOMEM */
+
+ /* Value reallocated */
+ if (t && t == u)
+ return 0;
+
+ /* Move old tuple to the dead table */
+ if (t) {
+ *prev = t->next;
+ t->next = h->nvram_dead;
+ h->nvram_dead = t;
+ }
+
+ /* Add new tuple to the hash table */
+ u->next = h->nvram_hash[i];
+ h->nvram_hash[i] = u;
+
+ return 0;
+}
+
+/* Unset the value of an NVRAM variable. */
+int nvram_unset(nvram_handle_t *h, const char *name)
+{
+ uint32_t i;
+ nvram_tuple_t *t, **prev;
+
+ if (!name)
+ return 0;
+
+ /* Hash the name */
+ i = hash(name) % NVRAM_ARRAYSIZE(h->nvram_hash);
+
+ /* Find the associated tuple in the hash table */
+ for (prev = &h->nvram_hash[i], t = *prev;
+ t && strcmp(t->name, name); prev = &t->next, t = *prev);
+
+ /* Move it to the dead table */
+ if (t) {
+ *prev = t->next;
+ t->next = h->nvram_dead;
+ h->nvram_dead = t;
+ }
+
+ return 0;
+}
+
+/* Get all NVRAM variables. */
+nvram_tuple_t * nvram_getall(nvram_handle_t *h)
+{
+ int i;
+ nvram_tuple_t *t, *l, *x;
+
+ l = NULL;
+
+ for (i = 0; i < NVRAM_ARRAYSIZE(h->nvram_hash); i++) {
+ for (t = h->nvram_hash[i]; t; t = t->next) {
+ if( (x = (nvram_tuple_t *) malloc(sizeof(nvram_tuple_t))) != NULL )
+ {
+ x->name = t->name;
+ x->value = t->value;
+ x->next = l;
+ l = x;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ return l;
+}
+
+/* Regenerate NVRAM. */
+int nvram_commit(nvram_handle_t *h)
+{
+ nvram_header_t *header = nvram_header(h);
+ char *init, *config, *refresh, *ncdl;
+ char *ptr, *end;
+ int i;
+ nvram_tuple_t *t;
+ nvram_header_t tmp;
+ uint8_t crc;
+
+ /* Regenerate header */
+ header->magic = NVRAM_MAGIC;
+ header->crc_ver_init = (NVRAM_VERSION << 8);
+ if (!(init = nvram_get(h, "sdram_init")) ||
+ !(config = nvram_get(h, "sdram_config")) ||
+ !(refresh = nvram_get(h, "sdram_refresh")) ||
+ !(ncdl = nvram_get(h, "sdram_ncdl"))) {
+ header->crc_ver_init |= SDRAM_INIT << 16;
+ header->config_refresh = SDRAM_CONFIG;
+ header->config_refresh |= SDRAM_REFRESH << 16;
+ header->config_ncdl = 0;
+ } else {
+ header->crc_ver_init |= (strtoul(init, NULL, 0) & 0xffff) << 16;
+ header->config_refresh = strtoul(config, NULL, 0) & 0xffff;
+ header->config_refresh |= (strtoul(refresh, NULL, 0) & 0xffff) << 16;
+ header->config_ncdl = strtoul(ncdl, NULL, 0);
+ }
+
+ /* Clear data area */
+ ptr = (char *) header + sizeof(nvram_header_t);
+ memset(ptr, 0xFF, NVRAM_SPACE - sizeof(nvram_header_t));
+ memset(&tmp, 0, sizeof(nvram_header_t));
+
+ /* Leave space for a double NUL at the end */
+ end = (char *) header + NVRAM_SPACE - 2;
+
+ /* Write out all tuples */
+ for (i = 0; i < NVRAM_ARRAYSIZE(h->nvram_hash); i++) {
+ for (t = h->nvram_hash[i]; t; t = t->next) {
+ if ((ptr + strlen(t->name) + 1 + strlen(t->value) + 1) > end)
+ break;
+ ptr += sprintf(ptr, "%s=%s", t->name, t->value) + 1;
+ }
+ }
+
+ /* End with a double NULL and pad to 4 bytes */
+ *ptr = '\0';
+ ptr++;
+
+ if( (int)ptr % 4 )
+ memset(ptr, 0, 4 - ((int)ptr % 4));
+
+ ptr++;
+
+ /* Set new length */
+ header->len = NVRAM_ROUNDUP(ptr - (char *) header, 4);
+
+ /* Little-endian CRC8 over the last 11 bytes of the header */
+ tmp.crc_ver_init = header->crc_ver_init;
+ tmp.config_refresh = header->config_refresh;
+ tmp.config_ncdl = header->config_ncdl;
+ crc = hndcrc8((unsigned char *) &tmp + NVRAM_CRC_START_POSITION,
+ sizeof(nvram_header_t) - NVRAM_CRC_START_POSITION, 0xff);
+
+ /* Continue CRC8 over data bytes */
+ crc = hndcrc8((unsigned char *) &header[0] + sizeof(nvram_header_t),
+ header->len - sizeof(nvram_header_t), crc);
+
+ /* Set new CRC8 */
+ header->crc_ver_init |= crc;
+
+ /* Write out */
+ msync(h->mmap, h->length, MS_SYNC);
+ fsync(h->fd);
+
+ /* Reinitialize hash table */
+ return _nvram_rehash(h);
+}
+
+/* Open NVRAM and obtain a handle. */
+nvram_handle_t * nvram_open(const char *file, int rdonly)
+{
+ int i;
+ int fd;
+ char *mtd = NULL;
+ nvram_handle_t *h;
+ nvram_header_t *header;
+ int offset = -1;
+
+ /* If erase size or file are undefined then try to define them */
+ if( (nvram_erase_size == 0) || (file == NULL) )
+ {
+ /* Finding the mtd will set the appropriate erase size */
+ if( (mtd = nvram_find_mtd()) == NULL || nvram_erase_size == 0 )
+ {
+ free(mtd);
+ return NULL;
+ }
+ }
+
+ if( (fd = open(file ? file : mtd, O_RDWR)) > -1 )
+ {
+ char *mmap_area = (char *) mmap(
+ NULL, nvram_erase_size, PROT_READ | PROT_WRITE,
+ (( rdonly == NVRAM_RO ) ? MAP_PRIVATE : MAP_SHARED) | MAP_LOCKED, fd, 0);
+
+ if( mmap_area != MAP_FAILED )
+ {
+ for( i = 0; i <= ((nvram_erase_size - NVRAM_SPACE) / sizeof(uint32_t)); i++ )
+ {
+ if( ((uint32_t *)mmap_area)[i] == NVRAM_MAGIC )
+ {
+ offset = i * sizeof(uint32_t);
+ break;
+ }
+ }
+
+ if( offset < 0 )
+ {
+ free(mtd);
+ return NULL;
+ }
+ else if( (h = malloc(sizeof(nvram_handle_t))) != NULL )
+ {
+ memset(h, 0, sizeof(nvram_handle_t));
+
+ h->fd = fd;
+ h->mmap = mmap_area;
+ h->length = nvram_erase_size;
+ h->offset = offset;
+
+ header = nvram_header(h);
+
+ if( header->magic == NVRAM_MAGIC )
+ {
+ _nvram_rehash(h);
+ free(mtd);
+ return h;
+ }
+ else
+ {
+ munmap(h->mmap, h->length);
+ free(h);
+ }
+ }
+ }
+ }
+
+ free(mtd);
+ return NULL;
+}
+
+/* Close NVRAM and free memory. */
+int nvram_close(nvram_handle_t *h)
+{
+ _nvram_free(h);
+ munmap(h->mmap, h->length);
+ close(h->fd);
+ free(h);
+
+ return 0;
+}
+
+/* Determine NVRAM device node. */
+char * nvram_find_mtd(void)
+{
+ FILE *fp;
+ int i, esz;
+ char dev[PATH_MAX];
+ char *path = NULL;
+ struct stat s;
+ int supported = 1;
+
+ /* Refuse any operation on the WGT634U */
+ if( (fp = fopen("/proc/diag/model", "r")) )
+ {
+ if( fgets(dev, sizeof(dev), fp) && !strncmp(dev, "Netgear WGT634U", 15) )
+ supported = 0;
+
+ fclose(fp);
+ }
+
+ if( supported && (fp = fopen("/proc/mtd", "r")) )
+ {
+ while( fgets(dev, sizeof(dev), fp) )
+ {
+ if( strstr(dev, "nvram") && sscanf(dev, "mtd%d: %08x", &i, &esz) )
+ {
+ nvram_erase_size = esz;
+
+ sprintf(dev, "/dev/mtdblock/%d", i);
+ if( stat(dev, &s) > -1 && (s.st_mode & S_IFBLK) )
+ {
+ if( (path = (char *) malloc(strlen(dev)+1)) != NULL )
+ {
+ strncpy(path, dev, strlen(dev)+1);
+ break;
+ }
+ }
+ else
+ {
+ sprintf(dev, "/dev/mtdblock%d", i);
+ if( stat(dev, &s) > -1 && (s.st_mode & S_IFBLK) )
+ {
+ if( (path = (char *) malloc(strlen(dev)+1)) != NULL )
+ {
+ strncpy(path, dev, strlen(dev)+1);
+ break;
+ }
+ }
+ }
+ }
+ }
+ fclose(fp);
+ }
+
+ return path;
+}
+
+/* Check NVRAM staging file. */
+char * nvram_find_staging(void)
+{
+ struct stat s;
+
+ if( (stat(NVRAM_STAGING, &s) > -1) && (s.st_mode & S_IFREG) )
+ {
+ return NVRAM_STAGING;
+ }
+
+ return NULL;
+}
+
+/* Copy NVRAM contents to staging file. */
+int nvram_to_staging(void)
+{
+ int fdmtd, fdstg, stat;
+ char *mtd = nvram_find_mtd();
+ char buf[nvram_erase_size];
+
+ stat = -1;
+
+ if( (mtd != NULL) && (nvram_erase_size > 0) )
+ {
+ if( (fdmtd = open(mtd, O_RDONLY)) > -1 )
+ {
+ if( read(fdmtd, buf, sizeof(buf)) == sizeof(buf) )
+ {
+ if((fdstg = open(NVRAM_STAGING, O_WRONLY | O_CREAT, 0600)) > -1)
+ {
+ write(fdstg, buf, sizeof(buf));
+ fsync(fdstg);
+ close(fdstg);
+
+ stat = 0;
+ }
+ }
+
+ close(fdmtd);
+ }
+ }
+
+ free(mtd);
+ return stat;
+}
+
+/* Copy staging file to NVRAM device. */
+int staging_to_nvram(void)
+{
+ int fdmtd, fdstg, stat;
+ char *mtd = nvram_find_mtd();
+ char buf[nvram_erase_size];
+
+ stat = -1;
+
+ if( (mtd != NULL) && (nvram_erase_size > 0) )
+ {
+ if( (fdstg = open(NVRAM_STAGING, O_RDONLY)) > -1 )
+ {
+ if( read(fdstg, buf, sizeof(buf)) == sizeof(buf) )
+ {
+ if( (fdmtd = open(mtd, O_WRONLY | O_SYNC)) > -1 )
+ {
+ write(fdmtd, buf, sizeof(buf));
+ fsync(fdmtd);
+ close(fdmtd);
+ stat = 0;
+ }
+ }
+
+ close(fdstg);
+
+ if( !stat )
+ stat = unlink(NVRAM_STAGING) ? 1 : 0;
+ }
+ }
+
+ free(mtd);
+ return stat;
+}
diff --git a/package/nvram/src/nvram.h b/package/nvram/src/nvram.h
new file mode 100644
index 000000000..c72f67e9a
--- /dev/null
+++ b/package/nvram/src/nvram.h
@@ -0,0 +1,123 @@
+/*
+ * NVRAM variable manipulation
+ *
+ * Copyright 2007, Broadcom Corporation
+ * Copyright 2009, OpenWrt.org
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ */
+
+#ifndef _nvram_h_
+#define _nvram_h_
+
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <linux/limits.h>
+
+#include "sdinitvals.h"
+
+
+struct nvram_header {
+ uint32_t magic;
+ uint32_t len;
+ uint32_t crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
+ uint32_t config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */
+ uint32_t config_ncdl; /* ncdl values for memc */
+} __attribute__((__packed__));
+
+struct nvram_tuple {
+ char *name;
+ char *value;
+ struct nvram_tuple *next;
+};
+
+struct nvram_handle {
+ int fd;
+ char *mmap;
+ unsigned int length;
+ unsigned int offset;
+ struct nvram_tuple *nvram_hash[257];
+ struct nvram_tuple *nvram_dead;
+};
+
+typedef struct nvram_handle nvram_handle_t;
+typedef struct nvram_header nvram_header_t;
+typedef struct nvram_tuple nvram_tuple_t;
+
+
+/* Get nvram header. */
+nvram_header_t * nvram_header(nvram_handle_t *h);
+
+/* Set the value of an NVRAM variable */
+int nvram_set(nvram_handle_t *h, const char *name, const char *value);
+
+/* Get the value of an NVRAM variable. */
+char * nvram_get(nvram_handle_t *h, const char *name);
+
+/* Unset the value of an NVRAM variable. */
+int nvram_unset(nvram_handle_t *h, const char *name);
+
+/* Get all NVRAM variables. */
+nvram_tuple_t * nvram_getall(nvram_handle_t *h);
+
+/* Regenerate NVRAM. */
+int nvram_commit(nvram_handle_t *h);
+
+/* Open NVRAM and obtain a handle. */
+nvram_handle_t * nvram_open(const char *file, int rdonly);
+
+/* Close NVRAM and free memory. */
+int nvram_close(nvram_handle_t *h);
+
+/* Get the value of an NVRAM variable in a safe way, use "" instead of NULL. */
+#define nvram_safe_get(h, name) (nvram_get(h, name) ? : "")
+
+/* Computes a crc8 over the input data. */
+uint8_t hndcrc8 (uint8_t * pdata, uint32_t nbytes, uint8_t crc);
+
+/* Returns the crc value of the nvram. */
+uint8_t nvram_calc_crc(nvram_header_t * nvh);
+
+/* Determine NVRAM device node. */
+char * nvram_find_mtd(void);
+
+/* Copy NVRAM contents to staging file. */
+int nvram_to_staging(void);
+
+/* Copy staging file to NVRAM device. */
+int staging_to_nvram(void);
+
+/* Check NVRAM staging file. */
+char * nvram_find_staging(void);
+
+
+/* Staging file for NVRAM */
+#define NVRAM_STAGING "/tmp/.nvram"
+#define NVRAM_RO 1
+#define NVRAM_RW 0
+
+/* Helper macros */
+#define NVRAM_ARRAYSIZE(a) sizeof(a)/sizeof(a[0])
+#define NVRAM_ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
+
+/* NVRAM constants */
+#define NVRAM_SPACE 0x8000
+#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */
+#define NVRAM_VERSION 1
+
+#define NVRAM_CRC_START_POSITION 9 /* magic, len, crc8 to be skipped */
+
+
+#endif /* _nvram_h_ */
diff --git a/package/nvram/src/sdinitvals.h b/package/nvram/src/sdinitvals.h
new file mode 100644
index 000000000..5a289adec
--- /dev/null
+++ b/package/nvram/src/sdinitvals.h
@@ -0,0 +1,30 @@
+/*
+ * SDRAM init values
+ *
+ * Copyright 2007, Broadcom Corporation
+ * Copyright 2009, OpenWrt.org
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ */
+
+#ifndef _sdinitvals_h_
+#define _sdinitvals_h_
+
+/* SDRAM refresh control (refresh) register bits */
+#define SDRAM_REF(p) (((p)&0xff) | SDRAM_REF_EN) /* Refresh period */
+#define SDRAM_REF_EN 0x8000 /* Writing 1 enables periodic refresh */
+
+/* SDRAM Core default Init values (OCP ID 0x803) */
+#define MEM4MX16X2 0x419 /* 16 MB */
+
+#define SDRAM_INIT MEM4MX16X2
+#define SDRAM_BURSTFULL 0x0000 /* Use full page bursts */
+#define SDRAM_CONFIG SDRAM_BURSTFULL
+#define SDRAM_REFRESH SDRAM_REF(0x40)
+
+#endif /* _sdinitvals_h_ */
diff --git a/package/ocf-crypto-headers/Makefile b/package/ocf-crypto-headers/Makefile
new file mode 100644
index 000000000..fee2a3734
--- /dev/null
+++ b/package/ocf-crypto-headers/Makefile
@@ -0,0 +1,36 @@
+#
+# Copyright (C) 2008-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ocf-crypto-headers
+PKG_VERSION:=20110720
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ocf-crypto-headers
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=OCF-Linux cryptodev header
+ PKGARCH:=all
+ URL:=http://ocf-linux.sourceforge.net/
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+endef
+
+define Build/InstallDev
+ mkdir -p $(1)/usr/include/crypto
+ $(CP) ./src/cryptodev.h $(1)/usr/include/crypto
+endef
+
+$(eval $(call BuildPackage,ocf-crypto-headers))
diff --git a/package/ocf-crypto-headers/src/cryptodev.h b/package/ocf-crypto-headers/src/cryptodev.h
new file mode 100644
index 000000000..cca0ec822
--- /dev/null
+++ b/package/ocf-crypto-headers/src/cryptodev.h
@@ -0,0 +1,480 @@
+/* $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@mcafee.com>
+ * Copyright (C) 2006-2010 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_LZS_COMP 26
+#define CRYPTO_ALGORITHM_MAX 26 /* Keep updated - see above */
+
+/* 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
+#define crd_mlen CRD_INI.cri_mlen
+
+ 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 --git a/package/om-watchdog/Makefile b/package/om-watchdog/Makefile
new file mode 100644
index 000000000..7d517a11e
--- /dev/null
+++ b/package/om-watchdog/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=om-watchdog
+PKG_RELEASE:=1
+PKG_VERSION:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/om-watchdog
+ SECTION:=base
+ CATEGORY:=Base system
+ TITLE:=om watchdog
+ URL:=http://openwrt.org/
+endef
+
+define Package/om-watchdog/description
+ This package contains the hw watchdog script for the OM1P and OM2P device.
+endef
+
+define Build/Prepare
+endef
+
+define Build/Compile
+endef
+
+define Build/Compile
+endef
+
+define Package/om-watchdog/install
+ $(INSTALL_DIR) $(1)/etc/init.d/
+ $(INSTALL_DIR) $(1)/sbin/
+ $(INSTALL_BIN) ./files/om-watchdog.init $(1)/etc/init.d/om-watchdog
+ $(INSTALL_BIN) ./files/om-watchdog $(1)/sbin/om-watchdog
+endef
+
+
+$(eval $(call BuildPackage,om-watchdog))
+
diff --git a/package/om-watchdog/files/om-watchdog b/package/om-watchdog/files/om-watchdog
new file mode 100644
index 000000000..d730c6844
--- /dev/null
+++ b/package/om-watchdog/files/om-watchdog
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+GPIO=$1
+
+trap "" INT HUP
+
+echo $GPIO > /sys/class/gpio/export
+echo out > /sys/class/gpio/gpio${GPIO}/direction
+
+while true; do
+ echo 1 > /sys/class/gpio/gpio${GPIO}/value
+ sleep 1
+ echo 0 > /sys/class/gpio/gpio${GPIO}/value
+ sleep 180
+done
diff --git a/package/om-watchdog/files/om-watchdog.init b/package/om-watchdog/files/om-watchdog.init
new file mode 100644
index 000000000..3d2666b21
--- /dev/null
+++ b/package/om-watchdog/files/om-watchdog.init
@@ -0,0 +1,24 @@
+#!/bin/sh /etc/rc.common
+#
+# Copyright (C) 2011 OpenWrt.org
+#
+
+START=11
+
+SERVICE_DAEMONIZE=1
+
+boot() {
+ if [ -r /lib/ar71xx.sh ]; then
+ . /lib/ar71xx.sh
+ local board=$(ar71xx_board_name)
+
+ if [ "$board" = "om2p" ]; then
+ service_start /sbin/om-watchdog 12
+ elif [ "$board" = "om2p-lc" ]; then
+ service_start /sbin/om-watchdog 26
+ fi
+ else
+ #we assume it is om1p in this case
+ service_start /sbin/om-watchdog 3
+ fi
+}
diff --git a/package/openssl/Config.in b/package/openssl/Config.in
new file mode 100644
index 000000000..11591de04
--- /dev/null
+++ b/package/openssl/Config.in
@@ -0,0 +1,13 @@
+menu "Configuration"
+ depends on PACKAGE_libopenssl
+
+config OPENSSL_ENGINE_CRYPTO
+ bool
+ prompt "Crypto acceleration support"
+
+config OPENSSL_ENGINE_DIGEST
+ bool
+ depends OPENSSL_ENGINE_CRYPTO
+ prompt "Digests acceleration support"
+
+endmenu
diff --git a/package/openssl/Makefile b/package/openssl/Makefile
new file mode 100644
index 000000000..cfc3b3d92
--- /dev/null
+++ b/package/openssl/Makefile
@@ -0,0 +1,179 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=openssl
+PKG_VERSION:=1.0.1c
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://www.openssl.org/source/ \
+ ftp://ftp.funet.fi/pub/crypt/cryptography/libs/openssl/source/ \
+ ftp://ftp.webmonster.de/pub/openssl/source/ \
+ ftp://ftp.sunet.se/pub/security/tools/net/openssl/source/
+PKG_MD5SUM:=ae412727c8c15b67880aef7bd2999b2e
+
+PKG_BUILD_DEPENDS:=ocf-crypto-headers
+PKG_CONFIG_DEPENDS:=CONFIG_OPENSSL_ENGINE_CRYPTO CONFIG_OPENSSL_ENGINE_DIGEST
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/openssl/Default
+ TITLE:=Open source SSL toolkit
+ URL:=http://www.openssl.org/
+endef
+
+define Package/libopenssl/config
+source "$(SOURCE)/Config.in"
+endef
+
+define Package/openssl/Default/description
+The OpenSSL Project is a collaborative effort to develop a robust,
+commercial-grade, full-featured, and Open Source toolkit implementing the Secure
+Sockets Layer (SSL v2/v3) and Transport Layer Security (TLS v1) protocols as well
+as a full-strength general purpose cryptography library.
+endef
+
+define Package/libopenssl
+$(call Package/openssl/Default)
+ SECTION:=libs
+ SUBMENU:=SSL
+ CATEGORY:=Libraries
+ DEPENDS:=+zlib
+ TITLE+= (libraries)
+ MENU:=1
+endef
+
+define Package/libopenssl/description
+$(call Package/openssl/Default/description)
+This package contains the OpenSSL shared libraries, needed by other programs.
+endef
+
+define Package/openssl-util
+ $(call Package/openssl/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libopenssl
+ TITLE+= (utility)
+endef
+
+define Package/openssl-util/conffiles
+/etc/ssl/openssl.cnf
+endef
+
+define Package/openssl-util/description
+$(call Package/openssl/Default/description)
+This package contains the OpenSSL command-line utility.
+endef
+
+
+OPENSSL_NO_CIPHERS:= no-idea no-md2 no-mdc2 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-hw no-threads zlib-dynamic no-sse2
+
+ifdef CONFIG_OPENSSL_ENGINE_CRYPTO
+ OPENSSL_OPTIONS += -DHAVE_CRYPTODEV
+ ifdef CONFIG_OPENSSL_ENGINE_DIGEST
+ OPENSSL_OPTIONS += -DUSE_CRYPTODEV_DIGESTS
+ endif
+else
+ OPENSSL_OPTIONS += no-engines
+endif
+
+ifeq ($(CONFIG_x86_64),y)
+ OPENSSL_TARGET:=linux-x86_64
+else
+ OPENSSL_OPTIONS+=no-sse2
+ ifeq ($(CONFIG_mips)$(CONFIG_mipsel),y)
+ OPENSSL_TARGET:=linux-mips-openwrt
+ else
+ OPENSSL_TARGET:=linux-generic-openwrt
+ OPENSSL_OPTIONS+=no-perlasm
+ endif
+endif
+
+define Build/Configure
+ (cd $(PKG_BUILD_DIR); \
+ ./Configure $(OPENSSL_TARGET) \
+ --prefix=/usr \
+ --openssldir=/etc/ssl \
+ $(TARGET_CPPFLAGS) \
+ $(TARGET_LDFLAGS) -ldl \
+ -DOPENSSL_SMALL_FOOTPRINT \
+ $(OPENSSL_NO_CIPHERS) \
+ $(OPENSSL_OPTIONS) \
+ )
+endef
+
+TARGET_CFLAGS += $(FPIC)
+
+define Build/Compile
+ # XXX: OpenSSL "make depend" will look for installed headers before its own,
+ # so remove installed stuff first
+ -$(SUBMAKE) -j1 clean-staging
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ MAKEDEPPROG="$(TARGET_CROSS)gcc" \
+ OPENWRT_OPTIMIZATION_FLAGS="$(TARGET_CFLAGS)" \
+ $(OPENSSL_MAKEFLAGS) \
+ depend
+ $(_SINGLE)$(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CC)" \
+ AR="$(TARGET_CROSS)ar r" \
+ RANLIB="$(TARGET_CROSS)ranlib" \
+ OPENWRT_OPTIMIZATION_FLAGS="$(TARGET_CFLAGS)" \
+ $(OPENSSL_MAKEFLAGS) \
+ all
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CC)" \
+ AR="$(TARGET_CROSS)ar r" \
+ RANLIB="$(TARGET_CROSS)ranlib" \
+ OPENWRT_OPTIMIZATION_FLAGS="$(TARGET_CFLAGS)" \
+ $(OPENSSL_MAKEFLAGS) \
+ build-shared
+ # Work around openssl build bug to link libssl.so with libcrypto.so.
+ -rm $(PKG_BUILD_DIR)/libssl.so.*.*.*
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CC)" \
+ OPENWRT_OPTIMIZATION_FLAGS="$(TARGET_CFLAGS)" \
+ $(OPENSSL_MAKEFLAGS) \
+ do_linux-shared
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CC)" \
+ INSTALL_PREFIX="$(PKG_INSTALL_DIR)" \
+ $(OPENSSL_MAKEFLAGS) \
+ install
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/openssl $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/lib{crypto,ssl}.{a,so*} $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/{openssl,libcrypto,libssl}.pc $(1)/usr/lib/pkgconfig/
+ [ -n "$(TARGET_LDFLAGS)" ] && $(SED) 's#$(TARGET_LDFLAGS)##g' $(1)/usr/lib/pkgconfig/{openssl,libcrypto,libssl}.pc || true
+endef
+
+define Package/libopenssl/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libcrypto.so.* $(1)/usr/lib/
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libssl.so.* $(1)/usr/lib/
+endef
+
+define Package/openssl-util/install
+ $(INSTALL_DIR) $(1)/etc/ssl
+ $(CP) $(PKG_INSTALL_DIR)/etc/ssl/openssl.cnf $(1)/etc/ssl/
+ $(INSTALL_DIR) $(1)/etc/ssl/certs
+ $(INSTALL_DIR) $(1)/etc/ssl/private
+ chmod 0700 $(1)/etc/ssl/private
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/openssl $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,libopenssl))
+$(eval $(call BuildPackage,openssl-util))
diff --git a/package/openssl/patches/110-optimize-for-size.patch b/package/openssl/patches/110-optimize-for-size.patch
new file mode 100644
index 000000000..f30101786
--- /dev/null
+++ b/package/openssl/patches/110-optimize-for-size.patch
@@ -0,0 +1,13 @@
+--- a/Configure
++++ b/Configure
+@@ -401,6 +401,10 @@ my %table=(
+ "linux-alpha-ccc","ccc:-fast -readonly_strings -DL_ENDIAN -DTERMIO::-D_REENTRANT:::SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL:${alpha_asm}",
+ "linux-alpha+bwx-ccc","ccc:-fast -readonly_strings -DL_ENDIAN -DTERMIO::-D_REENTRANT:::SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL:${alpha_asm}",
+
++# OpenWrt targets
++"linux-mips-openwrt","gcc:-DTERMIO \$(OPENWRT_OPTIMIZATION_FLAGS) -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-generic-openwrt","gcc:-DTERMIO \$(OPENWRT_OPTIMIZATION_FLAGS) -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++
+ # Android: linux-* but without -DTERMIO and pointers to headers and libs.
+ "android","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+ "android-x86","gcc:-mandroid -I\$(ANDROID_DEV)/include -B\$(ANDROID_DEV)/lib -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:".eval{my $asm=${x86_elf_asm};$asm=~s/:elf/:android/;$asm}.":dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
diff --git a/package/openssl/patches/130-perl-path.patch b/package/openssl/patches/130-perl-path.patch
new file mode 100644
index 000000000..dd4fa54d5
--- /dev/null
+++ b/package/openssl/patches/130-perl-path.patch
@@ -0,0 +1,64 @@
+--- a/Configure
++++ b/Configure
+@@ -1,4 +1,4 @@
+-:
++#!/usr/bin/perl
+ eval 'exec perl -S $0 ${1+"$@"}'
+ if $running_under_some_shell;
+ ##
+--- a/tools/c_rehash.in
++++ b/tools/c_rehash.in
+@@ -1,4 +1,4 @@
+-#!/usr/local/bin/perl
++#!/usr/bin/perl
+
+
+ # Perl c_rehash script, scan all files in a directory
+--- a/util/clean-depend.pl
++++ b/util/clean-depend.pl
+@@ -1,4 +1,4 @@
+-#!/usr/local/bin/perl -w
++#!/usr/bin/perl
+ # Clean the dependency list in a makefile of standard includes...
+ # Written by Ben Laurie <ben@algroup.co.uk> 19 Jan 1999
+
+--- a/util/mkdef.pl
++++ b/util/mkdef.pl
+@@ -1,4 +1,4 @@
+-#!/usr/local/bin/perl -w
++#!/usr/bin/perl
+ #
+ # generate a .def file
+ #
+--- a/util/mkerr.pl
++++ b/util/mkerr.pl
+@@ -1,4 +1,4 @@
+-#!/usr/local/bin/perl -w
++#!/usr/bin/perl
+
+ my $config = "crypto/err/openssl.ec";
+ my $hprefix = "openssl/";
+--- a/util/mkstack.pl
++++ b/util/mkstack.pl
+@@ -1,4 +1,4 @@
+-#!/usr/local/bin/perl -w
++#!/usr/bin/perl
+
+ # This is a utility that searches out "DECLARE_STACK_OF()"
+ # declarations in .h and .c files, and updates/creates/replaces
+--- a/util/pod2man.pl
++++ b/util/pod2man.pl
+@@ -1,4 +1,4 @@
+-: #!/usr/bin/perl-5.005
++#!/usr/bin/perl
+ eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
+ if $running_under_some_shell;
+
+--- a/util/selftest.pl
++++ b/util/selftest.pl
+@@ -1,4 +1,4 @@
+-#!/usr/local/bin/perl -w
++#!/usr/bin/perl
+ #
+ # Run the test suite and generate a report
+ #
diff --git a/package/openssl/patches/140-makefile-dirs.patch b/package/openssl/patches/140-makefile-dirs.patch
new file mode 100644
index 000000000..b51ca28b6
--- /dev/null
+++ b/package/openssl/patches/140-makefile-dirs.patch
@@ -0,0 +1,11 @@
+--- a/Makefile.org
++++ b/Makefile.org
+@@ -135,7 +135,7 @@ FIPSCANLIB=
+
+ BASEADDR=
+
+-DIRS= crypto ssl engines apps test tools
++DIRS= crypto ssl apps
+ ENGDIRS= ccgost
+ SHLIBDIRS= crypto ssl
+
diff --git a/package/openssl/patches/150-no_engines.patch b/package/openssl/patches/150-no_engines.patch
new file mode 100644
index 000000000..62aacc1e4
--- /dev/null
+++ b/package/openssl/patches/150-no_engines.patch
@@ -0,0 +1,81 @@
+--- a/Configure
++++ b/Configure
+@@ -2000,6 +2000,11 @@ EOF
+ 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.
+--- a/util/libeay.num
++++ b/util/libeay.num
+@@ -2071,7 +2071,6 @@ PKCS7_ATTR_SIGN_it
+ 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 @@ OCSP_RESPONSE_new
+ 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 @@ ASN1_primitive_free
+ 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 @@ asn1_get_choice_selector
+ 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
+ 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_2passwords
+ 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 @@ OPENSSL_load_builtin_modules
+ 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 @@ EC_GFp_nist_method
+ STORE_meth_set_modify_fn 3530 NOEXIST::FUNCTION:
+ STORE_method_set_modify_function 3530 NOEXIST::FUNCTION:
+ STORE_parse_attrs_next 3531 NOEXIST::FUNCTION:
+-ENGINE_load_padlock 3532 EXIST::FUNCTION:ENGINE,STATIC_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:
diff --git a/package/openssl/patches/160-disable_doc_tests.patch b/package/openssl/patches/160-disable_doc_tests.patch
new file mode 100644
index 000000000..b6dacc1f7
--- /dev/null
+++ b/package/openssl/patches/160-disable_doc_tests.patch
@@ -0,0 +1,58 @@
+--- a/Makefile
++++ b/Makefile
+@@ -137,7 +137,7 @@ FIPSCANLIB=
+
+ BASEADDR=0xFB00000
+
+-DIRS= crypto ssl engines apps test tools
++DIRS= crypto ssl engines apps tools
+ ENGDIRS= ccgost
+ SHLIBDIRS= crypto ssl
+
+@@ -155,7 +155,7 @@ SDIRS= \
+
+ # tests to perform. "alltests" is a special word indicating that all tests
+ # should be performed.
+-TESTS = alltests
++TESTS =
+
+ MAKEFILE= Makefile
+
+@@ -169,7 +169,7 @@ SHELL=/bin/sh
+
+ TOP= .
+ ONEDIRS=out tmp
+-EDIRS= times doc bugs util include certs ms shlib mt demos perl sf dep VMS
++EDIRS= times bugs util include certs ms shlib mt demos perl sf dep VMS
+ WDIRS= windows
+ LIBS= libcrypto.a libssl.a
+ SHARED_CRYPTO=libcrypto$(SHLIB_EXT)
+@@ -270,7 +270,7 @@ reflect:
+ @[ -n "$(THIS)" ] && $(CLEARENV) && $(MAKE) $(THIS) -e $(BUILDENV)
+
+ sub_all: build_all
+-build_all: build_libs build_apps build_tests build_tools
++build_all: build_libs build_apps build_tools
+
+ build_libs: build_crypto build_ssl build_engines
+
+@@ -539,7 +539,7 @@ dist:
+ dist_pem_h:
+ (cd crypto/pem; $(MAKE) -e $(BUILDENV) pem.h; $(MAKE) clean)
+
+-install: all install_docs install_sw
++install: all install_sw
+
+ install_sw:
+ @$(PERL) $(TOP)/util/mkdir-p.pl $(INSTALL_PREFIX)$(INSTALLTOP)/bin \
+--- a/Makefile.org
++++ b/Makefile.org
+@@ -537,7 +537,7 @@ dist:
+ dist_pem_h:
+ (cd crypto/pem; $(MAKE) -e $(BUILDENV) pem.h; $(MAKE) clean)
+
+-install: all install_docs install_sw
++install: all install_sw
+
+ install_sw:
+ @$(PERL) $(TOP)/util/mkdir-p.pl $(INSTALL_PREFIX)$(INSTALLTOP)/bin \
diff --git a/package/openssl/patches/170-bash_path.patch b/package/openssl/patches/170-bash_path.patch
new file mode 100644
index 000000000..c29b59afd
--- /dev/null
+++ b/package/openssl/patches/170-bash_path.patch
@@ -0,0 +1,8 @@
+--- a/util/domd
++++ b/util/domd
+@@ -1,4 +1,4 @@
+-#!/bin/sh
++#!/usr/bin/env bash
+ # Do a makedepend, only leave out the standard headers
+ # Written by Ben Laurie <ben@algroup.co.uk> 19 Jan 1999
+
diff --git a/package/openssl/patches/180-fix_link_segfault.patch b/package/openssl/patches/180-fix_link_segfault.patch
new file mode 100644
index 000000000..3e36beb49
--- /dev/null
+++ b/package/openssl/patches/180-fix_link_segfault.patch
@@ -0,0 +1,18 @@
+--- a/Makefile.shared
++++ b/Makefile.shared
+@@ -95,7 +95,6 @@ LINK_APP= \
+ LDCMD="$${LDCMD:-$(CC)}"; LDFLAGS="$${LDFLAGS:-$(CFLAGS)}"; \
+ LIBPATH=`for x in $$LIBDEPS; do echo $$x; done | sed -e 's/^ *-L//;t' -e d | uniq`; \
+ LIBPATH=`echo $$LIBPATH | sed -e 's/ /:/g'`; \
+- LD_LIBRARY_PATH=$$LIBPATH:$$LD_LIBRARY_PATH \
+ $${LDCMD} $${LDFLAGS} -o $${APPNAME:=$(APPNAME)} $(OBJECTS) $${LIBDEPS} )
+
+ LINK_SO= \
+@@ -105,7 +104,6 @@ LINK_SO= \
+ SHAREDFLAGS="$${SHAREDFLAGS:-$(CFLAGS) $(SHARED_LDFLAGS)}"; \
+ LIBPATH=`for x in $$LIBDEPS; do echo $$x; done | sed -e 's/^ *-L//;t' -e d | uniq`; \
+ LIBPATH=`echo $$LIBPATH | sed -e 's/ /:/g'`; \
+- LD_LIBRARY_PATH=$$LIBPATH:$$LD_LIBRARY_PATH \
+ $${SHAREDCMD} $${SHAREDFLAGS} \
+ -o $$SHLIB$$SHLIB_SOVER$$SHLIB_SUFFIX \
+ $$ALLSYMSFLAGS $$SHOBJECTS $$NOALLSYMSFLAGS $$LIBDEPS \
diff --git a/package/openssl/patches/190-remove_timestamp_check.patch b/package/openssl/patches/190-remove_timestamp_check.patch
new file mode 100644
index 000000000..2677b2d6f
--- /dev/null
+++ b/package/openssl/patches/190-remove_timestamp_check.patch
@@ -0,0 +1,23 @@
+--- a/Makefile.org
++++ b/Makefile.org
+@@ -184,7 +184,7 @@ WTARFILE= $(NAME)-win.tar
+ EXHEADER= e_os2.h
+ HEADER= e_os.h
+
+-all: Makefile build_all openssl.pc libssl.pc libcrypto.pc
++all: build_all openssl.pc libssl.pc libcrypto.pc
+
+ # as we stick to -e, CLEARENV ensures that local variables in lower
+ # Makefiles remain local and variable. $${VAR+VAR} is tribute to Korn
+@@ -396,11 +396,6 @@ openssl.pc: Makefile
+ echo 'Libs.private: $(EX_LIBS)'; \
+ echo 'Cflags: -I$${includedir} $(KRB5_INCLUDES)' ) > openssl.pc
+
+-Makefile: Makefile.org Configure config
+- @echo "Makefile is older than Makefile.org, Configure or config."
+- @echo "Reconfigure the source tree (via './config' or 'perl Configure'), please."
+- @false
+-
+ libclean:
+ rm -f *.map *.so *.so.* *.dylib *.dll engines/*.so engines/*.dll engines/*.dylib *.a engines/*.a */lib */*/lib
+
diff --git a/package/openssl/patches/200-etrax_support.patch b/package/openssl/patches/200-etrax_support.patch
new file mode 100644
index 000000000..9bd155e37
--- /dev/null
+++ b/package/openssl/patches/200-etrax_support.patch
@@ -0,0 +1,13 @@
+--- a/Configure
++++ b/Configure
+@@ -440,6 +440,10 @@ my %table=(
+ "beos-x86-r5", "gcc:-DL_ENDIAN -DTERMIOS -O3 -fomit-frame-pointer -mcpu=pentium -Wall::-D_REENTRANT:BEOS:-lbe -lnet:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:beos:beos-shared:-fPIC -DPIC:-shared:.so",
+ "beos-x86-bone", "gcc:-DL_ENDIAN -DTERMIOS -O3 -fomit-frame-pointer -mcpu=pentium -Wall::-D_REENTRANT:BEOS:-lbe -lbind -lsocket:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:beos:beos-shared:-fPIC:-shared:.so",
+
++# cris
++"linux-cris", "\$(TARGET_CC):-DL_ENDIAN -DTERMIO -fomit-frame-pointer::-D_REENTRANT::-ldl:BN_LLONG THIRTY_TWO_BIT RC4_CHAR::::::::::::dlfcn:linux-shared:-fpic::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)::",
++
++
+ #### SCO/Caldera targets.
+ #
+ # Originally we had like unixware-*, unixware-*-pentium, unixware-*-p6, etc.
diff --git a/package/openssl/patches/210-fix_aes_mips.patch b/package/openssl/patches/210-fix_aes_mips.patch
new file mode 100644
index 000000000..bbfc63a41
--- /dev/null
+++ b/package/openssl/patches/210-fix_aes_mips.patch
@@ -0,0 +1,64 @@
+--- a/crypto/aes/asm/aes-mips.pl
++++ b/crypto/aes/asm/aes-mips.pl
+@@ -1036,9 +1036,9 @@ _mips_AES_set_encrypt_key:
+ nop
+ .end _mips_AES_set_encrypt_key
+
+-.globl AES_set_encrypt_key
+-.ent AES_set_encrypt_key
+-AES_set_encrypt_key:
++.globl private_AES_set_encrypt_key
++.ent private_AES_set_encrypt_key
++private_AES_set_encrypt_key:
+ .frame $sp,$FRAMESIZE,$ra
+ .mask $SAVED_REGS_MASK,-$SZREG
+ .set noreorder
+@@ -1060,7 +1060,7 @@ $code.=<<___ if ($flavour =~ /nubi/i); #
+ ___
+ $code.=<<___ if ($flavour !~ /o32/i); # non-o32 PIC-ification
+ .cplocal $Tbl
+- .cpsetup $pf,$zero,AES_set_encrypt_key
++ .cpsetup $pf,$zero,private_AES_set_encrypt_key
+ ___
+ $code.=<<___;
+ .set reorder
+@@ -1083,7 +1083,7 @@ ___
+ $code.=<<___;
+ jr $ra
+ $PTR_ADD $sp,$FRAMESIZE
+-.end AES_set_encrypt_key
++.end private_AES_set_encrypt_key
+ ___
+
+ my ($head,$tail)=($inp,$bits);
+@@ -1091,9 +1091,9 @@ my ($tp1,$tp2,$tp4,$tp8,$tp9,$tpb,$tpd,$
+ my ($m,$x80808080,$x7f7f7f7f,$x1b1b1b1b)=($at,$t0,$t1,$t2);
+ $code.=<<___;
+ .align 5
+-.globl AES_set_decrypt_key
+-.ent AES_set_decrypt_key
+-AES_set_decrypt_key:
++.globl private_AES_set_decrypt_key
++.ent private_AES_set_decrypt_key
++private_AES_set_decrypt_key:
+ .frame $sp,$FRAMESIZE,$ra
+ .mask $SAVED_REGS_MASK,-$SZREG
+ .set noreorder
+@@ -1115,7 +1115,7 @@ $code.=<<___ if ($flavour =~ /nubi/i); #
+ ___
+ $code.=<<___ if ($flavour !~ /o32/i); # non-o32 PIC-ification
+ .cplocal $Tbl
+- .cpsetup $pf,$zero,AES_set_decrypt_key
++ .cpsetup $pf,$zero,private_AES_set_decrypt_key
+ ___
+ $code.=<<___;
+ .set reorder
+@@ -1226,7 +1226,7 @@ ___
+ $code.=<<___;
+ jr $ra
+ $PTR_ADD $sp,$FRAMESIZE
+-.end AES_set_decrypt_key
++.end private_AES_set_decrypt_key
+ ___
+ }}}
+
diff --git a/package/opkg/Makefile b/package/opkg/Makefile
new file mode 100644
index 000000000..4efd44a20
--- /dev/null
+++ b/package/opkg/Makefile
@@ -0,0 +1,99 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+include $(INCLUDE_DIR)/version.mk
+
+PKG_NAME:=opkg
+PKG_REV:=618
+PKG_VERSION:=$(PKG_REV)
+PKG_RELEASE:=2
+
+PKG_SOURCE_PROTO:=svn
+PKG_SOURCE_VERSION:=$(PKG_REV)
+PKG_SOURCE_SUBDIR:=opkg-$(PKG_VERSION)
+PKG_SOURCE_URL:=http://opkg.googlecode.com/svn/trunk/
+PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.gz
+PKG_FIXUP:=autoreconf
+PKG_REMOVE_FILES = autogen.sh aclocal.m4
+
+PKG_BUILD_PARALLEL:=1
+HOST_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/host-build.mk
+
+define Package/opkg
+ SECTION:=base
+ CATEGORY:=Base system
+ TITLE:=opkg package management system
+ MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org>
+ URL:=http://wiki.openmoko.org/wiki/Opkg
+endef
+
+define Package/opkg/description
+ Lightweight package management system
+ opkg is the opkg Package Management System, for handling
+ installation and removal of packages on a system. It can
+ recursively follow dependencies and download all packages
+ necessary to install a particular package.
+
+ opkg knows how to install both .ipk and .deb packages.
+endef
+
+define Package/opkg/conffiles
+/etc/opkg.conf
+endef
+
+TARGET_CFLAGS += $(if $(CONFIG_GCC_VERSION_4_3)$(CONFIG_GCC_VERSION_4_4),-Wno-array-bounds)
+TARGET_CFLAGS += -ffunction-sections -fdata-sections
+EXTRA_CFLAGS += $(TARGET_CPPFLAGS)
+
+CONFIGURE_ARGS += \
+ --disable-curl \
+ --disable-gpg \
+ --with-opkgetcdir=/etc \
+ --with-opkglockfile=/var/lock/opkg.lock
+
+MAKE_FLAGS = \
+ CC="$(TARGET_CC)" \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ HOST_CPU="$(PKGARCH)" \
+ LDFLAGS="-Wl,--gc-sections" \
+
+define Package/opkg/install
+ $(INSTALL_DIR) $(1)/usr/lib/opkg
+ $(INSTALL_DIR) $(1)/bin
+ $(INSTALL_DIR) $(1)/etc
+ $(INSTALL_DATA) ./files/opkg.conf $(1)/etc/
+ $(VERSION_SED) $(1)/etc/opkg.conf
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/opkg-cl $(1)/bin/opkg
+endef
+
+define Build/InstallDev
+ mkdir -p $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/libopkg $(1)/usr/include/
+endef
+
+
+HOST_CONFIGURE_ARGS+= \
+ --disable-curl \
+ --disable-gpg \
+ --with-opkgetcdir=/etc \
+ --with-opkglockfile=/tmp/opkg.lock
+
+define Host/Compile
+ +$(MAKE) $(HOST_JOBS) -C $(HOST_BUILD_DIR) CC="$(HOSTCC)" all
+endef
+
+define Host/Install
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/src/opkg-cl $(STAGING_DIR_HOST)/bin/opkg
+endef
+
+$(eval $(call BuildPackage,opkg))
+$(eval $(call HostBuild))
diff --git a/package/opkg/files/opkg.conf b/package/opkg/files/opkg.conf
new file mode 100644
index 000000000..6fb42b7fa
--- /dev/null
+++ b/package/opkg/files/opkg.conf
@@ -0,0 +1,5 @@
+src/gz %n %U
+dest root /
+dest ram /tmp
+lists_dir ext /var/opkg-lists
+option overlay_root /overlay
diff --git a/package/opkg/patches/001-ship-pkg-m4.patch b/package/opkg/patches/001-ship-pkg-m4.patch
new file mode 100644
index 000000000..4ca0f8897
--- /dev/null
+++ b/package/opkg/patches/001-ship-pkg-m4.patch
@@ -0,0 +1,168 @@
+--- /dev/null
++++ b/m4/pkg.m4
+@@ -0,0 +1,157 @@
++# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
++#
++# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# 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.
++#
++# As a special exception to the GNU General Public License, if you
++# distribute this file as part of a program that contains a
++# configuration script generated by Autoconf, you may include it under
++# the same distribution terms that you use for the rest of that program.
++
++# PKG_PROG_PKG_CONFIG([MIN-VERSION])
++# ----------------------------------
++AC_DEFUN([PKG_PROG_PKG_CONFIG],
++[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
++m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
++AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
++if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
++ AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
++fi
++if test -n "$PKG_CONFIG"; then
++ _pkg_min_version=m4_default([$1], [0.9.0])
++ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
++ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
++ AC_MSG_RESULT([yes])
++ else
++ AC_MSG_RESULT([no])
++ PKG_CONFIG=""
++ fi
++
++fi[]dnl
++])# PKG_PROG_PKG_CONFIG
++
++# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
++#
++# Check to see whether a particular set of modules exists. Similar
++# to PKG_CHECK_MODULES(), but does not set variables or print errors.
++#
++#
++# Similar to PKG_CHECK_MODULES, make sure that the first instance of
++# this or PKG_CHECK_MODULES is called, or make sure to call
++# PKG_CHECK_EXISTS manually
++# --------------------------------------------------------------
++AC_DEFUN([PKG_CHECK_EXISTS],
++[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
++if test -n "$PKG_CONFIG" && \
++ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
++ m4_ifval([$2], [$2], [:])
++m4_ifvaln([$3], [else
++ $3])dnl
++fi])
++
++
++# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
++# ---------------------------------------------
++m4_define([_PKG_CONFIG],
++[if test -n "$PKG_CONFIG"; then
++ if test -n "$$1"; then
++ pkg_cv_[]$1="$$1"
++ else
++ PKG_CHECK_EXISTS([$3],
++ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
++ [pkg_failed=yes])
++ fi
++else
++ pkg_failed=untried
++fi[]dnl
++])# _PKG_CONFIG
++
++# _PKG_SHORT_ERRORS_SUPPORTED
++# -----------------------------
++AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
++[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
++if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
++ _pkg_short_errors_supported=yes
++else
++ _pkg_short_errors_supported=no
++fi[]dnl
++])# _PKG_SHORT_ERRORS_SUPPORTED
++
++
++# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
++# [ACTION-IF-NOT-FOUND])
++#
++#
++# Note that if there is a possibility the first call to
++# PKG_CHECK_MODULES might not happen, you should be sure to include an
++# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
++#
++#
++# --------------------------------------------------------------
++AC_DEFUN([PKG_CHECK_MODULES],
++[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
++AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
++AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
++
++pkg_failed=no
++AC_MSG_CHECKING([for $1])
++
++_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
++_PKG_CONFIG([$1][_LIBS], [libs], [$2])
++
++m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
++and $1[]_LIBS to avoid the need to call pkg-config.
++See the pkg-config man page for more details.])
++
++if test $pkg_failed = yes; then
++ _PKG_SHORT_ERRORS_SUPPORTED
++ if test $_pkg_short_errors_supported = yes; then
++ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
++ else
++ $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
++ fi
++ # Put the nasty error message in config.log where it belongs
++ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
++
++ ifelse([$4], , [AC_MSG_ERROR(dnl
++[Package requirements ($2) were not met:
++
++$$1_PKG_ERRORS
++
++Consider adjusting the PKG_CONFIG_PATH environment variable if you
++installed software in a non-standard prefix.
++
++_PKG_TEXT
++])],
++ [AC_MSG_RESULT([no])
++ $4])
++elif test $pkg_failed = untried; then
++ ifelse([$4], , [AC_MSG_FAILURE(dnl
++[The pkg-config script could not be found or is too old. Make sure it
++is in your PATH or set the PKG_CONFIG environment variable to the full
++path to pkg-config.
++
++_PKG_TEXT
++
++To get pkg-config, see <http://pkg-config.freedesktop.org/>.])],
++ [$4])
++else
++ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
++ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
++ AC_MSG_RESULT([yes])
++ ifelse([$3], , :, [$3])
++fi[]dnl
++])# PKG_CHECK_MODULES
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1,4 +1,4 @@
+-ACLOCAL_AMFLAGS = -I shave
++ACLOCAL_AMFLAGS = -I shave -I m4
+
+ SUBDIRS = libbb libopkg src tests utils man
+
diff --git a/package/opkg/patches/002-no-shave.patch b/package/opkg/patches/002-no-shave.patch
new file mode 100644
index 000000000..313aa71b0
--- /dev/null
+++ b/package/opkg/patches/002-no-shave.patch
@@ -0,0 +1,37 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -4,7 +4,6 @@ AC_CONFIG_SRCDIR([libopkg/pkg.c])
+
+ AC_CONFIG_AUX_DIR([conf])
+ AC_CONFIG_MACRO_DIR([m4])
+-AC_CONFIG_MACRO_DIR([shave])
+
+ AM_INIT_AUTOMAKE
+ AM_CONFIG_HEADER(libopkg/config.h)
+@@ -277,9 +276,6 @@ AC_SUBST(opkgetcdir)
+ AC_SUBST(opkglockfile)
+ AC_SUBST([CLEAN_DATE])
+
+-# Setup output beautifier.
+-SHAVE_INIT([shave], [enable])
+-
+ AC_OUTPUT(
+ Makefile
+ libopkg/Makefile
+@@ -289,8 +285,6 @@ AC_OUTPUT(
+ utils/Makefile
+ utils/update-alternatives
+ libopkg.pc
+- shave/shave
+- shave/shave-libtool
+ man/Makefile
+ man/opkg-cl.1
+ man/opkg-key.1
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1,4 +1,4 @@
+-ACLOCAL_AMFLAGS = -I shave -I m4
++ACLOCAL_AMFLAGS = -I m4
+
+ SUBDIRS = libbb libopkg src tests utils man
+
diff --git a/package/opkg/patches/004-host_cpu.patch b/package/opkg/patches/004-host_cpu.patch
new file mode 100644
index 000000000..d500d603d
--- /dev/null
+++ b/package/opkg/patches/004-host_cpu.patch
@@ -0,0 +1,20 @@
+--- a/libbb/Makefile.am
++++ b/libbb/Makefile.am
+@@ -1,6 +1,6 @@
+ HOST_CPU=@host_cpu@
+ BUILD_CPU=@build_cpu@
+-ALL_CFLAGS=-g -O -Wall -DHOST_CPU_STR=\"@host_cpu@\" -DBUILD_CPU=@build_cpu@
++ALL_CFLAGS=-g -O -Wall -DHOST_CPU_STR=\"$(HOST_CPU)\" -DBUILD_CPU=@build_cpu@
+
+ noinst_LTLIBRARIES = libbb.la
+
+--- a/libopkg/Makefile.am
++++ b/libopkg/Makefile.am
+@@ -1,5 +1,5 @@
+-
+-AM_CFLAGS=-Wall -DHOST_CPU_STR=\"@host_cpu@\" -DBUILD_CPU=@build_cpu@ -DLIBDIR=\"@libdir@\" -DOPKGLIBDIR=\"@opkglibdir@\" -DOPKGETCDIR=\"@opkgetcdir@\" -DOPKGLOCKFILE=\"@opkglockfile@\" -DDATADIR=\"@datadir@\" -I$(top_srcdir) $(BIGENDIAN_CFLAGS) $(CURL_CFLAGS) $(GPGME_CFLAGS) $(PATHFINDER_CFLAGS)
++HOST_CPU=@host_cpu@
++AM_CFLAGS=-Wall -DHOST_CPU_STR=\"$(HOST_CPU)\" -DBUILD_CPU=@build_cpu@ -DLIBDIR=\"@libdir@\" -DOPKGLIBDIR=\"@opkglibdir@\" -DOPKGETCDIR=\"@opkgetcdir@\" -DOPKGLOCKFILE=\"@opkglockfile@\" -DDATADIR=\"@datadir@\" -I$(top_srcdir) $(BIGENDIAN_CFLAGS) $(CURL_CFLAGS) $(GPGME_CFLAGS) $(PATHFINDER_CFLAGS)
+
+ libopkg_includedir=$(includedir)/libopkg
+ libopkg_include_HEADERS= *.h
diff --git a/package/opkg/patches/007-force_static.patch b/package/opkg/patches/007-force_static.patch
new file mode 100644
index 000000000..80a9815a8
--- /dev/null
+++ b/package/opkg/patches/007-force_static.patch
@@ -0,0 +1,71 @@
+--- a/libopkg/Makefile.am
++++ b/libopkg/Makefile.am
+@@ -38,16 +38,10 @@ if HAVE_SHA256
+ opkg_util_sources += sha256.c sha256.h
+ endif
+
+-lib_LTLIBRARIES = libopkg.la
+-libopkg_la_SOURCES = \
++noinst_LIBRARIES = libopkg.a
++libopkg_a_SOURCES = \
+ $(opkg_libcore_sources) \
+ $(opkg_cmd_sources) $(opkg_db_sources) \
+ $(opkg_util_sources) $(opkg_list_sources)
+
+-libopkg_la_LIBADD = $(top_builddir)/libbb/libbb.la $(CURL_LIBS) $(GPGME_LIBS) $(OPENSSL_LIBS) $(PATHFINDER_LIBS)
+-
+-# make sure we only export symbols that are for public use
+-#libopkg_la_LDFLAGS = -export-symbols-regex "^opkg_.*"
+-
+-
+-
++libopkg_a_LIBADD = $(top_builddir)/libbb/libbb.a $(CURL_LIBS) $(GPGME_LIBS) $(OPENSSL_LIBS) $(PATHFINDER_LIBS)
+--- a/libbb/Makefile.am
++++ b/libbb/Makefile.am
+@@ -2,9 +2,9 @@ HOST_CPU=@host_cpu@
+ BUILD_CPU=@build_cpu@
+ ALL_CFLAGS=-g -O -Wall -DHOST_CPU_STR=\"$(HOST_CPU)\" -DBUILD_CPU=@build_cpu@
+
+-noinst_LTLIBRARIES = libbb.la
++noinst_LIBRARIES = libbb.a
+
+-libbb_la_SOURCES = gz_open.c \
++libbb_a_SOURCES = gz_open.c \
+ libbb.h \
+ unzip.c \
+ wfopen.c \
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -4,11 +4,11 @@ AM_CFLAGS = $(ALL_CFLAGS) -Wall -g -O3 -
+ #noinst_PROGRAMS = libopkg_test opkg_active_list_test
+ noinst_PROGRAMS = libopkg_test
+
+-#opkg_hash_test_LDADD = $(top_builddir)/libbb/libbb.la $(top_builddir)/libopkg/libopkg.la
++#opkg_hash_test_LDADD = $(top_builddir)/libbb/libbb.a $(top_builddir)/libopkg/libopkg.a
+ #opkg_hash_test_SOURCES = opkg_hash_test.c
+ #opkg_hash_test_CFLAGS = $(ALL_CFLAGS) -I$(top_srcdir)
+
+-#opkg_extract_test_LDADD = $(top_builddir)/libbb/libbb.la $(top_builddir)/libopkg/libopkg.la
++#opkg_extract_test_LDADD = $(top_builddir)/libbb/libbb.a $(top_builddir)/libopkg/libopkg.a
+ #opkg_extract_test_SOURCES = opkg_extract_test.c
+ #opkg_extract_test_CFLAGS = $(ALL_CFLAGS) -I$(top_srcdir)
+
+@@ -16,7 +16,7 @@ noinst_PROGRAMS = libopkg_test
+ #opkg_active_list_test_SOURCES = opkg_active_list_test.c
+ #opkg_active_list_test_CFLAGS = $(ALL_CFLAGS) -I$(top_srcdir)
+
+-libopkg_test_LDADD = $(top_builddir)/libopkg/libopkg.la
++libopkg_test_LDADD = $(top_builddir)/libopkg/libopkg.a $(top_builddir)/libbb/libbb.a
+ libopkg_test_SOURCE = libopkg_test.c
+ libopkg_test_LDFLAGS = -static
+
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -2,5 +2,5 @@ AM_CFLAGS = -I${top_srcdir}/libopkg ${AL
+ bin_PROGRAMS = opkg-cl
+
+ opkg_cl_SOURCES = opkg-cl.c
+-opkg_cl_LDADD = $(top_builddir)/libopkg/libopkg.la \
+- $(top_builddir)/libbb/libbb.la
++opkg_cl_LDADD = $(top_builddir)/libopkg/libopkg.a \
++ $(top_builddir)/libbb/libbb.a
diff --git a/package/opkg/patches/009-remove-upgrade-all.patch b/package/opkg/patches/009-remove-upgrade-all.patch
new file mode 100644
index 000000000..395a2a6f9
--- /dev/null
+++ b/package/opkg/patches/009-remove-upgrade-all.patch
@@ -0,0 +1,41 @@
+--- a/libopkg/opkg_cmd.c
++++ b/libopkg/opkg_cmd.c
+@@ -551,18 +551,6 @@ opkg_upgrade_cmd(int argc, char **argv)
+ err = -1;
+ }
+ }
+- } else {
+- pkg_vec_t *installed = pkg_vec_alloc();
+-
+- pkg_info_preinstall_check();
+-
+- pkg_hash_fetch_all_installed(installed);
+- for (i = 0; i < installed->len; i++) {
+- pkg = installed->pkgs[i];
+- if (opkg_upgrade_pkg(pkg))
+- err = -1;
+- }
+- pkg_vec_free(installed);
+ }
+
+ if (opkg_configure_packages(NULL))
+@@ -1258,7 +1246,7 @@ opkg_print_architecture_cmd(int argc, ch
+ array for easier maintenance */
+ static opkg_cmd_t cmds[] = {
+ {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd, PFM_DESCRIPTION|PFM_SOURCE},
+- {"upgrade", 0, (opkg_cmd_fun_t)opkg_upgrade_cmd, PFM_DESCRIPTION|PFM_SOURCE},
++ {"upgrade", 1, (opkg_cmd_fun_t)opkg_upgrade_cmd, PFM_DESCRIPTION|PFM_SOURCE},
+ {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd, PFM_SOURCE},
+ {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd, PFM_SOURCE},
+ {"list-installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd, PFM_SOURCE},
+--- a/src/opkg-cl.c
++++ b/src/opkg-cl.c
+@@ -221,7 +221,7 @@ usage()
+
+ printf("\nPackage Manipulation:\n");
+ printf("\tupdate Update list of available packages\n");
+- printf("\tupgrade Upgrade installed packages\n");
++ printf("\tupgrade <pkgs> Upgrade packages\n");
+ printf("\tinstall <pkgs> Install package(s)\n");
+ printf("\tconfigure <pkgs> Configure unpacked package(s)\n");
+ printf("\tremove <pkgs|regexp> Remove package(s)\n");
diff --git a/package/opkg/patches/011-old-config-location.patch b/package/opkg/patches/011-old-config-location.patch
new file mode 100644
index 000000000..055592686
--- /dev/null
+++ b/package/opkg/patches/011-old-config-location.patch
@@ -0,0 +1,12 @@
+--- a/src/opkg-cl.c
++++ b/src/opkg-cl.c
+@@ -207,6 +207,9 @@ args_parse(int argc, char *argv[])
+ }
+ }
+
++ if(!conf->conf_file && !conf->offline_root)
++ conf->conf_file = xstrdup("/etc/opkg.conf");
++
+ if (parse_err)
+ return parse_err;
+ else
diff --git a/package/opkg/patches/012-strip-trailing-conffiles-whitespace.patch b/package/opkg/patches/012-strip-trailing-conffiles-whitespace.patch
new file mode 100644
index 000000000..a47ae77ce
--- /dev/null
+++ b/package/opkg/patches/012-strip-trailing-conffiles-whitespace.patch
@@ -0,0 +1,23 @@
+--- a/libopkg/opkg_install.c
++++ b/libopkg/opkg_install.c
+@@ -274,6 +274,7 @@ unpack_pkg_control_files(pkg_t *pkg)
+ while (1) {
+ char *cf_name;
+ char *cf_name_in_dest;
++ int i;
+
+ cf_name = file_read_line_alloc(conffiles_file);
+ if (cf_name == NULL) {
+@@ -282,6 +283,12 @@ unpack_pkg_control_files(pkg_t *pkg)
+ if (cf_name[0] == '\0') {
+ continue;
+ }
++ for (i = strlen(cf_name) - 1;
++ (i >= 0) && (cf_name[i] == ' ' || cf_name[i] == '\t');
++ i--
++ ) {
++ cf_name[i] = '\0';
++ }
+
+ /* Prepend dest->root_dir to conffile name.
+ Take pains to avoid multiple slashes. */
diff --git a/package/opkg/patches/014-errors-to-stderr.patch b/package/opkg/patches/014-errors-to-stderr.patch
new file mode 100644
index 000000000..f0a93a871
--- /dev/null
+++ b/package/opkg/patches/014-errors-to-stderr.patch
@@ -0,0 +1,15 @@
+--- a/libopkg/opkg_message.c
++++ b/libopkg/opkg_message.c
+@@ -64,10 +64,10 @@ print_error_list(void)
+ struct errlist *err = error_list_head;
+
+ if (err) {
+- printf("Collected errors:\n");
++ fprintf(stderr, "Collected errors:\n");
+ /* Here we print the errors collected and free the list */
+ while (err != NULL) {
+- printf(" * %s", err->errmsg);
++ fprintf(stderr, " * %s", err->errmsg);
+ err = err->next;
+ }
+ }
diff --git a/package/opkg/patches/020-avoid_getline.patch b/package/opkg/patches/020-avoid_getline.patch
new file mode 100644
index 000000000..8a1a8f627
--- /dev/null
+++ b/package/opkg/patches/020-avoid_getline.patch
@@ -0,0 +1,317 @@
+--- a/libopkg/parse_util.c
++++ b/libopkg/parse_util.c
+@@ -22,6 +22,7 @@
+ #include "libbb/libbb.h"
+
+ #include "parse_util.h"
++#include "pkg_parse.h"
+
+ int
+ is_field(const char *type, const char *line)
+@@ -86,3 +87,84 @@ parse_list(const char *raw, unsigned int
+ *count = line_count;
+ return depends;
+ }
++
++int
++parse_from_stream_nomalloc(parse_line_t parse_line, void *item, FILE *fp, uint mask,
++ char **buf0, size_t buf0len)
++{
++ int ret, lineno;
++ char *buf, *nl;
++ size_t buflen;
++
++ lineno = 1;
++ ret = 0;
++
++ buflen = buf0len;
++ buf = *buf0;
++ buf[0] = '\0';
++
++ while (1) {
++ if (fgets(buf, (int)buflen, fp) == NULL) {
++ if (ferror(fp)) {
++ opkg_perror(ERROR, "fgets");
++ ret = -1;
++ } else if (strlen(*buf0) == buf0len-1) {
++ opkg_msg(ERROR, "Missing new line character"
++ " at end of file!\n");
++ parse_line(item, *buf0, mask);
++ }
++ break;
++ }
++
++ nl = strchr(buf, '\n');
++ if (nl == NULL) {
++ if (strlen(buf) < buflen-1) {
++ /*
++ * Line could be exactly buflen-1 long and
++ * missing a newline, but we won't know until
++ * fgets fails to read more data.
++ */
++ opkg_msg(ERROR, "Missing new line character"
++ " at end of file!\n");
++ parse_line(item, *buf0, mask);
++ break;
++ }
++ if (buf0len >= EXCESSIVE_LINE_LEN) {
++ opkg_msg(ERROR, "Excessively long line at "
++ "%d. Corrupt file?\n",
++ lineno);
++ ret = -1;
++ break;
++ }
++
++ /*
++ * Realloc and point buf past the data already read,
++ * at the NULL terminator inserted by fgets.
++ * |<--------------- buf0len ----------------->|
++ * | |<------- buflen ---->|
++ * |---------------------|---------------------|
++ * buf0 buf
++ */
++ buflen = buf0len +1;
++ buf0len *= 2;
++ *buf0 = xrealloc(*buf0, buf0len);
++ buf = *buf0 + buflen -2;
++
++ continue;
++ }
++
++ *nl = '\0';
++
++ lineno++;
++
++ if (parse_line(item, *buf0, mask))
++ break;
++
++ buf = *buf0;
++ buflen = buf0len;
++ buf[0] = '\0';
++ }
++
++ return ret;
++}
++
+--- a/libopkg/parse_util.h
++++ b/libopkg/parse_util.h
+@@ -22,4 +22,8 @@ int is_field(const char *type, const cha
+ char *parse_simple(const char *type, const char *line);
+ char **parse_list(const char *raw, unsigned int *count, const char sep, int skip_field);
+
++typedef int (*parse_line_t)(void *, const char *, uint);
++int parse_from_stream_nomalloc(parse_line_t parse_line, void *item, FILE *fp, uint mask,
++ char **buf0, size_t buf0len);
++
+ #endif
+--- a/libopkg/pkg_hash.c
++++ b/libopkg/pkg_hash.c
+@@ -23,6 +23,7 @@
+ #include "opkg_message.h"
+ #include "pkg_vec.h"
+ #include "pkg_hash.h"
++#include "parse_util.h"
+ #include "pkg_parse.h"
+ #include "opkg_utils.h"
+ #include "sprintf_alloc.h"
+@@ -119,8 +120,14 @@ pkg_hash_add_from_file(const char *file_
+ pkg->src = src;
+ pkg->dest = dest;
+
+- ret = pkg_parse_from_stream_nomalloc(pkg, fp, 0,
++ ret = parse_from_stream_nomalloc(pkg_parse_line, pkg, fp, 0,
+ &buf, len);
++
++ if (pkg->name == NULL) {
++ /* probably just a blank line */
++ ret = 1;
++ }
++
+ if (ret) {
+ pkg_deinit (pkg);
+ free(pkg);
+--- a/libopkg/pkg_parse.c
++++ b/libopkg/pkg_parse.c
+@@ -104,9 +104,11 @@ get_arch_priority(const char *arch)
+ return 0;
+ }
+
+-static int
+-pkg_parse_line(pkg_t *pkg, const char *line, uint mask)
++int
++pkg_parse_line(void *ptr, const char *line, uint mask)
+ {
++ pkg_t *pkg = (pkg_t *) ptr;
++
+ /* these flags are a bit hackish... */
+ static int reading_conffiles = 0, reading_description = 0;
+ int ret = 0;
+@@ -266,91 +268,6 @@ dont_reset_flags:
+ }
+
+ int
+-pkg_parse_from_stream_nomalloc(pkg_t *pkg, FILE *fp, uint mask,
+- char **buf0, size_t buf0len)
+-{
+- int ret, lineno;
+- char *buf, *nl;
+- size_t buflen;
+-
+- lineno = 1;
+- ret = 0;
+-
+- buflen = buf0len;
+- buf = *buf0;
+- buf[0] = '\0';
+-
+- while (1) {
+- if (fgets(buf, (int)buflen, fp) == NULL) {
+- if (ferror(fp)) {
+- opkg_perror(ERROR, "fgets");
+- ret = -1;
+- } else if (strlen(*buf0) == buf0len-1) {
+- opkg_msg(ERROR, "Missing new line character"
+- " at end of file!\n");
+- pkg_parse_line(pkg, *buf0, mask);
+- }
+- break;
+- }
+-
+- nl = strchr(buf, '\n');
+- if (nl == NULL) {
+- if (strlen(buf) < buflen-1) {
+- /*
+- * Line could be exactly buflen-1 long and
+- * missing a newline, but we won't know until
+- * fgets fails to read more data.
+- */
+- opkg_msg(ERROR, "Missing new line character"
+- " at end of file!\n");
+- pkg_parse_line(pkg, *buf0, mask);
+- break;
+- }
+- if (buf0len >= EXCESSIVE_LINE_LEN) {
+- opkg_msg(ERROR, "Excessively long line at "
+- "%d. Corrupt file?\n",
+- lineno);
+- ret = -1;
+- break;
+- }
+-
+- /*
+- * Realloc and point buf past the data already read,
+- * at the NULL terminator inserted by fgets.
+- * |<--------------- buf0len ----------------->|
+- * | |<------- buflen ---->|
+- * |---------------------|---------------------|
+- * buf0 buf
+- */
+- buflen = buf0len +1;
+- buf0len *= 2;
+- *buf0 = xrealloc(*buf0, buf0len);
+- buf = *buf0 + buflen -2;
+-
+- continue;
+- }
+-
+- *nl = '\0';
+-
+- lineno++;
+-
+- if (pkg_parse_line(pkg, *buf0, mask))
+- break;
+-
+- buf = *buf0;
+- buflen = buf0len;
+- buf[0] = '\0';
+- }
+-
+- if (pkg->name == NULL) {
+- /* probably just a blank line */
+- ret = 1;
+- }
+-
+- return ret;
+-}
+-
+-int
+ pkg_parse_from_stream(pkg_t *pkg, FILE *fp, uint mask)
+ {
+ int ret;
+@@ -358,8 +275,13 @@ pkg_parse_from_stream(pkg_t *pkg, FILE *
+ const size_t len = 4096;
+
+ buf = xmalloc(len);
+- ret = pkg_parse_from_stream_nomalloc(pkg, fp, mask, &buf, len);
++ ret = parse_from_stream_nomalloc(pkg_parse_line, pkg, fp, mask, &buf, len);
+ free(buf);
+
++ if (pkg->name == NULL) {
++ /* probably just a blank line */
++ ret = 1;
++ }
++
+ return ret;
+ }
+--- a/libopkg/pkg_parse.h
++++ b/libopkg/pkg_parse.h
+@@ -18,10 +18,11 @@
+ #ifndef PKG_PARSE_H
+ #define PKG_PARSE_H
+
++#include "pkg.h"
++
+ int parse_version(pkg_t *pkg, const char *raw);
+ int pkg_parse_from_stream(pkg_t *pkg, FILE *fp, uint mask);
+-int pkg_parse_from_stream_nomalloc(pkg_t *pkg, FILE *fp, uint mask,
+- char **buf0, size_t buf0len);
++int pkg_parse_line(void *ptr, const char *line, uint mask);
+
+ #define EXCESSIVE_LINE_LEN (4096 << 8)
+
+--- a/libopkg/release_parse.c
++++ b/libopkg/release_parse.c
+@@ -23,8 +23,10 @@
+ #include "parse_util.h"
+
+ static int
+-release_parse_line(release_t *release, const char *line)
++release_parse_line(void *ptr, const char *line, uint mask)
+ {
++ release_t *release = (release_t *) ptr;
++
+ int ret = 0;
+ unsigned int count = 0;
+ char **list = 0;
+@@ -111,25 +113,14 @@ dont_reset_flags:
+ int
+ release_parse_from_stream(release_t *release, FILE *fp)
+ {
+- int ret = 0;
+- char *buf = NULL;
+- size_t buflen, nread;
+-
+- nread = getline(&buf, &buflen, fp);
+- while ( nread != -1 ) {
+- if (buf[nread-1] == '\n') buf[nread-1] = '\0';
+- if (release_parse_line(release, buf))
+- opkg_msg(DEBUG, "Failed to parse release line for %s:\n\t%s\n",
+- release->name, buf);
+- nread = getline(&buf, &buflen, fp);
+- }
+-
+- if (!feof(fp)) {
+- opkg_perror(ERROR, "Problems reading Release file for %sd\n", release->name);
+- ret = -1;
+- }
++ int ret;
++ char *buf;
++ const size_t len = 4096;
+
++ buf = xmalloc(len);
++ ret = parse_from_stream_nomalloc(release_parse_line, release, fp, 0, &buf, len);
+ free(buf);
++
+ return ret;
+ }
+
diff --git a/package/opkg/patches/030-fix-double-free.patch b/package/opkg/patches/030-fix-double-free.patch
new file mode 100644
index 000000000..312e06c54
--- /dev/null
+++ b/package/opkg/patches/030-fix-double-free.patch
@@ -0,0 +1,10 @@
+--- a/libopkg/opkg_remove.c
++++ b/libopkg/opkg_remove.c
+@@ -138,7 +138,6 @@ opkg_remove_dependent_pkgs(pkg_t *pkg, a
+ for (i = 0; i < dependent_pkgs->len; i++) {
+ err = opkg_remove_pkg(dependent_pkgs->pkgs[i],0);
+ if (err) {
+- pkg_vec_free(dependent_pkgs);
+ break;
+ }
+ }
diff --git a/package/owipcalc/Makefile b/package/owipcalc/Makefile
new file mode 100644
index 000000000..a44131998
--- /dev/null
+++ b/package/owipcalc/Makefile
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2012 Jo-Philipp Wich <jow@openwrt.org>
+#
+# This is free software, licensed under the Apache 2 license.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=owipcalc
+PKG_RELEASE:=3
+
+include $(INCLUDE_DIR)/package.mk
+
+
+define Package/owipcalc
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Simple IPv4/IPv6 address calculator
+ MAINTAINER:=Jo-Philipp Wich <jow@openwrt.org>
+endef
+
+define Package/owipcalc/description
+ The owipcalc utility supports a number of calculations and tests to work
+ with ip-address ranges, this is useful for scripts that e.g. need to
+ partition ipv6-prefixes into small subnets or to calculate address ranges
+ for dhcp pools.
+endef
+
+
+define Build/Prepare
+ $(INSTALL_DIR) $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+ $(TARGET_CC) $(TARGET_CFLAGS) \
+ -o $(PKG_BUILD_DIR)/owipcalc $(PKG_BUILD_DIR)/owipcalc.c
+endef
+
+
+define Package/owipcalc/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/owipcalc $(1)/usr/bin/owipcalc
+endef
+
+$(eval $(call BuildPackage,owipcalc))
diff --git a/package/owipcalc/src/owipcalc.c b/package/owipcalc/src/owipcalc.c
new file mode 100644
index 000000000..d22594bd7
--- /dev/null
+++ b/package/owipcalc/src/owipcalc.c
@@ -0,0 +1,951 @@
+/*
+ * owipcalc - OpenWrt IP Calculator
+ *
+ * Copyright (C) 2012 Jo-Philipp Wich <jow@openwrt.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <string.h>
+#include <unistd.h>
+
+#include <arpa/inet.h>
+
+
+struct cidr {
+ uint8_t family;
+ uint32_t prefix;
+ union {
+ struct in_addr v4;
+ struct in6_addr v6;
+ } addr;
+ union {
+ char v4[sizeof("255.255.255.255/255.255.255.255 ")];
+ char v6[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/128 ")];
+ } buf;
+ struct cidr *next;
+};
+
+struct op {
+ const char *name;
+ const char *desc;
+ struct {
+ bool (*a1)(struct cidr *a);
+ bool (*a2)(struct cidr *a, struct cidr *b);
+ } f4;
+ struct {
+ bool (*a1)(struct cidr *a);
+ bool (*a2)(struct cidr *a, struct cidr *b);
+ } f6;
+};
+
+
+static bool quiet = false;
+static bool printed = false;
+
+static struct cidr *stack = NULL;
+
+#define qprintf(...) \
+ do { \
+ if (!quiet) printf(__VA_ARGS__); \
+ printed = true; \
+ } while(0)
+
+static void cidr_push(struct cidr *a)
+{
+ if (a)
+ {
+ a->next = stack;
+ stack = a;
+ }
+}
+
+static bool cidr_pop(struct cidr *a)
+{
+ struct cidr *old = stack;
+
+ if (old)
+ {
+ stack = stack->next;
+ free(old);
+
+ return true;
+ }
+
+ return false;
+}
+
+static struct cidr * cidr_clone(struct cidr *a)
+{
+ struct cidr *b = malloc(sizeof(*b));
+
+ if (!b)
+ {
+ fprintf(stderr, "out of memory\n");
+ exit(255);
+ }
+
+ memcpy(b, a, sizeof(*b));
+ cidr_push(b);
+
+ return b;
+}
+
+
+static struct cidr * cidr_parse4(const char *s)
+{
+ char *p = NULL, *r;
+ struct in_addr mask;
+ struct cidr *addr = malloc(sizeof(struct cidr));
+
+ if (!addr || (strlen(s) >= sizeof(addr->buf.v4)))
+ goto err;
+
+ snprintf(addr->buf.v4, sizeof(addr->buf.v4), "%s", s);
+
+ addr->family = AF_INET;
+
+ if ((p = strchr(addr->buf.v4, '/')) != NULL)
+ {
+ *p++ = 0;
+
+ if (strchr(p, '.') != NULL)
+ {
+ if (inet_pton(AF_INET, p, &mask) != 1)
+ goto err;
+
+ for (addr->prefix = 0; mask.s_addr; mask.s_addr >>= 1)
+ addr->prefix += (mask.s_addr & 1);
+ }
+ else
+ {
+ addr->prefix = strtoul(p, &r, 10);
+
+ if ((p == r) || (*r != 0) || (addr->prefix > 32))
+ goto err;
+ }
+ }
+ else
+ {
+ addr->prefix = 32;
+ }
+
+ if (p == addr->buf.v4+1)
+ memset(&addr->addr.v4, 0, sizeof(addr->addr.v4));
+ else if (inet_pton(AF_INET, addr->buf.v4, &addr->addr.v4) != 1)
+ goto err;
+
+ return addr;
+
+err:
+ if (addr)
+ free(addr);
+
+ return NULL;
+}
+
+static bool cidr_add4(struct cidr *a, struct cidr *b)
+{
+ uint32_t x = ntohl(a->addr.v4.s_addr);
+ uint32_t y = ntohl(b->addr.v4.s_addr);
+
+ struct cidr *n = cidr_clone(a);
+
+ if ((n->family != AF_INET) || (b->family != AF_INET))
+ return false;
+
+ if ((uint32_t)(x + y) < x)
+ {
+ fprintf(stderr, "overflow during 'add'\n");
+ return false;
+ }
+
+ n->addr.v4.s_addr = htonl(x + y);
+ return true;
+}
+
+static bool cidr_sub4(struct cidr *a, struct cidr *b)
+{
+ uint32_t x = ntohl(a->addr.v4.s_addr);
+ uint32_t y = ntohl(b->addr.v4.s_addr);
+
+ struct cidr *n = cidr_clone(a);
+
+ if ((n->family != AF_INET) || (b->family != AF_INET))
+ return false;
+
+ if ((uint32_t)(x - y) > x)
+ {
+ fprintf(stderr, "underflow during 'sub'\n");
+ return false;
+ }
+
+ n->addr.v4.s_addr = htonl(x - y);
+ return true;
+}
+
+static bool cidr_network4(struct cidr *a)
+{
+ struct cidr *n = cidr_clone(a);
+
+ n->addr.v4.s_addr &= htonl(~((1 << (32 - n->prefix)) - 1));
+ n->prefix = 32;
+
+ return true;
+}
+
+static bool cidr_broadcast4(struct cidr *a)
+{
+ struct cidr *n = cidr_clone(a);
+
+ n->addr.v4.s_addr |= htonl(((1 << (32 - n->prefix)) - 1));
+ n->prefix = 32;
+
+ return true;
+}
+
+static bool cidr_contains4(struct cidr *a, struct cidr *b)
+{
+ uint32_t net1 = a->addr.v4.s_addr & htonl(~((1 << (32 - a->prefix)) - 1));
+ uint32_t net2 = b->addr.v4.s_addr & htonl(~((1 << (32 - a->prefix)) - 1));
+
+ if (printed)
+ qprintf(" ");
+
+ if ((b->prefix >= a->prefix) && (net1 == net2))
+ {
+ qprintf("1");
+ return true;
+ }
+ else
+ {
+ qprintf("0");
+ return false;
+ }
+}
+
+static bool cidr_netmask4(struct cidr *a)
+{
+ struct cidr *n = cidr_clone(a);
+
+ n->addr.v4.s_addr = htonl(~((1 << (32 - n->prefix)) - 1));
+ n->prefix = 32;
+
+ return true;
+}
+
+static bool cidr_private4(struct cidr *a)
+{
+ uint32_t x = ntohl(a->addr.v4.s_addr);
+
+ if (printed)
+ qprintf(" ");
+
+ if (((x >= 0x0A000000) && (x <= 0x0AFFFFFF)) ||
+ ((x >= 0xAC100000) && (x <= 0xAC1FFFFF)) ||
+ ((x >= 0xC0A80000) && (x <= 0xC0A8FFFF)))
+ {
+ qprintf("1");
+ return true;
+ }
+ else
+ {
+ qprintf("0");
+ return false;
+ }
+}
+
+static bool cidr_linklocal4(struct cidr *a)
+{
+ uint32_t x = ntohl(a->addr.v4.s_addr);
+
+ if (printed)
+ qprintf(" ");
+
+ if ((x >= 0xA9FE0000) && (x <= 0xA9FEFFFF))
+ {
+ qprintf("1");
+ return true;
+ }
+ else
+ {
+ qprintf("0");
+ return false;
+ }
+}
+
+static bool cidr_prev4(struct cidr *a, struct cidr *b)
+{
+ struct cidr *n = cidr_clone(a);
+
+ n->prefix = b->prefix;
+ n->addr.v4.s_addr -= htonl(1 << (32 - b->prefix));
+
+ return true;
+}
+
+static bool cidr_next4(struct cidr *a, struct cidr *b)
+{
+ struct cidr *n = cidr_clone(a);
+
+ n->prefix = b->prefix;
+ n->addr.v4.s_addr += htonl(1 << (32 - b->prefix));
+
+ return true;
+}
+
+static bool cidr_6to4(struct cidr *a)
+{
+ struct cidr *n = cidr_clone(a);
+ uint32_t x = a->addr.v4.s_addr;
+
+ memset(&n->addr.v6.s6_addr, 0, sizeof(n->addr.v6.s6_addr));
+
+ n->family = AF_INET6;
+ n->prefix = 48;
+
+ n->addr.v6.s6_addr[0] = 0x20;
+ n->addr.v6.s6_addr[1] = 0x02;
+ n->addr.v6.s6_addr[2] = (x >> 24);
+ n->addr.v6.s6_addr[3] = (x >> 16) & 0xFF;
+ n->addr.v6.s6_addr[4] = (x >> 8) & 0xFF;
+ n->addr.v6.s6_addr[5] = x & 0xFF;
+
+ return true;
+}
+
+static bool cidr_print4(struct cidr *a)
+{
+ char *p;
+
+ if (!a || (a->family != AF_INET))
+ return false;
+
+ if (!(p = (char *)inet_ntop(AF_INET, &a->addr.v4, a->buf.v4, sizeof(a->buf.v4))))
+ return false;
+
+ if (printed)
+ qprintf(" ");
+
+ qprintf("%s", p);
+
+ if (a->prefix < 32)
+ qprintf("/%u", a->prefix);
+
+ cidr_pop(a);
+
+ return true;
+}
+
+
+static struct cidr * cidr_parse6(const char *s)
+{
+ char *p = NULL, *r;
+ struct cidr *addr = malloc(sizeof(struct cidr));
+
+ if (!addr || (strlen(s) >= sizeof(addr->buf.v6)))
+ goto err;
+
+ snprintf(addr->buf.v4, sizeof(addr->buf.v6), "%s", s);
+
+ addr->family = AF_INET6;
+
+ if ((p = strchr(addr->buf.v4, '/')) != NULL)
+ {
+ *p++ = 0;
+
+ addr->prefix = strtoul(p, &r, 10);
+
+ if ((p == r) || (*r != 0) || (addr->prefix > 128))
+ goto err;
+ }
+ else
+ {
+ addr->prefix = 128;
+ }
+
+ if (p == addr->buf.v4+1)
+ memset(&addr->addr.v6, 0, sizeof(addr->addr.v6));
+ else if (inet_pton(AF_INET6, addr->buf.v4, &addr->addr.v6) != 1)
+ goto err;
+
+ return addr;
+
+err:
+ if (addr)
+ free(addr);
+
+ return NULL;
+}
+
+static bool cidr_add6(struct cidr *a, struct cidr *b)
+{
+ uint8_t idx = 15, carry = 0, overflow = 0;
+
+ struct cidr *n = cidr_clone(a);
+ struct in6_addr *x = &n->addr.v6;
+ struct in6_addr *y = &b->addr.v6;
+
+ if ((a->family != AF_INET6) || (b->family != AF_INET6))
+ return false;
+
+ do {
+ overflow = !!((x->s6_addr[idx] + y->s6_addr[idx] + carry) >= 256);
+ x->s6_addr[idx] += y->s6_addr[idx] + carry;
+ carry = overflow;
+ }
+ while (idx-- > 0);
+
+ if (carry)
+ {
+ fprintf(stderr, "overflow during 'add'\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool cidr_sub6(struct cidr *a, struct cidr *b)
+{
+ uint8_t idx = 15, carry = 0, underflow = 0;
+
+ struct cidr *n = cidr_clone(a);
+ struct in6_addr *x = &n->addr.v6;
+ struct in6_addr *y = &b->addr.v6;
+
+ if ((n->family != AF_INET6) || (b->family != AF_INET6))
+ return false;
+
+ do {
+ underflow = !!((x->s6_addr[idx] - y->s6_addr[idx] - carry) < 0);
+ x->s6_addr[idx] -= y->s6_addr[idx] + carry;
+ carry = underflow;
+ }
+ while (idx-- > 0);
+
+ if (carry)
+ {
+ fprintf(stderr, "underflow during 'sub'\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool cidr_prev6(struct cidr *a, struct cidr *b)
+{
+ uint8_t idx, carry = 1, underflow = 0;
+ struct cidr *n = cidr_clone(a);
+ struct in6_addr *x = &n->addr.v6;
+
+ if (b->prefix == 0)
+ {
+ fprintf(stderr, "underflow during 'prev'\n");
+ return false;
+ }
+
+ idx = (b->prefix - 1) / 8;
+
+ do {
+ underflow = !!((x->s6_addr[idx] - carry) < 0);
+ x->s6_addr[idx] -= carry;
+ carry = underflow;
+ }
+ while (idx-- > 0);
+
+ if (carry)
+ {
+ fprintf(stderr, "underflow during 'prev'\n");
+ return false;
+ }
+
+ n->prefix = b->prefix;
+
+ return true;
+}
+
+static bool cidr_next6(struct cidr *a, struct cidr *b)
+{
+ uint8_t idx, carry = 1, overflow = 0;
+ struct cidr *n = cidr_clone(a);
+ struct in6_addr *x = &n->addr.v6;
+
+ if (b->prefix == 0)
+ {
+ fprintf(stderr, "overflow during 'next'\n");
+ return false;
+ }
+
+ idx = (b->prefix - 1) / 8;
+
+ do {
+ overflow = !!((x->s6_addr[idx] + carry) >= 256);
+ x->s6_addr[idx] += carry;
+ carry = overflow;
+ }
+ while (idx-- > 0);
+
+ if (carry)
+ {
+ fprintf(stderr, "overflow during 'next'\n");
+ return false;
+ }
+
+ n->prefix = b->prefix;
+
+ return true;
+}
+
+static bool cidr_network6(struct cidr *a)
+{
+ uint8_t i;
+ struct cidr *n = cidr_clone(a);
+
+ for (i = 0; i < (128 - n->prefix) / 8; i++)
+ n->addr.v6.s6_addr[15-i] = 0;
+
+ if ((128 - n->prefix) % 8)
+ n->addr.v6.s6_addr[15-i] &= ~((1 << ((128 - n->prefix) % 8)) - 1);
+
+ return true;
+}
+
+static bool cidr_contains6(struct cidr *a, struct cidr *b)
+{
+ struct cidr *n = cidr_clone(a);
+ struct in6_addr *x = &n->addr.v6;
+ struct in6_addr *y = &b->addr.v6;
+ uint8_t i = (128 - n->prefix) / 8;
+ uint8_t m = ~((1 << ((128 - n->prefix) % 8)) - 1);
+ uint8_t net1 = x->s6_addr[15-i] & m;
+ uint8_t net2 = y->s6_addr[15-i] & m;
+
+ if (printed)
+ qprintf(" ");
+
+ if ((b->prefix >= n->prefix) && (net1 == net2) &&
+ ((i == 15) || !memcmp(&x->s6_addr, &y->s6_addr, 15-i)))
+ {
+ qprintf("1");
+ return true;
+ }
+ else
+ {
+ qprintf("0");
+ return false;
+ }
+}
+
+static bool cidr_linklocal6(struct cidr *a)
+{
+ if (printed)
+ qprintf(" ");
+
+ if ((a->addr.v6.s6_addr[0] == 0xFE) &&
+ (a->addr.v6.s6_addr[1] >= 0x80) &&
+ (a->addr.v6.s6_addr[1] <= 0xBF))
+ {
+ qprintf("1");
+ return true;
+ }
+ else
+ {
+ qprintf("0");
+ return false;
+ }
+}
+
+static bool cidr_ula6(struct cidr *a)
+{
+ if (printed)
+ qprintf(" ");
+
+ if ((a->addr.v6.s6_addr[0] >= 0xFC) &&
+ (a->addr.v6.s6_addr[0] <= 0xFD))
+ {
+ qprintf("1");
+ return true;
+ }
+ else
+ {
+ qprintf("0");
+ return false;
+ }
+}
+
+static bool cidr_print6(struct cidr *a)
+{
+ char *p;
+
+ if (!a || (a->family != AF_INET6))
+ return NULL;
+
+ if (!(p = (char *)inet_ntop(AF_INET6, &a->addr.v6, a->buf.v6, sizeof(a->buf.v6))))
+ return false;
+
+ if (printed)
+ qprintf(" ");
+
+ qprintf("%s", p);
+
+ if (a->prefix < 128)
+ qprintf("/%u", a->prefix);
+
+ cidr_pop(a);
+
+ return true;
+}
+
+
+static struct cidr * cidr_parse(const char *op, const char *s, int af_hint)
+{
+ char *r;
+ struct cidr *a;
+
+ uint8_t i;
+ uint32_t sum = strtoul(s, &r, 0);
+
+ if ((r > s) && (*r == 0))
+ {
+ a = malloc(sizeof(struct cidr));
+
+ if (!a)
+ return NULL;
+
+ if (af_hint == AF_INET)
+ {
+ a->family = AF_INET;
+ a->prefix = sum;
+ a->addr.v4.s_addr = htonl(sum);
+ }
+ else
+ {
+ a->family = AF_INET6;
+ a->prefix = sum;
+
+ for (i = 0; i <= 15; i++)
+ {
+ a->addr.v6.s6_addr[15-i] = sum % 256;
+ sum >>= 8;
+ }
+ }
+
+ return a;
+ }
+
+ if (strchr(s, ':'))
+ a = cidr_parse6(s);
+ else
+ a = cidr_parse4(s);
+
+ if (!a)
+ return NULL;
+
+ if (a->family != af_hint)
+ {
+ fprintf(stderr, "attempt to '%s' %s with %s address\n",
+ op,
+ (af_hint == AF_INET) ? "ipv4" : "ipv6",
+ (af_hint != AF_INET) ? "ipv4" : "ipv6");
+ exit(4);
+ }
+
+ return a;
+}
+
+static bool cidr_howmany(struct cidr *a, struct cidr *b)
+{
+ if (printed)
+ qprintf(" ");
+
+ if (b->prefix < a->prefix)
+ qprintf("0");
+ else
+ qprintf("%u", 1 << (b->prefix - a->prefix));
+
+ return true;
+}
+
+static bool cidr_prefix(struct cidr *a, struct cidr *b)
+{
+ a->prefix = b->prefix;
+ return true;
+}
+
+static bool cidr_quiet(struct cidr *a)
+{
+ quiet = true;
+ return true;
+}
+
+
+struct op ops[] = {
+ { .name = "add",
+ .desc = "Add argument to base address",
+ .f4.a2 = cidr_add4,
+ .f6.a2 = cidr_add6 },
+
+ { .name = "sub",
+ .desc = "Substract argument from base address",
+ .f4.a2 = cidr_sub4,
+ .f6.a2 = cidr_sub6 },
+
+ { .name = "next",
+ .desc = "Advance base address to next prefix of given size",
+ .f4.a2 = cidr_next4,
+ .f6.a2 = cidr_next6 },
+
+ { .name = "prev",
+ .desc = "Lower base address to previous prefix of give size",
+ .f4.a2 = cidr_prev4,
+ .f6.a2 = cidr_prev6 },
+
+ { .name = "network",
+ .desc = "Turn base address into network address",
+ .f4.a1 = cidr_network4,
+ .f6.a1 = cidr_network6 },
+
+ { .name = "broadcast",
+ .desc = "Turn base address into broadcast address",
+ .f4.a1 = cidr_broadcast4 },
+
+ { .name = "prefix",
+ .desc = "Set the prefix of base address to argument",
+ .f4.a2 = cidr_prefix,
+ .f6.a2 = cidr_prefix },
+
+ { .name = "netmask",
+ .desc = "Calculate netmask of base address",
+ .f4.a1 = cidr_netmask4 },
+
+ { .name = "6to4",
+ .desc = "Calculate 6to4 prefix of given ipv4-address",
+ .f4.a1 = cidr_6to4 },
+
+ { .name = "howmany",
+ .desc = "Print amount of righ-hand prefixes that fit into base address",
+ .f4.a2 = cidr_howmany,
+ .f6.a2 = cidr_howmany },
+
+ { .name = "contains",
+ .desc = "Print '1' if argument fits into base address or '0' if not",
+ .f4.a2 = cidr_contains4,
+ .f6.a2 = cidr_contains6 },
+
+ { .name = "private",
+ .desc = "Print '1' if base address is in RFC1918 private space or '0' "
+ "if not",
+ .f4.a1 = cidr_private4 },
+
+ { .name = "linklocal",
+ .desc = "Print '1' if base address is in 169.254.0.0/16 or FE80::/10 "
+ "link local space or '0' if not",
+ .f4.a1 = cidr_linklocal4,
+ .f6.a1 = cidr_linklocal6 },
+
+ { .name = "ula",
+ .desc = "Print '1' if base address is in FC00::/7 unique local address "
+ "(ULA) space or '0' if not",
+ .f6.a1 = cidr_ula6 },
+
+ { .name = "quiet",
+ .desc = "Suppress output, useful for test operation where the result can "
+ "be inferred from the exit code",
+ .f4.a1 = cidr_quiet,
+ .f6.a1 = cidr_quiet },
+
+ { .name = "pop",
+ .desc = "Pop intermediate result from stack",
+ .f4.a1 = cidr_pop,
+ .f6.a1 = cidr_pop },
+
+ { .name = "print",
+ .desc = "Print intermediate result and pop it from stack, invoked "
+ "implicitely at the end of calculation if no intermediate prints "
+ "happened",
+ .f4.a1 = cidr_print4,
+ .f6.a1 = cidr_print6 },
+};
+
+static void usage(const char *prog)
+{
+ int i;
+
+ fprintf(stderr,
+ "\n"
+ "Usage:\n\n"
+ " %s {base address} operation [argument] "
+ "[operation [argument] ...]\n\n"
+ "Operations:\n\n",
+ prog);
+
+ for (i = 0; i < sizeof(ops) / sizeof(ops[0]); i++)
+ {
+ if (ops[i].f4.a2 || ops[i].f6.a2)
+ {
+ fprintf(stderr, " %s %s\n",
+ ops[i].name,
+ (ops[i].f4.a2 && ops[i].f6.a2) ? "{ipv4/ipv6/amount}" :
+ (ops[i].f6.a2 ? "{ipv6/amount}" : "{ipv4/amount}"));
+ }
+ else
+ {
+ fprintf(stderr, " %s\n", ops[i].name);
+ }
+
+ fprintf(stderr, " %s.\n", ops[i].desc);
+
+ if ((ops[i].f4.a1 && ops[i].f6.a1) || (ops[i].f4.a2 && ops[i].f6.a2))
+ fprintf(stderr, " Applicable to ipv4- and ipv6-addresses.\n\n");
+ else if (ops[i].f6.a2 || ops[i].f6.a1)
+ fprintf(stderr, " Only applicable to ipv6-addresses.\n\n");
+ else
+ fprintf(stderr, " Only applicable to ipv4-addresses.\n\n");
+ }
+
+ fprintf(stderr,
+ "Examples:\n\n"
+ " Calculate a DHCP range:\n\n"
+ " $ %s 192.168.1.1/255.255.255.0 network add 100 print add 150 print\n"
+ " 192.168.1.100\n"
+ " 192.168.1.250\n\n"
+ " Count number of prefixes:\n\n"
+ " $ %s 2001:0DB8:FDEF::/48 howmany ::/64\n"
+ " 65536\n\n",
+ prog, prog);
+
+ exit(1);
+}
+
+static bool runop(char ***arg, int *status)
+{
+ int i;
+ char *arg1 = **arg;
+ char *arg2 = *(*arg+1);
+ struct cidr *a = stack;
+ struct cidr *b = NULL;
+
+ if (!arg1)
+ return false;
+
+ for (i = 0; i < sizeof(ops) / sizeof(ops[0]); i++)
+ {
+ if (!strcmp(ops[i].name, arg1))
+ {
+ if (ops[i].f4.a2 || ops[i].f6.a2)
+ {
+ if (!arg2)
+ {
+ fprintf(stderr, "'%s' requires an argument\n",
+ ops[i].name);
+
+ *status = 2;
+ return false;
+ }
+
+ b = cidr_parse(ops[i].name, arg2, a->family);
+
+ if (!b)
+ {
+ fprintf(stderr, "invalid address argument for '%s'\n",
+ ops[i].name);
+
+ *status = 3;
+ return false;
+ }
+
+ *arg += 2;
+
+ if (((a->family == AF_INET) && !ops[i].f4.a2) ||
+ ((a->family == AF_INET6) && !ops[i].f6.a2))
+ {
+ fprintf(stderr, "'%s' not supported for %s addresses\n",
+ ops[i].name,
+ (a->family == AF_INET) ? "ipv4" : "ipv6");
+
+ *status = 5;
+ return false;
+ }
+
+ *status = !((a->family == AF_INET) ? ops[i].f4.a2(a, b)
+ : ops[i].f6.a2(a, b));
+
+ return true;
+ }
+ else
+ {
+ *arg += 1;
+
+ if (((a->family == AF_INET) && !ops[i].f4.a1) ||
+ ((a->family == AF_INET6) && !ops[i].f6.a1))
+ {
+ fprintf(stderr, "'%s' not supported for %s addresses\n",
+ ops[i].name,
+ (a->family == AF_INET) ? "ipv4" : "ipv6");
+
+ *status = 5;
+ return false;
+ }
+
+ *status = !((a->family == AF_INET) ? ops[i].f4.a1(a)
+ : ops[i].f6.a1(a));
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+int main(int argc, char **argv)
+{
+ int status = 0;
+ char **arg = argv+2;
+ struct cidr *a;
+
+ if (argc < 3)
+ usage(argv[0]);
+
+ a = strchr(argv[1], ':') ? cidr_parse6(argv[1]) : cidr_parse4(argv[1]);
+
+ if (!a)
+ usage(argv[0]);
+
+ cidr_push(a);
+
+ while (runop(&arg, &status));
+
+ if (*arg)
+ {
+ fprintf(stderr, "unknown operation '%s'\n", *arg);
+ exit(6);
+ }
+
+ if (!printed && (status < 2))
+ {
+ if (stack->family == AF_INET)
+ cidr_print4(stack);
+ else
+ cidr_print6(stack);
+ }
+
+ qprintf("\n");
+
+ exit(status);
+}
diff --git a/package/owsip/Makefile b/package/owsip/Makefile
new file mode 100644
index 000000000..4dcf1efdf
--- /dev/null
+++ b/package/owsip/Makefile
@@ -0,0 +1,73 @@
+#
+# Copyright (C) 2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+OWSIP_VERSION=2012-02-14
+OWSIP_RELEASE=1
+
+PKG_NAME:=owsip
+PKG_VERSION:=$(OWSIP_VERSION)$(if $(OWSIP_RELEASE),.$(OWSIP_RELEASE))
+PKG_RELEASE:=1
+PKG_REV:=da53a53db28b47ca1714ffba72d0df5bea357706
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=git://nbd.name/owsip.git
+PKG_SOURCE_SUBDIR:=owsip-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=$(PKG_REV)
+PKG_SOURCE_PROTO:=git
+PKG_MIRROR_MD5SUM:=74b0ab930321c4f85f220ff3852e210a
+
+include $(INCLUDE_DIR)/ltqtapi.mk
+include $(INCLUDE_DIR)/package.mk
+
+define Package/owsip-template
+ SUBMENU:=Telephony
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=owsip using $(2)
+ VARIANT:=$(1)
+ DEPENDS:=+librt +libuci +libubox +pjsip-$(1) $(3)
+endef
+
+Package/owsip-oss=$(call Package/owsip-template,oss,OSS,BROKEN)
+Package/owsip-ltq-tapi=$(call Package/owsip-template,ltq-tapi,Lantiq VMMC,$(LTQ_TAPI_DEPENDS) +kmod-ltq-kpi2udp)
+
+define Package/owsip-$(BUILD_VARIANT)/description
+ OpenWrt sip daemon - $(BUILD_VARIANT)
+endef
+
+USE_LOCAL=$(shell ls ./src/ 2>/dev/null >/dev/null && echo 1)
+ifneq ($(USE_LOCAL),)
+define Build/Prepare
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+endif
+
+EXTRA_CFLAGS=-I$(STAGING_DIR)/usr/include -I$(STAGING_DIR)/include \
+ -I$(STAGING_DIR)/usr/pjsip-$(BUILD_VARIANT)/include
+EXTRA_LDFLAGS=-L$(STAGING_DIR)/usr/lib -L$(STAGING_DIR)/usr/pjsip-$(BUILD_VARIANT)/lib
+
+define Build/Compile
+ PKG_CONFIG_PATH=$(STAGING_DIR)/usr/pjsip-$(BUILD_VARIANT)/lib/pkgconfig \
+ BACKEND=$(BUILD_VARIANT) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS="$(EXTRA_LDFLAGS)" $(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS)
+endef
+
+define Package/owsip-$(BUILD_VARIANT)/conffiles
+/etc/config/telephony.conf
+endef
+
+define Package/owsip-$(BUILD_VARIANT)/install
+ $(INSTALL_DIR) $(1)/usr/bin $(1)/etc/init.d $(1)/etc/config $(1)/etc/uci-defaults
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/owsip_ua $(1)/usr/bin
+ $(INSTALL_BIN) ./files/telephony.init $(1)/etc/init.d/telephony
+ $(INSTALL_DATA) ./files/telephony.conf $(1)/etc/config/telephony
+ $(INSTALL_DATA) ./files/telephony.defaults $(1)/etc/uci-defaults/telephony
+endef
+
+$(eval $(call BuildPackage,owsip-oss))
+$(eval $(call BuildPackage,owsip-ltq-tapi))
diff --git a/package/owsip/files/telephony.conf b/package/owsip/files/telephony.conf
new file mode 100644
index 000000000..7cc1e9f0f
--- /dev/null
+++ b/package/owsip/files/telephony.conf
@@ -0,0 +1,32 @@
+config general general
+ option name owsip
+ option backend ltq_tapi
+ option ossdev 0
+ option log_level 3
+ option interface nas0
+ option local_port 5060
+ option rtp_port 4000
+ option locale germany
+
+config stun stun
+ option host stun.myrealm.com
+ option port 3478
+
+config account example1
+ option realm myrealm1.com
+ option username myuser1
+ option password mypass1
+ option disabled 1
+
+config account example2
+ option realm myrealm2.com
+ option username myuser2
+ option password mypass2
+ option disabled 1
+
+config contact
+ option desc "example contact description"
+ option code "example"
+ option dial "0123456789"
+ option type realm
+
diff --git a/package/owsip/files/telephony.defaults b/package/owsip/files/telephony.defaults
new file mode 100755
index 000000000..bec2878a0
--- /dev/null
+++ b/package/owsip/files/telephony.defaults
@@ -0,0 +1,55 @@
+#!/bin/sh
+#
+# Copyright (C) 2011 OpenWrt.org
+# based on ar71xx
+#
+
+COMMIT_TELEPHONY=0
+
+set_relay() {
+ local cfg="relay_$1"
+ local gpio=$1
+ local val=$2
+
+ uci -q get telephony.$cfg && return 0
+
+ uci batch <<EOF
+set telephony.$cfg='relay'
+set telephony.$cfg.gpio='$gpio'
+set telephony.$cfg.value='$val'
+EOF
+ COMMIT_TELEPHONY=1
+}
+
+set_port() {
+ local cfg="port$1"
+ local id=$1
+ local led=$2
+
+ uci -q get telephony.$cfg && return 0
+
+ uci batch <<EOF
+set telephony.$cfg='port'
+set telephony.$cfg.id='$id'
+set telephony.$cfg.led='$led'
+set telephony.$cfg.noring='0'
+set telephony.$cfg.nodial='0'
+EOF
+ COMMIT_TELEPHONY=1
+}
+
+. /lib/lantiq.sh
+
+board=$(lantiq_board_name)
+
+case "$board" in
+ARV7525PW)
+ set_relay 31 1
+ set_port 0 "soc:green:fxs1"
+ #set_port 1 "soc:green:fxs2"
+ ;;
+esac
+
+[ "$COMMIT_TELEPHONY" == "1" ] && uci commit telephony
+
+exit 0
diff --git a/package/owsip/files/telephony.init b/package/owsip/files/telephony.init
new file mode 100644
index 000000000..90909e625
--- /dev/null
+++ b/package/owsip/files/telephony.init
@@ -0,0 +1,33 @@
+#!/bin/sh /etc/rc.common
+START=80
+
+SERVICE_WRITE_PID=1
+SERVICE_DAEMONIZE=1
+SERVICE_PID_FILE=/var/run/owsip.pid
+
+. /lib/functions.sh
+
+relay_set () {
+ local cfg="$1"
+ local gpio value
+
+ config_get gpio "$cfg" gpio
+ config_get value "$cfg" value
+ [ -n "gpio" ] || return 0
+ [ ! -f "/sys/class/gpio/gpio$gpio/direction" ] &&
+ echo "$gpio" > /sys/class/gpio/export
+ [ -f "/sys/class/gpio/gpio$gpio/direction" ] && {
+ echo "out" > /sys/class/gpio/gpio$gpio/direction
+ echo "$value" > /sys/class/gpio/gpio$gpio/value
+ }
+}
+
+start() {
+ config_load telephony
+ config_foreach relay_set relay
+ service_start /usr/bin/owsip_ua
+}
+
+stop() {
+ service_stop /usr/bin/owsip_ua
+}
diff --git a/package/pjsip/Makefile b/package/pjsip/Makefile
new file mode 100644
index 000000000..d2c6f6b88
--- /dev/null
+++ b/package/pjsip/Makefile
@@ -0,0 +1,101 @@
+#
+# Copyright (C) 2010-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=pjsip
+PKG_VERSION:=1.14.2
+PKG_RELEASE:=1
+
+PKG_SOURCE:=pjproject-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://www.pjsip.org/release/$(PKG_VERSION)/
+PKG_MD5SUM:=05428502384c16e7abd85f047e6e2f6c
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/pjproject-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/ltqtapi.mk
+PKG_BUILD_DEPENDS:=$(LTQ_TAPI_BUILD_DEPENDS)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/pjsip-template
+ SECTION:=lib
+ CATEGORY:=Libraries
+ URL:=http://www.pjsip.org/
+ MAINTAINER:=John Crispin <blogic@openwrt.org>
+ TITLE:=pjsip-$(1)
+ VARIANT:=$(1)
+ DEPENDS:=+libuuid $(2)
+endef
+
+CONFIGURE_PREFIX=/usr/pjsip-$(BUILD_VARIANT)
+
+ifeq ($(BUILD_VARIANT),oss)
+CONFIGURE_ARGS += \
+ --disable-floating-point \
+ --enable-g711-codec \
+ --disable-l16-codec \
+ --disable-g722-codec \
+ --disable-g7221-codec \
+ --disable-gsm-codec \
+ --disable-ilbc-coder \
+ --disable-libsamplerate \
+ --disable-ipp \
+ --disable-ssl \
+ --enable-oss \
+ --enable-sound
+endif
+
+ifeq ($(BUILD_VARIANT),ltq-tapi)
+CONFIGURE_ARGS += \
+ --disable-floating-point \
+ --enable-g711-codec \
+ --disable-l16-codec \
+ --disable-g722-codec \
+ --disable-g7221-codec \
+ --disable-ilbc-coder \
+ --disable-gsm-codec \
+ --disable-libsamplerate \
+ --disable-ipp \
+ --disable-ssl \
+ --enable-sound \
+ --enable-ltq-tapi
+EXTRA_CFLAGS:=-I$(STAGING_DIR)/usr/include/drv_tapi -I$(STAGING_DIR)/usr/include/drv_vmmc
+endif
+
+Package/pjsip-oss=$(call Package/pjsip-template,oss,BROKEN)
+Package/pjsip-ltq-tapi=$(call Package/pjsip-template,ltq-tapi,$(LTQ_TAPI_DEPENDS))
+
+USE_LOCAL=$(shell ls ./src/ 2>/dev/null >/dev/null && echo 1)
+ifneq ($(USE_LOCAL),)
+define Build/Prepare
+ $(CP) ./src/* $(PKG_BUILD_DIR)
+endef
+endif
+
+define Build/Configure
+ (cd $(PKG_BUILD_DIR); autoconf aconfigure.ac > aconfigure)
+ $(call Build/Configure/Default)
+endef
+
+define Build/Compile
+ +CFLAGS="$(TARGET_CFLAGS) $(EXTRA_CFLAGS) $(TARGET_CPPFLAGS) $(EXTRA_CPPFLAGS)" \
+ CXXFLAGS="$(TARGET_CFLAGS) $(EXTRA_CFLAGS) $(TARGET_CPPFLAGS) $(EXTRA_CPPFLAGS)" \
+ LDFLAGS="$(TARGET_LDFLAGS) -lc $(LIBGCC_S) -lm" \
+ $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/$(MAKE_PATH)
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr
+ $(CP) $(PKG_INSTALL_DIR)/usr/pjsip-$(BUILD_VARIANT) $(1)/usr
+endef
+
+$(eval $(call BuildPackage,pjsip-oss))
+$(eval $(call BuildPackage,pjsip-ltq-tapi))
diff --git a/package/pjsip/patches/0001-configure-fixup.patch b/package/pjsip/patches/0001-configure-fixup.patch
new file mode 100644
index 000000000..5fcf911c3
--- /dev/null
+++ b/package/pjsip/patches/0001-configure-fixup.patch
@@ -0,0 +1,78 @@
+Index: pjproject-1.14.2/aconfigure.ac
+===================================================================
+--- pjproject-1.14.2.orig/aconfigure.ac 2012-04-27 03:22:15.000000000 +0200
++++ pjproject-1.14.2/aconfigure.ac 2012-08-13 14:42:33.204641678 +0200
+@@ -48,9 +48,8 @@
+ CROSS_COMPILE=`echo ${CC} | sed 's/gcc//'`
+ fi
+
+-if test "$AR" = ""; then AR="${CROSS_COMPILE}ar rv"; fi
++AR="${AR} rv"
+ AC_SUBST(AR)
+-if test "$LD" = ""; then LD="$CC"; fi
+ AC_SUBST(LD)
+ if test "$LDOUT" = ""; then LDOUT="-o "; fi
+ AC_SUBST(LDOUT)
+@@ -584,13 +583,7 @@
+ ;;
+ *)
+ dnl # Check if ALSA is available
+- ac_pjmedia_snd=pa_unix
+- AC_CHECK_HEADER(alsa/version.h,
+- [AC_SUBST(ac_pa_use_alsa,1)
+- LIBS="$LIBS -lasound"
+- ],
+- [AC_SUBST(ac_pa_use_alsa,0)])
+- AC_MSG_RESULT([Checking sound device backend... unix])
++ AC_SUBST(ac_pa_use_alsa,0)
+
+ dnl # Check if OSS is disabled
+ AC_SUBST(ac_pa_use_oss,1)
+@@ -617,6 +610,15 @@
+ fi]
+ )
+
++AC_ARG_ENABLE(ltq_tapi,
++ AC_HELP_STRING([--enable-ltq-tapi],
++ [PJMEDIA will use ltq tapi backend]),
++ [if test "$enable_ltq_tapi" = "yes"; then
++ [ac_pjmedia_snd=ltqtapi]
++ AC_MSG_RESULT([Checking if external sound is set... yes])
++ fi]
++ )
++
+ dnl # Include resampling small filter
+ AC_SUBST(ac_no_small_filter)
+ AC_ARG_ENABLE(small-filter,
+@@ -737,14 +739,6 @@
+ AC_MSG_RESULT([Checking if iLBC codec is disabled...no]))
+
+ dnl # Include libsamplerate
+-AC_ARG_ENABLE(libsamplerate,
+- AC_HELP_STRING([--enable-libsamplerate],
+- [Link with libsamplerate when available. Note that PJMEDIA_RESAMPLE_IMP must also be configured]),
+- [ AC_CHECK_LIB(samplerate,src_new) ],
+- AC_MSG_RESULT([Skipping libsamplerate detection])
+- )
+-
+-dnl # Include libsamplerate
+ AC_SUBST(ac_resample_dll)
+ AC_ARG_ENABLE(resample_dll,
+ AC_HELP_STRING([--enable-resample-dll],
+Index: pjproject-1.14.2/pjmedia/build/os-auto.mak.in
+===================================================================
+--- pjproject-1.14.2.orig/pjmedia/build/os-auto.mak.in 2011-10-14 06:15:15.000000000 +0200
++++ pjproject-1.14.2/pjmedia/build/os-auto.mak.in 2012-08-13 14:40:47.680637171 +0200
+@@ -125,4 +125,11 @@
+ export CFLAGS += -DPJMEDIA_AUDIO_DEV_HAS_PORTAUDIO=0 -DPJMEDIA_AUDIO_DEV_HAS_WMME=0
+ endif
+
+-
++#
++# Lantiq tapi backend
++#
++ifeq ($(AC_PJMEDIA_SND),ltqtapi)
++export CFLAGS += -DPJMEDIA_AUDIO_DEV_HAS_PORTAUDIO=0 -DPJMEDIA_AUDIO_DEV_HAS_WMME=0
++export PJMEDIA_AUDIODEV_OBJS += tapi_dev.o
++export CFLAGS += -DPJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE=1
++endif
diff --git a/package/pjsip/patches/0002-register-tapi.patch b/package/pjsip/patches/0002-register-tapi.patch
new file mode 100644
index 000000000..4363bc7ff
--- /dev/null
+++ b/package/pjsip/patches/0002-register-tapi.patch
@@ -0,0 +1,1333 @@
+--- a/pjmedia/src/pjmedia-audiodev/audiodev.c
++++ b/pjmedia/src/pjmedia-audiodev/audiodev.c
+@@ -98,6 +98,10 @@ pjmedia_aud_dev_factory* pjmedia_symb_md
+ pjmedia_aud_dev_factory* pjmedia_null_audio_factory(pj_pool_factory *pf);
+ #endif
+
++#if PJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE
++pjmedia_aud_dev_factory* pjmedia_tapi_factory(pj_pool_factory *pf);
++#endif
++
+ #define MAX_DRIVERS 16
+ #define MAX_DEVS 64
+
+@@ -409,6 +413,9 @@ PJ_DEF(pj_status_t) pjmedia_aud_subsys_i
+ #if PJMEDIA_AUDIO_DEV_HAS_NULL_AUDIO
+ aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_null_audio_factory;
+ #endif
++#if PJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE
++ aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_tapi_factory;
++#endif
+
+ /* Initialize each factory and build the device ID list */
+ for (i=0; i<aud_subsys.drv_cnt; ++i) {
+--- /dev/null
++++ b/pjmedia/src/pjmedia-audiodev/tapi_dev.c
+@@ -0,0 +1,1307 @@
++/******************************************************************************
++
++ Copyright (c) 2010
++ Lantiq Deutschland GmbH
++ Am Campeon 3; 85579 Neubiberg, Germany
++
++ For licensing information, see the file 'LICENSE' in the root folder of
++ this software module.
++
++******************************************************************************/
++#include <pjmedia-audiodev/audiodev_imp.h>
++#include <pjmedia/errno.h>
++#include <pj/assert.h>
++#include <pj/pool.h>
++#include <pj/log.h>
++#include <pj/os.h>
++
++#if defined(PJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE) && PJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE
++
++/* Linux includes */
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++#include <ctype.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <sys/types.h>
++#include <sys/ioctl.h>
++#include <sys/select.h>
++#include <sys/time.h>
++#include <unistd.h>
++#include <poll.h>
++
++/* TAPI includes */
++#include "drv_tapi_io.h"
++#include "vmmc_io.h"
++
++/* Maximum 2 devices */
++#define TAPI_AUDIO_PORT_NUM 2
++#define TAPI_BASE_NAME "TAPI"
++#define TAPI_LL_DEV_BASE_PATH "/dev/vmmc"
++#define TAPI_LL_DEV_FIRMWARE_NAME "/lib/firmware/danube_firmware.bin"
++#define TAPI_LL_BBD_NAME "/lib/firmware/danube_bbd_fxs.bin"
++
++#define TAPI_LL_DEV_SELECT_TIMEOUT_MS 2000
++#define TAPI_LL_DEV_MAX_PACKET_SIZE 800
++#define TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE 12
++#define TAPI_LL_DEV_ENC_FRAME_LEN_MS 20
++#define TAPI_LL_DEV_ENC_SMPL_PER_SEC 8000
++#define TAPI_LL_DEV_ENC_BITS_PER_SMPLS 16
++#define TAPI_LL_DEV_ENC_SMPL_PER_FRAME 160
++#define TAPI_LL_DEV_ENC_BYTES_PER_FRAME (TAPI_LL_DEV_ENC_SMPL_PER_FRAME * (TAPI_LL_DEV_ENC_BITS_PER_SMPLS / 8))
++
++#define THIS_FILE "tapi_dev.c"
++
++/* Set to 1 to enable tracing */
++#if 1
++# define TRACE_(expr) PJ_LOG(1,expr)
++#else
++# define TRACE_(expr)
++#endif
++
++pj_int32_t ch_fd[TAPI_AUDIO_PORT_NUM];
++
++typedef struct
++{
++ pj_int32_t dev_fd;
++ pj_int32_t ch_fd[TAPI_AUDIO_PORT_NUM];
++ pj_int8_t data2phone_map[TAPI_AUDIO_PORT_NUM];
++} tapi_ctx;
++
++struct tapi_aud_factory
++{
++ pjmedia_aud_dev_factory base;
++ pj_pool_t *pool;
++ pj_pool_factory *pf;
++ pj_uint32_t dev_count;
++ pjmedia_aud_dev_info *dev_info;
++ tapi_ctx dev_ctx;
++};
++
++typedef struct tapi_aud_factory tapi_aud_factory_t;
++
++struct tapi_aud_stream
++{
++ pjmedia_aud_stream base;
++ pj_pool_t *pool;
++ pjmedia_aud_param param;
++ pjmedia_aud_rec_cb rec_cb;
++ pjmedia_aud_play_cb play_cb;
++ void *user_data;
++
++ pj_thread_desc thread_desc;
++ pj_thread_t *thread;
++ tapi_ctx *dev_ctx;
++ pj_uint8_t run_flag;
++ pj_timestamp timestamp;
++};
++
++typedef struct tapi_aud_stream tapi_aud_stream_t;
++
++/* Factory prototypes */
++static pj_status_t factory_init(pjmedia_aud_dev_factory *f);
++static pj_status_t factory_destroy(pjmedia_aud_dev_factory *f);
++static unsigned factory_get_dev_count(pjmedia_aud_dev_factory *f);
++static pj_status_t factory_get_dev_info(pjmedia_aud_dev_factory *f,
++ unsigned index,
++ pjmedia_aud_dev_info *info);
++static pj_status_t factory_default_param(pjmedia_aud_dev_factory *f,
++ unsigned index,
++ pjmedia_aud_param *param);
++static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f,
++ const pjmedia_aud_param *param,
++ pjmedia_aud_rec_cb rec_cb,
++ pjmedia_aud_play_cb play_cb,
++ void *user_data,
++ pjmedia_aud_stream **p_aud_strm);
++
++/* Stream prototypes */
++static pj_status_t stream_get_param(pjmedia_aud_stream *strm,
++ pjmedia_aud_param *param);
++static pj_status_t stream_get_cap(pjmedia_aud_stream *strm,
++ pjmedia_aud_dev_cap cap,
++ void *value);
++static pj_status_t stream_set_cap(pjmedia_aud_stream *strm,
++ pjmedia_aud_dev_cap cap,
++ const void *value);
++static pj_status_t stream_start(pjmedia_aud_stream *strm);
++static pj_status_t stream_stop(pjmedia_aud_stream *strm);
++static pj_status_t stream_destroy(pjmedia_aud_stream *strm);
++
++static pjmedia_aud_dev_factory_op tapi_fact_op =
++{
++ &factory_init,
++ &factory_destroy,
++ &factory_get_dev_count,
++ &factory_get_dev_info,
++ &factory_default_param,
++ &factory_create_stream
++};
++
++static pjmedia_aud_stream_op tapi_strm_op =
++{
++ &stream_get_param,
++ &stream_get_cap,
++ &stream_set_cap,
++ &stream_start,
++ &stream_stop,
++ &stream_destroy
++};
++
++/* TAPI configuration */
++static struct tapi_aud_stream streams[TAPI_AUDIO_PORT_NUM];
++
++void (*tapi_digit_callback)(pj_uint8_t port, pj_uint8_t digit) = NULL;
++void (*tapi_hook_callback)(pj_uint8_t port, pj_uint8_t event) = NULL;
++
++#define TAPI_TONE_LOCALE_NONE 32
++#define TAPI_TONE_LOCALE_BUSY_CODE 33
++#define TAPI_TONE_LOCALE_CONGESTION_CODE 34
++#define TAPI_TONE_LOCALE_DIAL_CODE 35
++#define TAPI_TONE_LOCALE_RING_CODE 36
++#define TAPI_TONE_LOCALE_WAITING_CODE 37
++
++static pj_uint8_t tapi_channel_revert = 0;
++static pj_uint8_t tapi_cid_type = 0;
++static pj_uint8_t tapi_locale = 0;
++
++void tapi_revert_channels(void)
++{
++ tapi_channel_revert = 1;
++ PJ_LOG(3, (THIS_FILE, "using reverted configuration for TAPI channels"));
++}
++
++void tapi_cid_select(char *cid)
++{
++ if (!stricmp(cid, "telecordia")) {
++ tapi_cid_type = IFX_TAPI_CID_STD_TELCORDIA;
++ PJ_LOG(3, (THIS_FILE, "using TELECORDIA configuration for TAPI CID"));
++ } else if (!stricmp(cid, "etsi_fsk")) {
++ tapi_cid_type = IFX_TAPI_CID_STD_ETSI_FSK;
++ PJ_LOG(3, (THIS_FILE, "using ETSI FSK configuration for TAPI CID"));
++ } else if (!stricmp(cid, "etsi_dtmf")) {
++ tapi_cid_type = IFX_TAPI_CID_STD_ETSI_DTMF;
++ PJ_LOG(3, (THIS_FILE, "using ETSI DTMF configuration for TAPI CID"));
++ } else if (!stricmp(cid, "sin")) {
++ tapi_cid_type = IFX_TAPI_CID_STD_SIN;
++ PJ_LOG(3, (THIS_FILE, "using SIN CID configuration for TAPI CID"));
++ } else if (!stricmp(cid, "ntt")) {
++ tapi_cid_type = IFX_TAPI_CID_STD_NTT;
++ PJ_LOG(3, (THIS_FILE, "using NTT configuration for TAPI CID"));
++ } else if (!stricmp(cid, "kpn_dtmf")) {
++ tapi_cid_type = IFX_TAPI_CID_STD_KPN_DTMF;
++ PJ_LOG(3, (THIS_FILE, "using KPN DTMF configuration for TAPI CID"));
++ } else if (!stricmp(cid, "kpn_dtmf_fsk")) {
++ tapi_cid_type = IFX_TAPI_CID_STD_KPN_DTMF_FSK;
++ PJ_LOG(3, (THIS_FILE, "using KPN DTMF FSK configuration for TAPI CID"));
++ }
++}
++
++void tapi_locale_select(char *country)
++{
++ IFX_TAPI_TONE_t tone;
++ pj_status_t status;
++ pj_uint8_t c;
++
++ tapi_locale = 1;
++
++ if (!stricmp(country, "croatia")) {
++ PJ_LOG(3, (THIS_FILE, "using localized tones for Croatia"));
++
++ memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
++ tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
++ tone.simple.index = TAPI_TONE_LOCALE_BUSY_CODE;
++ tone.simple.freqA = 425;
++ tone.simple.levelA = 0;
++ tone.simple.cadence[0] = 500;
++ tone.simple.cadence[1] = 500;
++ tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
++ tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
++ tone.simple.loop = 0;
++ tone.simple.pause = 0;
++ for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
++ status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
++ if (status != PJ_SUCCESS)
++ TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
++ }
++
++ memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
++ tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
++ tone.simple.index = TAPI_TONE_LOCALE_CONGESTION_CODE;
++ tone.simple.freqA = 425;
++ tone.simple.levelA = 0;
++ tone.simple.cadence[0] = 250;
++ tone.simple.cadence[1] = 250;
++ tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
++ tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
++ tone.simple.loop = 0;
++ tone.simple.pause = 0;
++ for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
++ status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
++ if (status != PJ_SUCCESS)
++ TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
++ }
++
++ memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
++ tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
++ tone.simple.index = TAPI_TONE_LOCALE_DIAL_CODE;
++ tone.simple.freqA = 425;
++ tone.simple.levelA = 0;
++ tone.simple.cadence[0] = 200;
++ tone.simple.cadence[1] = 300;
++ tone.simple.cadence[2] = 700;
++ tone.simple.cadence[3] = 800;
++ tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
++ tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
++ tone.simple.frequencies[2] = IFX_TAPI_TONE_FREQA;
++ tone.simple.frequencies[3] = IFX_TAPI_TONE_FREQNONE;
++ tone.simple.loop = 0;
++ tone.simple.pause = 0;
++ for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
++ status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
++ if (status != PJ_SUCCESS)
++ TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
++ }
++
++ memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
++ tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
++ tone.simple.index = TAPI_TONE_LOCALE_RING_CODE;
++ tone.simple.freqA = 425;
++ tone.simple.levelA = 0;
++ tone.simple.cadence[0] = 1000;
++ tone.simple.cadence[1] = 4000;
++ tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
++ tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
++ tone.simple.loop = 0;
++ tone.simple.pause = 0;
++ for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
++ status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
++ if (status != PJ_SUCCESS)
++ TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
++ }
++
++ memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
++ tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
++ tone.simple.index = TAPI_TONE_LOCALE_WAITING_CODE;
++ tone.simple.freqA = 425;
++ tone.simple.levelA = 0;
++ tone.simple.cadence[0] = 300;
++ tone.simple.cadence[1] = 8000;
++ tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
++ tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
++ tone.simple.loop = 0;
++ tone.simple.pause = 0;
++ for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
++ status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
++ if (status != PJ_SUCCESS)
++ TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
++ }
++ } else if (!stricmp(country, "germany")) {
++ PJ_LOG(3, (THIS_FILE, "using localized tones for Germany"));
++
++ memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
++ tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
++ tone.simple.index = TAPI_TONE_LOCALE_BUSY_CODE;
++ tone.simple.freqA = 425;
++ tone.simple.levelA = 0;
++ tone.simple.cadence[0] = 480;
++ tone.simple.cadence[1] = 480;
++ tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
++ tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
++ tone.simple.loop = 0;
++ tone.simple.pause = 0;
++ for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
++ status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
++ if (status != PJ_SUCCESS)
++ TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
++ }
++
++ memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
++ tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
++ tone.simple.index = TAPI_TONE_LOCALE_CONGESTION_CODE;
++ tone.simple.freqA = 425;
++ tone.simple.levelA = 0;
++ tone.simple.cadence[0] = 240;
++ tone.simple.cadence[1] = 240;
++ tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
++ tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
++ tone.simple.loop = 0;
++ tone.simple.pause = 0;
++ for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
++ status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
++ if (status != PJ_SUCCESS)
++ TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
++ }
++
++ memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
++ tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
++ tone.simple.index = TAPI_TONE_LOCALE_DIAL_CODE;
++ tone.simple.freqA = 425;
++ tone.simple.levelA = 0;
++ tone.simple.cadence[0] = 1000;
++ tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
++ tone.simple.loop = 0;
++ tone.simple.pause = 0;
++ for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
++ status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
++ if (status != PJ_SUCCESS)
++ TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
++ }
++
++ memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
++ tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
++ tone.simple.index = TAPI_TONE_LOCALE_RING_CODE;
++ tone.simple.freqA = 425;
++ tone.simple.levelA = 0;
++ tone.simple.cadence[0] = 1000;
++ tone.simple.cadence[1] = 4000;
++ tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
++ tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
++ tone.simple.loop = 0;
++ tone.simple.pause = 0;
++ for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
++ status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
++ if (status != PJ_SUCCESS)
++ TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
++ }
++
++ memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
++ tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
++ tone.simple.index = TAPI_TONE_LOCALE_WAITING_CODE;
++ tone.simple.freqA = 425;
++ tone.simple.levelA = 0;
++ tone.simple.cadence[0] = 200;
++ tone.simple.cadence[1] = 200;
++ tone.simple.cadence[2] = 200;
++ tone.simple.cadence[3] = 5000;
++ tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA;
++ tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
++ tone.simple.frequencies[2] = IFX_TAPI_TONE_FREQA;
++ tone.simple.frequencies[3] = IFX_TAPI_TONE_FREQNONE;
++ tone.simple.loop = 0;
++ tone.simple.pause = 0;
++ for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
++ status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
++ if (status != PJ_SUCCESS)
++ TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
++ }
++ }
++}
++
++static pj_int32_t
++tapi_dev_open(char* dev_path, const pj_int32_t ch_num)
++{
++ char devname[128] = { 0 };
++ pj_ansi_sprintf(devname,"%s%u%u", dev_path, 1, ch_num);
++ return open((const char*)devname, O_RDWR, 0644);
++}
++
++static pj_status_t
++tapi_dev_binary_buffer_create(const char *pPath, pj_uint8_t **ppBuf, pj_uint32_t *pBufSz)
++{
++ pj_status_t status = PJ_SUCCESS;
++ FILE *fd;
++ struct stat file_stat;
++
++ fd = fopen(pPath, "rb");
++ if (fd == NULL) {
++ TRACE_((THIS_FILE, "ERROR - binary file %s open failed!\n", pPath));
++ return PJ_EUNKNOWN;
++ }
++
++ if (stat(pPath, &file_stat) != 0) {
++ TRACE_((THIS_FILE, "ERROR - file %s statistics get failed!\n", pPath));
++ return PJ_EUNKNOWN;
++ }
++
++ *ppBuf = malloc(file_stat.st_size);
++ if (*ppBuf == NULL) {
++ TRACE_((THIS_FILE, "ERROR - binary file %s memory allocation failed!\n", pPath));
++ status = PJ_EUNKNOWN;
++ goto on_exit;
++ }
++
++ if (fread (*ppBuf, sizeof(pj_uint8_t), file_stat.st_size, fd) <= 0) {
++ TRACE_((THIS_FILE, "ERROR - file %s read failed!\n", pPath));
++ status = PJ_EUNKNOWN;
++ goto on_exit;
++ }
++
++ *pBufSz = file_stat.st_size;
++
++on_exit:
++ if (fd != NULL)
++ fclose(fd);
++
++ if (*ppBuf != NULL && status != PJ_SUCCESS)
++ free(*ppBuf);
++
++ return status;
++}
++
++static void
++tapi_dev_binary_buffer_delete(pj_uint8_t *pBuf)
++{
++ if (pBuf != NULL)
++ free(pBuf);
++}
++
++static pj_status_t
++tapi_dev_firmware_download(pj_int32_t fd, const char *pPath)
++{
++ pj_status_t status = PJ_SUCCESS;
++ pj_uint8_t *pFirmware = NULL;
++ pj_uint32_t binSz = 0;
++ VMMC_IO_INIT vmmc_io_init;
++
++ status = tapi_dev_binary_buffer_create(pPath, &pFirmware, &binSz);
++ if (status != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - binary buffer create failed!\n"));
++ return PJ_EUNKNOWN;
++ }
++
++ memset(&vmmc_io_init, 0, sizeof(VMMC_IO_INIT));
++ vmmc_io_init.pPRAMfw = pFirmware;
++ vmmc_io_init.pram_size = binSz;
++
++ status = ioctl(fd, FIO_FW_DOWNLOAD, &vmmc_io_init);
++ if (status != PJ_SUCCESS)
++ TRACE_((THIS_FILE, "ERROR - FIO_FW_DOWNLOAD ioctl failed!"));
++
++ tapi_dev_binary_buffer_delete(pFirmware);
++
++ return status;
++}
++
++/* NOT USED */
++#if 0
++static int
++tapi_dev_bbd_download(int fd, const char *pPath)
++{
++ int status = PJ_SUCCESS;
++ unsigned char *pFirmware = NULL;
++ unsigned int binSz = 0;
++ VMMC_DWLD_t bbd_data;
++
++
++ /* Create binary buffer */
++ status = tapi_dev_binary_buffer_create(pPath, &pFirmware, &binSz);
++ if (status != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - binary buffer create failed!\n"));
++ return status;
++ }
++
++ /* Download Voice Firmware */
++ memset(&bbd_data, 0, sizeof(VMMC_DWLD_t));
++ bbd_data.buf = pFirmware;
++ bbd_data.size = binSz;
++
++ status = ioctl(fd, FIO_BBD_DOWNLOAD, &bbd_data);
++ if (status != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - FIO_BBD_DOWNLOAD failed!\n"));
++ }
++
++ /* Delete binary buffer */
++ tapi_dev_binary_buffer_delete(pFirmware);
++
++ return status;
++}
++#endif
++
++static pj_status_t tapi_dev_start(tapi_aud_factory_t *f)
++{
++ pj_uint8_t c, hook_status;
++ IFX_TAPI_TONE_t tone;
++ IFX_TAPI_DEV_START_CFG_t tapistart;
++ IFX_TAPI_MAP_DATA_t datamap;
++ IFX_TAPI_ENC_CFG_t enc_cfg;
++ IFX_TAPI_LINE_VOLUME_t line_vol;
++ IFX_TAPI_WLEC_CFG_t lec_cfg;
++ IFX_TAPI_JB_CFG_t jb_cfg;
++ IFX_TAPI_CID_CFG_t cid_cfg;
++ pj_status_t status;
++
++ /* Open device */
++ f->dev_ctx.dev_fd = tapi_dev_open(TAPI_LL_DEV_BASE_PATH, 0);
++
++ if (f->dev_ctx.dev_fd < 0) {
++ TRACE_((THIS_FILE, "ERROR - TAPI device open failed!"));
++ return PJ_EUNKNOWN;
++ }
++
++ for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
++ if (tapi_channel_revert)
++ ch_fd[c] = f->dev_ctx.ch_fd[c] = tapi_dev_open(TAPI_LL_DEV_BASE_PATH, c + 1);
++ else
++ ch_fd[c] = f->dev_ctx.ch_fd[c] = tapi_dev_open(TAPI_LL_DEV_BASE_PATH, TAPI_AUDIO_PORT_NUM - c);
++
++ if (f->dev_ctx.dev_fd < 0) {
++ TRACE_((THIS_FILE, "ERROR - TAPI channel%d open failed!", c));
++ return PJ_EUNKNOWN;
++ }
++ if (tapi_channel_revert)
++ f->dev_ctx.data2phone_map[c] = c & 0x1 ? 1 : 0;
++ else
++ f->dev_ctx.data2phone_map[c] = c & 0x1 ? 0 : 1;
++ }
++
++ status = tapi_dev_firmware_download(f->dev_ctx.dev_fd, TAPI_LL_DEV_FIRMWARE_NAME);
++ if (status != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - Voice Firmware Download failed!"));
++ return PJ_EUNKNOWN;
++ }
++
++ /* Download coefficients */
++ /*
++ status = tapi_dev_bbd_download(f->dev_ctx.dev_fd, TAPI_LL_BBD_NAME);
++ if (status != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - Voice Coefficients Download failed!"));
++ return PJ_EUNKNOWN;
++ }
++ */
++
++ memset(&tapistart, 0x0, sizeof(IFX_TAPI_DEV_START_CFG_t));
++ tapistart.nMode = IFX_TAPI_INIT_MODE_VOICE_CODER;
++
++ /* Start TAPI */
++ status = ioctl(f->dev_ctx.dev_fd, IFX_TAPI_DEV_START, &tapistart);
++ if (status != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - IFX_TAPI_DEV_START ioctl failed"));
++ return PJ_EUNKNOWN;
++ }
++
++
++ /* OpenWrt default tone */
++ memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
++ tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
++ tone.simple.index = TAPI_TONE_LOCALE_NONE;
++ tone.simple.freqA = 400;
++ tone.simple.levelA = 0;
++ tone.simple.freqB = 450;
++ tone.simple.levelB = 0;
++ tone.simple.freqC = 550;
++ tone.simple.levelC = 0;
++ tone.simple.freqD = 600;
++ tone.simple.levelD = 0;
++ tone.simple.cadence[0] = 100;
++ tone.simple.cadence[1] = 150;
++ tone.simple.cadence[2] = 100;
++ tone.simple.cadence[3] = 150;
++ tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA | IFX_TAPI_TONE_FREQB;
++ tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE;
++ tone.simple.frequencies[2] = IFX_TAPI_TONE_FREQC | IFX_TAPI_TONE_FREQD;
++ tone.simple.frequencies[3] = IFX_TAPI_TONE_FREQNONE;
++ tone.simple.loop = 0;
++ tone.simple.pause = 0;
++ for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) {
++ /* OpenWrt default tone */
++ status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone);
++ if (status != PJ_SUCCESS)
++ TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n"));
++
++ /* Perform mapping */
++ memset(&datamap, 0x0, sizeof(IFX_TAPI_MAP_DATA_t));
++ datamap.nDstCh = f->dev_ctx.data2phone_map[c];
++ datamap.nChType = IFX_TAPI_MAP_TYPE_PHONE;
++
++ status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_MAP_DATA_ADD, &datamap);
++ if (status != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - IFX_TAPI_MAP_DATA_ADD ioctl failed"));
++ return PJ_EUNKNOWN;
++ }
++
++ /* Set Line feed */
++ status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_STANDBY);
++ if (status != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed"));
++ return PJ_EUNKNOWN;
++ }
++
++ /* Configure encoder for linear stream */
++ memset(&enc_cfg, 0x0, sizeof(IFX_TAPI_ENC_CFG_t));
++ enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
++ enc_cfg.nEncType = IFX_TAPI_COD_TYPE_LIN16_8;
++
++ status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_ENC_CFG_SET, &enc_cfg);
++ if (status != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - IFX_TAPI_ENC_CFG_SET ioctl failed"));
++ return PJ_EUNKNOWN;
++ }
++
++ /* Suppress TAPI volume, otherwise PJSIP starts autogeneration */
++ memset(&line_vol, 0, sizeof(line_vol));
++ line_vol.nGainRx = -8;
++ line_vol.nGainTx = -8;
++
++ status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_PHONE_VOLUME_SET, &line_vol);
++ if (status != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - IFX_TAPI_PHONE_VOLUME_SET ioctl failed"));
++ return PJ_EUNKNOWN;
++ }
++
++ /* Configure line echo canceller */
++ memset(&lec_cfg, 0, sizeof(lec_cfg));
++ lec_cfg.nType = IFX_TAPI_WLEC_TYPE_NFE;
++ lec_cfg.bNlp = IFX_TAPI_LEC_NLP_OFF;
++
++ status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_WLEC_PHONE_CFG_SET, &lec_cfg);
++ if (status != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - IFX_TAPI_WLEC_PHONE_CFG_SET ioctl failed"));
++ return PJ_EUNKNOWN;
++ }
++
++ /* Configure jitter buffer */
++ memset(&jb_cfg, 0, sizeof(jb_cfg));
++ jb_cfg.nJbType = IFX_TAPI_JB_TYPE_ADAPTIVE;
++ jb_cfg.nPckAdpt = IFX_TAPI_JB_PKT_ADAPT_VOICE;
++ jb_cfg.nLocalAdpt = IFX_TAPI_JB_LOCAL_ADAPT_ON;
++ jb_cfg.nScaling = 0x10;
++ jb_cfg.nInitialSize = 0x2d0;
++ jb_cfg.nMinSize = 0x50;
++ jb_cfg.nMaxSize = 0x5a0;
++
++ status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_JB_CFG_SET, &jb_cfg);
++ if (status != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - IFX_TAPI_JB_CFG_SET ioctl failed"));
++ return PJ_EUNKNOWN;
++ }
++
++ /* Configure Caller ID type */
++ if (tapi_cid_type) {
++ memset(&cid_cfg, 0, sizeof(cid_cfg));
++ cid_cfg.nStandard = tapi_cid_type;
++ status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_CID_CFG_SET, &cid_cfg);
++ if (status != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - IFX_TAPI_CID_CFG_SET ioctl failed"));
++ return PJ_EUNKNOWN;
++ }
++ }
++
++ /* check hook status */
++ hook_status = 0;
++ status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_LINE_HOOK_STATUS_GET, &hook_status);
++ if (status != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_HOOK_STATUS_GET ioctl failed!"));
++ return PJ_EUNKNOWN;
++ }
++
++ /* if off hook do initialization */
++ if (hook_status) {
++ status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_ACTIVE);
++ if (status != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed!"));
++ return PJ_EUNKNOWN;
++ }
++ status = ioctl(c, IFX_TAPI_ENC_START, 0);
++ if (status != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - IFX_TAPI_ENC_START ioctl failed!"));
++ return PJ_EUNKNOWN;
++ }
++
++ status = ioctl(c, IFX_TAPI_DEC_START, 0);
++ if (status != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - IFX_TAPI_DEC_START ioctl failed!"));
++ return PJ_EUNKNOWN;
++ }
++ }
++ }
++
++ return status;
++}
++
++static pj_status_t
++tapi_dev_stop(tapi_aud_factory_t *f)
++{
++ pj_status_t status = PJ_SUCCESS;
++ pj_uint8_t c;
++
++ if (ioctl(f->dev_ctx.dev_fd, IFX_TAPI_DEV_STOP, 0) != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - IFX_TAPI_DEV_STOP ioctl failed"));
++ status = PJ_EUNKNOWN;
++ }
++
++ close(f->dev_ctx.dev_fd);
++ for (c = TAPI_AUDIO_PORT_NUM; c > 0; c--)
++ close(f->dev_ctx.ch_fd[TAPI_AUDIO_PORT_NUM-c]);
++
++ return status;
++}
++
++static pj_status_t
++tapi_dev_codec_control(pj_int32_t fd, pj_uint8_t start)
++{
++ if (ioctl(fd, start ? IFX_TAPI_ENC_START : IFX_TAPI_ENC_STOP, 0) != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - IFX_TAPI_ENC_%s ioctl failed!",
++ start ? "START" : "STOP"));
++ return PJ_EUNKNOWN;
++ }
++
++ if (ioctl(fd, start ? IFX_TAPI_DEC_START : IFX_TAPI_DEC_STOP, 0) != IFX_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - IFX_TAPI_DEC_%s ioctl failed!",
++ start ? "START" : "STOP"));
++ return PJ_EUNKNOWN;
++ }
++
++ return PJ_SUCCESS;
++}
++
++static pj_status_t tapi_dev_event_on_hook(tapi_ctx *dev_ctx, pj_uint32_t dev_idx)
++{
++ PJ_LOG(1,(THIS_FILE, "TAPI: ONHOOK"));
++
++ if (ioctl(dev_ctx->ch_fd[dev_idx], IFX_TAPI_LINE_FEED_SET,
++ IFX_TAPI_LINE_FEED_STANDBY) != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed!"));
++ return PJ_EUNKNOWN;
++ }
++
++ /* enc/dec stop */
++ if (tapi_dev_codec_control(dev_ctx->ch_fd[dev_idx], 0) != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - codec start failed!"));
++ return PJ_EUNKNOWN;
++ }
++
++ return PJ_SUCCESS;
++}
++
++static pj_status_t tapi_dev_event_off_hook(tapi_ctx *dev_ctx, pj_uint32_t dev_idx)
++{
++ PJ_LOG(1,(THIS_FILE, "TAPI: OFFHOOK"));
++
++ if (ioctl(dev_ctx->ch_fd[dev_idx], IFX_TAPI_LINE_FEED_SET,
++ IFX_TAPI_LINE_FEED_ACTIVE) != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed!"));
++ return PJ_EUNKNOWN;
++ }
++
++ /* enc/dec stop */
++ if (tapi_dev_codec_control(dev_ctx->ch_fd[dev_idx], 1) != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - codec start failed!"));
++ return PJ_EUNKNOWN;
++ }
++
++ return PJ_SUCCESS;
++}
++
++static pj_status_t
++tapi_dev_event_digit(tapi_ctx *dev_ctx, pj_uint32_t dev_idx)
++{
++ PJ_LOG(1,(THIS_FILE, "TAPI: OFFHOOK"));
++
++ if (ioctl(dev_ctx->ch_fd[dev_idx], IFX_TAPI_LINE_FEED_SET,
++ IFX_TAPI_LINE_FEED_ACTIVE) != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed!"));
++ return PJ_EUNKNOWN;
++ }
++
++ /* enc/dec stop */
++ if (tapi_dev_codec_control(dev_ctx->ch_fd[dev_idx], 1) != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - codec start failed!"));
++ return PJ_EUNKNOWN;
++ }
++
++ return PJ_SUCCESS;
++}
++
++static pj_status_t
++tapi_dev_event_handler(tapi_aud_stream_t *stream)
++{
++ IFX_TAPI_EVENT_t tapiEvent;
++ tapi_ctx *dev_ctx = stream->dev_ctx;
++ pj_status_t status = PJ_SUCCESS;
++ unsigned int i;
++
++ for (i = 0; i < TAPI_AUDIO_PORT_NUM; i++) {
++ memset (&tapiEvent, 0, sizeof(tapiEvent));
++ tapiEvent.ch = dev_ctx->data2phone_map[i];
++ status = ioctl(dev_ctx->dev_fd, IFX_TAPI_EVENT_GET, &tapiEvent);
++
++ if ((status == PJ_SUCCESS) && (tapiEvent.id != IFX_TAPI_EVENT_NONE)) {
++ switch(tapiEvent.id) {
++ case IFX_TAPI_EVENT_FXS_ONHOOK:
++ status = tapi_dev_event_on_hook(dev_ctx, i);
++ if(tapi_hook_callback)
++ tapi_hook_callback(i, 0);
++ break;
++ case IFX_TAPI_EVENT_FXS_OFFHOOK:
++ status = tapi_dev_event_off_hook(dev_ctx, i);
++ if(tapi_hook_callback)
++ tapi_hook_callback(i, 1);
++ break;
++ case IFX_TAPI_EVENT_DTMF_DIGIT:
++ if(tapi_digit_callback)
++ tapi_digit_callback(i, tapiEvent.data.dtmf.ascii);
++ break;
++ case IFX_TAPI_EVENT_PULSE_DIGIT:
++ if(tapi_digit_callback)
++ if(tapiEvent.data.pulse.digit == 0xB)
++ tapi_digit_callback(i, '0');
++ else
++ tapi_digit_callback(i, '0' + tapiEvent.data.pulse.digit);
++ break;
++ case IFX_TAPI_EVENT_COD_DEC_CHG:
++ case IFX_TAPI_EVENT_TONE_GEN_END:
++ case IFX_TAPI_EVENT_CID_TX_SEQ_END:
++ break;
++ default:
++ PJ_LOG(1,(THIS_FILE, "unknown tapi event %08X", tapiEvent.id));
++ break;
++ }
++ }
++ }
++
++ return status;
++}
++
++static pj_status_t
++tapi_dev_data_handler(tapi_aud_stream_t *stream) {
++ pj_status_t status = PJ_SUCCESS;
++ tapi_ctx *dev_ctx = stream->dev_ctx;
++ pj_uint32_t dev_idx = stream->param.rec_id;
++ pj_uint8_t buf_rec[TAPI_LL_DEV_ENC_BYTES_PER_FRAME + TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE]={0};
++ pj_uint8_t buf_play[TAPI_LL_DEV_ENC_BYTES_PER_FRAME + TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE]={0};
++ pjmedia_frame frame_rec, frame_play;
++ pj_int32_t ret;
++
++ /* Get data from driver */
++ ret = read(dev_ctx->ch_fd[dev_idx], buf_rec, sizeof(buf_rec));
++ if (ret < 0) {
++ TRACE_((THIS_FILE, "ERROR - no data available from device!"));
++ return PJ_EUNKNOWN;
++ }
++
++ if (ret > 0) {
++ frame_rec.type = PJMEDIA_FRAME_TYPE_AUDIO;
++ frame_rec.buf = buf_rec + TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE;
++ frame_rec.size = ret - TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE;
++ frame_rec.timestamp.u64 = stream->timestamp.u64;
++
++ status = stream->rec_cb(stream->user_data, &frame_rec);
++ if (status != PJ_SUCCESS)
++ PJ_LOG(1, (THIS_FILE, "rec_cb() failed %d", status));
++
++ frame_play.type = PJMEDIA_FRAME_TYPE_AUDIO;
++ frame_play.buf = buf_play + TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE;
++ frame_play.size = TAPI_LL_DEV_ENC_BYTES_PER_FRAME;
++ frame_play.timestamp.u64 = stream->timestamp.u64;
++
++ status = (*stream->play_cb)(stream->user_data, &frame_play);
++ if (status != PJ_SUCCESS) {
++ PJ_LOG(1, (THIS_FILE, "play_cb() failed %d", status));
++ } else {
++ memcpy(buf_play, buf_rec, TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE);
++
++ ret = write(dev_ctx->ch_fd[dev_idx], buf_play, sizeof(buf_play));
++
++ if (ret < 0) {
++ PJ_LOG(1, (THIS_FILE, "ERROR - device data writing failed!"));
++ return PJ_EUNKNOWN;
++ }
++
++ if (ret == 0) {
++ PJ_LOG(1, (THIS_FILE, "ERROR - no data written to device!"));
++ return PJ_EUNKNOWN;
++ }
++ }
++
++ stream->timestamp.u64 += TAPI_LL_DEV_ENC_SMPL_PER_FRAME;
++ }
++
++ return PJ_SUCCESS;
++}
++
++static int
++PJ_THREAD_FUNC tapi_dev_thread(void *arg) {
++ tapi_ctx *dev_ctx = streams[0].dev_ctx;
++ pj_uint32_t sretval;
++ struct pollfd fds[3];
++
++ PJ_LOG(1,(THIS_FILE, "TAPI: thread starting..."));
++
++ streams[0].run_flag = 1;
++ streams[1].run_flag = 1;
++
++ fds[0].fd = dev_ctx->dev_fd;
++ fds[0].events = POLLIN;
++ fds[1].fd = dev_ctx->ch_fd[0];
++ fds[1].events = POLLIN;
++ fds[2].fd = dev_ctx->ch_fd[1];
++ fds[2].events = POLLIN;
++
++ while(1)
++ {
++ sretval = poll(fds, TAPI_AUDIO_PORT_NUM + 1, TAPI_LL_DEV_SELECT_TIMEOUT_MS);
++
++ if (!streams[0].run_flag && !streams[0].run_flag)
++ break;
++ if (sretval <= 0)
++ continue;
++
++ if (fds[0].revents == POLLIN) {
++ if (tapi_dev_event_handler(&streams[0]) != PJ_SUCCESS) {
++ PJ_LOG(1, (THIS_FILE, "TAPI: event hanldler failed"));
++ break;
++ }
++ }
++
++ if (fds[1].revents == POLLIN) {
++ if (tapi_dev_data_handler(&streams[0]) != PJ_SUCCESS) {
++ PJ_LOG(1, (THIS_FILE, "TAPI: data hanldler failed"));
++ break;
++ }
++ }
++
++ if (fds[2].revents == POLLIN) {
++ if (tapi_dev_data_handler(&streams[1]) != PJ_SUCCESS) {
++ PJ_LOG(1, (THIS_FILE, "TAPI: data hanldler failed"));
++ break;
++ }
++ }
++ }
++ PJ_LOG(1, (THIS_FILE, "TAPI: thread stopping..."));
++
++ return 0;
++}
++
++/* Factory operations */
++
++pjmedia_aud_dev_factory*
++pjmedia_tapi_factory(pj_pool_factory *pf) {
++ struct tapi_aud_factory *f;
++ pj_pool_t *pool;
++
++ TRACE_((THIS_FILE, "pjmedia_tapi_factory()"));
++
++ pool = pj_pool_create(pf, "tapi", 512, 512, NULL);
++ f = PJ_POOL_ZALLOC_T(pool, struct tapi_aud_factory);
++ f->pf = pf;
++ f->pool = pool;
++ f->base.op = &tapi_fact_op;
++
++ return &f->base;
++}
++
++static pj_status_t
++factory_init(pjmedia_aud_dev_factory *f)
++{
++ struct tapi_aud_factory *af = (struct tapi_aud_factory*)f;
++ pj_uint8_t i;
++
++ TRACE_((THIS_FILE, "factory_init()"));
++
++ af->dev_count = TAPI_AUDIO_PORT_NUM;
++ af->dev_info = (pjmedia_aud_dev_info*)
++ pj_pool_calloc(af->pool, af->dev_count, sizeof(pjmedia_aud_dev_info));
++ for (i = 0; i < TAPI_AUDIO_PORT_NUM; i++) {
++ pj_ansi_sprintf(af->dev_info[i].name,"%s_%02d", TAPI_BASE_NAME, i);
++ af->dev_info[i].input_count = af->dev_info[i].output_count = 1;
++ af->dev_info[i].default_samples_per_sec = TAPI_LL_DEV_ENC_SMPL_PER_SEC;
++ pj_ansi_strcpy(af->dev_info[i].driver, "/dev/vmmc");
++ af->dev_info[i].caps = PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING |
++ PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY |
++ PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY;
++ af->dev_info[i].routes = PJMEDIA_AUD_DEV_ROUTE_DEFAULT ;
++ }
++ if (tapi_dev_start(af) != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - TAPI device init failed!"));
++ return PJ_EUNKNOWN;
++ }
++
++ return PJ_SUCCESS;
++}
++
++static pj_status_t
++factory_destroy(pjmedia_aud_dev_factory *f)
++{
++ struct tapi_aud_factory *af = (struct tapi_aud_factory*)f;
++ pj_pool_t *pool;
++ pj_status_t status = PJ_SUCCESS;
++
++ TRACE_((THIS_FILE, "factory_destroy()"));
++
++ if (tapi_dev_stop(af) != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - TAPI device stop failed!"));
++ status = PJ_EUNKNOWN;
++ }
++ pool = af->pool;
++ af->pool = NULL;
++ pj_pool_release(pool);
++
++ return status;
++}
++
++static unsigned
++factory_get_dev_count(pjmedia_aud_dev_factory *f)
++{
++ struct tapi_aud_factory *af = (struct tapi_aud_factory*)f;
++ TRACE_((THIS_FILE, "factory_get_dev_count()"));
++
++ return af->dev_count;
++}
++
++static pj_status_t
++factory_get_dev_info(pjmedia_aud_dev_factory *f, unsigned index, pjmedia_aud_dev_info *info)
++{
++ struct tapi_aud_factory *af = (struct tapi_aud_factory*)f;
++
++ TRACE_((THIS_FILE, "factory_get_dev_info()"));
++ PJ_ASSERT_RETURN(index < af->dev_count, PJMEDIA_EAUD_INVDEV);
++
++ pj_memcpy(info, &af->dev_info[index], sizeof(*info));
++
++ return PJ_SUCCESS;
++}
++
++static pj_status_t
++factory_default_param(pjmedia_aud_dev_factory *f, unsigned index, pjmedia_aud_param *param)
++{
++ struct tapi_aud_factory *af = (struct tapi_aud_factory*)f;
++ struct pjmedia_aud_dev_info *di = &af->dev_info[index];
++
++ TRACE_((THIS_FILE, "factory_default_param."));
++ PJ_ASSERT_RETURN(index < af->dev_count, PJMEDIA_EAUD_INVDEV);
++
++ pj_bzero(param, sizeof(*param));
++ if (di->input_count && di->output_count) {
++ param->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
++ param->rec_id = index;
++ param->play_id = index;
++ } else if (di->input_count) {
++ param->dir = PJMEDIA_DIR_CAPTURE;
++ param->rec_id = index;
++ param->play_id = PJMEDIA_AUD_INVALID_DEV;
++ } else if (di->output_count) {
++ param->dir = PJMEDIA_DIR_PLAYBACK;
++ param->play_id = index;
++ param->rec_id = PJMEDIA_AUD_INVALID_DEV;
++ } else {
++ return PJMEDIA_EAUD_INVDEV;
++ }
++
++ param->clock_rate = TAPI_LL_DEV_ENC_SMPL_PER_SEC; //di->default_samples_per_sec;
++ param->channel_count = 1;
++ param->samples_per_frame = TAPI_LL_DEV_ENC_SMPL_PER_FRAME;
++ param->bits_per_sample = TAPI_LL_DEV_ENC_BITS_PER_SMPLS;
++ param->flags = PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE | di->caps;
++ param->output_route = PJMEDIA_AUD_DEV_ROUTE_DEFAULT;
++
++ return PJ_SUCCESS;
++}
++
++
++static pj_status_t
++factory_create_stream(pjmedia_aud_dev_factory *f, const pjmedia_aud_param *param,
++ pjmedia_aud_rec_cb rec_cb, pjmedia_aud_play_cb play_cb,
++ void *user_data, pjmedia_aud_stream **p_aud_strm)
++{
++ struct tapi_aud_factory *af = (struct tapi_aud_factory*)f;
++ pj_pool_t *pool;
++ pj_status_t status;
++ int id = param->rec_id;
++ struct tapi_aud_stream *strm = &streams[param->rec_id];
++ TRACE_((THIS_FILE, "factory_create_stream() rec_id:%d play_id:%d", param->rec_id, param->play_id));
++
++ /* Can only support 16bits per sample */
++ PJ_ASSERT_RETURN(param->bits_per_sample == TAPI_LL_DEV_ENC_BITS_PER_SMPLS, PJ_EINVAL);
++ PJ_ASSERT_RETURN(param->clock_rate == TAPI_LL_DEV_ENC_SMPL_PER_SEC, PJ_EINVAL);
++ PJ_ASSERT_RETURN(param->samples_per_frame == TAPI_LL_DEV_ENC_SMPL_PER_FRAME, PJ_EINVAL);
++
++ /* Can only support bidirectional stream */
++ PJ_ASSERT_RETURN(param->dir & PJMEDIA_DIR_CAPTURE_PLAYBACK, PJ_EINVAL);
++
++ if (id == 0) {
++ /* Initialize our stream data */
++ pool = pj_pool_create(af->pf, "tapi-dev", 1000, 1000, NULL);
++ PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
++
++ strm->pool = pool;
++ } else {
++ pool = strm->pool = streams[0].pool;
++ }
++
++ strm->rec_cb = rec_cb;
++ strm->play_cb = play_cb;
++ strm->user_data = user_data;
++
++ pj_memcpy(&strm->param, param, sizeof(*param));
++
++ if ((strm->param.flags & PJMEDIA_AUD_DEV_CAP_EXT_FORMAT) == 0) {
++ strm->param.ext_fmt.id = PJMEDIA_FORMAT_L16;
++ }
++
++ strm->timestamp.u64 = 0;
++ strm->dev_ctx = &(af->dev_ctx);
++
++ /* Create and start the thread */
++ if (id == 1) {
++ status = pj_thread_create(pool, "tapi", &tapi_dev_thread, strm, 0, 0, &streams[0].thread);
++ if (status != PJ_SUCCESS) {
++ stream_destroy(&strm->base);
++ return status;
++ }
++ }
++
++ /* Done */
++ strm->base.op = &tapi_strm_op;
++ *p_aud_strm = &strm->base;
++
++ return PJ_SUCCESS;
++}
++
++static pj_status_t
++stream_get_param(pjmedia_aud_stream *s, pjmedia_aud_param *pi)
++{
++ struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s;
++
++ PJ_ASSERT_RETURN(strm && pi, PJ_EINVAL);
++ pj_memcpy(pi, &strm->param, sizeof(*pi));
++
++ if (stream_get_cap(s, PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
++ &pi->output_vol) == PJ_SUCCESS)
++ pi->flags |= PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING;
++
++ if (stream_get_cap(s, PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY,
++ &pi->output_latency_ms) == PJ_SUCCESS)
++ pi->flags |= PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY;
++
++ if (stream_get_cap(s, PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY,
++ &pi->input_latency_ms) == PJ_SUCCESS)
++ pi->flags |= PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY;
++
++ return PJ_SUCCESS;
++}
++
++static pj_status_t
++stream_get_cap(pjmedia_aud_stream *s, pjmedia_aud_dev_cap cap, void *pval)
++{
++ // struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s;
++ return PJ_SUCCESS;
++}
++
++static pj_status_t
++stream_set_cap(pjmedia_aud_stream *s, pjmedia_aud_dev_cap cap, const void *pval)
++{
++ // struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s;
++ return PJ_SUCCESS;
++}
++
++static pj_status_t
++stream_start(pjmedia_aud_stream *s)
++{
++ struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s;
++ pj_uint32_t dev_idx;
++
++ TRACE_((THIS_FILE, "stream_start()"));
++
++ dev_idx = strm->param.rec_id;
++
++ return PJ_SUCCESS;
++}
++
++static pj_status_t
++stream_stop(pjmedia_aud_stream *s)
++{
++ struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s;
++ tapi_ctx *dev_ctx = strm->dev_ctx;
++ pj_uint32_t dev_idx;
++
++ TRACE_((THIS_FILE, "stream_stop()"));
++ dev_idx = strm->param.rec_id;
++
++ if (tapi_dev_codec_control(dev_ctx->ch_fd[dev_idx], 0) != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - codec start failed!"));
++ return PJ_EUNKNOWN;
++ }
++
++ return PJ_SUCCESS;
++}
++
++static pj_status_t
++stream_destroy(pjmedia_aud_stream *s)
++{
++ pj_status_t state = PJ_SUCCESS;
++ struct tapi_aud_stream *stream = (struct tapi_aud_stream*)s;
++ pj_pool_t *pool;
++
++ PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);
++ TRACE_((THIS_FILE, "stream_destroy()"));
++
++ stream_stop(&stream->base);
++ stream->run_flag = 0;
++
++ if (stream->thread)
++ {
++ pj_thread_join(stream->thread);
++ pj_thread_destroy(stream->thread);
++ stream->thread = NULL;
++ }
++
++ pool = stream->pool;
++ pj_bzero(stream, sizeof(stream));
++ pj_pool_release(pool);
++
++ return state;
++}
++
++pj_status_t
++tapi_hook_status(pj_uint8_t port, pj_int32_t *status)
++{
++ PJ_ASSERT_RETURN(port < TAPI_AUDIO_PORT_NUM, PJ_EINVAL);
++
++ if (ioctl(ch_fd[port], IFX_TAPI_LINE_HOOK_STATUS_GET, status)
++ != PJ_SUCCESS) {
++ TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_HOOK_STATUS_GET ioctl failed!"));
++ return PJ_EUNKNOWN;
++ }
++
++ return PJ_SUCCESS;
++}
++
++pj_status_t
++tapi_ring(pj_uint8_t port, pj_uint8_t state, char *caller_number)
++{
++ PJ_ASSERT_RETURN(port < TAPI_AUDIO_PORT_NUM, PJ_EINVAL);
++
++ if (state) {
++ if (tapi_cid_type && caller_number) {
++ IFX_TAPI_CID_MSG_t cid_msg;
++ IFX_TAPI_CID_MSG_ELEMENT_t cid_msg_el[1];
++ memset(&cid_msg, 0, sizeof(cid_msg));
++ memset(&cid_msg_el, 0, sizeof(cid_msg_el));
++
++ cid_msg_el[0].string.elementType = IFX_TAPI_CID_ST_CLI;
++ cid_msg_el[0].string.len = strlen(caller_number);
++ strncpy(cid_msg_el[0].string.element, caller_number, sizeof(cid_msg_el[0].string.element));
++
++ cid_msg.txMode = IFX_TAPI_CID_HM_ONHOOK;
++ cid_msg.messageType = IFX_TAPI_CID_MT_CSUP;
++ cid_msg.nMsgElements = 1;
++ cid_msg.message = cid_msg_el;
++ ioctl(ch_fd[port], IFX_TAPI_CID_TX_SEQ_START, &cid_msg);
++ } else {
++ ioctl(ch_fd[port], IFX_TAPI_RING_START, 0);
++ }
++ } else {
++ ioctl(ch_fd[port], IFX_TAPI_RING_STOP, 0);
++ }
++
++ return PJ_SUCCESS;
++}
++
++pj_status_t
++tapi_tone(pj_uint8_t port, pj_uint8_t code)
++{
++ PJ_ASSERT_RETURN(port < TAPI_AUDIO_PORT_NUM, PJ_EINVAL);
++
++ if (tapi_locale && code)
++ ioctl(ch_fd[port], IFX_TAPI_TONE_LOCAL_PLAY, code);
++ else if (code)
++ ioctl(ch_fd[port], IFX_TAPI_TONE_LOCAL_PLAY, TAPI_TONE_LOCALE_NONE);
++ else
++ ioctl(ch_fd[port], IFX_TAPI_TONE_LOCAL_PLAY, 0);
++
++ return PJ_SUCCESS;
++}
++
++#endif /* PJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE */
diff --git a/package/pjsip/patches/0003-adds-PJ_DEF-pj_status_t-pjsua_add_snd_port-int-id.patch b/package/pjsip/patches/0003-adds-PJ_DEF-pj_status_t-pjsua_add_snd_port-int-id.patch
new file mode 100644
index 000000000..3331c8482
--- /dev/null
+++ b/package/pjsip/patches/0003-adds-PJ_DEF-pj_status_t-pjsua_add_snd_port-int-id.patch
@@ -0,0 +1,207 @@
+--- a/pjsip/include/pjsua-lib/pjsua.h
++++ b/pjsip/include/pjsua-lib/pjsua.h
+@@ -1543,6 +1543,8 @@ PJ_DECL(pjmedia_endpt*) pjsua_get_pjmedi
+ PJ_DECL(pj_pool_factory*) pjsua_get_pool_factory(void);
+
+
++PJ_DECL(pj_status_t) pjsua_add_snd_port(int id, pjsua_conf_port_id *p_id);
++
+
+ /*****************************************************************************
+ * Utilities.
+--- a/pjsip/include/pjsua-lib/pjsua_internal.h
++++ b/pjsip/include/pjsua-lib/pjsua_internal.h
+@@ -261,6 +261,8 @@ typedef struct pjsua_stun_resolve
+ } pjsua_stun_resolve;
+
+
++#define MAX_PORT 2
++
+ /**
+ * Global pjsua application data.
+ */
+@@ -336,7 +338,7 @@ struct pjsua_data
+ pj_bool_t aud_open_cnt;/**< How many # device is opened */
+ pj_bool_t no_snd; /**< No sound (app will manage it) */
+ pj_pool_t *snd_pool; /**< Sound's private pool. */
+- pjmedia_snd_port *snd_port; /**< Sound port. */
++ pjmedia_snd_port *snd_port[MAX_PORT]; /**< Sound port. */
+ pj_timer_entry snd_idle_timer;/**< Sound device idle timer. */
+ pjmedia_master_port *null_snd; /**< Master port for null sound. */
+ pjmedia_port *null_port; /**< Null port. */
+--- a/pjsip/src/pjsua-lib/pjsua_media.c
++++ b/pjsip/src/pjsua-lib/pjsua_media.c
+@@ -588,7 +588,7 @@ static void check_snd_dev_idle()
+ * It is idle when there is no port connection in the bridge and
+ * there is no active call.
+ */
+- if ((pjsua_var.snd_port!=NULL || pjsua_var.null_snd!=NULL) &&
++ if ((pjsua_var.snd_port[0]!=NULL || pjsua_var.null_snd!=NULL) &&
+ pjsua_var.snd_idle_timer.id == PJ_FALSE &&
+ pjmedia_conf_get_connect_count(pjsua_var.mconf) == 0 &&
+ call_cnt == 0 &&
+@@ -2008,7 +2008,7 @@ PJ_DEF(pj_status_t) pjsua_conf_connect(
+ pj_assert(status == PJ_SUCCESS);
+
+ /* Check if sound device is instantiated. */
+- need_reopen = (pjsua_var.snd_port==NULL && pjsua_var.null_snd==NULL &&
++ need_reopen = (pjsua_var.snd_port[0]==NULL && pjsua_var.null_snd==NULL &&
+ !pjsua_var.no_snd);
+
+ /* Check if sound device need to reopen because it needs to modify
+@@ -2072,7 +2072,7 @@ PJ_DEF(pj_status_t) pjsua_conf_connect(
+ /* The bridge version */
+
+ /* Create sound port if none is instantiated */
+- if (pjsua_var.snd_port==NULL && pjsua_var.null_snd==NULL &&
++ if (pjsua_var.snd_port[0]==NULL && pjsua_var.null_snd==NULL &&
+ !pjsua_var.no_snd)
+ {
+ pj_status_t status;
+@@ -2686,9 +2686,9 @@ static pj_status_t update_initial_aud_pa
+ pjmedia_aud_param param;
+ pj_status_t status;
+
+- PJ_ASSERT_RETURN(pjsua_var.snd_port != NULL, PJ_EBUG);
++ PJ_ASSERT_RETURN(pjsua_var.snd_port[0] != NULL, PJ_EBUG);
+
+- strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port);
++ strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port[0]);
+
+ status = pjmedia_aud_stream_get_param(strm, &param);
+ if (status != PJ_SUCCESS) {
+@@ -2754,7 +2754,7 @@ static pj_status_t open_snd_dev(pjmedia_
+ 1000 / param->base.clock_rate));
+
+ status = pjmedia_snd_port_create2( pjsua_var.snd_pool,
+- param, &pjsua_var.snd_port);
++ param, &pjsua_var.snd_port[0]);
+ if (status != PJ_SUCCESS)
+ return status;
+
+@@ -2812,13 +2812,13 @@ static pj_status_t open_snd_dev(pjmedia_
+ }
+
+ /* Connect sound port to the bridge */
+- status = pjmedia_snd_port_connect(pjsua_var.snd_port,
++ status = pjmedia_snd_port_connect(pjsua_var.snd_port[0],
+ conf_port );
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Unable to connect conference port to "
+ "sound device", status);
+- pjmedia_snd_port_destroy(pjsua_var.snd_port);
+- pjsua_var.snd_port = NULL;
++ pjmedia_snd_port_destroy(pjsua_var.snd_port[0]);
++ pjsua_var.snd_port[0] = NULL;
+ return status;
+ }
+
+@@ -2833,7 +2833,7 @@ static pj_status_t open_snd_dev(pjmedia_
+ pjmedia_aud_param si;
+ pj_str_t tmp;
+
+- strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port);
++ strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port[0]);
+ status = pjmedia_aud_stream_get_param(strm, &si);
+ if (status == PJ_SUCCESS)
+ status = pjmedia_aud_dev_get_info(si.rec_id, &rec_info);
+@@ -2876,12 +2876,12 @@ static pj_status_t open_snd_dev(pjmedia_
+ static void close_snd_dev(void)
+ {
+ /* Close sound device */
+- if (pjsua_var.snd_port) {
++ if (pjsua_var.snd_port[0]) {
+ pjmedia_aud_dev_info cap_info, play_info;
+ pjmedia_aud_stream *strm;
+ pjmedia_aud_param param;
+
+- strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port);
++ strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port[0]);
+ pjmedia_aud_stream_get_param(strm, &param);
+
+ if (pjmedia_aud_dev_get_info(param.rec_id, &cap_info) != PJ_SUCCESS)
+@@ -2893,9 +2893,9 @@ static void close_snd_dev(void)
+ "%s sound capture device",
+ play_info.name, cap_info.name));
+
+- pjmedia_snd_port_disconnect(pjsua_var.snd_port);
+- pjmedia_snd_port_destroy(pjsua_var.snd_port);
+- pjsua_var.snd_port = NULL;
++ pjmedia_snd_port_disconnect(pjsua_var.snd_port[0]);
++ pjmedia_snd_port_destroy(pjsua_var.snd_port[0]);
++ pjsua_var.snd_port[0] = NULL;
+ }
+
+ /* Close null sound device */
+@@ -2984,6 +2984,35 @@ PJ_DEF(pj_status_t) pjsua_set_snd_dev( i
+ return PJ_SUCCESS;
+ }
+
++PJ_DEF(pj_status_t) pjsua_add_snd_port(int id, pjsua_conf_port_id *p_id)
++{
++ unsigned alt_cr_cnt = 1;
++ unsigned alt_cr = 0;
++ pj_status_t status = -1;
++ pjmedia_snd_port_param param;
++ unsigned samples_per_frame;
++ pjmedia_port *port;
++ const pj_str_t name = pj_str("tapi2");
++ alt_cr = pjsua_var.media_cfg.clock_rate;
++ samples_per_frame = alt_cr *
++ pjsua_var.media_cfg.audio_frame_ptime *
++ pjsua_var.media_cfg.channel_count / 1000;
++ status = create_aud_param(&param.base,
++ pjsua_var.play_dev,
++ pjsua_var.cap_dev,
++ alt_cr,
++ pjsua_var.media_cfg.channel_count,
++ samples_per_frame, 16);
++ if (status != PJ_SUCCESS)
++ return status;
++ param.base.rec_id = id;
++ param.base.play_id = id;
++ param.options = 0;
++ status = pjmedia_snd_port_create2(pjsua_var.snd_pool,
++ &param, &pjsua_var.snd_port[id]);
++ return PJ_SUCCESS;
++}
++
+
+ /*
+ * Get currently active sound devices. If sound devices has not been created
+@@ -3088,7 +3117,7 @@ PJ_DEF(pj_status_t) pjsua_set_ec(unsigne
+ pjsua_var.media_cfg.ec_options = options;
+
+ if (pjsua_var.snd_port)
+- status = pjmedia_snd_port_set_ec(pjsua_var.snd_port, pjsua_var.pool,
++ status = pjmedia_snd_port_set_ec(pjsua_var.snd_port[0], pjsua_var.pool,
+ tail_ms, options);
+
+ PJSUA_UNLOCK();
+@@ -3111,7 +3140,7 @@ PJ_DEF(pj_status_t) pjsua_get_ec_tail(un
+ */
+ PJ_DEF(pj_bool_t) pjsua_snd_is_active(void)
+ {
+- return pjsua_var.snd_port != NULL;
++ return pjsua_var.snd_port[0] != NULL;
+ }
+
+
+@@ -3135,7 +3164,7 @@ PJ_DEF(pj_status_t) pjsua_snd_set_settin
+ if (pjsua_snd_is_active()) {
+ pjmedia_aud_stream *strm;
+
+- strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port);
++ strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port[0]);
+ status = pjmedia_aud_stream_set_cap(strm, cap, pval);
+ } else {
+ status = PJ_SUCCESS;
+@@ -3181,7 +3210,7 @@ PJ_DEF(pj_status_t) pjsua_snd_get_settin
+ /* Sound is active, retrieve from device directly */
+ pjmedia_aud_stream *strm;
+
+- strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port);
++ strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port[0]);
+ status = pjmedia_aud_stream_get_cap(strm, cap, pval);
+ } else {
+ /* Otherwise retrieve from internal param */
diff --git a/package/ppp/Makefile b/package/ppp/Makefile
new file mode 100644
index 000000000..3f7aa7bdb
--- /dev/null
+++ b/package/ppp/Makefile
@@ -0,0 +1,262 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=ppp
+PKG_VERSION:=2.4.5
+PKG_RELEASE:=6
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=ftp://ftp.samba.org/pub/ppp/
+PKG_MD5SUM:=4621bc56167b6953ec4071043fe0ec57
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)
+
+PKG_BUILD_DEPENDS:=libpcap
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ppp/Default
+ SECTION:=net
+ CATEGORY:=Network
+ MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org>
+ URL:=http://ppp.samba.org/
+endef
+
+define Package/ppp
+$(call Package/ppp/Default)
+ DEPENDS:=+kmod-ppp
+ TITLE:=PPP daemon
+ VARIANT:=default
+endef
+
+define Package/ppp-multilink
+$(call Package/ppp/Default)
+ DEPENDS:=+kmod-ppp
+ TITLE:=PPP daemon (with multilink support)
+ VARIANT:=multilink
+endef
+
+define Package/ppp/description
+This package contains the PPP (Point-to-Point Protocol) daemon.
+endef
+
+define Package/ppp/conffiles
+/etc/ppp/chap-secrets
+/etc/ppp/filter
+/etc/ppp/ip-down
+/etc/ppp/ip-up
+/etc/ppp/ipv6-down
+/etc/ppp/ipv6-up
+/etc/ppp/options
+endef
+
+define Package/ppp-mod-pppoa
+$(call Package/ppp/Default)
+ DEPENDS:=@(PACKAGE_ppp||PACKAGE_ppp-multilink) +linux-atm +kmod-pppoa
+ TITLE:=PPPoA plugin
+endef
+
+define Package/ppp-mod-pppoa/description
+This package contains a PPPoA (PPP over ATM) plugin for ppp.
+endef
+
+define Package/ppp-mod-pppoe
+$(call Package/ppp/Default)
+ DEPENDS:=@(PACKAGE_ppp||PACKAGE_ppp-multilink) +kmod-pppoe
+ TITLE:=PPPoE plugin
+endef
+
+define Package/ppp-mod-pppoe/description
+This package contains a PPPoE (PPP over Ethernet) plugin for ppp.
+endef
+
+define Package/ppp-mod-radius
+$(call Package/ppp/Default)
+ DEPENDS:=@(PACKAGE_ppp||PACKAGE_ppp-multilink)
+ TITLE:=RADIUS plugin
+endef
+
+define Package/ppp-mod-radius/description
+This package contains a RADIUS (Remote Authentication Dial-In User Service)
+plugin for ppp.
+endef
+
+define Package/ppp-mod-radius/conffiles
+/etc/ppp/radius.conf
+/etc/ppp/radius/
+endef
+
+define Package/ppp-mod-pppol2tp
+$(call Package/ppp/Default)
+ DEPENDS:=@(PACKAGE_ppp||PACKAGE_ppp-multilink) +kmod-pppol2tp
+ TITLE:=PPPoL2TP plugin
+endef
+
+define Package/ppp-mod-pppol2tp/description
+This package contains a PPPoL2TP (PPP over L2TP) plugin for ppp.
+endef
+
+define Package/ppp-mod-pptp
+$(call Package/ppp/Default)
+ DEPENDS:=@(PACKAGE_ppp||PACKAGE_ppp-multilink) +kmod-pptp +kmod-mppe +resolveip
+ TITLE:=PPtP plugin
+endef
+
+define Package/ppp-mod-pptp/description
+This package contains a PPtP plugin for ppp.
+endef
+
+define Package/chat
+$(call Package/ppp/Default)
+ DEPENDS:=@(PACKAGE_ppp||PACKAGE_ppp-multilink)
+ TITLE:=Establish conversation with a modem
+endef
+
+define Package/chat/description
+This package contains an utility to establish conversation with other PPP servers
+(via a modem).
+endef
+
+define Package/pppdump
+$(call Package/ppp/Default)
+ DEPENDS:=@(PACKAGE_ppp||PACKAGE_ppp-multilink)
+ TITLE:=Read PPP record file
+endef
+
+define Package/pppdump/description
+This package contains an utility to read PPP record file.
+endef
+
+define Package/pppstats
+$(call Package/ppp/Default)
+ DEPENDS:=@(PACKAGE_ppp||PACKAGE_ppp-multilink)
+ TITLE:=Report PPP statistics
+endef
+
+define Package/pppstats/description
+This package contains an utility to report PPP statistics.
+endef
+
+
+define Build/Configure
+$(call Build/Configure/Default,, \
+ UNAME_S="Linux" \
+ UNAME_R="$(LINUX_VERSION)" \
+ UNAME_M="$(ARCH)" \
+)
+ mkdir -p $(PKG_BUILD_DIR)/pppd/plugins/pppoatm/linux
+ cp \
+ $(LINUX_DIR)/include/linux/compiler.h \
+ $(LINUX_DIR)/include/linux/atm*.h \
+ $(PKG_BUILD_DIR)/pppd/plugins/pppoatm/linux/
+endef
+
+MAKE_FLAGS += COPTS="$(TARGET_CFLAGS)" \
+ PRECOMPILED_FILTER=1 \
+ STAGING_DIR="$(STAGING_DIR)"
+
+ifeq ($(BUILD_VARIANT),multilink)
+ MAKE_FLAGS += HAVE_MULTILINK=y
+else
+ MAKE_FLAGS += HAVE_MULTILINK=
+endif
+
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/include/pppd $(1)/usr/include/
+endef
+
+define Package/ppp/script_install
+endef
+
+define Package/ppp/install
+ $(INSTALL_DIR) $(1)/usr/lib/pppd/$(PKG_VERSION)
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/sbin/pppd $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/etc/ppp
+ $(INSTALL_CONF) ./files/etc/ppp/chap-secrets $(1)/etc/ppp/
+ $(INSTALL_DATA) ./files/etc/ppp/filter $(1)/etc/ppp/
+ $(INSTALL_DATA) ./files/etc/ppp/options $(1)/etc/ppp/
+ ln -sf /tmp/resolv.conf.ppp $(1)/etc/ppp/resolv.conf
+ $(INSTALL_DIR) $(1)/lib/netifd/proto
+ $(INSTALL_BIN) ./files/ppp.sh $(1)/lib/netifd/proto/
+ $(INSTALL_BIN) ./files/lib/netifd/ppp-up $(1)/lib/netifd/
+ $(INSTALL_BIN) ./files/lib/netifd/ppp-down $(1)/lib/netifd/
+endef
+Package/ppp-multilink/install=$(Package/ppp/install)
+
+define Package/ppp-mod-pppoa/install
+ $(INSTALL_DIR) $(1)/usr/lib/pppd/$(PKG_VERSION)
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/lib/pppd/$(PKG_VERSION)/pppoatm.so \
+ $(1)/usr/lib/pppd/$(PKG_VERSION)/
+endef
+
+define Package/ppp-mod-pppoe/install
+ $(INSTALL_DIR) $(1)/usr/lib/pppd/$(PKG_VERSION)
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/lib/pppd/$(PKG_VERSION)/rp-pppoe.so \
+ $(1)/usr/lib/pppd/$(PKG_VERSION)/
+endef
+
+define Package/ppp-mod-radius/install
+ $(INSTALL_DIR) $(1)/usr/lib/pppd/$(PKG_VERSION)
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/lib/pppd/$(PKG_VERSION)/radius.so \
+ $(1)/usr/lib/pppd/$(PKG_VERSION)/
+ $(INSTALL_DIR) $(1)/etc/ppp
+ $(INSTALL_DATA) ./files/etc/ppp/radius.conf $(1)/etc/ppp/
+ $(INSTALL_DIR) $(1)/etc/ppp/radius
+ $(INSTALL_DATA) ./files/etc/ppp/radius/dictionary* \
+ $(1)/etc/ppp/radius/
+ $(INSTALL_CONF) ./files/etc/ppp/radius/servers \
+ $(1)/etc/ppp/radius/
+endef
+
+define Package/ppp-mod-pppol2tp/install
+ $(INSTALL_DIR) $(1)/usr/lib/pppd/$(PKG_VERSION)
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/lib/pppd/$(PKG_VERSION)/pppol2tp.so \
+ $(1)/usr/lib/pppd/$(PKG_VERSION)/
+endef
+
+define Package/ppp-mod-pptp/install
+ $(INSTALL_DIR) $(1)/usr/lib/pppd/$(PKG_VERSION)
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/lib/pppd/$(PKG_VERSION)/pptp.so \
+ $(1)/usr/lib/pppd/$(PKG_VERSION)/
+ $(INSTALL_DIR) $(1)/etc/ppp
+ $(INSTALL_DATA) ./files/etc/ppp/options.pptp $(1)/etc/ppp/
+endef
+
+define Package/chat/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/sbin/chat $(1)/usr/sbin/
+endef
+
+define Package/pppdump/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/sbin/pppdump $(1)/usr/sbin/
+endef
+
+define Package/pppstats/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/sbin/pppstats $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,ppp))
+$(eval $(call BuildPackage,ppp-multilink))
+$(eval $(call BuildPackage,ppp-mod-pppoa))
+$(eval $(call BuildPackage,ppp-mod-pppoe))
+$(eval $(call BuildPackage,ppp-mod-radius))
+$(eval $(call BuildPackage,ppp-mod-pppol2tp))
+$(eval $(call BuildPackage,ppp-mod-pptp))
+$(eval $(call BuildPackage,chat))
+$(eval $(call BuildPackage,pppdump))
+$(eval $(call BuildPackage,pppstats))
diff --git a/package/ppp/files/etc/ppp/chap-secrets b/package/ppp/files/etc/ppp/chap-secrets
new file mode 100644
index 000000000..6ab76e49e
--- /dev/null
+++ b/package/ppp/files/etc/ppp/chap-secrets
@@ -0,0 +1 @@
+#USERNAME PROVIDER PASSWORD IPADDRESS
diff --git a/package/ppp/files/etc/ppp/filter b/package/ppp/files/etc/ppp/filter
new file mode 100644
index 000000000..ec72a81a0
--- /dev/null
+++ b/package/ppp/files/etc/ppp/filter
@@ -0,0 +1,23 @@
+#
+# Expression: outbound and not icmp[0] != 8 and not tcp[13] & 4 != 0
+#
+19
+48 0 0 0
+21 0 16 1
+40 0 0 2
+21 0 13 33
+48 0 0 13
+21 0 5 1
+40 0 0 10
+69 9 0 8191
+177 0 0 4
+80 0 0 4
+21 6 7 8
+21 0 5 6
+40 0 0 10
+69 3 0 8191
+177 0 0 4
+80 0 0 17
+69 1 0 4
+6 0 0 4
+6 0 0 0
diff --git a/package/ppp/files/etc/ppp/options b/package/ppp/files/etc/ppp/options
new file mode 100644
index 000000000..6b93f7bdb
--- /dev/null
+++ b/package/ppp/files/etc/ppp/options
@@ -0,0 +1,10 @@
+#debug
+logfile /dev/null
+noipdefault
+noaccomp
+nopcomp
+nocrtscts
+lock
+maxfail 0
+lcp-echo-failure 5
+lcp-echo-interval 1
diff --git a/package/ppp/files/etc/ppp/options.pptp b/package/ppp/files/etc/ppp/options.pptp
new file mode 100644
index 000000000..46a3f4811
--- /dev/null
+++ b/package/ppp/files/etc/ppp/options.pptp
@@ -0,0 +1,7 @@
+noipdefault
+noauth
+nobsdcomp
+nodeflate
+idle 0
+mppe required,no40,no56,stateless
+maxfail 0
diff --git a/package/ppp/files/etc/ppp/radius.conf b/package/ppp/files/etc/ppp/radius.conf
new file mode 100644
index 000000000..0f24a8c7f
--- /dev/null
+++ b/package/ppp/files/etc/ppp/radius.conf
@@ -0,0 +1,8 @@
+authserver localhost:1812
+acctserver localhost:1813
+dictionary /etc/ppp/radius/dictionary
+servers /etc/ppp/radius/servers
+mapfile /dev/null
+seqfile /tmp/radius.seq
+radius_timeout 5
+radius_retries 3
diff --git a/package/ppp/files/etc/ppp/radius/dictionary b/package/ppp/files/etc/ppp/radius/dictionary
new file mode 100644
index 000000000..706d1ce99
--- /dev/null
+++ b/package/ppp/files/etc/ppp/radius/dictionary
@@ -0,0 +1,253 @@
+#
+# Updated 97/06/13 to livingston-radius-2.01 miquels@cistron.nl
+#
+# This file contains dictionary translations for parsing
+# requests and generating responses. All transactions are
+# composed of Attribute/Value Pairs. The value of each attribute
+# is specified as one of 4 data types. Valid data types are:
+#
+# string - 0-253 octets
+# ipaddr - 4 octets in network byte order
+# integer - 32 bit value in big endian order (high byte first)
+# date - 32 bit value in big endian order - seconds since
+# 00:00:00 GMT, Jan. 1, 1970
+#
+# Enumerated values are stored in the user file with dictionary
+# VALUE translations for easy administration.
+#
+# Example:
+#
+# ATTRIBUTE VALUE
+# --------------- -----
+# Framed-Protocol = PPP
+# 7 = 1 (integer encoding)
+#
+
+# The dictionary format now supports vendor-specific attributes.
+# Vendors are introduced like this:
+#
+# VENDOR vendor_name vendor_number
+#
+# For example:
+#
+# VENDOR RoaringPenguin 10055
+#
+# Vendor-specific attributes have a fifth field with the name of the
+# vendor. For example:
+#
+# ATTRIBUTE RP-Upstream-Speed-Limit 1 integer RoaringPenguin
+#
+# introduces a Roaring Penguin vendor-specific attribbute with name
+# RP-Upstream-Speed-Limit, number 1, type integer and vendor RoaringPenguin.
+
+#
+# Following are the proper new names. Use these.
+#
+ATTRIBUTE User-Name 1 string
+ATTRIBUTE Password 2 string
+ATTRIBUTE CHAP-Password 3 string
+ATTRIBUTE NAS-IP-Address 4 ipaddr
+ATTRIBUTE NAS-Port-Id 5 integer
+ATTRIBUTE Service-Type 6 integer
+ATTRIBUTE Framed-Protocol 7 integer
+ATTRIBUTE Framed-IP-Address 8 ipaddr
+ATTRIBUTE Framed-IP-Netmask 9 ipaddr
+ATTRIBUTE Framed-Routing 10 integer
+ATTRIBUTE Filter-Id 11 string
+ATTRIBUTE Framed-MTU 12 integer
+ATTRIBUTE Framed-Compression 13 integer
+ATTRIBUTE Login-IP-Host 14 ipaddr
+ATTRIBUTE Login-Service 15 integer
+ATTRIBUTE Login-TCP-Port 16 integer
+ATTRIBUTE Reply-Message 18 string
+ATTRIBUTE Callback-Number 19 string
+ATTRIBUTE Callback-Id 20 string
+ATTRIBUTE Framed-Route 22 string
+ATTRIBUTE Framed-IPX-Network 23 ipaddr
+ATTRIBUTE State 24 string
+ATTRIBUTE Class 25 string
+ATTRIBUTE Session-Timeout 27 integer
+ATTRIBUTE Idle-Timeout 28 integer
+ATTRIBUTE Termination-Action 29 integer
+ATTRIBUTE Called-Station-Id 30 string
+ATTRIBUTE Calling-Station-Id 31 string
+ATTRIBUTE NAS-Identifier 32 string
+ATTRIBUTE Acct-Status-Type 40 integer
+ATTRIBUTE Acct-Delay-Time 41 integer
+ATTRIBUTE Acct-Input-Octets 42 integer
+ATTRIBUTE Acct-Output-Octets 43 integer
+ATTRIBUTE Acct-Session-Id 44 string
+ATTRIBUTE Acct-Authentic 45 integer
+ATTRIBUTE Acct-Session-Time 46 integer
+ATTRIBUTE Acct-Input-Packets 47 integer
+ATTRIBUTE Acct-Output-Packets 48 integer
+ATTRIBUTE Acct-Terminate-Cause 49 integer
+ATTRIBUTE Chap-Challenge 60 string
+ATTRIBUTE NAS-Port-Type 61 integer
+ATTRIBUTE Port-Limit 62 integer
+ATTRIBUTE Connect-Info 77 string
+
+# RFC 2869
+ATTRIBUTE Acct-Interim-Interval 85 integer
+
+#
+# Experimental Non Protocol Attributes used by Cistron-Radiusd
+#
+ATTRIBUTE Huntgroup-Name 221 string
+ATTRIBUTE User-Category 1029 string
+ATTRIBUTE Group-Name 1030 string
+ATTRIBUTE Simultaneous-Use 1034 integer
+ATTRIBUTE Strip-User-Name 1035 integer
+ATTRIBUTE Fall-Through 1036 integer
+ATTRIBUTE Add-Port-To-IP-Address 1037 integer
+ATTRIBUTE Exec-Program 1038 string
+ATTRIBUTE Exec-Program-Wait 1039 string
+ATTRIBUTE Hint 1040 string
+
+#
+# Non-Protocol Attributes
+# These attributes are used internally by the server
+#
+ATTRIBUTE Expiration 21 date
+ATTRIBUTE Auth-Type 1000 integer
+ATTRIBUTE Menu 1001 string
+ATTRIBUTE Termination-Menu 1002 string
+ATTRIBUTE Prefix 1003 string
+ATTRIBUTE Suffix 1004 string
+ATTRIBUTE Group 1005 string
+ATTRIBUTE Crypt-Password 1006 string
+ATTRIBUTE Connect-Rate 1007 integer
+
+#
+# Experimental, implementation specific attributes
+#
+# Limit session traffic
+ATTRIBUTE Session-Octets-Limit 227 integer
+# What to assume as limit - 0 in+out, 1 in, 2 out, 3 max(in,out)
+ATTRIBUTE Octets-Direction 228 integer
+
+#
+# Integer Translations
+#
+
+# User Types
+
+VALUE Service-Type Login-User 1
+VALUE Service-Type Framed-User 2
+VALUE Service-Type Callback-Login-User 3
+VALUE Service-Type Callback-Framed-User 4
+VALUE Service-Type Outbound-User 5
+VALUE Service-Type Administrative-User 6
+VALUE Service-Type NAS-Prompt-User 7
+
+# Framed Protocols
+
+VALUE Framed-Protocol PPP 1
+VALUE Framed-Protocol SLIP 2
+
+# Framed Routing Values
+
+VALUE Framed-Routing None 0
+VALUE Framed-Routing Broadcast 1
+VALUE Framed-Routing Listen 2
+VALUE Framed-Routing Broadcast-Listen 3
+
+# Framed Compression Types
+
+VALUE Framed-Compression None 0
+VALUE Framed-Compression Van-Jacobson-TCP-IP 1
+
+# Login Services
+
+VALUE Login-Service Telnet 0
+VALUE Login-Service Rlogin 1
+VALUE Login-Service TCP-Clear 2
+VALUE Login-Service PortMaster 3
+
+# Status Types
+
+VALUE Acct-Status-Type Start 1
+VALUE Acct-Status-Type Stop 2
+VALUE Acct-Status-Type Accounting-On 7
+VALUE Acct-Status-Type Accounting-Off 8
+
+# Authentication Types
+
+VALUE Acct-Authentic RADIUS 1
+VALUE Acct-Authentic Local 2
+VALUE Acct-Authentic PowerLink128 100
+
+# Termination Options
+
+VALUE Termination-Action Default 0
+VALUE Termination-Action RADIUS-Request 1
+
+# NAS Port Types, available in 3.3.1 and later
+
+VALUE NAS-Port-Type Async 0
+VALUE NAS-Port-Type Sync 1
+VALUE NAS-Port-Type ISDN 2
+VALUE NAS-Port-Type ISDN-V120 3
+VALUE NAS-Port-Type ISDN-V110 4
+
+# Acct Terminate Causes, available in 3.3.2 and later
+
+VALUE Acct-Terminate-Cause User-Request 1
+VALUE Acct-Terminate-Cause Lost-Carrier 2
+VALUE Acct-Terminate-Cause Lost-Service 3
+VALUE Acct-Terminate-Cause Idle-Timeout 4
+VALUE Acct-Terminate-Cause Session-Timeout 5
+VALUE Acct-Terminate-Cause Admin-Reset 6
+VALUE Acct-Terminate-Cause Admin-Reboot 7
+VALUE Acct-Terminate-Cause Port-Error 8
+VALUE Acct-Terminate-Cause NAS-Error 9
+VALUE Acct-Terminate-Cause NAS-Request 10
+VALUE Acct-Terminate-Cause NAS-Reboot 11
+VALUE Acct-Terminate-Cause Port-Unneeded 12
+VALUE Acct-Terminate-Cause Port-Preempted 13
+VALUE Acct-Terminate-Cause Port-Suspended 14
+VALUE Acct-Terminate-Cause Service-Unavailable 15
+VALUE Acct-Terminate-Cause Callback 16
+VALUE Acct-Terminate-Cause User-Error 17
+VALUE Acct-Terminate-Cause Host-Request 18
+
+#
+# Non-Protocol Integer Translations
+#
+
+VALUE Auth-Type Local 0
+VALUE Auth-Type System 1
+VALUE Auth-Type SecurID 2
+VALUE Auth-Type Crypt-Local 3
+VALUE Auth-Type Reject 4
+
+#
+# Cistron extensions
+#
+VALUE Auth-Type Pam 253
+VALUE Auth-Type None 254
+
+#
+# Experimental Non-Protocol Integer Translations for Cistron-Radiusd
+#
+VALUE Fall-Through No 0
+VALUE Fall-Through Yes 1
+VALUE Add-Port-To-IP-Address No 0
+VALUE Add-Port-To-IP-Address Yes 1
+
+#
+# Configuration Values
+# uncomment these two lines to turn account expiration on
+#
+
+#VALUE Server-Config Password-Expiration 30
+#VALUE Server-Config Password-Warning 5
+
+# Octets-Direction
+VALUE Octets-Direction Sum 0
+VALUE Octets-Direction Input 1
+VALUE Octets-Direction Output 2
+VALUE Octets-Direction MaxOveral 3
+VALUE Octets-Direction MaxSession 4
+
+INCLUDE /etc/ppp/radius/dictionary.microsoft
diff --git a/package/ppp/files/etc/ppp/radius/dictionary.asnet b/package/ppp/files/etc/ppp/radius/dictionary.asnet
new file mode 100644
index 000000000..337d1e140
--- /dev/null
+++ b/package/ppp/files/etc/ppp/radius/dictionary.asnet
@@ -0,0 +1,3 @@
+VENDOR ASNET 50000
+ATTRIBUTE Speed-Down 1 string ASNET
+ATTRIBUTE Speed-Up 2 string ASNET
diff --git a/package/ppp/files/etc/ppp/radius/dictionary.microsoft b/package/ppp/files/etc/ppp/radius/dictionary.microsoft
new file mode 100644
index 000000000..2a6c20e5f
--- /dev/null
+++ b/package/ppp/files/etc/ppp/radius/dictionary.microsoft
@@ -0,0 +1,80 @@
+#
+# Microsoft's VSA's, from RFC 2548
+#
+#
+
+VENDOR Microsoft 311 Microsoft
+
+ATTRIBUTE MS-CHAP-Response 1 string Microsoft
+ATTRIBUTE MS-CHAP-Error 2 string Microsoft
+ATTRIBUTE MS-CHAP-CPW-1 3 string Microsoft
+ATTRIBUTE MS-CHAP-CPW-2 4 string Microsoft
+ATTRIBUTE MS-CHAP-LM-Enc-PW 5 string Microsoft
+ATTRIBUTE MS-CHAP-NT-Enc-PW 6 string Microsoft
+ATTRIBUTE MS-MPPE-Encryption-Policy 7 string Microsoft
+# This is referred to as both singular and plural in the RFC.
+# Plural seems to make more sense.
+ATTRIBUTE MS-MPPE-Encryption-Type 8 string Microsoft
+ATTRIBUTE MS-MPPE-Encryption-Types 8 string Microsoft
+ATTRIBUTE MS-RAS-Vendor 9 integer Microsoft
+ATTRIBUTE MS-CHAP-Domain 10 string Microsoft
+ATTRIBUTE MS-CHAP-Challenge 11 string Microsoft
+ATTRIBUTE MS-CHAP-MPPE-Keys 12 string Microsoft
+ATTRIBUTE MS-BAP-Usage 13 integer Microsoft
+ATTRIBUTE MS-Link-Utilization-Threshold 14 integer Microsoft
+ATTRIBUTE MS-Link-Drop-Time-Limit 15 integer Microsoft
+ATTRIBUTE MS-MPPE-Send-Key 16 string Microsoft
+ATTRIBUTE MS-MPPE-Recv-Key 17 string Microsoft
+ATTRIBUTE MS-RAS-Version 18 string Microsoft
+ATTRIBUTE MS-Old-ARAP-Password 19 string Microsoft
+ATTRIBUTE MS-New-ARAP-Password 20 string Microsoft
+ATTRIBUTE MS-ARAP-PW-Change-Reason 21 integer Microsoft
+
+ATTRIBUTE MS-Filter 22 string Microsoft
+ATTRIBUTE MS-Acct-Auth-Type 23 integer Microsoft
+ATTRIBUTE MS-Acct-EAP-Type 24 integer Microsoft
+
+ATTRIBUTE MS-CHAP2-Response 25 string Microsoft
+ATTRIBUTE MS-CHAP2-Success 26 string Microsoft
+ATTRIBUTE MS-CHAP2-CPW 27 string Microsoft
+
+ATTRIBUTE MS-Primary-DNS-Server 28 ipaddr Microsoft
+ATTRIBUTE MS-Secondary-DNS-Server 29 ipaddr Microsoft
+ATTRIBUTE MS-Primary-NBNS-Server 30 ipaddr Microsoft
+ATTRIBUTE MS-Secondary-NBNS-Server 31 ipaddr Microsoft
+
+#ATTRIBUTE MS-ARAP-Challenge 33 string Microsoft
+
+
+#
+# Integer Translations
+#
+
+# MS-BAP-Usage Values
+
+VALUE MS-BAP-Usage Not-Allowed 0
+VALUE MS-BAP-Usage Allowed 1
+VALUE MS-BAP-Usage Required 2
+
+# MS-ARAP-Password-Change-Reason Values
+
+VALUE MS-ARAP-PW-Change-Reason Just-Change-Password 1
+VALUE MS-ARAP-PW-Change-Reason Expired-Password 2
+VALUE MS-ARAP-PW-Change-Reason Admin-Requires-Password-Change 3
+VALUE MS-ARAP-PW-Change-Reason Password-Too-Short 4
+
+# MS-Acct-Auth-Type Values
+
+VALUE MS-Acct-Auth-Type PAP 1
+VALUE MS-Acct-Auth-Type CHAP 2
+VALUE MS-Acct-Auth-Type MS-CHAP-1 3
+VALUE MS-Acct-Auth-Type MS-CHAP-2 4
+VALUE MS-Acct-Auth-Type EAP 5
+
+# MS-Acct-EAP-Type Values
+
+VALUE MS-Acct-EAP-Type MD5 4
+VALUE MS-Acct-EAP-Type OTP 5
+VALUE MS-Acct-EAP-Type Generic-Token-Card 6
+VALUE MS-Acct-EAP-Type TLS 13
+
diff --git a/package/ppp/files/etc/ppp/radius/servers b/package/ppp/files/etc/ppp/radius/servers
new file mode 100644
index 000000000..0d4f0691d
--- /dev/null
+++ b/package/ppp/files/etc/ppp/radius/servers
@@ -0,0 +1,2 @@
+# SERVER SECRET
+localhost secret
diff --git a/package/ppp/files/lib/netifd/ppp-down b/package/ppp/files/lib/netifd/ppp-down
new file mode 100755
index 000000000..94cefc415
--- /dev/null
+++ b/package/ppp/files/lib/netifd/ppp-down
@@ -0,0 +1,13 @@
+#!/bin/sh
+PPP_IPPARAM="$6"
+
+. /lib/netifd/netifd-proto.sh
+proto_init_update "$IFNAME" 0
+proto_send_update "$PPP_IPPARAM"
+
+[ -d /etc/ppp/ip-down.d ] && {
+ for SCRIPT in /etc/ppp/ip-down.d/*
+ do
+ [ -x "$SCRIPT" ] && "$SCRIPT" "$@"
+ done
+}
diff --git a/package/ppp/files/lib/netifd/ppp-up b/package/ppp/files/lib/netifd/ppp-up
new file mode 100755
index 000000000..8ab8c9dd1
--- /dev/null
+++ b/package/ppp/files/lib/netifd/ppp-up
@@ -0,0 +1,22 @@
+#!/bin/sh
+PPP_IPPARAM="$6"
+
+. /lib/netifd/netifd-proto.sh
+proto_init_update "$IFNAME" 1 1
+proto_set_keep 1
+[ -n "$PPP_IPPARAM" ] && {
+ [ -n "$IPLOCAL" ] && proto_add_ipv4_address "$IPLOCAL" 32
+ [ -n "$IPREMOTE" ] && proto_add_ipv4_route 0.0.0.0 0 "$IPREMOTE"
+ [ -n "$LLLOCAL" ] && proto_add_ipv6_address "$LLLOCAL" 128
+ [ -n "$LLREMOTE" ] && proto_add_ipv6_route "::0" 0 "$LLREMOTE"
+ [ -n "$DNS1" ] && proto_add_dns_server "$DNS1"
+ [ -n "$DNS2" -a "$DNS1" != "$DNS2" ] && proto_add_dns_server "$DNS2"
+}
+proto_send_update "$PPP_IPPARAM"
+
+[ -d /etc/ppp/ip-up.d ] && {
+ for SCRIPT in /etc/ppp/ip-up.d/*
+ do
+ [ -x "$SCRIPT" ] && "$SCRIPT" "$@"
+ done
+}
diff --git a/package/ppp/files/ppp.sh b/package/ppp/files/ppp.sh
new file mode 100755
index 000000000..7e9b8dd85
--- /dev/null
+++ b/package/ppp/files/ppp.sh
@@ -0,0 +1,222 @@
+#!/bin/sh
+
+[ -x /usr/sbin/pppd ] || exit 0
+
+[ -n "$INCLUDE_ONLY" ] || {
+ . /lib/functions.sh
+ . ../netifd-proto.sh
+ init_proto "$@"
+}
+
+ppp_generic_init_config() {
+ proto_config_add_string "username"
+ proto_config_add_string "password"
+ proto_config_add_string "keepalive"
+ proto_config_add_int "demand"
+ proto_config_add_string "pppd_options"
+ proto_config_add_string "connect"
+ proto_config_add_string "disconnect"
+ proto_config_add_boolean "defaultroute"
+ proto_config_add_boolean "peerdns"
+ proto_config_add_boolean "ipv6"
+ proto_config_add_boolean "authfail"
+ proto_config_add_int "mtu"
+}
+
+ppp_generic_setup() {
+ local config="$1"; shift
+
+ json_get_vars ipv6 peerdns defaultroute demand keepalive username password pppd_options
+ [ "$ipv6" = 1 ] || ipv6=""
+ [ "$peerdns" = 0 ] && peerdns="" || peerdns="1"
+ if [ "$defaultroute" = 1 ]; then
+ defaultroute="defaultroute replacedefaultroute";
+ else
+ defaultroute="nodefaultroute"
+ fi
+ if [ "${demand:-0}" -gt 0 ]; then
+ demand="precompiled-active-filter /etc/ppp/filter demand idle $demand"
+ else
+ demand="persist"
+ fi
+
+ [ -n "$mtu" ] || json_get_var mtu mtu
+
+ local interval="${keepalive##*[, ]}"
+ [ "$interval" != "$keepalive" ] || interval=5
+ [ -n "$connect" ] || json_get_var connect connect
+ [ -n "$disconnect" ] || json_get_var disconnect disconnect
+
+ proto_run_command "$config" /usr/sbin/pppd \
+ nodetach ipparam "$config" \
+ ifname "${proto:-ppp}-$config" \
+ ${keepalive:+lcp-echo-interval $interval lcp-echo-failure ${keepalive%%[, ]*}} \
+ ${ipv6:++ipv6} $defaultroute \
+ ${peerdns:+usepeerdns} \
+ $demand maxfail 1 \
+ ${username:+user "$username" password "$password"} \
+ ${connect:+connect "$connect"} \
+ ${disconnect:+disconnect "$disconnect"} \
+ ip-up-script /lib/netifd/ppp-up \
+ ipv6-up-script /lib/netifd/ppp-up \
+ ip-down-script /lib/netifd/ppp-down \
+ ipv6-down-script /lib/netifd/ppp-down \
+ ${mtu:+mtu $mtu mru $mtu} \
+ $pppd_options "$@"
+}
+
+ppp_generic_teardown() {
+ local interface="$1"
+
+ case "$ERROR" in
+ 11|19)
+ proto_notify_error "$interface" AUTH_FAILED
+ json_get_var authfail authfail
+ if [ "${authfail:-0}" -gt 0 ]; then
+ proto_block_restart "$interface"
+ fi
+ ;;
+ 2)
+ proto_notify_error "$interface" INVALID_OPTIONS
+ proto_block_restart "$interface"
+ ;;
+ esac
+ proto_kill_command "$interface"
+}
+
+# PPP on serial device
+
+proto_ppp_init_config() {
+ proto_config_add_string "device"
+ ppp_generic_init_config
+ no_device=1
+ available=1
+}
+
+proto_ppp_setup() {
+ local config="$1"
+
+ json_get_var device device
+ ppp_generic_setup "$config" "$device"
+}
+
+proto_ppp_teardown() {
+ ppp_generic_teardown "$@"
+}
+
+proto_pppoe_init_config() {
+ ppp_generic_init_config
+ proto_config_add_string "ac"
+ proto_config_add_string "service"
+}
+
+proto_pppoe_setup() {
+ local config="$1"
+ local iface="$2"
+
+ for module in slhc ppp_generic pppox pppoe; do
+ /sbin/insmod $module 2>&- >&-
+ done
+
+ json_get_var mtu mtu
+ mtu="${mtu:-1492}"
+
+ json_get_var ac ac
+ json_get_var service service
+
+ ppp_generic_setup "$config" \
+ plugin rp-pppoe.so \
+ ${ac:+rp_pppoe_ac "$ac"} \
+ ${service:+rp_pppoe_service "$service"} \
+ "nic-$iface"
+}
+
+proto_pppoe_teardown() {
+ ppp_generic_teardown "$@"
+}
+
+proto_pppoa_init_config() {
+ ppp_generic_init_config
+ proto_config_add_int "atmdev"
+ proto_config_add_int "vci"
+ proto_config_add_int "vpi"
+ proto_config_add_string "encaps"
+ no_device=1
+ available=1
+}
+
+proto_pppoa_setup() {
+ local config="$1"
+ local iface="$2"
+
+ for module in slhc ppp_generic pppox pppoatm; do
+ /sbin/insmod $module 2>&- >&-
+ done
+
+ json_get_vars atmdev vci vpi encaps
+
+ case "$encaps" in
+ 1|vc) encaps="vc-encaps" ;;
+ *) encaps="llc-encaps" ;;
+ esac
+
+ ppp_generic_setup "$config" \
+ plugin pppoatm.so \
+ ${atmdev:+$atmdev.}${vpi:-8}.${vci:-35} \
+ ${encaps}
+}
+
+proto_pppoa_teardown() {
+ ppp_generic_teardown "$@"
+}
+
+proto_pptp_init_config() {
+ ppp_generic_init_config
+ proto_config_add_string "server"
+ available=1
+ no_device=1
+}
+
+proto_pptp_setup() {
+ local config="$1"
+ local iface="$2"
+
+ local ip serv_addr server
+ json_get_var server server && {
+ for ip in $(resolveip -t 5 "$server"); do
+ ( proto_add_host_dependency "$config" "$ip" )
+ serv_addr=1
+ done
+ }
+ [ -n "$serv_addr" ] || {
+ echo "Could not resolve server address"
+ sleep 5
+ proto_setup_failed "$config"
+ exit 1
+ }
+
+ local load
+ for module in slhc ppp_generic ppp_async ppp_mppe ip_gre gre pptp; do
+ grep -q "$module" /proc/modules && continue
+ /sbin/insmod $module 2>&- >&-
+ load=1
+ done
+ [ "$load" = "1" ] && sleep 1
+
+ ppp_generic_setup "$config" \
+ plugin pptp.so \
+ pptp_server $server \
+ file /etc/ppp/options.pptp
+}
+
+proto_pptp_teardown() {
+ ppp_generic_teardown "$@"
+}
+
+[ -n "$INCLUDE_ONLY" ] || {
+ add_protocol ppp
+ [ -f /usr/lib/pppd/*/rp-pppoe.so ] && add_protocol pppoe
+ [ -f /usr/lib/pppd/*/pppoatm.so ] && add_protocol pppoa
+ [ -f /usr/lib/pppd/*/pptp.so ] && add_protocol pptp
+}
+
diff --git a/package/ppp/patches/010-use_target_for_configure.patch b/package/ppp/patches/010-use_target_for_configure.patch
new file mode 100644
index 000000000..aff0df67f
--- /dev/null
+++ b/package/ppp/patches/010-use_target_for_configure.patch
@@ -0,0 +1,24 @@
+configure: Allow overriding uname results
+
+In a cross compile setting it makes no sense to rely on the "uname" values
+reported by the build host system. This patch allows overriding the
+"uname -r", "uname -s" and "uname -m" results with the "UNAME_R", "UNAME_S"
+and "UNAME_M" environment variables.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/configure
++++ b/configure
+@@ -8,9 +8,9 @@ SYSCONF=/etc
+ # if [ -d /NextApps ]; then
+ # system="NeXTStep"
+ # else
+- system=`uname -s`
+- release=`uname -r`
+- arch=`uname -m`
++ system=${UNAME_S:-`uname -s`}
++ release=${UNAME_R:-`uname -r`}
++ arch=${UNAME_M:-`uname -m`}
+ # fi
+ state="unknown"
+
diff --git a/package/ppp/patches/100-debian_ip-ip_option.patch b/package/ppp/patches/100-debian_ip-ip_option.patch
new file mode 100644
index 000000000..ca43cb278
--- /dev/null
+++ b/package/ppp/patches/100-debian_ip-ip_option.patch
@@ -0,0 +1,96 @@
+pppd: Allow specifying ip-up and ip-down scripts
+
+This patch implements the "ip-up-script" and "ip-down-script" options which
+allow to specify the path of the ip-up and ip-down scripts to call.
+
+These options default to _PATH_IPUP and _PATH_IPDOWN to retain the
+existing behaviour.
+
+The patch originated from the Debian project.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/ipcp.c
++++ b/pppd/ipcp.c
+@@ -1939,7 +1939,7 @@ ipcp_up(f)
+ */
+ if (ipcp_script_state == s_down && ipcp_script_pid == 0) {
+ ipcp_script_state = s_up;
+- ipcp_script(_PATH_IPUP, 0);
++ ipcp_script(path_ipup, 0);
+ }
+ }
+
+@@ -1989,7 +1989,7 @@ ipcp_down(f)
+ /* Execute the ip-down script */
+ if (ipcp_script_state == s_up && ipcp_script_pid == 0) {
+ ipcp_script_state = s_down;
+- ipcp_script(_PATH_IPDOWN, 0);
++ ipcp_script(path_ipdown, 0);
+ }
+ }
+
+@@ -2043,13 +2043,13 @@ ipcp_script_done(arg)
+ case s_up:
+ if (ipcp_fsm[0].state != OPENED) {
+ ipcp_script_state = s_down;
+- ipcp_script(_PATH_IPDOWN, 0);
++ ipcp_script(path_ipdown, 0);
+ }
+ break;
+ case s_down:
+ if (ipcp_fsm[0].state == OPENED) {
+ ipcp_script_state = s_up;
+- ipcp_script(_PATH_IPUP, 0);
++ ipcp_script(path_ipup, 0);
+ }
+ break;
+ }
+--- a/pppd/main.c
++++ b/pppd/main.c
+@@ -316,6 +316,9 @@ main(argc, argv)
+ struct protent *protp;
+ char numbuf[16];
+
++ strlcpy(path_ipup, _PATH_IPUP, sizeof(path_ipup));
++ strlcpy(path_ipdown, _PATH_IPDOWN, sizeof(path_ipdown));
++
+ link_stats_valid = 0;
+ new_phase(PHASE_INITIALIZE);
+
+--- a/pppd/options.c
++++ b/pppd/options.c
+@@ -113,6 +113,8 @@ char linkname[MAXPATHLEN]; /* logical na
+ bool tune_kernel; /* may alter kernel settings */
+ int connect_delay = 1000; /* wait this many ms after connect script */
+ int req_unit = -1; /* requested interface unit */
++char path_ipup[MAXPATHLEN]; /* pathname of ip-up script */
++char path_ipdown[MAXPATHLEN];/* pathname of ip-down script */
+ bool multilink = 0; /* Enable multilink operation */
+ char *bundle_name = NULL; /* bundle name for multilink */
+ bool dump_options; /* print out option values */
+@@ -281,6 +283,13 @@ option_t general_options[] = {
+ "Number of seconds to wait for child processes at exit",
+ OPT_PRIO },
+
++ { "ip-up-script", o_string, path_ipup,
++ "Set pathname of ip-up script",
++ OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN },
++ { "ip-down-script", o_string, path_ipdown,
++ "Set pathname of ip-down script",
++ OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN },
++
+ #ifdef HAVE_MULTILINK
+ { "multilink", o_bool, &multilink,
+ "Enable multilink operation", OPT_PRIO | 1 },
+--- a/pppd/pppd.h
++++ b/pppd/pppd.h
+@@ -313,6 +313,8 @@ extern bool tune_kernel; /* May alter ke
+ extern int connect_delay; /* Time to delay after connect script */
+ extern int max_data_rate; /* max bytes/sec through charshunt */
+ extern int req_unit; /* interface unit number to use */
++extern char path_ipup[MAXPATHLEN]; /* pathname of ip-up script */
++extern char path_ipdown[MAXPATHLEN]; /* pathname of ip-down script */
+ extern bool multilink; /* enable multilink operation */
+ extern bool noendpoint; /* don't send or accept endpt. discrim. */
+ extern char *bundle_name; /* bundle name for multilink */
diff --git a/package/ppp/patches/101-debian_close_dev_ppp.patch b/package/ppp/patches/101-debian_close_dev_ppp.patch
new file mode 100644
index 000000000..232b10b52
--- /dev/null
+++ b/package/ppp/patches/101-debian_close_dev_ppp.patch
@@ -0,0 +1,28 @@
+pppd: Close already open ppp descriptors
+
+When using the kernel PPPoE driver in conjunction with the "persist" option,
+the already open descriptor to /dev/ppp is not closed when the link is
+reestablished. This eventually leads to high CPU load because the stray
+descriptors are always reported as ready by select().
+
+This patch closes the descriptor if it is already open when establishing a
+new connection. It originated from the Debian project.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/sys-linux.c
++++ b/pppd/sys-linux.c
+@@ -453,6 +453,13 @@ int generic_establish_ppp (int fd)
+ if (new_style_driver) {
+ int flags;
+
++ /* if a ppp_fd is already open, close it first */
++ if(ppp_fd > 0) {
++ close(ppp_fd);
++ remove_fd(ppp_fd);
++ ppp_fd = -1;
++ }
++
+ /* Open an instance of /dev/ppp and connect the channel to it */
+ if (ioctl(fd, PPPIOCGCHAN, &chindex) == -1) {
+ error("Couldn't get channel number: %m");
diff --git a/package/ppp/patches/103-debian_fix_link_pidfile.patch b/package/ppp/patches/103-debian_fix_link_pidfile.patch
new file mode 100644
index 000000000..c8a23edd6
--- /dev/null
+++ b/package/ppp/patches/103-debian_fix_link_pidfile.patch
@@ -0,0 +1,23 @@
+pppd: Fix creation of linkpidfile
+
+When pppd is run without "nodetach" or with "updetach", the linkpidfile is
+never created. The call to create_linkpidfile() is protected by a check for
+linkpidfile[0] but this is only filled in when create_linkpidfile() is called.
+
+This patch changes to code to allways uncondiationally call
+create_linkpidfile(), it originated from the Debian project.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/main.c
++++ b/pppd/main.c
+@@ -773,8 +773,7 @@ detach()
+ /* update pid files if they have been written already */
+ if (pidfilename[0])
+ create_pidfile(pid);
+- if (linkpidfile[0])
+- create_linkpidfile(pid);
++ create_linkpidfile(pid);
+ exit(0); /* parent dies */
+ }
+ setsid();
diff --git a/package/ppp/patches/105-debian_demand.patch b/package/ppp/patches/105-debian_demand.patch
new file mode 100644
index 000000000..c27865698
--- /dev/null
+++ b/package/ppp/patches/105-debian_demand.patch
@@ -0,0 +1,172 @@
+--- a/pppd/demand.c
++++ b/pppd/demand.c
+@@ -36,6 +36,8 @@
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <netdb.h>
++#include <unistd.h>
++#include <syslog.h>
+ #include <sys/param.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
+@@ -43,6 +45,8 @@
+ #include <sys/resource.h>
+ #include <sys/stat.h>
+ #include <sys/socket.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
+ #ifdef PPP_FILTER
+ #include <pcap-bpf.h>
+ #endif
+@@ -221,6 +225,14 @@ loop_chars(p, n)
+ int c, rv;
+
+ rv = 0;
++
++/* check for synchronous connection... */
++
++ if ( (p[0] == 0xFF) && (p[1] == 0x03) ) {
++ rv = loop_frame(p,n);
++ return rv;
++ }
++
+ for (; n > 0; --n) {
+ c = *p++;
+ if (c == PPP_FLAG) {
+@@ -299,17 +311,102 @@ loop_frame(frame, len)
+ * loopback, now that the real serial link is up.
+ */
+ void
+-demand_rexmit(proto)
++demand_rexmit(proto, newip)
+ int proto;
++ u_int32_t newip;
+ {
+ struct packet *pkt, *prev, *nextpkt;
++ unsigned short checksum;
++ unsigned short pkt_checksum = 0;
++ unsigned iphdr;
++ struct timeval tv;
++ char cv = 0;
++ char ipstr[16];
+
+ prev = NULL;
+ pkt = pend_q;
+ pend_q = NULL;
++ tv.tv_sec = 1;
++ tv.tv_usec = 0;
++ select(0,NULL,NULL,NULL,&tv); /* Sleep for 1 Seconds */
+ for (; pkt != NULL; pkt = nextpkt) {
+ nextpkt = pkt->next;
+ if (PPP_PROTOCOL(pkt->data) == proto) {
++ if ( (proto == PPP_IP) && newip ) {
++ /* Get old checksum */
++
++ iphdr = (pkt->data[4] & 15) << 2;
++ checksum = *((unsigned short *) (pkt->data+14));
++ if (checksum == 0xFFFF) {
++ checksum = 0;
++ }
++
++
++ if (pkt->data[13] == 17) {
++ pkt_checksum = *((unsigned short *) (pkt->data+10+iphdr));
++ if (pkt_checksum) {
++ cv = 1;
++ if (pkt_checksum == 0xFFFF) {
++ pkt_checksum = 0;
++ }
++ }
++ else {
++ cv = 0;
++ }
++ }
++
++ if (pkt->data[13] == 6) {
++ pkt_checksum = *((unsigned short *) (pkt->data+20+iphdr));
++ cv = 1;
++ if (pkt_checksum == 0xFFFF) {
++ pkt_checksum = 0;
++ }
++ }
++
++ /* Delete old Source-IP-Address */
++ checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
++ checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
++
++ pkt_checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
++ pkt_checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
++
++ /* Change Source-IP-Address */
++ * ((u_int32_t *) (pkt->data + 16)) = newip;
++
++ /* Add new Source-IP-Address */
++ checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
++ checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
++
++ pkt_checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
++ pkt_checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
++
++ /* Write new checksum */
++ if (!checksum) {
++ checksum = 0xFFFF;
++ }
++ *((unsigned short *) (pkt->data+14)) = checksum;
++ if (pkt->data[13] == 6) {
++ *((unsigned short *) (pkt->data+20+iphdr)) = pkt_checksum;
++ }
++ if (cv && (pkt->data[13] == 17) ) {
++ *((unsigned short *) (pkt->data+10+iphdr)) = pkt_checksum;
++ }
++
++ /* Log Packet */
++ strcpy(ipstr,inet_ntoa(*( (struct in_addr *) (pkt->data+16))));
++ if (pkt->data[13] == 1) {
++ syslog(LOG_INFO,"Open ICMP %s -> %s\n",
++ ipstr,
++ inet_ntoa(*( (struct in_addr *) (pkt->data+20))));
++ } else {
++ syslog(LOG_INFO,"Open %s %s:%d -> %s:%d\n",
++ pkt->data[13] == 6 ? "TCP" : "UDP",
++ ipstr,
++ ntohs(*( (short *) (pkt->data+iphdr+4))),
++ inet_ntoa(*( (struct in_addr *) (pkt->data+20))),
++ ntohs(*( (short *) (pkt->data+iphdr+6))));
++ }
++ }
+ output(0, pkt->data, pkt->length);
+ free(pkt);
+ } else {
+--- a/pppd/ipcp.c
++++ b/pppd/ipcp.c
+@@ -1864,7 +1864,7 @@ ipcp_up(f)
+ proxy_arp_set[f->unit] = 1;
+
+ }
+- demand_rexmit(PPP_IP);
++ demand_rexmit(PPP_IP,go->ouraddr);
+ sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
+
+ } else {
+--- a/pppd/ipv6cp.c
++++ b/pppd/ipv6cp.c
+@@ -1232,7 +1232,7 @@ ipv6cp_up(f)
+ }
+
+ }
+- demand_rexmit(PPP_IPV6);
++ demand_rexmit(PPP_IPV6,0);
+ sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS);
+
+ } else {
+--- a/pppd/pppd.h
++++ b/pppd/pppd.h
+@@ -566,7 +566,7 @@ void demand_conf __P((void)); /* config
+ void demand_block __P((void)); /* set all NPs to queue up packets */
+ void demand_unblock __P((void)); /* set all NPs to pass packets */
+ void demand_discard __P((void)); /* set all NPs to discard packets */
+-void demand_rexmit __P((int)); /* retransmit saved frames for an NP */
++void demand_rexmit __P((int, u_int32_t)); /* retransmit saved frames for an NP*/
+ int loop_chars __P((unsigned char *, int)); /* process chars from loopback */
+ int loop_frame __P((unsigned char *, int)); /* should we bring link up? */
+
diff --git a/package/ppp/patches/106-debian_stripMSdomain.patch b/package/ppp/patches/106-debian_stripMSdomain.patch
new file mode 100644
index 000000000..86af1ef41
--- /dev/null
+++ b/package/ppp/patches/106-debian_stripMSdomain.patch
@@ -0,0 +1,47 @@
+pppd: Implement option to strip domain part from MS CHAP response
+
+This patch implements a new boolean option "chapms-strip-domain" which
+strips the leading domain part of the username in a received MS Chap
+response.
+
+When the option is set, all leading chars up to and including the last
+backslash in the username are stripped. The option defaults to false.
+
+The patch originated from the Debian project.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/chap-new.c
++++ b/pppd/chap-new.c
+@@ -58,6 +58,7 @@ int (*chap_verify_hook)(char *name, char
+ int chap_timeout_time = 3;
+ int chap_max_transmits = 10;
+ int chap_rechallenge_time = 0;
++int chapms_strip_domain = 0;
+
+ /*
+ * Command-line options.
+@@ -69,6 +70,8 @@ static option_t chap_option_list[] = {
+ "Set max #xmits for challenge", OPT_PRIO },
+ { "chap-interval", o_int, &chap_rechallenge_time,
+ "Set interval for rechallenge", OPT_PRIO },
++ { "chapms-strip-domain", o_bool, &chapms_strip_domain,
++ "Strip the domain prefix before the Username", 1 },
+ { NULL }
+ };
+
+@@ -336,6 +339,14 @@ chap_handle_response(struct chap_server_
+ /* Null terminate and clean remote name. */
+ slprintf(rname, sizeof(rname), "%.*v", len, name);
+ name = rname;
++
++ /* strip the MS domain name */
++ if (chapms_strip_domain && strrchr(rname, '\\')) {
++ char tmp[MAXNAMELEN+1];
++
++ strcpy(tmp, strrchr(rname, '\\') + 1);
++ strcpy(rname, tmp);
++ }
+ }
+
+ if (chap_verify_hook)
diff --git a/package/ppp/patches/107-debian_pppoatm_wildcard.patch b/package/ppp/patches/107-debian_pppoatm_wildcard.patch
new file mode 100644
index 000000000..eaad2cdaa
--- /dev/null
+++ b/package/ppp/patches/107-debian_pppoatm_wildcard.patch
@@ -0,0 +1,25 @@
+pppoatm: Allow wildcard ATM devices
+
+When operating pppd's pppoatm plugin with an USB ADSL modem, e.g. an
+Alcatel Speedtouch, the ATM device number might change when the modem is
+reconnected to the USB port or when the host controller resets the USB
+device.
+
+This patch allows to specify the ATM device as wildcard which gives
+enough flexibility to cope with changing device names.
+
+The patch originated from the Debain project.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/plugins/pppoatm/pppoatm.c
++++ b/pppd/plugins/pppoatm/pppoatm.c
+@@ -75,7 +75,7 @@ static int setdevname_pppoatm(const char
+ //info("PPPoATM setdevname_pppoatm: '%s'", cp);
+ memset(&addr, 0, sizeof addr);
+ if (text2atm(cp, (struct sockaddr *) &addr, sizeof(addr),
+- T2A_PVC | T2A_NAME) < 0) {
++ T2A_PVC | T2A_NAME | T2A_WILDCARD) < 0) {
+ if(doit)
+ info("atm does not recognize: %s", cp);
+ return 0;
diff --git a/package/ppp/patches/110-debian_defaultroute.patch b/package/ppp/patches/110-debian_defaultroute.patch
new file mode 100644
index 000000000..41d28909b
--- /dev/null
+++ b/package/ppp/patches/110-debian_defaultroute.patch
@@ -0,0 +1,313 @@
+pppd: Add "replacedefaultroute" and "noreplacedefaultroute" options
+
+This patch implements two new options, "replacedefaultroute" to replace any
+existing system default route when specified and "noreplacedefaultroute" to
+disable the "replacedefaultroute" option, which is useful in multi user
+environments where the administrator wants to allow users to dial pppd
+connections but not allow them to change the system default route.
+
+The patch originated from the Debian project.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/ipcp.c
++++ b/pppd/ipcp.c
+@@ -198,6 +198,14 @@ static option_t ipcp_option_list[] = {
+ "disable defaultroute option", OPT_ALIAS | OPT_A2CLR,
+ &ipcp_wantoptions[0].default_route },
+
++ { "replacedefaultroute", o_bool,
++ &ipcp_wantoptions[0].replace_default_route,
++ "Replace default route", 1
++ },
++ { "noreplacedefaultroute", o_bool,
++ &ipcp_allowoptions[0].replace_default_route,
++ "Never replace default route", OPT_A2COPY,
++ &ipcp_wantoptions[0].replace_default_route },
+ { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp,
+ "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp },
+ { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
+@@ -271,7 +279,7 @@ struct protent ipcp_protent = {
+ ip_active_pkt
+ };
+
+-static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t));
++static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t, bool));
+ static void ipcp_script __P((char *, int)); /* Run an up/down script */
+ static void ipcp_script_done __P((void *));
+
+@@ -1742,7 +1750,8 @@ ip_demand_conf(u)
+ if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
+ return 0;
+ if (wo->default_route)
+- if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
++ if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr,
++ wo->replace_default_route))
+ default_route_set[u] = 1;
+ if (wo->proxy_arp)
+ if (sifproxyarp(u, wo->hisaddr))
+@@ -1830,7 +1839,8 @@ ipcp_up(f)
+ */
+ if (demand) {
+ if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
+- ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr);
++ ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr,
++ wo->replace_default_route);
+ if (go->ouraddr != wo->ouraddr) {
+ warn("Local IP address changed to %I", go->ouraddr);
+ script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0);
+@@ -1855,7 +1865,8 @@ ipcp_up(f)
+
+ /* assign a default route through the interface if required */
+ if (ipcp_wantoptions[f->unit].default_route)
+- if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
++ if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
++ wo->replace_default_route))
+ default_route_set[f->unit] = 1;
+
+ /* Make a proxy ARP entry if requested. */
+@@ -1905,7 +1916,8 @@ ipcp_up(f)
+
+ /* assign a default route through the interface if required */
+ if (ipcp_wantoptions[f->unit].default_route)
+- if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
++ if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
++ wo->replace_default_route))
+ default_route_set[f->unit] = 1;
+
+ /* Make a proxy ARP entry if requested. */
+@@ -1983,7 +1995,7 @@ ipcp_down(f)
+ sifnpmode(f->unit, PPP_IP, NPMODE_DROP);
+ sifdown(f->unit);
+ ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr,
+- ipcp_hisoptions[f->unit].hisaddr);
++ ipcp_hisoptions[f->unit].hisaddr, 0);
+ }
+
+ /* Execute the ip-down script */
+@@ -1999,16 +2011,25 @@ ipcp_down(f)
+ * proxy arp entries, etc.
+ */
+ static void
+-ipcp_clear_addrs(unit, ouraddr, hisaddr)
++ipcp_clear_addrs(unit, ouraddr, hisaddr, replacedefaultroute)
+ int unit;
+ u_int32_t ouraddr; /* local address */
+ u_int32_t hisaddr; /* remote address */
++ bool replacedefaultroute;
+ {
+ if (proxy_arp_set[unit]) {
+ cifproxyarp(unit, hisaddr);
+ proxy_arp_set[unit] = 0;
+ }
+- if (default_route_set[unit]) {
++ /* If replacedefaultroute, sifdefaultroute will be called soon
++ * with replacedefaultroute set and that will overwrite the current
++ * default route. This is the case only when doing demand, otherwise
++ * during demand, this cifdefaultroute would restore the old default
++ * route which is not what we want in this case. In the non-demand
++ * case, we'll delete the default route and restore the old if there
++ * is one saved by an sifdefaultroute with replacedefaultroute.
++ */
++ if (!replacedefaultroute && default_route_set[unit]) {
+ cifdefaultroute(unit, ouraddr, hisaddr);
+ default_route_set[unit] = 0;
+ }
+--- a/pppd/ipcp.h
++++ b/pppd/ipcp.h
+@@ -70,6 +70,7 @@ typedef struct ipcp_options {
+ bool old_addrs; /* Use old (IP-Addresses) option? */
+ bool req_addr; /* Ask peer to send IP address? */
+ bool default_route; /* Assign default route through interface? */
++ bool replace_default_route; /* Replace default route through interface? */
+ bool proxy_arp; /* Make proxy ARP entry for peer? */
+ bool neg_vj; /* Van Jacobson Compression? */
+ bool old_vj; /* use old (short) form of VJ option? */
+--- a/pppd/pppd.8
++++ b/pppd/pppd.8
+@@ -121,6 +121,11 @@ the gateway, when IPCP negotiation is su
+ This entry is removed when the PPP connection is broken. This option
+ is privileged if the \fInodefaultroute\fR option has been specified.
+ .TP
++.B replacedefaultroute
++This option is a flag to the defaultroute option. If defaultroute is
++set and this flag is also set, pppd replaces an existing default route
++with the new default route.
++.TP
+ .B disconnect \fIscript
+ Execute the command specified by \fIscript\fR, by passing it to a
+ shell, after
+@@ -717,7 +722,12 @@ disable both forms of hardware flow cont
+ .TP
+ .B nodefaultroute
+ Disable the \fIdefaultroute\fR option. The system administrator who
+-wishes to prevent users from creating default routes with pppd
++wishes to prevent users from adding a default route with pppd
++can do so by placing this option in the /etc/ppp/options file.
++.TP
++.B noreplacedefaultroute
++Disable the \fIreplacedefaultroute\fR option. The system administrator who
++wishes to prevent users from replacing a default route with pppd
+ can do so by placing this option in the /etc/ppp/options file.
+ .TP
+ .B nodeflate
+--- a/pppd/pppd.h
++++ b/pppd/pppd.h
+@@ -645,7 +645,7 @@ int sif6addr __P((int, eui64_t, eui64_t
+ int cif6addr __P((int, eui64_t, eui64_t));
+ /* Remove an IPv6 address from i/f */
+ #endif
+-int sifdefaultroute __P((int, u_int32_t, u_int32_t));
++int sifdefaultroute __P((int, u_int32_t, u_int32_t, bool replace_default_rt));
+ /* Create default route through i/f */
+ int cifdefaultroute __P((int, u_int32_t, u_int32_t));
+ /* Delete default route through i/f */
+--- a/pppd/sys-linux.c
++++ b/pppd/sys-linux.c
+@@ -206,6 +206,8 @@ static unsigned char inbuf[512]; /* buff
+
+ static int if_is_up; /* Interface has been marked up */
+ static int have_default_route; /* Gateway for default route added */
++static struct rtentry old_def_rt; /* Old default route */
++static int default_rt_repl_rest; /* replace and restore old default rt */
+ static u_int32_t proxy_arp_addr; /* Addr for proxy arp entry added */
+ static char proxy_arp_dev[16]; /* Device for proxy arp entry */
+ static u_int32_t our_old_addr; /* for detecting address changes */
+@@ -1544,6 +1546,9 @@ static int read_route_table(struct rtent
+ p = NULL;
+ }
+
++ SET_SA_FAMILY (rt->rt_dst, AF_INET);
++ SET_SA_FAMILY (rt->rt_gateway, AF_INET);
++
+ SIN_ADDR(rt->rt_dst) = strtoul(cols[route_dest_col], NULL, 16);
+ SIN_ADDR(rt->rt_gateway) = strtoul(cols[route_gw_col], NULL, 16);
+ SIN_ADDR(rt->rt_genmask) = strtoul(cols[route_mask_col], NULL, 16);
+@@ -1613,20 +1618,51 @@ int have_route_to(u_int32_t addr)
+ /********************************************************************
+ *
+ * sifdefaultroute - assign a default route through the address given.
+- */
+-
+-int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
+-{
+- struct rtentry rt;
+-
+- if (defaultroute_exists(&rt) && strcmp(rt.rt_dev, ifname) != 0) {
+- if (rt.rt_flags & RTF_GATEWAY)
+- error("not replacing existing default route via %I",
+- SIN_ADDR(rt.rt_gateway));
+- else
++ *
++ * If the global default_rt_repl_rest flag is set, then this function
++ * already replaced the original system defaultroute with some other
++ * route and it should just replace the current defaultroute with
++ * another one, without saving the current route. Use: demand mode,
++ * when pppd sets first a defaultroute it it's temporary ppp0 addresses
++ * and then changes the temporary addresses to the addresses for the real
++ * ppp connection when it has come up.
++ */
++
++int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway, bool replace)
++{
++ struct rtentry rt, tmp_rt;
++ struct rtentry *del_rt = NULL;
++
++ if (default_rt_repl_rest) {
++ /* We have already reclaced the original defaultroute, if we
++ are called again, we will delete the current default route
++ and set the new default route in this function.
++ - this is normally only the case the doing demand: */
++ if (defaultroute_exists(&tmp_rt))
++ del_rt = &tmp_rt;
++ } else if (defaultroute_exists(&old_def_rt) &&
++ strcmp(old_def_rt.rt_dev, ifname) != 0) {
++ /* We did not yet replace an existing default route, let's
++ check if we should save and replace a default route: */
++ if (old_def_rt.rt_flags & RTF_GATEWAY) {
++ if (!replace) {
++ error("not replacing existing default route via %I",
++ SIN_ADDR(old_def_rt.rt_gateway));
++ return 0;
++ } else {
++ /* we need to copy rt_dev because we need it permanent too: */
++ char *tmp_dev = malloc(strlen(old_def_rt.rt_dev) + 1);
++ strcpy(tmp_dev, old_def_rt.rt_dev);
++ old_def_rt.rt_dev = tmp_dev;
++
++ notice("replacing old default route to %s [%I]",
++ old_def_rt.rt_dev, SIN_ADDR(old_def_rt.rt_gateway));
++ default_rt_repl_rest = 1;
++ del_rt = &old_def_rt;
++ }
++ } else
+ error("not replacing existing default route through %s",
+- rt.rt_dev);
+- return 0;
++ old_def_rt.rt_dev);
+ }
+
+ memset (&rt, 0, sizeof (rt));
+@@ -1641,10 +1677,16 @@ int sifdefaultroute (int unit, u_int32_t
+
+ rt.rt_flags = RTF_UP;
+ if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
+- if ( ! ok_error ( errno ))
++ if (!ok_error(errno))
+ error("default route ioctl(SIOCADDRT): %m");
+ return 0;
+ }
++ if (default_rt_repl_rest && del_rt)
++ if (ioctl(sock_fd, SIOCDELRT, del_rt) < 0) {
++ if (!ok_error(errno))
++ error("del old default route ioctl(SIOCDELRT): %m");
++ return 0;
++ }
+
+ have_default_route = 1;
+ return 1;
+@@ -1675,11 +1717,21 @@ int cifdefaultroute (int unit, u_int32_t
+ rt.rt_flags = RTF_UP;
+ if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
+ if (still_ppp()) {
+- if ( ! ok_error ( errno ))
++ if (!ok_error(errno))
+ error("default route ioctl(SIOCDELRT): %m");
+ return 0;
+ }
+ }
++ if (default_rt_repl_rest) {
++ notice("restoring old default route to %s [%I]",
++ old_def_rt.rt_dev, SIN_ADDR(old_def_rt.rt_gateway));
++ if (ioctl(sock_fd, SIOCADDRT, &old_def_rt) < 0) {
++ if (!ok_error(errno))
++ error("restore default route ioctl(SIOCADDRT): %m");
++ return 0;
++ }
++ default_rt_repl_rest = 0;
++ }
+
+ return 1;
+ }
+--- a/pppd/sys-solaris.c
++++ b/pppd/sys-solaris.c
+@@ -2036,12 +2036,18 @@ cifaddr(u, o, h)
+ * sifdefaultroute - assign a default route through the address given.
+ */
+ int
+-sifdefaultroute(u, l, g)
++sifdefaultroute(u, l, g, replace)
+ int u;
+ u_int32_t l, g;
++ bool replace;
+ {
+ struct rtentry rt;
+
++ if (replace) {
++ error("replacedefaultroute not supported on this platform");
++ return 0;
++ }
++
+ #if defined(__USLC__)
+ g = l; /* use the local address as gateway */
+ #endif
diff --git a/package/ppp/patches/120-debian_ipv6_updown_option.patch b/package/ppp/patches/120-debian_ipv6_updown_option.patch
new file mode 100644
index 000000000..c5457fa51
--- /dev/null
+++ b/package/ppp/patches/120-debian_ipv6_updown_option.patch
@@ -0,0 +1,95 @@
+pppd: Allow specifying ipv6-up and ipv6-down scripts
+
+This patch implements the "ipv6-up-script" and "ipv6-down-script" options
+which allow to specify the path of the ipv6-up and ipv6-down scripts to call.
+
+These options default to _PATH_IPV6UP and _PATH_IPV6DOWN to retain the
+existing behaviour.
+
+The patch originated from the Debian project.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/main.c
++++ b/pppd/main.c
+@@ -318,6 +318,8 @@ main(argc, argv)
+
+ strlcpy(path_ipup, _PATH_IPUP, sizeof(path_ipup));
+ strlcpy(path_ipdown, _PATH_IPDOWN, sizeof(path_ipdown));
++ strlcpy(path_ipv6up, _PATH_IPV6UP, sizeof(path_ipv6up));
++ strlcpy(path_ipv6down, _PATH_IPV6DOWN, sizeof(path_ipv6down));
+
+ link_stats_valid = 0;
+ new_phase(PHASE_INITIALIZE);
+--- a/pppd/options.c
++++ b/pppd/options.c
+@@ -115,6 +115,8 @@ int connect_delay = 1000; /* wait this m
+ int req_unit = -1; /* requested interface unit */
+ char path_ipup[MAXPATHLEN]; /* pathname of ip-up script */
+ char path_ipdown[MAXPATHLEN];/* pathname of ip-down script */
++char path_ipv6up[MAXPATHLEN]; /* pathname of ipv6-up script */
++char path_ipv6down[MAXPATHLEN];/* pathname of ipv6-down script */
+ bool multilink = 0; /* Enable multilink operation */
+ char *bundle_name = NULL; /* bundle name for multilink */
+ bool dump_options; /* print out option values */
+@@ -290,6 +292,13 @@ option_t general_options[] = {
+ "Set pathname of ip-down script",
+ OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN },
+
++ { "ipv6-up-script", o_string, path_ipv6up,
++ "Set pathname of ipv6-up script",
++ OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN },
++ { "ipv6-down-script", o_string, path_ipv6down,
++ "Set pathname of ipv6-down script",
++ OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN },
++
+ #ifdef HAVE_MULTILINK
+ { "multilink", o_bool, &multilink,
+ "Enable multilink operation", OPT_PRIO | 1 },
+--- a/pppd/ipv6cp.c
++++ b/pppd/ipv6cp.c
+@@ -1288,7 +1288,7 @@ ipv6cp_up(f)
+ */
+ if (ipv6cp_script_state == s_down && ipv6cp_script_pid == 0) {
+ ipv6cp_script_state = s_up;
+- ipv6cp_script(_PATH_IPV6UP);
++ ipv6cp_script(path_ipv6up);
+ }
+ }
+
+@@ -1339,7 +1339,7 @@ ipv6cp_down(f)
+ /* Execute the ipv6-down script */
+ if (ipv6cp_script_state == s_up && ipv6cp_script_pid == 0) {
+ ipv6cp_script_state = s_down;
+- ipv6cp_script(_PATH_IPV6DOWN);
++ ipv6cp_script(path_ipv6down);
+ }
+ }
+
+@@ -1382,13 +1382,13 @@ ipv6cp_script_done(arg)
+ case s_up:
+ if (ipv6cp_fsm[0].state != OPENED) {
+ ipv6cp_script_state = s_down;
+- ipv6cp_script(_PATH_IPV6DOWN);
++ ipv6cp_script(path_ipv6down);
+ }
+ break;
+ case s_down:
+ if (ipv6cp_fsm[0].state == OPENED) {
+ ipv6cp_script_state = s_up;
+- ipv6cp_script(_PATH_IPV6UP);
++ ipv6cp_script(path_ipv6up);
+ }
+ break;
+ }
+--- a/pppd/pppd.h
++++ b/pppd/pppd.h
+@@ -315,6 +315,8 @@ extern int max_data_rate; /* max bytes/s
+ extern int req_unit; /* interface unit number to use */
+ extern char path_ipup[MAXPATHLEN]; /* pathname of ip-up script */
+ extern char path_ipdown[MAXPATHLEN]; /* pathname of ip-down script */
++extern char path_ipv6up[MAXPATHLEN]; /* pathname of ipv6-up script */
++extern char path_ipv6down[MAXPATHLEN]; /* pathname of ipv6-down script */
+ extern bool multilink; /* enable multilink operation */
+ extern bool noendpoint; /* don't send or accept endpt. discrim. */
+ extern char *bundle_name; /* bundle name for multilink */
diff --git a/package/ppp/patches/200-makefile.patch b/package/ppp/patches/200-makefile.patch
new file mode 100644
index 000000000..9db908de8
--- /dev/null
+++ b/package/ppp/patches/200-makefile.patch
@@ -0,0 +1,55 @@
+pppd: tune Linux config defaults for OpenWrt
+
+This patch adjusts a number defaults to properly match the OpenWrt environment.
+It is not intended for upstream.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/Makefile.linux
++++ b/pppd/Makefile.linux
+@@ -48,7 +48,7 @@ MPPE=y
+ # Uncomment the next line to include support for PPP packet filtering.
+ # This requires that the libpcap library and headers be installed
+ # and that the kernel driver support PPP packet filtering.
+-FILTER=y
++#FILTER=y
+
+ # Uncomment the next line to enable multilink PPP (enabled by default)
+ # Linux distributions: Please leave multilink ENABLED in your builds
+@@ -58,11 +58,11 @@ HAVE_MULTILINK=y
+ # Uncomment the next line to enable the TDB database (enabled by default.)
+ # If you enable multilink, then TDB is automatically enabled also.
+ # Linux distributions: Please leave TDB ENABLED in your builds.
+-USE_TDB=y
++#USE_TDB=y
+
+-HAS_SHADOW=y
++#HAS_SHADOW=y
+ #USE_PAM=y
+-#HAVE_INET6=y
++HAVE_INET6=y
+
+ # Enable plugins
+ PLUGIN=y
+@@ -77,7 +77,7 @@ MAXOCTETS=y
+
+ INCLUDE_DIRS= -I../include
+
+-COMPILE_FLAGS= -DHAVE_PATHS_H -DIPX_CHANGE -DHAVE_MMAP
++COMPILE_FLAGS= -DHAVE_PATHS_H -DHAVE_MMAP
+
+ CFLAGS= $(COPTS) $(COMPILE_FLAGS) $(INCLUDE_DIRS) '-DDESTDIR="@DESTDIR@"'
+
+@@ -117,10 +117,10 @@ CFLAGS += -DHAS_SHADOW
+ #LIBS += -lshadow $(LIBS)
+ endif
+
+-ifneq ($(wildcard /usr/include/crypt.h),)
++#ifneq ($(wildcard /usr/include/crypt.h),)
+ CFLAGS += -DHAVE_CRYPT_H=1
+ LIBS += -lcrypt
+-endif
++#endif
+
+ ifdef NEEDDES
+ ifndef USE_CRYPT
diff --git a/package/ppp/patches/201-mppe_mppc_1.1.patch b/package/ppp/patches/201-mppe_mppc_1.1.patch
new file mode 100644
index 000000000..3edd11e7f
--- /dev/null
+++ b/package/ppp/patches/201-mppe_mppc_1.1.patch
@@ -0,0 +1,1495 @@
+pppd: add support for MPPE and MPPC encryption and compression protocols
+
+This is a forward ported version of ppp-2.4.3-mppe-mppc-1.1.patch.gz found on
+http://mppe-mppc.alphacron.de/ .
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/include/linux/ppp-comp.h
++++ b/include/linux/ppp-comp.h
+@@ -36,7 +36,7 @@
+ */
+
+ /*
+- * ==FILEVERSION 20020319==
++ * ==FILEVERSION 20020715==
+ *
+ * NOTE TO MAINTAINERS:
+ * If you modify this file at all, please set the above date.
+@@ -201,6 +201,33 @@ struct compressor {
+ #define CI_MPPE 18 /* config option for MPPE */
+ #define CILEN_MPPE 6 /* length of config option */
+
++/* MPPE/MPPC definitions by J.D.*/
++#define MPPE_STATELESS MPPE_H_BIT /* configuration bit H */
++#define MPPE_40BIT MPPE_L_BIT /* configuration bit L */
++#define MPPE_56BIT MPPE_M_BIT /* configuration bit M */
++#define MPPE_128BIT MPPE_S_BIT /* configuration bit S */
++#define MPPE_MPPC MPPE_C_BIT /* configuration bit C */
++
++/*
++ * Definitions for Stac LZS.
++ */
++
++#define CI_LZS 17 /* config option for Stac LZS */
++#define CILEN_LZS 5 /* length of config option */
++
++#define LZS_OVHD 4 /* max. LZS overhead */
++#define LZS_HIST_LEN 2048 /* LZS history size */
++#define LZS_MAX_CCOUNT 0x0FFF /* max. coherency counter value */
++
++#define LZS_MODE_NONE 0
++#define LZS_MODE_LCB 1
++#define LZS_MODE_CRC 2
++#define LZS_MODE_SEQ 3
++#define LZS_MODE_EXT 4
++
++#define LZS_EXT_BIT_FLUSHED 0x80 /* bit A */
++#define LZS_EXT_BIT_COMP 0x20 /* bit C */
++
+ /*
+ * Definitions for other, as yet unsupported, compression methods.
+ */
+--- a/include/net/ppp-comp.h
++++ b/include/net/ppp-comp.h
+@@ -168,6 +168,33 @@ struct compressor {
+ #define CI_MPPE 18 /* config option for MPPE */
+ #define CILEN_MPPE 6 /* length of config option */
+
++/* MPPE/MPPC definitions by J.D.*/
++#define MPPE_STATELESS MPPE_H_BIT /* configuration bit H */
++#define MPPE_40BIT MPPE_L_BIT /* configuration bit L */
++#define MPPE_56BIT MPPE_M_BIT /* configuration bit M */
++#define MPPE_128BIT MPPE_S_BIT /* configuration bit S */
++#define MPPE_MPPC MPPE_C_BIT /* configuration bit C */
++
++/*
++ * Definitions for Stac LZS.
++ */
++
++#define CI_LZS 17 /* config option for Stac LZS */
++#define CILEN_LZS 5 /* length of config option */
++
++#define LZS_OVHD 4 /* max. LZS overhead */
++#define LZS_HIST_LEN 2048 /* LZS history size */
++#define LZS_MAX_CCOUNT 0x0FFF /* max. coherency counter value */
++
++#define LZS_MODE_NONE 0
++#define LZS_MODE_LCB 1
++#define LZS_MODE_CRC 2
++#define LZS_MODE_SEQ 3
++#define LZS_MODE_EXT 4
++
++#define LZS_EXT_BIT_FLUSHED 0x80 /* bit A */
++#define LZS_EXT_BIT_COMP 0x20 /* bit C */
++
+ /*
+ * Definitions for other, as yet unsupported, compression methods.
+ */
+--- a/pppd/ccp.c
++++ b/pppd/ccp.c
+@@ -62,12 +62,10 @@ static int setdeflate __P((char **));
+ static char bsd_value[8];
+ static char deflate_value[8];
+
+-/*
+- * Option variables.
+- */
+ #ifdef MPPE
+-bool refuse_mppe_stateful = 1; /* Allow stateful mode? */
+-#endif
++static int setmppe(char **);
++static int setnomppe(void);
++#endif /* MPPE */
+
+ static option_t ccp_option_list[] = {
+ { "noccp", o_bool, &ccp_protent.enabled_flag,
+@@ -108,54 +106,36 @@ static option_t ccp_option_list[] = {
+ "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
+ &ccp_allowoptions[0].predictor_1 },
+
++ { "lzs", o_bool, &ccp_wantoptions[0].lzs,
++ "request Stac LZS", 1, &ccp_allowoptions[0].lzs, OPT_PRIO },
++ { "+lzs", o_bool, &ccp_wantoptions[0].lzs,
++ "request Stac LZS", 1, &ccp_allowoptions[0].lzs, OPT_ALIAS | OPT_PRIO },
++ { "nolzs", o_bool, &ccp_wantoptions[0].lzs,
++ "don't allow Stac LZS", OPT_PRIOSUB | OPT_A2CLR,
++ &ccp_allowoptions[0].lzs },
++ { "-lzs", o_bool, &ccp_wantoptions[0].lzs,
++ "don't allow Stac LZS", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
++ &ccp_allowoptions[0].lzs },
++
+ #ifdef MPPE
+- /* MPPE options are symmetrical ... we only set wantoptions here */
+- { "require-mppe", o_bool, &ccp_wantoptions[0].mppe,
+- "require MPPE encryption",
+- OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 },
+- { "+mppe", o_bool, &ccp_wantoptions[0].mppe,
+- "require MPPE encryption",
+- OPT_ALIAS | OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 },
+- { "nomppe", o_bool, &ccp_wantoptions[0].mppe,
+- "don't allow MPPE encryption", OPT_PRIO },
+- { "-mppe", o_bool, &ccp_wantoptions[0].mppe,
+- "don't allow MPPE encryption", OPT_ALIAS | OPT_PRIO },
+-
+- /* We use ccp_allowoptions[0].mppe as a junk var ... it is reset later */
+- { "require-mppe-40", o_bool, &ccp_allowoptions[0].mppe,
+- "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40,
+- &ccp_wantoptions[0].mppe },
+- { "+mppe-40", o_bool, &ccp_allowoptions[0].mppe,
+- "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40,
+- &ccp_wantoptions[0].mppe },
+- { "nomppe-40", o_bool, &ccp_allowoptions[0].mppe,
+- "don't allow MPPE 40-bit encryption",
+- OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40, &ccp_wantoptions[0].mppe },
+- { "-mppe-40", o_bool, &ccp_allowoptions[0].mppe,
+- "don't allow MPPE 40-bit encryption",
+- OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40,
+- &ccp_wantoptions[0].mppe },
+-
+- { "require-mppe-128", o_bool, &ccp_allowoptions[0].mppe,
+- "require MPPE 128-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_128,
+- &ccp_wantoptions[0].mppe },
+- { "+mppe-128", o_bool, &ccp_allowoptions[0].mppe,
+- "require MPPE 128-bit encryption",
+- OPT_ALIAS | OPT_PRIO | OPT_A2OR | MPPE_OPT_128,
+- &ccp_wantoptions[0].mppe },
+- { "nomppe-128", o_bool, &ccp_allowoptions[0].mppe,
+- "don't allow MPPE 128-bit encryption",
+- OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128, &ccp_wantoptions[0].mppe },
+- { "-mppe-128", o_bool, &ccp_allowoptions[0].mppe,
+- "don't allow MPPE 128-bit encryption",
+- OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128,
+- &ccp_wantoptions[0].mppe },
+-
+- /* strange one; we always request stateless, but will we allow stateful? */
+- { "mppe-stateful", o_bool, &refuse_mppe_stateful,
+- "allow MPPE stateful mode", OPT_PRIO },
+- { "nomppe-stateful", o_bool, &refuse_mppe_stateful,
+- "disallow MPPE stateful mode", OPT_PRIO | 1 },
++ { "mppc", o_bool, &ccp_wantoptions[0].mppc,
++ "request MPPC compression", 1, &ccp_allowoptions[0].mppc },
++ { "+mppc", o_bool, &ccp_wantoptions[0].mppc,
++ "request MPPC compression", 1, &ccp_allowoptions[0].mppc, OPT_ALIAS },
++ { "nomppc", o_bool, &ccp_wantoptions[0].mppc,
++ "don't allow MPPC compression", OPT_PRIOSUB | OPT_A2CLR,
++ &ccp_allowoptions[0].mppc },
++ { "-mppc", o_bool, &ccp_wantoptions[0].mppc,
++ "don't allow MPPC compression", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
++ &ccp_allowoptions[0].mppc },
++ { "mppe", o_special, (void *)setmppe,
++ "request MPPE encryption" },
++ { "+mppe", o_special, (void *)setmppe,
++ "request MPPE encryption" },
++ { "nomppe", o_special_noarg, (void *)setnomppe,
++ "don't allow MPPE encryption" },
++ { "-mppe", o_special_noarg, (void *)setnomppe,
++ "don't allow MPPE encryption" },
+ #endif /* MPPE */
+
+ { NULL }
+@@ -241,7 +221,7 @@ static fsm_callbacks ccp_callbacks = {
+ */
+ #define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \
+ || (opt).predictor_1 || (opt).predictor_2 \
+- || (opt).mppe)
++ || (opt).lzs || (opt).mppc || (opt).mppe)
+
+ /*
+ * Local state (mainly for handling reset-reqs and reset-acks).
+@@ -344,6 +324,100 @@ setdeflate(argv)
+ return 1;
+ }
+
++#ifdef MPPE
++/*
++ * Functions called from config options
++ */
++/*
++ MPPE suboptions:
++ required - require MPPE; disconnect if peer doesn't support it
++ stateless - use stateless mode
++ no40 - disable 40 bit keys
++ no56 - disable 56 bit keys
++ no128 - disable 128 bit keys
++*/
++int setmppe(char **argv)
++{
++ int i;
++ char *str, cmdbuf[16];
++
++ ccp_allowoptions[0].mppe = 1;
++ ccp_allowoptions[0].mppe_40 = 1;
++ ccp_allowoptions[0].mppe_56 = 1;
++ ccp_allowoptions[0].mppe_128 = 1;
++ ccp_allowoptions[0].mppe_stateless = 0;
++ ccp_wantoptions[0].mppe = 0;
++
++ str = *argv;
++
++ while (1) {
++ i = 0;
++ memset(cmdbuf, '\0', 16);
++ while ((i < 16) && (*str != ',') && (*str != '\0'))
++ cmdbuf[i++] = *str++;
++ cmdbuf[i] = '\0';
++ if (!strncasecmp(cmdbuf, "no40", strlen("no40"))) {
++ ccp_allowoptions[0].mppe_40 = 0;
++ goto next_param;
++ } else if (!strncasecmp(cmdbuf, "no56", strlen("no56"))) {
++ ccp_allowoptions[0].mppe_56 = 0;
++ goto next_param;
++ } else if (!strncasecmp(cmdbuf, "no128", strlen("no128"))) {
++ ccp_allowoptions[0].mppe_128 = 0;
++ goto next_param;
++ } else if (!strncasecmp(cmdbuf, "stateless", strlen("stateless"))) {
++ ccp_allowoptions[0].mppe_stateless = 1;
++ goto next_param;
++ } else if (!strncasecmp(cmdbuf, "required", strlen("required"))) {
++ ccp_wantoptions[0].mppe = 1;
++ goto next_param;
++ } else {
++ option_error("invalid parameter '%s' for mppe option", cmdbuf);
++ return 0;
++ }
++
++ next_param:
++ if (*str == ',') {
++ str++;
++ continue;
++ }
++ if (*str == '\0') {
++ if (!(ccp_allowoptions[0].mppe_40 || ccp_allowoptions[0].mppe_56 ||
++ ccp_allowoptions[0].mppe_128)) {
++ if (ccp_wantoptions[0].mppe == 1) {
++ option_error("You require MPPE but you have switched off "
++ "all encryption key lengths.");
++ return 0;
++ }
++ ccp_wantoptions[0].mppe = ccp_allowoptions[0].mppe = 0;
++ ccp_wantoptions[0].mppe_stateless =
++ ccp_allowoptions[0].mppe_stateless = 0;
++ } else {
++ ccp_allowoptions[0].mppe = 1;
++ ccp_wantoptions[0].mppe_stateless =
++ ccp_allowoptions[0].mppe_stateless;
++ if (ccp_wantoptions[0].mppe == 1) {
++ ccp_wantoptions[0].mppe_40 = ccp_allowoptions[0].mppe_40;
++ ccp_wantoptions[0].mppe_56 = ccp_allowoptions[0].mppe_56;
++ ccp_wantoptions[0].mppe_128 = ccp_allowoptions[0].mppe_128;
++ }
++ }
++ return 1;
++ }
++ }
++}
++
++int setnomppe(void)
++{
++ ccp_wantoptions[0].mppe = ccp_allowoptions[0].mppe = 0;
++ ccp_wantoptions[0].mppe_40 = ccp_allowoptions[0].mppe_40 = 0;
++ ccp_wantoptions[0].mppe_56 = ccp_allowoptions[0].mppe_56 = 0;
++ ccp_wantoptions[0].mppe_128 = ccp_allowoptions[0].mppe_128 = 0;
++ ccp_wantoptions[0].mppe_stateless = ccp_allowoptions[0].mppe_stateless = 0;
++ return 1;
++}
++#endif /* MPPE */
++
+ /*
+ * ccp_init - initialize CCP.
+ */
+@@ -378,6 +452,30 @@ ccp_init(unit)
+ ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS;
+
+ ccp_allowoptions[0].predictor_1 = 1;
++
++ ccp_wantoptions[0].lzs = 0; /* Stac LZS - will be enabled in the future */
++ ccp_wantoptions[0].lzs_mode = LZS_MODE_SEQ;
++ ccp_wantoptions[0].lzs_hists = 1;
++ ccp_allowoptions[0].lzs = 0; /* Stac LZS - will be enabled in the future */
++ ccp_allowoptions[0].lzs_mode = LZS_MODE_SEQ;
++ ccp_allowoptions[0].lzs_hists = 1;
++
++#ifdef MPPE
++ /* by default allow and request MPPC... */
++ ccp_wantoptions[0].mppc = ccp_allowoptions[0].mppc = 1;
++
++ /* ... and allow but don't request MPPE */
++ ccp_allowoptions[0].mppe = 1;
++ ccp_allowoptions[0].mppe_40 = 1;
++ ccp_allowoptions[0].mppe_56 = 1;
++ ccp_allowoptions[0].mppe_128 = 1;
++ ccp_allowoptions[0].mppe_stateless = 1;
++ ccp_wantoptions[0].mppe = 0;
++ ccp_wantoptions[0].mppe_40 = 0;
++ ccp_wantoptions[0].mppe_56 = 0;
++ ccp_wantoptions[0].mppe_128 = 0;
++ ccp_wantoptions[0].mppe_stateless = 0;
++#endif /* MPPE */
+ }
+
+ /*
+@@ -455,11 +553,11 @@ ccp_input(unit, p, len)
+ if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED) {
+ notice("Compression disabled by peer.");
+ #ifdef MPPE
+- if (ccp_gotoptions[unit].mppe) {
++ if (ccp_wantoptions[unit].mppe) {
+ error("MPPE disabled, closing LCP");
+ lcp_close(unit, "MPPE disabled by peer");
+ }
+-#endif
++#endif /* MPPE */
+ }
+
+ /*
+@@ -487,6 +585,15 @@ ccp_extcode(f, code, id, p, len)
+ break;
+ /* send a reset-ack, which the transmitter will see and
+ reset its compression state. */
++
++ /* In case of MPPE/MPPC or LZS we shouldn't send CCP_RESETACK,
++ but we do it in order to reset compressor; CCP_RESETACK is
++ then silently discarded. See functions ppp_send_frame and
++ ppp_ccp_peek in ppp_generic.c (Linux only !!!). All the
++ confusion is caused by the fact that CCP code is splited
++ into two parts - one part is handled by pppd, the other one
++ is handled by kernel. */
++
+ fsm_sdata(f, CCP_RESETACK, id, NULL, 0);
+ break;
+
+@@ -515,12 +622,11 @@ ccp_protrej(unit)
+ fsm_lowerdown(&ccp_fsm[unit]);
+
+ #ifdef MPPE
+- if (ccp_gotoptions[unit].mppe) {
++ if (ccp_wantoptions[unit].mppe) {
+ error("MPPE required but peer negotiation failed");
+ lcp_close(unit, "MPPE required but peer negotiation failed");
+ }
+-#endif
+-
++#endif /* MPPE */
+ }
+
+ /*
+@@ -537,7 +643,7 @@ ccp_resetci(f)
+ all_rejected[f->unit] = 0;
+
+ #ifdef MPPE
+- if (go->mppe) {
++ if (go->mppe || go->mppc) {
+ ccp_options *ao = &ccp_allowoptions[f->unit];
+ int auth_mschap_bits = auth_done[f->unit];
+ int numbits;
+@@ -551,80 +657,109 @@ ccp_resetci(f)
+ * NB: If MPPE is required, all other compression opts are invalid.
+ * So, we return right away if we can't do it.
+ */
++ if (ccp_wantoptions[f->unit].mppe) {
++ /* Leave only the mschap auth bits set */
++ auth_mschap_bits &= (CHAP_MS_WITHPEER | CHAP_MS_PEER |
++ CHAP_MS2_WITHPEER | CHAP_MS2_PEER);
++ /* Count the mschap auths */
++ auth_mschap_bits >>= CHAP_MS_SHIFT;
++ numbits = 0;
++ do {
++ numbits += auth_mschap_bits & 1;
++ auth_mschap_bits >>= 1;
++ } while (auth_mschap_bits);
++ if (numbits > 1) {
++ error("MPPE required, but auth done in both directions.");
++ lcp_close(f->unit, "MPPE required but not available");
++ return;
++ }
++ if (!numbits) {
++ error("MPPE required, but MS-CHAP[v2] auth not performed.");
++ lcp_close(f->unit, "MPPE required but not available");
++ return;
++ }
+
+- /* Leave only the mschap auth bits set */
+- auth_mschap_bits &= (CHAP_MS_WITHPEER | CHAP_MS_PEER |
+- CHAP_MS2_WITHPEER | CHAP_MS2_PEER);
+- /* Count the mschap auths */
+- auth_mschap_bits >>= CHAP_MS_SHIFT;
+- numbits = 0;
+- do {
+- numbits += auth_mschap_bits & 1;
+- auth_mschap_bits >>= 1;
+- } while (auth_mschap_bits);
+- if (numbits > 1) {
+- error("MPPE required, but auth done in both directions.");
+- lcp_close(f->unit, "MPPE required but not available");
+- return;
+- }
+- if (!numbits) {
+- error("MPPE required, but MS-CHAP[v2] auth not performed.");
+- lcp_close(f->unit, "MPPE required but not available");
+- return;
+- }
+-
+- /* A plugin (eg radius) may not have obtained key material. */
+- if (!mppe_keys_set) {
+- error("MPPE required, but keys are not available. "
+- "Possible plugin problem?");
+- lcp_close(f->unit, "MPPE required but not available");
+- return;
+- }
+-
+- /* LM auth not supported for MPPE */
+- if (auth_done[f->unit] & (CHAP_MS_WITHPEER | CHAP_MS_PEER)) {
+- /* This might be noise */
+- if (go->mppe & MPPE_OPT_40) {
+- notice("Disabling 40-bit MPPE; MS-CHAP LM not supported");
+- go->mppe &= ~MPPE_OPT_40;
+- ccp_wantoptions[f->unit].mppe &= ~MPPE_OPT_40;
++ /* A plugin (eg radius) may not have obtained key material. */
++ if (!mppe_keys_set) {
++ error("MPPE required, but keys are not available. "
++ "Possible plugin problem?");
++ lcp_close(f->unit, "MPPE required but not available");
++ return;
+ }
+ }
+
+- /* Last check: can we actually negotiate something? */
+- if (!(go->mppe & (MPPE_OPT_40 | MPPE_OPT_128))) {
+- /* Could be misconfig, could be 40-bit disabled above. */
+- error("MPPE required, but both 40-bit and 128-bit disabled.");
+- lcp_close(f->unit, "MPPE required but not available");
+- return;
++ /*
++ * Check whether the kernel knows about the various
++ * compression methods we might request. Key material
++ * unimportant here.
++ */
++ if (go->mppc) {
++ opt_buf[0] = CI_MPPE;
++ opt_buf[1] = CILEN_MPPE;
++ opt_buf[2] = 0;
++ opt_buf[3] = 0;
++ opt_buf[4] = 0;
++ opt_buf[5] = MPPE_MPPC;
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE, 0) <= 0)
++ go->mppc = 0;
++ }
++ if (go->mppe_40) {
++ opt_buf[0] = CI_MPPE;
++ opt_buf[1] = CILEN_MPPE;
++ opt_buf[2] = MPPE_STATELESS;
++ opt_buf[3] = 0;
++ opt_buf[4] = 0;
++ opt_buf[5] = MPPE_40BIT;
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0) <= 0)
++ go->mppe_40 = 0;
++ }
++ if (go->mppe_56) {
++ opt_buf[0] = CI_MPPE;
++ opt_buf[1] = CILEN_MPPE;
++ opt_buf[2] = MPPE_STATELESS;
++ opt_buf[3] = 0;
++ opt_buf[4] = 0;
++ opt_buf[5] = MPPE_56BIT;
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0) <= 0)
++ go->mppe_56 = 0;
++ }
++ if (go->mppe_128) {
++ opt_buf[0] = CI_MPPE;
++ opt_buf[1] = CILEN_MPPE;
++ opt_buf[2] = MPPE_STATELESS;
++ opt_buf[3] = 0;
++ opt_buf[4] = 0;
++ opt_buf[5] = MPPE_128BIT;
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0) <= 0)
++ go->mppe_128 = 0;
++ }
++ if (!go->mppe_40 && !go->mppe_56 && !go->mppe_128) {
++ if (ccp_wantoptions[f->unit].mppe) {
++ error("MPPE required, but kernel has no support.");
++ lcp_close(f->unit, "MPPE required but not available");
++ }
++ go->mppe = go->mppe_stateless = 0;
++ } else {
++ /* MPPE is not compatible with other compression types */
++ if (ccp_wantoptions[f->unit].mppe) {
++ ao->bsd_compress = go->bsd_compress = 0;
++ ao->predictor_1 = go->predictor_1 = 0;
++ ao->predictor_2 = go->predictor_2 = 0;
++ ao->deflate = go->deflate = 0;
++ ao->lzs = go->lzs = 0;
++ }
+ }
+-
+- /* sync options */
+- ao->mppe = go->mppe;
+- /* MPPE is not compatible with other compression types */
+- ao->bsd_compress = go->bsd_compress = 0;
+- ao->predictor_1 = go->predictor_1 = 0;
+- ao->predictor_2 = go->predictor_2 = 0;
+- ao->deflate = go->deflate = 0;
+ }
+ #endif /* MPPE */
+-
+- /*
+- * Check whether the kernel knows about the various
+- * compression methods we might request.
+- */
+-#ifdef MPPE
+- if (go->mppe) {
+- opt_buf[0] = CI_MPPE;
+- opt_buf[1] = CILEN_MPPE;
+- MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]);
+- /* Key material unimportant here. */
+- if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0) <= 0) {
+- error("MPPE required, but kernel has no support.");
+- lcp_close(f->unit, "MPPE required but not available");
+- }
++ if (go->lzs) {
++ opt_buf[0] = CI_LZS;
++ opt_buf[1] = CILEN_LZS;
++ opt_buf[2] = go->lzs_hists >> 8;
++ opt_buf[3] = go->lzs_hists & 0xff;
++ opt_buf[4] = LZS_MODE_SEQ;
++ if (ccp_test(f->unit, opt_buf, CILEN_LZS, 0) <= 0)
++ go->lzs = 0;
+ }
+-#endif
+ if (go->bsd_compress) {
+ opt_buf[0] = CI_BSD_COMPRESS;
+ opt_buf[1] = CILEN_BSD_COMPRESS;
+@@ -679,7 +814,8 @@ ccp_cilen(f)
+ + (go->deflate? CILEN_DEFLATE: 0)
+ + (go->predictor_1? CILEN_PREDICTOR_1: 0)
+ + (go->predictor_2? CILEN_PREDICTOR_2: 0)
+- + (go->mppe? CILEN_MPPE: 0);
++ + (go->lzs? CILEN_LZS: 0)
++ + ((go->mppe || go->mppc)? CILEN_MPPE: 0);
+ }
+
+ /*
+@@ -693,6 +829,8 @@ ccp_addci(f, p, lenp)
+ {
+ int res;
+ ccp_options *go = &ccp_gotoptions[f->unit];
++ ccp_options *ao = &ccp_allowoptions[f->unit];
++ ccp_options *wo = &ccp_wantoptions[f->unit];
+ u_char *p0 = p;
+
+ /*
+@@ -701,22 +839,43 @@ ccp_addci(f, p, lenp)
+ * in case it gets Acked.
+ */
+ #ifdef MPPE
+- if (go->mppe) {
++ if (go->mppe || go->mppc || (!wo->mppe && ao->mppe)) {
+ u_char opt_buf[CILEN_MPPE + MPPE_MAX_KEY_LEN];
+
+- p[0] = opt_buf[0] = CI_MPPE;
+- p[1] = opt_buf[1] = CILEN_MPPE;
+- MPPE_OPTS_TO_CI(go->mppe, &p[2]);
+- MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]);
++ p[0] = CI_MPPE;
++ p[1] = CILEN_MPPE;
++ p[2] = (go->mppe_stateless ? MPPE_STATELESS : 0);
++ p[3] = 0;
++ p[4] = 0;
++ p[5] = (go->mppe_40 ? MPPE_40BIT : 0) | (go->mppe_56 ? MPPE_56BIT : 0) |
++ (go->mppe_128 ? MPPE_128BIT : 0) | (go->mppc ? MPPE_MPPC : 0);
++
++ BCOPY(p, opt_buf, CILEN_MPPE);
+ BCOPY(mppe_recv_key, &opt_buf[CILEN_MPPE], MPPE_MAX_KEY_LEN);
+ res = ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0);
+- if (res > 0)
++ if (res > 0) {
+ p += CILEN_MPPE;
+- else
++ } else {
+ /* This shouldn't happen, we've already tested it! */
+- lcp_close(f->unit, "MPPE required but not available in kernel");
++ go->mppe = go->mppe_40 = go->mppe_56 = go->mppe_128 =
++ go->mppe_stateless = go->mppc = 0;
++ if (ccp_wantoptions[f->unit].mppe)
++ lcp_close(f->unit, "MPPE required but not available in kernel");
++ }
++ }
++#endif /* MPPE */
++ if (go->lzs) {
++ p[0] = CI_LZS;
++ p[1] = CILEN_LZS;
++ p[2] = go->lzs_hists >> 8;
++ p[3] = go->lzs_hists & 0xff;
++ p[4] = LZS_MODE_SEQ;
++ res = ccp_test(f->unit, p, CILEN_LZS, 0);
++ if (res > 0) {
++ p += CILEN_LZS;
++ } else
++ go->lzs = 0;
+ }
+-#endif
+ if (go->deflate) {
+ p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT;
+ p[1] = CILEN_DEFLATE;
+@@ -802,7 +961,7 @@ ccp_addci(f, p, lenp)
+
+ /*
+ * ccp_ackci - process a received configure-ack, and return
+- * 1 iff the packet was OK.
++ * 1 if the packet was OK.
+ */
+ static int
+ ccp_ackci(f, p, len)
+@@ -811,24 +970,44 @@ ccp_ackci(f, p, len)
+ int len;
+ {
+ ccp_options *go = &ccp_gotoptions[f->unit];
++ ccp_options *ao = &ccp_allowoptions[f->unit];
++ ccp_options *wo = &ccp_wantoptions[f->unit];
+ u_char *p0 = p;
+
+ #ifdef MPPE
+- if (go->mppe) {
+- u_char opt_buf[CILEN_MPPE];
+-
+- opt_buf[0] = CI_MPPE;
+- opt_buf[1] = CILEN_MPPE;
+- MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]);
+- if (len < CILEN_MPPE || memcmp(opt_buf, p, CILEN_MPPE))
++ if (go->mppe || go->mppc || (!wo->mppe && ao->mppe)) {
++ if (len < CILEN_MPPE
++ || p[1] != CILEN_MPPE || p[0] != CI_MPPE
++ || p[2] != (go->mppe_stateless ? MPPE_STATELESS : 0)
++ || p[3] != 0
++ || p[4] != 0
++ || (p[5] != ((go->mppe_40 ? MPPE_40BIT : 0) |
++ (go->mppc ? MPPE_MPPC : 0))
++ && p[5] != ((go->mppe_56 ? MPPE_56BIT : 0) |
++ (go->mppc ? MPPE_MPPC : 0))
++ && p[5] != ((go->mppe_128 ? MPPE_128BIT : 0) |
++ (go->mppc ? MPPE_MPPC : 0))))
+ return 0;
++ if (go->mppe_40 || go->mppe_56 || go->mppe_128)
++ go->mppe = 1;
+ p += CILEN_MPPE;
+ len -= CILEN_MPPE;
++ /* Cope with first/fast ack */
++ if (p == p0 && len == 0)
++ return 1;
++ }
++#endif /* MPPE */
++ if (go->lzs) {
++ if (len < CILEN_LZS || p[0] != CI_LZS || p[1] != CILEN_LZS
++ || p[2] != go->lzs_hists>>8 || p[3] != (go->lzs_hists&0xff)
++ || p[4] != LZS_MODE_SEQ)
++ return 0;
++ p += CILEN_LZS;
++ len -= CILEN_LZS;
+ /* XXX Cope with first/fast ack */
+- if (len == 0)
++ if (p == p0 && len == 0)
+ return 1;
+ }
+-#endif
+ if (go->deflate) {
+ if (len < CILEN_DEFLATE
+ || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
+@@ -901,6 +1080,8 @@ ccp_nakci(f, p, len, treat_as_reject)
+ int treat_as_reject;
+ {
+ ccp_options *go = &ccp_gotoptions[f->unit];
++ ccp_options *ao = &ccp_allowoptions[f->unit];
++ ccp_options *wo = &ccp_wantoptions[f->unit];
+ ccp_options no; /* options we've seen already */
+ ccp_options try; /* options to ask for next time */
+
+@@ -908,28 +1089,100 @@ ccp_nakci(f, p, len, treat_as_reject)
+ try = *go;
+
+ #ifdef MPPE
+- if (go->mppe && len >= CILEN_MPPE
+- && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
+- no.mppe = 1;
+- /*
+- * Peer wants us to use a different strength or other setting.
+- * Fail if we aren't willing to use his suggestion.
+- */
+- MPPE_CI_TO_OPTS(&p[2], try.mppe);
+- if ((try.mppe & MPPE_OPT_STATEFUL) && refuse_mppe_stateful) {
+- error("Refusing MPPE stateful mode offered by peer");
+- try.mppe = 0;
+- } else if (((go->mppe | MPPE_OPT_STATEFUL) & try.mppe) != try.mppe) {
+- /* Peer must have set options we didn't request (suggest) */
+- try.mppe = 0;
+- }
++ if ((go->mppe || go->mppc || (!wo->mppe && ao->mppe)) &&
++ len >= CILEN_MPPE && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
+
+- if (!try.mppe) {
+- error("MPPE required but peer negotiation failed");
+- lcp_close(f->unit, "MPPE required but peer negotiation failed");
++ if (go->mppc) {
++ no.mppc = 1;
++ if (!(p[5] & MPPE_MPPC))
++ try.mppc = 0;
++ }
++
++ if (go->mppe)
++ no.mppe = 1;
++ if (go->mppe_40)
++ no.mppe_40 = 1;
++ if (go->mppe_56)
++ no.mppe_56 = 1;
++ if (go->mppe_128)
++ no.mppe_128 = 1;
++ if (go->mppe_stateless)
++ no.mppe_stateless = 1;
++
++ if (ao->mppe_40) {
++ if ((p[5] & MPPE_40BIT))
++ try.mppe_40 = 1;
++ else
++ try.mppe_40 = (p[5] == 0) ? 1 : 0;
++ }
++ if (ao->mppe_56) {
++ if ((p[5] & MPPE_56BIT))
++ try.mppe_56 = 1;
++ else
++ try.mppe_56 = (p[5] == 0) ? 1 : 0;
++ }
++ if (ao->mppe_128) {
++ if ((p[5] & MPPE_128BIT))
++ try.mppe_128 = 1;
++ else
++ try.mppe_128 = (p[5] == 0) ? 1 : 0;
++ }
++
++ if (ao->mppe_stateless) {
++ if ((p[2] & MPPE_STATELESS) || wo->mppe_stateless)
++ try.mppe_stateless = 1;
++ else
++ try.mppe_stateless = 0;
++ }
++
++ if (!try.mppe_56 && !try.mppe_40 && !try.mppe_128) {
++ try.mppe = try.mppe_stateless = 0;
++ if (wo->mppe) {
++ /* we require encryption, but peer doesn't support it
++ so we close connection */
++ wo->mppc = wo->mppe = wo->mppe_stateless = wo->mppe_40 =
++ wo->mppe_56 = wo->mppe_128 = 0;
++ lcp_close(f->unit, "MPPE required but cannot negotiate MPPE "
++ "key length");
++ }
++ }
++ if (wo->mppe && (wo->mppe_40 != try.mppe_40) &&
++ (wo->mppe_56 != try.mppe_56) && (wo->mppe_128 != try.mppe_128)) {
++ /* cannot negotiate key length */
++ wo->mppc = wo->mppe = wo->mppe_stateless = wo->mppe_40 =
++ wo->mppe_56 = wo->mppe_128 = 0;
++ lcp_close(f->unit, "Cannot negotiate MPPE key length");
+ }
++ if (try.mppe_40 && try.mppe_56 && try.mppe_128)
++ try.mppe_40 = try.mppe_56 = 0;
++ else
++ if (try.mppe_56 && try.mppe_128)
++ try.mppe_56 = 0;
++ else
++ if (try.mppe_40 && try.mppe_128)
++ try.mppe_40 = 0;
++ else
++ if (try.mppe_40 && try.mppe_56)
++ try.mppe_40 = 0;
++
++ p += CILEN_MPPE;
++ len -= CILEN_MPPE;
+ }
+ #endif /* MPPE */
++
++ if (go->lzs && len >= CILEN_LZS && p[0] == CI_LZS && p[1] == CILEN_LZS) {
++ no.lzs = 1;
++ if (((p[2]<<8)|p[3]) > 1 || (p[4] != LZS_MODE_SEQ &&
++ p[4] != LZS_MODE_EXT))
++ try.lzs = 0;
++ else {
++ try.lzs_mode = p[4];
++ try.lzs_hists = (p[2] << 8) | p[3];
++ }
++ p += CILEN_LZS;
++ len -= CILEN_LZS;
++ }
++
+ if (go->deflate && len >= CILEN_DEFLATE
+ && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
+ && p[1] == CILEN_DEFLATE) {
+@@ -1002,14 +1255,50 @@ ccp_rejci(f, p, len)
+ return -1;
+
+ #ifdef MPPE
+- if (go->mppe && len >= CILEN_MPPE
++ if ((go->mppe || go->mppc) && len >= CILEN_MPPE
+ && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
+- error("MPPE required but peer refused");
+- lcp_close(f->unit, "MPPE required but peer refused");
++ ccp_options *wo = &ccp_wantoptions[f->unit];
++ if (p[2] != (go->mppe_stateless ? MPPE_STATELESS : 0) ||
++ p[3] != 0 ||
++ p[4] != 0 ||
++ p[5] != ((go->mppe_40 ? MPPE_40BIT : 0) |
++ (go->mppe_56 ? MPPE_56BIT : 0) |
++ (go->mppe_128 ? MPPE_128BIT : 0) |
++ (go->mppc ? MPPE_MPPC : 0)))
++ return 0;
++ if (go->mppc)
++ try.mppc = 0;
++ if (go->mppe) {
++ try.mppe = 0;
++ if (go->mppe_40)
++ try.mppe_40 = 0;
++ if (go->mppe_56)
++ try.mppe_56 = 0;
++ if (go->mppe_128)
++ try.mppe_128 = 0;
++ if (go->mppe_stateless)
++ try.mppe_stateless = 0;
++ if (!try.mppe_56 && !try.mppe_40 && !try.mppe_128)
++ try.mppe = try.mppe_stateless = 0;
++ if (wo->mppe) { /* we want MPPE but cannot negotiate key length */
++ wo->mppc = wo->mppe = wo->mppe_stateless = wo->mppe_40 =
++ wo->mppe_56 = wo->mppe_128 = 0;
++ lcp_close(f->unit, "MPPE required but cannot negotiate MPPE "
++ "key length");
++ }
++ }
+ p += CILEN_MPPE;
+ len -= CILEN_MPPE;
+ }
+-#endif
++#endif /* MPPE */
++ if (go->lzs && len >= CILEN_LZS && p[0] == CI_LZS && p[1] == CILEN_LZS) {
++ if (p[2] != go->lzs_hists>>8 || p[3] != (go->lzs_hists&0xff)
++ || p[4] != go->lzs_mode)
++ return 0;
++ try.lzs = 0;
++ p += CILEN_LZS;
++ len -= CILEN_LZS;
++ }
+ if (go->deflate_correct && len >= CILEN_DEFLATE
+ && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) {
+ if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
+@@ -1073,14 +1362,15 @@ ccp_reqci(f, p, lenp, dont_nak)
+ int dont_nak;
+ {
+ int ret, newret, res;
+- u_char *p0, *retp;
++ u_char *p0, *retp, p2, p5;
+ int len, clen, type, nb;
+ ccp_options *ho = &ccp_hisoptions[f->unit];
+ ccp_options *ao = &ccp_allowoptions[f->unit];
++ ccp_options *wo = &ccp_wantoptions[f->unit];
+ #ifdef MPPE
+- bool rej_for_ci_mppe = 1; /* Are we rejecting based on a bad/missing */
+- /* CI_MPPE, or due to other options? */
+-#endif
++ u_char opt_buf[CILEN_MPPE + MPPE_MAX_KEY_LEN];
++/* int mtu; */
++#endif /* MPPE */
+
+ ret = CONFACK;
+ retp = p0 = p;
+@@ -1103,106 +1393,302 @@ ccp_reqci(f, p, lenp, dont_nak)
+ switch (type) {
+ #ifdef MPPE
+ case CI_MPPE:
+- if (!ao->mppe || clen != CILEN_MPPE) {
++ if ((!ao->mppc && !ao->mppe) || clen != CILEN_MPPE) {
+ newret = CONFREJ;
+ break;
+ }
+- MPPE_CI_TO_OPTS(&p[2], ho->mppe);
+-
+- /* Nak if anything unsupported or unknown are set. */
+- if (ho->mppe & MPPE_OPT_UNSUPPORTED) {
+- newret = CONFNAK;
+- ho->mppe &= ~MPPE_OPT_UNSUPPORTED;
+- }
+- if (ho->mppe & MPPE_OPT_UNKNOWN) {
++ p2 = p[2];
++ p5 = p[5];
++ /* not sure what they want, tell 'em what we got */
++ if (((p[2] & ~MPPE_STATELESS) != 0 || p[3] != 0 || p[4] != 0 ||
++ (p[5] & ~(MPPE_40BIT | MPPE_56BIT | MPPE_128BIT |
++ MPPE_MPPC)) != 0 || p[5] == 0) ||
++ (p[2] == 0 && p[3] == 0 && p[4] == 0 && p[5] == 0)) {
+ newret = CONFNAK;
+- ho->mppe &= ~MPPE_OPT_UNKNOWN;
+- }
+-
+- /* Check state opt */
+- if (ho->mppe & MPPE_OPT_STATEFUL) {
+- /*
+- * We can Nak and request stateless, but it's a
+- * lot easier to just assume the peer will request
+- * it if he can do it; stateful mode is bad over
+- * the Internet -- which is where we expect MPPE.
+- */
+- if (refuse_mppe_stateful) {
+- error("Refusing MPPE stateful mode offered by peer");
+- newret = CONFREJ;
+- break;
++ p[2] = (wo->mppe_stateless ? MPPE_STATELESS : 0);
++ p[3] = 0;
++ p[4] = 0;
++ p[5] = (wo->mppe_40 ? MPPE_40BIT : 0) |
++ (wo->mppe_56 ? MPPE_56BIT : 0) |
++ (wo->mppe_128 ? MPPE_128BIT : 0) |
++ (wo->mppc ? MPPE_MPPC : 0);
++ break;
++ }
++
++ if ((p[5] & MPPE_MPPC)) {
++ if (ao->mppc) {
++ ho->mppc = 1;
++ BCOPY(p, opt_buf, CILEN_MPPE);
++ opt_buf[2] = opt_buf[3] = opt_buf[4] = 0;
++ opt_buf[5] = MPPE_MPPC;
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE, 1) <= 0) {
++ ho->mppc = 0;
++ p[5] &= ~MPPE_MPPC;
++ newret = CONFNAK;
++ }
++ } else {
++ newret = CONFREJ;
++ if (wo->mppe || ao->mppe) {
++ p[5] &= ~MPPE_MPPC;
++ newret = CONFNAK;
++ }
+ }
+ }
+-
+- /* Find out which of {S,L} are set. */
+- if ((ho->mppe & MPPE_OPT_128)
+- && (ho->mppe & MPPE_OPT_40)) {
+- /* Both are set, negotiate the strongest. */
+- newret = CONFNAK;
+- if (ao->mppe & MPPE_OPT_128)
+- ho->mppe &= ~MPPE_OPT_40;
+- else if (ao->mppe & MPPE_OPT_40)
+- ho->mppe &= ~MPPE_OPT_128;
+- else {
+- newret = CONFREJ;
+- break;
+- }
+- } else if (ho->mppe & MPPE_OPT_128) {
+- if (!(ao->mppe & MPPE_OPT_128)) {
+- newret = CONFREJ;
+- break;
+- }
+- } else if (ho->mppe & MPPE_OPT_40) {
+- if (!(ao->mppe & MPPE_OPT_40)) {
+- newret = CONFREJ;
+- break;
+- }
++ if (ao->mppe)
++ ho->mppe = 1;
++
++ if ((p[2] & MPPE_STATELESS)) {
++ if (ao->mppe_stateless) {
++ if (wo->mppe_stateless)
++ ho->mppe_stateless = 1;
++ else {
++ newret = CONFNAK;
++ if (!dont_nak)
++ p[2] &= ~MPPE_STATELESS;
++ }
++ } else {
++ newret = CONFNAK;
++ if (!dont_nak)
++ p[2] &= ~MPPE_STATELESS;
++ }
++ } else {
++ if (wo->mppe_stateless && !dont_nak) {
++ wo->mppe_stateless = 0;
++ newret = CONFNAK;
++ p[2] |= MPPE_STATELESS;
++ }
++ }
++
++ if ((p[5] & ~MPPE_MPPC) == (MPPE_40BIT|MPPE_56BIT|MPPE_128BIT)) {
++ newret = CONFNAK;
++ if (ao->mppe_128) {
++ ho->mppe_128 = 1;
++ p[5] &= ~(MPPE_40BIT|MPPE_56BIT);
++ BCOPY(p, opt_buf, CILEN_MPPE);
++ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
++ MPPE_MAX_KEY_LEN);
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
++ MPPE_MAX_KEY_LEN, 1) <= 0) {
++ ho->mppe_128 = 0;
++ p[5] |= (MPPE_40BIT|MPPE_56BIT);
++ p[5] &= ~MPPE_128BIT;
++ goto check_mppe_56_40;
++ }
++ goto check_mppe;
++ }
++ p[5] &= ~MPPE_128BIT;
++ goto check_mppe_56_40;
++ }
++ if ((p[5] & ~MPPE_MPPC) == (MPPE_56BIT|MPPE_128BIT)) {
++ newret = CONFNAK;
++ if (ao->mppe_128) {
++ ho->mppe_128 = 1;
++ p[5] &= ~MPPE_56BIT;
++ BCOPY(p, opt_buf, CILEN_MPPE);
++ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
++ MPPE_MAX_KEY_LEN);
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
++ MPPE_MAX_KEY_LEN, 1) <= 0) {
++ ho->mppe_128 = 0;
++ p[5] |= MPPE_56BIT;
++ p[5] &= ~MPPE_128BIT;
++ goto check_mppe_56;
++ }
++ goto check_mppe;
++ }
++ p[5] &= ~MPPE_128BIT;
++ goto check_mppe_56;
++ }
++ if ((p[5] & ~MPPE_MPPC) == (MPPE_40BIT|MPPE_128BIT)) {
++ newret = CONFNAK;
++ if (ao->mppe_128) {
++ ho->mppe_128 = 1;
++ p[5] &= ~MPPE_40BIT;
++ BCOPY(p, opt_buf, CILEN_MPPE);
++ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
++ MPPE_MAX_KEY_LEN);
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
++ MPPE_MAX_KEY_LEN, 1) <= 0) {
++ ho->mppe_128 = 0;
++ p[5] |= MPPE_40BIT;
++ p[5] &= ~MPPE_128BIT;
++ goto check_mppe_40;
++ }
++ goto check_mppe;
++ }
++ p[5] &= ~MPPE_128BIT;
++ goto check_mppe_40;
++ }
++ if ((p[5] & ~MPPE_MPPC) == MPPE_128BIT) {
++ if (ao->mppe_128) {
++ ho->mppe_128 = 1;
++ BCOPY(p, opt_buf, CILEN_MPPE);
++ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
++ MPPE_MAX_KEY_LEN);
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
++ MPPE_MAX_KEY_LEN, 1) <= 0) {
++ ho->mppe_128 = 0;
++ p[5] &= ~MPPE_128BIT;
++ newret = CONFNAK;
++ }
++ goto check_mppe;
++ }
++ p[5] &= ~MPPE_128BIT;
++ newret = CONFNAK;
++ goto check_mppe;
++ }
++ check_mppe_56_40:
++ if ((p[5] & ~MPPE_MPPC) == (MPPE_40BIT|MPPE_56BIT)) {
++ newret = CONFNAK;
++ if (ao->mppe_56) {
++ ho->mppe_56 = 1;
++ p[5] &= ~MPPE_40BIT;
++ BCOPY(p, opt_buf, CILEN_MPPE);
++ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
++ MPPE_MAX_KEY_LEN);
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
++ MPPE_MAX_KEY_LEN, 1) <= 0) {
++ ho->mppe_56 = 0;
++ p[5] |= MPPE_40BIT;
++ p[5] &= ~MPPE_56BIT;
++ newret = CONFNAK;
++ goto check_mppe_40;
++ }
++ goto check_mppe;
++ }
++ p[5] &= ~MPPE_56BIT;
++ goto check_mppe_40;
++ }
++ check_mppe_56:
++ if ((p[5] & ~MPPE_MPPC) == MPPE_56BIT) {
++ if (ao->mppe_56) {
++ ho->mppe_56 = 1;
++ BCOPY(p, opt_buf, CILEN_MPPE);
++ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
++ MPPE_MAX_KEY_LEN);
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
++ MPPE_MAX_KEY_LEN, 1) <= 0) {
++ ho->mppe_56 = 0;
++ p[5] &= ~MPPE_56BIT;
++ newret = CONFNAK;
++ }
++ goto check_mppe;
++ }
++ p[5] &= ~MPPE_56BIT;
++ newret = CONFNAK;
++ goto check_mppe;
++ }
++ check_mppe_40:
++ if ((p[5] & ~MPPE_MPPC) == MPPE_40BIT) {
++ if (ao->mppe_40) {
++ ho->mppe_40 = 1;
++ BCOPY(p, opt_buf, CILEN_MPPE);
++ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
++ MPPE_MAX_KEY_LEN);
++ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
++ MPPE_MAX_KEY_LEN, 1) <= 0) {
++ ho->mppe_40 = 0;
++ p[5] &= ~MPPE_40BIT;
++ newret = CONFNAK;
++ }
++ goto check_mppe;
++ }
++ p[5] &= ~MPPE_40BIT;
++ }
++
++ check_mppe:
++ if (!ho->mppe_40 && !ho->mppe_56 && !ho->mppe_128) {
++ if (wo->mppe_40 || wo->mppe_56 || wo->mppe_128) {
++ newret = CONFNAK;
++ p[2] |= (wo->mppe_stateless ? MPPE_STATELESS : 0);
++ p[5] |= (wo->mppe_40 ? MPPE_40BIT : 0) |
++ (wo->mppe_56 ? MPPE_56BIT : 0) |
++ (wo->mppe_128 ? MPPE_128BIT : 0) |
++ (wo->mppc ? MPPE_MPPC : 0);
++ } else {
++ ho->mppe = ho->mppe_stateless = 0;
++ }
+ } else {
+- /* Neither are set. */
+- /* We cannot accept this. */
+- newret = CONFNAK;
+- /* Give the peer our idea of what can be used,
+- so it can choose and confirm */
+- ho->mppe = ao->mppe;
+- }
+-
+- /* rebuild the opts */
+- MPPE_OPTS_TO_CI(ho->mppe, &p[2]);
+- if (newret == CONFACK) {
+- u_char opt_buf[CILEN_MPPE + MPPE_MAX_KEY_LEN];
+- int mtu;
+-
+- BCOPY(p, opt_buf, CILEN_MPPE);
+- BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
+- MPPE_MAX_KEY_LEN);
+- if (ccp_test(f->unit, opt_buf,
+- CILEN_MPPE + MPPE_MAX_KEY_LEN, 1) <= 0) {
+- /* This shouldn't happen, we've already tested it! */
+- error("MPPE required, but kernel has no support.");
+- lcp_close(f->unit, "MPPE required but not available");
+- newret = CONFREJ;
+- break;
+- }
+- /*
+- * We need to decrease the interface MTU by MPPE_PAD
+- * because MPPE frames **grow**. The kernel [must]
+- * allocate MPPE_PAD extra bytes in xmit buffers.
+- */
+- mtu = netif_get_mtu(f->unit);
+- if (mtu)
+- netif_set_mtu(f->unit, mtu - MPPE_PAD);
+- else
+- newret = CONFREJ;
+- }
+-
+- /*
+- * We have accepted MPPE or are willing to negotiate
+- * MPPE parameters. A CONFREJ is due to subsequent
+- * (non-MPPE) processing.
+- */
+- rej_for_ci_mppe = 0;
+- break;
+-#endif /* MPPE */
++ /* MPPE is not compatible with other compression types */
++ if (wo->mppe) {
++ ao->bsd_compress = 0;
++ ao->predictor_1 = 0;
++ ao->predictor_2 = 0;
++ ao->deflate = 0;
++ ao->lzs = 0;
++ }
++ }
++ if ((!ho->mppc || !ao->mppc) && !ho->mppe) {
++ p[2] = p2;
++ p[5] = p5;
++ newret = CONFREJ;
++ break;
++ }
++
++ /*
++ * I have commented the code below because according to RFC1547
++ * MTU is only information for higher level protocols about
++ * "the maximum allowable length for a packet (q.v.) transmitted
++ * over a point-to-point link without incurring network layer
++ * fragmentation." Of course a PPP implementation should be able
++ * to handle overhead added by MPPE - in our case apropriate code
++ * is located in drivers/net/ppp_generic.c in the kernel sources.
++ *
++ * According to RFC1661:
++ * - when negotiated MRU is less than 1500 octets, a PPP
++ * implementation must still be able to receive at least 1500
++ * octets,
++ * - when PFC is negotiated, a PPP implementation is still
++ * required to receive frames with uncompressed protocol field.
++ *
++ * So why not to handle MPPE overhead without changing MTU value?
++ * I am sure that RFC3078, unfortunately silently, assumes that.
++ */
++
++ /*
++ * We need to decrease the interface MTU by MPPE_PAD
++ * because MPPE frames **grow**. The kernel [must]
++ * allocate MPPE_PAD extra bytes in xmit buffers.
++ */
++ /*
++ mtu = netif_get_mtu(f->unit);
++ if (mtu) {
++ netif_set_mtu(f->unit, mtu - MPPE_PAD);
++ } else {
++ newret = CONFREJ;
++ if (ccp_wantoptions[f->unit].mppe) {
++ error("Cannot adjust MTU needed by MPPE.");
++ lcp_close(f->unit, "Cannot adjust MTU needed by MPPE.");
++ }
++ }
++ */
++ break;
++ #endif /* MPPE */
++
++ case CI_LZS:
++ if (!ao->lzs || clen != CILEN_LZS) {
++ newret = CONFREJ;
++ break;
++ }
++
++ ho->lzs = 1;
++ ho->lzs_hists = (p[2] << 8) | p[3];
++ ho->lzs_mode = p[4];
++ if ((ho->lzs_hists != ao->lzs_hists) ||
++ (ho->lzs_mode != ao->lzs_mode)) {
++ newret = CONFNAK;
++ if (!dont_nak) {
++ p[2] = ao->lzs_hists >> 8;
++ p[3] = ao->lzs_hists & 0xff;
++ p[4] = ao->lzs_mode;
++ } else
++ break;
++ }
++
++ if (p == p0 && ccp_test(f->unit, p, CILEN_LZS, 1) <= 0) {
++ newret = CONFREJ;
++ }
++ break;
+ case CI_DEFLATE:
+ case CI_DEFLATE_DRAFT:
+ if (!ao->deflate || clen != CILEN_DEFLATE
+@@ -1344,12 +1830,6 @@ ccp_reqci(f, p, lenp, dont_nak)
+ else
+ *lenp = retp - p0;
+ }
+-#ifdef MPPE
+- if (ret == CONFREJ && ao->mppe && rej_for_ci_mppe) {
+- error("MPPE required but peer negotiation failed");
+- lcp_close(f->unit, "MPPE required but peer negotiation failed");
+- }
+-#endif
+ return ret;
+ }
+
+@@ -1371,24 +1851,35 @@ method_name(opt, opt2)
+ char *p = result;
+ char *q = result + sizeof(result); /* 1 past result */
+
+- slprintf(p, q - p, "MPPE ");
+- p += 5;
+- if (opt->mppe & MPPE_OPT_128) {
+- slprintf(p, q - p, "128-bit ");
+- p += 8;
+- }
+- if (opt->mppe & MPPE_OPT_40) {
+- slprintf(p, q - p, "40-bit ");
+- p += 7;
+- }
+- if (opt->mppe & MPPE_OPT_STATEFUL)
+- slprintf(p, q - p, "stateful");
+- else
+- slprintf(p, q - p, "stateless");
+-
++ if (opt->mppe) {
++ if (opt->mppc) {
++ slprintf(p, q - p, "MPPC/MPPE ");
++ p += 10;
++ } else {
++ slprintf(p, q - p, "MPPE ");
++ p += 5;
++ }
++ if (opt->mppe_128) {
++ slprintf(p, q - p, "128-bit ");
++ p += 8;
++ } else if (opt->mppe_56) {
++ slprintf(p, q - p, "56-bit ");
++ p += 7;
++ } else if (opt->mppe_40) {
++ slprintf(p, q - p, "40-bit ");
++ p += 7;
++ }
++ if (opt->mppe_stateless)
++ slprintf(p, q - p, "stateless");
++ else
++ slprintf(p, q - p, "stateful");
++ } else if (opt->mppc)
++ slprintf(p, q - p, "MPPC");
+ break;
+ }
+-#endif
++#endif /* MPPE */
++ case CI_LZS:
++ return "Stac LZS";
+ case CI_DEFLATE:
+ case CI_DEFLATE_DRAFT:
+ if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
+@@ -1444,12 +1935,12 @@ ccp_up(f)
+ } else if (ANY_COMPRESS(*ho))
+ notice("%s transmit compression enabled", method_name(ho, NULL));
+ #ifdef MPPE
+- if (go->mppe) {
++ if (go->mppe || go->mppc) {
+ BZERO(mppe_recv_key, MPPE_MAX_KEY_LEN);
+ BZERO(mppe_send_key, MPPE_MAX_KEY_LEN);
+ continue_networks(f->unit); /* Bring up IP et al */
+ }
+-#endif
++#endif /* MPPE */
+ }
+
+ /*
+@@ -1472,7 +1963,7 @@ ccp_down(f)
+ lcp_close(f->unit, "MPPE disabled");
+ }
+ }
+-#endif
++#endif /* MPPE */
+ }
+
+ /*
+@@ -1532,24 +2023,28 @@ ccp_printpkt(p, plen, printer, arg)
+ #ifdef MPPE
+ case CI_MPPE:
+ if (optlen >= CILEN_MPPE) {
+- u_char mppe_opts;
+-
+- MPPE_CI_TO_OPTS(&p[2], mppe_opts);
+- printer(arg, "mppe %s %s %s %s %s %s%s",
+- (p[2] & MPPE_H_BIT)? "+H": "-H",
+- (p[5] & MPPE_M_BIT)? "+M": "-M",
+- (p[5] & MPPE_S_BIT)? "+S": "-S",
+- (p[5] & MPPE_L_BIT)? "+L": "-L",
++ printer(arg, "mppe %s %s %s %s %s %s",
++ (p[2] & MPPE_STATELESS)? "+H": "-H",
++ (p[5] & MPPE_56BIT)? "+M": "-M",
++ (p[5] & MPPE_128BIT)? "+S": "-S",
++ (p[5] & MPPE_40BIT)? "+L": "-L",
+ (p[5] & MPPE_D_BIT)? "+D": "-D",
+- (p[5] & MPPE_C_BIT)? "+C": "-C",
+- (mppe_opts & MPPE_OPT_UNKNOWN)? " +U": "");
+- if (mppe_opts & MPPE_OPT_UNKNOWN)
++ (p[5] & MPPE_MPPC)? "+C": "-C");
++ if ((p[5] & ~(MPPE_56BIT | MPPE_128BIT | MPPE_40BIT |
++ MPPE_D_BIT | MPPE_MPPC)) ||
++ (p[2] & ~MPPE_STATELESS))
+ printer(arg, " (%.2x %.2x %.2x %.2x)",
+ p[2], p[3], p[4], p[5]);
+ p += CILEN_MPPE;
+ }
+ break;
+-#endif
++#endif /* MPPE */
++ case CI_LZS:
++ if (optlen >= CILEN_LZS) {
++ printer(arg, "lzs %.2x %.2x %.2x", p[2], p[3], p[4]);
++ p += CILEN_LZS;
++ }
++ break;
+ case CI_DEFLATE:
+ case CI_DEFLATE_DRAFT:
+ if (optlen >= CILEN_DEFLATE) {
+@@ -1635,6 +2130,7 @@ ccp_datainput(unit, pkt, len)
+ error("Lost compression sync: disabling compression");
+ ccp_close(unit, "Lost compression sync");
+ #ifdef MPPE
++ /* My module dosn't need this. J.D., 2003-07-06 */
+ /*
+ * If we were doing MPPE, we must also take the link down.
+ */
+@@ -1642,9 +2138,18 @@ ccp_datainput(unit, pkt, len)
+ error("Too many MPPE errors, closing LCP");
+ lcp_close(unit, "Too many MPPE errors");
+ }
+-#endif
++#endif /* MPPE */
+ } else {
+ /*
++ * When LZS or MPPE/MPPC is negotiated we just send CCP_RESETREQ
++ * and don't wait for CCP_RESETACK
++ */
++ if ((ccp_gotoptions[f->unit].method == CI_LZS) ||
++ (ccp_gotoptions[f->unit].method == CI_MPPE)) {
++ fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
++ return;
++ }
++ /*
+ * Send a reset-request to reset the peer's compressor.
+ * We don't do that if we are still waiting for an
+ * acknowledgement to a previous reset-request.
+--- a/pppd/ccp.h
++++ b/pppd/ccp.h
+@@ -37,9 +37,17 @@ typedef struct ccp_options {
+ bool predictor_2; /* do Predictor-2? */
+ bool deflate_correct; /* use correct code for deflate? */
+ bool deflate_draft; /* use draft RFC code for deflate? */
++ bool lzs; /* do Stac LZS? */
++ bool mppc; /* do MPPC? */
+ bool mppe; /* do MPPE? */
++ bool mppe_40; /* allow 40 bit encryption? */
++ bool mppe_56; /* allow 56 bit encryption? */
++ bool mppe_128; /* allow 128 bit encryption? */
++ bool mppe_stateless; /* allow stateless encryption */
+ u_short bsd_bits; /* # bits/code for BSD Compress */
+ u_short deflate_size; /* lg(window size) for Deflate */
++ u_short lzs_mode; /* LZS check mode */
++ u_short lzs_hists; /* number of LZS histories */
+ short method; /* code for chosen compression method */
+ } ccp_options;
+
+--- a/pppd/chap_ms.c
++++ b/pppd/chap_ms.c
+@@ -898,13 +898,17 @@ set_mppe_enc_types(int policy, int types
+ /*
+ * Disable undesirable encryption types. Note that we don't ENABLE
+ * any encryption types, to avoid overriding manual configuration.
++ *
++ * It seems that 56 bit keys are unsupported in MS-RADIUS (see RFC 2548)
+ */
+ switch(types) {
+ case MPPE_ENC_TYPES_RC4_40:
+- ccp_wantoptions[0].mppe &= ~MPPE_OPT_128; /* disable 128-bit */
++ ccp_wantoptions[0].mppe_128 = 0; /* disable 128-bit */
++ ccp_wantoptions[0].mppe_56 = 0; /* disable 56-bit */
+ break;
+ case MPPE_ENC_TYPES_RC4_128:
+- ccp_wantoptions[0].mppe &= ~MPPE_OPT_40; /* disable 40-bit */
++ ccp_wantoptions[0].mppe_56 = 0; /* disable 56-bit */
++ ccp_wantoptions[0].mppe_40 = 0; /* disable 40-bit */
+ break;
+ default:
+ break;
diff --git a/package/ppp/patches/202-no_strip.patch b/package/ppp/patches/202-no_strip.patch
new file mode 100644
index 000000000..87c76ad0e
--- /dev/null
+++ b/package/ppp/patches/202-no_strip.patch
@@ -0,0 +1,88 @@
+build: Do not strip binaries on install
+
+Strippign executables should be handled by the distro packaging, not by ppp
+itself. This patch removes the "-s" (strip) switch from all "install" commands
+in order to install unstripped binaries into the destination prefix.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/chat/Makefile.linux
++++ b/chat/Makefile.linux
+@@ -25,7 +25,7 @@ chat.o: chat.c
+
+ install: chat
+ mkdir -p $(BINDIR) $(MANDIR)
+- $(INSTALL) -s -c chat $(BINDIR)
++ $(INSTALL) -c chat $(BINDIR)
+ $(INSTALL) -c -m 644 chat.8 $(MANDIR)
+
+ clean:
+--- a/pppd/Makefile.linux
++++ b/pppd/Makefile.linux
+@@ -99,7 +99,7 @@ ifdef USE_SRP
+ CFLAGS += -DUSE_SRP -DOPENSSL -I/usr/local/ssl/include
+ LIBS += -lsrp -L/usr/local/ssl/lib -lcrypto
+ TARGETS += srp-entry
+-EXTRAINSTALL = $(INSTALL) -s -c -m 555 srp-entry $(BINDIR)/srp-entry
++EXTRAINSTALL = $(INSTALL) -c -m 555 srp-entry $(BINDIR)/srp-entry
+ MANPAGES += srp-entry.8
+ EXTRACLEAN += srp-entry.o
+ NEEDDES=y
+@@ -200,7 +200,7 @@ all: $(TARGETS)
+ install: pppd
+ mkdir -p $(BINDIR) $(MANDIR)
+ $(EXTRAINSTALL)
+- $(INSTALL) -s -c -m 555 pppd $(BINDIR)/pppd
++ $(INSTALL) -c -m 555 pppd $(BINDIR)/pppd
+ if chgrp pppusers $(BINDIR)/pppd 2>/dev/null; then \
+ chmod o-rx,u+s $(BINDIR)/pppd; fi
+ $(INSTALL) -c -m 444 pppd.8 $(MANDIR)
+--- a/pppd/plugins/radius/Makefile.linux
++++ b/pppd/plugins/radius/Makefile.linux
+@@ -36,9 +36,9 @@ all: $(PLUGIN)
+
+ install: all
+ $(INSTALL) -d -m 755 $(LIBDIR)
+- $(INSTALL) -s -c -m 755 radius.so $(LIBDIR)
+- $(INSTALL) -s -c -m 755 radattr.so $(LIBDIR)
+- $(INSTALL) -s -c -m 755 radrealms.so $(LIBDIR)
++ $(INSTALL) -c -m 755 radius.so $(LIBDIR)
++ $(INSTALL) -c -m 755 radattr.so $(LIBDIR)
++ $(INSTALL) -c -m 755 radrealms.so $(LIBDIR)
+ $(INSTALL) -c -m 444 pppd-radius.8 $(MANDIR)
+ $(INSTALL) -c -m 444 pppd-radattr.8 $(MANDIR)
+
+--- a/pppd/plugins/rp-pppoe/Makefile.linux
++++ b/pppd/plugins/rp-pppoe/Makefile.linux
+@@ -43,9 +43,9 @@ rp-pppoe.so: plugin.o discovery.o if.o c
+
+ install: all
+ $(INSTALL) -d -m 755 $(LIBDIR)
+- $(INSTALL) -s -c -m 4550 rp-pppoe.so $(LIBDIR)
++ $(INSTALL) -c -m 4550 rp-pppoe.so $(LIBDIR)
+ $(INSTALL) -d -m 755 $(BINDIR)
+- $(INSTALL) -s -c -m 555 pppoe-discovery $(BINDIR)
++ $(INSTALL) -c -m 555 pppoe-discovery $(BINDIR)
+
+ clean:
+ rm -f *.o *.so pppoe-discovery
+--- a/pppdump/Makefile.linux
++++ b/pppdump/Makefile.linux
+@@ -17,5 +17,5 @@ clean:
+
+ install:
+ mkdir -p $(BINDIR) $(MANDIR)
+- $(INSTALL) -s -c pppdump $(BINDIR)
++ $(INSTALL) -c pppdump $(BINDIR)
+ $(INSTALL) -c -m 444 pppdump.8 $(MANDIR)
+--- a/pppstats/Makefile.linux
++++ b/pppstats/Makefile.linux
+@@ -22,7 +22,7 @@ all: pppstats
+
+ install: pppstats
+ -mkdir -p $(MANDIR)
+- $(INSTALL) -s -c pppstats $(BINDIR)
++ $(INSTALL) -c pppstats $(BINDIR)
+ $(INSTALL) -c -m 444 pppstats.8 $(MANDIR)
+
+ pppstats: $(PPPSTATSRCS)
diff --git a/package/ppp/patches/203-opt_flags.patch b/package/ppp/patches/203-opt_flags.patch
new file mode 100644
index 000000000..a36916352
--- /dev/null
+++ b/package/ppp/patches/203-opt_flags.patch
@@ -0,0 +1,32 @@
+build: Move optimization flags into a separate variable
+
+Isolate optimization related compiler flags from CFLAGS and move them into a
+separate COPTS variable so that it is easier to override optimizations from
+the environment.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/plugins/radius/Makefile.linux
++++ b/pppd/plugins/radius/Makefile.linux
+@@ -12,7 +12,8 @@ VERSION = $(shell awk -F '"' '/VERSION/
+ INSTALL = install
+
+ PLUGIN=radius.so radattr.so radrealms.so
+-CFLAGS=-I. -I../.. -I../../../include -O2 -fPIC -DRC_LOG_FACILITY=LOG_DAEMON
++COPTS = -O2
++CFLAGS=-I. -I../.. -I../../../include $(COPTS) -fPIC -DRC_LOG_FACILITY=LOG_DAEMON
+
+ # Uncomment the next line to include support for Microsoft's
+ # MS-CHAP authentication protocol.
+--- a/pppdump/Makefile.linux
++++ b/pppdump/Makefile.linux
+@@ -2,7 +2,8 @@ DESTDIR = $(INSTROOT)@DESTDIR@
+ BINDIR = $(DESTDIR)/sbin
+ MANDIR = $(DESTDIR)/share/man/man8
+
+-CFLAGS= -O -I../include/net
++COPTS = -O
++CFLAGS= $(COPTS) -I../include/net
+ OBJS = pppdump.o bsd-comp.o deflate.o zlib.o
+
+ INSTALL= install
diff --git a/package/ppp/patches/204-radius_config.patch b/package/ppp/patches/204-radius_config.patch
new file mode 100644
index 000000000..c97a53507
--- /dev/null
+++ b/package/ppp/patches/204-radius_config.patch
@@ -0,0 +1,72 @@
+--- a/pppd/plugins/radius/config.c
++++ b/pppd/plugins/radius/config.c
+@@ -369,31 +369,37 @@ static int test_config(char *filename)
+ }
+ #endif
+
++#if 0
+ if (rc_conf_int("login_tries") <= 0)
+ {
+ error("%s: login_tries <= 0 is illegal", filename);
+ return (-1);
+ }
++#endif
+ if (rc_conf_str("seqfile") == NULL)
+ {
+ error("%s: seqfile not specified", filename);
+ return (-1);
+ }
++#if 0
+ if (rc_conf_int("login_timeout") <= 0)
+ {
+ error("%s: login_timeout <= 0 is illegal", filename);
+ return (-1);
+ }
++#endif
+ if (rc_conf_str("mapfile") == NULL)
+ {
+ error("%s: mapfile not specified", filename);
+ return (-1);
+ }
++#if 0
+ if (rc_conf_str("nologin") == NULL)
+ {
+ error("%s: nologin not specified", filename);
+ return (-1);
+ }
++#endif
+
+ return 0;
+ }
+--- a/pppd/plugins/radius/options.h
++++ b/pppd/plugins/radius/options.h
+@@ -31,24 +31,21 @@ typedef struct _option {
+ static SERVER acctserver = {0};
+ static SERVER authserver = {0};
+
+-int default_tries = 4;
+-int default_timeout = 60;
+-
+ static OPTION config_options[] = {
+ /* internally used options */
+ {"config_file", OT_STR, ST_UNDEF, NULL},
+ /* General options */
+ {"auth_order", OT_AUO, ST_UNDEF, NULL},
+-{"login_tries", OT_INT, ST_UNDEF, &default_tries},
+-{"login_timeout", OT_INT, ST_UNDEF, &default_timeout},
+-{"nologin", OT_STR, ST_UNDEF, "/etc/nologin"},
+-{"issue", OT_STR, ST_UNDEF, "/etc/radiusclient/issue"},
++{"login_tries", OT_INT, ST_UNDEF, NULL},
++{"login_timeout", OT_INT, ST_UNDEF, NULL},
++{"nologin", OT_STR, ST_UNDEF, NULL},
++{"issue", OT_STR, ST_UNDEF, NULL},
+ /* RADIUS specific options */
+ {"authserver", OT_SRV, ST_UNDEF, &authserver},
+ {"acctserver", OT_SRV, ST_UNDEF, &acctserver},
+ {"servers", OT_STR, ST_UNDEF, NULL},
+ {"dictionary", OT_STR, ST_UNDEF, NULL},
+-{"login_radius", OT_STR, ST_UNDEF, "/usr/sbin/login.radius"},
++{"login_radius", OT_STR, ST_UNDEF, NULL},
+ {"seqfile", OT_STR, ST_UNDEF, NULL},
+ {"mapfile", OT_STR, ST_UNDEF, NULL},
+ {"default_realm", OT_STR, ST_UNDEF, NULL},
diff --git a/package/ppp/patches/205-no_exponential_timeout.patch b/package/ppp/patches/205-no_exponential_timeout.patch
new file mode 100644
index 000000000..7119fb83f
--- /dev/null
+++ b/package/ppp/patches/205-no_exponential_timeout.patch
@@ -0,0 +1,29 @@
+pppd: Don't use exponential timeout in discovery phase
+
+This patch removes the exponential timeout increase between PADO or PADS
+discovery attempts.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/plugins/rp-pppoe/discovery.c
++++ b/pppd/plugins/rp-pppoe/discovery.c
+@@ -548,7 +548,9 @@ discovery(PPPoEConnection *conn)
+ conn->discoveryState = STATE_SENT_PADI;
+ waitForPADO(conn, timeout);
+
++#if 0
+ timeout *= 2;
++#endif
+ } while (conn->discoveryState == STATE_SENT_PADI);
+
+ timeout = conn->discoveryTimeout;
+@@ -563,7 +565,9 @@ discovery(PPPoEConnection *conn)
+ sendPADR(conn);
+ conn->discoveryState = STATE_SENT_PADR;
+ waitForPADS(conn, timeout);
++#if 0
+ timeout *= 2;
++#endif
+ } while (conn->discoveryState == STATE_SENT_PADR);
+
+ /* We're done. */
diff --git a/package/ppp/patches/206-compensate_time_change.patch b/package/ppp/patches/206-compensate_time_change.patch
new file mode 100644
index 000000000..fb6c65679
--- /dev/null
+++ b/package/ppp/patches/206-compensate_time_change.patch
@@ -0,0 +1,94 @@
+pppd: Watch out for time warps
+
+On many embedded systems there is no battery backed RTC and a proper system
+time only becomes available through NTP after establishing a connection.
+
+When the clock suddenly jumps forward, the internal accounting (connect time)
+is confused resulting in unreliable data.
+
+This patch implements periodic clock checking to look for time warps, if one
+is detected, the internal counters are adjusted accordingly.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/main.c
++++ b/pppd/main.c
+@@ -90,6 +90,7 @@
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
++#include <sys/sysinfo.h>
+
+ #include "pppd.h"
+ #include "magic.h"
+@@ -228,6 +229,7 @@ static struct subprocess *children;
+
+ /* Prototypes for procedures local to this file. */
+
++static void check_time(void);
+ static void setup_signals __P((void));
+ static void create_pidfile __P((int pid));
+ static void create_linkpidfile __P((int pid));
+@@ -535,6 +537,7 @@ main(argc, argv)
+ info("Starting link");
+ }
+
++ check_time();
+ gettimeofday(&start_time, NULL);
+ script_unsetenv("CONNECT_TIME");
+ script_unsetenv("BYTES_SENT");
+@@ -1267,6 +1270,36 @@ struct callout {
+
+ static struct callout *callout = NULL; /* Callout list */
+ static struct timeval timenow; /* Current time */
++static long uptime_diff = 0;
++static int uptime_diff_set = 0;
++
++static void check_time(void)
++{
++ long new_diff;
++ struct timeval t;
++ struct sysinfo i;
++ struct callout *p;
++
++ gettimeofday(&t, NULL);
++ sysinfo(&i);
++ new_diff = t.tv_sec - i.uptime;
++
++ if (!uptime_diff_set) {
++ uptime_diff = new_diff;
++ uptime_diff_set = 1;
++ return;
++ }
++
++ if ((new_diff - 5 > uptime_diff) || (new_diff + 5 < uptime_diff)) {
++ /* system time has changed, update counters and timeouts */
++ info("System time change detected.");
++ start_time.tv_sec += new_diff - uptime_diff;
++
++ for (p = callout; p != NULL; p = p->c_next)
++ p->c_time.tv_sec += new_diff - uptime_diff;
++ }
++ uptime_diff = new_diff;
++}
+
+ /*
+ * timeout - Schedule a timeout.
+@@ -1337,6 +1370,8 @@ calltimeout()
+ {
+ struct callout *p;
+
++ check_time();
++
+ while (callout != NULL) {
+ p = callout;
+
+@@ -1364,6 +1399,8 @@ timeleft(tvp)
+ {
+ if (callout == NULL)
+ return NULL;
++
++ check_time();
+
+ gettimeofday(&timenow, NULL);
+ tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
diff --git a/package/ppp/patches/207-lcp_mtu_max.patch b/package/ppp/patches/207-lcp_mtu_max.patch
new file mode 100644
index 000000000..1ebcf412f
--- /dev/null
+++ b/package/ppp/patches/207-lcp_mtu_max.patch
@@ -0,0 +1,25 @@
+pppd: Cap MTU to the user configured value
+
+This patchs caps the calculated MTU value in lcp.c to the user specified "mru"
+option value. Without this patch pppd would advertise a different MTU value
+compared to what is set on the local interface in some cases.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/lcp.c
++++ b/pppd/lcp.c
+@@ -1904,12 +1904,12 @@ lcp_up(f)
+ * the interface MTU is set to the lowest of that, the
+ * MTU we want to use, and our link MRU.
+ */
+- mtu = ho->neg_mru? ho->mru: PPP_MRU;
++ mtu = MIN(ho->neg_mru? ho->mru: PPP_MRU, ao->mru);
+ mru = go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU;
+ #ifdef HAVE_MULTILINK
+ if (!(multilink && go->neg_mrru && ho->neg_mrru))
+ #endif /* HAVE_MULTILINK */
+- netif_set_mtu(f->unit, MIN(MIN(mtu, mru), ao->mru));
++ netif_set_mtu(f->unit, MIN(mtu, mru));
+ ppp_send_config(f->unit, mtu,
+ (ho->neg_asyncmap? ho->asyncmap: 0xffffffff),
+ ho->neg_pcompression, ho->neg_accompression);
diff --git a/package/ppp/patches/208-fix_status_code.patch b/package/ppp/patches/208-fix_status_code.patch
new file mode 100644
index 000000000..25e2a10b8
--- /dev/null
+++ b/package/ppp/patches/208-fix_status_code.patch
@@ -0,0 +1,24 @@
+pppd: Do not clobber exit codes on hangup
+
+When a modem hangup occurs, pppd unconditionally sets the exit status code
+to EXIT_HANGUP. This patch only sets EXIT_HANGUP if the exit status code is
+not already set to an error value.
+
+The motiviation of this patch is to allow applications which remote control
+pppd to react properly on errors, e.g. only redial (relaunch pppd) if there
+was a hangup, but not if the CHAP authentication failed.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/main.c
++++ b/pppd/main.c
+@@ -1048,7 +1048,8 @@ get_input()
+ }
+ notice("Modem hangup");
+ hungup = 1;
+- status = EXIT_HANGUP;
++ if (status == EXIT_OK)
++ status = EXIT_HANGUP;
+ lcp_lowerdown(0); /* serial link is no longer available */
+ link_terminated(0);
+ return;
diff --git a/package/ppp/patches/300-filter-pcap-includes-lib.patch b/package/ppp/patches/300-filter-pcap-includes-lib.patch
new file mode 100644
index 000000000..d8dcc64c8
--- /dev/null
+++ b/package/ppp/patches/300-filter-pcap-includes-lib.patch
@@ -0,0 +1,20 @@
+build: Add required CFLAGS for libpcap
+
+This patch adds some flags to required to properly link libpcap within the
+OpenWrt environment.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/Makefile.linux
++++ b/pppd/Makefile.linux
+@@ -170,8 +170,8 @@ endif
+
+ ifdef FILTER
+ ifneq ($(wildcard /usr/include/pcap-bpf.h),)
+-LIBS += -lpcap
+-CFLAGS += -DPPP_FILTER
++LIBS += -lpcap -L$(STAGING_DIR)/usr/lib
++CFLAGS += -DPPP_FILTER -I$(STAGING_DIR)/usr/include
+ endif
+ endif
+
diff --git a/package/ppp/patches/310-precompile_filter.patch b/package/ppp/patches/310-precompile_filter.patch
new file mode 100644
index 000000000..87b9687ef
--- /dev/null
+++ b/package/ppp/patches/310-precompile_filter.patch
@@ -0,0 +1,196 @@
+pppd: Implement support for precompiled pcap filters
+
+This patch implements support for precompiled pcap filters which is useful to
+support dial-on-demand on memory constrained embedded devices without having
+to link the full libpcap into pppd to generate the filters during runtime.
+
+Two new options are introduced; "precompiled-pass-filter" specifies a pre-
+compiled filter file containing rules to match packets which should be passed,
+"precompiled-active-filter" specifies a filter file containing rules to match
+packets which are treated as active.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/Makefile.linux
++++ b/pppd/Makefile.linux
+@@ -50,6 +50,9 @@ MPPE=y
+ # and that the kernel driver support PPP packet filtering.
+ #FILTER=y
+
++# Support for precompiled filters
++PRECOMPILED_FILTER=y
++
+ # Uncomment the next line to enable multilink PPP (enabled by default)
+ # Linux distributions: Please leave multilink ENABLED in your builds
+ # of pppd!
+@@ -175,6 +178,14 @@ CFLAGS += -DPPP_FILTER -I$(STAGING_DIR)
+ endif
+ endif
+
++ifdef PRECOMPILED_FILTER
++PPPDSRCS += pcap_pcc.c
++HEADERS += pcap_pcc.h
++PPPDOBJS += pcap_pcc.o
++LIBS += $(STAGING_DIR)/usr/lib/libpcap.a
++CFLAGS += -DPPP_FILTER -DPPP_PRECOMPILED_FILTER -I$(STAGING_DIR)/usr/include
++endif
++
+ ifdef HAVE_INET6
+ PPPDSRCS += ipv6cp.c eui64.c
+ HEADERS += ipv6cp.h eui64.h
+--- a/pppd/options.c
++++ b/pppd/options.c
+@@ -57,6 +57,7 @@
+
+ #ifdef PPP_FILTER
+ #include <pcap.h>
++#include <pcap-bpf.h>
+ /*
+ * There have been 3 or 4 different names for this in libpcap CVS, but
+ * this seems to be what they have settled on...
+@@ -162,6 +163,13 @@ static int setlogfile __P((char **));
+ static int loadplugin __P((char **));
+ #endif
+
++#ifdef PPP_PRECOMPILED_FILTER
++#include "pcap_pcc.h"
++static int setprecompiledpassfilter __P((char **));
++static int setprecompiledactivefilter __P((char **));
++#undef PPP_FILTER
++#endif
++
+ #ifdef PPP_FILTER
+ static int setpassfilter __P((char **));
+ static int setactivefilter __P((char **));
+@@ -326,6 +334,14 @@ option_t general_options[] = {
+ "set filter for active pkts", OPT_PRIO },
+ #endif
+
++#ifdef PPP_PRECOMPILED_FILTER
++ { "precompiled-pass-filter", 1, setprecompiledpassfilter,
++ "set precompiled filter for packets to pass", OPT_PRIO },
++
++ { "precompiled-active-filter", 1, setprecompiledactivefilter,
++ "set precompiled filter for active pkts", OPT_PRIO },
++#endif
++
+ #ifdef MAXOCTETS
+ { "maxoctets", o_int, &maxoctets,
+ "Set connection traffic limit",
+@@ -1472,6 +1488,29 @@ callfile(argv)
+ return ok;
+ }
+
++#ifdef PPP_PRECOMPILED_FILTER
++/*
++ * setprecompiledpassfilter - Set the pass filter for packets using a
++ * precompiled expression
++ */
++static int
++setprecompiledpassfilter(argv)
++ char **argv;
++{
++ return pcap_pre_compiled (*argv, &pass_filter);
++}
++
++/*
++ * setactivefilter - Set the active filter for packets
++ */
++static int
++setprecompiledactivefilter(argv)
++ char **argv;
++{
++ return pcap_pre_compiled (*argv, &active_filter);
++}
++#endif
++
+ #ifdef PPP_FILTER
+ /*
+ * setpassfilter - Set the pass filter for packets
+--- /dev/null
++++ b/pppd/pcap_pcc.c
+@@ -0,0 +1,74 @@
++#include <pcap.h>
++#include <pcap-bpf.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <errno.h>
++#include "pppd.h"
++
++int pcap_pre_compiled (char * fname, struct bpf_program *p)
++{
++ char buf[128];
++ int line = 0, size = 0, index=0, ret=1;
++ FILE *f = fopen (fname, "r");
++ if (!f)
++ {
++ option_error("error opening precompiled active-filter '%s': %s",
++ fname, strerror (errno));
++ return 0;
++ }
++ while (fgets (buf, 127, f))
++ {
++ line++;
++ if (*buf == '#')
++ continue;
++ if (size)
++ {
++ /*
++ struct bpf_insn {
++ u_short code;
++ u_char jt;
++ u_char jf;
++ bpf_int32 k;
++ }
++ */
++ struct bpf_insn * insn = & p->bf_insns[index];
++ unsigned code, jt, jf, k;
++ if (sscanf (buf, "%u %u %u %u", &code, &jt, &jf, &k) != 4)
++ {
++ goto err;
++ }
++ insn->code = code;
++ insn->jt = jt;
++ insn->jf = jf;
++ insn->k = k;
++ index++;
++ }
++ else
++ {
++ if (sscanf (buf, "%u", &size) != 1)
++ {
++ goto err;
++ }
++ p->bf_len = size;
++ p->bf_insns = (struct bpf_insn *)
++ malloc (size * sizeof (struct bpf_insn));
++ }
++ }
++ if (size != index)
++ {
++ option_error("error in precompiled active-filter,"
++ " expected %d expressions, got %dn",
++ size, index);
++ ret = 0;
++ }
++ fclose(f);
++ return ret;
++
++err:
++ option_error("error in precompiled active-filter"
++ " expression line %s:%d (wrong size)\n",
++ fname, line);
++ fclose (f);
++ return 0;
++}
+--- /dev/null
++++ b/pppd/pcap_pcc.h
+@@ -0,0 +1,7 @@
++#ifndef PCAP_PCC_H
++#define PCAP_PCC_H
++
++#include <pcap.h>
++
++int pcap_pre_compiled (char * fname, struct bpf_program *p);
++#endif /* PCAP_PCC_H */
diff --git a/package/ppp/patches/320-custom_iface_names.patch b/package/ppp/patches/320-custom_iface_names.patch
new file mode 100644
index 000000000..a95f4f8c8
--- /dev/null
+++ b/package/ppp/patches/320-custom_iface_names.patch
@@ -0,0 +1,135 @@
+pppd: Support arbitrary interface names
+
+This patch implements a new string option "ifname" which allows to specify
+fully custom PPP interface names on Linux. It does so by renaming the
+allocated pppX device immediately after it has been created to the requested
+interface name.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/main.c
++++ b/pppd/main.c
+@@ -745,8 +745,11 @@ void
+ set_ifunit(iskey)
+ int iskey;
+ {
+- info("Using interface %s%d", PPP_DRV_NAME, ifunit);
+- slprintf(ifname, sizeof(ifname), "%s%d", PPP_DRV_NAME, ifunit);
++ if (use_ifname[0] == 0)
++ slprintf(ifname, sizeof(ifname), "%s%d", PPP_DRV_NAME, ifunit);
++ else
++ slprintf(ifname, sizeof(ifname), "%s", use_ifname);
++ info("Using interface %s", ifname);
+ script_setenv("IFNAME", ifname, iskey);
+ if (iskey) {
+ create_pidfile(getpid()); /* write pid to file */
+--- a/pppd/options.c
++++ b/pppd/options.c
+@@ -111,6 +111,7 @@ int log_to_fd = 1; /* send log messages
+ bool log_default = 1; /* log_to_fd is default (stdout) */
+ int maxfail = 10; /* max # of unsuccessful connection attempts */
+ char linkname[MAXPATHLEN]; /* logical name for link */
++char use_ifname[IFNAMSIZ]; /* physical name for PPP link */
+ bool tune_kernel; /* may alter kernel settings */
+ int connect_delay = 1000; /* wait this many ms after connect script */
+ int req_unit = -1; /* requested interface unit */
+@@ -266,6 +267,9 @@ option_t general_options[] = {
+ { "linkname", o_string, linkname,
+ "Set logical name for link",
+ OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXPATHLEN },
++ { "ifname", o_string, use_ifname,
++ "Set physical name for PPP interface",
++ OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, IFNAMSIZ },
+
+ { "maxfail", o_int, &maxfail,
+ "Maximum number of unsuccessful connection attempts to allow",
+--- a/pppd/pppd.h
++++ b/pppd/pppd.h
+@@ -71,6 +71,10 @@
+ #include "eui64.h"
+ #endif
+
++#ifndef IFNAMSIZ
++#define IFNAMSIZ 16
++#endif
++
+ /*
+ * Limits.
+ */
+@@ -309,6 +313,7 @@ extern char *record_file; /* File to rec
+ extern bool sync_serial; /* Device is synchronous serial device */
+ extern int maxfail; /* Max # of unsuccessful connection attempts */
+ extern char linkname[MAXPATHLEN]; /* logical name for link */
++extern char use_ifname[IFNAMSIZ]; /* physical name for PPP interface */
+ extern bool tune_kernel; /* May alter kernel settings as necessary */
+ extern int connect_delay; /* Time to delay after connect script */
+ extern int max_data_rate; /* max bytes/sec through charshunt */
+--- a/pppd/sys-linux.c
++++ b/pppd/sys-linux.c
+@@ -168,6 +168,10 @@ struct in6_ifreq {
+ /* We can get an EIO error on an ioctl if the modem has hung up */
+ #define ok_error(num) ((num)==EIO)
+
++#if !defined(PPP_DRV_NAME)
++#define PPP_DRV_NAME "ppp"
++#endif /* !defined(PPP_DRV_NAME) */
++
+ static int tty_disc = N_TTY; /* The TTY discipline */
+ static int ppp_disc = N_PPP; /* The PPP discpline */
+ static int initfdflags = -1; /* Initial file descriptor flags for fd */
+@@ -622,7 +626,8 @@ void generic_disestablish_ppp(int dev_fd
+ */
+ static int make_ppp_unit()
+ {
+- int x, flags;
++ struct ifreq ifr;
++ int x, flags, s;
+
+ if (ppp_dev_fd >= 0) {
+ dbglog("in make_ppp_unit, already had /dev/ppp open?");
+@@ -645,6 +650,30 @@ static int make_ppp_unit()
+ }
+ if (x < 0)
+ error("Couldn't create new ppp unit: %m");
++
++ if (use_ifname[0] != 0) {
++ s = socket(PF_INET, SOCK_DGRAM, 0);
++ if (s < 0)
++ s = socket(PF_PACKET, SOCK_DGRAM, 0);
++ if (s < 0)
++ s = socket(PF_INET6, SOCK_DGRAM, 0);
++ if (s < 0)
++ s = socket(PF_UNIX, SOCK_DGRAM, 0);
++ if (s >= 0) {
++ slprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", PPP_DRV_NAME, ifunit);
++ slprintf(ifr.ifr_newname, sizeof(ifr.ifr_newname), "%s", use_ifname);
++ x = ioctl(s, SIOCSIFNAME, &ifr);
++ close(s);
++ } else {
++ x = s;
++ }
++ if (x < 0) {
++ error("Couldn't rename %s to %s", ifr.ifr_name, ifr.ifr_newname);
++ close(ppp_dev_fd);
++ ppp_dev_fd = -1;
++ }
++ }
++
+ return x;
+ }
+
+--- a/pppstats/pppstats.c
++++ b/pppstats/pppstats.c
+@@ -506,10 +506,12 @@ main(argc, argv)
+ if (argc > 0)
+ interface = argv[0];
+
++#if 0
+ if (sscanf(interface, PPP_DRV_NAME "%d", &unit) != 1) {
+ fprintf(stderr, "%s: invalid interface '%s' specified\n",
+ progname, interface);
+ }
++#endif
+
+ #ifndef STREAMS
+ {
diff --git a/package/ppp/patches/330-retain_foreign_default_routes.patch b/package/ppp/patches/330-retain_foreign_default_routes.patch
new file mode 100644
index 000000000..0d7fff9b4
--- /dev/null
+++ b/package/ppp/patches/330-retain_foreign_default_routes.patch
@@ -0,0 +1,22 @@
+pppd: Retain foreign default routes on Linux
+
+On Linux, when pppd attempts to delete its default route it does not fill
+the rt_dev field of the struct rtentry used to match the system default route.
+As a consequence, pppd happily deletes any default route even if it belongs
+to another interface.
+
+This patch makes pppd fill out the rt_dev field so that only own default
+routes are ever matched.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/sys-linux.c
++++ b/pppd/sys-linux.c
+@@ -1743,6 +1743,7 @@ int cifdefaultroute (int unit, u_int32_t
+ SIN_ADDR(rt.rt_genmask) = 0L;
+ }
+
++ rt.rt_dev = ifname;
+ rt.rt_flags = RTF_UP;
+ if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
+ if (still_ppp()) {
diff --git a/package/ppp/patches/340-populate_default_gateway.patch b/package/ppp/patches/340-populate_default_gateway.patch
new file mode 100644
index 000000000..9a0284eb2
--- /dev/null
+++ b/package/ppp/patches/340-populate_default_gateway.patch
@@ -0,0 +1,34 @@
+pppd: Fill in default gateway on Linux
+
+On Linux, when pppd creates the default route, it does not set the peer
+address as gateway, leading to a default route without gateway address.
+
+This behaviour breaks various downstream programs which attempt to infer
+the default gateway IP address from the system default route entry.
+
+This patch addresses the issue by filling in the peer address as gateway
+when generating the default route entry.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/sys-linux.c
++++ b/pppd/sys-linux.c
+@@ -1697,6 +1697,9 @@ int sifdefaultroute (int unit, u_int32_t
+ memset (&rt, 0, sizeof (rt));
+ SET_SA_FAMILY (rt.rt_dst, AF_INET);
+
++ SET_SA_FAMILY(rt.rt_gateway, AF_INET);
++ SIN_ADDR(rt.rt_gateway) = gateway;
++
+ rt.rt_dev = ifname;
+
+ if (kernel_version > KVERSION(2,1,0)) {
+@@ -1704,7 +1707,7 @@ int sifdefaultroute (int unit, u_int32_t
+ SIN_ADDR(rt.rt_genmask) = 0L;
+ }
+
+- rt.rt_flags = RTF_UP;
++ rt.rt_flags = RTF_UP | RTF_GATEWAY;
+ if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
+ if (!ok_error(errno))
+ error("default route ioctl(SIOCADDRT): %m");
diff --git a/package/ppp/patches/400-simplify_kernel_checks.patch b/package/ppp/patches/400-simplify_kernel_checks.patch
new file mode 100644
index 000000000..ec82576cb
--- /dev/null
+++ b/package/ppp/patches/400-simplify_kernel_checks.patch
@@ -0,0 +1,154 @@
+pppd: Remove runtime kernel checks
+
+On embedded system distributions the required kernel features for pppd are
+more or less guaranteed to be present, so there is not much point in
+performing runtime checks, it just increases the binary size.
+
+This patch removes the runtime kernel feature checks.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/sys-linux.c
++++ b/pppd/sys-linux.c
+@@ -203,7 +203,7 @@ static int driver_is_old = 0;
+ static int restore_term = 0; /* 1 => we've munged the terminal */
+ static struct termios inittermios; /* Initial TTY termios */
+
+-int new_style_driver = 0;
++static const int new_style_driver = 1;
+
+ static char loop_name[20];
+ static unsigned char inbuf[512]; /* buffer for chars read from loopback */
+@@ -220,8 +220,8 @@ static int looped; /* 1 if using loop
+ static int link_mtu; /* mtu for the link (not bundle) */
+
+ static struct utsname utsname; /* for the kernel version */
+-static int kernel_version;
+ #define KVERSION(j,n,p) ((j)*1000000 + (n)*1000 + (p))
++static const int kernel_version = KVERSION(2,6,37);
+
+ #define MAX_IFS 100
+
+@@ -1438,11 +1438,12 @@ int ccp_fatal_error (int unit)
+ *
+ * path_to_procfs - find the path to the proc file system mount point
+ */
+-static char proc_path[MAXPATHLEN];
+-static int proc_path_len;
++static char proc_path[MAXPATHLEN] = "/proc";
++static int proc_path_len = 5;
+
+ static char *path_to_procfs(const char *tail)
+ {
++#if 0
+ struct mntent *mntent;
+ FILE *fp;
+
+@@ -1464,6 +1465,7 @@ static char *path_to_procfs(const char *
+ fclose (fp);
+ }
+ }
++#endif
+
+ strlcpy(proc_path + proc_path_len, tail,
+ sizeof(proc_path) - proc_path_len);
+@@ -2116,15 +2118,19 @@ int ppp_available(void)
+ int my_version, my_modification, my_patch;
+ int osmaj, osmin, ospatch;
+
++#if 0
+ /* get the kernel version now, since we are called before sys_init */
+ uname(&utsname);
+ osmaj = osmin = ospatch = 0;
+ sscanf(utsname.release, "%d.%d.%d", &osmaj, &osmin, &ospatch);
+ kernel_version = KVERSION(osmaj, osmin, ospatch);
++#endif
+
+ fd = open("/dev/ppp", O_RDWR);
+ if (fd >= 0) {
++#if 0
+ new_style_driver = 1;
++#endif
+
+ /* XXX should get from driver */
+ driver_version = 2;
+@@ -2185,6 +2191,7 @@ int ppp_available(void)
+
+ if (ok && ((ifr.ifr_hwaddr.sa_family & ~0xFF) != ARPHRD_PPP))
+ ok = 0;
++ return ok;
+
+ /*
+ * This is the PPP device. Validate the version of the driver at this
+@@ -2678,6 +2685,7 @@ get_pty(master_fdp, slave_fdp, slave_nam
+ }
+ #endif /* TIOCGPTN */
+
++#if 0
+ if (sfd < 0) {
+ /* the old way - scan through the pty name space */
+ for (i = 0; i < 64; ++i) {
+@@ -2696,6 +2704,7 @@ get_pty(master_fdp, slave_fdp, slave_nam
+ }
+ }
+ }
++#endif
+
+ if (sfd < 0)
+ return 0;
+--- a/pppd/plugins/pppoatm/pppoatm.c
++++ b/pppd/plugins/pppoatm/pppoatm.c
+@@ -170,14 +170,6 @@ static void disconnect_pppoatm(void)
+
+ void plugin_init(void)
+ {
+-#if defined(__linux__)
+- extern int new_style_driver; /* From sys-linux.c */
+- if (!ppp_available() && !new_style_driver)
+- fatal("Kernel doesn't support ppp_generic - "
+- "needed for PPPoATM");
+-#else
+- fatal("No PPPoATM support on this OS");
+-#endif
+ info("PPPoATM plugin_init");
+ add_options(pppoa_options);
+ }
+--- a/pppd/plugins/rp-pppoe/plugin.c
++++ b/pppd/plugins/rp-pppoe/plugin.c
+@@ -60,9 +60,6 @@ static char const RCSID[] =
+
+ char pppd_version[] = VERSION;
+
+-/* From sys-linux.c in pppd -- MUST FIX THIS! */
+-extern int new_style_driver;
+-
+ char *pppd_pppoe_service = NULL;
+ static char *acName = NULL;
+ static char *existingSession = NULL;
+@@ -340,10 +337,6 @@ PPPoEDevnameHook(char *cmd, char **argv,
+ void
+ plugin_init(void)
+ {
+- if (!ppp_available() && !new_style_driver) {
+- fatal("Linux kernel does not support PPPoE -- are you running 2.4.x?");
+- }
+-
+ add_options(Options);
+
+ info("RP-PPPoE plugin version %s compiled against pppd %s",
+--- a/pppd/plugins/pppol2tp/pppol2tp.c
++++ b/pppd/plugins/pppol2tp/pppol2tp.c
+@@ -500,12 +500,7 @@ static void pppol2tp_cleanup(void)
+
+ void plugin_init(void)
+ {
+-#if defined(__linux__)
+- extern int new_style_driver; /* From sys-linux.c */
+- if (!ppp_available() && !new_style_driver)
+- fatal("Kernel doesn't support ppp_generic - "
+- "needed for PPPoL2TP");
+-#else
++#if !defined(__linux__)
+ fatal("No PPPoL2TP support on this OS");
+ #endif
+ add_options(pppol2tp_options);
diff --git a/package/ppp/patches/401-no_record_file.patch b/package/ppp/patches/401-no_record_file.patch
new file mode 100644
index 000000000..94c0263ea
--- /dev/null
+++ b/package/ppp/patches/401-no_record_file.patch
@@ -0,0 +1,39 @@
+pppd: Remove the "record" option
+
+On many embedded systems there is not enough space to record PPP session
+information to the permanent storage, therfore remove this option.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/pppd.h
++++ b/pppd/pppd.h
+@@ -309,7 +309,6 @@ extern int holdoff; /* Dead time before
+ extern bool holdoff_specified; /* true if user gave a holdoff value */
+ extern bool notty; /* Stdin/out is not a tty */
+ extern char *pty_socket; /* Socket to connect to pty */
+-extern char *record_file; /* File to record chars sent/received */
+ extern bool sync_serial; /* Device is synchronous serial device */
+ extern int maxfail; /* Max # of unsuccessful connection attempts */
+ extern char linkname[MAXPATHLEN]; /* logical name for link */
+--- a/pppd/tty.c
++++ b/pppd/tty.c
+@@ -145,7 +145,7 @@ char *disconnect_script = NULL; /* Scrip
+ char *welcomer = NULL; /* Script to run after phys link estab. */
+ char *ptycommand = NULL; /* Command to run on other side of pty */
+ bool notty = 0; /* Stdin/out is not a tty */
+-char *record_file = NULL; /* File to record chars sent/received */
++static char *const record_file = NULL; /* File to record chars sent/received */
+ int max_data_rate; /* max bytes/sec through charshunt */
+ bool sync_serial = 0; /* Device is synchronous serial device */
+ char *pty_socket = NULL; /* Socket to connect to pty */
+@@ -201,8 +201,10 @@ option_t tty_options[] = {
+ "Send and receive over socket, arg is host:port",
+ OPT_PRIO | OPT_DEVNAM },
+
++#if 0
+ { "record", o_string, &record_file,
+ "Record characters sent/received to file", OPT_PRIO },
++#endif
+
+ { "crtscts", o_int, &crtscts,
+ "Set hardware (RTS/CTS) flow control",
diff --git a/package/ppp/patches/403-no_wtmp.patch b/package/ppp/patches/403-no_wtmp.patch
new file mode 100644
index 000000000..71233200e
--- /dev/null
+++ b/package/ppp/patches/403-no_wtmp.patch
@@ -0,0 +1,25 @@
+pppd: Disable wtmp support
+
+Many uClibc based environments lack wtmp and utmp support, therfore remove
+the code updating the wtmp information.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/sys-linux.c
++++ b/pppd/sys-linux.c
+@@ -2254,6 +2254,7 @@ int ppp_available(void)
+
+ void logwtmp (const char *line, const char *name, const char *host)
+ {
++#if 0
+ struct utmp ut, *utp;
+ pid_t mypid = getpid();
+ #if __GLIBC__ < 2
+@@ -2319,6 +2320,7 @@ void logwtmp (const char *line, const ch
+ close (wtmp);
+ }
+ #endif
++#endif
+ }
+
+
diff --git a/package/ppp/patches/404-remove_obsolete_protocol_names.patch b/package/ppp/patches/404-remove_obsolete_protocol_names.patch
new file mode 100644
index 000000000..edbca7603
--- /dev/null
+++ b/package/ppp/patches/404-remove_obsolete_protocol_names.patch
@@ -0,0 +1,151 @@
+pppd: Remove historical protocol names
+
+Remove a number of historical protocol entries from pppd's builtin list, this
+reduced the binary size without loss of features.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/main.c
++++ b/pppd/main.c
+@@ -882,14 +882,17 @@ struct protocol_list {
+ const char *name;
+ } protocol_list[] = {
+ { 0x21, "IP" },
++#if 0
+ { 0x23, "OSI Network Layer" },
+ { 0x25, "Xerox NS IDP" },
+ { 0x27, "DECnet Phase IV" },
+ { 0x29, "Appletalk" },
+ { 0x2b, "Novell IPX" },
++#endif
+ { 0x2d, "VJ compressed TCP/IP" },
+ { 0x2f, "VJ uncompressed TCP/IP" },
+ { 0x31, "Bridging PDU" },
++#if 0
+ { 0x33, "Stream Protocol ST-II" },
+ { 0x35, "Banyan Vines" },
+ { 0x39, "AppleTalk EDDP" },
+@@ -903,8 +906,11 @@ struct protocol_list {
+ { 0x49, "Serial Data Transport Protocol (PPP-SDTP)" },
+ { 0x4b, "SNA over 802.2" },
+ { 0x4d, "SNA" },
++#endif
+ { 0x4f, "IP6 Header Compression" },
++#if 0
+ { 0x51, "KNX Bridging Data" },
++#endif
+ { 0x53, "Encryption" },
+ { 0x55, "Individual Link Encryption" },
+ { 0x57, "IPv6" },
+@@ -915,12 +921,15 @@ struct protocol_list {
+ { 0x65, "RTP IPHC Compressed non-TCP" },
+ { 0x67, "RTP IPHC Compressed UDP 8" },
+ { 0x69, "RTP IPHC Compressed RTP 8" },
++#if 0
+ { 0x6f, "Stampede Bridging" },
+ { 0x73, "MP+" },
+ { 0xc1, "NTCITS IPI" },
++#endif
+ { 0xfb, "single-link compression" },
+ { 0xfd, "Compressed Datagram" },
+ { 0x0201, "802.1d Hello Packets" },
++#if 0
+ { 0x0203, "IBM Source Routing BPDU" },
+ { 0x0205, "DEC LANBridge100 Spanning Tree" },
+ { 0x0207, "Cisco Discovery Protocol" },
+@@ -932,15 +941,19 @@ struct protocol_list {
+ { 0x0231, "Luxcom" },
+ { 0x0233, "Sigma Network Systems" },
+ { 0x0235, "Apple Client Server Protocol" },
++#endif
+ { 0x0281, "MPLS Unicast" },
+ { 0x0283, "MPLS Multicast" },
++#if 0
+ { 0x0285, "IEEE p1284.4 standard - data packets" },
+ { 0x0287, "ETSI TETRA Network Protocol Type 1" },
++#endif
+ { 0x0289, "Multichannel Flow Treatment Protocol" },
+ { 0x2063, "RTP IPHC Compressed TCP No Delta" },
+ { 0x2065, "RTP IPHC Context State" },
+ { 0x2067, "RTP IPHC Compressed UDP 16" },
+ { 0x2069, "RTP IPHC Compressed RTP 16" },
++#if 0
+ { 0x4001, "Cray Communications Control Protocol" },
+ { 0x4003, "CDPD Mobile Network Registration Protocol" },
+ { 0x4005, "Expand accelerator protocol" },
+@@ -951,8 +964,10 @@ struct protocol_list {
+ { 0x4023, "RefTek Protocol" },
+ { 0x4025, "Fibre Channel" },
+ { 0x4027, "EMIT Protocols" },
++#endif
+ { 0x405b, "Vendor-Specific Protocol (VSP)" },
+ { 0x8021, "Internet Protocol Control Protocol" },
++#if 0
+ { 0x8023, "OSI Network Layer Control Protocol" },
+ { 0x8025, "Xerox NS IDP Control Protocol" },
+ { 0x8027, "DECnet Phase IV Control Protocol" },
+@@ -961,7 +976,9 @@ struct protocol_list {
+ { 0x8031, "Bridging NCP" },
+ { 0x8033, "Stream Protocol Control Protocol" },
+ { 0x8035, "Banyan Vines Control Protocol" },
++#endif
+ { 0x803d, "Multi-Link Control Protocol" },
++#if 0
+ { 0x803f, "NETBIOS Framing Control Protocol" },
+ { 0x8041, "Cisco Systems Control Protocol" },
+ { 0x8043, "Ascom Timeplex" },
+@@ -970,18 +987,24 @@ struct protocol_list {
+ { 0x8049, "Serial Data Control Protocol (PPP-SDCP)" },
+ { 0x804b, "SNA over 802.2 Control Protocol" },
+ { 0x804d, "SNA Control Protocol" },
++#endif
+ { 0x804f, "IP6 Header Compression Control Protocol" },
++#if 0
+ { 0x8051, "KNX Bridging Control Protocol" },
++#endif
+ { 0x8053, "Encryption Control Protocol" },
+ { 0x8055, "Individual Link Encryption Control Protocol" },
+ { 0x8057, "IPv6 Control Protocol" },
+ { 0x8059, "PPP Muxing Control Protocol" },
+ { 0x805b, "Vendor-Specific Network Control Protocol (VSNCP)" },
++#if 0
+ { 0x806f, "Stampede Bridging Control Protocol" },
+ { 0x8073, "MP+ Control Protocol" },
+ { 0x80c1, "NTCITS IPI Control Protocol" },
++#endif
+ { 0x80fb, "Single Link Compression Control Protocol" },
+ { 0x80fd, "Compression Control Protocol" },
++#if 0
+ { 0x8207, "Cisco Discovery Protocol Control" },
+ { 0x8209, "Netcs Twin Routing" },
+ { 0x820b, "STP - Control Protocol" },
+@@ -990,24 +1013,29 @@ struct protocol_list {
+ { 0x8281, "MPLSCP" },
+ { 0x8285, "IEEE p1284.4 standard - Protocol Control" },
+ { 0x8287, "ETSI TETRA TNP1 Control Protocol" },
++#endif
+ { 0x8289, "Multichannel Flow Treatment Protocol" },
+ { 0xc021, "Link Control Protocol" },
+ { 0xc023, "Password Authentication Protocol" },
+ { 0xc025, "Link Quality Report" },
++#if 0
+ { 0xc027, "Shiva Password Authentication Protocol" },
+ { 0xc029, "CallBack Control Protocol (CBCP)" },
+ { 0xc02b, "BACP Bandwidth Allocation Control Protocol" },
+ { 0xc02d, "BAP" },
++#endif
+ { 0xc05b, "Vendor-Specific Authentication Protocol (VSAP)" },
+ { 0xc081, "Container Control Protocol" },
+ { 0xc223, "Challenge Handshake Authentication Protocol" },
+ { 0xc225, "RSA Authentication Protocol" },
+ { 0xc227, "Extensible Authentication Protocol" },
++#if 0
+ { 0xc229, "Mitsubishi Security Info Exch Ptcl (SIEP)" },
+ { 0xc26f, "Stampede Bridging Authorization Protocol" },
+ { 0xc281, "Proprietary Authentication Protocol" },
+ { 0xc283, "Proprietary Authentication Protocol" },
+ { 0xc481, "Proprietary Node ID Authentication Protocol" },
++#endif
+ { 0, NULL },
+ };
+
diff --git a/package/ppp/patches/405-no_multilink_option.patch b/package/ppp/patches/405-no_multilink_option.patch
new file mode 100644
index 000000000..97a79c474
--- /dev/null
+++ b/package/ppp/patches/405-no_multilink_option.patch
@@ -0,0 +1,28 @@
+pppd: Support "nomp" option even if multilink support is off
+
+This patch moves the "nomp" option entry outside of the defines protecting
+the multilink specific code. The motivation is to allow "nomp" even if pppd
+does not support multilink, so that controlling programs can unconditionally
+pass it to pppd regardless of the compile time features.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/pppd/options.c
++++ b/pppd/options.c
+@@ -318,13 +318,14 @@ option_t general_options[] = {
+ "Enable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 1 },
+ { "nomultilink", o_bool, &multilink,
+ "Disable multilink operation", OPT_PRIOSUB | 0 },
+- { "nomp", o_bool, &multilink,
+- "Disable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 0 },
+
+ { "bundle", o_string, &bundle_name,
+ "Bundle name for multilink", OPT_PRIO },
+ #endif /* HAVE_MULTILINK */
+
++ { "nomp", o_bool, &multilink,
++ "Disable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 0 },
++
+ #ifdef PLUGIN
+ { "plugin", o_special, (void *)loadplugin,
+ "Load a plug-in module into pppd", OPT_PRIV | OPT_A2LIST },
diff --git a/package/ppp/patches/430-pppol2tpv3-struct.patch b/package/ppp/patches/430-pppol2tpv3-struct.patch
new file mode 100644
index 000000000..4f517df76
--- /dev/null
+++ b/package/ppp/patches/430-pppol2tpv3-struct.patch
@@ -0,0 +1,30 @@
+pppol2tp: Provide struct pppol2tpv3_addr to align with Linux
+
+The struct pppol2tpv3_addr is referenced in the current Linux kernel sources
+but not provided by the shipped kernel headers, add it.
+
+Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
+
+--- a/include/linux/if_pppol2tp.h
++++ b/include/linux/if_pppol2tp.h
+@@ -32,6 +32,20 @@ struct pppol2tp_addr
+ __u16 d_tunnel, d_session; /* For sending outgoing packets */
+ };
+
++/* The L2TPv3 protocol changes tunnel and session ids from 16 to 32
++ * bits. So we need a different sockaddr structure.
++ */
++struct pppol2tpv3_addr {
++ pid_t pid; /* pid that owns the fd.
++ * 0 => current */
++ int fd; /* FD of UDP or IP socket to use */
++
++ struct sockaddr_in addr; /* IP address and port to send to */
++
++ __u32 s_tunnel, s_session; /* For matching incoming packets */
++ __u32 d_tunnel, d_session; /* For sending outgoing packets */
++};
++
+ /* Socket options:
+ * DEBUG - bitmask of debug message categories
+ * SENDSEQ - 0 => don't send packets with sequence numbers
diff --git a/package/ppp/patches/500-add-pptp-plugin.patch b/package/ppp/patches/500-add-pptp-plugin.patch
new file mode 100644
index 000000000..d984e1b16
--- /dev/null
+++ b/package/ppp/patches/500-add-pptp-plugin.patch
@@ -0,0 +1,3065 @@
+--- a/configure
++++ b/configure
+@@ -195,7 +195,7 @@ if [ -d "$ksrc" ]; then
+ mkmkf $ksrc/Makedefs$compiletype Makedefs.com
+ for dir in pppd pppstats chat pppdump pppd/plugins pppd/plugins/rp-pppoe \
+ pppd/plugins/radius pppd/plugins/pppoatm \
+- pppd/plugins/pppol2tp; do
++ pppd/plugins/pppol2tp pppd/plugins/pptp ; do
+ mkmkf $dir/Makefile.$makext $dir/Makefile
+ done
+ if [ -f $ksrc/Makefile.$makext$archvariant ]; then
+--- a/pppd/plugins/Makefile.linux
++++ b/pppd/plugins/Makefile.linux
+@@ -9,7 +9,7 @@ BINDIR = $(DESTDIR)/sbin
+ MANDIR = $(DESTDIR)/share/man/man8
+ LIBDIR = $(DESTDIR)/lib/pppd/$(VERSION)
+
+-SUBDIRS := rp-pppoe pppoatm pppol2tp
++SUBDIRS := rp-pppoe pppoatm pppol2tp pptp
+ # Uncomment the next line to include the radius authentication plugin
+ SUBDIRS += radius
+ PLUGINS := minconn.so passprompt.so passwordfd.so winbind.so
+--- /dev/null
++++ b/pppd/plugins/pptp/Makefile.linux
+@@ -0,0 +1,31 @@
++#
++# This program may be distributed according to the terms of the GNU
++# General Public License, version 2 or (at your option) any later version.
++#
++# $Id: Makefile.linux,v 1.9 2012/05/04 21:48:00 dgolle Exp $
++#***********************************************************************
++
++DESTDIR = $(INSTROOT)@DESTDIR@
++LIBDIR = $(DESTDIR)/lib/pppd/$(PPPDVERSION)
++
++PPPDVERSION = $(shell awk -F '"' '/VERSION/ { print $$2; }' ../../patchlevel.h)
++
++INSTALL = install
++
++COPTS=-O2 -g
++CFLAGS = $(COPTS) -I. -I../.. -I../../../include -fPIC -DPPPD_VERSION=\"$(PPPDVERSION)\"
++all: pptp.so
++
++%.o: %.c
++ $(CC) $(CFLAGS) -c -o $@ $<
++
++pptp.so: dirutil.o orckit_quirks.o pptp.o pptp_callmgr.o pptp_ctrl.o pptp_quirks.o util.o vector.o
++ $(CC) -o pptp.so -shared dirutil.o orckit_quirks.o pptp.o pptp_callmgr.o pptp_ctrl.o pptp_quirks.o util.o vector.o
++
++install: all
++ $(INSTALL) -d -m 755 $(LIBDIR)
++ $(INSTALL) -c -m 4550 pptp.so $(LIBDIR)
++
++clean:
++ rm -f *.o *.so
++
+--- /dev/null
++++ b/pppd/plugins/pptp/dirutil.c
+@@ -0,0 +1,68 @@
++/* dirutil.c ... directory utilities.
++ * C. Scott Ananian <cananian@alumni.princeton.edu>
++ *
++ * $Id: dirutil.c,v 1.2 2003/06/17 17:25:47 reink Exp $
++ */
++
++#include <sys/stat.h>
++#include <sys/types.h>
++#include <unistd.h>
++#include <string.h>
++#include <stdlib.h>
++#include "dirutil.h"
++
++/* Returned malloc'ed string representing basename */
++char *basenamex(char *pathname)
++{
++ char *dup = strdup(pathname);
++ char *ptr = strrchr(stripslash(dup), '/');
++ if (ptr == NULL) return dup;
++ ptr = strdup(ptr+1);
++ free(dup);
++ return ptr;
++}
++
++/* Return malloc'ed string representing directory name (no trailing slash) */
++char *dirnamex(char *pathname)
++{
++ char *dup = strdup(pathname);
++ char *ptr = strrchr(stripslash(dup), '/');
++ if (ptr == NULL) { free(dup); return strdup("."); }
++ if (ptr == dup && dup[0] == '/') ptr++;
++ *ptr = '\0';
++ return dup;
++}
++
++/* In-place modify a string to remove trailing slashes. Returns arg.
++ * stripslash("/") returns "/";
++ */
++char *stripslash(char *pathname) {
++ int len = strlen(pathname);
++ while (len > 1 && pathname[len - 1] == '/')
++ pathname[--len] = '\0';
++ return pathname;
++}
++
++/* ensure dirname exists, creating it if necessary. */
++int make_valid_path(char *dir, mode_t mode)
++{
++ struct stat st;
++ char *tmp = NULL, *path = stripslash(strdup(dir));
++ int retval;
++ if (stat(path, &st) == 0) { /* file exists */
++ if (S_ISDIR(st.st_mode)) { retval = 1; goto end; }
++ else { retval = 0; goto end; } /* not a directory. Oops. */
++ }
++ /* Directory doesn't exist. Let's make it. */
++ /* Make parent first. */
++ if (!make_valid_path(tmp = dirnamex(path), mode)) { retval = 0; goto end; }
++ /* Now make this 'un. */
++ if (mkdir(path, mode) < 0) { retval = 0; goto end; }
++ /* Success. */
++ retval = 1;
++
++end:
++ if (tmp != NULL) free(tmp);
++ if (path != NULL) free(path);
++ return retval;
++}
+--- /dev/null
++++ b/pppd/plugins/pptp/dirutil.h
+@@ -0,0 +1,14 @@
++/* dirutil.h ... directory utilities.
++ * C. Scott Ananian <cananian@alumni.princeton.edu>
++ *
++ * $Id: dirutil.h,v 1.1.1.1 2000/12/23 08:19:51 scott Exp $
++ */
++
++/* Returned malloc'ed string representing basename */
++char *basenamex(char *pathname);
++/* Return malloc'ed string representing directory name (no trailing slash) */
++char *dirnamex(char *pathname);
++/* In-place modify a string to remove trailing slashes. Returns arg. */
++char *stripslash(char *pathname);
++/* ensure dirname exists, creating it if necessary. */
++int make_valid_path(char *dirname, mode_t mode);
+--- /dev/null
++++ b/pppd/plugins/pptp/orckit_quirks.c
+@@ -0,0 +1,86 @@
++/* orckit_quirks.c ...... fix quirks in orckit adsl modems
++ * mulix <mulix@actcom.co.il>
++ *
++ * $Id: orckit_quirks.c,v 1.3 2002/03/01 01:23:36 quozl Exp $
++ */
++
++#include <string.h>
++#include <sys/types.h>
++#include <netinet/in.h>
++#include "pptp_msg.h"
++#include "pptp_options.h"
++#include "pptp_ctrl.h"
++#include "util.h"
++
++
++
++/* return 0 on success, non zero otherwise */
++int
++orckit_atur3_build_hook(struct pptp_out_call_rqst* packet)
++{
++ unsigned int name_length = 10;
++
++ struct pptp_out_call_rqst fixed_packet = {
++ PPTP_HEADER_CTRL(PPTP_OUT_CALL_RQST),
++ 0, /* hton16(call->callid) */
++ 0, /* hton16(call->sernum) */
++ hton32(PPTP_BPS_MIN), hton32(PPTP_BPS_MAX),
++ hton32(PPTP_BEARER_DIGITAL), hton32(PPTP_FRAME_ANY),
++ hton16(PPTP_WINDOW), 0, hton16(name_length), 0,
++ {'R','E','L','A','Y','_','P','P','P','1',0}, {0}
++ };
++
++ if (!packet)
++ return -1;
++
++ memcpy(packet, &fixed_packet, sizeof(*packet));
++
++ return 0;
++}
++
++/* return 0 on success, non zero otherwise */
++int
++orckit_atur3_set_link_hook(struct pptp_set_link_info* packet,
++ int peer_call_id)
++{
++ struct pptp_set_link_info fixed_packet = {
++ PPTP_HEADER_CTRL(PPTP_SET_LINK_INFO),
++ hton16(peer_call_id),
++ 0,
++ 0xffffffff,
++ 0xffffffff};
++
++ if (!packet)
++ return -1;
++
++ memcpy(packet, &fixed_packet, sizeof(*packet));
++ return 0;
++}
++
++/* return 0 on success, non 0 otherwise */
++int
++orckit_atur3_start_ctrl_conn_hook(struct pptp_start_ctrl_conn* packet)
++{
++ struct pptp_start_ctrl_conn fixed_packet = {
++ {0}, /* we'll set the header later */
++ hton16(PPTP_VERSION), 0, 0,
++ hton32(PPTP_FRAME_ASYNC), hton32(PPTP_BEARER_ANALOG),
++ hton16(0) /* max channels */,
++ hton16(0x6021),
++ {'R','E','L','A','Y','_','P','P','P','1',0}, /* hostname */
++ {'M','S',' ','W','i','n',' ','N','T',0} /* vendor */
++ };
++
++ if (!packet)
++ return -1;
++
++ /* grab the header from the original packet, since we dont
++ know if this is a request or a reply */
++ memcpy(&fixed_packet.header, &packet->header, sizeof(struct pptp_header));
++
++ /* and now overwrite the full packet, effectively preserving the header */
++ memcpy(packet, &fixed_packet, sizeof(*packet));
++ return 0;
++}
++
++
+--- /dev/null
++++ b/pppd/plugins/pptp/orckit_quirks.h
+@@ -0,0 +1,27 @@
++/* orckit_quirks.h ...... fix quirks in orckit adsl modems
++ * mulix <mulix@actcom.co.il>
++ *
++ * $Id: orckit_quirks.h,v 1.2 2001/11/23 03:42:51 quozl Exp $
++ */
++
++#ifndef INC_ORCKIT_QUIRKS_H_
++#define INC_ORCKIT_QUIRKS_H_
++
++#include "pptp_options.h"
++#include "pptp_ctrl.h"
++#include "pptp_msg.h"
++
++/* return 0 on success, non zero otherwise */
++int
++orckit_atur3_build_hook(struct pptp_out_call_rqst* packt);
++
++/* return 0 on success, non zero otherwise */
++int
++orckit_atur3_set_link_hook(struct pptp_set_link_info* packet,
++ int peer_call_id);
++
++/* return 0 on success, non zero otherwise */
++int
++orckit_atur3_start_ctrl_conn_hook(struct pptp_start_ctrl_conn* packet);
++
++#endif /* INC_ORCKIT_QUIRKS_H_ */
+--- /dev/null
++++ b/pppd/plugins/pptp/pppd-pptp.8
+@@ -0,0 +1,68 @@
++.\" manual page [] for PPTP plugin for pppd 2.4
++.\" $Id: pppd-pptp.8,v 1.0 2007/10/17 13:27:17 kad Exp $
++.\" SH section heading
++.\" SS subsection heading
++.\" LP paragraph
++.\" IP indented paragraph
++.\" TP hanging label
++.TH PPPD-PPTP 8
++.SH NAME
++pptp.so \- PPTP VPN plugin for
++.BR pppd (8)
++.SH SYNOPSIS
++.B pppd
++[
++.I options
++]
++plugin pptp.so
++.SH DESCRIPTION
++.LP
++The PPTP plugin for pppd performs interaction with pptp kernel module
++and has built-in call manager (client part of PPTP).
++It pasees necessary paremeters from \fIoptions\fR into kernel module
++to configure ppp-pptp channel. If it runs in client mode, then additionally
++call manager starts up. PPTPD daemon automaticaly invokes this plugin
++in server mode and passes necessary options, so additional configuration
++is not needed.
++
++.SH OPTIONS for client mode
++The PPTP plugin introduces one additional pppd option:
++.TP
++.BI "pptp_server " server " (required)"
++Specifies ip address or hostname of pptp server.
++.TP
++.BI "pptp_window " packets " (optional)"
++The amount of sliding window size.
++Set to 0 to turn off sliding window.
++ to 3-10 for low speed connections.
++ to >10 for hi speed connections.
++Default is 50
++.TP
++.BI "pptp_phone " phone " (optional)"
++The phone string that sended to pptp server.
++.SH USAGE
++Sample configuration file:
++.nf
++plugin "pptp.so"
++pptp_server 192.168.0.1
++pptp_window 100
++name myname
++remotename pptp
++noauth
++refuse-eap
++refuse-chap
++refuse-mschap
++nobsdcomp
++nodeflate
++novj
++novjccomp
++require-mppe-128
++lcp-echo-interval 20
++lcp-echo-failure 3
++.fi
++
++.SH SEE ALSO
++.BR pppd (8) " " pptpd (8) " " pptpd.conf (5)
++
++.SH AUTHOR
++xeb xeb@mail.ru
+--- /dev/null
++++ b/pppd/plugins/pptp/pptp.c
+@@ -0,0 +1,323 @@
++/***************************************************************************
++ * Copyright (C) 2006 by Kozlov D. <xeb@mail.ru> *
++ * some cleanup done (C) 2012 by Daniel Golle <dgolle@allnet.de> *
++ * *
++ * This program is free software; you can redistribute it and/or modify *
++ * it under the terms of the GNU General Public License as published by *
++ * the Free Software Foundation; either version 2 of the License, or *
++ * (at your option) any later version. *
++ * *
++ * 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. *
++ ***************************************************************************/
++
++#define PPTP_VERSION "1.00"
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include <netinet/in.h>
++#include <arpa/inet.h>
++#include <sys/un.h>
++#include <netdb.h>
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++#include <syslog.h>
++#include <unistd.h>
++#include <signal.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <sys/wait.h>
++#include <sys/ioctl.h>
++
++#include "pppd.h"
++#include "fsm.h"
++#include "lcp.h"
++#include "ipcp.h"
++#include "ccp.h"
++#include "pathnames.h"
++
++#include "pptp_callmgr.h"
++#include <net/if.h>
++#include <net/ethernet.h>
++#include <linux/if_pppox.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++
++
++
++extern char** environ;
++
++char pppd_version[] = PPPD_VERSION;
++extern int new_style_driver;
++
++
++char *pptp_server = NULL;
++char *pptp_client = NULL;
++char *pptp_phone = NULL;
++int pptp_window=50;
++int pptp_sock=-1;
++struct in_addr localbind = { INADDR_NONE };
++
++static int callmgr_sock;
++static int pptp_fd;
++int call_ID;
++
++static int open_callmgr(int call_id,struct in_addr inetaddr, char *phonenr,int window);
++static void launch_callmgr(int call_is,struct in_addr inetaddr, char *phonenr,int window);
++static int get_call_id(int sock, pid_t gre, pid_t pppd, u_int16_t *peer_call_id);
++
++static option_t Options[] =
++{
++ { "pptp_server", o_string, &pptp_server,
++ "PPTP Server" },
++ { "pptp_client", o_string, &pptp_client,
++ "PPTP Client" },
++ { "pptp_sock",o_int, &pptp_sock,
++ "PPTP socket" },
++ { "pptp_phone", o_string, &pptp_phone,
++ "PPTP Phone number" },
++ { "pptp_window",o_int, &pptp_window,
++ "PPTP window" },
++ { NULL }
++};
++
++static int pptp_connect(void);
++static void pptp_disconnect(void);
++
++struct channel pptp_channel = {
++ options: Options,
++ check_options: NULL,
++ connect: &pptp_connect,
++ disconnect: &pptp_disconnect,
++ establish_ppp: &generic_establish_ppp,
++ disestablish_ppp: &generic_disestablish_ppp,
++ close: NULL,
++ cleanup: NULL
++};
++
++static int pptp_start_server(void)
++{
++ pptp_fd=pptp_sock;
++ sprintf(ppp_devnam,"pptp (%s)",pptp_client);
++
++ return pptp_fd;
++}
++static int pptp_start_client(void)
++{
++ socklen_t len;
++ struct sockaddr_pppox src_addr,dst_addr;
++ struct hostent *hostinfo;
++
++ hostinfo=gethostbyname(pptp_server);
++ if (!hostinfo)
++ {
++ error("PPTP: Unknown host %s\n", pptp_server);
++ return -1;
++ }
++ dst_addr.sa_addr.pptp.sin_addr=*(struct in_addr*)hostinfo->h_addr;
++ {
++ int sock;
++ struct sockaddr_in addr;
++ len=sizeof(addr);
++ addr.sin_addr=dst_addr.sa_addr.pptp.sin_addr;
++ addr.sin_family=AF_INET;
++ addr.sin_port=htons(1700);
++ sock=socket(AF_INET,SOCK_DGRAM,0);
++ if (connect(sock,(struct sockaddr*)&addr,sizeof(addr)))
++ {
++ close(sock);
++ error("PPTP: connect failed (%s)\n",strerror(errno));
++ return -1;
++ }
++ getsockname(sock,(struct sockaddr*)&addr,&len);
++ src_addr.sa_addr.pptp.sin_addr=addr.sin_addr;
++ close(sock);
++ }
++
++ src_addr.sa_family=AF_PPPOX;
++ src_addr.sa_protocol=PX_PROTO_PPTP;
++ src_addr.sa_addr.pptp.call_id=0;
++
++ dst_addr.sa_family=AF_PPPOX;
++ dst_addr.sa_protocol=PX_PROTO_PPTP;
++ dst_addr.sa_addr.pptp.call_id=0;
++
++ pptp_fd=socket(AF_PPPOX,SOCK_STREAM,PX_PROTO_PPTP);
++ if (pptp_fd<0)
++ {
++ error("PPTP: failed to create PPTP socket (%s)\n",strerror(errno));
++ return -1;
++ }
++ if (bind(pptp_fd,(struct sockaddr*)&src_addr,sizeof(src_addr)))
++ {
++ close(pptp_fd);
++ error("PPTP: failed to bind PPTP socket (%s)\n",strerror(errno));
++ return -1;
++ }
++ len=sizeof(src_addr);
++ getsockname(pptp_fd,(struct sockaddr*)&src_addr,&len);
++ call_ID=src_addr.sa_addr.pptp.call_id;
++
++ do {
++ /*
++ * Open connection to call manager (Launch call manager if necessary.)
++ */
++ callmgr_sock = open_callmgr(src_addr.sa_addr.pptp.call_id,dst_addr.sa_addr.pptp.sin_addr, pptp_phone, pptp_window);
++ if (callmgr_sock<0)
++ {
++ close(pptp_fd);
++ return -1;
++ }
++ /* Exchange PIDs, get call ID */
++ } while (get_call_id(callmgr_sock, getpid(), getpid(), &dst_addr.sa_addr.pptp.call_id) < 0);
++
++ if (connect(pptp_fd,(struct sockaddr*)&dst_addr,sizeof(dst_addr)))
++ {
++ close(callmgr_sock);
++ close(pptp_fd);
++ error("PPTP: failed to connect PPTP socket (%s)\n",strerror(errno));
++ return -1;
++ }
++
++ sprintf(ppp_devnam,"pptp (%s)",pptp_server);
++
++ return pptp_fd;
++}
++static int pptp_connect(void)
++{
++ if ((!pptp_server && !pptp_client) || (pptp_server && pptp_client))
++ {
++ fatal("PPTP: unknown mode (you must specify pptp_server or pptp_client option)");
++ return -1;
++ }
++
++ if (pptp_server) return pptp_start_client();
++ return pptp_start_server();
++}
++
++static void pptp_disconnect(void)
++{
++ if (pptp_server) close(callmgr_sock);
++ close(pptp_fd);
++}
++
++static int open_callmgr(int call_id,struct in_addr inetaddr, char *phonenr,int window)
++{
++ /* Try to open unix domain socket to call manager. */
++ struct sockaddr_un where;
++ const int NUM_TRIES = 3;
++ int i, fd;
++ pid_t pid;
++ int status;
++ /* Open socket */
++ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
++ {
++ fatal("Could not create unix domain socket: %s", strerror(errno));
++ }
++ /* Make address */
++ callmgr_name_unixsock(&where, inetaddr, localbind);
++ for (i = 0; i < NUM_TRIES; i++)
++ {
++ if (connect(fd, (struct sockaddr *) &where, sizeof(where)) < 0)
++ {
++ /* couldn't connect. We'll have to launch this guy. */
++
++ unlink (where.sun_path);
++
++ /* fork and launch call manager process */
++ switch (pid = fork())
++ {
++ case -1: /* failure */
++ fatal("fork() to launch call manager failed.");
++ case 0: /* child */
++ {
++ /* close the pty and gre in the call manager */
++ close(fd);
++ close(pptp_fd);
++ launch_callmgr(call_id,inetaddr,phonenr,window);
++ }
++ default: /* parent */
++ waitpid(pid, &status, 0);
++ if (status!= 0)
++ {
++ close(fd);
++ error("Call manager exited with error %d", status);
++ return -1;
++ }
++ break;
++ }
++ sleep(1);
++ }
++ else return fd;
++ }
++ close(fd);
++ error("Could not launch call manager after %d tries.", i);
++ return -1; /* make gcc happy */
++}
++
++/*** call the call manager main ***********************************************/
++static void launch_callmgr(int call_id,struct in_addr inetaddr, char *phonenr,int window)
++{
++ dbglog("pptp: call manager for %s\n", inet_ntoa(inetaddr));
++ dbglog("window size:\t%d\n",window);
++ if (phonenr) dbglog("phone number:\t'%s'\n",phonenr);
++ dbglog("call id:\t%d\n",call_id);
++ exit(callmgr_main(inetaddr, phonenr, window, call_id));
++}
++
++/*** exchange data with the call manager *************************************/
++/* XXX need better error checking XXX */
++static int get_call_id(int sock, pid_t gre, pid_t pppd,
++ u_int16_t *peer_call_id)
++{
++ u_int16_t m_call_id, m_peer_call_id;
++ /* write pid's to socket */
++ /* don't bother with network byte order, because pid's are meaningless
++ * outside the local host.
++ */
++ int rc;
++ rc = write(sock, &gre, sizeof(gre));
++ if (rc != sizeof(gre))
++ return -1;
++ rc = write(sock, &pppd, sizeof(pppd));
++ if (rc != sizeof(pppd))
++ return -1;
++ rc = read(sock, &m_call_id, sizeof(m_call_id));
++ if (rc != sizeof(m_call_id))
++ return -1;
++ rc = read(sock, &m_peer_call_id, sizeof(m_peer_call_id));
++ if (rc != sizeof(m_peer_call_id))
++ return -1;
++ /*
++ * XXX FIXME ... DO ERROR CHECKING & TIME-OUTS XXX
++ * (Rhialto: I am assuming for now that timeouts are not relevant
++ * here, because the read and write calls would return -1 (fail) when
++ * the peer goes away during the process. We know it is (or was)
++ * running because the connect() call succeeded.)
++ * (James: on the other hand, if the route to the peer goes away, we
++ * wouldn't get told by read() or write() for quite some time.)
++ */
++ *peer_call_id = m_peer_call_id;
++ return 0;
++}
++
++void plugin_init(void)
++{
++ add_options(Options);
++
++ info("PPTP plugin version %s", PPTP_VERSION);
++
++ the_channel = &pptp_channel;
++ modem = 0;
++}
+--- /dev/null
++++ b/pppd/plugins/pptp/pptp_callmgr.c
+@@ -0,0 +1,381 @@
++/* pptp_callmgr.c ... Call manager for PPTP connections.
++ * Handles TCP port 1723 protocol.
++ * C. Scott Ananian <cananian@alumni.princeton.edu>
++ *
++ * $Id: pptp_callmgr.c,v 1.20 2005/03/31 07:42:39 quozl Exp $
++ */
++#include <signal.h>
++#include <sys/time.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
++#include <sys/un.h>
++#include <unistd.h>
++#include <stdlib.h>
++#include <string.h>
++#include <assert.h>
++#include <setjmp.h>
++#include <stdio.h>
++#include <errno.h>
++#include "pptp_callmgr.h"
++#include "pptp_ctrl.h"
++#include "pptp_msg.h"
++#include "dirutil.h"
++#include "vector.h"
++#include "util.h"
++#include "pppd.h"
++
++extern struct in_addr localbind; /* from pptp.c */
++extern int call_ID;
++
++int open_inetsock(struct in_addr inetaddr);
++int open_unixsock(struct in_addr inetaddr);
++void close_inetsock(int fd, struct in_addr inetaddr);
++void close_unixsock(int fd, struct in_addr inetaddr);
++
++sigjmp_buf callmgr_env;
++
++void callmgr_sighandler(int sig) {
++ /* TODO: according to signal(2), siglongjmp() is unsafe used here */
++ siglongjmp (callmgr_env, 1);
++}
++
++void callmgr_do_nothing(int sig) {
++ /* do nothing signal handler */
++}
++
++struct local_callinfo {
++ int unix_sock;
++ pid_t pid[2];
++};
++
++struct local_conninfo {
++ VECTOR * call_list;
++ fd_set * call_set;
++};
++
++/* Call callback */
++void call_callback(PPTP_CONN *conn, PPTP_CALL *call, enum call_state state)
++{
++ struct local_callinfo *lci;
++ struct local_conninfo *conninfo;
++ u_int16_t call_id[2];
++ switch(state) {
++ case CALL_OPEN_DONE:
++ /* okey dokey. This means that the call_id and peer_call_id are
++ * now valid, so lets send them on to our friends who requested
++ * this call. */
++ lci = pptp_call_closure_get(conn, call); assert(lci != NULL);
++ pptp_call_get_ids(conn, call, &call_id[0], &call_id[1]);
++ write(lci->unix_sock, &call_id, sizeof(call_id));
++ /* Our duty to the fatherland is now complete. */
++ break;
++ case CALL_OPEN_FAIL:
++ case CALL_CLOSE_RQST:
++ case CALL_CLOSE_DONE:
++ /* don't need to do anything here, except make sure tables
++ * are sync'ed */
++ dbglog("Closing connection (call state)");
++ conninfo = pptp_conn_closure_get(conn);
++ lci = pptp_call_closure_get(conn, call);
++ assert(lci != NULL && conninfo != NULL);
++ if (vector_contains(conninfo->call_list, lci->unix_sock)) {
++ vector_remove(conninfo->call_list, lci->unix_sock);
++ close(lci->unix_sock);
++ FD_CLR(lci->unix_sock, conninfo->call_set);
++ }
++ break;
++ default:
++ dbglog("Unhandled call callback state [%d].", (int) state);
++ break;
++ }
++}
++
++/******************************************************************************
++ * NOTE ABOUT 'VOLATILE':
++ * several variables here get a volatile qualifier to silence warnings
++ * from older (before 3.0) gccs. if the longjmp stuff is removed,
++ * the volatile qualifiers should be removed as well.
++ *****************************************************************************/
++
++/*** Call Manager *************************************************************/
++int callmgr_main(struct in_addr inetaddr, char phonenr[], int window, int pcallid)
++{
++ int inet_sock, unix_sock;
++ fd_set call_set;
++ PPTP_CONN * conn;
++ VECTOR * call_list;
++ int max_fd = 0;
++ volatile int first = 1;
++ int retval;
++ int i;
++ if (pcallid>0) call_ID=pcallid;
++
++ /* Step 1: Open sockets. */
++ if ((inet_sock = open_inetsock(inetaddr)) < 0)
++ fatal("Could not open control connection to %s", inet_ntoa(inetaddr));
++ dbglog("control connection");
++ if ((unix_sock = open_unixsock(inetaddr)) < 0)
++ fatal("Could not open unix socket for %s", inet_ntoa(inetaddr));
++ /* Step 1b: FORK and return status to calling process. */
++ dbglog("unix_sock");
++
++ switch (fork()) {
++ case 0: /* child. stick around. */
++ break;
++ case -1: /* failure. Fatal. */
++ fatal("Could not fork.");
++ default: /* Parent. Return status to caller. */
++ exit(0);
++ }
++ /* re-open stderr as /dev/null to release it */
++ file2fd("/dev/null", "wb", STDERR_FILENO);
++ /* Step 1c: Clean up unix socket on TERM */
++ if (sigsetjmp(callmgr_env, 1) != 0)
++ goto cleanup;
++ signal(SIGINT, callmgr_sighandler);
++ signal(SIGTERM, callmgr_sighandler);
++ signal(SIGPIPE, callmgr_do_nothing);
++ signal(SIGUSR1, callmgr_do_nothing); /* signal state change
++ wake up accept */
++ /* Step 2: Open control connection and register callback */
++ if ((conn = pptp_conn_open(inet_sock, 1, NULL/* callback */)) == NULL) {
++ close(unix_sock); close(inet_sock); fatal("Could not open connection.");
++ }
++ FD_ZERO(&call_set);
++ call_list = vector_create();
++ {
++ struct local_conninfo *conninfo = malloc(sizeof(*conninfo));
++ if (conninfo == NULL) {
++ close(unix_sock); close(inet_sock); fatal("No memory.");
++ }
++ conninfo->call_list = call_list;
++ conninfo->call_set = &call_set;
++ pptp_conn_closure_put(conn, conninfo);
++ }
++ if (sigsetjmp(callmgr_env, 1) != 0) goto shutdown;
++ /* Step 3: Get FD_SETs */
++ max_fd = unix_sock;
++ do {
++ int rc;
++ fd_set read_set = call_set, write_set;
++ FD_ZERO (&write_set);
++ if (pptp_conn_established(conn)) {
++ FD_SET (unix_sock, &read_set);
++ if (unix_sock > max_fd) max_fd = unix_sock;
++ }
++ pptp_fd_set(conn, &read_set, &write_set, &max_fd);
++ for (; max_fd > 0 ; max_fd--) {
++ if (FD_ISSET (max_fd, &read_set) ||
++ FD_ISSET (max_fd, &write_set))
++ break;
++ }
++ /* Step 4: Wait on INET or UNIX event */
++ if ((rc = select(max_fd + 1, &read_set, &write_set, NULL, NULL)) <0) {
++ if (errno == EBADF) break;
++ /* a signal or somesuch. */
++ continue;
++ }
++ /* Step 5a: Handle INET events */
++ rc = pptp_dispatch(conn, &read_set, &write_set);
++ if (rc < 0)
++ break;
++ /* Step 5b: Handle new connection to UNIX socket */
++ if (FD_ISSET(unix_sock, &read_set)) {
++ /* New call! */
++ struct sockaddr_un from;
++ int len = sizeof(from);
++ PPTP_CALL * call;
++ struct local_callinfo *lci;
++ int s;
++ /* Accept the socket */
++ FD_CLR (unix_sock, &read_set);
++ if ((s = accept(unix_sock, (struct sockaddr *) &from, &len)) < 0) {
++ warn("Socket not accepted: %s", strerror(errno));
++ goto skip_accept;
++ }
++ /* Allocate memory for local call information structure. */
++ if ((lci = malloc(sizeof(*lci))) == NULL) {
++ warn("Out of memory."); close(s); goto skip_accept;
++ }
++ lci->unix_sock = s;
++ /* Give the initiator time to write the PIDs while we open
++ * the call */
++ call = pptp_call_open(conn, call_ID,call_callback, phonenr,window);
++ /* Read and store the associated pids */
++ read(s, &lci->pid[0], sizeof(lci->pid[0]));
++ read(s, &lci->pid[1], sizeof(lci->pid[1]));
++ /* associate the local information with the call */
++ pptp_call_closure_put(conn, call, (void *) lci);
++ /* The rest is done on callback. */
++ /* Keep alive; wait for close */
++ retval = vector_insert(call_list, s, call); assert(retval);
++ if (s > max_fd) max_fd = s;
++ FD_SET(s, &call_set);
++ first = 0;
++ }
++skip_accept: /* Step 5c: Handle socket close */
++ for (i = 0; i < max_fd + 1; i++)
++ if (FD_ISSET(i, &read_set)) {
++ /* close it */
++ PPTP_CALL * call;
++ retval = vector_search(call_list, i, &call);
++ if (retval) {
++ struct local_callinfo *lci =
++ pptp_call_closure_get(conn, call);
++ dbglog("Closing connection (unhandled)");
++ free(lci);
++ /* soft shutdown. Callback will do hard shutdown later */
++ pptp_call_close(conn, call);
++ vector_remove(call_list, i);
++ }
++ FD_CLR(i, &call_set);
++ close(i);
++ }
++ } while (vector_size(call_list) > 0 || first);
++shutdown:
++ {
++ int rc;
++ fd_set read_set, write_set;
++ struct timeval tv;
++ signal(SIGINT, callmgr_do_nothing);
++ signal(SIGTERM, callmgr_do_nothing);
++ /* warn("Shutdown"); */
++ /* kill all open calls */
++ for (i = 0; i < vector_size(call_list); i++) {
++ PPTP_CALL *call = vector_get_Nth(call_list, i);
++ dbglog("Closing connection (shutdown)");
++ pptp_call_close(conn, call);
++ }
++ /* attempt to dispatch these messages */
++ FD_ZERO(&read_set);
++ FD_ZERO(&write_set);
++ pptp_fd_set(conn, &read_set, &write_set, &max_fd);
++ tv.tv_sec = 0;
++ tv.tv_usec = 0;
++ select(max_fd + 1, &read_set, &write_set, NULL, &tv);
++ rc = pptp_dispatch(conn, &read_set, &write_set);
++ if (rc > 0) {
++ /* wait for a respond, a timeout because there might not be one */
++ FD_ZERO(&read_set);
++ FD_ZERO(&write_set);
++ pptp_fd_set(conn, &read_set, &write_set, &max_fd);
++ tv.tv_sec = 2;
++ tv.tv_usec = 0;
++ select(max_fd + 1, &read_set, &write_set, NULL, &tv);
++ rc = pptp_dispatch(conn, &read_set, &write_set);
++ if (rc > 0) {
++ if (i > 0) sleep(2);
++ /* no more open calls. Close the connection. */
++ pptp_conn_close(conn, PPTP_STOP_LOCAL_SHUTDOWN);
++ /* wait for a respond, a timeout because there might not be one */
++ FD_ZERO(&read_set);
++ FD_ZERO(&write_set);
++ pptp_fd_set(conn, &read_set, &write_set, &max_fd);
++ tv.tv_sec = 2;
++ tv.tv_usec = 0;
++ select(max_fd + 1, &read_set, &write_set, NULL, &tv);
++ pptp_dispatch(conn, &read_set, &write_set);
++ if (rc > 0) sleep(2);
++ }
++ }
++ /* with extreme prejudice */
++ pptp_conn_destroy(conn);
++ vector_destroy(call_list);
++ }
++cleanup:
++ signal(SIGINT, callmgr_do_nothing);
++ signal(SIGTERM, callmgr_do_nothing);
++ close_inetsock(inet_sock, inetaddr);
++ close_unixsock(unix_sock, inetaddr);
++ return 0;
++}
++
++/*** open_inetsock ************************************************************/
++int open_inetsock(struct in_addr inetaddr)
++{
++ struct sockaddr_in dest, src;
++ int s;
++ dest.sin_family = AF_INET;
++ dest.sin_port = htons(PPTP_PORT);
++ dest.sin_addr = inetaddr;
++ if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
++ warn("socket: %s", strerror(errno));
++ return s;
++ }
++ if (localbind.s_addr != INADDR_NONE) {
++ bzero(&src, sizeof(src));
++ src.sin_family = AF_INET;
++ src.sin_addr = localbind;
++ if (bind(s, (struct sockaddr *) &src, sizeof(src)) != 0) {
++ warn("bind: %s", strerror(errno));
++ close(s); return -1;
++ }
++ }
++ if (connect(s, (struct sockaddr *) &dest, sizeof(dest)) < 0) {
++ warn("connect: %s", strerror(errno));
++ close(s); return -1;
++ }
++ return s;
++}
++
++/*** open_unixsock ************************************************************/
++int open_unixsock(struct in_addr inetaddr)
++{
++ struct sockaddr_un where;
++ struct stat st;
++ char *dir;
++ int s;
++ if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
++ warn("socket: %s", strerror(errno));
++ return s;
++ }
++ callmgr_name_unixsock( &where, inetaddr, localbind);
++ if (stat(where.sun_path, &st) >= 0)
++ {
++ warn("Call manager for %s is already running.", inet_ntoa(inetaddr));
++ close(s); return -1;
++ }
++ /* Make sure path is valid. */
++ dir = dirnamex(where.sun_path);
++ if (!make_valid_path(dir, 0770))
++ fatal("Could not make path to %s: %s", where.sun_path, strerror(errno));
++ free(dir);
++ if (bind(s, (struct sockaddr *) &where, sizeof(where)) < 0) {
++ warn("bind: %s", strerror(errno));
++ close(s); return -1;
++ }
++ chmod(where.sun_path, 0777);
++ listen(s, 127);
++ return s;
++}
++
++/*** close_inetsock ***********************************************************/
++void close_inetsock(int fd, struct in_addr inetaddr)
++{
++ close(fd);
++}
++
++/*** close_unixsock ***********************************************************/
++void close_unixsock(int fd, struct in_addr inetaddr)
++{
++ struct sockaddr_un where;
++ close(fd);
++ callmgr_name_unixsock(&where, inetaddr, localbind);
++ unlink(where.sun_path);
++}
++
++/*** make a unix socket address ***********************************************/
++void callmgr_name_unixsock(struct sockaddr_un *where,
++ struct in_addr inetaddr,
++ struct in_addr localbind)
++{
++ char localaddr[16], remoteaddr[16];
++ where->sun_family = AF_UNIX;
++ strncpy(localaddr, inet_ntoa(localbind), 16);
++ strncpy(remoteaddr, inet_ntoa(inetaddr), 16);
++ snprintf(where->sun_path, sizeof(where->sun_path),
++ PPTP_SOCKET_PREFIX "%s:%i", remoteaddr,call_ID);
++}
+--- /dev/null
++++ b/pppd/plugins/pptp/pptp_callmgr.h
+@@ -0,0 +1,17 @@
++/* pptp_callmgr.h ... Call manager for PPTP connections.
++ * Handles TCP port 1723 protocol.
++ * C. Scott Ananian <cananian@alumni.princeton.edu>
++ *
++ * $Id: pptp_callmgr.h,v 1.3 2003/02/17 00:22:17 quozl Exp $
++ */
++
++#define PPTP_SOCKET_PREFIX "/var/run/pptp/"
++
++int callmgr_main(struct in_addr inetaddr,
++ char phonenr[],
++ int window,
++ int pcallid);
++
++void callmgr_name_unixsock(struct sockaddr_un *where,
++ struct in_addr inetaddr,
++ struct in_addr localbind);
+--- /dev/null
++++ b/pppd/plugins/pptp/pptp_ctrl.c
+@@ -0,0 +1,1077 @@
++/* pptp_ctrl.c ... handle PPTP control connection.
++ * C. Scott Ananian <cananian@alumni.princeton.edu>
++ *
++ * $Id: pptp_ctrl.c,v 1.31 2005/03/31 07:42:39 quozl Exp $
++ */
++
++#include <errno.h>
++#include <sys/time.h>
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <unistd.h>
++#include <stdlib.h>
++#include <assert.h>
++#include <signal.h>
++#include <string.h>
++#include <ctype.h>
++#include <fcntl.h>
++#include "pptp_msg.h"
++#include "pptp_ctrl.h"
++#include "pptp_options.h"
++#include "vector.h"
++#include "util.h"
++#include "pptp_quirks.h"
++
++/* BECAUSE OF SIGNAL LIMITATIONS, EACH PROCESS CAN ONLY MANAGE ONE
++ * CONNECTION. SO THIS 'PPTP_CONN' STRUCTURE IS A BIT MISLEADING.
++ * WE'LL KEEP CONNECTION-SPECIFIC INFORMATION IN THERE ANYWAY (AS
++ * OPPOSED TO USING GLOBAL VARIABLES), BUT BEWARE THAT THE ENTIRE
++ * UNIX SIGNAL-HANDLING SEMANTICS WOULD HAVE TO CHANGE (OR THE
++ * TIME-OUT CODE DRASTICALLY REWRITTEN) BEFORE YOU COULD DO A
++ * PPTP_CONN_OPEN MORE THAN ONCE PER PROCESS AND GET AWAY WITH IT.
++ */
++
++/* This structure contains connection-specific information that the
++ * signal handler needs to see. Thus, it needs to be in a global
++ * variable. If you end up using pthreads or something (why not
++ * just processes?), this would have to be placed in a thread-specific
++ * data area, using pthread_get|set_specific, etc., so I've
++ * conveniently encapsulated it for you.
++ * [linux threads will have to support thread-specific signals
++ * before this would work at all, which, as of this writing
++ * (linux-threads v0.6, linux kernel 2.1.72), it does not.]
++ */
++
++/* Globals */
++
++/* control the number of times echo packets will be logged */
++static int nlogecho = 10;
++
++static struct thread_specific {
++ struct sigaction old_sigaction; /* evil signals */
++ PPTP_CONN * conn;
++} global;
++
++#define INITIAL_BUFSIZE 512 /* initial i/o buffer size. */
++
++struct PPTP_CONN {
++ int inet_sock;
++ /* Connection States */
++ enum {
++ CONN_IDLE, CONN_WAIT_CTL_REPLY, CONN_WAIT_STOP_REPLY, CONN_ESTABLISHED
++ } conn_state; /* on startup: CONN_IDLE */
++ /* Keep-alive states */
++ enum {
++ KA_NONE, KA_OUTSTANDING
++ } ka_state; /* on startup: KA_NONE */
++ /* Keep-alive ID; monotonically increasing (watch wrap-around!) */
++ u_int32_t ka_id; /* on startup: 1 */
++ /* Other properties. */
++ u_int16_t version;
++ u_int16_t firmware_rev;
++ u_int8_t hostname[64], vendor[64];
++ /* XXX these are only PNS properties, currently XXX */
++ /* Call assignment information. */
++ u_int16_t call_serial_number;
++ VECTOR *call;
++ void * closure;
++ pptp_conn_cb callback;
++ /******* IO buffers ******/
++ char * read_buffer, *write_buffer;
++ size_t read_alloc, write_alloc;
++ size_t read_size, write_size;
++};
++
++struct PPTP_CALL {
++ /* Call properties */
++ enum {
++ PPTP_CALL_PAC, PPTP_CALL_PNS
++ } call_type;
++ union {
++ enum pptp_pac_state {
++ PAC_IDLE, PAC_WAIT_REPLY, PAC_ESTABLISHED, PAC_WAIT_CS_ANS
++ } pac;
++ enum pptp_pns_state {
++ PNS_IDLE, PNS_WAIT_REPLY, PNS_ESTABLISHED, PNS_WAIT_DISCONNECT
++ } pns;
++ } state;
++ u_int16_t call_id, peer_call_id;
++ u_int16_t sernum;
++ u_int32_t speed;
++ /* For user data: */
++ pptp_call_cb callback;
++ void * closure;
++};
++
++
++/* PPTP error codes: ----------------------------------------------*/
++
++/* (General Error Codes) */
++static const struct {
++ const char *name, *desc;
++} pptp_general_errors[] = {
++#define PPTP_GENERAL_ERROR_NONE 0
++ { "(None)", "No general error" },
++#define PPTP_GENERAL_ERROR_NOT_CONNECTED 1
++ { "(Not-Connected)", "No control connection exists yet for this "
++ "PAC-PNS pair" },
++#define PPTP_GENERAL_ERROR_BAD_FORMAT 2
++ { "(Bad-Format)", "Length is wrong or Magic Cookie value is incorrect" },
++#define PPTP_GENERAL_ERROR_BAD_VALUE 3
++ { "(Bad-Value)", "One of the field values was out of range or "
++ "reserved field was non-zero" },
++#define PPTP_GENERAL_ERROR_NO_RESOURCE 4
++ { "(No-Resource)", "Insufficient resources to handle this command now" },
++#define PPTP_GENERAL_ERROR_BAD_CALLID 5
++ { "(Bad-Call ID)", "The Call ID is invalid in this context" },
++#define PPTP_GENERAL_ERROR_PAC_ERROR 6
++ { "(PAC-Error)", "A generic vendor-specific error occured in the PAC" }
++};
++
++#define MAX_GENERAL_ERROR ( sizeof(pptp_general_errors) / \
++ sizeof(pptp_general_errors[0]) - 1)
++
++/* Outgoing Call Reply Result Codes */
++static const char *pptp_out_call_reply_result[] = {
++/* 0 */ "Unknown Result Code",
++/* 1 */ "Connected",
++/* 2 */ "General Error",
++/* 3 */ "No Carrier Detected",
++/* 4 */ "Busy Signal",
++/* 5 */ "No Dial Tone",
++/* 6 */ "Time Out",
++/* 7 */ "Not Accepted, Call is administratively prohibited" };
++
++#define MAX_OUT_CALL_REPLY_RESULT 7
++
++/* Call Disconnect Notify Result Codes */
++static const char *pptp_call_disc_ntfy[] = {
++/* 0 */ "Unknown Result Code",
++/* 1 */ "Lost Carrier",
++/* 2 */ "General Error",
++/* 3 */ "Administrative Shutdown",
++/* 4 */ "(your) Request" };
++
++#define MAX_CALL_DISC_NTFY 4
++
++/* Call Disconnect Notify Result Codes */
++static const char *pptp_start_ctrl_conn_rply[] = {
++/* 0 */ "Unknown Result Code",
++/* 1 */ "Successful Channel Establishment",
++/* 2 */ "General Error",
++/* 3 */ "Command Channel Already Exists",
++/* 4 */ "Requester is not Authorized" };
++
++#define MAX_START_CTRL_CONN_REPLY 4
++
++/* timing options */
++int idle_wait = PPTP_TIMEOUT;
++int max_echo_wait = PPTP_TIMEOUT;
++
++/* Local prototypes */
++static void pptp_reset_timer(void);
++static void pptp_handle_timer();
++/* Write/read as much as we can without blocking. */
++int pptp_write_some(PPTP_CONN * conn);
++int pptp_read_some(PPTP_CONN * conn);
++/* Make valid packets from read_buffer */
++int pptp_make_packet(PPTP_CONN * conn, void **buf, size_t *size);
++/* Add packet to write_buffer */
++int pptp_send_ctrl_packet(PPTP_CONN * conn, void * buffer, size_t size);
++/* Dispatch packets (general) */
++int pptp_dispatch_packet(PPTP_CONN * conn, void * buffer, size_t size);
++/* Dispatch packets (control messages) */
++int ctrlp_disp(PPTP_CONN * conn, void * buffer, size_t size);
++/* Set link info, for pptp servers that need it.
++ this is a noop, unless the user specified a quirk and
++ there's a set_link hook defined in the quirks table
++ for that quirk */
++void pptp_set_link(PPTP_CONN * conn, int peer_call_id);
++
++/*** log error information in control packets *********************************/
++static void ctrlp_error( int result, int error, int cause,
++ const char *result_text[], int max_result)
++{
++ if( cause >= 0)
++ warn("Result code is %d '%s'. Error code is %d, Cause code is %d",
++ result, result_text[result <= max_result ? result : 0], error,
++ cause );
++ else
++ warn("Reply result code is %d '%s'. Error code is %d",
++ result, result_text[result <= max_result ? result : 0], error);
++ if ((error > 0) && (error <= MAX_GENERAL_ERROR)){
++ if( result != PPTP_RESULT_GENERAL_ERROR )
++ warn("Result code is something else then \"general error\", "
++ "so the following error is probably bogus.");
++ warn("Error is '%s', Error message: '%s'",
++ pptp_general_errors[error].name,
++ pptp_general_errors[error].desc);
++ }
++}
++
++static const char *ctrl_msg_types[] = {
++ "invalid control message type",
++/* (Control Connection Management) */
++ "Start-Control-Connection-Request", /* 1 */
++ "Start-Control-Connection-Reply", /* 2 */
++ "Stop-Control-Connection-Request", /* 3 */
++ "Stop-Control-Connection-Reply", /* 4 */
++ "Echo-Request", /* 5 */
++ "Echo-Reply", /* 6 */
++/* (Call Management) */
++ "Outgoing-Call-Request", /* 7 */
++ "Outgoing-Call-Reply", /* 8 */
++ "Incoming-Call-Request", /* 9 */
++ "Incoming-Call-Reply", /* 10 */
++ "Incoming-Call-Connected", /* 11 */
++ "Call-Clear-Request", /* 12 */
++ "Call-Disconnect-Notify", /* 13 */
++/* (Error Reporting) */
++ "WAN-Error-Notify", /* 14 */
++/* (PPP Session Control) */
++ "Set-Link-Info" /* 15 */
++};
++#define MAX_CTRLMSG_TYPE 15
++
++/*** report a sent packet ****************************************************/
++static void ctrlp_rep( void * buffer, int size, int isbuff)
++{
++ struct pptp_header *packet = buffer;
++ unsigned int type;
++ if(size < sizeof(struct pptp_header)) return;
++ type = ntoh16(packet->ctrl_type);
++ /* FIXME: do not report sending echo requests as long as they are
++ * sent in a signal handler. This may dead lock as the syslog call
++ * is not reentrant */
++ if( type == PPTP_ECHO_RQST ) return;
++ /* don't keep reporting sending of echo's */
++ if( (type == PPTP_ECHO_RQST || type == PPTP_ECHO_RPLY) && nlogecho <= 0 ) return;
++ dbglog("%s control packet type is %d '%s'\n",isbuff ? "Buffered" : "Sent",
++ type, ctrl_msg_types[type <= MAX_CTRLMSG_TYPE ? type : 0]);
++
++}
++
++
++
++/* Open new pptp_connection. Returns NULL on failure. */
++PPTP_CONN * pptp_conn_open(int inet_sock, int isclient, pptp_conn_cb callback)
++{
++ PPTP_CONN *conn;
++ /* Allocate structure */
++ if ((conn = malloc(sizeof(*conn))) == NULL) return NULL;
++ if ((conn->call = vector_create()) == NULL) { free(conn); return NULL; }
++ /* Initialize */
++ conn->inet_sock = inet_sock;
++ conn->conn_state = CONN_IDLE;
++ conn->ka_state = KA_NONE;
++ conn->ka_id = 1;
++ conn->call_serial_number = 0;
++ conn->callback = callback;
++ /* Create I/O buffers */
++ conn->read_size = conn->write_size = 0;
++ conn->read_alloc = conn->write_alloc = INITIAL_BUFSIZE;
++ conn->read_buffer =
++ malloc(sizeof(*(conn->read_buffer)) * conn->read_alloc);
++ conn->write_buffer =
++ malloc(sizeof(*(conn->write_buffer)) * conn->write_alloc);
++ if (conn->read_buffer == NULL || conn->write_buffer == NULL) {
++ if (conn->read_buffer != NULL) free(conn->read_buffer);
++ if (conn->write_buffer != NULL) free(conn->write_buffer);
++ vector_destroy(conn->call); free(conn); return NULL;
++ }
++ /* Make this socket non-blocking. */
++ fcntl(conn->inet_sock, F_SETFL, O_NONBLOCK);
++ /* Request connection from server, if this is a client */
++ if (isclient) {
++ struct pptp_start_ctrl_conn packet = {
++ PPTP_HEADER_CTRL(PPTP_START_CTRL_CONN_RQST),
++ hton16(PPTP_VERSION), 0, 0,
++ hton32(PPTP_FRAME_CAP), hton32(PPTP_BEARER_CAP),
++ hton16(PPTP_MAX_CHANNELS), hton16(PPTP_FIRMWARE_VERSION),
++ PPTP_HOSTNAME, PPTP_VENDOR
++ };
++ /* fix this packet, if necessary */
++ int idx, rc;
++ idx = get_quirk_index();
++ if (idx != -1 && pptp_fixups[idx].start_ctrl_conn) {
++ if ((rc = pptp_fixups[idx].start_ctrl_conn(&packet)))
++ warn("calling the start_ctrl_conn hook failed (%d)", rc);
++ }
++ if (pptp_send_ctrl_packet(conn, &packet, sizeof(packet)))
++ conn->conn_state = CONN_WAIT_CTL_REPLY;
++ else
++ return NULL; /* could not send initial start request. */
++ }
++ /* Set up interval/keep-alive timer */
++ /* First, register handler for SIGALRM */
++ sigpipe_create();
++ sigpipe_assign(SIGALRM);
++ global.conn = conn;
++ /* Reset event timer */
++ pptp_reset_timer();
++ /* all done. */
++ return conn;
++}
++
++int pptp_conn_established(PPTP_CONN *conn) {
++ return (conn->conn_state == CONN_ESTABLISHED);
++}
++
++/* This currently *only* works for client call requests.
++ * We need to do something else to allocate calls for incoming requests.
++ */
++PPTP_CALL * pptp_call_open(PPTP_CONN * conn, int call_id,pptp_call_cb callback,
++ char *phonenr,int window)
++{
++ PPTP_CALL * call;
++ int idx, rc;
++ /* Send off the call request */
++ struct pptp_out_call_rqst packet = {
++ PPTP_HEADER_CTRL(PPTP_OUT_CALL_RQST),
++ 0,0, /*call_id, sernum */
++ hton32(PPTP_BPS_MIN), hton32(PPTP_BPS_MAX),
++ hton32(PPTP_BEARER_CAP), hton32(PPTP_FRAME_CAP),
++ hton16(window), 0, 0, 0, {0}, {0}
++ };
++ assert(conn && conn->call);
++ assert(conn->conn_state == CONN_ESTABLISHED);
++ /* Assign call id */
++ if (!call_id && !vector_scan(conn->call, 0, PPTP_MAX_CHANNELS - 1, &call_id))
++ /* no more calls available! */
++ return NULL;
++ /* allocate structure. */
++ if ((call = malloc(sizeof(*call))) == NULL) return NULL;
++ /* Initialize call structure */
++ call->call_type = PPTP_CALL_PNS;
++ call->state.pns = PNS_IDLE;
++ call->call_id = (u_int16_t) call_id;
++ call->sernum = conn->call_serial_number++;
++ call->callback = callback;
++ call->closure = NULL;
++ packet.call_id = htons(call->call_id);
++ packet.call_sernum = htons(call->sernum);
++ /* if we have a quirk, build a new packet to fit it */
++ idx = get_quirk_index();
++ if (idx != -1 && pptp_fixups[idx].out_call_rqst_hook) {
++ if ((rc = pptp_fixups[idx].out_call_rqst_hook(&packet)))
++ warn("calling the out_call_rqst hook failed (%d)", rc);
++ }
++ /* fill in the phone number if it was specified */
++ if (phonenr) {
++ strncpy(packet.phone_num, phonenr, sizeof(packet.phone_num));
++ packet.phone_len = strlen(phonenr);
++ if( packet.phone_len > sizeof(packet.phone_num))
++ packet.phone_len = sizeof(packet.phone_num);
++ packet.phone_len = hton16 (packet.phone_len);
++ }
++ if (pptp_send_ctrl_packet(conn, &packet, sizeof(packet))) {
++ pptp_reset_timer();
++ call->state.pns = PNS_WAIT_REPLY;
++ /* and add it to the call vector */
++ vector_insert(conn->call, call_id, call);
++ return call;
++ } else { /* oops, unsuccessful. Deallocate. */
++ free(call);
++ return NULL;
++ }
++}
++
++/*** pptp_call_close **********************************************************/
++void pptp_call_close(PPTP_CONN * conn, PPTP_CALL * call)
++{
++ struct pptp_call_clear_rqst rqst = {
++ PPTP_HEADER_CTRL(PPTP_CALL_CLEAR_RQST), 0, 0
++ };
++ assert(conn && conn->call); assert(call);
++ assert(vector_contains(conn->call, call->call_id));
++ /* haven't thought about PAC yet */
++ assert(call->call_type == PPTP_CALL_PNS);
++ assert(call->state.pns != PNS_IDLE);
++ rqst.call_id = hton16(call->call_id);
++ /* don't check state against WAIT_DISCONNECT... allow multiple disconnect
++ * requests to be made.
++ */
++ pptp_send_ctrl_packet(conn, &rqst, sizeof(rqst));
++ pptp_reset_timer();
++ call->state.pns = PNS_WAIT_DISCONNECT;
++ /* call structure will be freed when we have confirmation of disconnect. */
++}
++
++/*** hard close ***************************************************************/
++void pptp_call_destroy(PPTP_CONN *conn, PPTP_CALL *call)
++{
++ assert(conn && conn->call); assert(call);
++ assert(vector_contains(conn->call, call->call_id));
++ /* notify */
++ if (call->callback != NULL) call->callback(conn, call, CALL_CLOSE_DONE);
++ /* deallocate */
++ vector_remove(conn->call, call->call_id);
++ free(call);
++}
++
++/*** this is a soft close *****************************************************/
++void pptp_conn_close(PPTP_CONN * conn, u_int8_t close_reason)
++{
++ struct pptp_stop_ctrl_conn rqst = {
++ PPTP_HEADER_CTRL(PPTP_STOP_CTRL_CONN_RQST),
++ hton8(close_reason), 0, 0
++ };
++ int i;
++ assert(conn && conn->call);
++ /* avoid repeated close attempts */
++ if (conn->conn_state == CONN_IDLE || conn->conn_state == CONN_WAIT_STOP_REPLY)
++ return;
++ /* close open calls, if any */
++ for (i = 0; i < vector_size(conn->call); i++)
++ pptp_call_close(conn, vector_get_Nth(conn->call, i));
++ /* now close connection */
++ info("Closing PPTP connection");
++ pptp_send_ctrl_packet(conn, &rqst, sizeof(rqst));
++ pptp_reset_timer(); /* wait 60 seconds for reply */
++ conn->conn_state = CONN_WAIT_STOP_REPLY;
++ return;
++}
++
++/*** this is a hard close *****************************************************/
++void pptp_conn_destroy(PPTP_CONN * conn)
++{
++ int i;
++ assert(conn != NULL); assert(conn->call != NULL);
++ /* destroy all open calls */
++ for (i = 0; i < vector_size(conn->call); i++)
++ pptp_call_destroy(conn, vector_get_Nth(conn->call, i));
++ /* notify */
++ if (conn->callback != NULL) conn->callback(conn, CONN_CLOSE_DONE);
++ sigpipe_close();
++ close(conn->inet_sock);
++ /* deallocate */
++ vector_destroy(conn->call);
++ free(conn);
++}
++
++/*** Deal with messages, in a non-blocking manner
++ * Add file descriptors used by pptp to fd_set.
++ */
++void pptp_fd_set(PPTP_CONN * conn, fd_set * read_set, fd_set * write_set,
++ int * max_fd)
++{
++ assert(conn && conn->call);
++ /* Add fd to write_set if there are outstanding writes. */
++ if (conn->write_size > 0)
++ FD_SET(conn->inet_sock, write_set);
++ /* Always add fd to read_set. (always want something to read) */
++ FD_SET(conn->inet_sock, read_set);
++ if (*max_fd < conn->inet_sock) *max_fd = conn->inet_sock;
++ /* Add signal pipe file descriptor to set */
++ int sig_fd = sigpipe_fd();
++ FD_SET(sig_fd, read_set);
++ if (*max_fd < sig_fd) *max_fd = sig_fd;
++}
++
++/*** handle any pptp file descriptors set in fd_set, and clear them ***********/
++int pptp_dispatch(PPTP_CONN * conn, fd_set * read_set, fd_set * write_set)
++{
++ int r = 0;
++ assert(conn && conn->call);
++ /* Check for signals */
++ if (FD_ISSET(sigpipe_fd(), read_set)) {
++ if (sigpipe_read() == SIGALRM) pptp_handle_timer();
++ FD_CLR(sigpipe_fd(), read_set);
++ }
++ /* Check write_set could be set. */
++ if (FD_ISSET(conn->inet_sock, write_set)) {
++ FD_CLR(conn->inet_sock, write_set);
++ if (conn->write_size > 0)
++ r = pptp_write_some(conn);/* write as much as we can without blocking */
++ }
++ /* Check read_set */
++ if (r >= 0 && FD_ISSET(conn->inet_sock, read_set)) {
++ void *buffer; size_t size;
++ FD_CLR(conn->inet_sock, read_set);
++ r = pptp_read_some(conn); /* read as much as we can without blocking */
++ if (r < 0)
++ return r;
++ /* make packets of the buffer, while we can. */
++ while (r >= 0 && pptp_make_packet(conn, &buffer, &size)) {
++ r = pptp_dispatch_packet(conn, buffer, size);
++ free(buffer);
++ }
++ }
++ /* That's all, folks. Simple, eh? */
++ return r;
++}
++
++/*** Non-blocking write *******************************************************/
++int pptp_write_some(PPTP_CONN * conn) {
++ ssize_t retval;
++ assert(conn && conn->call);
++ retval = write(conn->inet_sock, conn->write_buffer, conn->write_size);
++ if (retval < 0) { /* error. */
++ if (errno == EAGAIN || errno == EINTR) {
++ return 0;
++ } else { /* a real error */
++ warn("write error: %s", strerror(errno));
++ return -1;
++ }
++ }
++ assert(retval <= conn->write_size);
++ conn->write_size -= retval;
++ memmove(conn->write_buffer, conn->write_buffer + retval, conn->write_size);
++ ctrlp_rep(conn->write_buffer, retval, 0);
++ return 0;
++}
++
++/*** Non-blocking read ********************************************************/
++int pptp_read_some(PPTP_CONN * conn)
++{
++ ssize_t retval;
++ assert(conn && conn->call);
++ if (conn->read_size == conn->read_alloc) { /* need to alloc more memory */
++ char *new_buffer = realloc(conn->read_buffer,
++ sizeof(*(conn->read_buffer)) * conn->read_alloc * 2);
++ if (new_buffer == NULL) {
++ warn("Out of memory"); return -1;
++ }
++ conn->read_alloc *= 2;
++ conn->read_buffer = new_buffer;
++ }
++ retval = read(conn->inet_sock, conn->read_buffer + conn->read_size,
++ conn->read_alloc - conn->read_size);
++ if (retval == 0) {
++ warn("read returned zero, peer has closed");
++ return -1;
++ }
++ if (retval < 0) {
++ if (errno == EINTR || errno == EAGAIN)
++ return 0;
++ else { /* a real error */
++ warn("read error: %s", strerror(errno));
++ return -1;
++ }
++ }
++ conn->read_size += retval;
++ assert(conn->read_size <= conn->read_alloc);
++ return 0;
++}
++
++/*** Packet formation *********************************************************/
++int pptp_make_packet(PPTP_CONN * conn, void **buf, size_t *size)
++{
++ struct pptp_header *header;
++ size_t bad_bytes = 0;
++ assert(conn && conn->call); assert(buf != NULL); assert(size != NULL);
++ /* Give up unless there are at least sizeof(pptp_header) bytes */
++ while ((conn->read_size-bad_bytes) >= sizeof(struct pptp_header)) {
++ /* Throw out bytes until we have a valid header. */
++ header = (struct pptp_header *) (conn->read_buffer + bad_bytes);
++ if (ntoh32(header->magic) != PPTP_MAGIC) goto throwitout;
++ if (ntoh16(header->reserved0) != 0)
++ warn("reserved0 field is not zero! (0x%x) Cisco feature? \n",
++ ntoh16(header->reserved0));
++ if (ntoh16(header->length) < sizeof(struct pptp_header)) goto throwitout;
++ if (ntoh16(header->length) > PPTP_CTRL_SIZE_MAX) goto throwitout;
++ /* well. I guess it's good. Let's see if we've got it all. */
++ if (ntoh16(header->length) > (conn->read_size-bad_bytes))
++ /* nope. Let's wait until we've got it, then. */
++ goto flushbadbytes;
++ /* One last check: */
++ if ((ntoh16(header->pptp_type) == PPTP_MESSAGE_CONTROL) &&
++ (ntoh16(header->length) !=
++ PPTP_CTRL_SIZE(ntoh16(header->ctrl_type))))
++ goto throwitout;
++ /* well, I guess we've got it. */
++ *size = ntoh16(header->length);
++ *buf = malloc(*size);
++ if (*buf == NULL) { warn("Out of memory."); return 0; /* ack! */ }
++ memcpy(*buf, conn->read_buffer + bad_bytes, *size);
++ /* Delete this packet from the read_buffer. */
++ conn->read_size -= (bad_bytes + *size);
++ memmove(conn->read_buffer, conn->read_buffer + bad_bytes + *size,
++ conn->read_size);
++ if (bad_bytes > 0)
++ warn("%lu bad bytes thrown away.", (unsigned long) bad_bytes);
++ return 1;
++throwitout:
++ bad_bytes++;
++ }
++flushbadbytes:
++ /* no more packets. Let's get rid of those bad bytes */
++ conn->read_size -= bad_bytes;
++ memmove(conn->read_buffer, conn->read_buffer + bad_bytes, conn->read_size);
++ if (bad_bytes > 0)
++ warn("%lu bad bytes thrown away.", (unsigned long) bad_bytes);
++ return 0;
++}
++
++/*** pptp_send_ctrl_packet ****************************************************/
++int pptp_send_ctrl_packet(PPTP_CONN * conn, void * buffer, size_t size)
++{
++ assert(conn && conn->call); assert(buffer);
++ if( conn->write_size > 0) pptp_write_some( conn);
++ if( conn->write_size == 0) {
++ ssize_t retval;
++ retval = write(conn->inet_sock, buffer, size);
++ if (retval < 0) { /* error. */
++ if (errno == EAGAIN || errno == EINTR) {
++ /* ignore */;
++ retval = 0;
++ } else { /* a real error */
++ warn("write error: %s", strerror(errno));
++ pptp_conn_destroy(conn); /* shut down fast. */
++ return 0;
++ }
++ }
++ ctrlp_rep( buffer, retval, 0);
++ size -= retval;
++ if( size <= 0) return 1;
++ }
++ /* Shove anything not written into the write buffer */
++ if (conn->write_size + size > conn->write_alloc) { /* need more memory */
++ char *new_buffer = realloc(conn->write_buffer,
++ sizeof(*(conn->write_buffer)) * conn->write_alloc * 2);
++ if (new_buffer == NULL) {
++ warn("Out of memory"); return 0;
++ }
++ conn->write_alloc *= 2;
++ conn->write_buffer = new_buffer;
++ }
++ memcpy(conn->write_buffer + conn->write_size, buffer, size);
++ conn->write_size += size;
++ ctrlp_rep( buffer,size,1);
++ return 1;
++}
++
++/*** Packet Dispatch **********************************************************/
++int pptp_dispatch_packet(PPTP_CONN * conn, void * buffer, size_t size)
++{
++ int r = 0;
++ struct pptp_header *header = (struct pptp_header *)buffer;
++ assert(conn && conn->call); assert(buffer);
++ assert(ntoh32(header->magic) == PPTP_MAGIC);
++ assert(ntoh16(header->length) == size);
++ switch (ntoh16(header->pptp_type)) {
++ case PPTP_MESSAGE_CONTROL:
++ r = ctrlp_disp(conn, buffer, size);
++ break;
++ case PPTP_MESSAGE_MANAGE:
++ /* MANAGEMENT messages aren't even part of the spec right now. */
++ dbglog("PPTP management message received, but not understood.");
++ break;
++ default:
++ dbglog("Unknown PPTP control message type received: %u",
++ (unsigned int) ntoh16(header->pptp_type));
++ break;
++ }
++ return r;
++}
++
++/*** log echo request/replies *************************************************/
++static void logecho( int type)
++{
++ /* hack to stop flooding the log files (the most interesting part is right
++ * after the connection built-up) */
++ if( nlogecho > 0) {
++ dbglog("Echo Re%s received.", type == PPTP_ECHO_RQST ? "quest" :"ply");
++ if( --nlogecho == 0)
++ dbglog("no more Echo Reply/Request packets will be reported.");
++ }
++}
++
++/*** pptp_dispatch_ctrl_packet ************************************************/
++int ctrlp_disp(PPTP_CONN * conn, void * buffer, size_t size)
++{
++ struct pptp_header *header = (struct pptp_header *)buffer;
++ u_int8_t close_reason = PPTP_STOP_NONE;
++ assert(conn && conn->call); assert(buffer);
++ assert(ntoh32(header->magic) == PPTP_MAGIC);
++ assert(ntoh16(header->length) == size);
++ assert(ntoh16(header->pptp_type) == PPTP_MESSAGE_CONTROL);
++ if (size < PPTP_CTRL_SIZE(ntoh16(header->ctrl_type))) {
++ warn("Invalid packet received [type: %d; length: %d].",
++ (int) ntoh16(header->ctrl_type), (int) size);
++ return 0;
++ }
++ switch (ntoh16(header->ctrl_type)) {
++ /* ----------- STANDARD Start-Session MESSAGES ------------ */
++ case PPTP_START_CTRL_CONN_RQST:
++ {
++ struct pptp_start_ctrl_conn *packet =
++ (struct pptp_start_ctrl_conn *) buffer;
++ struct pptp_start_ctrl_conn reply = {
++ PPTP_HEADER_CTRL(PPTP_START_CTRL_CONN_RPLY),
++ hton16(PPTP_VERSION), 0, 0,
++ hton32(PPTP_FRAME_CAP), hton32(PPTP_BEARER_CAP),
++ hton16(PPTP_MAX_CHANNELS), hton16(PPTP_FIRMWARE_VERSION),
++ PPTP_HOSTNAME, PPTP_VENDOR };
++ int idx, rc;
++ dbglog("Received Start Control Connection Request");
++ /* fix this packet, if necessary */
++ idx = get_quirk_index();
++ if (idx != -1 && pptp_fixups[idx].start_ctrl_conn) {
++ if ((rc = pptp_fixups[idx].start_ctrl_conn(&reply)))
++ warn("calling the start_ctrl_conn hook failed (%d)", rc);
++ }
++ if (conn->conn_state == CONN_IDLE) {
++ if (ntoh16(packet->version) < PPTP_VERSION) {
++ /* Can't support this (earlier) PPTP_VERSION */
++ reply.version = packet->version;
++ /* protocol version not supported */
++ reply.result_code = hton8(5);
++ pptp_send_ctrl_packet(conn, &reply, sizeof(reply));
++ pptp_reset_timer(); /* give sender a chance for a retry */
++ } else { /* same or greater version */
++ if (pptp_send_ctrl_packet(conn, &reply, sizeof(reply))) {
++ conn->conn_state = CONN_ESTABLISHED;
++ dbglog("server connection ESTABLISHED.");
++ pptp_reset_timer();
++ }
++ }
++ }
++ break;
++ }
++ case PPTP_START_CTRL_CONN_RPLY:
++ {
++ struct pptp_start_ctrl_conn *packet =
++ (struct pptp_start_ctrl_conn *) buffer;
++ dbglog("Received Start Control Connection Reply");
++ if (conn->conn_state == CONN_WAIT_CTL_REPLY) {
++ /* XXX handle collision XXX [see rfc] */
++ if (ntoh16(packet->version) != PPTP_VERSION) {
++ if (conn->callback != NULL)
++ conn->callback(conn, CONN_OPEN_FAIL);
++ close_reason = PPTP_STOP_PROTOCOL;
++ goto pptp_conn_close;
++ }
++ if (ntoh8(packet->result_code) != 1 &&
++ /* J'ai change le if () afin que la connection ne se ferme
++ * pas pour un "rien" :p adel@cybercable.fr -
++ *
++ * Don't close the connection if the result code is zero
++ * (feature found in certain ADSL modems)
++ */
++ ntoh8(packet->result_code) != 0) {
++ dbglog("Negative reply received to our Start Control "
++ "Connection Request");
++ ctrlp_error(packet->result_code, packet->error_code,
++ -1, pptp_start_ctrl_conn_rply,
++ MAX_START_CTRL_CONN_REPLY);
++ if (conn->callback != NULL)
++ conn->callback(conn, CONN_OPEN_FAIL);
++ close_reason = PPTP_STOP_PROTOCOL;
++ goto pptp_conn_close;
++ }
++ conn->conn_state = CONN_ESTABLISHED;
++ /* log session properties */
++ conn->version = ntoh16(packet->version);
++ conn->firmware_rev = ntoh16(packet->firmware_rev);
++ memcpy(conn->hostname, packet->hostname, sizeof(conn->hostname));
++ memcpy(conn->vendor, packet->vendor, sizeof(conn->vendor));
++ pptp_reset_timer(); /* 60 seconds until keep-alive */
++ dbglog("Client connection established.");
++ if (conn->callback != NULL)
++ conn->callback(conn, CONN_OPEN_DONE);
++ } /* else goto pptp_conn_close; */
++ break;
++ }
++ /* ----------- STANDARD Stop-Session MESSAGES ------------ */
++ case PPTP_STOP_CTRL_CONN_RQST:
++ {
++ /* conn_state should be CONN_ESTABLISHED, but it could be
++ * something else */
++ struct pptp_stop_ctrl_conn reply = {
++ PPTP_HEADER_CTRL(PPTP_STOP_CTRL_CONN_RPLY),
++ hton8(1), hton8(PPTP_GENERAL_ERROR_NONE), 0
++ };
++ dbglog("Received Stop Control Connection Request.");
++ if (conn->conn_state == CONN_IDLE) break;
++ if (pptp_send_ctrl_packet(conn, &reply, sizeof(reply))) {
++ if (conn->callback != NULL)
++ conn->callback(conn, CONN_CLOSE_RQST);
++ conn->conn_state = CONN_IDLE;
++ return -1;
++ }
++ break;
++ }
++ case PPTP_STOP_CTRL_CONN_RPLY:
++ {
++ dbglog("Received Stop Control Connection Reply.");
++ /* conn_state should be CONN_WAIT_STOP_REPLY, but it
++ * could be something else */
++ if (conn->conn_state == CONN_IDLE) break;
++ conn->conn_state = CONN_IDLE;
++ return -1;
++ }
++ /* ----------- STANDARD Echo/Keepalive MESSAGES ------------ */
++ case PPTP_ECHO_RPLY:
++ {
++ struct pptp_echo_rply *packet =
++ (struct pptp_echo_rply *) buffer;
++ logecho( PPTP_ECHO_RPLY);
++ if ((conn->ka_state == KA_OUTSTANDING) &&
++ (ntoh32(packet->identifier) == conn->ka_id)) {
++ conn->ka_id++;
++ conn->ka_state = KA_NONE;
++ pptp_reset_timer();
++ }
++ break;
++ }
++ case PPTP_ECHO_RQST:
++ {
++ struct pptp_echo_rqst *packet =
++ (struct pptp_echo_rqst *) buffer;
++ struct pptp_echo_rply reply = {
++ PPTP_HEADER_CTRL(PPTP_ECHO_RPLY),
++ packet->identifier, /* skip hton32(ntoh32(id)) */
++ hton8(1), hton8(PPTP_GENERAL_ERROR_NONE), 0
++ };
++ logecho( PPTP_ECHO_RQST);
++ pptp_send_ctrl_packet(conn, &reply, sizeof(reply));
++ pptp_reset_timer();
++ break;
++ }
++ /* ----------- OUTGOING CALL MESSAGES ------------ */
++ case PPTP_OUT_CALL_RQST:
++ {
++ struct pptp_out_call_rqst *packet =
++ (struct pptp_out_call_rqst *)buffer;
++ struct pptp_out_call_rply reply = {
++ PPTP_HEADER_CTRL(PPTP_OUT_CALL_RPLY),
++ 0 /* callid */, packet->call_id, 1, PPTP_GENERAL_ERROR_NONE, 0,
++ hton32(PPTP_CONNECT_SPEED),
++ hton16(PPTP_WINDOW), hton16(PPTP_DELAY), 0
++ };
++ dbglog("Received Outgoing Call Request.");
++ /* XXX PAC: eventually this should make an outgoing call. XXX */
++ reply.result_code = hton8(7); /* outgoing calls verboten */
++ pptp_send_ctrl_packet(conn, &reply, sizeof(reply));
++ break;
++ }
++ case PPTP_OUT_CALL_RPLY:
++ {
++ struct pptp_out_call_rply *packet =
++ (struct pptp_out_call_rply *)buffer;
++ PPTP_CALL * call;
++ u_int16_t callid = ntoh16(packet->call_id_peer);
++ dbglog("Received Outgoing Call Reply.");
++ if (!vector_search(conn->call, (int) callid, &call)) {
++ dbglog("PPTP_OUT_CALL_RPLY received for non-existant call: "
++ "peer call ID (us) %d call ID (them) %d.",
++ callid, ntoh16(packet->call_id));
++ break;
++ }
++ if (call->call_type != PPTP_CALL_PNS) {
++ dbglog("Ack! How did this call_type get here?"); /* XXX? */
++ break;
++ }
++ if (call->state.pns != PNS_WAIT_REPLY) {
++ warn("Unexpected(?) Outgoing Call Reply will be ignored.");
++ break;
++ }
++ /* check for errors */
++ if (packet->result_code != 1) {
++ /* An error. Log it verbosely. */
++ dbglog("Our outgoing call request [callid %d] has not been "
++ "accepted.", (int) callid);
++ ctrlp_error(packet->result_code, packet->error_code,
++ packet->cause_code, pptp_out_call_reply_result,
++ MAX_OUT_CALL_REPLY_RESULT);
++ call->state.pns = PNS_IDLE;
++ if (call->callback != NULL)
++ call->callback(conn, call, CALL_OPEN_FAIL);
++ pptp_call_destroy(conn, call);
++ } else {
++ /* connection established */
++ call->state.pns = PNS_ESTABLISHED;
++ call->peer_call_id = ntoh16(packet->call_id);
++ call->speed = ntoh32(packet->speed);
++ pptp_reset_timer();
++ /* call pptp_set_link. unless the user specified a quirk
++ and this quirk has a set_link hook, this is a noop */
++ pptp_set_link(conn, call->peer_call_id);
++ if (call->callback != NULL)
++ call->callback(conn, call, CALL_OPEN_DONE);
++ dbglog("Outgoing call established (call ID %u, peer's "
++ "call ID %u).\n", call->call_id, call->peer_call_id);
++ }
++ break;
++ }
++ /* ----------- INCOMING CALL MESSAGES ------------ */
++ /* XXX write me XXX */
++ /* ----------- CALL CONTROL MESSAGES ------------ */
++ case PPTP_CALL_CLEAR_RQST:
++ {
++ struct pptp_call_clear_rqst *packet =
++ (struct pptp_call_clear_rqst *)buffer;
++ struct pptp_call_clear_ntfy reply = {
++ PPTP_HEADER_CTRL(PPTP_CALL_CLEAR_NTFY), packet->call_id,
++ 1, PPTP_GENERAL_ERROR_NONE, 0, 0, {0}
++ };
++ dbglog("Received Call Clear Request.");
++ if (vector_contains(conn->call, ntoh16(packet->call_id))) {
++ PPTP_CALL * call;
++ vector_search(conn->call, ntoh16(packet->call_id), &call);
++ if (call->callback != NULL)
++ call->callback(conn, call, CALL_CLOSE_RQST);
++ pptp_send_ctrl_packet(conn, &reply, sizeof(reply));
++ pptp_call_destroy(conn, call);
++ dbglog("Call closed (RQST) (call id %d)", (int) call->call_id);
++ }
++ break;
++ }
++ case PPTP_CALL_CLEAR_NTFY:
++ {
++ struct pptp_call_clear_ntfy *packet =
++ (struct pptp_call_clear_ntfy *)buffer;
++ dbglog("Call disconnect notification received (call id %d)",
++ ntoh16(packet->call_id));
++ if (vector_contains(conn->call, ntoh16(packet->call_id))) {
++ PPTP_CALL * call;
++ ctrlp_error(packet->result_code, packet->error_code,
++ packet->cause_code, pptp_call_disc_ntfy,
++ MAX_CALL_DISC_NTFY);
++ vector_search(conn->call, ntoh16(packet->call_id), &call);
++ pptp_call_destroy(conn, call);
++ }
++ /* XXX we could log call stats here XXX */
++ /* XXX not all servers send this XXX */
++ break;
++ }
++ case PPTP_SET_LINK_INFO:
++ {
++ /* I HAVE NO CLUE WHAT TO DO IF send_accm IS NOT 0! */
++ /* this is really dealt with in the HDLC deencapsulation, anyway. */
++ struct pptp_set_link_info *packet =
++ (struct pptp_set_link_info *)buffer;
++ /* log it. */
++ dbglog("PPTP_SET_LINK_INFO received from peer_callid %u",
++ (unsigned int) ntoh16(packet->call_id_peer));
++ dbglog(" send_accm is %08lX, recv_accm is %08lX",
++ (unsigned long) ntoh32(packet->send_accm),
++ (unsigned long) ntoh32(packet->recv_accm));
++ if (!(ntoh32(packet->send_accm) == 0 &&
++ ntoh32(packet->recv_accm) == 0))
++ warn("Non-zero Async Control Character Maps are not supported!");
++ break;
++ }
++ default:
++ dbglog("Unrecognized Packet %d received.",
++ (int) ntoh16(((struct pptp_header *)buffer)->ctrl_type));
++ /* goto pptp_conn_close; */
++ break;
++ }
++ return 0;
++pptp_conn_close:
++ warn("pptp_conn_close(%d)", (int) close_reason);
++ pptp_conn_close(conn, close_reason);
++ return 0;
++}
++
++/*** pptp_set_link **************************************************************/
++void pptp_set_link(PPTP_CONN* conn, int peer_call_id)
++{
++ int idx, rc;
++ /* if we need to send a set_link packet because of buggy
++ hardware or pptp server, do it now */
++ if ((idx = get_quirk_index()) != -1 && pptp_fixups[idx].set_link_hook) {
++ struct pptp_set_link_info packet;
++ if ((rc = pptp_fixups[idx].set_link_hook(&packet, peer_call_id)))
++ warn("calling the set_link hook failed (%d)", rc);
++ if (pptp_send_ctrl_packet(conn, &packet, sizeof(packet))) {
++ pptp_reset_timer();
++ }
++ }
++}
++
++/*** Get info from call structure *********************************************/
++/* NOTE: The peer_call_id is undefined until we get a server response. */
++void pptp_call_get_ids(PPTP_CONN * conn, PPTP_CALL * call,
++ u_int16_t * call_id, u_int16_t * peer_call_id)
++{
++ assert(conn != NULL); assert(call != NULL);
++ *call_id = call->call_id;
++ *peer_call_id = call->peer_call_id;
++}
++
++/*** pptp_call_closure_put ****************************************************/
++void pptp_call_closure_put(PPTP_CONN * conn, PPTP_CALL * call, void *cl)
++{
++ assert(conn != NULL); assert(call != NULL);
++ call->closure = cl;
++}
++
++/*** pptp_call_closure_get ****************************************************/
++void * pptp_call_closure_get(PPTP_CONN * conn, PPTP_CALL * call)
++{
++ assert(conn != NULL); assert(call != NULL);
++ return call->closure;
++}
++
++/*** pptp_conn_closure_put ****************************************************/
++void pptp_conn_closure_put(PPTP_CONN * conn, void *cl)
++{
++ assert(conn != NULL);
++ conn->closure = cl;
++}
++
++/*** pptp_conn_closure_get ****************************************************/
++void * pptp_conn_closure_get(PPTP_CONN * conn)
++{
++ assert(conn != NULL);
++ return conn->closure;
++}
++
++/*** Reset keep-alive timer ***************************************************/
++static void pptp_reset_timer(void)
++{
++ const struct itimerval tv = { { 0, 0 }, /* stop on time-out */
++ { idle_wait, 0 } };
++ if (idle_wait) setitimer(ITIMER_REAL, &tv, NULL);
++}
++
++
++/*** Handle keep-alive timer **************************************************/
++static void pptp_handle_timer()
++{
++ int i;
++ /* "Keep Alives and Timers, 1": check connection state */
++ if (global.conn->conn_state != CONN_ESTABLISHED) {
++ if (global.conn->conn_state == CONN_WAIT_STOP_REPLY)
++ /* hard close. */
++ pptp_conn_destroy(global.conn);
++ else /* soft close */
++ pptp_conn_close(global.conn, PPTP_STOP_NONE);
++ }
++ /* "Keep Alives and Timers, 2": check echo status */
++ if (global.conn->ka_state == KA_OUTSTANDING) {
++ /* no response to keep-alive */
++ info("closing control connection due to missing echo reply");
++ pptp_conn_close(global.conn, PPTP_STOP_NONE);
++ } else { /* ka_state == NONE */ /* send keep-alive */
++ struct pptp_echo_rqst rqst = {
++ PPTP_HEADER_CTRL(PPTP_ECHO_RQST), hton32(global.conn->ka_id) };
++ pptp_send_ctrl_packet(global.conn, &rqst, sizeof(rqst));
++ global.conn->ka_state = KA_OUTSTANDING;
++ }
++ /* check incoming/outgoing call states for !IDLE && !ESTABLISHED */
++ for (i = 0; i < vector_size(global.conn->call); i++) {
++ PPTP_CALL * call = vector_get_Nth(global.conn->call, i);
++ if (call->call_type == PPTP_CALL_PNS) {
++ if (call->state.pns == PNS_WAIT_REPLY) {
++ /* send close request */
++ pptp_call_close(global.conn, call);
++ assert(call->state.pns == PNS_WAIT_DISCONNECT);
++ } else if (call->state.pns == PNS_WAIT_DISCONNECT) {
++ /* hard-close the call */
++ pptp_call_destroy(global.conn, call);
++ }
++ } else if (call->call_type == PPTP_CALL_PAC) {
++ if (call->state.pac == PAC_WAIT_REPLY) {
++ /* XXX FIXME -- drop the PAC connection XXX */
++ } else if (call->state.pac == PAC_WAIT_CS_ANS) {
++ /* XXX FIXME -- drop the PAC connection XXX */
++ }
++ }
++ }
++ pptp_reset_timer();
++}
+--- /dev/null
++++ b/pppd/plugins/pptp/pptp_ctrl.h
+@@ -0,0 +1,57 @@
++/* pptp_ctrl.h ... handle PPTP control connection.
++ * C. Scott Ananian <cananian@alumni.princeton.edu>
++ *
++ * $Id: pptp_ctrl.h,v 1.5 2004/11/09 01:42:32 quozl Exp $
++ */
++
++#ifndef INC_PPTP_CTRL_H
++#define INC_PPTP_CTRL_H
++#include <sys/types.h>
++
++typedef struct PPTP_CONN PPTP_CONN;
++typedef struct PPTP_CALL PPTP_CALL;
++
++enum call_state { CALL_OPEN_RQST, CALL_OPEN_DONE, CALL_OPEN_FAIL,
++ CALL_CLOSE_RQST, CALL_CLOSE_DONE };
++enum conn_state { CONN_OPEN_RQST, CONN_OPEN_DONE, CONN_OPEN_FAIL,
++ CONN_CLOSE_RQST, CONN_CLOSE_DONE };
++
++typedef void (*pptp_call_cb)(PPTP_CONN*, PPTP_CALL*, enum call_state);
++typedef void (*pptp_conn_cb)(PPTP_CONN*, enum conn_state);
++
++/* if 'isclient' is true, then will send 'conn open' packet to other host.
++ * not necessary if this is being opened by a server process after
++ * receiving a conn_open packet from client.
++ */
++PPTP_CONN * pptp_conn_open(int inet_sock, int isclient,
++ pptp_conn_cb callback);
++PPTP_CALL * pptp_call_open(PPTP_CONN * conn, int call_id,
++ pptp_call_cb callback, char *phonenr,int window);
++int pptp_conn_established(PPTP_CONN * conn);
++/* soft close. Will callback on completion. */
++void pptp_call_close(PPTP_CONN * conn, PPTP_CALL * call);
++/* hard close. */
++void pptp_call_destroy(PPTP_CONN *conn, PPTP_CALL *call);
++/* soft close. Will callback on completion. */
++void pptp_conn_close(PPTP_CONN * conn, u_int8_t close_reason);
++/* hard close */
++void pptp_conn_destroy(PPTP_CONN * conn);
++
++/* Add file descriptors used by pptp to fd_set. */
++void pptp_fd_set(PPTP_CONN * conn, fd_set * read_set, fd_set * write_set, int *max_fd);
++/* handle any pptp file descriptors set in fd_set, and clear them */
++int pptp_dispatch(PPTP_CONN * conn, fd_set * read_set, fd_set * write_set);
++
++/* Get info about connection, call */
++void pptp_call_get_ids(PPTP_CONN * conn, PPTP_CALL * call,
++ u_int16_t * call_id, u_int16_t * peer_call_id);
++/* Arbitrary user data about this call/connection.
++ * It is the caller's responsibility to free this data before calling
++ * pptp_call|conn_close()
++ */
++void * pptp_conn_closure_get(PPTP_CONN * conn);
++void pptp_conn_closure_put(PPTP_CONN * conn, void *cl);
++void * pptp_call_closure_get(PPTP_CONN * conn, PPTP_CALL * call);
++void pptp_call_closure_put(PPTP_CONN * conn, PPTP_CALL * call, void *cl);
++
++#endif /* INC_PPTP_CTRL_H */
+--- /dev/null
++++ b/pppd/plugins/pptp/pptp_msg.h
+@@ -0,0 +1,303 @@
++/* pptp.h: packet structures and magic constants for the PPTP protocol
++ * C. Scott Ananian <cananian@alumni.princeton.edu>
++ *
++ * $Id: pptp_msg.h,v 1.3 2003/02/15 10:37:21 quozl Exp $
++ */
++
++#ifndef INC_PPTP_H
++#define INC_PPTP_H
++
++/* Grab definitions of int16, int32, etc. */
++#include <sys/types.h>
++/* define "portable" htons, etc. */
++#define hton8(x) (x)
++#define ntoh8(x) (x)
++#define hton16(x) htons(x)
++#define ntoh16(x) ntohs(x)
++#define hton32(x) htonl(x)
++#define ntoh32(x) ntohl(x)
++
++/* PPTP magic numbers: ----------------------------------------- */
++
++#define PPTP_MAGIC 0x1A2B3C4D /* Magic cookie for PPTP datagrams */
++#define PPTP_PORT 1723 /* PPTP TCP port number */
++#define PPTP_PROTO 47 /* PPTP IP protocol number */
++
++/* Control Connection Message Types: --------------------------- */
++
++#define PPTP_MESSAGE_CONTROL 1
++#define PPTP_MESSAGE_MANAGE 2
++
++/* Control Message Types: -------------------------------------- */
++
++/* (Control Connection Management) */
++#define PPTP_START_CTRL_CONN_RQST 1
++#define PPTP_START_CTRL_CONN_RPLY 2
++#define PPTP_STOP_CTRL_CONN_RQST 3
++#define PPTP_STOP_CTRL_CONN_RPLY 4
++#define PPTP_ECHO_RQST 5
++#define PPTP_ECHO_RPLY 6
++
++/* (Call Management) */
++#define PPTP_OUT_CALL_RQST 7
++#define PPTP_OUT_CALL_RPLY 8
++#define PPTP_IN_CALL_RQST 9
++#define PPTP_IN_CALL_RPLY 10
++#define PPTP_IN_CALL_CONNECT 11
++#define PPTP_CALL_CLEAR_RQST 12
++#define PPTP_CALL_CLEAR_NTFY 13
++
++/* (Error Reporting) */
++#define PPTP_WAN_ERR_NTFY 14
++
++/* (PPP Session Control) */
++#define PPTP_SET_LINK_INFO 15
++
++/* PPTP version information: --------------------------------------*/
++#define PPTP_VERSION_STRING "1.00"
++#define PPTP_VERSION 0x100
++#define PPTP_FIRMWARE_STRING "0.01"
++#define PPTP_FIRMWARE_VERSION 0x001
++
++/* PPTP capabilities: ---------------------------------------------*/
++
++/* (Framing capabilities for msg sender) */
++#define PPTP_FRAME_ASYNC 1
++#define PPTP_FRAME_SYNC 2
++#define PPTP_FRAME_ANY 3
++
++/* (Bearer capabilities for msg sender) */
++#define PPTP_BEARER_ANALOG 1
++#define PPTP_BEARER_DIGITAL 2
++#define PPTP_BEARER_ANY 3
++
++#define PPTP_RESULT_GENERAL_ERROR 2
++
++/* (Reasons to close a connection) */
++#define PPTP_STOP_NONE 1 /* no good reason */
++#define PPTP_STOP_PROTOCOL 2 /* can't support peer's protocol version */
++#define PPTP_STOP_LOCAL_SHUTDOWN 3 /* requester is being shut down */
++
++/* PPTP datagram structures (all data in network byte order): ----------*/
++
++struct pptp_header {
++ u_int16_t length; /* message length in octets, including header */
++ u_int16_t pptp_type; /* PPTP message type. 1 for control message. */
++ u_int32_t magic; /* this should be PPTP_MAGIC. */
++ u_int16_t ctrl_type; /* Control message type (0-15) */
++ u_int16_t reserved0; /* reserved. MUST BE ZERO. */
++};
++
++struct pptp_start_ctrl_conn { /* for control message types 1 and 2 */
++ struct pptp_header header;
++
++ u_int16_t version; /* PPTP protocol version. = PPTP_VERSION */
++ u_int8_t result_code; /* these two fields should be zero on rqst msg*/
++ u_int8_t error_code; /* 0 unless result_code==2 (General Error) */
++ u_int32_t framing_cap; /* Framing capabilities */
++ u_int32_t bearer_cap; /* Bearer Capabilities */
++ u_int16_t max_channels; /* Maximum Channels (=0 for PNS, PAC ignores) */
++ u_int16_t firmware_rev; /* Firmware or Software Revision */
++ u_int8_t hostname[64]; /* Host Name (64 octets, zero terminated) */
++ u_int8_t vendor[64]; /* Vendor string (64 octets, zero term.) */
++ /* MS says that end of hostname/vendor fields should be filled with */
++ /* octets of value 0, but Win95 PPTP driver doesn't do this. */
++};
++
++struct pptp_stop_ctrl_conn { /* for control message types 3 and 4 */
++ struct pptp_header header;
++
++ u_int8_t reason_result; /* reason for rqst, result for rply */
++ u_int8_t error_code; /* MUST be 0, unless rply result==2 (general err)*/
++ u_int16_t reserved1; /* MUST be 0 */
++};
++
++struct pptp_echo_rqst { /* for control message type 5 */
++ struct pptp_header header;
++ u_int32_t identifier; /* arbitrary value set by sender which is used */
++ /* to match up reply and request */
++};
++
++struct pptp_echo_rply { /* for control message type 6 */
++ struct pptp_header header;
++ u_int32_t identifier; /* should correspond to id of rqst */
++ u_int8_t result_code;
++ u_int8_t error_code; /* =0, unless result_code==2 (general error) */
++ u_int16_t reserved1; /* MUST BE ZERO */
++};
++
++struct pptp_out_call_rqst { /* for control message type 7 */
++ struct pptp_header header;
++ u_int16_t call_id; /* Call ID (unique id used to multiplex data) */
++ u_int16_t call_sernum; /* Call Serial Number (used for logging) */
++ u_int32_t bps_min; /* Minimum BPS (lowest acceptable line speed) */
++ u_int32_t bps_max; /* Maximum BPS (highest acceptable line speed) */
++ u_int32_t bearer; /* Bearer type */
++ u_int32_t framing; /* Framing type */
++ u_int16_t recv_size; /* Recv. Window Size (no. of buffered packets) */
++ u_int16_t delay; /* Packet Processing Delay (in 1/10 sec) */
++ u_int16_t phone_len; /* Phone Number Length (num. of valid digits) */
++ u_int16_t reserved1; /* MUST BE ZERO */
++ u_int8_t phone_num[64]; /* Phone Number (64 octets, null term.) */
++ u_int8_t subaddress[64]; /* Subaddress (64 octets, null term.) */
++};
++
++struct pptp_out_call_rply { /* for control message type 8 */
++ struct pptp_header header;
++ u_int16_t call_id; /* Call ID (used to multiplex data over tunnel)*/
++ u_int16_t call_id_peer; /* Peer's Call ID (call_id of pptp_out_call_rqst)*/
++ u_int8_t result_code; /* Result Code (1 is no errors) */
++ u_int8_t error_code; /* Error Code (=0 unless result_code==2) */
++ u_int16_t cause_code; /* Cause Code (addt'l failure information) */
++ u_int32_t speed; /* Connect Speed (in BPS) */
++ u_int16_t recv_size; /* Recv. Window Size (no. of buffered packets) */
++ u_int16_t delay; /* Packet Processing Delay (in 1/10 sec) */
++ u_int32_t channel; /* Physical Channel ID (for logging) */
++};
++
++struct pptp_in_call_rqst { /* for control message type 9 */
++ struct pptp_header header;
++ u_int16_t call_id; /* Call ID (unique id used to multiplex data) */
++ u_int16_t call_sernum; /* Call Serial Number (used for logging) */
++ u_int32_t bearer; /* Bearer type */
++ u_int32_t channel; /* Physical Channel ID (for logging) */
++ u_int16_t dialed_len; /* Dialed Number Length (# of valid digits) */
++ u_int16_t dialing_len; /* Dialing Number Length (# of valid digits) */
++ u_int8_t dialed_num[64]; /* Dialed Number (64 octets, zero term.) */
++ u_int8_t dialing_num[64]; /* Dialing Number (64 octets, zero term.) */
++ u_int8_t subaddress[64]; /* Subaddress (64 octets, zero term.) */
++};
++
++struct pptp_in_call_rply { /* for control message type 10 */
++ struct pptp_header header;
++ u_int16_t call_id; /* Call ID (used to multiplex data over tunnel)*/
++ u_int16_t call_id_peer; /* Peer's Call ID (call_id of pptp_out_call_rqst)*/
++ u_int8_t result_code; /* Result Code (1 is no errors) */
++ u_int8_t error_code; /* Error Code (=0 unless result_code==2) */
++ u_int16_t recv_size; /* Recv. Window Size (no. of buffered packets) */
++ u_int16_t delay; /* Packet Processing Delay (in 1/10 sec) */
++ u_int16_t reserved1; /* MUST BE ZERO */
++};
++
++struct pptp_in_call_connect { /* for control message type 11 */
++ struct pptp_header header;
++ u_int16_t call_id_peer; /* Peer's Call ID (call_id of pptp_out_call_rqst)*/
++ u_int16_t reserved1; /* MUST BE ZERO */
++ u_int32_t speed; /* Connect Speed (in BPS) */
++ u_int16_t recv_size; /* Recv. Window Size (no. of buffered packets) */
++ u_int16_t delay; /* Packet Processing Delay (in 1/10 sec) */
++ u_int32_t framing; /* Framing type */
++};
++
++struct pptp_call_clear_rqst { /* for control message type 12 */
++ struct pptp_header header;
++ u_int16_t call_id; /* Call ID (used to multiplex data over tunnel)*/
++ u_int16_t reserved1; /* MUST BE ZERO */
++};
++
++struct pptp_call_clear_ntfy { /* for control message type 13 */
++ struct pptp_header header;
++ u_int16_t call_id; /* Call ID (used to multiplex data over tunnel)*/
++ u_int8_t result_code; /* Result Code */
++ u_int8_t error_code; /* Error Code (=0 unless result_code==2) */
++ u_int16_t cause_code; /* Cause Code (for ISDN, is Q.931 cause code) */
++ u_int16_t reserved1; /* MUST BE ZERO */
++ u_int8_t call_stats[128]; /* Call Statistics: 128 octets, ascii, 0-term */
++};
++
++struct pptp_wan_err_ntfy { /* for control message type 14 */
++ struct pptp_header header;
++ u_int16_t call_id_peer; /* Peer's Call ID (call_id of pptp_out_call_rqst)*/
++ u_int16_t reserved1; /* MUST BE ZERO */
++ u_int32_t crc_errors; /* CRC errors */
++ u_int32_t frame_errors; /* Framing errors */
++ u_int32_t hard_errors; /* Hardware overruns */
++ u_int32_t buff_errors; /* Buffer overruns */
++ u_int32_t time_errors; /* Time-out errors */
++ u_int32_t align_errors; /* Alignment errors */
++};
++
++struct pptp_set_link_info { /* for control message type 15 */
++ struct pptp_header header;
++ u_int16_t call_id_peer; /* Peer's Call ID (call_id of pptp_out_call_rqst) */
++ u_int16_t reserved1; /* MUST BE ZERO */
++ u_int32_t send_accm; /* Send ACCM (for PPP packets; default 0xFFFFFFFF)*/
++ u_int32_t recv_accm; /* Receive ACCM (for PPP pack.;default 0xFFFFFFFF)*/
++};
++
++/* helpful #defines: -------------------------------------------- */
++#define pptp_isvalid_ctrl(header, type, length) \
++ (!( ( ntoh16(((struct pptp_header *)header)->length) < (length) ) || \
++ ( ntoh16(((struct pptp_header *)header)->pptp_type) !=(type) ) || \
++ ( ntoh32(((struct pptp_header *)header)->magic) !=PPTP_MAGIC) || \
++ ( ntoh16(((struct pptp_header *)header)->ctrl_type) > PPTP_SET_LINK_INFO) || \
++ ( ntoh16(((struct pptp_header *)header)->reserved0) !=0 ) ))
++
++#define PPTP_HEADER_CTRL(type) \
++{ hton16(PPTP_CTRL_SIZE(type)), \
++ hton16(PPTP_MESSAGE_CONTROL), \
++ hton32(PPTP_MAGIC), \
++ hton16(type), 0 }
++
++#define PPTP_CTRL_SIZE(type) ( \
++(type==PPTP_START_CTRL_CONN_RQST)?sizeof(struct pptp_start_ctrl_conn): \
++(type==PPTP_START_CTRL_CONN_RPLY)?sizeof(struct pptp_start_ctrl_conn): \
++(type==PPTP_STOP_CTRL_CONN_RQST )?sizeof(struct pptp_stop_ctrl_conn): \
++(type==PPTP_STOP_CTRL_CONN_RPLY )?sizeof(struct pptp_stop_ctrl_conn): \
++(type==PPTP_ECHO_RQST )?sizeof(struct pptp_echo_rqst): \
++(type==PPTP_ECHO_RPLY )?sizeof(struct pptp_echo_rply): \
++(type==PPTP_OUT_CALL_RQST )?sizeof(struct pptp_out_call_rqst): \
++(type==PPTP_OUT_CALL_RPLY )?sizeof(struct pptp_out_call_rply): \
++(type==PPTP_IN_CALL_RQST )?sizeof(struct pptp_in_call_rqst): \
++(type==PPTP_IN_CALL_RPLY )?sizeof(struct pptp_in_call_rply): \
++(type==PPTP_IN_CALL_CONNECT )?sizeof(struct pptp_in_call_connect): \
++(type==PPTP_CALL_CLEAR_RQST )?sizeof(struct pptp_call_clear_rqst): \
++(type==PPTP_CALL_CLEAR_NTFY )?sizeof(struct pptp_call_clear_ntfy): \
++(type==PPTP_WAN_ERR_NTFY )?sizeof(struct pptp_wan_err_ntfy): \
++(type==PPTP_SET_LINK_INFO )?sizeof(struct pptp_set_link_info): \
++0)
++#define max(a,b) (((a)>(b))?(a):(b))
++#define PPTP_CTRL_SIZE_MAX ( \
++max(sizeof(struct pptp_start_ctrl_conn), \
++max(sizeof(struct pptp_echo_rqst), \
++max(sizeof(struct pptp_echo_rply), \
++max(sizeof(struct pptp_out_call_rqst), \
++max(sizeof(struct pptp_out_call_rply), \
++max(sizeof(struct pptp_in_call_rqst), \
++max(sizeof(struct pptp_in_call_rply), \
++max(sizeof(struct pptp_in_call_connect), \
++max(sizeof(struct pptp_call_clear_rqst), \
++max(sizeof(struct pptp_call_clear_ntfy), \
++max(sizeof(struct pptp_wan_err_ntfy), \
++max(sizeof(struct pptp_set_link_info), 0)))))))))))))
++
++
++/* gre header structure: -------------------------------------------- */
++
++#define PPTP_GRE_PROTO 0x880B
++#define PPTP_GRE_VER 0x1
++
++#define PPTP_GRE_FLAG_C 0x80
++#define PPTP_GRE_FLAG_R 0x40
++#define PPTP_GRE_FLAG_K 0x20
++#define PPTP_GRE_FLAG_S 0x10
++#define PPTP_GRE_FLAG_A 0x80
++
++#define PPTP_GRE_IS_C(f) ((f)&PPTP_GRE_FLAG_C)
++#define PPTP_GRE_IS_R(f) ((f)&PPTP_GRE_FLAG_R)
++#define PPTP_GRE_IS_K(f) ((f)&PPTP_GRE_FLAG_K)
++#define PPTP_GRE_IS_S(f) ((f)&PPTP_GRE_FLAG_S)
++#define PPTP_GRE_IS_A(f) ((f)&PPTP_GRE_FLAG_A)
++
++struct pptp_gre_header {
++ u_int8_t flags; /* bitfield */
++ u_int8_t ver; /* should be PPTP_GRE_VER (enhanced GRE) */
++ u_int16_t protocol; /* should be PPTP_GRE_PROTO (ppp-encaps) */
++ u_int16_t payload_len; /* size of ppp payload, not inc. gre header */
++ u_int16_t call_id; /* peer's call_id for this session */
++ u_int32_t seq; /* sequence number. Present if S==1 */
++ u_int32_t ack; /* seq number of highest packet recieved by */
++ /* sender in this session */
++};
++
++#endif /* INC_PPTP_H */
+--- /dev/null
++++ b/pppd/plugins/pptp/pptp_options.h
+@@ -0,0 +1,41 @@
++/* pptp_options.h ...... various constants used in the PPTP protocol.
++ * #define STANDARD to emulate NT 4.0 exactly.
++ * C. Scott Ananian <cananian@alumni.princeton.edu>
++ *
++ * $Id: pptp_options.h,v 1.3 2004/11/09 01:42:32 quozl Exp $
++ */
++
++#ifndef INC_PPTP_OPTIONS_H
++#define INC_PPTP_OPTIONS_H
++
++#undef PPTP_FIRMWARE_STRING
++#undef PPTP_FIRMWARE_VERSION
++#define PPTP_BUF_MAX 65536
++#define PPTP_TIMEOUT 60 /* seconds */
++extern int idle_wait;
++extern int max_echo_wait;
++#define PPTP_CONNECT_SPEED 1000000000
++#define PPTP_WINDOW 3
++#define PPTP_DELAY 0
++#define PPTP_BPS_MIN 2400
++#define PPTP_BPS_MAX 1000000000
++
++#ifndef STANDARD
++#define PPTP_MAX_CHANNELS 65535
++#define PPTP_FIRMWARE_STRING "0.01"
++#define PPTP_FIRMWARE_VERSION 0x001
++#define PPTP_HOSTNAME {'l','o','c','a','l',0}
++#define PPTP_VENDOR {'c','a','n','a','n','i','a','n',0}
++#define PPTP_FRAME_CAP PPTP_FRAME_ANY
++#define PPTP_BEARER_CAP PPTP_BEARER_ANY
++#else
++#define PPTP_MAX_CHANNELS 5
++#define PPTP_FIRMWARE_STRING "0.01"
++#define PPTP_FIRMWARE_VERSION 0
++#define PPTP_HOSTNAME {'l','o','c','a','l',0}
++#define PPTP_VENDOR {'N','T',0}
++#define PPTP_FRAME_CAP 2
++#define PPTP_BEARER_CAP 1
++#endif
++
++#endif /* INC_PPTP_OPTIONS_H */
+--- /dev/null
++++ b/pppd/plugins/pptp/pptp_quirks.c
+@@ -0,0 +1,54 @@
++/* pptp_quirks.c ...... various options to fix quirks found in buggy adsl modems
++ * mulix <mulix@actcom.co.il>
++ *
++ * $Id: pptp_quirks.c,v 1.2 2001/11/23 03:42:51 quozl Exp $
++ */
++
++#include <string.h>
++#include "orckit_quirks.h"
++#include "pptp_quirks.h"
++
++static int quirk_index = -1;
++
++struct pptp_fixup pptp_fixups[] = {
++ {BEZEQ_ISRAEL, ORCKIT, ORCKIT_ATUR3,
++ orckit_atur3_build_hook,
++ orckit_atur3_start_ctrl_conn_hook,
++ orckit_atur3_set_link_hook}
++};
++
++static int fixups_sz = sizeof(pptp_fixups)/sizeof(pptp_fixups[0]);
++
++/* return 0 on success, non 0 otherwise */
++int set_quirk_index(int index)
++{
++ if (index >= 0 && index < fixups_sz) {
++ quirk_index = index;
++ return 0;
++ }
++
++ return -1;
++}
++
++int get_quirk_index()
++{
++ return quirk_index;
++}
++
++/* return the index for this isp in the quirks table, -1 if not found */
++int find_quirk(const char* isp_name)
++{
++ int i = 0;
++ if (isp_name) {
++ while (i < fixups_sz && pptp_fixups[i].isp) {
++ if (!strcmp(pptp_fixups[i].isp, isp_name)) {
++ return i;
++ }
++ ++i;
++ }
++ }
++
++ return -1;
++}
++
++
+--- /dev/null
++++ b/pppd/plugins/pptp/pptp_quirks.h
+@@ -0,0 +1,59 @@
++/* pptp_quirks.h ...... various options to fix quirks found in buggy adsl modems
++ * mulix <mulix@actcom.co.il>
++ *
++ * $Id: pptp_quirks.h,v 1.1 2001/11/20 06:30:10 quozl Exp $
++ */
++
++#ifndef INC_PPTP_QUIRKS_H
++#define INC_PPTP_QUIRKS_H
++
++/* isp defs - correspond to slots in the fixups table */
++#define BEZEQ_ISRAEL "BEZEQ_ISRAEL"
++
++/* vendor defs */
++
++#define ORCKIT 1
++#define ALCATEL 2
++
++/* device defs */
++
++#define ORCKIT_ATUR2 1
++#define ORCKIT_ATUR3 2
++
++#include "pptp_msg.h"
++#include "pptp_ctrl.h"
++
++struct pptp_fixup {
++ const char* isp; /* which isp? e.g. Bezeq in Israel */
++ int vendor; /* which vendor? e.g. Orckit */
++ int device; /* which device? e.g. Orckit Atur3 */
++
++ /* use this hook to build your own out call request packet */
++ int (*out_call_rqst_hook)(struct pptp_out_call_rqst* packet);
++
++ /* use this hook to build your own start control connection packet */
++ /* note that this hook is called from two different places, depending
++ on whether this is a request or reply */
++ int (*start_ctrl_conn)(struct pptp_start_ctrl_conn* packet);
++
++ /* use this hook if you need to send a 'set_link' packet once
++ the connection is established */
++ int (*set_link_hook)(struct pptp_set_link_info* packet,
++ int peer_call_id);
++};
++
++extern struct pptp_fixup pptp_fixups[];
++
++/* find the index for this isp in the quirks table */
++/* return the index on success, -1 if not found */
++int find_quirk(const char* isp_name);
++
++/* set the global quirk index. return 0 on success, non 0 otherwise */
++int set_quirk_index(int index);
++
++/* get the global quirk index. return the index on success,
++ -1 if no quirk is defined */
++int get_quirk_index();
++
++
++#endif /* INC_PPTP_QUIRKS_H */
+--- /dev/null
++++ b/pppd/plugins/pptp/util.c
+@@ -0,0 +1,109 @@
++/* util.c ....... error message utilities.
++ * C. Scott Ananian <cananian@alumni.princeton.edu>
++ *
++ * $Id: util.c,v 1.11 2005/08/22 00:49:48 quozl Exp $
++ */
++
++#include <stdio.h>
++#include <stdarg.h>
++#include <syslog.h>
++#include <unistd.h>
++#include <stdlib.h>
++#include "util.h"
++
++#define MAKE_STRING(label) \
++va_list ap; \
++char buf[256], string[256]; \
++va_start(ap, format); \
++vsnprintf(buf, sizeof(buf), format, ap); \
++snprintf(string, sizeof(string), "%s %s[%s:%s:%d]: %s", \
++ log_string, label, func, file, line, buf); \
++va_end(ap)
++
++/*** connect a file to a file descriptor **************************************/
++int file2fd(const char *path, const char *mode, int fd)
++{
++ int ok = 0;
++ FILE *file = NULL;
++ file = fopen(path, mode);
++ if (file != NULL && dup2(fileno(file), fd) != -1)
++ ok = 1;
++ if (file) fclose(file);
++ return ok;
++}
++
++/* signal to pipe delivery implementation */
++#include <unistd.h>
++#include <fcntl.h>
++#include <signal.h>
++#include <string.h>
++
++/* pipe private to process */
++static int sigpipe[2];
++
++/* create a signal pipe, returns 0 for success, -1 with errno for failure */
++int sigpipe_create()
++{
++ int rc;
++
++ rc = pipe(sigpipe);
++ if (rc < 0) return rc;
++
++ fcntl(sigpipe[0], F_SETFD, FD_CLOEXEC);
++ fcntl(sigpipe[1], F_SETFD, FD_CLOEXEC);
++
++#ifdef O_NONBLOCK
++#define FLAG_TO_SET O_NONBLOCK
++#else
++#ifdef SYSV
++#define FLAG_TO_SET O_NDELAY
++#else /* BSD */
++#define FLAG_TO_SET FNDELAY
++#endif
++#endif
++
++ rc = fcntl(sigpipe[1], F_GETFL);
++ if (rc != -1)
++ rc = fcntl(sigpipe[1], F_SETFL, rc | FLAG_TO_SET);
++ if (rc < 0) return rc;
++ return 0;
++#undef FLAG_TO_SET
++}
++
++/* generic handler for signals, writes signal number to pipe */
++void sigpipe_handler(int signum)
++{
++ write(sigpipe[1], &signum, sizeof(signum));
++ signal(signum, sigpipe_handler);
++}
++
++/* assign a signal number to the pipe */
++void sigpipe_assign(int signum)
++{
++ struct sigaction sa;
++
++ memset(&sa, 0, sizeof(sa));
++ sa.sa_handler = sigpipe_handler;
++ sigaction(signum, &sa, NULL);
++}
++
++/* return the signal pipe read file descriptor for select(2) */
++int sigpipe_fd()
++{
++ return sigpipe[0];
++}
++
++/* read and return the pending signal from the pipe */
++int sigpipe_read()
++{
++ int signum;
++ read(sigpipe[0], &signum, sizeof(signum));
++ return signum;
++}
++
++void sigpipe_close()
++{
++ close(sigpipe[0]);
++ close(sigpipe[1]);
++}
++
+--- /dev/null
++++ b/pppd/plugins/pptp/util.h
+@@ -0,0 +1,31 @@
++/* util.h ....... error message utilities.
++ * C. Scott Ananian <cananian@alumni.princeton.edu>
++ *
++ * $Id: util.h,v 1.6 2005/03/10 01:18:20 quozl Exp $
++ */
++
++#ifndef INC_UTIL_H
++#define INC_UTIL_H
++
++int file2fd(const char *path, const char *mode, int fd);
++
++/* signal to pipe delivery implementation */
++
++/* create a signal pipe, returns 0 for success, -1 with errno for failure */
++int sigpipe_create();
++
++/* generic handler for signals, writes signal number to pipe */
++void sigpipe_handler(int signum);
++
++/* assign a signal number to the pipe */
++void sigpipe_assign(int signum);
++
++/* return the signal pipe read file descriptor for select(2) */
++int sigpipe_fd();
++
++/* read and return the pending signal from the pipe */
++int sigpipe_read();
++
++void sigpipe_close();
++
++#endif /* INC_UTIL_H */
+--- /dev/null
++++ b/pppd/plugins/pptp/vector.c
+@@ -0,0 +1,209 @@
++/* vector.c ..... store a vector of PPTP_CALL information and search it
++ * efficiently.
++ * C. Scott Ananian <cananian@alumni.princeton.edu>
++ *
++ * $Id: vector.c,v 1.3 2003/06/17 10:12:55 reink Exp $
++ */
++
++#include <stdlib.h>
++#include <string.h>
++#include <assert.h>
++#include "pptp_ctrl.h"
++#include "vector.h"
++/* #define VECTOR_DEBUG */
++#ifndef TRUE
++#define TRUE 1
++#endif
++#ifndef FALSE
++#define FALSE 0
++#endif
++
++struct vector_item {
++ int key;
++ PPTP_CALL *call;
++};
++
++struct vector_struct {
++ struct vector_item *item;
++ int size;
++ int alloc;
++#ifdef VECTOR_DEBUG
++ int key_max;
++#endif
++};
++
++static struct vector_item *binary_search(VECTOR *v, int key);
++
++/*** vector_create ************************************************************/
++VECTOR *vector_create()
++{
++ const int INITIAL_SIZE = 4;
++
++ VECTOR *v = malloc(sizeof(*v));
++ if (v == NULL) return v;
++
++ v->size = 0;
++ v->alloc = INITIAL_SIZE;
++ v->item = malloc(sizeof(*(v->item)) * (v->alloc));
++#ifdef VECTOR_DEBUG
++ v->key_max = -1;
++#endif
++ if (v->item == NULL) { free(v); return NULL; }
++ else return v;
++}
++
++/*** vector_destroy ***********************************************************/
++void vector_destroy(VECTOR *v)
++{
++ free(v->item);
++#ifdef VECTOR_DEBUG
++ v->item = NULL;
++#endif
++ free(v);
++}
++
++/*** vector_size **************************************************************/
++int vector_size(VECTOR *v)
++{
++ assert(v != NULL);
++ return v->size;
++}
++
++/*** vector_insert*************************************************************
++ * nice thing about file descriptors is that we are assured by POSIX
++ * that they are monotonically increasing.
++ */
++int vector_insert(VECTOR *v, int key, PPTP_CALL * call)
++{
++ int i;
++ assert(v != NULL && call != NULL);
++ assert(!vector_contains(v, key));
++#ifdef VECTOR_DEBUG
++ assert(v->key_max < key);
++#endif
++ if (!(v->size < v->alloc)) {
++ void *tmp = realloc(v->item, sizeof(*(v->item)) * 2 * v->alloc);
++ if (tmp != NULL) {
++ v->alloc *= 2;
++ v->item = tmp;
++ } else return FALSE; /* failed to alloc memory. */
++ }
++ assert(v->size < v->alloc);
++ /* for safety, we make this work in the general case;
++ * but this is optimized for adding call to the end of the vector.
++ */
++ for(i = v->size - 1; i >= 0; i--)
++ if (v->item[i].key < key)
++ break;
++ /* insert after item i */
++ memmove(&v->item[i + 2], &v->item[i + 1],
++ (v->size - i - 1) * sizeof(*(v->item)));
++ v->item[i + 1].key = key;
++ v->item[i + 1].call = call;
++ v->size++;
++#ifdef VECTOR_DEBUG
++ if (v->key_max < key) /* ie, always. */
++ v->key_max = key;
++#endif
++ return TRUE;
++}
++
++/*** vector_remove ************************************************************/
++int vector_remove(VECTOR *v, int key)
++{
++ struct vector_item *tmp;
++ assert(v != NULL);
++ if ((tmp =binary_search(v,key)) == NULL) return FALSE;
++ assert(tmp >= v->item && tmp < v->item + v->size);
++ memmove(tmp, tmp + 1, (v->size - (v->item - tmp) - 1) * sizeof(*(v->item)));
++ v->size--;
++ return TRUE;
++}
++
++/*** vector_search ************************************************************/
++int vector_search(VECTOR *v, int key, PPTP_CALL **call)
++{
++ struct vector_item *tmp;
++ assert(v != NULL);
++ tmp = binary_search(v, key);
++ if (tmp ==NULL) return FALSE;
++ *call = tmp->call;
++ return TRUE;
++}
++
++/*** vector_contains **********************************************************/
++int vector_contains(VECTOR *v, int key)
++{
++ assert(v != NULL);
++ return (binary_search(v, key) != NULL);
++}
++
++/*** vector_item **************************************************************/
++static struct vector_item *binary_search(VECTOR *v, int key)
++{
++ int l,r,x;
++ l = 0;
++ r = v->size - 1;
++ while (r >= l) {
++ x = (l + r)/2;
++ if (key < v->item[x].key) r = x - 1; else l = x + 1;
++ if (key == v->item[x].key) return &(v->item[x]);
++ }
++ return NULL;
++}
++
++/*** vector_scan ***************************************************************
++ * Hmm. Let's be fancy and use a binary search for the first
++ * unused key, taking advantage of the list is stored sorted; ie
++ * we can look at pointers and keys at two different locations,
++ * and if (ptr1 - ptr2) = (key1 - key2) then all the slots
++ * between ptr1 and ptr2 are filled. Note that ptr1-ptr2 should
++ * never be greater than key1-key2 (no duplicate keys!)... we
++ * check for this.
++ */
++int vector_scan(VECTOR *v, int lo, int hi, int *key)
++{
++ int l,r,x;
++ assert(v != NULL);
++ assert(key != NULL);
++ if ((v->size<1) || (lo < v->item[0].key)) { *key = lo; return TRUE; }
++ /* our array bounds */
++ l = 0; r = v->size - 1;
++ while (r > l) {
++ /* check for a free spot right after l */
++ if (v->item[l].key + 1 < v->item[l + 1].key) { /* found it! */
++ *key = v->item[l].key + 1;
++ return TRUE;
++ }
++ /* no dice. Let's see if the free spot is before or after the midpoint */
++ x = (l + r)/2;
++ /* Okay, we have right (r), left (l) and the probe (x). */
++ assert(x - l <= v->item[x].key - v->item[l].key);
++ assert(r - x <= v->item[r].key - v->item[x].key);
++ if (x - l < v->item[x].key - v->item[l].key)
++ /* room between l and x */
++ r = x;
++ else /* no room between l and x */
++ if (r - x < v->item[r].key - v->item[x].key)
++ /* room between x and r */
++ l = x;
++ else /* no room between x and r, either */
++ break; /* game over, man. */
++ }
++ /* no room found in already allocated space. Check to see if
++ * there's free space above allocated entries. */
++ if (v->item[v->size - 1].key < hi) {
++ *key = v->item[v->size - 1].key + 1;
++ return TRUE;
++ }
++ /* outta luck */
++ return FALSE;
++}
++
++/*** vector_get_Nth ***********************************************************/
++PPTP_CALL * vector_get_Nth(VECTOR *v, int n)
++{
++ assert(v != NULL);
++ assert(0 <= n && n < vector_size(v));
++ return v->item[n].call;
++}
+--- /dev/null
++++ b/pppd/plugins/pptp/vector.h
+@@ -0,0 +1,31 @@
++/* vector.h ..... store a vector of PPTP_CALL information and search it
++ * efficiently.
++ * C. Scott Ananian <cananian@alumni.princeton.edu>
++ *
++ * $Id: vector.h,v 1.1.1.1 2000/12/23 08:19:51 scott Exp $
++ */
++
++#ifndef INC_VECTOR_H
++#define INC_VECTOR_H
++
++#include "pptp_ctrl.h" /* for definition of PPTP_CALL */
++
++typedef struct vector_struct VECTOR;
++
++VECTOR *vector_create();
++void vector_destroy(VECTOR *v);
++
++int vector_size(VECTOR *v);
++
++/* vector_insert and vector_search return TRUE on success, FALSE on failure. */
++int vector_insert(VECTOR *v, int key, PPTP_CALL * call);
++int vector_remove(VECTOR *v, int key);
++int vector_search(VECTOR *v, int key, PPTP_CALL ** call);
++/* vector_contains returns FALSE if not found, TRUE if found. */
++int vector_contains(VECTOR *v, int key);
++/* find first unused key. Returns TRUE on success, FALSE if no. */
++int vector_scan(VECTOR *v, int lo, int hi, int *key);
++/* get a specific PPTP_CALL ... useful only when iterating. */
++PPTP_CALL * vector_get_Nth(VECTOR *v, int n);
++
++#endif /* INC_VECTOR_H */
diff --git a/package/ppp/utils/pfc.c b/package/ppp/utils/pfc.c
new file mode 100644
index 000000000..5476be170
--- /dev/null
+++ b/package/ppp/utils/pfc.c
@@ -0,0 +1,51 @@
+/*
+ * Taken from fli4l 3.0
+ * Make sure you compile it against the same libpcap version used in OpenWrt
+ */
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <string.h>
+
+#include <linux/types.h>
+#include <linux/ppp_defs.h>
+
+#include <pcap.h>
+#include <pcap-bpf.h>
+
+int main (int argc, char ** argv)
+{
+ pcap_t *pc; /* Fake struct pcap so we can compile expr */
+ struct bpf_program filter; /* Filter program for link-active pkts */
+ u_int32_t netmask=0;
+
+ int dflag = 3;
+ if (argc == 4)
+ {
+ if (!strcmp (argv[1], "-d"))
+ {
+ dflag = atoi (argv[2]);
+ argv += 2;
+ argc -=2;
+ }
+ }
+ if (argc != 2)
+ {
+ printf ("usage; %s [ -d <debug_level> ] expression\n", argv[0]);
+ return 1;
+ }
+
+ pc = pcap_open_dead(DLT_PPP_PPPD, PPP_HDRLEN);
+ if (pcap_compile(pc, &filter, argv[1], 1, netmask) == 0)
+ {
+ printf ("#\n# Expression: %s\n#\n", argv[1]);
+ bpf_dump (&filter, dflag);
+ return 0;
+ }
+ else
+ {
+ printf("error in active-filter expression: %s\n", pcap_geterr(pc));
+ }
+ return 1;
+}
diff --git a/package/ps3-utils/Makefile b/package/ps3-utils/Makefile
new file mode 100644
index 000000000..3d3ea1bef
--- /dev/null
+++ b/package/ps3-utils/Makefile
@@ -0,0 +1,70 @@
+#
+# Copyright (C) 2008-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ps3-utils
+PKG_REV:=6488134e48cf2d6f2d6471ced8346ac8cb1b855a
+PKG_VERSION:=20090320
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=git://git.kernel.org/pub/scm/linux/kernel/git/geoff/ps3-utils.git
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=$(PKG_REV)
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ps3-utils
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=PS3 Linux Utilities
+ URL:=http://kernel.org/pub/linux/kernel/people/geoff/cell/ps3-utils/
+ MAINTAINER:=Geoff Levand <geoffrey.levand@am.sony.com>
+ DEPENDS:=@TARGET_ps3||TARGET_ps3chk||TARGET_powerpc
+endef
+
+define Package/ps3-utils/description
+ The ps3-utils package is a set of system administration utilites for the
+ PS3 game console.
+endef
+
+define Build/Configure
+ (cd $(PKG_BUILD_DIR) && $(BASH) -x ./bootstrap)
+ $(call Build/Configure/Default)
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(INSTALL_DATA) \
+ $(PKG_INSTALL_DIR)/usr/include/ps3*.h \
+ $(1)/usr/include
+
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(INSTALL_BIN) \
+ $(PKG_INSTALL_DIR)/usr/lib/libps3-utils.{la,a,so*} \
+ $(1)/usr/lib/
+endef
+
+define Package/ps3-utils/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_DIR) $(1)/usr/lib
+
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ps3-boot-game-os $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ps3-dump-bootloader $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ps3-flash-util $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ps3-video-mode $(1)/usr/bin
+
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libps3-utils.so.* $(1)/usr/lib
+endef
+
+$(eval $(call BuildPackage,ps3-utils))
diff --git a/package/px5g/Makefile b/package/px5g/Makefile
new file mode 100644
index 000000000..ad4ec4058
--- /dev/null
+++ b/package/px5g/Makefile
@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=px5g
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/px5g
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Standalone X.509 certificate generator
+ MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org>
+endef
+
+define Package/px5g/description
+ Px5g is a tiny standalone X.509 certificate generator.
+ It suitable to create key files and certificates in DER
+ and PEM format for use with stunnel, uhttpd and others.
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Package/px5g/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/px5g $(1)/usr/sbin/px5g
+endef
+
+$(eval $(call BuildPackage,px5g))
diff --git a/package/px5g/src/Makefile b/package/px5g/src/Makefile
new file mode 100644
index 000000000..2bd95739c
--- /dev/null
+++ b/package/px5g/src/Makefile
@@ -0,0 +1,14 @@
+CFLAGS?=-O2
+CFLAGS+=
+SFLAGS:=--std=gnu99
+WFLAGS:=-Wall -Werror -pedantic
+LDFLAGS?=
+BINARY:=px5g
+
+all: $(BINARY)
+
+$(BINARY): *.c library/*.c
+ $(CC) -I. $(CFLAGS) $(SFLAGS) $(WFLAGS) $(LDFLAGS) -o $@ $+
+
+clean:
+ rm -f $(BINARY)
diff --git a/package/px5g/src/library/base64.c b/package/px5g/src/library/base64.c
new file mode 100644
index 000000000..b7cc5b84e
--- /dev/null
+++ b/package/px5g/src/library/base64.c
@@ -0,0 +1,264 @@
+/*
+ * RFC 1521 base64 encoding/decoding
+ *
+ * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
+ *
+ * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the names of PolarSSL or XySSL 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_BASE64_C)
+
+#include "polarssl/base64.h"
+
+static const unsigned char base64_enc_map[64] =
+{
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
+ 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+ 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', '+', '/'
+};
+
+static const unsigned char base64_dec_map[128] =
+{
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
+ 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 127, 127, 127, 127, 127
+};
+
+/*
+ * Encode a buffer into base64 format
+ */
+int base64_encode( unsigned char *dst, int *dlen,
+ unsigned char *src, int slen )
+{
+ int i, n;
+ int C1, C2, C3;
+ unsigned char *p;
+
+ if( slen == 0 )
+ return( 0 );
+
+ n = (slen << 3) / 6;
+
+ switch( (slen << 3) - (n * 6) )
+ {
+ case 2: n += 3; break;
+ case 4: n += 2; break;
+ default: break;
+ }
+
+ if( *dlen < n + 1 )
+ {
+ *dlen = n + 1;
+ return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
+ }
+
+ n = (slen / 3) * 3;
+
+ for( i = 0, p = dst; i < n; i += 3 )
+ {
+ C1 = *src++;
+ C2 = *src++;
+ C3 = *src++;
+
+ *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
+ *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
+ *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
+ *p++ = base64_enc_map[C3 & 0x3F];
+ }
+
+ if( i < slen )
+ {
+ C1 = *src++;
+ C2 = ((i + 1) < slen) ? *src++ : 0;
+
+ *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
+ *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
+
+ if( (i + 1) < slen )
+ *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
+ else *p++ = '=';
+
+ *p++ = '=';
+ }
+
+ *dlen = p - dst;
+ *p = 0;
+
+ return( 0 );
+}
+
+/*
+ * Decode a base64-formatted buffer
+ */
+int base64_decode( unsigned char *dst, int *dlen,
+ unsigned char *src, int slen )
+{
+ int i, j, n;
+ unsigned long x;
+ unsigned char *p;
+
+ for( i = j = n = 0; i < slen; i++ )
+ {
+ if( ( slen - i ) >= 2 &&
+ src[i] == '\r' && src[i + 1] == '\n' )
+ continue;
+
+ if( src[i] == '\n' )
+ continue;
+
+ if( src[i] == '=' && ++j > 2 )
+ return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+
+ if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
+ return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+
+ if( base64_dec_map[src[i]] < 64 && j != 0 )
+ return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+
+ n++;
+ }
+
+ if( n == 0 )
+ return( 0 );
+
+ n = ((n * 6) + 7) >> 3;
+
+ if( *dlen < n )
+ {
+ *dlen = n;
+ return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
+ }
+
+ for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
+ {
+ if( *src == '\r' || *src == '\n' )
+ continue;
+
+ j -= ( base64_dec_map[*src] == 64 );
+ x = (x << 6) | ( base64_dec_map[*src] & 0x3F );
+
+ if( ++n == 4 )
+ {
+ n = 0;
+ if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
+ if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
+ if( j > 2 ) *p++ = (unsigned char)( x );
+ }
+ }
+
+ *dlen = p - dst;
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <string.h>
+#include <stdio.h>
+
+static const unsigned char base64_test_dec[64] =
+{
+ 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
+ 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
+ 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
+ 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
+ 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
+ 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
+ 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
+ 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
+};
+
+static const unsigned char base64_test_enc[] =
+ "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
+ "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
+
+/*
+ * Checkup routine
+ */
+int base64_self_test( int verbose )
+{
+ int len;
+ unsigned char *src, buffer[128];
+
+ if( verbose != 0 )
+ printf( " Base64 encoding test: " );
+
+ len = sizeof( buffer );
+ src = (unsigned char *) base64_test_dec;
+
+ if( base64_encode( buffer, &len, src, 64 ) != 0 ||
+ memcmp( base64_test_enc, buffer, 88 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n Base64 decoding test: " );
+
+ len = sizeof( buffer );
+ src = (unsigned char *) base64_test_enc;
+
+ if( base64_decode( buffer, &len, src, 88 ) != 0 ||
+ memcmp( base64_test_dec, buffer, 64 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/package/px5g/src/library/bignum.c b/package/px5g/src/library/bignum.c
new file mode 100644
index 000000000..8b7c12ff0
--- /dev/null
+++ b/package/px5g/src/library/bignum.c
@@ -0,0 +1,2010 @@
+/*
+ * Multi-precision integer library
+ *
+ * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
+ *
+ * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the names of PolarSSL or XySSL 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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.
+ */
+/*
+ * This MPI implementation is based on:
+ *
+ * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
+ * http://www.stillhq.com/extracted/gnupg-api/mpi/
+ * http://math.libtomcrypt.com/files/tommath.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_BIGNUM_C)
+
+#include "polarssl/bignum.h"
+#include "polarssl/bn_mul.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#define ciL ((int) sizeof(t_int)) /* chars in limb */
+#define biL (ciL << 3) /* bits in limb */
+#define biH (ciL << 2) /* half limb size */
+
+/*
+ * Convert between bits/chars and number of limbs
+ */
+#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL)
+#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
+
+/*
+ * Initialize one or more mpi
+ */
+void mpi_init( mpi *X, ... )
+{
+ va_list args;
+
+ va_start( args, X );
+
+ while( X != NULL )
+ {
+ X->s = 1;
+ X->n = 0;
+ X->p = NULL;
+
+ X = va_arg( args, mpi* );
+ }
+
+ va_end( args );
+}
+
+/*
+ * Unallocate one or more mpi
+ */
+void mpi_free( mpi *X, ... )
+{
+ va_list args;
+
+ va_start( args, X );
+
+ while( X != NULL )
+ {
+ if( X->p != NULL )
+ {
+ memset( X->p, 0, X->n * ciL );
+ free( X->p );
+ }
+
+ X->s = 1;
+ X->n = 0;
+ X->p = NULL;
+
+ X = va_arg( args, mpi* );
+ }
+
+ va_end( args );
+}
+
+/*
+ * Enlarge to the specified number of limbs
+ */
+int mpi_grow( mpi *X, int nblimbs )
+{
+ t_int *p;
+
+ if( X->n < nblimbs )
+ {
+ if( ( p = (t_int *) malloc( nblimbs * ciL ) ) == NULL )
+ return( 1 );
+
+ memset( p, 0, nblimbs * ciL );
+
+ if( X->p != NULL )
+ {
+ memcpy( p, X->p, X->n * ciL );
+ memset( X->p, 0, X->n * ciL );
+ free( X->p );
+ }
+
+ X->n = nblimbs;
+ X->p = p;
+ }
+
+ return( 0 );
+}
+
+/*
+ * Copy the contents of Y into X
+ */
+int mpi_copy( mpi *X, mpi *Y )
+{
+ int ret, i;
+
+ if( X == Y )
+ return( 0 );
+
+ for( i = Y->n - 1; i > 0; i-- )
+ if( Y->p[i] != 0 )
+ break;
+ i++;
+
+ X->s = Y->s;
+
+ MPI_CHK( mpi_grow( X, i ) );
+
+ memset( X->p, 0, X->n * ciL );
+ memcpy( X->p, Y->p, i * ciL );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Swap the contents of X and Y
+ */
+void mpi_swap( mpi *X, mpi *Y )
+{
+ mpi T;
+
+ memcpy( &T, X, sizeof( mpi ) );
+ memcpy( X, Y, sizeof( mpi ) );
+ memcpy( Y, &T, sizeof( mpi ) );
+}
+
+/*
+ * Set value from integer
+ */
+int mpi_lset( mpi *X, int z )
+{
+ int ret;
+
+ MPI_CHK( mpi_grow( X, 1 ) );
+ memset( X->p, 0, X->n * ciL );
+
+ X->p[0] = ( z < 0 ) ? -z : z;
+ X->s = ( z < 0 ) ? -1 : 1;
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Return the number of least significant bits
+ */
+int mpi_lsb( mpi *X )
+{
+ int i, j, count = 0;
+
+ for( i = 0; i < X->n; i++ )
+ for( j = 0; j < (int) biL; j++, count++ )
+ if( ( ( X->p[i] >> j ) & 1 ) != 0 )
+ return( count );
+
+ return( 0 );
+}
+
+/*
+ * Return the number of most significant bits
+ */
+int mpi_msb( mpi *X )
+{
+ int i, j;
+
+ for( i = X->n - 1; i > 0; i-- )
+ if( X->p[i] != 0 )
+ break;
+
+ for( j = biL - 1; j >= 0; j-- )
+ if( ( ( X->p[i] >> j ) & 1 ) != 0 )
+ break;
+
+ return( ( i * biL ) + j + 1 );
+}
+
+/*
+ * Return the total size in bytes
+ */
+int mpi_size( mpi *X )
+{
+ return( ( mpi_msb( X ) + 7 ) >> 3 );
+}
+
+/*
+ * Convert an ASCII character to digit value
+ */
+static int mpi_get_digit( t_int *d, int radix, char c )
+{
+ *d = 255;
+
+ if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
+ if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
+ if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
+
+ if( *d >= (t_int) radix )
+ return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
+
+ return( 0 );
+}
+
+/*
+ * Import from an ASCII string
+ */
+int mpi_read_string( mpi *X, int radix, char *s )
+{
+ int ret, i, j, n;
+ t_int d;
+ mpi T;
+
+ if( radix < 2 || radix > 16 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ mpi_init( &T, NULL );
+
+ if( radix == 16 )
+ {
+ n = BITS_TO_LIMBS( strlen( s ) << 2 );
+
+ MPI_CHK( mpi_grow( X, n ) );
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ for( i = strlen( s ) - 1, j = 0; i >= 0; i--, j++ )
+ {
+ if( i == 0 && s[i] == '-' )
+ {
+ X->s = -1;
+ break;
+ }
+
+ MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
+ X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ for( i = 0; i < (int) strlen( s ); i++ )
+ {
+ if( i == 0 && s[i] == '-' )
+ {
+ X->s = -1;
+ continue;
+ }
+
+ MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
+ MPI_CHK( mpi_mul_int( &T, X, radix ) );
+ MPI_CHK( mpi_add_int( X, &T, d ) );
+ }
+ }
+
+cleanup:
+
+ mpi_free( &T, NULL );
+
+ return( ret );
+}
+
+/*
+ * Helper to write the digits high-order first
+ */
+static int mpi_write_hlp( mpi *X, int radix, char **p )
+{
+ int ret;
+ t_int r;
+
+ if( radix < 2 || radix > 16 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ MPI_CHK( mpi_mod_int( &r, X, radix ) );
+ MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
+
+ if( mpi_cmp_int( X, 0 ) != 0 )
+ MPI_CHK( mpi_write_hlp( X, radix, p ) );
+
+ if( r < 10 )
+ *(*p)++ = (char)( r + 0x30 );
+ else
+ *(*p)++ = (char)( r + 0x37 );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Export into an ASCII string
+ */
+int mpi_write_string( mpi *X, int radix, char *s, int *slen )
+{
+ int ret = 0, n;
+ char *p;
+ mpi T;
+
+ if( radix < 2 || radix > 16 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ n = mpi_msb( X );
+ if( radix >= 4 ) n >>= 1;
+ if( radix >= 16 ) n >>= 1;
+ n += 3;
+
+ if( *slen < n )
+ {
+ *slen = n;
+ return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
+ }
+
+ p = s;
+ mpi_init( &T, NULL );
+
+ if( X->s == -1 )
+ *p++ = '-';
+
+ if( radix == 16 )
+ {
+ int c, i, j, k;
+
+ for( i = X->n - 1, k = 0; i >= 0; i-- )
+ {
+ for( j = ciL - 1; j >= 0; j-- )
+ {
+ c = ( X->p[i] >> (j << 3) ) & 0xFF;
+
+ if( c == 0 && k == 0 && (i + j) != 0 )
+ continue;
+
+ p += sprintf( p, "%02X", c );
+ k = 1;
+ }
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_copy( &T, X ) );
+ MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
+ }
+
+ *p++ = '\0';
+ *slen = p - s;
+
+cleanup:
+
+ mpi_free( &T, NULL );
+
+ return( ret );
+}
+
+/*
+ * Read X from an opened file
+ */
+int mpi_read_file( mpi *X, int radix, FILE *fin )
+{
+ t_int d;
+ int slen;
+ char *p;
+ char s[1024];
+
+ memset( s, 0, sizeof( s ) );
+ if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
+ return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
+
+ slen = strlen( s );
+ if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
+ if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
+
+ p = s + slen;
+ while( --p >= s )
+ if( mpi_get_digit( &d, radix, *p ) != 0 )
+ break;
+
+ return( mpi_read_string( X, radix, p + 1 ) );
+}
+
+/*
+ * Write X into an opened file (or stdout if fout == NULL)
+ */
+int mpi_write_file( char *p, mpi *X, int radix, FILE *fout )
+{
+ int n, ret;
+ size_t slen;
+ size_t plen;
+ char s[1024];
+
+ n = sizeof( s );
+ memset( s, 0, n );
+ n -= 2;
+
+ MPI_CHK( mpi_write_string( X, radix, s, (int *) &n ) );
+
+ if( p == NULL ) p = "";
+
+ plen = strlen( p );
+ slen = strlen( s );
+ s[slen++] = '\r';
+ s[slen++] = '\n';
+
+ if( fout != NULL )
+ {
+ if( fwrite( p, 1, plen, fout ) != plen ||
+ fwrite( s, 1, slen, fout ) != slen )
+ return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
+ }
+ else
+ printf( "%s%s", p, s );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Import X from unsigned binary data, big endian
+ */
+int mpi_read_binary( mpi *X, unsigned char *buf, int buflen )
+{
+ int ret, i, j, n;
+
+ for( n = 0; n < buflen; n++ )
+ if( buf[n] != 0 )
+ break;
+
+ MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ for( i = buflen - 1, j = 0; i >= n; i--, j++ )
+ X->p[j / ciL] |= ((t_int) buf[i]) << ((j % ciL) << 3);
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Export X into unsigned binary data, big endian
+ */
+int mpi_write_binary( mpi *X, unsigned char *buf, int buflen )
+{
+ int i, j, n;
+
+ n = mpi_size( X );
+
+ if( buflen < n )
+ return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
+
+ memset( buf, 0, buflen );
+
+ for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
+ buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
+
+ return( 0 );
+}
+
+/*
+ * Left-shift: X <<= count
+ */
+int mpi_shift_l( mpi *X, int count )
+{
+ int ret, i, v0, t1;
+ t_int r0 = 0, r1;
+
+ v0 = count / (biL );
+ t1 = count & (biL - 1);
+
+ i = mpi_msb( X ) + count;
+
+ if( X->n * (int) biL < i )
+ MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
+
+ ret = 0;
+
+ /*
+ * shift by count / limb_size
+ */
+ if( v0 > 0 )
+ {
+ for( i = X->n - 1; i >= v0; i-- )
+ X->p[i] = X->p[i - v0];
+
+ for( ; i >= 0; i-- )
+ X->p[i] = 0;
+ }
+
+ /*
+ * shift by count % limb_size
+ */
+ if( t1 > 0 )
+ {
+ for( i = v0; i < X->n; i++ )
+ {
+ r1 = X->p[i] >> (biL - t1);
+ X->p[i] <<= t1;
+ X->p[i] |= r0;
+ r0 = r1;
+ }
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Right-shift: X >>= count
+ */
+int mpi_shift_r( mpi *X, int count )
+{
+ int i, v0, v1;
+ t_int r0 = 0, r1;
+
+ v0 = count / biL;
+ v1 = count & (biL - 1);
+
+ /*
+ * shift by count / limb_size
+ */
+ if( v0 > 0 )
+ {
+ for( i = 0; i < X->n - v0; i++ )
+ X->p[i] = X->p[i + v0];
+
+ for( ; i < X->n; i++ )
+ X->p[i] = 0;
+ }
+
+ /*
+ * shift by count % limb_size
+ */
+ if( v1 > 0 )
+ {
+ for( i = X->n - 1; i >= 0; i-- )
+ {
+ r1 = X->p[i] << (biL - v1);
+ X->p[i] >>= v1;
+ X->p[i] |= r0;
+ r0 = r1;
+ }
+ }
+
+ return( 0 );
+}
+
+/*
+ * Compare unsigned values
+ */
+int mpi_cmp_abs( mpi *X, mpi *Y )
+{
+ int i, j;
+
+ for( i = X->n - 1; i >= 0; i-- )
+ if( X->p[i] != 0 )
+ break;
+
+ for( j = Y->n - 1; j >= 0; j-- )
+ if( Y->p[j] != 0 )
+ break;
+
+ if( i < 0 && j < 0 )
+ return( 0 );
+
+ if( i > j ) return( 1 );
+ if( j > i ) return( -1 );
+
+ for( ; i >= 0; i-- )
+ {
+ if( X->p[i] > Y->p[i] ) return( 1 );
+ if( X->p[i] < Y->p[i] ) return( -1 );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mpi_cmp_mpi( mpi *X, mpi *Y )
+{
+ int i, j;
+
+ for( i = X->n - 1; i >= 0; i-- )
+ if( X->p[i] != 0 )
+ break;
+
+ for( j = Y->n - 1; j >= 0; j-- )
+ if( Y->p[j] != 0 )
+ break;
+
+ if( i < 0 && j < 0 )
+ return( 0 );
+
+ if( i > j ) return( X->s );
+ if( j > i ) return( -X->s );
+
+ if( X->s > 0 && Y->s < 0 ) return( 1 );
+ if( Y->s > 0 && X->s < 0 ) return( -1 );
+
+ for( ; i >= 0; i-- )
+ {
+ if( X->p[i] > Y->p[i] ) return( X->s );
+ if( X->p[i] < Y->p[i] ) return( -X->s );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mpi_cmp_int( mpi *X, int z )
+{
+ mpi Y;
+ t_int p[1];
+
+ *p = ( z < 0 ) ? -z : z;
+ Y.s = ( z < 0 ) ? -1 : 1;
+ Y.n = 1;
+ Y.p = p;
+
+ return( mpi_cmp_mpi( X, &Y ) );
+}
+
+/*
+ * Unsigned addition: X = |A| + |B| (HAC 14.7)
+ */
+int mpi_add_abs( mpi *X, mpi *A, mpi *B )
+{
+ int ret, i, j;
+ t_int *o, *p, c;
+
+ if( X == B )
+ {
+ mpi *T = A; A = X; B = T;
+ }
+
+ if( X != A )
+ MPI_CHK( mpi_copy( X, A ) );
+
+ for( j = B->n - 1; j >= 0; j-- )
+ if( B->p[j] != 0 )
+ break;
+
+ MPI_CHK( mpi_grow( X, j + 1 ) );
+
+ o = B->p; p = X->p; c = 0;
+
+ for( i = 0; i <= j; i++, o++, p++ )
+ {
+ *p += c; c = ( *p < c );
+ *p += *o; c += ( *p < *o );
+ }
+
+ while( c != 0 )
+ {
+ if( i >= X->n )
+ {
+ MPI_CHK( mpi_grow( X, i + 1 ) );
+ p = X->p + i;
+ }
+
+ *p += c; c = ( *p < c ); i++;
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Helper for mpi substraction
+ */
+static void mpi_sub_hlp( int n, t_int *s, t_int *d )
+{
+ int i;
+ t_int c, z;
+
+ for( i = c = 0; i < n; i++, s++, d++ )
+ {
+ z = ( *d < c ); *d -= c;
+ c = ( *d < *s ) + z; *d -= *s;
+ }
+
+ while( c != 0 )
+ {
+ z = ( *d < c ); *d -= c;
+ c = z; i++; d++;
+ }
+}
+
+/*
+ * Unsigned substraction: X = |A| - |B| (HAC 14.9)
+ */
+int mpi_sub_abs( mpi *X, mpi *A, mpi *B )
+{
+ mpi TB;
+ int ret, n;
+
+ if( mpi_cmp_abs( A, B ) < 0 )
+ return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
+
+ mpi_init( &TB, NULL );
+
+ if( X == B )
+ {
+ MPI_CHK( mpi_copy( &TB, B ) );
+ B = &TB;
+ }
+
+ if( X != A )
+ MPI_CHK( mpi_copy( X, A ) );
+
+ ret = 0;
+
+ for( n = B->n - 1; n >= 0; n-- )
+ if( B->p[n] != 0 )
+ break;
+
+ mpi_sub_hlp( n + 1, B->p, X->p );
+
+cleanup:
+
+ mpi_free( &TB, NULL );
+
+ return( ret );
+}
+
+/*
+ * Signed addition: X = A + B
+ */
+int mpi_add_mpi( mpi *X, mpi *A, mpi *B )
+{
+ int ret, s = A->s;
+
+ if( A->s * B->s < 0 )
+ {
+ if( mpi_cmp_abs( A, B ) >= 0 )
+ {
+ MPI_CHK( mpi_sub_abs( X, A, B ) );
+ X->s = s;
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_abs( X, B, A ) );
+ X->s = -s;
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_add_abs( X, A, B ) );
+ X->s = s;
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Signed substraction: X = A - B
+ */
+int mpi_sub_mpi( mpi *X, mpi *A, mpi *B )
+{
+ int ret, s = A->s;
+
+ if( A->s * B->s > 0 )
+ {
+ if( mpi_cmp_abs( A, B ) >= 0 )
+ {
+ MPI_CHK( mpi_sub_abs( X, A, B ) );
+ X->s = s;
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_abs( X, B, A ) );
+ X->s = -s;
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_add_abs( X, A, B ) );
+ X->s = s;
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Signed addition: X = A + b
+ */
+int mpi_add_int( mpi *X, mpi *A, int b )
+{
+ mpi _B;
+ t_int p[1];
+
+ p[0] = ( b < 0 ) ? -b : b;
+ _B.s = ( b < 0 ) ? -1 : 1;
+ _B.n = 1;
+ _B.p = p;
+
+ return( mpi_add_mpi( X, A, &_B ) );
+}
+
+/*
+ * Signed substraction: X = A - b
+ */
+int mpi_sub_int( mpi *X, mpi *A, int b )
+{
+ mpi _B;
+ t_int p[1];
+
+ p[0] = ( b < 0 ) ? -b : b;
+ _B.s = ( b < 0 ) ? -1 : 1;
+ _B.n = 1;
+ _B.p = p;
+
+ return( mpi_sub_mpi( X, A, &_B ) );
+}
+
+/*
+ * Helper for mpi multiplication
+ */
+static void mpi_mul_hlp( int i, t_int *s, t_int *d, t_int b )
+{
+ t_int c = 0, t = 0;
+
+#if defined(MULADDC_HUIT)
+ for( ; i >= 8; i -= 8 )
+ {
+ MULADDC_INIT
+ MULADDC_HUIT
+ MULADDC_STOP
+ }
+
+ for( ; i > 0; i-- )
+ {
+ MULADDC_INIT
+ MULADDC_CORE
+ MULADDC_STOP
+ }
+#else
+ for( ; i >= 16; i -= 16 )
+ {
+ MULADDC_INIT
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_STOP
+ }
+
+ for( ; i >= 8; i -= 8 )
+ {
+ MULADDC_INIT
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_STOP
+ }
+
+ for( ; i > 0; i-- )
+ {
+ MULADDC_INIT
+ MULADDC_CORE
+ MULADDC_STOP
+ }
+#endif
+
+ t++;
+
+ do {
+ *d += c; c = ( *d < c ); d++;
+ }
+ while( c != 0 );
+}
+
+/*
+ * Baseline multiplication: X = A * B (HAC 14.12)
+ */
+int mpi_mul_mpi( mpi *X, mpi *A, mpi *B )
+{
+ int ret, i, j;
+ mpi TA, TB;
+
+ mpi_init( &TA, &TB, NULL );
+
+ if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
+ if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
+
+ for( i = A->n - 1; i >= 0; i-- )
+ if( A->p[i] != 0 )
+ break;
+
+ for( j = B->n - 1; j >= 0; j-- )
+ if( B->p[j] != 0 )
+ break;
+
+ MPI_CHK( mpi_grow( X, i + j + 2 ) );
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ for( i++; j >= 0; j-- )
+ mpi_mul_hlp( i, A->p, X->p + j, B->p[j] );
+
+ X->s = A->s * B->s;
+
+cleanup:
+
+ mpi_free( &TB, &TA, NULL );
+
+ return( ret );
+}
+
+/*
+ * Baseline multiplication: X = A * b
+ */
+int mpi_mul_int( mpi *X, mpi *A, t_int b )
+{
+ mpi _B;
+ t_int p[1];
+
+ _B.s = 1;
+ _B.n = 1;
+ _B.p = p;
+ p[0] = b;
+
+ return( mpi_mul_mpi( X, A, &_B ) );
+}
+
+/*
+ * Division by mpi: A = Q * B + R (HAC 14.20)
+ */
+int mpi_div_mpi( mpi *Q, mpi *R, mpi *A, mpi *B )
+{
+ int ret, i, n, t, k;
+ mpi X, Y, Z, T1, T2;
+
+ if( mpi_cmp_int( B, 0 ) == 0 )
+ return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
+
+ mpi_init( &X, &Y, &Z, &T1, &T2, NULL );
+
+ if( mpi_cmp_abs( A, B ) < 0 )
+ {
+ if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
+ if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
+ return( 0 );
+ }
+
+ MPI_CHK( mpi_copy( &X, A ) );
+ MPI_CHK( mpi_copy( &Y, B ) );
+ X.s = Y.s = 1;
+
+ MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
+ MPI_CHK( mpi_lset( &Z, 0 ) );
+ MPI_CHK( mpi_grow( &T1, 2 ) );
+ MPI_CHK( mpi_grow( &T2, 3 ) );
+
+ k = mpi_msb( &Y ) % biL;
+ if( k < (int) biL - 1 )
+ {
+ k = biL - 1 - k;
+ MPI_CHK( mpi_shift_l( &X, k ) );
+ MPI_CHK( mpi_shift_l( &Y, k ) );
+ }
+ else k = 0;
+
+ n = X.n - 1;
+ t = Y.n - 1;
+ mpi_shift_l( &Y, biL * (n - t) );
+
+ while( mpi_cmp_mpi( &X, &Y ) >= 0 )
+ {
+ Z.p[n - t]++;
+ mpi_sub_mpi( &X, &X, &Y );
+ }
+ mpi_shift_r( &Y, biL * (n - t) );
+
+ for( i = n; i > t ; i-- )
+ {
+ if( X.p[i] >= Y.p[t] )
+ Z.p[i - t - 1] = ~0;
+ else
+ {
+#if defined(POLARSSL_HAVE_LONGLONG)
+ t_dbl r;
+
+ r = (t_dbl) X.p[i] << biL;
+ r |= (t_dbl) X.p[i - 1];
+ r /= Y.p[t];
+ if( r > ((t_dbl) 1 << biL) - 1)
+ r = ((t_dbl) 1 << biL) - 1;
+
+ Z.p[i - t - 1] = (t_int) r;
+#else
+ /*
+ * __udiv_qrnnd_c, from gmp/longlong.h
+ */
+ t_int q0, q1, r0, r1;
+ t_int d0, d1, d, m;
+
+ d = Y.p[t];
+ d0 = ( d << biH ) >> biH;
+ d1 = ( d >> biH );
+
+ q1 = X.p[i] / d1;
+ r1 = X.p[i] - d1 * q1;
+ r1 <<= biH;
+ r1 |= ( X.p[i - 1] >> biH );
+
+ m = q1 * d0;
+ if( r1 < m )
+ {
+ q1--, r1 += d;
+ while( r1 >= d && r1 < m )
+ q1--, r1 += d;
+ }
+ r1 -= m;
+
+ q0 = r1 / d1;
+ r0 = r1 - d1 * q0;
+ r0 <<= biH;
+ r0 |= ( X.p[i - 1] << biH ) >> biH;
+
+ m = q0 * d0;
+ if( r0 < m )
+ {
+ q0--, r0 += d;
+ while( r0 >= d && r0 < m )
+ q0--, r0 += d;
+ }
+ r0 -= m;
+
+ Z.p[i - t - 1] = ( q1 << biH ) | q0;
+#endif
+ }
+
+ Z.p[i - t - 1]++;
+ do
+ {
+ Z.p[i - t - 1]--;
+
+ MPI_CHK( mpi_lset( &T1, 0 ) );
+ T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
+ T1.p[1] = Y.p[t];
+ MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
+
+ MPI_CHK( mpi_lset( &T2, 0 ) );
+ T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
+ T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
+ T2.p[2] = X.p[i];
+ }
+ while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
+
+ MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
+ MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
+ MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
+
+ if( mpi_cmp_int( &X, 0 ) < 0 )
+ {
+ MPI_CHK( mpi_copy( &T1, &Y ) );
+ MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
+ MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
+ Z.p[i - t - 1]--;
+ }
+ }
+
+ if( Q != NULL )
+ {
+ mpi_copy( Q, &Z );
+ Q->s = A->s * B->s;
+ }
+
+ if( R != NULL )
+ {
+ mpi_shift_r( &X, k );
+ mpi_copy( R, &X );
+
+ R->s = A->s;
+ if( mpi_cmp_int( R, 0 ) == 0 )
+ R->s = 1;
+ }
+
+cleanup:
+
+ mpi_free( &X, &Y, &Z, &T1, &T2, NULL );
+
+ return( ret );
+}
+
+/*
+ * Division by int: A = Q * b + R
+ *
+ * Returns 0 if successful
+ * 1 if memory allocation failed
+ * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
+ */
+int mpi_div_int( mpi *Q, mpi *R, mpi *A, int b )
+{
+ mpi _B;
+ t_int p[1];
+
+ p[0] = ( b < 0 ) ? -b : b;
+ _B.s = ( b < 0 ) ? -1 : 1;
+ _B.n = 1;
+ _B.p = p;
+
+ return( mpi_div_mpi( Q, R, A, &_B ) );
+}
+
+/*
+ * Modulo: R = A mod B
+ */
+int mpi_mod_mpi( mpi *R, mpi *A, mpi *B )
+{
+ int ret;
+
+ MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
+
+ while( mpi_cmp_int( R, 0 ) < 0 )
+ MPI_CHK( mpi_add_mpi( R, R, B ) );
+
+ while( mpi_cmp_mpi( R, B ) >= 0 )
+ MPI_CHK( mpi_sub_mpi( R, R, B ) );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Modulo: r = A mod b
+ */
+int mpi_mod_int( t_int *r, mpi *A, int b )
+{
+ int i;
+ t_int x, y, z;
+
+ if( b == 0 )
+ return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
+
+ if( b < 0 )
+ b = -b;
+
+ /*
+ * handle trivial cases
+ */
+ if( b == 1 )
+ {
+ *r = 0;
+ return( 0 );
+ }
+
+ if( b == 2 )
+ {
+ *r = A->p[0] & 1;
+ return( 0 );
+ }
+
+ /*
+ * general case
+ */
+ for( i = A->n - 1, y = 0; i >= 0; i-- )
+ {
+ x = A->p[i];
+ y = ( y << biH ) | ( x >> biH );
+ z = y / b;
+ y -= z * b;
+
+ x <<= biH;
+ y = ( y << biH ) | ( x >> biH );
+ z = y / b;
+ y -= z * b;
+ }
+
+ *r = y;
+
+ return( 0 );
+}
+
+/*
+ * Fast Montgomery initialization (thanks to Tom St Denis)
+ */
+static void mpi_montg_init( t_int *mm, mpi *N )
+{
+ t_int x, m0 = N->p[0];
+
+ x = m0;
+ x += ( ( m0 + 2 ) & 4 ) << 1;
+ x *= ( 2 - ( m0 * x ) );
+
+ if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
+ if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
+ if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
+
+ *mm = ~x + 1;
+}
+
+/*
+ * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
+ */
+static void mpi_montmul( mpi *A, mpi *B, mpi *N, t_int mm, mpi *T )
+{
+ int i, n, m;
+ t_int u0, u1, *d;
+
+ memset( T->p, 0, T->n * ciL );
+
+ d = T->p;
+ n = N->n;
+ m = ( B->n < n ) ? B->n : n;
+
+ for( i = 0; i < n; i++ )
+ {
+ /*
+ * T = (T + u0*B + u1*N) / 2^biL
+ */
+ u0 = A->p[i];
+ u1 = ( d[0] + u0 * B->p[0] ) * mm;
+
+ mpi_mul_hlp( m, B->p, d, u0 );
+ mpi_mul_hlp( n, N->p, d, u1 );
+
+ *d++ = u0; d[n + 1] = 0;
+ }
+
+ memcpy( A->p, d, (n + 1) * ciL );
+
+ if( mpi_cmp_abs( A, N ) >= 0 )
+ mpi_sub_hlp( n, N->p, A->p );
+ else
+ /* prevent timing attacks */
+ mpi_sub_hlp( n, A->p, T->p );
+}
+
+/*
+ * Montgomery reduction: A = A * R^-1 mod N
+ */
+static void mpi_montred( mpi *A, mpi *N, t_int mm, mpi *T )
+{
+ t_int z = 1;
+ mpi U;
+
+ U.n = U.s = z;
+ U.p = &z;
+
+ mpi_montmul( A, &U, N, mm, T );
+}
+
+/*
+ * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
+ */
+int mpi_exp_mod( mpi *X, mpi *A, mpi *E, mpi *N, mpi *_RR )
+{
+ int ret, i, j, wsize, wbits;
+ int bufsize, nblimbs, nbits;
+ t_int ei, mm, state;
+ mpi RR, T, W[64];
+
+ if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ /*
+ * Init temps and window size
+ */
+ mpi_montg_init( &mm, N );
+ mpi_init( &RR, &T, NULL );
+ memset( W, 0, sizeof( W ) );
+
+ i = mpi_msb( E );
+
+ wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
+ ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
+
+ j = N->n + 1;
+ MPI_CHK( mpi_grow( X, j ) );
+ MPI_CHK( mpi_grow( &W[1], j ) );
+ MPI_CHK( mpi_grow( &T, j * 2 ) );
+
+ /*
+ * If 1st call, pre-compute R^2 mod N
+ */
+ if( _RR == NULL || _RR->p == NULL )
+ {
+ MPI_CHK( mpi_lset( &RR, 1 ) );
+ MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
+ MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
+
+ if( _RR != NULL )
+ memcpy( _RR, &RR, sizeof( mpi ) );
+ }
+ else
+ memcpy( &RR, _RR, sizeof( mpi ) );
+
+ /*
+ * W[1] = A * R^2 * R^-1 mod N = A * R mod N
+ */
+ if( mpi_cmp_mpi( A, N ) >= 0 )
+ mpi_mod_mpi( &W[1], A, N );
+ else mpi_copy( &W[1], A );
+
+ mpi_montmul( &W[1], &RR, N, mm, &T );
+
+ /*
+ * X = R^2 * R^-1 mod N = R mod N
+ */
+ MPI_CHK( mpi_copy( X, &RR ) );
+ mpi_montred( X, N, mm, &T );
+
+ if( wsize > 1 )
+ {
+ /*
+ * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
+ */
+ j = 1 << (wsize - 1);
+
+ MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
+ MPI_CHK( mpi_copy( &W[j], &W[1] ) );
+
+ for( i = 0; i < wsize - 1; i++ )
+ mpi_montmul( &W[j], &W[j], N, mm, &T );
+
+ /*
+ * W[i] = W[i - 1] * W[1]
+ */
+ for( i = j + 1; i < (1 << wsize); i++ )
+ {
+ MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
+ MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
+
+ mpi_montmul( &W[i], &W[1], N, mm, &T );
+ }
+ }
+
+ nblimbs = E->n;
+ bufsize = 0;
+ nbits = 0;
+ wbits = 0;
+ state = 0;
+
+ while( 1 )
+ {
+ if( bufsize == 0 )
+ {
+ if( nblimbs-- == 0 )
+ break;
+
+ bufsize = sizeof( t_int ) << 3;
+ }
+
+ bufsize--;
+
+ ei = (E->p[nblimbs] >> bufsize) & 1;
+
+ /*
+ * skip leading 0s
+ */
+ if( ei == 0 && state == 0 )
+ continue;
+
+ if( ei == 0 && state == 1 )
+ {
+ /*
+ * out of window, square X
+ */
+ mpi_montmul( X, X, N, mm, &T );
+ continue;
+ }
+
+ /*
+ * add ei to current window
+ */
+ state = 2;
+
+ nbits++;
+ wbits |= (ei << (wsize - nbits));
+
+ if( nbits == wsize )
+ {
+ /*
+ * X = X^wsize R^-1 mod N
+ */
+ for( i = 0; i < wsize; i++ )
+ mpi_montmul( X, X, N, mm, &T );
+
+ /*
+ * X = X * W[wbits] R^-1 mod N
+ */
+ mpi_montmul( X, &W[wbits], N, mm, &T );
+
+ state--;
+ nbits = 0;
+ wbits = 0;
+ }
+ }
+
+ /*
+ * process the remaining bits
+ */
+ for( i = 0; i < nbits; i++ )
+ {
+ mpi_montmul( X, X, N, mm, &T );
+
+ wbits <<= 1;
+
+ if( (wbits & (1 << wsize)) != 0 )
+ mpi_montmul( X, &W[1], N, mm, &T );
+ }
+
+ /*
+ * X = A^E * R * R^-1 mod N = A^E mod N
+ */
+ mpi_montred( X, N, mm, &T );
+
+cleanup:
+
+ for( i = (1 << (wsize - 1)); i < (1 << wsize); i++ )
+ mpi_free( &W[i], NULL );
+
+ if( _RR != NULL )
+ mpi_free( &W[1], &T, NULL );
+ else mpi_free( &W[1], &T, &RR, NULL );
+
+ return( ret );
+}
+
+/*
+ * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
+ */
+int mpi_gcd( mpi *G, mpi *A, mpi *B )
+{
+ int ret, lz, lzt;
+ mpi TG, TA, TB;
+
+ mpi_init( &TG, &TA, &TB, NULL );
+
+ MPI_CHK( mpi_copy( &TA, A ) );
+ MPI_CHK( mpi_copy( &TB, B ) );
+
+ lz = mpi_lsb( &TA );
+ lzt = mpi_lsb( &TB );
+
+ if ( lzt < lz )
+ lz = lzt;
+
+ MPI_CHK( mpi_shift_r( &TA, lz ) );
+ MPI_CHK( mpi_shift_r( &TB, lz ) );
+
+ TA.s = TB.s = 1;
+
+ while( mpi_cmp_int( &TA, 0 ) != 0 )
+ {
+ MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
+ MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
+
+ if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
+ {
+ MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
+ MPI_CHK( mpi_shift_r( &TA, 1 ) );
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
+ MPI_CHK( mpi_shift_r( &TB, 1 ) );
+ }
+ }
+
+ MPI_CHK( mpi_shift_l( &TB, lz ) );
+ MPI_CHK( mpi_copy( G, &TB ) );
+
+cleanup:
+
+ mpi_free( &TB, &TA, &TG, NULL );
+
+ return( ret );
+}
+
+#if defined(POLARSSL_GENPRIME)
+
+/*
+ * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
+ */
+int mpi_inv_mod( mpi *X, mpi *A, mpi *N )
+{
+ int ret;
+ mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
+
+ if( mpi_cmp_int( N, 0 ) <= 0 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ mpi_init( &TA, &TU, &U1, &U2, &G,
+ &TB, &TV, &V1, &V2, NULL );
+
+ MPI_CHK( mpi_gcd( &G, A, N ) );
+
+ if( mpi_cmp_int( &G, 1 ) != 0 )
+ {
+ ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
+ goto cleanup;
+ }
+
+ MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
+ MPI_CHK( mpi_copy( &TU, &TA ) );
+ MPI_CHK( mpi_copy( &TB, N ) );
+ MPI_CHK( mpi_copy( &TV, N ) );
+
+ MPI_CHK( mpi_lset( &U1, 1 ) );
+ MPI_CHK( mpi_lset( &U2, 0 ) );
+ MPI_CHK( mpi_lset( &V1, 0 ) );
+ MPI_CHK( mpi_lset( &V2, 1 ) );
+
+ do
+ {
+ while( ( TU.p[0] & 1 ) == 0 )
+ {
+ MPI_CHK( mpi_shift_r( &TU, 1 ) );
+
+ if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
+ {
+ MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
+ MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
+ }
+
+ MPI_CHK( mpi_shift_r( &U1, 1 ) );
+ MPI_CHK( mpi_shift_r( &U2, 1 ) );
+ }
+
+ while( ( TV.p[0] & 1 ) == 0 )
+ {
+ MPI_CHK( mpi_shift_r( &TV, 1 ) );
+
+ if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
+ {
+ MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
+ MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
+ }
+
+ MPI_CHK( mpi_shift_r( &V1, 1 ) );
+ MPI_CHK( mpi_shift_r( &V2, 1 ) );
+ }
+
+ if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
+ {
+ MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
+ MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
+ MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
+ MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
+ MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
+ }
+ }
+ while( mpi_cmp_int( &TU, 0 ) != 0 );
+
+ while( mpi_cmp_int( &V1, 0 ) < 0 )
+ MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
+
+ while( mpi_cmp_mpi( &V1, N ) >= 0 )
+ MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
+
+ MPI_CHK( mpi_copy( X, &V1 ) );
+
+cleanup:
+
+ mpi_free( &V2, &V1, &TV, &TB, &G,
+ &U2, &U1, &TU, &TA, NULL );
+
+ return( ret );
+}
+
+static const int small_prime[] =
+{
+ 3, 5, 7, 11, 13, 17, 19, 23,
+ 29, 31, 37, 41, 43, 47, 53, 59,
+ 61, 67, 71, 73, 79, 83, 89, 97,
+ 101, 103, 107, 109, 113, 127, 131, 137,
+ 139, 149, 151, 157, 163, 167, 173, 179,
+ 181, 191, 193, 197, 199, 211, 223, 227,
+ 229, 233, 239, 241, 251, 257, 263, 269,
+ 271, 277, 281, 283, 293, 307, 311, 313,
+ 317, 331, 337, 347, 349, 353, 359, 367,
+ 373, 379, 383, 389, 397, 401, 409, 419,
+ 421, 431, 433, 439, 443, 449, 457, 461,
+ 463, 467, 479, 487, 491, 499, 503, 509,
+ 521, 523, 541, 547, 557, 563, 569, 571,
+ 577, 587, 593, 599, 601, 607, 613, 617,
+ 619, 631, 641, 643, 647, 653, 659, 661,
+ 673, 677, 683, 691, 701, 709, 719, 727,
+ 733, 739, 743, 751, 757, 761, 769, 773,
+ 787, 797, 809, 811, 821, 823, 827, 829,
+ 839, 853, 857, 859, 863, 877, 881, 883,
+ 887, 907, 911, 919, 929, 937, 941, 947,
+ 953, 967, 971, 977, 983, 991, 997, -103
+};
+
+/*
+ * Miller-Rabin primality test (HAC 4.24)
+ */
+int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng )
+{
+ int ret, i, j, n, s, xs;
+ mpi W, R, T, A, RR;
+ unsigned char *p;
+
+ if( mpi_cmp_int( X, 0 ) == 0 )
+ return( 0 );
+
+ mpi_init( &W, &R, &T, &A, &RR, NULL );
+
+ xs = X->s; X->s = 1;
+
+ /*
+ * test trivial factors first
+ */
+ if( ( X->p[0] & 1 ) == 0 )
+ return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+
+ for( i = 0; small_prime[i] > 0; i++ )
+ {
+ t_int r;
+
+ if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
+ return( 0 );
+
+ MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
+
+ if( r == 0 )
+ return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+ }
+
+ /*
+ * W = |X| - 1
+ * R = W >> lsb( W )
+ */
+ s = mpi_lsb( &W );
+ MPI_CHK( mpi_sub_int( &W, X, 1 ) );
+ MPI_CHK( mpi_copy( &R, &W ) );
+ MPI_CHK( mpi_shift_r( &R, s ) );
+
+ i = mpi_msb( X );
+ /*
+ * HAC, table 4.4
+ */
+ n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
+ ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
+ ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
+
+ for( i = 0; i < n; i++ )
+ {
+ /*
+ * pick a random A, 1 < A < |X| - 1
+ */
+ MPI_CHK( mpi_grow( &A, X->n ) );
+
+ p = (unsigned char *) A.p;
+ for( j = 0; j < A.n * ciL; j++ )
+ *p++ = (unsigned char) f_rng( p_rng );
+
+ j = mpi_msb( &A ) - mpi_msb( &W );
+ MPI_CHK( mpi_shift_r( &A, j + 1 ) );
+ A.p[0] |= 3;
+
+ /*
+ * A = A^R mod |X|
+ */
+ MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
+
+ if( mpi_cmp_mpi( &A, &W ) == 0 ||
+ mpi_cmp_int( &A, 1 ) == 0 )
+ continue;
+
+ j = 1;
+ while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
+ {
+ /*
+ * A = A * A mod |X|
+ */
+ MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
+ MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
+
+ if( mpi_cmp_int( &A, 1 ) == 0 )
+ break;
+
+ j++;
+ }
+
+ /*
+ * not prime if A != |X| - 1 or A == 1
+ */
+ if( mpi_cmp_mpi( &A, &W ) != 0 ||
+ mpi_cmp_int( &A, 1 ) == 0 )
+ {
+ ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
+ break;
+ }
+ }
+
+cleanup:
+
+ X->s = xs;
+
+ mpi_free( &RR, &A, &T, &R, &W, NULL );
+
+ return( ret );
+}
+
+/*
+ * Prime number generation
+ */
+int mpi_gen_prime( mpi *X, int nbits, int dh_flag,
+ int (*f_rng)(void *), void *p_rng )
+{
+ int ret, k, n;
+ unsigned char *p;
+ mpi Y;
+
+ if( nbits < 3 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ mpi_init( &Y, NULL );
+
+ n = BITS_TO_LIMBS( nbits );
+
+ MPI_CHK( mpi_grow( X, n ) );
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ p = (unsigned char *) X->p;
+ for( k = 0; k < X->n * ciL; k++ )
+ *p++ = (unsigned char) f_rng( p_rng );
+
+ k = mpi_msb( X );
+ if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
+ if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
+
+ X->p[0] |= 3;
+
+ if( dh_flag == 0 )
+ {
+ while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
+ {
+ if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+ goto cleanup;
+
+ MPI_CHK( mpi_add_int( X, X, 2 ) );
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
+ MPI_CHK( mpi_shift_r( &Y, 1 ) );
+
+ while( 1 )
+ {
+ if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
+ {
+ if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
+ break;
+
+ if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+ goto cleanup;
+ }
+
+ if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+ goto cleanup;
+
+ MPI_CHK( mpi_add_int( &Y, X, 1 ) );
+ MPI_CHK( mpi_add_int( X, X, 2 ) );
+ MPI_CHK( mpi_shift_r( &Y, 1 ) );
+ }
+ }
+
+cleanup:
+
+ mpi_free( &Y, NULL );
+
+ return( ret );
+}
+
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+
+#define GCD_PAIR_COUNT 3
+
+static const int gcd_pairs[GCD_PAIR_COUNT][3] =
+{
+ { 693, 609, 21 },
+ { 1764, 868, 28 },
+ { 768454923, 542167814, 1 }
+};
+
+/*
+ * Checkup routine
+ */
+int mpi_self_test( int verbose )
+{
+ int ret, i;
+ mpi A, E, N, X, Y, U, V;
+
+ mpi_init( &A, &E, &N, &X, &Y, &U, &V, NULL );
+
+ MPI_CHK( mpi_read_string( &A, 16,
+ "EFE021C2645FD1DC586E69184AF4A31E" \
+ "D5F53E93B5F123FA41680867BA110131" \
+ "944FE7952E2517337780CB0DB80E61AA" \
+ "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
+
+ MPI_CHK( mpi_read_string( &E, 16,
+ "B2E7EFD37075B9F03FF989C7C5051C20" \
+ "34D2A323810251127E7BF8625A4F49A5" \
+ "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
+ "5B5C25763222FEFCCFC38B832366C29E" ) );
+
+ MPI_CHK( mpi_read_string( &N, 16,
+ "0066A198186C18C10B2F5ED9B522752A" \
+ "9830B69916E535C8F047518A889A43A5" \
+ "94B6BED27A168D31D4A52F88925AA8F5" ) );
+
+ MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
+
+ MPI_CHK( mpi_read_string( &U, 16,
+ "602AB7ECA597A3D6B56FF9829A5E8B85" \
+ "9E857EA95A03512E2BAE7391688D264A" \
+ "A5663B0341DB9CCFD2C4C5F421FEC814" \
+ "8001B72E848A38CAE1C65F78E56ABDEF" \
+ "E12D3C039B8A02D6BE593F0BBBDA56F1" \
+ "ECF677152EF804370C1A305CAF3B5BF1" \
+ "30879B56C61DE584A0F53A2447A51E" ) );
+
+ if( verbose != 0 )
+ printf( " MPI test #1 (mul_mpi): " );
+
+ if( mpi_cmp_mpi( &X, &U ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+ MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
+
+ MPI_CHK( mpi_read_string( &U, 16,
+ "256567336059E52CAE22925474705F39A94" ) );
+
+ MPI_CHK( mpi_read_string( &V, 16,
+ "6613F26162223DF488E9CD48CC132C7A" \
+ "0AC93C701B001B092E4E5B9F73BCD27B" \
+ "9EE50D0657C77F374E903CDFA4C642" ) );
+
+ if( verbose != 0 )
+ printf( " MPI test #2 (div_mpi): " );
+
+ if( mpi_cmp_mpi( &X, &U ) != 0 ||
+ mpi_cmp_mpi( &Y, &V ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+ MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
+
+ MPI_CHK( mpi_read_string( &U, 16,
+ "36E139AEA55215609D2816998ED020BB" \
+ "BD96C37890F65171D948E9BC7CBAA4D9" \
+ "325D24D6A3C12710F10A09FA08AB87" ) );
+
+ if( verbose != 0 )
+ printf( " MPI test #3 (exp_mod): " );
+
+ if( mpi_cmp_mpi( &X, &U ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+ MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
+
+ MPI_CHK( mpi_read_string( &U, 16,
+ "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
+ "C3DBA76456363A10869622EAC2DD84EC" \
+ "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
+
+ if( verbose != 0 )
+ printf( " MPI test #4 (inv_mod): " );
+
+ if( mpi_cmp_mpi( &X, &U ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+ if( verbose != 0 )
+ printf( " MPI test #5 (simple gcd): " );
+
+ for ( i = 0; i < GCD_PAIR_COUNT; i++)
+ {
+ MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
+ MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
+
+ MPI_CHK( mpi_gcd( &A, &X, &Y ) );
+
+ if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed at %d\n", i );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+cleanup:
+
+ if( ret != 0 && verbose != 0 )
+ printf( "Unexpected error, return code = %08X\n", ret );
+
+ mpi_free( &V, &U, &Y, &X, &N, &E, &A, NULL );
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( ret );
+}
+
+#endif
+
+#endif
diff --git a/package/px5g/src/library/havege.c b/package/px5g/src/library/havege.c
new file mode 100644
index 000000000..266299d3b
--- /dev/null
+++ b/package/px5g/src/library/havege.c
@@ -0,0 +1,276 @@
+/*
+ * HAVEGE: HArdware Volatile Entropy Gathering and Expansion
+ *
+ * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
+ *
+ * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the names of PolarSSL or XySSL 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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.
+ */
+/*
+ * The HAVEGE RNG was designed by Andre Seznec in 2002.
+ *
+ * http://www.irisa.fr/caps/projects/hipsor/publi.php
+ *
+ * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr
+ */
+
+#include <string.h>
+#include <time.h>
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_HAVEGE_C)
+
+#include "polarssl/havege.h"
+#include "polarssl/timing.h"
+
+/* ------------------------------------------------------------------------
+ * On average, one iteration accesses two 8-word blocks in the havege WALK
+ * table, and generates 16 words in the RES array.
+ *
+ * The data read in the WALK table is updated and permuted after each use.
+ * The result of the hardware clock counter read is used for this update.
+ *
+ * 25 conditional tests are present. The conditional tests are grouped in
+ * two nested groups of 12 conditional tests and 1 test that controls the
+ * permutation; on average, there should be 6 tests executed and 3 of them
+ * should be mispredicted.
+ * ------------------------------------------------------------------------
+ */
+
+#define SWAP(X,Y) { int *T = X; X = Y; Y = T; }
+
+#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
+#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
+
+#define TST1_LEAVE U1++; }
+#define TST2_LEAVE U2++; }
+
+#define ONE_ITERATION \
+ \
+ PTEST = PT1 >> 20; \
+ \
+ TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
+ TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
+ TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
+ \
+ TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
+ TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
+ TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
+ \
+ PTX = (PT1 >> 18) & 7; \
+ PT1 &= 0x1FFF; \
+ PT2 &= 0x1FFF; \
+ CLK = (int) hardclock(); \
+ \
+ i = 0; \
+ A = &WALK[PT1 ]; RES[i++] ^= *A; \
+ B = &WALK[PT2 ]; RES[i++] ^= *B; \
+ C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \
+ D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \
+ \
+ IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \
+ *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \
+ *B = IN ^ U1; \
+ *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \
+ *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \
+ \
+ A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \
+ B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \
+ C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \
+ D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \
+ \
+ if( PTEST & 1 ) SWAP( A, C ); \
+ \
+ IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \
+ *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \
+ *B = IN; CLK = (int) hardclock(); \
+ *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \
+ *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \
+ \
+ A = &WALK[PT1 ^ 4]; \
+ B = &WALK[PT2 ^ 1]; \
+ \
+ PTEST = PT2 >> 1; \
+ \
+ PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \
+ PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \
+ PTY = (PT2 >> 10) & 7; \
+ \
+ TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
+ TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
+ TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
+ \
+ TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
+ TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
+ TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
+ \
+ C = &WALK[PT1 ^ 5]; \
+ D = &WALK[PT2 ^ 5]; \
+ \
+ RES[i++] ^= *A; \
+ RES[i++] ^= *B; \
+ RES[i++] ^= *C; \
+ RES[i++] ^= *D; \
+ \
+ IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \
+ *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \
+ *B = IN ^ U2; \
+ *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \
+ *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \
+ \
+ A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \
+ B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \
+ C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \
+ D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \
+ \
+ IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \
+ *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \
+ *B = IN; \
+ *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \
+ *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \
+ \
+ PT1 = ( RES[(i - 8) ^ PTX] ^ \
+ WALK[PT1 ^ PTX ^ 7] ) & (~1); \
+ PT1 ^= (PT2 ^ 0x10) & 0x10; \
+ \
+ for( n++, i = 0; i < 16; i++ ) \
+ hs->pool[n % COLLECT_SIZE] ^= RES[i];
+
+/*
+ * Entropy gathering function
+ */
+static void havege_fill( havege_state *hs )
+{
+ int i, n = 0;
+ int U1, U2, *A, *B, *C, *D;
+ int PT1, PT2, *WALK, RES[16];
+ int PTX, PTY, CLK, PTEST, IN;
+
+ WALK = hs->WALK;
+ PT1 = hs->PT1;
+ PT2 = hs->PT2;
+
+ PTX = U1 = 0;
+ PTY = U2 = 0;
+
+ memset( RES, 0, sizeof( RES ) );
+
+ while( n < COLLECT_SIZE * 4 )
+ {
+ ONE_ITERATION
+ ONE_ITERATION
+ ONE_ITERATION
+ ONE_ITERATION
+ }
+
+ hs->PT1 = PT1;
+ hs->PT2 = PT2;
+
+ hs->offset[0] = 0;
+ hs->offset[1] = COLLECT_SIZE / 2;
+}
+
+/*
+ * HAVEGE initialization
+ */
+void havege_init( havege_state *hs )
+{
+ memset( hs, 0, sizeof( havege_state ) );
+
+ havege_fill( hs );
+}
+
+/*
+ * HAVEGE rand function
+ */
+int havege_rand( void *p_rng )
+{
+ int ret;
+ havege_state *hs = (havege_state *) p_rng;
+
+ if( hs->offset[1] >= COLLECT_SIZE )
+ havege_fill( hs );
+
+ ret = hs->pool[hs->offset[0]++];
+ ret ^= hs->pool[hs->offset[1]++];
+
+ return( ret );
+}
+
+#if defined(POLARSSL_RAND_TEST)
+
+#include <stdio.h>
+
+int main( int argc, char *argv[] )
+{
+ FILE *f;
+ time_t t;
+ int i, j, k;
+ havege_state hs;
+ unsigned char buf[1024];
+
+ if( argc < 2 )
+ {
+ fprintf( stderr, "usage: %s <output filename>\n", argv[0] );
+ return( 1 );
+ }
+
+ if( ( f = fopen( argv[1], "wb+" ) ) == NULL )
+ {
+ printf( "failed to open '%s' for writing.\n", argv[0] );
+ return( 1 );
+ }
+
+ havege_init( &hs );
+
+ t = time( NULL );
+
+ for( i = 0, k = 32768; i < k; i++ )
+ {
+ for( j = 0; j < sizeof( buf ); j++ )
+ buf[j] = havege_rand( &hs );
+
+ fwrite( buf, sizeof( buf ), 1, f );
+
+ printf( "Generating 32Mb of data in file '%s'... %04.1f" \
+ "%% done\r", argv[1], (100 * (float) (i + 1)) / k );
+ fflush( stdout );
+ }
+
+ if( t == time( NULL ) )
+ t--;
+
+ fclose( f );
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/package/px5g/src/library/rsa.c b/package/px5g/src/library/rsa.c
new file mode 100644
index 000000000..131b6c6c9
--- /dev/null
+++ b/package/px5g/src/library/rsa.c
@@ -0,0 +1,750 @@
+/*
+ * The RSA public-key cryptosystem
+ *
+ * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
+ *
+ * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the names of PolarSSL or XySSL 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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.
+ */
+/*
+ * RSA was designed by Ron Rivest, Adi Shamir and Len Adleman.
+ *
+ * http://theory.lcs.mit.edu/~rivest/rsapaper.pdf
+ * http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_RSA_C)
+
+#include "polarssl/rsa.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+/*
+ * Initialize an RSA context
+ */
+void rsa_init( rsa_context *ctx,
+ int padding,
+ int hash_id,
+ int (*f_rng)(void *),
+ void *p_rng )
+{
+ memset( ctx, 0, sizeof( rsa_context ) );
+
+ ctx->padding = padding;
+ ctx->hash_id = hash_id;
+
+ ctx->f_rng = f_rng;
+ ctx->p_rng = p_rng;
+}
+
+#if defined(POLARSSL_GENPRIME)
+
+/*
+ * Generate an RSA keypair
+ */
+int rsa_gen_key( rsa_context *ctx, int nbits, int exponent )
+{
+ int ret;
+ mpi P1, Q1, H, G;
+
+ if( ctx->f_rng == NULL || nbits < 128 || exponent < 3 )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ mpi_init( &P1, &Q1, &H, &G, NULL );
+
+ /*
+ * find primes P and Q with Q < P so that:
+ * GCD( E, (P-1)*(Q-1) ) == 1
+ */
+ MPI_CHK( mpi_lset( &ctx->E, exponent ) );
+
+ do
+ {
+ MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0,
+ ctx->f_rng, ctx->p_rng ) );
+
+ MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0,
+ ctx->f_rng, ctx->p_rng ) );
+
+ if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 )
+ mpi_swap( &ctx->P, &ctx->Q );
+
+ if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 )
+ continue;
+
+ MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) );
+ if( mpi_msb( &ctx->N ) != nbits )
+ continue;
+
+ MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
+ MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
+ MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
+ MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) );
+ }
+ while( mpi_cmp_int( &G, 1 ) != 0 );
+
+ /*
+ * D = E^-1 mod ((P-1)*(Q-1))
+ * DP = D mod (P - 1)
+ * DQ = D mod (Q - 1)
+ * QP = Q^-1 mod P
+ */
+ MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) );
+ MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) );
+ MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) );
+ MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) );
+
+ ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3;
+
+cleanup:
+
+ mpi_free( &G, &H, &Q1, &P1, NULL );
+
+ if( ret != 0 )
+ {
+ rsa_free( ctx );
+ return( POLARSSL_ERR_RSA_KEY_GEN_FAILED | ret );
+ }
+
+ return( 0 );
+}
+
+#endif
+
+/*
+ * Check a public RSA key
+ */
+int rsa_check_pubkey( rsa_context *ctx )
+{
+ if( ( ctx->N.p[0] & 1 ) == 0 ||
+ ( ctx->E.p[0] & 1 ) == 0 )
+ return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+ if( mpi_msb( &ctx->N ) < 128 ||
+ mpi_msb( &ctx->N ) > 4096 )
+ return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+ if( mpi_msb( &ctx->E ) < 2 ||
+ mpi_msb( &ctx->E ) > 64 )
+ return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+ return( 0 );
+}
+
+/*
+ * Check a private RSA key
+ */
+int rsa_check_privkey( rsa_context *ctx )
+{
+ int ret;
+ mpi PQ, DE, P1, Q1, H, I, G;
+
+ if( ( ret = rsa_check_pubkey( ctx ) ) != 0 )
+ return( ret );
+
+ mpi_init( &PQ, &DE, &P1, &Q1, &H, &I, &G, NULL );
+
+ MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) );
+ MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) );
+ MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
+ MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
+ MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
+ MPI_CHK( mpi_mod_mpi( &I, &DE, &H ) );
+ MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) );
+
+ if( mpi_cmp_mpi( &PQ, &ctx->N ) == 0 &&
+ mpi_cmp_int( &I, 1 ) == 0 &&
+ mpi_cmp_int( &G, 1 ) == 0 )
+ {
+ mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, NULL );
+ return( 0 );
+ }
+
+cleanup:
+
+ mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, NULL );
+ return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED | ret );
+}
+
+/*
+ * Do an RSA public key operation
+ */
+int rsa_public( rsa_context *ctx,
+ unsigned char *input,
+ unsigned char *output )
+{
+ int ret, olen;
+ mpi T;
+
+ mpi_init( &T, NULL );
+
+ MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
+
+ if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
+ {
+ mpi_free( &T, NULL );
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ olen = ctx->len;
+ MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) );
+ MPI_CHK( mpi_write_binary( &T, output, olen ) );
+
+cleanup:
+
+ mpi_free( &T, NULL );
+
+ if( ret != 0 )
+ return( POLARSSL_ERR_RSA_PUBLIC_FAILED | ret );
+
+ return( 0 );
+}
+
+/*
+ * Do an RSA private key operation
+ */
+int rsa_private( rsa_context *ctx,
+ unsigned char *input,
+ unsigned char *output )
+{
+ int ret, olen;
+ mpi T, T1, T2;
+
+ mpi_init( &T, &T1, &T2, NULL );
+
+ MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
+
+ if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
+ {
+ mpi_free( &T, NULL );
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+#if 0
+ MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) );
+#else
+ /*
+ * faster decryption using the CRT
+ *
+ * T1 = input ^ dP mod P
+ * T2 = input ^ dQ mod Q
+ */
+ MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) );
+ MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) );
+
+ /*
+ * T = (T1 - T2) * (Q^-1 mod P) mod P
+ */
+ MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) );
+ MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) );
+ MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) );
+
+ /*
+ * output = T2 + T * Q
+ */
+ MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) );
+ MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) );
+#endif
+
+ olen = ctx->len;
+ MPI_CHK( mpi_write_binary( &T, output, olen ) );
+
+cleanup:
+
+ mpi_free( &T, &T1, &T2, NULL );
+
+ if( ret != 0 )
+ return( POLARSSL_ERR_RSA_PRIVATE_FAILED | ret );
+
+ return( 0 );
+}
+
+/*
+ * Add the message padding, then do an RSA operation
+ */
+int rsa_pkcs1_encrypt( rsa_context *ctx,
+ int mode, int ilen,
+ unsigned char *input,
+ unsigned char *output )
+{
+ int nb_pad, olen;
+ unsigned char *p = output;
+
+ olen = ctx->len;
+
+ switch( ctx->padding )
+ {
+ case RSA_PKCS_V15:
+
+ if( ilen < 0 || olen < ilen + 11 )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ nb_pad = olen - 3 - ilen;
+
+ *p++ = 0;
+ *p++ = RSA_CRYPT;
+
+ while( nb_pad-- > 0 )
+ {
+ do {
+ *p = (unsigned char) rand();
+ } while( *p == 0 );
+ p++;
+ }
+ *p++ = 0;
+ memcpy( p, input, ilen );
+ break;
+
+ default:
+
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ }
+
+ return( ( mode == RSA_PUBLIC )
+ ? rsa_public( ctx, output, output )
+ : rsa_private( ctx, output, output ) );
+}
+
+/*
+ * Do an RSA operation, then remove the message padding
+ */
+int rsa_pkcs1_decrypt( rsa_context *ctx,
+ int mode, int *olen,
+ unsigned char *input,
+ unsigned char *output,
+ int output_max_len)
+{
+ int ret, ilen;
+ unsigned char *p;
+ unsigned char buf[512];
+
+ ilen = ctx->len;
+
+ if( ilen < 16 || ilen > (int) sizeof( buf ) )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ ret = ( mode == RSA_PUBLIC )
+ ? rsa_public( ctx, input, buf )
+ : rsa_private( ctx, input, buf );
+
+ if( ret != 0 )
+ return( ret );
+
+ p = buf;
+
+ switch( ctx->padding )
+ {
+ case RSA_PKCS_V15:
+
+ if( *p++ != 0 || *p++ != RSA_CRYPT )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+ while( *p != 0 )
+ {
+ if( p >= buf + ilen - 1 )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ p++;
+ }
+ p++;
+ break;
+
+ default:
+
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ }
+
+ if (ilen - (int)(p - buf) > output_max_len)
+ return( POLARSSL_ERR_RSA_OUTPUT_TO_LARGE );
+
+ *olen = ilen - (int)(p - buf);
+ memcpy( output, p, *olen );
+
+ return( 0 );
+}
+
+/*
+ * Do an RSA operation to sign the message digest
+ */
+int rsa_pkcs1_sign( rsa_context *ctx,
+ int mode,
+ int hash_id,
+ int hashlen,
+ unsigned char *hash,
+ unsigned char *sig )
+{
+ int nb_pad, olen;
+ unsigned char *p = sig;
+
+ olen = ctx->len;
+
+ switch( ctx->padding )
+ {
+ case RSA_PKCS_V15:
+
+ switch( hash_id )
+ {
+ case RSA_RAW:
+ nb_pad = olen - 3 - hashlen;
+ break;
+
+ case RSA_MD2:
+ case RSA_MD4:
+ case RSA_MD5:
+ nb_pad = olen - 3 - 34;
+ break;
+
+ case RSA_SHA1:
+ nb_pad = olen - 3 - 35;
+ break;
+
+ default:
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ if( nb_pad < 8 )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ *p++ = 0;
+ *p++ = RSA_SIGN;
+ memset( p, 0xFF, nb_pad );
+ p += nb_pad;
+ *p++ = 0;
+ break;
+
+ default:
+
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ }
+
+ switch( hash_id )
+ {
+ case RSA_RAW:
+ memcpy( p, hash, hashlen );
+ break;
+
+ case RSA_MD2:
+ memcpy( p, ASN1_HASH_MDX, 18 );
+ memcpy( p + 18, hash, 16 );
+ p[13] = 2; break;
+
+ case RSA_MD4:
+ memcpy( p, ASN1_HASH_MDX, 18 );
+ memcpy( p + 18, hash, 16 );
+ p[13] = 4; break;
+
+ case RSA_MD5:
+ memcpy( p, ASN1_HASH_MDX, 18 );
+ memcpy( p + 18, hash, 16 );
+ p[13] = 5; break;
+
+ case RSA_SHA1:
+ memcpy( p, ASN1_HASH_SHA1, 15 );
+ memcpy( p + 15, hash, 20 );
+ break;
+
+ default:
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ return( ( mode == RSA_PUBLIC )
+ ? rsa_public( ctx, sig, sig )
+ : rsa_private( ctx, sig, sig ) );
+}
+
+/*
+ * Do an RSA operation and check the message digest
+ */
+int rsa_pkcs1_verify( rsa_context *ctx,
+ int mode,
+ int hash_id,
+ int hashlen,
+ unsigned char *hash,
+ unsigned char *sig )
+{
+ int ret, len, siglen;
+ unsigned char *p, c;
+ unsigned char buf[512];
+
+ siglen = ctx->len;
+
+ if( siglen < 16 || siglen > (int) sizeof( buf ) )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ ret = ( mode == RSA_PUBLIC )
+ ? rsa_public( ctx, sig, buf )
+ : rsa_private( ctx, sig, buf );
+
+ if( ret != 0 )
+ return( ret );
+
+ p = buf;
+
+ switch( ctx->padding )
+ {
+ case RSA_PKCS_V15:
+
+ if( *p++ != 0 || *p++ != RSA_SIGN )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+ while( *p != 0 )
+ {
+ if( p >= buf + siglen - 1 || *p != 0xFF )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ p++;
+ }
+ p++;
+ break;
+
+ default:
+
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ }
+
+ len = siglen - (int)( p - buf );
+
+ if( len == 34 )
+ {
+ c = p[13];
+ p[13] = 0;
+
+ if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 )
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+ if( ( c == 2 && hash_id == RSA_MD2 ) ||
+ ( c == 4 && hash_id == RSA_MD4 ) ||
+ ( c == 5 && hash_id == RSA_MD5 ) )
+ {
+ if( memcmp( p + 18, hash, 16 ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+ }
+ }
+
+ if( len == 35 && hash_id == RSA_SHA1 )
+ {
+ if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 &&
+ memcmp( p + 15, hash, 20 ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+ }
+
+ if( len == hashlen && hash_id == RSA_RAW )
+ {
+ if( memcmp( p, hash, hashlen ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+ }
+
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+}
+
+/*
+ * Free the components of an RSA key
+ */
+void rsa_free( rsa_context *ctx )
+{
+ mpi_free( &ctx->RQ, &ctx->RP, &ctx->RN,
+ &ctx->QP, &ctx->DQ, &ctx->DP,
+ &ctx->Q, &ctx->P, &ctx->D,
+ &ctx->E, &ctx->N, NULL );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include "polarssl/sha1.h"
+
+/*
+ * Example RSA-1024 keypair, for test purposes
+ */
+#define KEY_LEN 128
+
+#define RSA_N "9292758453063D803DD603D5E777D788" \
+ "8ED1D5BF35786190FA2F23EBC0848AEA" \
+ "DDA92CA6C3D80B32C4D109BE0F36D6AE" \
+ "7130B9CED7ACDF54CFC7555AC14EEBAB" \
+ "93A89813FBF3C4F8066D2D800F7C38A8" \
+ "1AE31942917403FF4946B0A83D3D3E05" \
+ "EE57C6F5F5606FB5D4BC6CD34EE0801A" \
+ "5E94BB77B07507233A0BC7BAC8F90F79"
+
+#define RSA_E "10001"
+
+#define RSA_D "24BF6185468786FDD303083D25E64EFC" \
+ "66CA472BC44D253102F8B4A9D3BFA750" \
+ "91386C0077937FE33FA3252D28855837" \
+ "AE1B484A8A9A45F7EE8C0C634F99E8CD" \
+ "DF79C5CE07EE72C7F123142198164234" \
+ "CABB724CF78B8173B9F880FC86322407" \
+ "AF1FEDFDDE2BEB674CA15F3E81A1521E" \
+ "071513A1E85B5DFA031F21ECAE91A34D"
+
+#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
+ "2C01CAD19EA484A87EA4377637E75500" \
+ "FCB2005C5C7DD6EC4AC023CDA285D796" \
+ "C3D9E75E1EFC42488BB4F1D13AC30A57"
+
+#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \
+ "E211C2B9E5DB1ED0BF61D0D9899620F4" \
+ "910E4168387E3C30AA1E00C339A79508" \
+ "8452DD96A9A5EA5D9DCA68DA636032AF"
+
+#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \
+ "3C94D22288ACD763FD8E5600ED4A702D" \
+ "F84198A5F06C2E72236AE490C93F07F8" \
+ "3CC559CD27BC2D1CA488811730BB5725"
+
+#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \
+ "D8AAEA56749EA28623272E4F7D0592AF" \
+ "7C1F1313CAC9471B5C523BFE592F517B" \
+ "407A1BD76C164B93DA2D32A383E58357"
+
+#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \
+ "F38D18D2B2F0E2DD275AA977E2BF4411" \
+ "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
+ "A74206CEC169D74BF5A8C50D6F48EA08"
+
+#define PT_LEN 24
+#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
+ "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"
+
+/*
+ * Checkup routine
+ */
+int rsa_self_test( int verbose )
+{
+ int len;
+ rsa_context rsa;
+ unsigned char sha1sum[20];
+ unsigned char rsa_plaintext[PT_LEN];
+ unsigned char rsa_decrypted[PT_LEN];
+ unsigned char rsa_ciphertext[KEY_LEN];
+
+ memset( &rsa, 0, sizeof( rsa_context ) );
+
+ rsa.len = KEY_LEN;
+ mpi_read_string( &rsa.N , 16, RSA_N );
+ mpi_read_string( &rsa.E , 16, RSA_E );
+ mpi_read_string( &rsa.D , 16, RSA_D );
+ mpi_read_string( &rsa.P , 16, RSA_P );
+ mpi_read_string( &rsa.Q , 16, RSA_Q );
+ mpi_read_string( &rsa.DP, 16, RSA_DP );
+ mpi_read_string( &rsa.DQ, 16, RSA_DQ );
+ mpi_read_string( &rsa.QP, 16, RSA_QP );
+
+ if( verbose != 0 )
+ printf( " RSA key validation: " );
+
+ if( rsa_check_pubkey( &rsa ) != 0 ||
+ rsa_check_privkey( &rsa ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n PKCS#1 encryption : " );
+
+ memcpy( rsa_plaintext, RSA_PT, PT_LEN );
+
+ if( rsa_pkcs1_encrypt( &rsa, RSA_PUBLIC, PT_LEN,
+ rsa_plaintext, rsa_ciphertext ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n PKCS#1 decryption : " );
+
+ if( rsa_pkcs1_decrypt( &rsa, RSA_PRIVATE, &len,
+ rsa_ciphertext, rsa_decrypted,
+ sizeof(rsa_decrypted) ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n PKCS#1 data sign : " );
+
+ sha1( rsa_plaintext, PT_LEN, sha1sum );
+
+ if( rsa_pkcs1_sign( &rsa, RSA_PRIVATE, RSA_SHA1, 20,
+ sha1sum, rsa_ciphertext ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n PKCS#1 sig. verify: " );
+
+ if( rsa_pkcs1_verify( &rsa, RSA_PUBLIC, RSA_SHA1, 20,
+ sha1sum, rsa_ciphertext ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n\n" );
+
+ rsa_free( &rsa );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/package/px5g/src/library/sha1.c b/package/px5g/src/library/sha1.c
new file mode 100644
index 000000000..54a4416f3
--- /dev/null
+++ b/package/px5g/src/library/sha1.c
@@ -0,0 +1,622 @@
+/*
+ * FIPS-180-1 compliant SHA-1 implementation
+ *
+ * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
+ *
+ * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the names of PolarSSL or XySSL 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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.
+ */
+/*
+ * The SHA-1 standard was published by NIST in 1993.
+ *
+ * http://www.itl.nist.gov/fipspubs/fip180-1.htm
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_SHA1_C)
+
+#include "polarssl/sha1.h"
+
+#include <string.h>
+#include <stdio.h>
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_ULONG_BE
+#define GET_ULONG_BE(n,b,i) \
+{ \
+ (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
+ | ( (unsigned long) (b)[(i) + 1] << 16 ) \
+ | ( (unsigned long) (b)[(i) + 2] << 8 ) \
+ | ( (unsigned long) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_ULONG_BE
+#define PUT_ULONG_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+/*
+ * SHA-1 context setup
+ */
+void sha1_starts( sha1_context *ctx )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+ ctx->state[4] = 0xC3D2E1F0;
+}
+
+static void sha1_process( sha1_context *ctx, unsigned char data[64] )
+{
+ unsigned long temp, W[16], A, B, C, D, E;
+
+ GET_ULONG_BE( W[ 0], data, 0 );
+ GET_ULONG_BE( W[ 1], data, 4 );
+ GET_ULONG_BE( W[ 2], data, 8 );
+ GET_ULONG_BE( W[ 3], data, 12 );
+ GET_ULONG_BE( W[ 4], data, 16 );
+ GET_ULONG_BE( W[ 5], data, 20 );
+ GET_ULONG_BE( W[ 6], data, 24 );
+ GET_ULONG_BE( W[ 7], data, 28 );
+ GET_ULONG_BE( W[ 8], data, 32 );
+ GET_ULONG_BE( W[ 9], data, 36 );
+ GET_ULONG_BE( W[10], data, 40 );
+ GET_ULONG_BE( W[11], data, 44 );
+ GET_ULONG_BE( W[12], data, 48 );
+ GET_ULONG_BE( W[13], data, 52 );
+ GET_ULONG_BE( W[14], data, 56 );
+ GET_ULONG_BE( W[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define R(t) \
+( \
+ temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
+ W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \
+ ( W[t & 0x0F] = S(temp,1) ) \
+)
+
+#define P(a,b,c,d,e,x) \
+{ \
+ e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
+}
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define K 0x5A827999
+
+ P( A, B, C, D, E, W[0] );
+ P( E, A, B, C, D, W[1] );
+ P( D, E, A, B, C, W[2] );
+ P( C, D, E, A, B, W[3] );
+ P( B, C, D, E, A, W[4] );
+ P( A, B, C, D, E, W[5] );
+ P( E, A, B, C, D, W[6] );
+ P( D, E, A, B, C, W[7] );
+ P( C, D, E, A, B, W[8] );
+ P( B, C, D, E, A, W[9] );
+ P( A, B, C, D, E, W[10] );
+ P( E, A, B, C, D, W[11] );
+ P( D, E, A, B, C, W[12] );
+ P( C, D, E, A, B, W[13] );
+ P( B, C, D, E, A, W[14] );
+ P( A, B, C, D, E, W[15] );
+ P( E, A, B, C, D, R(16) );
+ P( D, E, A, B, C, R(17) );
+ P( C, D, E, A, B, R(18) );
+ P( B, C, D, E, A, R(19) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0x6ED9EBA1
+
+ P( A, B, C, D, E, R(20) );
+ P( E, A, B, C, D, R(21) );
+ P( D, E, A, B, C, R(22) );
+ P( C, D, E, A, B, R(23) );
+ P( B, C, D, E, A, R(24) );
+ P( A, B, C, D, E, R(25) );
+ P( E, A, B, C, D, R(26) );
+ P( D, E, A, B, C, R(27) );
+ P( C, D, E, A, B, R(28) );
+ P( B, C, D, E, A, R(29) );
+ P( A, B, C, D, E, R(30) );
+ P( E, A, B, C, D, R(31) );
+ P( D, E, A, B, C, R(32) );
+ P( C, D, E, A, B, R(33) );
+ P( B, C, D, E, A, R(34) );
+ P( A, B, C, D, E, R(35) );
+ P( E, A, B, C, D, R(36) );
+ P( D, E, A, B, C, R(37) );
+ P( C, D, E, A, B, R(38) );
+ P( B, C, D, E, A, R(39) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) ((x & y) | (z & (x | y)))
+#define K 0x8F1BBCDC
+
+ P( A, B, C, D, E, R(40) );
+ P( E, A, B, C, D, R(41) );
+ P( D, E, A, B, C, R(42) );
+ P( C, D, E, A, B, R(43) );
+ P( B, C, D, E, A, R(44) );
+ P( A, B, C, D, E, R(45) );
+ P( E, A, B, C, D, R(46) );
+ P( D, E, A, B, C, R(47) );
+ P( C, D, E, A, B, R(48) );
+ P( B, C, D, E, A, R(49) );
+ P( A, B, C, D, E, R(50) );
+ P( E, A, B, C, D, R(51) );
+ P( D, E, A, B, C, R(52) );
+ P( C, D, E, A, B, R(53) );
+ P( B, C, D, E, A, R(54) );
+ P( A, B, C, D, E, R(55) );
+ P( E, A, B, C, D, R(56) );
+ P( D, E, A, B, C, R(57) );
+ P( C, D, E, A, B, R(58) );
+ P( B, C, D, E, A, R(59) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0xCA62C1D6
+
+ P( A, B, C, D, E, R(60) );
+ P( E, A, B, C, D, R(61) );
+ P( D, E, A, B, C, R(62) );
+ P( C, D, E, A, B, R(63) );
+ P( B, C, D, E, A, R(64) );
+ P( A, B, C, D, E, R(65) );
+ P( E, A, B, C, D, R(66) );
+ P( D, E, A, B, C, R(67) );
+ P( C, D, E, A, B, R(68) );
+ P( B, C, D, E, A, R(69) );
+ P( A, B, C, D, E, R(70) );
+ P( E, A, B, C, D, R(71) );
+ P( D, E, A, B, C, R(72) );
+ P( C, D, E, A, B, R(73) );
+ P( B, C, D, E, A, R(74) );
+ P( A, B, C, D, E, R(75) );
+ P( E, A, B, C, D, R(76) );
+ P( D, E, A, B, C, R(77) );
+ P( C, D, E, A, B, R(78) );
+ P( B, C, D, E, A, R(79) );
+
+#undef K
+#undef F
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+}
+
+/*
+ * SHA-1 process buffer
+ */
+void sha1_update( sha1_context *ctx, unsigned char *input, int ilen )
+{
+ int fill;
+ unsigned long left;
+
+ if( ilen <= 0 )
+ return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < (unsigned long) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left),
+ (void *) input, fill );
+ sha1_process( ctx, ctx->buffer );
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 64 )
+ {
+ sha1_process( ctx, input );
+ input += 64;
+ ilen -= 64;
+ }
+
+ if( ilen > 0 )
+ {
+ memcpy( (void *) (ctx->buffer + left),
+ (void *) input, ilen );
+ }
+}
+
+static const unsigned char sha1_padding[64] =
+{
+ 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
+};
+
+/*
+ * SHA-1 final digest
+ */
+void sha1_finish( sha1_context *ctx, unsigned char output[20] )
+{
+ unsigned long last, padn;
+ unsigned long high, low;
+ unsigned char msglen[8];
+
+ high = ( ctx->total[0] >> 29 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_ULONG_BE( high, msglen, 0 );
+ PUT_ULONG_BE( low, msglen, 4 );
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ sha1_update( ctx, (unsigned char *) sha1_padding, padn );
+ sha1_update( ctx, msglen, 8 );
+
+ PUT_ULONG_BE( ctx->state[0], output, 0 );
+ PUT_ULONG_BE( ctx->state[1], output, 4 );
+ PUT_ULONG_BE( ctx->state[2], output, 8 );
+ PUT_ULONG_BE( ctx->state[3], output, 12 );
+ PUT_ULONG_BE( ctx->state[4], output, 16 );
+}
+
+/*
+ * output = SHA-1( input buffer )
+ */
+void sha1( unsigned char *input, int ilen, unsigned char output[20] )
+{
+ sha1_context ctx;
+
+ sha1_starts( &ctx );
+ sha1_update( &ctx, input, ilen );
+ sha1_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha1_context ) );
+}
+
+/*
+ * output = SHA-1( file contents )
+ */
+int sha1_file( char *path, unsigned char output[20] )
+{
+ FILE *f;
+ size_t n;
+ sha1_context ctx;
+ unsigned char buf[1024];
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( 1 );
+
+ sha1_starts( &ctx );
+
+ while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+ sha1_update( &ctx, buf, (int) n );
+
+ sha1_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha1_context ) );
+
+ if( ferror( f ) != 0 )
+ {
+ fclose( f );
+ return( 2 );
+ }
+
+ fclose( f );
+ return( 0 );
+}
+
+/*
+ * SHA-1 HMAC context setup
+ */
+void sha1_hmac_starts( sha1_context *ctx, unsigned char *key, int keylen )
+{
+ int i;
+ unsigned char sum[20];
+
+ if( keylen > 64 )
+ {
+ sha1( key, keylen, sum );
+ keylen = 20;
+ key = sum;
+ }
+
+ memset( ctx->ipad, 0x36, 64 );
+ memset( ctx->opad, 0x5C, 64 );
+
+ for( i = 0; i < keylen; i++ )
+ {
+ ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+ ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+ }
+
+ sha1_starts( ctx );
+ sha1_update( ctx, ctx->ipad, 64 );
+
+ memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * SHA-1 HMAC process buffer
+ */
+void sha1_hmac_update( sha1_context *ctx, unsigned char *input, int ilen )
+{
+ sha1_update( ctx, input, ilen );
+}
+
+/*
+ * SHA-1 HMAC final digest
+ */
+void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] )
+{
+ unsigned char tmpbuf[20];
+
+ sha1_finish( ctx, tmpbuf );
+ sha1_starts( ctx );
+ sha1_update( ctx, ctx->opad, 64 );
+ sha1_update( ctx, tmpbuf, 20 );
+ sha1_finish( ctx, output );
+
+ memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * output = HMAC-SHA-1( hmac key, input buffer )
+ */
+void sha1_hmac( unsigned char *key, int keylen,
+ unsigned char *input, int ilen,
+ unsigned char output[20] )
+{
+ sha1_context ctx;
+
+ sha1_hmac_starts( &ctx, key, keylen );
+ sha1_hmac_update( &ctx, input, ilen );
+ sha1_hmac_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha1_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * FIPS-180-1 test vectors
+ */
+static unsigned char sha1_test_buf[3][57] =
+{
+ { "abc" },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
+ { "" }
+};
+
+static const int sha1_test_buflen[3] =
+{
+ 3, 56, 1000
+};
+
+static const unsigned char sha1_test_sum[3][20] =
+{
+ { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
+ 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },
+ { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
+ 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },
+ { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
+ 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
+};
+
+/*
+ * RFC 2202 test vectors
+ */
+static unsigned char sha1_hmac_test_key[7][26] =
+{
+ { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
+ "\x0B\x0B\x0B\x0B" },
+ { "Jefe" },
+ { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA" },
+ { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+ "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
+ { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
+ "\x0C\x0C\x0C\x0C" },
+ { "" }, /* 0xAA 80 times */
+ { "" }
+};
+
+static const int sha1_hmac_test_keylen[7] =
+{
+ 20, 4, 20, 25, 20, 80, 80
+};
+
+static unsigned char sha1_hmac_test_buf[7][74] =
+{
+ { "Hi There" },
+ { "what do ya want for nothing?" },
+ { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
+ { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
+ { "Test With Truncation" },
+ { "Test Using Larger Than Block-Size Key - Hash Key First" },
+ { "Test Using Larger Than Block-Size Key and Larger"
+ " Than One Block-Size Data" }
+};
+
+static const int sha1_hmac_test_buflen[7] =
+{
+ 8, 28, 50, 50, 20, 54, 73
+};
+
+static const unsigned char sha1_hmac_test_sum[7][20] =
+{
+ { 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B,
+ 0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00 },
+ { 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74,
+ 0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79 },
+ { 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3,
+ 0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3 },
+ { 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84,
+ 0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA },
+ { 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2,
+ 0x7B, 0xE1 },
+ { 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70,
+ 0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12 },
+ { 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B,
+ 0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91 }
+};
+
+/*
+ * Checkup routine
+ */
+int sha1_self_test( int verbose )
+{
+ int i, j, buflen;
+ unsigned char buf[1024];
+ unsigned char sha1sum[20];
+ sha1_context ctx;
+
+ /*
+ * SHA-1
+ */
+ for( i = 0; i < 3; i++ )
+ {
+ if( verbose != 0 )
+ printf( " SHA-1 test #%d: ", i + 1 );
+
+ sha1_starts( &ctx );
+
+ if( i == 2 )
+ {
+ memset( buf, 'a', buflen = 1000 );
+
+ for( j = 0; j < 1000; j++ )
+ sha1_update( &ctx, buf, buflen );
+ }
+ else
+ sha1_update( &ctx, sha1_test_buf[i],
+ sha1_test_buflen[i] );
+
+ sha1_finish( &ctx, sha1sum );
+
+ if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ for( i = 0; i < 7; i++ )
+ {
+ if( verbose != 0 )
+ printf( " HMAC-SHA-1 test #%d: ", i + 1 );
+
+ if( i == 5 || i == 6 )
+ {
+ memset( buf, '\xAA', buflen = 80 );
+ sha1_hmac_starts( &ctx, buf, buflen );
+ }
+ else
+ sha1_hmac_starts( &ctx, sha1_hmac_test_key[i],
+ sha1_hmac_test_keylen[i] );
+
+ sha1_hmac_update( &ctx, sha1_hmac_test_buf[i],
+ sha1_hmac_test_buflen[i] );
+
+ sha1_hmac_finish( &ctx, sha1sum );
+
+ buflen = ( i == 4 ) ? 12 : 20;
+
+ if( memcmp( sha1sum, sha1_hmac_test_sum[i], buflen ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/package/px5g/src/library/timing.c b/package/px5g/src/library/timing.c
new file mode 100644
index 000000000..6b7ab740e
--- /dev/null
+++ b/package/px5g/src/library/timing.c
@@ -0,0 +1,265 @@
+/*
+ * Portable interface to the CPU cycle counter
+ *
+ * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
+ *
+ * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the names of PolarSSL or XySSL 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_TIMING_C)
+
+#include "polarssl/timing.h"
+
+#if defined(WIN32)
+
+#include <windows.h>
+#include <winbase.h>
+
+struct _hr_time
+{
+ LARGE_INTEGER start;
+};
+
+#else
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <time.h>
+
+struct _hr_time
+{
+ struct timeval start;
+};
+
+#endif
+
+#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
+
+unsigned long hardclock( void )
+{
+ unsigned long tsc;
+ __asm rdtsc
+ __asm mov [tsc], eax
+ return( tsc );
+}
+
+#else
+#if defined(__GNUC__) && defined(__i386__)
+
+unsigned long hardclock( void )
+{
+ unsigned long tsc;
+ asm( "rdtsc" : "=a" (tsc) );
+ return( tsc );
+}
+
+#else
+#if defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__))
+
+unsigned long hardclock( void )
+{
+ unsigned long lo, hi;
+ asm( "rdtsc" : "=a" (lo), "=d" (hi) );
+ return( lo | (hi << 32) );
+}
+
+#else
+#if defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
+
+unsigned long hardclock( void )
+{
+ unsigned long tbl, tbu0, tbu1;
+
+ do
+ {
+ asm( "mftbu %0" : "=r" (tbu0) );
+ asm( "mftb %0" : "=r" (tbl ) );
+ asm( "mftbu %0" : "=r" (tbu1) );
+ }
+ while( tbu0 != tbu1 );
+
+ return( tbl );
+}
+
+#else
+#if defined(__GNUC__) && defined(__sparc__)
+
+unsigned long hardclock( void )
+{
+ unsigned long tick;
+ asm( ".byte 0x83, 0x41, 0x00, 0x00" );
+ asm( "mov %%g1, %0" : "=r" (tick) );
+ return( tick );
+}
+
+#else
+#if defined(__GNUC__) && defined(__alpha__)
+
+unsigned long hardclock( void )
+{
+ unsigned long cc;
+ asm( "rpcc %0" : "=r" (cc) );
+ return( cc & 0xFFFFFFFF );
+}
+
+#else
+#if defined(__GNUC__) && defined(__ia64__)
+
+unsigned long hardclock( void )
+{
+ unsigned long itc;
+ asm( "mov %0 = ar.itc" : "=r" (itc) );
+ return( itc );
+}
+
+#else
+
+static int hardclock_init = 0;
+static struct timeval tv_init;
+
+unsigned long hardclock( void )
+{
+ struct timeval tv_cur;
+
+ if( hardclock_init == 0 )
+ {
+ gettimeofday( &tv_init, NULL );
+ hardclock_init = 1;
+ }
+
+ gettimeofday( &tv_cur, NULL );
+ return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000
+ + ( tv_cur.tv_usec - tv_init.tv_usec ) );
+}
+
+#endif /* generic */
+#endif /* IA-64 */
+#endif /* Alpha */
+#endif /* SPARC8 */
+#endif /* PowerPC */
+#endif /* AMD64 */
+#endif /* i586+ */
+
+int alarmed = 0;
+
+#if defined(WIN32)
+
+unsigned long get_timer( struct hr_time *val, int reset )
+{
+ unsigned long delta;
+ LARGE_INTEGER offset, hfreq;
+ struct _hr_time *t = (struct _hr_time *) val;
+
+ QueryPerformanceCounter( &offset );
+ QueryPerformanceFrequency( &hfreq );
+
+ delta = (unsigned long)( ( 1000 *
+ ( offset.QuadPart - t->start.QuadPart ) ) /
+ hfreq.QuadPart );
+
+ if( reset )
+ QueryPerformanceCounter( &t->start );
+
+ return( delta );
+}
+
+DWORD WINAPI TimerProc( LPVOID uElapse )
+{
+ Sleep( (DWORD) uElapse );
+ alarmed = 1;
+ return( TRUE );
+}
+
+void set_alarm( int seconds )
+{
+ DWORD ThreadId;
+
+ alarmed = 0;
+ CloseHandle( CreateThread( NULL, 0, TimerProc,
+ (LPVOID) ( seconds * 1000 ), 0, &ThreadId ) );
+}
+
+void m_sleep( int milliseconds )
+{
+ Sleep( milliseconds );
+}
+
+#else
+
+unsigned long get_timer( struct hr_time *val, int reset )
+{
+ unsigned long delta;
+ struct timeval offset;
+ struct _hr_time *t = (struct _hr_time *) val;
+
+ gettimeofday( &offset, NULL );
+
+ delta = ( offset.tv_sec - t->start.tv_sec ) * 1000
+ + ( offset.tv_usec - t->start.tv_usec ) / 1000;
+
+ if( reset )
+ {
+ t->start.tv_sec = offset.tv_sec;
+ t->start.tv_usec = offset.tv_usec;
+ }
+
+ return( delta );
+}
+
+static void sighandler( int signum )
+{
+ alarmed = 1;
+ signal( signum, sighandler );
+}
+
+void set_alarm( int seconds )
+{
+ alarmed = 0;
+ signal( SIGALRM, sighandler );
+ alarm( seconds );
+}
+
+void m_sleep( int milliseconds )
+{
+ struct timeval tv;
+
+ tv.tv_sec = milliseconds / 1000;
+ tv.tv_usec = milliseconds * 1000;
+
+ select( 0, NULL, NULL, NULL, &tv );
+}
+
+#endif
+
+#endif
diff --git a/package/px5g/src/library/x509write.c b/package/px5g/src/library/x509write.c
new file mode 100644
index 000000000..fabee20ea
--- /dev/null
+++ b/package/px5g/src/library/x509write.c
@@ -0,0 +1,1139 @@
+/*
+ * X.509 certificate and private key writing
+ *
+ * Copyright (C) 2006-2007 Pascal Vizeli <pvizeli@yahoo.de>
+ * Modifications (C) 2009 Steven Barth <steven@midlink.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License, version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+/*
+ * The ITU-T X.509 standard defines a certificat format for PKI.
+ *
+ * http://www.ietf.org/rfc/rfc2459.txt
+ * http://www.ietf.org/rfc/rfc3279.txt
+ *
+ * ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
+ *
+ * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
+ * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
+ *
+ * For CRS:
+ * http://www.faqs.org/rfcs/rfc2314.html
+ */
+#include "polarssl/config.h"
+#include "polarssl/x509.h"
+#include "polarssl/base64.h"
+#include "polarssl/sha1.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+
+#define and &&
+#define or ||
+
+#if defined _MSC_VER && !defined snprintf
+#define snprintf _snprintf
+#endif
+
+static int x509write_realloc_node(x509_node *node, size_t larger);
+static int x509write_file(x509_node *node, char *path, int format, const char* pem_prolog, const char* pem_epilog);
+
+/*
+ * evaluate how mani octet have this integer
+ */
+static int asn1_eval_octet(unsigned int digit)
+{
+ int i, byte;
+
+ for (byte = 4, i = 24; i >= 0; i -= 8, --byte)
+ if (((digit >> i) & 0xFF) != 0)
+ return byte;
+
+ return 0;
+}
+
+/*
+ * write the asn.1 lenght form into p
+ */
+static int asn1_add_len(unsigned int size, x509_node *node)
+{
+ if (size > 127) {
+
+ /* long size */
+ int byte = asn1_eval_octet(size);
+ int i = 0;
+
+ *(node->p) = (0x80 | byte) & 0xFF;
+ ++node->p;
+
+ for (i = byte; i > 0; --i) {
+
+ *(node->p) = (size >> ((i - 1) * 8)) & 0xFF;
+ ++node->p;
+ }
+
+ } else {
+
+ /* short size */
+ *(node->p) = size & 0xFF;
+ if (size != 0)
+ ++node->p;
+ }
+
+ return 0;
+}
+
+/*
+ * write a ans.1 object into p
+ */
+static int asn1_add_obj(unsigned char *value, unsigned int size, int tag,
+ x509_node *node)
+{
+ int tl = 2;
+
+ if (tag == ASN1_BIT_STRING)
+ ++tl;
+
+ if (size > 127)
+ x509write_realloc_node(node, (size_t) size + tl +
+ asn1_eval_octet(size));
+ else
+ x509write_realloc_node(node, (size_t) size + tl);
+
+ if (node->data == NULL)
+ return 1;
+
+ /* tag */
+ *(node->p) = tag & 0xFF;
+ ++node->p;
+
+ /* len */
+ if (tag == ASN1_BIT_STRING) {
+ asn1_add_len((unsigned int) size + 1, node);
+ *(node->p) = 0x00;
+ ++node->p;
+ } else {
+ asn1_add_len((unsigned int) size, node);
+ }
+
+ /* value */
+ if (size > 0) {
+
+ memcpy(node->p, value, (size_t) size);
+ if ((node->p += size -1) != node->end)
+ return POLARSSL_ERR_X509_POINT_ERROR;
+ } else {
+ /* make nothing -> NULL */
+ }
+
+ return 0;
+}
+
+/*
+ * write a asn.1 conform integer object
+ */
+static int asn1_add_int(signed int value, x509_node *node)
+{
+ signed int i = 0, neg = 1;
+ unsigned int byte, u_val = 0, tmp_val = 0;
+
+ /* if negate? */
+ if (value < 0) {
+ neg = -1;
+ u_val = ~value;
+ } else {
+ u_val = value;
+ }
+
+ byte = asn1_eval_octet(u_val);
+ /* 0 isn't NULL */
+ if (byte == 0)
+ byte = 1;
+
+ /* ASN.1 integer is signed! */
+ if (byte < 4 and ((u_val >> ((byte -1) * 8)) & 0xFF) == 0x80)
+ byte += 1;
+
+ if (x509write_realloc_node(node, (size_t) byte + 2) != 0)
+ return 1;
+
+ /* tag */
+ *(node->p) = ASN1_INTEGER;
+ ++node->p;
+
+ /* len */
+ asn1_add_len(byte, node);
+
+ /* value */
+ for (i = byte; i > 0; --i) {
+
+ tmp_val = (u_val >> ((i - 1) * 8)) & 0xFF;
+ if (neg == 1)
+ *(node->p) = tmp_val;
+ else
+ *(node->p) = ~tmp_val;
+
+ if (i > 1)
+ ++node->p;
+ }
+
+ if (node->p != node->end)
+ return POLARSSL_ERR_X509_POINT_ERROR;
+
+ return 0;
+}
+
+/*
+ * write a asn.1 conform mpi object
+ */
+static int asn1_add_mpi(mpi *value, int tag, x509_node *node)
+{
+ size_t size = (mpi_msb(value) / 8) + 1;
+ unsigned char *buf;
+ int buf_len = (int) size, tl = 2;
+
+ if (tag == ASN1_BIT_STRING)
+ ++tl;
+
+ if (size > 127)
+ x509write_realloc_node(node, size + (size_t) tl +
+ asn1_eval_octet((unsigned int)size));
+ else
+ x509write_realloc_node(node, size + (size_t) tl);
+
+ if (node->data == NULL)
+ return 1;
+
+ buf = (unsigned char*) malloc(size);
+ if (mpi_write_binary(value, buf, buf_len) != 0)
+ return POLARSSL_ERR_MPI_BUFFER_TOO_SMALL;
+
+ /* tag */
+ *(node->p) = tag & 0xFF;
+ ++node->p;
+
+ /* len */
+ if (tag == ASN1_BIT_STRING) {
+ asn1_add_len((unsigned int) size + 1, node);
+ *(node->p) = 0x00;
+ ++node->p;
+ } else {
+ asn1_add_len((unsigned int) size, node);
+ }
+
+ /* value */
+ memcpy(node->p, buf, size);
+ free(buf);
+
+ if ((node->p += (int) size -1) != node->end)
+ return POLARSSL_ERR_X509_POINT_ERROR;
+
+ return 0;
+}
+
+/*
+ * write a node into asn.1 conform object
+ */
+static int asn1_append_tag(x509_node *node, int tag)
+{
+ int tl = 2;
+
+ x509_node tmp;
+ x509write_init_node(&tmp);
+
+ if (tag == ASN1_BIT_STRING)
+ ++tl;
+
+ if (node->len > 127)
+ x509write_realloc_node(&tmp, node->len + (size_t) tl +
+ asn1_eval_octet((unsigned int)node->len));
+ else
+ x509write_realloc_node(&tmp, node->len + (size_t) tl);
+
+ if (tmp.data == NULL) {
+ x509write_free_node(&tmp);
+ return 1;
+ }
+
+ /* tag */
+ *(tmp.p) = tag & 0xFF;
+ ++tmp.p;
+
+ /* len */
+ if (tag == ASN1_BIT_STRING) {
+ asn1_add_len((unsigned int) node->len + 1, &tmp);
+ *(tmp.p) = 0x00;
+ ++tmp.p;
+ } else {
+ asn1_add_len((unsigned int) node->len, &tmp);
+ }
+
+ /* value */
+ memcpy(tmp.p, node->data, node->len);
+
+ /* good? */
+ if ((tmp.p += (int) node->len -1) != tmp.end) {
+ x509write_free_node(&tmp);
+ return POLARSSL_ERR_X509_POINT_ERROR;
+ }
+
+ free(node->data);
+ node->data = tmp.data;
+ node->p = tmp.p;
+ node->end = tmp.end;
+ node->len = tmp.len;
+
+ return 0;
+}
+
+/*
+ * write nodes into a asn.1 object
+ */
+static int asn1_append_nodes(x509_node *node, int tag, int anz, ...)
+{
+ va_list ap;
+ size_t size = 0;
+ x509_node *tmp;
+ int count;
+
+ va_start(ap, anz);
+ count = anz;
+
+ while (count--) {
+
+ tmp = va_arg(ap, x509_node*);
+ if (tmp->data != NULL)
+ size += tmp->len;
+ }
+
+ if ( size > 127) {
+ if (x509write_realloc_node(node, size + (size_t) 2 +
+ asn1_eval_octet(size)) != 0)
+ return 1;
+ } else {
+ if (x509write_realloc_node(node, size + (size_t) 2) != 0)
+ return 1;
+ }
+
+ /* tag */
+ *(node->p) = tag & 0xFF;
+ ++node->p;
+
+ /* len */
+ asn1_add_len(size, node);
+
+ /* value */
+ va_start(ap, anz);
+ count = anz;
+
+ while (count--) {
+
+ tmp = va_arg(ap, x509_node*);
+ if (tmp->data != NULL) {
+
+ memcpy(node->p, tmp->data, tmp->len);
+ if ((node->p += (int) tmp->len -1) != node->end)
+ ++node->p;
+ }
+ }
+
+ va_end(ap);
+ return 0;
+}
+
+/*
+ * write a ASN.1 conform object identifiere include a "tag"
+ */
+static int asn1_add_oid(x509_node *node, unsigned char *oid, size_t len,
+ int tag, int tag_val, unsigned char *value, size_t val_len)
+{
+ int ret;
+ x509_node tmp;
+
+ x509write_init_node(&tmp);
+
+ /* OBJECT IDENTIFIER */
+ if ((ret = asn1_add_obj(oid, len, ASN1_OID, &tmp)) != 0) {
+ x509write_free_node(&tmp);
+ return ret;
+ }
+
+ /* value */
+ if ((ret = asn1_add_obj(value, val_len, tag_val, &tmp)) != 0) {
+ x509write_free_node(&tmp);
+ return ret;
+ }
+
+ /* SET/SEQUENCE */
+ if ((ret = asn1_append_nodes(node, tag, 1, &tmp)) != 0) {
+ x509write_free_node(&tmp);
+ return ret;
+ }
+
+ x509write_free_node(&tmp);
+ return 0;
+}
+
+/*
+ * utcTime UTCTime
+ */
+static int asn1_add_date_utc(unsigned char *time, x509_node *node)
+{
+ unsigned char date[13], *sp;
+ x509_time xtime;
+ int ret;
+
+ sscanf((char*)time, "%d-%d-%d %d:%d:%d", &xtime.year, &xtime.mon,
+ &xtime.day, &xtime.hour, &xtime.min, &xtime.sec);
+
+ /* convert to YY */
+ if (xtime.year > 2000)
+ xtime.year -= 2000;
+ else
+ xtime.year -= 1900;
+
+ snprintf((char*)date, 13, "%2d%2d%2d%2d%2d%2d", xtime.year, xtime.mon, xtime.day,
+ xtime.hour, xtime.min, xtime.sec);
+
+ /* replace ' ' to '0' */
+ for (sp = date; *sp != '\0'; ++sp)
+ if (*sp == '\x20')
+ *sp = '\x30';
+
+ date[12] = 'Z';
+
+ if ((ret = asn1_add_obj(date, 13, ASN1_UTC_TIME, node)) != 0)
+ return ret;
+
+ return 0;
+}
+
+/*
+ * serialize an rsa key into DER
+ */
+
+int x509write_serialize_key(rsa_context *rsa, x509_node *node)
+{
+ int ret = 0;
+ x509write_init_node(node);
+
+ /* vers, n, e, d, p, q, dp, dq, pq */
+ if ((ret = asn1_add_int(rsa->ver, node)) != 0)
+ return ret;
+ if ((ret = asn1_add_mpi(&rsa->N, ASN1_INTEGER, node)) != 0)
+ return ret;
+ if ((ret = asn1_add_mpi(&rsa->E, ASN1_INTEGER, node)) != 0)
+ return ret;
+ if ((ret = asn1_add_mpi(&rsa->D, ASN1_INTEGER, node)) != 0)
+ return ret;
+ if ((ret = asn1_add_mpi(&rsa->P, ASN1_INTEGER, node)) != 0)
+ return ret;
+ if ((ret = asn1_add_mpi(&rsa->Q, ASN1_INTEGER, node)) != 0)
+ return ret;
+ if ((ret = asn1_add_mpi(&rsa->DP, ASN1_INTEGER, node)) != 0)
+ return ret;
+ if ((ret = asn1_add_mpi(&rsa->DQ, ASN1_INTEGER, node)) != 0)
+ return ret;
+ if ((ret = asn1_add_mpi(&rsa->QP, ASN1_INTEGER, node)) != 0)
+ return ret;
+ if ((ret = asn1_append_tag(node, ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0)
+ return ret;
+
+ return 0;
+}
+
+/*
+ * write a der/pem encoded rsa private key into a file
+ */
+int x509write_keyfile(rsa_context *rsa, char *path, int out_flag)
+{
+ int ret = 0;
+ const char key_beg[] = "-----BEGIN RSA PRIVATE KEY-----\n",
+ key_end[] = "-----END RSA PRIVATE KEY-----\n";
+ x509_node node;
+
+ x509write_init_node(&node);
+ if ((ret = x509write_serialize_key(rsa,&node)) != 0) {
+ x509write_free_node(&node);
+ return ret;
+ }
+
+ ret = x509write_file(&node,path,out_flag,key_beg,key_end);
+ x509write_free_node(&node);
+
+ return ret;
+}
+
+
+/*
+ * reasize the memory for node
+ */
+static int x509write_realloc_node(x509_node *node, size_t larger)
+{
+ /* init len */
+ if (node->data == NULL) {
+ node->len = 0;
+ node->data = malloc(larger);
+ if(node->data == NULL)
+ return 1;
+ } else {
+ /* realloc memory */
+ if ((node->data = realloc(node->data, node->len + larger)) == NULL)
+ return 1;
+ }
+
+ /* init pointer */
+ node->p = &node->data[node->len];
+ node->len += larger;
+ node->end = &node->data[node->len -1];
+
+ return 0;
+}
+
+/*
+ * init node
+ */
+void x509write_init_node(x509_node *node)
+{
+ memset(node, 0, sizeof(x509_node));
+}
+
+/*
+ * clean memory
+ */
+void x509write_free_node(x509_node *node)
+{
+ if (node->data != NULL)
+ free(node->data);
+ node->p = NULL;
+ node->end = NULL;
+ node->len = 0;
+}
+
+/*
+ * write a x509 certificate into file
+ */
+int x509write_crtfile(x509_raw *chain, unsigned char *path, int out_flag)
+{
+ const char cer_beg[] = "-----BEGIN CERTIFICATE-----\n",
+ cer_end[] = "-----END CERTIFICATE-----\n";
+
+ return x509write_file(&chain->raw, (char*)path, out_flag, cer_beg, cer_end);
+}
+
+/*
+ * write a x509 certificate into file
+ */
+int x509write_csrfile(x509_raw *chain, unsigned char *path, int out_flag)
+{
+ const char cer_beg[] = "-----BEGIN CERTIFICATE REQUEST-----\n",
+ cer_end[] = "-----END CERTIFICATE REQUEST-----\n";
+
+ return x509write_file(&chain->raw, (char*)path, out_flag, cer_beg, cer_end);
+}
+
+/*
+ * write an x509 file
+ */
+static int x509write_file(x509_node *node, char *path, int format,
+ const char* pem_prolog, const char* pem_epilog)
+{
+ FILE *ofstream = stdout;
+ int is_err = 1, buf_len, i, n;
+ unsigned char* base_buf;
+
+ if (path) {
+ if ((ofstream = fopen(path, "wb")) == NULL)
+ return 1;
+ }
+
+ switch (format) {
+ case X509_OUTPUT_DER:
+ if (fwrite(node->data, 1, node->len, ofstream)
+ != node->len)
+ is_err = -1;
+ break;
+
+ case X509_OUTPUT_PEM:
+ if (fprintf(ofstream,pem_prolog)<0) {
+ is_err = -1;
+ break;
+ }
+
+ buf_len = node->len << 1;
+ base_buf = (unsigned char*) malloc((size_t)buf_len);
+ memset(base_buf,0,buf_len);
+ if (base64_encode(base_buf, &buf_len, node->data,
+ (int) node->len) != 0) {
+ is_err = -1;
+ break;
+ }
+
+ n=strlen((char*)base_buf);
+ for(i=0;i<n;i+=64) {
+ fprintf(ofstream,"%.64s\n",&base_buf[i]);
+ }
+
+ if (fprintf(ofstream, pem_epilog)<0) {
+ is_err = -1;
+ break;
+ }
+
+ free(base_buf);
+ }
+
+ fclose(ofstream);
+
+ if (is_err == -1)
+ return 1;
+
+ return 0;
+}
+
+
+/*
+ * add the owner public key to x509 certificate
+ */
+int x509write_add_pubkey(x509_raw *chain, rsa_context *pubkey)
+{
+ x509_node n_tmp, n_tmp2, *node;
+ int ret;
+
+ node = &chain->subpubkey;
+
+ x509write_init_node(&n_tmp);
+ x509write_init_node(&n_tmp2);
+
+ /*
+ * RSAPublicKey ::= SEQUENCE {
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER -- e
+ * }
+ */
+ if ((ret = asn1_add_mpi(&pubkey->N, ASN1_INTEGER, &n_tmp)) != 0) {
+ x509write_free_node(&n_tmp);
+ x509write_free_node(&n_tmp2);
+ return ret;
+ }
+ if ((ret = asn1_add_mpi(&pubkey->E, ASN1_INTEGER, &n_tmp)) != 0) {
+ x509write_free_node(&n_tmp);
+ x509write_free_node(&n_tmp2);
+ return ret;
+ }
+ if ((ret = asn1_append_tag(&n_tmp, ASN1_CONSTRUCTED | ASN1_SEQUENCE))
+ != 0) {
+ x509write_free_node(&n_tmp);
+ x509write_free_node(&n_tmp2);
+ return ret;
+ }
+
+ /*
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING }
+ */
+ if ((ret = asn1_append_tag(&n_tmp, ASN1_BIT_STRING)) != 0) {
+ x509write_free_node(&n_tmp);
+ x509write_free_node(&n_tmp2);
+ return ret;
+ }
+ if ((ret = asn1_add_oid(&n_tmp2, (unsigned char*)OID_PKCS1_RSA, 9,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE, ASN1_NULL,
+ (unsigned char *)"", 0)) != 0) {
+ x509write_free_node(&n_tmp);
+ x509write_free_node(&n_tmp2);
+ return ret;
+ }
+
+ if ((ret = asn1_append_nodes(node, ASN1_CONSTRUCTED | ASN1_SEQUENCE, 2,
+ &n_tmp2, &n_tmp))) {
+ x509write_free_node(&n_tmp);
+ x509write_free_node(&n_tmp2);
+ return ret;
+ }
+
+ x509write_free_node(&n_tmp);
+ x509write_free_node(&n_tmp2);
+ return 0;
+}
+
+/*
+ * RelativeDistinguishedName ::=
+ * SET OF AttributeTypeAndValue
+ *
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type AttributeType,
+ * value AttributeValue }
+ */
+static int x509write_add_name(x509_node *node, unsigned char *oid,
+ unsigned int oid_len, unsigned char *value, int len, int value_tag)
+{
+ int ret;
+ x509_node n_tmp;
+
+ x509write_init_node(&n_tmp);
+
+ if ((ret = asn1_add_oid(&n_tmp, oid, oid_len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE, value_tag,
+ value, len))) {
+ x509write_free_node(&n_tmp);
+ return ret;
+ }
+
+ if ((asn1_append_nodes(node, ASN1_CONSTRUCTED | ASN1_SET, 1, &n_tmp))
+ != 0) {
+ x509write_free_node(&n_tmp);
+ return ret;
+ }
+
+ x509write_free_node(&n_tmp);
+ return 0;
+}
+
+/*
+ * Parse the name string and add to node
+ */
+static int x509write_parse_names(x509_node *node, unsigned char *names)
+{
+ unsigned char *sp, *begin = NULL;
+ unsigned char oid[3] = OID_X520, tag[4], *tag_sp = tag;
+ unsigned char *C = NULL, *CN = NULL, *O = NULL, *OU = NULL,
+ *ST = NULL, *L = NULL, *R = NULL;
+ int C_len = 0, CN_len = 0, O_len = 0, OU_len = 0, ST_len = 0,
+ L_len = 0, R_len = 0;
+ int ret = 0, is_tag = 1, is_begin = -1, len = 0;
+
+
+ for (sp = names; ; ++sp) {
+
+ /* filter tag */
+ if (is_tag == 1) {
+
+ if (tag_sp == &tag[3])
+ return POLARSSL_ERR_X509_VALUE_TO_LENGTH;
+
+ /* is tag end? */
+ if (*sp == '=') {
+ is_tag = -1;
+ *tag_sp = '\0';
+ is_begin = 1;
+ /* set len 0 (reset) */
+ len = 0;
+ } else {
+ /* tag hasn't ' '! */
+ if (*sp != ' ') {
+ *tag_sp = *sp;
+ ++tag_sp;
+ }
+ }
+ /* filter value */
+ } else {
+
+ /* set pointer of value begin */
+ if (is_begin == 1) {
+ begin = sp;
+ is_begin = -1;
+ }
+
+ /* is value at end? */
+ if (*sp == ';' or *sp == '\0') {
+ is_tag = 1;
+
+ /* common name */
+ if (tag[0] == 'C' and tag[1] == 'N') {
+ CN = begin;
+ CN_len = len;
+
+ /* organization */
+ } else if (tag[0] == 'O' and tag[1] == '\0') {
+ O = begin;
+ O_len = len;
+
+ /* country */
+ } else if (tag[0] == 'C' and tag[1] == '\0') {
+ C = begin;
+ C_len = len;
+
+ /* organisation unit */
+ } else if (tag[0] == 'O' and tag[1] == 'U') {
+ OU = begin;
+ OU_len = len;
+
+ /* state */
+ } else if (tag[0] == 'S' and tag[1] == 'T') {
+ ST = begin;
+ ST_len = len;
+
+ /* locality */
+ } else if (tag[0] == 'L' and tag[1] == '\0') {
+ L = begin;
+ L_len = len;
+
+ /* email */
+ } else if (tag[0] == 'R' and tag[1] == '\0') {
+ R = begin;
+ R_len = len;
+ }
+
+ /* set tag poiner to begin */
+ tag_sp = tag;
+
+ /* is at end? */
+ if (*sp == '\0' or *(sp +1) == '\0')
+ break;
+ } else {
+ ++len;
+ }
+ }
+
+ /* make saver */
+ if (*sp == '\0')
+ break;
+ } /* end for */
+
+ /* country */
+ if (C != NULL) {
+ oid[2] = X520_COUNTRY;
+ if ((ret = x509write_add_name(node, oid, 3, C, C_len,
+ ASN1_PRINTABLE_STRING)) != 0)
+ return ret;
+ }
+
+ /* state */
+ if (ST != NULL) {
+ oid[2] = X520_STATE;
+ if ((ret = x509write_add_name(node, oid, 3, ST, ST_len,
+ ASN1_PRINTABLE_STRING)) != 0)
+ return ret;
+ }
+
+ /* locality */
+ if (L != NULL) {
+ oid[2] = X520_LOCALITY;
+ if ((ret = x509write_add_name(node, oid, 3, L, L_len,
+ ASN1_PRINTABLE_STRING)) != 0)
+ return ret;
+ }
+
+ /* organization */
+ if (O != NULL) {
+ oid[2] = X520_ORGANIZATION;
+ if ((ret = x509write_add_name(node, oid, 3, O, O_len,
+ ASN1_PRINTABLE_STRING)) != 0)
+ return ret;
+ }
+
+ /* organisation unit */
+ if (OU != NULL) {
+ oid[2] = X520_ORG_UNIT;
+ if ((ret = x509write_add_name(node, oid, 3, OU, OU_len,
+ ASN1_PRINTABLE_STRING)) != 0)
+ return ret;
+ }
+
+ /* common name */
+ if (CN != NULL) {
+ oid[2] = X520_COMMON_NAME;
+ if ((ret = x509write_add_name(node, oid, 3, CN, CN_len,
+ ASN1_PRINTABLE_STRING)) != 0)
+ return ret;
+ }
+
+ /* email */
+ if (R != NULL) {
+ if ((ret = x509write_add_name(node, (unsigned char*)OID_PKCS9_EMAIL,
+ 9, R, R_len, ASN1_IA5_STRING)) != 0)
+ return ret;
+ }
+
+ if ((asn1_append_tag(node, ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0)
+ return ret;
+
+ return 0;
+}
+
+/*
+ * Copy raw data from orginal ca to node
+ */
+static int x509write_copy_from_raw(x509_node *node, x509_buf *raw)
+{
+ if (x509write_realloc_node(node, raw->len) != 0)
+ return 1;
+
+ memcpy(node->p, raw->p, (size_t)raw->len);
+ if ((node->p += raw->len -1) != node->end)
+ return POLARSSL_ERR_X509_POINT_ERROR;
+
+ return 0;
+}
+
+/*
+ * Add the issuer
+ */
+
+int x509write_add_issuer(x509_raw *crt, unsigned char *issuer)
+{
+ return x509write_parse_names(&crt->issuer, issuer);
+}
+
+/*
+ * Add the subject
+ */
+int x509write_add_subject(x509_raw *crt, unsigned char *subject)
+{
+ return x509write_parse_names(&crt->subject, subject);
+}
+
+/*
+ * Copy issuer line from another cert to issuer
+ */
+int x509write_copy_issuer(x509_raw *crt, x509_cert *from_crt)
+{
+ return x509write_copy_from_raw(&crt->issuer, &from_crt->issuer_raw);
+}
+
+/*
+ * Copy subject line from another cert
+ */
+int x509write_copy_subject(x509_raw *crt, x509_cert *from_crt)
+{
+ return x509write_copy_from_raw(&crt->subject, &from_crt->subject_raw);
+}
+
+/*
+ * Copy subject line form antoher cert into issuer
+ */
+int x509write_copy_issuer_form_subject(x509_raw *crt,
+ x509_cert *from_crt)
+{
+ return x509write_copy_from_raw(&crt->issuer, &from_crt->subject_raw);
+}
+
+/*
+ * Copy issuer line from another cert into subject
+ */
+int x509write_copy_subject_from_issuer(x509_raw *crt,
+ x509_cert * from_crt)
+{
+ return x509write_copy_from_raw(&crt->subject, &from_crt->issuer_raw);
+}
+
+/*
+ * Validity ::= SEQUENCE {
+ * notBefore Time,
+ * notAfter Time }
+ *
+ * Time ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ */
+/* TODO: No handle GeneralizedTime! */
+int x509write_add_validity(x509_raw *chain, unsigned char *befor,
+ unsigned char *after)
+{
+ int ret;
+
+ x509_node *node = &chain->validity;
+
+ /* notBefore */
+ if ((ret = asn1_add_date_utc(befor, node)) != 0)
+ return ret;
+
+ /* notAfter */
+ if ((ret = asn1_add_date_utc(after, node)) != 0)
+ return ret;
+
+ if ((ret = asn1_append_tag(node, ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0)
+ return ret;
+
+ return 0;
+}
+
+/*
+ * make hash from tbs and sign that with private key
+ */
+static int x509write_make_sign(x509_raw *chain, rsa_context *privkey)
+{
+ int ret;
+ unsigned char hash[20], *sign;
+ size_t sign_len = (size_t) mpi_size(&privkey->N);
+
+ /* make hash */
+ sha1(chain->tbs.data, chain->tbs.len, hash);
+
+ /* create sign */
+ sign = (unsigned char *) malloc(sign_len);
+ if (sign == NULL)
+ return 1;
+
+ if ((ret = rsa_pkcs1_sign(privkey, RSA_PRIVATE, RSA_SHA1, 20, hash,
+ sign)) != 0)
+ return ret;
+
+ if ((ret = asn1_add_obj(sign, sign_len, ASN1_BIT_STRING,
+ &chain->sign)) != 0)
+ return ret;
+
+ /*
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ */
+ return asn1_add_oid(&chain->signalg, (unsigned char*)OID_PKCS1_RSA_SHA, 9,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE, ASN1_NULL,
+ (unsigned char*)"", 0);
+}
+
+/*
+ * Create a self signed certificate
+ */
+int x509write_create_sign(x509_raw *chain, rsa_context *privkey)
+{
+ int ret, serial;
+
+ /*
+ * Version ::= INTEGER { v1(0), v2(1), v3(2) }
+ */
+ if ((ret = asn1_add_int(2, &chain->version)) != 0)
+ return ret;
+
+ if ((ret = asn1_append_tag(&chain->version, ASN1_CONTEXT_SPECIFIC |
+ ASN1_CONSTRUCTED)) != 0)
+ return ret;
+
+
+ /*
+ * CertificateSerialNumber ::= INTEGER
+ */
+ srand((unsigned int) time(NULL));
+ serial = rand();
+ if ((ret = asn1_add_int(serial, &chain->serial)) != 0)
+ return ret;
+
+ /*
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ */
+ if ((ret = asn1_add_oid(&chain->tbs_signalg,
+ (unsigned char*)OID_PKCS1_RSA_SHA, 9, ASN1_CONSTRUCTED |
+ ASN1_SEQUENCE, ASN1_NULL, (unsigned char*)"", 0)) != 0)
+ return ret;
+
+ /*
+ * Create the tbs
+ */
+ if ((ret = asn1_append_nodes(&chain->tbs, ASN1_CONSTRUCTED |
+ ASN1_SEQUENCE, 7, &chain->version, &chain->serial,
+ &chain->tbs_signalg, &chain->issuer, &chain->validity,
+ &chain->subject, &chain->subpubkey)) != 0)
+ return ret;
+
+ /* make signing */
+ if ((ret = x509write_make_sign(chain, privkey)) != 0)
+ return ret;
+
+ /* finishing */
+ if ((ret = asn1_append_nodes(&chain->raw, ASN1_CONSTRUCTED |
+ ASN1_SEQUENCE, 3, &chain->tbs, &chain->signalg,
+ &chain->sign)) != 0)
+ return ret;
+
+ return 0;
+}
+
+int x509write_create_selfsign(x509_raw *chain, rsa_context *privkey)
+{
+ /*
+ * On self signed certificate are subject and issuer the same
+ */
+ x509write_free_node(&chain->issuer);
+ chain->issuer = chain->subject;
+ return x509write_create_sign(chain, privkey);
+}
+
+/*
+ * CertificationRequestInfo ::= SEQUENCE {
+ * version Version,
+ * subject Name,
+ * subjectPublicKeyInfo SubjectPublicKeyInfo,
+ * attributes [0] IMPLICIT Attributes }
+ *
+ * CertificationRequest ::= SEQUENCE {
+ * certificationRequestInfo CertificationRequestInfo,
+ * signatureAlgorithm SignatureAlgorithmIdentifier,
+ * signature Signature }
+ *
+ * It use chain.serail for attributes!
+ *
+ */
+int x509write_create_csr(x509_raw *chain, rsa_context *privkey)
+{
+ int ret;
+
+ /* version ::= INTEGER */
+ if ((ret = asn1_add_int(0, &chain->version)) != 0)
+ return ret;
+
+ /* write attributes */
+ if ((ret = asn1_add_obj((unsigned char*)"", 0, ASN1_CONTEXT_SPECIFIC |
+ ASN1_CONSTRUCTED, &chain->serial)) != 0)
+ return ret;
+
+ /* create CertificationRequestInfo */
+ if ((ret = asn1_append_nodes(&chain->tbs, ASN1_CONSTRUCTED |
+ ASN1_SEQUENCE, 4, &chain->version, &chain->subject,
+ &chain->subpubkey, &chain->serial)) != 0)
+ return ret;
+
+ /* make signing */
+ if ((ret = x509write_make_sign(chain, privkey)) != 0)
+ return ret;
+
+ /* finish */
+ if ((ret = asn1_append_nodes(&chain->raw, ASN1_CONSTRUCTED | ASN1_SEQUENCE,
+ 3, &chain->tbs, &chain->signalg, &chain->sign)) != 0)
+ return ret;
+
+ return ret;
+}
+
+/*
+ * Free memory
+ */
+void x509write_free_raw(x509_raw *chain)
+{
+ x509write_free_node(&chain->raw);
+ x509write_free_node(&chain->tbs);
+ x509write_free_node(&chain->version);
+ x509write_free_node(&chain->serial);
+ x509write_free_node(&chain->tbs_signalg);
+ x509write_free_node(&chain->issuer);
+ x509write_free_node(&chain->validity);
+ if (chain->subject.data != chain->issuer.data)
+ x509write_free_node(&chain->subject);
+ x509write_free_node(&chain->subpubkey);
+ x509write_free_node(&chain->signalg);
+ x509write_free_node(&chain->sign);
+}
+
+void x509write_init_raw(x509_raw *chain)
+{
+ memset((void *) chain, 0, sizeof(x509_raw));
+}
+
diff --git a/package/px5g/src/polarssl/base64.h b/package/px5g/src/polarssl/base64.h
new file mode 100644
index 000000000..c48267b1b
--- /dev/null
+++ b/package/px5g/src/polarssl/base64.h
@@ -0,0 +1,93 @@
+/**
+ * \file base64.h
+ *
+ * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
+ *
+ * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the names of PolarSSL or XySSL 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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 POLARSSL_BASE64_H
+#define POLARSSL_BASE64_H
+
+#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL -0x0010
+#define POLARSSL_ERR_BASE64_INVALID_CHARACTER -0x0012
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Encode a buffer into base64 format
+ *
+ * \param dst destination buffer
+ * \param dlen size of the buffer
+ * \param src source buffer
+ * \param slen amount of data to be encoded
+ *
+ * \return 0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL.
+ * *dlen is always updated to reflect the amount
+ * of data that has (or would have) been written.
+ *
+ * \note Call this function with *dlen = 0 to obtain the
+ * required buffer size in *dlen
+ */
+int base64_encode( unsigned char *dst, int *dlen,
+ unsigned char *src, int slen );
+
+/**
+ * \brief Decode a base64-formatted buffer
+ *
+ * \param dst destination buffer
+ * \param dlen size of the buffer
+ * \param src source buffer
+ * \param slen amount of data to be decoded
+ *
+ * \return 0 if successful, POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL, or
+ * POLARSSL_ERR_BASE64_INVALID_DATA if the input data is not
+ * correct. *dlen is always updated to reflect the amount
+ * of data that has (or would have) been written.
+ *
+ * \note Call this function with *dlen = 0 to obtain the
+ * required buffer size in *dlen
+ */
+int base64_decode( unsigned char *dst, int *dlen,
+ unsigned char *src, int slen );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int base64_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* base64.h */
diff --git a/package/px5g/src/polarssl/bignum.h b/package/px5g/src/polarssl/bignum.h
new file mode 100644
index 000000000..c66730332
--- /dev/null
+++ b/package/px5g/src/polarssl/bignum.h
@@ -0,0 +1,437 @@
+/**
+ * \file bignum.h
+ *
+ * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
+ *
+ * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the names of PolarSSL or XySSL 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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 POLARSSL_BIGNUM_H
+#define POLARSSL_BIGNUM_H
+
+#include <stdio.h>
+
+#define POLARSSL_ERR_MPI_FILE_IO_ERROR -0x0002
+#define POLARSSL_ERR_MPI_BAD_INPUT_DATA -0x0004
+#define POLARSSL_ERR_MPI_INVALID_CHARACTER -0x0006
+#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL -0x0008
+#define POLARSSL_ERR_MPI_NEGATIVE_VALUE -0x000A
+#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO -0x000C
+#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE -0x000E
+
+#define MPI_CHK(f) if( ( ret = f ) != 0 ) goto cleanup
+
+/*
+ * Define the base integer type, architecture-wise
+ */
+#if defined(POLARSSL_HAVE_INT8)
+typedef unsigned char t_int;
+typedef unsigned short t_dbl;
+#else
+#if defined(POLARSSL_HAVE_INT16)
+typedef unsigned short t_int;
+typedef unsigned long t_dbl;
+#else
+ typedef unsigned long t_int;
+ #if defined(_MSC_VER) && defined(_M_IX86)
+ typedef unsigned __int64 t_dbl;
+ #else
+ #if defined(__amd64__) || defined(__x86_64__) || \
+ defined(__ppc64__) || defined(__powerpc64__) || \
+ defined(__ia64__) || defined(__alpha__)
+ typedef unsigned int t_dbl __attribute__((mode(TI)));
+ #else
+ typedef unsigned long long t_dbl;
+ #endif
+ #endif
+#endif
+#endif
+
+/**
+ * \brief MPI structure
+ */
+typedef struct
+{
+ int s; /*!< integer sign */
+ int n; /*!< total # of limbs */
+ t_int *p; /*!< pointer to limbs */
+}
+mpi;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Initialize one or more mpi
+ */
+void mpi_init( mpi *X, ... );
+
+/**
+ * \brief Unallocate one or more mpi
+ */
+void mpi_free( mpi *X, ... );
+
+/**
+ * \brief Enlarge to the specified number of limbs
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_grow( mpi *X, int nblimbs );
+
+/**
+ * \brief Copy the contents of Y into X
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_copy( mpi *X, mpi *Y );
+
+/**
+ * \brief Swap the contents of X and Y
+ */
+void mpi_swap( mpi *X, mpi *Y );
+
+/**
+ * \brief Set value from integer
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_lset( mpi *X, int z );
+
+/**
+ * \brief Return the number of least significant bits
+ */
+int mpi_lsb( mpi *X );
+
+/**
+ * \brief Return the number of most significant bits
+ */
+int mpi_msb( mpi *X );
+
+/**
+ * \brief Return the total size in bytes
+ */
+int mpi_size( mpi *X );
+
+/**
+ * \brief Import from an ASCII string
+ *
+ * \param X destination mpi
+ * \param radix input numeric base
+ * \param s null-terminated string buffer
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code
+ */
+int mpi_read_string( mpi *X, int radix, char *s );
+
+/**
+ * \brief Export into an ASCII string
+ *
+ * \param X source mpi
+ * \param radix output numeric base
+ * \param s string buffer
+ * \param slen string buffer size
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code
+ *
+ * \note Call this function with *slen = 0 to obtain the
+ * minimum required buffer size in *slen.
+ */
+int mpi_write_string( mpi *X, int radix, char *s, int *slen );
+
+/**
+ * \brief Read X from an opened file
+ *
+ * \param X destination mpi
+ * \param radix input numeric base
+ * \param fin input file handle
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code
+ */
+int mpi_read_file( mpi *X, int radix, FILE *fin );
+
+/**
+ * \brief Write X into an opened file, or stdout
+ *
+ * \param p prefix, can be NULL
+ * \param X source mpi
+ * \param radix output numeric base
+ * \param fout output file handle
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code
+ *
+ * \note Set fout == NULL to print X on the console.
+ */
+int mpi_write_file( char *p, mpi *X, int radix, FILE *fout );
+
+/**
+ * \brief Import X from unsigned binary data, big endian
+ *
+ * \param X destination mpi
+ * \param buf input buffer
+ * \param buflen input buffer size
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_read_binary( mpi *X, unsigned char *buf, int buflen );
+
+/**
+ * \brief Export X into unsigned binary data, big endian
+ *
+ * \param X source mpi
+ * \param buf output buffer
+ * \param buflen output buffer size
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
+ *
+ * \note Call this function with *buflen = 0 to obtain the
+ * minimum required buffer size in *buflen.
+ */
+int mpi_write_binary( mpi *X, unsigned char *buf, int buflen );
+
+/**
+ * \brief Left-shift: X <<= count
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_shift_l( mpi *X, int count );
+
+/**
+ * \brief Right-shift: X >>= count
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_shift_r( mpi *X, int count );
+
+/**
+ * \brief Compare unsigned values
+ *
+ * \return 1 if |X| is greater than |Y|,
+ * -1 if |X| is lesser than |Y| or
+ * 0 if |X| is equal to |Y|
+ */
+int mpi_cmp_abs( mpi *X, mpi *Y );
+
+/**
+ * \brief Compare signed values
+ *
+ * \return 1 if X is greater than Y,
+ * -1 if X is lesser than Y or
+ * 0 if X is equal to Y
+ */
+int mpi_cmp_mpi( mpi *X, mpi *Y );
+
+/**
+ * \brief Compare signed values
+ *
+ * \return 1 if X is greater than z,
+ * -1 if X is lesser than z or
+ * 0 if X is equal to z
+ */
+int mpi_cmp_int( mpi *X, int z );
+
+/**
+ * \brief Unsigned addition: X = |A| + |B|
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_add_abs( mpi *X, mpi *A, mpi *B );
+
+/**
+ * \brief Unsigned substraction: X = |A| - |B|
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A
+ */
+int mpi_sub_abs( mpi *X, mpi *A, mpi *B );
+
+/**
+ * \brief Signed addition: X = A + B
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_add_mpi( mpi *X, mpi *A, mpi *B );
+
+/**
+ * \brief Signed substraction: X = A - B
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_sub_mpi( mpi *X, mpi *A, mpi *B );
+
+/**
+ * \brief Signed addition: X = A + b
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_add_int( mpi *X, mpi *A, int b );
+
+/**
+ * \brief Signed substraction: X = A - b
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_sub_int( mpi *X, mpi *A, int b );
+
+/**
+ * \brief Baseline multiplication: X = A * B
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_mul_mpi( mpi *X, mpi *A, mpi *B );
+
+/**
+ * \brief Baseline multiplication: X = A * b
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_mul_int( mpi *X, mpi *A, t_int b );
+
+/**
+ * \brief Division by mpi: A = Q * B + R
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed,
+ * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0
+ *
+ * \note Either Q or R can be NULL.
+ */
+int mpi_div_mpi( mpi *Q, mpi *R, mpi *A, mpi *B );
+
+/**
+ * \brief Division by int: A = Q * b + R
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed,
+ * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
+ *
+ * \note Either Q or R can be NULL.
+ */
+int mpi_div_int( mpi *Q, mpi *R, mpi *A, int b );
+
+/**
+ * \brief Modulo: R = A mod B
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed,
+ * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0
+ */
+int mpi_mod_mpi( mpi *R, mpi *A, mpi *B );
+
+/**
+ * \brief Modulo: r = A mod b
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed,
+ * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
+ */
+int mpi_mod_int( t_int *r, mpi *A, int b );
+
+/**
+ * \brief Sliding-window exponentiation: X = A^E mod N
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed,
+ * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even
+ *
+ * \note _RR is used to avoid re-computing R*R mod N across
+ * multiple calls, which speeds up things a bit. It can
+ * be set to NULL if the extra performance is unneeded.
+ */
+int mpi_exp_mod( mpi *X, mpi *A, mpi *E, mpi *N, mpi *_RR );
+
+/**
+ * \brief Greatest common divisor: G = gcd(A, B)
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed
+ */
+int mpi_gcd( mpi *G, mpi *A, mpi *B );
+
+/**
+ * \brief Modular inverse: X = A^-1 mod N
+ *
+ * \return 0 if successful,
+ * 1 if memory allocation failed,
+ * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil
+ * POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N
+ */
+int mpi_inv_mod( mpi *X, mpi *A, mpi *N );
+
+/**
+ * \brief Miller-Rabin primality test
+ *
+ * \return 0 if successful (probably prime),
+ * 1 if memory allocation failed,
+ * POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime
+ */
+int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng );
+
+/**
+ * \brief Prime number generation
+ *
+ * \param X destination mpi
+ * \param nbits required size of X in bits
+ * \param dh_flag if 1, then (X-1)/2 will be prime too
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful (probably prime),
+ * 1 if memory allocation failed,
+ * POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3
+ */
+int mpi_gen_prime( mpi *X, int nbits, int dh_flag,
+ int (*f_rng)(void *), void *p_rng );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int mpi_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* bignum.h */
diff --git a/package/px5g/src/polarssl/bn_mul.h b/package/px5g/src/polarssl/bn_mul.h
new file mode 100644
index 000000000..f6d34da58
--- /dev/null
+++ b/package/px5g/src/polarssl/bn_mul.h
@@ -0,0 +1,731 @@
+/**
+ * \file bn_mul.h
+ *
+ * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
+ *
+ * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the names of PolarSSL or XySSL 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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.
+ */
+/*
+ * Multiply source vector [s] with b, add result
+ * to destination vector [d] and set carry c.
+ *
+ * Currently supports:
+ *
+ * . IA-32 (386+) . AMD64 / EM64T
+ * . IA-32 (SSE2) . Motorola 68000
+ * . PowerPC, 32-bit . MicroBlaze
+ * . PowerPC, 64-bit . TriCore
+ * . SPARC v8 . ARM v3+
+ * . Alpha . MIPS32
+ * . C, longlong . C, generic
+ */
+#ifndef POLARSSL_BN_MUL_H
+#define POLARSSL_BN_MUL_H
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_HAVE_ASM)
+
+#if defined(__GNUC__)
+#if defined(__i386__)
+
+#define MULADDC_INIT \
+ asm( "movl %%ebx, %0 " : "=m" (t)); \
+ asm( "movl %0, %%esi " :: "m" (s)); \
+ asm( "movl %0, %%edi " :: "m" (d)); \
+ asm( "movl %0, %%ecx " :: "m" (c)); \
+ asm( "movl %0, %%ebx " :: "m" (b));
+
+#define MULADDC_CORE \
+ asm( "lodsl " ); \
+ asm( "mull %ebx " ); \
+ asm( "addl %ecx, %eax " ); \
+ asm( "adcl $0, %edx " ); \
+ asm( "addl (%edi), %eax " ); \
+ asm( "adcl $0, %edx " ); \
+ asm( "movl %edx, %ecx " ); \
+ asm( "stosl " );
+
+#if defined(POLARSSL_HAVE_SSE2)
+
+#define MULADDC_HUIT \
+ asm( "movd %ecx, %mm1 " ); \
+ asm( "movd %ebx, %mm0 " ); \
+ asm( "movd (%edi), %mm3 " ); \
+ asm( "paddq %mm3, %mm1 " ); \
+ asm( "movd (%esi), %mm2 " ); \
+ asm( "pmuludq %mm0, %mm2 " ); \
+ asm( "movd 4(%esi), %mm4 " ); \
+ asm( "pmuludq %mm0, %mm4 " ); \
+ asm( "movd 8(%esi), %mm6 " ); \
+ asm( "pmuludq %mm0, %mm6 " ); \
+ asm( "movd 12(%esi), %mm7 " ); \
+ asm( "pmuludq %mm0, %mm7 " ); \
+ asm( "paddq %mm2, %mm1 " ); \
+ asm( "movd 4(%edi), %mm3 " ); \
+ asm( "paddq %mm4, %mm3 " ); \
+ asm( "movd 8(%edi), %mm5 " ); \
+ asm( "paddq %mm6, %mm5 " ); \
+ asm( "movd 12(%edi), %mm4 " ); \
+ asm( "paddq %mm4, %mm7 " ); \
+ asm( "movd %mm1, (%edi) " ); \
+ asm( "movd 16(%esi), %mm2 " ); \
+ asm( "pmuludq %mm0, %mm2 " ); \
+ asm( "psrlq $32, %mm1 " ); \
+ asm( "movd 20(%esi), %mm4 " ); \
+ asm( "pmuludq %mm0, %mm4 " ); \
+ asm( "paddq %mm3, %mm1 " ); \
+ asm( "movd 24(%esi), %mm6 " ); \
+ asm( "pmuludq %mm0, %mm6 " ); \
+ asm( "movd %mm1, 4(%edi) " ); \
+ asm( "psrlq $32, %mm1 " ); \
+ asm( "movd 28(%esi), %mm3 " ); \
+ asm( "pmuludq %mm0, %mm3 " ); \
+ asm( "paddq %mm5, %mm1 " ); \
+ asm( "movd 16(%edi), %mm5 " ); \
+ asm( "paddq %mm5, %mm2 " ); \
+ asm( "movd %mm1, 8(%edi) " ); \
+ asm( "psrlq $32, %mm1 " ); \
+ asm( "paddq %mm7, %mm1 " ); \
+ asm( "movd 20(%edi), %mm5 " ); \
+ asm( "paddq %mm5, %mm4 " ); \
+ asm( "movd %mm1, 12(%edi) " ); \
+ asm( "psrlq $32, %mm1 " ); \
+ asm( "paddq %mm2, %mm1 " ); \
+ asm( "movd 24(%edi), %mm5 " ); \
+ asm( "paddq %mm5, %mm6 " ); \
+ asm( "movd %mm1, 16(%edi) " ); \
+ asm( "psrlq $32, %mm1 " ); \
+ asm( "paddq %mm4, %mm1 " ); \
+ asm( "movd 28(%edi), %mm5 " ); \
+ asm( "paddq %mm5, %mm3 " ); \
+ asm( "movd %mm1, 20(%edi) " ); \
+ asm( "psrlq $32, %mm1 " ); \
+ asm( "paddq %mm6, %mm1 " ); \
+ asm( "movd %mm1, 24(%edi) " ); \
+ asm( "psrlq $32, %mm1 " ); \
+ asm( "paddq %mm3, %mm1 " ); \
+ asm( "movd %mm1, 28(%edi) " ); \
+ asm( "addl $32, %edi " ); \
+ asm( "addl $32, %esi " ); \
+ asm( "psrlq $32, %mm1 " ); \
+ asm( "movd %mm1, %ecx " );
+
+#define MULADDC_STOP \
+ asm( "emms " ); \
+ asm( "movl %0, %%ebx " :: "m" (t)); \
+ asm( "movl %%ecx, %0 " : "=m" (c)); \
+ asm( "movl %%edi, %0 " : "=m" (d)); \
+ asm( "movl %%esi, %0 " : "=m" (s) :: \
+ "eax", "ecx", "edx", "esi", "edi" );
+
+#else
+
+#define MULADDC_STOP \
+ asm( "movl %0, %%ebx " :: "m" (t)); \
+ asm( "movl %%ecx, %0 " : "=m" (c)); \
+ asm( "movl %%edi, %0 " : "=m" (d)); \
+ asm( "movl %%esi, %0 " : "=m" (s) :: \
+ "eax", "ecx", "edx", "esi", "edi" );
+
+#endif /* SSE2 */
+#endif /* i386 */
+
+#if defined(__amd64__) || defined (__x86_64__)
+
+#define MULADDC_INIT \
+ asm( "movq %0, %%rsi " :: "m" (s)); \
+ asm( "movq %0, %%rdi " :: "m" (d)); \
+ asm( "movq %0, %%rcx " :: "m" (c)); \
+ asm( "movq %0, %%rbx " :: "m" (b)); \
+ asm( "xorq %r8, %r8 " );
+
+#define MULADDC_CORE \
+ asm( "movq (%rsi),%rax " ); \
+ asm( "mulq %rbx " ); \
+ asm( "addq $8, %rsi " ); \
+ asm( "addq %rcx, %rax " ); \
+ asm( "movq %r8, %rcx " ); \
+ asm( "adcq $0, %rdx " ); \
+ asm( "nop " ); \
+ asm( "addq %rax, (%rdi) " ); \
+ asm( "adcq %rdx, %rcx " ); \
+ asm( "addq $8, %rdi " );
+
+#define MULADDC_STOP \
+ asm( "movq %%rcx, %0 " : "=m" (c)); \
+ asm( "movq %%rdi, %0 " : "=m" (d)); \
+ asm( "movq %%rsi, %0 " : "=m" (s) :: \
+ "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" );
+
+#endif /* AMD64 */
+
+#if defined(__mc68020__) || defined(__mcpu32__)
+
+#define MULADDC_INIT \
+ asm( "movl %0, %%a2 " :: "m" (s)); \
+ asm( "movl %0, %%a3 " :: "m" (d)); \
+ asm( "movl %0, %%d3 " :: "m" (c)); \
+ asm( "movl %0, %%d2 " :: "m" (b)); \
+ asm( "moveq #0, %d0 " );
+
+#define MULADDC_CORE \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d4:%d1 " ); \
+ asm( "addl %d3, %d1 " ); \
+ asm( "addxl %d0, %d4 " ); \
+ asm( "moveq #0, %d3 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "addxl %d4, %d3 " );
+
+#define MULADDC_STOP \
+ asm( "movl %%d3, %0 " : "=m" (c)); \
+ asm( "movl %%a3, %0 " : "=m" (d)); \
+ asm( "movl %%a2, %0 " : "=m" (s) :: \
+ "d0", "d1", "d2", "d3", "d4", "a2", "a3" );
+
+#define MULADDC_HUIT \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d4:%d1 " ); \
+ asm( "addxl %d3, %d1 " ); \
+ asm( "addxl %d0, %d4 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d3:%d1 " ); \
+ asm( "addxl %d4, %d1 " ); \
+ asm( "addxl %d0, %d3 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d4:%d1 " ); \
+ asm( "addxl %d3, %d1 " ); \
+ asm( "addxl %d0, %d4 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d3:%d1 " ); \
+ asm( "addxl %d4, %d1 " ); \
+ asm( "addxl %d0, %d3 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d4:%d1 " ); \
+ asm( "addxl %d3, %d1 " ); \
+ asm( "addxl %d0, %d4 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d3:%d1 " ); \
+ asm( "addxl %d4, %d1 " ); \
+ asm( "addxl %d0, %d3 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d4:%d1 " ); \
+ asm( "addxl %d3, %d1 " ); \
+ asm( "addxl %d0, %d4 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d3:%d1 " ); \
+ asm( "addxl %d4, %d1 " ); \
+ asm( "addxl %d0, %d3 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "addxl %d0, %d3 " );
+
+#endif /* MC68000 */
+
+#if defined(__powerpc__) || defined(__ppc__)
+#if defined(__powerpc64__) || defined(__ppc64__)
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT \
+ asm( "ld r3, %0 " :: "m" (s)); \
+ asm( "ld r4, %0 " :: "m" (d)); \
+ asm( "ld r5, %0 " :: "m" (c)); \
+ asm( "ld r6, %0 " :: "m" (b)); \
+ asm( "addi r3, r3, -8 " ); \
+ asm( "addi r4, r4, -8 " ); \
+ asm( "addic r5, r5, 0 " );
+
+#define MULADDC_CORE \
+ asm( "ldu r7, 8(r3) " ); \
+ asm( "mulld r8, r7, r6 " ); \
+ asm( "mulhdu r9, r7, r6 " ); \
+ asm( "adde r8, r8, r5 " ); \
+ asm( "ld r7, 8(r4) " ); \
+ asm( "addze r5, r9 " ); \
+ asm( "addc r8, r8, r7 " ); \
+ asm( "stdu r8, 8(r4) " );
+
+#define MULADDC_STOP \
+ asm( "addze r5, r5 " ); \
+ asm( "addi r4, r4, 8 " ); \
+ asm( "addi r3, r3, 8 " ); \
+ asm( "std r5, %0 " : "=m" (c)); \
+ asm( "std r4, %0 " : "=m" (d)); \
+ asm( "std r3, %0 " : "=m" (s) :: \
+ "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#else
+
+#define MULADDC_INIT \
+ asm( "ld %%r3, %0 " :: "m" (s)); \
+ asm( "ld %%r4, %0 " :: "m" (d)); \
+ asm( "ld %%r5, %0 " :: "m" (c)); \
+ asm( "ld %%r6, %0 " :: "m" (b)); \
+ asm( "addi %r3, %r3, -8 " ); \
+ asm( "addi %r4, %r4, -8 " ); \
+ asm( "addic %r5, %r5, 0 " );
+
+#define MULADDC_CORE \
+ asm( "ldu %r7, 8(%r3) " ); \
+ asm( "mulld %r8, %r7, %r6 " ); \
+ asm( "mulhdu %r9, %r7, %r6 " ); \
+ asm( "adde %r8, %r8, %r5 " ); \
+ asm( "ld %r7, 8(%r4) " ); \
+ asm( "addze %r5, %r9 " ); \
+ asm( "addc %r8, %r8, %r7 " ); \
+ asm( "stdu %r8, 8(%r4) " );
+
+#define MULADDC_STOP \
+ asm( "addze %r5, %r5 " ); \
+ asm( "addi %r4, %r4, 8 " ); \
+ asm( "addi %r3, %r3, 8 " ); \
+ asm( "std %%r5, %0 " : "=m" (c)); \
+ asm( "std %%r4, %0 " : "=m" (d)); \
+ asm( "std %%r3, %0 " : "=m" (s) :: \
+ "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#endif
+
+#else /* PPC32 */
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT \
+ asm( "lwz r3, %0 " :: "m" (s)); \
+ asm( "lwz r4, %0 " :: "m" (d)); \
+ asm( "lwz r5, %0 " :: "m" (c)); \
+ asm( "lwz r6, %0 " :: "m" (b)); \
+ asm( "addi r3, r3, -4 " ); \
+ asm( "addi r4, r4, -4 " ); \
+ asm( "addic r5, r5, 0 " );
+
+#define MULADDC_CORE \
+ asm( "lwzu r7, 4(r3) " ); \
+ asm( "mullw r8, r7, r6 " ); \
+ asm( "mulhwu r9, r7, r6 " ); \
+ asm( "adde r8, r8, r5 " ); \
+ asm( "lwz r7, 4(r4) " ); \
+ asm( "addze r5, r9 " ); \
+ asm( "addc r8, r8, r7 " ); \
+ asm( "stwu r8, 4(r4) " );
+
+#define MULADDC_STOP \
+ asm( "addze r5, r5 " ); \
+ asm( "addi r4, r4, 4 " ); \
+ asm( "addi r3, r3, 4 " ); \
+ asm( "stw r5, %0 " : "=m" (c)); \
+ asm( "stw r4, %0 " : "=m" (d)); \
+ asm( "stw r3, %0 " : "=m" (s) :: \
+ "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#else
+
+#define MULADDC_INIT \
+ asm( "lwz %%r3, %0 " :: "m" (s)); \
+ asm( "lwz %%r4, %0 " :: "m" (d)); \
+ asm( "lwz %%r5, %0 " :: "m" (c)); \
+ asm( "lwz %%r6, %0 " :: "m" (b)); \
+ asm( "addi %r3, %r3, -4 " ); \
+ asm( "addi %r4, %r4, -4 " ); \
+ asm( "addic %r5, %r5, 0 " );
+
+#define MULADDC_CORE \
+ asm( "lwzu %r7, 4(%r3) " ); \
+ asm( "mullw %r8, %r7, %r6 " ); \
+ asm( "mulhwu %r9, %r7, %r6 " ); \
+ asm( "adde %r8, %r8, %r5 " ); \
+ asm( "lwz %r7, 4(%r4) " ); \
+ asm( "addze %r5, %r9 " ); \
+ asm( "addc %r8, %r8, %r7 " ); \
+ asm( "stwu %r8, 4(%r4) " );
+
+#define MULADDC_STOP \
+ asm( "addze %r5, %r5 " ); \
+ asm( "addi %r4, %r4, 4 " ); \
+ asm( "addi %r3, %r3, 4 " ); \
+ asm( "stw %%r5, %0 " : "=m" (c)); \
+ asm( "stw %%r4, %0 " : "=m" (d)); \
+ asm( "stw %%r3, %0 " : "=m" (s) :: \
+ "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#endif
+
+#endif /* PPC32 */
+#endif /* PPC64 */
+
+#if defined(__sparc__)
+
+#define MULADDC_INIT \
+ asm( "ld %0, %%o0 " :: "m" (s)); \
+ asm( "ld %0, %%o1 " :: "m" (d)); \
+ asm( "ld %0, %%o2 " :: "m" (c)); \
+ asm( "ld %0, %%o3 " :: "m" (b));
+
+#define MULADDC_CORE \
+ asm( "ld [%o0], %o4 " ); \
+ asm( "inc 4, %o0 " ); \
+ asm( "ld [%o1], %o5 " ); \
+ asm( "umul %o3, %o4, %o4 " ); \
+ asm( "addcc %o4, %o2, %o4 " ); \
+ asm( "rd %y, %g1 " ); \
+ asm( "addx %g1, 0, %g1 " ); \
+ asm( "addcc %o4, %o5, %o4 " ); \
+ asm( "st %o4, [%o1] " ); \
+ asm( "addx %g1, 0, %o2 " ); \
+ asm( "inc 4, %o1 " );
+
+#define MULADDC_STOP \
+ asm( "st %%o2, %0 " : "=m" (c)); \
+ asm( "st %%o1, %0 " : "=m" (d)); \
+ asm( "st %%o0, %0 " : "=m" (s) :: \
+ "g1", "o0", "o1", "o2", "o3", "o4", "o5" );
+
+#endif /* SPARCv8 */
+
+#if defined(__microblaze__) || defined(microblaze)
+
+#define MULADDC_INIT \
+ asm( "lwi r3, %0 " :: "m" (s)); \
+ asm( "lwi r4, %0 " :: "m" (d)); \
+ asm( "lwi r5, %0 " :: "m" (c)); \
+ asm( "lwi r6, %0 " :: "m" (b)); \
+ asm( "andi r7, r6, 0xffff" ); \
+ asm( "bsrli r6, r6, 16 " );
+
+#define MULADDC_CORE \
+ asm( "lhui r8, r3, 0 " ); \
+ asm( "addi r3, r3, 2 " ); \
+ asm( "lhui r9, r3, 0 " ); \
+ asm( "addi r3, r3, 2 " ); \
+ asm( "mul r10, r9, r6 " ); \
+ asm( "mul r11, r8, r7 " ); \
+ asm( "mul r12, r9, r7 " ); \
+ asm( "mul r13, r8, r6 " ); \
+ asm( "bsrli r8, r10, 16 " ); \
+ asm( "bsrli r9, r11, 16 " ); \
+ asm( "add r13, r13, r8 " ); \
+ asm( "add r13, r13, r9 " ); \
+ asm( "bslli r10, r10, 16 " ); \
+ asm( "bslli r11, r11, 16 " ); \
+ asm( "add r12, r12, r10 " ); \
+ asm( "addc r13, r13, r0 " ); \
+ asm( "add r12, r12, r11 " ); \
+ asm( "addc r13, r13, r0 " ); \
+ asm( "lwi r10, r4, 0 " ); \
+ asm( "add r12, r12, r10 " ); \
+ asm( "addc r13, r13, r0 " ); \
+ asm( "add r12, r12, r5 " ); \
+ asm( "addc r5, r13, r0 " ); \
+ asm( "swi r12, r4, 0 " ); \
+ asm( "addi r4, r4, 4 " );
+
+#define MULADDC_STOP \
+ asm( "swi r5, %0 " : "=m" (c)); \
+ asm( "swi r4, %0 " : "=m" (d)); \
+ asm( "swi r3, %0 " : "=m" (s) :: \
+ "r3", "r4" , "r5" , "r6" , "r7" , "r8" , \
+ "r9", "r10", "r11", "r12", "r13" );
+
+#endif /* MicroBlaze */
+
+#if defined(__tricore__)
+
+#define MULADDC_INIT \
+ asm( "ld.a %%a2, %0 " :: "m" (s)); \
+ asm( "ld.a %%a3, %0 " :: "m" (d)); \
+ asm( "ld.w %%d4, %0 " :: "m" (c)); \
+ asm( "ld.w %%d1, %0 " :: "m" (b)); \
+ asm( "xor %d5, %d5 " );
+
+#define MULADDC_CORE \
+ asm( "ld.w %d0, [%a2+] " ); \
+ asm( "madd.u %e2, %e4, %d0, %d1 " ); \
+ asm( "ld.w %d0, [%a3] " ); \
+ asm( "addx %d2, %d2, %d0 " ); \
+ asm( "addc %d3, %d3, 0 " ); \
+ asm( "mov %d4, %d3 " ); \
+ asm( "st.w [%a3+], %d2 " );
+
+#define MULADDC_STOP \
+ asm( "st.w %0, %%d4 " : "=m" (c)); \
+ asm( "st.a %0, %%a3 " : "=m" (d)); \
+ asm( "st.a %0, %%a2 " : "=m" (s) :: \
+ "d0", "d1", "e2", "d4", "a2", "a3" );
+
+#endif /* TriCore */
+
+#if defined(__arm__)
+
+#define MULADDC_INIT \
+ asm( "ldr r0, %0 " :: "m" (s)); \
+ asm( "ldr r1, %0 " :: "m" (d)); \
+ asm( "ldr r2, %0 " :: "m" (c)); \
+ asm( "ldr r3, %0 " :: "m" (b));
+
+#define MULADDC_CORE \
+ asm( "ldr r4, [r0], #4 " ); \
+ asm( "mov r5, #0 " ); \
+ asm( "ldr r6, [r1] " ); \
+ asm( "umlal r2, r5, r3, r4 " ); \
+ asm( "adds r7, r6, r2 " ); \
+ asm( "adc r2, r5, #0 " ); \
+ asm( "str r7, [r1], #4 " );
+
+#define MULADDC_STOP \
+ asm( "str r2, %0 " : "=m" (c)); \
+ asm( "str r1, %0 " : "=m" (d)); \
+ asm( "str r0, %0 " : "=m" (s) :: \
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" );
+
+#endif /* ARMv3 */
+
+#if defined(__alpha__)
+
+#define MULADDC_INIT \
+ asm( "ldq $1, %0 " :: "m" (s)); \
+ asm( "ldq $2, %0 " :: "m" (d)); \
+ asm( "ldq $3, %0 " :: "m" (c)); \
+ asm( "ldq $4, %0 " :: "m" (b));
+
+#define MULADDC_CORE \
+ asm( "ldq $6, 0($1) " ); \
+ asm( "addq $1, 8, $1 " ); \
+ asm( "mulq $6, $4, $7 " ); \
+ asm( "umulh $6, $4, $6 " ); \
+ asm( "addq $7, $3, $7 " ); \
+ asm( "cmpult $7, $3, $3 " ); \
+ asm( "ldq $5, 0($2) " ); \
+ asm( "addq $7, $5, $7 " ); \
+ asm( "cmpult $7, $5, $5 " ); \
+ asm( "stq $7, 0($2) " ); \
+ asm( "addq $2, 8, $2 " ); \
+ asm( "addq $6, $3, $3 " ); \
+ asm( "addq $5, $3, $3 " );
+
+#define MULADDC_STOP \
+ asm( "stq $3, %0 " : "=m" (c)); \
+ asm( "stq $2, %0 " : "=m" (d)); \
+ asm( "stq $1, %0 " : "=m" (s) :: \
+ "$1", "$2", "$3", "$4", "$5", "$6", "$7" );
+
+#endif /* Alpha */
+
+#if defined(__mips__)
+
+#define MULADDC_INIT \
+ asm( "lw $10, %0 " :: "m" (s)); \
+ asm( "lw $11, %0 " :: "m" (d)); \
+ asm( "lw $12, %0 " :: "m" (c)); \
+ asm( "lw $13, %0 " :: "m" (b));
+
+#define MULADDC_CORE \
+ asm( "lw $14, 0($10) " ); \
+ asm( "multu $13, $14 " ); \
+ asm( "addi $10, $10, 4 " ); \
+ asm( "mflo $14 " ); \
+ asm( "mfhi $9 " ); \
+ asm( "addu $14, $12, $14 " ); \
+ asm( "lw $15, 0($11) " ); \
+ asm( "sltu $12, $14, $12 " ); \
+ asm( "addu $15, $14, $15 " ); \
+ asm( "sltu $14, $15, $14 " ); \
+ asm( "addu $12, $12, $9 " ); \
+ asm( "sw $15, 0($11) " ); \
+ asm( "addu $12, $12, $14 " ); \
+ asm( "addi $11, $11, 4 " );
+
+#define MULADDC_STOP \
+ asm( "sw $12, %0 " : "=m" (c)); \
+ asm( "sw $11, %0 " : "=m" (d)); \
+ asm( "sw $10, %0 " : "=m" (s) :: \
+ "$9", "$10", "$11", "$12", "$13", "$14", "$15" );
+
+#endif /* MIPS */
+#endif /* GNUC */
+
+#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
+
+#define MULADDC_INIT \
+ __asm mov esi, s \
+ __asm mov edi, d \
+ __asm mov ecx, c \
+ __asm mov ebx, b
+
+#define MULADDC_CORE \
+ __asm lodsd \
+ __asm mul ebx \
+ __asm add eax, ecx \
+ __asm adc edx, 0 \
+ __asm add eax, [edi] \
+ __asm adc edx, 0 \
+ __asm mov ecx, edx \
+ __asm stosd
+
+#if defined(POLARSSL_HAVE_SSE2)
+
+#define EMIT __asm _emit
+
+#define MULADDC_HUIT \
+ EMIT 0x0F EMIT 0x6E EMIT 0xC9 \
+ EMIT 0x0F EMIT 0x6E EMIT 0xC3 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x1F \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
+ EMIT 0x0F EMIT 0x6E EMIT 0x16 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
+ EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xDC \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xEE \
+ EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xFC \
+ EMIT 0x0F EMIT 0x7E EMIT 0x0F \
+ EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
+ EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCD \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCF \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCC \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xDD \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCE \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \
+ EMIT 0x83 EMIT 0xC7 EMIT 0x20 \
+ EMIT 0x83 EMIT 0xC6 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x7E EMIT 0xC9
+
+#define MULADDC_STOP \
+ EMIT 0x0F EMIT 0x77 \
+ __asm mov c, ecx \
+ __asm mov d, edi \
+ __asm mov s, esi \
+
+#else
+
+#define MULADDC_STOP \
+ __asm mov c, ecx \
+ __asm mov d, edi \
+ __asm mov s, esi \
+
+#endif /* SSE2 */
+#endif /* MSVC */
+
+#endif /* POLARSSL_HAVE_ASM */
+
+#if !defined(MULADDC_CORE)
+#if defined(POLARSSL_HAVE_LONGLONG)
+
+#define MULADDC_INIT \
+{ \
+ t_dbl r; \
+ t_int r0, r1;
+
+#define MULADDC_CORE \
+ r = *(s++) * (t_dbl) b; \
+ r0 = r; \
+ r1 = r >> biL; \
+ r0 += c; r1 += (r0 < c); \
+ r0 += *d; r1 += (r0 < *d); \
+ c = r1; *(d++) = r0;
+
+#define MULADDC_STOP \
+}
+
+#else
+#define MULADDC_INIT \
+{ \
+ t_int s0, s1, b0, b1; \
+ t_int r0, r1, rx, ry; \
+ b0 = ( b << biH ) >> biH; \
+ b1 = ( b >> biH );
+
+#define MULADDC_CORE \
+ s0 = ( *s << biH ) >> biH; \
+ s1 = ( *s >> biH ); s++; \
+ rx = s0 * b1; r0 = s0 * b0; \
+ ry = s1 * b0; r1 = s1 * b1; \
+ r1 += ( rx >> biH ); \
+ r1 += ( ry >> biH ); \
+ rx <<= biH; ry <<= biH; \
+ r0 += rx; r1 += (r0 < rx); \
+ r0 += ry; r1 += (r0 < ry); \
+ r0 += c; r1 += (r0 < c); \
+ r0 += *d; r1 += (r0 < *d); \
+ c = r1; *(d++) = r0;
+
+#define MULADDC_STOP \
+}
+
+#endif /* C (generic) */
+#endif /* C (longlong) */
+
+#endif /* bn_mul.h */
diff --git a/package/px5g/src/polarssl/config.h b/package/px5g/src/polarssl/config.h
new file mode 100644
index 000000000..6463e5219
--- /dev/null
+++ b/package/px5g/src/polarssl/config.h
@@ -0,0 +1,329 @@
+/**
+ * \file config.h
+ *
+ * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
+ *
+ * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the names of PolarSSL or XySSL 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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.
+ *
+ * This set of compile-time options may be used to enable
+ * or disable features selectively, and reduce the global
+ * memory footprint.
+ */
+#ifndef POLARSSL_CONFIG_H
+#define POLARSSL_CONFIG_H
+
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+/*
+ * Uncomment if native integers are 8-bit wide.
+ *
+#define POLARSSL_HAVE_INT8
+ */
+
+/*
+ * Uncomment if native integers are 16-bit wide.
+ *
+#define POLARSSL_HAVE_INT16
+ */
+
+/*
+ * Uncomment if the compiler supports long long.
+ */
+#define POLARSSL_HAVE_LONGLONG
+
+
+/*
+ * Uncomment to enable the use of assembly code.
+ */
+#define POLARSSL_HAVE_ASM
+
+/*
+ * Uncomment if the CPU supports SSE2 (IA-32 specific).
+ *
+#define POLARSSL_HAVE_SSE2
+ */
+
+/*
+ * Enable all SSL/TLS debugging messages.
+ */
+#define POLARSSL_DEBUG_MSG
+
+/*
+ * Enable the checkup functions (*_self_test).
+ */
+#define POLARSSL_SELF_TEST
+
+/*
+ * Enable the prime-number generation code.
+ */
+#define POLARSSL_GENPRIME
+
+/*
+ * Uncomment this macro to store the AES tables in ROM.
+ *
+#define POLARSSL_AES_ROM_TABLES
+ */
+
+/*
+ * Module: library/aes.c
+ * Caller: library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites:
+ * SSL_RSA_AES_128_SHA
+ * SSL_RSA_AES_256_SHA
+ * SSL_EDH_RSA_AES_256_SHA
+ */
+#define POLARSSL_AES_C
+
+/*
+ * Module: library/arc4.c
+ * Caller: library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites:
+ * SSL_RSA_RC4_128_MD5
+ * SSL_RSA_RC4_128_SHA
+ */
+#define POLARSSL_ARC4_C
+
+/*
+ * Module: library/base64.c
+ * Caller: library/x509parse.c
+ *
+ * This module is required for X.509 support.
+ */
+#define POLARSSL_BASE64_C
+
+/*
+ * Module: library/bignum.c
+ * Caller: library/dhm.c
+ * library/rsa.c
+ * library/ssl_tls.c
+ * library/x509parse.c
+ *
+ * This module is required for RSA and DHM support.
+ */
+#define POLARSSL_BIGNUM_C
+
+/*
+ * Module: library/camellia.c
+ * Caller:
+ *
+ * This module enabled the following cipher suites:
+ */
+#define POLARSSL_CAMELLIA_C
+
+/*
+ * Module: library/certs.c
+ * Caller:
+ *
+ * This module is used for testing (ssl_client/server).
+ */
+#define POLARSSL_CERTS_C
+
+/*
+ * Module: library/debug.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ * library/ssl_tls.c
+ *
+ * This module provides debugging functions.
+ */
+#define POLARSSL_DEBUG_C
+
+/*
+ * Module: library/des.c
+ * Caller: library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites:
+ * SSL_RSA_DES_168_SHA
+ * SSL_EDH_RSA_DES_168_SHA
+ */
+#define POLARSSL_DES_C
+
+/*
+ * Module: library/dhm.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ *
+ * This module enables the following ciphersuites:
+ * SSL_EDH_RSA_DES_168_SHA
+ * SSL_EDH_RSA_AES_256_SHA
+ */
+#define POLARSSL_DHM_C
+
+/*
+ * Module: library/havege.c
+ * Caller:
+ *
+ * This module enables the HAVEGE random number generator.
+ */
+#define POLARSSL_HAVEGE_C
+
+/*
+ * Module: library/md2.c
+ * Caller: library/x509parse.c
+ *
+ * Uncomment to enable support for (rare) MD2-signed X.509 certs.
+ *
+#define POLARSSL_MD2_C
+ */
+
+/*
+ * Module: library/md4.c
+ * Caller: library/x509parse.c
+ *
+ * Uncomment to enable support for (rare) MD4-signed X.509 certs.
+ *
+#define POLARSSL_MD4_C
+ */
+
+/*
+ * Module: library/md5.c
+ * Caller: library/ssl_tls.c
+ * library/x509parse.c
+ *
+ * This module is required for SSL/TLS and X.509.
+ */
+#define POLARSSL_MD5_C
+
+/*
+ * Module: library/net.c
+ * Caller:
+ *
+ * This module provides TCP/IP networking routines.
+ */
+#define POLARSSL_NET_C
+
+/*
+ * Module: library/padlock.c
+ * Caller: library/aes.c
+ *
+ * This modules adds support for the VIA PadLock on x86.
+ */
+#define POLARSSL_PADLOCK_C
+
+/*
+ * Module: library/rsa.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ * library/ssl_tls.c
+ * library/x509.c
+ *
+ * This module is required for SSL/TLS and MD5-signed certificates.
+ */
+#define POLARSSL_RSA_C
+
+/*
+ * Module: library/sha1.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ * library/ssl_tls.c
+ * library/x509parse.c
+ *
+ * This module is required for SSL/TLS and SHA1-signed certificates.
+ */
+#define POLARSSL_SHA1_C
+
+/*
+ * Module: library/sha2.c
+ * Caller:
+ *
+ * This module adds support for SHA-224 and SHA-256.
+ */
+#define POLARSSL_SHA2_C
+
+/*
+ * Module: library/sha4.c
+ * Caller:
+ *
+ * This module adds support for SHA-384 and SHA-512.
+ */
+#define POLARSSL_SHA4_C
+
+/*
+ * Module: library/ssl_cli.c
+ * Caller:
+ *
+ * This module is required for SSL/TLS client support.
+ */
+#define POLARSSL_SSL_CLI_C
+
+/*
+ * Module: library/ssl_srv.c
+ * Caller:
+ *
+ * This module is required for SSL/TLS server support.
+ */
+#define POLARSSL_SSL_SRV_C
+
+/*
+ * Module: library/ssl_tls.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ *
+ * This module is required for SSL/TLS.
+ */
+#define POLARSSL_SSL_TLS_C
+
+/*
+ * Module: library/timing.c
+ * Caller: library/havege.c
+ *
+ * This module is used by the HAVEGE random number generator.
+ */
+#define POLARSSL_TIMING_C
+
+/*
+ * Module: library/x509parse.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ * library/ssl_tls.c
+ *
+ * This module is required for X.509 certificate parsing.
+ */
+#define POLARSSL_X509_PARSE_C
+
+/*
+ * Module: library/x509_write.c
+ * Caller:
+ *
+ * This module is required for X.509 certificate writing.
+ */
+#define POLARSSL_X509_WRITE_C
+
+/*
+ * Module: library/xtea.c
+ * Caller:
+ */
+#define POLARSSL_XTEA_C
+
+#endif /* config.h */
diff --git a/package/px5g/src/polarssl/havege.h b/package/px5g/src/polarssl/havege.h
new file mode 100644
index 000000000..c27cecac0
--- /dev/null
+++ b/package/px5g/src/polarssl/havege.h
@@ -0,0 +1,75 @@
+/**
+ * \file havege.h
+ *
+ * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
+ *
+ * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the names of PolarSSL or XySSL 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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 POLARSSL_HAVEGE_H
+#define POLARSSL_HAVEGE_H
+
+#define COLLECT_SIZE 1024
+
+/**
+ * \brief HAVEGE state structure
+ */
+typedef struct
+{
+ int PT1, PT2, offset[2];
+ int pool[COLLECT_SIZE];
+ int WALK[8192];
+}
+havege_state;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief HAVEGE initialization
+ *
+ * \param hs HAVEGE state to be initialized
+ */
+void havege_init( havege_state *hs );
+
+/**
+ * \brief HAVEGE rand function
+ *
+ * \param rng_st points to an HAVEGE state
+ *
+ * \return A random int
+ */
+int havege_rand( void *p_rng );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* havege.h */
diff --git a/package/px5g/src/polarssl/rsa.h b/package/px5g/src/polarssl/rsa.h
new file mode 100644
index 000000000..b31dc2f14
--- /dev/null
+++ b/package/px5g/src/polarssl/rsa.h
@@ -0,0 +1,309 @@
+/**
+ * \file rsa.h
+ *
+ * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
+ *
+ * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the names of PolarSSL or XySSL 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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 POLARSSL_RSA_H
+#define POLARSSL_RSA_H
+
+#include "polarssl/bignum.h"
+
+#define POLARSSL_ERR_RSA_BAD_INPUT_DATA -0x0400
+#define POLARSSL_ERR_RSA_INVALID_PADDING -0x0410
+#define POLARSSL_ERR_RSA_KEY_GEN_FAILED -0x0420
+#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED -0x0430
+#define POLARSSL_ERR_RSA_PUBLIC_FAILED -0x0440
+#define POLARSSL_ERR_RSA_PRIVATE_FAILED -0x0450
+#define POLARSSL_ERR_RSA_VERIFY_FAILED -0x0460
+#define POLARSSL_ERR_RSA_OUTPUT_TO_LARGE -0x0470
+
+/*
+ * PKCS#1 constants
+ */
+#define RSA_RAW 0
+#define RSA_MD2 2
+#define RSA_MD4 3
+#define RSA_MD5 4
+#define RSA_SHA1 5
+#define RSA_SHA256 6
+
+#define RSA_PUBLIC 0
+#define RSA_PRIVATE 1
+
+#define RSA_PKCS_V15 0
+#define RSA_PKCS_V21 1
+
+#define RSA_SIGN 1
+#define RSA_CRYPT 2
+
+/*
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm DigestAlgorithmIdentifier,
+ * digest Digest }
+ *
+ * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * Digest ::= OCTET STRING
+ */
+#define ASN1_HASH_MDX \
+ "\x30\x20\x30\x0C\x06\x08\x2A\x86\x48" \
+ "\x86\xF7\x0D\x02\x00\x05\x00\x04\x10"
+
+#define ASN1_HASH_SHA1 \
+ "\x30\x21\x30\x09\x06\x05\x2B\x0E\x03" \
+ "\x02\x1A\x05\x00\x04\x14"
+
+/**
+ * \brief RSA context structure
+ */
+typedef struct
+{
+ int ver; /*!< always 0 */
+ int len; /*!< size(N) in chars */
+
+ mpi N; /*!< public modulus */
+ mpi E; /*!< public exponent */
+
+ mpi D; /*!< private exponent */
+ mpi P; /*!< 1st prime factor */
+ mpi Q; /*!< 2nd prime factor */
+ mpi DP; /*!< D % (P - 1) */
+ mpi DQ; /*!< D % (Q - 1) */
+ mpi QP; /*!< 1 / (Q % P) */
+
+ mpi RN; /*!< cached R^2 mod N */
+ mpi RP; /*!< cached R^2 mod P */
+ mpi RQ; /*!< cached R^2 mod Q */
+
+ int padding; /*!< 1.5 or OAEP/PSS */
+ int hash_id; /*!< hash identifier */
+ int (*f_rng)(void *); /*!< RNG function */
+ void *p_rng; /*!< RNG parameter */
+}
+rsa_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Initialize an RSA context
+ *
+ * \param ctx RSA context to be initialized
+ * \param padding RSA_PKCS_V15 or RSA_PKCS_V21
+ * \param hash_id RSA_PKCS_V21 hash identifier
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \note The hash_id parameter is actually ignored
+ * when using RSA_PKCS_V15 padding.
+ *
+ * \note Currently (xyssl-0.8), RSA_PKCS_V21 padding
+ * is not supported.
+ */
+void rsa_init( rsa_context *ctx,
+ int padding,
+ int hash_id,
+ int (*f_rng)(void *),
+ void *p_rng );
+
+/**
+ * \brief Generate an RSA keypair
+ *
+ * \param ctx RSA context that will hold the key
+ * \param nbits size of the public key in bits
+ * \param exponent public exponent (e.g., 65537)
+ *
+ * \note rsa_init() must be called beforehand to setup
+ * the RSA context (especially f_rng and p_rng).
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ */
+int rsa_gen_key( rsa_context *ctx, int nbits, int exponent );
+
+/**
+ * \brief Check a public RSA key
+ *
+ * \param ctx RSA context to be checked
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ */
+int rsa_check_pubkey( rsa_context *ctx );
+
+/**
+ * \brief Check a private RSA key
+ *
+ * \param ctx RSA context to be checked
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ */
+int rsa_check_privkey( rsa_context *ctx );
+
+/**
+ * \brief Do an RSA public key operation
+ *
+ * \param ctx RSA context
+ * \param input input buffer
+ * \param output output buffer
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note This function does NOT take care of message
+ * padding. Also, be sure to set input[0] = 0.
+ *
+ * \note The input and output buffers must be large
+ * enough (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_public( rsa_context *ctx,
+ unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief Do an RSA private key operation
+ *
+ * \param ctx RSA context
+ * \param input input buffer
+ * \param output output buffer
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The input and output buffers must be large
+ * enough (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_private( rsa_context *ctx,
+ unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief Add the message padding, then do an RSA operation
+ *
+ * \param ctx RSA context
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param ilen contains the the plaintext length
+ * \param input buffer holding the data to be encrypted
+ * \param output buffer that will hold the ciphertext
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The output buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_pkcs1_encrypt( rsa_context *ctx,
+ int mode, int ilen,
+ unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief Do an RSA operation, then remove the message padding
+ *
+ * \param ctx RSA context
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param input buffer holding the encrypted data
+ * \param output buffer that will hold the plaintext
+ * \param olen will contain the plaintext length
+ * \param output_max_len maximum length of the output buffer
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The output buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
+ * an error is thrown.
+ */
+int rsa_pkcs1_decrypt( rsa_context *ctx,
+ int mode, int *olen,
+ unsigned char *input,
+ unsigned char *output,
+ int output_max_len);
+
+/**
+ * \brief Do a private RSA to sign a message digest
+ *
+ * \param ctx RSA context
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param hash_id RSA_RAW, RSA_MD{2,4,5} or RSA_SHA{1,256}
+ * \param hashlen message digest length (for RSA_RAW only)
+ * \param hash buffer holding the message digest
+ * \param sig buffer that will hold the ciphertext
+ *
+ * \return 0 if the signing operation was successful,
+ * or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The "sig" buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_pkcs1_sign( rsa_context *ctx,
+ int mode,
+ int hash_id,
+ int hashlen,
+ unsigned char *hash,
+ unsigned char *sig );
+
+/**
+ * \brief Do a public RSA and check the message digest
+ *
+ * \param ctx points to an RSA public key
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param hash_id RSA_RAW, RSA_MD{2,4,5} or RSA_SHA{1,256}
+ * \param hashlen message digest length (for RSA_RAW only)
+ * \param hash buffer holding the message digest
+ * \param sig buffer holding the ciphertext
+ *
+ * \return 0 if the verify operation was successful,
+ * or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The "sig" buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_pkcs1_verify( rsa_context *ctx,
+ int mode,
+ int hash_id,
+ int hashlen,
+ unsigned char *hash,
+ unsigned char *sig );
+
+/**
+ * \brief Free the components of an RSA key
+ */
+void rsa_free( rsa_context *ctx );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int rsa_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* rsa.h */
diff --git a/package/px5g/src/polarssl/sha1.h b/package/px5g/src/polarssl/sha1.h
new file mode 100644
index 000000000..3ca7dc319
--- /dev/null
+++ b/package/px5g/src/polarssl/sha1.h
@@ -0,0 +1,150 @@
+/**
+ * \file sha1.h
+ *
+ * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
+ *
+ * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the names of PolarSSL or XySSL 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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 POLARSSL_SHA1_H
+#define POLARSSL_SHA1_H
+
+/**
+ * \brief SHA-1 context structure
+ */
+typedef struct
+{
+ unsigned long total[2]; /*!< number of bytes processed */
+ unsigned long state[5]; /*!< intermediate digest state */
+ unsigned char buffer[64]; /*!< data block being processed */
+
+ unsigned char ipad[64]; /*!< HMAC: inner padding */
+ unsigned char opad[64]; /*!< HMAC: outer padding */
+}
+sha1_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief SHA-1 context setup
+ *
+ * \param ctx context to be initialized
+ */
+void sha1_starts( sha1_context *ctx );
+
+/**
+ * \brief SHA-1 process buffer
+ *
+ * \param ctx SHA-1 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void sha1_update( sha1_context *ctx, unsigned char *input, int ilen );
+
+/**
+ * \brief SHA-1 final digest
+ *
+ * \param ctx SHA-1 context
+ * \param output SHA-1 checksum result
+ */
+void sha1_finish( sha1_context *ctx, unsigned char output[20] );
+
+/**
+ * \brief Output = SHA-1( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output SHA-1 checksum result
+ */
+void sha1( unsigned char *input, int ilen, unsigned char output[20] );
+
+/**
+ * \brief Output = SHA-1( file contents )
+ *
+ * \param path input file name
+ * \param output SHA-1 checksum result
+ *
+ * \return 0 if successful, 1 if fopen failed,
+ * or 2 if fread failed
+ */
+int sha1_file( char *path, unsigned char output[20] );
+
+/**
+ * \brief SHA-1 HMAC context setup
+ *
+ * \param ctx HMAC context to be initialized
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ */
+void sha1_hmac_starts( sha1_context *ctx, unsigned char *key, int keylen );
+
+/**
+ * \brief SHA-1 HMAC process buffer
+ *
+ * \param ctx HMAC context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void sha1_hmac_update( sha1_context *ctx, unsigned char *input, int ilen );
+
+/**
+ * \brief SHA-1 HMAC final digest
+ *
+ * \param ctx HMAC context
+ * \param output SHA-1 HMAC checksum result
+ */
+void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] );
+
+/**
+ * \brief Output = HMAC-SHA-1( hmac key, input buffer )
+ *
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output HMAC-SHA-1 result
+ */
+void sha1_hmac( unsigned char *key, int keylen,
+ unsigned char *input, int ilen,
+ unsigned char output[20] );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int sha1_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* sha1.h */
diff --git a/package/px5g/src/polarssl/timing.h b/package/px5g/src/polarssl/timing.h
new file mode 100644
index 000000000..62d627f61
--- /dev/null
+++ b/package/px5g/src/polarssl/timing.h
@@ -0,0 +1,81 @@
+/**
+ * \file timing.h
+ *
+ * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
+ *
+ * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the names of PolarSSL or XySSL 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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 POLARSSL_TIMING_H
+#define POLARSSL_TIMING_H
+
+/**
+ * \brief timer structure
+ */
+struct hr_time
+{
+ unsigned char opaque[32];
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int alarmed;
+
+/**
+ * \brief Return the CPU cycle counter value
+ */
+unsigned long hardclock( void );
+
+/**
+ * \brief Return the elapsed time in milliseconds
+ *
+ * \param val points to a timer structure
+ * \param reset if set to 1, the timer is restarted
+ */
+unsigned long get_timer( struct hr_time *val, int reset );
+
+/**
+ * \brief Setup an alarm clock
+ *
+ * \param seconds delay before the "alarmed" flag is set
+ */
+void set_alarm( int seconds );
+
+/**
+ * \brief Sleep for a certain amount of time
+ */
+void m_sleep( int milliseconds );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* timing.h */
diff --git a/package/px5g/src/polarssl/x509.h b/package/px5g/src/polarssl/x509.h
new file mode 100644
index 000000000..908a1dbf5
--- /dev/null
+++ b/package/px5g/src/polarssl/x509.h
@@ -0,0 +1,549 @@
+/**
+ * \file x509.h
+ *
+ * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
+ *
+ * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the names of PolarSSL or XySSL 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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 POLARSSL_X509_H
+#define POLARSSL_X509_H
+
+#include "polarssl/rsa.h"
+
+#define POLARSSL_ERR_ASN1_OUT_OF_DATA -0x0014
+#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG -0x0016
+#define POLARSSL_ERR_ASN1_INVALID_LENGTH -0x0018
+#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH -0x001A
+#define POLARSSL_ERR_ASN1_INVALID_DATA -0x001C
+
+#define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE -0x0020
+#define POLARSSL_ERR_X509_CERT_INVALID_PEM -0x0040
+#define POLARSSL_ERR_X509_CERT_INVALID_FORMAT -0x0060
+#define POLARSSL_ERR_X509_CERT_INVALID_VERSION -0x0080
+#define POLARSSL_ERR_X509_CERT_INVALID_SERIAL -0x00A0
+#define POLARSSL_ERR_X509_CERT_INVALID_ALG -0x00C0
+#define POLARSSL_ERR_X509_CERT_INVALID_NAME -0x00E0
+#define POLARSSL_ERR_X509_CERT_INVALID_DATE -0x0100
+#define POLARSSL_ERR_X509_CERT_INVALID_PUBKEY -0x0120
+#define POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE -0x0140
+#define POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS -0x0160
+#define POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION -0x0180
+#define POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG -0x01A0
+#define POLARSSL_ERR_X509_CERT_UNKNOWN_PK_ALG -0x01C0
+#define POLARSSL_ERR_X509_CERT_SIG_MISMATCH -0x01E0
+#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED -0x0200
+#define POLARSSL_ERR_X509_KEY_INVALID_PEM -0x0220
+#define POLARSSL_ERR_X509_KEY_INVALID_VERSION -0x0240
+#define POLARSSL_ERR_X509_KEY_INVALID_FORMAT -0x0260
+#define POLARSSL_ERR_X509_KEY_INVALID_ENC_IV -0x0280
+#define POLARSSL_ERR_X509_KEY_UNKNOWN_ENC_ALG -0x02A0
+#define POLARSSL_ERR_X509_KEY_PASSWORD_REQUIRED -0x02C0
+#define POLARSSL_ERR_X509_KEY_PASSWORD_MISMATCH -0x02E0
+#define POLARSSL_ERR_X509_POINT_ERROR -0x0300
+#define POLARSSL_ERR_X509_VALUE_TO_LENGTH -0x0320
+
+#define BADCERT_EXPIRED 1
+#define BADCERT_REVOKED 2
+#define BADCERT_CN_MISMATCH 4
+#define BADCERT_NOT_TRUSTED 8
+
+/*
+ * DER constants
+ */
+#define ASN1_BOOLEAN 0x01
+#define ASN1_INTEGER 0x02
+#define ASN1_BIT_STRING 0x03
+#define ASN1_OCTET_STRING 0x04
+#define ASN1_NULL 0x05
+#define ASN1_OID 0x06
+#define ASN1_UTF8_STRING 0x0C
+#define ASN1_SEQUENCE 0x10
+#define ASN1_SET 0x11
+#define ASN1_PRINTABLE_STRING 0x13
+#define ASN1_T61_STRING 0x14
+#define ASN1_IA5_STRING 0x16
+#define ASN1_UTC_TIME 0x17
+#define ASN1_UNIVERSAL_STRING 0x1C
+#define ASN1_BMP_STRING 0x1E
+#define ASN1_PRIMITIVE 0x00
+#define ASN1_CONSTRUCTED 0x20
+#define ASN1_CONTEXT_SPECIFIC 0x80
+
+/*
+ * various object identifiers
+ */
+#define X520_COMMON_NAME 3
+#define X520_COUNTRY 6
+#define X520_LOCALITY 7
+#define X520_STATE 8
+#define X520_ORGANIZATION 10
+#define X520_ORG_UNIT 11
+#define PKCS9_EMAIL 1
+
+#define X509_OUTPUT_DER 0x01
+#define X509_OUTPUT_PEM 0x02
+#define PEM_LINE_LENGTH 72
+#define X509_ISSUER 0x01
+#define X509_SUBJECT 0x02
+
+#define OID_X520 "\x55\x04"
+#define OID_CN "\x55\x04\x03"
+#define OID_PKCS1 "\x2A\x86\x48\x86\xF7\x0D\x01\x01"
+#define OID_PKCS1_RSA "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01"
+#define OID_PKCS1_RSA_SHA "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05"
+#define OID_PKCS9 "\x2A\x86\x48\x86\xF7\x0D\x01\x09"
+#define OID_PKCS9_EMAIL "\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01"
+
+/*
+ * Structures for parsing X.509 certificates
+ */
+typedef struct _x509_buf
+{
+ int tag;
+ int len;
+ unsigned char *p;
+}
+x509_buf;
+
+typedef struct _x509_name
+{
+ x509_buf oid;
+ x509_buf val;
+ struct _x509_name *next;
+}
+x509_name;
+
+typedef struct _x509_time
+{
+ int year, mon, day;
+ int hour, min, sec;
+}
+x509_time;
+
+typedef struct _x509_cert
+{
+ x509_buf raw;
+ x509_buf tbs;
+
+ int version;
+ x509_buf serial;
+ x509_buf sig_oid1;
+
+ x509_buf issuer_raw;
+ x509_buf subject_raw;
+
+ x509_name issuer;
+ x509_name subject;
+
+ x509_time valid_from;
+ x509_time valid_to;
+
+ x509_buf pk_oid;
+ rsa_context rsa;
+
+ x509_buf issuer_id;
+ x509_buf subject_id;
+ x509_buf v3_ext;
+
+ int ca_istrue;
+ int max_pathlen;
+
+ x509_buf sig_oid2;
+ x509_buf sig;
+
+ struct _x509_cert *next;
+}
+x509_cert;
+
+/*
+ * Structures for writing X.509 certificates
+ */
+typedef struct _x509_node
+{
+ unsigned char *data;
+ unsigned char *p;
+ unsigned char *end;
+
+ size_t len;
+}
+x509_node;
+
+typedef struct _x509_raw
+{
+ x509_node raw;
+ x509_node tbs;
+
+ x509_node version;
+ x509_node serial;
+ x509_node tbs_signalg;
+ x509_node issuer;
+ x509_node validity;
+ x509_node subject;
+ x509_node subpubkey;
+
+ x509_node signalg;
+ x509_node sign;
+}
+x509_raw;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Parse one or more certificates and add them
+ * to the chained list
+ *
+ * \param chain points to the start of the chain
+ * \param buf buffer holding the certificate data
+ * \param buflen size of the buffer
+ *
+ * \return 0 if successful, or a specific X509 error code
+ */
+int x509parse_crt( x509_cert *crt, unsigned char *buf, int buflen );
+
+/**
+ * \brief Load one or more certificates and add them
+ * to the chained list
+ *
+ * \param chain points to the start of the chain
+ * \param path filename to read the certificates from
+ *
+ * \return 0 if successful, or a specific X509 error code
+ */
+int x509parse_crtfile( x509_cert *crt, char *path );
+
+/**
+ * \brief Parse a private RSA key
+ *
+ * \param rsa RSA context to be initialized
+ * \param buf input buffer
+ * \param buflen size of the buffer
+ * \param pwd password for decryption (optional)
+ * \param pwdlen size of the password
+ *
+ * \return 0 if successful, or a specific X509 error code
+ */
+int x509parse_key( rsa_context *rsa,
+ unsigned char *buf, int buflen,
+ unsigned char *pwd, int pwdlen );
+
+/**
+ * \brief Load and parse a private RSA key
+ *
+ * \param rsa RSA context to be initialized
+ * \param path filename to read the private key from
+ * \param pwd password to decrypt the file (can be NULL)
+ *
+ * \return 0 if successful, or a specific X509 error code
+ */
+int x509parse_keyfile( rsa_context *rsa, char *path, char *password );
+
+/**
+ * \brief Store the certificate DN in printable form into buf;
+ * no more than (end - buf) characters will be written.
+ */
+int x509parse_dn_gets( char *buf, char *end, x509_name *dn );
+
+/**
+ * \brief Returns an informational string about the
+ * certificate.
+ */
+char *x509parse_cert_info( char *prefix, x509_cert *crt );
+
+/**
+ * \brief Return 0 if the certificate is still valid,
+ * or BADCERT_EXPIRED
+ */
+int x509parse_expired( x509_cert *crt );
+
+/**
+ * \brief Verify the certificate signature
+ *
+ * \param crt a certificate to be verified
+ * \param trust_ca the trusted CA chain
+ * \param cn expected Common Name (can be set to
+ * NULL if the CN must not be verified)
+ * \param flags result of the verification
+ *
+ * \return 0 if successful or POLARSSL_ERR_X509_SIG_VERIFY_FAILED,
+ * in which case *flags will have one or more of
+ * the following values set:
+ * BADCERT_EXPIRED --
+ * BADCERT_REVOKED --
+ * BADCERT_CN_MISMATCH --
+ * BADCERT_NOT_TRUSTED
+ *
+ * \note TODO: add two arguments, depth and crl
+ */
+int x509parse_verify( x509_cert *crt,
+ x509_cert *trust_ca,
+ char *cn, int *flags );
+
+/**
+ * \brief Unallocate all certificate data
+ */
+void x509_free( x509_cert *crt );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int x509_self_test( int verbose );
+
+/**
+ * \brief Write a certificate info file
+ *
+ * \param chain points to the raw certificate data
+ * \param path filename to write the certificate to
+ * \param format X509_OUTPUT_DER or X509_OUTPUT_PEM
+ *
+ * \return 0 if successful, or a specific X509 error code
+ */
+int x509write_crtfile( x509_raw *chain,
+ unsigned char *path,
+ int format );
+
+/**
+ * \brief Write a certificate signing request message format file
+ *
+ * \param chain points to the raw certificate (with x509write_create_csr) data
+ * \param path filename to write the certificate to
+ * \param format X509_OUTPUT_DER or X509_OUTPUT_PEM
+ *
+ * \return 0 if successful, or a specific X509 error code
+ */
+int x509write_csrfile( x509_raw *chain,
+ unsigned char *path,
+ int format );
+
+/*
+ * \brief Write a private RSA key into a file
+ *
+ * \param rsa points to an RSA key
+ * \param path filename to write the key to
+ * \param format X509_OUTPUT_DER or X509_OUTPUT_PEM
+ *
+ * \return 0 if successful, or a specific X509 error code
+ */
+int x509write_keyfile( rsa_context *rsa,
+ char *path,
+ int format );
+
+/**
+ * \brief Add a public key to certificate
+ *
+ * \param chain points to the raw certificate data
+ * \param pubkey points to an RSA key
+ *
+ * \return 0 if successful, or a specific X509 error code
+ */
+int x509write_add_pubkey( x509_raw *chain, rsa_context *pubkey );
+
+/**
+ * \brief Create x509 subject/issuer field to raw certificate
+ * from string or CA cert. Make string NULL if you will
+ * use the CA copy function or make CA NULL then used
+ * the string parse.
+ *
+ * \param chain points to the raw certificate data
+ * \param names a string that can hold (separete with ";"):
+ * CN=CommonName
+ * -- O=Organization
+ * -- OU=OrgUnit
+ * -- ST=State
+ * -- L=Locality
+ * -- R=Email
+ * -- C=Country
+ * . Make that NULL if you didn't need that.
+ * \param flag flag is X509_ISSUER or X509_SUBJECT that defined
+ * where change
+ * \param ca the certificate for copy data. Make that NULL if you
+ * didn't need that.
+ * \param ca_flag set the ca field from copy to crt
+ *
+ * \return 0 if successful, or a specific X509 error code
+ */
+int x509write_add_customize ( x509_raw *crt,
+ unsigned char *names,
+ int flag,
+ x509_cert *ca,
+ int ca_flag );
+
+/**
+* \brief Add x509 issuer field
+*
+* \param chain points to the raw certificate data
+* \param issuer a string holding (separete with ";"):
+* CN=CommonName
+* -- O=Organization
+* -- OU=OrgUnit
+* -- ST=State
+* -- L=Locality
+* -- R=Email
+* -- C=Country
+* . Set this to NULL if not needed.
+* \return 0 if successful, or a specific X509 error code
+*/
+int x509write_add_issuer( x509_raw *crt, unsigned char *issuer);
+
+/**
+ * \brief Add x509 subject field
+ *
+ * \param chain points to the raw certificate data
+ * \param subject a string holding (separete with ";"):
+ * CN=CommonName
+ * -- O=Organization
+ * -- OU=OrgUnit
+ * -- ST=State
+ * -- L=Locality
+ * -- R=Email
+ * -- C=Country
+ * . Set this to NULL if not needed.
+ * \return 0 if successful, or a specific X509 error code
+ */
+int x509write_add_subject( x509_raw *crt, unsigned char *subject);
+
+/**
+* \brief Copy x509 issuer field from another certificate
+*
+* \param chain points to the raw certificate data
+* \param from_crt the certificate whose issuer is to be copied.
+* \return 0 if successful, or a specific X509 error code
+*/
+int x509write_copy_issuer(x509_raw *crt, x509_cert *from_crt);
+
+/**
+* \brief Copy x509 subject field from another certificate
+*
+* \param chain points to the raw certificate data
+* \param from_crt the certificate whose subject is to be copied.
+* \return 0 if successful, or a specific X509 error code
+*/
+int x509write_copy_subject(x509_raw *crt, x509_cert *from_crt);
+
+/**
+* \brief Copy x509 issuer field from the subject of another certificate
+*
+* \param chain points to the raw certificate data
+* \param from_crt the certificate whose subject is to be copied.
+* \return 0 if successful, or a specific X509 error code
+*/
+int x509write_copy_issuer_from_subject(x509_raw *crt, x509_cert *from_crt);
+
+/**
+* \brief Copy x509 subject field from the issuer of another certificate
+*
+* \param chain points to the raw certificate data
+* \param from_crt the certificate whose issuer is to be copied.
+* \return 0 if successful, or a specific X509 error code
+*/
+int x509write_copy_subject_from_issuer(x509_raw *crt, x509_cert *from_crt);
+
+/**
+ * \brief Create x509 validity time in UTC
+ *
+ * \param chain points to the raw certificate data
+ * \param before valid not before in format YYYY-MM-DD hh:mm:ss
+ * \param after valid not after in format YYYY-MM-DD hh:mm:ss
+ *
+ * \return 0 if successful, or a specific X509 error code
+ */
+int x509write_add_validity( x509_raw *crt,
+ unsigned char *before,
+ unsigned char *after );
+
+/**
+ * \brief Create a self-signed certificate
+ *
+ * \param chain points to the raw certificate data
+ * \param rsa a private key to sign the certificate
+ *
+ * \return 0 if successful, or a specific X509 error code
+ */
+int x509write_create_selfsign( x509_raw *crt, rsa_context *raw );
+
+/**
+ * \brief Create a certificate
+ *
+ * \param chain points to the raw certificate data
+ * \param rsa a private key to sign the certificate
+ *
+ * \return 0 if successful, or a specific X509 error code
+ */
+int x509write_create_sign( x509_raw *crt, rsa_context *raw );
+
+/**
+ * \brief Create a certificate signing request
+ *
+ * \param chain points to the raw certificate data. Didn't use the
+ * same chain that u have use for certificate.
+ * \param privkey a rsa private key
+ *
+ * \return 0 if successful, or a specific X509 error code
+ */
+int x509write_create_csr( x509_raw *chain, rsa_context *privkey );
+
+/**
+ * \brief Serialize an rsa key into DER
+ *
+ * \param rsa a rsa key for output
+ * \param node a x509 node for write into
+ *
+ * \return 0 if successful, or a specific X509 error code
+ */
+int x509write_serialize_key( rsa_context *rsa, x509_node *node );
+
+/**
+ * \brief Unallocate all raw certificate data
+ */
+void x509write_free_raw( x509_raw *crt );
+
+/**
+ * \brief Allocate all raw certificate data
+ */
+void x509write_init_raw( x509_raw *crt );
+
+/**
+ * \brief Unallocate all node certificate data
+ */
+void x509write_free_node( x509_node *crt_node );
+
+/**
+ * \brief Allocate all node certificate data
+ */
+void x509write_init_node( x509_node *crt_node );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* x509.h */
diff --git a/package/px5g/src/px5g.c b/package/px5g/src/px5g.c
new file mode 100644
index 000000000..2b3e78585
--- /dev/null
+++ b/package/px5g/src/px5g.c
@@ -0,0 +1,197 @@
+/*
+ * px5g - Embedded x509 key and certificate generator based on PolarSSL
+ *
+ * Copyright (C) 2009 Steven Barth <steven@midlink.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License, version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "polarssl/havege.h"
+#include "polarssl/bignum.h"
+#include "polarssl/x509.h"
+#include "polarssl/rsa.h"
+
+#define PX5G_VERSION "0.1"
+#define PX5G_COPY "Copyright (c) 2009 Steven Barth <steven@midlink.org>"
+#define PX5G_LICENSE "Licensed under the GNU Lesser General Public License v2.1"
+
+int rsakey(char **arg) {
+ havege_state hs;
+ rsa_context rsa;
+
+ unsigned int ksize = 512;
+ int exp = 65537;
+ char *path = NULL;
+ int flag = X509_OUTPUT_PEM;
+
+ while (*arg && **arg == '-') {
+ if (!strcmp(*arg, "-out") && arg[1]) {
+ path = arg[1];
+ arg++;
+ } else if (!strcmp(*arg, "-3")) {
+ exp = 3;
+ } else if (!strcmp(*arg, "-der")) {
+ flag = X509_OUTPUT_DER;
+ }
+ arg++;
+ }
+
+ if (*arg) {
+ ksize = (unsigned int)atoi(*arg);
+ }
+
+ havege_init(&hs);
+ rsa_init(&rsa, RSA_PKCS_V15, 0, havege_rand, &hs);
+
+ fprintf(stderr, "Generating RSA private key, %i bit long modulus\n", ksize);
+ if (rsa_gen_key(&rsa, ksize, exp)) {
+ fprintf(stderr, "error: key generation failed\n");
+ return 1;
+ }
+
+ if (x509write_keyfile(&rsa, path, flag)) {
+ fprintf(stderr, "error: I/O error\n");
+ return 1;
+ }
+
+ rsa_free(&rsa);
+ return 0;
+}
+
+int selfsigned(char **arg) {
+ havege_state hs;
+ rsa_context rsa;
+ x509_node node;
+
+ char *subject = "";
+ unsigned int ksize = 512;
+ int exp = 65537;
+ unsigned int days = 30;
+ char *keypath = NULL, *certpath = NULL;
+ int flag = X509_OUTPUT_PEM;
+ time_t from = time(NULL), to;
+ char fstr[20], tstr[20];
+
+ while (*arg && **arg == '-') {
+ if (!strcmp(*arg, "-der")) {
+ flag = X509_OUTPUT_DER;
+ } else if (!strcmp(*arg, "-newkey") && arg[1]) {
+ if (strncmp(arg[1], "rsa:", 4)) {
+ fprintf(stderr, "error: invalid algorithm");
+ return 1;
+ }
+ ksize = (unsigned int)atoi(arg[1] + 4);
+ arg++;
+ } else if (!strcmp(*arg, "-days") && arg[1]) {
+ days = (unsigned int)atoi(arg[1]);
+ arg++;
+ } else if (!strcmp(*arg, "-keyout") && arg[1]) {
+ keypath = arg[1];
+ arg++;
+ } else if (!strcmp(*arg, "-out") && arg[1]) {
+ certpath = arg[1];
+ arg++;
+ } else if (!strcmp(*arg, "-subj") && arg[1]) {
+ if (arg[1][0] != '/' || strchr(arg[1], ';')) {
+ fprintf(stderr, "error: invalid subject");
+ return 1;
+ }
+ subject = calloc(strlen(arg[1]) + 1, 1);
+ char *oldc = arg[1] + 1, *newc = subject, *delim;
+ do {
+ delim = strchr(oldc, '=');
+ if (!delim) {
+ fprintf(stderr, "error: invalid subject");
+ return 1;
+ }
+ memcpy(newc, oldc, delim - oldc + 1);
+ newc += delim - oldc + 1;
+ oldc = delim + 1;
+
+ delim = strchr(oldc, '/');
+ if (!delim) {
+ delim = arg[1] + strlen(arg[1]);
+ }
+ memcpy(newc, oldc, delim - oldc);
+ newc += delim - oldc;
+ *newc++ = ';';
+ oldc = delim + 1;
+ } while(*delim);
+ arg++;
+ }
+ arg++;
+ }
+
+ havege_init(&hs);
+ rsa_init(&rsa, RSA_PKCS_V15, 0, havege_rand, &hs);
+ x509write_init_node(&node);
+ fprintf(stderr, "Generating RSA private key, %i bit long modulus\n", ksize);
+ if (rsa_gen_key(&rsa, ksize, exp)) {
+ fprintf(stderr, "error: key generation failed\n");
+ return 1;
+ }
+
+ if (keypath) {
+ if (x509write_keyfile(&rsa, keypath, flag)) {
+ fprintf(stderr, "error: I/O error\n");
+ return 1;
+ }
+ }
+
+ from = (from < 1000000000) ? 1000000000 : from;
+ strftime(fstr, sizeof(fstr), "%F %H:%M:%S", gmtime(&from));
+ to = from + 60 * 60 * 24 * days;
+ strftime(tstr, sizeof(tstr), "%F %H:%M:%S", gmtime(&to));
+
+ x509_raw cert;
+ x509write_init_raw(&cert);
+ x509write_add_pubkey(&cert, &rsa);
+ x509write_add_subject(&cert, (unsigned char*)subject);
+ x509write_add_validity(&cert, (unsigned char*)fstr, (unsigned char*)tstr);
+ fprintf(stderr, "Generating selfsigned certificate with subject '%s'"
+ " and validity %s-%s\n", subject, fstr, tstr);
+ if (x509write_create_selfsign(&cert, &rsa)) {
+ fprintf(stderr, "error: certificate generation failed\n");
+ }
+
+ if (x509write_crtfile(&cert, (unsigned char*)certpath, flag)) {
+ fprintf(stderr, "error: I/O error\n");
+ return 1;
+ }
+
+ x509write_free_raw(&cert);
+ rsa_free(&rsa);
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ if (!argv[1]) {
+ //Usage
+ } else if (!strcmp(argv[1], "rsakey")) {
+ return rsakey(argv+2);
+ } else if (!strcmp(argv[1], "selfsigned")) {
+ return selfsigned(argv+2);
+ }
+
+ fprintf(stderr,
+ "PX5G X.509 Certificate Generator Utility v" PX5G_VERSION "\n" PX5G_COPY
+ "\nbased on PolarSSL by Christophe Devine and Paul Bakker\n\n");
+ fprintf(stderr, "Usage: %s [rsakey|selfsigned]\n", *argv);
+ return 1;
+}
diff --git a/package/qos-scripts/Makefile b/package/qos-scripts/Makefile
new file mode 100644
index 000000000..be2a5a8ed
--- /dev/null
+++ b/package/qos-scripts/Makefile
@@ -0,0 +1,50 @@
+#
+# Copyright (C) 2006-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=qos-scripts
+PKG_VERSION:=1.2.1
+PKG_RELEASE:=6
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/qos-scripts
+ SECTION:=utils
+ CATEGORY:=Base system
+ DEPENDS:=+tc +kmod-sched-core +kmod-sched-connmark +kmod-ifb +iptables +iptables-mod-filter +iptables-mod-ipopt +iptables-mod-conntrack-extra
+ TITLE:=QoS scripts
+ PKGARCH:=all
+endef
+
+define Package/qos-scripts/description
+ A set of scripts that abstract QoS configuration into a simple
+ configuration file supporting stanzas that specify any number of QoS
+ entries.
+endef
+
+define Package/qos-scripts/conffiles
+/etc/config/qos
+endef
+
+define Build/Prepare
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+endef
+
+define Package/qos-scripts/install
+ $(INSTALL_DIR) $(1)
+ $(CP) ./files/* $(1)/
+endef
+
+$(eval $(call BuildPackage,qos-scripts))
diff --git a/package/qos-scripts/files/etc/config/qos b/package/qos-scripts/files/etc/config/qos
new file mode 100644
index 000000000..8faff1834
--- /dev/null
+++ b/package/qos-scripts/files/etc/config/qos
@@ -0,0 +1,79 @@
+# QoS configuration for OpenWrt
+
+# INTERFACES:
+config interface wan
+ option classgroup "Default"
+ option enabled 0
+ option upload 128
+ option download 1024
+
+# RULES:
+config classify
+ option target "Priority"
+ option ports "22,53"
+config classify
+ option target "Normal"
+ option proto "tcp"
+ option ports "20,21,25,80,110,443,993,995"
+config classify
+ option target "Express"
+ option ports "5190"
+config default
+ option target "Express"
+ option proto "udp"
+ option pktsize "-500"
+config reclassify
+ option target "Priority"
+ option proto "icmp"
+config default
+ option target "Bulk"
+ option portrange "1024-65535"
+config reclassify
+ option target "Priority"
+ option proto "tcp"
+ option pktsize "-128"
+ option mark "!Bulk"
+ option tcpflags "SYN"
+config reclassify
+ option target "Priority"
+ option proto "tcp"
+ option pktsize "-128"
+ option mark "!Bulk"
+ option tcpflags "ACK"
+
+
+# Don't change the stuff below unless you
+# really know what it means :)
+
+config classgroup "Default"
+ option classes "Priority Express Normal Bulk"
+ option default "Normal"
+
+
+config class "Priority"
+ option packetsize 400
+ option maxsize 400
+ option avgrate 10
+ option priority 20
+config class "Priority_down"
+ option packetsize 1000
+ option avgrate 10
+
+
+config class "Express"
+ option packetsize 1000
+ option maxsize 800
+ option avgrate 50
+ option priority 10
+
+config class "Normal"
+ option packetsize 1500
+ option packetdelay 100
+ option avgrate 10
+ option priority 5
+config class "Normal_down"
+ option avgrate 20
+
+config class "Bulk"
+ option avgrate 1
+ option packetdelay 200
diff --git a/package/qos-scripts/files/etc/hotplug.d/iface/10-qos b/package/qos-scripts/files/etc/hotplug.d/iface/10-qos
new file mode 100755
index 000000000..0ced29ac7
--- /dev/null
+++ b/package/qos-scripts/files/etc/hotplug.d/iface/10-qos
@@ -0,0 +1,2 @@
+#!/bin/sh
+[ "$ACTION" = ifup ] && /etc/init.d/qos enabled && /usr/lib/qos/generate.sh interface "$INTERFACE" | sh
diff --git a/package/qos-scripts/files/etc/init.d/qos b/package/qos-scripts/files/etc/init.d/qos
new file mode 100755
index 000000000..3f711155e
--- /dev/null
+++ b/package/qos-scripts/files/etc/init.d/qos
@@ -0,0 +1,16 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+START=50
+
+boot() {
+ /usr/lib/qos/generate.sh firewall | sh
+}
+
+start() {
+ qos-start
+}
+
+stop() {
+ qos-stop
+}
diff --git a/package/qos-scripts/files/usr/bin/qos-start b/package/qos-scripts/files/usr/bin/qos-start
new file mode 100755
index 000000000..261ffb42b
--- /dev/null
+++ b/package/qos-scripts/files/usr/bin/qos-start
@@ -0,0 +1,4 @@
+#!/bin/sh
+qos-stop
+/usr/lib/qos/generate.sh all | sh
+
diff --git a/package/qos-scripts/files/usr/bin/qos-stat b/package/qos-scripts/files/usr/bin/qos-stat
new file mode 100755
index 000000000..78d163888
--- /dev/null
+++ b/package/qos-scripts/files/usr/bin/qos-stat
@@ -0,0 +1,67 @@
+#!/bin/sh
+# Copyright (C) 2011 OpenWrt.org
+
+. /lib/functions.sh
+
+include /lib/network
+
+get_ifname() {
+ local interface="$1"
+ local cfgt
+
+ scan_interfaces
+ config_get cfgt "$interface" TYPE
+ [ "$cfgt" == "interface" ] && config_get "$interface" ifname
+}
+
+config_cb() {
+ config_get TYPE "$CONFIG_SECTION" TYPE
+ [ "interface" == "$TYPE" ] && {
+ config_get device "$CONFIG_SECTION" ifname
+ [ -z "$device" ] && device="$(get_ifname ${CONFIG_SECTION})"
+ config_set "$CONFIG_SECTION" device "$device"
+ }
+}
+
+config_load qos
+
+print_comments() {
+ echo ''
+ echo '# Interface: '"$1"
+ echo '# Direction: '"$2"
+ echo '# Stats: '"$3"
+ echo ''
+}
+
+get_device() {
+ ( config_load network; scan_interfaces; config_get "$1" ifname )
+}
+
+interface_stats() {
+ local interface="$1"
+ local device
+
+ device="$(get_device "$interface")"
+ [ -z "$device" ] && config_get device "$interface" device
+ config_get_bool enabled "$interface" enabled 1
+ [ -z "$device" -o 1 -ne "$enabled" ] && {
+ return 1
+ }
+ config_get_bool halfduplex "$interface" halfduplex 0
+
+ if [ 1 -ne "$halfduplex" ]; then
+ unset halfduplex
+ print_comments "$interface" "Egress" "Start"
+ tc -s class show dev "$device"
+ print_comments "$interface" "Egress" "End"
+ id="root"
+ else
+ id=""
+ fi
+
+ print_comments "$interface" "Ingress${halfduplex:+/Egress}" "Start"
+ tc -s class show dev "$(tc filter show dev $device $id | grep mirred | sed -e 's,.*\(ifb.*\)).*,\1,')"
+ print_comments "$interface" "Ingress${halfduplex:+/Egress}" "End"
+}
+
+[ -z "$1" ] && config_foreach interface_stats interface || interface_stats "$1"
diff --git a/package/qos-scripts/files/usr/bin/qos-stop b/package/qos-scripts/files/usr/bin/qos-stop
new file mode 100755
index 000000000..7f654d858
--- /dev/null
+++ b/package/qos-scripts/files/usr/bin/qos-stop
@@ -0,0 +1,6 @@
+#!/bin/sh
+for iface in $(tc qdisc show | grep -E '(hfsc|ingress)' | awk '{print $5}'); do
+ tc qdisc del dev "$iface" ingress 2>&- >&-
+ tc qdisc del dev "$iface" root 2>&- >&-
+done
+/usr/lib/qos/generate.sh firewall stop | sh
diff --git a/package/qos-scripts/files/usr/lib/qos/generate.sh b/package/qos-scripts/files/usr/lib/qos/generate.sh
new file mode 100755
index 000000000..440b43f5d
--- /dev/null
+++ b/package/qos-scripts/files/usr/lib/qos/generate.sh
@@ -0,0 +1,497 @@
+#!/bin/sh
+[ -e /lib/functions.sh ] && . /lib/functions.sh || . ./functions.sh
+[ -x /sbin/modprobe ] && {
+ insmod="modprobe"
+ rmmod="$insmod -r"
+} || {
+ insmod="insmod"
+ rmmod="rmmod"
+}
+
+add_insmod() {
+ eval "export isset=\${insmod_$1}"
+ case "$isset" in
+ 1) ;;
+ *) {
+ [ "$2" ] && append INSMOD "$rmmod $1 >&- 2>&-" "$N"
+ append INSMOD "$insmod $* >&- 2>&-" "$N"; export insmod_$1=1
+ };;
+ esac
+}
+
+[ -e /etc/config/network ] && {
+ # only try to parse network config on openwrt
+
+ find_ifname() {(
+ reset_cb
+ include /lib/network
+ scan_interfaces
+ config_get "$1" ifname
+ )}
+} || {
+ find_ifname() {
+ echo "Interface not found."
+ exit 1
+ }
+}
+
+parse_matching_rule() {
+ local var="$1"
+ local section="$2"
+ local options="$3"
+ local prefix="$4"
+ local suffix="$5"
+ local proto="$6"
+ local mport=""
+ local ports=""
+
+ append "$var" "$prefix" "$N"
+ for option in $options; do
+ case "$option" in
+ proto) config_get value "$section" proto; proto="${proto:-$value}";;
+ esac
+ done
+ config_get type "$section" TYPE
+ case "$type" in
+ classify) unset pkt; append "$var" "-m mark --mark 0/0xff";;
+ default) pkt=1; append "$var" "-m mark --mark 0/0xff";;
+ reclassify) pkt=1;;
+ esac
+ append "$var" "${proto:+-p $proto}"
+ for option in $options; do
+ config_get value "$section" "$option"
+
+ case "$pkt:$option" in
+ *:srchost)
+ append "$var" "-s $value"
+ ;;
+ *:dsthost)
+ append "$var" "-d $value"
+ ;;
+ *:layer7)
+ add_insmod ipt_layer7
+ add_insmod xt_layer7
+ append "$var" "-m layer7 --l7proto $value${pkt:+ --l7pkt}"
+ ;;
+ *:ports|*:srcports|*:dstports)
+ value="$(echo "$value" | sed -e 's,-,:,g')"
+ lproto=${lproto:-tcp}
+ case "$proto" in
+ ""|tcp|udp) append "$var" "-m ${proto:-tcp -p tcp} -m multiport";;
+ *) unset "$var"; return 0;;
+ esac
+ case "$option" in
+ ports)
+ config_set "$section" srcports ""
+ config_set "$section" dstports ""
+ config_set "$section" portrange ""
+ append "$var" "--ports $value"
+ ;;
+ srcports)
+ config_set "$section" ports ""
+ config_set "$section" dstports ""
+ config_set "$section" portrange ""
+ append "$var" "--sports $value"
+ ;;
+ dstports)
+ config_set "$section" ports ""
+ config_set "$section" srcports ""
+ config_set "$section" portrange ""
+ append "$var" "--dports $value"
+ ;;
+ esac
+ ports=1
+ ;;
+ *:portrange)
+ config_set "$section" ports ""
+ config_set "$section" srcports ""
+ config_set "$section" dstports ""
+ value="$(echo "$value" | sed -e 's,-,:,g')"
+ case "$proto" in
+ ""|tcp|udp) append "$var" "-m ${proto:-tcp -p tcp} --sport $value --dport $value";;
+ *) unset "$var"; return 0;;
+ esac
+ ports=1
+ ;;
+ *:connbytes)
+ value="$(echo "$value" | sed -e 's,-,:,g')"
+ add_insmod ipt_connbytes
+ append "$var" "-m connbytes --connbytes $value --connbytes-dir both --connbytes-mode bytes"
+ ;;
+ *:tos)
+ add_insmod ipt_tos
+ case "$value" in
+ !*) append "$var" "-m tos ! --tos $value";;
+ *) append "$var" "-m tos --tos $value"
+ esac
+ ;;
+ *:dscp)
+ add_insmod ipt_dscp
+ dscp_option="--dscp"
+ [ -z "${value%%[EBCA]*}" ] && dscp_option="--dscp-class"
+ case "$value" in
+ !*) append "$var" "-m dscp ! $dscp_option $value";;
+ *) append "$var" "-m dscp $dscp_option $value"
+ esac
+ ;;
+ *:direction)
+ value="$(echo "$value" | sed -e 's,-,:,g')"
+ if [ "$value" = "out" ]; then
+ append "$var" "-o $device"
+ elif [ "$value" = "in" ]; then
+ append "$var" "-i $device"
+ fi
+ ;;
+ 1:pktsize)
+ value="$(echo "$value" | sed -e 's,-,:,g')"
+ add_insmod ipt_length
+ append "$var" "-m length --length $value"
+ ;;
+ 1:limit)
+ add_insmod ipt_limit
+ append "$var" "-m limit --limit $value"
+ ;;
+ 1:tcpflags)
+ case "$proto" in
+ tcp) append "$var" "-m tcp --tcp-flags ALL $value";;
+ *) unset $var; return 0;;
+ esac
+ ;;
+ 1:mark)
+ config_get class "${value##!}" classnr
+ [ -z "$class" ] && continue;
+ case "$value" in
+ !*) append "$var" "-m mark ! --mark $class/0xff";;
+ *) append "$var" "-m mark --mark $class/0xff";;
+ esac
+ ;;
+ 1:TOS)
+ add_insmod ipt_TOS
+ config_get TOS "$rule" 'TOS'
+ suffix="-j TOS --set-tos "${TOS:-"Normal-Service"}
+ ;;
+ 1:DSCP)
+ add_insmod ipt_DSCP
+ config_get DSCP "$rule" 'DSCP'
+ [ -z "${DSCP%%[EBCA]*}" ] && set_value="--set-dscp-class $DSCP" \
+ || set_value="--set-dscp $DSCP"
+ suffix="-j DSCP $set_value"
+ ;;
+ esac
+ done
+ append "$var" "$suffix"
+ case "$ports:$proto" in
+ 1:) parse_matching_rule "$var" "$section" "$options" "$prefix" "$suffix" "udp";;
+ esac
+}
+
+config_cb() {
+ option_cb() {
+ return 0
+ }
+
+ # Section start
+ case "$1" in
+ interface)
+ config_set "$2" "classgroup" "Default"
+ config_set "$2" "upload" "128"
+ ;;
+ classify|default|reclassify)
+ option_cb() {
+ append options "$1"
+ }
+ ;;
+ esac
+
+ # Section end
+ config_get TYPE "$CONFIG_SECTION" TYPE
+ case "$TYPE" in
+ interface)
+ config_get_bool enabled "$CONFIG_SECTION" enabled 1
+ [ 1 -eq "$enabled" ] || return 0
+ config_get classgroup "$CONFIG_SECTION" classgroup
+ config_set "$CONFIG_SECTION" ifbdev "$C"
+ C=$(($C+1))
+ append INTERFACES "$CONFIG_SECTION"
+ config_set "$classgroup" enabled 1
+ config_get device "$CONFIG_SECTION" device
+ [ -z "$device" ] && {
+ device="$(find_ifname ${CONFIG_SECTION})"
+ config_set "$CONFIG_SECTION" device "${device:-eth0}"
+ }
+ ;;
+ classgroup) append CG "$CONFIG_SECTION";;
+ classify|default|reclassify)
+ case "$TYPE" in
+ classify) var="ctrules";;
+ *) var="rules";;
+ esac
+ config_get target "$CONFIG_SECTION" target
+ config_set "$CONFIG_SECTION" options "$options"
+ append "$var" "$CONFIG_SECTION"
+ unset options
+ ;;
+ esac
+}
+
+
+enum_classes() {
+ local c="0"
+ config_get classes "$1" classes
+ config_get default "$1" default
+ for class in $classes; do
+ c="$(($c + 1))"
+ config_set "${class}" classnr $c
+ case "$class" in
+ $default) class_default=$c;;
+ esac
+ done
+ class_default="${class_default:-$c}"
+}
+
+cls_var() {
+ local varname="$1"
+ local class="$2"
+ local name="$3"
+ local type="$4"
+ local default="$5"
+ local tmp tmp1 tmp2
+ config_get tmp1 "$class" "$name"
+ config_get tmp2 "${class}_${type}" "$name"
+ tmp="${tmp2:-$tmp1}"
+ tmp="${tmp:-$tmp2}"
+ export ${varname}="${tmp:-$default}"
+}
+
+tcrules() {
+ dir=/usr/lib/qos
+ [ -e $dir/tcrules.awk ] || dir=.
+ echo "$cstr" | awk \
+ -v device="$dev" \
+ -v linespeed="$rate" \
+ -f $dir/tcrules.awk
+}
+
+start_interface() {
+ local iface="$1"
+ local num_ifb="$2"
+ config_get device "$iface" device
+ config_get_bool enabled "$iface" enabled 1
+ [ -z "$device" -o 1 -ne "$enabled" ] && {
+ return 1
+ }
+ config_get upload "$iface" upload
+ config_get_bool halfduplex "$iface" halfduplex
+ config_get download "$iface" download
+ config_get classgroup "$iface" classgroup
+ config_get_bool overhead "$iface" overhead 0
+
+ download="${download:-${halfduplex:+$upload}}"
+ enum_classes "$classgroup"
+ for dir in ${halfduplex:-up} ${download:+down}; do
+ case "$dir" in
+ up)
+ [ "$overhead" = 1 ] && upload=$(($upload * 98 / 100 - (15 * 128 / $upload)))
+ dev="$device"
+ rate="$upload"
+ dl_mode=""
+ prefix="cls"
+ ;;
+ down)
+ [ "$(ls -d /proc/sys/net/ipv4/conf/ifb* 2>&- | wc -l)" -ne "$num_ifb" ] && add_insmod ifb numifbs="$num_ifb"
+ config_get ifbdev "$iface" ifbdev
+ [ "$overhead" = 1 ] && download=$(($download * 98 / 100 - (80 * 1024 / $download)))
+ dev="ifb$ifbdev"
+ rate="$download"
+ dl_mode=1
+ prefix="d_cls"
+ ;;
+ *) continue;;
+ esac
+ cstr=
+ for class in $classes; do
+ cls_var pktsize "$class" packetsize $dir 1500
+ cls_var pktdelay "$class" packetdelay $dir 0
+ cls_var maxrate "$class" limitrate $dir 100
+ cls_var prio "$class" priority $dir 1
+ cls_var avgrate "$class" avgrate $dir 0
+ cls_var qdisc "$class" qdisc $dir ""
+ cls_var filter "$class" filter $dir ""
+ config_get classnr "$class" classnr
+ append cstr "$classnr:$prio:$avgrate:$pktsize:$pktdelay:$maxrate:$qdisc:$filter" "$N"
+ done
+ append ${prefix}q "$(tcrules)" "$N"
+ export dev_${dir}="ifconfig $dev up txqueuelen 5 >&- 2>&-
+tc qdisc del dev $dev root >&- 2>&-
+tc qdisc add dev $dev root handle 1: hfsc default ${class_default}0
+tc class add dev $dev parent 1: classid 1:1 hfsc sc rate ${rate}kbit ul rate ${rate}kbit"
+ done
+ [ -n "$download" ] && {
+ add_insmod cls_u32
+ add_insmod em_u32
+ add_insmod act_connmark
+ add_insmod act_mirred
+ add_insmod sch_ingress
+ }
+ if [ -n "$halfduplex" ]; then
+ export dev_up="tc qdisc del dev $device root >&- 2>&-
+tc qdisc add dev $device root handle 1: hfsc
+tc filter add dev $device parent 1: protocol ip prio 10 u32 match u32 0 0 flowid 1:1 action mirred egress redirect dev ifb$ifbdev"
+ elif [ -n "$download" ]; then
+ append dev_${dir} "tc qdisc del dev $device ingress >&- 2>&-
+tc qdisc add dev $device ingress
+tc filter add dev $device parent ffff: protocol ip prio 1 u32 match u32 0 0 flowid 1:1 action connmark action mirred egress redirect dev ifb$ifbdev" "$N"
+ fi
+ add_insmod cls_fw
+ add_insmod sch_hfsc
+ add_insmod sch_fq_codel
+
+ cat <<EOF
+${INSMOD:+$INSMOD$N}${dev_up:+$dev_up
+$clsq
+}${ifbdev:+$dev_down
+$d_clsq
+$d_clsl
+$d_clsf
+}
+EOF
+ unset INSMOD clsq clsf clsl d_clsq d_clsl d_clsf dev_up dev_down
+}
+
+start_interfaces() {
+ local C="$1"
+ for iface in $INTERFACES; do
+ start_interface "$iface" "$C"
+ done
+}
+
+add_rules() {
+ local var="$1"
+ local rules="$2"
+ local prefix="$3"
+
+ for rule in $rules; do
+ unset iptrule
+ config_get target "$rule" target
+ config_get target "$target" classnr
+ config_get options "$rule" options
+
+ ## If we want to override the TOS field, let's clear the DSCP field first.
+ [ ! -z "$(echo $options | grep 'TOS')" ] && {
+ s_options=${options%%TOS}
+ add_insmod ipt_DSCP
+ parse_matching_rule iptrule "$rule" "$s_options" "$prefix" "-j DSCP --set-dscp 0"
+ append "$var" "$iptrule" "$N"
+ unset iptrule
+ }
+
+ parse_matching_rule iptrule "$rule" "$options" "$prefix" "-j MARK --set-mark $target/0xff"
+ append "$var" "$iptrule" "$N"
+ done
+}
+
+start_cg() {
+ local cg="$1"
+ local iptrules
+ local pktrules
+ local sizerules
+ enum_classes "$cg"
+ add_rules iptrules "$ctrules" "iptables -t mangle -A qos_${cg}_ct"
+ config_get classes "$cg" classes
+ for class in $classes; do
+ config_get mark "$class" classnr
+ config_get maxsize "$class" maxsize
+ [ -z "$maxsize" -o -z "$mark" ] || {
+ add_insmod ipt_length
+ append pktrules "iptables -t mangle -A qos_${cg} -m mark --mark $mark/0xff -m length --length $maxsize: -j MARK --set-mark 0/0xff" "$N"
+ }
+ done
+ add_rules pktrules "$rules" "iptables -t mangle -A qos_${cg}"
+ for iface in $INTERFACES; do
+ config_get classgroup "$iface" classgroup
+ config_get device "$iface" device
+ config_get ifbdev "$iface" ifbdev
+ config_get upload "$iface" upload
+ config_get download "$iface" download
+ config_get halfduplex "$iface" halfduplex
+ download="${download:-${halfduplex:+$upload}}"
+ append up "iptables -t mangle -A OUTPUT -o $device -j qos_${cg}" "$N"
+ append up "iptables -t mangle -A FORWARD -o $device -j qos_${cg}" "$N"
+ done
+ cat <<EOF
+$INSMOD
+iptables -t mangle -N qos_${cg} >&- 2>&-
+iptables -t mangle -N qos_${cg}_ct >&- 2>&-
+${iptrules:+${iptrules}${N}iptables -t mangle -A qos_${cg}_ct -j CONNMARK --save-mark --mask 0xff}
+iptables -t mangle -A qos_${cg} -j CONNMARK --restore-mark --mask 0xff
+iptables -t mangle -A qos_${cg} -m mark --mark 0/0xff -j qos_${cg}_ct
+$pktrules
+$up$N${down:+${down}$N}
+EOF
+ unset INSMOD
+}
+
+start_firewall() {
+ add_insmod ipt_multiport
+ add_insmod ipt_CONNMARK
+ stop_firewall
+ for group in $CG; do
+ start_cg $group
+ done
+}
+
+stop_firewall() {
+ # Builds up a list of iptables commands to flush the qos_* chains,
+ # remove rules referring to them, then delete them
+
+ # Print rules in the mangle table, like iptables-save
+ iptables -t mangle -S |
+ # Find rules for the qos_* chains
+ grep '^-N qos_\|-j qos_' |
+ # Exclude rules in qos_* chains (inter-qos_* refs)
+ grep -v '^-A qos_' |
+ # Replace -N with -X and hold, with -F and print
+ # Replace -A with -D
+ # Print held lines at the end (note leading newline)
+ sed -e '/^-N/{s/^-N/-X/;H;s/^-X/-F/}' \
+ -e 's/^-A/-D/' \
+ -e '${p;g}' |
+ # Make into proper iptables calls
+ # Note: awkward in previous call due to hold space usage
+ sed -n -e 's/^./iptables -t mangle &/p'
+}
+
+C="0"
+INTERFACES=""
+[ -e ./qos.conf ] && {
+ . ./qos.conf
+ config_cb
+} || config_load qos
+
+C="0"
+for iface in $INTERFACES; do
+ export C="$(($C + 1))"
+done
+
+case "$1" in
+ all)
+ start_interfaces "$C"
+ start_firewall
+ ;;
+ interface)
+ start_interface "$2" "$C"
+ ;;
+ interfaces)
+ start_interfaces
+ ;;
+ firewall)
+ case "$2" in
+ stop)
+ stop_firewall
+ ;;
+ start|"")
+ start_firewall
+ ;;
+ esac
+ ;;
+esac
diff --git a/package/qos-scripts/files/usr/lib/qos/tcrules.awk b/package/qos-scripts/files/usr/lib/qos/tcrules.awk
new file mode 100644
index 000000000..a19b65192
--- /dev/null
+++ b/package/qos-scripts/files/usr/lib/qos/tcrules.awk
@@ -0,0 +1,95 @@
+BEGIN {
+ dmax=100
+ if (!(linespeed > 0)) linespeed = 128
+ FS=":"
+ n = 0
+}
+
+($1 != "") {
+ n++
+ class[n] = $1
+ prio[n] = $2
+ avgrate[n] = ($3 * linespeed / 100)
+ pktsize[n] = $4
+ delay[n] = $5
+ maxrate[n] = ($6 * linespeed / 100)
+ qdisc[n] = $7
+ filter[n] = $8
+}
+
+END {
+ allocated = 0
+ maxdelay = 0
+
+ for (i = 1; i <= n; i++) {
+ # set defaults
+ if (!(pktsize[i] > 0)) pktsize[i] = 1500
+ if (!(prio[i] > 0)) prio[i] = 1
+
+ allocated += avgrate[i]
+ sum_prio += prio[i]
+ if ((avgrate[i] > 0) && !(delay[i] > 0)) {
+ sum_rtprio += prio[i]
+ }
+ }
+
+ # allocation of m1 in rt classes:
+ # sum(d * m1) must not exceed dmax * (linespeed - allocated)
+ dmax = 0
+ for (i = 1; i <= n; i++) {
+ if (avgrate[i] > 0) {
+ rtm2[i] = avgrate[i]
+ if (delay[i] > 0) {
+ d[i] = delay[i]
+ } else {
+ d[i] = 2 * pktsize[i] * 1000 / (linespeed * 1024)
+ if (d[i] > dmax) dmax = d[i]
+ }
+ }
+ }
+
+ ds_avail = dmax * (linespeed - allocated)
+ for (i = 1; i <= n; i++) {
+ lsm1[i] = 0
+ rtm1[i] = 0
+ lsm2[i] = linespeed * prio[i] / sum_prio
+ if ((avgrate[i] > 0) && (d[i] > 0)) {
+ if (!(delay[i] > 0)) {
+ ds = ds_avail * prio[i] / sum_rtprio
+ ds_avail -= ds
+ rtm1[i] = rtm2[i] + ds/d[i]
+ }
+ lsm1[i] = rtm1[i]
+ }
+ else {
+ d[i] = 0
+ }
+ }
+
+ # main qdisc
+ for (i = 1; i <= n; i++) {
+ printf "tc class add dev "device" parent 1:1 classid 1:"class[i]"0 hfsc"
+ if (rtm1[i] > 0) {
+ printf " rt m1 " int(rtm1[i]) "kbit d " int(d[i] * 1000) "us m2 " int(rtm2[i])"kbit"
+ }
+ printf " ls m1 " int(lsm1[i]) "kbit d " int(d[i] * 1000) "us m2 " int(lsm2[i]) "kbit"
+ print " ul rate " int(maxrate[i]) "kbit"
+ }
+
+ # leaf qdisc
+ avpkt = 1200
+ for (i = 1; i <= n; i++) {
+ print "tc qdisc add dev "device" parent 1:"class[i]"0 handle "class[i]"00: fq_codel"
+ }
+
+ # filter rule
+ for (i = 1; i <= n; i++) {
+ print "tc filter add dev "device" parent 1: prio "class[i]" protocol ip handle "class[i]"/0xff fw flowid 1:"class[i] "0"
+ filterc=1
+ if (filter[i] != "") {
+ print " tc filter add dev "device" parent "class[i]"00: handle "filterc"0 "filter[i]
+ filterc=filterc+1
+ }
+ }
+}
+
diff --git a/package/rbcfg/Makefile b/package/rbcfg/Makefile
new file mode 100644
index 000000000..51fefd594
--- /dev/null
+++ b/package/rbcfg/Makefile
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=rbcfg
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/rbcfg
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=RouterBOOT configuration tool
+ DEPENDS:=@TARGET_ar71xx
+endef
+
+define Package/rbcfg/description
+ This package contains an utility to manipulate RouterBOOT configuration on the
+ MikroTIK RB-4XX devices.
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CC)" \
+ CFLAGS="$(TARGET_CFLAGS) -Wall" \
+ LDFLAGS="$(TARGET_LDFLAGS)"
+endef
+
+define Package/rbcfg/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/rbcfg $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,rbcfg))
diff --git a/package/rbcfg/src/Makefile b/package/rbcfg/src/Makefile
new file mode 100644
index 000000000..62c74b267
--- /dev/null
+++ b/package/rbcfg/src/Makefile
@@ -0,0 +1,14 @@
+CC = gcc
+CFLAGS = -Wall
+OBJS = main.o cyg_crc32.o
+
+all: rbcfg
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+rbcfg: $(OBJS)
+ $(CC) -o $@ $(OBJS)
+
+clean:
+ rm -f rbcfg *.o
diff --git a/package/rbcfg/src/cyg_crc.h b/package/rbcfg/src/cyg_crc.h
new file mode 100644
index 000000000..7b5980344
--- /dev/null
+++ b/package/rbcfg/src/cyg_crc.h
@@ -0,0 +1,109 @@
+//==========================================================================
+//
+// crc.h
+//
+// Interface for the CRC algorithms.
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2002 Andrew Lunn
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Andrew Lunn
+// Contributors: Andrew Lunn
+// Date: 2002-08-06
+// Purpose:
+// Description:
+//
+// This code is part of eCos (tm).
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#ifndef _SERVICES_CRC_CRC_H_
+#define _SERVICES_CRC_CRC_H_
+
+#if 0
+#include <cyg/infra/cyg_type.h>
+#else
+#include <stdint.h>
+typedef uint32_t cyg_uint32;
+typedef uint16_t cyg_uint16;
+#endif
+
+#ifndef __externC
+# ifdef __cplusplus
+# define __externC extern "C"
+# else
+# define __externC extern
+# endif
+#endif
+
+// Compute a CRC, using the POSIX 1003 definition
+
+__externC cyg_uint32
+cyg_posix_crc32(unsigned char *s, int len);
+
+// Gary S. Brown's 32 bit CRC
+
+__externC cyg_uint32
+cyg_crc32(unsigned char *s, int len);
+
+// Gary S. Brown's 32 bit CRC, but accumulate the result from a
+// previous CRC calculation
+
+__externC cyg_uint32
+cyg_crc32_accumulate(cyg_uint32 crc, unsigned char *s, int len);
+
+// Ethernet FCS Algorithm
+
+__externC cyg_uint32
+cyg_ether_crc32(unsigned char *s, int len);
+
+// Ethernet FCS algorithm, but accumulate the result from a previous
+// CRC calculation.
+
+__externC cyg_uint32
+cyg_ether_crc32_accumulate(cyg_uint32 crc, unsigned char *s, int len);
+
+// 16 bit CRC with polynomial x^16+x^12+x^5+1
+
+__externC cyg_uint16
+cyg_crc16(unsigned char *s, int len);
+
+#endif // _SERVICES_CRC_CRC_H_
+
+
+
diff --git a/package/rbcfg/src/cyg_crc32.c b/package/rbcfg/src/cyg_crc32.c
new file mode 100644
index 000000000..9462598ae
--- /dev/null
+++ b/package/rbcfg/src/cyg_crc32.c
@@ -0,0 +1,172 @@
+//==========================================================================
+//
+// crc32.c
+//
+// Gary S. Brown's 32 bit CRC
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2002 Gary Thomas
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): gthomas
+// Contributors: gthomas,asl
+// Date: 2001-01-31
+// Purpose:
+// Description:
+//
+// This code is part of eCos (tm).
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#if 0
+#include <cyg/crc/crc.h>
+#else
+#include "cyg_crc.h"
+#endif
+
+ /* ====================================================================== */
+ /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */
+ /* code or tables extracted from it, as desired without restriction. */
+ /* */
+ /* First, the polynomial itself and its table of feedback terms. The */
+ /* polynomial is */
+ /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
+ /* */
+ /* ====================================================================== */
+
+static const cyg_uint32 crc32_tab[] = {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+ };
+
+/* This is the standard Gary S. Brown's 32 bit CRC algorithm, but
+ accumulate the CRC into the result of a previous CRC. */
+cyg_uint32
+cyg_crc32_accumulate(cyg_uint32 crc32val, unsigned char *s, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8);
+ }
+ return crc32val;
+}
+
+/* This is the standard Gary S. Brown's 32 bit CRC algorithm */
+cyg_uint32
+cyg_crc32(unsigned char *s, int len)
+{
+ return (cyg_crc32_accumulate(0,s,len));
+}
+
+/* Return a 32-bit CRC of the contents of the buffer accumulating the
+ result from a previous CRC calculation. This uses the Ethernet FCS
+ algorithm.*/
+cyg_uint32
+cyg_ether_crc32_accumulate(cyg_uint32 crc32val, unsigned char *s, int len)
+{
+ int i;
+
+ if (s == 0) return 0L;
+
+ crc32val = crc32val ^ 0xffffffff;
+ for (i = 0; i < len; i++) {
+ crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8);
+ }
+ return crc32val ^ 0xffffffff;
+}
+
+/* Return a 32-bit CRC of the contents of the buffer, using the
+ Ethernet FCS algorithm. */
+cyg_uint32
+cyg_ether_crc32(unsigned char *s, int len)
+{
+ return cyg_ether_crc32_accumulate(0,s,len);
+}
+
+
diff --git a/package/rbcfg/src/main.c b/package/rbcfg/src/main.c
new file mode 100644
index 000000000..5614a6c22
--- /dev/null
+++ b/package/rbcfg/src/main.c
@@ -0,0 +1,791 @@
+/*
+ * RouterBOOT configuration utility
+ *
+ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <linux/limits.h>
+
+#include "rbcfg.h"
+#include "cyg_crc.h"
+
+#define RBCFG_TMP_FILE "/tmp/.rbcfg"
+#define RBCFG_MTD_NAME "soft_config"
+
+#define RB_ERR_NOTFOUND 1
+#define RB_ERR_INVALID 2
+#define RB_ERR_NOMEM 3
+#define RB_ERR_IO 4
+
+#define ARRAY_SIZE(_a) (sizeof((_a)) / sizeof((_a)[0]))
+
+struct rbcfg_ctx {
+ char *mtd_device;
+ char *tmp_file;
+ char *buf;
+ unsigned buflen;
+};
+
+struct rbcfg_value {
+ const char *name;
+ const char *desc;
+ union {
+ uint32_t u32;
+ const char *raw;
+ } val;
+};
+
+#define RBCFG_ENV_TYPE_U32 0
+
+struct rbcfg_env {
+ const char *name;
+ int type;
+ uint16_t id;
+ const struct rbcfg_value *values;
+ int num_values;
+};
+
+#define CMD_FLAG_USES_CFG 0x01
+
+struct rbcfg_command {
+ const char *command;
+ const char *usage;
+ int flags;
+ int (*exec)(int argc, const char *argv[]);
+};
+
+static void usage(void);
+
+/* Globals */
+
+static struct rbcfg_ctx *rbcfg_ctx;
+static char *rbcfg_name;
+
+#define CFG_U32(_name, _desc, _val) { \
+ .name = (_name), \
+ .desc = (_desc), \
+ .val.u32 = (_val), \
+}
+
+static const struct rbcfg_value rbcfg_boot_delay[] = {
+ CFG_U32("1", "1 second", RB_BOOT_DELAY_1SEC),
+ CFG_U32("2", "2 seconds", RB_BOOT_DELAY_2SEC),
+ CFG_U32("3", "3 seconds", RB_BOOT_DELAY_3SEC),
+ CFG_U32("4", "4 seconds", RB_BOOT_DELAY_4SEC),
+ CFG_U32("5", "5 seconds", RB_BOOT_DELAY_5SEC),
+ CFG_U32("6", "6 seconds", RB_BOOT_DELAY_6SEC),
+ CFG_U32("7", "7 seconds", RB_BOOT_DELAY_7SEC),
+ CFG_U32("8", "8 seconds", RB_BOOT_DELAY_8SEC),
+ CFG_U32("9", "9 seconds", RB_BOOT_DELAY_9SEC),
+};
+
+static const struct rbcfg_value rbcfg_boot_device[] = {
+ CFG_U32("eth", "boot over Ethernet",
+ RB_BOOT_DEVICE_ETHER),
+ CFG_U32("nandeth", "boot from NAND, if fail then Ethernet",
+ RB_BOOT_DEVICE_NANDETH),
+ CFG_U32("ethnand", "boot Ethernet once, then NAND",
+ RB_BOOT_DEVICE_ETHONCE),
+ CFG_U32("nand", "boot from NAND only",
+ RB_BOOT_DEVICE_NANDONLY),
+};
+
+static const struct rbcfg_value rbcfg_boot_key[] = {
+ CFG_U32("any", "any key", RB_BOOT_KEY_ANY),
+ CFG_U32("del", "<Delete> key only", RB_BOOT_KEY_DEL),
+};
+
+static const struct rbcfg_value rbcfg_boot_protocol[] = {
+ CFG_U32("bootp", "BOOTP protocol", RB_BOOT_PROTOCOL_BOOTP),
+ CFG_U32("dhcp", "DHCP protocol", RB_BOOT_PROTOCOL_DHCP),
+};
+
+static const struct rbcfg_value rbcfg_uart_speed[] = {
+ CFG_U32("115200", "", RB_UART_SPEED_115200),
+ CFG_U32("57600", "", RB_UART_SPEED_57600),
+ CFG_U32("38400", "", RB_UART_SPEED_38400),
+ CFG_U32("19200", "", RB_UART_SPEED_19200),
+ CFG_U32("9600", "", RB_UART_SPEED_9600),
+ CFG_U32("4800", "", RB_UART_SPEED_4800),
+ CFG_U32("2400", "", RB_UART_SPEED_2400),
+ CFG_U32("1200", "", RB_UART_SPEED_1200),
+ CFG_U32("off", "disable console output", RB_UART_SPEED_OFF),
+};
+
+static const struct rbcfg_value rbcfg_cpu_mode[] = {
+ CFG_U32("powersave", "power save", RB_CPU_MODE_POWERSAVE),
+ CFG_U32("regular", "regular (better for -0c environment)",
+ RB_CPU_MODE_REGULAR),
+};
+
+static const struct rbcfg_value rbcfg_booter[] = {
+ CFG_U32("regular", "load regular booter", RB_BOOTER_REGULAR),
+ CFG_U32("backup", "force backup-booter loading", RB_BOOTER_BACKUP),
+};
+
+static const struct rbcfg_env rbcfg_envs[] = {
+ {
+ .name = "boot_delay",
+ .id = RB_ID_BOOT_DELAY,
+ .type = RBCFG_ENV_TYPE_U32,
+ .values = rbcfg_boot_delay,
+ .num_values = ARRAY_SIZE(rbcfg_boot_delay),
+ }, {
+ .name = "boot_device",
+ .id = RB_ID_BOOT_DEVICE,
+ .type = RBCFG_ENV_TYPE_U32,
+ .values = rbcfg_boot_device,
+ .num_values = ARRAY_SIZE(rbcfg_boot_device),
+ }, {
+ .name = "boot_key",
+ .id = RB_ID_BOOT_KEY,
+ .type = RBCFG_ENV_TYPE_U32,
+ .values = rbcfg_boot_key,
+ .num_values = ARRAY_SIZE(rbcfg_boot_key),
+ }, {
+ .name = "boot_protocol",
+ .id = RB_ID_BOOT_PROTOCOL,
+ .type = RBCFG_ENV_TYPE_U32,
+ .values = rbcfg_boot_protocol,
+ .num_values = ARRAY_SIZE(rbcfg_boot_protocol),
+ }, {
+ .name = "booter",
+ .id = RB_ID_BOOTER,
+ .type = RBCFG_ENV_TYPE_U32,
+ .values = rbcfg_booter,
+ .num_values = ARRAY_SIZE(rbcfg_booter),
+ }, {
+ .name = "cpu_mode",
+ .id = RB_ID_CPU_MODE,
+ .type = RBCFG_ENV_TYPE_U32,
+ .values = rbcfg_cpu_mode,
+ .num_values = ARRAY_SIZE(rbcfg_cpu_mode),
+ }, {
+ .name = "uart_speed",
+ .id = RB_ID_UART_SPEED,
+ .type = RBCFG_ENV_TYPE_U32,
+ .values = rbcfg_uart_speed,
+ .num_values = ARRAY_SIZE(rbcfg_uart_speed),
+ }
+};
+
+static inline uint16_t
+get_u16(const void *buf)
+{
+ const uint8_t *p = buf;
+
+ return ((uint16_t) p[1] + ((uint16_t) p[0] << 8));
+}
+
+static inline uint32_t
+get_u32(const void *buf)
+{
+ const uint8_t *p = buf;
+
+ return ((uint32_t) p[3] + ((uint32_t) p[2] << 8) +
+ ((uint32_t) p[1] << 16) + ((uint32_t) p[0] << 24));
+}
+
+static inline void
+put_u32(void *buf, uint32_t val)
+{
+ uint8_t *p = buf;
+
+ p[3] = val & 0xff;
+ p[2] = (val >> 8) & 0xff;
+ p[1] = (val >> 16) & 0xff;
+ p[0] = (val >> 24) & 0xff;
+}
+
+static int
+rbcfg_find_tag(struct rbcfg_ctx *ctx, uint16_t tag_id, uint16_t *tag_len,
+ void **tag_data)
+{
+ uint16_t id;
+ uint16_t len;
+ char *buf = ctx->buf;
+ unsigned int buflen = ctx->buflen;
+ int ret = RB_ERR_NOTFOUND;
+
+ /* skip magic and CRC value */
+ buf += 8;
+ buflen -= 8;
+
+ while (buflen > 2) {
+ len = get_u16(buf);
+ buf += 2;
+ buflen -= 2;
+
+ if (buflen < 2)
+ break;
+
+ id = get_u16(buf);
+ buf += 2;
+ buflen -= 2;
+
+ if (id == RB_ID_TERMINATOR)
+ break;
+
+ if (buflen < len)
+ break;
+
+ if (id == tag_id) {
+ *tag_len = len;
+ *tag_data = buf;
+ ret = 0;
+ break;
+ }
+
+ buf += len;
+ buflen -= len;
+ }
+
+ if (ret)
+ fprintf(stderr, "no tag found with id=%u\n", tag_id);
+
+ return ret;
+}
+
+static int
+rbcfg_get_u32(struct rbcfg_ctx *ctx, uint16_t id, uint32_t *val)
+{
+ void *tag_data;
+ uint16_t tag_len;
+ int err;
+
+ err = rbcfg_find_tag(ctx, id, &tag_len, &tag_data);
+ if (err)
+ return err;
+
+ *val = get_u32(tag_data);
+ return 0;
+}
+
+static int
+rbcfg_set_u32(struct rbcfg_ctx *ctx, uint16_t id, uint32_t val)
+{
+ void *tag_data;
+ uint16_t tag_len;
+ int err;
+
+ err = rbcfg_find_tag(ctx, id, &tag_len, &tag_data);
+ if (err)
+ return err;
+
+ put_u32(tag_data, val);
+ return 0;
+}
+
+char *rbcfg_find_mtd(const char *name, int *erase_size)
+{
+ FILE *f;
+ int mtd_num;
+ char dev[PATH_MAX];
+ char *ret = NULL;
+ struct stat s;
+ int err;
+
+ f = fopen("/proc/mtd", "r");
+ if (!f)
+ return NULL;
+
+ while (1) {
+ char *p;
+ p = fgets(dev, sizeof(dev), f);
+ if (!p)
+ break;
+
+ if (!strstr(dev, name))
+ continue;
+
+ err = sscanf(dev, "mtd%d: %08x", &mtd_num, erase_size);
+ if (err != 2)
+ break;
+
+ sprintf(dev, "/dev/mtdblock%d", mtd_num);
+ err = stat(dev, &s);
+ if (err < 0)
+ break;
+
+ if ((s.st_mode & S_IFBLK) == 0)
+ break;
+
+ ret = malloc(strlen(dev) + 1);
+ if (ret == NULL)
+ break;
+
+ strncpy(ret, dev, strlen(dev) + 1);
+ break;
+ }
+
+ fclose(f);
+ return ret;
+}
+
+static int
+rbcfg_check_tmp(struct rbcfg_ctx *ctx)
+{
+ struct stat s;
+ int err;
+
+ err = stat(ctx->tmp_file, &s);
+ if (err < 0)
+ return 0;
+
+ if ((s.st_mode & S_IFREG) == 0)
+ return 0;
+
+ if (s.st_size != ctx->buflen)
+ return 0;
+
+ return 1;
+}
+
+static int
+rbcfg_load(struct rbcfg_ctx *ctx)
+{
+ uint32_t magic;
+ uint32_t crc_orig, crc;
+ char *name;
+ int tmp;
+ int fd;
+ int err;
+
+ tmp = rbcfg_check_tmp(ctx);
+ name = (tmp) ? ctx->tmp_file : ctx->mtd_device;
+
+ fd = open(name, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "unable to open %s\n", name);
+ err = RB_ERR_IO;
+ goto err;
+ }
+
+ err = read(fd, ctx->buf, ctx->buflen);
+ if (err != ctx->buflen) {
+ fprintf(stderr, "unable to read from %s\n", name);
+ err = RB_ERR_IO;
+ goto err_close;
+ }
+
+ magic = get_u32(ctx->buf);
+ if (magic != RB_MAGIC_SOFT) {
+ fprintf(stderr, "invalid configuration\n");
+ err = RB_ERR_INVALID;
+ goto err_close;
+ }
+
+ crc_orig = get_u32(ctx->buf + 4);
+ put_u32(ctx->buf + 4, 0);
+ crc = cyg_ether_crc32((unsigned char *) ctx->buf, ctx->buflen);
+ if (crc != crc_orig) {
+ fprintf(stderr, "configuration has CRC error\n");
+ err = RB_ERR_INVALID;
+ goto err_close;
+ }
+
+ err = 0;
+
+ err_close:
+ close(fd);
+ err:
+ return err;
+}
+
+static int
+rbcfg_open()
+{
+ char *mtd_device;
+ struct rbcfg_ctx *ctx;
+ int buflen;
+ int err;
+
+ mtd_device = rbcfg_find_mtd(RBCFG_MTD_NAME, &buflen);
+ if (!mtd_device) {
+ fprintf(stderr, "unable to find configuration\n");
+ return RB_ERR_NOTFOUND;
+ }
+
+ ctx = malloc(sizeof(struct rbcfg_ctx) + buflen);
+ if (ctx == NULL) {
+ err = RB_ERR_NOMEM;
+ goto err_free_mtd;
+ }
+
+ ctx->mtd_device = mtd_device;
+ ctx->tmp_file = RBCFG_TMP_FILE;
+ ctx->buflen = buflen;
+ ctx->buf = (char *) &ctx[1];
+
+ err = rbcfg_load(ctx);
+ if (err)
+ goto err_free_ctx;
+
+ rbcfg_ctx = ctx;
+ return 0;
+
+ err_free_ctx:
+ free(ctx);
+ err_free_mtd:
+ free(mtd_device);
+ return err;
+}
+
+static int
+rbcfg_update(int tmp)
+{
+ struct rbcfg_ctx *ctx = rbcfg_ctx;
+ char *name;
+ uint32_t crc;
+ int fd;
+ int err;
+
+ put_u32(ctx->buf, RB_MAGIC_SOFT);
+ put_u32(ctx->buf + 4, 0);
+ crc = cyg_ether_crc32((unsigned char *) ctx->buf, ctx->buflen);
+ put_u32(ctx->buf + 4, crc);
+
+ name = (tmp) ? ctx->tmp_file : ctx->mtd_device;
+ fd = open(name, O_WRONLY | O_CREAT);
+ if (fd < 0) {
+ fprintf(stderr, "unable to open %s for writing\n", name);
+ err = RB_ERR_IO;
+ goto out;
+ }
+
+ err = write(fd, ctx->buf, ctx->buflen);
+ if (err != ctx->buflen) {
+ err = RB_ERR_IO;
+ goto out_close;
+ }
+
+ fsync(fd);
+ err = 0;
+
+ out_close:
+ close(fd);
+ out:
+ return err;
+}
+
+static void
+rbcfg_close(void)
+{
+ struct rbcfg_ctx *ctx;
+
+ ctx = rbcfg_ctx;
+ free(ctx->mtd_device);
+ free(ctx);
+}
+
+static const struct rbcfg_value *
+rbcfg_env_find(const struct rbcfg_env *env, const char *name)
+{
+ unsigned i;
+
+ for (i = 0; i < env->num_values; i++) {
+ const struct rbcfg_value *v = &env->values[i];
+
+ if (strcmp(v->name, name) == 0)
+ return v;
+ }
+
+ return NULL;
+}
+
+static const struct rbcfg_value *
+rbcfg_env_find_u32(const struct rbcfg_env *env, uint32_t val)
+{
+ unsigned i;
+
+ for (i = 0; i < env->num_values; i++) {
+ const struct rbcfg_value *v = &env->values[i];
+
+ if (v->val.u32 == val)
+ return v;
+ }
+
+ return NULL;
+}
+
+static const char *
+rbcfg_env_get_u32(const struct rbcfg_env *env)
+{
+ const struct rbcfg_value *v;
+ uint32_t val;
+ int err;
+
+ err = rbcfg_get_u32(rbcfg_ctx, env->id, &val);
+ if (err)
+ return NULL;
+
+ v = rbcfg_env_find_u32(env, val);
+ if (v == NULL) {
+ fprintf(stderr, "unknown value %08x found for %s\n",
+ val, env->name);
+ return NULL;
+ }
+
+ return v->name;
+}
+
+static int
+rbcfg_env_set_u32(const struct rbcfg_env *env, const char *data)
+{
+ const struct rbcfg_value *v;
+ int err;
+
+ v = rbcfg_env_find(env, data);
+ if (v == NULL) {
+ fprintf(stderr, "invalid value '%s'\n", data);
+ return RB_ERR_INVALID;
+ }
+
+ err = rbcfg_set_u32(rbcfg_ctx, env->id, v->val.u32);
+ return err;
+}
+
+static const char *
+rbcfg_env_get(const struct rbcfg_env *env)
+{
+ const char *ret = NULL;
+
+ switch (env->type) {
+ case RBCFG_ENV_TYPE_U32:
+ ret = rbcfg_env_get_u32(env);
+ break;
+ }
+
+ return ret;
+}
+
+static int
+rbcfg_env_set(const struct rbcfg_env *env, const char *data)
+{
+ int ret = 0;
+
+ switch (env->type) {
+ case RBCFG_ENV_TYPE_U32:
+ ret = rbcfg_env_set_u32(env, data);
+ break;
+ }
+
+ return ret;
+}
+
+static int
+rbcfg_cmd_apply(int argc, const char *argv[])
+{
+ return rbcfg_update(0);
+}
+
+static int
+rbcfg_cmd_help(int argc, const char *argv[])
+{
+ usage();
+ return 0;
+}
+
+static int
+rbcfg_cmd_get(int argc, const char *argv[])
+{
+ int err = RB_ERR_NOTFOUND;
+ int i;
+
+ if (argc != 1) {
+ usage();
+ return RB_ERR_INVALID;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(rbcfg_envs); i++) {
+ const struct rbcfg_env *env = &rbcfg_envs[i];
+ const char *value;
+
+ if (strcmp(env->name, argv[0]))
+ continue;
+
+ value = rbcfg_env_get(env);
+ if (value) {
+ fprintf(stdout, "%s\n", value);
+ err = 0;
+ }
+ break;
+ }
+
+ return err;
+}
+
+static int
+rbcfg_cmd_set(int argc, const char *argv[])
+{
+ int err = RB_ERR_INVALID;
+ int i;
+
+ if (argc != 2) {
+ /* not enough parameters */
+ usage();
+ return RB_ERR_INVALID;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(rbcfg_envs); i++) {
+ const struct rbcfg_env *env = &rbcfg_envs[i];
+
+ if (strcmp(env->name, argv[0]))
+ continue;
+
+ err = rbcfg_env_set(env, argv[1]);
+ if (err == 0)
+ err = rbcfg_update(1);
+ break;
+ }
+
+ return err;
+}
+
+static int
+rbcfg_cmd_show(int argc, const char *argv[])
+{
+ int i;
+
+ if (argc != 0) {
+ usage();
+ return RB_ERR_INVALID;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(rbcfg_envs); i++) {
+ const struct rbcfg_env *env = &rbcfg_envs[i];
+ const char *value;
+
+ value = rbcfg_env_get(env);
+ if (value)
+ fprintf(stdout, "%s=%s\n", env->name, value);
+ }
+
+ return 0;
+}
+
+static const struct rbcfg_command rbcfg_commands[] = {
+ {
+ .command = "apply",
+ .usage = "apply\n"
+ "\t- write configuration to the mtd device",
+ .flags = CMD_FLAG_USES_CFG,
+ .exec = rbcfg_cmd_apply,
+ }, {
+ .command = "help",
+ .usage = "help\n"
+ "\t- show this screen",
+ .exec = rbcfg_cmd_help,
+ }, {
+ .command = "get",
+ .usage = "get <name>\n"
+ "\t- get value of the configuration option <name>",
+ .flags = CMD_FLAG_USES_CFG,
+ .exec = rbcfg_cmd_get,
+ }, {
+ .command = "set",
+ .usage = "set <name> <value>\n"
+ "\t- set value of the configuration option <name> to <value>",
+ .flags = CMD_FLAG_USES_CFG,
+ .exec = rbcfg_cmd_set,
+ }, {
+ .command = "show",
+ .usage = "show\n"
+ "\t- show value of all configuration options",
+ .flags = CMD_FLAG_USES_CFG,
+ .exec = rbcfg_cmd_show,
+ }
+};
+
+static void
+usage(void)
+{
+ char buf[255];
+ int len;
+ int i;
+
+ fprintf(stderr, "Usage: %s <command>\n", rbcfg_name);
+
+ fprintf(stderr, "\nCommands:\n");
+ for (i = 0; i < ARRAY_SIZE(rbcfg_commands); i++) {
+ const struct rbcfg_command *cmd;
+ cmd = &rbcfg_commands[i];
+
+ len = snprintf(buf, sizeof(buf), cmd->usage);
+ buf[len] = '\0';
+ fprintf(stderr, "%s\n", buf);
+ }
+
+ fprintf(stderr, "\nConfiguration options:\n");
+ for (i = 0; i < ARRAY_SIZE(rbcfg_envs); i++) {
+ const struct rbcfg_env *env;
+ int j;
+
+ env = &rbcfg_envs[i];
+ fprintf(stderr, "\n%s:\n", env->name);
+ for (j = 0; j < env->num_values; j++) {
+ const struct rbcfg_value *v = &env->values[j];
+ fprintf(stderr, "\t%-12s %s\n", v->name, v->desc);
+ }
+ }
+ fprintf(stderr, "\n");
+}
+
+int main(int argc, const char *argv[])
+{
+ const struct rbcfg_command *cmd = NULL;
+ int ret;
+ int i;
+
+ rbcfg_name = (char *) argv[0];
+
+ if (argc < 2) {
+ usage();
+ return EXIT_FAILURE;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(rbcfg_commands); i++) {
+ if (strcmp(rbcfg_commands[i].command, argv[1]) == 0) {
+ cmd = &rbcfg_commands[i];
+ break;
+ }
+ }
+
+ if (cmd == NULL) {
+ fprintf(stderr, "unknown command '%s'\n", argv[1]);
+ usage();
+ return EXIT_FAILURE;
+ }
+
+ argc -= 2;
+ argv += 2;
+
+ if (cmd->flags & CMD_FLAG_USES_CFG) {
+ ret = rbcfg_open();
+ if (ret)
+ return EXIT_FAILURE;
+ }
+
+ ret = cmd->exec(argc, argv);
+
+ if (cmd->flags & CMD_FLAG_USES_CFG)
+ rbcfg_close();
+
+ if (ret)
+ return EXIT_FAILURE;
+
+ return EXIT_SUCCESS;
+}
diff --git a/package/rbcfg/src/rbcfg.h b/package/rbcfg/src/rbcfg.h
new file mode 100644
index 000000000..899161a10
--- /dev/null
+++ b/package/rbcfg/src/rbcfg.h
@@ -0,0 +1,75 @@
+/*
+ * Mikrotik's RouterBOOT configuration defines
+ *
+ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * 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.
+ *
+ */
+
+#ifndef _RBCFG_H
+#define _RBCFG_H
+
+/*
+ * Magic numbers
+ */
+#define RB_MAGIC_SOFT 0x74666f53 /* 'Soft' */
+
+/*
+ * ID values for Software settings
+ */
+#define RB_ID_TERMINATOR 0
+#define RB_ID_UART_SPEED 1
+#define RB_ID_BOOT_DELAY 2
+#define RB_ID_BOOT_DEVICE 3
+#define RB_ID_BOOT_KEY 4
+#define RB_ID_CPU_MODE 5
+#define RB_ID_FW_VERSION 6
+#define RB_ID_SOFT_07 7
+#define RB_ID_SOFT_08 8
+#define RB_ID_BOOT_PROTOCOL 9
+#define RB_ID_SOFT_10 10
+#define RB_ID_SOFT_11 11
+#define RB_ID_BOOTER 13
+
+#define RB_UART_SPEED_115200 0
+#define RB_UART_SPEED_57600 1
+#define RB_UART_SPEED_38400 2
+#define RB_UART_SPEED_19200 3
+#define RB_UART_SPEED_9600 4
+#define RB_UART_SPEED_4800 5
+#define RB_UART_SPEED_2400 6
+#define RB_UART_SPEED_1200 7
+#define RB_UART_SPEED_OFF 8
+
+#define RB_BOOT_DELAY_1SEC 1
+#define RB_BOOT_DELAY_2SEC 2
+#define RB_BOOT_DELAY_3SEC 3
+#define RB_BOOT_DELAY_4SEC 4
+#define RB_BOOT_DELAY_5SEC 5
+#define RB_BOOT_DELAY_6SEC 6
+#define RB_BOOT_DELAY_7SEC 7
+#define RB_BOOT_DELAY_8SEC 8
+#define RB_BOOT_DELAY_9SEC 9
+
+#define RB_BOOT_DEVICE_ETHER 0
+#define RB_BOOT_DEVICE_NANDETH 1
+#define RB_BOOT_DEVICE_CFCARD 2
+#define RB_BOOT_DEVICE_ETHONCE 3
+#define RB_BOOT_DEVICE_NANDONLY 5
+
+#define RB_BOOT_KEY_ANY 0
+#define RB_BOOT_KEY_DEL 1
+
+#define RB_CPU_MODE_POWERSAVE 0
+#define RB_CPU_MODE_REGULAR 1
+
+#define RB_BOOT_PROTOCOL_BOOTP 0
+#define RB_BOOT_PROTOCOL_DHCP 1
+
+#define RB_BOOTER_REGULAR 0
+#define RB_BOOTER_BACKUP 1
+
+#endif /* _RBCFG_H */
diff --git a/package/redboot-ar231x/Makefile b/package/redboot-ar231x/Makefile
new file mode 100644
index 000000000..b07b5a3d2
--- /dev/null
+++ b/package/redboot-ar231x/Makefile
@@ -0,0 +1,52 @@
+#
+# Copyright (C) 2008 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=redboot-ar231x
+PKG_VERSION:=2010-10-26
+PKG_RELEASE=$(PKG_SOURCE_VERSION)
+
+PKG_TARGETS:=bin
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=git://nbd.name/redboot-ar231x.git
+PKG_SOURCE_VERSION:=327f02ce1645d3427f26cf8116353332c81564a9
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.bz2
+
+include $(INCLUDE_DIR)/package.mk
+
+export GCC_HONOUR_COPTS=s
+
+define Package/redboot-ar231x
+ SECTION:=boot
+ CATEGORY:=Boot Loaders
+ DEPENDS:=@TARGET_atheros @BROKEN
+ TITLE:=Tiny redboot for AR231x/AR531x
+endef
+
+define Build/Configure
+ mkdir -p $(PKG_BUILD_DIR)/host-build
+ if [ \! -x $(PKG_BUILD_DIR)/host-install/bin/ecosconfig ]; then ( \
+ cd $(PKG_BUILD_DIR)/host-build; \
+ ../ecos/host/configure \
+ --prefix=$(PKG_BUILD_DIR)/host-install \
+ --exec-prefix=$(PKG_BUILD_DIR)/host-install; \
+ CFLAGS="$(HOST_CFLAGS)" $(MAKE) all install; \
+ ) fi
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) all
+endef
+
+define Package/redboot-ar231x/install
+ $(CP) $(PKG_BUILD_DIR)/bin/* $(1)/
+endef
+
+$(eval $(call BuildPackage,redboot-ar231x))
diff --git a/package/redboot-ar231x/patches/010-fix-compile.patch b/package/redboot-ar231x/patches/010-fix-compile.patch
new file mode 100644
index 000000000..962b13349
--- /dev/null
+++ b/package/redboot-ar231x/patches/010-fix-compile.patch
@@ -0,0 +1,181 @@
+--- a/ecos/packages/hal/mips/ap30/current/cdl/hal_mips_ap30.cdl
++++ b/ecos/packages/hal/mips/ap30/current/cdl/hal_mips_ap30.cdl
+@@ -98,7 +98,7 @@ cdl_package CYGPKG_HAL_MIPS_AP30 {
+ $(CC) $(CFLAGS) $(INCLUDE_PATH) -Wp,-MD,plf_defs.tmp -o plf_mk_defs.tmp -S $<
+ fgrep .equ plf_mk_defs.tmp | sed s/#// > $@
+ @echo $@ ": \\" > $(notdir $@).deps
+- @tail +2 plf_defs.tmp >> $(notdir $@).deps
++ @tail -n +2 plf_defs.tmp >> $(notdir $@).deps
+ @echo >> $(notdir $@).deps
+ @rm plf_defs.tmp plf_mk_defs.tmp
+ }
+--- a/ecos/packages/hal/mips/ap43/current/cdl/hal_mips_ap43.cdl
++++ b/ecos/packages/hal/mips/ap43/current/cdl/hal_mips_ap43.cdl
+@@ -98,7 +98,7 @@ cdl_package CYGPKG_HAL_MIPS_AP43 {
+ $(CC) $(CFLAGS) $(INCLUDE_PATH) -Wp,-MD,plf_defs.tmp -o plf_mk_defs.tmp -S $<
+ fgrep .equ plf_mk_defs.tmp | sed s/#// > $@
+ @echo $@ ": \\" > $(notdir $@).deps
+- @tail +2 plf_defs.tmp >> $(notdir $@).deps
++ @tail -n +2 plf_defs.tmp >> $(notdir $@).deps
+ @echo >> $(notdir $@).deps
+ @rm plf_defs.tmp plf_mk_defs.tmp
+ }
+--- a/ecos/packages/hal/mips/ap48/current/cdl/hal_mips_ap48.cdl
++++ b/ecos/packages/hal/mips/ap48/current/cdl/hal_mips_ap48.cdl
+@@ -98,7 +98,7 @@ cdl_package CYGPKG_HAL_MIPS_AP48 {
+ $(CC) $(CFLAGS) $(INCLUDE_PATH) -Wp,-MD,plf_defs.tmp -o plf_mk_defs.tmp -S $<
+ fgrep .equ plf_mk_defs.tmp | sed s/#// > $@
+ @echo $@ ": \\" > $(notdir $@).deps
+- @tail +2 plf_defs.tmp >> $(notdir $@).deps
++ @tail -n +2 plf_defs.tmp >> $(notdir $@).deps
+ @echo >> $(notdir $@).deps
+ @rm plf_defs.tmp plf_mk_defs.tmp
+ }
+--- a/ecos/packages/hal/mips/ap51/current/cdl/hal_mips_ap51.cdl
++++ b/ecos/packages/hal/mips/ap51/current/cdl/hal_mips_ap51.cdl
+@@ -93,7 +93,7 @@ cdl_package CYGPKG_HAL_MIPS_AP51 {
+ $(CC) $(CFLAGS) $(INCLUDE_PATH) -Wp,-MD,plf_defs.tmp -o plf_mk_defs.tmp -S $<
+ fgrep .equ plf_mk_defs.tmp | sed s/#// > $@
+ @echo $@ ": \\" > $(notdir $@).deps
+- @tail +2 plf_defs.tmp >> $(notdir $@).deps
++ @tail -n +2 plf_defs.tmp >> $(notdir $@).deps
+ @echo >> $(notdir $@).deps
+ @rm plf_defs.tmp plf_mk_defs.tmp
+ }
+--- a/ecos/packages/hal/mips/ap53/current/cdl/hal_mips_ap53.cdl
++++ b/ecos/packages/hal/mips/ap53/current/cdl/hal_mips_ap53.cdl
+@@ -93,7 +93,7 @@ cdl_package CYGPKG_HAL_MIPS_AP53 {
+ $(CC) $(CFLAGS) $(INCLUDE_PATH) -Wp,-MD,plf_defs.tmp -o plf_mk_defs.tmp -S $<
+ fgrep .equ plf_mk_defs.tmp | sed s/#// > $@
+ @echo $@ ": \\" > $(notdir $@).deps
+- @tail +2 plf_defs.tmp >> $(notdir $@).deps
++ @tail -n +2 plf_defs.tmp >> $(notdir $@).deps
+ @echo >> $(notdir $@).deps
+ @rm plf_defs.tmp plf_mk_defs.tmp
+ }
+--- a/ecos/packages/hal/mips/ap61/current/cdl/hal_mips_ap61.cdl
++++ b/ecos/packages/hal/mips/ap61/current/cdl/hal_mips_ap61.cdl
+@@ -93,7 +93,7 @@ cdl_package CYGPKG_HAL_MIPS_AP61 {
+ $(CC) $(CFLAGS) $(INCLUDE_PATH) -Wp,-MD,plf_defs.tmp -o plf_mk_defs.tmp -S $<
+ fgrep .equ plf_mk_defs.tmp | sed s/#// > $@
+ @echo $@ ": \\" > $(notdir $@).deps
+- @tail +2 plf_defs.tmp >> $(notdir $@).deps
++ @tail -n +2 plf_defs.tmp >> $(notdir $@).deps
+ @echo >> $(notdir $@).deps
+ @rm plf_defs.tmp plf_mk_defs.tmp
+ }
+--- a/ecos/packages/hal/mips/ap65/current/cdl/hal_mips_ap65.cdl
++++ b/ecos/packages/hal/mips/ap65/current/cdl/hal_mips_ap65.cdl
+@@ -93,7 +93,7 @@ cdl_package CYGPKG_HAL_MIPS_AP65 {
+ $(CC) $(CFLAGS) $(INCLUDE_PATH) -Wp,-MD,plf_defs.tmp -o plf_mk_defs.tmp -S $<
+ fgrep .equ plf_mk_defs.tmp | sed s/#// > $@
+ @echo $@ ": \\" > $(notdir $@).deps
+- @tail +2 plf_defs.tmp >> $(notdir $@).deps
++ @tail -n +2 plf_defs.tmp >> $(notdir $@).deps
+ @echo >> $(notdir $@).deps
+ @rm plf_defs.tmp plf_mk_defs.tmp
+ }
+--- a/ecos/packages/hal/mips/pb32/current/cdl/hal_mips_pb32.cdl
++++ b/ecos/packages/hal/mips/pb32/current/cdl/hal_mips_pb32.cdl
+@@ -91,7 +91,7 @@ cdl_package CYGPKG_HAL_MIPS_PB32 {
+ $(CC) $(CFLAGS) $(INCLUDE_PATH) -Wp,-MD,plf_defs.tmp -o plf_mk_defs.tmp -S $<
+ fgrep .equ plf_mk_defs.tmp | sed s/#// > $@
+ @echo $@ ": \\" > $(notdir $@).deps
+- @tail +2 plf_defs.tmp >> $(notdir $@).deps
++ @tail -n +2 plf_defs.tmp >> $(notdir $@).deps
+ @echo >> $(notdir $@).deps
+ @rm plf_defs.tmp plf_mk_defs.tmp
+ }
+--- a/ecos/packages/hal/mips/pb44/current/cdl/hal_mips_pb44.cdl
++++ b/ecos/packages/hal/mips/pb44/current/cdl/hal_mips_pb44.cdl
+@@ -99,7 +99,7 @@ cdl_package CYGPKG_HAL_MIPS_PB44 {
+ $(CC) $(CFLAGS) $(INCLUDE_PATH) -Wp,-MD,plf_defs.tmp -o plf_mk_defs.tmp -S $<
+ fgrep .equ plf_mk_defs.tmp | sed s/#// > $@
+ @echo $@ ": \\" > $(notdir $@).deps
+- @tail +2 plf_defs.tmp >> $(notdir $@).deps
++ @tail -n +2 plf_defs.tmp >> $(notdir $@).deps
+ @echo >> $(notdir $@).deps
+ @rm plf_defs.tmp plf_mk_defs.tmp
+ }
+--- a/ecos/packages/hal/mips/pb45/current/cdl/hal_mips_pb45.cdl
++++ b/ecos/packages/hal/mips/pb45/current/cdl/hal_mips_pb45.cdl
+@@ -99,7 +99,7 @@ cdl_package CYGPKG_HAL_MIPS_PB45 {
+ $(CC) $(CFLAGS) $(INCLUDE_PATH) -Wp,-MD,plf_defs.tmp -o plf_mk_defs.tmp -S $<
+ fgrep .equ plf_mk_defs.tmp | sed s/#// > $@
+ @echo $@ ": \\" > $(notdir $@).deps
+- @tail +2 plf_defs.tmp >> $(notdir $@).deps
++ @tail -n +2 plf_defs.tmp >> $(notdir $@).deps
+ @echo >> $(notdir $@).deps
+ @rm plf_defs.tmp plf_mk_defs.tmp
+ }
+--- a/ecos/packages/hal/mips/tb225/current/cdl/hal_mips_tb225.cdl
++++ b/ecos/packages/hal/mips/tb225/current/cdl/hal_mips_tb225.cdl
+@@ -99,7 +99,7 @@ cdl_package CYGPKG_HAL_MIPS_TB225 {
+ $(CC) $(CFLAGS) $(INCLUDE_PATH) -Wp,-MD,plf_defs.tmp -o plf_mk_defs.tmp -S $<
+ fgrep .equ plf_mk_defs.tmp | sed s/#// > $@
+ @echo $@ ": \\" > $(notdir $@).deps
+- @tail +2 plf_defs.tmp >> $(notdir $@).deps
++ @tail -n +2 plf_defs.tmp >> $(notdir $@).deps
+ @echo >> $(notdir $@).deps
+ @rm plf_defs.tmp plf_mk_defs.tmp
+ }
+--- a/ecos/host/tools/configtool/standalone/common/cdl_exec.cxx
++++ b/ecos/host/tools/configtool/standalone/common/cdl_exec.cxx
+@@ -51,6 +51,7 @@
+ #endif
+ #include "build.hxx"
+ #include "cdl_exec.hxx"
++#include <linux/limits.h>
+
+ // ----------------------------------------------------------------------------
+ bool cdl_exec::quiet = false;
+--- a/ecos/host/tools/configtool/standalone/common/ecosconfig.cxx
++++ b/ecos/host/tools/configtool/standalone/common/ecosconfig.cxx
+@@ -50,6 +50,7 @@
+ #endif
+ #include "cdl_exec.hxx"
+ #include "ecosconfig.hxx"
++#include <cstring>
+
+ #define TOOL_VERSION "2.net"
+ #define TOOL_COPYRIGHT "Copyright (c) 2002 Red Hat, Inc."
+--- a/ecos/host/libcdl/build.cxx
++++ b/ecos/host/libcdl/build.cxx
+@@ -57,6 +57,7 @@
+ // It implicitly supplies <string>, <vector> and <map> because
+ // the class definitions rely on these headers.
+ #include <cdlcore.hxx>
++#include <cstring>
+
+ //}}}
+
+--- a/ecos/host/libcdl/parse.cxx
++++ b/ecos/host/libcdl/parse.cxx
+@@ -58,6 +58,7 @@
+ // It implicitly supplies <string>, <vector> and <map> because
+ // the class definitions rely on these headers.
+ #include <cdlcore.hxx>
++#include <cstring>
+
+ //}}}
+
+--- a/ecos/host/libcdl/cdlmisc.cxx
++++ b/ecos/host/libcdl/cdlmisc.cxx
+@@ -66,6 +66,7 @@
+
+ // For access to strtod()
+ #include <cstdlib>
++#include <cstring>
+
+ // strtod() involves errno...
+ #include <cerrno>
+--- a/ecos/host/infra/assert.cxx
++++ b/ecos/host/infra/assert.cxx
+@@ -61,6 +61,7 @@
+ // STDLIB is needed for exit() and the status codes.
+ #include <cstdio>
+ #include <cstdlib>
++#include <cstring>
+
+ #if defined(__unix__) || defined(__CYGWIN32__)
+ extern "C" {
diff --git a/package/relayd/Makefile b/package/relayd/Makefile
new file mode 100644
index 000000000..c8730a323
--- /dev/null
+++ b/package/relayd/Makefile
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2010-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=relayd
+PKG_VERSION:=2011-10-24
+PKG_RELEASE=$(PKG_SOURCE_VERSION)
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_URL:=git://nbd.name/relayd.git
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_VERSION:=4e8f1fa4ca2b176500362843a9e57ea5abd4b7a3
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/relayd
+ SECTION:=net
+ CATEGORY:=Network
+ SUBMENU:=Routing and Redirection
+ TITLE:=Transparent routing / relay daemon
+ DEPENDS:=+libubox
+endef
+
+TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include
+
+define Package/relayd/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/relayd $(1)/usr/sbin/relayd
+ $(INSTALL_DIR) $(1)/etc/hotplug.d/iface
+ $(INSTALL_DATA) ./files/relay.hotplug $(1)/etc/hotplug.d/iface/30-relay
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/relay.init $(1)/etc/init.d/relayd
+endef
+
+$(eval $(call BuildPackage,relayd))
diff --git a/package/relayd/files/relay.hotplug b/package/relayd/files/relay.hotplug
new file mode 100644
index 000000000..afffbfeab
--- /dev/null
+++ b/package/relayd/files/relay.hotplug
@@ -0,0 +1,2 @@
+#!/bin/sh
+/etc/init.d/relayd enabled && /etc/init.d/relayd start
diff --git a/package/relayd/files/relay.init b/package/relayd/files/relay.init
new file mode 100644
index 000000000..43ba6e10f
--- /dev/null
+++ b/package/relayd/files/relay.init
@@ -0,0 +1,97 @@
+#!/bin/sh /etc/rc.common
+# Copyright (c) 2011-2012 OpenWrt.org
+START=80
+
+resolve_ifname() {
+ grep -qs "^ *$1:" /proc/net/dev && {
+ append args "-I $1"
+ append ifaces "$1"
+ }
+}
+
+resolve_network() {
+ local ifn
+ fixup_interface "$1"
+ config_get ifn "$1" ifname
+ [ -z "$ifn" ] && return 1
+ resolve_ifname "$ifn"
+}
+
+start_relay() {
+ local cfg="$1"
+
+ local args=""
+ local ifaces=""
+
+ config_get proto "$cfg" proto
+ [[ "$proto" == relay ]] || return 0
+
+ SERVICE_DAEMONIZE=1
+ SERVICE_WRITE_PID=1
+ SERVICE_PID_FILE="/var/run/relay-$cfg.pid"
+ [ -f "$SERVICE_PID_FILE" ] && {
+ if grep -q relayd "/proc/$(cat $SERVICE_PID_FILE)/cmdline"; then
+ return 0
+ else
+ rm -f "$SERVICE_PID_FILE"
+ fi
+ }
+
+ local net networks
+ config_get networks "$cfg" network
+ for net in $networks; do
+ resolve_network "$net" || {
+ return 1
+ }
+ done
+
+ local ifn ifnames
+ config_get ifnames "$cfg" ifname
+ for ifn in $ifnames; do
+ resolve_ifname "$ifn"
+ done
+
+ local ipaddr
+ config_get ipaddr "$cfg" ipaddr
+ [ -n "$ipaddr" ] && append args "-L $ipaddr"
+
+ local gateway
+ config_get gateway "$cfg" gateway
+ [ -n "$gateway" ] && append args "-G $gateway"
+
+ local expiry # = 30
+ config_get expiry "$cfg" expiry
+ [ -n "$expiry" ] && append args "-t $expiry"
+
+ local retry # = 5
+ config_get retry "$cfg" retry
+ [ -n "$retry" ] && append args "-p $retry"
+
+ local table # = 16800
+ config_get table "$cfg" table
+ [ -n "$table" ] && append args "-T $table"
+
+ local fwd_bcast # = 1
+ config_get_bool fwd_bcast "$cfg" forward_bcast 1
+ [ $fwd_bcast -eq 1 ] && append args "-B"
+
+ local fwd_dhcp # = 1
+ config_get_bool fwd_dhcp "$cfg" forward_dhcp 1
+ [ $fwd_dhcp -eq 1 ] && append args "-D"
+
+ service_start /usr/sbin/relayd $args
+}
+
+stop() {
+ for pid in /var/run/relay-*.pid; do
+ SERVICE_PID_FILE="$pid"
+ service_stop /usr/sbin/relayd
+ rm -f "$SERVICE_PID_FILE"
+ done
+}
+
+start() {
+ include /lib/network
+ config_load network
+ config_foreach start_relay interface
+}
diff --git a/package/resolveip/Makefile b/package/resolveip/Makefile
new file mode 100644
index 000000000..6ab04e162
--- /dev/null
+++ b/package/resolveip/Makefile
@@ -0,0 +1,44 @@
+#
+# Copyright (C) 2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=resolveip
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/resolveip
+ SECTION:=utils
+ CATEGORY:=Base system
+ TITLE:=Simple DNS resolver with configurable timeout
+endef
+
+define Package/resolveip/description
+ This package contains the small resolveip utility which
+ can be used by scripts to turn host names into numeric
+ IP addresses. It supports IPv4 and IPv6 resolving and
+ has a configurable timeout to guarantee a certain maximum
+ runtime in case of slow or defunct DNS servers.
+endef
+
+define Build/Prepare
+ $(INSTALL_DIR) $(PKG_BUILD_DIR)
+ $(INSTALL_DATA) ./src/resolveip.c $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ $(TARGET_CC) $(TARGET_CFLAGS) -Wall \
+ -o $(PKG_BUILD_DIR)/resolveip $(PKG_BUILD_DIR)/resolveip.c
+endef
+
+define Package/resolveip/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/resolveip $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,resolveip))
diff --git a/package/resolveip/src/resolveip.c b/package/resolveip/src/resolveip.c
new file mode 100644
index 000000000..310f35ffd
--- /dev/null
+++ b/package/resolveip/src/resolveip.c
@@ -0,0 +1,98 @@
+/*
+ * Based on code found at https://dev.openwrt.org/ticket/4876 .
+ * Extended by Jo-Philipp Wich <jow@openwrt.org> for use in OpenWrt.
+ *
+ * You may use this program under the terms of the GPLv2 license.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+
+
+static void abort_query(int sig)
+{
+ exit(1);
+}
+
+static void show_usage(void)
+{
+ printf("Usage:\n");
+ printf(" resolveip -h\n");
+ printf(" resolveip [-t timeout] hostname\n");
+ printf(" resolveip -4 [-t timeout] hostname\n");
+ printf(" resolveip -6 [-t timeout] hostname\n");
+ exit(255);
+}
+
+int main(int argc, char **argv)
+{
+ int timeout = 3;
+ char opt;
+ char ipaddr[INET6_ADDRSTRLEN];
+ void *addr;
+ struct addrinfo *res, *rp;
+ struct sigaction sa = { .sa_handler = &abort_query };
+ struct addrinfo hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_STREAM,
+ .ai_protocol = IPPROTO_TCP,
+ .ai_flags = 0
+ };
+
+ while ((opt = getopt(argc, argv, "46t:h")) > -1)
+ {
+ switch (opt)
+ {
+ case '4':
+ hints.ai_family = AF_INET;
+ break;
+
+ case '6':
+ hints.ai_family = AF_INET6;
+ break;
+
+ case 't':
+ timeout = atoi(optarg);
+ if (timeout <= 0)
+ show_usage();
+ break;
+
+ case 'h':
+ show_usage();
+ break;
+ }
+ }
+
+ if (!argv[optind])
+ show_usage();
+
+ sigaction(SIGALRM, &sa, NULL);
+ alarm(timeout);
+
+ if (getaddrinfo(argv[optind], NULL, &hints, &res))
+ exit(2);
+
+ for (rp = res; rp != NULL; rp = rp->ai_next)
+ {
+ addr = (rp->ai_family == AF_INET)
+ ? (void *)&((struct sockaddr_in *)rp->ai_addr)->sin_addr
+ : (void *)&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr
+ ;
+
+ if (!inet_ntop(rp->ai_family, addr, ipaddr, INET6_ADDRSTRLEN - 1))
+ exit(3);
+
+ printf("%s\n", ipaddr);
+ }
+
+ freeaddrinfo(res);
+ exit(0);
+}
diff --git a/package/robocfg/Makefile b/package/robocfg/Makefile
new file mode 100644
index 000000000..4bc72f51d
--- /dev/null
+++ b/package/robocfg/Makefile
@@ -0,0 +1,39 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=robocfg
+PKG_VERSION:=0.01
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/robocfg
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/robocfg
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=BCM5325E/536x switch configuration utility
+endef
+
+define Package/robocfg/description
+ This package contains an utility for configuring the Broadcom BCM5325E/536x
+ based switches.
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Package/robocfg/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/robocfg $(1)/sbin/
+endef
+
+$(eval $(call BuildPackage,robocfg))
diff --git a/package/robocfg/src/Makefile b/package/robocfg/src/Makefile
new file mode 100644
index 000000000..e11acb020
--- /dev/null
+++ b/package/robocfg/src/Makefile
@@ -0,0 +1,11 @@
+
+all: robocfg
+
+%.o: %.c
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $^
+
+robocfg: robocfg.o
+ $(CC) -o $@ $^
+
+clean:
+ rm -f *.o robocfg
diff --git a/package/robocfg/src/etc53xx.h b/package/robocfg/src/etc53xx.h
new file mode 100644
index 000000000..d5b1310cb
--- /dev/null
+++ b/package/robocfg/src/etc53xx.h
@@ -0,0 +1,619 @@
+/*
+ * Broadcom Home Gateway Reference Design
+ * BCM53xx Register definitions
+ *
+ * Copyright 2004, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ */
+
+#ifndef __BCM535M_H_
+#define __BCM535M_H_
+
+/* ROBO embedded device type */
+#define ROBO_DEV_5380 1
+#define ROBO_DEV_5365 2
+#define ROBO_DEV_5350 3
+
+/* BCM5325m GLOBAL PAGE REGISTER MAP */
+#ifndef _CFE_
+#pragma pack(1)
+#endif
+
+/* BCM5325m Serial Management Port (SMP) Page offsets */
+#define ROBO_CTRL_PAGE 0x00 /* Control registers */
+#define ROBO_STAT_PAGE 0x01 /* Status register */
+#define ROBO_MGMT_PAGE 0x02 /* Management Mode registers */
+#define ROBO_MIB_AC_PAGE 0x03 /* MIB Autocast registers */
+#define ROBO_ARLCTRL_PAGE 0x04 /* ARL Control Registers */
+#define ROBO_ARLIO_PAGE 0x05 /* ARL Access Registers */
+#define ROBO_FRAMEBUF_PAGE 0x06 /* Management frame access registers */
+#define ROBO_MEM_ACCESS_PAGE 0x08 /* Memory access registers */
+
+/* PHY Registers */
+#define ROBO_PORT0_MII_PAGE 0x10 /* Port 0 MII Registers */
+#define ROBO_PORT1_MII_PAGE 0x11 /* Port 1 MII Registers */
+#define ROBO_PORT2_MII_PAGE 0x12 /* Port 2 MII Registers */
+#define ROBO_PORT3_MII_PAGE 0x13 /* Port 3 MII Registers */
+#define ROBO_PORT4_MII_PAGE 0x14 /* Port 4 MII Registers */
+/* (start) registers only for BCM5380 */
+#define ROBO_PORT5_MII_PAGE 0x15 /* Port 5 MII Registers */
+#define ROBO_PORT6_MII_PAGE 0x16 /* Port 6 MII Registers */
+#define ROBO_PORT7_MII_PAGE 0x17 /* Port 7 MII Registers */
+/* (end) registers only for BCM5380 */
+#define ROBO_IM_PORT_PAGE 0x18 /* Inverse MII Port (to EMAC) */
+#define ROBO_ALL_PORT_PAGE 0x19 /* All ports MII Registers (broadcast)*/
+
+/* MAC Statistics registers */
+#define ROBO_PORT0_MIB_PAGE 0x20 /* Port 0 10/100 MIB Statistics */
+#define ROBO_PORT1_MIB_PAGE 0x21 /* Port 1 10/100 MIB Statistics */
+#define ROBO_PORT2_MIB_PAGE 0x22 /* Port 2 10/100 MIB Statistics */
+#define ROBO_PORT3_MIB_PAGE 0x23 /* Port 3 10/100 MIB Statistics */
+#define ROBO_PORT4_MIB_PAGE 0x24 /* Port 4 10/100 MIB Statistics */
+/* (start) registers only for BCM5380 */
+#define ROBO_PORT5_MIB_PAGE 0x25 /* Port 5 10/100 MIB Statistics */
+#define ROBO_PORT6_MIB_PAGE 0x26 /* Port 6 10/100 MIB Statistics */
+#define ROBO_PORT7_MIB_PAGE 0x27 /* Port 7 10/100 MIB Statistics */
+/* (end) registers only for BCM5380 */
+#define ROBO_IM_PORT_MIB_PAGE 0x28 /* Inverse MII Port MIB Statistics */
+
+/* Quality of Service (QoS) Registers */
+#define ROBO_QOS_PAGE 0x30 /* QoS Registers */
+
+/* VLAN Registers */
+#define ROBO_VLAN_PAGE 0x34 /* VLAN Registers */
+
+/* Note SPI Data/IO Registers not used */
+#define ROBO_SPI_DATA_IO_0_PAGE 0xf0 /* SPI Data I/O 0 */
+#define ROBO_SPI_DATA_IO_1_PAGE 0xf1 /* SPI Data I/O 1 */
+#define ROBO_SPI_DATA_IO_2_PAGE 0xf2 /* SPI Data I/O 2 */
+#define ROBO_SPI_DATA_IO_3_PAGE 0xf3 /* SPI Data I/O 3 */
+#define ROBO_SPI_DATA_IO_4_PAGE 0xf4 /* SPI Data I/O 4 */
+#define ROBO_SPI_DATA_IO_5_PAGE 0xf5 /* SPI Data I/O 5 */
+#define ROBO_SPI_DATA_IO_6_PAGE 0xf6 /* SPI Data I/O 6 */
+#define ROBO_SPI_DATA_IO_7_PAGE 0xf7 /* SPI Data I/O 7 */
+
+#define ROBO_SPI_STATUS_PAGE 0xfe /* SPI Status Registers */
+#define ROBO_PAGE_PAGE 0xff /* Page Registers */
+
+
+/* BCM5325m CONTROL PAGE (0x00) REGISTER MAP : 8bit (byte) registers */
+typedef struct _ROBO_PORT_CTRL_STRUC
+{
+ unsigned char rx_disable:1; /* rx disable */
+ unsigned char tx_disable:1; /* tx disable */
+ unsigned char rsvd:3; /* reserved */
+ unsigned char stp_state:3; /* spanning tree state */
+} ROBO_PORT_CTRL_STRUC;
+
+#define ROBO_PORT0_CTRL 0x00 /* 10/100 Port 0 Control */
+#define ROBO_PORT1_CTRL 0x01 /* 10/100 Port 1 Control */
+#define ROBO_PORT2_CTRL 0x02 /* 10/100 Port 2 Control */
+#define ROBO_PORT3_CTRL 0x03 /* 10/100 Port 3 Control */
+#define ROBO_PORT4_CTRL 0x04 /* 10/100 Port 4 Control */
+/* (start) registers only for BCM5380 */
+#define ROBO_PORT5_CTRL 0x05 /* 10/100 Port 5 Control */
+#define ROBO_PORT6_CTRL 0x06 /* 10/100 Port 6 Control */
+#define ROBO_PORT7_CTRL 0x07 /* 10/100 Port 7 Control */
+/* (end) registers only for BCM5380 */
+#define ROBO_IM_PORT_CTRL 0x08 /* 10/100 Port 8 Control */
+#define ROBO_SMP_CTRL 0x0a /* SMP Control register */
+#define ROBO_SWITCH_MODE 0x0b /* Switch Mode Control */
+#define ROBO_PORT_OVERRIDE_CTRL 0x0e /* Port state override */
+#define ROBO_PORT_OVERRIDE_RVMII (1<<4) /* Bit 4 enables RvMII */
+#define ROBO_PD_MODE_CTRL 0x0f /* Power-down mode control */
+#define ROBO_IP_MULTICAST_CTRL 0x21 /* IP Multicast control */
+
+/* BCM5325m STATUS PAGE (0x01) REGISTER MAP : 16bit/48bit registers */
+#define ROBO_HALF_DUPLEX 0
+#define ROBO_FULL_DUPLEX 1
+
+#define ROBO_LINK_STAT_SUMMARY 0x00 /* Link Status Summary: 16bit */
+#define ROBO_LINK_STAT_CHANGE 0x02 /* Link Status Change: 16bit */
+#define ROBO_SPEED_STAT_SUMMARY 0x04 /* Port Speed Summary: 16bit*/
+#define ROBO_DUPLEX_STAT_SUMMARY 0x06 /* Duplex Status Summary: 16bit */
+#define ROBO_PAUSE_STAT_SUMMARY 0x08 /* PAUSE Status Summary: 16bit */
+#define ROBO_SOURCE_ADDR_CHANGE 0x0C /* Source Address Change: 16bit */
+#define ROBO_LSA_PORT0 0x10 /* Last Source Addr, Port 0: 48bits*/
+#define ROBO_LSA_PORT1 0x16 /* Last Source Addr, Port 1: 48bits*/
+#define ROBO_LSA_PORT2 0x1c /* Last Source Addr, Port 2: 48bits*/
+#define ROBO_LSA_PORT3 0x22 /* Last Source Addr, Port 3: 48bits*/
+#define ROBO_LSA_PORT4 0x28 /* Last Source Addr, Port 4: 48bits*/
+#define ROBO_LSA_IM_PORT 0x40 /* Last Source Addr, IM Port: 48bits*/
+
+/* BCM5325m MANAGEMENT MODE REGISTERS (0x02) REGISTER MAP: 8/48 bit regs*/
+typedef struct _ROBO_GLOBAL_CONFIG_STRUC
+{
+ unsigned char resetMIB:1; /* reset MIB counters */
+ unsigned char rxBPDU:1; /* receive BDPU enable */
+ unsigned char rsvd1:2; /* reserved */
+ unsigned char MIBacHdrCtrl:1; /* MIB autocast header control */
+ unsigned char MIBac:1; /* MIB autocast enable */
+ unsigned char frameMgmtPort:2; /* frame management port */
+} ROBO_GLOBAL_CONFIG_STRUC;
+#define ROBO_GLOBAL_CONFIG 0x00 /* Global Management Config: 8bit*/
+#define ROBO_MGMT_PORT_ID 0x02 /* Management Port ID: 8bit*/
+#define ROBO_RMON_MIB_STEER 0x04 /* RMON Mib Steering: 16bit */
+#define ROBO_MIB_MODE_SELECT 0x04 /* MIB Mode select: 16bit (BCM5350) */
+#define ROBO_AGE_TIMER_CTRL 0x06 /* Age time control: 32bit */
+#define ROBO_MIRROR_CAP_CTRL 0x10 /* Mirror Capture : 16bit */
+#define ROBO_MIRROR_ING_CTRL 0x12 /* Mirror Ingress Control: 16bit */
+#define ROBO_MIRROR_ING_DIV_CTRL 0x14 /* Mirror Ingress Divider: 16bit */
+#define ROBO_MIRROR_ING_MAC_ADDR 0x16 /* Ingress Mirror MAC Addr: 48bit*/
+#define ROBO_MIRROR_EGR_CTRL 0x1c /* Mirror Egress Control: 16bit */
+#define ROBO_MIRROR_EGR_DIV_CTRL 0x1e /* Mirror Egress Divider: 16bit */
+#define ROBO_MIRROR_EGR_MAC_ADDR 0x20 /* Egress Mirror MAC Addr: 48bit*/
+
+/* BCM5325m MIB AUTOCAST REGISTERS (0x03) REGISTER MAP: 8/16/48 bit regs */
+#define ROBO_MIB_AC_PORT 0x00 /* MIB Autocast Port: 16bit */
+#define ROBO_MIB_AC_HDR_PTR 0x02 /* MIB Autocast Header pointer:16bit*/
+#define ROBO_MIB_AC_HDR_LEN 0x04 /* MIB Autocast Header Len: 16bit */
+#define ROBO_MIB_AC_DA 0x06 /* MIB Autocast DA: 48bit */
+#define ROBO_MIB_AC_SA 0x0c /* MIB Autocast SA: 48bit */
+#define ROBO_MIB_AC_TYPE 0x12 /* MIB Autocast Type: 16bit */
+#define ROBO_MIB_AC_RATE 0x14 /* MIB Autocast Rate: 8bit */
+#define ROBO_GET_AC_RATE(secs) ((secs)*10)
+#define ROBO_AC_RATE_MAX 0xff
+#define ROBO_AC_RATE_DEFAULT 0x64 /* 10 secs */
+typedef struct _ROBO_MIB_AC_STRUCT
+{
+ unsigned char opcode:4; /* Tx MIB Autocast opcode */
+ unsigned char portno:4; /* zero-based port no. */
+ unsigned char portstate:8; /* port state */
+ unsigned long long TxOctets;
+ unsigned int TxDropPkts;
+ unsigned int rsvd;
+ unsigned int TxBroadcastPkts;
+ unsigned int TxMulticastPkts;
+ unsigned int TxUnicastPkts;
+ unsigned int TxCollisions;
+ unsigned int TxSingleCollision;
+ unsigned int TxMultiCollision;
+ unsigned int TxDeferredTransmit;
+ unsigned int TxLateCollision;
+ unsigned int TxExcessiveCollision;
+ unsigned int TxFrameInDiscards;
+ unsigned int TxPausePkts;
+ unsigned int rsvd1[2];
+ unsigned long long RxOctets;
+ unsigned int RxUndersizePkts;
+ unsigned int RxPausePkts;
+ unsigned int RxPkts64Octets;
+ unsigned int RxPkts64to127Octets;
+ unsigned int RxPkts128to255Octets;
+ unsigned int RxPkts256to511Octets;
+ unsigned int RxPkts512to1023Octets;
+ unsigned int RxPkts1024to1522Octets;
+ unsigned int RxOversizePkts;
+ unsigned int RxJabbers;
+ unsigned int RxAlignmentErrors;
+ unsigned int RxFCSErrors;
+ unsigned long long RxGoodOctets;
+ unsigned int RxDropPkts;
+ unsigned int RxUnicastPkts;
+ unsigned int RxMulticastPkts;
+ unsigned int RxBroadcastPkts;
+ unsigned int RxSAChanges;
+ unsigned int RxFragments;
+ unsigned int RxExcessSizeDisc;
+ unsigned int RxSymbolError;
+} ROBO_MIB_AC_STRUCT;
+
+/* BCM5325m ARL CONTROL REGISTERS (0x04) REGISTER MAP: 8/16/48/64 bit regs */
+#define ROBO_ARL_CONFIG 0x00 /* ARL Global Configuration: 8bit*/
+#define ROBO_BPDU_MC_ADDR_REG 0x04 /* BPDU Multicast Address Reg:64bit*/
+#define ROBO_MULTIPORT_ADDR_1 0x10 /* Multiport Address 1: 48 bits*/
+#define ROBO_MULTIPORT_VECTOR_1 0x16 /* Multiport Vector 1: 16 bits */
+#define ROBO_MULTIPORT_ADDR_2 0x20 /* Multiport Address 2: 48 bits*/
+#define ROBO_MULTIPORT_VECTOR_2 0x26 /* Multiport Vector 2: 16 bits */
+#define ROBO_SECURE_SRC_PORT_MASK 0x30 /* Secure Source Port Mask: 16 bits*/
+#define ROBO_SECURE_DST_PORT_MASK 0x32 /* Secure Dest Port Mask: 16 bits */
+
+
+/* BCM5325m ARL IO REGISTERS (0x05) REGISTER MAP: 8/16/48/64 bit regs */
+#define ARL_TABLE_WRITE 0 /* for read/write state in control reg */
+#define ARL_TABLE_READ 1 /* for read/write state in control reg */
+#ifdef BCM5380
+#define ARL_VID_BYTES 2 /* number of bytes for VID */
+#else
+#define ARL_VID_BYTES 1 /* number of bytes for VID */
+#endif
+typedef struct _ROBO_ARL_RW_CTRL_STRUC
+{
+ unsigned char ARLrw:1; /* ARL read/write (1=read) */
+ unsigned char rsvd:6; /* reserved */
+ unsigned char ARLStart:1; /* ARL start/done (1=start) */
+} ROBO_ARL_RW_CTRL_STRUC;
+typedef struct _ROBO_ARL_SEARCH_CTRL_STRUC
+{
+ unsigned char valid:1; /* ARL search result valid */
+ unsigned char rsvd:6; /* reserved */
+ unsigned char ARLStart:1; /* ARL start/done (1=start) */
+} ROBO_ARL_SEARCH_CTRL_STRUC;
+typedef struct _ROBO_ARL_ENTRY_CTRL_STRUC
+{
+ unsigned char portID:4; /* port id */
+ unsigned char chipID:2; /* chip id */
+ unsigned char rsvd:5; /* reserved */
+ unsigned char prio:2; /* priority */
+ unsigned char age:1; /* age */
+ unsigned char staticEn:1; /* static */
+ unsigned char valid:1; /* valid */
+} ROBO_ARL_ENTRY_CTRL_STRUC;
+typedef struct _ROBO_ARL_SEARCH_RESULT_CTRL_STRUC
+{
+ unsigned char portID:4; /* port id */
+ unsigned char rsvd:1; /* reserved */
+ unsigned char vid:8; /* vlan id */
+ unsigned char age:1; /* age */
+ unsigned char staticEn:1; /* static */
+ unsigned char valid:1; /* valid */
+} ROBO_ARL_SEARCH_RESULT_CTRL_STRUC;
+typedef struct _ROBO_ARL_ENTRY_MAC_STRUC
+{
+ unsigned char macBytes[6]; /* MAC address */
+} ROBO_ARL_ENTRY_MAC_STRUC;
+
+typedef struct _ROBO_ARL_ENTRY_STRUC
+{
+ ROBO_ARL_ENTRY_MAC_STRUC mac; /* MAC address */
+ ROBO_ARL_ENTRY_CTRL_STRUC ctrl; /* control bits */
+} ROBO_ARL_ENTRY_STRUC;
+
+typedef struct _ROBO_ARL_SEARCH_RESULT_STRUC
+{
+ ROBO_ARL_ENTRY_MAC_STRUC mac; /* MAC address */
+ ROBO_ARL_SEARCH_RESULT_CTRL_STRUC ctrl; /* control bits */
+} ROBO_ARL_SEARCH_RESULT_STRUC;
+
+/* multicast versions of ARL entry structs */
+typedef struct _ROBO_ARL_ENTRY_MCAST_CTRL_STRUC
+{
+ unsigned int portMask:12;/* multicast port mask */
+ unsigned char prio:1; /* priority */
+ unsigned char gigPort:1; /* gigabit port 1 mask */
+ unsigned char staticEn:1; /* static */
+ unsigned char valid:1; /* valid */
+} ROBO_ARL_ENTRY_MCAST_CTRL_STRUC;
+typedef struct _ROBO_ARL_SEARCH_RESULT_MCAST_CTRL_STRUC
+{
+ unsigned int portMask:13; /* multicast port mask */
+ unsigned char age:1; /* age */
+ unsigned char staticEn:1; /* static */
+ unsigned char valid:1; /* valid */
+} ROBO_ARL_SEARCH_RESULT_MCAST_CTRL_STRUC;
+/* BCM5350 extension register */
+typedef struct _ROBO_ARL_SEARCH_RESULT_EXTENSION
+{
+ unsigned int prio:2; /* priority */
+ unsigned int portMask:1; /* MSB (MII) of port mask for multicast */
+ unsigned int reserved:5;
+} ROBO_ARL_SEARCH_RESULT_EXTENSION;
+
+typedef struct _ROBO_ARL_ENTRY_MCAST_STRUC
+{
+ ROBO_ARL_ENTRY_MAC_STRUC mac; /* MAC address */
+ ROBO_ARL_ENTRY_MCAST_CTRL_STRUC ctrl; /* control bits */
+} ROBO_ARL_ENTRY_MCAST_STRUC;
+typedef struct _ROBO_ARL_SEARCH_RESULT_MCAST_STRUC
+{
+ ROBO_ARL_ENTRY_MAC_STRUC mac; /* MAC address */
+ ROBO_ARL_SEARCH_RESULT_MCAST_CTRL_STRUC ctrl; /* control bits */
+} ROBO_ARL_SEARCH_RESULT_MCAST_STRUC;
+
+#define ROBO_ARL_RW_CTRL 0x00 /* ARL Read/Write Control : 8bit */
+#define ROBO_ARL_MAC_ADDR_IDX 0x02 /* MAC Address Index: 48bit */
+#define ROBO_ARL_VID_TABLE_IDX 0x08 /* VID Table Address Index: 8bit */
+#define ROBO_ARL_ENTRY0 0x10 /* ARL Entry 0 : 64 bit */
+#define ROBO_ARL_ENTRY1 0x18 /* ARL Entry 1 : 64 bit */
+#define ROBO_ARL_SEARCH_CTRL 0x20 /* ARL Search Control: 8bit */
+#define ROBO_ARL_SEARCH_ADDR 0x22 /* ARL Search Address: 16bit */
+#define ROBO_ARL_SEARCH_RESULT 0x24 /* ARL Search Result: 64bit */
+#define ROBO_ARL_SEARCH_RESULT_EXT 0x2c /* ARL Search Result Extension (5350): 8bit */
+#define ROBO_ARL_VID_ENTRY0 0x30 /* ARL VID Entry 0: 64bit */
+#define ROBO_ARL_VID_ENTRY1 0x32 /* ARL VID Entry 1: 64bit */
+
+/* BCM5325m MANAGEMENT FRAME REGISTERS (0x6) REGISTER MAP: 8/16 bit regs */
+#define ROBO_MGMT_FRAME_RD_DATA 0x00 /* Management Frame Read Data :8bit*/
+#define ROBO_MGMT_FRAME_WR_DATA 0x01 /* Management Frame Write Data:8bit*/
+#define ROBO_MGMT_FRAME_WR_CTRL 0x02 /* Write Control: 16bit */
+#define ROBO_MGMT_FRAME_RD_STAT 0x04 /* Read Status: 16bit */
+
+/* BCM5325m MEMORY ACCESS REGISTERS (Page 0x08) REGISTER MAP: 32 bit regs */
+#define MEM_TABLE_READ 1 /* for read/write state in mem access reg */
+#define MEM_TABLE_WRITE 0 /* for read/write state in mem access reg */
+#define MEM_TABLE_ACCESS_START 1 /* for mem access read/write start */
+#define MEM_TABLE_ACCESS_DONE 0 /* for mem access read/write done */
+#define VLAN_TABLE_ADDR 0x3800 /* BCM5380 only */
+#ifdef BCM5380
+#define NUM_ARL_TABLE_ENTRIES 4096 /* number of entries in ARL table */
+#define NUM_VLAN_TABLE_ENTRIES 2048 /* number of entries in VLAN table */
+#define ARL_TABLE_ADDR 0 /* offset of ARL table start */
+#else
+#define NUM_ARL_TABLE_ENTRIES 2048 /* number of entries in ARL table */
+#define NUM_VLAN_TABLE_ENTRIES 256 /* number of entries in VLAN table */
+#define ARL_TABLE_ADDR 0x3800 /* offset of ARL table start */
+/* corresponding values for 5350 */
+#define NUM_ARL_TABLE_ENTRIES_5350 1024 /* number of entries in ARL table (5350) */
+#define NUM_VLAN_TABLE_ENTRIES_5350 16 /* number of entries in VLAN table */
+#define ARL_TABLE_ADDR_5350 0x1c00 /* offset of ARL table start (5350) */
+#endif
+typedef struct _ROBO_MEM_ACCESS_CTRL_STRUC
+{
+ unsigned int memAddr:14; /* 64-bit memory address */
+ unsigned char rsvd:4; /* reserved */
+ unsigned char readEn:1; /* read enable (0 == write) */
+ unsigned char startDone:1;/* memory access start/done */
+ unsigned int rsvd1:12; /* reserved */
+} ROBO_MEM_ACCESS_CTRL_STRUC;
+typedef struct _ROBO_MEM_ACCESS_DATA_STRUC
+{
+ unsigned int memData[2]; /* 64-bit data */
+ unsigned short rsvd; /* reserved */
+} ROBO_MEM_ACCESS_DATA_STRUC;
+
+#ifdef BCM5380
+typedef struct _ROBO_ARL_TABLE_DATA_STRUC
+{
+ unsigned char MACaddr[6]; /* MAC addr */
+ unsigned int portID:4; /* port ID */
+ unsigned int chipID:2; /* chip ID */
+ unsigned int rsvd:6; /* reserved */
+ unsigned int highPrio:1; /* high priority address */
+ unsigned int age:1; /* entry accessed/learned since ageing process */
+ unsigned int staticAddr:1;/* entry is static */
+ unsigned int valid:1; /* entry is valid */
+ unsigned int vid:12; /* vlan id */
+ unsigned int rsvd2:4; /* reserved */
+} ROBO_ARL_TABLE_DATA_STRUC;
+#else
+typedef struct _ROBO_ARL_TABLE_DATA_STRUC
+{
+ unsigned char MACaddr[6]; /* MAC addr */
+ unsigned int portID:4; /* port ID */
+ unsigned int chipID:2; /* chip ID */
+ unsigned int rsvd:7; /* reserved */
+ unsigned int age:1; /* entry accessed/learned since ageing process */
+ unsigned int staticAddr:1;/* entry is static */
+ unsigned int valid:1; /* entry is valid */
+} ROBO_ARL_TABLE_DATA_STRUC;
+#endif
+
+/* multicast format*/
+typedef struct _ROBO_ARL_TABLE_MCAST_DATA_STRUC
+{
+ unsigned char MACaddr[6]; /* MAC addr */
+ unsigned int portMask:12;/* multicast port mask */
+ unsigned char prio:1; /* priority */
+ unsigned char gigPort:1; /* gigabit port 1 mask */
+ unsigned char staticEn:1; /* static */
+ unsigned char valid:1; /* valid */
+ unsigned int vid:12; /* vlan id */
+ unsigned int rsvd2:4; /* reserved */
+} ROBO_ARL_TABLE_MCAST_DATA_STRUC;
+#define ROBO_MEM_ACCESS_CTRL 0x00 /* Memory Read/Write Control :32bit*/
+#define ROBO_MEM_ACCESS_DATA 0x04 /* Memory Read/Write Data:64bit*/
+
+/* BCM5325m SWITCH PORT (0x10-18) REGISTER MAP: 8/16 bit regs */
+typedef struct _ROBO_MII_CTRL_STRUC
+{
+ unsigned char rsvd:8; /* reserved */
+ unsigned char duplex:1; /* duplex mode */
+ unsigned char restartAN:1;/* restart auto-negotiation */
+ unsigned char rsvd1:1; /* reserved */
+ unsigned char powerDown:1;/* power down */
+ unsigned char ANenable:1; /* auto-negotiation enable */
+ unsigned char speed:1; /* forced speed selection */
+ unsigned char loopback:1; /* loopback */
+ unsigned char reset:1; /* reset */
+} ROBO_MII_CTRL_STRUC;
+typedef struct _ROBO_MII_AN_ADVERT_STRUC
+{
+ unsigned char selector:5; /* advertise selector field */
+ unsigned char T10BaseT:1; /* advertise 10BaseT */
+ unsigned char T10BaseTFull:1; /* advertise 10BaseT, full duplex */
+ unsigned char T100BaseX:1; /* advertise 100BaseX */
+ unsigned char T100BaseXFull:1;/* advertise 100BaseX full duplex */
+ unsigned char noT4:1; /* do not advertise T4 */
+ unsigned char pause:1; /* advertise pause for full duplex */
+ unsigned char rsvd:2; /* reserved */
+ unsigned char remoteFault:1; /* transmit remote fault */
+ unsigned char rsvd1:1; /* reserved */
+ unsigned char nextPage:1; /* nex page operation supported */
+} ROBO_MII_AN_ADVERT_STRUC;
+#define ROBO_MII_CTRL 0x00 /* Port MII Control */
+#define ROBO_MII_STAT 0x02 /* Port MII Status */
+/* Fields of link status register */
+#define ROBO_MII_STAT_JABBER (1<<1) /* Jabber detected */
+#define ROBO_MII_STAT_LINK (1<<2) /* Link status */
+
+#define ROBO_MII_PHYID_HI 0x04 /* Port PHY ID High */
+#define ROBO_MII_PHYID_LO 0x06 /* Port PHY ID Low */
+#define ROBO_MII_ANA_REG 0x08 /* MII Auto-Neg Advertisement */
+#define ROBO_MII_ANP_REG 0x0a /* MII Auto-Neg Partner Ability */
+#define ROBO_MII_AN_EXP_REG 0x0c /* MII Auto-Neg Expansion */
+#define ROBO_MII_AN_NP_REG 0x0e /* MII next page */
+#define ROBO_MII_ANP_NP_REG 0x10 /* MII Partner next page */
+#define ROBO_MII_100BX_AUX_CTRL 0x20 /* 100BASE-X Auxiliary Control */
+#define ROBO_MII_100BX_AUX_STAT 0x22 /* 100BASE-X Auxiliary Status */
+#define ROBO_MII_100BX_RCV_ERR_CTR 0x24 /* 100BASE-X Receive Error Ctr */
+#define ROBO_MII_100BX_RCV_FS_ERR 0x26 /* 100BASE-X Rcv False Sense Ctr */
+#define ROBO_MII_AUX_CTRL 0x30 /* Auxiliary Control/Status */
+/* Fields of Auxiliary control register */
+#define ROBO_MII_AUX_CTRL_FD (1<<0) /* Full duplex link detected*/
+#define ROBO_MII_AUX_CTRL_SP100 (1<<1) /* Speed 100 indication */
+#define ROBO_MII_AUX_STATUS 0x32 /* Aux Status Summary */
+#define ROBO_MII_CONN_STATUS 0x34 /* Aux Connection Status */
+#define ROBO_MII_AUX_MODE2 0x36 /* Aux Mode 2 */
+#define ROBO_MII_AUX_ERR_STATUS 0x38 /* Aux Error and General Status */
+#define ROBO_MII_AUX_MULTI_PHY 0x3c /* Aux Multiple PHY Register*/
+#define ROBO_MII_BROADCOM_TEST 0x3e /* Broadcom Test Register */
+
+
+/* BCM5325m PORT MIB REGISTERS (Pages 0x20-0x24,0x28) REGISTER MAP: 64/32 */
+/* Tranmit Statistics */
+#define ROBO_MIB_TX_OCTETS 0x00 /* 64b: TxOctets */
+#define ROBO_MIB_TX_DROP_PKTS 0x08 /* 32b: TxDropPkts */
+#define ROBO_MIB_TX_BC_PKTS 0x10 /* 32b: TxBroadcastPkts */
+#define ROBO_MIB_TX_MC_PKTS 0x14 /* 32b: TxMulticastPkts */
+#define ROBO_MIB_TX_UC_PKTS 0x18 /* 32b: TxUnicastPkts */
+#define ROBO_MIB_TX_COLLISIONS 0x1c /* 32b: TxCollisions */
+#define ROBO_MIB_TX_SINGLE_COLLISIONS 0x20 /* 32b: TxSingleCollision */
+#define ROBO_MIB_TX_MULTI_COLLISIONS 0x24 /* 32b: TxMultiCollision */
+#define ROBO_MIB_TX_DEFER_TX 0x28 /* 32b: TxDeferred Transmit */
+#define ROBO_MIB_TX_LATE_COLLISIONS 0x2c /* 32b: TxLateCollision */
+#define ROBO_MIB_EXCESS_COLLISIONS 0x30 /* 32b: TxExcessiveCollision*/
+#define ROBO_MIB_FRAME_IN_DISCARDS 0x34 /* 32b: TxFrameInDiscards */
+#define ROBO_MIB_TX_PAUSE_PKTS 0x38 /* 32b: TxPausePkts */
+
+/* Receive Statistics */
+#define ROBO_MIB_RX_OCTETS 0x44 /* 64b: RxOctets */
+#define ROBO_MIB_RX_UNDER_SIZE_PKTS 0x4c /* 32b: RxUndersizePkts(runts)*/
+#define ROBO_MIB_RX_PAUSE_PKTS 0x50 /* 32b: RxPausePkts */
+#define ROBO_MIB_RX_PKTS_64 0x54 /* 32b: RxPkts64Octets */
+#define ROBO_MIB_RX_PKTS_65_TO_127 0x58 /* 32b: RxPkts64to127Octets*/
+#define ROBO_MIB_RX_PKTS_128_TO_255 0x5c /* 32b: RxPkts128to255Octets*/
+#define ROBO_MIB_RX_PKTS_256_TO_511 0x60 /* 32b: RxPkts256to511Octets*/
+#define ROBO_MIB_RX_PKTS_512_TO_1023 0x64 /* 32b: RxPkts512to1023Octets*/
+#define ROBO_MIB_RX_PKTS_1024_TO_1522 0x68 /* 32b: RxPkts1024to1522Octets*/
+#define ROBO_MIB_RX_OVER_SIZE_PKTS 0x6c /* 32b: RxOversizePkts*/
+#define ROBO_MIB_RX_JABBERS 0x70 /* 32b: RxJabbers*/
+#define ROBO_MIB_RX_ALIGNMENT_ERRORS 0x74 /* 32b: RxAlignmentErrors*/
+#define ROBO_MIB_RX_FCS_ERRORS 0x78 /* 32b: RxFCSErrors */
+#define ROBO_MIB_RX_GOOD_OCTETS 0x7c /* 32b: RxGoodOctets */
+#define ROBO_MIB_RX_DROP_PKTS 0x84 /* 32b: RxDropPkts */
+#define ROBO_MIB_RX_UC_PKTS 0x88 /* 32b: RxUnicastPkts */
+#define ROBO_MIB_RX_MC_PKTS 0x8c /* 32b: RxMulticastPkts */
+#define ROBO_MIB_RX_BC_PKTS 0x90 /* 32b: RxBroadcastPkts */
+#define ROBO_MIB_RX_SA_CHANGES 0x94 /* 32b: RxSAChanges */
+#define ROBO_MIB_RX_FRAGMENTS 0x98 /* 32b: RxFragments */
+#define ROBO_MIB_RX_EXCESS_SZ_DISC 0x9c /* 32b: RxExcessSizeDisc*/
+#define ROBO_MIB_RX_SYMBOL_ERROR 0xa0 /* 32b: RxSymbolError */
+
+/* BCM5350 MIB Statistics */
+/* Group 0 */
+#define ROBO_MIB_TX_GOOD_PKTS 0x00 /* 16b: TxGoodPkts */
+#define ROBO_MIB_TX_UNICAST_PKTS 0x02 /* 16b: TxUnicastPkts */
+#define ROBO_MIB_RX_GOOD_PKTS 0x04 /* 16b: RxGoodPkts */
+#define ROBO_MIB_RX_GOOD_UNICAST_PKTS 0x06 /* 16b: RxGoodUnicastPkts */
+/* Group 1 */
+#define ROBO_MIB_TX_COLLISION 0x00 /* 16b: TxCollision */
+#define ROBO_MIB_TX_OCTETS_5350 0x02 /* 16b: TxOctets */
+#define ROBO_MIB_RX_FCS_ERRORS_5350 0x04 /* 16b: RxFCSErrors */
+#define ROBO_MIB_RX_GOOD_OCTETS_5350 0x06 /* 16b: RxGoodOctets */
+
+/* BCM5325m QoS REGISTERS (Page 0x30) REGISTER MAP: 8/16 */
+#define ROBO_QOS_CTRL 0x00 /* 16b: QoS Control Register */
+#define ROBO_QOS_LOCAL_WEIGHT_CTRL 0x10 /* 8b: Local HQ/LQ Weight Register*/
+#define ROBO_QOS_CPU_WEIGHT_CTRL 0x12 /* 8b: CPU HQ/LQ Weight Register*/
+#define ROBO_QOS_PAUSE_ENA 0x13 /* 16b: Qos Pause Enable Register*/
+#define ROBO_QOS_PRIO_THRESHOLD 0x15 /* 8b: Priority Threshold Register*/
+#define ROBO_QOS_RESERVED 0x16 /* 8b: Qos Reserved Register */
+
+/* BCM5325m VLAN REGISTERS (Page 0x34) REGISTER MAP: 8/16bit */
+typedef struct _ROBO_VLAN_CTRL0_STRUC
+{
+ unsigned char frameControlP:2; /* 802.1P frame control */
+ unsigned char frameControlQ:2; /* 802.1Q frame control */
+ unsigned char dropMissedVID:1; /* enable drop missed VID packet */
+ unsigned char vidMacHash:1; /* VID_MAC hash enable */
+ unsigned char vidMacCheck:1; /* VID_MAC check enable */
+ unsigned char VLANen:1; /* 802.1Q VLAN enable */
+} ROBO_VLAN_CTRL0_STRUC;
+#define VLAN_TABLE_WRITE 1 /* for read/write state in table access reg */
+#define VLAN_TABLE_READ 0 /* for read/write state in table access reg */
+#define VLAN_ID_HIGH_BITS 0 /* static high bits in table access reg */
+#define VLAN_ID_MAX 255 /* max VLAN id */
+#define VLAN_ID_MAX5350 15 /* max VLAN id (5350) */
+#define VLAN_ID_MASK VLAN_ID_MAX /* VLAN id mask */
+#ifdef BCM5380
+#define VLAN_UNTAG_SHIFT 13 /* for postioning untag bits in write reg */
+#define VLAN_VALID 0x4000000 /* valid bit in write reg */
+#else
+#define VLAN_UNTAG_SHIFT 7 /* for postioning untag bits in write reg */
+#define VLAN_VALID 0x4000 /* valid bit in write reg */
+/* corresponding values for 5350 */
+#define VLAN_UNTAG_SHIFT_5350 6 /* for postioning untag bits in write reg */
+#define VLAN_VALID_5350 0x00100000 /* valid bit in write reg */
+#endif
+typedef struct _ROBO_VLAN_TABLE_ACCESS_STRUC
+{
+ unsigned char VLANid:8; /* VLAN ID (low 8 bits) */
+ unsigned char VLANidHi:4; /* VLAN ID (fixed upper portion) */
+ unsigned char readWriteState:1; /* read/write state (write = 1) */
+ volatile unsigned char readWriteEnable:1; /* table read/write enable */
+ unsigned char rsvd:2; /* reserved */
+} ROBO_VLAN_TABLE_ACCESS_STRUC;
+#ifdef BCM5380
+typedef struct _ROBO_VLAN_READ_WRITE_STRUC
+{
+ unsigned int VLANgroup:13;/* VLAN group mask */
+ unsigned int VLANuntag:13;/* VLAN untag enable mask */
+ unsigned char valid:1; /* valid */
+ unsigned char rsvd:5; /* reserved */
+} ROBO_VLAN_READ_WRITE_STRUC;
+#else
+typedef struct _ROBO_VLAN_READ_WRITE_STRUC
+{
+ unsigned char VLANgroup:7; /* VLAN group mask */
+ unsigned char VLANuntag:7; /* VLAN untag enable mask */
+ unsigned char valid:1; /* valid */
+ unsigned char rsvd:1; /* reserved */
+} ROBO_VLAN_READ_WRITE_STRUC;
+typedef struct _ROBO_VLAN_READ_WRITE_STRUC_5350
+{
+ unsigned char VLANgroup:6; /* VLAN group mask */
+ unsigned char VLANuntag:6; /* VLAN untag enable mask */
+ unsigned char highVID:8; /* upper bits of vid */
+ unsigned char valid:1; /* valid */
+ unsigned int rsvd:11; /* reserved */
+} ROBO_VLAN_READ_WRITE_STRUC_5350;
+#endif
+#define ROBO_VLAN_CTRL0 0x00 /* 8b: VLAN Control 0 Register */
+#define ROBO_VLAN_CTRL1 0x01 /* 8b: VLAN Control 1 Register */
+#define ROBO_VLAN_CTRL2 0x02 /* 8b: VLAN Control 2 Register */
+#define ROBO_VLAN_CTRL3 0x03 /* 8b: VLAN Control 3 Register */
+#define ROBO_VLAN_CTRL4 0x04 /* 8b: VLAN Control 4 Register */
+#define ROBO_VLAN_CTRL5 0x05 /* 8b: VLAN Control 5 Register */
+#define ROBO_VLAN_TABLE_ACCESS 0x08 /* 14b: VLAN Table Access Register */
+#define ROBO_VLAN_TABLE_ACCESS_5350 0x06 /* 14b: VLAN Table Access Register (5350) */
+#define ROBO_VLAN_WRITE 0x0a /* 15b: VLAN Write Register */
+#define ROBO_VLAN_WRITE_5350 0x08 /* 15b: VLAN Write Register (5350) */
+#define ROBO_VLAN_READ 0x0c /* 15b: VLAN Read Register */
+#define ROBO_VLAN_PORT0_DEF_TAG 0x10 /* 16b: VLAN Port 0 Default Tag Register */
+#define ROBO_VLAN_PORT1_DEF_TAG 0x12 /* 16b: VLAN Port 1 Default Tag Register */
+#define ROBO_VLAN_PORT2_DEF_TAG 0x14 /* 16b: VLAN Port 2 Default Tag Register */
+#define ROBO_VLAN_PORT3_DEF_TAG 0x16 /* 16b: VLAN Port 3 Default Tag Register */
+#define ROBO_VLAN_PORT4_DEF_TAG 0x18 /* 16b: VLAN Port 4 Default Tag Register */
+#define ROBO_VLAN_PORTMII_DEF_TAG 0x1a /* 16b: VLAN Port MII Default Tag Register */
+/* 5380 only */
+#define ROBO_VLAN_PORT5_DEF_TAG 0x1a /* 16b: VLAN Port 5 Default Tag Register */
+#define ROBO_VLAN_PORT6_DEF_TAG 0x1c /* 16b: VLAN Port 6 Default Tag Register */
+#define ROBO_VLAN_PORT7_DEF_TAG 0x1e /* 16b: VLAN Port 7 Default Tag Register */
+
+/* obsolete */
+#define ROBO_VLAN_PORT0_CTRL 0x00 /* 16b: Port 0 VLAN Register */
+#define ROBO_VLAN_PORT1_CTRL 0x02 /* 16b: Port 1 VLAN Register */
+#define ROBO_VLAN_PORT2_CTRL 0x04 /* 16b: Port 2 VLAN Register */
+#define ROBO_VLAN_PORT3_CTRL 0x06 /* 16b: Port 3 VLAN Register */
+#define ROBO_VLAN_PORT4_CTRL 0x08 /* 16b: Port 4 VLAN Register */
+#define ROBO_VLAN_IM_PORT_CTRL 0x10 /* 16b: Inverse MII Port VLAN Reg */
+#define ROBO_VLAN_SMP_PORT_CTRL 0x12 /* 16b: Serial Port VLAN Register */
+#define ROBO_VLAN_PORTSPI_DEF_TAG 0x1c /* 16b: VLAN Port SPI Default Tag Register */
+#define ROBO_VLAN_PRIORITY_REMAP 0x20 /* 24b: VLAN Priority Re-Map Register */
+
+#ifndef _CFE_
+#pragma pack()
+#endif
+
+
+#endif /* !__BCM535M_H_ */
+
+
+
+
+
diff --git a/package/robocfg/src/robocfg.c b/package/robocfg/src/robocfg.c
new file mode 100644
index 000000000..7a4094dd4
--- /dev/null
+++ b/package/robocfg/src/robocfg.c
@@ -0,0 +1,581 @@
+/*
+ * Broadcom BCM5325E/536x switch configuration utility
+ *
+ * Copyright (C) 2005 Oleg I. Vdovikin
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+/* linux stuff */
+typedef u_int64_t u64;
+typedef u_int32_t u32;
+typedef u_int16_t u16;
+typedef u_int8_t u8;
+
+#include <linux/if.h>
+#include <linux/sockios.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+
+#include "etc53xx.h"
+#define ROBO_PHY_ADDR 0x1E /* robo switch phy address */
+
+/* MII registers */
+#define REG_MII_PAGE 0x10 /* MII Page register */
+#define REG_MII_ADDR 0x11 /* MII Address register */
+#define REG_MII_DATA0 0x18 /* MII Data register 0 */
+
+#define REG_MII_PAGE_ENABLE 1
+#define REG_MII_ADDR_WRITE 1
+#define REG_MII_ADDR_READ 2
+
+/* Private et.o ioctls */
+#define SIOCGETCPHYRD (SIOCDEVPRIVATE + 9)
+#define SIOCSETCPHYWR (SIOCDEVPRIVATE + 10)
+
+typedef struct {
+ struct ifreq ifr;
+ int fd;
+ int et; /* use private ioctls */
+} robo_t;
+
+static u16 mdio_read(robo_t *robo, u16 phy_id, u8 reg)
+{
+ if (robo->et) {
+ int args[2] = { reg };
+
+ if (phy_id != ROBO_PHY_ADDR) {
+ fprintf(stderr,
+ "Access to real 'phy' registers unavaliable.\n"
+ "Upgrade kernel driver.\n");
+
+ return 0xffff;
+ }
+
+ robo->ifr.ifr_data = (caddr_t) args;
+ if (ioctl(robo->fd, SIOCGETCPHYRD, (caddr_t)&robo->ifr) < 0) {
+ perror("SIOCGETCPHYRD");
+ exit(1);
+ }
+
+ return args[1];
+ } else {
+ struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&robo->ifr.ifr_data;
+ mii->phy_id = phy_id;
+ mii->reg_num = reg;
+ if (ioctl(robo->fd, SIOCGMIIREG, &robo->ifr) < 0) {
+ perror("SIOCGMIIREG");
+ exit(1);
+ }
+ return mii->val_out;
+ }
+}
+
+static void mdio_write(robo_t *robo, u16 phy_id, u8 reg, u16 val)
+{
+ if (robo->et) {
+ int args[2] = { reg, val };
+
+ if (phy_id != ROBO_PHY_ADDR) {
+ fprintf(stderr,
+ "Access to real 'phy' registers unavaliable.\n"
+ "Upgrade kernel driver.\n");
+ return;
+ }
+
+ robo->ifr.ifr_data = (caddr_t) args;
+ if (ioctl(robo->fd, SIOCSETCPHYWR, (caddr_t)&robo->ifr) < 0) {
+ perror("SIOCGETCPHYWR");
+ exit(1);
+ }
+ } else {
+ struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&robo->ifr.ifr_data;
+ mii->phy_id = phy_id;
+ mii->reg_num = reg;
+ mii->val_in = val;
+ if (ioctl(robo->fd, SIOCSMIIREG, &robo->ifr) < 0) {
+ perror("SIOCSMIIREG");
+ exit(1);
+ }
+ }
+}
+
+static int robo_reg(robo_t *robo, u8 page, u8 reg, u8 op)
+{
+ int i = 3;
+
+ /* set page number */
+ mdio_write(robo, ROBO_PHY_ADDR, REG_MII_PAGE,
+ (page << 8) | REG_MII_PAGE_ENABLE);
+
+ /* set register address */
+ mdio_write(robo, ROBO_PHY_ADDR, REG_MII_ADDR,
+ (reg << 8) | op);
+
+ /* check if operation completed */
+ while (i--) {
+ if ((mdio_read(robo, ROBO_PHY_ADDR, REG_MII_ADDR) & 3) == 0)
+ return 0;
+ }
+
+ fprintf(stderr, "robo_reg: timeout\n");
+ exit(1);
+
+ return 0;
+}
+
+static void robo_read(robo_t *robo, u8 page, u8 reg, u16 *val, int count)
+{
+ int i;
+
+ robo_reg(robo, page, reg, REG_MII_ADDR_READ);
+
+ for (i = 0; i < count; i++)
+ val[i] = mdio_read(robo, ROBO_PHY_ADDR, REG_MII_DATA0 + i);
+}
+
+static u16 robo_read16(robo_t *robo, u8 page, u8 reg)
+{
+ robo_reg(robo, page, reg, REG_MII_ADDR_READ);
+
+ return mdio_read(robo, ROBO_PHY_ADDR, REG_MII_DATA0);
+}
+
+static u32 robo_read32(robo_t *robo, u8 page, u8 reg)
+{
+ robo_reg(robo, page, reg, REG_MII_ADDR_READ);
+
+ return mdio_read(robo, ROBO_PHY_ADDR, REG_MII_DATA0) +
+ (mdio_read(robo, ROBO_PHY_ADDR, REG_MII_DATA0 + 1) << 16);
+}
+
+static void robo_write16(robo_t *robo, u8 page, u8 reg, u16 val16)
+{
+ /* write data */
+ mdio_write(robo, ROBO_PHY_ADDR, REG_MII_DATA0, val16);
+
+ robo_reg(robo, page, reg, REG_MII_ADDR_WRITE);
+}
+
+static void robo_write32(robo_t *robo, u8 page, u8 reg, u32 val32)
+{
+ /* write data */
+ mdio_write(robo, ROBO_PHY_ADDR, REG_MII_DATA0, val32 & 65535);
+ mdio_write(robo, ROBO_PHY_ADDR, REG_MII_DATA0 + 1, val32 >> 16);
+
+ robo_reg(robo, page, reg, REG_MII_ADDR_WRITE);
+}
+
+/* checks that attached switch is 5325E/5350 */
+static int robo_vlan5350(robo_t *robo)
+{
+ /* set vlan access id to 15 and read it back */
+ u16 val16 = 15;
+ robo_write16(robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
+
+ /* 5365 will refuse this as it does not have this reg */
+ return (robo_read16(robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350) == val16);
+}
+
+u8 port[6] = { 0, 1, 2, 3, 4, 8 };
+char ports[6] = { 'W', '4', '3', '2', '1', 'C' };
+char *rxtx[4] = { "enabled", "rx_disabled", "tx_disabled", "disabled" };
+char *stp[8] = { "none", "disable", "block", "listen", "learn", "forward", "6", "7" };
+
+struct {
+ char *name;
+ u16 bmcr;
+} media[5] = { { "auto", BMCR_ANENABLE | BMCR_ANRESTART },
+ { "10HD", 0 }, { "10FD", BMCR_FULLDPLX },
+ { "100HD", BMCR_SPEED100 }, { "100FD", BMCR_SPEED100 | BMCR_FULLDPLX } };
+
+struct {
+ char *name;
+ u16 value;
+} mdix[3] = { { "auto", 0x0000 }, { "on", 0x1800 }, { "off", 0x0800 } };
+
+void usage()
+{
+ fprintf(stderr, "Broadcom BCM5325E/536x switch configuration utility\n"
+ "Copyright (C) 2005 Oleg I. Vdovikin\n\n"
+ "This program is distributed in the hope that it will be useful,\n"
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+ "GNU General Public License for more details.\n\n");
+
+ fprintf(stderr, "Usage: robocfg <op> ... <op>\n"
+ "Operations are as below:\n"
+ "\tshow\n"
+ "\tswitch <enable|disable>\n"
+ "\tport <port_number> [state <%s|%s|%s|%s>]\n\t\t[stp %s|%s|%s|%s|%s|%s] [tag <vlan_tag>]\n"
+ "\t\t[media %s|%s|%s|%s|%s] [mdi-x %s|%s|%s]\n"
+ "\tvlan <vlan_number> [ports <ports_list>]\n"
+ "\tvlans <enable|disable|reset>\n\n"
+ "\tports_list should be one argument, space separated, quoted if needed,\n"
+ "\tport number could be followed by 't' to leave packet vlan tagged (CPU \n"
+ "\tport default) or by 'u' to untag packet (other ports default) before \n"
+ "\tbringing it to the port, '*' is ignored\n"
+ "\nSamples:\n"
+ "1) ASUS WL-500g Deluxe stock config (eth0 is WAN, eth0.1 is LAN):\n"
+ "robocfg switch disable vlans enable reset vlan 0 ports \"0 5u\" vlan 1 ports \"1 2 3 4 5t\""
+ " port 0 state enabled stp none switch enable\n"
+ "2) WRT54g, WL-500g Deluxe OpenWRT config (vlan0 is LAN, vlan1 is WAN):\n"
+ "robocfg switch disable vlans enable reset vlan 0 ports \"1 2 3 4 5t\" vlan 1 ports \"0 5t\""
+ " port 0 state enabled stp none switch enable\n",
+ rxtx[0], rxtx[1], rxtx[2], rxtx[3], stp[0], stp[1], stp[2], stp[3], stp[4], stp[5],
+ media[0].name, media[1].name, media[2].name, media[3].name, media[4].name,
+ mdix[0].name, mdix[1].name, mdix[2].name);
+}
+
+static robo_t robo;
+int bcm53xx_probe(const char *dev)
+{
+ struct ethtool_drvinfo info;
+ unsigned int phyid;
+ int ret;
+
+ fprintf(stderr, "probing %s\n", dev);
+
+ strcpy(robo.ifr.ifr_name, dev);
+ memset(&info, 0, sizeof(info));
+ info.cmd = ETHTOOL_GDRVINFO;
+ robo.ifr.ifr_data = (caddr_t)&info;
+ ret = ioctl(robo.fd, SIOCETHTOOL, (caddr_t)&robo.ifr);
+ if (ret < 0) {
+ perror("SIOCETHTOOL");
+ return ret;
+ }
+
+ if ( strcmp(info.driver, "et0") &&
+ strcmp(info.driver, "b44") &&
+ strcmp(info.driver, "bcm63xx_enet") ) {
+ fprintf(stderr, "driver not supported %s\n", info.driver);
+ return -ENOSYS;
+ }
+
+ /* try access using MII ioctls - get phy address */
+ robo.et = 0;
+ if (ioctl(robo.fd, SIOCGMIIPHY, &robo.ifr) < 0)
+ robo.et = 1;
+
+ if (robo.et) {
+ unsigned int args[2] = { 2 };
+
+ robo.ifr.ifr_data = (caddr_t) args;
+ ret = ioctl(robo.fd, SIOCGETCPHYRD, (caddr_t)&robo.ifr);
+ if (ret < 0) {
+ perror("SIOCGETCPHYRD");
+ return ret;
+ }
+ phyid = args[1] & 0xffff;
+
+ args[0] = 3;
+ robo.ifr.ifr_data = (caddr_t) args;
+ ret = ioctl(robo.fd, SIOCGETCPHYRD, (caddr_t)&robo.ifr);
+ if (ret < 0) {
+ perror("SIOCGETCPHYRD");
+ return ret;
+ }
+ phyid |= args[1] << 16;
+ } else {
+ struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&robo.ifr.ifr_data;
+ mii->phy_id = ROBO_PHY_ADDR;
+ mii->reg_num = 2;
+ ret = ioctl(robo.fd, SIOCGMIIREG, &robo.ifr);
+ if (ret < 0) {
+ perror("SIOCGMIIREG");
+ return ret;
+ }
+ phyid = mii->val_out & 0xffff;
+
+ mii->phy_id = ROBO_PHY_ADDR;
+ mii->reg_num = 3;
+ ret = ioctl(robo.fd, SIOCGMIIREG, &robo.ifr);
+ if (ret < 0) {
+ perror("SIOCGMIIREG");
+ return ret;
+ }
+ phyid |= mii->val_out << 16;
+ }
+
+ if (phyid == 0xffffffff || phyid == 0x55210022) {
+ perror("phyid");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+ u16 val16;
+ u16 mac[3];
+ int i = 0, j;
+ int robo5350 = 0;
+ u32 phyid;
+
+ if ((robo.fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror("socket");
+ exit(1);
+ }
+
+ if (bcm53xx_probe("eth1")) {
+ if (bcm53xx_probe("eth0")) {
+ perror("bcm53xx_probe");
+ exit(1);
+ }
+ }
+
+ robo5350 = robo_vlan5350(&robo);
+
+ for (i = 1; i < argc;) {
+ if (strcasecmp(argv[i], "port") == 0 && (i + 1) < argc)
+ {
+ int index = atoi(argv[++i]);
+ /* read port specs */
+ while (++i < argc) {
+ if (strcasecmp(argv[i], "state") == 0 && ++i < argc) {
+ for (j = 0; j < 4 && strcasecmp(argv[i], rxtx[j]); j++);
+ if (j < 4) {
+ /* change state */
+ robo_write16(&robo,ROBO_CTRL_PAGE, port[index],
+ (robo_read16(&robo, ROBO_CTRL_PAGE, port[index]) & ~(3 << 0)) | (j << 0));
+ } else {
+ fprintf(stderr, "Invalid state '%s'.\n", argv[i]);
+ exit(1);
+ }
+ } else
+ if (strcasecmp(argv[i], "stp") == 0 && ++i < argc) {
+ for (j = 0; j < 8 && strcasecmp(argv[i], stp[j]); j++);
+ if (j < 8) {
+ /* change stp */
+ robo_write16(&robo,ROBO_CTRL_PAGE, port[index],
+ (robo_read16(&robo, ROBO_CTRL_PAGE, port[index]) & ~(7 << 5)) | (j << 5));
+ } else {
+ fprintf(stderr, "Invalid stp '%s'.\n", argv[i]);
+ exit(1);
+ }
+ } else
+ if (strcasecmp(argv[i], "media") == 0 && ++i < argc) {
+ for (j = 0; j < 5 && strcasecmp(argv[i], media[j].name); j++);
+ if (j < 5) {
+ mdio_write(&robo, port[index], MII_BMCR, media[j].bmcr);
+ } else {
+ fprintf(stderr, "Invalid media '%s'.\n", argv[i]);
+ exit(1);
+ }
+ } else
+ if (strcasecmp(argv[i], "mdi-x") == 0 && ++i < argc) {
+ for (j = 0; j < 3 && strcasecmp(argv[i], mdix[j].name); j++);
+ if (j < 3) {
+ mdio_write(&robo, port[index], 0x1c, mdix[j].value |
+ (mdio_read(&robo, port[index], 0x1c) & ~0x1800));
+ } else {
+ fprintf(stderr, "Invalid mdi-x '%s'.\n", argv[i]);
+ exit(1);
+ }
+ } else
+ if (strcasecmp(argv[i], "tag") == 0 && ++i < argc) {
+ j = atoi(argv[i]);
+ /* change vlan tag */
+ robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (index << 1), j);
+ } else break;
+ }
+ } else
+ if (strcasecmp(argv[i], "vlan") == 0 && (i + 1) < argc)
+ {
+ int index = atoi(argv[++i]);
+ while (++i < argc) {
+ if (strcasecmp(argv[i], "ports") == 0 && ++i < argc) {
+ char *ports = argv[i];
+ int untag = 0;
+ int member = 0;
+
+ while (*ports >= '0' && *ports <= '9') {
+ j = *ports++ - '0';
+ member |= 1 << j;
+
+ /* untag if needed, CPU port requires special handling */
+ if (*ports == 'u' || (j != 5 && (*ports == ' ' || *ports == 0)))
+ {
+ untag |= 1 << j;
+ if (*ports) ports++;
+ /* change default vlan tag */
+ robo_write16(&robo, ROBO_VLAN_PAGE,
+ ROBO_VLAN_PORT0_DEF_TAG + (j << 1), index);
+ } else
+ if (*ports == '*' || *ports == 't' || *ports == ' ') ports++;
+ else break;
+
+ while (*ports == ' ') ports++;
+ }
+
+ if (*ports) {
+ fprintf(stderr, "Invalid ports '%s'.\n", argv[i]);
+ exit(1);
+ } else {
+ /* write config now */
+ val16 = (index) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */;
+ if (robo5350) {
+ robo_write32(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5350,
+ (1 << 20) /* valid */ | (untag << 6) | member);
+ robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
+ } else {
+ robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_WRITE,
+ (1 << 14) /* valid */ | (untag << 7) | member);
+ robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16);
+ }
+ }
+ } else break;
+ }
+ } else
+ if (strcasecmp(argv[i], "switch") == 0 && (i + 1) < argc)
+ {
+ /* enable/disable switching */
+ robo_write16(&robo, ROBO_CTRL_PAGE, ROBO_SWITCH_MODE,
+ (robo_read16(&robo, ROBO_CTRL_PAGE, ROBO_SWITCH_MODE) & ~2) |
+ (*argv[++i] == 'e' ? 2 : 0));
+ i++;
+ } else
+ if (strcasecmp(argv[i], "vlans") == 0 && (i + 1) < argc)
+ {
+ while (++i < argc) {
+ if (strcasecmp(argv[i], "reset") == 0) {
+ /* reset vlan validity bit */
+ for (j = 0; j <= (robo5350 ? VLAN_ID_MAX5350 : VLAN_ID_MAX); j++)
+ {
+ /* write config now */
+ val16 = (j) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */;
+ if (robo5350) {
+ robo_write32(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5350, 0);
+ robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
+ } else {
+ robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_WRITE, 0);
+ robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16);
+ }
+ }
+ } else
+ if (strcasecmp(argv[i], "enable") == 0 || strcasecmp(argv[i], "disable") == 0)
+ {
+ int disable = (*argv[i] == 'd') || (*argv[i] == 'D');
+ /* enable/disable vlans */
+ robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_CTRL0, disable ? 0 :
+ (1 << 7) /* 802.1Q VLAN */ | (3 << 5) /* mac check and hash */);
+
+ robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_CTRL1, disable ? 0 :
+ (1 << 1) | (1 << 2) | (1 << 3) /* RSV multicast */);
+
+ robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_CTRL4, disable ? 0 :
+ (1 << 6) /* drop invalid VID frames */);
+
+ robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_CTRL5, disable ? 0 :
+ (1 << 3) /* drop miss V table frames */);
+
+ } else break;
+ }
+ } else
+ if (strcasecmp(argv[i], "show") == 0)
+ {
+ break;
+ } else {
+ fprintf(stderr, "Invalid option %s\n", argv[i]);
+ usage();
+ exit(1);
+ }
+ }
+
+ if (i == argc) {
+ if (argc == 1) usage();
+ return 0;
+ }
+
+ /* show config */
+
+ printf("Switch: %sabled\n", robo_read16(&robo, ROBO_CTRL_PAGE, ROBO_SWITCH_MODE) & 2 ? "en" : "dis");
+
+ for (i = 0; i < 6; i++) {
+ printf(robo_read16(&robo, ROBO_STAT_PAGE, ROBO_LINK_STAT_SUMMARY) & (1 << port[i]) ?
+ "Port %d(%c): %s%s " : "Port %d(%c): DOWN ", i, ports[i],
+ robo_read16(&robo, ROBO_STAT_PAGE, ROBO_SPEED_STAT_SUMMARY) & (1 << port[i]) ? "100" : " 10",
+ robo_read16(&robo, ROBO_STAT_PAGE, ROBO_DUPLEX_STAT_SUMMARY) & (1 << port[i]) ? "FD" : "HD");
+
+ val16 = robo_read16(&robo, ROBO_CTRL_PAGE, port[i]);
+
+ printf("%s stp: %s vlan: %d ", rxtx[val16 & 3], stp[(val16 >> 5) & 7],
+ robo_read16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (i << 1)));
+
+ robo_read(&robo, ROBO_STAT_PAGE, ROBO_LSA_PORT0 + port[i] * 6, mac, 3);
+
+ printf("mac: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ mac[2] >> 8, mac[2] & 255, mac[1] >> 8, mac[1] & 255, mac[0] >> 8, mac[0] & 255);
+ }
+
+ val16 = robo_read16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_CTRL0);
+
+ printf("VLANs: %s %sabled%s%s\n",
+ robo5350 ? "BCM5325/535x" : "BCM536x",
+ (val16 & (1 << 7)) ? "en" : "dis",
+ (val16 & (1 << 6)) ? " mac_check" : "",
+ (val16 & (1 << 5)) ? " mac_hash" : "");
+
+ /* scan VLANs */
+ for (i = 0; i <= (robo5350 ? VLAN_ID_MAX5350 : VLAN_ID_MAX); i++) {
+ /* issue read */
+ val16 = (i) /* vlan */ | (0 << 12) /* read */ | (1 << 13) /* enable */;
+
+ if (robo5350) {
+ u32 val32;
+ robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
+ /* actual read */
+ val32 = robo_read32(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_READ);
+ if ((val32 & (1 << 20)) /* valid */) {
+ printf("vlan%d:", i);
+ for (j = 0; j < 6; j++) {
+ if (val32 & (1 << j)) {
+ printf(" %d%s", j, (val32 & (1 << (j + 6))) ?
+ (j == 5 ? "u" : "") : "t");
+ }
+ }
+ printf("\n");
+ }
+ } else {
+ robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16);
+ /* actual read */
+ val16 = robo_read16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_READ);
+ if ((val16 & (1 << 14)) /* valid */) {
+ printf("vlan%d:", i);
+ for (j = 0; j < 6; j++) {
+ if (val16 & (1 << j)) {
+ printf(" %d%s", j, (val16 & (1 << (j + 7))) ?
+ (j == 5 ? "u" : "") : "t");
+ }
+ }
+ printf("\n");
+ }
+ }
+ }
+
+ return (0);
+}
diff --git a/package/rotary-gpio-custom/Makefile b/package/rotary-gpio-custom/Makefile
new file mode 100644
index 000000000..315ec31f4
--- /dev/null
+++ b/package/rotary-gpio-custom/Makefile
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2008-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=rotary-gpio-custom
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/rotary-gpio-custom
+ SUBMENU:=Other modules
+ TITLE:=Custom GPIO-based rotary encoder device
+ DEPENDS:=@GPIO_SUPPORT +kmod-input-gpio-encoder
+ FILES:=$(PKG_BUILD_DIR)/rotary-gpio-custom.ko
+ KCONFIG:=
+endef
+
+define KernelPackage/rotary-gpio-custom/description
+ Kernel module for register a custom rotary-gpio-encoder platform device.
+endef
+
+EXTRA_KCONFIG:= \
+ CONFIG_ROTARY_GPIO_CUSTOM=m
+
+EXTRA_CFLAGS:= \
+ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \
+ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \
+
+MAKE_OPTS:= \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ SUBDIRS="$(PKG_BUILD_DIR)" \
+ EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
+ $(EXTRA_KCONFIG)
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ $(MAKE) -C "$(LINUX_DIR)" \
+ $(MAKE_OPTS) \
+ modules
+endef
+
+$(eval $(call KernelPackage,rotary-gpio-custom))
diff --git a/package/rotary-gpio-custom/src/Kconfig b/package/rotary-gpio-custom/src/Kconfig
new file mode 100644
index 000000000..b4d55d535
--- /dev/null
+++ b/package/rotary-gpio-custom/src/Kconfig
@@ -0,0 +1,9 @@
+config ROTARY_GPIO_CUSTOM
+ tristate "Custom GPIO-based rotary driver"
+ depends on GENERIC_GPIO
+ help
+ This is a driver to register 1 to 4 custom rotary encoder using
+ GPIO lines.
+
+ This support is also available as a module. If so, the module
+ will be called rotary-gpio-custom.
diff --git a/package/rotary-gpio-custom/src/Makefile b/package/rotary-gpio-custom/src/Makefile
new file mode 100644
index 000000000..133672687
--- /dev/null
+++ b/package/rotary-gpio-custom/src/Makefile
@@ -0,0 +1 @@
+obj-${CONFIG_ROTARY_GPIO_CUSTOM} += rotary-gpio-custom.o
diff --git a/package/rotary-gpio-custom/src/rotary-gpio-custom.c b/package/rotary-gpio-custom/src/rotary-gpio-custom.c
new file mode 100644
index 000000000..8cd8ef12a
--- /dev/null
+++ b/package/rotary-gpio-custom/src/rotary-gpio-custom.c
@@ -0,0 +1,188 @@
+/*
+ * Custom GPIO-based rotary driver
+ *
+ * Copyright (C) 2010 Claudio Mignanti <c.mignanti@gmail.com>
+ *
+ * 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.
+ *
+ * Strongly based on Custom GPIO-based I2C driver by:
+ * Copyright (C) 2007-2008 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * The behaviour of this driver can be altered by setting some parameters
+ * from the insmod command line.
+ *
+ * The following parameters are adjustable:
+ *
+ * bus0 These four arguments can be arrays of
+ * bus1 1-8 unsigned integers as follows:
+ * bus2
+ * bus3 <id>,<steps>,<axis>,<gpioa>,<gpiob>,<inverted>
+ *
+ *
+ * If this driver is built into the kernel, you can use the following kernel
+ * command line parameters, with the same values as the corresponding module
+ * parameters listed above:
+ *
+ * rotary-gpio-custom.bus0
+ * rotary-gpio-custom.bus1
+ * rotary-gpio-custom.bus2
+ * rotary-gpio-custom.bus3
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/rotary_encoder.h>
+
+#define DRV_NAME "rotary-gpio-custom"
+#define DRV_DESC "Custom GPIO-based rotary driver"
+#define DRV_VERSION "0.1.0"
+
+#define PFX DRV_NAME ": "
+
+#define BUS_PARAM_REQUIRED 5
+#define BUS_PARAM_COUNT 6
+#define BUS_COUNT_MAX 4
+
+static unsigned int bus0[BUS_PARAM_COUNT] __initdata;
+static unsigned int bus1[BUS_PARAM_COUNT] __initdata;
+static unsigned int bus2[BUS_PARAM_COUNT] __initdata;
+static unsigned int bus3[BUS_PARAM_COUNT] __initdata;
+
+static unsigned int bus_nump[BUS_COUNT_MAX] __initdata;
+
+#define BUS_PARM_DESC \
+ " config -> id,steps,axis,gpioa,gpiob[,inverted]"
+
+module_param_array(bus0, uint, &bus_nump[0], 0);
+MODULE_PARM_DESC(bus0, "bus0" BUS_PARM_DESC);
+module_param_array(bus1, uint, &bus_nump[1], 0);
+MODULE_PARM_DESC(bus1, "bus1" BUS_PARM_DESC);
+module_param_array(bus2, uint, &bus_nump[2], 0);
+MODULE_PARM_DESC(bus2, "bus2" BUS_PARM_DESC);
+module_param_array(bus3, uint, &bus_nump[3], 0);
+MODULE_PARM_DESC(bus3, "bus3" BUS_PARM_DESC);
+
+static struct platform_device *devices[BUS_COUNT_MAX];
+static unsigned int nr_devices;
+
+static void rotary_gpio_custom_cleanup(void)
+{
+ int i;
+
+ for (i = 0; i < nr_devices; i++)
+ if (devices[i])
+ platform_device_put(devices[i]);
+}
+
+static int __init rotary_gpio_custom_add_one(unsigned int id, unsigned int *params)
+{
+ struct platform_device *pdev;
+ struct rotary_encoder_platform_data pdata;
+ int err;
+
+ if (!bus_nump[id])
+ return 0;
+
+ if (bus_nump[id] < BUS_PARAM_REQUIRED) {
+ printk(KERN_ERR PFX "not enough parameters for bus%d\n", id);
+ err = -EINVAL;
+ goto err;
+ }
+
+ pdev = platform_device_alloc("rotary-gpio", params[0]);
+ if (!pdev) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ pdata.steps = params[1];
+ pdata.axis = params[2];
+ pdata.relative_axis = false;
+ pdata.rollover = false;
+ pdata.gpio_a = params[3];
+ pdata.gpio_b = params[4];
+
+ if (params[5] == 1) {
+ pdata.inverted_a = 1;
+ pdata.inverted_b = 1;
+ } else {
+ pdata.inverted_a = 0;
+ pdata.inverted_b = 0;
+ }
+
+ err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
+ if (err)
+ goto err_put;
+
+ err = platform_device_add(pdev);
+ if (err)
+ goto err_put;
+
+ devices[nr_devices++] = pdev;
+ return 0;
+
+err_put:
+ platform_device_put(pdev);
+err:
+ return err;
+}
+
+static int __init rotary_gpio_custom_probe(void)
+{
+ int err;
+
+ printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n");
+
+ err = rotary_gpio_custom_add_one(0, bus0);
+ if (err) goto err;
+
+ err = rotary_gpio_custom_add_one(1, bus1);
+ if (err) goto err;
+
+ err = rotary_gpio_custom_add_one(2, bus2);
+ if (err) goto err;
+
+ err = rotary_gpio_custom_add_one(3, bus3);
+ if (err) goto err;
+
+ if (!nr_devices) {
+ printk(KERN_ERR PFX "no bus parameter(s) specified\n");
+ err = -ENODEV;
+ goto err;
+ }
+
+ return 0;
+
+err:
+ rotary_gpio_custom_cleanup();
+ return err;
+}
+
+#ifdef MODULE
+static int __init rotary_gpio_custom_init(void)
+{
+ return rotary_gpio_custom_probe();
+}
+module_init(rotary_gpio_custom_init);
+
+static void __exit rotary_gpio_custom_exit(void)
+{
+ rotary_gpio_custom_cleanup();
+}
+module_exit(rotary_gpio_custom_exit);
+#else
+subsys_initcall(rotary_gpio_custom_probe);
+#endif /* MODULE*/
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org >");
+MODULE_AUTHOR("Claudio Mignanti <c.mignanti@gmail.com>");
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_VERSION(DRV_VERSION);
diff --git a/package/rssileds/Makefile b/package/rssileds/Makefile
new file mode 100644
index 000000000..27354f0fe
--- /dev/null
+++ b/package/rssileds/Makefile
@@ -0,0 +1,47 @@
+#
+# Copyright (C) 2011-2012 Daniel Golle <dgolle@allnet.de>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=rssileds
+PKG_VERSION:=0.1
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/rssileds
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=RSSI real-time LED indicator
+ DEPENDS:=libiwinfo
+endef
+
+define Package/rssileds/description
+ A small process written in C to update the signal-strength indicator LEDs
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+ $(TARGET_CC) $(TARGET_CFLAGS) -Wall -liwinfo \
+ -o $(PKG_BUILD_DIR)/rssileds $(PKG_BUILD_DIR)/rssileds.c
+endef
+
+define Package/rssileds/install
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/rssileds.init $(1)/etc/init.d/rssileds
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/rssileds $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,rssileds))
diff --git a/package/rssileds/files/rssileds.init b/package/rssileds/files/rssileds.init
new file mode 100644
index 000000000..b0d262725
--- /dev/null
+++ b/package/rssileds/files/rssileds.init
@@ -0,0 +1,75 @@
+#!/bin/sh /etc/rc.common
+# (C) 2012 Daniel Golle, Allnet GmbH <dgolle@allnet.de>
+
+START=96
+STOP=96
+RSSILEDS_BIN="/usr/sbin/rssileds"
+
+SERVICE_DAEMONIZE=1
+SERVICE_WRITE_PID=1
+
+start_rssid() {
+ local name
+ local dev
+ local threshold
+ local refresh
+ local leds
+ config_get name $1 name
+ config_get dev $1 dev
+ config_get threshold $1 threshold
+ config_get refresh $1 refresh
+ leds="$( cur_iface=$1 ; config_foreach get_led led )"
+ SERVICE_PID_FILE=/var/run/rssileds-$dev.pid
+ service_start $RSSILEDS_BIN $dev $refresh $threshold $leds
+}
+
+stop_rssid() {
+ local dev
+ config_get dev $1 dev
+ SERVICE_PID_FILE=/var/run/rssileds-$dev.pid
+ service_stop $RSSILEDS_BIN
+}
+
+get_led() {
+ local name
+ local sysfs
+ local trigger
+ local iface
+ config_get sysfs $1 sysfs
+ config_get name $1 name "$sysfs"
+ config_get trigger $1 trigger "none"
+ config_get iface $1 iface
+ config_get minq $1 minq
+ config_get maxq $1 maxq
+ config_get offset $1 offset
+ config_get factor $1 factor
+ [ "$trigger" = "rssi" ] || return
+ [ "$iface" = "$cur_iface" ] || return
+ [ ! "$minq" ] || [ ! "$maxq" ] || [ ! "$offset" ] || [ ! "$factor" ] && return
+ echo "none" > /sys/class/leds/$sysfs/trigger
+ echo "$sysfs $minq $maxq $offset $factor"
+}
+
+off_led() {
+ local name
+ local sysfs
+ local trigger
+ config_get sysfs $1 sysfs
+ config_get name $1 name "$sysfs"
+ config_get trigger $1 trigger "none"
+ [ "$trigger" = "rssi" ] || return
+ echo "0" > /sys/class/leds/$sysfs/brightness
+}
+
+start() {
+ [ -e /sys/class/leds/ ] && [ -x "$RSSILEDS_BIN" ] && {
+ config_load system
+ config_foreach start_rssid rssid
+ }
+}
+
+stop() {
+ config_load system
+ config_foreach stop_rssid rssid
+ config_foreach off_led led
+}
diff --git a/package/rssileds/src/rssileds.c b/package/rssileds/src/rssileds.c
new file mode 100644
index 000000000..2f25c846c
--- /dev/null
+++ b/package/rssileds/src/rssileds.c
@@ -0,0 +1,280 @@
+/*
+ * configurable RSSI LED control daemon for OpenWrt
+ * (c) 2012 Allnet GmbH, Daniel Golle <dgolle@allnet.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ *
+ * The author may be reached as dgolle@allnet.de, or
+ * ALLNET GmbH
+ * Maistr. 2
+ * D-82110 Germering
+ * Germany
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <syslog.h>
+
+#include "iwinfo.h"
+
+#define RUN_DIR "/var/run"
+#define LEDS_BASEPATH "/sys/class/leds/"
+#define BACKEND_RETRY_DELAY 500000
+
+char *ifname;
+int qual_max;
+
+struct led {
+ char *sysfspath;
+ FILE *controlfd;
+ unsigned char state;
+};
+
+typedef struct rule rule_t;
+struct rule {
+ struct led *led;
+ int minq;
+ int maxq;
+ int boffset;
+ int bfactor;
+ rule_t *next;
+};
+
+void log_rules(rule_t *rules)
+{
+ rule_t *rule = rules;
+ while (rule)
+ {
+ syslog(LOG_INFO, " %s r: %d..%d, o: %d, f: %d\n",
+ rule->led->sysfspath,
+ rule->minq, rule->maxq,
+ rule->boffset, rule->bfactor);
+ rule = rule->next;
+ }
+}
+
+int init_led(struct led **led, char *ledname)
+{
+ struct led *newled;
+ struct stat statbuffer;
+ int status;
+ char *bp;
+ FILE *bfp;
+
+ bp = calloc(sizeof(char), strlen(ledname) + strlen(LEDS_BASEPATH) + 12);
+ if ( ! bp )
+ goto return_error;
+
+ sprintf(bp, "%s%s/brightness", LEDS_BASEPATH, ledname);
+
+ status = stat(bp, &statbuffer);
+ if ( status )
+ goto cleanup_fname;
+
+ bfp = fopen( bp, "w" );
+ if ( !bfp )
+ goto cleanup_fname;
+
+ if ( ferror(bfp) )
+ goto cleanup_fp;
+
+ /* sysfs path exists and, allocate LED struct */
+ newled = calloc(sizeof(struct led),1);
+ if ( !newled )
+ goto cleanup_fp;
+
+ newled->sysfspath = bp;
+ newled->controlfd = bfp;
+
+ *led = newled;
+ return 0;
+
+cleanup_fp:
+ fclose(bfp);
+cleanup_fname:
+ free(bp);
+return_error:
+ syslog(LOG_CRIT, "can't open LED %s\n", ledname);
+ *led = NULL;
+ return -1;
+}
+
+void close_led(struct led **led)
+{
+ fclose((*led)->controlfd);
+ free((*led)->sysfspath);
+ free((*led));
+ (*led)=NULL;
+}
+
+int set_led(struct led *led, unsigned char value)
+{
+ char buf[8];
+
+ if ( ! led )
+ return -1;
+
+ if ( ! led->controlfd )
+ return -1;
+
+ snprintf(buf, 8, "%d", value);
+
+ rewind(led->controlfd);
+
+ if ( ! fwrite(buf, sizeof(char), strlen(buf), led->controlfd) )
+ return -2;
+
+ fflush(led->controlfd);
+ led->state=value;
+
+ return 0;
+}
+
+
+int quality(const struct iwinfo_ops *iw, const char *ifname)
+{
+ int qual;
+
+ if ( ! iw ) return -1;
+
+ if (qual_max < 1)
+ if (iw->quality_max(ifname, &qual_max))
+ return -1;
+
+ if (iw->quality(ifname, &qual))
+ return -1;
+
+ return ( qual * 100 ) / qual_max ;
+}
+
+int open_backend(const struct iwinfo_ops **iw, const char *ifname)
+{
+ *iw = iwinfo_backend(ifname);
+
+ if (!(*iw))
+ return 1;
+
+ return 0;
+}
+
+void update_leds(rule_t *rules, int q)
+{
+ rule_t *rule = rules;
+ while (rule)
+ {
+ int b;
+ /* offset and factore correction according to rule */
+ b = ( q + rule->boffset ) * rule->bfactor;
+ if ( b < 0 )
+ b=0;
+ if ( b > 255 )
+ b=255;
+
+ if ( q >= rule->minq && q <= rule->maxq )
+ set_led(rule->led, (unsigned char)b);
+ else
+ set_led(rule->led, 0);
+
+ rule = rule->next;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int i,q,q0,r,s;
+ const struct iwinfo_ops *iw = NULL;
+ rule_t *headrule = NULL, *currentrule = NULL;
+
+ if (argc < 9 || ( (argc-4) % 5 != 0 ) )
+ {
+ printf("syntax: %s (ifname) (refresh) (threshold) (rule) [rule] ...\n", argv[0]);
+ printf(" rule: (sysfs-name) (minq) (maxq) (offset) (factore)\n");
+ return 1;
+ }
+
+ ifname = argv[1];
+
+ /* refresh interval */
+ if ( sscanf(argv[2], "%d", &r) != 1 )
+ return 1;
+
+ /* sustain threshold */
+ if ( sscanf(argv[3], "%d", &s) != 1 )
+ return 1;
+
+ openlog("rssileds", LOG_PID, LOG_DAEMON);
+ syslog(LOG_INFO, "monitoring %s, refresh rate %d, threshold %d\n", ifname, r, s);
+
+ currentrule = headrule;
+ for (i=4; i<argc; i=i+5) {
+ if (! currentrule)
+ {
+ /* first element in the list */
+ currentrule = calloc(sizeof(rule_t),1);
+ headrule = currentrule;
+ }
+ else
+ {
+ /* follow-up element */
+ currentrule->next = calloc(sizeof(rule_t),1);
+ currentrule = currentrule->next;
+ }
+
+ if ( init_led(&(currentrule->led), argv[i]) )
+ return 1;
+
+ if ( sscanf(argv[i+1], "%d", &(currentrule->minq)) != 1 )
+ return 1;
+
+ if ( sscanf(argv[i+2], "%d", &(currentrule->maxq)) != 1 )
+ return 1;
+
+ if ( sscanf(argv[i+3], "%d", &(currentrule->boffset)) != 1 )
+ return 1;
+
+ if ( sscanf(argv[i+4], "%d", &(currentrule->bfactor)) != 1 )
+ return 1;
+ }
+ log_rules(headrule);
+
+ q0 = -1;
+ do {
+ q = quality(iw, ifname);
+ if ( q < q0 - s || q > q0 + s ) {
+ update_leds(headrule, q);
+ q0=q;
+ };
+ // re-open backend...
+ if ( q == -1 && q0 == -1 ) {
+ if (iw) {
+ iwinfo_finish();
+ iw=NULL;
+ usleep(BACKEND_RETRY_DELAY);
+ }
+ while (open_backend(&iw, ifname))
+ usleep(BACKEND_RETRY_DELAY);
+ }
+ usleep(r);
+ } while(1);
+
+ iwinfo_finish();
+
+ return 0;
+}
diff --git a/package/rtc-rv5c386a/Makefile b/package/rtc-rv5c386a/Makefile
new file mode 100644
index 000000000..e13ead528
--- /dev/null
+++ b/package/rtc-rv5c386a/Makefile
@@ -0,0 +1,38 @@
+#
+# Copyright (C) 2006-2009 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=rtc-rv5c386a
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/rtc-rv5c386a
+ SUBMENU:=Other modules
+ DEPENDS:=@TARGET_brcm47xx
+ TITLE:=Driver for RTC RV5C386A (used in WL-700gE and WL-HDD)
+ AUTOLOAD:=$(call AutoLoad,70,rtc)
+ FILES:=$(PKG_BUILD_DIR)/rtc.ko
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ $(MAKE) -C "$(LINUX_DIR)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ ARCH="$(LINUX_KARCH)" \
+ SUBDIRS="$(PKG_BUILD_DIR)" \
+ EXTRA_CFLAGS="$(BUILDFLAGS)" \
+ modules
+endef
+
+$(eval $(call KernelPackage,rtc-rv5c386a))
diff --git a/package/rtc-rv5c386a/src/Makefile b/package/rtc-rv5c386a/src/Makefile
new file mode 100644
index 000000000..eeb043077
--- /dev/null
+++ b/package/rtc-rv5c386a/src/Makefile
@@ -0,0 +1,18 @@
+# $Id$
+#
+# Makefile for Real Time Clock driver for WL-HDD
+#
+# Copyright (C) 2007 Andreas Engel
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+
+obj-m := rtc.o
+
+ifeq ($(MAKING_MODULES),1)
+
+-include $(TOPDIR)/Rules.make
+endif
diff --git a/package/rtc-rv5c386a/src/rtc.c b/package/rtc-rv5c386a/src/rtc.c
new file mode 100644
index 000000000..7c51bf4bf
--- /dev/null
+++ b/package/rtc-rv5c386a/src/rtc.c
@@ -0,0 +1,611 @@
+/*
+ * Real Time Clock driver for WL-HDD
+ *
+ * Copyright (C) 2007 Andreas Engel
+ *
+ * Hacked together mostly by copying the relevant code parts from:
+ * drivers/i2c/i2c-bcm5365.c
+ * drivers/i2c/i2c-algo-bit.c
+ * drivers/char/rtc.c
+ *
+ * Note 1:
+ * This module uses the standard char device (10,135), while the Asus module
+ * rtcdrv.o uses (12,0). So, both can coexist which might be handy during
+ * development (but see the comment in rtc_open()).
+ *
+ * Note 2:
+ * You might need to set the clock once after loading the driver the first
+ * time because the driver switches the chip into 24h mode if it is running
+ * in 12h mode.
+ *
+ * Usage:
+ * For compatibility reasons with the original asus driver, the time can be
+ * read and set via the /dev/rtc device entry. The only accepted data format
+ * is "YYYY:MM:DD:W:HH:MM:SS\n". See OpenWrt wiki for a script which handles
+ * this format.
+ *
+ * In addition, this driver supports the standard ioctl() calls for setting
+ * and reading the hardware clock, so the ordinary hwclock utility can also
+ * be used.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * TODO:
+ * - add a /proc/driver/rtc interface?
+ * - make the battery failure bit available through the /proc interface?
+ *
+ * $Id: rtc.c 7 2007-05-25 19:37:01Z ae $
+ */
+
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/mc146818rtc.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/rtc.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/uaccess.h>
+
+#include <asm/current.h>
+#include <asm/system.h>
+
+#include <bcm47xx.h>
+#include <nvram.h>
+
+#define RTC_IS_OPEN 0x01 /* Means /dev/rtc is in use. */
+
+/* Can be changed via a module parameter. */
+static int rtc_debug = 0;
+
+static unsigned long rtc_status = 0; /* Bitmapped status byte. */
+
+/* These settings are platform dependents. */
+unsigned int sda_index = 0;
+unsigned int scl_index = 0;
+
+#define I2C_READ_MASK 1
+#define I2C_WRITE_MASK 0
+
+#define I2C_ACK 1
+#define I2C_NAK 0
+
+#define RTC_EPOCH 1900
+#define RTC_I2C_ADDRESS (0x32 << 1)
+#define RTC_24HOUR_MODE_MASK 0x20
+#define RTC_PM_MASK 0x20
+#define RTC_VDET_MASK 0x40
+#define RTC_Y2K_MASK 0x80
+
+/*
+ * Delay in microseconds for generating the pulses on the I2C bus. We use
+ * a rather conservative setting here. See datasheet of the RTC chip.
+ */
+#define ADAP_DELAY 50
+
+/* Avoid spurious compiler warnings. */
+#define UNUSED __attribute__((unused))
+
+MODULE_AUTHOR("Andreas Engel");
+MODULE_LICENSE("GPL");
+
+/* Test stolen from switch-adm.c. */
+module_param(rtc_debug, int, 0);
+
+static inline void sdalo(void)
+{
+ gpio_direction_output(sda_index, 1);
+ udelay(ADAP_DELAY);
+}
+
+static inline void sdahi(void)
+{
+ gpio_direction_input(sda_index);
+ udelay(ADAP_DELAY);
+}
+
+static inline void scllo(void)
+{
+ gpio_direction_output(scl_index, 1);
+ udelay(ADAP_DELAY);
+}
+
+static inline int getscl(void)
+{
+ return (gpio_get_value(scl_index));
+}
+
+static inline int getsda(void)
+{
+ return (gpio_get_value(sda_index));
+}
+
+/*
+ * We shouldn't simply set the SCL pin to high. Like SDA, the SCL line is
+ * bidirectional too. According to the I2C spec, the slave is allowed to
+ * pull down the SCL line to slow down the clock, so we need to check this.
+ * Generally, we'd need a timeout here, but in our case, we just check the
+ * line, assuming the RTC chip behaves well.
+ */
+static int sclhi(void)
+{
+ gpio_direction_input(scl_index);
+ udelay(ADAP_DELAY);
+ if (!getscl()) {
+ printk(KERN_ERR "SCL pin should be low\n");
+ return -ETIMEDOUT;
+ }
+ return 0;
+}
+
+static void i2c_start(void)
+{
+ sdalo();
+ scllo();
+}
+
+static void i2c_stop(void)
+{
+ sdalo();
+ sclhi();
+ sdahi();
+}
+
+static int i2c_outb(int c)
+{
+ int i;
+ int ack;
+
+ /* assert: scl is low */
+ for (i = 7; i >= 0; i--) {
+ if (c & ( 1 << i )) {
+ sdahi();
+ } else {
+ sdalo();
+ }
+ if (sclhi() < 0) { /* timed out */
+ sdahi(); /* we don't want to block the net */
+ return -ETIMEDOUT;
+ };
+ scllo();
+ }
+ sdahi();
+ if (sclhi() < 0) {
+ return -ETIMEDOUT;
+ };
+ /* read ack: SDA should be pulled down by slave */
+ ack = getsda() == 0; /* ack: sda is pulled low ->success. */
+ scllo();
+
+ if (rtc_debug)
+ printk(KERN_DEBUG "i2c_outb(0x%02x) -> %s\n",
+ c, ack ? "ACK": "NAK");
+
+ return ack; /* return 1 if device acked */
+ /* assert: scl is low (sda undef) */
+}
+
+static int i2c_inb(int ack)
+{
+ int i;
+ unsigned int indata = 0;
+
+ /* assert: scl is low */
+
+ sdahi();
+ for (i = 0; i < 8; i++) {
+ if (sclhi() < 0) {
+ return -ETIMEDOUT;
+ };
+ indata *= 2;
+ if (getsda())
+ indata |= 0x01;
+ scllo();
+ }
+ if (ack) {
+ sdalo();
+ } else {
+ sdahi();
+ }
+
+ if (sclhi() < 0) {
+ sdahi();
+ return -ETIMEDOUT;
+ }
+ scllo();
+ sdahi();
+
+ if (rtc_debug)
+ printk(KERN_DEBUG "i2c_inb() -> 0x%02x\n", indata);
+
+ /* assert: scl is low */
+ return indata & 0xff;
+}
+
+static void i2c_init(void)
+{
+ /* no gpio_control for EXTIF */
+ // ssb_gpio_control(&ssb, sda_mask | scl_mask, 0);
+
+ gpio_set_value(sda_index, 0);
+ gpio_set_value(scl_index, 0);
+ sdahi();
+ sclhi();
+}
+
+static int rtc_open(UNUSED struct inode *inode, UNUSED struct file *filp)
+{
+ spin_lock_irq(&rtc_lock);
+
+ if (rtc_status & RTC_IS_OPEN) {
+ spin_unlock_irq(&rtc_lock);
+ return -EBUSY;
+ }
+
+ rtc_status |= RTC_IS_OPEN;
+
+ /*
+ * The following call is only necessary if we use both this driver and
+ * the proprietary one from asus at the same time (which, b.t.w. only
+ * makes sense during development). Otherwise, each access via the asus
+ * driver will make access via this driver impossible.
+ */
+ i2c_init();
+
+ spin_unlock_irq(&rtc_lock);
+
+ return 0;
+}
+
+static int rtc_release(UNUSED struct inode *inode, UNUSED struct file *filp)
+{
+ /* No need for locking here. */
+ rtc_status &= ~RTC_IS_OPEN;
+ return 0;
+}
+
+static int from_bcd(int bcdnum)
+{
+ int fac, num = 0;
+
+ for (fac = 1; bcdnum; fac *= 10) {
+ num += (bcdnum % 16) * fac;
+ bcdnum /= 16;
+ }
+
+ return num;
+}
+
+static int to_bcd(int decnum)
+{
+ int fac, num = 0;
+
+ for (fac = 1; decnum; fac *= 16) {
+ num += (decnum % 10) * fac;
+ decnum /= 10;
+ }
+
+ return num;
+}
+
+static void get_rtc_time(struct rtc_time *rtc_tm)
+{
+ int cr2;
+
+ /*
+ * Read date and time from the RTC. We use read method (3).
+ */
+
+ spin_lock_irq(&rtc_lock);
+ i2c_start();
+ i2c_outb(RTC_I2C_ADDRESS | I2C_READ_MASK);
+ cr2 = i2c_inb(I2C_ACK);
+ rtc_tm->tm_sec = i2c_inb(I2C_ACK);
+ rtc_tm->tm_min = i2c_inb(I2C_ACK);
+ rtc_tm->tm_hour = i2c_inb(I2C_ACK);
+ rtc_tm->tm_wday = i2c_inb(I2C_ACK);
+ rtc_tm->tm_mday = i2c_inb(I2C_ACK);
+ rtc_tm->tm_mon = i2c_inb(I2C_ACK);
+ rtc_tm->tm_year = i2c_inb(I2C_NAK);
+ i2c_stop();
+ spin_unlock_irq(&rtc_lock);
+
+ if (cr2 & RTC_VDET_MASK) {
+ printk(KERN_WARNING "***RTC BATTERY FAILURE***\n");
+ }
+
+ /* Handle century bit */
+ if (rtc_tm->tm_mon & RTC_Y2K_MASK) {
+ rtc_tm->tm_mon &= ~RTC_Y2K_MASK;
+ rtc_tm->tm_year += 0x100;
+ }
+
+ rtc_tm->tm_sec = from_bcd(rtc_tm->tm_sec);
+ rtc_tm->tm_min = from_bcd(rtc_tm->tm_min);
+ rtc_tm->tm_hour = from_bcd(rtc_tm->tm_hour);
+ rtc_tm->tm_mday = from_bcd(rtc_tm->tm_mday);
+ rtc_tm->tm_mon = from_bcd(rtc_tm->tm_mon) - 1;
+ rtc_tm->tm_year = from_bcd(rtc_tm->tm_year);
+
+ rtc_tm->tm_isdst = -1; /* DST not known */
+}
+
+static void set_rtc_time(struct rtc_time *rtc_tm)
+{
+ rtc_tm->tm_sec = to_bcd(rtc_tm->tm_sec);
+ rtc_tm->tm_min = to_bcd(rtc_tm->tm_min);
+ rtc_tm->tm_hour = to_bcd(rtc_tm->tm_hour);
+ rtc_tm->tm_mday = to_bcd(rtc_tm->tm_mday);
+ rtc_tm->tm_mon = to_bcd(rtc_tm->tm_mon + 1);
+ rtc_tm->tm_year = to_bcd(rtc_tm->tm_year);
+
+ if (rtc_tm->tm_year >= 0x100) {
+ rtc_tm->tm_year -= 0x100;
+ rtc_tm->tm_mon |= RTC_Y2K_MASK;
+ }
+
+ spin_lock_irq(&rtc_lock);
+ i2c_start();
+ i2c_outb(RTC_I2C_ADDRESS | I2C_WRITE_MASK);
+ i2c_outb(0x00); /* set starting register to 0 (=seconds) */
+ i2c_outb(rtc_tm->tm_sec);
+ i2c_outb(rtc_tm->tm_min);
+ i2c_outb(rtc_tm->tm_hour);
+ i2c_outb(rtc_tm->tm_wday);
+ i2c_outb(rtc_tm->tm_mday);
+ i2c_outb(rtc_tm->tm_mon);
+ i2c_outb(rtc_tm->tm_year);
+ i2c_stop();
+ spin_unlock_irq(&rtc_lock);
+}
+
+static ssize_t rtc_write(UNUSED struct file *filp, const char *buf,
+ size_t count, loff_t *ppos)
+{
+ struct rtc_time rtc_tm;
+ char buffer[23];
+ char *p;
+
+ if (!capable(CAP_SYS_TIME))
+ return -EACCES;
+
+ if (ppos != &filp->f_pos)
+ return -ESPIPE;
+
+ /*
+ * For simplicity, the only acceptable format is:
+ * YYYY:MM:DD:W:HH:MM:SS\n
+ */
+
+ if (count != 22)
+ goto err_out;
+
+ if (copy_from_user(buffer, buf, count))
+ return -EFAULT;
+
+ buffer[sizeof(buffer)-1] = '\0';
+
+ p = &buffer[0];
+
+ rtc_tm.tm_year = simple_strtoul(p, &p, 10);
+ if (*p++ != ':') goto err_out;
+
+ rtc_tm.tm_mon = simple_strtoul(p, &p, 10) - 1;
+ if (*p++ != ':') goto err_out;
+
+ rtc_tm.tm_mday = simple_strtoul(p, &p, 10);
+ if (*p++ != ':') goto err_out;
+
+ rtc_tm.tm_wday = simple_strtoul(p, &p, 10);
+ if (*p++ != ':') goto err_out;
+
+ rtc_tm.tm_hour = simple_strtoul(p, &p, 10);
+ if (*p++ != ':') goto err_out;
+
+ rtc_tm.tm_min = simple_strtoul(p, &p, 10);
+ if (*p++ != ':') goto err_out;
+
+ rtc_tm.tm_sec = simple_strtoul(p, &p, 10);
+ if (*p != '\n') goto err_out;
+
+ rtc_tm.tm_year -= RTC_EPOCH;
+
+ set_rtc_time(&rtc_tm);
+
+ *ppos += count;
+
+ return count;
+
+ err_out:
+ printk(KERN_ERR "invalid format: use YYYY:MM:DD:W:HH:MM:SS\\n\n");
+ return -EINVAL;
+}
+
+
+static ssize_t rtc_read(UNUSED struct file *filp, char *buf, size_t count,
+ loff_t *ppos)
+{
+ char wbuf[23];
+ struct rtc_time tm;
+ ssize_t len;
+
+ if (count == 0 || *ppos != 0)
+ return 0;
+
+ get_rtc_time(&tm);
+
+ len = sprintf(wbuf, "%04d:%02d:%02d:%d:%02d:%02d:%02d\n",
+ tm.tm_year + RTC_EPOCH,
+ tm.tm_mon + 1,
+ tm.tm_mday,
+ tm.tm_wday,
+ tm.tm_hour,
+ tm.tm_min,
+ tm.tm_sec);
+
+ if (len > (ssize_t)count)
+ len = count;
+
+ if (copy_to_user(buf, wbuf, len))
+ return -EFAULT;
+
+ *ppos += len;
+
+ return len;
+}
+
+static int rtc_do_ioctl(unsigned int cmd, unsigned long arg)
+{
+ struct rtc_time rtc_tm;
+
+ switch (cmd) {
+ case RTC_RD_TIME:
+ memset(&rtc_tm, 0, sizeof(struct rtc_time));
+ get_rtc_time(&rtc_tm);
+ if (copy_to_user((void *)arg, &rtc_tm, sizeof(rtc_tm)))
+ return -EFAULT;
+ break;
+
+ case RTC_SET_TIME:
+ if (!capable(CAP_SYS_TIME))
+ return -EACCES;
+
+ if (copy_from_user(&rtc_tm, (struct rtc_time *)arg,
+ sizeof(struct rtc_time)))
+ return -EFAULT;
+
+ set_rtc_time(&rtc_tm);
+ break;
+
+ default:
+ return -ENOTTY;
+ }
+
+ return 0;
+}
+
+static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ long ret;
+ ret = rtc_do_ioctl(cmd, arg);
+ return ret;
+}
+
+static const struct file_operations rtc_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .read = rtc_read,
+ .write = rtc_write,
+ .unlocked_ioctl = rtc_ioctl,
+ .open = rtc_open,
+ .release = rtc_release,
+};
+
+static struct miscdevice rtc_dev = {
+ .minor = RTC_MINOR,
+ .name = "rtc",
+ .fops = &rtc_fops,
+};
+
+/* Savagely ripped from diag.c. */
+static inline int startswith (char *source, char *cmp)
+{
+ return !strncmp(source, cmp, strlen(cmp));
+}
+
+static void platform_detect(void)
+{
+ char buf[20];
+ int et0phyaddr, et1phyaddr;
+
+ /* Based on "model_no". */
+ if (nvram_getenv("model_no", buf, sizeof(buf)) >= 0) {
+ if (startswith(buf, "WL700")) { /* WL700* */
+ sda_index = 2;
+ scl_index = 5;
+ return;
+ }
+ }
+
+ if (nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 )
+ et0phyaddr = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 )
+ et1phyaddr = simple_strtoul(buf, NULL, 0);
+
+ if (nvram_getenv("hardware_version", buf, sizeof(buf)) >= 0) {
+ /* Either WL-300g or WL-HDD, do more extensive checks */
+ if (startswith(buf, "WL300-") && et0phyaddr == 0 && et1phyaddr == 1) {
+ sda_index = 4;
+ scl_index = 5;
+ return;
+ }
+ }
+ /* not found */
+}
+
+static int __init rtc_init(void)
+{
+ int cr1;
+
+ platform_detect();
+
+ if (sda_index == scl_index) {
+ printk(KERN_ERR "RTC-RV5C386A: unrecognized platform!\n");
+ return -ENODEV;
+ }
+
+ i2c_init();
+
+ /*
+ * Switch RTC to 24h mode
+ */
+ spin_lock_irq(&rtc_lock);
+ i2c_start();
+ i2c_outb(RTC_I2C_ADDRESS | I2C_WRITE_MASK);
+ i2c_outb(0xE4); /* start at address 0xE, transmission mode 4 */
+ cr1 = i2c_inb(I2C_NAK);
+ i2c_stop();
+ spin_unlock_irq(&rtc_lock);
+ if ((cr1 & RTC_24HOUR_MODE_MASK) == 0) {
+ /* RTC is running in 12h mode */
+ printk(KERN_INFO "rtc.o: switching to 24h mode\n");
+ spin_lock_irq(&rtc_lock);
+ i2c_start();
+ i2c_outb(RTC_I2C_ADDRESS | I2C_WRITE_MASK);
+ i2c_outb(0xE0);
+ i2c_outb(cr1 | RTC_24HOUR_MODE_MASK);
+ i2c_stop();
+ spin_unlock_irq(&rtc_lock);
+ }
+
+ misc_register(&rtc_dev);
+
+ printk(KERN_INFO "RV5C386A Real Time Clock Driver loaded\n");
+
+ return 0;
+}
+
+static void __exit rtc_exit (void)
+{
+ misc_deregister(&rtc_dev);
+ printk(KERN_INFO "Successfully removed RTC RV5C386A driver\n");
+}
+
+module_init(rtc_init);
+module_exit(rtc_exit);
+
+/*
+ * Local Variables:
+ * indent-tabs-mode:t
+ * c-basic-offset:8
+ * End:
+ */
diff --git a/package/sierra-directip/Makefile b/package/sierra-directip/Makefile
new file mode 100644
index 000000000..fc0e4ea52
--- /dev/null
+++ b/package/sierra-directip/Makefile
@@ -0,0 +1,41 @@
+#
+# Copyright (C) 2006-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=sierra-directip
+PKG_RELEASE:=10
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/usb-sierrawireless-directip
+ SUBMENU:=USB Support
+ DEPENDS:=+kmod-usb-serial +kmod-usb-net
+ TITLE:=Updated Sierra Wireless drivers for DirectIP
+ FILES:= \
+ $(PKG_BUILD_DIR)/sierra.ko \
+ $(PKG_BUILD_DIR)/sierra_net.ko
+ AUTOLOAD:=$(call AutoLoad,60,sierra sierra_net)
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+ $(Build/Patch)
+endef
+
+define Build/Compile
+ $(MAKE) -C "$(LINUX_DIR)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ ARCH="$(LINUX_KARCH)" \
+ SUBDIRS="$(PKG_BUILD_DIR)" \
+ EXTRA_CFLAGS="$(BUILDFLAGS)" \
+ modules
+endef
+
+$(eval $(call KernelPackage,usb-sierrawireless-directip))
diff --git a/package/sierra-directip/patches/100-sierra_net_endian.patch b/package/sierra-directip/patches/100-sierra_net_endian.patch
new file mode 100644
index 000000000..196d77d49
--- /dev/null
+++ b/package/sierra-directip/patches/100-sierra_net_endian.patch
@@ -0,0 +1,22 @@
+--- a/sierra_net.c
++++ b/sierra_net.c
+@@ -840,8 +840,8 @@ static int sierra_net_bind(struct usbnet
+ init_timer(&priv->sync_timer);
+ /* verify fw attributes */
+ status = sierra_net_get_fw_attr(dev, &fwattr);
+- dev_dbg(&dev->udev->dev, "Fw attr: %x\n", fwattr);
+- if (status == sizeof(fwattr) && (fwattr & SWI_GET_FW_ATTR_APM)) {
++ dev_dbg(&dev->udev->dev, "Fw attr: %x\n", cpu_to_le16(fwattr));
++ if (status == sizeof(fwattr) && (cpu_to_le16(fwattr) & SWI_GET_FW_ATTR_APM)) {
+ /*******************************************************************************
+ * If you want the default /sys/bus/usb/devices/.../.../power/level to be forced
+ * to auto, the following needs to be compiled in.
+@@ -856,7 +856,7 @@ static int sierra_net_bind(struct usbnet
+ usb_disable_autosuspend(dev->udev);
+ }
+ /* test whether firmware supports DHCP */
+- if (!(status == sizeof(fwattr) && (fwattr & SWI_GET_FW_ATTR_MASK))) {
++ if (!(status == sizeof(fwattr) && (cpu_to_le16(fwattr) & SWI_GET_FW_ATTR_MASK))) {
+ /* found incompatible firmware version */
+ dev_err(&dev->udev->dev, "Incompatible driver and firmware"
+ " versions\n");
diff --git a/package/sierra-directip/patches/110-drop_dhcp_requirement.patch b/package/sierra-directip/patches/110-drop_dhcp_requirement.patch
new file mode 100644
index 000000000..4c4d0ba65
--- /dev/null
+++ b/package/sierra-directip/patches/110-drop_dhcp_requirement.patch
@@ -0,0 +1,14 @@
+--- a/sierra_net.c
++++ b/sierra_net.c
+@@ -858,10 +858,7 @@ static int sierra_net_bind(struct usbnet
+ /* test whether firmware supports DHCP */
+ if (!(status == sizeof(fwattr) && (cpu_to_le16(fwattr) & SWI_GET_FW_ATTR_MASK))) {
+ /* found incompatible firmware version */
+- dev_err(&dev->udev->dev, "Incompatible driver and firmware"
+- " versions\n");
+- kfree(priv);
+- return -ENODEV;
++ dev_err(&dev->udev->dev, "Warning: Firmware does not have DHCP support\n");
+ }
+ /* prepare sync message from template */
+ memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg));
diff --git a/package/sierra-directip/src/Makefile b/package/sierra-directip/src/Makefile
new file mode 100644
index 000000000..7ceb03b58
--- /dev/null
+++ b/package/sierra-directip/src/Makefile
@@ -0,0 +1 @@
+obj-m := sierra.o sierra_net.o
diff --git a/package/sierra-directip/src/sierra.c b/package/sierra-directip/src/sierra.c
new file mode 100644
index 000000000..9752d1142
--- /dev/null
+++ b/package/sierra-directip/src/sierra.c
@@ -0,0 +1,1409 @@
+/*
+ USB Driver for Sierra Wireless
+
+ Copyright (C) 2006, 2007, 2008 Kevin Lloyd <klloyd@sierrawireless.com>,
+
+ Copyright (C) 2008 - 2011 Elina Pasheva, Matthew Safar, Rory Filer
+ <linux@sierrawireless.com>
+
+ IMPORTANT DISCLAIMER: This driver is not commercially supported by
+ Sierra Wireless. Use at your own risk.
+
+ This driver is free software; you can redistribute it and/or modify
+ it under the terms of Version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ Portions based on the option driver by Matthias Urlichs <smurf@smurf.noris.de>
+ Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
+*/
+/* Uncomment to log function calls */
+/*#define DEBUG*/
+/* Uncomment to force power level set to auto when attaching a device */
+/*#define POWER_LEVEL_AUTO*/
+
+/* Sierra driver - kernel 3.0 */
+#define DRIVER_VERSION "v.1.7.40"
+#define DRIVER_AUTHOR "Kevin Lloyd, Elina Pasheva, Matthew Safar, Rory Filer"
+#define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
+
+#include <linux/kernel.h>
+#include <linux/jiffies.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include <asm/unaligned.h>
+
+#define SWIMS_USB_REQUEST_SetPower 0x00
+#define SWIMS_USB_REQUEST_GetFwAttr 0x06
+#define SWIMS_USB_REQUEST_SetNmea 0x07
+#define USB_REQUEST_TYPE_CLASS 0xA1
+#define USB_REQUEST_IFACE 0x20
+
+#define N_IN_URB_HM 8
+#define N_OUT_URB_HM 64
+#define N_IN_URB 4
+#define N_OUT_URB 4
+#define IN_BUFLEN 4096
+
+#define MAX_TRANSFER (PAGE_SIZE - 512)
+/* MAX_TRANSFER is chosen so that the VM is not stressed by
+ allocations > PAGE_SIZE and the number of packets in a page
+ is an integer 512 is the largest possible packet on EHCI */
+
+#define SWI_FW_ATTR_PM_MASK 0x02
+/* PORTION_LEN defines the length of device attribute buffer */
+#define PORTION_LEN 4096
+
+static int debug;
+static int nmea;
+
+/* sysfs attributes */
+static int sierra_create_sysfs_attrs(struct usb_serial_port *port);
+static int sierra_remove_sysfs_attrs(struct usb_serial_port *port);
+
+/* Used in interface blacklisting */
+struct sierra_iface_info {
+ const u32 infolen; /* number of interface numbers on blacklist */
+ const u8 *ifaceinfo; /* pointer to the array holding the numbers */
+};
+
+/* per interface statistics */
+struct sierra_intf_stats {
+ atomic_t rx_bytes; /* received bytes */
+ atomic_t indat_cb_cnt; /* indat callback count */
+ atomic_t indat_cb_fail; /* indat cb with error */
+
+ atomic_t tx_bytes; /* transmitted bytes */
+ atomic_t write_cnt; /* no. of writes */
+ atomic_t write_err; /* no. of failed writes */
+
+ atomic_t delayed_writes; /* no. of delayed writes */
+ atomic_t delayed_write_err; /* no. of delayed write errs */
+
+ atomic_t outdat_cb_cnt; /* outdat callback count */
+ atomic_t outdat_cb_fail; /* outdat cb with error */
+
+};
+
+struct sierra_intf_private {
+ spinlock_t susp_lock;
+ unsigned int suspended:1;
+ int in_flight;
+
+ struct sierra_intf_stats stats;
+};
+
+static int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
+{
+ int result;
+ dev_dbg(&udev->dev, "%s\n", __func__);
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ SWIMS_USB_REQUEST_SetPower, /* __u8 request */
+ USB_TYPE_VENDOR, /* __u8 request type */
+ swiState, /* __u16 value */
+ 0, /* __u16 index */
+ NULL, /* void *data */
+ 0, /* __u16 size */
+ USB_CTRL_SET_TIMEOUT); /* int timeout */
+ return result;
+}
+
+static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable)
+{
+ int result;
+ dev_dbg(&udev->dev, "%s\n", __func__);
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ SWIMS_USB_REQUEST_SetNmea, /* __u8 request */
+ USB_TYPE_VENDOR, /* __u8 request type */
+ enable, /* __u16 value */
+ 0x0000, /* __u16 index */
+ NULL, /* void *data */
+ 0, /* __u16 size */
+ USB_CTRL_SET_TIMEOUT); /* int timeout */
+ return result;
+}
+
+static int sierra_get_fw_attr(struct usb_device *udev, u16 *data)
+{
+ int result;
+ u16 *attrdata;
+
+ dev_dbg(&udev->dev, "%s\n", __func__);
+
+ attrdata = kmalloc(sizeof(*attrdata), GFP_KERNEL);
+ if (!attrdata)
+ return -ENOMEM;
+
+ result = usb_control_msg(udev,
+ usb_rcvctrlpipe(udev, 0),
+ SWIMS_USB_REQUEST_GetFwAttr, /* __u8 request*/
+ USB_TYPE_VENDOR | USB_DIR_IN, /* request type*/
+ 0x0000, /* __u16 value */
+ 0x0000, /* __u16 index */
+ attrdata, /* void *data */
+ sizeof(*attrdata), /* _u16 size */
+ USB_CTRL_SET_TIMEOUT); /* in timeout */
+
+ if (result < 0) {
+ kfree(attrdata);
+ return -EIO;
+ }
+
+ *data = *attrdata;
+
+ kfree(attrdata);
+ return result;
+}
+
+static int sierra_calc_num_ports(struct usb_serial *serial)
+{
+ int num_ports = 0;
+ u8 ifnum, numendpoints;
+
+ dev_dbg(&serial->dev->dev, "%s\n", __func__);
+
+ ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+ numendpoints = serial->interface->cur_altsetting->desc.bNumEndpoints;
+
+ /* Dummy interface present on some SKUs should be ignored */
+ if (ifnum == 0x99)
+ num_ports = 0;
+ else if (numendpoints <= 3)
+ num_ports = 1;
+ else
+ num_ports = (numendpoints-1)/2;
+ return num_ports;
+}
+
+static int is_blacklisted(const u8 ifnum,
+ const struct sierra_iface_info *blacklist)
+{
+ const u8 *info;
+ int i;
+
+ if (blacklist) {
+ info = blacklist->ifaceinfo;
+
+ for (i = 0; i < blacklist->infolen; i++) {
+ if (info[i] == ifnum)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int is_himemory(const u8 ifnum,
+ const struct sierra_iface_info *himemorylist)
+{
+ const u8 *info;
+ int i;
+
+ if (himemorylist) {
+ info = himemorylist->ifaceinfo;
+
+ for (i=0; i < himemorylist->infolen; i++) {
+ if (info[i] == ifnum)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int sierra_calc_interface(struct usb_serial *serial)
+{
+ int interface;
+ struct usb_interface *p_interface;
+ struct usb_host_interface *p_host_interface;
+
+ /* Get the interface structure pointer from the serial struct */
+ p_interface = serial->interface;
+
+ /* Get a pointer to the host interface structure */
+ p_host_interface = p_interface->cur_altsetting;
+
+ /* read the interface descriptor for this active altsetting
+ * to find out the interface number we are on */
+ interface = p_host_interface->desc.bInterfaceNumber;
+
+ return interface;
+}
+
+static int sierra_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
+{
+ int result = 0;
+ struct usb_device *udev;
+ struct sierra_intf_private *intfdata;
+ u8 ifnum;
+
+ udev = serial->dev;
+ dev_dbg(&udev->dev, "%s\n", __func__);
+
+ ifnum = sierra_calc_interface(serial);
+ /*
+ * If this interface supports more than 1 alternate
+ * select the 2nd one
+ */
+ if (serial->interface->num_altsetting == 2) {
+ dev_dbg(&udev->dev, "Selecting alt setting for interface %d\n",
+ ifnum);
+ /* We know the alternate setting is for composite USB interface
+ * modems
+ */
+ usb_set_interface(udev, ifnum, 1);
+ }
+
+ /* ifnum could have changed - by calling usb_set_interface */
+ ifnum = sierra_calc_interface(serial);
+
+ if (is_blacklisted(ifnum,
+ (struct sierra_iface_info *)id->driver_info)) {
+ dev_dbg(&serial->dev->dev,
+ "Ignoring blacklisted interface #%d\n", ifnum);
+ return -ENODEV;
+ }
+
+ intfdata = serial->private = kzalloc(sizeof(struct sierra_intf_private),
+ GFP_KERNEL);
+ if (!intfdata)
+ return -ENOMEM;
+ spin_lock_init(&intfdata->susp_lock);
+
+ return result;
+}
+
+/* interfaces with higher memory requirements */
+static const u8 hi_memory_typeA_ifaces[] = { 0, 2 };
+static const struct sierra_iface_info typeA_interface_list = {
+ .infolen = ARRAY_SIZE(hi_memory_typeA_ifaces),
+ .ifaceinfo = hi_memory_typeA_ifaces,
+};
+
+static const u8 hi_memory_typeB_ifaces[] = { 3, 4, 5, 6 };
+static const struct sierra_iface_info typeB_interface_list = {
+ .infolen = ARRAY_SIZE(hi_memory_typeB_ifaces),
+ .ifaceinfo = hi_memory_typeB_ifaces,
+};
+
+/* 'blacklist' of interfaces not served by this driver */
+static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11 };
+static const struct sierra_iface_info direct_ip_interface_blacklist = {
+ .infolen = ARRAY_SIZE( direct_ip_non_serial_ifaces ),
+ .ifaceinfo = direct_ip_non_serial_ifaces,
+};
+
+static const struct usb_device_id id_table [] = {
+ { USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */
+ { USB_DEVICE(0x03F0, 0x1B1D) }, /* HP ev2200 a.k.a MC5720 */
+ { USB_DEVICE(0x03F0, 0x1E1D) }, /* HP hs2300 a.k.a MC8775 */
+ { USB_DEVICE(0x03F0, 0x211D) }, /* HP ev2210 a.k.a MC5725 */
+
+ { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
+ { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
+ { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
+ { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */
+ { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */
+ { USB_DEVICE(0x1199, 0x0022) }, /* Sierra Wireless EM5725 */
+ { USB_DEVICE(0x1199, 0x0024) }, /* Sierra Wireless MC5727 */
+ { USB_DEVICE(0x1199, 0x0224) }, /* Sierra Wireless MC5727 */
+ { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
+ { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */
+ { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
+ { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */
+ { USB_DEVICE(0x1199, 0x0301) }, /* Sierra Wireless USB Dongle 250U/3G */
+ /* Sierra Wireless MC5728 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0400, 0xFF, 0xFF, 0xFF) },
+
+ /* Sierra Wireless C597 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) },
+ /* Sierra Wireless T598 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0025, 0xFF, 0xFF, 0xFF) },
+ { USB_DEVICE(0x1199, 0x0026) }, /* Sierra Wireless T11 */
+ { USB_DEVICE(0x1199, 0x0027) }, /* Sierra Wireless AC402 */
+ { USB_DEVICE(0x1199, 0x0028) }, /* Sierra Wireless MC5728 */
+ { USB_DEVICE(0x114F, 0x6000) }, /* Sierra Wireless Q26 Elite */
+
+ { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
+ { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */
+ { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */
+ { USB_DEVICE(0x1199, 0x6805) }, /* Sierra Wireless MC8765 */
+ { USB_DEVICE(0x1199, 0x6808) }, /* Sierra Wireless MC8755 */
+ { USB_DEVICE(0x1199, 0x6809) }, /* Sierra Wireless MC8765 */
+ { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */
+ { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 */
+ { USB_DEVICE(0x1199, 0x6815) }, /* Sierra Wireless MC8775 */
+ { USB_DEVICE(0x1199, 0x6816) }, /* Sierra Wireless MC8775 */
+ { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */
+ { USB_DEVICE(0x1199, 0x6821) }, /* Sierra Wireless AirCard 875U */
+ { USB_DEVICE(0x1199, 0x6822) }, /* Sierra Wireless AirCard 875E */
+ { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780 */
+ { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781 */
+ { USB_DEVICE(0x1199, 0x6834) }, /* Sierra Wireless MC8780 */
+ { USB_DEVICE(0x1199, 0x6835) }, /* Sierra Wireless MC8781 */
+ { USB_DEVICE(0x1199, 0x6838) }, /* Sierra Wireless MC8780 */
+ { USB_DEVICE(0x1199, 0x6839) }, /* Sierra Wireless MC8781 */
+ { USB_DEVICE(0x1199, 0x683A) }, /* Sierra Wireless MC8785 */
+ { USB_DEVICE(0x1199, 0x683B) }, /* Sierra Wireless MC8785 Composite */
+ /* Sierra Wireless MC8790, MC8791, MC8792 Composite */
+ { USB_DEVICE(0x1199, 0x683C) },
+ { USB_DEVICE(0x1199, 0x683D) }, /* Sierra Wireless MC8791 Composite */
+ /* Sierra Wireless MC8790, MC8791, MC8792 */
+ { USB_DEVICE(0x1199, 0x683E) },
+ { USB_DEVICE(0x1199, 0x6850) }, /* Sierra Wireless AirCard 880 */
+ { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */
+ { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880 E */
+ { USB_DEVICE(0x1199, 0x6853) }, /* Sierra Wireless AirCard 881 E */
+ { USB_DEVICE(0x1199, 0x6855) }, /* Sierra Wireless AirCard 880 U */
+ { USB_DEVICE(0x1199, 0x6856) }, /* Sierra Wireless AirCard 881 U */
+ { USB_DEVICE(0x1199, 0x6859) }, /* Sierra Wireless AirCard 885 E */
+ { USB_DEVICE(0x1199, 0x685A) }, /* Sierra Wireless AirCard 885 E */
+ /* Sierra Wireless C885 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6880, 0xFF, 0xFF, 0xFF)},
+ /* Sierra Wireless C888, Air Card 501, USB 303, USB 304 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6890, 0xFF, 0xFF, 0xFF)},
+ /* Sierra Wireless C22/C33 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6891, 0xFF, 0xFF, 0xFF)},
+ /* Sierra Wireless HSPA Non-Composite Device */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)},
+ { USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */
+ /* Sierra Wireless Direct IP modems */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68A3, 0xFF, 0xFF, 0xFF),
+ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
+ },
+ /* AT&T Direct IP modems */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68A3, 0xFF, 0xFF, 0xFF),
+ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
+ },
+ /* Sierra Wireless Direct IP LTE modems */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68AA, 0xFF, 0xFF, 0xFF),
+ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
+ },
+ /* AT&T Direct IP LTE modems */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68AA, 0xFF, 0xFF, 0xFF),
+ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
+ },
+ /* Wireless 5720 VZW Mobile Broadband (EVDO Rev-A) Minicard GPS Port */
+ { USB_DEVICE(0x413C, 0x8133) },
+
+ { }
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+/* per port private data */
+struct sierra_port_private {
+ spinlock_t lock; /* lock the structure */
+ int outstanding_urbs; /* number of out urbs in flight */
+
+ struct usb_anchor active;
+ struct usb_anchor delayed;
+
+ int num_out_urbs;
+ int num_in_urbs;
+ /* Input endpoints and buffers for this port */
+ struct urb *in_urbs[N_IN_URB_HM];
+
+ /* Settings for the port */
+ int rts_state; /* Handshaking pins (outputs) */
+ int dtr_state;
+ int cts_state; /* Handshaking pins (inputs) */
+ int dsr_state;
+ int dcd_state;
+ int ri_state;
+ unsigned int opened:1;
+};
+
+static int sierra_send_setup(struct usb_serial_port *port)
+{
+ struct usb_serial *serial = port->serial;
+ struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+ __u16 interface = 0;
+ int val = 0;
+ int do_send = 0;
+ int retval;
+
+ dev_dbg(&port->dev, "%s\n", __func__);
+
+ if (portdata->dtr_state)
+ val |= 0x01;
+ if (portdata->rts_state)
+ val |= 0x02;
+
+ /* If composite device then properly report interface */
+ if (serial->num_ports == 1) {
+ interface = sierra_calc_interface(serial);
+ /* Control message is sent only to interfaces with
+ * interrupt_in endpoints
+ */
+ if (port->interrupt_in_urb) {
+ /* send control message */
+ do_send = 1;
+ }
+ }
+
+ /* Otherwise the need to do non-composite mapping */
+ else {
+ if (port->bulk_out_endpointAddress == 2)
+ interface = 0;
+ else if (port->bulk_out_endpointAddress == 4)
+ interface = 1;
+ else if (port->bulk_out_endpointAddress == 5)
+ interface = 2;
+
+ do_send = 1;
+ }
+ if (!do_send)
+ return 0;
+
+ usb_autopm_get_interface(serial->interface);
+ retval = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ 0x22, 0x21, val, interface, NULL, 0, USB_CTRL_SET_TIMEOUT);
+ usb_autopm_put_interface(serial->interface);
+
+ return retval;
+}
+
+static void sierra_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
+{
+ dev_dbg(&port->dev, "%s\n", __func__);
+ tty_termios_copy_hw(tty->termios, old_termios);
+ sierra_send_setup(port);
+}
+
+static int sierra_tiocmget(struct tty_struct *tty)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ unsigned int value;
+ struct sierra_port_private *portdata;
+
+ dev_dbg(&port->dev, "%s\n", __func__);
+ portdata = usb_get_serial_port_data(port);
+
+ value = ((portdata->rts_state) ? TIOCM_RTS : 0) |
+ ((portdata->dtr_state) ? TIOCM_DTR : 0) |
+ ((portdata->cts_state) ? TIOCM_CTS : 0) |
+ ((portdata->dsr_state) ? TIOCM_DSR : 0) |
+ ((portdata->dcd_state) ? TIOCM_CAR : 0) |
+ ((portdata->ri_state) ? TIOCM_RNG : 0);
+
+ return value;
+}
+
+static int sierra_tiocmset(struct tty_struct *tty,
+ unsigned int set, unsigned int clear)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct sierra_port_private *portdata;
+
+ portdata = usb_get_serial_port_data(port);
+
+ if (set & TIOCM_RTS)
+ portdata->rts_state = 1;
+ if (set & TIOCM_DTR)
+ portdata->dtr_state = 1;
+
+ if (clear & TIOCM_RTS)
+ portdata->rts_state = 0;
+ if (clear & TIOCM_DTR)
+ portdata->dtr_state = 0;
+ return sierra_send_setup(port);
+}
+
+static void sierra_release_urb(struct urb *urb)
+{
+ struct usb_serial_port *port;
+ if (urb) {
+ port = urb->context;
+ dev_dbg(&port->dev, "%s: %p\n", __func__, urb);
+ usb_free_urb(urb);
+ }
+}
+
+/* Sysfs Attributes */
+
+static ssize_t show_suspend_status(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct usb_serial_port *port;
+ struct sierra_port_private *portdata;
+ struct sierra_intf_private *intfdata;
+ unsigned long flags;
+ unsigned int flag_suspended = 0;
+
+ port = to_usb_serial_port(dev);
+ portdata = usb_get_serial_port_data(port);
+ intfdata = port->serial->private;
+
+ spin_lock_irqsave(&intfdata->susp_lock, flags);
+ flag_suspended = intfdata->suspended;
+ spin_unlock_irqrestore(&intfdata->susp_lock, flags);
+
+ return snprintf(buf, PORTION_LEN, "%i\n", flag_suspended);
+}
+
+static ssize_t show_stats(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct usb_serial_port *port;
+ struct sierra_intf_private *intfdata;
+
+ port = to_usb_serial_port(dev);
+ intfdata = port->serial->private;
+
+ return snprintf(buf, PORTION_LEN,
+ "rx: %i B\tindat: %i\tindat err: %i\n"
+ "tx: %i B\toutdat: %i\toutdat err: %i\n"
+ "writes: %i\t\twrite err: %i\n"
+ "delayed writes: %i\tdelayed write err: %i\n",
+ atomic_read(&intfdata->stats.rx_bytes), atomic_read(&intfdata->stats.indat_cb_cnt), atomic_read(&intfdata->stats.indat_cb_fail),
+ atomic_read(&intfdata->stats.tx_bytes), atomic_read(&intfdata->stats.outdat_cb_cnt), atomic_read(&intfdata->stats.outdat_cb_fail),
+ atomic_read(&intfdata->stats.write_cnt), atomic_read(&intfdata->stats.write_err),
+ atomic_read(&intfdata->stats.delayed_writes), atomic_read(&intfdata->stats.delayed_write_err)
+ );
+}
+
+/* Read only suspend status */
+static DEVICE_ATTR(suspend_status, S_IWUSR | S_IRUGO, show_suspend_status,
+ NULL);
+
+/* Read only statistics */
+static DEVICE_ATTR(stats, S_IWUSR | S_IRUGO, show_stats, NULL);
+
+static int sierra_create_sysfs_attrs(struct usb_serial_port *port)
+{
+ int result = 0;
+
+ result = device_create_file(&port->dev, &dev_attr_stats);
+ if (unlikely (result < 0))
+ return result;
+ return device_create_file(&port->dev, &dev_attr_suspend_status);
+}
+
+static int sierra_remove_sysfs_attrs(struct usb_serial_port *port)
+{
+ device_remove_file(&port->dev, &dev_attr_stats);
+ device_remove_file(&port->dev, &dev_attr_suspend_status);
+ return 0;
+}
+
+static void sierra_outdat_callback(struct urb *urb)
+{
+ struct usb_serial_port *port = urb->context;
+ struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+ struct sierra_intf_private *intfdata;
+ int status = urb->status;
+
+ dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number);
+ intfdata = port->serial->private;
+
+ usb_autopm_put_interface_async(port->serial->interface);
+
+ atomic_inc(&intfdata->stats.outdat_cb_cnt);
+
+ if (status) {
+ dev_dbg(&port->dev, "%s - nonzero write bulk status "
+ "received: %d\n", __func__, status);
+ atomic_inc(&intfdata->stats.outdat_cb_fail);
+ }
+
+ spin_lock(&portdata->lock);
+ --portdata->outstanding_urbs;
+ spin_unlock(&portdata->lock);
+
+ spin_lock(&intfdata->susp_lock);
+ --intfdata->in_flight;
+ spin_unlock(&intfdata->susp_lock);
+
+ usb_serial_port_softint(port);
+}
+
+/* Write */
+static int sierra_write(struct tty_struct *tty,
+ struct usb_serial_port *port,
+ const unsigned char *buf, int count)
+{
+ struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+ struct sierra_intf_private *intfdata;
+ struct usb_serial *serial = port->serial;
+ unsigned long flags;
+ unsigned char *buffer;
+ struct urb *urb;
+ size_t writesize = min((size_t)count, (size_t)MAX_TRANSFER);
+ int retval = 0;
+
+ /* verify that we actually have some data to write */
+ if (count == 0)
+ return 0;
+
+ dev_dbg(&port->dev, "%s: write (%zu bytes)\n", __func__, writesize);
+
+ intfdata = serial->private;
+
+ spin_lock_irqsave(&portdata->lock, flags);
+ if (portdata->outstanding_urbs > portdata->num_out_urbs) {
+ spin_unlock_irqrestore(&portdata->lock, flags);
+ dev_dbg(&port->dev, "%s - write limit hit\n", __func__);
+ return 0;
+ }
+ portdata->outstanding_urbs++;
+ spin_unlock_irqrestore(&portdata->lock, flags);
+
+ retval = usb_autopm_get_interface_async(serial->interface);
+ if (unlikely(retval < 0)) {
+ spin_lock_irqsave(&portdata->lock, flags);
+ portdata->outstanding_urbs--;
+ spin_unlock_irqrestore(&portdata->lock, flags);
+ return retval;
+ }
+
+ buffer = kmalloc(writesize, GFP_ATOMIC);
+ if (!buffer) {
+ dev_err(&port->dev, "out of memory\n");
+ spin_lock_irqsave(&portdata->lock, flags);
+ --portdata->outstanding_urbs;
+ spin_unlock_irqrestore(&portdata->lock, flags);
+ usb_autopm_put_interface_async(serial->interface);
+ return -ENOMEM;
+ }
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ dev_err(&port->dev, "no more free urbs\n");
+ kfree(buffer);
+ spin_lock_irqsave(&portdata->lock, flags);
+ --portdata->outstanding_urbs;
+ spin_unlock_irqrestore(&portdata->lock, flags);
+ usb_autopm_put_interface_async(serial->interface);
+ return -ENOMEM;
+ }
+
+ memcpy(buffer, buf, writesize);
+
+ usb_serial_debug_data(debug, &port->dev, __func__, writesize, buffer);
+
+ usb_fill_bulk_urb(urb, serial->dev,
+ usb_sndbulkpipe(serial->dev,
+ port->bulk_out_endpointAddress),
+ buffer, writesize, sierra_outdat_callback, port);
+
+ /* Handle the need to send a zero length packet and release the
+ * transfer buffer
+ */
+ urb->transfer_flags |= (URB_ZERO_PACKET | URB_FREE_BUFFER);
+
+ spin_lock_irqsave(&intfdata->susp_lock, flags);
+
+ if (intfdata->suspended) {
+ usb_anchor_urb(urb, &portdata->delayed);
+ spin_unlock_irqrestore(&intfdata->susp_lock, flags);
+ /* release our reference to this urb, the USB core will
+ * eventually free it entirely */
+ usb_free_urb(urb);
+ return writesize;
+ }
+ usb_anchor_urb(urb, &portdata->active);
+
+ /* send it down the pipe */
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval) {
+ usb_unanchor_urb(urb);
+ spin_unlock_irqrestore(&intfdata->susp_lock, flags);
+
+ dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
+ "with status = %d\n", __func__, retval);
+ usb_free_urb(urb);
+ spin_lock_irqsave(&portdata->lock, flags);
+ --portdata->outstanding_urbs;
+ spin_unlock_irqrestore(&portdata->lock, flags);
+ usb_autopm_put_interface_async(serial->interface);
+ atomic_inc(&intfdata->stats.write_err);
+ return retval;
+ } else {
+ intfdata->in_flight++;
+ spin_unlock_irqrestore(&intfdata->susp_lock, flags);
+ atomic_inc(&intfdata->stats.write_cnt);
+ atomic_add(writesize, &intfdata->stats.tx_bytes);
+ }
+ /* release our reference to this urb, the USB core will eventually
+ * free it entirely */
+ usb_free_urb(urb);
+
+ return writesize;
+}
+
+static void sierra_indat_callback(struct urb *urb)
+{
+ int err;
+ int endpoint;
+ struct usb_serial_port *port = urb->context;
+ struct tty_struct *tty;
+ struct sierra_intf_private *intfdata;
+ unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
+
+ endpoint = usb_pipeendpoint(urb->pipe);
+
+ dev_dbg(&port->dev, "%s: %p\n", __func__, urb);
+
+ intfdata = port->serial->private;
+
+ atomic_inc(&intfdata->stats.indat_cb_cnt); /* indat calls */
+
+ if (status) {
+ dev_dbg(&port->dev, "%s: nonzero status: %d on"
+ " endpoint %02x\n", __func__, status, endpoint);
+ atomic_inc(&intfdata->stats.indat_cb_fail); /* indat fails */
+ } else {
+ if (urb->actual_length) {
+ tty = tty_port_tty_get(&port->port);
+ if (tty) {
+ tty_insert_flip_string(tty, data,
+ urb->actual_length);
+ tty_flip_buffer_push(tty);
+
+ tty_kref_put(tty);
+ /* tty invalid after this point */
+ /* rx'd bytes */
+ atomic_add(urb->actual_length,
+ &intfdata->stats.rx_bytes);
+ usb_serial_debug_data(debug, &port->dev,
+ __func__, urb->actual_length, data);
+ }
+ } else {
+ dev_dbg(&port->dev, "%s: empty read urb"
+ " received\n", __func__);
+ }
+ }
+
+ /* Resubmit urb so we continue receiving */
+ if (status != -ESHUTDOWN && status != -ENOENT && status != -ENODEV) {
+ usb_mark_last_busy(port->serial->dev);
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err && err != -ENODEV)
+ dev_err(&port->dev, "resubmit read urb failed."
+ "(%d)\n", err);
+ }
+
+ return;
+}
+
+static void sierra_instat_callback(struct urb *urb)
+{
+ int err;
+ int status = urb->status;
+ struct usb_serial_port *port = urb->context;
+ struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+ struct usb_serial *serial = port->serial;
+
+ dev_dbg(&port->dev, "%s: %p\n", __func__, urb);
+
+ if (status == 0) {
+ struct usb_ctrlrequest *req_pkt =
+ (struct usb_ctrlrequest *)urb->transfer_buffer;
+
+ const u16 *sigp = (u16 *)(req_pkt + 1);
+ /* usb_ctrlrequest we parsed is followed by two bytes of data
+ * make sure we received that many bytes
+ */
+ if (urb->actual_length >= sizeof(*req_pkt) + sizeof(*sigp) &&
+ req_pkt->bRequestType == USB_REQUEST_TYPE_CLASS &&
+ req_pkt->bRequest == USB_REQUEST_IFACE) {
+ int old_dcd_state;
+ const u16 signals = get_unaligned_le16(sigp);
+ struct tty_struct *tty;
+
+ dev_dbg(&port->dev, "%s: signal 0x%x\n", __func__,
+ signals);
+
+ old_dcd_state = portdata->dcd_state;
+ /* Note: CTS from modem is in reverse logic! */
+ portdata->cts_state = ((signals & 0x100) ? 0 : 1);
+ portdata->dcd_state = ((signals & 0x01) ? 1 : 0);
+ portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
+ portdata->ri_state = ((signals & 0x08) ? 1 : 0);
+
+ tty = tty_port_tty_get(&port->port);
+ if (tty && !C_CLOCAL(tty) &&
+ old_dcd_state && !portdata->dcd_state)
+ tty_hangup(tty);
+ tty_kref_put(tty);
+ } else {
+ /* dump the data we don't understand to log */
+ usb_serial_debug_data(1, &port->dev, __func__,
+ urb->actual_length, urb->transfer_buffer);
+ }
+ } else
+ dev_dbg(&port->dev, "%s: error %d\n", __func__, status);
+
+ /* Resubmit urb so we continue receiving IRQ data */
+ if (status != -ESHUTDOWN && status != -ENOENT && status != -ENODEV) {
+ usb_mark_last_busy(serial->dev);
+ urb->dev = serial->dev;
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err && err != -ENODEV)
+ dev_err(&port->dev, "%s: resubmit intr urb "
+ "failed. (%d)\n", __func__, err);
+ }
+}
+
+static int sierra_write_room(struct tty_struct *tty)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+ unsigned long flags;
+ int retval;
+
+ dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number);
+
+ /* try to give a good number back based on if we have any free urbs at
+ * this point in time */
+ retval = MAX_TRANSFER;
+
+ spin_lock_irqsave(&portdata->lock, flags);
+ if (portdata->outstanding_urbs >= portdata->num_out_urbs) {
+ retval = 0;
+ }
+ spin_unlock_irqrestore(&portdata->lock, flags);
+
+ return retval;
+}
+
+static void sierra_stop_rx_urbs(struct usb_serial_port *port)
+{
+ int i;
+ struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+
+ for (i = 0; i < portdata->num_in_urbs; i++)
+ usb_kill_urb(portdata->in_urbs[i]);
+
+ usb_kill_urb(port->interrupt_in_urb);
+}
+
+static int sierra_submit_rx_urbs(struct usb_serial_port *port, gfp_t mem_flags)
+{
+ int ok_cnt;
+ int err = -EINVAL;
+ int i;
+ struct urb *urb;
+ struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+
+ ok_cnt = 0;
+ for (i = 0; i < portdata->num_in_urbs; i++) {
+ urb = portdata->in_urbs[i];
+ if (!urb)
+ continue;
+ urb->transfer_flags |= URB_FREE_BUFFER;
+ err = usb_submit_urb(urb, mem_flags);
+ if (err) {
+ dev_err(&port->dev, "%s: submit urb failed: %d\n",
+ __func__, err);
+ } else {
+ ok_cnt++;
+ }
+ }
+
+ if (ok_cnt && port->interrupt_in_urb) {
+ err = usb_submit_urb(port->interrupt_in_urb, mem_flags);
+ if (err) {
+ dev_err(&port->dev, "%s: submit intr urb failed: %d\n",
+ __func__, err);
+ }
+ }
+
+ if (ok_cnt > 0) /* at least one rx urb submitted */
+ return 0;
+ else
+ return err;
+}
+
+static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint,
+ int dir, void *ctx, int len,
+ gfp_t mem_flags,
+ usb_complete_t callback)
+{
+ struct urb *urb;
+ u8 *buf;
+
+ if (endpoint == -1)
+ return NULL;
+
+ urb = usb_alloc_urb(0, mem_flags);
+ if (urb == NULL) {
+ dev_dbg(&serial->dev->dev, "%s: alloc for endpoint %d failed\n",
+ __func__, endpoint);
+ return NULL;
+ }
+
+ buf = kmalloc(len, mem_flags);
+ if (buf) {
+ /* Fill URB using supplied data */
+ usb_fill_bulk_urb(urb, serial->dev,
+ usb_sndbulkpipe(serial->dev, endpoint) | dir,
+ buf, len, callback, ctx);
+
+ /* debug */
+ dev_dbg(&serial->dev->dev, "%s %c u : %p d:%p\n", __func__,
+ dir == USB_DIR_IN ? 'i' : 'o', urb, buf);
+ } else {
+ dev_dbg(&serial->dev->dev, "%s %c u:%p d:%p\n", __func__,
+ dir == USB_DIR_IN ? 'i' : 'o', urb, buf);
+
+ sierra_release_urb(urb);
+ urb = NULL;
+ }
+
+ return urb;
+}
+static void sierra_close(struct usb_serial_port *port)
+{
+ int i;
+ struct urb *urb;
+ struct usb_serial *serial = port->serial;
+ struct sierra_port_private *portdata;
+ struct sierra_intf_private *intfdata = port->serial->private;
+
+ dev_dbg(&port->dev, "%s\n", __func__);
+ portdata = usb_get_serial_port_data(port);
+
+ portdata->rts_state = 0;
+ portdata->dtr_state = 0;
+
+ usb_autopm_get_interface(serial->interface);
+
+ if (serial->dev) {
+ mutex_lock(&serial->disc_mutex);
+ if (!serial->disconnected)
+ sierra_send_setup(port);
+ mutex_unlock(&serial->disc_mutex);
+ spin_lock_irq(&intfdata->susp_lock);
+ portdata->opened = 0;
+ spin_unlock_irq(&intfdata->susp_lock);
+
+ /* Stop reading urbs */
+ sierra_stop_rx_urbs(port);
+ /* .. and release them */
+ for (i = 0; i < portdata->num_in_urbs; i++) {
+ sierra_release_urb(portdata->in_urbs[i]);
+ portdata->in_urbs[i] = NULL;
+ }
+ while((urb = usb_get_from_anchor(&portdata->delayed))) {
+ sierra_release_urb(urb);
+ usb_autopm_put_interface(serial->interface);
+ }
+ /* wait for active to finish */
+ usb_wait_anchor_empty_timeout(&portdata->active, 500);
+ usb_kill_anchored_urbs(&portdata->active);
+
+ }
+}
+
+static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port)
+{
+ struct sierra_port_private *portdata;
+ struct usb_serial *serial = port->serial;
+ struct sierra_intf_private *intfdata = serial->private;
+ int i;
+ int err;
+ int endpoint;
+ struct urb *urb;
+
+ portdata = usb_get_serial_port_data(port);
+
+ dev_dbg(&port->dev, "%s\n", __func__);
+
+ /* Set some sane defaults */
+ portdata->rts_state = 1;
+ portdata->dtr_state = 1;
+
+
+ endpoint = port->bulk_in_endpointAddress;
+ for (i = 0; i < portdata->num_in_urbs; i++) {
+ urb = sierra_setup_urb(serial, endpoint, USB_DIR_IN, port,
+ IN_BUFLEN, GFP_KERNEL,
+ sierra_indat_callback);
+ portdata->in_urbs[i] = urb;
+ }
+ /* clear halt condition */
+ usb_clear_halt(serial->dev,
+ usb_sndbulkpipe(serial->dev, endpoint) | USB_DIR_IN);
+
+ /* reset outstanding out urbs counter */
+ spin_lock_irq(&portdata->lock);
+ portdata->outstanding_urbs = 0;
+ spin_unlock_irq(&portdata->lock);
+
+ err = sierra_submit_rx_urbs(port, GFP_KERNEL);
+ if (err) {
+ /* do everything as in close() but do not call close() because
+ * usbserial calls sierra_open() with mutex taken;
+ * then if we call sierra_close() inside sierra_open() we
+ * violate 'no nested mutexes' kernel condition
+ */
+ portdata->rts_state = 0;
+ portdata->dtr_state = 0;
+ usb_autopm_get_interface(serial->interface);
+ /* Stop reading urbs */
+ sierra_stop_rx_urbs(port);
+ /* .. and release them */
+ for (i = 0; i < portdata->num_in_urbs; i++) {
+ sierra_release_urb(portdata->in_urbs[i]);
+ portdata->in_urbs[i] = NULL;
+ }
+ while((urb = usb_get_from_anchor(&portdata->delayed))) {
+ sierra_release_urb(urb);
+ usb_autopm_put_interface(serial->interface);
+ }
+ /* wait for active to finish */
+ usb_wait_anchor_empty_timeout(&portdata->active, 500);
+ usb_kill_anchored_urbs(&portdata->active);
+ /* restore balance for autopm */
+ usb_autopm_put_interface(serial->interface);
+ return err;
+ }
+ sierra_send_setup(port);
+
+ spin_lock_irq(&intfdata->susp_lock);
+ portdata->opened = 1;
+ spin_unlock_irq(&intfdata->susp_lock);
+ usb_autopm_put_interface(serial->interface);
+
+ return 0;
+}
+
+static void sierra_dtr_rts(struct usb_serial_port *port, int on)
+{
+ struct usb_serial *serial = port->serial;
+ struct sierra_port_private *portdata;
+
+ portdata = usb_get_serial_port_data(port);
+ portdata->rts_state = on;
+ portdata->dtr_state = on;
+
+ if (serial->dev) {
+ mutex_lock(&serial->disc_mutex);
+ if (!serial->disconnected)
+ sierra_send_setup(port);
+ mutex_unlock(&serial->disc_mutex);
+ }
+}
+
+static int sierra_startup(struct usb_serial *serial)
+{
+ struct usb_serial_port *port = NULL;
+ struct sierra_port_private *portdata = NULL;
+ struct sierra_iface_info *himemoryp = NULL;
+ int i;
+ u8 ifnum;
+ u16 fw_attr;
+ int result;
+
+ dev_dbg(&serial->dev->dev, "%s\n", __func__);
+
+ /* Set Device mode to D0 */
+ sierra_set_power_state(serial->dev, 0x0000);
+
+ /* Check NMEA and set */
+ if (nmea)
+ sierra_vsc_set_nmea(serial->dev, 1);
+
+ if (serial->num_ports) {
+ /* Note: One big piece of memory is allocated for all ports
+ * private data in one shot. This memory is split into equal
+ * pieces for each port.
+ */
+ portdata = (struct sierra_port_private *)kzalloc
+ (sizeof(*portdata) * serial->num_ports, GFP_KERNEL);
+ if (!portdata) {
+ dev_dbg(&serial->dev->dev, "%s: No memory!\n", __func__);
+ return -ENOMEM;
+ }
+ }
+
+ /* Now setup per port private data */
+ for (i = 0; i < serial->num_ports; i++, portdata++) {
+ port = serial->port[i];
+ /* Initialize selected members of private data because these
+ * may be referred to right away */
+ spin_lock_init(&portdata->lock);
+ init_usb_anchor(&portdata->active);
+ init_usb_anchor(&portdata->delayed);
+
+ portdata->cts_state = 1;
+
+ ifnum = i;
+ /* Assume low memory requirements */
+ portdata->num_out_urbs = N_OUT_URB;
+ portdata->num_in_urbs = N_IN_URB;
+
+ /* Determine actual memory requirements */
+ if (serial->num_ports == 1) {
+ /* Get interface number for composite device */
+ ifnum = sierra_calc_interface(serial);
+ himemoryp =
+ (struct sierra_iface_info *)&typeB_interface_list;
+ if (is_himemory(ifnum, himemoryp)) {
+ portdata->num_out_urbs = N_OUT_URB_HM;
+ portdata->num_in_urbs = N_IN_URB_HM;
+ }
+ }
+ else {
+ himemoryp =
+ (struct sierra_iface_info *)&typeA_interface_list;
+ if (is_himemory(i, himemoryp)) {
+ portdata->num_out_urbs = N_OUT_URB_HM;
+ portdata->num_in_urbs = N_IN_URB_HM;
+ }
+ }
+ dev_dbg(&serial->dev->dev,
+ "Memory usage (urbs) interface #%d, in=%d, out=%d\n",
+ ifnum,portdata->num_in_urbs, portdata->num_out_urbs );
+ /* Set the port private data pointer */
+ usb_set_serial_port_data(port, portdata);
+ }
+ serial->interface->needs_remote_wakeup = 1;
+
+ result = sierra_get_fw_attr(serial->dev, &fw_attr);
+ if (result == sizeof(fw_attr) && (fw_attr & SWI_FW_ATTR_PM_MASK) ) {
+ dev_info(&serial->dev->dev,
+ "APM supported, enabling autosuspend.\n");
+/*******************************************************************************
+ * If you want the default /sys/bus/usb/devices/.../.../power/level to be forced
+ * to auto, the following needs to be compiled in.
+ */
+#ifdef POWER_LEVEL_AUTO
+ /* make power level default be 'auto' */
+ usb_enable_autosuspend(serial->dev);
+#endif
+ } else {
+ usb_disable_autosuspend(serial->dev);
+ }
+
+ return 0;
+}
+
+static void sierra_release(struct usb_serial *serial)
+{
+ int i;
+ struct usb_serial_port *port;
+ struct sierra_intf_private *intfdata = serial->private;
+
+ dev_dbg(&serial->dev->dev, "%s\n", __func__);
+
+ if (serial->num_ports > 0) {
+ port = serial->port[0];
+ if (port)
+ /* Note: The entire piece of memory that was allocated
+ * in the startup routine can be released by passing
+ * a pointer to the beginning of the piece.
+ * This address corresponds to the address of the chunk
+ * that was given to port 0.
+ */
+ kfree(usb_get_serial_port_data(port));
+ }
+
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+ if (!port)
+ continue;
+ usb_set_serial_port_data(port, NULL);
+ }
+ kfree(intfdata);
+}
+
+#ifdef CONFIG_PM
+static void stop_read_write_urbs(struct usb_serial *serial)
+{
+ int i;
+ struct usb_serial_port *port;
+ struct sierra_port_private *portdata;
+
+ /* Stop reading/writing urbs */
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+ portdata = usb_get_serial_port_data(port);
+ sierra_stop_rx_urbs(port);
+ usb_kill_anchored_urbs(&portdata->active);
+ }
+}
+
+static int sierra_suspend(struct usb_serial *serial, pm_message_t message)
+{
+ struct sierra_intf_private *intfdata;
+
+ dev_dbg(&serial->dev->dev, "%s\n", __func__);
+
+ intfdata = serial->private;
+ spin_lock_irq(&intfdata->susp_lock);
+
+ if (message.event & PM_EVENT_AUTO) {
+ if (intfdata->in_flight) {
+ spin_unlock_irq(&intfdata->susp_lock);
+ return -EBUSY;
+ }
+ }
+ intfdata->suspended = 1;
+ spin_unlock_irq(&intfdata->susp_lock);
+
+ stop_read_write_urbs(serial);
+
+ return 0;
+}
+
+static int sierra_resume(struct usb_serial *serial)
+{
+ struct usb_serial_port *port;
+ struct sierra_intf_private *intfdata = serial->private;
+ struct sierra_port_private *portdata;
+ struct urb *urb;
+ int ec = 0;
+ int i, err;
+ int len;
+ int failed_submits;
+
+ dev_dbg(&serial->dev->dev, "%s\n", __func__);
+
+ spin_lock_irq(&intfdata->susp_lock);
+ for (i = 0; i < serial->num_ports; i++) {
+ port = serial->port[i];
+ portdata = usb_get_serial_port_data(port);
+ failed_submits = 0;
+ while ((urb = usb_get_from_anchor(&portdata->delayed))) {
+ usb_anchor_urb(urb, &portdata->active);
+ intfdata->in_flight++;
+ len = urb->transfer_buffer_length;
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err < 0) {
+ intfdata->in_flight--;
+ usb_unanchor_urb(urb);
+ failed_submits++;
+ atomic_inc(&intfdata->stats.delayed_write_err);
+ /* fix pm_usage_cnt */
+ usb_autopm_put_interface_async(
+ port->serial->interface);
+ } else {
+ atomic_inc(&intfdata->stats.delayed_writes);
+ atomic_add(len, &intfdata->stats.tx_bytes);
+ }
+ /* release urb - usb_get_from_anchor increased kref */
+ usb_free_urb(urb);
+ }
+
+ if (portdata->opened) {
+ err = sierra_submit_rx_urbs(port, GFP_ATOMIC);
+ if (err)
+ ec++;
+ }
+ if (failed_submits) {
+ /* fix outstanding_urbs counter */
+ spin_lock(&portdata->lock); /* assuming irq disabled */
+ portdata->outstanding_urbs -= failed_submits;
+ spin_unlock(&portdata->lock);
+ /* unblock a writer */
+ usb_serial_port_softint(port);
+ }
+ }
+ intfdata->suspended = 0;
+ spin_unlock_irq(&intfdata->susp_lock);
+
+ return ec ? -EIO : 0;
+}
+#else
+#define sierra_suspend NULL
+#define sierra_resume NULL
+#endif
+
+static int sierra_reset_resume(struct usb_interface *intf)
+{
+ struct usb_serial *serial = usb_get_intfdata(intf);
+ dev_err(&serial->dev->dev, "%s\n", __func__);
+ return usb_serial_resume(intf);
+}
+
+static struct usb_driver sierra_driver = {
+ .name = "sierra",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .suspend = usb_serial_suspend,
+ .resume = usb_serial_resume,
+ .reset_resume = sierra_reset_resume,
+ .id_table = id_table,
+
+ .no_dynamic_id = 1,
+ .supports_autosuspend = 1,
+};
+
+
+static struct usb_serial_driver sierra_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "sierra",
+ },
+ .description = "Sierra USB modem",
+ .id_table = id_table,
+ .usb_driver = &sierra_driver,
+ .calc_num_ports = sierra_calc_num_ports,
+ .probe = sierra_probe,
+ .open = sierra_open,
+ .close = sierra_close,
+ .dtr_rts = sierra_dtr_rts,
+ .write = sierra_write,
+ .write_room = sierra_write_room,
+ .set_termios = sierra_set_termios,
+ .tiocmget = sierra_tiocmget,
+ .tiocmset = sierra_tiocmset,
+ .attach = sierra_startup,
+ .release = sierra_release,
+ .port_probe = sierra_create_sysfs_attrs,
+ .port_remove = sierra_remove_sysfs_attrs,
+ .suspend = sierra_suspend,
+ .resume = sierra_resume,
+ .read_int_callback = sierra_instat_callback,
+
+};
+
+/* Functions used by new usb-serial code. */
+static int __init sierra_init(void)
+{
+ int retval;
+ retval = usb_serial_register(&sierra_device);
+ if (retval)
+ goto failed_device_register;
+
+ retval = usb_register(&sierra_driver);
+ if (retval)
+ goto failed_driver_register;
+
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
+
+ return 0;
+
+failed_driver_register:
+ usb_serial_deregister(&sierra_device);
+failed_device_register:
+ return retval;
+}
+
+static void __exit sierra_exit(void)
+{
+ usb_deregister(&sierra_driver);
+ usb_serial_deregister(&sierra_device);
+}
+
+module_init(sierra_init);
+module_exit(sierra_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(nmea, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(nmea, "NMEA streaming");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug messages");
diff --git a/package/sierra-directip/src/sierra_net.c b/package/sierra-directip/src/sierra_net.c
new file mode 100644
index 000000000..f6057d918
--- /dev/null
+++ b/package/sierra-directip/src/sierra_net.c
@@ -0,0 +1,1123 @@
+/*
+ * USB-to-WWAN Driver for Sierra Wireless modems
+ *
+ * Copyright (C) 2008 - 2011 Paxton Smith, Matthew Safar, Rory Filer
+ * <linux@sierrawireless.com>
+ *
+ * Portions of this based on the cdc_ether driver by David Brownell (2003-2005)
+ * and Ole Andre Vadla Ravnas (ActiveSync) (2006).
+ *
+ * IMPORTANT DISCLAIMER: This driver is not commercially supported by
+ * Sierra Wireless. Use at your own risk.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ */
+
+#define DRIVER_VERSION "v.3.2"
+#define DRIVER_AUTHOR "Paxton Smith, Matthew Safar, Rory Filer"
+#define DRIVER_DESC "USB-to-WWAN Driver for Sierra Wireless modems"
+static const char driver_name[] = "sierra_net";
+
+/* if defined debug messages enabled */
+/*#define DEBUG*/
+/* more debug messages */
+/*#define VERBOSE*/
+/* Uncomment to force power level set to auto when attaching a device */
+/*#define POWER_LEVEL_AUTO*/
+
+#include <linux/module.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/usb.h>
+#include <linux/usb/cdc.h>
+#include <net/ip.h>
+#include <net/udp.h>
+#include <asm/unaligned.h>
+#include <linux/usb/usbnet.h>
+
+#define SWI_USB_REQUEST_GET_FW_ATTR 0x06
+#define SWI_GET_FW_ATTR_MASK 0x08
+#define SWI_GET_FW_ATTR_APM 0x2
+
+/* atomic counter partially included in MAC address to make sure 2 devices
+ * do not end up with the same MAC - concept breaks in case of > 255 ifaces
+ */
+static atomic_t iface_counter = ATOMIC_INIT(0);
+
+/*
+ * SYNC Timer Delay definition used to set the expiry time
+ */
+#define SIERRA_NET_SYNCDELAY (2*HZ)
+
+/* Max. MTU supported. The modem buffers are limited to 1500 */
+#define SIERRA_NET_MAX_SUPPORTED_MTU 1500
+
+/* The SIERRA_NET_USBCTL_BUF_LEN defines a buffer size allocated for control
+ * message reception ... and thus the max. received packet.
+ * (May be the cause for parse_hip returning -EINVAL)
+ */
+#define SIERRA_NET_USBCTL_BUF_LEN 1024
+
+/* The SIERRA_NET_RX_URB_SZ defines the receive urb size
+ * for optimal throughput.
+ */
+#define SIERRA_NET_RX_URB_SZ 1540
+
+/* list of interface numbers - used for constructing interface lists */
+struct sierra_net_iface_info {
+ const u32 infolen; /* number of interface numbers on list */
+ const u8 *ifaceinfo; /* pointer to the array holding the numbers */
+};
+
+struct sierra_net_info_data {
+ u16 rx_urb_size;
+ struct sierra_net_iface_info whitelist;
+};
+
+/* Private data structure */
+struct sierra_net_data {
+
+ u8 ethr_hdr_tmpl[ETH_HLEN]; /* ethernet header template for rx'd pkts */
+
+ u16 link_up; /* air link up or down */
+ u8 tx_hdr_template[4]; /* part of HIP hdr for tx'd packets */
+
+ u8 sync_msg[4]; /* SYNC message */
+ u8 shdwn_msg[4]; /* Shutdown message */
+
+ /* Backpointer to the container */
+ struct usbnet *usbnet;
+
+ u8 ifnum; /* interface number */
+
+/* Bit masks, must be a power of 2 */
+#define SIERRA_NET_EVENT_RESP_AVAIL 0x01
+#define SIERRA_NET_TIMER_EXPIRY 0x02
+ unsigned long kevent_flags;
+ struct work_struct sierra_net_kevent;
+ struct timer_list sync_timer; /* For retrying SYNC sequence */
+};
+
+struct param {
+ int is_present;
+ union {
+ void *ptr;
+ u32 dword;
+ u16 word;
+ u8 byte;
+ };
+};
+
+/* HIP message type */
+#define SIERRA_NET_HIP_EXTENDEDID 0x7F
+#define SIERRA_NET_HIP_HSYNC_ID 0x60 /* Modem -> host */
+#define SIERRA_NET_HIP_RESTART_ID 0x62 /* Modem -> host */
+#define SIERRA_NET_HIP_MSYNC_ID 0x20 /* Host -> modem */
+#define SIERRA_NET_HIP_SHUTD_ID 0x26 /* Host -> modem */
+
+#define SIERRA_NET_HIP_EXT_IP_IN_ID 0x0202
+#define SIERRA_NET_HIP_EXT_IP_OUT_ID 0x0002
+
+/* 3G UMTS Link Sense Indication definitions */
+#define SIERRA_NET_HIP_LSI_UMTSID 0x78
+
+/* Reverse Channel Grant Indication HIP message */
+#define SIERRA_NET_HIP_RCGI 0x64
+
+/* LSI Protocol types */
+#define SIERRA_NET_PROTOCOL_UMTS 0x01
+/* LSI Coverage */
+#define SIERRA_NET_COVERAGE_NONE 0x00
+#define SIERRA_NET_COVERAGE_NOPACKET 0x01
+
+/* LSI Session */
+#define SIERRA_NET_SESSION_IDLE 0x00
+/* LSI Link types */
+#define SIERRA_NET_AS_LINK_TYPE_IPv4 0x00
+#define SIERRA_NET_AS_LINK_TYPE_IPv6 0x02
+
+struct lsi_umts {
+ u8 protocol;
+ u8 unused1;
+ __be16 length;
+ /* eventually use a union for the rest - assume umts for now */
+ u8 coverage;
+ u8 unused2[41];
+ u8 session_state;
+ u8 unused3[33];
+ u8 link_type;
+ u8 pdp_addr_len; /* NW-supplied PDP address len */
+ u8 pdp_addr[16]; /* NW-supplied PDP address (bigendian)) */
+ u8 unused4[23];
+ u8 dns1_addr_len; /* NW-supplied 1st DNS address len (bigendian) */
+ u8 dns1_addr[16]; /* NW-supplied 1st DNS address */
+ u8 dns2_addr_len; /* NW-supplied 2nd DNS address len */
+ u8 dns2_addr[16]; /* NW-supplied 2nd DNS address (bigendian)*/
+ u8 wins1_addr_len; /* NW-supplied 1st Wins address len */
+ u8 wins1_addr[16]; /* NW-supplied 1st Wins address (bigendian)*/
+ u8 wins2_addr_len; /* NW-supplied 2nd Wins address len */
+ u8 wins2_addr[16]; /* NW-supplied 2nd Wins address (bigendian) */
+ u8 unused5[4];
+ u8 gw_addr_len; /* NW-supplied GW address len */
+ u8 gw_addr[16]; /* NW-supplied GW address (bigendian) */
+ u8 reserved[8];
+} __packed;
+
+#define SIERRA_NET_LSI_COMMON_LEN 4
+#define SIERRA_NET_LSI_UMTS_LEN (sizeof(struct lsi_umts))
+#define SIERRA_NET_LSI_UMTS_STATUS_LEN \
+ (SIERRA_NET_LSI_UMTS_LEN - SIERRA_NET_LSI_COMMON_LEN)
+
+/* Forward definitions */
+static void sierra_sync_timer(unsigned long syncdata);
+static int sierra_net_change_mtu(struct net_device *net, int new_mtu);
+
+/* Our own net device operations structure */
+static const struct net_device_ops sierra_net_device_ops = {
+ .ndo_open = usbnet_open,
+ .ndo_stop = usbnet_stop,
+ .ndo_start_xmit = usbnet_start_xmit,
+ .ndo_tx_timeout = usbnet_tx_timeout,
+ .ndo_change_mtu = sierra_net_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
+/* get private data associated with passed in usbnet device */
+static inline struct sierra_net_data *sierra_net_get_private(struct usbnet *dev)
+{
+ return (struct sierra_net_data *)dev->data[0];
+}
+
+/* set private data associated with passed in usbnet device */
+static inline void sierra_net_set_private(struct usbnet *dev,
+ struct sierra_net_data *priv)
+{
+ dev->data[0] = (unsigned long)priv;
+}
+
+/* is packet IP */
+static inline int is_ip(struct sk_buff *skb)
+{
+ return ((skb->protocol == cpu_to_be16(ETH_P_IP)) ||
+ (skb->protocol == cpu_to_be16(ETH_P_IPV6)));
+}
+
+/*
+ * check passed in packet and make sure that:
+ * - it is linear (no scatter/gather)
+ * - it is ethernet (mac_header properly set)
+ */
+static int check_ethip_packet(struct sk_buff *skb, struct usbnet *dev)
+{
+ skb_reset_mac_header(skb); /* ethernet header */
+
+ if (skb_is_nonlinear(skb)) {
+ netdev_err(dev->net, "Non linear buffer-dropping\n");
+ return 0;
+ }
+
+ if (!pskb_may_pull(skb, ETH_HLEN))
+ return 0;
+ skb->protocol = eth_hdr(skb)->h_proto;
+
+ return 1;
+}
+
+static const u8 *save16bit(struct param *p, const u8 *datap)
+{
+ p->is_present = 1;
+ p->word = get_unaligned_be16(datap);
+ return datap + sizeof(p->word);
+}
+
+static const u8 *save8bit(struct param *p, const u8 *datap)
+{
+ p->is_present = 1;
+ p->byte = *datap;
+ return datap + sizeof(p->byte);
+}
+
+/*----------------------------------------------------------------------------*
+ * BEGIN HIP *
+ *----------------------------------------------------------------------------*/
+/* HIP header */
+#define SIERRA_NET_HIP_HDR_LEN 4
+/* Extended HIP header */
+#define SIERRA_NET_HIP_EXT_HDR_LEN 6
+
+struct hip_hdr {
+ int hdrlen;
+ struct param payload_len;
+ struct param msgid;
+ struct param msgspecific;
+ struct param extmsgid;
+};
+
+static int parse_hip(const u8 *buf, const u32 buflen, struct hip_hdr *hh)
+{
+ const u8 *curp = buf;
+ int padded;
+
+ if (buflen < SIERRA_NET_HIP_HDR_LEN)
+ return -EPROTO;
+
+ curp = save16bit(&hh->payload_len, curp);
+ curp = save8bit(&hh->msgid, curp);
+ curp = save8bit(&hh->msgspecific, curp);
+
+ padded = hh->msgid.byte & 0x80;
+ hh->msgid.byte &= 0x7F; /* 7 bits */
+
+ hh->extmsgid.is_present = (hh->msgid.byte == SIERRA_NET_HIP_EXTENDEDID);
+ if (hh->extmsgid.is_present) {
+ if (buflen < SIERRA_NET_HIP_EXT_HDR_LEN)
+ return -EPROTO;
+
+ hh->payload_len.word &= 0x3FFF; /* 14 bits */
+
+ curp = save16bit(&hh->extmsgid, curp);
+ hh->extmsgid.word &= 0x03FF; /* 10 bits */
+
+ hh->hdrlen = SIERRA_NET_HIP_EXT_HDR_LEN;
+ } else {
+ hh->payload_len.word &= 0x07FF; /* 11 bits */
+ hh->hdrlen = SIERRA_NET_HIP_HDR_LEN;
+ }
+
+ if (padded) {
+ hh->hdrlen++;
+ hh->payload_len.word--;
+ }
+
+ /* if real packet shorter than the claimed length */
+ if (buflen < (hh->hdrlen + hh->payload_len.word))
+ return -EINVAL;
+
+ return 0;
+}
+
+static void build_hip(u8 *buf, const u16 payloadlen,
+ struct sierra_net_data *priv)
+{
+ /* the following doesn't have the full functionality. We
+ * currently build only one kind of header, so it is faster this way
+ */
+ put_unaligned_be16(payloadlen, buf);
+ memcpy(buf+2, priv->tx_hdr_template, sizeof(priv->tx_hdr_template));
+}
+/*----------------------------------------------------------------------------*
+ * END HIP *
+ *----------------------------------------------------------------------------*/
+/* This should come out before going to kernel.org */
+static void sierra_net_printk_buf(u8 *buf, u16 len)
+{
+#ifdef VERBOSE
+ u16 i;
+ u16 k;
+
+ for (i = k = 0; i < len / 4; i++, k += 4) {
+ printk(KERN_DEBUG "%02x%02x%02x%02x ",
+ buf[k+0], buf[k+1], buf[k+2], buf[k+3]);
+ }
+
+ for (; k < len; k++)
+ printk(KERN_DEBUG "%02x", buf[k]);
+
+ printk("\n");
+#endif
+}
+
+static int sierra_net_send_cmd(struct usbnet *dev,
+ u8 *cmd, int cmdlen, const char * cmd_name)
+{
+ struct sierra_net_data *priv = sierra_net_get_private(dev);
+ int status;
+
+ usb_autopm_get_interface(dev->intf);
+ status = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+ USB_CDC_SEND_ENCAPSULATED_COMMAND,
+ USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE, 0,
+ priv->ifnum, cmd, cmdlen, USB_CTRL_SET_TIMEOUT);
+ usb_autopm_put_interface(dev->intf);
+
+ if (status != cmdlen && status != -ENODEV)
+ netdev_err(dev->net, "Submit %s failed %d\n", cmd_name, status);
+
+ return status;
+}
+
+static int sierra_net_send_sync(struct usbnet *dev)
+{
+ int status;
+ struct sierra_net_data *priv = sierra_net_get_private(dev);
+
+ dev_dbg(&dev->udev->dev, "%s", __func__);
+
+ status = sierra_net_send_cmd(dev, priv->sync_msg,
+ sizeof(priv->sync_msg), "SYNC");
+ return status;
+}
+
+static void sierra_net_send_shutdown(struct usbnet *dev)
+{
+ struct sierra_net_data *priv = sierra_net_get_private(dev);
+
+ dev_dbg(&dev->udev->dev, "%s", __func__);
+
+ sierra_net_send_cmd(dev, priv->shdwn_msg,
+ sizeof(priv->shdwn_msg), "Shutdown");
+}
+
+static void sierra_net_set_ctx_index(struct sierra_net_data *priv, u8 ctx_ix)
+{
+ dev_dbg(&(priv->usbnet->udev->dev), "%s %d", __func__, ctx_ix);
+ priv->tx_hdr_template[0] = 0x3F;
+ priv->tx_hdr_template[1] = ctx_ix;
+ *((u16 *)&priv->tx_hdr_template[2]) =
+ cpu_to_be16(SIERRA_NET_HIP_EXT_IP_OUT_ID);
+}
+
+static inline int sierra_net_is_valid_addrlen(u8 len)
+{
+ return (len == sizeof(struct in_addr));
+}
+
+static int sierra_net_parse_lsi(struct usbnet *dev, char *data, int datalen)
+{
+ struct lsi_umts *lsi = (struct lsi_umts *)data;
+
+ if (datalen < sizeof(struct lsi_umts)) {
+ netdev_err(dev->net, "%s: Data length %d, exp %Zu\n",
+ __func__, datalen,
+ sizeof(struct lsi_umts));
+ return -1;
+ }
+
+ if (lsi->length != cpu_to_be16(SIERRA_NET_LSI_UMTS_STATUS_LEN)) {
+ netdev_err(dev->net, "%s: LSI_UMTS_STATUS_LEN %d, exp %u\n",
+ __func__, be16_to_cpu(lsi->length),
+ (u32)SIERRA_NET_LSI_UMTS_STATUS_LEN);
+ return -1;
+ }
+
+ /* Validate the protocol - only support UMTS for now */
+ if (lsi->protocol != SIERRA_NET_PROTOCOL_UMTS) {
+ netdev_err(dev->net, "Protocol unsupported, 0x%02x\n",
+ lsi->protocol);
+ return -1;
+ }
+
+ /* Validate the link type */
+ if ((lsi->link_type != SIERRA_NET_AS_LINK_TYPE_IPv4) &&
+ (lsi->link_type != SIERRA_NET_AS_LINK_TYPE_IPv6)) {
+ netdev_err(dev->net, "Link unavailable: 0x%02x",
+ lsi->link_type);
+ return 0;
+ }
+
+ /* Validate the coverage */
+ if (lsi->coverage == SIERRA_NET_COVERAGE_NONE
+ || lsi->coverage == SIERRA_NET_COVERAGE_NOPACKET) {
+ netdev_err(dev->net, "No coverage, 0x%02x\n", lsi->coverage);
+ return 0;
+ }
+
+ /* Validate the session state */
+ if (lsi->session_state == SIERRA_NET_SESSION_IDLE) {
+ netdev_err(dev->net, "Session idle, 0x%02x\n",
+ lsi->session_state);
+ return 0;
+ }
+
+ /* Set link_sense true */
+ return 1;
+}
+
+static void sierra_net_handle_lsi(struct usbnet *dev, char *data,
+ struct hip_hdr *hh)
+{
+ struct sierra_net_data *priv = sierra_net_get_private(dev);
+ int link_up;
+
+ link_up = sierra_net_parse_lsi(dev, data + hh->hdrlen,
+ hh->payload_len.word);
+ if (link_up < 0) {
+ netdev_err(dev->net, "Invalid LSI\n");
+ return;
+ }
+ if (link_up) {
+ sierra_net_set_ctx_index(priv, hh->msgspecific.byte);
+ priv->link_up = 1;
+ netif_carrier_on(dev->net);
+ } else {
+ priv->link_up = 0;
+ netif_carrier_off(dev->net);
+ }
+}
+
+static void sierra_net_dosync(struct usbnet *dev)
+{
+ int status;
+ struct sierra_net_data *priv = sierra_net_get_private(dev);
+
+ dev_dbg(&dev->udev->dev, "%s", __func__);
+
+ /* tell modem we are ready */
+ status = sierra_net_send_sync(dev);
+ if (status < 0)
+ netdev_err(dev->net,
+ "Send SYNC failed, status %d\n", status);
+ status = sierra_net_send_sync(dev);
+ if (status < 0)
+ netdev_err(dev->net,
+ "Send SYNC failed, status %d\n", status);
+
+ /* Now, start a timer and make sure we get the Restart Indication */
+ priv->sync_timer.function = sierra_sync_timer;
+ priv->sync_timer.data = (unsigned long) dev;
+ priv->sync_timer.expires = jiffies + SIERRA_NET_SYNCDELAY;
+ add_timer(&priv->sync_timer);
+}
+
+static void sierra_net_kevent(struct work_struct *work)
+{
+ struct sierra_net_data *priv =
+ container_of(work, struct sierra_net_data, sierra_net_kevent);
+ struct usbnet *dev = priv->usbnet;
+ int len;
+ int err;
+ u8 *buf;
+ u8 ifnum;
+
+ if (test_bit(SIERRA_NET_EVENT_RESP_AVAIL, &priv->kevent_flags)) {
+ clear_bit(SIERRA_NET_EVENT_RESP_AVAIL, &priv->kevent_flags);
+
+ /* Query the modem for the LSI message */
+ buf = kzalloc(SIERRA_NET_USBCTL_BUF_LEN, GFP_KERNEL);
+ if (!buf) {
+ netdev_err(dev->net,
+ "failed to allocate buf for LS msg\n");
+ return;
+ }
+ ifnum = priv->ifnum;
+ usb_autopm_get_interface(dev->intf);
+ len = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+ USB_CDC_GET_ENCAPSULATED_RESPONSE,
+ USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE,
+ 0, ifnum, buf, SIERRA_NET_USBCTL_BUF_LEN,
+ USB_CTRL_SET_TIMEOUT);
+ usb_autopm_put_interface(dev->intf);
+
+ if (unlikely(len < 0)) {
+ netdev_err(dev->net,
+ "usb_control_msg failed, status %d\n", len);
+ } else {
+ struct hip_hdr hh;
+
+ dev_dbg(&dev->udev->dev, "%s: Received status message,"
+ " %04x bytes", __func__, len);
+ sierra_net_printk_buf(buf, len);
+
+ err = parse_hip(buf, len, &hh);
+ if (err) {
+ netdev_err(dev->net, "%s: Bad packet,"
+ " parse result %d\n", __func__, err);
+ kfree(buf);
+ return;
+ }
+
+ /* Validate packet length */
+ if (len != hh.hdrlen + hh.payload_len.word) {
+ netdev_err(dev->net, "%s: Bad packet, received"
+ " %d, expected %d\n", __func__, len,
+ hh.hdrlen + hh.payload_len.word);
+ kfree(buf);
+ return;
+ }
+
+ /* Switch on received message types */
+ switch (hh.msgid.byte) {
+ case SIERRA_NET_HIP_LSI_UMTSID:
+ dev_dbg(&dev->udev->dev, "LSI for ctx:%d",
+ hh.msgspecific.byte);
+ sierra_net_handle_lsi(dev, buf, &hh);
+ break;
+ case SIERRA_NET_HIP_RESTART_ID:
+ dev_dbg(&dev->udev->dev, "Restart reported: %d,"
+ " stopping sync timer",
+ hh.msgspecific.byte);
+ /* Got sync resp - stop timer & clear mask */
+ del_timer_sync(&priv->sync_timer);
+ clear_bit(SIERRA_NET_TIMER_EXPIRY,
+ &priv->kevent_flags);
+ break;
+ case SIERRA_NET_HIP_HSYNC_ID:
+ dev_dbg(&dev->udev->dev, "SYNC received");
+ err = sierra_net_send_sync(dev);
+ if (err < 0)
+ netdev_err(dev->net,
+ "Send SYNC failed %d\n", err);
+ break;
+ case SIERRA_NET_HIP_EXTENDEDID:
+ netdev_err(dev->net, "Unrecognized HIP msg, "
+ "extmsgid 0x%04x\n", hh.extmsgid.word);
+ break;
+ case SIERRA_NET_HIP_RCGI:
+ /* Ignored. It is a firmware
+ * workaround to solve a Windows driver bug and
+ * may be removed in the future.
+ */
+ break;
+ default:
+ netdev_err(dev->net, "Unrecognized HIP msg, "
+ "msgid 0x%02x\n", hh.msgid.byte);
+ break;
+ }
+ }
+ kfree(buf);
+ }
+ /* The sync timer bit might be set */
+ if (test_bit(SIERRA_NET_TIMER_EXPIRY, &priv->kevent_flags)) {
+ clear_bit(SIERRA_NET_TIMER_EXPIRY, &priv->kevent_flags);
+ dev_dbg(&dev->udev->dev, "Deferred sync timer expiry");
+ sierra_net_dosync(priv->usbnet);
+ }
+
+ if (priv->kevent_flags)
+ dev_dbg(&dev->udev->dev, "sierra_net_kevent done, "
+ "kevent_flags = 0x%lx", priv->kevent_flags);
+}
+
+static void sierra_net_defer_kevent(struct usbnet *dev, int work)
+{
+ struct sierra_net_data *priv = sierra_net_get_private(dev);
+
+ set_bit(work, &priv->kevent_flags);
+ if (!schedule_work(&priv->sierra_net_kevent))
+ dev_dbg(&dev->udev->dev, "sierra_net_kevent %d may have been dropped", work);
+ else
+ dev_dbg(&dev->udev->dev, "sierra_net_kevent %d scheduled", work);
+}
+
+/*
+ * Sync Retransmit Timer Handler. On expiry, kick the work queue
+ */
+void sierra_sync_timer(unsigned long syncdata)
+{
+ struct usbnet *dev = (struct usbnet *)syncdata;
+
+ dev_dbg(&dev->udev->dev, "%s", __func__);
+ /* Kick the tasklet */
+ sierra_net_defer_kevent(dev, SIERRA_NET_TIMER_EXPIRY);
+}
+
+static void sierra_net_status(struct usbnet *dev, struct urb *urb)
+{
+ struct usb_cdc_notification *event;
+
+ dev_dbg(&dev->udev->dev, "%s", __func__);
+ sierra_net_printk_buf(urb->transfer_buffer, urb->actual_length);
+
+ if (urb->actual_length < sizeof *event)
+ return;
+
+ /* Add cases to handle other standard notifications. */
+ event = urb->transfer_buffer;
+ switch (event->bNotificationType) {
+ case USB_CDC_NOTIFY_NETWORK_CONNECTION:
+ case USB_CDC_NOTIFY_SPEED_CHANGE:
+ /* USB 305 sends those */
+ break;
+ case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:
+ sierra_net_defer_kevent(dev, SIERRA_NET_EVENT_RESP_AVAIL);
+ break;
+ default:
+ netdev_err(dev->net, ": unexpected notification %02x!\n",
+ event->bNotificationType);
+ break;
+ }
+}
+
+static void sierra_net_get_drvinfo(struct net_device *net,
+ struct ethtool_drvinfo *info)
+{
+ /* Inherit standard device info */
+ usbnet_get_drvinfo(net, info);
+ strncpy(info->driver, driver_name, sizeof info->driver);
+ strncpy(info->version, DRIVER_VERSION, sizeof info->version);
+}
+
+static u32 sierra_net_get_link(struct net_device *net)
+{
+ struct usbnet *dev = netdev_priv(net);
+ /* Report link is down whenever the interface is down */
+ return sierra_net_get_private(dev)->link_up && netif_running(net);
+}
+
+static struct ethtool_ops sierra_net_ethtool_ops = {
+ .get_drvinfo = sierra_net_get_drvinfo,
+ .get_link = sierra_net_get_link,
+ .get_msglevel = usbnet_get_msglevel,
+ .set_msglevel = usbnet_set_msglevel,
+ .get_settings = usbnet_get_settings,
+ .set_settings = usbnet_set_settings,
+ .nway_reset = usbnet_nway_reset,
+};
+
+/* MTU can not be more than 1500 bytes, enforce it. */
+static int sierra_net_change_mtu(struct net_device *net, int new_mtu)
+{
+ if (new_mtu > SIERRA_NET_MAX_SUPPORTED_MTU)
+ return -EINVAL;
+
+ return usbnet_change_mtu(net, new_mtu);
+}
+
+static int is_whitelisted(const u8 ifnum,
+ const struct sierra_net_iface_info *whitelist)
+{
+ if (whitelist) {
+ const u8 *list = whitelist->ifaceinfo;
+ int i;
+
+ for (i = 0; i < whitelist->infolen; i++) {
+ if (list[i] == ifnum)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap)
+{
+ int result = 0;
+ u16 *attrdata;
+
+ attrdata = kmalloc(sizeof(*attrdata), GFP_KERNEL);
+ if (!attrdata)
+ return -ENOMEM;
+
+ usb_autopm_get_interface(dev->intf);
+ result = usb_control_msg(
+ dev->udev,
+ usb_rcvctrlpipe(dev->udev, 0),
+ /* _u8 vendor specific request */
+ SWI_USB_REQUEST_GET_FW_ATTR,
+ USB_DIR_IN | USB_TYPE_VENDOR, /* __u8 request type */
+ 0x0000, /* __u16 value not used */
+ 0x0000, /* __u16 index not used */
+ attrdata, /* char *data */
+ sizeof(*attrdata), /* __u16 size */
+ USB_CTRL_SET_TIMEOUT); /* int timeout */
+ usb_autopm_put_interface(dev->intf);
+
+ if (result < 0) {
+ kfree(attrdata);
+ return -EIO;
+ }
+
+ *datap = *attrdata;
+
+ kfree(attrdata);
+ return result;
+}
+
+static int sierra_net_manage_power(struct usbnet *dev, int on)
+{
+ dev->intf->needs_remote_wakeup = on;
+ return 0;
+}
+
+/*
+ * collects the bulk endpoints, the status endpoint.
+ */
+static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ u8 ifacenum;
+ u8 numendpoints;
+ u16 fwattr = 0;
+ int status;
+ struct ethhdr *eth;
+ struct sierra_net_data *priv;
+ static const u8 sync_tmplate[sizeof(priv->sync_msg)] = {
+ 0x00, 0x00, SIERRA_NET_HIP_MSYNC_ID, 0x00};
+ static const u8 shdwn_tmplate[sizeof(priv->shdwn_msg)] = {
+ 0x00, 0x00, SIERRA_NET_HIP_SHUTD_ID, 0x00};
+
+ struct sierra_net_info_data *data =
+ (struct sierra_net_info_data *)dev->driver_info->data;
+
+ dev_dbg(&dev->udev->dev, "%s", __func__);
+
+ ifacenum = intf->cur_altsetting->desc.bInterfaceNumber;
+ /* We only accept certain interfaces */
+ if (!is_whitelisted(ifacenum, &data->whitelist)) {
+ dev_dbg(&dev->udev->dev, "Ignoring interface: %d", ifacenum);
+ return -ENODEV;
+ }
+ numendpoints = intf->cur_altsetting->desc.bNumEndpoints;
+ /* We have three endpoints, bulk in and out, and a status */
+ if (numendpoints != 3) {
+ dev_err(&dev->udev->dev, "Expected 3 endpoints, found: %d",
+ numendpoints);
+ return -ENODEV;
+ }
+ /* Status endpoint set in usbnet_get_endpoints() */
+ dev->status = NULL;
+ status = usbnet_get_endpoints(dev, intf);
+ if (status < 0) {
+ dev_err(&dev->udev->dev, "Error in usbnet_get_endpoints (%d)",
+ status);
+ return -ENODEV;
+ }
+ /* Initialize sierra private data */
+ priv = kzalloc(sizeof *priv, GFP_KERNEL);
+ if (!priv) {
+ dev_err(&dev->udev->dev, "No memory");
+ return -ENOMEM;
+ }
+
+ priv->usbnet = dev;
+ priv->ifnum = ifacenum;
+ /* override change_mtu with our own routine - need to bound check */
+ /* replace structure to our own structure where we have our own
+ * routine - need to bound check
+ */
+ dev->net->netdev_ops = &sierra_net_device_ops;
+
+ /* change MAC addr to include, ifacenum, and to be unique */
+ dev->net->dev_addr[ETH_ALEN-2] = atomic_inc_return(&iface_counter);
+ dev->net->dev_addr[ETH_ALEN-1] = ifacenum;
+
+ /* we will have to manufacture ethernet headers, prepare template */
+ eth = (struct ethhdr *)priv->ethr_hdr_tmpl;
+ memcpy(&eth->h_dest, dev->net->dev_addr, ETH_ALEN);
+ eth->h_proto = cpu_to_be16(ETH_P_IP);
+
+ /* prepare shutdown message template */
+ memcpy(priv->shdwn_msg, shdwn_tmplate, sizeof(priv->shdwn_msg));
+ /* set context index initially to 0 - prepares tx hdr template */
+ sierra_net_set_ctx_index(priv, 0);
+
+ /* decrease the rx_urb_size and max_tx_size to 4k on USB 1.1 */
+ dev->rx_urb_size = data->rx_urb_size;
+ if (dev->udev->speed != USB_SPEED_HIGH)
+ dev->rx_urb_size = min_t(size_t, 4096, data->rx_urb_size);
+
+ dev->net->hard_header_len += SIERRA_NET_HIP_EXT_HDR_LEN;
+ dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
+
+ /* Set up the netdev */
+ dev->net->flags |= IFF_NOARP;
+ dev->net->flags |= IFF_MULTICAST;
+ dev->net->ethtool_ops = &sierra_net_ethtool_ops;
+ netif_carrier_off(dev->net);
+
+ sierra_net_set_private(dev, priv);
+
+ priv->kevent_flags = 0;
+
+ /* Use the shared workqueue */
+ INIT_WORK(&priv->sierra_net_kevent, sierra_net_kevent);
+
+ /* Only need to do this once */
+ init_timer(&priv->sync_timer);
+ /* verify fw attributes */
+ status = sierra_net_get_fw_attr(dev, &fwattr);
+ dev_dbg(&dev->udev->dev, "Fw attr: %x\n", fwattr);
+ if (status == sizeof(fwattr) && (fwattr & SWI_GET_FW_ATTR_APM)) {
+/*******************************************************************************
+ * If you want the default /sys/bus/usb/devices/.../.../power/level to be forced
+ * to auto, the following needs to be compiled in.
+ */
+#ifdef POWER_LEVEL_AUTO
+ /* make power level default be 'auto' */
+ dev_dbg(&dev->udev->dev, "Enabling APM");
+ usb_enable_autosuspend(dev->udev);
+#endif
+ } else {
+ dev_info(&intf->dev, "Disabling APM - not supported");
+ usb_disable_autosuspend(dev->udev);
+ }
+ /* test whether firmware supports DHCP */
+ if (!(status == sizeof(fwattr) && (fwattr & SWI_GET_FW_ATTR_MASK))) {
+ /* found incompatible firmware version */
+ dev_err(&dev->udev->dev, "Incompatible driver and firmware"
+ " versions\n");
+ kfree(priv);
+ return -ENODEV;
+ }
+ /* prepare sync message from template */
+ memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg));
+
+ return 0;
+}
+
+static void sierra_net_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+ struct sierra_net_data *priv = sierra_net_get_private(dev);
+
+ dev_dbg(&dev->udev->dev, "%s", __func__);
+
+ sierra_net_set_private(dev, NULL);
+
+ kfree(priv);
+}
+
+static int sierra_net_open(struct usbnet *dev)
+{
+ dev_dbg(&dev->udev->dev, "%s", __func__);
+
+ /* initiate the sync sequence */
+ sierra_net_dosync(dev);
+
+ return 0;
+}
+
+static int sierra_net_stop(struct usbnet *dev)
+{
+ struct sierra_net_data *priv = sierra_net_get_private(dev);
+
+ dev_dbg(&dev->udev->dev, "%s", __func__);
+
+ /* Kill the timer then flush the work queue */
+ del_timer_sync(&priv->sync_timer);
+
+ cancel_work_sync(&priv->sierra_net_kevent);
+
+ /* tell modem we are going away */
+ sierra_net_send_shutdown(dev);
+
+ return 0;
+}
+
+static struct sk_buff *sierra_net_skb_clone(struct usbnet *dev,
+ struct sk_buff *skb, int len)
+{
+ struct sk_buff *new_skb;
+
+ /* clone skb */
+ new_skb = skb_clone(skb, GFP_ATOMIC);
+
+ /* remove len bytes from original */
+ skb_pull(skb, len);
+
+ /* trim next packet to it's length */
+ if (new_skb) {
+ skb_trim(new_skb, len);
+ } else {
+ if (netif_msg_rx_err(dev))
+ netdev_err(dev->net, "failed to get skb\n");
+ dev->net->stats.rx_dropped++;
+ }
+
+ return new_skb;
+}
+
+/* ---------------------------- Receive data path ----------------------*/
+static int sierra_net_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+ int err;
+ struct hip_hdr hh;
+ struct sk_buff *new_skb;
+ struct ethhdr *eth;
+ struct iphdr *ip;
+
+ dev_dbg(&dev->udev->dev, "%s", __func__);
+
+ sierra_net_printk_buf(skb->data, skb->len);
+
+ /* could contain multiple packets */
+ while (likely(skb->len)) {
+ err = parse_hip(skb->data, skb->len, &hh);
+ if (err) {
+ if (netif_msg_rx_err(dev))
+ netdev_err(dev->net, "Invalid HIP header %d\n",
+ err);
+ /* dev->net->stats.rx_errors incremented by caller */
+ dev->net->stats.rx_length_errors++;
+ return 0;
+ }
+
+ /* Validate Extended HIP header */
+ if (!hh.extmsgid.is_present
+ || hh.extmsgid.word != SIERRA_NET_HIP_EXT_IP_IN_ID) {
+ if (netif_msg_rx_err(dev))
+ netdev_err(dev->net, "HIP/ETH: Invalid pkt\n");
+
+ dev->net->stats.rx_frame_errors++;
+ /* dev->net->stats.rx_errors incremented by caller */;
+ return 0;
+ }
+
+ skb_pull(skb, hh.hdrlen);
+
+ /* We are going to accept this packet, prepare it */
+ memcpy(skb->data, sierra_net_get_private(dev)->ethr_hdr_tmpl,
+ ETH_HLEN);
+
+ ip = (struct iphdr *)((char *)skb->data + ETH_HLEN);
+ if(ip->version == 6) {
+ eth = (struct ethhdr *)skb->data;
+ eth->h_proto = cpu_to_be16(ETH_P_IPV6);
+ }
+
+ /* Last packet in batch handled by usbnet */
+ if (hh.payload_len.word == skb->len)
+ return 1;
+
+ new_skb = sierra_net_skb_clone(dev, skb, hh.payload_len.word);
+ if (new_skb)
+ usbnet_skb_return(dev, new_skb);
+
+ } /* while */
+
+ return 0;
+}
+
+/* ---------------------------- Transmit data path ----------------------*/
+struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+ gfp_t flags)
+{
+ struct sierra_net_data *priv = sierra_net_get_private(dev);
+ u16 len;
+ bool need_tail;
+
+ dev_dbg(&dev->udev->dev, "%s", __func__);
+ if (priv->link_up && check_ethip_packet(skb, dev) && is_ip(skb)) {
+ /* enough head room as is? */
+ if (SIERRA_NET_HIP_EXT_HDR_LEN <= skb_headroom(skb)) {
+ /* Save the Eth/IP length and set up HIP hdr */
+ len = skb->len;
+ skb_push(skb, SIERRA_NET_HIP_EXT_HDR_LEN);
+ /* Handle ZLP issue */
+ need_tail = ((len + SIERRA_NET_HIP_EXT_HDR_LEN)
+ % dev->maxpacket == 0);
+ if (need_tail) {
+ if (unlikely(skb_tailroom(skb) == 0)) {
+ netdev_err(dev->net, "tx_fixup:"
+ "no room for packet\n");
+ dev_kfree_skb_any(skb);
+ return NULL;
+ } else {
+ skb->data[skb->len] = 0;
+ __skb_put(skb, 1);
+ len = len + 1;
+ }
+ }
+ build_hip(skb->data, len, priv);
+
+ sierra_net_printk_buf(skb->data, skb->len);
+ return skb;
+ } else {
+ /*
+ * compensate in the future if necessary
+ */
+ netdev_err(dev->net, "tx_fixup: no room for HIP\n");
+ } /* headroom */
+ }
+
+ if (!priv->link_up)
+ dev->net->stats.tx_carrier_errors++;
+
+ /* tx_dropped incremented by usbnet */
+
+ /* filter the packet out, release it */
+ dev_kfree_skb_any(skb);
+ return NULL;
+}
+
+static int sierra_net_reset_resume(struct usb_interface *intf)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+ netdev_err(dev->net, "%s\n", __func__);
+ return usbnet_resume(intf);
+}
+
+static const u8 sierra_net_ifnum_list[] = { 7, 10, 11 };
+static const struct sierra_net_info_data sierra_net_info_data_direct_ip = {
+ /* .rx_urb_size = 8 * 1024, */
+ .rx_urb_size = SIERRA_NET_RX_URB_SZ,
+ .whitelist = {
+ .infolen = ARRAY_SIZE(sierra_net_ifnum_list),
+ .ifaceinfo = sierra_net_ifnum_list
+ }
+};
+
+static const struct driver_info sierra_net_info_direct_ip = {
+ .description = "Sierra Wireless USB-to-WWAN Modem",
+ .flags = FLAG_WWAN | FLAG_SEND_ZLP,
+ .bind = sierra_net_bind,
+ .unbind = sierra_net_unbind,
+ .status = sierra_net_status,
+ .rx_fixup = sierra_net_rx_fixup,
+ .tx_fixup = sierra_net_tx_fixup,
+ .manage_power = sierra_net_manage_power,
+ .stop = sierra_net_stop,
+ .check_connect = sierra_net_open,
+ .data = (unsigned long)&sierra_net_info_data_direct_ip,
+};
+
+static const struct usb_device_id products[] = {
+ {USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modem */
+ .driver_info = (unsigned long) &sierra_net_info_direct_ip},
+ {USB_DEVICE(0xF3D, 0x68A3), /* AT&T Direct IP modem */
+ .driver_info = (unsigned long) &sierra_net_info_direct_ip},
+ {USB_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */
+ .driver_info = (unsigned long) &sierra_net_info_direct_ip},
+ {USB_DEVICE(0xF3D, 0x68AA), /* AT&T Direct IP LTE modem */
+ .driver_info = (unsigned long) &sierra_net_info_direct_ip},
+
+ {}, /* last item */
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+/* We are based on usbnet, so let it handle the USB driver specifics */
+static struct usb_driver sierra_net_driver = {
+ .name = "sierra_net",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .disconnect = usbnet_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+ .reset_resume = sierra_net_reset_resume,
+ .no_dynamic_id = 1,
+ .supports_autosuspend = 1,
+};
+
+static int __init sierra_net_init(void)
+{
+ BUILD_BUG_ON(FIELD_SIZEOF(struct usbnet, data)
+ < sizeof(struct cdc_state));
+
+ return usb_register(&sierra_net_driver);
+}
+
+static void __exit sierra_net_exit(void)
+{
+ usb_deregister(&sierra_net_driver);
+}
+
+module_exit(sierra_net_exit);
+module_init(sierra_net_init);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/package/siit/Makefile b/package/siit/Makefile
new file mode 100644
index 000000000..4cd147f77
--- /dev/null
+++ b/package/siit/Makefile
@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2006-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=siit
+PKG_VERSION:=1.1
+PKG_RELEASE:=2
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/siit
+ SUBMENU:=Network Devices
+ TITLE:=Stateless IP ICMP Translation Algorithm
+ DEPENDS:= @(!(TARGET_ps3||TARGET_pxcab)||BROKEN)
+ FILES:=$(PKG_BUILD_DIR)/siit.ko
+ AUTOLOAD:=$(call AutoLoad,50,siit)
+endef
+
+include $(INCLUDE_DIR)/kernel-defaults.mk
+
+define KernelPackage/siit/description
+ Stateless IP ICMP Translation Algorithm
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ cp src/Makefile src/siit.h src/siit.c $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ $(MAKE) $(KERNEL_MAKEOPTS) SUBDIRS="$(PKG_BUILD_DIR)" modules
+endef
+
+$(eval $(call KernelPackage,siit))
diff --git a/package/siit/src/Makefile b/package/siit/src/Makefile
new file mode 100644
index 000000000..06c36f1e3
--- /dev/null
+++ b/package/siit/src/Makefile
@@ -0,0 +1,5 @@
+obj-m := siit.o
+ifeq ($(MAKING_MODULES),1)
+-include $(TOPDIR)/Rules.make
+endif
+
diff --git a/package/siit/src/siit.c b/package/siit/src/siit.c
new file mode 100644
index 000000000..5362c1daa
--- /dev/null
+++ b/package/siit/src/siit.c
@@ -0,0 +1,1478 @@
+/*
+ * siit.c: the Stateless IP/ICMP Translator (SIIT) module for Linux.
+ *
+ *
+ */
+
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
+#include <generated/autoconf.h>
+#else
+#include <linux/autoconf.h>
+#endif
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h> /* printk() */
+#include <linux/slab.h>
+
+#include <linux/errno.h> /* error codes */
+#include <linux/types.h> /* size_t */
+#include <linux/interrupt.h> /* mark_bh */
+#include <linux/random.h>
+#include <linux/in.h>
+#include <linux/netdevice.h> /* struct device, and other headers */
+#include <linux/etherdevice.h> /* eth_type_trans */
+#include <net/ip.h> /* struct iphdr */
+#include <net/icmp.h> /* struct icmphdr */
+#include <net/ipv6.h>
+#include <net/udp.h>
+#include <linux/skbuff.h>
+#include <linux/in6.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <asm/checksum.h>
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
+#include <net/ip6_checksum.h>
+#endif
+#include <linux/in6.h>
+#include "siit.h"
+
+MODULE_AUTHOR("Dmitriy Moscalev, Grigory Klyuchnikov, Felix Fietkau");
+
+/*
+ * If tos_ignore_flag != 0, we don't copy TOS and Traffic Class
+ * from origin paket and set it to 0
+ */
+int tos_ignore_flag = 0;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+static inline void
+skb_reset_mac_header(struct sk_buff *skb)
+{
+ skb->mac.raw=skb->data;
+}
+
+static struct net_device_stats *
+siit_get_stats(struct net_device *dev)
+{
+ return netdev_priv(dev);
+}
+
+static inline void random_ether_addr(u8 *addr)
+{
+ get_random_bytes (addr, ETH_ALEN);
+ addr [0] &= 0xfe; /* clear multicast bit */
+ addr [0] |= 0x02; /* set local assignment bit (IEEE802) */
+}
+
+
+#define siit_stats(_dev) ((struct net_device_stats *)netdev_priv(_dev))
+#else
+#define siit_stats(_dev) (&(_dev)->stats)
+#endif
+
+/*
+ * The Utility stuff
+ */
+
+#ifdef SIIT_DEBUG
+/* print dump bytes (data point data area sizeof len and message
+ * before dump.
+ */
+static int siit_print_dump(char *data, int len, char *message)
+{
+ int i;
+ int j = 0, k = 1;
+
+ len = len > BUFF_SIZE ? BUFF_SIZE : len;
+ printk("%s:\n", message);
+ for (i=0; i < len; i++, k++) {
+ if( i == len-1 || k == 16) {
+ printk("%02x\n", (~(~0 << 8) & *(data+i)));
+ j = 0;
+ k = 0;
+ }
+ else if (j) {
+ printk("%02x ", (~(~0 << 8) & *(data+i)));
+ j--;
+ }
+ else {
+ printk("%02x", (~(~0 << 8) & *(data+i)));
+ j++;
+ }
+ }
+ return 0;
+}
+#endif
+
+/*
+ * Open and close
+ */
+static int siit_open(struct net_device *dev)
+{
+ netif_start_queue(dev);
+ return 0;
+}
+
+
+static int siit_release(struct net_device *dev)
+{
+ netif_stop_queue(dev); /* can't transmit any more */
+ return 0;
+}
+
+/*
+ * Translation IPv4 to IPv6 stuff
+ *
+ * ip4_ip6 (src, len, dst, include_flag)
+ *
+ * where
+ * src - buffer with original IPv4 packet,
+ * len - size of original packet,
+ * dst - new buffer for IPv6 packet,
+ * include_flag - if = 1, dst point to IPv4 packet that is ICMP error
+ * included IP packet, else = 0
+ */
+
+static int ip4_ip6(char *src, int len, char *dst, int include_flag)
+{
+ struct iphdr *ih4 = (struct iphdr *) src; /* point to current IPv4 header struct */
+ struct icmphdr *icmp_hdr; /* point to current ICMPv4 header struct */
+ struct udphdr *udp_hdr; /* point to current IPv4 UDP header struct */
+
+ struct ipv6hdr *ih6 = (struct ipv6hdr *) dst; /* point to current IPv6 header struct */
+ struct frag_hdr *ih6_frag = (struct frag_hdr *)(dst+sizeof(struct ipv6hdr));
+ /* point to current IPv6 fragment header struct */
+ struct icmp6hdr *icmp6_hdr; /* point to current ICMPv6 header */
+
+ int hdr_len = (int)(ih4->ihl * 4); /* IPv4 header length */
+ int icmp_len; /* ICMPv4 packet length */
+ int plen; /* payload length */
+
+ unsigned int csum; /* need to calculate ICMPv6 and UDP checksum */
+ int fl_csum = 0; /* flag to calculate UDP checksum */
+ int icmperr = 1; /* flag to indicate ICMP error message and to need
+ translate ICMP included IP packet */
+ int fr_flag = 0; /* fragment flag, if = 0 - don't add
+ fragment header */
+ __u16 new_tot_len; /* need to calculate IPv6 total length */
+ __u8 new_nexthdr; /* next header code */
+ __u16 icmp_ptr = 0; /* Pointer field in ICMP_PARAMETERPROB */
+
+#ifdef SIIT_DEBUG /* print IPv4 header dump */
+ siit_print_dump(src, hdr_len, "siit: ip4_ip6() (in) ip4 header dump");
+#endif
+
+ /* If DF == 1 && MF == 0 && Fragment Offset == 0
+ * or this packet is ICMP included IP packet
+ * we don't need fragment header */
+ if (ntohs(ih4->frag_off) == IP_DF || include_flag ) {
+ /* not fragment and we need not to add Fragment
+ * Header to IPv6 packet. */
+ /* total length = total length from IPv4 packet */
+ new_tot_len = ntohs(ih4->tot_len);
+
+ if (ih4->protocol == IPPROTO_ICMP)
+ new_nexthdr = NEXTHDR_ICMP;
+ else
+ new_nexthdr = ih4->protocol;
+ }
+ else {
+ /* need to add Fragment Header */
+ fr_flag = 1;
+ /* total length = total length from IPv4 packet +
+ length of Fragment Header */
+ new_tot_len = ntohs(ih4->tot_len) + sizeof(struct frag_hdr);
+ /* IPv6 Header NextHeader = NEXTHDR_FRAGMENT */
+ new_nexthdr = NEXTHDR_FRAGMENT;
+ /* Fragment Header NextHeader copy from IPv4 packet */
+ if (ih4->protocol == IPPROTO_ICMP)
+ ih6_frag->nexthdr = NEXTHDR_ICMP;
+ else
+ ih6_frag->nexthdr = ih4->protocol;
+
+ /* copy frag offset from IPv4 packet */
+ ih6_frag->frag_off = htons((ntohs(ih4->frag_off) & IP_OFFSET) << 3);
+ /* copy MF flag from IPv4 packet */
+ ih6_frag->frag_off = htons((ntohs(ih6_frag->frag_off) |
+ ((ntohs(ih4->frag_off) & IP_MF) >> 13)));
+ /* copy Identification field from IPv4 packet */
+ ih6_frag->identification = htonl(ntohs(ih4->id));
+ /* reserved field initialized to zero */
+ ih6_frag->reserved = 0;
+ }
+
+ /* Form rest IPv6 fields */
+
+ /*
+ * At this point we need to add checking of unxpired source
+ * route optin and if it is, send ICMPv4 "destination
+ * unreacheble/source route failes" Type 3/Code 5 and
+ * drop packet. (NOT RELEASED YET)
+ */
+
+ /* IP version = 6 */
+ ih6->version = 6;
+
+ if (tos_ignore_flag) {
+ ih6->priority = 0;
+ ih6->flow_lbl[0] = 0;
+ } else {
+ ih6->priority = (ih4->tos & 0xf0) >> 4;
+ ih6->flow_lbl[0] = (ih4->tos & 0x0f) << 4;
+ }
+ ih6->flow_lbl[1] = 0;
+ ih6->flow_lbl[2] = 0;
+
+ /* Hop Limit = IPv4 TTL */
+ ih6->hop_limit = ih4->ttl;
+
+ /* Translate source destination addresses,
+ for IPv6 host it's IPv4-translated IPv6 address,
+ for IPv4 host it's IPv4-mapped IPv6 address
+
+ !!WARNING!! Instead IPv4-mapped IPv6 addresses we use addreesses
+ with unused prefix ::ffff:ffff:0:0/96, because KAME implementation
+ doesn't support IPv4-mapped addresses in IPv6 packets and discard them.
+
+ */
+
+ if (include_flag) {
+ /*
+ It's ICMP included IP packet and there is a diffirence
+ in src/dst addresses then src/dst in normal direction
+ */
+
+ /*
+ Source address
+ is IPv4-translated IPv6 address because packet traveled
+ from IPv6 to IPv4 area
+ */
+ ih6->saddr.in6_u.u6_addr32[0] = 0;
+ ih6->saddr.in6_u.u6_addr32[1] = 0;
+ ih6->saddr.in6_u.u6_addr32[2] = htonl(TRANSLATED_PREFIX); /* to network order bytes */
+ ih6->saddr.in6_u.u6_addr32[3] = ih4->saddr;
+
+ /*
+ Destination address
+ is IPv4-mapped address (but it's not IPv4- mapped, we use
+ prefix ::ffff:ffff:0:0/96
+ */
+ ih6->daddr.in6_u.u6_addr32[0] = 0;
+ ih6->daddr.in6_u.u6_addr32[1] = 0;
+ ih6->daddr.in6_u.u6_addr32[2] = htonl(MAPPED_PREFIX); /* to network order bytes */
+ ih6->daddr.in6_u.u6_addr32[3] = ih4->daddr;
+ }
+ else {
+
+ /*
+ This is normal case (packet isn't included IP packet)
+
+ Source address
+ is IPv4-mapped address (but it's not IPv4- mapped, we use
+ prefix ::ffff:ffff:0:0/96)
+ */
+ ih6->saddr.in6_u.u6_addr32[0] = 0;
+ ih6->saddr.in6_u.u6_addr32[1] = 0;
+ ih6->saddr.in6_u.u6_addr32[2] = htonl(MAPPED_PREFIX); /* to network order bytes */
+ ih6->saddr.in6_u.u6_addr32[3] = ih4->saddr;
+
+ /* Destination address
+ is is IPv4-translated IPv6 address
+ */
+ ih6->daddr.in6_u.u6_addr32[0] = 0;
+ ih6->daddr.in6_u.u6_addr32[1] = 0;
+ ih6->daddr.in6_u.u6_addr32[2] = htonl(TRANSLATED_PREFIX); /* to network order bytes */
+ ih6->daddr.in6_u.u6_addr32[3] = ih4->daddr;
+ }
+
+ /* Payload Length */
+ plen = new_tot_len - hdr_len; /* Payload length = IPv4 total len - IPv4 header len */
+ ih6->payload_len = htons(plen);
+
+ /* Next Header */
+ ih6->nexthdr = new_nexthdr; /* Next Header */
+
+ /* Process ICMP protocols data */
+
+ switch (ih4->protocol) {
+ case IPPROTO_ICMP:
+ if ( (ntohs(ih4->frag_off) & IP_OFFSET) != 0 || (ntohs(ih4->frag_off) & IP_MF) != 0 ) {
+ PDEBUG("ip4_ip6(): don't translate ICMPv4 fragments - packet dropped.\n");
+ return -1;
+ }
+
+ icmp_hdr = (struct icmphdr *) (src+hdr_len); /* point to ICMPv4 header */
+ csum = 0;
+ icmp_len = ntohs(ih4->tot_len) - hdr_len; /* ICMPv4 packet length */
+ icmp6_hdr = (struct icmp6hdr *)(dst+sizeof(struct ipv6hdr)
+ +fr_flag*sizeof(struct frag_hdr)); /* point to ICMPv6 header */
+
+ if (include_flag) {
+ /* ICMPv4 packet cannot be included in ICMPv4 Error message */
+ /* !!! May be it's WRONG !!! ICMPv4 QUERY packet can be included
+ in ICMPv4 Error message */
+ PDEBUG("ip4_ip6(): It's included ICMPv4 in ICMPv4 Error message - packet dropped.\n");
+ return -1;
+ }
+
+ /* Check ICMPv4 Type field */
+ switch (icmp_hdr->type) {
+ /* ICMP Error messages */
+ /* Destination Unreachable (Type 3) */
+ case ICMP_DEST_UNREACH:
+ icmp6_hdr->icmp6_type = ICMPV6_DEST_UNREACH; /* to Type 1 */
+ icmp6_hdr->icmp6_unused = 0;
+ switch (icmp_hdr->code)
+ {
+ case ICMP_NET_UNREACH: /* Code 0 */
+ case ICMP_HOST_UNREACH: /* Code 1 */
+ case ICMP_SR_FAILED: /* Code 5 */
+ case ICMP_NET_UNKNOWN: /* Code 6 */
+ case ICMP_HOST_UNKNOWN: /* Code 7 */
+ case ICMP_HOST_ISOLATED: /* Code 8 */
+ case ICMP_NET_UNR_TOS: /* Code 11 */
+ case ICMP_HOST_UNR_TOS: /* Code 12 */
+ icmp6_hdr->icmp6_code = ICMPV6_NOROUTE; /* to Code 0 */
+ break;
+ case ICMP_PROT_UNREACH: /* Code 2 */
+ icmp6_hdr->icmp6_type = ICMPV6_PARAMPROB; /* to Type 4 */
+ icmp6_hdr->icmp6_code = ICMPV6_UNK_NEXTHDR; /* to Code 1 */
+ /* Set pointer filed to 6, it's octet offset IPv6 Next Header field */
+ icmp6_hdr->icmp6_pointer = htonl(6);
+ break;
+ case ICMP_PORT_UNREACH: /* Code 3 */
+ icmp6_hdr->icmp6_code = ICMPV6_PORT_UNREACH; /* to Code 4 */
+ break;
+ case ICMP_FRAG_NEEDED: /* Code 4 */
+ icmp6_hdr->icmp6_type = ICMPV6_PKT_TOOBIG; /* to Type 2 */
+ icmp6_hdr->icmp6_code = 0;
+ /* Correct MTU */
+ if (icmp_hdr->un.frag.mtu == 0)
+ /* we use minimum MTU for IPv4 PMTUv4 RFC1191, section 5;
+ IPv6 implementation wouldn't accept Path MTU < 1280,
+ but it records info correctly to always include
+ a fragment header */
+ icmp6_hdr->icmp6_mtu = htonl(576);
+ else
+ /* needs to adjusted for difference between IPv4/IPv6 headers
+ * SIIT RFC2765, section 3.3,
+ * we assume that difference is 20 bytes */
+ icmp6_hdr->icmp6_mtu = htonl(ntohs(icmp_hdr->un.frag.mtu)+IP4_IP6_HDR_DIFF);
+
+ break;
+ case ICMP_NET_ANO: /* Code 9 */
+ case ICMP_HOST_ANO: /* Code 10 */
+ icmp6_hdr->icmp6_code = ICMPV6_ADM_PROHIBITED; /* to Code 1 */
+ break;
+ default: /* discard any other Code */
+ PDEBUG("ip4_ip6(): Unknown ICMPv4 Type %d Code %d - packet dropped.\n",
+ ICMP_DEST_UNREACH, icmp_hdr->code);
+ return -1;
+ }
+ break;
+ /* Time Exceeded (Type 11) */
+ case ICMP_TIME_EXCEEDED:
+ icmp6_hdr->icmp6_type = ICMPV6_TIME_EXCEED;
+ icmp6_hdr->icmp6_code = icmp_hdr->code;
+ break;
+ /* Parameter Problem (Type 12) */
+ case ICMP_PARAMETERPROB:
+ icmp6_hdr->icmp6_type = ICMPV6_PARAMPROB;
+ icmp6_hdr->icmp6_code = icmp_hdr->code;
+
+ icmp_ptr = ntohs(icmp_hdr->un.echo.id) >> 8;
+ switch (icmp_ptr) {
+ case 0:
+ icmp6_hdr->icmp6_pointer = 0; /* IPv4 Version -> IPv6 Version */
+ break;
+ case 2:
+ icmp6_hdr->icmp6_pointer = __constant_htonl(4); /* IPv4 length -> IPv6 Payload Length */
+ break;
+ case 8:
+ icmp6_hdr->icmp6_pointer = __constant_htonl(7); /* IPv4 TTL -> IPv6 Hop Limit */
+ break;
+ case 9:
+ icmp6_hdr->icmp6_pointer = __constant_htonl(6); /* IPv4 Protocol -> IPv6 Next Header */
+ break;
+ case 12:
+ icmp6_hdr->icmp6_pointer = __constant_htonl(8); /* IPv4 Src Addr -> IPv6 Src Addr */
+ break;
+ case 16:
+ icmp6_hdr->icmp6_pointer = __constant_htonl(24); /* IPv4 Dst Addr -> IPv6 Dst Addr */
+ break;
+ default:
+ icmp6_hdr->icmp6_pointer = 0xffffffff; /* set to all ones in any other cases */
+ break;
+ }
+ break;
+ case ICMP_ECHO:
+ icmperr = 0;
+ icmp6_hdr->icmp6_type = ICMPV6_ECHO_REQUEST;
+ icmp6_hdr->icmp6_code = 0;
+ /* Copy rest ICMP data to new IPv6 packet without changing */
+ memcpy(((char *)icmp6_hdr)+4, ((char *)icmp_hdr)+4, len - hdr_len - 4);
+ break;
+
+ case ICMP_ECHOREPLY:
+ icmperr = 0;
+ icmp6_hdr->icmp6_type = ICMPV6_ECHO_REPLY;
+ icmp6_hdr->icmp6_code = 0;
+ /* Copy rest ICMP data to new IPv6 packet without changing */
+ memcpy(((char *)icmp6_hdr)+4, ((char *)icmp_hdr)+4, len - hdr_len - 4);
+ break;
+
+ /* Discard any other ICMP messages */
+ default:
+ PDEBUG("ip4_ip6(): Unknown ICMPv4 packet Type %x - packet dropped.\n", icmp_hdr->type);
+ return -1;
+ }
+
+ /* Now if it's ICMPv4 Error message we must translate included IP packet */
+
+ if (icmperr) {
+ /* Call our ip4_ip6() to translate included IP packet */
+ if (ip4_ip6(src+hdr_len+sizeof(struct icmphdr), len - hdr_len - sizeof(struct icmphdr),
+ dst+sizeof(struct ipv6hdr)+fr_flag*sizeof(struct frag_hdr)
+ +sizeof(struct icmp6hdr), 1) == -1) {
+ PDEBUG("ip4_ip6(): Uncorrect translation of ICMPv4 Error message - packet dropped.\n");
+ return -1;
+ }
+ /* correct ICMPv6 packet length for diffirence between IPv4 and IPv6 headers
+ in included IP packet
+ */
+ icmp_len += 20;
+ /* and correct Payload length for diffirence between IPv4 and IPv6 headers */
+ plen += 20;
+ ih6->payload_len = htons(plen);
+ }
+
+ /* Calculate ICMPv6 checksum */
+
+ icmp6_hdr->icmp6_cksum = 0;
+ csum = 0;
+
+ csum = csum_partial((u_char *)icmp6_hdr, icmp_len, csum);
+ icmp6_hdr->icmp6_cksum = csum_ipv6_magic(&ih6->saddr, &ih6->daddr, icmp_len,
+ IPPROTO_ICMPV6, csum);
+ break;
+
+ /* Process TCP protocols data */
+ case IPPROTO_TCP:
+ /* Copy TCP data to new IPv6 packet without changing */
+ memcpy(dst+sizeof(struct ipv6hdr)+fr_flag*sizeof(struct frag_hdr),
+ src+hdr_len, len - hdr_len);
+ break;
+
+ /* Process UDP protocols data */
+ case IPPROTO_UDP:
+ udp_hdr = (struct udphdr *)(src+hdr_len);
+ if ((ntohs(ih4->frag_off) & IP_OFFSET) == 0) {
+ if ((ntohs(ih4->frag_off) & IP_MF) != 0) {
+ /* It's a first fragment */
+ if (udp_hdr->check == 0) {
+ /* System management event */
+ printk("siit: First fragment of UDP with zero checksum - packet droped\n");
+ printk("siit: addr: %x src port: %d dst port: %d\n",
+ htonl(ih4->saddr), htons(udp_hdr->source), htons(udp_hdr->dest));
+ return -1;
+ }
+ }
+ else if (udp_hdr->check == 0)
+ fl_csum = 1;
+ }
+
+ /* Copy UDP data to new IPv6 packet */
+ udp_hdr = (struct udphdr *)(dst+sizeof(struct ipv6hdr)
+ + fr_flag*sizeof(struct frag_hdr));
+ memcpy((char *)udp_hdr, src+hdr_len, len - hdr_len);
+
+ /* Calculate UDP checksum if UDP checksum in IPv4 packet was ZERO
+ and if it isn't included IP packet
+ */
+ if (fl_csum && (!include_flag)) {
+ udp_hdr->check = 0;
+ csum = 0;
+ csum = csum_partial((unsigned char *)udp_hdr, plen - fr_flag*sizeof(struct frag_hdr), csum);
+ udp_hdr->check = csum_ipv6_magic(&ih6->saddr, &ih6->daddr, plen -
+ fr_flag*sizeof(struct frag_hdr), IPPROTO_UDP, csum);
+ }
+ break;
+
+ /* Discard packets with any other protocol */
+ default:
+ PDEBUG("ip4_ip6(): Unknown upper protocol - packet dropped.\n");
+ return -1;
+ }
+
+#ifdef SIIT_DEBUG
+ siit_print_dump(dst, sizeof(struct ipv6hdr), "siit: ip4_ip6(): (out) ipv6 header dump");
+#endif
+
+ return 0;
+}
+
+/*
+ * Translation IPv6 to IPv4 stuff
+ *
+ * ip6_ip4(src, len, dst, include_flag)
+ *
+ * where
+ * src - buffer with original IPv6 packet,
+ * len - size of original packet,
+ * dst - new buffer for IPv4 packet,
+ * include_flag - if = 1, dst point to IPv6 packet that is ICMP error
+ * included IP packet, else = 0
+ *
+ */
+
+static int ip6_ip4(char *src, int len, char *dst, int include_flag)
+{
+ struct ipv6hdr *ip6_hdr; /* point to current IPv6 header struct */
+ struct iphdr *ip_hdr; /* point to current IPv4 header struct */
+ int opts_len = 0; /* to sum Option Headers length */
+ int icmperr = 1; /* if = 1, indicate that packet is ICMP Error message, else = 0 */
+ int ntot_len = 0; /* to calculate IPv6 Total Length field */
+ int real_len;
+ int len_delta;
+ int ip6_payload_len;
+ int inc_opts_len = 0; /* to sum Option Headers length in ICMP included IP packet */
+ __u8 next_hdr; /* Next Header */
+
+#ifdef SIIT_DEBUG
+ siit_print_dump(src, sizeof(struct ipv6hdr), "siit: ip6_ip4(): (in) ipv6 header dump");
+#endif
+
+ if ( (len_delta = len - sizeof(struct ipv6hdr)) >= 0)
+ {
+ ip6_hdr = (struct ipv6hdr *)src;
+ ip_hdr = (struct iphdr *)dst;
+
+ real_len = sizeof(struct iphdr);
+
+ /* Check validation of Saddr & Daddr? is a packet to fall under our translation? */
+ if (include_flag) { /* It's ICMP included IP packet,
+ about process include_flag see comment in ip4_ip6() */
+ if (ip6_hdr->saddr.s6_addr32[2] != htonl(MAPPED_PREFIX)) {
+ PDEBUG("ip6_ip4(): Included IP packet Src addr isn't mapped addr: %x%x%x%x, packet dropped.\n",
+ ip6_hdr->saddr.s6_addr32[0], ip6_hdr->saddr.s6_addr32[1],
+ ip6_hdr->saddr.s6_addr32[2], ip6_hdr->saddr.s6_addr32[3]);
+ return -1;
+ }
+ if ( ip6_hdr->daddr.s6_addr32[2] != htonl(TRANSLATED_PREFIX)) {
+ PDEBUG("ip6_ip4(): Included IP packet Dst addr isn't translated addr: %x%x%x%x, packet dropped.\n",
+ ip6_hdr->daddr.s6_addr32[0], ip6_hdr->daddr.s6_addr32[1],
+ ip6_hdr->daddr.s6_addr32[2], ip6_hdr->daddr.s6_addr32[3]);
+ return -1;
+ }
+ }
+ else { /* It's normal IP packet (not included in ICMP) */
+ if (ip6_hdr->saddr.s6_addr32[2] != htonl(TRANSLATED_PREFIX)) {
+ PDEBUG("ip6_ip4(): Src addr isn't translated addr: %x%x%x%x, packet dropped.\n",
+ ip6_hdr->saddr.s6_addr32[0], ip6_hdr->saddr.s6_addr32[1],
+ ip6_hdr->saddr.s6_addr32[2], ip6_hdr->saddr.s6_addr32[3]);
+ return -1;
+ }
+ if ( ip6_hdr->daddr.s6_addr32[2] != htonl(MAPPED_PREFIX)) {
+ PDEBUG("ip6_ip4(): Dst addr isn't mapped addr: %x%x%x%x, packet dropped.\n",
+ ip6_hdr->daddr.s6_addr32[0], ip6_hdr->daddr.s6_addr32[1],
+ ip6_hdr->daddr.s6_addr32[2], ip6_hdr->daddr.s6_addr32[3]);
+ return -1;
+ }
+ }
+
+ /* Set IPv4 Fragment Offset and ID to 0
+ before process any Option Headers */
+ ip_hdr->frag_off = 0;
+ ip_hdr->id = 0;
+
+ /*
+ * We process only Fragment Header. Any other options headers
+ * are ignored, i.e. there is no attempt to translate them.
+ * However, the Total Length field and the Protocol field would
+ * have to be adjusted to "skip" these extension headers.
+ */
+
+ next_hdr = ip6_hdr->nexthdr;
+
+ /* Hop_by_Hop options header (ip6_hdr->nexthdr = 0). It must
+ * appear only in IPv6 header's Next Header field.
+ */
+ if (next_hdr == NEXTHDR_HOP) {
+ if ( (len_delta - sizeof(struct ipv6_opt_hdr)) >= 0)
+ {
+ struct ipv6_opt_hdr *ip6h =
+ (struct ipv6_opt_hdr *)(src+sizeof(struct ipv6hdr) + opts_len);
+ if ( (len_delta -= ip6h->hdrlen*8 + 8) >= 0)
+ {
+ opts_len += ip6h->hdrlen*8 + 8; /* See RFC 2460 page 11:
+ Hdr Ext Len 8-bit unsigned integer. Length of the Hop-by-
+ Hop Options header in 8-octet units, not
+ including the first 8 octets.
+ */
+ next_hdr = ip6h->nexthdr;
+ }
+ else
+ {
+ PDEBUG("ip6_ip4(): hop_by_hop header error, packet droped");
+ /* Generate ICMP Parameter Problem */
+ return -1;
+ }
+ }
+ }
+
+ if (len_delta > 0)
+ {
+ while(next_hdr != NEXTHDR_ICMP && next_hdr != NEXTHDR_TCP
+ && next_hdr != NEXTHDR_UDP)
+ {
+ /* Destination options header */
+ if (next_hdr == NEXTHDR_DEST)
+ {
+ if ( (len_delta - sizeof(struct ipv6_opt_hdr)) >= 0)
+ {
+ struct ipv6_opt_hdr *ip6d =
+ (struct ipv6_opt_hdr *)(src + sizeof(struct ipv6hdr) + opts_len);
+ if ( (len_delta -= ip6d->hdrlen*8 + 8) >= 0)
+ {
+ opts_len += ip6d->hdrlen*8 + 8;
+ next_hdr = ip6d->nexthdr;
+ }
+ }
+ else
+ {
+ PDEBUG("ip6_ip4(): destination header error, packet droped");
+ /* Generate ICMP Parameter Problem */
+ return -1;
+ }
+ }
+ /* Routing options header */
+ else if (next_hdr == NEXTHDR_ROUTING)
+ {
+ if ( (len_delta - sizeof(struct ipv6_rt_hdr)) >= 0)
+ {
+ struct ipv6_rt_hdr *ip6rt =
+ (struct ipv6_rt_hdr *)(src+sizeof(struct ipv6hdr) + opts_len);
+ /* RFC 2765 SIIT, 4.1:
+ If a routing header with a non-zero Segments Left field is present
+ then the packet MUST NOT be translated, and an ICMPv6 "parameter
+ problem/ erroneous header field encountered" (Type 4/Code 0) error
+ message, with the Pointer field indicating the first byte of the
+ Segments Left field, SHOULD be returned to the sender.
+ */
+ if (ip6rt->segments_left != 0) {
+ /* Build ICMPv6 "Parameter Problem/Erroneous Header
+ Field Encountered" & drop the packet */
+ /* !!! We don't send ICMPv6 "Parameter Problem" !!! */
+ PDEBUG("ip6_ip4(): routing header type != 0\n");
+ return -1;
+ }
+ if ( (len_delta -= ip6rt->hdrlen*8 + 8) >= 0)
+ {
+ opts_len += ip6rt->hdrlen*8 + 8;
+ next_hdr = ip6rt->nexthdr;
+ }
+ else
+ {
+ PDEBUG("ip6_ip4(): routing header error, packet droped");
+ /* Generate ICMP Parameter Problem */
+ return -1;
+ }
+ }
+ }
+ /* Fragment options header */
+ else if (next_hdr == NEXTHDR_FRAGMENT)
+ {
+ if ( (len_delta -= sizeof(struct frag_hdr)) >= 0)
+ {
+ struct frag_hdr *ip6f =
+ (struct frag_hdr *)(src+sizeof(struct ipv6hdr)+opts_len);
+
+ opts_len += sizeof(struct frag_hdr); /* Frag Header Length = 8 */
+ ip_hdr->id = htons(ntohl(ip6f->identification)); /* ID field */
+ ip_hdr->frag_off = htons((ntohs(ip6f->frag_off) & IP6F_OFF_MASK) >> 3);
+ /* fragment offset */
+ ip_hdr->frag_off = htons(ntohs(ip_hdr->frag_off) |
+ ((ntohs(ip6f->frag_off) & IP6F_MORE_FRAG) << 13));
+ /* more fragments flag */
+ next_hdr = ip6f->nexthdr;
+ }
+ else
+ {
+ PDEBUG("ip6_ip4(): fragment header error, packet droped");
+ /* Generate ICMP Parameter Problem */
+ return -1;
+ }
+ }
+ /* No Next Header */
+ else if (next_hdr == NEXTHDR_NONE)
+ {
+ /* RFC 2460 IPv6 Specification, 4.7
+ 4.7 No Next Header
+
+ The value 59 in the Next Header field of an IPv6 header or any
+ extension header indicates that there is nothing following that
+ header. If the Payload Length field of the IPv6 header indicates the
+ presence of octets past the end of a header whose Next Header field
+ contains 59, those octets must be ignored, and passed on unchanged if
+ the packet is forwarded.
+ */
+ break;
+ }
+ else if (next_hdr == NEXTHDR_ESP || next_hdr == NEXTHDR_AUTH)
+ {
+ PDEBUG("ip6_ip4(): cannot translate AUTH or ESP extention header, packet dropped\n");
+ return -1;
+ }
+ else if (next_hdr == NEXTHDR_IPV6)
+ {
+ PDEBUG("ip6_ip4(): cannot translate IPv6-IPv6 packet, packet dropped\n");
+ return -1;
+ }
+ else if (next_hdr == 0)
+ {
+ /* As say RFC 2460 (IPv6 Spec) we should discard the packet and send an
+ ICMP Parameter Problem message to the source of the packet, with an
+ ICMP Code value of 1 ("unrecognized Next Header type encountered")
+ and the ICMP Pointer field containing the offset of the unrecognized
+ value within the original packet
+ */
+ /* NOT IMPLEMENTED */
+ PDEBUG("ip6_ip4(): NEXTHDR in extention header = 0, packet dropped\n");
+ return -1;
+ }
+ else
+ {
+ PDEBUG("ip6_ip4(): cannot translate extention header = %d, packet dropped\n", next_hdr);
+ return -1;
+ }
+ }
+ }
+ }
+ else
+ {
+ PDEBUG("ip6_ip4(): error packet len, packet dropped.\n");
+ return -1;
+ }
+
+ /* Building ipv4 packet */
+
+ ip_hdr->version = IPVERSION;
+ ip_hdr->ihl = 5;
+
+ /* TOS see comment about TOS in ip4_ip6() */
+ if (tos_ignore_flag)
+ ip_hdr->tos = 0;
+ else {
+ ip_hdr->tos = ip6_hdr->priority << 4;
+ ip_hdr->tos = ip_hdr->tos | (ip6_hdr->flow_lbl[0] >> 4);
+ }
+
+ /* IPv4 Total Len = IPv6 Payload Len +
+ IPv4 Header Len (without options) - Options Headers Len */
+ ip6_payload_len = ntohs(ip6_hdr->payload_len);
+
+ if (ip6_payload_len == 0)
+ ntot_len = 0;
+ else
+ ntot_len = ip6_payload_len + IP4_IP6_HDR_DIFF - opts_len;
+
+ ip_hdr->tot_len = htons(ntot_len);
+
+ /* IPv4 TTL = IPv6 Hop Limit */
+ ip_hdr->ttl = ip6_hdr->hop_limit;
+
+ /* IPv4 Protocol = Next Header that will point to upper layer protocol */
+ ip_hdr->protocol = next_hdr;
+
+ /* IPv4 Src addr = last 4 bytes from IPv6 Src addr */
+ ip_hdr->saddr = ip6_hdr->saddr.s6_addr32[3];
+ /* IPv4 Dst addr = last 4 bytes from IPv6 Dst addr */
+ ip_hdr->daddr = ip6_hdr->daddr.s6_addr32[3];
+
+ /* Calculate IPv4 header checksum */
+ ip_hdr->check = 0;
+ ip_hdr->check = ip_fast_csum((unsigned char *)ip_hdr, ip_hdr->ihl);
+
+ if (len_delta > 0)
+ {
+ /* PROCESS ICMP */
+
+ if (next_hdr == NEXTHDR_ICMP)
+ {
+ struct icmp6hdr *icmp6_hdr;
+ struct icmphdr *icmp_hdr;
+
+ if ((len_delta -= sizeof(struct icmp6hdr)) >= 0)
+ {
+ icmp6_hdr = (struct icmp6hdr *)(src + sizeof(struct ipv6hdr) + opts_len);
+ icmp_hdr = (struct icmphdr *)(dst + sizeof(struct iphdr));
+
+ real_len += len_delta + sizeof(struct icmphdr);
+
+ /* There is diffirent between ICMPv4/ICMPv6 protocol codes
+ IPPROTO_ICMP = 1
+ IPPROTO_ICMPV6 = 58 */
+ ip_hdr->protocol = IPPROTO_ICMP;
+
+ if (include_flag) {
+ /* !!! Warnig !!! We discard ICMP packets with any ICMP as included
+ in ICMP Error. But ICMP Error messages can include ICMP Query message
+ */
+ if (icmp6_hdr->icmp6_type != ICMPV6_ECHO_REQUEST)
+ {
+ PDEBUG("ip6_ip4(): included ICMPv6 in ICMPv6 Error message, packet dropped\n");
+ return -1;
+ }
+ }
+
+ /* Translate ICMPv6 to ICMPv4 */
+ switch (icmp6_hdr->icmp6_type)
+ {
+/* ICMP Error messages */
+ /* Destination Unreachable (Type 1) */
+ case ICMPV6_DEST_UNREACH: /* Type 1 */
+ icmp_hdr->type = ICMP_DEST_UNREACH; /* to Type 3 */
+ icmp_hdr->un.echo.id = 0;
+ icmp_hdr->un.echo.sequence = 0;
+ switch (icmp6_hdr->icmp6_code)
+ {
+ case ICMPV6_NOROUTE: /* Code 0 */
+ case ICMPV6_NOT_NEIGHBOUR: /* Code 2 */
+ case ICMPV6_ADDR_UNREACH: /* Code 3 */
+ icmp_hdr->code = ICMP_HOST_UNREACH; /* To Code 1 */
+ break;
+ case ICMPV6_ADM_PROHIBITED: /* Code 1 */
+ icmp_hdr->code = ICMP_HOST_ANO; /* To Code 10 */
+ break;
+ case ICMPV6_PORT_UNREACH: /* Code 4 */
+ icmp_hdr->code = ICMP_PORT_UNREACH; /* To Code 3 */
+
+ break;
+ default: /* discard any other codes */
+ PDEBUG("ip6_ip4(): Unknown ICMPv6 Type %d Code %d - packet dropped.\n",
+ ICMPV6_DEST_UNREACH, icmp6_hdr->icmp6_code);
+ return -1;
+ }
+ break;
+ /* Packet Too Big (Type 2) */
+ case ICMPV6_PKT_TOOBIG: /* Type 2 */
+ icmp_hdr->type = ICMP_DEST_UNREACH; /* to Type 3 */
+ icmp_hdr->code = ICMP_FRAG_NEEDED; /* to Code 4 */
+ /* Change MTU, RFC 2765 (SIIT), 4.2:
+ The MTU field needs to be adjusted for the difference between
+ the IPv4 and IPv6 header sizes taking into account whether or
+ not the packet in error includes a Fragment header.
+ */
+ /* !!! Don't implement !!! */
+ icmp_hdr->un.frag.mtu = (__u16) icmp6_hdr->icmp6_mtu;
+ break;
+ /* Time Exceeded (Type 3) */
+ case ICMPV6_TIME_EXCEED:
+ icmp_hdr->type = ICMP_TIME_EXCEEDED; /* to Type 11 */
+ icmp_hdr->code = icmp6_hdr->icmp6_code; /* Code unchanged */
+ break;
+ /* Parameter Problem (Type 4) */
+ case ICMPV6_PARAMPROB:
+ switch (icmp6_hdr->icmp6_code) {
+ case ICMPV6_UNK_NEXTHDR: /* Code 1 */
+ icmp_hdr->type = ICMP_DEST_UNREACH; /* to Type 3 */
+ icmp_hdr->code = ICMP_PROT_UNREACH; /* to Code 2 */
+ break;
+ default: /* if Code != 1 */
+ icmp_hdr->type = ICMP_PARAMETERPROB; /* to Type 12 */
+ icmp_hdr->code = 0; /* to Code 0 */
+ /* Update Pointer field
+ RFC 2765 (SIIT), 4.2:
+ The Pointer needs to be updated to point to the corresponding
+ field in the translated include IP header.
+ */
+ switch (ntohl(icmp6_hdr->icmp6_pointer))
+ {
+ case 0: /* IPv6 Version -> IPv4 Version */
+ icmp_hdr->un.echo.id = 0;
+ break;
+ case 4: /* IPv6 PayloadLength -> IPv4 Total Length */
+ icmp_hdr->un.echo.id = 0x0002; /* 2 */
+ break;
+ case 6: /* IPv6 Next Header-> IPv4 Protocol */
+ icmp_hdr->un.echo.id = 0x0009; /* 9 */
+ break;
+ case 7: /* IPv6 Hop Limit -> IPv4 TTL */
+ icmp_hdr->un.echo.id = 0x0008; /* 8 */
+ break;
+ case 8: /* IPv6 Src addr -> IPv4 Src addr */
+ icmp_hdr->un.echo.id = 0x000c; /* 12 */
+ break;
+ case 24: /* IPv6 Dst addr -> IPv4 Dst addr*/
+ icmp_hdr->un.echo.id = 0x0010; /* 16 */
+ break;
+ default: /* set all ones in other cases */
+ icmp_hdr->un.echo.id = 0xff;
+ break;
+ }
+ break;
+ }
+ break;
+
+/* End of ICMP Error messages */
+
+ /* Echo Request and Echo Reply (Type 128 and 129) */
+ case ICMPV6_ECHO_REQUEST:
+ icmperr = 0; /* not error ICMP message */
+ icmp_hdr->type = ICMP_ECHO; /* to Type 8 */
+ icmp_hdr->code = 0; /* to Code 0 */
+ icmp_hdr->un.echo.id = icmp6_hdr->icmp6_identifier;
+ icmp_hdr->un.echo.sequence = icmp6_hdr->icmp6_sequence;
+ /* copy rest of ICMP data to result packet */
+ if (len_delta > 0)
+ memcpy(((char *)icmp_hdr) + sizeof(struct icmphdr),
+ ((char *)icmp6_hdr) + sizeof(struct icmp6hdr), len_delta);
+ break;
+ case ICMPV6_ECHO_REPLY:
+ icmperr = 0; /* not error ICMP message */
+ icmp_hdr->type = ICMP_ECHOREPLY; /* to Type 0 */
+ icmp_hdr->code = 0; /* to Code 0 */
+ icmp_hdr->un.echo.id = icmp6_hdr->icmp6_identifier;
+ icmp_hdr->un.echo.sequence = icmp6_hdr->icmp6_sequence;
+ /* copy rest of ICMP data */
+ if (len_delta > 0)
+ memcpy(((char *)icmp_hdr) + sizeof(struct icmphdr),
+ ((char *)icmp6_hdr) + sizeof(struct icmp6hdr), len_delta);
+ break;
+ default:
+ /* Unknown error messages. Silently drop. */
+ PDEBUG("ip6_ip4(): unknown ICMPv6 Type %d, packet dropped.\n", icmp6_hdr->icmp6_type);
+ return -1;
+ }
+
+ if (icmperr)
+ {
+ /* If ICMP Error message, we translate IP included packet*/
+ if (len_delta >= sizeof(struct ipv6hdr))
+ {
+ if((inc_opts_len = ip6_ip4((char *)icmp6_hdr + sizeof(struct icmp6hdr), len_delta,
+ (char *)icmp_hdr + sizeof(struct icmphdr), 1)) == -1) {
+ PDEBUG("ip6_ip4(): incorrect translation of ICMPv6 Error message, packet dropped\n");
+ return -1;
+ }
+ /* correct IPv4 Total Len that = old Total Len
+ - Options Headers Len in included IP packet
+ - diffirence between IPv6 Header Len and IPv4 Header Len
+ */
+ if (ntot_len != 0)
+ ip_hdr->tot_len = htons(ntot_len - inc_opts_len - IP4_IP6_HDR_DIFF);
+ real_len = real_len - inc_opts_len - IP4_IP6_HDR_DIFF;
+ }
+ else if (len_delta > 0)
+ {
+ /* May be it need set 0x0 to rest area in result IPv4 packet,
+ * but we copy rest data unchanged
+ */
+ memcpy(((char *)icmp_hdr) + sizeof(struct icmphdr),
+ ((char *)icmp6_hdr) + sizeof(struct icmp6hdr), len_delta);
+ }
+ }
+
+ /* Calculate IPv4 Header checksum */
+ ip_hdr->check = 0;
+ ip_hdr->check = ip_fast_csum((unsigned char *)ip_hdr, ip_hdr->ihl);
+
+ /* Calculate ICMPv4 checksum */
+ if (ntot_len != 0)
+ {
+ icmp_hdr->checksum = 0;
+ icmp_hdr->checksum = ip_compute_csum((unsigned char *)icmp_hdr, ntohs(ip_hdr->tot_len)
+ - sizeof(struct iphdr));
+ }
+ }
+ else
+ {
+ PDEBUG("ip6_ip4(): error length ICMP packet, packet dropped.\n");
+ return -1;
+ }
+
+ }
+ /* PROCESS TCP and UDP (and rest data) */
+
+ else {
+ real_len += len_delta;
+ /* we copy rest data to IPv4 packet without changing */
+ memcpy(dst+sizeof(struct iphdr), src + sizeof(struct ipv6hdr) + opts_len, len_delta);
+ }
+ }
+
+ if (include_flag) /* if it's included IP packet */
+ return opts_len; /* return options headers length */
+ else
+ return real_len; /* result packet len */
+}
+
+/*
+ * ip4_fragment(skb, len, hdr_len, dev, eth_h)
+ * to fragment original IPv4 packet if result IPv6 packet will be > 1280
+ */
+
+static int ip4_fragment(struct sk_buff *skb, int len, int hdr_len, struct net_device *dev, struct ethhdr *eth_h)
+{
+ struct sk_buff *skb2 = NULL; /* pointer to new struct sk_buff for transleded packet */
+ char buff[FRAG_BUFF_SIZE+hdr_len]; /* buffer to form new fragment packet */
+ char *cur_ptr = skb->data+hdr_len; /* pointter to current packet data with len = frag_len */
+ struct iphdr *ih4 = (struct iphdr *) skb->data;
+ struct iphdr *new_ih4 = (struct iphdr *) buff; /* point to new IPv4 hdr */
+ struct ethhdr *new_eth_h; /* point to ether hdr, need to set hard header data in fragment */
+ int data_len = len - hdr_len; /* origin packet data len */
+ int rest_len = data_len; /* rest data to fragment */
+ int frag_len = 0; /* current fragment len */
+ int last_frag = 0; /* last fragment flag, if = 1, it's last fragment */
+ int flag_last_mf = 0;
+ __u16 new_id = 0; /* to generate identification field */
+ __u16 frag_offset = 0; /* fragment offset */
+ unsigned int csum;
+ unsigned short udp_len;
+
+#ifdef SIIT_DEBUG
+ printk("siit: it's DF == 0 and result IPv6 packet will be > 1280\n");
+ siit_print_dump(skb->data, hdr_len, "siit: (orig) ipv4_hdr dump");
+#endif
+
+ if ((ntohs(ih4->frag_off) & IP_MF) == 0 )
+ /* it's a case we'll clear MF flag in our last packet */
+ flag_last_mf = 1;
+
+ if (ih4->protocol == IPPROTO_UDP) {
+ if ( (ntohs(ih4->frag_off) & IP_OFFSET) == 0) {
+ struct udphdr *udp_hdr = (struct udphdr *)((char *)ih4 + hdr_len);
+ if (!flag_last_mf) {
+ if (udp_hdr->check == 0) {
+ /* it's a first fragment with ZERO checksum and we drop packet */
+ printk("siit: First fragment of UDP with zero checksum - packet droped\n");
+ printk("siit: addr: %x src port: %d dst port: %d\n",
+ htonl(ih4->saddr), htons(udp_hdr->source), htons(udp_hdr->dest));
+ return -1;
+ }
+ }
+ else if (udp_hdr->check == 0) {
+ /* Calculate UDP checksum only if it's not fragment */
+ udp_len = ntohs(udp_hdr->len);
+ csum = 0;
+ csum = csum_partial((unsigned char *)udp_hdr, udp_len, csum);
+ udp_hdr->check = csum_tcpudp_magic(ih4->saddr, ih4->daddr, udp_len, IPPROTO_UDP, csum);
+ }
+ }
+ }
+
+ frag_offset = ntohs(ih4->frag_off) & IP_OFFSET;
+
+ new_id = ih4->id;
+
+ while(1) {
+ if (rest_len <= FRAG_BUFF_SIZE) {
+ /* it's last fragmen */
+ frag_len = rest_len; /* rest data */
+ last_frag = 1;
+ }
+ else
+ frag_len = FRAG_BUFF_SIZE;
+
+ /* copy IP header to buffer */
+ memcpy(buff, skb->data, hdr_len);
+ /* copy data to buffer with len = frag_len */
+ memcpy(buff + hdr_len, cur_ptr, frag_len);
+
+ /* set id field in new IPv4 header*/
+ new_ih4->id = new_id;
+
+ /* is it last fragmet */
+ if(last_frag && flag_last_mf)
+ /* clear MF flag */
+ new_ih4->frag_off = htons(frag_offset & (~IP_MF));
+ else
+ /* set MF flag */
+ new_ih4->frag_off = htons(frag_offset | IP_MF);
+
+ /* change packet total length */
+ new_ih4->tot_len = htons(frag_len+hdr_len);
+
+ /* rebuild the header checksum (IP needs it) */
+ new_ih4->check = 0;
+ new_ih4->check = ip_fast_csum((unsigned char *)new_ih4,new_ih4->ihl);
+
+ /* Allocate new sk_buff to compose translated packet */
+ skb2 = dev_alloc_skb(frag_len+hdr_len+dev->hard_header_len+IP4_IP6_HDR_DIFF+IP6_FRAGMENT_SIZE);
+ if (!skb2) {
+ printk(KERN_DEBUG "%s: alloc_skb failure - packet dropped.\n", dev->name);
+ dev_kfree_skb(skb2);
+ return -1;
+ }
+ /* allocate skb->data portion for IP header len, fragment data len and ether header len
+ * and copy to head ether header from origin skb
+ */
+ memcpy(skb_put(skb2, frag_len+hdr_len+dev->hard_header_len+IP4_IP6_HDR_DIFF+IP6_FRAGMENT_SIZE), (char *) eth_h,
+ dev->hard_header_len);
+ /* correct ether header data, ether protocol field to ETH_P_IPV6 */
+ new_eth_h = (struct ethhdr *)skb2->data;
+ new_eth_h->h_proto = htons(ETH_P_IPV6);
+
+ /* reset the mac header */
+ skb_reset_mac_header(skb2);
+
+ /* pull ether header from new skb->data */
+ skb_pull(skb2, dev->hard_header_len);
+ /* set skb protocol to IPV6 */
+ skb2->protocol = htons(ETH_P_IPV6);
+
+ /* call translation function */
+ if ( ip4_ip6(buff, frag_len+hdr_len, skb2->data, 0) == -1) {
+ dev_kfree_skb(skb2);
+ return -1;
+ }
+
+ /*
+ * Set needed fields in new sk_buff
+ */
+ skb2->dev = dev;
+ skb2->ip_summed = CHECKSUM_UNNECESSARY;
+ skb2->pkt_type = PACKET_HOST;
+
+ /* Add transmit statistic */
+ siit_stats(dev)->tx_packets++;
+ siit_stats(dev)->tx_bytes += skb2->len;
+
+ /* send packet to upper layer */
+ netif_rx(skb2);
+
+ /* exit if it was last fragment */
+ if (last_frag)
+ break;
+
+ /* correct current data pointer */
+ cur_ptr += frag_len;
+ /* rest data len */
+ rest_len -= frag_len;
+ /* current fragment offset */
+ frag_offset = (frag_offset*8 + frag_len)/8;
+ }
+
+ return 0;
+}
+/*
+ * Transmit a packet (called by the kernel)
+ *
+ * siit_xmit(skb, dev)
+ *
+ * where
+ * skb - pointer to struct sk_buff with incomed packet
+ * dev - pointer to struct device on which packet revieved
+ *
+ * Statistic:
+ * for all incoming packes:
+ * stats.rx_bytes+=skb->len
+ * stats.rx_packets++
+ * for packets we can't transle:
+ * stats.tx_errors++
+ * device busy:
+ * stats.tx_errors++
+ * for packets we can't allocate sk_buff:
+ * stats.tx_dropped++
+ * for outgoing packes:
+ * stats.tx_packets++
+ * stats.tx_bytes+=skb2->len !!! But we don't set skb2->len !!!
+ */
+
+static int siit_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct sk_buff *skb2 = NULL;/* pointer to new struct sk_buff for transleded packet */
+ struct ethhdr *eth_h; /* pointer to incoming Ether header */
+ int len; /* original packets length */
+ int new_packet_len;
+ int skb_delta = 0; /* delta size for allocate new skb */
+ char new_packet_buff[2048];
+
+ /* Check pointer to sk_buff and device structs */
+ if (skb == NULL || dev == NULL)
+ return -EINVAL;
+
+ /* Add receive statistic */
+ siit_stats(dev)->rx_bytes += skb->len;
+ siit_stats(dev)->rx_packets++;
+
+ dev->trans_start = jiffies;
+
+ /* Upper layer (IP) protocol forms sk_buff for outgoing packet
+ * and sets IP header + Ether header too. IP layer sets outgoing
+ * device in sk_buff->dev.
+ * In function (from linux/net/core/dev.c) ther is a call to
+ * device transmit function (dev->hard_start_xmit):
+ *
+ * dev_queue_xmit(struct sk_buff *skb)
+ * {
+ * ...
+ * device *dev = skb->dev;
+ * ...
+ * dev->hard_start_xmit(skb, dev);
+ * ...
+ * }
+ * We save pointer to ether header in eth_h and skb_pull ether header
+ * from data field of skb_buff
+ */
+
+ eth_h = (struct ethhdr *)skb->data; /* point to incoming packet Ether Header */
+
+#ifdef SIIT_DEBUG
+ siit_print_dump(skb->data, ETH_HLEN, "siit: eth_hdr dump");
+#endif
+
+ /* Remove hardware header from origin sk_buff */
+ skb_pull(skb,dev->hard_header_len);
+
+ /*
+ * Process IPv4 paket
+ */
+ if (ntohs(skb->protocol) == ETH_P_IP) {
+ int hdr_len; /* IPv4 header length */
+ int data_len; /* IPv4 data length */
+ struct iphdr *ih4; /* pointer to IPv4 header */
+ struct icmphdr *icmp_hdr; /* point to current ICMPv4 header struct */
+
+ ih4 = (struct iphdr *)skb->data; /* point to incoming packet's IPv4 header */
+
+ /* Check IPv4 Total Length */
+ if (skb->len != ntohs(ih4->tot_len)) {
+ PDEBUG("siit_xmit(): Different skb_len %x and ip4 tot_len %x - packet dropped.\n",
+ skb->len, ih4->tot_len);
+ siit_stats(dev)->tx_errors++;
+ dev_kfree_skb(skb);
+ return 0;
+ }
+
+ len = skb->len; /* packet's total len */
+ hdr_len = (int)(ih4->ihl * 4); /* packet's header len */
+ data_len = len - hdr_len; /* packet's data len */
+
+ /* If DF == 0 */
+ if ( (ntohs(ih4->frag_off) & IP_DF) == 0 ) {
+ /* If result IPv6 packet will be > 1280
+ we need to fragment original IPv4 packet
+ */
+ if ( data_len > FRAG_BUFF_SIZE ) {
+ /* call function that fragment packet and translate to IPv6 each fragment
+ * and send to upper layer
+ */
+ if ( ip4_fragment(skb, len, hdr_len, dev, eth_h) == -1) {
+ siit_stats(dev)->tx_errors++;
+ }
+ /* Free incoming skb */
+ dev_kfree_skb(skb);
+ /* Device can accept a new packet */
+
+ return 0;
+
+ }
+ }
+ /* If DF == 1 && MF == 0 && Fragment Offset == 0
+ * we don't include fragment header
+ */
+ if ( ntohs(ih4->frag_off) == IP_DF )
+ skb_delta = IP4_IP6_HDR_DIFF; /* delta is +20 */
+ else
+ skb_delta = IP4_IP6_HDR_DIFF + IP6_FRAGMENT_SIZE; /* delta is +20 and +8 */
+
+ /* If it's ICMP, check is it included IP packet in it */
+ if ( ih4->protocol == IPPROTO_ICMP) {
+ icmp_hdr = (struct icmphdr *) (skb->data+hdr_len); /* point to ICMPv4 header */
+ if ( icmp_hdr->type != ICMP_ECHO && icmp_hdr->type != ICMP_ECHOREPLY) {
+ /*
+ * It's ICMP Error that has included IP packet
+ * we'll add only +20 because we don't include Fragment Header
+ * into translated included IP packet
+ */
+ skb_delta += IP4_IP6_HDR_DIFF;
+ }
+ }
+
+ /* Allocate new sk_buff to compose translated packet */
+ skb2 = dev_alloc_skb(len+dev->hard_header_len+skb_delta);
+ if (!skb2) {
+ printk(KERN_DEBUG "%s: alloc_skb failure - packet dropped.\n", dev->name);
+ dev_kfree_skb(skb);
+ siit_stats(dev)->rx_dropped++;
+
+ return 0;
+ }
+ /* allocate skb->data portion = IPv4 packet len + ether header len
+ * + skb_delta (max = two times (diffirence between IPv4 header and
+ * IPv6 header + Frag Header), second for included packet,
+ * and copy to head of skb->data ether header from origin skb
+ */
+ memcpy(skb_put(skb2, len+dev->hard_header_len+skb_delta), (char *)eth_h, dev->hard_header_len);
+ /* correct ether header data, ether protocol field to ETH_P_IPV6 */
+ eth_h = (struct ethhdr *)skb2->data;
+ eth_h->h_proto = htons(ETH_P_IPV6);
+ skb_reset_mac_header(skb2);
+ /* remove ether header from new skb->data,
+ * NOTE! data will rest, pointer to data and data len will change
+ */
+ skb_pull(skb2,dev->hard_header_len);
+ /* set skb protocol to IPV6 */
+ skb2->protocol = htons(ETH_P_IPV6);
+
+ /* call translation function */
+ if (ip4_ip6(skb->data, len, skb2->data, 0) == -1 ) {
+ dev_kfree_skb(skb);
+ dev_kfree_skb(skb2);
+ siit_stats(dev)->rx_errors++;
+
+ return 0;
+ }
+ }
+ /*
+ * IPv6 paket
+ */
+ else if (ntohs(skb->protocol) == ETH_P_IPV6) {
+
+#ifdef SIIT_DEBUG
+ siit_print_dump(skb->data, sizeof(struct ipv6hdr), "siit: (in) ip6_hdr dump");
+#endif
+ /* packet len = skb->data len*/
+ len = skb->len;
+
+ /* call translation function */
+ if ((new_packet_len = ip6_ip4(skb->data, len, new_packet_buff, 0)) == -1 )
+ {
+ PDEBUG("siit_xmit(): error translation ipv6->ipv4, packet dropped.\n");
+ siit_stats(dev)->rx_dropped++;
+ goto end;
+ }
+
+ /* Allocate new sk_buff to compose translated packet */
+ skb2 = dev_alloc_skb(new_packet_len + dev->hard_header_len);
+ if (!skb2) {
+ printk(KERN_DEBUG "%s: alloc_skb failure, packet dropped.\n", dev->name);
+ siit_stats(dev)->rx_dropped++;
+ goto end;
+ }
+ memcpy(skb_put(skb2, new_packet_len + dev->hard_header_len), (char *)eth_h, dev->hard_header_len);
+ eth_h = (struct ethhdr *)skb2->data;
+ eth_h->h_proto = htons(ETH_P_IP);
+ skb_reset_mac_header(skb2);
+ skb_pull(skb2, dev->hard_header_len);
+ memcpy(skb2->data, new_packet_buff, new_packet_len);
+ skb2->protocol = htons(ETH_P_IP);
+ }
+ else {
+ PDEBUG("siit_xmit(): unsupported protocol family %x, packet dropped.\n", skb->protocol);
+ goto end;
+ }
+
+ /*
+ * Set needed fields in new sk_buff
+ */
+ skb2->pkt_type = PACKET_HOST;
+ skb2->dev = dev;
+ skb2->ip_summed = CHECKSUM_UNNECESSARY;
+
+ /* Add transmit statistic */
+ siit_stats(dev)->tx_packets++;
+ siit_stats(dev)->tx_bytes += skb2->len;
+
+ /* Send packet to upper layer protocol */
+ netif_rx(skb2);
+
+end:
+ dev_kfree_skb(skb);
+
+ return 0;
+}
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
+static bool header_ops_init = false;
+static struct header_ops siit_header_ops ____cacheline_aligned;
+#endif
+
+#if !(defined CONFIG_COMPAT_NET_DEV_OPS) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
+static const struct net_device_ops siit_netdev_ops = {
+ .ndo_open = siit_open,
+ .ndo_stop = siit_release,
+ .ndo_start_xmit = siit_xmit,
+};
+#endif
+
+/*
+ * The init function initialize of the SIIT device..
+ * It is invoked by register_netdev()
+ */
+
+static void
+siit_init(struct net_device *dev)
+{
+ ether_setup(dev); /* assign some of the fields */
+ random_ether_addr(dev->dev_addr);
+
+ /*
+ * Assign device function.
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
+ dev->open = siit_open;
+ dev->stop = siit_release;
+ dev->hard_start_xmit = siit_xmit;
+#else
+#if !(defined CONFIG_COMPAT_NET_DEV_OPS) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
+ dev->netdev_ops = &siit_netdev_ops;
+#endif
+#endif
+ dev->flags |= IFF_NOARP; /* ARP not used */
+ dev->tx_queue_len = 10;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ dev->hard_header_cache = NULL; /* Disable caching */
+ memset(netdev_priv(dev), 0, sizeof(struct net_device_stats));
+ dev->get_stats = siit_get_stats;
+#else
+ if (!header_ops_init) {
+ memcpy(&siit_header_ops, dev->header_ops, sizeof(struct header_ops));
+ siit_header_ops.cache = NULL;
+ }
+ dev->header_ops = &siit_header_ops;
+#endif
+}
+
+/*
+ * Finally, the module stuff
+ */
+static struct net_device *siit_dev = NULL;
+
+int init_module(void)
+{
+ int res = -ENOMEM;
+ int priv_size;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ priv_size = sizeof(struct net_device_stats);
+#else
+ priv_size = sizeof(struct header_ops);
+#endif
+ siit_dev = alloc_netdev(priv_size, "siit%d", siit_init);
+ if (!siit_dev)
+ goto err_alloc;
+
+ res = register_netdev(siit_dev);
+ if (res)
+ goto err_register;
+
+ return 0;
+
+err_register:
+ free_netdev(siit_dev);
+err_alloc:
+ printk(KERN_ERR "Error creating siit device: %d\n", res);
+ return res;
+}
+
+void cleanup_module(void)
+{
+ unregister_netdev(siit_dev);
+ free_netdev(siit_dev);
+}
+
+
diff --git a/package/siit/src/siit.h b/package/siit/src/siit.h
new file mode 100644
index 000000000..47cf77645
--- /dev/null
+++ b/package/siit/src/siit.h
@@ -0,0 +1,61 @@
+/*
+ * siit.h -- definitions for the SIIT module
+ *
+ *
+ */
+
+/*
+ * Constants
+ */
+
+/* SIIT_ETH control the name of SIIT interface:
+ * 0 - interface name is siit0,
+ * 1 - interface name is ethX.
+ */
+#define SIIT_ETH 0
+
+#define BUFF_SIZE 4096
+#define FRAG_BUFF_SIZE 1232 /* IPv6 max fragment size without IPv6 header
+ * to fragmanet IPv4 if result IPv6 packet will be > 1280
+ */
+
+#define TRANSLATED_PREFIX 0x0000ffff /* third byte in IPv4-translated addr prefix */
+#define MAPPED_PREFIX 0x0000ffff /* third byte in IPv4-mapped addr prefix */
+
+#define IP4_IP6_HDR_DIFF 20 /* diffirence between IPv4 and IPv6 headers */
+#define IP6_FRAGMENT_SIZE 8 /* size of Fragment Header */
+
+/* IPv6 header fields masks */
+#define IP6F_OFF_MASK 0xfff8 /* mask out offset from frag_off */
+#define IP6F_RESERVED_MASK 0x0006 /* reserved bits in frag_off */
+#define IP6F_MORE_FRAG 0x0001 /* more-fragments flag */
+
+
+
+/*
+ * Macros to help debugging
+ */
+
+#undef PDEBUG /* undef it, just in case */
+#ifdef SIIT_DEBUG
+# ifdef __KERNEL__
+ /* This one if debugging is on, and kernel space */
+# define PDEBUG(fmt, args...) printk(KERN_DEBUG "siit: " fmt, ## args)
+# else
+ /* This one for user space */
+# define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
+# endif
+#else
+# define PDEBUG(fmt, args...) /* not debugging: nothing */
+#endif
+
+#undef PDEBUGG
+#define PDEBUGG(fmt, args...)
+
+
+
+
+
+
+
+
diff --git a/package/soloscli/Makefile b/package/soloscli/Makefile
new file mode 100644
index 000000000..9a7cd894f
--- /dev/null
+++ b/package/soloscli/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2006-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=soloscli
+PKG_VERSION:=0.11
+PKG_RELEASE:=3
+
+PKG_SOURCE:=solos-pci-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/openadsl
+PKG_MD5SUM:=ab3f3fa654ef7c3a402980eca094e690
+
+PKG_INSTALL:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/solos-pci-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/soloscli
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=Configuration utility for Solos ADSL2+ modems
+ DEPENDS:=+kmod-solos-pci
+ URL:=http://sourceforge.net/projects/openadsl
+endef
+
+define Package/soloscli/description
+ This package contains the soloscli utility
+ for interrogating Traverse Technologies' Solos ADSL2+ modems.
+endef
+
+define Package/soloscli/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/soloscli/soloscli $(1)/usr/bin/
+ $(INSTALL_BIN) ./files/solos-log-stats $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/etc/hotplug.d/atm
+ $(INSTALL_DATA) ./files/etc/hotplug.d/atm/15-solos-init $(1)/etc/hotplug.d/atm/
+endef
+
+$(eval $(call BuildPackage,soloscli))
diff --git a/package/soloscli/files/etc/hotplug.d/atm/15-solos-init b/package/soloscli/files/etc/hotplug.d/atm/15-solos-init
new file mode 100644
index 000000000..36d13ea5a
--- /dev/null
+++ b/package/soloscli/files/etc/hotplug.d/atm/15-solos-init
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+dialog() {
+ local tag="$(echo "$1" | cut -d= -f1)"
+ local value="$(echo "$1" | cut -d= -f2-)"
+ local response
+
+ response="$(soloscli -s "$port" "$tag" "$value")"
+ [ $? -ne 0 ] && {
+ logger "soloscli($port): $tag '$value' returns $response"
+ }
+}
+
+if [ "$ACTION" = "add" ]; then
+ include /lib/network
+ scan_interfaces
+
+ case $DEVICENAME in
+ solos-pci[0-3])
+ port="${DEVICENAME#solos-pci}"
+ device="solos${port}"
+
+ config_list_foreach wan "$device" dialog
+ ;;
+ esac
+fi
diff --git a/package/soloscli/files/etc/uci-default/solos b/package/soloscli/files/etc/uci-default/solos
new file mode 100644
index 000000000..7f69da62c
--- /dev/null
+++ b/package/soloscli/files/etc/uci-default/solos
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+uci batch <<__EOF__
+
+delete network.wan.solos0
+
+add_list network.wan.solos0="ActivateLine=Abort"
+add_list network.wan.solos0="Retrain=EnableAll"
+add_list network.wan.solos0="DetectNoise=Enable"
+add_list network.wan.solos0="BisMCapability=Disable"
+add_list network.wan.solos0="BisACapability=Disable"
+add_list network.wan.solos0="ActivateLine=Start"
+
+commit network
+__EOF__
diff --git a/package/soloscli/files/solos-log-stats b/package/soloscli/files/solos-log-stats
new file mode 100644
index 000000000..2b75ee30c
--- /dev/null
+++ b/package/soloscli/files/solos-log-stats
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+cd /sys/class/atm/ || exit 1
+
+for PORT in solos-pci* ; do
+
+ RXRATE=`cat $PORT/parameters/RxBitRate`
+ TXRATE=`cat $PORT/parameters/TxBitRate`
+ RXSNR=`cat $PORT/parameters/LocalSNRMargin | sed "s/ dB//"`
+ TXSNR=`cat $PORT/parameters/RemoteSNRMargin | sed "s/ dB//"`
+ RXERR=`cat $PORT/parameters/RSUnCorrectedErrorsDn`
+ TXERR=`cat $PORT/parameters/RSUnCorrectedErrorsUp`
+ RXFEC=`cat $PORT/parameters/RSCorrectedErrorsDn`
+ TXFEC=`cat $PORT/parameters/RSCorrectedErrorsUp`
+
+ echo "$RXRATE $RXSNR $RXERR $RXFEC / $TXRATE $TXSNR $TXERR $TXFEC" |
+ logger -t $PORT
+done
+
diff --git a/package/soloscli/patches/000-Makefile.patch b/package/soloscli/patches/000-Makefile.patch
new file mode 100644
index 000000000..914d6d886
--- /dev/null
+++ b/package/soloscli/patches/000-Makefile.patch
@@ -0,0 +1,21 @@
+--- a/Makefile 2010-06-14 14:17:11.000000000 +1000
++++ b/Makefile 2010-06-14 14:17:54.000000000 +1000
+@@ -13,6 +13,11 @@
+ KDIR ?= /lib/modules/$(shell uname -r)/build
+ PWD := $(shell pwd)
+
++soloscli/soloscli:
++ $(MAKE) -C soloscli
++
++install:
++
+ default:
+ $(MAKE) -C $(KDIR) M=$(PWD) modules
+
+@@ -20,5 +25,6 @@
+ rm -f *.o *.ko *.mod.c .*.cmd
+ rm -rf .tmp_versions
+ rm -f Module.symvers
++ $(MAKE) -C soloscli clean
+
+ endif
diff --git a/package/soloscli/patches/001-newline.patch b/package/soloscli/patches/001-newline.patch
new file mode 100644
index 000000000..4b663e889
--- /dev/null
+++ b/package/soloscli/patches/001-newline.patch
@@ -0,0 +1,15 @@
+--- a/soloscli/soloscli.c
++++ b/soloscli/soloscli.c
+@@ -238,7 +238,11 @@
+ }
+ if (strcmp(buf,pid) == 0) {
+ /* printf("Sequence matches.\n"); */
+- printf("%s",bufp);
++ if(buf[(len-1)] == '\n'){
++ printf("%s",bufp);
++ } else {
++ printf("%s\n",bufp);
++ }
+ } else {
+ printf("Sequence incorrect.\n");
+ buf[i] = '\n';
diff --git a/package/spi-ks8995/Makefile b/package/spi-ks8995/Makefile
new file mode 100644
index 000000000..0be9fe3dc
--- /dev/null
+++ b/package/spi-ks8995/Makefile
@@ -0,0 +1,54 @@
+#
+# Copyright (C) 2008 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=spi-ks8995
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/spi-ks8995
+ SUBMENU:=SPI Support
+ TITLE:=Micrel/Kendin KS8995 Ethernet switch control
+ FILES:=$(PKG_BUILD_DIR)/spi_ks8995.ko
+ KCONFIG:=CONFIG_SPI=y \
+ CONFIG_SPI_MASTER=y
+ AUTOLOAD:=$(call AutoLoad,50,spi_ks8995)
+endef
+
+define KernelPackage/spi-ks8995/description
+ Kernel module for Micrel/Kendin KS8995 ethernet switch
+endef
+
+EXTRA_KCONFIG:= \
+ CONFIG_SPI_KS8995=m
+
+EXTRA_CFLAGS:= \
+ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \
+ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \
+
+MAKE_OPTS:= \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ SUBDIRS="$(PKG_BUILD_DIR)" \
+ EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
+ $(EXTRA_KCONFIG)
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ $(MAKE) -C "$(LINUX_DIR)" \
+ $(MAKE_OPTS) \
+ modules
+endef
+
+$(eval $(call KernelPackage,spi-ks8995))
diff --git a/package/spi-ks8995/src/Kconfig b/package/spi-ks8995/src/Kconfig
new file mode 100644
index 000000000..7859be183
--- /dev/null
+++ b/package/spi-ks8995/src/Kconfig
@@ -0,0 +1,3 @@
+config SPI_KS8995
+ tristate "Micrel/Kendin KS8995 Ethernet switch"
+ depends on SPI
diff --git a/package/spi-ks8995/src/Makefile b/package/spi-ks8995/src/Makefile
new file mode 100644
index 000000000..810c3bd1d
--- /dev/null
+++ b/package/spi-ks8995/src/Makefile
@@ -0,0 +1 @@
+obj-${CONFIG_SPI_KS8995} += spi_ks8995.o \ No newline at end of file
diff --git a/package/spi-ks8995/src/spi_ks8995.c b/package/spi-ks8995/src/spi_ks8995.c
new file mode 100644
index 000000000..c0dd86b4c
--- /dev/null
+++ b/package/spi-ks8995/src/spi_ks8995.c
@@ -0,0 +1,419 @@
+/*
+ * SPI driver for Micrel/Kendin KS8995M ethernet switch
+ *
+ * Copyright (C) 2008 Gabor Juhos <juhosg at openwrt.org>
+ *
+ * This file was based on: drivers/spi/at25.c
+ * Copyright (C) 2006 David Brownell
+ *
+ * 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/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+
+#include <linux/spi/spi.h>
+
+#define DRV_VERSION "0.1.1"
+#define DRV_DESC "Micrel/Kendin KS8995 Ethernet switch SPI driver"
+
+/*-------------------------------------------------------------------------*/
+
+#define KS8995_REG_ID0 0x00 /* Chip ID0 */
+#define KS8995_REG_ID1 0x01 /* Chip ID1 */
+
+#define KS8995_REG_GC0 0x02 /* Global Control 0 */
+#define KS8995_REG_GC1 0x03 /* Global Control 1 */
+#define KS8995_REG_GC2 0x04 /* Global Control 2 */
+#define KS8995_REG_GC3 0x05 /* Global Control 3 */
+#define KS8995_REG_GC4 0x06 /* Global Control 4 */
+#define KS8995_REG_GC5 0x07 /* Global Control 5 */
+#define KS8995_REG_GC6 0x08 /* Global Control 6 */
+#define KS8995_REG_GC7 0x09 /* Global Control 7 */
+#define KS8995_REG_GC8 0x0a /* Global Control 8 */
+#define KS8995_REG_GC9 0x0b /* Global Control 9 */
+
+#define KS8995_REG_PC(p,r) ((0x10 * p) + r) /* Port Control */
+#define KS8995_REG_PS(p,r) ((0x10 * p) + r + 0xe) /* Port Status */
+
+#define KS8995_REG_TPC0 0x60 /* TOS Priority Control 0 */
+#define KS8995_REG_TPC1 0x61 /* TOS Priority Control 1 */
+#define KS8995_REG_TPC2 0x62 /* TOS Priority Control 2 */
+#define KS8995_REG_TPC3 0x63 /* TOS Priority Control 3 */
+#define KS8995_REG_TPC4 0x64 /* TOS Priority Control 4 */
+#define KS8995_REG_TPC5 0x65 /* TOS Priority Control 5 */
+#define KS8995_REG_TPC6 0x66 /* TOS Priority Control 6 */
+#define KS8995_REG_TPC7 0x67 /* TOS Priority Control 7 */
+
+#define KS8995_REG_MAC0 0x68 /* MAC address 0 */
+#define KS8995_REG_MAC1 0x69 /* MAC address 1 */
+#define KS8995_REG_MAC2 0x6a /* MAC address 2 */
+#define KS8995_REG_MAC3 0x6b /* MAC address 3 */
+#define KS8995_REG_MAC4 0x6c /* MAC address 4 */
+#define KS8995_REG_MAC5 0x6d /* MAC address 5 */
+
+#define KS8995_REG_IAC0 0x6e /* Indirect Access Control 0 */
+#define KS8995_REG_IAC1 0x6f /* Indirect Access Control 0 */
+
+#define KS8995_REG_IAD7 0x70 /* Indirect Access Data 7 */
+#define KS8995_REG_IAD6 0x71 /* Indirect Access Data 6 */
+#define KS8995_REG_IAD5 0x72 /* Indirect Access Data 5 */
+#define KS8995_REG_IAD4 0x73 /* Indirect Access Data 4 */
+#define KS8995_REG_IAD3 0x74 /* Indirect Access Data 3 */
+#define KS8995_REG_IAD2 0x75 /* Indirect Access Data 2 */
+#define KS8995_REG_IAD1 0x76 /* Indirect Access Data 1 */
+#define KS8995_REG_IAD0 0x77 /* Indirect Access Data 0 */
+
+#define KS8995_REGS_SIZE 0x80
+
+#define ID1_CHIPID_M 0xf
+#define ID1_CHIPID_S 4
+#define ID1_REVISION_M 0x7
+#define ID1_REVISION_S 1
+#define ID1_START_SW 1 /* start the switch */
+
+#define FAMILY_KS8995 0x95
+#define CHIPID_M 0
+
+#define KS8995_CMD_WRITE 0x02U
+#define KS8995_CMD_READ 0x03U
+
+#define KS8995_RESET_DELAY 10 /* usec */
+
+/*-------------------------------------------------------------------------*/
+
+struct ks8995_pdata {
+ /* not yet implemented */
+};
+
+struct ks8995_switch {
+ struct spi_device *spi;
+ struct mutex lock;
+ struct ks8995_pdata *pdata;
+};
+
+/*-------------------------------------------------------------------------*/
+
+static inline u8 get_chip_id(u8 val)
+{
+ return ((val >> ID1_CHIPID_S) & ID1_CHIPID_M);
+}
+
+static inline u8 get_chip_rev(u8 val)
+{
+ return ((val >> ID1_REVISION_S) & ID1_REVISION_M);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int ks8995_read(struct ks8995_switch *ks, char *buf,
+ unsigned offset, size_t count)
+{
+ u8 cmd[2];
+ struct spi_transfer t[2];
+ struct spi_message m;
+ int err;
+
+ spi_message_init(&m);
+
+ memset(&t, 0, sizeof(t));
+
+ t[0].tx_buf = cmd;
+ t[0].len = sizeof(cmd);
+ spi_message_add_tail(&t[0], &m);
+
+ t[1].rx_buf = buf;
+ t[1].len = count;
+ spi_message_add_tail(&t[1], &m);
+
+ cmd[0] = KS8995_CMD_READ;
+ cmd[1] = offset;
+
+ mutex_lock(&ks->lock);
+ err = spi_sync(ks->spi, &m);
+ mutex_unlock(&ks->lock);
+
+ return err ? err : count;
+}
+
+
+static int ks8995_write(struct ks8995_switch *ks, char *buf,
+ unsigned offset, size_t count)
+{
+ u8 cmd[2];
+ struct spi_transfer t[2];
+ struct spi_message m;
+ int err;
+
+ spi_message_init(&m);
+
+ memset(&t, 0, sizeof(t));
+
+ t[0].tx_buf = cmd;
+ t[0].len = sizeof(cmd);
+ spi_message_add_tail(&t[0], &m);
+
+ t[1].tx_buf = buf;
+ t[1].len = count;
+ spi_message_add_tail(&t[1], &m);
+
+ cmd[0] = KS8995_CMD_WRITE;
+ cmd[1] = offset;
+
+ mutex_lock(&ks->lock);
+ err = spi_sync(ks->spi, &m);
+ mutex_unlock(&ks->lock);
+
+ return err ? err : count;
+}
+
+static inline int ks8995_read_reg(struct ks8995_switch *ks, u8 addr, u8 *buf)
+{
+ return (ks8995_read(ks, buf, addr, 1) != 1);
+}
+
+static inline int ks8995_write_reg(struct ks8995_switch *ks, u8 addr, u8 val)
+{
+ char buf = val;
+
+ return (ks8995_write(ks, &buf, addr, 1) != 1);
+}
+
+/*-------------------------------------------------------------------------*/
+
+#if 0
+static int ks8995_setup(struct spi_device *spi)
+{
+ struct ks8995_switch *ks;
+ u8 t;
+
+ ks = dev_get_drvdata(&spi->dev);
+
+ ks8995_write_reg(ks, KS8995_REG_GC0, 0x4c);
+ ks8995_write_reg(ks, KS8995_REG_GC1, 0x05);
+
+ ks8995_read_reg(ks, KS8995_REG_GC2, &t);
+ ks8995_write_reg(ks, KS8995_REG_GC2, t | 1);
+
+ ks8995_write_reg(ks, KS8995_REG_GC4, 0x20);
+
+ ks8995_write_reg(ks, KS8995_REG_PC(1,0), 0x61);
+ ks8995_write_reg(ks, KS8995_REG_PC(2,0), 0x61);
+ ks8995_write_reg(ks, KS8995_REG_PC(3,0), 0x61);
+ ks8995_write_reg(ks, KS8995_REG_PC(4,0), 0x61);
+ ks8995_write_reg(ks, KS8995_REG_PC(5,0), 0x61);
+
+ ks8995_write_reg(ks, KS8995_REG_PC(5,11), 0x18);
+
+ ks8995_write_reg(ks, KS8995_REG_TPC0, 0xff);
+ ks8995_write_reg(ks, KS8995_REG_TPC1, 0xff);
+ ks8995_write_reg(ks, KS8995_REG_TPC2, 0xff);
+ ks8995_write_reg(ks, KS8995_REG_TPC3, 0xff);
+ ks8995_write_reg(ks, KS8995_REG_TPC4, 0xff);
+ ks8995_write_reg(ks, KS8995_REG_TPC5, 0xff);
+ ks8995_write_reg(ks, KS8995_REG_TPC6, 0xff);
+ ks8995_write_reg(ks, KS8995_REG_TPC7, 0xfe);
+
+ return 0;
+}
+#endif
+
+static int ks8995_stop(struct ks8995_switch *ks)
+{
+ return ks8995_write_reg(ks, KS8995_REG_ID1, 0);
+}
+
+static int ks8995_start(struct ks8995_switch *ks)
+{
+ return ks8995_write_reg(ks, KS8995_REG_ID1, 1);
+}
+
+static int ks8995_reset(struct ks8995_switch *ks)
+{
+ int err;
+
+ err = ks8995_stop(ks);
+ if (err)
+ return err;
+
+ udelay(KS8995_RESET_DELAY);
+
+ return ks8995_start(ks);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int ks8995_registers_read(struct kobject *kobj,
+ struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)
+{
+ struct device *dev;
+ struct ks8995_switch *ks8995;
+
+ dev = container_of(kobj, struct device, kobj);
+ ks8995 = dev_get_drvdata(dev);
+
+ if (unlikely(off > KS8995_REGS_SIZE))
+ return 0;
+
+ if ((off + count) > KS8995_REGS_SIZE)
+ count = KS8995_REGS_SIZE - off;
+
+ if (unlikely(!count))
+ return count;
+
+ return ks8995_read(ks8995, buf, off, count);
+}
+
+
+static int ks8995_registers_write(struct kobject *kobj,
+ struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)
+{
+ struct device *dev;
+ struct ks8995_switch *ks8995;
+
+ dev = container_of(kobj, struct device, kobj);
+ ks8995 = dev_get_drvdata(dev);
+
+ if (unlikely(off >= KS8995_REGS_SIZE))
+ return -EFBIG;
+
+ if ((off + count) > KS8995_REGS_SIZE)
+ count = KS8995_REGS_SIZE - off;
+
+ if (unlikely(!count))
+ return count;
+
+ return ks8995_write(ks8995, buf, off, count);
+}
+
+
+static struct bin_attribute ks8995_registers_attr = {
+ .attr = {
+ .name = "registers",
+ .mode = S_IRUSR | S_IWUSR,
+ },
+ .size = KS8995_REGS_SIZE,
+ .read = ks8995_registers_read,
+ .write = ks8995_registers_write,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __devinit ks8995_probe(struct spi_device *spi)
+{
+ struct ks8995_switch *ks;
+ struct ks8995_pdata *pdata;
+ u8 ids[2];
+ int err;
+
+ /* Chip description */
+ pdata = spi->dev.platform_data;
+
+ ks = kzalloc(sizeof(*ks), GFP_KERNEL);
+ if (!ks) {
+ dev_err(&spi->dev, "no memory for private data\n");
+ return-ENOMEM;
+ }
+
+ mutex_init(&ks->lock);
+ ks->pdata = pdata;
+ ks->spi = spi_dev_get(spi);
+ dev_set_drvdata(&spi->dev, ks);
+
+ spi->mode = SPI_MODE_0;
+ spi->bits_per_word = 8;
+ err = spi_setup(spi);
+ if (err) {
+ dev_err(&spi->dev, "spi_setup failed, err=%d \n", err);
+ goto err_drvdata;
+ }
+
+ err = ks8995_read(ks, ids, KS8995_REG_ID0, sizeof(ids));
+ if (err < 0) {
+ dev_err(&spi->dev, "unable to read id registers, err=%d \n",
+ err);
+ goto err_drvdata;
+ }
+
+ switch (ids[0]) {
+ case FAMILY_KS8995:
+ break;
+ default:
+ dev_err(&spi->dev, "unknown family id:%02x\n", ids[0]);
+ err = -ENODEV;
+ goto err_drvdata;
+ }
+
+ err = ks8995_reset(ks);
+ if (err)
+ goto err_drvdata;
+
+ err = sysfs_create_bin_file(&spi->dev.kobj, &ks8995_registers_attr);
+ if (err) {
+ dev_err(&spi->dev, "unable to create sysfs file, err=%d\n",
+ err);
+ goto err_drvdata;
+ }
+
+ dev_info(&spi->dev, "KS89%02X device found, Chip ID:%01x, "
+ "Revision:%01x\n", ids[0],
+ get_chip_id(ids[1]), get_chip_rev(ids[1]));
+
+ return 0;
+
+err_drvdata:
+ dev_set_drvdata(&spi->dev, NULL);
+ kfree(ks);
+ return err;
+}
+
+static int __devexit ks8995_remove(struct spi_device *spi)
+{
+ struct ks8995_data *ks8995;
+
+ ks8995 = dev_get_drvdata(&spi->dev);
+ sysfs_remove_bin_file(&spi->dev.kobj, &ks8995_registers_attr);
+
+ dev_set_drvdata(&spi->dev, NULL);
+ kfree(ks8995);
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct spi_driver ks8995_driver = {
+ .driver = {
+ .name = "spi-ks8995",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = ks8995_probe,
+ .remove = __devexit_p(ks8995_remove),
+};
+
+static int __init ks8995_init(void)
+{
+ printk(KERN_INFO DRV_DESC " version " DRV_VERSION"\n");
+
+ return spi_register_driver(&ks8995_driver);
+}
+module_init(ks8995_init);
+
+static void __exit ks8995_exit(void)
+{
+ spi_unregister_driver(&ks8995_driver);
+}
+module_exit(ks8995_exit);
+
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
+MODULE_LICENSE("GPL v2");
+
diff --git a/package/spidev_test/Makefile b/package/spidev_test/Makefile
new file mode 100644
index 000000000..e0a989e60
--- /dev/null
+++ b/package/spidev_test/Makefile
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2009 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=spidev-test
+PKG_RELEASE:=$(LINUX_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/spidev-test
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+kmod-spi-dev
+ TITLE:=SPI testing utility
+ VERSION:=$(LINUX_VERSION)-$(PKG_RELEASE)
+ URL:=http://www.kernel.org
+endef
+
+define Package/spidev-test/description
+ SPI testing utility.
+endef
+
+define Build/Prepare
+endef
+
+define Build/Compile
+ $(TARGET_CC) $(TARGET_CFLAGS) -o $(PKG_BUILD_DIR)/spidev_test \
+ $(LINUX_DIR)/Documentation/spi/spidev_test.c
+endef
+
+define Package/spidev-test/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/spidev_test $(1)/sbin/
+endef
+
+$(eval $(call BuildPackage,spidev-test))
diff --git a/package/swconfig/Makefile b/package/swconfig/Makefile
new file mode 100644
index 000000000..099058e5f
--- /dev/null
+++ b/package/swconfig/Makefile
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2008-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=swconfig
+PKG_RELEASE:=10
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+define Package/swconfig
+ SECTION:=base
+ CATEGORY:=Base system
+ DEPENDS:=@!TARGET_brcm47xx +libuci +libnl-tiny
+ TITLE:=Switch configuration utility
+endef
+
+TARGET_CPPFLAGS := \
+ -D_GNU_SOURCE \
+ -I$(STAGING_DIR)/usr/include/libnl-tiny \
+ -I$(LINUX_DIR)/include \
+ -I$(LINUX_DIR)/arch/$(LINUX_KARCH)/include \
+ -I$(PKG_BUILD_DIR) \
+ $(TARGET_CPPFLAGS)
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ LIBS="$(TARGET_LDFLAGS) -lnl-tiny -lm -luci"
+endef
+
+define Package/swconfig/install
+ $(INSTALL_DIR) $(1)/sbin $(1)/lib/network
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/swconfig $(1)/sbin/swconfig
+ $(INSTALL_DATA) ./files/switch.sh $(1)/lib/network/
+endef
+
+$(eval $(call BuildPackage,swconfig))
diff --git a/package/swconfig/files/switch.sh b/package/swconfig/files/switch.sh
new file mode 100644
index 000000000..18d5fbd2c
--- /dev/null
+++ b/package/swconfig/files/switch.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+# Copyright (C) 2009 OpenWrt.org
+
+setup_switch_dev() {
+ config_get name "$1" name
+ name="${name:-$1}"
+ [ -d "/sys/class/net/$name" ] && ifconfig "$name" up
+ swconfig dev "$name" load network
+}
+
+setup_switch() {
+ config_load network
+ config_foreach setup_switch_dev switch
+}
diff --git a/package/swconfig/src/Makefile b/package/swconfig/src/Makefile
new file mode 100644
index 000000000..0d56f4315
--- /dev/null
+++ b/package/swconfig/src/Makefile
@@ -0,0 +1,12 @@
+ifndef CFLAGS
+CFLAGS = -O2 -g -I ../src
+endif
+LIBS=-lnl -lnl-genl
+
+all: swconfig
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c -o $@ $^
+
+swconfig: cli.o swlib.o uci.o
+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
diff --git a/package/swconfig/src/cli.c b/package/swconfig/src/cli.c
new file mode 100644
index 000000000..9cd16abb5
--- /dev/null
+++ b/package/swconfig/src/cli.c
@@ -0,0 +1,340 @@
+/*
+ * swconfig.c: Switch configuration utility
+ *
+ * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2010 Martin Mares <mj@ucw.cz>
+ *
+ * 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 Foundatio.
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <uci.h>
+
+#include <linux/types.h>
+#include <linux/netlink.h>
+#include <linux/genetlink.h>
+#include <netlink/netlink.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/ctrl.h>
+#include <linux/switch.h>
+#include "swlib.h"
+
+enum {
+ CMD_NONE,
+ CMD_GET,
+ CMD_SET,
+ CMD_LOAD,
+ CMD_HELP,
+ CMD_SHOW,
+};
+
+static void
+print_attrs(const struct switch_attr *attr)
+{
+ int i = 0;
+ while (attr) {
+ const char *type;
+ switch(attr->type) {
+ case SWITCH_TYPE_INT:
+ type = "int";
+ break;
+ case SWITCH_TYPE_STRING:
+ type = "string";
+ break;
+ case SWITCH_TYPE_PORTS:
+ type = "ports";
+ break;
+ case SWITCH_TYPE_NOVAL:
+ type = "none";
+ break;
+ default:
+ type = "unknown";
+ break;
+ }
+ printf("\tAttribute %d (%s): %s (%s)\n", ++i, type, attr->name, attr->description);
+ attr = attr->next;
+ }
+}
+
+static void
+list_attributes(struct switch_dev *dev)
+{
+ printf("%s: %s(%s), ports: %d (cpu @ %d), vlans: %d\n", dev->dev_name, dev->alias, dev->name, dev->ports, dev->cpu_port, dev->vlans);
+ printf(" --switch\n");
+ print_attrs(dev->ops);
+ printf(" --vlan\n");
+ print_attrs(dev->vlan_ops);
+ printf(" --port\n");
+ print_attrs(dev->port_ops);
+}
+
+static void
+print_attr_val(const struct switch_attr *attr, const struct switch_val *val)
+{
+ int i;
+
+ switch (attr->type) {
+ case SWITCH_TYPE_INT:
+ printf("%d", val->value.i);
+ break;
+ case SWITCH_TYPE_STRING:
+ printf("%s", val->value.s);
+ break;
+ case SWITCH_TYPE_PORTS:
+ for(i = 0; i < val->len; i++) {
+ printf("%d%s ",
+ val->value.ports[i].id,
+ (val->value.ports[i].flags &
+ SWLIB_PORT_FLAG_TAGGED) ? "t" : "");
+ }
+ break;
+ default:
+ printf("?unknown-type?");
+ }
+}
+
+static void
+show_attrs(struct switch_dev *dev, struct switch_attr *attr, struct switch_val *val)
+{
+ while (attr) {
+ if (attr->type != SWITCH_TYPE_NOVAL) {
+ printf("\t%s: ", attr->name);
+ if (swlib_get_attr(dev, attr, val) < 0)
+ printf("???");
+ else
+ print_attr_val(attr, val);
+ putchar('\n');
+ }
+ attr = attr->next;
+ }
+}
+
+static void
+show_global(struct switch_dev *dev)
+{
+ struct switch_val val;
+
+ printf("Global attributes:\n");
+ show_attrs(dev, dev->ops, &val);
+}
+
+static void
+show_port(struct switch_dev *dev, int port)
+{
+ struct switch_val val;
+
+ printf("Port %d:\n", port);
+ val.port_vlan = port;
+ show_attrs(dev, dev->port_ops, &val);
+}
+
+static void
+show_vlan(struct switch_dev *dev, int vlan, bool all)
+{
+ struct switch_val val;
+ struct switch_attr *attr;
+
+ val.port_vlan = vlan;
+
+ if (all) {
+ attr = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_VLAN, "ports");
+ if (swlib_get_attr(dev, attr, &val) < 0)
+ return;
+
+ if (!val.len)
+ return;
+ }
+
+ printf("VLAN %d:\n", vlan);
+ show_attrs(dev, dev->vlan_ops, &val);
+}
+
+static void
+print_usage(void)
+{
+ printf("swconfig dev <dev> [port <port>|vlan <vlan>] (help|set <key> <value>|get <key>|load <config>|show)\n");
+ exit(1);
+}
+
+static void
+swconfig_load_uci(struct switch_dev *dev, const char *name)
+{
+ struct uci_context *ctx;
+ struct uci_package *p = NULL;
+ struct uci_element *e;
+ int ret = -1;
+
+ ctx = uci_alloc_context();
+ if (!ctx)
+ return;
+
+ uci_load(ctx, name, &p);
+ if (!p) {
+ uci_perror(ctx, "Failed to load config file: ");
+ goto out;
+ }
+
+ ret = swlib_apply_from_uci(dev, p);
+ if (ret < 0)
+ fprintf(stderr, "Failed to apply configuration for switch '%s'\n", dev->dev_name);
+
+out:
+ uci_free_context(ctx);
+ exit(ret);
+}
+
+int main(int argc, char **argv)
+{
+ int retval = 0;
+ struct switch_dev *dev;
+ struct switch_attr *a;
+ struct switch_val val;
+ int err;
+ int i;
+
+ int cmd = CMD_NONE;
+ char *cdev = NULL;
+ int cport = -1;
+ int cvlan = -1;
+ char *ckey = NULL;
+ char *cvalue = NULL;
+
+ if(argc < 4)
+ print_usage();
+
+ if(strcmp(argv[1], "dev"))
+ print_usage();
+
+ cdev = argv[2];
+
+ for(i = 3; i < argc; i++)
+ {
+ char *arg = argv[i];
+ if (cmd != CMD_NONE) {
+ print_usage();
+ } else if (!strcmp(arg, "port") && i+1 < argc) {
+ cport = atoi(argv[++i]);
+ } else if (!strcmp(arg, "vlan") && i+1 < argc) {
+ cvlan = atoi(argv[++i]);
+ } else if (!strcmp(arg, "help")) {
+ cmd = CMD_HELP;
+ } else if (!strcmp(arg, "set") && i+1 < argc) {
+ cmd = CMD_SET;
+ ckey = argv[++i];
+ if (i+1 < argc)
+ cvalue = argv[++i];
+ } else if (!strcmp(arg, "get") && i+1 < argc) {
+ cmd = CMD_GET;
+ ckey = argv[++i];
+ } else if (!strcmp(arg, "load") && i+1 < argc) {
+ if ((cport >= 0) || (cvlan >= 0))
+ print_usage();
+ cmd = CMD_LOAD;
+ ckey = argv[++i];
+ } else if (!strcmp(arg, "show")) {
+ cmd = CMD_SHOW;
+ } else {
+ print_usage();
+ }
+ }
+
+ if (cmd == CMD_NONE)
+ print_usage();
+ if (cport > -1 && cvlan > -1)
+ print_usage();
+
+ dev = swlib_connect(cdev);
+ if (!dev) {
+ fprintf(stderr, "Failed to connect to the switch\n");
+ return 1;
+ }
+
+ swlib_scan(dev);
+
+ if (cmd == CMD_GET || cmd == CMD_SET) {
+ if(cport > -1)
+ a = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_PORT, ckey);
+ else if(cvlan > -1)
+ a = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_VLAN, ckey);
+ else
+ a = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_GLOBAL, ckey);
+
+ if(!a)
+ {
+ fprintf(stderr, "Unknown attribute \"%s\"\n", ckey);
+ goto out;
+ }
+ }
+
+ switch(cmd)
+ {
+ case CMD_SET:
+ if ((a->type != SWITCH_TYPE_NOVAL) &&
+ (cvalue == NULL))
+ print_usage();
+
+ if(cvlan > -1)
+ cport = cvlan;
+
+ if(swlib_set_attr_string(dev, a, cport, cvalue) < 0)
+ {
+ fprintf(stderr, "failed\n");
+ retval = -1;
+ goto out;
+ }
+ break;
+ case CMD_GET:
+ if(cvlan > -1)
+ val.port_vlan = cvlan;
+ if(cport > -1)
+ val.port_vlan = cport;
+ if(swlib_get_attr(dev, a, &val) < 0)
+ {
+ fprintf(stderr, "failed\n");
+ retval = -1;
+ goto out;
+ }
+ print_attr_val(a, &val);
+ putchar('\n');
+ break;
+ case CMD_LOAD:
+ swconfig_load_uci(dev, ckey);
+ break;
+ case CMD_HELP:
+ list_attributes(dev);
+ break;
+ case CMD_SHOW:
+ if (cport >= 0 || cvlan >= 0) {
+ if (cport >= 0)
+ show_port(dev, cport);
+ else
+ show_vlan(dev, cvlan, false);
+ } else {
+ show_global(dev);
+ for (i=0; i < dev->ports; i++)
+ show_port(dev, i);
+ for (i=0; i < dev->vlans; i++)
+ show_vlan(dev, i, true);
+ }
+ break;
+ }
+
+out:
+ swlib_free_all(dev);
+ return 0;
+}
diff --git a/package/swconfig/src/swlib.c b/package/swconfig/src/swlib.c
new file mode 100644
index 000000000..de08717e3
--- /dev/null
+++ b/package/swconfig/src/swlib.c
@@ -0,0 +1,686 @@
+/*
+ * swlib.c: Switch configuration API (user space part)
+ *
+ * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <linux/switch.h>
+#include "swlib.h"
+#include <netlink/netlink.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+
+//#define DEBUG 1
+#ifdef DEBUG
+#define DPRINTF(fmt, ...) fprintf(stderr, "%s(%d): " fmt, __func__, __LINE__, ##__VA_ARGS__)
+#else
+#define DPRINTF(fmt, ...) do {} while (0)
+#endif
+
+static struct nl_sock *handle;
+static struct nl_cache *cache;
+static struct genl_family *family;
+static struct nlattr *tb[SWITCH_ATTR_MAX + 1];
+static int refcount = 0;
+
+static struct nla_policy port_policy[] = {
+ [SWITCH_PORT_ID] = { .type = NLA_U32 },
+ [SWITCH_PORT_FLAG_TAGGED] = { .type = NLA_FLAG },
+};
+
+static inline void *
+swlib_alloc(size_t size)
+{
+ void *ptr;
+
+ ptr = malloc(size);
+ if (!ptr)
+ goto done;
+ memset(ptr, 0, size);
+
+done:
+ return ptr;
+}
+
+static int
+wait_handler(struct nl_msg *msg, void *arg)
+{
+ int *finished = arg;
+
+ *finished = 1;
+ return NL_STOP;
+}
+
+/* helper function for performing netlink requests */
+static int
+swlib_call(int cmd, int (*call)(struct nl_msg *, void *),
+ int (*data)(struct nl_msg *, void *), void *arg)
+{
+ struct nl_msg *msg;
+ struct nl_cb *cb = NULL;
+ int finished;
+ int flags = 0;
+ int err;
+
+ msg = nlmsg_alloc();
+ if (!msg) {
+ fprintf(stderr, "Out of memory!\n");
+ exit(1);
+ }
+
+ if (!data)
+ flags |= NLM_F_DUMP;
+
+ genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, genl_family_get_id(family), 0, flags, cmd, 0);
+ if (data) {
+ if (data(msg, arg) < 0)
+ goto nla_put_failure;
+ }
+
+ cb = nl_cb_alloc(NL_CB_CUSTOM);
+ if (!cb) {
+ fprintf(stderr, "nl_cb_alloc failed.\n");
+ exit(1);
+ }
+
+ err = nl_send_auto_complete(handle, msg);
+ if (err < 0) {
+ fprintf(stderr, "nl_send_auto_complete failed: %d\n", err);
+ goto out;
+ }
+
+ finished = 0;
+
+ if (call)
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, call, arg);
+
+ if (data)
+ nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, wait_handler, &finished);
+ else
+ nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, wait_handler, &finished);
+
+ err = nl_recvmsgs(handle, cb);
+ if (err < 0) {
+ goto out;
+ }
+
+ if (!finished)
+ err = nl_wait_for_ack(handle);
+
+out:
+ if (cb)
+ nl_cb_put(cb);
+nla_put_failure:
+ nlmsg_free(msg);
+ return err;
+}
+
+static int
+send_attr(struct nl_msg *msg, void *arg)
+{
+ struct switch_val *val = arg;
+ struct switch_attr *attr = val->attr;
+
+ NLA_PUT_U32(msg, SWITCH_ATTR_ID, attr->dev->id);
+ NLA_PUT_U32(msg, SWITCH_ATTR_OP_ID, attr->id);
+ switch(attr->atype) {
+ case SWLIB_ATTR_GROUP_PORT:
+ NLA_PUT_U32(msg, SWITCH_ATTR_OP_PORT, val->port_vlan);
+ break;
+ case SWLIB_ATTR_GROUP_VLAN:
+ NLA_PUT_U32(msg, SWITCH_ATTR_OP_VLAN, val->port_vlan);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
+static int
+store_port_val(struct nl_msg *msg, struct nlattr *nla, struct switch_val *val)
+{
+ struct nlattr *p;
+ int ports = val->attr->dev->ports;
+ int err = 0;
+ int remaining;
+
+ if (!val->value.ports)
+ val->value.ports = malloc(sizeof(struct switch_port) * ports);
+
+ nla_for_each_nested(p, nla, remaining) {
+ struct nlattr *tb[SWITCH_PORT_ATTR_MAX+1];
+ struct switch_port *port;
+
+ if (val->len >= ports)
+ break;
+
+ err = nla_parse_nested(tb, SWITCH_PORT_ATTR_MAX, p, port_policy);
+ if (err < 0)
+ goto out;
+
+ if (!tb[SWITCH_PORT_ID])
+ continue;
+
+ port = &val->value.ports[val->len];
+ port->id = nla_get_u32(tb[SWITCH_PORT_ID]);
+ port->flags = 0;
+ if (tb[SWITCH_PORT_FLAG_TAGGED])
+ port->flags |= SWLIB_PORT_FLAG_TAGGED;
+
+ val->len++;
+ }
+
+out:
+ return err;
+}
+
+static int
+store_val(struct nl_msg *msg, void *arg)
+{
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct switch_val *val = arg;
+ struct switch_attr *attr = val->attr;
+
+ if (!val)
+ goto error;
+
+ if (nla_parse(tb, SWITCH_ATTR_MAX - 1, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL) < 0) {
+ goto error;
+ }
+
+ if (tb[SWITCH_ATTR_OP_VALUE_INT])
+ val->value.i = nla_get_u32(tb[SWITCH_ATTR_OP_VALUE_INT]);
+ else if (tb[SWITCH_ATTR_OP_VALUE_STR])
+ val->value.s = strdup(nla_get_string(tb[SWITCH_ATTR_OP_VALUE_STR]));
+ else if (tb[SWITCH_ATTR_OP_VALUE_PORTS])
+ val->err = store_port_val(msg, tb[SWITCH_ATTR_OP_VALUE_PORTS], val);
+
+ val->err = 0;
+ return 0;
+
+error:
+ return NL_SKIP;
+}
+
+int
+swlib_get_attr(struct switch_dev *dev, struct switch_attr *attr, struct switch_val *val)
+{
+ int cmd;
+ int err;
+
+ switch(attr->atype) {
+ case SWLIB_ATTR_GROUP_GLOBAL:
+ cmd = SWITCH_CMD_GET_GLOBAL;
+ break;
+ case SWLIB_ATTR_GROUP_PORT:
+ cmd = SWITCH_CMD_GET_PORT;
+ break;
+ case SWLIB_ATTR_GROUP_VLAN:
+ cmd = SWITCH_CMD_GET_VLAN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ memset(&val->value, 0, sizeof(val->value));
+ val->len = 0;
+ val->attr = attr;
+ val->err = -EINVAL;
+ err = swlib_call(cmd, store_val, send_attr, val);
+ if (!err)
+ err = val->err;
+
+ return err;
+}
+
+static int
+send_attr_ports(struct nl_msg *msg, struct switch_val *val)
+{
+ struct nlattr *n;
+ int i;
+
+ /* TODO implement multipart? */
+ if (val->len == 0)
+ goto done;
+ n = nla_nest_start(msg, SWITCH_ATTR_OP_VALUE_PORTS);
+ if (!n)
+ goto nla_put_failure;
+ for (i = 0; i < val->len; i++) {
+ struct switch_port *port = &val->value.ports[i];
+ struct nlattr *np;
+
+ np = nla_nest_start(msg, SWITCH_ATTR_PORT);
+ if (!np)
+ goto nla_put_failure;
+
+ NLA_PUT_U32(msg, SWITCH_PORT_ID, port->id);
+ if (port->flags & SWLIB_PORT_FLAG_TAGGED)
+ NLA_PUT_FLAG(msg, SWITCH_PORT_FLAG_TAGGED);
+
+ nla_nest_end(msg, np);
+ }
+ nla_nest_end(msg, n);
+done:
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
+static int
+send_attr_val(struct nl_msg *msg, void *arg)
+{
+ struct switch_val *val = arg;
+ struct switch_attr *attr = val->attr;
+
+ if (send_attr(msg, arg))
+ goto nla_put_failure;
+
+ switch(attr->type) {
+ case SWITCH_TYPE_NOVAL:
+ break;
+ case SWITCH_TYPE_INT:
+ NLA_PUT_U32(msg, SWITCH_ATTR_OP_VALUE_INT, val->value.i);
+ break;
+ case SWITCH_TYPE_STRING:
+ if (!val->value.s)
+ goto nla_put_failure;
+ NLA_PUT_STRING(msg, SWITCH_ATTR_OP_VALUE_STR, val->value.s);
+ break;
+ case SWITCH_TYPE_PORTS:
+ if (send_attr_ports(msg, val) < 0)
+ goto nla_put_failure;
+ break;
+ default:
+ goto nla_put_failure;
+ }
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
+int
+swlib_set_attr(struct switch_dev *dev, struct switch_attr *attr, struct switch_val *val)
+{
+ int cmd;
+
+ switch(attr->atype) {
+ case SWLIB_ATTR_GROUP_GLOBAL:
+ cmd = SWITCH_CMD_SET_GLOBAL;
+ break;
+ case SWLIB_ATTR_GROUP_PORT:
+ cmd = SWITCH_CMD_SET_PORT;
+ break;
+ case SWLIB_ATTR_GROUP_VLAN:
+ cmd = SWITCH_CMD_SET_VLAN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ val->attr = attr;
+ return swlib_call(cmd, NULL, send_attr_val, val);
+}
+
+int swlib_set_attr_string(struct switch_dev *dev, struct switch_attr *a, int port_vlan, const char *str)
+{
+ struct switch_port *ports;
+ struct switch_val val;
+ char *ptr;
+
+ memset(&val, 0, sizeof(val));
+ val.port_vlan = port_vlan;
+ switch(a->type) {
+ case SWITCH_TYPE_INT:
+ val.value.i = atoi(str);
+ break;
+ case SWITCH_TYPE_STRING:
+ val.value.s = str;
+ break;
+ case SWITCH_TYPE_PORTS:
+ ports = alloca(sizeof(struct switch_port) * dev->ports);
+ memset(ports, 0, sizeof(struct switch_port) * dev->ports);
+ val.len = 0;
+ ptr = (char *)str;
+ while(ptr && *ptr)
+ {
+ while(*ptr && isspace(*ptr))
+ ptr++;
+
+ if (!*ptr)
+ break;
+
+ if (!isdigit(*ptr))
+ return -1;
+
+ if (val.len >= dev->ports)
+ return -1;
+
+ ports[val.len].flags = 0;
+ ports[val.len].id = strtoul(ptr, &ptr, 10);
+ while(*ptr && !isspace(*ptr)) {
+ if (*ptr == 't')
+ ports[val.len].flags |= SWLIB_PORT_FLAG_TAGGED;
+ else
+ return -1;
+
+ ptr++;
+ }
+ if (*ptr)
+ ptr++;
+ val.len++;
+ }
+ val.value.ports = ports;
+ break;
+ case SWITCH_TYPE_NOVAL:
+ if (str && !strcmp(str, "0"))
+ return 0;
+
+ break;
+ default:
+ return -1;
+ }
+ return swlib_set_attr(dev, a, &val);
+}
+
+
+struct attrlist_arg {
+ int id;
+ int atype;
+ struct switch_dev *dev;
+ struct switch_attr *prev;
+ struct switch_attr **head;
+};
+
+static int
+add_id(struct nl_msg *msg, void *arg)
+{
+ struct attrlist_arg *l = arg;
+
+ NLA_PUT_U32(msg, SWITCH_ATTR_ID, l->id);
+
+ return 0;
+nla_put_failure:
+ return -1;
+}
+
+static int
+add_attr(struct nl_msg *msg, void *ptr)
+{
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct attrlist_arg *arg = ptr;
+ struct switch_attr *new;
+
+ if (nla_parse(tb, SWITCH_ATTR_MAX - 1, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL) < 0)
+ goto done;
+
+ new = swlib_alloc(sizeof(struct switch_attr));
+ if (!new)
+ goto done;
+
+ new->dev = arg->dev;
+ new->atype = arg->atype;
+ if (arg->prev) {
+ arg->prev->next = new;
+ } else {
+ arg->prev = *arg->head;
+ }
+ *arg->head = new;
+ arg->head = &new->next;
+
+ if (tb[SWITCH_ATTR_OP_ID])
+ new->id = nla_get_u32(tb[SWITCH_ATTR_OP_ID]);
+ if (tb[SWITCH_ATTR_OP_TYPE])
+ new->type = nla_get_u32(tb[SWITCH_ATTR_OP_TYPE]);
+ if (tb[SWITCH_ATTR_OP_NAME])
+ new->name = strdup(nla_get_string(tb[SWITCH_ATTR_OP_NAME]));
+ if (tb[SWITCH_ATTR_OP_DESCRIPTION])
+ new->description = strdup(nla_get_string(tb[SWITCH_ATTR_OP_DESCRIPTION]));
+
+done:
+ return NL_SKIP;
+}
+
+int
+swlib_scan(struct switch_dev *dev)
+{
+ struct attrlist_arg arg;
+
+ if (dev->ops || dev->port_ops || dev->vlan_ops)
+ return 0;
+
+ arg.atype = SWLIB_ATTR_GROUP_GLOBAL;
+ arg.dev = dev;
+ arg.id = dev->id;
+ arg.prev = NULL;
+ arg.head = &dev->ops;
+ swlib_call(SWITCH_CMD_LIST_GLOBAL, add_attr, add_id, &arg);
+
+ arg.atype = SWLIB_ATTR_GROUP_PORT;
+ arg.prev = NULL;
+ arg.head = &dev->port_ops;
+ swlib_call(SWITCH_CMD_LIST_PORT, add_attr, add_id, &arg);
+
+ arg.atype = SWLIB_ATTR_GROUP_VLAN;
+ arg.prev = NULL;
+ arg.head = &dev->vlan_ops;
+ swlib_call(SWITCH_CMD_LIST_VLAN, add_attr, add_id, &arg);
+
+ return 0;
+}
+
+struct switch_attr *swlib_lookup_attr(struct switch_dev *dev,
+ enum swlib_attr_group atype, const char *name)
+{
+ struct switch_attr *head;
+
+ if (!name || !dev)
+ return NULL;
+
+ switch(atype) {
+ case SWLIB_ATTR_GROUP_GLOBAL:
+ head = dev->ops;
+ break;
+ case SWLIB_ATTR_GROUP_PORT:
+ head = dev->port_ops;
+ break;
+ case SWLIB_ATTR_GROUP_VLAN:
+ head = dev->vlan_ops;
+ break;
+ }
+ while(head) {
+ if (!strcmp(name, head->name))
+ return head;
+ head = head->next;
+ }
+
+ return NULL;
+}
+
+static void
+swlib_priv_free(void)
+{
+ if (cache)
+ nl_cache_free(cache);
+ if (handle)
+ nl_socket_free(handle);
+ handle = NULL;
+ cache = NULL;
+}
+
+static int
+swlib_priv_init(void)
+{
+ int ret;
+
+ handle = nl_socket_alloc();
+ if (!handle) {
+ DPRINTF("Failed to create handle\n");
+ goto err;
+ }
+
+ if (genl_connect(handle)) {
+ DPRINTF("Failed to connect to generic netlink\n");
+ goto err;
+ }
+
+ ret = genl_ctrl_alloc_cache(handle, &cache);
+ if (ret < 0) {
+ DPRINTF("Failed to allocate netlink cache\n");
+ goto err;
+ }
+
+ family = genl_ctrl_search_by_name(cache, "switch");
+ if (!family) {
+ DPRINTF("Switch API not present\n");
+ goto err;
+ }
+ return 0;
+
+err:
+ swlib_priv_free();
+ return -EINVAL;
+}
+
+struct swlib_scan_arg {
+ const char *name;
+ struct switch_dev *head;
+ struct switch_dev *ptr;
+};
+
+static int
+add_switch(struct nl_msg *msg, void *arg)
+{
+ struct swlib_scan_arg *sa = arg;
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct switch_dev *dev;
+ const char *name;
+ const char *alias;
+
+ if (nla_parse(tb, SWITCH_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL) < 0)
+ goto done;
+
+ if (!tb[SWITCH_ATTR_DEV_NAME])
+ goto done;
+
+ name = nla_get_string(tb[SWITCH_ATTR_DEV_NAME]);
+ alias = nla_get_string(tb[SWITCH_ATTR_ALIAS]);
+
+ if (sa->name && (strcmp(name, sa->name) != 0) && (strcmp(alias, sa->name) != 0))
+ goto done;
+
+ dev = swlib_alloc(sizeof(struct switch_dev));
+ if (!dev)
+ goto done;
+
+ strncpy(dev->dev_name, name, IFNAMSIZ - 1);
+ dev->alias = strdup(alias);
+ if (tb[SWITCH_ATTR_ID])
+ dev->id = nla_get_u32(tb[SWITCH_ATTR_ID]);
+ if (tb[SWITCH_ATTR_NAME])
+ dev->name = strdup(nla_get_string(tb[SWITCH_ATTR_NAME]));
+ if (tb[SWITCH_ATTR_PORTS])
+ dev->ports = nla_get_u32(tb[SWITCH_ATTR_PORTS]);
+ if (tb[SWITCH_ATTR_VLANS])
+ dev->vlans = nla_get_u32(tb[SWITCH_ATTR_VLANS]);
+ if (tb[SWITCH_ATTR_CPU_PORT])
+ dev->cpu_port = nla_get_u32(tb[SWITCH_ATTR_CPU_PORT]);
+
+ if (!sa->head) {
+ sa->head = dev;
+ sa->ptr = dev;
+ } else {
+ sa->ptr->next = dev;
+ sa->ptr = dev;
+ }
+
+ refcount++;
+done:
+ return NL_SKIP;
+}
+
+
+struct switch_dev *
+swlib_connect(const char *name)
+{
+ struct swlib_scan_arg arg;
+ int err;
+
+ if (!refcount) {
+ if (swlib_priv_init() < 0)
+ return NULL;
+ };
+
+ arg.head = NULL;
+ arg.ptr = NULL;
+ arg.name = name;
+ swlib_call(SWITCH_CMD_GET_SWITCH, add_switch, NULL, &arg);
+
+ if (!refcount)
+ swlib_priv_free();
+
+ return arg.head;
+}
+
+static void
+swlib_free_attributes(struct switch_attr **head)
+{
+ struct switch_attr *a = *head;
+ struct switch_attr *next;
+
+ while (a) {
+ next = a->next;
+ free(a);
+ a = next;
+ }
+ *head = NULL;
+}
+
+void
+swlib_free(struct switch_dev *dev)
+{
+ swlib_free_attributes(&dev->ops);
+ swlib_free_attributes(&dev->port_ops);
+ swlib_free_attributes(&dev->vlan_ops);
+ free(dev);
+
+ if (--refcount == 0)
+ swlib_priv_free();
+}
+
+void
+swlib_free_all(struct switch_dev *dev)
+{
+ struct switch_dev *p;
+
+ while (dev) {
+ p = dev->next;
+ swlib_free(dev);
+ dev = p;
+ }
+}
diff --git a/package/swconfig/src/swlib.h b/package/swconfig/src/swlib.h
new file mode 100644
index 000000000..ff73969c8
--- /dev/null
+++ b/package/swconfig/src/swlib.h
@@ -0,0 +1,234 @@
+/*
+ * swlib.h: Switch configuration API (user space part)
+ *
+ * Copyright (C) 2008-2009 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 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.
+ *
+
+Usage of the library functions:
+
+ The main datastructure for a switch is the struct switch_device
+ To get started, you first need to use switch_connect() to probe
+ for switches and allocate an instance of this struct.
+
+ There are two possible usage modes:
+ dev = switch_connect("eth0");
+ - this call will look for a switch registered for the linux device
+ "eth0" and only allocate a switch_device for this particular switch.
+
+ dev = switch_connect(NULL)
+ - this will return one switch_device struct for each available
+ switch. The switch_device structs are chained with by ->next pointer
+
+ Then to query a switch for all available attributes, use:
+ swlib_scan(dev);
+
+ All allocated datastructures for the switch_device struct can be freed with
+ swlib_free(dev);
+ or
+ swlib_free_all(dev);
+
+ The latter traverses a whole chain of switch_device structs and frees them all
+
+ Switch attributes (struct switch_attr) are divided into three groups:
+ dev->ops:
+ - global settings
+ dev->port_ops:
+ - per-port settings
+ dev->vlan_ops:
+ - per-vlan settings
+
+ switch_lookup_attr() is a small helper function to locate attributes
+ by name.
+
+ switch_set_attr() and switch_get_attr() can alter or request the values
+ of attributes.
+
+Usage of the switch_attr struct:
+
+ ->atype: attribute group, one of:
+ - SWLIB_ATTR_GROUP_GLOBAL
+ - SWLIB_ATTR_GROUP_VLAN
+ - SWLIB_ATTR_GROUP_PORT
+
+ ->id: identifier for the attribute
+
+ ->type: data type, one of:
+ - SWITCH_TYPE_INT
+ - SWITCH_TYPE_STRING
+ - SWITCH_TYPE_PORT
+
+ ->name: short name of the attribute
+ ->description: longer description
+ ->next: pointer to the next attribute of the current group
+
+
+Usage of the switch_val struct:
+
+ When setting attributes, following members of the struct switch_val need
+ to be set up:
+
+ ->len (for attr->type == SWITCH_TYPE_PORT)
+ ->port_vlan:
+ - port number (for attr->atype == SWLIB_ATTR_GROUP_PORT), or:
+ - vlan number (for attr->atype == SWLIB_ATTR_GROUP_VLAN)
+ ->value.i (for attr->type == SWITCH_TYPE_INT)
+ ->value.s (for attr->type == SWITCH_TYPE_STRING)
+ - owned by the caller, not stored in the library internally
+ ->value.ports (for attr->type == SWITCH_TYPE_PORT)
+ - must point to an array of at lest val->len * sizeof(struct switch_port)
+
+ When getting string attributes, val->value.s must be freed by the caller
+ When getting port list attributes, an internal static buffer is used,
+ which changes from call to call.
+
+ */
+
+#ifndef __SWLIB_H
+#define __SWLIB_H
+
+enum swlib_attr_group {
+ SWLIB_ATTR_GROUP_GLOBAL,
+ SWLIB_ATTR_GROUP_VLAN,
+ SWLIB_ATTR_GROUP_PORT,
+};
+
+enum swlib_port_flags {
+ SWLIB_PORT_FLAG_TAGGED = (1 << 0),
+};
+
+
+struct switch_dev;
+struct switch_attr;
+struct switch_port;
+struct switch_val;
+struct uci_package;
+
+struct switch_dev {
+ int id;
+ char dev_name[IFNAMSIZ];
+ const char *name;
+ const char *alias;
+ int ports;
+ int vlans;
+ int cpu_port;
+ struct switch_attr *ops;
+ struct switch_attr *port_ops;
+ struct switch_attr *vlan_ops;
+ struct switch_dev *next;
+ void *priv;
+};
+
+struct switch_val {
+ struct switch_attr *attr;
+ int len;
+ int err;
+ int port_vlan;
+ union {
+ const char *s;
+ int i;
+ struct switch_port *ports;
+ } value;
+};
+
+struct switch_attr {
+ struct switch_dev *dev;
+ int atype;
+ int id;
+ int type;
+ const char *name;
+ const char *description;
+ struct switch_attr *next;
+};
+
+struct switch_port {
+ unsigned int id;
+ unsigned int flags;
+};
+
+/**
+ * swlib_connect: connect to the switch through netlink
+ * @name: name of the ethernet interface,
+ *
+ * if name is NULL, it connect and builds a chain of all switches
+ */
+struct switch_dev *swlib_connect(const char *name);
+
+/**
+ * swlib_free: free all dynamically allocated data for the switch connection
+ * @dev: switch device struct
+ *
+ * all members of a switch device chain (generated by swlib_connect(NULL))
+ * must be freed individually
+ */
+void swlib_free(struct switch_dev *dev);
+
+/**
+ * swlib_free_all: run swlib_free on all devices in the chain
+ * @dev: switch device struct
+ */
+void swlib_free_all(struct switch_dev *dev);
+
+/**
+ * swlib_scan: probe the switch driver for available commands/attributes
+ * @dev: switch device struct
+ */
+int swlib_scan(struct switch_dev *dev);
+
+/**
+ * swlib_lookup_attr: look up a switch attribute
+ * @dev: switch device struct
+ * @type: global, port or vlan
+ * @name: name of the attribute
+ */
+struct switch_attr *swlib_lookup_attr(struct switch_dev *dev,
+ enum swlib_attr_group atype, const char *name);
+
+/**
+ * swlib_set_attr: set the value for an attribute
+ * @dev: switch device struct
+ * @attr: switch attribute struct
+ * @val: attribute value pointer
+ * returns 0 on success
+ */
+int swlib_set_attr(struct switch_dev *dev, struct switch_attr *attr,
+ struct switch_val *val);
+
+/**
+ * swlib_set_attr_string: set the value for an attribute with type conversion
+ * @dev: switch device struct
+ * @attr: switch attribute struct
+ * @port_vlan: port or vlan (if applicable)
+ * @str: string value
+ * returns 0 on success
+ */
+int swlib_set_attr_string(struct switch_dev *dev, struct switch_attr *attr,
+ int port_vlan, const char *str);
+
+/**
+ * swlib_get_attr: get the value for an attribute
+ * @dev: switch device struct
+ * @attr: switch attribute struct
+ * @val: attribute value pointer
+ * returns 0 on success
+ * for string attributes, the result string must be freed by the caller
+ */
+int swlib_get_attr(struct switch_dev *dev, struct switch_attr *attr,
+ struct switch_val *val);
+
+/**
+ * swlib_apply_from_uci: set up the switch from a uci configuration
+ * @dev: switch device struct
+ * @p: uci package which contains the desired global config
+ */
+int swlib_apply_from_uci(struct switch_dev *dev, struct uci_package *p);
+
+#endif
diff --git a/package/swconfig/src/uci.c b/package/swconfig/src/uci.c
new file mode 100644
index 000000000..893e3d1dd
--- /dev/null
+++ b/package/swconfig/src/uci.c
@@ -0,0 +1,248 @@
+/*
+ * uci.c: UCI binding for the switch configuration utility
+ *
+ * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+ *
+ * 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 Foundatio.
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <uci.h>
+
+#include <linux/types.h>
+#include <linux/netlink.h>
+#include <linux/genetlink.h>
+#include <netlink/netlink.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/ctrl.h>
+#include <linux/switch.h>
+#include "swlib.h"
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+#endif
+
+struct swlib_setting {
+ struct switch_attr *attr;
+ const char *name;
+ int port_vlan;
+ const char *val;
+ struct swlib_setting *next;
+};
+
+struct swlib_setting early_settings[] = {
+ { .name = "reset", .val = "1" },
+ { .name = "enable_vlan", .val = "1" },
+};
+
+static struct swlib_setting *settings;
+static struct swlib_setting **head;
+
+static bool swlib_match_name(struct switch_dev *dev, const char *name)
+{
+ return (strcmp(name, dev->dev_name) == 0 ||
+ strcmp(name, dev->alias) == 0);
+}
+
+static int
+swlib_map_settings(struct switch_dev *dev, int type, int port_vlan, struct uci_section *s)
+{
+ struct swlib_setting *setting;
+ struct switch_attr *attr;
+ struct uci_element *e;
+ struct uci_option *o;
+ int i;
+
+ uci_foreach_element(&s->options, e) {
+ o = uci_to_option(e);
+
+ if (o->type != UCI_TYPE_STRING)
+ continue;
+
+ if (!strcmp(e->name, "device"))
+ continue;
+
+ /* map early settings */
+ if (type == SWLIB_ATTR_GROUP_GLOBAL) {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(early_settings); i++) {
+ if (strcmp(e->name, early_settings[i].name) != 0)
+ continue;
+
+ early_settings[i].val = o->v.string;
+ goto skip;
+ }
+ }
+
+ attr = swlib_lookup_attr(dev, type, e->name);
+ if (!attr)
+ continue;
+
+ setting = malloc(sizeof(struct swlib_setting));
+ memset(setting, 0, sizeof(struct swlib_setting));
+ setting->attr = attr;
+ setting->port_vlan = port_vlan;
+ setting->val = o->v.string;
+ *head = setting;
+ head = &setting->next;
+skip:
+ continue;
+ }
+}
+
+int swlib_apply_from_uci(struct switch_dev *dev, struct uci_package *p)
+{
+ struct switch_attr *attr;
+ struct uci_context *ctx = p->ctx;
+ struct uci_element *e;
+ struct uci_section *s;
+ struct uci_option *o;
+ struct uci_ptr ptr;
+ struct switch_val val;
+ int i;
+
+ settings = NULL;
+ head = &settings;
+
+ uci_foreach_element(&p->sections, e) {
+ struct uci_element *n;
+
+ s = uci_to_section(e);
+
+ if (strcmp(s->type, "switch") != 0)
+ continue;
+
+ uci_foreach_element(&s->options, n) {
+ struct uci_option *o = uci_to_option(n);
+
+ if (strcmp(n->name, "name") != 0)
+ continue;
+
+ if (o->type != UCI_TYPE_STRING)
+ continue;
+
+ if (swlib_match_name(dev, o->v.string))
+ goto found;
+
+ break;
+ }
+
+ if (!swlib_match_name(dev, e->name))
+ continue;
+
+ goto found;
+ }
+
+ /* not found */
+ return -1;
+
+found:
+ /* look up available early options, which need to be taken care
+ * of in the correct order */
+ for (i = 0; i < ARRAY_SIZE(early_settings); i++) {
+ early_settings[i].attr = swlib_lookup_attr(dev,
+ SWLIB_ATTR_GROUP_GLOBAL, early_settings[i].name);
+ }
+ swlib_map_settings(dev, SWLIB_ATTR_GROUP_GLOBAL, 0, s);
+
+ /* look for port or vlan sections */
+ uci_foreach_element(&p->sections, e) {
+ struct uci_element *os;
+ s = uci_to_section(e);
+
+ if (!strcmp(s->type, "switch_port")) {
+ char *devn, *port, *port_err = NULL;
+ int port_n;
+
+ uci_foreach_element(&s->options, os) {
+ o = uci_to_option(os);
+ if (o->type != UCI_TYPE_STRING)
+ continue;
+
+ if (!strcmp(os->name, "device")) {
+ devn = o->v.string;
+ if (!swlib_match_name(dev, devn))
+ devn = NULL;
+ } else if (!strcmp(os->name, "port")) {
+ port = o->v.string;
+ }
+ }
+ if (!devn || !port || !port[0])
+ continue;
+
+ port_n = strtoul(port, &port_err, 0);
+ if (port_err && port_err[0])
+ continue;
+
+ swlib_map_settings(dev, SWLIB_ATTR_GROUP_PORT, port_n, s);
+ } else if (!strcmp(s->type, "switch_vlan")) {
+ char *devn, *vlan, *vlan_err = NULL;
+ int vlan_n;
+
+ uci_foreach_element(&s->options, os) {
+ o = uci_to_option(os);
+ if (o->type != UCI_TYPE_STRING)
+ continue;
+
+ if (!strcmp(os->name, "device")) {
+ devn = o->v.string;
+ if (!swlib_match_name(dev, devn))
+ devn = NULL;
+ } else if (!strcmp(os->name, "vlan")) {
+ vlan = o->v.string;
+ }
+ }
+ if (!devn || !vlan || !vlan[0])
+ continue;
+
+ vlan_n = strtoul(vlan, &vlan_err, 0);
+ if (vlan_err && vlan_err[0])
+ continue;
+
+ swlib_map_settings(dev, SWLIB_ATTR_GROUP_VLAN, vlan_n, s);
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(early_settings); i++) {
+ struct swlib_setting *st = &early_settings[i];
+ if (!st->attr || !st->val)
+ continue;
+ swlib_set_attr_string(dev, st->attr, st->port_vlan, st->val);
+
+ }
+
+ while (settings) {
+ struct swlib_setting *st = settings;
+
+ swlib_set_attr_string(dev, st->attr, st->port_vlan, st->val);
+ st = st->next;
+ free(settings);
+ settings = st;
+ }
+
+ /* Apply the config */
+ attr = swlib_lookup_attr(dev, SWLIB_ATTR_GROUP_GLOBAL, "apply");
+ if (!attr)
+ return 0;
+
+ memset(&val, 0, sizeof(val));
+ swlib_set_attr(dev, attr, &val);
+
+ return 0;
+}
diff --git a/package/switch/Makefile b/package/switch/Makefile
new file mode 100644
index 000000000..2b036b07d
--- /dev/null
+++ b/package/switch/Makefile
@@ -0,0 +1,59 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=kmod-switch
+PKG_RELEASE:=5
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/switch
+ SUBMENU:=Other modules
+ DEPENDS:=@TARGET_brcm47xx||TARGET_brcm63xx
+ TITLE:=Switch drivers
+ FILES:= \
+ $(PKG_BUILD_DIR)/switch-core.ko \
+ $(PKG_BUILD_DIR)/switch-adm.ko \
+ $(PKG_BUILD_DIR)/switch-robo.ko
+ AUTOLOAD:=$(call AutoLoad,20,switch-core switch-robo switch-adm)
+endef
+
+define KernelPackage/switch/description
+ This package contains switch drivers for ADM6996L and BCM53XX RoboSwitch.
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ $(MAKE) -C "$(LINUX_DIR)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ ARCH="$(LINUX_KARCH)" \
+ SUBDIRS="$(PKG_BUILD_DIR)" \
+ EXTRA_CFLAGS="$(BUILDFLAGS)" \
+ modules
+endef
+
+define Build/InstallDev
+ mkdir -p $(1)/usr/include
+ $(CP) ./src/switch-core.h $(1)/usr/include/
+endef
+
+define Build/UninstallDev
+ rm -f $(1)/usr/include/switch-core.h
+endef
+
+define KernelPackage/switch/install
+ $(INSTALL_DIR) $(1)/lib/network/
+ $(INSTALL_BIN) ./files/switch.sh $(1)/lib/network/
+endef
+
+$(eval $(call KernelPackage,switch))
diff --git a/package/switch/files/switch.sh b/package/switch/files/switch.sh
new file mode 100644
index 000000000..2563d410e
--- /dev/null
+++ b/package/switch/files/switch.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+# Copyright (C) 2006-2010 OpenWrt.org
+
+setup_switch_hw() {
+ local dev="$1"
+ local enable reset evlan
+
+ config_get_bool enable "$dev" enable 1
+ config_get_bool evlan "$dev" enable_vlan 1
+ config_get_bool reset "$dev" reset 1
+
+ local proc="/proc/switch/$dev"
+ [ -d "$proc" ] && {
+ ifconfig "$dev" up
+ echo "$reset" > "$proc/reset"
+ echo "$evlan" > "$proc/enable_vlan"
+ [ -f "$proc/enable" ] && echo "$enable" > "$proc/enable"
+ }
+
+ local vlan
+ for vlan in `seq 0 15`; do
+ proc="/proc/switch/$dev/vlan/$vlan/ports"
+ [ -f "$proc" ] && echo "" > "$proc"
+ done
+}
+
+setup_switch_vlan() {
+ local s="$1"
+ local dev vlan ports
+
+ config_get dev "$s" device
+ config_get vlan "$s" vlan
+ config_get ports "$s" ports
+
+ [ -n "$dev" ] && [ -n "$vlan" ] && {
+ ports="${ports%\*}"
+
+ [ "$_vlan_pvid_set" = 1 ] || {
+ ports="$ports*"
+ _vlan_pvid_set=1
+ }
+
+ local proc="/proc/switch/$dev/vlan/$vlan/ports"
+ [ -f "$proc" ] && echo "$ports" > "$proc"
+ }
+}
+
+setup_switch() {
+ _vlan_pvid_set=0
+ config_load network
+ config_foreach setup_switch_hw switch
+ config_foreach setup_switch_vlan switch_vlan
+}
diff --git a/package/switch/src/Makefile b/package/switch/src/Makefile
new file mode 100644
index 000000000..b6934cc66
--- /dev/null
+++ b/package/switch/src/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for switch driver
+#
+# Copyright (C) 2005 Felix Fietkau <nbd@openwrt.org>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+
+obj-m := switch-core.o switch-adm.o switch-robo.o
+
+ifeq ($(MAKING_MODULES),1)
+export-objs := switch-core.o
+
+-include $(TOPDIR)/Rules.make
+endif
diff --git a/package/switch/src/etc53xx.h b/package/switch/src/etc53xx.h
new file mode 100644
index 000000000..d5b1310cb
--- /dev/null
+++ b/package/switch/src/etc53xx.h
@@ -0,0 +1,619 @@
+/*
+ * Broadcom Home Gateway Reference Design
+ * BCM53xx Register definitions
+ *
+ * Copyright 2004, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ */
+
+#ifndef __BCM535M_H_
+#define __BCM535M_H_
+
+/* ROBO embedded device type */
+#define ROBO_DEV_5380 1
+#define ROBO_DEV_5365 2
+#define ROBO_DEV_5350 3
+
+/* BCM5325m GLOBAL PAGE REGISTER MAP */
+#ifndef _CFE_
+#pragma pack(1)
+#endif
+
+/* BCM5325m Serial Management Port (SMP) Page offsets */
+#define ROBO_CTRL_PAGE 0x00 /* Control registers */
+#define ROBO_STAT_PAGE 0x01 /* Status register */
+#define ROBO_MGMT_PAGE 0x02 /* Management Mode registers */
+#define ROBO_MIB_AC_PAGE 0x03 /* MIB Autocast registers */
+#define ROBO_ARLCTRL_PAGE 0x04 /* ARL Control Registers */
+#define ROBO_ARLIO_PAGE 0x05 /* ARL Access Registers */
+#define ROBO_FRAMEBUF_PAGE 0x06 /* Management frame access registers */
+#define ROBO_MEM_ACCESS_PAGE 0x08 /* Memory access registers */
+
+/* PHY Registers */
+#define ROBO_PORT0_MII_PAGE 0x10 /* Port 0 MII Registers */
+#define ROBO_PORT1_MII_PAGE 0x11 /* Port 1 MII Registers */
+#define ROBO_PORT2_MII_PAGE 0x12 /* Port 2 MII Registers */
+#define ROBO_PORT3_MII_PAGE 0x13 /* Port 3 MII Registers */
+#define ROBO_PORT4_MII_PAGE 0x14 /* Port 4 MII Registers */
+/* (start) registers only for BCM5380 */
+#define ROBO_PORT5_MII_PAGE 0x15 /* Port 5 MII Registers */
+#define ROBO_PORT6_MII_PAGE 0x16 /* Port 6 MII Registers */
+#define ROBO_PORT7_MII_PAGE 0x17 /* Port 7 MII Registers */
+/* (end) registers only for BCM5380 */
+#define ROBO_IM_PORT_PAGE 0x18 /* Inverse MII Port (to EMAC) */
+#define ROBO_ALL_PORT_PAGE 0x19 /* All ports MII Registers (broadcast)*/
+
+/* MAC Statistics registers */
+#define ROBO_PORT0_MIB_PAGE 0x20 /* Port 0 10/100 MIB Statistics */
+#define ROBO_PORT1_MIB_PAGE 0x21 /* Port 1 10/100 MIB Statistics */
+#define ROBO_PORT2_MIB_PAGE 0x22 /* Port 2 10/100 MIB Statistics */
+#define ROBO_PORT3_MIB_PAGE 0x23 /* Port 3 10/100 MIB Statistics */
+#define ROBO_PORT4_MIB_PAGE 0x24 /* Port 4 10/100 MIB Statistics */
+/* (start) registers only for BCM5380 */
+#define ROBO_PORT5_MIB_PAGE 0x25 /* Port 5 10/100 MIB Statistics */
+#define ROBO_PORT6_MIB_PAGE 0x26 /* Port 6 10/100 MIB Statistics */
+#define ROBO_PORT7_MIB_PAGE 0x27 /* Port 7 10/100 MIB Statistics */
+/* (end) registers only for BCM5380 */
+#define ROBO_IM_PORT_MIB_PAGE 0x28 /* Inverse MII Port MIB Statistics */
+
+/* Quality of Service (QoS) Registers */
+#define ROBO_QOS_PAGE 0x30 /* QoS Registers */
+
+/* VLAN Registers */
+#define ROBO_VLAN_PAGE 0x34 /* VLAN Registers */
+
+/* Note SPI Data/IO Registers not used */
+#define ROBO_SPI_DATA_IO_0_PAGE 0xf0 /* SPI Data I/O 0 */
+#define ROBO_SPI_DATA_IO_1_PAGE 0xf1 /* SPI Data I/O 1 */
+#define ROBO_SPI_DATA_IO_2_PAGE 0xf2 /* SPI Data I/O 2 */
+#define ROBO_SPI_DATA_IO_3_PAGE 0xf3 /* SPI Data I/O 3 */
+#define ROBO_SPI_DATA_IO_4_PAGE 0xf4 /* SPI Data I/O 4 */
+#define ROBO_SPI_DATA_IO_5_PAGE 0xf5 /* SPI Data I/O 5 */
+#define ROBO_SPI_DATA_IO_6_PAGE 0xf6 /* SPI Data I/O 6 */
+#define ROBO_SPI_DATA_IO_7_PAGE 0xf7 /* SPI Data I/O 7 */
+
+#define ROBO_SPI_STATUS_PAGE 0xfe /* SPI Status Registers */
+#define ROBO_PAGE_PAGE 0xff /* Page Registers */
+
+
+/* BCM5325m CONTROL PAGE (0x00) REGISTER MAP : 8bit (byte) registers */
+typedef struct _ROBO_PORT_CTRL_STRUC
+{
+ unsigned char rx_disable:1; /* rx disable */
+ unsigned char tx_disable:1; /* tx disable */
+ unsigned char rsvd:3; /* reserved */
+ unsigned char stp_state:3; /* spanning tree state */
+} ROBO_PORT_CTRL_STRUC;
+
+#define ROBO_PORT0_CTRL 0x00 /* 10/100 Port 0 Control */
+#define ROBO_PORT1_CTRL 0x01 /* 10/100 Port 1 Control */
+#define ROBO_PORT2_CTRL 0x02 /* 10/100 Port 2 Control */
+#define ROBO_PORT3_CTRL 0x03 /* 10/100 Port 3 Control */
+#define ROBO_PORT4_CTRL 0x04 /* 10/100 Port 4 Control */
+/* (start) registers only for BCM5380 */
+#define ROBO_PORT5_CTRL 0x05 /* 10/100 Port 5 Control */
+#define ROBO_PORT6_CTRL 0x06 /* 10/100 Port 6 Control */
+#define ROBO_PORT7_CTRL 0x07 /* 10/100 Port 7 Control */
+/* (end) registers only for BCM5380 */
+#define ROBO_IM_PORT_CTRL 0x08 /* 10/100 Port 8 Control */
+#define ROBO_SMP_CTRL 0x0a /* SMP Control register */
+#define ROBO_SWITCH_MODE 0x0b /* Switch Mode Control */
+#define ROBO_PORT_OVERRIDE_CTRL 0x0e /* Port state override */
+#define ROBO_PORT_OVERRIDE_RVMII (1<<4) /* Bit 4 enables RvMII */
+#define ROBO_PD_MODE_CTRL 0x0f /* Power-down mode control */
+#define ROBO_IP_MULTICAST_CTRL 0x21 /* IP Multicast control */
+
+/* BCM5325m STATUS PAGE (0x01) REGISTER MAP : 16bit/48bit registers */
+#define ROBO_HALF_DUPLEX 0
+#define ROBO_FULL_DUPLEX 1
+
+#define ROBO_LINK_STAT_SUMMARY 0x00 /* Link Status Summary: 16bit */
+#define ROBO_LINK_STAT_CHANGE 0x02 /* Link Status Change: 16bit */
+#define ROBO_SPEED_STAT_SUMMARY 0x04 /* Port Speed Summary: 16bit*/
+#define ROBO_DUPLEX_STAT_SUMMARY 0x06 /* Duplex Status Summary: 16bit */
+#define ROBO_PAUSE_STAT_SUMMARY 0x08 /* PAUSE Status Summary: 16bit */
+#define ROBO_SOURCE_ADDR_CHANGE 0x0C /* Source Address Change: 16bit */
+#define ROBO_LSA_PORT0 0x10 /* Last Source Addr, Port 0: 48bits*/
+#define ROBO_LSA_PORT1 0x16 /* Last Source Addr, Port 1: 48bits*/
+#define ROBO_LSA_PORT2 0x1c /* Last Source Addr, Port 2: 48bits*/
+#define ROBO_LSA_PORT3 0x22 /* Last Source Addr, Port 3: 48bits*/
+#define ROBO_LSA_PORT4 0x28 /* Last Source Addr, Port 4: 48bits*/
+#define ROBO_LSA_IM_PORT 0x40 /* Last Source Addr, IM Port: 48bits*/
+
+/* BCM5325m MANAGEMENT MODE REGISTERS (0x02) REGISTER MAP: 8/48 bit regs*/
+typedef struct _ROBO_GLOBAL_CONFIG_STRUC
+{
+ unsigned char resetMIB:1; /* reset MIB counters */
+ unsigned char rxBPDU:1; /* receive BDPU enable */
+ unsigned char rsvd1:2; /* reserved */
+ unsigned char MIBacHdrCtrl:1; /* MIB autocast header control */
+ unsigned char MIBac:1; /* MIB autocast enable */
+ unsigned char frameMgmtPort:2; /* frame management port */
+} ROBO_GLOBAL_CONFIG_STRUC;
+#define ROBO_GLOBAL_CONFIG 0x00 /* Global Management Config: 8bit*/
+#define ROBO_MGMT_PORT_ID 0x02 /* Management Port ID: 8bit*/
+#define ROBO_RMON_MIB_STEER 0x04 /* RMON Mib Steering: 16bit */
+#define ROBO_MIB_MODE_SELECT 0x04 /* MIB Mode select: 16bit (BCM5350) */
+#define ROBO_AGE_TIMER_CTRL 0x06 /* Age time control: 32bit */
+#define ROBO_MIRROR_CAP_CTRL 0x10 /* Mirror Capture : 16bit */
+#define ROBO_MIRROR_ING_CTRL 0x12 /* Mirror Ingress Control: 16bit */
+#define ROBO_MIRROR_ING_DIV_CTRL 0x14 /* Mirror Ingress Divider: 16bit */
+#define ROBO_MIRROR_ING_MAC_ADDR 0x16 /* Ingress Mirror MAC Addr: 48bit*/
+#define ROBO_MIRROR_EGR_CTRL 0x1c /* Mirror Egress Control: 16bit */
+#define ROBO_MIRROR_EGR_DIV_CTRL 0x1e /* Mirror Egress Divider: 16bit */
+#define ROBO_MIRROR_EGR_MAC_ADDR 0x20 /* Egress Mirror MAC Addr: 48bit*/
+
+/* BCM5325m MIB AUTOCAST REGISTERS (0x03) REGISTER MAP: 8/16/48 bit regs */
+#define ROBO_MIB_AC_PORT 0x00 /* MIB Autocast Port: 16bit */
+#define ROBO_MIB_AC_HDR_PTR 0x02 /* MIB Autocast Header pointer:16bit*/
+#define ROBO_MIB_AC_HDR_LEN 0x04 /* MIB Autocast Header Len: 16bit */
+#define ROBO_MIB_AC_DA 0x06 /* MIB Autocast DA: 48bit */
+#define ROBO_MIB_AC_SA 0x0c /* MIB Autocast SA: 48bit */
+#define ROBO_MIB_AC_TYPE 0x12 /* MIB Autocast Type: 16bit */
+#define ROBO_MIB_AC_RATE 0x14 /* MIB Autocast Rate: 8bit */
+#define ROBO_GET_AC_RATE(secs) ((secs)*10)
+#define ROBO_AC_RATE_MAX 0xff
+#define ROBO_AC_RATE_DEFAULT 0x64 /* 10 secs */
+typedef struct _ROBO_MIB_AC_STRUCT
+{
+ unsigned char opcode:4; /* Tx MIB Autocast opcode */
+ unsigned char portno:4; /* zero-based port no. */
+ unsigned char portstate:8; /* port state */
+ unsigned long long TxOctets;
+ unsigned int TxDropPkts;
+ unsigned int rsvd;
+ unsigned int TxBroadcastPkts;
+ unsigned int TxMulticastPkts;
+ unsigned int TxUnicastPkts;
+ unsigned int TxCollisions;
+ unsigned int TxSingleCollision;
+ unsigned int TxMultiCollision;
+ unsigned int TxDeferredTransmit;
+ unsigned int TxLateCollision;
+ unsigned int TxExcessiveCollision;
+ unsigned int TxFrameInDiscards;
+ unsigned int TxPausePkts;
+ unsigned int rsvd1[2];
+ unsigned long long RxOctets;
+ unsigned int RxUndersizePkts;
+ unsigned int RxPausePkts;
+ unsigned int RxPkts64Octets;
+ unsigned int RxPkts64to127Octets;
+ unsigned int RxPkts128to255Octets;
+ unsigned int RxPkts256to511Octets;
+ unsigned int RxPkts512to1023Octets;
+ unsigned int RxPkts1024to1522Octets;
+ unsigned int RxOversizePkts;
+ unsigned int RxJabbers;
+ unsigned int RxAlignmentErrors;
+ unsigned int RxFCSErrors;
+ unsigned long long RxGoodOctets;
+ unsigned int RxDropPkts;
+ unsigned int RxUnicastPkts;
+ unsigned int RxMulticastPkts;
+ unsigned int RxBroadcastPkts;
+ unsigned int RxSAChanges;
+ unsigned int RxFragments;
+ unsigned int RxExcessSizeDisc;
+ unsigned int RxSymbolError;
+} ROBO_MIB_AC_STRUCT;
+
+/* BCM5325m ARL CONTROL REGISTERS (0x04) REGISTER MAP: 8/16/48/64 bit regs */
+#define ROBO_ARL_CONFIG 0x00 /* ARL Global Configuration: 8bit*/
+#define ROBO_BPDU_MC_ADDR_REG 0x04 /* BPDU Multicast Address Reg:64bit*/
+#define ROBO_MULTIPORT_ADDR_1 0x10 /* Multiport Address 1: 48 bits*/
+#define ROBO_MULTIPORT_VECTOR_1 0x16 /* Multiport Vector 1: 16 bits */
+#define ROBO_MULTIPORT_ADDR_2 0x20 /* Multiport Address 2: 48 bits*/
+#define ROBO_MULTIPORT_VECTOR_2 0x26 /* Multiport Vector 2: 16 bits */
+#define ROBO_SECURE_SRC_PORT_MASK 0x30 /* Secure Source Port Mask: 16 bits*/
+#define ROBO_SECURE_DST_PORT_MASK 0x32 /* Secure Dest Port Mask: 16 bits */
+
+
+/* BCM5325m ARL IO REGISTERS (0x05) REGISTER MAP: 8/16/48/64 bit regs */
+#define ARL_TABLE_WRITE 0 /* for read/write state in control reg */
+#define ARL_TABLE_READ 1 /* for read/write state in control reg */
+#ifdef BCM5380
+#define ARL_VID_BYTES 2 /* number of bytes for VID */
+#else
+#define ARL_VID_BYTES 1 /* number of bytes for VID */
+#endif
+typedef struct _ROBO_ARL_RW_CTRL_STRUC
+{
+ unsigned char ARLrw:1; /* ARL read/write (1=read) */
+ unsigned char rsvd:6; /* reserved */
+ unsigned char ARLStart:1; /* ARL start/done (1=start) */
+} ROBO_ARL_RW_CTRL_STRUC;
+typedef struct _ROBO_ARL_SEARCH_CTRL_STRUC
+{
+ unsigned char valid:1; /* ARL search result valid */
+ unsigned char rsvd:6; /* reserved */
+ unsigned char ARLStart:1; /* ARL start/done (1=start) */
+} ROBO_ARL_SEARCH_CTRL_STRUC;
+typedef struct _ROBO_ARL_ENTRY_CTRL_STRUC
+{
+ unsigned char portID:4; /* port id */
+ unsigned char chipID:2; /* chip id */
+ unsigned char rsvd:5; /* reserved */
+ unsigned char prio:2; /* priority */
+ unsigned char age:1; /* age */
+ unsigned char staticEn:1; /* static */
+ unsigned char valid:1; /* valid */
+} ROBO_ARL_ENTRY_CTRL_STRUC;
+typedef struct _ROBO_ARL_SEARCH_RESULT_CTRL_STRUC
+{
+ unsigned char portID:4; /* port id */
+ unsigned char rsvd:1; /* reserved */
+ unsigned char vid:8; /* vlan id */
+ unsigned char age:1; /* age */
+ unsigned char staticEn:1; /* static */
+ unsigned char valid:1; /* valid */
+} ROBO_ARL_SEARCH_RESULT_CTRL_STRUC;
+typedef struct _ROBO_ARL_ENTRY_MAC_STRUC
+{
+ unsigned char macBytes[6]; /* MAC address */
+} ROBO_ARL_ENTRY_MAC_STRUC;
+
+typedef struct _ROBO_ARL_ENTRY_STRUC
+{
+ ROBO_ARL_ENTRY_MAC_STRUC mac; /* MAC address */
+ ROBO_ARL_ENTRY_CTRL_STRUC ctrl; /* control bits */
+} ROBO_ARL_ENTRY_STRUC;
+
+typedef struct _ROBO_ARL_SEARCH_RESULT_STRUC
+{
+ ROBO_ARL_ENTRY_MAC_STRUC mac; /* MAC address */
+ ROBO_ARL_SEARCH_RESULT_CTRL_STRUC ctrl; /* control bits */
+} ROBO_ARL_SEARCH_RESULT_STRUC;
+
+/* multicast versions of ARL entry structs */
+typedef struct _ROBO_ARL_ENTRY_MCAST_CTRL_STRUC
+{
+ unsigned int portMask:12;/* multicast port mask */
+ unsigned char prio:1; /* priority */
+ unsigned char gigPort:1; /* gigabit port 1 mask */
+ unsigned char staticEn:1; /* static */
+ unsigned char valid:1; /* valid */
+} ROBO_ARL_ENTRY_MCAST_CTRL_STRUC;
+typedef struct _ROBO_ARL_SEARCH_RESULT_MCAST_CTRL_STRUC
+{
+ unsigned int portMask:13; /* multicast port mask */
+ unsigned char age:1; /* age */
+ unsigned char staticEn:1; /* static */
+ unsigned char valid:1; /* valid */
+} ROBO_ARL_SEARCH_RESULT_MCAST_CTRL_STRUC;
+/* BCM5350 extension register */
+typedef struct _ROBO_ARL_SEARCH_RESULT_EXTENSION
+{
+ unsigned int prio:2; /* priority */
+ unsigned int portMask:1; /* MSB (MII) of port mask for multicast */
+ unsigned int reserved:5;
+} ROBO_ARL_SEARCH_RESULT_EXTENSION;
+
+typedef struct _ROBO_ARL_ENTRY_MCAST_STRUC
+{
+ ROBO_ARL_ENTRY_MAC_STRUC mac; /* MAC address */
+ ROBO_ARL_ENTRY_MCAST_CTRL_STRUC ctrl; /* control bits */
+} ROBO_ARL_ENTRY_MCAST_STRUC;
+typedef struct _ROBO_ARL_SEARCH_RESULT_MCAST_STRUC
+{
+ ROBO_ARL_ENTRY_MAC_STRUC mac; /* MAC address */
+ ROBO_ARL_SEARCH_RESULT_MCAST_CTRL_STRUC ctrl; /* control bits */
+} ROBO_ARL_SEARCH_RESULT_MCAST_STRUC;
+
+#define ROBO_ARL_RW_CTRL 0x00 /* ARL Read/Write Control : 8bit */
+#define ROBO_ARL_MAC_ADDR_IDX 0x02 /* MAC Address Index: 48bit */
+#define ROBO_ARL_VID_TABLE_IDX 0x08 /* VID Table Address Index: 8bit */
+#define ROBO_ARL_ENTRY0 0x10 /* ARL Entry 0 : 64 bit */
+#define ROBO_ARL_ENTRY1 0x18 /* ARL Entry 1 : 64 bit */
+#define ROBO_ARL_SEARCH_CTRL 0x20 /* ARL Search Control: 8bit */
+#define ROBO_ARL_SEARCH_ADDR 0x22 /* ARL Search Address: 16bit */
+#define ROBO_ARL_SEARCH_RESULT 0x24 /* ARL Search Result: 64bit */
+#define ROBO_ARL_SEARCH_RESULT_EXT 0x2c /* ARL Search Result Extension (5350): 8bit */
+#define ROBO_ARL_VID_ENTRY0 0x30 /* ARL VID Entry 0: 64bit */
+#define ROBO_ARL_VID_ENTRY1 0x32 /* ARL VID Entry 1: 64bit */
+
+/* BCM5325m MANAGEMENT FRAME REGISTERS (0x6) REGISTER MAP: 8/16 bit regs */
+#define ROBO_MGMT_FRAME_RD_DATA 0x00 /* Management Frame Read Data :8bit*/
+#define ROBO_MGMT_FRAME_WR_DATA 0x01 /* Management Frame Write Data:8bit*/
+#define ROBO_MGMT_FRAME_WR_CTRL 0x02 /* Write Control: 16bit */
+#define ROBO_MGMT_FRAME_RD_STAT 0x04 /* Read Status: 16bit */
+
+/* BCM5325m MEMORY ACCESS REGISTERS (Page 0x08) REGISTER MAP: 32 bit regs */
+#define MEM_TABLE_READ 1 /* for read/write state in mem access reg */
+#define MEM_TABLE_WRITE 0 /* for read/write state in mem access reg */
+#define MEM_TABLE_ACCESS_START 1 /* for mem access read/write start */
+#define MEM_TABLE_ACCESS_DONE 0 /* for mem access read/write done */
+#define VLAN_TABLE_ADDR 0x3800 /* BCM5380 only */
+#ifdef BCM5380
+#define NUM_ARL_TABLE_ENTRIES 4096 /* number of entries in ARL table */
+#define NUM_VLAN_TABLE_ENTRIES 2048 /* number of entries in VLAN table */
+#define ARL_TABLE_ADDR 0 /* offset of ARL table start */
+#else
+#define NUM_ARL_TABLE_ENTRIES 2048 /* number of entries in ARL table */
+#define NUM_VLAN_TABLE_ENTRIES 256 /* number of entries in VLAN table */
+#define ARL_TABLE_ADDR 0x3800 /* offset of ARL table start */
+/* corresponding values for 5350 */
+#define NUM_ARL_TABLE_ENTRIES_5350 1024 /* number of entries in ARL table (5350) */
+#define NUM_VLAN_TABLE_ENTRIES_5350 16 /* number of entries in VLAN table */
+#define ARL_TABLE_ADDR_5350 0x1c00 /* offset of ARL table start (5350) */
+#endif
+typedef struct _ROBO_MEM_ACCESS_CTRL_STRUC
+{
+ unsigned int memAddr:14; /* 64-bit memory address */
+ unsigned char rsvd:4; /* reserved */
+ unsigned char readEn:1; /* read enable (0 == write) */
+ unsigned char startDone:1;/* memory access start/done */
+ unsigned int rsvd1:12; /* reserved */
+} ROBO_MEM_ACCESS_CTRL_STRUC;
+typedef struct _ROBO_MEM_ACCESS_DATA_STRUC
+{
+ unsigned int memData[2]; /* 64-bit data */
+ unsigned short rsvd; /* reserved */
+} ROBO_MEM_ACCESS_DATA_STRUC;
+
+#ifdef BCM5380
+typedef struct _ROBO_ARL_TABLE_DATA_STRUC
+{
+ unsigned char MACaddr[6]; /* MAC addr */
+ unsigned int portID:4; /* port ID */
+ unsigned int chipID:2; /* chip ID */
+ unsigned int rsvd:6; /* reserved */
+ unsigned int highPrio:1; /* high priority address */
+ unsigned int age:1; /* entry accessed/learned since ageing process */
+ unsigned int staticAddr:1;/* entry is static */
+ unsigned int valid:1; /* entry is valid */
+ unsigned int vid:12; /* vlan id */
+ unsigned int rsvd2:4; /* reserved */
+} ROBO_ARL_TABLE_DATA_STRUC;
+#else
+typedef struct _ROBO_ARL_TABLE_DATA_STRUC
+{
+ unsigned char MACaddr[6]; /* MAC addr */
+ unsigned int portID:4; /* port ID */
+ unsigned int chipID:2; /* chip ID */
+ unsigned int rsvd:7; /* reserved */
+ unsigned int age:1; /* entry accessed/learned since ageing process */
+ unsigned int staticAddr:1;/* entry is static */
+ unsigned int valid:1; /* entry is valid */
+} ROBO_ARL_TABLE_DATA_STRUC;
+#endif
+
+/* multicast format*/
+typedef struct _ROBO_ARL_TABLE_MCAST_DATA_STRUC
+{
+ unsigned char MACaddr[6]; /* MAC addr */
+ unsigned int portMask:12;/* multicast port mask */
+ unsigned char prio:1; /* priority */
+ unsigned char gigPort:1; /* gigabit port 1 mask */
+ unsigned char staticEn:1; /* static */
+ unsigned char valid:1; /* valid */
+ unsigned int vid:12; /* vlan id */
+ unsigned int rsvd2:4; /* reserved */
+} ROBO_ARL_TABLE_MCAST_DATA_STRUC;
+#define ROBO_MEM_ACCESS_CTRL 0x00 /* Memory Read/Write Control :32bit*/
+#define ROBO_MEM_ACCESS_DATA 0x04 /* Memory Read/Write Data:64bit*/
+
+/* BCM5325m SWITCH PORT (0x10-18) REGISTER MAP: 8/16 bit regs */
+typedef struct _ROBO_MII_CTRL_STRUC
+{
+ unsigned char rsvd:8; /* reserved */
+ unsigned char duplex:1; /* duplex mode */
+ unsigned char restartAN:1;/* restart auto-negotiation */
+ unsigned char rsvd1:1; /* reserved */
+ unsigned char powerDown:1;/* power down */
+ unsigned char ANenable:1; /* auto-negotiation enable */
+ unsigned char speed:1; /* forced speed selection */
+ unsigned char loopback:1; /* loopback */
+ unsigned char reset:1; /* reset */
+} ROBO_MII_CTRL_STRUC;
+typedef struct _ROBO_MII_AN_ADVERT_STRUC
+{
+ unsigned char selector:5; /* advertise selector field */
+ unsigned char T10BaseT:1; /* advertise 10BaseT */
+ unsigned char T10BaseTFull:1; /* advertise 10BaseT, full duplex */
+ unsigned char T100BaseX:1; /* advertise 100BaseX */
+ unsigned char T100BaseXFull:1;/* advertise 100BaseX full duplex */
+ unsigned char noT4:1; /* do not advertise T4 */
+ unsigned char pause:1; /* advertise pause for full duplex */
+ unsigned char rsvd:2; /* reserved */
+ unsigned char remoteFault:1; /* transmit remote fault */
+ unsigned char rsvd1:1; /* reserved */
+ unsigned char nextPage:1; /* nex page operation supported */
+} ROBO_MII_AN_ADVERT_STRUC;
+#define ROBO_MII_CTRL 0x00 /* Port MII Control */
+#define ROBO_MII_STAT 0x02 /* Port MII Status */
+/* Fields of link status register */
+#define ROBO_MII_STAT_JABBER (1<<1) /* Jabber detected */
+#define ROBO_MII_STAT_LINK (1<<2) /* Link status */
+
+#define ROBO_MII_PHYID_HI 0x04 /* Port PHY ID High */
+#define ROBO_MII_PHYID_LO 0x06 /* Port PHY ID Low */
+#define ROBO_MII_ANA_REG 0x08 /* MII Auto-Neg Advertisement */
+#define ROBO_MII_ANP_REG 0x0a /* MII Auto-Neg Partner Ability */
+#define ROBO_MII_AN_EXP_REG 0x0c /* MII Auto-Neg Expansion */
+#define ROBO_MII_AN_NP_REG 0x0e /* MII next page */
+#define ROBO_MII_ANP_NP_REG 0x10 /* MII Partner next page */
+#define ROBO_MII_100BX_AUX_CTRL 0x20 /* 100BASE-X Auxiliary Control */
+#define ROBO_MII_100BX_AUX_STAT 0x22 /* 100BASE-X Auxiliary Status */
+#define ROBO_MII_100BX_RCV_ERR_CTR 0x24 /* 100BASE-X Receive Error Ctr */
+#define ROBO_MII_100BX_RCV_FS_ERR 0x26 /* 100BASE-X Rcv False Sense Ctr */
+#define ROBO_MII_AUX_CTRL 0x30 /* Auxiliary Control/Status */
+/* Fields of Auxiliary control register */
+#define ROBO_MII_AUX_CTRL_FD (1<<0) /* Full duplex link detected*/
+#define ROBO_MII_AUX_CTRL_SP100 (1<<1) /* Speed 100 indication */
+#define ROBO_MII_AUX_STATUS 0x32 /* Aux Status Summary */
+#define ROBO_MII_CONN_STATUS 0x34 /* Aux Connection Status */
+#define ROBO_MII_AUX_MODE2 0x36 /* Aux Mode 2 */
+#define ROBO_MII_AUX_ERR_STATUS 0x38 /* Aux Error and General Status */
+#define ROBO_MII_AUX_MULTI_PHY 0x3c /* Aux Multiple PHY Register*/
+#define ROBO_MII_BROADCOM_TEST 0x3e /* Broadcom Test Register */
+
+
+/* BCM5325m PORT MIB REGISTERS (Pages 0x20-0x24,0x28) REGISTER MAP: 64/32 */
+/* Tranmit Statistics */
+#define ROBO_MIB_TX_OCTETS 0x00 /* 64b: TxOctets */
+#define ROBO_MIB_TX_DROP_PKTS 0x08 /* 32b: TxDropPkts */
+#define ROBO_MIB_TX_BC_PKTS 0x10 /* 32b: TxBroadcastPkts */
+#define ROBO_MIB_TX_MC_PKTS 0x14 /* 32b: TxMulticastPkts */
+#define ROBO_MIB_TX_UC_PKTS 0x18 /* 32b: TxUnicastPkts */
+#define ROBO_MIB_TX_COLLISIONS 0x1c /* 32b: TxCollisions */
+#define ROBO_MIB_TX_SINGLE_COLLISIONS 0x20 /* 32b: TxSingleCollision */
+#define ROBO_MIB_TX_MULTI_COLLISIONS 0x24 /* 32b: TxMultiCollision */
+#define ROBO_MIB_TX_DEFER_TX 0x28 /* 32b: TxDeferred Transmit */
+#define ROBO_MIB_TX_LATE_COLLISIONS 0x2c /* 32b: TxLateCollision */
+#define ROBO_MIB_EXCESS_COLLISIONS 0x30 /* 32b: TxExcessiveCollision*/
+#define ROBO_MIB_FRAME_IN_DISCARDS 0x34 /* 32b: TxFrameInDiscards */
+#define ROBO_MIB_TX_PAUSE_PKTS 0x38 /* 32b: TxPausePkts */
+
+/* Receive Statistics */
+#define ROBO_MIB_RX_OCTETS 0x44 /* 64b: RxOctets */
+#define ROBO_MIB_RX_UNDER_SIZE_PKTS 0x4c /* 32b: RxUndersizePkts(runts)*/
+#define ROBO_MIB_RX_PAUSE_PKTS 0x50 /* 32b: RxPausePkts */
+#define ROBO_MIB_RX_PKTS_64 0x54 /* 32b: RxPkts64Octets */
+#define ROBO_MIB_RX_PKTS_65_TO_127 0x58 /* 32b: RxPkts64to127Octets*/
+#define ROBO_MIB_RX_PKTS_128_TO_255 0x5c /* 32b: RxPkts128to255Octets*/
+#define ROBO_MIB_RX_PKTS_256_TO_511 0x60 /* 32b: RxPkts256to511Octets*/
+#define ROBO_MIB_RX_PKTS_512_TO_1023 0x64 /* 32b: RxPkts512to1023Octets*/
+#define ROBO_MIB_RX_PKTS_1024_TO_1522 0x68 /* 32b: RxPkts1024to1522Octets*/
+#define ROBO_MIB_RX_OVER_SIZE_PKTS 0x6c /* 32b: RxOversizePkts*/
+#define ROBO_MIB_RX_JABBERS 0x70 /* 32b: RxJabbers*/
+#define ROBO_MIB_RX_ALIGNMENT_ERRORS 0x74 /* 32b: RxAlignmentErrors*/
+#define ROBO_MIB_RX_FCS_ERRORS 0x78 /* 32b: RxFCSErrors */
+#define ROBO_MIB_RX_GOOD_OCTETS 0x7c /* 32b: RxGoodOctets */
+#define ROBO_MIB_RX_DROP_PKTS 0x84 /* 32b: RxDropPkts */
+#define ROBO_MIB_RX_UC_PKTS 0x88 /* 32b: RxUnicastPkts */
+#define ROBO_MIB_RX_MC_PKTS 0x8c /* 32b: RxMulticastPkts */
+#define ROBO_MIB_RX_BC_PKTS 0x90 /* 32b: RxBroadcastPkts */
+#define ROBO_MIB_RX_SA_CHANGES 0x94 /* 32b: RxSAChanges */
+#define ROBO_MIB_RX_FRAGMENTS 0x98 /* 32b: RxFragments */
+#define ROBO_MIB_RX_EXCESS_SZ_DISC 0x9c /* 32b: RxExcessSizeDisc*/
+#define ROBO_MIB_RX_SYMBOL_ERROR 0xa0 /* 32b: RxSymbolError */
+
+/* BCM5350 MIB Statistics */
+/* Group 0 */
+#define ROBO_MIB_TX_GOOD_PKTS 0x00 /* 16b: TxGoodPkts */
+#define ROBO_MIB_TX_UNICAST_PKTS 0x02 /* 16b: TxUnicastPkts */
+#define ROBO_MIB_RX_GOOD_PKTS 0x04 /* 16b: RxGoodPkts */
+#define ROBO_MIB_RX_GOOD_UNICAST_PKTS 0x06 /* 16b: RxGoodUnicastPkts */
+/* Group 1 */
+#define ROBO_MIB_TX_COLLISION 0x00 /* 16b: TxCollision */
+#define ROBO_MIB_TX_OCTETS_5350 0x02 /* 16b: TxOctets */
+#define ROBO_MIB_RX_FCS_ERRORS_5350 0x04 /* 16b: RxFCSErrors */
+#define ROBO_MIB_RX_GOOD_OCTETS_5350 0x06 /* 16b: RxGoodOctets */
+
+/* BCM5325m QoS REGISTERS (Page 0x30) REGISTER MAP: 8/16 */
+#define ROBO_QOS_CTRL 0x00 /* 16b: QoS Control Register */
+#define ROBO_QOS_LOCAL_WEIGHT_CTRL 0x10 /* 8b: Local HQ/LQ Weight Register*/
+#define ROBO_QOS_CPU_WEIGHT_CTRL 0x12 /* 8b: CPU HQ/LQ Weight Register*/
+#define ROBO_QOS_PAUSE_ENA 0x13 /* 16b: Qos Pause Enable Register*/
+#define ROBO_QOS_PRIO_THRESHOLD 0x15 /* 8b: Priority Threshold Register*/
+#define ROBO_QOS_RESERVED 0x16 /* 8b: Qos Reserved Register */
+
+/* BCM5325m VLAN REGISTERS (Page 0x34) REGISTER MAP: 8/16bit */
+typedef struct _ROBO_VLAN_CTRL0_STRUC
+{
+ unsigned char frameControlP:2; /* 802.1P frame control */
+ unsigned char frameControlQ:2; /* 802.1Q frame control */
+ unsigned char dropMissedVID:1; /* enable drop missed VID packet */
+ unsigned char vidMacHash:1; /* VID_MAC hash enable */
+ unsigned char vidMacCheck:1; /* VID_MAC check enable */
+ unsigned char VLANen:1; /* 802.1Q VLAN enable */
+} ROBO_VLAN_CTRL0_STRUC;
+#define VLAN_TABLE_WRITE 1 /* for read/write state in table access reg */
+#define VLAN_TABLE_READ 0 /* for read/write state in table access reg */
+#define VLAN_ID_HIGH_BITS 0 /* static high bits in table access reg */
+#define VLAN_ID_MAX 255 /* max VLAN id */
+#define VLAN_ID_MAX5350 15 /* max VLAN id (5350) */
+#define VLAN_ID_MASK VLAN_ID_MAX /* VLAN id mask */
+#ifdef BCM5380
+#define VLAN_UNTAG_SHIFT 13 /* for postioning untag bits in write reg */
+#define VLAN_VALID 0x4000000 /* valid bit in write reg */
+#else
+#define VLAN_UNTAG_SHIFT 7 /* for postioning untag bits in write reg */
+#define VLAN_VALID 0x4000 /* valid bit in write reg */
+/* corresponding values for 5350 */
+#define VLAN_UNTAG_SHIFT_5350 6 /* for postioning untag bits in write reg */
+#define VLAN_VALID_5350 0x00100000 /* valid bit in write reg */
+#endif
+typedef struct _ROBO_VLAN_TABLE_ACCESS_STRUC
+{
+ unsigned char VLANid:8; /* VLAN ID (low 8 bits) */
+ unsigned char VLANidHi:4; /* VLAN ID (fixed upper portion) */
+ unsigned char readWriteState:1; /* read/write state (write = 1) */
+ volatile unsigned char readWriteEnable:1; /* table read/write enable */
+ unsigned char rsvd:2; /* reserved */
+} ROBO_VLAN_TABLE_ACCESS_STRUC;
+#ifdef BCM5380
+typedef struct _ROBO_VLAN_READ_WRITE_STRUC
+{
+ unsigned int VLANgroup:13;/* VLAN group mask */
+ unsigned int VLANuntag:13;/* VLAN untag enable mask */
+ unsigned char valid:1; /* valid */
+ unsigned char rsvd:5; /* reserved */
+} ROBO_VLAN_READ_WRITE_STRUC;
+#else
+typedef struct _ROBO_VLAN_READ_WRITE_STRUC
+{
+ unsigned char VLANgroup:7; /* VLAN group mask */
+ unsigned char VLANuntag:7; /* VLAN untag enable mask */
+ unsigned char valid:1; /* valid */
+ unsigned char rsvd:1; /* reserved */
+} ROBO_VLAN_READ_WRITE_STRUC;
+typedef struct _ROBO_VLAN_READ_WRITE_STRUC_5350
+{
+ unsigned char VLANgroup:6; /* VLAN group mask */
+ unsigned char VLANuntag:6; /* VLAN untag enable mask */
+ unsigned char highVID:8; /* upper bits of vid */
+ unsigned char valid:1; /* valid */
+ unsigned int rsvd:11; /* reserved */
+} ROBO_VLAN_READ_WRITE_STRUC_5350;
+#endif
+#define ROBO_VLAN_CTRL0 0x00 /* 8b: VLAN Control 0 Register */
+#define ROBO_VLAN_CTRL1 0x01 /* 8b: VLAN Control 1 Register */
+#define ROBO_VLAN_CTRL2 0x02 /* 8b: VLAN Control 2 Register */
+#define ROBO_VLAN_CTRL3 0x03 /* 8b: VLAN Control 3 Register */
+#define ROBO_VLAN_CTRL4 0x04 /* 8b: VLAN Control 4 Register */
+#define ROBO_VLAN_CTRL5 0x05 /* 8b: VLAN Control 5 Register */
+#define ROBO_VLAN_TABLE_ACCESS 0x08 /* 14b: VLAN Table Access Register */
+#define ROBO_VLAN_TABLE_ACCESS_5350 0x06 /* 14b: VLAN Table Access Register (5350) */
+#define ROBO_VLAN_WRITE 0x0a /* 15b: VLAN Write Register */
+#define ROBO_VLAN_WRITE_5350 0x08 /* 15b: VLAN Write Register (5350) */
+#define ROBO_VLAN_READ 0x0c /* 15b: VLAN Read Register */
+#define ROBO_VLAN_PORT0_DEF_TAG 0x10 /* 16b: VLAN Port 0 Default Tag Register */
+#define ROBO_VLAN_PORT1_DEF_TAG 0x12 /* 16b: VLAN Port 1 Default Tag Register */
+#define ROBO_VLAN_PORT2_DEF_TAG 0x14 /* 16b: VLAN Port 2 Default Tag Register */
+#define ROBO_VLAN_PORT3_DEF_TAG 0x16 /* 16b: VLAN Port 3 Default Tag Register */
+#define ROBO_VLAN_PORT4_DEF_TAG 0x18 /* 16b: VLAN Port 4 Default Tag Register */
+#define ROBO_VLAN_PORTMII_DEF_TAG 0x1a /* 16b: VLAN Port MII Default Tag Register */
+/* 5380 only */
+#define ROBO_VLAN_PORT5_DEF_TAG 0x1a /* 16b: VLAN Port 5 Default Tag Register */
+#define ROBO_VLAN_PORT6_DEF_TAG 0x1c /* 16b: VLAN Port 6 Default Tag Register */
+#define ROBO_VLAN_PORT7_DEF_TAG 0x1e /* 16b: VLAN Port 7 Default Tag Register */
+
+/* obsolete */
+#define ROBO_VLAN_PORT0_CTRL 0x00 /* 16b: Port 0 VLAN Register */
+#define ROBO_VLAN_PORT1_CTRL 0x02 /* 16b: Port 1 VLAN Register */
+#define ROBO_VLAN_PORT2_CTRL 0x04 /* 16b: Port 2 VLAN Register */
+#define ROBO_VLAN_PORT3_CTRL 0x06 /* 16b: Port 3 VLAN Register */
+#define ROBO_VLAN_PORT4_CTRL 0x08 /* 16b: Port 4 VLAN Register */
+#define ROBO_VLAN_IM_PORT_CTRL 0x10 /* 16b: Inverse MII Port VLAN Reg */
+#define ROBO_VLAN_SMP_PORT_CTRL 0x12 /* 16b: Serial Port VLAN Register */
+#define ROBO_VLAN_PORTSPI_DEF_TAG 0x1c /* 16b: VLAN Port SPI Default Tag Register */
+#define ROBO_VLAN_PRIORITY_REMAP 0x20 /* 24b: VLAN Priority Re-Map Register */
+
+#ifndef _CFE_
+#pragma pack()
+#endif
+
+
+#endif /* !__BCM535M_H_ */
+
+
+
+
+
diff --git a/package/switch/src/gpio.h b/package/switch/src/gpio.h
new file mode 100644
index 000000000..cb734f7b1
--- /dev/null
+++ b/package/switch/src/gpio.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2006 OpenWrt.org
+ *
+ * This is free software, licensed under the GNU General Public License v2.
+ * See /LICENSE for more information.
+ */
+
+#ifndef __GPIO_H
+#define __GPIO_H
+
+#ifdef CONFIG_BCM47XX
+#include <linux/gpio.h>
+#else
+#warning "Unsupported configuration."
+
+#define bcm47xx_gpio_in(mask) (-1U)
+#define bcm47xx_gpio_out(mask, value) (-1U)
+#define bcm47xx_gpio_outen(mask, value) (-1U)
+#define bcm47xx_gpio_control(mask, value) (-1U)
+#define bcm47xx_gpio_intmask(mask, value) (-1U)
+#define bcm47xx_gpio_polarity(mask, value) (-1U)
+
+#endif
+
+#endif /* __GPIO_H */
diff --git a/package/switch/src/switch-adm.c b/package/switch/src/switch-adm.c
new file mode 100644
index 000000000..9a6d32b1e
--- /dev/null
+++ b/package/switch/src/switch-adm.c
@@ -0,0 +1,595 @@
+/*
+ * ADMTEK Adm6996 switch configuration module
+ *
+ * Copyright (C) 2005 Felix Fietkau <nbd@nbd.name>
+ *
+ * Partially based on Broadcom Home Networking Division 10/100 Mbit/s
+ * Ethernet Device Driver (from Montavista 2.4.20_mvl31 Kernel).
+ * Copyright (C) 2004 Broadcom Corporation
+ *
+ * adm_rreg function from adm6996
+ * Copyright (C) 2004 Nikki Chumakov <nikki@gattaca.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/if.h>
+#include <linux/if_arp.h>
+#include <linux/sockios.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+
+#include "switch-core.h"
+#include "gpio.h"
+
+#ifdef CONFIG_BCM47XX
+#include <nvram.h>
+#endif
+
+#define DRIVER_NAME "adm6996"
+#define DRIVER_VERSION "0.01"
+
+static int eecs = 0;
+static int eesk = 0;
+static int eedi = 0;
+static int eerc = 0;
+static int force = 0;
+
+MODULE_AUTHOR("Felix Fietkau <openwrt@nbd.name>");
+MODULE_LICENSE("GPL");
+module_param(eecs, int, 0);
+module_param(eesk, int, 0);
+module_param(eedi, int, 0);
+module_param(eerc, int, 0);
+module_param(force, int, 0);
+
+/* Minimum timing constants */
+#define EECK_EDGE_TIME 3 /* 3us - max(adm 2.5us, 93c 1us) */
+#define EEDI_SETUP_TIME 1 /* 1us - max(adm 10ns, 93c 400ns) */
+#define EECS_SETUP_TIME 1 /* 1us - max(adm no, 93c 200ns) */
+
+/* Handy macros for writing fixed length values */
+#define adm_write8(cs, b) { __u8 val = (__u8) (b); adm_write(cs, &val, sizeof(val)*8); }
+#define adm_write16(cs, w) { __u16 val = hton16(w); adm_write(cs, (__u8 *)&val, sizeof(val)*8); }
+#define adm_write32(cs, i) { uint32 val = hton32(i); adm_write(cs, (__u8 *)&val, sizeof(val)*8); }
+
+#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0)
+
+#ifdef CONFIG_BCM47XX
+
+/* Return gpio pin number assigned to the named pin */
+/*
+* Variable should be in format:
+*
+* gpio<N>=pin_name
+*
+* 'def_pin' is returned if there is no such variable found.
+*/
+static unsigned int get_gpiopin(char *pin_name, unsigned int def_pin)
+{
+ char name[] = "gpioXXXX";
+ char val[10];
+ unsigned int pin;
+
+ /* Go thru all possibilities till a match in pin name */
+ for (pin = 0; pin < 16; pin ++) {
+ sprintf(name, "gpio%d", pin);
+ if (nvram_getenv(name, val, sizeof(val)) >= 0) {
+ if (!strcmp(val, pin_name))
+ return pin;
+ }
+ }
+ return def_pin;
+}
+#endif
+
+
+static void adm_write(int cs, char *buf, unsigned int bits)
+{
+ int i, len = (bits + 7) / 8;
+ __u8 mask;
+
+ bcm47xx_gpio_out(eecs, (cs ? eecs : 0));
+ udelay(EECK_EDGE_TIME);
+
+ /* Byte assemble from MSB to LSB */
+ for (i = 0; i < len; i++) {
+ /* Bit bang from MSB to LSB */
+ for (mask = 0x80; mask && bits > 0; mask >>= 1, bits --) {
+ /* Clock low */
+ bcm47xx_gpio_out(eesk, 0);
+ udelay(EECK_EDGE_TIME);
+
+ /* Output on rising edge */
+ bcm47xx_gpio_out(eedi, ((mask & buf[i]) ? eedi : 0));
+ udelay(EEDI_SETUP_TIME);
+
+ /* Clock high */
+ bcm47xx_gpio_out(eesk, eesk);
+ udelay(EECK_EDGE_TIME);
+ }
+ }
+
+ /* Clock low */
+ bcm47xx_gpio_out(eesk, 0);
+ udelay(EECK_EDGE_TIME);
+
+ if (cs)
+ bcm47xx_gpio_out(eecs, 0);
+}
+
+
+static void adm_read(int cs, char *buf, unsigned int bits)
+{
+ int i, len = (bits + 7) / 8;
+ __u8 mask;
+
+ bcm47xx_gpio_out(eecs, (cs ? eecs : 0));
+ udelay(EECK_EDGE_TIME);
+
+ /* Byte assemble from MSB to LSB */
+ for (i = 0; i < len; i++) {
+ __u8 byte;
+
+ /* Bit bang from MSB to LSB */
+ for (mask = 0x80, byte = 0; mask && bits > 0; mask >>= 1, bits --) {
+ __u8 gp;
+
+ /* Clock low */
+ bcm47xx_gpio_out(eesk, 0);
+ udelay(EECK_EDGE_TIME);
+
+ /* Input on rising edge */
+ gp = bcm47xx_gpio_in(~0);
+ if (gp & eedi)
+ byte |= mask;
+
+ /* Clock high */
+ bcm47xx_gpio_out(eesk, eesk);
+ udelay(EECK_EDGE_TIME);
+ }
+
+ *buf++ = byte;
+ }
+
+ /* Clock low */
+ bcm47xx_gpio_out(eesk, 0);
+ udelay(EECK_EDGE_TIME);
+
+ if (cs)
+ bcm47xx_gpio_out(eecs, 0);
+}
+
+
+/* Enable outputs with specified value to the chip */
+static void adm_enout(__u8 pins, __u8 val)
+{
+ /* Prepare GPIO output value */
+ bcm47xx_gpio_out(pins, val);
+
+ /* Enable GPIO outputs */
+ bcm47xx_gpio_outen(pins, pins);
+ udelay(EECK_EDGE_TIME);
+}
+
+
+/* Disable outputs to the chip */
+static void adm_disout(__u8 pins)
+{
+ /* Disable GPIO outputs */
+ bcm47xx_gpio_outen(pins, 0);
+ udelay(EECK_EDGE_TIME);
+}
+
+
+/* Advance clock(s) */
+static void adm_adclk(int clocks)
+{
+ int i;
+ for (i = 0; i < clocks; i++) {
+ /* Clock high */
+ bcm47xx_gpio_out(eesk, eesk);
+ udelay(EECK_EDGE_TIME);
+
+ /* Clock low */
+ bcm47xx_gpio_out(eesk, 0);
+ udelay(EECK_EDGE_TIME);
+ }
+}
+
+static __u32 adm_rreg(__u8 table, __u8 addr)
+{
+ /* cmd: 01 10 T DD R RRRRRR */
+ __u8 bits[6] = {
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ (0x06 << 4) | ((table & 0x01) << 3 | (addr&64)>>6),
+ ((addr&63)<<2)
+ };
+
+ __u8 rbits[4];
+
+ /* Enable GPIO outputs with all pins to 0 */
+ adm_enout((__u8)(eecs | eesk | eedi), 0);
+
+ adm_write(0, bits, 46);
+ adm_disout((__u8)(eedi));
+ adm_adclk(2);
+ adm_read (0, rbits, 32);
+
+ /* Extra clock(s) required per datasheet */
+ adm_adclk(2);
+
+ /* Disable GPIO outputs */
+ adm_disout((__u8)(eecs | eesk));
+
+ if (!table) /* EEPROM has 16-bit registers, but pumps out two registers in one request */
+ return (addr & 0x01 ? (rbits[0]<<8) | rbits[1] : (rbits[2]<<8) | (rbits[3]));
+ else
+ return (rbits[0]<<24) | (rbits[1]<<16) | (rbits[2]<<8) | rbits[3];
+}
+
+
+
+/* Write chip configuration register */
+/* Follow 93c66 timing and chip's min EEPROM timing requirement */
+void
+adm_wreg(__u8 addr, __u16 val)
+{
+ /* cmd(27bits): sb(1) + opc(01) + addr(bbbbbbbb) + data(bbbbbbbbbbbbbbbb) */
+ __u8 bits[4] = {
+ (0x05 << 5) | (addr >> 3),
+ (addr << 5) | (__u8)(val >> 11),
+ (__u8)(val >> 3),
+ (__u8)(val << 5)
+ };
+
+ /* Enable GPIO outputs with all pins to 0 */
+ adm_enout((__u8)(eecs | eesk | eedi), 0);
+
+ /* Write cmd. Total 27 bits */
+ adm_write(1, bits, 27);
+
+ /* Extra clock(s) required per datasheet */
+ adm_adclk(2);
+
+ /* Disable GPIO outputs */
+ adm_disout((__u8)(eecs | eesk | eedi));
+}
+
+
+/* Port configuration registers */
+static int port_conf[] = { 0x01, 0x03, 0x05, 0x07, 0x08, 0x09 };
+
+/* Bits in VLAN port mapping */
+static int vlan_ports[] = { 1 << 0, 1 << 2, 1 << 4, 1 << 6, 1 << 7, 1 << 8 };
+
+static int handle_vlan_port_read(void *driver, char *buf, int nr)
+{
+ int ports, i, c, len = 0;
+
+ if ((nr < 0) || (nr > 15))
+ return 0;
+
+ /* Get VLAN port map */
+ ports = adm_rreg(0, 0x13 + nr);
+
+ for (i = 0; i <= 5; i++) {
+ if (ports & vlan_ports[i]) {
+ c = adm_rreg(0, port_conf[i]);
+
+ len += sprintf(buf + len, "%d", i);
+ if (c & (1 << 4)) {
+ buf[len++] = 't';
+ if (((c & (0xf << 10)) >> 10) == nr)
+ buf[len++] = '*';
+ } else if (i == 5)
+ buf[len++] = 'u';
+
+ buf[len++] = '\t';
+ }
+ }
+ len += sprintf(buf + len, "\n");
+
+ return len;
+}
+
+static int handle_vlan_port_write(void *driver, char *buf, int nr)
+{
+ int i, cfg, ports;
+ switch_driver *d = (switch_driver *) driver;
+ switch_vlan_config *c = switch_parse_vlan(d, buf);
+
+ if (c == NULL)
+ return -1;
+
+ ports = adm_rreg(0, 0x13 + nr);
+ for (i = 0; i < d->ports; i++) {
+ if (c->port & (1 << i)) {
+ ports |= vlan_ports[i];
+
+ cfg = adm_rreg(0, port_conf[i]);
+
+ /* Tagging */
+ if (c->untag & (1 << i))
+ cfg &= ~(1 << 4);
+ else
+ cfg |= (1 << 4);
+
+ if ((c->untag | c->pvid) & (1 << i)) {
+ cfg = (cfg & ~(0xf << 10)) | (nr << 10);
+ }
+
+ adm_wreg(port_conf[i], (__u16) cfg);
+ } else {
+ ports &= ~(vlan_ports[i]);
+ }
+ }
+ adm_wreg(0x13 + nr, (__u16) ports);
+
+ kfree(c);
+ return 0;
+}
+
+static int handle_port_enable_read(void *driver, char *buf, int nr)
+{
+ return sprintf(buf, "%d\n", ((adm_rreg(0, port_conf[nr]) & (1 << 5)) ? 0 : 1));
+}
+
+static int handle_port_enable_write(void *driver, char *buf, int nr)
+{
+ int reg = adm_rreg(0, port_conf[nr]);
+
+ if (buf[0] == '0')
+ reg |= (1 << 5);
+ else if (buf[0] == '1')
+ reg &= ~(1 << 5);
+ else return -1;
+
+ adm_wreg(port_conf[nr], (__u16) reg);
+ return 0;
+}
+
+static int handle_port_media_read(void *driver, char *buf, int nr)
+{
+ int len;
+ int media = 0;
+ int reg = adm_rreg(0, port_conf[nr]);
+
+ if (reg & (1 << 1))
+ media |= SWITCH_MEDIA_AUTO;
+ if (reg & (1 << 2))
+ media |= SWITCH_MEDIA_100;
+ if (reg & (1 << 3))
+ media |= SWITCH_MEDIA_FD;
+
+ len = switch_print_media(buf, media);
+ return len + sprintf(buf + len, "\n");
+}
+
+static int handle_port_media_write(void *driver, char *buf, int nr)
+{
+ int media = switch_parse_media(buf);
+ int reg = adm_rreg(0, port_conf[nr]);
+
+ if (media < 0)
+ return -1;
+
+ reg &= ~((1 << 1) | (1 << 2) | (1 << 3));
+ if (media & SWITCH_MEDIA_AUTO)
+ reg |= 1 << 1;
+ if (media & SWITCH_MEDIA_100)
+ reg |= 1 << 2;
+ if (media & SWITCH_MEDIA_FD)
+ reg |= 1 << 3;
+
+ adm_wreg(port_conf[nr], reg);
+
+ return 0;
+}
+
+static int handle_vlan_enable_read(void *driver, char *buf, int nr)
+{
+ return sprintf(buf, "%d\n", ((adm_rreg(0, 0x11) & (1 << 5)) ? 1 : 0));
+}
+
+static int handle_vlan_enable_write(void *driver, char *buf, int nr)
+{
+ int reg = adm_rreg(0, 0x11);
+
+ if (buf[0] == '1')
+ reg |= (1 << 5);
+ else if (buf[0] == '0')
+ reg &= ~(1 << 5);
+ else return -1;
+
+ adm_wreg(0x11, (__u16) reg);
+ return 0;
+}
+
+static int handle_reset(void *driver, char *buf, int nr)
+{
+ int i;
+ u32 cfg;
+
+ /*
+ * Reset sequence: RC high->low(100ms)->high(30ms)
+ *
+ * WAR: Certain boards don't have the correct power on
+ * reset logic therefore we must explicitly perform the
+ * sequence in software.
+ */
+ if (eerc) {
+ /* Keep RC high for at least 20ms */
+ adm_enout(eerc, eerc);
+ for (i = 0; i < 20; i ++)
+ udelay(1000);
+ /* Keep RC low for at least 100ms */
+ adm_enout(eerc, 0);
+ for (i = 0; i < 100; i++)
+ udelay(1000);
+ /* Set default configuration */
+ adm_enout((__u8)(eesk | eedi), eesk);
+ /* Keep RC high for at least 30ms */
+ adm_enout(eerc, eerc);
+ for (i = 0; i < 30; i++)
+ udelay(1000);
+ /* Leave RC high and disable GPIO outputs */
+ adm_disout((__u8)(eecs | eesk | eedi));
+
+ }
+
+ /* set up initial configuration for cpu port */
+ cfg = (0x8000 | /* Auto MDIX */
+ (0xf << 10) | /* PVID */
+ (1 << 4) | /* Tagging */
+ 0xf); /* full duplex, 100Mbps, auto neg, flow ctrl */
+ adm_wreg(port_conf[5], cfg);
+
+ /* vlan mode select register (0x11): vlan on, mac clone */
+ adm_wreg(0x11, 0xff30);
+
+ return 0;
+}
+
+static int handle_registers(void *driver, char *buf, int nr)
+{
+ int i, len = 0;
+
+ for (i = 0; i <= 0x33; i++) {
+ len += sprintf(buf + len, "0x%02x: 0x%04x\n", i, adm_rreg(0, i));
+ }
+
+ return len;
+}
+
+static int handle_counters(void *driver, char *buf, int nr)
+{
+ int i, len = 0;
+
+ for (i = 0; i <= 0x3c; i++) {
+ len += sprintf(buf + len, "0x%02x: 0x%08x\n", i, adm_rreg(1, i));
+ }
+
+ return len;
+}
+
+static int detect_adm(void)
+{
+ int ret = 0;
+
+#ifdef CONFIG_BCM47XX
+ char buf[20];
+ int boardflags = 0;
+ int boardnum = 0;
+
+ if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0)
+ boardflags = simple_strtoul(buf, NULL, 0);
+
+ if (nvram_getenv("boardnum", buf, sizeof(buf)) >= 0)
+ boardnum = simple_strtoul(buf, NULL, 0);
+
+ if ((boardnum == 44) && (boardflags == 0x0388)) { /* Trendware TEW-411BRP+ */
+ ret = 1;
+
+ eecs = get_gpiopin("adm_eecs", 2);
+ eesk = get_gpiopin("adm_eesk", 3);
+ eedi = get_gpiopin("adm_eedi", 4);
+ eerc = get_gpiopin("adm_rc", 5);
+
+ } else if ((boardflags & 0x80) || force) {
+ ret = 1;
+
+ eecs = get_gpiopin("adm_eecs", 2);
+ eesk = get_gpiopin("adm_eesk", 3);
+ eedi = get_gpiopin("adm_eedi", 4);
+ eerc = get_gpiopin("adm_rc", 0);
+
+ } else if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0) {
+ if (strcmp(buf, "bcm94710dev") == 0) {
+ if (nvram_getenv("boardnum", buf, sizeof(buf)) >= 0) {
+ if (strncmp(buf, "42", 2) == 0) {
+ /* WRT54G v1.1 hack */
+ eecs = 2;
+ eesk = 3;
+ eedi = 5;
+
+ ret = 1;
+ }
+ }
+ }
+ }
+
+ if (eecs)
+ eecs = (1 << eecs);
+ if (eesk)
+ eesk = (1 << eesk);
+ if (eedi)
+ eedi = (1 << eedi);
+ if (eerc)
+ eerc = (1 << eerc);
+#else
+ ret = 1;
+#endif
+
+ return ret;
+}
+
+static int __init adm_init(void)
+{
+ switch_config cfg[] = {
+ {"registers", handle_registers, NULL},
+ {"counters", handle_counters, NULL},
+ {"reset", NULL, handle_reset},
+ {"enable_vlan", handle_vlan_enable_read, handle_vlan_enable_write},
+ {NULL, NULL, NULL}
+ };
+ switch_config port[] = {
+ {"enable", handle_port_enable_read, handle_port_enable_write},
+ {"media", handle_port_media_read, handle_port_media_write},
+ {NULL, NULL, NULL}
+ };
+ switch_config vlan[] = {
+ {"ports", handle_vlan_port_read, handle_vlan_port_write},
+ {NULL, NULL, NULL}
+ };
+ switch_driver driver = {
+ name: DRIVER_NAME,
+ version: DRIVER_VERSION,
+ interface: "eth0",
+ ports: 6,
+ cpuport: 5,
+ vlans: 16,
+ driver_handlers: cfg,
+ port_handlers: port,
+ vlan_handlers: vlan,
+ };
+
+ if (!detect_adm())
+ return -ENODEV;
+
+ return switch_register_driver(&driver);
+}
+
+static void __exit adm_exit(void)
+{
+ switch_unregister_driver(DRIVER_NAME);
+}
+
+
+module_init(adm_init);
+module_exit(adm_exit);
diff --git a/package/switch/src/switch-core.c b/package/switch/src/switch-core.c
new file mode 100644
index 000000000..79b4e93f0
--- /dev/null
+++ b/package/switch/src/switch-core.c
@@ -0,0 +1,491 @@
+/*
+ * switch-core.c
+ *
+ * Copyright (C) 2005 Felix Fietkau <openwrt@nbd.name>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ *
+ * Basic doc of driver's /proc interface:
+ * /proc/switch/<interface>/
+ * registers: read-only
+ * counters: read-only
+ * reset: write causes hardware reset
+ * enable_vlan: "0", "1"
+ * port/<port-number>/
+ * enabled: "0", "1"
+ * media: "AUTO", "100FD", "100HD", "10FD", "10HD"
+ * vlan/<port-number>/
+ * ports: same syntax as for nvram's vlan*ports (eg. "1 2 3 4 5*")
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/list.h>
+
+#include "switch-core.h"
+
+static int drv_num = 0;
+static struct proc_dir_entry *switch_root;
+switch_driver drivers;
+
+typedef struct {
+ struct list_head list;
+ struct proc_dir_entry *parent;
+ int nr;
+ void *driver;
+ switch_config handler;
+} switch_proc_handler;
+
+typedef struct {
+ struct proc_dir_entry *driver_dir, *port_dir, *vlan_dir;
+ struct proc_dir_entry **ports, **vlans;
+ switch_proc_handler data;
+ int nr;
+} switch_priv;
+
+static ssize_t switch_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos);
+static ssize_t switch_proc_write(struct file *file, const char *buf, size_t count, void *data);
+
+static struct file_operations switch_proc_fops = {
+ .read = (ssize_t (*) (struct file *, char __user *, size_t, loff_t *))switch_proc_read,
+ .write = (ssize_t (*) (struct file *, const char __user *, size_t, loff_t *))switch_proc_write
+};
+
+static ssize_t switch_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+ struct proc_dir_entry *dent = PDE(file->f_dentry->d_inode);
+ char *page;
+ int len = 0;
+
+ if ((page = kmalloc(SWITCH_MAX_BUFSZ, GFP_KERNEL)) == NULL)
+ return -ENOBUFS;
+
+ if (dent->data != NULL) {
+ switch_proc_handler *handler = (switch_proc_handler *) dent->data;
+ if (handler->handler.read != NULL)
+ len += handler->handler.read(handler->driver, page + len, handler->nr);
+ }
+ len += 1;
+
+ if (*ppos < len) {
+ len = min_t(int, len - *ppos, count);
+ if (copy_to_user(buf, (page + *ppos), len)) {
+ kfree(page);
+ return -EFAULT;
+ }
+ *ppos += len;
+ } else {
+ len = 0;
+ }
+
+ kfree(page);
+ return len;
+}
+
+
+static ssize_t switch_proc_write(struct file *file, const char *buf, size_t count, void *data)
+{
+ struct proc_dir_entry *dent = PDE(file->f_dentry->d_inode);
+ char *page;
+ int ret = -EINVAL;
+
+ if ((page = kmalloc(count + 1, GFP_KERNEL)) == NULL)
+ return -ENOBUFS;
+
+ if (copy_from_user(page, buf, count)) {
+ kfree(page);
+ return -EINVAL;
+ }
+ page[count] = 0;
+
+ if (dent->data != NULL) {
+ switch_proc_handler *handler = (switch_proc_handler *) dent->data;
+ if (handler->handler.write != NULL) {
+ if ((ret = handler->handler.write(handler->driver, page, handler->nr)) >= 0)
+ ret = count;
+ }
+ }
+
+ kfree(page);
+ return ret;
+}
+
+static int handle_driver_name(void *driver, char *buf, int nr)
+{
+ const char *name = ((switch_driver *) driver)->name;
+ return sprintf(buf, "%s\n", name);
+}
+
+static int handle_driver_version(void *driver, char *buf, int nr)
+{
+ const char *version = ((switch_driver *) driver)->version;
+ strcpy(buf, version);
+ return sprintf(buf, "%s\n", version);
+}
+
+static void add_handler(switch_driver *driver, const switch_config *handler, struct proc_dir_entry *parent, int nr)
+{
+ switch_priv *priv = (switch_priv *) driver->data;
+ struct proc_dir_entry *p;
+ int mode;
+
+ switch_proc_handler *tmp;
+ tmp = (switch_proc_handler *) kmalloc(sizeof(switch_proc_handler), GFP_KERNEL);
+ if (!tmp)
+ return;
+ INIT_LIST_HEAD(&tmp->list);
+ tmp->parent = parent;
+ tmp->nr = nr;
+ tmp->driver = driver;
+ memcpy(&tmp->handler, handler, sizeof(switch_config));
+ list_add(&tmp->list, &priv->data.list);
+
+ mode = 0;
+ if (handler->read != NULL) mode |= S_IRUSR;
+ if (handler->write != NULL) mode |= S_IWUSR;
+
+ if ((p = create_proc_entry(handler->name, mode, parent)) != NULL) {
+ p->data = (void *) tmp;
+ p->proc_fops = &switch_proc_fops;
+ }
+}
+
+static inline void add_handlers(switch_driver *driver, const switch_config *handlers, struct proc_dir_entry *parent, int nr)
+{
+ int i;
+
+ for (i = 0; handlers[i].name != NULL; i++) {
+ add_handler(driver, &(handlers[i]), parent, nr);
+ }
+}
+
+static void remove_handlers(switch_priv *priv)
+{
+ struct list_head *pos, *q;
+ switch_proc_handler *tmp;
+
+ list_for_each_safe(pos, q, &priv->data.list) {
+ tmp = list_entry(pos, switch_proc_handler, list);
+ list_del(pos);
+ remove_proc_entry(tmp->handler.name, tmp->parent);
+ kfree(tmp);
+ }
+}
+
+
+static void do_unregister(switch_driver *driver)
+{
+ char buf[4];
+ int i;
+ switch_priv *priv = (switch_priv *) driver->data;
+
+ remove_handlers(priv);
+
+ for(i = 0; priv->ports[i] != NULL; i++) {
+ sprintf(buf, "%d", i);
+ remove_proc_entry(buf, priv->port_dir);
+ }
+ kfree(priv->ports);
+ remove_proc_entry("port", priv->driver_dir);
+
+ for(i = 0; priv->vlans[i] != NULL; i++) {
+ sprintf(buf, "%d", i);
+ remove_proc_entry(buf, priv->vlan_dir);
+ }
+ kfree(priv->vlans);
+ remove_proc_entry("vlan", priv->driver_dir);
+
+ remove_proc_entry(driver->interface, switch_root);
+
+ if (priv->nr == (drv_num - 1))
+ drv_num--;
+
+ kfree(priv);
+}
+
+switch_config global_driver_handlers[] = {
+ {"driver", handle_driver_name, NULL},
+ {"version", handle_driver_version, NULL},
+ {NULL, NULL, NULL}
+};
+
+static int do_register(switch_driver *driver)
+{
+ switch_priv *priv;
+ int i;
+ char buf[4];
+
+ priv = kmalloc(sizeof(switch_priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+ driver->data = (void *) priv;
+
+ priv->ports = kmalloc((driver->ports + 1) * sizeof(struct proc_dir_entry *),
+ GFP_KERNEL);
+ if (!priv->ports) {
+ kfree(priv);
+ return -ENOMEM;
+ }
+ priv->vlans = kmalloc((driver->vlans + 1) * sizeof(struct proc_dir_entry *),
+ GFP_KERNEL);
+ if (!priv->vlans) {
+ kfree(priv->ports);
+ kfree(priv);
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&priv->data.list);
+
+ priv->nr = drv_num++;
+ priv->driver_dir = proc_mkdir(driver->interface, switch_root);
+ if (driver->driver_handlers != NULL) {
+ add_handlers(driver, driver->driver_handlers, priv->driver_dir, 0);
+ add_handlers(driver, global_driver_handlers, priv->driver_dir, 0);
+ }
+
+ priv->port_dir = proc_mkdir("port", priv->driver_dir);
+ for (i = 0; i < driver->ports; i++) {
+ sprintf(buf, "%d", i);
+ priv->ports[i] = proc_mkdir(buf, priv->port_dir);
+ if (driver->port_handlers != NULL)
+ add_handlers(driver, driver->port_handlers, priv->ports[i], i);
+ }
+ priv->ports[i] = NULL;
+
+ priv->vlan_dir = proc_mkdir("vlan", priv->driver_dir);
+ for (i = 0; i < driver->vlans; i++) {
+ sprintf(buf, "%d", i);
+ priv->vlans[i] = proc_mkdir(buf, priv->vlan_dir);
+ if (driver->vlan_handlers != NULL)
+ add_handlers(driver, driver->vlan_handlers, priv->vlans[i], i);
+ }
+ priv->vlans[i] = NULL;
+
+
+ return 0;
+}
+
+static inline int isspace(char c) {
+ switch(c) {
+ case ' ':
+ case 0x09:
+ case 0x0a:
+ case 0x0d:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+#define toupper(c) (islower(c) ? ((c) ^ 0x20) : (c))
+#define islower(c) (((unsigned char)((c) - 'a')) < 26)
+
+int switch_parse_media(char *buf)
+{
+ char *str = buf;
+ while (*buf != 0) {
+ *buf = toupper(*buf);
+ buf++;
+ }
+
+ if (strncmp(str, "AUTO", 4) == 0)
+ return SWITCH_MEDIA_AUTO;
+ else if (strncmp(str, "100FD", 5) == 0)
+ return SWITCH_MEDIA_100 | SWITCH_MEDIA_FD;
+ else if (strncmp(str, "100HD", 5) == 0)
+ return SWITCH_MEDIA_100;
+ else if (strncmp(str, "10FD", 4) == 0)
+ return SWITCH_MEDIA_FD;
+ else if (strncmp(str, "10HD", 4) == 0)
+ return 0;
+ else return -1;
+}
+
+int switch_print_media(char *buf, int media)
+{
+ int len = 0;
+
+ if (media & SWITCH_MEDIA_AUTO)
+ len = sprintf(buf, "Auto");
+ else if (media == (SWITCH_MEDIA_100 | SWITCH_MEDIA_FD))
+ len = sprintf(buf, "100FD");
+ else if (media == SWITCH_MEDIA_100)
+ len = sprintf(buf, "100HD");
+ else if (media == SWITCH_MEDIA_FD)
+ len = sprintf(buf, "10FD");
+ else if (media == 0)
+ len = sprintf(buf, "10HD");
+ else
+ len = sprintf(buf, "Invalid");
+
+ return len;
+}
+
+switch_vlan_config *switch_parse_vlan(switch_driver *driver, char *buf)
+{
+ switch_vlan_config *c;
+ int j, u, p, s;
+
+ c = kzalloc(sizeof(switch_vlan_config), GFP_KERNEL);
+ if (!c)
+ return NULL;
+
+ while (isspace(*buf)) buf++;
+ j = 0;
+ while (*buf >= '0' && *buf <= '9') {
+ j *= 10;
+ j += *buf++ - '0';
+
+ u = ((j == driver->cpuport) ? 0 : 1);
+ p = 0;
+ s = !(*buf >= '0' && *buf <= '9');
+
+ if (s) {
+ while (s && !isspace(*buf) && (*buf != 0)) {
+ switch(*buf) {
+ case 'u':
+ u = 1;
+ break;
+ case 't':
+ u = 0;
+ break;
+ case '*':
+ p = 1;
+ break;
+ }
+ buf++;
+ }
+ c->port |= (1 << j);
+ if (u)
+ c->untag |= (1 << j);
+ if (p)
+ c->pvid |= (1 << j);
+
+ j = 0;
+ }
+
+ while (isspace(*buf)) buf++;
+ }
+ if (*buf != 0) {
+ kfree(c);
+ return NULL;
+ }
+
+ c->port &= (1 << driver->ports) - 1;
+ c->untag &= (1 << driver->ports) - 1;
+ c->pvid &= (1 << driver->ports) - 1;
+
+ return c;
+}
+
+
+int switch_device_registered (char* device) {
+ struct list_head *pos;
+
+ list_for_each(pos, &drivers.list) {
+ if (strcmp(list_entry(pos, switch_driver, list)->interface, device) == 0) {
+ printk("There is already a switch registered on the device '%s'\n", device);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+
+int switch_register_driver(switch_driver *driver)
+{
+ struct list_head *pos;
+ switch_driver *new;
+ int ret;
+
+ list_for_each(pos, &drivers.list) {
+ if (strcmp(list_entry(pos, switch_driver, list)->name, driver->name) == 0) {
+ printk("Switch driver '%s' already exists in the kernel\n", driver->name);
+ return -EINVAL;
+ }
+ if (strcmp(list_entry(pos, switch_driver, list)->interface, driver->interface) == 0) {
+ printk("There is already a switch registered on the device '%s'\n", driver->interface);
+ return -EINVAL;
+ }
+ }
+
+ new = kmalloc(sizeof(switch_driver), GFP_KERNEL);
+ if (!new)
+ return -ENOMEM;
+ memcpy(new, driver, sizeof(switch_driver));
+ new->name = strdup(driver->name);
+ new->interface = strdup(driver->interface);
+
+ if ((ret = do_register(new)) < 0) {
+ kfree(new->name);
+ kfree(new);
+ return ret;
+ }
+ INIT_LIST_HEAD(&new->list);
+ list_add(&new->list, &drivers.list);
+
+ return 0;
+}
+
+void switch_unregister_driver(char *name) {
+ struct list_head *pos, *q;
+ switch_driver *tmp;
+
+ list_for_each_safe(pos, q, &drivers.list) {
+ tmp = list_entry(pos, switch_driver, list);
+ if (strcmp(tmp->name, name) == 0) {
+ do_unregister(tmp);
+ list_del(pos);
+ kfree(tmp->name);
+ kfree(tmp);
+
+ return;
+ }
+ }
+}
+
+static int __init switch_init(void)
+{
+ if ((switch_root = proc_mkdir("switch", NULL)) == NULL) {
+ printk("%s: proc_mkdir failed.\n", __FILE__);
+ return -ENODEV;
+ }
+
+ INIT_LIST_HEAD(&drivers.list);
+
+ return 0;
+}
+
+static void __exit switch_exit(void)
+{
+ remove_proc_entry("switch", NULL);
+}
+
+MODULE_AUTHOR("Felix Fietkau <openwrt@nbd.name>");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(switch_device_registered);
+EXPORT_SYMBOL(switch_register_driver);
+EXPORT_SYMBOL(switch_unregister_driver);
+EXPORT_SYMBOL(switch_parse_vlan);
+EXPORT_SYMBOL(switch_parse_media);
+EXPORT_SYMBOL(switch_print_media);
+
+module_init(switch_init);
+module_exit(switch_exit);
diff --git a/package/switch/src/switch-core.h b/package/switch/src/switch-core.h
new file mode 100644
index 000000000..a2114cf92
--- /dev/null
+++ b/package/switch/src/switch-core.h
@@ -0,0 +1,52 @@
+#ifndef __SWITCH_CORE_H
+#define __SWITCH_CORE_H
+
+#include <linux/version.h>
+#include <linux/list.h>
+#define SWITCH_MAX_BUFSZ 4096
+
+#define SWITCH_MEDIA_AUTO 1
+#define SWITCH_MEDIA_100 2
+#define SWITCH_MEDIA_FD 4
+
+typedef int (*switch_handler)(void *driver, char *buf, int nr);
+
+typedef struct {
+ const char *name;
+ switch_handler read, write;
+} switch_config;
+
+typedef struct {
+ struct list_head list;
+ const char *name;
+ const char *version;
+ const char *interface;
+ int cpuport;
+ int ports;
+ int vlans;
+ const switch_config *driver_handlers, *port_handlers, *vlan_handlers;
+ void *data;
+ void *priv;
+} switch_driver;
+
+typedef struct {
+ u32 port, untag, pvid;
+} switch_vlan_config;
+
+
+extern int switch_device_registered (char* device);
+extern int switch_register_driver(switch_driver *driver);
+extern void switch_unregister_driver(char *name);
+extern switch_vlan_config *switch_parse_vlan(switch_driver *driver, char *buf);
+extern int switch_parse_media(char *buf);
+extern int switch_print_media(char *buf, int media);
+
+static inline char *strdup(const char *str)
+{
+ char *new = kmalloc(strlen(str) + 1, GFP_KERNEL);
+ strcpy(new, str);
+ return new;
+}
+
+
+#endif
diff --git a/package/switch/src/switch-robo.c b/package/switch/src/switch-robo.c
new file mode 100644
index 000000000..f1160c889
--- /dev/null
+++ b/package/switch/src/switch-robo.c
@@ -0,0 +1,583 @@
+/*
+ * Broadcom BCM5325E/536x switch configuration module
+ *
+ * Copyright (C) 2005 Felix Fietkau <nbd@nbd.name>
+ * Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
+ * Based on 'robocfg' by Oleg I. Vdovikin
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/if.h>
+#include <linux/if_arp.h>
+#include <linux/sockios.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+
+#include "switch-core.h"
+#include "etc53xx.h"
+
+#ifdef CONFIG_BCM47XX
+#include <nvram.h>
+#endif
+
+#define DRIVER_NAME "bcm53xx"
+#define DRIVER_VERSION "0.02"
+#define PFX "roboswitch: "
+
+#define ROBO_PHY_ADDR 0x1E /* robo switch phy address */
+#define ROBO_PHY_ADDR_TG3 0x01 /* Tigon3 PHY address */
+#define ROBO_PHY_ADDR_BCM63XX 0x00 /* BCM63XX PHY address */
+
+/* MII registers */
+#define REG_MII_PAGE 0x10 /* MII Page register */
+#define REG_MII_ADDR 0x11 /* MII Address register */
+#define REG_MII_DATA0 0x18 /* MII Data register 0 */
+
+#define REG_MII_PAGE_ENABLE 1
+#define REG_MII_ADDR_WRITE 1
+#define REG_MII_ADDR_READ 2
+
+/* Robo device ID register (in ROBO_MGMT_PAGE) */
+#define ROBO_DEVICE_ID 0x30
+#define ROBO_DEVICE_ID_5325 0x25 /* Faked */
+#define ROBO_DEVICE_ID_5395 0x95
+#define ROBO_DEVICE_ID_5397 0x97
+#define ROBO_DEVICE_ID_5398 0x98
+#define ROBO_DEVICE_ID_53115 0x3115
+
+/* Private et.o ioctls */
+#define SIOCGETCPHYRD (SIOCDEVPRIVATE + 9)
+#define SIOCSETCPHYWR (SIOCDEVPRIVATE + 10)
+
+/* Data structure for a Roboswitch device. */
+struct robo_switch {
+ char *device; /* The device name string (ethX) */
+ u16 devid; /* ROBO_DEVICE_ID_53xx */
+ bool is_5350;
+ struct ifreq ifr;
+ struct net_device *dev;
+ unsigned char port[6];
+};
+
+/* Currently we can only have one device in the system. */
+static struct robo_switch robo;
+
+
+static int do_ioctl(int cmd)
+{
+ mm_segment_t old_fs = get_fs();
+ int ret;
+
+ set_fs(KERNEL_DS);
+ ret = robo.dev->netdev_ops->ndo_do_ioctl(robo.dev, &robo.ifr, cmd);
+ set_fs(old_fs);
+
+ return ret;
+}
+
+static u16 mdio_read(__u16 phy_id, __u8 reg)
+{
+ struct mii_ioctl_data *mii = if_mii(&robo.ifr);
+ int err;
+
+ mii->phy_id = phy_id;
+ mii->reg_num = reg;
+
+ err = do_ioctl(SIOCGMIIREG);
+ if (err < 0) {
+ printk(KERN_ERR PFX
+ "[%s:%d] SIOCGMIIREG failed! err: %i\n", __FILE__, __LINE__, err);
+
+ return 0xffff;
+ }
+
+ return mii->val_out;
+}
+
+static void mdio_write(__u16 phy_id, __u8 reg, __u16 val)
+{
+ struct mii_ioctl_data *mii = if_mii(&robo.ifr);
+ int err;
+
+ mii->phy_id = phy_id;
+ mii->reg_num = reg;
+ mii->val_in = val;
+
+ err = do_ioctl(SIOCSMIIREG);
+ if (err < 0) {
+ printk(KERN_ERR PFX
+ "[%s:%d] SIOCSMIIREG failed! err: %i\n", __FILE__, __LINE__, err);
+ return;
+ }
+}
+
+static int robo_reg(__u8 page, __u8 reg, __u8 op)
+{
+ int i = 3;
+
+ /* set page number */
+ mdio_write(ROBO_PHY_ADDR, REG_MII_PAGE,
+ (page << 8) | REG_MII_PAGE_ENABLE);
+
+ /* set register address */
+ mdio_write(ROBO_PHY_ADDR, REG_MII_ADDR,
+ (reg << 8) | op);
+
+ /* check if operation completed */
+ while (i--) {
+ if ((mdio_read(ROBO_PHY_ADDR, REG_MII_ADDR) & 3) == 0)
+ return 0;
+ }
+
+ printk(KERN_ERR PFX "[%s:%d] timeout in robo_reg!\n", __FILE__, __LINE__);
+
+ return 0;
+}
+
+/*
+static void robo_read(__u8 page, __u8 reg, __u16 *val, int count)
+{
+ int i;
+
+ robo_reg(page, reg, REG_MII_ADDR_READ);
+
+ for (i = 0; i < count; i++)
+ val[i] = mdio_read(ROBO_PHY_ADDR, REG_MII_DATA0 + i);
+}
+*/
+
+static __u16 robo_read16(__u8 page, __u8 reg)
+{
+ robo_reg(page, reg, REG_MII_ADDR_READ);
+
+ return mdio_read(ROBO_PHY_ADDR, REG_MII_DATA0);
+}
+
+static __u32 robo_read32(__u8 page, __u8 reg)
+{
+ robo_reg(page, reg, REG_MII_ADDR_READ);
+
+ return mdio_read(ROBO_PHY_ADDR, REG_MII_DATA0) +
+ (mdio_read(ROBO_PHY_ADDR, REG_MII_DATA0 + 1) << 16);
+}
+
+static void robo_write16(__u8 page, __u8 reg, __u16 val16)
+{
+ /* write data */
+ mdio_write(ROBO_PHY_ADDR, REG_MII_DATA0, val16);
+
+ robo_reg(page, reg, REG_MII_ADDR_WRITE);
+}
+
+static void robo_write32(__u8 page, __u8 reg, __u32 val32)
+{
+ /* write data */
+ mdio_write(ROBO_PHY_ADDR, REG_MII_DATA0, val32 & 65535);
+ mdio_write(ROBO_PHY_ADDR, REG_MII_DATA0 + 1, val32 >> 16);
+
+ robo_reg(page, reg, REG_MII_ADDR_WRITE);
+}
+
+/* checks that attached switch is 5325E/5350 */
+static int robo_vlan5350(void)
+{
+ /* set vlan access id to 15 and read it back */
+ __u16 val16 = 15;
+ robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
+
+ /* 5365 will refuse this as it does not have this reg */
+ return (robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350) == val16);
+}
+
+static int robo_switch_enable(void)
+{
+ unsigned int i, last_port;
+ u16 val;
+#ifdef CONFIG_BCM47XX
+ char buf[20];
+#endif
+
+ val = robo_read16(ROBO_CTRL_PAGE, ROBO_SWITCH_MODE);
+ if (!(val & (1 << 1))) {
+ /* Unmanaged mode */
+ val &= ~(1 << 0);
+ /* With forwarding */
+ val |= (1 << 1);
+ robo_write16(ROBO_CTRL_PAGE, ROBO_SWITCH_MODE, val);
+ val = robo_read16(ROBO_CTRL_PAGE, ROBO_SWITCH_MODE);
+ if (!(val & (1 << 1))) {
+ printk("Failed to enable switch\n");
+ return -EBUSY;
+ }
+
+ last_port = (robo.devid == ROBO_DEVICE_ID_5398) ?
+ ROBO_PORT6_CTRL : ROBO_PORT3_CTRL;
+ for (i = ROBO_PORT0_CTRL; i < last_port + 1; i++)
+ robo_write16(ROBO_CTRL_PAGE, i, 0);
+ }
+
+#ifdef CONFIG_BCM47XX
+ /* WAN port LED, except for Netgear WGT634U */
+ if (nvram_getenv("nvram_type", buf, sizeof(buf)) >= 0) {
+ if (strcmp(buf, "cfe") != 0)
+ robo_write16(ROBO_CTRL_PAGE, 0x16, 0x1F);
+ }
+#endif
+ return 0;
+}
+
+static void robo_switch_reset(void)
+{
+ if ((robo.devid == ROBO_DEVICE_ID_5395) ||
+ (robo.devid == ROBO_DEVICE_ID_5397) ||
+ (robo.devid == ROBO_DEVICE_ID_5398)) {
+ /* Trigger a software reset. */
+ robo_write16(ROBO_CTRL_PAGE, 0x79, 0x83);
+ mdelay(500);
+ robo_write16(ROBO_CTRL_PAGE, 0x79, 0);
+ }
+}
+
+static int robo_probe(char *devname)
+{
+ __u32 phyid;
+ unsigned int i;
+ int err = 1;
+
+ printk(KERN_INFO PFX "Probing device %s: ", devname);
+ strcpy(robo.ifr.ifr_name, devname);
+
+ if ((robo.dev = dev_get_by_name(&init_net, devname)) == NULL) {
+ printk("No such device\n");
+ return 1;
+ }
+ if (!robo.dev->netdev_ops || !robo.dev->netdev_ops->ndo_do_ioctl) {
+ printk("ndo_do_ioctl not implemented in ethernet driver\n");
+ return 1;
+ }
+
+ robo.device = devname;
+ for (i = 0; i < 5; i++)
+ robo.port[i] = i;
+ robo.port[5] = 8;
+
+ /* try access using MII ioctls - get phy address */
+ if (do_ioctl(SIOCGMIIPHY) < 0) {
+ printk("error while accessing MII phy registers with ioctls\n");
+ goto done;
+ }
+
+ /* got phy address check for robo address */
+ struct mii_ioctl_data *mii = if_mii(&robo.ifr);
+ if ((mii->phy_id != ROBO_PHY_ADDR) &&
+ (mii->phy_id != ROBO_PHY_ADDR_BCM63XX) &&
+ (mii->phy_id != ROBO_PHY_ADDR_TG3)) {
+ printk("Invalid phy address (%d)\n", mii->phy_id);
+ goto done;
+ }
+
+ phyid = mdio_read(ROBO_PHY_ADDR, 0x2) |
+ (mdio_read(ROBO_PHY_ADDR, 0x3) << 16);
+
+ if (phyid == 0xffffffff || phyid == 0x55210022) {
+ printk("No Robo switch in managed mode found, phy_id = 0x%08x\n", phyid);
+ goto done;
+ }
+
+ /* Get the device ID */
+ for (i = 0; i < 10; i++) {
+ robo.devid = robo_read16(ROBO_MGMT_PAGE, ROBO_DEVICE_ID);
+ if (robo.devid)
+ break;
+ udelay(10);
+ }
+ if (!robo.devid)
+ robo.devid = ROBO_DEVICE_ID_5325; /* Fake it */
+ robo.is_5350 = robo_vlan5350();
+
+ robo_switch_reset();
+ err = robo_switch_enable();
+ if (err)
+ goto done;
+ err = 0;
+
+ printk("found a 5%s%x!%s\n", robo.devid & 0xff00 ? "" : "3", robo.devid,
+ robo.is_5350 ? " It's a 5350." : "");
+
+done:
+ if (err) {
+ dev_put(robo.dev);
+ robo.dev = NULL;
+ }
+ return err;
+}
+
+
+static int handle_vlan_port_read(void *driver, char *buf, int nr)
+{
+ __u16 val16;
+ int len = 0;
+ int j;
+
+ val16 = (nr) /* vlan */ | (0 << 12) /* read */ | (1 << 13) /* enable */;
+
+ if (robo.is_5350) {
+ u32 val32;
+ robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
+ /* actual read */
+ val32 = robo_read32(ROBO_VLAN_PAGE, ROBO_VLAN_READ);
+ if ((val32 & (1 << 20)) /* valid */) {
+ for (j = 0; j < 6; j++) {
+ if (val32 & (1 << j)) {
+ len += sprintf(buf + len, "%d", j);
+ if (val32 & (1 << (j + 6))) {
+ if (j == 5) buf[len++] = 'u';
+ } else {
+ buf[len++] = 't';
+ if (robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (j << 1)) == nr)
+ buf[len++] = '*';
+ }
+ buf[len++] = '\t';
+ }
+ }
+ len += sprintf(buf + len, "\n");
+ }
+ } else {
+ robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16);
+ /* actual read */
+ val16 = robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_READ);
+ if ((val16 & (1 << 14)) /* valid */) {
+ for (j = 0; j < 6; j++) {
+ if (val16 & (1 << j)) {
+ len += sprintf(buf + len, "%d", j);
+ if (val16 & (1 << (j + 7))) {
+ if (j == 5) buf[len++] = 'u';
+ } else {
+ buf[len++] = 't';
+ if (robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (j << 1)) == nr)
+ buf[len++] = '*';
+ }
+ buf[len++] = '\t';
+ }
+ }
+ len += sprintf(buf + len, "\n");
+ }
+ }
+
+ buf[len] = '\0';
+
+ return len;
+}
+
+static int handle_vlan_port_write(void *driver, char *buf, int nr)
+{
+ switch_driver *d = (switch_driver *) driver;
+ switch_vlan_config *c = switch_parse_vlan(d, buf);
+ int j;
+ __u16 val16;
+
+ if (c == NULL)
+ return -EINVAL;
+
+ for (j = 0; j < d->ports; j++) {
+ if ((c->untag | c->pvid) & (1 << j))
+ /* change default vlan tag */
+ robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (j << 1), nr);
+ }
+
+ /* write config now */
+
+ if (robo.devid != ROBO_DEVICE_ID_5325) {
+ __u8 regoff = ((robo.devid == ROBO_DEVICE_ID_5395) ||
+ (robo.devid == ROBO_DEVICE_ID_53115)) ? 0x20 : 0;
+
+ robo_write32(ROBO_ARLIO_PAGE, 0x63 + regoff, (c->untag << 9) | c->port);
+ robo_write16(ROBO_ARLIO_PAGE, 0x61 + regoff, nr);
+ robo_write16(ROBO_ARLIO_PAGE, 0x60 + regoff, 1 << 7);
+ kfree(c);
+ return 0;
+ }
+
+ val16 = (nr) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */;
+ if (robo.is_5350) {
+ robo_write32(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5350,
+ (1 << 20) /* valid */ | (c->untag << 6) | c->port);
+ robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16);
+ } else {
+ robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE,
+ (1 << 14) /* valid */ | (c->untag << 7) | c->port);
+ robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16);
+ }
+
+ kfree(c);
+ return 0;
+}
+
+#define set_switch(state) \
+ robo_write16(ROBO_CTRL_PAGE, ROBO_SWITCH_MODE, (robo_read16(ROBO_CTRL_PAGE, ROBO_SWITCH_MODE) & ~2) | (state ? 2 : 0));
+
+static int handle_enable_read(void *driver, char *buf, int nr)
+{
+ return sprintf(buf, "%d\n", (((robo_read16(ROBO_CTRL_PAGE, ROBO_SWITCH_MODE) & 2) == 2) ? 1 : 0));
+}
+
+static int handle_enable_write(void *driver, char *buf, int nr)
+{
+ set_switch(buf[0] == '1');
+
+ return 0;
+}
+
+static int handle_enable_vlan_read(void *driver, char *buf, int nr)
+{
+ return sprintf(buf, "%d\n", (((robo_read16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL0) & (1 << 7)) == (1 << 7)) ? 1 : 0));
+}
+
+static int handle_enable_vlan_write(void *driver, char *buf, int nr)
+{
+ int disable = ((buf[0] != '1') ? 1 : 0);
+
+ robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL0, disable ? 0 :
+ (1 << 7) /* 802.1Q VLAN */ | (3 << 5) /* mac check and hash */);
+ robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL1, disable ? 0 :
+ (robo.devid == ROBO_DEVICE_ID_5325 ? (1 << 1) :
+ 0) | (1 << 2) | (1 << 3)); /* RSV multicast */
+
+ if (robo.devid != ROBO_DEVICE_ID_5325)
+ return 0;
+
+ robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL4, disable ? 0 :
+ (1 << 6) /* drop invalid VID frames */);
+ robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_CTRL5, disable ? 0 :
+ (1 << 3) /* drop miss V table frames */);
+
+ return 0;
+}
+
+static int handle_reset(void *driver, char *buf, int nr)
+{
+ switch_driver *d = (switch_driver *) driver;
+ int j;
+ __u16 val16;
+
+ /* disable switching */
+ set_switch(0);
+
+ /* reset vlans */
+ for (j = 0; j <= ((robo.is_5350) ? VLAN_ID_MAX5350 : VLAN_ID_MAX); j++) {
+ /* write config now */
+ val16 = (j) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */;
+ if (robo.is_5350)
+ robo_write32(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5350, 0);
+ else
+ robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_WRITE, 0);
+ robo_write16(ROBO_VLAN_PAGE, robo.is_5350 ? ROBO_VLAN_TABLE_ACCESS_5350 :
+ ROBO_VLAN_TABLE_ACCESS,
+ val16);
+ }
+
+ /* reset ports to a known good state */
+ for (j = 0; j < d->ports; j++) {
+ robo_write16(ROBO_CTRL_PAGE, robo.port[j], 0x0000);
+ robo_write16(ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (j << 1), 0);
+ }
+
+ /* enable switching */
+ set_switch(1);
+
+ /* enable vlans */
+ handle_enable_vlan_write(driver, "1", 0);
+
+ return 0;
+}
+
+static int __init robo_init(void)
+{
+ int notfound = 1;
+ char *device;
+
+ device = strdup("ethX");
+ for (device[3] = '0'; (device[3] <= '3') && notfound; device[3]++) {
+ if (! switch_device_registered (device))
+ notfound = robo_probe(device);
+ }
+ device[3]--;
+
+ if (notfound) {
+ kfree(device);
+ return -ENODEV;
+ } else {
+ static const switch_config cfg[] = {
+ {
+ .name = "enable",
+ .read = handle_enable_read,
+ .write = handle_enable_write
+ }, {
+ .name = "enable_vlan",
+ .read = handle_enable_vlan_read,
+ .write = handle_enable_vlan_write
+ }, {
+ .name = "reset",
+ .read = NULL,
+ .write = handle_reset
+ }, { NULL, },
+ };
+ static const switch_config vlan[] = {
+ {
+ .name = "ports",
+ .read = handle_vlan_port_read,
+ .write = handle_vlan_port_write
+ }, { NULL, },
+ };
+ switch_driver driver = {
+ .name = DRIVER_NAME,
+ .version = DRIVER_VERSION,
+ .interface = device,
+ .cpuport = 5,
+ .ports = 6,
+ .vlans = 16,
+ .driver_handlers = cfg,
+ .port_handlers = NULL,
+ .vlan_handlers = vlan,
+ };
+ if (robo.devid != ROBO_DEVICE_ID_5325) {
+ driver.ports = 9;
+ driver.cpuport = 8;
+ }
+
+ return switch_register_driver(&driver);
+ }
+}
+
+static void __exit robo_exit(void)
+{
+ switch_unregister_driver(DRIVER_NAME);
+ if (robo.dev)
+ dev_put(robo.dev);
+ kfree(robo.device);
+}
+
+
+MODULE_AUTHOR("Felix Fietkau <openwrt@nbd.name>");
+MODULE_LICENSE("GPL");
+
+module_init(robo_init);
+module_exit(robo_exit);
diff --git a/package/toolchain/Makefile b/package/toolchain/Makefile
new file mode 100644
index 000000000..fac6ecd6c
--- /dev/null
+++ b/package/toolchain/Makefile
@@ -0,0 +1,560 @@
+#
+# Copyright (C) 2007-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+PKG_NAME:=toolchain
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+ifneq ($(DUMP),1)
+ LIBGCC_VERSION:=$(GCC_VERSION)
+else
+ LIBC_VERSION:=<LIBC_VERSION>
+ LIBGCC_VERSION:=<LIBGCC_VERSION>
+endif
+
+define Package/gcc/Default
+ SECTION:=libs
+ CATEGORY:=Base system
+ URL:=http://gcc.gnu.org/
+ VERSION:=$(LIBGCC_VERSION)-$(PKG_RELEASE)
+endef
+
+define Package/libgcc
+$(call Package/gcc/Default)
+ TITLE:=GCC support library
+endef
+
+define Package/libgcc/config
+ menu "Configuration"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_libgcc
+
+ config LIBGCC_ROOT_DIR
+ string
+ prompt "libgcc shared library base directory"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_libgcc
+ default TOOLCHAIN_ROOT if !NATIVE_TOOLCHAIN
+ default "/" if NATIVE_TOOLCHAIN
+
+ config LIBGCC_FILE_SPEC
+ string
+ prompt "libgcc shared library files (use wildcards)"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_libgcc
+ default "./lib/libgcc_s.so.*"
+
+ endmenu
+endef
+
+
+define Package/libssp
+$(call Package/gcc/Default)
+ DEPENDS+=@SSP_SUPPORT
+ TITLE:=GCC support library
+endef
+
+define Package/libssp/config
+ menu "Configuration"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_libssp
+
+ config LIBSSP_ROOT_DIR
+ string
+ prompt "libssp shared library base directory"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_libssp
+ default TOOLCHAIN_ROOT if !NATIVE_TOOLCHAIN
+ default "/" if NATIVE_TOOLCHAIN
+
+ config LIBSSP_FILE_SPEC
+ string
+ prompt "libssp shared library files (use wildcards)"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_libssp
+ default "./lib/libssp.so.*"
+
+ endmenu
+endef
+
+
+define Package/libstdcpp
+$(call Package/gcc/Default)
+ NAME:=libstdc++
+ TITLE:=GNU Standard C++ Library v3
+ DEPENDS+=@INSTALL_LIBSTDCPP
+endef
+
+define Package/libstdcpp/config
+ menu "Configuration"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_libstdcpp
+
+ config LIBSTDCPP_ROOT_DIR
+ string
+ prompt "libstdcpp shared library base directory"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_libstdcpp
+ default TOOLCHAIN_ROOT if !NATIVE_TOOLCHAIN
+ default "/" if NATIVE_TOOLCHAIN
+
+ config LIBSTDCPP_FILE_SPEC
+ string
+ prompt "libstdc++ shared library files (use wildcards)"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_libstdcpp
+ default "./lib/libstdc++.so.*"
+
+ endmenu
+endef
+
+
+define Package/libc/Default
+ SECTION:=libs
+ CATEGORY:=Base system
+ VERSION:=$(LIBC_VERSION)-$(PKG_RELEASE)
+ DEPENDS:=+libgcc
+ URL:=$(LIBC_URL)
+ PKG_FLAGS:=hold essential
+endef
+
+
+define Package/libc
+$(call Package/libc/Default)
+ TITLE:=C library
+endef
+
+define Package/libc/config
+ menu "Configuration"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_libc
+
+ config LIBC_ROOT_DIR
+ string
+ prompt "libc shared library base directory"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_libc
+ default TOOLCHAIN_ROOT if !NATIVE_TOOLCHAIN
+ default "/" if NATIVE_TOOLCHAIN
+
+ config LIBC_FILE_SPEC
+ string
+ prompt "libc shared library files (use wildcards)"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_libc
+ default "./lib/ld{-*.so,-linux*.so.*} ./lib/lib{anl,c,cidn,crypt,dl,m,nsl,nss_dns,nss_files,resolv,util}{-*.so,.so.*}"
+
+ endmenu
+endef
+
+
+define Package/libpthread
+$(call Package/libc/Default)
+ TITLE:=POSIX thread library
+endef
+
+define Package/libpthread/config
+ menu "Configuration"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_libpthread
+
+ config LIBPTHREAD_ROOT_DIR
+ string
+ prompt "libpthread shared library base directory"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_libpthread
+ default TOOLCHAIN_ROOT if !NATIVE_TOOLCHAIN
+ default "/" if NATIVE_TOOLCHAIN
+
+ config LIBPTHREAD_FILE_SPEC
+ string
+ prompt "libpthread shared library files (use wildcards)"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_libpthread
+ default "./lib/libpthread{-*.so,.so.*}"
+
+ endmenu
+endef
+
+
+define Package/librt
+$(call Package/libc/Default)
+ TITLE:=POSIX.1b RealTime extension library
+ DEPENDS:=+libpthread
+endef
+
+define Package/librt/config
+ menu "Configuration"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_librt
+
+ config LIBRT_ROOT_DIR
+ string
+ prompt "librt shared library base directory"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_librt
+ default TOOLCHAIN_ROOT if !NATIVE_TOOLCHAIN
+ default "/" if NATIVE_TOOLCHAIN
+
+ config LIBRT_FILE_SPEC
+ string
+ prompt "librt shared library files (use wildcards)"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_librt
+ default "./lib/librt{-*.so,.so.*}"
+
+ endmenu
+endef
+
+
+define Package/libgfortran
+$(call Package/gcc/Default)
+ TITLE:=GFortran support library
+ DEPENDS+=@INSTALL_GFORTRAN
+endef
+
+define Package/libgfortran/config
+ menu "Configuration"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_libgfortran
+
+ config LIBGFORTRAN_ROOT_DIR
+ string
+ prompt "libgfortran shared library base directory"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_libgfortran
+ default TOOLCHAIN_ROOT if !NATIVE_TOOLCHAIN
+ default "/" if NATIVE_TOOLCHAIN
+
+ config LIBGFORTRAN_FILE_SPEC
+ string
+ prompt "libgfortran shared library files (use wildcards)"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_libgfortran
+ default "./usr/lib/libgfortran.so.*"
+
+ endmenu
+endef
+
+define Package/ldd
+$(call Package/libc/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=LDD trace utility
+endef
+
+define Package/ldd/config
+ menu "Configuration"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_ldd
+
+ config LDD_ROOT_DIR
+ string
+ prompt "ldd trace utility base directory"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_ldd
+ default TOOLCHAIN_ROOT if !NATIVE_TOOLCHAIN
+ default "/" if NATIVE_TOOLCHAIN
+
+ config LDD_FILE_SPEC
+ string
+ prompt "ldd trace utility file"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_ldd
+ default "./usr/bin/ldd"
+
+ endmenu
+endef
+
+
+define Package/ldconfig
+$(call Package/libc/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Shared library path configuration
+endef
+
+define Package/ldconfig/config
+ menu "Configuration"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_ldconfig
+
+ config LDCONFIG_ROOT_DIR
+ string
+ prompt "ldconfig base directory"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_ldconfig
+ default TOOLCHAIN_ROOT if !NATIVE_TOOLCHAIN
+ default "/" if NATIVE_TOOLCHAIN
+
+ config LDCONFIG_FILE_SPEC
+ string
+ prompt "ldconfig file"
+ depends EXTERNAL_TOOLCHAIN && PACKAGE_ldconfig
+ default "./sbin/ldconfig"
+
+ endmenu
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+endef
+
+LIBGCC_A=$(wildcard $(TOOLCHAIN_DIR)/lib/gcc/*/*/libgcc_pic.a)
+LIBGCC_MAP=$(wildcard $(TOOLCHAIN_DIR)/lib/gcc/*/*/libgcc.map)
+LIBGCC_SO=$(wildcard $(TOOLCHAIN_DIR)/lib/libgcc_s.so.*)
+ifeq ($(CONFIG_EXTERNAL_TOOLCHAIN),)
+ ifneq ($(if $(CONFIG_USE_UCLIBC),$(CONFIG_GCC_VERSION_LINARO)),)
+ BUILD_LIBGCC:=$(if $(CONFIG_avr32)$(CONFIG_m68k)$(CONFIG_powerpc),,$(PKG_BUILD_DIR)/libgcc_s.so.*)
+ endif
+endif
+
+ifneq ($(BUILD_LIBGCC),)
+ define Build/Compile/uClibc
+ $(SCRIPT_DIR)/relink-lib.sh \
+ "$(TARGET_CROSS)" \
+ "$(wildcard $(TOOLCHAIN_DIR)/lib/libc_so.a)" \
+ "$(wildcard $(TOOLCHAIN_DIR)/lib/libc_so.a)" \
+ "$(patsubst $(TOOLCHAIN_DIR)/lib/%,$(PKG_BUILD_DIR)/%,$(wildcard $(TOOLCHAIN_DIR)/lib/libuClibc-*.so))" \
+ -Wl,-init,__uClibc_init -Wl,-soname=libc.so.0 \
+ $(BUILD_LIBGCC)
+ $(SCRIPT_DIR)/relink-lib.sh \
+ "$(TARGET_CROSS)" \
+ "$(wildcard $(TOOLCHAIN_DIR)/lib/libcrypt-*.so)" \
+ "$(wildcard $(TOOLCHAIN_DIR)/lib/libcrypt_pic.a)" \
+ "$(patsubst $(TOOLCHAIN_DIR)/lib/%,$(PKG_BUILD_DIR)/%,$(wildcard $(TOOLCHAIN_DIR)/lib/libcrypt-*.so))" \
+ $(BUILD_LIBGCC) \
+ -Wl,-soname=libcrypt.so.0
+ $(SCRIPT_DIR)/relink-lib.sh \
+ "$(TARGET_CROSS)" \
+ "$(wildcard $(TOOLCHAIN_DIR)/lib/libm-*.so)" \
+ "$(wildcard $(TOOLCHAIN_DIR)/lib/libm_pic.a)" \
+ "$(patsubst $(TOOLCHAIN_DIR)/lib/%,$(PKG_BUILD_DIR)/%,$(wildcard $(TOOLCHAIN_DIR)/lib/libm-*.so))" \
+ $(BUILD_LIBGCC) \
+ -Wl,-soname=libm.so.0
+ $(SCRIPT_DIR)/relink-lib.sh \
+ "$(TARGET_CROSS)" \
+ "$(wildcard $(TOOLCHAIN_DIR)/lib/libpthread-*.so)" \
+ "$(wildcard $(TOOLCHAIN_DIR)/lib/libpthread_so.a)" \
+ "$(patsubst $(TOOLCHAIN_DIR)/lib/%,$(PKG_BUILD_DIR)/%,$(wildcard $(TOOLCHAIN_DIR)/lib/libpthread-*.so))" \
+ -Wl,-z,nodelete,-z,initfirst,-init=__pthread_initialize_minimal_internal \
+ -ldl -lc $(BUILD_LIBGCC) \
+ -Wl,-soname=libpthread.so.0
+ endef
+ define Build/Compile/libgcc
+ $(SCRIPT_DIR)/relink-lib.sh \
+ "$(TARGET_CROSS)" \
+ "$(LIBGCC_SO)" \
+ "$(LIBGCC_A)" \
+ "$(patsubst $(TOOLCHAIN_DIR)/lib/%,$(PKG_BUILD_DIR)/%,$(LIBGCC_SO))" \
+ -Wl,--version-script=$(LIBGCC_MAP) -Wl,-soname=libgcc_s.so.1
+ endef
+else
+ define Build/Compile/uClibc
+ $(CP) \
+ $(TOOLCHAIN_DIR)/lib/libuClibc-*.so \
+ $(TOOLCHAIN_DIR)/lib/libcrypt-*.so \
+ $(TOOLCHAIN_DIR)/lib/libm-*.so \
+ $(TOOLCHAIN_DIR)/lib/libpthread-*.so \
+ $(PKG_BUILD_DIR)/
+ endef
+ ifneq ($(LIBGCC_SO),)
+ define Build/Compile/libgcc
+ $(CP) $(LIBGCC_SO) $(PKG_BUILD_DIR)/
+ endef
+ endif
+endif
+
+define Build/Compile/Default
+ $(call Build/Compile/libgcc)
+ $(call Build/Compile/$(LIBC))
+endef
+Build/Compile = $(Build/Compile/Default)
+
+ifeq ($(CONFIG_EXTERNAL_TOOLCHAIN),)
+
+ define Package/libgcc/install
+ $(INSTALL_DIR) $(1)/lib
+ $(if $(CONFIG_TARGET_avr32)$(CONFIG_TARGET_coldfire),,$(CP) $(TOOLCHAIN_DIR)/lib/libgcc_s.so.* $(1)/lib/)
+ endef
+
+ define Package/libgfortran/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(if $(CONFIG_TARGET_avr32)$(CONFIG_TARGET_coldfire),,$(CP) $(TOOLCHAIN_DIR)/lib/libgfortran.so.* $(1)/usr/lib/)
+ endef
+
+ define Package/libssp/install
+ $(INSTALL_DIR) $(1)/lib
+ $(CP) $(TOOLCHAIN_DIR)/lib/libssp.so.* $(1)/lib/
+ endef
+
+ define Package/libstdcpp/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(TOOLCHAIN_DIR)/lib/libstdc++.so.* $(1)/usr/lib/
+ endef
+
+ use_libutil=$(if $(CONFIG_EGLIBC_OPTION_EGLIBC_UTMP),libutil)
+ use_libnsl=$(if $(CONFIG_EGLIBC_OPTION_EGLIBC_NIS),libnsl)
+ use_nsswitch=$(if $(CONFIG_EGLIBC_OPTION_EGLIBC_NSSWITCH),libnss_dns libnss_files)
+
+ define Package/eglibc/install
+ $(CP) ./eglibc-files/* $(1)/
+ rm -f $(1)/etc/localtime
+ ln -sf /tmp/localtime $(1)/etc/localtime
+ $(INSTALL_DIR) $(1)/lib
+ $(CP) \
+ $(TOOLCHAIN_DIR)/lib/ld*.so.* \
+ $(TOOLCHAIN_DIR)/lib/ld-$(LIBC_SO_VERSION).so \
+ $(1)/lib/
+ for file in libanl libc libcidn libcrypt libdl libm $(use_libnsl) $(use_nsswitch) libresolv $(use_libutil); do \
+ for file in $(TOOLCHAIN_DIR)/lib/$$$$file.so.* $(TOOLCHAIN_DIR)/lib/$$$$file-$(LIBC_SO_VERSION).so; do \
+ if [ -e "$$$$file" ]; then \
+ $(CP) $$$$file $(1)/lib/; \
+ fi; \
+ done; \
+ done
+ endef
+
+ define Package/uClibc/install
+ $(INSTALL_DIR) $(1)/lib
+ $(CP) \
+ $(TOOLCHAIN_DIR)/lib/ld*-uClibc.so.* \
+ $(TOOLCHAIN_DIR)/lib/ld*-uClibc-$(LIBC_SO_VERSION).so \
+ $(1)/lib/
+ $(CP) \
+ $(TOOLCHAIN_DIR)/lib/libc.so.* \
+ $(TOOLCHAIN_DIR)/lib/libuClibc-$(LIBC_SO_VERSION).so \
+ $(1)/lib/
+ for file in libcrypt libdl libm libutil; do \
+ $(CP) \
+ $(TOOLCHAIN_DIR)/lib/$$$$file.so.* \
+ $(TOOLCHAIN_DIR)/lib/$$$$file-$(LIBC_SO_VERSION).so \
+ $(1)/lib/; \
+ done
+
+ $(CP) \
+ $(PKG_BUILD_DIR)/libuClibc-* \
+ $(PKG_BUILD_DIR)/libm-* \
+ $(PKG_BUILD_DIR)/libcrypt-* \
+ $(1)/lib/
+ endef
+
+ define Package/libc/install
+ $(call Package/$(LIBC)/install,$1)
+ endef
+
+ define Package/libc/install_lib
+ $(CP) $(filter-out %/libdl_pic.a %/libpthread_pic.a %/libresolv_pic.a,$(wildcard $(TOOLCHAIN_DIR)/lib/lib*.a)) $(1)/lib/
+ $(if $(wildcard $(TOOLCHAIN_DIR)/lib/libc_so.a),$(CP) $(TOOLCHAIN_DIR)/lib/libc_so.a $(1)/lib/libc_pic.a)
+ $(if $(LIBGCC_MAP), \
+ $(CP) $(LIBGCC_A) $(1)/lib/libgcc_s_pic.a; \
+ $(CP) $(LIBGCC_MAP) $(1)/lib/libgcc_s_pic.map \
+ )
+ endef
+
+ define Package/libpthread/install
+ $(INSTALL_DIR) $(1)/lib
+ $(CP) \
+ $(TOOLCHAIN_DIR)/lib/libpthread.so.* \
+ $(if $(BUILD_LIBGCC),\
+ $(PKG_BUILD_DIR)/libpthread-$(LIBC_SO_VERSION).so, \
+ $(TOOLCHAIN_DIR)/lib/libpthread-$(LIBC_SO_VERSION).so \
+ ) \
+ $(1)/lib/
+ endef
+
+ define Package/libpthread/install_lib
+ $(if $(wildcard $(TOOLCHAIN_DIR)/lib/libpthread_so.a),$(CP) $(TOOLCHAIN_DIR)/lib/libpthread_so.a $(1)/lib/libpthread_pic.a)
+ endef
+
+ define Package/librt/install
+ $(INSTALL_DIR) $(1)/lib
+ $(CP) \
+ $(TOOLCHAIN_DIR)/lib/librt.so.* \
+ $(TOOLCHAIN_DIR)/lib/librt-$(LIBC_SO_VERSION).so \
+ $(1)/lib/
+ endef
+
+ define Package/ldd/install
+ $(INSTALL_DIR) $(1)/usr/bin/
+ $(CP) $(TOOLCHAIN_DIR)/bin/ldd $(1)/usr/bin/
+ endef
+
+ define Package/ldconfig/install
+ $(INSTALL_DIR) $(1)/sbin/
+ $(CP) $(TOOLCHAIN_DIR)/sbin/ldconfig $(1)/sbin/
+ endef
+
+else
+
+ define Package/libgcc/install
+ for file in $(call qstrip,$(CONFIG_LIBGCC_FILE_SPEC)); do \
+ dir=`dirname $$$$file` ; \
+ $(INSTALL_DIR) $(1)/$$$$dir ; \
+ $(CP) $(call qstrip,$(CONFIG_LIBGCC_ROOT_DIR))/$$$$file $(1)/$$$$dir/ ; \
+ done ; \
+ exit 0
+ endef
+
+ define Package/libgfortran/install
+ for file in $(call qstrip,$(CONFIG_LIBGFORTRAN_FILE_SPEC)); do \
+ dir=`dirname $$$$file` ; \
+ $(INSTALL_DIR) $(1)/$$$$dir ; \
+ $(CP) $(call qstrip,$(CONFIG_LIBGFORTRAN_ROOT_DIR))/$$$$file $(1)/$$$$dir/ ; \
+ done
+ endef
+
+ define Package/libssp/install
+ for file in $(call qstrip,$(CONFIG_LIBSSP_FILE_SPEC)); do \
+ dir=`dirname $$$$file` ; \
+ $(INSTALL_DIR) $(1)/$$$$dir ; \
+ $(CP) $(call qstrip,$(CONFIG_LIBSSP_ROOT_DIR))/$$$$file $(1)/$$$$dir/ ; \
+ done ; \
+ exit 0
+ endef
+
+ define Package/libstdcpp/install
+ for file in $(call qstrip,$(CONFIG_LIBSTDCPP_FILE_SPEC)); do \
+ dir=`dirname $$$$file` ; \
+ $(INSTALL_DIR) $(1)/$$$$dir ; \
+ $(CP) $(call qstrip,$(CONFIG_LIBSTDCPP_ROOT_DIR))/$$$$file $(1)/$$$$dir/ ; \
+ done ; \
+ exit 0
+ endef
+
+ define Package/libc/install
+ for file in $(call qstrip,$(CONFIG_LIBC_FILE_SPEC)); do \
+ dir=`dirname $$$$file` ; \
+ $(INSTALL_DIR) $(1)/$$$$dir ; \
+ $(CP) $(call qstrip,$(CONFIG_LIBC_ROOT_DIR))/$$$$file $(1)/$$$$dir/ ; \
+ done ; \
+ exit 0
+ endef
+
+ define Package/libpthread/install
+ for file in $(call qstrip,$(CONFIG_LIBPTHREAD_FILE_SPEC)); do \
+ dir=`dirname $$$$file` ; \
+ $(INSTALL_DIR) $(1)/$$$$dir ; \
+ $(CP) $(call qstrip,$(CONFIG_LIBPTHREAD_ROOT_DIR))/$$$$file $(1)/$$$$dir/ ; \
+ done ; \
+ exit 0
+ endef
+
+ define Package/librt/install
+ for file in $(call qstrip,$(CONFIG_LIBRT_FILE_SPEC)); do \
+ dir=`dirname $$$$file` ; \
+ $(INSTALL_DIR) $(1)/$$$$dir ; \
+ $(CP) $(call qstrip,$(CONFIG_LIBRT_ROOT_DIR))/$$$$file $(1)/$$$$dir/ ; \
+ done ; \
+ exit 0
+ endef
+
+ define Package/ldd/install
+ for file in $(call qstrip,$(CONFIG_LDD_FILE_SPEC)); do \
+ dir=`dirname $$$$file` ; \
+ $(INSTALL_DIR) $(1)/$$$$dir ; \
+ $(CP) $(call qstrip,$(CONFIG_LDD_ROOT_DIR))/$$$$file $(1)/$$$$dir/ ; \
+ done ; \
+ exit 0
+ endef
+
+ define Package/ldconfig/install
+ for file in $(call qstrip,$(CONFIG_LDCONFIG_FILE_SPEC)); do \
+ dir=`dirname $$$$file` ; \
+ $(INSTALL_DIR) $(1)/$$$$dir ; \
+ $(CP) $(call qstrip,$(CONFIG_LDCONFIG_ROOT_DIR))/$$$$file $(1)/$$$$dir/ ; \
+ done ; \
+ exit 0
+ endef
+
+endif
+
+$(eval $(call BuildPackage,libc))
+$(eval $(call BuildPackage,libgcc))
+$(eval $(call BuildPackage,libssp))
+$(eval $(call BuildPackage,libstdcpp))
+$(eval $(call BuildPackage,libpthread))
+$(eval $(call BuildPackage,librt))
+$(eval $(call BuildPackage,libgfortran))
+$(eval $(call BuildPackage,ldd))
+$(eval $(call BuildPackage,ldconfig))
diff --git a/package/toolchain/eglibc-files/etc/nsswitch.conf b/package/toolchain/eglibc-files/etc/nsswitch.conf
new file mode 100644
index 000000000..981c425da
--- /dev/null
+++ b/package/toolchain/eglibc-files/etc/nsswitch.conf
@@ -0,0 +1,13 @@
+passwd:files
+shadow:files
+group:files
+hosts:dns files
+bootparams:files
+ethers:files
+netmasks:files
+networks:files
+protocols:files
+rpc:files
+services:files
+automount:files
+aliases:files
diff --git a/package/trelay/Makefile b/package/trelay/Makefile
new file mode 100644
index 000000000..82c41018a
--- /dev/null
+++ b/package/trelay/Makefile
@@ -0,0 +1,50 @@
+#
+# Copyright (C) 2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=trelay
+PKG_VERSION:=0.1
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/trelay
+ SUBMENU:=Network Support
+ TITLE:=Trivial Ethernet Relay
+ FILES:=$(PKG_BUILD_DIR)/trelay.ko
+ AUTOLOAD:=$(call AutoLoad,50,trelay)
+endef
+
+define KernelPackage/trelay/description
+trelay relays ethernet packets between two devices (similar to a bridge), but
+without any MAC address checks. This makes it possible to bridge client mode
+or ad-hoc mode wifi devices to ethernet VLANs, assuming the remote end uses
+the same source MAC address as the device that packets are supposed to exit
+from.
+endef
+
+include $(INCLUDE_DIR)/kernel-defaults.mk
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ cp src/Makefile src/trelay.c $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ $(MAKE) $(KERNEL_MAKEOPTS) SUBDIRS="$(PKG_BUILD_DIR)" modules
+endef
+
+define KernelPackage/trelay/install
+ $(INSTALL_DIR) $(1)/etc/hotplug.d/net $(1)/etc/init.d $(1)/etc/config
+ $(INSTALL_DATA) ./files/trelay.hotplug $(1)/etc/hotplug.d/net/50-trelay
+ $(INSTALL_BIN) ./files/trelay.init $(1)/etc/init.d/trelay
+ $(INSTALL_DATA) ./files/trelay.config $(1)/etc/config/trelay
+endef
+
+$(eval $(call KernelPackage,trelay))
diff --git a/package/trelay/files/trelay.config b/package/trelay/files/trelay.config
new file mode 100644
index 000000000..eb0501305
--- /dev/null
+++ b/package/trelay/files/trelay.config
@@ -0,0 +1,4 @@
+config trelay
+ option enabled 0
+ option dev1 eth0
+ option dev2 wlan0
diff --git a/package/trelay/files/trelay.hotplug b/package/trelay/files/trelay.hotplug
new file mode 100644
index 000000000..31f737840
--- /dev/null
+++ b/package/trelay/files/trelay.hotplug
@@ -0,0 +1,5 @@
+case "$ACTION" in
+ add|register)
+ [ -f /var/run/trelay.active ] && /etc/init.d/trelay start
+ ;;
+esac
diff --git a/package/trelay/files/trelay.init b/package/trelay/files/trelay.init
new file mode 100644
index 000000000..c812e12c6
--- /dev/null
+++ b/package/trelay/files/trelay.init
@@ -0,0 +1,32 @@
+#!/bin/sh /etc/rc.common
+START=80
+
+check_relay() {
+ local cfg="$1"
+
+ config_get_bool enabled "$cfg" enabled 1
+ [ "$enabled" -gt 0 ] || return
+
+ config_get dev1 "$cfg" dev1
+ config_get dev2 "$cfg" dev2
+
+ [ -d "/sys/kernel/debug/trelay/${dev1}-${dev2}" ] && return
+ [ -d "/sys/class/net/${dev1}" -a -d "/sys/class/net/${dev2}" ] || return
+
+ ifconfig "$dev1" up
+ ifconfig "$dev2" up
+ echo "${dev1}-${dev2},${dev1},${dev2}" > /sys/kernel/debug/trelay/add
+}
+
+start() {
+ config_load trelay
+ config_foreach check_relay trelay
+ touch /var/run/trelay.active
+}
+
+stop() {
+ rm -f /var/run/trelay.active
+ for relay in /sys/kernel/debug/trelay/*; do
+ [ -d "$relay" ] && echo > "$relay/remove"
+ done
+}
diff --git a/package/trelay/src/Makefile b/package/trelay/src/Makefile
new file mode 100644
index 000000000..e6bde8969
--- /dev/null
+++ b/package/trelay/src/Makefile
@@ -0,0 +1 @@
+obj-m := trelay.o
diff --git a/package/trelay/src/trelay.c b/package/trelay/src/trelay.c
new file mode 100644
index 000000000..8fa4374c0
--- /dev/null
+++ b/package/trelay/src/trelay.c
@@ -0,0 +1,272 @@
+/*
+ * trelay.c: Trivial Ethernet Relay
+ *
+ * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/debugfs.h>
+
+static LIST_HEAD(trelay_devs);
+static struct dentry *debugfs_dir;
+
+struct trelay {
+ struct list_head list;
+ struct net_device *dev1, *dev2;
+ struct dentry *debugfs;
+ char name[];
+};
+
+rx_handler_result_t trelay_handle_frame(struct sk_buff **pskb)
+{
+ struct net_device *dev;
+ struct sk_buff *skb = *pskb;
+
+ dev = rcu_dereference(skb->dev->rx_handler_data);
+ if (!dev)
+ return RX_HANDLER_PASS;
+
+ if (skb->protocol == htons(ETH_P_PAE))
+ return RX_HANDLER_PASS;
+
+ skb_push(skb, ETH_HLEN);
+ skb->dev = dev;
+ skb_forward_csum(skb);
+ dev_queue_xmit(skb);
+
+ return RX_HANDLER_CONSUMED;
+}
+
+static int trelay_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static int trelay_do_remove(struct trelay *tr)
+{
+ list_del(&tr->list);
+
+ dev_put(tr->dev1);
+ dev_put(tr->dev2);
+
+ netdev_rx_handler_unregister(tr->dev1);
+ netdev_rx_handler_unregister(tr->dev2);
+
+ debugfs_remove_recursive(tr->debugfs);
+ kfree(tr);
+
+ return 0;
+}
+
+static struct trelay *trelay_find(struct net_device *dev)
+{
+ struct trelay *tr;
+
+ list_for_each_entry(tr, &trelay_devs, list) {
+ if (tr->dev1 == dev || tr->dev2 == dev)
+ return tr;
+ }
+ return NULL;
+}
+
+static int tr_device_event(struct notifier_block *unused, unsigned long event,
+ void *ptr)
+{
+ struct net_device *dev = ptr;
+ struct trelay *tr;
+
+ if (event != NETDEV_UNREGISTER)
+ goto out;
+
+ tr = trelay_find(dev);
+ if (!tr)
+ goto out;
+
+ trelay_do_remove(tr);
+
+out:
+ return NOTIFY_DONE;
+}
+
+static ssize_t trelay_remove_write(struct file *file, const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct trelay *tr = file->private_data;
+ int ret;
+
+ rtnl_lock();
+ ret = trelay_do_remove(tr);
+ rtnl_unlock();
+
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static const struct file_operations fops_remove = {
+ .owner = THIS_MODULE,
+ .open = trelay_open,
+ .write = trelay_remove_write,
+ .llseek = default_llseek,
+};
+
+
+static int trelay_do_add(char *name, char *devn1, char *devn2)
+{
+ struct net_device *dev1, *dev2;
+ struct trelay *tr, *tr1;
+ int ret;
+
+ tr = kzalloc(sizeof(*tr) + strlen(name) + 1, GFP_KERNEL);
+ if (!tr)
+ return -ENOMEM;
+
+ rtnl_lock();
+ rcu_read_lock();
+
+ ret = -EEXIST;
+ list_for_each_entry(tr1, &trelay_devs, list) {
+ if (!strcmp(tr1->name, name))
+ goto out;
+ }
+
+ ret = -ENOENT;
+ dev1 = dev_get_by_name_rcu(&init_net, devn1);
+ dev2 = dev_get_by_name_rcu(&init_net, devn2);
+ if (!dev1 || !dev2)
+ goto out;
+
+ ret = netdev_rx_handler_register(dev1, trelay_handle_frame, dev2);
+ if (ret < 0)
+ goto out;
+
+ ret = netdev_rx_handler_register(dev2, trelay_handle_frame, dev1);
+ if (ret < 0) {
+ netdev_rx_handler_unregister(dev1);
+ goto out;
+ }
+
+ dev_hold(dev1);
+ dev_hold(dev2);
+
+ strcpy(tr->name, name);
+ tr->dev1 = dev1;
+ tr->dev2 = dev2;
+ list_add_tail(&tr->list, &trelay_devs);
+
+ tr->debugfs = debugfs_create_dir(name, debugfs_dir);
+ debugfs_create_file("remove", S_IWUSR, tr->debugfs, tr, &fops_remove);
+ ret = 0;
+
+out:
+ rcu_read_unlock();
+ rtnl_unlock();
+ if (ret < 0)
+ kfree(tr);
+
+ return ret;
+}
+
+static ssize_t trelay_add_write(struct file *file, const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ char buf[256];
+ char *dev1, *dev2, *tmp;
+ ssize_t len, ret;
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, ubuf, len))
+ return -EFAULT;
+
+ buf[len] = 0;
+
+ if ((tmp = strchr(buf, '\n')))
+ *tmp = 0;
+
+ dev1 = strchr(buf, ',');
+ if (!dev1)
+ return -EINVAL;
+
+ *(dev1++) = 0;
+
+ dev2 = strchr(dev1, ',');
+ if (!dev2)
+ return -EINVAL;
+
+ *(dev2++) = 0;
+ if (strchr(dev2, ','))
+ return -EINVAL;
+
+ if (!strlen(buf) || !strlen(dev1) || !strlen(dev2))
+ return -EINVAL;
+
+ ret = trelay_do_add(buf, dev1, dev2);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static const struct file_operations fops_add = {
+ .owner = THIS_MODULE,
+ .write = trelay_add_write,
+ .llseek = default_llseek,
+};
+
+static struct notifier_block tr_dev_notifier = {
+ .notifier_call = tr_device_event
+};
+
+static int __init trelay_init(void)
+{
+ int ret;
+
+ debugfs_dir = debugfs_create_dir("trelay", NULL);
+ if (!debugfs_dir)
+ return -ENOMEM;
+
+ debugfs_create_file("add", S_IWUSR, debugfs_dir, NULL, &fops_add);
+
+ ret = register_netdevice_notifier(&tr_dev_notifier);
+ if (ret < 0)
+ goto error;
+
+ return 0;
+
+error:
+ debugfs_remove_recursive(debugfs_dir);
+ return ret;
+}
+
+static void __exit trelay_exit(void)
+{
+ struct trelay *tr, *tmp;
+
+ unregister_netdevice_notifier(&tr_dev_notifier);
+
+ rtnl_lock();
+ list_for_each_entry_safe(tr, tmp, &trelay_devs, list)
+ trelay_do_remove(tr);
+ rtnl_unlock();
+
+ debugfs_remove_recursive(debugfs_dir);
+}
+
+module_init(trelay_init);
+module_exit(trelay_exit);
+MODULE_LICENSE("GPL");
diff --git a/package/uboot-ar71xx/Makefile b/package/uboot-ar71xx/Makefile
new file mode 100644
index 000000000..ab692d579
--- /dev/null
+++ b/package/uboot-ar71xx/Makefile
@@ -0,0 +1,90 @@
+#
+# Copyright (C) 2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=u-boot
+PKG_VERSION:=2010.03
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=ftp://ftp.denx.de/pub/u-boot
+PKG_MD5SUM:=
+PKG_TARGETS:=bin
+
+include $(INCLUDE_DIR)/package.mk
+
+define uboot/Default
+ TITLE:=
+ CONFIG:=
+ IMAGE:=
+endef
+
+define uboot/nbg460n_550n_550nh
+ TITLE:=U-boot for the NBG460N/550N/550NH routers
+endef
+
+UBOOTS:=nbg460n_550n_550nh
+
+define Package/uboot/template
+define Package/uboot-ar71xx-$(1)
+ SECTION:=boot
+ CATEGORY:=Boot Loaders
+ TITLE:=$(2)
+ DEPENDS:=@TARGET_ar71xx
+ URL:=http://www.denx.de/wiki/U-Boot
+ DEFAULT:=y if (TARGET_ar71xx_generic_NBG_460N_550N_550NH || TARGET_ar71xx_generic_Default || CONFIG_TARGET_ar71xx_generic_Minimal)
+ VARIANT:=$(1)
+endef
+endef
+
+define BuildUbootPackage
+ $(eval $(uboot/Default))
+ $(eval $(uboot/$(1)))
+ $(call Package/uboot/template,$(1),$(TITLE))
+endef
+
+
+ifdef BUILD_VARIANT
+$(eval $(call uboot/$(BUILD_VARIANT)))
+UBOOT_CONFIG:=$(if $(CONFIG),$(CONFIG),$(BUILD_VARIANT))
+UBOOT_IMAGE:=$(if $(IMAGE),$(IMAGE),openwrt-$(BOARD)-$(BUILD_VARIANT)-u-boot.bin)
+endif
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ $(CP) ./files/* $(PKG_BUILD_DIR)
+ find $(PKG_BUILD_DIR) -name .svn | $(XARGS) rm -rf
+endef
+
+define Build/Configure
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(UBOOT_CONFIG)_config
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CROSS_COMPILE=$(TARGET_CROSS)
+endef
+
+define Package/uboot/install/template
+define Package/uboot-ar71xx-$(1)/install
+ $(INSTALL_DIR) $$(1)
+ $(CP) $(PKG_BUILD_DIR)/u-boot.bin $(BIN_DIR)/$(2)
+endef
+endef
+
+$(foreach u,$(UBOOTS), \
+ $(eval $(call Package/uboot/install/template,$(u),openwrt-$(BOARD)-$(SUBTARGET)-$(u)-u-boot.bin)) \
+)
+
+$(foreach u,$(UBOOTS), \
+ $(eval $(call BuildUbootPackage,$(u))) \
+ $(eval $(call BuildPackage,uboot-ar71xx-$(u))) \
+)
diff --git a/package/uboot-ar71xx/files/board/zyxel/nbg460n/Makefile b/package/uboot-ar71xx/files/board/zyxel/nbg460n/Makefile
new file mode 100644
index 000000000..b0a385bab
--- /dev/null
+++ b/package/uboot-ar71xx/files/board/zyxel/nbg460n/Makefile
@@ -0,0 +1,46 @@
+#
+# (C) Copyright 2003-2008
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(BOARD).a
+
+COBJS-y += $(BOARD).o
+SOBJS-y += lowlevel_init.o
+
+SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS-y))
+SOBJS := $(addprefix $(obj),$(SOBJS-y))
+
+$(LIB): $(obj).depend $(OBJS) $(SOBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
+
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/package/uboot-ar71xx/files/board/zyxel/nbg460n/config.mk b/package/uboot-ar71xx/files/board/zyxel/nbg460n/config.mk
new file mode 100644
index 000000000..e042e78bf
--- /dev/null
+++ b/package/uboot-ar71xx/files/board/zyxel/nbg460n/config.mk
@@ -0,0 +1 @@
+TEXT_BASE = 0x81E00000
diff --git a/package/uboot-ar71xx/files/board/zyxel/nbg460n/lowlevel_init.S b/package/uboot-ar71xx/files/board/zyxel/nbg460n/lowlevel_init.S
new file mode 100644
index 000000000..83084c8d4
--- /dev/null
+++ b/package/uboot-ar71xx/files/board/zyxel/nbg460n/lowlevel_init.S
@@ -0,0 +1,39 @@
+/*
+ * (C) Copyright 2010
+ * Michael Kurz <michi.kurz@googlemail.com>.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <config.h>
+#include <version.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+
+
+
+.globl lowlevel_init
+/*
+ All done by Bootbase, nothing to do
+*/
+lowlevel_init:
+ jr ra
+ nop
+
diff --git a/package/uboot-ar71xx/files/board/zyxel/nbg460n/nbg460n.c b/package/uboot-ar71xx/files/board/zyxel/nbg460n/nbg460n.c
new file mode 100644
index 000000000..03a479d52
--- /dev/null
+++ b/package/uboot-ar71xx/files/board/zyxel/nbg460n/nbg460n.c
@@ -0,0 +1,96 @@
+/*
+ * (C) Copyright 2010
+ * Michael Kurz <michi.kurz@googlemail.com>.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <netdev.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/reboot.h>
+#include <asm/ar71xx.h>
+#include <asm/ar71xx_gpio.h>
+
+#define NBG460N_WAN_LED 19
+
+phys_size_t initdram(int board_type)
+{
+ return (32*1024*1024);
+}
+
+int checkboard(void)
+{
+ // Set pin 19 to 1, to stop WAN LED blinking
+ ar71xx_setpindir(NBG460N_WAN_LED, 1);
+ ar71xx_setpin(NBG460N_WAN_LED, 1);
+
+ printf("U-boot on Zyxel NBG460N\n");
+ return 0;
+}
+
+void _machine_restart(void)
+{
+ for (;;) {
+ writel((RESET_MODULE_FULL_CHIP | RESET_MODULE_DDR),
+ KSEG1ADDR(AR71XX_RESET_BASE + AR91XX_RESET_REG_RESET_MODULE));
+ readl(KSEG1ADDR(AR71XX_RESET_BASE + AR91XX_RESET_REG_RESET_MODULE));
+ }
+}
+
+int board_eth_init(bd_t *bis)
+{
+ char *phynames[] = {RTL8366_DEVNAME, RTL8366_DEVNAME};
+ u16 phyids[] = {RTL8366_LANPHY_ID, RTL8366_WANPHY_ID};
+ u16 phyfixed[] = {1, 0};
+
+ if (ag71xx_register(bis, phynames, phyids, phyfixed) <= 0)
+ return -1;
+
+ if (rtl8366s_initialize())
+ return -1;
+
+ if (rtl8366_mii_register(bis))
+ return -1;
+
+ return 0;
+}
+
+int misc_init_r(void) {
+ uint8_t macaddr[6];
+ uint8_t enetaddr[6];
+
+ debug("Testing mac addresses\n");
+
+ memcpy(macaddr, (uint8_t *) CONFIG_ETHADDR_ADDR, 6);
+
+ if (!eth_getenv_enetaddr("ethaddr", enetaddr)) {
+ debug("Setting eth0 mac addr to %pM\n", macaddr);
+ eth_setenv_enetaddr("ethaddr", macaddr);
+ }
+
+ if (!eth_getenv_enetaddr("eth1addr", enetaddr)) {
+ macaddr[5] += 1;
+ debug("Setting eth1 mac addr to %pM\n", macaddr);
+ eth_setenv_enetaddr("eth1addr", macaddr);
+ }
+
+ return 0;
+}
diff --git a/package/uboot-ar71xx/files/board/zyxel/nbg460n/u-boot.lds b/package/uboot-ar71xx/files/board/zyxel/nbg460n/u-boot.lds
new file mode 100644
index 000000000..8dc2b764c
--- /dev/null
+++ b/package/uboot-ar71xx/files/board/zyxel/nbg460n/u-boot.lds
@@ -0,0 +1,42 @@
+OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradbigmips")
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .sdata : { *(.sdata) }
+
+ _gp = ALIGN(16);
+
+ __got_start = .;
+ .got : { *(.got) }
+ __got_end = .;
+
+ .sdata : { *(.sdata) }
+
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+ uboot_end_data = .;
+ num_got_entries = (__got_end - __got_start) >> 2;
+
+ . = ALIGN(4);
+ .sbss : { *(.sbss) }
+ .bss : { *(.bss) }
+ uboot_end = .;
+}
diff --git a/package/uboot-ar71xx/files/cpu/mips/ar71xx_serial.c b/package/uboot-ar71xx/files/cpu/mips/ar71xx_serial.c
new file mode 100644
index 000000000..f09331895
--- /dev/null
+++ b/package/uboot-ar71xx/files/cpu/mips/ar71xx_serial.c
@@ -0,0 +1,177 @@
+/*
+ * (C) Copyright 2010
+ * Michael Kurz <michi.kurz@googlemail.com>.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <config.h>
+#include <asm/ar71xx.h>
+
+#define REG_SIZE 4
+
+/* === END OF CONFIG === */
+
+/* register offset */
+#define OFS_RCV_BUFFER (0*REG_SIZE)
+#define OFS_TRANS_HOLD (0*REG_SIZE)
+#define OFS_SEND_BUFFER (0*REG_SIZE)
+#define OFS_INTR_ENABLE (1*REG_SIZE)
+#define OFS_INTR_ID (2*REG_SIZE)
+#define OFS_DATA_FORMAT (3*REG_SIZE)
+#define OFS_LINE_CONTROL (3*REG_SIZE)
+#define OFS_MODEM_CONTROL (4*REG_SIZE)
+#define OFS_RS232_OUTPUT (4*REG_SIZE)
+#define OFS_LINE_STATUS (5*REG_SIZE)
+#define OFS_MODEM_STATUS (6*REG_SIZE)
+#define OFS_RS232_INPUT (6*REG_SIZE)
+#define OFS_SCRATCH_PAD (7*REG_SIZE)
+
+#define OFS_DIVISOR_LSB (0*REG_SIZE)
+#define OFS_DIVISOR_MSB (1*REG_SIZE)
+
+#define UART16550_READ(y) readl(KSEG1ADDR(AR71XX_UART_BASE+y))
+#define UART16550_WRITE(x, z) writel(z, KSEG1ADDR((AR71XX_UART_BASE+x)))
+
+void
+ar71xx_sys_frequency(u32 *cpu_freq, u32 *ddr_freq, u32 *ahb_freq)
+{
+#ifndef CONFIG_AR91XX
+ u32 pll, pll_div, cpu_div, ahb_div, ddr_div, freq;
+
+ pll = readl(KSEG1ADDR(AR71XX_PLL_REG_CPU_CONFIG + AR71XX_PLL_BASE));
+
+ pll_div =
+ ((pll & AR71XX_PLL_DIV_MASK) >> AR71XX_PLL_DIV_SHIFT) + 1;
+
+ cpu_div =
+ ((pll & AR71XX_CPU_DIV_MASK) >> AR71XX_CPU_DIV_SHIFT) + 1;
+
+ ddr_div =
+ ((pll & AR71XX_DDR_DIV_MASK) >> AR71XX_DDR_DIV_SHIFT) + 1;
+
+ ahb_div =
+ (((pll & AR71XX_AHB_DIV_MASK) >> AR71XX_AHB_DIV_SHIFT) + 1)*2;
+
+ freq = pll_div * 40000000;
+
+ if (cpu_freq)
+ *cpu_freq = freq/cpu_div;
+
+ if (ddr_freq)
+ *ddr_freq = freq/ddr_div;
+
+ if (ahb_freq)
+ *ahb_freq = (freq/cpu_div)/ahb_div;
+
+#else
+ u32 pll, pll_div, ahb_div, ddr_div, freq;
+
+ pll = readl(KSEG1ADDR(AR91XX_PLL_REG_CPU_CONFIG + AR71XX_PLL_BASE));
+
+ pll_div =
+ ((pll & AR91XX_PLL_DIV_MASK) >> AR91XX_PLL_DIV_SHIFT);
+
+ ddr_div =
+ ((pll & AR91XX_DDR_DIV_MASK) >> AR91XX_DDR_DIV_SHIFT) + 1;
+
+ ahb_div =
+ (((pll & AR91XX_AHB_DIV_MASK) >> AR91XX_AHB_DIV_SHIFT) + 1)*2;
+
+ freq = pll_div * 5000000;
+
+ if (cpu_freq)
+ *cpu_freq = freq;
+
+ if (ddr_freq)
+ *ddr_freq = freq/ddr_div;
+
+ if (ahb_freq)
+ *ahb_freq = freq/ahb_div;
+#endif
+}
+
+
+int serial_init(void)
+{
+ u32 div;
+ u32 ahb_freq = 100000000;
+
+ ar71xx_sys_frequency (0, 0, &ahb_freq);
+ div = ahb_freq/(16 * CONFIG_BAUDRATE);
+
+ // enable uart pins
+#ifndef CONFIG_AR91XX
+ writel(AR71XX_GPIO_FUNC_UART_EN, KSEG1ADDR(AR71XX_GPIO_BASE + GPIO_REG_FUNC));
+#else
+ writel(AR91XX_GPIO_FUNC_UART_EN, KSEG1ADDR(AR71XX_GPIO_BASE + GPIO_REG_FUNC));
+#endif
+
+ /* set DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+
+ /* set divisor */
+ UART16550_WRITE(OFS_DIVISOR_LSB, (div & 0xff));
+ UART16550_WRITE(OFS_DIVISOR_MSB, ((div >> 8) & 0xff));
+
+ /* clear DIAB bit*/
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x00);
+
+ /* set data format */
+ UART16550_WRITE(OFS_DATA_FORMAT, 0x3);
+
+ UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+ return 0;
+}
+
+int serial_tstc (void)
+{
+ return(UART16550_READ(OFS_LINE_STATUS) & 0x1);
+}
+
+int serial_getc(void)
+{
+ while(!serial_tstc());
+
+ return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+
+void serial_putc(const char byte)
+{
+ if (byte == '\n') serial_putc ('\r');
+
+ while (((UART16550_READ(OFS_LINE_STATUS)) & 0x20) == 0x0);
+ UART16550_WRITE(OFS_SEND_BUFFER, byte);
+}
+
+void serial_setbrg (void)
+{
+}
+
+void serial_puts (const char *s)
+{
+ while (*s)
+ {
+ serial_putc (*s++);
+ }
+}
diff --git a/package/uboot-ar71xx/files/drivers/net/ag71xx.c b/package/uboot-ar71xx/files/drivers/net/ag71xx.c
new file mode 100644
index 000000000..b3324c019
--- /dev/null
+++ b/package/uboot-ar71xx/files/drivers/net/ag71xx.c
@@ -0,0 +1,809 @@
+/*
+ * Atheros AR71xx built-in ethernet mac driver
+ *
+ * Copyright (C) 2010 Michael Kurz <michi.kurz@googlemail.com>
+ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * Based on Atheros' AG7100 driver
+ *
+ * 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 <common.h>
+#include <malloc.h>
+#include <net.h>
+#include <miiphy.h>
+
+#include <asm/ar71xx.h>
+
+#include "ag71xx.h"
+
+#ifdef AG71XX_DEBUG
+#define DBG(fmt,args...) printf(fmt ,##args)
+#else
+#define DBG(fmt,args...)
+#endif
+
+
+static struct ag71xx agtable[] = {
+ {
+ .mac_base = KSEG1ADDR(AR71XX_GE0_BASE),
+ .mii_ctrl = KSEG1ADDR(AR71XX_MII_BASE + MII_REG_MII0_CTRL),
+ .mii_if = CONFIG_AG71XX_MII0_IIF,
+ } , {
+ .mac_base = KSEG1ADDR(AR71XX_GE1_BASE),
+ .mii_ctrl = KSEG1ADDR(AR71XX_MII_BASE + MII_REG_MII1_CTRL),
+ .mii_if = CONFIG_AG71XX_MII1_IIF,
+ }
+};
+
+static int ag71xx_ring_alloc(struct ag71xx_ring *ring, unsigned int size)
+{
+ int err;
+ int i;
+ int rsize;
+
+ ring->desc_size = sizeof(struct ag71xx_desc);
+ if (ring->desc_size % (CONFIG_SYS_CACHELINE_SIZE)) {
+ rsize = roundup(ring->desc_size, CONFIG_SYS_CACHELINE_SIZE);
+ DBG("ag71xx: ring %p, desc size %u rounded to %u\n",
+ ring, ring->desc_size,
+ rsize);
+ ring->desc_size = rsize;
+ }
+
+ ring->descs_cpu = (u8 *) malloc((size * ring->desc_size)
+ + CONFIG_SYS_CACHELINE_SIZE - 1);
+ if (!ring->descs_cpu) {
+ err = -1;
+ goto err;
+ }
+ ring->descs_cpu = (u8 *) UNCACHED_SDRAM((((u32) ring->descs_cpu +
+ CONFIG_SYS_CACHELINE_SIZE - 1) & ~(CONFIG_SYS_CACHELINE_SIZE - 1)));
+ ring->descs_dma = (u8 *) virt_to_phys(ring->descs_cpu);
+
+ ring->size = size;
+
+ ring->buf = malloc(size * sizeof(*ring->buf));
+ if (!ring->buf) {
+ err = -1;
+ goto err;
+ }
+ memset(ring->buf, 0, size * sizeof(*ring->buf));
+
+ for (i = 0; i < size; i++) {
+ ring->buf[i].desc =
+ (struct ag71xx_desc *)&ring->descs_cpu[i * ring->desc_size];
+ DBG("ag71xx: ring %p, desc %d at %p\n",
+ ring, i, ring->buf[i].desc);
+ }
+
+ flush_cache( (u32) ring->buf, size * sizeof(*ring->buf));
+
+ return 0;
+
+ err:
+ return err;
+}
+
+static void ag71xx_ring_tx_init(struct ag71xx *ag)
+{
+ struct ag71xx_ring *ring = &ag->tx_ring;
+ int i;
+
+ for (i = 0; i < AG71XX_TX_RING_SIZE; i++) {
+ ring->buf[i].desc->next = (u32) virt_to_phys((ring->descs_dma +
+ ring->desc_size * ((i + 1) % AG71XX_TX_RING_SIZE)));
+
+ ring->buf[i].desc->ctrl = DESC_EMPTY;
+ ring->buf[i].skb = NULL;
+ }
+
+ ring->curr = 0;
+}
+
+static void ag71xx_ring_rx_clean(struct ag71xx *ag)
+{
+ struct ag71xx_ring *ring = &ag->rx_ring;
+ int i;
+
+ if (!ring->buf)
+ return;
+
+ for (i = 0; i < AG71XX_RX_RING_SIZE; i++) {
+ ring->buf[i].desc->data = (u32) virt_to_phys(NetRxPackets[i]);
+ flush_cache((u32) NetRxPackets[i], PKTSIZE_ALIGN);
+ ring->buf[i].desc->ctrl = DESC_EMPTY;
+ }
+
+ ring->curr = 0;
+}
+
+static int ag71xx_ring_rx_init(struct ag71xx *ag)
+{
+ struct ag71xx_ring *ring = &ag->rx_ring;
+ unsigned int i;
+
+ for (i = 0; i < AG71XX_RX_RING_SIZE; i++) {
+ ring->buf[i].desc->next = (u32) virt_to_phys((ring->descs_dma +
+ ring->desc_size * ((i + 1) % AG71XX_RX_RING_SIZE)));
+
+ DBG("ag71xx: RX desc at %p, next is %08x\n",
+ ring->buf[i].desc,
+ ring->buf[i].desc->next);
+ }
+
+ for (i = 0; i < AG71XX_RX_RING_SIZE; i++) {
+ ring->buf[i].desc->data = (u32) virt_to_phys(NetRxPackets[i]);
+ ring->buf[i].desc->ctrl = DESC_EMPTY;
+ }
+
+ ring->curr = 0;
+
+ return 0;
+}
+
+static int ag71xx_rings_init(struct ag71xx *ag)
+{
+ int ret;
+
+ ret = ag71xx_ring_alloc(&ag->tx_ring, AG71XX_TX_RING_SIZE);
+ if (ret)
+ return ret;
+
+ ag71xx_ring_tx_init(ag);
+
+ ret = ag71xx_ring_alloc(&ag->rx_ring, AG71XX_RX_RING_SIZE);
+ if (ret)
+ return ret;
+
+ ret = ag71xx_ring_rx_init(ag);
+ return ret;
+}
+
+static void ar71xx_set_pll(u32 cfg_reg, u32 pll_reg, u32 pll_val, u32 shift)
+{
+ uint32_t base = KSEG1ADDR(AR71XX_PLL_BASE);
+ u32 t;
+
+ t = readl(base + cfg_reg);
+ t &= ~(3 << shift);
+ t |= (2 << shift);
+ writel(t, base + cfg_reg);
+ udelay(100);
+
+ writel(pll_val, base + pll_reg);
+
+ t |= (3 << shift);
+ writel(t, base + cfg_reg);
+ udelay(100);
+
+ t &= ~(3 << shift);
+ writel(t, base + cfg_reg);
+ udelay(100);
+
+ debug("ar71xx: pll_reg %#x: %#x\n", (unsigned int)(base + pll_reg),
+ readl(base + pll_reg));
+}
+
+static void ar91xx_set_pll_ge0(int speed)
+{
+ //u32 val = ar71xx_get_eth_pll(0, speed);
+ u32 pll_val;
+
+ switch (speed) {
+ case SPEED_10:
+ pll_val = 0x00441099;
+ break;
+ case SPEED_100:
+ pll_val = 0x13000a44;
+ break;
+ case SPEED_1000:
+ pll_val = 0x1a000000;
+ break;
+ default:
+ BUG();
+ }
+
+ ar71xx_set_pll(AR91XX_PLL_REG_ETH_CONFIG, AR91XX_PLL_REG_ETH0_INT_CLOCK,
+ pll_val, AR91XX_ETH0_PLL_SHIFT);
+}
+
+static void ar91xx_set_pll_ge1(int speed)
+{
+ //u32 val = ar71xx_get_eth_pll(1, speed);
+ u32 pll_val;
+
+ switch (speed) {
+ case SPEED_10:
+ pll_val = 0x00441099;
+ break;
+ case SPEED_100:
+ pll_val = 0x13000a44;
+ break;
+ case SPEED_1000:
+ pll_val = 0x1a000000;
+ break;
+ default:
+ BUG();
+ }
+
+ ar71xx_set_pll(AR91XX_PLL_REG_ETH_CONFIG, AR91XX_PLL_REG_ETH1_INT_CLOCK,
+ pll_val, AR91XX_ETH1_PLL_SHIFT);
+}
+
+static void ag71xx_hw_set_macaddr(struct ag71xx *ag, unsigned char *mac)
+{
+ u32 t;
+
+ t = (((u32) mac[5]) << 24) | (((u32) mac[4]) << 16)
+ | (((u32) mac[3]) << 8) | ((u32) mac[2]);
+
+ ag71xx_wr(ag, AG71XX_REG_MAC_ADDR1, t);
+
+ t = (((u32) mac[1]) << 24) | (((u32) mac[0]) << 16);
+ ag71xx_wr(ag, AG71XX_REG_MAC_ADDR2, t);
+}
+
+static void ag71xx_dma_reset(struct ag71xx *ag)
+{
+ u32 val;
+ int i;
+
+ DBG("%s: txdesc reg: 0x%08x rxdesc reg: 0x%08x\n",
+ ag->dev->name,
+ ag71xx_rr(ag, AG71XX_REG_TX_DESC),
+ ag71xx_rr(ag, AG71XX_REG_RX_DESC));
+
+ /* stop RX and TX */
+ ag71xx_wr(ag, AG71XX_REG_RX_CTRL, 0);
+ ag71xx_wr(ag, AG71XX_REG_TX_CTRL, 0);
+
+ /* clear descriptor addresses */
+ ag71xx_wr(ag, AG71XX_REG_TX_DESC, 0);
+ ag71xx_wr(ag, AG71XX_REG_RX_DESC, 0);
+
+ /* clear pending RX/TX interrupts */
+ for (i = 0; i < 256; i++) {
+ ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_PR);
+ ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_PS);
+ }
+
+ /* clear pending errors */
+ ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_BE | RX_STATUS_OF);
+ ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_BE | TX_STATUS_UR);
+
+ val = ag71xx_rr(ag, AG71XX_REG_RX_STATUS);
+ if (val)
+ printf("%s: unable to clear DMA Rx status: %08x\n",
+ ag->dev->name, val);
+
+ val = ag71xx_rr(ag, AG71XX_REG_TX_STATUS);
+
+ /* mask out reserved bits */
+ val &= ~0xff000000;
+
+ if (val)
+ printf("%s: unable to clear DMA Tx status: %08x\n",
+ ag->dev->name, val);
+}
+
+static void ag71xx_halt(struct eth_device *dev)
+{
+ struct ag71xx *ag = (struct ag71xx *) dev->priv;
+
+ /* stop RX engine */
+ ag71xx_wr(ag, AG71XX_REG_RX_CTRL, 0);
+
+ ag71xx_dma_reset(ag);
+}
+
+#define MAX_WAIT 1000
+
+static int ag71xx_send(struct eth_device *dev, volatile void *packet,
+ int length)
+{
+ struct ag71xx *ag = (struct ag71xx *) dev->priv;
+ struct ag71xx_ring *ring = &ag->tx_ring;
+ struct ag71xx_desc *desc;
+ int i;
+
+ i = ring->curr % AG71XX_TX_RING_SIZE;
+ desc = ring->buf[i].desc;
+
+ if (!ag71xx_desc_empty(desc)) {
+ printf("%s: tx buffer full\n", ag->dev->name);
+ return 1;
+ }
+
+ flush_cache((u32) packet, length);
+ desc->data = (u32) virt_to_phys(packet);
+ desc->ctrl = (length & DESC_PKTLEN_M);
+
+ DBG("%s: sending %#08x length %#08x\n",
+ ag->dev->name, desc->data, desc->ctrl);
+
+ ring->curr++;
+ if (ring->curr >= AG71XX_TX_RING_SIZE){
+ ring->curr = 0;
+ }
+
+ /* enable TX engine */
+ ag71xx_wr(ag, AG71XX_REG_TX_CTRL, TX_CTRL_TXE);
+
+ for (i = 0; i < MAX_WAIT; i++)
+ {
+ if (ag71xx_desc_empty(desc))
+ break;
+ udelay(10);
+ }
+ if (i == MAX_WAIT) {
+ printf("%s: tx timed out!\n", ag->dev->name);
+ return -1;
+ }
+
+ /* disable TX engine */
+ ag71xx_wr(ag, AG71XX_REG_TX_CTRL, 0);
+ desc->data = 0;
+ desc->ctrl = DESC_EMPTY;
+
+ return 0;
+}
+
+static int ag71xx_recv(struct eth_device *dev)
+{
+ struct ag71xx *ag = (struct ag71xx *) dev->priv;
+ struct ag71xx_ring *ring = &ag->rx_ring;
+
+ for (;;) {
+ unsigned int i = ring->curr % AG71XX_RX_RING_SIZE;
+ struct ag71xx_desc *desc = ring->buf[i].desc;
+ int pktlen;
+
+ if (ag71xx_desc_empty(desc))
+ break;
+
+ DBG("%s: rx packets, curr=%u\n", dev->name, ring->curr);
+
+ pktlen = ag71xx_desc_pktlen(desc);
+ pktlen -= ETH_FCS_LEN;
+
+
+ NetReceive(NetRxPackets[i] , pktlen);
+ flush_cache( (u32) NetRxPackets[i], PKTSIZE_ALIGN);
+
+ ring->buf[i].desc->ctrl = DESC_EMPTY;
+ ring->curr++;
+ if (ring->curr >= AG71XX_RX_RING_SIZE){
+ ring->curr = 0;
+ }
+
+ }
+
+ if ((ag71xx_rr(ag, AG71XX_REG_RX_CTRL) & RX_CTRL_RXE) == 0) {
+ /* start RX engine */
+ ag71xx_wr(ag, AG71XX_REG_RX_CTRL, RX_CTRL_RXE);
+ }
+
+ return 0;
+}
+
+#ifdef AG71XX_DEBUG
+static char *ag71xx_speed_str(struct ag71xx *ag)
+{
+ switch (ag->speed) {
+ case SPEED_1000:
+ return "1000";
+ case SPEED_100:
+ return "100";
+ case SPEED_10:
+ return "10";
+ }
+
+ return "?";
+}
+#endif
+
+void ag71xx_link_adjust(struct ag71xx *ag)
+{
+ u32 cfg2;
+ u32 ifctl;
+ u32 fifo5;
+ u32 mii_speed;
+
+ if (!ag->link) {
+ DBG("%s: link down\n", ag->dev->name);
+ return;
+ }
+
+ cfg2 = ag71xx_rr(ag, AG71XX_REG_MAC_CFG2);
+ cfg2 &= ~(MAC_CFG2_IF_1000 | MAC_CFG2_IF_10_100 | MAC_CFG2_FDX);
+ cfg2 |= (ag->duplex) ? MAC_CFG2_FDX : 0;
+
+ ifctl = ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL);
+ ifctl &= ~(MAC_IFCTL_SPEED);
+
+ fifo5 = ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5);
+ fifo5 &= ~FIFO_CFG5_BM;
+
+ switch (ag->speed) {
+ case SPEED_1000:
+ mii_speed = MII_CTRL_SPEED_1000;
+ cfg2 |= MAC_CFG2_IF_1000;
+ fifo5 |= FIFO_CFG5_BM;
+ break;
+ case SPEED_100:
+ mii_speed = MII_CTRL_SPEED_100;
+ cfg2 |= MAC_CFG2_IF_10_100;
+ ifctl |= MAC_IFCTL_SPEED;
+ break;
+ case SPEED_10:
+ mii_speed = MII_CTRL_SPEED_10;
+ cfg2 |= MAC_CFG2_IF_10_100;
+ break;
+ default:
+ BUG();
+ return;
+ }
+
+ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x00780fff);
+
+ if (ag->macNum == 0)
+ ar91xx_set_pll_ge0(ag->speed);
+ else
+ ar91xx_set_pll_ge1(ag->speed);
+
+ ag71xx_mii_ctrl_set_speed(ag, mii_speed);
+
+ ag71xx_wr(ag, AG71XX_REG_MAC_CFG2, cfg2);
+ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, fifo5);
+ ag71xx_wr(ag, AG71XX_REG_MAC_IFCTL, ifctl);
+
+ DBG("%s: link up (%sMbps/%s duplex)\n",
+ ag->dev->name,
+ ag71xx_speed_str(ag),
+ (1 == ag->duplex) ? "Full" : "Half");
+
+ DBG("%s: fifo_cfg0=%#x, fifo_cfg1=%#x, fifo_cfg2=%#x\n",
+ ag->dev->name,
+ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG0),
+ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG1),
+ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG2));
+
+ DBG("%s: fifo_cfg3=%#x, fifo_cfg4=%#x, fifo_cfg5=%#x\n",
+ ag->dev->name,
+ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG3),
+ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG4),
+ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5));
+
+ DBG("%s: mac_cfg2=%#x, mac_ifctl=%#x, mii_ctrl=%#x\n",
+ ag->dev->name,
+ ag71xx_rr(ag, AG71XX_REG_MAC_CFG2),
+ ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL),
+ ag71xx_mii_ctrl_rr(ag));
+}
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+static int ag71xx_getMiiSpeed(struct ag71xx *ag)
+{
+ uint16_t phyreg, cap;
+
+ if (miiphy_read(ag->phyname, ag->phyid,
+ PHY_BMSR, &phyreg)) {
+ puts("PHY_BMSR read failed, assuming no link\n");
+ return -1;
+ }
+
+ if ((phyreg & PHY_BMSR_LS) == 0) {
+ return -1;
+ }
+
+ if (miiphy_read(ag->phyname, ag->phyid,
+ PHY_1000BTSR, &phyreg))
+ return -1;
+
+ if (phyreg & PHY_1000BTSR_1000FD) {
+ ag->speed = SPEED_1000;
+ ag->duplex = 1;
+ } else if (phyreg & PHY_1000BTSR_1000HD) {
+ ag->speed = SPEED_1000;
+ ag->duplex = 0;
+ } else {
+ if (miiphy_read(ag->phyname, ag->phyid,
+ PHY_ANAR, &cap))
+ return -1;
+
+ if (miiphy_read(ag->phyname, ag->phyid,
+ PHY_ANLPAR, &phyreg))
+ return -1;
+
+ cap &= phyreg;
+ if (cap & PHY_ANLPAR_TXFD) {
+ ag->speed = SPEED_100;
+ ag->duplex = 1;
+ } else if (cap & PHY_ANLPAR_TX) {
+ ag->speed = SPEED_100;
+ ag->duplex = 0;
+ } else if (cap & PHY_ANLPAR_10FD) {
+ ag->speed = SPEED_10;
+ ag->duplex = 1;
+ } else {
+ ag->speed = SPEED_10;
+ ag->duplex = 0;
+ }
+ }
+
+ ag->link = 1;
+
+ return 0;
+}
+#endif
+
+static int ag71xx_hw_start(struct eth_device *dev, bd_t * bd)
+{
+ struct ag71xx *ag = (struct ag71xx *) dev->priv;
+
+ ag71xx_dma_reset(ag);
+
+ ag71xx_ring_rx_clean(ag);
+ ag71xx_ring_tx_init(ag);
+
+ ag71xx_wr(ag, AG71XX_REG_TX_DESC,
+ (u32) virt_to_phys(ag->tx_ring.descs_dma));
+ ag71xx_wr(ag, AG71XX_REG_RX_DESC,
+ (u32) virt_to_phys(ag->rx_ring.descs_dma));
+
+ ag71xx_hw_set_macaddr(ag, ag->dev->enetaddr);
+
+ if (ag->phyfixed) {
+ ag->link = 1;
+ ag->duplex = 1;
+ ag->speed = SPEED_1000;
+ } else {
+
+#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
+ if (ag71xx_getMiiSpeed(ag))
+ return -1;
+#else
+ /* only fixed, without mii */
+ return -1;
+#endif
+
+ }
+ ag71xx_link_adjust(ag);
+
+ DBG("%s: txdesc reg: %#08x rxdesc reg: %#08x\n",
+ ag->dev->name,
+ ag71xx_rr(ag, AG71XX_REG_TX_DESC),
+ ag71xx_rr(ag, AG71XX_REG_RX_DESC));
+
+ /* start RX engine */
+ ag71xx_wr(ag, AG71XX_REG_RX_CTRL, RX_CTRL_RXE);
+
+ return 0;
+}
+
+#define FIFO_CFG0_INIT (FIFO_CFG0_ALL << FIFO_CFG0_ENABLE_SHIFT)
+
+#define FIFO_CFG4_INIT (FIFO_CFG4_DE | FIFO_CFG4_DV | FIFO_CFG4_FC | \
+ FIFO_CFG4_CE | FIFO_CFG4_CR | FIFO_CFG4_LM | \
+ FIFO_CFG4_LO | FIFO_CFG4_OK | FIFO_CFG4_MC | \
+ FIFO_CFG4_BC | FIFO_CFG4_DR | FIFO_CFG4_LE | \
+ FIFO_CFG4_CF | FIFO_CFG4_PF | FIFO_CFG4_UO | \
+ FIFO_CFG4_VT)
+
+#define FIFO_CFG5_INIT (FIFO_CFG5_DE | FIFO_CFG5_DV | FIFO_CFG5_FC | \
+ FIFO_CFG5_CE | FIFO_CFG5_LO | FIFO_CFG5_OK | \
+ FIFO_CFG5_MC | FIFO_CFG5_BC | FIFO_CFG5_DR | \
+ FIFO_CFG5_CF | FIFO_CFG5_PF | FIFO_CFG5_VT | \
+ FIFO_CFG5_LE | FIFO_CFG5_FT | FIFO_CFG5_16 | \
+ FIFO_CFG5_17 | FIFO_CFG5_SF)
+
+static int ag71xx_hw_init(struct ag71xx *ag)
+{
+ int ret = 0;
+ uint32_t reg;
+ uint32_t mask, mii_type;
+
+ if (ag->macNum == 0) {
+ mask = (RESET_MODULE_GE0_MAC | RESET_MODULE_GE0_PHY);
+ mii_type = 0x13;
+ } else {
+ mask = (RESET_MODULE_GE1_MAC | RESET_MODULE_GE1_PHY);
+ mii_type = 0x11;
+ }
+
+ // mac soft reset
+ ag71xx_sb(ag, AG71XX_REG_MAC_CFG1, MAC_CFG1_SR);
+ udelay(20);
+
+ // device stop
+ reg = ar71xx_reset_rr(AR91XX_RESET_REG_RESET_MODULE);
+ ar71xx_reset_wr(AR91XX_RESET_REG_RESET_MODULE, reg | mask);
+ udelay(100 * 1000);
+
+ // device start
+ reg = ar71xx_reset_rr(AR91XX_RESET_REG_RESET_MODULE);
+ ar71xx_reset_wr(AR91XX_RESET_REG_RESET_MODULE, reg & ~mask);
+ udelay(100 * 1000);
+
+ /* setup MAC configuration registers */
+ ag71xx_wr(ag, AG71XX_REG_MAC_CFG1, (MAC_CFG1_RXE | MAC_CFG1_TXE));
+
+ ag71xx_sb(ag, AG71XX_REG_MAC_CFG2,
+ MAC_CFG2_PAD_CRC_EN | MAC_CFG2_LEN_CHECK);
+
+ /* setup FIFO configuration register 0 */
+ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG0, FIFO_CFG0_INIT);
+
+ /* setup MII interface type */
+ ag71xx_mii_ctrl_set_if(ag, ag->mii_if);
+
+ /* setup mdio clock divisor */
+ ag71xx_wr(ag, AG71XX_REG_MII_CFG, MII_CFG_CLK_DIV_20);
+
+ /* setup FIFO configuration registers */
+ ag71xx_sb(ag, AG71XX_REG_FIFO_CFG4, FIFO_CFG4_INIT);
+ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG1, 0x0fff0000);
+ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG2, 0x00001fff);
+ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, FIFO_CFG5_INIT);
+
+ ag71xx_dma_reset(ag);
+
+ ret = ag71xx_rings_init(ag);
+ if (ret)
+ return -1;
+
+ ag71xx_wr(ag, AG71XX_REG_TX_DESC,
+ (u32) virt_to_phys(ag->tx_ring.descs_dma));
+ ag71xx_wr(ag, AG71XX_REG_RX_DESC,
+ (u32) virt_to_phys(ag->rx_ring.descs_dma));
+
+ ag71xx_hw_set_macaddr(ag, ag->dev->enetaddr);
+
+ return 0;
+}
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+#define AG71XX_MDIO_RETRY 1000
+#define AG71XX_MDIO_DELAY 5
+
+static inline struct ag71xx *ag71xx_name2mac(char *devname)
+{
+ if (strcmp(devname, agtable[0].dev->name) == 0)
+ return &agtable[0];
+ else if (strcmp(devname, agtable[1].dev->name) == 0)
+ return &agtable[1];
+ else
+ return NULL;
+}
+
+static inline void ag71xx_mdio_wr(struct ag71xx *ag, unsigned reg,
+ u32 value)
+{
+ uint32_t r;
+
+ r = ag->mac_base + reg;
+ writel(value, r);
+
+ /* flush write */
+ (void) readl(r);
+}
+
+static inline u32 ag71xx_mdio_rr(struct ag71xx *ag, unsigned reg)
+{
+ return readl(ag->mac_base + reg);
+}
+
+static int ag71xx_mdio_read(char *devname, unsigned char addr,
+ unsigned char reg, unsigned short *val)
+{
+ struct ag71xx *ag = ag71xx_name2mac(devname);
+ uint16_t regData;
+ int i;
+
+ ag71xx_mdio_wr(ag, AG71XX_REG_MII_CMD, MII_CMD_WRITE);
+ ag71xx_mdio_wr(ag, AG71XX_REG_MII_ADDR,
+ ((addr & 0xff) << MII_ADDR_SHIFT) | (reg & 0xff));
+ ag71xx_mdio_wr(ag, AG71XX_REG_MII_CMD, MII_CMD_READ);
+
+ i = AG71XX_MDIO_RETRY;
+ while (ag71xx_mdio_rr(ag, AG71XX_REG_MII_IND) & MII_IND_BUSY) {
+ if (i-- == 0) {
+ printf("%s: mii_read timed out\n",
+ ag->dev->name);
+ return -1;
+ }
+ udelay(AG71XX_MDIO_DELAY);
+ }
+
+ regData = (uint16_t) ag71xx_mdio_rr(ag, AG71XX_REG_MII_STATUS) & 0xffff;
+ ag71xx_mdio_wr(ag, AG71XX_REG_MII_CMD, MII_CMD_WRITE);
+
+ DBG("mii_read: addr=%04x, reg=%04x, value=%04x\n", addr, reg, regData);
+
+ if (val)
+ *val = regData;
+
+ return 0;
+}
+
+static int ag71xx_mdio_write(char *devname, unsigned char addr,
+ unsigned char reg, unsigned short val)
+{
+ struct ag71xx *ag = ag71xx_name2mac(devname);
+ int i;
+
+ if (ag == NULL)
+ return 1;
+
+ DBG("mii_write: addr=%04x, reg=%04x, value=%04x\n", addr, reg, val);
+
+ ag71xx_mdio_wr(ag, AG71XX_REG_MII_ADDR,
+ ((addr & 0xff) << MII_ADDR_SHIFT) | (reg & 0xff));
+ ag71xx_mdio_wr(ag, AG71XX_REG_MII_CTRL, val);
+
+ i = AG71XX_MDIO_RETRY;
+ while (ag71xx_mdio_rr(ag, AG71XX_REG_MII_IND) & MII_IND_BUSY) {
+ if (i-- == 0) {
+ printf("%s: mii_write timed out\n",
+ ag->dev->name);
+ break;
+ }
+ udelay(AG71XX_MDIO_DELAY);
+ }
+
+ return 0;
+}
+#endif
+
+int ag71xx_register(bd_t * bis, char *phyname[], uint16_t phyid[], uint16_t phyfixed[])
+{
+ int i, num = 0;
+ u8 used_ports[MAX_AG71XX_DEVS] = CONFIG_AG71XX_PORTS;
+
+ for (i = 0; i < MAX_AG71XX_DEVS; i++) {
+ /*skip if port is configured not to use */
+ if (used_ports[i] == 0)
+ continue;
+
+ agtable[i].dev = malloc(sizeof(struct eth_device));
+ if (agtable[i].dev == NULL) {
+ puts("malloc failed\n");
+ return 0;
+ }
+ memset(agtable[i].dev, 0, sizeof(struct eth_device));
+ sprintf(agtable[i].dev->name, "eth%d", i);
+
+ agtable[i].dev->iobase = 0;
+ agtable[i].dev->init = ag71xx_hw_start;
+ agtable[i].dev->halt = ag71xx_halt;
+ agtable[i].dev->send = ag71xx_send;
+ agtable[i].dev->recv = ag71xx_recv;
+ agtable[i].dev->priv = (void *) (&agtable[i]);
+ agtable[i].macNum = i;
+ eth_register(agtable[i].dev);
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+
+ if ((phyname == NULL) || (phyid == NULL) || (phyfixed == NULL))
+ return -1;
+
+ agtable[i].phyname = strdup(phyname[i]);
+ agtable[i].phyid = phyid[i];
+ agtable[i].phyfixed = phyfixed[i];
+
+ miiphy_register(agtable[i].dev->name, ag71xx_mdio_read,
+ ag71xx_mdio_write);
+#endif
+
+ if (ag71xx_hw_init(&agtable[i]))
+ continue;
+
+ num++;
+ }
+
+ return num;
+}
diff --git a/package/uboot-ar71xx/files/drivers/net/ag71xx.h b/package/uboot-ar71xx/files/drivers/net/ag71xx.h
new file mode 100644
index 000000000..edce42974
--- /dev/null
+++ b/package/uboot-ar71xx/files/drivers/net/ag71xx.h
@@ -0,0 +1,374 @@
+/*
+ * Atheros AR71xx built-in ethernet mac driver
+ *
+ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * Based on Atheros' AG7100 driver
+ *
+ * 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.
+ */
+
+#ifndef __AG71XX_H
+#define __AG71XX_H
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+
+#include <asm/ar71xx.h>
+
+// controller has 2 ports
+#define MAX_AG71XX_DEVS 2
+
+#define ETH_FCS_LEN 4
+
+#define SPEED_10 10
+#define SPEED_100 100
+#define SPEED_1000 1000
+
+
+#define AG71XX_INT_ERR (AG71XX_INT_RX_BE | AG71XX_INT_TX_BE)
+#define AG71XX_INT_TX (AG71XX_INT_TX_PS)
+#define AG71XX_INT_RX (AG71XX_INT_RX_PR | AG71XX_INT_RX_OF)
+
+#define AG71XX_INT_POLL (AG71XX_INT_RX | AG71XX_INT_TX)
+#define AG71XX_INT_INIT (AG71XX_INT_ERR | AG71XX_INT_POLL)
+
+#define AG71XX_TX_FIFO_LEN 2048
+#define AG71XX_TX_MTU_LEN 1536
+#define AG71XX_RX_PKT_RESERVE 64
+#define AG71XX_RX_PKT_SIZE \
+ (AG71XX_RX_PKT_RESERVE + ETH_HLEN + ETH_FRAME_LEN + ETH_FCS_LEN)
+
+#ifndef CONFIG_SYS_RX_ETH_BUFFER
+#define AG71XX_TX_RING_SIZE 4
+#define AG71XX_RX_RING_SIZE 4
+#else
+#define AG71XX_TX_RING_SIZE CONFIG_SYS_RX_ETH_BUFFER
+#define AG71XX_RX_RING_SIZE CONFIG_SYS_RX_ETH_BUFFER
+#endif
+
+#define AG71XX_TX_THRES_STOP (AG71XX_TX_RING_SIZE - 4)
+#define AG71XX_TX_THRES_WAKEUP \
+ (AG71XX_TX_RING_SIZE - (AG71XX_TX_RING_SIZE / 4))
+
+
+
+
+struct ag71xx_desc {
+ u32 data;
+ u32 ctrl;
+#define DESC_EMPTY BIT(31)
+#define DESC_MORE BIT(24)
+#define DESC_PKTLEN_M 0xfff
+ u32 next;
+ u32 pad;
+} __attribute__((aligned(4)));
+
+struct ag71xx_buf {
+ struct sk_buff *skb;
+ struct ag71xx_desc *desc;
+ dma_addr_t dma_addr;
+ u32 pad;
+};
+
+struct ag71xx_ring {
+ struct ag71xx_buf *buf;
+ u8 *descs_cpu;
+ u8 *descs_dma;
+ unsigned int desc_size;
+ unsigned int curr;
+ unsigned int size;
+};
+
+struct ag71xx {
+ uint32_t mac_base;
+ uint32_t mii_ctrl;
+
+ struct eth_device *dev;
+
+ struct ag71xx_ring rx_ring;
+ struct ag71xx_ring tx_ring;
+
+ char *phyname;
+ u16 phyid;
+ u16 phyfixed;
+ uint32_t link;
+ uint32_t speed;
+ int32_t duplex;
+ uint32_t macNum;
+ uint32_t mii_if;
+};
+
+void ag71xx_link_adjust(struct ag71xx *ag);
+
+int ag71xx_phy_connect(struct ag71xx *ag);
+void ag71xx_phy_disconnect(struct ag71xx *ag);
+void ag71xx_phy_start(struct ag71xx *ag);
+void ag71xx_phy_stop(struct ag71xx *ag);
+
+static inline int ag71xx_desc_empty(struct ag71xx_desc *desc)
+{
+ return ((desc->ctrl & DESC_EMPTY) != 0);
+}
+
+static inline int ag71xx_desc_pktlen(struct ag71xx_desc *desc)
+{
+ return (desc->ctrl & DESC_PKTLEN_M);
+}
+
+/* Register offsets */
+#define AG71XX_REG_MAC_CFG1 0x0000
+#define AG71XX_REG_MAC_CFG2 0x0004
+#define AG71XX_REG_MAC_IPG 0x0008
+#define AG71XX_REG_MAC_HDX 0x000c
+#define AG71XX_REG_MAC_MFL 0x0010
+#define AG71XX_REG_MII_CFG 0x0020
+#define AG71XX_REG_MII_CMD 0x0024
+#define AG71XX_REG_MII_ADDR 0x0028
+#define AG71XX_REG_MII_CTRL 0x002c
+#define AG71XX_REG_MII_STATUS 0x0030
+#define AG71XX_REG_MII_IND 0x0034
+#define AG71XX_REG_MAC_IFCTL 0x0038
+#define AG71XX_REG_MAC_ADDR1 0x0040
+#define AG71XX_REG_MAC_ADDR2 0x0044
+#define AG71XX_REG_FIFO_CFG0 0x0048
+#define AG71XX_REG_FIFO_CFG1 0x004c
+#define AG71XX_REG_FIFO_CFG2 0x0050
+#define AG71XX_REG_FIFO_CFG3 0x0054
+#define AG71XX_REG_FIFO_CFG4 0x0058
+#define AG71XX_REG_FIFO_CFG5 0x005c
+#define AG71XX_REG_FIFO_RAM0 0x0060
+#define AG71XX_REG_FIFO_RAM1 0x0064
+#define AG71XX_REG_FIFO_RAM2 0x0068
+#define AG71XX_REG_FIFO_RAM3 0x006c
+#define AG71XX_REG_FIFO_RAM4 0x0070
+#define AG71XX_REG_FIFO_RAM5 0x0074
+#define AG71XX_REG_FIFO_RAM6 0x0078
+#define AG71XX_REG_FIFO_RAM7 0x007c
+
+#define AG71XX_REG_TX_CTRL 0x0180
+#define AG71XX_REG_TX_DESC 0x0184
+#define AG71XX_REG_TX_STATUS 0x0188
+#define AG71XX_REG_RX_CTRL 0x018c
+#define AG71XX_REG_RX_DESC 0x0190
+#define AG71XX_REG_RX_STATUS 0x0194
+#define AG71XX_REG_INT_ENABLE 0x0198
+#define AG71XX_REG_INT_STATUS 0x019c
+
+#define MAC_CFG1_TXE BIT(0) /* Tx Enable */
+#define MAC_CFG1_STX BIT(1) /* Synchronize Tx Enable */
+#define MAC_CFG1_RXE BIT(2) /* Rx Enable */
+#define MAC_CFG1_SRX BIT(3) /* Synchronize Rx Enable */
+#define MAC_CFG1_TFC BIT(4) /* Tx Flow Control Enable */
+#define MAC_CFG1_RFC BIT(5) /* Rx Flow Control Enable */
+#define MAC_CFG1_LB BIT(8) /* Loopback mode */
+#define MAC_CFG1_SR BIT(31) /* Soft Reset */
+
+#define MAC_CFG2_FDX BIT(0)
+#define MAC_CFG2_CRC_EN BIT(1)
+#define MAC_CFG2_PAD_CRC_EN BIT(2)
+#define MAC_CFG2_LEN_CHECK BIT(4)
+#define MAC_CFG2_HUGE_FRAME_EN BIT(5)
+#define MAC_CFG2_IF_1000 BIT(9)
+#define MAC_CFG2_IF_10_100 BIT(8)
+
+#define FIFO_CFG0_WTM BIT(0) /* Watermark Module */
+#define FIFO_CFG0_RXS BIT(1) /* Rx System Module */
+#define FIFO_CFG0_RXF BIT(2) /* Rx Fabric Module */
+#define FIFO_CFG0_TXS BIT(3) /* Tx System Module */
+#define FIFO_CFG0_TXF BIT(4) /* Tx Fabric Module */
+#define FIFO_CFG0_ALL (FIFO_CFG0_WTM | FIFO_CFG0_RXS | FIFO_CFG0_RXF \
+ | FIFO_CFG0_TXS | FIFO_CFG0_TXF)
+
+#define FIFO_CFG0_ENABLE_SHIFT 8
+
+#define FIFO_CFG4_DE BIT(0) /* Drop Event */
+#define FIFO_CFG4_DV BIT(1) /* RX_DV Event */
+#define FIFO_CFG4_FC BIT(2) /* False Carrier */
+#define FIFO_CFG4_CE BIT(3) /* Code Error */
+#define FIFO_CFG4_CR BIT(4) /* CRC error */
+#define FIFO_CFG4_LM BIT(5) /* Length Mismatch */
+#define FIFO_CFG4_LO BIT(6) /* Length out of range */
+#define FIFO_CFG4_OK BIT(7) /* Packet is OK */
+#define FIFO_CFG4_MC BIT(8) /* Multicast Packet */
+#define FIFO_CFG4_BC BIT(9) /* Broadcast Packet */
+#define FIFO_CFG4_DR BIT(10) /* Dribble */
+#define FIFO_CFG4_LE BIT(11) /* Long Event */
+#define FIFO_CFG4_CF BIT(12) /* Control Frame */
+#define FIFO_CFG4_PF BIT(13) /* Pause Frame */
+#define FIFO_CFG4_UO BIT(14) /* Unsupported Opcode */
+#define FIFO_CFG4_VT BIT(15) /* VLAN tag detected */
+#define FIFO_CFG4_FT BIT(16) /* Frame Truncated */
+#define FIFO_CFG4_UC BIT(17) /* Unicast Packet */
+
+#define FIFO_CFG5_DE BIT(0) /* Drop Event */
+#define FIFO_CFG5_DV BIT(1) /* RX_DV Event */
+#define FIFO_CFG5_FC BIT(2) /* False Carrier */
+#define FIFO_CFG5_CE BIT(3) /* Code Error */
+#define FIFO_CFG5_LM BIT(4) /* Length Mismatch */
+#define FIFO_CFG5_LO BIT(5) /* Length Out of Range */
+#define FIFO_CFG5_OK BIT(6) /* Packet is OK */
+#define FIFO_CFG5_MC BIT(7) /* Multicast Packet */
+#define FIFO_CFG5_BC BIT(8) /* Broadcast Packet */
+#define FIFO_CFG5_DR BIT(9) /* Dribble */
+#define FIFO_CFG5_CF BIT(10) /* Control Frame */
+#define FIFO_CFG5_PF BIT(11) /* Pause Frame */
+#define FIFO_CFG5_UO BIT(12) /* Unsupported Opcode */
+#define FIFO_CFG5_VT BIT(13) /* VLAN tag detected */
+#define FIFO_CFG5_LE BIT(14) /* Long Event */
+#define FIFO_CFG5_FT BIT(15) /* Frame Truncated */
+#define FIFO_CFG5_16 BIT(16) /* unknown */
+#define FIFO_CFG5_17 BIT(17) /* unknown */
+#define FIFO_CFG5_SF BIT(18) /* Short Frame */
+#define FIFO_CFG5_BM BIT(19) /* Byte Mode */
+
+#define AG71XX_INT_TX_PS BIT(0)
+#define AG71XX_INT_TX_UR BIT(1)
+#define AG71XX_INT_TX_BE BIT(3)
+#define AG71XX_INT_RX_PR BIT(4)
+#define AG71XX_INT_RX_OF BIT(6)
+#define AG71XX_INT_RX_BE BIT(7)
+
+#define MAC_IFCTL_SPEED BIT(16)
+
+#define MII_CFG_CLK_DIV_4 0
+#define MII_CFG_CLK_DIV_6 2
+#define MII_CFG_CLK_DIV_8 3
+#define MII_CFG_CLK_DIV_10 4
+#define MII_CFG_CLK_DIV_14 5
+#define MII_CFG_CLK_DIV_20 6
+#define MII_CFG_CLK_DIV_28 7
+#define MII_CFG_RESET BIT(31)
+
+#define MII_CMD_WRITE 0x0
+#define MII_CMD_READ 0x1
+#define MII_ADDR_SHIFT 8
+#define MII_IND_BUSY BIT(0)
+#define MII_IND_INVALID BIT(2)
+
+#define TX_CTRL_TXE BIT(0) /* Tx Enable */
+
+#define TX_STATUS_PS BIT(0) /* Packet Sent */
+#define TX_STATUS_UR BIT(1) /* Tx Underrun */
+#define TX_STATUS_BE BIT(3) /* Bus Error */
+
+#define RX_CTRL_RXE BIT(0) /* Rx Enable */
+
+#define RX_STATUS_PR BIT(0) /* Packet Received */
+#define RX_STATUS_OF BIT(2) /* Rx Overflow */
+#define RX_STATUS_BE BIT(3) /* Bus Error */
+
+#define MII_CTRL_IF_MASK 3
+#define MII_CTRL_SPEED_SHIFT 4
+#define MII_CTRL_SPEED_MASK 3
+#define MII_CTRL_SPEED_10 0
+#define MII_CTRL_SPEED_100 1
+#define MII_CTRL_SPEED_1000 2
+
+static inline void ag71xx_wr(struct ag71xx *ag, unsigned reg, u32 value)
+{
+ __raw_writel(value, ag->mac_base + reg);
+ /* flush write */
+ (void) __raw_readl(ag->mac_base + reg);
+}
+
+static inline u32 ag71xx_rr(struct ag71xx *ag, unsigned reg)
+{
+ return __raw_readl(ag->mac_base + reg);
+}
+
+static inline void ag71xx_sb(struct ag71xx *ag, unsigned reg, u32 mask)
+{
+ uint32_t r;
+
+ r = ag->mac_base + reg;
+ __raw_writel(__raw_readl(r) | mask, r);
+ /* flush write */
+ (void)__raw_readl(r);
+}
+
+static inline void ag71xx_cb(struct ag71xx *ag, unsigned reg, u32 mask)
+{
+ uint32_t r;
+
+ r = ag->mac_base + reg;
+ __raw_writel(__raw_readl(r) & ~mask, r);
+ /* flush write */
+ (void) __raw_readl(r);
+}
+
+static inline void ag71xx_int_enable(struct ag71xx *ag, u32 ints)
+{
+ ag71xx_sb(ag, AG71XX_REG_INT_ENABLE, ints);
+}
+
+static inline void ag71xx_int_disable(struct ag71xx *ag, u32 ints)
+{
+ ag71xx_cb(ag, AG71XX_REG_INT_ENABLE, ints);
+}
+
+static inline void ag71xx_mii_ctrl_wr(struct ag71xx *ag, u32 value)
+{
+ __raw_writel(value, ag->mii_ctrl);
+
+ /* flush write */
+ __raw_readl(ag->mii_ctrl);
+}
+
+static inline u32 ag71xx_mii_ctrl_rr(struct ag71xx *ag)
+{
+ return __raw_readl(ag->mii_ctrl);
+}
+
+static void inline ag71xx_mii_ctrl_set_if(struct ag71xx *ag,
+ unsigned int mii_if)
+{
+ u32 t;
+
+ t = ag71xx_mii_ctrl_rr(ag);
+ t &= ~(MII_CTRL_IF_MASK);
+ t |= (mii_if & MII_CTRL_IF_MASK);
+ ag71xx_mii_ctrl_wr(ag, t);
+}
+
+static void inline ag71xx_mii_ctrl_set_speed(struct ag71xx *ag,
+ unsigned int speed)
+{
+ u32 t;
+
+ t = ag71xx_mii_ctrl_rr(ag);
+ t &= ~(MII_CTRL_SPEED_MASK << MII_CTRL_SPEED_SHIFT);
+ t |= (speed & MII_CTRL_SPEED_MASK) << MII_CTRL_SPEED_SHIFT;
+ ag71xx_mii_ctrl_wr(ag, t);
+}
+
+#ifdef CONFIG_AG71XX_AR8216_SUPPORT
+void ag71xx_add_ar8216_header(struct ag71xx *ag, struct sk_buff *skb);
+int ag71xx_remove_ar8216_header(struct ag71xx *ag, struct sk_buff *skb,
+ int pktlen);
+static inline int ag71xx_has_ar8216(struct ag71xx *ag)
+{
+ return ag71xx_get_pdata(ag)->has_ar8216;
+}
+#else
+static inline void ag71xx_add_ar8216_header(struct ag71xx *ag,
+ struct sk_buff *skb)
+{
+}
+
+static inline int ag71xx_remove_ar8216_header(struct ag71xx *ag,
+ struct sk_buff *skb,
+ int pktlen)
+{
+ return 0;
+}
+static inline int ag71xx_has_ar8216(struct ag71xx *ag)
+{
+ return 0;
+}
+#endif
+
+#endif /* _AG71XX_H */
diff --git a/package/uboot-ar71xx/files/drivers/net/phy/rtl8366.h b/package/uboot-ar71xx/files/drivers/net/phy/rtl8366.h
new file mode 100644
index 000000000..f0567dd64
--- /dev/null
+++ b/package/uboot-ar71xx/files/drivers/net/phy/rtl8366.h
@@ -0,0 +1,188 @@
+/*
+ * (C) Copyright 2010
+ * Michael Kurz <michi.kurz@googlemail.com>.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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 RTL8366_MII_H
+#define RTL8366_MII_H
+
+#define MII_CONTROL_REG 0
+#define MII_STATUS_REG 1
+#define MII_PHY_ID0 2
+#define MII_PHY_ID1 3
+#define MII_LOCAL_CAP 4
+#define MII_REMOTE_CAP 5
+#define MII_EXT_AUTONEG 6
+#define MII_LOCAL_NEXT_PAGE 7
+#define MII_REMOTE_NEXT_PAGE 8
+#define MII_GIGA_CONTROL 9
+#define MII_GIGA_STATUS 10
+#define MII_EXT_STATUS_REG 15
+
+/* Control register */
+#define MII_CONTROL_1000MBPS 6
+#define MII_CONTROL_COLL_TEST 7
+#define MII_CONTROL_FULLDUPLEX 8
+#define MII_CONTROL_RENEG 9
+#define MII_CONTROL_ISOLATE 10
+#define MII_CONTROL_POWERDOWN 11
+#define MII_CONTROL_AUTONEG 12
+#define MII_CONTROL_100MBPS 13
+#define MII_CONTROL_LOOPBACK 14
+#define MII_CONTROL_RESET 15
+
+/* Status/Extended status register */
+/* Basic status */
+#define MII_STATUS_CAPABILITY 0
+#define MII_STATUS_JABBER 1
+#define MII_STATUS_LINK_UP 2
+#define MII_STATUS_AUTONEG_ABLE 3
+#define MII_STATUS_REMOTE_FAULT 4
+#define MII_STATUS_AUTONEG_DONE 5
+#define MII_STATUS_NO_PREAMBLE 6
+#define MII_STATUS_RESERVED 7
+#define MII_STATUS_EXTENDED 8
+#define MII_STATUS_100_T2_HALF 9
+#define MII_STATUS_100_T2_FULL 10
+#define MII_STATUS_10_TX_HALF 11
+#define MII_STATUS_10_TX_FULL 12
+#define MII_STATUS_100_TX_HALF 13
+#define MII_STATUS_100_TX_FULL 14
+#define MII_STATUS_100_T4 15
+
+#define MII_GIGA_CONTROL_HALF 8
+#define MII_GIGA_CONTROL_FULL 9
+#define MII_GIGA_STATUS_HALF 10
+#define MII_GIGA_STATUS_FULL 11
+
+/* Extended status */
+#define MII_STATUS_1000_T_HALF 12
+#define MII_STATUS_1000_T_FULL 13
+#define MII_STATUS_1000_X_HALF 14
+#define MII_STATUS_1000_X_FULL 15
+
+/* Local/Remmote capability register */
+#define MII_CAP_10BASE_TX 5
+#define MII_CAP_10BASE_TX_FULL 6
+#define MII_CAP_100BASE_TX 7
+#define MII_CAP_100BASE_TX_FULL 8
+#define MII_CAP_100BASE_T4 9
+#define MII_CAP_SYMM_PAUSE 10
+#define MII_CAP_ASYMM_PAUSE 11
+#define MII_CAP_RESERVED 12
+#define MII_CAP_REMOTE_FAULT 13
+#define MII_CAP_ACKNOWLEDGE 14
+#define MII_CAP_NEXT_PAGE 15
+#define MII_CAP_IEEE_802_3 0x0001
+
+#define MII_LINK_MODE_MASK 0x1f
+
+#define REALTEK_RTL8366_CHIP_ID0 0x001C
+#define REALTEK_RTL8366_CHIP_ID1 0xC940
+#define REALTEK_RTL8366_CHIP_ID1_MP 0xC960
+
+#define REALTEK_MIN_PORT_ID 0
+#define REALTEK_MAX_PORT_ID 5
+#define REALTEK_MIN_PHY_ID REALTEK_MIN_PORT_ID
+#define REALTEK_MAX_PHY_ID 4
+#define REALTEK_CPU_PORT_ID REALTEK_MAX_PORT_ID
+#define REALTEK_PHY_PORT_MASK ((1<<(REALTEK_MAX_PHY_ID+1)) - (1<<REALTEK_MIN_PHY_ID))
+#define REALTEK_CPU_PORT_MASK (1<<REALTEK_CPU_PORT_ID)
+#define REALTEK_ALL_PORT_MASK (REALTEK_PHY_PORT_MASK | REALTEK_CPU_PORT_MASK)
+
+/* port ability */
+#define RTL8366S_PORT_ABILITY_BASE 0x0011
+
+/* port vlan control register */
+#define RTL8366S_PORT_VLAN_CTRL_BASE 0x0058
+
+/* port linking status */
+#define RTL8366S_PORT_LINK_STATUS_BASE 0x0060
+#define RTL8366S_PORT_STATUS_SPEED_BIT 0
+#define RTL8366S_PORT_STATUS_SPEED_MSK 0x0003
+#define RTL8366S_PORT_STATUS_DUPLEX_BIT 2
+#define RTL8366S_PORT_STATUS_DUPLEX_MSK 0x0004
+#define RTL8366S_PORT_STATUS_LINK_BIT 4
+#define RTL8366S_PORT_STATUS_LINK_MSK 0x0010
+#define RTL8366S_PORT_STATUS_TXPAUSE_BIT 5
+#define RTL8366S_PORT_STATUS_TXPAUSE_MSK 0x0020
+#define RTL8366S_PORT_STATUS_RXPAUSE_BIT 6
+#define RTL8366S_PORT_STATUS_RXPAUSE_MSK 0x0040
+#define RTL8366S_PORT_STATUS_AN_BIT 7
+#define RTL8366S_PORT_STATUS_AN_MSK 0x0080
+
+/* internal control */
+#define RTL8366S_RESET_CONTROL_REG 0x0100
+#define RTL8366S_RESET_QUEUE_BIT 2
+
+#define RTL8366S_CHIP_ID_REG 0x0105
+
+/* MAC control */
+#define RTL8366S_MAC_FORCE_CTRL0_REG 0x0F04
+#define RTL8366S_MAC_FORCE_CTRL1_REG 0x0F05
+
+
+/* PHY registers control */
+#define RTL8366S_PHY_ACCESS_CTRL_REG 0x8028
+#define RTL8366S_PHY_ACCESS_DATA_REG 0x8029
+
+#define RTL8366S_PHY_CTRL_READ 1
+#define RTL8366S_PHY_CTRL_WRITE 0
+
+#define RTL8366S_PHY_REG_MASK 0x1F
+#define RTL8366S_PHY_PAGE_OFFSET 5
+#define RTL8366S_PHY_PAGE_MASK (0x7<<5)
+#define RTL8366S_PHY_NO_OFFSET 9
+#define RTL8366S_PHY_NO_MASK (0x1F<<9)
+
+#define RTL8366S_PHY_NO_MAX 4
+#define RTL8366S_PHY_PAGE_MAX 7
+#define RTL8366S_PHY_ADDR_MAX 31
+
+/* cpu port control reg */
+#define RTL8366S_CPU_CTRL_REG 0x004F
+#define RTL8366S_CPU_DRP_BIT 14
+#define RTL8366S_CPU_DRP_MSK 0x4000
+#define RTL8366S_CPU_INSTAG_BIT 15
+#define RTL8366S_CPU_INSTAG_MSK 0x8000
+
+/* LED registers*/
+#define RTL8366S_LED_BLINK_REG 0x420
+#define RTL8366S_LED_BLINKRATE_BIT 0
+#define RTL8366S_LED_BLINKRATE_MSK 0x0007
+#define RTL8366S_LED_INDICATED_CONF_REG 0x421
+#define RTL8366S_LED_0_1_FORCE_REG 0x422
+#define RTL8366S_LED_2_3_FORCE_REG 0x423
+#define RTL8366S_LEDCONF_LEDFORCE 0x1F
+#define RTL8366S_LED_GROUP_MAX 4
+
+#define RTL8366S_GREEN_FEATURE_REG 0x000A
+#define RTL8366S_GREEN_FEATURE_TX_BIT 3
+#define RTL8366S_GREEN_FEATURE_TX_MSK 0x0008
+#define RTL8366S_GREEN_FEATURE_RX_BIT 4
+#define RTL8366S_GREEN_FEATURE_RX_MSK 0x0010
+
+#define RTL8366S_MODEL_ID_REG 0x5C
+#define RTL8366S_REV_ID_REG 0x5D
+#define RTL8366S_MODEL_8366SR 0x6027
+#define RTL8366S_MODEL_8366RB 0x5937
+
+#endif
diff --git a/package/uboot-ar71xx/files/drivers/net/phy/rtl8366_mii.c b/package/uboot-ar71xx/files/drivers/net/phy/rtl8366_mii.c
new file mode 100644
index 000000000..e3c531654
--- /dev/null
+++ b/package/uboot-ar71xx/files/drivers/net/phy/rtl8366_mii.c
@@ -0,0 +1,786 @@
+/*
+ * (C) Copyright 2010
+ * Michael Kurz <michi.kurz@googlemail.com>.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+
+#include <common.h>
+#include <net.h>
+#include <netdev.h>
+#include <miiphy.h>
+#include MII_GPIOINCLUDE
+
+#include "rtl8366.h"
+
+#ifdef DEBUG_RTL8366
+ #define DBG(fmt,args...) printf (fmt ,##args)
+#else
+ #define DBG(fmt,args...)
+#endif
+
+
+//-------------------------------------------------------------------
+// Soft SMI functions
+//-------------------------------------------------------------------
+
+#define DELAY 2
+
+static void smi_init(void)
+{
+ MII_SDAINPUT;
+ MII_SCKINPUT;
+
+ MII_SETSDA(1);
+ MII_SETSCK(1);
+
+ udelay(20);
+}
+
+static void smi_start(void)
+{
+/*
+ * rtl8366 chip needs a extra clock with
+ * SDA high before start condition
+ */
+
+ /* set gpio pins output */
+ MII_SDAOUTPUT;
+ MII_SCKOUTPUT;
+ udelay(DELAY);
+
+ /* set initial state: SCK:0, SDA:1 */
+ MII_SETSCK(0);
+ MII_SETSDA(1);
+ udelay(DELAY);
+
+ /* toggle clock */
+ MII_SETSCK(1);
+ udelay(DELAY);
+ MII_SETSCK(0);
+ udelay(DELAY);
+
+ /* start condition */
+ MII_SETSCK(1);
+ udelay(DELAY);
+ MII_SETSDA(0);
+ udelay(DELAY);
+ MII_SETSCK(0);
+ udelay(DELAY);
+ MII_SETSDA(1);
+}
+
+static void smi_stop(void)
+{
+/*
+ * rtl8366 chip needs a extra clock with
+ * SDA high after stop condition
+ */
+
+ /* stop condition */
+ udelay(DELAY);
+ MII_SETSDA(0);
+ MII_SETSCK(1);
+ udelay(DELAY);
+ MII_SETSDA(1);
+ udelay(DELAY);
+ MII_SETSCK(1);
+ udelay(DELAY);
+ MII_SETSCK(0);
+ udelay(DELAY);
+
+ /* toggle clock */
+ MII_SETSCK(1);
+ udelay(DELAY);
+ MII_SETSCK(0);
+ udelay(DELAY);
+ MII_SETSCK(1);
+
+ /* set gpio pins input */
+ MII_SDAINPUT;
+ MII_SCKINPUT;
+}
+
+static void smi_writeBits(uint32_t data, uint8_t length)
+{
+ uint8_t test;
+
+ for( ; length > 0; length--) {
+ udelay(DELAY);
+
+ /* output data */
+ test = (((data & (1 << (length - 1))) != 0) ? 1 : 0);
+ MII_SETSDA(test);
+ udelay(DELAY);
+
+ /* toogle clock */
+ MII_SETSCK(1);
+ udelay(DELAY);
+ MII_SETSCK(0);
+ }
+}
+
+static uint32_t smi_readBits(uint8_t length)
+{
+ uint32_t ret;
+
+ MII_SDAINPUT;
+
+ for(ret = 0 ; length > 0; length--) {
+ udelay(DELAY);
+
+ ret <<= 1;
+
+ /* toogle clock */
+ MII_SETSCK(1);
+ udelay(DELAY);
+ ret |= MII_GETSDA;
+ MII_SETSCK(0);
+ }
+
+ MII_SDAOUTPUT;
+
+ return ret;
+}
+
+static int smi_waitAck(void)
+{
+ uint32_t retry = 0;
+
+ while (smi_readBits(1)) {
+ if (retry++ == 5)
+ return -1;
+ }
+
+ return 0;
+
+}
+
+static int smi_read(uint32_t reg, uint32_t *data)
+{
+ uint32_t rawData;
+
+ /* send start condition */
+ smi_start();
+ /* send CTRL1 code: 0b1010*/
+ smi_writeBits(0x0a, 4);
+ /* send CTRL2 code: 0b100 */
+ smi_writeBits(0x04, 3);
+ /* send READ command */
+ smi_writeBits(0x01, 1);
+
+ /* wait for ACK */
+ if (smi_waitAck())
+ return -1;
+
+ /* send address low */
+ smi_writeBits(reg & 0xFF, 8);
+ /* wait for ACK */
+ if (smi_waitAck())
+ return -1;
+ /* send address high */
+ smi_writeBits((reg & 0xFF00) >> 8, 8);
+ /* wait for ACK */
+ if (smi_waitAck())
+ return -1;
+
+ /* read data low */
+ rawData = (smi_readBits(8) & 0xFF);
+ /* send ACK */
+ smi_writeBits(0, 1);
+ /* read data high */
+ rawData |= (smi_readBits(8) & 0xFF) << 8;
+ /* send NACK */
+ smi_writeBits(1, 1);
+
+ /* send stop condition */
+ smi_stop();
+
+ if (data)
+ *data = rawData;
+
+ return 0;
+}
+
+static int smi_write(uint32_t reg, uint32_t data)
+{
+ /* send start condition */
+ smi_start();
+ /* send CTRL1 code: 0b1010*/
+ smi_writeBits(0x0a, 4);
+ /* send CTRL2 code: 0b100 */
+ smi_writeBits(0x04, 3);
+ /* send WRITE command */
+ smi_writeBits(0x00, 1);
+
+ /* wait for ACK */
+ if (smi_waitAck())
+ return -1;
+
+ /* send address low */
+ smi_writeBits(reg & 0xFF, 8);
+ /* wait for ACK */
+ if (smi_waitAck())
+ return -1;
+ /* send address high */
+ smi_writeBits((reg & 0xFF00) >> 8, 8);
+ /* wait for ACK */
+ if (smi_waitAck())
+ return -1;
+
+ /* send data low */
+ smi_writeBits(data & 0xFF, 8);
+ /* wait for ACK */
+ if (smi_waitAck())
+ return -1;
+ /* send data high */
+ smi_writeBits((data & 0xFF00) >> 8, 8);
+ /* wait for ACK */
+ if (smi_waitAck())
+ return -1;
+
+ /* send stop condition */
+ smi_stop();
+
+ return 0;
+}
+
+
+//-------------------------------------------------------------------
+// Switch register read / write functions
+//-------------------------------------------------------------------
+static int rtl8366_readRegister(uint32_t reg, uint16_t *data)
+{
+ uint32_t regData;
+
+ DBG("rtl8366: read register=%#04x, data=", reg);
+
+ if (smi_read(reg, &regData)) {
+ printf("\nrtl8366 smi read failed!\n");
+ return -1;
+ }
+
+ if (data)
+ *data = regData;
+
+ DBG("%#04x\n", regData);
+
+ return 0;
+}
+
+static int rtl8366_writeRegister(uint32_t reg, uint16_t data)
+{
+ DBG("rtl8366: write register=%#04x, data=%#04x\n", reg, data);
+
+ if (smi_write(reg, data)) {
+ printf("rtl8366 smi write failed!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int rtl8366_setRegisterBit(uint32_t reg, uint32_t bitNum, uint32_t value)
+{
+ uint16_t regData;
+
+ if (bitNum >= 16)
+ return -1;
+
+ if (rtl8366_readRegister(reg, &regData))
+ return -1;
+
+ if (value)
+ regData |= (1 << bitNum);
+ else
+ regData &= ~(1 << bitNum);
+
+ if (rtl8366_writeRegister(reg, regData))
+ return -1;
+
+ return 0;
+}
+
+//-------------------------------------------------------------------
+// MII PHY read / write functions
+//-------------------------------------------------------------------
+static int rtl8366_getPhyReg(uint32_t phyNum, uint32_t reg, uint16_t *data)
+{
+ uint16_t phyAddr, regData;
+
+ if (phyNum > RTL8366S_PHY_NO_MAX) {
+ printf("rtl8366s: invalid phy number!\n");
+ return -1;
+ }
+
+ if (phyNum > RTL8366S_PHY_ADDR_MAX) {
+ printf("rtl8366s: invalid phy register number!\n");
+ return -1;
+ }
+
+ if (rtl8366_writeRegister(RTL8366S_PHY_ACCESS_CTRL_REG,
+ RTL8366S_PHY_CTRL_READ))
+ return -1;
+
+ phyAddr = 0x8000 | (1 << (phyNum + RTL8366S_PHY_NO_OFFSET))
+ | (reg & RTL8366S_PHY_REG_MASK);
+ if (rtl8366_writeRegister(phyAddr, 0))
+ return -1;
+
+ if (rtl8366_readRegister(RTL8366S_PHY_ACCESS_DATA_REG, &regData))
+ return -1;
+
+ if (data)
+ *data = regData;
+
+ return 0;
+}
+
+static int rtl8366_setPhyReg(uint32_t phyNum, uint32_t reg, uint16_t data)
+{
+ uint16_t phyAddr;
+
+ if (phyNum > RTL8366S_PHY_NO_MAX) {
+ printf("rtl8366s: invalid phy number!\n");
+ return -1;
+ }
+
+ if (phyNum > RTL8366S_PHY_ADDR_MAX) {
+ printf("rtl8366s: invalid phy register number!\n");
+ return -1;
+ }
+
+ if (rtl8366_writeRegister(RTL8366S_PHY_ACCESS_CTRL_REG,
+ RTL8366S_PHY_CTRL_WRITE))
+ return -1;
+
+ phyAddr = 0x8000 | (1 << (phyNum + RTL8366S_PHY_NO_OFFSET))
+ | (reg & RTL8366S_PHY_REG_MASK);
+ if (rtl8366_writeRegister(phyAddr, data))
+ return -1;
+
+ return 0;
+}
+
+static int rtl8366_miiread(char *devname, uchar phy_adr, uchar reg, ushort *data)
+{
+ uint16_t regData;
+
+ DBG("rtl8366_miiread: devname=%s, addr=%#02x, reg=%#02x\n",
+ devname, phy_adr, reg);
+
+ if (strcmp(devname, RTL8366_DEVNAME) != 0)
+ return -1;
+
+ if (rtl8366_getPhyReg(phy_adr, reg, &regData)) {
+ printf("rtl8366_miiread: write failed!\n");
+ return -1;
+ }
+
+ if (data)
+ *data = regData;
+
+ return 0;
+}
+
+static int rtl8366_miiwrite(char *devname, uchar phy_adr, uchar reg, ushort data)
+{
+ DBG("rtl8366_miiwrite: devname=%s, addr=%#02x, reg=%#02x, data=%#04x\n",
+ devname, phy_adr, reg, data);
+
+ if (strcmp(devname, RTL8366_DEVNAME) != 0)
+ return -1;
+
+ if (rtl8366_setPhyReg(phy_adr, reg, data)) {
+ printf("rtl8366_miiwrite: write failed!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int rtl8366_mii_register(bd_t *bis)
+{
+ miiphy_register(strdup(RTL8366_DEVNAME), rtl8366_miiread,
+ rtl8366_miiwrite);
+
+ return 0;
+}
+
+
+//-------------------------------------------------------------------
+// Switch management functions
+//-------------------------------------------------------------------
+
+int rtl8366s_setGreenFeature(uint32_t tx, uint32_t rx)
+{
+ if (rtl8366_setRegisterBit(RTL8366S_GREEN_FEATURE_REG,
+ RTL8366S_GREEN_FEATURE_TX_BIT, tx))
+ return -1;
+
+ if (rtl8366_setRegisterBit(RTL8366S_GREEN_FEATURE_REG,
+ RTL8366S_GREEN_FEATURE_RX_BIT, rx))
+ return -1;
+
+ return 0;
+}
+
+int rtl8366s_setPowerSaving(uint32_t phyNum, uint32_t enabled)
+{
+ uint16_t regData;
+
+ if (phyNum > RTL8366S_PHY_NO_MAX)
+ return -1;
+
+ if (rtl8366_getPhyReg(phyNum, 12, &regData))
+ return -1;
+
+ if (enabled)
+ regData |= (1 << 12);
+ else
+ regData &= ~(1 << 12);
+
+ if (rtl8366_setPhyReg(phyNum, 12, regData))
+ return -1;
+
+ return 0;
+}
+
+int rtl8366s_setGreenEthernet(uint32_t greenFeature, uint32_t powerSaving)
+{
+ uint32_t phyNum, i;
+ uint16_t regData;
+
+ const uint16_t greenSettings[][2] =
+ {
+ {0xBE5B,0x3500},
+ {0xBE5C,0xB975},
+ {0xBE5D,0xB9B9},
+ {0xBE77,0xA500},
+ {0xBE78,0x5A78},
+ {0xBE79,0x6478}
+ };
+
+ if (rtl8366_readRegister(RTL8366S_MODEL_ID_REG, &regData))
+ return -1;
+
+ switch (regData)
+ {
+ case 0x0000:
+ for (i = 0; i < 6; i++) {
+ if (rtl8366_writeRegister(RTL8366S_PHY_ACCESS_CTRL_REG, RTL8366S_PHY_CTRL_WRITE))
+ return -1;
+ if (rtl8366_writeRegister(greenSettings[i][0], greenSettings[i][1]))
+ return -1;
+ }
+ break;
+
+ case RTL8366S_MODEL_8366SR:
+ if (rtl8366_writeRegister(RTL8366S_PHY_ACCESS_CTRL_REG, RTL8366S_PHY_CTRL_WRITE))
+ return -1;
+ if (rtl8366_writeRegister(greenSettings[0][0], greenSettings[0][1]))
+ return -1;
+ break;
+
+ default:
+ printf("rtl8366s_initChip: unsupported chip found!\n");
+ return -1;
+ }
+
+ if (rtl8366s_setGreenFeature(greenFeature, powerSaving))
+ return -1;
+
+ for (phyNum = 0; phyNum <= RTL8366S_PHY_NO_MAX; phyNum++) {
+ if (rtl8366s_setPowerSaving(phyNum, powerSaving))
+ return -1;
+ }
+
+ return 0;
+}
+
+int rtl8366s_setCPUPortMask(uint8_t port, uint32_t enabled)
+{
+ if(port >= 6){
+ printf("rtl8366s_setCPUPortMask: invalid port number\n");
+ return -1;
+ }
+
+ return rtl8366_setRegisterBit(RTL8366S_CPU_CTRL_REG, port, enabled);
+}
+
+int rtl8366s_setCPUDisableInsTag(uint32_t enable)
+{
+ return rtl8366_setRegisterBit(RTL8366S_CPU_CTRL_REG,
+ RTL8366S_CPU_INSTAG_BIT, enable);
+}
+
+int rtl8366s_setCPUDropUnda(uint32_t enable)
+{
+ return rtl8366_setRegisterBit(RTL8366S_CPU_CTRL_REG,
+ RTL8366S_CPU_DRP_BIT, enable);
+}
+
+int rtl8366s_setCPUPort(uint8_t port, uint32_t noTag, uint32_t dropUnda)
+{
+ uint32_t i;
+
+ if(port >= 6){
+ printf("rtl8366s_setCPUPort: invalid port number\n");
+ return -1;
+ }
+
+ /* reset register */
+ for(i = 0; i < 6; i++)
+ {
+ if(rtl8366s_setCPUPortMask(i, 0)){
+ printf("rtl8366s_setCPUPort: rtl8366s_setCPUPortMask failed\n");
+ return -1;
+ }
+ }
+
+ if(rtl8366s_setCPUPortMask(port, 1)){
+ printf("rtl8366s_setCPUPort: rtl8366s_setCPUPortMask failed\n");
+ return -1;
+ }
+
+ if(rtl8366s_setCPUDisableInsTag(noTag)){
+ printf("rtl8366s_setCPUPort: rtl8366s_setCPUDisableInsTag fail\n");
+ return -1;
+ }
+
+ if(rtl8366s_setCPUDropUnda(dropUnda)){
+ printf("rtl8366s_setCPUPort: rtl8366s_setCPUDropUnda fail\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int rtl8366s_setLedConfig(uint32_t ledNum, uint8_t config)
+{
+ uint16_t regData;
+
+ if(ledNum >= RTL8366S_LED_GROUP_MAX) {
+ DBG("rtl8366s_setLedConfig: invalid led group\n");
+ return -1;
+ }
+
+ if(config > RTL8366S_LEDCONF_LEDFORCE) {
+ DBG("rtl8366s_setLedConfig: invalid led config\n");
+ return -1;
+ }
+
+ if (rtl8366_readRegister(RTL8366S_LED_INDICATED_CONF_REG, &regData)) {
+ printf("rtl8366s_setLedConfig: failed to get led register!\n");
+ return -1;
+ }
+
+ regData &= ~(0xF << (ledNum * 4));
+ regData |= config << (ledNum * 4);
+
+ if (rtl8366_writeRegister(RTL8366S_LED_INDICATED_CONF_REG, regData)) {
+ printf("rtl8366s_setLedConfig: failed to set led register!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int rtl8366s_getLedConfig(uint32_t ledNum, uint8_t *config)
+{
+ uint16_t regData;
+
+ if(ledNum >= RTL8366S_LED_GROUP_MAX) {
+ DBG("rtl8366s_getLedConfig: invalid led group\n");
+ return -1;
+ }
+
+ if (rtl8366_readRegister(RTL8366S_LED_INDICATED_CONF_REG, &regData)) {
+ printf("rtl8366s_getLedConfig: failed to get led register!\n");
+ return -1;
+ }
+
+ if (config)
+ *config = (regData >> (ledNum * 4)) & 0xF;
+
+ return 0;
+}
+
+int rtl8366s_setLedForceValue(uint32_t group0, uint32_t group1,
+ uint32_t group2, uint32_t group3)
+{
+ uint16_t regData;
+
+ regData = (group0 & 0x3F) | ((group1 & 0x3F) << 6);
+ if (rtl8366_writeRegister(RTL8366S_LED_0_1_FORCE_REG, regData)) {
+ printf("rtl8366s_setLedForceValue: failed to set led register!\n");
+ return -1;
+ }
+
+ regData = (group2 & 0x3F) | ((group3 & 0x3F) << 6);
+ if (rtl8366_writeRegister(RTL8366S_LED_2_3_FORCE_REG, regData)) {
+ printf("rtl8366s_setLedForceValue: failed to set led register!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int rtl8366s_initChip(void)
+{
+ uint32_t ledGroup, i = 0;
+ uint16_t regData;
+ uint8_t ledData[RTL8366S_LED_GROUP_MAX];
+ const uint16_t (*chipData)[2];
+
+ const uint16_t chipB[][2] =
+ {
+ {0x0000, 0x0038},{0x8100, 0x1B37},{0xBE2E, 0x7B9F},{0xBE2B, 0xA4C8},
+ {0xBE74, 0xAD14},{0xBE2C, 0xDC00},{0xBE69, 0xD20F},{0xBE3B, 0xB414},
+ {0xBE24, 0x0000},{0xBE23, 0x00A1},{0xBE22, 0x0008},{0xBE21, 0x0120},
+ {0xBE20, 0x1000},{0xBE24, 0x0800},{0xBE24, 0x0000},{0xBE24, 0xF000},
+ {0xBE23, 0xDF01},{0xBE22, 0xDF20},{0xBE21, 0x101A},{0xBE20, 0xA0FF},
+ {0xBE24, 0xF800},{0xBE24, 0xF000},{0x0242, 0x02BF},{0x0245, 0x02BF},
+ {0x0248, 0x02BF},{0x024B, 0x02BF},{0x024E, 0x02BF},{0x0251, 0x02BF},
+ {0x0230, 0x0A32},{0x0233, 0x0A32},{0x0236, 0x0A32},{0x0239, 0x0A32},
+ {0x023C, 0x0A32},{0x023F, 0x0A32},{0x0254, 0x0A3F},{0x0255, 0x0064},
+ {0x0256, 0x0A3F},{0x0257, 0x0064},{0x0258, 0x0A3F},{0x0259, 0x0064},
+ {0x025A, 0x0A3F},{0x025B, 0x0064},{0x025C, 0x0A3F},{0x025D, 0x0064},
+ {0x025E, 0x0A3F},{0x025F, 0x0064},{0x0260, 0x0178},{0x0261, 0x01F4},
+ {0x0262, 0x0320},{0x0263, 0x0014},{0x021D, 0x9249},{0x021E, 0x0000},
+ {0x0100, 0x0004},{0xBE4A, 0xA0B4},{0xBE40, 0x9C00},{0xBE41, 0x501D},
+ {0xBE48, 0x3602},{0xBE47, 0x8051},{0xBE4C, 0x6465},{0x8000, 0x1F00},
+ {0x8001, 0x000C},{0x8008, 0x0000},{0x8007, 0x0000},{0x800C, 0x00A5},
+ {0x8101, 0x02BC},{0xBE53, 0x0005},{0x8E45, 0xAFE8},{0x8013, 0x0005},
+ {0xBE4B, 0x6700},{0x800B, 0x7000},{0xBE09, 0x0E00},
+ {0xFFFF, 0xABCD}
+ };
+
+ const uint16_t chipDefault[][2] =
+ {
+ {0x0242, 0x02BF},{0x0245, 0x02BF},{0x0248, 0x02BF},{0x024B, 0x02BF},
+ {0x024E, 0x02BF},{0x0251, 0x02BF},
+ {0x0254, 0x0A3F},{0x0256, 0x0A3F},{0x0258, 0x0A3F},{0x025A, 0x0A3F},
+ {0x025C, 0x0A3F},{0x025E, 0x0A3F},
+ {0x0263, 0x007C},{0x0100, 0x0004},
+ {0xBE5B, 0x3500},{0x800E, 0x200F},{0xBE1D, 0x0F00},{0x8001, 0x5011},
+ {0x800A, 0xA2F4},{0x800B, 0x17A3},{0xBE4B, 0x17A3},{0xBE41, 0x5011},
+ {0xBE17, 0x2100},{0x8000, 0x8304},{0xBE40, 0x8304},{0xBE4A, 0xA2F4},
+ {0x800C, 0xA8D5},{0x8014, 0x5500},{0x8015, 0x0004},{0xBE4C, 0xA8D5},
+ {0xBE59, 0x0008},{0xBE09, 0x0E00},{0xBE36, 0x1036},{0xBE37, 0x1036},
+ {0x800D, 0x00FF},{0xBE4D, 0x00FF},
+ {0xFFFF, 0xABCD}
+ };
+
+ DBG("rtl8366s_initChip\n");
+
+ /* save current led config and set to led force */
+ for (ledGroup = 0; ledGroup < RTL8366S_LED_GROUP_MAX; ledGroup++) {
+ if (rtl8366s_getLedConfig(ledGroup, &ledData[ledGroup]))
+ return -1;
+
+ if (rtl8366s_setLedConfig(ledGroup, RTL8366S_LEDCONF_LEDFORCE))
+ return -1;
+ }
+
+ if (rtl8366s_setLedForceValue(0,0,0,0))
+ return -1;
+
+ if (rtl8366_readRegister(RTL8366S_MODEL_ID_REG, &regData))
+ return -1;
+
+ switch (regData)
+ {
+ case 0x0000:
+ chipData = chipB;
+ break;
+
+ case RTL8366S_MODEL_8366SR:
+ chipData = chipDefault;
+ break;
+
+ default:
+ printf("rtl8366s_initChip: unsupported chip found!\n");
+ return -1;
+ }
+
+ DBG("rtl8366s_initChip: found %x chip\n", regData);
+
+ while ((chipData[i][0] != 0xFFFF) && (chipData[i][1] != 0xABCD)) {
+
+ /* phy settings*/
+ if ((chipData[i][0] & 0xBE00) == 0xBE00) {
+ if (rtl8366_writeRegister(RTL8366S_PHY_ACCESS_CTRL_REG,
+ RTL8366S_PHY_CTRL_WRITE))
+ return -1;
+ }
+
+ if (rtl8366_writeRegister(chipData[i][0], chipData[i][1]))
+ return -1;
+
+ i++;
+ }
+
+ /* chip needs some time */
+ udelay(100 * 1000);
+
+ /* restore led config */
+ for (ledGroup = 0; ledGroup < RTL8366S_LED_GROUP_MAX; ledGroup++) {
+ if (rtl8366s_setLedConfig(ledGroup, ledData[ledGroup]))
+ return -1;
+ }
+
+ return 0;
+}
+
+int rtl8366s_initialize(void)
+{
+ uint16_t regData;
+
+ DBG("rtl8366s_initialize: start setup\n");
+
+ smi_init();
+
+ rtl8366_readRegister(RTL8366S_CHIP_ID_REG, &regData);
+ DBG("Realtek 8366SR switch ID %#04x\n", regData);
+
+ if (regData != 0x8366) {
+ printf("rtl8366s_initialize: found unsupported switch\n");
+ return -1;
+ }
+
+ if (rtl8366s_initChip()) {
+ printf("rtl8366s_initialize: init chip failed\n");
+ return -1;
+ }
+
+ if (rtl8366s_setGreenEthernet(1, 1)) {
+ printf("rtl8366s_initialize: set green ethernet failed\n");
+ return -1;
+ }
+
+ /* Set port 5 noTag and don't dropUnda */
+ if (rtl8366s_setCPUPort(5, 1, 0)) {
+ printf("rtl8366s_initialize: set CPU port failed\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/package/uboot-ar71xx/files/drivers/spi/ar71xx_spi.c b/package/uboot-ar71xx/files/drivers/spi/ar71xx_spi.c
new file mode 100644
index 000000000..bbe27b16e
--- /dev/null
+++ b/package/uboot-ar71xx/files/drivers/spi/ar71xx_spi.c
@@ -0,0 +1,191 @@
+/*
+ * (C) Copyright 2010
+ * Michael Kurz <michi.kurz@googlemail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <asm/ar71xx.h>
+
+/*-----------------------------------------------------------------------
+ * Definitions
+ */
+
+#ifdef DEBUG_SPI
+#define PRINTD(fmt,args...) printf (fmt ,##args)
+#else
+#define PRINTD(fmt,args...)
+#endif
+
+struct ar71xx_spi_slave {
+ struct spi_slave slave;
+ unsigned int mode;
+};
+
+static inline struct ar71xx_spi_slave *to_ar71xx_spi(struct spi_slave *slave)
+{
+ return container_of(slave, struct ar71xx_spi_slave, slave);
+}
+
+/*=====================================================================*/
+/* Public Functions */
+/*=====================================================================*/
+
+/*-----------------------------------------------------------------------
+ * Initialization
+ */
+
+void spi_init()
+{
+ PRINTD("ar71xx_spi: spi_init");
+
+ // Init SPI Hardware, disable remap, set clock
+ __raw_writel(0x43, KSEG1ADDR(AR71XX_SPI_BASE + SPI_REG_CTRL));
+
+ PRINTD(" ---> out\n");
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct ar71xx_spi_slave *ss;
+
+ PRINTD("ar71xx_spi: spi_setup_slave");
+
+ if ((bus != 0) || (cs > 2))
+ return NULL;
+
+ ss = malloc(sizeof(struct ar71xx_spi_slave));
+ if (!ss)
+ return NULL;
+
+ ss->slave.bus = bus;
+ ss->slave.cs = cs;
+ ss->mode = mode;
+
+ /* TODO: Use max_hz to limit the SCK rate */
+
+ PRINTD(" ---> out\n");
+
+ return &ss->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct ar71xx_spi_slave *ss = to_ar71xx_spi(slave);
+
+ free(ss);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ struct ar71xx_spi_slave *ss = to_ar71xx_spi(slave);
+ uint8_t *rx = din;
+ const uint8_t *tx = dout;
+ uint8_t curbyte, curbitlen, restbits;
+ uint32_t bytes = bitlen / 8;
+ uint32_t out;
+ uint32_t in;
+
+ PRINTD("ar71xx_spi: spi_xfer: slave:%p bitlen:%08x dout:%p din:%p flags:%08x\n", slave, bitlen, dout, din, flags);
+
+ if (flags & SPI_XFER_BEGIN) {
+ __raw_writel(SPI_FS_GPIO, KSEG1ADDR(AR71XX_SPI_BASE + SPI_REG_FS));
+ __raw_writel(SPI_IOC_CS_ALL, KSEG1ADDR(AR71XX_SPI_BASE + SPI_REG_IOC));
+ }
+
+ restbits = (bitlen % 8);
+ if (restbits != 0)
+ bytes++;
+
+ // enable chip select
+ out = SPI_IOC_CS_ALL & ~(SPI_IOC_CS(slave->cs));
+
+ while (bytes--) {
+
+ curbyte = 0;
+ if (tx) {
+ curbyte = *tx++;
+ }
+
+ if (restbits != 0) {
+ curbitlen = restbits;
+ curbyte <<= 8 - restbits;
+ } else {
+ curbitlen = 8;
+ }
+
+ PRINTD("ar71xx_spi: sending: data:%02x length:%d\n", curbyte, curbitlen);
+
+ /* clock starts at inactive polarity */
+ for (curbyte <<= (8 - curbitlen); curbitlen; curbitlen--) {
+
+ if (curbyte & (1 << 7))
+ out |= SPI_IOC_DO;
+ else
+ out &= ~(SPI_IOC_DO);
+
+ /* setup MSB (to slave) on trailing edge */
+ __raw_writel(out, KSEG1ADDR(AR71XX_SPI_BASE + SPI_REG_IOC));
+
+ __raw_writel(out | SPI_IOC_CLK, KSEG1ADDR(AR71XX_SPI_BASE + SPI_REG_IOC));
+
+ curbyte <<= 1;
+ }
+
+ in = __raw_readl(KSEG1ADDR(AR71XX_SPI_BASE + SPI_REG_RDS));
+ PRINTD("ar71xx_spi: received:%02x\n", in);
+
+ if (rx) {
+ if (restbits == 0) {
+ *rx++ = in;
+ } else {
+ *rx++ = (in << (8 - restbits));
+ }
+ }
+ }
+
+ if (flags & SPI_XFER_END) {
+ __raw_writel(SPI_IOC_CS(slave->cs), KSEG1ADDR(AR71XX_SPI_BASE + SPI_REG_IOC));
+ __raw_writel(SPI_IOC_CS_ALL, KSEG1ADDR(AR71XX_SPI_BASE + SPI_REG_IOC));
+ __raw_writel(0, KSEG1ADDR(AR71XX_SPI_BASE + SPI_REG_FS));
+ }
+
+ PRINTD(" ---> out\n");
+
+ return 0;
+}
diff --git a/package/uboot-ar71xx/files/include/asm-mips/ar71xx.h b/package/uboot-ar71xx/files/include/asm-mips/ar71xx.h
new file mode 100644
index 000000000..e8f3f61d2
--- /dev/null
+++ b/package/uboot-ar71xx/files/include/asm-mips/ar71xx.h
@@ -0,0 +1,515 @@
+/*
+ * Atheros AR71xx SoC specific definitions
+ *
+ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * Parts of this file are based on Atheros' 2.6.15 BSP
+ *
+ * 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.
+ */
+
+#ifndef __ASM_MACH_AR71XX_H
+#define __ASM_MACH_AR71XX_H
+
+#include <linux/types.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+
+#ifndef __ASSEMBLER__
+
+#define BIT(x) (1<<(x))
+
+#define AR71XX_PCI_MEM_BASE 0x10000000
+#define AR71XX_PCI_MEM_SIZE 0x08000000
+#define AR71XX_APB_BASE 0x18000000
+#define AR71XX_GE0_BASE 0x19000000
+#define AR71XX_GE0_SIZE 0x01000000
+#define AR71XX_GE1_BASE 0x1a000000
+#define AR71XX_GE1_SIZE 0x01000000
+#define AR71XX_EHCI_BASE 0x1b000000
+#define AR71XX_EHCI_SIZE 0x01000000
+#define AR71XX_OHCI_BASE 0x1c000000
+#define AR71XX_OHCI_SIZE 0x01000000
+#define AR7240_OHCI_BASE 0x1b000000
+#define AR7240_OHCI_SIZE 0x01000000
+#define AR71XX_SPI_BASE 0x1f000000
+#define AR71XX_SPI_SIZE 0x01000000
+
+#define AR71XX_DDR_CTRL_BASE (AR71XX_APB_BASE + 0x00000000)
+#define AR71XX_DDR_CTRL_SIZE 0x10000
+#define AR71XX_CPU_BASE (AR71XX_APB_BASE + 0x00010000)
+#define AR71XX_UART_BASE (AR71XX_APB_BASE + 0x00020000)
+#define AR71XX_UART_SIZE 0x10000
+#define AR71XX_USB_CTRL_BASE (AR71XX_APB_BASE + 0x00030000)
+#define AR71XX_USB_CTRL_SIZE 0x10000
+#define AR71XX_GPIO_BASE (AR71XX_APB_BASE + 0x00040000)
+#define AR71XX_GPIO_SIZE 0x10000
+#define AR71XX_PLL_BASE (AR71XX_APB_BASE + 0x00050000)
+#define AR71XX_PLL_SIZE 0x10000
+#define AR71XX_RESET_BASE (AR71XX_APB_BASE + 0x00060000)
+#define AR71XX_RESET_SIZE 0x10000
+#define AR71XX_MII_BASE (AR71XX_APB_BASE + 0x00070000)
+#define AR71XX_MII_SIZE 0x10000
+#define AR71XX_SLIC_BASE (AR71XX_APB_BASE + 0x00090000)
+#define AR71XX_SLIC_SIZE 0x10000
+#define AR71XX_DMA_BASE (AR71XX_APB_BASE + 0x000A0000)
+#define AR71XX_DMA_SIZE 0x10000
+#define AR71XX_STEREO_BASE (AR71XX_APB_BASE + 0x000B0000)
+#define AR71XX_STEREO_SIZE 0x10000
+
+#define AR724X_PCI_CRP_BASE (AR71XX_APB_BASE + 0x000C0000)
+#define AR724X_PCI_CRP_SIZE 0x100
+
+#define AR724X_PCI_CTRL_BASE (AR71XX_APB_BASE + 0x000F0000)
+#define AR724X_PCI_CTRL_SIZE 0x100
+
+#define AR91XX_WMAC_BASE (AR71XX_APB_BASE + 0x000C0000)
+#define AR91XX_WMAC_SIZE 0x30000
+
+#define AR71XX_MEM_SIZE_MIN 0x0200000
+#define AR71XX_MEM_SIZE_MAX 0x10000000
+
+#define AR71XX_CPU_IRQ_BASE 0
+#define AR71XX_MISC_IRQ_BASE 8
+#define AR71XX_MISC_IRQ_COUNT 8
+#define AR71XX_GPIO_IRQ_BASE 16
+#define AR71XX_GPIO_IRQ_COUNT 32
+#define AR71XX_PCI_IRQ_BASE 48
+#define AR71XX_PCI_IRQ_COUNT 8
+
+#define AR71XX_CPU_IRQ_IP2 (AR71XX_CPU_IRQ_BASE + 2)
+#define AR71XX_CPU_IRQ_USB (AR71XX_CPU_IRQ_BASE + 3)
+#define AR71XX_CPU_IRQ_GE0 (AR71XX_CPU_IRQ_BASE + 4)
+#define AR71XX_CPU_IRQ_GE1 (AR71XX_CPU_IRQ_BASE + 5)
+#define AR71XX_CPU_IRQ_MISC (AR71XX_CPU_IRQ_BASE + 6)
+#define AR71XX_CPU_IRQ_TIMER (AR71XX_CPU_IRQ_BASE + 7)
+
+#define AR71XX_MISC_IRQ_TIMER (AR71XX_MISC_IRQ_BASE + 0)
+#define AR71XX_MISC_IRQ_ERROR (AR71XX_MISC_IRQ_BASE + 1)
+#define AR71XX_MISC_IRQ_GPIO (AR71XX_MISC_IRQ_BASE + 2)
+#define AR71XX_MISC_IRQ_UART (AR71XX_MISC_IRQ_BASE + 3)
+#define AR71XX_MISC_IRQ_WDOG (AR71XX_MISC_IRQ_BASE + 4)
+#define AR71XX_MISC_IRQ_PERFC (AR71XX_MISC_IRQ_BASE + 5)
+#define AR71XX_MISC_IRQ_OHCI (AR71XX_MISC_IRQ_BASE + 6)
+#define AR71XX_MISC_IRQ_DMA (AR71XX_MISC_IRQ_BASE + 7)
+
+#define AR71XX_GPIO_IRQ(_x) (AR71XX_GPIO_IRQ_BASE + (_x))
+
+#define AR71XX_PCI_IRQ_DEV0 (AR71XX_PCI_IRQ_BASE + 0)
+#define AR71XX_PCI_IRQ_DEV1 (AR71XX_PCI_IRQ_BASE + 1)
+#define AR71XX_PCI_IRQ_DEV2 (AR71XX_PCI_IRQ_BASE + 2)
+#define AR71XX_PCI_IRQ_CORE (AR71XX_PCI_IRQ_BASE + 4)
+
+extern u32 ar71xx_ahb_freq;
+extern u32 ar71xx_cpu_freq;
+extern u32 ar71xx_ddr_freq;
+
+enum ar71xx_soc_type {
+ AR71XX_SOC_UNKNOWN,
+ AR71XX_SOC_AR7130,
+ AR71XX_SOC_AR7141,
+ AR71XX_SOC_AR7161,
+ AR71XX_SOC_AR7240,
+ AR71XX_SOC_AR7241,
+ AR71XX_SOC_AR7242,
+ AR71XX_SOC_AR9130,
+ AR71XX_SOC_AR9132
+};
+
+extern enum ar71xx_soc_type ar71xx_soc;
+
+/*
+ * PLL block
+ */
+#define AR71XX_PLL_REG_CPU_CONFIG 0x00
+#define AR71XX_PLL_REG_SEC_CONFIG 0x04
+#define AR71XX_PLL_REG_ETH0_INT_CLOCK 0x10
+#define AR71XX_PLL_REG_ETH1_INT_CLOCK 0x14
+
+#define AR71XX_PLL_DIV_SHIFT 3
+#define AR71XX_PLL_DIV_MASK 0x1f
+#define AR71XX_CPU_DIV_SHIFT 16
+#define AR71XX_CPU_DIV_MASK 0x3
+#define AR71XX_DDR_DIV_SHIFT 18
+#define AR71XX_DDR_DIV_MASK 0x3
+#define AR71XX_AHB_DIV_SHIFT 20
+#define AR71XX_AHB_DIV_MASK 0x7
+
+#define AR71XX_ETH0_PLL_SHIFT 17
+#define AR71XX_ETH1_PLL_SHIFT 19
+
+#define AR724X_PLL_REG_CPU_CONFIG 0x00
+#define AR724X_PLL_REG_PCIE_CONFIG 0x18
+
+#define AR724X_PLL_DIV_SHIFT 0
+#define AR724X_PLL_DIV_MASK 0x3ff
+#define AR724X_PLL_REF_DIV_SHIFT 10
+#define AR724X_PLL_REF_DIV_MASK 0xf
+#define AR724X_AHB_DIV_SHIFT 19
+#define AR724X_AHB_DIV_MASK 0x1
+#define AR724X_DDR_DIV_SHIFT 22
+#define AR724X_DDR_DIV_MASK 0x3
+
+#define AR91XX_PLL_REG_CPU_CONFIG 0x00
+#define AR91XX_PLL_REG_ETH_CONFIG 0x04
+#define AR91XX_PLL_REG_ETH0_INT_CLOCK 0x14
+#define AR91XX_PLL_REG_ETH1_INT_CLOCK 0x18
+
+#define AR91XX_PLL_DIV_SHIFT 0
+#define AR91XX_PLL_DIV_MASK 0x3ff
+#define AR91XX_DDR_DIV_SHIFT 22
+#define AR91XX_DDR_DIV_MASK 0x3
+#define AR91XX_AHB_DIV_SHIFT 19
+#define AR91XX_AHB_DIV_MASK 0x1
+
+#define AR91XX_ETH0_PLL_SHIFT 20
+#define AR91XX_ETH1_PLL_SHIFT 22
+
+// extern void __iomem *ar71xx_pll_base;
+
+// static inline void ar71xx_pll_wr(unsigned reg, u32 val)
+// {
+ // __raw_writel(val, ar71xx_pll_base + reg);
+// }
+
+// static inline u32 ar71xx_pll_rr(unsigned reg)
+// {
+ // return __raw_readl(ar71xx_pll_base + reg);
+// }
+
+/*
+ * USB_CONFIG block
+ */
+#define USB_CTRL_REG_FLADJ 0x00
+#define USB_CTRL_REG_CONFIG 0x04
+
+// extern void __iomem *ar71xx_usb_ctrl_base;
+
+// static inline void ar71xx_usb_ctrl_wr(unsigned reg, u32 val)
+// {
+ // __raw_writel(val, ar71xx_usb_ctrl_base + reg);
+// }
+
+// static inline u32 ar71xx_usb_ctrl_rr(unsigned reg)
+// {
+ // return __raw_readl(ar71xx_usb_ctrl_base + reg);
+// }
+
+/*
+ * GPIO block
+ */
+#define GPIO_REG_OE 0x00
+#define GPIO_REG_IN 0x04
+#define GPIO_REG_OUT 0x08
+#define GPIO_REG_SET 0x0c
+#define GPIO_REG_CLEAR 0x10
+#define GPIO_REG_INT_MODE 0x14
+#define GPIO_REG_INT_TYPE 0x18
+#define GPIO_REG_INT_POLARITY 0x1c
+#define GPIO_REG_INT_PENDING 0x20
+#define GPIO_REG_INT_ENABLE 0x24
+#define GPIO_REG_FUNC 0x28
+
+#define AR71XX_GPIO_FUNC_STEREO_EN BIT(17)
+#define AR71XX_GPIO_FUNC_SLIC_EN BIT(16)
+#define AR71XX_GPIO_FUNC_SPI_CS2_EN BIT(13)
+#define AR71XX_GPIO_FUNC_SPI_CS1_EN BIT(12)
+#define AR71XX_GPIO_FUNC_UART_EN BIT(8)
+#define AR71XX_GPIO_FUNC_USB_OC_EN BIT(4)
+#define AR71XX_GPIO_FUNC_USB_CLK_EN BIT(0)
+
+#define AR71XX_GPIO_COUNT 16
+
+#define AR724X_GPIO_FUNC_GE0_MII_CLK_EN BIT(19)
+#define AR724X_GPIO_FUNC_SPI_EN BIT(18)
+#define AR724X_GPIO_FUNC_SPI_CS_EN2 BIT(14)
+#define AR724X_GPIO_FUNC_SPI_CS_EN1 BIT(13)
+#define AR724X_GPIO_FUNC_CLK_OBS5_EN BIT(12)
+#define AR724X_GPIO_FUNC_CLK_OBS4_EN BIT(11)
+#define AR724X_GPIO_FUNC_CLK_OBS3_EN BIT(10)
+#define AR724X_GPIO_FUNC_CLK_OBS2_EN BIT(9)
+#define AR724X_GPIO_FUNC_CLK_OBS1_EN BIT(8)
+#define AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN BIT(7)
+#define AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN BIT(6)
+#define AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN BIT(5)
+#define AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN BIT(4)
+#define AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN BIT(3)
+#define AR724X_GPIO_FUNC_UART_RTS_CTS_EN BIT(2)
+#define AR724X_GPIO_FUNC_UART_EN BIT(1)
+#define AR724X_GPIO_FUNC_JTAG_DISABLE BIT(0)
+
+#define AR724X_GPIO_COUNT 18
+
+#define AR91XX_GPIO_FUNC_WMAC_LED_EN BIT(22)
+#define AR91XX_GPIO_FUNC_EXP_PORT_CS_EN BIT(21)
+#define AR91XX_GPIO_FUNC_I2S_REFCLKEN BIT(20)
+#define AR91XX_GPIO_FUNC_I2S_MCKEN BIT(19)
+#define AR91XX_GPIO_FUNC_I2S1_EN BIT(18)
+#define AR91XX_GPIO_FUNC_I2S0_EN BIT(17)
+#define AR91XX_GPIO_FUNC_SLIC_EN BIT(16)
+#define AR91XX_GPIO_FUNC_UART_RTSCTS_EN BIT(9)
+#define AR91XX_GPIO_FUNC_UART_EN BIT(8)
+#define AR91XX_GPIO_FUNC_USB_CLK_EN BIT(4)
+
+#define AR91XX_GPIO_COUNT 22
+
+// extern void __iomem *ar71xx_gpio_base;
+
+// static inline void ar71xx_gpio_wr(unsigned reg, u32 value)
+// {
+ // __raw_writel(value, ar71xx_gpio_base + reg);
+// }
+
+// static inline u32 ar71xx_gpio_rr(unsigned reg)
+// {
+ // return __raw_readl(ar71xx_gpio_base + reg);
+// }
+
+// void ar71xx_gpio_init(void) __init;
+// void ar71xx_gpio_function_enable(u32 mask);
+// void ar71xx_gpio_function_disable(u32 mask);
+// void ar71xx_gpio_function_setup(u32 set, u32 clear);
+
+/*
+ * DDR_CTRL block
+ */
+#define AR71XX_DDR_REG_PCI_WIN0 0x7c
+#define AR71XX_DDR_REG_PCI_WIN1 0x80
+#define AR71XX_DDR_REG_PCI_WIN2 0x84
+#define AR71XX_DDR_REG_PCI_WIN3 0x88
+#define AR71XX_DDR_REG_PCI_WIN4 0x8c
+#define AR71XX_DDR_REG_PCI_WIN5 0x90
+#define AR71XX_DDR_REG_PCI_WIN6 0x94
+#define AR71XX_DDR_REG_PCI_WIN7 0x98
+#define AR71XX_DDR_REG_FLUSH_GE0 0x9c
+#define AR71XX_DDR_REG_FLUSH_GE1 0xa0
+#define AR71XX_DDR_REG_FLUSH_USB 0xa4
+#define AR71XX_DDR_REG_FLUSH_PCI 0xa8
+
+#define AR724X_DDR_REG_FLUSH_GE0 0x7c
+#define AR724X_DDR_REG_FLUSH_GE1 0x80
+#define AR724X_DDR_REG_FLUSH_USB 0x84
+#define AR724X_DDR_REG_FLUSH_PCIE 0x88
+
+#define AR91XX_DDR_REG_FLUSH_GE0 0x7c
+#define AR91XX_DDR_REG_FLUSH_GE1 0x80
+#define AR91XX_DDR_REG_FLUSH_USB 0x84
+#define AR91XX_DDR_REG_FLUSH_WMAC 0x88
+
+#define PCI_WIN0_OFFS 0x10000000
+#define PCI_WIN1_OFFS 0x11000000
+#define PCI_WIN2_OFFS 0x12000000
+#define PCI_WIN3_OFFS 0x13000000
+#define PCI_WIN4_OFFS 0x14000000
+#define PCI_WIN5_OFFS 0x15000000
+#define PCI_WIN6_OFFS 0x16000000
+#define PCI_WIN7_OFFS 0x07000000
+
+// extern void __iomem *ar71xx_ddr_base;
+
+// static inline void ar71xx_ddr_wr(unsigned reg, u32 val)
+// {
+ // __raw_writel(val, ar71xx_ddr_base + reg);
+// }
+
+// static inline u32 ar71xx_ddr_rr(unsigned reg)
+// {
+ // return __raw_readl(ar71xx_ddr_base + reg);
+// }
+
+// void ar71xx_ddr_flush(u32 reg);
+
+/*
+ * PCI block
+ */
+#define AR71XX_PCI_CFG_BASE (AR71XX_PCI_MEM_BASE + PCI_WIN7_OFFS + 0x10000)
+#define AR71XX_PCI_CFG_SIZE 0x100
+
+#define PCI_REG_CRP_AD_CBE 0x00
+#define PCI_REG_CRP_WRDATA 0x04
+#define PCI_REG_CRP_RDDATA 0x08
+#define PCI_REG_CFG_AD 0x0c
+#define PCI_REG_CFG_CBE 0x10
+#define PCI_REG_CFG_WRDATA 0x14
+#define PCI_REG_CFG_RDDATA 0x18
+#define PCI_REG_PCI_ERR 0x1c
+#define PCI_REG_PCI_ERR_ADDR 0x20
+#define PCI_REG_AHB_ERR 0x24
+#define PCI_REG_AHB_ERR_ADDR 0x28
+
+#define PCI_CRP_CMD_WRITE 0x00010000
+#define PCI_CRP_CMD_READ 0x00000000
+#define PCI_CFG_CMD_READ 0x0000000a
+#define PCI_CFG_CMD_WRITE 0x0000000b
+
+#define PCI_IDSEL_ADL_START 17
+
+#define AR724X_PCI_CFG_BASE (AR71XX_PCI_MEM_BASE + 0x4000000)
+#define AR724X_PCI_CFG_SIZE 0x1000
+
+#define AR724X_PCI_REG_APP 0x00
+#define AR724X_PCI_REG_RESET 0x18
+#define AR724X_PCI_REG_INT_STATUS 0x4c
+#define AR724X_PCI_REG_INT_MASK 0x50
+
+#define AR724X_PCI_APP_LTSSM_ENABLE BIT(0)
+#define AR724X_PCI_RESET_LINK_UP BIT(0)
+
+#define AR724X_PCI_INT_DEV0 BIT(14)
+
+/*
+ * RESET block
+ */
+#define AR71XX_RESET_REG_TIMER 0x00
+#define AR71XX_RESET_REG_TIMER_RELOAD 0x04
+#define AR71XX_RESET_REG_WDOG_CTRL 0x08
+#define AR71XX_RESET_REG_WDOG 0x0c
+#define AR71XX_RESET_REG_MISC_INT_STATUS 0x10
+#define AR71XX_RESET_REG_MISC_INT_ENABLE 0x14
+#define AR71XX_RESET_REG_PCI_INT_STATUS 0x18
+#define AR71XX_RESET_REG_PCI_INT_ENABLE 0x1c
+#define AR71XX_RESET_REG_GLOBAL_INT_STATUS 0x20
+#define AR71XX_RESET_REG_RESET_MODULE 0x24
+#define AR71XX_RESET_REG_PERFC_CTRL 0x2c
+#define AR71XX_RESET_REG_PERFC0 0x30
+#define AR71XX_RESET_REG_PERFC1 0x34
+#define AR71XX_RESET_REG_REV_ID 0x90
+
+#define AR91XX_RESET_REG_GLOBAL_INT_STATUS 0x18
+#define AR91XX_RESET_REG_RESET_MODULE 0x1c
+#define AR91XX_RESET_REG_PERF_CTRL 0x20
+#define AR91XX_RESET_REG_PERFC0 0x24
+#define AR91XX_RESET_REG_PERFC1 0x28
+
+#define AR724X_RESET_REG_RESET_MODULE 0x1c
+
+#define WDOG_CTRL_LAST_RESET BIT(31)
+#define WDOG_CTRL_ACTION_MASK 3
+#define WDOG_CTRL_ACTION_NONE 0 /* no action */
+#define WDOG_CTRL_ACTION_GPI 1 /* general purpose interrupt */
+#define WDOG_CTRL_ACTION_NMI 2 /* NMI */
+#define WDOG_CTRL_ACTION_FCR 3 /* full chip reset */
+
+#define MISC_INT_DMA BIT(7)
+#define MISC_INT_OHCI BIT(6)
+#define MISC_INT_PERFC BIT(5)
+#define MISC_INT_WDOG BIT(4)
+#define MISC_INT_UART BIT(3)
+#define MISC_INT_GPIO BIT(2)
+#define MISC_INT_ERROR BIT(1)
+#define MISC_INT_TIMER BIT(0)
+
+#define PCI_INT_CORE BIT(4)
+#define PCI_INT_DEV2 BIT(2)
+#define PCI_INT_DEV1 BIT(1)
+#define PCI_INT_DEV0 BIT(0)
+
+#define RESET_MODULE_EXTERNAL BIT(28)
+#define RESET_MODULE_FULL_CHIP BIT(24)
+#define RESET_MODULE_AMBA2WMAC BIT(22)
+#define RESET_MODULE_CPU_NMI BIT(21)
+#define RESET_MODULE_CPU_COLD BIT(20)
+#define RESET_MODULE_DMA BIT(19)
+#define RESET_MODULE_SLIC BIT(18)
+#define RESET_MODULE_STEREO BIT(17)
+#define RESET_MODULE_DDR BIT(16)
+#define RESET_MODULE_GE1_MAC BIT(13)
+#define RESET_MODULE_GE1_PHY BIT(12)
+#define RESET_MODULE_USBSUS_OVERRIDE BIT(10)
+#define RESET_MODULE_GE0_MAC BIT(9)
+#define RESET_MODULE_GE0_PHY BIT(8)
+#define RESET_MODULE_USB_OHCI_DLL BIT(6)
+#define RESET_MODULE_USB_HOST BIT(5)
+#define RESET_MODULE_USB_PHY BIT(4)
+#define RESET_MODULE_USB_OHCI_DLL_7240 BIT(3)
+#define RESET_MODULE_PCI_BUS BIT(1)
+#define RESET_MODULE_PCI_CORE BIT(0)
+
+#define AR724X_RESET_GE1_MDIO BIT(23)
+#define AR724X_RESET_GE0_MDIO BIT(22)
+#define AR724X_RESET_PCIE_PHY_SERIAL BIT(10)
+#define AR724X_RESET_PCIE_PHY BIT(7)
+#define AR724X_RESET_PCIE BIT(6)
+
+#define REV_ID_MAJOR_MASK 0xfff0
+#define REV_ID_MAJOR_AR71XX 0x00a0
+#define REV_ID_MAJOR_AR913X 0x00b0
+#define REV_ID_MAJOR_AR7240 0x00c0
+#define REV_ID_MAJOR_AR7241 0x0100
+#define REV_ID_MAJOR_AR7242 0x1100
+
+#define AR71XX_REV_ID_MINOR_MASK 0x3
+#define AR71XX_REV_ID_MINOR_AR7130 0x0
+#define AR71XX_REV_ID_MINOR_AR7141 0x1
+#define AR71XX_REV_ID_MINOR_AR7161 0x2
+#define AR71XX_REV_ID_REVISION_MASK 0x3
+#define AR71XX_REV_ID_REVISION_SHIFT 2
+
+#define AR91XX_REV_ID_MINOR_MASK 0x3
+#define AR91XX_REV_ID_MINOR_AR9130 0x0
+#define AR91XX_REV_ID_MINOR_AR9132 0x1
+#define AR91XX_REV_ID_REVISION_MASK 0x3
+#define AR91XX_REV_ID_REVISION_SHIFT 2
+
+#define AR724X_REV_ID_REVISION_MASK 0x3
+
+// extern void __iomem *ar71xx_reset_base;
+
+static inline void ar71xx_reset_wr(unsigned reg, u32 val)
+{
+ __raw_writel(val, KSEG1ADDR(AR71XX_RESET_BASE) + reg);
+}
+
+static inline u32 ar71xx_reset_rr(unsigned reg)
+{
+ return __raw_readl(KSEG1ADDR(AR71XX_RESET_BASE) + reg);
+}
+
+// void ar71xx_device_stop(u32 mask);
+// void ar71xx_device_start(u32 mask);
+// int ar71xx_device_stopped(u32 mask);
+
+/*
+ * SPI block
+ */
+#define SPI_REG_FS 0x00 /* Function Select */
+#define SPI_REG_CTRL 0x04 /* SPI Control */
+#define SPI_REG_IOC 0x08 /* SPI I/O Control */
+#define SPI_REG_RDS 0x0c /* Read Data Shift */
+
+#define SPI_FS_GPIO BIT(0) /* Enable GPIO mode */
+
+#define SPI_CTRL_RD BIT(6) /* Remap Disable */
+#define SPI_CTRL_DIV_MASK 0x3f
+
+#define SPI_IOC_DO BIT(0) /* Data Out pin */
+#define SPI_IOC_CLK BIT(8) /* CLK pin */
+#define SPI_IOC_CS(n) BIT(16 + (n))
+#define SPI_IOC_CS0 SPI_IOC_CS(0)
+#define SPI_IOC_CS1 SPI_IOC_CS(1)
+#define SPI_IOC_CS2 SPI_IOC_CS(2)
+#define SPI_IOC_CS_ALL (SPI_IOC_CS0 | SPI_IOC_CS1 | SPI_IOC_CS2)
+
+// void ar71xx_flash_acquire(void);
+// void ar71xx_flash_release(void);
+
+/*
+ * MII_CTRL block
+ */
+#define MII_REG_MII0_CTRL 0x00
+#define MII_REG_MII1_CTRL 0x04
+
+#define MII0_CTRL_IF_GMII 0
+#define MII0_CTRL_IF_MII 1
+#define MII0_CTRL_IF_RGMII 2
+#define MII0_CTRL_IF_RMII 3
+
+#define MII1_CTRL_IF_RGMII 0
+#define MII1_CTRL_IF_RMII 1
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __ASM_MACH_AR71XX_H */
diff --git a/package/uboot-ar71xx/files/include/asm-mips/ar71xx_gpio.h b/package/uboot-ar71xx/files/include/asm-mips/ar71xx_gpio.h
new file mode 100644
index 000000000..c92364b88
--- /dev/null
+++ b/package/uboot-ar71xx/files/include/asm-mips/ar71xx_gpio.h
@@ -0,0 +1,65 @@
+/*
+ * (C) Copyright 2010
+ * Michael Kurz <michi.kurz@googlemail.com>.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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 _AR71XX_GPIO_H
+#define _AR71XX_GPIO_H
+
+#include <common.h>
+#include <asm/ar71xx.h>
+
+static inline void ar71xx_setpin(uint8_t pin, uint8_t state)
+{
+ uint32_t reg = readl(KSEG1ADDR(AR71XX_GPIO_BASE + GPIO_REG_OUT));
+
+ if (state != 0) {
+ reg |= (1 << pin);
+ } else {
+ reg &= ~(1 << pin);
+ }
+
+ writel(reg, KSEG1ADDR(AR71XX_GPIO_BASE + GPIO_REG_OUT));
+ readl(KSEG1ADDR(AR71XX_GPIO_BASE + GPIO_REG_OUT));
+}
+
+static inline uint32_t ar71xx_getpin(uint8_t pin)
+{
+ uint32_t reg = readl(KSEG1ADDR(AR71XX_GPIO_BASE + GPIO_REG_IN));
+ return (((reg & (1 << pin)) != 0) ? 1 : 0);
+}
+
+static inline void ar71xx_setpindir(uint8_t pin, uint8_t direction)
+{
+ uint32_t reg = readl(KSEG1ADDR(AR71XX_GPIO_BASE + GPIO_REG_OE));
+
+ if (direction != 0) {
+ reg |= (1 << pin);
+ } else {
+ reg &= ~(1 << pin);
+ }
+
+ writel(reg, KSEG1ADDR(AR71XX_GPIO_BASE + GPIO_REG_OE));
+ readl(KSEG1ADDR(AR71XX_GPIO_BASE + GPIO_REG_OE));
+}
+
+
+#endif /* AR71XX_GPIO_H */
diff --git a/package/uboot-ar71xx/files/include/configs/nbg460n.h b/package/uboot-ar71xx/files/include/configs/nbg460n.h
new file mode 100644
index 000000000..dd9b4c38a
--- /dev/null
+++ b/package/uboot-ar71xx/files/include/configs/nbg460n.h
@@ -0,0 +1,136 @@
+/*
+ * (C) Copyright 2010
+ * Michael Kurz <michi.kurz@googlemail.com>.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+/* This file contains the configuration parameters for the zyxel nbg460n board. */
+
+#ifndef _NBG460N_CONFIG_H
+#define _NBG460N_CONFIG_H
+
+#define CONFIG_MIPS32 1 /* MIPS32 CPU core */
+#define CONFIG_AR71XX 1
+#define CONFIG_AR91XX 1
+#define CONFIG_SYS_HZ 1000
+#define CONFIG_SYS_MIPS_TIMER_FREQ (400000000/2)
+
+/* Cache Configuration */
+#define CONFIG_SYS_DCACHE_SIZE 32768
+#define CONFIG_SYS_ICACHE_SIZE 65536
+#define CONFIG_SYS_CACHELINE_SIZE 32
+/* Cache lock for stack */
+#define CONFIG_SYS_INIT_SP_OFFSET 0x1000
+
+#define CONFIG_SYS_MONITOR_BASE (TEXT_BASE)
+
+#define CONFIG_BAUDRATE 115200
+#define CONFIG_SYS_BAUDRATE_TABLE {115200}
+
+#define CONFIG_MISC_INIT_R
+
+/* SPI-Flash support */
+#define CONFIG_SPI_FLASH
+#define CONFIG_AR71XX_SPI
+#define CONFIG_SPI_FLASH_MACRONIX
+#define CONFIG_SF_DEFAULT_HZ 25000000
+
+#define CONFIG_ENV_SPI_MAX_HZ 25000000
+#define CONFIG_ENV_SPI_BUS 0
+#define CONFIG_ENV_SPI_CS 0
+
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_ADDR 0xbfc20000
+#define CONFIG_ENV_OFFSET 0x20000
+#define CONFIG_ENV_SIZE 0x01000
+#define CONFIG_ENV_SECT_SIZE 0x10000
+#define CONFIG_SYS_MAX_FLASH_BANKS 1
+#define CONFIG_SYS_MAX_FLASH_SECT 64
+#define CONFIG_SYS_FLASH_BASE 0xbfc00000
+
+/* Net support */
+#define CONFIG_ETHADDR_ADDR 0xbfc0fff8
+#define CONFIG_SYS_RX_ETH_BUFFER 16
+#define CONFIG_AG71XX
+#define CONFIG_AG71XX_PORTS { 1, 1 }
+#define CONFIG_AG71XX_MII0_IIF MII0_CTRL_IF_RGMII
+#define CONFIG_AG71XX_MII1_IIF MII1_CTRL_IF_RGMII
+#define CONFIG_NET_MULTI
+#define CONFIG_IPADDR 192.168.1.254
+#define CONFIG_SERVERIP 192.168.1.42
+
+/* Switch support */
+#define CONFIG_MII
+#define CONFIG_RTL8366_MII
+#define RTL8366_PIN_SDA 16
+#define RTL8366_PIN_SCK 18
+#define MII_GPIOINCLUDE <asm/ar71xx_gpio.h>
+#define MII_SETSDA(x) ar71xx_setpin(RTL8366_PIN_SDA, x)
+#define MII_GETSDA ar71xx_getpin(RTL8366_PIN_SDA)
+#define MII_SETSCK(x) ar71xx_setpin(RTL8366_PIN_SCK, x)
+#define MII_SDAINPUT ar71xx_setpindir(RTL8366_PIN_SDA, 0)
+#define MII_SDAOUTPUT ar71xx_setpindir(RTL8366_PIN_SDA, 1)
+#define MII_SCKINPUT ar71xx_setpindir(RTL8366_PIN_SCK, 0)
+#define MII_SCKOUTPUT ar71xx_setpindir(RTL8366_PIN_SCK, 1)
+
+#define CONFIG_BOOTDELAY 3
+#define CONFIG_BOOTARGS "console=ttyS0,115200 rootfstype==squashfs,jffs2 noinitrd machtype=NBG460N"
+#define CONFIG_BOOTCOMMAND "bootm 0xbfc70000"
+#define CONFIG_LZMA
+
+
+/* Commands */
+#define CONFIG_SYS_NO_FLASH
+#include <config_cmd_default.h>
+#undef CONFIG_CMD_BDI
+#undef CONFIG_CMD_FPGA
+#undef CONFIG_CMD_IMI
+#undef CONFIG_CMD_IMLS
+#undef CONFIG_CMD_LOADS
+#define CONFIG_CMD_SF
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_SPI
+
+/* Miscellaneous configurable options */
+#define CONFIG_SYS_PROMPT "U-Boot> "
+#define CONFIG_SYS_CBSIZE 256
+#define CONFIG_SYS_MAXARGS 16
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_LONGHELP 1
+#define CONFIG_CMDLINE_EDITING 1
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_SYS_HUSH_PARSER
+#define CONFIG_SYS_PROMPT_HUSH_PS2 "> "
+
+/* Size of malloc() pool */
+#define CONFIG_SYS_MALLOC_LEN ROUND(3 * 0x10000 + 128*1024, 0x1000)
+#define CONFIG_SYS_GBL_DATA_SIZE 128 /* 128 bytes for initial data */
+
+#define CONFIG_SYS_BOOTPARAMS_LEN 128*1024
+
+#define CONFIG_SYS_SDRAM_BASE 0x80000000 /* Cached addr */
+#define CONFIG_SYS_LOAD_ADDR 0x80060000 /* default load address */
+
+#define CONFIG_SYS_MEMTEST_START 0x80000800
+#define CONFIG_SYS_MEMTEST_END 0x81E00000
+
+#endif /* _NBG460N_CONFIG_H */
diff --git a/package/uboot-ar71xx/patches/001-ar71xx.patch b/package/uboot-ar71xx/patches/001-ar71xx.patch
new file mode 100644
index 000000000..409f67a57
--- /dev/null
+++ b/package/uboot-ar71xx/patches/001-ar71xx.patch
@@ -0,0 +1,28 @@
+diff -ur u-boot-2010.03/cpu/mips/Makefile u-boot-nbg/cpu/mips/Makefile
+--- u-boot-2010.03/cpu/mips/Makefile 2010-03-31 23:54:39.000000000 +0200
++++ u-boot-nbg/cpu/mips/Makefile 2010-04-15 18:58:01.000000000 +0200
+@@ -33,6 +33,7 @@
+ COBJS-$(CONFIG_INCA_IP) += asc_serial.o incaip_clock.o
+ COBJS-$(CONFIG_PURPLE) += asc_serial.o
+ COBJS-$(CONFIG_SOC_AU1X00) += au1x00_eth.o au1x00_serial.o au1x00_usb_ohci.o
++COBJS-$(CONFIG_AR71XX) += ar71xx_serial.o
+
+ SRCS := $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+ OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+diff -ur u-boot-2010.03/Makefile u-boot-nbg/Makefile
+--- u-boot-2010.03/Makefile 2010-03-31 23:54:39.000000000 +0200
++++ u-boot-nbg/Makefile 2010-04-11 23:31:29.000000000 +0200
+@@ -3455,6 +3455,13 @@
+ @$(MKCONFIG) -a qemu-mips mips mips qemu-mips
+
+ #########################################################################
++## MIPS32 AR71XX (24K)
++#########################################################################
++
++nbg460n_550n_550nh_config : unconfig
++ @$(MKCONFIG) -a nbg460n mips mips nbg460n zyxel
++
++#########################################################################
+ ## MIPS64 5Kc
+ #########################################################################
+
diff --git a/package/uboot-ar71xx/patches/002-ar71xx-spi.patch b/package/uboot-ar71xx/patches/002-ar71xx-spi.patch
new file mode 100644
index 000000000..2bb1ba221
--- /dev/null
+++ b/package/uboot-ar71xx/patches/002-ar71xx-spi.patch
@@ -0,0 +1,11 @@
+diff -ur u-boot-2010.03/drivers/spi/Makefile u-boot-nbg/drivers/spi/Makefile
+--- u-boot-2010.03/drivers/spi/Makefile 2010-03-31 23:54:39.000000000 +0200
++++ u-boot-nbg/drivers/spi/Makefile 2010-04-15 19:31:27.000000000 +0200
+@@ -25,6 +25,7 @@
+
+ LIB := $(obj)libspi.a
+
++COBJS-$(CONFIG_AR71XX_SPI) += ar71xx_spi.o
+ COBJS-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
+ COBJS-$(CONFIG_ATMEL_SPI) += atmel_spi.o
+ COBJS-$(CONFIG_BFIN_SPI) += bfin_spi.o
diff --git a/package/uboot-ar71xx/patches/010-enet-ag71xx.patch b/package/uboot-ar71xx/patches/010-enet-ag71xx.patch
new file mode 100644
index 000000000..ee90e32c7
--- /dev/null
+++ b/package/uboot-ar71xx/patches/010-enet-ag71xx.patch
@@ -0,0 +1,22 @@
+diff -ur u-boot-2010.03/drivers/net/Makefile u-boot-nbg/drivers/net/Makefile
+--- u-boot-2010.03/drivers/net/Makefile 2010-03-31 23:54:39.000000000 +0200
++++ u-boot-nbg/drivers/net/Makefile 2010-04-19 23:30:01.000000000 +0200
+@@ -27,6 +27,7 @@
+
+ COBJS-$(CONFIG_DRIVER_3C589) += 3c589.o
+ COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o
++COBJS-$(CONFIG_AG71XX) += ag71xx.o
+ COBJS-$(CONFIG_DRIVER_AT91EMAC) += at91_emac.o
+ COBJS-$(CONFIG_DRIVER_AX88180) += ax88180.o
+ COBJS-$(CONFIG_BCM570x) += bcm570x.o bcm570x_autoneg.o 5701rls.o
+diff -ur u-boot-2010.03/include/netdev.h u-boot-nbg/include/netdev.h
+--- u-boot-2010.03/include/netdev.h 2010-03-31 23:54:39.000000000 +0200
++++ u-boot-nbg/include/netdev.h 2010-05-02 11:30:58.000000000 +0200
+@@ -42,6 +42,7 @@
+
+ /* Driver initialization prototypes */
+ int au1x00_enet_initialize(bd_t*);
++int ag71xx_register(bd_t * bis, char *phyname[], u16 phyid[], u16 phyfixed[]);
+ int at91emac_register(bd_t *bis, unsigned long iobase);
+ int bfin_EMAC_initialize(bd_t *bis);
+ int cs8900_initialize(u8 dev_num, int base_addr);
diff --git a/package/uboot-ar71xx/patches/011-switch-rtl8366sr.patch b/package/uboot-ar71xx/patches/011-switch-rtl8366sr.patch
new file mode 100644
index 000000000..5d2ba41ea
--- /dev/null
+++ b/package/uboot-ar71xx/patches/011-switch-rtl8366sr.patch
@@ -0,0 +1,28 @@
+diff -ur u-boot-2010.03/drivers/net/Makefile u-boot-nbg/drivers/net/Makefile
+--- u-boot-2010.03/drivers/net/Makefile 2010-03-31 23:54:39.000000000 +0200
++++ u-boot-nbg/drivers/net/Makefile 2010-04-19 23:30:01.000000000 +0200
+@@ -65,6 +65,7 @@
+ COBJS-$(CONFIG_DRIVER_RTL8019) += rtl8019.o
+ COBJS-$(CONFIG_RTL8139) += rtl8139.o
+ COBJS-$(CONFIG_RTL8169) += rtl8169.o
++COBJS-$(CONFIG_RTL8366_MII) += phy/rtl8366_mii.o
+ COBJS-$(CONFIG_DRIVER_S3C4510_ETH) += s3c4510b_eth.o
+ COBJS-$(CONFIG_SH_ETHER) += sh_eth.o
+ COBJS-$(CONFIG_SMC91111) += smc91111.o
+diff -ur u-boot-2010.03/include/netdev.h u-boot-nbg/include/netdev.h
+--- u-boot-2010.03/include/netdev.h 2010-03-31 23:54:39.000000000 +0200
++++ u-boot-nbg/include/netdev.h 2010-05-02 11:30:58.000000000 +0200
+@@ -175,5 +175,13 @@
+
+ int mv88e61xx_switch_initialize(struct mv88e61xx_config *swconfig);
+ #endif /* CONFIG_MV88E61XX_SWITCH */
++
++#if defined(CONFIG_RTL8366_MII)
++#define RTL8366_DEVNAME "rtl8366"
++#define RTL8366_WANPHY_ID 4
++#define RTL8366_LANPHY_ID -1
++int rtl8366_mii_register(bd_t *bis);
++int rtl8366s_initialize(void);
++#endif
+
+ #endif /* _NETDEV_H_ */
diff --git a/package/uboot-ar71xx/patches/020-freebsd-compat.patch b/package/uboot-ar71xx/patches/020-freebsd-compat.patch
new file mode 100644
index 000000000..fee06699c
--- /dev/null
+++ b/package/uboot-ar71xx/patches/020-freebsd-compat.patch
@@ -0,0 +1,11 @@
+--- a/include/compiler.h
++++ b/include/compiler.h
+@@ -46,7 +46,7 @@ extern int errno;
+ #ifdef __linux__
+ # include <endian.h>
+ # include <byteswap.h>
+-#elif defined(__MACH__)
++#elif defined(__MACH__) || defined(__FreeBSD__)
+ # include <machine/endian.h>
+ typedef unsigned long ulong;
+ typedef unsigned int uint;
diff --git a/package/uboot-ar71xx/patches/021-darwin_compat.patch b/package/uboot-ar71xx/patches/021-darwin_compat.patch
new file mode 100644
index 000000000..dde83d490
--- /dev/null
+++ b/package/uboot-ar71xx/patches/021-darwin_compat.patch
@@ -0,0 +1,23 @@
+--- a/config.mk
++++ b/config.mk
+@@ -64,9 +64,17 @@ HOSTSTRIP = strip
+ #
+
+ ifeq ($(HOSTOS),darwin)
+-HOSTCC = cc
+-HOSTCFLAGS += -traditional-cpp
+-HOSTLDFLAGS += -multiply_defined suppress
++#get the major and minor product version (e.g. '10' and '6' for Snow Leopard)
++DARWIN_MAJOR_VERSION = $(shell sw_vers -productVersion | cut -f 1 -d '.')
++DARWIN_MINOR_VERSION = $(shell sw_vers -productVersion | cut -f 2 -d '.')
++
++before-snow-leopard = $(shell if [ $(DARWIN_MAJOR_VERSION) -le 10 -a \
++ $(DARWIN_MINOR_VERSION) -le 5 ] ; then echo "$(1)"; else echo "$(2)"; fi ;)
++
++# Snow Leopards build environment has no longer restrictions as described above
++HOSTCC = $(call before-snow-leopard, "cc", "gcc")
++HOSTCFLAGS += $(call before-snow-leopard, "-traditional-cpp")
++HOSTLDFLAGS += $(call before-snow-leopard, "-multiply_defined suppress")
+ else
+ HOSTCC = gcc
+ endif
diff --git a/package/uboot-ar71xx/patches/022-getline_backport.patch b/package/uboot-ar71xx/patches/022-getline_backport.patch
new file mode 100644
index 000000000..2ce2b614b
--- /dev/null
+++ b/package/uboot-ar71xx/patches/022-getline_backport.patch
@@ -0,0 +1,21 @@
+--- a/tools/os_support.c
++++ b/tools/os_support.c
+@@ -23,6 +23,6 @@
+ #ifdef __MINGW32__
+ #include "mingw_support.c"
+ #endif
+-#ifdef __APPLE__
++#if defined(__APPLE__) && __DARWIN_C_LEVEL < 200809L
+ #include "getline.c"
+ #endif
+--- a/tools/os_support.h
++++ b/tools/os_support.h
+@@ -28,7 +28,7 @@
+ #include "mingw_support.h"
+ #endif
+
+-#ifdef __APPLE__
++#if defined(__APPLE__) && __DARWIN_C_LEVEL < 200809L
+ #include "getline.h"
+ #endif
+
diff --git a/package/uboot-envtools/Makefile b/package/uboot-envtools/Makefile
new file mode 100644
index 000000000..74da5ea12
--- /dev/null
+++ b/package/uboot-envtools/Makefile
@@ -0,0 +1,70 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=uboot-envtools
+PKG_DISTNAME:=u-boot
+PKG_VERSION:=2012.04.01
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_DISTNAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=ftp://ftp.denx.de/pub/u-boot
+PKG_MD5SUM:=192bb231082d9159fb6e16de3039b6b2
+PKG_BUILD_DEPENDS:=zlib
+
+include $(INCLUDE_DIR)/package.mk
+
+TAR_OPTIONS+= --strip-components=3 -C $(PKG_BUILD_DIR) $(PKG_DISTNAME)-$(PKG_VERSION)/tools/env
+
+define Package/uboot-envtools
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=read/modify U-Boot bootloader environment
+ URL:=http://www.denx.de/wiki/U-Boot
+endef
+
+define Package/uboot-envtools/description
+ This package includes tools to read and modify U-Boot bootloader environment.
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ tar xvjf $(DL_DIR)/$(PKG_SOURCE) --strip-components=2 -C $(PKG_BUILD_DIR) $(PKG_DISTNAME)-$(PKG_VERSION)/lib/crc32.c
+ $(call Build/Prepare/Default)
+endef
+
+define Package/uboot-envtools/conffiles
+/etc/config/ubootenv
+/etc/fw_env.config
+endef
+
+define Package/uboot-envtools/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/fw_printenv $(1)/usr/sbin
+ ln -s fw_printenv $(1)/usr/sbin/fw_setenv
+ $(INSTALL_DIR) $(1)/lib
+ $(INSTALL_DATA) ./files/uboot-envtools.sh $(1)/lib
+ifneq ($(CONFIG_TARGET_ar71xx),)
+ $(INSTALL_DIR) $(1)/etc/uci-defaults
+ $(INSTALL_BIN) ./files/ar71xx $(1)/etc/uci-defaults/uboot-envtools
+endif
+ifneq ($(CONFIG_TARGET_kirkwood),)
+ $(INSTALL_DIR) $(1)/etc/uci-defaults
+ $(INSTALL_BIN) ./files/kirkwood $(1)/etc/uci-defaults/uboot-envtools
+endif
+ifneq ($(CONFIG_TARGET_lantiq),)
+ $(INSTALL_DIR) $(1)/etc/uci-defaults
+ $(INSTALL_BIN) ./files/lantiq $(1)/etc/uci-defaults/uboot-envtools
+endif
+ifneq ($(CONFIG_TARGET_ramips),)
+ $(INSTALL_DIR) $(1)/etc/uci-defaults
+ $(INSTALL_BIN) ./files/ramips $(1)/etc/uci-defaults/uboot-envtools
+endif
+endef
+
+$(eval $(call BuildPackage,uboot-envtools))
diff --git a/package/uboot-envtools/files/ar71xx b/package/uboot-envtools/files/ar71xx
new file mode 100644
index 000000000..ad0d921a5
--- /dev/null
+++ b/package/uboot-envtools/files/ar71xx
@@ -0,0 +1,31 @@
+#!/bin/sh
+#
+# Copyright (C) 2011-2012 OpenWrt.org
+#
+
+[ -e /etc/config/ubootenv ] && exit 0
+
+touch /etc/config/ubootenv
+
+. /lib/ar71xx.sh
+. /lib/uboot-envtools.sh
+. /lib/functions.sh
+
+board=$(ar71xx_board_name)
+
+case "$board" in
+all0258n)
+ ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x10000" "0x10000"
+ ;;
+alfa-ap96 | \
+all0315n | \
+om2p | \
+om2p-lc)
+ ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x40000" "0x40000"
+ ;;
+esac
+
+config_load ubootenv
+config_foreach ubootenv_add_app_config ubootenv
+
+exit 0
diff --git a/package/uboot-envtools/files/kirkwood b/package/uboot-envtools/files/kirkwood
new file mode 100644
index 000000000..cad53aa37
--- /dev/null
+++ b/package/uboot-envtools/files/kirkwood
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright (C) 2012 OpenWrt.org
+#
+
+[ -e /etc/config/ubootenv ] && exit 0
+
+touch /etc/config/ubootenv
+
+. /lib/kirkwood.sh
+. /lib/uboot-envtools.sh
+. /lib/functions.sh
+
+hardware=$(kirkwood_hardware_name)
+
+case "$hardware" in
+"RaidSonic ICY BOX IB-NAS6210")
+ ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x20000" "0x20000"
+ ;;
+esac
+
+config_load ubootenv
+config_foreach ubootenv_add_app_config ubootenv
+
+exit 0
diff --git a/package/uboot-envtools/files/lantiq b/package/uboot-envtools/files/lantiq
new file mode 100644
index 000000000..40befc368
--- /dev/null
+++ b/package/uboot-envtools/files/lantiq
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright (C) 2012 OpenWrt.org
+#
+
+[ -e /etc/config/ubootenv ] && exit 0
+
+touch /etc/config/ubootenv
+
+. /lib/lantiq.sh
+. /lib/uboot-envtools.sh
+. /lib/functions.sh
+
+board=$(lantiq_board_name)
+
+case "$board" in
+GIGASX76X)
+ ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x10000" "0x10000" "1"
+ ;;
+esac
+
+config_load ubootenv
+config_foreach ubootenv_add_app_config ubootenv
+
+exit 0
diff --git a/package/uboot-envtools/files/ramips b/package/uboot-envtools/files/ramips
new file mode 100644
index 000000000..65cd49cf1
--- /dev/null
+++ b/package/uboot-envtools/files/ramips
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+# Copyright (C) 2011-2012 OpenWrt.org
+#
+
+[ -e /etc/config/ubootenv ] && exit 0
+
+touch /etc/config/ubootenv
+
+. /lib/ramips.sh
+. /lib/uboot-envtools.sh
+. /lib/functions.sh
+
+board=$(ramips_board_name)
+
+case "$board" in
+all0239-3g | \
+all0256n | \
+all5002)
+ ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x10000" "0x10000"
+ ;;
+esac
+
+config_load ubootenv
+config_foreach ubootenv_add_app_config ubootenv
+
+exit 0
diff --git a/package/uboot-envtools/files/uboot-envtools.sh b/package/uboot-envtools/files/uboot-envtools.sh
new file mode 100644
index 000000000..e21b28367
--- /dev/null
+++ b/package/uboot-envtools/files/uboot-envtools.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# Copyright (C) 2011-2012 OpenWrt.org
+#
+
+ubootenv_add_uci_config() {
+ local dev=$1
+ local offset=$2
+ local envsize=$3
+ local secsize=$4
+ local numsec=$5
+ uci batch <<EOF
+add ubootenv ubootenv
+set ubootenv.@ubootenv[-1].dev='$dev'
+set ubootenv.@ubootenv[-1].offset='$offset'
+set ubootenv.@ubootenv[-1].envsize='$envsize'
+set ubootenv.@ubootenv[-1].secsize='$secsize'
+set ubootenv.@ubootenv[-1].numsec='$numsec'
+EOF
+ uci commit ubootenv
+}
+
+ubootenv_add_app_config() {
+ local dev
+ local offset
+ local envsize
+ local secsize
+ local numsec
+ config_get dev "$1" dev
+ config_get offset "$1" offset
+ config_get envsize "$1" envsize
+ config_get secsize "$1" secsize
+ config_get numsec "$1" numsec
+ echo "$dev $offset $envsize $secsize $numsec" >>/etc/fw_env.config
+}
+
diff --git a/package/uboot-envtools/patches/001-crc32_func_signature.patch b/package/uboot-envtools/patches/001-crc32_func_signature.patch
new file mode 100644
index 000000000..f68f29ea0
--- /dev/null
+++ b/package/uboot-envtools/patches/001-crc32_func_signature.patch
@@ -0,0 +1,130 @@
+--- a/crc32.c
++++ b/crc32.c
+@@ -8,21 +8,16 @@
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+-#ifndef USE_HOSTCC
+-#include <common.h>
+-#endif
+-#include <compiler.h>
+-#include <u-boot/crc.h>
++#include <stdint.h>
++#include <asm/byteorder.h>
++
++#include "zlib.h"
+
+-#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+-#include <watchdog.h>
+-#endif
+-#include "u-boot/zlib.h"
+
+ #define local static
+ #define ZEXPORT /* empty */
+
+-#define tole(x) cpu_to_le32(x)
++#define tole(x) __constant_cpu_to_le32(x)
+
+ #ifdef DYNAMIC_CRC_TABLE
+
+@@ -151,7 +146,7 @@ tole(0xb40bbe37L), tole(0xc30c8ea1L), to
+
+ #if 0
+ /* =========================================================================
+- * This function can be used by asm versions of crc32()
++ * This function can be used by asm versions of uboot_crc32()
+ */
+ const uint32_t * ZEXPORT get_crc_table()
+ {
+@@ -183,7 +178,7 @@ uint32_t ZEXPORT crc32_no_comp(uint32_t
+ if (crc_table_empty)
+ make_crc_table();
+ #endif
+- crc = cpu_to_le32(crc);
++ crc = __cpu_to_le32(crc);
+ /* Align it */
+ if (((long)b) & 3 && len) {
+ uint8_t *p = (uint8_t *)b;
+@@ -212,11 +207,11 @@ uint32_t ZEXPORT crc32_no_comp(uint32_t
+ } while (--len);
+ }
+
+- return le32_to_cpu(crc);
++ return __le32_to_cpu(crc);
+ }
+ #undef DO_CRC
+
+-uint32_t ZEXPORT crc32 (uint32_t crc, const Bytef *p, uInt len)
++uint32_t ZEXPORT uboot_crc32 (uint32_t crc, const Bytef *p, uInt len)
+ {
+ return crc32_no_comp(crc ^ 0xffffffffL, p, len) ^ 0xffffffffL;
+ }
+@@ -239,12 +234,12 @@ uint32_t ZEXPORT crc32_wd (uint32_t crc,
+ chunk = end - curr;
+ if (chunk > chunk_sz)
+ chunk = chunk_sz;
+- crc = crc32 (crc, curr, chunk);
++ crc = uboot_crc32 (crc, curr, chunk);
+ curr += chunk;
+ WATCHDOG_RESET ();
+ }
+ #else
+- crc = crc32 (crc, buf, len);
++ crc = uboot_crc32 (crc, buf, len);
+ #endif
+
+ return crc;
+--- a/fw_env.c
++++ b/fw_env.c
+@@ -34,6 +34,7 @@
+ #include <sys/ioctl.h>
+ #include <sys/stat.h>
+ #include <unistd.h>
++#include <zlib.h>
+
+ #ifdef MTD_OLD
+ # include <stdint.h>
+@@ -212,13 +213,14 @@ static char default_environment[] = {
+ static int flash_io (int mode);
+ static char *envmatch (char * s1, char * s2);
+ static int parse_config (void);
++uint32_t uboot_crc32 (uint32_t crc, const Bytef *p, uInt len);
+
+ #if defined(CONFIG_FILE)
+ static int get_config (char *);
+ #endif
+-static inline ulong getenvsize (void)
++static inline uint32_t getenvsize (void)
+ {
+- ulong rc = CONFIG_ENV_SIZE - sizeof (long);
++ uint32_t rc = CONFIG_ENV_SIZE - sizeof (uint32_t);
+
+ if (HaveRedundEnv)
+ rc -= sizeof (char);
+@@ -348,7 +350,7 @@ int fw_env_close(void)
+ /*
+ * Update CRC
+ */
+- *environment.crc = crc32(0, (uint8_t *) environment.data, ENV_SIZE);
++ *environment.crc = uboot_crc32(0, (uint8_t *) environment.data, ENV_SIZE);
+
+ /* write environment back to flash */
+ if (flash_io(O_RDWR)) {
+@@ -1116,7 +1118,7 @@ int fw_env_open(void)
+ if (flash_io (O_RDONLY))
+ return -1;
+
+- crc0 = crc32 (0, (uint8_t *) environment.data, ENV_SIZE);
++ crc0 = uboot_crc32 (0, (uint8_t *) environment.data, ENV_SIZE);
+ crc0_ok = (crc0 == *environment.crc);
+ if (!HaveRedundEnv) {
+ if (!crc0_ok) {
+@@ -1160,7 +1162,7 @@ int fw_env_open(void)
+ return -1;
+ }
+
+- crc1 = crc32 (0, (uint8_t *) redundant->data, ENV_SIZE);
++ crc1 = uboot_crc32 (0, (uint8_t *) redundant->data, ENV_SIZE);
+ crc1_ok = (crc1 == redundant->crc);
+ flag1 = redundant->flags;
+
diff --git a/package/uboot-envtools/patches/002-makefile.patch b/package/uboot-envtools/patches/002-makefile.patch
new file mode 100644
index 000000000..b18bff6e7
--- /dev/null
+++ b/package/uboot-envtools/patches/002-makefile.patch
@@ -0,0 +1,44 @@
+--- a/Makefile
++++ b/Makefile
+@@ -21,34 +21,17 @@
+ # MA 02111-1307 USA
+ #
+
+-include $(TOPDIR)/config.mk
+-
+-HOSTSRCS := $(SRCTREE)/lib/crc32.c fw_env.c fw_env_main.c
++SRCS := crc32.c fw_env.c fw_env_main.c
+ HEADERS := fw_env.h
+
+-# Compile for a hosted environment on the target
+-HOSTCPPFLAGS = -idirafter $(SRCTREE)/include \
+- -idirafter $(OBJTREE)/include2 \
+- -idirafter $(OBJTREE)/include \
+- -DUSE_HOSTCC
+-
+-ifeq ($(MTD_VERSION),old)
+-HOSTCPPFLAGS += -DMTD_OLD
+-endif
+-
+-all: $(obj)fw_printenv
+-
+-# Some files complain if compiled with -pedantic, use HOSTCFLAGS_NOPED
+-$(obj)fw_printenv: $(HOSTSRCS) $(HEADERS)
+- $(HOSTCC) $(HOSTCFLAGS_NOPED) $(HOSTLDFLAGS) -o $@ $(HOSTSRCS)
++CPPFLAGS := -Wall $(CFLAGS)
+
+-clean:
+- rm -f $(obj)fw_printenv
++all: fw_printenv
+
+-#########################################################################
++fw_printenv: $(SRCS) $(HEADERS)
++ $(CC) $(CPPFLAGS) $(SRCS) -o fw_printenv
+
+-include $(TOPDIR)/rules.mk
+-
+-sinclude $(obj).depend
++clean:
++ rm -f fw_printenv
+
+ #########################################################################
diff --git a/package/uboot-envtools/patches/003-nor-eraselen.patch b/package/uboot-envtools/patches/003-nor-eraselen.patch
new file mode 100644
index 000000000..c6eb59a72
--- /dev/null
+++ b/package/uboot-envtools/patches/003-nor-eraselen.patch
@@ -0,0 +1,14 @@
+--- a/fw_env.c
++++ b/fw_env.c
+@@ -790,7 +790,10 @@ static int flash_write_buf (int dev, int
+ erase_offset = (offset / blocklen) * blocklen;
+
+ /* Maximum area we may use */
+- erase_len = top_of_range - erase_offset;
++ if (mtd_type == MTD_NANDFLASH)
++ erase_len = top_of_range - erase_offset;
++ else
++ erase_len = blocklen;
+
+ blockstart = erase_offset;
+ /* Offset inside a block */
diff --git a/package/uboot-envtools/patches/004-allow_mac_change.patch b/package/uboot-envtools/patches/004-allow_mac_change.patch
new file mode 100644
index 000000000..b7d600b69
--- /dev/null
+++ b/package/uboot-envtools/patches/004-allow_mac_change.patch
@@ -0,0 +1,21 @@
+--- a/fw_env.c
++++ b/fw_env.c
+@@ -46,8 +46,6 @@
+
+ #include "fw_env.h"
+
+-#include <config.h>
+-
+ #define WHITESPACE(c) ((c == '\t') || (c == ' '))
+
+ #define min(x, y) ({ \
+@@ -401,9 +399,7 @@ int fw_env_write(char *name, char *value
+ if (
+ (strcmp(name, "serial#") == 0) ||
+ ((strcmp(name, "ethaddr") == 0)
+-#if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR)
+ && (strcmp(oldval, MK_STR(CONFIG_ETHADDR)) != 0)
+-#endif /* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */
+ ) ) {
+ fprintf (stderr, "Can't overwrite \"%s\"\n", name);
+ errno = EROFS;
diff --git a/package/uboot-kirkwood/Makefile b/package/uboot-kirkwood/Makefile
new file mode 100644
index 000000000..48bcf9966
--- /dev/null
+++ b/package/uboot-kirkwood/Makefile
@@ -0,0 +1,110 @@
+#
+# Copyright (C) 2010-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=u-boot
+PKG_VERSION:=2012.04.01
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=ftp://ftp.denx.de/pub/u-boot
+PKG_MD5SUM:=192bb231082d9159fb6e16de3039b6b2
+PKG_TARGETS:=bin
+
+include $(INCLUDE_DIR)/package.mk
+
+define uboot/Default
+ TITLE:=
+ CONFIG:=
+ IMAGE:=
+endef
+
+define uboot/sheevaplug
+ TITLE:=U-Boot for the SheevaPlug
+endef
+
+define uboot/dockstar
+ TITLE:=U-Boot for the Seagate DockStar
+endef
+
+define uboot/iconnect
+ TITLE:=U-Boot for the Iomega iConnect Wireless
+endef
+
+define uboot/ib62x0
+ TITLE:=U-Boot for the RaidSonic ICY BOX NAS6210 and NAS6220
+endef
+
+UBOOTS:=sheevaplug dockstar iconnect ib62x0
+
+define Package/uboot/template
+define Package/uboot-kirkwood-$(1)
+ SECTION:=boot
+ CATEGORY:=Boot Loaders
+ DEPENDS:=@TARGET_kirkwood
+ TITLE:=$(2)
+ URL:=http://www.denx.de/wiki/U-Boot
+ VARIANT:=$(1)
+endef
+endef
+
+define BuildUBootPackage
+ $(eval $(uboot/Default))
+ $(eval $(uboot/$(1)))
+ $(call Package/uboot/template,$(1),$(TITLE))
+endef
+
+ifdef BUILD_VARIANT
+$(eval $(call uboot/$(BUILD_VARIANT)))
+UBOOT_CONFIG:=$(if $(CONFIG),$(CONFIG),$(BUILD_VARIANT))
+UBOOT_IMAGE:=$(if $(IMAGE),$(IMAGE),openwrt-$(BOARD)-$(BUILD_VARIANT)-u-boot.bin)
+endif
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ $(CP) ./files/* $(PKG_BUILD_DIR)
+endef
+
+define Build/Configure
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(UBOOT_CONFIG)_config
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ u-boot.kwb \
+ CROSS_COMPILE=$(TARGET_CROSS)
+endef
+
+define Package/uboot/install/default
+ $(INSTALL_DIR) $(BIN_DIR)
+ $(CP) $(PKG_BUILD_DIR)/u-boot.bin \
+ $(BIN_DIR)/openwrt-$(BOARD)-$(1)-u-boot.bin
+ $(CP) $(PKG_BUILD_DIR)/u-boot.kwb \
+ $(BIN_DIR)/openwrt-$(BOARD)-$(1)-u-boot.kwb
+ $(INSTALL_DIR) $(BIN_DIR)/u-boot-kwboot/
+ $(CP) $(PKG_BUILD_DIR)/tools/kwboot \
+ $(BIN_DIR)/u-boot-kwboot/
+endef
+
+define Package/uboot/install/template
+define Package/uboot-kirkwood-$(1)/install
+ $(call Package/uboot/install/default,$(2))
+endef
+endef
+
+$(foreach u,$(UBOOTS), \
+ $(eval $(call Package/uboot/install/template,$(u),$(u))) \
+)
+
+$(foreach u,$(UBOOTS), \
+ $(eval $(call BuildUBootPackage,$(u))) \
+ $(eval $(call BuildPackage,uboot-kirkwood-$(u))) \
+)
diff --git a/package/uboot-kirkwood/files/board/iomega/iconnect/Makefile b/package/uboot-kirkwood/files/board/iomega/iconnect/Makefile
new file mode 100644
index 000000000..f77fcfb99
--- /dev/null
+++ b/package/uboot-kirkwood/files/board/iomega/iconnect/Makefile
@@ -0,0 +1,43 @@
+#
+# (C) Copyright 2009
+# Marvell Semiconductor <www.marvell.com>
+# Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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, see <http://www.gnu.org/licenses/>.
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(BOARD).o
+
+COBJS := iconnect.o
+
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+SOBJS := $(addprefix $(obj),$(SOBJS))
+
+$(LIB): $(obj).depend $(OBJS) $(SOBJS)
+ $(call cmd_link_o_target, $(OBJS) $(SOBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/package/uboot-kirkwood/files/board/iomega/iconnect/iconnect.c b/package/uboot-kirkwood/files/board/iomega/iconnect/iconnect.c
new file mode 100644
index 000000000..34ddadf8a
--- /dev/null
+++ b/package/uboot-kirkwood/files/board/iomega/iconnect/iconnect.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2009-2012
+ * Wojciech Dubowik <wojciech.dubowik@neratec.com>
+ * Luka Perkov <uboot@lukaperkov.net>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <common.h>
+#include <miiphy.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/kirkwood.h>
+#include <asm/arch/mpp.h>
+#include "iconnect.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_early_init_f(void)
+{
+ /*
+ * default gpio configuration
+ * There are maximum 64 gpios controlled through 2 sets of registers
+ * the below configuration configures mainly initial LED status
+ */
+ kw_config_gpio(ICONNECT_OE_VAL_LOW,
+ ICONNECT_OE_VAL_HIGH,
+ ICONNECT_OE_LOW, ICONNECT_OE_HIGH);
+
+ /* Multi-Purpose Pins Functionality configuration */
+ u32 kwmpp_config[] = {
+ MPP0_NF_IO2,
+ MPP1_NF_IO3,
+ MPP2_NF_IO4,
+ MPP3_NF_IO5,
+ MPP4_NF_IO6,
+ MPP5_NF_IO7,
+ MPP6_SYSRST_OUTn,
+ MPP7_GPO,
+ MPP8_TW_SDA,
+ MPP9_TW_SCK,
+ MPP10_UART0_TXD,
+ MPP11_UART0_RXD,
+ MPP12_GPO,
+ MPP13_SD_CMD,
+ MPP14_SD_D0,
+ MPP15_SD_D1,
+ MPP16_SD_D2,
+ MPP17_SD_D3,
+ MPP18_NF_IO0,
+ MPP19_NF_IO1,
+ MPP20_GE1_0,
+ MPP21_GE1_1,
+ MPP22_GE1_2,
+ MPP23_GE1_3,
+ MPP24_GE1_4,
+ MPP25_GE1_5,
+ MPP26_GE1_6,
+ MPP27_GE1_7,
+ MPP28_GPIO,
+ MPP29_GPIO,
+ MPP30_GE1_10,
+ MPP31_GE1_11,
+ MPP32_GE1_12,
+ MPP33_GE1_13,
+ MPP34_GE1_14,
+ MPP35_GPIO,
+ MPP36_AUDIO_SPDIFI,
+ MPP37_AUDIO_SPDIFO,
+ MPP38_GPIO,
+ MPP39_TDM_SPI_CS0,
+ MPP40_TDM_SPI_SCK,
+ MPP41_GPIO,
+ MPP42_GPIO,
+ MPP43_GPIO,
+ MPP44_GPIO,
+ MPP45_GPIO,
+ MPP46_GPIO,
+ MPP47_GPIO,
+ MPP48_GPIO,
+ MPP49_GPIO,
+ 0
+ };
+ kirkwood_mpp_conf(kwmpp_config);
+ return 0;
+}
+
+int board_init(void)
+{
+ /* Boot parameters address */
+ gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+
+ return 0;
+}
+
+#ifdef CONFIG_RESET_PHY_R
+/* Configure and initialize PHY */
+void reset_phy(void)
+{
+ u16 reg;
+ u16 devadr;
+ char *name = "egiga0";
+
+ if (miiphy_set_current_dev(name))
+ return;
+
+ /* command to read PHY dev address */
+ if (miiphy_read(name, 0xEE, 0xEE, (u16 *) &devadr)) {
+ printf("Err..(%s) could not read PHY dev address\n", __func__);
+ return;
+ }
+
+ /*
+ * Enable RGMII delay on Tx and Rx for CPU port
+ * Ref: sec 4.7.2 of chip datasheet
+ */
+ miiphy_write(name, devadr, MV88E1116_PGADR_REG, 2);
+ miiphy_read(name, devadr, MV88E1116_MAC_CTRL_REG, &reg);
+ reg |= (MV88E1116_RGMII_RXTM_CTRL | MV88E1116_RGMII_TXTM_CTRL);
+ miiphy_write(name, devadr, MV88E1116_MAC_CTRL_REG, reg);
+ miiphy_write(name, devadr, MV88E1116_PGADR_REG, 0);
+
+ /* reset the phy */
+ miiphy_reset(name, devadr);
+
+ debug("88E1116 Initialized on %s\n", name);
+}
+#endif /* CONFIG_RESET_PHY_R */
diff --git a/package/uboot-kirkwood/files/board/iomega/iconnect/iconnect.h b/package/uboot-kirkwood/files/board/iomega/iconnect/iconnect.h
new file mode 100644
index 000000000..2fb3e5ed8
--- /dev/null
+++ b/package/uboot-kirkwood/files/board/iomega/iconnect/iconnect.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009-2012
+ * Wojciech Dubowik <wojciech.dubowik@neratec.com>
+ * Luka Perkov <uboot@lukaperkov.net>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ICONNECT_H
+#define __ICONNECT_H
+
+#define ICONNECT_OE_LOW (~(1 << 7))
+#define ICONNECT_OE_HIGH (~(1 << 10))
+#define ICONNECT_OE_VAL_LOW (0)
+#define ICONNECT_OE_VAL_HIGH (1 << 10)
+
+/* PHY related */
+#define MV88E1116_LED_FCTRL_REG 10
+#define MV88E1116_CPRSP_CR3_REG 21
+#define MV88E1116_MAC_CTRL_REG 21
+#define MV88E1116_PGADR_REG 22
+#define MV88E1116_RGMII_TXTM_CTRL (1 << 4)
+#define MV88E1116_RGMII_RXTM_CTRL (1 << 5)
+
+#endif /* __ICONNECT_H */
diff --git a/package/uboot-kirkwood/files/board/iomega/iconnect/kwbimage.cfg b/package/uboot-kirkwood/files/board/iomega/iconnect/kwbimage.cfg
new file mode 100644
index 000000000..dee546a52
--- /dev/null
+++ b/package/uboot-kirkwood/files/board/iomega/iconnect/kwbimage.cfg
@@ -0,0 +1,165 @@
+#
+# (C) Copyright 2009-2012
+# Wojciech Dubowik <wojciech.dubowik@neratec.com>
+# Luka Perkov <uboot@lukaperkov.net>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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, see <http://www.gnu.org/licenses/>.
+#
+# Refer docs/README.kwimage for more details about how-to configure
+# and create kirkwood boot image
+#
+
+# Boot Media configurations
+BOOT_FROM nand
+NAND_ECC_MODE default
+NAND_PAGE_SIZE 0x0800
+
+# SOC registers configuration using bootrom header extension
+# Maximum KWBIMAGE_MAX_CONFIG configurations allowed
+
+# Configure RGMII-0 interface pad voltage to 1.8V
+DATA 0xffd100e0 0x1b1b1b9b
+
+#Dram initalization for SINGLE x16 CL=5 @ 400MHz
+DATA 0xffd01400 0x43000c30 # DDR Configuration register
+# bit13-0: 0xc30, (3120 DDR2 clks refresh rate)
+# bit23-14: 0x0,
+# bit24: 0x1, enable exit self refresh mode on DDR access
+# bit25: 0x1, required
+# bit29-26: 0x0,
+# bit31-30: 0x1,
+
+DATA 0xffd01404 0x37543000 # DDR Controller Control Low
+# bit4: 0x0, addr/cmd in smame cycle
+# bit5: 0x0, clk is driven during self refresh, we don't care for APX
+# bit6: 0x0, use recommended falling edge of clk for addr/cmd
+# bit14: 0x0, input buffer always powered up
+# bit18: 0x1, cpu lock transaction enabled
+# bit23-20: 0x5, recommended value for CL=5 and STARTBURST_DEL disabled bit31=0
+# bit27-24: 0x7, CL+2, STARTBURST sample stages, for freqs 400MHz, unbuffered DIMM
+# bit30-28: 0x3, required
+# bit31: 0x0, no additional STARTBURST delay
+
+DATA 0xffd01408 0x22125451 # DDR Timing (Low) (active cycles value +1)
+# bit3-0: TRAS lsbs
+# bit7-4: TRCD
+# bit11-8: TRP
+# bit15-12: TWR
+# bit19-16: TWTR
+# bit20: TRAS msb
+# bit23-21: 0x0
+# bit27-24: TRRD
+# bit31-28: TRTP
+
+DATA 0xffd0140c 0x00000a33 # DDR Timing (High)
+# bit6-0: TRFC
+# bit8-7: TR2R
+# bit10-9: TR2W
+# bit12-11: TW2W
+# bit31-13: 0x0, required
+
+DATA 0xffd01410 0x000000cc # DDR Address Control
+# bit1-0: 00, Cs0width (x8)
+# bit3-2: 11, Cs0size (1Gb)
+# bit5-4: 00, Cs1width (x8)
+# bit7-6: 11, Cs1size (1Gb)
+# bit9-8: 00, Cs2width (nonexistent)
+# bit11-10: 00, Cs2size (nonexistent)
+# bit13-12: 00, Cs3width (nonexistent)
+# bit15-14: 00, Cs3size (nonexistent)
+# bit16: 0, Cs0AddrSel
+# bit17: 0, Cs1AddrSel
+# bit18: 0, Cs2AddrSel
+# bit19: 0, Cs3AddrSel
+# bit31-20: 0x0, required
+
+DATA 0xffd01414 0x00000000 # DDR Open Pages Control
+# bit0: 0, OpenPage enabled
+# bit31-1: 0x0, required
+
+DATA 0xffd01418 0x00000000 # DDR Operation
+# bit3-0: 0x0, DDR cmd
+# bit31-4: 0x0, required
+
+DATA 0xffd0141c 0x00000c52 # DDR Mode
+# bit2-0: 0x2, BurstLen=2 required
+# bit3: 0x0, BurstType=0 required
+# bit6-4: 0x4, CL=5
+# bit7: 0x0, TestMode=0 normal
+# bit8: 0x0, DLL reset=0 normal
+# bit11-9: 0x6, auto-precharge write recovery ????????????
+# bit12: 0x0, PD must be zero
+# bit31-13: 0x0, required
+
+DATA 0xffd01420 0x00000040 # DDR Extended Mode
+# bit0: 0, DDR DLL enabled
+# bit1: 0, DDR drive strenght normal
+# bit2: 0, DDR ODT control lsd (disabled)
+# bit5-3: 0x0, required
+# bit6: 1, DDR ODT control msb, (disabled)
+# bit9-7: 0x0, required
+# bit10: 0, differential DQS enabled
+# bit11: 0, required
+# bit12: 0, DDR output buffer enabled
+# bit31-13: 0x0, required
+
+DATA 0xffd01424 0x0000f17f # DDR Controller Control High
+# bit2-0: 0x7, required
+# bit3: 0x1, MBUS Burst Chop disabled
+# bit6-4: 0x7, required
+# bit7: 0x0,
+# bit8: 0x1, add writepath sample stage, must be 1 for DDR freq >= 300MHz
+# bit9: 0x0, no half clock cycle addition to dataout
+# bit10: 0x0, 1/4 clock cycle skew enabled for addr/ctl signals
+# bit11: 0x0, 1/4 clock cycle skew disabled for write mesh
+# bit15-12: 0xf, required
+# bit31-16: 0x0, required
+
+DATA 0xffd01428 0x00085520 # DDR2 ODT Read Timing (default values)
+DATA 0xffd0147c 0x00008552 # DDR2 ODT Write Timing (default values)
+
+DATA 0xffd01500 0x00000000 # CS[0]n Base address to 0x0
+DATA 0xffd01504 0x0ffffff1 # CS[0]n Size
+# bit0: 0x1, Window enabled
+# bit1: 0x0, Write Protect disabled
+# bit3-2: 0x0, CS0 hit selected
+# bit23-4: 0xfffff, required
+# bit31-24: 0x0f, Size (i.e. 256MB)
+
+DATA 0xffd01508 0x00000000 # CS[1]n Base address to 256Mb
+DATA 0xffd0150c 0x00000000 # CS[1]n Size 256Mb Window enabled for CS1
+
+DATA 0xffd01514 0x00000000 # CS[2]n Size, window disabled
+DATA 0xffd0151c 0x00000000 # CS[3]n Size, window disabled
+
+DATA 0xffd01494 0x00030000 # DDR ODT Control (Low)
+# bit3-0: ODT0Rd, MODT[0] asserted during read from DRAM CS1
+# bit7-4: ODT0Rd, MODT[0] asserted during read from DRAM CS0
+# bit19-16:2, ODT0Wr, MODT[0] asserted during write to DRAM CS1
+# bit23-20:1, ODT0Wr, MODT[0] asserted during write to DRAM CS0
+
+DATA 0xffd01498 0x00000000 # DDR ODT Control (High)
+# bit1-0: 0x0, ODT0 controlled by ODT Control (low) register above
+# bit3-2: 0x1, ODT1 active NEVER!
+# bit31-4: 0x0, required
+
+DATA 0xffd0149c 0x0000e803 # CPU ODT Control
+DATA 0xffd01480 0x00000001 # DDR Initialization Control
+# bit0: 0x1, enable DDR init upon this register write
+
+# End of Header extension
+DATA 0x0 0x0
diff --git a/package/uboot-kirkwood/files/include/configs/iconnect.h b/package/uboot-kirkwood/files/include/configs/iconnect.h
new file mode 100644
index 000000000..59432f14d
--- /dev/null
+++ b/package/uboot-kirkwood/files/include/configs/iconnect.h
@@ -0,0 +1,124 @@
+/*
+ * (C) Copyright 2009-2012
+ * Wojciech Dubowik <wojciech.dubowik@neratec.com>
+ * Luka Perkov <uboot@lukaperkov.net>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CONFIG_ICONNECT_H
+#define _CONFIG_ICONNECT_H
+
+/*
+ * Version number information
+ */
+#define CONFIG_IDENT_STRING " Iomega iConnect Wireless"
+
+/*
+ * High level configuration options
+ */
+#define CONFIG_FEROCEON_88FR131 /* CPU Core subversion */
+#define CONFIG_KIRKWOOD /* SOC Family Name */
+#define CONFIG_KW88F6281 /* SOC Name */
+#define CONFIG_SKIP_LOWLEVEL_INIT /* disable board lowlevel_init */
+#define CONFIG_KIRKWOOD_EGIGA_INIT /* Enable GbePort0/1 for kernel */
+
+/*
+ * Machine type
+ */
+#define CONFIG_MACH_TYPE MACH_TYPE_ICONNECT
+
+
+/*
+ * Commands configuration
+ */
+#define CONFIG_SYS_NO_FLASH /* declare no flash (NOR/SPI) */
+#define CONFIG_SYS_MVFS
+#include <config_cmd_default.h>
+#define CONFIG_CMD_ENV
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_NAND
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_USB
+
+/*
+ * mv-common.h should be defined after CMD configs since it used them
+ * to enable certain macros
+ */
+#include "mv-common.h"
+
+#undef CONFIG_SYS_PROMPT
+#define CONFIG_SYS_PROMPT "iconnect => "
+
+/*
+ * Environment variables configuration
+ */
+#ifdef CONFIG_CMD_NAND
+#define CONFIG_ENV_IS_IN_NAND
+#define CONFIG_ENV_SECT_SIZE 0x20000
+#else
+#define CONFIG_ENV_IS_NOWHERE
+#endif
+#define CONFIG_ENV_SIZE 0x20000
+#define CONFIG_ENV_OFFSET 0xc0000
+
+/*
+ * Default environment variables
+ */
+#define CONFIG_BOOTCOMMAND "${x_bootcmd_kernel}; " \
+ "setenv bootargs ${x_bootargs} ${x_bootargs_root}; " \
+ "${x_bootcmd_usb}; bootm 0x6400000;"
+
+#define CONFIG_MTDPARTS "orion_nand:1M(u-boot)," \
+ "3M@1M(kernel),32M@4M(rootfs),475M@36M(data)\0"
+
+#define CONFIG_EXTRA_ENV_SETTINGS "x_bootargs=console" \
+ "=ttyS0,115200 mtdparts="CONFIG_MTDPARTS \
+ "x_bootcmd_kernel=nand read 0x6400000 0x100000 0x300000\0" \
+ "x_bootcmd_usb=usb start\0" \
+ "x_bootargs_root=root=/dev/mtdblock2 rw rootfstype=jffs2\0"
+
+/*
+ * Ethernet driver configuration
+ */
+#ifdef CONFIG_CMD_NET
+#define CONFIG_MVGBE_PORTS {1, 0} /* enable port 0 only */
+#define CONFIG_PHY_BASE_ADR 11
+#endif /* CONFIG_CMD_NET */
+
+/*
+ * SATA driver configuration
+ */
+#ifdef CONFIG_CMD_IDE
+#define CONFIG_SYS_ATA_IDE0_OFFSET MV_SATA_PORT0_OFFSET
+#define CONFIG_SYS_ATA_IDE1_OFFSET MV_SATA_PORT1_OFFSET
+#endif /* CONFIG_CMD_IDE */
+
+/*
+ * File system
+ */
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_JFFS2
+#define CONFIG_CMD_UBI
+#define CONFIG_CMD_UBIFS
+#define CONFIG_RBTREE
+#define CONFIG_MTD_DEVICE
+#define CONFIG_MTD_PARTITIONS
+#define CONFIG_CMD_MTDPARTS
+
+#endif /* _CONFIG_ICONNECT_H */
diff --git a/package/uboot-kirkwood/patches/0001-ib62x0.patch b/package/uboot-kirkwood/patches/0001-ib62x0.patch
new file mode 100644
index 000000000..0a7dc47a5
--- /dev/null
+++ b/package/uboot-kirkwood/patches/0001-ib62x0.patch
@@ -0,0 +1,542 @@
+http://lists.denx.de/pipermail/u-boot/2012-April/122597.html
+http://patchwork.ozlabs.org/patch/153293/
+---
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 708ded7..9d2aba7 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -777,6 +777,10 @@ Linus Walleij <linus.walleij@linaro.org>
+ integratorap various
+ integratorcp various
+
++Luka Perkov <uboot@lukaperkov.net>
++
++ ib62x0 ARM926EJS
++
+ Dave Peverley <dpeverley@mpc-data.co.uk>
+
+ omap730p2 ARM926EJS
+diff --git a/board/raidsonic/ib62x0/Makefile b/board/raidsonic/ib62x0/Makefile
+new file mode 100644
+index 0000000..d450f8d
+--- /dev/null
++++ b/board/raidsonic/ib62x0/Makefile
+@@ -0,0 +1,43 @@
++#
++# (C) Copyright 2009
++# Marvell Semiconductor <www.marvell.com>
++# Written-by: Prafulla Wadaskar <prafulla@marvell.com>
++#
++# See file CREDITS for list of people who contributed to this
++# project.
++#
++# This program is free software; you can redistribute it and/or
++# modify it under the terms of the GNU General Public License as
++# published by the Free Software Foundation; either version 2 of
++# the License, or (at your option) any later version.
++#
++# 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, see <http://www.gnu.org/licenses/>.
++#
++
++include $(TOPDIR)/config.mk
++
++LIB = $(obj)lib$(BOARD).o
++
++COBJS := ib62x0.o
++
++SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
++OBJS := $(addprefix $(obj),$(COBJS))
++SOBJS := $(addprefix $(obj),$(SOBJS))
++
++$(LIB): $(obj).depend $(OBJS) $(SOBJS)
++ $(call cmd_link_o_target, $(OBJS) $(SOBJS))
++
++#########################################################################
++
++# defines $(obj).depend target
++include $(SRCTREE)/rules.mk
++
++sinclude $(obj).depend
++
++#########################################################################
+diff --git a/board/raidsonic/ib62x0/ib62x0.c b/board/raidsonic/ib62x0/ib62x0.c
+new file mode 100644
+index 0000000..65f2c2e
+--- /dev/null
++++ b/board/raidsonic/ib62x0/ib62x0.c
+@@ -0,0 +1,79 @@
++/*
++ * Copyright (C) 2011-2012
++ * Gerald Kerma <dreagle@doukki.net>
++ * Luka Perkov <uboot@lukaperkov.net>
++ * Simon Baatz <gmbnomis@gmail.com>
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <common.h>
++#include <miiphy.h>
++#include <asm/arch/cpu.h>
++#include <asm/arch/kirkwood.h>
++#include <asm/arch/mpp.h>
++#include "ib62x0.h"
++
++DECLARE_GLOBAL_DATA_PTR;
++
++int board_early_init_f(void)
++{
++ /*
++ * default gpio configuration
++ * There are maximum 64 gpios controlled through 2 sets of registers
++ * the below configuration configures mainly initial LED status
++ */
++ kw_config_gpio(IB62x0_OE_VAL_LOW,
++ IB62x0_OE_VAL_HIGH,
++ IB62x0_OE_LOW, IB62x0_OE_HIGH);
++
++ /* Multi-Purpose Pins Functionality configuration */
++ u32 kwmpp_config[] = {
++ MPP0_NF_IO2,
++ MPP1_NF_IO3,
++ MPP2_NF_IO4,
++ MPP3_NF_IO5,
++ MPP4_NF_IO6,
++ MPP5_NF_IO7,
++ MPP6_SYSRST_OUTn,
++ MPP8_TW_SDA,
++ MPP9_TW_SCK,
++ MPP10_UART0_TXD,
++ MPP11_UART0_RXD,
++ MPP18_NF_IO0,
++ MPP19_NF_IO1,
++ MPP20_SATA1_ACTn,
++ MPP21_SATA0_ACTn,
++ MPP22_GPIO, /* Power LED red */
++ MPP24_GPIO, /* Power off device */
++ MPP25_GPIO, /* Power LED green */
++ MPP27_GPIO, /* USB transfer LED */
++ MPP28_GPIO, /* Reset button */
++ MPP29_GPIO, /* USB Copy button */
++ 0
++ };
++ kirkwood_mpp_conf(kwmpp_config);
++ return 0;
++}
++
++int board_init(void)
++{
++ /* adress of boot parameters */
++ gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
++
++ return 0;
++}
+diff --git a/board/raidsonic/ib62x0/ib62x0.h b/board/raidsonic/ib62x0/ib62x0.h
+new file mode 100644
+index 0000000..0c30690
+--- /dev/null
++++ b/board/raidsonic/ib62x0/ib62x0.h
+@@ -0,0 +1,40 @@
++/*
++ * Copyright (C) 2011-2012
++ * Gerald Kerma <dreagle@doukki.net>
++ * Simon Baatz <gmbnomis@gmail.com>
++ * Luka Perkov <uboot@lukaperkov.net>
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __IB62x0_H
++#define __IB62x0_H
++
++#define IB62x0_OE_LOW (~(1 << 22 | 1 << 24 | 1 << 25 | 1 << 27))
++#define IB62x0_OE_HIGH (~(0))
++#define IB62x0_OE_VAL_LOW 0
++#define IB62x0_OE_VAL_HIGH 0
++
++/* PHY related */
++#define MV88E1116_LED_FCTRL_REG 10
++#define MV88E1116_CPRSP_CR3_REG 21
++#define MV88E1116_MAC_CTRL_REG 21
++#define MV88E1116_PGADR_REG 22
++#define MV88E1116_RGMII_TXTM_CTRL (1 << 4)
++#define MV88E1116_RGMII_RXTM_CTRL (1 << 5)
++
++#endif /* __IB62x0_H */
+diff --git a/board/raidsonic/ib62x0/kwbimage.cfg b/board/raidsonic/ib62x0/kwbimage.cfg
+new file mode 100644
+index 0000000..bd594eb
+--- /dev/null
++++ b/board/raidsonic/ib62x0/kwbimage.cfg
+@@ -0,0 +1,169 @@
++#
++# Copyright (C) 2011-2012
++# Gerald Kerma <dreagle@doukki.net>
++# Simon Baatz <gmbnomis@gmail.com>
++# Luka Perkov <uboot@lukaperkov.net>
++#
++# See file CREDITS for list of people who contributed to this
++# project.
++#
++# This program is free software; you can redistribute it and/or
++# modify it under the terms of the GNU General Public License as
++# published by the Free Software Foundation; either version 2 of
++# the License, or (at your option) any later version.
++#
++# 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, see <http://www.gnu.org/licenses/>.
++#
++# Refer docs/README.kwimage for more details about how-to configure
++# and create kirkwood boot image
++#
++
++# Boot Media configurations
++BOOT_FROM nand # change from nand to uart if building UART image
++NAND_ECC_MODE default
++NAND_PAGE_SIZE 0x0800
++
++# SOC registers configuration using bootrom header extension
++# Maximum KWBIMAGE_MAX_CONFIG configurations allowed
++
++# Configure RGMII-0 interface pad voltage to 1.8V
++DATA 0xffd100e0 0x1b1b1b9b
++
++#Dram initalization for SINGLE x16 CL=5 @ 400MHz
++DATA 0xffd01400 0x43000c30 # DDR Configuration register
++# bit13-0: 0xc30, (3120 DDR2 clks refresh rate)
++# bit23-14: 0x0,
++# bit24: 0x1, enable exit self refresh mode on DDR access
++# bit25: 0x1, required
++# bit29-26: 0x0,
++# bit31-30: 0x1,
++
++DATA 0xffd01404 0x37543000 # DDR Controller Control Low
++# bit4: 0x0, addr/cmd in smame cycle
++# bit5: 0x0, clk is driven during self refresh, we don't care for APX
++# bit6: 0x0, use recommended falling edge of clk for addr/cmd
++# bit14: 0x0, input buffer always powered up
++# bit18: 0x1, cpu lock transaction enabled
++# bit23-20: 0x5, recommended value for CL=5 and STARTBURST_DEL disabled bit31=0
++# bit27-24: 0x7, CL+2, STARTBURST sample stages, for freqs 400MHz, unbuffered DIMM
++# bit30-28: 0x3, required
++# bit31: 0x0, no additional STARTBURST delay
++
++DATA 0xffd01408 0x22125451 # DDR Timing (Low) (active cycles value +1)
++# bit3-0: TRAS lsbs
++# bit7-4: TRCD
++# bit11-8: TRP
++# bit15-12: TWR
++# bit19-16: TWTR
++# bit20: TRAS msb
++# bit23-21: 0x0
++# bit27-24: TRRD
++# bit31-28: TRTP
++
++DATA 0xffd0140c 0x00000a33 # DDR Timing (High)
++# bit6-0: TRFC
++# bit8-7: TR2R
++# bit10-9: TR2W
++# bit12-11: TW2W
++# bit31-13: 0x0, required
++
++DATA 0xffd01410 0x0000000c # DDR Address Control
++# bit1-0: 00, Cs0width (x8)
++# bit3-2: 11, Cs0size (1Gb)
++# bit5-4: 00, Cs1width (x8)
++# bit7-6: 11, Cs1size (1Gb)
++# bit9-8: 00, Cs2width (nonexistent
++# bit11-10: 00, Cs2size (nonexistent
++# bit13-12: 00, Cs3width (nonexistent
++# bit15-14: 00, Cs3size (nonexistent
++# bit16: 0, Cs0AddrSel
++# bit17: 0, Cs1AddrSel
++# bit18: 0, Cs2AddrSel
++# bit19: 0, Cs3AddrSel
++# bit31-20: 0x0, required
++
++DATA 0xffd01414 0x00000000 # DDR Open Pages Control
++# bit0: 0, OpenPage enabled
++# bit31-1: 0x0, required
++
++DATA 0xffd01418 0x00000000 # DDR Operation
++# bit3-0: 0x0, DDR cmd
++# bit31-4: 0x0, required
++
++DATA 0xffd0141c 0x00000c52 # DDR Mode
++# bit2-0: 0x2, BurstLen=2 required
++# bit3: 0x0, BurstType=0 required
++# bit6-4: 0x4, CL=5
++# bit7: 0x0, TestMode=0 normal
++# bit8: 0x0, DLL reset=0 normal
++# bit11-9: 0x6, auto-precharge write recovery ????????????
++# bit12: 0x0, PD must be zero
++# bit31-13: 0x0, required
++
++DATA 0xffd01420 0x00000040 # DDR Extended Mode
++# bit0: 0, DDR DLL enabled
++# bit1: 0, DDR drive strenght normal
++# bit2: 1, DDR ODT control lsd (disabled)
++# bit5-3: 0x0, required
++# bit6: 0, DDR ODT control msb, (disabled)
++# bit9-7: 0x0, required
++# bit10: 0, differential DQS enabled
++# bit11: 0, required
++# bit12: 0, DDR output buffer enabled
++# bit31-13: 0x0, required
++
++DATA 0xffd01424 0x0000f17f # DDR Controller Control High
++# bit2-0: 0x7, required
++# bit3: 0x1, MBUS Burst Chop disabled
++# bit6-4: 0x7, required
++# bit7: 0x0,
++# bit8: 0x1, add writepath sample stage, must be 1 for DDR freq >= 300MHz
++# bit9: 0x0, no half clock cycle addition to dataout
++# bit10: 0x0, 1/4 clock cycle skew enabled for addr/ctl signals
++# bit11: 0x0, 1/4 clock cycle skew disabled for write mesh
++# bit15-12: 0xf, required
++# bit31-16: 0, required
++
++DATA 0xffd01428 0x00085520 # DDR2 ODT Read Timing (default values)
++DATA 0xffd0147c 0x00008552 # DDR2 ODT Write Timing (default values)
++
++DATA 0xffd01500 0x00000000 # CS[0]n Base address to 0x0
++DATA 0xffd01504 0x0ffffff1 # CS[0]n Size
++# bit0: 0x1, Window enabled
++# bit1: 0x0, Write Protect disabled
++# bit3-2: 0x0, CS0 hit selected
++# bit23-4: 0xfffff, required
++# bit31-24: 0x0f, Size (i.e. 256MB)
++
++DATA 0xffd01508 0x10000000 # CS[1]n Base address to 256Mb
++DATA 0xffd0150c 0x00000000 # CS[1]n Size, window disabled
++
++DATA 0xffd01514 0x00000000 # CS[2]n Size, window disabled
++DATA 0xffd0151c 0x00000000 # CS[3]n Size, window disabled
++
++DATA 0xffd01494 0x00030000 # DDR ODT Control (Low)
++# bit3-0: ODT0Rd, MODT[0] asserted during read from DRAM CS1
++# bit7-4: ODT0Rd, MODT[0] asserted during read from DRAM CS0
++# bit19-16:2, ODT0Wr, MODT[0] asserted during write to DRAM CS1
++# bit23-20:1, ODT0Wr, MODT[0] asserted during write to DRAM CS0
++
++DATA 0xffd01498 0x00000000 # DDR ODT Control (High)
++# bit1-0: 0x0, ODT0 controlled by ODT Control (low) register above
++# bit3-2: 0x1, ODT1 active NEVER!
++# bit31-4: 0x0, required
++
++DATA 0xffd0149c 0x0000e803 # CPU ODT Control
++DATA 0xffd01480 0x00000001 # DDR Initialization Control
++# bit0: 0x1, enable DDR init upon this register write
++
++DATA 0xFFD20134 0x66666666 # L2 RAM Timing 0 Register
++DATA 0xFFD20138 0x66666666 # L2 RAM Timing 1 Register
++
++# End of Header extension
++DATA 0x0 0x0
+diff --git a/boards.cfg b/boards.cfg
+index 3cf75c3..23f84e8 100644
+--- a/boards.cfg
++++ b/boards.cfg
+@@ -153,6 +153,7 @@ openrd_client arm arm926ejs openrd Marvell
+ openrd_ultimate arm arm926ejs openrd Marvell kirkwood openrd:BOARD_IS_OPENRD_ULTIMATE
+ rd6281a arm arm926ejs - Marvell kirkwood
+ sheevaplug arm arm926ejs - Marvell kirkwood
++ib62x0 arm arm926ejs ib62x0 raidsonic kirkwood
+ dockstar arm arm926ejs - Seagate kirkwood
+ jadecpu arm arm926ejs jadecpu syteco mb86r0x
+ mx25pdk arm arm926ejs mx25pdk freescale mx25 mx25pdk:IMX_CONFIG=board/freescale/mx25pdk/imximage.cfg
+diff --git a/include/configs/ib62x0.h b/include/configs/ib62x0.h
+new file mode 100644
+index 0000000..85856f2
+--- /dev/null
++++ b/include/configs/ib62x0.h
+@@ -0,0 +1,150 @@
++/*
++ * Copyright (C) 2011-2012
++ * Gerald Kerma <dreagle@doukki.net>
++ * Luka Perkov <uboot@lukaperkov.net>
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _CONFIG_IB62x0_H
++#define _CONFIG_IB62x0_H
++
++/*
++ * Version number information
++ */
++#define CONFIG_IDENT_STRING " RaidSonic ICY BOX IB-NAS62x0"
++
++/*
++ * High level configuration options
++ */
++#define CONFIG_FEROCEON_88FR131 /* CPU Core subversion */
++#define CONFIG_KIRKWOOD /* SOC Family Name */
++#define CONFIG_KW88F6281 /* SOC Name */
++#define CONFIG_SKIP_LOWLEVEL_INIT /* disable board lowlevel_init */
++
++/*
++ * Machine type
++ */
++#define CONFIG_MACH_TYPE MACH_TYPE_NAS6210
++
++/*
++ * Compression configuration
++ */
++#define CONFIG_BZIP2
++#define CONFIG_LZMA
++#define CONFIG_LZO
++
++/*
++ * Commands configuration
++ */
++#define CONFIG_SYS_NO_FLASH /* declare no flash (NOR/SPI) */
++#define CONFIG_SYS_MVFS
++#include <config_cmd_default.h>
++#define CONFIG_CMD_ENV
++#define CONFIG_CMD_IDE
++#define CONFIG_CMD_MII
++#define CONFIG_CMD_NAND
++#define CONFIG_CMD_PING
++#define CONFIG_CMD_USB
++
++/*
++ * mv-common.h should be defined after CMD configs since it used them
++ * to enable certain macros
++ */
++#include "mv-common.h"
++
++#undef CONFIG_SYS_PROMPT
++#define CONFIG_SYS_PROMPT "ib62x0 => "
++
++/*
++ * Environment variables configuration
++ */
++#ifdef CONFIG_CMD_NAND
++#define CONFIG_ENV_IS_IN_NAND
++#define CONFIG_ENV_SECT_SIZE 0x20000
++#else
++#define CONFIG_ENV_IS_NOWHERE
++#endif
++#define CONFIG_ENV_SIZE 0x20000
++#define CONFIG_ENV_OFFSET 0x80000
++
++/*
++ * Default environment variables
++ */
++#define CONFIG_BOOTCOMMAND \
++ "setenv bootargs ${console} ${mtdparts} ${bootargs_root}; " \
++ "ubi part rootfs; " \
++ "ubifsmount rootfs; " \
++ "ubifsload 0x800000 ${kernel}; " \
++ "bootm 0x800000"
++
++#define CONFIG_MTDPARTS \
++ "mtdparts=orion_nand:" \
++ "0x80000@0x0(uboot)," \
++ "0x20000@0x80000(uboot_env)," \
++ "-@0xa0000(rootfs)\0"
++
++#define CONFIG_EXTRA_ENV_SETTINGS \
++ "console=console=ttyS0,115200\0" \
++ "mtdids=nand0=orion_nand\0" \
++ "mtdparts="CONFIG_MTDPARTS \
++ "kernel=/boot/uImage\0" \
++ "bootargs_root=noinitrd ubi.mtd=2 root=ubi0:rootfs rootfstype=ubifs\0"
++
++/*
++ * Ethernet driver configuration
++ */
++#ifdef CONFIG_CMD_NET
++#define CONFIG_MVGBE_PORTS {1, 0} /* enable port 0 only */
++#define CONFIG_PHY_BASE_ADR 0
++#undef CONFIG_RESET_PHY_R
++#endif /* CONFIG_CMD_NET */
++
++/*
++ * SATA driver configuration
++ */
++#ifdef CONFIG_CMD_IDE
++#define __io
++#define CONFIG_IDE_PREINIT
++#define CONFIG_DOS_PARTITION
++#define CONFIG_MVSATA_IDE_USE_PORT0
++#define CONFIG_MVSATA_IDE_USE_PORT1
++#define CONFIG_SYS_ATA_IDE0_OFFSET MV_SATA_PORT0_OFFSET
++#define CONFIG_SYS_ATA_IDE1_OFFSET MV_SATA_PORT1_OFFSET
++#endif /* CONFIG_CMD_IDE */
++
++/*
++ * RTC driver configuration
++ */
++#ifdef CONFIG_CMD_DATE
++#define CONFIG_RTC_MV
++#endif /* CONFIG_CMD_DATE */
++
++/*
++ * File system
++ */
++#define CONFIG_CMD_EXT2
++#define CONFIG_CMD_FAT
++#define CONFIG_CMD_JFFS2
++#define CONFIG_CMD_UBI
++#define CONFIG_CMD_UBIFS
++#define CONFIG_RBTREE
++#define CONFIG_MTD_DEVICE
++#define CONFIG_MTD_PARTITIONS
++#define CONFIG_CMD_MTDPARTS
++
++#endif /* _CONFIG_IB62x0_H */
diff --git a/package/uboot-kirkwood/patches/0002-kwboot.patch b/package/uboot-kirkwood/patches/0002-kwboot.patch
new file mode 100644
index 000000000..091d6a164
--- /dev/null
+++ b/package/uboot-kirkwood/patches/0002-kwboot.patch
@@ -0,0 +1,873 @@
+http://lists.denx.de/pipermail/u-boot/2012-May/125296.html
+http://patchwork.ozlabs.org/patch/161566/
+---
+
+diff --git a/doc/kwboot.1 b/doc/kwboot.1
+new file mode 100644
+index 0000000..ed08398
+--- /dev/null
++++ b/doc/kwboot.1
+@@ -0,0 +1,84 @@
++.TH KWBOOT 1 "2012-05-19"
++
++.SH NAME
++kwboot \- Boot Marvell Kirkwood SoCs over a serial link.
++.SH SYNOPSIS
++.B kwboot
++.RB [ "-b \fIimage\fP" ]
++.RB [ "-p" ]
++.RB [ "-t" ]
++.RB [ "-B \fIbaudrate\fP" ]
++.RB \fITTY\fP
++.SH "DESCRIPTION"
++
++The \fBmkimage\fP program boots boards based on Marvell's Kirkwood
++platform over their integrated UART. Boot image files will typically
++contain a second stage boot loader, such as U-Boot. The image file
++must conform to Marvell's BootROM firmware image format
++(\fIkwbimage\fP), created using a tool such as \fBmkimage\fP.
++
++Following power-up or a system reset, system BootROM code polls the
++UART for a brief period of time, sensing a handshake message which
++initiates an image upload. This program sends this boot message until
++it receives a positive acknowledgement. The image is transfered using
++Xmodem.
++
++Additionally, this program implements a minimal terminal mode, which
++can be used either standalone, or entered immediately following boot
++image transfer completion. This is often useful to catch early boot
++messages, or to manually interrupt a default boot procedure performed
++by the second-stage loader.
++
++.SH "OPTIONS"
++
++.TP
++.BI "\-b \fIimage\fP"
++Handshake; then upload file \fIimage\fP over \fITTY\fP.
++
++Note that for the encapsulated boot code to be executed, \fIimage\fP
++must be of type "UART boot" (0x69). Boot images of different types,
++such as backup images of vendor firmware downloaded from flash memory
++(type 0x8B), will not work (or not as expected). See \fB-p\fP for a
++workaround.
++
++This mode writes handshake status and upload progress indication to
++stdout.
++
++.TP
++.BI "\-p"
++In combination with \fB-b\fP, patches the header in \fIimage\fP prior
++to upload, to "UART boot" type.
++
++This option attempts on-the-fly conversion of some none-UART image
++types, such as images which were originally formatted to be stored in
++flash memory.
++
++Conversion is performed in memory. The contents of \fIimage\fP will
++not be altered.
++
++.TP
++.BI "\-t"
++Run a terminal program, connecting standard input and output to
++.RB \fITTY\fP.
++
++If used in combination with \fB-b\fP, terminal mode is entered
++immediately following a successful image upload.
++
++If standard I/O streams connect to a console, this mode will terminate
++after receiving 'ctrl-\\' followed by 'c' from console input.
++
++.TP
++.BI "\-B \fIbaudrate\fP"
++Adjust the baud rate on \fITTY\fP. Default rate is 115200.
++
++.SH "SEE ALSO"
++.PP
++\fBmkimage\fP(1)
++
++.SH "AUTHORS"
++
++Daniel Stodden <daniel.stodden@gmail.com>
++.br
++Luka Perkov <uboot@lukaperkov.net>
++.br
++David Purdy <david.c.purdy@gmail.com>
+diff --git a/tools/Makefile b/tools/Makefile
+index 8993fdd..8097d95 100644
+--- a/tools/Makefile
++++ b/tools/Makefile
+@@ -72,6 +72,7 @@ BIN_FILES-$(CONFIG_SMDK5250) += mksmdk5250spl$(SFX)
+ BIN_FILES-$(CONFIG_MX28) += mxsboot$(SFX)
+ BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX)
+ BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX)
++BIN_FILES-$(CONFIG_KIRKWOOD) += kwboot$(SFX)
+
+ # Source files which exist outside the tools directory
+ EXT_OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += common/env_embedded.o
+@@ -101,6 +102,7 @@ OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o
+ NOPED_OBJ_FILES-y += os_support.o
+ OBJ_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1.o
+ NOPED_OBJ_FILES-y += ublimage.o
++OBJ_FILES-$(CONFIG_KIRKWOOD) += kwboot.o
+
+ # Don't build by default
+ #ifeq ($(ARCH),ppc)
+@@ -234,6 +236,10 @@ $(obj)ncb$(SFX): $(obj)ncb.o
+ $(obj)ubsha1$(SFX): $(obj)os_support.o $(obj)sha1.o $(obj)ubsha1.o
+ $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
+
++$(obj)kwboot$(SFX): $(obj)kwboot.o
++ $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
++ $(HOSTSTRIP) $@
++
+ # Some of the tool objects need to be accessed from outside the tools directory
+ $(obj)%.o: $(SRCTREE)/common/%.c
+ $(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $<
+diff --git a/tools/kwboot.c b/tools/kwboot.c
+new file mode 100644
+index 0000000..e773f01
+--- /dev/null
++++ b/tools/kwboot.c
+@@ -0,0 +1,742 @@
++/*
++ * Boot a Marvell Kirkwood SoC, with Xmodem over UART0.
++ *
++ * (c) 2012 Daniel Stodden <daniel.stodden@gmail.com>
++ *
++ * References: marvell.com, "88F6180, 88F6190, 88F6192, and 88F6281
++ * Integrated Controller: Functional Specifications" December 2,
++ * 2008. Chapter 24.2 "BootROM Firmware".
++ */
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <stdarg.h>
++#include <libgen.h>
++#include <fcntl.h>
++#include <errno.h>
++#include <unistd.h>
++#include <stdint.h>
++#include <termios.h>
++#include <sys/mman.h>
++#include <sys/stat.h>
++
++#include "kwbimage.h"
++
++#ifdef __GNUC__
++#define PACKED __attribute((packed))
++#else
++#define PACKED
++#endif
++
++/*
++ * Marvell BootROM UART Sensing
++ */
++
++static unsigned char kwboot_msg_boot[] = {
++ 0xBB, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77
++};
++
++#define KWBOOT_MSG_REQ_DELAY 10 /* ms */
++#define KWBOOT_MSG_RSP_TIMEO 50 /* ms */
++
++/*
++ * Xmodem Transfers
++ */
++
++#define SOH 1 /* sender start of block header */
++#define EOT 4 /* sender end of block transfer */
++#define ACK 6 /* target block ack */
++#define NAK 21 /* target block negative ack */
++#define CAN 24 /* target/sender transfer cancellation */
++
++struct kwboot_block {
++ uint8_t soh;
++ uint8_t pnum;
++ uint8_t _pnum;
++ uint8_t data[128];
++ uint8_t csum;
++} PACKED;
++
++#define KWBOOT_BLK_RSP_TIMEO 1000 /* ms */
++
++static int kwboot_verbose;
++
++static void
++kwboot_printv(const char *fmt, ...)
++{
++ va_list ap;
++
++ if (kwboot_verbose) {
++ va_start(ap, fmt);
++ vprintf(fmt, ap);
++ va_end(ap);
++ fflush(stdout);
++ }
++}
++
++static void
++__spinner(void)
++{
++ const char seq[] = { '-', '\\', '|', '/' };
++ const int div = 8;
++ static int state, bs;
++
++ if (state % div == 0) {
++ fputc(bs, stdout);
++ fputc(seq[state / div % sizeof(seq)], stdout);
++ fflush(stdout);
++ }
++
++ bs = '\b';
++ state++;
++}
++
++static void
++kwboot_spinner(void)
++{
++ if (kwboot_verbose)
++ __spinner();
++}
++
++static void
++__progress(int pct, char c)
++{
++ const int width = 70;
++ static const char *nl = "";
++ static int pos;
++
++ if (pos % width == 0)
++ printf("%s%3d %% [", nl, pct);
++
++ fputc(c, stdout);
++
++ nl = "]\n";
++ pos++;
++
++ if (pct == 100) {
++ while (pos++ < width)
++ fputc(' ', stdout);
++ fputs(nl, stdout);
++ }
++
++ fflush(stdout);
++
++}
++
++static void
++kwboot_progress(int _pct, char c)
++{
++ static int pct;
++
++ if (_pct != -1)
++ pct = _pct;
++
++ if (kwboot_verbose)
++ __progress(pct, c);
++}
++
++static int
++kwboot_tty_recv(int fd, void *buf, size_t len, int timeo)
++{
++ int rc, nfds;
++ fd_set rfds;
++ struct timeval tv;
++ ssize_t n;
++
++ rc = -1;
++
++ FD_ZERO(&rfds);
++ FD_SET(fd, &rfds);
++
++ tv.tv_sec = 0;
++ tv.tv_usec = timeo * 1000;
++ if (tv.tv_usec > 1000000) {
++ tv.tv_sec += tv.tv_usec / 1000000;
++ tv.tv_usec %= 1000000;
++ }
++
++ do {
++ nfds = select(fd + 1, &rfds, NULL, NULL, &tv);
++ if (nfds < 0)
++ goto out;
++ if (!nfds) {
++ errno = ETIMEDOUT;
++ goto out;
++ }
++
++ n = read(fd, buf, len);
++ if (n < 0)
++ goto out;
++
++ buf = (char *)buf + n;
++ len -= n;
++ } while (len > 0);
++
++ rc = 0;
++out:
++ return rc;
++}
++
++static int
++kwboot_tty_send(int fd, const void *buf, size_t len)
++{
++ int rc;
++ ssize_t n;
++
++ rc = -1;
++
++ do {
++ n = write(fd, buf, len);
++ if (n < 0)
++ goto out;
++
++ buf = (char *)buf + n;
++ len -= n;
++ } while (len > 0);
++
++ rc = tcdrain(fd);
++out:
++ return rc;
++}
++
++static int
++kwboot_tty_send_char(int fd, unsigned char c)
++{
++ return kwboot_tty_send(fd, &c, 1);
++}
++
++static speed_t
++kwboot_tty_speed(int baudrate)
++{
++ switch (baudrate) {
++ case 115200:
++ return B115200;
++ case 57600:
++ return B57600;
++ case 38400:
++ return B38400;
++ case 19200:
++ return B19200;
++ case 9600:
++ return B9600;
++ }
++
++ return -1;
++}
++
++static int
++kwboot_open_tty(const char *path, speed_t speed)
++{
++ int rc, fd;
++ struct termios tio;
++
++ rc = -1;
++
++ fd = open(path, O_RDWR|O_NOCTTY|O_NDELAY);
++ if (fd < 0)
++ goto out;
++
++ memset(&tio, 0, sizeof(tio));
++
++ tio.c_iflag = 0;
++ tio.c_cflag = CREAD|CLOCAL|CS8;
++
++ tio.c_cc[VMIN] = 1;
++ tio.c_cc[VTIME] = 10;
++
++ cfsetospeed(&tio, speed);
++ cfsetispeed(&tio, speed);
++
++ rc = tcsetattr(fd, TCSANOW, &tio);
++ if (rc)
++ goto out;
++
++ rc = fd;
++out:
++ if (rc < 0) {
++ if (fd >= 0)
++ close(fd);
++ }
++
++ return rc;
++}
++
++static int
++kwboot_bootmsg(int tty, void *msg)
++{
++ int rc;
++ char c;
++
++ kwboot_printv("Sending boot message. Please reboot the target...");
++
++ do {
++ rc = tcflush(tty, TCIOFLUSH);
++ if (rc)
++ break;
++
++ rc = kwboot_tty_send(tty, msg, 8);
++ if (rc) {
++ usleep(KWBOOT_MSG_REQ_DELAY * 1000);
++ continue;
++ }
++
++ rc = kwboot_tty_recv(tty, &c, 1, KWBOOT_MSG_RSP_TIMEO);
++
++ kwboot_spinner();
++
++ } while (rc || c != NAK);
++
++ kwboot_printv("\n");
++
++ return rc;
++}
++
++static int
++kwboot_xm_makeblock(struct kwboot_block *block, const void *data,
++ size_t size, int pnum)
++{
++ const size_t blksz = sizeof(block->data);
++ size_t n;
++ int i;
++
++ block->pnum = pnum;
++ block->_pnum = ~block->pnum;
++
++ n = size < blksz ? size : blksz;
++ memcpy(&block->data[0], data, n);
++ memset(&block->data[n], 0, blksz - n);
++
++ block->csum = 0;
++ for (i = 0; i < n; i++)
++ block->csum += block->data[i];
++
++ return n;
++}
++
++static int
++kwboot_xm_sendblock(int fd, struct kwboot_block *block)
++{
++ int rc, retries;
++ char c;
++
++ retries = 16;
++ do {
++ rc = kwboot_tty_send(fd, block, sizeof(*block));
++ if (rc)
++ break;
++
++ rc = kwboot_tty_recv(fd, &c, 1, KWBOOT_BLK_RSP_TIMEO);
++ if (rc)
++ break;
++
++ if (c != ACK)
++ kwboot_progress(-1, '+');
++
++ } while (c == NAK && retries-- > 0);
++
++ rc = -1;
++
++ switch (c) {
++ case ACK:
++ rc = 0;
++ break;
++ case NAK:
++ errno = EBADMSG;
++ break;
++ case CAN:
++ errno = ECANCELED;
++ break;
++ default:
++ errno = EPROTO;
++ break;
++ }
++
++ return rc;
++}
++
++static int
++kwboot_xmodem(int tty, const void *_data, size_t size)
++{
++ const uint8_t *data = _data;
++ int rc, pnum, N, err;
++
++ pnum = 1;
++ N = 0;
++
++ kwboot_printv("Sending boot image...\n");
++
++ do {
++ struct kwboot_block block;
++ int n;
++
++ n = kwboot_xm_makeblock(&block,
++ data + N, size - N,
++ pnum++);
++ if (n < 0)
++ goto can;
++
++ if (!n)
++ break;
++
++ rc = kwboot_xm_sendblock(tty, &block);
++ if (rc)
++ goto out;
++
++ N += n;
++ kwboot_progress(N * 100 / size, '.');
++ } while (1);
++
++ rc = kwboot_tty_send_char(tty, EOT);
++
++out:
++ return rc;
++
++can:
++ err = errno;
++ kwboot_tty_send_char(tty, CAN);
++ errno = err;
++ goto out;
++}
++
++static int
++kwboot_term_pipe(int in, int out, char *quit, int *s)
++{
++ ssize_t nin, nout;
++ char _buf[128], *buf = _buf;
++
++ nin = read(in, buf, sizeof(buf));
++ if (nin < 0)
++ return -1;
++
++ if (quit) {
++ int i;
++
++ for (i = 0; i < nin; i++) {
++ if (*buf == quit[*s]) {
++ (*s)++;
++ if (!quit[*s])
++ return 0;
++ buf++;
++ nin--;
++ } else
++ while (*s > 0) {
++ nout = write(out, quit, *s);
++ if (nout <= 0)
++ return -1;
++ (*s) -= nout;
++ }
++ }
++ }
++
++ while (nin > 0) {
++ nout = write(out, buf, nin);
++ if (nout <= 0)
++ return -1;
++ nin -= nout;
++ }
++
++ return 0;
++}
++
++static int
++kwboot_terminal(int tty)
++{
++ int rc, in, s;
++ char *quit = "\34c";
++ struct termios otio, tio;
++
++ rc = -1;
++
++ in = STDIN_FILENO;
++ if (isatty(in)) {
++ rc = tcgetattr(in, &otio);
++ if (!rc) {
++ tio = otio;
++ cfmakeraw(&tio);
++ rc = tcsetattr(in, TCSANOW, &tio);
++ }
++ if (rc) {
++ perror("tcsetattr");
++ goto out;
++ }
++
++ kwboot_printv("[Type Ctrl-%c + %c to quit]\r\n",
++ quit[0]|0100, quit[1]);
++ } else
++ in = -1;
++
++ rc = 0;
++ s = 0;
++
++ do {
++ fd_set rfds;
++ int nfds = 0;
++
++ FD_SET(tty, &rfds);
++ nfds = nfds < tty ? tty : nfds;
++
++ if (in >= 0) {
++ FD_SET(in, &rfds);
++ nfds = nfds < in ? in : nfds;
++ }
++
++ nfds = select(nfds + 1, &rfds, NULL, NULL, NULL);
++ if (nfds < 0)
++ break;
++
++ if (FD_ISSET(tty, &rfds)) {
++ rc = kwboot_term_pipe(tty, STDOUT_FILENO, NULL, NULL);
++ if (rc)
++ break;
++ }
++
++ if (FD_ISSET(in, &rfds)) {
++ rc = kwboot_term_pipe(in, tty, quit, &s);
++ if (rc)
++ break;
++ }
++ } while (quit[s] != 0);
++
++ tcsetattr(in, TCSANOW, &otio);
++out:
++ return rc;
++}
++
++static void *
++kwboot_mmap_image(const char *path, size_t *size, int prot)
++{
++ int rc, fd, flags;
++ struct stat st;
++ void *img;
++
++ rc = -1;
++ fd = -1;
++ img = NULL;
++
++ fd = open(path, O_RDONLY);
++ if (fd < 0)
++ goto out;
++
++ rc = fstat(fd, &st);
++ if (rc)
++ goto out;
++
++ flags = (prot & PROT_WRITE) ? MAP_PRIVATE : MAP_SHARED;
++
++ img = mmap(NULL, st.st_size, prot, flags, fd, 0);
++ if (img == MAP_FAILED) {
++ img = NULL;
++ goto out;
++ }
++
++ rc = 0;
++ *size = st.st_size;
++out:
++ if (rc && img) {
++ munmap(img, st.st_size);
++ img = NULL;
++ }
++ if (fd >= 0)
++ close(fd);
++
++ return img;
++}
++
++static uint8_t
++kwboot_img_csum8(void *_data, size_t size)
++{
++ uint8_t *data = _data, csum;
++
++ for (csum = 0; size-- > 0; data++)
++ csum += *data;
++
++ return csum;
++}
++
++static int
++kwboot_img_patch_hdr(void *img, size_t size)
++{
++ int rc;
++ bhr_t *hdr;
++ uint8_t csum;
++ const size_t hdrsz = sizeof(*hdr);
++
++ rc = -1;
++ hdr = img;
++
++ if (size < hdrsz) {
++ errno = EINVAL;
++ goto out;
++ }
++
++ csum = kwboot_img_csum8(hdr, hdrsz) - hdr->checkSum;
++ if (csum != hdr->checkSum) {
++ errno = EINVAL;
++ goto out;
++ }
++
++ if (hdr->blockid == IBR_HDR_UART_ID) {
++ rc = 0;
++ goto out;
++ }
++
++ hdr->blockid = IBR_HDR_UART_ID;
++
++ hdr->nandeccmode = IBR_HDR_ECC_DISABLED;
++ hdr->nandpagesize = 0;
++
++ hdr->srcaddr = hdr->ext
++ ? sizeof(struct kwb_header)
++ : sizeof(*hdr);
++
++ hdr->checkSum = kwboot_img_csum8(hdr, hdrsz) - csum;
++
++ rc = 0;
++out:
++ return rc;
++}
++
++static void
++kwboot_usage(FILE *stream, char *progname)
++{
++ fprintf(stream,
++ "Usage: %s -b <image> [ -p ] [ -t ] "
++ "[-B <baud> ] <TTY>\n", progname);
++ fprintf(stream, "\n");
++ fprintf(stream, " -b <image>: boot <image>\n");
++ fprintf(stream, " -p: patch <image> to type 0x69 (uart boot)\n");
++ fprintf(stream, "\n");
++ fprintf(stream, " -t: mini terminal\n");
++ fprintf(stream, "\n");
++ fprintf(stream, " -B <baud>: set baud rate\n");
++ fprintf(stream, "\n");
++}
++
++int
++main(int argc, char **argv)
++{
++ const char *ttypath, *imgpath;
++ int rv, rc, tty, term, prot, patch;
++ void *bootmsg;
++ void *img;
++ size_t size;
++ speed_t speed;
++
++ rv = 1;
++ tty = -1;
++ bootmsg = NULL;
++ imgpath = NULL;
++ img = NULL;
++ term = 0;
++ patch = 0;
++ size = 0;
++ speed = B115200;
++
++ kwboot_verbose = isatty(STDOUT_FILENO);
++
++ do {
++ int c = getopt(argc, argv, "hb:ptB:");
++ if (c < 0)
++ break;
++
++ switch (c) {
++ case 'b':
++ bootmsg = kwboot_msg_boot;
++ imgpath = optarg;
++ break;
++
++ case 'p':
++ patch = 1;
++ break;
++
++ case 't':
++ term = 1;
++ break;
++
++ case 'B':
++ speed = kwboot_tty_speed(atoi(optarg));
++ if (speed == -1)
++ goto usage;
++ break;
++
++ case 'h':
++ rv = 0;
++ default:
++ goto usage;
++ }
++ } while (1);
++
++ if (!bootmsg && !term)
++ goto usage;
++
++ if (patch && !imgpath)
++ goto usage;
++
++ if (argc - optind < 1)
++ goto usage;
++
++ ttypath = argv[optind++];
++
++ tty = kwboot_open_tty(ttypath, speed);
++ if (tty < 0) {
++ perror(ttypath);
++ goto out;
++ }
++
++ if (imgpath) {
++ prot = PROT_READ | (patch ? PROT_WRITE : 0);
++
++ img = kwboot_mmap_image(imgpath, &size, prot);
++ if (!img) {
++ perror(imgpath);
++ goto out;
++ }
++ }
++
++ if (patch) {
++ rc = kwboot_img_patch_hdr(img, size);
++ if (rc) {
++ fprintf(stderr, "%s: Invalid image.\n", imgpath);
++ goto out;
++ }
++ }
++
++ if (bootmsg) {
++ rc = kwboot_bootmsg(tty, bootmsg);
++ if (rc) {
++ perror("bootmsg");
++ goto out;
++ }
++ }
++
++ if (img) {
++ rc = kwboot_xmodem(tty, img, size);
++ if (rc) {
++ perror("xmodem");
++ goto out;
++ }
++ }
++
++ if (term) {
++ rc = kwboot_terminal(tty);
++ if (rc && !(errno == EINTR)) {
++ perror("terminal");
++ goto out;
++ }
++ }
++
++ rv = 0;
++out:
++ if (tty >= 0)
++ close(tty);
++
++ if (img)
++ munmap(img, size);
++
++ return rv;
++
++usage:
++ kwboot_usage(rv ? stderr : stdout, basename(argv[0]));
++ goto out;
++}
diff --git a/package/uboot-kirkwood/patches/0003-ide_bus.patch b/package/uboot-kirkwood/patches/0003-ide_bus.patch
new file mode 100644
index 000000000..c94d63da9
--- /dev/null
+++ b/package/uboot-kirkwood/patches/0003-ide_bus.patch
@@ -0,0 +1,17 @@
+http://lists.denx.de/pipermail/u-boot/2012-April/122594.html
+http://patchwork.ozlabs.org/patch/159129/
+---
+
+diff --git a/include/ide.h b/include/ide.h
+index 8ecc9dd..385e909 100644
+--- a/include/ide.h
++++ b/include/ide.h
+@@ -24,7 +24,7 @@
+ #ifndef _IDE_H
+ #define _IDE_H
+
+-#define IDE_BUS(dev) (dev >> 1)
++#define IDE_BUS(dev) (dev / (CONFIG_SYS_IDE_MAXDEVICE / CONFIG_SYS_IDE_MAXBUS))
+
+ #define ATA_CURR_BASE(dev) (CONFIG_SYS_ATA_BASE_ADDR+ide_bus_offset[IDE_BUS(dev)])
+
diff --git a/package/uboot-kirkwood/patches/100-iconnect.patch b/package/uboot-kirkwood/patches/100-iconnect.patch
new file mode 100644
index 000000000..d2f35ad5a
--- /dev/null
+++ b/package/uboot-kirkwood/patches/100-iconnect.patch
@@ -0,0 +1,10 @@
+--- a/boards.cfg
++++ b/boards.cfg
+@@ -137,6 +137,7 @@ hawkboard_uart arm
+ enbw_cmc arm arm926ejs enbw_cmc enbw davinci
+ calimain arm arm926ejs calimain omicron davinci
+ dns325 arm arm926ejs - d-link kirkwood
++iconnect arm arm926ejs - iomega kirkwood
+ km_kirkwood arm arm926ejs km_arm keymile kirkwood km_kirkwood:KM_DISABLE_PCI
+ km_kirkwood_pci arm arm926ejs km_arm keymile kirkwood km_kirkwood:KM_RECONFIG_XLX
+ mgcoge3un arm arm926ejs km_arm keymile kirkwood
diff --git a/package/uboot-kirkwood/patches/110-dockstar.patch b/package/uboot-kirkwood/patches/110-dockstar.patch
new file mode 100644
index 000000000..4ff7e57bb
--- /dev/null
+++ b/package/uboot-kirkwood/patches/110-dockstar.patch
@@ -0,0 +1,35 @@
+--- a/include/configs/dockstar.h
++++ b/include/configs/dockstar.h
+@@ -83,22 +83,19 @@
+ * Default environment variables
+ */
+ #define CONFIG_BOOTCOMMAND \
+- "setenv bootargs ${console} ${mtdparts} ${bootargs_root}; " \
+- "ubi part root; " \
+- "ubifsmount root; " \
+- "ubifsload 0x800000 ${kernel}; " \
+- "ubifsload 0x1100000 ${initrd}; " \
+- "bootm 0x800000 0x1100000"
++ "${x_bootcmd_kernel}; " \
++ "setenv bootargs ${x_bootargs} ${x_bootargs_root}; " \
++ "${x_bootcmd_usb}; bootm 0x6400000;"
+
+-#define CONFIG_MTDPARTS "mtdparts=orion_nand:1m(uboot),-(root)\0"
++#define CONFIG_MTDPARTS \
++ "orion_nand:1M(u-boot),1M@1M(second_stage_u-boot)," \
++ "3M@2M(kernel),32M@5M(rootfs),219M@37M(data) rw\0"
+
+ #define CONFIG_EXTRA_ENV_SETTINGS \
+- "console=console=ttyS0,115200\0" \
+- "mtdids=nand0=orion_nand\0" \
+- "mtdparts="CONFIG_MTDPARTS \
+- "kernel=/boot/uImage\0" \
+- "initrd=/boot/uInitrd\0" \
+- "bootargs_root=ubi.mtd=1 root=ubi0:root rootfstype=ubifs ro\0"
++ "x_bootargs=console=ttyS0,115200 mtdparts="CONFIG_MTDPARTS \
++ "x_bootcmd_kernel=nand read 0x6400000 0x200000 0x300000\0" \
++ "x_bootargs_root=root=/dev/mtdblock3 rw rootfstype=jffs2\0" \
++ "x_bootcmd_usb=usb start\0"
+
+ /*
+ * Ethernet Driver configuration
diff --git a/package/uboot-lantiq/Makefile b/package/uboot-lantiq/Makefile
new file mode 100644
index 000000000..8909ee981
--- /dev/null
+++ b/package/uboot-lantiq/Makefile
@@ -0,0 +1,190 @@
+#
+# Copyright (C) 2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=u-boot
+
+PKG_VERSION:=2010.03
+PKG_MD5SUM:=2bf5ebf497dddc52440b1ea386cc1332
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=ftp://ftp.denx.de/pub/u-boot
+PKG_TARGETS:=bin
+
+include $(INCLUDE_DIR)/package.mk
+
+ifeq ($(DUMP),)
+ STAMP_CONFIGURED:=$(PKG_BUILD_DIR)/$(BUILD_VARIANT)/.configured
+ STAMP_BUILT:=$(PKG_BUILD_DIR)/$(BUILD_VARIANT)/.built
+endif
+
+define Package/uboot-lantiq-template
+ SECTION:=boot
+ CATEGORY:=Boot Loaders
+ DEPENDS:=@TARGET_lantiq_danube
+ URL:=http://www.denx.de/wiki/U-Boot
+ VARIANT:=$(1)
+ TITLE:=$(1) ($(2))
+ MAINTAINER:=John Crispin <blogic@openwrt.org>
+endef
+
+#Lantiq
+Package/uboot-lantiq-easy50712_DDR166M_flash=$(call Package/uboot-lantiq-template,easy50712_DDR166M_flash,NOR)
+Package/uboot-lantiq-easy50712_DDR166M_ramboot=$(call Package/uboot-lantiq-template,easy50712_DDR166M_ramboot,RAM)
+Package/uboot-lantiq-easy50812_DDR166M_flash=$(call Package/uboot-lantiq-template,easy50812_DDR166M_flash,NOR)
+Package/uboot-lantiq-easy50812_DDR166M_ramboot=$(call Package/uboot-lantiq-template,easy50812_DDR166M_ramboot,RAM)
+
+DDR_CONFIG_easy50712_DDR166M_ramboot:=easy50712_DDR166M
+DDR_CONFIG_easy50812_DDR166M_ramboot:=easy50812
+
+#Siemens
+Package/uboot-lantiq-gigaSX76X_DDRsamsung166_flash=$(call Package/uboot-lantiq-template,gigaSX76X_DDRsamsung166_flash,NOR)
+Package/uboot-lantiq-gigaSX76X_DDRsamsung166_ramboot=$(call Package/uboot-lantiq-template,gigaSX76X_DDRsamsung166_ramboot,RAM)
+
+DDR_CONFIG_gigaSX76X_DDRsamsung166_ramboot:=easy50712_DDR166M
+
+#Arcadyan
+Package/uboot-lantiq-arv3527P_flash=$(call Package/uboot-lantiq-template,arv3527P_flash,NOR)
+Package/uboot-lantiq-arv3527P_ramboot=$(call Package/uboot-lantiq-template,arv3527P_ramboot,RAM)
+Package/uboot-lantiq-arv3527P_brnboot=$(call Package/uboot-lantiq-template,arv3527P_brnboot,BRN)
+Package/uboot-lantiq-arv4518PW_flash=$(call Package/uboot-lantiq-template,arv4518PW_flash,NOR)
+Package/uboot-lantiq-arv4518PW_ramboot=$(call Package/uboot-lantiq-template,arv4518PW_ramboot,RAM)
+Package/uboot-lantiq-arv4518PW_brnboot=$(call Package/uboot-lantiq-template,arv4518PW_brnboot,BRN)
+Package/uboot-lantiq-arv4519PW_flash=$(call Package/uboot-lantiq-template,arv4519PW_flash,NOR)
+Package/uboot-lantiq-arv4519PW_ramboot=$(call Package/uboot-lantiq-template,arv4519PW_ramboot,RAM)
+Package/uboot-lantiq-arv4519PW_brnboot=$(call Package/uboot-lantiq-template,arv4519PW_brnboot,BRN)
+Package/uboot-lantiq-arv4520PW_flash=$(call Package/uboot-lantiq-template,arv4520PW_flash,NOR)
+Package/uboot-lantiq-arv4520PW_ramboot=$(call Package/uboot-lantiq-template,arv4520PW_ramboot,RAM)
+Package/uboot-lantiq-arv4520PW_brnboot=$(call Package/uboot-lantiq-template,arv4520PW_brnboot,BRN)
+Package/uboot-lantiq-arv4525PW_flash=$(call Package/uboot-lantiq-template,arv4525PW_flash,NOR)
+Package/uboot-lantiq-arv4525PW_ramboot=$(call Package/uboot-lantiq-template,arv4525PW_ramboot,RAM)
+Package/uboot-lantiq-arv4525PW_brnboot=$(call Package/uboot-lantiq-template,arv4525PW_brnboot,BRN)
+Package/uboot-lantiq-arv7525PW_flash=$(call Package/uboot-lantiq-template,arv7525PW_flash,NOR)
+Package/uboot-lantiq-arv7525PW_ramboot=$(call Package/uboot-lantiq-template,arv7525PW_ramboot,RAM)
+Package/uboot-lantiq-arv7525PW_brnboot=$(call Package/uboot-lantiq-template,arv7525PW_brnboot,BRN)
+Package/uboot-lantiq-arv452CPW_flash=$(call Package/uboot-lantiq-template,arv452CPW_flash,NOR)
+Package/uboot-lantiq-arv452CPW_ramboot=$(call Package/uboot-lantiq-template,arv452CPW_ramboot,RAM)
+Package/uboot-lantiq-arv452CPW_brnboot=$(call Package/uboot-lantiq-template,arv452CPW_brnboot,BRN)
+Package/uboot-lantiq-arv752DPW_flash=$(call Package/uboot-lantiq-template,arv752DPW_flash,NOR)
+Package/uboot-lantiq-arv752DPW_ramboot=$(call Package/uboot-lantiq-template,arv752DPW_ramboot,RAM)
+Package/uboot-lantiq-arv752DPW_brnboot=$(call Package/uboot-lantiq-template,arv752DPW_brnboot,BRN)
+Package/uboot-lantiq-arv752DPW22_flash=$(call Package/uboot-lantiq-template,arv752DPW22_flash,NOR)
+Package/uboot-lantiq-arv752DPW22_ramboot=$(call Package/uboot-lantiq-template,arv752DPW22_ramboot,RAM)
+Package/uboot-lantiq-arv752DPW22_brnboot=$(call Package/uboot-lantiq-template,arv752DPW22_brnboot,BRN)
+Package/uboot-lantiq-arv7518PW_flash=$(call Package/uboot-lantiq-template,arv7518PW_flash,NOR)
+Package/uboot-lantiq-arv7518PW_ramboot=$(call Package/uboot-lantiq-template,arv7518PW_ramboot,RAM)
+Package/uboot-lantiq-arv7518PW_brnboot=$(call Package/uboot-lantiq-template,arv7518PW_brnboot,BRN)
+
+DDR_CONFIG_arv3527P_ramboot:=arcadyan_psc166_32
+DDR_CONFIG_arv4518PW_ramboot:=arcadyan_psc166_64
+DDR_CONFIG_arv4519PW_ramboot:=arcadyan_psc166_32
+DDR_CONFIG_arv4520PW_ramboot:=arcadyan_psc166_32
+DDR_CONFIG_arv4525PW_ramboot:=arcadyan_psc166_32
+DDR_CONFIG_arv7525PW_ramboot:=arcadyan_psc166_32
+DDR_CONFIG_arv452CPW_ramboot:=arcadyan_psc166_32
+DDR_CONFIG_arv752DPW_ramboot:=arcadyan_psc166_64
+DDR_CONFIG_arv752DPW22_ramboot:=arcadyan_psc166_64
+DDR_CONFIG_arv7518PW_ramboot:=arcadyan_psc166_64
+
+define Build/Prepare
+ $(PKG_UNPACK)
+ cp -r $(CP_OPTS) $(FILES_DIR)/* $(PKG_BUILD_DIR)/
+ $(Build/Patch)
+ find $(PKG_BUILD_DIR) -name .svn | $(XARGS) rm -rf
+endef
+
+UBOOT_MAKE_OPTS:= \
+ CROSS_COMPILE=$(TARGET_CROSS) \
+ ENDIANNESS= \
+ V=1
+
+define Build/Configure/Target
+ $(MAKE) -s -C $(PKG_BUILD_DIR) \
+ $(UBOOT_MAKE_OPTS) \
+ O=$(PKG_BUILD_DIR)/$(BUILD_VARIANT) \
+ $(1)_config
+endef
+
+define Build/Configure
+ $(call Build/Configure/Target,$(BUILD_VARIANT))
+endef
+
+define Build/Compile/Target
+ $(MAKE) -s -C $(PKG_BUILD_DIR) \
+ $(UBOOT_MAKE_OPTS) \
+ O=$(PKG_BUILD_DIR)/$(1) \
+ all
+endef
+
+define Build/Compile
+ $(call Build/Compile/Target,$(BUILD_VARIANT))
+endef
+
+define Package/uboot-lantiq-$(BUILD_VARIANT)/install
+ mkdir -p $(1)
+ifneq ($(findstring flash,$(BUILD_VARIANT)),)
+ dd \
+ if=$(PKG_BUILD_DIR)/$(BUILD_VARIANT)/u-boot-bootstrap.bin \
+ of=$(1)/u-boot-bootstrap.bin \
+ bs=64k conv=sync
+else
+ dd \
+ if=$(PKG_BUILD_DIR)/$(BUILD_VARIANT)/u-boot.bin \
+ of=$(1)/u-boot.bin \
+ bs=64k conv=sync
+endif
+ifneq ($(findstring ramboot,$(BUILD_VARIANT)),)
+ if [ -e $(DDR_CONFIG_$(BUILD_VARIANT)).conf ]; then \
+ perl ./gct \
+ $(DDR_CONFIG_$(BUILD_VARIANT)).conf \
+ $(PKG_BUILD_DIR)/$(BUILD_VARIANT)/u-boot.srec \
+ $(1)/u-boot.asc; \
+ fi
+endif
+endef
+
+$(eval $(call BuildPackage,uboot-lantiq-easy50712_DDR166M_flash))
+$(eval $(call BuildPackage,uboot-lantiq-easy50712_DDR166M_ramboot))
+$(eval $(call BuildPackage,uboot-lantiq-easy50812_DDR166M_flash))
+$(eval $(call BuildPackage,uboot-lantiq-easy50812_DDR166M_ramboot))
+$(eval $(call BuildPackage,uboot-lantiq-gigaSX76X_DDRsamsung166_flash))
+$(eval $(call BuildPackage,uboot-lantiq-gigaSX76X_DDRsamsung166_ramboot))
+#$(eval $(call BuildPackage,uboot-lantiq-arv3527P_flash))
+#$(eval $(call BuildPackage,uboot-lantiq-arv3527P_brnboot))
+#$(eval $(call BuildPackage,uboot-lantiq-arv3527P_ramboot))
+$(eval $(call BuildPackage,uboot-lantiq-arv4518PW_flash))
+$(eval $(call BuildPackage,uboot-lantiq-arv4518PW_brnboot))
+$(eval $(call BuildPackage,uboot-lantiq-arv4518PW_ramboot))
+$(eval $(call BuildPackage,uboot-lantiq-arv4519PW_flash))
+$(eval $(call BuildPackage,uboot-lantiq-arv4519PW_brnboot))
+$(eval $(call BuildPackage,uboot-lantiq-arv4519PW_ramboot))
+$(eval $(call BuildPackage,uboot-lantiq-arv4520PW_flash))
+$(eval $(call BuildPackage,uboot-lantiq-arv4520PW_brnboot))
+$(eval $(call BuildPackage,uboot-lantiq-arv4520PW_ramboot))
+$(eval $(call BuildPackage,uboot-lantiq-arv4525PW_flash))
+$(eval $(call BuildPackage,uboot-lantiq-arv4525PW_brnboot))
+$(eval $(call BuildPackage,uboot-lantiq-arv4525PW_ramboot))
+$(eval $(call BuildPackage,uboot-lantiq-arv7525PW_flash))
+$(eval $(call BuildPackage,uboot-lantiq-arv7525PW_brnboot))
+$(eval $(call BuildPackage,uboot-lantiq-arv7525PW_ramboot))
+$(eval $(call BuildPackage,uboot-lantiq-arv452CPW_flash))
+$(eval $(call BuildPackage,uboot-lantiq-arv452CPW_brnboot))
+$(eval $(call BuildPackage,uboot-lantiq-arv452CPW_ramboot))
+$(eval $(call BuildPackage,uboot-lantiq-arv752DPW_flash))
+$(eval $(call BuildPackage,uboot-lantiq-arv752DPW_brnboot))
+$(eval $(call BuildPackage,uboot-lantiq-arv752DPW_ramboot))
+$(eval $(call BuildPackage,uboot-lantiq-arv752DPW22_flash))
+$(eval $(call BuildPackage,uboot-lantiq-arv752DPW22_brnboot))
+$(eval $(call BuildPackage,uboot-lantiq-arv752DPW22_ramboot))
+$(eval $(call BuildPackage,uboot-lantiq-arv7518PW_flash))
+$(eval $(call BuildPackage,uboot-lantiq-arv7518PW_brnboot))
+$(eval $(call BuildPackage,uboot-lantiq-arv7518PW_ramboot))
+
diff --git a/package/uboot-lantiq/arcadyan_psc166_32.conf b/package/uboot-lantiq/arcadyan_psc166_32.conf
new file mode 100644
index 000000000..6f9ba0cbe
--- /dev/null
+++ b/package/uboot-lantiq/arcadyan_psc166_32.conf
@@ -0,0 +1,71 @@
+ 0xbf800060 0x7
+ 0xbf800010 0x0
+ 0xbf800020 0x0
+ 0xbf800200 0x02
+ 0xbf800210 0x0
+
+ 0xbf801000 0x1b1b
+ 0xbf801010 0x0
+ 0xbf801020 0x0
+ 0xbf801030 0x0
+ 0xbf801040 0x0
+ 0xbf801050 0x200
+ 0xbf801060 0x605
+ 0xbf801070 0x0303
+ 0xbf801080 0x102
+ 0xbf801090 0x70a
+ 0xbf8010a0 0x203
+ 0xbf8010b0 0xc02
+ 0xbf8010c0 0x1c8
+ 0xbf8010d0 0x1
+ 0xbf8010e0 0x0
+ 0xbf8010f0 0x120
+ 0xbf801100 0xc800
+ 0xbf801110 0xd
+ 0xbf801120 0x301
+ 0xbf801130 0x200
+ 0xbf801140 0xa04
+ 0xbf801150 0x1700
+ 0xbf801160 0x1717
+ 0xbf801170 0x0
+ 0xbf801180 0x52
+ 0xbf801190 0x0
+ 0xbf8011a0 0x0
+ 0xbf8011b0 0x0
+ 0xbf8011c0 0x510
+ 0xbf8011d0 0x4e20
+ 0xbf8011e0 0x8235
+ 0xbf8011f0 0x0
+ 0xbf801200 0x0
+ 0xbf801210 0x0
+ 0xbf801220 0x0
+ 0xbf801230 0x0
+ 0xbf801240 0x0
+ 0xbf801250 0x0
+ 0xbf801260 0x0
+ 0xbf801270 0x0
+ 0xbf801280 0x0
+ 0xbf801290 0x0
+ 0xbf8012a0 0x0
+ 0xbf8012b0 0x0
+ 0xbf8012c0 0x0
+ 0xbf8012d0 0x500
+ 0xbf8012e0 0x0
+
+ 0xbf800060 0x05
+ 0xbf801030 0x100
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/package/uboot-lantiq/arcadyan_psc166_64.conf b/package/uboot-lantiq/arcadyan_psc166_64.conf
new file mode 100644
index 000000000..8cae0c77e
--- /dev/null
+++ b/package/uboot-lantiq/arcadyan_psc166_64.conf
@@ -0,0 +1,141 @@
+ 0xbf800060 0x7
+ 0xbf800010 0x0
+ 0xbf800020 0x0
+ 0xbf800200 0x02
+ 0xbf800210 0x0
+
+;REG32(MC_DC0) = 0x00001B1B;
+ 0xbf801000 0x1b1b
+;REG32(MC_DC1) = 0x00000000;
+ 0xbf801010 0x0
+;REG32(MC_DC2) = 0x00000000;
+ 0xbf801020 0x0
+;REG32(MC_DC3) = 0x00000000;
+ 0xbf801030 0x0
+;REG32(MC_DC4) = 0x00000000;
+ 0xbf801040 0x0
+;REG32(MC_DC5) = 0x00000200;
+ 0xbf801050 0x200
+;REG32(MC_DC6) = 0x00000306;
+; 0xbf801060 0x0306
+ 0xbf801060 0x0605
+;REG32(MC_DC7) = 0x00000303;
+; 0xbf801070 0x302
+; 0xbf801070 0x0203
+ 0xbf801070 0x0303
+;REG32(MC_DC8) = 0x00000102;
+ 0xbf801080 0x102
+;REG32(MC_DC9) = 0x0000070A;
+ 0xbf801090 0x70a
+; 0xbf801090 0x608
+;REG32(MC_DC10) = 0x00000203;
+ 0xbf8010a0 0x203
+;REG32(MC_DC11) = 0x00000C02;
+ 0xbf8010b0 0xc02
+; 0xbf8010b0 0x0a02
+;REG32(MC_DC12) = 0x000001C8;
+ 0xbf8010c0 0x1c8
+;REG32(MC_DC13) = 0x00000001;
+ 0xbf8010d0 0x1
+;REG32(MC_DC14) = 0x00000000;
+ 0xbf8010e0 0x0
+;REG32(MC_DC15) = 0x00000F5F;
+; 0xbf8010f0 0xf5f
+; 0xbf8010f0 0xf3c
+ 0xbf8010f0 0x130
+;REG32(MC_DC16) = 0x0000C800;
+ 0xbf801100 0xc800
+;REG32(MC_DC17) = 0x0000000D;
+; 0xbf801110 0xd
+ 0xbf801110 0xd
+;REG32(MC_DC18) = 0x00000300;
+; 0xbf801120 0x300
+ 0xbf801120 0x301
+;REG32(MC_DC19) = 0x00000300;
+; 0xbf801130 0x300
+ 0xbf801130 0x200
+;REG32(MC_DC20) = 0x00000A04;
+; 0xbf801140 0xa04
+ 0xbf801140 0xa03
+;REG32(MC_DC21) = 0x00001c00;
+; 0xbf801150 0xd00
+; 0xbf801150 0x1f00
+ 0xbf801150 0x1b00
+;REG32(MC_DC22) = 0x00001E1E;
+; 0xbf801160 0xd0d
+; 0xbf801160 0x1f1f
+ 0xbf801160 0x1b1b
+;REG32(MC_DC23) = 0x00000000;
+ 0xbf801170 0x0
+;//Disable ECC
+;REG32(MC_DC24) = 0x0000007F;
+; 0xbf801180 0x7f
+; 0xbf801180 0x062
+; 0xbf801180 0x37f
+ 0xbf801180 0x59
+;REG32(MC_DC25) = 0x00000000;
+ 0xbf801190 0x0
+;REG32(MC_DC26) = 0x00000000;
+ 0xbf8011a0 0x0
+;REG32(MC_DC27) = 0x00000000;
+ 0xbf8011b0 0x0
+;REG32(MC_DC28) = 0x00000A24;
+; 0xbf8011c0 0xa24
+ 0xbf8011c0 0x510
+;REG32(MC_DC29) = 0x00002D89;
+; 0xbf8011d0 0x2d89
+; 0xbf8011d0 0x2d92
+ 0xbf8011d0 0x4e20
+;REG32(MC_DC30) = 0x00000022;
+; 0xbf8011e0 0x8300
+ 0xbf8011e0 0x8235
+;REG32(MC_DC31) = 0x00000000;
+ 0xbf8011f0 0x0
+;REG32(MC_DC32) = 0x00000000;
+ 0xbf801200 0x0
+;REG32(MC_DC33) = 0x00000000;
+ 0xbf801210 0x0
+;REG32(MC_DC34) = 0x00000000;
+ 0xbf801220 0x0
+;REG32(MC_DC35) = 0x00000000;
+ 0xbf801230 0x0
+;REG32(MC_DC36) = 0x00000000;
+ 0xbf801240 0x0
+;REG32(MC_DC37) = 0x00000000;
+ 0xbf801250 0x0
+;REG32(MC_DC38) = 0x00000000;
+ 0xbf801260 0x0
+;REG32(MC_DC39) = 0x00000000;
+ 0xbf801270 0x0
+;REG32(MC_DC40) = 0x00000000;
+ 0xbf801280 0x0
+;REG32(MC_DC41) = 0x00000000;
+ 0xbf801290 0x0
+;REG32(MC_DC42) = 0x00000000;
+ 0xbf8012a0 0x0
+;REG32(MC_DC43) = 0x00000000;
+ 0xbf8012b0 0x0
+;REG32(MC_DC44) = 0x00000000;
+ 0xbf8012c0 0x0
+;REG32(MC_DC45) = 0x00000600;
+ 0xbf8012d0 0x500
+;REG32(MC_DC46) = 0x00000000;
+ 0xbf8012e0 0x0
+
+ 0xbf800060 0x05
+ 0xbf801030 0x100
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/package/uboot-lantiq/easy50712_DDR166M.conf b/package/uboot-lantiq/easy50712_DDR166M.conf
new file mode 100644
index 000000000..351d6a108
--- /dev/null
+++ b/package/uboot-lantiq/easy50712_DDR166M.conf
@@ -0,0 +1,134 @@
+ 0xbf800060 0x7
+ 0xbf800010 0x0
+ 0xbf800020 0x0
+ 0xbf800200 0x02
+ 0xbf800210 0x0
+
+;REG32(MC_DC0) = 0x00001B1B;
+ 0xbf801000 0x1b1b
+;REG32(MC_DC1) = 0x00000000;
+ 0xbf801010 0x0
+;REG32(MC_DC2) = 0x00000000;
+ 0xbf801020 0x0
+;REG32(MC_DC3) = 0x00000000;
+ 0xbf801030 0x0
+;REG32(MC_DC4) = 0x00000000;
+ 0xbf801040 0x0
+;REG32(MC_DC5) = 0x00000200;
+ 0xbf801050 0x200
+;REG32(MC_DC6) = 0x00000306;
+; 0xbf801060 0x0306
+ 0xbf801060 0x0605
+;REG32(MC_DC7) = 0x00000303;
+ 0xbf801070 0x302
+; 0xbf801070 0x0203
+;REG32(MC_DC8) = 0x00000102;
+ 0xbf801080 0x102
+;REG32(MC_DC9) = 0x0000070A;
+ 0xbf801090 0x70a
+; 0xbf801090 0x608
+;REG32(MC_DC10) = 0x00000203;
+ 0xbf8010a0 0x203
+;REG32(MC_DC11) = 0x00000C02;
+ 0xbf8010b0 0xc02
+; 0xbf8010b0 0x0a02
+;REG32(MC_DC12) = 0x000001C8;
+ 0xbf8010c0 0x1c8
+;REG32(MC_DC13) = 0x00000001;
+ 0xbf8010d0 0x1
+;REG32(MC_DC14) = 0x00000000;
+ 0xbf8010e0 0x0
+;REG32(MC_DC15) = 0x00000F5F;
+; 0xbf8010f0 0xf5f
+ 0xbf8010f0 0xf3c
+;REG32(MC_DC16) = 0x0000C800;
+ 0xbf801100 0xc800
+;REG32(MC_DC17) = 0x0000000D;
+; 0xbf801110 0xd
+ 0xbf801110 0xd
+;REG32(MC_DC18) = 0x00000300;
+ 0xbf801120 0x300
+;REG32(MC_DC19) = 0x00000300;
+; 0xbf801130 0x300
+ 0xbf801130 0x200
+;REG32(MC_DC20) = 0x00000A04;
+; 0xbf801140 0xa04
+ 0xbf801140 0xa04
+;REG32(MC_DC21) = 0x00001c00;
+ 0xbf801150 0xd00
+; 0xbf801150 0x1f00
+;REG32(MC_DC22) = 0x00001E1E;
+ 0xbf801160 0xd0d
+; 0xbf801160 0x1f1f
+;REG32(MC_DC23) = 0x00000000;
+ 0xbf801170 0x0
+;//Disable ECC
+;REG32(MC_DC24) = 0x0000007F;
+; 0xbf801180 0x7f
+ 0xbf801180 0x062
+; 0xbf801180 0x37f
+;REG32(MC_DC25) = 0x00000000;
+ 0xbf801190 0x0
+;REG32(MC_DC26) = 0x00000000;
+ 0xbf8011a0 0x0
+;REG32(MC_DC27) = 0x00000000;
+ 0xbf8011b0 0x0
+;REG32(MC_DC28) = 0x00000A24;
+; 0xbf8011c0 0xa24
+ 0xbf8011c0 0x510
+;REG32(MC_DC29) = 0x00002D89;
+ 0xbf8011d0 0x2d89
+; 0xbf8011d0 0x2d92
+;REG32(MC_DC30) = 0x00000022;
+ 0xbf8011e0 0x8300
+; 0xbf8011e0 0x8235
+;REG32(MC_DC31) = 0x00000000;
+ 0xbf8011f0 0x0
+;REG32(MC_DC32) = 0x00000000;
+ 0xbf801200 0x0
+;REG32(MC_DC33) = 0x00000000;
+ 0xbf801210 0x0
+;REG32(MC_DC34) = 0x00000000;
+ 0xbf801220 0x0
+;REG32(MC_DC35) = 0x00000000;
+ 0xbf801230 0x0
+;REG32(MC_DC36) = 0x00000000;
+ 0xbf801240 0x0
+;REG32(MC_DC37) = 0x00000000;
+ 0xbf801250 0x0
+;REG32(MC_DC38) = 0x00000000;
+ 0xbf801260 0x0
+;REG32(MC_DC39) = 0x00000000;
+ 0xbf801270 0x0
+;REG32(MC_DC40) = 0x00000000;
+ 0xbf801280 0x0
+;REG32(MC_DC41) = 0x00000000;
+ 0xbf801290 0x0
+;REG32(MC_DC42) = 0x00000000;
+ 0xbf8012a0 0x0
+;REG32(MC_DC43) = 0x00000000;
+ 0xbf8012b0 0x0
+;REG32(MC_DC44) = 0x00000000;
+ 0xbf8012c0 0x0
+;REG32(MC_DC45) = 0x00000600;
+ 0xbf8012d0 0x500
+;REG32(MC_DC46) = 0x00000000;
+ 0xbf8012e0 0x0
+
+ 0xbf800060 0x05
+ 0xbf801030 0x100
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/package/uboot-lantiq/easy50812.conf b/package/uboot-lantiq/easy50812.conf
new file mode 100644
index 000000000..d28198c2f
--- /dev/null
+++ b/package/uboot-lantiq/easy50812.conf
@@ -0,0 +1,55 @@
+0xbf800060 0x0000000f
+0xbf800010 0x00000000
+0xbf800020 0x00000000
+0xbf800200 0x00000002
+0xbf800210 0x00000000
+0xbf801000 0x00001b1b
+0xbf801010 0x00000000
+0xbf801020 0x00000000
+0xbf801030 0x00000000
+0xbf801040 0x00000000
+0xbf801050 0x00000200
+0xbf801060 0x00000306
+0xbf801070 0x00000303
+0xbf801080 0x00000102
+0xbf801090 0x0000070a
+0xbf8010a0 0x00000203
+0xbf8010b0 0x00000c02
+0xbf8010c0 0x000001c8
+0xbf8010d0 0x00000001
+0xbf8010e0 0x00000000
+0xbf8010f0 0x00000139
+0xbf801100 0x00002200
+0xbf801110 0x0000000d
+0xbf801120 0x00000301
+0xbf801130 0x00000200
+0xbf801140 0x00000a04
+0xbf801150 0x00001800
+0xbf801160 0x00001818
+0xbf801170 0x00000000
+0xbf801180 0x00000059
+0xbf801190 0x00000000
+0xbf8011a0 0x00000000
+0xbf8011b0 0x00000000
+0xbf8011c0 0x00000514
+0xbf8011d0 0x00002d93
+0xbf8011e0 0x00008235
+0xbf8011f0 0x00000000
+0xbf801200 0x00000000
+0xbf801210 0x00000000
+0xbf801220 0x00000000
+0xbf801230 0x00000000
+0xbf801240 0x00000000
+0xbf801250 0x00000000
+0xbf801260 0x00000000
+0xbf801270 0x00000000
+0xbf801280 0x00000000
+0xbf801290 0x00000000
+0xbf8012a0 0x00000000
+0xbf8012b0 0x00000000
+0xbf8012c0 0x00000000
+0xbf8012d0 0x00000600
+0xbf8012e0 0x00000000
+0xbf800060 0x0000000d
+0xbf801030 0x00000100
+
diff --git a/package/uboot-lantiq/files/board/arcadyan/Makefile b/package/uboot-lantiq/files/board/arcadyan/Makefile
new file mode 100644
index 000000000..0038ac4d2
--- /dev/null
+++ b/package/uboot-lantiq/files/board/arcadyan/Makefile
@@ -0,0 +1,62 @@
+#
+# (C) Copyright 2003-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(BOARD).a
+BOOTSTRAP_LIB = $(obj)lib$(BOARD)_bootstrap.a
+
+BOOTSTRAP_LIB-$(CONFIG_BOOTSTRAP) = $(BOOTSTRAP_LIB)
+
+COBJS-y += board.o athrs26_phy.o
+
+SOBJS = lowlevel_init.o pmuenable.o
+
+BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) = $(BOARD)_bootstrap.o
+BOOTSTRAP_SOBJS-$(CONFIG_BOOTSTRAP) = lowlevel_bootstrap_init.o
+
+BOOTSTRAP_SRCS := $(BOOTSTRAP_SOBJS-y:.o=.S) $(BOOTSTRAP_COBJS-y:.o=.c)
+
+SRCS := $(sort $(SOBJS:.o=.S) $(COBJS:.o=.c) $(BOOTSTRAP_SOBJS:.o=.S))
+OBJS := $(addprefix $(obj),$(COBJS-y))
+SOBJS := $(addprefix $(obj),$(SOBJS))
+BOOTSTRAP_OBJS := $(addprefix $(obj),$(BOOTSTRAP_COBJS-y))
+BOOTSTRAP_SOBJS := $(addprefix $(obj),$(BOOTSTRAP_SOBJS-y))
+
+
+all: $(obj).depend $(LIB) $(BOOTSTRAP_LIB)
+
+$(LIB): $(obj).depend $(OBJS) $(SOBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
+
+$(BOOTSTRAP_LIB): $(BOOTSTRAP_OBJS) $(BOOTSTRAP_SOBJS)
+ $(AR) $(ARFLAGS) $@ $(BOOTSTRAP_OBJS) $(BOOTSTRAP_SOBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/package/uboot-lantiq/files/board/arcadyan/arcadyan_bootstrap.c b/package/uboot-lantiq/files/board/arcadyan/arcadyan_bootstrap.c
new file mode 100644
index 000000000..11bf6d0b7
--- /dev/null
+++ b/package/uboot-lantiq/files/board/arcadyan/arcadyan_bootstrap.c
@@ -0,0 +1,48 @@
+/*
+ * (C) Copyright 2010 Industrie Dial Face S.p.A.
+ * Luigi 'Comio' Mantellini, luigi.mantellini@idf-hit.com
+ *
+ * (C) Copyright 2007
+ * Vlad Lungu vlad.lungu@windriver.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/mipsregs.h>
+#include <asm/io.h>
+
+phys_size_t bootstrap_initdram(int board_type)
+{
+ /* Sdram is setup by assembler code */
+ /* If memory could be changed, we should return the true value here */
+ return CONFIG_SYS_MAX_RAM;
+}
+
+int bootstrap_checkboard(void)
+{
+ return 0;
+}
+
+int bootstrap_misc_init_r(void)
+{
+ set_io_port_base(0);
+ return 0;
+}
diff --git a/package/uboot-lantiq/files/board/arcadyan/athrs26_phy.c b/package/uboot-lantiq/files/board/arcadyan/athrs26_phy.c
new file mode 100644
index 000000000..663c4aa20
--- /dev/null
+++ b/package/uboot-lantiq/files/board/arcadyan/athrs26_phy.c
@@ -0,0 +1,812 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved.
+ */
+
+/*
+ * Manage the atheros ethernet PHY.
+ *
+ * All definitions in this file are operating system independent!
+ */
+
+#include <config.h>
+#include <linux/types.h>
+#include <common.h>
+#include <miiphy.h>
+//#include "phy.h"
+//#include "ar7100_soc.h"
+#include "athrs26_phy.h"
+
+#define phy_reg_read(base, addr, reg, datap) \
+ miiphy_read("lq_cpe_eth", addr, reg, datap);
+#define phy_reg_write(base, addr, reg, data) \
+ miiphy_write("lq_cpe_eth", addr, reg, data);
+
+
+/* PHY selections and access functions */
+
+typedef enum {
+ PHY_SRCPORT_INFO,
+ PHY_PORTINFO_SIZE,
+} PHY_CAP_TYPE;
+
+typedef enum {
+ PHY_SRCPORT_NONE,
+ PHY_SRCPORT_VLANTAG,
+ PHY_SRCPORT_TRAILER,
+} PHY_SRCPORT_TYPE;
+
+#ifdef DEBUG
+#define DRV_DEBUG 1
+#endif
+//#define DRV_DEBUG 1
+
+#define DRV_DEBUG_PHYERROR 0x00000001
+#define DRV_DEBUG_PHYCHANGE 0x00000002
+#define DRV_DEBUG_PHYSETUP 0x00000004
+
+#if DRV_DEBUG
+int athrPhyDebug = DRV_DEBUG_PHYERROR|DRV_DEBUG_PHYCHANGE|DRV_DEBUG_PHYSETUP;
+
+#define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) \
+{ \
+ if (athrPhyDebug & (FLG)) { \
+ logMsg(X0, X1, X2, X3, X4, X5, X6); \
+ } \
+}
+
+#define DRV_MSG(x,a,b,c,d,e,f) \
+ logMsg(x,a,b,c,d,e,f)
+
+#define DRV_PRINT(FLG, X) \
+{ \
+ if (athrPhyDebug & (FLG)) { \
+ printf X; \
+ } \
+}
+
+#else /* !DRV_DEBUG */
+#define DRV_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)
+#define DRV_MSG(x,a,b,c,d,e,f)
+#define DRV_PRINT(DBG_SW,X)
+#endif
+
+#define ATHR_LAN_PORT_VLAN 1
+#define ATHR_WAN_PORT_VLAN 2
+
+#define ENET_UNIT_LAN 0
+
+#define TRUE 1
+#define FALSE 0
+
+#define ATHR_PHY0_ADDR 0x0
+#define ATHR_PHY1_ADDR 0x1
+#define ATHR_PHY2_ADDR 0x2
+#define ATHR_PHY3_ADDR 0x3
+#define ATHR_PHY4_ADDR 0x4
+
+/*
+ * Track per-PHY port information.
+ */
+typedef struct {
+ BOOL isEnetPort; /* normal enet port */
+ BOOL isPhyAlive; /* last known state of link */
+ int ethUnit; /* MAC associated with this phy port */
+ uint32_t phyBase;
+ uint32_t phyAddr; /* PHY registers associated with this phy port */
+ uint32_t VLANTableSetting; /* Value to be written to VLAN table */
+} athrPhyInfo_t;
+
+/*
+ * Per-PHY information, indexed by PHY unit number.
+ */
+static athrPhyInfo_t athrPhyInfo[] = {
+ {TRUE, /* phy port 0 -- LAN port 0 */
+ FALSE,
+ ENET_UNIT_LAN,
+ 0,
+ ATHR_PHY0_ADDR,
+ ATHR_LAN_PORT_VLAN
+ },
+
+ {TRUE, /* phy port 1 -- LAN port 1 */
+ FALSE,
+ ENET_UNIT_LAN,
+ 0,
+ ATHR_PHY1_ADDR,
+ ATHR_LAN_PORT_VLAN
+ },
+
+ {TRUE, /* phy port 2 -- LAN port 2 */
+ FALSE,
+ ENET_UNIT_LAN,
+ 0,
+ ATHR_PHY2_ADDR,
+ ATHR_LAN_PORT_VLAN
+ },
+
+ {TRUE, /* phy port 3 -- LAN port 3 */
+ FALSE,
+ ENET_UNIT_LAN,
+ 0,
+ ATHR_PHY3_ADDR,
+ ATHR_LAN_PORT_VLAN
+ },
+
+ {TRUE, /* phy port 4 -- WAN port or LAN port 4 */
+ FALSE,
+ 1,
+ 0,
+ ATHR_PHY4_ADDR,
+ ATHR_LAN_PORT_VLAN /* Send to all ports */
+ },
+
+ {FALSE, /* phy port 5 -- CPU port (no RJ45 connector) */
+ TRUE,
+ ENET_UNIT_LAN,
+ 0,
+ 0x00,
+ ATHR_LAN_PORT_VLAN /* Send to all ports */
+ },
+};
+
+#ifdef CFG_ATHRHDR_EN
+typedef struct {
+ uint8_t data[ATHRHDR_MAX_DATA];
+ uint8_t len;
+ uint32_t seq;
+} cmd_resp_t;
+
+typedef struct {
+ uint16_t reg_addr;
+ uint16_t cmd_len;
+ uint8_t *reg_data;
+}cmd_write_t;
+
+static cmd_write_t cmd_write,cmd_read;
+static cmd_resp_t cmd_resp;
+static struct eth_device *lan_mac;
+//static atomic_t seqcnt = ATOMIC_INIT(0);
+static int seqcnt = 0;
+static int cmd = 1;
+//volatile uchar AthrHdrPkt[60];
+#endif
+
+#define ATHR_GLOBALREGBASE 0
+
+//#define ATHR_PHY_MAX (sizeof(athrPhyInfo) / sizeof(athrPhyInfo[0]))
+#define ATHR_PHY_MAX 5
+
+/* Range of valid PHY IDs is [MIN..MAX] */
+#define ATHR_ID_MIN 0
+#define ATHR_ID_MAX (ATHR_PHY_MAX-1)
+
+/* Convenience macros to access myPhyInfo */
+#define ATHR_IS_ENET_PORT(phyUnit) (athrPhyInfo[phyUnit].isEnetPort)
+#define ATHR_IS_PHY_ALIVE(phyUnit) (athrPhyInfo[phyUnit].isPhyAlive)
+#define ATHR_ETHUNIT(phyUnit) (athrPhyInfo[phyUnit].ethUnit)
+#define ATHR_PHYBASE(phyUnit) (athrPhyInfo[phyUnit].phyBase)
+#define ATHR_PHYADDR(phyUnit) (athrPhyInfo[phyUnit].phyAddr)
+#define ATHR_VLAN_TABLE_SETTING(phyUnit) (athrPhyInfo[phyUnit].VLANTableSetting)
+
+
+#define ATHR_IS_ETHUNIT(phyUnit, ethUnit) \
+ (ATHR_IS_ENET_PORT(phyUnit) && \
+ ATHR_ETHUNIT(phyUnit) == (ethUnit))
+
+#define ATHR_IS_WAN_PORT(phyUnit) (!(ATHR_ETHUNIT(phyUnit)==ENET_UNIT_LAN))
+
+/* Forward references */
+BOOL athrs26_phy_is_link_alive(int phyUnit);
+//static uint32_t athrs26_reg_read(uint16_t reg_addr);
+static void athrs26_reg_write(uint16_t reg_addr,
+ uint32_t reg_val);
+
+/******************************************************************************
+*
+* athrs26_phy_is_link_alive - test to see if the specified link is alive
+*
+* RETURNS:
+* TRUE --> link is alive
+* FALSE --> link is down
+*/
+
+void athrs26_reg_init(void)
+{
+
+ athrs26_reg_write(0x200, 0x200);
+ athrs26_reg_write(0x300, 0x200);
+ athrs26_reg_write(0x400, 0x200);
+ athrs26_reg_write(0x500, 0x200);
+ athrs26_reg_write(0x600, 0x7d);
+
+#ifdef S26_VER_1_0
+ phy_reg_write(0, 0, 29, 41);
+ phy_reg_write(0, 0, 30, 0);
+ phy_reg_write(0, 1, 29, 41);
+ phy_reg_write(0, 1, 30, 0);
+ phy_reg_write(0, 2, 29, 41);
+ phy_reg_write(0, 2, 30, 0);
+ phy_reg_write(0, 3, 29, 41);
+ phy_reg_write(0, 3, 30, 0);
+ phy_reg_write(0, 4, 29, 41);
+ phy_reg_write(0, 4, 30, 0);
+#endif
+
+ athrs26_reg_write(0x38, 0xc000050e);
+
+#ifdef CFG_ATHRHDR_EN
+ athrs26_reg_write(0x104, 0x4804);
+#else
+ athrs26_reg_write(0x104, 0x4004);
+#endif
+
+ athrs26_reg_write(0x60, 0xffffffff);
+ athrs26_reg_write(0x64, 0xaaaaaaaa);
+ athrs26_reg_write(0x68, 0x55555555);
+ athrs26_reg_write(0x6c, 0x0);
+
+ athrs26_reg_write(0x70, 0x41af);
+}
+
+BOOL
+athrs26_phy_is_link_alive(int phyUnit)
+{
+ uint16_t phyHwStatus;
+ uint32_t phyBase;
+ uint32_t phyAddr;
+
+ phyBase = ATHR_PHYBASE(phyUnit);
+ phyAddr = ATHR_PHYADDR(phyUnit);
+
+ phy_reg_read(phyBase, phyAddr, ATHR_PHY_SPEC_STATUS, &phyHwStatus);
+
+ if (phyHwStatus & ATHR_STATUS_LINK_PASS)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/******************************************************************************
+*
+* athrs26_phy_setup - reset and setup the PHY associated with
+* the specified MAC unit number.
+*
+* Resets the associated PHY port.
+*
+* RETURNS:
+* TRUE --> associated PHY is alive
+* FALSE --> no LINKs on this ethernet unit
+*/
+
+BOOL
+athrs26_phy_setup(int ethUnit)
+{
+ int phyUnit;
+ uint16_t phyHwStatus;
+ uint16_t timeout;
+ int liveLinks = 0;
+ uint32_t phyBase = 0;
+ BOOL foundPhy = FALSE;
+ uint32_t phyAddr = 0;
+ uint32_t regVal;
+
+
+ /* See if there's any configuration data for this enet */
+ /* start auto negogiation on each phy */
+ for (phyUnit=0; phyUnit < ATHR_PHY_MAX; phyUnit++) {
+ if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) {
+ continue;
+ }
+
+
+ foundPhy = TRUE;
+ phyBase = ATHR_PHYBASE(phyUnit);
+ phyAddr = ATHR_PHYADDR(phyUnit);
+
+ phy_reg_write(phyBase, phyAddr, ATHR_AUTONEG_ADVERT,
+ ATHR_ADVERTISE_ALL);
+
+ /* Reset PHYs*/
+ phy_reg_write(phyBase, phyAddr, ATHR_PHY_CONTROL,
+ ATHR_CTRL_AUTONEGOTIATION_ENABLE
+ | ATHR_CTRL_SOFTWARE_RESET);
+
+ }
+
+ if (!foundPhy) {
+ return FALSE; /* No PHY's configured for this ethUnit */
+ }
+
+ /*
+ * After the phy is reset, it takes a little while before
+ * it can respond properly.
+ */
+ sysMsDelay(1000);
+
+ /*
+ * Wait up to .75 seconds for ALL associated PHYs to finish
+ * autonegotiation. The only way we get out of here sooner is
+ * if ALL PHYs are connected AND finish autonegotiation.
+ */
+ for (phyUnit=0; (phyUnit < ATHR_PHY_MAX) /*&& (timeout > 0) */; phyUnit++) {
+ if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) {
+ continue;
+ }
+
+ timeout=20;
+ for (;;) {
+ phyHwStatus = 0;
+ phy_reg_read(phyBase, phyAddr, ATHR_PHY_CONTROL, &phyHwStatus);
+
+ if (ATHR_RESET_DONE(phyHwStatus)) {
+ DRV_PRINT(DRV_DEBUG_PHYSETUP,
+ ("Port %d, Neg Success\n", phyUnit));
+ break;
+ }
+ if (timeout == 0) {
+ DRV_PRINT(DRV_DEBUG_PHYSETUP,
+ ("Port %d, Negogiation timeout\n", phyUnit));
+ break;
+ }
+ if (--timeout == 0) {
+ DRV_PRINT(DRV_DEBUG_PHYSETUP,
+ ("Port %d, Negogiation timeout\n", phyUnit));
+ break;
+ }
+
+ sysMsDelay(150);
+ }
+ }
+
+ /*
+ * All PHYs have had adequate time to autonegotiate.
+ * Now initialize software status.
+ *
+ * It's possible that some ports may take a bit longer
+ * to autonegotiate; but we can't wait forever. They'll
+ * get noticed by mv_phyCheckStatusChange during regular
+ * polling activities.
+ */
+ for (phyUnit=0; phyUnit < ATHR_PHY_MAX; phyUnit++) {
+ if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) {
+ continue;
+ }
+
+ if (athrs26_phy_is_link_alive(phyUnit)) {
+ liveLinks++;
+ ATHR_IS_PHY_ALIVE(phyUnit) = TRUE;
+ } else {
+ ATHR_IS_PHY_ALIVE(phyUnit) = FALSE;
+ }
+
+ phy_reg_read(ATHR_PHYBASE(phyUnit), ATHR_PHYADDR(phyUnit),
+ ATHR_PHY_SPEC_STATUS, &regVal);
+ DRV_PRINT(DRV_DEBUG_PHYSETUP,
+ ("eth%d: Phy Specific Status=%4.4x\n", ethUnit, regVal));
+ }
+#if 0
+ /* if using header for register configuration, we have to */
+ /* configure s26 register after frame transmission is enabled */
+
+ athrs26_reg_write(0x200, 0x200);
+ athrs26_reg_write(0x300, 0x200);
+ athrs26_reg_write(0x400, 0x200);
+ athrs26_reg_write(0x500, 0x200);
+ athrs26_reg_write(0x600, 0x200);
+ athrs26_reg_write(0x38, 0x50e);
+#endif
+#ifndef CFG_ATHRHDR_EN
+/* if using header for register configuration, we have to */
+ /* configure s26 register after frame transmission is enabled */
+ athrs26_reg_init();
+#endif
+
+ return (liveLinks > 0);
+}
+
+/******************************************************************************
+*
+* athrs26_phy_is_fdx - Determines whether the phy ports associated with the
+* specified device are FULL or HALF duplex.
+*
+* RETURNS:
+* 1 --> FULL
+* 0 --> HALF
+*/
+int
+athrs26_phy_is_fdx(int ethUnit)
+{
+ int phyUnit;
+ uint32_t phyBase;
+ uint32_t phyAddr;
+ uint16_t phyHwStatus;
+ int ii = 200;
+
+ if (ethUnit == ENET_UNIT_LAN)
+ return TRUE;
+
+ for (phyUnit=0; phyUnit < ATHR_PHY_MAX; phyUnit++) {
+ if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) {
+ continue;
+ }
+
+ if (athrs26_phy_is_link_alive(phyUnit)) {
+
+ phyBase = ATHR_PHYBASE(phyUnit);
+ phyAddr = ATHR_PHYADDR(phyUnit);
+
+ do {
+ phy_reg_read(phyBase, phyAddr, ATHR_PHY_SPEC_STATUS, &phyHwStatus);
+ sysMsDelay(10);
+ } while((!(phyHwStatus & ATHR_STATUS_RESOVLED)) && --ii);
+
+ if (phyHwStatus & ATHER_STATUS_FULL_DEPLEX)
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/******************************************************************************
+*
+* athrs26_phy_speed - Determines the speed of phy ports associated with the
+* specified device.
+*
+* RETURNS:
+* AG7100_PHY_SPEED_10T, AG7100_PHY_SPEED_100TX;
+* AG7100_PHY_SPEED_1000T;
+*/
+
+BOOL
+athrs26_phy_speed(int ethUnit)
+{
+ int phyUnit;
+ uint16_t phyHwStatus;
+ uint32_t phyBase;
+ uint32_t phyAddr;
+ int ii = 200;
+
+ if (ethUnit == ENET_UNIT_LAN)
+ return _100BASET;
+
+ for (phyUnit=0; phyUnit < ATHR_PHY_MAX; phyUnit++) {
+ if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) {
+ continue;
+ }
+
+ if (athrs26_phy_is_link_alive(phyUnit)) {
+
+ phyBase = ATHR_PHYBASE(phyUnit);
+ phyAddr = ATHR_PHYADDR(phyUnit);
+
+ do {
+ phy_reg_read(phyBase, phyAddr,
+ ATHR_PHY_SPEC_STATUS, &phyHwStatus);
+ sysMsDelay(10);
+ }while((!(phyHwStatus & ATHR_STATUS_RESOVLED)) && --ii);
+
+ phyHwStatus = ((phyHwStatus & ATHER_STATUS_LINK_MASK) >>
+ ATHER_STATUS_LINK_SHIFT);
+
+ switch(phyHwStatus) {
+ case 0:
+ return _10BASET;
+ case 1:
+ return _100BASET;
+ case 2:
+ return _1000BASET;
+ default:
+ DRV_PRINT(DRV_DEBUG_PHYERROR, ("Unkown speed read!\n"));
+ }
+ }
+ }
+
+ return _10BASET;
+}
+
+/*****************************************************************************
+*
+* athr_phy_is_up -- checks for significant changes in PHY state.
+*
+* A "significant change" is:
+* dropped link (e.g. ethernet cable unplugged) OR
+* autonegotiation completed + link (e.g. ethernet cable plugged in)
+*
+* When a PHY is plugged in, phyLinkGained is called.
+* When a PHY is unplugged, phyLinkLost is called.
+*/
+
+int
+athrs26_phy_is_up(int ethUnit)
+{
+ int phyUnit;
+ uint16_t phyHwStatus;
+ athrPhyInfo_t *lastStatus;
+ int linkCount = 0;
+ int lostLinks = 0;
+ int gainedLinks = 0;
+ uint32_t phyBase;
+ uint32_t phyAddr;
+#ifdef CFG_ATHRHDR_REG
+ /* if using header to config s26, the link of MAC0 should always be up */
+ if (ethUnit == ENET_UNIT_LAN)
+ return 1;
+#endif
+
+ for (phyUnit=0; phyUnit < ATHR_PHY_MAX; phyUnit++) {
+ if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) {
+ continue;
+ }
+
+ phyBase = ATHR_PHYBASE(phyUnit);
+ phyAddr = ATHR_PHYADDR(phyUnit);
+
+
+ lastStatus = &athrPhyInfo[phyUnit];
+ phy_reg_read(phyBase, phyAddr, ATHR_PHY_SPEC_STATUS, &phyHwStatus);
+
+ if (lastStatus->isPhyAlive) { /* last known link status was ALIVE */
+ /* See if we've lost link */
+ if (phyHwStatus & ATHR_STATUS_LINK_PASS) {
+ linkCount++;
+ } else {
+ lostLinks++;
+ DRV_PRINT(DRV_DEBUG_PHYCHANGE,("\nenet%d port%d down\n",
+ ethUnit, phyUnit));
+ lastStatus->isPhyAlive = FALSE;
+ }
+ } else { /* last known link status was DEAD */
+ /* Check for reset complete */
+ phy_reg_read(phyBase, phyAddr, ATHR_PHY_STATUS, &phyHwStatus);
+ if (!ATHR_RESET_DONE(phyHwStatus))
+ continue;
+
+ /* Check for AutoNegotiation complete */
+ if (ATHR_AUTONEG_DONE(phyHwStatus)) {
+ //printk("autoneg done\n");
+ gainedLinks++;
+ linkCount++;
+ DRV_PRINT(DRV_DEBUG_PHYCHANGE,("\nenet%d port%d up\n",
+ ethUnit, phyUnit));
+ lastStatus->isPhyAlive = TRUE;
+ }
+ }
+ }
+
+ return (linkCount);
+
+#if 0
+ if (linkCount == 0) {
+ if (lostLinks) {
+ /* We just lost the last link for this MAC */
+ phyLinkLost(ethUnit);
+ }
+ } else {
+ if (gainedLinks == linkCount) {
+ /* We just gained our first link(s) for this MAC */
+ phyLinkGained(ethUnit);
+ }
+ }
+#endif
+}
+
+#ifdef CFG_ATHRHDR_EN
+void athr_hdr_timeout(void){
+ eth_halt();
+ NetState = NETLOOP_FAIL;
+}
+
+void athr_hdr_handler(uchar *recv_pkt, unsigned dest, unsigned src, unsigned len){
+ header_receive_pkt(recv_pkt);
+ NetState = NETLOOP_SUCCESS;
+}
+static int
+athrs26_header_config_reg (struct eth_device *dev, uint8_t wr_flag,
+ uint16_t reg_addr, uint16_t cmd_len,
+ uint8_t *val)
+{
+ at_header_t at_header;
+ reg_cmd_t reg_cmd;
+ uchar *AthrHdrPkt;
+
+ AthrHdrPkt = NetTxPacket;
+
+ if(AthrHdrPkt == NULL) {
+ printf("Null packet\n");
+ return;
+ }
+ memset(AthrHdrPkt,0,60);
+
+ /*fill at_header*/
+ at_header.reserved0 = 0x10; //default
+ at_header.priority = 0;
+ at_header.type = 0x5;
+ at_header.broadcast = 0;
+ at_header.from_cpu = 1;
+ at_header.reserved1 = 0x01; //default
+ at_header.port_num = 0;
+
+ AthrHdrPkt[0] = at_header.port_num;
+ AthrHdrPkt[0] |= at_header.reserved1 << 4;
+ AthrHdrPkt[0] |= at_header.from_cpu << 6;
+ AthrHdrPkt[0] |= at_header.broadcast << 7;
+
+ AthrHdrPkt[1] = at_header.type;
+ AthrHdrPkt[1] |= at_header.priority << 4;
+ AthrHdrPkt[1] |= at_header.reserved0 << 6;
+
+
+ /*fill reg cmd*/
+ if(cmd_len > 4)
+ cmd_len = 4;//only support 32bits register r/w
+
+ reg_cmd.reg_addr = reg_addr&0x3FFFC;
+ reg_cmd.cmd_len = cmd_len;
+ reg_cmd.cmd = wr_flag;
+ reg_cmd.reserved2 = 0x5; //default
+ reg_cmd.seq_num = seqcnt;
+
+ AthrHdrPkt[2] = reg_cmd.reg_addr & 0xff;
+ AthrHdrPkt[3] = (reg_cmd.reg_addr & 0xff00) >> 8;
+ AthrHdrPkt[4] = (reg_cmd.reg_addr & 0x30000) >> 16;
+ AthrHdrPkt[4] |= reg_cmd.cmd_len << 4;
+ AthrHdrPkt[5] = reg_cmd.cmd << 4;
+ AthrHdrPkt[5] |= reg_cmd.reserved2 << 5;
+ AthrHdrPkt[6] = (reg_cmd.seq_num & 0x7f) << 1;
+ AthrHdrPkt[7] = (reg_cmd.seq_num & 0x7f80) >> 7;
+ AthrHdrPkt[8] = (reg_cmd.seq_num & 0x7f8000) >> 15;
+ AthrHdrPkt[9] = (reg_cmd.seq_num & 0x7f800000) >> 23;
+
+ /*fill reg data*/
+ if(!wr_flag)//write
+ memcpy((AthrHdrPkt + 10), val, cmd_len);
+
+ /*start xmit*/
+ if(dev == NULL) {
+ printf("ERROR device not found\n");
+ return -1;
+ }
+ header_xmit(dev, AthrHdrPkt ,60);
+ return 0;
+}
+void athr_hdr_func(void) {
+
+ NetSetTimeout (1 * CFG_HZ,athr_hdr_timeout );
+ NetSetHandler (athr_hdr_handler);
+
+ if(cmd)
+ athrs26_header_config_reg(lan_mac, cmd, cmd_read.reg_addr, cmd_read.cmd_len, cmd_read.reg_data);
+ else
+ athrs26_header_config_reg(lan_mac, cmd, cmd_write.reg_addr, cmd_write.cmd_len, cmd_write.reg_data);
+}
+static int
+athrs26_header_write_reg(uint16_t reg_addr, uint16_t cmd_len, uint8_t *reg_data)
+{
+ int i = 2;
+ cmd_write.reg_addr = reg_addr;
+ cmd_write.cmd_len = cmd_len;
+ cmd_write.reg_data = reg_data;
+ cmd = 0;
+ seqcnt++;
+
+ do {
+ if (NetLoop(ATHRHDR) >= 0) /* polls for read/write ack from PHY */
+ break;
+ } while (i--);
+
+ return i;
+}
+
+static int
+athrs26_header_read_reg(uint16_t reg_addr, uint16_t cmd_len, uint8_t *reg_data)
+{
+ int i = 2;
+
+ cmd_read.reg_addr = reg_addr;
+ cmd_read.cmd_len = cmd_len;
+ cmd_read.reg_data = reg_data;
+ cmd = 1;
+ seqcnt++;
+
+ do {
+ if (NetLoop(ATHRHDR) >= 0) /* polls for read/write ack from PHY */
+ break;
+ } while (i--);
+
+ if ((i==0) || (seqcnt != cmd_resp.seq) || (cmd_len != cmd_resp.len)) {
+ return -1;
+ }
+ memcpy (cmd_read.reg_data, cmd_resp.data, cmd_len);
+ return 0;
+}
+int header_receive_pkt(uchar *recv_pkt)
+{
+ cmd_resp.len = recv_pkt[4] >> 4;
+ if (cmd_resp.len > 10)
+ goto out;
+
+ cmd_resp.seq = recv_pkt[6] >> 1;
+ cmd_resp.seq |= recv_pkt[7] << 7;
+ cmd_resp.seq |= recv_pkt[8] << 15;
+ cmd_resp.seq |= recv_pkt[9] << 23;
+
+ if (cmd_resp.seq < seqcnt)
+ goto out;
+ memcpy (cmd_resp.data, (recv_pkt + 10), cmd_resp.len);
+out:
+ return 0;
+}
+
+void athrs26_reg_dev(struct eth_device *mac)
+{
+ lan_mac = mac;
+}
+
+#endif
+
+/*static uint32_t
+athrs26_reg_read(uint16_t reg_addr)
+{
+#ifndef CFG_ATHRHDR_REG
+ uint16_t reg_word_addr = reg_addr / 2, phy_val;
+ uint32_t phy_addr;
+ uint8_t phy_reg;
+
+ phy_addr = 0x18;
+ phy_reg = 0x0;
+ phy_val = (reg_word_addr >> 8) & 0x1ff;
+ phy_reg_write (0, phy_addr, phy_reg, phy_val);
+
+ phy_addr = 0x10 | ((reg_word_addr >> 5) & 0x7);
+ phy_reg = reg_word_addr & 0x1f;
+ phy_reg_read(0, phy_addr, phy_reg, &phy_val);
+
+ return phy_val;
+#else
+ uint8_t reg_data[4];
+
+ memset (reg_data, 0, 4);
+ athrs26_header_read_reg(reg_addr, 4, reg_data);
+ return (reg_data[0] | (reg_data[1] << 8) | (reg_data[2] << 16) | (reg_data[3] << 24));
+#endif
+}
+*/
+static void
+athrs26_reg_write(uint16_t reg_addr, uint32_t reg_val)
+{
+#ifndef CFG_ATHRHDR_REG
+ uint16_t reg_word_addr = reg_addr / 2, phy_val;
+ uint32_t phy_addr;
+ uint8_t phy_reg;
+
+ /* configure register high address */
+ phy_addr = 0x18;
+ phy_reg = 0x0;
+ phy_val = (reg_word_addr >> 8) & 0x1ff; /* bit16-8 of reg address*/
+ phy_reg_write (0, phy_addr, phy_reg, phy_val);
+
+ /* read register with low address */
+ phy_addr = 0x10 | ((reg_word_addr >> 5) & 0x7); /* bit7-5 of reg address */
+ phy_reg = reg_word_addr & 0x1f; /* bit 4-0 of reg address */
+ phy_reg_write (0, phy_addr, phy_reg, reg_val);
+#else
+ uint8_t reg_data[4];
+
+ memset (reg_data, 0, 4);
+ reg_data[0] = (uint8_t)(0x00ff & reg_val);
+ reg_data[1] = (uint8_t)((0xff00 & reg_val) >> 8);
+ reg_data[2] = (uint8_t)((0xff0000 & reg_val) >> 16);
+ reg_data[3] = (uint8_t)((0xff000000 & reg_val) >> 24);
+
+ athrs26_header_write_reg (reg_addr, 4, reg_data);
+#endif
+
+}
+
diff --git a/package/uboot-lantiq/files/board/arcadyan/athrs26_phy.h b/package/uboot-lantiq/files/board/arcadyan/athrs26_phy.h
new file mode 100644
index 000000000..0fdde376e
--- /dev/null
+++ b/package/uboot-lantiq/files/board/arcadyan/athrs26_phy.h
@@ -0,0 +1,134 @@
+#ifndef _ATHRS26_PHY_H
+#define _ATHRS26_PHY_H
+
+/*****************/
+/* PHY Registers */
+/*****************/
+#define ATHR_PHY_CONTROL 0
+#define ATHR_PHY_STATUS 1
+#define ATHR_PHY_ID1 2
+#define ATHR_PHY_ID2 3
+#define ATHR_AUTONEG_ADVERT 4
+#define ATHR_LINK_PARTNER_ABILITY 5
+#define ATHR_AUTONEG_EXPANSION 6
+#define ATHR_NEXT_PAGE_TRANSMIT 7
+#define ATHR_LINK_PARTNER_NEXT_PAGE 8
+#define ATHR_1000BASET_CONTROL 9
+#define ATHR_1000BASET_STATUS 10
+#define ATHR_PHY_SPEC_CONTROL 16
+#define ATHR_PHY_SPEC_STATUS 17
+#define ATHR_DEBUG_PORT_ADDRESS 29
+#define ATHR_DEBUG_PORT_DATA 30
+
+/* ATHR_PHY_CONTROL fields */
+#define ATHR_CTRL_SOFTWARE_RESET 0x8000
+#define ATHR_CTRL_SPEED_LSB 0x2000
+#define ATHR_CTRL_AUTONEGOTIATION_ENABLE 0x1000
+#define ATHR_CTRL_RESTART_AUTONEGOTIATION 0x0200
+#define ATHR_CTRL_SPEED_FULL_DUPLEX 0x0100
+#define ATHR_CTRL_SPEED_MSB 0x0040
+
+#define ATHR_RESET_DONE(phy_control) \
+ (((phy_control) & (ATHR_CTRL_SOFTWARE_RESET)) == 0)
+
+/* Phy status fields */
+#define ATHR_STATUS_AUTO_NEG_DONE 0x0020
+
+#define ATHR_AUTONEG_DONE(ip_phy_status) \
+ (((ip_phy_status) & \
+ (ATHR_STATUS_AUTO_NEG_DONE)) == \
+ (ATHR_STATUS_AUTO_NEG_DONE))
+
+/* Link Partner ability */
+#define ATHR_LINK_100BASETX_FULL_DUPLEX 0x0100
+#define ATHR_LINK_100BASETX 0x0080
+#define ATHR_LINK_10BASETX_FULL_DUPLEX 0x0040
+#define ATHR_LINK_10BASETX 0x0020
+
+/* Advertisement register. */
+#define ATHR_ADVERTISE_NEXT_PAGE 0x8000
+#define ATHR_ADVERTISE_ASYM_PAUSE 0x0800
+#define ATHR_ADVERTISE_PAUSE 0x0400
+#define ATHR_ADVERTISE_100FULL 0x0100
+#define ATHR_ADVERTISE_100HALF 0x0080
+#define ATHR_ADVERTISE_10FULL 0x0040
+#define ATHR_ADVERTISE_10HALF 0x0020
+
+#define ATHR_ADVERTISE_ALL (ATHR_ADVERTISE_10HALF | ATHR_ADVERTISE_10FULL | \
+ ATHR_ADVERTISE_100HALF | ATHR_ADVERTISE_100FULL)
+
+/* 1000BASET_CONTROL */
+#define ATHR_ADVERTISE_1000FULL 0x0200
+
+/* Phy Specific status fields */
+#define ATHER_STATUS_LINK_MASK 0xC000
+#define ATHER_STATUS_LINK_SHIFT 14
+#define ATHER_STATUS_FULL_DEPLEX 0x2000
+#define ATHR_STATUS_LINK_PASS 0x0400
+#define ATHR_STATUS_RESOVLED 0x0800
+
+/*phy debug port register */
+#define ATHER_DEBUG_SERDES_REG 5
+
+/* Serdes debug fields */
+#define ATHER_SERDES_BEACON 0x0100
+
+#ifndef BOOL
+#define BOOL int
+#define TRUE 1
+#define FALSE 0
+#endif
+
+#define sysMsDelay(_x) udelay((_x) * 1000)
+
+#undef S26_VER_1_0
+
+#ifdef CFG_ATHRHDR_EN
+
+#include <net.h>
+#define header_xmit(dev,pkt,len) dev->send(dev,pkt,len) //dev_queue_xmit(skb)
+#define header_recv_ack(dev) dev->recv(dev) //dev_queue_xmit(skb)
+
+typedef enum {
+ NORMAL_PACKET,
+ RESERVED0,
+ MIB_1ST,
+ RESERVED1,
+ RESERVED2,
+ READ_WRITE_REG,
+ READ_WRITE_REG_ACK,
+ RESERVED3
+} ATHR_HDR_TYPE;
+
+typedef struct {
+ uint16_t reserved0;
+ uint16_t priority;
+ uint16_t type ;
+ uint16_t broadcast;
+ uint16_t from_cpu;
+ uint16_t reserved1;
+ uint16_t port_num;
+}at_header_t;
+
+typedef struct {
+ uint64_t reg_addr;
+ uint64_t reserved0;
+ uint64_t cmd_len;
+ uint64_t reserved1;
+ uint64_t cmd;
+ uint64_t reserved2;
+ uint64_t seq_num;
+}reg_cmd_t;
+void athrs26_reg_init(void);
+int header_receive_pkt(uchar *pkt);
+void athrs26_reg_dev(struct eth_device *mac);
+
+#endif
+
+int athrs26_phy_is_up(int unit);
+int athrs26_phy_is_fdx(int unit);
+int athrs26_phy_speed(int unit);
+BOOL athrs26_phy_setup(int unit);
+
+#endif /* _ATHRS26_PHY_H */
+
diff --git a/package/uboot-lantiq/files/board/arcadyan/board.c b/package/uboot-lantiq/files/board/arcadyan/board.c
new file mode 100644
index 000000000..57f460362
--- /dev/null
+++ b/package/uboot-lantiq/files/board/arcadyan/board.c
@@ -0,0 +1,517 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2010
+ * Thomas Langer, Ralph Hempel
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <command.h>
+#include <netdev.h>
+#include <miiphy.h>
+#include <asm/addrspace.h>
+#include <asm/danube.h>
+#include <asm/reboot.h>
+#include <asm/io.h>
+#if defined(CONFIG_CMD_HTTPD)
+#include <httpd.h>
+#endif
+#if defined(CONFIG_PCI)
+#include <pci.h>
+#endif
+#if defined(CONFIG_AR8216_SWITCH)
+#include "athrs26_phy.h"
+#endif
+
+extern ulong ifx_get_ddr_hz(void);
+extern ulong ifx_get_cpuclk(void);
+
+/* IDs and registers of known external switches */
+void _machine_restart(void)
+{
+ *DANUBE_RCU_RST_REQ |=1<<30;
+}
+
+#ifdef CONFIG_SYS_RAMBOOT
+phys_size_t initdram(int board_type)
+{
+ return get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_MAX_RAM);
+}
+#elif defined(CONFIG_USE_DDR_RAM)
+phys_size_t initdram(int board_type)
+{
+ return (CONFIG_SYS_MAX_RAM);
+}
+#else
+
+static ulong max_sdram_size(void) /* per Chip Select */
+{
+ /* The only supported SDRAM data width is 16bit.
+ */
+#define CFG_DW 4
+
+ /* The only supported number of SDRAM banks is 4.
+ */
+#define CFG_NB 4
+
+ ulong cfgpb0 = *DANUBE_SDRAM_MC_CFGPB0;
+ int cols = cfgpb0 & 0xF;
+ int rows = (cfgpb0 & 0xF0) >> 4;
+ ulong size = (1 << (rows + cols)) * CFG_DW * CFG_NB;
+
+ return size;
+}
+
+/*
+ * Check memory range for valid RAM. A simple memory test determines
+ * the actually available RAM size between addresses `base' and
+ * `base + maxsize'.
+ */
+
+static long int dram_size(long int *base, long int maxsize)
+{
+ volatile long int *addr;
+ ulong cnt, val;
+ ulong save[32]; /* to make test non-destructive */
+ unsigned char i = 0;
+
+ for (cnt = (maxsize / sizeof (long)) >> 1; cnt > 0; cnt >>= 1) {
+ addr = base + cnt; /* pointer arith! */
+
+ save[i++] = *addr;
+ *addr = ~cnt;
+ }
+
+ /* write 0 to base address */
+ addr = base;
+ save[i] = *addr;
+ *addr = 0;
+
+ /* check at base address */
+ if ((val = *addr) != 0) {
+ *addr = save[i];
+ return (0);
+ }
+
+ for (cnt = 1; cnt < maxsize / sizeof (long); cnt <<= 1) {
+ addr = base + cnt; /* pointer arith! */
+
+ val = *addr;
+ *addr = save[--i];
+
+ if (val != (~cnt)) {
+ return (cnt * sizeof (long));
+ }
+ }
+ return (maxsize);
+}
+
+phys_size_t initdram(int board_type)
+{
+ int rows, cols, best_val = *DANUBE_SDRAM_MC_CFGPB0;
+ ulong size, max_size = 0;
+ ulong our_address;
+
+ /* load t9 into our_address */
+ asm volatile ("move %0, $25" : "=r" (our_address) :);
+
+ /* Can't probe for RAM size unless we are running from Flash.
+ * find out whether running from DRAM or Flash.
+ */
+ if (CPHYSADDR(our_address) < CPHYSADDR(PHYS_FLASH_1))
+ {
+ return max_sdram_size();
+ }
+
+ for (cols = 0x8; cols <= 0xC; cols++)
+ {
+ for (rows = 0xB; rows <= 0xD; rows++)
+ {
+ *DANUBE_SDRAM_MC_CFGPB0 = (0x14 << 8) |
+ (rows << 4) | cols;
+ size = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE,
+ max_sdram_size());
+
+ if (size > max_size)
+ {
+ best_val = *DANUBE_SDRAM_MC_CFGPB0;
+ max_size = size;
+ }
+ }
+ }
+
+ *DANUBE_SDRAM_MC_CFGPB0 = best_val;
+ return max_size;
+}
+#endif
+
+static void gpio_default(void)
+{
+#ifdef CONFIG_SWITCH_PORT0
+ *DANUBE_GPIO_P0_ALTSEL0 &= ~(1<<CONFIG_SWITCH_PIN);
+ *DANUBE_GPIO_P0_ALTSEL1 &= ~(1<<CONFIG_SWITCH_PIN);
+ *DANUBE_GPIO_P0_OD |= (1<<CONFIG_SWITCH_PIN);
+ *DANUBE_GPIO_P0_DIR |= (1<<CONFIG_SWITCH_PIN);
+ *DANUBE_GPIO_P0_OUT |= (1<<CONFIG_SWITCH_PIN);
+#elif defined(CONFIG_SWITCH_PORT1)
+ *DANUBE_GPIO_P1_ALTSEL0 &= ~(1<<CONFIG_SWITCH_PIN);
+ *DANUBE_GPIO_P1_ALTSEL1 &= ~(1<<CONFIG_SWITCH_PIN);
+ *DANUBE_GPIO_P1_OD |= (1<<CONFIG_SWITCH_PIN);
+ *DANUBE_GPIO_P1_DIR |= (1<<CONFIG_SWITCH_PIN);
+ *DANUBE_GPIO_P1_OUT |= (1<<CONFIG_SWITCH_PIN);
+#endif
+#ifdef CONFIG_EBU_GPIO
+ {
+ int i = 0;
+ printf ("bring up ebu gpio\n");
+ *DANUBE_EBU_BUSCON1 = 0x1e7ff;
+ *DANUBE_EBU_ADDSEL1 = 0x14000001;
+
+ *((volatile u16*)0xb4000000) = 0x0;
+ for(i = 0; i < 1000; i++)
+ udelay(1000);
+ *((volatile u16*)0xb4000000) = CONFIG_EBU_GPIO;
+ *DANUBE_EBU_BUSCON1 = 0x8001e7ff;
+ }
+#endif
+#ifdef CONFIG_BUTTON_PORT0
+ *DANUBE_GPIO_P0_ALTSEL0 &= ~(1<<CONFIG_BUTTON_PIN);
+ *DANUBE_GPIO_P0_ALTSEL1 &= ~(1<<CONFIG_BUTTON_PIN);
+ *DANUBE_GPIO_P0_DIR &= ~(1<<CONFIG_BUTTON_PIN);
+ if(!!(*DANUBE_GPIO_P0_IN & (1<<CONFIG_BUTTON_PIN)) == CONFIG_BUTTON_LEVEL)
+ {
+ printf("button is pressed\n");
+ setenv("bootdelay", "0");
+ setenv("bootcmd", "httpd");
+ }
+#elif defined(CONFIG_BUTTON_PORT1)
+ *DANUBE_GPIO_P1_ALTSEL0 &= ~(1<<CONFIG_BUTTON_PIN);
+ *DANUBE_GPIO_P1_ALTSEL1 &= ~(1<<CONFIG_BUTTON_PIN);
+ *DANUBE_GPIO_P1_DIR &= ~(1<<CONFIG_BUTTON_PIN);
+ if(!!(*DANUBE_GPIO_P1_IN & (1<<CONFIG_BUTTON_PIN)) == CONFIG_BUTTON_LEVEL)
+ {
+ printf("button is pressed\n");
+ setenv("bootdelay", "0");
+ setenv("bootcmd", "httpd");
+ }
+#endif
+#ifdef CONFIG_ARV4525
+ *DANUBE_GPIO_P0_ALTSEL0 &= ~((1<<4)|(1<<5)|(1<<6)|(1<<8)|(1<<9));
+ *DANUBE_GPIO_P0_ALTSEL1 &= ~((1<<4)|(1<<5)|(1<<6)|(1<<8)|(1<<9));
+ *DANUBE_GPIO_P0_OD |= ((1<<4)|(1<<5)|(1<<6)|(1<<8)|(1<<9));
+ *DANUBE_GPIO_P0_DIR |= ((1<<4)|(1<<5)|(1<<6)|(1<<8)|(1<<9));
+ *DANUBE_GPIO_P0_OUT &= ~((1<<4)|(1<<5)|(1<<6)|(1<<8)|(1<<9));
+#endif
+}
+
+int checkboard (void)
+{
+ unsigned long chipid = *DANUBE_MPS_CHIPID;
+ int part_num;
+
+ puts ("Board: "CONFIG_ARCADYAN"\n");
+ puts ("SoC: ");
+
+ part_num = DANUBE_MPS_CHIPID_PARTNUM_GET(chipid);
+ switch (part_num)
+ {
+ case 0x129:
+ case 0x12D:
+ case 0x12b:
+ puts("Danube/Twinpass/Vinax-VE ");
+ break;
+ default:
+ printf ("unknown, chip part number 0x%03X ", part_num);
+ break;
+ }
+ printf ("V1.%ld, ", DANUBE_MPS_CHIPID_VERSION_GET(chipid));
+
+ printf("DDR Speed %ld MHz, ", ifx_get_ddr_hz()/1000000);
+ printf("CPU Speed %ld MHz\n", ifx_get_cpuclk()/1000000);
+
+
+ return 0;
+}
+
+#ifdef CONFIG_SKIP_LOWLEVEL_INIT
+int board_early_init_f(void)
+{
+#ifdef CONFIG_EBU_ADDSEL0
+ (*DANUBE_EBU_ADDSEL0) = CONFIG_EBU_ADDSEL0;
+#endif
+#ifdef CONFIG_EBU_ADDSEL1
+ (*DANUBE_EBU_ADDSEL1) = CONFIG_EBU_ADDSEL1;
+#endif
+#ifdef CONFIG_EBU_ADDSEL2
+ (*DANUBE_EBU_ADDSEL2) = CONFIG_EBU_ADDSEL2;
+#endif
+#ifdef CONFIG_EBU_ADDSEL3
+ (*DANUBE_EBU_ADDSEL3) = CONFIG_EBU_ADDSEL3;
+#endif
+#ifdef CONFIG_EBU_BUSCON0
+ (*DANUBE_EBU_BUSCON0) = CONFIG_EBU_BUSCON0;
+#endif
+#ifdef CONFIG_EBU_BUSCON1
+ (*DANUBE_EBU_BUSCON1) = CONFIG_EBU_BUSCON1;
+#endif
+#ifdef CONFIG_EBU_BUSCON2
+ (*DANUBE_EBU_BUSCON2) = CONFIG_EBU_BUSCON2;
+#endif
+#ifdef CONFIG_EBU_BUSCON3
+ (*DANUBE_EBU_BUSCON3) = CONFIG_EBU_BUSCON3;
+#endif
+
+ return 0;
+}
+#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
+
+#ifdef CONFIG_RTL8306_SWITCH
+#define ID_RTL8306 0x5988
+static int external_switch_rtl8306(void)
+{
+ unsigned short chipid;
+ static char * const name = "lq_cpe_eth";
+
+ udelay(100000);
+
+ puts("\nsearching for rtl8306 switch ... ");
+ if (miiphy_read(name, 4, 30, &chipid) == 0) {
+ if (chipid == ID_RTL8306) {
+ puts("found");
+ /* set led mode */
+ miiphy_write(name, 0, 19, 0xffff);
+ /* magic */
+ miiphy_write(name, 4, 22, 0x877f);
+ puts("\n");
+ return 0;
+ }
+ puts("failed\n");
+ }
+ puts("\nno known switch found ... \n");
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_RTL8306G_SWITCH
+#define ID_RTL8306 0x5988
+
+static int external_switch_rtl8306G(void)
+{
+ unsigned short chipid,val;
+ int i;
+ static char * const name = "lq_cpe_eth";
+ unsigned int chipid2, chipver, chiptype;
+ char str[128];
+ int cpu_mask = 1 << 5;
+ udelay(100000);
+
+ puts("\nsearching for rtl8306 switch ... ");
+ if (miiphy_read(name, 4, 30, &chipid) == 0) {
+ if (chipid == ID_RTL8306) {
+ puts("found\nReset Hard\n");
+#ifdef CONFIG_ARV752DPW
+ //gpio 19
+ //reset reset ping to high
+ *DANUBE_GPIO_P1_DIR |= 8;
+ *DANUBE_GPIO_P1_OUT |= 8;
+ udelay(500*1000);
+ *DANUBE_GPIO_P1_OUT &= ~(8); // now low again for at least 10 ms
+ udelay(500*1000);
+ *DANUBE_GPIO_P1_OUT |= 8;
+ udelay(500*1000);
+ puts("Done\n");
+#endif
+ /* set led mode */
+
+ miiphy_write(name, 0, 0, 0x3100);
+ miiphy_write(name, 0, 18, 0x7fff);
+ miiphy_write(name, 0, 19, 0xffff);
+ miiphy_write(name, 0, 22, 0x877f);
+ miiphy_write(name, 0, 24, 0x0ed1);
+
+ miiphy_write(name, 1, 0, 0x3100);
+ miiphy_write(name, 1, 22, 0x877f);
+ miiphy_write(name, 1, 24, 0x1ed2);
+
+ miiphy_write(name, 2, 0, 0x3100);
+ miiphy_write(name, 2, 22, 0x877f);
+ miiphy_write(name, 2, 23, 0x0020);
+ miiphy_write(name, 2, 24, 0x2ed4);
+
+ miiphy_write(name, 3, 0, 0x3100);
+ miiphy_write(name, 3, 22, 0x877f);
+ miiphy_write(name, 3, 24, 0x3ed8);
+
+ miiphy_write(name, 4, 0, 0x3100);
+ miiphy_write(name, 4, 22, 0x877f);
+ miiphy_write(name, 4, 24, 0x4edf);
+
+ miiphy_write(name, 5, 0, 0x3100);
+ miiphy_write(name, 6, 0, 0x2100);
+
+ //important. enable phy 5 link status, for rmii
+ miiphy_write(name, 6, 22, 0x873f);
+
+ miiphy_write(name, 6, 24, 0x8eff);
+ //disable ports
+ for (i=0;i<5;i++) {
+ miiphy_read(name, 0, 24, &val);
+ val&=~(1<<10);
+ val&=~(1<<11);
+ miiphy_write(name, 0, 24, val);
+ }
+
+ puts("Reset Soft\n");
+ miiphy_write(name,0 ,0 ,1<<15);
+ for (i=0;i<1000;i++)
+ {
+ miiphy_read(name,0 ,0 ,&val);
+ if (!(val&1<<15))
+ break;
+ udelay(1000);
+ }
+ if (i==1000)
+ puts("Failed\n");
+ else
+ puts("Success\n");
+ //enable ports egain
+ for (i=0;i<5;i++) // enable ports
+ {
+ miiphy_read(name, 0, 24, &val);
+ val|=(1<<10);
+ val|=(1<<11);
+ miiphy_write(name, 0, 24, val);
+ }
+ puts("\n");
+ return 0;
+ }
+ puts("failed\n");
+ }
+ puts("\nno known switch found ... \n");
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_AR8216_SWITCH
+static int external_switch_ar8216(void)
+{
+ puts("initializing ar8216 switch... ");
+ if (athrs26_phy_setup(0)==0) {
+ printf("initialized\n");
+ return 0;
+ }
+ puts("failed ... \n");
+ return 0;
+}
+#endif
+
+int board_eth_init(bd_t *bis)
+{
+ gpio_default();
+
+#if defined(CONFIG_IFX_ETOP)
+ uchar enetaddr[6];
+ if (!eth_getenv_enetaddr("ethaddr", enetaddr))
+ eth_setenv_enetaddr("ethaddr", (uchar *)0xb03f0016);
+
+ *DANUBE_PMU_PWDCR &= 0xFFFFEFDF;
+ *DANUBE_PMU_PWDCR &=~(1<<DANUBE_PMU_DMA_SHIFT);/*enable DMA from PMU*/
+
+ if (lq_eth_initialize(bis))
+ return -1;
+
+ *DANUBE_RCU_RST_REQ |=1;
+ udelay(200000);
+ *DANUBE_RCU_RST_REQ &=(unsigned long)~1;
+ udelay(1000);
+
+#ifdef CONFIG_RTL8306G_SWITCH
+ if (external_switch_rtl8306G()<0)
+ return -1;
+#endif
+#ifdef CONFIG_RTL8306_SWITCH
+ if (external_switch_rtl8306()<0)
+ return -1;
+#endif
+#ifdef CONFIG_AR8216_SWITCH
+ if (external_switch_ar8216()<0)
+ return -1;
+#endif
+#endif
+ return 0;
+}
+
+#if defined(CONFIG_CMD_HTTPD)
+int do_http_upgrade(const unsigned char *data, const ulong size)
+{
+ char buf[128];
+
+ if(getenv ("ram_addr") == NULL)
+ return -1;
+ if(getenv ("kernel_addr") == NULL)
+ return -1;
+ /* check the image */
+ if(run_command("imi ${ram_addr}", 0) < 0) {
+ return -1;
+ }
+ /* write the image to the flash */
+ puts("http ugrade ...\n");
+ sprintf(buf, "era ${kernel_addr} +0x%lx; cp.b ${ram_addr} ${kernel_addr} 0x%lx", size, size);
+ return run_command(buf, 0);
+}
+
+int do_http_progress(const int state)
+{
+ /* toggle LED's here */
+ switch(state) {
+ case HTTP_PROGRESS_START:
+ puts("http start\n");
+ break;
+ case HTTP_PROGRESS_TIMEOUT:
+ puts(".");
+ break;
+ case HTTP_PROGRESS_UPLOAD_READY:
+ puts("http upload ready\n");
+ break;
+ case HTTP_PROGRESS_UGRADE_READY:
+ puts("http ugrade ready\n");
+ break;
+ case HTTP_PROGRESS_UGRADE_FAILED:
+ puts("http ugrade failed\n");
+ break;
+ }
+ return 0;
+}
+
+unsigned long do_http_tmp_address(void)
+{
+ char *s = getenv ("ram_addr");
+ if (s) {
+ ulong tmp = simple_strtoul (s, NULL, 16);
+ return tmp;
+ }
+ return 0 /*0x80a00000*/;
+}
+
+#endif
diff --git a/package/uboot-lantiq/files/board/arcadyan/config.mk b/package/uboot-lantiq/files/board/arcadyan/config.mk
new file mode 100644
index 000000000..cc8cd3090
--- /dev/null
+++ b/package/uboot-lantiq/files/board/arcadyan/config.mk
@@ -0,0 +1,36 @@
+#
+# (C) Copyright 2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp
+
+ifdef CONFIG_BOOTSTRAP
+TEXT_BASE = 0x80001000
+CONFIG_BOOTSTRAP_TEXT_BASE = 0xb0000000
+CONFIG_SYS_RAMBOOT = y
+else
+
+ifndef TEXT_BASE
+$(info redefine TEXT_BASE = 0xB0000000 )
+TEXT_BASE = 0xB0000000
+endif
+
+endif
diff --git a/package/uboot-lantiq/files/board/arcadyan/ddr_settings.h b/package/uboot-lantiq/files/board/arcadyan/ddr_settings.h
new file mode 100644
index 000000000..4df6f1170
--- /dev/null
+++ b/package/uboot-lantiq/files/board/arcadyan/ddr_settings.h
@@ -0,0 +1,50 @@
+/* Settings for Denali DDR SDRAM controller */
+/* Optimise for DDR PSC A3S12D40ETP for arv4518pw Danube Board DDR 166 Mhz - by Ngp 14th Sept. 2010 */
+
+#define MC_DC0_VALUE 0x1B1B
+#define MC_DC1_VALUE 0x0
+#define MC_DC2_VALUE 0x0
+#define MC_DC3_VALUE 0x0
+#define MC_DC4_VALUE 0x0
+#define MC_DC5_VALUE 0x200
+#define MC_DC6_VALUE 0x605
+#define MC_DC7_VALUE 0x303
+#define MC_DC8_VALUE 0x102
+#define MC_DC9_VALUE 0x70a
+#define MC_DC10_VALUE 0x203
+#define MC_DC11_VALUE 0xc02
+#define MC_DC12_VALUE 0x1C8
+#define MC_DC13_VALUE 0x1
+#define MC_DC14_VALUE 0x0
+#define MC_DC15_VALUE 0x130 /* WDQS tuning for clk_wr*/
+#define MC_DC16_VALUE 0xC800
+#define MC_DC17_VALUE 0xd
+#define MC_DC18_VALUE 0x301
+#define MC_DC19_VALUE 0x200
+#define MC_DC20_VALUE 0xA03 /* A04 for reference board, A03 for Eval board */
+#define MC_DC21_VALUE 0x1b00
+#define MC_DC22_VALUE 0x1b1b
+#define MC_DC23_VALUE 0x0
+#define MC_DC24_VALUE 0x59 /* WDQS Tuning for DQS */
+#define MC_DC25_VALUE 0x0
+#define MC_DC26_VALUE 0x0
+#define MC_DC27_VALUE 0x0
+#define MC_DC28_VALUE 0x510
+#define MC_DC29_VALUE 0x4e20
+#define MC_DC30_VALUE 0x8235
+#define MC_DC31_VALUE 0x0
+#define MC_DC32_VALUE 0x0
+#define MC_DC33_VALUE 0x0
+#define MC_DC34_VALUE 0x0
+#define MC_DC35_VALUE 0x0
+#define MC_DC36_VALUE 0x0
+#define MC_DC37_VALUE 0x0
+#define MC_DC38_VALUE 0x0
+#define MC_DC39_VALUE 0x0
+#define MC_DC40_VALUE 0x0
+#define MC_DC41_VALUE 0x0
+#define MC_DC42_VALUE 0x0
+#define MC_DC43_VALUE 0x0
+#define MC_DC44_VALUE 0x0
+#define MC_DC45_VALUE 0x500
+#define MC_DC46_VALUE 0x0
diff --git a/package/uboot-lantiq/files/board/arcadyan/ddr_settings_psc_32.h b/package/uboot-lantiq/files/board/arcadyan/ddr_settings_psc_32.h
new file mode 100644
index 000000000..445b7dac1
--- /dev/null
+++ b/package/uboot-lantiq/files/board/arcadyan/ddr_settings_psc_32.h
@@ -0,0 +1,51 @@
+/* Settings for Denali DDR SDRAM controller */
+/* Optimise for PSC DDR A2S56D40CTP for Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 27th Nov 2006 */
+
+#define MC_DC0_VALUE 0x1B1B
+#define MC_DC1_VALUE 0x0
+#define MC_DC2_VALUE 0x0
+#define MC_DC3_VALUE 0x0
+#define MC_DC4_VALUE 0x0
+#define MC_DC5_VALUE 0x200
+#define MC_DC6_VALUE 0x605
+#define MC_DC7_VALUE 0x303
+#define MC_DC8_VALUE 0x102
+#define MC_DC9_VALUE 0x70a
+#define MC_DC10_VALUE 0x203
+#define MC_DC11_VALUE 0xc02
+#define MC_DC12_VALUE 0x1C8
+#define MC_DC13_VALUE 0x1
+#define MC_DC14_VALUE 0x0
+#define MC_DC15_VALUE 0x120 /* WDQS tuning for clk_wr*/
+#define MC_DC16_VALUE 0xC800
+#define MC_DC17_VALUE 0xd
+#define MC_DC18_VALUE 0x301
+#define MC_DC19_VALUE 0x200
+#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */
+#define MC_DC21_VALUE 0x1700
+#define MC_DC22_VALUE 0x1717
+#define MC_DC23_VALUE 0x0
+#define MC_DC24_VALUE 0x52 /* WDQS Tuning for DQS */
+#define MC_DC25_VALUE 0x0
+#define MC_DC26_VALUE 0x0
+#define MC_DC27_VALUE 0x0
+#define MC_DC28_VALUE 0x510
+#define MC_DC29_VALUE 0x4e20
+#define MC_DC30_VALUE 0x8235
+#define MC_DC31_VALUE 0x0
+#define MC_DC32_VALUE 0x0
+#define MC_DC33_VALUE 0x0
+#define MC_DC34_VALUE 0x0
+#define MC_DC35_VALUE 0x0
+#define MC_DC36_VALUE 0x0
+#define MC_DC37_VALUE 0x0
+#define MC_DC38_VALUE 0x0
+#define MC_DC39_VALUE 0x0
+#define MC_DC40_VALUE 0x0
+#define MC_DC41_VALUE 0x0
+#define MC_DC42_VALUE 0x0
+#define MC_DC43_VALUE 0x0
+#define MC_DC44_VALUE 0x0
+#define MC_DC45_VALUE 0x500
+//#define MC_DC45_VALUE 0x400
+#define MC_DC46_VALUE 0x0
diff --git a/package/uboot-lantiq/files/board/arcadyan/ddr_settings_psc_64.h b/package/uboot-lantiq/files/board/arcadyan/ddr_settings_psc_64.h
new file mode 100644
index 000000000..c5afb8e21
--- /dev/null
+++ b/package/uboot-lantiq/files/board/arcadyan/ddr_settings_psc_64.h
@@ -0,0 +1,47 @@
+#define MC_DC0_VALUE 0x1B1B
+#define MC_DC1_VALUE 0x0
+#define MC_DC2_VALUE 0x0
+#define MC_DC3_VALUE 0x0
+#define MC_DC4_VALUE 0x0
+#define MC_DC5_VALUE 0x200
+#define MC_DC6_VALUE 0x605
+#define MC_DC7_VALUE 0x303
+#define MC_DC8_VALUE 0x102
+#define MC_DC9_VALUE 0x70a
+#define MC_DC10_VALUE 0x203
+#define MC_DC11_VALUE 0xc02
+#define MC_DC12_VALUE 0x1C8
+#define MC_DC13_VALUE 0x1
+#define MC_DC14_VALUE 0x0
+#define MC_DC15_VALUE 0x134 /* WDQS tuning for clk_wr*/
+#define MC_DC16_VALUE 0xC800
+#define MC_DC17_VALUE 0xd
+#define MC_DC18_VALUE 0x301
+#define MC_DC19_VALUE 0x200
+#define MC_DC20_VALUE 0xA03 /* A04 for reference board, A03 for Eval board */
+#define MC_DC21_VALUE 0x1400
+#define MC_DC22_VALUE 0x1414
+#define MC_DC23_VALUE 0x0
+#define MC_DC24_VALUE 0x5b /* WDQS Tuning for DQS */
+#define MC_DC25_VALUE 0x0
+#define MC_DC26_VALUE 0x0
+#define MC_DC27_VALUE 0x0
+#define MC_DC28_VALUE 0x510
+#define MC_DC29_VALUE 0x4e20
+#define MC_DC30_VALUE 0x8235
+#define MC_DC31_VALUE 0x0
+#define MC_DC32_VALUE 0x0
+#define MC_DC33_VALUE 0x0
+#define MC_DC34_VALUE 0x0
+#define MC_DC35_VALUE 0x0
+#define MC_DC36_VALUE 0x0
+#define MC_DC37_VALUE 0x0
+#define MC_DC38_VALUE 0x0
+#define MC_DC39_VALUE 0x0
+#define MC_DC40_VALUE 0x0
+#define MC_DC41_VALUE 0x0
+#define MC_DC42_VALUE 0x0
+#define MC_DC43_VALUE 0x0
+#define MC_DC44_VALUE 0x0
+#define MC_DC45_VALUE 0x500
+#define MC_DC46_VALUE 0x0
diff --git a/package/uboot-lantiq/files/board/arcadyan/lowlevel_bootstrap_init.S b/package/uboot-lantiq/files/board/arcadyan/lowlevel_bootstrap_init.S
new file mode 100644
index 000000000..4747ad6db
--- /dev/null
+++ b/package/uboot-lantiq/files/board/arcadyan/lowlevel_bootstrap_init.S
@@ -0,0 +1,583 @@
+/*
+ * Memory sub-system initialization code for Danube board.
+ * Andre Messerschmidt
+ * Copyright (c) 2005 Infineon Technologies AG
+ *
+ * Based on Inca-IP code
+ * Copyright (c) 2003 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+/* History:
+ peng liu May 25, 2006, for PLL setting after reset, 05252006
+ */
+#include <config.h>
+#include <version.h>
+#include <asm/regdef.h>
+
+#if defined(CONFIG_USE_DDR_PSC_32)
+#include "ddr_settings_psc_32.h"
+#define DDR166
+#elif defined(CONFIG_USE_DDR_PSC_64)
+#include "ddr_settings_psc_64.h"
+#define DDR166
+#else
+#error "missing definition for RAM"
+#endif
+
+#define EBU_MODUL_BASE 0xBE105300
+#define EBU_CLC(value) 0x0000(value)
+#define EBU_CON(value) 0x0010(value)
+#define EBU_ADDSEL0(value) 0x0020(value)
+#define EBU_ADDSEL1(value) 0x0024(value)
+#define EBU_ADDSEL2(value) 0x0028(value)
+#define EBU_ADDSEL3(value) 0x002C(value)
+#define EBU_BUSCON0(value) 0x0060(value)
+#define EBU_BUSCON1(value) 0x0064(value)
+#define EBU_BUSCON2(value) 0x0068(value)
+#define EBU_BUSCON3(value) 0x006C(value)
+
+#define MC_MODUL_BASE 0xBF800000
+#define MC_ERRCAUSE(value) 0x0010(value)
+#define MC_ERRADDR(value) 0x0020(value)
+#define MC_CON(value) 0x0060(value)
+
+#define MC_SRAM_ENABLE 0x00000004
+#define MC_SDRAM_ENABLE 0x00000002
+#define MC_DDRRAM_ENABLE 0x00000001
+
+#define MC_SDR_MODUL_BASE 0xBF800200
+#define MC_IOGP(value) 0x0000(value)
+#define MC_CTRLENA(value) 0x0010(value)
+#define MC_MRSCODE(value) 0x0020(value)
+#define MC_CFGDW(value) 0x0030(value)
+#define MC_CFGPB0(value) 0x0040(value)
+#define MC_LATENCY(value) 0x0080(value)
+#define MC_TREFRESH(value) 0x0090(value)
+#define MC_SELFRFSH(value) 0x00A0(value)
+
+#define MC_DDR_MODUL_BASE 0xBF801000
+#define MC_DC00(value) 0x0000(value)
+#define MC_DC01(value) 0x0010(value)
+#define MC_DC02(value) 0x0020(value)
+#define MC_DC03(value) 0x0030(value)
+#define MC_DC04(value) 0x0040(value)
+#define MC_DC05(value) 0x0050(value)
+#define MC_DC06(value) 0x0060(value)
+#define MC_DC07(value) 0x0070(value)
+#define MC_DC08(value) 0x0080(value)
+#define MC_DC09(value) 0x0090(value)
+#define MC_DC10(value) 0x00A0(value)
+#define MC_DC11(value) 0x00B0(value)
+#define MC_DC12(value) 0x00C0(value)
+#define MC_DC13(value) 0x00D0(value)
+#define MC_DC14(value) 0x00E0(value)
+#define MC_DC15(value) 0x00F0(value)
+#define MC_DC16(value) 0x0100(value)
+#define MC_DC17(value) 0x0110(value)
+#define MC_DC18(value) 0x0120(value)
+#define MC_DC19(value) 0x0130(value)
+#define MC_DC20(value) 0x0140(value)
+#define MC_DC21(value) 0x0150(value)
+#define MC_DC22(value) 0x0160(value)
+#define MC_DC23(value) 0x0170(value)
+#define MC_DC24(value) 0x0180(value)
+#define MC_DC25(value) 0x0190(value)
+#define MC_DC26(value) 0x01A0(value)
+#define MC_DC27(value) 0x01B0(value)
+#define MC_DC28(value) 0x01C0(value)
+#define MC_DC29(value) 0x01D0(value)
+#define MC_DC30(value) 0x01E0(value)
+#define MC_DC31(value) 0x01F0(value)
+#define MC_DC32(value) 0x0200(value)
+#define MC_DC33(value) 0x0210(value)
+#define MC_DC34(value) 0x0220(value)
+#define MC_DC35(value) 0x0230(value)
+#define MC_DC36(value) 0x0240(value)
+#define MC_DC37(value) 0x0250(value)
+#define MC_DC38(value) 0x0260(value)
+#define MC_DC39(value) 0x0270(value)
+#define MC_DC40(value) 0x0280(value)
+#define MC_DC41(value) 0x0290(value)
+#define MC_DC42(value) 0x02A0(value)
+#define MC_DC43(value) 0x02B0(value)
+#define MC_DC44(value) 0x02C0(value)
+#define MC_DC45(value) 0x02D0(value)
+#define MC_DC46(value) 0x02E0(value)
+
+#define RCU_OFFSET 0xBF203000
+#define RCU_RST_REQ (RCU_OFFSET + 0x0010)
+#define RCU_STS (RCU_OFFSET + 0x0014)
+
+#define CGU_OFFSET 0xBF103000
+#define PLL0_CFG (CGU_OFFSET + 0x0004)
+#define PLL1_CFG (CGU_OFFSET + 0x0008)
+#define PLL2_CFG (CGU_OFFSET + 0x000C)
+#define CGU_SYS (CGU_OFFSET + 0x0010)
+#define CGU_UPDATE (CGU_OFFSET + 0x0014)
+#define IF_CLK (CGU_OFFSET + 0x0018)
+#define CGU_SMD (CGU_OFFSET + 0x0020)
+#define CGU_CT1SR (CGU_OFFSET + 0x0028)
+#define CGU_CT2SR (CGU_OFFSET + 0x002C)
+#define CGU_PCMCR (CGU_OFFSET + 0x0030)
+#define PCI_CR_PCI (CGU_OFFSET + 0x0034)
+#define CGU_OSC_CTRL (CGU_OFFSET + 0x001C)
+#define CGU_MIPS_PWR_DWN (CGU_OFFSET + 0x0038)
+#define CLK_MEASURE (CGU_OFFSET + 0x003C)
+
+//05252006
+#define pll0_35MHz_CONFIG 0x9D861059
+#define pll1_35MHz_CONFIG 0x1A260CD9
+#define pll2_35MHz_CONFIG 0x8000f1e5
+#define pll0_36MHz_CONFIG 0x1000125D
+#define pll1_36MHz_CONFIG 0x1B1E0C99
+#define pll2_36MHz_CONFIG 0x8002f2a1
+//05252006
+
+//06063001-joelin disable the PCI CFRAME mask -start
+/*CFRAME is an I/O signal, in the chip, the output CFRAME is selected via GPIO altsel pins, so if you select MII1 RXD1, the CFRAME will not come out.
+But the CFRAME input still take the signal from the pad and not disabled when altsel choose other function. So when MII1_RXD1 is low from other device, the EBU interface will be disabled.
+
+The chip function in such a way that disable the CFRAME mask mean EBU not longer check CFRAME to be the device using the bus.
+The side effect is the entire PCI block will see CFRAME low all the time meaning PCI cannot use the bus at all so no more PCI function.
+*/
+#define PCI_CR_PR_OFFSET 0xBE105400
+#define PCI_CR_PCI_MOD_REG (PCI_CR_PR_OFFSET + 0x0030)
+#define PCI_CONFIG_SPACE 0xB7000000
+#define CS_CFM (PCI_CONFIG_SPACE + 0x6C)
+//06063001-joelin disable the PCI CFRAME mask -end
+ .set noreorder
+
+
+/*
+ * void ebu_init(void)
+ */
+ .globl ebu_init
+ .ent ebu_init
+ebu_init:
+
+#if defined(CONFIG_EBU_ADDSEL0) || defined(CONFIG_EBU_ADDSEL1) || \
+ defined(CONFIG_EBU_ADDSEL2) || defined(CONFIG_EBU_ADDSEL3) || \
+ defined(CONFIG_EBU_BUSCON0) || defined(CONFIG_EBU_BUSCON1) || \
+ defined(CONFIG_EBU_BUSCON2) || defined(CONFIG_EBU_BUSCON3)
+
+ li t1, EBU_MODUL_BASE
+#if defined(CONFIG_EBU_ADDSEL0)
+ li t2, CONFIG_EBU_ADDSEL0
+ sw t2, EBU_ADDSEL0(t1)
+#endif
+#if defined(CONFIG_EBU_ADDSEL1)
+ li t2, CONFIG_EBU_ADDSEL1
+ sw t2, EBU_ADDSEL1(t1)
+#endif
+#if defined(CONFIG_EBU_ADDSEL2)
+ li t2, CONFIG_EBU_ADDSEL2
+ sw t2, EBU_ADDSEL2(t1)
+#endif
+#if defined(CONFIG_EBU_ADDSEL3)
+ li t2, CONFIG_EBU_ADDSEL3
+ sw t2, EBU_ADDSEL3(t1)
+#endif
+
+#if defined(CONFIG_EBU_BUSCON0)
+ li t2, CONFIG_EBU_BUSCON0
+ sw t2, EBU_BUSCON0(t1)
+#endif
+#if defined(CONFIG_EBU_BUSCON1)
+ li t2, CONFIG_EBU_BUSCON1
+ sw t2, EBU_BUSCON1(t1)
+#endif
+#if defined(CONFIG_EBU_BUSCON2)
+ li t2, CONFIG_EBU_BUSCON2
+ sw t2, EBU_BUSCON2(t1)
+#endif
+#if defined(CONFIG_EBU_BUSCON3)
+ li t2, CONFIG_EBU_BUSCON3
+ sw t2, EBU_BUSCON3(t1)
+#endif
+
+#endif
+
+ j ra
+ nop
+
+ .end ebu_init
+
+
+/*
+ * void cgu_init(long)
+ *
+ * a0 has the clock value
+ */
+ .globl cgu_init
+ .ent cgu_init
+cgu_init:
+ li t2, CGU_SYS
+ lw t2,0(t2)
+ beq t2,a0,freq_up2date
+ nop
+
+ li t2, RCU_STS
+ lw t2, 0(t2)
+ and t2,0x00020000
+ beq t2,0x00020000,boot_36MHZ
+ nop
+//05252006
+ li t1, PLL0_CFG
+ li t2, pll0_35MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL1_CFG
+ li t2, pll1_35MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL2_CFG
+ li t2, pll2_35MHz_CONFIG
+ sw t2,0(t1)
+ li t1, CGU_SYS
+ sw a0,0(t1)
+ li t1, RCU_RST_REQ
+ li t2, 0x40000008
+ sw t2,0(t1)
+ b wait_reset
+ nop
+boot_36MHZ:
+ li t1, PLL0_CFG
+ li t2, pll0_36MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL1_CFG
+ li t2, pll1_36MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL2_CFG
+ li t2, pll2_36MHz_CONFIG
+ sw t2,0(t1)
+ li t1, CGU_SYS
+ sw a0,0(t1)
+ li t1, RCU_RST_REQ
+ li t2, 0x40000008
+ sw t2,0(t1)
+//05252006
+
+wait_reset:
+ b wait_reset
+ nop
+freq_up2date:
+ j ra
+ nop
+
+ .end cgu_init
+
+#ifndef CONFIG_USE_DDR_RAM
+/*
+ * void sdram_init(long)
+ *
+ * a0 has the clock value
+ */
+ .globl sdram_init
+ .ent sdram_init
+sdram_init:
+
+ /* SDRAM Initialization
+ */
+ li t1, MC_MODUL_BASE
+
+ /* Clear Error log registers */
+ sw zero, MC_ERRCAUSE(t1)
+ sw zero, MC_ERRADDR(t1)
+
+ /* Enable SDRAM module in memory controller */
+ li t3, MC_SDRAM_ENABLE
+ lw t2, MC_CON(t1)
+ or t3, t2, t3
+ sw t3, MC_CON(t1)
+
+ li t1, MC_SDR_MODUL_BASE
+
+ /* disable the controller */
+ li t2, 0
+ sw t2, MC_CTRLENA(t1)
+
+ li t2, 0x822
+ sw t2, MC_IOGP(t1)
+
+ li t2, 0x2
+ sw t2, MC_CFGDW(t1)
+
+ /* Set CAS Latency */
+ li t2, 0x00000020
+ sw t2, MC_MRSCODE(t1)
+
+ /* Set CS0 to SDRAM parameters */
+ li t2, 0x000014d8
+ sw t2, MC_CFGPB0(t1)
+
+ /* Set SDRAM latency parameters */
+ li t2, 0x00036325; /* BC PC100 */
+ sw t2, MC_LATENCY(t1)
+
+ /* Set SDRAM refresh rate */
+ li t2, 0x00000C30
+ sw t2, MC_TREFRESH(t1)
+
+ /* Clear Power-down registers */
+ sw zero, MC_SELFRFSH(t1)
+
+ /* Finally enable the controller */
+ li t2, 1
+ sw t2, MC_CTRLENA(t1)
+
+ j ra
+ nop
+
+ .end sdram_init
+
+#endif /* !CONFIG_USE_DDR_RAM */
+
+#ifdef CONFIG_USE_DDR_RAM
+/*
+ * void ddrram_init(long)
+ *
+ * a0 has the clock value
+ */
+ .globl ddrram_init
+ .ent ddrram_init
+ddrram_init:
+
+ /* DDR-DRAM Initialization
+ */
+ li t1, MC_MODUL_BASE
+
+ /* Clear Error log registers */
+ sw zero, MC_ERRCAUSE(t1)
+ sw zero, MC_ERRADDR(t1)
+
+ /* Enable DDR module in memory controller */
+ li t3, MC_DDRRAM_ENABLE
+ lw t2, MC_CON(t1)
+ or t3, t2, t3
+ sw t3, MC_CON(t1)
+
+ li t1, MC_DDR_MODUL_BASE
+
+ /* Write configuration to DDR controller registers */
+ li t2, MC_DC0_VALUE
+ sw t2, MC_DC00(t1)
+
+ li t2, MC_DC1_VALUE
+ sw t2, MC_DC01(t1)
+
+ li t2, MC_DC2_VALUE
+ sw t2, MC_DC02(t1)
+
+ li t2, MC_DC3_VALUE
+ sw t2, MC_DC03(t1)
+
+ li t2, MC_DC4_VALUE
+ sw t2, MC_DC04(t1)
+
+ li t2, MC_DC5_VALUE
+ sw t2, MC_DC05(t1)
+
+ li t2, MC_DC6_VALUE
+ sw t2, MC_DC06(t1)
+
+ li t2, MC_DC7_VALUE
+ sw t2, MC_DC07(t1)
+
+ li t2, MC_DC8_VALUE
+ sw t2, MC_DC08(t1)
+
+ li t2, MC_DC9_VALUE
+ sw t2, MC_DC09(t1)
+
+ li t2, MC_DC10_VALUE
+ sw t2, MC_DC10(t1)
+
+ li t2, MC_DC11_VALUE
+ sw t2, MC_DC11(t1)
+
+ li t2, MC_DC12_VALUE
+ sw t2, MC_DC12(t1)
+
+ li t2, MC_DC13_VALUE
+ sw t2, MC_DC13(t1)
+
+ li t2, MC_DC14_VALUE
+ sw t2, MC_DC14(t1)
+
+ li t2, MC_DC15_VALUE
+ sw t2, MC_DC15(t1)
+
+ li t2, MC_DC16_VALUE
+ sw t2, MC_DC16(t1)
+
+ li t2, MC_DC17_VALUE
+ sw t2, MC_DC17(t1)
+
+ li t2, MC_DC18_VALUE
+ sw t2, MC_DC18(t1)
+
+ li t2, MC_DC19_VALUE
+ sw t2, MC_DC19(t1)
+
+ li t2, MC_DC20_VALUE
+ sw t2, MC_DC20(t1)
+
+ li t2, MC_DC21_VALUE
+ sw t2, MC_DC21(t1)
+
+ li t2, MC_DC22_VALUE
+ sw t2, MC_DC22(t1)
+
+ li t2, MC_DC23_VALUE
+ sw t2, MC_DC23(t1)
+
+ li t2, MC_DC24_VALUE
+ sw t2, MC_DC24(t1)
+
+ li t2, MC_DC25_VALUE
+ sw t2, MC_DC25(t1)
+
+ li t2, MC_DC26_VALUE
+ sw t2, MC_DC26(t1)
+
+ li t2, MC_DC27_VALUE
+ sw t2, MC_DC27(t1)
+
+ li t2, MC_DC28_VALUE
+ sw t2, MC_DC28(t1)
+
+ li t2, MC_DC29_VALUE
+ sw t2, MC_DC29(t1)
+
+ li t2, MC_DC30_VALUE
+ sw t2, MC_DC30(t1)
+
+ li t2, MC_DC31_VALUE
+ sw t2, MC_DC31(t1)
+
+ li t2, MC_DC32_VALUE
+ sw t2, MC_DC32(t1)
+
+ li t2, MC_DC33_VALUE
+ sw t2, MC_DC33(t1)
+
+ li t2, MC_DC34_VALUE
+ sw t2, MC_DC34(t1)
+
+ li t2, MC_DC35_VALUE
+ sw t2, MC_DC35(t1)
+
+ li t2, MC_DC36_VALUE
+ sw t2, MC_DC36(t1)
+
+ li t2, MC_DC37_VALUE
+ sw t2, MC_DC37(t1)
+
+ li t2, MC_DC38_VALUE
+ sw t2, MC_DC38(t1)
+
+ li t2, MC_DC39_VALUE
+ sw t2, MC_DC39(t1)
+
+ li t2, MC_DC40_VALUE
+ sw t2, MC_DC40(t1)
+
+ li t2, MC_DC41_VALUE
+ sw t2, MC_DC41(t1)
+
+ li t2, MC_DC42_VALUE
+ sw t2, MC_DC42(t1)
+
+ li t2, MC_DC43_VALUE
+ sw t2, MC_DC43(t1)
+
+ li t2, MC_DC44_VALUE
+ sw t2, MC_DC44(t1)
+
+ li t2, MC_DC45_VALUE
+ sw t2, MC_DC45(t1)
+
+ li t2, MC_DC46_VALUE
+ sw t2, MC_DC46(t1)
+
+ li t2, 0x00000100
+ sw t2, MC_DC03(t1)
+
+ j ra
+ nop
+
+ .end ddrram_init
+#endif /* CONFIG_USE_DDR_RAM */
+
+ .globl lowlevel_init
+ .ent lowlevel_init
+lowlevel_init:
+ /* EBU, CGU and SDRAM/DDR-RAM Initialization.
+ */
+ move t0, ra
+ /* We rely on the fact that non of the following ..._init() functions
+ * modify t0
+ */
+#if defined(DDR166)
+ /* 0xe8 means CPU0/CPU1 333M, DDR 167M, FPI 83M, PPE 240M */
+ li a0,0xe8
+#elif defined(DDR133)
+ /* 0xe9 means CPU0/CPU1 333M, DDR 133M, FPI 83M, PPE 240M */
+ li a0,0xe9
+#else /* defined(DDR111) */
+ /* 0xea means CPU0/CPU1 333M, DDR 111M, FPI 83M, PPE 240M */
+ li a0,0xea
+#endif
+ bal cgu_init
+ nop
+
+ bal ebu_init
+ nop
+
+//06063001-joelin disable the PCI CFRAME mask-start
+#ifdef DISABLE_CFRAME
+ li t1, PCI_CR_PCI //mw bf103034 80000000
+ li t2, 0x80000000
+ sw t2,0(t1)
+
+ li t1, PCI_CR_PCI_MOD_REG //mw be105430 103
+ li t2, 0x103
+ sw t2,0(t1)
+
+ li t1, CS_CFM //mw b700006c 0
+ li t2, 0x00
+ sw t2, 0(t1)
+
+ li t1, PCI_CR_PCI_MOD_REG //mw be105430 103
+ li t2, 0x1000103
+ sw t2, 0(t1)
+#endif
+//06063001-joelin disable the PCI CFRAME mask-end
+
+#ifdef CONFIG_USE_DDR_RAM
+ bal ddrram_init
+ nop
+#else
+ bal sdram_init
+ nop
+#endif
+ move ra, t0
+ j ra
+ nop
+
+ .end lowlevel_init
diff --git a/package/uboot-lantiq/files/board/arcadyan/lowlevel_init.S b/package/uboot-lantiq/files/board/arcadyan/lowlevel_init.S
new file mode 100644
index 000000000..d9fe38bc6
--- /dev/null
+++ b/package/uboot-lantiq/files/board/arcadyan/lowlevel_init.S
@@ -0,0 +1,279 @@
+/*
+ * Memory sub-system initialization code for Danube board.
+ * Andre Messerschmidt
+ * Copyright (c) 2005 Infineon Technologies AG
+ *
+ * Based on Inca-IP code
+ * Copyright (c) 2003 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+/* History:
+ peng liu May 25, 2006, for PLL setting after reset, 05252006
+ */
+#include <config.h>
+#include <version.h>
+#include <asm/regdef.h>
+
+#if defined(CONFIG_USE_DDR_PSC_32)
+#include "ddr_settings_psc_32.h"
+#define DDR166
+#elif defined(CONFIG_USE_DDR_PSC_64)
+#include "ddr_settings_psc_64.h"
+#define DDR166
+#else
+#error "missing definition for RAM"
+#endif
+
+#define EBU_MODUL_BASE 0xBE105300
+#define EBU_CLC(value) 0x0000(value)
+#define EBU_CON(value) 0x0010(value)
+#define EBU_ADDSEL0(value) 0x0020(value)
+#define EBU_ADDSEL1(value) 0x0024(value)
+#define EBU_ADDSEL2(value) 0x0028(value)
+#define EBU_ADDSEL3(value) 0x002C(value)
+#define EBU_BUSCON0(value) 0x0060(value)
+#define EBU_BUSCON1(value) 0x0064(value)
+#define EBU_BUSCON2(value) 0x0068(value)
+#define EBU_BUSCON3(value) 0x006C(value)
+
+#define MC_MODUL_BASE 0xBF800000
+#define MC_ERRCAUSE(value) 0x0010(value)
+#define MC_ERRADDR(value) 0x0020(value)
+#define MC_CON(value) 0x0060(value)
+
+#define MC_SRAM_ENABLE 0x00000004
+#define MC_SDRAM_ENABLE 0x00000002
+#define MC_DDRRAM_ENABLE 0x00000001
+
+#define MC_SDR_MODUL_BASE 0xBF800200
+#define MC_IOGP(value) 0x0000(value)
+#define MC_CTRLENA(value) 0x0010(value)
+#define MC_MRSCODE(value) 0x0020(value)
+#define MC_CFGDW(value) 0x0030(value)
+#define MC_CFGPB0(value) 0x0040(value)
+#define MC_LATENCY(value) 0x0080(value)
+#define MC_TREFRESH(value) 0x0090(value)
+#define MC_SELFRFSH(value) 0x00A0(value)
+
+#define MC_DDR_MODUL_BASE 0xBF801000
+#define MC_DC00(value) 0x0000(value)
+#define MC_DC01(value) 0x0010(value)
+#define MC_DC02(value) 0x0020(value)
+#define MC_DC03(value) 0x0030(value)
+#define MC_DC04(value) 0x0040(value)
+#define MC_DC05(value) 0x0050(value)
+#define MC_DC06(value) 0x0060(value)
+#define MC_DC07(value) 0x0070(value)
+#define MC_DC08(value) 0x0080(value)
+#define MC_DC09(value) 0x0090(value)
+#define MC_DC10(value) 0x00A0(value)
+#define MC_DC11(value) 0x00B0(value)
+#define MC_DC12(value) 0x00C0(value)
+#define MC_DC13(value) 0x00D0(value)
+#define MC_DC14(value) 0x00E0(value)
+#define MC_DC15(value) 0x00F0(value)
+#define MC_DC16(value) 0x0100(value)
+#define MC_DC17(value) 0x0110(value)
+#define MC_DC18(value) 0x0120(value)
+#define MC_DC19(value) 0x0130(value)
+#define MC_DC20(value) 0x0140(value)
+#define MC_DC21(value) 0x0150(value)
+#define MC_DC22(value) 0x0160(value)
+#define MC_DC23(value) 0x0170(value)
+#define MC_DC24(value) 0x0180(value)
+#define MC_DC25(value) 0x0190(value)
+#define MC_DC26(value) 0x01A0(value)
+#define MC_DC27(value) 0x01B0(value)
+#define MC_DC28(value) 0x01C0(value)
+#define MC_DC29(value) 0x01D0(value)
+#define MC_DC30(value) 0x01E0(value)
+#define MC_DC31(value) 0x01F0(value)
+#define MC_DC32(value) 0x0200(value)
+#define MC_DC33(value) 0x0210(value)
+#define MC_DC34(value) 0x0220(value)
+#define MC_DC35(value) 0x0230(value)
+#define MC_DC36(value) 0x0240(value)
+#define MC_DC37(value) 0x0250(value)
+#define MC_DC38(value) 0x0260(value)
+#define MC_DC39(value) 0x0270(value)
+#define MC_DC40(value) 0x0280(value)
+#define MC_DC41(value) 0x0290(value)
+#define MC_DC42(value) 0x02A0(value)
+#define MC_DC43(value) 0x02B0(value)
+#define MC_DC44(value) 0x02C0(value)
+#define MC_DC45(value) 0x02D0(value)
+#define MC_DC46(value) 0x02E0(value)
+
+#define RCU_OFFSET 0xBF203000
+#define RCU_RST_REQ (RCU_OFFSET + 0x0010)
+#define RCU_STS (RCU_OFFSET + 0x0014)
+
+#define CGU_OFFSET 0xBF103000
+#define PLL0_CFG (CGU_OFFSET + 0x0004)
+#define PLL1_CFG (CGU_OFFSET + 0x0008)
+#define PLL2_CFG (CGU_OFFSET + 0x000C)
+#define CGU_SYS (CGU_OFFSET + 0x0010)
+#define CGU_UPDATE (CGU_OFFSET + 0x0014)
+#define IF_CLK (CGU_OFFSET + 0x0018)
+#define CGU_SMD (CGU_OFFSET + 0x0020)
+#define CGU_CT1SR (CGU_OFFSET + 0x0028)
+#define CGU_CT2SR (CGU_OFFSET + 0x002C)
+#define CGU_PCMCR (CGU_OFFSET + 0x0030)
+#define PCI_CR_PCI (CGU_OFFSET + 0x0034)
+#define CGU_OSC_CTRL (CGU_OFFSET + 0x001C)
+#define CGU_MIPS_PWR_DWN (CGU_OFFSET + 0x0038)
+#define CLK_MEASURE (CGU_OFFSET + 0x003C)
+
+//05252006
+#define pll0_35MHz_CONFIG 0x9D861059
+#define pll1_35MHz_CONFIG 0x1A260CD9
+#define pll2_35MHz_CONFIG 0x8000f1e5
+#define pll0_36MHz_CONFIG 0x1000125D
+#define pll1_36MHz_CONFIG 0x1B1E0C99
+#define pll2_36MHz_CONFIG 0x8002f2a1
+//05252006
+
+//06063001-joelin disable the PCI CFRAME mask -start
+/*CFRAME is an I/O signal, in the chip, the output CFRAME is selected via GPIO altsel pins, so if you select MII1 RXD1, the CFRAME will not come out.
+But the CFRAME input still take the signal from the pad and not disabled when altsel choose other function. So when MII1_RXD1 is low from other device, the EBU interface will be disabled.
+
+The chip function in such a way that disable the CFRAME mask mean EBU not longer check CFRAME to be the device using the bus.
+The side effect is the entire PCI block will see CFRAME low all the time meaning PCI cannot use the bus at all so no more PCI function.
+*/
+#define PCI_CR_PR_OFFSET 0xBE105400
+#define PCI_CR_PCI_MOD_REG (PCI_CR_PR_OFFSET + 0x0030)
+#define PCI_CONFIG_SPACE 0xB7000000
+#define CS_CFM (PCI_CONFIG_SPACE + 0x6C)
+//06063001-joelin disable the PCI CFRAME mask -end
+ .set noreorder
+
+
+/*
+ * void ebu_init(void)
+ */
+ .globl ebu_init
+ .ent ebu_init
+ebu_init:
+
+ j ra
+ nop
+
+ .end ebu_init
+
+
+/*
+ * void cgu_init(long)
+ *
+ * a0 has the clock value
+ */
+ .globl cgu_init
+ .ent cgu_init
+cgu_init:
+ li t2, CGU_SYS
+ lw t2,0(t2)
+ beq t2,a0,freq_up2date
+ nop
+
+ li t2, RCU_STS
+ lw t2, 0(t2)
+ and t2,0x00020000
+ beq t2,0x00020000,boot_36MHZ
+ nop
+//05252006
+ li t1, PLL0_CFG
+ li t2, pll0_35MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL1_CFG
+ li t2, pll1_35MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL2_CFG
+ li t2, pll2_35MHz_CONFIG
+ sw t2,0(t1)
+ li t1, CGU_SYS
+ sw a0,0(t1)
+ li t1, RCU_RST_REQ
+ li t2, 0x40000008
+ sw t2,0(t1)
+ b wait_reset
+ nop
+boot_36MHZ:
+ li t1, PLL0_CFG
+ li t2, pll0_36MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL1_CFG
+ li t2, pll1_36MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL2_CFG
+ li t2, pll2_36MHz_CONFIG
+ sw t2,0(t1)
+ li t1, CGU_SYS
+ sw a0,0(t1)
+ li t1, RCU_RST_REQ
+ li t2, 0x40000008
+ sw t2,0(t1)
+//05252006
+
+wait_reset:
+ b wait_reset
+ nop
+freq_up2date:
+ j ra
+ nop
+
+ .end cgu_init
+
+ .globl lowlevel_init
+ .ent lowlevel_init
+lowlevel_init:
+ /* EBU, CGU and SDRAM/DDR-RAM Initialization.
+ */
+ move t0, ra
+ /* We rely on the fact that non of the following ..._init() functions
+ * modify t0
+ */
+
+ bal ebu_init
+ nop
+
+//06063001-joelin disable the PCI CFRAME mask-start
+#ifdef DISABLE_CFRAME
+ li t1, PCI_CR_PCI //mw bf103034 80000000
+ li t2, 0x80000000
+ sw t2,0(t1)
+
+ li t1, PCI_CR_PCI_MOD_REG //mw be105430 103
+ li t2, 0x103
+ sw t2,0(t1)
+
+ li t1, CS_CFM //mw b700006c 0
+ li t2, 0x00
+ sw t2, 0(t1)
+
+ li t1, PCI_CR_PCI_MOD_REG //mw be105430 103
+ li t2, 0x1000103
+ sw t2, 0(t1)
+#endif
+//06063001-joelin disable the PCI CFRAME mask-end
+
+ move ra, t0
+ j ra
+ nop
+
+ .end lowlevel_init
diff --git a/package/uboot-lantiq/files/board/arcadyan/pmuenable.S b/package/uboot-lantiq/files/board/arcadyan/pmuenable.S
new file mode 100644
index 000000000..e0d7971d8
--- /dev/null
+++ b/package/uboot-lantiq/files/board/arcadyan/pmuenable.S
@@ -0,0 +1,48 @@
+/*
+ * Power Management unit initialization code for AMAZON development board.
+ *
+ * Copyright (c) 2003 Ou Ke, Infineon.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <config.h>
+#include <version.h>
+#include <asm/regdef.h>
+
+#define PMU_PWDCR 0xBF10201C
+#define PMU_SR 0xBF102020
+
+ .globl pmuenable
+
+pmuenable:
+ li t0, PMU_PWDCR
+ li t1, 0x2 /* enable everything */
+ sw t1, 0(t0)
+#if 0
+1:
+ li t0, PMU_SR
+ lw t2, 0(t0)
+ bne t1, t2, 1b
+ nop
+#endif
+ j ra
+ nop
+
+
diff --git a/package/uboot-lantiq/files/board/arcadyan/u-boot-bootstrap.lds b/package/uboot-lantiq/files/board/arcadyan/u-boot-bootstrap.lds
new file mode 100644
index 000000000..52d7dafad
--- /dev/null
+++ b/package/uboot-lantiq/files/board/arcadyan/u-boot-bootstrap.lds
@@ -0,0 +1,74 @@
+/*
+ * (C) Copyright 2010 Industrie Dial Face S.p.A.
+ * Luigi 'Comio' Mantellini, luigi.mantellini@idf-hit.com
+ *
+ * (C) Copyright 2003
+ * Wolfgang Denk Engineering, <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+/*
+OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-bigmips")
+*/
+OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradlittlemips")
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = .;
+ _gp = ALIGN(16) +0x7ff0;
+
+ .got : {
+ __got_start = .;
+ *(.got)
+ __got_end = .;
+ }
+
+ . = ALIGN(4);
+ .sdata : { *(.sdata) }
+
+ . = .;
+ . = ALIGN(4);
+ .payload : { *(.payload) }
+ . = ALIGN(4);
+
+ uboot_end_data = .;
+ num_got_entries = (__got_end - __got_start) >> 2;
+
+ . = ALIGN(4);
+ .sbss : { *(.sbss) }
+ .bss : { *(.bss) . = ALIGN(4); }
+ uboot_end = .;
+}
+
diff --git a/package/uboot-lantiq/files/board/arcadyan/u-boot.lds b/package/uboot-lantiq/files/board/arcadyan/u-boot.lds
new file mode 100644
index 000000000..9a6cd1b8a
--- /dev/null
+++ b/package/uboot-lantiq/files/board/arcadyan/u-boot.lds
@@ -0,0 +1,70 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk Engineering, <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+/*
+OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-bigmips")
+*/
+OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradbigmips")
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = .;
+ _gp = ALIGN(16) + 0x7ff0;
+
+ .got : {
+ __got_start = .;
+ *(.got)
+ __got_end = .;
+ }
+
+ .sdata : { *(.sdata) }
+
+ .u_boot_cmd : {
+ __u_boot_cmd_start = .;
+ *(.u_boot_cmd)
+ __u_boot_cmd_end = .;
+ }
+
+ uboot_end_data = .;
+ num_got_entries = (__got_end - __got_start) >> 2;
+
+ . = ALIGN(4);
+ .sbss (NOLOAD) : { *(.sbss) }
+ .bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
+ uboot_end = .;
+}
diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/Makefile b/package/uboot-lantiq/files/board/infineon/easy50712/Makefile
new file mode 100644
index 000000000..67570505d
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50712/Makefile
@@ -0,0 +1,62 @@
+#
+# (C) Copyright 2003-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(BOARD).a
+BOOTSTRAP_LIB = $(obj)lib$(BOARD)_bootstrap.a
+
+BOOTSTRAP_LIB-$(CONFIG_BOOTSTRAP) = $(BOOTSTRAP_LIB)
+
+COBJS-y += danube.o
+
+SOBJS = lowlevel_init.o pmuenable.o
+
+BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) = $(BOARD)_bootstrap.o
+BOOTSTRAP_SOBJS-$(CONFIG_BOOTSTRAP) = lowlevel_bootstrap_init.o
+
+BOOTSTRAP_SRCS := $(BOOTSTRAP_SOBJS-y:.o=.S) $(BOOTSTRAP_COBJS-y:.o=.c)
+
+SRCS := $(sort $(SOBJS:.o=.S) $(COBJS:.o=.c) $(BOOTSTRAP_SOBJS:.o=.S))
+OBJS := $(addprefix $(obj),$(COBJS-y))
+SOBJS := $(addprefix $(obj),$(SOBJS))
+BOOTSTRAP_OBJS := $(addprefix $(obj),$(BOOTSTRAP_COBJS-y))
+BOOTSTRAP_SOBJS := $(addprefix $(obj),$(BOOTSTRAP_SOBJS-y))
+
+
+all: $(obj).depend $(LIB) $(BOOTSTRAP_LIB)
+
+$(LIB): $(obj).depend $(OBJS) $(SOBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
+
+$(BOOTSTRAP_LIB): $(BOOTSTRAP_OBJS) $(BOOTSTRAP_SOBJS)
+ $(AR) $(ARFLAGS) $@ $(BOOTSTRAP_OBJS) $(BOOTSTRAP_SOBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/config.mk b/package/uboot-lantiq/files/board/infineon/easy50712/config.mk
new file mode 100644
index 000000000..b110f6f32
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50712/config.mk
@@ -0,0 +1,40 @@
+#
+# (C) Copyright 2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+
+#
+# Danube board with MIPS 24Kc CPU core
+#
+sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp
+
+ifdef CONFIG_BOOTSTRAP
+TEXT_BASE = 0x80001000
+CONFIG_BOOTSTRAP_TEXT_BASE = 0xb0000000
+CONFIG_SYS_RAMBOOT = y
+else
+
+ifndef TEXT_BASE
+$(info redefine TEXT_BASE = 0xB0000000 )
+TEXT_BASE = 0xB0000000
+endif
+
+endif
diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/danube.c b/package/uboot-lantiq/files/board/infineon/easy50712/danube.c
new file mode 100644
index 000000000..e3845cb38
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50712/danube.c
@@ -0,0 +1,436 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2010
+ * Thomas Langer, Ralph Hempel
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <command.h>
+#include <netdev.h>
+#include <miiphy.h>
+#include <asm/addrspace.h>
+#include <asm/danube.h>
+#include <asm/reboot.h>
+#include <asm/io.h>
+#if defined(CONFIG_CMD_HTTPD)
+#include <httpd.h>
+#endif
+
+extern ulong ifx_get_ddr_hz(void);
+extern ulong ifx_get_cpuclk(void);
+
+/* definitions for external PHYs / Switches */
+/* Split values into phy address and register address */
+#define PHYADDR(_reg) ((_reg >> 5) & 0xff), (_reg & 0x1f)
+
+/* IDs and registers of known external switches */
+#define ID_SAMURAI_0 0x1020
+#define ID_SAMURAI_1 0x0007
+#define SAMURAI_ID_REG0 0xA0
+#define SAMURAI_ID_REG1 0xA1
+
+#define ID_TANTOS 0x2599
+
+void _machine_restart(void)
+{
+ *DANUBE_RCU_RST_REQ |=1<<30;
+}
+
+#ifdef CONFIG_SYS_RAMBOOT
+phys_size_t initdram(int board_type)
+{
+ return get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_MAX_RAM);
+}
+#elif defined(CONFIG_USE_DDR_RAM)
+phys_size_t initdram(int board_type)
+{
+ return (CONFIG_SYS_MAX_RAM);
+}
+#else
+
+static ulong max_sdram_size(void) /* per Chip Select */
+{
+ /* The only supported SDRAM data width is 16bit.
+ */
+#define CFG_DW 4
+
+ /* The only supported number of SDRAM banks is 4.
+ */
+#define CFG_NB 4
+
+ ulong cfgpb0 = *DANUBE_SDRAM_MC_CFGPB0;
+ int cols = cfgpb0 & 0xF;
+ int rows = (cfgpb0 & 0xF0) >> 4;
+ ulong size = (1 << (rows + cols)) * CFG_DW * CFG_NB;
+
+ return size;
+}
+
+/*
+ * Check memory range for valid RAM. A simple memory test determines
+ * the actually available RAM size between addresses `base' and
+ * `base + maxsize'.
+ */
+
+static long int dram_size(long int *base, long int maxsize)
+{
+ volatile long int *addr;
+ ulong cnt, val;
+ ulong save[32]; /* to make test non-destructive */
+ unsigned char i = 0;
+
+ for (cnt = (maxsize / sizeof (long)) >> 1; cnt > 0; cnt >>= 1) {
+ addr = base + cnt; /* pointer arith! */
+
+ save[i++] = *addr;
+ *addr = ~cnt;
+ }
+
+ /* write 0 to base address */
+ addr = base;
+ save[i] = *addr;
+ *addr = 0;
+
+ /* check at base address */
+ if ((val = *addr) != 0) {
+ *addr = save[i];
+ return (0);
+ }
+
+ for (cnt = 1; cnt < maxsize / sizeof (long); cnt <<= 1) {
+ addr = base + cnt; /* pointer arith! */
+
+ val = *addr;
+ *addr = save[--i];
+
+ if (val != (~cnt)) {
+ return (cnt * sizeof (long));
+ }
+ }
+ return (maxsize);
+}
+
+phys_size_t initdram(int board_type)
+{
+ int rows, cols, best_val = *DANUBE_SDRAM_MC_CFGPB0;
+ ulong size, max_size = 0;
+ ulong our_address;
+
+ /* load t9 into our_address */
+ asm volatile ("move %0, $25" : "=r" (our_address) :);
+
+ /* Can't probe for RAM size unless we are running from Flash.
+ * find out whether running from DRAM or Flash.
+ */
+ if (CPHYSADDR(our_address) < CPHYSADDR(PHYS_FLASH_1))
+ {
+ return max_sdram_size();
+ }
+
+ for (cols = 0x8; cols <= 0xC; cols++)
+ {
+ for (rows = 0xB; rows <= 0xD; rows++)
+ {
+ *DANUBE_SDRAM_MC_CFGPB0 = (0x14 << 8) |
+ (rows << 4) | cols;
+ size = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE,
+ max_sdram_size());
+
+ if (size > max_size)
+ {
+ best_val = *DANUBE_SDRAM_MC_CFGPB0;
+ max_size = size;
+ }
+ }
+ }
+
+ *DANUBE_SDRAM_MC_CFGPB0 = best_val;
+ return max_size;
+}
+#endif
+
+int checkboard (void)
+{
+ unsigned long chipid = *DANUBE_MPS_CHIPID;
+ int part_num;
+
+ puts ("Board: ");
+
+ part_num = DANUBE_MPS_CHIPID_PARTNUM_GET(chipid);
+ switch (part_num)
+ {
+ case 0x129:
+ case 0x12B:
+ case 0x12D:
+ puts("Danube/Twinpass/Vinax-VE ");
+ break;
+ default:
+ printf ("unknown, chip part number 0x%03X ", part_num);
+ break;
+ }
+ printf ("V1.%ld, ", DANUBE_MPS_CHIPID_VERSION_GET(chipid));
+
+ printf("DDR Speed %ld MHz, ", ifx_get_ddr_hz()/1000000);
+ printf("CPU Speed %ld MHz\n", ifx_get_cpuclk()/1000000);
+
+ return 0;
+}
+
+#ifdef CONFIG_SKIP_LOWLEVEL_INIT
+int board_early_init_f(void)
+{
+#ifdef CONFIG_EBU_ADDSEL0
+ (*DANUBE_EBU_ADDSEL0) = CONFIG_EBU_ADDSEL0;
+#endif
+#ifdef CONFIG_EBU_ADDSEL1
+ (*DANUBE_EBU_ADDSEL1) = CONFIG_EBU_ADDSEL1;
+#endif
+#ifdef CONFIG_EBU_ADDSEL2
+ (*DANUBE_EBU_ADDSEL2) = CONFIG_EBU_ADDSEL2;
+#endif
+#ifdef CONFIG_EBU_ADDSEL3
+ (*DANUBE_EBU_ADDSEL3) = CONFIG_EBU_ADDSEL3;
+#endif
+#ifdef CONFIG_EBU_BUSCON0
+ (*DANUBE_EBU_BUSCON0) = CONFIG_EBU_BUSCON0;
+#endif
+#ifdef CONFIG_EBU_BUSCON1
+ (*DANUBE_EBU_BUSCON1) = CONFIG_EBU_BUSCON1;
+#endif
+#ifdef CONFIG_EBU_BUSCON2
+ (*DANUBE_EBU_BUSCON2) = CONFIG_EBU_BUSCON2;
+#endif
+#ifdef CONFIG_EBU_BUSCON3
+ (*DANUBE_EBU_BUSCON3) = CONFIG_EBU_BUSCON3;
+#endif
+
+ return 0;
+}
+#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
+
+#ifdef CONFIG_EXTRA_SWITCH
+static int external_switch_init(void)
+{
+ unsigned short chipid0=0xdead, chipid1=0xbeef;
+ static char * const name = "lq_cpe_eth";
+
+#ifdef CONFIG_SWITCH_PORT0
+ *DANUBE_GPIO_P0_ALTSEL0 &= ~(1<<CONFIG_SWITCH_PIN);
+ *DANUBE_GPIO_P0_ALTSEL1 &= ~(1<<CONFIG_SWITCH_PIN);
+ *DANUBE_GPIO_P0_OD |= (1<<CONFIG_SWITCH_PIN);
+ *DANUBE_GPIO_P0_DIR |= (1<<CONFIG_SWITCH_PIN);
+ *DANUBE_GPIO_P0_OUT |= (1<<CONFIG_SWITCH_PIN);
+#elif defined(CONFIG_SWITCH_PORT1)
+ *DANUBE_GPIO_P1_ALTSEL0 &= ~(1<<CONFIG_SWITCH_PIN);
+ *DANUBE_GPIO_P1_ALTSEL1 &= ~(1<<CONFIG_SWITCH_PIN);
+ *DANUBE_GPIO_P1_OD |= (1<<CONFIG_SWITCH_PIN);
+ *DANUBE_GPIO_P1_DIR |= (1<<CONFIG_SWITCH_PIN);
+ *DANUBE_GPIO_P1_OUT |= (1<<CONFIG_SWITCH_PIN);
+#endif
+#ifdef CLK_OUT2_25MHZ
+ *DANUBE_GPIO_P0_DIR=0x0000ae78;
+ *DANUBE_GPIO_P0_ALTSEL0=0x00008078;
+ //joelin for Mii-1 *DANUBE_GPIO_P0_ALTSEL1=0x80000080;
+ *DANUBE_GPIO_P0_ALTSEL1=0x80000000; //joelin for Mii-1
+ *DANUBE_CGU_IFCCR=0x00400010;
+ *DANUBE_GPIO_P0_OD=0x0000ae78;
+#endif
+
+ /* earlier no valid response is available, at least on Twinpass & Tantos @ 111MHz, M4530 platform */
+ udelay(100000);
+
+ debug("\nsearching for Samurai switch ... ");
+ if ( (miiphy_read(name, PHYADDR(SAMURAI_ID_REG0), &chipid0)==0) &&
+ (miiphy_read(name, PHYADDR(SAMURAI_ID_REG1), &chipid1)==0) ) {
+ if (((chipid0 & 0xFFF0) == ID_SAMURAI_0) &&
+ ((chipid1 & 0x000F) == ID_SAMURAI_1)) {
+ debug("found");
+
+ /* enable "Crossover Auto Detect" + defaults */
+ /* P0 */
+ miiphy_write(name, PHYADDR(0x01), 0x840F);
+ /* P1 */
+ miiphy_write(name, PHYADDR(0x03), 0x840F);
+ /* P2 */
+ miiphy_write(name, PHYADDR(0x05), 0x840F);
+ /* P3 */
+ miiphy_write(name, PHYADDR(0x07), 0x840F);
+ /* P4 */
+ miiphy_write(name, PHYADDR(0x08), 0x840F);
+ /* P5 */
+ miiphy_write(name, PHYADDR(0x09), 0x840F);
+ /* System Control 4: CPU on port 1 and other */
+ miiphy_write(name, PHYADDR(0x12), 0x3602);
+ #ifdef CLK_OUT2_25MHZ
+ /* Bandwidth Control Enable Register: enable */
+ miiphy_write(name, PHYADDR(0x33), 0x4000);
+ #endif
+ }
+ }
+
+ debug("\nsearching for TANTOS switch ... ");
+ if (miiphy_read(name, PHYADDR(0x101), &chipid0) == 0) {
+ if (chipid0 == ID_TANTOS) {
+ debug("found");
+
+ /* P5 Basic Control: Force Link Up */
+ miiphy_write(name, PHYADDR(0xA1), 0x0004);
+ /* P6 Basic Control: Force Link Up */
+ miiphy_write(name, PHYADDR(0xC1), 0x0004);
+ /* RGMII/MII Port Control (P4/5/6) */
+ miiphy_write(name, PHYADDR(0xF5), 0x0773);
+
+ /* Software workaround. */
+ /* PHY reset from P0 to P4. */
+
+ /* set data for indirect write */
+ miiphy_write(name, PHYADDR(0x121), 0x8000);
+
+ /* P0 */
+ miiphy_write(name, PHYADDR(0x120), 0x0400);
+ udelay(1000);
+ /* P1 */
+ miiphy_write(name, PHYADDR(0x120), 0x0420);
+ udelay(1000);
+ /* P2 */
+ miiphy_write(name, PHYADDR(0x120), 0x0440);
+ udelay(1000);
+ /* P3 */
+ miiphy_write(name, PHYADDR(0x120), 0x0460);
+ udelay(1000);
+ /* P4 */
+ miiphy_write(name, PHYADDR(0x120), 0x0480);
+ udelay(1000);
+ }
+ }
+ debug("\n");
+
+ return 0;
+}
+#endif /* CONFIG_EXTRA_SWITCH */
+
+int board_gpio_init(void)
+{
+#ifdef CONFIG_BUTTON_PORT0
+ *DANUBE_GPIO_P0_ALTSEL0 &= ~(1<<CONFIG_BUTTON_PIN);
+ *DANUBE_GPIO_P0_ALTSEL1 &= ~(1<<CONFIG_BUTTON_PIN);
+ *DANUBE_GPIO_P0_DIR &= ~(1<<CONFIG_BUTTON_PIN);
+ if(!!(*DANUBE_GPIO_P0_IN & (1<<CONFIG_BUTTON_PIN)) == CONFIG_BUTTON_LEVEL)
+ {
+ printf("button is pressed\n");
+ setenv("bootdelay", "0");
+ setenv("bootcmd", "httpd");
+ }
+#elif defined(CONFIG_BUTTON_PORT1)
+ *DANUBE_GPIO_P1_ALTSEL0 &= ~(1<<CONFIG_BUTTON_PIN);
+ *DANUBE_GPIO_P1_ALTSEL1 &= ~(1<<CONFIG_BUTTON_PIN);
+ *DANUBE_GPIO_P1_DIR &= ~(1<<CONFIG_BUTTON_PIN);
+ if(!!(*DANUBE_GPIO_P1_IN & (1<<CONFIG_BUTTON_PIN)) == CONFIG_BUTTON_LEVEL)
+ {
+ printf("button is pressed\n");
+ setenv("bootdelay", "0");
+ setenv("bootcmd", "httpd");
+ }
+#endif
+}
+
+int board_eth_init(bd_t *bis)
+{
+
+ board_gpio_init();
+
+#if defined(CONFIG_IFX_ETOP)
+
+ *DANUBE_PMU_PWDCR &= 0xFFFFEFDF;
+ *DANUBE_PMU_PWDCR &=~(1<<DANUBE_PMU_DMA_SHIFT);/*enable DMA from PMU*/
+
+ if (lq_eth_initialize(bis)<0)
+ return -1;
+
+ *DANUBE_RCU_RST_REQ |=1;
+ udelay(200000);
+ *DANUBE_RCU_RST_REQ &=(unsigned long)~1;
+ udelay(1000);
+
+#ifdef CONFIG_EXTRA_SWITCH
+ if (external_switch_init()<0)
+ return -1;
+#endif /* CONFIG_EXTRA_SWITCH */
+#endif /* CONFIG_IFX_ETOP */
+
+ return 0;
+}
+
+#if defined(CONFIG_CMD_HTTPD)
+int do_http_upgrade(const unsigned char *data, const ulong size)
+{
+ char buf[128];
+
+ if(getenv ("ram_addr") == NULL)
+ return -1;
+ if(getenv ("kernel_addr") == NULL)
+ return -1;
+ /* check the image */
+ if(run_command("imi ${ram_addr}", 0) < 0) {
+ return -1;
+ }
+ /* write the image to the flash */
+ puts("http ugrade ...\n");
+ sprintf(buf, "era ${kernel_addr} +0x%x; cp.b ${ram_addr} ${kernel_addr} 0x%x", size, size);
+ return run_command(buf, 0);
+}
+
+int do_http_progress(const int state)
+{
+ /* toggle LED's here */
+ switch(state) {
+ case HTTP_PROGRESS_START:
+ puts("http start\n");
+ break;
+ case HTTP_PROGRESS_TIMEOUT:
+ puts(".");
+ break;
+ case HTTP_PROGRESS_UPLOAD_READY:
+ puts("http upload ready\n");
+ break;
+ case HTTP_PROGRESS_UGRADE_READY:
+ puts("http ugrade ready\n");
+ break;
+ case HTTP_PROGRESS_UGRADE_FAILED:
+ puts("http ugrade failed\n");
+ break;
+ }
+ return 0;
+}
+
+unsigned long do_http_tmp_address(void)
+{
+ char *s = getenv ("ram_addr");
+ if (s) {
+ ulong tmp = simple_strtoul (s, NULL, 16);
+ return tmp;
+ }
+ return 0 /*0x80a00000*/;
+}
+
+#endif
diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings.h b/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings.h
new file mode 100644
index 000000000..3a4b1350e
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings.h
@@ -0,0 +1,50 @@
+/* Settings for Denali DDR SDRAM controller */
+/* Optimise for Danube Eval Board DDR 167 Mhz - by Ng Aik Ann 29th April */
+#define MC_DC0_VALUE 0x1B1B
+#define MC_DC1_VALUE 0x0
+#define MC_DC2_VALUE 0x0
+#define MC_DC3_VALUE 0x0
+#define MC_DC4_VALUE 0x0
+#define MC_DC5_VALUE 0x200
+#define MC_DC6_VALUE 0x605
+#define MC_DC7_VALUE 0x303
+#define MC_DC8_VALUE 0x102
+#define MC_DC9_VALUE 0x70a
+#define MC_DC10_VALUE 0x203
+#define MC_DC11_VALUE 0xc02
+#define MC_DC12_VALUE 0x1C8
+#define MC_DC13_VALUE 0x1
+#define MC_DC14_VALUE 0x0
+#define MC_DC15_VALUE 0xf3c
+#define MC_DC16_VALUE 0xC800
+#define MC_DC17_VALUE 0xd
+#define MC_DC18_VALUE 0x300
+#define MC_DC19_VALUE 0x200
+#define MC_DC20_VALUE 0xA03
+#define MC_DC21_VALUE 0x1d00
+#define MC_DC22_VALUE 0x1d1d
+#define MC_DC23_VALUE 0x0
+#define MC_DC24_VALUE 0x5e /* was 0x7f */
+#define MC_DC25_VALUE 0x0
+#define MC_DC26_VALUE 0x0
+#define MC_DC27_VALUE 0x0
+#define MC_DC28_VALUE 0x510
+#define MC_DC29_VALUE 0x2d89
+#define MC_DC30_VALUE 0x8300
+#define MC_DC31_VALUE 0x0
+#define MC_DC32_VALUE 0x0
+#define MC_DC33_VALUE 0x0
+#define MC_DC34_VALUE 0x0
+#define MC_DC35_VALUE 0x0
+#define MC_DC36_VALUE 0x0
+#define MC_DC37_VALUE 0x0
+#define MC_DC38_VALUE 0x0
+#define MC_DC39_VALUE 0x0
+#define MC_DC40_VALUE 0x0
+#define MC_DC41_VALUE 0x0
+#define MC_DC42_VALUE 0x0
+#define MC_DC43_VALUE 0x0
+#define MC_DC44_VALUE 0x0
+#define MC_DC45_VALUE 0x500
+//#define MC_DC45_VALUE 0x400
+#define MC_DC46_VALUE 0x0
diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_PROMOSDDR400.h b/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_PROMOSDDR400.h
new file mode 100644
index 000000000..54bb6c9e3
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_PROMOSDDR400.h
@@ -0,0 +1,50 @@
+/* Settings for Denali DDR SDRAM controller */
+/* Optimise for Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 29th April */
+#define MC_DC0_VALUE 0x1B1B
+#define MC_DC1_VALUE 0x0
+#define MC_DC2_VALUE 0x0
+#define MC_DC3_VALUE 0x0
+#define MC_DC4_VALUE 0x0
+#define MC_DC5_VALUE 0x200
+#define MC_DC6_VALUE 0x605
+#define MC_DC7_VALUE 0x303
+#define MC_DC8_VALUE 0x102
+#define MC_DC9_VALUE 0x70a
+#define MC_DC10_VALUE 0x203
+#define MC_DC11_VALUE 0xa02
+#define MC_DC12_VALUE 0x1C8
+#define MC_DC13_VALUE 0x0
+#define MC_DC14_VALUE 0x0
+#define MC_DC15_VALUE 0xf3c /* WDQS tuning for clk_wr*/
+#define MC_DC16_VALUE 0xC800
+#define MC_DC17_VALUE 0xd
+#define MC_DC18_VALUE 0x300
+#define MC_DC19_VALUE 0x200
+#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */
+#define MC_DC21_VALUE 0x1200
+#define MC_DC22_VALUE 0x1212
+#define MC_DC23_VALUE 0x0
+#define MC_DC24_VALUE 0x62 /* WDQS Tuning for DQS */
+#define MC_DC25_VALUE 0x0
+#define MC_DC26_VALUE 0x0
+#define MC_DC27_VALUE 0x0
+#define MC_DC28_VALUE 0x510
+#define MC_DC29_VALUE 0x4e20
+#define MC_DC30_VALUE 0x8300
+#define MC_DC31_VALUE 0x0
+#define MC_DC32_VALUE 0x0
+#define MC_DC33_VALUE 0x0
+#define MC_DC34_VALUE 0x0
+#define MC_DC35_VALUE 0x0
+#define MC_DC36_VALUE 0x0
+#define MC_DC37_VALUE 0x0
+#define MC_DC38_VALUE 0x0
+#define MC_DC39_VALUE 0x0
+#define MC_DC40_VALUE 0x0
+#define MC_DC41_VALUE 0x0
+#define MC_DC42_VALUE 0x0
+#define MC_DC43_VALUE 0x0
+#define MC_DC44_VALUE 0x0
+#define MC_DC45_VALUE 0x500
+//#define MC_DC45_VALUE 0x400
+#define MC_DC46_VALUE 0x0
diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_Samsung_166.h b/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_Samsung_166.h
new file mode 100644
index 000000000..7975c3ec0
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_Samsung_166.h
@@ -0,0 +1,51 @@
+/* Settings for Denali DDR SDRAM controller */
+/* Optimise for Samsung DDR K4H561638H Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 27th Nov 2006 */
+
+#define MC_DC0_VALUE 0x1B1B
+#define MC_DC1_VALUE 0x0
+#define MC_DC2_VALUE 0x0
+#define MC_DC3_VALUE 0x0
+#define MC_DC4_VALUE 0x0
+#define MC_DC5_VALUE 0x200
+#define MC_DC6_VALUE 0x605
+#define MC_DC7_VALUE 0x303
+#define MC_DC8_VALUE 0x102
+#define MC_DC9_VALUE 0x70a
+#define MC_DC10_VALUE 0x203
+#define MC_DC11_VALUE 0xc02
+#define MC_DC12_VALUE 0x1C8
+#define MC_DC13_VALUE 0x1
+#define MC_DC14_VALUE 0x0
+#define MC_DC15_VALUE 0x120 /* WDQS tuning for clk_wr*/
+#define MC_DC16_VALUE 0xC800
+#define MC_DC17_VALUE 0xd
+#define MC_DC18_VALUE 0x301
+#define MC_DC19_VALUE 0x200
+#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */
+#define MC_DC21_VALUE 0x1400
+#define MC_DC22_VALUE 0x1414
+#define MC_DC23_VALUE 0x0
+#define MC_DC24_VALUE 0x4e /* WDQS Tuning for DQS */
+#define MC_DC25_VALUE 0x0
+#define MC_DC26_VALUE 0x0
+#define MC_DC27_VALUE 0x0
+#define MC_DC28_VALUE 0x510
+#define MC_DC29_VALUE 0x2d93
+#define MC_DC30_VALUE 0x8235
+#define MC_DC31_VALUE 0x0
+#define MC_DC32_VALUE 0x0
+#define MC_DC33_VALUE 0x0
+#define MC_DC34_VALUE 0x0
+#define MC_DC35_VALUE 0x0
+#define MC_DC36_VALUE 0x0
+#define MC_DC37_VALUE 0x0
+#define MC_DC38_VALUE 0x0
+#define MC_DC39_VALUE 0x0
+#define MC_DC40_VALUE 0x0
+#define MC_DC41_VALUE 0x0
+#define MC_DC42_VALUE 0x0
+#define MC_DC43_VALUE 0x0
+#define MC_DC44_VALUE 0x0
+#define MC_DC45_VALUE 0x500
+//#define MC_DC45_VALUE 0x400
+#define MC_DC46_VALUE 0x0
diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_e111.h b/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_e111.h
new file mode 100644
index 000000000..b655ca289
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_e111.h
@@ -0,0 +1,50 @@
+/* Settings for Denali DDR SDRAM controller */
+/* Optimise for Danube Eval Board DDR 167 Mhz - by Ng Aik Ann 29th April */
+#define MC_DC0_VALUE 0x1B1B
+#define MC_DC1_VALUE 0x0
+#define MC_DC2_VALUE 0x0
+#define MC_DC3_VALUE 0x0
+#define MC_DC4_VALUE 0x0
+#define MC_DC5_VALUE 0x200
+#define MC_DC6_VALUE 0x605
+#define MC_DC7_VALUE 0x303
+#define MC_DC8_VALUE 0x102
+#define MC_DC9_VALUE 0x70a
+#define MC_DC10_VALUE 0x203
+#define MC_DC11_VALUE 0xc02
+#define MC_DC12_VALUE 0x1C8
+#define MC_DC13_VALUE 0x1
+#define MC_DC14_VALUE 0x0
+#define MC_DC15_VALUE 0xf3c /* WDQS tuning for clk_wr*/
+#define MC_DC16_VALUE 0xC800
+#define MC_DC17_VALUE 0xd
+#define MC_DC18_VALUE 0x300
+#define MC_DC19_VALUE 0x200
+#define MC_DC20_VALUE 0xA03 /* A04 for reference board, A03 for Eval board */
+#define MC_DC21_VALUE 0x1800
+#define MC_DC22_VALUE 0x1818
+#define MC_DC23_VALUE 0x0
+#define MC_DC24_VALUE 0x5e /* WDQS Tuning for DQS */
+#define MC_DC25_VALUE 0x0
+#define MC_DC26_VALUE 0x0
+#define MC_DC27_VALUE 0x0
+#define MC_DC28_VALUE 0x510
+#define MC_DC29_VALUE 0x2d89
+#define MC_DC30_VALUE 0x8300
+#define MC_DC31_VALUE 0x0
+#define MC_DC32_VALUE 0x0
+#define MC_DC33_VALUE 0x0
+#define MC_DC34_VALUE 0x0
+#define MC_DC35_VALUE 0x0
+#define MC_DC36_VALUE 0x0
+#define MC_DC37_VALUE 0x0
+#define MC_DC38_VALUE 0x0
+#define MC_DC39_VALUE 0x0
+#define MC_DC40_VALUE 0x0
+#define MC_DC41_VALUE 0x0
+#define MC_DC42_VALUE 0x0
+#define MC_DC43_VALUE 0x0
+#define MC_DC44_VALUE 0x0
+#define MC_DC45_VALUE 0x500
+//#define MC_DC45_VALUE 0x400
+#define MC_DC46_VALUE 0x0
diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_e166.h b/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_e166.h
new file mode 100644
index 000000000..b655ca289
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_e166.h
@@ -0,0 +1,50 @@
+/* Settings for Denali DDR SDRAM controller */
+/* Optimise for Danube Eval Board DDR 167 Mhz - by Ng Aik Ann 29th April */
+#define MC_DC0_VALUE 0x1B1B
+#define MC_DC1_VALUE 0x0
+#define MC_DC2_VALUE 0x0
+#define MC_DC3_VALUE 0x0
+#define MC_DC4_VALUE 0x0
+#define MC_DC5_VALUE 0x200
+#define MC_DC6_VALUE 0x605
+#define MC_DC7_VALUE 0x303
+#define MC_DC8_VALUE 0x102
+#define MC_DC9_VALUE 0x70a
+#define MC_DC10_VALUE 0x203
+#define MC_DC11_VALUE 0xc02
+#define MC_DC12_VALUE 0x1C8
+#define MC_DC13_VALUE 0x1
+#define MC_DC14_VALUE 0x0
+#define MC_DC15_VALUE 0xf3c /* WDQS tuning for clk_wr*/
+#define MC_DC16_VALUE 0xC800
+#define MC_DC17_VALUE 0xd
+#define MC_DC18_VALUE 0x300
+#define MC_DC19_VALUE 0x200
+#define MC_DC20_VALUE 0xA03 /* A04 for reference board, A03 for Eval board */
+#define MC_DC21_VALUE 0x1800
+#define MC_DC22_VALUE 0x1818
+#define MC_DC23_VALUE 0x0
+#define MC_DC24_VALUE 0x5e /* WDQS Tuning for DQS */
+#define MC_DC25_VALUE 0x0
+#define MC_DC26_VALUE 0x0
+#define MC_DC27_VALUE 0x0
+#define MC_DC28_VALUE 0x510
+#define MC_DC29_VALUE 0x2d89
+#define MC_DC30_VALUE 0x8300
+#define MC_DC31_VALUE 0x0
+#define MC_DC32_VALUE 0x0
+#define MC_DC33_VALUE 0x0
+#define MC_DC34_VALUE 0x0
+#define MC_DC35_VALUE 0x0
+#define MC_DC36_VALUE 0x0
+#define MC_DC37_VALUE 0x0
+#define MC_DC38_VALUE 0x0
+#define MC_DC39_VALUE 0x0
+#define MC_DC40_VALUE 0x0
+#define MC_DC41_VALUE 0x0
+#define MC_DC42_VALUE 0x0
+#define MC_DC43_VALUE 0x0
+#define MC_DC44_VALUE 0x0
+#define MC_DC45_VALUE 0x500
+//#define MC_DC45_VALUE 0x400
+#define MC_DC46_VALUE 0x0
diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_psc_166.h b/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_psc_166.h
new file mode 100644
index 000000000..445b7dac1
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_psc_166.h
@@ -0,0 +1,51 @@
+/* Settings for Denali DDR SDRAM controller */
+/* Optimise for PSC DDR A2S56D40CTP for Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 27th Nov 2006 */
+
+#define MC_DC0_VALUE 0x1B1B
+#define MC_DC1_VALUE 0x0
+#define MC_DC2_VALUE 0x0
+#define MC_DC3_VALUE 0x0
+#define MC_DC4_VALUE 0x0
+#define MC_DC5_VALUE 0x200
+#define MC_DC6_VALUE 0x605
+#define MC_DC7_VALUE 0x303
+#define MC_DC8_VALUE 0x102
+#define MC_DC9_VALUE 0x70a
+#define MC_DC10_VALUE 0x203
+#define MC_DC11_VALUE 0xc02
+#define MC_DC12_VALUE 0x1C8
+#define MC_DC13_VALUE 0x1
+#define MC_DC14_VALUE 0x0
+#define MC_DC15_VALUE 0x120 /* WDQS tuning for clk_wr*/
+#define MC_DC16_VALUE 0xC800
+#define MC_DC17_VALUE 0xd
+#define MC_DC18_VALUE 0x301
+#define MC_DC19_VALUE 0x200
+#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */
+#define MC_DC21_VALUE 0x1700
+#define MC_DC22_VALUE 0x1717
+#define MC_DC23_VALUE 0x0
+#define MC_DC24_VALUE 0x52 /* WDQS Tuning for DQS */
+#define MC_DC25_VALUE 0x0
+#define MC_DC26_VALUE 0x0
+#define MC_DC27_VALUE 0x0
+#define MC_DC28_VALUE 0x510
+#define MC_DC29_VALUE 0x4e20
+#define MC_DC30_VALUE 0x8235
+#define MC_DC31_VALUE 0x0
+#define MC_DC32_VALUE 0x0
+#define MC_DC33_VALUE 0x0
+#define MC_DC34_VALUE 0x0
+#define MC_DC35_VALUE 0x0
+#define MC_DC36_VALUE 0x0
+#define MC_DC37_VALUE 0x0
+#define MC_DC38_VALUE 0x0
+#define MC_DC39_VALUE 0x0
+#define MC_DC40_VALUE 0x0
+#define MC_DC41_VALUE 0x0
+#define MC_DC42_VALUE 0x0
+#define MC_DC43_VALUE 0x0
+#define MC_DC44_VALUE 0x0
+#define MC_DC45_VALUE 0x500
+//#define MC_DC45_VALUE 0x400
+#define MC_DC46_VALUE 0x0
diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_r111.h b/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_r111.h
new file mode 100644
index 000000000..fd155973e
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_r111.h
@@ -0,0 +1,50 @@
+/* Settings for Denali DDR SDRAM controller */
+/* Optimise for Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 29th April */
+#define MC_DC0_VALUE 0x1B1B
+#define MC_DC1_VALUE 0x0
+#define MC_DC2_VALUE 0x0
+#define MC_DC3_VALUE 0x0
+#define MC_DC4_VALUE 0x0
+#define MC_DC5_VALUE 0x200
+#define MC_DC6_VALUE 0x605
+#define MC_DC7_VALUE 0x303
+#define MC_DC8_VALUE 0x102
+#define MC_DC9_VALUE 0x70a
+#define MC_DC10_VALUE 0x203
+#define MC_DC11_VALUE 0xc02
+#define MC_DC12_VALUE 0x1C8
+#define MC_DC13_VALUE 0x1
+#define MC_DC14_VALUE 0x0
+#define MC_DC15_VALUE 0xf3c /* WDQS tuning for clk_wr*/
+#define MC_DC16_VALUE 0xC800
+#define MC_DC17_VALUE 0xd
+#define MC_DC18_VALUE 0x300
+#define MC_DC19_VALUE 0x200
+#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */
+#define MC_DC21_VALUE 0x1200
+#define MC_DC22_VALUE 0x1212
+#define MC_DC23_VALUE 0x0
+#define MC_DC24_VALUE 0x5e /* WDQS Tuning for DQS */
+#define MC_DC25_VALUE 0x0
+#define MC_DC26_VALUE 0x0
+#define MC_DC27_VALUE 0x0
+#define MC_DC28_VALUE 0x510
+#define MC_DC29_VALUE 0x2d89
+#define MC_DC30_VALUE 0x8300
+#define MC_DC31_VALUE 0x0
+#define MC_DC32_VALUE 0x0
+#define MC_DC33_VALUE 0x0
+#define MC_DC34_VALUE 0x0
+#define MC_DC35_VALUE 0x0
+#define MC_DC36_VALUE 0x0
+#define MC_DC37_VALUE 0x0
+#define MC_DC38_VALUE 0x0
+#define MC_DC39_VALUE 0x0
+#define MC_DC40_VALUE 0x0
+#define MC_DC41_VALUE 0x0
+#define MC_DC42_VALUE 0x0
+#define MC_DC43_VALUE 0x0
+#define MC_DC44_VALUE 0x0
+#define MC_DC45_VALUE 0x500
+//#define MC_DC45_VALUE 0x400
+#define MC_DC46_VALUE 0x0
diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_r166.h b/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_r166.h
new file mode 100644
index 000000000..742d34f1d
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50712/ddr_settings_r166.h
@@ -0,0 +1,50 @@
+/* Settings for Denali DDR SDRAM controller */
+/* Optimise for Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 29th April */
+#define MC_DC0_VALUE 0x1B1B
+#define MC_DC1_VALUE 0x0
+#define MC_DC2_VALUE 0x0
+#define MC_DC3_VALUE 0x0
+#define MC_DC4_VALUE 0x0
+#define MC_DC5_VALUE 0x200
+#define MC_DC6_VALUE 0x605
+#define MC_DC7_VALUE 0x303
+#define MC_DC8_VALUE 0x102
+#define MC_DC9_VALUE 0x70a
+#define MC_DC10_VALUE 0x203
+#define MC_DC11_VALUE 0xc02
+#define MC_DC12_VALUE 0x1C8
+#define MC_DC13_VALUE 0x1
+#define MC_DC14_VALUE 0x0
+#define MC_DC15_VALUE 0xf3c /* WDQS tuning for clk_wr*/
+#define MC_DC16_VALUE 0xC800
+#define MC_DC17_VALUE 0xd
+#define MC_DC18_VALUE 0x300
+#define MC_DC19_VALUE 0x200
+#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */
+#define MC_DC21_VALUE 0xd00
+#define MC_DC22_VALUE 0xd0d
+#define MC_DC23_VALUE 0x0
+#define MC_DC24_VALUE 0x62 /* WDQS Tuning for DQS */
+#define MC_DC25_VALUE 0x0
+#define MC_DC26_VALUE 0x0
+#define MC_DC27_VALUE 0x0
+#define MC_DC28_VALUE 0x510
+#define MC_DC29_VALUE 0x2d89
+#define MC_DC30_VALUE 0x8300
+#define MC_DC31_VALUE 0x0
+#define MC_DC32_VALUE 0x0
+#define MC_DC33_VALUE 0x0
+#define MC_DC34_VALUE 0x0
+#define MC_DC35_VALUE 0x0
+#define MC_DC36_VALUE 0x0
+#define MC_DC37_VALUE 0x0
+#define MC_DC38_VALUE 0x0
+#define MC_DC39_VALUE 0x0
+#define MC_DC40_VALUE 0x0
+#define MC_DC41_VALUE 0x0
+#define MC_DC42_VALUE 0x0
+#define MC_DC43_VALUE 0x0
+#define MC_DC44_VALUE 0x0
+#define MC_DC45_VALUE 0x500
+//#define MC_DC45_VALUE 0x400
+#define MC_DC46_VALUE 0x0
diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/easy50712_bootstrap.c b/package/uboot-lantiq/files/board/infineon/easy50712/easy50712_bootstrap.c
new file mode 100644
index 000000000..11bf6d0b7
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50712/easy50712_bootstrap.c
@@ -0,0 +1,48 @@
+/*
+ * (C) Copyright 2010 Industrie Dial Face S.p.A.
+ * Luigi 'Comio' Mantellini, luigi.mantellini@idf-hit.com
+ *
+ * (C) Copyright 2007
+ * Vlad Lungu vlad.lungu@windriver.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/mipsregs.h>
+#include <asm/io.h>
+
+phys_size_t bootstrap_initdram(int board_type)
+{
+ /* Sdram is setup by assembler code */
+ /* If memory could be changed, we should return the true value here */
+ return CONFIG_SYS_MAX_RAM;
+}
+
+int bootstrap_checkboard(void)
+{
+ return 0;
+}
+
+int bootstrap_misc_init_r(void)
+{
+ set_io_port_base(0);
+ return 0;
+}
diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/lowlevel_bootstrap_init.S b/package/uboot-lantiq/files/board/infineon/easy50712/lowlevel_bootstrap_init.S
new file mode 100644
index 000000000..216c38145
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50712/lowlevel_bootstrap_init.S
@@ -0,0 +1,606 @@
+/*
+ * Memory sub-system initialization code for Danube board.
+ * Andre Messerschmidt
+ * Copyright (c) 2005 Infineon Technologies AG
+ *
+ * Based on Inca-IP code
+ * Copyright (c) 2003 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+/* History:
+ peng liu May 25, 2006, for PLL setting after reset, 05252006
+ */
+#include <config.h>
+#include <version.h>
+#include <asm/regdef.h>
+
+#if defined(CONFIG_USE_DDR_RAM)
+
+#if defined(CONFIG_USE_DDR_RAM_CFG_111M)
+#include "ddr_settings_r111.h"
+#define DDR111
+#elif defined(CONFIG_USE_DDR_RAM_CFG_166M)
+#include "ddr_settings_r166.h"
+#define DDR166
+#elif defined(CONFIG_USE_DDR_RAM_CFG_e111M)
+#include "ddr_settings_e111.h"
+#define DDR111
+#elif defined(CONFIG_USE_DDR_RAM_CFG_e166M)
+#include "ddr_settings_e166.h"
+#define DDR166
+#elif defined(CONFIG_USE_DDR_RAM_CFG_promos400)
+#include "ddr_settings_PROMOSDDR400.h"
+#define DDR166
+#elif defined(CONFIG_USE_DDR_RAM_CFG_samsung166)
+#include "ddr_settings_Samsung_166.h"
+#define DDR166
+#elif defined(CONFIG_USE_DDR_RAM_CFG_psc166)
+#include "ddr_settings_psc_166.h"
+#define DDR166
+#else
+#warning "missing definition for ddr_settings.h, use default!"
+#include "ddr_settings.h"
+#endif
+#endif /* CONFIG_USE_DDR_RAM */
+
+#if defined(CONFIG_USE_DDR_RAM) && !defined(MC_DC0_VALUE)
+#error "missing include of ddr_settings.h"
+#endif
+
+#define EBU_MODUL_BASE 0xBE105300
+#define EBU_CLC(value) 0x0000(value)
+#define EBU_CON(value) 0x0010(value)
+#define EBU_ADDSEL0(value) 0x0020(value)
+#define EBU_ADDSEL1(value) 0x0024(value)
+#define EBU_ADDSEL2(value) 0x0028(value)
+#define EBU_ADDSEL3(value) 0x002C(value)
+#define EBU_BUSCON0(value) 0x0060(value)
+#define EBU_BUSCON1(value) 0x0064(value)
+#define EBU_BUSCON2(value) 0x0068(value)
+#define EBU_BUSCON3(value) 0x006C(value)
+
+#define MC_MODUL_BASE 0xBF800000
+#define MC_ERRCAUSE(value) 0x0010(value)
+#define MC_ERRADDR(value) 0x0020(value)
+#define MC_CON(value) 0x0060(value)
+
+#define MC_SRAM_ENABLE 0x00000004
+#define MC_SDRAM_ENABLE 0x00000002
+#define MC_DDRRAM_ENABLE 0x00000001
+
+#define MC_SDR_MODUL_BASE 0xBF800200
+#define MC_IOGP(value) 0x0000(value)
+#define MC_CTRLENA(value) 0x0010(value)
+#define MC_MRSCODE(value) 0x0020(value)
+#define MC_CFGDW(value) 0x0030(value)
+#define MC_CFGPB0(value) 0x0040(value)
+#define MC_LATENCY(value) 0x0080(value)
+#define MC_TREFRESH(value) 0x0090(value)
+#define MC_SELFRFSH(value) 0x00A0(value)
+
+#define MC_DDR_MODUL_BASE 0xBF801000
+#define MC_DC00(value) 0x0000(value)
+#define MC_DC01(value) 0x0010(value)
+#define MC_DC02(value) 0x0020(value)
+#define MC_DC03(value) 0x0030(value)
+#define MC_DC04(value) 0x0040(value)
+#define MC_DC05(value) 0x0050(value)
+#define MC_DC06(value) 0x0060(value)
+#define MC_DC07(value) 0x0070(value)
+#define MC_DC08(value) 0x0080(value)
+#define MC_DC09(value) 0x0090(value)
+#define MC_DC10(value) 0x00A0(value)
+#define MC_DC11(value) 0x00B0(value)
+#define MC_DC12(value) 0x00C0(value)
+#define MC_DC13(value) 0x00D0(value)
+#define MC_DC14(value) 0x00E0(value)
+#define MC_DC15(value) 0x00F0(value)
+#define MC_DC16(value) 0x0100(value)
+#define MC_DC17(value) 0x0110(value)
+#define MC_DC18(value) 0x0120(value)
+#define MC_DC19(value) 0x0130(value)
+#define MC_DC20(value) 0x0140(value)
+#define MC_DC21(value) 0x0150(value)
+#define MC_DC22(value) 0x0160(value)
+#define MC_DC23(value) 0x0170(value)
+#define MC_DC24(value) 0x0180(value)
+#define MC_DC25(value) 0x0190(value)
+#define MC_DC26(value) 0x01A0(value)
+#define MC_DC27(value) 0x01B0(value)
+#define MC_DC28(value) 0x01C0(value)
+#define MC_DC29(value) 0x01D0(value)
+#define MC_DC30(value) 0x01E0(value)
+#define MC_DC31(value) 0x01F0(value)
+#define MC_DC32(value) 0x0200(value)
+#define MC_DC33(value) 0x0210(value)
+#define MC_DC34(value) 0x0220(value)
+#define MC_DC35(value) 0x0230(value)
+#define MC_DC36(value) 0x0240(value)
+#define MC_DC37(value) 0x0250(value)
+#define MC_DC38(value) 0x0260(value)
+#define MC_DC39(value) 0x0270(value)
+#define MC_DC40(value) 0x0280(value)
+#define MC_DC41(value) 0x0290(value)
+#define MC_DC42(value) 0x02A0(value)
+#define MC_DC43(value) 0x02B0(value)
+#define MC_DC44(value) 0x02C0(value)
+#define MC_DC45(value) 0x02D0(value)
+#define MC_DC46(value) 0x02E0(value)
+
+#define RCU_OFFSET 0xBF203000
+#define RCU_RST_REQ (RCU_OFFSET + 0x0010)
+#define RCU_STS (RCU_OFFSET + 0x0014)
+
+#define CGU_OFFSET 0xBF103000
+#define PLL0_CFG (CGU_OFFSET + 0x0004)
+#define PLL1_CFG (CGU_OFFSET + 0x0008)
+#define PLL2_CFG (CGU_OFFSET + 0x000C)
+#define CGU_SYS (CGU_OFFSET + 0x0010)
+#define CGU_UPDATE (CGU_OFFSET + 0x0014)
+#define IF_CLK (CGU_OFFSET + 0x0018)
+#define CGU_SMD (CGU_OFFSET + 0x0020)
+#define CGU_CT1SR (CGU_OFFSET + 0x0028)
+#define CGU_CT2SR (CGU_OFFSET + 0x002C)
+#define CGU_PCMCR (CGU_OFFSET + 0x0030)
+#define PCI_CR_PCI (CGU_OFFSET + 0x0034)
+#define CGU_OSC_CTRL (CGU_OFFSET + 0x001C)
+#define CGU_MIPS_PWR_DWN (CGU_OFFSET + 0x0038)
+#define CLK_MEASURE (CGU_OFFSET + 0x003C)
+
+//05252006
+#define pll0_35MHz_CONFIG 0x9D861059
+#define pll1_35MHz_CONFIG 0x1A260CD9
+#define pll2_35MHz_CONFIG 0x8000f1e5
+#define pll0_36MHz_CONFIG 0x1000125D
+#define pll1_36MHz_CONFIG 0x1B1E0C99
+#define pll2_36MHz_CONFIG 0x8002f2a1
+//05252006
+
+//06063001-joelin disable the PCI CFRAME mask -start
+/*CFRAME is an I/O signal, in the chip, the output CFRAME is selected via GPIO altsel pins, so if you select MII1 RXD1, the CFRAME will not come out.
+But the CFRAME input still take the signal from the pad and not disabled when altsel choose other function. So when MII1_RXD1 is low from other device, the EBU interface will be disabled.
+
+The chip function in such a way that disable the CFRAME mask mean EBU not longer check CFRAME to be the device using the bus.
+The side effect is the entire PCI block will see CFRAME low all the time meaning PCI cannot use the bus at all so no more PCI function.
+*/
+#define PCI_CR_PR_OFFSET 0xBE105400
+#define PCI_CR_PCI_MOD_REG (PCI_CR_PR_OFFSET + 0x0030)
+#define PCI_CONFIG_SPACE 0xB7000000
+#define CS_CFM (PCI_CONFIG_SPACE + 0x6C)
+//06063001-joelin disable the PCI CFRAME mask -end
+ .set noreorder
+
+
+/*
+ * void ebu_init(void)
+ */
+ .globl ebu_init
+ .ent ebu_init
+ebu_init:
+
+#if defined(CONFIG_EBU_ADDSEL0) || defined(CONFIG_EBU_ADDSEL1) || \
+ defined(CONFIG_EBU_ADDSEL2) || defined(CONFIG_EBU_ADDSEL3) || \
+ defined(CONFIG_EBU_BUSCON0) || defined(CONFIG_EBU_BUSCON1) || \
+ defined(CONFIG_EBU_BUSCON2) || defined(CONFIG_EBU_BUSCON3)
+
+ li t1, EBU_MODUL_BASE
+#if defined(CONFIG_EBU_ADDSEL0)
+ li t2, CONFIG_EBU_ADDSEL0
+ sw t2, EBU_ADDSEL0(t1)
+#endif
+#if defined(CONFIG_EBU_ADDSEL1)
+ li t2, CONFIG_EBU_ADDSEL1
+ sw t2, EBU_ADDSEL1(t1)
+#endif
+#if defined(CONFIG_EBU_ADDSEL2)
+ li t2, CONFIG_EBU_ADDSEL2
+ sw t2, EBU_ADDSEL2(t1)
+#endif
+#if defined(CONFIG_EBU_ADDSEL3)
+ li t2, CONFIG_EBU_ADDSEL3
+ sw t2, EBU_ADDSEL3(t1)
+#endif
+
+#if defined(CONFIG_EBU_BUSCON0)
+ li t2, CONFIG_EBU_BUSCON0
+ sw t2, EBU_BUSCON0(t1)
+#endif
+#if defined(CONFIG_EBU_BUSCON1)
+ li t2, CONFIG_EBU_BUSCON1
+ sw t2, EBU_BUSCON1(t1)
+#endif
+#if defined(CONFIG_EBU_BUSCON2)
+ li t2, CONFIG_EBU_BUSCON2
+ sw t2, EBU_BUSCON2(t1)
+#endif
+#if defined(CONFIG_EBU_BUSCON3)
+ li t2, CONFIG_EBU_BUSCON3
+ sw t2, EBU_BUSCON3(t1)
+#endif
+
+#endif
+
+ j ra
+ nop
+
+ .end ebu_init
+
+
+/*
+ * void cgu_init(long)
+ *
+ * a0 has the clock value
+ */
+ .globl cgu_init
+ .ent cgu_init
+cgu_init:
+ li t2, CGU_SYS
+ lw t2,0(t2)
+ beq t2,a0,freq_up2date
+ nop
+
+ li t2, RCU_STS
+ lw t2, 0(t2)
+ and t2,0x00020000
+ beq t2,0x00020000,boot_36MHZ
+ nop
+//05252006
+ li t1, PLL0_CFG
+ li t2, pll0_35MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL1_CFG
+ li t2, pll1_35MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL2_CFG
+ li t2, pll2_35MHz_CONFIG
+ sw t2,0(t1)
+ li t1, CGU_SYS
+ sw a0,0(t1)
+ li t1, RCU_RST_REQ
+ li t2, 0x40000008
+ sw t2,0(t1)
+ b wait_reset
+ nop
+boot_36MHZ:
+ li t1, PLL0_CFG
+ li t2, pll0_36MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL1_CFG
+ li t2, pll1_36MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL2_CFG
+ li t2, pll2_36MHz_CONFIG
+ sw t2,0(t1)
+ li t1, CGU_SYS
+ sw a0,0(t1)
+ li t1, RCU_RST_REQ
+ li t2, 0x40000008
+ sw t2,0(t1)
+//05252006
+
+wait_reset:
+ b wait_reset
+ nop
+freq_up2date:
+ j ra
+ nop
+
+ .end cgu_init
+
+#ifndef CONFIG_USE_DDR_RAM
+/*
+ * void sdram_init(long)
+ *
+ * a0 has the clock value
+ */
+ .globl sdram_init
+ .ent sdram_init
+sdram_init:
+
+ /* SDRAM Initialization
+ */
+ li t1, MC_MODUL_BASE
+
+ /* Clear Error log registers */
+ sw zero, MC_ERRCAUSE(t1)
+ sw zero, MC_ERRADDR(t1)
+
+ /* Enable SDRAM module in memory controller */
+ li t3, MC_SDRAM_ENABLE
+ lw t2, MC_CON(t1)
+ or t3, t2, t3
+ sw t3, MC_CON(t1)
+
+ li t1, MC_SDR_MODUL_BASE
+
+ /* disable the controller */
+ li t2, 0
+ sw t2, MC_CTRLENA(t1)
+
+ li t2, 0x822
+ sw t2, MC_IOGP(t1)
+
+ li t2, 0x2
+ sw t2, MC_CFGDW(t1)
+
+ /* Set CAS Latency */
+ li t2, 0x00000020
+ sw t2, MC_MRSCODE(t1)
+
+ /* Set CS0 to SDRAM parameters */
+ li t2, 0x000014d8
+ sw t2, MC_CFGPB0(t1)
+
+ /* Set SDRAM latency parameters */
+ li t2, 0x00036325; /* BC PC100 */
+ sw t2, MC_LATENCY(t1)
+
+ /* Set SDRAM refresh rate */
+ li t2, 0x00000C30
+ sw t2, MC_TREFRESH(t1)
+
+ /* Clear Power-down registers */
+ sw zero, MC_SELFRFSH(t1)
+
+ /* Finally enable the controller */
+ li t2, 1
+ sw t2, MC_CTRLENA(t1)
+
+ j ra
+ nop
+
+ .end sdram_init
+
+#endif /* !CONFIG_USE_DDR_RAM */
+
+#ifdef CONFIG_USE_DDR_RAM
+/*
+ * void ddrram_init(long)
+ *
+ * a0 has the clock value
+ */
+ .globl ddrram_init
+ .ent ddrram_init
+ddrram_init:
+
+ /* DDR-DRAM Initialization
+ */
+ li t1, MC_MODUL_BASE
+
+ /* Clear Error log registers */
+ sw zero, MC_ERRCAUSE(t1)
+ sw zero, MC_ERRADDR(t1)
+
+ /* Enable DDR module in memory controller */
+ li t3, MC_DDRRAM_ENABLE
+ lw t2, MC_CON(t1)
+ or t3, t2, t3
+ sw t3, MC_CON(t1)
+
+ li t1, MC_DDR_MODUL_BASE
+
+ /* Write configuration to DDR controller registers */
+ li t2, MC_DC0_VALUE
+ sw t2, MC_DC00(t1)
+
+ li t2, MC_DC1_VALUE
+ sw t2, MC_DC01(t1)
+
+ li t2, MC_DC2_VALUE
+ sw t2, MC_DC02(t1)
+
+ li t2, MC_DC3_VALUE
+ sw t2, MC_DC03(t1)
+
+ li t2, MC_DC4_VALUE
+ sw t2, MC_DC04(t1)
+
+ li t2, MC_DC5_VALUE
+ sw t2, MC_DC05(t1)
+
+ li t2, MC_DC6_VALUE
+ sw t2, MC_DC06(t1)
+
+ li t2, MC_DC7_VALUE
+ sw t2, MC_DC07(t1)
+
+ li t2, MC_DC8_VALUE
+ sw t2, MC_DC08(t1)
+
+ li t2, MC_DC9_VALUE
+ sw t2, MC_DC09(t1)
+
+ li t2, MC_DC10_VALUE
+ sw t2, MC_DC10(t1)
+
+ li t2, MC_DC11_VALUE
+ sw t2, MC_DC11(t1)
+
+ li t2, MC_DC12_VALUE
+ sw t2, MC_DC12(t1)
+
+ li t2, MC_DC13_VALUE
+ sw t2, MC_DC13(t1)
+
+ li t2, MC_DC14_VALUE
+ sw t2, MC_DC14(t1)
+
+ li t2, MC_DC15_VALUE
+ sw t2, MC_DC15(t1)
+
+ li t2, MC_DC16_VALUE
+ sw t2, MC_DC16(t1)
+
+ li t2, MC_DC17_VALUE
+ sw t2, MC_DC17(t1)
+
+ li t2, MC_DC18_VALUE
+ sw t2, MC_DC18(t1)
+
+ li t2, MC_DC19_VALUE
+ sw t2, MC_DC19(t1)
+
+ li t2, MC_DC20_VALUE
+ sw t2, MC_DC20(t1)
+
+ li t2, MC_DC21_VALUE
+ sw t2, MC_DC21(t1)
+
+ li t2, MC_DC22_VALUE
+ sw t2, MC_DC22(t1)
+
+ li t2, MC_DC23_VALUE
+ sw t2, MC_DC23(t1)
+
+ li t2, MC_DC24_VALUE
+ sw t2, MC_DC24(t1)
+
+ li t2, MC_DC25_VALUE
+ sw t2, MC_DC25(t1)
+
+ li t2, MC_DC26_VALUE
+ sw t2, MC_DC26(t1)
+
+ li t2, MC_DC27_VALUE
+ sw t2, MC_DC27(t1)
+
+ li t2, MC_DC28_VALUE
+ sw t2, MC_DC28(t1)
+
+ li t2, MC_DC29_VALUE
+ sw t2, MC_DC29(t1)
+
+ li t2, MC_DC30_VALUE
+ sw t2, MC_DC30(t1)
+
+ li t2, MC_DC31_VALUE
+ sw t2, MC_DC31(t1)
+
+ li t2, MC_DC32_VALUE
+ sw t2, MC_DC32(t1)
+
+ li t2, MC_DC33_VALUE
+ sw t2, MC_DC33(t1)
+
+ li t2, MC_DC34_VALUE
+ sw t2, MC_DC34(t1)
+
+ li t2, MC_DC35_VALUE
+ sw t2, MC_DC35(t1)
+
+ li t2, MC_DC36_VALUE
+ sw t2, MC_DC36(t1)
+
+ li t2, MC_DC37_VALUE
+ sw t2, MC_DC37(t1)
+
+ li t2, MC_DC38_VALUE
+ sw t2, MC_DC38(t1)
+
+ li t2, MC_DC39_VALUE
+ sw t2, MC_DC39(t1)
+
+ li t2, MC_DC40_VALUE
+ sw t2, MC_DC40(t1)
+
+ li t2, MC_DC41_VALUE
+ sw t2, MC_DC41(t1)
+
+ li t2, MC_DC42_VALUE
+ sw t2, MC_DC42(t1)
+
+ li t2, MC_DC43_VALUE
+ sw t2, MC_DC43(t1)
+
+ li t2, MC_DC44_VALUE
+ sw t2, MC_DC44(t1)
+
+ li t2, MC_DC45_VALUE
+ sw t2, MC_DC45(t1)
+
+ li t2, MC_DC46_VALUE
+ sw t2, MC_DC46(t1)
+
+ li t2, 0x00000100
+ sw t2, MC_DC03(t1)
+
+ j ra
+ nop
+
+ .end ddrram_init
+#endif /* CONFIG_USE_DDR_RAM */
+
+ .globl lowlevel_init
+ .ent lowlevel_init
+lowlevel_init:
+ /* EBU, CGU and SDRAM/DDR-RAM Initialization.
+ */
+ move t0, ra
+ /* We rely on the fact that non of the following ..._init() functions
+ * modify t0
+ */
+#if defined(DDR166)
+ /* 0xe8 means CPU0/CPU1 333M, DDR 167M, FPI 83M, PPE 240M */
+ li a0,0xe8
+#elif defined(DDR133)
+ /* 0xe9 means CPU0/CPU1 333M, DDR 133M, FPI 83M, PPE 240M */
+ li a0,0xe9
+#else /* defined(DDR111) */
+ /* 0xea means CPU0/CPU1 333M, DDR 111M, FPI 83M, PPE 240M */
+ li a0,0xea
+#endif
+ bal cgu_init
+ nop
+
+ bal ebu_init
+ nop
+
+//06063001-joelin disable the PCI CFRAME mask-start
+#ifdef DISABLE_CFRAME
+ li t1, PCI_CR_PCI //mw bf103034 80000000
+ li t2, 0x80000000
+ sw t2,0(t1)
+
+ li t1, PCI_CR_PCI_MOD_REG //mw be105430 103
+ li t2, 0x103
+ sw t2,0(t1)
+
+ li t1, CS_CFM //mw b700006c 0
+ li t2, 0x00
+ sw t2, 0(t1)
+
+ li t1, PCI_CR_PCI_MOD_REG //mw be105430 103
+ li t2, 0x1000103
+ sw t2, 0(t1)
+#endif
+//06063001-joelin disable the PCI CFRAME mask-end
+
+#ifdef CONFIG_USE_DDR_RAM
+ bal ddrram_init
+ nop
+#else
+ bal sdram_init
+ nop
+#endif
+ move ra, t0
+ j ra
+ nop
+
+ .end lowlevel_init
diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/lowlevel_init.S b/package/uboot-lantiq/files/board/infineon/easy50712/lowlevel_init.S
new file mode 100644
index 000000000..4dc179fc0
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50712/lowlevel_init.S
@@ -0,0 +1,613 @@
+/*
+ * Memory sub-system initialization code for Danube board.
+ * Andre Messerschmidt
+ * Copyright (c) 2005 Infineon Technologies AG
+ *
+ * Based on Inca-IP code
+ * Copyright (c) 2003 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+/* History:
+ peng liu May 25, 2006, for PLL setting after reset, 05252006
+ */
+#include <config.h>
+#include <version.h>
+#include <asm/regdef.h>
+
+#if defined(CONFIG_USE_DDR_RAM)
+
+#if defined(CONFIG_USE_DDR_RAM_CFG_111M)
+#include "ddr_settings_r111.h"
+#define DDR111
+#elif defined(CONFIG_USE_DDR_RAM_CFG_166M)
+#include "ddr_settings_r166.h"
+#define DDR166
+#elif defined(CONFIG_USE_DDR_RAM_CFG_e111M)
+#include "ddr_settings_e111.h"
+#define DDR111
+#elif defined(CONFIG_USE_DDR_RAM_CFG_e166M)
+#include "ddr_settings_e166.h"
+#define DDR166
+#elif defined(CONFIG_USE_DDR_RAM_CFG_promos400)
+#include "ddr_settings_PROMOSDDR400.h"
+#define DDR166
+#elif defined(CONFIG_USE_DDR_RAM_CFG_samsung166)
+#include "ddr_settings_Samsung_166.h"
+#define DDR166
+#elif defined(CONFIG_USE_DDR_RAM_CFG_psc166)
+#include "ddr_settings_psc_166.h"
+#define DDR166
+#else
+#warning "missing definition for ddr_settings.h, use default!"
+#include "ddr_settings.h"
+#endif
+#endif /* CONFIG_USE_DDR_RAM */
+
+#if defined(CONFIG_USE_DDR_RAM) && !defined(MC_DC0_VALUE)
+#error "missing include of ddr_settings.h"
+#endif
+
+#define EBU_MODUL_BASE 0xBE105300
+#define EBU_CLC(value) 0x0000(value)
+#define EBU_CON(value) 0x0010(value)
+#define EBU_ADDSEL0(value) 0x0020(value)
+#define EBU_ADDSEL1(value) 0x0024(value)
+#define EBU_ADDSEL2(value) 0x0028(value)
+#define EBU_ADDSEL3(value) 0x002C(value)
+#define EBU_BUSCON0(value) 0x0060(value)
+#define EBU_BUSCON1(value) 0x0064(value)
+#define EBU_BUSCON2(value) 0x0068(value)
+#define EBU_BUSCON3(value) 0x006C(value)
+
+#define MC_MODUL_BASE 0xBF800000
+#define MC_ERRCAUSE(value) 0x0010(value)
+#define MC_ERRADDR(value) 0x0020(value)
+#define MC_CON(value) 0x0060(value)
+
+#define MC_SRAM_ENABLE 0x00000004
+#define MC_SDRAM_ENABLE 0x00000002
+#define MC_DDRRAM_ENABLE 0x00000001
+
+#define MC_SDR_MODUL_BASE 0xBF800200
+#define MC_IOGP(value) 0x0000(value)
+#define MC_CTRLENA(value) 0x0010(value)
+#define MC_MRSCODE(value) 0x0020(value)
+#define MC_CFGDW(value) 0x0030(value)
+#define MC_CFGPB0(value) 0x0040(value)
+#define MC_LATENCY(value) 0x0080(value)
+#define MC_TREFRESH(value) 0x0090(value)
+#define MC_SELFRFSH(value) 0x00A0(value)
+
+#define MC_DDR_MODUL_BASE 0xBF801000
+#define MC_DC00(value) 0x0000(value)
+#define MC_DC01(value) 0x0010(value)
+#define MC_DC02(value) 0x0020(value)
+#define MC_DC03(value) 0x0030(value)
+#define MC_DC04(value) 0x0040(value)
+#define MC_DC05(value) 0x0050(value)
+#define MC_DC06(value) 0x0060(value)
+#define MC_DC07(value) 0x0070(value)
+#define MC_DC08(value) 0x0080(value)
+#define MC_DC09(value) 0x0090(value)
+#define MC_DC10(value) 0x00A0(value)
+#define MC_DC11(value) 0x00B0(value)
+#define MC_DC12(value) 0x00C0(value)
+#define MC_DC13(value) 0x00D0(value)
+#define MC_DC14(value) 0x00E0(value)
+#define MC_DC15(value) 0x00F0(value)
+#define MC_DC16(value) 0x0100(value)
+#define MC_DC17(value) 0x0110(value)
+#define MC_DC18(value) 0x0120(value)
+#define MC_DC19(value) 0x0130(value)
+#define MC_DC20(value) 0x0140(value)
+#define MC_DC21(value) 0x0150(value)
+#define MC_DC22(value) 0x0160(value)
+#define MC_DC23(value) 0x0170(value)
+#define MC_DC24(value) 0x0180(value)
+#define MC_DC25(value) 0x0190(value)
+#define MC_DC26(value) 0x01A0(value)
+#define MC_DC27(value) 0x01B0(value)
+#define MC_DC28(value) 0x01C0(value)
+#define MC_DC29(value) 0x01D0(value)
+#define MC_DC30(value) 0x01E0(value)
+#define MC_DC31(value) 0x01F0(value)
+#define MC_DC32(value) 0x0200(value)
+#define MC_DC33(value) 0x0210(value)
+#define MC_DC34(value) 0x0220(value)
+#define MC_DC35(value) 0x0230(value)
+#define MC_DC36(value) 0x0240(value)
+#define MC_DC37(value) 0x0250(value)
+#define MC_DC38(value) 0x0260(value)
+#define MC_DC39(value) 0x0270(value)
+#define MC_DC40(value) 0x0280(value)
+#define MC_DC41(value) 0x0290(value)
+#define MC_DC42(value) 0x02A0(value)
+#define MC_DC43(value) 0x02B0(value)
+#define MC_DC44(value) 0x02C0(value)
+#define MC_DC45(value) 0x02D0(value)
+#define MC_DC46(value) 0x02E0(value)
+
+#define RCU_OFFSET 0xBF203000
+#define RCU_RST_REQ (RCU_OFFSET + 0x0010)
+#define RCU_STS (RCU_OFFSET + 0x0014)
+
+#define CGU_OFFSET 0xBF103000
+#define PLL0_CFG (CGU_OFFSET + 0x0004)
+#define PLL1_CFG (CGU_OFFSET + 0x0008)
+#define PLL2_CFG (CGU_OFFSET + 0x000C)
+#define CGU_SYS (CGU_OFFSET + 0x0010)
+#define CGU_UPDATE (CGU_OFFSET + 0x0014)
+#define IF_CLK (CGU_OFFSET + 0x0018)
+#define CGU_SMD (CGU_OFFSET + 0x0020)
+#define CGU_CT1SR (CGU_OFFSET + 0x0028)
+#define CGU_CT2SR (CGU_OFFSET + 0x002C)
+#define CGU_PCMCR (CGU_OFFSET + 0x0030)
+#define PCI_CR_PCI (CGU_OFFSET + 0x0034)
+#define CGU_OSC_CTRL (CGU_OFFSET + 0x001C)
+#define CGU_MIPS_PWR_DWN (CGU_OFFSET + 0x0038)
+#define CLK_MEASURE (CGU_OFFSET + 0x003C)
+
+//05252006
+#define pll0_35MHz_CONFIG 0x9D861059
+#define pll1_35MHz_CONFIG 0x1A260CD9
+#define pll2_35MHz_CONFIG 0x8000f1e5
+#define pll0_36MHz_CONFIG 0x1000125D
+#define pll1_36MHz_CONFIG 0x1B1E0C99
+#define pll2_36MHz_CONFIG 0x8002f2a1
+//05252006
+
+//06063001-joelin disable the PCI CFRAME mask -start
+/*CFRAME is an I/O signal, in the chip, the output CFRAME is selected via GPIO altsel pins, so if you select MII1 RXD1, the CFRAME will not come out.
+But the CFRAME input still take the signal from the pad and not disabled when altsel choose other function. So when MII1_RXD1 is low from other device, the EBU interface will be disabled.
+
+The chip function in such a way that disable the CFRAME mask mean EBU not longer check CFRAME to be the device using the bus.
+The side effect is the entire PCI block will see CFRAME low all the time meaning PCI cannot use the bus at all so no more PCI function.
+*/
+#define PCI_CR_PR_OFFSET 0xBE105400
+#define PCI_CR_PCI_MOD_REG (PCI_CR_PR_OFFSET + 0x0030)
+#define PCI_CONFIG_SPACE 0xB7000000
+#define CS_CFM (PCI_CONFIG_SPACE + 0x6C)
+//06063001-joelin disable the PCI CFRAME mask -end
+ .set noreorder
+
+
+/*
+ * void ebu_init(void)
+ */
+ .globl ebu_init
+ .ent ebu_init
+ebu_init:
+
+#if defined(CONFIG_EBU_ADDSEL0) || defined(CONFIG_EBU_ADDSEL1) || \
+ defined(CONFIG_EBU_ADDSEL2) || defined(CONFIG_EBU_ADDSEL3) || \
+ defined(CONFIG_EBU_BUSCON0) || defined(CONFIG_EBU_BUSCON1) || \
+ defined(CONFIG_EBU_BUSCON2) || defined(CONFIG_EBU_BUSCON3)
+
+ li t1, EBU_MODUL_BASE
+#if defined(CONFIG_EBU_ADDSEL0)
+ li t2, CONFIG_EBU_ADDSEL0
+ sw t2, EBU_ADDSEL0(t1)
+#endif
+#if defined(CONFIG_EBU_ADDSEL1)
+ li t2, CONFIG_EBU_ADDSEL1
+ sw t2, EBU_ADDSEL1(t1)
+#endif
+#if defined(CONFIG_EBU_ADDSEL2)
+ li t2, CONFIG_EBU_ADDSEL2
+ sw t2, EBU_ADDSEL2(t1)
+#endif
+#if defined(CONFIG_EBU_ADDSEL3)
+ li t2, CONFIG_EBU_ADDSEL3
+ sw t2, EBU_ADDSEL3(t1)
+#endif
+
+#if defined(CONFIG_EBU_BUSCON0)
+ li t2, CONFIG_EBU_BUSCON0
+ sw t2, EBU_BUSCON0(t1)
+#endif
+#if defined(CONFIG_EBU_BUSCON1)
+ li t2, CONFIG_EBU_BUSCON1
+ sw t2, EBU_BUSCON1(t1)
+#endif
+#if defined(CONFIG_EBU_BUSCON2)
+ li t2, CONFIG_EBU_BUSCON2
+ sw t2, EBU_BUSCON2(t1)
+#endif
+#if defined(CONFIG_EBU_BUSCON3)
+ li t2, CONFIG_EBU_BUSCON3
+ sw t2, EBU_BUSCON3(t1)
+#endif
+
+#endif
+
+ j ra
+ nop
+
+ .end ebu_init
+
+
+/*
+ * void cgu_init(long)
+ *
+ * a0 has the clock value
+ */
+ .globl cgu_init
+ .ent cgu_init
+cgu_init:
+ li t2, CGU_SYS
+ lw t2,0(t2)
+ beq t2,a0,freq_up2date
+ nop
+
+ li t2, RCU_STS
+ lw t2, 0(t2)
+ and t2,0x00020000
+ beq t2,0x00020000,boot_36MHZ
+ nop
+//05252006
+ li t1, PLL0_CFG
+ li t2, pll0_35MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL1_CFG
+ li t2, pll1_35MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL2_CFG
+ li t2, pll2_35MHz_CONFIG
+ sw t2,0(t1)
+ li t1, CGU_SYS
+ sw a0,0(t1)
+ li t1, RCU_RST_REQ
+ li t2, 0x40000008
+ sw t2,0(t1)
+ b wait_reset
+ nop
+boot_36MHZ:
+ li t1, PLL0_CFG
+ li t2, pll0_36MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL1_CFG
+ li t2, pll1_36MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL2_CFG
+ li t2, pll2_36MHz_CONFIG
+ sw t2,0(t1)
+ li t1, CGU_SYS
+ sw a0,0(t1)
+ li t1, RCU_RST_REQ
+ li t2, 0x40000008
+ sw t2,0(t1)
+//05252006
+
+wait_reset:
+ b wait_reset
+ nop
+freq_up2date:
+ j ra
+ nop
+
+ .end cgu_init
+
+#ifndef CONFIG_USE_DDR_RAM
+/*
+ * void sdram_init(long)
+ *
+ * a0 has the clock value
+ */
+ .globl sdram_init
+ .ent sdram_init
+sdram_init:
+
+ /* SDRAM Initialization
+ */
+ li t1, MC_MODUL_BASE
+
+ /* Clear Error log registers */
+ sw zero, MC_ERRCAUSE(t1)
+ sw zero, MC_ERRADDR(t1)
+
+ /* Enable SDRAM module in memory controller */
+ li t3, MC_SDRAM_ENABLE
+ lw t2, MC_CON(t1)
+ or t3, t2, t3
+ sw t3, MC_CON(t1)
+
+ li t1, MC_SDR_MODUL_BASE
+
+ /* disable the controller */
+ li t2, 0
+ sw t2, MC_CTRLENA(t1)
+
+ li t2, 0x822
+ sw t2, MC_IOGP(t1)
+
+ li t2, 0x2
+ sw t2, MC_CFGDW(t1)
+
+ /* Set CAS Latency */
+ li t2, 0x00000020
+ sw t2, MC_MRSCODE(t1)
+
+ /* Set CS0 to SDRAM parameters */
+ li t2, 0x000014d8
+ sw t2, MC_CFGPB0(t1)
+
+ /* Set SDRAM latency parameters */
+ li t2, 0x00036325; /* BC PC100 */
+ sw t2, MC_LATENCY(t1)
+
+ /* Set SDRAM refresh rate */
+ li t2, 0x00000C30
+ sw t2, MC_TREFRESH(t1)
+
+ /* Clear Power-down registers */
+ sw zero, MC_SELFRFSH(t1)
+
+ /* Finally enable the controller */
+ li t2, 1
+ sw t2, MC_CTRLENA(t1)
+
+ j ra
+ nop
+
+ .end sdram_init
+
+#endif /* !CONFIG_USE_DDR_RAM */
+
+#ifdef CONFIG_USE_DDR_RAM
+/*
+ * void ddrram_init(long)
+ *
+ * a0 has the clock value
+ */
+ .globl ddrram_init
+ .ent ddrram_init
+ddrram_init:
+
+ /* DDR-DRAM Initialization
+ */
+ li t1, MC_MODUL_BASE
+
+ /* Clear Error log registers */
+ sw zero, MC_ERRCAUSE(t1)
+ sw zero, MC_ERRADDR(t1)
+
+ /* Enable DDR module in memory controller */
+ li t3, MC_DDRRAM_ENABLE
+ lw t2, MC_CON(t1)
+ or t3, t2, t3
+ sw t3, MC_CON(t1)
+
+ li t1, MC_DDR_MODUL_BASE
+
+ /* Write configuration to DDR controller registers */
+ li t2, MC_DC0_VALUE
+ sw t2, MC_DC00(t1)
+
+ li t2, MC_DC1_VALUE
+ sw t2, MC_DC01(t1)
+
+ li t2, MC_DC2_VALUE
+ sw t2, MC_DC02(t1)
+
+ li t2, MC_DC3_VALUE
+ sw t2, MC_DC03(t1)
+
+ li t2, MC_DC4_VALUE
+ sw t2, MC_DC04(t1)
+
+ li t2, MC_DC5_VALUE
+ sw t2, MC_DC05(t1)
+
+ li t2, MC_DC6_VALUE
+ sw t2, MC_DC06(t1)
+
+ li t2, MC_DC7_VALUE
+ sw t2, MC_DC07(t1)
+
+ li t2, MC_DC8_VALUE
+ sw t2, MC_DC08(t1)
+
+ li t2, MC_DC9_VALUE
+ sw t2, MC_DC09(t1)
+
+ li t2, MC_DC10_VALUE
+ sw t2, MC_DC10(t1)
+
+ li t2, MC_DC11_VALUE
+ sw t2, MC_DC11(t1)
+
+ li t2, MC_DC12_VALUE
+ sw t2, MC_DC12(t1)
+
+ li t2, MC_DC13_VALUE
+ sw t2, MC_DC13(t1)
+
+ li t2, MC_DC14_VALUE
+ sw t2, MC_DC14(t1)
+
+ li t2, MC_DC15_VALUE
+ sw t2, MC_DC15(t1)
+
+ li t2, MC_DC16_VALUE
+ sw t2, MC_DC16(t1)
+
+ li t2, MC_DC17_VALUE
+ sw t2, MC_DC17(t1)
+
+ li t2, MC_DC18_VALUE
+ sw t2, MC_DC18(t1)
+
+ li t2, MC_DC19_VALUE
+ sw t2, MC_DC19(t1)
+
+ li t2, MC_DC20_VALUE
+ sw t2, MC_DC20(t1)
+
+ li t2, MC_DC21_VALUE
+ sw t2, MC_DC21(t1)
+
+ li t2, MC_DC22_VALUE
+ sw t2, MC_DC22(t1)
+
+ li t2, MC_DC23_VALUE
+ sw t2, MC_DC23(t1)
+
+ li t2, MC_DC24_VALUE
+ sw t2, MC_DC24(t1)
+
+ li t2, MC_DC25_VALUE
+ sw t2, MC_DC25(t1)
+
+ li t2, MC_DC26_VALUE
+ sw t2, MC_DC26(t1)
+
+ li t2, MC_DC27_VALUE
+ sw t2, MC_DC27(t1)
+
+ li t2, MC_DC28_VALUE
+ sw t2, MC_DC28(t1)
+
+ li t2, MC_DC29_VALUE
+ sw t2, MC_DC29(t1)
+
+ li t2, MC_DC30_VALUE
+ sw t2, MC_DC30(t1)
+
+ li t2, MC_DC31_VALUE
+ sw t2, MC_DC31(t1)
+
+ li t2, MC_DC32_VALUE
+ sw t2, MC_DC32(t1)
+
+ li t2, MC_DC33_VALUE
+ sw t2, MC_DC33(t1)
+
+ li t2, MC_DC34_VALUE
+ sw t2, MC_DC34(t1)
+
+ li t2, MC_DC35_VALUE
+ sw t2, MC_DC35(t1)
+
+ li t2, MC_DC36_VALUE
+ sw t2, MC_DC36(t1)
+
+ li t2, MC_DC37_VALUE
+ sw t2, MC_DC37(t1)
+
+ li t2, MC_DC38_VALUE
+ sw t2, MC_DC38(t1)
+
+ li t2, MC_DC39_VALUE
+ sw t2, MC_DC39(t1)
+
+ li t2, MC_DC40_VALUE
+ sw t2, MC_DC40(t1)
+
+ li t2, MC_DC41_VALUE
+ sw t2, MC_DC41(t1)
+
+ li t2, MC_DC42_VALUE
+ sw t2, MC_DC42(t1)
+
+ li t2, MC_DC43_VALUE
+ sw t2, MC_DC43(t1)
+
+ li t2, MC_DC44_VALUE
+ sw t2, MC_DC44(t1)
+
+ li t2, MC_DC45_VALUE
+ sw t2, MC_DC45(t1)
+
+ li t2, MC_DC46_VALUE
+ sw t2, MC_DC46(t1)
+
+ li t2, 0x00000100
+ sw t2, MC_DC03(t1)
+
+ j ra
+ nop
+
+ .end ddrram_init
+#endif /* CONFIG_USE_DDR_RAM */
+
+ .globl lowlevel_init
+ .ent lowlevel_init
+lowlevel_init:
+ /* EBU, CGU and SDRAM/DDR-RAM Initialization.
+ */
+ move t0, ra
+ /* We rely on the fact that non of the following ..._init() functions
+ * modify t0
+ */
+#if defined(CONFIG_SYS_EBU_BOOT)
+#if defined(DDR166)
+ /* 0xe8 means CPU0/CPU1 333M, DDR 167M, FPI 83M, PPE 240M */
+ li a0,0xe8
+#elif defined(DDR133)
+ /* 0xe9 means CPU0/CPU1 333M, DDR 133M, FPI 83M, PPE 240M */
+ li a0,0xe9
+#else /* defined(DDR111) */
+ /* 0xea means CPU0/CPU1 333M, DDR 111M, FPI 83M, PPE 240M */
+ li a0,0xea
+#endif
+ bal cgu_init
+ nop
+#endif /* CONFIG_SYS_EBU_BOOT */
+
+ bal ebu_init
+ nop
+
+//06063001-joelin disable the PCI CFRAME mask-start
+#ifdef DISABLE_CFRAME
+ li t1, PCI_CR_PCI //mw bf103034 80000000
+ li t2, 0x80000000
+ sw t2,0(t1)
+
+ li t1, PCI_CR_PCI_MOD_REG //mw be105430 103
+ li t2, 0x103
+ sw t2,0(t1)
+
+ li t1, CS_CFM //mw b700006c 0
+ li t2, 0x00
+ sw t2, 0(t1)
+
+ li t1, PCI_CR_PCI_MOD_REG //mw be105430 103
+ li t2, 0x1000103
+ sw t2, 0(t1)
+#endif
+//06063001-joelin disable the PCI CFRAME mask-end
+
+#ifdef CONFIG_SYS_EBU_BOOT
+#ifndef CONFIG_SYS_RAMBOOT
+#ifdef CONFIG_USE_DDR_RAM
+ bal ddrram_init
+ nop
+#else
+ bal sdram_init
+ nop
+#endif
+#endif /* CONFIG_SYS_RAMBOOT */
+#endif /* CONFIG_SYS_EBU_BOOT */
+
+ move ra, t0
+ j ra
+ nop
+
+ .end lowlevel_init
diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/pmuenable.S b/package/uboot-lantiq/files/board/infineon/easy50712/pmuenable.S
new file mode 100644
index 000000000..e0d7971d8
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50712/pmuenable.S
@@ -0,0 +1,48 @@
+/*
+ * Power Management unit initialization code for AMAZON development board.
+ *
+ * Copyright (c) 2003 Ou Ke, Infineon.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <config.h>
+#include <version.h>
+#include <asm/regdef.h>
+
+#define PMU_PWDCR 0xBF10201C
+#define PMU_SR 0xBF102020
+
+ .globl pmuenable
+
+pmuenable:
+ li t0, PMU_PWDCR
+ li t1, 0x2 /* enable everything */
+ sw t1, 0(t0)
+#if 0
+1:
+ li t0, PMU_SR
+ lw t2, 0(t0)
+ bne t1, t2, 1b
+ nop
+#endif
+ j ra
+ nop
+
+
diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/u-boot-bootstrap.lds b/package/uboot-lantiq/files/board/infineon/easy50712/u-boot-bootstrap.lds
new file mode 100644
index 000000000..52d7dafad
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50712/u-boot-bootstrap.lds
@@ -0,0 +1,74 @@
+/*
+ * (C) Copyright 2010 Industrie Dial Face S.p.A.
+ * Luigi 'Comio' Mantellini, luigi.mantellini@idf-hit.com
+ *
+ * (C) Copyright 2003
+ * Wolfgang Denk Engineering, <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+/*
+OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-bigmips")
+*/
+OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradlittlemips")
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = .;
+ _gp = ALIGN(16) +0x7ff0;
+
+ .got : {
+ __got_start = .;
+ *(.got)
+ __got_end = .;
+ }
+
+ . = ALIGN(4);
+ .sdata : { *(.sdata) }
+
+ . = .;
+ . = ALIGN(4);
+ .payload : { *(.payload) }
+ . = ALIGN(4);
+
+ uboot_end_data = .;
+ num_got_entries = (__got_end - __got_start) >> 2;
+
+ . = ALIGN(4);
+ .sbss : { *(.sbss) }
+ .bss : { *(.bss) . = ALIGN(4); }
+ uboot_end = .;
+}
+
diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/u-boot.lds b/package/uboot-lantiq/files/board/infineon/easy50712/u-boot.lds
new file mode 100644
index 000000000..9a6cd1b8a
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50712/u-boot.lds
@@ -0,0 +1,70 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk Engineering, <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+/*
+OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-bigmips")
+*/
+OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradbigmips")
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = .;
+ _gp = ALIGN(16) + 0x7ff0;
+
+ .got : {
+ __got_start = .;
+ *(.got)
+ __got_end = .;
+ }
+
+ .sdata : { *(.sdata) }
+
+ .u_boot_cmd : {
+ __u_boot_cmd_start = .;
+ *(.u_boot_cmd)
+ __u_boot_cmd_end = .;
+ }
+
+ uboot_end_data = .;
+ num_got_entries = (__got_end - __got_start) >> 2;
+
+ . = ALIGN(4);
+ .sbss (NOLOAD) : { *(.sbss) }
+ .bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
+ uboot_end = .;
+}
diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/Makefile b/package/uboot-lantiq/files/board/infineon/easy50812/Makefile
new file mode 100644
index 000000000..97d189895
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50812/Makefile
@@ -0,0 +1,62 @@
+#
+# (C) Copyright 2003-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(BOARD).a
+BOOTSTRAP_LIB = $(obj)lib$(BOARD)_bootstrap.a
+
+BOOTSTRAP_LIB-$(CONFIG_BOOTSTRAP) = $(BOOTSTRAP_LIB)
+
+COBJS-y += ar9.o
+
+SOBJS = lowlevel_init.o pmuenable.o
+
+BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) = $(BOARD)_bootstrap.o
+BOOTSTRAP_SOBJS-$(CONFIG_BOOTSTRAP) = lowlevel_bootstrap_init.o
+
+BOOTSTRAP_SRCS := $(BOOTSTRAP_SOBJS-y:.o=.S) $(BOOTSTRAP_COBJS-y:.o=.c)
+
+SRCS := $(sort $(SOBJS:.o=.S) $(COBJS:.o=.c) $(BOOTSTRAP_SOBJS:.o=.S))
+OBJS := $(addprefix $(obj),$(COBJS-y))
+SOBJS := $(addprefix $(obj),$(SOBJS))
+BOOTSTRAP_OBJS := $(addprefix $(obj),$(BOOTSTRAP_COBJS-y))
+BOOTSTRAP_SOBJS := $(addprefix $(obj),$(BOOTSTRAP_SOBJS-y))
+
+
+all: $(obj).depend $(LIB) $(BOOTSTRAP_LIB)
+
+$(LIB): $(obj).depend $(OBJS) $(SOBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
+
+$(BOOTSTRAP_LIB): $(BOOTSTRAP_OBJS) $(BOOTSTRAP_SOBJS)
+ $(AR) $(ARFLAGS) $@ $(BOOTSTRAP_OBJS) $(BOOTSTRAP_SOBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/ar9.c b/package/uboot-lantiq/files/board/infineon/easy50812/ar9.c
new file mode 100644
index 000000000..d4cd049af
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50812/ar9.c
@@ -0,0 +1,619 @@
+/*
+* (C) Copyright 2003
+* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+*
+* (C) Copyright 2010
+* Thomas Langer, Ralph Hempel
+*
+* See file CREDITS for list of people who contributed to this
+* project.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License, or (at your option) any later version.
+*
+* 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
+*/
+
+#include <common.h>
+#include <command.h>
+#include <netdev.h>
+#include <miiphy.h>
+#include <asm/addrspace.h>
+#include <asm/ar9.h>
+#include <asm/reboot.h>
+#include <asm/io.h>
+#if defined(CONFIG_CMD_HTTPD)
+#include <httpd.h>
+#endif
+
+extern ulong ifx_get_ddr_hz(void);
+extern ulong ifx_get_cpuclk(void);
+
+/* definitions for external PHYs / Switches */
+/* Split values into phy address and register address */
+#define PHYADDR(_reg) ((_reg >> 5) & 0xff), (_reg & 0x1f)
+
+/* IDs and registers of known external switches */
+#define ID_SAMURAI_0 0x1020
+#define ID_SAMURAI_1 0x0007
+#define SAMURAI_ID_REG0 0xA0
+#define SAMURAI_ID_REG1 0xA1
+#define ID_TANTOS 0x2599
+
+#define RGMII_MODE 0
+#define MII_MODE 1
+#define REV_MII_MODE 2
+#define RED_MII_MODE_IC 3 /*Input clock */
+#define RGMII_MODE_100MB 4
+#define TURBO_REV_MII_MODE 6 /*Turbo Rev Mii mode */
+#define RED_MII_MODE_OC 7 /*Output clock */
+#define RGMII_MODE_10MB 8
+
+#define mdelay(n) udelay((n)*1000)
+
+static void ar9_sw_chip_init(u8 port, u8 mode);
+static void ar9_enable_sw_port(u8 port, u8 state);
+static void ar9_configure_sw_port(u8 port, u8 mode);
+static u16 ar9_smi_reg_read(u16 reg);
+static u16 ar9_smi_reg_write(u16 reg, u16 data);
+static char * const name = "lq_cpe_eth";
+static int external_switch_init(void);
+
+void _machine_restart(void)
+{
+ *AR9_RCU_RST_REQ |= AR9_RST_ALL;
+}
+
+#ifdef CONFIG_SYS_RAMBOOT
+phys_size_t initdram(int board_type)
+{
+ return get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_MAX_RAM);
+}
+#elif defined(CONFIG_USE_DDR_RAM)
+phys_size_t initdram(int board_type)
+{
+ return (CONFIG_SYS_MAX_RAM);
+}
+#else
+
+static ulong max_sdram_size(void) /* per Chip Select */
+{
+ /* The only supported SDRAM data width is 16bit.
+ */
+#define CFG_DW 4
+
+ /* The only supported number of SDRAM banks is 4.
+ */
+#define CFG_NB 4
+
+ ulong cfgpb0 = *AR9_SDRAM_MC_CFGPB0;
+ int cols = cfgpb0 & 0xF;
+ int rows = (cfgpb0 & 0xF0) >> 4;
+ ulong size = (1 << (rows + cols)) * CFG_DW * CFG_NB;
+
+ return size;
+}
+
+/*
+* Check memory range for valid RAM. A simple memory test determines
+* the actually available RAM size between addresses `base' and
+* `base + maxsize'.
+*/
+
+static long int dram_size(long int *base, long int maxsize)
+{
+ volatile long int *addr;
+ ulong cnt, val;
+ ulong save[32]; /* to make test non-destructive */
+ unsigned char i = 0;
+
+ for (cnt = (maxsize / sizeof (long)) >> 1; cnt > 0; cnt >>= 1) {
+ addr = base + cnt; /* pointer arith! */
+
+ save[i++] = *addr;
+ *addr = ~cnt;
+ }
+
+ /* write 0 to base address */
+ addr = base;
+ save[i] = *addr;
+ *addr = 0;
+
+ /* check at base address */
+ if ((val = *addr) != 0) {
+ *addr = save[i];
+ return (0);
+ }
+
+ for (cnt = 1; cnt < maxsize / sizeof (long); cnt <<= 1) {
+ addr = base + cnt; /* pointer arith! */
+
+ val = *addr;
+ *addr = save[--i];
+
+ if (val != (~cnt)) {
+ return (cnt * sizeof (long));
+ }
+ }
+ return (maxsize);
+}
+
+phys_size_t initdram(int board_type)
+{
+ int rows, cols, best_val = *AR9_SDRAM_MC_CFGPB0;
+ ulong size, max_size = 0;
+ ulong our_address;
+
+ /* load t9 into our_address */
+ asm volatile ("move %0, $25" : "=r" (our_address) :);
+
+ /* Can't probe for RAM size unless we are running from Flash.
+ * find out whether running from DRAM or Flash.
+ */
+ if (CPHYSADDR(our_address) < CPHYSADDR(PHYS_FLASH_1))
+ {
+ return max_sdram_size();
+ }
+
+ for (cols = 0x8; cols <= 0xC; cols++)
+ {
+ for (rows = 0xB; rows <= 0xD; rows++)
+ {
+ *AR9_SDRAM_MC_CFGPB0 = (0x14 << 8) |
+ (rows << 4) | cols;
+ size = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE,
+ max_sdram_size());
+
+ if (size > max_size)
+ {
+ best_val = *AR9_SDRAM_MC_CFGPB0;
+ max_size = size;
+ }
+ }
+ }
+
+ *AR9_SDRAM_MC_CFGPB0 = best_val;
+ return max_size;
+}
+#endif
+
+int checkboard (void)
+{
+ unsigned long chipid = *AR9_MPS_CHIPID;
+ int part_num;
+
+ puts ("Board: ");
+
+ part_num = AR9_MPS_CHIPID_PARTNUM_GET(chipid);
+ switch (part_num)
+ {
+ case 0x16C:
+ puts("ARX188 ");
+ break;
+ case 0x16D:
+ puts("ARX168 ");
+ break;
+ case 0x16F:
+ puts("ARX182 ");
+ break;
+ case 0x170:
+ puts("GRX188 ");
+ break;
+ case 0x171:
+ puts("GRX168 ");
+ break;
+ default:
+ printf ("unknown, chip part number 0x%03X ", part_num);
+ break;
+ }
+ printf ("V1.%ld, ", AR9_MPS_CHIPID_VERSION_GET(chipid));
+
+ printf("DDR Speed %ld MHz, ", ifx_get_ddr_hz()/1000000);
+ printf("CPU Speed %ld MHz\n", ifx_get_cpuclk()/1000000);
+
+ return 0;
+}
+
+#ifdef CONFIG_SKIP_LOWLEVEL_INIT
+int board_early_init_f(void)
+{
+#ifdef CONFIG_EBU_ADDSEL0
+ (*AR9_EBU_ADDSEL0) = CONFIG_EBU_ADDSEL0;
+#endif
+#ifdef CONFIG_EBU_ADDSEL1
+ (*AR9_EBU_ADDSEL1) = CONFIG_EBU_ADDSEL1;
+#endif
+#ifdef CONFIG_EBU_ADDSEL2
+ (*AR9_EBU_ADDSEL2) = CONFIG_EBU_ADDSEL2;
+#endif
+#ifdef CONFIG_EBU_ADDSEL3
+ (*AR9_EBU_ADDSEL3) = CONFIG_EBU_ADDSEL3;
+#endif
+#ifdef CONFIG_EBU_BUSCON0
+ (*AR9_EBU_BUSCON0) = CONFIG_EBU_BUSCON0;
+#endif
+#ifdef CONFIG_EBU_BUSCON1
+ (*AR9_EBU_BUSCON1) = CONFIG_EBU_BUSCON1;
+#endif
+#ifdef CONFIG_EBU_BUSCON2
+ (*AR9_EBU_BUSCON2) = CONFIG_EBU_BUSCON2;
+#endif
+#ifdef CONFIG_EBU_BUSCON3
+ (*AR9_EBU_BUSCON3) = CONFIG_EBU_BUSCON3;
+#endif
+
+ return 0;
+}
+#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
+
+int board_eth_init(bd_t *bis)
+{
+#if defined(CONFIG_IFX_ETOP)
+
+ *AR9_PMU_PWDCR &= 0xFFFFEFDF;
+ *AR9_PMU_PWDCR &= ~AR9_PMU_DMA; /* enable DMA from PMU */
+
+ if (lq_eth_initialize(bis) < 0)
+ return -1;
+
+ *AR9_RCU_RST_REQ |= 1;
+ udelay(200000);
+ *AR9_RCU_RST_REQ &= (unsigned long)~1;
+ udelay(1000);
+
+#ifdef CONFIG_EXTRA_SWITCH
+ if (external_switch_init()<0)
+ return -1;
+#endif /* CONFIG_EXTRA_SWITCH */
+#endif /* CONFIG_IFX_ETOP */
+
+ return 0;
+}
+
+static void ar9_configure_sw_port(u8 port, u8 mode)
+{
+ if(port)
+ {
+ if (mode == 1) //MII mode
+ {
+ *AR9_GPIO_P2_ALTSEL0 = *AR9_GPIO_P2_ALTSEL0 | (0xf000);
+ *AR9_GPIO_P2_ALTSEL1 = *AR9_GPIO_P2_ALTSEL1 & ~(0xf000);
+ *AR9_GPIO_P2_DIR = (*AR9_GPIO_P2_DIR & ~(0xf000)) | 0x2000;
+ *AR9_GPIO_P2_OD = *AR9_GPIO_P2_OD | 0x2000;
+ }
+ else if(mode == 2 || mode == 6) //Rev Mii mode
+ {
+ *AR9_GPIO_P2_ALTSEL0 = *AR9_GPIO_P2_ALTSEL0 | (0xf000);
+ *AR9_GPIO_P2_ALTSEL1 = *AR9_GPIO_P2_ALTSEL1 & ~(0xf000);
+ *AR9_GPIO_P2_DIR = (*AR9_GPIO_P2_DIR | (0xf000)) & ~0x2000;
+ *AR9_GPIO_P2_OD = *AR9_GPIO_P2_OD | 0xd000;
+ }
+ }
+ else //Port 0
+ {
+ if (mode == 1) //MII mode
+ {
+ *AR9_GPIO_P2_ALTSEL0 = *AR9_GPIO_P2_ALTSEL0 | (0x0303);
+ *AR9_GPIO_P2_ALTSEL1 = *AR9_GPIO_P2_ALTSEL1 & ~(0x0303);
+ *AR9_GPIO_P2_DIR = (*AR9_GPIO_P2_DIR & ~(0x0303)) | 0x0100;
+ *AR9_GPIO_P2_OD = *AR9_GPIO_P2_OD | 0x0100;
+ }
+ else if(mode ==2 || mode ==6) //Rev Mii mode
+ {
+ *AR9_GPIO_P2_ALTSEL0 = *AR9_GPIO_P2_ALTSEL0 | (0x0303);
+ *AR9_GPIO_P2_ALTSEL1 = *AR9_GPIO_P2_ALTSEL1 & ~(0x0303);
+ *AR9_GPIO_P2_DIR = (*AR9_GPIO_P2_DIR | (0x0303)) & ~0x0100;
+ *AR9_GPIO_P2_OD = *AR9_GPIO_P2_OD | 0x0203;
+ }
+ }
+}
+
+/*
+Call this function to place either MAC port 0 or 1 into working mode.
+Parameters:
+port - select ports 0 or 1.
+state of interface : state
+0: RGMII
+1: MII
+2: Rev MII
+3: Reduce MII (input clock)
+4: RGMII 100mb
+5: Reserve
+6: Turbo Rev MII
+7: Reduce MII (output clock)
+*/
+void ar9_enable_sw_port(u8 port, u8 state)
+{
+ REG32(AR9_SW_GCTL0) |= 0x80000000;
+ if (port == 0)
+ {
+ REG32(AR9_SW_RGMII_CTL) &= 0xffcffc0e ;
+ //#if AR9_REFBOARD_TANTOS
+ REG32(0xbf20302c) &= 0xffff81ff;
+ REG32(0xbf20302c) |= 4<<9 ;
+ //#endif
+ REG32(AR9_SW_RGMII_CTL) |= ((u32)(state &0x3))<<8;
+ if((state &0x3) == 0)
+ {
+ REG32(AR9_SW_RGMII_CTL) &= 0xfffffff3;
+ if(state == 4)
+ REG32(AR9_SW_RGMII_CTL) |= 0x4;
+ else
+ REG32(AR9_SW_RGMII_CTL) |= 0x8;
+ }
+ if(state == 6)
+ REG32(AR9_SW_RGMII_CTL) |= ((u32) (1<<20));
+ if(state == 7)
+ REG32(AR9_SW_RGMII_CTL) |= ((u32) (1<<21));
+ }
+// *AR9_PPE32_ETOP_CFG = *AR9_PPE32_ETOP_CFG & 0xfffffffe;
+ else
+ {
+ REG32(AR9_SW_RGMII_CTL) &= 0xff303fff ;
+ REG32(AR9_SW_RGMII_CTL) |= ((u32)(state &0x3))<<18;
+ if((state &0x3) == 0)
+ {
+ REG32(AR9_SW_RGMII_CTL) &= 0xffffcfff;
+ if(state == 4)
+ REG32(AR9_SW_RGMII_CTL) |= 0x1000;
+ else
+ REG32(AR9_SW_RGMII_CTL) |= 0x2000;
+ }
+ if(state == 6)
+ REG32(AR9_SW_RGMII_CTL) |= ((u32) (1<<22));
+ if(state == 7)
+ REG32(AR9_SW_RGMII_CTL) |= ((u32) (1<<23));
+ }
+}
+
+void pci_reset(void)
+{
+ int i,j;
+#define AR9_V1_PCI_RST_FIX 1
+#if AR9_V1_PCI_RST_FIX // 5th June 2008 Add GPIO19 to control EJTAG_TRST
+ *AR9_GPIO_P1_ALTSEL0 = *AR9_GPIO_P1_ALTSEL0 & ~0x8;
+ *AR9_GPIO_P1_ALTSEL1 = *AR9_GPIO_P1_ALTSEL1 & ~0x8;
+ *AR9_GPIO_P1_DIR = *AR9_GPIO_P1_DIR | 0x8;
+ *AR9_GPIO_P1_OD = *AR9_GPIO_P1_OD | 0x8;
+ *AR9_GPIO_P1_OUT = *AR9_GPIO_P1_OUT | 0x8;
+ *AR9_GPIO_P0_ALTSEL0 = *AR9_GPIO_P0_ALTSEL0 & ~0x4000;
+ *AR9_GPIO_P0_ALTSEL1 = *AR9_GPIO_P0_ALTSEL1 & ~0x4000;
+ *AR9_GPIO_P0_DIR = *AR9_GPIO_P0_DIR | 0x4000;
+ *AR9_GPIO_P0_OD = *AR9_GPIO_P0_OD | 0x4000;
+ for(j=0;j<5;j++) {
+ *AR9_GPIO_P0_OUT = *AR9_GPIO_P0_OUT & ~0x4000;
+ for(i=0;i<0x10000;i++);
+ *AR9_GPIO_P0_OUT = *AR9_GPIO_P0_OUT | 0x4000;
+ for(i=0;i<0x10000;i++);
+ }
+ *AR9_GPIO_P0_DIR = *AR9_GPIO_P0_DIR & ~0x4000;
+ *AR9_GPIO_P1_DIR = *AR9_GPIO_P1_DIR & ~0x8;
+#endif
+}
+
+static u16 ar9_smi_reg_read(u16 reg)
+{
+ int i;
+ while(REG32(AR9_SW_MDIO_CTL) & 0x8000);
+ REG32(AR9_SW_MDIO_CTL) = 0x8000| 0x2<<10 | ((u32) (reg&0x3ff)) ; /*0x10=MDIO_OP_READ*/
+ for(i=0;i<0x3fff;i++);
+ udelay(50);
+ while(REG32(AR9_SW_MDIO_CTL) & 0x8000);
+ return((u16) (REG32(AR9_SW_MDIO_DATA)));
+}
+
+static u16 ar9_smi_reg_write(u16 reg, u16 data)
+{
+ int i;
+ while(REG32(AR9_SW_MDIO_CTL) & 0x8000);
+ REG32(AR9_SW_MDIO_CTL) = 0x8000| (((u32) data)<<16) | 0x01<<10 | ((u32) (reg&0x3ff)) ; /*0x01=MDIO_OP_WRITE*/
+ for(i=0;i<0x3fff;i++);
+ udelay(50);
+ return 0;
+}
+
+static void ar9_sw_chip_init(u8 port, u8 mode)
+{
+ int i;
+ u16 chipid;
+
+ debug("\nsearching for switches ... ");
+
+ asm("sync");
+ pci_reset();
+
+ /* 25mhz clock out */
+ *AR9_CGU_IFCCR &= ~(3<<10);
+ *AR9_GPIO_P0_ALTSEL0 = *AR9_GPIO_P0_ALTSEL0 | (1<<3);
+ *AR9_GPIO_P0_ALTSEL1 = *AR9_GPIO_P0_ALTSEL1 & ~(1<<3);
+ *AR9_GPIO_P0_DIR = *AR9_GPIO_P0_DIR | (1<<3);
+ *AR9_GPIO_P0_OD = *AR9_GPIO_P0_OD | (1<<3);
+ *AR9_GPIO_P2_ALTSEL0 = *AR9_GPIO_P2_ALTSEL0 & ~(1<<0);
+ *AR9_GPIO_P2_ALTSEL1 = *AR9_GPIO_P2_ALTSEL1 & ~(1<<0);
+ *AR9_GPIO_P2_DIR = *AR9_GPIO_P2_DIR | (1<<0);
+ *AR9_GPIO_P2_OD = *AR9_GPIO_P2_OD | (1<<0);
+
+ *AR9_PMU_PWDCR = (*AR9_PMU_PWDCR & 0xFFFBDFDF) ;
+ *AR9_PMU_PWDCR = (*AR9_PMU_PWDCR & ~(AR9_PMU_DMA | AR9_PMU_SWITCH));
+ *AR9_PMU_PWDCR = (*AR9_PMU_PWDCR | AR9_PMU_USB0 | AR9_PMU_USB0_P);
+
+ *AR9_GPIO_P2_OUT &= ~(1<<0);
+ asm("sync");
+
+ ar9_configure_sw_port(port, mode);
+ ar9_enable_sw_port(port, mode);
+ REG32(AR9_SW_P0_CTL) |= 0x400000; /* disable mdio polling for tantos */
+ asm("sync");
+
+ /*GPIO 55(P3.7) used as output, set high*/
+ *AR9_GPIO_P3_OD |=(1<<7);
+ *AR9_GPIO_P3_DIR |= (1<<7);
+ *AR9_GPIO_P3_ALTSEL0 &=~(1<<7);
+ *AR9_GPIO_P3_ALTSEL1 &=~(1<<7);
+ asm("sync");
+ udelay(10);
+
+ *AR9_GPIO_P3_OUT &= ~(1<<7);
+ for(i=0;i<1000;i++)
+ udelay(110);
+ *AR9_GPIO_P3_OUT |=(1<<7);
+ udelay(100);
+
+ if(port==0)
+ REG32(AR9_SW_P0_CTL) |= 0x40001;
+ else
+ REG32(AR9_SW_P1_CTL) |= 0x40001;
+
+ REG32(AR9_SW_P2_CTL) |= 0x40001;
+ REG32(AR9_SW_PMAC_HD_CTL) |= 0x40000; /* enable CRC */
+
+ *AR9_GPIO_P2_ALTSEL0 = *AR9_GPIO_P2_ALTSEL0 | (0xc00);
+ *AR9_GPIO_P2_ALTSEL1 = *AR9_GPIO_P2_ALTSEL1 & ~(0xc00);
+ *AR9_GPIO_P2_DIR = *AR9_GPIO_P2_DIR | 0xc00;
+ *AR9_GPIO_P2_OD = *AR9_GPIO_P2_OD | 0xc00;
+
+ asm("sync");
+ chipid = (unsigned short)(ar9_smi_reg_read(0x101));
+ printf("\nswitch chip id=%08x\n",chipid);
+ if (chipid != ID_TANTOS) {
+ debug("whatever detected\n");
+ ar9_smi_reg_write(0x1,0x840f);
+ ar9_smi_reg_write(0x3,0x840f);
+ ar9_smi_reg_write(0x5,0x840f);
+ ar9_smi_reg_write(0x7,0x840f);
+ ar9_smi_reg_write(0x8,0x840f);
+ ar9_smi_reg_write(0x12,0x3602);
+#ifdef CLK_OUT2_25MHZ
+ ar9_smi_reg_write(0x33,0x4000);
+#endif
+ } else { // Tantos switch ship
+ debug("Tantos switch detected\n");
+ ar9_smi_reg_write(0xa1,0x0004); /*port 5 force link up*/
+ ar9_smi_reg_write(0xc1,0x0004); /*port 6 force link up*/
+ ar9_smi_reg_write(0xf5,0x0BBB); /*port 4 duplex mode, flow control enable,1000Mbit/s*/
+ /*port 5 duplex mode, flow control enable, 1000Mbit/s*/
+ /*port 6 duplex mode, flow control enable, 1000Mbit/s*/
+ }
+ asm("sync");
+
+ /*reset GPHY*/
+ mdelay(200);
+ *AR9_RCU_RST_REQ |= (AR9_RCU_RST_REQ_DMA | AR9_RCU_RST_REQ_PPE) ;
+ udelay(50);
+ *AR9_GPIO_P2_OUT |= (1<<0);
+}
+
+static void ar9_dma_init(void)
+{
+ /* select port */
+ *AR9_DMA_PS = 0;
+
+ /*
+ TXWGT 14:12 rw Port Weight for Transmit Direction (the default value “001”)
+
+ TXENDI 11:10 rw Endianness for Transmit Direction
+ Determine a byte swap between memory interface (left hand side) and
+ peripheral interface (right hand side).
+ 00B B0_B1_B2_B3 No byte switching
+ 01B B1_B0_B3_B2 B0B1B2B3 => B1B0B3B2
+ 10B B2_B3_B0_B1 B0B1B2B3 => B2B3B0B1
+
+ RXENDI 9:8 rw Endianness for Receive Direction
+ Determine a byte swap between peripheral (left hand side) and memory
+ interface (right hand side).
+ 00B B0_B1_B2_B3 No byte switching
+ 01B B1_B0_B3_B2 B0B1B2B3 => B1B0B3B2
+ 10B B2_B3_B0_B1 B0B1B2B3 => B2B3B0B1
+ 11B B3_B2_B1_B0 B0B1B2B3 => B3B2B1B0
+
+ TXBL 5:4 rw Burst Length for Transmit Direction
+ Selects burst length for TX direction.
+ Others are reserved and will result in 2_WORDS burst length.
+ 01B 2_WORDS 2 words
+ 10B 4_WORDS 4 words
+ 11B 8_WORDS 8 words
+
+ RXBL 3:2 rw Burst Length for Receive Direction
+ Selects burst length for RX direction.
+ Others are reserved and will result in 2_WORDS burst length.
+ 01B 2_WORDS 2 words
+ 10B 4_WORDS 4 words
+ 11B 8_WORDS 8 words
+ */
+ *AR9_DMA_PCTRL = 0x1f28;
+}
+
+#ifdef CONFIG_EXTRA_SWITCH
+static int external_switch_init(void)
+{
+ ar9_sw_chip_init(0, RGMII_MODE);
+
+ ar9_dma_init();
+
+ return 0;
+}
+#endif /* CONFIG_EXTRA_SWITCH */
+
+#if defined(CONFIG_CMD_HTTPD)
+int do_http_upgrade(const unsigned char *data, const ulong size)
+{
+ char buf[128];
+
+ if(getenv ("ram_addr") == NULL)
+ return -1;
+ if(getenv ("kernel_addr") == NULL)
+ return -1;
+ /* check the image */
+ if(run_command("imi ${ram_addr}", 0) < 0) {
+ return -1;
+ }
+ /* write the image to the flash */
+ puts("http ugrade ...\n");
+ sprintf(buf, "era ${kernel_addr} +0x%x; cp.b ${ram_addr} ${kernel_addr} 0x%x", size, size);
+ return run_command(buf, 0);
+}
+
+int do_http_progress(const int state)
+{
+ /* toggle LED's here */
+ switch(state) {
+ case HTTP_PROGRESS_START:
+ puts("http start\n");
+ break;
+ case HTTP_PROGRESS_TIMEOUT:
+ puts(".");
+ break;
+ case HTTP_PROGRESS_UPLOAD_READY:
+ puts("http upload ready\n");
+ break;
+ case HTTP_PROGRESS_UGRADE_READY:
+ puts("http ugrade ready\n");
+ break;
+ case HTTP_PROGRESS_UGRADE_FAILED:
+ puts("http ugrade failed\n");
+ break;
+ }
+ return 0;
+}
+
+unsigned long do_http_tmp_address(void)
+{
+ char *s = getenv ("ram_addr");
+ if (s) {
+ ulong tmp = simple_strtoul (s, NULL, 16);
+ return tmp;
+ }
+ return 0 /*0x80a00000*/;
+}
+
+#endif
diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr111_settings.h b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr111_settings.h
new file mode 100644
index 000000000..766f1e00d
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr111_settings.h
@@ -0,0 +1,51 @@
+/* Settings for Denali DDR SDRAM controller */
+/* Optimise for Samsung DDR K4H561638H Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 27th Nov 2006 */
+
+#define MC_DC0_VALUE 0x1B1B
+#define MC_DC1_VALUE 0x0
+#define MC_DC2_VALUE 0x0
+#define MC_DC3_VALUE 0x0
+#define MC_DC4_VALUE 0x0
+#define MC_DC5_VALUE 0x200
+#define MC_DC6_VALUE 0x306
+#define MC_DC7_VALUE 0x303
+#define MC_DC8_VALUE 0x102
+#define MC_DC9_VALUE 0x70a
+#define MC_DC10_VALUE 0x203
+#define MC_DC11_VALUE 0xc02
+#define MC_DC12_VALUE 0x1C8
+#define MC_DC13_VALUE 0x1
+#define MC_DC14_VALUE 0x0
+#define MC_DC15_VALUE 0x139 /* WDQS tuning for clk_wr*/
+#define MC_DC16_VALUE 0x2200
+#define MC_DC17_VALUE 0xd
+#define MC_DC18_VALUE 0x301
+#define MC_DC19_VALUE 0x200
+#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */
+#define MC_DC21_VALUE 0x1800
+#define MC_DC22_VALUE 0x1818
+#define MC_DC23_VALUE 0x0
+#define MC_DC24_VALUE 0x59 /* WDQS Tuning for DQS */
+#define MC_DC25_VALUE 0x0
+#define MC_DC26_VALUE 0x0
+#define MC_DC27_VALUE 0x0
+#define MC_DC28_VALUE 0x514
+#define MC_DC29_VALUE 0x2d93
+#define MC_DC30_VALUE 0x8235
+#define MC_DC31_VALUE 0x0
+#define MC_DC32_VALUE 0x0
+#define MC_DC33_VALUE 0x0
+#define MC_DC34_VALUE 0x0
+#define MC_DC35_VALUE 0x0
+#define MC_DC36_VALUE 0x0
+#define MC_DC37_VALUE 0x0
+#define MC_DC38_VALUE 0x0
+#define MC_DC39_VALUE 0x0
+#define MC_DC40_VALUE 0x0
+#define MC_DC41_VALUE 0x0
+#define MC_DC42_VALUE 0x0
+#define MC_DC43_VALUE 0x0
+#define MC_DC44_VALUE 0x0
+#define MC_DC45_VALUE 0x600
+//#define MC_DC45_VALUE 0x400
+#define MC_DC46_VALUE 0x0
diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr166_settings.h b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr166_settings.h
new file mode 100644
index 000000000..6d940ac6c
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr166_settings.h
@@ -0,0 +1,51 @@
+/* Settings for Denali DDR SDRAM controller */
+/* Optimise for Samsung DDR K4H561638H Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 27th Nov 2006 */
+
+#define MC_DC0_VALUE 0x1B1B
+#define MC_DC1_VALUE 0x0
+#define MC_DC2_VALUE 0x0
+#define MC_DC3_VALUE 0x0
+#define MC_DC4_VALUE 0x0
+#define MC_DC5_VALUE 0x200
+#define MC_DC6_VALUE 0x306
+#define MC_DC7_VALUE 0x303
+#define MC_DC8_VALUE 0x102
+#define MC_DC9_VALUE 0x70a
+#define MC_DC10_VALUE 0x203
+#define MC_DC11_VALUE 0xc02
+#define MC_DC12_VALUE 0x1C8
+#define MC_DC13_VALUE 0x1
+#define MC_DC14_VALUE 0x0
+#define MC_DC15_VALUE 0x13f /* WDQS tuning for clk_wr*/
+#define MC_DC16_VALUE 0x2200
+#define MC_DC17_VALUE 0xd
+#define MC_DC18_VALUE 0x301
+#define MC_DC19_VALUE 0x200
+#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */
+#define MC_DC21_VALUE 0x1600
+#define MC_DC22_VALUE 0x1616
+#define MC_DC23_VALUE 0x0
+#define MC_DC24_VALUE 0x5d /* WDQS Tuning for DQS */
+#define MC_DC25_VALUE 0x0
+#define MC_DC26_VALUE 0x0
+#define MC_DC27_VALUE 0x0
+#define MC_DC28_VALUE 0x514
+#define MC_DC29_VALUE 0x2d93
+#define MC_DC30_VALUE 0x8235
+#define MC_DC31_VALUE 0x0
+#define MC_DC32_VALUE 0x0
+#define MC_DC33_VALUE 0x0
+#define MC_DC34_VALUE 0x0
+#define MC_DC35_VALUE 0x0
+#define MC_DC36_VALUE 0x0
+#define MC_DC37_VALUE 0x0
+#define MC_DC38_VALUE 0x0
+#define MC_DC39_VALUE 0x0
+#define MC_DC40_VALUE 0x0
+#define MC_DC41_VALUE 0x0
+#define MC_DC42_VALUE 0x0
+#define MC_DC43_VALUE 0x0
+#define MC_DC44_VALUE 0x0
+#define MC_DC45_VALUE 0x600
+//#define MC_DC45_VALUE 0x400
+#define MC_DC46_VALUE 0x0
diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr196_settings.h b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr196_settings.h
new file mode 100644
index 000000000..45daa188d
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr196_settings.h
@@ -0,0 +1,51 @@
+/* Settings for Denali DDR SDRAM controller */
+/* Optimise for Samsung DDR K4H561638H Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 27th Nov 2006 */
+
+#define MC_DC0_VALUE 0x1B1B
+#define MC_DC1_VALUE 0x0
+#define MC_DC2_VALUE 0x0
+#define MC_DC3_VALUE 0x0
+#define MC_DC4_VALUE 0x0
+#define MC_DC5_VALUE 0x200
+#define MC_DC6_VALUE 0x306
+#define MC_DC7_VALUE 0x303
+#define MC_DC8_VALUE 0x102
+#define MC_DC9_VALUE 0x80B
+#define MC_DC10_VALUE 0x203
+#define MC_DC11_VALUE 0xD02
+#define MC_DC12_VALUE 0x1C8
+#define MC_DC13_VALUE 0x1
+#define MC_DC14_VALUE 0x0
+#define MC_DC15_VALUE 0x144 /* WDQS tuning for clk_wr*/
+#define MC_DC16_VALUE 0xC800
+#define MC_DC17_VALUE 0xF
+#define MC_DC18_VALUE 0x301
+#define MC_DC19_VALUE 0x200
+#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */
+#define MC_DC21_VALUE 0x1200
+#define MC_DC22_VALUE 0x1212
+#define MC_DC23_VALUE 0x0
+#define MC_DC24_VALUE 0x66 /* WDQS Tuning for DQS */
+#define MC_DC25_VALUE 0x0
+#define MC_DC26_VALUE 0x0
+#define MC_DC27_VALUE 0x0
+#define MC_DC28_VALUE 0x5FB
+#define MC_DC29_VALUE 0x35DF
+#define MC_DC30_VALUE 0x99E9
+#define MC_DC31_VALUE 0x0
+#define MC_DC32_VALUE 0x0
+#define MC_DC33_VALUE 0x0
+#define MC_DC34_VALUE 0x0
+#define MC_DC35_VALUE 0x0
+#define MC_DC36_VALUE 0x0
+#define MC_DC37_VALUE 0x0
+#define MC_DC38_VALUE 0x0
+#define MC_DC39_VALUE 0x0
+#define MC_DC40_VALUE 0x0
+#define MC_DC41_VALUE 0x0
+#define MC_DC42_VALUE 0x0
+#define MC_DC43_VALUE 0x0
+#define MC_DC44_VALUE 0x0
+#define MC_DC45_VALUE 0x600
+//#define MC_DC45_VALUE 0x400
+#define MC_DC46_VALUE 0x0
diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr221_settings.h b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr221_settings.h
new file mode 100644
index 000000000..7f87d43f7
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr221_settings.h
@@ -0,0 +1,51 @@
+/* Settings for Denali DDR SDRAM controller */
+/* Optimise for AR9 Ref Board DDR 221 Mhz - by Ng Aik Ann 16th May 2008 */
+
+#define MC_DC0_VALUE 0x1B1B
+#define MC_DC1_VALUE 0x0
+#define MC_DC2_VALUE 0x0
+#define MC_DC3_VALUE 0x0
+#define MC_DC4_VALUE 0x0
+#define MC_DC5_VALUE 0x200
+#define MC_DC6_VALUE 0x306
+#define MC_DC7_VALUE 0x403
+#define MC_DC8_VALUE 0x102
+#define MC_DC9_VALUE 0x90c
+#define MC_DC10_VALUE 0x203
+#define MC_DC11_VALUE 0xf02
+#define MC_DC12_VALUE 0x2c8
+#define MC_DC13_VALUE 0x1
+#define MC_DC14_VALUE 0x0
+#define MC_DC15_VALUE 0x12f /* WDQS tuning for clk_wr*/
+#define MC_DC16_VALUE 0xc800
+#define MC_DC17_VALUE 0xf
+#define MC_DC18_VALUE 0x301
+#define MC_DC19_VALUE 0x200
+#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */
+#define MC_DC21_VALUE 0x1500
+#define MC_DC22_VALUE 0x1515
+#define MC_DC23_VALUE 0x0
+#define MC_DC24_VALUE 0x57 /* WDQS Tuning for DQS */
+#define MC_DC25_VALUE 0x0
+#define MC_DC26_VALUE 0x0
+#define MC_DC27_VALUE 0x0
+#define MC_DC28_VALUE 0x6b8
+#define MC_DC29_VALUE 0x3c84
+#define MC_DC30_VALUE 0xace5
+#define MC_DC31_VALUE 0x0
+#define MC_DC32_VALUE 0x0
+#define MC_DC33_VALUE 0x0
+#define MC_DC34_VALUE 0x0
+#define MC_DC35_VALUE 0x0
+#define MC_DC36_VALUE 0x0
+#define MC_DC37_VALUE 0x0
+#define MC_DC38_VALUE 0x0
+#define MC_DC39_VALUE 0x0
+#define MC_DC40_VALUE 0x0
+#define MC_DC41_VALUE 0x0
+#define MC_DC42_VALUE 0x0
+#define MC_DC43_VALUE 0x0
+#define MC_DC44_VALUE 0x0
+#define MC_DC45_VALUE 0x600
+//#define MC_DC45_VALUE 0x400
+#define MC_DC46_VALUE 0x0
diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr250_settings.h b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr250_settings.h
new file mode 100644
index 000000000..2e49db99d
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr250_settings.h
@@ -0,0 +1,51 @@
+/* Settings for Denali DDR SDRAM controller */
+/* Optimise for AR9 Ref Board DDR 221 Mhz - by Ng Aik Ann 16th May 2008 */
+
+#define MC_DC0_VALUE 0x1B1B
+#define MC_DC1_VALUE 0x0
+#define MC_DC2_VALUE 0x0
+#define MC_DC3_VALUE 0x0
+#define MC_DC4_VALUE 0x0
+#define MC_DC5_VALUE 0x200
+#define MC_DC6_VALUE 0x306
+#define MC_DC7_VALUE 0x403
+#define MC_DC8_VALUE 0x103
+#define MC_DC9_VALUE 0xb0e
+#define MC_DC10_VALUE 0x204
+#define MC_DC11_VALUE 0x1102
+#define MC_DC12_VALUE 0x2c8
+#define MC_DC13_VALUE 0x1
+#define MC_DC14_VALUE 0x0
+#define MC_DC15_VALUE 0x155 /* WDQS tuning for clk_wr*/
+#define MC_DC16_VALUE 0xc800
+#define MC_DC17_VALUE 0x13
+#define MC_DC18_VALUE 0x401
+#define MC_DC19_VALUE 0x200
+#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */
+#define MC_DC21_VALUE 0xc00
+#define MC_DC22_VALUE 0xc0c
+#define MC_DC23_VALUE 0x0
+#define MC_DC24_VALUE 0x74 /* WDQS Tuning for DQS */
+#define MC_DC25_VALUE 0x0
+#define MC_DC26_VALUE 0x0
+#define MC_DC27_VALUE 0x0
+#define MC_DC28_VALUE 0x798
+#define MC_DC29_VALUE 0x445d
+#define MC_DC30_VALUE 0xc351
+#define MC_DC31_VALUE 0x0
+#define MC_DC32_VALUE 0x0
+#define MC_DC33_VALUE 0x0
+#define MC_DC34_VALUE 0x0
+#define MC_DC35_VALUE 0x0
+#define MC_DC36_VALUE 0x0
+#define MC_DC37_VALUE 0x0
+#define MC_DC38_VALUE 0x0
+#define MC_DC39_VALUE 0x0
+#define MC_DC40_VALUE 0x0
+#define MC_DC41_VALUE 0x0
+#define MC_DC42_VALUE 0x0
+#define MC_DC43_VALUE 0x0
+#define MC_DC44_VALUE 0x0
+#define MC_DC45_VALUE 0x600
+//#define MC_DC45_VALUE 0x400
+#define MC_DC46_VALUE 0x0
diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/config.mk b/package/uboot-lantiq/files/board/infineon/easy50812/config.mk
new file mode 100644
index 000000000..b110f6f32
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50812/config.mk
@@ -0,0 +1,40 @@
+#
+# (C) Copyright 2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+
+#
+# Danube board with MIPS 24Kc CPU core
+#
+sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp
+
+ifdef CONFIG_BOOTSTRAP
+TEXT_BASE = 0x80001000
+CONFIG_BOOTSTRAP_TEXT_BASE = 0xb0000000
+CONFIG_SYS_RAMBOOT = y
+else
+
+ifndef TEXT_BASE
+$(info redefine TEXT_BASE = 0xB0000000 )
+TEXT_BASE = 0xB0000000
+endif
+
+endif
diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/easy50812_bootstrap.c b/package/uboot-lantiq/files/board/infineon/easy50812/easy50812_bootstrap.c
new file mode 100644
index 000000000..11bf6d0b7
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50812/easy50812_bootstrap.c
@@ -0,0 +1,48 @@
+/*
+ * (C) Copyright 2010 Industrie Dial Face S.p.A.
+ * Luigi 'Comio' Mantellini, luigi.mantellini@idf-hit.com
+ *
+ * (C) Copyright 2007
+ * Vlad Lungu vlad.lungu@windriver.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/mipsregs.h>
+#include <asm/io.h>
+
+phys_size_t bootstrap_initdram(int board_type)
+{
+ /* Sdram is setup by assembler code */
+ /* If memory could be changed, we should return the true value here */
+ return CONFIG_SYS_MAX_RAM;
+}
+
+int bootstrap_checkboard(void)
+{
+ return 0;
+}
+
+int bootstrap_misc_init_r(void)
+{
+ set_io_port_base(0);
+ return 0;
+}
diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/lowlevel_bootstrap_init.S b/package/uboot-lantiq/files/board/infineon/easy50812/lowlevel_bootstrap_init.S
new file mode 100644
index 000000000..ec82e231c
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50812/lowlevel_bootstrap_init.S
@@ -0,0 +1,597 @@
+/*
+ * Memory sub-system initialization code for Danube board.
+ * Andre Messerschmidt
+ * Copyright (c) 2005 Infineon Technologies AG
+ *
+ * Based on Inca-IP code
+ * Copyright (c) 2003 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+/* History:
+ peng liu May 25, 2006, for PLL setting after reset, 05252006
+ */
+#include <config.h>
+#include <version.h>
+#include <asm/regdef.h>
+
+#if defined(CONFIG_USE_DDR_RAM)
+
+#if defined(CONFIG_CPU_111M_RAM_111M) || defined(CONFIG_CPU_333M_RAM_111M)
+# include "ar9_ddr111_settings.h"
+#elif defined(CONFIG_CPU_166M_RAM_166M) || defined(CONFIG_CPU_333M_RAM_166M) || defined(CONFIG_CPU_500M_RAM_166M)
+# include "ar9_ddr166_settings.h"
+#elif defined(CONFIG_CPU_442M_RAM_147M)
+# include "ar9_ddr166_settings.h"
+#elif defined(CONFIG_CPU_393M_RAM_196M)
+# ifdef CONFIG_ETRON_RAM
+# include "etron_ddr196_settings.h"
+# else
+# include "ar9_ddr196_settings.h"
+# endif
+#elif defined(CONFIG_CPU_442M_RAM_221M)
+# include "ar9_ddr221_settings.h"
+#elif defined(CONFIG_CPU_500M_RAM_250M)
+# include "ar9_ddr250_settings.h"
+#else
+# warning "missing definition for ddr_settings.h, use default!"
+# include "ar9_ddr_settings.h"
+#endif
+#endif /* CONFIG_USE_DDR_RAM */
+
+#define EBU_MODUL_BASE 0xBE105300
+#define EBU_CLC(value) 0x0000(value)
+#define EBU_CON(value) 0x0010(value)
+#define EBU_ADDSEL0(value) 0x0020(value)
+#define EBU_ADDSEL1(value) 0x0024(value)
+#define EBU_ADDSEL2(value) 0x0028(value)
+#define EBU_ADDSEL3(value) 0x002C(value)
+#define EBU_BUSCON0(value) 0x0060(value)
+#define EBU_BUSCON1(value) 0x0064(value)
+#define EBU_BUSCON2(value) 0x0068(value)
+#define EBU_BUSCON3(value) 0x006C(value)
+
+#define MC_MODUL_BASE 0xBF800000
+#define MC_ERRCAUSE(value) 0x0010(value)
+#define MC_ERRADDR(value) 0x0020(value)
+#define MC_CON(value) 0x0060(value)
+
+#define MC_SRAM_ENABLE 0x00000004
+#define MC_SDRAM_ENABLE 0x00000002
+#define MC_DDRRAM_ENABLE 0x00000001
+
+#define MC_SDR_MODUL_BASE 0xBF800200
+#define MC_IOGP(value) 0x0000(value)
+#define MC_CTRLENA(value) 0x0010(value)
+#define MC_MRSCODE(value) 0x0020(value)
+#define MC_CFGDW(value) 0x0030(value)
+#define MC_CFGPB0(value) 0x0040(value)
+#define MC_LATENCY(value) 0x0080(value)
+#define MC_TREFRESH(value) 0x0090(value)
+#define MC_SELFRFSH(value) 0x00A0(value)
+
+#define MC_DDR_MODUL_BASE 0xBF801000
+#define MC_DC00(value) 0x0000(value)
+#define MC_DC01(value) 0x0010(value)
+#define MC_DC02(value) 0x0020(value)
+#define MC_DC03(value) 0x0030(value)
+#define MC_DC04(value) 0x0040(value)
+#define MC_DC05(value) 0x0050(value)
+#define MC_DC06(value) 0x0060(value)
+#define MC_DC07(value) 0x0070(value)
+#define MC_DC08(value) 0x0080(value)
+#define MC_DC09(value) 0x0090(value)
+#define MC_DC10(value) 0x00A0(value)
+#define MC_DC11(value) 0x00B0(value)
+#define MC_DC12(value) 0x00C0(value)
+#define MC_DC13(value) 0x00D0(value)
+#define MC_DC14(value) 0x00E0(value)
+#define MC_DC15(value) 0x00F0(value)
+#define MC_DC16(value) 0x0100(value)
+#define MC_DC17(value) 0x0110(value)
+#define MC_DC18(value) 0x0120(value)
+#define MC_DC19(value) 0x0130(value)
+#define MC_DC20(value) 0x0140(value)
+#define MC_DC21(value) 0x0150(value)
+#define MC_DC22(value) 0x0160(value)
+#define MC_DC23(value) 0x0170(value)
+#define MC_DC24(value) 0x0180(value)
+#define MC_DC25(value) 0x0190(value)
+#define MC_DC26(value) 0x01A0(value)
+#define MC_DC27(value) 0x01B0(value)
+#define MC_DC28(value) 0x01C0(value)
+#define MC_DC29(value) 0x01D0(value)
+#define MC_DC30(value) 0x01E0(value)
+#define MC_DC31(value) 0x01F0(value)
+#define MC_DC32(value) 0x0200(value)
+#define MC_DC33(value) 0x0210(value)
+#define MC_DC34(value) 0x0220(value)
+#define MC_DC35(value) 0x0230(value)
+#define MC_DC36(value) 0x0240(value)
+#define MC_DC37(value) 0x0250(value)
+#define MC_DC38(value) 0x0260(value)
+#define MC_DC39(value) 0x0270(value)
+#define MC_DC40(value) 0x0280(value)
+#define MC_DC41(value) 0x0290(value)
+#define MC_DC42(value) 0x02A0(value)
+#define MC_DC43(value) 0x02B0(value)
+#define MC_DC44(value) 0x02C0(value)
+#define MC_DC45(value) 0x02D0(value)
+#define MC_DC46(value) 0x02E0(value)
+
+#define RCU_OFFSET 0xBF203000
+#define RCU_RST_REQ (RCU_OFFSET + 0x0010)
+#define RCU_STS (RCU_OFFSET + 0x0014)
+
+#define CGU_OFFSET 0xBF103000
+#define PLL0_CFG (CGU_OFFSET + 0x0004)
+#define PLL1_CFG (CGU_OFFSET + 0x0008)
+#define PLL2_CFG (CGU_OFFSET + 0x000C)
+#define CGU_SYS (CGU_OFFSET + 0x0010)
+#define CGU_UPDATE (CGU_OFFSET + 0x0014)
+#define IF_CLK (CGU_OFFSET + 0x0018)
+#define CGU_SMD (CGU_OFFSET + 0x0020)
+#define CGU_CT1SR (CGU_OFFSET + 0x0028)
+#define CGU_CT2SR (CGU_OFFSET + 0x002C)
+#define CGU_PCMCR (CGU_OFFSET + 0x0030)
+#define PCI_CR_PCI (CGU_OFFSET + 0x0034)
+#define CGU_OSC_CTRL (CGU_OFFSET + 0x001C)
+#define CGU_MIPS_PWR_DWN (CGU_OFFSET + 0x0038)
+#define CLK_MEASURE (CGU_OFFSET + 0x003C)
+
+//05252006
+#define pll0_35MHz_CONFIG 0x9D861059
+#define pll1_35MHz_CONFIG 0x1A260CD9
+#define pll2_35MHz_CONFIG 0x8000f1e5
+#define pll0_36MHz_CONFIG 0x1000125D
+#define pll1_36MHz_CONFIG 0x1B1E0C99
+#define pll2_36MHz_CONFIG 0x8002f2a1
+//05252006
+
+//06063001-joelin disable the PCI CFRAME mask -start
+/*CFRAME is an I/O signal, in the chip, the output CFRAME is selected via GPIO altsel pins, so if you select MII1 RXD1, the CFRAME will not come out.
+But the CFRAME input still take the signal from the pad and not disabled when altsel choose other function. So when MII1_RXD1 is low from other device, the EBU interface will be disabled.
+
+The chip function in such a way that disable the CFRAME mask mean EBU not longer check CFRAME to be the device using the bus.
+The side effect is the entire PCI block will see CFRAME low all the time meaning PCI cannot use the bus at all so no more PCI function.
+*/
+#define PCI_CR_PR_OFFSET 0xBE105400
+#define PCI_CR_PCI_MOD_REG (PCI_CR_PR_OFFSET + 0x0030)
+#define PCI_CONFIG_SPACE 0xB7000000
+#define CS_CFM (PCI_CONFIG_SPACE + 0x6C)
+//06063001-joelin disable the PCI CFRAME mask -end
+ .set noreorder
+
+
+/*
+ * void ebu_init(void)
+ */
+ .globl ebu_init
+ .ent ebu_init
+ebu_init:
+
+#if defined(CONFIG_EBU_ADDSEL0) || defined(CONFIG_EBU_ADDSEL1) || \
+ defined(CONFIG_EBU_ADDSEL2) || defined(CONFIG_EBU_ADDSEL3) || \
+ defined(CONFIG_EBU_BUSCON0) || defined(CONFIG_EBU_BUSCON1) || \
+ defined(CONFIG_EBU_BUSCON2) || defined(CONFIG_EBU_BUSCON3)
+
+ li t1, EBU_MODUL_BASE
+#if defined(CONFIG_EBU_ADDSEL0)
+ li t2, CONFIG_EBU_ADDSEL0
+ sw t2, EBU_ADDSEL0(t1)
+#endif
+#if defined(CONFIG_EBU_ADDSEL1)
+ li t2, CONFIG_EBU_ADDSEL1
+ sw t2, EBU_ADDSEL1(t1)
+#endif
+#if defined(CONFIG_EBU_ADDSEL2)
+ li t2, CONFIG_EBU_ADDSEL2
+ sw t2, EBU_ADDSEL2(t1)
+#endif
+#if defined(CONFIG_EBU_ADDSEL3)
+ li t2, CONFIG_EBU_ADDSEL3
+ sw t2, EBU_ADDSEL3(t1)
+#endif
+
+#if defined(CONFIG_EBU_BUSCON0)
+ li t2, CONFIG_EBU_BUSCON0
+ sw t2, EBU_BUSCON0(t1)
+#endif
+#if defined(CONFIG_EBU_BUSCON1)
+ li t2, CONFIG_EBU_BUSCON1
+ sw t2, EBU_BUSCON1(t1)
+#endif
+#if defined(CONFIG_EBU_BUSCON2)
+ li t2, CONFIG_EBU_BUSCON2
+ sw t2, EBU_BUSCON2(t1)
+#endif
+#if defined(CONFIG_EBU_BUSCON3)
+ li t2, CONFIG_EBU_BUSCON3
+ sw t2, EBU_BUSCON3(t1)
+#endif
+
+#endif
+
+ j ra
+ nop
+
+ .end ebu_init
+
+
+/*
+ * void cgu_init(long)
+ *
+ * a0 has the clock value
+ */
+ .globl cgu_init
+ .ent cgu_init
+cgu_init:
+ li t2, CGU_SYS
+ lw t2,0(t2)
+ beq t2,a0,freq_up2date
+ nop
+
+ li t2, RCU_STS
+ lw t2, 0(t2)
+ and t2,0x00020000
+ beq t2,0x00020000,boot_36MHZ
+ nop
+//05252006
+ li t1, PLL0_CFG
+ li t2, pll0_35MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL1_CFG
+ li t2, pll1_35MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL2_CFG
+ li t2, pll2_35MHz_CONFIG
+ sw t2,0(t1)
+ li t1, CGU_SYS
+ sw a0,0(t1)
+ li t1, RCU_RST_REQ
+ li t2, 0x40000008
+ sw t2,0(t1)
+ b wait_reset
+ nop
+boot_36MHZ:
+ li t1, PLL0_CFG
+ li t2, pll0_36MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL1_CFG
+ li t2, pll1_36MHz_CONFIG
+ sw t2,0(t1)
+ li t1, PLL2_CFG
+ li t2, pll2_36MHz_CONFIG
+ sw t2,0(t1)
+ li t1, CGU_SYS
+ sw a0,0(t1)
+ li t1, RCU_RST_REQ
+ li t2, 0x40000008
+ sw t2,0(t1)
+//05252006
+
+wait_reset:
+ b wait_reset
+ nop
+freq_up2date:
+ j ra
+ nop
+
+ .end cgu_init
+
+#ifndef CONFIG_USE_DDR_RAM
+/*
+ * void sdram_init(long)
+ *
+ * a0 has the clock value
+ */
+ .globl sdram_init
+ .ent sdram_init
+sdram_init:
+
+ /* SDRAM Initialization
+ */
+ li t1, MC_MODUL_BASE
+
+ /* Clear Error log registers */
+ sw zero, MC_ERRCAUSE(t1)
+ sw zero, MC_ERRADDR(t1)
+
+ /* Enable SDRAM module in memory controller */
+ li t3, MC_SDRAM_ENABLE
+ lw t2, MC_CON(t1)
+ or t3, t2, t3
+ sw t3, MC_CON(t1)
+
+ li t1, MC_SDR_MODUL_BASE
+
+ /* disable the controller */
+ li t2, 0
+ sw t2, MC_CTRLENA(t1)
+
+ li t2, 0x822
+ sw t2, MC_IOGP(t1)
+
+ li t2, 0x2
+ sw t2, MC_CFGDW(t1)
+
+ /* Set CAS Latency */
+ li t2, 0x00000020
+ sw t2, MC_MRSCODE(t1)
+
+ /* Set CS0 to SDRAM parameters */
+ li t2, 0x000014d8
+ sw t2, MC_CFGPB0(t1)
+
+ /* Set SDRAM latency parameters */
+ li t2, 0x00036325; /* BC PC100 */
+ sw t2, MC_LATENCY(t1)
+
+ /* Set SDRAM refresh rate */
+ li t2, 0x00000C30
+ sw t2, MC_TREFRESH(t1)
+
+ /* Clear Power-down registers */
+ sw zero, MC_SELFRFSH(t1)
+
+ /* Finally enable the controller */
+ li t2, 1
+ sw t2, MC_CTRLENA(t1)
+
+ j ra
+ nop
+
+ .end sdram_init
+
+#endif /* !CONFIG_USE_DDR_RAM */
+
+#ifdef CONFIG_USE_DDR_RAM
+/*
+ * void ddrram_init(long)
+ *
+ * a0 has the clock value
+ */
+ .globl ddrram_init
+ .ent ddrram_init
+ddrram_init:
+
+ /* DDR-DRAM Initialization
+ */
+ li t1, MC_MODUL_BASE
+
+ /* Clear Error log registers */
+ sw zero, MC_ERRCAUSE(t1)
+ sw zero, MC_ERRADDR(t1)
+
+ /* Enable DDR module in memory controller */
+ li t3, MC_DDRRAM_ENABLE
+ lw t2, MC_CON(t1)
+ or t3, t2, t3
+ sw t3, MC_CON(t1)
+
+ li t1, MC_DDR_MODUL_BASE
+
+ /* Write configuration to DDR controller registers */
+ li t2, MC_DC0_VALUE
+ sw t2, MC_DC00(t1)
+
+ li t2, MC_DC1_VALUE
+ sw t2, MC_DC01(t1)
+
+ li t2, MC_DC2_VALUE
+ sw t2, MC_DC02(t1)
+
+ li t2, MC_DC3_VALUE
+ sw t2, MC_DC03(t1)
+
+ li t2, MC_DC4_VALUE
+ sw t2, MC_DC04(t1)
+
+ li t2, MC_DC5_VALUE
+ sw t2, MC_DC05(t1)
+
+ li t2, MC_DC6_VALUE
+ sw t2, MC_DC06(t1)
+
+ li t2, MC_DC7_VALUE
+ sw t2, MC_DC07(t1)
+
+ li t2, MC_DC8_VALUE
+ sw t2, MC_DC08(t1)
+
+ li t2, MC_DC9_VALUE
+ sw t2, MC_DC09(t1)
+
+ li t2, MC_DC10_VALUE
+ sw t2, MC_DC10(t1)
+
+ li t2, MC_DC11_VALUE
+ sw t2, MC_DC11(t1)
+
+ li t2, MC_DC12_VALUE
+ sw t2, MC_DC12(t1)
+
+ li t2, MC_DC13_VALUE
+ sw t2, MC_DC13(t1)
+
+ li t2, MC_DC14_VALUE
+ sw t2, MC_DC14(t1)
+
+ li t2, MC_DC15_VALUE
+ sw t2, MC_DC15(t1)
+
+ li t2, MC_DC16_VALUE
+ sw t2, MC_DC16(t1)
+
+ li t2, MC_DC17_VALUE
+ sw t2, MC_DC17(t1)
+
+ li t2, MC_DC18_VALUE
+ sw t2, MC_DC18(t1)
+
+ li t2, MC_DC19_VALUE
+ sw t2, MC_DC19(t1)
+
+ li t2, MC_DC20_VALUE
+ sw t2, MC_DC20(t1)
+
+ li t2, MC_DC21_VALUE
+ sw t2, MC_DC21(t1)
+
+ li t2, MC_DC22_VALUE
+ sw t2, MC_DC22(t1)
+
+ li t2, MC_DC23_VALUE
+ sw t2, MC_DC23(t1)
+
+ li t2, MC_DC24_VALUE
+ sw t2, MC_DC24(t1)
+
+ li t2, MC_DC25_VALUE
+ sw t2, MC_DC25(t1)
+
+ li t2, MC_DC26_VALUE
+ sw t2, MC_DC26(t1)
+
+ li t2, MC_DC27_VALUE
+ sw t2, MC_DC27(t1)
+
+ li t2, MC_DC28_VALUE
+ sw t2, MC_DC28(t1)
+
+ li t2, MC_DC29_VALUE
+ sw t2, MC_DC29(t1)
+
+ li t2, MC_DC30_VALUE
+ sw t2, MC_DC30(t1)
+
+ li t2, MC_DC31_VALUE
+ sw t2, MC_DC31(t1)
+
+ li t2, MC_DC32_VALUE
+ sw t2, MC_DC32(t1)
+
+ li t2, MC_DC33_VALUE
+ sw t2, MC_DC33(t1)
+
+ li t2, MC_DC34_VALUE
+ sw t2, MC_DC34(t1)
+
+ li t2, MC_DC35_VALUE
+ sw t2, MC_DC35(t1)
+
+ li t2, MC_DC36_VALUE
+ sw t2, MC_DC36(t1)
+
+ li t2, MC_DC37_VALUE
+ sw t2, MC_DC37(t1)
+
+ li t2, MC_DC38_VALUE
+ sw t2, MC_DC38(t1)
+
+ li t2, MC_DC39_VALUE
+ sw t2, MC_DC39(t1)
+
+ li t2, MC_DC40_VALUE
+ sw t2, MC_DC40(t1)
+
+ li t2, MC_DC41_VALUE
+ sw t2, MC_DC41(t1)
+
+ li t2, MC_DC42_VALUE
+ sw t2, MC_DC42(t1)
+
+ li t2, MC_DC43_VALUE
+ sw t2, MC_DC43(t1)
+
+ li t2, MC_DC44_VALUE
+ sw t2, MC_DC44(t1)
+
+ li t2, MC_DC45_VALUE
+ sw t2, MC_DC45(t1)
+
+ li t2, MC_DC46_VALUE
+ sw t2, MC_DC46(t1)
+
+ li t2, 0x00000100
+ sw t2, MC_DC03(t1)
+
+ j ra
+ nop
+
+ .end ddrram_init
+#endif /* CONFIG_USE_DDR_RAM */
+
+ .globl lowlevel_init
+ .ent lowlevel_init
+lowlevel_init:
+ /* EBU, CGU and SDRAM/DDR-RAM Initialization.
+ */
+ move t0, ra
+ /* We rely on the fact that non of the following ..._init() functions
+ * modify t0
+ */
+#if defined(DDR166)
+ /* 0xe8 means CPU0/CPU1 333M, DDR 167M, FPI 83M, PPE 240M */
+ li a0,0xe8
+#elif defined(DDR133)
+ /* 0xe9 means CPU0/CPU1 333M, DDR 133M, FPI 83M, PPE 240M */
+ li a0,0xe9
+#else /* defined(DDR111) */
+ /* 0xea means CPU0/CPU1 333M, DDR 111M, FPI 83M, PPE 240M */
+ li a0,0xea
+#endif
+ bal cgu_init
+ nop
+
+ bal ebu_init
+ nop
+
+//06063001-joelin disable the PCI CFRAME mask-start
+#ifdef DISABLE_CFRAME
+ li t1, PCI_CR_PCI //mw bf103034 80000000
+ li t2, 0x80000000
+ sw t2,0(t1)
+
+ li t1, PCI_CR_PCI_MOD_REG //mw be105430 103
+ li t2, 0x103
+ sw t2,0(t1)
+
+ li t1, CS_CFM //mw b700006c 0
+ li t2, 0x00
+ sw t2, 0(t1)
+
+ li t1, PCI_CR_PCI_MOD_REG //mw be105430 103
+ li t2, 0x1000103
+ sw t2, 0(t1)
+#endif
+//06063001-joelin disable the PCI CFRAME mask-end
+
+#ifdef CONFIG_USE_DDR_RAM
+ bal ddrram_init
+ nop
+#else
+ bal sdram_init
+ nop
+#endif
+ move ra, t0
+ j ra
+ nop
+
+ .end lowlevel_init
diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/lowlevel_init.S b/package/uboot-lantiq/files/board/infineon/easy50812/lowlevel_init.S
new file mode 100644
index 000000000..58f7a16ea
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50812/lowlevel_init.S
@@ -0,0 +1,543 @@
+/*
+ * Memory sub-system initialization code for AR9 board.
+ *
+ * Copyright (c) 2003 Wolfgang Denk <wd@denx.de>
+ * Copyright (c) 2005 Andre Messerschmidt Infineon
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+/* History:
+ peng liu May 25, 2006, for PLL setting after reset, 05252006
+ */
+#include <config.h>
+#include <version.h>
+#include <asm/regdef.h>
+
+#if defined(CONFIG_USE_DDR_RAM)
+
+#if defined(CONFIG_CPU_111M_RAM_111M) || defined(CONFIG_CPU_333M_RAM_111M)
+# include "ar9_ddr111_settings.h"
+#elif defined(CONFIG_CPU_166M_RAM_166M) || defined(CONFIG_CPU_333M_RAM_166M) || defined(CONFIG_CPU_500M_RAM_166M)
+# include "ar9_ddr166_settings.h"
+#elif defined(CONFIG_CPU_442M_RAM_147M)
+# include "ar9_ddr166_settings.h"
+#elif defined(CONFIG_CPU_393M_RAM_196M)
+# ifdef CONFIG_ETRON_RAM
+# include "etron_ddr196_settings.h"
+# else
+# include "ar9_ddr196_settings.h"
+# endif
+#elif defined(CONFIG_CPU_442M_RAM_221M)
+# include "ar9_ddr221_settings.h"
+#elif defined(CONFIG_CPU_500M_RAM_250M)
+# include "ar9_ddr250_settings.h"
+#else
+# warning "missing definition for ddr_settings.h, use default!"
+# include "ar9_ddr_settings.h"
+#endif
+#endif /* CONFIG_USE_DDR_RAM */
+
+#if defined(CONFIG_USE_DDR_RAM) && !defined(MC_DC0_VALUE)
+#error "missing include of ddr_settings.h"
+#endif
+
+#define EBU_MODUL_BASE 0xBE105300
+#define EBU_CLC(value) 0x0000(value)
+#define EBU_CON(value) 0x0010(value)
+#define EBU_ADDSEL0(value) 0x0020(value)
+#define EBU_ADDSEL1(value) 0x0024(value)
+#define EBU_ADDSEL2(value) 0x0028(value)
+#define EBU_ADDSEL3(value) 0x002C(value)
+#define EBU_BUSCON0(value) 0x0060(value)
+#define EBU_BUSCON1(value) 0x0064(value)
+#define EBU_BUSCON2(value) 0x0068(value)
+#define EBU_BUSCON3(value) 0x006C(value)
+
+#define MC_MODUL_BASE 0xBF800000
+#define MC_ERRCAUSE(value) 0x0010(value)
+#define MC_ERRADDR(value) 0x0020(value)
+#define MC_CON(value) 0x0060(value)
+
+#define MC_SRAM_ENABLE 0x00000004
+#define MC_SDRAM_ENABLE 0x00000002
+#define MC_DDRRAM_ENABLE 0x00000001
+
+#define MC_SDR_MODUL_BASE 0xBF800200
+#define MC_IOGP(value) 0x0000(value)
+#define MC_CTRLENA(value) 0x0010(value)
+#define MC_MRSCODE(value) 0x0020(value)
+#define MC_CFGDW(value) 0x0030(value)
+#define MC_CFGPB0(value) 0x0040(value)
+#define MC_LATENCY(value) 0x0080(value)
+#define MC_TREFRESH(value) 0x0090(value)
+#define MC_SELFRFSH(value) 0x00A0(value)
+
+#define MC_DDR_MODUL_BASE 0xBF801000
+#define MC_DC00(value) 0x0000(value)
+#define MC_DC01(value) 0x0010(value)
+#define MC_DC02(value) 0x0020(value)
+#define MC_DC03(value) 0x0030(value)
+#define MC_DC04(value) 0x0040(value)
+#define MC_DC05(value) 0x0050(value)
+#define MC_DC06(value) 0x0060(value)
+#define MC_DC07(value) 0x0070(value)
+#define MC_DC08(value) 0x0080(value)
+#define MC_DC09(value) 0x0090(value)
+#define MC_DC10(value) 0x00A0(value)
+#define MC_DC11(value) 0x00B0(value)
+#define MC_DC12(value) 0x00C0(value)
+#define MC_DC13(value) 0x00D0(value)
+#define MC_DC14(value) 0x00E0(value)
+#define MC_DC15(value) 0x00F0(value)
+#define MC_DC16(value) 0x0100(value)
+#define MC_DC17(value) 0x0110(value)
+#define MC_DC18(value) 0x0120(value)
+#define MC_DC19(value) 0x0130(value)
+#define MC_DC20(value) 0x0140(value)
+#define MC_DC21(value) 0x0150(value)
+#define MC_DC22(value) 0x0160(value)
+#define MC_DC23(value) 0x0170(value)
+#define MC_DC24(value) 0x0180(value)
+#define MC_DC25(value) 0x0190(value)
+#define MC_DC26(value) 0x01A0(value)
+#define MC_DC27(value) 0x01B0(value)
+#define MC_DC28(value) 0x01C0(value)
+#define MC_DC29(value) 0x01D0(value)
+#define MC_DC30(value) 0x01E0(value)
+#define MC_DC31(value) 0x01F0(value)
+#define MC_DC32(value) 0x0200(value)
+#define MC_DC33(value) 0x0210(value)
+#define MC_DC34(value) 0x0220(value)
+#define MC_DC35(value) 0x0230(value)
+#define MC_DC36(value) 0x0240(value)
+#define MC_DC37(value) 0x0250(value)
+#define MC_DC38(value) 0x0260(value)
+#define MC_DC39(value) 0x0270(value)
+#define MC_DC40(value) 0x0280(value)
+#define MC_DC41(value) 0x0290(value)
+#define MC_DC42(value) 0x02A0(value)
+#define MC_DC43(value) 0x02B0(value)
+#define MC_DC44(value) 0x02C0(value)
+#define MC_DC45(value) 0x02D0(value)
+#define MC_DC46(value) 0x02E0(value)
+
+#define RCU_OFFSET 0xBF203000
+#define RCU_RST_REQ (RCU_OFFSET + 0x0010)
+#define RCU_STS (RCU_OFFSET + 0x0014)
+
+#define CGU_OFFSET 0xBF103000
+#define PLL0_CFG (CGU_OFFSET + 0x0004)
+#define PLL1_CFG (CGU_OFFSET + 0x0008)
+#define PLL2_CFG (CGU_OFFSET + 0x000C)
+#define CGU_SYS (CGU_OFFSET + 0x0010)
+#define CGU_UPDATE (CGU_OFFSET + 0x0014)
+#define IF_CLK (CGU_OFFSET + 0x0018)
+#define CGU_SMD (CGU_OFFSET + 0x0020)
+#define CGU_CT1SR (CGU_OFFSET + 0x0028)
+#define CGU_CT2SR (CGU_OFFSET + 0x002C)
+#define CGU_PCMCR (CGU_OFFSET + 0x0030)
+#define PCI_CR_PCI (CGU_OFFSET + 0x0034)
+#define CGU_OSC_CTRL (CGU_OFFSET + 0x001C)
+#define CGU_MIPS_PWR_DWN (CGU_OFFSET + 0x0038)
+#define CLK_MEASURE (CGU_OFFSET + 0x003C)
+
+#define pll1_36MHz_CONFIG 0x9800f25f
+
+ .set noreorder
+
+
+/*
+ * void ebu_init(void)
+ */
+ .globl ebu_init
+ .ent ebu_init
+ebu_init:
+
+#if defined(CONFIG_EBU_ADDSEL0) || defined(CONFIG_EBU_ADDSEL1) || \
+ defined(CONFIG_EBU_ADDSEL2) || defined(CONFIG_EBU_ADDSEL3) || \
+ defined(CONFIG_EBU_BUSCON0) || defined(CONFIG_EBU_BUSCON1) || \
+ defined(CONFIG_EBU_BUSCON2) || defined(CONFIG_EBU_BUSCON3)
+
+ li t1, EBU_MODUL_BASE
+#if defined(CONFIG_EBU_ADDSEL0)
+ li t2, CONFIG_EBU_ADDSEL0
+ sw t2, EBU_ADDSEL0(t1)
+#endif
+#if defined(CONFIG_EBU_ADDSEL1)
+ li t2, CONFIG_EBU_ADDSEL1
+ sw t2, EBU_ADDSEL1(t1)
+#endif
+#if defined(CONFIG_EBU_ADDSEL2)
+ li t2, CONFIG_EBU_ADDSEL2
+ sw t2, EBU_ADDSEL2(t1)
+#endif
+#if defined(CONFIG_EBU_ADDSEL3)
+ li t2, CONFIG_EBU_ADDSEL3
+ sw t2, EBU_ADDSEL3(t1)
+#endif
+
+#if defined(CONFIG_EBU_BUSCON0)
+ li t2, CONFIG_EBU_BUSCON0
+ sw t2, EBU_BUSCON0(t1)
+#endif
+#if defined(CONFIG_EBU_BUSCON1)
+ li t2, CONFIG_EBU_BUSCON1
+ sw t2, EBU_BUSCON1(t1)
+#endif
+#if defined(CONFIG_EBU_BUSCON2)
+ li t2, CONFIG_EBU_BUSCON2
+ sw t2, EBU_BUSCON2(t1)
+#endif
+#if defined(CONFIG_EBU_BUSCON3)
+ li t2, CONFIG_EBU_BUSCON3
+ sw t2, EBU_BUSCON3(t1)
+#endif
+
+#endif
+
+ j ra
+ nop
+
+ .end ebu_init
+
+
+/*
+ * void cgu_init(long)
+ *
+ * a0 has the clock value
+ */
+ .globl cgu_init
+ .ent cgu_init
+cgu_init:
+ li t2, CGU_SYS
+ lw t2,0(t2)
+ beq t2,a0,freq_up2date
+ nop
+ li t1, CGU_SYS
+ sw a0,0(t1)
+
+#if defined(CONFIG_CPU_333M_RAM_166M) && defined(CONFIG_USE_PLL1)
+ li t1, PLL1_CFG
+ li a1, pll1_36MHz_CONFIG
+ sw a1, 0(t1)
+#endif
+
+#if defined(CONFIG_CLASS_II_DDR_PAD)
+ li t1, CGU_SMD
+ li a1, 0x200000
+ sw a1, 0(t1) // Turn on DDR PAD Class II to INC drive.
+#endif
+
+ li t1, RCU_RST_REQ
+ li t2, 0x40000008
+ sw t2,0(t1)
+ b wait_reset
+ nop
+
+wait_reset:
+ b wait_reset
+ nop
+
+freq_up2date:
+ j ra
+ nop
+ .end cgu_init
+
+
+#ifndef CONFIG_USE_DDR_RAM
+/*
+ * void sdram_init(long)
+ *
+ * a0 has the clock value
+ */
+ .globl sdram_init
+ .ent sdram_init
+sdram_init:
+
+ /* SDRAM Initialization
+ */
+ li t1, MC_MODUL_BASE
+
+ /* Clear Error log registers */
+ sw zero, MC_ERRCAUSE(t1)
+ sw zero, MC_ERRADDR(t1)
+
+ /* Enable SDRAM module in memory controller */
+ li t3, MC_SDRAM_ENABLE
+ lw t2, MC_CON(t1)
+ or t3, t2, t3
+ sw t3, MC_CON(t1)
+
+ li t1, MC_SDR_MODUL_BASE
+
+ /* disable the controller */
+ li t2, 0
+ sw t2, MC_CTRLENA(t1)
+
+ li t2, 0x822
+ sw t2, MC_IOGP(t1)
+
+ li t2, 0x2
+ sw t2, MC_CFGDW(t1)
+
+ /* Set CAS Latency */
+ li t2, 0x00000020
+ sw t2, MC_MRSCODE(t1)
+
+ /* Set CS0 to SDRAM parameters */
+ li t2, 0x000014d8
+ sw t2, MC_CFGPB0(t1)
+
+ /* Set SDRAM latency parameters */
+ li t2, 0x00036325; /* BC PC100 */
+ sw t2, MC_LATENCY(t1)
+
+ /* Set SDRAM refresh rate */
+ li t2, 0x00000C30
+ sw t2, MC_TREFRESH(t1)
+
+ /* Clear Power-down registers */
+ sw zero, MC_SELFRFSH(t1)
+
+ /* Finally enable the controller */
+ li t2, 1
+ sw t2, MC_CTRLENA(t1)
+
+ j ra
+ nop
+
+ .end sdram_init
+
+#endif /* !CONFIG_USE_DDR_RAM */
+
+#ifdef CONFIG_USE_DDR_RAM
+/*
+ * void ddrram_init(long)
+ *
+ * a0 has the clock value
+ */
+ .globl ddrram_init
+ .ent ddrram_init
+ddrram_init:
+
+ /* DDR-DRAM Initialization
+ */
+ li t1, MC_MODUL_BASE
+
+ /* Clear Error log registers */
+ sw zero, MC_ERRCAUSE(t1)
+ sw zero, MC_ERRADDR(t1)
+
+ /* Enable DDR module in memory controller */
+ li t3, MC_DDRRAM_ENABLE
+ lw t2, MC_CON(t1)
+ or t3, t2, t3
+ sw t3, MC_CON(t1)
+
+ li t1, MC_DDR_MODUL_BASE
+
+ /* Write configuration to DDR controller registers */
+ li t2, MC_DC0_VALUE
+ sw t2, MC_DC00(t1)
+
+ li t2, MC_DC1_VALUE
+ sw t2, MC_DC01(t1)
+
+ li t2, MC_DC2_VALUE
+ sw t2, MC_DC02(t1)
+
+ li t2, MC_DC3_VALUE
+ sw t2, MC_DC03(t1)
+
+ li t2, MC_DC4_VALUE
+ sw t2, MC_DC04(t1)
+
+ li t2, MC_DC5_VALUE
+ sw t2, MC_DC05(t1)
+
+ li t2, MC_DC6_VALUE
+ sw t2, MC_DC06(t1)
+
+ li t2, MC_DC7_VALUE
+ sw t2, MC_DC07(t1)
+
+ li t2, MC_DC8_VALUE
+ sw t2, MC_DC08(t1)
+
+ li t2, MC_DC9_VALUE
+ sw t2, MC_DC09(t1)
+
+ li t2, MC_DC10_VALUE
+ sw t2, MC_DC10(t1)
+
+ li t2, MC_DC11_VALUE
+ sw t2, MC_DC11(t1)
+
+ li t2, MC_DC12_VALUE
+ sw t2, MC_DC12(t1)
+
+ li t2, MC_DC13_VALUE
+ sw t2, MC_DC13(t1)
+
+ li t2, MC_DC14_VALUE
+ sw t2, MC_DC14(t1)
+
+ li t2, MC_DC15_VALUE
+ sw t2, MC_DC15(t1)
+
+ li t2, MC_DC16_VALUE
+ sw t2, MC_DC16(t1)
+
+ li t2, MC_DC17_VALUE
+ sw t2, MC_DC17(t1)
+
+ li t2, MC_DC18_VALUE
+ sw t2, MC_DC18(t1)
+
+ li t2, MC_DC19_VALUE
+ sw t2, MC_DC19(t1)
+
+ li t2, MC_DC20_VALUE
+ sw t2, MC_DC20(t1)
+
+ li t2, MC_DC21_VALUE
+ sw t2, MC_DC21(t1)
+
+ li t2, MC_DC22_VALUE
+ sw t2, MC_DC22(t1)
+
+ li t2, MC_DC23_VALUE
+ sw t2, MC_DC23(t1)
+
+ li t2, MC_DC24_VALUE
+ sw t2, MC_DC24(t1)
+
+ li t2, MC_DC25_VALUE
+ sw t2, MC_DC25(t1)
+
+ li t2, MC_DC26_VALUE
+ sw t2, MC_DC26(t1)
+
+ li t2, MC_DC27_VALUE
+ sw t2, MC_DC27(t1)
+
+ li t2, MC_DC28_VALUE
+ sw t2, MC_DC28(t1)
+
+ li t2, MC_DC29_VALUE
+ sw t2, MC_DC29(t1)
+
+ li t2, MC_DC30_VALUE
+ sw t2, MC_DC30(t1)
+
+ li t2, MC_DC31_VALUE
+ sw t2, MC_DC31(t1)
+
+ li t2, MC_DC32_VALUE
+ sw t2, MC_DC32(t1)
+
+ li t2, MC_DC33_VALUE
+ sw t2, MC_DC33(t1)
+
+ li t2, MC_DC34_VALUE
+ sw t2, MC_DC34(t1)
+
+ li t2, MC_DC35_VALUE
+ sw t2, MC_DC35(t1)
+
+ li t2, MC_DC36_VALUE
+ sw t2, MC_DC36(t1)
+
+ li t2, MC_DC37_VALUE
+ sw t2, MC_DC37(t1)
+
+ li t2, MC_DC38_VALUE
+ sw t2, MC_DC38(t1)
+
+ li t2, MC_DC39_VALUE
+ sw t2, MC_DC39(t1)
+
+ li t2, MC_DC40_VALUE
+ sw t2, MC_DC40(t1)
+
+ li t2, MC_DC41_VALUE
+ sw t2, MC_DC41(t1)
+
+ li t2, MC_DC42_VALUE
+ sw t2, MC_DC42(t1)
+
+ li t2, MC_DC43_VALUE
+ sw t2, MC_DC43(t1)
+
+ li t2, MC_DC44_VALUE
+ sw t2, MC_DC44(t1)
+
+ li t2, MC_DC45_VALUE
+ sw t2, MC_DC45(t1)
+
+ li t2, MC_DC46_VALUE
+ sw t2, MC_DC46(t1)
+
+ li t2, 0x00000100
+ sw t2, MC_DC03(t1)
+
+ j ra
+ nop
+
+ .end ddrram_init
+#endif /* CONFIG_USE_DDR_RAM */
+
+ .globl lowlevel_init
+ .ent lowlevel_init
+lowlevel_init:
+ /* EBU, CGU and SDRAM/DDR-RAM Initialization.
+ */
+ move t0, ra
+ /* We rely on the fact that non of the following ..._init() functions
+ * modify t0
+ */
+#if defined(CONFIG_SYS_EBU_BOOT)
+/*
+ using PPL1 value
+*/
+ li a0,0x90
+ bal cgu_init
+ nop
+#endif /* CONFIG_SYS_EBU_BOOT */
+
+ bal ebu_init
+ nop
+
+#ifdef CONFIG_SYS_EBU_BOOT
+#ifndef CONFIG_SYS_RAMBOOT
+#ifdef CONFIG_USE_DDR_RAM
+ bal ddrram_init
+ nop
+#else
+ bal sdram_init
+ nop
+#endif
+#endif /* CONFIG_SYS_RAMBOOT */
+#endif /* CONFIG_SYS_EBU_BOOT */
+
+ move ra, t0
+ j ra
+ nop
+
+ .end lowlevel_init
diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/pmuenable.S b/package/uboot-lantiq/files/board/infineon/easy50812/pmuenable.S
new file mode 100644
index 000000000..e0d7971d8
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50812/pmuenable.S
@@ -0,0 +1,48 @@
+/*
+ * Power Management unit initialization code for AMAZON development board.
+ *
+ * Copyright (c) 2003 Ou Ke, Infineon.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <config.h>
+#include <version.h>
+#include <asm/regdef.h>
+
+#define PMU_PWDCR 0xBF10201C
+#define PMU_SR 0xBF102020
+
+ .globl pmuenable
+
+pmuenable:
+ li t0, PMU_PWDCR
+ li t1, 0x2 /* enable everything */
+ sw t1, 0(t0)
+#if 0
+1:
+ li t0, PMU_SR
+ lw t2, 0(t0)
+ bne t1, t2, 1b
+ nop
+#endif
+ j ra
+ nop
+
+
diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/u-boot-bootstrap.lds b/package/uboot-lantiq/files/board/infineon/easy50812/u-boot-bootstrap.lds
new file mode 100644
index 000000000..52d7dafad
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50812/u-boot-bootstrap.lds
@@ -0,0 +1,74 @@
+/*
+ * (C) Copyright 2010 Industrie Dial Face S.p.A.
+ * Luigi 'Comio' Mantellini, luigi.mantellini@idf-hit.com
+ *
+ * (C) Copyright 2003
+ * Wolfgang Denk Engineering, <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+/*
+OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-bigmips")
+*/
+OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradlittlemips")
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = .;
+ _gp = ALIGN(16) +0x7ff0;
+
+ .got : {
+ __got_start = .;
+ *(.got)
+ __got_end = .;
+ }
+
+ . = ALIGN(4);
+ .sdata : { *(.sdata) }
+
+ . = .;
+ . = ALIGN(4);
+ .payload : { *(.payload) }
+ . = ALIGN(4);
+
+ uboot_end_data = .;
+ num_got_entries = (__got_end - __got_start) >> 2;
+
+ . = ALIGN(4);
+ .sbss : { *(.sbss) }
+ .bss : { *(.bss) . = ALIGN(4); }
+ uboot_end = .;
+}
+
diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/u-boot.lds b/package/uboot-lantiq/files/board/infineon/easy50812/u-boot.lds
new file mode 100644
index 000000000..9a6cd1b8a
--- /dev/null
+++ b/package/uboot-lantiq/files/board/infineon/easy50812/u-boot.lds
@@ -0,0 +1,70 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk Engineering, <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+/*
+OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-bigmips")
+*/
+OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradbigmips")
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = .;
+ _gp = ALIGN(16) + 0x7ff0;
+
+ .got : {
+ __got_start = .;
+ *(.got)
+ __got_end = .;
+ }
+
+ .sdata : { *(.sdata) }
+
+ .u_boot_cmd : {
+ __u_boot_cmd_start = .;
+ *(.u_boot_cmd)
+ __u_boot_cmd_end = .;
+ }
+
+ uboot_end_data = .;
+ num_got_entries = (__got_end - __got_start) >> 2;
+
+ . = ALIGN(4);
+ .sbss (NOLOAD) : { *(.sbss) }
+ .bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
+ uboot_end = .;
+}
diff --git a/package/uboot-lantiq/files/cpu/mips/ar9-clock.c b/package/uboot-lantiq/files/cpu/mips/ar9-clock.c
new file mode 100644
index 000000000..a8aecb422
--- /dev/null
+++ b/package/uboot-lantiq/files/cpu/mips/ar9-clock.c
@@ -0,0 +1,67 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <asm/ar9.h>
+
+ulong ifx_get_ddr_hz(void)
+{
+ switch((*AR9_CGU_SYS) & 0x05) {
+ case 0x01:
+ case 0x05:
+ return CLOCK_111M;
+
+ case 0x00:
+ case 0x04:
+ return CLOCK_166M;
+ }
+
+ return 0;
+}
+
+ulong ifx_get_cpuclk(void)
+{
+ switch((*AR9_CGU_SYS) & 0x05) {
+ case 0x00:
+ case 0x01:
+ return CLOCK_333M;
+
+ case 0x04:
+ return CLOCK_166M;
+
+ case 0x05:
+ return CLOCK_111M;
+ }
+
+ return 0;
+}
+
+ulong get_bus_freq(ulong dummy)
+{
+ unsigned int ddr_clock=ifx_get_ddr_hz();
+ if((*AR9_CGU_SYS) & 0x40){
+ return ddr_clock/2;
+ } else {
+ return ddr_clock;
+ }
+}
diff --git a/package/uboot-lantiq/files/cpu/mips/ar9/Makefile b/package/uboot-lantiq/files/cpu/mips/ar9/Makefile
new file mode 100644
index 000000000..c48d02eaa
--- /dev/null
+++ b/package/uboot-lantiq/files/cpu/mips/ar9/Makefile
@@ -0,0 +1,46 @@
+#########################################################################
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(SOC).a
+
+COBJS = clock.o
+
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
+
+all: $(obj).depend $(LIB)
+
+$(LIB): $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/package/uboot-lantiq/files/cpu/mips/ar9/clock.c b/package/uboot-lantiq/files/cpu/mips/ar9/clock.c
new file mode 100644
index 000000000..a8aecb422
--- /dev/null
+++ b/package/uboot-lantiq/files/cpu/mips/ar9/clock.c
@@ -0,0 +1,67 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <asm/ar9.h>
+
+ulong ifx_get_ddr_hz(void)
+{
+ switch((*AR9_CGU_SYS) & 0x05) {
+ case 0x01:
+ case 0x05:
+ return CLOCK_111M;
+
+ case 0x00:
+ case 0x04:
+ return CLOCK_166M;
+ }
+
+ return 0;
+}
+
+ulong ifx_get_cpuclk(void)
+{
+ switch((*AR9_CGU_SYS) & 0x05) {
+ case 0x00:
+ case 0x01:
+ return CLOCK_333M;
+
+ case 0x04:
+ return CLOCK_166M;
+
+ case 0x05:
+ return CLOCK_111M;
+ }
+
+ return 0;
+}
+
+ulong get_bus_freq(ulong dummy)
+{
+ unsigned int ddr_clock=ifx_get_ddr_hz();
+ if((*AR9_CGU_SYS) & 0x40){
+ return ddr_clock/2;
+ } else {
+ return ddr_clock;
+ }
+}
diff --git a/package/uboot-lantiq/files/cpu/mips/ar9/ifx_cache.S b/package/uboot-lantiq/files/cpu/mips/ar9/ifx_cache.S
new file mode 100644
index 000000000..fc482dcd6
--- /dev/null
+++ b/package/uboot-lantiq/files/cpu/mips/ar9/ifx_cache.S
@@ -0,0 +1,60 @@
+
+#define IFX_CACHE_EXTRA_INVALID_TAG \
+ mtc0 zero, CP0_TAGLO, 1; \
+ mtc0 zero, CP0_TAGLO, 2; \
+ mtc0 zero, CP0_TAGLO, 3; \
+ mtc0 zero, CP0_TAGLO, 4;
+
+#define IFX_CACHE_EXTRA_OPERATION \
+ /* set WST bit */ \
+ mfc0 a0, CP0_ECC; \
+ li a1, ECCF_WST; \
+ or a0, a1; \
+ mtc0 a0, CP0_ECC; \
+ \
+ li a0, K0BASE; \
+ move a2, t2; /* icacheSize */ \
+ move a3, t4; /* icacheLineSize */ \
+ move a1, a2; \
+ icacheop(a0,a1,a2,a3,(Index_Store_Tag_I)); \
+ \
+ /* clear WST bit */ \
+ mfc0 a0, CP0_ECC; \
+ li a1, ~ECCF_WST; \
+ and a0, a1; \
+ mtc0 a0, CP0_ECC; \
+ \
+ /* 1: initialise dcache tags. */ \
+ \
+ /* cache line size */ \
+ li a2, CFG_CACHELINE_SIZE; \
+ /* kseg0 mem address */ \
+ li a1, 0; \
+ li a3, CFG_CACHE_SETS * CFG_CACHE_WAYS; \
+1: \
+ /* store tag (invalid, not locked) */ \
+ cache 0x8, 0(a1); \
+ cache 0x9, 0(a1); \
+ \
+ add a3, -1; \
+ bne a3, zero, 1b; \
+ add a1, a2; \
+ \
+ /* set WST bit */ \
+ mfc0 a0, CP0_ECC; \
+ li a1, ECCF_WST; \
+ or a0, a1; \
+ mtc0 a0, CP0_ECC; \
+ \
+ li a0, K0BASE; \
+ move a2, t3; /* dcacheSize */ \
+ move a3, t5; /* dcacheLineSize */ \
+ move a1, a2; \
+ icacheop(a0,a1,a2,a3,(Index_Store_Tag_D)); \
+ \
+ /* clear WST bit */ \
+ mfc0 a0, CP0_ECC; \
+ li a1, ~ECCF_WST; \
+ and a0, a1; \
+ mtc0 a0, CP0_ECC;
+
diff --git a/package/uboot-lantiq/files/cpu/mips/danube-clock.c b/package/uboot-lantiq/files/cpu/mips/danube-clock.c
new file mode 100644
index 000000000..4219f8f92
--- /dev/null
+++ b/package/uboot-lantiq/files/cpu/mips/danube-clock.c
@@ -0,0 +1,65 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <asm/danube.h>
+
+ulong ifx_get_ddr_hz(void)
+{
+ static const ulong ddr_freq[] = {166666667,133333333,111111111,83333333};
+ return ddr_freq[((*DANUBE_CGU_SYS) & 0x3)];
+}
+
+ulong ifx_get_cpuclk(void)
+{
+#ifdef CONFIG_USE_EMULATOR
+ return EMULATOR_CPU_SPEED;
+#else //NOT CONFIG_USE_EMULATOR
+ unsigned int ddr_clock=ifx_get_ddr_hz();
+ switch((*DANUBE_CGU_SYS) & 0xc){
+ case 0:
+ default:
+ return 323333333;
+ case 4:
+ return ddr_clock;
+ case 8:
+ return ddr_clock << 1;
+ }
+#endif
+}
+
+ulong get_bus_freq(ulong dummy)
+{
+#ifdef CONFIG_USE_EMULATOR
+ unsigned int clkCPU;
+ clkCPU = ifx_get_cpuclk();
+ return clkCPU >> 2;
+#else //NOT CONFIG_USE_EMULATOR
+ unsigned int ddr_clock=ifx_get_ddr_hz();
+ if ((*DANUBE_CGU_SYS) & 0x40){
+ return ddr_clock >> 1;
+ }
+ return ddr_clock;
+#endif
+}
+
diff --git a/package/uboot-lantiq/files/cpu/mips/danube/Makefile b/package/uboot-lantiq/files/cpu/mips/danube/Makefile
new file mode 100644
index 000000000..c48d02eaa
--- /dev/null
+++ b/package/uboot-lantiq/files/cpu/mips/danube/Makefile
@@ -0,0 +1,46 @@
+#########################################################################
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(SOC).a
+
+COBJS = clock.o
+
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
+
+all: $(obj).depend $(LIB)
+
+$(LIB): $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/package/uboot-lantiq/files/cpu/mips/danube/clock.c b/package/uboot-lantiq/files/cpu/mips/danube/clock.c
new file mode 100644
index 000000000..4219f8f92
--- /dev/null
+++ b/package/uboot-lantiq/files/cpu/mips/danube/clock.c
@@ -0,0 +1,65 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <asm/danube.h>
+
+ulong ifx_get_ddr_hz(void)
+{
+ static const ulong ddr_freq[] = {166666667,133333333,111111111,83333333};
+ return ddr_freq[((*DANUBE_CGU_SYS) & 0x3)];
+}
+
+ulong ifx_get_cpuclk(void)
+{
+#ifdef CONFIG_USE_EMULATOR
+ return EMULATOR_CPU_SPEED;
+#else //NOT CONFIG_USE_EMULATOR
+ unsigned int ddr_clock=ifx_get_ddr_hz();
+ switch((*DANUBE_CGU_SYS) & 0xc){
+ case 0:
+ default:
+ return 323333333;
+ case 4:
+ return ddr_clock;
+ case 8:
+ return ddr_clock << 1;
+ }
+#endif
+}
+
+ulong get_bus_freq(ulong dummy)
+{
+#ifdef CONFIG_USE_EMULATOR
+ unsigned int clkCPU;
+ clkCPU = ifx_get_cpuclk();
+ return clkCPU >> 2;
+#else //NOT CONFIG_USE_EMULATOR
+ unsigned int ddr_clock=ifx_get_ddr_hz();
+ if ((*DANUBE_CGU_SYS) & 0x40){
+ return ddr_clock >> 1;
+ }
+ return ddr_clock;
+#endif
+}
+
diff --git a/package/uboot-lantiq/files/cpu/mips/danube/ifx_cache.S b/package/uboot-lantiq/files/cpu/mips/danube/ifx_cache.S
new file mode 100644
index 000000000..fc482dcd6
--- /dev/null
+++ b/package/uboot-lantiq/files/cpu/mips/danube/ifx_cache.S
@@ -0,0 +1,60 @@
+
+#define IFX_CACHE_EXTRA_INVALID_TAG \
+ mtc0 zero, CP0_TAGLO, 1; \
+ mtc0 zero, CP0_TAGLO, 2; \
+ mtc0 zero, CP0_TAGLO, 3; \
+ mtc0 zero, CP0_TAGLO, 4;
+
+#define IFX_CACHE_EXTRA_OPERATION \
+ /* set WST bit */ \
+ mfc0 a0, CP0_ECC; \
+ li a1, ECCF_WST; \
+ or a0, a1; \
+ mtc0 a0, CP0_ECC; \
+ \
+ li a0, K0BASE; \
+ move a2, t2; /* icacheSize */ \
+ move a3, t4; /* icacheLineSize */ \
+ move a1, a2; \
+ icacheop(a0,a1,a2,a3,(Index_Store_Tag_I)); \
+ \
+ /* clear WST bit */ \
+ mfc0 a0, CP0_ECC; \
+ li a1, ~ECCF_WST; \
+ and a0, a1; \
+ mtc0 a0, CP0_ECC; \
+ \
+ /* 1: initialise dcache tags. */ \
+ \
+ /* cache line size */ \
+ li a2, CFG_CACHELINE_SIZE; \
+ /* kseg0 mem address */ \
+ li a1, 0; \
+ li a3, CFG_CACHE_SETS * CFG_CACHE_WAYS; \
+1: \
+ /* store tag (invalid, not locked) */ \
+ cache 0x8, 0(a1); \
+ cache 0x9, 0(a1); \
+ \
+ add a3, -1; \
+ bne a3, zero, 1b; \
+ add a1, a2; \
+ \
+ /* set WST bit */ \
+ mfc0 a0, CP0_ECC; \
+ li a1, ECCF_WST; \
+ or a0, a1; \
+ mtc0 a0, CP0_ECC; \
+ \
+ li a0, K0BASE; \
+ move a2, t3; /* dcacheSize */ \
+ move a3, t5; /* dcacheLineSize */ \
+ move a1, a2; \
+ icacheop(a0,a1,a2,a3,(Index_Store_Tag_D)); \
+ \
+ /* clear WST bit */ \
+ mfc0 a0, CP0_ECC; \
+ li a1, ~ECCF_WST; \
+ and a0, a1; \
+ mtc0 a0, CP0_ECC;
+
diff --git a/package/uboot-lantiq/files/cpu/mips/ifx_asc.c b/package/uboot-lantiq/files/cpu/mips/ifx_asc.c
new file mode 100644
index 000000000..5c13f2662
--- /dev/null
+++ b/package/uboot-lantiq/files/cpu/mips/ifx_asc.c
@@ -0,0 +1,218 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * (C) Copyright 2009
+ * Infineon Technologies AG, http://www.infineon.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+
+#include "ifx_asc.h"
+
+#define SET_BIT(reg, mask) asc_writel(reg, asc_readl(reg) | (mask))
+#define CLEAR_BIT(reg, mask) asc_writel(reg, asc_readl(reg) & (~mask))
+#define SET_BITFIELD(reg, mask, off, val) asc_writel(reg, (asc_readl(reg) & (~mask)) | (val << off) )
+
+#undef DEBUG_ASC_RAW
+#ifdef DEBUG_ASC_RAW
+#define DEBUG_ASC_RAW_RX_BUF 0xA0800000
+#define DEBUG_ASC_RAW_TX_BUF 0xA0900000
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static IfxAsc_t *pAsc = (IfxAsc_t *)CKSEG1ADDR(CONFIG_SYS_IFX_ASC_BASE);
+
+/*
+ * FDV fASC
+ * BaudRate = ----- * --------------------
+ * 512 16 * (ReloadValue+1)
+ */
+
+/*
+ * FDV fASC
+ * ReloadValue = ( ----- * --------------- ) - 1
+ * 512 16 * BaudRate
+ */
+static void serial_divs(u32 baudrate, u32 fasc, u32 *pfdv, u32 *preload)
+{
+ u32 clock = fasc / 16;
+
+ u32 fdv; /* best fdv */
+ u32 reload = 0; /* best reload */
+ u32 diff; /* smallest diff */
+ u32 idiff; /* current diff */
+ u32 ireload; /* current reload */
+ u32 i; /* current fdv */
+ u32 result; /* current resulting baudrate */
+
+ if (clock > 0x7FFFFF)
+ clock /= 512;
+ else
+ baudrate *= 512;
+
+ fdv = 512; /* start with 1:1 fraction */
+ diff = baudrate; /* highest possible */
+
+ /* i is the test fdv value -- start with the largest possible */
+ for (i = 512; i > 0; i--)
+ {
+ ireload = (clock * i) / baudrate;
+ if (ireload < 1)
+ break; /* already invalid */
+ result = (clock * i) / ireload;
+
+ idiff = (result > baudrate) ? (result - baudrate) : (baudrate - result);
+ if (idiff == 0)
+ {
+ fdv = i;
+ reload = ireload;
+ break; /* can't do better */
+ }
+ else if (idiff < diff)
+ {
+ fdv = i; /* best so far */
+ reload = ireload;
+ diff = idiff; /* update lowest diff*/
+ }
+ }
+
+ *pfdv = (fdv == 512) ? 0 : fdv;
+ *preload = reload - 1;
+}
+
+
+void serial_setbrg (void)
+{
+ u32 ReloadValue, fdv;
+
+ serial_divs(gd->baudrate, get_bus_freq(0), &fdv, &ReloadValue);
+
+ /* Disable Baud Rate Generator; BG should only be written when R=0 */
+ CLEAR_BIT(asc_con, ASCCON_R);
+
+ /* Enable Fractional Divider */
+ SET_BIT(asc_con, ASCCON_FDE); /* FDE = 1 */
+
+ /* Set fractional divider value */
+ asc_writel(asc_fdv, fdv & ASCFDV_VALUE_MASK);
+
+ /* Set reload value in BG */
+ asc_writel(asc_bg, ReloadValue);
+
+ /* Enable Baud Rate Generator */
+ SET_BIT(asc_con, ASCCON_R); /* R = 1 */
+}
+
+
+int serial_init (void)
+{
+
+ /* and we have to set CLC register*/
+ CLEAR_BIT(asc_clc, ASCCLC_DISS);
+ SET_BITFIELD(asc_clc, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 0x0001);
+
+ /* initialy we are in async mode */
+ asc_writel(asc_con, ASCCON_M_8ASYNC);
+
+ /* select input port */
+ asc_writel(asc_pisel, CONSOLE_TTY & 0x1);
+
+ /* TXFIFO's filling level */
+ SET_BITFIELD(asc_txfcon, ASCTXFCON_TXFITLMASK,
+ ASCTXFCON_TXFITLOFF, ASC_TXFIFO_FL);
+ /* enable TXFIFO */
+ SET_BIT(asc_txfcon, ASCTXFCON_TXFEN);
+
+ /* RXFIFO's filling level */
+ SET_BITFIELD(asc_txfcon, ASCRXFCON_RXFITLMASK,
+ ASCRXFCON_RXFITLOFF, ASC_RXFIFO_FL);
+ /* enable RXFIFO */
+ SET_BIT(asc_rxfcon, ASCRXFCON_RXFEN);
+
+ /* set baud rate */
+ serial_setbrg();
+
+ /* enable error signals & Receiver enable */
+ SET_BIT(asc_whbstate, ASCWHBSTATE_SETREN|ASCCON_FEN|ASCCON_TOEN|ASCCON_ROEN);
+
+ return 0;
+}
+
+
+void serial_putc (const char c)
+{
+ u32 txFl = 0;
+#ifdef DEBUG_ASC_RAW
+ static u8 * debug = (u8 *) DEBUG_ASC_RAW_TX_BUF;
+ *debug++=c;
+#endif
+ if (c == '\n')
+ serial_putc ('\r');
+ /* check do we have a free space in the TX FIFO */
+ /* get current filling level */
+ do {
+ txFl = ( asc_readl(asc_fstat) & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF;
+ }
+ while ( txFl == ASC_TXFIFO_FULL );
+
+ asc_writel(asc_tbuf, c); /* write char to Transmit Buffer Register */
+
+ /* check for errors */
+ if ( asc_readl(asc_state) & ASCSTATE_TOE ) {
+ SET_BIT(asc_whbstate, ASCWHBSTATE_CLRTOE);
+ return;
+ }
+}
+
+void serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
+
+int serial_getc (void)
+{
+ char c;
+ while ((asc_readl(asc_fstat) & ASCFSTAT_RXFFLMASK) == 0 );
+ c = (char)(asc_readl(asc_rbuf) & 0xff);
+
+#ifdef DEBUG_ASC_RAW
+ static u8* debug=(u8*)(DEBUG_ASC_RAW_RX_BUF);
+ *debug++=c;
+#endif
+ return c;
+}
+
+
+int serial_tstc (void)
+{
+ int res = 1;
+
+ if ( (asc_readl(asc_fstat) & ASCFSTAT_RXFFLMASK) == 0 ) {
+ res = 0;
+ }
+ return res;
+}
diff --git a/package/uboot-lantiq/files/cpu/mips/ifx_asc.h b/package/uboot-lantiq/files/cpu/mips/ifx_asc.h
new file mode 100644
index 000000000..2d3a49e1e
--- /dev/null
+++ b/package/uboot-lantiq/files/cpu/mips/ifx_asc.h
@@ -0,0 +1,199 @@
+/*****************************************************************************
+ * DANUBE BootROM
+ * Copyright (c) 2005, Infineon Technologies AG, All rights reserved
+ * IFAP DC COM SD
+ *****************************************************************************/
+#ifndef __ASC_H
+#define __ASC_H
+
+/* channel operating modes */
+#define ASCOPT_CSIZE 0x00000003
+#define ASCOPT_CS7 0x00000001
+#define ASCOPT_CS8 0x00000002
+#define ASCOPT_PARENB 0x00000004
+#define ASCOPT_STOPB 0x00000008
+#define ASCOPT_PARODD 0x00000010
+#define ASCOPT_CREAD 0x00000020
+
+#define ASC_OPTIONS (ASCOPT_CREAD | ASCOPT_CS8)
+
+/* ASC input select (0 or 1) */
+#define CONSOLE_TTY 0
+
+#define ASC_TXFIFO_FL 1
+#define ASC_RXFIFO_FL 1
+#define ASC_TXFIFO_FULL 16
+
+/* CLC register's bits and bitfields */
+#define ASCCLC_DISR 0x00000001
+#define ASCCLC_DISS 0x00000002
+#define ASCCLC_RMCMASK 0x0000FF00
+#define ASCCLC_RMCOFFSET 8
+
+/* CON register's bits and bitfields */
+#define ASCCON_MODEMASK 0x0000000f
+#define ASCCON_M_8ASYNC 0x0
+#define ASCCON_M_8IRDA 0x1
+#define ASCCON_M_7ASYNC 0x2
+#define ASCCON_M_7IRDA 0x3
+#define ASCCON_WLSMASK 0x0000000c
+#define ASCCON_WLSOFFSET 2
+#define ASCCON_WLS_8BIT 0x0
+#define ASCCON_WLS_7BIT 0x1
+#define ASCCON_PEN 0x00000010
+#define ASCCON_ODD 0x00000020
+#define ASCCON_SP 0x00000040
+#define ASCCON_STP 0x00000080
+#define ASCCON_BRS 0x00000100
+#define ASCCON_FDE 0x00000200
+#define ASCCON_ERRCLK 0x00000400
+#define ASCCON_EMMASK 0x00001800
+#define ASCCON_EMOFFSET 11
+#define ASCCON_EM_ECHO_OFF 0x0
+#define ASCCON_EM_ECHO_AB 0x1
+#define ASCCON_EM_ECHO_ON 0x2
+#define ASCCON_LB 0x00002000
+#define ASCCON_ACO 0x00004000
+#define ASCCON_R 0x00008000
+#define ASCCON_PAL 0x00010000
+#define ASCCON_FEN 0x00020000
+#define ASCCON_RUEN 0x00040000
+#define ASCCON_ROEN 0x00080000
+#define ASCCON_TOEN 0x00100000
+#define ASCCON_BEN 0x00200000
+#define ASCCON_TXINV 0x01000000
+#define ASCCON_RXINV 0x02000000
+#define ASCCON_TXMSB 0x04000000
+#define ASCCON_RXMSB 0x08000000
+
+/* STATE register's bits and bitfields */
+#define ASCSTATE_REN 0x00000001
+#define ASCSTATE_PE 0x00010000
+#define ASCSTATE_FE 0x00020000
+#define ASCSTATE_RUE 0x00040000
+#define ASCSTATE_ROE 0x00080000
+#define ASCSTATE_TOE 0x00100000
+#define ASCSTATE_BE 0x00200000
+#define ASCSTATE_TXBVMASK 0x07000000
+#define ASCSTATE_TXBVOFFSET 24
+#define ASCSTATE_TXEOM 0x08000000
+#define ASCSTATE_RXBVMASK 0x70000000
+#define ASCSTATE_RXBVOFFSET 28
+#define ASCSTATE_RXEOM 0x80000000
+
+/* WHBSTATE register's bits and bitfields */
+#define ASCWHBSTATE_CLRREN 0x00000001
+#define ASCWHBSTATE_SETREN 0x00000002
+#define ASCWHBSTATE_CLRPE 0x00000004
+#define ASCWHBSTATE_CLRFE 0x00000008
+#define ASCWHBSTATE_CLRRUE 0x00000010
+#define ASCWHBSTATE_CLRROE 0x00000020
+#define ASCWHBSTATE_CLRTOE 0x00000040
+#define ASCWHBSTATE_CLRBE 0x00000080
+#define ASCWHBSTATE_SETPE 0x00000100
+#define ASCWHBSTATE_SETFE 0x00000200
+#define ASCWHBSTATE_SETRUE 0x00000400
+#define ASCWHBSTATE_SETROE 0x00000800
+#define ASCWHBSTATE_SETTOE 0x00001000
+#define ASCWHBSTATE_SETBE 0x00002000
+
+/* ABCON register's bits and bitfields */
+#define ASCABCON_ABEN 0x0001
+#define ASCABCON_AUREN 0x0002
+#define ASCABCON_ABSTEN 0x0004
+#define ASCABCON_ABDETEN 0x0008
+#define ASCABCON_FCDETEN 0x0010
+
+/* FDV register mask, offset and bitfields*/
+#define ASCFDV_VALUE_MASK 0x000001FF
+
+/* WHBABCON register's bits and bitfields */
+#define ASCWHBABCON_CLRABEN 0x0001
+#define ASCWHBABCON_SETABEN 0x0002
+
+/* ABSTAT register's bits and bitfields */
+#define ASCABSTAT_FCSDET 0x0001
+#define ASCABSTAT_FCCDET 0x0002
+#define ASCABSTAT_SCSDET 0x0004
+#define ASCABSTAT_SCCDET 0x0008
+#define ASCABSTAT_DETWAIT 0x0010
+
+/* WHBABSTAT register's bits and bitfields */
+#define ASCWHBABSTAT_CLRFCSDET 0x0001
+#define ASCWHBABSTAT_SETFCSDET 0x0002
+#define ASCWHBABSTAT_CLRFCCDET 0x0004
+#define ASCWHBABSTAT_SETFCCDET 0x0008
+#define ASCWHBABSTAT_CLRSCSDET 0x0010
+#define ASCWHBABSTAT_SETSCSDET 0x0020
+#define ASCWHBABSTAT_CLRSCCDET 0x0040
+#define ASCWHBABSTAT_SETSCCDET 0x0080
+#define ASCWHBABSTAT_CLRDETWAIT 0x0100
+#define ASCWHBABSTAT_SETDETWAIT 0x0200
+
+/* TXFCON register's bits and bitfields */
+#define ASCTXFCON_TXFIFO1 0x00000400
+#define ASCTXFCON_TXFEN 0x0001
+#define ASCTXFCON_TXFFLU 0x0002
+#define ASCTXFCON_TXFITLMASK 0x3F00
+#define ASCTXFCON_TXFITLOFF 8
+
+/* RXFCON register's bits and bitfields */
+#define ASCRXFCON_RXFIFO1 0x00000400
+#define ASCRXFCON_RXFEN 0x0001
+#define ASCRXFCON_RXFFLU 0x0002
+#define ASCRXFCON_RXFITLMASK 0x3F00
+#define ASCRXFCON_RXFITLOFF 8
+
+/* FSTAT register's bits and bitfields */
+#define ASCFSTAT_RXFFLMASK 0x003F
+#define ASCFSTAT_TXFFLMASK 0x3F00
+#define ASCFSTAT_TXFFLOFF 8
+
+typedef struct IfxAsc_s
+{
+ unsigned long asc_clc; /*0x0000*/
+ unsigned long asc_pisel; /*0x0004*/
+ unsigned long asc_id; /*0x0008*/
+ unsigned long asc_rsvd1[1]; /* for mapping */ /*0x000C*/
+ unsigned long asc_con; /*0x0010*/
+ unsigned long asc_state; /*0x0014*/
+ unsigned long asc_whbstate; /*0x0018*/
+ unsigned long asc_rsvd2[1]; /* for mapping */ /*0x001C*/
+ unsigned long asc_tbuf; /*0x0020*/
+ unsigned long asc_rbuf; /*0x0024*/
+ unsigned long asc_rsvd3[2]; /* for mapping */ /*0x0028*/
+ unsigned long asc_abcon; /*0x0030*/
+ unsigned long asc_abstat; /* not used */ /*0x0034*/
+ unsigned long asc_whbabcon; /*0x0038*/
+ unsigned long asc_whbabstat; /* not used */ /*0x003C*/
+ unsigned long asc_rxfcon; /*0x0040*/
+ unsigned long asc_txfcon; /*0x0044*/
+ unsigned long asc_fstat; /*0x0048*/
+ unsigned long asc_rsvd4[1]; /* for mapping */ /*0x004C*/
+ unsigned long asc_bg; /*0x0050*/
+ unsigned long asc_bg_timer; /*0x0054*/
+ unsigned long asc_fdv; /*0x0058*/
+ unsigned long asc_pmw; /*0x005C*/
+ unsigned long asc_modcon; /*0x0060*/
+ unsigned long asc_modstat; /*0x0064*/
+ unsigned long asc_rsvd5[2]; /* for mapping */ /*0x0068*/
+ unsigned long asc_sfcc; /*0x0070*/
+ unsigned long asc_rsvd6[3]; /* for mapping */ /*0x0074*/
+ unsigned long asc_eomcon; /*0x0080*/
+ unsigned long asc_rsvd7[26]; /* for mapping */ /*0x0084*/
+ unsigned long asc_dmacon; /*0x00EC*/
+ unsigned long asc_rsvd8[1]; /* for mapping */ /*0x00F0*/
+ unsigned long asc_irnen; /*0x00F4*/
+ unsigned long asc_irnicr; /*0x00F8*/
+ unsigned long asc_irncr; /*0x00FC*/
+} IfxAsc_t;
+
+
+/* Register access macros */
+#define asc_readl(reg) \
+ readl(&pAsc->reg)
+#define asc_writel(reg,value) \
+ writel((value), &pAsc->reg)
+
+
+#endif /* __ASC_H */
diff --git a/package/uboot-lantiq/files/drivers/net/ifx_etop.c b/package/uboot-lantiq/files/drivers/net/ifx_etop.c
new file mode 100644
index 000000000..8a03683c0
--- /dev/null
+++ b/package/uboot-lantiq/files/drivers/net/ifx_etop.c
@@ -0,0 +1,401 @@
+/*
+ * Lantiq CPE device ethernet driver.
+ * Supposed to work on Twinpass/Danube.
+ *
+ * Based on INCA-IP driver:
+ * (C) Copyright 2003-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2010
+ * Thomas Langer, Ralph Hempel
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <common.h>
+
+#include <malloc.h>
+#include <net.h>
+#include <miiphy.h>
+#include <asm/types.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <config.h>
+
+#include "ifx_etop.h"
+
+#if defined(CONFIG_AR9)
+#define TX_CHAN_NO 1
+#define RX_CHAN_NO 0
+#else
+#define TX_CHAN_NO 7
+#define RX_CHAN_NO 6
+#endif
+
+#define NUM_RX_DESC PKTBUFSRX
+#define NUM_TX_DESC 8
+#define TOUT_LOOP 100
+
+typedef struct
+{
+ union
+ {
+ struct
+ {
+ volatile u32 OWN :1;
+ volatile u32 C :1;
+ volatile u32 Sop :1;
+ volatile u32 Eop :1;
+ volatile u32 reserved :3;
+ volatile u32 Byteoffset :2;
+ volatile u32 reserve :7;
+ volatile u32 DataLen :16;
+ }field;
+
+ volatile u32 word;
+ }status;
+
+ volatile u32 DataPtr;
+} dma_rx_descriptor_t;
+
+typedef struct
+{
+ union
+ {
+ struct
+ {
+ volatile u32 OWN :1;
+ volatile u32 C :1;
+ volatile u32 Sop :1;
+ volatile u32 Eop :1;
+ volatile u32 Byteoffset :5;
+ volatile u32 reserved :7;
+ volatile u32 DataLen :16;
+ }field;
+
+ volatile u32 word;
+ }status;
+
+ volatile u32 DataPtr;
+} dma_tx_descriptor_t;
+
+static volatile dma_rx_descriptor_t rx_des_ring[NUM_RX_DESC] __attribute__ ((aligned(8)));
+static volatile dma_tx_descriptor_t tx_des_ring[NUM_TX_DESC] __attribute__ ((aligned(8)));
+static int tx_num, rx_num;
+
+static volatile IfxDMA_t *pDma = (IfxDMA_t *)CKSEG1ADDR(DANUBE_DMA_BASE);
+
+static int lq_eth_init(struct eth_device *dev, bd_t * bis);
+static int lq_eth_send(struct eth_device *dev, volatile void *packet,int length);
+static int lq_eth_recv(struct eth_device *dev);
+static void lq_eth_halt(struct eth_device *dev);
+static void lq_eth_init_chip(void);
+static void lq_eth_init_dma(void);
+
+static int lq_eth_miiphy_read(char *devname, u8 phyAddr, u8 regAddr, u16 * retVal)
+{
+ u32 timeout = 50000;
+ u32 phy, reg;
+
+ if ((phyAddr > 0x1F) || (regAddr > 0x1F) || (retVal == NULL))
+ return -1;
+
+ phy = (phyAddr & 0x1F) << 21;
+ reg = (regAddr & 0x1F) << 16;
+
+ *ETOP_MDIO_ACC = 0xC0000000 | phy | reg;
+ while ((timeout--) && (*ETOP_MDIO_ACC & 0x80000000))
+ udelay(10);
+
+ if (timeout==0) {
+ *retVal = 0;
+ return -1;
+ }
+ *retVal = *ETOP_MDIO_ACC & 0xFFFF;
+ return 0;
+}
+
+static int lq_eth_miiphy_write(char *devname, u8 phyAddr, u8 regAddr, u16 data)
+{
+ u32 timeout = 50000;
+ u32 phy, reg;
+
+ if ((phyAddr > 0x1F) || (regAddr > 0x1F))
+ return -1;
+
+ phy = (phyAddr & 0x1F) << 21;
+ reg = (regAddr & 0x1F) << 16;
+
+ *ETOP_MDIO_ACC = 0x80000000 | phy | reg | data;
+ while ((timeout--) && (*ETOP_MDIO_ACC & 0x80000000))
+ udelay(10);
+
+ if (timeout==0)
+ return -1;
+ return 0;
+}
+
+
+int lq_eth_initialize(bd_t * bis)
+{
+ struct eth_device *dev;
+
+ debug("Entered lq_eth_initialize()\n");
+
+ if (!(dev = malloc (sizeof *dev))) {
+ printf("Failed to allocate memory\n");
+ return -1;
+ }
+ memset(dev, 0, sizeof(*dev));
+
+ sprintf(dev->name, "lq_cpe_eth");
+ dev->init = lq_eth_init;
+ dev->halt = lq_eth_halt;
+ dev->send = lq_eth_send;
+ dev->recv = lq_eth_recv;
+
+ eth_register(dev);
+
+#if defined (CONFIG_MII) || defined(CONFIG_CMD_MII)
+ /* register mii command access routines */
+ miiphy_register(dev->name,
+ lq_eth_miiphy_read, lq_eth_miiphy_write);
+#endif
+
+ lq_eth_init_dma();
+ lq_eth_init_chip();
+
+ return 0;
+}
+
+static int lq_eth_init(struct eth_device *dev, bd_t * bis)
+{
+ int i;
+ uchar *enetaddr = dev->enetaddr;
+
+ debug("lq_eth_init %x:%x:%x:%x:%x:%x\n",
+ enetaddr[0], enetaddr[1], enetaddr[2], enetaddr[3], enetaddr[4], enetaddr[5]);
+
+ *ENET_MAC_DA0 = (enetaddr[0]<<24) + (enetaddr[1]<<16) + (enetaddr[2]<< 8) + enetaddr[3];
+ *ENET_MAC_DA1 = (enetaddr[4]<<24) + (enetaddr[5]<<16);
+ *ENETS_CFG |= 1<<28; /* enable filter for unicast packets */
+
+ tx_num=0;
+ rx_num=0;
+
+ for(i=0;i < NUM_RX_DESC; i++) {
+ dma_rx_descriptor_t * rx_desc = (dma_rx_descriptor_t *)CKSEG1ADDR(&rx_des_ring[i]);
+ rx_desc->status.word=0;
+ rx_desc->status.field.OWN=1;
+ rx_desc->status.field.DataLen=PKTSIZE_ALIGN; /* 1536 */
+ rx_desc->DataPtr=(u32)CKSEG1ADDR(NetRxPackets[i]);
+ NetRxPackets[i][0] = 0xAA;
+ }
+
+ /* Reset DMA */
+ dma_writel(dma_cs, RX_CHAN_NO);
+ dma_writel(dma_cctrl, 0x2);/*fix me, need to reset this channel first?*/
+ dma_writel(dma_cpoll, 0x80000040);
+ /*set descriptor base*/
+ dma_writel(dma_cdba, (u32)rx_des_ring);
+ dma_writel(dma_cdlen, NUM_RX_DESC);
+ dma_writel(dma_cie, 0);
+ dma_writel(dma_cctrl, 0x30000);
+
+ for(i=0;i < NUM_TX_DESC; i++) {
+ dma_tx_descriptor_t * tx_desc = (dma_tx_descriptor_t *)CKSEG1ADDR(&tx_des_ring[i]);
+ memset(tx_desc, 0, sizeof(tx_des_ring[0]));
+ }
+
+ dma_writel(dma_cs, TX_CHAN_NO);
+ dma_writel(dma_cctrl, 0x2);/*fix me, need to reset this channel first?*/
+ dma_writel(dma_cpoll, 0x80000040);
+ dma_writel(dma_cdba, (u32)tx_des_ring);
+ dma_writel(dma_cdlen, NUM_TX_DESC);
+ dma_writel(dma_cie, 0);
+ dma_writel(dma_cctrl, 0x30100);
+
+ /* turn on DMA rx & tx channel
+ */
+ dma_writel(dma_cs, RX_CHAN_NO);
+ dma_writel(dma_cctrl, dma_readl(dma_cctrl) | 1); /*reset and turn on the channel*/
+
+ return 0;
+}
+
+static void lq_eth_halt(struct eth_device *dev)
+{
+ int i;
+
+ debug("lq_eth_halt()\n");
+
+ for(i=0;i<8;i++) {
+ dma_writel(dma_cs, i);
+ dma_writel(dma_cctrl, dma_readl(dma_cctrl) & ~1);/*stop the dma channel*/
+ }
+}
+
+#ifdef DEBUG
+static void lq_dump(const u8 *data, const u32 length)
+{
+ u32 i;
+ debug("\n");
+ for(i=0;i<length;i++) {
+ debug("%02x ", data[i]);
+ }
+ debug("\n");
+}
+#endif
+
+static int lq_eth_send(struct eth_device *dev, volatile void *packet, int length)
+{
+ int i;
+ int res = -1;
+ volatile dma_tx_descriptor_t * tx_desc = (dma_tx_descriptor_t *)CKSEG1ADDR(&tx_des_ring[tx_num]);
+
+ if (length <= 0) {
+ printf ("%s: bad packet size: %d\n", dev->name, length);
+ goto Done;
+ }
+
+ for(i=0; tx_desc->status.field.OWN==1; i++) {
+ if (i>=TOUT_LOOP) {
+ printf("NO Tx Descriptor...");
+ goto Done;
+ }
+ }
+
+ tx_desc->status.field.Sop=1;
+ tx_desc->status.field.Eop=1;
+ tx_desc->status.field.C=0;
+ tx_desc->DataPtr = (u32)CKSEG1ADDR(packet);
+ if (length<60)
+ tx_desc->status.field.DataLen = 60;
+ else
+ tx_desc->status.field.DataLen = (u32)length;
+
+ flush_cache((u32)packet, tx_desc->status.field.DataLen);
+ asm("SYNC");
+ tx_desc->status.field.OWN=1;
+
+ res=length;
+ tx_num++;
+ if (tx_num==NUM_TX_DESC) tx_num=0;
+
+#ifdef DEBUG
+ lq_dump(tx_desc->DataPtr, tx_desc->status.field.DataLen);
+#endif
+
+ dma_writel(dma_cs, TX_CHAN_NO);
+ if (!(dma_readl(dma_cctrl) & 1)) {
+ dma_writel(dma_cctrl, dma_readl(dma_cctrl) | 1);
+ }
+
+Done:
+ return res;
+}
+
+static int lq_eth_recv(struct eth_device *dev)
+{
+ int length = 0;
+ volatile dma_rx_descriptor_t * rx_desc;
+
+ rx_desc = (dma_rx_descriptor_t *)CKSEG1ADDR(&rx_des_ring[rx_num]);
+
+ if ((rx_desc->status.field.C == 0) || (rx_desc->status.field.OWN == 1)) {
+ return 0;
+ }
+ debug("rx");
+#ifdef DEBUG
+ lq_dump(rx_desc->DataPtr, rx_desc->status.field.DataLen);
+#endif
+ length = rx_desc->status.field.DataLen;
+ if (length > 4) {
+ invalidate_dcache_range((u32)CKSEG0ADDR(rx_desc->DataPtr), (u32) CKSEG0ADDR(rx_desc->DataPtr) + length);
+ NetReceive(NetRxPackets[rx_num], length);
+ } else {
+ printf("ERROR: Invalid rx packet length.\n");
+ }
+
+ rx_desc->status.field.Sop=0;
+ rx_desc->status.field.Eop=0;
+ rx_desc->status.field.C=0;
+ rx_desc->status.field.DataLen=PKTSIZE_ALIGN;
+ rx_desc->status.field.OWN=1;
+
+ rx_num++;
+ if (rx_num == NUM_RX_DESC)
+ rx_num=0;
+
+ return length;
+}
+
+static void lq_eth_init_chip(void)
+{
+ *ETOP_MDIO_CFG &= ~0x6;
+ *ENET_MAC_CFG = 0x187;
+
+ // turn on port0, set to rmii and turn off port1.
+#ifdef CONFIG_RMII
+ *ETOP_CFG = (*ETOP_CFG & 0xFFFFFFFC) | 0x0000000A;
+#else
+ *ETOP_CFG = (*ETOP_CFG & 0xFFFFFFFC) | 0x00000008;
+#endif
+
+ *ETOP_IG_PLEN_CTRL = 0x004005EE; // set packetlen.
+ *ENET_MAC_CFG |= 1<<11; /*enable the crc*/
+ return;
+}
+
+static void lq_eth_init_dma(void)
+{
+ /* Reset DMA */
+ dma_writel(dma_ctrl, dma_readl(dma_ctrl) | 1);
+ dma_writel(dma_irnen, 0);/*disable all the interrupts first*/
+
+ /* Clear Interrupt Status Register */
+ dma_writel(dma_irncr, 0xfffff);
+ /*disable all the dma interrupts*/
+ dma_writel(dma_irnen, 0);
+ /*disable channel 0 and channel 1 interrupts*/
+
+ dma_writel(dma_cs, RX_CHAN_NO);
+ dma_writel(dma_cctrl, 0x2);/*fix me, need to reset this channel first?*/
+ dma_writel(dma_cpoll, 0x80000040);
+ /*set descriptor base*/
+ dma_writel(dma_cdba, (u32)rx_des_ring);
+ dma_writel(dma_cdlen, NUM_RX_DESC);
+ dma_writel(dma_cie, 0);
+ dma_writel(dma_cctrl, 0x30000);
+
+ dma_writel(dma_cs, TX_CHAN_NO);
+ dma_writel(dma_cctrl, 0x2);/*fix me, need to reset this channel first?*/
+ dma_writel(dma_cpoll, 0x80000040);
+ dma_writel(dma_cdba, (u32)tx_des_ring);
+ dma_writel(dma_cdlen, NUM_TX_DESC);
+ dma_writel(dma_cie, 0);
+ dma_writel(dma_cctrl, 0x30100);
+ /*enable the poll function and set the poll counter*/
+ //dma_writel(DMA_CPOLL=DANUBE_DMA_POLL_EN | (DANUBE_DMA_POLL_COUNT<<4);
+ /*set port properties, enable endian conversion for switch*/
+ dma_writel(dma_ps, 0);
+ dma_writel(dma_pctrl, dma_readl(dma_pctrl) | (0xf<<8));/*enable 32 bit endian conversion*/
+
+ return;
+}
diff --git a/package/uboot-lantiq/files/drivers/net/ifx_etop.h b/package/uboot-lantiq/files/drivers/net/ifx_etop.h
new file mode 100644
index 000000000..99708684e
--- /dev/null
+++ b/package/uboot-lantiq/files/drivers/net/ifx_etop.h
@@ -0,0 +1,91 @@
+/*
+ * Lantiq switch ethernet driver for Danube family.
+ *
+ * Based on INCA-IP driver:
+ * (C) Copyright 2003-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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 __DRIVERS_IFX_SW_H__
+#define __DRIVERS_IFX_SW_H__
+
+#define DANUBE_PPE32_BASE 0xBE180000
+#define DANUBE_PPE32_DATA_MEM_MAP_REG_BASE (DANUBE_PPE32_BASE + (0x4000 * 4))
+
+#define ETOP_MDIO_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0600 * 4)))
+#define ETOP_MDIO_ACC ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0601 * 4)))
+#define ETOP_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0602 * 4)))
+#define ETOP_IG_VLAN_COS ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0603 * 4)))
+#define ETOP_IG_DSCP_COS3 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0604 * 4)))
+#define ETOP_IG_DSCP_COS2 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0605 * 4)))
+#define ETOP_IG_DSCP_COS1 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0606 * 4)))
+#define ETOP_IG_DSCP_COS0 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0607 * 4)))
+#define ETOP_IG_PLEN_CTRL ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0608 * 4)))
+#define ETOP_ISR ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x060A * 4)))
+#define ETOP_IER ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x060B * 4)))
+#define ETOP_VPID ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x060C * 4)))
+#define ENET_MAC_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0610 * 4)))
+#define ENETS_DBA ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0612 * 4)))
+#define ENETS_CBA ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0613 * 4)))
+#define ENETS_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0614 * 4)))
+#define ENETS_PGCNT ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0615 * 4)))
+#define ENETS_PKTCNT ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0616 * 4)))
+#define ENETS_BUF_CTRL ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0617 * 4)))
+#define ENETS_COS_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0618 * 4)))
+#define ENETS_IGDROP ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0619 * 4)))
+#define ENETS_IGERR ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x061A * 4)))
+#define ENET_MAC_DA0 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x061B * 4)))
+#define ENET_MAC_DA1 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x061C * 4)))
+
+
+
+#define DANUBE_DMA_BASE 0xBE104100
+
+typedef struct IfxDMA_s
+{
+ unsigned long dma_clc; /*0x0000*/
+ unsigned long dma_rsvd1[1]; /* for mapping */ /*0x0004*/
+ unsigned long dma_id; /*0x0008*/
+ unsigned long dma_rsvd2[1]; /* for mapping */ /*0x000C*/
+ unsigned long dma_ctrl; /*0x0010*/
+ unsigned long dma_cpoll; /*0x0014*/
+ unsigned long dma_cs; /*0x0018*/
+ unsigned long dma_cctrl; /*0x001C*/
+ unsigned long dma_cdba; /*0x0020*/
+ unsigned long dma_cdlen; /*0x0024*/
+ unsigned long dma_cis; /*0x0028*/
+ unsigned long dma_cie; /*0x002C*/
+ unsigned long dma_rsvd3[4]; /* for mapping */ /*0x0030*/
+ unsigned long dma_ps; /*0x0040*/
+ unsigned long dma_pctrl; /*0x0044*/
+ unsigned long dma_rsvd4[43]; /* for mapping */ /*0x0048*/
+ unsigned long dma_irnen; /*0x00F4*/
+ unsigned long dma_irncr; /*0x00F8*/
+ unsigned long dma_irnicr; /*0x00FC*/
+} IfxDMA_t;
+
+/* Register access macros */
+#define dma_readl(reg) \
+ readl(&pDma->reg)
+#define dma_writel(reg,value) \
+ writel((value), &pDma->reg)
+
+int lq_eth_initialize(bd_t * bis);
+
+#endif /* __DRIVERS_IFX_SW_H__ */
diff --git a/package/uboot-lantiq/files/drivers/serial/ifx_asc.c b/package/uboot-lantiq/files/drivers/serial/ifx_asc.c
new file mode 100644
index 000000000..5c13f2662
--- /dev/null
+++ b/package/uboot-lantiq/files/drivers/serial/ifx_asc.c
@@ -0,0 +1,218 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * (C) Copyright 2009
+ * Infineon Technologies AG, http://www.infineon.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+
+#include "ifx_asc.h"
+
+#define SET_BIT(reg, mask) asc_writel(reg, asc_readl(reg) | (mask))
+#define CLEAR_BIT(reg, mask) asc_writel(reg, asc_readl(reg) & (~mask))
+#define SET_BITFIELD(reg, mask, off, val) asc_writel(reg, (asc_readl(reg) & (~mask)) | (val << off) )
+
+#undef DEBUG_ASC_RAW
+#ifdef DEBUG_ASC_RAW
+#define DEBUG_ASC_RAW_RX_BUF 0xA0800000
+#define DEBUG_ASC_RAW_TX_BUF 0xA0900000
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static IfxAsc_t *pAsc = (IfxAsc_t *)CKSEG1ADDR(CONFIG_SYS_IFX_ASC_BASE);
+
+/*
+ * FDV fASC
+ * BaudRate = ----- * --------------------
+ * 512 16 * (ReloadValue+1)
+ */
+
+/*
+ * FDV fASC
+ * ReloadValue = ( ----- * --------------- ) - 1
+ * 512 16 * BaudRate
+ */
+static void serial_divs(u32 baudrate, u32 fasc, u32 *pfdv, u32 *preload)
+{
+ u32 clock = fasc / 16;
+
+ u32 fdv; /* best fdv */
+ u32 reload = 0; /* best reload */
+ u32 diff; /* smallest diff */
+ u32 idiff; /* current diff */
+ u32 ireload; /* current reload */
+ u32 i; /* current fdv */
+ u32 result; /* current resulting baudrate */
+
+ if (clock > 0x7FFFFF)
+ clock /= 512;
+ else
+ baudrate *= 512;
+
+ fdv = 512; /* start with 1:1 fraction */
+ diff = baudrate; /* highest possible */
+
+ /* i is the test fdv value -- start with the largest possible */
+ for (i = 512; i > 0; i--)
+ {
+ ireload = (clock * i) / baudrate;
+ if (ireload < 1)
+ break; /* already invalid */
+ result = (clock * i) / ireload;
+
+ idiff = (result > baudrate) ? (result - baudrate) : (baudrate - result);
+ if (idiff == 0)
+ {
+ fdv = i;
+ reload = ireload;
+ break; /* can't do better */
+ }
+ else if (idiff < diff)
+ {
+ fdv = i; /* best so far */
+ reload = ireload;
+ diff = idiff; /* update lowest diff*/
+ }
+ }
+
+ *pfdv = (fdv == 512) ? 0 : fdv;
+ *preload = reload - 1;
+}
+
+
+void serial_setbrg (void)
+{
+ u32 ReloadValue, fdv;
+
+ serial_divs(gd->baudrate, get_bus_freq(0), &fdv, &ReloadValue);
+
+ /* Disable Baud Rate Generator; BG should only be written when R=0 */
+ CLEAR_BIT(asc_con, ASCCON_R);
+
+ /* Enable Fractional Divider */
+ SET_BIT(asc_con, ASCCON_FDE); /* FDE = 1 */
+
+ /* Set fractional divider value */
+ asc_writel(asc_fdv, fdv & ASCFDV_VALUE_MASK);
+
+ /* Set reload value in BG */
+ asc_writel(asc_bg, ReloadValue);
+
+ /* Enable Baud Rate Generator */
+ SET_BIT(asc_con, ASCCON_R); /* R = 1 */
+}
+
+
+int serial_init (void)
+{
+
+ /* and we have to set CLC register*/
+ CLEAR_BIT(asc_clc, ASCCLC_DISS);
+ SET_BITFIELD(asc_clc, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 0x0001);
+
+ /* initialy we are in async mode */
+ asc_writel(asc_con, ASCCON_M_8ASYNC);
+
+ /* select input port */
+ asc_writel(asc_pisel, CONSOLE_TTY & 0x1);
+
+ /* TXFIFO's filling level */
+ SET_BITFIELD(asc_txfcon, ASCTXFCON_TXFITLMASK,
+ ASCTXFCON_TXFITLOFF, ASC_TXFIFO_FL);
+ /* enable TXFIFO */
+ SET_BIT(asc_txfcon, ASCTXFCON_TXFEN);
+
+ /* RXFIFO's filling level */
+ SET_BITFIELD(asc_txfcon, ASCRXFCON_RXFITLMASK,
+ ASCRXFCON_RXFITLOFF, ASC_RXFIFO_FL);
+ /* enable RXFIFO */
+ SET_BIT(asc_rxfcon, ASCRXFCON_RXFEN);
+
+ /* set baud rate */
+ serial_setbrg();
+
+ /* enable error signals & Receiver enable */
+ SET_BIT(asc_whbstate, ASCWHBSTATE_SETREN|ASCCON_FEN|ASCCON_TOEN|ASCCON_ROEN);
+
+ return 0;
+}
+
+
+void serial_putc (const char c)
+{
+ u32 txFl = 0;
+#ifdef DEBUG_ASC_RAW
+ static u8 * debug = (u8 *) DEBUG_ASC_RAW_TX_BUF;
+ *debug++=c;
+#endif
+ if (c == '\n')
+ serial_putc ('\r');
+ /* check do we have a free space in the TX FIFO */
+ /* get current filling level */
+ do {
+ txFl = ( asc_readl(asc_fstat) & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF;
+ }
+ while ( txFl == ASC_TXFIFO_FULL );
+
+ asc_writel(asc_tbuf, c); /* write char to Transmit Buffer Register */
+
+ /* check for errors */
+ if ( asc_readl(asc_state) & ASCSTATE_TOE ) {
+ SET_BIT(asc_whbstate, ASCWHBSTATE_CLRTOE);
+ return;
+ }
+}
+
+void serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
+
+int serial_getc (void)
+{
+ char c;
+ while ((asc_readl(asc_fstat) & ASCFSTAT_RXFFLMASK) == 0 );
+ c = (char)(asc_readl(asc_rbuf) & 0xff);
+
+#ifdef DEBUG_ASC_RAW
+ static u8* debug=(u8*)(DEBUG_ASC_RAW_RX_BUF);
+ *debug++=c;
+#endif
+ return c;
+}
+
+
+int serial_tstc (void)
+{
+ int res = 1;
+
+ if ( (asc_readl(asc_fstat) & ASCFSTAT_RXFFLMASK) == 0 ) {
+ res = 0;
+ }
+ return res;
+}
diff --git a/package/uboot-lantiq/files/drivers/serial/ifx_asc.h b/package/uboot-lantiq/files/drivers/serial/ifx_asc.h
new file mode 100644
index 000000000..2d3a49e1e
--- /dev/null
+++ b/package/uboot-lantiq/files/drivers/serial/ifx_asc.h
@@ -0,0 +1,199 @@
+/*****************************************************************************
+ * DANUBE BootROM
+ * Copyright (c) 2005, Infineon Technologies AG, All rights reserved
+ * IFAP DC COM SD
+ *****************************************************************************/
+#ifndef __ASC_H
+#define __ASC_H
+
+/* channel operating modes */
+#define ASCOPT_CSIZE 0x00000003
+#define ASCOPT_CS7 0x00000001
+#define ASCOPT_CS8 0x00000002
+#define ASCOPT_PARENB 0x00000004
+#define ASCOPT_STOPB 0x00000008
+#define ASCOPT_PARODD 0x00000010
+#define ASCOPT_CREAD 0x00000020
+
+#define ASC_OPTIONS (ASCOPT_CREAD | ASCOPT_CS8)
+
+/* ASC input select (0 or 1) */
+#define CONSOLE_TTY 0
+
+#define ASC_TXFIFO_FL 1
+#define ASC_RXFIFO_FL 1
+#define ASC_TXFIFO_FULL 16
+
+/* CLC register's bits and bitfields */
+#define ASCCLC_DISR 0x00000001
+#define ASCCLC_DISS 0x00000002
+#define ASCCLC_RMCMASK 0x0000FF00
+#define ASCCLC_RMCOFFSET 8
+
+/* CON register's bits and bitfields */
+#define ASCCON_MODEMASK 0x0000000f
+#define ASCCON_M_8ASYNC 0x0
+#define ASCCON_M_8IRDA 0x1
+#define ASCCON_M_7ASYNC 0x2
+#define ASCCON_M_7IRDA 0x3
+#define ASCCON_WLSMASK 0x0000000c
+#define ASCCON_WLSOFFSET 2
+#define ASCCON_WLS_8BIT 0x0
+#define ASCCON_WLS_7BIT 0x1
+#define ASCCON_PEN 0x00000010
+#define ASCCON_ODD 0x00000020
+#define ASCCON_SP 0x00000040
+#define ASCCON_STP 0x00000080
+#define ASCCON_BRS 0x00000100
+#define ASCCON_FDE 0x00000200
+#define ASCCON_ERRCLK 0x00000400
+#define ASCCON_EMMASK 0x00001800
+#define ASCCON_EMOFFSET 11
+#define ASCCON_EM_ECHO_OFF 0x0
+#define ASCCON_EM_ECHO_AB 0x1
+#define ASCCON_EM_ECHO_ON 0x2
+#define ASCCON_LB 0x00002000
+#define ASCCON_ACO 0x00004000
+#define ASCCON_R 0x00008000
+#define ASCCON_PAL 0x00010000
+#define ASCCON_FEN 0x00020000
+#define ASCCON_RUEN 0x00040000
+#define ASCCON_ROEN 0x00080000
+#define ASCCON_TOEN 0x00100000
+#define ASCCON_BEN 0x00200000
+#define ASCCON_TXINV 0x01000000
+#define ASCCON_RXINV 0x02000000
+#define ASCCON_TXMSB 0x04000000
+#define ASCCON_RXMSB 0x08000000
+
+/* STATE register's bits and bitfields */
+#define ASCSTATE_REN 0x00000001
+#define ASCSTATE_PE 0x00010000
+#define ASCSTATE_FE 0x00020000
+#define ASCSTATE_RUE 0x00040000
+#define ASCSTATE_ROE 0x00080000
+#define ASCSTATE_TOE 0x00100000
+#define ASCSTATE_BE 0x00200000
+#define ASCSTATE_TXBVMASK 0x07000000
+#define ASCSTATE_TXBVOFFSET 24
+#define ASCSTATE_TXEOM 0x08000000
+#define ASCSTATE_RXBVMASK 0x70000000
+#define ASCSTATE_RXBVOFFSET 28
+#define ASCSTATE_RXEOM 0x80000000
+
+/* WHBSTATE register's bits and bitfields */
+#define ASCWHBSTATE_CLRREN 0x00000001
+#define ASCWHBSTATE_SETREN 0x00000002
+#define ASCWHBSTATE_CLRPE 0x00000004
+#define ASCWHBSTATE_CLRFE 0x00000008
+#define ASCWHBSTATE_CLRRUE 0x00000010
+#define ASCWHBSTATE_CLRROE 0x00000020
+#define ASCWHBSTATE_CLRTOE 0x00000040
+#define ASCWHBSTATE_CLRBE 0x00000080
+#define ASCWHBSTATE_SETPE 0x00000100
+#define ASCWHBSTATE_SETFE 0x00000200
+#define ASCWHBSTATE_SETRUE 0x00000400
+#define ASCWHBSTATE_SETROE 0x00000800
+#define ASCWHBSTATE_SETTOE 0x00001000
+#define ASCWHBSTATE_SETBE 0x00002000
+
+/* ABCON register's bits and bitfields */
+#define ASCABCON_ABEN 0x0001
+#define ASCABCON_AUREN 0x0002
+#define ASCABCON_ABSTEN 0x0004
+#define ASCABCON_ABDETEN 0x0008
+#define ASCABCON_FCDETEN 0x0010
+
+/* FDV register mask, offset and bitfields*/
+#define ASCFDV_VALUE_MASK 0x000001FF
+
+/* WHBABCON register's bits and bitfields */
+#define ASCWHBABCON_CLRABEN 0x0001
+#define ASCWHBABCON_SETABEN 0x0002
+
+/* ABSTAT register's bits and bitfields */
+#define ASCABSTAT_FCSDET 0x0001
+#define ASCABSTAT_FCCDET 0x0002
+#define ASCABSTAT_SCSDET 0x0004
+#define ASCABSTAT_SCCDET 0x0008
+#define ASCABSTAT_DETWAIT 0x0010
+
+/* WHBABSTAT register's bits and bitfields */
+#define ASCWHBABSTAT_CLRFCSDET 0x0001
+#define ASCWHBABSTAT_SETFCSDET 0x0002
+#define ASCWHBABSTAT_CLRFCCDET 0x0004
+#define ASCWHBABSTAT_SETFCCDET 0x0008
+#define ASCWHBABSTAT_CLRSCSDET 0x0010
+#define ASCWHBABSTAT_SETSCSDET 0x0020
+#define ASCWHBABSTAT_CLRSCCDET 0x0040
+#define ASCWHBABSTAT_SETSCCDET 0x0080
+#define ASCWHBABSTAT_CLRDETWAIT 0x0100
+#define ASCWHBABSTAT_SETDETWAIT 0x0200
+
+/* TXFCON register's bits and bitfields */
+#define ASCTXFCON_TXFIFO1 0x00000400
+#define ASCTXFCON_TXFEN 0x0001
+#define ASCTXFCON_TXFFLU 0x0002
+#define ASCTXFCON_TXFITLMASK 0x3F00
+#define ASCTXFCON_TXFITLOFF 8
+
+/* RXFCON register's bits and bitfields */
+#define ASCRXFCON_RXFIFO1 0x00000400
+#define ASCRXFCON_RXFEN 0x0001
+#define ASCRXFCON_RXFFLU 0x0002
+#define ASCRXFCON_RXFITLMASK 0x3F00
+#define ASCRXFCON_RXFITLOFF 8
+
+/* FSTAT register's bits and bitfields */
+#define ASCFSTAT_RXFFLMASK 0x003F
+#define ASCFSTAT_TXFFLMASK 0x3F00
+#define ASCFSTAT_TXFFLOFF 8
+
+typedef struct IfxAsc_s
+{
+ unsigned long asc_clc; /*0x0000*/
+ unsigned long asc_pisel; /*0x0004*/
+ unsigned long asc_id; /*0x0008*/
+ unsigned long asc_rsvd1[1]; /* for mapping */ /*0x000C*/
+ unsigned long asc_con; /*0x0010*/
+ unsigned long asc_state; /*0x0014*/
+ unsigned long asc_whbstate; /*0x0018*/
+ unsigned long asc_rsvd2[1]; /* for mapping */ /*0x001C*/
+ unsigned long asc_tbuf; /*0x0020*/
+ unsigned long asc_rbuf; /*0x0024*/
+ unsigned long asc_rsvd3[2]; /* for mapping */ /*0x0028*/
+ unsigned long asc_abcon; /*0x0030*/
+ unsigned long asc_abstat; /* not used */ /*0x0034*/
+ unsigned long asc_whbabcon; /*0x0038*/
+ unsigned long asc_whbabstat; /* not used */ /*0x003C*/
+ unsigned long asc_rxfcon; /*0x0040*/
+ unsigned long asc_txfcon; /*0x0044*/
+ unsigned long asc_fstat; /*0x0048*/
+ unsigned long asc_rsvd4[1]; /* for mapping */ /*0x004C*/
+ unsigned long asc_bg; /*0x0050*/
+ unsigned long asc_bg_timer; /*0x0054*/
+ unsigned long asc_fdv; /*0x0058*/
+ unsigned long asc_pmw; /*0x005C*/
+ unsigned long asc_modcon; /*0x0060*/
+ unsigned long asc_modstat; /*0x0064*/
+ unsigned long asc_rsvd5[2]; /* for mapping */ /*0x0068*/
+ unsigned long asc_sfcc; /*0x0070*/
+ unsigned long asc_rsvd6[3]; /* for mapping */ /*0x0074*/
+ unsigned long asc_eomcon; /*0x0080*/
+ unsigned long asc_rsvd7[26]; /* for mapping */ /*0x0084*/
+ unsigned long asc_dmacon; /*0x00EC*/
+ unsigned long asc_rsvd8[1]; /* for mapping */ /*0x00F0*/
+ unsigned long asc_irnen; /*0x00F4*/
+ unsigned long asc_irnicr; /*0x00F8*/
+ unsigned long asc_irncr; /*0x00FC*/
+} IfxAsc_t;
+
+
+/* Register access macros */
+#define asc_readl(reg) \
+ readl(&pAsc->reg)
+#define asc_writel(reg,value) \
+ writel((value), &pAsc->reg)
+
+
+#endif /* __ASC_H */
diff --git a/package/uboot-lantiq/files/include/asm-mips/ar9.h b/package/uboot-lantiq/files/include/asm-mips/ar9.h
new file mode 100644
index 000000000..cfafe4490
--- /dev/null
+++ b/package/uboot-lantiq/files/include/asm-mips/ar9.h
@@ -0,0 +1,424 @@
+/*
+ * (C) Copyright 2010
+ * Ralph Hempel
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+/***********************************************************************/
+/* Module : PMU register address and bits */
+/***********************************************************************/
+#define AR9_PMU (0xBF102000)
+/* PMU Power down Control Register */
+#define AR9_PMU_PWDCR ((volatile u32*)(AR9_PMU + 0x001C))
+/* PMU Status Register */
+#define AR9_PMU_SR ((volatile u32*)(AR9_PMU + 0x0020))
+/** DMA block */
+#define AR9_PMU_DMA (1<<5)
+#define AR9_PMU_SDIO (1<<16)
+#define AR9_PMU_USB0 (1<<6)
+#define AR9_PMU_USB0_P (1<<0)
+#define AR9_PMU_SWITCH (1<<28)
+
+
+/***********************************************************************/
+/* Module : RCU register address and bits */
+/***********************************************************************/
+#define AR9_RCU_BASE_ADDR (0xBF203000)
+#define AR9_RCU_RST_REQ ((volatile u32*)(AR9_RCU_BASE_ADDR + 0x0010))
+#define AR9_RCU_RST_STAT ((volatile u32*)(AR9_RCU_BASE_ADDR + 0x0014))
+#define AR9_RST_ALL (1 << 30)
+
+/*** Reset Request Register Bits ***/
+#define AR9_RCU_RST_REQ_SRST (1 << 30)
+#define AR9_RCU_RST_REQ_ARC_JTAG (1 << 20)
+#define AR9_RCU_RST_REQ_PCI (1 << 13)
+#define AR9_RCU_RST_REQ_AFE (1 << 11)
+#define AR9_RCU_RST_REQ_SDIO (1 << 19)
+#define AR9_RCU_RST_REQ_DMA (1 << 9)
+#define AR9_RCU_RST_REQ_PPE (1 << 8)
+#define AR9_RCU_RST_REQ_DFE (1 << 7)
+
+/***********************************************************************/
+/* Module : GPIO register address and bits */
+/***********************************************************************/
+#define AR9_GPIO (0xBE100B00)
+/***Port 0 Data Output Register (0010H)***/
+#define AR9_GPIO_P0_OUT ((volatile u32 *)(AR9_GPIO+ 0x0010))
+/***Port 1 Data Output Register (0040H)***/
+#define AR9_GPIO_P1_OUT ((volatile u32 *)(AR9_GPIO+ 0x0040))
+/***Port 2 Data Output Register (0070H)***/
+#define AR9_GPIO_P2_OUT ((volatile u32 *)(AR9_GPIO+ 0x0070))
+/***Port 3 Data Output Register (00A0H)***/
+#define AR9_GPIO_P3_OUT ((volatile u32 *)(AR9_GPIO+ 0x00A0))
+/***Port 0 Data Input Register (0014H)***/
+#define AR9_GPIO_P0_IN ((volatile u32 *)(AR9_GPIO+ 0x0014))
+/***Port 1 Data Input Register (0044H)***/
+#define AR9_GPIO_P1_IN ((volatile u32 *)(AR9_GPIO+ 0x0044))
+/***Port 2 Data Input Register (0074H)***/
+#define AR9_GPIO_P2_IN ((volatile u32 *)(AR9_GPIO+ 0x0074))
+/***Port 3 Data Input Register (00A4H)***/
+#define AR9_GPIO_P3_IN ((volatile u32 *)(AR9_GPIO+ 0x00A4))
+/***Port 0 Direction Register (0018H)***/
+#define AR9_GPIO_P0_DIR ((volatile u32 *)(AR9_GPIO+ 0x0018))
+/***Port 1 Direction Register (0048H)***/
+#define AR9_GPIO_P1_DIR ((volatile u32 *)(AR9_GPIO+ 0x0048))
+/***Port 2 Direction Register (0078H)***/
+#define AR9_GPIO_P2_DIR ((volatile u32 *)(AR9_GPIO+ 0x0078))
+/***Port 3 Direction Register (0048H)***/
+#define AR9_GPIO_P3_DIR ((volatile u32 *)(AR9_GPIO+ 0x00A8))
+/***Port 0 Alternate Function Select Register 0 (001C H) ***/
+#define AR9_GPIO_P0_ALTSEL0 ((volatile u32 *)(AR9_GPIO+ 0x001C))
+/***Port 1 Alternate Function Select Register 0 (004C H) ***/
+#define AR9_GPIO_P1_ALTSEL0 ((volatile u32 *)(AR9_GPIO+ 0x004C))
+/***Port 2 Alternate Function Select Register 0 (007C H) ***/
+#define AR9_GPIO_P2_ALTSEL0 ((volatile u32 *)(AR9_GPIO+ 0x007C))
+/***Port 3 Alternate Function Select Register 0 (00AC H) ***/
+#define AR9_GPIO_P3_ALTSEL0 ((volatile u32 *)(AR9_GPIO+ 0x00AC))
+/***Port 0 Alternate Function Select Register 1 (0020 H) ***/
+#define AR9_GPIO_P0_ALTSEL1 ((volatile u32 *)(AR9_GPIO+ 0x0020))
+/***Port 1 Alternate Function Select Register 0 (0050 H) ***/
+#define AR9_GPIO_P1_ALTSEL1 ((volatile u32 *)(AR9_GPIO+ 0x0050))
+/***Port 2 Alternate Function Select Register 0 (0080 H) ***/
+#define AR9_GPIO_P2_ALTSEL1 ((volatile u32 *)(AR9_GPIO+ 0x0080))
+/***Port 3 Alternate Function Select Register 0 (0064 H) ***/
+#define AR9_GPIO_P3_ALTSEL1 ((volatile u32 *)(AR9_GPIO+ 0x0064))
+/***Port 0 Open Drain Control Register (0024H)***/
+#define AR9_GPIO_P0_OD ((volatile u32 *)(AR9_GPIO+ 0x0024))
+/***Port 1 Open Drain Control Register (0054H)***/
+#define AR9_GPIO_P1_OD ((volatile u32 *)(AR9_GPIO+ 0x0054))
+/***Port 2 Open Drain Control Register (0084H)***/
+#define AR9_GPIO_P2_OD ((volatile u32 *)(AR9_GPIO+ 0x0084))
+/***Port 3 Open Drain Control Register (0034H)***/
+#define AR9_GPIO_P3_OD ((volatile u32 *)(AR9_GPIO+ 0x0034))
+/***Port 0 Input Schmitt-Trigger Off Register (0028 H) ***/
+#define AR9_GPIO_P0_STOFF ((volatile u32 *)(AR9_GPIO+ 0x0028))
+/***Port 1 Input Schmitt-Trigger Off Register (0058 H) ***/
+#define AR9_GPIO_P1_STOFF ((volatile u32 *)(AR9_GPIO+ 0x0058))
+/***Port 2 Input Schmitt-Trigger Off Register (0088 H) ***/
+#define AR9_GPIO_P2_STOFF ((volatile u32 *)(AR9_GPIO+ 0x0088))
+/***Port 3 Input Schmitt-Trigger Off Register (0094 H) ***/
+//#define AR9_GPIO_P3_STOFF ((volatile u32 *)(AR9_GPIO+ 0x0094))
+/***Port 0 Pull Up/Pull Down Select Register (002C H)***/
+#define AR9_GPIO_P0_PUDSEL ((volatile u32 *)(AR9_GPIO+ 0x002C))
+/***Port 1 Pull Up/Pull Down Select Register (005C H)***/
+#define AR9_GPIO_P1_PUDSEL ((volatile u32 *)(AR9_GPIO+ 0x005C))
+/***Port 2 Pull Up/Pull Down Select Register (008C H)***/
+#define AR9_GPIO_P2_PUDSEL ((volatile u32 *)(AR9_GPIO+ 0x008C))
+/***Port 3 Pull Up/Pull Down Select Register (0038 H)***/
+#define AR9_GPIO_P3_PUDSEL ((volatile u32 *)(AR9_GPIO+ 0x0038))
+/***Port 0 Pull Up Device Enable Register (0030 H)***/
+#define AR9_GPIO_P0_PUDEN ((volatile u32 *)(AR9_GPIO+ 0x0030))
+/***Port 1 Pull Up Device Enable Register (0060 H)***/
+#define AR9_GPIO_P1_PUDEN ((volatile u32 *)(AR9_GPIO+ 0x0060))
+/***Port 2 Pull Up Device Enable Register (0090 H)***/
+#define AR9_GPIO_P2_PUDEN ((volatile u32 *)(AR9_GPIO+ 0x0090))
+/***Port 3 Pull Up Device Enable Register (003c H)***/
+#define AR9_GPIO_P3_PUDEN ((volatile u32 *)(AR9_GPIO+ 0x003C))
+
+/***********************************************************************/
+/* Module : CGU register address and bits */
+/***********************************************************************/
+#define AR9_CGU (0xBF103000)
+/***CGU Clock PLL0 ***/
+#define AR9_CGU_PLL0_CFG ((volatile u32*)(AR9_CGU+ 0x0004))
+/***CGU Clock PLL1 ***/
+#define AR9_CGU_PLL1_CFG ((volatile u32*)(AR9_CGU+ 0x0008))
+/***CGU Clock SYS Mux Register***/
+#define AR9_CGU_SYS ((volatile u32*)(AR9_CGU+ 0x0010))
+/***CGU Interface Clock Control Register***/
+#define AR9_CGU_IFCCR ((volatile u32*)(AR9_CGU+ 0x0018))
+/***CGU PCI Clock Control Register**/
+#define AR9_CGU_PCICR ((volatile u32*)(AR9_CGU+ 0x0034))
+#define CLOCK_60M 60000000
+#define CLOCK_83M 83333333
+#define CLOCK_111M 111111111
+#define CLOCK_133M 133333333
+#define CLOCK_166M 166666667
+#define CLOCK_196M 196666667
+#define CLOCK_333M 333333333
+#define CLOCK_366M 366666667
+#define CLOCK_500M 500000000
+
+/***********************************************************************/
+/* Module : MPS register address and bits */
+/***********************************************************************/
+#define AR9_MPS (KSEG1+0x1F107000)
+#define AR9_MPS_CHIPID ((volatile u32*)(AR9_MPS + 0x0344))
+#define AR9_MPS_CHIPID_VERSION_GET(value) (((value) >> 28) & ((1 << 4) - 1))
+#define AR9_MPS_CHIPID_PARTNUM_GET(value) (((value) >> 12) & ((1 << 16) - 1))
+#define AR9_MPS_CHIPID_MANID_GET(value) (((value) >> 1) & ((1 << 10) - 1))
+
+/***********************************************************************/
+/* Module : EBU register address and bits */
+/***********************************************************************/
+#define AR9_EBU (0xBE105300)
+
+#define AR9_EBU_CLC ((volatile u32*)(AR9_EBU+ 0x0000))
+#define AR9_EBU_CLC_DISS (1 << 1)
+#define AR9_EBU_CLC_DISR (1 << 0)
+
+#define AR9_EBU_ID ((volatile u32*)(AR9_EBU+ 0x0008))
+
+/***EBU Global Control Register***/
+#define AR9_EBU_CON ((volatile u32*)(AR9_EBU+ 0x0010))
+#define AR9_EBU_CON_DTACS (value) (((( 1 << 3) - 1) & (value)) << 20)
+#define AR9_EBU_CON_DTARW (value) (((( 1 << 3) - 1) & (value)) << 16)
+#define AR9_EBU_CON_TOUTC (value) (((( 1 << 8) - 1) & (value)) << 8)
+#define AR9_EBU_CON_ARBMODE (value) (((( 1 << 2) - 1) & (value)) << 6)
+#define AR9_EBU_CON_ARBSYNC (1 << 5)
+//#define AR9_EBU_CON_1 (1 << 3)
+
+/***EBU Address Select Register 0***/
+#define AR9_EBU_ADDSEL0 ((volatile u32*)(AR9_EBU + 0x0020))
+/***EBU Address Select Register 1***/
+#define AR9_EBU_ADDSEL1 ((volatile u32*)(AR9_EBU + 0x0024))
+/***EBU Address Select Register 2***/
+#define AR9_EBU_ADDSEL2 ((volatile u32*)(AR9_EBU + 0x0028))
+/***EBU Address Select Register 3***/
+#define AR9_EBU_ADDSEL3 ((volatile u32*)(AR9_EBU + 0x002C))
+#define AR9_EBU_ADDSEL_BASE (value) (((( 1 << 20) - 1) & (value)) << 12)
+#define AR9_EBU_ADDSEL_MASK (value) (((( 1 << 4) - 1) & (value)) << 4)
+#define AR9_EBU_ADDSEL_MIRRORE (1 << 1)
+#define AR9_EBU_ADDSEL_REGEN (1 << 0)
+
+/***EBU Bus Configuration Register 0***/
+#define AR9_EBU_BUSCON0 ((volatile u32*)(AR9_EBU+ 0x0060))
+#define AR9_EBU_BUSCON0_WRDIS (1 << 31)
+#define AR9_EBU_BUSCON0_ADSWP (value) (1 << 30)
+#define AR9_EBU_BUSCON0_PG_EN (value) (1 << 29)
+#define AR9_EBU_BUSCON0_AGEN (value) (((( 1 << 3) - 1) & (value)) << 24)
+#define AR9_EBU_BUSCON0_SETUP (1 << 22)
+#define AR9_EBU_BUSCON0_WAIT (value) (((( 1 << 2) - 1) & (value)) << 20)
+#define AR9_EBU_BUSCON0_WAITINV (1 << 19)
+#define AR9_EBU_BUSCON0_VN_EN (1 << 18)
+#define AR9_EBU_BUSCON0_PORTW (value) (((( 1 << 2) - 1) & (value)) << 16)
+#define AR9_EBU_BUSCON0_ALEC (value) (((( 1 << 2) - 1) & (value)) << 14)
+#define AR9_EBU_BUSCON0_BCGEN (value) (((( 1 << 2) - 1) & (value)) << 12)
+#define AR9_EBU_BUSCON0_WAITWDC (value) (((( 1 << 4) - 1) & (value)) << 8)
+#define AR9_EBU_BUSCON0_WAITRRC (value) (((( 1 << 2) - 1) & (value)) << 6)
+#define AR9_EBU_BUSCON0_HOLDC (value) (((( 1 << 2) - 1) & (value)) << 4)
+#define AR9_EBU_BUSCON0_RECOVC (value) (((( 1 << 2) - 1) & (value)) << 2)
+#define AR9_EBU_BUSCON0_CMULT (value) (((( 1 << 2) - 1) & (value)) << 0)
+
+/***EBU Bus Configuration Register 1***/
+#define AR9_EBU_BUSCON1 ((volatile u32*)(AR9_EBU+ 0x0064))
+#define AR9_EBU_BUSCON1_WRDIS (1 << 31)
+#define AR9_EBU_BUSCON1_ALEC (value) (((( 1 << 2) - 1) & (value)) << 29)
+#define AR9_EBU_BUSCON1_BCGEN (value) (((( 1 << 2) - 1) & (value)) << 27)
+#define AR9_EBU_BUSCON1_AGEN (value) (((( 1 << 2) - 1) & (value)) << 24)
+#define AR9_EBU_BUSCON1_CMULTR (value) (((( 1 << 2) - 1) & (value)) << 22)
+#define AR9_EBU_BUSCON1_WAIT (value) (((( 1 << 2) - 1) & (value)) << 20)
+#define AR9_EBU_BUSCON1_WAITINV (1 << 19)
+#define AR9_EBU_BUSCON1_SETUP (1 << 18)
+#define AR9_EBU_BUSCON1_PORTW (value) (((( 1 << 2) - 1) & (value)) << 16)
+#define AR9_EBU_BUSCON1_WAITRDC (value) (((( 1 << 7) - 1) & (value)) << 9)
+#define AR9_EBU_BUSCON1_WAITWRC (value) (((( 1 << 3) - 1) & (value)) << 6)
+#define AR9_EBU_BUSCON1_HOLDC (value) (((( 1 << 2) - 1) & (value)) << 4)
+#define AR9_EBU_BUSCON1_RECOVC (value) (((( 1 << 2) - 1) & (value)) << 2)
+#define AR9_EBU_BUSCON1_CMULT (value) (((( 1 << 2) - 1) & (value)) << 0)
+
+/***EBU Bus Configuration Register 2***/
+#define AR9_EBU_BUSCON2 ((volatile u32*)(AR9_EBU+ 0x0068))
+#define AR9_EBU_BUSCON2_WRDIS (1 << 31)
+#define AR9_EBU_BUSCON2_ALEC (value) (((( 1 << 2) - 1) & (value)) << 29)
+#define AR9_EBU_BUSCON2_BCGEN (value) (((( 1 << 2) - 1) & (value)) << 27)
+#define AR9_EBU_BUSCON2_AGEN (value) (((( 1 << 2) - 1) & (value)) << 24)
+#define AR9_EBU_BUSCON2_CMULTR (value) (((( 1 << 2) - 1) & (value)) << 22)
+#define AR9_EBU_BUSCON2_WAIT (value) (((( 1 << 2) - 1) & (value)) << 20)
+#define AR9_EBU_BUSCON2_WAITINV (1 << 19)
+#define AR9_EBU_BUSCON2_SETUP (1 << 18)
+#define AR9_EBU_BUSCON2_PORTW (value) (((( 1 << 2) - 1) & (value)) << 16)
+#define AR9_EBU_BUSCON2_WAITRDC (value) (((( 1 << 7) - 1) & (value)) << 9)
+#define AR9_EBU_BUSCON2_WAITWRC (value) (((( 1 << 3) - 1) & (value)) << 6)
+#define AR9_EBU_BUSCON2_HOLDC (value) (((( 1 << 2) - 1) & (value)) << 4)
+#define AR9_EBU_BUSCON2_RECOVC (value) (((( 1 << 2) - 1) & (value)) << 2)
+#define AR9_EBU_BUSCON2_CMULT (value) (((( 1 << 2) - 1) & (value)) << 0)
+
+/***EBU Bus Configuration Register 2***/
+#define AR9_EBU_BUSCON3 ((volatile u32*)(AR9_EBU+ 0x006C))
+#define AR9_EBU_BUSCON3_WRDIS (1 << 31)
+#define AR9_EBU_BUSCON3_ADSWP (value) (1 << 30)
+#define AR9_EBU_BUSCON3_PG_EN (value) (1 << 29)
+#define AR9_EBU_BUSCON3_AGEN (value) (((( 1 << 3) - 1) & (value)) << 24)
+#define AR9_EBU_BUSCON3_SETUP (1 << 22)
+#define AR9_EBU_BUSCON3_WAIT (value) (((( 1 << 2) - 1) & (value)) << 20)
+#define AR9_EBU_BUSCON3_WAITINV (1 << 19)
+#define AR9_EBU_BUSCON3_VN_EN (1 << 18)
+#define AR9_EBU_BUSCON3_PORTW (value) (((( 1 << 2) - 1) & (value)) << 16)
+#define AR9_EBU_BUSCON3_ALEC (value) (((( 1 << 2) - 1) & (value)) << 14)
+#define AR9_EBU_BUSCON3_BCGEN (value) (((( 1 << 2) - 1) & (value)) << 12)
+#define AR9_EBU_BUSCON3_WAITWDC (value) (((( 1 << 4) - 1) & (value)) << 8)
+#define AR9_EBU_BUSCON3_WAITRRC (value) (((( 1 << 2) - 1) & (value)) << 6)
+#define AR9_EBU_BUSCON3_HOLDC (value) (((( 1 << 2) - 1) & (value)) << 4)
+#define AR9_EBU_BUSCON3_RECOVC (value) (((( 1 << 2) - 1) & (value)) << 2)
+#define AR9_EBU_BUSCON3_CMULT (value) (((( 1 << 2) - 1) & (value)) << 0)
+
+/***********************************************************************/
+/* Module : SDRAM register address and bits */
+/***********************************************************************/
+#define AR9_SDRAM (0xBF800000)
+
+/***********************************************************************/
+/* Module : ASC0 register address and bits */
+/***********************************************************************/
+#define AR9_ASC0 (KSEG1 | 0x1E100400)
+#define AR9_ASC0_TBUF ((volatile u32*)(AR9_ASC0 + 0x0020))
+#define AR9_ASC0_RBUF ((volatile u32*)(AR9_ASC0 + 0x0024))
+#define AR9_ASC0_FSTAT ((volatile u32*)(AR9_ASC0 + 0x0048))
+
+/***********************************************************************/
+/* Module : ASC1 register address and bits */
+/***********************************************************************/
+#define AR9_ASC1 (KSEG1 | 0x1E100C00)
+#define AR9_ASC1_TBUF ((volatile u32*)(AR9_ASC1 + 0x0020))
+#define AR9_ASC1_RBUF ((volatile u32*)(AR9_ASC1 + 0x0024))
+#define AR9_ASC1_FSTAT ((volatile u32*)(AR9_ASC1 + 0x0048))
+
+/***********************************************************************/
+/* Module : DMA register address and bits */
+/***********************************************************************/
+#define AR9_DMA_OFFSET (0xBE104100)
+/***********************************************************************/
+#define AR9_DMA_CLC ((volatile u32*)(AR9_DMA_OFFSET + 0x0000))
+#define AR9_DMA_ID ((volatile u32*)(AR9_DMA_OFFSET + 0x0008))
+#define AR9_DMA_CTRL (volatile u32*)(AR9_DMA_BASE + 0x10)
+
+/** DMA Port Select Register */
+#define AR9_DMA_PS ((volatile u32*)(AR9_DMA_OFFSET + 0x0040))
+/** DMA Port Control Register */
+#define AR9_DMA_PCTRL ((volatile u32*)(AR9_DMA_OFFSET + 0x0044))
+#define AR9_DMA_IRNEN ((volatile u32*)(AR9_DMA_OFFSET + 0x00F4))
+#define AR9_DMA_IRNCR ((volatile u32*)(AR9_DMA_OFFSET + 0x00F8))
+#define AR9_DMA_IRNICR ((volatile u32*)(AR9_DMA_OFFSET + 0x00FC))
+
+#define AR9_DMA_CS ((volatile u32*)(AR9_DMA_OFFSET + 0x0018))
+#define AR9_DMA_CCTRL ((volatile u32*)(AR9_DMA_OFFSET + 0x001C))
+#define AR9_DMA_CDBA ((volatile u32*)(AR9_DMA_OFFSET + 0x0020))
+#define AR9_DMA_CIE ((volatile u32*)(AR9_DMA_OFFSET + 0x002C))
+#define AR9_DMA_CIS ((volatile u32*)(AR9_DMA_OFFSET + 0x0028))
+#define AR9_DMA_CDLEN ((volatile u32*)(AR9_DMA_OFFSET + 0x0024))
+#define AR9_DMA_CPOLL ((volatile u32*)(AR9_DMA_OFFSET + 0x0014))
+
+/***********************************************************************/
+/* Module : GPORT switch register */
+/***********************************************************************/
+#define AR9_SW (0xBE108000)
+#define AR9_SW_PS (AR9_SW + 0x000)
+#define AR9_SW_P0_CTL (AR9_SW + 0x004)
+#define AR9_SW_P1_CTL (AR9_SW + 0x008)
+#define AR9_SW_P2_CTL (AR9_SW + 0x00C)
+#define AR9_SW_P0_VLAN (AR9_SW + 0x010)
+#define AR9_SW_P1_VLAN (AR9_SW + 0x014)
+#define AR9_SW_P2_VLAN (AR9_SW + 0x018)
+#define AR9_SW_P0_INCTL (AR9_SW + 0x020)
+#define AR9_SW_P1_INCTL (AR9_SW + 0x024)
+#define AR9_SW_P2_INCTL (AR9_SW + 0x028)
+#define AR9_SW_DF_PORTMAP (AR9_SW + 0x02C)
+#define AR9_SW_P0_ECS_Q32 (AR9_SW + 0x030)
+#define AR9_SW_P0_ECS_Q10 (AR9_SW + 0x034)
+#define AR9_SW_P0_ECW_Q32 (AR9_SW + 0x038)
+#define AR9_SW_P0_ECW_Q10 (AR9_SW + 0x03C)
+#define AR9_SW_P1_ECS_Q32 (AR9_SW + 0x040)
+#define AR9_SW_P1_ECS_Q10 (AR9_SW + 0x044)
+#define AR9_SW_P1_ECW_Q32 (AR9_SW + 0x048)
+#define AR9_SW_P1_ECW_Q10 (AR9_SW + 0x04C)
+#define AR9_SW_P2_ECS_Q32 (AR9_SW + 0x050)
+#define AR9_SW_P2_ECS_Q10 (AR9_SW + 0x054)
+#define AR9_SW_P2_ECW_Q32 (AR9_SW + 0x058)
+#define AR9_SW_P2_ECW_Q10 (AR9_SW + 0x05C)
+#define AR9_SW_INT_ENA (AR9_SW + 0x060)
+#define AR9_SW_INT_ST (AR9_SW + 0x064)
+#define AR9_SW_GCTL0 (AR9_SW + 0x068)
+#define AR9_SW_GCTL1 (AR9_SW + 0x06C)
+#define AR9_SW_ARP (AR9_SW + 0x070)
+#define AR9_SW_STRM_CTL (AR9_SW + 0x074)
+#define AR9_SW_RGMII_CTL (AR9_SW + 0x078)
+#define AR9_SW_1P_PRT (AR9_SW + 0x07C)
+#define AR9_SW_GBKT_SZBS (AR9_SW + 0x080)
+#define AR9_SW_GBKT_SZEBS (AR9_SW + 0x084)
+#define AR9_SW_BF_TH (AR9_SW + 0x088)
+#define AR9_SW_PMAC_HD_CTL (AR9_SW + 0x08C)
+#define AR9_SW_PMAC_SA1 (AR9_SW + 0x090)
+#define AR9_SW_PMAC_SA2 (AR9_SW + 0x094)
+#define AR9_SW_PMAC_DA1 (AR9_SW + 0x098)
+#define AR9_SW_PMAC_DA2 (AR9_SW + 0x09C)
+#define AR9_SW_PMAC_VLAN (AR9_SW + 0x0A0)
+#define AR9_SW_PMAC_TX_IPG (AR9_SW + 0x0A4)
+#define AR9_SW_PMAC_RX_IPG (AR9_SW + 0x0A8)
+#define AR9_SW_ADR_TB_CTL0 (AR9_SW + 0x0AC)
+#define AR9_SW_ADR_TB_CTL1 (AR9_SW + 0x0B0)
+#define AR9_SW_ADR_TB_CTL2 (AR9_SW + 0x0B4)
+#define AR9_SW_ADR_TB_ST0 (AR9_SW + 0x0B8)
+#define AR9_SW_ADR_TB_ST1 (AR9_SW + 0x0BC)
+#define AR9_SW_ADR_TB_ST2 (AR9_SW + 0x0C0)
+#define AR9_SW_RMON_CTL (AR9_SW + 0x0C4)
+#define AR9_SW_RMON_ST (AR9_SW + 0x0C8)
+#define AR9_SW_MDIO_CTL (AR9_SW + 0x0CC)
+#define AR9_SW_MDIO_DATA (AR9_SW + 0x0D0)
+#define AR9_SW_TP_FLT_ACT (AR9_SW + 0x0D4)
+#define AR9_SW_PRTCL_FLT_ACT (AR9_SW + 0x0D8)
+#define AR9_SW_VLAN_FLT0 (AR9_SW + 0x100)
+#define AR9_SW_VLAN_FLT1 (AR9_SW + 0x104)
+#define AR9_SW_VLAN_FLT2 (AR9_SW + 0x108)
+#define AR9_SW_VLAN_FLT3 (AR9_SW + 0x10C)
+#define AR9_SW_VLAN_FLT4 (AR9_SW + 0x110)
+#define AR9_SW_VLAN_FLT5 (AR9_SW + 0x114)
+#define AR9_SW_VLAN_FLT6 (AR9_SW + 0x118)
+#define AR9_SW_VLAN_FLT7 (AR9_SW + 0x11C)
+#define AR9_SW_VLAN_FLT8 (AR9_SW + 0x120)
+#define AR9_SW_VLAN_FLT9 (AR9_SW + 0x124)
+#define AR9_SW_VLAN_FLT10 (AR9_SW + 0x128)
+#define AR9_SW_VLAN_FLT11 (AR9_SW + 0x12C)
+#define AR9_SW_VLAN_FLT12 (AR9_SW + 0x130)
+#define AR9_SW_VLAN_FLT13 (AR9_SW + 0x134)
+#define AR9_SW_VLAN_FLT14 (AR9_SW + 0x138)
+#define AR9_SW_VLAN_FLT15 (AR9_SW + 0x13C)
+#define AR9_SW_TP_FLT10 (AR9_SW + 0x140)
+#define AR9_SW_TP_FLT32 (AR9_SW + 0x144)
+#define AR9_SW_TP_FLT54 (AR9_SW + 0x148)
+#define AR9_SW_TP_FLT76 (AR9_SW + 0x14C)
+#define AR9_SW_DFSRV_MAP0 (AR9_SW + 0x150)
+#define AR9_SW_DFSRV_MAP1 (AR9_SW + 0x154)
+#define AR9_SW_DFSRV_MAP2 (AR9_SW + 0x158)
+#define AR9_SW_DFSRV_MAP3 (AR9_SW + 0x15C)
+#define AR9_SW_TCP_PF0 (AR9_SW + 0x160)
+#define AR9_SW_TCP_PF1 (AR9_SW + 0x164)
+#define AR9_SW_TCP_PF2 (AR9_SW + 0x168)
+#define AR9_SW_TCP_PF3 (AR9_SW + 0x16C)
+#define AR9_SW_TCP_PF4 (AR9_SW + 0x170)
+#define AR9_SW_TCP_PF5 (AR9_SW + 0x174)
+#define AR9_SW_TCP_PF6 (AR9_SW + 0x178)
+#define AR9_SW_TCP_PF7 (AR9_SW + 0x17C)
+#define AR9_SW_RA_03_00 (AR9_SW + 0x180)
+#define AR9_SW_RA_07_04 (AR9_SW + 0x184)
+#define AR9_SW_RA_0B_08 (AR9_SW + 0x188)
+#define AR9_SW_RA_0F_0C (AR9_SW + 0x18C)
+#define AR9_SW_RA_13_10 (AR9_SW + 0x190)
+#define AR9_SW_RA_17_14 (AR9_SW + 0x194)
+#define AR9_SW_RA_1B_18 (AR9_SW + 0x198)
+#define AR9_SW_RA_1F_1C (AR9_SW + 0x19C)
+#define AR9_SW_RA_23_20 (AR9_SW + 0x1A0)
+#define AR9_SW_RA_27_24 (AR9_SW + 0x1A4)
+#define AR9_SW_RA_2B_28 (AR9_SW + 0x1A8)
+#define AR9_SW_RA_2F_2C (AR9_SW + 0x1AC)
+#define AR9_SW_F0 (AR9_SW + 0x1B0)
+#define AR9_SW_F1 (AR9_SW + 0x1B4)
+
+#define REG32(addr) *((volatile u32 *)(addr))
diff --git a/package/uboot-lantiq/files/include/asm-mips/danube.h b/package/uboot-lantiq/files/include/asm-mips/danube.h
new file mode 100644
index 000000000..7caf8f7aa
--- /dev/null
+++ b/package/uboot-lantiq/files/include/asm-mips/danube.h
@@ -0,0 +1,2015 @@
+#ifndef DANUBE_H
+#define DANUBE_H
+/******************************************************************************
+ Copyright (c) 2002, Infineon Technologies. All rights reserved.
+
+ No Warranty
+ Because the program is licensed free of charge, there is no warranty for
+ the program, to the extent permitted by applicable law. Except when
+ otherwise stated in writing the copyright holders and/or other parties
+ provide the program "as is" without warranty of any kind, either
+ expressed or implied, including, but not limited to, the implied
+ warranties of merchantability and fitness for a particular purpose. The
+ entire risk as to the quality and performance of the program is with
+ you. should the program prove defective, you assume the cost of all
+ necessary servicing, repair or correction.
+
+ In no event unless required by applicable law or agreed to in writing
+ will any copyright holder, or any other party who may modify and/or
+ redistribute the program as permitted above, be liable to you for
+ damages, including any general, special, incidental or consequential
+ damages arising out of the use or inability to use the program
+ (including but not limited to loss of data or data being rendered
+ inaccurate or losses sustained by you or third parties or a failure of
+ the program to operate with any other programs), even if such holder or
+ other party has been advised of the possibility of such damages.
+******************************************************************************/
+
+/***********************************************************************/
+/* Module : MEI register address and bits */
+/***********************************************************************/
+#define MEI_SPACE_ACCESS 0xB0100C00
+#define MEI_DATA_XFR (0x0000 + MEI_SPACE_ACCESS)
+#define MEI_VERSION (0x0200 + MEI_SPACE_ACCESS)
+#define ARC_GP_STAT (0x0204 + MEI_SPACE_ACCESS)
+#define MEI_XFR_ADDR (0x020C + MEI_SPACE_ACCESS)
+#define MEI_TO_ARC_INT (0x021C + MEI_SPACE_ACCESS)
+#define ARC_TO_MEI_INT (0x0220 + MEI_SPACE_ACCESS)
+#define ARC_TO_MEI_INT_MASK (0x0224 + MEI_SPACE_ACCESS)
+#define MEI_DEBUG_WAD (0x0228 + MEI_SPACE_ACCESS)
+#define MEI_DEBUG_RAD (0x022C + MEI_SPACE_ACCESS)
+#define MEI_DEBUG_DATA (0x0230 + MEI_SPACE_ACCESS)
+#define MEI_DEBUG_DEC (0x0234 + MEI_SPACE_ACCESS)
+#define MEI_CONTROL (0x0238 + MEI_SPACE_ACCESS)
+#define AT_CELLRDY_BC0 (0x023C + MEI_SPACE_ACCESS)
+#define AT_CELLRDY_BC1 (0x0240 + MEI_SPACE_ACCESS)
+#define AR_CELLRDY_BC0 (0x0244 + MEI_SPACE_ACCESS)
+#define AR_CELLRDY_BC1 (0x0248 + MEI_SPACE_ACCESS)
+#define AAI_ACCESS (0x024C + MEI_SPACE_ACCESS)
+#define AAITXCB0 (0x0300 + MEI_SPACE_ACCESS)
+#define AAITXCB1 (0x0304 + MEI_SPACE_ACCESS)
+#define AAIRXCB0 (0x0308 + MEI_SPACE_ACCESS)
+#define AAIRXCB1 (0x030C + MEI_SPACE_ACCESS)
+
+
+/***********************************************************************/
+/* Module : WDT register address and bits */
+/***********************************************************************/
+#define DANUBE_BIU_WDT_BASE (0xBf8803F0)
+#define DANUBE_BIU_WDT_CR (0x0000 + DANUBE_BIU_WDT_BASE)
+#define DANUBE_BIU_WDT_SR (0x0008 + DANUBE_BIU_WDT_BASE)
+
+
+/***********************************************************************/
+/* Module : PMU register address and bits */
+/***********************************************************************/
+#define DANUBE_PMU_BASE_ADDR (KSEG1+0x1F102000)
+
+/***PM Control Register***/
+#define DANUBE_PMU_CR ((volatile u32*)(0x001C + DANUBE_PMU_BASE_ADDR))
+#define DANUBE_PMU_PWDCR DANUBE_PMU_CR
+#define DANUBE_PMU_SR ((volatile u32*)(0x0020 + DANUBE_PMU_BASE_ADDR))
+
+#define DANUBE_PMU_DMA_SHIFT 5
+#define DANUBE_PMU_PPE_SHIFT 13
+#define DANUBE_PMU_ETOP_SHIFT 22
+#define DANUBE_PMU_ENET0_SHIFT 24
+#define DANUBE_PMU_ENET1_SHIFT 25
+
+
+#define DANUBE_PMU DANUBE_PMU_BASE_ADDR
+/***PM Global Enable Register***/
+#define DANUBE_PMU_PM_GEN ((volatile u32*)(DANUBE_PMU+ 0x0000))
+#define DANUBE_PMU_PM_GEN_EN16 (1 << 16)
+#define DANUBE_PMU_PM_GEN_EN15 (1 << 15)
+#define DANUBE_PMU_PM_GEN_EN14 (1 << 14)
+#define DANUBE_PMU_PM_GEN_EN13 (1 << 13)
+#define DANUBE_PMU_PM_GEN_EN12 (1 << 12)
+#define DANUBE_PMU_PM_GEN_EN11 (1 << 11)
+#define DANUBE_PMU_PM_GEN_EN10 (1 << 10)
+#define DANUBE_PMU_PM_GEN_EN9 (1 << 9)
+#define DANUBE_PMU_PM_GEN_EN8 (1 << 8)
+#define DANUBE_PMU_PM_GEN_EN7 (1 << 7)
+#define DANUBE_PMU_PM_GEN_EN6 (1 << 6)
+#define DANUBE_PMU_PM_GEN_EN5 (1 << 5)
+#define DANUBE_PMU_PM_GEN_EN4 (1 << 4)
+#define DANUBE_PMU_PM_GEN_EN3 (1 << 3)
+#define DANUBE_PMU_PM_GEN_EN2 (1 << 2)
+#define DANUBE_PMU_PM_GEN_EN0 (1 << 0)
+
+/***PM Power Down Enable Register***/
+#define DANUBE_PMU_PM_PDEN ((volatile u32*)(DANUBE_PMU+ 0x0008))
+#define DANUBE_PMU_PM_PDEN_EN16 (1 << 16)
+#define DANUBE_PMU_PM_PDEN_EN15 (1 << 15)
+#define DANUBE_PMU_PM_PDEN_EN14 (1 << 14)
+#define DANUBE_PMU_PM_PDEN_EN13 (1 << 13)
+#define DANUBE_PMU_PM_PDEN_EN12 (1 << 12)
+#define DANUBE_PMU_PM_PDEN_EN11 (1 << 11)
+#define DANUBE_PMU_PM_PDEN_EN10 (1 << 10)
+#define DANUBE_PMU_PM_PDEN_EN9 (1 << 9)
+#define DANUBE_PMU_PM_PDEN_EN8 (1 << 8)
+#define DANUBE_PMU_PM_PDEN_EN7 (1 << 7)
+#define DANUBE_PMU_PM_PDEN_EN5 (1 << 5)
+#define DANUBE_PMU_PM_PDEN_EN4 (1 << 4)
+#define DANUBE_PMU_PM_PDEN_EN3 (1 << 3)
+#define DANUBE_PMU_PM_PDEN_EN2 (1 << 2)
+#define DANUBE_PMU_PM_PDEN_EN0 (1 << 0)
+
+/***PM Wake-Up from Power Down Register***/
+#define DANUBE_PMU_PM_WUP ((volatile u32*)(DANUBE_PMU+ 0x0010))
+#define DANUBE_PMU_PM_WUP_WUP16 (1 << 16)
+#define DANUBE_PMU_PM_WUP_WUP15 (1 << 15)
+#define DANUBE_PMU_PM_WUP_WUP14 (1 << 14)
+#define DANUBE_PMU_PM_WUP_WUP13 (1 << 13)
+#define DANUBE_PMU_PM_WUP_WUP12 (1 << 12)
+#define DANUBE_PMU_PM_WUP_WUP11 (1 << 11)
+#define DANUBE_PMU_PM_WUP_WUP10 (1 << 10)
+#define DANUBE_PMU_PM_WUP_WUP9 (1 << 9)
+#define DANUBE_PMU_PM_WUP_WUP8 (1 << 8)
+#define DANUBE_PMU_PM_PDEN_EN7 (1 << 7)
+#define DANUBE_PMU_PM_PDEN_EN5 (1 << 5)
+#define DANUBE_PMU_PM_PDEN_EN4 (1 << 4)
+#define DANUBE_PMU_PM_PDEN_EN3 (1 << 3)
+#define DANUBE_PMU_PM_PDEN_EN2 (1 << 2)
+#define DANUBE_PMU_PM_PDEN_EN0 (1 << 0)
+
+/***PM Wake-Up from Power Down Register***/
+#define DANUBE_PMU_PM_WUP ((volatile u32*)(DANUBE_PMU+ 0x0010))
+#define DANUBE_PMU_PM_WUP_WUP16 (1 << 16)
+#define DANUBE_PMU_PM_WUP_WUP15 (1 << 15)
+#define DANUBE_PMU_PM_WUP_WUP14 (1 << 14)
+#define DANUBE_PMU_PM_WUP_WUP13 (1 << 13)
+#define DANUBE_PMU_PM_WUP_WUP12 (1 << 12)
+#define DANUBE_PMU_PM_WUP_WUP11 (1 << 11)
+#define DANUBE_PMU_PM_WUP_WUP10 (1 << 10)
+#define DANUBE_PMU_PM_WUP_WUP9 (1 << 9)
+#define DANUBE_PMU_PM_WUP_WUP8 (1 << 8)
+#define DANUBE_PMU_PM_WUP_WUP7 (1 << 7)
+#define DANUBE_PMU_PM_WUP_WUP5 (1 << 5)
+#define DANUBE_PMU_PM_WUP_WUP4 (1 << 4)
+#define DANUBE_PMU_PM_WUP_WUP3 (1 << 3)
+#define DANUBE_PMU_PM_WUP_WUP2 (1 << 2)
+#define DANUBE_PMU_PM_WUP_WUP0 (1 << 0)
+
+/***PM Control Register***/
+#define DANUBE_PMU_PM_CR ((volatile u32*)(DANUBE_PMU+ 0x0014))
+#define DANUBE_PMU_PM_CR_AWEN (1 << 31)
+#define DANUBE_PMU_PM_CR_SWRST (1 << 30)
+#define DANUBE_PMU_PM_CR_SWCR (1 << 2)
+#define DANUBE_PMU_PM_CR_CRD (value) (((( 1 << 2) - 1) & (value)) << 0)
+
+/***********************************************************************/
+/* Module : RCU register address and bits */
+/***********************************************************************/
+#define DANUBE_RCU_BASE_ADDR (0xBF203000)
+
+#define DANUBE_RCU_REQ (0x0010 + DANUBE_RCU_BASE_ADDR)
+#define DANUBE_RCU_RST_REQ ((volatile u32*)(DANUBE_RCU_REQ))
+#define DANUBE_RCU_STAT (0x0014 + DANUBE_RCU_BASE_ADDR)
+#define DANUBE_RCU_RST_SR ( (volatile u32 *)(DANUBE_RCU_STAT))
+#define DANUBE_RCU_PCI_RDY ( (volatile u32 *)(DANUBE_RCU_BASE_ADDR+0x28))
+#define DANUBE_RCU_MON (0x0030 + DANUBE_RCU_BASE_ADDR)
+
+
+/***********************************************************************/
+/* Module : BCU register address and bits */
+/***********************************************************************/
+#define DANUBE_BCU_BASE_ADDR (0xB0100000)
+/***BCU Control Register (0010H)***/
+#define DANUBE_BCU_CON (0x0010 + DANUBE_BCU_BASE_ADDR)
+#define DANUBE_BCU_BCU_CON_SPC (value) (((( 1 << 8) - 1) & (value)) << 24)
+#define DANUBE_BCU_BCU_CON_SPE (1 << 19)
+#define DANUBE_BCU_BCU_CON_PSE (1 << 18)
+#define DANUBE_BCU_BCU_CON_DBG (1 << 16)
+#define DANUBE_BCU_BCU_CON_TOUT (value) (((( 1 << 16) - 1) & (value)) << 0)
+
+
+/***BCU Error Control Capture Register (0020H)***/
+#define DANUBE_BCU_ECON (0x0020 + DANUBE_BCU_BASE_ADDR)
+#define DANUBE_BCU_BCU_ECON_TAG (value) (((( 1 << 4) - 1) & (value)) << 24)
+#define DANUBE_BCU_BCU_ECON_RDN (1 << 23)
+#define DANUBE_BCU_BCU_ECON_WRN (1 << 22)
+#define DANUBE_BCU_BCU_ECON_SVM (1 << 21)
+#define DANUBE_BCU_BCU_ECON_ACK (value) (((( 1 << 2) - 1) & (value)) << 19)
+#define DANUBE_BCU_BCU_ECON_ABT (1 << 18)
+#define DANUBE_BCU_BCU_ECON_RDY (1 << 17)
+#define DANUBE_BCU_BCU_ECON_TOUT (1 << 16)
+#define DANUBE_BCU_BCU_ECON_ERRCNT (value) (((( 1 << 16) - 1) & (value)) << 0)
+#define DANUBE_BCU_BCU_ECON_OPC (value) (((( 1 << 4) - 1) & (value)) << 28)
+
+/***BCU Error Address Capture Register (0024 H)***/
+#define DANUBE_BCU_EADD (0x0024 + DANUBE_BCU_BASE_ADDR)
+
+/***BCU Error Data Capture Register (0028H)***/
+#define DANUBE_BCU_EDAT (0x0028 + DANUBE_BCU_BASE_ADDR)
+
+#define DANUBE_BCU_IRNEN (0x00F4 + DANUBE_BCU_BASE_ADDR)
+#define DANUBE_BCU_IRNICR (0x00F8 + DANUBE_BCU_BASE_ADDR)
+#define DANUBE_BCU_IRNCR (0x00FC + DANUBE_BCU_BASE_ADDR)
+
+
+/***********************************************************************/
+/* Module : MBC register address and bits */
+/***********************************************************************/
+
+#define DANUBE_MBC (0xBF103000)
+/***********************************************************************/
+
+
+/***Mailbox CPU Configuration Register***/
+#define DANUBE_MBC_MBC_CFG ((volatile u32*)(DANUBE_MBC+ 0x0080))
+#define DANUBE_MBC_MBC_CFG_SWAP (value) (((( 1 << 2) - 1) & (value)) << 6)
+#define DANUBE_MBC_MBC_CFG_RES (1 << 5)
+#define DANUBE_MBC_MBC_CFG_FWID (value) (((( 1 << 4) - 1) & (value)) << 1)
+#define DANUBE_MBC_MBC_CFG_SIZE (1 << 0)
+
+/***Mailbox CPU Interrupt Status Register***/
+#define DANUBE_MBC_MBC_ISR ((volatile u32*)(DANUBE_MBC+ 0x0084))
+#define DANUBE_MBC_MBC_ISR_B3DA (1 << 31)
+#define DANUBE_MBC_MBC_ISR_B2DA (1 << 30)
+#define DANUBE_MBC_MBC_ISR_B1E (1 << 29)
+#define DANUBE_MBC_MBC_ISR_B0E (1 << 28)
+#define DANUBE_MBC_MBC_ISR_WDT (1 << 27)
+#define DANUBE_MBC_MBC_ISR_DS260 (value) (((( 1 << 27) - 1) & (value)) << 0)
+
+/***Mailbox CPU Mask Register***/
+#define DANUBE_MBC_MBC_MSK ((volatile u32*)(DANUBE_MBC+ 0x0088))
+#define DANUBE_MBC_MBC_MSK_B3DA (1 << 31)
+#define DANUBE_MBC_MBC_MSK_B2DA (1 << 30)
+#define DANUBE_MBC_MBC_MSK_B1E (1 << 29)
+#define DANUBE_MBC_MBC_MSK_B0E (1 << 28)
+#define DANUBE_MBC_MBC_MSK_WDT (1 << 27)
+#define DANUBE_MBC_MBC_MSK_DS260 (value) (((( 1 << 27) - 1) & (value)) << 0)
+
+/***Mailbox CPU Mask 01 Register***/
+#define DANUBE_MBC_MBC_MSK01 ((volatile u32*)(DANUBE_MBC+ 0x008C))
+#define DANUBE_MBC_MBC_MSK01_B3DA (1 << 31)
+#define DANUBE_MBC_MBC_MSK01_B2DA (1 << 30)
+#define DANUBE_MBC_MBC_MSK01_B1E (1 << 29)
+#define DANUBE_MBC_MBC_MSK01_B0E (1 << 28)
+#define DANUBE_MBC_MBC_MSK01_WDT (1 << 27)
+#define DANUBE_MBC_MBC_MSK01_DS260 (value) (((( 1 << 27) - 1) & (value)) << 0)
+
+/***Mailbox CPU Mask 10 Register***/
+#define DANUBE_MBC_MBC_MSK10 ((volatile u32*)(DANUBE_MBC+ 0x0090))
+#define DANUBE_MBC_MBC_MSK10_B3DA (1 << 31)
+#define DANUBE_MBC_MBC_MSK10_B2DA (1 << 30)
+#define DANUBE_MBC_MBC_MSK10_B1E (1 << 29)
+#define DANUBE_MBC_MBC_MSK10_B0E (1 << 28)
+#define DANUBE_MBC_MBC_MSK10_WDT (1 << 27)
+#define DANUBE_MBC_MBC_MSK10_DS260 (value) (((( 1 << 27) - 1) & (value)) << 0)
+
+/***Mailbox CPU Short Command Register***/
+#define DANUBE_MBC_MBC_CMD ((volatile u32*)(DANUBE_MBC+ 0x0094))
+#define DANUBE_MBC_MBC_CMD_CS270 (value) (((( 1 << 28) - 1) & (value)) << 0)
+
+/***Mailbox CPU Input Data of Buffer 0***/
+#define DANUBE_MBC_MBC_ID0 ((volatile u32*)(DANUBE_MBC+ 0x0000))
+#define DANUBE_MBC_MBC_ID0_INDATA
+
+/***Mailbox CPU Input Data of Buffer 1***/
+#define DANUBE_MBC_MBC_ID1 ((volatile u32*)(DANUBE_MBC+ 0x0020))
+#define DANUBE_MBC_MBC_ID1_INDATA
+
+/***Mailbox CPU Output Data of Buffer 2***/
+#define DANUBE_MBC_MBC_OD2 ((volatile u32*)(DANUBE_MBC+ 0x0040))
+#define DANUBE_MBC_MBC_OD2_OUTDATA
+
+/***Mailbox CPU Output Data of Buffer 3***/
+#define DANUBE_MBC_MBC_OD3 ((volatile u32*)(DANUBE_MBC+ 0x0060))
+#define DANUBE_MBC_MBC_OD3_OUTDATA
+
+/***Mailbox CPU Control Register of Buffer 0***/
+#define DANUBE_MBC_MBC_CR0 ((volatile u32*)(DANUBE_MBC+ 0x0004))
+#define DANUBE_MBC_MBC_CR0_RDYABTFLS (value) (((( 1 << 3) - 1) & (value)) << 0)
+
+/***Mailbox CPU Control Register of Buffer 1***/
+#define DANUBE_MBC_MBC_CR1 ((volatile u32*)(DANUBE_MBC+ 0x0024))
+#define DANUBE_MBC_MBC_CR1_RDYABTFLS (value) (((( 1 << 3) - 1) & (value)) << 0)
+
+/***Mailbox CPU Control Register of Buffer 2***/
+#define DANUBE_MBC_MBC_CR2 ((volatile u32*)(DANUBE_MBC+ 0x0044))
+#define DANUBE_MBC_MBC_CR2_RDYABTFLS (value) (((( 1 << 3) - 1) & (value)) << 0)
+
+/***Mailbox CPU Control Register of Buffer 3***/
+#define DANUBE_MBC_MBC_CR3 ((volatile u32*)(DANUBE_MBC+ 0x0064))
+#define DANUBE_MBC_MBC_CR3_RDYABTFLS (value) (((( 1 << 3) - 1) & (value)) << 0)
+
+/***Mailbox CPU Free Space of Buffer 0***/
+#define DANUBE_MBC_MBC_FS0 ((volatile u32*)(DANUBE_MBC+ 0x0008))
+#define DANUBE_MBC_MBC_FS0_FS
+
+/***Mailbox CPU Free Space of Buffer 1***/
+#define DANUBE_MBC_MBC_FS1 ((volatile u32*)(DANUBE_MBC+ 0x0028))
+#define DANUBE_MBC_MBC_FS1_FS
+
+/***Mailbox CPU Free Space of Buffer 2***/
+#define DANUBE_MBC_MBC_FS2 ((volatile u32*)(DANUBE_MBC+ 0x0048))
+#define DANUBE_MBC_MBC_FS2_FS
+
+/***Mailbox CPU Free Space of Buffer 3***/
+#define DANUBE_MBC_MBC_FS3 ((volatile u32*)(DANUBE_MBC+ 0x0068))
+#define DANUBE_MBC_MBC_FS3_FS
+
+/***Mailbox CPU Data Available in Buffer 0***/
+#define DANUBE_MBC_MBC_DA0 ((volatile u32*)(DANUBE_MBC+ 0x000C))
+#define DANUBE_MBC_MBC_DA0_DA
+
+/***Mailbox CPU Data Available in Buffer 1***/
+#define DANUBE_MBC_MBC_DA1 ((volatile u32*)(DANUBE_MBC+ 0x002C))
+#define DANUBE_MBC_MBC_DA1_DA
+
+/***Mailbox CPU Data Available in Buffer 2***/
+#define DANUBE_MBC_MBC_DA2 ((volatile u32*)(DANUBE_MBC+ 0x004C))
+#define DANUBE_MBC_MBC_DA2_DA
+
+/***Mailbox CPU Data Available in Buffer 3***/
+#define DANUBE_MBC_MBC_DA3 ((volatile u32*)(DANUBE_MBC+ 0x006C))
+#define DANUBE_MBC_MBC_DA3_DA
+
+/***Mailbox CPU Input Absolute Pointer of Buffer 0***/
+#define DANUBE_MBC_MBC_IABS0 ((volatile u32*)(DANUBE_MBC+ 0x0010))
+#define DANUBE_MBC_MBC_IABS0_IABS
+
+/***Mailbox CPU Input Absolute Pointer of Buffer 1***/
+#define DANUBE_MBC_MBC_IABS1 ((volatile u32*)(DANUBE_MBC+ 0x0030))
+#define DANUBE_MBC_MBC_IABS1_IABS
+
+/***Mailbox CPU Input Absolute Pointer of Buffer 2***/
+#define DANUBE_MBC_MBC_IABS2 ((volatile u32*)(DANUBE_MBC+ 0x0050))
+#define DANUBE_MBC_MBC_IABS2_IABS
+
+/***Mailbox CPU Input Absolute Pointer of Buffer 3***/
+#define DANUBE_MBC_MBC_IABS3 ((volatile u32*)(DANUBE_MBC+ 0x0070))
+#define DANUBE_MBC_MBC_IABS3_IABS
+
+/***Mailbox CPU Input Temporary Pointer of Buffer 0***/
+#define DANUBE_MBC_MBC_ITMP0 ((volatile u32*)(DANUBE_MBC+ 0x0014))
+#define DANUBE_MBC_MBC_ITMP0_ITMP
+
+/***Mailbox CPU Input Temporary Pointer of Buffer 1***/
+#define DANUBE_MBC_MBC_ITMP1 ((volatile u32*)(DANUBE_MBC+ 0x0034))
+#define DANUBE_MBC_MBC_ITMP1_ITMP
+
+/***Mailbox CPU Input Temporary Pointer of Buffer 2***/
+#define DANUBE_MBC_MBC_ITMP2 ((volatile u32*)(DANUBE_MBC+ 0x0054))
+#define DANUBE_MBC_MBC_ITMP2_ITMP
+
+/***Mailbox CPU Input Temporary Pointer of Buffer 3***/
+#define DANUBE_MBC_MBC_ITMP3 ((volatile u32*)(DANUBE_MBC+ 0x0074))
+#define DANUBE_MBC_MBC_ITMP3_ITMP
+
+/***Mailbox CPU Output Absolute Pointer of Buffer 0***/
+#define DANUBE_MBC_MBC_OABS0 ((volatile u32*)(DANUBE_MBC+ 0x0018))
+#define DANUBE_MBC_MBC_OABS0_OABS
+
+/***Mailbox CPU Output Absolute Pointer of Buffer 1***/
+#define DANUBE_MBC_MBC_OABS1 ((volatile u32*)(DANUBE_MBC+ 0x0038))
+#define DANUBE_MBC_MBC_OABS1_OABS
+
+/***Mailbox CPU Output Absolute Pointer of Buffer 2***/
+#define DANUBE_MBC_MBC_OABS2 ((volatile u32*)(DANUBE_MBC+ 0x0058))
+#define DANUBE_MBC_MBC_OABS2_OABS
+
+/***Mailbox CPU Output Absolute Pointer of Buffer 3***/
+#define DANUBE_MBC_MBC_OABS3 ((volatile u32*)(DANUBE_MBC+ 0x0078))
+#define DANUBE_MBC_MBC_OABS3_OABS
+
+/***Mailbox CPU Output Temporary Pointer of Buffer 0***/
+#define DANUBE_MBC_MBC_OTMP0 ((volatile u32*)(DANUBE_MBC+ 0x001C))
+#define DANUBE_MBC_MBC_OTMP0_OTMP
+
+/***Mailbox CPU Output Temporary Pointer of Buffer 1***/
+#define DANUBE_MBC_MBC_OTMP1 ((volatile u32*)(DANUBE_MBC+ 0x003C))
+#define DANUBE_MBC_MBC_OTMP1_OTMP
+
+/***Mailbox CPU Output Temporary Pointer of Buffer 2***/
+#define DANUBE_MBC_MBC_OTMP2 ((volatile u32*)(DANUBE_MBC+ 0x005C))
+#define DANUBE_MBC_MBC_OTMP2_OTMP
+
+/***Mailbox CPU Output Temporary Pointer of Buffer 3***/
+#define DANUBE_MBC_MBC_OTMP3 ((volatile u32*)(DANUBE_MBC+ 0x007C))
+#define DANUBE_MBC_MBC_OTMP3_OTMP
+
+/***DSP Control Register***/
+#define DANUBE_MBC_DCTRL ((volatile u32*)(DANUBE_MBC+ 0x00A0))
+#define DANUBE_MBC_DCTRL_BA (1 << 0)
+#define DANUBE_MBC_DCTRL_BMOD (value) (((( 1 << 3) - 1) & (value)) << 1)
+#define DANUBE_MBC_DCTRL_IDL (1 << 4)
+#define DANUBE_MBC_DCTRL_RES (1 << 15)
+
+/***DSP Status Register***/
+#define DANUBE_MBC_DSTA ((volatile u32*)(DANUBE_MBC+ 0x00A4))
+#define DANUBE_MBC_DSTA_IDLE (1 << 0)
+#define DANUBE_MBC_DSTA_PD (1 << 1)
+
+/***DSP Test 1 Register***/
+#define DANUBE_MBC_DTST1 ((volatile u32*)(DANUBE_MBC+ 0x00A8))
+#define DANUBE_MBC_DTST1_ABORT (1 << 0)
+#define DANUBE_MBC_DTST1_HWF32 (1 << 1)
+#define DANUBE_MBC_DTST1_HWF4M (1 << 2)
+#define DANUBE_MBC_DTST1_HWFOP (1 << 3)
+
+
+/***********************************************************************/
+/* Module : SSC1 register address and bits */
+/***********************************************************************/
+#define DANUBE_SSC1 (KSEG1+0x1e100800)
+/***********************************************************************/
+/***SSC Clock Control Register***/
+#define DANUBE_SSC_CLC (0x0000)
+#define DANUBE_SSC_CLC_RMC(value) (((( 1 << 8) - 1) & (value)) << 8)
+#define DANUBE_SSC_CLC_DISS (1 << 1)
+#define DANUBE_SSC_CLC_DISR (1 << 0)
+/***SSC Port Input Selection Register***/
+#define DANUBE_SSC_PISEL (0x0004)
+/***SSC Identification Register***/
+#define DANUBE_SSC_ID (0x0008)
+/***Control Register (Programming Mode)***/
+#define DANUBE_SSC_CON (0x0010)
+#define DANUBE_SSC_CON_RUEN (1 << 12)
+#define DANUBE_SSC_CON_TUEN (1 << 11)
+#define DANUBE_SSC_CON_AEN (1 << 10)
+#define DANUBE_SSC_CON_REN (1 << 9)
+#define DANUBE_SSC_CON_TEN (1 << 8)
+#define DANUBE_SSC_CON_LB (1 << 7)
+#define DANUBE_SSC_CON_PO (1 << 6)
+#define DANUBE_SSC_CON_PH (1 << 5)
+#define DANUBE_SSC_CON_HB (1 << 4)
+#define DANUBE_SSC_CON_BM(value) (((( 1 << 5) - 1) & (value)) << 16)
+#define DANUBE_SSC_CON_RX_OFF (1 << 1)
+#define DANUBE_SSC_CON_TX_OFF (1 << 0)
+/***SCC Status Register***/
+#define DANUBE_SSC_STATE (0x0014)
+#define DANUBE_SSC_STATE_EN (1 << 0)
+#define DANUBE_SSC_STATE_MS (1 << 1)
+#define DANUBE_SSC_STATE_BSY (1 << 13)
+#define DANUBE_SSC_STATE_RUE (1 << 12)
+#define DANUBE_SSC_STATE_TUE (1 << 11)
+#define DANUBE_SSC_STATE_AE (1 << 10)
+#define DANUBE_SSC_STATE_RE (1 << 9)
+#define DANUBE_SSC_STATE_TE (1 << 8)
+#define DANUBE_SSC_STATE_BC(value) (((( 1 << 5) - 1) & (value)) << 16)
+/***SSC Write Hardware Modified Control Register***/
+#define DANUBE_SSC_WHBSTATE ( 0x0018)
+#define DANUBE_SSC_WHBSTATE_SETBE (1 << 15)
+#define DANUBE_SSC_WHBSTATE_SETPE (1 << 14)
+#define DANUBE_SSC_WHBSTATE_SETRE (1 << 13)
+#define DANUBE_SSC_WHBSTATE_SETTE (1 << 12)
+#define DANUBE_SSC_WHBSTATE_CLRBE (1 << 11)
+#define DANUBE_SSC_WHBSTATE_CLRPE (1 << 10)
+#define DANUBE_SSC_WHBSTATE_CLRRE (1 << 9)
+#define DANUBE_SSC_WHBSTATE_CLRTE (1 << 8)
+/***SSC Transmitter Buffer Register***/
+#define DANUBE_SSC_TB (0x0020)
+#define DANUBE_SSC_TB_TB_VALUE(value) (((( 1 << 16) - 1) & (value)) << 0)
+/***SSC Receiver Buffer Register***/
+#define DANUBE_SSC_RB (0x0024)
+#define DANUBE_SSC_RB_RB_VALUE(value) (((( 1 << 16) - 1) & (value)) << 0)
+/***SSC Receive FIFO Control Register***/
+#define DANUBE_SSC_RXFCON (0x0030)
+#define DANUBE_SSC_RXFCON_RXFITL(value) (((( 1 << 6) - 1) & (value)) << 8)
+#define DANUBE_SSC_RXFCON_RXTMEN (1 << 2)
+#define DANUBE_SSC_RXFCON_RXFLU (1 << 1)
+#define DANUBE_SSC_RXFCON_RXFEN (1 << 0)
+/***SSC Transmit FIFO Control Register***/
+#define DANUBE_SSC_TXFCON ( 0x0034)
+#define DANUBE_SSC_TXFCON_RXFITL(value) (((( 1 << 6) - 1) & (value)) << 8)
+#define DANUBE_SSC_TXFCON_TXTMEN (1 << 2)
+#define DANUBE_SSC_TXFCON_TXFLU (1 << 1)
+#define DANUBE_SSC_TXFCON_TXFEN (1 << 0)
+/***SSC FIFO Status Register***/
+#define DANUBE_SSC_FSTAT (0x0038)
+#define DANUBE_SSC_FSTAT_TXFFL(value) (((( 1 << 6) - 1) & (value)) << 8)
+#define DANUBE_SSC_FSTAT_RXFFL(value) (((( 1 << 6) - 1) & (value)) << 0)
+/***SSC Baudrate Timer Reload Register***/
+#define DANUBE_SSC_BR (0x0040)
+#define DANUBE_SSC_BR_BR_VALUE(value) (((( 1 << 16) - 1) & (value)) << 0)
+#define DANUBE_SSC_BRSTAT (0x0044)
+#define DANUBE_SSC_SFCON (0x0060)
+#define DANUBE_SSC_SFSTAT (0x0064)
+#define DANUBE_SSC_GPOCON (0x0070)
+#define DANUBE_SSC_GPOSTAT (0x0074)
+#define DANUBE_SSC_WHBGPOSTAT (0x0078)
+#define DANUBE_SSC_RXREQ (0x0080)
+#define DANUBE_SSC_RXCNT (0x0084)
+/*DMA Registers in Bus Clock Domain*/
+#define DANUBE_SSC_DMA_CON (0x00EC)
+/*interrupt Node Registers in Bus Clock Domain*/
+#define DANUBE_SSC_IRNEN (0x00F4)
+#define DANUBE_SSC_IRNCR (0x00F8)
+#define DANUBE_SSC_IRNICR (0x00FC)
+#define DANUBE_SSC_IRN_FIR 0x8
+#define DANUBE_SSC_IRN_EIR 0x4
+#define DANUBE_SSC_IRN_RIR 0x2
+#define DANUBE_SSC_IRN_TIR 0x1
+
+
+#define DANUBE_SSC1_CLC ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_CLC))
+#define DANUBE_SSC1_ID ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_ID))
+#define DANUBE_SSC1_CON ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_CON))
+#define DANUBE_SSC1_STATE ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_STATE))
+#define DANUBE_SSC1_WHBSTATE ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_WHBSTATE))
+#define DANUBE_SSC1_TB ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_TB))
+#define DANUBE_SSC1_RB ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_RB))
+#define DANUBE_SSC1_FSTAT ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_FSTAT))
+#define DANUBE_SSC1_PISEL ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_PISEL))
+#define DANUBE_SSC1_RXFCON ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_RXFCON))
+#define DANUBE_SSC1_TXFCON ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_TXFCON))
+#define DANUBE_SSC1_BR ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_BR))
+#define DANUBE_SSC1_BRSTAT ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_BRSTAT))
+#define DANUBE_SSC1_SFCON ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_SFCON))
+#define DANUBE_SSC1_SFSTAT ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_SFSTAT))
+#define DANUBE_SSC1_GPOCON ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_GPOCON))
+#define DANUBE_SSC1_GPOSTAT ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_GPOSTAT))
+#define DANUBE_SSC1_WHBGPOSTAT ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_WHBGPOSTAT))
+#define DANUBE_SSC1_RXREQ ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_RXREQ))
+#define DANUBE_SSC1_RXCNT ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_RXCNT))
+#define DANUBE_SSC1_DMA_CON ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_DMA_CON))
+#define DANUBE_SSC1_IRNEN ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_IRNEN))
+#define DANUBE_SSC1_IRNICR ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_IRNICR))
+#define DANUBE_SSC1_IRNCR ((volatile u32*)(DANUBE_SSC1+DANUBE_SSC_IRNCR))
+
+/***********************************************************************/
+/* Module : GPIO register address and bits */
+/***********************************************************************/
+#define DANUBE_GPIO (0xBE100B00)
+/***Port 0 Data Output Register (0010H)***/
+#define DANUBE_GPIO_P0_OUT ((volatile u32 *)(DANUBE_GPIO+ 0x0010))
+/***Port 1 Data Output Register (0040H)***/
+#define DANUBE_GPIO_P1_OUT ((volatile u32 *)(DANUBE_GPIO+ 0x0040))
+/***Port 0 Data Input Register (0014H)***/
+#define DANUBE_GPIO_P0_IN ((volatile u32 *)(DANUBE_GPIO+ 0x0014))
+/***Port 1 Data Input Register (0044H)***/
+#define DANUBE_GPIO_P1_IN ((volatile u32 *)(DANUBE_GPIO+ 0x0044))
+/***Port 0 Direction Register (0018H)***/
+#define DANUBE_GPIO_P0_DIR ((volatile u32 *)(DANUBE_GPIO+ 0x0018))
+/***Port 1 Direction Register (0048H)***/
+#define DANUBE_GPIO_P1_DIR ((volatile u32 *)(DANUBE_GPIO+ 0x0048))
+/***Port 0 Alternate Function Select Register 0 (001C H) ***/
+#define DANUBE_GPIO_P0_ALTSEL0 ((volatile u32 *)(DANUBE_GPIO+ 0x001C))
+/***Port 1 Alternate Function Select Register 0 (004C H) ***/
+#define DANUBE_GPIO_P1_ALTSEL0 ((volatile u32 *)(DANUBE_GPIO+ 0x004C))
+/***Port 0 Alternate Function Select Register 1 (0020 H) ***/
+#define DANUBE_GPIO_P0_ALTSEL1 ((volatile u32 *)(DANUBE_GPIO+ 0x0020))
+/***Port 1 Alternate Function Select Register 0 (0050 H) ***/
+#define DANUBE_GPIO_P1_ALTSEL1 ((volatile u32 *)(DANUBE_GPIO+ 0x0050))
+/***Port 0 Open Drain Control Register (0024H)***/
+#define DANUBE_GPIO_P0_OD ((volatile u32 *)(DANUBE_GPIO+ 0x0024))
+/***Port 1 Open Drain Control Register (0054H)***/
+#define DANUBE_GPIO_P1_OD ((volatile u32 *)(DANUBE_GPIO+ 0x0054))
+/***Port 0 Input Schmitt-Trigger Off Register (0028 H) ***/
+#define DANUBE_GPIO_P0_STOFF ((volatile u32 *)(DANUBE_GPIO+ 0x0028))
+/***Port 1 Input Schmitt-Trigger Off Register (0058 H) ***/
+#define DANUBE_GPIO_P1_STOFF ((volatile u32 *)(DANUBE_GPIO+ 0x0058))
+/***Port 0 Pull Up/Pull Down Select Register (002C H)***/
+#define DANUBE_GPIO_P0_PUDSEL ((volatile u32 *)(DANUBE_GPIO+ 0x002C))
+/***Port 1 Pull Up/Pull Down Select Register (005C H)***/
+#define DANUBE_GPIO_P1_PUDSEL ((volatile u32 *)(DANUBE_GPIO+ 0x005C))
+/***Port 0 Pull Up Device Enable Register (0030 H)***/
+#define DANUBE_GPIO_P0_PUDEN ((volatile u32 *)(DANUBE_GPIO+ 0x0030))
+/***Port 1 Pull Up Device Enable Register (0060 H)***/
+#define DANUBE_GPIO_P1_PUDEN ((volatile u32 *)(DANUBE_GPIO+ 0x0060))
+/***********************************************************************/
+/* Module : CGU register address and bits */
+/***********************************************************************/
+
+#define DANUBE_CGU (0xBF103000)
+/***********************************************************************/
+
+/***CGU Clock PLL0 ***/
+#define DANUBE_CGU_PLL0_CFG ((volatile u32*)(DANUBE_CGU+ 0x0004))
+/***CGU Clock PLL1 ***/
+#define DANUBE_CGU_PLL1_CFG ((volatile u32*)(DANUBE_CGU+ 0x0008))
+/***CGU Clock SYS Mux Register***/
+#define DANUBE_CGU_SYS ((volatile u32*)(DANUBE_CGU+ 0x0010))
+/***CGU Interface Clock Control Register***/
+#define DANUBE_CGU_IFCCR ((volatile u32*)(DANUBE_CGU+ 0x0018))
+/***CGU PCI Clock Control Register**/
+#define DANUBE_CGU_PCICR ((volatile u32*)(DANUBE_CGU+ 0x0034))
+
+
+/***********************************************************************/
+/* Module : PCI register address and bits */
+/***********************************************************************/
+#define PCI_CR_PR_OFFSET 0xBE105400
+#define PCI_CR_CLK_CTRL_REG (PCI_CR_PR_OFFSET + 0x0000)
+
+#define PCI_CR_PCI_ID_REG (PCI_CR_PR_OFFSET + 0x0004)
+#define PCI_CR_SFT_RST_REG (PCI_CR_PR_OFFSET + 0x0010)
+#define PCI_CR_PCI_FPI_ERR_ADDR_REG (PCI_CR_PR_OFFSET + 0x0014)
+#define PCI_CR_FCI_PCI_ERR_ADDR_REG (PCI_CR_PR_OFFSET + 0x0018)
+#define PCI_CR_FPI_ERR_TAG_REG (PCI_CR_PR_OFFSET + 0x001C)
+#define PCI_CR_PCI_IRR_REG (PCI_CR_PR_OFFSET + 0x0020)
+#define PCI_CR_PCI_IRA_REG (PCI_CR_PR_OFFSET + 0x0024)
+#define PCI_CR_PCI_IRM_REG (PCI_CR_PR_OFFSET + 0x0028)
+#define PCI_CR_PCI_EOI_REG (PCI_CR_PR_OFFSET + 0x002C)
+#define PCI_CR_PCI_MOD_REG (PCI_CR_PR_OFFSET + 0x0030)
+#define PCI_CR_DV_ID_REG (PCI_CR_PR_OFFSET + 0x0034)
+#define PCI_CR_SUBSYS_ID_REG (PCI_CR_PR_OFFSET + 0x0038)
+#define PCI_CR_PCI_PM_REG (PCI_CR_PR_OFFSET + 0x003C)
+#define PCI_CR_CLASS_CODE1_REG (PCI_CR_PR_OFFSET + 0x0040)
+#define PCI_CR_BAR11MASK_REG (PCI_CR_PR_OFFSET + 0x0044)
+#define PCI_CR_BAR12MASK_REG (PCI_CR_PR_OFFSET + 0x0048)
+#define PCI_CR_BAR13MASK_REG (PCI_CR_PR_OFFSET + 0x004C)
+#define PCI_CR_BAR14MASK_REG (PCI_CR_PR_OFFSET + 0x0050)
+#define PCI_CR_BAR15MASK_REG (PCI_CR_PR_OFFSET + 0x0054)
+#define PCI_CR_BAR16MASK_REG (PCI_CR_PR_OFFSET + 0x0058)
+#define PCI_CR_CIS_PT1_REG (PCI_CR_PR_OFFSET + 0x005C)
+#define PCI_CR_SUBSYS_ID1_REG (PCI_CR_PR_OFFSET + 0x0060)
+#define PCI_CR_PCI_ADDR_MAP11_REG (PCI_CR_PR_OFFSET + 0x0064)
+#define PCI_CR_PCI_ADDR_MAP12_REG (PCI_CR_PR_OFFSET + 0x0068)
+#define PCI_CR_PCI_ADDR_MAP13_REG (PCI_CR_PR_OFFSET + 0x006C)
+#define PCI_CR_PCI_ADDR_MAP14_REG (PCI_CR_PR_OFFSET + 0x0070)
+#define PCI_CR_PCI_ADDR_MAP15_REG (PCI_CR_PR_OFFSET + 0x0074)
+#define PCI_CR_PCI_ADDR_MAP16_REG (PCI_CR_PR_OFFSET + 0x0078)
+#define PCI_CR_FPI_SEG_EN_REG (PCI_CR_PR_OFFSET + 0x007C)
+#define PCI_CR_PC_ARB_REG (PCI_CR_PR_OFFSET + 0x0080)
+#define PCI_CR_BAR21MASK_REG (PCI_CR_PR_OFFSET + 0x0084)
+#define PCI_CR_BAR22MASK_REG (PCI_CR_PR_OFFSET + 0x0088)
+#define PCI_CR_BAR23MASK_REG (PCI_CR_PR_OFFSET + 0x008C)
+#define PCI_CR_BAR24MASK_REG (PCI_CR_PR_OFFSET + 0x0090)
+#define PCI_CR_BAR25MASK_REG (PCI_CR_PR_OFFSET + 0x0094)
+#define PCI_CR_BAR26MASK_REG (PCI_CR_PR_OFFSET + 0x0098)
+#define PCI_CR_CIS_PT2_REG (PCI_CR_PR_OFFSET + 0x009C)
+#define PCI_CR_SUBSYS_ID2_REG (PCI_CR_PR_OFFSET + 0x00A0)
+#define PCI_CR_PCI_ADDR_MAP21_REG (PCI_CR_PR_OFFSET + 0x00A4)
+#define PCI_CR_PCI_ADDR_MAP22_REG (PCI_CR_PR_OFFSET + 0x00A8)
+#define PCI_CR_PCI_ADDR_MAP23_REG (PCI_CR_PR_OFFSET + 0x00AC)
+
+
+/***********************************************************************/
+/* Module : MCD register address and bits */
+/***********************************************************************/
+#define DANUBE_MCD (KSEG1+0x1F106000)
+
+/***Manufacturer Identification Register***/
+#define DANUBE_MCD_MANID ((volatile u32*)(DANUBE_MCD+ 0x0024))
+#define DANUBE_MCD_MANID_MANUF(value) (((( 1 << 11) - 1) & (value)) << 5)
+
+/***Chip Identification Register***/
+#define DANUBE_MCD_CHIPID ((volatile u32*)(DANUBE_MCD+ 0x0028))
+#define DANUBE_MCD_CHIPID_VERSION_GET(value) (((value) >> 28) & ((1 << 4) - 1))
+#define DANUBE_MCD_CHIPID_VERSION_SET(value) (((( 1 << 4) - 1) & (value)) << 28)
+#define DANUBE_MCD_CHIPID_PART_NUMBER_GET(value) (((value) >> 12) & ((1 << 16) - 1))
+#define DANUBE_MCD_CHIPID_PART_NUMBER_SET(value) (((( 1 << 16) - 1) & (value)) << 12)
+#define DANUBE_MCD_CHIPID_MANID_GET(value) (((value) >> 1) & ((1 << 11) - 1))
+#define DANUBE_MCD_CHIPID_MANID_SET(value) (((( 1 << 11) - 1) & (value)) << 1)
+
+#define DANUBE_CHIPID_STANDARD 0x00EB
+#define DANUBE_CHIPID_YANGTSE 0x00ED
+
+/***Redesign Tracing Identification Register***/
+#define DANUBE_MCD_RTID ((volatile u32*)(DANUBE_MCD+ 0x002C))
+#define DANUBE_MCD_RTID_LC (1 << 15)
+#define DANUBE_MCD_RTID_RIX(value) (((( 1 << 3) - 1) & (value)) << 0)
+
+
+/***********************************************************************/
+/* Module : EBU register address and bits */
+/***********************************************************************/
+
+#define DANUBE_EBU (0xBE105300)
+#define EBU_NAND_CON (volatile u32*)(DANUBE_EBU + 0xB0)
+#define EBU_NAND_WAIT (volatile u32*)(DANUBE_EBU + 0xB4)
+#define EBU_NAND_ECC0 (volatile u32*)(DANUBE_EBU + 0xB8)
+#define EBU_NAND_ECC_AC (volatile u32*)(DANUBE_EBU + 0xBC)
+
+/***********************************************************************/
+
+
+/***EBU Clock Control Register***/
+#define DANUBE_EBU_CLC ((volatile u32*)(DANUBE_EBU+ 0x0000))
+#define DANUBE_EBU_CLC_DISS (1 << 1)
+#define DANUBE_EBU_CLC_DISR (1 << 0)
+
+/***EBU Global Control Register***/
+#define DANUBE_EBU_CON ((volatile u32*)(DANUBE_EBU+ 0x0010))
+#define DANUBE_EBU_CON_DTACS (value) (((( 1 << 3) - 1) & (value)) << 20)
+#define DANUBE_EBU_CON_DTARW (value) (((( 1 << 3) - 1) & (value)) << 16)
+#define DANUBE_EBU_CON_TOUTC (value) (((( 1 << 8) - 1) & (value)) << 8)
+#define DANUBE_EBU_CON_ARBMODE (value) (((( 1 << 2) - 1) & (value)) << 6)
+#define DANUBE_EBU_CON_ARBSYNC (1 << 5)
+#define DANUBE_EBU_CON_1 (1 << 3)
+
+/***EBU Address Select Register 0***/
+#define DANUBE_EBU_ADDSEL0 ((volatile u32*)(DANUBE_EBU+ 0x0020))
+#define DANUBE_EBU_ADDSEL0_BASE (value) (((( 1 << 20) - 1) & (value)) << 12)
+#define DANUBE_EBU_ADDSEL0_MASK (value) (((( 1 << 4) - 1) & (value)) << 4)
+#define DANUBE_EBU_ADDSEL0_MIRRORE (1 << 1)
+#define DANUBE_EBU_ADDSEL0_REGEN (1 << 0)
+
+/***EBU Address Select Register 1***/
+#define DANUBE_EBU_ADDSEL1 ((volatile u32*)(DANUBE_EBU+ 0x0024))
+#define DANUBE_EBU_ADDSEL1_BASE (value) (((( 1 << 20) - 1) & (value)) << 12)
+#define DANUBE_EBU_ADDSEL1_MASK (value) (((( 1 << 4) - 1) & (value)) << 4)
+#define DANUBE_EBU_ADDSEL1_MIRRORE (1 << 1)
+#define DANUBE_EBU_ADDSEL1_REGEN (1 << 0)
+
+/***EBU Address Select Register 2***/
+#define DANUBE_EBU_ADDSEL2 ((volatile u32*)(DANUBE_EBU+ 0x0028))
+#define DANUBE_EBU_ADDSEL2_BASE (value) (((( 1 << 20) - 1) & (value)) << 12)
+#define DANUBE_EBU_ADDSEL2_MASK (value) (((( 1 << 4) - 1) & (value)) << 4)
+#define DANUBE_EBU_ADDSEL2_MIRRORE (1 << 1)
+#define DANUBE_EBU_ADDSEL2_REGEN (1 << 0)
+
+/***EBU Address Select Register 3***/
+#define DANUBE_EBU_ADDSEL3 ((volatile u32*)(DANUBE_EBU+ 0x002C))
+#define DANUBE_EBU_ADDSEL3_BASE (value) (((( 1 << 20) - 1) & (value)) << 12)
+#define DANUBE_EBU_ADDSEL3_MASK (value) (((( 1 << 4) - 1) & (value)) << 4)
+#define DANUBE_EBU_ADDSEL3_MIRRORE (1 << 1)
+#define DANUBE_EBU_ADDSEL3_REGEN (1 << 0)
+
+/***EBU Bus Configuration Register 0***/
+#define DANUBE_EBU_BUSCON0 ((volatile u32*)(DANUBE_EBU+ 0x0060))
+#define DANUBE_EBU_BUSCON0_WRDIS (1 << 31)
+#define DANUBE_EBU_BUSCON0_ALEC (value) (((( 1 << 2) - 1) & (value)) << 29)
+#define DANUBE_EBU_BUSCON0_BCGEN (value) (((( 1 << 2) - 1) & (value)) << 27)
+#define DANUBE_EBU_BUSCON0_AGEN (value) (((( 1 << 2) - 1) & (value)) << 24)
+#define DANUBE_EBU_BUSCON0_CMULTR (value) (((( 1 << 2) - 1) & (value)) << 22)
+#define DANUBE_EBU_BUSCON0_WAIT (value) (((( 1 << 2) - 1) & (value)) << 20)
+#define DANUBE_EBU_BUSCON0_WAITINV (1 << 19)
+#define DANUBE_EBU_BUSCON0_SETUP (1 << 18)
+#define DANUBE_EBU_BUSCON0_PORTW (value) (((( 1 << 2) - 1) & (value)) << 16)
+#define DANUBE_EBU_BUSCON0_WAITRDC (value) (((( 1 << 7) - 1) & (value)) << 9)
+#define DANUBE_EBU_BUSCON0_WAITWRC (value) (((( 1 << 3) - 1) & (value)) << 6)
+#define DANUBE_EBU_BUSCON0_HOLDC (value) (((( 1 << 2) - 1) & (value)) << 4)
+#define DANUBE_EBU_BUSCON0_RECOVC (value) (((( 1 << 2) - 1) & (value)) << 2)
+#define DANUBE_EBU_BUSCON0_CMULT (value) (((( 1 << 2) - 1) & (value)) << 0)
+
+/***EBU Bus Configuration Register 1***/
+#define DANUBE_EBU_BUSCON1 ((volatile u32*)(DANUBE_EBU+ 0x0064))
+#define DANUBE_EBU_BUSCON1_WRDIS (1 << 31)
+#define DANUBE_EBU_BUSCON1_ALEC (value) (((( 1 << 2) - 1) & (value)) << 29)
+#define DANUBE_EBU_BUSCON1_BCGEN (value) (((( 1 << 2) - 1) & (value)) << 27)
+#define DANUBE_EBU_BUSCON1_AGEN (value) (((( 1 << 2) - 1) & (value)) << 24)
+#define DANUBE_EBU_BUSCON1_CMULTR (value) (((( 1 << 2) - 1) & (value)) << 22)
+#define DANUBE_EBU_BUSCON1_WAIT (value) (((( 1 << 2) - 1) & (value)) << 20)
+#define DANUBE_EBU_BUSCON1_WAITINV (1 << 19)
+#define DANUBE_EBU_BUSCON1_SETUP (1 << 18)
+#define DANUBE_EBU_BUSCON1_PORTW (value) (((( 1 << 2) - 1) & (value)) << 16)
+#define DANUBE_EBU_BUSCON1_WAITRDC (value) (((( 1 << 7) - 1) & (value)) << 9)
+#define DANUBE_EBU_BUSCON1_WAITWRC (value) (((( 1 << 3) - 1) & (value)) << 6)
+#define DANUBE_EBU_BUSCON1_HOLDC (value) (((( 1 << 2) - 1) & (value)) << 4)
+#define DANUBE_EBU_BUSCON1_RECOVC (value) (((( 1 << 2) - 1) & (value)) << 2)
+#define DANUBE_EBU_BUSCON1_CMULT (value) (((( 1 << 2) - 1) & (value)) << 0)
+
+/***EBU Bus Configuration Register 2***/
+#define DANUBE_EBU_BUSCON2 ((volatile u32*)(DANUBE_EBU+ 0x0068))
+#define DANUBE_EBU_BUSCON2_WRDIS (1 << 31)
+#define DANUBE_EBU_BUSCON2_ALEC (value) (((( 1 << 2) - 1) & (value)) << 29)
+#define DANUBE_EBU_BUSCON2_BCGEN (value) (((( 1 << 2) - 1) & (value)) << 27)
+#define DANUBE_EBU_BUSCON2_AGEN (value) (((( 1 << 2) - 1) & (value)) << 24)
+#define DANUBE_EBU_BUSCON2_CMULTR (value) (((( 1 << 2) - 1) & (value)) << 22)
+#define DANUBE_EBU_BUSCON2_WAIT (value) (((( 1 << 2) - 1) & (value)) << 20)
+#define DANUBE_EBU_BUSCON2_WAITINV (1 << 19)
+#define DANUBE_EBU_BUSCON2_SETUP (1 << 18)
+#define DANUBE_EBU_BUSCON2_PORTW (value) (((( 1 << 2) - 1) & (value)) << 16)
+#define DANUBE_EBU_BUSCON2_WAITRDC (value) (((( 1 << 7) - 1) & (value)) << 9)
+#define DANUBE_EBU_BUSCON2_WAITWRC (value) (((( 1 << 3) - 1) & (value)) << 6)
+#define DANUBE_EBU_BUSCON2_HOLDC (value) (((( 1 << 2) - 1) & (value)) << 4)
+#define DANUBE_EBU_BUSCON2_RECOVC (value) (((( 1 << 2) - 1) & (value)) << 2)
+#define DANUBE_EBU_BUSCON2_CMULT (value) (((( 1 << 2) - 1) & (value)) << 0)
+
+/***********************************************************************/
+/* Module : SDRAM register address and bits */
+/***********************************************************************/
+
+#define DANUBE_SDRAM (0xBF800000)
+/***********************************************************************/
+
+
+/***MC Access Error Cause Register***/
+#define DANUBE_SDRAM_MC_ERRCAUSE ((volatile u32*)(DANUBE_SDRAM+ 0x0100))
+#define DANUBE_SDRAM_MC_ERRCAUSE_ERR (1 << 31)
+#define DANUBE_SDRAM_MC_ERRCAUSE_PORT (value) (((( 1 << 4) - 1) & (value)) << 16)
+#define DANUBE_SDRAM_MC_ERRCAUSE_CAUSE (value) (((( 1 << 2) - 1) & (value)) << 0)
+#define DANUBE_SDRAM_MC_ERRCAUSE_Res (value) (((( 1 << NaN) - 1) & (value)) << NaN)
+
+/***MC Access Error Address Register***/
+#define DANUBE_SDRAM_MC_ERRADDR ((volatile u32*)(DANUBE_SDRAM+ 0x0108))
+#define DANUBE_SDRAM_MC_ERRADDR_ADDR
+
+/***MC I/O General Purpose Register***/
+#define DANUBE_SDRAM_MC_IOGP ((volatile u32*)(DANUBE_SDRAM+ 0x0800))
+#define DANUBE_SDRAM_MC_IOGP_GPR6 (value) (((( 1 << 4) - 1) & (value)) << 28)
+#define DANUBE_SDRAM_MC_IOGP_GPR5 (value) (((( 1 << 4) - 1) & (value)) << 24)
+#define DANUBE_SDRAM_MC_IOGP_GPR4 (value) (((( 1 << 4) - 1) & (value)) << 20)
+#define DANUBE_SDRAM_MC_IOGP_GPR3 (value) (((( 1 << 4) - 1) & (value)) << 16)
+#define DANUBE_SDRAM_MC_IOGP_GPR2 (value) (((( 1 << 4) - 1) & (value)) << 12)
+#define DANUBE_SDRAM_MC_IOGP_CPS (1 << 11)
+#define DANUBE_SDRAM_MC_IOGP_CLKDELAY (value) (((( 1 << 3) - 1) & (value)) << 8)
+#define DANUBE_SDRAM_MC_IOGP_CLKRAT (value) (((( 1 << 4) - 1) & (value)) << 4)
+#define DANUBE_SDRAM_MC_IOGP_RDDEL (value) (((( 1 << 4) - 1) & (value)) << 0)
+
+/***MC Self Refresh Register***/
+#define DANUBE_SDRAM_MC_SELFRFSH ((volatile u32*)(DANUBE_SDRAM+ 0x0A00))
+#define DANUBE_SDRAM_MC_SELFRFSH_PWDS (1 << 1)
+#define DANUBE_SDRAM_MC_SELFRFSH_PWD (1 << 0)
+#define DANUBE_SDRAM_MC_SELFRFSH_Res (value) (((( 1 << 30) - 1) & (value)) << 2)
+
+/***MC Enable Register***/
+#define DANUBE_SDRAM_MC_CTRLENA ((volatile u32*)(DANUBE_SDRAM+ 0x1000))
+#define DANUBE_SDRAM_MC_CTRLENA_ENA (1 << 0)
+#define DANUBE_SDRAM_MC_CTRLENA_Res (value) (((( 1 << 31) - 1) & (value)) << 1)
+
+/***MC Mode Register Setup Code***/
+#define DANUBE_SDRAM_MC_MRSCODE ((volatile u32*)(DANUBE_SDRAM+ 0x1008))
+#define DANUBE_SDRAM_MC_MRSCODE_UMC (value) (((( 1 << 5) - 1) & (value)) << 7)
+#define DANUBE_SDRAM_MC_MRSCODE_CL (value) (((( 1 << 3) - 1) & (value)) << 4)
+#define DANUBE_SDRAM_MC_MRSCODE_WT (1 << 3)
+#define DANUBE_SDRAM_MC_MRSCODE_BL (value) (((( 1 << 3) - 1) & (value)) << 0)
+
+/***MC Configuration Data-word Width Register***/
+#define DANUBE_SDRAM_MC_CFGDW ((volatile u32*)(DANUBE_SDRAM+ 0x1010))
+#define DANUBE_SDRAM_MC_CFGDW_DW (value) (((( 1 << 4) - 1) & (value)) << 0)
+#define DANUBE_SDRAM_MC_CFGDW_Res (value) (((( 1 << 28) - 1) & (value)) << 4)
+
+/***MC Configuration Physical Bank 0 Register***/
+#define DANUBE_SDRAM_MC_CFGPB0 ((volatile u32*)(DANUBE_SDRAM+ 0x1018))
+#define DANUBE_SDRAM_MC_CFGPB0_MCSEN0 (value) (((( 1 << 4) - 1) & (value)) << 12)
+#define DANUBE_SDRAM_MC_CFGPB0_BANKN0 (value) (((( 1 << 4) - 1) & (value)) << 8)
+#define DANUBE_SDRAM_MC_CFGPB0_ROWW0 (value) (((( 1 << 4) - 1) & (value)) << 4)
+#define DANUBE_SDRAM_MC_CFGPB0_COLW0 (value) (((( 1 << 4) - 1) & (value)) << 0)
+#define DANUBE_SDRAM_MC_CFGPB0_Res (value) (((( 1 << 16) - 1) & (value)) << 16)
+
+/***MC Latency Register***/
+#define DANUBE_SDRAM_MC_LATENCY ((volatile u32*)(DANUBE_SDRAM+ 0x1038))
+#define DANUBE_SDRAM_MC_LATENCY_TRP (value) (((( 1 << 4) - 1) & (value)) << 16)
+#define DANUBE_SDRAM_MC_LATENCY_TRAS (value) (((( 1 << 4) - 1) & (value)) << 12)
+#define DANUBE_SDRAM_MC_LATENCY_TRCD (value) (((( 1 << 4) - 1) & (value)) << 8)
+#define DANUBE_SDRAM_MC_LATENCY_TDPL (value) (((( 1 << 4) - 1) & (value)) << 4)
+#define DANUBE_SDRAM_MC_LATENCY_TDAL (value) (((( 1 << 4) - 1) & (value)) << 0)
+#define DANUBE_SDRAM_MC_LATENCY_Res (value) (((( 1 << 12) - 1) & (value)) << 20)
+
+/***MC Refresh Cycle Time Register***/
+#define DANUBE_SDRAM_MC_TREFRESH ((volatile u32*)(DANUBE_SDRAM+ 0x1040))
+#define DANUBE_SDRAM_MC_TREFRESH_TREF (value) (((( 1 << 13) - 1) & (value)) << 0)
+#define DANUBE_SDRAM_MC_TREFRESH_Res (value) (((( 1 << 19) - 1) & (value)) << 13)
+
+
+/***********************************************************************/
+/* Module : GPTU register address and bits */
+/***********************************************************************/
+
+#define DANUBE_GPTU (0xB8000300)
+/***********************************************************************/
+
+
+/***GPT Clock Control Register***/
+#define DANUBE_GPTU_GPT_CLC ((volatile u32*)(DANUBE_GPTU+ 0x0000))
+#define DANUBE_GPTU_GPT_CLC_RMC (value) (((( 1 << 8) - 1) & (value)) << 8)
+#define DANUBE_GPTU_GPT_CLC_DISS (1 << 1)
+#define DANUBE_GPTU_GPT_CLC_DISR (1 << 0)
+
+/***GPT Timer 3 Control Register***/
+#define DANUBE_GPTU_GPT_T3CON ((volatile u32*)(DANUBE_GPTU+ 0x0014))
+#define DANUBE_GPTU_GPT_T3CON_T3RDIR (1 << 15)
+#define DANUBE_GPTU_GPT_T3CON_T3CHDIR (1 << 14)
+#define DANUBE_GPTU_GPT_T3CON_T3EDGE (1 << 13)
+#define DANUBE_GPTU_GPT_T3CON_BPS1 (value) (((( 1 << 2) - 1) & (value)) << 11)
+#define DANUBE_GPTU_GPT_T3CON_T3OTL (1 << 10)
+#define DANUBE_GPTU_GPT_T3CON_T3UD (1 << 7)
+#define DANUBE_GPTU_GPT_T3CON_T3R (1 << 6)
+#define DANUBE_GPTU_GPT_T3CON_T3M (value) (((( 1 << 3) - 1) & (value)) << 3)
+#define DANUBE_GPTU_GPT_T3CON_T3I (value) (((( 1 << 3) - 1) & (value)) << 0)
+
+/***GPT Write Hardware Modified Timer 3 Control Register
+If set and clear bit are written concurrently with 1, the associated bit is not changed.***/
+#define DANUBE_GPTU_GPT_WHBT3CON ((volatile u32*)(DANUBE_GPTU+ 0x004C))
+#define DANUBE_GPTU_GPT_WHBT3CON_SETT3CHDIR (1 << 15)
+#define DANUBE_GPTU_GPT_WHBT3CON_CLRT3CHDIR (1 << 14)
+#define DANUBE_GPTU_GPT_WHBT3CON_SETT3EDGE (1 << 13)
+#define DANUBE_GPTU_GPT_WHBT3CON_CLRT3EDGE (1 << 12)
+#define DANUBE_GPTU_GPT_WHBT3CON_SETT3OTL (1 << 11)
+#define DANUBE_GPTU_GPT_WHBT3CON_CLRT3OTL (1 << 10)
+
+/***GPT Timer 2 Control Register***/
+#define DANUBE_GPTU_GPT_T2CON ((volatile u32*)(DANUBE_GPTU+ 0x0010))
+#define DANUBE_GPTU_GPT_T2CON_TxRDIR (1 << 15)
+#define DANUBE_GPTU_GPT_T2CON_TxCHDIR (1 << 14)
+#define DANUBE_GPTU_GPT_T2CON_TxEDGE (1 << 13)
+#define DANUBE_GPTU_GPT_T2CON_TxIRDIS (1 << 12)
+#define DANUBE_GPTU_GPT_T2CON_TxRC (1 << 9)
+#define DANUBE_GPTU_GPT_T2CON_TxUD (1 << 7)
+#define DANUBE_GPTU_GPT_T2CON_TxR (1 << 6)
+#define DANUBE_GPTU_GPT_T2CON_TxM (value) (((( 1 << 3) - 1) & (value)) << 3)
+#define DANUBE_GPTU_GPT_T2CON_TxI (value) (((( 1 << 3) - 1) & (value)) << 0)
+
+/***GPT Timer 4 Control Register***/
+#define DANUBE_GPTU_GPT_T4CON ((volatile u32*)(DANUBE_GPTU+ 0x0018))
+#define DANUBE_GPTU_GPT_T4CON_TxRDIR (1 << 15)
+#define DANUBE_GPTU_GPT_T4CON_TxCHDIR (1 << 14)
+#define DANUBE_GPTU_GPT_T4CON_TxEDGE (1 << 13)
+#define DANUBE_GPTU_GPT_T4CON_TxIRDIS (1 << 12)
+#define DANUBE_GPTU_GPT_T4CON_TxRC (1 << 9)
+#define DANUBE_GPTU_GPT_T4CON_TxUD (1 << 7)
+#define DANUBE_GPTU_GPT_T4CON_TxR (1 << 6)
+#define DANUBE_GPTU_GPT_T4CON_TxM (value) (((( 1 << 3) - 1) & (value)) << 3)
+#define DANUBE_GPTU_GPT_T4CON_TxI (value) (((( 1 << 3) - 1) & (value)) << 0)
+
+/***GPT Write HW Modified Timer 2 Control Register If set
+ and clear bit are written concurrently with 1, the associated bit is not changed.***/
+#define DANUBE_GPTU_GPT_WHBT2CON ((volatile u32*)(DANUBE_GPTU+ 0x0048))
+#define DANUBE_GPTU_GPT_WHBT2CON_SETTxCHDIR (1 << 15)
+#define DANUBE_GPTU_GPT_WHBT2CON_CLRTxCHDIR (1 << 14)
+#define DANUBE_GPTU_GPT_WHBT2CON_SETTxEDGE (1 << 13)
+#define DANUBE_GPTU_GPT_WHBT2CON_CLRTxEDGE (1 << 12)
+
+/***GPT Write HW Modified Timer 4 Control Register If set
+ and clear bit are written concurrently with 1, the associated bit is not changed.***/
+#define DANUBE_GPTU_GPT_WHBT4CON ((volatile u32*)(DANUBE_GPTU+ 0x0050))
+#define DANUBE_GPTU_GPT_WHBT4CON_SETTxCHDIR (1 << 15)
+#define DANUBE_GPTU_GPT_WHBT4CON_CLRTxCHDIR (1 << 14)
+#define DANUBE_GPTU_GPT_WHBT4CON_SETTxEDGE (1 << 13)
+#define DANUBE_GPTU_GPT_WHBT4CON_CLRTxEDGE (1 << 12)
+
+/***GPT Capture Reload Register***/
+#define DANUBE_GPTU_GPT_CAPREL ((volatile u32*)(DANUBE_GPTU+ 0x0030))
+#define DANUBE_GPTU_GPT_CAPREL_CAPREL (value) (((( 1 << 16) - 1) & (value)) << 0)
+
+/***GPT Timer 2 Register***/
+#define DANUBE_GPTU_GPT_T2 ((volatile u32*)(DANUBE_GPTU+ 0x0034))
+#define DANUBE_GPTU_GPT_T2_TVAL (value) (((( 1 << 16) - 1) & (value)) << 0)
+
+/***GPT Timer 3 Register***/
+#define DANUBE_GPTU_GPT_T3 ((volatile u32*)(DANUBE_GPTU+ 0x0038))
+#define DANUBE_GPTU_GPT_T3_TVAL (value) (((( 1 << 16) - 1) & (value)) << 0)
+
+/***GPT Timer 4 Register***/
+#define DANUBE_GPTU_GPT_T4 ((volatile u32*)(DANUBE_GPTU+ 0x003C))
+#define DANUBE_GPTU_GPT_T4_TVAL (value) (((( 1 << 16) - 1) & (value)) << 0)
+
+/***GPT Timer 5 Register***/
+#define DANUBE_GPTU_GPT_T5 ((volatile u32*)(DANUBE_GPTU+ 0x0040))
+#define DANUBE_GPTU_GPT_T5_TVAL (value) (((( 1 << 16) - 1) & (value)) << 0)
+
+/***GPT Timer 6 Register***/
+#define DANUBE_GPTU_GPT_T6 ((volatile u32*)(DANUBE_GPTU+ 0x0044))
+#define DANUBE_GPTU_GPT_T6_TVAL (value) (((( 1 << 16) - 1) & (value)) << 0)
+
+/***GPT Timer 6 Control Register***/
+#define DANUBE_GPTU_GPT_T6CON ((volatile u32*)(DANUBE_GPTU+ 0x0020))
+#define DANUBE_GPTU_GPT_T6CON_T6SR (1 << 15)
+#define DANUBE_GPTU_GPT_T6CON_T6CLR (1 << 14)
+#define DANUBE_GPTU_GPT_T6CON_BPS2 (value) (((( 1 << 2) - 1) & (value)) << 11)
+#define DANUBE_GPTU_GPT_T6CON_T6OTL (1 << 10)
+#define DANUBE_GPTU_GPT_T6CON_T6UD (1 << 7)
+#define DANUBE_GPTU_GPT_T6CON_T6R (1 << 6)
+#define DANUBE_GPTU_GPT_T6CON_T6M (value) (((( 1 << 3) - 1) & (value)) << 3)
+#define DANUBE_GPTU_GPT_T6CON_T6I (value) (((( 1 << 3) - 1) & (value)) << 0)
+
+/***GPT Write HW Modified Timer 6 Control Register If set
+ and clear bit are written concurrently with 1, the associated bit is not changed.***/
+#define DANUBE_GPTU_GPT_WHBT6CON ((volatile u32*)(DANUBE_GPTU+ 0x0054))
+#define DANUBE_GPTU_GPT_WHBT6CON_SETT6OTL (1 << 11)
+#define DANUBE_GPTU_GPT_WHBT6CON_CLRT6OTL (1 << 10)
+
+/***GPT Timer 5 Control Register***/
+#define DANUBE_GPTU_GPT_T5CON ((volatile u32*)(DANUBE_GPTU+ 0x001C))
+#define DANUBE_GPTU_GPT_T5CON_T5SC (1 << 15)
+#define DANUBE_GPTU_GPT_T5CON_T5CLR (1 << 14)
+#define DANUBE_GPTU_GPT_T5CON_CI (value) (((( 1 << 2) - 1) & (value)) << 12)
+#define DANUBE_GPTU_GPT_T5CON_T5CC (1 << 11)
+#define DANUBE_GPTU_GPT_T5CON_CT3 (1 << 10)
+#define DANUBE_GPTU_GPT_T5CON_T5RC (1 << 9)
+#define DANUBE_GPTU_GPT_T5CON_T5UDE (1 << 8)
+#define DANUBE_GPTU_GPT_T5CON_T5UD (1 << 7)
+#define DANUBE_GPTU_GPT_T5CON_T5R (1 << 6)
+#define DANUBE_GPTU_GPT_T5CON_T5M (value) (((( 1 << 3) - 1) & (value)) << 3)
+#define DANUBE_GPTU_GPT_T5CON_T5I (value) (((( 1 << 3) - 1) & (value)) << 0)
+
+
+/***********************************************************************/
+/* Module : IOM register address and bits */
+/***********************************************************************/
+
+#define DANUBE_IOM (0xBF105000)
+/***********************************************************************/
+
+
+/***Receive FIFO***/
+#define DANUBE_IOM_RFIFO ((volatile u32*)(DANUBE_IOM+ 0x0000))
+#define DANUBE_IOM_RFIFO_RXD (value) (((( 1 << 8) - 1) & (value)) << 0)
+
+/***Transmit FIFO***/
+#define DANUBE_IOM_XFIFO ((volatile u32*)(DANUBE_IOM+ 0x0000))
+#define DANUBE_IOM_XFIFO_TXD (value) (((( 1 << 8) - 1) & (value)) << 0)
+
+/***Interrupt Status Register HDLC***/
+#define DANUBE_IOM_ISTAH ((volatile u32*)(DANUBE_IOM+ 0x0080))
+#define DANUBE_IOM_ISTAH_RME (1 << 7)
+#define DANUBE_IOM_ISTAH_RPF (1 << 6)
+#define DANUBE_IOM_ISTAH_RFO (1 << 5)
+#define DANUBE_IOM_ISTAH_XPR (1 << 4)
+#define DANUBE_IOM_ISTAH_XMR (1 << 3)
+#define DANUBE_IOM_ISTAH_XDU (1 << 2)
+
+/***Interrupt Mask Register HDLC***/
+#define DANUBE_IOM_MASKH ((volatile u32*)(DANUBE_IOM+ 0x0080))
+#define DANUBE_IOM_MASKH_RME (1 << 7)
+#define DANUBE_IOM_MASKH_RPF (1 << 6)
+#define DANUBE_IOM_MASKH_RFO (1 << 5)
+#define DANUBE_IOM_MASKH_XPR (1 << 4)
+#define DANUBE_IOM_MASKH_XMR (1 << 3)
+#define DANUBE_IOM_MASKH_XDU (1 << 2)
+
+/***Status Register***/
+#define DANUBE_IOM_STAR ((volatile u32*)(DANUBE_IOM+ 0x0084))
+#define DANUBE_IOM_STAR_XDOV (1 << 7)
+#define DANUBE_IOM_STAR_XFW (1 << 6)
+#define DANUBE_IOM_STAR_RACI (1 << 3)
+#define DANUBE_IOM_STAR_XACI (1 << 1)
+
+/***Command Register***/
+#define DANUBE_IOM_CMDR ((volatile u32*)(DANUBE_IOM+ 0x0084))
+#define DANUBE_IOM_CMDR_RMC (1 << 7)
+#define DANUBE_IOM_CMDR_RRES (1 << 6)
+#define DANUBE_IOM_CMDR_XTF (1 << 3)
+#define DANUBE_IOM_CMDR_XME (1 << 1)
+#define DANUBE_IOM_CMDR_XRES (1 << 0)
+
+/***Mode Register***/
+#define DANUBE_IOM_MODEH ((volatile u32*)(DANUBE_IOM+ 0x0088))
+#define DANUBE_IOM_MODEH_MDS2 (1 << 7)
+#define DANUBE_IOM_MODEH_MDS1 (1 << 6)
+#define DANUBE_IOM_MODEH_MDS0 (1 << 5)
+#define DANUBE_IOM_MODEH_RAC (1 << 3)
+#define DANUBE_IOM_MODEH_DIM2 (1 << 2)
+#define DANUBE_IOM_MODEH_DIM1 (1 << 1)
+#define DANUBE_IOM_MODEH_DIM0 (1 << 0)
+
+/***Extended Mode Register***/
+#define DANUBE_IOM_EXMR ((volatile u32*)(DANUBE_IOM+ 0x008C))
+#define DANUBE_IOM_EXMR_XFBS (1 << 7)
+#define DANUBE_IOM_EXMR_RFBS (value) (((( 1 << 2) - 1) & (value)) << 5)
+#define DANUBE_IOM_EXMR_SRA (1 << 4)
+#define DANUBE_IOM_EXMR_XCRC (1 << 3)
+#define DANUBE_IOM_EXMR_RCRC (1 << 2)
+#define DANUBE_IOM_EXMR_ITF (1 << 0)
+
+/***SAPI1 Register***/
+#define DANUBE_IOM_SAP1 ((volatile u32*)(DANUBE_IOM+ 0x0094))
+#define DANUBE_IOM_SAP1_SAPI1 (value) (((( 1 << 6) - 1) & (value)) << 2)
+#define DANUBE_IOM_SAP1_MHA (1 << 0)
+
+/***Receive Frame Byte Count Low***/
+#define DANUBE_IOM_RBCL ((volatile u32*)(DANUBE_IOM+ 0x0098))
+#define DANUBE_IOM_RBCL_RBC(value) (1 << value)
+
+
+/***SAPI2 Register***/
+#define DANUBE_IOM_SAP2 ((volatile u32*)(DANUBE_IOM+ 0x0098))
+#define DANUBE_IOM_SAP2_SAPI2 (value) (((( 1 << 6) - 1) & (value)) << 2)
+#define DANUBE_IOM_SAP2_MLA (1 << 0)
+
+/***Receive Frame Byte Count High***/
+#define DANUBE_IOM_RBCH ((volatile u32*)(DANUBE_IOM+ 0x009C))
+#define DANUBE_IOM_RBCH_OV (1 << 4)
+#define DANUBE_IOM_RBCH_RBC11 (1 << 3)
+#define DANUBE_IOM_RBCH_RBC10 (1 << 2)
+#define DANUBE_IOM_RBCH_RBC9 (1 << 1)
+#define DANUBE_IOM_RBCH_RBC8 (1 << 0)
+
+/***TEI1 Register 1***/
+#define DANUBE_IOM_TEI1 ((volatile u32*)(DANUBE_IOM+ 0x009C))
+#define DANUBE_IOM_TEI1_TEI1 (value) (((( 1 << 7) - 1) & (value)) << 1)
+#define DANUBE_IOM_TEI1_EA (1 << 0)
+
+/***Receive Status Register***/
+#define DANUBE_IOM_RSTA ((volatile u32*)(DANUBE_IOM+ 0x00A0))
+#define DANUBE_IOM_RSTA_VFR (1 << 7)
+#define DANUBE_IOM_RSTA_RDO (1 << 6)
+#define DANUBE_IOM_RSTA_CRC (1 << 5)
+#define DANUBE_IOM_RSTA_RAB (1 << 4)
+#define DANUBE_IOM_RSTA_SA1 (1 << 3)
+#define DANUBE_IOM_RSTA_SA0 (1 << 2)
+#define DANUBE_IOM_RSTA_TA (1 << 0)
+#define DANUBE_IOM_RSTA_CR (1 << 1)
+
+/***TEI2 Register***/
+#define DANUBE_IOM_TEI2 ((volatile u32*)(DANUBE_IOM+ 0x00A0))
+#define DANUBE_IOM_TEI2_TEI2 (value) (((( 1 << 7) - 1) & (value)) << 1)
+#define DANUBE_IOM_TEI2_EA (1 << 0)
+
+/***Test Mode Register HDLC***/
+#define DANUBE_IOM_TMH ((volatile u32*)(DANUBE_IOM+ 0x00A4))
+#define DANUBE_IOM_TMH_TLP (1 << 0)
+
+/***Command/Indication Receive 0***/
+#define DANUBE_IOM_CIR0 ((volatile u32*)(DANUBE_IOM+ 0x00B8))
+#define DANUBE_IOM_CIR0_CODR0 (value) (((( 1 << 4) - 1) & (value)) << 4)
+#define DANUBE_IOM_CIR0_CIC0 (1 << 3)
+#define DANUBE_IOM_CIR0_CIC1 (1 << 2)
+#define DANUBE_IOM_CIR0_SG (1 << 1)
+#define DANUBE_IOM_CIR0_BAS (1 << 0)
+
+/***Command/Indication Transmit 0***/
+#define DANUBE_IOM_CIX0 ((volatile u32*)(DANUBE_IOM+ 0x00B8))
+#define DANUBE_IOM_CIX0_CODX0 (value) (((( 1 << 4) - 1) & (value)) << 4)
+#define DANUBE_IOM_CIX0_TBA2 (1 << 3)
+#define DANUBE_IOM_CIX0_TBA1 (1 << 2)
+#define DANUBE_IOM_CIX0_TBA0 (1 << 1)
+#define DANUBE_IOM_CIX0_BAC (1 << 0)
+
+/***Command/Indication Receive 1***/
+#define DANUBE_IOM_CIR1 ((volatile u32*)(DANUBE_IOM+ 0x00BC))
+#define DANUBE_IOM_CIR1_CODR1 (value) (((( 1 << 6) - 1) & (value)) << 2)
+
+/***Command/Indication Transmit 1***/
+#define DANUBE_IOM_CIX1 ((volatile u32*)(DANUBE_IOM+ 0x00BC))
+#define DANUBE_IOM_CIX1_CODX1 (value) (((( 1 << 6) - 1) & (value)) << 2)
+#define DANUBE_IOM_CIX1_CICW (1 << 1)
+#define DANUBE_IOM_CIX1_CI1E (1 << 0)
+
+/***Controller Data Access Reg. (CH10)***/
+#define DANUBE_IOM_CDA10 ((volatile u32*)(DANUBE_IOM+ 0x0100))
+#define DANUBE_IOM_CDA10_CDA (value) (((( 1 << 8) - 1) & (value)) << 0)
+
+/***Controller Data Access Reg. (CH11)***/
+#define DANUBE_IOM_CDA11 ((volatile u32*)(DANUBE_IOM+ 0x0104))
+#define DANUBE_IOM_CDA11_CDA (value) (((( 1 << 8) - 1) & (value)) << 0)
+
+/***Controller Data Access Reg. (CH20)***/
+#define DANUBE_IOM_CDA20 ((volatile u32*)(DANUBE_IOM+ 0x0108))
+#define DANUBE_IOM_CDA20_CDA (value) (((( 1 << 8) - 1) & (value)) << 0)
+
+/***Controller Data Access Reg. (CH21)***/
+#define DANUBE_IOM_CDA21 ((volatile u32*)(DANUBE_IOM+ 0x010C))
+#define DANUBE_IOM_CDA21_CDA (value) (((( 1 << 8) - 1) & (value)) << 0)
+
+/***Time Slot and Data Port Sel. (CH10)***/
+#define DANUBE_IOM_CDA_TSDP10 ((volatile u32*)(DANUBE_IOM+ 0x0110))
+#define DANUBE_IOM_CDA_TSDP10_DPS (1 << 7)
+#define DANUBE_IOM_CDA_TSDP10_TSS (value) (((( 1 << 4) - 1) & (value)) << 0)
+
+/***Time Slot and Data Port Sel. (CH11)***/
+#define DANUBE_IOM_CDA_TSDP11 ((volatile u32*)(DANUBE_IOM+ 0x0114))
+#define DANUBE_IOM_CDA_TSDP11_DPS (1 << 7)
+#define DANUBE_IOM_CDA_TSDP11_TSS (value) (((( 1 << 4) - 1) & (value)) << 0)
+
+/***Time Slot and Data Port Sel. (CH20)***/
+#define DANUBE_IOM_CDA_TSDP20 ((volatile u32*)(DANUBE_IOM+ 0x0118))
+#define DANUBE_IOM_CDA_TSDP20_DPS (1 << 7)
+#define DANUBE_IOM_CDA_TSDP20_TSS (value) (((( 1 << 4) - 1) & (value)) << 0)
+
+/***Time Slot and Data Port Sel. (CH21)***/
+#define DANUBE_IOM_CDA_TSDP21 ((volatile u32*)(DANUBE_IOM+ 0x011C))
+#define DANUBE_IOM_CDA_TSDP21_DPS (1 << 7)
+#define DANUBE_IOM_CDA_TSDP21_TSS (value) (((( 1 << 4) - 1) & (value)) << 0)
+
+/***Time Slot and Data Port Sel. (CH10)***/
+#define DANUBE_IOM_CO_TSDP10 ((volatile u32*)(DANUBE_IOM+ 0x0120))
+#define DANUBE_IOM_CO_TSDP10_DPS (1 << 7)
+#define DANUBE_IOM_CO_TSDP10_TSS (value) (((( 1 << 4) - 1) & (value)) << 0)
+
+/***Time Slot and Data Port Sel. (CH11)***/
+#define DANUBE_IOM_CO_TSDP11 ((volatile u32*)(DANUBE_IOM+ 0x0124))
+#define DANUBE_IOM_CO_TSDP11_DPS (1 << 7)
+#define DANUBE_IOM_CO_TSDP11_TSS (value) (((( 1 << 4) - 1) & (value)) << 0)
+
+/***Time Slot and Data Port Sel. (CH20)***/
+#define DANUBE_IOM_CO_TSDP20 ((volatile u32*)(DANUBE_IOM+ 0x0128))
+#define DANUBE_IOM_CO_TSDP20_DPS (1 << 7)
+#define DANUBE_IOM_CO_TSDP20_TSS (value) (((( 1 << 4) - 1) & (value)) << 0)
+
+/***Time Slot and Data Port Sel. (CH21)***/
+#define DANUBE_IOM_CO_TSDP21 ((volatile u32*)(DANUBE_IOM+ 0x012C))
+#define DANUBE_IOM_CO_TSDP21_DPS (1 << 7)
+#define DANUBE_IOM_CO_TSDP21_TSS (value) (((( 1 << 4) - 1) & (value)) << 0)
+
+/***Ctrl. Reg. Contr. Data Access CH1x***/
+#define DANUBE_IOM_CDA1_CR ((volatile u32*)(DANUBE_IOM+ 0x0138))
+#define DANUBE_IOM_CDA1_CR_EN_TBM (1 << 5)
+#define DANUBE_IOM_CDA1_CR_EN_I1 (1 << 4)
+#define DANUBE_IOM_CDA1_CR_EN_I0 (1 << 3)
+#define DANUBE_IOM_CDA1_CR_EN_O1 (1 << 2)
+#define DANUBE_IOM_CDA1_CR_EN_O0 (1 << 1)
+#define DANUBE_IOM_CDA1_CR_SWAP (1 << 0)
+
+/***Ctrl. Reg. Contr. Data Access CH1x***/
+#define DANUBE_IOM_CDA2_CR ((volatile u32*)(DANUBE_IOM+ 0x013C))
+#define DANUBE_IOM_CDA2_CR_EN_TBM (1 << 5)
+#define DANUBE_IOM_CDA2_CR_EN_I1 (1 << 4)
+#define DANUBE_IOM_CDA2_CR_EN_I0 (1 << 3)
+#define DANUBE_IOM_CDA2_CR_EN_O1 (1 << 2)
+#define DANUBE_IOM_CDA2_CR_EN_O0 (1 << 1)
+#define DANUBE_IOM_CDA2_CR_SWAP (1 << 0)
+
+/***Control Register B-Channel Data***/
+#define DANUBE_IOM_BCHA_CR ((volatile u32*)(DANUBE_IOM+ 0x0144))
+#define DANUBE_IOM_BCHA_CR_EN_BC2 (1 << 4)
+#define DANUBE_IOM_BCHA_CR_EN_BC1 (1 << 3)
+
+/***Control Register B-Channel Data***/
+#define DANUBE_IOM_BCHB_CR ((volatile u32*)(DANUBE_IOM+ 0x0148))
+#define DANUBE_IOM_BCHB_CR_EN_BC2 (1 << 4)
+#define DANUBE_IOM_BCHB_CR_EN_BC1 (1 << 3)
+
+/***Control Reg. for HDLC and CI1 Data***/
+#define DANUBE_IOM_DCI_CR ((volatile u32*)(DANUBE_IOM+ 0x014C))
+#define DANUBE_IOM_DCI_CR_DPS_CI1 (1 << 7)
+#define DANUBE_IOM_DCI_CR_EN_CI1 (1 << 6)
+#define DANUBE_IOM_DCI_CR_EN_D (1 << 5)
+
+/***Control Reg. for HDLC and CI1 Data***/
+#define DANUBE_IOM_DCIC_CR ((volatile u32*)(DANUBE_IOM+ 0x014C))
+#define DANUBE_IOM_DCIC_CR_DPS_CI0 (1 << 7)
+#define DANUBE_IOM_DCIC_CR_EN_CI0 (1 << 6)
+#define DANUBE_IOM_DCIC_CR_DPS_D (1 << 5)
+
+/***Control Reg. Serial Data Strobe x***/
+#define DANUBE_IOM_SDS_CR ((volatile u32*)(DANUBE_IOM+ 0x0154))
+#define DANUBE_IOM_SDS_CR_ENS_TSS (1 << 7)
+#define DANUBE_IOM_SDS_CR_ENS_TSS_1 (1 << 6)
+#define DANUBE_IOM_SDS_CR_ENS_TSS_3 (1 << 5)
+#define DANUBE_IOM_SDS_CR_TSS (value) (((( 1 << 4) - 1) & (value)) << 0)
+
+/***Control Register IOM Data***/
+#define DANUBE_IOM_IOM_CR ((volatile u32*)(DANUBE_IOM+ 0x015C))
+#define DANUBE_IOM_IOM_CR_SPU (1 << 7)
+#define DANUBE_IOM_IOM_CR_CI_CS (1 << 5)
+#define DANUBE_IOM_IOM_CR_TIC_DIS (1 << 4)
+#define DANUBE_IOM_IOM_CR_EN_BCL (1 << 3)
+#define DANUBE_IOM_IOM_CR_CLKM (1 << 2)
+#define DANUBE_IOM_IOM_CR_Res (1 << 1)
+#define DANUBE_IOM_IOM_CR_DIS_IOM (1 << 0)
+
+/***Synchronous Transfer Interrupt***/
+#define DANUBE_IOM_STI ((volatile u32*)(DANUBE_IOM+ 0x0160))
+#define DANUBE_IOM_STI_STOV21 (1 << 7)
+#define DANUBE_IOM_STI_STOV20 (1 << 6)
+#define DANUBE_IOM_STI_STOV11 (1 << 5)
+#define DANUBE_IOM_STI_STOV10 (1 << 4)
+#define DANUBE_IOM_STI_STI21 (1 << 3)
+#define DANUBE_IOM_STI_STI20 (1 << 2)
+#define DANUBE_IOM_STI_STI11 (1 << 1)
+#define DANUBE_IOM_STI_STI10 (1 << 0)
+
+/***Acknowledge Synchronous Transfer Interrupt***/
+#define DANUBE_IOM_ASTI ((volatile u32*)(DANUBE_IOM+ 0x0160))
+#define DANUBE_IOM_ASTI_ACK21 (1 << 3)
+#define DANUBE_IOM_ASTI_ACK20 (1 << 2)
+#define DANUBE_IOM_ASTI_ACK11 (1 << 1)
+#define DANUBE_IOM_ASTI_ACK10 (1 << 0)
+
+/***Mask Synchronous Transfer Interrupt***/
+#define DANUBE_IOM_MSTI ((volatile u32*)(DANUBE_IOM+ 0x0164))
+#define DANUBE_IOM_MSTI_STOV21 (1 << 7)
+#define DANUBE_IOM_MSTI_STOV20 (1 << 6)
+#define DANUBE_IOM_MSTI_STOV11 (1 << 5)
+#define DANUBE_IOM_MSTI_STOV10 (1 << 4)
+#define DANUBE_IOM_MSTI_STI21 (1 << 3)
+#define DANUBE_IOM_MSTI_STI20 (1 << 2)
+#define DANUBE_IOM_MSTI_STI11 (1 << 1)
+#define DANUBE_IOM_MSTI_STI10 (1 << 0)
+
+/***Configuration Register for Serial Data Strobes***/
+#define DANUBE_IOM_SDS_CONF ((volatile u32*)(DANUBE_IOM+ 0x0168))
+#define DANUBE_IOM_SDS_CONF_SDS_BCL (1 << 0)
+
+/***Monitoring CDA Bits***/
+#define DANUBE_IOM_MCDA ((volatile u32*)(DANUBE_IOM+ 0x016C))
+#define DANUBE_IOM_MCDA_MCDA21 (value) (((( 1 << 2) - 1) & (value)) << 6)
+#define DANUBE_IOM_MCDA_MCDA20 (value) (((( 1 << 2) - 1) & (value)) << 4)
+#define DANUBE_IOM_MCDA_MCDA11 (value) (((( 1 << 2) - 1) & (value)) << 2)
+#define DANUBE_IOM_MCDA_MCDA10 (value) (((( 1 << 2) - 1) & (value)) << 0)
+
+/***********************************************************************/
+/* Module : ASC0 register address and bits */
+/***********************************************************************/
+#define DANUBE_ASC0 (KSEG1+0x1E100400)
+/***********************************************************************/
+#define DANUBE_ASC0_TBUF ((volatile u32*)(DANUBE_ASC0 + 0x0020))
+#define DANUBE_ASC0_RBUF ((volatile u32*)(DANUBE_ASC0 + 0x0024))
+#define DANUBE_ASC0_FSTAT ((volatile u32*)(DANUBE_ASC0 + 0x0048))
+#define DANUBE_ASC0_FSTAT_TXFREE_GET(value) (((value) >> 24) & ((1 << 6) - 1))
+#define DANUBE_ASC0_FSTAT_TXFREE_SET(value) (((( 1 << 6) - 1) & (value)) << 24)
+#define DANUBE_ASC0_FSTAT_RXFREE_GET(value) (((value) >> 16) & ((1 << 6) - 1))
+#define DANUBE_ASC0_FSTAT_RXFREE_SET(value) (((( 1 << 6) - 1) & (value)) << 16)
+#define DANUBE_ASC0_FSTAT_TXFFL_GET(value) (((value) >> 8) & ((1 << 6) - 1))
+#define DANUBE_ASC0_FSTAT_TXFFL_SET(value) (((( 1 << 6) - 1) & (value)) << 8)
+#define DANUBE_ASC0_FSTAT_RXFFL_GET(value) (((value) >> 0) & ((1 << 6) - 1))
+#define DANUBE_ASC0_FSTAT_RXFFL_SET(value) (((( 1 << 6) - 1) & (value)) << 0)
+
+
+/***********************************************************************/
+/* Module : ASC1 register address and bits */
+/***********************************************************************/
+
+#define DANUBE_ASC1 (KSEG1+0x1E100C00)
+ /***********************************************************************/
+
+#define DANUBE_ASC1_TBUF ((volatile u32*)(DANUBE_ASC1 + 0x0020))
+#define DANUBE_ASC1_RBUF ((volatile u32*)(DANUBE_ASC1 + 0x0024))
+#define DANUBE_ASC1_FSTAT ((volatile u32*)(DANUBE_ASC1 + 0x0048))
+#define DANUBE_ASC1_FSTAT_TXFREE_GET(value) (((value) >> 24) & ((1 << 6) - 1))
+#define DANUBE_ASC1_FSTAT_TXFREE_SET(value) (((( 1 << 6) - 1) & (value)) << 24)
+#define DANUBE_ASC1_FSTAT_RXFREE_GET(value) (((value) >> 16) & ((1 << 6) - 1))
+#define DANUBE_ASC1_FSTAT_RXFREE_SET(value) (((( 1 << 6) - 1) & (value)) << 16)
+#define DANUBE_ASC1_FSTAT_TXFFL_GET(value) (((value) >> 8) & ((1 << 6) - 1))
+#define DANUBE_ASC1_FSTAT_TXFFL_SET(value) (((( 1 << 6) - 1) & (value)) << 8)
+#define DANUBE_ASC1_FSTAT_RXFFL_GET(value) (((value) >> 0) & ((1 << 6) - 1))
+#define DANUBE_ASC1_FSTAT_RXFFL_SET(value) (((( 1 << 6) - 1) & (value)) << 0)
+
+/***********************************************************************/
+/* Module : DMA register address and bits */
+/***********************************************************************/
+
+#define DANUBE_DMA (0xBE104100)
+/***********************************************************************/
+
+#define DANUBE_DMA_BASE DANUBE_DMA
+#define DANUBE_DMA_CLC (volatile u32*)DANUBE_DMA_BASE
+#define DANUBE_DMA_ID (volatile u32*)(DANUBE_DMA_BASE+0x08)
+#define DANUBE_DMA_CTRL (volatile u32*)(DANUBE_DMA_BASE+0x10)
+#define DANUBE_DMA_CPOLL (volatile u32*)(DANUBE_DMA_BASE+0x14)
+#define DANUBE_DMA_CS (volatile u32*)(DANUBE_DMA_BASE+0x18)
+#define DANUBE_DMA_CCTRL (volatile u32*)(DANUBE_DMA_BASE+0x1C)
+#define DANUBE_DMA_CDBA (volatile u32*)(DANUBE_DMA_BASE+0x20)
+#define DANUBE_DMA_CDLEN (volatile u32*)(DANUBE_DMA_BASE+0x24)
+#define DANUBE_DMA_CIS (volatile u32*)(DANUBE_DMA_BASE+0x28)
+#define DANUBE_DMA_CIE (volatile u32*)(DANUBE_DMA_BASE+0x2C)
+
+#define DANUBE_DMA_PS (volatile u32*)(DANUBE_DMA_BASE+0x40)
+#define DANUBE_DMA_PCTRL (volatile u32*)(DANUBE_DMA_BASE+0x44)
+
+#define DANUBE_DMA_IRNEN (volatile u32*)(DANUBE_DMA_BASE+0xf4)
+#define DANUBE_DMA_IRNCR (volatile u32*)(DANUBE_DMA_BASE+0xf8)
+#define DANUBE_DMA_IRNICR (volatile u32*)(DANUBE_DMA_BASE+0xfc)
+/***********************************************************************/
+/* Module : Debug register address and bits */
+/***********************************************************************/
+
+#define DANUBE_Debug (0xBF106000)
+/***********************************************************************/
+
+
+/***MCD Break Bus Switch Register***/
+#define DANUBE_Debug_MCD_BBS ((volatile u32*)(DANUBE_Debug+ 0x0000))
+#define DANUBE_Debug_MCD_BBS_BTP1 (1 << 19)
+#define DANUBE_Debug_MCD_BBS_BTP0 (1 << 18)
+#define DANUBE_Debug_MCD_BBS_BSP1 (1 << 17)
+#define DANUBE_Debug_MCD_BBS_BSP0 (1 << 16)
+#define DANUBE_Debug_MCD_BBS_BT5EN (1 << 15)
+#define DANUBE_Debug_MCD_BBS_BT4EN (1 << 14)
+#define DANUBE_Debug_MCD_BBS_BT5 (1 << 13)
+#define DANUBE_Debug_MCD_BBS_BT4 (1 << 12)
+#define DANUBE_Debug_MCD_BBS_BS5EN (1 << 7)
+#define DANUBE_Debug_MCD_BBS_BS4EN (1 << 6)
+#define DANUBE_Debug_MCD_BBS_BS5 (1 << 5)
+#define DANUBE_Debug_MCD_BBS_BS4 (1 << 4)
+
+/***MCD Multiplexer Control Register***/
+#define DANUBE_Debug_MCD_MCR ((volatile u32*)(DANUBE_Debug+ 0x0008))
+#define DANUBE_Debug_MCD_MCR_MUX5 (1 << 4)
+#define DANUBE_Debug_MCD_MCR_MUX4 (1 << 3)
+#define DANUBE_Debug_MCD_MCR_MUX1 (1 << 0)
+
+
+/***********************************************************************/
+/* Module : SRAM register address and bits */
+/***********************************************************************/
+
+#define DANUBE_SRAM (0xBF980000)
+/***********************************************************************/
+
+
+/***SRAM Size Register***/
+#define DANUBE_SRAM_SRAM_SIZE ((volatile u32*)(DANUBE_SRAM+ 0x0800))
+#define DANUBE_SRAM_SRAM_SIZE_SIZE (value) (((( 1 << 23) - 1) & (value)) << 0)
+
+/***********************************************************************/
+/* Module : BIU register address and bits */
+/***********************************************************************/
+
+#define DANUBE_BIU (0xBFA80000)
+/***********************************************************************/
+
+
+/***BIU Identification Register***/
+#define DANUBE_BIU_BIU_ID ((volatile u32*)(DANUBE_BIU+ 0x0000))
+#define DANUBE_BIU_BIU_ID_ARCH (1 << 16)
+#define DANUBE_BIU_BIU_ID_ID (value) (((( 1 << 8) - 1) & (value)) << 8)
+#define DANUBE_BIU_BIU_ID_REV (value) (((( 1 << 8) - 1) & (value)) << 0)
+
+/***BIU Access Error Cause Register***/
+#define DANUBE_BIU_BIU_ERRCAUSE ((volatile u32*)(DANUBE_BIU+ 0x0100))
+#define DANUBE_BIU_BIU_ERRCAUSE_ERR (1 << 31)
+#define DANUBE_BIU_BIU_ERRCAUSE_PORT (value) (((( 1 << 4) - 1) & (value)) << 16)
+#define DANUBE_BIU_BIU_ERRCAUSE_CAUSE (value) (((( 1 << 2) - 1) & (value)) << 0)
+
+/***BIU Access Error Address Register***/
+#define DANUBE_BIU_BIU_ERRADDR ((volatile u32*)(DANUBE_BIU+ 0x0108))
+#define DANUBE_BIU_BIU_ERRADDR_ADDR
+
+
+/***********************************************************************/
+/* Module : ICU register address and bits */
+/***********************************************************************/
+
+#define DANUBE_ICU (0xBF880200)
+#define DANUBE_ICU (0xBF880200)
+#define DANUBE_ICU_EXI (0xBF101000)
+/***********************************************************************/
+
+
+/***IM0 Interrupt Status Register***/
+#define DANUBE_ICU_IM0_ISR ((volatile u32*)(DANUBE_ICU+ 0x0000))
+#define DANUBE_ICU_IM0_ISR_IR(value) (1 << (value))
+
+
+/***IM1 Interrupt Status Register***/
+#define DANUBE_ICU_IM1_ISR ((volatile u32*)(DANUBE_ICU+ 0x0020))
+#define DANUBE_ICU_IM1_ISR_IR(value) (1 << (value))
+
+
+/***IM2 Interrupt Status Register***/
+#define DANUBE_ICU_IM2_ISR ((volatile u32*)(DANUBE_ICU+ 0x0040))
+#define DANUBE_ICU_IM2_ISR_IR(value) (1 << (value))
+
+/***IM3 Interrupt Status Register***/
+#define DANUBE_ICU_IM3_ISR ((volatile u32*)(DANUBE_ICU+ 0x0060))
+#define DANUBE_ICU_IM3_ISR_IR(value) (1 << (value))
+
+/***IM4 Interrupt Status Register***/
+#define DANUBE_ICU_IM4_ISR ((volatile u32*)(DANUBE_ICU+ 0x0080))
+#define DANUBE_ICU_IM4_ISR_IR(value) (1 << (value))
+
+
+/***IM0 Interrupt Enable Register***/
+#define DANUBE_ICU_IM0_IER ((volatile u32*)(DANUBE_ICU+ 0x0008))
+#define DANUBE_ICU_IM0_IER_IR(value) (1 << (value))
+
+
+/***IM1 Interrupt Enable Register***/
+#define DANUBE_ICU_IM1_IER ((volatile u32*)(DANUBE_ICU+ 0x0028))
+#define DANUBE_ICU_IM1_IER_IR(value) (1 << (value))
+
+
+/***IM2 Interrupt Enable Register***/
+#define DANUBE_ICU_IM2_IER ((volatile u32*)(DANUBE_ICU+ 0x0048))
+#define DANUBE_ICU_IM2_IER_IR(value) (1 << (value)8
+
+/***IM3 Interrupt Enable Register***/
+#define DANUBE_ICU_IM3_IER ((volatile u32*)(DANUBE_ICU+ 0x0068))
+#define DANUBE_ICU_IM3_IER_IR(value) (1 << (value))
+
+/***IM4 Interrupt Enable Register***/
+#define DANUBE_ICU_IM4_IER ((volatile u32*)(DANUBE_ICU+ 0x0088))
+#define DANUBE_ICU_IM4_IER_IR(value) (1 << (value))
+
+
+/***IM0 Interrupt Output Status Register***/
+#define DANUBE_ICU_IM0_IOSR ((volatile u32*)(DANUBE_ICU+ 0x0010))
+#define DANUBE_ICU_IM0_IOSR_IR(value) (1 << (value))
+
+
+/***IM1 Interrupt Output Status Register***/
+#define DANUBE_ICU_IM1_IOSR ((volatile u32*)(DANUBE_ICU+ 0x0030))
+#define DANUBE_ICU_IM1_IOSR_IR(value) (1 << (value))
+
+
+/***IM2 Interrupt Output Status Register***/
+#define DANUBE_ICU_IM2_IOSR ((volatile u32*)(DANUBE_ICU+ 0x0050))
+#define DANUBE_ICU_IM2_IOSR_IR(value) (1 << (value))
+
+/***IM3 Interrupt Output Status Register***/
+#define DANUBE_ICU_IM3_IOSR ((volatile u32*)(DANUBE_ICU+ 0x0070))
+#define DANUBE_ICU_IM3_IOSR_IR(value) (1 << (value))
+
+/***IM4 Interrupt Output Status Register***/
+#define DANUBE_ICU_IM4_IOSR ((volatile u32*)(DANUBE_ICU+ 0x0090))
+#define DANUBE_ICU_IM4_IOSR_IR(value) (1 << (value))
+
+
+/***IM0 Interrupt Request Set Register***/
+#define DANUBE_ICU_IM0_IRSR ((volatile u32*)(DANUBE_ICU+ 0x0018))
+#define DANUBE_ICU_IM0_IRSR_IR(value) (1 << (value))
+
+
+/***IM1 Interrupt Request Set Register***/
+#define DANUBE_ICU_IM1_IRSR ((volatile u32*)(DANUBE_ICU+ 0x0038))
+#define DANUBE_ICU_IM1_IRSR_IR(value) (1 << (value))
+
+
+/***IM2 Interrupt Request Set Register***/
+#define DANUBE_ICU_IM2_IRSR ((volatile u32*)(DANUBE_ICU+ 0x0058))
+#define DANUBE_ICU_IM2_IRSR_IR(value) (1 << (value))
+
+/***IM3 Interrupt Request Set Register***/
+#define DANUBE_ICU_IM3_IRSR ((volatile u32*)(DANUBE_ICU+ 0x0078))
+#define DANUBE_ICU_IM3_IRSR_IR(value) (1 << (value))
+
+/***IM4 Interrupt Request Set Register***/
+#define DANUBE_ICU_IM4_IRSR ((volatile u32*)(DANUBE_ICU+ 0x0098))
+#define DANUBE_ICU_IM4_IRSR_IR(value) (1 << (value))
+
+/***Interrupt Vector Value Register***/
+#define DANUBE_ICU_IM_VEC ((volatile u32*)(DANUBE_ICU+ 0x0060))
+
+/***Interrupt Vector Value Mask***/
+#define DANUBE_ICU_IM0_VEC_MASK 0x0000001f
+#define DANUBE_ICU_IM1_VEC_MASK 0x000003e0
+#define DANUBE_ICU_IM2_VEC_MASK 0x00007c00
+#define DANUBE_ICU_IM3_VEC_MASK 0x000f8000
+#define DANUBE_ICU_IM4_VEC_MASK 0x01f00000
+
+/***DMA Interrupt Mask Value***/
+#define DANUBE_DMA_H_MASK 0x00000fff
+
+/***External Interrupt Control Register***/
+#define DANUBE_ICU_EXTINTCR ((volatile u32*)(DANUBE_ICU_EXI+ 0x0000))
+#define DANUBE_ICU_IRNICR ((volatile u32*)(DANUBE_ICU_EXI+ 0x0004))
+#define DANUBE_ICU_IRNCR ((volatile u32*)(DANUBE_ICU_EXI+ 0x0008))
+#define DANUBE_ICU_IRNEN ((volatile u32*)(DANUBE_ICU_EXI+ 0x000c))
+#define DANUBE_ICU_NMI_CR ((volatile u32*)(DANUBE_ICU_EXI+ 0x00f0))
+#define DANUBE_ICU_NMI_SR ((volatile u32*)(DANUBE_ICU_EXI+ 0x00f4))
+
+/***********************************************************************/
+/* Module : MPS register address and bits */
+/***********************************************************************/
+
+#define DANUBE_MPS (KSEG1+0x1F107000)
+/***********************************************************************/
+
+#define DANUBE_MPS_CHIPID ((volatile u32*)(DANUBE_MPS + 0x0344))
+#define DANUBE_MPS_CHIPID_VERSION_GET(value) (((value) >> 28) & ((1 << 4) - 1))
+#define DANUBE_MPS_CHIPID_VERSION_SET(value) (((( 1 << 4) - 1) & (value)) << 28)
+#define DANUBE_MPS_CHIPID_PARTNUM_GET(value) (((value) >> 12) & ((1 << 16) - 1))
+#define DANUBE_MPS_CHIPID_PARTNUM_SET(value) (((( 1 << 16) - 1) & (value)) << 12)
+#define DANUBE_MPS_CHIPID_MANID_GET(value) (((value) >> 1) & ((1 << 10) - 1))
+#define DANUBE_MPS_CHIPID_MANID_SET(value) (((( 1 << 10) - 1) & (value)) << 1)
+
+
+/* voice channel 0 ... 3 interrupt enable register */
+#define DANUBE_MPS_VC0ENR ((volatile u32*)(DANUBE_MPS + 0x0000))
+#define DANUBE_MPS_VC1ENR ((volatile u32*)(DANUBE_MPS + 0x0004))
+#define DANUBE_MPS_VC2ENR ((volatile u32*)(DANUBE_MPS + 0x0008))
+#define DANUBE_MPS_VC3ENR ((volatile u32*)(DANUBE_MPS + 0x000C))
+/* voice channel 0 ... 3 interrupt status read register */
+#define DANUBE_MPS_RVC0SR ((volatile u32*)(DANUBE_MPS + 0x0010))
+#define DANUBE_MPS_RVC1SR ((volatile u32*)(DANUBE_MPS + 0x0014))
+#define DANUBE_MPS_RVC2SR ((volatile u32*)(DANUBE_MPS + 0x0018))
+#define DANUBE_MPS_RVC3SR ((volatile u32*)(DANUBE_MPS + 0x001C))
+/* voice channel 0 ... 3 interrupt status set register */
+#define DANUBE_MPS_SVC0SR ((volatile u32*)(DANUBE_MPS + 0x0020))
+#define DANUBE_MPS_SVC1SR ((volatile u32*)(DANUBE_MPS + 0x0024))
+#define DANUBE_MPS_SVC2SR ((volatile u32*)(DANUBE_MPS + 0x0028))
+#define DANUBE_MPS_SVC3SR ((volatile u32*)(DANUBE_MPS + 0x002C))
+/* voice channel 0 ... 3 interrupt status clear register */
+#define DANUBE_MPS_CVC0SR ((volatile u32*)(DANUBE_MPS + 0x0030))
+#define DANUBE_MPS_CVC1SR ((volatile u32*)(DANUBE_MPS + 0x0034))
+#define DANUBE_MPS_CVC2SR ((volatile u32*)(DANUBE_MPS + 0x0038))
+#define DANUBE_MPS_CVC3SR ((volatile u32*)(DANUBE_MPS + 0x003C))
+/* common status 0 and 1 read register */
+#define DANUBE_MPS_RAD0SR ((volatile u32*)(DANUBE_MPS + 0x0040))
+#define DANUBE_MPS_RAD1SR ((volatile u32*)(DANUBE_MPS + 0x0044))
+/* common status 0 and 1 set register */
+#define DANUBE_MPS_SAD0SR ((volatile u32*)(DANUBE_MPS + 0x0048))
+#define DANUBE_MPS_SAD1SR ((volatile u32*)(DANUBE_MPS + 0x004C))
+/* common status 0 and 1 clear register */
+#define DANUBE_MPS_CAD0SR ((volatile u32*)(DANUBE_MPS + 0x0050))
+#define DANUBE_MPS_CAD1SR ((volatile u32*)(DANUBE_MPS + 0x0054))
+/* common status 0 and 1 enable register */
+#define DANUBE_MPS_AD0ENR ((volatile u32*)(DANUBE_MPS + 0x0058))
+#define DANUBE_MPS_AD1ENR ((volatile u32*)(DANUBE_MPS + 0x005C))
+/* notification enable register */
+#define DANUBE_MPS_CPU0_NFER ((volatile u32*)(DANUBE_MPS + 0x0060))
+#define DANUBE_MPS_CPU1_NFER ((volatile u32*)(DANUBE_MPS + 0x0064))
+/* CPU to CPU interrup request register */
+#define DANUBE_MPS_CPU0_2_CPU1_IRR ((volatile u32*)(DANUBE_MPS + 0x0070))
+#define DANUBE_MPS_CPU0_2_CPU1_IER ((volatile u32*)(DANUBE_MPS + 0x0074))
+/* Global interrupt request and request enable register */
+#define DANUBE_MPS_GIRR ((volatile u32*)(DANUBE_MPS + 0x0078))
+#define DANUBE_MPS_GIER ((volatile u32*)(DANUBE_MPS + 0x007C))
+
+
+#define DANUBE_MPS_CPU0_SMP0 ((volatile u32*)(DANUBE_MPS + 0x00100))
+
+#define DANUBE_MPS_CPU1_SMP0 ((volatile u32*)(DANUBE_MPS + 0x00200))
+
+/************************************************************************/
+/* Module : DEU register address and bits */
+/************************************************************************/
+#define DANUBE_DEU_BASE_ADDR (0xBE102000)
+/* DEU Control Register */
+#define DANUBE_DEU_CLK ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0000))
+#define DANUBE_DEU_ID ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0008))
+
+/* DEU control register */
+#define DANUBE_DEU_CON ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0010))
+#define DANUBE_DEU_IHR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0014))
+#define DANUBE_DEU_ILR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0018))
+#define DANUBE_DEU_K1HR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x001C))
+#define DANUBE_DEU_K1LR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0020))
+#define DANUBE_DEU_K3HR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0024))
+#define DANUBE_DEU_K3LR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0028))
+#define DANUBE_DEU_IVHR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x002C))
+#define DANUBE_DEU_IVLR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0030))
+#define DANUBE_DEU_OHR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0040))
+#define DANUBE_DEU_OLR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0050))
+
+/* AES DEU register */
+#define DANUBE_AES_CON ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0050))
+#define DANUBE_AES_ID3R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0054))
+#define DANUBE_AES_ID2R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0058))
+#define DANUBE_AES_ID1R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x005C))
+#define DANUBE_AES_ID0R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0060))
+
+/* AES Key register */
+#define DANUBE_AES_K7R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0064))
+#define DANUBE_AES_K6R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0068))
+#define DANUBE_AES_K5R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x006C))
+#define DANUBE_AES_K4R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0070))
+#define DANUBE_AES_K3R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0074))
+#define DANUBE_AES_K2R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0078))
+#define DANUBE_AES_K1R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x007C))
+#define DANUBE_AES_K0R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0080))
+
+/* AES vector register */
+#define DANUBE_AES_IV3R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0084))
+#define DANUBE_AES_IV2R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0088))
+#define DANUBE_AES_IV1R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x008C))
+#define DANUBE_AES_IV0R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0090))
+#define DANUBE_AES_0D3R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0094))
+#define DANUBE_AES_0D2R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0098))
+#define DANUBE_AES_OD1R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x009C))
+#define DANUBE_AES_OD0R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x00A0))
+
+/* hash control registe */
+#define DANUBE_HASH_CON ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x00B0))
+#define DANUBE_HASH_MR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x00B4))
+#define DANUBE_HASH_D1R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x00B8 ))
+#define DANUBE_HASH_D2R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x00BC ))
+#define DANUBE_HASH_D3R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x00C0 ))
+#define DANUBE_HASH_D4R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x00C4))
+#define DANUBE_HASH_D5R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x00C8))
+
+#define DANUBE_CON ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x00EC))
+
+
+
+
+/************************************************************************/
+/* Module : PPE register address and bits */
+/************************************************************************/
+#define DANUBE_PPE_BASE_ADDR (KSEG1 + 0x1E180000)
+#define DANUBE_PPE_PP32_DEBUG_REG_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x0000) << 2)))
+#define DANUBE_PPE_PPM_INT_REG_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x0030) << 2)))
+#define DANUBE_PPE_PP32_INTERNAL_RES_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x0040) << 2)))
+#define DANUBE_PPE_PPE_CLOCK_CONTROL_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x0100) << 2)))
+#define DANUBE_PPE_CDM_CODE_MEMORY_RAM0_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x1000) << 2)))
+#define DANUBE_PPE_CDM_CODE_MEMORY_RAM1_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x2000) << 2)))
+#define DANUBE_PPE_REG_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x4000) << 2)))
+#define DANUBE_PPE_PP32_DATA_MEMORY_RAM1_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x5000) << 2)))
+#define DANUBE_PPE_PPM_INT_UNIT_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x6000) << 2)))
+#define DANUBE_PPE_PPM_TIMER0_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x6100) << 2)))
+#define DANUBE_PPE_PPM_TASK_IND_REG_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x6200) << 2)))
+#define DANUBE_PPE_PPS_BRK_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x6300) << 2)))
+#define DANUBE_PPE_PPM_TIMER1_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x6400) << 2)))
+#define DANUBE_PPE_SB_RAM0_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x8000) << 2)))
+#define DANUBE_PPE_SB_RAM1_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x8400) << 2)))
+#define DANUBE_PPE_SB_RAM2_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x8C00) << 2)))
+#define DANUBE_PPE_SB_RAM3_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x9600) << 2)))
+
+#define DANUBE_PPE_PP32_SLEEP DANUBE_PPE_REG_ADDR(0x0010) /* PP32 Power Saving Register */
+#define DANUBE_PPE_CDM_CFG DANUBE_PPE_REG_ADDR(0x0100) /* Code/Data Memory (CDM) Register */
+
+/* Mailbox Registers */
+#define DANUBE_PPE_MBOX_IGU0_ISRS DANUBE_PPE_REG_ADDR(0x0200)
+#define DANUBE_PPE_MBOX_IGU0_ISRC DANUBE_PPE_REG_ADDR(0x0201)
+#define DANUBE_PPE_MBOX_IGU0_ISR DANUBE_PPE_REG_ADDR(0x0202)
+#define DANUBE_PPE_MBOX_IGU0_IER DANUBE_PPE_REG_ADDR(0x0203)
+#define DANUBE_PPE_MBOX_IGU1_ISRS0 DANUBE_PPE_REG_ADDR(0x0204)
+#define DANUBE_PPE_MBOX_IGU1_ISRC0 DANUBE_PPE_REG_ADDR(0x0205)
+#define DANUBE_PPE_MBOX_IGU1_ISR0 DANUBE_PPE_REG_ADDR(0x0206)
+#define DANUBE_PPE_MBOX_IGU1_IER0 DANUBE_PPE_REG_ADDR(0x0207)
+#define DANUBE_PPE_MBOX_IGU1_ISRS1 DANUBE_PPE_REG_ADDR(0x0208)
+#define DANUBE_PPE_MBOX_IGU1_ISRC1 DANUBE_PPE_REG_ADDR(0x0209)
+#define DANUBE_PPE_MBOX_IGU1_ISR1 DANUBE_PPE_REG_ADDR(0x020A)
+#define DANUBE_PPE_MBOX_IGU1_IER1 DANUBE_PPE_REG_ADDR(0x020B)
+#define DANUBE_PPE_MBOX_IGU1_ISRS2 DANUBE_PPE_REG_ADDR(0x020C)
+#define DANUBE_PPE_MBOX_IGU1_ISRC2 DANUBE_PPE_REG_ADDR(0x020D)
+#define DANUBE_PPE_MBOX_IGU1_ISR2 DANUBE_PPE_REG_ADDR(0x020E)
+#define DANUBE_PPE_MBOX_IGU1_IER2 DANUBE_PPE_REG_ADDR(0x020F)
+#define DANUBE_PPE_MBOX_IGU2_ISRS DANUBE_PPE_REG_ADDR(0x0210)
+#define DANUBE_PPE_MBOX_IGU2_ISRC DANUBE_PPE_REG_ADDR(0x0211)
+#define DANUBE_PPE_MBOX_IGU2_ISR DANUBE_PPE_REG_ADDR(0x0212)
+#define DANUBE_PPE_MBOX_IGU2_IER DANUBE_PPE_REG_ADDR(0x0213)
+#define DANUBE_PPE_MBOX_IGU3_ISRS DANUBE_PPE_REG_ADDR(0x0214)
+#define DANUBE_PPE_MBOX_IGU3_ISRC DANUBE_PPE_REG_ADDR(0x0215)
+#define DANUBE_PPE_MBOX_IGU3_ISR DANUBE_PPE_REG_ADDR(0x0216)
+#define DANUBE_PPE_MBOX_IGU3_IER DANUBE_PPE_REG_ADDR(0x0217)
+#define DANUBE_PPE_MBOX_IGU4_ISRS DANUBE_PPE_REG_ADDR(0x0218)
+#define DANUBE_PPE_MBOX_IGU4_ISRC DANUBE_PPE_REG_ADDR(0x0219)
+#define DANUBE_PPE_MBOX_IGU4_ISR DANUBE_PPE_REG_ADDR(0x021A)
+#define DANUBE_PPE_MBOX_IGU4_IER DANUBE_PPE_REG_ADDR(0x021B)
+/*
+ * Shared Buffer (SB) Registers
+ */
+#define DANUBE_PPE_SB_MST_PRI0 DANUBE_PPE_REG_ADDR(0x0300)
+#define DANUBE_PPE_SB_MST_PRI1 DANUBE_PPE_REG_ADDR(0x0301)
+#define DANUBE_PPE_SB_MST_PRI2 DANUBE_PPE_REG_ADDR(0x0302)
+#define DANUBE_PPE_SB_MST_PRI3 DANUBE_PPE_REG_ADDR(0x0303)
+#define DANUBE_PPE_SB_MST_PRI4 DANUBE_PPE_REG_ADDR(0x0304)
+#define DANUBE_PPE_SB_MST_SEL DANUBE_PPE_REG_ADDR(0x0305)
+/*
+ * RTHA Registers
+ */
+#define DANUBE_PPE_RFBI_CFG DANUBE_PPE_REG_ADDR(0x0400)
+#define DANUBE_PPE_RBA_CFG0 DANUBE_PPE_REG_ADDR(0x0404)
+#define DANUBE_PPE_RBA_CFG1 DANUBE_PPE_REG_ADDR(0x0405)
+#define DANUBE_PPE_RCA_CFG0 DANUBE_PPE_REG_ADDR(0x0408)
+#define DANUBE_PPE_RCA_CFG1 DANUBE_PPE_REG_ADDR(0x0409)
+#define DANUBE_PPE_RDES_CFG0 DANUBE_PPE_REG_ADDR(0x040C)
+#define DANUBE_PPE_RDES_CFG1 DANUBE_PPE_REG_ADDR(0x040D)
+#define DANUBE_PPE_SFSM_STATE0 DANUBE_PPE_REG_ADDR(0x0410)
+#define DANUBE_PPE_SFSM_STATE1 DANUBE_PPE_REG_ADDR(0x0411)
+#define DANUBE_PPE_SFSM_DBA0 DANUBE_PPE_REG_ADDR(0x0412)
+#define DANUBE_PPE_SFSM_DBA1 DANUBE_PPE_REG_ADDR(0x0413)
+#define DANUBE_PPE_SFSM_CBA0 DANUBE_PPE_REG_ADDR(0x0414)
+#define DANUBE_PPE_SFSM_CBA1 DANUBE_PPE_REG_ADDR(0x0415)
+#define DANUBE_PPE_SFSM_CFG0 DANUBE_PPE_REG_ADDR(0x0416)
+#define DANUBE_PPE_SFSM_CFG1 DANUBE_PPE_REG_ADDR(0x0417)
+#define DANUBE_PPE_SFSM_PGCNT0 DANUBE_PPE_REG_ADDR(0x041C)
+#define DANUBE_PPE_SFSM_PGCNT1 DANUBE_PPE_REG_ADDR(0x041D)
+/*
+ * TTHA Registers
+ */
+#define DANUBE_PPE_FFSM_DBA0 DANUBE_PPE_REG_ADDR(0x0508)
+#define DANUBE_PPE_FFSM_DBA1 DANUBE_PPE_REG_ADDR(0x0509)
+#define DANUBE_PPE_FFSM_CFG0 DANUBE_PPE_REG_ADDR(0x050A)
+#define DANUBE_PPE_FFSM_CFG1 DANUBE_PPE_REG_ADDR(0x050B)
+#define DANUBE_PPE_FFSM_IDLE_HEAD_BC0 DANUBE_PPE_REG_ADDR(0x050E)
+#define DANUBE_PPE_FFSM_IDLE_HEAD_BC1 DANUBE_PPE_REG_ADDR(0x050F)
+#define DANUBE_PPE_FFSM_PGCNT0 DANUBE_PPE_REG_ADDR(0x0514)
+#define DANUBE_PPE_FFSM_PGCNT1 DANUBE_PPE_REG_ADDR(0x0515)
+/*
+ * ETOP MDIO Registers
+ */
+#define DANUBE_PPE_ETOP_MDIO_CFG DANUBE_PPE_REG_ADDR(0x0600)
+#define DANUBE_PPE_ETOP_MDIO_ACC DANUBE_PPE_REG_ADDR(0x0601)
+#define DANUBE_PPE_ETOP_CFG DANUBE_PPE_REG_ADDR(0x0602)
+#define DANUBE_PPE_ETOP_IG_VLAN_COS DANUBE_PPE_REG_ADDR(0x0603)
+#define DANUBE_PPE_ETOP_IG_DSCP_COS3 DANUBE_PPE_REG_ADDR(0x0604)
+#define DANUBE_PPE_ETOP_IG_DSCP_COS2 DANUBE_PPE_REG_ADDR(0x0605)
+#define DANUBE_PPE_ETOP_IG_DSCP_COS1 DANUBE_PPE_REG_ADDR(0x0606)
+#define DANUBE_PPE_ETOP_IG_DSCP_COS0 DANUBE_PPE_REG_ADDR(0x0607)
+#define DANUBE_PPE_ETOP_IG_PLEN_CTRL0 DANUBE_PPE_REG_ADDR(0x0608)
+#define DANUBE_PPE_ETOP_IG_PLEN_CTRL1 DANUBE_PPE_REG_ADDR(0x0609)
+#define DANUBE_PPE_ETOP_ISR DANUBE_PPE_REG_ADDR(0x060A)
+#define DANUBE_PPE_ETOP_IER DANUBE_PPE_REG_ADDR(0x060B)
+#define DANUBE_PPE_ETOP_VPID DANUBE_PPE_REG_ADDR(0x060C)
+#define DANUBE_PPE_ENET_MAC_CFG DANUBE_PPE_REG_ADDR(0x0610)
+#define DANUBE_PPE_ENETS_DBA DANUBE_PPE_REG_ADDR(0x0612)
+#define DANUBE_PPE_ENETS_CBA DANUBE_PPE_REG_ADDR(0x0613)
+#define DANUBE_PPE_ENETS_CFG DANUBE_PPE_REG_ADDR(0x0614)
+#define DANUBE_PPE_ENETS_PGCNT DANUBE_PPE_REG_ADDR(0x0615)
+#define DANUBE_PPE_ENETS_PGCNT_DSRC_PP32 (0x00020000)
+#define DANUBE_PPE_ENETS_PGCNT_DVAL_SHIFT (9)
+#define DANUBE_PPE_ENETS_PGCNT_DCMD (0x00000100)
+#define DANUBE_PPE_ENETS_PKTCNT DANUBE_PPE_REG_ADDR(0x0616)
+#define DANUBE_PPE_ENETS_PKTCNT_DSRC_PP32 (0x00000200)
+#define DANUBE_PPE_ENETS_PKTCNT_DCMD (0x00000100)
+#define DANUBE_PPE_ENETS_PKTCNT_UPKT (0x000000FF)
+#define DANUBE_PPE_ENETS_BUF_CTRL DANUBE_PPE_REG_ADDR(0x0617)
+#define DANUBE_PPE_ENETS_COS_CFG DANUBE_PPE_REG_ADDR(0x0618)
+#define DANUBE_PPE_ENETS_IGDROP DANUBE_PPE_REG_ADDR(0x0619)
+#define DANUBE_PPE_ENETF_DBA DANUBE_PPE_REG_ADDR(0x0630)
+#define DANUBE_PPE_ENETF_CBA DANUBE_PPE_REG_ADDR(0x0631)
+#define DANUBE_PPE_ENETF_CFG DANUBE_PPE_REG_ADDR(0x0632)
+#define DANUBE_PPE_ENETF_PGCNT DANUBE_PPE_REG_ADDR(0x0633)
+#define DANUBE_PPE_ENETF_PGCNT_ISRC_PP32 (0x00020000)
+#define DANUBE_PPE_ENETF_PGCNT_IVAL_SHIFT (9)
+#define DANUBE_PPE_ENETF_PGCNT_ICMD (0x00000100)
+#define DANUBE_PPE_ENETF_PKTCNT DANUBE_PPE_REG_ADDR(0x0634)
+#define DANUBE_PPE_ENETF_PKTCNT_ISRC_PP32 (0x00000200)
+#define DANUBE_PPE_ENETF_PKTCNT_ICMD (0x00000100)
+#define DANUBE_PPE_ENETF_PKTCNT_VPKT (0x000000FF)
+#define DANUBE_PPE_ENETF_HFCTRL DANUBE_PPE_REG_ADDR(0x0635)
+#define DANUBE_PPE_ENETF_TXCTRL DANUBE_PPE_REG_ADDR(0x0636)
+#define DANUBE_PPE_ENETF_VLCOS0 DANUBE_PPE_REG_ADDR(0x0638)
+#define DANUBE_PPE_ENETF_VLCOS1 DANUBE_PPE_REG_ADDR(0x0639)
+#define DANUBE_PPE_ENETF_VLCOS2 DANUBE_PPE_REG_ADDR(0x063A)
+#define DANUBE_PPE_ENETF_VLCOS3 DANUBE_PPE_REG_ADDR(0x063B)
+#define DANUBE_PPE_ENETF_EGERR DANUBE_PPE_REG_ADDR(0x063C)
+#define DANUBE_PPE_ENETF_EGDROP DANUBE_PPE_REG_ADDR(0x063D)
+/*
+ * DPLUS Registers
+ */
+#define DANUBE_PPE_DPLUS_TXDB DANUBE_PPE_REG_ADDR(0x0700)
+#define DANUBE_PPE_DPLUS_TXCB DANUBE_PPE_REG_ADDR(0x0701)
+#define DANUBE_PPE_DPLUS_TXCFG DANUBE_PPE_REG_ADDR(0x0702)
+#define DANUBE_PPE_DPLUS_TXPGCNT DANUBE_PPE_REG_ADDR(0x0703)
+#define DANUBE_PPE_DPLUS_RXDB DANUBE_PPE_REG_ADDR(0x0710)
+#define DANUBE_PPE_DPLUS_RXCB DANUBE_PPE_REG_ADDR(0x0711)
+#define DANUBE_PPE_DPLUS_RXCFG DANUBE_PPE_REG_ADDR(0x0712)
+#define DANUBE_PPE_DPLUS_RXPGCNT DANUBE_PPE_REG_ADDR(0x0713)
+/*
+ * BMC Registers
+ */
+#define DANUBE_PPE_BMC_CMD3 DANUBE_PPE_REG_ADDR(0x0800)
+#define DANUBE_PPE_BMC_CMD2 DANUBE_PPE_REG_ADDR(0x0801)
+#define DANUBE_PPE_BMC_CMD1 DANUBE_PPE_REG_ADDR(0x0802)
+#define DANUBE_PPE_BMC_CMD0 DANUBE_PPE_REG_ADDR(0x0803)
+#define DANUBE_PPE_BMC_CFG0 DANUBE_PPE_REG_ADDR(0x0804)
+#define DANUBE_PPE_BMC_CFG1 DANUBE_PPE_REG_ADDR(0x0805)
+#define DANUBE_PPE_BMC_POLY0 DANUBE_PPE_REG_ADDR(0x0806)
+#define DANUBE_PPE_BMC_POLY1 DANUBE_PPE_REG_ADDR(0x0807)
+#define DANUBE_PPE_BMC_CRC0 DANUBE_PPE_REG_ADDR(0x0808)
+#define DANUBE_PPE_BMC_CRC1 DANUBE_PPE_REG_ADDR(0x0809)
+/*
+ * SLL Registers
+ */
+#define DANUBE_PPE_SLL_CMD1 DANUBE_PPE_REG_ADDR(0x0900)
+#define DANUBE_PPE_SLL_CMD0 DANUBE_PPE_REG_ADDR(0x0901)
+#define DANUBE_PPE_SLL_KEY0 DANUBE_PPE_REG_ADDR(0x0910)
+#define DANUBE_PPE_SLL_KEY1 DANUBE_PPE_REG_ADDR(0x0911)
+#define DANUBE_PPE_SLL_KEY2 DANUBE_PPE_REG_ADDR(0x0912)
+#define DANUBE_PPE_SLL_KEY3 DANUBE_PPE_REG_ADDR(0x0913)
+#define DANUBE_PPE_SLL_KEY4 DANUBE_PPE_REG_ADDR(0x0914)
+#define DANUBE_PPE_SLL_KEY5 DANUBE_PPE_REG_ADDR(0x0915)
+#define DANUBE_PPE_SLL_RESULT DANUBE_PPE_REG_ADDR(0x0920)
+/*
+ * EMA Registers
+ */
+#define DANUBE_PPE_EMA_CMD2 DANUBE_PPE_REG_ADDR(0x0A00)
+#define DANUBE_PPE_EMA_CMD1 DANUBE_PPE_REG_ADDR(0x0A01)
+#define DANUBE_PPE_EMA_CMD0 DANUBE_PPE_REG_ADDR(0x0A02)
+#define DANUBE_PPE_EMA_ISR DANUBE_PPE_REG_ADDR(0x0A04)
+#define DANUBE_PPE_EMA_IER DANUBE_PPE_REG_ADDR(0x0A05)
+#define DANUBE_PPE_EMA_CFG DANUBE_PPE_REG_ADDR(0x0A06)
+/*
+ * UTPS Registers
+ */
+#define DANUBE_PPE_UTP_TXCA0 DANUBE_PPE_REG_ADDR(0x0B00)
+#define DANUBE_PPE_UTP_TXNA0 DANUBE_PPE_REG_ADDR(0x0B01)
+#define DANUBE_PPE_UTP_TXCA1 DANUBE_PPE_REG_ADDR(0x0B02)
+#define DANUBE_PPE_UTP_TXNA1 DANUBE_PPE_REG_ADDR(0x0B03)
+#define DANUBE_PPE_UTP_RXCA0 DANUBE_PPE_REG_ADDR(0x0B10)
+#define DANUBE_PPE_UTP_RXNA0 DANUBE_PPE_REG_ADDR(0x0B11)
+#define DANUBE_PPE_UTP_RXCA1 DANUBE_PPE_REG_ADDR(0x0B12)
+#define DANUBE_PPE_UTP_RXNA1 DANUBE_PPE_REG_ADDR(0x0B13)
+#define DANUBE_PPE_UTP_CFG DANUBE_PPE_REG_ADDR(0x0B20)
+#define DANUBE_PPE_UTP_ISR DANUBE_PPE_REG_ADDR(0x0B30)
+#define DANUBE_PPE_UTP_IER DANUBE_PPE_REG_ADDR(0x0B31)
+/*
+ * QSB Registers
+ */
+#define DANUBE_PPE_QSB_RELOG DANUBE_PPE_REG_ADDR(0x0C00)
+#define DANUBE_PPE_QSB_EMIT0 DANUBE_PPE_REG_ADDR(0x0C01)
+#define DANUBE_PPE_QSB_EMIT1 DANUBE_PPE_REG_ADDR(0x0C02)
+#define DANUBE_PPE_QSB_ICDV DANUBE_PPE_REG_ADDR(0x0C07)
+#define DANUBE_PPE_QSB_SBL DANUBE_PPE_REG_ADDR(0x0C09)
+#define DANUBE_PPE_QSB_CFG DANUBE_PPE_REG_ADDR(0x0C0A)
+#define DANUBE_PPE_QSB_RTM DANUBE_PPE_REG_ADDR(0x0C0B)
+#define DANUBE_PPE_QSB_RTD DANUBE_PPE_REG_ADDR(0x0C0C)
+#define DANUBE_PPE_QSB_RAMAC DANUBE_PPE_REG_ADDR(0x0C0D)
+#define DANUBE_PPE_QSB_ISTAT DANUBE_PPE_REG_ADDR(0x0C0E)
+#define DANUBE_PPE_QSB_IMR DANUBE_PPE_REG_ADDR(0x0C0F)
+#define DANUBE_PPE_QSB_SRC DANUBE_PPE_REG_ADDR(0x0C10)
+/*
+ * DSP User Registers
+ */
+#define DANUBE_PPE_DREG_A_VERSION DANUBE_PPE_REG_ADDR(0x0D00)
+#define DANUBE_PPE_DREG_A_CFG DANUBE_PPE_REG_ADDR(0x0D01)
+#define DANUBE_PPE_DREG_AT_CTRL DANUBE_PPE_REG_ADDR(0x0D02)
+#define DANUBE_PPE_DREG_AR_CTRL DANUBE_PPE_REG_ADDR(0x0D08)
+#define DANUBE_PPE_DREG_A_UTPCFG DANUBE_PPE_REG_ADDR(0x0D0E)
+#define DANUBE_PPE_DREG_A_STATUS DANUBE_PPE_REG_ADDR(0x0D0F)
+#define DANUBE_PPE_DREG_AT_CFG0 DANUBE_PPE_REG_ADDR(0x0D20)
+#define DANUBE_PPE_DREG_AT_CFG1 DANUBE_PPE_REG_ADDR(0x0D21)
+#define DANUBE_PPE_DREG_FB_SIZE0 DANUBE_PPE_REG_ADDR(0x0D22)
+#define DANUBE_PPE_DREG_FB_SIZE1 DANUBE_PPE_REG_ADDR(0x0D23)
+#define DANUBE_PPE_DREG_AT_CELL0 DANUBE_PPE_REG_ADDR(0x0D24)
+#define DANUBE_PPE_DREG_AT_CELL1 DANUBE_PPE_REG_ADDR(0x0D25)
+#define DANUBE_PPE_DREG_AT_IDLE_CNT0 DANUBE_PPE_REG_ADDR(0x0D26)
+#define DANUBE_PPE_DREG_AT_IDLE_CNT1 DANUBE_PPE_REG_ADDR(0x0D27)
+#define DANUBE_PPE_DREG_AT_IDLE0 DANUBE_PPE_REG_ADDR(0x0D28)
+#define DANUBE_PPE_DREG_AT_IDLE1 DANUBE_PPE_REG_ADDR(0x0D29)
+#define DANUBE_PPE_DREG_AR_CFG0 DANUBE_PPE_REG_ADDR(0x0D60)
+#define DANUBE_PPE_DREG_AR_CFG1 DANUBE_PPE_REG_ADDR(0x0D61)
+#define DANUBE_PPE_DREG_AR_FB_START0 DANUBE_PPE_REG_ADDR(0x0D62)
+#define DANUBE_PPE_DREG_AR_FB_START1 DANUBE_PPE_REG_ADDR(0x0D63)
+#define DANUBE_PPE_DREG_AR_FB_END0 DANUBE_PPE_REG_ADDR(0x0D64)
+#define DANUBE_PPE_DREG_AR_FB_END1 DANUBE_PPE_REG_ADDR(0x0D65)
+#define DANUBE_PPE_DREG_AR_ATM_STAT0 DANUBE_PPE_REG_ADDR(0x0D66)
+#define DANUBE_PPE_DREG_AR_ATM_STAT1 DANUBE_PPE_REG_ADDR(0x0D67)
+#define DANUBE_PPE_DREG_AR_CELL0 DANUBE_PPE_REG_ADDR(0x0D68)
+#define DANUBE_PPE_DREG_AR_CELL1 DANUBE_PPE_REG_ADDR(0x0D69)
+#define DANUBE_PPE_DREG_AR_IDLE_CNT0 DANUBE_PPE_REG_ADDR(0x0D6A)
+#define DANUBE_PPE_DREG_AR_IDLE_CNT1 DANUBE_PPE_REG_ADDR(0x0D6B)
+#define DANUBE_PPE_DREG_AR_AIIDLE_CNT0 DANUBE_PPE_REG_ADDR(0x0D6C)
+#define DANUBE_PPE_DREG_AR_AIIDLE_CNT1 DANUBE_PPE_REG_ADDR(0x0D6D)
+#define DANUBE_PPE_DREG_AR_BE_CNT0 DANUBE_PPE_REG_ADDR(0x0D6E)
+#define DANUBE_PPE_DREG_AR_BE_CNT1 DANUBE_PPE_REG_ADDR(0x0D6F)
+#define DANUBE_PPE_DREG_AR_HEC_CNT0 DANUBE_PPE_REG_ADDR(0x0D70)
+#define DANUBE_PPE_DREG_AR_HEC_CNT1 DANUBE_PPE_REG_ADDR(0x0D71)
+#define DANUBE_PPE_DREG_AR_CD_CNT0 DANUBE_PPE_REG_ADDR(0x0D72)
+#define DANUBE_PPE_DREG_AR_CD_CNT1 DANUBE_PPE_REG_ADDR(0x0D73)
+#define DANUBE_PPE_DREG_AR_IDLE0 DANUBE_PPE_REG_ADDR(0x0D74)
+#define DANUBE_PPE_DREG_AR_IDLE1 DANUBE_PPE_REG_ADDR(0x0D75)
+#define DANUBE_PPE_DREG_AR_DELIN0 DANUBE_PPE_REG_ADDR(0x0D76)
+#define DANUBE_PPE_DREG_AR_DELIN1 DANUBE_PPE_REG_ADDR(0x0D77)
+#define DANUBE_PPE_DREG_RESV0 DANUBE_PPE_REG_ADDR(0x0D78)
+#define DANUBE_PPE_DREG_RESV1 DANUBE_PPE_REG_ADDR(0x0D79)
+#define DANUBE_PPE_DREG_RX_MIB_CMD0 DANUBE_PPE_REG_ADDR(0x0D80)
+#define DANUBE_PPE_DREG_RX_MIB_CMD1 DANUBE_PPE_REG_ADDR(0x0D81)
+#define DANUBE_PPE_DREG_AR_OVDROP_CNT0 DANUBE_PPE_REG_ADDR(0x0D98)
+#define DANUBE_PPE_DREG_AR_OVDROP_CNT1 DANUBE_PPE_REG_ADDR(0x0D99)
+
+
+/************************************************************************/
+/* Module : PPE register address and bits */
+/************************************************************************/
+#define DANUBE_PPE32_BASE 0xBE180000
+#define DANUBE_PPE32_DEBUG_BREAK_TRACE_REG (DANUBE_PPE32_BASE + (0x0000 * 4))
+#define DANUBE_PPE32_INT_MASK_STATUS_REG (DANUBE_PPE32_BASE + (0x0030 * 4))
+#define DANUBE_PPE32_INT_RESOURCE_REG (DANUBE_PPE32_BASE + (0x0040 * 4))
+#define DANUBE_PPE32_CDM_CODE_MEM_B0 (DANUBE_PPE32_BASE + (0x1000 * 4))
+#define DANUBE_PPE32_CDM_CODE_MEM_B1 (DANUBE_PPE32_BASE + (0x2000 * 4))
+#define DANUBE_PPE32_DATA_MEM_MAP_REG_BASE (DANUBE_PPE32_BASE + (0x4000 * 4))
+
+/*
+ * ETOP MDIO Registers
+ */
+#define ETOP_MDIO_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0600 * 4)))
+#define ETOP_MDIO_ACC ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0601 * 4)))
+#define ETOP_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0602 * 4)))
+#define ETOP_IG_VLAN_COS ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0603 * 4)))
+#define ETOP_IG_DSCP_COS3 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0604 * 4)))
+#define ETOP_IG_DSCP_COS2 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0605 * 4)))
+#define ETOP_IG_DSCP_COS1 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0606 * 4)))
+#define ETOP_IG_DSCP_COS0 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0607 * 4)))
+#define ETOP_IG_PLEN_CTRL ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0608 * 4)))
+#define ETOP_ISR ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x060A * 4)))
+#define ETOP_IER ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x060B * 4)))
+#define ETOP_VPID ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x060C * 4)))
+#define ENET_MAC_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0610 * 4)))
+#define ENETS_DBA ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0612 * 4)))
+#define ENETS_CBA ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0613 * 4)))
+#define ENETS_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0614 * 4)))
+#define ENETS_PGCNT ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0615 * 4)))
+#define ENETS_PKTCNT ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0616 * 4)))
+#define ENETS_BUF_CTRL ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0617 * 4)))
+#define ENETS_COS_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0618 * 4)))
+#define ENETS_IGDROP ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0619 * 4)))
+#define ENETS_IGERR ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x061A * 4)))
+#define ENET_MAC_DA0 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x061B * 4)))
+#define ENET_MAC_DA1 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x061C * 4)))
+
+#define ENETF_DBA ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0630 * 4)))
+#define ENETF_CBA ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0631 * 4)))
+#define ENETF_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0632 * 4)))
+#define ENETF_PGCNT ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0633 * 4)))
+#define ENETF_PKTCNT ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0634 * 4)))
+#define ENETF_HFCTRL ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0635 * 4)))
+#define ENETF_TXCTRL ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0636 * 4)))
+
+#define ENETF_VLCOS0 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0638 * 4)))
+#define ENETF_VLCOS1 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0639 * 4)))
+#define ENETF_VLCOS2 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x063A * 4)))
+#define ENETF_VLCOS3 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x063B * 4)))
+#define ENETF_EGERR ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x063C * 4)))
+#define ENETF_EGDROP ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x063D * 4)))
+
+
+/*
+ * ETOP MDIO Registers
+ */
+#define DANUBE_PPE32_ETOP_MDIO_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0600 * 4)))
+#define DANUBE_PPE32_ETOP_MDIO_ACC ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0601 * 4)))
+#define DANUBE_PPE32_ETOP_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0602 * 4)))
+#define DANUBE_PPE32_ETOP_IG_VLAN_COS ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0603 * 4)))
+#define DANUBE_PPE32_ETOP_IG_DSCP_COS3 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0604 * 4)))
+#define DANUBE_PPE32_ETOP_IG_DSCP_COS2 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0605 * 4)))
+#define DANUBE_PPE32_ETOP_IG_DSCP_COS1 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0606 * 4)))
+#define DANUBE_PPE32_ETOP_IG_DSCP_COS0 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0607 * 4)))
+#define DANUBE_PPE32_ETOP_IG_PLEN_CTRL ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0608 * 4)))
+#define DANUBE_PPE32_ETOP_ISR ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x060A * 4)))
+#define DANUBE_PPE32_ETOP_IER ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x060B * 4)))
+#define DANUBE_PPE32_ETOP_VPID ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x060C * 4)))
+
+
+/* ENET Register */
+#define DANUBE_PPE32_ENET_MAC_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0610 * 4)))
+#define DANUBE_PPE32_ENET_IG_PKTDROP ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0619 * 4)))
+#define DANUBE_PPE32_ENET_CoS_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0618 * 4)))
+
+/*********LED register definition****************/
+
+#define DANUBE_LED 0xBE100BB0
+#define DANUBE_LED_CON0 ((volatile u32*)(DANUBE_LED + 0x0000))
+#define DANUBE_LED_CON1 ((volatile u32*)(DANUBE_LED + 0x0004))
+#define DANUBE_LED_CPU0 ((volatile u32*)(DANUBE_LED + 0x0008))
+#define DANUBE_LED_CPU1 ((volatile u32*)(DANUBE_LED + 0x000C))
+#define DANUBE_LED_AR ((volatile u32*)(DANUBE_LED + 0x0010))
+
+
+
+
+/***********************************************************************/
+#define DANUBE_REG32(addr) *((volatile u32 *)(addr))
+/***********************************************************************/
+#endif //DANUBE_H
diff --git a/package/uboot-lantiq/files/include/configs/arcadyan-common.h b/package/uboot-lantiq/files/include/configs/arcadyan-common.h
new file mode 100644
index 000000000..75f5c3863
--- /dev/null
+++ b/package/uboot-lantiq/files/include/configs/arcadyan-common.h
@@ -0,0 +1,146 @@
+/*
+ * (C) Copyright 2003-2005
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+/*
+ * This file contains the configuration parameters for the Danube reference board.
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define CONFIG_MIPS32 1 /* MIPS32 CPU compatible */
+#define CONFIG_MIPS24KEC 1 /* MIPS 24KEc CPU core */
+#define CONFIG_DANUBE 1 /* in a Danube/Twinpass Chip */
+
+#define CONFIG_SYS_MIPS_MULTI_CPU 1 /* This is a multi cpu system */
+
+#define CONFIG_USE_DDR_RAM
+
+#define CONFIG_FLASH_CFI_DRIVER 1
+
+#define CONFIG_SYS_INIT_RAM_LOCK_MIPS
+
+#ifdef CONFIG_SYS_RAMBOOT
+ //#warning CONFIG_SYS_RAMBOOT
+ #define CONFIG_SKIP_LOWLEVEL_INIT
+#else /* CONFIG_SYS_RAMBOOT */
+ #define CONFIG_SYS_EBU_BOOT
+ #define INFINEON_EBU_BOOTCFG 0x688C688C /* CMULT = 8 for 150 MHz */
+#endif /* CONFIG_SYS_RAMBOOT */
+
+#if 1
+#ifndef CPU_CLOCK_RATE
+#define CPU_CLOCK_RATE (ifx_get_cpuclk())
+#endif
+#endif
+
+#undef CONFIG_SYS_HUSH_PARSER /* Use the HUSH parser */
+
+/*
+ * Include common defines/options for all Infineon boards
+ */
+#include "ifx-common.h"
+
+
+#undef CONFIG_EXTRA_ENV_SETTINGS
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "ram_addr=0x80500000\0" \
+ "kernel_addr=0xb0020000\0" \
+ "flashargs=setenv bootargs rootfstype=squashfs,jffs2\0" \
+ "nfsargs=setenv bootargs root=/dev/nfs rw " \
+ "nfsroot=${serverip}:${rootpath} \0" \
+ "addip=setenv bootargs ${bootargs} " \
+ "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \
+ ":${hostname}:${netdev}:off\0" \
+ "addmisc=setenv bootargs ${bootargs} init=/etc/preinit " \
+ "console=ttyS1,115200 ethaddr=${ethaddr} " \
+ "${mtdparts}\0" \
+ "flash_flash=run flashargs addip addmisc;" \
+ "bootm ${kernel_addr}\0" \
+ "flash_nfs=run nfsargs addip addmisc;bootm ${kernel_addr}\0" \
+ "net_flash=run load_kernel flashargs addip addmisc;" \
+ "bootm ${ram_addr}\0" \
+ "net_nfs=run load_kernel nfsargs addip addmisc;" \
+ "bootm ${ram_addr}\0" \
+ "load_kernel=tftp ${ram_addr} " \
+ "${tftppath}openwrt-ifxmips-uImage\0" \
+ "update_uboot=tftp 0x80500000 ${tftppath}u-boot-" CONFIG_ARCADYAN ".bin;era 0xb0000000 +${filesize};" \
+ "cp.b 0x80500000 0xb0000000 ${filesize}\0" \
+ "update_openwrt=tftp ${ram_addr} " \
+ "${tftppath}" CONFIG_ARCADYAN "-squashfs.image;" \
+ "era ${kernel_addr} +${filesize};" \
+ "cp.b ${ram_addr} ${kernel_addr} ${filesize}\0"
+
+/*
+ * Cache Configuration (cpu/chip specific, Danube)
+ */
+#define CONFIG_SYS_DCACHE_SIZE 16384
+#define CONFIG_SYS_ICACHE_SIZE 16384
+#define CONFIG_SYS_CACHELINE_SIZE 32
+#define CONFIG_SYS_MIPS_CACHE_OPER_MODE CONF_CM_CACHABLE_NO_WA
+
+#define CONFIG_NET_MULTI
+
+#define CONFIG_IFX_ETOP
+//#define CLK_OUT2_25MHZ
+
+#define CONFIG_MII
+#undef CONFIG_CMD_MII
+
+#define CONFIG_IFX_ASC
+
+#ifdef CONFIG_USE_ASC0
+#define CONFIG_SYS_IFX_ASC_BASE 0x1E100400
+#else
+#define CONFIG_SYS_IFX_ASC_BASE 0x1E100C00
+#endif
+
+#ifdef CONFIG_SYS_RAMBOOT
+/* Configuration of EBU: */
+/* starting address from 0xb0000000 */
+/* make the flash available from RAM boot */
+# define CONFIG_EBU_ADDSEL0 0x10000031
+# define CONFIG_EBU_BUSCON0 0x0001D7FF
+# define CONFIG_EBU_ADDSEL1 0x14000001
+# define CONFIG_EBU_BUSCON1 0x4041D7FD
+#endif
+
+#define CONFIG_CMD_HTTPD /* enable upgrade via HTTPD */
+
+#define CONFIG_IPADDR 192.168.1.1
+#define CONFIG_SERVERIP 192.168.1.101
+#define CONFIG_GATEWAYIP 192.168.1.254
+#define CONFIG_NETMASK 255.255.255.0
+#define CONFIG_ROOTPATH "/export"
+
+#ifdef CONFIG_BOOTSTRAP
+#define CONFIG_BOOTSTRAP_BASE CONFIG_BOOTSTRAP_TEXT_BASE
+#define CONFIG_BOOTSTRAP_BAUDRATE CONFIG_BAUDRATE
+#define CONFIG_SKIP_LOWLEVEL_INIT
+#define CONFIG_BOOTSTRAP_LZMA
+//#define CONFIG_BOOTSTRAP_SERIAL
+#endif
+
+
+
+#endif /* __CONFIG_H */
diff --git a/package/uboot-lantiq/files/include/configs/arv3527P.h b/package/uboot-lantiq/files/include/configs/arv3527P.h
new file mode 100644
index 000000000..f282fc816
--- /dev/null
+++ b/package/uboot-lantiq/files/include/configs/arv3527P.h
@@ -0,0 +1,17 @@
+#ifndef __CONFIG_H_3527
+#define __CONFIG_H_3527
+
+#define CONFIG_ARV3527 1
+#define CONFIG_ARCADYAN "ARV3527P"
+
+#define CONFIG_SYS_MAX_RAM 32*1024*1024
+#define CONFIG_USE_DDR_PSC_32 1
+#define CONFIG_SYS_PROMPT "ARV3527 => "
+
+/*#define CONFIG_BUTTON_PORT1
+#define CONFIG_BUTTON_PIN 13
+#define CONFIG_BUTTON_LEVEL 0
+*/
+#include "arcadyan-common.h"
+
+#endif
diff --git a/package/uboot-lantiq/files/include/configs/arv4518PW.h b/package/uboot-lantiq/files/include/configs/arv4518PW.h
new file mode 100644
index 000000000..30bbf6e46
--- /dev/null
+++ b/package/uboot-lantiq/files/include/configs/arv4518PW.h
@@ -0,0 +1,16 @@
+#ifndef __CONFIG_H_4518
+#define __CONFIG_H_4518
+
+#define CONFIG_ARV4518 1
+#define CONFIG_ARCADYAN "ARV4518PW"
+
+#define CONFIG_SYS_MAX_RAM 64*1024*1024
+#define CONFIG_USE_DDR_PSC_64 1
+#define CONFIG_SYS_PROMPT "ARV4518 => "
+
+//#define CONFIG_RMII 1
+#define CONFIG_RTL8306_SWITCH 1
+
+#include "arcadyan-common.h"
+
+#endif
diff --git a/package/uboot-lantiq/files/include/configs/arv4519PW.h b/package/uboot-lantiq/files/include/configs/arv4519PW.h
new file mode 100644
index 000000000..1fbc361dc
--- /dev/null
+++ b/package/uboot-lantiq/files/include/configs/arv4519PW.h
@@ -0,0 +1,21 @@
+#ifndef __CONFIG_H_4519
+#define __CONFIG_H_4519
+
+#define CONFIG_ARV4519 1
+#define CONFIG_ARCADYAN "ARV4519PW"
+
+#define CONFIG_SYS_MAX_RAM 32*1024*1024
+#define CONFIG_USE_DDR_PSC_32 1
+#define CONFIG_SYS_PROMPT "ARV4519 => "
+
+#define CONFIG_AR8216_SWITCH 1
+#define CONFIG_EBU_GPIO 0
+#define CONFIG_SWITCH_PORT0
+#define CONFIG_SWITCH_PIN 13
+#define CONFIG_BUTTON_PORT1
+#define CONFIG_BUTTON_PIN 12
+#define CONFIG_BUTTON_LEVEL 0
+
+#include "arcadyan-common.h"
+
+#endif
diff --git a/package/uboot-lantiq/files/include/configs/arv4520PW.h b/package/uboot-lantiq/files/include/configs/arv4520PW.h
new file mode 100644
index 000000000..d4b130b9d
--- /dev/null
+++ b/package/uboot-lantiq/files/include/configs/arv4520PW.h
@@ -0,0 +1,20 @@
+#ifndef __CONFIG_H_4520
+#define __CONFIG_H_4520
+
+#define CONFIG_ARV4520 1
+#define CONFIG_ARCADYAN "ARV4520PW"
+
+#define CONFIG_SYS_MAX_RAM 32*1024*1024
+#define CONFIG_USE_DDR_PSC_32 1
+#define CONFIG_SYS_PROMPT "ARV4520 => "
+#define CONFIG_RMII 1
+#define CONFIG_ADM6996_SWITCH 1
+#define CONFIG_EBU_GPIO 0x400
+
+#define CONFIG_BUTTON_PORT0
+#define CONFIG_BUTTON_PIN 11
+#define CONFIG_BUTTON_LEVEL 0
+
+#include "arcadyan-common.h"
+
+#endif
diff --git a/package/uboot-lantiq/files/include/configs/arv4525PW.h b/package/uboot-lantiq/files/include/configs/arv4525PW.h
new file mode 100644
index 000000000..63e7d32b4
--- /dev/null
+++ b/package/uboot-lantiq/files/include/configs/arv4525PW.h
@@ -0,0 +1,18 @@
+#ifndef __CONFIG_H_4525
+#define __CONFIG_H_4525
+
+#define CONFIG_ARV4525 1
+#define CONFIG_ARCADYAN "ARV4525PW"
+
+#define CONFIG_SYS_MAX_RAM 32*1024*1024
+#define CONFIG_USE_DDR_PSC_32 1
+#define CONFIG_SYS_PROMPT "ARV4525 => "
+
+#define CONFIG_BUTTON_PORT1
+#define CONFIG_BUTTON_PIN 13
+#define CONFIG_BUTTON_LEVEL 0
+
+
+#include "arcadyan-common.h"
+
+#endif
diff --git a/package/uboot-lantiq/files/include/configs/arv452CPW.h b/package/uboot-lantiq/files/include/configs/arv452CPW.h
new file mode 100644
index 000000000..579105f97
--- /dev/null
+++ b/package/uboot-lantiq/files/include/configs/arv452CPW.h
@@ -0,0 +1,20 @@
+#ifndef __CONFIG_H_452C
+#define __CONFIG_H_452C
+
+#define CONFIG_ARV452C 1
+#define CONFIG_ARCADYAN "ARV452CPW"
+
+#define CONFIG_SYS_MAX_RAM 32*1024*1024
+#define CONFIG_USE_DDR_PSC_32 1
+#define CONFIG_SYS_PROMPT "ARV452c => "
+#define CONFIG_RMII 1
+#define CONFIG_RTL8306_SWITCH 1
+#define CONFIG_EBU_GPIO 0xf00
+
+#define CONFIG_BUTTON_PORT0
+#define CONFIG_BUTTON_PIN 11
+#define CONFIG_BUTTON_LEVEL 0
+
+#include "arcadyan-common.h"
+
+#endif
diff --git a/package/uboot-lantiq/files/include/configs/arv7518PW.h b/package/uboot-lantiq/files/include/configs/arv7518PW.h
new file mode 100644
index 000000000..5d65dbbf9
--- /dev/null
+++ b/package/uboot-lantiq/files/include/configs/arv7518PW.h
@@ -0,0 +1,16 @@
+#ifndef __CONFIG_H_7518
+#define __CONFIG_H_7518
+
+#define CONFIG_ARV7518 1
+#define CONFIG_ARCADYAN "ARV7518PW"
+
+#define CONFIG_SYS_MAX_RAM 64*1024*1024
+#define CONFIG_USE_DDR_PSC_64 1
+#define CONFIG_SYS_PROMPT "ARV7518 => "
+
+//#define CONFIG_RMII 1
+#define CONFIG_AR8216_SWITCH 1
+
+#include "arcadyan-common.h"
+
+#endif
diff --git a/package/uboot-lantiq/files/include/configs/arv7525PW.h b/package/uboot-lantiq/files/include/configs/arv7525PW.h
new file mode 100644
index 000000000..ffa59947b
--- /dev/null
+++ b/package/uboot-lantiq/files/include/configs/arv7525PW.h
@@ -0,0 +1,18 @@
+#ifndef __CONFIG_H_7525PW
+#define __CONFIG_H_7525PW
+
+#define CONFIG_ARV7525 1
+#define CONFIG_ARCADYAN "ARV7525PW"
+
+#define CONFIG_SYS_MAX_RAM 32*1024*1024
+#define CONFIG_USE_DDR_PSC_32 1
+#define CONFIG_SYS_PROMPT "ARV7525 => "
+
+#define CONFIG_BUTTON_PORT1
+#define CONFIG_BUTTON_PIN 13
+#define CONFIG_BUTTON_LEVEL 0
+
+
+#include "arcadyan-common.h"
+
+#endif
diff --git a/package/uboot-lantiq/files/include/configs/arv752DPW.h b/package/uboot-lantiq/files/include/configs/arv752DPW.h
new file mode 100644
index 000000000..594ce61e6
--- /dev/null
+++ b/package/uboot-lantiq/files/include/configs/arv752DPW.h
@@ -0,0 +1,19 @@
+#ifndef __CONFIG_H_752DPW
+#define __CONFIG_H_752DPW
+
+#define CONFIG_ARV752DPW 1
+#define CONFIG_ARCADYAN "ARV752DPW"
+
+#define CONFIG_SYS_MAX_RAM 64*1024*1024
+#define CONFIG_USE_DDR_PSC_64 1
+#define CONFIG_SYS_PROMPT "ARV752DPW => "
+
+#define CONFIG_RMII
+#define CONFIG_RTL8306G_SWITCH 1
+//#define CONFIG_EBU_GPIO 0x2
+//#define CONFIG_BUTTON_PORT0
+//#define CONFIG_BUTTON_PIN 12
+
+#include "arcadyan-common.h"
+
+#endif
diff --git a/package/uboot-lantiq/files/include/configs/arv752DPW22.h b/package/uboot-lantiq/files/include/configs/arv752DPW22.h
new file mode 100644
index 000000000..294628dbe
--- /dev/null
+++ b/package/uboot-lantiq/files/include/configs/arv752DPW22.h
@@ -0,0 +1,21 @@
+#ifndef __CONFIG_H_752DPW22
+#define __CONFIG_H_752DPW22
+
+#define CONFIG_ARV752DPW22 1
+#define CONFIG_ARCADYAN "ARV752DPW22"
+
+#define CONFIG_SYS_MAX_RAM 64*1024*1024
+#define CONFIG_USE_DDR_PSC_64 1
+#define CONFIG_SYS_PROMPT "ARV752DPW22 => "
+
+#define CONFIG_AR8216_SWITCH 1
+#define CONFIG_EBU_GPIO 0x2
+#define CONFIG_SWITCH_PORT1
+#define CONFIG_SWITCH_PIN 3
+#define CONFIG_BUTTON_PORT0
+#define CONFIG_BUTTON_PIN 13
+#define CONFIG_BUTTON_LEVEL 0
+
+#include "arcadyan-common.h"
+
+#endif
diff --git a/package/uboot-lantiq/files/include/configs/easy50712.h b/package/uboot-lantiq/files/include/configs/easy50712.h
new file mode 100644
index 000000000..8eeb6c06a
--- /dev/null
+++ b/package/uboot-lantiq/files/include/configs/easy50712.h
@@ -0,0 +1,117 @@
+/*
+ * (C) Copyright 2003-2005
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+/*
+ * This file contains the configuration parameters for the Danube reference board.
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/* #define DEBUG */
+
+#define CONFIG_MIPS32 1 /* MIPS32 CPU compatible */
+#define CONFIG_MIPS24KEC 1 /* MIPS 24KEc CPU core */
+#define CONFIG_DANUBE 1 /* in a Danube/Twinpass Chip */
+#define CONFIG_EASY50712 1 /* on the Danube Reference Board */
+
+#define CONFIG_SYS_MIPS_MULTI_CPU 1 /* This is a multi cpu system */
+
+#define CONFIG_SYS_MAX_RAM 32*1024*1024
+
+#define CONFIG_FLASH_CFI_DRIVER 1
+
+#define CONFIG_SYS_INIT_RAM_LOCK_MIPS
+#ifdef CONFIG_SYS_RAMBOOT
+ //#warning CONFIG_SYS_RAMBOOT
+ #define CONFIG_SKIP_LOWLEVEL_INIT
+#else /* CONFIG_SYS_RAMBOOT */
+
+ #define CONFIG_SYS_EBU_BOOT
+
+ #ifdef CONFIG_USE_DDR_RAM
+ /* FIXME: should not need these workarounds */
+ #define DANUBE_DDR_RAM_SIZE 32 /* 32M DDR-DRAM for reference board */
+ #endif
+
+ #define INFINEON_EBU_BOOTCFG 0x688C688C /* CMULT = 8 for 150 MHz */
+
+#endif /* CONFIG_SYS_RAMBOOT */
+
+#if 1
+#ifndef CPU_CLOCK_RATE
+#define CPU_CLOCK_RATE (ifx_get_cpuclk())
+#endif
+#endif
+
+#define CONFIG_SYS_PROMPT "DANUBE => " /* Monitor Command Prompt */
+
+#undef CONFIG_SYS_HUSH_PARSER /* Use the HUSH parser */
+
+/*
+ * Include common defines/options for all Infineon boards
+ */
+#include "ifx-common.h"
+
+/*
+ * Cache Configuration (cpu/chip specific, Danube)
+ */
+#define CONFIG_SYS_DCACHE_SIZE 16384
+#define CONFIG_SYS_ICACHE_SIZE 16384
+#define CONFIG_SYS_CACHELINE_SIZE 32
+#define CONFIG_SYS_MIPS_CACHE_OPER_MODE CONF_CM_CACHABLE_NO_WA
+
+#define CONFIG_NET_MULTI
+#if 0
+#define CONFIG_M4530_ETH
+#define CONFIG_M4530_FPGA
+#endif
+
+#define CONFIG_IFX_ETOP
+#define CLK_OUT2_25MHZ
+#define CONFIG_EXTRA_SWITCH
+
+#define CONFIG_RMII /* use interface in RMII mode */
+
+#define CONFIG_MII
+#define CONFIG_CMD_MII
+
+#define CONFIG_IFX_ASC
+
+#ifdef CONFIG_USE_ASC0
+#define CONFIG_SYS_IFX_ASC_BASE 0x1E100400
+#else
+#define CONFIG_SYS_IFX_ASC_BASE 0x1E100C00
+#endif
+
+#ifdef CONFIG_SYS_RAMBOOT
+/* Configuration of EBU: */
+/* starting address from 0xb0000000 */
+/* make the flash available from RAM boot */
+# define CONFIG_EBU_ADDSEL0 0x10000031
+# define CONFIG_EBU_BUSCON0 0x0001D7FF
+#endif
+
+#define CONFIG_CMD_HTTPD /* enable upgrade via HTTPD */
+
+#endif /* __CONFIG_H */
diff --git a/package/uboot-lantiq/files/include/configs/easy50812.h b/package/uboot-lantiq/files/include/configs/easy50812.h
new file mode 100644
index 000000000..c7e96c1bc
--- /dev/null
+++ b/package/uboot-lantiq/files/include/configs/easy50812.h
@@ -0,0 +1,104 @@
+/*
+ * (C) Copyright 2003-2005
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+/*
+ * This file contains the configuration parameters for the Danube reference board.
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/* #define DEBUG */
+
+#define CONFIG_MIPS32 1 /* MIPS32 CPU compatible */
+#define CONFIG_MIPS34KC 1 /* MIPS 34Kc CPU core */
+#define CONFIG_AR9 1 /* an AR9 device */
+#define CONFIG_EASY50812 1 /* on the AR9 reference board */
+#define CONFIG_SYS_MAX_RAM 32*1024*1024 /* 32 MB */
+#define CONFIG_FLASH_CFI_DRIVER 1 /* using CFI flash driver */
+
+#define CONFIG_SYS_INIT_RAM_LOCK_MIPS
+
+/* use PPL1 and fixed values for CPU / DDR and bus speed */
+#define CONFIG_USE_PLL1
+#define CONFIG_CPU_333M_RAM_166M
+#define CONFIG_CLASS_II_DDR_PAD
+
+#ifdef CONFIG_SYS_RAMBOOT
+ #define CONFIG_SKIP_LOWLEVEL_INIT /* no cache */
+#else
+ #define CONFIG_SYS_EBU_BOOT
+ #define INFINEON_EBU_BOOTCFG 0x688C688C /* CMULT = 8 for 150 MHz */
+#endif
+
+#ifndef CPU_CLOCK_RATE
+#define CPU_CLOCK_RATE (ifx_get_cpuclk())
+#endif
+
+#define CONFIG_SYS_PROMPT "AR9 => " /* Monitor Command Prompt */
+#undef CONFIG_SYS_HUSH_PARSER /* Use the HUSH parser */
+
+/*
+ * Include common defines/options for all Lantiq boards
+ */
+#include "ifx-common.h"
+
+/*
+ * Cache Configuration (cpu/chip specific, ar9)
+ */
+#define CONFIG_SYS_DCACHE_SIZE (16384)
+#define CONFIG_SYS_ICACHE_SIZE (16384)
+#define CONFIG_SYS_CACHELINE_SIZE (32)
+#define CONFIG_SYS_MIPS_CACHE_OPER_MODE CONF_CM_CACHABLE_NO_WA
+
+#define CONFIG_NET_MULTI
+#if 0
+#define CONFIG_M4530_ETH
+#define CONFIG_M4530_FPGA
+#endif
+
+#define CONFIG_IFX_ETOP /* lantiq ethernet cpe interface */
+#define CLK_OUT2_25MHZ
+#define CONFIG_EXTRA_SWITCH /* search for external switches like tantos */
+#define CONFIG_RMII /* use interface in RMII mode */
+#define CONFIG_MII
+#define CONFIG_CMD_MII /* enable MII command */
+
+#define CONFIG_IFX_ASC /* use lantiq ASC driver */
+#ifdef CONFIG_USE_ASC0
+#define CONFIG_SYS_IFX_ASC_BASE 0x1E100400
+#else
+#define CONFIG_SYS_IFX_ASC_BASE 0x1E100C00
+#endif
+
+#ifdef CONFIG_SYS_RAMBOOT
+/* Configuration of EBU: */
+/* starting address from 0xb0000000 */
+/* make the flash available from RAM boot */
+# define CONFIG_EBU_ADDSEL0 0x10000031
+# define CONFIG_EBU_BUSCON0 0x0001D7FF
+#endif
+
+#define CONFIG_CMD_HTTPD /* enable upgrade via HTTPD */
+
+#endif /* __CONFIG_H */
diff --git a/package/uboot-lantiq/files/include/configs/ifx-common.h b/package/uboot-lantiq/files/include/configs/ifx-common.h
new file mode 100644
index 000000000..4189031b9
--- /dev/null
+++ b/package/uboot-lantiq/files/include/configs/ifx-common.h
@@ -0,0 +1,192 @@
+/*
+ * (C) Copyright 2008
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * Common configuration options for all AMCC boards
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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 __IFX_COMMON_H
+#define __IFX_COMMON_H
+
+#define CONFIG_BOOTDELAY 2 /* autoboot after 5 seconds */
+
+#define CONFIG_BAUDRATE 115200
+
+/* valid baudrates */
+#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
+
+#define CONFIG_TIMESTAMP /* Print image info with timestamp */
+
+#undef CONFIG_PREBOOT
+
+#undef CONFIG_BOOTARGS
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "ram_addr=0x80500000\0" \
+ "kernel_addr=0xb0020000\0" \
+ "mtdparts=mtdparts=ifx-nor:256k(uboot)ro,64k(uboot_env)ro,64k(kernel),-(rootfs)\0" \
+ "flashargs=setenv bootargs rootfstype=squashfs,jffs2\0" \
+ "nfsargs=setenv bootargs root=/dev/nfs rw " \
+ "nfsroot=${serverip}:${rootpath} \0" \
+ "addip=setenv bootargs ${bootargs} " \
+ "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \
+ ":${hostname}:${netdev}:off\0" \
+ "addmisc=setenv bootargs ${bootargs} init=/etc/preinit " \
+ "console=ttyS1,115200 ethaddr=${ethaddr} " \
+ "${mtdparts}\0" \
+ "flash_flash=run flashargs addip addmisc;" \
+ "bootm ${kernel_addr}\0" \
+ "flash_nfs=run nfsargs addip addmisc;bootm ${kernel_addr}\0" \
+ "net_flash=run load_kernel flashargs addip addmisc;" \
+ "bootm ${ram_addr}\0" \
+ "net_nfs=run load_kernel nfsargs addip addmisc;" \
+ "bootm ${ram_addr}\0" \
+ "load_kernel=tftp ${ram_addr} " \
+ "${tftppath}openwrt-ifxmips-uImage\0" \
+ "update_uboot=tftp 0x80500000 ${tftppath}u-boot.bin;era 0xb0000000 +${filesize};" \
+ "cp.b 0x80500000 0xb0000000 ${filesize}\0" \
+ "update_openwrt=tftp ${ram_addr} " \
+ "${tftppath}openwrt-ifxmips-squashfs.image;" \
+ "era ${kernel_addr} +${filesize};" \
+ "cp.b ${ram_addr} ${kernel_addr} ${filesize}\0"
+
+#define CONFIG_BOOTCOMMAND "run flash_flash"
+
+/*
+ * TFTP is using fragmented packets
+*/
+#define CONFIG_IP_DEFRAG
+
+/*
+ * BOOTP options
+ */
+#define CONFIG_BOOTP_BOOTFILESIZE
+#define CONFIG_BOOTP_BOOTPATH
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_HOSTNAME
+
+
+/*
+ * Command line configuration.
+ */
+
+#define CONFIG_CMD_FLASH /* flinfo, erase, protect */
+#define CONFIG_CMD_MEMORY /* md mm nm mw cp cmp crc base loop mtest */
+#define CONFIG_CMD_NET /* bootp, tftpboot, rarpboot */
+#define CONFIG_CMD_RUN /* run command in env variable */
+#define CONFIG_CMD_SAVEENV /* saveenv */
+#define CONFIG_CMD_IMI
+#undef CONFIG_CMD_PING
+#undef CONFIG_ZLIB
+#undef CONFIG_GZIP
+#undef CONFIG_SYS_HUSH_PARSER
+
+/*
+ * Miscellaneous configurable options
+ */
+
+#define CONFIG_LZMA
+
+#undef CONFIG_SYS_LONGHELP /* undef to save memory */
+#ifndef CONFIG_SYS_PROMPT
+#define CONFIG_SYS_PROMPT "=> " /* Monitor Command Prompt */
+#endif
+#define CONFIG_SYS_CBSIZE 512 /* Console I/O Buffer Size */
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */
+#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
+
+#define CONFIG_SYS_MALLOC_LEN 1024*1024
+#define CONFIG_SYS_BOOTPARAMS_LEN 128*1024
+
+#define CONFIG_SYS_MIPS_TIMER_FREQ (CPU_CLOCK_RATE/2)
+#define CONFIG_SYS_HZ 1000
+
+#define CONFIG_SYS_SDRAM_BASE 0x80000000
+#define CONFIG_SYS_LOAD_ADDR 0x80100000 /* default load address */
+#define CONFIG_SYS_MEMTEST_START 0x80100000
+#define CONFIG_SYS_MEMTEST_END 0x80800000
+
+#define CONFIG_CMDLINE_EDITING /* add command line history */
+#undef CONFIG_AUTO_COMPLETE /* add autocompletion support */
+
+#define CONFIG_ZERO_BOOTDELAY_CHECK /* check for keypress on bootdelay==0 */
+#define CONFIG_VERSION_VARIABLE /* include version env variable */
+#define CONFIG_SYS_CONSOLE_INFO_QUIET /* don't print console @ startup*/
+
+#ifdef CONFIG_SYS_HUSH_PARSER
+#define CONFIG_SYS_PROMPT_HUSH_PS2 "> "
+#endif
+
+#define CONFIG_LOADS_ECHO /* echo on for serial download */
+#define CONFIG_SYS_LOADS_BAUD_CHANGE /* allow baudrate change */
+
+/*-----------------------------------------------------------------------
+ * FLASH and environment organization
+ */
+
+#define CONFIG_SYS_MAX_FLASH_BANKS_DETECT 1
+
+#define CONFIG_SYS_MAX_FLASH_BANKS 1 /* max number of memory banks */
+#define CONFIG_SYS_MAX_FLASH_SECT (140) /* max number of sectors on one chip */
+
+#define PHYS_FLASH_1 0xB0000000 /* Flash Bank #1 */
+#define PHYS_FLASH_2 0xB0800000 /* Flash Bank #2 */
+
+/* The following #defines are needed to get flash environment right */
+#define CONFIG_SYS_MONITOR_BASE TEXT_BASE
+#define CONFIG_SYS_MONITOR_LEN (192 << 10)
+
+#define CONFIG_SYS_INIT_SP_OFFSET 0x400000
+
+#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
+
+#define CONFIG_ENV_OVERWRITE 1
+#define CONFIG_ENV_IS_IN_FLASH 1
+
+/* Address and size of Primary Environment Sector */
+#define CONFIG_ENV_ADDR 0xB0010000
+#define CONFIG_ENV_SIZE 0x10000
+
+#ifdef CONFIG_FLASH_CFI_DRIVER
+#define CONFIG_SYS_FLASH_CFI
+#define CONFIG_SYS_FLASH_SWAP_ADDR
+#define CONFIG_FLASH_SHOW_PROGRESS 45
+
+#define CONFIG_SYS_FLASH_CFI_WIDTH FLASH_CFI_16BIT
+
+#define FLASH_FIXUP_ADDR_8(addr) ((void*)((ulong)(addr)^2))
+#define FLASH_FIXUP_ADDR_16(addr) ((void*)((ulong)(addr)^2))
+
+#endif
+
+#define CONFIG_NR_DRAM_BANKS 1
+
+#ifdef CONFIG_SYS_EBU_BOOT
+#ifndef INFINEON_EBU_BOOTCFG
+#error Please define INFINEON_EBU_BOOTCFG
+#endif
+#endif
+
+#ifdef CONFIG_BOOTSTRAP
+#define CONFIG_BOOTSTRAP_BASE CONFIG_BOOTSTRAP_TEXT_BASE
+#define CONFIG_BOOTSTRAP_BAUDRATE CONFIG_BAUDRATE
+#define CONFIG_SKIP_LOWLEVEL_INIT
+#define CONFIG_BOOTSTRAP_LZMA
+//#define CONFIG_BOOTSTRAP_SERIAL
+#endif
+
+#endif /* __IFX_COMMON_H */
diff --git a/package/uboot-lantiq/gct b/package/uboot-lantiq/gct
new file mode 100755
index 000000000..4054c15f5
--- /dev/null
+++ b/package/uboot-lantiq/gct
@@ -0,0 +1,165 @@
+#!/usr/bin/perl
+
+#use strict;
+#use Cwd;
+#use Env;
+
+my $aline;
+my $lineid;
+my $length;
+my $address;
+my @bytes;
+my $addstr;
+my $chsum=0;
+my $count=0;
+my $firstime=1;
+my $i;
+my $currentaddr;
+my $tmp;
+my $holder="";
+my $loadaddr;
+
+if(@ARGV < 2){
+ die("\n Syntax: ./program_SDRAM input1(memory setup) input2(*\.srec) output\n");
+}
+
+open(INFILE1, "<$ARGV[0]") || die("\ninput1 open fail\n");
+open(INFILE2, "<$ARGV[1]") || die("\ninput2 open fail\n");
+open(OUTFILE, ">$ARGV[2]") || die("\nOutput file open fail\n");
+
+$i=0;
+while ($line = <INFILE1>){
+ if($line=~/\w/){
+ if($line!~/[;#\*]/){
+ if($i eq 0){
+ printf OUTFILE ("33333333");
+ }
+ chomp($line);
+ $line=~s/\t//;
+ @array=split(/ +/,$line);
+ $j=0;
+ while(@array[$j]!~/\w/){
+ $j=$j+1;
+ }
+ $addr=@array[$j];
+ $regval=@array[$j+1];
+ $addr=~s/0x//;
+ $regval=~s/0x//;
+ printf OUTFILE ("%08x%08x",hex($addr),hex($regval));
+ $i=$i+1;
+ if($i eq 8){
+ $i=0;
+ printf OUTFILE ("\n");
+ }
+ }
+ }
+}
+
+while($i lt 8 && $i gt 0){
+ printf OUTFILE "00"x8;
+ $i=$i+1;
+}
+
+if($i eq 8){
+ printf OUTFILE ("\n");
+}
+
+while($aline=<INFILE2>){
+ $aline=uc($aline);
+ chomp($aline);
+ next if(($aline=~/^S0/) || ($aline=~/^S7/));
+ ($lineid, $length, $address, @bytes) = unpack"A2A2A8"."A2"x300, $aline;
+ $length = hex($length);
+ $address = hex($address);
+ $length -=5;
+ $i=0;
+
+ while($length>0){
+ if($firstime==1){
+ $addstr = sprintf("%x", $address);
+ $addstr = "0"x(8-length($addstr)).$addstr;
+ print OUTFILE $addstr;
+ addchsum($addstr);
+ $firstime=0;
+ $currentaddr=$address;
+ $loadaddr = $addstr;
+ }
+ else{
+ if($count==64){
+ $addstr = sprintf("%x", $currentaddr);
+ $addstr = "0"x(8-length($addstr)).$addstr;
+ print OUTFILE $addstr;
+ addchsum($addstr);
+ $count=0;
+ }
+ #printf("*** %x != %x\n", $address, $currentaddr) if $address != $currentaddr;
+ }
+ if($currentaddr < $address) {
+ print OUTFILE "00";
+ addchsum("00");
+ $count++;
+ $currentaddr++;
+ }
+ else {
+ while($count<64){
+ $bytes[$i]=~tr/ABCDEF/abcdef/;
+ print OUTFILE "$bytes[$i]";
+ addchsum($bytes[$i]);
+ $i++;
+ $count++;
+ $currentaddr++;
+ $length--;
+ last if($length==0);
+ }
+ }
+ if($count==64){
+ print OUTFILE "\n";
+ #print OUTFILE "\r";
+ }
+ }
+}
+if($count != 64){
+ $tmp = "00";
+ for($i=0;$i<(64-$count);$i++){
+ print OUTFILE "00";
+ addchsum($tmp);
+ }
+ print OUTFILE "\n";
+ #print OUTFILE "\r";
+}
+
+
+print OUTFILE "11"x4;
+use integer;
+$chsum=$chsum & 0xffffffff;
+$chsum = sprintf("%X", $chsum);
+$chsum = "0"x(8-length($chsum)).$chsum;
+$chsum =~tr/ABCDEF/abcdef/;
+print OUTFILE $chsum;
+print OUTFILE "00"x60;
+print OUTFILE "\n";
+#print OUTFILE "\r";
+
+print OUTFILE "99"x4;
+print OUTFILE $loadaddr;
+print OUTFILE "00"x60;
+print OUTFILE "\n";
+#print OUTFILE "\r";
+
+
+close OUTFILE;
+#END of Program
+
+
+
+sub addchsum{
+ my $cc=$_[0];
+ $holder=$holder.$cc;
+ if(length($holder)==8){
+ $holder = hex($holder);
+ $chsum+=$holder;
+ $holder="";
+ }
+}
+#END
+
diff --git a/package/uboot-lantiq/patches/000-build-infos.patch b/package/uboot-lantiq/patches/000-build-infos.patch
new file mode 100644
index 000000000..bd185d9b5
--- /dev/null
+++ b/package/uboot-lantiq/patches/000-build-infos.patch
@@ -0,0 +1,60 @@
+Add output like in linux kernel for current compiled file
+Used normaly in combination with make option -s
+
+Like in following example:
+
+$ make -s V=1
+[CC] tools/img2srec.c
+[CC] tools/bmp_logo.c
+[CC] examples/hello_world.c
+
+--- a/config.mk
++++ b/config.mk
+@@ -234,17 +234,47 @@ export TEXT_BASE PLATFORM_CPPFLAGS PLATF
+
+ #########################################################################
+
++ifndef KBUILD_VERBOSE
++ KBUILD_VERBOSE:=0
++endif
++ifeq ("$(origin V)", "command line")
++ KBUILD_VERBOSE:=$(V)
++endif
++ifeq (,$(findstring s,$(MAKEFLAGS)))
++ KBUILD_VERBOSE:=0
++endif
++
++ifneq ($(KBUILD_VERBOSE),0)
++ define MESSAGE
++ @printf " %s %s/%s\n" $(1) $(2) $(3)
++ endef
++else
++ define MESSAGE
++ endef
++endif
++
+ # Allow boards to use custom optimize flags on a per dir/file basis
+ BCURDIR := $(notdir $(CURDIR))
++
+ $(obj)%.s: %.S
++ $(call MESSAGE, [CPP],$(subst $(SRCTREE)/,,$(CURDIR)),$<)
++ #echo $(CPP) $(AFLAGS) $(AFLAGS_$(@F)) $(AFLAGS_$(BCURDIR)) -o $@ $<
+ $(CPP) $(AFLAGS) $(AFLAGS_$(@F)) $(AFLAGS_$(BCURDIR)) -o $@ $<
+ $(obj)%.o: %.S
++ $(call MESSAGE, [AS], $(subst $(SRCTREE)/,,$(CURDIR)),$<)
++ #echo $(CC) $(AFLAGS) $(AFLAGS_$(@F)) $(AFLAGS_$(BCURDIR)) -o $@ $< -c
+ $(CC) $(AFLAGS) $(AFLAGS_$(@F)) $(AFLAGS_$(BCURDIR)) -o $@ $< -c
+ $(obj)%.o: %.c
++ $(call MESSAGE, [CC], $(subst $(SRCTREE)/,,$(CURDIR)),$<)
++ #echo $(CC) $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c
+ $(CC) $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c
+ $(obj)%.i: %.c
++ $(call MESSAGE, [CPP],$(subst $(SRCTREE)/,,$(CURDIR)),$<)
++ #echo $(CPP) $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c
+ $(CPP) $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c
+ $(obj)%.s: %.c
++ $(call MESSAGE, [CC], $(subst $(SRCTREE)/,,$(CURDIR)),$<)
++ #echo $(CC) $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c -S
+ $(CC) $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c -S
+
+ #########################################################################
diff --git a/package/uboot-lantiq/patches/010-fix-mips-flags.patch b/package/uboot-lantiq/patches/010-fix-mips-flags.patch
new file mode 100644
index 000000000..6dd7d8f56
--- /dev/null
+++ b/package/uboot-lantiq/patches/010-fix-mips-flags.patch
@@ -0,0 +1,25 @@
+--- a/cpu/mips/config.mk
++++ b/cpu/mips/config.mk
+@@ -23,17 +23,19 @@
+ v=$(shell $(AS) --version | grep 'GNU assembler' | egrep -o '2\.[0-9\.]+' | cut -d. -f2)
+ MIPSFLAGS:=$(shell \
+ if [ "$v" -lt "14" ]; then \
+- echo "-mcpu=4kc"; \
++ echo "-mcpu=mips32"; \
+ else \
+- echo "-march=4kc -mtune=4kc"; \
++ echo "-mips32 -march=mips32 -mtune=mips32"; \
+ fi)
+
++ifndef ENDIANNESS
+ ifneq (,$(findstring 4KCle,$(CROSS_COMPILE)))
+ ENDIANNESS = -EL
+ else
+ ENDIANNESS = -EB
+ endif
++endif
+
+-MIPSFLAGS += $(ENDIANNESS)
++MIPSFLAGS += $(ENDIANNESS) -fno-schedule-insns -fno-schedule-insns2
+
+ PLATFORM_CPPFLAGS += $(MIPSFLAGS)
diff --git a/package/uboot-lantiq/patches/020-mips-enhancements.patch b/package/uboot-lantiq/patches/020-mips-enhancements.patch
new file mode 100644
index 000000000..d05646770
--- /dev/null
+++ b/package/uboot-lantiq/patches/020-mips-enhancements.patch
@@ -0,0 +1,124 @@
+--- a/cpu/mips/start.S
++++ b/cpu/mips/start.S
+@@ -69,6 +69,9 @@ _start:
+ #elif defined(CONFIG_PURPLE)
+ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
+ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
++#elif defined(CONFIG_SYS_EBU_BOOT)
++ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
++ .word 0x00000000 /* phase of the flash */
+ #else
+ RVECENT(romReserved,2)
+ #endif
+@@ -202,7 +205,25 @@ _start:
+ * 128 * 8 == 1024 == 0x400
+ * so this is address R_VEC+0x400 == 0xbfc00400
+ */
+-#ifdef CONFIG_PURPLE
++#ifndef CONFIG_PURPLE
++ XVECENT(romExcHandle,0x400); /* bfc00400: Int, CauseIV=1 */
++ RVECENT(romReserved,129);
++ RVECENT(romReserved,130);
++ RVECENT(romReserved,131);
++ RVECENT(romReserved,132);
++ RVECENT(romReserved,133);
++ RVECENT(romReserved,134);
++ RVECENT(romReserved,135);
++ RVECENT(romReserved,136);
++ RVECENT(romReserved,137);
++ RVECENT(romReserved,138);
++ RVECENT(romReserved,139);
++ RVECENT(romReserved,140);
++ RVECENT(romReserved,141);
++ RVECENT(romReserved,142);
++ RVECENT(romReserved,143);
++ XVECENT(romExcHandle,0x480); /* bfc00480: EJTAG debug exception */
++#else /* CONFIG_PURPLE */
+ /* 0xbfc00400 */
+ .word 0xdc870000
+ .word 0xfca70000
+@@ -228,6 +249,12 @@ _start:
+ #endif /* CONFIG_PURPLE */
+ .align 4
+ reset:
++#ifdef CONFIG_SYS_MIPS_MULTI_CPU
++ mfc0 k0, CP0_EBASE
++ and k0, EBASEF_CPUNUM
++ bne k0, zero, ifx_mips_handler_cpux
++ nop
++#endif
+
+ /* Clear watch registers.
+ */
+@@ -239,6 +266,16 @@ reset:
+
+ setup_c0_status_reset
+
++#if defined(CONFIG_MIPS24KEC) || defined(CONFIG_MIPS34KC)
++ /* CONFIG7 register */
++ /* Erratum "RPS May Cause Incorrect Instruction Execution"
++ * for 24KEC and 34KC */
++ mfc0 k0, CP0_CONFIG, 7
++ li k1, MIPS_CONF7_RPS
++ or k0, k1
++ mtc0 k0, CP0_CONFIG, 7
++#endif
++
+ /* Init Timer */
+ mtc0 zero, CP0_COUNT
+ mtc0 zero, CP0_COMPARE
+@@ -270,9 +307,12 @@ reset:
+ jalr t9
+ nop
+
++#ifndef CONFIG_SYS_MIPS_CACHE_OPER_MODE
++#define CONFIG_SYS_MIPS_CACHE_OPER_MODE CONF_CM_CACHABLE_NONCOHERENT
++#endif
+ /* ... and enable them.
+ */
+- li t0, CONF_CM_CACHABLE_NONCOHERENT
++ li t0, CONFIG_SYS_MIPS_CACHE_OPER_MODE
+ mtc0 t0, CP0_CONFIG
+ #endif /* !CONFIG_SKIP_LOWLEVEL_INIT */
+
+@@ -419,3 +459,15 @@ romReserved:
+
+ romExcHandle:
+ b romExcHandle
++
++ /* Additional handlers.
++ */
++#ifdef CONFIG_SYS_MIPS_MULTI_CPU
++/*
++ * Stop Slave CPUs
++ */
++ifx_mips_handler_cpux:
++ wait;
++ b ifx_mips_handler_cpux;
++ nop;
++#endif
+--- a/include/asm-mips/mipsregs.h
++++ b/include/asm-mips/mipsregs.h
+@@ -57,6 +57,7 @@
+ #define CP0_CAUSE $13
+ #define CP0_EPC $14
+ #define CP0_PRID $15
++#define CP0_EBASE $15,1
+ #define CP0_CONFIG $16
+ #define CP0_LLADDR $17
+ #define CP0_WATCHLO $18
+@@ -395,6 +396,14 @@
+ #define CAUSEF_BD (_ULCAST_(1) << 31)
+
+ /*
++ * Bits in the coprocessor 0 EBase register
++ */
++#define EBASEB_CPUNUM 0
++#define EBASEF_CPUNUM (0x3ff << EBASEB_CPUNUM)
++#define EBASEB_EXPBASE 12
++#define EBASEF_EXPBASE (0x3ffff << EBASEB_EXPBASE)
++
++/*
+ * Bits in the coprocessor 0 config register.
+ */
+ /* Generic bits. */
diff --git a/package/uboot-lantiq/patches/030-cfi-addr-fixup.patch b/package/uboot-lantiq/patches/030-cfi-addr-fixup.patch
new file mode 100644
index 000000000..8f95da1f7
--- /dev/null
+++ b/package/uboot-lantiq/patches/030-cfi-addr-fixup.patch
@@ -0,0 +1,225 @@
+--- a/drivers/mtd/cfi_flash.c
++++ b/drivers/mtd/cfi_flash.c
+@@ -85,6 +85,22 @@ flash_info_t flash_info[CFI_MAX_FLASH_BA
+ #define CONFIG_SYS_FLASH_CFI_WIDTH FLASH_CFI_8BIT
+ #endif
+
++/*
++ * Check if address fixup macros are defined, define defaults otherwise
++ */
++#ifndef FLASH_FIXUP_ADDR_8
++#define FLASH_FIXUP_ADDR_8(addr) (addr)
++#endif
++#ifndef FLASH_FIXUP_ADDR_16
++#define FLASH_FIXUP_ADDR_16(addr) (addr)
++#endif
++#ifndef FLASH_FIXUP_ADDR_32
++#define FLASH_FIXUP_ADDR_32(addr) (addr)
++#endif
++#ifndef FLASH_FIXUP_ADDR_64
++#define FLASH_FIXUP_ADDR_64(addr) (addr)
++#endif
++
+ static void __flash_write8(u8 value, void *addr)
+ {
+ __raw_writeb(value, addr);
+@@ -264,9 +280,9 @@ static inline uchar flash_read_uchar (fl
+
+ cp = flash_map (info, 0, offset);
+ #if defined(__LITTLE_ENDIAN) || defined(CONFIG_SYS_WRITE_SWAPPED_DATA)
+- retval = flash_read8(cp);
++ retval = flash_read8(FLASH_FIXUP_ADDR_8(cp));
+ #else
+- retval = flash_read8(cp + info->portwidth - 1);
++ retval = flash_read8(FLASH_FIXUP_ADDR_8(cp) + info->portwidth - 1);
+ #endif
+ flash_unmap (info, 0, offset, cp);
+ return retval;
+@@ -280,7 +296,7 @@ static inline ushort flash_read_word (fl
+ ushort *addr, retval;
+
+ addr = flash_map (info, 0, offset);
+- retval = flash_read16 (addr);
++ retval = flash_read16 (FLASH_FIXUP_ADDR_16(addr));
+ flash_unmap (info, 0, offset, addr);
+ return retval;
+ }
+@@ -305,19 +321,28 @@ static ulong flash_read_long (flash_info
+ debug ("long addr is at %p info->portwidth = %d\n", addr,
+ info->portwidth);
+ for (x = 0; x < 4 * info->portwidth; x++) {
+- debug ("addr[%x] = 0x%x\n", x, flash_read8(addr + x));
++ debug ("addr[%x] = 0x%x\n", x,
++ flash_read8(FLASH_FIXUP_ADDR_32(addr) + x));
+ }
+ #endif
+ #if defined(__LITTLE_ENDIAN) || defined(CONFIG_SYS_WRITE_SWAPPED_DATA)
+- retval = ((flash_read8(addr) << 16) |
+- (flash_read8(addr + info->portwidth) << 24) |
+- (flash_read8(addr + 2 * info->portwidth)) |
+- (flash_read8(addr + 3 * info->portwidth) << 8));
++ retval = ((flash_read8(FLASH_FIXUP_ADDR_8
++ (addr) << 16) |
++ (flash_read8(FLASH_FIXUP_ADDR_8
++ (addr + info->portwidth)) << 24) |
++ (flash_read8(FLASH_FIXUP_ADDR_8
++ (addr + 2 * info->portwidth))) |
++ (flash_read8(FLASH_FIXUP_ADDR_8
++ (addr + 3 * info->portwidth)) << 8));
+ #else
+- retval = ((flash_read8(addr + 2 * info->portwidth - 1) << 24) |
+- (flash_read8(addr + info->portwidth - 1) << 16) |
+- (flash_read8(addr + 4 * info->portwidth - 1) << 8) |
+- (flash_read8(addr + 3 * info->portwidth - 1)));
++ retval = ((flash_read8(FLASH_FIXUP_ADDR_8
++ (addr + 2 * info->portwidth - 1)) << 24) |
++ (flash_read8(FLASH_FIXUP_ADDR_8
++ (addr + info->portwidth - 1)) << 16) |
++ (flash_read8(FLASH_FIXUP_ADDR_8
++ (addr + 4 * info->portwidth - 1)) << 8) |
++ (flash_read8(FLASH_FIXUP_ADDR_8
++ (addr + 3 * info->portwidth - 1))));
+ #endif
+ flash_unmap(info, sect, offset, addr);
+
+@@ -338,21 +363,22 @@ void flash_write_cmd (flash_info_t * inf
+ flash_make_cmd (info, cmd, &cword);
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+- debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", addr, cmd,
+- cword.c, info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+- flash_write8(cword.c, addr);
++ debug ("fwc addr %p cmd %x %x 8bit x %d bit\n",
++ FLASH_FIXUP_ADDR_8(addr), cmd, cword.c,
++ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
++ flash_write8(cword.c, FLASH_FIXUP_ADDR_8(addr));
+ break;
+ case FLASH_CFI_16BIT:
+- debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", addr,
+- cmd, cword.w,
++ debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n",
++ FLASH_FIXUP_ADDR_16(addr), cmd, cword.w,
+ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+- flash_write16(cword.w, addr);
++ flash_write16(cword.w, FLASH_FIXUP_ADDR_16(addr));
+ break;
+ case FLASH_CFI_32BIT:
+- debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", addr,
+- cmd, cword.l,
++ debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n",
++ FLASH_FIXUP_ADDR_32(addr), cmd, cword.l,
+ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+- flash_write32(cword.l, addr);
++ flash_write32(cword.l, FLASH_FIXUP_ADDR_32(addr));
+ break;
+ case FLASH_CFI_64BIT:
+ #ifdef DEBUG
+@@ -362,11 +388,11 @@ void flash_write_cmd (flash_info_t * inf
+ print_longlong (str, cword.ll);
+
+ debug ("fwrite addr %p cmd %x %s 64 bit x %d bit\n",
+- addr, cmd, str,
++ FLASH_FIXUP_ADDR_64(addr), cmd, str,
+ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+ }
+ #endif
+- flash_write64(cword.ll, addr);
++ flash_write64(cword.ll, FLASH_FIXUP_ADDR_64(addr));
+ break;
+ }
+
+@@ -397,16 +423,19 @@ static int flash_isequal (flash_info_t *
+ debug ("is= cmd %x(%c) addr %p ", cmd, cmd, addr);
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+- debug ("is= %x %x\n", flash_read8(addr), cword.c);
+- retval = (flash_read8(addr) == cword.c);
++ debug ("is= %x %x\n",
++ flash_read8(FLASH_FIXUP_ADDR_8(addr)), cword.c);
++ retval = (flash_read8(FLASH_FIXUP_ADDR_8(addr)) == cword.c);
+ break;
+ case FLASH_CFI_16BIT:
+- debug ("is= %4.4x %4.4x\n", flash_read16(addr), cword.w);
+- retval = (flash_read16(addr) == cword.w);
++ debug ("is= %4.4x %4.4x\n",
++ flash_read16(FLASH_FIXUP_ADDR_16(addr)), cword.w);
++ retval = (flash_read16(FLASH_FIXUP_ADDR_16(addr)) == cword.w);
+ break;
+ case FLASH_CFI_32BIT:
+- debug ("is= %8.8x %8.8lx\n", flash_read32(addr), cword.l);
+- retval = (flash_read32(addr) == cword.l);
++ debug ("is= %8.8x %8.8lx\n",
++ flash_read32(FLASH_FIXUP_ADDR_32(addr)), cword.l);
++ retval = (flash_read32(FLASH_FIXUP_ADDR_32(addr)) == cword.l);
+ break;
+ case FLASH_CFI_64BIT:
+ #ifdef DEBUG
+@@ -414,12 +443,13 @@ static int flash_isequal (flash_info_t *
+ char str1[20];
+ char str2[20];
+
+- print_longlong (str1, flash_read64(addr));
++ print_longlong (str1, flash_read64(FLASH_FIXUP_ADDR_64
++ (addr)));
+ print_longlong (str2, cword.ll);
+ debug ("is= %s %s\n", str1, str2);
+ }
+ #endif
+- retval = (flash_read64(addr) == cword.ll);
++ retval = (flash_read64(FLASH_FIXUP_ADDR_64(addr)) == cword.ll);
+ break;
+ default:
+ retval = 0;
+@@ -443,16 +473,20 @@ static int flash_isset (flash_info_t * i
+ flash_make_cmd (info, cmd, &cword);
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+- retval = ((flash_read8(addr) & cword.c) == cword.c);
++ retval = ((flash_read8(FLASH_FIXUP_ADDR_8(addr))
++ & cword.c) == cword.c);
+ break;
+ case FLASH_CFI_16BIT:
+- retval = ((flash_read16(addr) & cword.w) == cword.w);
++ retval = ((flash_read16(FLASH_FIXUP_ADDR_16(addr))
++ & cword.w) == cword.w);
+ break;
+ case FLASH_CFI_32BIT:
+- retval = ((flash_read32(addr) & cword.l) == cword.l);
++ retval = ((flash_read32(FLASH_FIXUP_ADDR_32(addr))
++ & cword.l) == cword.l);
+ break;
+ case FLASH_CFI_64BIT:
+- retval = ((flash_read64(addr) & cword.ll) == cword.ll);
++ retval = ((flash_read64(FLASH_FIXUP_ADDR_64(addr))
++ & cword.ll) == cword.ll);
+ break;
+ default:
+ retval = 0;
+@@ -476,17 +510,22 @@ static int flash_toggle (flash_info_t *
+ flash_make_cmd (info, cmd, &cword);
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+- retval = flash_read8(addr) != flash_read8(addr);
++ retval = flash_read8(FLASH_FIXUP_ADDR_8(addr)) !=
++ flash_read8(FLASH_FIXUP_ADDR_8(addr));
+ break;
+ case FLASH_CFI_16BIT:
+- retval = flash_read16(addr) != flash_read16(addr);
++ retval = flash_read16(FLASH_FIXUP_ADDR_16(addr)) !=
++ flash_read16(FLASH_FIXUP_ADDR_16(addr));
+ break;
+ case FLASH_CFI_32BIT:
+- retval = flash_read32(addr) != flash_read32(addr);
++ retval = flash_read32(FLASH_FIXUP_ADDR_32(addr)) !=
++ flash_read32(FLASH_FIXUP_ADDR_32(addr));
+ break;
+ case FLASH_CFI_64BIT:
+- retval = ( (flash_read32( addr ) != flash_read32( addr )) ||
+- (flash_read32(addr+4) != flash_read32(addr+4)) );
++ retval = ( (flash_read32(FLASH_FIXUP_ADDR_64( addr )) !=
++ flash_read32(FLASH_FIXUP_ADDR_64( addr ))) ||
++ (flash_read32(FLASH_FIXUP_ADDR_64(addr+4)) !=
++ flash_read32(FLASH_FIXUP_ADDR_64(addr+4))) );
+ break;
+ default:
+ retval = 0;
diff --git a/package/uboot-lantiq/patches/040-compile.patch b/package/uboot-lantiq/patches/040-compile.patch
new file mode 100644
index 000000000..c00230069
--- /dev/null
+++ b/package/uboot-lantiq/patches/040-compile.patch
@@ -0,0 +1,20 @@
+--- a/common/env_common.c
++++ b/common/env_common.c
+@@ -26,6 +26,7 @@
+
+ #include <common.h>
+ #include <command.h>
++#include <configs/ifx-common.h>
+ #include <environment.h>
+ #include <linux/stddef.h>
+ #include <malloc.h>
+--- a/common/env_embedded.c
++++ b/common/env_embedded.c
+@@ -27,6 +27,7 @@
+ #define __ASM_STUB_PROCESSOR_H__ /* don't include asm/processor. */
+ #include <config.h>
+ #undef __ASSEMBLY__
++#include <configs/ifx-common.h>
+ #include <environment.h>
+
+ /*
diff --git a/package/uboot-lantiq/patches/050-portability.patch b/package/uboot-lantiq/patches/050-portability.patch
new file mode 100644
index 000000000..ae38ad68e
--- /dev/null
+++ b/package/uboot-lantiq/patches/050-portability.patch
@@ -0,0 +1,31 @@
+--- a/tools/kwbimage.c
++++ b/tools/kwbimage.c
+@@ -206,6 +206,28 @@ INVL_DATA:
+ exit (EXIT_FAILURE);
+ }
+
++#ifndef __GLIBC__
++static ssize_t
++getline(char **line, size_t *len, FILE *fd)
++{
++ char *tmp;
++ int tmplen;
++
++ tmp = fgetln(fd, &tmplen);
++ if (!tmp)
++ return -1;
++
++ if (!*line || tmplen > *len) {
++ *len = tmplen + 1;
++ *line = realloc(*line, *len);
++ }
++
++ strncpy(*line, tmp, tmplen);
++ line[tmplen] = 0;
++ return tmplen;
++}
++#endif
++
+ /*
+ * this function sets the kwbimage header by-
+ * 1. Abstracting input command line arguments data
diff --git a/package/uboot-lantiq/patches/100-ifx_targets.patch b/package/uboot-lantiq/patches/100-ifx_targets.patch
new file mode 100644
index 000000000..dcd931cb8
--- /dev/null
+++ b/package/uboot-lantiq/patches/100-ifx_targets.patch
@@ -0,0 +1,135 @@
+--- a/MAKEALL
++++ b/MAKEALL
+@@ -730,6 +730,12 @@
+ ## MIPS Systems (default = big endian)
+ #########################################################################
+
++LIST_ifxcpe=" \
++ easy50712 \
++ easy50712_DDR166M \
++ easy50712_DDR166M_ramboot \
++"
++
+ LIST_mips4kc=" \
+ incaip \
+ qemu_mips \
+@@ -761,6 +767,7 @@
+ "
+
+ LIST_mips=" \
++ ${LIST_ifxcpe} \
+ ${LIST_mips4kc} \
+ ${LIST_mips5kc} \
+ ${LIST_au1xx0} \
+--- a/Makefile
++++ b/Makefile
+@@ -447,7 +447,7 @@
+ set -e ; \
+ : Extract the config macros ; \
+ $(CPP) $(CFLAGS) -DDO_DEPS_ONLY -dM include/common.h | \
+- sed -n -f tools/scripts/define2mk.sed > $@.tmp && \
++ sed -n -f tools/scripts/define2mk.sed |sort > $@.tmp && \
+ mv $@.tmp $@
+
+ #########################################################################
+@@ -3370,7 +3370,7 @@
+ { echo "#define CPU_CLOCK_RATE 150000000" >>$(obj)include/config.h ; \
+ $(XECHO) "... with 150MHz system clock" ; \
+ }
+- @$(MKCONFIG) -a $(call xtract_incaip,$@) mips mips incaip
++ @$(MKCONFIG) -a $(call xtract_incaip,$@) mips mips incaip infineon
+
+ tb0229_config: unconfig
+ @$(MKCONFIG) $(@:_config=) mips mips tb0229
+@@ -3411,6 +3411,53 @@
+ @$(MKCONFIG) -a vct mips mips vct micronas
+
+ #########################################################################
++## MIPS32 ifxcpe
++#########################################################################
++
++easy50712%config : unconfig
++ @mkdir -p $(obj)include
++ @mkdir -p $(obj)board/infineon/easy50712
++ @[ -z "$(findstring ramboot,$@)" ] || \
++ { echo "TEXT_BASE = 0xA0400000" >$(obj)board/infineon/easy50712/config.tmp ; \
++ echo "#define CONFIG_SYS_RAMBOOT" >>$(obj)include/config.h ; \
++ $(XECHO) "... with ramboot configuration" ; \
++ }
++ @if [ "$(findstring _DDR,$@)" -a -z "$(findstring ramboot,$@)" ] ; then \
++ echo "#define CONFIG_USE_DDR_RAM" >>$(obj)include/config.h ; \
++ echo "#define CONFIG_BOOTSTRAP" >>$(obj)include/config.h ; \
++ DDR=$(subst DDR,,$(filter DDR%,$(subst _, ,$@))); \
++ case "$${DDR}" in \
++ 111M|166M|e111M|e166M|promos400|samsung166|psc166) \
++ $(XECHO) "... with DDR RAM config $${DDR}" ; \
++ echo "#define CONFIG_USE_DDR_RAM_CFG_$${DDR}" >>$(obj)include/config.h ;; \
++ *) $(XECHO) "... DDR RAM config \\\"$${DDR}\\\" unknown, use default"; \
++ esac; \
++ fi
++ @$(MKCONFIG) -a $(word 1,$(subst _, ,$@)) mips mips easy50712 infineon danube
++
++easy50812%config : unconfig
++ @mkdir -p $(obj)include
++ @mkdir -p $(obj)board/infineon/easy50812
++ @[ -z "$(findstring ramboot,$@)" ] || \
++ { echo "TEXT_BASE = 0xA0400000" >$(obj)board/infineon/easy50812/config.tmp ; \
++ echo "CONFIG_BOOTSTRAP = 0" >>$(obj)board/infineon/easy50812/config.tmp ; \
++ echo "#define CONFIG_SYS_RAMBOOT" >>$(obj)include/config.h ; \
++ $(XECHO) "... with ramboot configuration" ; \
++ }
++ @if [ "$(findstring _DDR,$@)" -a -z "$(findstring ramboot,$@)" ] ; then \
++ echo "#define CONFIG_USE_DDR_RAM" >>$(obj)include/config.h ; \
++ echo "#define CONFIG_BOOTSTRAP" >>$(obj)include/config.h ; \
++ DDR=$(subst DDR,,$(filter DDR%,$(subst _, ,$@))); \
++ case "$${DDR}" in \
++ 111M|166M|e111M|e166M|promos400|samsung166|psc166) \
++ $(XECHO) "... with DDR RAM config $${DDR}" ; \
++ echo "#define CONFIG_USE_DDR_RAM_CFG_$${DDR}" >>$(obj)include/config.h ;; \
++ *) $(XECHO) "... DDR RAM config \\\"$${DDR}\\\" unknown, use default"; \
++ esac; \
++ fi
++ @$(MKCONFIG) -a $(word 1,$(subst _, ,$@)) mips mips easy50812 infineon ar9
++
++#########################################################################
+ ## MIPS32 AU1X00
+ #########################################################################
+
+--- a/drivers/net/Makefile
++++ b/drivers/net/Makefile
+@@ -43,6 +43,7 @@
+ COBJS-$(CONFIG_FSLDMAFEC) += fsl_mcdmafec.o mcfmii.o
+ COBJS-$(CONFIG_FTMAC100) += ftmac100.o
+ COBJS-$(CONFIG_GRETH) += greth.o
++COBJS-$(CONFIG_IFX_ETOP) += ifx_etop.o
+ COBJS-$(CONFIG_INCA_IP_SWITCH) += inca-ip_sw.o
+ COBJS-$(CONFIG_KIRKWOOD_EGIGA) += kirkwood_egiga.o
+ COBJS-$(CONFIG_DRIVER_KS8695ETH) += ks8695eth.o
+--- a/drivers/serial/Makefile
++++ b/drivers/serial/Makefile
+@@ -28,6 +28,7 @@
+ COBJS-$(CONFIG_ARM_DCC) += arm_dcc.o
+ COBJS-$(CONFIG_AT91RM9200_USART) += at91rm9200_usart.o
+ COBJS-$(CONFIG_ATMEL_USART) += atmel_usart.o
++COBJS-$(CONFIG_IFX_ASC) += ifx_asc.o
+ COBJS-$(CONFIG_MCFUART) += mcfuart.o
+ COBJS-$(CONFIG_NS9750_UART) += ns9750_serial.o
+ COBJS-$(CONFIG_SYS_NS16550) += ns16550.o
+--- a/include/netdev.h
++++ b/include/netdev.h
+@@ -57,6 +57,7 @@
+ int ftmac100_initialize(bd_t *bits);
+ int greth_initialize(bd_t *bis);
+ void gt6426x_eth_initialize(bd_t *bis);
++int ifx_etop_initialize(bd_t *bis);
+ int inca_switch_initialize(bd_t *bis);
+ int kirkwood_egiga_initialize(bd_t *bis);
+ int lan91c96_initialize(u8 dev_num, int base_addr);
+@@ -85,6 +86,7 @@
+ int uli526x_initialize(bd_t *bis);
+ int sh_eth_initialize(bd_t *bis);
+ int dm9000_initialize(bd_t *bis);
++int lq_eth_initialize(bd_t * bis);
+
+ /* Boards with PCI network controllers can call this from their board_eth_init()
+ * function to initialize whatever's on board.
diff --git a/package/uboot-lantiq/patches/200-httpd.patch b/package/uboot-lantiq/patches/200-httpd.patch
new file mode 100644
index 000000000..b0ab3b6af
--- /dev/null
+++ b/package/uboot-lantiq/patches/200-httpd.patch
@@ -0,0 +1,6164 @@
+--- a/common/cmd_net.c
++++ b/common/cmd_net.c
+@@ -43,6 +43,18 @@ U_BOOT_CMD(
+ "[loadAddress] [[hostIPaddr:]bootfilename]"
+ );
+
++#if defined(CONFIG_CMD_HTTPD)
++int do_httpd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
++{
++ return NetLoopHttpd();
++}
++
++U_BOOT_CMD(
++ httpd, 1, 1, do_httpd,
++ "httpd\t- start webserver", ""
++);
++#endif
++
+ int do_tftpb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+ {
+ return netboot_common (TFTP, cmdtp, argc, argv);
+--- /dev/null
++++ b/include/httpd.h
+@@ -0,0 +1,17 @@
++#ifndef _UIP_HTTPD_H__
++#define _UIP_HTTPD_H__
++
++void HttpdStart (void);
++void HttpdHandler (void);
++
++/* board specific implementation */
++extern int do_http_upgrade(const unsigned char *data, const ulong size);
++
++#define HTTP_PROGRESS_START 0
++#define HTTP_PROGRESS_TIMEOUT 1
++#define HTTP_PROGRESS_UPLOAD_READY 2
++#define HTTP_PROGRESS_UGRADE_READY 3
++#define HTTP_PROGRESS_UGRADE_FAILED 4
++extern int do_http_progress(const int state);
++
++#endif
+--- a/include/net.h
++++ b/include/net.h
+@@ -383,7 +383,8 @@ extern int NetTimeOffset; /* offset ti
+
+ /* Initialize the network adapter */
+ extern int NetLoop(proto_t);
+-
++extern int NetLoopHttpd(void);
++extern void NetSendHttpd(void);
+ /* Shutdown adapters and cleanup */
+ extern void NetStop(void);
+
+--- a/net/Makefile
++++ b/net/Makefile
+@@ -26,6 +26,8 @@ include $(TOPDIR)/config.mk
+ # CFLAGS += -DDEBUG
+
+ LIB = $(obj)libnet.a
++UIPDIR = uip-0.9
++$(shell mkdir -p $(obj)$(UIPDIR))
+
+ COBJS-$(CONFIG_CMD_NET) += bootp.o
+ COBJS-$(CONFIG_CMD_DNS) += dns.o
+@@ -36,6 +40,8 @@ COBJS-$(CONFIG_CMD_NET) += rarp.o
+ COBJS-$(CONFIG_CMD_SNTP) += sntp.o
+ COBJS-$(CONFIG_CMD_NET) += tftp.o
+
++COBJS-$(CONFIG_CMD_HTTPD) += httpd.o $(UIPDIR)/fs.o $(UIPDIR)/httpd.o $(UIPDIR)/uip_arp.o $(UIPDIR)/uip_arch.o $(UIPDIR)/uip.o
++
+ COBJS := $(COBJS-y)
+ SRCS := $(COBJS:.o=.c)
+ OBJS := $(addprefix $(obj),$(COBJS))
+--- /dev/null
++++ b/net/httpd.c
+@@ -0,0 +1,52 @@
++/*
++ * Copyright 1994, 1995, 2000 Neil Russell.
++ * (See License)
++ * Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de
++ */
++
++#include <common.h>
++#include <command.h>
++#include <net.h>
++#include "uip-0.9/uipopt.h"
++#include "uip-0.9/uip.h"
++#include "uip-0.9/uip_arp.h"
++
++
++#if defined(CONFIG_CMD_HTTPD)
++
++#define TIMEOUT 5
++
++static int arptimer = 0;
++
++void
++HttpdHandler (void)
++{
++ int i;
++ for(i = 0; i < UIP_CONNS; i++) {
++ uip_periodic(i);
++ if(uip_len > 0) {
++ uip_arp_out();
++ NetSendHttpd();
++ }
++ }
++ if(++arptimer == 20) {
++ uip_arp_timer();
++ arptimer = 0;
++ }
++}
++
++static void
++HttpdTimeout (void)
++{
++ puts ("T ");
++ NetSetTimeout (TIMEOUT * 1000, HttpdTimeout);
++}
++
++void
++HttpdStart (void)
++{
++ uip_init();
++ httpd_init();
++}
++
++#endif
+--- a/net/net.c
++++ b/net/net.c
+@@ -95,6 +95,19 @@
+ #if defined(CONFIG_CMD_DNS)
+ #include "dns.h"
+ #endif
++#if defined(CONFIG_CMD_HTTPD)
++#include "httpd.h"
++#include "uip-0.9/uipopt.h"
++#include "uip-0.9/uip.h"
++#include "uip-0.9/uip_arp.h"
++static int https_running = 0;
++int httpd_upload_complete = 0;
++unsigned char *httpd_upload_data = 0;
++extern int upload_running;
++void NetReceiveHttpd(volatile uchar * inpkt, int len);
++void NetSendHttpd(void);
++extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
++#endif
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+@@ -1308,6 +1321,13 @@ NetReceive(volatile uchar * inpkt, int l
+
+ debug("packet received\n");
+
++#if defined(CONFIG_CMD_HTTPD)
++ if(https_running) {
++ NetReceiveHttpd(inpkt, len);
++ return;
++ }
++#endif
++
+ NetRxPacket = inpkt;
+ NetRxPacketLen = len;
+ et = (Ethernet_t *)inpkt;
+@@ -1922,3 +1942,162 @@ ushort getenv_VLAN(char *var)
+ {
+ return (string_to_VLAN(getenv(var)));
+ }
++
++#if defined(CONFIG_CMD_HTTPD)
++
++void
++NetSendHttpd(void)
++{
++ volatile uchar *tmpbuf = NetTxPacket;
++ int i;
++
++ for(i = 0; i < 40 + UIP_LLH_LEN; i++) {
++ tmpbuf[i] = uip_buf[i];
++ }
++
++ for(; i < uip_len; i++) {
++ tmpbuf[i] = uip_appdata[i - 40 - UIP_LLH_LEN];
++ }
++ eth_send(NetTxPacket, uip_len);
++}
++
++#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
++
++void
++NetReceiveHttpd(volatile uchar * inpkt, int len)
++{
++ memcpy(uip_buf, inpkt, len);
++ uip_len = len;
++ if(BUF->type == htons(UIP_ETHTYPE_IP)) {
++ uip_arp_ipin();
++ uip_input();
++ if(uip_len > 0) {
++ uip_arp_out();
++ NetSendHttpd();
++ }
++ } else if(BUF->type == htons(UIP_ETHTYPE_ARP)) {
++ uip_arp_arpin();
++ if(uip_len > 0) {
++ NetSendHttpd();
++ }
++ }
++}
++
++int
++NetLoopHttpd(void)
++{
++ unsigned long long tout = 0;
++ bd_t *bd = gd->bd;
++ unsigned short int ip[2];
++
++#ifdef CONFIG_NET_MULTI
++ NetRestarted = 0;
++ NetDevExists = 0;
++#endif
++
++ /* XXX problem with bss workaround */
++ NetArpWaitPacketMAC = NULL;
++ NetArpWaitTxPacket = NULL;
++ NetArpWaitPacketIP = 0;
++ NetArpWaitReplyIP = 0;
++ NetArpWaitTxPacket = NULL;
++ NetTxPacket = NULL;
++ NetTryCount = 1;
++
++ if (!NetTxPacket) {
++ int i;
++ /*
++ * Setup packet buffers, aligned correctly.
++ */
++ NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
++ NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
++ for (i = 0; i < PKTBUFSRX; i++) {
++ NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
++ }
++ }
++
++ if (!NetArpWaitTxPacket) {
++ NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
++ NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
++ NetArpWaitTxPacketSize = 0;
++ }
++
++restart:
++
++ eth_halt();
++#ifdef CONFIG_NET_MULTI
++ eth_set_current();
++#endif
++ if (eth_init(bd) < 0) {
++ eth_halt();
++ return(-1);
++ }
++
++#ifdef CONFIG_NET_MULTI
++ memcpy (NetOurEther, eth_get_dev()->enetaddr, 6);
++#else
++ eth_getenv_enetaddr("ethaddr", NetOurEther);
++#endif
++
++ NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
++ NetOurGatewayIP = getenv_IPaddr ("gatewayip");
++ NetOurSubnetMask= getenv_IPaddr ("netmask");
++ NetOurVLAN = getenv_VLAN("vlan");
++ NetOurNativeVLAN = getenv_VLAN("nvlan");
++
++ printf("starting httpd server from server %ld.%ld.%ld.%ld\n",
++ (bd->bi_ip_addr & 0xff000000) >> 24,
++ (bd->bi_ip_addr & 0x00ff0000) >> 16,
++ (bd->bi_ip_addr & 0x0000ff00) >> 8,
++ (bd->bi_ip_addr & 0x000000ff));
++
++ HttpdStart();
++
++ ip[0] = ((bd->bi_ip_addr & 0xffff0000) >> 16);
++ ip[1] = (bd->bi_ip_addr & 0x0000ffff);
++ uip_sethostaddr(ip);
++
++ do_http_progress(HTTP_PROGRESS_START);
++
++ https_running = 1;
++ for (;;) {
++ unsigned long long t1;
++ WATCHDOG_RESET();
++ if(eth_rx() > 0) {
++ HttpdHandler();
++ } else {
++ t1 = get_ticks();
++ if(t1 - tout > 1000) {
++ do_http_progress(HTTP_PROGRESS_TIMEOUT);
++ tout = t1;
++ }
++ }
++ if(!httpd_upload_complete)
++ continue;
++ printf("Bytes transferred = %ld (%lx hex)\n",
++ NetBootFileXferSize,
++ NetBootFileXferSize);
++ eth_halt();
++ do_http_progress(HTTP_PROGRESS_UPLOAD_READY);
++ if(do_http_upgrade(&httpd_upload_data[0], NetBootFileXferSize) == 0) {
++ do_http_progress(HTTP_PROGRESS_UGRADE_READY);
++ udelay(1000 * 10);
++ do_reset (0,0,0,0);
++ return 0;
++ }
++ break;
++ }
++ https_running = 0;
++ NetBootFileXferSize = 0;
++ httpd_upload_complete = 0;
++ upload_running = 0;
++// free(httpd_upload_data);
++
++ do_http_progress(HTTP_PROGRESS_UGRADE_FAILED);
++
++ goto restart;
++
++ return -1;
++}
++
++#endif
+--- /dev/null
++++ b/net/uip-0.9/Makefile
+@@ -0,0 +1,54 @@
++# Copyright (c) 2001, Adam Dunkels.
++# 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 Adam Dunkels.
++# 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.
++#
++# This file is part of the uIP TCP/IP stack.
++#
++# $Id: Makefile,v 1.8.2.2 2003/10/04 22:54:17 adam Exp $
++#
++
++CC=gcc
++CFLAGS=-Wall -fpack-struct -DDUMP=0
++
++all: uip
++
++uip: uip.o uip_arch.o tapdev.o httpd.o main.o fs.o uip_arp.o
++ $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@
++
++%.o: %.c
++ $(CC) $(CFLAGS) -c $^ -o $@
++
++clean:
++ rm -f *.o *~ *core uip
++
++
++
++
++
++
+--- /dev/null
++++ b/net/uip-0.9/fs.c
+@@ -0,0 +1,154 @@
++/**
++ * \addtogroup httpd
++ * @{
++ */
++
++/**
++ * \file
++ * HTTP server read-only file system code.
++ * \author Adam Dunkels <adam@dunkels.com>
++ *
++ * A simple read-only filesystem.
++ */
++
++/*
++ * Copyright (c) 2001, Swedish Institute of Computer Science.
++ * 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
++ *
++ * This file is part of the lwIP TCP/IP stack.
++ *
++ * Author: Adam Dunkels <adam@sics.se>
++ *
++ * $Id: fs.c,v 1.7.2.3 2003/10/07 13:22:27 adam Exp $
++ */
++
++#include "uip.h"
++#include "httpd.h"
++#include "fs.h"
++#include "fsdata.h"
++
++#include "fsdata.c"
++
++#ifdef FS_STATISTICS
++#if FS_STATISTICS == 1
++static u16_t count[FS_NUMFILES];
++#endif /* FS_STATISTICS */
++#endif /* FS_STATISTICS */
++
++/*-----------------------------------------------------------------------------------*/
++static u8_t
++fs_strcmp(const char *str1, const char *str2)
++{
++ u8_t i;
++ i = 0;
++ loop:
++
++ if(str2[i] == 0 ||
++ str1[i] == '\r' ||
++ str1[i] == '\n') {
++ return 0;
++ }
++
++ if(str1[i] != str2[i]) {
++ return 1;
++ }
++
++
++ ++i;
++ goto loop;
++}
++/*-----------------------------------------------------------------------------------*/
++int
++fs_open(const char *name, struct fs_file *file)
++{
++#ifdef FS_STATISTICS
++#if FS_STATISTICS == 1
++ u16_t i = 0;
++#endif /* FS_STATISTICS */
++#endif /* FS_STATISTICS */
++ struct fsdata_file_noconst *f;
++
++ for(f = (struct fsdata_file_noconst *)FS_ROOT;
++ f != NULL;
++ f = (struct fsdata_file_noconst *)f->next) {
++
++ if(fs_strcmp(name, f->name) == 0) {
++ file->data = f->data;
++ file->len = f->len;
++#ifdef FS_STATISTICS
++#if FS_STATISTICS == 1
++ ++count[i];
++#endif /* FS_STATISTICS */
++#endif /* FS_STATISTICS */
++ return 1;
++ }
++#ifdef FS_STATISTICS
++#if FS_STATISTICS == 1
++ ++i;
++#endif /* FS_STATISTICS */
++#endif /* FS_STATISTICS */
++
++ }
++ return 0;
++}
++/*-----------------------------------------------------------------------------------*/
++void
++fs_init(void)
++{
++#ifdef FS_STATISTICS
++#if FS_STATISTICS == 1
++ u16_t i;
++ for(i = 0; i < FS_NUMFILES; i++) {
++ count[i] = 0;
++ }
++#endif /* FS_STATISTICS */
++#endif /* FS_STATISTICS */
++}
++/*-----------------------------------------------------------------------------------*/
++#ifdef FS_STATISTICS
++#if FS_STATISTICS == 1
++u16_t fs_count
++(char *name)
++{
++ struct fsdata_file_noconst *f;
++ u16_t i;
++
++ i = 0;
++ for(f = (struct fsdata_file_noconst *)FS_ROOT;
++ f != NULL;
++ f = (struct fsdata_file_noconst *)f->next) {
++
++ if(fs_strcmp(name, f->name) == 0) {
++ return count[i];
++ }
++ ++i;
++ }
++ return 0;
++}
++#endif /* FS_STATISTICS */
++#endif /* FS_STATISTICS */
++/*-----------------------------------------------------------------------------------*/
+--- /dev/null
++++ b/net/uip-0.9/fs.h
+@@ -0,0 +1,80 @@
++/**
++ * \addtogroup httpd
++ * @{
++ */
++
++/**
++ * \file
++ * HTTP server read-only file system header file.
++ * \author Adam Dunkels <adam@dunkels.com>
++ */
++
++/*
++ * Copyright (c) 2001, Swedish Institute of Computer Science.
++ * 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
++ *
++ * This file is part of the lwIP TCP/IP stack.
++ *
++ * Author: Adam Dunkels <adam@sics.se>
++ *
++ * $Id: fs.h,v 1.6.2.3 2003/10/07 13:22:27 adam Exp $
++ */
++#ifndef __FS_H__
++#define __FS_H__
++
++#include "uip.h"
++
++/**
++ * An open file in the read-only file system.
++ */
++struct fs_file {
++ char *data; /**< The actual file data. */
++ int len; /**< The length of the file data. */
++};
++
++/**
++ * Open a file in the read-only file system.
++ *
++ * \param name The name of the file.
++ *
++ * \param file The file pointer, which must be allocated by caller and
++ * will be filled in by the function.
++ */
++int fs_open(const char *name, struct fs_file *file);
++
++#ifdef FS_STATISTICS
++#if FS_STATISTICS == 1
++u16_t fs_count(char *name);
++#endif /* FS_STATISTICS */
++#endif /* FS_STATISTICS */
++
++/**
++ * Initialize the read-only file system.
++ */
++void fs_init(void);
++
++#endif /* __FS_H__ */
+--- /dev/null
++++ b/net/uip-0.9/fsdata.c
+@@ -0,0 +1,199 @@
++static const char data_flashing_html[] = {
++ /* /flashing.html */
++ 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30,
++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63,
++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69,
++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65,
++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74,
++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa,
++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c, 0x62,
++ 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3d,
++ 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30,
++ 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x20, 0x68,
++ 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x31, 0x30, 0x30, 0x25,
++ 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23,
++ 0x66, 0x66, 0x66, 0x3b, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67,
++ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
++ 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, 0x62, 0x30, 0x33, 0x34,
++ 0x3b, 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72,
++ 0x3e, 0x3c, 0x68, 0x31, 0x3e, 0x55, 0x70, 0x67, 0x72, 0x61,
++ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65,
++ 0x6d, 0x20, 0x2e, 0x2e, 0x2e, 0x2e, 0x3c, 0x2f, 0x68, 0x31,
++ 0x3e, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e,
++ 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68,
++ 0x74, 0x6d, 0x6c, 0x3e, 0xa, };
++
++static const char data_fail_html[] = {
++ /* /fail.html */
++ 0x2f, 0x66, 0x61, 0x69, 0x6c, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30,
++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63,
++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69,
++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65,
++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74,
++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa,
++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9,
++ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c,
++ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9,
++ 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46,
++ 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49,
++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65,
++ 0x3e, 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa,
++ 0x9, 0x9, 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73,
++ 0x68, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65,
++ 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9, 0x45,
++ 0x52, 0x52, 0x4f, 0x52, 0x20, 0x2d, 0x20, 0x74, 0x68, 0x65,
++ 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x79, 0x6f, 0x75,
++ 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x20,
++ 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20,
++ 0x70, 0x61, 0x73, 0x73, 0x20, 0x76, 0x65, 0x72, 0x69, 0x66,
++ 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x50,
++ 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x6d, 0x61, 0x6b, 0x65,
++ 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x75,
++ 0x73, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x66, 0x66, 0x69,
++ 0x63, 0x69, 0x61, 0x6c, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74,
++ 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64,
++ 0x20, 0x62, 0x79, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
++ 0x2f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e,
++ 0x66, 0x6f, 0x6e, 0x6f, 0x73, 0x66, 0x65, 0x72, 0x61, 0x2e,
++ 0x6f, 0x72, 0x67, 0x2f, 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f,
++ 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c,
++ 0x3e, 0xa, };
++
++static const char data_404_html[] = {
++ /* /404.html */
++ 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x34,
++ 0x30, 0x34, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f,
++ 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0xd, 0xa, 0x53,
++ 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50,
++ 0x2f, 0x30, 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70,
++ 0x3a, 0x2f, 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73,
++ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f,
++ 0x75, 0x69, 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e,
++ 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a,
++ 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c,
++ 0xd, 0xa, 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e,
++ 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f,
++ 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65,
++ 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e,
++ 0x3c, 0x68, 0x31, 0x3e, 0x34, 0x30, 0x34, 0x20, 0x2d, 0x20,
++ 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66,
++ 0x6f, 0x75, 0x6e, 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0x3c,
++ 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x2f,
++ 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74, 0x6d,
++ 0x6c, 0x3e, };
++
++static const char data_index_html[] = {
++ /* /index.html */
++ 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30,
++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63,
++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69,
++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65,
++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74,
++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa,
++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9,
++ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c,
++ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9,
++ 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46,
++ 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49,
++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65,
++ 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e,
++ 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74,
++ 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69,
++ 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74,
++ 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a,
++ 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
++ 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62,
++ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
++ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62,
++ 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9,
++ 0x3c, 0x68, 0x31, 0x3e, 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65,
++ 0x72, 0x61, 0x20, 0x46, 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66,
++ 0x65, 0x20, 0x55, 0x49, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa,
++ 0x9, 0x9, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x65,
++ 0x74, 0x68, 0x6f, 0x64, 0x3d, 0x22, 0x70, 0x6f, 0x73, 0x74,
++ 0x22, 0x20, 0x65, 0x6e, 0x63, 0x74, 0x79, 0x70, 0x65, 0x3d,
++ 0x22, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74,
++ 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x64, 0x61, 0x74, 0x61,
++ 0x22, 0x3e, 0xa, 0x9, 0x9, 0x9, 0x3c, 0x69, 0x6e, 0x70,
++ 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69,
++ 0x6c, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x66, 0x69,
++ 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x3e, 0xa, 0x9, 0x9,
++ 0x9, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79,
++ 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x3e,
++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x3e,
++ 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa,
++ 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, };
++
++static const char data_flash_html[] = {
++ /* /flash.html */
++ 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30,
++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63,
++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69,
++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65,
++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74,
++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa,
++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9,
++ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c,
++ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9,
++ 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46,
++ 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49,
++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65,
++ 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e,
++ 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74,
++ 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69,
++ 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74,
++ 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a,
++ 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
++ 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62,
++ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
++ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62,
++ 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9,
++ 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73, 0x68, 0x69,
++ 0x6e, 0x67, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9,
++ 0x54, 0x68, 0x65, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
++ 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x72,
++ 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x6c,
++ 0x61, 0x73, 0x68, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68,
++ 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x70,
++ 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x2c, 0x20, 0x74, 0x68,
++ 0x65, 0x20, 0x6c, 0x65, 0x64, 0x73, 0x20, 0x77, 0x69, 0x6c,
++ 0x6c, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x6f,
++ 0x20, 0x62, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0xa, 0xa, 0x9,
++ 0x9, 0x41, 0x66, 0x74, 0x65, 0x72, 0x20, 0x61, 0x20, 0x73,
++ 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x6c,
++ 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68,
++ 0x65, 0x20, 0x62, 0x6f, 0x78, 0x20, 0x77, 0x69, 0x6c, 0x6c,
++ 0x20, 0x72, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0xa, 0x9, 0x3c,
++ 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68,
++ 0x74, 0x6d, 0x6c, 0x3e, 0xa, };
++
++const struct fsdata_file file_flashing_html[] = {{NULL, data_flashing_html, data_flashing_html + 15, sizeof(data_flashing_html) - 15}};
++
++const struct fsdata_file file_fail_html[] = {{file_flashing_html, data_fail_html, data_fail_html + 11, sizeof(data_fail_html) - 11}};
++
++const struct fsdata_file file_404_html[] = {{file_fail_html, data_404_html, data_404_html + 10, sizeof(data_404_html) - 10}};
++
++const struct fsdata_file file_index_html[] = {{file_404_html, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}};
++
++const struct fsdata_file file_flash_html[] = {{file_index_html, data_flash_html, data_flash_html + 12, sizeof(data_flash_html) - 12}};
++
++#define FS_ROOT file_flash_html
++
++#define FS_NUMFILES 5
+\ No newline at end of file
+--- /dev/null
++++ b/net/uip-0.9/fsdata.h
+@@ -0,0 +1,64 @@
++/*
++ * Copyright (c) 2001, Swedish Institute of Computer Science.
++ * 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
++ *
++ * This file is part of the lwIP TCP/IP stack.
++ *
++ * Author: Adam Dunkels <adam@sics.se>
++ *
++ * $Id: fsdata.h,v 1.4.2.1 2003/10/04 22:54:06 adam Exp $
++ */
++#ifndef __FSDATA_H__
++#define __FSDATA_H__
++
++#include "uipopt.h"
++
++struct fsdata_file {
++ const struct fsdata_file *next;
++ const char *name;
++ const char *data;
++ const int len;
++#ifdef FS_STATISTICS
++#if FS_STATISTICS == 1
++ u16_t count;
++#endif /* FS_STATISTICS */
++#endif /* FS_STATISTICS */
++};
++
++struct fsdata_file_noconst {
++ struct fsdata_file *next;
++ char *name;
++ char *data;
++ int len;
++#ifdef FS_STATISTICS
++#if FS_STATISTICS == 1
++ u16_t count;
++#endif /* FS_STATISTICS */
++#endif /* FS_STATISTICS */
++};
++
++#endif /* __FSDATA_H__ */
+--- /dev/null
++++ b/net/uip-0.9/httpd.c
+@@ -0,0 +1,278 @@
++#include "uip.h"
++#include "httpd.h"
++#include "fs.h"
++#include "fsdata.h"
++#include <asm/addrspace.h>
++
++#define HTTP_NONE 0
++#define HTTP_FILE 1
++#define HTTP_FIRMWARE 2
++
++#define PRINT(x) printf("%s", x)
++#define PRINTLN(x) printf("%s\n", x)
++
++extern unsigned long do_http_tmp_address(void);
++
++struct httpd_state *hs;
++
++extern const struct fsdata_file file_index_html;
++extern const struct fsdata_file file_404_html;
++extern const struct fsdata_file file_flash_html;
++extern int httpd_upload_complete;
++extern unsigned char *httpd_upload_data;
++unsigned char *upload_data;
++extern ulong NetBootFileXferSize;
++int upload_running = 0;
++
++#define ISO_G 0x47
++#define ISO_E 0x45
++#define ISO_T 0x54
++#define ISO_P 0x50
++#define ISO_O 0x4f
++#define ISO_S 0x53
++#define ISO_T 0x54
++#define ISO_slash 0x2f
++#define ISO_c 0x63
++#define ISO_g 0x67
++#define ISO_i 0x69
++#define ISO_space 0x20
++#define ISO_nl 0x0a
++#define ISO_cr 0x0d
++#define ISO_a 0x61
++#define ISO_t 0x74
++#define ISO_hash 0x23
++#define ISO_period 0x2e
++
++static char eol[3] = { 0x0d, 0x0a, 0x00 };
++static char eol2[5] = { 0x0d, 0x0a, 0x0d, 0x0a, 0x00 };
++static char boundary[128];
++static int boundary_len = 0;
++
++/* we use this so that we can do without the ctype library */
++#define is_digit(c) ((c) >= '0' && (c) <= '9')
++static int atoi(const char *s)
++{
++ int i=0;
++
++ while (is_digit(*s))
++ i = i*10 + *(s++) - '0';
++ return i;
++}
++
++void
++httpd_init(void)
++{
++ fs_init();
++ uip_listen(HTONS(80));
++}
++
++void
++httpd_appcall(void)
++{
++ struct fs_file fsfile;
++ u8_t i;
++ switch(uip_conn->lport) {
++ case HTONS(80):
++ hs = (struct httpd_state *)(uip_conn->appstate);
++ if(uip_connected())
++ {
++ hs->state = HTTP_NONE;
++ hs->count = 0;
++ return;
++ } else if(uip_poll())
++ {
++ if(hs->count++ >= 1000) {
++ uip_abort();
++ }
++ return;
++ } else if(uip_newdata() && hs->state == HTTP_NONE)
++ {
++ if(uip_appdata[0] == ISO_G &&
++ uip_appdata[1] == ISO_E &&
++ uip_appdata[2] == ISO_T &&
++ uip_appdata[3] == ISO_space)
++ {
++ hs->state = HTTP_FILE;
++ }
++ if(uip_appdata[0] == ISO_P &&
++ uip_appdata[1] == ISO_O &&
++ uip_appdata[2] == ISO_S &&
++ uip_appdata[3] == ISO_T &&
++ uip_appdata[4] == ISO_space)
++ {
++ hs->state = HTTP_FIRMWARE;
++ }
++ if(hs->state == HTTP_NONE)
++ {
++ uip_abort();
++ return;
++ }
++ if(hs->state == HTTP_FILE)
++ {
++ for(i = 4; i < 40; ++i)
++ {
++ if(uip_appdata[i] == ISO_space ||
++ uip_appdata[i] == ISO_cr ||
++ uip_appdata[i] == ISO_nl)
++ {
++ uip_appdata[i] = 0;
++ break;
++ }
++ }
++
++ PRINT("request for file ");
++ PRINTLN(&uip_appdata[4]);
++ if(uip_appdata[4] == ISO_slash &&
++ uip_appdata[5] == 0)
++ {
++ fs_open(file_index_html.name, &fsfile);
++ } else {
++ if(!fs_open((const char *)&uip_appdata[4], &fsfile))
++ {
++ PRINTLN("couldn't open file");
++ fs_open(file_index_html.name, &fsfile);
++ }
++ }
++ hs->script = 0;
++ hs->state = HTTP_FILE;
++ hs->dataptr = fsfile.data;
++ hs->count = fsfile.len;
++ }
++ if(hs->state == HTTP_FIRMWARE)
++ {
++ unsigned char *start = (unsigned char*)uip_appdata;
++ char *clen = strstr(start, "Content-Length:");
++ int len = 0;
++ unsigned char *next, *end;
++ unsigned char *boundary_start;
++ int i;
++ uip_appdata[uip_len] = '\0';
++ if(clen)
++ {
++ clen += sizeof("Content-Length:");
++ next = strstr(clen, eol);
++ if(next)
++ {
++ len = atoi(clen);
++ next++;
++ printf("expecting %d bytes\n", len);
++ upload_data = httpd_upload_data = (unsigned char *)do_http_tmp_address();
++ printf("received data will be stored at 0x%08X\n", upload_data);
++ if(!upload_data)
++ {
++ printf("failed to allocate memory\n");
++ uip_close();
++ return;
++ }
++ } else {
++ uip_close();
++ return;
++ }
++ }
++ if(len < 4 * 1024)
++ {
++ uip_close();
++ return;
++ }
++ boundary_start = strstr(next, "---");
++ if(!boundary_start)
++ {
++ uip_close();
++ return;
++ }
++ end = strstr(boundary_start, eol);
++ if(!eol)
++ {
++ uip_close();
++ return;
++ }
++ boundary_len = end - boundary_start;
++ memcpy(boundary, boundary_start, boundary_len);
++ boundary[boundary_len] = 0;
++ next = strstr(boundary_start, "name=\"firmware\";");
++ if(!next)
++ {
++ uip_close();
++ return;
++ }
++ next = strstr(next, eol2);
++ if(!next)
++ {
++ printf("could not find start of data\n");
++ uip_close();
++ return;
++ }
++ next += 4;
++ hs->script = 0;
++ hs->state = HTTP_FIRMWARE;
++ hs->upload = uip_len - (next - start);
++ hs->upload_total = len - (int)(next - boundary_start);
++ hs->upload_total -= (strlen(boundary) + 6);
++ //printf("storing %d bytes at %p\n", (int)hs->upload, upload_data);
++ for(i = 0; i < hs->upload; i++)
++ upload_data[i] = next[i];
++ upload_data += (int)hs->upload;
++ printf("%d / %d\n", (int)hs->upload, hs->upload_total);
++ uip_slen = 0;
++ return;
++ }
++ }
++
++ if(hs->state == HTTP_FIRMWARE)
++ {
++ if(uip_newdata())
++ {
++ int i;
++ hs->count = 0;
++ uip_appdata[uip_len] = '\0';
++ hs->upload += uip_len;
++ //printf("storing %d bytes at %p\n", uip_len, upload_data);
++ printf("%d / %d\n", (int)hs->upload, hs->upload_total);
++ for(i = 0; i < uip_len; i++)
++ upload_data[i] = uip_appdata[i];
++ upload_data += uip_len;
++ uip_slen = 0;
++ if(hs->upload >= hs->upload_total)
++ {
++ upload_running = 1;
++ NetBootFileXferSize = hs->upload_total;
++ fs_open(file_flash_html.name, &fsfile);
++ hs->script = 0;
++ hs->state = HTTP_FILE;
++ hs->dataptr = fsfile.data;
++ hs->count = fsfile.len;
++ }
++ }
++ }
++ if(hs->state == HTTP_FILE)
++ {
++ if(uip_acked())
++ {
++ if(hs->count >= uip_conn->len)
++ {
++ hs->count -= uip_conn->len;
++ hs->dataptr += uip_conn->len;
++ } else {
++ hs->count = 0;
++ }
++ if(hs->count == 0)
++ {
++ if(upload_running)
++ {
++ int i;
++ httpd_upload_complete = 1;
++ // for(i = 0; i < hs->upload_total; i++)
++ // printf("%c", httpd_upload_data[i]);
++ }
++ uip_close();
++ }
++ }
++ uip_send(hs->dataptr, hs->count);
++ }
++ break;
++
++ default:
++ uip_abort();
++ break;
++ }
++}
+--- /dev/null
++++ b/net/uip-0.9/httpd.h
+@@ -0,0 +1,83 @@
++/**
++ * \addtogroup httpd
++ * @{
++ */
++
++/**
++ * \file
++ * HTTP server header file.
++ * \author Adam Dunkels <adam@dunkels.com>
++ */
++
++/*
++ * Copyright (c) 2001, Adam Dunkels.
++ * 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.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: httpd.h,v 1.4.2.3 2003/10/06 22:56:44 adam Exp $
++ *
++ */
++
++#ifndef __HTTPD_H__
++#define __HTTPD_H__
++
++void httpd_init(void);
++void httpd_appcall(void);
++
++/* UIP_APPCALL: the name of the application function. This function
++ must return void and take no arguments (i.e., C type "void
++ appfunc(void)"). */
++#ifndef UIP_APPCALL
++#define UIP_APPCALL httpd_appcall
++#endif
++
++struct httpd_state {
++ u8_t state;
++ u16_t count;
++ char *dataptr;
++ char *script;
++ unsigned int upload;
++ unsigned int upload_total;
++};
++
++
++/* UIP_APPSTATE_SIZE: The size of the application-specific state
++ stored in the uip_conn structure. */
++#ifndef UIP_APPSTATE_SIZE
++#define UIP_APPSTATE_SIZE (sizeof(struct httpd_state))
++#endif
++
++#define FS_STATISTICS 1
++
++extern struct httpd_state *hs;
++
++
++/* we copy the data to RAM+10MB */
++#define TMP_DATA 0x8A100000
++
++#endif /* __HTTPD_H__ */
+--- /dev/null
++++ b/net/uip-0.9/main.c
+@@ -0,0 +1,88 @@
++/*
++ * Copyright (c) 2001-2003, Adam Dunkels.
++ * 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.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: main.c,v 1.10.2.1 2003/10/04 22:54:17 adam Exp $
++ *
++ */
++
++
++#include "uip.h"
++#include "uip_arp.h"
++#include "tapdev.h"
++#include "httpd.h"
++
++#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
++
++#ifndef NULL
++#define NULL (void *)0
++#endif /* NULL */
++
++/*-----------------------------------------------------------------------------------*/
++int
++main(void)
++{
++ u8_t i, arptimer;
++ tapdev_init();
++ uip_init();
++ httpd_init();
++ arptimer = 0;
++ while(1) {
++ uip_len = tapdev_read();
++ if(uip_len == 0) {
++ for(i = 0; i < UIP_CONNS; i++) {
++ uip_periodic(i);
++ if(uip_len > 0) {
++ uip_arp_out();
++ tapdev_send();
++ }
++ }
++
++ if(++arptimer == 20) {
++ uip_arp_timer();
++ arptimer = 0;
++ }
++ } else {
++ if(BUF->type == htons(UIP_ETHTYPE_IP)) {
++ uip_arp_ipin();
++ uip_input();
++ if(uip_len > 0) {
++ uip_arp_out();
++ tapdev_send();
++ }
++ } else if(BUF->type == htons(UIP_ETHTYPE_ARP)) {
++ uip_arp_arpin();
++ if(uip_len > 0) {
++ tapdev_send();
++ }
++ }
++ }
++ }
++ return 0;
++}
+--- /dev/null
++++ b/net/uip-0.9/tapdev.c
+@@ -0,0 +1,192 @@
++/*
++ * Copyright (c) 2001, Swedish Institute of Computer Science.
++ * 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
++ *
++ * Author: Adam Dunkels <adam@sics.se>
++ *
++ * $Id: tapdev.c,v 1.7.2.1 2003/10/07 13:23:19 adam Exp $
++ */
++
++
++#include <fcntl.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <unistd.h>
++#include <string.h>
++#include <sys/ioctl.h>
++#include <sys/socket.h>
++#include <sys/types.h>
++#include <sys/time.h>
++#include <sys/uio.h>
++#include <sys/socket.h>
++
++#ifdef linux
++#include <sys/ioctl.h>
++#include <linux/if.h>
++#include <linux/if_tun.h>
++#define DEVTAP "/dev/net/tun"
++#else /* linux */
++#define DEVTAP "/dev/tap0"
++#endif /* linux */
++
++#include "uip.h"
++
++static int fd;
++
++static unsigned long lasttime;
++static struct timezone tz;
++
++/*-----------------------------------------------------------------------------------*/
++void
++tapdev_init(void)
++{
++ char buf[1024];
++
++ fd = open(DEVTAP, O_RDWR);
++ if(fd == -1) {
++ perror("tapdev: tapdev_init: open");
++ exit(1);
++ }
++
++#ifdef linux
++ {
++ struct ifreq ifr;
++ memset(&ifr, 0, sizeof(ifr));
++ ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
++ if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
++ perror(buf);
++ exit(1);
++ }
++ }
++#endif /* Linux */
++
++ snprintf(buf, sizeof(buf), "ifconfig tap0 inet %d.%d.%d.%d",
++ UIP_DRIPADDR0, UIP_DRIPADDR1, UIP_DRIPADDR2, UIP_DRIPADDR3);
++ system(buf);
++
++ lasttime = 0;
++}
++
++void dump_mem(int type, int len)
++{
++#if DUMP == 1
++ int i;
++ for(i = 0; i < len; i++)
++ printf("%c", uip_buf[i]);
++ if(type)
++ {
++ printf("\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01");
++ printf("\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01");
++ } else {
++ printf("\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02");
++ printf("\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02");
++ }
++ fflush(stdout);
++#endif
++}
++
++/*-----------------------------------------------------------------------------------*/
++unsigned int
++tapdev_read(void)
++{
++ fd_set fdset;
++ struct timeval tv, now;
++ int ret;
++
++ if(lasttime >= 500000) {
++ lasttime = 0;
++ return 0;
++ }
++
++ tv.tv_sec = 0;
++ tv.tv_usec = 500000 - lasttime;
++
++
++ FD_ZERO(&fdset);
++ FD_SET(fd, &fdset);
++
++ gettimeofday(&now, &tz);
++ ret = select(fd + 1, &fdset, NULL, NULL, &tv);
++ if(ret == 0) {
++ lasttime = 0;
++ return 0;
++ }
++ ret = read(fd, uip_buf, UIP_BUFSIZE);
++ if(ret == -1) {
++ perror("tap_dev: tapdev_read: read");
++ }
++ gettimeofday(&tv, &tz);
++ lasttime += (tv.tv_sec - now.tv_sec) * 1000000 + (tv.tv_usec - now.tv_usec);
++ dump_mem(0, ret);
++ return ret;
++}
++/*-----------------------------------------------------------------------------------*/
++void
++tapdev_send(void)
++{
++ int ret;
++ struct iovec iov[2];
++
++#ifdef linux
++ {
++ char tmpbuf[UIP_BUFSIZE];
++ int i;
++
++ for(i = 0; i < 40 + UIP_LLH_LEN; i++) {
++ tmpbuf[i] = uip_buf[i];
++ }
++
++ for(; i < uip_len; i++) {
++ tmpbuf[i] = uip_appdata[i - 40 - UIP_LLH_LEN];
++ }
++
++ ret = write(fd, tmpbuf, uip_len);
++ }
++#else
++
++ if(uip_len < 40 + UIP_LLH_LEN) {
++ ret = write(fd, uip_buf, uip_len + UIP_LLH_LEN);
++ } else {
++ iov[0].iov_base = uip_buf;
++ iov[0].iov_len = 40 + UIP_LLH_LEN;
++ iov[1].iov_base = (char *)uip_appdata;
++ iov[1].iov_len = uip_len - (40 + UIP_LLH_LEN);
++
++ ret = writev(fd, iov, 2);
++ }
++#endif
++ dump_mem(1, ret);
++
++ if(ret == -1) {
++ perror("tap_dev: tapdev_send: writev");
++ exit(1);
++ }
++}
++/*-----------------------------------------------------------------------------------*/
+--- /dev/null
++++ b/net/uip-0.9/tapdev.h
+@@ -0,0 +1,42 @@
++/*
++ * Copyright (c) 2001, Adam Dunkels.
++ * 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.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: tapdev.h,v 1.1.2.1 2003/10/04 22:54:17 adam Exp $
++ *
++ */
++
++#ifndef __TAPDEV_H__
++#define __TAPDEV_H__
++
++void tapdev_init(void);
++unsigned int tapdev_read(void);
++void tapdev_send(void);
++
++#endif /* __TAPDEV_H__ */
+--- /dev/null
++++ b/net/uip-0.9/uip.c
+@@ -0,0 +1,1503 @@
++/**
++ * \addtogroup uip
++ * @{
++ */
++
++/**
++ * \file
++ * The uIP TCP/IP stack code.
++ * \author Adam Dunkels <adam@dunkels.com>
++ */
++
++/*
++ * Copyright (c) 2001-2003, Adam Dunkels.
++ * 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.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: uip.c,v 1.62.2.10 2003/10/07 13:23:01 adam Exp $
++ *
++ */
++
++/*
++This is a small implementation of the IP and TCP protocols (as well as
++some basic ICMP stuff). The implementation couples the IP, TCP and the
++application layers very tightly. To keep the size of the compiled code
++down, this code also features heavy usage of the goto statement.
++
++The principle is that we have a small buffer, called the uip_buf, in
++which the device driver puts an incoming packet. The TCP/IP stack
++parses the headers in the packet, and calls upon the application. If
++the remote host has sent data to the application, this data is present
++in the uip_buf and the application read the data from there. It is up
++to the application to put this data into a byte stream if needed. The
++application will not be fed with data that is out of sequence.
++
++If the application whishes to send data to the peer, it should put its
++data into the uip_buf, 40 bytes from the start of the buffer. The
++TCP/IP stack will calculate the checksums, and fill in the necessary
++header fields and finally send the packet back to the peer.
++*/
++
++#include "uip.h"
++#include "uipopt.h"
++#include "uip_arch.h"
++
++/*-----------------------------------------------------------------------------------*/
++/* Variable definitions. */
++
++
++/* The IP address of this host. If it is defined to be fixed (by setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set here. Otherwise, the address */
++#if UIP_FIXEDADDR > 0
++const unsigned short int uip_hostaddr[2] =
++ {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1),
++ HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)};
++const unsigned short int uip_arp_draddr[2] =
++ {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1),
++ HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)};
++const unsigned short int uip_arp_netmask[2] =
++ {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1),
++ HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};
++#else
++unsigned short int uip_hostaddr[2];
++unsigned short int uip_arp_draddr[2], uip_arp_netmask[2];
++#endif /* UIP_FIXEDADDR */
++
++u8_t uip_buf[UIP_BUFSIZE+2]; /* The packet buffer that contains
++ incoming packets. */
++volatile u8_t *uip_appdata; /* The uip_appdata pointer points to
++ application data. */
++volatile u8_t *uip_sappdata; /* The uip_appdata pointer points to the
++ application data which is to be sent. */
++#if UIP_URGDATA > 0
++volatile u8_t *uip_urgdata; /* The uip_urgdata pointer points to
++ urgent data (out-of-band data), if
++ present. */
++volatile u8_t uip_urglen, uip_surglen;
++#endif /* UIP_URGDATA > 0 */
++
++volatile unsigned short int uip_len, uip_slen;
++ /* The uip_len is either 8 or 16 bits,
++ depending on the maximum packet
++ size. */
++
++volatile u8_t uip_flags; /* The uip_flags variable is used for
++ communication between the TCP/IP stack
++ and the application program. */
++struct uip_conn *uip_conn; /* uip_conn always points to the current
++ connection. */
++
++struct uip_conn uip_conns[UIP_CONNS];
++ /* The uip_conns array holds all TCP
++ connections. */
++unsigned short int uip_listenports[UIP_LISTENPORTS];
++ /* The uip_listenports list all currently
++ listning ports. */
++#if UIP_UDP
++struct uip_udp_conn *uip_udp_conn;
++struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
++#endif /* UIP_UDP */
++
++
++static unsigned short int ipid; /* Ths ipid variable is an increasing
++ number that is used for the IP ID
++ field. */
++
++static u8_t iss[4]; /* The iss variable is used for the TCP
++ initial sequence number. */
++
++#if UIP_ACTIVE_OPEN
++static unsigned short int lastport; /* Keeps track of the last port used for
++ a new connection. */
++#endif /* UIP_ACTIVE_OPEN */
++
++/* Temporary variables. */
++volatile u8_t uip_acc32[4];
++static u8_t c, opt;
++static unsigned short int tmp16;
++
++/* Structures and definitions. */
++#define TCP_FIN 0x01
++#define TCP_SYN 0x02
++#define TCP_RST 0x04
++#define TCP_PSH 0x08
++#define TCP_ACK 0x10
++#define TCP_URG 0x20
++#define TCP_CTL 0x3f
++
++#define ICMP_ECHO_REPLY 0
++#define ICMP_ECHO 8
++
++/* Macros. */
++#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
++#define FBUF ((uip_tcpip_hdr *)&uip_reassbuf[0])
++#define ICMPBUF ((uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN])
++#define UDPBUF ((uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
++
++#if UIP_STATISTICS == 1
++struct uip_stats uip_stat;
++#define UIP_STAT(s) s
++#else
++#define UIP_STAT(s)
++#endif /* UIP_STATISTICS == 1 */
++
++#if UIP_LOGGING == 1
++extern void puts(const char *s);
++#define UIP_LOG(m) puts(m)
++#else
++#define UIP_LOG(m)
++#endif /* UIP_LOGGING == 1 */
++
++/*-----------------------------------------------------------------------------------*/
++void
++uip_init(void)
++{
++ for(c = 0; c < UIP_LISTENPORTS; ++c) {
++ uip_listenports[c] = 0;
++ }
++ for(c = 0; c < UIP_CONNS; ++c) {
++ uip_conns[c].tcpstateflags = CLOSED;
++ }
++#if UIP_ACTIVE_OPEN
++ lastport = 1024;
++#endif /* UIP_ACTIVE_OPEN */
++
++#if UIP_UDP
++ for(c = 0; c < UIP_UDP_CONNS; ++c) {
++ uip_udp_conns[c].lport = 0;
++ }
++#endif /* UIP_UDP */
++
++
++ /* IPv4 initialization. */
++#if UIP_FIXEDADDR == 0
++ uip_hostaddr[0] = uip_hostaddr[1] = 0;
++#endif /* UIP_FIXEDADDR */
++
++}
++/*-----------------------------------------------------------------------------------*/
++#if UIP_ACTIVE_OPEN
++struct uip_conn *
++uip_connect(unsigned short int *ripaddr, unsigned short int rport)
++{
++ register struct uip_conn *conn, *cconn;
++
++ /* Find an unused local port. */
++ again:
++ ++lastport;
++
++ if(lastport >= 32000) {
++ lastport = 4096;
++ }
++
++ /* Check if this port is already in use, and if so try to find
++ another one. */
++ for(c = 0; c < UIP_CONNS; ++c) {
++ conn = &uip_conns[c];
++ if(conn->tcpstateflags != CLOSED &&
++ conn->lport == htons(lastport)) {
++ goto again;
++ }
++ }
++
++
++ conn = 0;
++ for(c = 0; c < UIP_CONNS; ++c) {
++ cconn = &uip_conns[c];
++ if(cconn->tcpstateflags == CLOSED) {
++ conn = cconn;
++ break;
++ }
++ if(cconn->tcpstateflags == TIME_WAIT) {
++ if(conn == 0 ||
++ cconn->timer > uip_conn->timer) {
++ conn = cconn;
++ }
++ }
++ }
++
++ if(conn == 0) {
++ return 0;
++ }
++
++ conn->tcpstateflags = SYN_SENT;
++
++ conn->snd_nxt[0] = iss[0];
++ conn->snd_nxt[1] = iss[1];
++ conn->snd_nxt[2] = iss[2];
++ conn->snd_nxt[3] = iss[3];
++
++ conn->initialmss = conn->mss = UIP_TCP_MSS;
++
++ conn->len = 1; /* TCP length of the SYN is one. */
++ conn->nrtx = 0;
++ conn->timer = 1; /* Send the SYN next time around. */
++ conn->rto = UIP_RTO;
++ conn->sa = 0;
++ conn->sv = 16;
++ conn->lport = htons(lastport);
++ conn->rport = rport;
++ conn->ripaddr[0] = ripaddr[0];
++ conn->ripaddr[1] = ripaddr[1];
++
++ return conn;
++}
++#endif /* UIP_ACTIVE_OPEN */
++/*-----------------------------------------------------------------------------------*/
++#if UIP_UDP
++struct uip_udp_conn *
++uip_udp_new(unsigned short int *ripaddr, unsigned short int rport)
++{
++ register struct uip_udp_conn *conn;
++
++ /* Find an unused local port. */
++ again:
++ ++lastport;
++
++ if(lastport >= 32000) {
++ lastport = 4096;
++ }
++
++ for(c = 0; c < UIP_UDP_CONNS; ++c) {
++ if(uip_udp_conns[c].lport == lastport) {
++ goto again;
++ }
++ }
++
++
++ conn = 0;
++ for(c = 0; c < UIP_UDP_CONNS; ++c) {
++ if(uip_udp_conns[c].lport == 0) {
++ conn = &uip_udp_conns[c];
++ break;
++ }
++ }
++
++ if(conn == 0) {
++ return 0;
++ }
++
++ conn->lport = HTONS(lastport);
++ conn->rport = HTONS(rport);
++ conn->ripaddr[0] = ripaddr[0];
++ conn->ripaddr[1] = ripaddr[1];
++
++ return conn;
++}
++#endif /* UIP_UDP */
++/*-----------------------------------------------------------------------------------*/
++void
++uip_unlisten(unsigned short int port)
++{
++ for(c = 0; c < UIP_LISTENPORTS; ++c) {
++ if(uip_listenports[c] == port) {
++ uip_listenports[c] = 0;
++ return;
++ }
++ }
++}
++/*-----------------------------------------------------------------------------------*/
++void
++uip_listen(unsigned short int port)
++{
++ for(c = 0; c < UIP_LISTENPORTS; ++c) {
++ if(uip_listenports[c] == 0) {
++ uip_listenports[c] = port;
++ return;
++ }
++ }
++}
++/*-----------------------------------------------------------------------------------*/
++/* XXX: IP fragment reassembly: not well-tested. */
++
++#if UIP_REASSEMBLY
++#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)
++static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];
++static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)];
++static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f,
++ 0x0f, 0x07, 0x03, 0x01};
++static unsigned short int uip_reasslen;
++static u8_t uip_reassflags;
++#define UIP_REASS_FLAG_LASTFRAG 0x01
++static u8_t uip_reasstmr;
++
++#define IP_HLEN 20
++#define IP_MF 0x20
++
++static u8_t
++uip_reass(void)
++{
++ unsigned short int offset, len;
++ unsigned short int i;
++
++ /* If ip_reasstmr is zero, no packet is present in the buffer, so we
++ write the IP header of the fragment into the reassembly
++ buffer. The timer is updated with the maximum age. */
++ if(uip_reasstmr == 0) {
++ memcpy(uip_reassbuf, &BUF->vhl, IP_HLEN);
++ uip_reasstmr = UIP_REASS_MAXAGE;
++ uip_reassflags = 0;
++ /* Clear the bitmap. */
++ memset(uip_reassbitmap, sizeof(uip_reassbitmap), 0);
++ }
++
++ /* Check if the incoming fragment matches the one currently present
++ in the reasembly buffer. If so, we proceed with copying the
++ fragment into the buffer. */
++ if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&
++ BUF->srcipaddr[1] == FBUF->srcipaddr[1] &&
++ BUF->destipaddr[0] == FBUF->destipaddr[0] &&
++ BUF->destipaddr[1] == FBUF->destipaddr[1] &&
++ BUF->ipid[0] == FBUF->ipid[0] &&
++ BUF->ipid[1] == FBUF->ipid[1]) {
++
++ len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4;
++ offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8;
++
++ /* If the offset or the offset + fragment length overflows the
++ reassembly buffer, we discard the entire packet. */
++ if(offset > UIP_REASS_BUFSIZE ||
++ offset + len > UIP_REASS_BUFSIZE) {
++ uip_reasstmr = 0;
++ goto nullreturn;
++ }
++
++ /* Copy the fragment into the reassembly buffer, at the right
++ offset. */
++ memcpy(&uip_reassbuf[IP_HLEN + offset],
++ (char *)BUF + (int)((BUF->vhl & 0x0f) * 4),
++ len);
++
++ /* Update the bitmap. */
++ if(offset / (8 * 8) == (offset + len) / (8 * 8)) {
++ /* If the two endpoints are in the same byte, we only update
++ that byte. */
++
++ uip_reassbitmap[offset / (8 * 8)] |=
++ bitmap_bits[(offset / 8 ) & 7] &
++ ~bitmap_bits[((offset + len) / 8 ) & 7];
++ } else {
++ /* If the two endpoints are in different bytes, we update the
++ bytes in the endpoints and fill the stuff inbetween with
++ 0xff. */
++ uip_reassbitmap[offset / (8 * 8)] |=
++ bitmap_bits[(offset / 8 ) & 7];
++ for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
++ uip_reassbitmap[i] = 0xff;
++ }
++ uip_reassbitmap[(offset + len) / (8 * 8)] |=
++ ~bitmap_bits[((offset + len) / 8 ) & 7];
++ }
++
++ /* If this fragment has the More Fragments flag set to zero, we
++ know that this is the last fragment, so we can calculate the
++ size of the entire packet. We also set the
++ IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
++ the final fragment. */
++
++ if((BUF->ipoffset[0] & IP_MF) == 0) {
++ uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
++ uip_reasslen = offset + len;
++ }
++
++ /* Finally, we check if we have a full packet in the buffer. We do
++ this by checking if we have the last fragment and if all bits
++ in the bitmap are set. */
++ if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {
++ /* Check all bytes up to and including all but the last byte in
++ the bitmap. */
++ for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {
++ if(uip_reassbitmap[i] != 0xff) {
++ goto nullreturn;
++ }
++ }
++ /* Check the last byte in the bitmap. It should contain just the
++ right amount of bits. */
++ if(uip_reassbitmap[uip_reasslen / (8 * 8)] !=
++ (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) {
++ goto nullreturn;
++ }
++
++ /* If we have come this far, we have a full packet in the
++ buffer, so we allocate a pbuf and copy the packet into it. We
++ also reset the timer. */
++ uip_reasstmr = 0;
++ memcpy(BUF, FBUF, uip_reasslen);
++
++ /* Pretend to be a "normal" (i.e., not fragmented) IP packet
++ from now on. */
++ BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
++ BUF->len[0] = uip_reasslen >> 8;
++ BUF->len[1] = uip_reasslen & 0xff;
++ BUF->ipchksum = 0;
++ BUF->ipchksum = ~(uip_ipchksum());
++
++ return uip_reasslen;
++ }
++ }
++
++ nullreturn:
++ return 0;
++}
++#endif /* UIP_REASSEMBL */
++/*-----------------------------------------------------------------------------------*/
++static void
++uip_add_rcv_nxt(unsigned short int n)
++{
++ uip_add32(uip_conn->rcv_nxt, n);
++ uip_conn->rcv_nxt[0] = uip_acc32[0];
++ uip_conn->rcv_nxt[1] = uip_acc32[1];
++ uip_conn->rcv_nxt[2] = uip_acc32[2];
++ uip_conn->rcv_nxt[3] = uip_acc32[3];
++}
++/*-----------------------------------------------------------------------------------*/
++void
++uip_process(u8_t flag)
++{
++ register struct uip_conn *uip_connr = uip_conn;
++
++ uip_appdata = &uip_buf[40 + UIP_LLH_LEN];
++
++
++ /* Check if we were invoked because of the perodic timer fireing. */
++ if(flag == UIP_TIMER) {
++#if UIP_REASSEMBLY
++ if(uip_reasstmr != 0) {
++ --uip_reasstmr;
++ }
++#endif /* UIP_REASSEMBLY */
++ /* Increase the initial sequence number. */
++ if(++iss[3] == 0) {
++ if(++iss[2] == 0) {
++ if(++iss[1] == 0) {
++ ++iss[0];
++ }
++ }
++ }
++ uip_len = 0;
++ if(uip_connr->tcpstateflags == TIME_WAIT ||
++ uip_connr->tcpstateflags == FIN_WAIT_2) {
++ ++(uip_connr->timer);
++ if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) {
++ uip_connr->tcpstateflags = CLOSED;
++ }
++ } else if(uip_connr->tcpstateflags != CLOSED) {
++ /* If the connection has outstanding data, we increase the
++ connection's timer and see if it has reached the RTO value
++ in which case we retransmit. */
++ if(uip_outstanding(uip_connr)) {
++ if(uip_connr->timer-- == 0) {
++ if(uip_connr->nrtx == UIP_MAXRTX ||
++ ((uip_connr->tcpstateflags == SYN_SENT ||
++ uip_connr->tcpstateflags == SYN_RCVD) &&
++ uip_connr->nrtx == UIP_MAXSYNRTX)) {
++ uip_connr->tcpstateflags = CLOSED;
++
++ /* We call UIP_APPCALL() with uip_flags set to
++ UIP_TIMEDOUT to inform the application that the
++ connection has timed out. */
++ uip_flags = UIP_TIMEDOUT;
++ UIP_APPCALL();
++
++ /* We also send a reset packet to the remote host. */
++ BUF->flags = TCP_RST | TCP_ACK;
++ goto tcp_send_nodata;
++ }
++
++ /* Exponential backoff. */
++ uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?
++ 4:
++ uip_connr->nrtx);
++ ++(uip_connr->nrtx);
++
++ /* Ok, so we need to retransmit. We do this differently
++ depending on which state we are in. In ESTABLISHED, we
++ call upon the application so that it may prepare the
++ data for the retransmit. In SYN_RCVD, we resend the
++ SYNACK that we sent earlier and in LAST_ACK we have to
++ retransmit our FINACK. */
++ UIP_STAT(++uip_stat.tcp.rexmit);
++ switch(uip_connr->tcpstateflags & TS_MASK) {
++ case SYN_RCVD:
++ /* In the SYN_RCVD state, we should retransmit our
++ SYNACK. */
++ goto tcp_send_synack;
++
++#if UIP_ACTIVE_OPEN
++ case SYN_SENT:
++ /* In the SYN_SENT state, we retransmit out SYN. */
++ BUF->flags = 0;
++ goto tcp_send_syn;
++#endif /* UIP_ACTIVE_OPEN */
++
++ case ESTABLISHED:
++ /* In the ESTABLISHED state, we call upon the application
++ to do the actual retransmit after which we jump into
++ the code for sending out the packet (the apprexmit
++ label). */
++ uip_len = 0;
++ uip_slen = 0;
++ uip_flags = UIP_REXMIT;
++ UIP_APPCALL();
++ goto apprexmit;
++
++ case FIN_WAIT_1:
++ case CLOSING:
++ case LAST_ACK:
++ /* In all these states we should retransmit a FINACK. */
++ goto tcp_send_finack;
++
++ }
++ }
++ } else if((uip_connr->tcpstateflags & TS_MASK) == ESTABLISHED) {
++ /* If there was no need for a retransmission, we poll the
++ application for new data. */
++ uip_len = 0;
++ uip_slen = 0;
++ uip_flags = UIP_POLL;
++ UIP_APPCALL();
++ goto appsend;
++ }
++ }
++ goto drop;
++ }
++#if UIP_UDP
++ if(flag == UIP_UDP_TIMER) {
++ if(uip_udp_conn->lport != 0) {
++ uip_appdata = &uip_buf[UIP_LLH_LEN + 28];
++ uip_len = uip_slen = 0;
++ uip_flags = UIP_POLL;
++ UIP_UDP_APPCALL();
++ goto udp_send;
++ } else {
++ goto drop;
++ }
++ }
++#endif
++
++ /* This is where the input processing starts. */
++ UIP_STAT(++uip_stat.ip.recv);
++
++
++ /* Start of IPv4 input header processing code. */
++
++ /* Check validity of the IP header. */
++ if(BUF->vhl != 0x45) { /* IP version and header length. */
++ UIP_STAT(++uip_stat.ip.drop);
++ UIP_STAT(++uip_stat.ip.vhlerr);
++ UIP_LOG("ip: invalid version or header length.");
++ goto drop;
++ }
++
++ /* Check the size of the packet. If the size reported to us in
++ uip_len doesn't match the size reported in the IP header, there
++ has been a transmission error and we drop the packet. */
++
++ if(BUF->len[0] != (uip_len >> 8)) { /* IP length, high byte. */
++ uip_len = (uip_len & 0xff) | (BUF->len[0] << 8);
++ }
++ if(BUF->len[1] != (uip_len & 0xff)) { /* IP length, low byte. */
++ uip_len = (uip_len & 0xff00) | BUF->len[1];
++ }
++
++ /* Check the fragment flag. */
++ if((BUF->ipoffset[0] & 0x3f) != 0 ||
++ BUF->ipoffset[1] != 0) {
++#if UIP_REASSEMBLY
++ uip_len = uip_reass();
++ if(uip_len == 0) {
++ goto drop;
++ }
++#else
++ UIP_STAT(++uip_stat.ip.drop);
++ UIP_STAT(++uip_stat.ip.fragerr);
++ UIP_LOG("ip: fragment dropped.");
++ goto drop;
++#endif /* UIP_REASSEMBLY */
++ }
++
++ /* If we are configured to use ping IP address configuration and
++ hasn't been assigned an IP address yet, we accept all ICMP
++ packets. */
++#if UIP_PINGADDRCONF
++ if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {
++ if(BUF->proto == UIP_PROTO_ICMP) {
++ UIP_LOG("ip: possible ping config packet received.");
++ goto icmp_input;
++ } else {
++ UIP_LOG("ip: packet dropped since no address assigned.");
++ goto drop;
++ }
++ }
++#endif /* UIP_PINGADDRCONF */
++
++ /* Check if the packet is destined for our IP address. */
++ if(BUF->destipaddr[0] != uip_hostaddr[0]) {
++ UIP_STAT(++uip_stat.ip.drop);
++ UIP_LOG("ip: packet not for us.");
++ goto drop;
++ }
++ if(BUF->destipaddr[1] != uip_hostaddr[1]) {
++ UIP_STAT(++uip_stat.ip.drop);
++ UIP_LOG("ip: packet not for us.");
++ goto drop;
++ }
++
++ if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header
++ checksum. */
++ UIP_STAT(++uip_stat.ip.drop);
++ UIP_STAT(++uip_stat.ip.chkerr);
++ UIP_LOG("ip: bad checksum.");
++ goto drop;
++ }
++
++ if(BUF->proto == UIP_PROTO_TCP) /* Check for TCP packet. If so, jump
++ to the tcp_input label. */
++ goto tcp_input;
++
++#if UIP_UDP
++ if(BUF->proto == UIP_PROTO_UDP)
++ goto udp_input;
++#endif /* UIP_UDP */
++
++ if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from
++ here. */
++ UIP_STAT(++uip_stat.ip.drop);
++ UIP_STAT(++uip_stat.ip.protoerr);
++ UIP_LOG("ip: neither tcp nor icmp.");
++ goto drop;
++ }
++
++ //icmp_input:
++ UIP_STAT(++uip_stat.icmp.recv);
++
++ /* ICMP echo (i.e., ping) processing. This is simple, we only change
++ the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP
++ checksum before we return the packet. */
++ if(ICMPBUF->type != ICMP_ECHO) {
++ UIP_STAT(++uip_stat.icmp.drop);
++ UIP_STAT(++uip_stat.icmp.typeerr);
++ UIP_LOG("icmp: not icmp echo.");
++ goto drop;
++ }
++
++ /* If we are configured to use ping IP address assignment, we use
++ the destination IP address of this ping packet and assign it to
++ ourself. */
++#if UIP_PINGADDRCONF
++ if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {
++ uip_hostaddr[0] = BUF->destipaddr[0];
++ uip_hostaddr[1] = BUF->destipaddr[1];
++ }
++#endif /* UIP_PINGADDRCONF */
++
++ ICMPBUF->type = ICMP_ECHO_REPLY;
++
++ if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) {
++ ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1;
++ } else {
++ ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8);
++ }
++
++ /* Swap IP addresses. */
++ tmp16 = BUF->destipaddr[0];
++ BUF->destipaddr[0] = BUF->srcipaddr[0];
++ BUF->srcipaddr[0] = tmp16;
++ tmp16 = BUF->destipaddr[1];
++ BUF->destipaddr[1] = BUF->srcipaddr[1];
++ BUF->srcipaddr[1] = tmp16;
++
++ UIP_STAT(++uip_stat.icmp.sent);
++ goto send;
++
++ /* End of IPv4 input header processing code. */
++
++
++#if UIP_UDP
++ /* UDP input processing. */
++ udp_input:
++ /* UDP processing is really just a hack. We don't do anything to the
++ UDP/IP headers, but let the UDP application do all the hard
++ work. If the application sets uip_slen, it has a packet to
++ send. */
++#if UIP_UDP_CHECKSUMS
++ if(uip_udpchksum() != 0xffff) {
++ UIP_STAT(++uip_stat.udp.drop);
++ UIP_STAT(++uip_stat.udp.chkerr);
++ UIP_LOG("udp: bad checksum.");
++ goto drop;
++ }
++#endif /* UIP_UDP_CHECKSUMS */
++
++ /* Demultiplex this UDP packet between the UDP "connections". */
++ for(uip_udp_conn = &uip_udp_conns[0];
++ uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS];
++ ++uip_udp_conn) {
++ if(uip_udp_conn->lport != 0 &&
++ UDPBUF->destport == uip_udp_conn->lport &&
++ (uip_udp_conn->rport == 0 ||
++ UDPBUF->srcport == uip_udp_conn->rport) &&
++ BUF->srcipaddr[0] == uip_udp_conn->ripaddr[0] &&
++ BUF->srcipaddr[1] == uip_udp_conn->ripaddr[1]) {
++ goto udp_found;
++ }
++ }
++ goto drop;
++
++ udp_found:
++ uip_len = uip_len - 28;
++ uip_appdata = &uip_buf[UIP_LLH_LEN + 28];
++ uip_flags = UIP_NEWDATA;
++ uip_slen = 0;
++ UIP_UDP_APPCALL();
++ udp_send:
++ if(uip_slen == 0) {
++ goto drop;
++ }
++ uip_len = uip_slen + 28;
++
++ BUF->len[0] = (uip_len >> 8);
++ BUF->len[1] = (uip_len & 0xff);
++
++ BUF->proto = UIP_PROTO_UDP;
++
++ UDPBUF->udplen = HTONS(uip_slen + 8);
++ UDPBUF->udpchksum = 0;
++#if UIP_UDP_CHECKSUMS
++ /* Calculate UDP checksum. */
++ UDPBUF->udpchksum = ~(uip_udpchksum());
++ if(UDPBUF->udpchksum == 0) {
++ UDPBUF->udpchksum = 0xffff;
++ }
++#endif /* UIP_UDP_CHECKSUMS */
++
++ BUF->srcport = uip_udp_conn->lport;
++ BUF->destport = uip_udp_conn->rport;
++
++ BUF->srcipaddr[0] = uip_hostaddr[0];
++ BUF->srcipaddr[1] = uip_hostaddr[1];
++ BUF->destipaddr[0] = uip_udp_conn->ripaddr[0];
++ BUF->destipaddr[1] = uip_udp_conn->ripaddr[1];
++
++ uip_appdata = &uip_buf[UIP_LLH_LEN + 40];
++ goto ip_send_nolen;
++#endif /* UIP_UDP */
++
++ /* TCP input processing. */
++ tcp_input:
++ UIP_STAT(++uip_stat.tcp.recv);
++
++ /* Start of TCP input header processing code. */
++
++ if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP
++ checksum. */
++ UIP_STAT(++uip_stat.tcp.drop);
++ UIP_STAT(++uip_stat.tcp.chkerr);
++ UIP_LOG("tcp: bad checksum.");
++ goto drop;
++ }
++
++ /* Demultiplex this segment. */
++ /* First check any active connections. */
++ for(uip_connr = &uip_conns[0]; uip_connr < &uip_conns[UIP_CONNS]; ++uip_connr) {
++ if(uip_connr->tcpstateflags != CLOSED &&
++ BUF->destport == uip_connr->lport &&
++ BUF->srcport == uip_connr->rport &&
++ BUF->srcipaddr[0] == uip_connr->ripaddr[0] &&
++ BUF->srcipaddr[1] == uip_connr->ripaddr[1]) {
++ goto found;
++ }
++ }
++
++ /* If we didn't find and active connection that expected the packet,
++ either this packet is an old duplicate, or this is a SYN packet
++ destined for a connection in LISTEN. If the SYN flag isn't set,
++ it is an old packet and we send a RST. */
++ if((BUF->flags & TCP_CTL) != TCP_SYN)
++ goto reset;
++
++ tmp16 = BUF->destport;
++ /* Next, check listening connections. */
++ for(c = 0; c < UIP_LISTENPORTS; ++c) {
++ if(tmp16 == uip_listenports[c])
++ goto found_listen;
++ }
++
++ /* No matching connection found, so we send a RST packet. */
++ UIP_STAT(++uip_stat.tcp.synrst);
++ reset:
++
++ /* We do not send resets in response to resets. */
++ if(BUF->flags & TCP_RST)
++ goto drop;
++
++ UIP_STAT(++uip_stat.tcp.rst);
++
++ BUF->flags = TCP_RST | TCP_ACK;
++ uip_len = 40;
++ BUF->tcpoffset = 5 << 4;
++
++ /* Flip the seqno and ackno fields in the TCP header. */
++ c = BUF->seqno[3];
++ BUF->seqno[3] = BUF->ackno[3];
++ BUF->ackno[3] = c;
++
++ c = BUF->seqno[2];
++ BUF->seqno[2] = BUF->ackno[2];
++ BUF->ackno[2] = c;
++
++ c = BUF->seqno[1];
++ BUF->seqno[1] = BUF->ackno[1];
++ BUF->ackno[1] = c;
++
++ c = BUF->seqno[0];
++ BUF->seqno[0] = BUF->ackno[0];
++ BUF->ackno[0] = c;
++
++ /* We also have to increase the sequence number we are
++ acknowledging. If the least significant byte overflowed, we need
++ to propagate the carry to the other bytes as well. */
++ if(++BUF->ackno[3] == 0) {
++ if(++BUF->ackno[2] == 0) {
++ if(++BUF->ackno[1] == 0) {
++ ++BUF->ackno[0];
++ }
++ }
++ }
++
++ /* Swap port numbers. */
++ tmp16 = BUF->srcport;
++ BUF->srcport = BUF->destport;
++ BUF->destport = tmp16;
++
++ /* Swap IP addresses. */
++ tmp16 = BUF->destipaddr[0];
++ BUF->destipaddr[0] = BUF->srcipaddr[0];
++ BUF->srcipaddr[0] = tmp16;
++ tmp16 = BUF->destipaddr[1];
++ BUF->destipaddr[1] = BUF->srcipaddr[1];
++ BUF->srcipaddr[1] = tmp16;
++
++
++ /* And send out the RST packet! */
++ goto tcp_send_noconn;
++
++ /* This label will be jumped to if we matched the incoming packet
++ with a connection in LISTEN. In that case, we should create a new
++ connection and send a SYNACK in return. */
++ found_listen:
++ /* First we check if there are any connections avaliable. Unused
++ connections are kept in the same table as used connections, but
++ unused ones have the tcpstate set to CLOSED. Also, connections in
++ TIME_WAIT are kept track of and we'll use the oldest one if no
++ CLOSED connections are found. Thanks to Eddie C. Dost for a very
++ nice algorithm for the TIME_WAIT search. */
++ uip_connr = 0;
++ for(c = 0; c < UIP_CONNS; ++c) {
++ if(uip_conns[c].tcpstateflags == CLOSED) {
++ uip_connr = &uip_conns[c];
++ break;
++ }
++ if(uip_conns[c].tcpstateflags == TIME_WAIT) {
++ if(uip_connr == 0 ||
++ uip_conns[c].timer > uip_connr->timer) {
++ uip_connr = &uip_conns[c];
++ }
++ }
++ }
++
++ if(uip_connr == 0) {
++ /* All connections are used already, we drop packet and hope that
++ the remote end will retransmit the packet at a time when we
++ have more spare connections. */
++ UIP_STAT(++uip_stat.tcp.syndrop);
++ UIP_LOG("tcp: found no unused connections.");
++ goto drop;
++ }
++ uip_conn = uip_connr;
++
++ /* Fill in the necessary fields for the new connection. */
++ uip_connr->rto = uip_connr->timer = UIP_RTO;
++ uip_connr->sa = 0;
++ uip_connr->sv = 4;
++ uip_connr->nrtx = 0;
++ uip_connr->lport = BUF->destport;
++ uip_connr->rport = BUF->srcport;
++ uip_connr->ripaddr[0] = BUF->srcipaddr[0];
++ uip_connr->ripaddr[1] = BUF->srcipaddr[1];
++ uip_connr->tcpstateflags = SYN_RCVD;
++
++ uip_connr->snd_nxt[0] = iss[0];
++ uip_connr->snd_nxt[1] = iss[1];
++ uip_connr->snd_nxt[2] = iss[2];
++ uip_connr->snd_nxt[3] = iss[3];
++ uip_connr->len = 1;
++
++ /* rcv_nxt should be the seqno from the incoming packet + 1. */
++ uip_connr->rcv_nxt[3] = BUF->seqno[3];
++ uip_connr->rcv_nxt[2] = BUF->seqno[2];
++ uip_connr->rcv_nxt[1] = BUF->seqno[1];
++ uip_connr->rcv_nxt[0] = BUF->seqno[0];
++ uip_add_rcv_nxt(1);
++
++ /* Parse the TCP MSS option, if present. */
++ if((BUF->tcpoffset & 0xf0) > 0x50) {
++ for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
++ opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
++ if(opt == 0x00) {
++ /* End of options. */
++ break;
++ } else if(opt == 0x01) {
++ ++c;
++ /* NOP option. */
++ } else if(opt == 0x02 &&
++ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) {
++ /* An MSS option with the right option length. */
++ tmp16 = ((unsigned short int)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
++ (unsigned short int)uip_buf[40 + UIP_LLH_LEN + 3 + c];
++ uip_connr->initialmss = uip_connr->mss =
++ tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
++
++ /* And we are done processing options. */
++ break;
++ } else {
++ /* All other options have a length field, so that we easily
++ can skip past them. */
++ if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
++ /* If the length field is zero, the options are malformed
++ and we don't process them further. */
++ break;
++ }
++ c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
++ }
++ }
++ }
++
++ /* Our response will be a SYNACK. */
++#if UIP_ACTIVE_OPEN
++ tcp_send_synack:
++ BUF->flags = TCP_ACK;
++
++ tcp_send_syn:
++ BUF->flags |= TCP_SYN;
++#else /* UIP_ACTIVE_OPEN */
++ tcp_send_synack:
++ BUF->flags = TCP_SYN | TCP_ACK;
++#endif /* UIP_ACTIVE_OPEN */
++
++ /* We send out the TCP Maximum Segment Size option with our
++ SYNACK. */
++ BUF->optdata[0] = 2;
++ BUF->optdata[1] = 4;
++ BUF->optdata[2] = (UIP_TCP_MSS) / 256;
++ BUF->optdata[3] = (UIP_TCP_MSS) & 255;
++ uip_len = 44;
++ BUF->tcpoffset = 6 << 4;
++ goto tcp_send;
++
++ /* This label will be jumped to if we found an active connection. */
++ found:
++ uip_conn = uip_connr;
++ uip_flags = 0;
++
++ /* We do a very naive form of TCP reset processing; we just accept
++ any RST and kill our connection. We should in fact check if the
++ sequence number of this reset is wihtin our advertised window
++ before we accept the reset. */
++ if(BUF->flags & TCP_RST) {
++ uip_connr->tcpstateflags = CLOSED;
++ UIP_LOG("tcp: got reset, aborting connection.");
++ uip_flags = UIP_ABORT;
++ UIP_APPCALL();
++ goto drop;
++ }
++ /* Calculated the length of the data, if the application has sent
++ any data to us. */
++ c = (BUF->tcpoffset >> 4) << 2;
++ /* uip_len will contain the length of the actual TCP data. This is
++ calculated by subtracing the length of the TCP header (in
++ c) and the length of the IP header (20 bytes). */
++ uip_len = uip_len - c - 20;
++
++ /* First, check if the sequence number of the incoming packet is
++ what we're expecting next. If not, we send out an ACK with the
++ correct numbers in. */
++ if(uip_len > 0 &&
++ (BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
++ BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
++ BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
++ BUF->seqno[3] != uip_connr->rcv_nxt[3])) {
++ goto tcp_send_ack;
++ }
++
++ /* Next, check if the incoming segment acknowledges any outstanding
++ data. If so, we update the sequence number, reset the length of
++ the outstanding data, calculate RTT estimations, and reset the
++ retransmission timer. */
++ if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) {
++ uip_add32(uip_connr->snd_nxt, uip_connr->len);
++ if(BUF->ackno[0] == uip_acc32[0] &&
++ BUF->ackno[1] == uip_acc32[1] &&
++ BUF->ackno[2] == uip_acc32[2] &&
++ BUF->ackno[3] == uip_acc32[3]) {
++ /* Update sequence number. */
++ uip_connr->snd_nxt[0] = uip_acc32[0];
++ uip_connr->snd_nxt[1] = uip_acc32[1];
++ uip_connr->snd_nxt[2] = uip_acc32[2];
++ uip_connr->snd_nxt[3] = uip_acc32[3];
++
++
++ /* Do RTT estimation, unless we have done retransmissions. */
++ if(uip_connr->nrtx == 0) {
++ signed char m;
++ m = uip_connr->rto - uip_connr->timer;
++ /* This is taken directly from VJs original code in his paper */
++ m = m - (uip_connr->sa >> 3);
++ uip_connr->sa += m;
++ if(m < 0) {
++ m = -m;
++ }
++ m = m - (uip_connr->sv >> 2);
++ uip_connr->sv += m;
++ uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;
++
++ }
++ /* Set the acknowledged flag. */
++ uip_flags = UIP_ACKDATA;
++ /* Reset the retransmission timer. */
++ uip_connr->timer = uip_connr->rto;
++ }
++
++ }
++
++ /* Do different things depending on in what state the connection is. */
++ switch(uip_connr->tcpstateflags & TS_MASK) {
++ /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not
++ implemented, since we force the application to close when the
++ peer sends a FIN (hence the application goes directly from
++ ESTABLISHED to LAST_ACK). */
++ case SYN_RCVD:
++ /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and
++ we are waiting for an ACK that acknowledges the data we sent
++ out the last time. Therefore, we want to have the UIP_ACKDATA
++ flag set. If so, we enter the ESTABLISHED state. */
++ if(uip_flags & UIP_ACKDATA) {
++ uip_connr->tcpstateflags = ESTABLISHED;
++ uip_flags = UIP_CONNECTED;
++ uip_connr->len = 0;
++ if(uip_len > 0) {
++ uip_flags |= UIP_NEWDATA;
++ uip_add_rcv_nxt(uip_len);
++ }
++ uip_slen = 0;
++ UIP_APPCALL();
++ goto appsend;
++ }
++ goto drop;
++#if UIP_ACTIVE_OPEN
++ case SYN_SENT:
++ /* In SYN_SENT, we wait for a SYNACK that is sent in response to
++ our SYN. The rcv_nxt is set to sequence number in the SYNACK
++ plus one, and we send an ACK. We move into the ESTABLISHED
++ state. */
++ if((uip_flags & UIP_ACKDATA) &&
++ BUF->flags == (TCP_SYN | TCP_ACK)) {
++
++ /* Parse the TCP MSS option, if present. */
++ if((BUF->tcpoffset & 0xf0) > 0x50) {
++ for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
++ opt = uip_buf[40 + UIP_LLH_LEN + c];
++ if(opt == 0x00) {
++ /* End of options. */
++ break;
++ } else if(opt == 0x01) {
++ ++c;
++ /* NOP option. */
++ } else if(opt == 0x02 &&
++ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) {
++ /* An MSS option with the right option length. */
++ tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
++ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
++ uip_connr->initialmss =
++ uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
++
++ /* And we are done processing options. */
++ break;
++ } else {
++ /* All other options have a length field, so that we easily
++ can skip past them. */
++ if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
++ /* If the length field is zero, the options are malformed
++ and we don't process them further. */
++ break;
++ }
++ c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
++ }
++ }
++ }
++ uip_connr->tcpstateflags = ESTABLISHED;
++ uip_connr->rcv_nxt[0] = BUF->seqno[0];
++ uip_connr->rcv_nxt[1] = BUF->seqno[1];
++ uip_connr->rcv_nxt[2] = BUF->seqno[2];
++ uip_connr->rcv_nxt[3] = BUF->seqno[3];
++ uip_add_rcv_nxt(1);
++ uip_flags = UIP_CONNECTED | UIP_NEWDATA;
++ uip_connr->len = 0;
++ uip_len = 0;
++ uip_slen = 0;
++ UIP_APPCALL();
++ goto appsend;
++ }
++ goto reset;
++#endif /* UIP_ACTIVE_OPEN */
++
++ case ESTABLISHED:
++ /* In the ESTABLISHED state, we call upon the application to feed
++ data into the uip_buf. If the UIP_ACKDATA flag is set, the
++ application should put new data into the buffer, otherwise we are
++ retransmitting an old segment, and the application should put that
++ data into the buffer.
++
++ If the incoming packet is a FIN, we should close the connection on
++ this side as well, and we send out a FIN and enter the LAST_ACK
++ state. We require that there is no outstanding data; otherwise the
++ sequence numbers will be screwed up. */
++
++ if(BUF->flags & TCP_FIN) {
++ if(uip_outstanding(uip_connr)) {
++ goto drop;
++ }
++ uip_add_rcv_nxt(1 + uip_len);
++ uip_flags = UIP_CLOSE;
++ if(uip_len > 0) {
++ uip_flags |= UIP_NEWDATA;
++ }
++ UIP_APPCALL();
++ uip_connr->len = 1;
++ uip_connr->tcpstateflags = LAST_ACK;
++ uip_connr->nrtx = 0;
++ tcp_send_finack:
++ BUF->flags = TCP_FIN | TCP_ACK;
++ goto tcp_send_nodata;
++ }
++
++ /* Check the URG flag. If this is set, the segment carries urgent
++ data that we must pass to the application. */
++ if(BUF->flags & TCP_URG) {
++#if UIP_URGDATA > 0
++ uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1];
++ if(uip_urglen > uip_len) {
++ /* There is more urgent data in the next segment to come. */
++ uip_urglen = uip_len;
++ }
++ uip_add_rcv_nxt(uip_urglen);
++ uip_len -= uip_urglen;
++ uip_urgdata = uip_appdata;
++ uip_appdata += uip_urglen;
++ } else {
++ uip_urglen = 0;
++#endif /* UIP_URGDATA > 0 */
++ uip_appdata += (BUF->urgp[0] << 8) | BUF->urgp[1];
++ uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1];
++ }
++
++
++ /* If uip_len > 0 we have TCP data in the packet, and we flag this
++ by setting the UIP_NEWDATA flag and update the sequence number
++ we acknowledge. If the application has stopped the dataflow
++ using uip_stop(), we must not accept any data packets from the
++ remote host. */
++ if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
++ uip_flags |= UIP_NEWDATA;
++ uip_add_rcv_nxt(uip_len);
++ }
++
++ /* Check if the available buffer space advertised by the other end
++ is smaller than the initial MSS for this connection. If so, we
++ set the current MSS to the window size to ensure that the
++ application does not send more data than the other end can
++ handle.
++
++ If the remote host advertises a zero window, we set the MSS to
++ the initial MSS so that the application will send an entire MSS
++ of data. This data will not be acknowledged by the receiver,
++ and the application will retransmit it. This is called the
++ "persistent timer" and uses the retransmission mechanim.
++ */
++ tmp16 = ((unsigned short int)BUF->wnd[0] << 8) + (unsigned short int)BUF->wnd[1];
++ if(tmp16 > uip_connr->initialmss ||
++ tmp16 == 0) {
++ tmp16 = uip_connr->initialmss;
++ }
++ uip_connr->mss = tmp16;
++
++ /* If this packet constitutes an ACK for outstanding data (flagged
++ by the UIP_ACKDATA flag, we should call the application since it
++ might want to send more data. If the incoming packet had data
++ from the peer (as flagged by the UIP_NEWDATA flag), the
++ application must also be notified.
++
++ When the application is called, the global variable uip_len
++ contains the length of the incoming data. The application can
++ access the incoming data through the global pointer
++ uip_appdata, which usually points 40 bytes into the uip_buf
++ array.
++
++ If the application wishes to send any data, this data should be
++ put into the uip_appdata and the length of the data should be
++ put into uip_len. If the application don't have any data to
++ send, uip_len must be set to 0. */
++ if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) {
++ uip_slen = 0;
++ UIP_APPCALL();
++
++ appsend:
++
++ if(uip_flags & UIP_ABORT) {
++ uip_slen = 0;
++ uip_connr->tcpstateflags = CLOSED;
++ BUF->flags = TCP_RST | TCP_ACK;
++ goto tcp_send_nodata;
++ }
++
++ if(uip_flags & UIP_CLOSE) {
++ uip_slen = 0;
++ uip_connr->len = 1;
++ uip_connr->tcpstateflags = FIN_WAIT_1;
++ uip_connr->nrtx = 0;
++ BUF->flags = TCP_FIN | TCP_ACK;
++ goto tcp_send_nodata;
++ }
++
++ /* If uip_slen > 0, the application has data to be sent. */
++ if(uip_slen > 0) {
++
++ /* If the connection has acknowledged data, the contents of
++ the ->len variable should be discarded. */
++ if((uip_flags & UIP_ACKDATA) != 0) {
++ uip_connr->len = 0;
++ }
++
++ /* If the ->len variable is non-zero the connection has
++ already data in transit and cannot send anymore right
++ now. */
++ if(uip_connr->len == 0) {
++
++ /* The application cannot send more than what is allowed by
++ the mss (the minumum of the MSS and the available
++ window). */
++ if(uip_slen > uip_connr->mss) {
++ uip_slen = uip_connr->mss;
++ }
++
++ /* Remember how much data we send out now so that we know
++ when everything has been acknowledged. */
++ uip_connr->len = uip_slen;
++ } else {
++
++ /* If the application already had unacknowledged data, we
++ make sure that the application does not send (i.e.,
++ retransmit) out more than it previously sent out. */
++ uip_slen = uip_connr->len;
++ }
++ } else {
++ uip_connr->len = 0;
++ }
++ uip_connr->nrtx = 0;
++ apprexmit:
++ uip_appdata = uip_sappdata;
++
++ /* If the application has data to be sent, or if the incoming
++ packet had new data in it, we must send out a packet. */
++ if(uip_slen > 0 && uip_connr->len > 0) {
++ /* Add the length of the IP and TCP headers. */
++ uip_len = uip_connr->len + UIP_TCPIP_HLEN;
++ /* We always set the ACK flag in response packets. */
++ BUF->flags = TCP_ACK | TCP_PSH;
++ /* Send the packet. */
++ goto tcp_send_noopts;
++ }
++ /* If there is no data to send, just send out a pure ACK if
++ there is newdata. */
++ if(uip_flags & UIP_NEWDATA) {
++ uip_len = UIP_TCPIP_HLEN;
++ BUF->flags = TCP_ACK;
++ goto tcp_send_noopts;
++ }
++ }
++ goto drop;
++ case LAST_ACK:
++ /* We can close this connection if the peer has acknowledged our
++ FIN. This is indicated by the UIP_ACKDATA flag. */
++ if(uip_flags & UIP_ACKDATA) {
++ uip_connr->tcpstateflags = CLOSED;
++ uip_flags = UIP_CLOSE;
++ UIP_APPCALL();
++ }
++ break;
++
++ case FIN_WAIT_1:
++ /* The application has closed the connection, but the remote host
++ hasn't closed its end yet. Thus we do nothing but wait for a
++ FIN from the other side. */
++ if(uip_len > 0) {
++ uip_add_rcv_nxt(uip_len);
++ }
++ if(BUF->flags & TCP_FIN) {
++ if(uip_flags & UIP_ACKDATA) {
++ uip_connr->tcpstateflags = TIME_WAIT;
++ uip_connr->timer = 0;
++ uip_connr->len = 0;
++ } else {
++ uip_connr->tcpstateflags = CLOSING;
++ }
++ uip_add_rcv_nxt(1);
++ uip_flags = UIP_CLOSE;
++ UIP_APPCALL();
++ goto tcp_send_ack;
++ } else if(uip_flags & UIP_ACKDATA) {
++ uip_connr->tcpstateflags = FIN_WAIT_2;
++ uip_connr->len = 0;
++ goto drop;
++ }
++ if(uip_len > 0) {
++ goto tcp_send_ack;
++ }
++ goto drop;
++
++ case FIN_WAIT_2:
++ if(uip_len > 0) {
++ uip_add_rcv_nxt(uip_len);
++ }
++ if(BUF->flags & TCP_FIN) {
++ uip_connr->tcpstateflags = TIME_WAIT;
++ uip_connr->timer = 0;
++ uip_add_rcv_nxt(1);
++ uip_flags = UIP_CLOSE;
++ UIP_APPCALL();
++ goto tcp_send_ack;
++ }
++ if(uip_len > 0) {
++ goto tcp_send_ack;
++ }
++ goto drop;
++
++ case TIME_WAIT:
++ goto tcp_send_ack;
++
++ case CLOSING:
++ if(uip_flags & UIP_ACKDATA) {
++ uip_connr->tcpstateflags = TIME_WAIT;
++ uip_connr->timer = 0;
++ }
++ }
++ goto drop;
++
++
++ /* We jump here when we are ready to send the packet, and just want
++ to set the appropriate TCP sequence numbers in the TCP header. */
++ tcp_send_ack:
++ BUF->flags = TCP_ACK;
++ tcp_send_nodata:
++ uip_len = 40;
++ tcp_send_noopts:
++ BUF->tcpoffset = 5 << 4;
++ tcp_send:
++ /* We're done with the input processing. We are now ready to send a
++ reply. Our job is to fill in all the fields of the TCP and IP
++ headers before calculating the checksum and finally send the
++ packet. */
++ BUF->ackno[0] = uip_connr->rcv_nxt[0];
++ BUF->ackno[1] = uip_connr->rcv_nxt[1];
++ BUF->ackno[2] = uip_connr->rcv_nxt[2];
++ BUF->ackno[3] = uip_connr->rcv_nxt[3];
++
++ BUF->seqno[0] = uip_connr->snd_nxt[0];
++ BUF->seqno[1] = uip_connr->snd_nxt[1];
++ BUF->seqno[2] = uip_connr->snd_nxt[2];
++ BUF->seqno[3] = uip_connr->snd_nxt[3];
++
++ BUF->proto = UIP_PROTO_TCP;
++
++ BUF->srcport = uip_connr->lport;
++ BUF->destport = uip_connr->rport;
++
++ BUF->srcipaddr[0] = uip_hostaddr[0];
++ BUF->srcipaddr[1] = uip_hostaddr[1];
++ BUF->destipaddr[0] = uip_connr->ripaddr[0];
++ BUF->destipaddr[1] = uip_connr->ripaddr[1];
++
++
++ if(uip_connr->tcpstateflags & UIP_STOPPED) {
++ /* If the connection has issued uip_stop(), we advertise a zero
++ window so that the remote host will stop sending data. */
++ BUF->wnd[0] = BUF->wnd[1] = 0;
++ } else {
++ BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);
++ BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff);
++ }
++
++ tcp_send_noconn:
++
++ BUF->len[0] = (uip_len >> 8);
++ BUF->len[1] = (uip_len & 0xff);
++
++ /* Calculate TCP checksum. */
++ BUF->tcpchksum = 0;
++ BUF->tcpchksum = ~(uip_tcpchksum());
++
++ //ip_send_nolen:
++
++ BUF->vhl = 0x45;
++ BUF->tos = 0;
++ BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
++ BUF->ttl = UIP_TTL;
++ ++ipid;
++ BUF->ipid[0] = ipid >> 8;
++ BUF->ipid[1] = ipid & 0xff;
++
++ /* Calculate IP checksum. */
++ BUF->ipchksum = 0;
++ BUF->ipchksum = ~(uip_ipchksum());
++
++ UIP_STAT(++uip_stat.tcp.sent);
++ send:
++ UIP_STAT(++uip_stat.ip.sent);
++ /* Return and let the caller do the actual transmission. */
++ return;
++ drop:
++ uip_len = 0;
++ return;
++}
++/*-----------------------------------------------------------------------------------*/
++/*unsigned short int
++htons(unsigned short int val)
++{
++ return HTONS(val);
++}*/
++/*-----------------------------------------------------------------------------------*/
++/** @} */
+--- /dev/null
++++ b/net/uip-0.9/uip.h
+@@ -0,0 +1,1066 @@
++/**
++ * \addtogroup uip
++ * @{
++ */
++
++/**
++ * \file
++ * Header file for the uIP TCP/IP stack.
++ * \author Adam Dunkels <adam@dunkels.com>
++ *
++ * The uIP TCP/IP stack header file contains definitions for a number
++ * of C macros that are used by uIP programs as well as internal uIP
++ * structures, TCP/IP header structures and function declarations.
++ *
++ */
++
++
++/*
++ * Copyright (c) 2001-2003, Adam Dunkels.
++ * 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.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: uip.h,v 1.36.2.7 2003/10/07 13:47:51 adam Exp $
++ *
++ */
++
++#ifndef __UIP_H__
++#define __UIP_H__
++#include <linux/types.h>
++#include <linux/string.h>
++#include <linux/ctype.h>
++#include <malloc.h>
++#include <common.h>
++
++
++#include "uipopt.h"
++
++/*-----------------------------------------------------------------------------------*/
++/* First, the functions that should be called from the
++ * system. Initialization, the periodic timer and incoming packets are
++ * handled by the following three functions.
++ */
++
++/**
++ * \defgroup uipconffunc uIP configuration functions
++ * @{
++ *
++ * The uIP configuration functions are used for setting run-time
++ * parameters in uIP such as IP addresses.
++ */
++
++/**
++ * Set the IP address of this host.
++ *
++ * The IP address is represented as a 4-byte array where the first
++ * octet of the IP address is put in the first member of the 4-byte
++ * array.
++ *
++ * \param addr A pointer to a 4-byte representation of the IP address.
++ *
++ * \hideinitializer
++ */
++#define uip_sethostaddr(addr) do { uip_hostaddr[0] = addr[0]; \
++ uip_hostaddr[1] = addr[1]; } while(0)
++
++/**
++ * Get the IP address of this host.
++ *
++ * The IP address is represented as a 4-byte array where the first
++ * octet of the IP address is put in the first member of the 4-byte
++ * array.
++ *
++ * \param addr A pointer to a 4-byte array that will be filled in with
++ * the currently configured IP address.
++ *
++ * \hideinitializer
++ */
++#define uip_gethostaddr(addr) do { addr[0] = uip_hostaddr[0]; \
++ addr[1] = uip_hostaddr[1]; } while(0)
++
++/** @} */
++
++/**
++ * \defgroup uipinit uIP initialization functions
++ * @{
++ *
++ * The uIP initialization functions are used for booting uIP.
++ */
++
++/**
++ * uIP initialization function.
++ *
++ * This function should be called at boot up to initilize the uIP
++ * TCP/IP stack.
++ */
++void uip_init(void);
++
++/** @} */
++
++/**
++ * \defgroup uipdevfunc uIP device driver functions
++ * @{
++ *
++ * These functions are used by a network device driver for interacting
++ * with uIP.
++ */
++
++/**
++ * Process an incoming packet.
++ *
++ * This function should be called when the device driver has received
++ * a packet from the network. The packet from the device driver must
++ * be present in the uip_buf buffer, and the length of the packet
++ * should be placed in the uip_len variable.
++ *
++ * When the function returns, there may be an outbound packet placed
++ * in the uip_buf packet buffer. If so, the uip_len variable is set to
++ * the length of the packet. If no packet is to be sent out, the
++ * uip_len variable is set to 0.
++ *
++ * The usual way of calling the function is presented by the source
++ * code below.
++ \code
++ uip_len = devicedriver_poll();
++ if(uip_len > 0) {
++ uip_input();
++ if(uip_len > 0) {
++ devicedriver_send();
++ }
++ }
++ \endcode
++ *
++ * \note If you are writing a uIP device driver that needs ARP
++ * (Address Resolution Protocol), e.g., when running uIP over
++ * Ethernet, you will need to call the uIP ARP code before calling
++ * this function:
++ \code
++ #define BUF ((struct uip_eth_hdr *)&uip_buf[0])
++ uip_len = ethernet_devicedrver_poll();
++ if(uip_len > 0) {
++ if(BUF->type == HTONS(UIP_ETHTYPE_IP)) {
++ uip_arp_ipin();
++ uip_input();
++ if(uip_len > 0) {
++ uip_arp_out();
++ ethernet_devicedriver_send();
++ }
++ } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) {
++ uip_arp_arpin();
++ if(uip_len > 0) {
++ ethernet_devicedriver_send();
++ }
++ }
++ \endcode
++ *
++ * \hideinitializer
++ */
++#define uip_input() uip_process(UIP_DATA)
++
++/**
++ * Periodic processing for a connection identified by its number.
++ *
++ * This function does the necessary periodic processing (timers,
++ * polling) for a uIP TCP conneciton, and should be called when the
++ * periodic uIP timer goes off. It should be called for every
++ * connection, regardless of whether they are open of closed.
++ *
++ * When the function returns, it may have an outbound packet waiting
++ * for service in the uIP packet buffer, and if so the uip_len
++ * variable is set to a value larger than zero. The device driver
++ * should be called to send out the packet.
++ *
++ * The ususal way of calling the function is through a for() loop like
++ * this:
++ \code
++ for(i = 0; i < UIP_CONNS; ++i) {
++ uip_periodic(i);
++ if(uip_len > 0) {
++ devicedriver_send();
++ }
++ }
++ \endcode
++ *
++ * \note If you are writing a uIP device driver that needs ARP
++ * (Address Resolution Protocol), e.g., when running uIP over
++ * Ethernet, you will need to call the uip_arp_out() function before
++ * calling the device driver:
++ \code
++ for(i = 0; i < UIP_CONNS; ++i) {
++ uip_periodic(i);
++ if(uip_len > 0) {
++ uip_arp_out();
++ ethernet_devicedriver_send();
++ }
++ }
++ \endcode
++ *
++ * \param conn The number of the connection which is to be periodically polled.
++ *
++ * \hideinitializer
++ */
++#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \
++ uip_process(UIP_TIMER); } while (0)
++
++/**
++ * Periodic processing for a connection identified by a pointer to its structure.
++ *
++ * Same as uip_periodic() but takes a pointer to the actual uip_conn
++ * struct instead of an integer as its argument. This function can be
++ * used to force periodic processing of a specific connection.
++ *
++ * \param conn A pointer to the uip_conn struct for the connection to
++ * be processed.
++ *
++ * \hideinitializer
++ */
++#define uip_periodic_conn(conn) do { uip_conn = conn; \
++ uip_process(UIP_TIMER); } while (0)
++
++#if UIP_UDP
++/**
++ * Periodic processing for a UDP connection identified by its number.
++ *
++ * This function is essentially the same as uip_prerioic(), but for
++ * UDP connections. It is called in a similar fashion as the
++ * uip_periodic() function:
++ \code
++ for(i = 0; i < UIP_UDP_CONNS; i++) {
++ uip_udp_periodic(i);
++ if(uip_len > 0) {
++ devicedriver_send();
++ }
++ }
++ \endcode
++ *
++ * \note As for the uip_periodic() function, special care has to be
++ * taken when using uIP together with ARP and Ethernet:
++ \code
++ for(i = 0; i < UIP_UDP_CONNS; i++) {
++ uip_udp_periodic(i);
++ if(uip_len > 0) {
++ uip_arp_out();
++ ethernet_devicedriver_send();
++ }
++ }
++ \endcode
++ *
++ * \param conn The number of the UDP connection to be processed.
++ *
++ * \hideinitializer
++ */
++#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \
++ uip_process(UIP_UDP_TIMER); } while (0)
++
++/**
++ * Periodic processing for a UDP connection identified by a pointer to
++ * its structure.
++ *
++ * Same as uip_udp_periodic() but takes a pointer to the actual
++ * uip_conn struct instead of an integer as its argument. This
++ * function can be used to force periodic processing of a specific
++ * connection.
++ *
++ * \param conn A pointer to the uip_udp_conn struct for the connection
++ * to be processed.
++ *
++ * \hideinitializer
++ */
++#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \
++ uip_process(UIP_UDP_TIMER); } while (0)
++
++
++#endif /* UIP_UDP */
++
++/**
++ * The uIP packet buffer.
++ *
++ * The uip_buf array is used to hold incoming and outgoing
++ * packets. The device driver should place incoming data into this
++ * buffer. When sending data, the device driver should read the link
++ * level headers and the TCP/IP headers from this buffer. The size of
++ * the link level headers is configured by the UIP_LLH_LEN define.
++ *
++ * \note The application data need not be placed in this buffer, so
++ * the device driver must read it from the place pointed to by the
++ * uip_appdata pointer as illustrated by the following example:
++ \code
++ void
++ devicedriver_send(void)
++ {
++ hwsend(&uip_buf[0], UIP_LLH_LEN);
++ hwsend(&uip_buf[UIP_LLH_LEN], 40);
++ hwsend(uip_appdata, uip_len - 40 - UIP_LLH_LEN);
++ }
++ \endcode
++ */
++extern u8_t uip_buf[UIP_BUFSIZE+2];
++
++/** @} */
++
++/*-----------------------------------------------------------------------------------*/
++/* Functions that are used by the uIP application program. Opening and
++ * closing connections, sending and receiving data, etc. is all
++ * handled by the functions below.
++*/
++/**
++ * \defgroup uipappfunc uIP application functions
++ * @{
++ *
++ * Functions used by an application running of top of uIP.
++ */
++
++/**
++ * Start listening to the specified port.
++ *
++ * \note Since this function expects the port number in network byte
++ * order, a conversion using HTONS() or htons() is necessary.
++ *
++ \code
++ uip_listen(HTONS(80));
++ \endcode
++ *
++ * \param port A 16-bit port number in network byte order.
++ */
++void uip_listen(u16_t port);
++
++/**
++ * Stop listening to the specified port.
++ *
++ * \note Since this function expects the port number in network byte
++ * order, a conversion using HTONS() or htons() is necessary.
++ *
++ \code
++ uip_unlisten(HTONS(80));
++ \endcode
++ *
++ * \param port A 16-bit port number in network byte order.
++ */
++void uip_unlisten(u16_t port);
++
++/**
++ * Connect to a remote host using TCP.
++ *
++ * This function is used to start a new connection to the specified
++ * port on the specied host. It allocates a new connection identifier,
++ * sets the connection to the SYN_SENT state and sets the
++ * retransmission timer to 0. This will cause a TCP SYN segment to be
++ * sent out the next time this connection is periodically processed,
++ * which usually is done within 0.5 seconds after the call to
++ * uip_connect().
++ *
++ * \note This function is avaliable only if support for active open
++ * has been configured by defining UIP_ACTIVE_OPEN to 1 in uipopt.h.
++ *
++ * \note Since this function requires the port number to be in network
++ * byte order, a convertion using HTONS() or htons() is necessary.
++ *
++ \code
++ u16_t ipaddr[2];
++
++ uip_ipaddr(ipaddr, 192,168,1,2);
++ uip_connect(ipaddr, HTONS(80));
++ \endcode
++ *
++ * \param ripaddr A pointer to a 4-byte array representing the IP
++ * address of the remote hot.
++ *
++ * \param port A 16-bit port number in network byte order.
++ *
++ * \return A pointer to the uIP connection identifier for the new connection,
++ * or NULL if no connection could be allocated.
++ *
++ */
++struct uip_conn *uip_connect(u16_t *ripaddr, u16_t port);
++
++
++
++/**
++ * \internal
++ *
++ * Check if a connection has outstanding (i.e., unacknowledged) data.
++ *
++ * \param conn A pointer to the uip_conn structure for the connection.
++ *
++ * \hideinitializer
++ */
++#define uip_outstanding(conn) ((conn)->len)
++
++/**
++ * Send data on the current connection.
++ *
++ * This function is used to send out a single segment of TCP
++ * data. Only applications that have been invoked by uIP for event
++ * processing can send data.
++ *
++ * The amount of data that actually is sent out after a call to this
++ * funcion is determined by the maximum amount of data TCP allows. uIP
++ * will automatically crop the data so that only the appropriate
++ * amount of data is sent. The function uip_mss() can be used to query
++ * uIP for the amount of data that actually will be sent.
++ *
++ * \note This function does not guarantee that the sent data will
++ * arrive at the destination. If the data is lost in the network, the
++ * application will be invoked with the uip_rexmit() event being
++ * set. The application will then have to resend the data using this
++ * function.
++ *
++ * \param data A pointer to the data which is to be sent.
++ *
++ * \param len The maximum amount of data bytes to be sent.
++ *
++ * \hideinitializer
++ */
++#define uip_send(data, len) do { uip_sappdata = (data); uip_slen = (len);} while(0)
++
++/**
++ * The length of any incoming data that is currently avaliable (if avaliable)
++ * in the uip_appdata buffer.
++ *
++ * The test function uip_data() must first be used to check if there
++ * is any data available at all.
++ *
++ * \hideinitializer
++ */
++#define uip_datalen() uip_len
++
++/**
++ * The length of any out-of-band data (urgent data) that has arrived
++ * on the connection.
++ *
++ * \note The configuration parameter UIP_URGDATA must be set for this
++ * function to be enabled.
++ *
++ * \hideinitializer
++ */
++#define uip_urgdatalen() uip_urglen
++
++/**
++ * Close the current connection.
++ *
++ * This function will close the current connection in a nice way.
++ *
++ * \hideinitializer
++ */
++#define uip_close() (uip_flags = UIP_CLOSE)
++
++/**
++ * Abort the current connection.
++ *
++ * This function will abort (reset) the current connection, and is
++ * usually used when an error has occured that prevents using the
++ * uip_close() function.
++ *
++ * \hideinitializer
++ */
++#define uip_abort() (uip_flags = UIP_ABORT)
++
++/**
++ * Tell the sending host to stop sending data.
++ *
++ * This function will close our receiver's window so that we stop
++ * receiving data for the current connection.
++ *
++ * \hideinitializer
++ */
++#define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED)
++
++/**
++ * Find out if the current connection has been previously stopped with
++ * uip_stop().
++ *
++ * \hideinitializer
++ */
++#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED)
++
++/**
++ * Restart the current connection, if is has previously been stopped
++ * with uip_stop().
++ *
++ * This function will open the receiver's window again so that we
++ * start receiving data for the current connection.
++ *
++ * \hideinitializer
++ */
++#define uip_restart() do { uip_flags |= UIP_NEWDATA; \
++ uip_conn->tcpstateflags &= ~UIP_STOPPED; \
++ } while(0)
++
++
++/* uIP tests that can be made to determine in what state the current
++ connection is, and what the application function should do. */
++
++/**
++ * Is new incoming data available?
++ *
++ * Will reduce to non-zero if there is new data for the application
++ * present at the uip_appdata pointer. The size of the data is
++ * avaliable through the uip_len variable.
++ *
++ * \hideinitializer
++ */
++#define uip_newdata() (uip_flags & UIP_NEWDATA)
++
++/**
++ * Has previously sent data been acknowledged?
++ *
++ * Will reduce to non-zero if the previously sent data has been
++ * acknowledged by the remote host. This means that the application
++ * can send new data.
++ *
++ * \hideinitializer
++ */
++#define uip_acked() (uip_flags & UIP_ACKDATA)
++
++/**
++ * Has the connection just been connected?
++ *
++ * Reduces to non-zero if the current connection has been connected to
++ * a remote host. This will happen both if the connection has been
++ * actively opened (with uip_connect()) or passively opened (with
++ * uip_listen()).
++ *
++ * \hideinitializer
++ */
++#define uip_connected() (uip_flags & UIP_CONNECTED)
++
++/**
++ * Has the connection been closed by the other end?
++ *
++ * Is non-zero if the connection has been closed by the remote
++ * host. The application may then do the necessary clean-ups.
++ *
++ * \hideinitializer
++ */
++#define uip_closed() (uip_flags & UIP_CLOSE)
++
++/**
++ * Has the connection been aborted by the other end?
++ *
++ * Non-zero if the current connection has been aborted (reset) by the
++ * remote host.
++ *
++ * \hideinitializer
++ */
++#define uip_aborted() (uip_flags & UIP_ABORT)
++
++/**
++ * Has the connection timed out?
++ *
++ * Non-zero if the current connection has been aborted due to too many
++ * retransmissions.
++ *
++ * \hideinitializer
++ */
++#define uip_timedout() (uip_flags & UIP_TIMEDOUT)
++
++/**
++ * Do we need to retransmit previously data?
++ *
++ * Reduces to non-zero if the previously sent data has been lost in
++ * the network, and the application should retransmit it. The
++ * application should send the exact same data as it did the last
++ * time, using the uip_send() function.
++ *
++ * \hideinitializer
++ */
++#define uip_rexmit() (uip_flags & UIP_REXMIT)
++
++/**
++ * Is the connection being polled by uIP?
++ *
++ * Is non-zero if the reason the application is invoked is that the
++ * current connection has been idle for a while and should be
++ * polled.
++ *
++ * The polling event can be used for sending data without having to
++ * wait for the remote host to send data.
++ *
++ * \hideinitializer
++ */
++#define uip_poll() (uip_flags & UIP_POLL)
++
++/**
++ * Get the initial maxium segment size (MSS) of the current
++ * connection.
++ *
++ * \hideinitializer
++ */
++#define uip_initialmss() (uip_conn->initialmss)
++
++/**
++ * Get the current maxium segment size that can be sent on the current
++ * connection.
++ *
++ * The current maxiumum segment size that can be sent on the
++ * connection is computed from the receiver's window and the MSS of
++ * the connection (which also is available by calling
++ * uip_initialmss()).
++ *
++ * \hideinitializer
++ */
++#define uip_mss() (uip_conn->mss)
++
++/**
++ * Set up a new UDP connection.
++ *
++ * \param ripaddr A pointer to a 4-byte structure representing the IP
++ * address of the remote host.
++ *
++ * \param rport The remote port number in network byte order.
++ *
++ * \return The uip_udp_conn structure for the new connection or NULL
++ * if no connection could be allocated.
++ */
++struct uip_udp_conn *uip_udp_new(u16_t *ripaddr, u16_t rport);
++
++/**
++ * Removed a UDP connection.
++ *
++ * \param conn A pointer to the uip_udp_conn structure for the connection.
++ *
++ * \hideinitializer
++ */
++#define uip_udp_remove(conn) (conn)->lport = 0
++
++/**
++ * Send a UDP datagram of length len on the current connection.
++ *
++ * This function can only be called in response to a UDP event (poll
++ * or newdata). The data must be present in the uip_buf buffer, at the
++ * place pointed to by the uip_appdata pointer.
++ *
++ * \param len The length of the data in the uip_buf buffer.
++ *
++ * \hideinitializer
++ */
++#define uip_udp_send(len) uip_slen = (len)
++
++/** @} */
++
++/* uIP convenience and converting functions. */
++
++/**
++ * \defgroup uipconvfunc uIP conversion functions
++ * @{
++ *
++ * These functions can be used for converting between different data
++ * formats used by uIP.
++ */
++
++/**
++ * Pack an IP address into a 4-byte array which is used by uIP to
++ * represent IP addresses.
++ *
++ * Example:
++ \code
++ u16_t ipaddr[2];
++
++ uip_ipaddr(&ipaddr, 192,168,1,2);
++ \endcode
++ *
++ * \param addr A pointer to a 4-byte array that will be filled in with
++ * the IP addres.
++ * \param addr0 The first octet of the IP address.
++ * \param addr1 The second octet of the IP address.
++ * \param addr2 The third octet of the IP address.
++ * \param addr3 The forth octet of the IP address.
++ *
++ * \hideinitializer
++ */
++#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \
++ (addr)[0] = HTONS(((addr0) << 8) | (addr1)); \
++ (addr)[1] = HTONS(((addr2) << 8) | (addr3)); \
++ } while(0)
++
++/**
++ * Convert 16-bit quantity from host byte order to network byte order.
++ *
++ * This macro is primarily used for converting constants from host
++ * byte order to network byte order. For converting variables to
++ * network byte order, use the htons() function instead.
++ *
++ * \hideinitializer
++ */
++#ifndef HTONS
++# if BYTE_ORDER == BIG_ENDIAN
++# define HTONS(n) (n)
++# else /* BYTE_ORDER == BIG_ENDIAN */
++# define HTONS(n) ((((u16_t)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8))
++# endif /* BYTE_ORDER == BIG_ENDIAN */
++#endif /* HTONS */
++
++/**
++ * Convert 16-bit quantity from host byte order to network byte order.
++ *
++ * This function is primarily used for converting variables from host
++ * byte order to network byte order. For converting constants to
++ * network byte order, use the HTONS() macro instead.
++ */
++#ifndef htons
++u16_t htons(u16_t val);
++#endif /* htons */
++
++/** @} */
++
++/**
++ * Pointer to the application data in the packet buffer.
++ *
++ * This pointer points to the application data when the application is
++ * called. If the application wishes to send data, the application may
++ * use this space to write the data into before calling uip_send().
++ */
++extern volatile u8_t *uip_appdata;
++extern volatile u8_t *uip_sappdata;
++
++#if UIP_URGDATA > 0
++/* u8_t *uip_urgdata:
++ *
++ * This pointer points to any urgent data that has been received. Only
++ * present if compiled with support for urgent data (UIP_URGDATA).
++ */
++extern volatile u8_t *uip_urgdata;
++#endif /* UIP_URGDATA > 0 */
++
++
++/* u[8|16]_t uip_len:
++ *
++ * When the application is called, uip_len contains the length of any
++ * new data that has been received from the remote host. The
++ * application should set this variable to the size of any data that
++ * the application wishes to send. When the network device driver
++ * output function is called, uip_len should contain the length of the
++ * outgoing packet.
++ */
++extern volatile u16_t uip_len, uip_slen;
++
++#if UIP_URGDATA > 0
++extern volatile u8_t uip_urglen, uip_surglen;
++#endif /* UIP_URGDATA > 0 */
++
++
++/**
++ * Representation of a uIP TCP connection.
++ *
++ * The uip_conn structure is used for identifying a connection. All
++ * but one field in the structure are to be considered read-only by an
++ * application. The only exception is the appstate field whos purpose
++ * is to let the application store application-specific state (e.g.,
++ * file pointers) for the connection. The size of this field is
++ * configured in the "uipopt.h" header file.
++ */
++struct uip_conn {
++ u16_t ripaddr[2]; /**< The IP address of the remote host. */
++
++ u16_t lport; /**< The local TCP port, in network byte order. */
++ u16_t rport; /**< The local remote TCP port, in network byte
++ order. */
++
++ u8_t rcv_nxt[4]; /**< The sequence number that we expect to
++ receive next. */
++ u8_t snd_nxt[4]; /**< The sequence number that was last sent by
++ us. */
++ u16_t len; /**< Length of the data that was previously sent. */
++ u16_t mss; /**< Current maximum segment size for the
++ connection. */
++ u16_t initialmss; /**< Initial maximum segment size for the
++ connection. */
++ u8_t sa; /**< Retransmission time-out calculation state
++ variable. */
++ u8_t sv; /**< Retransmission time-out calculation state
++ variable. */
++ u8_t rto; /**< Retransmission time-out. */
++ u8_t tcpstateflags; /**< TCP state and flags. */
++ u8_t timer; /**< The retransmission timer. */
++ u8_t nrtx; /**< The number of retransmissions for the last
++ segment sent. */
++
++ /** The application state. */
++ u8_t appstate[UIP_APPSTATE_SIZE];
++};
++
++
++/* Pointer to the current connection. */
++extern struct uip_conn *uip_conn;
++/* The array containing all uIP connections. */
++extern struct uip_conn uip_conns[UIP_CONNS];
++/**
++ * \addtogroup uiparch
++ * @{
++ */
++
++/**
++ * 4-byte array used for the 32-bit sequence number calculations.
++ */
++extern volatile u8_t uip_acc32[4];
++
++/** @} */
++
++
++#if UIP_UDP
++/**
++ * Representation of a uIP UDP connection.
++ */
++struct uip_udp_conn {
++ u16_t ripaddr[2]; /**< The IP address of the remote peer. */
++ u16_t lport; /**< The local port number in network byte order. */
++ u16_t rport; /**< The remote port number in network byte order. */
++};
++
++extern struct uip_udp_conn *uip_udp_conn;
++extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
++#endif /* UIP_UDP */
++
++/**
++ * The structure holding the TCP/IP statistics that are gathered if
++ * UIP_STATISTICS is set to 1.
++ *
++ */
++struct uip_stats {
++ struct {
++ uip_stats_t drop; /**< Number of dropped packets at the IP
++ layer. */
++ uip_stats_t recv; /**< Number of received packets at the IP
++ layer. */
++ uip_stats_t sent; /**< Number of sent packets at the IP
++ layer. */
++ uip_stats_t vhlerr; /**< Number of packets dropped due to wrong
++ IP version or header length. */
++ uip_stats_t hblenerr; /**< Number of packets dropped due to wrong
++ IP length, high byte. */
++ uip_stats_t lblenerr; /**< Number of packets dropped due to wrong
++ IP length, low byte. */
++ uip_stats_t fragerr; /**< Number of packets dropped since they
++ were IP fragments. */
++ uip_stats_t chkerr; /**< Number of packets dropped due to IP
++ checksum errors. */
++ uip_stats_t protoerr; /**< Number of packets dropped since they
++ were neither ICMP, UDP nor TCP. */
++ } ip; /**< IP statistics. */
++ struct {
++ uip_stats_t drop; /**< Number of dropped ICMP packets. */
++ uip_stats_t recv; /**< Number of received ICMP packets. */
++ uip_stats_t sent; /**< Number of sent ICMP packets. */
++ uip_stats_t typeerr; /**< Number of ICMP packets with a wrong
++ type. */
++ } icmp; /**< ICMP statistics. */
++ struct {
++ uip_stats_t drop; /**< Number of dropped TCP segments. */
++ uip_stats_t recv; /**< Number of recived TCP segments. */
++ uip_stats_t sent; /**< Number of sent TCP segments. */
++ uip_stats_t chkerr; /**< Number of TCP segments with a bad
++ checksum. */
++ uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK
++ number. */
++ uip_stats_t rst; /**< Number of recevied TCP RST (reset) segments. */
++ uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */
++ uip_stats_t syndrop; /**< Number of dropped SYNs due to too few
++ connections was avaliable. */
++ uip_stats_t synrst; /**< Number of SYNs for closed ports,
++ triggering a RST. */
++ } tcp; /**< TCP statistics. */
++};
++
++/**
++ * The uIP TCP/IP statistics.
++ *
++ * This is the variable in which the uIP TCP/IP statistics are gathered.
++ */
++extern struct uip_stats uip_stat;
++
++
++/*-----------------------------------------------------------------------------------*/
++/* All the stuff below this point is internal to uIP and should not be
++ * used directly by an application or by a device driver.
++ */
++/*-----------------------------------------------------------------------------------*/
++/* u8_t uip_flags:
++ *
++ * When the application is called, uip_flags will contain the flags
++ * that are defined in this file. Please read below for more
++ * infomation.
++ */
++extern volatile u8_t uip_flags;
++
++/* The following flags may be set in the global variable uip_flags
++ before calling the application callback. The UIP_ACKDATA and
++ UIP_NEWDATA flags may both be set at the same time, whereas the
++ others are mutualy exclusive. Note that these flags should *NOT* be
++ accessed directly, but through the uIP functions/macros. */
++
++#define UIP_ACKDATA 1 /* Signifies that the outstanding data was
++ acked and the application should send
++ out new data instead of retransmitting
++ the last data. */
++#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent
++ us new data. */
++#define UIP_REXMIT 4 /* Tells the application to retransmit the
++ data that was last sent. */
++#define UIP_POLL 8 /* Used for polling the application, to
++ check if the application has data that
++ it wants to send. */
++#define UIP_CLOSE 16 /* The remote host has closed the
++ connection, thus the connection has
++ gone away. Or the application signals
++ that it wants to close the
++ connection. */
++#define UIP_ABORT 32 /* The remote host has aborted the
++ connection, thus the connection has
++ gone away. Or the application signals
++ that it wants to abort the
++ connection. */
++#define UIP_CONNECTED 64 /* We have got a connection from a remote
++ host and have set up a new connection
++ for it, or an active connection has
++ been successfully established. */
++
++#define UIP_TIMEDOUT 128 /* The connection has been aborted due to
++ too many retransmissions. */
++
++
++/* uip_process(flag):
++ *
++ * The actual uIP function which does all the work.
++ */
++void uip_process(u8_t flag);
++
++/* The following flags are passed as an argument to the uip_process()
++ function. They are used to distinguish between the two cases where
++ uip_process() is called. It can be called either because we have
++ incoming data that should be processed, or because the periodic
++ timer has fired. */
++
++#define UIP_DATA 1 /* Tells uIP that there is incoming data in
++ the uip_buf buffer. The length of the
++ data is stored in the global variable
++ uip_len. */
++#define UIP_TIMER 2 /* Tells uIP that the periodic timer has
++ fired. */
++#if UIP_UDP
++#define UIP_UDP_TIMER 3
++#endif /* UIP_UDP */
++
++/* The TCP states used in the uip_conn->tcpstateflags. */
++#define CLOSED 0
++#define SYN_RCVD 1
++#define SYN_SENT 2
++#define ESTABLISHED 3
++#define FIN_WAIT_1 4
++#define FIN_WAIT_2 5
++#define CLOSING 6
++#define TIME_WAIT 7
++#define LAST_ACK 8
++#define TS_MASK 15
++
++#define UIP_STOPPED 16
++
++#define UIP_TCPIP_HLEN 40
++
++/* The TCP and IP headers. */
++typedef struct {
++ /* IP header. */
++ u8_t vhl,
++ tos,
++ len[2],
++ ipid[2],
++ ipoffset[2],
++ ttl,
++ proto;
++ u16_t ipchksum;
++ u16_t srcipaddr[2],
++ destipaddr[2];
++
++ /* TCP header. */
++ u16_t srcport,
++ destport;
++ u8_t seqno[4],
++ ackno[4],
++ tcpoffset,
++ flags,
++ wnd[2];
++ u16_t tcpchksum;
++ u8_t urgp[2];
++ u8_t optdata[4];
++} uip_tcpip_hdr;
++
++/* The ICMP and IP headers. */
++typedef struct {
++ /* IP header. */
++ u8_t vhl,
++ tos,
++ len[2],
++ ipid[2],
++ ipoffset[2],
++ ttl,
++ proto;
++ u16_t ipchksum;
++ u16_t srcipaddr[2],
++ destipaddr[2];
++ /* ICMP (echo) header. */
++ u8_t type, icode;
++ u16_t icmpchksum;
++ u16_t id, seqno;
++} uip_icmpip_hdr;
++
++
++/* The UDP and IP headers. */
++typedef struct {
++ /* IP header. */
++ u8_t vhl,
++ tos,
++ len[2],
++ ipid[2],
++ ipoffset[2],
++ ttl,
++ proto;
++ u16_t ipchksum;
++ u16_t srcipaddr[2],
++ destipaddr[2];
++
++ /* UDP header. */
++ u16_t srcport,
++ destport;
++ u16_t udplen;
++ u16_t udpchksum;
++} uip_udpip_hdr;
++
++#define UIP_PROTO_ICMP 1
++#define UIP_PROTO_TCP 6
++#define UIP_PROTO_UDP 17
++
++#if UIP_FIXEDADDR
++extern const u16_t uip_hostaddr[2];
++#else /* UIP_FIXEDADDR */
++extern u16_t uip_hostaddr[2];
++#endif /* UIP_FIXEDADDR */
++
++#endif /* __UIP_H__ */
++
++
++/** @} */
++
+--- /dev/null
++++ b/net/uip-0.9/uip_arch.c
+@@ -0,0 +1,145 @@
++/*
++ * Copyright (c) 2001, Adam Dunkels.
++ * 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.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: uip_arch.c,v 1.2.2.1 2003/10/04 22:54:17 adam Exp $
++ *
++ */
++
++
++#include "uip.h"
++#include "uip_arch.h"
++
++#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
++#define IP_PROTO_TCP 6
++
++/*-----------------------------------------------------------------------------------*/
++void
++uip_add32(u8_t *op32, u16_t op16)
++{
++
++ uip_acc32[3] = op32[3] + (op16 & 0xff);
++ uip_acc32[2] = op32[2] + (op16 >> 8);
++ uip_acc32[1] = op32[1];
++ uip_acc32[0] = op32[0];
++
++ if(uip_acc32[2] < (op16 >> 8)) {
++ ++uip_acc32[1];
++ if(uip_acc32[1] == 0) {
++ ++uip_acc32[0];
++ }
++ }
++
++
++ if(uip_acc32[3] < (op16 & 0xff)) {
++ ++uip_acc32[2];
++ if(uip_acc32[2] == 0) {
++ ++uip_acc32[1];
++ if(uip_acc32[1] == 0) {
++ ++uip_acc32[0];
++ }
++ }
++ }
++}
++/*-----------------------------------------------------------------------------------*/
++u16_t
++uip_chksum(u16_t *sdata, u16_t len)
++{
++ u16_t acc;
++
++ for(acc = 0; len > 1; len -= 2) {
++ acc += *sdata;
++ if(acc < *sdata) {
++ /* Overflow, so we add the carry to acc (i.e., increase by
++ one). */
++ ++acc;
++ }
++ ++sdata;
++ }
++
++ /* add up any odd byte */
++ if(len == 1) {
++ acc += htons(((u16_t)(*(u8_t *)sdata)) << 8);
++ if(acc < htons(((u16_t)(*(u8_t *)sdata)) << 8)) {
++ ++acc;
++ }
++ }
++
++ return acc;
++}
++/*-----------------------------------------------------------------------------------*/
++u16_t
++uip_ipchksum(void)
++{
++ return uip_chksum((u16_t *)&uip_buf[UIP_LLH_LEN], 20);
++}
++/*-----------------------------------------------------------------------------------*/
++u16_t
++uip_tcpchksum(void)
++{
++ u16_t hsum, sum;
++
++
++ /* Compute the checksum of the TCP header. */
++ hsum = uip_chksum((u16_t *)&uip_buf[20 + UIP_LLH_LEN], 20);
++
++ /* Compute the checksum of the data in the TCP packet and add it to
++ the TCP header checksum. */
++ sum = uip_chksum((u16_t *)uip_appdata,
++ (u16_t)(((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 40)));
++
++ if((sum += hsum) < hsum) {
++ ++sum;
++ }
++
++ if((sum += BUF->srcipaddr[0]) < BUF->srcipaddr[0]) {
++ ++sum;
++ }
++ if((sum += BUF->srcipaddr[1]) < BUF->srcipaddr[1]) {
++ ++sum;
++ }
++ if((sum += BUF->destipaddr[0]) < BUF->destipaddr[0]) {
++ ++sum;
++ }
++ if((sum += BUF->destipaddr[1]) < BUF->destipaddr[1]) {
++ ++sum;
++ }
++ if((sum += (u16_t)htons((u16_t)IP_PROTO_TCP)) < (u16_t)htons((u16_t)IP_PROTO_TCP)) {
++ ++sum;
++ }
++
++ hsum = (u16_t)htons((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 20);
++
++ if((sum += hsum) < hsum) {
++ ++sum;
++ }
++
++ return sum;
++}
++/*-----------------------------------------------------------------------------------*/
+--- /dev/null
++++ b/net/uip-0.9/uip_arch.h
+@@ -0,0 +1,130 @@
++/**
++ * \defgroup uiparch Architecture specific uIP functions
++ * @{
++ *
++ * The functions in the architecture specific module implement the IP
++ * check sum and 32-bit additions.
++ *
++ * The IP checksum calculation is the most computationally expensive
++ * operation in the TCP/IP stack and it therefore pays off to
++ * implement this in efficient assembler. The purpose of the uip-arch
++ * module is to let the checksum functions to be implemented in
++ * architecture specific assembler.
++ *
++ */
++
++/**
++ * \file
++ * Declarations of architecture specific functions.
++ * \author Adam Dunkels <adam@dunkels.com>
++ */
++
++/*
++ * Copyright (c) 2001, Adam Dunkels.
++ * 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.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: uip_arch.h,v 1.1.2.2 2003/10/06 15:10:22 adam Exp $
++ *
++ */
++
++#ifndef __UIP_ARCH_H__
++#define __UIP_ARCH_H__
++
++#include "uip.h"
++
++/**
++ * Carry out a 32-bit addition.
++ *
++ * Because not all architectures for which uIP is intended has native
++ * 32-bit arithmetic, uIP uses an external C function for doing the
++ * required 32-bit additions in the TCP protocol processing. This
++ * function should add the two arguments and place the result in the
++ * global variable uip_acc32.
++ *
++ * \note The 32-bit integer pointed to by the op32 parameter and the
++ * result in the uip_acc32 variable are in network byte order (big
++ * endian).
++ *
++ * \param op32 A pointer to a 4-byte array representing a 32-bit
++ * integer in network byte order (big endian).
++ *
++ * \param op16 A 16-bit integer in host byte order.
++ */
++void uip_add32(u8_t *op32, u16_t op16);
++
++/**
++ * Calculate the Internet checksum over a buffer.
++ *
++ * The Internet checksum is the one's complement of the one's
++ * complement sum of all 16-bit words in the buffer.
++ *
++ * See RFC1071.
++ *
++ * \note This function is not called in the current version of uIP,
++ * but future versions might make use of it.
++ *
++ * \param buf A pointer to the buffer over which the checksum is to be
++ * computed.
++ *
++ * \param len The length of the buffer over which the checksum is to
++ * be computed.
++ *
++ * \return The Internet checksum of the buffer.
++ */
++u16_t uip_chksum(u16_t *buf, u16_t len);
++
++/**
++ * Calculate the IP header checksum of the packet header in uip_buf.
++ *
++ * The IP header checksum is the Internet checksum of the 20 bytes of
++ * the IP header.
++ *
++ * \return The IP header checksum of the IP header in the uip_buf
++ * buffer.
++ */
++u16_t uip_ipchksum(void);
++
++/**
++ * Calculate the TCP checksum of the packet in uip_buf and uip_appdata.
++ *
++ * The TCP checksum is the Internet checksum of data contents of the
++ * TCP segment, and a pseudo-header as defined in RFC793.
++ *
++ * \note The uip_appdata pointer that points to the packet data may
++ * point anywhere in memory, so it is not possible to simply calculate
++ * the Internet checksum of the contents of the uip_buf buffer.
++ *
++ * \return The TCP checksum of the TCP segment in uip_buf and pointed
++ * to by uip_appdata.
++ */
++u16_t uip_tcpchksum(void);
++
++/** @} */
++
++#endif /* __UIP_ARCH_H__ */
+--- /dev/null
++++ b/net/uip-0.9/uip_arp.c
+@@ -0,0 +1,421 @@
++/**
++ * \addtogroup uip
++ * @{
++ */
++
++/**
++ * \defgroup uiparp uIP Address Resolution Protocol
++ * @{
++ *
++ * The Address Resolution Protocol ARP is used for mapping between IP
++ * addresses and link level addresses such as the Ethernet MAC
++ * addresses. ARP uses broadcast queries to ask for the link level
++ * address of a known IP address and the host which is configured with
++ * the IP address for which the query was meant, will respond with its
++ * link level address.
++ *
++ * \note This ARP implementation only supports Ethernet.
++ */
++
++/**
++ * \file
++ * Implementation of the ARP Address Resolution Protocol.
++ * \author Adam Dunkels <adam@dunkels.com>
++ *
++ */
++
++/*
++ * Copyright (c) 2001-2003, Adam Dunkels.
++ * 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.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: uip_arp.c,v 1.7.2.3 2003/10/06 22:42:30 adam Exp $
++ *
++ */
++
++
++#include "uip_arp.h"
++
++struct arp_hdr {
++ struct uip_eth_hdr ethhdr;
++ u16_t hwtype;
++ u16_t protocol;
++ u8_t hwlen;
++ u8_t protolen;
++ u16_t opcode;
++ struct uip_eth_addr shwaddr;
++ u16_t sipaddr[2];
++ struct uip_eth_addr dhwaddr;
++ u16_t dipaddr[2];
++};
++
++struct ethip_hdr {
++ struct uip_eth_hdr ethhdr;
++ /* IP header. */
++ u8_t vhl,
++ tos,
++ len[2],
++ ipid[2],
++ ipoffset[2],
++ ttl,
++ proto;
++ u16_t ipchksum;
++ u16_t srcipaddr[2],
++ destipaddr[2];
++};
++
++#define ARP_REQUEST 1
++#define ARP_REPLY 2
++
++#define ARP_HWTYPE_ETH 1
++
++struct arp_entry {
++ u16_t ipaddr[2];
++ struct uip_eth_addr ethaddr;
++ u8_t time;
++};
++
++struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0,
++ UIP_ETHADDR1,
++ UIP_ETHADDR2,
++ UIP_ETHADDR3,
++ UIP_ETHADDR4,
++ UIP_ETHADDR5}};
++
++static struct arp_entry arp_table[UIP_ARPTAB_SIZE];
++static u16_t ipaddr[2];
++static u8_t i, c;
++
++static u8_t arptime;
++static u8_t tmpage;
++
++#define BUF ((struct arp_hdr *)&uip_buf[0])
++#define IPBUF ((struct ethip_hdr *)&uip_buf[0])
++/*-----------------------------------------------------------------------------------*/
++/**
++ * Initialize the ARP module.
++ *
++ */
++/*-----------------------------------------------------------------------------------*/
++void
++uip_arp_init(void)
++{
++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
++ memset(arp_table[i].ipaddr, 0, 4);
++ }
++}
++/*-----------------------------------------------------------------------------------*/
++/**
++ * Periodic ARP processing function.
++ *
++ * This function performs periodic timer processing in the ARP module
++ * and should be called at regular intervals. The recommended interval
++ * is 10 seconds between the calls.
++ *
++ */
++/*-----------------------------------------------------------------------------------*/
++void
++uip_arp_timer(void)
++{
++ struct arp_entry *tabptr;
++
++ ++arptime;
++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
++ tabptr = &arp_table[i];
++ if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 &&
++ arptime - tabptr->time >= UIP_ARP_MAXAGE) {
++ memset(tabptr->ipaddr, 0, 4);
++ }
++ }
++
++}
++/*-----------------------------------------------------------------------------------*/
++static void
++uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr)
++{
++ register struct arp_entry *tabptr = 0;
++ /* Walk through the ARP mapping table and try to find an entry to
++ update. If none is found, the IP -> MAC address mapping is
++ inserted in the ARP table. */
++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
++
++ tabptr = &arp_table[i];
++ /* Only check those entries that are actually in use. */
++ if(tabptr->ipaddr[0] != 0 &&
++ tabptr->ipaddr[1] != 0) {
++
++ /* Check if the source IP address of the incoming packet matches
++ the IP address in this ARP table entry. */
++ if(ipaddr[0] == tabptr->ipaddr[0] &&
++ ipaddr[1] == tabptr->ipaddr[1]) {
++
++ /* An old entry found, update this and return. */
++ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
++ tabptr->time = arptime;
++
++ return;
++ }
++ }
++ }
++
++ /* If we get here, no existing ARP table entry was found, so we
++ create one. */
++
++ /* First, we try to find an unused entry in the ARP table. */
++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
++ tabptr = &arp_table[i];
++ if(tabptr->ipaddr[0] == 0 &&
++ tabptr->ipaddr[1] == 0) {
++ break;
++ }
++ }
++
++ /* If no unused entry is found, we try to find the oldest entry and
++ throw it away. */
++ if(i == UIP_ARPTAB_SIZE) {
++ tmpage = 0;
++ c = 0;
++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
++ tabptr = &arp_table[i];
++ if(arptime - tabptr->time > tmpage) {
++ tmpage = arptime - tabptr->time;
++ c = i;
++ }
++ }
++ i = c;
++ }
++
++ /* Now, i is the ARP table entry which we will fill with the new
++ information. */
++ memcpy(tabptr->ipaddr, ipaddr, 4);
++ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
++ tabptr->time = arptime;
++}
++/*-----------------------------------------------------------------------------------*/
++/**
++ * ARP processing for incoming IP packets
++ *
++ * This function should be called by the device driver when an IP
++ * packet has been received. The function will check if the address is
++ * in the ARP cache, and if so the ARP cache entry will be
++ * refreshed. If no ARP cache entry was found, a new one is created.
++ *
++ * This function expects an IP packet with a prepended Ethernet header
++ * in the uip_buf[] buffer, and the length of the packet in the global
++ * variable uip_len.
++ */
++/*-----------------------------------------------------------------------------------*/
++void
++uip_arp_ipin(void)
++{
++ uip_len -= sizeof(struct uip_eth_hdr);
++
++ /* Only insert/update an entry if the source IP address of the
++ incoming IP packet comes from a host on the local network. */
++ if((IPBUF->srcipaddr[0] & uip_arp_netmask[0]) !=
++ (uip_hostaddr[0] & uip_arp_netmask[0])) {
++ return;
++ }
++ if((IPBUF->srcipaddr[1] & uip_arp_netmask[1]) !=
++ (uip_hostaddr[1] & uip_arp_netmask[1])) {
++ return;
++ }
++ uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src));
++
++ return;
++}
++/*-----------------------------------------------------------------------------------*/
++/**
++ * ARP processing for incoming ARP packets.
++ *
++ * This function should be called by the device driver when an ARP
++ * packet has been received. The function will act differently
++ * depending on the ARP packet type: if it is a reply for a request
++ * that we previously sent out, the ARP cache will be filled in with
++ * the values from the ARP reply. If the incoming ARP packet is an ARP
++ * request for our IP address, an ARP reply packet is created and put
++ * into the uip_buf[] buffer.
++ *
++ * When the function returns, the value of the global variable uip_len
++ * indicates whether the device driver should send out a packet or
++ * not. If uip_len is zero, no packet should be sent. If uip_len is
++ * non-zero, it contains the length of the outbound packet that is
++ * present in the uip_buf[] buffer.
++ *
++ * This function expects an ARP packet with a prepended Ethernet
++ * header in the uip_buf[] buffer, and the length of the packet in the
++ * global variable uip_len.
++ */
++/*-----------------------------------------------------------------------------------*/
++void
++uip_arp_arpin(void)
++{
++
++ if(uip_len < sizeof(struct arp_hdr)) {
++ uip_len = 0;
++ return;
++ }
++
++ uip_len = 0;
++
++ switch(BUF->opcode) {
++ case HTONS(ARP_REQUEST):
++ /* ARP request. If it asked for our address, we send out a
++ reply. */
++ if(BUF->dipaddr[0] == uip_hostaddr[0] &&
++ BUF->dipaddr[1] == uip_hostaddr[1]) {
++ /* The reply opcode is 2. */
++ BUF->opcode = HTONS(2);
++
++ memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6);
++ memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
++ memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
++ memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6);
++
++ BUF->dipaddr[0] = BUF->sipaddr[0];
++ BUF->dipaddr[1] = BUF->sipaddr[1];
++ BUF->sipaddr[0] = uip_hostaddr[0];
++ BUF->sipaddr[1] = uip_hostaddr[1];
++
++ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
++ uip_len = sizeof(struct arp_hdr);
++ }
++ break;
++ case HTONS(ARP_REPLY):
++ /* ARP reply. We insert or update the ARP table if it was meant
++ for us. */
++ if(BUF->dipaddr[0] == uip_hostaddr[0] &&
++ BUF->dipaddr[1] == uip_hostaddr[1]) {
++
++ uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
++ }
++ break;
++ }
++
++ return;
++}
++/*-----------------------------------------------------------------------------------*/
++/**
++ * Prepend Ethernet header to an outbound IP packet and see if we need
++ * to send out an ARP request.
++ *
++ * This function should be called before sending out an IP packet. The
++ * function checks the destination IP address of the IP packet to see
++ * what Ethernet MAC address that should be used as a destination MAC
++ * address on the Ethernet.
++ *
++ * If the destination IP address is in the local network (determined
++ * by logical ANDing of netmask and our IP address), the function
++ * checks the ARP cache to see if an entry for the destination IP
++ * address is found. If so, an Ethernet header is prepended and the
++ * function returns. If no ARP cache entry is found for the
++ * destination IP address, the packet in the uip_buf[] is replaced by
++ * an ARP request packet for the IP address. The IP packet is dropped
++ * and it is assumed that they higher level protocols (e.g., TCP)
++ * eventually will retransmit the dropped packet.
++ *
++ * If the destination IP address is not on the local network, the IP
++ * address of the default router is used instead.
++ *
++ * When the function returns, a packet is present in the uip_buf[]
++ * buffer, and the length of the packet is in the global variable
++ * uip_len.
++ */
++/*-----------------------------------------------------------------------------------*/
++void
++uip_arp_out(void)
++{
++ struct arp_entry *tabptr = 0;
++ /* Find the destination IP address in the ARP table and construct
++ the Ethernet header. If the destination IP addres isn't on the
++ local network, we use the default router's IP address instead.
++
++ If not ARP table entry is found, we overwrite the original IP
++ packet with an ARP request for the IP address. */
++
++ /* Check if the destination address is on the local network. */
++ if((IPBUF->destipaddr[0] & uip_arp_netmask[0]) !=
++ (uip_hostaddr[0] & uip_arp_netmask[0]) ||
++ (IPBUF->destipaddr[1] & uip_arp_netmask[1]) !=
++ (uip_hostaddr[1] & uip_arp_netmask[1])) {
++ /* Destination address was not on the local network, so we need to
++ use the default router's IP address instead of the destination
++ address when determining the MAC address. */
++ ipaddr[0] = uip_arp_draddr[0];
++ ipaddr[1] = uip_arp_draddr[1];
++ } else {
++ /* Else, we use the destination IP address. */
++ ipaddr[0] = IPBUF->destipaddr[0];
++ ipaddr[1] = IPBUF->destipaddr[1];
++ }
++
++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
++ tabptr = &arp_table[i];
++ if(ipaddr[0] == tabptr->ipaddr[0] &&
++ ipaddr[1] == tabptr->ipaddr[1])
++ break;
++ }
++
++ if(i == UIP_ARPTAB_SIZE) {
++ /* The destination address was not in our ARP table, so we
++ overwrite the IP packet with an ARP request. */
++
++ memset(BUF->ethhdr.dest.addr, 0xff, 6);
++ memset(BUF->dhwaddr.addr, 0x00, 6);
++ memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
++ memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
++
++ BUF->dipaddr[0] = ipaddr[0];
++ BUF->dipaddr[1] = ipaddr[1];
++ BUF->sipaddr[0] = uip_hostaddr[0];
++ BUF->sipaddr[1] = uip_hostaddr[1];
++ BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */
++ BUF->hwtype = HTONS(ARP_HWTYPE_ETH);
++ BUF->protocol = HTONS(UIP_ETHTYPE_IP);
++ BUF->hwlen = 6;
++ BUF->protolen = 4;
++ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
++
++ uip_appdata = &uip_buf[40 + UIP_LLH_LEN];
++
++ uip_len = sizeof(struct arp_hdr);
++ return;
++ }
++
++ /* Build an ethernet header. */
++ memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6);
++ memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
++
++ IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP);
++
++ uip_len += sizeof(struct uip_eth_hdr);
++}
++/*-----------------------------------------------------------------------------------*/
++
++/** @} */
++/** @} */
+--- /dev/null
++++ b/net/uip-0.9/uip_arp.h
+@@ -0,0 +1,201 @@
++/**
++ * \addtogroup uip
++ * @{
++ */
++
++/**
++ * \addtogroup uiparp
++ * @{
++ */
++
++/**
++ * \file
++ * Macros and definitions for the ARP module.
++ * \author Adam Dunkels <adam@dunkels.com>
++ */
++
++
++/*
++ * Copyright (c) 2001-2003, Adam Dunkels.
++ * 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.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: uip_arp.h,v 1.3.2.2 2003/10/06 15:10:22 adam Exp $
++ *
++ */
++
++#ifndef __UIP_ARP_H__
++#define __UIP_ARP_H__
++
++#include "uip.h"
++
++
++/**
++ * Representation of a 48-bit Ethernet address.
++ */
++struct uip_eth_addr {
++ u8_t addr[6];
++};
++
++extern struct uip_eth_addr uip_ethaddr;
++
++/**
++ * The Ethernet header.
++ */
++struct uip_eth_hdr {
++ struct uip_eth_addr dest;
++ struct uip_eth_addr src;
++ u16_t type;
++};
++
++#define UIP_ETHTYPE_ARP 0x0806
++#define UIP_ETHTYPE_IP 0x0800
++#define UIP_ETHTYPE_IP6 0x86dd
++
++
++/* The uip_arp_init() function must be called before any of the other
++ ARP functions. */
++void uip_arp_init(void);
++
++/* The uip_arp_ipin() function should be called whenever an IP packet
++ arrives from the Ethernet. This function refreshes the ARP table or
++ inserts a new mapping if none exists. The function assumes that an
++ IP packet with an Ethernet header is present in the uip_buf buffer
++ and that the length of the packet is in the uip_len variable. */
++void uip_arp_ipin(void);
++
++/* The uip_arp_arpin() should be called when an ARP packet is received
++ by the Ethernet driver. This function also assumes that the
++ Ethernet frame is present in the uip_buf buffer. When the
++ uip_arp_arpin() function returns, the contents of the uip_buf
++ buffer should be sent out on the Ethernet if the uip_len variable
++ is > 0. */
++void uip_arp_arpin(void);
++
++/* The uip_arp_out() function should be called when an IP packet
++ should be sent out on the Ethernet. This function creates an
++ Ethernet header before the IP header in the uip_buf buffer. The
++ Ethernet header will have the correct Ethernet MAC destination
++ address filled in if an ARP table entry for the destination IP
++ address (or the IP address of the default router) is present. If no
++ such table entry is found, the IP packet is overwritten with an ARP
++ request and we rely on TCP to retransmit the packet that was
++ overwritten. In any case, the uip_len variable holds the length of
++ the Ethernet frame that should be transmitted. */
++void uip_arp_out(void);
++
++/* The uip_arp_timer() function should be called every ten seconds. It
++ is responsible for flushing old entries in the ARP table. */
++void uip_arp_timer(void);
++
++/** @} */
++
++/**
++ * \addtogroup uipconffunc
++ * @{
++ */
++
++/**
++ * Set the default router's IP address.
++ *
++ * \param addr A pointer to a 4-byte array containing the IP address
++ * of the default router.
++ *
++ * \hideinitializer
++ */
++#define uip_setdraddr(addr) do { uip_arp_draddr[0] = addr[0]; \
++ uip_arp_draddr[1] = addr[1]; } while(0)
++
++/**
++ * Set the netmask.
++ *
++ * \param addr A pointer to a 4-byte array containing the IP address
++ * of the netmask.
++ *
++ * \hideinitializer
++ */
++#define uip_setnetmask(addr) do { uip_arp_netmask[0] = addr[0]; \
++ uip_arp_netmask[1] = addr[1]; } while(0)
++
++
++/**
++ * Get the default router's IP address.
++ *
++ * \param addr A pointer to a 4-byte array that will be filled in with
++ * the IP address of the default router.
++ *
++ * \hideinitializer
++ */
++#define uip_getdraddr(addr) do { addr[0] = uip_arp_draddr[0]; \
++ addr[1] = uip_arp_draddr[1]; } while(0)
++
++/**
++ * Get the netmask.
++ *
++ * \param addr A pointer to a 4-byte array that will be filled in with
++ * the value of the netmask.
++ *
++ * \hideinitializer
++ */
++#define uip_getnetmask(addr) do { addr[0] = uip_arp_netmask[0]; \
++ addr[1] = uip_arp_netmask[1]; } while(0)
++
++
++/**
++ * Specifiy the Ethernet MAC address.
++ *
++ * The ARP code needs to know the MAC address of the Ethernet card in
++ * order to be able to respond to ARP queries and to generate working
++ * Ethernet headers.
++ *
++ * \note This macro only specifies the Ethernet MAC address to the ARP
++ * code. It cannot be used to change the MAC address of the Ethernet
++ * card.
++ *
++ * \param eaddr A pointer to a struct uip_eth_addr containing the
++ * Ethernet MAC address of the Ethernet card.
++ *
++ * \hideinitializer
++ */
++#define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \
++ uip_ethaddr.addr[1] = eaddr.addr[1];\
++ uip_ethaddr.addr[2] = eaddr.addr[2];\
++ uip_ethaddr.addr[3] = eaddr.addr[3];\
++ uip_ethaddr.addr[4] = eaddr.addr[4];\
++ uip_ethaddr.addr[5] = eaddr.addr[5];} while(0)
++
++/** @} */
++
++/**
++ * \internal Internal variables that are set using the macros
++ * uip_setdraddr and uip_setnetmask.
++ */
++extern u16_t uip_arp_draddr[2], uip_arp_netmask[2];
++#endif /* __UIP_ARP_H__ */
++
++
+--- /dev/null
++++ b/net/uip-0.9/uipopt.h
+@@ -0,0 +1,557 @@
++/**
++ * \defgroup uipopt Configuration options for uIP
++ * @{
++ *
++ * uIP is configured using the per-project configuration file
++ * "uipopt.h". This file contains all compile-time options for uIP and
++ * should be tweaked to match each specific project. The uIP
++ * distribution contains a documented example "uipopt.h" that can be
++ * copied and modified for each project.
++ */
++
++/**
++ * \file
++ * Configuration options for uIP.
++ * \author Adam Dunkels <adam@dunkels.com>
++ *
++ * This file is used for tweaking various configuration options for
++ * uIP. You should make a copy of this file into one of your project's
++ * directories instead of editing this example "uipopt.h" file that
++ * comes with the uIP distribution.
++ */
++
++/*
++ * Copyright (c) 2001-2003, Adam Dunkels.
++ * 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.
++ *
++ * This file is part of the uIP TCP/IP stack.
++ *
++ * $Id: uipopt.h,v 1.16.2.5 2003/10/07 13:22:51 adam Exp $
++ *
++ */
++
++#ifndef __UIPOPT_H__
++#define __UIPOPT_H__
++
++/*------------------------------------------------------------------------------*/
++/**
++ * \defgroup uipopttypedef uIP type definitions
++ * @{
++ */
++
++/**
++ * The 8-bit unsigned data type.
++ *
++ * This may have to be tweaked for your particular compiler. "unsigned
++ * char" works for most compilers.
++ */
++typedef unsigned char u8_t;
++
++/**
++ * The 16-bit unsigned data type.
++ *
++ * This may have to be tweaked for your particular compiler. "unsigned
++ * short" works for most compilers.
++ */
++typedef unsigned short u16_t;
++
++/**
++ * The statistics data type.
++ *
++ * This datatype determines how high the statistics counters are able
++ * to count.
++ */
++typedef unsigned short uip_stats_t;
++
++/** @} */
++
++/*------------------------------------------------------------------------------*/
++
++/**
++ * \defgroup uipoptstaticconf Static configuration options
++ * @{
++ *
++ * These configuration options can be used for setting the IP address
++ * settings statically, but only if UIP_FIXEDADDR is set to 1. The
++ * configuration options for a specific node includes IP address,
++ * netmask and default router as well as the Ethernet address. The
++ * netmask, default router and Ethernet address are appliciable only
++ * if uIP should be run over Ethernet.
++ *
++ * All of these should be changed to suit your project.
++*/
++
++/**
++ * Determines if uIP should use a fixed IP address or not.
++ *
++ * If uIP should use a fixed IP address, the settings are set in the
++ * uipopt.h file. If not, the macros uip_sethostaddr(),
++ * uip_setdraddr() and uip_setnetmask() should be used instead.
++ *
++ * \hideinitializer
++ */
++#define UIP_FIXEDADDR 0
++
++/**
++ * Ping IP address asignment.
++ *
++ * uIP uses a "ping" packets for setting its own IP address if this
++ * option is set. If so, uIP will start with an empty IP address and
++ * the destination IP address of the first incoming "ping" (ICMP echo)
++ * packet will be used for setting the hosts IP address.
++ *
++ * \note This works only if UIP_FIXEDADDR is 0.
++ *
++ * \hideinitializer
++ */
++#define UIP_PINGADDRCONF 0
++
++#define UIP_IPADDR0 192 /**< The first octet of the IP address of
++ this uIP node, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++#define UIP_IPADDR1 168 /**< The second octet of the IP address of
++ this uIP node, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++#define UIP_IPADDR2 0 /**< The third octet of the IP address of
++ this uIP node, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++#define UIP_IPADDR3 250 /**< The fourth octet of the IP address of
++ this uIP node, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++
++#define UIP_NETMASK0 255 /**< The first octet of the netmask of
++ this uIP node, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++#define UIP_NETMASK1 255 /**< The second octet of the netmask of
++ this uIP node, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++#define UIP_NETMASK2 255 /**< The third octet of the netmask of
++ this uIP node, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++#define UIP_NETMASK3 0 /**< The fourth octet of the netmask of
++ this uIP node, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++
++#define UIP_DRIPADDR0 192 /**< The first octet of the IP address of
++ the default router, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++#define UIP_DRIPADDR1 168 /**< The second octet of the IP address of
++ the default router, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++#define UIP_DRIPADDR2 0 /**< The third octet of the IP address of
++ the default router, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++#define UIP_DRIPADDR3 1 /**< The fourth octet of the IP address of
++ the default router, if UIP_FIXEDADDR is
++ 1. \hideinitializer */
++
++/**
++ * Specifies if the uIP ARP module should be compiled with a fixed
++ * Ethernet MAC address or not.
++ *
++ * If this configuration option is 0, the macro uip_setethaddr() can
++ * be used to specify the Ethernet address at run-time.
++ *
++ * \hideinitializer
++ */
++#define UIP_FIXEDETHADDR 0
++
++#define UIP_ETHADDR0 0x00 /**< The first octet of the Ethernet
++ address if UIP_FIXEDETHADDR is
++ 1. \hideinitializer */
++#define UIP_ETHADDR1 0xbd /**< The second octet of the Ethernet
++ address if UIP_FIXEDETHADDR is
++ 1. \hideinitializer */
++#define UIP_ETHADDR2 0x3b /**< The third octet of the Ethernet
++ address if UIP_FIXEDETHADDR is
++ 1. \hideinitializer */
++#define UIP_ETHADDR3 0x33 /**< The fourth octet of the Ethernet
++ address if UIP_FIXEDETHADDR is
++ 1. \hideinitializer */
++#define UIP_ETHADDR4 0x05 /**< The fifth octet of the Ethernet
++ address if UIP_FIXEDETHADDR is
++ 1. \hideinitializer */
++#define UIP_ETHADDR5 0x71 /**< The sixth octet of the Ethernet
++ address if UIP_FIXEDETHADDR is
++ 1. \hideinitializer */
++
++/** @} */
++/*------------------------------------------------------------------------------*/
++/**
++ * \defgroup uipoptip IP configuration options
++ * @{
++ *
++ */
++/**
++ * The IP TTL (time to live) of IP packets sent by uIP.
++ *
++ * This should normally not be changed.
++ */
++#define UIP_TTL 255
++
++/**
++ * Turn on support for IP packet reassembly.
++ *
++ * uIP supports reassembly of fragmented IP packets. This features
++ * requires an additonal amount of RAM to hold the reassembly buffer
++ * and the reassembly code size is approximately 700 bytes. The
++ * reassembly buffer is of the same size as the uip_buf buffer
++ * (configured by UIP_BUFSIZE).
++ *
++ * \note IP packet reassembly is not heavily tested.
++ *
++ * \hideinitializer
++ */
++#define UIP_REASSEMBLY 0
++
++/**
++ * The maximum time an IP fragment should wait in the reassembly
++ * buffer before it is dropped.
++ *
++ */
++#define UIP_REASS_MAXAGE 40
++
++/** @} */
++
++/*------------------------------------------------------------------------------*/
++/**
++ * \defgroup uipoptudp UDP configuration options
++ * @{
++ *
++ * \note The UDP support in uIP is still not entirely complete; there
++ * is no support for sending or receiving broadcast or multicast
++ * packets, but it works well enough to support a number of vital
++ * applications such as DNS queries, though
++ */
++
++/**
++ * Toggles wether UDP support should be compiled in or not.
++ *
++ * \hideinitializer
++ */
++#define UIP_UDP 0
++
++/**
++ * Toggles if UDP checksums should be used or not.
++ *
++ * \note Support for UDP checksums is currently not included in uIP,
++ * so this option has no function.
++ *
++ * \hideinitializer
++ */
++#define UIP_UDP_CHECKSUMS 0
++
++/**
++ * The maximum amount of concurrent UDP connections.
++ *
++ * \hideinitializer
++ */
++#define UIP_UDP_CONNS 10
++
++/**
++ * The name of the function that should be called when UDP datagrams arrive.
++ *
++ * \hideinitializer
++ */
++#define UIP_UDP_APPCALL udp_appcall
++
++/** @} */
++/*------------------------------------------------------------------------------*/
++/**
++ * \defgroup uipopttcp TCP configuration options
++ * @{
++ */
++
++/**
++ * Determines if support for opening connections from uIP should be
++ * compiled in.
++ *
++ * If the applications that are running on top of uIP for this project
++ * do not need to open outgoing TCP connections, this configration
++ * option can be turned off to reduce the code size of uIP.
++ *
++ * \hideinitializer
++ */
++#define UIP_ACTIVE_OPEN 1
++
++/**
++ * The maximum number of simultaneously open TCP connections.
++ *
++ * Since the TCP connections are statically allocated, turning this
++ * configuration knob down results in less RAM used. Each TCP
++ * connection requires approximatly 30 bytes of memory.
++ *
++ * \hideinitializer
++ */
++#define UIP_CONNS 10
++
++/**
++ * The maximum number of simultaneously listening TCP ports.
++ *
++ * Each listening TCP port requires 2 bytes of memory.
++ *
++ * \hideinitializer
++ */
++#define UIP_LISTENPORTS 10
++
++/**
++ * The size of the advertised receiver's window.
++ *
++ * Should be set low (i.e., to the size of the uip_buf buffer) is the
++ * application is slow to process incoming data, or high (32768 bytes)
++ * if the application processes data quickly.
++ *
++ * \hideinitializer
++ */
++#define UIP_RECEIVE_WINDOW 32768
++
++/**
++ * Determines if support for TCP urgent data notification should be
++ * compiled in.
++ *
++ * Urgent data (out-of-band data) is a rarely used TCP feature that
++ * very seldom would be required.
++ *
++ * \hideinitializer
++ */
++#define UIP_URGDATA 1
++
++/**
++ * The initial retransmission timeout counted in timer pulses.
++ *
++ * This should not be changed.
++ */
++#define UIP_RTO 3
++
++/**
++ * The maximum number of times a segment should be retransmitted
++ * before the connection should be aborted.
++ *
++ * This should not be changed.
++ */
++#define UIP_MAXRTX 8
++
++/**
++ * The maximum number of times a SYN segment should be retransmitted
++ * before a connection request should be deemed to have been
++ * unsuccessful.
++ *
++ * This should not need to be changed.
++ */
++#define UIP_MAXSYNRTX 3
++
++/**
++ * The TCP maximum segment size.
++ *
++ * This is should not be to set to more than UIP_BUFSIZE - UIP_LLH_LEN - 40.
++ */
++#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - 40)
++
++/**
++ * How long a connection should stay in the TIME_WAIT state.
++ *
++ * This configiration option has no real implication, and it should be
++ * left untouched.
++ */
++#define UIP_TIME_WAIT_TIMEOUT 120
++
++
++/** @} */
++/*------------------------------------------------------------------------------*/
++/**
++ * \defgroup uipoptarp ARP configuration options
++ * @{
++ */
++
++/**
++ * The size of the ARP table.
++ *
++ * This option should be set to a larger value if this uIP node will
++ * have many connections from the local network.
++ *
++ * \hideinitializer
++ */
++#define UIP_ARPTAB_SIZE 8
++
++/**
++ * The maxium age of ARP table entries measured in 10ths of seconds.
++ *
++ * An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD
++ * default).
++ */
++#define UIP_ARP_MAXAGE 120
++
++/** @} */
++
++/*------------------------------------------------------------------------------*/
++
++/**
++ * \defgroup uipoptgeneral General configuration options
++ * @{
++ */
++
++/**
++ * The size of the uIP packet buffer.
++ *
++ * The uIP packet buffer should not be smaller than 60 bytes, and does
++ * not need to be larger than 1500 bytes. Lower size results in lower
++ * TCP throughput, larger size results in higher TCP throughput.
++ *
++ * \hideinitializer
++ */
++#define UIP_BUFSIZE 1500
++
++
++/**
++ * Determines if statistics support should be compiled in.
++ *
++ * The statistics is useful for debugging and to show the user.
++ *
++ * \hideinitializer
++ */
++#define UIP_STATISTICS 1
++
++/**
++ * Determines if logging of certain events should be compiled in.
++ *
++ * This is useful mostly for debugging. The function uip_log()
++ * must be implemented to suit the architecture of the project, if
++ * logging is turned on.
++ *
++ * \hideinitializer
++ */
++#define UIP_LOGGING 0
++
++/**
++ * Print out a uIP log message.
++ *
++ * This function must be implemented by the module that uses uIP, and
++ * is called by uIP whenever a log message is generated.
++ */
++void uip_log(char *msg);
++
++/**
++ * The link level header length.
++ *
++ * This is the offset into the uip_buf where the IP header can be
++ * found. For Ethernet, this should be set to 14. For SLIP, this
++ * should be set to 0.
++ *
++ * \hideinitializer
++ */
++#define UIP_LLH_LEN 14
++
++
++/** @} */
++/*------------------------------------------------------------------------------*/
++/**
++ * \defgroup uipoptcpu CPU architecture configuration
++ * @{
++ *
++ * The CPU architecture configuration is where the endianess of the
++ * CPU on which uIP is to be run is specified. Most CPUs today are
++ * little endian, and the most notable exception are the Motorolas
++ * which are big endian. The BYTE_ORDER macro should be changed to
++ * reflect the CPU architecture on which uIP is to be run.
++ */
++#ifndef LITTLE_ENDIAN
++#define LITTLE_ENDIAN 3412
++#endif /* LITTLE_ENDIAN */
++#ifndef BIG_ENDIAN
++#define BIG_ENDIAN 1234
++#endif /* BIGE_ENDIAN */
++
++/**
++ * The byte order of the CPU architecture on which uIP is to be run.
++ *
++ * This option can be either BIG_ENDIAN (Motorola byte order) or
++ * LITTLE_ENDIAN (Intel byte order).
++ *
++ * \hideinitializer
++ */
++/*#ifndef BYTE_ORDER*/
++#define BYTE_ORDER BIG_ENDIAN
++/*#endif*/ /* BYTE_ORDER */
++
++/** @} */
++/*------------------------------------------------------------------------------*/
++
++/**
++ * \defgroup uipoptapp Appication specific configurations
++ * @{
++ *
++ * An uIP application is implemented using a single application
++ * function that is called by uIP whenever a TCP/IP event occurs. The
++ * name of this function must be registered with uIP at compile time
++ * using the UIP_APPCALL definition.
++ *
++ * uIP applications can store the application state within the
++ * uip_conn structure by specifying the size of the application
++ * structure with the UIP_APPSTATE_SIZE macro.
++ *
++ * The file containing the definitions must be included in the
++ * uipopt.h file.
++ *
++ * The following example illustrates how this can look.
++ \code
++
++void httpd_appcall(void);
++#define UIP_APPCALL httpd_appcall
++
++struct httpd_state {
++ u8_t state;
++ u16_t count;
++ char *dataptr;
++ char *script;
++};
++#define UIP_APPSTATE_SIZE (sizeof(struct httpd_state))
++ \endcode
++ */
++
++/**
++ * \var #define UIP_APPCALL
++ *
++ * The name of the application function that uIP should call in
++ * response to TCP/IP events.
++ *
++ */
++
++/**
++ * \var #define UIP_APPSTATE_SIZE
++ *
++ * The size of the application state that is to be stored in the
++ * uip_conn structure.
++ */
++/** @} */
++
++/* Include the header file for the application program that should be
++ used. If you don't use the example web server, you should change
++ this. */
++#include "httpd.h"
++
++
++#endif /* __UIPOPT_H__ */
+--- a/board/infineon/easy50712/danube.c
++++ b/board/infineon/easy50712/danube.c
+@@ -354,7 +354,7 @@ int do_http_upgrade(const unsigned char
+ }
+ /* write the image to the flash */
+ puts("http ugrade ...\n");
+- sprintf(buf, "era ${kernel_addr} +0x%x; cp.b ${ram_addr} ${kernel_addr} 0x%x", size, size);
++ sprintf(buf, "era ${kernel_addr} +0x%lx; cp.b ${ram_addr} ${kernel_addr} 0x%lx", size, size);
+ return run_command(buf, 0);
+ }
+
+--- a/common/main.c
++++ b/common/main.c
+@@ -273,6 +273,8 @@ static __inline__ int abortboot(int boot
+
+ void main_loop (void)
+ {
++ int ret;
++
+ #ifndef CONFIG_SYS_HUSH_PARSER
+ static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, };
+ int len;
+@@ -403,12 +407,22 @@ void main_loop (void)
+ # endif
+
+ # ifndef CONFIG_SYS_HUSH_PARSER
+- run_command (s, 0);
++ ret = run_command (s, 0);
+ # else
+- parse_string_outer(s, FLAG_PARSE_SEMICOLON |
++ ret = parse_string_outer(s, FLAG_PARSE_SEMICOLON |
+ FLAG_EXIT_FROM_LOOP);
+ # endif
+
++# ifdef CONFIG_CMD_HTTPD
++ if (ret != 0) {
++ printf("Failed to execute bootcmd "
++ "(maybe invalid u-boot environment?), "
++ "starting httpd to update firmware...\n");
++ NetLoopHttpd();
++ }
++# endif
++
++
+ # ifdef CONFIG_AUTOBOOT_KEYED
+ disable_ctrlc(prev); /* restore Control C checking */
+ # endif
+--- a/include/configs/easy50712.h
++++ b/include/configs/easy50712.h
+@@ -114,4 +114,7 @@
+
+ #define CONFIG_CMD_HTTPD /* enable upgrade via HTTPD */
+
++#define CONFIG_IPADDR 192.168.0.119
++#define CONFIG_ETHADDR 00:01:02:03:04:05
++
+ #endif /* __CONFIG_H */
+--- a/lib_mips/time.c
++++ b/lib_mips/time.c
+@@ -29,6 +29,8 @@ static unsigned long timestamp;
+ /* how many counter cycles in a jiffy */
+ #define CYCLES_PER_JIFFY (CONFIG_SYS_MIPS_TIMER_FREQ + CONFIG_SYS_HZ / 2) / CONFIG_SYS_HZ
+
++unsigned long ifx_get_cpuclk(void);
++
+ /*
+ * timer without interrupts
+ */
+--- a/net/httpd.c
++++ b/net/httpd.c
+@@ -35,12 +35,14 @@ HttpdHandler (void)
+ }
+ }
+
++#if 0
+ static void
+ HttpdTimeout (void)
+ {
+ puts ("T ");
+ NetSetTimeout (TIMEOUT * 1000, HttpdTimeout);
+ }
++#endif
+
+ void
+ HttpdStart (void)
+--- a/net/net.c
++++ b/net/net.c
+@@ -1966,7 +1966,7 @@ NetSendHttpd(void)
+ void
+ NetReceiveHttpd(volatile uchar * inpkt, int len)
+ {
+- memcpy(uip_buf, inpkt, len);
++ memcpy(uip_buf, (const void *)inpkt, len);
+ uip_len = len;
+ if(BUF->type == htons(UIP_ETHTYPE_IP)) {
+ uip_arp_ipin();
+@@ -1989,6 +1989,7 @@ NetLoopHttpd(void)
+ unsigned long long tout = 0;
+ bd_t *bd = gd->bd;
+ unsigned short int ip[2];
++ struct uip_eth_addr eaddr;
+
+ #ifdef CONFIG_NET_MULTI
+ NetRestarted = 0;
+@@ -2039,6 +2040,15 @@ restart:
+ eth_getenv_enetaddr("ethaddr", NetOurEther);
+ #endif
+
++ eaddr.addr[0] = NetOurEther[0];
++ eaddr.addr[1] = NetOurEther[1];
++ eaddr.addr[2] = NetOurEther[2];
++ eaddr.addr[3] = NetOurEther[3];
++ eaddr.addr[4] = NetOurEther[4];
++ eaddr.addr[5] = NetOurEther[5];
++
++ uip_setethaddr(eaddr);
++
+ NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
+ NetOurGatewayIP = getenv_IPaddr ("gatewayip");
+ NetOurSubnetMask= getenv_IPaddr ("netmask");
+@@ -2072,6 +2082,14 @@ restart:
+ tout = t1;
+ }
+ }
++
++ if (ctrlc()) {
++ eth_halt();
++ puts ("\nAbort\n");
++ return (-1);
++ }
++
++
+ if(!httpd_upload_complete)
+ continue;
+ printf("Bytes transferred = %ld (%lx hex)\n",
+--- a/net/uip-0.9/fsdata.c
++++ b/net/uip-0.9/fsdata.c
+@@ -1,199 +1,108 @@
+-static const char data_flashing_html[] = {
+- /* /flashing.html */
+- 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
+- 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
+- 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30,
+- 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+- 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63,
+- 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69,
+- 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65,
+- 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74,
+- 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa,
+- 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c, 0x62,
+- 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3d,
+- 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30,
+- 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x20, 0x68,
+- 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x31, 0x30, 0x30, 0x25,
+- 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23,
+- 0x66, 0x66, 0x66, 0x3b, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67,
+- 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+- 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, 0x62, 0x30, 0x33, 0x34,
+- 0x3b, 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72,
+- 0x3e, 0x3c, 0x68, 0x31, 0x3e, 0x55, 0x70, 0x67, 0x72, 0x61,
+- 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65,
+- 0x6d, 0x20, 0x2e, 0x2e, 0x2e, 0x2e, 0x3c, 0x2f, 0x68, 0x31,
+- 0x3e, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e,
+- 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68,
+- 0x74, 0x6d, 0x6c, 0x3e, 0xa, };
+-
+-static const char data_fail_html[] = {
+- /* /fail.html */
+- 0x2f, 0x66, 0x61, 0x69, 0x6c, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
+- 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
+- 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30,
+- 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+- 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63,
+- 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69,
+- 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65,
+- 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74,
+- 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa,
+- 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9,
+- 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c,
+- 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9,
+- 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46,
+- 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49,
+- 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65,
+- 0x3e, 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa,
+- 0x9, 0x9, 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73,
+- 0x68, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65,
+- 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9, 0x45,
+- 0x52, 0x52, 0x4f, 0x52, 0x20, 0x2d, 0x20, 0x74, 0x68, 0x65,
+- 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x79, 0x6f, 0x75,
+- 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x20,
+- 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20,
+- 0x70, 0x61, 0x73, 0x73, 0x20, 0x76, 0x65, 0x72, 0x69, 0x66,
+- 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x50,
+- 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x6d, 0x61, 0x6b, 0x65,
+- 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x75,
+- 0x73, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x66, 0x66, 0x69,
+- 0x63, 0x69, 0x61, 0x6c, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74,
+- 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64,
+- 0x20, 0x62, 0x79, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+- 0x2f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e,
+- 0x66, 0x6f, 0x6e, 0x6f, 0x73, 0x66, 0x65, 0x72, 0x61, 0x2e,
+- 0x6f, 0x72, 0x67, 0x2f, 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f,
+- 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c,
+- 0x3e, 0xa, };
+-
+-static const char data_404_html[] = {
+- /* /404.html */
+- 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x34,
+- 0x30, 0x34, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f,
+- 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0xd, 0xa, 0x53,
+- 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50,
+- 0x2f, 0x30, 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70,
+- 0x3a, 0x2f, 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73,
+- 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f,
+- 0x75, 0x69, 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e,
+- 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a,
+- 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c,
+- 0xd, 0xa, 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e,
+- 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f,
+- 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65,
+- 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e,
+- 0x3c, 0x68, 0x31, 0x3e, 0x34, 0x30, 0x34, 0x20, 0x2d, 0x20,
+- 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66,
+- 0x6f, 0x75, 0x6e, 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0x3c,
+- 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x2f,
+- 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74, 0x6d,
+- 0x6c, 0x3e, };
+-
+-static const char data_index_html[] = {
+- /* /index.html */
+- 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
+- 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
+- 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30,
+- 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+- 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63,
+- 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69,
+- 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65,
+- 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74,
+- 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa,
+- 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9,
+- 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c,
+- 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9,
+- 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46,
+- 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49,
+- 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65,
+- 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e,
+- 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74,
+- 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69,
+- 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74,
+- 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a,
+- 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
+- 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62,
+- 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+- 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62,
+- 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9,
+- 0x3c, 0x68, 0x31, 0x3e, 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65,
+- 0x72, 0x61, 0x20, 0x46, 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66,
+- 0x65, 0x20, 0x55, 0x49, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa,
+- 0x9, 0x9, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x65,
+- 0x74, 0x68, 0x6f, 0x64, 0x3d, 0x22, 0x70, 0x6f, 0x73, 0x74,
+- 0x22, 0x20, 0x65, 0x6e, 0x63, 0x74, 0x79, 0x70, 0x65, 0x3d,
+- 0x22, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74,
+- 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x64, 0x61, 0x74, 0x61,
+- 0x22, 0x3e, 0xa, 0x9, 0x9, 0x9, 0x3c, 0x69, 0x6e, 0x70,
+- 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69,
+- 0x6c, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x66, 0x69,
+- 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x3e, 0xa, 0x9, 0x9,
+- 0x9, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79,
+- 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x3e,
+- 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x3e,
+- 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa,
+- 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, };
+-
+-static const char data_flash_html[] = {
+- /* /flash.html */
+- 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
+- 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72,
+- 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30,
+- 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+- 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63,
+- 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69,
+- 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65,
+- 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74,
+- 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa,
+- 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9,
+- 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c,
+- 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9,
+- 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46,
+- 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49,
+- 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65,
+- 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e,
+- 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74,
+- 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69,
+- 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74,
+- 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a,
+- 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
+- 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62,
+- 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+- 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62,
+- 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9,
+- 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73, 0x68, 0x69,
+- 0x6e, 0x67, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9,
+- 0x54, 0x68, 0x65, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
+- 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x72,
+- 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x6c,
+- 0x61, 0x73, 0x68, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68,
+- 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x70,
+- 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x2c, 0x20, 0x74, 0x68,
+- 0x65, 0x20, 0x6c, 0x65, 0x64, 0x73, 0x20, 0x77, 0x69, 0x6c,
+- 0x6c, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x6f,
+- 0x20, 0x62, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0xa, 0xa, 0x9,
+- 0x9, 0x41, 0x66, 0x74, 0x65, 0x72, 0x20, 0x61, 0x20, 0x73,
+- 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x6c,
+- 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68,
+- 0x65, 0x20, 0x62, 0x6f, 0x78, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+- 0x20, 0x72, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0xa, 0x9, 0x3c,
+- 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68,
+- 0x74, 0x6d, 0x6c, 0x3e, 0xa, };
+-
+-const struct fsdata_file file_flashing_html[] = {{NULL, data_flashing_html, data_flashing_html + 15, sizeof(data_flashing_html) - 15}};
++static const char data_flashing_html[] =
++"HTTP/1.0 200 OK\n"
++"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n"
++"Content-type: text/html\n"
++"\n"
++"<html>\n"
++"\t<head>\n"
++"\t\t<title>\n"
++"\t\t\tFailsafe UI\n"
++"\t\t</title>\n"
++"\t</head>\n"
++"\t<body>\n"
++"\t\t<center><h1>Upgrading system...</h1></center>\n"
++"\t</body>\n"
++"</html>\n";
++
++static const char data_fail_html[] =
++"HTTP/1.0 200 OK\n"
++"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n"
++"Content-type: text/html\n"
++"\n"
++"<html>\n"
++"\t<head>\n"
++"\t\t<title>\n"
++"\t\t\tFailsafe UI\n"
++"\t\t</title>\n"
++"\t</head>\n"
++"\t<body>\n"
++"\t\t<h1>Flashing failed</h1>\n"
++"\t\tERROR - the image you uploaded failed to pass verification.<br>\n"
++"\t\tPlease make sure to use an official update provided by http://lantiq.com/\n"
++"\t</body>\n"
++"</html>\n";
++
++static const char data_404_html[] =
++"HTTP/1.0 404 File not found\n"
++"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n"
++"Content-type: text/html\n"
++"\n"
++"<html>\n"
++"\t<head>\n"
++"\t\t<title>\n"
++"\t\t\tFailsafe UI\n"
++"\t\t</title>\n"
++"\t</head>\n"
++"\t<body>\n"
++"\t\t<center><h1>404 - file not found</h1></center>\n"
++"\t</body>\n"
++"</html>\n";
++
++static const char data_index_html[] =
++"HTTP/1.0 200 OK\n"
++"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n"
++"Content-type: text/html\n"
++"\n"
++"<html>\n"
++"\t<head>\n"
++"\t\t<title>\n"
++"\t\t\tFailsafe UI\n"
++"\t\t</title>\n"
++"\t</head>\n"
++"\t<body>\n"
++"\t\t<h1>Failsafe UI</h1>\n"
++"\t\t<form method=\"post\" enctype=\"multipart/form-data\">\n"
++"\t\t\t<input type=file name=firmware>\n"
++"\t\t\t<input type=submit>\n"
++"\t\t</form>\n"
++"\t</body>\n"
++"</html>\n";
++
++static const char data_flash_html[] =
++"HTTP/1.0 200 OK\n"
++"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n"
++"Content-type: text/html\n"
++"\n"
++"<html>\n"
++"\t<head>\n"
++"\t\t<title>\n"
++"\t\t\tFailsafe UI\n"
++"\t\t</title>\n"
++"\t</head>\n"
++"\t<body>\n"
++"\t\t<h1>Flashing...</h1>\n"
++"\t\tThe system is now trying to flash. If there is a problem, the LEDs will "
++"start to blink.<br>\n"
++"\n"
++"\t\tAfter a successful update the box will reboot\n"
++"\t</body>\n"
++"</html>\n";
++
++const struct fsdata_file file_flashing_html[] =
++{{NULL, "/flashing.html", data_flashing_html, sizeof(data_flashing_html)}};
++
++const struct fsdata_file file_fail_html[] =
++{{file_flashing_html, "/fail.html", data_fail_html, sizeof(data_fail_html)}};
+
+-const struct fsdata_file file_fail_html[] = {{file_flashing_html, data_fail_html, data_fail_html + 11, sizeof(data_fail_html) - 11}};
++const struct fsdata_file file_404_html[] =
++{{file_fail_html, "/404.html", data_404_html, sizeof(data_404_html)}};
+
+-const struct fsdata_file file_404_html[] = {{file_fail_html, data_404_html, data_404_html + 10, sizeof(data_404_html) - 10}};
++const struct fsdata_file file_index_html[] =
++{{file_404_html, "/index.html", data_index_html, sizeof(data_index_html)}};
+
+-const struct fsdata_file file_index_html[] = {{file_404_html, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}};
+-
+-const struct fsdata_file file_flash_html[] = {{file_index_html, data_flash_html, data_flash_html + 12, sizeof(data_flash_html) - 12}};
++const struct fsdata_file file_flash_html[] =
++{{file_index_html, "/flash.html", data_flash_html, sizeof(data_flash_html)}};
+
+ #define FS_ROOT file_flash_html
+
+-#define FS_NUMFILES 5
+\ No newline at end of file
++#define FS_NUMFILES 5
+--- a/net/uip-0.9/httpd.c
++++ b/net/uip-0.9/httpd.c
+@@ -130,7 +130,7 @@ httpd_appcall(void)
+ if(!fs_open((const char *)&uip_appdata[4], &fsfile))
+ {
+ PRINTLN("couldn't open file");
+- fs_open(file_index_html.name, &fsfile);
++ fs_open(file_404_html.name, &fsfile);
+ }
+ }
+ hs->script = 0;
+@@ -141,7 +141,7 @@ httpd_appcall(void)
+ if(hs->state == HTTP_FIRMWARE)
+ {
+ unsigned char *start = (unsigned char*)uip_appdata;
+- char *clen = strstr(start, "Content-Length:");
++ char *clen = strstr((char *)start, "Content-Length:");
+ int len = 0;
+ unsigned char *next, *end;
+ unsigned char *boundary_start;
+@@ -150,14 +150,14 @@ httpd_appcall(void)
+ if(clen)
+ {
+ clen += sizeof("Content-Length:");
+- next = strstr(clen, eol);
++ next = (unsigned char *)strstr(clen, eol);
+ if(next)
+ {
+ len = atoi(clen);
+ next++;
+ printf("expecting %d bytes\n", len);
+ upload_data = httpd_upload_data = (unsigned char *)do_http_tmp_address();
+- printf("received data will be stored at 0x%08X\n", upload_data);
++ printf("received data will be stored at %p\n", upload_data);
+ if(!upload_data)
+ {
+ printf("failed to allocate memory\n");
+@@ -174,14 +174,14 @@ httpd_appcall(void)
+ uip_close();
+ return;
+ }
+- boundary_start = strstr(next, "---");
++ boundary_start = (unsigned char *)strstr((char *)next, "---");
+ if(!boundary_start)
+ {
+ uip_close();
+ return;
+ }
+- end = strstr(boundary_start, eol);
+- if(!eol)
++ end = (unsigned char *)strstr((char *)boundary_start, eol);
++ if(!end)
+ {
+ uip_close();
+ return;
+@@ -189,13 +189,13 @@ httpd_appcall(void)
+ boundary_len = end - boundary_start;
+ memcpy(boundary, boundary_start, boundary_len);
+ boundary[boundary_len] = 0;
+- next = strstr(boundary_start, "name=\"firmware\";");
++ next = (unsigned char *)strstr((char *)boundary_start, "name=\"firmware\";");
+ if(!next)
+ {
+ uip_close();
+ return;
+ }
+- next = strstr(next, eol2);
++ next = (unsigned char *)strstr((char *)next, eol2);
+ if(!next)
+ {
+ printf("could not find start of data\n");
+@@ -259,7 +259,6 @@ httpd_appcall(void)
+ {
+ if(upload_running)
+ {
+- int i;
+ httpd_upload_complete = 1;
+ // for(i = 0; i < hs->upload_total; i++)
+ // printf("%c", httpd_upload_data[i]);
+@@ -267,7 +266,7 @@ httpd_appcall(void)
+ uip_close();
+ }
+ }
+- uip_send(hs->dataptr, hs->count);
++ uip_send((unsigned char *)hs->dataptr, hs->count);
+ }
+ break;
+
diff --git a/package/uboot-lantiq/patches/300-arcadyan.patch b/package/uboot-lantiq/patches/300-arcadyan.patch
new file mode 100644
index 000000000..a91ac589f
--- /dev/null
+++ b/package/uboot-lantiq/patches/300-arcadyan.patch
@@ -0,0 +1,98 @@
+--- a/common/Makefile
++++ b/common/Makefile
+@@ -127,7 +127,9 @@
+ ifdef CONFIG_PCI
+ COBJS-$(CONFIG_CMD_PCI) += cmd_pci.o
+ endif
++ifdef CONFIG_CMD_PCMCIA
+ COBJS-y += cmd_pcmcia.o
++endif
+ COBJS-$(CONFIG_CMD_PORTIO) += cmd_portio.o
+ COBJS-$(CONFIG_CMD_REGINFO) += cmd_reginfo.o
+ COBJS-$(CONFIG_CMD_REISER) += cmd_reiser.o
+--- a/drivers/pcmcia/Makefile
++++ b/drivers/pcmcia/Makefile
+@@ -28,9 +28,11 @@
+ COBJS-$(CONFIG_I82365) += i82365.o
+ COBJS-$(CONFIG_8xx) += mpc8xx_pcmcia.o
+ COBJS-$(CONFIG_PXA_PCMCIA) += pxa_pcmcia.o
+-COBJS-y += rpx_pcmcia.o
++#COBJS-y += rpx_pcmcia.o
++COBJS-$(CONFIG_RPX_PCMCIA) += rpx_pcmcia.o
+ COBJS-$(CONFIG_IDE_TI_CARDBUS) += ti_pci1410a.o
+-COBJS-y += tqm8xx_pcmcia.o
++#COBJS-y += tqm8xx_pcmcia.o
++COBJS-$(CONFIG_TQM8XX_PCMCIA) += tqm8xx_pcmcia.o
+ COBJS-$(CONFIG_MARUBUN_PCCARD) += marubun_pcmcia.o
+
+ COBJS := $(COBJS-y)
+--- a/drivers/usb/phy/Makefile
++++ b/drivers/usb/phy/Makefile
+@@ -23,7 +23,7 @@
+ LIB := $(obj)libusb_phy.a
+
+ COBJS-$(CONFIG_TWL4030_USB) += twl4030.o
+-COBJS-y := twl4030.o
++#COBJS-y := twl4030.o
+
+ COBJS := $(COBJS-y)
+ SRCS := $(COBJS:.o=.c)
+--- a/Makefile
++++ b/Makefile
+@@ -3414,6 +3414,42 @@
+ ## MIPS32 ifxcpe
+ #########################################################################
+
++define arcadyan
++$(1) : unconfig
++ @mkdir -p $(obj)include
++ @mkdir -p $(obj)board/arcadyan/
++ @[ -z "$$(findstring brnboot,$$@)" ] || \
++ { echo "TEXT_BASE = 0x80002000" >$(obj)board/arcadyan/config.tmp ; \
++ echo "#define CONFIG_SYS_RAMBOOT" >>$(obj)include/config.h ; \
++ echo "#define CONFIG_SYS_BRNBOOT" >>$(obj)include/config.h ; \
++ $(XECHO) "... with brnboot configuration" ; \
++ }
++ @[ -z "$$(findstring ramboot,$$@)" ] || \
++ { echo "TEXT_BASE = 0xA0400000" >$(obj)board/arcadyan/config.tmp ; \
++ echo "#define CONFIG_SYS_RAMBOOT" >>$(obj)include/config.h ; \
++ $(XECHO) "... with ramboot configuration" ; \
++ }
++ @if [ "$$(findstring flash,$$@)" ] ; then \
++ echo "#TEXT_BASE = 0xB0050000" >$(obj)board/arcadyan/config.tmp ; \
++ echo "#define CONFIG_BOOTSTRAP" >>$(obj)include/config.h ; \
++ echo "#define CONFIG_USE_DDR_RAM" >>$(obj)include/config.h ; \
++ echo "#define CONFIG_USE_DDR_RAM_CFG_psc166" >>$(obj)include/config.h ; \
++ fi
++ @$(MKCONFIG) -a $$(word 1,$$(subst _, ,$$@)) mips mips arcadyan "" danube
++endef
++
++$(eval $(call arcadyan, arv3527P%config))
++$(eval $(call arcadyan, arv4520PW%config))
++$(eval $(call arcadyan, arv452CPW%config))
++$(eval $(call arcadyan, arv4525PW%config))
++$(eval $(call arcadyan, arv4510PW%config))
++$(eval $(call arcadyan, arv4518PW%config))
++$(eval $(call arcadyan, arv4519PW%config))
++$(eval $(call arcadyan, arv7518PW%config))
++$(eval $(call arcadyan, arv7525PW%config))
++$(eval $(call arcadyan, arv752DPW%config))
++$(eval $(call arcadyan, arv752DPW22%config))
++
+ easy50712%config : unconfig
+ @mkdir -p $(obj)include
+ @mkdir -p $(obj)board/infineon/easy50712
+--- a/net/tftp.c
++++ b/net/tftp.c
+@@ -11,9 +11,9 @@
+ #include "bootp.h"
+
+ #define WELL_KNOWN_PORT 69 /* Well known TFTP port # */
+-#define TIMEOUT 5000UL /* Millisecs to timeout for lost pkt */
++#define TIMEOUT 10000UL /* Millisecs to timeout for lost pkt */
+ #ifndef CONFIG_NET_RETRY_COUNT
+-# define TIMEOUT_COUNT 10 /* # of timeouts before giving up */
++# define TIMEOUT_COUNT 200 /* # of timeouts before giving up */
+ #else
+ # define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT * 2)
+ #endif
diff --git a/package/uboot-lantiq/patches/400-lzma.patch b/package/uboot-lantiq/patches/400-lzma.patch
new file mode 100644
index 000000000..b2f498ac5
--- /dev/null
+++ b/package/uboot-lantiq/patches/400-lzma.patch
@@ -0,0 +1,1687 @@
+--- a/.gitignore
++++ b/.gitignore
+@@ -23,6 +23,11 @@
+ /u-boot.hex
+ /u-boot.map
+ /u-boot.bin
++/u-boot.bin.bz2
++/u-boot.bin.gz
++/u-boot.bin.lzma
++/u-boot.bin.lzo
++/u-boot.dis
+ /u-boot.srec
+ /u-boot.ldr
+ /u-boot.ldr.hex
+@@ -30,6 +35,20 @@
+ /u-boot.lds
+ /u-boot-onenand.bin
+ /u-boot-flexonenand.bin
++/u-boot-bootstrap
++/u-boot-bootstrap.hex
++/u-boot-bootstrap.map
++/u-boot-bootstrap.bin
++/u-boot-bootstrap.bin.bz2
++/u-boot-bootstrap.bin.gz
++/u-boot-bootstrap.bin.lzma
++/u-boot-bootstrap.bin.lzo
++/u-boot-bootstrap.dis
++/u-boot-bootstrap.srec
++/u-boot-bootstrap.ldr
++/u-boot-bootstrap.ldr.hex
++/u-boot-bootstrap.ldr.srec
++/u-boot-bootstrap.lds
+
+ #
+ # Generated files
+@@ -38,6 +57,7 @@
+ *.depend
+ /LOG
+ /errlog
++/.payload.s
+ /reloc_off
+
+ # stgit generated dirs
+@@ -63,3 +83,6 @@
+ /onenand_ipl/onenand-ipl*
+ /onenand_ipl/board/*/onenand*
+ /onenand_ipl/board/*/*.S
++examples/standalone/
++
++setvars
+--- a/Makefile
++++ b/Makefile
+@@ -183,6 +183,12 @@
+
+ OBJS := $(addprefix $(obj),$(OBJS))
+
++ifeq ($(CONFIG_BOOTSTRAP),y)
++BOOTSTRAP_OBJS = cpu/$(ARCH)/start_bootstrap.o
++
++BOOTSTRAP_OBJS := $(addprefix $(obj),$(BOOTSTRAP_OBJS))
++endif
++
+ LIBS = lib_generic/libgeneric.a
+ LIBS += lib_generic/lzma/liblzma.a
+ LIBS += lib_generic/lzo/liblzo.a
+@@ -254,6 +260,25 @@
+ LIBBOARD = board/$(BOARDDIR)/lib$(BOARD).a
+ LIBBOARD := $(addprefix $(obj),$(LIBBOARD))
+
++ifeq ($(CONFIG_BOOTSTRAP),y)
++BOOTSTRAP_LIBS = lib_generic/libgeneric_bootstrap.a
++BOOTSTRAP_LIBS += cpu/$(ARCH)/lib$(ARCH)_bootstrap.a
++BOOTSTRAP_LIBS += lib_$(ARCH)/lib$(ARCH)_bootstrap.a
++BOOTSTRAP_LIBS += common/libcommon_bootstrap.a
++BOOTSTRAP_LIBS-$(CONFIG_BOOTSTRAP_SERIAL) += drivers/serial/libserial.a
++
++BOOTSTRAP_LIBS-$(CONFIG_BOOTSTRAP_LZMA) += lib_generic/lzma/liblzma.a
++BOOTSTRAP_LIBS-$(CONFIG_BOOTSTRAP_LZO) += lib/lzo/liblzo.a
++BOOTSTRAP_LIBS += $(BOOTSTRAP_LIBS-y)
++
++BOOTSTRAP_LIBS := $(addprefix $(obj),$(BOOTSTRAP_LIBS))
++.PHONY : $(BOOTSTRAP_LIBS)
++
++BOOTSTRAP_LIBBOARD = board/$(BOARDDIR)/lib$(BOARD)_bootstrap.a
++BOOTSTRAP_LIBBOARD := $(addprefix $(obj),$(BOOTSTRAP_LIBBOARD))
++endif
++
++
+ # Add GCC lib
+ ifdef USE_PRIVATE_LIBGCC
+ ifeq ("$(USE_PRIVATE_LIBGCC)", "yes")
+@@ -267,6 +292,9 @@
+ PLATFORM_LIBS += $(PLATFORM_LIBGCC)
+ export PLATFORM_LIBS
+
++BOOTSTRAP_PLATFORM_LIBS += $(PLATFORM_LIBGCC)
++export BOOTSTRAP_PLATFORM_LIBS
++
+ # Special flags for CPP when processing the linker script.
+ # Pass the version down so we can handle backwards compatibility
+ # on the fly.
+@@ -289,12 +317,19 @@
+ __OBJS := $(subst $(obj),,$(OBJS))
+ __LIBS := $(subst $(obj),,$(LIBS)) $(subst $(obj),,$(LIBBOARD))
+
++__BOOTSTRAP_OBJS := $(subst $(obj),,$(BOOTSTRAP_OBJS))
++__BOOTSTRAP_LIBS := $(subst $(obj),,$(BOOTSTRAP_LIBS)) $(subst $(obj),,$(BOOTSTRAP_LIBBOARD))
++
+ #########################################################################
+ #########################################################################
+
+ # Always append ALL so that arch config.mk's can add custom ones
+ ALL += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND)
+
++ifeq ($(CONFIG_BOOTSTRAP),y)
++ALL += $(obj)u-boot-bootstrap.srec $(obj)u-boot-bootstrap.bin
++endif
++
+ all: $(ALL)
+
+ $(obj)u-boot.hex: $(obj)u-boot
+@@ -306,6 +341,19 @@
+ $(obj)u-boot.bin: $(obj)u-boot
+ $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
+
++$(obj)u-boot.bin.gz: $(obj)u-boot.bin
++ gzip -c $< > $@
++
++$(obj)u-boot.bin.lzma: $(obj)u-boot.bin
++ echo lzma -e -z -c $< $@
++ lzma e $< $@
++
++$(obj)u-boot.bin.lzo: $(obj)u-boot.bin
++ lzop -9 -c $< > $@
++
++$(obj)u-boot.bin.bz2: $(obj)u-boot.bin
++ bzip2 --best -z -c $< > $@
++
+ $(obj)u-boot.ldr: $(obj)u-boot
+ $(CREATE_LDR_ENV)
+ $(LDR) -T $(CONFIG_BFIN_CPU) -c $@ $< $(LDR_FLAGS)
+@@ -335,12 +383,12 @@
+ $(obj)tools/ubsha1 $(obj)u-boot.bin
+
+ $(obj)u-boot.dis: $(obj)u-boot
+- $(OBJDUMP) -d $< > $@
++ $(OBJDUMP) -S -d $< > $@
+
+ GEN_UBOOT = \
+ UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | \
+ sed -n -e 's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
+- cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
++ cd $(LNDIR) && $(LD) --gc-sections $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
+ --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
+ -Map u-boot.map -o u-boot
+ $(obj)u-boot: depend $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds
+@@ -362,6 +410,120 @@
+ $(LIBBOARD): depend $(LIBS)
+ $(MAKE) -C $(dir $(subst $(obj),,$@))
+
++# Bootstrap targets
++
++ifeq ($(CONFIG_BOOTSTRAP),y)
++$(obj)u-boot-bootstrap.hex: $(obj)u-boot-bootstrap
++ $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@
++
++$(obj)u-boot-bootstrap.srec: $(obj)u-boot-bootstrap
++ $(OBJCOPY) -O srec $< $@
++
++$(obj)u-boot-bootstrap.bin: $(obj)u-boot-bootstrap
++ $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
++ $(BOARD_SIZE_CHECK)
++
++$(obj)u-boot-bootstrap.bin.gz: $(obj)u-boot-bootstrap.bin
++ gzip -c $< > $@
++
++$(obj)u-boot-bootstrap.bin.lzma: $(obj)u-boot-bootstrap.bin
++ lzma -e -z -c $< > $@
++
++$(obj)u-boot.bin-bootstrap.lzo: $(obj)u-boot-bootstrap.bin
++ lzop -9 -c $< > $@
++
++$(obj)u-boot.bin-bootstrap.bz2: $(obj)u-boot-bootstrap.bin
++ bzip2 --best -z -c $< > $@
++
++$(obj)u-boot-bootstrap.ldr: $(obj)u-boot-bootstrap
++ $(CREATE_LDR_ENV)
++ $(LDR) -T $(CONFIG_BFIN_CPU) -c $@ $< $(LDR_FLAGS)
++ $(BOARD_SIZE_CHECK)
++
++$(obj)u-boot-bootstrap.ldr.hex: $(obj)u-boot-bootstrap.ldr
++ $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@ -I binary
++
++$(obj)u-boot-bootstrap.ldr.srec: $(obj)u-boot-bootstrap.ldr
++ $(OBJCOPY) ${OBJCFLAGS} -O srec $< $@ -I binary
++
++$(obj)u-boot-bootstrap.img: $(obj)u-boot-bootstrap.bin
++ $(obj)tools/mkimage -A $(ARCH) -T firmware -C none \
++ -a $(CONFIG_BOOTSTRAP_BASE) -e 0 \
++ -n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \
++ sed -e 's/"[ ]*$$/ for $(BOARD) board"/') \
++ -d $< $@
++
++$(obj)u-boot-bootstrap.imx: $(obj)u-boot-bootstrap.bin
++ $(obj)tools/mkimage -n $(IMX_CONFIG) -T imximage \
++ -e $(CONFIG_BOOTSTRAP_BASE) -d $< $@
++
++$(obj)u-boot-bootstrap.kwb: $(obj)u-boot-bootstrap.bin
++ $(obj)tools/mkimage -n $(CONFIG_SYS_KWD_CONFIG) -T kwbimage \
++ -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE) -d $< $@
++
++$(obj)u-boot-bootstrap.sha1: $(obj)u-boot-bootstrap.bin
++ $(obj)tools/ubsha1 $(obj)u-boot-bootstrap.bin
++
++$(obj)u-boot-bootstrap.dis: $(obj)u-boot-bootstrap
++ echo $(OBJDUMP) -S -d $< > $@
++ $(OBJDUMP) -S -d $< > $@
++
++PAYLOAD_FILE_BASE=$(obj)u-boot.bin
++ifeq ($(CONFIG_BOOTSTRAP_GZIP),y)
++PAYLOAD_FILE_EXT:=.gz
++endif
++ifeq ($(CONFIG_BOOTSTRAP_LZMA),y)
++PAYLOAD_FILE_EXT:=.lzma
++endif
++ifeq ($(CONFIG_BOOTSTRAP_LZO),y)
++PAYLOAD_FILE_EXT:=.lzo
++endif
++ifeq ($(CONFIG_BOOTSTRAP_BZIP2),y)
++PAYLOAD_FILE_EXT:=.bz2
++endif
++
++PAYLOAD_FILE := $(PAYLOAD_FILE_BASE)$(PAYLOAD_FILE_EXT)
++
++$(obj).payload.s: $(PAYLOAD_FILE)
++ echo ".globl payload_start" > $@
++ echo ".globl payload_end" >> $@
++ echo ".globl payload_size" >> $@
++ echo ".globl payload_uncsize" >> $@
++ echo .section .payload,\"a\",@progbits >> $@
++ echo "payload_size:" >> $@
++ echo -n ".word " >> $@
++ wc -c $(PAYLOAD_FILE) | cut -f1 -d' ' >> $@
++ echo "payload_uncsize:" >> $@
++ echo -n ".word " >> $@
++ wc -c $(obj)u-boot.bin | cut -f1 -d' ' >> $@
++ echo "payload_start:" >> $@
++ echo .incbin \"$(PAYLOAD_FILE)\" >> $@
++ echo "payload_end:" >> $@
++
++
++GEN_UBOOT_BOOTSTRAP = \
++ UNDEF_SYM=`$(OBJDUMP) -x $(BOOTSTRAP_LIBBOARD) $(BOOTSTRAP_LIBS) | \
++ sed -n -e 's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
++ cd $(LNDIR) && $(LD) --gc-sections $(BOOTSTRAP_LDFLAGS) $$UNDEF_SYM $(obj).payload.o $(__BOOTSTRAP_OBJS) \
++ --start-group $(__BOOTSTRAP_LIBS) --end-group $(BOOTSTRAP_PLATFORM_LIBS) \
++ -Map u-boot-bootstrap.map -o u-boot-bootstrap
++
++$(obj)u-boot-bootstrap: depend $(SUBDIRS) $(BOOTSTRAP_OBJS) $(BOOTSTRAP_LIBS) $(BOOTSTRAP_LDSCRIPT) $(obj)u-boot-bootstrap.lds $(obj).payload.o #$(BOOTSTRAP_LIBBOARD)
++ #echo "--------$(BOOTSTRAP_LIBBOARD)"
++ #echo "$(GEN_UBOOT_BOOTSTRAP)"
++ $(GEN_UBOOT_BOOTSTRAP)
++ifeq ($(CONFIG_KALLSYMS),y)
++ smap=`$(call SYSTEM_MAP,u-boot-bootstrap) | \
++ awk '$$2 ~ /[tTwW]/ {printf $$1 $$3 "\\\\000"}'` ; \
++ $(CC) $(CFLAGS) -DSYSTEM_MAP="\"$${smap}\"" \
++ -c common/system_map.c -o $(obj)common/system_map.o
++ $(GEN_UBOOT_BOOTSTRAP) $(obj)common/system_map.o
++endif
++
++$(BOOTSTRAP_LIBBOARD): depend $(BOOTSTRAP_LIBS)
++ $(MAKE) -C $(dir $(subst $(obj),,$@)) $(notdir $@)
++endif
++
+ $(SUBDIRS): depend
+ $(MAKE) -C $@ all
+
+@@ -371,6 +533,9 @@
+ $(obj)u-boot.lds: $(LDSCRIPT)
+ $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -ansi -D__ASSEMBLY__ -P - <$^ >$@
+
++$(obj)u-boot-bootstrap.lds: $(BOOTSTRAP_LDSCRIPT)
++ $(CPP) $(CPPFLAGS) $(BOOTSTRAP_LDPPFLAGS) -ansi -D__ASSEMBLY__ -P - <$^ >$@
++
+ $(NAND_SPL): $(TIMESTAMP_FILE) $(VERSION_FILE) $(obj)include/autoconf.mk
+ $(MAKE) -C nand_spl/board/$(BOARDDIR) all
+
+@@ -3829,6 +3994,7 @@
+ $(obj)board/netstar/{eeprom,crcek,crcit,*.srec,*.bin} \
+ $(obj)board/trab/trab_fkt $(obj)board/voiceblue/eeprom \
+ $(obj)board/armltd/{integratorap,integratorcp}/u-boot.lds \
++ $(obj)u-boot-bootstrap.lds \
+ $(obj)lib_blackfin/u-boot.lds \
+ $(obj)u-boot.lds \
+ $(obj)cpu/blackfin/bootrom-asm-offsets.[chs]
+@@ -3853,6 +4019,12 @@
+ @rm -f $(obj)u-boot $(obj)u-boot.map $(obj)u-boot.hex $(ALL)
+ @rm -f $(obj)u-boot.kwb
+ @rm -f $(obj)u-boot.imx
++ @rm -f $(obj)u-boot.bin{.gz,.lzma,.lzo,.bz2}
++ @rm -f $(obj)u-boot-bootstrap $(obj)u-boot-bootstrap.map $(obj)u-boot-bootstrap.hex
++ @rm -f $(obj)u-boot-bootstrap.kwb
++ @rm -f $(obj)u-boot-bootstrap.imx
++ @rm -f $(obj)u-boot-bootstrap.bin{.gz,.lzma,.lzo,.bz2}
++ @rm -f $(obj).payload.s
+ @rm -f $(obj)tools/{env/crc32.c,inca-swap-bytes}
+ @rm -f $(obj)cpu/mpc824x/bedbug_603e.c
+ @rm -f $(obj)include/asm/proc $(obj)include/asm/arch $(obj)include/asm
+--- a/lib_mips/config.mk
++++ b/lib_mips/config.mk
+@@ -47,6 +47,6 @@
+ # On the other hand, we want PIC in the U-Boot code to relocate it from ROM
+ # to RAM. $28 is always used as gp.
+ #
+-PLATFORM_CPPFLAGS += -G 0 -mabicalls -fpic
++PLATFORM_CPPFLAGS += -G 0 -mabicalls -fpic -g
+ PLATFORM_CPPFLAGS += -msoft-float
+ PLATFORM_LDFLAGS += -G 0 -static -n -nostdlib
+--- /dev/null
++++ b/cpu/mips/reset.c
+@@ -0,0 +1,39 @@
++/*
++ * (C) Copyright 2003
++ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * 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
++ */
++
++#include <common.h>
++#include <command.h>
++#include <asm/mipsregs.h>
++#include <asm/reboot.h>
++
++void __attribute__((weak)) _machine_restart(void)
++{
++}
++
++int __attribute__((weak)) do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
++{
++ _machine_restart();
++
++ fprintf(stderr, "*** reset failed ***\n");
++ return 0;
++}
+--- /dev/null
++++ b/cpu/mips/reset_bootstrap.c
+@@ -0,0 +1,39 @@
++/*
++ * (C) Copyright 2003
++ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * 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
++ */
++
++#include <common.h>
++#include <command.h>
++#include <asm/mipsregs.h>
++#include <asm/reboot.h>
++
++void __attribute__((weak)) _machine_restart(void)
++{
++}
++
++int __attribute__((weak)) do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
++{
++ _machine_restart();
++
++ printf("*** reset failed ***\n");
++ return 0;
++}
+--- /dev/null
++++ b/cpu/mips/start_bootstrap.S
+@@ -0,0 +1,534 @@
++/*
++ * Startup Code for MIPS32 CPU-core base on start.S source
++ *
++ * Copyright (c) 2010 Industrie Dial Face S.p.A.
++ * Luigi 'Comio' Mantellini <luigi.mantellini@idf-hit.com>
++ *
++ * Copyright (c) 2003 Wolfgang Denk <wd@denx.de>
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * 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
++ */
++
++//#include <generated/generic-asm-offsets.h>
++#include <config.h>
++#include <asm/regdef.h>
++//#include <asm/mipsregs.h>
++#define CP0_INDEX $0
++#define CP0_RANDOM $1
++#define CP0_ENTRYLO0 $2
++#define CP0_ENTRYLO1 $3
++#define CP0_CONF $3
++#define CP0_CONTEXT $4
++#define CP0_PAGEMASK $5
++#define CP0_WIRED $6
++#define CP0_INFO $7
++#define CP0_BADVADDR $8
++#define CP0_COUNT $9
++#define CP0_ENTRYHI $10
++#define CP0_COMPARE $11
++#define CP0_STATUS $12
++#define CP0_CAUSE $13
++#define CP0_EPC $14
++#define CP0_PRID $15
++#define CP0_EBASE $15,1
++#define CP0_CONFIG $16
++#define CP0_LLADDR $17
++#define CP0_WATCHLO $18
++#define CP0_WATCHHI $19
++#define CP0_XCONTEXT $20
++#define CP0_FRAMEMASK $21
++#define CP0_DIAGNOSTIC $22
++#define CP0_DEBUG $23
++#define CP0_DEPC $24
++#define CP0_PERFORMANCE $25
++#define CP0_ECC $26
++#define CP0_CACHEERR $27
++#define CP0_TAGLO $28
++#define CP0_TAGHI $29
++#define CP0_ERROREPC $30
++#define CP0_DESAVE $31
++#define ST0_CU0 0x10000000
++#define CONF_CM_UNCACHED 2
++#define CONF_CM_CACHABLE_NONCOHERENT 3
++#define EBASEB_CPUNUM 0
++#define EBASEF_CPUNUM (0x3ff << EBASEB_CPUNUM)
++#define MIPS_CONF7_RPS 4 //((unsigned long)(1) << 2)
++#define CONF_CM_CACHABLE_NONCOHERENT 3
++#ifndef CONFIG_SYS_MIPS_CACHE_OPER_MODE
++#define CONFIG_SYS_MIPS_CACHE_OPER_MODE CONF_CM_CACHABLE_NONCOHERENT
++#endif
++
++ /*
++ * For the moment disable interrupts, mark the kernel mode and
++ * set ST0_KX so that the CPU does not spit fire when using
++ * 64-bit addresses.
++ */
++ .macro setup_c0_status set clr
++ .set push
++ mfc0 t0, CP0_STATUS
++ or t0, ST0_CU0 | \set | 0x1f | \clr
++ xor t0, 0x1f | \clr
++ mtc0 t0, CP0_STATUS
++ .set noreorder
++ sll zero, 3 # ehb
++ .set pop
++ .endm
++
++ .macro setup_c0_status_reset
++#ifdef CONFIG_64BIT
++ setup_c0_status ST0_KX 0
++#else
++ setup_c0_status 0 0
++#endif
++ .endm
++
++#define RVECENT(f,n) \
++ b f; nop
++#define XVECENT(f,bev) \
++ b f ; \
++ li k0,bev
++
++ .set noreorder
++
++ .globl _start
++ .text
++_start:
++ RVECENT(reset,0) /* U-boot entry point */
++ RVECENT(reset,1) /* software reboot */
++#if defined(CONFIG_INCA_IP)
++ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
++ .word 0x00000000 /* phase of the flash */
++#elif defined(CONFIG_PURPLE)
++ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
++ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
++#else
++ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
++ .word 0x00000000 /* phase of the flash */
++#endif
++ RVECENT(romReserved,3)
++ RVECENT(romReserved,4)
++ RVECENT(romReserved,5)
++ RVECENT(romReserved,6)
++ RVECENT(romReserved,7)
++ RVECENT(romReserved,8)
++ RVECENT(romReserved,9)
++ RVECENT(romReserved,10)
++ RVECENT(romReserved,11)
++ RVECENT(romReserved,12)
++ RVECENT(romReserved,13)
++ RVECENT(romReserved,14)
++ RVECENT(romReserved,15)
++ RVECENT(romReserved,16)
++ RVECENT(romReserved,17)
++ RVECENT(romReserved,18)
++ RVECENT(romReserved,19)
++ RVECENT(romReserved,20)
++ RVECENT(romReserved,21)
++ RVECENT(romReserved,22)
++ RVECENT(romReserved,23)
++ RVECENT(romReserved,24)
++ RVECENT(romReserved,25)
++ RVECENT(romReserved,26)
++ RVECENT(romReserved,27)
++ RVECENT(romReserved,28)
++ RVECENT(romReserved,29)
++ RVECENT(romReserved,30)
++ RVECENT(romReserved,31)
++ RVECENT(romReserved,32)
++ RVECENT(romReserved,33)
++ RVECENT(romReserved,34)
++ RVECENT(romReserved,35)
++ RVECENT(romReserved,36)
++ RVECENT(romReserved,37)
++ RVECENT(romReserved,38)
++ RVECENT(romReserved,39)
++ RVECENT(romReserved,40)
++ RVECENT(romReserved,41)
++ RVECENT(romReserved,42)
++ RVECENT(romReserved,43)
++ RVECENT(romReserved,44)
++ RVECENT(romReserved,45)
++ RVECENT(romReserved,46)
++ RVECENT(romReserved,47)
++ RVECENT(romReserved,48)
++ RVECENT(romReserved,49)
++ RVECENT(romReserved,50)
++ RVECENT(romReserved,51)
++ RVECENT(romReserved,52)
++ RVECENT(romReserved,53)
++ RVECENT(romReserved,54)
++ RVECENT(romReserved,55)
++ RVECENT(romReserved,56)
++ RVECENT(romReserved,57)
++ RVECENT(romReserved,58)
++ RVECENT(romReserved,59)
++ RVECENT(romReserved,60)
++ RVECENT(romReserved,61)
++ RVECENT(romReserved,62)
++ RVECENT(romReserved,63)
++ XVECENT(romExcHandle,0x200) /* bfc00200: R4000 tlbmiss vector */
++ RVECENT(romReserved,65)
++ RVECENT(romReserved,66)
++ RVECENT(romReserved,67)
++ RVECENT(romReserved,68)
++ RVECENT(romReserved,69)
++ RVECENT(romReserved,70)
++ RVECENT(romReserved,71)
++ RVECENT(romReserved,72)
++ RVECENT(romReserved,73)
++ RVECENT(romReserved,74)
++ RVECENT(romReserved,75)
++ RVECENT(romReserved,76)
++ RVECENT(romReserved,77)
++ RVECENT(romReserved,78)
++ RVECENT(romReserved,79)
++ XVECENT(romExcHandle,0x280) /* bfc00280: R4000 xtlbmiss vector */
++ RVECENT(romReserved,81)
++ RVECENT(romReserved,82)
++ RVECENT(romReserved,83)
++ RVECENT(romReserved,84)
++ RVECENT(romReserved,85)
++ RVECENT(romReserved,86)
++ RVECENT(romReserved,87)
++ RVECENT(romReserved,88)
++ RVECENT(romReserved,89)
++ RVECENT(romReserved,90)
++ RVECENT(romReserved,91)
++ RVECENT(romReserved,92)
++ RVECENT(romReserved,93)
++ RVECENT(romReserved,94)
++ RVECENT(romReserved,95)
++ XVECENT(romExcHandle,0x300) /* bfc00300: R4000 cache vector */
++ RVECENT(romReserved,97)
++ RVECENT(romReserved,98)
++ RVECENT(romReserved,99)
++ RVECENT(romReserved,100)
++ RVECENT(romReserved,101)
++ RVECENT(romReserved,102)
++ RVECENT(romReserved,103)
++ RVECENT(romReserved,104)
++ RVECENT(romReserved,105)
++ RVECENT(romReserved,106)
++ RVECENT(romReserved,107)
++ RVECENT(romReserved,108)
++ RVECENT(romReserved,109)
++ RVECENT(romReserved,110)
++ RVECENT(romReserved,111)
++ XVECENT(romExcHandle,0x380) /* bfc00380: R4000 general vector */
++ RVECENT(romReserved,113)
++ RVECENT(romReserved,114)
++ RVECENT(romReserved,115)
++ RVECENT(romReserved,116)
++ RVECENT(romReserved,116)
++ RVECENT(romReserved,118)
++ RVECENT(romReserved,119)
++ RVECENT(romReserved,120)
++ RVECENT(romReserved,121)
++ RVECENT(romReserved,122)
++ RVECENT(romReserved,123)
++ RVECENT(romReserved,124)
++ RVECENT(romReserved,125)
++ RVECENT(romReserved,126)
++ RVECENT(romReserved,127)
++
++ /* We hope there are no more reserved vectors!
++ * 128 * 8 == 1024 == 0x400
++ * so this is address R_VEC+0x400 == 0xbfc00400
++ */
++#if 1
++ XVECENT(romExcHandle,0x400); /* bfc00400: Int, CauseIV=1 */
++ RVECENT(romReserved,129);
++ RVECENT(romReserved,130);
++ RVECENT(romReserved,131);
++ RVECENT(romReserved,132);
++ RVECENT(romReserved,133);
++ RVECENT(romReserved,134);
++ RVECENT(romReserved,135);
++ RVECENT(romReserved,136);
++ RVECENT(romReserved,137);
++ RVECENT(romReserved,138);
++ RVECENT(romReserved,139);
++ RVECENT(romReserved,140);
++ RVECENT(romReserved,141);
++ RVECENT(romReserved,142);
++ RVECENT(romReserved,143);
++ XVECENT(romExcHandle,0x480); /* bfc00480: EJTAG debug exception */
++#elif defined(CONFIG_PURPLE)
++/* 0xbfc00400 */
++ .word 0xdc870000
++ .word 0xfca70000
++ .word 0x20840008
++ .word 0x20a50008
++ .word 0x20c6ffff
++ .word 0x14c0fffa
++ .word 0x00000000
++ .word 0x03e00008
++ .word 0x00000000
++ .word 0x00000000
++/* 0xbfc00428 */
++ .word 0xdc870000
++ .word 0xfca70000
++ .word 0x20840008
++ .word 0x20a50008
++ .word 0x20c6ffff
++ .word 0x14c0fffa
++ .word 0x00000000
++ .word 0x03e00008
++ .word 0x00000000
++ .word 0x00000000
++#endif /* CONFIG_PURPLE */
++ .align 4
++reset:
++#ifdef CONFIG_SYS_MIPS_MULTI_CPU
++ mfc0 k0, CP0_EBASE
++ and k0, EBASEF_CPUNUM
++ bne k0, zero, ifx_mips_handler_cpux
++ nop
++#endif
++ /* Clear watch registers.
++ */
++ mtc0 zero, CP0_WATCHLO
++ mtc0 zero, CP0_WATCHHI
++
++ /* WP(Watch Pending), SW0/1 should be cleared. */
++ mtc0 zero, CP0_CAUSE
++
++ setup_c0_status_reset
++#if defined(CONFIG_MIPS24KEC) || defined(CONFIG_MIPS34KC)
++ /* CONFIG7 register */
++ /* Erratum "RPS May Cause Incorrect Instruction Execution"
++ * for 24KEC and 34KC */
++ mfc0 k0, CP0_CONFIG, 7
++ li k1, MIPS_CONF7_RPS
++ or k0, k1
++ mtc0 k0, CP0_CONFIG, 7
++#endif
++
++ /* Init Timer */
++ mtc0 zero, CP0_COUNT
++ mtc0 zero, CP0_COMPARE
++
++ /* CONFIG0 register */
++ li t0, CONF_CM_UNCACHED
++ mtc0 t0, CP0_CONFIG
++
++ /* Initialize $gp.
++ */
++ bal 1f
++ nop
++ .word _gp
++1:
++ lw gp, 0(ra)
++
++ /* Initialize any external memory.
++ */
++ la t9, lowlevel_init
++ jalr t9
++ nop
++
++ /* Initialize caches...
++ */
++ la t9, mips_cache_reset
++ jalr t9
++ nop
++
++ /* ... and enable them.
++ */
++ li t0, CONF_CM_CACHABLE_NONCOHERENT /*CONFIG_SYS_MIPS_CACHE_OPER_MODE*/
++ mtc0 t0, CP0_CONFIG
++
++ /* Set up temporary stack.
++ */
++#ifdef CONFIG_SYS_INIT_RAM_LOCK_MIPS
++ li a0, CONFIG_SYS_INIT_SP_OFFSET
++ la t9, mips_cache_lock
++ jalr t9
++ nop
++#endif
++
++ li t0, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET
++ la sp, 0(t0)
++
++ la t9, bootstrap_board_init_f
++ jr t9
++ nop
++
++/*
++ * void relocate_code (addr_sp, gd, addr_moni)
++ *
++ * This "function" does not return, instead it continues in RAM
++ * after relocating the monitor code.
++ *
++ * a0 = addr_sp
++ * a1 = gd
++ * a2 = destination address
++ */
++ .globl relocate_code
++ .ent relocate_code
++relocate_code:
++ move sp, a0 /* Set new stack pointer */
++
++ li t0, CONFIG_BOOTSTRAP_TEXT_BASE
++ la t3, in_ram
++ lw t2, -12(t3) /* t2 <-- uboot_end_data */
++ move t1, a2
++ move s2, a2 /* s2 <-- destination address */
++
++ /*
++ * Fix $gp:
++ *
++ * New $gp = (Old $gp - CONFIG_SYS_MONITOR_BASE) + Destination Address
++ */
++ move t6, gp
++ sub gp, CONFIG_BOOTSTRAP_TEXT_BASE
++ add gp, a2 /* gp now adjusted */
++ sub s1, gp, t6 /* s1 <-- relocation offset */
++
++ /*
++ * t0 = source address
++ * t1 = target address
++ * t2 = source end address
++ */
++
++ /*
++ * Save destination address and size for later usage in flush_cache()
++ */
++ move s0, a1 /* save gd in s0 */
++ move a0, t1 /* a0 <-- destination addr */
++ sub a1, t2, t0 /* a1 <-- size */
++
++ /* On the purple board we copy the code earlier in a special way
++ * in order to solve flash problems
++ */
++#ifndef CONFIG_PURPLE
++1:
++ lw t3, 0(t0)
++ sw t3, 0(t1)
++ addu t0, 4
++ ble t0, t2, 1b
++ addu t1, 4 /* delay slot */
++#endif
++
++ /* If caches were enabled, we would have to flush them here.
++ */
++
++ /* a0 & a1 are already set up for flush_cache(start, size) */
++ la t9, flush_cache
++ jalr t9
++ nop
++
++ /* Jump to where we've relocated ourselves.
++ */
++ addi t0, s2, in_ram - _start
++ jr t0
++ nop
++
++ .word _gp
++ .word _GLOBAL_OFFSET_TABLE_
++ .word uboot_end_data
++ .word uboot_end
++ .word num_got_entries
++
++in_ram:
++ /*
++ * Now we want to update GOT.
++ *
++ * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
++ * generated by GNU ld. Skip these reserved entries from relocation.
++ */
++ lw t3, -4(t0) /* t3 <-- num_got_entries */
++ lw t4, -16(t0) /* t4 <-- _GLOBAL_OFFSET_TABLE_ */
++ lw t5, -20(t0) /* t5 <-- _gp */
++ sub t4, t5 /* compute offset*/
++ add t4, t4, gp /* t4 now holds relocated _GLOBAL_OFFSET_TABLE_ */
++ addi t4, t4, 8 /* Skipping first two entries. */
++ li t2, 2
++1:
++ lw t1, 0(t4)
++ beqz t1, 2f
++ add t1, s1
++ sw t1, 0(t4)
++2:
++ addi t2, 1
++ blt t2, t3, 1b
++ addi t4, 4 /* delay slot */
++
++ /* Clear BSS.
++ */
++ lw t1, -12(t0) /* t1 <-- uboot_end_data */
++ lw t2, -8(t0) /* t2 <-- uboot_end */
++ add t1, s1 /* adjust pointers */
++ add t2, s1
++
++ sub t1, 4
++1:
++ addi t1, 4
++ bltl t1, t2, 1b
++ sw zero, 0(t1) /* delay slot */
++
++ move a0, s0 /* a0 <-- gd */
++ la t9, bootstrap_board_init_r
++ jr t9
++ move a1, s2 /* delay slot */
++
++ .end relocate_code
++
++/*
++ * void copy_and_jump (void)
++ *
++ * This function copies/unzips the u-boot image and runs it.
++ * This "function" does not return
++ *
++*/
++ .globl copy_and_jump
++ .ent copy_and_jump
++copy_and_jump:
++
++ /* copy_uboot(CONFIG_SYS_MONITOR_BASE, payload_uncsize, payload_start, payload_size) */
++ li a0, CONFIG_SYS_MONITOR_BASE
++ la a1, payload_uncsize
++ lw a1, 0(a1)
++ la a2, payload_start
++ la a3, payload_size
++ la t9, copy_uboot
++ jalr t9
++ lw a3, 0(a3) /* delay slot */
++
++ li t9, CONFIG_SYS_MONITOR_BASE
++ jr t9
++ nop
++
++ .end copy_and_jump
++
++ /* Exception handlers.
++ */
++romReserved:
++ b romReserved
++
++romExcHandle:
++ b romExcHandle
++#ifdef CONFIG_SYS_MIPS_MULTI_CPU
++/*
++ * Stop Slave CPUs
++ */
++ifx_mips_handler_cpux:
++ wait;
++ b ifx_mips_handler_cpux;
++ nop;
++#endif
+--- a/lib_mips/Makefile
++++ b/lib_mips/Makefile
+@@ -24,6 +24,9 @@
+ include $(TOPDIR)/config.mk
+
+ LIB = $(obj)lib$(ARCH).a
++BOOTSTRAP_LIB = $(obj)lib$(ARCH)_bootstrap.a
++
++BOOTSTRAP_LIB-$(CONFIG_BOOTSTRAP) = $(BOOTSTRAP_LIB)
+
+ SOBJS-y +=
+
+@@ -35,12 +38,21 @@
+ endif
+ COBJS-y += time.o
+
+-SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += board_bootstrap.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += time.o
++
++BOOTSTRAP_OBJS := $(addprefix $(obj),$(BOOTSTRAP_SOBJS-y) $(BOOTSTRAP_COBJS-y))
++
++SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) $(BOOTSTRAP_SOBJS-y:.o=.S) $(BOOTSTRAP_COBJS-y:.o=.c)
+ OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
++all: $(obj).depend $(LIB) $(BOOTSTRAP_LIB)
+ $(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
++$(BOOTSTRAP_LIB): $(obj).depend $(BOOTSTRAP_OBJS)
++ $(AR) $(ARFLAGS) $@ $(BOOTSTRAP_OBJS)
++
+ #########################################################################
+
+ # defines $(obj).depend target
+--- /dev/null
++++ b/lib_mips/board_bootstrap.c
+@@ -0,0 +1,270 @@
++/*
++ * (C) Copyright 2010 Industrie Dial Face S.p.A.
++ * Luigi 'Comio' Mantellini, luigi.mantellini@idf-hit.com
++ *
++ * (C) Copyright 2003
++ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * 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
++ */
++
++#include <common.h>
++#include <command.h>
++#include <malloc.h>
++#include <stdio_dev.h>
++
++DECLARE_GLOBAL_DATA_PTR;
++
++extern int timer_init(void);
++
++extern int incaip_set_cpuclk(void);
++
++extern ulong uboot_end_data;
++extern ulong uboot_end;
++
++#ifdef CONFIG_BOOTSTRAP_SERIAL
++static char *failed = "*** failed ***\n";
++#endif
++/*
++ * mips_io_port_base is the begin of the address space to which x86 style
++ * I/O ports are mapped.
++ */
++unsigned long mips_io_port_base = -1;
++
++int __board_early_init_f(void)
++{
++ /*
++ * Nothing to do in this dummy implementation
++ */
++ return 0;
++}
++
++int board_early_init_f(void) __attribute__((weak, alias("__board_early_init_f")));
++int bootstrap_board_early_init_f(void) __attribute__((weak, alias("board_early_init_f")));
++
++static int bootstrap_init_func_ram (void)
++{
++ if ((gd->ram_size = bootstrap_initdram (0)) > 0) {
++ return (0);
++ }
++#ifdef CONFIG_BOOTSTRAP_SERIAL
++ puts (failed);
++#endif
++ return (1);
++}
++
++static int bootstrap_display_banner(void)
++{
++#ifdef CONFIG_BOOTSTRAP_SERIAL
++ puts ("bootstrap...");
++#endif
++ return (0);
++}
++
++static int bootstrap_init_baudrate (void)
++{
++#if defined(CONFIG_BOOTSTRAP_BAUDRATE)
++ gd->baudrate = CONFIG_BOOTSTRAP_BAUDRATE;
++#else
++ gd->baudrate = CONFIG_BAUDRATE;
++#endif
++ return 0;
++}
++
++/*
++ * Breath some life into the board...
++ *
++ * The first part of initialization is running from Flash memory;
++ * its main purpose is to initialize the RAM so that we
++ * can relocate the monitor code to RAM.
++ */
++
++/*
++ * All attempts to come up with a "common" initialization sequence
++ * that works for all boards and architectures failed: some of the
++ * requirements are just _too_ different. To get rid of the resulting
++ * mess of board dependend #ifdef'ed code we now make the whole
++ * initialization sequence configurable to the user.
++ *
++ * The requirements for any new initalization function is simple: it
++ * receives a pointer to the "global data" structure as it's only
++ * argument, and returns an integer return code, where 0 means
++ * "continue" and != 0 means "fatal error, hang the system".
++ */
++typedef int (init_fnc_t) (void);
++
++static init_fnc_t *init_sequence[] = {
++ bootstrap_board_early_init_f,
++ timer_init,
++ bootstrap_init_baudrate,/* initialze baudrate settings */
++#ifdef CONFIG_BOOTSTRAP_SERIAL
++ serial_init, /* serial communications setup */
++#endif
++ bootstrap_display_banner, /* say that we are here */
++ bootstrap_checkboard,
++ bootstrap_init_func_ram,
++ NULL,
++};
++
++
++void bootstrap_board_init_f(ulong bootflag)
++{
++ gd_t gd_data, *id;
++ bd_t *bd;
++ init_fnc_t **init_fnc_ptr;
++ ulong addr, addr_sp, len = (ulong)&uboot_end - CONFIG_BOOTSTRAP_TEXT_BASE;
++ ulong *s;
++
++ /* Pointer is writable since we allocated a register for it.
++ */
++ gd = &gd_data;
++ /* compiler optimization barrier needed for GCC >= 3.4 */
++ __asm__ __volatile__("": : :"memory");
++
++ memset ((void *)gd, 0, sizeof (gd_t));
++
++ for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
++ if ((*init_fnc_ptr)() != 0) {
++ bootstrap_hang ();
++ }
++ }
++
++ /*
++ * Now that we have DRAM mapped and working, we can
++ * relocate the code and continue running from DRAM.
++ */
++ addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
++
++ /* We can reserve some RAM "on top" here.
++ */
++
++ /* round down to next 4 kB limit.
++ */
++ addr &= ~(4096 - 1);
++ debug ("Top of RAM usable for U-Boot at: %08lx\n", addr);
++
++ /* Reserve memory for U-Boot code, data & bss
++ * round down to next 16 kB limit
++ */
++ addr -= len;
++ addr &= ~(16 * 1024 - 1);
++
++ debug ("Reserving %ldk for U-Boot at: %08lx\n", len >> 10, addr);
++
++ /* Reserve memory for malloc() arena.
++ */
++ addr_sp = addr - CONFIG_SYS_MALLOC_LEN;
++ debug ("Reserving %dk for malloc() at: %08lx\n",
++ CONFIG_SYS_MALLOC_LEN >> 10, addr_sp);
++
++ /*
++ * (permanently) allocate a Board Info struct
++ * and a permanent copy of the "global" data
++ */
++ addr_sp -= sizeof(bd_t);
++ bd = (bd_t *)addr_sp;
++ gd->bd = bd;
++ debug ("Reserving %zu Bytes for Board Info at: %08lx\n",
++ sizeof(bd_t), addr_sp);
++
++ addr_sp -= sizeof(gd_t);
++ id = (gd_t *)addr_sp;
++ debug ("Reserving %zu Bytes for Global Data at: %08lx\n",
++ sizeof (gd_t), addr_sp);
++
++ /* Reserve memory for boot params.
++ */
++ addr_sp -= CONFIG_SYS_BOOTPARAMS_LEN;
++ bd->bi_boot_params = addr_sp;
++ debug ("Reserving %dk for boot params() at: %08lx\n",
++ CONFIG_SYS_BOOTPARAMS_LEN >> 10, addr_sp);
++
++ /*
++ * Finally, we set up a new (bigger) stack.
++ *
++ * Leave some safety gap for SP, force alignment on 16 byte boundary
++ * Clear initial stack frame
++ */
++ addr_sp -= 16;
++ addr_sp &= ~0xF;
++ s = (ulong *)addr_sp;
++ *s-- = 0;
++ *s-- = 0;
++ addr_sp = (ulong)s;
++ debug ("Stack Pointer at: %08lx\n", addr_sp);
++
++ /*
++ * Save local variables to board info struct
++ */
++ bd->bi_memstart = CONFIG_SYS_SDRAM_BASE; /* start of DRAM memory */
++ bd->bi_memsize = gd->ram_size; /* size of DRAM memory in bytes */
++ bd->bi_baudrate = gd->baudrate; /* Console Baudrate */
++
++ memcpy (id, (void *)gd, sizeof (gd_t));
++
++ /* On the purple board we copy the code in a special way
++ * in order to solve flash problems
++ */
++ relocate_code (addr_sp, id, addr);
++
++ /* NOTREACHED - relocate_code() does not return */
++}
++/************************************************************************
++ *
++ * This is the next part if the initialization sequence: we are now
++ * running from RAM and have a "normal" C environment, i. e. global
++ * data can be written, BSS has been cleared, the stack size in not
++ * that critical any more, etc.
++ *
++ ************************************************************************
++ */
++
++void bootstrap_board_init_r (gd_t *id, ulong dest_addr)
++{
++ extern void malloc_bin_reloc (void);
++ extern void copy_and_jump(void);
++
++ bd_t *bd;
++
++ gd = id;
++ gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
++
++ debug ("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
++
++ gd->reloc_off = dest_addr - CONFIG_BOOTSTRAP_TEXT_BASE;
++
++ bd = gd->bd;
++
++ /* The Malloc area is immediately below the monitor copy in DRAM */
++ mem_malloc_init(CONFIG_BOOTSTRAP_BASE + gd->reloc_off -
++ CONFIG_SYS_MALLOC_LEN, CONFIG_SYS_MALLOC_LEN);
++ malloc_bin_reloc();
++
++ copy_and_jump();
++
++ /* NOTREACHED - no way out of command loop except booting */
++}
++
++void bootstrap_hang (void)
++{
++#ifdef CONFIG_BOOTSTRAP_SERIAL
++ puts ("### ERROR ### Please RESET the board ###\n");
++#endif
++ for (;;);
++}
+--- a/common/Makefile
++++ b/common/Makefile
+@@ -24,6 +24,9 @@
+ include $(TOPDIR)/config.mk
+
+ LIB = $(obj)libcommon.a
++BOOTSTRAP_LIB = $(obj)libcommon_bootstrap.a
++
++BOOTSTRAP_LIB-$(CONFIG_BOOTSTRAP) = $(BOOTSTRAP_LIB)
+
+ AOBJS =
+
+@@ -168,18 +171,27 @@
+ COBJS-$(CONFIG_UPDATE_TFTP) += update.o
+ COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
+
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += dlmalloc.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_SERIAL) += console_bootstrap.o
++
++BOOTSTRAP_COBJS := $(sort $(BOOTSTRAP_COBJS-y))
++BOOTSTRAP_OBJS := $(addprefix $(obj),$(BOOTSTRAP_COBJS))
++
+
+ COBJS := $(sort $(COBJS-y))
+-SRCS := $(AOBJS:.o=.S) $(COBJS:.o=.c)
++SRCS := $(AOBJS:.o=.S) $(COBJS:.o=.c) $(BOOTSTRAP_COBJS:.o=.c)
+ OBJS := $(addprefix $(obj),$(AOBJS) $(COBJS))
+
+ CPPFLAGS += -I..
+
+-all: $(LIB) $(AOBJS)
++all: $(LIB) $(BOOTSTRAP_LIB-y) $(AOBJS)
+
+ $(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
++$(BOOTSTRAP_LIB): $(obj).depend $(BOOTSTRAP_OBJS)
++ $(AR) $(ARFLAGS) $@ $(BOOTSTRAP_OBJS)
++
+ $(obj)env_embedded.o: $(src)env_embedded.c $(obj)../tools/envcrc
+ $(CC) $(AFLAGS) -Wa,--no-warn \
+ -DENV_CRC=$(shell $(obj)../tools/envcrc) \
+--- /dev/null
++++ b/common/console_bootstrap.c
+@@ -0,0 +1,81 @@
++/*
++ * (C) Copyright 2000
++ * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * 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
++ */
++
++#include <common.h>
++#include <stdarg.h>
++#include <malloc.h>
++
++/** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/
++
++int getc(void)
++{
++ /* Send directly to the handler */
++ return serial_getc();
++}
++
++int tstc(void)
++{
++ /* Send directly to the handler */
++ return serial_tstc();
++}
++
++void putc(const char c)
++{
++ /* Send directly to the handler */
++ serial_putc(c);
++}
++
++void puts(const char *s)
++{
++ serial_puts(s);
++}
++
++void printf(const char *fmt, ...)
++{
++ va_list args;
++ char printbuffer[CONFIG_SYS_PBSIZE];
++
++ va_start(args, fmt);
++
++ /* For this to work, printbuffer must be larger than
++ * anything we ever want to print.
++ */
++ vsprintf(printbuffer, fmt, args);
++ va_end(args);
++
++ /* Print the string */
++ puts(printbuffer);
++}
++
++void vprintf(const char *fmt, va_list args)
++{
++ char printbuffer[CONFIG_SYS_PBSIZE];
++
++ /* For this to work, printbuffer must be larger than
++ * anything we ever want to print.
++ */
++ vsprintf(printbuffer, fmt, args);
++
++ /* Print the string */
++ puts(printbuffer);
++}
+--- a/config.mk
++++ b/config.mk
+@@ -136,7 +136,7 @@
+ ARFLAGS = crv
+ endif
+ RELFLAGS= $(PLATFORM_RELFLAGS)
+-DBGFLAGS= -g # -DDEBUG
++DBGFLAGS= -g
+ OPTFLAGS= -Os #-fomit-frame-pointer
+ ifndef LDSCRIPT
+ #LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds.debug
+@@ -146,6 +146,11 @@
+ LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds
+ endif
+ endif
++ifeq ($(CONFIG_BOOTSTRAP),y)
++ifndef BOOTSTRAP_LDSCRIPT
++BOOTSTRAP_LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-bootstrap.lds
++endif
++endif
+ OBJCFLAGS += --gap-fill=0xff
+
+ gccincdir := $(shell $(CC) -print-file-name=include)
+@@ -156,6 +161,10 @@
+ CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE)
+ endif
+
++ifneq ($(CONFIG_BOOTSTRAP_TEXT_BASE),)
++CPPFLAGS += -DCONFIG_BOOTSTRAP_TEXT_BASE=$(CONFIG_BOOTSTRAP_TEXT_BASE)
++endif
++
+ ifneq ($(RESET_VECTOR_ADDRESS),)
+ CPPFLAGS += -DRESET_VECTOR_ADDRESS=$(RESET_VECTOR_ADDRESS)
+ endif
+@@ -176,6 +185,7 @@
+ endif
+
+ CFLAGS += $(call cc-option,-fno-stack-protector)
++CFLAGS += $(call cc-option,-ffunction-sections)
+
+ # avoid trigraph warnings while parsing pci.h (produced by NIOS gcc-2.9)
+ # this option have to be placed behind -Wall -- that's why it is here
+@@ -203,6 +213,13 @@
+ LDFLAGS += -Ttext $(TEXT_BASE)
+ endif
+
++ifeq ($(CONFIG_BOOTSTRAP),y)
++BOOTSTRAP_LDFLAGS += -Bstatic -T $(obj)u-boot-bootstrap.lds $(PLATFORM_LDFLAGS)
++ifneq ($(CONFIG_BOOTSTRAP_TEXT_BASE),)
++BOOTSTRAP_LDFLAGS += -Ttext $(CONFIG_BOOTSTRAP_TEXT_BASE)
++endif
++endif
++
+ # Location of a usable BFD library, where we define "usable" as
+ # "built for ${HOST}, supports ${TARGET}". Sensible values are
+ # - When cross-compiling: the root of the cross-environment
+--- a/include/common.h
++++ b/include/common.h
+@@ -722,6 +722,27 @@
+ int cpu_release(int nr, int argc, char *argv[]);
+ #endif
+
++/* Bootstrap specific code */
++#ifdef CONFIG_BOOTSTRAP
++void bootstrap_hang(void) __attribute__ ((noreturn));
++void bootstrap_board_init_f(ulong) __attribute__ ((noreturn));
++void bootstrap_board_init_r(gd_t *, ulong) __attribute__ ((noreturn));
++int bootstrap_checkboard(void);
++
++int bootstrap_serial_init(void);
++void bootstrap_serial_exit(void);
++void bootstrap_serial_setbrg(void);
++void bootstrap_serial_putc(const char);
++void bootstrap_serial_putc_raw(const char);
++void bootstrap_serial_puts(const char *);
++int bootstrap_serial_getc(void);
++int bootstrap_serial_tstc(void);
++
++phys_size_t bootstrap_initdram (int);
++
++int copy_uboot(void *dst, size_t unc_size, void *src, size_t size);
++#endif
++
+ #endif /* __ASSEMBLY__ */
+
+ /* Put only stuff here that the assembler can digest */
+--- a/lib_generic/Makefile
++++ b/lib_generic/Makefile
+@@ -24,6 +24,9 @@
+ include $(TOPDIR)/config.mk
+
+ LIB = $(obj)libgeneric.a
++BOOTSTRAP_LIB = $(obj)libgeneric_bootstrap.a
++
++BOOTSTRAP_LIB-$(CONFIG_BOOTSTRAP) = $(BOOTSTRAP_LIB)
+
+ COBJS-$(CONFIG_ADDR_MAP) += addr_map.o
+ COBJS-$(CONFIG_BZIP2) += bzlib.o
+@@ -50,14 +53,37 @@
+ COBJS-y += vsprintf.o
+ COBJS-$(CONFIG_ZLIB) += zlib.o
+ COBJS-$(CONFIG_RBTREE) += rbtree.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += string.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += vsprintf.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += div64.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += ctype.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += time.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += bootstrap.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_GZIP) += zlib.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_GZIP) += gunzip.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_GZIP) += crc32.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_BZIP2) += bzlib.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_BZIP2) += bzlib_crctable.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_BZIP2) += bzlib_decompress.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_BZIP2) += bzlib_randtable.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_BZIP2) += bzlib_huffman.o
++
++BOOTSTRAP_COBJS := $(BOOTSTRAP_COBJS-y)
++BOOTSTRAP_OBJS := $(addprefix $(obj),$(BOOTSTRAP_COBJS))
+
+ COBJS := $(COBJS-y)
+-SRCS := $(COBJS:.o=.c)
++SRCS := $(COBJS:.o=.c) $(BOOTSTRAP_COBJS:.o=.c)
+ OBJS := $(addprefix $(obj),$(COBJS))
+
++all: $(obj).depend $(LIB) $(BOOTSTRAP_LIB-y)
++
+ $(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
++$(BOOTSTRAP_LIB): $(obj).depend $(BOOTSTRAP_OBJS)
++ $(AR) $(ARFLAGS) $@ $(BOOTSTRAP_OBJS)
++
++
+ #########################################################################
+
+ # defines $(obj).depend target
+--- /dev/null
++++ b/lib_generic/bootstrap.c
+@@ -0,0 +1,95 @@
++/*
++ * (C) Copyright 2010 Industrie Dial Face S.p.A.
++ * Luigi 'Comio' Mantellini, luigi.mantellini@idf-hit.com
++ *
++ * (C) Copyright 2003
++ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * 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
++ */
++
++#include <common.h>
++#include <command.h>
++#include <stdio_dev.h>
++
++#ifdef CONFIG_BOOTSTRAP_LZMA
++#include <lzma/LzmaTypes.h>
++#include <lzma/LzmaDec.h>
++#include <lzma/LzmaTools.h>
++#endif /* CONFIG_BOOTSTRAP_LZMA */
++
++#ifdef CONFIG_BOOTSTRAP_LZO
++#include <linux/lzo.h>
++#endif /* CONFIG_BOOTSTRAP_LZO */
++
++#ifdef CONFIG_BOOTSTRAP_BZIP2
++#include <bzlib.h>
++#endif
++
++DECLARE_GLOBAL_DATA_PTR;
++
++#if defined(CONFIG_BOOTSTRAP_SERIAL)
++static const char *algo =
++#if defined(CONFIG_BOOTSTRAP_GZIP)
++ "gzip";
++#elif defined(CONFIG_BOOTSTRAP_LZMA)
++ "lzma";
++#elif defined(CONFIG_BOOTSTRAP_LZO)
++ "lzo";
++#elif defined(CONFIG_BOOTSTRAP_BZIP2)
++ "bzip2";
++#else
++ "flat";
++#endif
++#endif
++
++int copy_uboot(void *dst, size_t unc_size, void *src, size_t size)
++{
++ int ret;
++ debug("copy from %p (%d) to %p (%d)\n", src, size, dst, unc_size);
++#if defined(CONFIG_BOOTSTRAP_SERIAL)
++ printf("Uncompressing payload (%s)...", algo);
++#endif
++#if defined(CONFIG_BOOTSTRAP_GZIP)
++ ret = gunzip(dst, unc_size, src, &size);
++#elif defined(CONFIG_BOOTSTRAP_LZMA)
++ SizeT outsize = unc_size;
++ ret = lzmaBuffToBuffDecompress(dst, &outsize, src, size);
++#elif defined(CONFIG_BOOTSTRAP_LZO)
++ uint unc_len = unc_size;
++ ret = lzop_decompress(src, size, dst, &unc_len);
++#elif defined(CONFIG_BOOTSTRAP_BZIP2)
++ uint unc_len = unc_size;
++ ret = BZ2_bzBuffToBuffDecompress ((char*)dst, &unc_len, (char *)src, size, CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
++#else
++ memcpy(dst, src, size);
++ ret = 0;
++#endif
++ if (ret) {
++#if defined(CONFIG_BOOTSTRAP_SERIAL)
++ printf("failed with error %d.\n", ret);
++#endif
++ bootstrap_hang();
++ } else {
++#if defined(CONFIG_BOOTSTRAP_SERIAL)
++ puts("done.\n");
++#endif
++ }
++ return ret;
++}
+--- a/lib_generic/lzma/Makefile
++++ b/lib_generic/lzma/Makefile
+@@ -32,7 +32,9 @@
+
+ CFLAGS += -D_LZMA_PROB32
+
+-COBJS-$(CONFIG_LZMA) += LzmaDec.o LzmaTools.o
++COBJS-$(CONFIG_LZMA)$(CONFIG_BOOTSTRAP_LZMA) += LzmaDec.o LzmaTools.o
++
++COBJS-y += $(COBJS-yy)
+
+ COBJS = $(COBJS-y)
+ SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+--- a/lib_generic/lzo/Makefile
++++ b/lib_generic/lzo/Makefile
+@@ -27,7 +27,9 @@
+
+ SOBJS =
+
+-COBJS-$(CONFIG_LZO) += lzo1x_decompress.o
++COBJS-$(CONFIG_LZO)$(CONFIG_BOOTSTRAP_LZO) += lzo1x_decompress.o
++
++COBJS-y += $(OBJS-yy)
+
+ COBJS = $(COBJS-y)
+ SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+--- a/cpu/mips/Makefile
++++ b/cpu/mips/Makefile
+@@ -24,25 +24,46 @@
+ include $(TOPDIR)/config.mk
+
+ LIB = $(obj)lib$(CPU).a
++BOOTSTRAP_LIB = $(obj)lib$(CPU)_bootstrap.a
++
++BOOTSTRAP_LIB-$(CONFIG_BOOTSTRAP) = $(BOOTSTRAP_LIB)
+
+ START = start.o
+ SOBJS-y = cache.o
+-COBJS-y = cpu.o interrupts.o
++COBJS-y = cpu.o reset.o interrupts.o
+
+ SOBJS-$(CONFIG_INCA_IP) += incaip_wdt.o
+ COBJS-$(CONFIG_INCA_IP) += asc_serial.o incaip_clock.o
++#COBJS-$(CONFIG_IFX_ASC) += ifx_asc.o
+ COBJS-$(CONFIG_PURPLE) += asc_serial.o
+ COBJS-$(CONFIG_SOC_AU1X00) += au1x00_eth.o au1x00_serial.o au1x00_usb_ohci.o
+
+-SRCS := $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
++#BOOTSTRAP_START = start_bootstrap.o
++BOOTSTRAP_START-$(CONFIG_BOOTSTRAP) += start_bootstrap.o #$(BOOTSTRAP_START)
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP) += cpu.o interrupts.o reset_bootstrap.o
++BOOTSTRAP_SOBJS-$(CONFIG_BOOTSTRAP) += cache.o
++BOOTSTRAP_COBJS-$(CONFIG_DANUBE) += danube-clock.o
++BOOTSTRAP_COBJS-$(CONFIG_AR9) += ar9-clock.o
++BOOTSTRAP_COBJS-$(CONFIG_BOOTSTRAP_SERIAL) += ifx_asc.o
++
++BOOTSTRAP_OBJS := $(addprefix $(obj),$(BOOTSTRAP_SOBJS-y) $(BOOTSTRAP_COBJS-y))
++BOOTSTRAP_START := $(addprefix $(obj),$(BOOTSTRAP_START-y))
++
++SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) $(BOOTSTRAP_START-y:.o=.S) $(BOOTSTRAP_SOBJS-y:.o=.S) $(BOOTSTRAP_COBJS-y:.o=.c)
+ OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+ START := $(addprefix $(obj),$(START))
+
+-all: $(obj).depend $(START) $(LIB)
++all: $(obj).depend $(START) $(LIB) $(BOOTSTRAP_START-y) $(BOOTSTRAP_LIB-y)
+
+-$(LIB): $(OBJS)
++$(LIB): $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
++#$(BOOTSTRAP_START): $(obj).depend
++
++$(BOOTSTRAP_LIB): $(BOOTSTRAP_OBJS)
++ $(AR) $(ARFLAGS) $@ $(BOOTSTRAP_OBJS)
++
++
+ #########################################################################
+
+ # defines $(obj).depend target
diff --git a/package/uboot-lantiq/patches/500-gigasx.patch b/package/uboot-lantiq/patches/500-gigasx.patch
new file mode 100644
index 000000000..fe384ef78
--- /dev/null
+++ b/package/uboot-lantiq/patches/500-gigasx.patch
@@ -0,0 +1,35 @@
+--- a/Makefile
++++ b/Makefile
+@@ -3613,6 +3613,32 @@
+ $(eval $(call arcadyan, arv752DPW%config))
+ $(eval $(call arcadyan, arv752DPW22%config))
+
++gigaSX76X%config : unconfig
++ @mkdir -p $(obj)include
++ @mkdir -p $(obj)board/infineon/easy50712
++ @[ -z "$(findstring ramboot,$@)" ] || \
++ { echo "TEXT_BASE = 0xA0400000" >$(obj)board/infineon/easy50712/config.tmp ; \
++ echo "#define CONFIG_SYS_RAMBOOT" >>$(obj)include/config.h ; \
++ $(XECHO) "... with ramboot configuration" ; \
++ }
++ @if [ "$(findstring _DDR,$@)" -a -z "$(findstring ramboot,$@)" ] ; then \
++ echo "#define CONFIG_USE_DDR_RAM" >>$(obj)include/config.h ; \
++ echo "#define CONFIG_BOOTSTRAP" >>$(obj)include/config.h ; \
++ DDR=$(subst DDR,,$(filter DDR%,$(subst _, ,$@))); \
++ case "$${DDR}" in \
++ 111M|166M|e111M|e166M|promos400|samsung166|psc166) \
++ $(XECHO) "... with DDR RAM config $${DDR}" ; \
++ echo "#define CONFIG_USE_DDR_RAM_CFG_$${DDR}" >>$(obj)include/config.h ;; \
++ *) $(XECHO) "... DDR RAM config \\\"$${DDR}\\\" unknown, use default"; \
++ esac; \
++ fi
++ echo "#define CONFIG_SWITCH_PORT1 1" >>$(obj)include/config.h
++ echo "#define CONFIG_SWITCH_PIN 3" >>$(obj)include/config.h
++ echo "#define CONFIG_BUTTON_PORT0 1" >>$(obj)include/config.h
++ echo "#define CONFIG_BUTTON_PIN 14" >>$(obj)include/config.h
++ echo "#define CONFIG_BUTTON_LEVEL 1" >>$(obj)include/config.h
++ @$(MKCONFIG) -a easy50712 mips mips easy50712 infineon danube
++
+ easy50712%config : unconfig
+ @mkdir -p $(obj)include
+ @mkdir -p $(obj)board/infineon/easy50712
diff --git a/package/uboot-omap35xx/Makefile b/package/uboot-omap35xx/Makefile
new file mode 100644
index 000000000..928acc7d4
--- /dev/null
+++ b/package/uboot-omap35xx/Makefile
@@ -0,0 +1,89 @@
+#
+# Copyright (C) 2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=u-boot
+PKG_VERSION:=2010.12
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=ftp://ftp.denx.de/pub/u-boot
+PKG_MD5SUM:=
+PKG_TARGETS:=bin
+
+include $(INCLUDE_DIR)/package.mk
+
+define uboot/Default
+ TITLE:=
+ CONFIG:=
+ IMAGE:=
+endef
+
+define uboot/omap3_overo
+ TITLE:=U-boot for the gumstix board
+endef
+
+UBOOTS:=omap3_overo
+
+define Package/uboot/template
+define Package/uboot-omap35xx-$(1)
+ SECTION:=boot
+ CATEGORY:=Boot Loaders
+ DEPENDS:=@TARGET_omap35xx
+ TITLE:=$(2)
+ URL:=http://www.denx.de/wiki/U-Boot
+ VARIANT:=$(1)
+endef
+endef
+
+define BuildUbootPackage
+ $(eval $(uboot/Default))
+ $(eval $(uboot/$(1)))
+ $(call Package/uboot/template,$(1),$(TITLE))
+endef
+
+
+ifdef BUILD_VARIANT
+$(eval $(call uboot/$(BUILD_VARIANT)))
+UBOOT_CONFIG:=$(if $(CONFIG),$(CONFIG),$(BUILD_VARIANT))
+UBOOT_IMAGE:=$(if $(IMAGE),$(IMAGE),openwrt-$(BOARD)-$(BUILD_VARIANT)-u-boot.bin)
+endif
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ $(CP) ./files/* $(PKG_BUILD_DIR)
+ find $(PKG_BUILD_DIR) -name .svn | $(XARGS) rm -rf
+endef
+
+define Build/Configure
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(UBOOT_CONFIG)_config
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CROSS_COMPILE=$(TARGET_CROSS)
+endef
+
+define Package/uboot/install/template
+define Package/uboot-omap35xx-$(1)/install
+ $(INSTALL_DIR) $$(1)
+ $(CP) $(PKG_BUILD_DIR)/u-boot.bin $(BIN_DIR)/$(2)
+endef
+endef
+
+$(foreach u,$(UBOOTS), \
+ $(eval $(call Package/uboot/install/template,$(u),openwrt-$(BOARD)-$(u)-u-boot.bin)) \
+)
+
+$(foreach u,$(UBOOTS), \
+ $(eval $(call BuildUbootPackage,$(u))) \
+ $(eval $(call BuildPackage,uboot-omap35xx-$(u))) \
+)
diff --git a/package/uboot-omap35xx/files/include/configs/omap3_overo.h b/package/uboot-omap35xx/files/include/configs/omap3_overo.h
new file mode 100644
index 000000000..e1c930df5
--- /dev/null
+++ b/package/uboot-omap35xx/files/include/configs/omap3_overo.h
@@ -0,0 +1,316 @@
+/*
+ * Configuration settings for the Gumstix Overo board.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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 __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ */
+#define CONFIG_ARMV7 1 /* This is an ARM V7 CPU core */
+#define CONFIG_OMAP 1 /* in a TI OMAP core */
+#define CONFIG_OMAP34XX 1 /* which is a 34XX */
+#define CONFIG_OMAP3430 1 /* which is in a 3430 */
+#define CONFIG_OMAP3_OVERO 1 /* working with overo */
+
+#define CONFIG_SDRC /* The chip has SDRC controller */
+
+#include <asm/arch/cpu.h> /* get chip and board defs */
+#include <asm/arch/omap3.h>
+
+/*
+ * Display CPU and Board information
+ */
+#define CONFIG_DISPLAY_CPUINFO 1
+#define CONFIG_DISPLAY_BOARDINFO 1
+
+/* Clock Defines */
+#define V_OSCK 26000000 /* Clock output from T2 */
+#define V_SCLK (V_OSCK >> 1)
+
+#undef CONFIG_USE_IRQ /* no support for IRQs */
+#define CONFIG_MISC_INIT_R
+
+#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */
+#define CONFIG_SETUP_MEMORY_TAGS 1
+#define CONFIG_INITRD_TAG 1
+#define CONFIG_REVISION_TAG 1
+
+/*
+ * Size of malloc() pool
+ */
+#define CONFIG_ENV_SIZE (128 << 10) /* 128 KiB */
+ /* Sector */
+#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + (128 << 10))
+ /* initial data */
+
+/*
+ * Hardware drivers
+ */
+
+/*
+ * NS16550 Configuration
+ */
+#define V_NS16550_CLK 48000000 /* 48MHz (APLL96/2) */
+
+#define CONFIG_SYS_NS16550
+#define CONFIG_SYS_NS16550_SERIAL
+#define CONFIG_SYS_NS16550_REG_SIZE (-4)
+#define CONFIG_SYS_NS16550_CLK V_NS16550_CLK
+
+/*
+ * select serial console configuration
+ */
+#define CONFIG_CONS_INDEX 3
+#define CONFIG_SYS_NS16550_COM3 OMAP34XX_UART3
+#define CONFIG_SERIAL3 3
+
+/* allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+#define CONFIG_BAUDRATE 115200
+#define CONFIG_SYS_BAUDRATE_TABLE {4800, 9600, 19200, 38400, 57600, \
+ 115200}
+#define CONFIG_GENERIC_MMC 1
+#define CONFIG_MMC 1
+#define CONFIG_OMAP_HSMMC 1
+#define CONFIG_DOS_PARTITION 1
+
+/* DDR - I use Micron DDR */
+#define CONFIG_OMAP3_MICRON_DDR 1
+
+/* commands to include */
+#include <config_cmd_default.h>
+
+#define CONFIG_CMD_CACHE
+#define CONFIG_CMD_EXT2 /* EXT2 Support */
+#define CONFIG_CMD_FAT /* FAT support */
+#define CONFIG_CMD_JFFS2 /* JFFS2 Support */
+
+#define CONFIG_CMD_I2C /* I2C serial bus support */
+#define CONFIG_CMD_MMC /* MMC support */
+#define CONFIG_CMD_NAND /* NAND support */
+
+#undef CONFIG_CMD_FLASH /* flinfo, erase, protect */
+#undef CONFIG_CMD_FPGA /* FPGA configuration Support */
+#undef CONFIG_CMD_IMI /* iminfo */
+#undef CONFIG_CMD_IMLS /* List all found images */
+#undef CONFIG_CMD_NFS /* NFS support */
+#define CONFIG_CMD_NET /* bootp, tftpboot, rarpboot */
+
+#define CONFIG_SYS_NO_FLASH
+#define CONFIG_HARD_I2C 1
+#define CONFIG_SYS_I2C_SPEED 100000
+#define CONFIG_SYS_I2C_SLAVE 1
+#define CONFIG_SYS_I2C_BUS 0
+#define CONFIG_SYS_I2C_BUS_SELECT 1
+#define CONFIG_I2C_MULTI_BUS 1
+#define CONFIG_DRIVER_OMAP34XX_I2C 1
+
+/*
+ * TWL4030
+ */
+#define CONFIG_TWL4030_POWER 1
+#define CONFIG_TWL4030_LED 1
+
+/*
+ * Board NAND Info.
+ */
+#define CONFIG_SYS_NAND_QUIET_TEST 1
+#define CONFIG_NAND_OMAP_GPMC
+#define CONFIG_SYS_NAND_ADDR NAND_BASE /* physical address */
+ /* to access nand */
+#define CONFIG_SYS_NAND_BASE NAND_BASE /* physical address */
+ /* to access nand */
+ /* at CS0 */
+#define GPMC_NAND_ECC_LP_x16_LAYOUT 1
+
+#define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND */
+ /* devices */
+#define CONFIG_JFFS2_NAND
+/* nand device jffs2 lives on */
+#define CONFIG_JFFS2_DEV "nand0"
+/* start of jffs2 partition */
+#define CONFIG_JFFS2_PART_OFFSET 0x680000
+#define CONFIG_JFFS2_PART_SIZE 0xf980000 /* size of jffs2 */
+ /* partition */
+
+/* Environment information */
+#define CONFIG_BOOTDELAY 5
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "loadaddr=0x82000000\0" \
+ "console=ttyO2,115200n8\0" \
+ "mpurate=500\0" \
+ "vram=12M\0" \
+ "dvimode=1024x768MR-16@60\0" \
+ "defaultdisplay=dvi\0" \
+ "mmcdev=0\0" \
+ "mmcroot=/dev/mmcblk0p2 rw\0" \
+ "mmcrootfstype=ext3 rootwait\0" \
+ "nandroot='ubi0:rootfs ubi.mtd=5 ubi.mtd=6 ubi.mtd=7'\0" \
+ "nandrootfstype=ubifs\0" \
+ "mmcargs=setenv bootargs console=${console} " \
+ "mpurate=${mpurate} " \
+ "vram=${vram} " \
+ "omapfb.mode=dvi:${dvimode} " \
+ "omapfb.debug=y " \
+ "omapdss.def_disp=${defaultdisplay} " \
+ "root=${mmcroot} " \
+ "rootfstype=${mmcrootfstype}\0" \
+ "nandargs=setenv bootargs console=${console} " \
+ "mpurate=${mpurate} " \
+ "vram=${vram} " \
+ "omapfb.mode=dvi:${dvimode} " \
+ "omapfb.debug=y " \
+ "omapdss.def_disp=${defaultdisplay} " \
+ "root=${nandroot} " \
+ "rootfstype=${nandrootfstype}\0" \
+ "loadbootscript=fatload mmc ${mmcdev} ${loadaddr} boot.scr\0" \
+ "bootscript=echo Running bootscript from mmc ...; " \
+ "source ${loadaddr}\0" \
+ "loaduimage=fatload mmc ${mmcdev} ${loadaddr} uImage\0" \
+ "mmcboot=echo Booting from mmc ...; " \
+ "run mmcargs; " \
+ "bootm ${loadaddr}\0" \
+ "nandboot=echo Booting from nand ...; " \
+ "run nandargs; " \
+ "nand read ${loadaddr} 280000 200000; " \
+ "bootm ${loadaddr}\0" \
+
+#define CONFIG_BOOTCOMMAND \
+ "if mmc rescan ${mmcdev}; then " \
+ "if run loadbootscript; then " \
+ "run bootscript; " \
+ "else " \
+ "if run loaduimage; then " \
+ "run mmcboot; " \
+ "else run nandboot; " \
+ "fi; " \
+ "fi; " \
+ "else run nandboot; fi"
+
+#define CONFIG_AUTO_COMPLETE 1
+/*
+ * Miscellaneous configurable options
+ */
+#define CONFIG_SYS_LONGHELP /* undef to save memory */
+#define CONFIG_SYS_HUSH_PARSER /* use "hush" command parser */
+#define CONFIG_SYS_PROMPT_HUSH_PS2 "> "
+#define CONFIG_SYS_PROMPT "Overo # "
+#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
+/* Print Buffer Size */
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \
+ sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_MAXARGS 16 /* max number of command */
+ /* args */
+/* Boot Argument Buffer Size */
+#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
+/* memtest works on */
+#define CONFIG_SYS_MEMTEST_START (OMAP34XX_SDRC_CS0)
+#define CONFIG_SYS_MEMTEST_END (OMAP34XX_SDRC_CS0 + \
+ 0x01F00000) /* 31MB */
+
+#define CONFIG_SYS_LOAD_ADDR (OMAP34XX_SDRC_CS0) /* default load */
+ /* address */
+/*
+ * OMAP3 has 12 GP timers, they can be driven by the system clock
+ * (12/13/16.8/19.2/38.4MHz) or by 32KHz clock. We use 13MHz (V_SCLK).
+ * This rate is divided by a local divisor.
+ */
+#define CONFIG_SYS_TIMERBASE OMAP34XX_GPT2
+#define CONFIG_SYS_PTV 2 /* Divisor: 2^(PTV+1) => 8 */
+#define CONFIG_SYS_HZ 1000
+
+/*-----------------------------------------------------------------------
+ * Stack sizes
+ *
+ * The stack sizes are set up in start.S using the settings below
+ */
+#define CONFIG_STACKSIZE (128 << 10) /* regular stack 128 KiB */
+#ifdef CONFIG_USE_IRQ
+#define CONFIG_STACKSIZE_IRQ (4 << 10) /* IRQ stack 4 KiB */
+#define CONFIG_STACKSIZE_FIQ (4 << 10) /* FIQ stack 4 KiB */
+#endif
+
+/*-----------------------------------------------------------------------
+ * Physical Memory Map
+ */
+#define CONFIG_NR_DRAM_BANKS 2 /* CS1 may or may not be populated */
+#define PHYS_SDRAM_1 OMAP34XX_SDRC_CS0
+#define PHYS_SDRAM_1_SIZE (32 << 20) /* at least 32 MiB */
+#define PHYS_SDRAM_2 OMAP34XX_SDRC_CS1
+
+/* SDRAM Bank Allocation method */
+#define SDRC_R_B_C 1
+
+/*-----------------------------------------------------------------------
+ * FLASH and environment organization
+ */
+
+/* **** PISMO SUPPORT *** */
+
+/* Configure the PISMO */
+#define PISMO1_NAND_SIZE GPMC_SIZE_128M
+#define PISMO1_ONEN_SIZE GPMC_SIZE_128M
+
+#define CONFIG_SYS_MONITOR_LEN (256 << 10) /* Reserve 2 sectors */
+
+#define CONFIG_SYS_FLASH_BASE boot_flash_base
+
+/* Monitor at start of flash */
+#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_FLASH_BASE
+#define CONFIG_SYS_ONENAND_BASE ONENAND_MAP
+
+#define CONFIG_ENV_IS_IN_NAND 1
+#define ONENAND_ENV_OFFSET 0x240000 /* environment starts here */
+#define SMNAND_ENV_OFFSET 0x240000 /* environment starts here */
+
+#define CONFIG_SYS_ENV_SECT_SIZE boot_flash_sec
+#define CONFIG_ENV_OFFSET boot_flash_off
+#define CONFIG_ENV_ADDR SMNAND_ENV_OFFSET
+
+#ifndef __ASSEMBLY__
+extern unsigned int boot_flash_base;
+extern volatile unsigned int boot_flash_env_addr;
+extern unsigned int boot_flash_off;
+extern unsigned int boot_flash_sec;
+extern unsigned int boot_flash_type;
+#endif
+
+#if defined(CONFIG_CMD_NET)
+/*----------------------------------------------------------------------------
+ * SMSC9211 Ethernet from SMSC9118 family
+ *----------------------------------------------------------------------------
+ */
+
+#define CONFIG_NET_MULTI
+#define CONFIG_SMC911X 1
+#define CONFIG_SMC911X_32_BIT
+#define CONFIG_SMC911X_BASE 0x2C000000
+
+#endif /* (CONFIG_CMD_NET) */
+
+#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1
+#define CONFIG_SYS_INIT_RAM_ADDR 0x4020f800
+#define CONFIG_SYS_INIT_RAM_SIZE 0x800
+#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_INIT_RAM_ADDR + \
+ CONFIG_SYS_INIT_RAM_SIZE - \
+ GENERATED_GBL_DATA_SIZE)
+
+#endif /* __CONFIG_H */
diff --git a/package/uboot-omap4/Makefile b/package/uboot-omap4/Makefile
new file mode 100644
index 000000000..d128e16bd
--- /dev/null
+++ b/package/uboot-omap4/Makefile
@@ -0,0 +1,90 @@
+#
+# Copyright (C) 2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=u-boot
+PKG_VERSION:=2011.12
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=ftp://ftp.denx.de/pub/u-boot
+PKG_MD5SUM:=7f29b9f6da44d6e46e988e7561fd1d5f
+PKG_TARGETS:=bin
+
+include $(INCLUDE_DIR)/package.mk
+
+define uboot/Default
+ TITLE:=
+ CONFIG:=
+ IMAGE:=
+endef
+
+define uboot/omap4_panda
+ TITLE:=U-Boot for the Pandaboard
+endef
+
+UBOOTS:=omap4_panda
+
+define Package/uboot/template
+define Package/uboot-omap4-$(1)
+ SECTION:=boot
+ CATEGORY:=Boot Loaders
+ DEPENDS:=@TARGET_omap4
+ TITLE:=$(2)
+ URL:=http://www.denx.de/wiki/U-Boot
+ VARIANT:=$(1)
+endef
+endef
+
+define BuildUbootPackage
+ $(eval $(uboot/Default))
+ $(eval $(uboot/$(1)))
+ $(call Package/uboot/template,$(1),$(TITLE))
+endef
+
+
+ifdef BUILD_VARIANT
+$(eval $(call uboot/$(BUILD_VARIANT)))
+UBOOT_CONFIG:=$(if $(CONFIG),$(CONFIG),$(BUILD_VARIANT))
+UBOOT_IMAGE:=$(if $(IMAGE),$(IMAGE),openwrt-$(BOARD)-$(BUILD_VARIANT)-u-boot.bin)
+endif
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+# $(CP) ./files/* $(PKG_BUILD_DIR)
+ find $(PKG_BUILD_DIR) -name .svn | $(XARGS) rm -rf
+endef
+
+define Build/Configure
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(UBOOT_CONFIG)_config
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CROSS_COMPILE=$(TARGET_CROSS)
+endef
+
+define Package/uboot/install/template
+define Package/uboot-omap4-$(1)/install
+ $(INSTALL_DIR) $$(1)
+ $(CP) $(PKG_BUILD_DIR)/MLO $(BIN_DIR)/MLO-$(BOARD)
+ $(CP) $(PKG_BUILD_DIR)/u-boot.img $(BIN_DIR)/$(2)
+endef
+endef
+
+$(foreach u,$(UBOOTS), \
+ $(eval $(call Package/uboot/install/template,$(u),openwrt-$(BOARD)-$(u)-u-boot.img)) \
+)
+
+$(foreach u,$(UBOOTS), \
+ $(eval $(call BuildUbootPackage,$(u))) \
+ $(eval $(call BuildPackage,uboot-omap4-$(u))) \
+)
diff --git a/package/uboot-pxa/Makefile b/package/uboot-pxa/Makefile
new file mode 100644
index 000000000..d6b375362
--- /dev/null
+++ b/package/uboot-pxa/Makefile
@@ -0,0 +1,88 @@
+#
+# Copyright (C) 2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=u-boot
+PKG_VERSION:=2011.08.25
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=git://github.com/ashcharles/verdex-uboot.git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=ca6bf3ef6ac5f5132a359b43dfa31e07076b74b7
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
+
+include $(INCLUDE_DIR)/package.mk
+
+define uboot/Default
+ TITLE:=
+ CONFIG:=
+ IMAGE:=
+endef
+
+define uboot/gumstix
+ TITLE:=U-Boot for the Gumstix Verdex
+endef
+
+UBOOTS:=gumstix
+
+define Package/uboot/template
+define Package/uboot-pxa-$(1)
+ SECTION:=boot
+ CATEGORY:=Boot Loaders
+ DEPENDS:=@TARGET_pxa
+ TITLE:=$(2)
+ URL:=http://www.denx.de/wiki/U-Boot
+ VARIANT:=$(1)
+endef
+endef
+
+define BuildUBootPackage
+ $(eval $(uboot/Default))
+ $(eval $(uboot/$(1)))
+ $(call Package/uboot/template,$(1),$(TITLE))
+endef
+
+ifdef BUILD_VARIANT
+$(eval $(call uboot/$(BUILD_VARIANT)))
+UBOOT_CONFIG:=$(if $(CONFIG),$(CONFIG),$(BUILD_VARIANT))
+UBOOT_IMAGE:=$(if $(IMAGE),$(IMAGE),openwrt-$(BOARD)-$(BUILD_VARIANT)-u-boot.bin)
+endif
+
+define Build/Configure
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(UBOOT_CONFIG)_config
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ u-boot.bin \
+ CROSS_COMPILE=$(TARGET_CROSS)
+endef
+
+define Package/uboot/install/default
+ $(INSTALL_DIR) $(BIN_DIR)
+ $(CP) $(PKG_BUILD_DIR)/u-boot.bin \
+ $(BIN_DIR)/openwrt-$(BOARD)-$(1)-u-boot.bin
+endef
+
+define Package/uboot/install/template
+define Package/uboot-pxa-$(1)/install
+ $(call Package/uboot/install/default,$(2))
+endef
+endef
+
+$(foreach u,$(UBOOTS), \
+ $(eval $(call Package/uboot/install/template,$(u),$(u))) \
+)
+
+$(foreach u,$(UBOOTS), \
+ $(eval $(call BuildUBootPackage,$(u))) \
+ $(eval $(call BuildPackage,uboot-pxa-$(u))) \
+)
diff --git a/package/uboot-pxa/patches/001-squashfs_rootfstype_cmdline.patch b/package/uboot-pxa/patches/001-squashfs_rootfstype_cmdline.patch
new file mode 100644
index 000000000..cfef66b8f
--- /dev/null
+++ b/package/uboot-pxa/patches/001-squashfs_rootfstype_cmdline.patch
@@ -0,0 +1,13 @@
+diff --git a/include/configs/gumstix.h b/include/configs/gumstix.h
+index 319da63..5483993 100644
+--- a/include/configs/gumstix.h
++++ b/include/configs/gumstix.h
+@@ -136,7 +136,7 @@
+ #define CONFIG_MISC_INIT_R /* misc_init_r function in gumstix sets board serial number */
+
+ #define CONFIG_BOOTFILE boot/uImage
+-#define CONFIG_BOOTARGS "console=ttyS0,115200n8 root=1f01 rootfstype=jffs2 reboot=cold,hard"
++#define CONFIG_BOOTARGS "console=ttyS0,115200n8 root=1f01 rootfstype=squashfs,jffs2 reboot=cold,hard"
+ #define CONFIG_BOOTCOMMAND "icache on; setenv stderr nulldev; setenv stdout nulldev; if pinit on && fatload ide 0 a2000000 gumstix-factory.script; then setenv stdout serial; setenv stderr serial; echo Found gumstix-factory.script on CF...; autoscr; else if mmcinit && fatload mmc 0 a2000000 gumstix-factory.script; then setenv stdout serial; setenv stderr serial; echo Found gumstix-factory.script on MMC...; autoscr; else setenv stdout serial; setenv stderr serial; katload 100000 && bootm; fi; fi"
+ #define CONFIG_BOOTDELAY 2 /* in seconds */
+ #define CONFIG_EXTRA_ENV_SETTINGS "verify=no"
diff --git a/package/uboot-xburst/Makefile b/package/uboot-xburst/Makefile
new file mode 100644
index 000000000..1d340fd5e
--- /dev/null
+++ b/package/uboot-xburst/Makefile
@@ -0,0 +1,102 @@
+#
+# Copyright (C) 2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=u-boot
+PKG_VERSION:=2009.11
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=ftp://ftp.denx.de/pub/u-boot
+PKG_MD5SUM:=
+PKG_TARGETS:=bin
+
+include $(INCLUDE_DIR)/package.mk
+
+define uboot/Default
+ TITLE:=
+ CONFIG:=
+ IMAGE:=
+endef
+
+define uboot/qi_lb60
+ TITLE:=U-boot for the qi_lb60 board
+endef
+
+define uboot/avt2
+ TITLE:=U-boot for the avt2 board
+endef
+
+define uboot/sakc
+ TITLE:=U-boot for the sakc board
+endef
+
+define uboot/n516
+ TITLE:=U-boot for the N516 e-book reader
+ CONFIG:=n516_nand
+endef
+
+UBOOTS:=qi_lb60 n516 avt2 sakc
+
+define Package/uboot/template
+define Package/uboot-xburst-$(1)
+ SECTION:=boot
+ CATEGORY:=Boot Loaders
+ DEPENDS:=@TARGET_xburst
+ TITLE:=$(2)
+ URL:=http://www.denx.de/wiki/U-Boot
+ VARIANT:=$(1)
+endef
+endef
+
+define BuildUbootPackage
+ $(eval $(uboot/Default))
+ $(eval $(uboot/$(1)))
+ $(call Package/uboot/template,$(1),$(TITLE))
+endef
+
+
+ifdef BUILD_VARIANT
+$(eval $(call uboot/$(BUILD_VARIANT)))
+UBOOT_CONFIG:=$(if $(CONFIG),$(CONFIG),$(BUILD_VARIANT))
+UBOOT_IMAGE:=$(if $(IMAGE),$(IMAGE),openwrt-$(BOARD)-$(BUILD_VARIANT)-u-boot.bin)
+endif
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ $(CP) ./files/* $(PKG_BUILD_DIR)
+ find $(PKG_BUILD_DIR) -name .svn | $(XARGS) rm -rf
+endef
+
+define Build/Configure
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(UBOOT_CONFIG)_config
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CROSS_COMPILE=$(TARGET_CROSS)
+endef
+
+define Package/uboot/install/template
+define Package/uboot-xburst-$(1)/install
+ $(INSTALL_DIR) $$(1)
+ $(CP) $(PKG_BUILD_DIR)/u-boot-nand.bin $(BIN_DIR)/$(2)
+endef
+endef
+
+$(foreach u,$(UBOOTS), \
+ $(eval $(call Package/uboot/install/template,$(u),openwrt-$(BOARD)-$(u)-u-boot.bin)) \
+)
+
+$(foreach u,$(UBOOTS), \
+ $(eval $(call BuildUbootPackage,$(u))) \
+ $(eval $(call BuildPackage,uboot-xburst-$(u))) \
+)
diff --git a/package/uboot-xburst/files/board/n516/Makefile b/package/uboot-xburst/files/board/n516/Makefile
new file mode 100644
index 000000000..da3bb4c85
--- /dev/null
+++ b/package/uboot-xburst/files/board/n516/Makefile
@@ -0,0 +1,40 @@
+#
+# (C) Copyright 2006
+# Ingenic Semiconductor, <jlwei@ingenic.cn>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(BOARD).a
+
+COBJS = $(BOARD).o flash.o
+
+OBJS = $(addprefix $(obj),$(COBJS))
+SOBJS =
+
+$(LIB): $(obj).depend $(OBJS) $(SOBJS)
+ $(AR) crv $@ $(OBJS) $(SOBJS)
+
+#########################################################################
+
+$(obj).depend: Makefile $(SOBJS:.o=.S) $(COBJS:.o=.c)
+ $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(COBJS:.o=.c) > $@
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/package/uboot-xburst/files/board/n516/config.mk b/package/uboot-xburst/files/board/n516/config.mk
new file mode 100644
index 000000000..4bfe68082
--- /dev/null
+++ b/package/uboot-xburst/files/board/n516/config.mk
@@ -0,0 +1,33 @@
+#
+# (C) Copyright 2006
+# Ingenic Semiconductor, <jlwei@ingenic.cn>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+
+#
+# Hanvon n516 e-book, MIPS32 core
+#
+
+sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp
+
+ifndef TEXT_BASE
+# ROM version
+TEXT_BASE = 0x88000000
+
+# RAM version
+#TEXT_BASE = 0x80100000
+endif
diff --git a/package/uboot-xburst/files/board/n516/flash.c b/package/uboot-xburst/files/board/n516/flash.c
new file mode 100644
index 000000000..fd5f81533
--- /dev/null
+++ b/package/uboot-xburst/files/board/n516/flash.c
@@ -0,0 +1,50 @@
+/*
+ * (C) Copyright 2006
+ * Ingenic Semiconductor, <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <common.h>
+
+flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
+
+/*-----------------------------------------------------------------------
+ * flash_init()
+ *
+ * sets up flash_info and returns size of FLASH (bytes)
+ */
+unsigned long flash_init (void)
+{
+ return (0);
+}
+
+int flash_erase (flash_info_t * info, int s_first, int s_last)
+{
+ printf ("flash_erase not implemented\n");
+ return 0;
+}
+
+void flash_print_info (flash_info_t * info)
+{
+ printf ("flash_print_info not implemented\n");
+}
+
+int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
+{
+ printf ("write_buff not implemented\n");
+ return (-1);
+}
diff --git a/package/uboot-xburst/files/board/n516/n516.c b/package/uboot-xburst/files/board/n516/n516.c
new file mode 100644
index 000000000..d7885965c
--- /dev/null
+++ b/package/uboot-xburst/files/board/n516/n516.c
@@ -0,0 +1,126 @@
+/*
+ * (C) Copyright 2006
+ * Ingenic Semiconductor, <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/mipsregs.h>
+#include <asm/jz4740.h>
+#include <asm/addrspace.h>
+#include <asm/cacheops.h>
+
+void _machine_restart(void)
+{
+ __wdt_select_extalclk();
+ __wdt_select_clk_div64();
+ __wdt_set_data(100);
+ __wdt_set_count(0);
+ __tcu_start_wdt_clock();
+ __wdt_start();
+ while(1);
+
+}
+
+static void gpio_init(void)
+{
+
+ REG_GPIO_PXPES(0) = 0xffffffff;
+ REG_GPIO_PXPES(1) = 0xffffffff;
+ REG_GPIO_PXPES(2) = 0xffffffff;
+ REG_GPIO_PXPES(3) = 0xffffffff;
+
+ /*
+ * Initialize NAND Flash Pins
+ */
+ __gpio_as_nand();
+
+ /*
+ * Initialize SDRAM pins
+ */
+ __gpio_as_sdram_32bit();
+
+ /*
+ * Initialize UART0 pins
+ */
+ __gpio_as_uart0();
+
+ /*
+ * Initialize MSC pins
+ */
+ __gpio_as_msc();
+
+ /*
+ * Initialize LCD pins
+ */
+ __gpio_as_lcd_16bit();
+
+ /*
+ * Initialize Other pins
+ */
+ __gpio_as_output(GPIO_SD_VCC_EN_N);
+ __gpio_clear_pin(GPIO_SD_VCC_EN_N);
+
+ __gpio_as_input(GPIO_SD_CD_N);
+ __gpio_disable_pull(GPIO_SD_CD_N);
+
+ __gpio_as_output(GPIO_DISP_OFF_N);
+
+ __gpio_as_output(GPIO_LED_EN);
+ __gpio_set_pin(GPIO_LED_EN);
+
+ __gpio_as_input(127);
+}
+
+static void cpm_init(void)
+{
+ __cpm_stop_ipu();
+ __cpm_stop_cim();
+ __cpm_stop_i2c();
+ __cpm_stop_ssi();
+ __cpm_stop_uart1();
+ __cpm_stop_sadc();
+ __cpm_stop_uhc();
+ __cpm_stop_udc();
+ __cpm_stop_aic1();
+ __cpm_stop_aic2();
+ __cpm_suspend_udcphy();
+ __cpm_suspend_usbphy();
+}
+
+//----------------------------------------------------------------------
+// board early init routine
+
+void board_early_init(void)
+{
+ gpio_init();
+ cpm_init();
+}
+
+//----------------------------------------------------------------------
+// U-Boot common routines
+
+int checkboard (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ printf("Board: Hanvon n516 e-book (CPU Speed %d MHz)\n",
+ gd->cpu_clk/1000000);
+
+ return 0; /* success */
+}
diff --git a/package/uboot-xburst/files/board/n516/u-boot-nand.lds b/package/uboot-xburst/files/board/n516/u-boot-nand.lds
new file mode 100644
index 000000000..a15a96ec8
--- /dev/null
+++ b/package/uboot-xburst/files/board/n516/u-boot-nand.lds
@@ -0,0 +1,63 @@
+/*
+ * (C) Copyright 2006
+ * Ingenic Semiconductor, <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradlittlemips", "elf32-tradlittlemips")
+
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .sdata : { *(.sdata) }
+
+ _gp = ALIGN(16);
+
+ __got_start = .;
+ .got : { *(.got) }
+ __got_end = .;
+
+ .sdata : { *(.sdata) }
+
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+ uboot_end_data = .;
+ num_got_entries = (__got_end - __got_start) >> 2;
+
+ . = ALIGN(4);
+ .sbss : { *(.sbss) }
+ .bss : { *(.bss) }
+ uboot_end = .;
+}
diff --git a/package/uboot-xburst/files/board/n516/u-boot.lds b/package/uboot-xburst/files/board/n516/u-boot.lds
new file mode 100644
index 000000000..a15a96ec8
--- /dev/null
+++ b/package/uboot-xburst/files/board/n516/u-boot.lds
@@ -0,0 +1,63 @@
+/*
+ * (C) Copyright 2006
+ * Ingenic Semiconductor, <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradlittlemips", "elf32-tradlittlemips")
+
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .sdata : { *(.sdata) }
+
+ _gp = ALIGN(16);
+
+ __got_start = .;
+ .got : { *(.got) }
+ __got_end = .;
+
+ .sdata : { *(.sdata) }
+
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+ uboot_end_data = .;
+ num_got_entries = (__got_end - __got_start) >> 2;
+
+ . = ALIGN(4);
+ .sbss : { *(.sbss) }
+ .bss : { *(.bss) }
+ uboot_end = .;
+}
diff --git a/package/uboot-xburst/files/board/nanonote/Makefile b/package/uboot-xburst/files/board/nanonote/Makefile
new file mode 100644
index 000000000..2c726a788
--- /dev/null
+++ b/package/uboot-xburst/files/board/nanonote/Makefile
@@ -0,0 +1,38 @@
+#
+# (C) Copyright 2006
+# Ingenic Semiconductor, <jlwei@ingenic.cn>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = lib$(BOARD).a
+
+OBJS = $(BOARD).o
+SOBJS =
+
+$(LIB): .depend $(OBJS) $(SOBJS)
+ $(AR) crv $@ $(OBJS) $(SOBJS)
+
+#########################################################################
+
+.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+ $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/package/uboot-xburst/files/board/nanonote/config.mk b/package/uboot-xburst/files/board/nanonote/config.mk
new file mode 100644
index 000000000..858e6a2f9
--- /dev/null
+++ b/package/uboot-xburst/files/board/nanonote/config.mk
@@ -0,0 +1,31 @@
+#
+# (C) Copyright 2006 Qi Hardware, Inc.
+# Author: Xiangfu Liu <xiangfu.z@gmail.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+
+#
+# Qi Hardware, Inc. Ben NanoNote (QI_LB60)
+#
+
+ifndef TEXT_BASE
+# ROM version
+# TEXT_BASE = 0x88000000
+
+# RAM version
+TEXT_BASE = 0x80100000
+endif
diff --git a/package/uboot-xburst/files/board/nanonote/nanonote.c b/package/uboot-xburst/files/board/nanonote/nanonote.c
new file mode 100644
index 000000000..96a3c7da0
--- /dev/null
+++ b/package/uboot-xburst/files/board/nanonote/nanonote.c
@@ -0,0 +1,123 @@
+/*
+ * Authors: Xiangfu Liu <xiangfu.z@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 3 of the License, or (at your option) any later version.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/mipsregs.h>
+#include <asm/jz4740.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void gpio_init(void)
+{
+ /*
+ * Initialize NAND Flash Pins
+ */
+ __gpio_as_nand();
+
+ /*
+ * Initialize SDRAM pins
+ */
+ __gpio_as_sdram_32bit();
+
+ /*
+ * Initialize LCD pins
+ */
+ __gpio_as_lcd_8bit();
+
+ /*
+ * Initialize MSC pins
+ */
+ __gpio_as_msc();
+
+ /*
+ * Initialize Other pins
+ */
+ unsigned int i;
+ for (i = 0; i < 7; i++){
+ __gpio_as_input(GPIO_KEYIN_BASE + i);
+ __gpio_enable_pull(GPIO_KEYIN_BASE + i);
+ }
+
+ for (i = 0; i < 8; i++) {
+ __gpio_as_output(GPIO_KEYOUT_BASE + i);
+ __gpio_clear_pin(GPIO_KEYOUT_BASE + i);
+ }
+
+ /*
+ * Initialize UART0 pins, in Ben NanoNote uart0 and keyin8 use the
+ * same gpio, init the gpio as uart0 cause a keyboard bug. so for
+ * end user we disable the uart0
+ */
+ if (__gpio_get_pin(GPIO_KEYIN_BASE + 2) == 0){
+ /* if pressed [S] */
+ printf("[S] pressed, enable UART0\n");
+ gd->boot_option = 5;
+ __gpio_as_uart0();
+ } else {
+ printf("[S] not pressed, disable UART0\n");
+ __gpio_as_input(GPIO_KEYIN_8);
+ __gpio_enable_pull(GPIO_KEYIN_8);
+ }
+
+ __gpio_as_output(GPIO_AUDIO_POP);
+ __gpio_set_pin(GPIO_AUDIO_POP);
+
+ __gpio_as_output(GPIO_LCD_CS);
+ __gpio_clear_pin(GPIO_LCD_CS);
+
+ __gpio_as_output(GPIO_AMP_EN);
+ __gpio_clear_pin(GPIO_AMP_EN);
+
+ __gpio_as_output(GPIO_SDPW_EN);
+ __gpio_disable_pull(GPIO_SDPW_EN);
+ __gpio_clear_pin(GPIO_SDPW_EN);
+
+ __gpio_as_input(GPIO_SD_DETECT);
+ __gpio_disable_pull(GPIO_SD_DETECT);
+
+ __gpio_as_input(GPIO_USB_DETECT);
+ __gpio_enable_pull(GPIO_USB_DETECT);
+
+ if (__gpio_get_pin(GPIO_KEYIN_BASE + 3) == 0) {
+ printf("[M] pressed, boot from sd card\n");
+ gd->boot_option = 1;
+ }
+}
+
+static void cpm_init(void)
+{
+ __cpm_stop_ipu();
+ __cpm_stop_cim();
+ __cpm_stop_i2c();
+ __cpm_stop_ssi();
+ __cpm_stop_uart1();
+ __cpm_stop_sadc();
+ __cpm_stop_uhc();
+ __cpm_stop_udc();
+ __cpm_stop_aic1();
+/* __cpm_stop_aic2();*/
+}
+
+void board_early_init(void)
+{
+ gpio_init();
+ cpm_init();
+}
+
+/* U-Boot common routines */
+
+int checkboard (void)
+{
+
+ printf("Board: Qi LB60 (Ingenic XBurst Jz4740 SoC, Speed %d MHz)\n",
+ gd->cpu_clk/1000000);
+
+ return 0; /* success */
+}
diff --git a/package/uboot-xburst/files/board/nanonote/u-boot-nand.lds b/package/uboot-xburst/files/board/nanonote/u-boot-nand.lds
new file mode 100644
index 000000000..a15a96ec8
--- /dev/null
+++ b/package/uboot-xburst/files/board/nanonote/u-boot-nand.lds
@@ -0,0 +1,63 @@
+/*
+ * (C) Copyright 2006
+ * Ingenic Semiconductor, <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradlittlemips", "elf32-tradlittlemips")
+
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .sdata : { *(.sdata) }
+
+ _gp = ALIGN(16);
+
+ __got_start = .;
+ .got : { *(.got) }
+ __got_end = .;
+
+ .sdata : { *(.sdata) }
+
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+ uboot_end_data = .;
+ num_got_entries = (__got_end - __got_start) >> 2;
+
+ . = ALIGN(4);
+ .sbss : { *(.sbss) }
+ .bss : { *(.bss) }
+ uboot_end = .;
+}
diff --git a/package/uboot-xburst/files/board/nanonote/u-boot.lds b/package/uboot-xburst/files/board/nanonote/u-boot.lds
new file mode 100644
index 000000000..a15a96ec8
--- /dev/null
+++ b/package/uboot-xburst/files/board/nanonote/u-boot.lds
@@ -0,0 +1,63 @@
+/*
+ * (C) Copyright 2006
+ * Ingenic Semiconductor, <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradlittlemips", "elf32-tradlittlemips")
+
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .sdata : { *(.sdata) }
+
+ _gp = ALIGN(16);
+
+ __got_start = .;
+ .got : { *(.got) }
+ __got_end = .;
+
+ .sdata : { *(.sdata) }
+
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+ uboot_end_data = .;
+ num_got_entries = (__got_end - __got_start) >> 2;
+
+ . = ALIGN(4);
+ .sbss : { *(.sbss) }
+ .bss : { *(.bss) }
+ uboot_end = .;
+}
diff --git a/package/uboot-xburst/files/board/sakc/Makefile b/package/uboot-xburst/files/board/sakc/Makefile
new file mode 100644
index 000000000..470447d45
--- /dev/null
+++ b/package/uboot-xburst/files/board/sakc/Makefile
@@ -0,0 +1,38 @@
+#
+# (C) Copyright 2006
+# Ingenic Semiconductor, <jlwei@ingenic.cn>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = lib$(BOARD).a
+
+OBJS = $(BOARD).o
+SOBJS =
+
+$(LIB): .depend $(OBJS) $(SOBJS)
+ $(AR) crv $@ $(OBJS) $(SOBJS)
+
+#########################################################################
+
+.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+ $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/package/uboot-xburst/files/board/sakc/config.mk b/package/uboot-xburst/files/board/sakc/config.mk
new file mode 100644
index 000000000..b2549587e
--- /dev/null
+++ b/package/uboot-xburst/files/board/sakc/config.mk
@@ -0,0 +1,31 @@
+#
+# (C) Copyright 2006 Qi Hardware, Inc.
+# Author: Xiangfu Liu <xiangfu.z@gmail.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+
+#
+# SAKC Board
+#
+
+ifndef TEXT_BASE
+# ROM version
+# TEXT_BASE = 0x88000000
+
+# RAM version
+TEXT_BASE = 0x80100000
+endif
diff --git a/package/uboot-xburst/files/board/sakc/sakc.c b/package/uboot-xburst/files/board/sakc/sakc.c
new file mode 100644
index 000000000..85763c754
--- /dev/null
+++ b/package/uboot-xburst/files/board/sakc/sakc.c
@@ -0,0 +1,94 @@
+/*
+ * Authors: Xiangfu Liu <xiangfu.z@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 3 of the License, or (at your option) any later version.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/mipsregs.h>
+#include <asm/jz4740.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void gpio_init(void)
+{
+ /*
+ * Initialize NAND Flash Pins
+ */
+ __gpio_as_nand();
+
+ /*
+ * Initialize SDRAM pins
+ */
+ __gpio_as_sdram_16bit_4725();
+
+ /*
+ * Initialize UART0 pins
+ */
+ __gpio_as_uart0();
+
+ /*
+ * Initialize LCD pins
+ */
+ __gpio_as_lcd_18bit();
+
+ /*
+ * Initialize MSC pins
+ */
+ __gpio_as_msc();
+
+ /*
+ * Initialize SSI pins
+ */
+ __gpio_as_ssi();
+
+ /*
+ * Initialize I2C pins
+ */
+ __gpio_as_i2c();
+
+ /*
+ * Initialize MSC pins
+ */
+ __gpio_as_msc();
+
+ /*
+ * Initialize Other pins
+ */
+ __gpio_as_input(GPIO_SD_DETECT);
+ __gpio_disable_pull(GPIO_SD_DETECT);
+}
+/* TODO SAKC
+static void cpm_init(void)
+{
+ __cpm_stop_ipu();
+ __cpm_stop_cim();
+ __cpm_stop_i2c();
+ __cpm_stop_ssi();
+ __cpm_stop_uart1();
+ __cpm_stop_sadc();
+ __cpm_stop_uhc();
+ __cpm_stop_aic1();
+ __cpm_stop_aic2();
+}*/
+
+void board_early_init(void)
+{
+ gpio_init();
+ //cpm_init(); //TODO SAKC
+}
+
+/* U-Boot common routines */
+
+int checkboard (void)
+{
+
+ printf("Board: SAKC (Ingenic XBurst Jz4725 SoC, Speed %d MHz)\n",
+ gd->cpu_clk/1000000);
+
+ return 0; /* success */
+}
diff --git a/package/uboot-xburst/files/board/sakc/u-boot-nand.lds b/package/uboot-xburst/files/board/sakc/u-boot-nand.lds
new file mode 100644
index 000000000..a15a96ec8
--- /dev/null
+++ b/package/uboot-xburst/files/board/sakc/u-boot-nand.lds
@@ -0,0 +1,63 @@
+/*
+ * (C) Copyright 2006
+ * Ingenic Semiconductor, <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradlittlemips", "elf32-tradlittlemips")
+
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .sdata : { *(.sdata) }
+
+ _gp = ALIGN(16);
+
+ __got_start = .;
+ .got : { *(.got) }
+ __got_end = .;
+
+ .sdata : { *(.sdata) }
+
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+ uboot_end_data = .;
+ num_got_entries = (__got_end - __got_start) >> 2;
+
+ . = ALIGN(4);
+ .sbss : { *(.sbss) }
+ .bss : { *(.bss) }
+ uboot_end = .;
+}
diff --git a/package/uboot-xburst/files/board/sakc/u-boot.lds b/package/uboot-xburst/files/board/sakc/u-boot.lds
new file mode 100644
index 000000000..a15a96ec8
--- /dev/null
+++ b/package/uboot-xburst/files/board/sakc/u-boot.lds
@@ -0,0 +1,63 @@
+/*
+ * (C) Copyright 2006
+ * Ingenic Semiconductor, <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradlittlemips", "elf32-tradlittlemips")
+
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .sdata : { *(.sdata) }
+
+ _gp = ALIGN(16);
+
+ __got_start = .;
+ .got : { *(.got) }
+ __got_end = .;
+
+ .sdata : { *(.sdata) }
+
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+ uboot_end_data = .;
+ num_got_entries = (__got_end - __got_start) >> 2;
+
+ . = ALIGN(4);
+ .sbss : { *(.sbss) }
+ .bss : { *(.bss) }
+ uboot_end = .;
+}
diff --git a/package/uboot-xburst/files/cpu/mips/jz4740.c b/package/uboot-xburst/files/cpu/mips/jz4740.c
new file mode 100644
index 000000000..5ae57971d
--- /dev/null
+++ b/package/uboot-xburst/files/cpu/mips/jz4740.c
@@ -0,0 +1,559 @@
+/*
+ * Jz4740 common routines
+ *
+ * Copyright (c) 2006
+ * Ingenic Semiconductor, <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <config.h>
+
+#ifdef CONFIG_JZ4740
+#include <common.h>
+#include <command.h>
+#include <asm/jz4740.h>
+
+extern void board_early_init(void);
+
+/* PLL output clock = EXTAL * NF / (NR * NO)
+ *
+ * NF = FD + 2, NR = RD + 2
+ * NO = 1 (if OD = 0), NO = 2 (if OD = 1 or 2), NO = 4 (if OD = 3)
+ */
+void pll_init(void)
+{
+ register unsigned int cfcr, plcr1;
+ int n2FR[33] = {
+ 0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
+ 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
+ 9
+ };
+ int div[5] = {1, 3, 3, 3, 3}; /* divisors of I:S:P:L:M */
+ int nf, pllout2;
+
+ cfcr = CPM_CPCCR_CLKOEN |
+ CPM_CPCCR_PCS |
+ (n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) |
+ (n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) |
+ (n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) |
+ (n2FR[div[3]] << CPM_CPCCR_MDIV_BIT) |
+ (n2FR[div[4]] << CPM_CPCCR_LDIV_BIT);
+
+ pllout2 = (cfcr & CPM_CPCCR_PCS) ? CONFIG_SYS_CPU_SPEED : (CONFIG_SYS_CPU_SPEED / 2);
+
+ /* Init USB Host clock, pllout2 must be n*48MHz */
+ REG_CPM_UHCCDR = pllout2 / 48000000 - 1;
+
+ nf = CONFIG_SYS_CPU_SPEED * 2 / CONFIG_SYS_EXTAL;
+ plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */
+ (0 << CPM_CPPCR_PLLN_BIT) | /* RD=0, NR=2 */
+ (0 << CPM_CPPCR_PLLOD_BIT) | /* OD=0, NO=1 */
+ (0x20 << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */
+ CPM_CPPCR_PLLEN; /* enable PLL */
+
+ /* init PLL */
+ REG_CPM_CPCCR = cfcr;
+ REG_CPM_CPPCR = plcr1;
+}
+
+void pll_add_test(int new_freq)
+{
+ register unsigned int cfcr, plcr1;
+ int n2FR[33] = {
+ 0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
+ 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
+ 9
+ };
+ int div[5] = {1, 4, 4, 4, 4}; /* divisors of I:S:P:M:L */
+ int nf, pllout2;
+
+ cfcr = CPM_CPCCR_CLKOEN |
+ (n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) |
+ (n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) |
+ (n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) |
+ (n2FR[div[3]] << CPM_CPCCR_MDIV_BIT) |
+ (n2FR[div[4]] << CPM_CPCCR_LDIV_BIT);
+
+ pllout2 = (cfcr & CPM_CPCCR_PCS) ? new_freq : (new_freq / 2);
+
+ /* Init UHC clock */
+ REG_CPM_UHCCDR = pllout2 / 48000000 - 1;
+
+ /* nf = new_freq * 2 / CONFIG_SYS_EXTAL; */
+ nf = new_freq / 1000000; /* step length is 1M */
+ plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */
+ (10 << CPM_CPPCR_PLLN_BIT) | /* RD=0, NR=2 */
+ (0 << CPM_CPPCR_PLLOD_BIT) | /* OD=0, NO=1 */
+ (0x20 << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */
+ CPM_CPPCR_PLLEN; /* enable PLL */
+
+ /* init PLL */
+ REG_CPM_CPCCR = cfcr;
+ REG_CPM_CPPCR = plcr1;
+}
+
+void calc_clocks_add_test(void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ unsigned int pllout;
+ unsigned int div[10] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
+
+ pllout = __cpm_get_pllout();
+
+ gd->cpu_clk = pllout / div[__cpm_get_cdiv()];
+ gd->sys_clk = pllout / div[__cpm_get_hdiv()];
+ gd->per_clk = pllout / div[__cpm_get_pdiv()];
+ gd->mem_clk = pllout / div[__cpm_get_mdiv()];
+ gd->dev_clk = CONFIG_SYS_EXTAL;
+}
+
+void sdram_add_test(int new_freq)
+{
+ register unsigned int dmcr, sdmode, tmp, cpu_clk, mem_clk, ns;
+
+ unsigned int cas_latency_sdmr[2] = {
+ EMC_SDMR_CAS_2,
+ EMC_SDMR_CAS_3,
+ };
+
+ unsigned int cas_latency_dmcr[2] = {
+ 1 << EMC_DMCR_TCL_BIT, /* CAS latency is 2 */
+ 2 << EMC_DMCR_TCL_BIT /* CAS latency is 3 */
+ };
+
+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
+
+ cpu_clk = new_freq;
+ mem_clk = cpu_clk * div[__cpm_get_cdiv()] / div[__cpm_get_mdiv()];
+
+ REG_EMC_RTCSR = EMC_RTCSR_CKS_DISABLE;
+ REG_EMC_RTCOR = 0;
+ REG_EMC_RTCNT = 0;
+
+ /* Basic DMCR register value. */
+ dmcr = ((SDRAM_ROW-11)<<EMC_DMCR_RA_BIT) |
+ ((SDRAM_COL-8)<<EMC_DMCR_CA_BIT) |
+ (SDRAM_BANK4<<EMC_DMCR_BA_BIT) |
+ (SDRAM_BW16<<EMC_DMCR_BW_BIT) |
+ EMC_DMCR_EPIN |
+ cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
+
+ /* SDRAM timimg parameters */
+ ns = 1000000000 / mem_clk;
+
+#if 0
+ tmp = SDRAM_TRAS/ns;
+ if (tmp < 4) tmp = 4;
+ if (tmp > 11) tmp = 11;
+ dmcr |= ((tmp-4) << EMC_DMCR_TRAS_BIT);
+
+ tmp = SDRAM_RCD/ns;
+ if (tmp > 3) tmp = 3;
+ dmcr |= (tmp << EMC_DMCR_RCD_BIT);
+
+ tmp = SDRAM_TPC/ns;
+ if (tmp > 7) tmp = 7;
+ dmcr |= (tmp << EMC_DMCR_TPC_BIT);
+
+ tmp = SDRAM_TRWL/ns;
+ if (tmp > 3) tmp = 3;
+ dmcr |= (tmp << EMC_DMCR_TRWL_BIT);
+
+ tmp = (SDRAM_TRAS + SDRAM_TPC)/ns;
+ if (tmp > 14) tmp = 14;
+ dmcr |= (((tmp + 1) >> 1) << EMC_DMCR_TRC_BIT);
+#else
+ dmcr |= 0xfffc;
+#endif
+
+ /* First, precharge phase */
+ REG_EMC_DMCR = dmcr;
+
+ /* Set refresh registers */
+ tmp = SDRAM_TREF/ns;
+ tmp = tmp/64 + 1;
+ if (tmp > 0xff) tmp = 0xff;
+
+ REG_EMC_RTCOR = tmp;
+ REG_EMC_RTCSR = EMC_RTCSR_CKS_64; /* Divisor is 64, CKO/64 */
+
+ /* SDRAM mode values */
+ sdmode = EMC_SDMR_BT_SEQ |
+ EMC_SDMR_OM_NORMAL |
+ EMC_SDMR_BL_4 |
+ cas_latency_sdmr[((SDRAM_CASL == 3) ? 1 : 0)];
+
+ /* precharge all chip-selects */
+ REG8(EMC_SDMR0|sdmode) = 0;
+
+ /* wait for precharge, > 200us */
+ tmp = (cpu_clk / 1000000) * 200;
+ while (tmp--);
+
+ /* enable refresh and set SDRAM mode */
+ REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
+
+ /* write sdram mode register for each chip-select */
+ REG8(EMC_SDMR0|sdmode) = 0;
+
+ /* everything is ok now */
+}
+
+void sdram_init(void)
+{
+ register unsigned int dmcr0, dmcr, sdmode, tmp, cpu_clk, mem_clk, ns;
+
+ unsigned int cas_latency_sdmr[2] = {
+ EMC_SDMR_CAS_2,
+ EMC_SDMR_CAS_3,
+ };
+
+ unsigned int cas_latency_dmcr[2] = {
+ 1 << EMC_DMCR_TCL_BIT, /* CAS latency is 2 */
+ 2 << EMC_DMCR_TCL_BIT /* CAS latency is 3 */
+ };
+
+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
+
+ cpu_clk = CONFIG_SYS_CPU_SPEED;
+ mem_clk = cpu_clk * div[__cpm_get_cdiv()] / div[__cpm_get_mdiv()];
+
+ REG_EMC_BCR = 0; /* Disable bus release */
+ REG_EMC_RTCSR = 0; /* Disable clock for counting */
+
+ /* Fault DMCR value for mode register setting*/
+#define SDRAM_ROW0 11
+#define SDRAM_COL0 8
+#define SDRAM_BANK40 0
+
+ dmcr0 = ((SDRAM_ROW0-11)<<EMC_DMCR_RA_BIT) |
+ ((SDRAM_COL0-8)<<EMC_DMCR_CA_BIT) |
+ (SDRAM_BANK40<<EMC_DMCR_BA_BIT) |
+ (SDRAM_BW16<<EMC_DMCR_BW_BIT) |
+ EMC_DMCR_EPIN |
+ cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
+
+ /* Basic DMCR value */
+ dmcr = ((SDRAM_ROW-11)<<EMC_DMCR_RA_BIT) |
+ ((SDRAM_COL-8)<<EMC_DMCR_CA_BIT) |
+ (SDRAM_BANK4<<EMC_DMCR_BA_BIT) |
+ (SDRAM_BW16<<EMC_DMCR_BW_BIT) |
+ EMC_DMCR_EPIN |
+ cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
+
+ /* SDRAM timimg */
+ ns = 1000000000 / mem_clk;
+ tmp = SDRAM_TRAS/ns;
+ if (tmp < 4) tmp = 4;
+ if (tmp > 11) tmp = 11;
+ dmcr |= ((tmp-4) << EMC_DMCR_TRAS_BIT);
+ tmp = SDRAM_RCD/ns;
+ if (tmp > 3) tmp = 3;
+ dmcr |= (tmp << EMC_DMCR_RCD_BIT);
+ tmp = SDRAM_TPC/ns;
+ if (tmp > 7) tmp = 7;
+ dmcr |= (tmp << EMC_DMCR_TPC_BIT);
+ tmp = SDRAM_TRWL/ns;
+ if (tmp > 3) tmp = 3;
+ dmcr |= (tmp << EMC_DMCR_TRWL_BIT);
+ tmp = (SDRAM_TRAS + SDRAM_TPC)/ns;
+ if (tmp > 14) tmp = 14;
+ dmcr |= (((tmp + 1) >> 1) << EMC_DMCR_TRC_BIT);
+
+ /* SDRAM mode value */
+ sdmode = EMC_SDMR_BT_SEQ |
+ EMC_SDMR_OM_NORMAL |
+ EMC_SDMR_BL_4 |
+ cas_latency_sdmr[((SDRAM_CASL == 3) ? 1 : 0)];
+
+ /* Stage 1. Precharge all banks by writing SDMR with DMCR.MRSET=0 */
+ REG_EMC_DMCR = dmcr;
+ REG8(EMC_SDMR0|sdmode) = 0;
+
+ /* Wait for precharge, > 200us */
+ tmp = (cpu_clk / 1000000) * 1000;
+ while (tmp--);
+
+ /* Stage 2. Enable auto-refresh */
+ REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH;
+
+ tmp = SDRAM_TREF/ns;
+ tmp = tmp/64 + 1;
+ if (tmp > 0xff) tmp = 0xff;
+ REG_EMC_RTCOR = tmp;
+ REG_EMC_RTCNT = 0;
+ REG_EMC_RTCSR = EMC_RTCSR_CKS_64; /* Divisor is 64, CKO/64 */
+
+ /* Wait for number of auto-refresh cycles */
+ tmp = (cpu_clk / 1000000) * 1000;
+ while (tmp--);
+
+ /* Stage 3. Mode Register Set */
+ REG_EMC_DMCR = dmcr0 | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
+ REG8(EMC_SDMR0|sdmode) = 0;
+
+ /* Set back to basic DMCR value */
+ REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
+
+ /* everything is ok now */
+}
+
+#ifndef CONFIG_NAND_SPL
+
+static void calc_clocks(void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+
+ unsigned int pllout;
+ unsigned int div[10] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
+
+ pllout = __cpm_get_pllout();
+
+ gd->cpu_clk = pllout / div[__cpm_get_cdiv()];
+ gd->sys_clk = pllout / div[__cpm_get_hdiv()];
+ gd->per_clk = pllout / div[__cpm_get_pdiv()];
+ gd->mem_clk = pllout / div[__cpm_get_mdiv()];
+ gd->dev_clk = CONFIG_SYS_EXTAL;
+}
+
+static void rtc_init(void)
+{
+ unsigned long rtcsta;
+
+ while ( !__rtc_write_ready()) ;
+ __rtc_enable_alarm(); /* enable alarm */
+
+ while ( !__rtc_write_ready())
+ ;
+ REG_RTC_RGR = 0x00007fff; /* type value */
+
+ while ( !__rtc_write_ready())
+ ;
+ REG_RTC_HWFCR = 0x0000ffe0; /* Power on delay 2s */
+
+ while ( !__rtc_write_ready())
+ ;
+ REG_RTC_HRCR = 0x00000fe0; /* reset delay 125ms */
+#if 0
+ while ( !__rtc_write_ready())
+ ;
+ rtcsta = REG_RTC_HWRSR;
+ while ( !__rtc_write_ready())
+ ;
+ if (rtcsta & 0x33) {
+ if (rtcsta & 0x10) {
+ while ( !__rtc_write_ready())
+ ;
+ REG_RTC_RSR = 0x0;
+ }
+ while ( !__rtc_write_ready())
+ ;
+ REG_RTC_HWRSR = 0x0;
+ }
+#endif
+}
+
+/*
+ * jz4740 board init routine
+ */
+int jz_board_init(void)
+{
+ board_early_init(); /* init gpio, pll etc. */
+#ifndef CONFIG_NAND_U_BOOT
+ pll_init(); /* init PLL */
+ sdram_init(); /* init sdram memory */
+#endif
+ calc_clocks(); /* calc the clocks */
+ rtc_init(); /* init rtc on any reset: */
+ return 0;
+}
+
+/* U-Boot common routines */
+phys_size_t initdram(int board_type)
+{
+ u32 dmcr;
+ u32 rows, cols, dw, banks;
+ ulong size;
+
+ dmcr = REG_EMC_DMCR;
+ rows = 11 + ((dmcr & EMC_DMCR_RA_MASK) >> EMC_DMCR_RA_BIT);
+ cols = 8 + ((dmcr & EMC_DMCR_CA_MASK) >> EMC_DMCR_CA_BIT);
+ dw = (dmcr & EMC_DMCR_BW) ? 2 : 4;
+ banks = (dmcr & EMC_DMCR_BA) ? 4 : 2;
+
+ size = (1 << (rows + cols)) * dw * banks;
+
+ return size;
+}
+
+/*
+ * Timer routines
+ */
+
+#define TIMER_CHAN 0
+#define TIMER_FDATA 0xffff /* Timer full data value */
+#define TIMER_HZ CONFIG_SYS_HZ
+
+#define READ_TIMER REG_TCU_TCNT(TIMER_CHAN) /* macro to read the 16 bit timer */
+
+static ulong timestamp;
+static ulong lastdec;
+
+void reset_timer_masked (void);
+ulong get_timer_masked (void);
+void udelay_masked (unsigned long usec);
+
+/*
+ * timer without interrupts
+ */
+
+int timer_init(void)
+{
+ REG_TCU_TCSR(TIMER_CHAN) = TCU_TCSR_PRESCALE256 | TCU_TCSR_EXT_EN;
+ REG_TCU_TCNT(TIMER_CHAN) = 0;
+ REG_TCU_TDHR(TIMER_CHAN) = 0;
+ REG_TCU_TDFR(TIMER_CHAN) = TIMER_FDATA;
+
+ REG_TCU_TMSR = (1 << TIMER_CHAN) | (1 << (TIMER_CHAN + 16)); /* mask irqs */
+ REG_TCU_TSCR = (1 << TIMER_CHAN); /* enable timer clock */
+ REG_TCU_TESR = (1 << TIMER_CHAN); /* start counting up */
+
+ lastdec = 0;
+ timestamp = 0;
+
+ return 0;
+}
+
+void reset_timer(void)
+{
+ reset_timer_masked ();
+}
+
+ulong get_timer(ulong base)
+{
+ return get_timer_masked () - base;
+}
+
+void set_timer(ulong t)
+{
+ timestamp = t;
+}
+
+void udelay (unsigned long usec)
+{
+ ulong tmo,tmp;
+
+ /* normalize */
+ if (usec >= 1000) {
+ tmo = usec / 1000;
+ tmo *= TIMER_HZ;
+ tmo /= 1000;
+ }
+ else {
+ if (usec >= 1) {
+ tmo = usec * TIMER_HZ;
+ tmo /= (1000*1000);
+ }
+ else
+ tmo = 1;
+ }
+
+ /* check for rollover during this delay */
+ tmp = get_timer (0);
+ if ((tmp + tmo) < tmp )
+ reset_timer_masked(); /* timer would roll over */
+ else
+ tmo += tmp;
+
+ while (get_timer_masked () < tmo);
+}
+
+void reset_timer_masked (void)
+{
+ /* reset time */
+ lastdec = READ_TIMER;
+ timestamp = 0;
+}
+
+ulong get_timer_masked (void)
+{
+ ulong now = READ_TIMER;
+
+ if (lastdec <= now) {
+ /* normal mode */
+ timestamp += (now - lastdec);
+ } else {
+ /* we have an overflow ... */
+ timestamp += TIMER_FDATA + now - lastdec;
+ }
+ lastdec = now;
+
+ return timestamp;
+}
+
+void udelay_masked (unsigned long usec)
+{
+ ulong tmo;
+ ulong endtime;
+ signed long diff;
+
+ /* normalize */
+ if (usec >= 1000) {
+ tmo = usec / 1000;
+ tmo *= TIMER_HZ;
+ tmo /= 1000;
+ } else {
+ if (usec > 1) {
+ tmo = usec * TIMER_HZ;
+ tmo /= (1000*1000);
+ } else {
+ tmo = 1;
+ }
+ }
+
+ endtime = get_timer_masked () + tmo;
+
+ do {
+ ulong now = get_timer_masked ();
+ diff = endtime - now;
+ } while (diff >= 0);
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On MIPS it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+ return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On MIPS it returns the number of timer ticks per second.
+ */
+ulong get_tbclk (void)
+{
+ return TIMER_HZ;
+}
+
+#endif /* CONFIG_NAND_SPL */
+
+/* End of timer routine. */
+
+#endif
diff --git a/package/uboot-xburst/files/cpu/mips/jz4740_nand.c b/package/uboot-xburst/files/cpu/mips/jz4740_nand.c
new file mode 100644
index 000000000..7877194f1
--- /dev/null
+++ b/package/uboot-xburst/files/cpu/mips/jz4740_nand.c
@@ -0,0 +1,199 @@
+/*
+ * Platform independend driver for JZ4740.
+ *
+ * Copyright (c) 2007 Ingenic Semiconductor Inc.
+ * Author: <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+#include <common.h>
+
+#if defined(CONFIG_CMD_NAND) && defined(CONFIG_JZ4740)
+
+#include <nand.h>
+#include <asm/jz4740.h>
+#include <asm/io.h>
+
+#define PAR_SIZE 9
+#define __nand_ecc_enable() (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST )
+#define __nand_ecc_disable() (REG_EMC_NFECR &= ~EMC_NFECR_ECCE)
+
+#define __nand_select_rs_ecc() (REG_EMC_NFECR |= EMC_NFECR_RS)
+
+#define __nand_rs_ecc_encoding() (REG_EMC_NFECR |= EMC_NFECR_RS_ENCODING)
+#define __nand_rs_ecc_decoding() (REG_EMC_NFECR |= EMC_NFECR_RS_DECODING)
+#define __nand_ecc_encode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_ENCF))
+#define __nand_ecc_decode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_DECF))
+
+static void jz_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+ struct nand_chip *this = mtd->priv;
+ unsigned long nandaddr = (unsigned long)this->IO_ADDR_W;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ /* Change this to use I/O accessors. */
+ if (ctrl & NAND_NCE)
+ REG_EMC_NFCSR |= EMC_NFCSR_NFCE1;
+ else
+ REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1;
+ }
+
+ if (cmd == NAND_CMD_NONE)
+ return;
+
+ if (ctrl & NAND_CLE)
+ nandaddr |= 0x00008000;
+ else /* must be ALE */
+ nandaddr |= 0x00010000;
+
+ writeb(cmd, (uint8_t *)nandaddr);
+}
+
+static int jz_device_ready(struct mtd_info *mtd)
+{
+ int ready;
+ udelay(20); /* FIXME: add 20us delay */
+ ready = (REG_GPIO_PXPIN(2) & 0x40000000) ? 1 : 0;
+ return ready;
+}
+
+/*
+ * EMC setup
+ */
+static void jz_device_setup(void)
+{
+ /* Set NFE bit */
+ REG_EMC_NFCSR |= EMC_NFCSR_NFE1;
+ REG_EMC_SMCR1 = 0x094c4400;
+ /* REG_EMC_SMCR3 = 0x04444400; */
+}
+
+void board_nand_select_device(struct nand_chip *nand, int chip)
+{
+ /*
+ * Don't use "chip" to address the NAND device,
+ * generate the cs from the address where it is encoded.
+ */
+}
+
+static int jzsoc_nand_calculate_rs_ecc(struct mtd_info* mtd, const u_char* dat,
+ u_char* ecc_code)
+{
+ volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0;
+ short i;
+
+ __nand_ecc_encode_sync()
+ __nand_ecc_disable();
+
+ for(i = 0; i < PAR_SIZE; i++)
+ ecc_code[i] = *paraddr++;
+
+ return 0;
+}
+
+static void jzsoc_nand_enable_rs_hwecc(struct mtd_info* mtd, int mode)
+{
+ __nand_ecc_enable();
+ __nand_select_rs_ecc();
+
+ REG_EMC_NFINTS = 0x0;
+ if (NAND_ECC_READ == mode){
+ __nand_rs_ecc_decoding();
+ }
+ if (NAND_ECC_WRITE == mode){
+ __nand_rs_ecc_encoding();
+ }
+}
+
+/* Correct 1~9-bit errors in 512-bytes data */
+static void jzsoc_rs_correct(unsigned char *dat, int idx, int mask)
+{
+ int i;
+
+ idx--;
+
+ i = idx + (idx >> 3);
+ if (i >= 512)
+ return;
+
+ mask <<= (idx & 0x7);
+
+ dat[i] ^= mask & 0xff;
+ if (i < 511)
+ dat[i+1] ^= (mask >> 8) & 0xff;
+}
+
+static int jzsoc_nand_rs_correct_data(struct mtd_info *mtd, u_char *dat,
+ u_char *read_ecc, u_char *calc_ecc)
+{
+ volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0;
+ short k;
+ u32 stat;
+ /* Set PAR values */
+
+ for (k = 0; k < PAR_SIZE; k++) {
+ *paraddr++ = read_ecc[k];
+ }
+
+ /* Set PRDY */
+ REG_EMC_NFECR |= EMC_NFECR_PRDY;
+
+ /* Wait for completion */
+ __nand_ecc_decode_sync();
+ __nand_ecc_disable();
+
+ /* Check decoding */
+ stat = REG_EMC_NFINTS;
+ if (stat & EMC_NFINTS_ERR) {
+ if (stat & EMC_NFINTS_UNCOR) {
+ printk("Uncorrectable error occurred\n");
+ return -1;
+ }
+ else {
+ u32 errcnt = (stat & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT;
+ switch (errcnt) {
+ case 4:
+ jzsoc_rs_correct(dat, (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
+ case 3:
+ jzsoc_rs_correct(dat, (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
+ case 2:
+ jzsoc_rs_correct(dat, (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
+ case 1:
+ jzsoc_rs_correct(dat, (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
+ return 0;
+ default:
+ break;
+ }
+ }
+ }
+ /* no error need to be correct */
+ return 0;
+}
+
+/*
+ * Main initialization routine
+ */
+int board_nand_init(struct nand_chip *nand)
+{
+ jz_device_setup();
+
+ nand->cmd_ctrl = jz_hwcontrol;
+ nand->dev_ready = jz_device_ready;
+
+ /* FIXME: should use NAND_ECC_SOFT */
+ nand->ecc.hwctl = jzsoc_nand_enable_rs_hwecc;
+ nand->ecc.correct = jzsoc_nand_rs_correct_data;
+ nand->ecc.calculate = jzsoc_nand_calculate_rs_ecc;
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->ecc.size = 512;
+ nand->ecc.bytes = 9;
+
+ /* 20 us command delay time */
+ nand->chip_delay = 20;
+
+ return 0;
+}
+#endif /* (CONFIG_SYS_CMD_NAND) */
diff --git a/package/uboot-xburst/files/cpu/mips/jz_lcd.c b/package/uboot-xburst/files/cpu/mips/jz_lcd.c
new file mode 100644
index 000000000..927b82a6a
--- /dev/null
+++ b/package/uboot-xburst/files/cpu/mips/jz_lcd.c
@@ -0,0 +1,484 @@
+/*
+ * JzRISC lcd controller
+ *
+ * xiangfu liu <xiangfu.z@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+/*
+ * Fallowing macro may be used:
+ * CONFIG_LCD : LCD support
+ * LCD_BPP : Bits per pixel, 0 = 1, 1 = 2, 2 = 4, 3 = 8
+ * CONFIG_LCD_LOGO : show logo
+ */
+
+#include <config.h>
+#include <common.h>
+#include <lcd.h>
+
+#include <asm/io.h> /* virt_to_phys() */
+
+#if defined(CONFIG_LCD) && !defined(CONFIG_SLCD)
+
+#if defined(CONFIG_JZ4740)
+#include <asm/jz4740.h>
+#endif
+
+#include "jz_lcd.h"
+
+
+struct jzfb_info {
+ unsigned int cfg; /* panel mode and pin usage etc. */
+ unsigned int w;
+ unsigned int h;
+ unsigned int bpp; /* bit per pixel */
+ unsigned int fclk; /* frame clk */
+ unsigned int hsw; /* hsync width, in pclk */
+ unsigned int vsw; /* vsync width, in line count */
+ unsigned int elw; /* end of line, in pclk */
+ unsigned int blw; /* begin of line, in pclk */
+ unsigned int efw; /* end of frame, in line count */
+ unsigned int bfw; /* begin of frame, in line count */
+};
+
+static struct jzfb_info jzfb = {
+ #if defined(CONFIG_NANONOTE)
+ MODE_8BIT_SERIAL_TFT | PCLK_N | HSYNC_N | VSYNC_N,
+ 320, 240, 32, 70, 1, 1, 273, 140, 1, 20
+ #endif
+
+};
+
+/************************************************************************/
+
+vidinfo_t panel_info = {
+#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01)
+ 320, 240, LCD_BPP,
+#endif
+};
+
+/*----------------------------------------------------------------------*/
+
+int lcd_line_length;
+
+int lcd_color_fg;
+int lcd_color_bg;
+
+/*
+ * Frame buffer memory information
+ */
+void *lcd_base; /* Start of framebuffer memory */
+void *lcd_console_address; /* Start of console buffer */
+
+short console_col;
+short console_row;
+
+/*----------------------------------------------------------------------*/
+
+void lcd_ctrl_init (void *lcdbase);
+
+void lcd_enable (void);
+void lcd_disable (void);
+
+/*----------------------------------------------------------------------*/
+
+static int jz_lcd_init_mem(void *lcdbase, vidinfo_t *vid);
+static void jz_lcd_desc_init(vidinfo_t *vid);
+static int jz_lcd_hw_init( vidinfo_t *vid );
+extern int flush_cache_all(void);
+
+#if LCD_BPP == LCD_COLOR8
+void lcd_setcolreg (ushort regno, ushort red, ushort green, ushort blue);
+#endif
+#if LCD_BPP == LCD_MONOCHROME
+void lcd_initcolregs (void);
+#endif
+
+/*-----------------------------------------------------------------------*/
+
+void lcd_ctrl_init (void *lcdbase)
+{
+ __lcd_display_pin_init();
+
+ jz_lcd_init_mem(lcdbase, &panel_info);
+ jz_lcd_desc_init(&panel_info);
+ jz_lcd_hw_init(&panel_info);
+
+ __lcd_display_on() ;
+}
+
+/*----------------------------------------------------------------------*/
+#if LCD_BPP == LCD_COLOR8
+void
+lcd_setcolreg (ushort regno, ushort red, ushort green, ushort blue)
+{
+}
+#endif
+/*----------------------------------------------------------------------*/
+
+#if LCD_BPP == LCD_MONOCHROME
+static
+void lcd_initcolregs (void)
+{
+}
+#endif
+
+/*
+ * Before enabled lcd controller, lcd registers should be configured correctly.
+ */
+
+void lcd_enable (void)
+{
+ REG_LCD_CTRL &= ~(1<<4); /* LCDCTRL.DIS */
+ REG_LCD_CTRL |= 1<<3; /* LCDCTRL.ENA*/
+}
+
+void lcd_disable (void)
+{
+ REG_LCD_CTRL |= (1<<4); /* LCDCTRL.DIS, regular disable */
+ /* REG_LCD_CTRL |= (1<<3); */ /* LCDCTRL.DIS, quikly disable */
+}
+
+static int jz_lcd_init_mem(void *lcdbase, vidinfo_t *vid)
+{
+ u_long palette_mem_size;
+ struct jz_fb_info *fbi = &vid->jz_fb;
+ int fb_size = vid->vl_row * (vid->vl_col * NBITS (vid->vl_bpix)) / 8;
+
+ fbi->screen = (u_long)lcdbase;
+ fbi->palette_size = 256;
+ palette_mem_size = fbi->palette_size * sizeof(u16);
+
+ debug("jz_lcd.c palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);
+ /* locate palette and descs at end of page following fb */
+ fbi->palette = (u_long)lcdbase + fb_size + PAGE_SIZE - palette_mem_size;
+
+ return 0;
+}
+
+static void jz_lcd_desc_init(vidinfo_t *vid)
+{
+ struct jz_fb_info * fbi;
+ fbi = &vid->jz_fb;
+ fbi->dmadesc_fblow = (struct jz_fb_dma_descriptor *)((unsigned int)fbi->palette - 3*16);
+ fbi->dmadesc_fbhigh = (struct jz_fb_dma_descriptor *)((unsigned int)fbi->palette - 2*16);
+ fbi->dmadesc_palette = (struct jz_fb_dma_descriptor *)((unsigned int)fbi->palette - 1*16);
+
+ #define BYTES_PER_PANEL (vid->vl_col * vid->vl_row * NBITS(vid->vl_bpix) / 8)
+
+ /* populate descriptors */
+ fbi->dmadesc_fblow->fdadr = virt_to_phys(fbi->dmadesc_fblow);
+ fbi->dmadesc_fblow->fsadr = virt_to_phys((void *)(fbi->screen + BYTES_PER_PANEL));
+ fbi->dmadesc_fblow->fidr = 0;
+ fbi->dmadesc_fblow->ldcmd = BYTES_PER_PANEL / 4 ;
+
+ fbi->fdadr1 = virt_to_phys(fbi->dmadesc_fblow); /* only used in dual-panel mode */
+
+ fbi->dmadesc_fbhigh->fsadr = virt_to_phys((void *)fbi->screen);
+ fbi->dmadesc_fbhigh->fidr = 0;
+ fbi->dmadesc_fbhigh->ldcmd = BYTES_PER_PANEL / 4; /* length in word */
+
+ fbi->dmadesc_palette->fsadr = virt_to_phys((void *)fbi->palette);
+ fbi->dmadesc_palette->fidr = 0;
+ fbi->dmadesc_palette->ldcmd = (fbi->palette_size * 2)/4 | (1<<28);
+
+ if( NBITS(vid->vl_bpix) < 12)
+ {
+ /* assume any mode with <12 bpp is palette driven */
+ fbi->dmadesc_palette->fdadr = virt_to_phys(fbi->dmadesc_fbhigh);
+ fbi->dmadesc_fbhigh->fdadr = virt_to_phys(fbi->dmadesc_palette);
+ /* flips back and forth between pal and fbhigh */
+ fbi->fdadr0 = virt_to_phys(fbi->dmadesc_palette);
+ } else {
+ /* palette shouldn't be loaded in true-color mode */
+ fbi->dmadesc_fbhigh->fdadr = virt_to_phys((void *)fbi->dmadesc_fbhigh);
+ fbi->fdadr0 = virt_to_phys(fbi->dmadesc_fbhigh); /* no pal just fbhigh */
+ }
+
+ flush_cache_all();
+}
+
+static int jz_lcd_hw_init(vidinfo_t *vid)
+{
+ struct jz_fb_info *fbi = &vid->jz_fb;
+ unsigned int val = 0;
+ unsigned int pclk;
+ unsigned int stnH;
+#if defined(CONFIG_MIPS_JZ4740)
+ int pll_div;
+#endif
+
+ /* Setting Control register */
+ switch (jzfb.bpp) {
+ case 1:
+ val |= LCD_CTRL_BPP_1;
+ break;
+ case 2:
+ val |= LCD_CTRL_BPP_2;
+ break;
+ case 4:
+ val |= LCD_CTRL_BPP_4;
+ break;
+ case 8:
+ val |= LCD_CTRL_BPP_8;
+ break;
+ case 15:
+ val |= LCD_CTRL_RGB555;
+ case 16:
+ val |= LCD_CTRL_BPP_16;
+ break;
+#if defined(CONFIG_MIPS_JZ4740)
+ case 17 ... 32:
+ val |= LCD_CTRL_BPP_18_24; /* target is 4bytes/pixel */
+ break;
+#endif
+ default:
+ printf("jz_lcd.c The BPP %d is not supported\n", jzfb.bpp);
+ val |= LCD_CTRL_BPP_16;
+ break;
+ }
+
+ switch (jzfb.cfg & MODE_MASK) {
+ case MODE_STN_MONO_DUAL:
+ case MODE_STN_COLOR_DUAL:
+ case MODE_STN_MONO_SINGLE:
+ case MODE_STN_COLOR_SINGLE:
+ switch (jzfb.bpp) {
+ case 1:
+ /* val |= LCD_CTRL_PEDN; */
+ case 2:
+ val |= LCD_CTRL_FRC_2;
+ break;
+ case 4:
+ val |= LCD_CTRL_FRC_4;
+ break;
+ case 8:
+ default:
+ val |= LCD_CTRL_FRC_16;
+ break;
+ }
+ break;
+ }
+
+ val |= LCD_CTRL_BST_16; /* Burst Length is 16WORD=64Byte */
+ val |= LCD_CTRL_OFUP; /* OutFIFO underrun protect */
+
+ switch (jzfb.cfg & MODE_MASK) {
+ case MODE_STN_MONO_DUAL:
+ case MODE_STN_COLOR_DUAL:
+ case MODE_STN_MONO_SINGLE:
+ case MODE_STN_COLOR_SINGLE:
+ switch (jzfb.cfg & STN_DAT_PINMASK) {
+#define align2(n) (n)=((((n)+1)>>1)<<1)
+#define align4(n) (n)=((((n)+3)>>2)<<2)
+#define align8(n) (n)=((((n)+7)>>3)<<3)
+ case STN_DAT_PIN1:
+ /* Do not adjust the hori-param value. */
+ break;
+ case STN_DAT_PIN2:
+ align2(jzfb.hsw);
+ align2(jzfb.elw);
+ align2(jzfb.blw);
+ break;
+ case STN_DAT_PIN4:
+ align4(jzfb.hsw);
+ align4(jzfb.elw);
+ align4(jzfb.blw);
+ break;
+ case STN_DAT_PIN8:
+ align8(jzfb.hsw);
+ align8(jzfb.elw);
+ align8(jzfb.blw);
+ break;
+ }
+ break;
+ }
+
+ REG_LCD_CTRL = val;
+
+ switch (jzfb.cfg & MODE_MASK) {
+ case MODE_STN_MONO_DUAL:
+ case MODE_STN_COLOR_DUAL:
+ case MODE_STN_MONO_SINGLE:
+ case MODE_STN_COLOR_SINGLE:
+ if (((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL) ||
+ ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL))
+ stnH = jzfb.h >> 1;
+ else
+ stnH = jzfb.h;
+
+ REG_LCD_VSYNC = (0 << 16) | jzfb.vsw;
+ REG_LCD_HSYNC = ((jzfb.blw+jzfb.w) << 16) | (jzfb.blw+jzfb.w+jzfb.hsw);
+
+ /* Screen setting */
+ REG_LCD_VAT = ((jzfb.blw + jzfb.w + jzfb.hsw + jzfb.elw) << 16) | (stnH + jzfb.vsw + jzfb.bfw + jzfb.efw);
+ REG_LCD_DAH = (jzfb.blw << 16) | (jzfb.blw + jzfb.w);
+ REG_LCD_DAV = (0 << 16) | (stnH);
+
+ /* AC BIAs signal */
+ REG_LCD_PS = (0 << 16) | (stnH+jzfb.vsw+jzfb.efw+jzfb.bfw);
+
+ break;
+
+ case MODE_TFT_GEN:
+ case MODE_TFT_SHARP:
+ case MODE_TFT_CASIO:
+ case MODE_TFT_SAMSUNG:
+ case MODE_8BIT_SERIAL_TFT:
+ case MODE_TFT_18BIT:
+ REG_LCD_VSYNC = (0 << 16) | jzfb.vsw;
+ REG_LCD_HSYNC = (0 << 16) | jzfb.hsw;
+#if defined(CONFIG_JZLCD_INNOLUX_AT080TN42)
+ REG_LCD_DAV = (0 << 16) | ( jzfb.h );
+#else
+ REG_LCD_DAV =((jzfb.vsw+jzfb.bfw) << 16) | (jzfb.vsw +jzfb.bfw+jzfb.h);
+#endif /*#if defined(CONFIG_JZLCD_INNOLUX_AT080TN42)*/
+ REG_LCD_DAH = ((jzfb.hsw + jzfb.blw) << 16) | (jzfb.hsw + jzfb.blw + jzfb.w );
+ REG_LCD_VAT = (((jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw)) << 16) \
+ | (jzfb.vsw + jzfb.bfw + jzfb.h + jzfb.efw);
+ break;
+ }
+
+ switch (jzfb.cfg & MODE_MASK) {
+ case MODE_TFT_SAMSUNG:
+ {
+ unsigned int total, tp_s, tp_e, ckv_s, ckv_e;
+ unsigned int rev_s, rev_e, inv_s, inv_e;
+
+ pclk = val * (jzfb.w + jzfb.hsw + jzfb.elw + jzfb.blw) *
+ (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */
+
+ total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw;
+ tp_s = jzfb.blw + jzfb.w + 1;
+ tp_e = tp_s + 1;
+ /* ckv_s = tp_s - jz_clocks.pixclk/(1000000000/4100); */
+ ckv_s = tp_s - pclk/(1000000000/4100);
+ ckv_e = tp_s + total;
+ rev_s = tp_s - 11; /* -11.5 clk */
+ rev_e = rev_s + total;
+ inv_s = tp_s;
+ inv_e = inv_s + total;
+ REG_LCD_CLS = (tp_s << 16) | tp_e;
+ REG_LCD_PS = (ckv_s << 16) | ckv_e;
+ REG_LCD_SPL = (rev_s << 16) | rev_e;
+ REG_LCD_REV = (inv_s << 16) | inv_e;
+ jzfb.cfg |= STFT_REVHI | STFT_SPLHI;
+ break;
+ }
+ case MODE_TFT_SHARP:
+ {
+ unsigned int total, cls_s, cls_e, ps_s, ps_e;
+ unsigned int spl_s, spl_e, rev_s, rev_e;
+ total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw;
+#if !defined(CONFIG_JZLCD_INNOLUX_AT080TN42)
+ spl_s = 1;
+ spl_e = spl_s + 1;
+ cls_s = 0;
+ cls_e = total - 60; /* > 4us (pclk = 80ns) */
+ ps_s = cls_s;
+ ps_e = cls_e;
+ rev_s = total - 40; /* > 3us (pclk = 80ns) */
+ rev_e = rev_s + total;
+ jzfb.cfg |= STFT_PSHI;
+#else /*#if defined(CONFIG_JZLCD_INNOLUX_AT080TN42)*/
+ spl_s = total - 5; /* LD */
+ spl_e = total -3;
+ cls_s = 32; /* CKV */
+ cls_e = 145;
+ ps_s = 0; /* OEV */
+ ps_e = 45;
+ rev_s = 0; /* POL */
+ rev_e = 0;
+#endif /*#if defined(CONFIG_JZLCD_INNOLUX_AT080TN42)*/
+ REG_LCD_SPL = (spl_s << 16) | spl_e;
+ REG_LCD_CLS = (cls_s << 16) | cls_e;
+ REG_LCD_PS = (ps_s << 16) | ps_e;
+ REG_LCD_REV = (rev_s << 16) | rev_e;
+ break;
+ }
+ case MODE_TFT_CASIO:
+ break;
+ }
+
+ /* Configure the LCD panel */
+ REG_LCD_CFG = jzfb.cfg;
+
+ /* Timing setting */
+ __cpm_stop_lcd();
+
+ val = jzfb.fclk; /* frame clk */
+ if ( (jzfb.cfg & MODE_MASK) != MODE_8BIT_SERIAL_TFT) {
+ pclk = val * (jzfb.w + jzfb.hsw + jzfb.elw + jzfb.blw) *
+ (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */
+ }
+ else {
+ /* serial mode: Hsync period = 3*Width_Pixel */
+ pclk = val * (jzfb.w*3 + jzfb.hsw + jzfb.elw + jzfb.blw) *
+ (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */
+ }
+
+ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) ||
+ ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL))
+ pclk = (pclk * 3);
+
+ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) ||
+ ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ||
+ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_SINGLE) ||
+ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL))
+ pclk = pclk >> ((jzfb.cfg & STN_DAT_PINMASK) >> 4);
+
+ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ||
+ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL))
+ pclk >>= 1;
+
+ pll_div = ( REG_CPM_CPCCR & CPM_CPCCR_PCS ); /* clock source,0:pllout/2 1: pllout */
+ pll_div = pll_div ? 1 : 2 ;
+ val = ( __cpm_get_pllout()/pll_div ) / pclk;
+ val--;
+ if ( val > 0x1ff ) {
+ printf("CPM_LPCDR too large, set it to 0x1ff\n");
+ val = 0x1ff;
+ }
+ __cpm_set_pixdiv(val);
+
+ val = pclk * 3 ; /* LCDClock > 2.5*Pixclock */
+ if ( val > 150000000 ) {
+ printf("Warning: LCDClock=%d\n, LCDClock must less or equal to 150MHz.\n", val);
+ printf("Change LCDClock to 150MHz\n");
+ val = 150000000;
+ }
+ val = ( __cpm_get_pllout()/pll_div ) / val;
+ val--;
+ if ( val > 0x1f ) {
+ printf("CPM_CPCCR.LDIV too large, set it to 0x1f\n");
+ val = 0x1f;
+ }
+ __cpm_set_ldiv( val );
+ REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* update divide */
+
+ __cpm_start_lcd();
+ udelay(1000);
+
+ REG_LCD_DA0 = fbi->fdadr0; /* frame descripter*/
+
+ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ||
+ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL))
+ REG_LCD_DA1 = fbi->fdadr1; /* frame descripter*/
+
+ return 0;
+}
+
diff --git a/package/uboot-xburst/files/cpu/mips/jz_lcd.h b/package/uboot-xburst/files/cpu/mips/jz_lcd.h
new file mode 100644
index 000000000..dfd63e03a
--- /dev/null
+++ b/package/uboot-xburst/files/cpu/mips/jz_lcd.h
@@ -0,0 +1,260 @@
+/*
+ * JzRISC lcd controller
+ *
+ * xiangfu liu <xiangfu.z@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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 __JZLCD_H__
+#define __JZLCD_H__
+
+#include <asm/io.h>
+/*
+ * change u-boot macro to celinux macro
+ */
+/* Chip type */
+#if defined(CONFIG_JZ4740)
+#define CONFIG_MIPS_JZ4740 1
+#endif
+
+/* board type */
+#if defined(CONFIG_NANONOTE)
+#define CONFIG_MIPS_JZ4740_PI 1
+#endif
+
+#define mdelay(n) udelay((n)*1000)
+
+/*
+ * change u-boot macro to celinux macro
+ */
+
+#define NR_PALETTE 256
+
+struct lcd_desc{
+ unsigned int next_desc; /* LCDDAx */
+ unsigned int databuf; /* LCDSAx */
+ unsigned int frame_id; /* LCDFIDx */
+ unsigned int cmd; /* LCDCMDx */
+};
+
+#define MODE_MASK 0x0f
+#define MODE_TFT_GEN 0x00
+#define MODE_TFT_SHARP 0x01
+#define MODE_TFT_CASIO 0x02
+#define MODE_TFT_SAMSUNG 0x03
+#define MODE_CCIR656_NONINT 0x04
+#define MODE_CCIR656_INT 0x05
+#define MODE_STN_COLOR_SINGLE 0x08
+#define MODE_STN_MONO_SINGLE 0x09
+#define MODE_STN_COLOR_DUAL 0x0a
+#define MODE_STN_MONO_DUAL 0x0b
+#define MODE_8BIT_SERIAL_TFT 0x0c
+
+#define MODE_TFT_18BIT (1<<7)
+
+#define STN_DAT_PIN1 (0x00 << 4)
+#define STN_DAT_PIN2 (0x01 << 4)
+#define STN_DAT_PIN4 (0x02 << 4)
+#define STN_DAT_PIN8 (0x03 << 4)
+#define STN_DAT_PINMASK STN_DAT_PIN8
+
+#define STFT_PSHI (1 << 15)
+#define STFT_CLSHI (1 << 14)
+#define STFT_SPLHI (1 << 13)
+#define STFT_REVHI (1 << 12)
+
+#define SYNC_MASTER (0 << 16)
+#define SYNC_SLAVE (1 << 16)
+
+#define DE_P (0 << 9)
+#define DE_N (1 << 9)
+
+#define PCLK_P (0 << 10)
+#define PCLK_N (1 << 10)
+
+#define HSYNC_P (0 << 11)
+#define HSYNC_N (1 << 11)
+
+#define VSYNC_P (0 << 8)
+#define VSYNC_N (1 << 8)
+
+#define DATA_NORMAL (0 << 17)
+#define DATA_INVERSE (1 << 17)
+
+
+/* Jz LCDFB supported I/O controls. */
+#define FBIOSETBACKLIGHT 0x4688
+#define FBIODISPON 0x4689
+#define FBIODISPOFF 0x468a
+#define FBIORESET 0x468b
+#define FBIOPRINT_REG 0x468c
+
+/*
+ * LCD panel specific definition
+ */
+
+#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) || defined(CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL)
+
+#if defined(CONFIG_JZLCD_FOXCONN_PT035TN01) /* board pmp */
+#define MODE 0xcd /* 24bit parellel RGB */
+#endif
+#if defined(CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL)
+#define MODE 0xc9 /* 8bit serial RGB */
+#endif
+
+#if defined(CONFIG_MIPS_JZ4740_PI) /* board pavo */
+ #define SPEN (32*2+21) /*LCD_SPL */
+ #define SPCK (32*2+23) /*LCD_CLS */
+ #define SPDA (32*2+22) /*LCD_D12 */
+ #define LCD_RET (32*3+27)
+#else
+#error "cpu/misp/Jzlcd.h, please define SPI pins on your board."
+#endif
+
+ #define __spi_write_reg1(reg, val) \
+ do { \
+ unsigned char no;\
+ unsigned short value;\
+ unsigned char a=0;\
+ unsigned char b=0;\
+ a=reg;\
+ b=val;\
+ __gpio_set_pin(SPEN);\
+ __gpio_set_pin(SPCK);\
+ __gpio_clear_pin(SPDA);\
+ __gpio_clear_pin(SPEN);\
+ udelay(25);\
+ value=((a<<8)|(b&0xFF));\
+ for(no=0;no<16;no++)\
+ {\
+ __gpio_clear_pin(SPCK);\
+ if((value&0x8000)==0x8000)\
+ __gpio_set_pin(SPDA);\
+ else\
+ __gpio_clear_pin(SPDA);\
+ udelay(25);\
+ __gpio_set_pin(SPCK);\
+ value=(value<<1); \
+ udelay(25);\
+ }\
+ __gpio_set_pin(SPEN);\
+ udelay(100);\
+ } while (0)
+
+ #define __spi_write_reg(reg, val) \
+ do {\
+ __spi_write_reg1((reg<<2|2), val);\
+ udelay(100); \
+ }while(0)
+
+
+ #define __lcd_special_pin_init() \
+ do { \
+ __gpio_as_output(SPEN); /* use SPDA */\
+ __gpio_as_output(SPCK); /* use SPCK */\
+ __gpio_as_output(SPDA); /* use SPDA */\
+ __gpio_as_output(LCD_RET);\
+ } while (0)
+
+#if defined(CONFIG_NANONOTE)
+ #define __lcd_special_on() \
+ do { \
+ udelay(50);\
+ __spi_write_reg1(0x05, 0x16); \
+ __spi_write_reg1(0x04, 0x0b); \
+ __spi_write_reg1(0x07, 0x8d); \
+ __spi_write_reg1(0x01, 0x95); \
+ __spi_write_reg1(0x08, 0xc0); \
+ __spi_write_reg1(0x03, 0x40); \
+ __spi_write_reg1(0x06, 0x15); \
+ __spi_write_reg1(0x05, 0xd7); \
+ } while (0) /* reg 0x0a is control the display direction:DB0->horizontal level DB1->vertical level */
+
+ #define __lcd_special_off() \
+ do { \
+ __spi_write_reg1(0x05, 0x5e); \
+ } while (0)
+#endif /* CONFIG_NANONOTE */
+#endif /* CONFIG_JZLCD_FOXCONN_PT035TN01 or CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL */
+
+#ifndef __lcd_special_pin_init
+#define __lcd_special_pin_init()
+#endif
+#ifndef __lcd_special_on
+#define __lcd_special_on()
+#endif
+#ifndef __lcd_special_off
+#define __lcd_special_off()
+#endif
+
+
+/*
+ * Platform specific definition
+ */
+
+#if defined(CONFIG_MIPS_JZ4740_PI)
+
+ /* 100 level: 0,1,...,100 */
+ #define __lcd_set_backlight_level(n)\
+ do { \
+ __gpio_as_output(32*3+27); \
+ __gpio_set_pin(32*3+27); \
+ } while (0)
+
+ #define __lcd_close_backlight() \
+ do { \
+ __gpio_as_output(GPIO_PWM); \
+ __gpio_clear_pin(GPIO_PWM); \
+ } while (0)
+
+ #define __lcd_display_pin_init() \
+ do { \
+ __gpio_as_output(GPIO_DISP_OFF_N); \
+ __cpm_start_tcu(); \
+ __lcd_special_pin_init(); \
+ } while (0)
+ /* __lcd_set_backlight_level(100); \*/
+ #define __lcd_display_on() \
+ do { \
+ __gpio_set_pin(GPIO_DISP_OFF_N); \
+ __lcd_special_on(); \
+ } while (0)
+
+ #define __lcd_display_off() \
+ do { \
+ __lcd_special_off(); \
+ __gpio_clear_pin(GPIO_DISP_OFF_N); \
+ } while (0)
+
+#endif /* CONFIG_MIPS_JZ4740_PI) */
+
+/*****************************************************************************
+ * LCD display pin dummy macros
+ *****************************************************************************/
+#ifndef __lcd_display_pin_init
+#define __lcd_display_pin_init()
+#endif
+#ifndef __lcd_display_on
+#define __lcd_display_on()
+#endif
+#ifndef __lcd_display_off
+#define __lcd_display_off()
+#endif
+#ifndef __lcd_set_backlight_level
+#define __lcd_set_backlight_level(n)
+#endif
+
diff --git a/package/uboot-xburst/files/cpu/mips/jz_mmc.c b/package/uboot-xburst/files/cpu/mips/jz_mmc.c
new file mode 100644
index 000000000..b3c4e9960
--- /dev/null
+++ b/package/uboot-xburst/files/cpu/mips/jz_mmc.c
@@ -0,0 +1,1416 @@
+/*
+ * (C) Copyright 2003
+ * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <config.h>
+#include <common.h>
+#include <part.h>
+
+#if defined CONFIG_JZ4740
+#include <asm-mips/jz4740.h>
+
+#include "jz_mmc.h"
+
+#define CFG_MMC_BASE 0x80600000
+static int sd2_0 = 0;
+
+/*
+ * GPIO definition
+ */
+#if defined(CONFIG_SAKC)
+
+#define __msc_init_io() \
+do { \
+ __gpio_as_input(GPIO_SD_CD_N); \
+} while (0)
+
+#else
+#define __msc_init_io() \
+do { \
+ __gpio_as_output(GPIO_SD_VCC_EN_N); \
+ __gpio_as_input(GPIO_SD_CD_N); \
+} while (0)
+
+#define __msc_enable_power() \
+do { \
+ __gpio_clear_pin(GPIO_SD_VCC_EN_N); \
+} while (0)
+
+#define __msc_disable_power() \
+do { \
+ __gpio_set_pin(GPIO_SD_VCC_EN_N); \
+} while (0)
+
+#endif /* CONFIG_SAKE */
+
+#define __msc_card_detected() \
+({ \
+ int detected = 1; \
+ __gpio_as_input(GPIO_SD_CD_N); \
+ __gpio_disable_pull(GPIO_SD_CD_N); \
+ if (!__gpio_get_pin(GPIO_SD_CD_N)) \
+ detected = 0; \
+ detected; \
+})
+
+/*
+ * Local functions
+ */
+
+#ifdef CONFIG_MMC
+extern int
+fat_register_device(block_dev_desc_t *dev_desc, int part_no);
+
+static block_dev_desc_t mmc_dev;
+
+block_dev_desc_t * mmc_get_dev(int dev)
+{
+ return ((block_dev_desc_t *)&mmc_dev);
+}
+
+/*
+ * FIXME needs to read cid and csd info to determine block size
+ * and other parameters
+ */
+static uchar mmc_buf[MMC_BLOCK_SIZE];
+static int mmc_ready = 0;
+static mmc_csd_t mmc_csd;
+static int use_4bit; /* Use 4-bit data bus */
+/*
+ * MMC Events
+ */
+#define MMC_EVENT_NONE 0x00 /* No events */
+#define MMC_EVENT_RX_DATA_DONE 0x01 /* Rx data done */
+#define MMC_EVENT_TX_DATA_DONE 0x02 /* Tx data done */
+#define MMC_EVENT_PROG_DONE 0x04 /* Programming is done */
+
+
+#define MMC_IRQ_MASK() \
+do { \
+ REG_MSC_IMASK = 0xffff; \
+ REG_MSC_IREG = 0xffff; \
+} while (0)
+
+/* Stop the MMC clock and wait while it happens */
+static inline int jz_mmc_stop_clock(void)
+{
+ int timeout = 1000;
+
+ REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_STOP;
+
+ while (timeout && (REG_MSC_STAT & MSC_STAT_CLK_EN)) {
+ timeout--;
+ if (timeout == 0) {
+ return MMC_ERROR_TIMEOUT;
+ }
+ udelay(1);
+ }
+ return MMC_NO_ERROR;
+}
+
+/* Start the MMC clock and operation */
+static inline int jz_mmc_start_clock(void)
+{
+ REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_START | MSC_STRPCL_START_OP;
+ return MMC_NO_ERROR;
+}
+
+static inline u32 jz_mmc_calc_clkrt(int is_sd, u32 rate)
+{
+ u32 clkrt;
+ u32 clk_src = is_sd ? 24000000: 16000000;
+
+ clkrt = 0;
+ while (rate < clk_src)
+ {
+ clkrt ++;
+ clk_src >>= 1;
+ }
+ return clkrt;
+}
+
+/* Set the MMC clock frequency */
+void jz_mmc_set_clock(int sd, u32 rate)
+{
+ jz_mmc_stop_clock();
+
+ /* Select clock source of MSC */
+ __cpm_select_msc_clk(sd);
+
+ /* Set clock dividor of MSC */
+ REG_MSC_CLKRT = jz_mmc_calc_clkrt(sd, rate);
+}
+
+static int jz_mmc_check_status(struct mmc_request *request)
+{
+ u32 status = REG_MSC_STAT;
+
+ /* Checking for response or data timeout */
+ if (status & (MSC_STAT_TIME_OUT_RES | MSC_STAT_TIME_OUT_READ)) {
+ printf("MMC/SD timeout, MMC_STAT 0x%x CMD %d\n", status, request->cmd);
+ return MMC_ERROR_TIMEOUT;
+ }
+
+ /* Checking for CRC error */
+ if (status & (MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR | MSC_STAT_CRC_RES_ERR)) {
+ printf("MMC/CD CRC error, MMC_STAT 0x%x\n", status);
+ return MMC_ERROR_CRC;
+ }
+
+ return MMC_NO_ERROR;
+}
+
+/* Obtain response to the command and store it to response buffer */
+static void jz_mmc_get_response(struct mmc_request *request)
+{
+ int i;
+ u8 *buf;
+ u32 data;
+
+ DEBUG(3, "fetch response for request %d, cmd %d\n", request->rtype, request->cmd);
+
+ buf = request->response;
+ request->result = MMC_NO_ERROR;
+
+ switch (request->rtype) {
+ case RESPONSE_R1: case RESPONSE_R1B: case RESPONSE_R6:
+ case RESPONSE_R3: case RESPONSE_R4: case RESPONSE_R5:
+ {
+ data = REG_MSC_RES;
+ buf[0] = (data >> 8) & 0xff;
+ buf[1] = data & 0xff;
+ data = REG_MSC_RES;
+ buf[2] = (data >> 8) & 0xff;
+ buf[3] = data & 0xff;
+ data = REG_MSC_RES;
+ buf[4] = data & 0xff;
+
+ DEBUG(3, "request %d, response [%02x %02x %02x %02x %02x]\n",
+ request->rtype, buf[0], buf[1], buf[2], buf[3], buf[4]);
+ break;
+ }
+ case RESPONSE_R2_CID: case RESPONSE_R2_CSD:
+ {
+ for (i = 0; i < 16; i += 2) {
+ data = REG_MSC_RES;
+ buf[i] = (data >> 8) & 0xff;
+ buf[i+1] = data & 0xff;
+ }
+ DEBUG(3, "request %d, response [", request->rtype);
+#if CONFIG_MMC_DEBUG_VERBOSE > 2
+ if (g_mmc_debug >= 3) {
+ int n;
+ for (n = 0; n < 17; n++)
+ printk("%02x ", buf[n]);
+ printk("]\n");
+ }
+#endif
+ break;
+ }
+ case RESPONSE_NONE:
+ DEBUG(3, "No response\n");
+ break;
+
+ default:
+ DEBUG(3, "unhandled response type for request %d\n", request->rtype);
+ break;
+ }
+}
+
+static int jz_mmc_receive_data(struct mmc_request *req)
+{
+ u32 stat, timeout, data, cnt;
+ u8 *buf = req->buffer;
+ u32 wblocklen = (u32)(req->block_len + 3) >> 2; /* length in word */
+
+ timeout = 0x3ffffff;
+
+ while (timeout) {
+ timeout--;
+ stat = REG_MSC_STAT;
+
+ if (stat & MSC_STAT_TIME_OUT_READ)
+ return MMC_ERROR_TIMEOUT;
+ else if (stat & MSC_STAT_CRC_READ_ERROR)
+ return MMC_ERROR_CRC;
+ else if (!(stat & MSC_STAT_DATA_FIFO_EMPTY)
+ || (stat & MSC_STAT_DATA_FIFO_AFULL)) {
+ /* Ready to read data */
+ break;
+ }
+ udelay(1);
+ }
+ if (!timeout)
+ return MMC_ERROR_TIMEOUT;
+
+ /* Read data from RXFIFO. It could be FULL or PARTIAL FULL */
+ cnt = wblocklen;
+ while (cnt) {
+ data = REG_MSC_RXFIFO;
+ {
+ *buf++ = (u8)(data >> 0);
+ *buf++ = (u8)(data >> 8);
+ *buf++ = (u8)(data >> 16);
+ *buf++ = (u8)(data >> 24);
+ }
+ cnt --;
+ while (cnt && (REG_MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY))
+ ;
+ }
+ return MMC_NO_ERROR;
+}
+
+static int jz_mmc_transmit_data(struct mmc_request *req)
+{
+#if 0
+ u32 nob = req->nob;
+ u32 wblocklen = (u32)(req->block_len + 3) >> 2; /* length in word */
+ u8 *buf = req->buffer;
+ u32 *wbuf = (u32 *)buf;
+ u32 waligned = (((u32)buf & 0x3) == 0); /* word aligned ? */
+ u32 stat, timeout, data, cnt;
+
+ for (nob; nob >= 1; nob--) {
+ timeout = 0x3FFFFFF;
+
+ while (timeout) {
+ timeout--;
+ stat = REG_MSC_STAT;
+
+ if (stat & (MSC_STAT_CRC_WRITE_ERROR | MSC_STAT_CRC_WRITE_ERROR_NOSTS))
+ return MMC_ERROR_CRC;
+ else if (!(stat & MSC_STAT_DATA_FIFO_FULL)) {
+ /* Ready to write data */
+ break;
+ }
+
+ udelay(1);
+ }
+
+ if (!timeout)
+ return MMC_ERROR_TIMEOUT;
+
+ /* Write data to TXFIFO */
+ cnt = wblocklen;
+ while (cnt) {
+ while (REG_MSC_STAT & MSC_STAT_DATA_FIFO_FULL)
+ ;
+
+ if (waligned) {
+ REG_MSC_TXFIFO = *wbuf++;
+ }
+ else {
+ data = *buf++ | (*buf++ << 8) | (*buf++ << 16) | (*buf++ << 24);
+ REG_MSC_TXFIFO = data;
+ }
+
+ cnt--;
+ }
+ }
+#endif
+ return MMC_NO_ERROR;
+}
+
+
+/*
+ * Name: int jz_mmc_exec_cmd()
+ * Function: send command to the card, and get a response
+ * Input: struct mmc_request *req : MMC/SD request
+ * Output: 0: right >0: error code
+ */
+int jz_mmc_exec_cmd(struct mmc_request *request)
+{
+ u32 cmdat = 0, events = 0;
+ int retval, timeout = 0x3fffff;
+
+ /* Indicate we have no result yet */
+ request->result = MMC_NO_RESPONSE;
+ if (request->cmd == MMC_CIM_RESET) {
+ /* On reset, 1-bit bus width */
+ use_4bit = 0;
+
+ /* Reset MMC/SD controller */
+ __msc_reset();
+
+ /* On reset, drop MMC clock down */
+ jz_mmc_set_clock(0, MMC_CLOCK_SLOW);
+
+ /* On reset, stop MMC clock */
+ jz_mmc_stop_clock();
+ }
+ if (request->cmd == MMC_SEND_OP_COND) {
+ DEBUG(3, "Have an MMC card\n");
+ /* always use 1bit for MMC */
+ use_4bit = 0;
+ }
+ if (request->cmd == SET_BUS_WIDTH) {
+ if (request->arg == 0x2) {
+ printf("Use 4-bit bus width\n");
+ use_4bit = 1;
+ }
+ else {
+ printf("Use 1-bit bus width\n");
+ use_4bit = 0;
+ }
+ }
+
+ /* stop clock */
+ jz_mmc_stop_clock();
+
+ /* mask all interrupts */
+ REG_MSC_IMASK = 0xffff;
+
+ /* clear status */
+ REG_MSC_IREG = 0xffff;
+
+ /* use 4-bit bus width when possible */
+ if (use_4bit)
+ cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT;
+
+ /* Set command type and events */
+ switch (request->cmd) {
+ /* MMC core extra command */
+ case MMC_CIM_RESET:
+ cmdat |= MSC_CMDAT_INIT; /* Initialization sequence sent prior to command */
+ break;
+
+ /* bc - broadcast - no response */
+ case MMC_GO_IDLE_STATE:
+ case MMC_SET_DSR:
+ break;
+
+ /* bcr - broadcast with response */
+ case MMC_SEND_OP_COND:
+ case MMC_ALL_SEND_CID:
+ case MMC_GO_IRQ_STATE:
+ break;
+
+ /* adtc - addressed with data transfer */
+ case MMC_READ_DAT_UNTIL_STOP:
+ case MMC_READ_SINGLE_BLOCK:
+ case MMC_READ_MULTIPLE_BLOCK:
+ case SEND_SCR:
+ cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_READ;
+ events = MMC_EVENT_RX_DATA_DONE;
+ break;
+
+ case MMC_WRITE_DAT_UNTIL_STOP:
+ case MMC_WRITE_BLOCK:
+ case MMC_WRITE_MULTIPLE_BLOCK:
+ case MMC_PROGRAM_CID:
+ case MMC_PROGRAM_CSD:
+ case MMC_SEND_WRITE_PROT:
+ case MMC_GEN_CMD:
+ case MMC_LOCK_UNLOCK:
+ cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_WRITE;
+ events = MMC_EVENT_TX_DATA_DONE | MMC_EVENT_PROG_DONE;
+
+ break;
+
+ case MMC_STOP_TRANSMISSION:
+ events = MMC_EVENT_PROG_DONE;
+ break;
+
+ /* ac - no data transfer */
+ default:
+ break;
+ }
+
+ /* Set response type */
+ switch (request->rtype) {
+ case RESPONSE_NONE:
+ break;
+
+ case RESPONSE_R1B:
+ cmdat |= MSC_CMDAT_BUSY;
+ /*FALLTHRU*/
+ case RESPONSE_R1:
+ cmdat |= MSC_CMDAT_RESPONSE_R1;
+ break;
+ case RESPONSE_R2_CID:
+ case RESPONSE_R2_CSD:
+ cmdat |= MSC_CMDAT_RESPONSE_R2;
+ break;
+ case RESPONSE_R3:
+ cmdat |= MSC_CMDAT_RESPONSE_R3;
+ break;
+ case RESPONSE_R4:
+ cmdat |= MSC_CMDAT_RESPONSE_R4;
+ break;
+ case RESPONSE_R5:
+ cmdat |= MSC_CMDAT_RESPONSE_R5;
+ break;
+ case RESPONSE_R6:
+ cmdat |= MSC_CMDAT_RESPONSE_R6;
+ break;
+ default:
+ break;
+ }
+
+ /* Set command index */
+ if (request->cmd == MMC_CIM_RESET) {
+ REG_MSC_CMD = MMC_GO_IDLE_STATE;
+ } else {
+ REG_MSC_CMD = request->cmd;
+ }
+
+ /* Set argument */
+ REG_MSC_ARG = request->arg;
+
+ /* Set block length and nob */
+ if (request->cmd == SEND_SCR) { /* get SCR from DataFIFO */
+ REG_MSC_BLKLEN = 8;
+ REG_MSC_NOB = 1;
+ } else {
+ REG_MSC_BLKLEN = request->block_len;
+ REG_MSC_NOB = request->nob;
+ }
+
+ /* Set command */
+ REG_MSC_CMDAT = cmdat;
+
+ DEBUG(1, "Send cmd %d cmdat: %x arg: %x resp %d\n", request->cmd,
+ cmdat, request->arg, request->rtype);
+
+ /* Start MMC/SD clock and send command to card */
+ jz_mmc_start_clock();
+
+ /* Wait for command completion */
+ while (timeout-- && !(REG_MSC_STAT & MSC_STAT_END_CMD_RES))
+ ;
+
+ if (timeout == 0)
+ return MMC_ERROR_TIMEOUT;
+
+ REG_MSC_IREG = MSC_IREG_END_CMD_RES; /* clear flag */
+
+ /* Check for status */
+ retval = jz_mmc_check_status(request);
+ if (retval) {
+ return retval;
+ }
+
+ /* Complete command with no response */
+ if (request->rtype == RESPONSE_NONE) {
+ return MMC_NO_ERROR;
+ }
+
+ /* Get response */
+ jz_mmc_get_response(request);
+
+ /* Start data operation */
+ if (events & (MMC_EVENT_RX_DATA_DONE | MMC_EVENT_TX_DATA_DONE)) {
+ if (events & MMC_EVENT_RX_DATA_DONE) {
+ if (request->cmd == SEND_SCR) {
+ /* SD card returns SCR register as data.
+ MMC core expect it in the response buffer,
+ after normal response. */
+ request->buffer = (u8 *)((u32)request->response + 5);
+ }
+ jz_mmc_receive_data(request);
+ }
+
+ if (events & MMC_EVENT_TX_DATA_DONE) {
+ jz_mmc_transmit_data(request);
+ }
+
+ /* Wait for Data Done */
+ while (!(REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE))
+ ;
+ REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE; /* clear status */
+ }
+
+ /* Wait for Prog Done event */
+ if (events & MMC_EVENT_PROG_DONE) {
+ while (!(REG_MSC_IREG & MSC_IREG_PRG_DONE))
+ ;
+ REG_MSC_IREG = MSC_IREG_PRG_DONE; /* clear status */
+ }
+
+ /* Command completed */
+
+ return MMC_NO_ERROR; /* return successfully */
+}
+
+int mmc_block_read(u8 *dst, ulong src, ulong len)
+{
+
+ struct mmc_request request;
+ struct mmc_response_r1 r1;
+ int retval;
+
+ if (len == 0) {
+ return 0;
+ }
+ mmc_simple_cmd(&request, MMC_SEND_STATUS, mmcinfo.rca, RESPONSE_R1);
+ retval = mmc_unpack_r1(&request, &r1, 0);
+ if (retval && (retval != MMC_ERROR_STATE_MISMATCH)) {
+ return retval;
+ }
+
+ mmc_simple_cmd(&request, MMC_SET_BLOCKLEN, len, RESPONSE_R1);
+ if ((retval = mmc_unpack_r1(&request, &r1, 0))) {
+ return retval;
+ }
+
+ if (sd2_0)
+ src /= len;
+
+ mmc_send_cmd(&request, MMC_READ_SINGLE_BLOCK, src, 1,len, RESPONSE_R1, dst);
+ if ((retval = mmc_unpack_r1(&request, &r1, 0))) {
+ return retval;
+ }
+ return retval;
+}
+
+int mmc_block_write(ulong dst, uchar *src, int len)
+{
+ return 0;
+}
+
+int mmc_read(ulong src, uchar *dst, int size)
+{
+ ulong end, part_start, part_end, part_len, aligned_start, aligned_end;
+ ulong mmc_block_size, mmc_block_address;
+
+ if (size == 0) {
+ return 0;
+ }
+
+ if (!mmc_ready) {
+ printf("MMC card is not ready\n");
+ return -1;
+ }
+
+ mmc_block_size = MMC_BLOCK_SIZE;
+ mmc_block_address = ~(mmc_block_size - 1);
+
+ src -= CFG_MMC_BASE;
+ end = src + size;
+ part_start = ~mmc_block_address & src;
+ part_end = ~mmc_block_address & end;
+ aligned_start = mmc_block_address & src;
+ aligned_end = mmc_block_address & end;
+ /* all block aligned accesses */
+ debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
+ src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+ if (part_start) {
+ part_len = mmc_block_size - part_start;
+ debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
+ src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+ if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0) {
+ return -1;
+ }
+ memcpy(dst, mmc_buf+part_start, part_len);
+ dst += part_len;
+ src += part_len;
+ }
+ debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
+ src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+ for (; src < aligned_end; src += mmc_block_size, dst += mmc_block_size) {
+ debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
+ src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+
+ if ((mmc_block_read((uchar *)(dst), src, mmc_block_size)) < 0) {
+ return -1;
+ }
+ }
+ debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
+ src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+
+ if (part_end && src < end) {
+ if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0) {
+ return -1;
+ }
+ memcpy(dst, mmc_buf, part_end);
+ }
+ return 0;
+
+}
+
+int mmc_write(uchar *src, ulong dst, int size)
+{
+ ulong end, part_start, part_end, part_len, aligned_start, aligned_end;
+ ulong mmc_block_size, mmc_block_address;
+
+ if (size == 0) {
+ return 0;
+ }
+
+ if (!mmc_ready) {
+ printf("MMC card is not ready\n");
+ return -1;
+ }
+
+ mmc_block_size = MMC_BLOCK_SIZE;
+ mmc_block_address = ~(mmc_block_size - 1);
+
+ dst -= CFG_MMC_BASE;
+ end = dst + size;
+ part_start = ~mmc_block_address & dst;
+ part_end = ~mmc_block_address & end;
+ aligned_start = mmc_block_address & dst;
+ aligned_end = mmc_block_address & end;
+
+ /* all block aligned accesses */
+ debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
+ src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+ if (part_start) {
+ part_len = mmc_block_size - part_start;
+ debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
+ (ulong)src, dst, end, part_start, part_end, aligned_start, aligned_end);
+ if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0) {
+ return -1;
+ }
+ memcpy(mmc_buf+part_start, src, part_len);
+ if ((mmc_block_write(aligned_start, mmc_buf, mmc_block_size)) < 0) {
+ return -1;
+ }
+ dst += part_len;
+ src += part_len;
+ }
+ debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
+ src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+ for (; dst < aligned_end; src += mmc_block_size, dst += mmc_block_size) {
+ debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
+ src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+ if ((mmc_block_write(dst, (uchar *)src, mmc_block_size)) < 0) {
+ return -1;
+ }
+ }
+ debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
+ src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+ if (part_end && dst < end) {
+ debug("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
+ src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+ if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0) {
+ return -1;
+ }
+ memcpy(mmc_buf, src, part_end);
+ if ((mmc_block_write(aligned_end, mmc_buf, mmc_block_size)) < 0) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+ulong mmc_bread(int dev_num, ulong blknr, ulong blkcnt, ulong *dst)
+{
+ ulong src;
+ int mmc_block_size = MMC_BLOCK_SIZE;
+
+ src = blknr * mmc_block_size + CFG_MMC_BASE;
+ mmc_read(src, (uchar *)dst, blkcnt*mmc_block_size);
+ return blkcnt;
+}
+
+int mmc_select_card(void)
+{
+ struct mmc_request request;
+ struct mmc_response_r1 r1;
+ int retval;
+
+ mmc_simple_cmd(&request, MMC_SELECT_CARD, mmcinfo.rca, RESPONSE_R1B);
+ retval = mmc_unpack_r1(&request, &r1, 0);
+ if (retval) {
+ return retval;
+ }
+
+ if (mmcinfo.sd) {
+ mmc_simple_cmd(&request, MMC_APP_CMD, mmcinfo.rca, RESPONSE_R1);
+ retval = mmc_unpack_r1(&request,&r1,0);
+ if (retval) {
+ return retval;
+ }
+#if defined(MMC_BUS_WIDTH_1BIT)
+ mmc_simple_cmd(&request, SET_BUS_WIDTH, 1, RESPONSE_R1);
+#else
+ mmc_simple_cmd(&request, SET_BUS_WIDTH, 2, RESPONSE_R1);
+#endif
+ retval = mmc_unpack_r1(&request,&r1,0);
+ if (retval) {
+ return retval;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Configure card
+ */
+static void mmc_configure_card(void)
+{
+ u32 rate;
+
+ /* Get card info */
+ if (sd2_0)
+ mmcinfo.block_num = (mmcinfo.csd.c_size + 1) << 10;
+ else
+ mmcinfo.block_num = (mmcinfo.csd.c_size + 1) * (1 << (mmcinfo.csd.c_size_mult + 2));
+
+ mmcinfo.block_len = 1 << mmcinfo.csd.read_bl_len;
+
+ /* Fix the clock rate */
+ rate = mmc_tran_speed(mmcinfo.csd.tran_speed);
+ if (rate < MMC_CLOCK_SLOW)
+ rate = MMC_CLOCK_SLOW;
+ if ((mmcinfo.sd == 0) && (rate > MMC_CLOCK_FAST))
+ rate = MMC_CLOCK_FAST;
+ if ((mmcinfo.sd) && (rate > SD_CLOCK_FAST))
+ rate = SD_CLOCK_FAST;
+
+ DEBUG(2,"mmc_configure_card: block_len=%d block_num=%d rate=%d\n", mmcinfo.block_len, mmcinfo.block_num, rate);
+
+ jz_mmc_set_clock(mmcinfo.sd, rate);
+}
+
+/*
+ * State machine routines to initialize card(s)
+ */
+
+/*
+ CIM_SINGLE_CARD_ACQ (frequency at 400 kHz)
+ --- Must enter from GO_IDLE_STATE ---
+ 1. SD_SEND_OP_COND (SD Card) [CMD55] + [CMD41]
+ 2. SEND_OP_COND (Full Range) [CMD1] {optional}
+ 3. SEND_OP_COND (Set Range ) [CMD1]
+ If busy, delay and repeat step 2
+ 4. ALL_SEND_CID [CMD2]
+ If timeout, set an error (no cards found)
+ 5. SET_RELATIVE_ADDR [CMD3]
+ 6. SEND_CSD [CMD9]
+ 7. SET_DSR [CMD4] Only call this if (csd.dsr_imp).
+ 8. Set clock frequency (check available in csd.tran_speed)
+ */
+
+#define MMC_INIT_DOING 0
+#define MMC_INIT_PASSED 1
+#define MMC_INIT_FAILED 2
+
+static int mmc_init_card_state(struct mmc_request *request)
+{
+ struct mmc_response_r1 r1;
+ struct mmc_response_r3 r3;
+ int retval;
+ int ocr = 0x40300000;
+ int limit_41 = 0;
+
+ DEBUG(2,"mmc_init_card_state\n");
+
+ switch (request->cmd) {
+ case MMC_GO_IDLE_STATE: /* No response to parse */
+ if (mmcinfo.sd)
+ mmc_simple_cmd(request, 8, 0x1aa, RESPONSE_R1);
+ else
+ mmc_simple_cmd(request, MMC_SEND_OP_COND, MMC_OCR_ARG, RESPONSE_R3);
+ break;
+
+ case 8:
+ retval = mmc_unpack_r1(request,&r1,mmcinfo.state);
+ mmc_simple_cmd(request, MMC_APP_CMD, 0, RESPONSE_R1);
+ break;
+
+ case MMC_APP_CMD:
+ retval = mmc_unpack_r1(request,&r1,mmcinfo.state);
+ if (retval & (limit_41 < 100)) {
+ DEBUG(0, "mmc_init_card_state: unable to MMC_APP_CMD error=%d (%s)\n",
+ retval, mmc_result_to_string(retval));
+ limit_41++;
+ mmc_simple_cmd(request, SD_SEND_OP_COND, ocr, RESPONSE_R3);
+ } else if (limit_41 < 100) {
+ limit_41++;
+ mmc_simple_cmd(request, SD_SEND_OP_COND, ocr, RESPONSE_R3);
+ } else{
+ /* reset the card to idle*/
+ mmc_simple_cmd(request, MMC_GO_IDLE_STATE, 0, RESPONSE_NONE);
+ mmcinfo.sd = 0;
+ }
+ break;
+
+ case SD_SEND_OP_COND:
+ retval = mmc_unpack_r3(request, &r3);
+ if (retval) {
+ /* Try MMC card */
+ mmc_simple_cmd(request, MMC_SEND_OP_COND, MMC_OCR_ARG, RESPONSE_R3);
+ break;
+ }
+
+ DEBUG(2,"mmc_init_card_state: read ocr value = 0x%08x\n", r3.ocr);
+
+ if(!(r3.ocr & MMC_CARD_BUSY || ocr == 0)){
+ udelay(10000);
+ mmc_simple_cmd(request, MMC_APP_CMD, 0, RESPONSE_R1);
+ }
+ else {
+ /* Set the data bus width to 4 bits */
+ mmcinfo.sd = 1; /* SD Card ready */
+ mmcinfo.state = CARD_STATE_READY;
+ mmc_simple_cmd(request, MMC_ALL_SEND_CID, 0, RESPONSE_R2_CID);
+ }
+ break;
+
+ case MMC_SEND_OP_COND:
+ retval = mmc_unpack_r3(request, &r3);
+ if (retval) {
+ DEBUG(0,"mmc_init_card_state: failed SEND_OP_COND error=%d (%s)\n",
+ retval, mmc_result_to_string(retval));
+ return MMC_INIT_FAILED;
+ }
+
+ DEBUG(2,"mmc_init_card_state: read ocr value = 0x%08x\n", r3.ocr);
+ if (!(r3.ocr & MMC_CARD_BUSY)) {
+ mmc_simple_cmd(request, MMC_SEND_OP_COND, MMC_OCR_ARG, RESPONSE_R3);
+ }
+ else {
+ mmcinfo.sd = 0; /* MMC Card ready */
+ mmcinfo.state = CARD_STATE_READY;
+ mmc_simple_cmd(request, MMC_ALL_SEND_CID, 0, RESPONSE_R2_CID);
+ }
+ break;
+
+ case MMC_ALL_SEND_CID:
+ retval = mmc_unpack_cid( request, &mmcinfo.cid );
+ mmc_dev.if_type = IF_TYPE_MMC;
+ mmc_dev.part_type = PART_TYPE_DOS;
+ mmc_dev.dev = 0;
+ mmc_dev.lun = 0;
+ mmc_dev.type = 0;
+ /* FIXME fill in the correct size (is set to 32MByte) */
+ mmc_dev.blksz = 512;
+ mmc_dev.lba = 0x10000;
+ mmc_dev.removable = 0;
+
+ /*FIXME:ignore CRC error for CMD2/CMD9/CMD10 */
+ if ( retval && (retval != MMC_ERROR_CRC)) {
+ DEBUG(0,"mmc_init_card_state: unable to ALL_SEND_CID error=%d (%s)\n",
+ retval, mmc_result_to_string(retval));
+ return MMC_INIT_FAILED;
+ }
+ mmcinfo.state = CARD_STATE_IDENT;
+ if(mmcinfo.sd)
+ mmc_simple_cmd(request, MMC_SET_RELATIVE_ADDR, 0, RESPONSE_R6);
+ else
+ mmc_simple_cmd(request, MMC_SET_RELATIVE_ADDR, ID_TO_RCA(mmcinfo.id) << 16, RESPONSE_R1);
+ break;
+
+ case MMC_SET_RELATIVE_ADDR:
+ if (mmcinfo.sd) {
+ retval = mmc_unpack_r6(request, &r1, mmcinfo.state, &mmcinfo.rca);
+ mmcinfo.rca = mmcinfo.rca << 16;
+ DEBUG(2, "mmc_init_card_state: Get RCA from SD: 0x%04x Status: %x\n", mmcinfo.rca, r1.status);
+ } else {
+ retval = mmc_unpack_r1(request,&r1,mmcinfo.state);
+ mmcinfo.rca = ID_TO_RCA(mmcinfo.id) << 16;
+ }
+ if (retval) {
+ DEBUG(0, "mmc_init_card_state: unable to SET_RELATIVE_ADDR error=%d (%s)\n",
+ retval, mmc_result_to_string(retval));
+ return MMC_INIT_FAILED;
+ }
+
+ mmcinfo.state = CARD_STATE_STBY;
+ mmc_simple_cmd(request, MMC_SEND_CSD, mmcinfo.rca, RESPONSE_R2_CSD);
+
+ break;
+
+ case MMC_SEND_CSD:
+ retval = mmc_unpack_csd(request, &mmcinfo.csd);
+ mmc_csd_t *csd = (mmc_csd_t *)retval;
+ memcpy(&mmc_csd, csd, sizeof(csd));
+ mmc_ready = 1;
+
+ printf("MMC card is ready\n");
+ /* FIXME add verbose printout for csd */
+
+ /*FIXME:ignore CRC error for CMD2/CMD9/CMD10 */
+ if (retval && (retval != MMC_ERROR_CRC)) {
+ DEBUG(0, "mmc_init_card_state: unable to SEND_CSD error=%d (%s)\n",
+ retval, mmc_result_to_string(retval));
+ return MMC_INIT_FAILED;
+ }
+ if (mmcinfo.csd.dsr_imp) {
+ DEBUG(0, "mmc_init_card_state: driver doesn't support setting DSR\n");
+ }
+ mmc_configure_card();
+ return MMC_INIT_PASSED;
+
+ default:
+ DEBUG(0, "mmc_init_card_state: error! Illegal last cmd %d\n", request->cmd);
+ return MMC_INIT_FAILED;
+ }
+
+ return MMC_INIT_DOING;
+}
+
+int mmc_init_card(void)
+{
+ struct mmc_request request;
+ int retval;
+
+ mmc_simple_cmd(&request, MMC_CIM_RESET, 0, RESPONSE_NONE); /* reset card */
+ mmc_simple_cmd(&request, MMC_GO_IDLE_STATE, 0, RESPONSE_NONE);
+ mmcinfo.sd = 1; /* assuming a SD card */
+
+ while ((retval = mmc_init_card_state(&request)) == MMC_INIT_DOING)
+ ;
+
+ if (retval == MMC_INIT_PASSED)
+ return MMC_NO_ERROR;
+ else
+ return MMC_NO_RESPONSE;
+}
+
+int mmc_legacy_init(int verbose)
+{
+ if (!__msc_card_detected())
+ return 1;
+
+ printf("MMC card found\n");
+
+ /* Step-1: init GPIO */
+ __gpio_as_msc();
+
+ __msc_init_io();
+
+ /* Step-2: turn on power of card */
+#if !defined(CONFIG_SAKC)
+ __msc_enable_power();
+#endif
+
+ /* Step-3: Reset MSC Controller. */
+ __msc_reset();
+
+ /* Step-3: mask all IRQs. */
+ MMC_IRQ_MASK();
+
+ /* Step-4: stop MMC/SD clock */
+ jz_mmc_stop_clock();
+ mmc_init_card();
+ mmc_select_card();
+
+ mmc_dev.block_read = mmc_bread;
+ fat_register_device(&mmc_dev,1); /* partitions start counting with 1 */
+
+ return 0;
+}
+
+int mmc_ident(block_dev_desc_t *dev)
+{
+ return 0;
+}
+
+int mmc2info(ulong addr)
+{
+ /* FIXME hard codes to 32 MB device */
+ if (addr >= CFG_MMC_BASE && addr < CFG_MMC_BASE + 0x02000000) {
+ return 1;
+ }
+ return 0;
+}
+/*
+ * Debugging functions
+ */
+
+static char * mmc_result_strings[] = {
+ "NO_RESPONSE",
+ "NO_ERROR",
+ "ERROR_OUT_OF_RANGE",
+ "ERROR_ADDRESS",
+ "ERROR_BLOCK_LEN",
+ "ERROR_ERASE_SEQ",
+ "ERROR_ERASE_PARAM",
+ "ERROR_WP_VIOLATION",
+ "ERROR_CARD_IS_LOCKED",
+ "ERROR_LOCK_UNLOCK_FAILED",
+ "ERROR_COM_CRC",
+ "ERROR_ILLEGAL_COMMAND",
+ "ERROR_CARD_ECC_FAILED",
+ "ERROR_CC",
+ "ERROR_GENERAL",
+ "ERROR_UNDERRUN",
+ "ERROR_OVERRUN",
+ "ERROR_CID_CSD_OVERWRITE",
+ "ERROR_STATE_MISMATCH",
+ "ERROR_HEADER_MISMATCH",
+ "ERROR_TIMEOUT",
+ "ERROR_CRC",
+ "ERROR_DRIVER_FAILURE",
+};
+
+char * mmc_result_to_string(int i)
+{
+ return mmc_result_strings[i+1];
+}
+
+static char * card_state_strings[] = {
+ "empty",
+ "idle",
+ "ready",
+ "ident",
+ "stby",
+ "tran",
+ "data",
+ "rcv",
+ "prg",
+ "dis",
+};
+
+static inline char * card_state_to_string(int i)
+{
+ return card_state_strings[i+1];
+}
+
+/*
+ * Utility functions
+ */
+
+#define PARSE_U32(_buf,_index) \
+ (((u32)_buf[_index]) << 24) | (((u32)_buf[_index+1]) << 16) | \
+ (((u32)_buf[_index+2]) << 8) | ((u32)_buf[_index+3]);
+
+#define PARSE_U16(_buf,_index) \
+ (((u16)_buf[_index]) << 8) | ((u16)_buf[_index+1]);
+
+int mmc_unpack_csd(struct mmc_request *request, struct mmc_csd *csd)
+{
+ u8 *buf = request->response;
+ int num = 0;
+
+ if (request->result)
+ return request->result;
+
+ csd->csd_structure = (buf[1] & 0xc0) >> 6;
+ if (csd->csd_structure)
+ sd2_0 = 1;
+ else
+ sd2_0 = 0;
+
+ switch (csd->csd_structure) {
+ case 0 :
+ csd->taac = buf[2];
+ csd->nsac = buf[3];
+ csd->tran_speed = buf[4];
+ csd->ccc = (((u16)buf[5]) << 4) | ((buf[6] & 0xf0) >> 4);
+ csd->read_bl_len = buf[6] & 0x0f;
+ /* for support 2GB card*/
+ if (csd->read_bl_len >= 10)
+ {
+ num = csd->read_bl_len - 9;
+ csd->read_bl_len = 9;
+ }
+
+ csd->read_bl_partial = (buf[7] & 0x80) ? 1 : 0;
+ csd->write_blk_misalign = (buf[7] & 0x40) ? 1 : 0;
+ csd->read_blk_misalign = (buf[7] & 0x20) ? 1 : 0;
+ csd->dsr_imp = (buf[7] & 0x10) ? 1 : 0;
+ csd->c_size = ((((u16)buf[7]) & 0x03) << 10) | (((u16)buf[8]) << 2) | (((u16)buf[9]) & 0xc0) >> 6;
+
+ if (num)
+ csd->c_size = csd->c_size << num;
+
+
+ csd->vdd_r_curr_min = (buf[9] & 0x38) >> 3;
+ csd->vdd_r_curr_max = buf[9] & 0x07;
+ csd->vdd_w_curr_min = (buf[10] & 0xe0) >> 5;
+ csd->vdd_w_curr_max = (buf[10] & 0x1c) >> 2;
+ csd->c_size_mult = ((buf[10] & 0x03) << 1) | ((buf[11] & 0x80) >> 7);
+ switch (csd->csd_structure) {
+ case CSD_STRUCT_VER_1_0:
+ case CSD_STRUCT_VER_1_1:
+ csd->erase.v22.sector_size = (buf[11] & 0x7c) >> 2;
+ csd->erase.v22.erase_grp_size = ((buf[11] & 0x03) << 3) | ((buf[12] & 0xe0) >> 5);
+
+ break;
+ case CSD_STRUCT_VER_1_2:
+ default:
+ csd->erase.v31.erase_grp_size = (buf[11] & 0x7c) >> 2;
+ csd->erase.v31.erase_grp_mult = ((buf[11] & 0x03) << 3) | ((buf[12] & 0xe0) >> 5);
+ break;
+ }
+ csd->wp_grp_size = buf[12] & 0x1f;
+ csd->wp_grp_enable = (buf[13] & 0x80) ? 1 : 0;
+ csd->default_ecc = (buf[13] & 0x60) >> 5;
+ csd->r2w_factor = (buf[13] & 0x1c) >> 2;
+ csd->write_bl_len = ((buf[13] & 0x03) << 2) | ((buf[14] & 0xc0) >> 6);
+ if (csd->write_bl_len >= 10)
+ csd->write_bl_len = 9;
+
+ csd->write_bl_partial = (buf[14] & 0x20) ? 1 : 0;
+ csd->file_format_grp = (buf[15] & 0x80) ? 1 : 0;
+ csd->copy = (buf[15] & 0x40) ? 1 : 0;
+ csd->perm_write_protect = (buf[15] & 0x20) ? 1 : 0;
+ csd->tmp_write_protect = (buf[15] & 0x10) ? 1 : 0;
+ csd->file_format = (buf[15] & 0x0c) >> 2;
+ csd->ecc = buf[15] & 0x03;
+
+ DEBUG(2," csd_structure=%d spec_vers=%d taac=%02x nsac=%02x tran_speed=%02x\n"
+ " ccc=%04x read_bl_len=%d read_bl_partial=%d write_blk_misalign=%d\n"
+ " read_blk_misalign=%d dsr_imp=%d c_size=%d vdd_r_curr_min=%d\n"
+ " vdd_r_curr_max=%d vdd_w_curr_min=%d vdd_w_curr_max=%d c_size_mult=%d\n"
+ " wp_grp_size=%d wp_grp_enable=%d default_ecc=%d r2w_factor=%d\n"
+ " write_bl_len=%d write_bl_partial=%d file_format_grp=%d copy=%d\n"
+ " perm_write_protect=%d tmp_write_protect=%d file_format=%d ecc=%d\n",
+ csd->csd_structure, csd->spec_vers,
+ csd->taac, csd->nsac, csd->tran_speed,
+ csd->ccc, csd->read_bl_len,
+ csd->read_bl_partial, csd->write_blk_misalign,
+ csd->read_blk_misalign, csd->dsr_imp,
+ csd->c_size, csd->vdd_r_curr_min,
+ csd->vdd_r_curr_max, csd->vdd_w_curr_min,
+ csd->vdd_w_curr_max, csd->c_size_mult,
+ csd->wp_grp_size, csd->wp_grp_enable,
+ csd->default_ecc, csd->r2w_factor,
+ csd->write_bl_len, csd->write_bl_partial,
+ csd->file_format_grp, csd->copy,
+ csd->perm_write_protect, csd->tmp_write_protect,
+ csd->file_format, csd->ecc);
+ switch (csd->csd_structure) {
+ case CSD_STRUCT_VER_1_0:
+ case CSD_STRUCT_VER_1_1:
+ DEBUG(2," V22 sector_size=%d erase_grp_size=%d\n",
+ csd->erase.v22.sector_size,
+ csd->erase.v22.erase_grp_size);
+ break;
+ case CSD_STRUCT_VER_1_2:
+ default:
+ DEBUG(2," V31 erase_grp_size=%d erase_grp_mult=%d\n",
+ csd->erase.v31.erase_grp_size,
+ csd->erase.v31.erase_grp_mult);
+ break;
+
+ }
+ break;
+
+ case 1 :
+ csd->taac = 0;
+ csd->nsac = 0;
+ csd->tran_speed = buf[4];
+ csd->ccc = (((u16)buf[5]) << 4) | ((buf[6] & 0xf0) >> 4);
+
+ csd->read_bl_len = 9;
+ csd->read_bl_partial = 0;
+ csd->write_blk_misalign = 0;
+ csd->read_blk_misalign = 0;
+ csd->dsr_imp = (buf[7] & 0x10) ? 1 : 0;
+ csd->c_size = ((((u16)buf[8]) & 0x3f) << 16) | (((u16)buf[9]) << 8) | ((u16)buf[10]) ;
+ switch (csd->csd_structure) {
+ case CSD_STRUCT_VER_1_0:
+ case CSD_STRUCT_VER_1_1:
+ csd->erase.v22.sector_size = 0x7f;
+ csd->erase.v22.erase_grp_size = 0;
+ break;
+ case CSD_STRUCT_VER_1_2:
+ default:
+ csd->erase.v31.erase_grp_size = 0x7f;
+ csd->erase.v31.erase_grp_mult = 0;
+ break;
+ }
+ csd->wp_grp_size = 0;
+ csd->wp_grp_enable = 0;
+ csd->default_ecc = (buf[13] & 0x60) >> 5;
+ csd->r2w_factor = 4;/* Unused */
+ csd->write_bl_len = 9;
+
+ csd->write_bl_partial = 0;
+ csd->file_format_grp = 0;
+ csd->copy = (buf[15] & 0x40) ? 1 : 0;
+ csd->perm_write_protect = (buf[15] & 0x20) ? 1 : 0;
+ csd->tmp_write_protect = (buf[15] & 0x10) ? 1 : 0;
+ csd->file_format = 0;
+ csd->ecc = buf[15] & 0x03;
+
+ DEBUG(2," csd_structure=%d spec_vers=%d taac=%02x nsac=%02x tran_speed=%02x\n"
+ " ccc=%04x read_bl_len=%d read_bl_partial=%d write_blk_misalign=%d\n"
+ " read_blk_misalign=%d dsr_imp=%d c_size=%d vdd_r_curr_min=%d\n"
+ " vdd_r_curr_max=%d vdd_w_curr_min=%d vdd_w_curr_max=%d c_size_mult=%d\n"
+ " wp_grp_size=%d wp_grp_enable=%d default_ecc=%d r2w_factor=%d\n"
+ " write_bl_len=%d write_bl_partial=%d file_format_grp=%d copy=%d\n"
+ " perm_write_protect=%d tmp_write_protect=%d file_format=%d ecc=%d\n",
+ csd->csd_structure, csd->spec_vers,
+ csd->taac, csd->nsac, csd->tran_speed,
+ csd->ccc, csd->read_bl_len,
+ csd->read_bl_partial, csd->write_blk_misalign,
+ csd->read_blk_misalign, csd->dsr_imp,
+ csd->c_size, csd->vdd_r_curr_min,
+ csd->vdd_r_curr_max, csd->vdd_w_curr_min,
+ csd->vdd_w_curr_max, csd->c_size_mult,
+ csd->wp_grp_size, csd->wp_grp_enable,
+ csd->default_ecc, csd->r2w_factor,
+ csd->write_bl_len, csd->write_bl_partial,
+ csd->file_format_grp, csd->copy,
+ csd->perm_write_protect, csd->tmp_write_protect,
+ csd->file_format, csd->ecc);
+ switch (csd->csd_structure) {
+ case CSD_STRUCT_VER_1_0:
+ case CSD_STRUCT_VER_1_1:
+ DEBUG(2," V22 sector_size=%d erase_grp_size=%d\n",
+ csd->erase.v22.sector_size,
+ csd->erase.v22.erase_grp_size);
+ break;
+ case CSD_STRUCT_VER_1_2:
+ default:
+ DEBUG(2," V31 erase_grp_size=%d erase_grp_mult=%d\n",
+ csd->erase.v31.erase_grp_size,
+ csd->erase.v31.erase_grp_mult);
+ break;
+ }
+ }
+
+ if (buf[0] != 0x3f) return MMC_ERROR_HEADER_MISMATCH;
+
+ return 0;
+}
+
+int mmc_unpack_r1(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state)
+{
+ u8 *buf = request->response;
+
+ if (request->result) return request->result;
+
+ r1->cmd = buf[0];
+ r1->status = PARSE_U32(buf,1);
+
+ DEBUG(2, "mmc_unpack_r1: cmd=%d status=%08x\n", r1->cmd, r1->status);
+
+ if (R1_STATUS(r1->status)) {
+ if (r1->status & R1_OUT_OF_RANGE) return MMC_ERROR_OUT_OF_RANGE;
+ if (r1->status & R1_ADDRESS_ERROR) return MMC_ERROR_ADDRESS;
+ if (r1->status & R1_BLOCK_LEN_ERROR) return MMC_ERROR_BLOCK_LEN;
+ if (r1->status & R1_ERASE_SEQ_ERROR) return MMC_ERROR_ERASE_SEQ;
+ if (r1->status & R1_ERASE_PARAM) return MMC_ERROR_ERASE_PARAM;
+ if (r1->status & R1_WP_VIOLATION) return MMC_ERROR_WP_VIOLATION;
+ /*if (r1->status & R1_CARD_IS_LOCKED) return MMC_ERROR_CARD_IS_LOCKED; */
+ if (r1->status & R1_LOCK_UNLOCK_FAILED) return MMC_ERROR_LOCK_UNLOCK_FAILED;
+ if (r1->status & R1_COM_CRC_ERROR) return MMC_ERROR_COM_CRC;
+ if (r1->status & R1_ILLEGAL_COMMAND) return MMC_ERROR_ILLEGAL_COMMAND;
+ if (r1->status & R1_CARD_ECC_FAILED) return MMC_ERROR_CARD_ECC_FAILED;
+ if (r1->status & R1_CC_ERROR) return MMC_ERROR_CC;
+ if (r1->status & R1_ERROR) return MMC_ERROR_GENERAL;
+ if (r1->status & R1_UNDERRUN) return MMC_ERROR_UNDERRUN;
+ if (r1->status & R1_OVERRUN) return MMC_ERROR_OVERRUN;
+ if (r1->status & R1_CID_CSD_OVERWRITE) return MMC_ERROR_CID_CSD_OVERWRITE;
+ }
+
+ if (buf[0] != request->cmd) return MMC_ERROR_HEADER_MISMATCH;
+
+ /* This should be last - it's the least dangerous error */
+
+ return 0;
+}
+
+int mmc_unpack_scr(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state, u32 *scr)
+{
+ u8 *buf = request->response;
+ if (request->result) return request->result;
+
+ *scr = PARSE_U32(buf, 5); /* Save SCR returned by the SD Card */
+ return mmc_unpack_r1(request, r1, state);
+
+}
+
+int mmc_unpack_r6(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state, int *rca)
+{
+ u8 *buf = request->response;
+
+ if (request->result) return request->result;
+
+ *rca = PARSE_U16(buf,1); /* Save RCA returned by the SD Card */
+
+ *(buf+1) = 0;
+ *(buf+2) = 0;
+
+ return mmc_unpack_r1(request, r1, state);
+}
+
+int mmc_unpack_cid(struct mmc_request *request, struct mmc_cid *cid)
+{
+ u8 *buf = request->response;
+ int i;
+
+ if (request->result) return request->result;
+
+ cid->mid = buf[1];
+ cid->oid = PARSE_U16(buf,2);
+ for (i = 0 ; i < 6 ; i++)
+ cid->pnm[i] = buf[4+i];
+ cid->pnm[6] = 0;
+ cid->prv = buf[10];
+ cid->psn = PARSE_U32(buf,11);
+ cid->mdt = buf[15];
+
+ DEBUG(2,"mmc_unpack_cid: mid=%d oid=%d pnm=%s prv=%d.%d psn=%08x mdt=%d/%d\n",
+ cid->mid, cid->oid, cid->pnm,
+ (cid->prv>>4), (cid->prv&0xf),
+ cid->psn, (cid->mdt>>4), (cid->mdt&0xf)+1997);
+
+ if (buf[0] != 0x3f) return MMC_ERROR_HEADER_MISMATCH;
+ return 0;
+}
+
+int mmc_unpack_r3(struct mmc_request *request, struct mmc_response_r3 *r3)
+{
+ u8 *buf = request->response;
+
+ if (request->result) return request->result;
+
+ r3->ocr = PARSE_U32(buf,1);
+ DEBUG(2,"mmc_unpack_r3: ocr=%08x\n", r3->ocr);
+
+ if (buf[0] != 0x3f) return MMC_ERROR_HEADER_MISMATCH;
+ return 0;
+}
+
+#define KBPS 1
+#define MBPS 1000
+
+static u32 ts_exp[] = { 100*KBPS, 1*MBPS, 10*MBPS, 100*MBPS, 0, 0, 0, 0 };
+static u32 ts_mul[] = { 0, 1000, 1200, 1300, 1500, 2000, 2500, 3000,
+ 3500, 4000, 4500, 5000, 5500, 6000, 7000, 8000 };
+
+u32 mmc_tran_speed(u8 ts)
+{
+ u32 rate = ts_exp[(ts & 0x7)] * ts_mul[(ts & 0x78) >> 3];
+
+ if (rate <= 0) {
+ DEBUG(0, "mmc_tran_speed: error - unrecognized speed 0x%02x\n", ts);
+ return 1;
+ }
+
+ return rate;
+}
+
+void mmc_send_cmd(struct mmc_request *request, int cmd, u32 arg,
+ u16 nob, u16 block_len, enum mmc_rsp_t rtype, u8 *buffer)
+{
+ request->cmd = cmd;
+ request->arg = arg;
+ request->rtype = rtype;
+ request->nob = nob;
+ request->block_len = block_len;
+ request->buffer = buffer;
+ request->cnt = nob * block_len;
+
+ jz_mmc_exec_cmd(request);
+}
+
+#endif /* CONFIG_MMC */
+#endif /* CONFIG_JZ4740 */
diff --git a/package/uboot-xburst/files/cpu/mips/jz_mmc.h b/package/uboot-xburst/files/cpu/mips/jz_mmc.h
new file mode 100644
index 000000000..0c7b70ff8
--- /dev/null
+++ b/package/uboot-xburst/files/cpu/mips/jz_mmc.h
@@ -0,0 +1,113 @@
+/*
+ * linux/drivers/mmc/jz_mmc.h
+ *
+ * Author: Vladimir Shebordaev, Igor Oblakov
+ * Copyright: MontaVista Software Inc.
+ *
+ * $Id: jz_mmc.h,v 1.3 2007-06-15 08:04:20 jlwei Exp $
+ *
+ * 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.
+ */
+#ifndef __MMC_JZMMC_H__
+#define __MMC_JZMMC_H__
+
+#include "mmc_protocol.h"
+
+#define MMC_DEBUG_LEVEL 0 /* Enable Debug: 0 - no debug */
+
+#define MMC_BLOCK_SIZE 512 /* MMC/SD Block Size */
+
+#define ID_TO_RCA(x) ((x)+1)
+
+#define MMC_OCR_ARG 0x00ff8000 /* Argument of OCR */
+
+enum mmc_result_t {
+ MMC_NO_RESPONSE = -1,
+ MMC_NO_ERROR = 0,
+ MMC_ERROR_OUT_OF_RANGE,
+ MMC_ERROR_ADDRESS,
+ MMC_ERROR_BLOCK_LEN,
+ MMC_ERROR_ERASE_SEQ,
+ MMC_ERROR_ERASE_PARAM,
+ MMC_ERROR_WP_VIOLATION,
+ MMC_ERROR_CARD_IS_LOCKED,
+ MMC_ERROR_LOCK_UNLOCK_FAILED,
+ MMC_ERROR_COM_CRC,
+ MMC_ERROR_ILLEGAL_COMMAND,
+ MMC_ERROR_CARD_ECC_FAILED,
+ MMC_ERROR_CC,
+ MMC_ERROR_GENERAL,
+ MMC_ERROR_UNDERRUN,
+ MMC_ERROR_OVERRUN,
+ MMC_ERROR_CID_CSD_OVERWRITE,
+ MMC_ERROR_STATE_MISMATCH,
+ MMC_ERROR_HEADER_MISMATCH,
+ MMC_ERROR_TIMEOUT,
+ MMC_ERROR_CRC,
+ MMC_ERROR_DRIVER_FAILURE,
+};
+
+/* the information structure of MMC/SD Card */
+typedef struct MMC_INFO
+{
+ int id; /* Card index */
+ int sd; /* MMC or SD card */
+ int rca; /* RCA */
+ u32 scr; /* SCR 63:32*/
+ int flags; /* Ejected, inserted */
+ enum card_state state; /* empty, ident, ready, whatever */
+
+ /* Card specific information */
+ struct mmc_cid cid;
+ struct mmc_csd csd;
+ u32 block_num;
+ u32 block_len;
+ u32 erase_unit;
+} mmc_info;
+
+mmc_info mmcinfo;
+
+struct mmc_request {
+ int index; /* Slot index - used for CS lines */
+ int cmd; /* Command to send */
+ u32 arg; /* Argument to send */
+ enum mmc_rsp_t rtype; /* Response type expected */
+
+ /* Data transfer (these may be modified at the low level) */
+ u16 nob; /* Number of blocks to transfer*/
+ u16 block_len; /* Block length */
+ u8 *buffer; /* Data buffer */
+ u32 cnt; /* Data length, for PIO */
+
+ /* Results */
+ u8 response[18]; /* Buffer to store response - CRC is optional */
+ enum mmc_result_t result;
+};
+
+char * mmc_result_to_string(int);
+int mmc_unpack_csd(struct mmc_request *request, struct mmc_csd *csd);
+int mmc_unpack_r1(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state);
+int mmc_unpack_r6(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state, int *rca);
+int mmc_unpack_scr(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state, u32 *scr);
+int mmc_unpack_cid(struct mmc_request *request, struct mmc_cid *cid);
+int mmc_unpack_r3(struct mmc_request *request, struct mmc_response_r3 *r3);
+
+void mmc_send_cmd(struct mmc_request *request, int cmd, u32 arg,
+ u16 nob, u16 block_len, enum mmc_rsp_t rtype, u8 *buffer);
+u32 mmc_tran_speed(u8 ts);
+void jz_mmc_set_clock(int sd, u32 rate);
+void jz_mmc_hardware_init(void);
+
+static inline void mmc_simple_cmd(struct mmc_request *request, int cmd, u32 arg, enum mmc_rsp_t rtype)
+{
+ mmc_send_cmd( request, cmd, arg, 0, 0, rtype, 0);
+}
+
+int mmc_legacy_init(int verbose);
+int mmc_read(ulong src, uchar *dst, int size);
+int mmc_write(uchar *src, ulong dst, int size);
+int mmc2info(ulong addr);
+
+#endif /* __MMC_JZMMC_H__ */
diff --git a/package/uboot-xburst/files/cpu/mips/jz_serial.c b/package/uboot-xburst/files/cpu/mips/jz_serial.c
new file mode 100644
index 000000000..e9a18a105
--- /dev/null
+++ b/package/uboot-xburst/files/cpu/mips/jz_serial.c
@@ -0,0 +1,141 @@
+/*
+ * Jz47xx UART support
+ *
+ * Hardcoded to UART 0 for now
+ * Options also hardcoded to 8N1
+ *
+ * Copyright (c) 2005
+ * Ingenic Semiconductor, <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <config.h>
+
+#if defined(CONFIG_JZ4740)
+
+#include <common.h>
+
+#include <asm/jz4740.h>
+
+#undef UART_BASE
+#ifndef CONFIG_SYS_UART_BASE
+#define UART_BASE UART0_BASE
+#else
+#define UART_BASE CONFIG_SYS_UART_BASE
+#endif
+
+/******************************************************************************
+*
+* serial_init - initialize a channel
+*
+* This routine initializes the number of data bits, parity
+* and set the selected baud rate. Interrupts are disabled.
+* Set the modem control signals if the option is selected.
+*
+* RETURNS: N/A
+*/
+
+int serial_init (void)
+{
+#if !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL)
+ volatile u8 *uart_fcr = (volatile u8 *)(UART_BASE + OFF_FCR);
+ volatile u8 *uart_lcr = (volatile u8 *)(UART_BASE + OFF_LCR);
+ volatile u8 *uart_ier = (volatile u8 *)(UART_BASE + OFF_IER);
+ volatile u8 *uart_sircr = (volatile u8 *)(UART_BASE + OFF_SIRCR);
+
+ /* Disable port interrupts while changing hardware */
+ *uart_ier = 0;
+
+ /* Disable UART unit function */
+ *uart_fcr = ~UART_FCR_UUE;
+
+ /* Set both receiver and transmitter in UART mode (not SIR) */
+ *uart_sircr = ~(SIRCR_RSIRE | SIRCR_TSIRE);
+
+ /* Set databits, stopbits and parity. (8-bit data, 1 stopbit, no parity) */
+ *uart_lcr = UART_LCR_WLEN_8 | UART_LCR_STOP_1;
+
+ /* Set baud rate */
+ serial_setbrg();
+
+ /* Enable UART unit, enable and clear FIFO */
+ *uart_fcr = UART_FCR_UUE | UART_FCR_FE | UART_FCR_TFLS | UART_FCR_RFLS;
+#endif
+ return 0;
+}
+
+void serial_setbrg (void)
+{
+ volatile u8 *uart_lcr = (volatile u8 *)(UART_BASE + OFF_LCR);
+ volatile u8 *uart_dlhr = (volatile u8 *)(UART_BASE + OFF_DLHR);
+ volatile u8 *uart_dllr = (volatile u8 *)(UART_BASE + OFF_DLLR);
+ u32 baud_div, tmp;
+
+ baud_div = CONFIG_SYS_EXTAL / 16 / CONFIG_BAUDRATE;
+
+ tmp = *uart_lcr;
+ tmp |= UART_LCR_DLAB;
+ *uart_lcr = tmp;
+
+ *uart_dlhr = (baud_div >> 8) & 0xff;
+ *uart_dllr = baud_div & 0xff;
+
+ tmp &= ~UART_LCR_DLAB;
+ *uart_lcr = tmp;
+}
+
+void serial_putc (const char c)
+{
+ volatile u8 *uart_lsr = (volatile u8 *)(UART_BASE + OFF_LSR);
+ volatile u8 *uart_tdr = (volatile u8 *)(UART_BASE + OFF_TDR);
+
+ if (c == '\n') serial_putc ('\r');
+
+ /* Wait for fifo to shift out some bytes */
+ while ( !((*uart_lsr & (UART_LSR_TDRQ | UART_LSR_TEMT)) == 0x60) );
+
+ *uart_tdr = (u8)c;
+}
+
+void serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
+
+int serial_getc (void)
+{
+ volatile u8 *uart_rdr = (volatile u8 *)(UART_BASE + OFF_RDR);
+
+ while (!serial_tstc());
+
+ return *uart_rdr;
+}
+
+int serial_tstc (void)
+{
+ volatile u8 *uart_lsr = (volatile u8 *)(UART_BASE + OFF_LSR);
+
+ if (*uart_lsr & UART_LSR_DR) {
+ /* Data in rfifo */
+ return (1);
+ }
+ return 0;
+}
+
+#endif
diff --git a/package/uboot-xburst/files/cpu/mips/mmc_protocol.h b/package/uboot-xburst/files/cpu/mips/mmc_protocol.h
new file mode 100644
index 000000000..ebd59125b
--- /dev/null
+++ b/package/uboot-xburst/files/cpu/mips/mmc_protocol.h
@@ -0,0 +1,273 @@
+/*
+**********************************************************************
+*
+* uC/MMC
+*
+* (c) Copyright 2005 - 2007, Ingenic Semiconductor, Inc
+* All rights reserved.
+*
+***********************************************************************
+
+----------------------------------------------------------------------
+File : mmc_protocol.h
+Purpose : MMC protocol definitions.
+
+----------------------------------------------------------------------
+Version-Date-----Author-Explanation
+----------------------------------------------------------------------
+1.00.00 20060831 WeiJianli First release
+
+----------------------------------------------------------------------
+Known problems or limitations with current version
+----------------------------------------------------------------------
+(none)
+---------------------------END-OF-HEADER------------------------------
+*/
+
+#ifndef __MMC_PROTOCOL__
+#define __MMC_PROTOCOL__
+
+/* Standard MMC/SD clock speeds */
+#define MMC_CLOCK_SLOW 400000 /* 400 kHz for initial setup */
+#define MMC_CLOCK_FAST 20000000 /* 20 MHz for maximum for normal operation */
+#define SD_CLOCK_FAST 24000000 /* 24 MHz for SD Cards */
+
+/* Extra MMC commands for state control */
+/* Use negative numbers to disambiguate */
+#define MMC_CIM_RESET -1
+
+/* Standard MMC commands (3.1) type argument response */
+ /* class 1 */
+#define MMC_GO_IDLE_STATE 0 /* bc */
+#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */
+#define MMC_ALL_SEND_CID 2 /* bcr R2 */
+#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */
+#define MMC_SET_DSR 4 /* bc [31:16] RCA */
+#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */
+#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */
+#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */
+#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */
+#define MMC_STOP_TRANSMISSION 12 /* ac R1b */
+#define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */
+#define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */
+
+ /* class 2 */
+#define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */
+#define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */
+#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */
+
+ /* class 3 */
+#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */
+
+ /* class 4 */
+#define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */
+#define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */
+#define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */
+#define MMC_PROGRAM_CID 26 /* adtc R1 */
+#define MMC_PROGRAM_CSD 27 /* adtc R1 */
+
+ /* class 6 */
+#define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */
+#define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */
+#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */
+
+ /* class 5 */
+#define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */
+#define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */
+#define MMC_ERASE 37 /* ac R1b */
+
+ /* class 9 */
+#define MMC_FAST_IO 39 /* ac <Complex> R4 */
+#define MMC_GO_IRQ_STATE 40 /* bcr R5 */
+
+ /* class 7 */
+#define MMC_LOCK_UNLOCK 42 /* adtc R1b */
+
+ /* class 8 */
+#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
+#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1b */
+
+ /* SD class */
+#define SD_SEND_OP_COND 41 /* bcr [31:0] OCR R3 */
+#define SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
+#define SEND_SCR 51 /* adtc [31:0] staff R1 */
+
+/* Don't change the order of these; they are used in dispatch tables */
+enum mmc_rsp_t {
+ RESPONSE_NONE = 0,
+ RESPONSE_R1 = 1,
+ RESPONSE_R1B = 2,
+ RESPONSE_R2_CID = 3,
+ RESPONSE_R2_CSD = 4,
+ RESPONSE_R3 = 5,
+ RESPONSE_R4 = 6,
+ RESPONSE_R5 = 7,
+ RESPONSE_R6 = 8,
+};
+
+
+/*
+ MMC status in R1
+ Type
+ e : error bit
+ s : status bit
+ r : detected and set for the actual command response
+ x : detected and set during command execution. the host must poll
+ the card by sending status command in order to read these bits.
+ Clear condition
+ a : according to the card state
+ b : always related to the previous command. Reception of
+ a valid command will clear it (with a delay of one command)
+ c : clear by read
+ */
+
+#define R1_OUT_OF_RANGE (1 << 31) /* er, c */
+#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */
+#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */
+#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */
+#define R1_ERASE_PARAM (1 << 27) /* ex, c */
+#define R1_WP_VIOLATION (1 << 26) /* erx, c */
+#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */
+#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */
+#define R1_COM_CRC_ERROR (1 << 23) /* er, b */
+#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */
+#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */
+#define R1_CC_ERROR (1 << 20) /* erx, c */
+#define R1_ERROR (1 << 19) /* erx, c */
+#define R1_UNDERRUN (1 << 18) /* ex, c */
+#define R1_OVERRUN (1 << 17) /* ex, c */
+#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */
+#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */
+#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */
+#define R1_ERASE_RESET (1 << 13) /* sr, c */
+#define R1_STATUS(x) (x & 0xFFFFE000)
+#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */
+#define R1_READY_FOR_DATA (1 << 8) /* sx, a */
+#define R1_APP_CMD (1 << 7) /* sr, c */
+
+enum card_state {
+ CARD_STATE_EMPTY = -1,
+ CARD_STATE_IDLE = 0,
+ CARD_STATE_READY = 1,
+ CARD_STATE_IDENT = 2,
+ CARD_STATE_STBY = 3,
+ CARD_STATE_TRAN = 4,
+ CARD_STATE_DATA = 5,
+ CARD_STATE_RCV = 6,
+ CARD_STATE_PRG = 7,
+ CARD_STATE_DIS = 8,
+};
+
+/* These are unpacked versions of the actual responses */
+
+ struct mmc_response_r1 {
+ u8 cmd;
+ u32 status;
+};
+
+typedef struct mmc_cid {
+ u8 mid;
+ u16 oid;
+ u8 pnm[7]; /* Product name (we null-terminate) */
+ u8 prv;
+ u32 psn;
+ u8 mdt;
+}mmc_cid_t;
+
+typedef struct mmc_csd {
+ u8 csd_structure;
+ u8 spec_vers;
+ u8 taac;
+ u8 nsac;
+ u8 tran_speed;
+ u16 ccc;
+ u8 read_bl_len;
+ u8 read_bl_partial;
+ u8 write_blk_misalign;
+ u8 read_blk_misalign;
+ u8 dsr_imp;
+ u16 c_size;
+ u8 vdd_r_curr_min;
+ u8 vdd_r_curr_max;
+ u8 vdd_w_curr_min;
+ u8 vdd_w_curr_max;
+ u8 c_size_mult;
+ union {
+ struct { /* MMC system specification version 3.1 */
+ u8 erase_grp_size;
+ u8 erase_grp_mult;
+ } v31;
+ struct { /* MMC system specification version 2.2 */
+ u8 sector_size;
+ u8 erase_grp_size;
+ } v22;
+ } erase;
+ u8 wp_grp_size;
+ u8 wp_grp_enable;
+ u8 default_ecc;
+ u8 r2w_factor;
+ u8 write_bl_len;
+ u8 write_bl_partial;
+ u8 file_format_grp;
+ u8 copy;
+ u8 perm_write_protect;
+ u8 tmp_write_protect;
+ u8 file_format;
+ u8 ecc;
+}mmc_csd_t;;
+
+struct mmc_response_r3 {
+ u32 ocr;
+};
+
+#define MMC_VDD_145_150 0x00000001 /* VDD voltage 1.45 - 1.50 */
+#define MMC_VDD_150_155 0x00000002 /* VDD voltage 1.50 - 1.55 */
+#define MMC_VDD_155_160 0x00000004 /* VDD voltage 1.55 - 1.60 */
+#define MMC_VDD_160_165 0x00000008 /* VDD voltage 1.60 - 1.65 */
+#define MMC_VDD_165_170 0x00000010 /* VDD voltage 1.65 - 1.70 */
+#define MMC_VDD_17_18 0x00000020 /* VDD voltage 1.7 - 1.8 */
+#define MMC_VDD_18_19 0x00000040 /* VDD voltage 1.8 - 1.9 */
+#define MMC_VDD_19_20 0x00000080 /* VDD voltage 1.9 - 2.0 */
+#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */
+#define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */
+#define MMC_VDD_22_23 0x00000400 /* VDD voltage 2.2 ~ 2.3 */
+#define MMC_VDD_23_24 0x00000800 /* VDD voltage 2.3 ~ 2.4 */
+#define MMC_VDD_24_25 0x00001000 /* VDD voltage 2.4 ~ 2.5 */
+#define MMC_VDD_25_26 0x00002000 /* VDD voltage 2.5 ~ 2.6 */
+#define MMC_VDD_26_27 0x00004000 /* VDD voltage 2.6 ~ 2.7 */
+#define MMC_VDD_27_28 0x00008000 /* VDD voltage 2.7 ~ 2.8 */
+#define MMC_VDD_28_29 0x00010000 /* VDD voltage 2.8 ~ 2.9 */
+#define MMC_VDD_29_30 0x00020000 /* VDD voltage 2.9 ~ 3.0 */
+#define MMC_VDD_30_31 0x00040000 /* VDD voltage 3.0 ~ 3.1 */
+#define MMC_VDD_31_32 0x00080000 /* VDD voltage 3.1 ~ 3.2 */
+#define MMC_VDD_32_33 0x00100000 /* VDD voltage 3.2 ~ 3.3 */
+#define MMC_VDD_33_34 0x00200000 /* VDD voltage 3.3 ~ 3.4 */
+#define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */
+#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */
+#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */
+
+
+/* CSD field definitions */
+
+#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */
+#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */
+#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 */
+
+#define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */
+#define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */
+#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */
+#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 */
+
+#if MMC_DEBUG_LEVEL
+
+#define DEBUG(n, args...) \
+ do { \
+ if (n <= MMC_DEBUG_LEVEL) { \
+ printf(args); \
+ } \
+ } while(0)
+#else
+#define DEBUG(n, args...)
+#endif /* MMC_DEBUG_EN */
+
+#endif /* __MMC_PROTOCOL__ */
diff --git a/package/uboot-xburst/files/cpu/mips/nanonote_gpm940b0.c b/package/uboot-xburst/files/cpu/mips/nanonote_gpm940b0.c
new file mode 100644
index 000000000..4c98d2943
--- /dev/null
+++ b/package/uboot-xburst/files/cpu/mips/nanonote_gpm940b0.c
@@ -0,0 +1,420 @@
+/*
+ * JzRISC lcd controller
+ *
+ * xiangfu liu <xiangfu.z@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <config.h>
+#include <common.h>
+#include <lcd.h>
+
+#include <asm/io.h> /* virt_to_phys() */
+
+#include <asm/jz4740.h>
+#include "nanonote_gpm940b0.h"
+
+#define align2(n) (n)=((((n)+1)>>1)<<1)
+#define align4(n) (n)=((((n)+3)>>2)<<2)
+#define align8(n) (n)=((((n)+7)>>3)<<3)
+
+struct jzfb_info {
+ unsigned int cfg; /* panel mode and pin usage etc. */
+ unsigned int w;
+ unsigned int h;
+ unsigned int bpp; /* bit per pixel */
+ unsigned int fclk; /* frame clk */
+ unsigned int hsw; /* hsync width, in pclk */
+ unsigned int vsw; /* vsync width, in line count */
+ unsigned int elw; /* end of line, in pclk */
+ unsigned int blw; /* begin of line, in pclk */
+ unsigned int efw; /* end of frame, in line count */
+ unsigned int bfw; /* begin of frame, in line count */
+};
+
+static struct jzfb_info jzfb = {
+ MODE_8BIT_SERIAL_TFT | PCLK_N | HSYNC_N | VSYNC_N,
+ 320, 240, 32, 70, 1, 1, 273, 140, 1, 20
+};
+
+vidinfo_t panel_info = {
+ 320, 240, LCD_BPP,
+};
+
+int lcd_line_length;
+
+int lcd_color_fg;
+int lcd_color_bg;
+/*
+ * Frame buffer memory information
+ */
+void *lcd_base; /* Start of framebuffer memory */
+void *lcd_console_address; /* Start of console buffer */
+
+short console_col;
+short console_row;
+
+void lcd_ctrl_init (void *lcdbase);
+void lcd_enable (void);
+void lcd_disable (void);
+
+static int jz_lcd_init_mem(void *lcdbase, vidinfo_t *vid);
+static void jz_lcd_desc_init(vidinfo_t *vid);
+static int jz_lcd_hw_init( vidinfo_t *vid );
+extern int flush_cache_all(void);
+
+void lcd_ctrl_init (void *lcdbase)
+{
+ __lcd_display_pin_init();
+
+ jz_lcd_init_mem(lcdbase, &panel_info);
+ jz_lcd_desc_init(&panel_info);
+ jz_lcd_hw_init(&panel_info);
+
+ __lcd_display_on() ;
+}
+
+/*
+ * Before enabled lcd controller, lcd registers should be configured correctly.
+ */
+
+void lcd_enable (void)
+{
+ REG_LCD_CTRL &= ~(1<<4); /* LCDCTRL.DIS */
+ REG_LCD_CTRL |= 1<<3; /* LCDCTRL.ENA*/
+}
+
+void lcd_disable (void)
+{
+ REG_LCD_CTRL |= (1<<4); /* LCDCTRL.DIS, regular disable */
+ /* REG_LCD_CTRL |= (1<<3); */ /* LCDCTRL.DIS, quikly disable */
+}
+
+static int jz_lcd_init_mem(void *lcdbase, vidinfo_t *vid)
+{
+ u_long palette_mem_size;
+ struct jz_fb_info *fbi = &vid->jz_fb;
+ int fb_size = vid->vl_row * (vid->vl_col * NBITS (vid->vl_bpix)) / 8;
+
+ fbi->screen = (u_long)lcdbase;
+ fbi->palette_size = 256;
+ palette_mem_size = fbi->palette_size * sizeof(u16);
+
+ debug("jz_lcd.c palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);
+ /* locate palette and descs at end of page following fb */
+ fbi->palette = (u_long)lcdbase + fb_size + PAGE_SIZE - palette_mem_size;
+
+ return 0;
+}
+
+static void jz_lcd_desc_init(vidinfo_t *vid)
+{
+ struct jz_fb_info * fbi;
+ fbi = &vid->jz_fb;
+ fbi->dmadesc_fblow = (struct jz_fb_dma_descriptor *)((unsigned int)fbi->palette - 3*16);
+ fbi->dmadesc_fbhigh = (struct jz_fb_dma_descriptor *)((unsigned int)fbi->palette - 2*16);
+ fbi->dmadesc_palette = (struct jz_fb_dma_descriptor *)((unsigned int)fbi->palette - 1*16);
+
+ #define BYTES_PER_PANEL (vid->vl_col * vid->vl_row * NBITS(vid->vl_bpix) / 8)
+
+ /* populate descriptors */
+ fbi->dmadesc_fblow->fdadr = virt_to_phys(fbi->dmadesc_fblow);
+ fbi->dmadesc_fblow->fsadr = virt_to_phys((void *)(fbi->screen + BYTES_PER_PANEL));
+ fbi->dmadesc_fblow->fidr = 0;
+ fbi->dmadesc_fblow->ldcmd = BYTES_PER_PANEL / 4 ;
+
+ fbi->fdadr1 = virt_to_phys(fbi->dmadesc_fblow); /* only used in dual-panel mode */
+
+ fbi->dmadesc_fbhigh->fsadr = virt_to_phys((void *)fbi->screen);
+ fbi->dmadesc_fbhigh->fidr = 0;
+ fbi->dmadesc_fbhigh->ldcmd = BYTES_PER_PANEL / 4; /* length in word */
+
+ fbi->dmadesc_palette->fsadr = virt_to_phys((void *)fbi->palette);
+ fbi->dmadesc_palette->fidr = 0;
+ fbi->dmadesc_palette->ldcmd = (fbi->palette_size * 2)/4 | (1<<28);
+
+ if(NBITS(vid->vl_bpix) < 12)
+ {
+ /* assume any mode with <12 bpp is palette driven */
+ fbi->dmadesc_palette->fdadr = virt_to_phys(fbi->dmadesc_fbhigh);
+ fbi->dmadesc_fbhigh->fdadr = virt_to_phys(fbi->dmadesc_palette);
+ /* flips back and forth between pal and fbhigh */
+ fbi->fdadr0 = virt_to_phys(fbi->dmadesc_palette);
+ } else {
+ /* palette shouldn't be loaded in true-color mode */
+ fbi->dmadesc_fbhigh->fdadr = virt_to_phys((void *)fbi->dmadesc_fbhigh);
+ fbi->fdadr0 = virt_to_phys(fbi->dmadesc_fbhigh); /* no pal just fbhigh */
+ }
+
+ flush_cache_all();
+}
+
+static int jz_lcd_hw_init(vidinfo_t *vid)
+{
+ struct jz_fb_info *fbi = &vid->jz_fb;
+ unsigned int val = 0;
+ unsigned int pclk;
+ unsigned int stnH;
+ int pll_div;
+
+ /* Setting Control register */
+ switch (jzfb.bpp) {
+ case 1:
+ val |= LCD_CTRL_BPP_1;
+ break;
+ case 2:
+ val |= LCD_CTRL_BPP_2;
+ break;
+ case 4:
+ val |= LCD_CTRL_BPP_4;
+ break;
+ case 8:
+ val |= LCD_CTRL_BPP_8;
+ break;
+ case 15:
+ val |= LCD_CTRL_RGB555;
+ case 16:
+ val |= LCD_CTRL_BPP_16;
+ break;
+ case 17 ... 32:
+ val |= LCD_CTRL_BPP_18_24; /* target is 4bytes/pixel */
+ break;
+
+ default:
+ printf("jz_lcd.c The BPP %d is not supported\n", jzfb.bpp);
+ val |= LCD_CTRL_BPP_16;
+ break;
+ }
+
+ switch (jzfb.cfg & MODE_MASK) {
+ case MODE_STN_MONO_DUAL:
+ case MODE_STN_COLOR_DUAL:
+ case MODE_STN_MONO_SINGLE:
+ case MODE_STN_COLOR_SINGLE:
+ switch (jzfb.bpp) {
+ case 1:
+ /* val |= LCD_CTRL_PEDN; */
+ case 2:
+ val |= LCD_CTRL_FRC_2;
+ break;
+ case 4:
+ val |= LCD_CTRL_FRC_4;
+ break;
+ case 8:
+ default:
+ val |= LCD_CTRL_FRC_16;
+ break;
+ }
+ break;
+ }
+
+ val |= LCD_CTRL_BST_16; /* Burst Length is 16WORD=64Byte */
+ val |= LCD_CTRL_OFUP; /* OutFIFO underrun protect */
+
+ switch (jzfb.cfg & MODE_MASK) {
+ case MODE_STN_MONO_DUAL:
+ case MODE_STN_COLOR_DUAL:
+ case MODE_STN_MONO_SINGLE:
+ case MODE_STN_COLOR_SINGLE:
+ switch (jzfb.cfg & STN_DAT_PINMASK) {
+ case STN_DAT_PIN1:
+ /* Do not adjust the hori-param value. */
+ break;
+ case STN_DAT_PIN2:
+ align2(jzfb.hsw);
+ align2(jzfb.elw);
+ align2(jzfb.blw);
+ break;
+ case STN_DAT_PIN4:
+ align4(jzfb.hsw);
+ align4(jzfb.elw);
+ align4(jzfb.blw);
+ break;
+ case STN_DAT_PIN8:
+ align8(jzfb.hsw);
+ align8(jzfb.elw);
+ align8(jzfb.blw);
+ break;
+ }
+ break;
+ }
+
+ REG_LCD_CTRL = val;
+
+ switch (jzfb.cfg & MODE_MASK) {
+ case MODE_STN_MONO_DUAL:
+ case MODE_STN_COLOR_DUAL:
+ case MODE_STN_MONO_SINGLE:
+ case MODE_STN_COLOR_SINGLE:
+ if (((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL) ||
+ ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL))
+ stnH = jzfb.h >> 1;
+ else
+ stnH = jzfb.h;
+
+ REG_LCD_VSYNC = (0 << 16) | jzfb.vsw;
+ REG_LCD_HSYNC = ((jzfb.blw+jzfb.w) << 16) | (jzfb.blw+jzfb.w+jzfb.hsw);
+
+ /* Screen setting */
+ REG_LCD_VAT = ((jzfb.blw + jzfb.w + jzfb.hsw + jzfb.elw) << 16) | (stnH + jzfb.vsw + jzfb.bfw + jzfb.efw);
+ REG_LCD_DAH = (jzfb.blw << 16) | (jzfb.blw + jzfb.w);
+ REG_LCD_DAV = (0 << 16) | (stnH);
+
+ /* AC BIAs signal */
+ REG_LCD_PS = (0 << 16) | (stnH+jzfb.vsw+jzfb.efw+jzfb.bfw);
+
+ break;
+
+ case MODE_TFT_GEN:
+ case MODE_TFT_SHARP:
+ case MODE_TFT_CASIO:
+ case MODE_TFT_SAMSUNG:
+ case MODE_8BIT_SERIAL_TFT:
+ case MODE_TFT_18BIT:
+ REG_LCD_VSYNC = (0 << 16) | jzfb.vsw;
+ REG_LCD_HSYNC = (0 << 16) | jzfb.hsw;
+ REG_LCD_DAV =((jzfb.vsw+jzfb.bfw) << 16) | (jzfb.vsw +jzfb.bfw+jzfb.h);
+ REG_LCD_DAH = ((jzfb.hsw + jzfb.blw) << 16) | (jzfb.hsw + jzfb.blw + jzfb.w );
+ REG_LCD_VAT = (((jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw)) << 16) \
+ | (jzfb.vsw + jzfb.bfw + jzfb.h + jzfb.efw);
+ break;
+ }
+
+ switch (jzfb.cfg & MODE_MASK) {
+ case MODE_TFT_SAMSUNG:
+ {
+ unsigned int total, tp_s, tp_e, ckv_s, ckv_e;
+ unsigned int rev_s, rev_e, inv_s, inv_e;
+
+ pclk = val * (jzfb.w + jzfb.hsw + jzfb.elw + jzfb.blw) *
+ (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */
+
+ total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw;
+ tp_s = jzfb.blw + jzfb.w + 1;
+ tp_e = tp_s + 1;
+ /* ckv_s = tp_s - jz_clocks.pixclk/(1000000000/4100); */
+ ckv_s = tp_s - pclk/(1000000000/4100);
+ ckv_e = tp_s + total;
+ rev_s = tp_s - 11; /* -11.5 clk */
+ rev_e = rev_s + total;
+ inv_s = tp_s;
+ inv_e = inv_s + total;
+ REG_LCD_CLS = (tp_s << 16) | tp_e;
+ REG_LCD_PS = (ckv_s << 16) | ckv_e;
+ REG_LCD_SPL = (rev_s << 16) | rev_e;
+ REG_LCD_REV = (inv_s << 16) | inv_e;
+ jzfb.cfg |= STFT_REVHI | STFT_SPLHI;
+ break;
+ }
+ case MODE_TFT_SHARP:
+ {
+ unsigned int total, cls_s, cls_e, ps_s, ps_e;
+ unsigned int spl_s, spl_e, rev_s, rev_e;
+ total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw;
+ spl_s = 1;
+ spl_e = spl_s + 1;
+ cls_s = 0;
+ cls_e = total - 60; /* > 4us (pclk = 80ns) */
+ ps_s = cls_s;
+ ps_e = cls_e;
+ rev_s = total - 40; /* > 3us (pclk = 80ns) */
+ rev_e = rev_s + total;
+ jzfb.cfg |= STFT_PSHI;
+ REG_LCD_SPL = (spl_s << 16) | spl_e;
+ REG_LCD_CLS = (cls_s << 16) | cls_e;
+ REG_LCD_PS = (ps_s << 16) | ps_e;
+ REG_LCD_REV = (rev_s << 16) | rev_e;
+ break;
+ }
+ case MODE_TFT_CASIO:
+ break;
+ }
+
+ /* Configure the LCD panel */
+ REG_LCD_CFG = jzfb.cfg;
+
+ /* Timing setting */
+ __cpm_stop_lcd();
+
+ val = jzfb.fclk; /* frame clk */
+ if ( (jzfb.cfg & MODE_MASK) != MODE_8BIT_SERIAL_TFT) {
+ pclk = val * (jzfb.w + jzfb.hsw + jzfb.elw + jzfb.blw) *
+ (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */
+ } else {
+ /* serial mode: Hsync period = 3*Width_Pixel */
+ pclk = val * (jzfb.w*3 + jzfb.hsw + jzfb.elw + jzfb.blw) *
+ (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */
+ }
+
+ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) ||
+ ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL))
+ pclk = (pclk * 3);
+
+ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) ||
+ ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ||
+ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_SINGLE) ||
+ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL))
+ pclk = pclk >> ((jzfb.cfg & STN_DAT_PINMASK) >> 4);
+
+ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ||
+ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL))
+ pclk >>= 1;
+
+ pll_div = ( REG_CPM_CPCCR & CPM_CPCCR_PCS ); /* clock source,0:pllout/2 1: pllout */
+ pll_div = pll_div ? 1 : 2 ;
+ val = ( __cpm_get_pllout()/pll_div ) / pclk;
+ val--;
+ if ( val > 0x1ff ) {
+ printf("CPM_LPCDR too large, set it to 0x1ff\n");
+ val = 0x1ff;
+ }
+ __cpm_set_pixdiv(val);
+
+ val = pclk * 3 ; /* LCDClock > 2.5*Pixclock */
+ if ( val > 150000000 ) {
+ printf("Warning: LCDClock=%d\n, LCDClock must less or equal to 150MHz.\n", val);
+ printf("Change LCDClock to 150MHz\n");
+ val = 150000000;
+ }
+ val = ( __cpm_get_pllout()/pll_div ) / val;
+ val--;
+ if ( val > 0x1f ) {
+ printf("CPM_CPCCR.LDIV too large, set it to 0x1f\n");
+ val = 0x1f;
+ }
+ __cpm_set_ldiv( val );
+ REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* update divide */
+
+ __cpm_start_lcd();
+ udelay(1000);
+
+ REG_LCD_DA0 = fbi->fdadr0; /* frame descripter*/
+
+ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ||
+ ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL))
+ REG_LCD_DA1 = fbi->fdadr1; /* frame descripter*/
+
+ return 0;
+}
+
+void lcd_setcolreg (ushort regno, ushort red, ushort green, ushort blue)
+{
+}
+
+void lcd_initcolregs (void)
+{
+}
diff --git a/package/uboot-xburst/files/cpu/mips/nanonote_gpm940b0.h b/package/uboot-xburst/files/cpu/mips/nanonote_gpm940b0.h
new file mode 100644
index 000000000..8ff78ada2
--- /dev/null
+++ b/package/uboot-xburst/files/cpu/mips/nanonote_gpm940b0.h
@@ -0,0 +1,234 @@
+/*
+ * JzRISC lcd controller
+ *
+ * xiangfu liu <xiangfu.z@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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 __QI_LB60_GPM940B0_H__
+#define __QI_LB60_GPM940B0_H__
+
+#include <asm/io.h>
+
+#define mdelay(n) udelay((n)*1000)
+
+#define NR_PALETTE 256
+
+struct lcd_desc{
+ unsigned int next_desc; /* LCDDAx */
+ unsigned int databuf; /* LCDSAx */
+ unsigned int frame_id; /* LCDFIDx */
+ unsigned int cmd; /* LCDCMDx */
+};
+
+#define MODE_MASK 0x0f
+#define MODE_TFT_GEN 0x00
+#define MODE_TFT_SHARP 0x01
+#define MODE_TFT_CASIO 0x02
+#define MODE_TFT_SAMSUNG 0x03
+#define MODE_CCIR656_NONINT 0x04
+#define MODE_CCIR656_INT 0x05
+#define MODE_STN_COLOR_SINGLE 0x08
+#define MODE_STN_MONO_SINGLE 0x09
+#define MODE_STN_COLOR_DUAL 0x0a
+#define MODE_STN_MONO_DUAL 0x0b
+#define MODE_8BIT_SERIAL_TFT 0x0c
+
+#define MODE_TFT_18BIT (1<<7)
+
+#define STN_DAT_PIN1 (0x00 << 4)
+#define STN_DAT_PIN2 (0x01 << 4)
+#define STN_DAT_PIN4 (0x02 << 4)
+#define STN_DAT_PIN8 (0x03 << 4)
+#define STN_DAT_PINMASK STN_DAT_PIN8
+
+#define STFT_PSHI (1 << 15)
+#define STFT_CLSHI (1 << 14)
+#define STFT_SPLHI (1 << 13)
+#define STFT_REVHI (1 << 12)
+
+#define SYNC_MASTER (0 << 16)
+#define SYNC_SLAVE (1 << 16)
+
+#define DE_P (0 << 9)
+#define DE_N (1 << 9)
+
+#define PCLK_P (0 << 10)
+#define PCLK_N (1 << 10)
+
+#define HSYNC_P (0 << 11)
+#define HSYNC_N (1 << 11)
+
+#define VSYNC_P (0 << 8)
+#define VSYNC_N (1 << 8)
+
+#define DATA_NORMAL (0 << 17)
+#define DATA_INVERSE (1 << 17)
+
+
+/* Jz LCDFB supported I/O controls. */
+#define FBIOSETBACKLIGHT 0x4688
+#define FBIODISPON 0x4689
+#define FBIODISPOFF 0x468a
+#define FBIORESET 0x468b
+#define FBIOPRINT_REG 0x468c
+
+/*
+ * LCD panel specific definition
+ */
+#define MODE 0xc9 /* 8bit serial RGB */
+#define SPEN (32*2+21) /*LCD_SPL */
+#define SPCK (32*2+23) /*LCD_CLS */
+#define SPDA (32*2+22) /*LCD_D12 */
+#define LCD_RET (32*3+27)
+
+#define __spi_write_reg1(reg, val) \
+do { \
+ unsigned char no;\
+ unsigned short value;\
+ unsigned char a=0;\
+ unsigned char b=0;\
+ a=reg;\
+ b=val;\
+ __gpio_set_pin(SPEN);\
+ __gpio_set_pin(SPCK);\
+ __gpio_clear_pin(SPDA);\
+ __gpio_clear_pin(SPEN);\
+ udelay(25);\
+ value=((a<<8)|(b&0xFF));\
+ for(no=0;no<16;no++)\
+ {\
+ __gpio_clear_pin(SPCK);\
+ if((value&0x8000)==0x8000)\
+ __gpio_set_pin(SPDA);\
+ else\
+ __gpio_clear_pin(SPDA);\
+ udelay(25);\
+ __gpio_set_pin(SPCK);\
+ value=(value<<1); \
+ udelay(25);\
+ }\
+ __gpio_set_pin(SPEN);\
+ udelay(100);\
+} while (0)
+
+#define __spi_write_reg(reg, val) \
+do {\
+ __spi_write_reg1((reg<<2|2), val);\
+ udelay(100); \
+}while(0)
+
+#define __lcd_special_pin_init() \
+do { \
+ __gpio_as_output(SPEN); /* use SPDA */\
+ __gpio_as_output(SPCK); /* use SPCK */\
+ __gpio_as_output(SPDA); /* use SPDA */\
+ __gpio_as_output(LCD_RET);\
+} while (0)
+
+#define __lcd_special_on() \
+do { \
+ __spi_write_reg1(0x05, 0x1e); \
+ udelay(50);\
+ __spi_write_reg1(0x05, 0x5d); \
+ __spi_write_reg1(0x0B, 0x81); \
+ __spi_write_reg1(0x01, 0x95); \
+ __spi_write_reg1(0x00, 0x07); \
+ __spi_write_reg1(0x06, 0x15); \
+ __spi_write_reg1(0x07, 0x8d); \
+ __spi_write_reg1(0x04, 0x0f); \
+ __spi_write_reg1(0x0d, 0x3d); \
+ __spi_write_reg1(0x10, 0x42); \
+ __spi_write_reg1(0x11, 0x3a); \
+ __spi_write_reg1(0x05, 0x5f); \
+} while (0)
+
+#define __lcd_special_off() \
+do { \
+ __spi_write_reg1(0x05, 0x5e); \
+} while (0)
+
+#define __lcd_display_pin_init() \
+do { \
+ __lcd_special_pin_init();\
+ __gpio_as_pwm();\
+ __lcd_set_backlight_level(8);\
+} while (0)
+
+#define __lcd_display_on() \
+do { \
+ __lcd_set_backlight_level(8); \
+ __lcd_special_on();\
+} while (0)
+
+#define __lcd_display_off() \
+do { \
+ __lcd_set_backlight_level(0); \
+ __lcd_special_off();\
+} while (0)
+
+#define __lcd_set_backlight_level(n)\
+do { \
+ __gpio_as_output(LCD_RET); \
+ __gpio_set_pin(LCD_RET); \
+} while (0)
+
+#if defined(CONFIG_SAKC)
+#define __lcd_close_backlight() \
+do { \
+ __gpio_as_output(GPIO_PWM); \
+ __gpio_clear_pin(GPIO_PWM); \
+} while (0)
+#endif
+
+#if defined(CONFIG_SAKC)
+#define __lcd_display_pin_init() \
+do { \
+ __cpm_start_tcu(); \
+ __lcd_special_pin_init(); \
+} while (0)
+
+#define __lcd_display_on() \
+do { \
+ __lcd_special_on(); \
+} while (0)
+
+#define __lcd_display_off() \
+do { \
+ __lcd_special_off(); \
+} while (0)
+#else
+#define __lcd_display_pin_init() \
+do { \
+ __cpm_start_tcu(); \
+ __lcd_special_pin_init(); \
+} while (0)
+
+#define __lcd_display_on() \
+do { \
+ __gpio_set_pin(GPIO_DISP_OFF_N); \
+ __lcd_special_on(); \
+} while (0)
+
+#define __lcd_display_off() \
+do { \
+ __lcd_special_off(); \
+ __gpio_clear_pin(GPIO_DISP_OFF_N); \
+} while (0)
+#endif
+
+#endif /* __QI_LB60_GPM940B0_H__ */
diff --git a/package/uboot-xburst/files/cpu/mips/usb_boot.S b/package/uboot-xburst/files/cpu/mips/usb_boot.S
new file mode 100644
index 000000000..107b928c7
--- /dev/null
+++ b/package/uboot-xburst/files/cpu/mips/usb_boot.S
@@ -0,0 +1,880 @@
+/*
+ * for jz4740 usb boot
+ *
+ * Copyright (c) 2009 Xiangfu Liu <xiangfu.z@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+ .set noreorder
+ .globl usb_boot
+ .text
+
+//----------------------------------------------------------------------
+// Both NAND and USB boot load data to D-Cache first, then transfer
+// data from D-Cache to I-Cache, and jump to execute the code in I-Cache.
+// So init caches first and then dispatch to a proper boot routine.
+//----------------------------------------------------------------------
+
+.macro load_addr reg addr
+ li \reg, 0x80000000
+ addiu \reg, \reg, \addr
+ la $2, usbboot_begin
+ subu \reg, \reg, $2
+.endm
+
+usb_boot:
+ //--------------------------------------------------------------
+ // Initialize PLL: set ICLK to 84MHz and HCLK to 42MHz.
+ //--------------------------------------------------------------
+ la $9, 0xB0000000 // CPCCR: Clock Control Register
+ la $8, 0x42041110 // I:S:M:P=1:2:2:2
+ sw $8, 0($9)
+
+ la $9, 0xB0000010 // CPPCR: PLL Control Register
+ la $8, 0x06000120 // M=12 N=0 D=0 CLK=12*(M+2)/(N+2)
+ sw $8, 0($9)
+
+ mtc0 $0, $26 // CP0_ERRCTL, restore WST reset state
+ nop
+
+ mtc0 $0, $16 // CP0_CONFIG
+ nop
+
+ // Relocate code to beginning of the ram
+
+ la $2, usbboot_begin
+ la $3, usbboot_end
+ li $4, 0x80000000
+
+1:
+ lw $5, 0($2)
+ sw $5, 0($4)
+ addiu $2, $2, 4
+ bne $2, $3, 1b
+ addiu $4, $4, 4
+
+ li $2, 0x80000000
+ ori $3, $2, 0
+ addiu $3, $3, usbboot_end
+ la $4, usbboot_begin
+ subu $3, $3, $4
+
+
+2:
+ cache 0x0, 0($2) // Index_Invalidate_I
+ cache 0x1, 0($2) // Index_Writeback_Inv_D
+ addiu $2, $2, 32
+ subu $4, $3, $2
+ bgtz $4, 2b
+ nop
+
+ load_addr $3, usb_boot_return
+
+ jr $3
+
+usbboot_begin:
+
+init_caches:
+ li $2, 3 // cacheable for kseg0 access
+ mtc0 $2, $16 // CP0_CONFIG
+ nop
+
+ li $2, 0x20000000 // enable idx-store-data cache insn
+ mtc0 $2, $26 // CP0_ERRCTL
+
+ ori $2, $28, 0 // start address
+ ori $3, $2, 0x3fe0 // end address, total 16KB
+ mtc0 $0, $28, 0 // CP0_TAGLO
+ mtc0 $0, $28, 1 // CP0_DATALO
+cache_clear_a_line:
+ cache 0x8, 0($2) // Index_Store_Tag_I
+ cache 0x9, 0($2) // Index_Store_Tag_D
+ bne $2, $3, cache_clear_a_line
+ addiu $2, $2, 32 // increment CACHE_LINE_SIZE
+
+ ori $2, $28, 0 // start address
+ ori $3, $2, 0x3fe0 // end address, total 16KB
+ la $4, 0x1ffff000 // physical address and 4KB page mask
+cache_alloc_a_line:
+ and $5, $2, $4
+ ori $5, $5, 1 // V bit of the physical tag
+ mtc0 $5, $28, 0 // CP0_TAGLO
+ cache 0x8, 0($2) // Index_Store_Tag_I
+ cache 0x9, 0($2) // Index_Store_Tag_D
+ bne $2, $3, cache_alloc_a_line
+ addiu $2, $2, 32 // increment CACHE_LINE_SIZE
+
+ nop
+ nop
+ nop
+ //--------------------------------------------------------------
+ // Transfer data from dcache to icache, then jump to icache.
+ //
+ // Input parameters:
+ //
+ // $19: data length in bytes
+ // $20: jump target address
+ //--------------------------------------------------------------
+xfer_d2i:
+
+ ori $8, $20, 0
+ addu $9, $8, $19 // total 16KB
+
+1:
+ cache 0x0, 0($8) // Index_Invalidate_I
+ cache 0x1, 0($8) // Index_Writeback_Inv_D
+ bne $8, $9, 1b
+ addiu $8, $8, 32
+
+ // flush write-buffer
+ sync
+
+ // Invalidate BTB
+ mfc0 $8, $16, 7 // CP0_CONFIG
+ nop
+ ori $8, 2
+ mtc0 $8, $16, 7
+ nop
+
+ // Overwrite config to disable ram initalisation
+ li $2, 0xff
+ sb $2, 20($20)
+
+ jalr $20
+ nop
+
+icache_return:
+ //--------------------------------------------------------------
+ // User code can return to here after executing itself in
+ // icache, by jumping to $31.
+ //--------------------------------------------------------------
+ b usb_boot_return
+ nop
+
+
+usb_boot_return:
+ //--------------------------------------------------------------
+ // Enable the USB PHY
+ //--------------------------------------------------------------
+ la $9, 0xB0000024 // CPM_SCR
+ lw $8, 0($9)
+ ori $8, 0x40 // USBPHY_ENABLE
+ sw $8, 0($9)
+
+ //--------------------------------------------------------------
+ // Initialize USB registers
+ //--------------------------------------------------------------
+ la $27, 0xb3040000 // USB registers base address
+
+ sb $0, 0x0b($27) // INTRUSBE: disable common USB interrupts
+ sh $0, 0x06($27) // INTRINE: disable EPIN interrutps
+ sh $0, 0x08($27) // INTROUTE: disable EPOUT interrutps
+
+ li $9, 0x61
+ sb $9, 0x01($27) // POWER: HSENAB | SUSPENDM | SOFTCONN
+
+ //--------------------------------------------------------------
+ // Initialize USB states
+ //--------------------------------------------------------------
+ li $22, 0 // set EP0 to IDLE state
+ li $23, 1 // no data stage
+
+ //--------------------------------------------------------------
+ // Main loop of polling the usb commands
+ //--------------------------------------------------------------
+usb_command_loop:
+ lbu $9, 0x0a($27) // read INTRUSB
+ andi $9, 0x04 // check USB_INTR_RESET
+ beqz $9, check_intr_ep0in
+ nop
+
+ //--------------------------------------------------------------
+ // 1. Handle USB reset interrupt
+ //--------------------------------------------------------------
+handle_reset_intr:
+ lbu $9, 0x01($27) // read POWER
+ andi $9, 0x10 // test HS_MODE
+ bnez $9, _usb_set_maxpktsize
+ li $9, 512 // max packet size of HS mode
+ li $9, 64 // max packet size of FS mode
+
+_usb_set_maxpktsize:
+ li $8, 1
+ sb $8, 0x0e($27) // set INDEX 1
+
+ sh $9, 0x10($27) // INMAXP
+ sb $0, 0x13($27) // INCSRH
+ sh $9, 0x14($27) // OUTMAXP
+ sb $0, 0x17($27) // OUTCSRH
+
+_usb_flush_fifo:
+ li $8, 0x48 // INCSR_CDT && INCSR_FF
+ sb $8, 0x12($27) // INCSR
+ li $8, 0x90 // OUTCSR_CDT && OUTCSR_FF
+ sb $8, 0x16($27) // OUTCSR
+
+ li $22, 0 // set EP0 to IDLE state
+ li $23, 1 // no data stage
+
+ //--------------------------------------------------------------
+ // 2. Check and handle EP0 interrupt
+ //--------------------------------------------------------------
+check_intr_ep0in:
+ lhu $10, 0x02($27) // read INTRIN
+ andi $9, $10, 0x1 // check EP0 interrupt
+ beqz $9, check_intr_ep1in
+ nop
+
+handle_ep0_intr:
+ sb $0, 0x0e($27) // set INDEX 0
+ lbu $11, 0x12($27) // read CSR0
+
+ andi $9, $11, 0x04 // check SENTSTALL
+ beqz $9, _ep0_setupend
+ nop
+
+_ep0_sentstall:
+ andi $9, $11, 0xdb
+ sb $9, 0x12($27) // clear SENDSTALL and SENTSTALL
+ li $22, 0 // set EP0 to IDLE state
+
+_ep0_setupend:
+ andi $9, $11, 0x10 // check SETUPEND
+ beqz $9, ep0_idle_state
+ nop
+
+ ori $9, $11, 0x80
+ sb $9, 0x12($27) // set SVDSETUPEND
+ li $22, 0 // set EP0 to IDLE state
+
+ep0_idle_state:
+ bnez $22, ep0_tx_state
+ nop
+
+ //--------------------------------------------------------------
+ // 2.1 Handle EP0 IDLE state interrupt
+ //--------------------------------------------------------------
+ andi $9, $11, 0x01 // check OUTPKTRDY
+ beqz $9, check_intr_ep1in
+ nop
+
+ //--------------------------------------------------------------
+ // Read 8-bytes setup packet from the FIFO
+ //--------------------------------------------------------------
+ lw $25, 0x20($27) // first word of setup packet
+ lw $26, 0x20($27) // second word of setup packet
+
+ andi $9, $25, 0x60 // bRequestType & USB_TYPE_MASK
+ beqz $9, _ep0_std_req
+ nop
+
+ //--------------------------------------------------------------
+ // 2.1.1 Vendor-specific setup request
+ //--------------------------------------------------------------
+_ep0_vend_req:
+ li $22, 0 // set EP0 to IDLE state
+ li $23, 1 // NoData = 1
+
+ andi $9, $25, 0xff00 // check bRequest
+ srl $9, $9, 8
+ beqz $9, __ep0_get_cpu_info
+ sub $8, $9, 0x1
+ beqz $8, __ep0_set_data_address
+ sub $8, $9, 0x2
+ beqz $8, __ep0_set_data_length
+ sub $8, $9, 0x3
+ beqz $8, __ep0_flush_caches
+ sub $8, $9, 0x4
+ beqz $8, __ep0_prog_start1
+ sub $8, $9, 0x5
+ beqz $8, __ep0_prog_start2
+ nop
+ b _ep0_idle_state_fini // invalid request
+ nop
+
+__ep0_get_cpu_info:
+ load_addr $20, cpu_info_data // data pointer to transfer
+ li $21, 8 // bytes left to transfer
+ li $22, 1 // set EP0 to TX state
+ li $23, 0 // NoData = 0
+
+ b _ep0_idle_state_fini
+ nop
+
+__ep0_set_data_address:
+ li $9, 0xffff0000
+ and $9, $25, $9
+ andi $8, $26, 0xffff
+ or $20, $9, $8 // data address of next transfer
+
+ b _ep0_idle_state_fini
+ nop
+
+__ep0_set_data_length:
+ li $9, 0xffff0000
+ and $9, $25, $9
+ andi $8, $26, 0xffff
+ or $21, $9, $8 // data length of next transfer
+
+ li $9, 0x48 // SVDOUTPKTRDY and DATAEND
+ sb $9, 0x12($27) // CSR0
+
+ // We must write packet to FIFO before EP1-IN interrupt here.
+ b handle_epin1_intr
+ nop
+
+__ep0_flush_caches:
+ // Flush dcache and invalidate icache.
+ li $8, 0x80000000
+ addi $9, $8, 0x3fe0 // total 16KB
+
+1:
+ cache 0x0, 0($8) // Index_Invalidate_I
+ cache 0x1, 0($8) // Index_Writeback_Inv_D
+ bne $8, $9, 1b
+ addiu $8, $8, 32
+
+ // flush write-buffer
+ sync
+
+ // Invalidate BTB
+ mfc0 $8, $16, 7 // CP0_CONFIG
+ nop
+ ori $8, 2
+ mtc0 $8, $16, 7
+ nop
+
+ b _ep0_idle_state_fini
+ nop
+
+__ep0_prog_start1:
+ li $9, 0x48 // SVDOUTPKTRDY and DATAEND
+ sb $9, 0x12($27) // CSR0
+
+ li $9, 0xffff0000
+ and $9, $25, $9
+ andi $8, $26, 0xffff
+ or $20, $9, $8 // target address
+
+ b xfer_d2i
+ li $19, 0x2000 // 16KB data length
+
+__ep0_prog_start2:
+ li $9, 0x48 // SVDOUTPKTRDY and DATAEND
+ sb $9, 0x12($27) // CSR0
+
+ li $9, 0xffff0000
+ and $9, $25, $9
+ andi $8, $26, 0xffff
+ or $20, $9, $8 // target address
+
+ jalr $20 // jump, and place the return address in $31
+ nop
+
+__ep0_prog_start2_return:
+ // User code can return to here after executing itself, by jumping to $31.
+ b usb_boot_return
+ nop
+
+ //--------------------------------------------------------------
+ // 2.1.2 Standard setup request
+ //--------------------------------------------------------------
+_ep0_std_req:
+ andi $12, $25, 0xff00 // check bRequest
+ srl $12, $12, 8
+ sub $9, $12, 0x05 // check USB_REQ_SET_ADDRESS
+ bnez $9, __ep0_req_set_config
+ nop
+
+ //--------------------------------------------------------------
+ // Handle USB_REQ_SET_ADDRESS
+ //--------------------------------------------------------------
+__ep0_req_set_addr:
+ srl $9, $25, 16 // get wValue
+ sb $9, 0x0($27) // set FADDR
+ li $23, 1 // NoData = 1
+ b _ep0_idle_state_fini
+ nop
+
+__ep0_req_set_config:
+ sub $9, $12, 0x09 // check USB_REQ_SET_CONFIGURATION
+ bnez $9, __ep0_req_get_desc
+ nop
+
+ //--------------------------------------------------------------
+ // Handle USB_REQ_SET_CONFIGURATION
+ //--------------------------------------------------------------
+ li $23, 1 // NoData = 1
+ b _ep0_idle_state_fini
+ nop
+
+__ep0_req_get_desc:
+ sub $9, $12, 0x06 // check USB_REQ_GET_DESCRIPTOR
+ bnez $9, _ep0_idle_state_fini
+ li $23, 1 // NoData = 1
+
+ //--------------------------------------------------------------
+ // Handle USB_REQ_GET_DESCRIPTOR
+ //--------------------------------------------------------------
+ li $23, 0 // NoData = 0
+
+ srl $9, $25, 24 // wValue >> 8
+ sub $8, $9, 0x01 // check USB_DT_DEVICE
+ beqz $8, ___ep0_get_dev_desc
+ srl $21, $26, 16 // get wLength
+ sub $8, $9, 0x02 // check USB_DT_CONFIG
+ beqz $8, ___ep0_get_conf_desc
+ sub $8, $9, 0x03 // check USB_DT_STRING
+ beqz $8, ___ep0_get_string_desc
+ sub $8, $9, 0x06 // check USB_DT_DEVICE_QUALIFIER
+ beqz $8, ___ep0_get_dev_qualifier
+ nop
+ b _ep0_idle_state_fini
+ nop
+
+___ep0_get_dev_desc:
+ load_addr $20, device_desc // data pointer
+ li $22, 1 // set EP0 to TX state
+ sub $8, $21, 18
+ blez $8, _ep0_idle_state_fini // wLength <= 18
+ nop
+ li $21, 18 // max length of device_desc
+ b _ep0_idle_state_fini
+ nop
+
+___ep0_get_dev_qualifier:
+ load_addr $20, dev_qualifier // data pointer
+ li $22, 1 // set EP0 to TX state
+ sub $8, $21, 10
+ blez $8, _ep0_idle_state_fini // wLength <= 10
+ nop
+ li $21, 10 // max length of dev_qualifier
+ b _ep0_idle_state_fini
+ nop
+
+___ep0_get_conf_desc:
+ load_addr $20, config_desc_fs // data pointer of FS mode
+ lbu $8, 0x01($27) // read POWER
+ andi $8, 0x10 // test HS_MODE
+ beqz $8, ___ep0_get_conf_desc2
+ nop
+ load_addr $20, config_desc_hs // data pointer of HS mode
+
+___ep0_get_conf_desc2:
+ li $22, 1 // set EP0 to TX state
+ sub $8, $21, 32
+ blez $8, _ep0_idle_state_fini // wLength <= 32
+ nop
+ li $21, 32 // max length of config_desc
+ b _ep0_idle_state_fini
+ nop
+
+___ep0_get_string_desc:
+ li $22, 1 // set EP0 to TX state
+
+ srl $9, $25, 16 // wValue & 0xff
+ andi $9, 0xff
+
+ sub $8, $9, 1
+ beqz $8, ___ep0_get_string_manufacture
+ sub $8, $9, 2
+ beqz $8, ___ep0_get_string_product
+ nop
+
+___ep0_get_string_lang_ids:
+ load_addr $20, string_lang_ids // data pointer
+ b _ep0_idle_state_fini
+ li $21, 4 // data length
+
+___ep0_get_string_manufacture:
+ load_addr $20, string_manufacture // data pointer
+ b _ep0_idle_state_fini
+ li $21, 16 // data length
+
+___ep0_get_string_product:
+ load_addr $20, string_product // data pointer
+ b _ep0_idle_state_fini
+ li $21, 46 // data length
+
+_ep0_idle_state_fini:
+ li $9, 0x40 // SVDOUTPKTRDY
+ beqz $23, _ep0_idle_state_fini2
+ nop
+ ori $9, $9, 0x08 // DATAEND
+_ep0_idle_state_fini2:
+ sb $9, 0x12($27) // CSR0
+ beqz $22, check_intr_ep1in
+ nop
+
+ //--------------------------------------------------------------
+ // 2.2 Handle EP0 TX state interrupt
+ //--------------------------------------------------------------
+ep0_tx_state:
+ sub $9, $22, 1
+ bnez $9, check_intr_ep1in
+ nop
+
+ sub $9, $21, 64 // max packetsize
+ blez $9, _ep0_tx_state2 // data count <= 64
+ ori $19, $21, 0
+ li $19, 64
+
+_ep0_tx_state2:
+ beqz $19, _ep0_tx_state3 // send ZLP
+ ori $18, $19, 0 // record bytes to be transferred
+ sub $21, $21, $19 // decrement data count
+
+_ep0_fifo_write_loop:
+ lbu $9, 0($20) // read data
+ sb $9, 0x20($27) // load FIFO
+ sub $19, $19, 1 // decrement counter
+ bnez $19, _ep0_fifo_write_loop
+ addi $20, $20, 1 // increment data pointer
+
+ sub $9, $18, 64 // max packetsize
+ beqz $9, _ep0_tx_state4
+ nop
+
+_ep0_tx_state3:
+ // transferred bytes < max packetsize
+ li $9, 0x0a // set INPKTRDY and DATAEND
+ sb $9, 0x12($27) // CSR0
+ li $22, 0 // set EP0 to IDLE state
+ b check_intr_ep1in
+ nop
+
+_ep0_tx_state4:
+ // transferred bytes == max packetsize
+ li $9, 0x02 // set INPKTRDY
+ sb $9, 0x12($27) // CSR0
+ b check_intr_ep1in
+ nop
+
+ //--------------------------------------------------------------
+ // 3. Check and handle EP1 BULK-IN interrupt
+ //--------------------------------------------------------------
+check_intr_ep1in:
+ andi $9, $10, 0x2 // check EP1 IN interrupt
+ beqz $9, check_intr_ep1out
+ nop
+
+handle_epin1_intr:
+ li $9, 1
+ sb $9, 0x0e($27) // set INDEX 1
+ lbu $9, 0x12($27) // read INCSR
+
+ andi $8, $9, 0x2 // check INCSR_FFNOTEMPT
+ bnez $8, _epin1_tx_state4
+ nop
+
+_epin1_write_fifo:
+ lhu $9, 0x10($27) // get INMAXP
+ sub $8, $21, $9
+ blez $8, _epin1_tx_state1 // bytes left <= INMAXP
+ ori $19, $21, 0
+ ori $19, $9, 0
+
+_epin1_tx_state1:
+ beqz $19, _epin1_tx_state4 // No data
+ nop
+
+ sub $21, $21, $19 // decrement data count
+
+ srl $5, $19, 2 // # of word
+ andi $6, $19, 0x3 // # of byte
+ beqz $5, _epin1_tx_state2
+ nop
+
+_epin1_fifo_write_word:
+ lw $9, 0($20) // read data from source address
+ sw $9, 0x24($27) // write FIFO
+ sub $5, $5, 1 // decrement counter
+ bnez $5, _epin1_fifo_write_word
+ addiu $20, $20, 4 // increment dest address
+
+_epin1_tx_state2:
+ beqz $6, _epin1_tx_state3
+ nop
+
+_epin1_fifo_write_byte:
+ lbu $9, 0($20) // read data from source address
+ sb $9, 0x24($27) // write FIFO
+ sub $6, $6, 1 // decrement counter
+ bnez $6, _epin1_fifo_write_byte
+ addiu $20, $20, 1 // increment dest address
+
+_epin1_tx_state3:
+ li $9, 0x1
+ sb $9, 0x12($27) // INCSR, set INPKTRDY
+
+_epin1_tx_state4:
+ // nop
+
+ //--------------------------------------------------------------
+ // 4. Check and handle EP1 BULK-OUT interrupt
+ //--------------------------------------------------------------
+check_intr_ep1out:
+ lhu $9, 0x04($27) // read INTROUT
+ andi $9, 0x2
+ beqz $9, check_status_next
+ nop
+
+handle_epout1_intr:
+ li $9, 1
+ sb $9, 0x0e($27) // set INDEX 1
+
+ lbu $9, 0x16($27) // read OUTCSR
+ andi $9, 0x1 // check OUTPKTRDY
+ beqz $9, check_status_next
+ nop
+
+_epout1_read_fifo:
+ lhu $19, 0x18($27) // read OUTCOUNT
+ srl $5, $19, 2 // # of word
+ andi $6, $19, 0x3 // # of byte
+ beqz $5, _epout1_rx_state1
+ nop
+
+_epout1_fifo_read_word:
+ lw $9, 0x24($27) // read FIFO
+ sw $9, 0($20) // store to dest address
+ sub $5, $5, 1 // decrement counter
+ bnez $5, _epout1_fifo_read_word
+ addiu $20, $20, 4 // increment dest address
+
+_epout1_rx_state1:
+ beqz $6, _epout1_rx_state2
+ nop
+
+_epout1_fifo_read_byte:
+ lbu $9, 0x24($27) // read FIFO
+ sb $9, 0($20) // store to dest address
+ sub $6, $6, 1 // decrement counter
+ bnez $6, _epout1_fifo_read_byte
+ addiu $20, $20, 1 // increment dest address
+
+_epout1_rx_state2:
+ sb $0, 0x16($27) // clear OUTPKTRDY
+
+check_status_next:
+ b usb_command_loop
+ nop
+
+//--------------------------------------------------------------
+// Device/Configuration/Interface/Endpoint/String Descriptors
+//--------------------------------------------------------------
+
+ .align 2
+device_desc:
+ .byte 0x12 // bLength
+ .byte 0x01 // bDescriptorType
+ .byte 0x00 // bcdUSB
+ .byte 0x02 // bcdUSB
+ .byte 0x00 // bDeviceClass
+ .byte 0x00 // bDeviceSubClass
+ .byte 0x00 // bDeviceProtocol
+ .byte 0x40 // bMaxPacketSize0
+ .byte 0x1a // idVendor
+ .byte 0x60 // idVendor
+ .byte 0x40 // idProduct
+ .byte 0x47 // idProduct
+ .byte 0x00 // bcdDevice
+ .byte 0x01 // bcdDevice
+ .byte 0x01 // iManufacturer
+ .byte 0x02 // iProduct
+ .byte 0x00 // iSerialNumber
+ .byte 0x01 // bNumConfigurations
+
+ .align 2
+dev_qualifier:
+ .byte 0x0a // bLength
+ .byte 0x06 // bDescriptorType
+ .byte 0x00 // bcdUSB
+ .byte 0x02 // bcdUSB
+ .byte 0x00 // bDeviceClass
+ .byte 0x00 // bDeviceSubClass
+ .byte 0x00 // bDeviceProtocol
+ .byte 0x40 // bMaxPacketSize0
+ .byte 0x01 // bNumConfigurations
+ .byte 0x00 // bRESERVED
+
+ .align 2
+config_desc_hs:
+ .byte 0x09 // bLength
+ .byte 0x02 // bDescriptorType
+ .byte 0x20 // wTotalLength
+ .byte 0x00 // wTotalLength
+ .byte 0x01 // bNumInterfaces
+ .byte 0x01 // bConfigurationValue
+ .byte 0x00 // iConfiguration
+ .byte 0xc0 // bmAttributes
+ .byte 0x01 // MaxPower
+intf_desc_hs:
+ .byte 0x09 // bLength
+ .byte 0x04 // bDescriptorType
+ .byte 0x00 // bInterfaceNumber
+ .byte 0x00 // bAlternateSetting
+ .byte 0x02 // bNumEndpoints
+ .byte 0xff // bInterfaceClass
+ .byte 0x00 // bInterfaceSubClass
+ .byte 0x50 // bInterfaceProtocol
+ .byte 0x00 // iInterface
+ep1_desc_hs:
+ .byte 0x07 // bLength
+ .byte 0x05 // bDescriptorType
+ .byte 0x01 // bEndpointAddress
+ .byte 0x02 // bmAttributes
+ .byte 0x00 // wMaxPacketSize
+ .byte 0x02 // wMaxPacketSize
+ .byte 0x00 // bInterval
+ep2_desc_hs:
+ .byte 0x07 // bLength
+ .byte 0x05 // bDescriptorType
+ .byte 0x81 // bEndpointAddress
+ .byte 0x02 // bmAttributes
+ .byte 0x00 // wMaxPacketSize
+ .byte 0x02 // wMaxPacketSize
+ .byte 0x00 // bInterval
+
+ .align 2
+config_desc_fs:
+ .byte 0x09 // bLength
+ .byte 0x02 // bDescriptorType
+ .byte 0x20 // wTotalLength
+ .byte 0x00 // wTotalLength
+ .byte 0x01 // bNumInterfaces
+ .byte 0x01 // bConfigurationValue
+ .byte 0x00 // iConfiguration
+ .byte 0xc0 // bmAttributes
+ .byte 0x01 // MaxPower
+intf_desc_fs:
+ .byte 0x09 // bLength
+ .byte 0x04 // bDescriptorType
+ .byte 0x00 // bInterfaceNumber
+ .byte 0x00 // bAlternateSetting
+ .byte 0x02 // bNumEndpoints
+ .byte 0xff // bInterfaceClass
+ .byte 0x00 // bInterfaceSubClass
+ .byte 0x50 // bInterfaceProtocol
+ .byte 0x00 // iInterface
+ep1_desc_fs:
+ .byte 0x07 // bLength
+ .byte 0x05 // bDescriptorType
+ .byte 0x01 // bEndpointAddress
+ .byte 0x02 // bmAttributes
+ .byte 0x40 // wMaxPacketSize
+ .byte 0x00 // wMaxPacketSize
+ .byte 0x00 // bInterval
+ep2_desc_fs:
+ .byte 0x07 // bLength
+ .byte 0x05 // bDescriptorType
+ .byte 0x81 // bEndpointAddress
+ .byte 0x02 // bmAttributes
+ .byte 0x40 // wMaxPacketSize
+ .byte 0x00 // wMaxPacketSize
+ .byte 0x00 // bInterval
+
+ .align 2
+string_lang_ids:
+ .byte 0x04
+ .byte 0x03
+ .byte 0x09
+ .byte 0x04
+
+ .align 2
+string_manufacture:
+ .byte 0x10
+ .byte 0x03
+ .byte 0x49
+ .byte 0x00
+ .byte 0x6e
+ .byte 0x00
+ .byte 0x67
+ .byte 0x00
+ .byte 0x65
+ .byte 0x00
+ .byte 0x6e
+ .byte 0x00
+ .byte 0x69
+ .byte 0x00
+ .byte 0x63
+ .byte 0x00
+
+ .align 2
+string_product:
+ .byte 0x2e
+ .byte 0x03
+ .byte 0x4a
+ .byte 0x00
+ .byte 0x5a
+ .byte 0x00
+ .byte 0x34
+ .byte 0x00
+ .byte 0x37
+ .byte 0x00
+ .byte 0x34
+ .byte 0x00
+ .byte 0x30
+ .byte 0x00
+ .byte 0x20
+ .byte 0x00
+ .byte 0x55
+ .byte 0x00
+ .byte 0x53
+ .byte 0x00
+ .byte 0x42
+ .byte 0x00
+ .byte 0x20
+ .byte 0x00
+ .byte 0x42
+ .byte 0x00
+ .byte 0x6f
+ .byte 0x00
+ .byte 0x6f
+ .byte 0x00
+ .byte 0x74
+ .byte 0x00
+ .byte 0x20
+ .byte 0x00
+ .byte 0x44
+ .byte 0x00
+ .byte 0x65
+ .byte 0x00
+ .byte 0x76
+ .byte 0x00
+ .byte 0x69
+ .byte 0x00
+ .byte 0x63
+ .byte 0x00
+ .byte 0x65
+ .byte 0x00
+
+ .align 2
+cpu_info_data:
+ .byte 0x4a
+ .byte 0x5a
+ .byte 0x34
+ .byte 0x37
+ .byte 0x34
+ .byte 0x30
+ .byte 0x56
+ .byte 0x31
+usbboot_end:
+
+ .set reorder
diff --git a/package/uboot-xburst/files/include/asm-mips/jz4740.h b/package/uboot-xburst/files/include/asm-mips/jz4740.h
new file mode 100644
index 000000000..4098873ec
--- /dev/null
+++ b/package/uboot-xburst/files/include/asm-mips/jz4740.h
@@ -0,0 +1,4892 @@
+/*
+ * Include file for Ingenic Semiconductor's JZ4740 CPU.
+ */
+#ifndef __JZ4740_H__
+#define __JZ4740_H__
+
+#ifndef __ASSEMBLY__
+#define UCOS_CSP 0
+
+#if UCOS_CSP
+#define __KERNEL__
+#include <bsp.h>
+#include <types.h>
+
+#include <sysdefs.h>
+#include <cacheops.h>
+#define KSEG0 KSEG0BASE
+#else
+#include <asm/addrspace.h>
+#include <asm/cacheops.h>
+#endif
+
+#define cache_unroll(base,op) \
+ __asm__ __volatile__(" \
+ .set noreorder; \
+ .set mips3; \
+ cache %1, (%0); \
+ .set mips0; \
+ .set reorder" \
+ : \
+ : "r" (base), \
+ "i" (op));
+
+static inline void jz_flush_dcache(void)
+{
+ unsigned long start;
+ unsigned long end;
+
+ start = KSEG0;
+ end = start + CONFIG_SYS_DCACHE_SIZE;
+ while (start < end) {
+ cache_unroll(start,Index_Writeback_Inv_D);
+ start += CONFIG_SYS_CACHELINE_SIZE;
+ }
+}
+
+static inline void jz_flush_icache(void)
+{
+ unsigned long start;
+ unsigned long end;
+
+ start = KSEG0;
+ end = start + CONFIG_SYS_ICACHE_SIZE;
+ while(start < end) {
+ cache_unroll(start,Index_Invalidate_I);
+ start += CONFIG_SYS_CACHELINE_SIZE;
+ }
+}
+
+/* cpu pipeline flush */
+static inline void jz_sync(void)
+{
+ __asm__ volatile ("sync");
+}
+
+static inline void jz_writeb(u32 address, u8 value)
+{
+ *((volatile u8 *)address) = value;
+}
+
+static inline void jz_writew(u32 address, u16 value)
+{
+ *((volatile u16 *)address) = value;
+}
+
+static inline void jz_writel(u32 address, u32 value)
+{
+ *((volatile u32 *)address) = value;
+}
+
+static inline u8 jz_readb(u32 address)
+{
+ return *((volatile u8 *)address);
+}
+
+static inline u16 jz_readw(u32 address)
+{
+ return *((volatile u16 *)address);
+}
+
+static inline u32 jz_readl(u32 address)
+{
+ return *((volatile u32 *)address);
+}
+
+#define REG8(addr) *((volatile u8 *)(addr))
+#define REG16(addr) *((volatile u16 *)(addr))
+#define REG32(addr) *((volatile u32 *)(addr))
+
+#else
+
+#define REG8(addr) (addr)
+#define REG16(addr) (addr)
+#define REG32(addr) (addr)
+
+#endif /* !ASSEMBLY */
+
+/* Boot ROM Specification */
+/* NOR Boot config */
+#define JZ4740_NORBOOT_8BIT 0x00000000 /* 8-bit data bus flash */
+#define JZ4740_NORBOOT_16BIT 0x10101010 /* 16-bit data bus flash */
+#define JZ4740_NORBOOT_32BIT 0x20202020 /* 32-bit data bus flash */
+
+/* NAND Boot config */
+#define JZ4740_NANDBOOT_B8R3 0xffffffff /* 8-bit bus & 3 row cycles */
+#define JZ4740_NANDBOOT_B8R2 0xf0f0f0f0 /* 8-bit bus & 2 row cycles */
+#define JZ4740_NANDBOOT_B16R3 0x0f0f0f0f /* 16-bit bus & 3 row cycles */
+#define JZ4740_NANDBOOT_B16R2 0x00000000 /* 16-bit bus & 2 row cycles */
+
+
+/* Register Definitions */
+#define CPM_BASE 0xB0000000
+#define INTC_BASE 0xB0001000
+#define TCU_BASE 0xB0002000
+#define WDT_BASE 0xB0002000
+#define RTC_BASE 0xB0003000
+#define GPIO_BASE 0xB0010000
+#define AIC_BASE 0xB0020000
+#define ICDC_BASE 0xB0020000
+#define MSC_BASE 0xB0021000
+#define UART0_BASE 0xB0030000
+#define I2C_BASE 0xB0042000
+#define SSI_BASE 0xB0043000
+#define SADC_BASE 0xB0070000
+#define EMC_BASE 0xB3010000
+#define DMAC_BASE 0xB3020000
+#define UHC_BASE 0xB3030000
+#define UDC_BASE 0xB3040000
+#define LCD_BASE 0xB3050000
+#define SLCD_BASE 0xB3050000
+#define CIM_BASE 0xB3060000
+#define ETH_BASE 0xB3100000
+
+
+/*
+ * INTC (Interrupt Controller)
+ */
+#define INTC_ISR (INTC_BASE + 0x00)
+#define INTC_IMR (INTC_BASE + 0x04)
+#define INTC_IMSR (INTC_BASE + 0x08)
+#define INTC_IMCR (INTC_BASE + 0x0c)
+#define INTC_IPR (INTC_BASE + 0x10)
+
+#define REG_INTC_ISR REG32(INTC_ISR)
+#define REG_INTC_IMR REG32(INTC_IMR)
+#define REG_INTC_IMSR REG32(INTC_IMSR)
+#define REG_INTC_IMCR REG32(INTC_IMCR)
+#define REG_INTC_IPR REG32(INTC_IPR)
+
+/* 1st-level interrupts */
+#define IRQ_I2C 1
+#define IRQ_UHC 3
+#define IRQ_UART0 9
+#define IRQ_SADC 12
+#define IRQ_MSC 14
+#define IRQ_RTC 15
+#define IRQ_SSI 16
+#define IRQ_CIM 17
+#define IRQ_AIC 18
+#define IRQ_ETH 19
+#define IRQ_DMAC 20
+#define IRQ_TCU2 21
+#define IRQ_TCU1 22
+#define IRQ_TCU0 23
+#define IRQ_UDC 24
+#define IRQ_GPIO3 25
+#define IRQ_GPIO2 26
+#define IRQ_GPIO1 27
+#define IRQ_GPIO0 28
+#define IRQ_IPU 29
+#define IRQ_LCD 30
+
+/* 2nd-level interrupts */
+#define IRQ_DMA_0 32 /* 32 to 37 for DMAC channel 0 to 5 */
+#define IRQ_GPIO_0 48 /* 48 to 175 for GPIO pin 0 to 127 */
+
+
+/*
+ * RTC
+ */
+#define RTC_RCR (RTC_BASE + 0x00) /* RTC Control Register */
+#define RTC_RSR (RTC_BASE + 0x04) /* RTC Second Register */
+#define RTC_RSAR (RTC_BASE + 0x08) /* RTC Second Alarm Register */
+#define RTC_RGR (RTC_BASE + 0x0c) /* RTC Regulator Register */
+
+#define RTC_HCR (RTC_BASE + 0x20) /* Hibernate Control Register */
+#define RTC_HWFCR (RTC_BASE + 0x24) /* Hibernate Wakeup Filter Counter Reg */
+#define RTC_HRCR (RTC_BASE + 0x28) /* Hibernate Reset Counter Register */
+#define RTC_HWCR (RTC_BASE + 0x2c) /* Hibernate Wakeup Control Register */
+#define RTC_HWRSR (RTC_BASE + 0x30) /* Hibernate Wakeup Status Register */
+#define RTC_HSPR (RTC_BASE + 0x34) /* Hibernate Scratch Pattern Register */
+
+#define REG_RTC_RCR REG32(RTC_RCR)
+#define REG_RTC_RSR REG32(RTC_RSR)
+#define REG_RTC_RSAR REG32(RTC_RSAR)
+#define REG_RTC_RGR REG32(RTC_RGR)
+#define REG_RTC_HCR REG32(RTC_HCR)
+#define REG_RTC_HWFCR REG32(RTC_HWFCR)
+#define REG_RTC_HRCR REG32(RTC_HRCR)
+#define REG_RTC_HWCR REG32(RTC_HWCR)
+#define REG_RTC_HWRSR REG32(RTC_HWRSR)
+#define REG_RTC_HSPR REG32(RTC_HSPR)
+
+/* RTC Control Register */
+#define RTC_RCR_WRDY (1 << 7) /* Write Ready Flag */
+#define RTC_RCR_HZ (1 << 6) /* 1Hz Flag */
+#define RTC_RCR_HZIE (1 << 5) /* 1Hz Interrupt Enable */
+#define RTC_RCR_AF (1 << 4) /* Alarm Flag */
+#define RTC_RCR_AIE (1 << 3) /* Alarm Interrupt Enable */
+#define RTC_RCR_AE (1 << 2) /* Alarm Enable */
+#define RTC_RCR_RTCE (1 << 0) /* RTC Enable */
+
+/* RTC Regulator Register */
+#define RTC_RGR_LOCK (1 << 31) /* Lock Bit */
+#define RTC_RGR_ADJC_BIT 16
+#define RTC_RGR_ADJC_MASK (0x3ff << RTC_RGR_ADJC_BIT)
+#define RTC_RGR_NC1HZ_BIT 0
+#define RTC_RGR_NC1HZ_MASK (0xffff << RTC_RGR_NC1HZ_BIT)
+
+/* Hibernate Control Register */
+#define RTC_HCR_PD (1 << 0) /* Power Down */
+
+/* Hibernate Wakeup Filter Counter Register */
+#define RTC_HWFCR_BIT 5
+#define RTC_HWFCR_MASK (0x7ff << RTC_HWFCR_BIT)
+
+/* Hibernate Reset Counter Register */
+#define RTC_HRCR_BIT 5
+#define RTC_HRCR_MASK (0x7f << RTC_HRCR_BIT)
+
+/* Hibernate Wakeup Control Register */
+#define RTC_HWCR_EALM (1 << 0) /* RTC alarm wakeup enable */
+
+/* Hibernate Wakeup Status Register */
+#define RTC_HWRSR_HR (1 << 5) /* Hibernate reset */
+#define RTC_HWRSR_PPR (1 << 4) /* PPR reset */
+#define RTC_HWRSR_PIN (1 << 1) /* Wakeup pin status bit */
+#define RTC_HWRSR_ALM (1 << 0) /* RTC alarm status bit */
+
+
+/*************************************************************************
+ * CPM (Clock reset and Power control Management)
+ *************************************************************************/
+#define CPM_CPCCR (CPM_BASE+0x00)
+#define CPM_CPPCR (CPM_BASE+0x10)
+#define CPM_I2SCDR (CPM_BASE+0x60)
+#define CPM_LPCDR (CPM_BASE+0x64)
+#define CPM_MSCCDR (CPM_BASE+0x68)
+#define CPM_UHCCDR (CPM_BASE+0x6C)
+
+#define CPM_LCR (CPM_BASE+0x04)
+#define CPM_CLKGR (CPM_BASE+0x20)
+#define CPM_SCR (CPM_BASE+0x24)
+
+#define CPM_HCR (CPM_BASE+0x30)
+#define CPM_HWFCR (CPM_BASE+0x34)
+#define CPM_HRCR (CPM_BASE+0x38)
+#define CPM_HWCR (CPM_BASE+0x3c)
+#define CPM_HWSR (CPM_BASE+0x40)
+#define CPM_HSPR (CPM_BASE+0x44)
+
+#define CPM_RSR (CPM_BASE+0x08)
+
+
+#define REG_CPM_CPCCR REG32(CPM_CPCCR)
+#define REG_CPM_CPPCR REG32(CPM_CPPCR)
+#define REG_CPM_I2SCDR REG32(CPM_I2SCDR)
+#define REG_CPM_LPCDR REG32(CPM_LPCDR)
+#define REG_CPM_MSCCDR REG32(CPM_MSCCDR)
+#define REG_CPM_UHCCDR REG32(CPM_UHCCDR)
+
+#define REG_CPM_LCR REG32(CPM_LCR)
+#define REG_CPM_CLKGR REG32(CPM_CLKGR)
+#define REG_CPM_SCR REG32(CPM_SCR)
+#define REG_CPM_HCR REG32(CPM_HCR)
+#define REG_CPM_HWFCR REG32(CPM_HWFCR)
+#define REG_CPM_HRCR REG32(CPM_HRCR)
+#define REG_CPM_HWCR REG32(CPM_HWCR)
+#define REG_CPM_HWSR REG32(CPM_HWSR)
+#define REG_CPM_HSPR REG32(CPM_HSPR)
+
+#define REG_CPM_RSR REG32(CPM_RSR)
+
+
+/* Clock Control Register */
+#define CPM_CPCCR_I2CS (1 << 31)
+#define CPM_CPCCR_CLKOEN (1 << 30)
+#define CPM_CPCCR_UCS (1 << 29)
+#define CPM_CPCCR_UDIV_BIT 23
+#define CPM_CPCCR_UDIV_MASK (0x3f << CPM_CPCCR_UDIV_BIT)
+#define CPM_CPCCR_CE (1 << 22)
+#define CPM_CPCCR_PCS (1 << 21)
+#define CPM_CPCCR_LDIV_BIT 16
+#define CPM_CPCCR_LDIV_MASK (0x1f << CPM_CPCCR_LDIV_BIT)
+#define CPM_CPCCR_MDIV_BIT 12
+#define CPM_CPCCR_MDIV_MASK (0x0f << CPM_CPCCR_MDIV_BIT)
+#define CPM_CPCCR_PDIV_BIT 8
+#define CPM_CPCCR_PDIV_MASK (0x0f << CPM_CPCCR_PDIV_BIT)
+#define CPM_CPCCR_HDIV_BIT 4
+#define CPM_CPCCR_HDIV_MASK (0x0f << CPM_CPCCR_HDIV_BIT)
+#define CPM_CPCCR_CDIV_BIT 0
+#define CPM_CPCCR_CDIV_MASK (0x0f << CPM_CPCCR_CDIV_BIT)
+
+/* I2S Clock Divider Register */
+#define CPM_I2SCDR_I2SDIV_BIT 0
+#define CPM_I2SCDR_I2SDIV_MASK (0x1ff << CPM_I2SCDR_I2SDIV_BIT)
+
+/* LCD Pixel Clock Divider Register */
+#define CPM_LPCDR_PIXDIV_BIT 0
+#define CPM_LPCDR_PIXDIV_MASK (0x1ff << CPM_LPCDR_PIXDIV_BIT)
+
+/* MSC Clock Divider Register */
+#define CPM_MSCCDR_MSCDIV_BIT 0
+#define CPM_MSCCDR_MSCDIV_MASK (0x1f << CPM_MSCCDR_MSCDIV_BIT)
+
+/* PLL Control Register */
+#define CPM_CPPCR_PLLM_BIT 23
+#define CPM_CPPCR_PLLM_MASK (0x1ff << CPM_CPPCR_PLLM_BIT)
+#define CPM_CPPCR_PLLN_BIT 18
+#define CPM_CPPCR_PLLN_MASK (0x1f << CPM_CPPCR_PLLN_BIT)
+#define CPM_CPPCR_PLLOD_BIT 16
+#define CPM_CPPCR_PLLOD_MASK (0x03 << CPM_CPPCR_PLLOD_BIT)
+#define CPM_CPPCR_PLLS (1 << 10)
+#define CPM_CPPCR_PLLBP (1 << 9)
+#define CPM_CPPCR_PLLEN (1 << 8)
+#define CPM_CPPCR_PLLST_BIT 0
+#define CPM_CPPCR_PLLST_MASK (0xff << CPM_CPPCR_PLLST_BIT)
+
+/* Low Power Control Register */
+#define CPM_LCR_DOZE_DUTY_BIT 3
+#define CPM_LCR_DOZE_DUTY_MASK (0x1f << CPM_LCR_DOZE_DUTY_BIT)
+#define CPM_LCR_DOZE_ON (1 << 2)
+#define CPM_LCR_LPM_BIT 0
+#define CPM_LCR_LPM_MASK (0x3 << CPM_LCR_LPM_BIT)
+ #define CPM_LCR_LPM_IDLE (0x0 << CPM_LCR_LPM_BIT)
+ #define CPM_LCR_LPM_SLEEP (0x1 << CPM_LCR_LPM_BIT)
+
+/* Clock Gate Register */
+#define CPM_CLKGR_UART1 (1 << 15)
+#define CPM_CLKGR_UHC (1 << 14)
+#define CPM_CLKGR_IPU (1 << 13)
+#define CPM_CLKGR_DMAC (1 << 12)
+#define CPM_CLKGR_UDC (1 << 11)
+#define CPM_CLKGR_LCD (1 << 10)
+#define CPM_CLKGR_CIM (1 << 9)
+#define CPM_CLKGR_SADC (1 << 8)
+#define CPM_CLKGR_MSC (1 << 7)
+#define CPM_CLKGR_AIC1 (1 << 6)
+#define CPM_CLKGR_AIC2 (1 << 5)
+#define CPM_CLKGR_SSI (1 << 4)
+#define CPM_CLKGR_I2C (1 << 3)
+#define CPM_CLKGR_RTC (1 << 2)
+#define CPM_CLKGR_TCU (1 << 1)
+#define CPM_CLKGR_UART0 (1 << 0)
+
+/* Sleep Control Register */
+#define CPM_SCR_O1ST_BIT 8
+#define CPM_SCR_O1ST_MASK (0xff << CPM_SCR_O1ST_BIT)
+#define CPM_SCR_UDCPHY_ENABLE (1 << 6)
+#define CPM_SCR_USBPHY_DISABLE (1 << 7)
+#define CPM_SCR_OSC_ENABLE (1 << 4)
+
+/* Hibernate Control Register */
+#define CPM_HCR_PD (1 << 0)
+
+/* Wakeup Filter Counter Register in Hibernate Mode */
+#define CPM_HWFCR_TIME_BIT 0
+#define CPM_HWFCR_TIME_MASK (0x3ff << CPM_HWFCR_TIME_BIT)
+
+/* Reset Counter Register in Hibernate Mode */
+#define CPM_HRCR_TIME_BIT 0
+#define CPM_HRCR_TIME_MASK (0x7f << CPM_HRCR_TIME_BIT)
+
+/* Wakeup Control Register in Hibernate Mode */
+#define CPM_HWCR_WLE_LOW (0 << 2)
+#define CPM_HWCR_WLE_HIGH (1 << 2)
+#define CPM_HWCR_PIN_WAKEUP (1 << 1)
+#define CPM_HWCR_RTC_WAKEUP (1 << 0)
+
+/* Wakeup Status Register in Hibernate Mode */
+#define CPM_HWSR_WSR_PIN (1 << 1)
+#define CPM_HWSR_WSR_RTC (1 << 0)
+
+/* Reset Status Register */
+#define CPM_RSR_HR (1 << 2)
+#define CPM_RSR_WR (1 << 1)
+#define CPM_RSR_PR (1 << 0)
+
+
+/*************************************************************************
+ * TCU (Timer Counter Unit)
+ *************************************************************************/
+#define TCU_TSR (TCU_BASE + 0x1C) /* Timer Stop Register */
+#define TCU_TSSR (TCU_BASE + 0x2C) /* Timer Stop Set Register */
+#define TCU_TSCR (TCU_BASE + 0x3C) /* Timer Stop Clear Register */
+#define TCU_TER (TCU_BASE + 0x10) /* Timer Counter Enable Register */
+#define TCU_TESR (TCU_BASE + 0x14) /* Timer Counter Enable Set Register */
+#define TCU_TECR (TCU_BASE + 0x18) /* Timer Counter Enable Clear Register */
+#define TCU_TFR (TCU_BASE + 0x20) /* Timer Flag Register */
+#define TCU_TFSR (TCU_BASE + 0x24) /* Timer Flag Set Register */
+#define TCU_TFCR (TCU_BASE + 0x28) /* Timer Flag Clear Register */
+#define TCU_TMR (TCU_BASE + 0x30) /* Timer Mask Register */
+#define TCU_TMSR (TCU_BASE + 0x34) /* Timer Mask Set Register */
+#define TCU_TMCR (TCU_BASE + 0x38) /* Timer Mask Clear Register */
+#define TCU_TDFR0 (TCU_BASE + 0x40) /* Timer Data Full Register */
+#define TCU_TDHR0 (TCU_BASE + 0x44) /* Timer Data Half Register */
+#define TCU_TCNT0 (TCU_BASE + 0x48) /* Timer Counter Register */
+#define TCU_TCSR0 (TCU_BASE + 0x4C) /* Timer Control Register */
+#define TCU_TDFR1 (TCU_BASE + 0x50)
+#define TCU_TDHR1 (TCU_BASE + 0x54)
+#define TCU_TCNT1 (TCU_BASE + 0x58)
+#define TCU_TCSR1 (TCU_BASE + 0x5C)
+#define TCU_TDFR2 (TCU_BASE + 0x60)
+#define TCU_TDHR2 (TCU_BASE + 0x64)
+#define TCU_TCNT2 (TCU_BASE + 0x68)
+#define TCU_TCSR2 (TCU_BASE + 0x6C)
+#define TCU_TDFR3 (TCU_BASE + 0x70)
+#define TCU_TDHR3 (TCU_BASE + 0x74)
+#define TCU_TCNT3 (TCU_BASE + 0x78)
+#define TCU_TCSR3 (TCU_BASE + 0x7C)
+#define TCU_TDFR4 (TCU_BASE + 0x80)
+#define TCU_TDHR4 (TCU_BASE + 0x84)
+#define TCU_TCNT4 (TCU_BASE + 0x88)
+#define TCU_TCSR4 (TCU_BASE + 0x8C)
+#define TCU_TDFR5 (TCU_BASE + 0x90)
+#define TCU_TDHR5 (TCU_BASE + 0x94)
+#define TCU_TCNT5 (TCU_BASE + 0x98)
+#define TCU_TCSR5 (TCU_BASE + 0x9C)
+
+#define REG_TCU_TSR REG32(TCU_TSR)
+#define REG_TCU_TSSR REG32(TCU_TSSR)
+#define REG_TCU_TSCR REG32(TCU_TSCR)
+#define REG_TCU_TER REG8(TCU_TER)
+#define REG_TCU_TESR REG8(TCU_TESR)
+#define REG_TCU_TECR REG8(TCU_TECR)
+#define REG_TCU_TFR REG32(TCU_TFR)
+#define REG_TCU_TFSR REG32(TCU_TFSR)
+#define REG_TCU_TFCR REG32(TCU_TFCR)
+#define REG_TCU_TMR REG32(TCU_TMR)
+#define REG_TCU_TMSR REG32(TCU_TMSR)
+#define REG_TCU_TMCR REG32(TCU_TMCR)
+#define REG_TCU_TDFR0 REG16(TCU_TDFR0)
+#define REG_TCU_TDHR0 REG16(TCU_TDHR0)
+#define REG_TCU_TCNT0 REG16(TCU_TCNT0)
+#define REG_TCU_TCSR0 REG16(TCU_TCSR0)
+#define REG_TCU_TDFR1 REG16(TCU_TDFR1)
+#define REG_TCU_TDHR1 REG16(TCU_TDHR1)
+#define REG_TCU_TCNT1 REG16(TCU_TCNT1)
+#define REG_TCU_TCSR1 REG16(TCU_TCSR1)
+#define REG_TCU_TDFR2 REG16(TCU_TDFR2)
+#define REG_TCU_TDHR2 REG16(TCU_TDHR2)
+#define REG_TCU_TCNT2 REG16(TCU_TCNT2)
+#define REG_TCU_TCSR2 REG16(TCU_TCSR2)
+#define REG_TCU_TDFR3 REG16(TCU_TDFR3)
+#define REG_TCU_TDHR3 REG16(TCU_TDHR3)
+#define REG_TCU_TCNT3 REG16(TCU_TCNT3)
+#define REG_TCU_TCSR3 REG16(TCU_TCSR3)
+#define REG_TCU_TDFR4 REG16(TCU_TDFR4)
+#define REG_TCU_TDHR4 REG16(TCU_TDHR4)
+#define REG_TCU_TCNT4 REG16(TCU_TCNT4)
+#define REG_TCU_TCSR4 REG16(TCU_TCSR4)
+
+/* n = 0,1,2,3,4,5 */
+#define TCU_TDFR(n) (TCU_BASE + (0x40 + (n)*0x10)) /* Timer Data Full Reg */
+#define TCU_TDHR(n) (TCU_BASE + (0x44 + (n)*0x10)) /* Timer Data Half Reg */
+#define TCU_TCNT(n) (TCU_BASE + (0x48 + (n)*0x10)) /* Timer Counter Reg */
+#define TCU_TCSR(n) (TCU_BASE + (0x4C + (n)*0x10)) /* Timer Control Reg */
+
+#define REG_TCU_TDFR(n) REG16(TCU_TDFR((n)))
+#define REG_TCU_TDHR(n) REG16(TCU_TDHR((n)))
+#define REG_TCU_TCNT(n) REG16(TCU_TCNT((n)))
+#define REG_TCU_TCSR(n) REG16(TCU_TCSR((n)))
+
+/* Register definitions */
+#define TCU_TCSR_PWM_SD (1 << 9)
+#define TCU_TCSR_PWM_INITL_HIGH (1 << 8)
+#define TCU_TCSR_PWM_EN (1 << 7)
+#define TCU_TCSR_PRESCALE_BIT 3
+#define TCU_TCSR_PRESCALE_MASK (0x7 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_PRESCALE1 (0x0 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_PRESCALE4 (0x1 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_PRESCALE16 (0x2 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_PRESCALE64 (0x3 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_PRESCALE256 (0x4 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_PRESCALE1024 (0x5 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_EXT_EN (1 << 2)
+#define TCU_TCSR_RTC_EN (1 << 1)
+#define TCU_TCSR_PCK_EN (1 << 0)
+
+#define TCU_TER_TCEN5 (1 << 5)
+#define TCU_TER_TCEN4 (1 << 4)
+#define TCU_TER_TCEN3 (1 << 3)
+#define TCU_TER_TCEN2 (1 << 2)
+#define TCU_TER_TCEN1 (1 << 1)
+#define TCU_TER_TCEN0 (1 << 0)
+
+#define TCU_TESR_TCST5 (1 << 5)
+#define TCU_TESR_TCST4 (1 << 4)
+#define TCU_TESR_TCST3 (1 << 3)
+#define TCU_TESR_TCST2 (1 << 2)
+#define TCU_TESR_TCST1 (1 << 1)
+#define TCU_TESR_TCST0 (1 << 0)
+
+#define TCU_TECR_TCCL5 (1 << 5)
+#define TCU_TECR_TCCL4 (1 << 4)
+#define TCU_TECR_TCCL3 (1 << 3)
+#define TCU_TECR_TCCL2 (1 << 2)
+#define TCU_TECR_TCCL1 (1 << 1)
+#define TCU_TECR_TCCL0 (1 << 0)
+
+#define TCU_TFR_HFLAG5 (1 << 21)
+#define TCU_TFR_HFLAG4 (1 << 20)
+#define TCU_TFR_HFLAG3 (1 << 19)
+#define TCU_TFR_HFLAG2 (1 << 18)
+#define TCU_TFR_HFLAG1 (1 << 17)
+#define TCU_TFR_HFLAG0 (1 << 16)
+#define TCU_TFR_FFLAG5 (1 << 5)
+#define TCU_TFR_FFLAG4 (1 << 4)
+#define TCU_TFR_FFLAG3 (1 << 3)
+#define TCU_TFR_FFLAG2 (1 << 2)
+#define TCU_TFR_FFLAG1 (1 << 1)
+#define TCU_TFR_FFLAG0 (1 << 0)
+
+#define TCU_TFSR_HFLAG5 (1 << 21)
+#define TCU_TFSR_HFLAG4 (1 << 20)
+#define TCU_TFSR_HFLAG3 (1 << 19)
+#define TCU_TFSR_HFLAG2 (1 << 18)
+#define TCU_TFSR_HFLAG1 (1 << 17)
+#define TCU_TFSR_HFLAG0 (1 << 16)
+#define TCU_TFSR_FFLAG5 (1 << 5)
+#define TCU_TFSR_FFLAG4 (1 << 4)
+#define TCU_TFSR_FFLAG3 (1 << 3)
+#define TCU_TFSR_FFLAG2 (1 << 2)
+#define TCU_TFSR_FFLAG1 (1 << 1)
+#define TCU_TFSR_FFLAG0 (1 << 0)
+
+#define TCU_TFCR_HFLAG5 (1 << 21)
+#define TCU_TFCR_HFLAG4 (1 << 20)
+#define TCU_TFCR_HFLAG3 (1 << 19)
+#define TCU_TFCR_HFLAG2 (1 << 18)
+#define TCU_TFCR_HFLAG1 (1 << 17)
+#define TCU_TFCR_HFLAG0 (1 << 16)
+#define TCU_TFCR_FFLAG5 (1 << 5)
+#define TCU_TFCR_FFLAG4 (1 << 4)
+#define TCU_TFCR_FFLAG3 (1 << 3)
+#define TCU_TFCR_FFLAG2 (1 << 2)
+#define TCU_TFCR_FFLAG1 (1 << 1)
+#define TCU_TFCR_FFLAG0 (1 << 0)
+
+#define TCU_TMR_HMASK5 (1 << 21)
+#define TCU_TMR_HMASK4 (1 << 20)
+#define TCU_TMR_HMASK3 (1 << 19)
+#define TCU_TMR_HMASK2 (1 << 18)
+#define TCU_TMR_HMASK1 (1 << 17)
+#define TCU_TMR_HMASK0 (1 << 16)
+#define TCU_TMR_FMASK5 (1 << 5)
+#define TCU_TMR_FMASK4 (1 << 4)
+#define TCU_TMR_FMASK3 (1 << 3)
+#define TCU_TMR_FMASK2 (1 << 2)
+#define TCU_TMR_FMASK1 (1 << 1)
+#define TCU_TMR_FMASK0 (1 << 0)
+
+#define TCU_TMSR_HMST5 (1 << 21)
+#define TCU_TMSR_HMST4 (1 << 20)
+#define TCU_TMSR_HMST3 (1 << 19)
+#define TCU_TMSR_HMST2 (1 << 18)
+#define TCU_TMSR_HMST1 (1 << 17)
+#define TCU_TMSR_HMST0 (1 << 16)
+#define TCU_TMSR_FMST5 (1 << 5)
+#define TCU_TMSR_FMST4 (1 << 4)
+#define TCU_TMSR_FMST3 (1 << 3)
+#define TCU_TMSR_FMST2 (1 << 2)
+#define TCU_TMSR_FMST1 (1 << 1)
+#define TCU_TMSR_FMST0 (1 << 0)
+
+#define TCU_TMCR_HMCL5 (1 << 21)
+#define TCU_TMCR_HMCL4 (1 << 20)
+#define TCU_TMCR_HMCL3 (1 << 19)
+#define TCU_TMCR_HMCL2 (1 << 18)
+#define TCU_TMCR_HMCL1 (1 << 17)
+#define TCU_TMCR_HMCL0 (1 << 16)
+#define TCU_TMCR_FMCL5 (1 << 5)
+#define TCU_TMCR_FMCL4 (1 << 4)
+#define TCU_TMCR_FMCL3 (1 << 3)
+#define TCU_TMCR_FMCL2 (1 << 2)
+#define TCU_TMCR_FMCL1 (1 << 1)
+#define TCU_TMCR_FMCL0 (1 << 0)
+
+#define TCU_TSR_WDTS (1 << 16)
+#define TCU_TSR_STOP5 (1 << 5)
+#define TCU_TSR_STOP4 (1 << 4)
+#define TCU_TSR_STOP3 (1 << 3)
+#define TCU_TSR_STOP2 (1 << 2)
+#define TCU_TSR_STOP1 (1 << 1)
+#define TCU_TSR_STOP0 (1 << 0)
+
+#define TCU_TSSR_WDTSS (1 << 16)
+#define TCU_TSSR_STPS5 (1 << 5)
+#define TCU_TSSR_STPS4 (1 << 4)
+#define TCU_TSSR_STPS3 (1 << 3)
+#define TCU_TSSR_STPS2 (1 << 2)
+#define TCU_TSSR_STPS1 (1 << 1)
+#define TCU_TSSR_STPS0 (1 << 0)
+
+#define TCU_TSSR_WDTSC (1 << 16)
+#define TCU_TSSR_STPC5 (1 << 5)
+#define TCU_TSSR_STPC4 (1 << 4)
+#define TCU_TSSR_STPC3 (1 << 3)
+#define TCU_TSSR_STPC2 (1 << 2)
+#define TCU_TSSR_STPC1 (1 << 1)
+#define TCU_TSSR_STPC0 (1 << 0)
+
+
+/*
+ * WDT (WatchDog Timer)
+ */
+#define WDT_TDR (WDT_BASE + 0x00)
+#define WDT_TCER (WDT_BASE + 0x04)
+#define WDT_TCNT (WDT_BASE + 0x08)
+#define WDT_TCSR (WDT_BASE + 0x0C)
+
+#define REG_WDT_TDR REG16(WDT_TDR)
+#define REG_WDT_TCER REG8(WDT_TCER)
+#define REG_WDT_TCNT REG16(WDT_TCNT)
+#define REG_WDT_TCSR REG16(WDT_TCSR)
+
+/* Register definition */
+#define WDT_TCSR_PRESCALE_BIT 3
+#define WDT_TCSR_PRESCALE_MASK (0x7 << WDT_TCSR_PRESCALE_BIT)
+ #define WDT_TCSR_PRESCALE1 (0x0 << WDT_TCSR_PRESCALE_BIT)
+ #define WDT_TCSR_PRESCALE4 (0x1 << WDT_TCSR_PRESCALE_BIT)
+ #define WDT_TCSR_PRESCALE16 (0x2 << WDT_TCSR_PRESCALE_BIT)
+ #define WDT_TCSR_PRESCALE64 (0x3 << WDT_TCSR_PRESCALE_BIT)
+ #define WDT_TCSR_PRESCALE256 (0x4 << WDT_TCSR_PRESCALE_BIT)
+ #define WDT_TCSR_PRESCALE1024 (0x5 << WDT_TCSR_PRESCALE_BIT)
+#define WDT_TCSR_EXT_EN (1 << 2)
+#define WDT_TCSR_RTC_EN (1 << 1)
+#define WDT_TCSR_PCK_EN (1 << 0)
+
+#define WDT_TCER_TCEN (1 << 0)
+
+
+/*
+ * DMAC (DMA Controller)
+ */
+
+#define MAX_DMA_NUM 6 /* max 6 channels */
+
+#define DMAC_DSAR(n) (DMAC_BASE + (0x00 + (n) * 0x20)) /* DMA source address */
+#define DMAC_DTAR(n) (DMAC_BASE + (0x04 + (n) * 0x20)) /* DMA target address */
+#define DMAC_DTCR(n) (DMAC_BASE + (0x08 + (n) * 0x20)) /* DMA transfer count */
+#define DMAC_DRSR(n) (DMAC_BASE + (0x0c + (n) * 0x20)) /* DMA request source */
+#define DMAC_DCCSR(n) (DMAC_BASE + (0x10 + (n) * 0x20)) /* DMA control/status */
+#define DMAC_DCMD(n) (DMAC_BASE + (0x14 + (n) * 0x20)) /* DMA command */
+#define DMAC_DDA(n) (DMAC_BASE + (0x18 + (n) * 0x20)) /* DMA descriptor address */
+#define DMAC_DMACR (DMAC_BASE + 0x0300) /* DMA control register */
+#define DMAC_DMAIPR (DMAC_BASE + 0x0304) /* DMA interrupt pending */
+#define DMAC_DMADBR (DMAC_BASE + 0x0308) /* DMA doorbell */
+#define DMAC_DMADBSR (DMAC_BASE + 0x030C) /* DMA doorbell set */
+
+/* channel 0 */
+#define DMAC_DSAR0 DMAC_DSAR(0)
+#define DMAC_DTAR0 DMAC_DTAR(0)
+#define DMAC_DTCR0 DMAC_DTCR(0)
+#define DMAC_DRSR0 DMAC_DRSR(0)
+#define DMAC_DCCSR0 DMAC_DCCSR(0)
+#define DMAC_DCMD0 DMAC_DCMD(0)
+#define DMAC_DDA0 DMAC_DDA(0)
+
+/* channel 1 */
+#define DMAC_DSAR1 DMAC_DSAR(1)
+#define DMAC_DTAR1 DMAC_DTAR(1)
+#define DMAC_DTCR1 DMAC_DTCR(1)
+#define DMAC_DRSR1 DMAC_DRSR(1)
+#define DMAC_DCCSR1 DMAC_DCCSR(1)
+#define DMAC_DCMD1 DMAC_DCMD(1)
+#define DMAC_DDA1 DMAC_DDA(1)
+
+/* channel 2 */
+#define DMAC_DSAR2 DMAC_DSAR(2)
+#define DMAC_DTAR2 DMAC_DTAR(2)
+#define DMAC_DTCR2 DMAC_DTCR(2)
+#define DMAC_DRSR2 DMAC_DRSR(2)
+#define DMAC_DCCSR2 DMAC_DCCSR(2)
+#define DMAC_DCMD2 DMAC_DCMD(2)
+#define DMAC_DDA2 DMAC_DDA(2)
+
+/* channel 3 */
+#define DMAC_DSAR3 DMAC_DSAR(3)
+#define DMAC_DTAR3 DMAC_DTAR(3)
+#define DMAC_DTCR3 DMAC_DTCR(3)
+#define DMAC_DRSR3 DMAC_DRSR(3)
+#define DMAC_DCCSR3 DMAC_DCCSR(3)
+#define DMAC_DCMD3 DMAC_DCMD(3)
+#define DMAC_DDA3 DMAC_DDA(3)
+
+/* channel 4 */
+#define DMAC_DSAR4 DMAC_DSAR(4)
+#define DMAC_DTAR4 DMAC_DTAR(4)
+#define DMAC_DTCR4 DMAC_DTCR(4)
+#define DMAC_DRSR4 DMAC_DRSR(4)
+#define DMAC_DCCSR4 DMAC_DCCSR(4)
+#define DMAC_DCMD4 DMAC_DCMD(4)
+#define DMAC_DDA4 DMAC_DDA(4)
+
+/* channel 5 */
+#define DMAC_DSAR5 DMAC_DSAR(5)
+#define DMAC_DTAR5 DMAC_DTAR(5)
+#define DMAC_DTCR5 DMAC_DTCR(5)
+#define DMAC_DRSR5 DMAC_DRSR(5)
+#define DMAC_DCCSR5 DMAC_DCCSR(5)
+#define DMAC_DCMD5 DMAC_DCMD(5)
+#define DMAC_DDA5 DMAC_DDA(5)
+
+#define REG_DMAC_DSAR(n) REG32(DMAC_DSAR((n)))
+#define REG_DMAC_DTAR(n) REG32(DMAC_DTAR((n)))
+#define REG_DMAC_DTCR(n) REG32(DMAC_DTCR((n)))
+#define REG_DMAC_DRSR(n) REG32(DMAC_DRSR((n)))
+#define REG_DMAC_DCCSR(n) REG32(DMAC_DCCSR((n)))
+#define REG_DMAC_DCMD(n) REG32(DMAC_DCMD((n)))
+#define REG_DMAC_DDA(n) REG32(DMAC_DDA((n)))
+#define REG_DMAC_DMACR REG32(DMAC_DMACR)
+#define REG_DMAC_DMAIPR REG32(DMAC_DMAIPR)
+#define REG_DMAC_DMADBR REG32(DMAC_DMADBR)
+#define REG_DMAC_DMADBSR REG32(DMAC_DMADBSR)
+
+/* DMA request source register */
+#define DMAC_DRSR_RS_BIT 0
+#define DMAC_DRSR_RS_MASK (0x1f << DMAC_DRSR_RS_BIT)
+#define DMAC_DRSR_RS_AUTO (8 << DMAC_DRSR_RS_BIT)
+#define DMAC_DRSR_RS_UART0OUT (20 << DMAC_DRSR_RS_BIT)
+#define DMAC_DRSR_RS_UART0IN (21 << DMAC_DRSR_RS_BIT)
+#define DMAC_DRSR_RS_SSIOUT (22 << DMAC_DRSR_RS_BIT)
+#define DMAC_DRSR_RS_SSIIN (23 << DMAC_DRSR_RS_BIT)
+#define DMAC_DRSR_RS_AICOUT (24 << DMAC_DRSR_RS_BIT)
+#define DMAC_DRSR_RS_AICIN (25 << DMAC_DRSR_RS_BIT)
+#define DMAC_DRSR_RS_MSCOUT (26 << DMAC_DRSR_RS_BIT)
+#define DMAC_DRSR_RS_MSCIN (27 << DMAC_DRSR_RS_BIT)
+#define DMAC_DRSR_RS_TCU (28 << DMAC_DRSR_RS_BIT)
+#define DMAC_DRSR_RS_SADC (29 << DMAC_DRSR_RS_BIT)
+#define DMAC_DRSR_RS_SLCD (30 << DMAC_DRSR_RS_BIT)
+
+/* DMA channel control/status register */
+#define DMAC_DCCSR_NDES (1 << 31) /* descriptor (0) or not (1) ? */
+#define DMAC_DCCSR_CDOA_BIT 16 /* copy of DMA offset address */
+#define DMAC_DCCSR_CDOA_MASK (0xff << DMAC_DCCSR_CDOA_BIT)
+#define DMAC_DCCSR_INV (1 << 6) /* descriptor invalid */
+#define DMAC_DCCSR_AR (1 << 4) /* address error */
+#define DMAC_DCCSR_TT (1 << 3) /* transfer terminated */
+#define DMAC_DCCSR_HLT (1 << 2) /* DMA halted */
+#define DMAC_DCCSR_CT (1 << 1) /* count terminated */
+#define DMAC_DCCSR_EN (1 << 0) /* channel enable bit */
+
+/* DMA channel command register */
+#define DMAC_DCMD_SAI (1 << 23) /* source address increment */
+#define DMAC_DCMD_DAI (1 << 22) /* dest address increment */
+#define DMAC_DCMD_RDIL_BIT 16 /* request detection interval length */
+#define DMAC_DCMD_RDIL_MASK (0x0f << DMAC_DCMD_RDIL_BIT)
+ #define DMAC_DCMD_RDIL_IGN (0 << DMAC_DCMD_RDIL_BIT)
+ #define DMAC_DCMD_RDIL_2 (1 << DMAC_DCMD_RDIL_BIT)
+ #define DMAC_DCMD_RDIL_4 (2 << DMAC_DCMD_RDIL_BIT)
+ #define DMAC_DCMD_RDIL_8 (3 << DMAC_DCMD_RDIL_BIT)
+ #define DMAC_DCMD_RDIL_12 (4 << DMAC_DCMD_RDIL_BIT)
+ #define DMAC_DCMD_RDIL_16 (5 << DMAC_DCMD_RDIL_BIT)
+ #define DMAC_DCMD_RDIL_20 (6 << DMAC_DCMD_RDIL_BIT)
+ #define DMAC_DCMD_RDIL_24 (7 << DMAC_DCMD_RDIL_BIT)
+ #define DMAC_DCMD_RDIL_28 (8 << DMAC_DCMD_RDIL_BIT)
+ #define DMAC_DCMD_RDIL_32 (9 << DMAC_DCMD_RDIL_BIT)
+ #define DMAC_DCMD_RDIL_48 (10 << DMAC_DCMD_RDIL_BIT)
+ #define DMAC_DCMD_RDIL_60 (11 << DMAC_DCMD_RDIL_BIT)
+ #define DMAC_DCMD_RDIL_64 (12 << DMAC_DCMD_RDIL_BIT)
+ #define DMAC_DCMD_RDIL_124 (13 << DMAC_DCMD_RDIL_BIT)
+ #define DMAC_DCMD_RDIL_128 (14 << DMAC_DCMD_RDIL_BIT)
+ #define DMAC_DCMD_RDIL_200 (15 << DMAC_DCMD_RDIL_BIT)
+#define DMAC_DCMD_SWDH_BIT 14 /* source port width */
+#define DMAC_DCMD_SWDH_MASK (0x03 << DMAC_DCMD_SWDH_BIT)
+ #define DMAC_DCMD_SWDH_32 (0 << DMAC_DCMD_SWDH_BIT)
+ #define DMAC_DCMD_SWDH_8 (1 << DMAC_DCMD_SWDH_BIT)
+ #define DMAC_DCMD_SWDH_16 (2 << DMAC_DCMD_SWDH_BIT)
+#define DMAC_DCMD_DWDH_BIT 12 /* dest port width */
+#define DMAC_DCMD_DWDH_MASK (0x03 << DMAC_DCMD_DWDH_BIT)
+ #define DMAC_DCMD_DWDH_32 (0 << DMAC_DCMD_DWDH_BIT)
+ #define DMAC_DCMD_DWDH_8 (1 << DMAC_DCMD_DWDH_BIT)
+ #define DMAC_DCMD_DWDH_16 (2 << DMAC_DCMD_DWDH_BIT)
+#define DMAC_DCMD_DS_BIT 8 /* transfer data size of a data unit */
+#define DMAC_DCMD_DS_MASK (0x07 << DMAC_DCMD_DS_BIT)
+ #define DMAC_DCMD_DS_32BIT (0 << DMAC_DCMD_DS_BIT)
+ #define DMAC_DCMD_DS_8BIT (1 << DMAC_DCMD_DS_BIT)
+ #define DMAC_DCMD_DS_16BIT (2 << DMAC_DCMD_DS_BIT)
+ #define DMAC_DCMD_DS_16BYTE (3 << DMAC_DCMD_DS_BIT)
+ #define DMAC_DCMD_DS_32BYTE (4 << DMAC_DCMD_DS_BIT)
+#define DMAC_DCMD_TM (1 << 7) /* transfer mode: 0-single 1-block */
+#define DMAC_DCMD_DES_V (1 << 4) /* descriptor valid flag */
+#define DMAC_DCMD_DES_VM (1 << 3) /* descriptor valid mask: 1:support V-bit */
+#define DMAC_DCMD_DES_VIE (1 << 2) /* DMA valid error interrupt enable */
+#define DMAC_DCMD_TIE (1 << 1) /* DMA transfer interrupt enable */
+#define DMAC_DCMD_LINK (1 << 0) /* descriptor link enable */
+
+/* DMA descriptor address register */
+#define DMAC_DDA_BASE_BIT 12 /* descriptor base address */
+#define DMAC_DDA_BASE_MASK (0x0fffff << DMAC_DDA_BASE_BIT)
+#define DMAC_DDA_OFFSET_BIT 4 /* descriptor offset address */
+#define DMAC_DDA_OFFSET_MASK (0x0ff << DMAC_DDA_OFFSET_BIT)
+
+/* DMA control register */
+#define DMAC_DMACR_PR_BIT 8 /* channel priority mode */
+#define DMAC_DMACR_PR_MASK (0x03 << DMAC_DMACR_PR_BIT)
+ #define DMAC_DMACR_PR_012345 (0 << DMAC_DMACR_PR_BIT)
+ #define DMAC_DMACR_PR_023145 (1 << DMAC_DMACR_PR_BIT)
+ #define DMAC_DMACR_PR_201345 (2 << DMAC_DMACR_PR_BIT)
+ #define DMAC_DMACR_PR_RR (3 << DMAC_DMACR_PR_BIT) /* round robin */
+#define DMAC_DMACR_HLT (1 << 3) /* DMA halt flag */
+#define DMAC_DMACR_AR (1 << 2) /* address error flag */
+#define DMAC_DMACR_DMAE (1 << 0) /* DMA enable bit */
+
+/* DMA doorbell register */
+#define DMAC_DMADBR_DB5 (1 << 5) /* doorbell for channel 5 */
+#define DMAC_DMADBR_DB4 (1 << 5) /* doorbell for channel 4 */
+#define DMAC_DMADBR_DB3 (1 << 5) /* doorbell for channel 3 */
+#define DMAC_DMADBR_DB2 (1 << 5) /* doorbell for channel 2 */
+#define DMAC_DMADBR_DB1 (1 << 5) /* doorbell for channel 1 */
+#define DMAC_DMADBR_DB0 (1 << 5) /* doorbell for channel 0 */
+
+/* DMA doorbell set register */
+#define DMAC_DMADBSR_DBS5 (1 << 5) /* enable doorbell for channel 5 */
+#define DMAC_DMADBSR_DBS4 (1 << 5) /* enable doorbell for channel 4 */
+#define DMAC_DMADBSR_DBS3 (1 << 5) /* enable doorbell for channel 3 */
+#define DMAC_DMADBSR_DBS2 (1 << 5) /* enable doorbell for channel 2 */
+#define DMAC_DMADBSR_DBS1 (1 << 5) /* enable doorbell for channel 1 */
+#define DMAC_DMADBSR_DBS0 (1 << 5) /* enable doorbell for channel 0 */
+
+/* DMA interrupt pending register */
+#define DMAC_DMAIPR_CIRQ5 (1 << 5) /* irq pending status for channel 5 */
+#define DMAC_DMAIPR_CIRQ4 (1 << 4) /* irq pending status for channel 4 */
+#define DMAC_DMAIPR_CIRQ3 (1 << 3) /* irq pending status for channel 3 */
+#define DMAC_DMAIPR_CIRQ2 (1 << 2) /* irq pending status for channel 2 */
+#define DMAC_DMAIPR_CIRQ1 (1 << 1) /* irq pending status for channel 1 */
+#define DMAC_DMAIPR_CIRQ0 (1 << 0) /* irq pending status for channel 0 */
+
+
+/*************************************************************************
+ * GPIO (General-Purpose I/O Ports)
+ *************************************************************************/
+#define MAX_GPIO_NUM 128
+
+/* = 0,1,2,3 */
+#define GPIO_PXPIN(n) (GPIO_BASE + (0x00 + (n)*0x100)) /* PIN Level Register */
+#define GPIO_PXDAT(n) (GPIO_BASE + (0x10 + (n)*0x100)) /* Port Data Register */
+#define GPIO_PXDATS(n) (GPIO_BASE + (0x14 + (n)*0x100)) /* Port Data Set Register */
+#define GPIO_PXDATC(n) (GPIO_BASE + (0x18 + (n)*0x100)) /* Port Data Clear Register */
+#define GPIO_PXIM(n) (GPIO_BASE + (0x20 + (n)*0x100)) /* Interrupt Mask Register */
+#define GPIO_PXIMS(n) (GPIO_BASE + (0x24 + (n)*0x100)) /* Interrupt Mask Set Reg */
+#define GPIO_PXIMC(n) (GPIO_BASE + (0x28 + (n)*0x100)) /* Interrupt Mask Clear Reg */
+#define GPIO_PXPE(n) (GPIO_BASE + (0x30 + (n)*0x100)) /* Pull Enable Register */
+#define GPIO_PXPES(n) (GPIO_BASE + (0x34 + (n)*0x100)) /* Pull Enable Set Reg. */
+#define GPIO_PXPEC(n) (GPIO_BASE + (0x38 + (n)*0x100)) /* Pull Enable Clear Reg. */
+#define GPIO_PXFUN(n) (GPIO_BASE + (0x40 + (n)*0x100)) /* Function Register */
+#define GPIO_PXFUNS(n) (GPIO_BASE + (0x44 + (n)*0x100)) /* Function Set Register */
+#define GPIO_PXFUNC(n) (GPIO_BASE + (0x48 + (n)*0x100)) /* Function Clear Register */
+#define GPIO_PXSEL(n) (GPIO_BASE + (0x50 + (n)*0x100)) /* Select Register */
+#define GPIO_PXSELS(n) (GPIO_BASE + (0x54 + (n)*0x100)) /* Select Set Register */
+#define GPIO_PXSELC(n) (GPIO_BASE + (0x58 + (n)*0x100)) /* Select Clear Register */
+#define GPIO_PXDIR(n) (GPIO_BASE + (0x60 + (n)*0x100)) /* Direction Register */
+#define GPIO_PXDIRS(n) (GPIO_BASE + (0x64 + (n)*0x100)) /* Direction Set Register */
+#define GPIO_PXDIRC(n) (GPIO_BASE + (0x68 + (n)*0x100)) /* Direction Clear Register */
+#define GPIO_PXTRG(n) (GPIO_BASE + (0x70 + (n)*0x100)) /* Trigger Register */
+#define GPIO_PXTRGS(n) (GPIO_BASE + (0x74 + (n)*0x100)) /* Trigger Set Register */
+#define GPIO_PXTRGC(n) (GPIO_BASE + (0x78 + (n)*0x100)) /* Trigger Set Register */
+#define GPIO_PXFLG(n) (GPIO_BASE + (0x80 + (n)*0x100)) /* Port Flag Register */
+#define GPIO_PXFLGC(n) (GPIO_BASE + (0x14 + (n)*0x100)) /* Port Flag clear Register */
+
+#define REG_GPIO_PXPIN(n) REG32(GPIO_PXPIN((n))) /* PIN level */
+#define REG_GPIO_PXDAT(n) REG32(GPIO_PXDAT((n))) /* 1: interrupt pending */
+#define REG_GPIO_PXDATS(n) REG32(GPIO_PXDATS((n)))
+#define REG_GPIO_PXDATC(n) REG32(GPIO_PXDATC((n)))
+#define REG_GPIO_PXIM(n) REG32(GPIO_PXIM((n))) /* 1: mask pin interrupt */
+#define REG_GPIO_PXIMS(n) REG32(GPIO_PXIMS((n)))
+#define REG_GPIO_PXIMC(n) REG32(GPIO_PXIMC((n)))
+#define REG_GPIO_PXPE(n) REG32(GPIO_PXPE((n))) /* 1: disable pull up/down */
+#define REG_GPIO_PXPES(n) REG32(GPIO_PXPES((n)))
+#define REG_GPIO_PXPEC(n) REG32(GPIO_PXPEC((n)))
+#define REG_GPIO_PXFUN(n) REG32(GPIO_PXFUN((n))) /* 0:GPIO or intr, 1:FUNC */
+#define REG_GPIO_PXFUNS(n) REG32(GPIO_PXFUNS((n)))
+#define REG_GPIO_PXFUNC(n) REG32(GPIO_PXFUNC((n)))
+#define REG_GPIO_PXSEL(n) REG32(GPIO_PXSEL((n))) /* 0:GPIO/Fun0,1:intr/fun1*/
+#define REG_GPIO_PXSELS(n) REG32(GPIO_PXSELS((n)))
+#define REG_GPIO_PXSELC(n) REG32(GPIO_PXSELC((n)))
+#define REG_GPIO_PXDIR(n) REG32(GPIO_PXDIR((n))) /* 0:input/low-level-trig/falling-edge-trig, 1:output/high-level-trig/rising-edge-trig */
+#define REG_GPIO_PXDIRS(n) REG32(GPIO_PXDIRS((n)))
+#define REG_GPIO_PXDIRC(n) REG32(GPIO_PXDIRC((n)))
+#define REG_GPIO_PXTRG(n) REG32(GPIO_PXTRG((n))) /* 0:level-trigger, 1:edge-trigger */
+#define REG_GPIO_PXTRGS(n) REG32(GPIO_PXTRGS((n)))
+#define REG_GPIO_PXTRGC(n) REG32(GPIO_PXTRGC((n)))
+#define REG_GPIO_PXFLG(n) REG32(GPIO_PXFLG((n))) /* interrupt flag */
+#define REG_GPIO_PXFLGC(n) REG32(GPIO_PXFLGC((n))) /* interrupt flag */
+
+
+/*************************************************************************
+ * UART
+ *************************************************************************/
+
+#define IRDA_BASE UART0_BASE
+#define UART_BASE UART0_BASE
+#define UART_OFF 0x1000
+
+/* Register Offset */
+#define OFF_RDR (0x00) /* R 8b H'xx */
+#define OFF_TDR (0x00) /* W 8b H'xx */
+#define OFF_DLLR (0x00) /* RW 8b H'00 */
+#define OFF_DLHR (0x04) /* RW 8b H'00 */
+#define OFF_IER (0x04) /* RW 8b H'00 */
+#define OFF_ISR (0x08) /* R 8b H'01 */
+#define OFF_FCR (0x08) /* W 8b H'00 */
+#define OFF_LCR (0x0C) /* RW 8b H'00 */
+#define OFF_MCR (0x10) /* RW 8b H'00 */
+#define OFF_LSR (0x14) /* R 8b H'00 */
+#define OFF_MSR (0x18) /* R 8b H'00 */
+#define OFF_SPR (0x1C) /* RW 8b H'00 */
+#define OFF_SIRCR (0x20) /* RW 8b H'00, UART0 */
+#define OFF_UMR (0x24) /* RW 8b H'00, UART M Register */
+#define OFF_UACR (0x28) /* RW 8b H'00, UART Add Cycle Register */
+
+/* Register Address */
+#define UART0_RDR (UART0_BASE + OFF_RDR)
+#define UART0_TDR (UART0_BASE + OFF_TDR)
+#define UART0_DLLR (UART0_BASE + OFF_DLLR)
+#define UART0_DLHR (UART0_BASE + OFF_DLHR)
+#define UART0_IER (UART0_BASE + OFF_IER)
+#define UART0_ISR (UART0_BASE + OFF_ISR)
+#define UART0_FCR (UART0_BASE + OFF_FCR)
+#define UART0_LCR (UART0_BASE + OFF_LCR)
+#define UART0_MCR (UART0_BASE + OFF_MCR)
+#define UART0_LSR (UART0_BASE + OFF_LSR)
+#define UART0_MSR (UART0_BASE + OFF_MSR)
+#define UART0_SPR (UART0_BASE + OFF_SPR)
+#define UART0_SIRCR (UART0_BASE + OFF_SIRCR)
+#define UART0_UMR (UART0_BASE + OFF_UMR)
+#define UART0_UACR (UART0_BASE + OFF_UACR)
+
+/*
+ * Define macros for UART_IER
+ * UART Interrupt Enable Register
+ */
+#define UART_IER_RIE (1 << 0) /* 0: receive fifo "full" interrupt disable */
+#define UART_IER_TIE (1 << 1) /* 0: transmit fifo "empty" interrupt disable */
+#define UART_IER_RLIE (1 << 2) /* 0: receive line status interrupt disable */
+#define UART_IER_MIE (1 << 3) /* 0: modem status interrupt disable */
+#define UART_IER_RTIE (1 << 4) /* 0: receive timeout interrupt disable */
+
+/*
+ * Define macros for UART_ISR
+ * UART Interrupt Status Register
+ */
+#define UART_ISR_IP (1 << 0) /* 0: interrupt is pending 1: no interrupt */
+#define UART_ISR_IID (7 << 1) /* Source of Interrupt */
+#define UART_ISR_IID_MSI (0 << 1) /* Modem status interrupt */
+#define UART_ISR_IID_THRI (1 << 1) /* Transmitter holding register empty */
+#define UART_ISR_IID_RDI (2 << 1) /* Receiver data interrupt */
+#define UART_ISR_IID_RLSI (3 << 1) /* Receiver line status interrupt */
+#define UART_ISR_FFMS (3 << 6) /* FIFO mode select, set when UART_FCR.FE is set to 1 */
+#define UART_ISR_FFMS_NO_FIFO (0 << 6)
+#define UART_ISR_FFMS_FIFO_MODE (3 << 6)
+
+/*
+ * Define macros for UART_FCR
+ * UART FIFO Control Register
+ */
+#define UART_FCR_FE (1 << 0) /* 0: non-FIFO mode 1: FIFO mode */
+#define UART_FCR_RFLS (1 << 1) /* write 1 to flush receive FIFO */
+#define UART_FCR_TFLS (1 << 2) /* write 1 to flush transmit FIFO */
+#define UART_FCR_DMS (1 << 3) /* 0: disable DMA mode */
+#define UART_FCR_UUE (1 << 4) /* 0: disable UART */
+#define UART_FCR_RTRG (3 << 6) /* Receive FIFO Data Trigger */
+#define UART_FCR_RTRG_1 (0 << 6)
+#define UART_FCR_RTRG_4 (1 << 6)
+#define UART_FCR_RTRG_8 (2 << 6)
+#define UART_FCR_RTRG_15 (3 << 6)
+
+/*
+ * Define macros for UART_LCR
+ * UART Line Control Register
+ */
+#define UART_LCR_WLEN (3 << 0) /* word length */
+#define UART_LCR_WLEN_5 (0 << 0)
+#define UART_LCR_WLEN_6 (1 << 0)
+#define UART_LCR_WLEN_7 (2 << 0)
+#define UART_LCR_WLEN_8 (3 << 0)
+#define UART_LCR_STOP (1 << 2) /* 0: 1 stop bit when word length is 5,6,7,8
+ 1: 1.5 stop bits when 5; 2 stop bits when 6,7,8 */
+#define UART_LCR_STOP_1 (0 << 2) /* 0: 1 stop bit when word length is 5,6,7,8
+ 1: 1.5 stop bits when 5; 2 stop bits when 6,7,8 */
+#define UART_LCR_STOP_2 (1 << 2) /* 0: 1 stop bit when word length is 5,6,7,8
+ 1: 1.5 stop bits when 5; 2 stop bits when 6,7,8 */
+
+#define UART_LCR_PE (1 << 3) /* 0: parity disable */
+#define UART_LCR_PROE (1 << 4) /* 0: even parity 1: odd parity */
+#define UART_LCR_SPAR (1 << 5) /* 0: sticky parity disable */
+#define UART_LCR_SBRK (1 << 6) /* write 0 normal, write 1 send break */
+#define UART_LCR_DLAB (1 << 7) /* 0: access UART_RDR/TDR/IER 1: access UART_DLLR/DLHR */
+
+/*
+ * Define macros for UART_LSR
+ * UART Line Status Register
+ */
+#define UART_LSR_DR (1 << 0) /* 0: receive FIFO is empty 1: receive data is ready */
+#define UART_LSR_ORER (1 << 1) /* 0: no overrun error */
+#define UART_LSR_PER (1 << 2) /* 0: no parity error */
+#define UART_LSR_FER (1 << 3) /* 0; no framing error */
+#define UART_LSR_BRK (1 << 4) /* 0: no break detected 1: receive a break signal */
+#define UART_LSR_TDRQ (1 << 5) /* 1: transmit FIFO half "empty" */
+#define UART_LSR_TEMT (1 << 6) /* 1: transmit FIFO and shift registers empty */
+#define UART_LSR_RFER (1 << 7) /* 0: no receive error 1: receive error in FIFO mode */
+
+/*
+ * Define macros for UART_MCR
+ * UART Modem Control Register
+ */
+#define UART_MCR_DTR (1 << 0) /* 0: DTR_ ouput high */
+#define UART_MCR_RTS (1 << 1) /* 0: RTS_ output high */
+#define UART_MCR_OUT1 (1 << 2) /* 0: UART_MSR.RI is set to 0 and RI_ input high */
+#define UART_MCR_OUT2 (1 << 3) /* 0: UART_MSR.DCD is set to 0 and DCD_ input high */
+#define UART_MCR_LOOP (1 << 4) /* 0: normal 1: loopback mode */
+#define UART_MCR_MCE (1 << 7) /* 0: modem function is disable */
+
+/*
+ * Define macros for UART_MSR
+ * UART Modem Status Register
+ */
+#define UART_MSR_DCTS (1 << 0) /* 0: no change on CTS_ pin since last read of UART_MSR */
+#define UART_MSR_DDSR (1 << 1) /* 0: no change on DSR_ pin since last read of UART_MSR */
+#define UART_MSR_DRI (1 << 2) /* 0: no change on RI_ pin since last read of UART_MSR */
+#define UART_MSR_DDCD (1 << 3) /* 0: no change on DCD_ pin since last read of UART_MSR */
+#define UART_MSR_CTS (1 << 4) /* 0: CTS_ pin is high */
+#define UART_MSR_DSR (1 << 5) /* 0: DSR_ pin is high */
+#define UART_MSR_RI (1 << 6) /* 0: RI_ pin is high */
+#define UART_MSR_DCD (1 << 7) /* 0: DCD_ pin is high */
+
+/*
+ * Define macros for SIRCR
+ * Slow IrDA Control Register
+ */
+#define SIRCR_TSIRE (1 << 0) /* 0: transmitter is in UART mode 1: IrDA mode */
+#define SIRCR_RSIRE (1 << 1) /* 0: receiver is in UART mode 1: IrDA mode */
+#define SIRCR_TPWS (1 << 2) /* 0: transmit 0 pulse width is 3/16 of bit length
+ 1: 0 pulse width is 1.6us for 115.2Kbps */
+#define SIRCR_TXPL (1 << 3) /* 0: encoder generates a positive pulse for 0 */
+#define SIRCR_RXPL (1 << 4) /* 0: decoder interprets positive pulse as 0 */
+
+
+/*************************************************************************
+ * AIC (AC97/I2S Controller)
+ *************************************************************************/
+#define AIC_FR (AIC_BASE + 0x000)
+#define AIC_CR (AIC_BASE + 0x004)
+#define AIC_ACCR1 (AIC_BASE + 0x008)
+#define AIC_ACCR2 (AIC_BASE + 0x00C)
+#define AIC_I2SCR (AIC_BASE + 0x010)
+#define AIC_SR (AIC_BASE + 0x014)
+#define AIC_ACSR (AIC_BASE + 0x018)
+#define AIC_I2SSR (AIC_BASE + 0x01C)
+#define AIC_ACCAR (AIC_BASE + 0x020)
+#define AIC_ACCDR (AIC_BASE + 0x024)
+#define AIC_ACSAR (AIC_BASE + 0x028)
+#define AIC_ACSDR (AIC_BASE + 0x02C)
+#define AIC_I2SDIV (AIC_BASE + 0x030)
+#define AIC_DR (AIC_BASE + 0x034)
+
+#define REG_AIC_FR REG32(AIC_FR)
+#define REG_AIC_CR REG32(AIC_CR)
+#define REG_AIC_ACCR1 REG32(AIC_ACCR1)
+#define REG_AIC_ACCR2 REG32(AIC_ACCR2)
+#define REG_AIC_I2SCR REG32(AIC_I2SCR)
+#define REG_AIC_SR REG32(AIC_SR)
+#define REG_AIC_ACSR REG32(AIC_ACSR)
+#define REG_AIC_I2SSR REG32(AIC_I2SSR)
+#define REG_AIC_ACCAR REG32(AIC_ACCAR)
+#define REG_AIC_ACCDR REG32(AIC_ACCDR)
+#define REG_AIC_ACSAR REG32(AIC_ACSAR)
+#define REG_AIC_ACSDR REG32(AIC_ACSDR)
+#define REG_AIC_I2SDIV REG32(AIC_I2SDIV)
+#define REG_AIC_DR REG32(AIC_DR)
+
+/* AIC Controller Configuration Register (AIC_FR) */
+
+#define AIC_FR_RFTH_BIT 12 /* Receive FIFO Threshold */
+#define AIC_FR_RFTH_MASK (0xf << AIC_FR_RFTH_BIT)
+#define AIC_FR_TFTH_BIT 8 /* Transmit FIFO Threshold */
+#define AIC_FR_TFTH_MASK (0xf << AIC_FR_TFTH_BIT)
+#define AIC_FR_ICDC (1 << 5) /* External(0) or Internal CODEC(1) */
+#define AIC_FR_AUSEL (1 << 4) /* AC97(0) or I2S/MSB-justified(1) */
+#define AIC_FR_RST (1 << 3) /* AIC registers reset */
+#define AIC_FR_BCKD (1 << 2) /* I2S BIT_CLK direction, 0:input,1:output */
+#define AIC_FR_SYNCD (1 << 1) /* I2S SYNC direction, 0:input,1:output */
+#define AIC_FR_ENB (1 << 0) /* AIC enable bit */
+
+/* AIC Controller Common Control Register (AIC_CR) */
+
+#define AIC_CR_OSS_BIT 19 /* Output Sample Size from memory (AIC V2 only) */
+#define AIC_CR_OSS_MASK (0x7 << AIC_CR_OSS_BIT)
+ #define AIC_CR_OSS_8BIT (0x0 << AIC_CR_OSS_BIT)
+ #define AIC_CR_OSS_16BIT (0x1 << AIC_CR_OSS_BIT)
+ #define AIC_CR_OSS_18BIT (0x2 << AIC_CR_OSS_BIT)
+ #define AIC_CR_OSS_20BIT (0x3 << AIC_CR_OSS_BIT)
+ #define AIC_CR_OSS_24BIT (0x4 << AIC_CR_OSS_BIT)
+#define AIC_CR_ISS_BIT 16 /* Input Sample Size from memory (AIC V2 only) */
+#define AIC_CR_ISS_MASK (0x7 << AIC_CR_ISS_BIT)
+ #define AIC_CR_ISS_8BIT (0x0 << AIC_CR_ISS_BIT)
+ #define AIC_CR_ISS_16BIT (0x1 << AIC_CR_ISS_BIT)
+ #define AIC_CR_ISS_18BIT (0x2 << AIC_CR_ISS_BIT)
+ #define AIC_CR_ISS_20BIT (0x3 << AIC_CR_ISS_BIT)
+ #define AIC_CR_ISS_24BIT (0x4 << AIC_CR_ISS_BIT)
+#define AIC_CR_RDMS (1 << 15) /* Receive DMA enable */
+#define AIC_CR_TDMS (1 << 14) /* Transmit DMA enable */
+#define AIC_CR_M2S (1 << 11) /* Mono to Stereo enable */
+#define AIC_CR_ENDSW (1 << 10) /* Endian switch enable */
+#define AIC_CR_AVSTSU (1 << 9) /* Signed <-> Unsigned toggle enable */
+#define AIC_CR_FLUSH (1 << 8) /* Flush FIFO */
+#define AIC_CR_EROR (1 << 6) /* Enable ROR interrupt */
+#define AIC_CR_ETUR (1 << 5) /* Enable TUR interrupt */
+#define AIC_CR_ERFS (1 << 4) /* Enable RFS interrupt */
+#define AIC_CR_ETFS (1 << 3) /* Enable TFS interrupt */
+#define AIC_CR_ENLBF (1 << 2) /* Enable Loopback Function */
+#define AIC_CR_ERPL (1 << 1) /* Enable Playback Function */
+#define AIC_CR_EREC (1 << 0) /* Enable Record Function */
+
+/* AIC Controller AC-link Control Register 1 (AIC_ACCR1) */
+
+#define AIC_ACCR1_RS_BIT 16 /* Receive Valid Slots */
+#define AIC_ACCR1_RS_MASK (0x3ff << AIC_ACCR1_RS_BIT)
+ #define AIC_ACCR1_RS_SLOT12 (1 << 25) /* Slot 12 valid bit */
+ #define AIC_ACCR1_RS_SLOT11 (1 << 24) /* Slot 11 valid bit */
+ #define AIC_ACCR1_RS_SLOT10 (1 << 23) /* Slot 10 valid bit */
+ #define AIC_ACCR1_RS_SLOT9 (1 << 22) /* Slot 9 valid bit, LFE */
+ #define AIC_ACCR1_RS_SLOT8 (1 << 21) /* Slot 8 valid bit, Surround Right */
+ #define AIC_ACCR1_RS_SLOT7 (1 << 20) /* Slot 7 valid bit, Surround Left */
+ #define AIC_ACCR1_RS_SLOT6 (1 << 19) /* Slot 6 valid bit, PCM Center */
+ #define AIC_ACCR1_RS_SLOT5 (1 << 18) /* Slot 5 valid bit */
+ #define AIC_ACCR1_RS_SLOT4 (1 << 17) /* Slot 4 valid bit, PCM Right */
+ #define AIC_ACCR1_RS_SLOT3 (1 << 16) /* Slot 3 valid bit, PCM Left */
+#define AIC_ACCR1_XS_BIT 0 /* Transmit Valid Slots */
+#define AIC_ACCR1_XS_MASK (0x3ff << AIC_ACCR1_XS_BIT)
+ #define AIC_ACCR1_XS_SLOT12 (1 << 9) /* Slot 12 valid bit */
+ #define AIC_ACCR1_XS_SLOT11 (1 << 8) /* Slot 11 valid bit */
+ #define AIC_ACCR1_XS_SLOT10 (1 << 7) /* Slot 10 valid bit */
+ #define AIC_ACCR1_XS_SLOT9 (1 << 6) /* Slot 9 valid bit, LFE */
+ #define AIC_ACCR1_XS_SLOT8 (1 << 5) /* Slot 8 valid bit, Surround Right */
+ #define AIC_ACCR1_XS_SLOT7 (1 << 4) /* Slot 7 valid bit, Surround Left */
+ #define AIC_ACCR1_XS_SLOT6 (1 << 3) /* Slot 6 valid bit, PCM Center */
+ #define AIC_ACCR1_XS_SLOT5 (1 << 2) /* Slot 5 valid bit */
+ #define AIC_ACCR1_XS_SLOT4 (1 << 1) /* Slot 4 valid bit, PCM Right */
+ #define AIC_ACCR1_XS_SLOT3 (1 << 0) /* Slot 3 valid bit, PCM Left */
+
+/* AIC Controller AC-link Control Register 2 (AIC_ACCR2) */
+
+#define AIC_ACCR2_ERSTO (1 << 18) /* Enable RSTO interrupt */
+#define AIC_ACCR2_ESADR (1 << 17) /* Enable SADR interrupt */
+#define AIC_ACCR2_ECADT (1 << 16) /* Enable CADT interrupt */
+#define AIC_ACCR2_OASS_BIT 8 /* Output Sample Size for AC-link */
+#define AIC_ACCR2_OASS_MASK (0x3 << AIC_ACCR2_OASS_BIT)
+ #define AIC_ACCR2_OASS_20BIT (0 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 20-bit */
+ #define AIC_ACCR2_OASS_18BIT (1 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 18-bit */
+ #define AIC_ACCR2_OASS_16BIT (2 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 16-bit */
+ #define AIC_ACCR2_OASS_8BIT (3 << AIC_ACCR2_OASS_BIT) /* Output Audio Sample Size is 8-bit */
+#define AIC_ACCR2_IASS_BIT 6 /* Output Sample Size for AC-link */
+#define AIC_ACCR2_IASS_MASK (0x3 << AIC_ACCR2_IASS_BIT)
+ #define AIC_ACCR2_IASS_20BIT (0 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 20-bit */
+ #define AIC_ACCR2_IASS_18BIT (1 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 18-bit */
+ #define AIC_ACCR2_IASS_16BIT (2 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 16-bit */
+ #define AIC_ACCR2_IASS_8BIT (3 << AIC_ACCR2_IASS_BIT) /* Input Audio Sample Size is 8-bit */
+#define AIC_ACCR2_SO (1 << 3) /* SDATA_OUT output value */
+#define AIC_ACCR2_SR (1 << 2) /* RESET# pin level */
+#define AIC_ACCR2_SS (1 << 1) /* SYNC pin level */
+#define AIC_ACCR2_SA (1 << 0) /* SYNC and SDATA_OUT alternation */
+
+/* AIC Controller I2S/MSB-justified Control Register (AIC_I2SCR) */
+
+#define AIC_I2SCR_STPBK (1 << 12) /* Stop BIT_CLK for I2S/MSB-justified */
+#define AIC_I2SCR_WL_BIT 1 /* Input/Output Sample Size for I2S/MSB-justified */
+#define AIC_I2SCR_WL_MASK (0x7 << AIC_I2SCR_WL_BIT)
+ #define AIC_I2SCR_WL_24BIT (0 << AIC_I2SCR_WL_BIT) /* Word Length is 24 bit */
+ #define AIC_I2SCR_WL_20BIT (1 << AIC_I2SCR_WL_BIT) /* Word Length is 20 bit */
+ #define AIC_I2SCR_WL_18BIT (2 << AIC_I2SCR_WL_BIT) /* Word Length is 18 bit */
+ #define AIC_I2SCR_WL_16BIT (3 << AIC_I2SCR_WL_BIT) /* Word Length is 16 bit */
+ #define AIC_I2SCR_WL_8BIT (4 << AIC_I2SCR_WL_BIT) /* Word Length is 8 bit */
+#define AIC_I2SCR_AMSL (1 << 0) /* 0:I2S, 1:MSB-justified */
+
+/* AIC Controller FIFO Status Register (AIC_SR) */
+
+#define AIC_SR_RFL_BIT 24 /* Receive FIFO Level */
+#define AIC_SR_RFL_MASK (0x3f << AIC_SR_RFL_BIT)
+#define AIC_SR_TFL_BIT 8 /* Transmit FIFO level */
+#define AIC_SR_TFL_MASK (0x3f << AIC_SR_TFL_BIT)
+#define AIC_SR_ROR (1 << 6) /* Receive FIFO Overrun */
+#define AIC_SR_TUR (1 << 5) /* Transmit FIFO Underrun */
+#define AIC_SR_RFS (1 << 4) /* Receive FIFO Service Request */
+#define AIC_SR_TFS (1 << 3) /* Transmit FIFO Service Request */
+
+/* AIC Controller AC-link Status Register (AIC_ACSR) */
+
+#define AIC_ACSR_SLTERR (1 << 21) /* Slot Error Flag */
+#define AIC_ACSR_CRDY (1 << 20) /* External CODEC Ready Flag */
+#define AIC_ACSR_CLPM (1 << 19) /* External CODEC low power mode flag */
+#define AIC_ACSR_RSTO (1 << 18) /* External CODEC regs read status timeout */
+#define AIC_ACSR_SADR (1 << 17) /* External CODEC regs status addr and data received */
+#define AIC_ACSR_CADT (1 << 16) /* Command Address and Data Transmitted */
+
+/* AIC Controller I2S/MSB-justified Status Register (AIC_I2SSR) */
+
+#define AIC_I2SSR_BSY (1 << 2) /* AIC Busy in I2S/MSB-justified format */
+
+/* AIC Controller AC97 codec Command Address Register (AIC_ACCAR) */
+
+#define AIC_ACCAR_CAR_BIT 0
+#define AIC_ACCAR_CAR_MASK (0xfffff << AIC_ACCAR_CAR_BIT)
+
+/* AIC Controller AC97 codec Command Data Register (AIC_ACCDR) */
+
+#define AIC_ACCDR_CDR_BIT 0
+#define AIC_ACCDR_CDR_MASK (0xfffff << AIC_ACCDR_CDR_BIT)
+
+/* AIC Controller AC97 codec Status Address Register (AIC_ACSAR) */
+
+#define AIC_ACSAR_SAR_BIT 0
+#define AIC_ACSAR_SAR_MASK (0xfffff << AIC_ACSAR_SAR_BIT)
+
+/* AIC Controller AC97 codec Status Data Register (AIC_ACSDR) */
+
+#define AIC_ACSDR_SDR_BIT 0
+#define AIC_ACSDR_SDR_MASK (0xfffff << AIC_ACSDR_SDR_BIT)
+
+/* AIC Controller I2S/MSB-justified Clock Divider Register (AIC_I2SDIV) */
+
+#define AIC_I2SDIV_DIV_BIT 0
+#define AIC_I2SDIV_DIV_MASK (0x7f << AIC_I2SDIV_DIV_BIT)
+ #define AIC_I2SDIV_BITCLK_3072KHZ (0x0C << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 3.072MHz */
+ #define AIC_I2SDIV_BITCLK_2836KHZ (0x0D << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 2.836MHz */
+ #define AIC_I2SDIV_BITCLK_1418KHZ (0x1A << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.418MHz */
+ #define AIC_I2SDIV_BITCLK_1024KHZ (0x24 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 1.024MHz */
+ #define AIC_I2SDIV_BITCLK_7089KHZ (0x34 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 708.92KHz */
+ #define AIC_I2SDIV_BITCLK_512KHZ (0x48 << AIC_I2SDIV_DIV_BIT) /* BIT_CLK of 512.00KHz */
+
+
+/*************************************************************************
+ * ICDC (Internal CODEC)
+ *************************************************************************/
+#define ICDC_CR (ICDC_BASE + 0x0400) /* ICDC Control Register */
+#define ICDC_APWAIT (ICDC_BASE + 0x0404) /* Anti-Pop WAIT Stage Timing Control Register */
+#define ICDC_APPRE (ICDC_BASE + 0x0408) /* Anti-Pop HPEN-PRE Stage Timing Control Register */
+#define ICDC_APHPEN (ICDC_BASE + 0x040C) /* Anti-Pop HPEN Stage Timing Control Register */
+#define ICDC_APSR (ICDC_BASE + 0x0410) /* Anti-Pop Status Register */
+#define ICDC_CDCCR1 (ICDC_BASE + 0x0080)
+#define ICDC_CDCCR2 (ICDC_BASE + 0x0084)
+
+#define REG_ICDC_CR REG32(ICDC_CR)
+#define REG_ICDC_APWAIT REG32(ICDC_APWAIT)
+#define REG_ICDC_APPRE REG32(ICDC_APPRE)
+#define REG_ICDC_APHPEN REG32(ICDC_APHPEN)
+#define REG_ICDC_APSR REG32(ICDC_APSR)
+#define REG_ICDC_CDCCR1 REG32(ICDC_CDCCR1)
+#define REG_ICDC_CDCCR2 REG32(ICDC_CDCCR2)
+
+/* ICDC Control Register */
+#define ICDC_CR_LINVOL_BIT 24 /* LINE Input Volume Gain: GAIN=LINVOL*1.5-34.5 */
+#define ICDC_CR_LINVOL_MASK (0x1f << ICDC_CR_LINVOL_BIT)
+#define ICDC_CR_ASRATE_BIT 20 /* Audio Sample Rate */
+#define ICDC_CR_ASRATE_MASK (0x0f << ICDC_CR_ASRATE_BIT)
+ #define ICDC_CR_ASRATE_8000 (0x0 << ICDC_CR_ASRATE_BIT)
+ #define ICDC_CR_ASRATE_11025 (0x1 << ICDC_CR_ASRATE_BIT)
+ #define ICDC_CR_ASRATE_12000 (0x2 << ICDC_CR_ASRATE_BIT)
+ #define ICDC_CR_ASRATE_16000 (0x3 << ICDC_CR_ASRATE_BIT)
+ #define ICDC_CR_ASRATE_22050 (0x4 << ICDC_CR_ASRATE_BIT)
+ #define ICDC_CR_ASRATE_24000 (0x5 << ICDC_CR_ASRATE_BIT)
+ #define ICDC_CR_ASRATE_32000 (0x6 << ICDC_CR_ASRATE_BIT)
+ #define ICDC_CR_ASRATE_44100 (0x7 << ICDC_CR_ASRATE_BIT)
+ #define ICDC_CR_ASRATE_48000 (0x8 << ICDC_CR_ASRATE_BIT)
+#define ICDC_CR_MICBG_BIT 18 /* MIC Boost Gain */
+#define ICDC_CR_MICBG_MASK (0x3 << ICDC_CR_MICBG_BIT)
+ #define ICDC_CR_MICBG_0DB (0x0 << ICDC_CR_MICBG_BIT)
+ #define ICDC_CR_MICBG_6DB (0x1 << ICDC_CR_MICBG_BIT)
+ #define ICDC_CR_MICBG_12DB (0x2 << ICDC_CR_MICBG_BIT)
+ #define ICDC_CR_MICBG_20DB (0x3 << ICDC_CR_MICBG_BIT)
+#define ICDC_CR_HPVOL_BIT 16 /* Headphone Volume Gain */
+#define ICDC_CR_HPVOL_MASK (0x3 << ICDC_CR_HPVOL_BIT)
+ #define ICDC_CR_HPVOL_0DB (0x0 << ICDC_CR_HPVOL_BIT)
+ #define ICDC_CR_HPVOL_2DB (0x1 << ICDC_CR_HPVOL_BIT)
+ #define ICDC_CR_HPVOL_4DB (0x2 << ICDC_CR_HPVOL_BIT)
+ #define ICDC_CR_HPVOL_6DB (0x3 << ICDC_CR_HPVOL_BIT)
+#define ICDC_CR_ELINEIN (1 << 13) /* Enable LINE Input */
+#define ICDC_CR_EMIC (1 << 12) /* Enable MIC Input */
+#define ICDC_CR_SW1ON (1 << 11) /* Switch 1 in CODEC is on */
+#define ICDC_CR_EADC (1 << 10) /* Enable ADC */
+#define ICDC_CR_SW2ON (1 << 9) /* Switch 2 in CODEC is on */
+#define ICDC_CR_EDAC (1 << 8) /* Enable DAC */
+#define ICDC_CR_HPMUTE (1 << 5) /* Headphone Mute */
+#define ICDC_CR_HPTON (1 << 4) /* Headphone Amplifier Trun On */
+#define ICDC_CR_HPTOFF (1 << 3) /* Headphone Amplifier Trun Off */
+#define ICDC_CR_TAAP (1 << 2) /* Turn Around of the Anti-Pop Procedure */
+#define ICDC_CR_EAP (1 << 1) /* Enable Anti-Pop Procedure */
+#define ICDC_CR_SUSPD (1 << 0) /* CODEC Suspend */
+
+/* Anti-Pop WAIT Stage Timing Control Register */
+#define ICDC_APWAIT_WAITSN_BIT 0
+#define ICDC_APWAIT_WAITSN_MASK (0x7ff << ICDC_APWAIT_WAITSN_BIT)
+
+/* Anti-Pop HPEN-PRE Stage Timing Control Register */
+#define ICDC_APPRE_PRESN_BIT 0
+#define ICDC_APPRE_PRESN_MASK (0x1ff << ICDC_APPRE_PRESN_BIT)
+
+/* Anti-Pop HPEN Stage Timing Control Register */
+#define ICDC_APHPEN_HPENSN_BIT 0
+#define ICDC_APHPEN_HPENSN_MASK (0x3fff << ICDC_APHPEN_HPENSN_BIT)
+
+/* Anti-Pop Status Register */
+#define ICDC_SR_HPST_BIT 14 /* Headphone Amplifier State */
+#define ICDC_SR_HPST_MASK (0x7 << ICDC_SR_HPST_BIT)
+#define ICDC_SR_HPST_HP_OFF (0x0 << ICDC_SR_HPST_BIT) /* HP amplifier is off */
+#define ICDC_SR_HPST_TON_WAIT (0x1 << ICDC_SR_HPST_BIT) /* wait state in turn-on */
+ #define ICDC_SR_HPST_TON_PRE (0x2 << ICDC_SR_HPST_BIT) /* pre-enable state in turn-on */
+#define ICDC_SR_HPST_TON_HPEN (0x3 << ICDC_SR_HPST_BIT) /* HP enable state in turn-on */
+ #define ICDC_SR_HPST_TOFF_HPEN (0x4 << ICDC_SR_HPST_BIT) /* HP enable state in turn-off */
+ #define ICDC_SR_HPST_TOFF_PRE (0x5 << ICDC_SR_HPST_BIT) /* pre-enable state in turn-off */
+ #define ICDC_SR_HPST_TOFF_WAIT (0x6 << ICDC_SR_HPST_BIT) /* wait state in turn-off */
+ #define ICDC_SR_HPST_HP_ON (0x7 << ICDC_SR_HPST_BIT) /* HP amplifier is on */
+#define ICDC_SR_SNCNT_BIT 0 /* Sample Number Counter */
+#define ICDC_SR_SNCNT_MASK (0x3fff << ICDC_SR_SNCNT_BIT)
+
+
+/*************************************************************************
+ * I2C
+ *************************************************************************/
+#define I2C_DR (I2C_BASE + 0x000)
+#define I2C_CR (I2C_BASE + 0x004)
+#define I2C_SR (I2C_BASE + 0x008)
+#define I2C_GR (I2C_BASE + 0x00C)
+
+#define REG_I2C_DR REG8(I2C_DR)
+#define REG_I2C_CR REG8(I2C_CR)
+#define REG_I2C_SR REG8(I2C_SR)
+#define REG_I2C_GR REG16(I2C_GR)
+
+/* I2C Control Register (I2C_CR) */
+
+#define I2C_CR_IEN (1 << 4)
+#define I2C_CR_STA (1 << 3)
+#define I2C_CR_STO (1 << 2)
+#define I2C_CR_AC (1 << 1)
+#define I2C_CR_I2CE (1 << 0)
+
+/* I2C Status Register (I2C_SR) */
+
+#define I2C_SR_STX (1 << 4)
+#define I2C_SR_BUSY (1 << 3)
+#define I2C_SR_TEND (1 << 2)
+#define I2C_SR_DRF (1 << 1)
+#define I2C_SR_ACKF (1 << 0)
+
+
+/*************************************************************************
+ * SSI
+ *************************************************************************/
+#define SSI_DR (SSI_BASE + 0x000)
+#define SSI_CR0 (SSI_BASE + 0x004)
+#define SSI_CR1 (SSI_BASE + 0x008)
+#define SSI_SR (SSI_BASE + 0x00C)
+#define SSI_ITR (SSI_BASE + 0x010)
+#define SSI_ICR (SSI_BASE + 0x014)
+#define SSI_GR (SSI_BASE + 0x018)
+
+#define REG_SSI_DR REG32(SSI_DR)
+#define REG_SSI_CR0 REG16(SSI_CR0)
+#define REG_SSI_CR1 REG32(SSI_CR1)
+#define REG_SSI_SR REG32(SSI_SR)
+#define REG_SSI_ITR REG16(SSI_ITR)
+#define REG_SSI_ICR REG8(SSI_ICR)
+#define REG_SSI_GR REG16(SSI_GR)
+
+/* SSI Data Register (SSI_DR) */
+
+#define SSI_DR_GPC_BIT 0
+#define SSI_DR_GPC_MASK (0x1ff << SSI_DR_GPC_BIT)
+
+/* SSI Control Register 0 (SSI_CR0) */
+
+#define SSI_CR0_SSIE (1 << 15)
+#define SSI_CR0_TIE (1 << 14)
+#define SSI_CR0_RIE (1 << 13)
+#define SSI_CR0_TEIE (1 << 12)
+#define SSI_CR0_REIE (1 << 11)
+#define SSI_CR0_LOOP (1 << 10)
+#define SSI_CR0_RFINE (1 << 9)
+#define SSI_CR0_RFINC (1 << 8)
+#define SSI_CR0_FSEL (1 << 6)
+#define SSI_CR0_TFLUSH (1 << 2)
+#define SSI_CR0_RFLUSH (1 << 1)
+#define SSI_CR0_DISREV (1 << 0)
+
+/* SSI Control Register 1 (SSI_CR1) */
+
+#define SSI_CR1_FRMHL_BIT 30
+#define SSI_CR1_FRMHL_MASK (0x3 << SSI_CR1_FRMHL_BIT)
+ #define SSI_CR1_FRMHL_CELOW_CE2LOW (0 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is low valid */
+ #define SSI_CR1_FRMHL_CEHIGH_CE2LOW (1 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is low valid */
+ #define SSI_CR1_FRMHL_CELOW_CE2HIGH (2 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is low valid and SSI_CE2_ is high valid */
+ #define SSI_CR1_FRMHL_CEHIGH_CE2HIGH (3 << SSI_CR1_FRMHL_BIT) /* SSI_CE_ is high valid and SSI_CE2_ is high valid */
+#define SSI_CR1_TFVCK_BIT 28
+#define SSI_CR1_TFVCK_MASK (0x3 << SSI_CR1_TFVCK_BIT)
+ #define SSI_CR1_TFVCK_0 (0 << SSI_CR1_TFVCK_BIT)
+ #define SSI_CR1_TFVCK_1 (1 << SSI_CR1_TFVCK_BIT)
+ #define SSI_CR1_TFVCK_2 (2 << SSI_CR1_TFVCK_BIT)
+ #define SSI_CR1_TFVCK_3 (3 << SSI_CR1_TFVCK_BIT)
+#define SSI_CR1_TCKFI_BIT 26
+#define SSI_CR1_TCKFI_MASK (0x3 << SSI_CR1_TCKFI_BIT)
+ #define SSI_CR1_TCKFI_0 (0 << SSI_CR1_TCKFI_BIT)
+ #define SSI_CR1_TCKFI_1 (1 << SSI_CR1_TCKFI_BIT)
+ #define SSI_CR1_TCKFI_2 (2 << SSI_CR1_TCKFI_BIT)
+ #define SSI_CR1_TCKFI_3 (3 << SSI_CR1_TCKFI_BIT)
+#define SSI_CR1_LFST (1 << 25)
+#define SSI_CR1_ITFRM (1 << 24)
+#define SSI_CR1_UNFIN (1 << 23)
+#define SSI_CR1_MULTS (1 << 22)
+#define SSI_CR1_FMAT_BIT 20
+#define SSI_CR1_FMAT_MASK (0x3 << SSI_CR1_FMAT_BIT)
+ #define SSI_CR1_FMAT_SPI (0 << SSI_CR1_FMAT_BIT) /* Motorola¡¯s SPI format */
+ #define SSI_CR1_FMAT_SSP (1 << SSI_CR1_FMAT_BIT) /* TI's SSP format */
+ #define SSI_CR1_FMAT_MW1 (2 << SSI_CR1_FMAT_BIT) /* National Microwire 1 format */
+ #define SSI_CR1_FMAT_MW2 (3 << SSI_CR1_FMAT_BIT) /* National Microwire 2 format */
+#define SSI_CR1_TTRG_BIT 16
+#define SSI_CR1_TTRG_MASK (0xf << SSI_CR1_TTRG_BIT)
+ #define SSI_CR1_TTRG_1 (0 << SSI_CR1_TTRG_BIT)
+ #define SSI_CR1_TTRG_8 (1 << SSI_CR1_TTRG_BIT)
+ #define SSI_CR1_TTRG_16 (2 << SSI_CR1_TTRG_BIT)
+ #define SSI_CR1_TTRG_24 (3 << SSI_CR1_TTRG_BIT)
+ #define SSI_CR1_TTRG_32 (4 << SSI_CR1_TTRG_BIT)
+ #define SSI_CR1_TTRG_40 (5 << SSI_CR1_TTRG_BIT)
+ #define SSI_CR1_TTRG_48 (6 << SSI_CR1_TTRG_BIT)
+ #define SSI_CR1_TTRG_56 (7 << SSI_CR1_TTRG_BIT)
+ #define SSI_CR1_TTRG_64 (8 << SSI_CR1_TTRG_BIT)
+ #define SSI_CR1_TTRG_72 (9 << SSI_CR1_TTRG_BIT)
+ #define SSI_CR1_TTRG_80 (10<< SSI_CR1_TTRG_BIT)
+ #define SSI_CR1_TTRG_88 (11<< SSI_CR1_TTRG_BIT)
+ #define SSI_CR1_TTRG_96 (12<< SSI_CR1_TTRG_BIT)
+ #define SSI_CR1_TTRG_104 (13<< SSI_CR1_TTRG_BIT)
+ #define SSI_CR1_TTRG_112 (14<< SSI_CR1_TTRG_BIT)
+ #define SSI_CR1_TTRG_120 (15<< SSI_CR1_TTRG_BIT)
+#define SSI_CR1_MCOM_BIT 12
+#define SSI_CR1_MCOM_MASK (0xf << SSI_CR1_MCOM_BIT)
+ #define SSI_CR1_MCOM_1BIT (0x0 << SSI_CR1_MCOM_BIT) /* 1-bit command selected */
+ #define SSI_CR1_MCOM_2BIT (0x1 << SSI_CR1_MCOM_BIT) /* 2-bit command selected */
+ #define SSI_CR1_MCOM_3BIT (0x2 << SSI_CR1_MCOM_BIT) /* 3-bit command selected */
+ #define SSI_CR1_MCOM_4BIT (0x3 << SSI_CR1_MCOM_BIT) /* 4-bit command selected */
+ #define SSI_CR1_MCOM_5BIT (0x4 << SSI_CR1_MCOM_BIT) /* 5-bit command selected */
+ #define SSI_CR1_MCOM_6BIT (0x5 << SSI_CR1_MCOM_BIT) /* 6-bit command selected */
+ #define SSI_CR1_MCOM_7BIT (0x6 << SSI_CR1_MCOM_BIT) /* 7-bit command selected */
+ #define SSI_CR1_MCOM_8BIT (0x7 << SSI_CR1_MCOM_BIT) /* 8-bit command selected */
+ #define SSI_CR1_MCOM_9BIT (0x8 << SSI_CR1_MCOM_BIT) /* 9-bit command selected */
+ #define SSI_CR1_MCOM_10BIT (0x9 << SSI_CR1_MCOM_BIT) /* 10-bit command selected */
+ #define SSI_CR1_MCOM_11BIT (0xA << SSI_CR1_MCOM_BIT) /* 11-bit command selected */
+ #define SSI_CR1_MCOM_12BIT (0xB << SSI_CR1_MCOM_BIT) /* 12-bit command selected */
+ #define SSI_CR1_MCOM_13BIT (0xC << SSI_CR1_MCOM_BIT) /* 13-bit command selected */
+ #define SSI_CR1_MCOM_14BIT (0xD << SSI_CR1_MCOM_BIT) /* 14-bit command selected */
+ #define SSI_CR1_MCOM_15BIT (0xE << SSI_CR1_MCOM_BIT) /* 15-bit command selected */
+ #define SSI_CR1_MCOM_16BIT (0xF << SSI_CR1_MCOM_BIT) /* 16-bit command selected */
+#define SSI_CR1_RTRG_BIT 8
+#define SSI_CR1_RTRG_MASK (0xf << SSI_CR1_RTRG_BIT)
+ #define SSI_CR1_RTRG_1 (0 << SSI_CR1_RTRG_BIT)
+ #define SSI_CR1_RTRG_8 (1 << SSI_CR1_RTRG_BIT)
+ #define SSI_CR1_RTRG_16 (2 << SSI_CR1_RTRG_BIT)
+ #define SSI_CR1_RTRG_24 (3 << SSI_CR1_RTRG_BIT)
+ #define SSI_CR1_RTRG_32 (4 << SSI_CR1_RTRG_BIT)
+ #define SSI_CR1_RTRG_40 (5 << SSI_CR1_RTRG_BIT)
+ #define SSI_CR1_RTRG_48 (6 << SSI_CR1_RTRG_BIT)
+ #define SSI_CR1_RTRG_56 (7 << SSI_CR1_RTRG_BIT)
+ #define SSI_CR1_RTRG_64 (8 << SSI_CR1_RTRG_BIT)
+ #define SSI_CR1_RTRG_72 (9 << SSI_CR1_RTRG_BIT)
+ #define SSI_CR1_RTRG_80 (10<< SSI_CR1_RTRG_BIT)
+ #define SSI_CR1_RTRG_88 (11<< SSI_CR1_RTRG_BIT)
+ #define SSI_CR1_RTRG_96 (12<< SSI_CR1_RTRG_BIT)
+ #define SSI_CR1_RTRG_104 (13<< SSI_CR1_RTRG_BIT)
+ #define SSI_CR1_RTRG_112 (14<< SSI_CR1_RTRG_BIT)
+ #define SSI_CR1_RTRG_120 (15<< SSI_CR1_RTRG_BIT)
+#define SSI_CR1_FLEN_BIT 4
+#define SSI_CR1_FLEN_MASK (0xf << SSI_CR1_FLEN_BIT)
+ #define SSI_CR1_FLEN_2BIT (0x0 << SSI_CR1_FLEN_BIT)
+ #define SSI_CR1_FLEN_3BIT (0x1 << SSI_CR1_FLEN_BIT)
+ #define SSI_CR1_FLEN_4BIT (0x2 << SSI_CR1_FLEN_BIT)
+ #define SSI_CR1_FLEN_5BIT (0x3 << SSI_CR1_FLEN_BIT)
+ #define SSI_CR1_FLEN_6BIT (0x4 << SSI_CR1_FLEN_BIT)
+ #define SSI_CR1_FLEN_7BIT (0x5 << SSI_CR1_FLEN_BIT)
+ #define SSI_CR1_FLEN_8BIT (0x6 << SSI_CR1_FLEN_BIT)
+ #define SSI_CR1_FLEN_9BIT (0x7 << SSI_CR1_FLEN_BIT)
+ #define SSI_CR1_FLEN_10BIT (0x8 << SSI_CR1_FLEN_BIT)
+ #define SSI_CR1_FLEN_11BIT (0x9 << SSI_CR1_FLEN_BIT)
+ #define SSI_CR1_FLEN_12BIT (0xA << SSI_CR1_FLEN_BIT)
+ #define SSI_CR1_FLEN_13BIT (0xB << SSI_CR1_FLEN_BIT)
+ #define SSI_CR1_FLEN_14BIT (0xC << SSI_CR1_FLEN_BIT)
+ #define SSI_CR1_FLEN_15BIT (0xD << SSI_CR1_FLEN_BIT)
+ #define SSI_CR1_FLEN_16BIT (0xE << SSI_CR1_FLEN_BIT)
+ #define SSI_CR1_FLEN_17BIT (0xF << SSI_CR1_FLEN_BIT)
+#define SSI_CR1_PHA (1 << 1)
+#define SSI_CR1_POL (1 << 0)
+
+/* SSI Status Register (SSI_SR) */
+
+#define SSI_SR_TFIFONUM_BIT 16
+#define SSI_SR_TFIFONUM_MASK (0xff << SSI_SR_TFIFONUM_BIT)
+#define SSI_SR_RFIFONUM_BIT 8
+#define SSI_SR_RFIFONUM_MASK (0xff << SSI_SR_RFIFONUM_BIT)
+#define SSI_SR_END (1 << 7)
+#define SSI_SR_BUSY (1 << 6)
+#define SSI_SR_TFF (1 << 5)
+#define SSI_SR_RFE (1 << 4)
+#define SSI_SR_TFHE (1 << 3)
+#define SSI_SR_RFHF (1 << 2)
+#define SSI_SR_UNDR (1 << 1)
+#define SSI_SR_OVER (1 << 0)
+
+/* SSI Interval Time Control Register (SSI_ITR) */
+
+#define SSI_ITR_CNTCLK (1 << 15)
+#define SSI_ITR_IVLTM_BIT 0
+#define SSI_ITR_IVLTM_MASK (0x7fff << SSI_ITR_IVLTM_BIT)
+
+
+/*************************************************************************
+ * MSC
+ *************************************************************************/
+#define MSC_STRPCL (MSC_BASE + 0x000)
+#define MSC_STAT (MSC_BASE + 0x004)
+#define MSC_CLKRT (MSC_BASE + 0x008)
+#define MSC_CMDAT (MSC_BASE + 0x00C)
+#define MSC_RESTO (MSC_BASE + 0x010)
+#define MSC_RDTO (MSC_BASE + 0x014)
+#define MSC_BLKLEN (MSC_BASE + 0x018)
+#define MSC_NOB (MSC_BASE + 0x01C)
+#define MSC_SNOB (MSC_BASE + 0x020)
+#define MSC_IMASK (MSC_BASE + 0x024)
+#define MSC_IREG (MSC_BASE + 0x028)
+#define MSC_CMD (MSC_BASE + 0x02C)
+#define MSC_ARG (MSC_BASE + 0x030)
+#define MSC_RES (MSC_BASE + 0x034)
+#define MSC_RXFIFO (MSC_BASE + 0x038)
+#define MSC_TXFIFO (MSC_BASE + 0x03C)
+
+#define REG_MSC_STRPCL REG16(MSC_STRPCL)
+#define REG_MSC_STAT REG32(MSC_STAT)
+#define REG_MSC_CLKRT REG16(MSC_CLKRT)
+#define REG_MSC_CMDAT REG32(MSC_CMDAT)
+#define REG_MSC_RESTO REG16(MSC_RESTO)
+#define REG_MSC_RDTO REG16(MSC_RDTO)
+#define REG_MSC_BLKLEN REG16(MSC_BLKLEN)
+#define REG_MSC_NOB REG16(MSC_NOB)
+#define REG_MSC_SNOB REG16(MSC_SNOB)
+#define REG_MSC_IMASK REG16(MSC_IMASK)
+#define REG_MSC_IREG REG16(MSC_IREG)
+#define REG_MSC_CMD REG8(MSC_CMD)
+#define REG_MSC_ARG REG32(MSC_ARG)
+#define REG_MSC_RES REG16(MSC_RES)
+#define REG_MSC_RXFIFO REG32(MSC_RXFIFO)
+#define REG_MSC_TXFIFO REG32(MSC_TXFIFO)
+
+/* MSC Clock and Control Register (MSC_STRPCL) */
+
+#define MSC_STRPCL_EXIT_MULTIPLE (1 << 7)
+#define MSC_STRPCL_EXIT_TRANSFER (1 << 6)
+#define MSC_STRPCL_START_READWAIT (1 << 5)
+#define MSC_STRPCL_STOP_READWAIT (1 << 4)
+#define MSC_STRPCL_RESET (1 << 3)
+#define MSC_STRPCL_START_OP (1 << 2)
+#define MSC_STRPCL_CLOCK_CONTROL_BIT 0
+#define MSC_STRPCL_CLOCK_CONTROL_MASK (0x3 << MSC_STRPCL_CLOCK_CONTROL_BIT)
+ #define MSC_STRPCL_CLOCK_CONTROL_STOP (0x1 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Stop MMC/SD clock */
+ #define MSC_STRPCL_CLOCK_CONTROL_START (0x2 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Start MMC/SD clock */
+
+/* MSC Status Register (MSC_STAT) */
+
+#define MSC_STAT_IS_RESETTING (1 << 15)
+#define MSC_STAT_SDIO_INT_ACTIVE (1 << 14)
+#define MSC_STAT_PRG_DONE (1 << 13)
+#define MSC_STAT_DATA_TRAN_DONE (1 << 12)
+#define MSC_STAT_END_CMD_RES (1 << 11)
+#define MSC_STAT_DATA_FIFO_AFULL (1 << 10)
+#define MSC_STAT_IS_READWAIT (1 << 9)
+#define MSC_STAT_CLK_EN (1 << 8)
+#define MSC_STAT_DATA_FIFO_FULL (1 << 7)
+#define MSC_STAT_DATA_FIFO_EMPTY (1 << 6)
+#define MSC_STAT_CRC_RES_ERR (1 << 5)
+#define MSC_STAT_CRC_READ_ERROR (1 << 4)
+#define MSC_STAT_CRC_WRITE_ERROR_BIT 2
+#define MSC_STAT_CRC_WRITE_ERROR_MASK (0x3 << MSC_STAT_CRC_WRITE_ERROR_BIT)
+ #define MSC_STAT_CRC_WRITE_ERROR_NO (0 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No error on transmission of data */
+ #define MSC_STAT_CRC_WRITE_ERROR (1 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* Card observed erroneous transmission of data */
+ #define MSC_STAT_CRC_WRITE_ERROR_NOSTS (2 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No CRC status is sent back */
+#define MSC_STAT_TIME_OUT_RES (1 << 1)
+#define MSC_STAT_TIME_OUT_READ (1 << 0)
+
+/* MSC Bus Clock Control Register (MSC_CLKRT) */
+
+#define MSC_CLKRT_CLK_RATE_BIT 0
+#define MSC_CLKRT_CLK_RATE_MASK (0x7 << MSC_CLKRT_CLK_RATE_BIT)
+ #define MSC_CLKRT_CLK_RATE_DIV_1 (0x0 << MSC_CLKRT_CLK_RATE_BIT) /* CLK_SRC */
+ #define MSC_CLKRT_CLK_RATE_DIV_2 (0x1 << MSC_CLKRT_CLK_RATE_BIT) /* 1/2 of CLK_SRC */
+ #define MSC_CLKRT_CLK_RATE_DIV_4 (0x2 << MSC_CLKRT_CLK_RATE_BIT) /* 1/4 of CLK_SRC */
+ #define MSC_CLKRT_CLK_RATE_DIV_8 (0x3 << MSC_CLKRT_CLK_RATE_BIT) /* 1/8 of CLK_SRC */
+ #define MSC_CLKRT_CLK_RATE_DIV_16 (0x4 << MSC_CLKRT_CLK_RATE_BIT) /* 1/16 of CLK_SRC */
+ #define MSC_CLKRT_CLK_RATE_DIV_32 (0x5 << MSC_CLKRT_CLK_RATE_BIT) /* 1/32 of CLK_SRC */
+ #define MSC_CLKRT_CLK_RATE_DIV_64 (0x6 << MSC_CLKRT_CLK_RATE_BIT) /* 1/64 of CLK_SRC */
+ #define MSC_CLKRT_CLK_RATE_DIV_128 (0x7 << MSC_CLKRT_CLK_RATE_BIT) /* 1/128 of CLK_SRC */
+
+/* MSC Command Sequence Control Register (MSC_CMDAT) */
+
+#define MSC_CMDAT_IO_ABORT (1 << 11)
+#define MSC_CMDAT_BUS_WIDTH_BIT 9
+#define MSC_CMDAT_BUS_WIDTH_MASK (0x3 << MSC_CMDAT_BUS_WIDTH_BIT)
+ #define MSC_CMDAT_BUS_WIDTH_1BIT (0x0 << MSC_CMDAT_BUS_WIDTH_BIT) /* 1-bit data bus */
+ #define MSC_CMDAT_BUS_WIDTH_4BIT (0x2 << MSC_CMDAT_BUS_WIDTH_BIT) /* 4-bit data bus */
+ #define CMDAT_BUS_WIDTH1 (0x0 << MSC_CMDAT_BUS_WIDTH_BIT)
+ #define CMDAT_BUS_WIDTH4 (0x2 << MSC_CMDAT_BUS_WIDTH_BIT)
+#define MSC_CMDAT_DMA_EN (1 << 8)
+#define MSC_CMDAT_INIT (1 << 7)
+#define MSC_CMDAT_BUSY (1 << 6)
+#define MSC_CMDAT_STREAM_BLOCK (1 << 5)
+#define MSC_CMDAT_WRITE (1 << 4)
+#define MSC_CMDAT_READ (0 << 4)
+#define MSC_CMDAT_DATA_EN (1 << 3)
+#define MSC_CMDAT_RESPONSE_BIT 0
+#define MSC_CMDAT_RESPONSE_MASK (0x7 << MSC_CMDAT_RESPONSE_BIT)
+ #define MSC_CMDAT_RESPONSE_NONE (0x0 << MSC_CMDAT_RESPONSE_BIT) /* No response */
+ #define MSC_CMDAT_RESPONSE_R1 (0x1 << MSC_CMDAT_RESPONSE_BIT) /* Format R1 and R1b */
+ #define MSC_CMDAT_RESPONSE_R2 (0x2 << MSC_CMDAT_RESPONSE_BIT) /* Format R2 */
+ #define MSC_CMDAT_RESPONSE_R3 (0x3 << MSC_CMDAT_RESPONSE_BIT) /* Format R3 */
+ #define MSC_CMDAT_RESPONSE_R4 (0x4 << MSC_CMDAT_RESPONSE_BIT) /* Format R4 */
+ #define MSC_CMDAT_RESPONSE_R5 (0x5 << MSC_CMDAT_RESPONSE_BIT) /* Format R5 */
+ #define MSC_CMDAT_RESPONSE_R6 (0x6 << MSC_CMDAT_RESPONSE_BIT) /* Format R6 */
+
+#define CMDAT_DMA_EN (1 << 8)
+#define CMDAT_INIT (1 << 7)
+#define CMDAT_BUSY (1 << 6)
+#define CMDAT_STREAM (1 << 5)
+#define CMDAT_WRITE (1 << 4)
+#define CMDAT_DATA_EN (1 << 3)
+
+/* MSC Interrupts Mask Register (MSC_IMASK) */
+
+#define MSC_IMASK_SDIO (1 << 7)
+#define MSC_IMASK_TXFIFO_WR_REQ (1 << 6)
+#define MSC_IMASK_RXFIFO_RD_REQ (1 << 5)
+#define MSC_IMASK_END_CMD_RES (1 << 2)
+#define MSC_IMASK_PRG_DONE (1 << 1)
+#define MSC_IMASK_DATA_TRAN_DONE (1 << 0)
+
+
+/* MSC Interrupts Status Register (MSC_IREG) */
+
+#define MSC_IREG_SDIO (1 << 7)
+#define MSC_IREG_TXFIFO_WR_REQ (1 << 6)
+#define MSC_IREG_RXFIFO_RD_REQ (1 << 5)
+#define MSC_IREG_END_CMD_RES (1 << 2)
+#define MSC_IREG_PRG_DONE (1 << 1)
+#define MSC_IREG_DATA_TRAN_DONE (1 << 0)
+
+
+/*************************************************************************
+ * EMC (External Memory Controller)
+ *************************************************************************/
+#define EMC_BCR (EMC_BASE + 0x0) /* BCR */
+
+#define EMC_SMCR0 (EMC_BASE + 0x10) /* Static Memory Control Register 0 */
+#define EMC_SMCR1 (EMC_BASE + 0x14) /* Static Memory Control Register 1 */
+#define EMC_SMCR2 (EMC_BASE + 0x18) /* Static Memory Control Register 2 */
+#define EMC_SMCR3 (EMC_BASE + 0x1c) /* Static Memory Control Register 3 */
+#define EMC_SMCR4 (EMC_BASE + 0x20) /* Static Memory Control Register 4 */
+#define EMC_SACR0 (EMC_BASE + 0x30) /* Static Memory Bank 0 Addr Config Reg */
+#define EMC_SACR1 (EMC_BASE + 0x34) /* Static Memory Bank 1 Addr Config Reg */
+#define EMC_SACR2 (EMC_BASE + 0x38) /* Static Memory Bank 2 Addr Config Reg */
+#define EMC_SACR3 (EMC_BASE + 0x3c) /* Static Memory Bank 3 Addr Config Reg */
+#define EMC_SACR4 (EMC_BASE + 0x40) /* Static Memory Bank 4 Addr Config Reg */
+
+#define EMC_NFCSR (EMC_BASE + 0x050) /* NAND Flash Control/Status Register */
+#define EMC_NFECR (EMC_BASE + 0x100) /* NAND Flash ECC Control Register */
+#define EMC_NFECC (EMC_BASE + 0x104) /* NAND Flash ECC Data Register */
+#define EMC_NFPAR0 (EMC_BASE + 0x108) /* NAND Flash RS Parity 0 Register */
+#define EMC_NFPAR1 (EMC_BASE + 0x10c) /* NAND Flash RS Parity 1 Register */
+#define EMC_NFPAR2 (EMC_BASE + 0x110) /* NAND Flash RS Parity 2 Register */
+#define EMC_NFINTS (EMC_BASE + 0x114) /* NAND Flash Interrupt Status Register */
+#define EMC_NFINTE (EMC_BASE + 0x118) /* NAND Flash Interrupt Enable Register */
+#define EMC_NFERR0 (EMC_BASE + 0x11c) /* NAND Flash RS Error Report 0 Register */
+#define EMC_NFERR1 (EMC_BASE + 0x120) /* NAND Flash RS Error Report 1 Register */
+#define EMC_NFERR2 (EMC_BASE + 0x124) /* NAND Flash RS Error Report 2 Register */
+#define EMC_NFERR3 (EMC_BASE + 0x128) /* NAND Flash RS Error Report 3 Register */
+
+#define EMC_DMCR (EMC_BASE + 0x80) /* DRAM Control Register */
+#define EMC_RTCSR (EMC_BASE + 0x84) /* Refresh Time Control/Status Register */
+#define EMC_RTCNT (EMC_BASE + 0x88) /* Refresh Timer Counter */
+#define EMC_RTCOR (EMC_BASE + 0x8c) /* Refresh Time Constant Register */
+#define EMC_DMAR0 (EMC_BASE + 0x90) /* SDRAM Bank 0 Addr Config Register */
+#define EMC_SDMR0 (EMC_BASE + 0xa000) /* Mode Register of SDRAM bank 0 */
+
+#define REG_EMC_BCR REG32(EMC_BCR)
+
+#define REG_EMC_SMCR0 REG32(EMC_SMCR0)
+#define REG_EMC_SMCR1 REG32(EMC_SMCR1)
+#define REG_EMC_SMCR2 REG32(EMC_SMCR2)
+#define REG_EMC_SMCR3 REG32(EMC_SMCR3)
+#define REG_EMC_SMCR4 REG32(EMC_SMCR4)
+#define REG_EMC_SACR0 REG32(EMC_SACR0)
+#define REG_EMC_SACR1 REG32(EMC_SACR1)
+#define REG_EMC_SACR2 REG32(EMC_SACR2)
+#define REG_EMC_SACR3 REG32(EMC_SACR3)
+#define REG_EMC_SACR4 REG32(EMC_SACR4)
+
+#define REG_EMC_NFCSR REG32(EMC_NFCSR)
+#define REG_EMC_NFECR REG32(EMC_NFECR)
+#define REG_EMC_NFECC REG32(EMC_NFECC)
+#define REG_EMC_NFPAR0 REG32(EMC_NFPAR0)
+#define REG_EMC_NFPAR1 REG32(EMC_NFPAR1)
+#define REG_EMC_NFPAR2 REG32(EMC_NFPAR2)
+#define REG_EMC_NFINTS REG32(EMC_NFINTS)
+#define REG_EMC_NFINTE REG32(EMC_NFINTE)
+#define REG_EMC_NFERR0 REG32(EMC_NFERR0)
+#define REG_EMC_NFERR1 REG32(EMC_NFERR1)
+#define REG_EMC_NFERR2 REG32(EMC_NFERR2)
+#define REG_EMC_NFERR3 REG32(EMC_NFERR3)
+
+#define REG_EMC_DMCR REG32(EMC_DMCR)
+#define REG_EMC_RTCSR REG16(EMC_RTCSR)
+#define REG_EMC_RTCNT REG16(EMC_RTCNT)
+#define REG_EMC_RTCOR REG16(EMC_RTCOR)
+#define REG_EMC_DMAR0 REG32(EMC_DMAR0)
+
+/* Static Memory Control Register */
+#define EMC_SMCR_STRV_BIT 24
+#define EMC_SMCR_STRV_MASK (0x0f << EMC_SMCR_STRV_BIT)
+#define EMC_SMCR_TAW_BIT 20
+#define EMC_SMCR_TAW_MASK (0x0f << EMC_SMCR_TAW_BIT)
+#define EMC_SMCR_TBP_BIT 16
+#define EMC_SMCR_TBP_MASK (0x0f << EMC_SMCR_TBP_BIT)
+#define EMC_SMCR_TAH_BIT 12
+#define EMC_SMCR_TAH_MASK (0x07 << EMC_SMCR_TAH_BIT)
+#define EMC_SMCR_TAS_BIT 8
+#define EMC_SMCR_TAS_MASK (0x07 << EMC_SMCR_TAS_BIT)
+#define EMC_SMCR_BW_BIT 6
+#define EMC_SMCR_BW_MASK (0x03 << EMC_SMCR_BW_BIT)
+ #define EMC_SMCR_BW_8BIT (0 << EMC_SMCR_BW_BIT)
+ #define EMC_SMCR_BW_16BIT (1 << EMC_SMCR_BW_BIT)
+ #define EMC_SMCR_BW_32BIT (2 << EMC_SMCR_BW_BIT)
+#define EMC_SMCR_BCM (1 << 3)
+#define EMC_SMCR_BL_BIT 1
+#define EMC_SMCR_BL_MASK (0x03 << EMC_SMCR_BL_BIT)
+ #define EMC_SMCR_BL_4 (0 << EMC_SMCR_BL_BIT)
+ #define EMC_SMCR_BL_8 (1 << EMC_SMCR_BL_BIT)
+ #define EMC_SMCR_BL_16 (2 << EMC_SMCR_BL_BIT)
+ #define EMC_SMCR_BL_32 (3 << EMC_SMCR_BL_BIT)
+#define EMC_SMCR_SMT (1 << 0)
+
+/* Static Memory Bank Addr Config Reg */
+#define EMC_SACR_BASE_BIT 8
+#define EMC_SACR_BASE_MASK (0xff << EMC_SACR_BASE_BIT)
+#define EMC_SACR_MASK_BIT 0
+#define EMC_SACR_MASK_MASK (0xff << EMC_SACR_MASK_BIT)
+
+/* NAND Flash Control/Status Register */
+#define EMC_NFCSR_NFCE4 (1 << 7) /* NAND Flash Enable */
+#define EMC_NFCSR_NFE4 (1 << 6) /* NAND Flash FCE# Assertion Enable */
+#define EMC_NFCSR_NFCE3 (1 << 5)
+#define EMC_NFCSR_NFE3 (1 << 4)
+#define EMC_NFCSR_NFCE2 (1 << 3)
+#define EMC_NFCSR_NFE2 (1 << 2)
+#define EMC_NFCSR_NFCE1 (1 << 1)
+#define EMC_NFCSR_NFE1 (1 << 0)
+
+/* NAND Flash ECC Control Register */
+#define EMC_NFECR_PRDY (1 << 4) /* Parity Ready */
+#define EMC_NFECR_RS_DECODING (0 << 3) /* RS is in decoding phase */
+#define EMC_NFECR_RS_ENCODING (1 << 3) /* RS is in encoding phase */
+#define EMC_NFECR_HAMMING (0 << 2) /* Select HAMMING Correction Algorithm */
+#define EMC_NFECR_RS (1 << 2) /* Select RS Correction Algorithm */
+#define EMC_NFECR_ERST (1 << 1) /* ECC Reset */
+#define EMC_NFECR_ECCE (1 << 0) /* ECC Enable */
+
+/* NAND Flash ECC Data Register */
+#define EMC_NFECC_ECC2_BIT 16
+#define EMC_NFECC_ECC2_MASK (0xff << EMC_NFECC_ECC2_BIT)
+#define EMC_NFECC_ECC1_BIT 8
+#define EMC_NFECC_ECC1_MASK (0xff << EMC_NFECC_ECC1_BIT)
+#define EMC_NFECC_ECC0_BIT 0
+#define EMC_NFECC_ECC0_MASK (0xff << EMC_NFECC_ECC0_BIT)
+
+/* NAND Flash Interrupt Status Register */
+#define EMC_NFINTS_ERRCNT_BIT 29 /* Error Count */
+#define EMC_NFINTS_ERRCNT_MASK (0x7 << EMC_NFINTS_ERRCNT_BIT)
+#define EMC_NFINTS_PADF (1 << 4) /* Padding Finished */
+#define EMC_NFINTS_DECF (1 << 3) /* Decoding Finished */
+#define EMC_NFINTS_ENCF (1 << 2) /* Encoding Finished */
+#define EMC_NFINTS_UNCOR (1 << 1) /* Uncorrectable Error Occurred */
+#define EMC_NFINTS_ERR (1 << 0) /* Error Occurred */
+
+/* NAND Flash Interrupt Enable Register */
+#define EMC_NFINTE_PADFE (1 << 4) /* Padding Finished Interrupt Enable */
+#define EMC_NFINTE_DECFE (1 << 3) /* Decoding Finished Interrupt Enable */
+#define EMC_NFINTE_ENCFE (1 << 2) /* Encoding Finished Interrupt Enable */
+#define EMC_NFINTE_UNCORE (1 << 1) /* Uncorrectable Error Occurred Intr Enable */
+#define EMC_NFINTE_ERRE (1 << 0) /* Error Occurred Interrupt */
+
+/* NAND Flash RS Error Report Register */
+#define EMC_NFERR_INDEX_BIT 16 /* Error Symbol Index */
+#define EMC_NFERR_INDEX_MASK (0x1ff << EMC_NFERR_INDEX_BIT)
+#define EMC_NFERR_MASK_BIT 0 /* Error Symbol Value */
+#define EMC_NFERR_MASK_MASK (0x1ff << EMC_NFERR_MASK_BIT)
+
+
+/* DRAM Control Register */
+#define EMC_DMCR_BW_BIT 31
+#define EMC_DMCR_BW (1 << EMC_DMCR_BW_BIT)
+#define EMC_DMCR_CA_BIT 26
+#define EMC_DMCR_CA_MASK (0x07 << EMC_DMCR_CA_BIT)
+ #define EMC_DMCR_CA_8 (0 << EMC_DMCR_CA_BIT)
+ #define EMC_DMCR_CA_9 (1 << EMC_DMCR_CA_BIT)
+ #define EMC_DMCR_CA_10 (2 << EMC_DMCR_CA_BIT)
+ #define EMC_DMCR_CA_11 (3 << EMC_DMCR_CA_BIT)
+ #define EMC_DMCR_CA_12 (4 << EMC_DMCR_CA_BIT)
+#define EMC_DMCR_RMODE (1 << 25)
+#define EMC_DMCR_RFSH (1 << 24)
+#define EMC_DMCR_MRSET (1 << 23)
+#define EMC_DMCR_RA_BIT 20
+#define EMC_DMCR_RA_MASK (0x03 << EMC_DMCR_RA_BIT)
+ #define EMC_DMCR_RA_11 (0 << EMC_DMCR_RA_BIT)
+ #define EMC_DMCR_RA_12 (1 << EMC_DMCR_RA_BIT)
+ #define EMC_DMCR_RA_13 (2 << EMC_DMCR_RA_BIT)
+#define EMC_DMCR_BA_BIT 19
+#define EMC_DMCR_BA (1 << EMC_DMCR_BA_BIT)
+#define EMC_DMCR_PDM (1 << 18)
+#define EMC_DMCR_EPIN (1 << 17)
+#define EMC_DMCR_TRAS_BIT 13
+#define EMC_DMCR_TRAS_MASK (0x07 << EMC_DMCR_TRAS_BIT)
+#define EMC_DMCR_RCD_BIT 11
+#define EMC_DMCR_RCD_MASK (0x03 << EMC_DMCR_RCD_BIT)
+#define EMC_DMCR_TPC_BIT 8
+#define EMC_DMCR_TPC_MASK (0x07 << EMC_DMCR_TPC_BIT)
+#define EMC_DMCR_TRWL_BIT 5
+#define EMC_DMCR_TRWL_MASK (0x03 << EMC_DMCR_TRWL_BIT)
+#define EMC_DMCR_TRC_BIT 2
+#define EMC_DMCR_TRC_MASK (0x07 << EMC_DMCR_TRC_BIT)
+#define EMC_DMCR_TCL_BIT 0
+#define EMC_DMCR_TCL_MASK (0x03 << EMC_DMCR_TCL_BIT)
+
+/* Refresh Time Control/Status Register */
+#define EMC_RTCSR_CMF (1 << 7)
+#define EMC_RTCSR_CKS_BIT 0
+#define EMC_RTCSR_CKS_MASK (0x07 << EMC_RTCSR_CKS_BIT)
+ #define EMC_RTCSR_CKS_DISABLE (0 << EMC_RTCSR_CKS_BIT)
+ #define EMC_RTCSR_CKS_4 (1 << EMC_RTCSR_CKS_BIT)
+ #define EMC_RTCSR_CKS_16 (2 << EMC_RTCSR_CKS_BIT)
+ #define EMC_RTCSR_CKS_64 (3 << EMC_RTCSR_CKS_BIT)
+ #define EMC_RTCSR_CKS_256 (4 << EMC_RTCSR_CKS_BIT)
+ #define EMC_RTCSR_CKS_1024 (5 << EMC_RTCSR_CKS_BIT)
+ #define EMC_RTCSR_CKS_2048 (6 << EMC_RTCSR_CKS_BIT)
+ #define EMC_RTCSR_CKS_4096 (7 << EMC_RTCSR_CKS_BIT)
+
+/* SDRAM Bank Address Configuration Register */
+#define EMC_DMAR_BASE_BIT 8
+#define EMC_DMAR_BASE_MASK (0xff << EMC_DMAR_BASE_BIT)
+#define EMC_DMAR_MASK_BIT 0
+#define EMC_DMAR_MASK_MASK (0xff << EMC_DMAR_MASK_BIT)
+
+/* Mode Register of SDRAM bank 0 */
+#define EMC_SDMR_BM (1 << 9) /* Write Burst Mode */
+#define EMC_SDMR_OM_BIT 7 /* Operating Mode */
+#define EMC_SDMR_OM_MASK (3 << EMC_SDMR_OM_BIT)
+ #define EMC_SDMR_OM_NORMAL (0 << EMC_SDMR_OM_BIT)
+#define EMC_SDMR_CAS_BIT 4 /* CAS Latency */
+#define EMC_SDMR_CAS_MASK (7 << EMC_SDMR_CAS_BIT)
+ #define EMC_SDMR_CAS_1 (1 << EMC_SDMR_CAS_BIT)
+ #define EMC_SDMR_CAS_2 (2 << EMC_SDMR_CAS_BIT)
+ #define EMC_SDMR_CAS_3 (3 << EMC_SDMR_CAS_BIT)
+#define EMC_SDMR_BT_BIT 3 /* Burst Type */
+#define EMC_SDMR_BT_MASK (1 << EMC_SDMR_BT_BIT)
+ #define EMC_SDMR_BT_SEQ (0 << EMC_SDMR_BT_BIT) /* Sequential */
+ #define EMC_SDMR_BT_INT (1 << EMC_SDMR_BT_BIT) /* Interleave */
+#define EMC_SDMR_BL_BIT 0 /* Burst Length */
+#define EMC_SDMR_BL_MASK (7 << EMC_SDMR_BL_BIT)
+ #define EMC_SDMR_BL_1 (0 << EMC_SDMR_BL_BIT)
+ #define EMC_SDMR_BL_2 (1 << EMC_SDMR_BL_BIT)
+ #define EMC_SDMR_BL_4 (2 << EMC_SDMR_BL_BIT)
+ #define EMC_SDMR_BL_8 (3 << EMC_SDMR_BL_BIT)
+
+#define EMC_SDMR_CAS2_16BIT \
+ (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2)
+#define EMC_SDMR_CAS2_32BIT \
+ (EMC_SDMR_CAS_2 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4)
+#define EMC_SDMR_CAS3_16BIT \
+ (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_2)
+#define EMC_SDMR_CAS3_32BIT \
+ (EMC_SDMR_CAS_3 | EMC_SDMR_BT_SEQ | EMC_SDMR_BL_4)
+
+/*************************************************************************
+ * CIM
+ *************************************************************************/
+#define CIM_CFG (CIM_BASE + 0x0000)
+#define CIM_CTRL (CIM_BASE + 0x0004)
+#define CIM_STATE (CIM_BASE + 0x0008)
+#define CIM_IID (CIM_BASE + 0x000C)
+#define CIM_RXFIFO (CIM_BASE + 0x0010)
+#define CIM_DA (CIM_BASE + 0x0020)
+#define CIM_FA (CIM_BASE + 0x0024)
+#define CIM_FID (CIM_BASE + 0x0028)
+#define CIM_CMD (CIM_BASE + 0x002C)
+
+#define REG_CIM_CFG REG32(CIM_CFG)
+#define REG_CIM_CTRL REG32(CIM_CTRL)
+#define REG_CIM_STATE REG32(CIM_STATE)
+#define REG_CIM_IID REG32(CIM_IID)
+#define REG_CIM_RXFIFO REG32(CIM_RXFIFO)
+#define REG_CIM_DA REG32(CIM_DA)
+#define REG_CIM_FA REG32(CIM_FA)
+#define REG_CIM_FID REG32(CIM_FID)
+#define REG_CIM_CMD REG32(CIM_CMD)
+
+/* CIM Configuration Register (CIM_CFG) */
+
+#define CIM_CFG_INV_DAT (1 << 15)
+#define CIM_CFG_VSP (1 << 14)
+#define CIM_CFG_HSP (1 << 13)
+#define CIM_CFG_PCP (1 << 12)
+#define CIM_CFG_DUMMY_ZERO (1 << 9)
+#define CIM_CFG_EXT_VSYNC (1 << 8)
+#define CIM_CFG_PACK_BIT 4
+#define CIM_CFG_PACK_MASK (0x7 << CIM_CFG_PACK_BIT)
+ #define CIM_CFG_PACK_0 (0 << CIM_CFG_PACK_BIT)
+ #define CIM_CFG_PACK_1 (1 << CIM_CFG_PACK_BIT)
+ #define CIM_CFG_PACK_2 (2 << CIM_CFG_PACK_BIT)
+ #define CIM_CFG_PACK_3 (3 << CIM_CFG_PACK_BIT)
+ #define CIM_CFG_PACK_4 (4 << CIM_CFG_PACK_BIT)
+ #define CIM_CFG_PACK_5 (5 << CIM_CFG_PACK_BIT)
+ #define CIM_CFG_PACK_6 (6 << CIM_CFG_PACK_BIT)
+ #define CIM_CFG_PACK_7 (7 << CIM_CFG_PACK_BIT)
+#define CIM_CFG_DSM_BIT 0
+#define CIM_CFG_DSM_MASK (0x3 << CIM_CFG_DSM_BIT)
+ #define CIM_CFG_DSM_CPM (0 << CIM_CFG_DSM_BIT) /* CCIR656 Progressive Mode */
+ #define CIM_CFG_DSM_CIM (1 << CIM_CFG_DSM_BIT) /* CCIR656 Interlace Mode */
+ #define CIM_CFG_DSM_GCM (2 << CIM_CFG_DSM_BIT) /* Gated Clock Mode */
+ #define CIM_CFG_DSM_NGCM (3 << CIM_CFG_DSM_BIT) /* Non-Gated Clock Mode */
+
+/* CIM Control Register (CIM_CTRL) */
+
+#define CIM_CTRL_MCLKDIV_BIT 24
+#define CIM_CTRL_MCLKDIV_MASK (0xff << CIM_CTRL_MCLKDIV_BIT)
+#define CIM_CTRL_FRC_BIT 16
+#define CIM_CTRL_FRC_MASK (0xf << CIM_CTRL_FRC_BIT)
+ #define CIM_CTRL_FRC_1 (0x0 << CIM_CTRL_FRC_BIT) /* Sample every frame */
+ #define CIM_CTRL_FRC_2 (0x1 << CIM_CTRL_FRC_BIT) /* Sample 1/2 frame */
+ #define CIM_CTRL_FRC_3 (0x2 << CIM_CTRL_FRC_BIT) /* Sample 1/3 frame */
+ #define CIM_CTRL_FRC_4 (0x3 << CIM_CTRL_FRC_BIT) /* Sample 1/4 frame */
+ #define CIM_CTRL_FRC_5 (0x4 << CIM_CTRL_FRC_BIT) /* Sample 1/5 frame */
+ #define CIM_CTRL_FRC_6 (0x5 << CIM_CTRL_FRC_BIT) /* Sample 1/6 frame */
+ #define CIM_CTRL_FRC_7 (0x6 << CIM_CTRL_FRC_BIT) /* Sample 1/7 frame */
+ #define CIM_CTRL_FRC_8 (0x7 << CIM_CTRL_FRC_BIT) /* Sample 1/8 frame */
+ #define CIM_CTRL_FRC_9 (0x8 << CIM_CTRL_FRC_BIT) /* Sample 1/9 frame */
+ #define CIM_CTRL_FRC_10 (0x9 << CIM_CTRL_FRC_BIT) /* Sample 1/10 frame */
+ #define CIM_CTRL_FRC_11 (0xA << CIM_CTRL_FRC_BIT) /* Sample 1/11 frame */
+ #define CIM_CTRL_FRC_12 (0xB << CIM_CTRL_FRC_BIT) /* Sample 1/12 frame */
+ #define CIM_CTRL_FRC_13 (0xC << CIM_CTRL_FRC_BIT) /* Sample 1/13 frame */
+ #define CIM_CTRL_FRC_14 (0xD << CIM_CTRL_FRC_BIT) /* Sample 1/14 frame */
+ #define CIM_CTRL_FRC_15 (0xE << CIM_CTRL_FRC_BIT) /* Sample 1/15 frame */
+ #define CIM_CTRL_FRC_16 (0xF << CIM_CTRL_FRC_BIT) /* Sample 1/16 frame */
+#define CIM_CTRL_VDDM (1 << 13)
+#define CIM_CTRL_DMA_SOFM (1 << 12)
+#define CIM_CTRL_DMA_EOFM (1 << 11)
+#define CIM_CTRL_DMA_STOPM (1 << 10)
+#define CIM_CTRL_RXF_TRIGM (1 << 9)
+#define CIM_CTRL_RXF_OFM (1 << 8)
+#define CIM_CTRL_RXF_TRIG_BIT 4
+#define CIM_CTRL_RXF_TRIG_MASK (0x7 << CIM_CTRL_RXF_TRIG_BIT)
+ #define CIM_CTRL_RXF_TRIG_4 (0 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 4 */
+ #define CIM_CTRL_RXF_TRIG_8 (1 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 8 */
+ #define CIM_CTRL_RXF_TRIG_12 (2 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 12 */
+ #define CIM_CTRL_RXF_TRIG_16 (3 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 16 */
+ #define CIM_CTRL_RXF_TRIG_20 (4 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 20 */
+ #define CIM_CTRL_RXF_TRIG_24 (5 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 24 */
+ #define CIM_CTRL_RXF_TRIG_28 (6 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 28 */
+ #define CIM_CTRL_RXF_TRIG_32 (7 << CIM_CTRL_RXF_TRIG_BIT) /* RXFIFO Trigger Value is 32 */
+#define CIM_CTRL_DMA_EN (1 << 2)
+#define CIM_CTRL_RXF_RST (1 << 1)
+#define CIM_CTRL_ENA (1 << 0)
+
+/* CIM State Register (CIM_STATE) */
+
+#define CIM_STATE_DMA_SOF (1 << 6)
+#define CIM_STATE_DMA_EOF (1 << 5)
+#define CIM_STATE_DMA_STOP (1 << 4)
+#define CIM_STATE_RXF_OF (1 << 3)
+#define CIM_STATE_RXF_TRIG (1 << 2)
+#define CIM_STATE_RXF_EMPTY (1 << 1)
+#define CIM_STATE_VDD (1 << 0)
+
+/* CIM DMA Command Register (CIM_CMD) */
+
+#define CIM_CMD_SOFINT (1 << 31)
+#define CIM_CMD_EOFINT (1 << 30)
+#define CIM_CMD_STOP (1 << 28)
+#define CIM_CMD_LEN_BIT 0
+#define CIM_CMD_LEN_MASK (0xffffff << CIM_CMD_LEN_BIT)
+
+
+/*************************************************************************
+ * SADC (Smart A/D Controller)
+ *************************************************************************/
+
+#define SADC_ENA (SADC_BASE + 0x00) /* ADC Enable Register */
+#define SADC_CFG (SADC_BASE + 0x04) /* ADC Configure Register */
+#define SADC_CTRL (SADC_BASE + 0x08) /* ADC Control Register */
+#define SADC_STATE (SADC_BASE + 0x0C) /* ADC Status Register*/
+#define SADC_SAMETIME (SADC_BASE + 0x10) /* ADC Same Point Time Register */
+#define SADC_WAITTIME (SADC_BASE + 0x14) /* ADC Wait Time Register */
+#define SADC_TSDAT (SADC_BASE + 0x18) /* ADC Touch Screen Data Register */
+#define SADC_BATDAT (SADC_BASE + 0x1C) /* ADC PBAT Data Register */
+#define SADC_SADDAT (SADC_BASE + 0x20) /* ADC SADCIN Data Register */
+
+#define REG_SADC_ENA REG8(SADC_ENA)
+#define REG_SADC_CFG REG32(SADC_CFG)
+#define REG_SADC_CTRL REG8(SADC_CTRL)
+#define REG_SADC_STATE REG8(SADC_STATE)
+#define REG_SADC_SAMETIME REG16(SADC_SAMETIME)
+#define REG_SADC_WAITTIME REG16(SADC_WAITTIME)
+#define REG_SADC_TSDAT REG32(SADC_TSDAT)
+#define REG_SADC_BATDAT REG16(SADC_BATDAT)
+#define REG_SADC_SADDAT REG16(SADC_SADDAT)
+
+/* ADC Enable Register */
+#define SADC_ENA_ADEN (1 << 7) /* Touch Screen Enable */
+#define SADC_ENA_TSEN (1 << 2) /* Touch Screen Enable */
+#define SADC_ENA_PBATEN (1 << 1) /* PBAT Enable */
+#define SADC_ENA_SADCINEN (1 << 0) /* SADCIN Enable */
+
+/* ADC Configure Register */
+#define SADC_CFG_CLKOUT_NUM_BIT 16
+#define SADC_CFG_CLKOUT_NUM_MASK (0x7 << SADC_CFG_CLKOUT_NUM_BIT)
+#define SADC_CFG_TS_DMA (1 << 15) /* Touch Screen DMA Enable */
+#define SADC_CFG_XYZ_BIT 13 /* XYZ selection */
+#define SADC_CFG_XYZ_MASK (0x3 << SADC_CFG_XYZ_BIT)
+ #define SADC_CFG_XY (0 << SADC_CFG_XYZ_BIT)
+ #define SADC_CFG_XYZ (1 << SADC_CFG_XYZ_BIT)
+ #define SADC_CFG_XYZ1Z2 (2 << SADC_CFG_XYZ_BIT)
+#define SADC_CFG_SNUM_BIT 10 /* Sample Number */
+#define SADC_CFG_SNUM_MASK (0x7 << SADC_CFG_SNUM_BIT)
+ #define SADC_CFG_SNUM_1 (0x0 << SADC_CFG_SNUM_BIT)
+ #define SADC_CFG_SNUM_2 (0x1 << SADC_CFG_SNUM_BIT)
+ #define SADC_CFG_SNUM_3 (0x2 << SADC_CFG_SNUM_BIT)
+ #define SADC_CFG_SNUM_4 (0x3 << SADC_CFG_SNUM_BIT)
+ #define SADC_CFG_SNUM_5 (0x4 << SADC_CFG_SNUM_BIT)
+ #define SADC_CFG_SNUM_6 (0x5 << SADC_CFG_SNUM_BIT)
+ #define SADC_CFG_SNUM_8 (0x6 << SADC_CFG_SNUM_BIT)
+ #define SADC_CFG_SNUM_9 (0x7 << SADC_CFG_SNUM_BIT)
+#define SADC_CFG_CLKDIV_BIT 5 /* AD Converter frequency clock divider */
+#define SADC_CFG_CLKDIV_MASK (0x1f << SADC_CFG_CLKDIV_BIT)
+#define SADC_CFG_PBAT_HIGH (0 << 4) /* PBAT >= 2.5V */
+#define SADC_CFG_PBAT_LOW (1 << 4) /* PBAT < 2.5V */
+#define SADC_CFG_CMD_BIT 0 /* ADC Command */
+#define SADC_CFG_CMD_MASK (0xf << SADC_CFG_CMD_BIT)
+ #define SADC_CFG_CMD_X_SE (0x0 << SADC_CFG_CMD_BIT) /* X Single-End */
+ #define SADC_CFG_CMD_Y_SE (0x1 << SADC_CFG_CMD_BIT) /* Y Single-End */
+ #define SADC_CFG_CMD_X_DIFF (0x2 << SADC_CFG_CMD_BIT) /* X Differential */
+ #define SADC_CFG_CMD_Y_DIFF (0x3 << SADC_CFG_CMD_BIT) /* Y Differential */
+ #define SADC_CFG_CMD_Z1_DIFF (0x4 << SADC_CFG_CMD_BIT) /* Z1 Differential */
+ #define SADC_CFG_CMD_Z2_DIFF (0x5 << SADC_CFG_CMD_BIT) /* Z2 Differential */
+ #define SADC_CFG_CMD_Z3_DIFF (0x6 << SADC_CFG_CMD_BIT) /* Z3 Differential */
+ #define SADC_CFG_CMD_Z4_DIFF (0x7 << SADC_CFG_CMD_BIT) /* Z4 Differential */
+ #define SADC_CFG_CMD_TP_SE (0x8 << SADC_CFG_CMD_BIT) /* Touch Pressure */
+ #define SADC_CFG_CMD_PBATH_SE (0x9 << SADC_CFG_CMD_BIT) /* PBAT >= 2.5V */
+ #define SADC_CFG_CMD_PBATL_SE (0xa << SADC_CFG_CMD_BIT) /* PBAT < 2.5V */
+ #define SADC_CFG_CMD_SADCIN_SE (0xb << SADC_CFG_CMD_BIT) /* Measure SADCIN */
+ #define SADC_CFG_CMD_INT_PEN (0xc << SADC_CFG_CMD_BIT) /* INT_PEN Enable */
+
+/* ADC Control Register */
+#define SADC_CTRL_PENDM (1 << 4) /* Pen Down Interrupt Mask */
+#define SADC_CTRL_PENUM (1 << 3) /* Pen Up Interrupt Mask */
+#define SADC_CTRL_TSRDYM (1 << 2) /* Touch Screen Data Ready Interrupt Mask */
+#define SADC_CTRL_PBATRDYM (1 << 1) /* PBAT Data Ready Interrupt Mask */
+#define SADC_CTRL_SRDYM (1 << 0) /* SADCIN Data Ready Interrupt Mask */
+
+/* ADC Status Register */
+#define SADC_STATE_TSBUSY (1 << 7) /* TS A/D is working */
+#define SADC_STATE_PBATBUSY (1 << 6) /* PBAT A/D is working */
+#define SADC_STATE_SBUSY (1 << 5) /* SADCIN A/D is working */
+#define SADC_STATE_PEND (1 << 4) /* Pen Down Interrupt Flag */
+#define SADC_STATE_PENU (1 << 3) /* Pen Up Interrupt Flag */
+#define SADC_STATE_TSRDY (1 << 2) /* Touch Screen Data Ready Interrupt Flag */
+#define SADC_STATE_PBATRDY (1 << 1) /* PBAT Data Ready Interrupt Flag */
+#define SADC_STATE_SRDY (1 << 0) /* SADCIN Data Ready Interrupt Flag */
+
+/* ADC Touch Screen Data Register */
+#define SADC_TSDAT_DATA0_BIT 0
+#define SADC_TSDAT_DATA0_MASK (0xfff << SADC_TSDAT_DATA0_BIT)
+#define SADC_TSDAT_TYPE0 (1 << 15)
+#define SADC_TSDAT_DATA1_BIT 16
+#define SADC_TSDAT_DATA1_MASK (0xfff << SADC_TSDAT_DATA1_BIT)
+#define SADC_TSDAT_TYPE1 (1 << 31)
+
+
+/*************************************************************************
+ * SLCD (Smart LCD Controller)
+ *************************************************************************/
+
+#define SLCD_CFG (SLCD_BASE + 0xA0) /* SLCD Configure Register */
+#define SLCD_CTRL (SLCD_BASE + 0xA4) /* SLCD Control Register */
+#define SLCD_STATE (SLCD_BASE + 0xA8) /* SLCD Status Register */
+#define SLCD_DATA (SLCD_BASE + 0xAC) /* SLCD Data Register */
+#define SLCD_FIFO (SLCD_BASE + 0xB0) /* SLCD FIFO Register */
+
+#define REG_SLCD_CFG REG32(SLCD_CFG)
+#define REG_SLCD_CTRL REG8(SLCD_CTRL)
+#define REG_SLCD_STATE REG8(SLCD_STATE)
+#define REG_SLCD_DATA REG32(SLCD_DATA)
+#define REG_SLCD_FIFO REG32(SLCD_FIFO)
+
+/* SLCD Configure Register */
+#define SLCD_CFG_BURST_BIT 14
+#define SLCD_CFG_BURST_MASK (0x3 << SLCD_CFG_BURST_BIT)
+ #define SLCD_CFG_BURST_4_WORD (0 << SLCD_CFG_BURST_BIT)
+ #define SLCD_CFG_BURST_8_WORD (1 << SLCD_CFG_BURST_BIT)
+#define SLCD_CFG_DWIDTH_BIT 10
+#define SLCD_CFG_DWIDTH_MASK (0x7 << SLCD_CFG_DWIDTH_BIT)
+ #define SLCD_CFG_DWIDTH_18 (0 << SLCD_CFG_DWIDTH_BIT)
+ #define SLCD_CFG_DWIDTH_16 (1 << SLCD_CFG_DWIDTH_BIT)
+ #define SLCD_CFG_DWIDTH_8_x3 (2 << SLCD_CFG_DWIDTH_BIT)
+ #define SLCD_CFG_DWIDTH_8_x2 (3 << SLCD_CFG_DWIDTH_BIT)
+ #define SLCD_CFG_DWIDTH_8_x1 (4 << SLCD_CFG_DWIDTH_BIT)
+ #define SLCD_CFG_DWIDTH_9_x2 (4 << SLCD_CFG_DWIDTH_BIT)
+#define SLCD_CFG_CWIDTH_16BIT (0 << 8)
+#define SLCD_CFG_CWIDTH_8BIT (1 << 8)
+#define SLCD_CFG_CWIDTH_18BIT (2 << 8)
+#define SLCD_CFG_CS_ACTIVE_LOW (0 << 4)
+#define SLCD_CFG_CS_ACTIVE_HIGH (1 << 4)
+#define SLCD_CFG_RS_CMD_LOW (0 << 3)
+#define SLCD_CFG_RS_CMD_HIGH (1 << 3)
+#define SLCD_CFG_CLK_ACTIVE_FALLING (0 << 1)
+#define SLCD_CFG_CLK_ACTIVE_RISING (1 << 1)
+#define SLCD_CFG_TYPE_PARALLEL (0 << 0)
+#define SLCD_CFG_TYPE_SERIAL (1 << 0)
+
+/* SLCD Control Register */
+#define SLCD_CTRL_DMA_EN (1 << 0)
+
+/* SLCD Status Register */
+#define SLCD_STATE_BUSY (1 << 0)
+
+/* SLCD Data Register */
+#define SLCD_DATA_RS_DATA (0 << 31)
+#define SLCD_DATA_RS_COMMAND (1 << 31)
+
+/* SLCD FIFO Register */
+#define SLCD_FIFO_RS_DATA (0 << 31)
+#define SLCD_FIFO_RS_COMMAND (1 << 31)
+
+
+/*************************************************************************
+ * LCD (LCD Controller)
+ *************************************************************************/
+#define LCD_CFG (LCD_BASE + 0x00) /* LCD Configure Register */
+#define LCD_VSYNC (LCD_BASE + 0x04) /* Vertical Synchronize Register */
+#define LCD_HSYNC (LCD_BASE + 0x08) /* Horizontal Synchronize Register */
+#define LCD_VAT (LCD_BASE + 0x0c) /* Virtual Area Setting Register */
+#define LCD_DAH (LCD_BASE + 0x10) /* Display Area Horizontal Start/End Point */
+#define LCD_DAV (LCD_BASE + 0x14) /* Display Area Vertical Start/End Point */
+#define LCD_PS (LCD_BASE + 0x18) /* PS Signal Setting */
+#define LCD_CLS (LCD_BASE + 0x1c) /* CLS Signal Setting */
+#define LCD_SPL (LCD_BASE + 0x20) /* SPL Signal Setting */
+#define LCD_REV (LCD_BASE + 0x24) /* REV Signal Setting */
+#define LCD_CTRL (LCD_BASE + 0x30) /* LCD Control Register */
+#define LCD_STATE (LCD_BASE + 0x34) /* LCD Status Register */
+#define LCD_IID (LCD_BASE + 0x38) /* Interrupt ID Register */
+#define LCD_DA0 (LCD_BASE + 0x40) /* Descriptor Address Register 0 */
+#define LCD_SA0 (LCD_BASE + 0x44) /* Source Address Register 0 */
+#define LCD_FID0 (LCD_BASE + 0x48) /* Frame ID Register 0 */
+#define LCD_CMD0 (LCD_BASE + 0x4c) /* DMA Command Register 0 */
+#define LCD_DA1 (LCD_BASE + 0x50) /* Descriptor Address Register 1 */
+#define LCD_SA1 (LCD_BASE + 0x54) /* Source Address Register 1 */
+#define LCD_FID1 (LCD_BASE + 0x58) /* Frame ID Register 1 */
+#define LCD_CMD1 (LCD_BASE + 0x5c) /* DMA Command Register 1 */
+
+#define REG_LCD_CFG REG32(LCD_CFG)
+#define REG_LCD_VSYNC REG32(LCD_VSYNC)
+#define REG_LCD_HSYNC REG32(LCD_HSYNC)
+#define REG_LCD_VAT REG32(LCD_VAT)
+#define REG_LCD_DAH REG32(LCD_DAH)
+#define REG_LCD_DAV REG32(LCD_DAV)
+#define REG_LCD_PS REG32(LCD_PS)
+#define REG_LCD_CLS REG32(LCD_CLS)
+#define REG_LCD_SPL REG32(LCD_SPL)
+#define REG_LCD_REV REG32(LCD_REV)
+#define REG_LCD_CTRL REG32(LCD_CTRL)
+#define REG_LCD_STATE REG32(LCD_STATE)
+#define REG_LCD_IID REG32(LCD_IID)
+#define REG_LCD_DA0 REG32(LCD_DA0)
+#define REG_LCD_SA0 REG32(LCD_SA0)
+#define REG_LCD_FID0 REG32(LCD_FID0)
+#define REG_LCD_CMD0 REG32(LCD_CMD0)
+#define REG_LCD_DA1 REG32(LCD_DA1)
+#define REG_LCD_SA1 REG32(LCD_SA1)
+#define REG_LCD_FID1 REG32(LCD_FID1)
+#define REG_LCD_CMD1 REG32(LCD_CMD1)
+
+/* LCD Configure Register */
+#define LCD_CFG_LCDPIN_BIT 31 /* LCD pins selection */
+#define LCD_CFG_LCDPIN_MASK (0x1 << LCD_CFG_LCDPIN_BIT)
+ #define LCD_CFG_LCDPIN_LCD (0x0 << LCD_CFG_LCDPIN_BIT)
+ #define LCD_CFG_LCDPIN_SLCD (0x1 << LCD_CFG_LCDPIN_BIT)
+#define LCD_CFG_PSM (1 << 23) /* PS signal mode */
+#define LCD_CFG_CLSM (1 << 22) /* CLS signal mode */
+#define LCD_CFG_SPLM (1 << 21) /* SPL signal mode */
+#define LCD_CFG_REVM (1 << 20) /* REV signal mode */
+#define LCD_CFG_HSYNM (1 << 19) /* HSYNC signal mode */
+#define LCD_CFG_PCLKM (1 << 18) /* PCLK signal mode */
+#define LCD_CFG_INVDAT (1 << 17) /* Inverse output data */
+#define LCD_CFG_SYNDIR_IN (1 << 16) /* VSYNC&HSYNC direction */
+#define LCD_CFG_PSP (1 << 15) /* PS pin reset state */
+#define LCD_CFG_CLSP (1 << 14) /* CLS pin reset state */
+#define LCD_CFG_SPLP (1 << 13) /* SPL pin reset state */
+#define LCD_CFG_REVP (1 << 12) /* REV pin reset state */
+#define LCD_CFG_HSP (1 << 11) /* HSYNC pority:0-active high,1-active low */
+#define LCD_CFG_PCP (1 << 10) /* PCLK pority:0-rising,1-falling */
+#define LCD_CFG_DEP (1 << 9) /* DE pority:0-active high,1-active low */
+#define LCD_CFG_VSP (1 << 8) /* VSYNC pority:0-rising,1-falling */
+#define LCD_CFG_PDW_BIT 4 /* STN pins utilization */
+#define LCD_CFG_PDW_MASK (0x3 << LCD_DEV_PDW_BIT)
+#define LCD_CFG_PDW_1 (0 << LCD_CFG_PDW_BIT) /* LCD_D[0] */
+ #define LCD_CFG_PDW_2 (1 << LCD_CFG_PDW_BIT) /* LCD_D[0:1] */
+ #define LCD_CFG_PDW_4 (2 << LCD_CFG_PDW_BIT) /* LCD_D[0:3]/LCD_D[8:11] */
+ #define LCD_CFG_PDW_8 (3 << LCD_CFG_PDW_BIT) /* LCD_D[0:7]/LCD_D[8:15] */
+#define LCD_CFG_MODE_BIT 0 /* Display Device Mode Select */
+#define LCD_CFG_MODE_MASK (0x0f << LCD_CFG_MODE_BIT)
+ #define LCD_CFG_MODE_GENERIC_TFT (0 << LCD_CFG_MODE_BIT) /* 16,18 bit TFT */
+ #define LCD_CFG_MODE_SPECIAL_TFT_1 (1 << LCD_CFG_MODE_BIT)
+ #define LCD_CFG_MODE_SPECIAL_TFT_2 (2 << LCD_CFG_MODE_BIT)
+ #define LCD_CFG_MODE_SPECIAL_TFT_3 (3 << LCD_CFG_MODE_BIT)
+ #define LCD_CFG_MODE_NONINTER_CCIR656 (4 << LCD_CFG_MODE_BIT)
+ #define LCD_CFG_MODE_INTER_CCIR656 (5 << LCD_CFG_MODE_BIT)
+ #define LCD_CFG_MODE_SINGLE_CSTN (8 << LCD_CFG_MODE_BIT)
+ #define LCD_CFG_MODE_SINGLE_MSTN (9 << LCD_CFG_MODE_BIT)
+ #define LCD_CFG_MODE_DUAL_CSTN (10 << LCD_CFG_MODE_BIT)
+ #define LCD_CFG_MODE_DUAL_MSTN (11 << LCD_CFG_MODE_BIT)
+ #define LCD_CFG_MODE_SERIAL_TFT (12 << LCD_CFG_MODE_BIT)
+ #define LCD_CFG_MODE_GENERIC_18BIT_TFT (13 << LCD_CFG_MODE_BIT)
+ /* JZ47XX defines */
+ #define LCD_CFG_MODE_SHARP_HR (1 << LCD_CFG_MODE_BIT)
+ #define LCD_CFG_MODE_CASIO_TFT (2 << LCD_CFG_MODE_BIT)
+ #define LCD_CFG_MODE_SAMSUNG_ALPHA (3 << LCD_CFG_MODE_BIT)
+
+
+
+/* Vertical Synchronize Register */
+#define LCD_VSYNC_VPS_BIT 16 /* VSYNC pulse start in line clock, fixed to 0 */
+#define LCD_VSYNC_VPS_MASK (0xffff << LCD_VSYNC_VPS_BIT)
+#define LCD_VSYNC_VPE_BIT 0 /* VSYNC pulse end in line clock */
+#define LCD_VSYNC_VPE_MASK (0xffff << LCD_VSYNC_VPS_BIT)
+
+/* Horizontal Synchronize Register */
+#define LCD_HSYNC_HPS_BIT 16 /* HSYNC pulse start position in dot clock */
+#define LCD_HSYNC_HPS_MASK (0xffff << LCD_HSYNC_HPS_BIT)
+#define LCD_HSYNC_HPE_BIT 0 /* HSYNC pulse end position in dot clock */
+#define LCD_HSYNC_HPE_MASK (0xffff << LCD_HSYNC_HPE_BIT)
+
+/* Virtual Area Setting Register */
+#define LCD_VAT_HT_BIT 16 /* Horizontal Total size in dot clock */
+#define LCD_VAT_HT_MASK (0xffff << LCD_VAT_HT_BIT)
+#define LCD_VAT_VT_BIT 0 /* Vertical Total size in dot clock */
+#define LCD_VAT_VT_MASK (0xffff << LCD_VAT_VT_BIT)
+
+/* Display Area Horizontal Start/End Point Register */
+#define LCD_DAH_HDS_BIT 16 /* Horizontal display area start in dot clock */
+#define LCD_DAH_HDS_MASK (0xffff << LCD_DAH_HDS_BIT)
+#define LCD_DAH_HDE_BIT 0 /* Horizontal display area end in dot clock */
+#define LCD_DAH_HDE_MASK (0xffff << LCD_DAH_HDE_BIT)
+
+/* Display Area Vertical Start/End Point Register */
+#define LCD_DAV_VDS_BIT 16 /* Vertical display area start in line clock */
+#define LCD_DAV_VDS_MASK (0xffff << LCD_DAV_VDS_BIT)
+#define LCD_DAV_VDE_BIT 0 /* Vertical display area end in line clock */
+#define LCD_DAV_VDE_MASK (0xffff << LCD_DAV_VDE_BIT)
+
+/* PS Signal Setting */
+#define LCD_PS_PSS_BIT 16 /* PS signal start position in dot clock */
+#define LCD_PS_PSS_MASK (0xffff << LCD_PS_PSS_BIT)
+#define LCD_PS_PSE_BIT 0 /* PS signal end position in dot clock */
+#define LCD_PS_PSE_MASK (0xffff << LCD_PS_PSE_BIT)
+
+/* CLS Signal Setting */
+#define LCD_CLS_CLSS_BIT 16 /* CLS signal start position in dot clock */
+#define LCD_CLS_CLSS_MASK (0xffff << LCD_CLS_CLSS_BIT)
+#define LCD_CLS_CLSE_BIT 0 /* CLS signal end position in dot clock */
+#define LCD_CLS_CLSE_MASK (0xffff << LCD_CLS_CLSE_BIT)
+
+/* SPL Signal Setting */
+#define LCD_SPL_SPLS_BIT 16 /* SPL signal start position in dot clock */
+#define LCD_SPL_SPLS_MASK (0xffff << LCD_SPL_SPLS_BIT)
+#define LCD_SPL_SPLE_BIT 0 /* SPL signal end position in dot clock */
+#define LCD_SPL_SPLE_MASK (0xffff << LCD_SPL_SPLE_BIT)
+
+/* REV Signal Setting */
+#define LCD_REV_REVS_BIT 16 /* REV signal start position in dot clock */
+#define LCD_REV_REVS_MASK (0xffff << LCD_REV_REVS_BIT)
+
+/* LCD Control Register */
+#define LCD_CTRL_BST_BIT 28 /* Burst Length Selection */
+#define LCD_CTRL_BST_MASK (0x03 << LCD_CTRL_BST_BIT)
+ #define LCD_CTRL_BST_4 (0 << LCD_CTRL_BST_BIT) /* 4-word */
+ #define LCD_CTRL_BST_8 (1 << LCD_CTRL_BST_BIT) /* 8-word */
+ #define LCD_CTRL_BST_16 (2 << LCD_CTRL_BST_BIT) /* 16-word */
+#define LCD_CTRL_RGB565 (0 << 27) /* RGB565 mode */
+#define LCD_CTRL_RGB555 (1 << 27) /* RGB555 mode */
+#define LCD_CTRL_OFUP (1 << 26) /* Output FIFO underrun protection enable */
+#define LCD_CTRL_FRC_BIT 24 /* STN FRC Algorithm Selection */
+#define LCD_CTRL_FRC_MASK (0x03 << LCD_CTRL_FRC_BIT)
+ #define LCD_CTRL_FRC_16 (0 << LCD_CTRL_FRC_BIT) /* 16 grayscale */
+ #define LCD_CTRL_FRC_4 (1 << LCD_CTRL_FRC_BIT) /* 4 grayscale */
+ #define LCD_CTRL_FRC_2 (2 << LCD_CTRL_FRC_BIT) /* 2 grayscale */
+#define LCD_CTRL_PDD_BIT 16 /* Load Palette Delay Counter */
+#define LCD_CTRL_PDD_MASK (0xff << LCD_CTRL_PDD_BIT)
+#define LCD_CTRL_EOFM (1 << 13) /* EOF interrupt mask */
+#define LCD_CTRL_SOFM (1 << 12) /* SOF interrupt mask */
+#define LCD_CTRL_OFUM (1 << 11) /* Output FIFO underrun interrupt mask */
+#define LCD_CTRL_IFUM0 (1 << 10) /* Input FIFO 0 underrun interrupt mask */
+#define LCD_CTRL_IFUM1 (1 << 9) /* Input FIFO 1 underrun interrupt mask */
+#define LCD_CTRL_LDDM (1 << 8) /* LCD disable done interrupt mask */
+#define LCD_CTRL_QDM (1 << 7) /* LCD quick disable done interrupt mask */
+#define LCD_CTRL_BEDN (1 << 6) /* Endian selection */
+#define LCD_CTRL_PEDN (1 << 5) /* Endian in byte:0-msb first, 1-lsb first */
+#define LCD_CTRL_DIS (1 << 4) /* Disable indicate bit */
+#define LCD_CTRL_ENA (1 << 3) /* LCD enable bit */
+#define LCD_CTRL_BPP_BIT 0 /* Bits Per Pixel */
+#define LCD_CTRL_BPP_MASK (0x07 << LCD_CTRL_BPP_BIT)
+ #define LCD_CTRL_BPP_1 (0 << LCD_CTRL_BPP_BIT) /* 1 bpp */
+ #define LCD_CTRL_BPP_2 (1 << LCD_CTRL_BPP_BIT) /* 2 bpp */
+ #define LCD_CTRL_BPP_4 (2 << LCD_CTRL_BPP_BIT) /* 4 bpp */
+ #define LCD_CTRL_BPP_8 (3 << LCD_CTRL_BPP_BIT) /* 8 bpp */
+ #define LCD_CTRL_BPP_16 (4 << LCD_CTRL_BPP_BIT) /* 15/16 bpp */
+ #define LCD_CTRL_BPP_18_24 (5 << LCD_CTRL_BPP_BIT) /* 18/24/32 bpp */
+
+/* LCD Status Register */
+#define LCD_STATE_QD (1 << 7) /* Quick Disable Done */
+#define LCD_STATE_EOF (1 << 5) /* EOF Flag */
+#define LCD_STATE_SOF (1 << 4) /* SOF Flag */
+#define LCD_STATE_OFU (1 << 3) /* Output FIFO Underrun */
+#define LCD_STATE_IFU0 (1 << 2) /* Input FIFO 0 Underrun */
+#define LCD_STATE_IFU1 (1 << 1) /* Input FIFO 1 Underrun */
+#define LCD_STATE_LDD (1 << 0) /* LCD Disabled */
+
+/* DMA Command Register */
+#define LCD_CMD_SOFINT (1 << 31)
+#define LCD_CMD_EOFINT (1 << 30)
+#define LCD_CMD_PAL (1 << 28)
+#define LCD_CMD_LEN_BIT 0
+#define LCD_CMD_LEN_MASK (0xffffff << LCD_CMD_LEN_BIT)
+
+
+/*************************************************************************
+ * USB Device
+ *************************************************************************/
+#define USB_BASE UDC_BASE
+
+#define USB_REG_FADDR (USB_BASE + 0x00) /* Function Address 8-bit */
+#define USB_REG_POWER (USB_BASE + 0x01) /* Power Managemetn 8-bit */
+#define USB_REG_INTRIN (USB_BASE + 0x02) /* Interrupt IN 16-bit */
+#define USB_REG_INTROUT (USB_BASE + 0x04) /* Interrupt OUT 16-bit */
+#define USB_REG_INTRINE (USB_BASE + 0x06) /* Intr IN enable 16-bit */
+#define USB_REG_INTROUTE (USB_BASE + 0x08) /* Intr OUT enable 16-bit */
+#define USB_REG_INTRUSB (USB_BASE + 0x0a) /* Interrupt USB 8-bit */
+#define USB_REG_INTRUSBE (USB_BASE + 0x0b) /* Interrupt USB Enable 8-bit */
+#define USB_REG_FRAME (USB_BASE + 0x0c) /* Frame number 16-bit */
+#define USB_REG_INDEX (USB_BASE + 0x0e) /* Index register 8-bit */
+#define USB_REG_TESTMODE (USB_BASE + 0x0f) /* USB test mode 8-bit */
+
+#define USB_REG_CSR0 (USB_BASE + 0x12) /* EP0 CSR 8-bit */
+#define USB_REG_INMAXP (USB_BASE + 0x10) /* EP1-2 IN Max Pkt Size 16-bit */
+#define USB_REG_INCSR (USB_BASE + 0x12) /* EP1-2 IN CSR LSB 8/16bit */
+#define USB_REG_INCSRH (USB_BASE + 0x13) /* EP1-2 IN CSR MSB 8-bit */
+#define USB_REG_OUTMAXP (USB_BASE + 0x14) /* EP1 OUT Max Pkt Size 16-bit */
+#define USB_REG_OUTCSR (USB_BASE + 0x16) /* EP1 OUT CSR LSB 8/16bit */
+#define USB_REG_OUTCSRH (USB_BASE + 0x17) /* EP1 OUT CSR MSB 8-bit */
+#define USB_REG_OUTCOUNT (USB_BASE + 0x18) /* bytes in EP0/1 OUT FIFO 16-bit */
+
+#define USB_FIFO_EP0 (USB_BASE + 0x20)
+#define USB_FIFO_EP1 (USB_BASE + 0x24)
+#define USB_FIFO_EP2 (USB_BASE + 0x28)
+
+#define USB_REG_EPINFO (USB_BASE + 0x78) /* Endpoint information */
+#define USB_REG_RAMINFO (USB_BASE + 0x79) /* RAM information */
+
+#define USB_REG_INTR (USB_BASE + 0x200) /* DMA pending interrupts */
+#define USB_REG_CNTL1 (USB_BASE + 0x204) /* DMA channel 1 control */
+#define USB_REG_ADDR1 (USB_BASE + 0x208) /* DMA channel 1 AHB memory addr */
+#define USB_REG_COUNT1 (USB_BASE + 0x20c) /* DMA channel 1 byte count */
+#define USB_REG_CNTL2 (USB_BASE + 0x214) /* DMA channel 2 control */
+#define USB_REG_ADDR2 (USB_BASE + 0x218) /* DMA channel 2 AHB memory addr */
+#define USB_REG_COUNT2 (USB_BASE + 0x21c) /* DMA channel 2 byte count */
+
+
+/* Power register bit masks */
+#define USB_POWER_SUSPENDM 0x01
+#define USB_POWER_RESUME 0x04
+#define USB_POWER_HSMODE 0x10
+#define USB_POWER_HSENAB 0x20
+#define USB_POWER_SOFTCONN 0x40
+
+/* Interrupt register bit masks */
+#define USB_INTR_SUSPEND 0x01
+#define USB_INTR_RESUME 0x02
+#define USB_INTR_RESET 0x04
+
+#define USB_INTR_EP0 0x0001
+#define USB_INTR_INEP1 0x0002
+#define USB_INTR_INEP2 0x0004
+#define USB_INTR_OUTEP1 0x0002
+
+/* CSR0 bit masks */
+#define USB_CSR0_OUTPKTRDY 0x01
+#define USB_CSR0_INPKTRDY 0x02
+#define USB_CSR0_SENTSTALL 0x04
+#define USB_CSR0_DATAEND 0x08
+#define USB_CSR0_SETUPEND 0x10
+#define USB_CSR0_SENDSTALL 0x20
+#define USB_CSR0_SVDOUTPKTRDY 0x40
+#define USB_CSR0_SVDSETUPEND 0x80
+
+/* Endpoint CSR register bits */
+#define USB_INCSRH_AUTOSET 0x80
+#define USB_INCSRH_ISO 0x40
+#define USB_INCSRH_MODE 0x20
+#define USB_INCSRH_DMAREQENAB 0x10
+#define USB_INCSRH_DMAREQMODE 0x04
+#define USB_INCSR_CDT 0x40
+#define USB_INCSR_SENTSTALL 0x20
+#define USB_INCSR_SENDSTALL 0x10
+#define USB_INCSR_FF 0x08
+#define USB_INCSR_UNDERRUN 0x04
+#define USB_INCSR_FFNOTEMPT 0x02
+#define USB_INCSR_INPKTRDY 0x01
+#define USB_OUTCSRH_AUTOCLR 0x80
+#define USB_OUTCSRH_ISO 0x40
+#define USB_OUTCSRH_DMAREQENAB 0x20
+#define USB_OUTCSRH_DNYT 0x10
+#define USB_OUTCSRH_DMAREQMODE 0x08
+#define USB_OUTCSR_CDT 0x80
+#define USB_OUTCSR_SENTSTALL 0x40
+#define USB_OUTCSR_SENDSTALL 0x20
+#define USB_OUTCSR_FF 0x10
+#define USB_OUTCSR_DATAERR 0x08
+#define USB_OUTCSR_OVERRUN 0x04
+#define USB_OUTCSR_FFFULL 0x02
+#define USB_OUTCSR_OUTPKTRDY 0x01
+
+/* Testmode register bits */
+#define USB_TEST_SE0NAK 0x01
+#define USB_TEST_J 0x02
+#define USB_TEST_K 0x04
+#define USB_TEST_PACKET 0x08
+
+/* DMA control bits */
+#define USB_CNTL_ENA 0x01
+#define USB_CNTL_DIR_IN 0x02
+#define USB_CNTL_MODE_1 0x04
+#define USB_CNTL_INTR_EN 0x08
+#define USB_CNTL_EP(n) ((n) << 4)
+#define USB_CNTL_BURST_0 (0 << 9)
+#define USB_CNTL_BURST_4 (1 << 9)
+#define USB_CNTL_BURST_8 (2 << 9)
+#define USB_CNTL_BURST_16 (3 << 9)
+
+
+
+/* Module Operation Definitions */
+#ifndef __ASSEMBLY__
+
+
+/* GPIO Pins Description */
+/* PORT 0: */
+/* PIN/BIT N FUNC0 FUNC1 */
+/* 0 D0 - */
+/* 1 D1 - */
+/* 2 D2 - */
+/* 3 D3 - */
+/* 4 D4 - */
+/* 5 D5 - */
+/* 6 D6 - */
+/* 7 D7 - */
+/* 8 D8 - */
+/* 9 D9 - */
+/* 10 D10 - */
+/* 11 D11 - */
+/* 12 D12 - */
+/* 13 D13 - */
+/* 14 D14 - */
+/* 15 D15 - */
+/* 16 D16 - */
+/* 17 D17 - */
+/* 18 D18 - */
+/* 19 D19 - */
+/* 20 D20 - */
+/* 21 D21 - */
+/* 22 D22 - */
+/* 23 D23 - */
+/* 24 D24 - */
+/* 25 D25 - */
+/* 26 D26 - */
+/* 27 D27 - */
+/* 28 D28 - */
+/* 29 D29 - */
+/* 30 D30 - */
+/* 31 D31 - */
+/*------------------------------------------------------ */
+/* PORT 1: */
+/* */
+/* PIN/BIT N FUNC0 FUNC1 */
+/* 0 A0 - */
+/* 1 A1 - */
+/* 2 A2 - */
+/* 3 A3 - */
+/* 4 A4 - */
+/* 5 A5 - */
+/* 6 A6 - */
+/* 7 A7 - */
+/* 8 A8 - */
+/* 9 A9 - */
+/* 10 A10 - */
+/* 11 A11 - */
+/* 12 A12 - */
+/* 13 A13 - */
+/* 14 A14 - */
+/* 15 A15/CL - */
+/* 16 A16/AL - */
+/* 17 LCD_CLS A21 */
+/* 18 LCD_SPL A22 */
+/* 19 DCS# - */
+/* 20 RAS# - */
+/* 21 CAS# - */
+/* 22 RDWE#/BUFD# - */
+/* 23 CKE - */
+/* 24 CKO - */
+/* 25 CS1# - */
+/* 26 CS2# - */
+/* 27 CS3# - */
+/* 28 CS4# - */
+/* 29 RD# - */
+/* 30 WR# - */
+/* 31 WE0# - */
+/* Note: PIN15&16 are CL&AL when connecting to NAND flash. */
+/*------------------------------------------------------ */
+/* PORT 2: */
+/* */
+/* PIN/BIT N FUNC0 FUNC1 */
+/* 0 LCD_D0 - */
+/* 1 LCD_D1 - */
+/* 2 LCD_D2 - */
+/* 3 LCD_D3 - */
+/* 4 LCD_D4 - */
+/* 5 LCD_D5 - */
+/* 6 LCD_D6 - */
+/* 7 LCD_D7 - */
+/* 8 LCD_D8 - */
+/* 9 LCD_D9 - */
+/* 10 LCD_D10 - */
+/* 11 LCD_D11 - */
+/* 12 LCD_D12 - */
+/* 13 LCD_D13 - */
+/* 14 LCD_D14 - */
+/* 15 LCD_D15 - */
+/* 16 LCD_D16 - */
+/* 17 LCD_D17 - */
+/* 18 LCD_PCLK - */
+/* 19 LCD_HSYNC - */
+/* 20 LCD_VSYNC - */
+/* 21 LCD_DE - */
+/* 22 LCD_PS A19 */
+/* 23 LCD_REV A20 */
+/* 24 WE1# - */
+/* 25 WE2# - */
+/* 26 WE3# - */
+/* 27 WAIT# - */
+/* 28 FRE# - */
+/* 29 FWE# - */
+/* 30(NOTE:FRB#) - - */
+/* 31 - - */
+/* NOTE(1): PIN30 is used for FRB# when connecting to NAND flash. */
+/*------------------------------------------------------ */
+/* PORT 3: */
+/* */
+/* PIN/BIT N FUNC0 FUNC1 */
+/* 0 CIM_D0 - */
+/* 1 CIM_D1 - */
+/* 2 CIM_D2 - */
+/* 3 CIM_D3 - */
+/* 4 CIM_D4 - */
+/* 5 CIM_D5 - */
+/* 6 CIM_D6 - */
+/* 7 CIM_D7 - */
+/* 8 MSC_CMD - */
+/* 9 MSC_CLK - */
+/* 10 MSC_D0 - */
+/* 11 MSC_D1 - */
+/* 12 MSC_D2 - */
+/* 13 MSC_D3 - */
+/* 14 CIM_MCLK - */
+/* 15 CIM_PCLK - */
+/* 16 CIM_VSYNC - */
+/* 17 CIM_HSYNC - */
+/* 18 SSI_CLK SCLK_RSTN */
+/* 19 SSI_CE0# BIT_CLK(AIC) */
+/* 20 SSI_DT SDATA_OUT(AIC) */
+/* 21 SSI_DR SDATA_IN(AIC) */
+/* 22 SSI_CE1#&GPC SYNC(AIC) */
+/* 23 PWM0 I2C_SDA */
+/* 24 PWM1 I2C_SCK */
+/* 25 PWM2 UART0_TxD */
+/* 26 PWM3 UART0_RxD */
+/* 27 PWM4 A17 */
+/* 28 PWM5 A18 */
+/* 29 - - */
+/* 30 PWM6 UART0_CTS/UART1_RxD */
+/* 31 PWM7 UART0_RTS/UART1_TxD */
+/*
+ * p is the port number (0,1,2,3)
+ * o is the pin offset (0-31) inside the port
+ * n is the absolute number of a pin (0-127), regardless of the port
+ */
+
+/* Function Pins Mode */
+
+#define __gpio_as_func0(n) \
+do { \
+ unsigned int p, o; \
+ p = (n) / 32; \
+ o = (n) % 32; \
+ REG_GPIO_PXFUNS(p) = (1 << o); \
+ REG_GPIO_PXSELC(p) = (1 << o); \
+} while (0)
+
+#define __gpio_as_func1(n) \
+do { \
+ unsigned int p, o; \
+ p = (n) / 32; \
+ o = (n) % 32; \
+ REG_GPIO_PXFUNS(p) = (1 << o); \
+ REG_GPIO_PXSELS(p) = (1 << o); \
+} while (0)
+
+/*
+ * D0 ~ D31, A0 ~ A16, DCS#, RAS#, CAS#, CKE#,
+ * RDWE#, CKO#, WE0#, WE1#, WE2#, WE3#
+ */
+#define __gpio_as_sdram_32bit() \
+do { \
+ REG_GPIO_PXFUNS(0) = 0xffffffff; \
+ REG_GPIO_PXSELC(0) = 0xffffffff; \
+ REG_GPIO_PXPES(0) = 0xffffffff; \
+ REG_GPIO_PXFUNS(1) = 0x81f9ffff; \
+ REG_GPIO_PXSELC(1) = 0x81f9ffff; \
+ REG_GPIO_PXPES(1) = 0x81f9ffff; \
+ REG_GPIO_PXFUNS(2) = 0x07000000; \
+ REG_GPIO_PXSELC(2) = 0x07000000; \
+ REG_GPIO_PXPES(2) = 0x07000000; \
+} while (0)
+
+/*
+ * D0 ~ D15, A0 ~ A16, DCS#, RAS#, CAS#, CKE#,
+ * RDWE#, CKO#, WE0#, WE1#
+ */
+#define __gpio_as_sdram_16bit_4720() \
+do { \
+ REG_GPIO_PXFUNS(0) = 0x5442bfaa; \
+ REG_GPIO_PXSELC(0) = 0x5442bfaa; \
+ REG_GPIO_PXPES(0) = 0x5442bfaa; \
+ REG_GPIO_PXFUNS(1) = 0x81f9ffff; \
+ REG_GPIO_PXSELC(1) = 0x81f9ffff; \
+ REG_GPIO_PXPES(1) = 0x81f9ffff; \
+ REG_GPIO_PXFUNS(2) = 0x01000000; \
+ REG_GPIO_PXSELC(2) = 0x01000000; \
+ REG_GPIO_PXPES(2) = 0x01000000; \
+} while (0)
+
+/*
+ * D0 ~ D15, A0 ~ A16, DCS#, RAS#, CAS#, CKE#,
+ * RDWE#, CKO#, WE0#, WE1#
+ */
+#define __gpio_as_sdram_16bit_4725() \
+do { \
+ REG_GPIO_PXFUNS(0) = 0x0000ffff; \
+ REG_GPIO_PXSELC(0) = 0x0000ffff; \
+ REG_GPIO_PXPES(0) = 0x0000ffff; \
+ REG_GPIO_PXFUNS(1) = 0x81f9ffff; \
+ REG_GPIO_PXSELC(1) = 0x81f9ffff; \
+ REG_GPIO_PXPES(1) = 0x81f9ffff; \
+ REG_GPIO_PXFUNS(2) = 0x01000000; \
+ REG_GPIO_PXSELC(2) = 0x01000000; \
+ REG_GPIO_PXPES(2) = 0x01000000; \
+} while (0)
+
+
+/*
+ * CS1#, CLE, ALE, FRE#, FWE#, FRB#, RDWE#/BUFD#
+ */
+#define __gpio_as_nand() \
+do { \
+ REG_GPIO_PXFUNS(1) = 0x02018000; \
+ REG_GPIO_PXSELC(1) = 0x02018000; \
+ REG_GPIO_PXPES(1) = 0x02018000; \
+ REG_GPIO_PXFUNS(2) = 0x30000000; \
+ REG_GPIO_PXSELC(2) = 0x30000000; \
+ REG_GPIO_PXPES(2) = 0x30000000; \
+ REG_GPIO_PXFUNC(2) = 0x40000000; \
+ REG_GPIO_PXSELC(2) = 0x40000000; \
+ REG_GPIO_PXDIRC(2) = 0x40000000; \
+ REG_GPIO_PXPES(2) = 0x40000000; \
+ REG_GPIO_PXFUNS(1) = 0x00400000; \
+ REG_GPIO_PXSELC(1) = 0x00400000; \
+} while (0)
+
+/*
+ * CS4#, RD#, WR#, WAIT#, A0 ~ A22, D0 ~ D7
+ */
+#define __gpio_as_nor_8bit() \
+do { \
+ REG_GPIO_PXFUNS(0) = 0x000000ff; \
+ REG_GPIO_PXSELC(0) = 0x000000ff; \
+ REG_GPIO_PXPES(0) = 0x000000ff; \
+ REG_GPIO_PXFUNS(1) = 0x7041ffff; \
+ REG_GPIO_PXSELC(1) = 0x7041ffff; \
+ REG_GPIO_PXPES(1) = 0x7041ffff; \
+ REG_GPIO_PXFUNS(1) = 0x00060000; \
+ REG_GPIO_PXSELS(1) = 0x00060000; \
+ REG_GPIO_PXPES(1) = 0x00060000; \
+ REG_GPIO_PXFUNS(2) = 0x08000000; \
+ REG_GPIO_PXSELC(2) = 0x08000000; \
+ REG_GPIO_PXPES(2) = 0x08000000; \
+ REG_GPIO_PXFUNS(2) = 0x00c00000; \
+ REG_GPIO_PXSELS(2) = 0x00c00000; \
+ REG_GPIO_PXPES(2) = 0x00c00000; \
+ REG_GPIO_PXFUNS(3) = 0x18000000; \
+ REG_GPIO_PXSELS(3) = 0x18000000; \
+ REG_GPIO_PXPES(3) = 0x18000000; \
+} while (0)
+
+/*
+ * CS4#, RD#, WR#, WAIT#, A0 ~ A22, D0 ~ D15
+ */
+#define __gpio_as_nor_16bit() \
+do { \
+ REG_GPIO_PXFUNS(0) = 0x0000ffff; \
+ REG_GPIO_PXSELC(0) = 0x0000ffff; \
+ REG_GPIO_PXPES(0) = 0x0000ffff; \
+ REG_GPIO_PXFUNS(1) = 0x7041ffff; \
+ REG_GPIO_PXSELC(1) = 0x7041ffff; \
+ REG_GPIO_PXPES(1) = 0x7041ffff; \
+ REG_GPIO_PXFUNS(1) = 0x00060000; \
+ REG_GPIO_PXSELS(1) = 0x00060000; \
+ REG_GPIO_PXPES(1) = 0x00060000; \
+ REG_GPIO_PXFUNS(2) = 0x08000000; \
+ REG_GPIO_PXSELC(2) = 0x08000000; \
+ REG_GPIO_PXPES(2) = 0x08000000; \
+ REG_GPIO_PXFUNS(2) = 0x00c00000; \
+ REG_GPIO_PXSELS(2) = 0x00c00000; \
+ REG_GPIO_PXPES(2) = 0x00c00000; \
+ REG_GPIO_PXFUNS(3) = 0x18000000; \
+ REG_GPIO_PXSELS(3) = 0x18000000; \
+ REG_GPIO_PXPES(3) = 0x18000000; \
+} while (0)
+
+/*
+ * UART0_TxD, UART_RxD0
+ */
+#define __gpio_as_uart0() \
+do { \
+ REG_GPIO_PXFUNS(3) = 0x06000000; \
+ REG_GPIO_PXSELS(3) = 0x06000000; \
+ REG_GPIO_PXPES(3) = 0x06000000; \
+} while (0)
+
+#define __gpio_jtag_to_uart0() \
+do { \
+ REG_GPIO_PXSELS(2) = 0x80000000; \
+} while (0)
+
+/*
+ * UART0_CTS, UART0_RTS
+ */
+#define __gpio_as_ctsrts() \
+do { \
+ REG_GPIO_PXFUNS(3) = 0xc0000000; \
+ REG_GPIO_PXSELS(3) = 0xc0000000; \
+ REG_GPIO_PXTRGC(3) = 0xc0000000; \
+ REG_GPIO_PXPES(3) = 0xc0000000; \
+} while (0)
+
+/*
+ * UART1_TxD, UART1_RxD1
+ */
+#define __gpio_as_uart1() \
+do { \
+ REG_GPIO_PXFUNS(3) = 0xc0000000; \
+ REG_GPIO_PXSELC(3) = 0xc0000000; \
+ REG_GPIO_PXTRGS(3) = 0xc0000000; \
+ REG_GPIO_PXPES(3) = 0xc0000000; \
+} while (0)
+
+/*
+ * LCD_D0~LCD_D7, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE
+ */
+#define __gpio_as_lcd_8bit() \
+do { \
+ REG_GPIO_PXFUNS(2) = 0x003c00ff; \
+ REG_GPIO_PXSELC(2) = 0x003c00ff; \
+ REG_GPIO_PXPES(2) = 0x003c00ff; \
+} while (0)
+
+/*
+ * LCD_D0~LCD_D15, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE
+ */
+#define __gpio_as_lcd_16bit() \
+do { \
+ REG_GPIO_PXFUNS(2) = 0x003cffff; \
+ REG_GPIO_PXSELC(2) = 0x003cffff; \
+ REG_GPIO_PXPES(2) = 0x003cffff; \
+} while (0)
+
+/*
+ * LCD_D0~LCD_D17, LCD_PCLK, LCD_HSYNC, LCD_VSYNC, LCD_DE
+ */
+#define __gpio_as_lcd_18bit() \
+do { \
+ REG_GPIO_PXFUNS(2) = 0x003fffff; \
+ REG_GPIO_PXSELC(2) = 0x003fffff; \
+ REG_GPIO_PXPES(2) = 0x003fffff; \
+} while (0)
+
+
+/* LCD_D0~LCD_D7, SLCD_RS, SLCD_CS */
+#define __gpio_as_slcd_8bit() \
+do { \
+ REG_GPIO_PXFUNS(2) = 0x001800ff; \
+ REG_GPIO_PXSELC(2) = 0x001800ff; \
+} while (0)
+
+/* LCD_D0~LCD_D7, SLCD_RS, SLCD_CS */
+#define __gpio_as_slcd_9bit() \
+do { \
+ REG_GPIO_PXFUNS(2) = 0x001801ff; \
+ REG_GPIO_PXSELC(2) = 0x001801ff; \
+} while (0)
+
+/* LCD_D0~LCD_D15, SLCD_RS, SLCD_CS */
+#define __gpio_as_slcd_16bit() \
+do { \
+ REG_GPIO_PXFUNS(2) = 0x0018ffff; \
+ REG_GPIO_PXSELC(2) = 0x0018ffff; \
+} while (0)
+
+/* LCD_D0~LCD_D17, SLCD_RS, SLCD_CS */
+#define __gpio_as_slcd_18bit() \
+do { \
+ REG_GPIO_PXFUNS(2) = 0x001bffff; \
+ REG_GPIO_PXSELC(2) = 0x001bffff; \
+} while (0)
+/*
+ * CIM_D0~CIM_D7, CIM_MCLK, CIM_PCLK, CIM_VSYNC, CIM_HSYNC
+ */
+#define __gpio_as_cim() \
+do { \
+ REG_GPIO_PXFUNS(3) = 0x0003c0ff; \
+ REG_GPIO_PXSELC(3) = 0x0003c0ff; \
+ REG_GPIO_PXPES(3) = 0x0003c0ff; \
+} while (0)
+
+/*
+ * SDATA_OUT, SDATA_IN, BIT_CLK, SYNC, SCLK_RESET
+ */
+#define __gpio_as_aic() \
+do { \
+ REG_GPIO_PXFUNS(3) = 0x007c0000; \
+ REG_GPIO_PXSELS(3) = 0x007c0000; \
+ REG_GPIO_PXPES(3) = 0x007c0000; \
+} while (0)
+
+/*
+ * MSC_CMD, MSC_CLK, MSC_D0 ~ MSC_D3
+ */
+#define __gpio_as_msc() \
+do { \
+ REG_GPIO_PXFUNS(3) = 0x00003f00; \
+ REG_GPIO_PXSELC(3) = 0x00003f00; \
+ REG_GPIO_PXPES(3) = 0x00003f00; \
+} while (0)
+
+/*
+ * SSI_CS0, SSI_CLK, SSI_DT, SSI_DR
+ */
+#define __gpio_as_ssi() \
+do { \
+ REG_GPIO_PXFUNS(3) = 0x003c0000; \
+ REG_GPIO_PXSELC(3) = 0x003c0000; \
+ REG_GPIO_PXPES(3) = 0x003c0000; \
+} while (0)
+
+/*
+ * I2C_SCK, I2C_SDA
+ */
+#define __gpio_as_i2c() \
+do { \
+ REG_GPIO_PXFUNS(3) = 0x01800000; \
+ REG_GPIO_PXSELS(3) = 0x01800000; \
+ REG_GPIO_PXPES(3) = 0x01800000; \
+} while (0)
+
+/*
+ * PWM0
+ */
+#define __gpio_as_pwm0() \
+do { \
+ REG_GPIO_PXFUNS(3) = 0x00800000; \
+ REG_GPIO_PXSELC(3) = 0x00800000; \
+ REG_GPIO_PXPES(3) = 0x00800000; \
+} while (0)
+
+/*
+ * PWM1
+ */
+#define __gpio_as_pwm1() \
+do { \
+ REG_GPIO_PXFUNS(3) = 0x01000000; \
+ REG_GPIO_PXSELC(3) = 0x01000000; \
+ REG_GPIO_PXPES(3) = 0x01000000; \
+} while (0)
+
+/*
+ * PWM2
+ */
+#define __gpio_as_pwm2() \
+do { \
+ REG_GPIO_PXFUNS(3) = 0x02000000; \
+ REG_GPIO_PXSELC(3) = 0x02000000; \
+ REG_GPIO_PXPES(3) = 0x02000000; \
+} while (0)
+
+/*
+ * PWM3
+ */
+#define __gpio_as_pwm3() \
+do { \
+ REG_GPIO_PXFUNS(3) = 0x04000000; \
+ REG_GPIO_PXSELC(3) = 0x04000000; \
+ REG_GPIO_PXPES(3) = 0x04000000; \
+} while (0)
+
+/*
+ * PWM4
+ */
+#define __gpio_as_pwm4() \
+do { \
+ REG_GPIO_PXFUNS(3) = 0x08000000; \
+ REG_GPIO_PXSELC(3) = 0x08000000; \
+ REG_GPIO_PXPES(3) = 0x08000000; \
+} while (0)
+
+/*
+ * PWM5
+ */
+#define __gpio_as_pwm5() \
+do { \
+ REG_GPIO_PXFUNS(3) = 0x10000000; \
+ REG_GPIO_PXSELC(3) = 0x10000000; \
+ REG_GPIO_PXPES(3) = 0x10000000; \
+} while (0)
+
+/*
+ * PWM6
+ */
+#define __gpio_as_pwm6() \
+do { \
+ REG_GPIO_PXFUNS(3) = 0x40000000; \
+ REG_GPIO_PXSELC(3) = 0x40000000; \
+ REG_GPIO_PXPES(3) = 0x40000000; \
+} while (0)
+
+/*
+ * PWM7
+ */
+#define __gpio_as_pwm7() \
+do { \
+ REG_GPIO_PXFUNS(3) = 0x80000000; \
+ REG_GPIO_PXSELC(3) = 0x80000000; \
+ REG_GPIO_PXPES(3) = 0x80000000; \
+} while (0)
+
+/*
+ * n = 0 ~ 7
+ */
+#define __gpio_as_pwm(n) __gpio_as_pwm##n()
+
+/* GPIO or Interrupt Mode */
+
+#define __gpio_get_port(p) (REG_GPIO_PXPIN(p))
+
+#define __gpio_port_as_output(p, o) \
+do { \
+ REG_GPIO_PXFUNC(p) = (1 << (o)); \
+ REG_GPIO_PXSELC(p) = (1 << (o)); \
+ REG_GPIO_PXDIRS(p) = (1 << (o)); \
+} while (0)
+
+#define __gpio_port_as_input(p, o) \
+do { \
+ REG_GPIO_PXFUNC(p) = (1 << (o)); \
+ REG_GPIO_PXSELC(p) = (1 << (o)); \
+ REG_GPIO_PXDIRC(p) = (1 << (o)); \
+} while (0)
+
+#define __gpio_as_output(n) \
+do { \
+ unsigned int p, o; \
+ p = (n) / 32; \
+ o = (n) % 32; \
+ __gpio_port_as_output(p, o); \
+} while (0)
+
+#define __gpio_as_input(n) \
+do { \
+ unsigned int p, o; \
+ p = (n) / 32; \
+ o = (n) % 32; \
+ __gpio_port_as_input(p, o); \
+} while (0)
+
+#define __gpio_set_pin(n) \
+do { \
+ unsigned int p, o; \
+ p = (n) / 32; \
+ o = (n) % 32; \
+ REG_GPIO_PXDATS(p) = (1 << o); \
+} while (0)
+
+#define __gpio_clear_pin(n) \
+do { \
+ unsigned int p, o; \
+ p = (n) / 32; \
+ o = (n) % 32; \
+ REG_GPIO_PXDATC(p) = (1 << o); \
+} while (0)
+
+#define __gpio_get_pin(n) \
+({ \
+ unsigned int p, o, v; \
+ p = (n) / 32; \
+ o = (n) % 32; \
+ if (__gpio_get_port(p) & (1 << o)) \
+ v = 1; \
+ else \
+ v = 0; \
+ v; \
+})
+
+#define __gpio_as_irq_high_level(n) \
+do { \
+ unsigned int p, o; \
+ p = (n) / 32; \
+ o = (n) % 32; \
+ REG_GPIO_PXIMS(p) = (1 << o); \
+ REG_GPIO_PXTRGC(p) = (1 << o); \
+ REG_GPIO_PXFUNC(p) = (1 << o); \
+ REG_GPIO_PXSELS(p) = (1 << o); \
+ REG_GPIO_PXDIRS(p) = (1 << o); \
+ REG_GPIO_PXFLGC(p) = (1 << o); \
+ REG_GPIO_PXIMC(p) = (1 << o); \
+} while (0)
+
+#define __gpio_as_irq_low_level(n) \
+do { \
+ unsigned int p, o; \
+ p = (n) / 32; \
+ o = (n) % 32; \
+ REG_GPIO_PXIMS(p) = (1 << o); \
+ REG_GPIO_PXTRGC(p) = (1 << o); \
+ REG_GPIO_PXFUNC(p) = (1 << o); \
+ REG_GPIO_PXSELS(p) = (1 << o); \
+ REG_GPIO_PXDIRC(p) = (1 << o); \
+ REG_GPIO_PXFLGC(p) = (1 << o); \
+ REG_GPIO_PXIMC(p) = (1 << o); \
+} while (0)
+
+#define __gpio_as_irq_rise_edge(n) \
+do { \
+ unsigned int p, o; \
+ p = (n) / 32; \
+ o = (n) % 32; \
+ REG_GPIO_PXIMS(p) = (1 << o); \
+ REG_GPIO_PXTRGS(p) = (1 << o); \
+ REG_GPIO_PXFUNC(p) = (1 << o); \
+ REG_GPIO_PXSELS(p) = (1 << o); \
+ REG_GPIO_PXDIRS(p) = (1 << o); \
+ REG_GPIO_PXFLGC(p) = (1 << o); \
+ REG_GPIO_PXIMC(p) = (1 << o); \
+} while (0)
+
+#define __gpio_as_irq_fall_edge(n) \
+do { \
+ unsigned int p, o; \
+ p = (n) / 32; \
+ o = (n) % 32; \
+ REG_GPIO_PXIMS(p) = (1 << o); \
+ REG_GPIO_PXTRGS(p) = (1 << o); \
+ REG_GPIO_PXFUNC(p) = (1 << o); \
+ REG_GPIO_PXSELS(p) = (1 << o); \
+ REG_GPIO_PXDIRC(p) = (1 << o); \
+ REG_GPIO_PXFLGC(p) = (1 << o); \
+ REG_GPIO_PXIMC(p) = (1 << o); \
+} while (0)
+
+#define __gpio_mask_irq(n) \
+do { \
+ unsigned int p, o; \
+ p = (n) / 32; \
+ o = (n) % 32; \
+ REG_GPIO_PXIMS(p) = (1 << o); \
+} while (0)
+
+#define __gpio_unmask_irq(n) \
+do { \
+ unsigned int p, o; \
+ p = (n) / 32; \
+ o = (n) % 32; \
+ REG_GPIO_PXIMC(p) = (1 << o); \
+} while (0)
+
+#define __gpio_ack_irq(n) \
+do { \
+ unsigned int p, o; \
+ p = (n) / 32; \
+ o = (n) % 32; \
+ REG_GPIO_PXFLGC(p) = (1 << o); \
+} while (0)
+
+#define __gpio_get_irq() \
+({ \
+ unsigned int p, i, tmp, v = 0; \
+ for (p = 3; p >= 0; p--) { \
+ tmp = REG_GPIO_PXFLG(p); \
+ for (i = 0; i < 32; i++) \
+ if (tmp & (1 << i)) \
+ v = (32*p + i); \
+ } \
+ v; \
+})
+
+#define __gpio_group_irq(n) \
+({ \
+ register int tmp, i; \
+ tmp = REG_GPIO_PXFLG((n)); \
+ for (i=31;i>=0;i--) \
+ if (tmp & (1 << i)) \
+ break; \
+ i; \
+})
+
+#define __gpio_enable_pull(n) \
+do { \
+ unsigned int p, o; \
+ p = (n) / 32; \
+ o = (n) % 32; \
+ REG_GPIO_PXPEC(p) = (1 << o); \
+} while (0)
+
+#define __gpio_disable_pull(n) \
+do { \
+ unsigned int p, o; \
+ p = (n) / 32; \
+ o = (n) % 32; \
+ REG_GPIO_PXPES(p) = (1 << o); \
+} while (0)
+
+
+/***************************************************************************
+ * CPM
+ ***************************************************************************/
+#define __cpm_get_pllm() \
+ ((REG_CPM_CPPCR & CPM_CPPCR_PLLM_MASK) >> CPM_CPPCR_PLLM_BIT)
+#define __cpm_get_plln() \
+ ((REG_CPM_CPPCR & CPM_CPPCR_PLLN_MASK) >> CPM_CPPCR_PLLN_BIT)
+#define __cpm_get_pllod() \
+ ((REG_CPM_CPPCR & CPM_CPPCR_PLLOD_MASK) >> CPM_CPPCR_PLLOD_BIT)
+
+#define __cpm_get_cdiv() \
+ ((REG_CPM_CPCCR & CPM_CPCCR_CDIV_MASK) >> CPM_CPCCR_CDIV_BIT)
+#define __cpm_get_hdiv() \
+ ((REG_CPM_CPCCR & CPM_CPCCR_HDIV_MASK) >> CPM_CPCCR_HDIV_BIT)
+#define __cpm_get_pdiv() \
+ ((REG_CPM_CPCCR & CPM_CPCCR_PDIV_MASK) >> CPM_CPCCR_PDIV_BIT)
+#define __cpm_get_mdiv() \
+ ((REG_CPM_CPCCR & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT)
+#define __cpm_get_ldiv() \
+ ((REG_CPM_CPCCR & CPM_CPCCR_LDIV_MASK) >> CPM_CPCCR_LDIV_BIT)
+#define __cpm_get_udiv() \
+ ((REG_CPM_CPCCR & CPM_CPCCR_UDIV_MASK) >> CPM_CPCCR_UDIV_BIT)
+#define __cpm_get_i2sdiv() \
+ ((REG_CPM_I2SCDR & CPM_I2SCDR_I2SDIV_MASK) >> CPM_I2SCDR_I2SDIV_BIT)
+#define __cpm_get_pixdiv() \
+ ((REG_CPM_LPCDR & CPM_LPCDR_PIXDIV_MASK) >> CPM_LPCDR_PIXDIV_BIT)
+#define __cpm_get_mscdiv() \
+ ((REG_CPM_MSCCDR & CPM_MSCCDR_MSCDIV_MASK) >> CPM_MSCCDR_MSCDIV_BIT)
+
+#define __cpm_set_cdiv(v) \
+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_CDIV_MASK) | ((v) << (CPM_CPCCR_CDIV_BIT)))
+#define __cpm_set_hdiv(v) \
+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_HDIV_MASK) | ((v) << (CPM_CPCCR_HDIV_BIT)))
+#define __cpm_set_pdiv(v) \
+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_PDIV_MASK) | ((v) << (CPM_CPCCR_PDIV_BIT)))
+#define __cpm_set_mdiv(v) \
+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_MDIV_MASK) | ((v) << (CPM_CPCCR_MDIV_BIT)))
+#define __cpm_set_ldiv(v) \
+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_LDIV_MASK) | ((v) << (CPM_CPCCR_LDIV_BIT)))
+#define __cpm_set_udiv(v) \
+ (REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_UDIV_MASK) | ((v) << (CPM_CPCCR_UDIV_BIT)))
+#define __cpm_set_i2sdiv(v) \
+ (REG_CPM_I2SCDR = (REG_CPM_I2SCDR & ~CPM_I2SCDR_I2SDIV_MASK) | ((v) << (CPM_I2SCDR_I2SDIV_BIT)))
+#define __cpm_set_pixdiv(v) \
+ (REG_CPM_LPCDR = (REG_CPM_LPCDR & ~CPM_LPCDR_PIXDIV_MASK) | ((v) << (CPM_LPCDR_PIXDIV_BIT)))
+#define __cpm_set_mscdiv(v) \
+ (REG_CPM_MSCCDR = (REG_CPM_MSCCDR & ~CPM_MSCCDR_MSCDIV_MASK) | ((v) << (CPM_MSCCDR_MSCDIV_BIT)))
+
+#define __cpm_select_i2sclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_I2CS)
+#define __cpm_select_i2sclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_I2CS)
+#define __cpm_enable_cko() (REG_CPM_CPCCR |= CPM_CPCCR_CLKOEN)
+#define __cpm_select_usbclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_UCS)
+#define __cpm_select_usbclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_UCS)
+#define __cpm_enable_pll_change() (REG_CPM_CPCCR |= CPM_CPCCR_CE)
+#define __cpm_pllout_direct() (REG_CPM_CPCCR |= CPM_CPCCR_PCS)
+#define __cpm_pllout_div2() (REG_CPM_CPCCR &= ~CPM_CPCCR_PCS)
+
+#define __cpm_pll_is_on() (REG_CPM_CPPCR & CPM_CPPCR_PLLS)
+#define __cpm_pll_bypass() (REG_CPM_CPPCR |= CPM_CPPCR_PLLBP)
+#define __cpm_pll_enable() (REG_CPM_CPPCR |= CPM_CPPCR_PLLEN)
+
+#define __cpm_get_cclk_doze_duty() \
+ ((REG_CPM_LCR & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT)
+#define __cpm_set_cclk_doze_duty(v) \
+ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_DOZE_DUTY_MASK) | ((v) << (CPM_LCR_DOZE_DUTY_BIT)))
+
+#define __cpm_doze_mode() (REG_CPM_LCR |= CPM_LCR_DOZE_ON)
+#define __cpm_idle_mode() \
+ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_IDLE)
+#define __cpm_sleep_mode() \
+ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_SLEEP)
+
+#define __cpm_stop_all() (REG_CPM_CLKGR = 0x7fff)
+#define __cpm_stop_uart1() (REG_CPM_CLKGR |= CPM_CLKGR_UART1)
+#define __cpm_stop_uhc() (REG_CPM_CLKGR |= CPM_CLKGR_UHC)
+#define __cpm_stop_ipu() (REG_CPM_CLKGR |= CPM_CLKGR_IPU)
+#define __cpm_stop_dmac() (REG_CPM_CLKGR |= CPM_CLKGR_DMAC)
+#define __cpm_stop_udc() (REG_CPM_CLKGR |= CPM_CLKGR_UDC)
+#define __cpm_stop_lcd() (REG_CPM_CLKGR |= CPM_CLKGR_LCD)
+#define __cpm_stop_cim() (REG_CPM_CLKGR |= CPM_CLKGR_CIM)
+#define __cpm_stop_sadc() (REG_CPM_CLKGR |= CPM_CLKGR_SADC)
+#define __cpm_stop_msc() (REG_CPM_CLKGR |= CPM_CLKGR_MSC)
+#define __cpm_stop_aic1() (REG_CPM_CLKGR |= CPM_CLKGR_AIC1)
+#define __cpm_stop_aic2() (REG_CPM_CLKGR |= CPM_CLKGR_AIC2)
+#define __cpm_stop_ssi() (REG_CPM_CLKGR |= CPM_CLKGR_SSI)
+#define __cpm_stop_i2c() (REG_CPM_CLKGR |= CPM_CLKGR_I2C)
+#define __cpm_stop_rtc() (REG_CPM_CLKGR |= CPM_CLKGR_RTC)
+#define __cpm_stop_tcu() (REG_CPM_CLKGR |= CPM_CLKGR_TCU)
+#define __cpm_stop_uart0() (REG_CPM_CLKGR |= CPM_CLKGR_UART0)
+
+#define __cpm_start_all() (REG_CPM_CLKGR = 0x0)
+#define __cpm_start_uart1() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART1)
+#define __cpm_start_uhc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UHC)
+#define __cpm_start_ipu() (REG_CPM_CLKGR &= ~CPM_CLKGR_IPU)
+#define __cpm_start_dmac() (REG_CPM_CLKGR &= ~CPM_CLKGR_DMAC)
+#define __cpm_start_udc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UDC)
+#define __cpm_start_lcd() (REG_CPM_CLKGR &= ~CPM_CLKGR_LCD)
+#define __cpm_start_cim() (REG_CPM_CLKGR &= ~CPM_CLKGR_CIM)
+#define __cpm_start_sadc() (REG_CPM_CLKGR &= ~CPM_CLKGR_SADC)
+#define __cpm_start_msc() (REG_CPM_CLKGR &= ~CPM_CLKGR_MSC)
+#define __cpm_start_aic1() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC1)
+#define __cpm_start_aic2() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC2)
+#define __cpm_start_ssi() (REG_CPM_CLKGR &= ~CPM_CLKGR_SSI)
+#define __cpm_start_i2c() (REG_CPM_CLKGR &= ~CPM_CLKGR_I2C)
+#define __cpm_start_rtc() (REG_CPM_CLKGR &= ~CPM_CLKGR_RTC)
+#define __cpm_start_tcu() (REG_CPM_CLKGR &= ~CPM_CLKGR_TCU)
+#define __cpm_start_uart0() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART0)
+
+#define __cpm_get_o1st() \
+ ((REG_CPM_SCR & CPM_SCR_O1ST_MASK) >> CPM_SCR_O1ST_BIT)
+#define __cpm_set_o1st(v) \
+ (REG_CPM_SCR = (REG_CPM_SCR & ~CPM_SCR_O1ST_MASK) | ((v) << (CPM_SCR_O1ST_BIT)))
+#define __cpm_suspend_udcphy() (REG_CPM_SCR &= ~CPM_SCR_UDCPHY_ENABLE)
+#define __cpm_suspend_usbphy() (REG_CPM_SCR |= CPM_SCR_USBPHY_DISABLE)
+#define __cpm_enable_osc_in_sleep() (REG_CPM_SCR |= CPM_SCR_OSC_ENABLE)
+
+
+#ifdef CONFIG_SYS_EXTAL
+#define JZ_EXTAL CONFIG_SYS_EXTAL
+#else
+#define JZ_EXTAL 3686400
+#endif
+#define JZ_EXTAL2 32768 /* RTC clock */
+
+/* PLL output frequency */
+static __inline__ unsigned int __cpm_get_pllout(void)
+{
+ unsigned long m, n, no, pllout;
+ unsigned long cppcr = REG_CPM_CPPCR;
+ unsigned long od[4] = {1, 2, 2, 4};
+ if ((cppcr & CPM_CPPCR_PLLEN) && !(cppcr & CPM_CPPCR_PLLBP)) {
+ m = __cpm_get_pllm() + 2;
+ n = __cpm_get_plln() + 2;
+ no = od[__cpm_get_pllod()];
+ pllout = ((JZ_EXTAL) / (n * no)) * m;
+ } else
+ pllout = JZ_EXTAL;
+ return pllout;
+}
+
+/* PLL output frequency for MSC/I2S/LCD/USB */
+static __inline__ unsigned int __cpm_get_pllout2(void)
+{
+ if (REG_CPM_CPCCR & CPM_CPCCR_PCS)
+ return __cpm_get_pllout();
+ else
+ return __cpm_get_pllout()/2;
+}
+
+/* CPU core clock */
+static __inline__ unsigned int __cpm_get_cclk(void)
+{
+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
+
+ return __cpm_get_pllout() / div[__cpm_get_cdiv()];
+}
+
+/* AHB system bus clock */
+static __inline__ unsigned int __cpm_get_hclk(void)
+{
+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
+
+ return __cpm_get_pllout() / div[__cpm_get_hdiv()];
+}
+
+/* Memory bus clock */
+static __inline__ unsigned int __cpm_get_mclk(void)
+{
+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
+
+ return __cpm_get_pllout() / div[__cpm_get_mdiv()];
+}
+
+/* APB peripheral bus clock */
+static __inline__ unsigned int __cpm_get_pclk(void)
+{
+ int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
+
+ return __cpm_get_pllout() / div[__cpm_get_pdiv()];
+}
+
+/* LCDC module clock */
+static __inline__ unsigned int __cpm_get_lcdclk(void)
+{
+ return __cpm_get_pllout2() / (__cpm_get_ldiv() + 1);
+}
+
+/* LCD pixel clock */
+static __inline__ unsigned int __cpm_get_pixclk(void)
+{
+ return __cpm_get_pllout2() / (__cpm_get_pixdiv() + 1);
+}
+
+/* I2S clock */
+static __inline__ unsigned int __cpm_get_i2sclk(void)
+{
+ if (REG_CPM_CPCCR & CPM_CPCCR_I2CS) {
+ return __cpm_get_pllout2() / (__cpm_get_i2sdiv() + 1);
+ }
+ else {
+ return JZ_EXTAL;
+ }
+}
+
+/* USB clock */
+static __inline__ unsigned int __cpm_get_usbclk(void)
+{
+ if (REG_CPM_CPCCR & CPM_CPCCR_UCS) {
+ return __cpm_get_pllout2() / (__cpm_get_udiv() + 1);
+ }
+ else {
+ return JZ_EXTAL;
+ }
+}
+
+/* MSC clock */
+static __inline__ unsigned int __cpm_get_mscclk(void)
+{
+ return __cpm_get_pllout2() / (__cpm_get_mscdiv() + 1);
+}
+
+/* EXTAL clock for UART,I2C,SSI,TCU,USB-PHY */
+static __inline__ unsigned int __cpm_get_extalclk(void)
+{
+ return JZ_EXTAL;
+}
+
+/* RTC clock for CPM,INTC,RTC,TCU,WDT */
+static __inline__ unsigned int __cpm_get_rtcclk(void)
+{
+ return JZ_EXTAL2;
+}
+
+/*
+ * Output 24MHz for SD and 16MHz for MMC.
+ */
+static inline void __cpm_select_msc_clk(int sd)
+{
+ unsigned int pllout2 = __cpm_get_pllout2();
+ unsigned int div = 0;
+
+ if (sd) {
+ div = pllout2 / 24000000;
+ }
+ else {
+ div = pllout2 / 16000000;
+ }
+
+ REG_CPM_MSCCDR = div - 1;
+}
+
+/*
+ * TCU
+ */
+/* where 'n' is the TCU channel */
+#define __tcu_select_extalclk(n) \
+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_EXT_EN)
+#define __tcu_select_rtcclk(n) \
+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_RTC_EN)
+#define __tcu_select_pclk(n) \
+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~(TCU_TCSR_EXT_EN | TCU_TCSR_RTC_EN | TCU_TCSR_PCK_EN)) | TCU_TCSR_PCK_EN)
+
+#define __tcu_select_clk_div1(n) \
+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE1)
+#define __tcu_select_clk_div4(n) \
+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE4)
+#define __tcu_select_clk_div16(n) \
+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE16)
+#define __tcu_select_clk_div64(n) \
+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE64)
+#define __tcu_select_clk_div256(n) \
+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE256)
+#define __tcu_select_clk_div1024(n) \
+ (REG_TCU_TCSR((n)) = (REG_TCU_TCSR((n)) & ~TCU_TCSR_PRESCALE_MASK) | TCU_TCSR_PRESCALE1024)
+
+#define __tcu_enable_pwm_output(n) ( REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_EN )
+#define __tcu_disable_pwm_output(n) ( REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_EN )
+
+#define __tcu_init_pwm_output_high(n) ( REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_INITL_HIGH )
+#define __tcu_init_pwm_output_low(n) ( REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_INITL_HIGH )
+
+#define __tcu_set_pwm_output_shutdown_graceful(n) ( REG_TCU_TCSR((n)) &= ~TCU_TCSR_PWM_SD )
+#define __tcu_set_pwm_output_shutdown_abrupt(n) ( REG_TCU_TCSR((n)) |= TCU_TCSR_PWM_SD )
+
+#define __tcu_start_counter(n) ( REG_TCU_TESR |= (1 << (n)) )
+#define __tcu_stop_counter(n) ( REG_TCU_TECR |= (1 << (n)) )
+
+#define __tcu_half_match_flag(n) ( REG_TCU_TFR & (1 << ((n) + 16)) )
+#define __tcu_full_match_flag(n) ( REG_TCU_TFR & (1 << (n)) )
+#define __tcu_set_half_match_flag(n) ( REG_TCU_TFSR = (1 << ((n) + 16)) )
+#define __tcu_set_full_match_flag(n) ( REG_TCU_TFSR = (1 << (n)) )
+#define __tcu_clear_half_match_flag(n) ( REG_TCU_TFCR = (1 << ((n) + 16)) )
+#define __tcu_clear_full_match_flag(n) ( REG_TCU_TFCR = (1 << (n)) )
+#define __tcu_mask_half_match_irq(n) ( REG_TCU_TMSR = (1 << ((n) + 16)) )
+#define __tcu_mask_full_match_irq(n) ( REG_TCU_TMSR = (1 << (n)) )
+#define __tcu_unmask_half_match_irq(n) ( REG_TCU_TMCR = (1 << ((n) + 16)) )
+#define __tcu_unmask_full_match_irq(n) ( REG_TCU_TMCR = (1 << (n)) )
+
+#define __tcu_wdt_clock_stopped() ( REG_TCU_TSR & TCU_TSSR_WDTSC )
+#define __tcu_timer_clock_stopped(n) ( REG_TCU_TSR & (1 << (n)) )
+
+#define __tcu_start_wdt_clock() ( REG_TCU_TSCR = TCU_TSSR_WDTSC )
+#define __tcu_start_timer_clock(n) ( REG_TCU_TSCR = (1 << (n)) )
+
+#define __tcu_stop_wdt_clock() ( REG_TCU_TSSR = TCU_TSSR_WDTSC )
+#define __tcu_stop_timer_clock(n) ( REG_TCU_TSSR = (1 << (n)) )
+
+#define __tcu_get_count(n) ( REG_TCU_TCNT((n)) )
+#define __tcu_set_count(n,v) ( REG_TCU_TCNT((n)) = (v) )
+#define __tcu_set_full_data(n,v) ( REG_TCU_TDFR((n)) = (v) )
+#define __tcu_set_half_data(n,v) ( REG_TCU_TDHR((n)) = (v) )
+
+
+/***************************************************************************
+ * WDT
+ ***************************************************************************/
+#define __wdt_start() ( REG_WDT_TCER |= WDT_TCER_TCEN )
+#define __wdt_stop() ( REG_WDT_TCER &= ~WDT_TCER_TCEN )
+#define __wdt_set_count(v) ( REG_WDT_TCNT = (v) )
+#define __wdt_set_data(v) ( REG_WDT_TDR = (v) )
+
+#define __wdt_select_extalclk() \
+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_EXT_EN)
+#define __wdt_select_rtcclk() \
+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_RTC_EN)
+#define __wdt_select_pclk() \
+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~(WDT_TCSR_EXT_EN | WDT_TCSR_RTC_EN | WDT_TCSR_PCK_EN)) | WDT_TCSR_PCK_EN)
+
+#define __wdt_select_clk_div1() \
+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE1)
+#define __wdt_select_clk_div4() \
+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE4)
+#define __wdt_select_clk_div16() \
+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE16)
+#define __wdt_select_clk_div64() \
+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE64)
+#define __wdt_select_clk_div256() \
+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE256)
+#define __wdt_select_clk_div1024() \
+ (REG_WDT_TCSR = (REG_WDT_TCSR & ~WDT_TCSR_PRESCALE_MASK) | WDT_TCSR_PRESCALE1024)
+
+
+/***************************************************************************
+ * UART
+ ***************************************************************************/
+
+#define __uart_enable() ( REG8(UART0_FCR) |= UARTFCR_UUE | UARTFCR_FE )
+#define __uart_disable() ( REG8(UART0_FCR) = ~UARTFCR_UUE )
+
+#define __uart_enable_transmit_irq() ( REG8(UART0_IER) |= UARTIER_TIE )
+#define __uart_disable_transmit_irq() ( REG8(UART0_IER) &= ~UARTIER_TIE )
+
+#define __uart_enable_receive_irq() \
+ ( REG8(UART0_IER) |= UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE )
+#define __uart_disable_receive_irq() \
+ ( REG8(UART0_IER) &= ~(UARTIER_RIE | UARTIER_RLIE | UARTIER_RTIE) )
+
+#define __uart_enable_loopback() ( REG8(UART0_MCR) |= UARTMCR_LOOP )
+#define __uart_disable_loopback() ( REG8(UART0_MCR) &= ~UARTMCR_LOOP )
+
+#define __uart_set_8n1() ( REG8(UART0_LCR) = UARTLCR_WLEN_8 )
+
+#define __uart_set_baud(devclk, baud) \
+ do { \
+ REG8(UART0_LCR) |= UARTLCR_DLAB; \
+ REG8(UART0_DLLR) = (devclk / 16 / baud) & 0xff; \
+ REG8(UART0_DLHR) = ((devclk / 16 / baud) >> 8) & 0xff; \
+ REG8(UART0_LCR) &= ~UARTLCR_DLAB; \
+ } while (0)
+
+#define __uart_parity_error() ( (REG8(UART0_LSR) & UARTLSR_PER) != 0 )
+#define __uart_clear_errors() \
+ ( REG8(UART0_LSR) &= ~(UARTLSR_ORER | UARTLSR_BRK | UARTLSR_FER | UARTLSR_PER | UARTLSR_RFER) )
+
+#define __uart_transmit_fifo_empty() ( (REG8(UART0_LSR) & UARTLSR_TDRQ) != 0 )
+#define __uart_transmit_end() ( (REG8(UART0_LSR) & UARTLSR_TEMT) != 0 )
+#define __uart_transmit_char(ch) ( REG8(UART0_TDR) = (ch) )
+#define __uart_receive_fifo_full() ( (REG8(UART0_LSR) & UARTLSR_DR) != 0 )
+#define __uart_receive_ready() ( (REG8(UART0_LSR) & UARTLSR_DR) != 0 )
+#define __uart_receive_char() REG8(UART0_RDR)
+#define __uart_disable_irda() ( REG8(UART0_SIRCR) &= ~(SIRCR_TSIRE | SIRCR_RSIRE) )
+#define __uart_enable_irda() \
+ /* Tx high pulse as 0, Rx low pulse as 0 */ \
+ ( REG8(UART0_SIRCR) = SIRCR_TSIRE | SIRCR_RSIRE | SIRCR_RXPL | SIRCR_TPWS )
+
+
+/***************************************************************************
+ * DMAC
+ ***************************************************************************/
+
+/* n is the DMA channel (0 - 5) */
+
+#define __dmac_enable_module() \
+ ( REG_DMAC_DMACR |= DMAC_DMACR_DMAE | DMAC_DMACR_PR_RR )
+#define __dmac_disable_module() \
+ ( REG_DMAC_DMACR &= ~DMAC_DMACR_DMAE )
+
+/* p=0,1,2,3 */
+#define __dmac_set_priority(p) \
+do { \
+ REG_DMAC_DMACR &= ~DMAC_DMACR_PR_MASK; \
+ REG_DMAC_DMACR |= ((p) << DMAC_DMACR_PR_BIT); \
+} while (0)
+
+#define __dmac_test_halt_error() ( REG_DMAC_DMACR & DMAC_DMACR_HLT )
+#define __dmac_test_addr_error() ( REG_DMAC_DMACR & DMAC_DMACR_AR )
+
+#define __dmac_enable_descriptor(n) \
+ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_NDES )
+#define __dmac_disable_descriptor(n) \
+ ( REG_DMAC_DCCSR((n)) |= DMAC_DCCSR_NDES )
+
+#define __dmac_enable_channel(n) \
+ ( REG_DMAC_DCCSR((n)) |= DMAC_DCCSR_EN )
+#define __dmac_disable_channel(n) \
+ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_EN )
+#define __dmac_channel_enabled(n) \
+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_EN )
+
+#define __dmac_channel_enable_irq(n) \
+ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_TIE )
+#define __dmac_channel_disable_irq(n) \
+ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_TIE )
+
+#define __dmac_channel_transmit_halt_detected(n) \
+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_HLT )
+#define __dmac_channel_transmit_end_detected(n) \
+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_TT )
+#define __dmac_channel_address_error_detected(n) \
+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_AR )
+#define __dmac_channel_count_terminated_detected(n) \
+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_CT )
+#define __dmac_channel_descriptor_invalid_detected(n) \
+ ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_INV )
+
+#define __dmac_channel_clear_transmit_halt(n) \
+ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_HLT )
+#define __dmac_channel_clear_transmit_end(n) \
+ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_TT )
+#define __dmac_channel_clear_address_error(n) \
+ ( REG_DMAC_DCCSR(n) &= ~DMAC_DCCSR_AR )
+#define __dmac_channel_clear_count_terminated(n) \
+ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_CT )
+#define __dmac_channel_clear_descriptor_invalid(n) \
+ ( REG_DMAC_DCCSR((n)) &= ~DMAC_DCCSR_INV )
+
+#define __dmac_channel_set_single_mode(n) \
+ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_TM )
+#define __dmac_channel_set_block_mode(n) \
+ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_TM )
+
+#define __dmac_channel_set_transfer_unit_32bit(n) \
+do { \
+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \
+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_32BIT; \
+} while (0)
+
+#define __dmac_channel_set_transfer_unit_16bit(n) \
+do { \
+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \
+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_16BIT; \
+} while (0)
+
+#define __dmac_channel_set_transfer_unit_8bit(n) \
+do { \
+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \
+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_8BIT; \
+} while (0)
+
+#define __dmac_channel_set_transfer_unit_16byte(n) \
+do { \
+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \
+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_16BYTE; \
+} while (0)
+
+#define __dmac_channel_set_transfer_unit_32byte(n) \
+do { \
+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DS_MASK; \
+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DS_32BYTE; \
+} while (0)
+
+/* w=8,16,32 */
+#define __dmac_channel_set_dest_port_width(n,w) \
+do { \
+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DWDH_MASK; \
+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_DWDH_##w; \
+} while (0)
+
+/* w=8,16,32 */
+#define __dmac_channel_set_src_port_width(n,w) \
+do { \
+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_SWDH_MASK; \
+ REG_DMAC_DCMD((n)) |= DMAC_DCMD_SWDH_##w; \
+} while (0)
+
+/* v=0-15 */
+#define __dmac_channel_set_rdil(n,v) \
+do { \
+ REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_RDIL_MASK; \
+ REG_DMAC_DCMD((n) |= ((v) << DMAC_DCMD_RDIL_BIT); \
+} while (0)
+
+#define __dmac_channel_dest_addr_fixed(n) \
+ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_DAI )
+#define __dmac_channel_dest_addr_increment(n) \
+ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_DAI )
+
+#define __dmac_channel_src_addr_fixed(n) \
+ ( REG_DMAC_DCMD((n)) &= ~DMAC_DCMD_SAI )
+#define __dmac_channel_src_addr_increment(n) \
+ ( REG_DMAC_DCMD((n)) |= DMAC_DCMD_SAI )
+
+#define __dmac_channel_set_doorbell(n) \
+ ( REG_DMAC_DMADBSR = (1 << (n)) )
+
+#define __dmac_channel_irq_detected(n) ( REG_DMAC_DMAIPR & (1 << (n)) )
+#define __dmac_channel_ack_irq(n) ( REG_DMAC_DMAIPR &= ~(1 << (n)) )
+
+static __inline__ int __dmac_get_irq(void)
+{
+ int i;
+ for (i = 0; i < MAX_DMA_NUM; i++)
+ if (__dmac_channel_irq_detected(i))
+ return i;
+ return -1;
+}
+
+
+/***************************************************************************
+ * AIC (AC'97 & I2S Controller)
+ ***************************************************************************/
+
+#define __aic_enable() ( REG_AIC_FR |= AIC_FR_ENB )
+#define __aic_disable() ( REG_AIC_FR &= ~AIC_FR_ENB )
+
+#define __aic_select_ac97() ( REG_AIC_FR &= ~AIC_FR_AUSEL )
+#define __aic_select_i2s() ( REG_AIC_FR |= AIC_FR_AUSEL )
+
+#define __i2s_as_master() ( REG_AIC_FR |= AIC_FR_BCKD | AIC_FR_SYNCD )
+#define __i2s_as_slave() ( REG_AIC_FR &= ~(AIC_FR_BCKD | AIC_FR_SYNCD) )
+#define __aic_reset_status() ( REG_AIC_FR & AIC_FR_RST )
+
+#define __aic_reset() \
+do { \
+ REG_AIC_FR |= AIC_FR_RST; \
+} while(0)
+
+
+#define __aic_set_transmit_trigger(n) \
+do { \
+ REG_AIC_FR &= ~AIC_FR_TFTH_MASK; \
+ REG_AIC_FR |= ((n) << AIC_FR_TFTH_BIT); \
+} while(0)
+
+#define __aic_set_receive_trigger(n) \
+do { \
+ REG_AIC_FR &= ~AIC_FR_RFTH_MASK; \
+ REG_AIC_FR |= ((n) << AIC_FR_RFTH_BIT); \
+} while(0)
+
+#define __aic_enable_record() ( REG_AIC_CR |= AIC_CR_EREC )
+#define __aic_disable_record() ( REG_AIC_CR &= ~AIC_CR_EREC )
+#define __aic_enable_replay() ( REG_AIC_CR |= AIC_CR_ERPL )
+#define __aic_disable_replay() ( REG_AIC_CR &= ~AIC_CR_ERPL )
+#define __aic_enable_loopback() ( REG_AIC_CR |= AIC_CR_ENLBF )
+#define __aic_disable_loopback() ( REG_AIC_CR &= ~AIC_CR_ENLBF )
+
+#define __aic_flush_fifo() ( REG_AIC_CR |= AIC_CR_FLUSH )
+#define __aic_unflush_fifo() ( REG_AIC_CR &= ~AIC_CR_FLUSH )
+
+#define __aic_enable_transmit_intr() \
+ ( REG_AIC_CR |= (AIC_CR_ETFS | AIC_CR_ETUR) )
+#define __aic_disable_transmit_intr() \
+ ( REG_AIC_CR &= ~(AIC_CR_ETFS | AIC_CR_ETUR) )
+#define __aic_enable_receive_intr() \
+ ( REG_AIC_CR |= (AIC_CR_ERFS | AIC_CR_EROR) )
+#define __aic_disable_receive_intr() \
+ ( REG_AIC_CR &= ~(AIC_CR_ERFS | AIC_CR_EROR) )
+
+#define __aic_enable_transmit_dma() ( REG_AIC_CR |= AIC_CR_TDMS )
+#define __aic_disable_transmit_dma() ( REG_AIC_CR &= ~AIC_CR_TDMS )
+#define __aic_enable_receive_dma() ( REG_AIC_CR |= AIC_CR_RDMS )
+#define __aic_disable_receive_dma() ( REG_AIC_CR &= ~AIC_CR_RDMS )
+
+#define __aic_enable_mono2stereo() ( REG_AIC_CR |= AIC_CR_M2S )
+#define __aic_disable_mono2stereo() ( REG_AIC_CR &= ~AIC_CR_M2S )
+#define __aic_enable_byteswap() ( REG_AIC_CR |= AIC_CR_ENDSW )
+#define __aic_disable_byteswap() ( REG_AIC_CR &= ~AIC_CR_ENDSW )
+#define __aic_enable_unsignadj() ( REG_AIC_CR |= AIC_CR_AVSTSU )
+#define __aic_disable_unsignadj() ( REG_AIC_CR &= ~AIC_CR_AVSTSU )
+
+#define AC97_PCM_XS_L_FRONT AIC_ACCR1_XS_SLOT3
+#define AC97_PCM_XS_R_FRONT AIC_ACCR1_XS_SLOT4
+#define AC97_PCM_XS_CENTER AIC_ACCR1_XS_SLOT6
+#define AC97_PCM_XS_L_SURR AIC_ACCR1_XS_SLOT7
+#define AC97_PCM_XS_R_SURR AIC_ACCR1_XS_SLOT8
+#define AC97_PCM_XS_LFE AIC_ACCR1_XS_SLOT9
+
+#define AC97_PCM_RS_L_FRONT AIC_ACCR1_RS_SLOT3
+#define AC97_PCM_RS_R_FRONT AIC_ACCR1_RS_SLOT4
+#define AC97_PCM_RS_CENTER AIC_ACCR1_RS_SLOT6
+#define AC97_PCM_RS_L_SURR AIC_ACCR1_RS_SLOT7
+#define AC97_PCM_RS_R_SURR AIC_ACCR1_RS_SLOT8
+#define AC97_PCM_RS_LFE AIC_ACCR1_RS_SLOT9
+
+#define __ac97_set_xs_none() ( REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK )
+#define __ac97_set_xs_mono() \
+do { \
+ REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK; \
+ REG_AIC_ACCR1 |= AC97_PCM_XS_R_FRONT; \
+} while(0)
+#define __ac97_set_xs_stereo() \
+do { \
+ REG_AIC_ACCR1 &= ~AIC_ACCR1_XS_MASK; \
+ REG_AIC_ACCR1 |= AC97_PCM_XS_L_FRONT | AC97_PCM_XS_R_FRONT; \
+} while(0)
+
+/* In fact, only stereo is support now. */
+#define __ac97_set_rs_none() ( REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK )
+#define __ac97_set_rs_mono() \
+do { \
+ REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK; \
+ REG_AIC_ACCR1 |= AC97_PCM_RS_R_FRONT; \
+} while(0)
+#define __ac97_set_rs_stereo() \
+do { \
+ REG_AIC_ACCR1 &= ~AIC_ACCR1_RS_MASK; \
+ REG_AIC_ACCR1 |= AC97_PCM_RS_L_FRONT | AC97_PCM_RS_R_FRONT; \
+} while(0)
+
+#define __ac97_warm_reset_codec() \
+ do { \
+ REG_AIC_ACCR2 |= AIC_ACCR2_SA; \
+ REG_AIC_ACCR2 |= AIC_ACCR2_SS; \
+ udelay(2); \
+ REG_AIC_ACCR2 &= ~AIC_ACCR2_SS; \
+ REG_AIC_ACCR2 &= ~AIC_ACCR2_SA; \
+ } while (0)
+
+#define __ac97_cold_reset_codec() \
+ do { \
+ REG_AIC_ACCR2 |= AIC_ACCR2_SR; \
+ udelay(2); \
+ REG_AIC_ACCR2 &= ~AIC_ACCR2_SR; \
+ } while (0)
+
+/* n=8,16,18,20 */
+#define __ac97_set_iass(n) \
+ ( REG_AIC_ACCR2 = (REG_AIC_ACCR2 & ~AIC_ACCR2_IASS_MASK) | AIC_ACCR2_IASS_##n##BIT )
+#define __ac97_set_oass(n) \
+ ( REG_AIC_ACCR2 = (REG_AIC_ACCR2 & ~AIC_ACCR2_OASS_MASK) | AIC_ACCR2_OASS_##n##BIT )
+
+#define __i2s_select_i2s() ( REG_AIC_I2SCR &= ~AIC_I2SCR_AMSL )
+#define __i2s_select_msbjustified() ( REG_AIC_I2SCR |= AIC_I2SCR_AMSL )
+
+/* n=8,16,18,20,24 */
+/*#define __i2s_set_sample_size(n) \
+ ( REG_AIC_I2SCR |= (REG_AIC_I2SCR & ~AIC_I2SCR_WL_MASK) | AIC_I2SCR_WL_##n##BIT )*/
+
+#define __i2s_set_oss_sample_size(n) \
+ ( REG_AIC_CR = (REG_AIC_CR & ~AIC_CR_OSS_MASK) | AIC_CR_OSS_##n##BIT )
+#define __i2s_set_iss_sample_size(n) \
+ ( REG_AIC_CR = (REG_AIC_CR & ~AIC_CR_ISS_MASK) | AIC_CR_ISS_##n##BIT )
+
+#define __i2s_stop_bitclk() ( REG_AIC_I2SCR |= AIC_I2SCR_STPBK )
+#define __i2s_start_bitclk() ( REG_AIC_I2SCR &= ~AIC_I2SCR_STPBK )
+
+#define __aic_transmit_request() ( REG_AIC_SR & AIC_SR_TFS )
+#define __aic_receive_request() ( REG_AIC_SR & AIC_SR_RFS )
+#define __aic_transmit_underrun() ( REG_AIC_SR & AIC_SR_TUR )
+#define __aic_receive_overrun() ( REG_AIC_SR & AIC_SR_ROR )
+
+#define __aic_clear_errors() ( REG_AIC_SR &= ~(AIC_SR_TUR | AIC_SR_ROR) )
+
+#define __aic_get_transmit_resident() \
+ ( (REG_AIC_SR & AIC_SR_TFL_MASK) >> AIC_SR_TFL_BIT )
+#define __aic_get_receive_count() \
+ ( (REG_AIC_SR & AIC_SR_RFL_MASK) >> AIC_SR_RFL_BIT )
+
+#define __ac97_command_transmitted() ( REG_AIC_ACSR & AIC_ACSR_CADT )
+#define __ac97_status_received() ( REG_AIC_ACSR & AIC_ACSR_SADR )
+#define __ac97_status_receive_timeout() ( REG_AIC_ACSR & AIC_ACSR_RSTO )
+#define __ac97_codec_is_low_power_mode() ( REG_AIC_ACSR & AIC_ACSR_CLPM )
+#define __ac97_codec_is_ready() ( REG_AIC_ACSR & AIC_ACSR_CRDY )
+#define __ac97_slot_error_detected() ( REG_AIC_ACSR & AIC_ACSR_SLTERR )
+#define __ac97_clear_slot_error() ( REG_AIC_ACSR &= ~AIC_ACSR_SLTERR )
+
+#define __i2s_is_busy() ( REG_AIC_I2SSR & AIC_I2SSR_BSY )
+
+#define CODEC_READ_CMD (1 << 19)
+#define CODEC_WRITE_CMD (0 << 19)
+#define CODEC_REG_INDEX_BIT 12
+#define CODEC_REG_INDEX_MASK (0x7f << CODEC_REG_INDEX_BIT) /* 18:12 */
+#define CODEC_REG_DATA_BIT 4
+#define CODEC_REG_DATA_MASK (0x0ffff << 4) /* 19:4 */
+
+#define __ac97_out_rcmd_addr(reg) \
+do { \
+ REG_AIC_ACCAR = CODEC_READ_CMD | ((reg) << CODEC_REG_INDEX_BIT); \
+} while (0)
+
+#define __ac97_out_wcmd_addr(reg) \
+do { \
+ REG_AIC_ACCAR = CODEC_WRITE_CMD | ((reg) << CODEC_REG_INDEX_BIT); \
+} while (0)
+
+#define __ac97_out_data(value) \
+do { \
+ REG_AIC_ACCDR = ((value) << CODEC_REG_DATA_BIT); \
+} while (0)
+
+#define __ac97_in_data() \
+ ( (REG_AIC_ACSDR & CODEC_REG_DATA_MASK) >> CODEC_REG_DATA_BIT )
+
+#define __ac97_in_status_addr() \
+ ( (REG_AIC_ACSAR & CODEC_REG_INDEX_MASK) >> CODEC_REG_INDEX_BIT )
+
+#define __i2s_set_sample_rate(i2sclk, sync) \
+ ( REG_AIC_I2SDIV = ((i2sclk) / (4*64)) / (sync) )
+
+#define __aic_write_tfifo(v) ( REG_AIC_DR = (v) )
+#define __aic_read_rfifo() ( REG_AIC_DR )
+
+#define __aic_internal_codec() ( REG_AIC_FR |= AIC_FR_ICDC )
+#define __aic_external_codec() ( REG_AIC_FR &= ~AIC_FR_ICDC )
+
+/* Define next ops for AC97 compatible */
+
+#define AC97_ACSR AIC_ACSR
+
+#define __ac97_enable() __aic_enable(); __aic_select_ac97()
+#define __ac97_disable() __aic_disable()
+#define __ac97_reset() __aic_reset()
+
+#define __ac97_set_transmit_trigger(n) __aic_set_transmit_trigger(n)
+#define __ac97_set_receive_trigger(n) __aic_set_receive_trigger(n)
+
+#define __ac97_enable_record() __aic_enable_record()
+#define __ac97_disable_record() __aic_disable_record()
+#define __ac97_enable_replay() __aic_enable_replay()
+#define __ac97_disable_replay() __aic_disable_replay()
+#define __ac97_enable_loopback() __aic_enable_loopback()
+#define __ac97_disable_loopback() __aic_disable_loopback()
+
+#define __ac97_enable_transmit_dma() __aic_enable_transmit_dma()
+#define __ac97_disable_transmit_dma() __aic_disable_transmit_dma()
+#define __ac97_enable_receive_dma() __aic_enable_receive_dma()
+#define __ac97_disable_receive_dma() __aic_disable_receive_dma()
+
+#define __ac97_transmit_request() __aic_transmit_request()
+#define __ac97_receive_request() __aic_receive_request()
+#define __ac97_transmit_underrun() __aic_transmit_underrun()
+#define __ac97_receive_overrun() __aic_receive_overrun()
+
+#define __ac97_clear_errors() __aic_clear_errors()
+
+#define __ac97_get_transmit_resident() __aic_get_transmit_resident()
+#define __ac97_get_receive_count() __aic_get_receive_count()
+
+#define __ac97_enable_transmit_intr() __aic_enable_transmit_intr()
+#define __ac97_disable_transmit_intr() __aic_disable_transmit_intr()
+#define __ac97_enable_receive_intr() __aic_enable_receive_intr()
+#define __ac97_disable_receive_intr() __aic_disable_receive_intr()
+
+#define __ac97_write_tfifo(v) __aic_write_tfifo(v)
+#define __ac97_read_rfifo() __aic_read_rfifo()
+
+/* Define next ops for I2S compatible */
+
+#define I2S_ACSR AIC_I2SSR
+
+#define __i2s_enable() __aic_enable(); __aic_select_i2s()
+#define __i2s_disable() __aic_disable()
+#define __i2s_reset() __aic_reset()
+
+#define __i2s_set_transmit_trigger(n) __aic_set_transmit_trigger(n)
+#define __i2s_set_receive_trigger(n) __aic_set_receive_trigger(n)
+
+#define __i2s_enable_record() __aic_enable_record()
+#define __i2s_disable_record() __aic_disable_record()
+#define __i2s_enable_replay() __aic_enable_replay()
+#define __i2s_disable_replay() __aic_disable_replay()
+#define __i2s_enable_loopback() __aic_enable_loopback()
+#define __i2s_disable_loopback() __aic_disable_loopback()
+
+#define __i2s_enable_transmit_dma() __aic_enable_transmit_dma()
+#define __i2s_disable_transmit_dma() __aic_disable_transmit_dma()
+#define __i2s_enable_receive_dma() __aic_enable_receive_dma()
+#define __i2s_disable_receive_dma() __aic_disable_receive_dma()
+
+#define __i2s_transmit_request() __aic_transmit_request()
+#define __i2s_receive_request() __aic_receive_request()
+#define __i2s_transmit_underrun() __aic_transmit_underrun()
+#define __i2s_receive_overrun() __aic_receive_overrun()
+
+#define __i2s_clear_errors() __aic_clear_errors()
+
+#define __i2s_get_transmit_resident() __aic_get_transmit_resident()
+#define __i2s_get_receive_count() __aic_get_receive_count()
+
+#define __i2s_enable_transmit_intr() __aic_enable_transmit_intr()
+#define __i2s_disable_transmit_intr() __aic_disable_transmit_intr()
+#define __i2s_enable_receive_intr() __aic_enable_receive_intr()
+#define __i2s_disable_receive_intr() __aic_disable_receive_intr()
+
+#define __i2s_write_tfifo(v) __aic_write_tfifo(v)
+#define __i2s_read_rfifo() __aic_read_rfifo()
+
+#define __i2s_reset_codec() \
+ do { \
+ } while (0)
+
+
+/***************************************************************************
+ * ICDC
+ ***************************************************************************/
+#define __i2s_internal_codec() __aic_internal_codec()
+#define __i2s_external_codec() __aic_external_codec()
+
+/***************************************************************************
+ * INTC
+ ***************************************************************************/
+#define __intc_unmask_irq(n) ( REG_INTC_IMCR = (1 << (n)) )
+#define __intc_mask_irq(n) ( REG_INTC_IMSR = (1 << (n)) )
+#define __intc_ack_irq(n) ( REG_INTC_IPR = (1 << (n)) )
+
+
+/***************************************************************************
+ * I2C
+ ***************************************************************************/
+
+#define __i2c_enable() ( REG_I2C_CR |= I2C_CR_I2CE )
+#define __i2c_disable() ( REG_I2C_CR &= ~I2C_CR_I2CE )
+
+#define __i2c_send_start() ( REG_I2C_CR |= I2C_CR_STA )
+#define __i2c_send_stop() ( REG_I2C_CR |= I2C_CR_STO )
+#define __i2c_send_ack() ( REG_I2C_CR &= ~I2C_CR_AC )
+#define __i2c_send_nack() ( REG_I2C_CR |= I2C_CR_AC )
+
+#define __i2c_set_drf() ( REG_I2C_SR |= I2C_SR_DRF )
+#define __i2c_clear_drf() ( REG_I2C_SR &= ~I2C_SR_DRF )
+#define __i2c_check_drf() ( REG_I2C_SR & I2C_SR_DRF )
+
+#define __i2c_received_ack() ( !(REG_I2C_SR & I2C_SR_ACKF) )
+#define __i2c_is_busy() ( REG_I2C_SR & I2C_SR_BUSY )
+#define __i2c_transmit_ended() ( REG_I2C_SR & I2C_SR_TEND )
+
+#define __i2c_set_clk(dev_clk, i2c_clk) \
+ ( REG_I2C_GR = (dev_clk) / (16*(i2c_clk)) - 1 )
+
+#define __i2c_read() ( REG_I2C_DR )
+#define __i2c_write(val) ( REG_I2C_DR = (val) )
+
+
+/***************************************************************************
+ * MSC
+ ***************************************************************************/
+
+#define __msc_start_op() \
+ ( REG_MSC_STRPCL = MSC_STRPCL_START_OP | MSC_STRPCL_CLOCK_CONTROL_START )
+
+#define __msc_set_resto(to) ( REG_MSC_RESTO = to )
+#define __msc_set_rdto(to) ( REG_MSC_RDTO = to )
+#define __msc_set_cmd(cmd) ( REG_MSC_CMD = cmd )
+#define __msc_set_arg(arg) ( REG_MSC_ARG = arg )
+#define __msc_set_nob(nob) ( REG_MSC_NOB = nob )
+#define __msc_get_nob() ( REG_MSC_NOB )
+#define __msc_set_blklen(len) ( REG_MSC_BLKLEN = len )
+#define __msc_set_cmdat(cmdat) ( REG_MSC_CMDAT = cmdat )
+#define __msc_set_cmdat_ioabort() ( REG_MSC_CMDAT |= MSC_CMDAT_IO_ABORT )
+#define __msc_clear_cmdat_ioabort() ( REG_MSC_CMDAT &= ~MSC_CMDAT_IO_ABORT )
+
+#define __msc_set_cmdat_bus_width1() \
+do { \
+ REG_MSC_CMDAT &= ~MSC_CMDAT_BUS_WIDTH_MASK; \
+ REG_MSC_CMDAT |= MSC_CMDAT_BUS_WIDTH_1BIT; \
+} while(0)
+
+#define __msc_set_cmdat_bus_width4() \
+do { \
+ REG_MSC_CMDAT &= ~MSC_CMDAT_BUS_WIDTH_MASK; \
+ REG_MSC_CMDAT |= MSC_CMDAT_BUS_WIDTH_4BIT; \
+} while(0)
+
+#define __msc_set_cmdat_dma_en() ( REG_MSC_CMDAT |= MSC_CMDAT_DMA_EN )
+#define __msc_set_cmdat_init() ( REG_MSC_CMDAT |= MSC_CMDAT_INIT )
+#define __msc_set_cmdat_busy() ( REG_MSC_CMDAT |= MSC_CMDAT_BUSY )
+#define __msc_set_cmdat_stream() ( REG_MSC_CMDAT |= MSC_CMDAT_STREAM_BLOCK )
+#define __msc_set_cmdat_block() ( REG_MSC_CMDAT &= ~MSC_CMDAT_STREAM_BLOCK )
+#define __msc_set_cmdat_read() ( REG_MSC_CMDAT &= ~MSC_CMDAT_WRITE_READ )
+#define __msc_set_cmdat_write() ( REG_MSC_CMDAT |= MSC_CMDAT_WRITE_READ )
+#define __msc_set_cmdat_data_en() ( REG_MSC_CMDAT |= MSC_CMDAT_DATA_EN )
+
+/* r is MSC_CMDAT_RESPONSE_FORMAT_Rx or MSC_CMDAT_RESPONSE_FORMAT_NONE */
+#define __msc_set_cmdat_res_format(r) \
+do { \
+ REG_MSC_CMDAT &= ~MSC_CMDAT_RESPONSE_FORMAT_MASK; \
+ REG_MSC_CMDAT |= (r); \
+} while(0)
+
+#define __msc_clear_cmdat() \
+ REG_MSC_CMDAT &= ~( MSC_CMDAT_IO_ABORT | MSC_CMDAT_DMA_EN | MSC_CMDAT_INIT| \
+ MSC_CMDAT_BUSY | MSC_CMDAT_STREAM_BLOCK | MSC_CMDAT_WRITE_READ | \
+ MSC_CMDAT_DATA_EN | MSC_CMDAT_RESPONSE_FORMAT_MASK )
+
+#define __msc_get_imask() ( REG_MSC_IMASK )
+#define __msc_mask_all_intrs() ( REG_MSC_IMASK = 0xff )
+#define __msc_unmask_all_intrs() ( REG_MSC_IMASK = 0x00 )
+#define __msc_mask_rd() ( REG_MSC_IMASK |= MSC_IMASK_RXFIFO_RD_REQ )
+#define __msc_unmask_rd() ( REG_MSC_IMASK &= ~MSC_IMASK_RXFIFO_RD_REQ )
+#define __msc_mask_wr() ( REG_MSC_IMASK |= MSC_IMASK_TXFIFO_WR_REQ )
+#define __msc_unmask_wr() ( REG_MSC_IMASK &= ~MSC_IMASK_TXFIFO_WR_REQ )
+#define __msc_mask_endcmdres() ( REG_MSC_IMASK |= MSC_IMASK_END_CMD_RES )
+#define __msc_unmask_endcmdres() ( REG_MSC_IMASK &= ~MSC_IMASK_END_CMD_RES )
+#define __msc_mask_datatrandone() ( REG_MSC_IMASK |= MSC_IMASK_DATA_TRAN_DONE )
+#define __msc_unmask_datatrandone() ( REG_MSC_IMASK &= ~MSC_IMASK_DATA_TRAN_DONE )
+#define __msc_mask_prgdone() ( REG_MSC_IMASK |= MSC_IMASK_PRG_DONE )
+#define __msc_unmask_prgdone() ( REG_MSC_IMASK &= ~MSC_IMASK_PRG_DONE )
+
+/* n=0,1,2,3,4,5,6,7 */
+#define __msc_set_clkrt(n) \
+do { \
+ REG_MSC_CLKRT = n; \
+} while(0)
+
+#define __msc_get_ireg() ( REG_MSC_IREG )
+#define __msc_ireg_rd() ( REG_MSC_IREG & MSC_IREG_RXFIFO_RD_REQ )
+#define __msc_ireg_wr() ( REG_MSC_IREG & MSC_IREG_TXFIFO_WR_REQ )
+#define __msc_ireg_end_cmd_res() ( REG_MSC_IREG & MSC_IREG_END_CMD_RES )
+#define __msc_ireg_data_tran_done() ( REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE )
+#define __msc_ireg_prg_done() ( REG_MSC_IREG & MSC_IREG_PRG_DONE )
+#define __msc_ireg_clear_end_cmd_res() ( REG_MSC_IREG = MSC_IREG_END_CMD_RES )
+#define __msc_ireg_clear_data_tran_done() ( REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE )
+#define __msc_ireg_clear_prg_done() ( REG_MSC_IREG = MSC_IREG_PRG_DONE )
+
+#define __msc_get_stat() ( REG_MSC_STAT )
+#define __msc_stat_not_end_cmd_res() ( (REG_MSC_STAT & MSC_STAT_END_CMD_RES) == 0)
+#define __msc_stat_crc_err() \
+ ( REG_MSC_STAT & (MSC_STAT_CRC_RES_ERR | MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR_YES) )
+#define __msc_stat_res_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_RES_ERR )
+#define __msc_stat_rd_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_READ_ERROR )
+#define __msc_stat_wr_crc_err() ( REG_MSC_STAT & MSC_STAT_CRC_WRITE_ERROR_YES )
+#define __msc_stat_resto_err() ( REG_MSC_STAT & MSC_STAT_TIME_OUT_RES )
+#define __msc_stat_rdto_err() ( REG_MSC_STAT & MSC_STAT_TIME_OUT_READ )
+
+#define __msc_rd_resfifo() ( REG_MSC_RES )
+#define __msc_rd_rxfifo() ( REG_MSC_RXFIFO )
+#define __msc_wr_txfifo(v) ( REG_MSC_TXFIFO = v )
+
+#define __msc_reset() \
+do { \
+ REG_MSC_STRPCL = MSC_STRPCL_RESET; \
+ while (REG_MSC_STAT & MSC_STAT_IS_RESETTING); \
+} while (0)
+
+#define __msc_start_clk() \
+do { \
+ REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_START; \
+} while (0)
+
+#define __msc_stop_clk() \
+do { \
+ REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_STOP; \
+} while (0)
+
+#define MMC_CLK 19169200
+#define SD_CLK 24576000
+
+/* msc_clk should little than pclk and little than clk retrieve from card */
+#define __msc_calc_clk_divisor(type,dev_clk,msc_clk,lv) \
+do { \
+ unsigned int rate, pclk, i; \
+ pclk = dev_clk; \
+ rate = type?SD_CLK:MMC_CLK; \
+ if (msc_clk && msc_clk < pclk) \
+ pclk = msc_clk; \
+ i = 0; \
+ while (pclk < rate) \
+ { \
+ i ++; \
+ rate >>= 1; \
+ } \
+ lv = i; \
+} while(0)
+
+/* divide rate to little than or equal to 400kHz */
+#define __msc_calc_slow_clk_divisor(type, lv) \
+do { \
+ unsigned int rate, i; \
+ rate = (type?SD_CLK:MMC_CLK)/1000/400; \
+ i = 0; \
+ while (rate > 0) \
+ { \
+ rate >>= 1; \
+ i ++; \
+ } \
+ lv = i; \
+} while(0)
+
+
+/***************************************************************************
+ * SSI
+ ***************************************************************************/
+
+#define __ssi_enable() ( REG_SSI_CR0 |= SSI_CR0_SSIE )
+#define __ssi_disable() ( REG_SSI_CR0 &= ~SSI_CR0_SSIE )
+#define __ssi_select_ce() ( REG_SSI_CR0 &= ~SSI_CR0_FSEL )
+
+#define __ssi_normal_mode() ( REG_SSI_ITR &= ~SSI_ITR_IVLTM_MASK )
+
+#define __ssi_select_ce2() \
+do { \
+ REG_SSI_CR0 |= SSI_CR0_FSEL; \
+ REG_SSI_CR1 &= ~SSI_CR1_MULTS; \
+} while (0)
+
+#define __ssi_select_gpc() \
+do { \
+ REG_SSI_CR0 &= ~SSI_CR0_FSEL; \
+ REG_SSI_CR1 |= SSI_CR1_MULTS; \
+} while (0)
+
+#define __ssi_enable_tx_intr() \
+ ( REG_SSI_CR0 |= SSI_CR0_TIE | SSI_CR0_TEIE )
+
+#define __ssi_disable_tx_intr() \
+ ( REG_SSI_CR0 &= ~(SSI_CR0_TIE | SSI_CR0_TEIE) )
+
+#define __ssi_enable_rx_intr() \
+ ( REG_SSI_CR0 |= SSI_CR0_RIE | SSI_CR0_REIE )
+
+#define __ssi_disable_rx_intr() \
+ ( REG_SSI_CR0 &= ~(SSI_CR0_RIE | SSI_CR0_REIE) )
+
+#define __ssi_enable_loopback() ( REG_SSI_CR0 |= SSI_CR0_LOOP )
+#define __ssi_disable_loopback() ( REG_SSI_CR0 &= ~SSI_CR0_LOOP )
+
+#define __ssi_enable_receive() ( REG_SSI_CR0 &= ~SSI_CR0_DISREV )
+#define __ssi_disable_receive() ( REG_SSI_CR0 |= SSI_CR0_DISREV )
+
+#define __ssi_finish_receive() \
+ ( REG_SSI_CR0 |= (SSI_CR0_RFINE | SSI_CR0_RFINC) )
+
+#define __ssi_disable_recvfinish() \
+ ( REG_SSI_CR0 &= ~(SSI_CR0_RFINE | SSI_CR0_RFINC) )
+
+#define __ssi_flush_txfifo() ( REG_SSI_CR0 |= SSI_CR0_TFLUSH )
+#define __ssi_flush_rxfifo() ( REG_SSI_CR0 |= SSI_CR0_RFLUSH )
+
+#define __ssi_flush_fifo() \
+ ( REG_SSI_CR0 |= SSI_CR0_TFLUSH | SSI_CR0_RFLUSH )
+
+#define __ssi_finish_transmit() ( REG_SSI_CR1 &= ~SSI_CR1_UNFIN )
+
+#define __ssi_spi_format() \
+do { \
+ REG_SSI_CR1 &= ~SSI_CR1_FMAT_MASK; \
+ REG_SSI_CR1 |= SSI_CR1_FMAT_SPI; \
+ REG_SSI_CR1 &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK);\
+ REG_SSI_CR1 |= (SSI_CR1_TFVCK_1 | SSI_CR1_TCKFI_1); \
+} while (0)
+
+/* TI's SSP format, must clear SSI_CR1.UNFIN */
+#define __ssi_ssp_format() \
+do { \
+ REG_SSI_CR1 &= ~(SSI_CR1_FMAT_MASK | SSI_CR1_UNFIN); \
+ REG_SSI_CR1 |= SSI_CR1_FMAT_SSP; \
+} while (0)
+
+/* National's Microwire format, must clear SSI_CR0.RFINE, and set max delay */
+#define __ssi_microwire_format() \
+do { \
+ REG_SSI_CR1 &= ~SSI_CR1_FMAT_MASK; \
+ REG_SSI_CR1 |= SSI_CR1_FMAT_MW1; \
+ REG_SSI_CR1 &= ~(SSI_CR1_TFVCK_MASK|SSI_CR1_TCKFI_MASK);\
+ REG_SSI_CR1 |= (SSI_CR1_TFVCK_3 | SSI_CR1_TCKFI_3); \
+ REG_SSI_CR0 &= ~SSI_CR0_RFINE; \
+} while (0)
+
+/* CE# level (FRMHL), CE# in interval time (ITFRM),
+ clock phase and polarity (PHA POL),
+ interval time (SSIITR), interval characters/frame (SSIICR) */
+
+ /* frmhl,endian,mcom,flen,pha,pol MASK */
+#define SSICR1_MISC_MASK \
+ ( SSI_CR1_FRMHL_MASK | SSI_CR1_LFST | SSI_CR1_MCOM_MASK \
+ | SSI_CR1_FLEN_MASK | SSI_CR1_PHA | SSI_CR1_POL ) \
+
+#define __ssi_spi_set_misc(frmhl,endian,flen,mcom,pha,pol) \
+do { \
+ REG_SSI_CR1 &= ~SSICR1_MISC_MASK; \
+ REG_SSI_CR1 |= ((frmhl) << 30) | ((endian) << 25) | \
+ (((mcom) - 1) << 12) | (((flen) - 2) << 4) | \
+ ((pha) << 1) | (pol); \
+} while(0)
+
+/* Transfer with MSB or LSB first */
+#define __ssi_set_msb() ( REG_SSI_CR1 &= ~SSI_CR1_LFST )
+#define __ssi_set_lsb() ( REG_SSI_CR1 |= SSI_CR1_LFST )
+
+#define __ssi_set_frame_length(n) \
+ REG_SSI_CR1 = (REG_SSI_CR1 & ~SSI_CR1_FLEN_MASK) | (((n) - 2) << 4)
+
+/* n = 1 - 16 */
+#define __ssi_set_microwire_command_length(n) \
+ ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_MCOM_MASK) | SSI_CR1_MCOM_##n##BIT) )
+
+/* Set the clock phase for SPI */
+#define __ssi_set_spi_clock_phase(n) \
+ ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_PHA) | (n&0x1)) )
+
+/* Set the clock polarity for SPI */
+#define __ssi_set_spi_clock_polarity(n) \
+ ( REG_SSI_CR1 = ((REG_SSI_CR1 & ~SSI_CR1_POL) | (n&0x1)) )
+
+/* n = ix8 */
+#define __ssi_set_tx_trigger(n) \
+do { \
+ REG_SSI_CR1 &= ~SSI_CR1_TTRG_MASK; \
+ REG_SSI_CR1 |= SSI_CR1_TTRG_##n; \
+} while (0)
+
+/* n = ix8 */
+#define __ssi_set_rx_trigger(n) \
+do { \
+ REG_SSI_CR1 &= ~SSI_CR1_RTRG_MASK; \
+ REG_SSI_CR1 |= SSI_CR1_RTRG_##n; \
+} while (0)
+
+#define __ssi_get_txfifo_count() \
+ ( (REG_SSI_SR & SSI_SR_TFIFONUM_MASK) >> SSI_SR_TFIFONUM_BIT )
+
+#define __ssi_get_rxfifo_count() \
+ ( (REG_SSI_SR & SSI_SR_RFIFONUM_MASK) >> SSI_SR_RFIFONUM_BIT )
+
+#define __ssi_clear_errors() \
+ ( REG_SSI_SR &= ~(SSI_SR_UNDR | SSI_SR_OVER) )
+
+#define __ssi_transfer_end() ( REG_SSI_SR & SSI_SR_END )
+#define __ssi_is_busy() ( REG_SSI_SR & SSI_SR_BUSY )
+
+#define __ssi_txfifo_full() ( REG_SSI_SR & SSI_SR_TFF )
+#define __ssi_rxfifo_empty() ( REG_SSI_SR & SSI_SR_RFE )
+#define __ssi_rxfifo_noempty() ( REG_SSI_SR & SSI_SR_RFHF )
+
+#define __ssi_set_clk(dev_clk, ssi_clk) \
+ ( REG_SSI_GR = (dev_clk) / (2*(ssi_clk)) - 1 )
+
+#define __ssi_receive_data() REG_SSI_DR
+#define __ssi_transmit_data(v) ( REG_SSI_DR = (v) )
+
+
+/***************************************************************************
+ * CIM
+ ***************************************************************************/
+
+#define __cim_enable() ( REG_CIM_CTRL |= CIM_CTRL_ENA )
+#define __cim_disable() ( REG_CIM_CTRL &= ~CIM_CTRL_ENA )
+
+#define __cim_input_data_inverse() ( REG_CIM_CFG |= CIM_CFG_INV_DAT )
+#define __cim_input_data_normal() ( REG_CIM_CFG &= ~CIM_CFG_INV_DAT )
+
+#define __cim_vsync_active_low() ( REG_CIM_CFG |= CIM_CFG_VSP )
+#define __cim_vsync_active_high() ( REG_CIM_CFG &= ~CIM_CFG_VSP )
+
+#define __cim_hsync_active_low() ( REG_CIM_CFG |= CIM_CFG_HSP )
+#define __cim_hsync_active_high() ( REG_CIM_CFG &= ~CIM_CFG_HSP )
+
+#define __cim_sample_data_at_pclk_falling_edge() \
+ ( REG_CIM_CFG |= CIM_CFG_PCP )
+#define __cim_sample_data_at_pclk_rising_edge() \
+ ( REG_CIM_CFG &= ~CIM_CFG_PCP )
+
+#define __cim_enable_dummy_zero() ( REG_CIM_CFG |= CIM_CFG_DUMMY_ZERO )
+#define __cim_disable_dummy_zero() ( REG_CIM_CFG &= ~CIM_CFG_DUMMY_ZERO )
+
+#define __cim_select_external_vsync() ( REG_CIM_CFG |= CIM_CFG_EXT_VSYNC )
+#define __cim_select_internal_vsync() ( REG_CIM_CFG &= ~CIM_CFG_EXT_VSYNC )
+
+/* n=0-7 */
+#define __cim_set_data_packing_mode(n) \
+do { \
+ REG_CIM_CFG &= ~CIM_CFG_PACK_MASK; \
+ REG_CIM_CFG |= (CIM_CFG_PACK_##n); \
+} while (0)
+
+#define __cim_enable_ccir656_progressive_mode() \
+do { \
+ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \
+ REG_CIM_CFG |= CIM_CFG_DSM_CPM; \
+} while (0)
+
+#define __cim_enable_ccir656_interlace_mode() \
+do { \
+ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \
+ REG_CIM_CFG |= CIM_CFG_DSM_CIM; \
+} while (0)
+
+#define __cim_enable_gated_clock_mode() \
+do { \
+ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \
+ REG_CIM_CFG |= CIM_CFG_DSM_GCM; \
+} while (0)
+
+#define __cim_enable_nongated_clock_mode() \
+do { \
+ REG_CIM_CFG &= ~CIM_CFG_DSM_MASK; \
+ REG_CIM_CFG |= CIM_CFG_DSM_NGCM; \
+} while (0)
+
+/* sclk:system bus clock
+ * mclk: CIM master clock
+ */
+#define __cim_set_master_clk(sclk, mclk) \
+do { \
+ REG_CIM_CTRL &= ~CIM_CTRL_MCLKDIV_MASK; \
+ REG_CIM_CTRL |= (((sclk)/(mclk) - 1) << CIM_CTRL_MCLKDIV_BIT); \
+} while (0)
+
+#define __cim_enable_sof_intr() \
+ ( REG_CIM_CTRL |= CIM_CTRL_DMA_SOFM )
+#define __cim_disable_sof_intr() \
+ ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_SOFM )
+
+#define __cim_enable_eof_intr() \
+ ( REG_CIM_CTRL |= CIM_CTRL_DMA_EOFM )
+#define __cim_disable_eof_intr() \
+ ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_EOFM )
+
+#define __cim_enable_stop_intr() \
+ ( REG_CIM_CTRL |= CIM_CTRL_DMA_STOPM )
+#define __cim_disable_stop_intr() \
+ ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_STOPM )
+
+#define __cim_enable_trig_intr() \
+ ( REG_CIM_CTRL |= CIM_CTRL_RXF_TRIGM )
+#define __cim_disable_trig_intr() \
+ ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_TRIGM )
+
+#define __cim_enable_rxfifo_overflow_intr() \
+ ( REG_CIM_CTRL |= CIM_CTRL_RXF_OFM )
+#define __cim_disable_rxfifo_overflow_intr() \
+ ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_OFM )
+
+/* n=1-16 */
+#define __cim_set_frame_rate(n) \
+do { \
+ REG_CIM_CTRL &= ~CIM_CTRL_FRC_MASK; \
+ REG_CIM_CTRL |= CIM_CTRL_FRC_##n; \
+} while (0)
+
+#define __cim_enable_dma() ( REG_CIM_CTRL |= CIM_CTRL_DMA_EN )
+#define __cim_disable_dma() ( REG_CIM_CTRL &= ~CIM_CTRL_DMA_EN )
+
+#define __cim_reset_rxfifo() ( REG_CIM_CTRL |= CIM_CTRL_RXF_RST )
+#define __cim_unreset_rxfifo() ( REG_CIM_CTRL &= ~CIM_CTRL_RXF_RST )
+
+/* n=4,8,12,16,20,24,28,32 */
+#define __cim_set_rxfifo_trigger(n) \
+do { \
+ REG_CIM_CTRL &= ~CIM_CTRL_RXF_TRIG_MASK; \
+ REG_CIM_CTRL |= CIM_CTRL_RXF_TRIG_##n; \
+} while (0)
+
+#define __cim_clear_state() ( REG_CIM_STATE = 0 )
+
+#define __cim_disable_done() ( REG_CIM_STATE & CIM_STATE_VDD )
+#define __cim_rxfifo_empty() ( REG_CIM_STATE & CIM_STATE_RXF_EMPTY )
+#define __cim_rxfifo_reach_trigger() ( REG_CIM_STATE & CIM_STATE_RXF_TRIG )
+#define __cim_rxfifo_overflow() ( REG_CIM_STATE & CIM_STATE_RXF_OF )
+#define __cim_clear_rxfifo_overflow() ( REG_CIM_STATE &= ~CIM_STATE_RXF_OF )
+#define __cim_dma_stop() ( REG_CIM_STATE & CIM_STATE_DMA_STOP )
+#define __cim_dma_eof() ( REG_CIM_STATE & CIM_STATE_DMA_EOF )
+#define __cim_dma_sof() ( REG_CIM_STATE & CIM_STATE_DMA_SOF )
+
+#define __cim_get_iid() ( REG_CIM_IID )
+#define __cim_get_image_data() ( REG_CIM_RXFIFO )
+#define __cim_get_dam_cmd() ( REG_CIM_CMD )
+
+#define __cim_set_da(a) ( REG_CIM_DA = (a) )
+
+/***************************************************************************
+ * LCD
+ ***************************************************************************/
+#define __lcd_as_smart_lcd() ( REG_LCD_CFG |= (1<<LCD_CFG_LCDPIN_BIT) )
+#define __lcd_as_general_lcd() ( REG_LCD_CFG &= ~(1<<LCD_CFG_LCDPIN_BIT) )
+
+#define __lcd_set_dis() ( REG_LCD_CTRL |= LCD_CTRL_DIS )
+#define __lcd_clr_dis() ( REG_LCD_CTRL &= ~LCD_CTRL_DIS )
+
+#define __lcd_set_ena() ( REG_LCD_CTRL |= LCD_CTRL_ENA )
+#define __lcd_clr_ena() ( REG_LCD_CTRL &= ~LCD_CTRL_ENA )
+
+/* n=1,2,4,8,16 */
+#define __lcd_set_bpp(n) \
+ ( REG_LCD_CTRL = (REG_LCD_CTRL & ~LCD_CTRL_BPP_MASK) | LCD_CTRL_BPP_##n )
+
+/* n=4,8,16 */
+#define __lcd_set_burst_length(n) \
+do { \
+ REG_LCD_CTRL &= ~LCD_CTRL_BST_MASK; \
+ REG_LCD_CTRL |= LCD_CTRL_BST_n##; \
+} while (0)
+
+#define __lcd_select_rgb565() ( REG_LCD_CTRL &= ~LCD_CTRL_RGB555 )
+#define __lcd_select_rgb555() ( REG_LCD_CTRL |= LCD_CTRL_RGB555 )
+
+#define __lcd_set_ofup() ( REG_LCD_CTRL |= LCD_CTRL_OFUP )
+#define __lcd_clr_ofup() ( REG_LCD_CTRL &= ~LCD_CTRL_OFUP )
+
+/* n=2,4,16 */
+#define __lcd_set_stn_frc(n) \
+do { \
+ REG_LCD_CTRL &= ~LCD_CTRL_FRC_MASK; \
+ REG_LCD_CTRL |= LCD_CTRL_FRC_n##; \
+} while (0)
+
+
+#define __lcd_pixel_endian_little() ( REG_LCD_CTRL |= LCD_CTRL_PEDN )
+#define __lcd_pixel_endian_big() ( REG_LCD_CTRL &= ~LCD_CTRL_PEDN )
+
+#define __lcd_reverse_byte_endian() ( REG_LCD_CTRL |= LCD_CTRL_BEDN )
+#define __lcd_normal_byte_endian() ( REG_LCD_CTRL &= ~LCD_CTRL_BEDN )
+
+#define __lcd_enable_eof_intr() ( REG_LCD_CTRL |= LCD_CTRL_EOFM )
+#define __lcd_disable_eof_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_EOFM )
+
+#define __lcd_enable_sof_intr() ( REG_LCD_CTRL |= LCD_CTRL_SOFM )
+#define __lcd_disable_sof_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_SOFM )
+
+#define __lcd_enable_ofu_intr() ( REG_LCD_CTRL |= LCD_CTRL_OFUM )
+#define __lcd_disable_ofu_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_OFUM )
+
+#define __lcd_enable_ifu0_intr() ( REG_LCD_CTRL |= LCD_CTRL_IFUM0 )
+#define __lcd_disable_ifu0_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_IFUM0 )
+
+#define __lcd_enable_ifu1_intr() ( REG_LCD_CTRL |= LCD_CTRL_IFUM1 )
+#define __lcd_disable_ifu1_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_IFUM1 )
+
+#define __lcd_enable_ldd_intr() ( REG_LCD_CTRL |= LCD_CTRL_LDDM )
+#define __lcd_disable_ldd_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_LDDM )
+
+#define __lcd_enable_qd_intr() ( REG_LCD_CTRL |= LCD_CTRL_QDM )
+#define __lcd_disable_qd_intr() ( REG_LCD_CTRL &= ~LCD_CTRL_QDM )
+
+
+/* LCD status register indication */
+
+#define __lcd_quick_disable_done() ( REG_LCD_STATE & LCD_STATE_QD )
+#define __lcd_disable_done() ( REG_LCD_STATE & LCD_STATE_LDD )
+#define __lcd_infifo0_underrun() ( REG_LCD_STATE & LCD_STATE_IFU0 )
+#define __lcd_infifo1_underrun() ( REG_LCD_STATE & LCD_STATE_IFU1 )
+#define __lcd_outfifo_underrun() ( REG_LCD_STATE & LCD_STATE_OFU )
+#define __lcd_start_of_frame() ( REG_LCD_STATE & LCD_STATE_SOF )
+#define __lcd_end_of_frame() ( REG_LCD_STATE & LCD_STATE_EOF )
+
+#define __lcd_clr_outfifounderrun() ( REG_LCD_STATE &= ~LCD_STATE_OFU )
+#define __lcd_clr_sof() ( REG_LCD_STATE &= ~LCD_STATE_SOF )
+#define __lcd_clr_eof() ( REG_LCD_STATE &= ~LCD_STATE_EOF )
+
+#define __lcd_panel_white() ( REG_LCD_CFG |= LCD_CFG_WHITE )
+#define __lcd_panel_black() ( REG_LCD_CFG &= ~LCD_CFG_WHITE )
+
+/* n=1,2,4,8 for single mono-STN
+ * n=4,8 for dual mono-STN
+ */
+#define __lcd_set_panel_datawidth(n) \
+do { \
+ REG_LCD_CFG &= ~LCD_CFG_PDW_MASK; \
+ REG_LCD_CFG |= LCD_CFG_PDW_n##; \
+} while (0)
+
+/* m=LCD_CFG_MODE_GENERUIC_TFT_xxx */
+#define __lcd_set_panel_mode(m) \
+do { \
+ REG_LCD_CFG &= ~LCD_CFG_MODE_MASK; \
+ REG_LCD_CFG |= (m); \
+} while(0)
+
+/* n = 0-255 */
+#define __lcd_disable_ac_bias() ( REG_LCD_IO = 0xff )
+#define __lcd_set_ac_bias(n) \
+do { \
+ REG_LCD_IO &= ~LCD_IO_ACB_MASK; \
+ REG_LCD_IO |= ((n) << LCD_IO_ACB_BIT); \
+} while(0)
+
+#define __lcd_io_set_dir() ( REG_LCD_IO |= LCD_IO_DIR )
+#define __lcd_io_clr_dir() ( REG_LCD_IO &= ~LCD_IO_DIR )
+
+#define __lcd_io_set_dep() ( REG_LCD_IO |= LCD_IO_DEP )
+#define __lcd_io_clr_dep() ( REG_LCD_IO &= ~LCD_IO_DEP )
+
+#define __lcd_io_set_vsp() ( REG_LCD_IO |= LCD_IO_VSP )
+#define __lcd_io_clr_vsp() ( REG_LCD_IO &= ~LCD_IO_VSP )
+
+#define __lcd_io_set_hsp() ( REG_LCD_IO |= LCD_IO_HSP )
+#define __lcd_io_clr_hsp() ( REG_LCD_IO &= ~LCD_IO_HSP )
+
+#define __lcd_io_set_pcp() ( REG_LCD_IO |= LCD_IO_PCP )
+#define __lcd_io_clr_pcp() ( REG_LCD_IO &= ~LCD_IO_PCP )
+
+#define __lcd_vsync_get_vps() \
+ ( (REG_LCD_VSYNC & LCD_VSYNC_VPS_MASK) >> LCD_VSYNC_VPS_BIT )
+
+#define __lcd_vsync_get_vpe() \
+ ( (REG_LCD_VSYNC & LCD_VSYNC_VPE_MASK) >> LCD_VSYNC_VPE_BIT )
+#define __lcd_vsync_set_vpe(n) \
+do { \
+ REG_LCD_VSYNC &= ~LCD_VSYNC_VPE_MASK; \
+ REG_LCD_VSYNC |= (n) << LCD_VSYNC_VPE_BIT; \
+} while (0)
+
+#define __lcd_hsync_get_hps() \
+ ( (REG_LCD_HSYNC & LCD_HSYNC_HPS_MASK) >> LCD_HSYNC_HPS_BIT )
+#define __lcd_hsync_set_hps(n) \
+do { \
+ REG_LCD_HSYNC &= ~LCD_HSYNC_HPS_MASK; \
+ REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPS_BIT; \
+} while (0)
+
+#define __lcd_hsync_get_hpe() \
+ ( (REG_LCD_HSYNC & LCD_HSYNC_HPE_MASK) >> LCD_VSYNC_HPE_BIT )
+#define __lcd_hsync_set_hpe(n) \
+do { \
+ REG_LCD_HSYNC &= ~LCD_HSYNC_HPE_MASK; \
+ REG_LCD_HSYNC |= (n) << LCD_HSYNC_HPE_BIT; \
+} while (0)
+
+#define __lcd_vat_get_ht() \
+ ( (REG_LCD_VAT & LCD_VAT_HT_MASK) >> LCD_VAT_HT_BIT )
+#define __lcd_vat_set_ht(n) \
+do { \
+ REG_LCD_VAT &= ~LCD_VAT_HT_MASK; \
+ REG_LCD_VAT |= (n) << LCD_VAT_HT_BIT; \
+} while (0)
+
+#define __lcd_vat_get_vt() \
+ ( (REG_LCD_VAT & LCD_VAT_VT_MASK) >> LCD_VAT_VT_BIT )
+#define __lcd_vat_set_vt(n) \
+do { \
+ REG_LCD_VAT &= ~LCD_VAT_VT_MASK; \
+ REG_LCD_VAT |= (n) << LCD_VAT_VT_BIT; \
+} while (0)
+
+#define __lcd_dah_get_hds() \
+ ( (REG_LCD_DAH & LCD_DAH_HDS_MASK) >> LCD_DAH_HDS_BIT )
+#define __lcd_dah_set_hds(n) \
+do { \
+ REG_LCD_DAH &= ~LCD_DAH_HDS_MASK; \
+ REG_LCD_DAH |= (n) << LCD_DAH_HDS_BIT; \
+} while (0)
+
+#define __lcd_dah_get_hde() \
+ ( (REG_LCD_DAH & LCD_DAH_HDE_MASK) >> LCD_DAH_HDE_BIT )
+#define __lcd_dah_set_hde(n) \
+do { \
+ REG_LCD_DAH &= ~LCD_DAH_HDE_MASK; \
+ REG_LCD_DAH |= (n) << LCD_DAH_HDE_BIT; \
+} while (0)
+
+#define __lcd_dav_get_vds() \
+ ( (REG_LCD_DAV & LCD_DAV_VDS_MASK) >> LCD_DAV_VDS_BIT )
+#define __lcd_dav_set_vds(n) \
+do { \
+ REG_LCD_DAV &= ~LCD_DAV_VDS_MASK; \
+ REG_LCD_DAV |= (n) << LCD_DAV_VDS_BIT; \
+} while (0)
+
+#define __lcd_dav_get_vde() \
+ ( (REG_LCD_DAV & LCD_DAV_VDE_MASK) >> LCD_DAV_VDE_BIT )
+#define __lcd_dav_set_vde(n) \
+do { \
+ REG_LCD_DAV &= ~LCD_DAV_VDE_MASK; \
+ REG_LCD_DAV |= (n) << LCD_DAV_VDE_BIT; \
+} while (0)
+
+#define __lcd_cmd0_set_sofint() ( REG_LCD_CMD0 |= LCD_CMD_SOFINT )
+#define __lcd_cmd0_clr_sofint() ( REG_LCD_CMD0 &= ~LCD_CMD_SOFINT )
+#define __lcd_cmd1_set_sofint() ( REG_LCD_CMD1 |= LCD_CMD_SOFINT )
+#define __lcd_cmd1_clr_sofint() ( REG_LCD_CMD1 &= ~LCD_CMD_SOFINT )
+
+#define __lcd_cmd0_set_eofint() ( REG_LCD_CMD0 |= LCD_CMD_EOFINT )
+#define __lcd_cmd0_clr_eofint() ( REG_LCD_CMD0 &= ~LCD_CMD_EOFINT )
+#define __lcd_cmd1_set_eofint() ( REG_LCD_CMD1 |= LCD_CMD_EOFINT )
+#define __lcd_cmd1_clr_eofint() ( REG_LCD_CMD1 &= ~LCD_CMD_EOFINT )
+
+#define __lcd_cmd0_set_pal() ( REG_LCD_CMD0 |= LCD_CMD_PAL )
+#define __lcd_cmd0_clr_pal() ( REG_LCD_CMD0 &= ~LCD_CMD_PAL )
+
+#define __lcd_cmd0_get_len() \
+ ( (REG_LCD_CMD0 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT )
+#define __lcd_cmd1_get_len() \
+ ( (REG_LCD_CMD1 & LCD_CMD_LEN_MASK) >> LCD_CMD_LEN_BIT )
+
+/***************************************************************************
+ * RTC ops
+ ***************************************************************************/
+
+#define __rtc_write_ready() ( REG_RTC_RCR & RTC_RCR_WRDY )
+#define __rtc_enabled() \
+do{ \
+ while(!__rtc_write_ready()); \
+ REG_RTC_RCR |= RTC_RCR_RTCE ; \
+}while(0) \
+
+#define __rtc_disabled() \
+do{ \
+ while(!__rtc_write_ready()); \
+ REG_RTC_RCR &= ~RTC_RCR_RTCE; \
+}while(0)
+#define __rtc_enable_alarm() \
+do{ \
+ while(!__rtc_write_ready()); \
+ REG_RTC_RCR |= RTC_RCR_AE; \
+}while(0)
+
+#define __rtc_disable_alarm() \
+do{ \
+ while(!__rtc_write_ready()); \
+ REG_RTC_RCR &= ~RTC_RCR_AE; \
+}while(0)
+
+#define __rtc_enable_alarm_irq() \
+do{ \
+ while(!__rtc_write_ready()); \
+ REG_RTC_RCR |= RTC_RCR_AIE; \
+}while(0)
+
+#define __rtc_disable_alarm_irq() \
+do{ \
+ while(!__rtc_write_ready()); \
+ REG_RTC_RCR &= ~RTC_RCR_AIE; \
+}while(0)
+#define __rtc_enable_Hz_irq() \
+do{ \
+ while(!__rtc_write_ready()); \
+ REG_RTC_RCR |= RTC_RCR_HZIE; \
+}while(0)
+
+#define __rtc_disable_Hz_irq() \
+do{ \
+ while(!__rtc_write_ready()); \
+ REG_RTC_RCR &= ~RTC_RCR_HZIE; \
+}while(0)
+#define __rtc_get_1Hz_flag() \
+do{ \
+ while(!__rtc_write_ready()); \
+ ((REG_RTC_RCR >> RTC_RCR_HZ) & 0x1); \
+}while(0)
+#define __rtc_clear_1Hz_flag() \
+do{ \
+ while(!__rtc_write_ready()); \
+ REG_RTC_RCR &= ~RTC_RCR_HZ; \
+}while(0)
+#define __rtc_get_alarm_flag() \
+do{ \
+ while(!__rtc_write_ready()); \
+ ((REG_RTC_RCR >> RTC_RCR_AF) & 0x1) \
+while(0)
+#define __rtc_clear_alarm_flag() \
+do{ \
+ while(!__rtc_write_ready()); \
+ REG_RTC_RCR &= ~RTC_RCR_AF; \
+}while(0)
+#define __rtc_get_second() \
+do{ \
+ while(!__rtc_write_ready());\
+ REG_RTC_RSR; \
+}while(0)
+
+#define __rtc_set_second(v) \
+do{ \
+ while(!__rtc_write_ready()); \
+ REG_RTC_RSR = v; \
+}while(0)
+
+#define __rtc_get_alarm_second() \
+do{ \
+ while(!__rtc_write_ready()); \
+ REG_RTC_RSAR; \
+}while(0)
+
+
+#define __rtc_set_alarm_second(v) \
+do{ \
+ while(!__rtc_write_ready()); \
+ REG_RTC_RSAR = v; \
+}while(0)
+
+#define __rtc_RGR_is_locked() \
+do{ \
+ while(!__rtc_write_ready()); \
+ REG_RTC_RGR >> RTC_RGR_LOCK; \
+}while(0)
+#define __rtc_lock_RGR() \
+do{ \
+ while(!__rtc_write_ready()); \
+ REG_RTC_RGR |= RTC_RGR_LOCK; \
+}while(0)
+
+#define __rtc_unlock_RGR() \
+do{ \
+ while(!__rtc_write_ready()); \
+ REG_RTC_RGR &= ~RTC_RGR_LOCK; \
+}while(0)
+
+#define __rtc_get_adjc_val() \
+do{ \
+ while(!__rtc_write_ready()); \
+ ( (REG_RTC_RGR & RTC_RGR_ADJC_MASK) >> RTC_RGR_ADJC_BIT ); \
+}while(0)
+#define __rtc_set_adjc_val(v) \
+do{ \
+ while(!__rtc_write_ready()); \
+ ( REG_RTC_RGR = ( (REG_RTC_RGR & ~RTC_RGR_ADJC_MASK) | (v << RTC_RGR_ADJC_BIT) )) \
+}while(0)
+
+#define __rtc_get_nc1Hz_val() \
+ while(!__rtc_write_ready()); \
+ ( (REG_RTC_RGR & RTC_RGR_NC1HZ_MASK) >> RTC_RGR_NC1HZ_BIT )
+
+#define __rtc_set_nc1Hz_val(v) \
+do{ \
+ while(!__rtc_write_ready()); \
+ ( REG_RTC_RGR = ( (REG_RTC_RGR & ~RTC_RGR_NC1HZ_MASK) | (v << RTC_RGR_NC1HZ_BIT) )) \
+}while(0)
+#define __rtc_power_down() \
+do{ \
+ while(!__rtc_write_ready()); \
+ REG_RTC_HCR |= RTC_HCR_PD; \
+}while(0)
+
+#define __rtc_get_hwfcr_val() \
+do{ \
+ while(!__rtc_write_ready()); \
+ REG_RTC_HWFCR & RTC_HWFCR_MASK; \
+}while(0)
+#define __rtc_set_hwfcr_val(v) \
+do{ \
+ while(!__rtc_write_ready()); \
+ REG_RTC_HWFCR = (v) & RTC_HWFCR_MASK; \
+}while(0)
+
+#define __rtc_get_hrcr_val() \
+do{ \
+ while(!__rtc_write_ready()); \
+ ( REG_RTC_HRCR & RTC_HRCR_MASK ); \
+}while(0)
+#define __rtc_set_hrcr_val(v) \
+do{ \
+ while(!__rtc_write_ready()); \
+ ( REG_RTC_HRCR = (v) & RTC_HRCR_MASK ); \
+}while(0)
+
+#define __rtc_enable_alarm_wakeup() \
+do{ \
+ while(!__rtc_write_ready()); \
+ ( REG_RTC_HWCR |= RTC_HWCR_EALM ); \
+}while(0)
+
+#define __rtc_disable_alarm_wakeup() \
+do{ \
+ while(!__rtc_write_ready()); \
+ ( REG_RTC_HWCR &= ~RTC_HWCR_EALM ); \
+}while(0)
+
+#define __rtc_status_hib_reset_occur() \
+do{ \
+ while(!__rtc_write_ready()); \
+ ( (REG_RTC_HWRSR >> RTC_HWRSR_HR) & 0x1 ); \
+}while(0)
+#define __rtc_status_ppr_reset_occur() \
+do{ \
+ while(!__rtc_write_ready()); \
+ ( (REG_RTC_HWRSR >> RTC_HWRSR_PPR) & 0x1 ); \
+}while(0)
+#define __rtc_status_wakeup_pin_waken_up() \
+do{ \
+ while(!__rtc_write_ready()); \
+ ( (REG_RTC_HWRSR >> RTC_HWRSR_PIN) & 0x1 ); \
+}while(0)
+#define __rtc_status_alarm_waken_up() \
+do{ \
+ while(!__rtc_write_ready()); \
+ ( (REG_RTC_HWRSR >> RTC_HWRSR_ALM) & 0x1 ); \
+}while(0)
+#define __rtc_clear_hib_stat_all() \
+do{ \
+ while(!__rtc_write_ready()); \
+ ( REG_RTC_HWRSR = 0 ); \
+}while(0)
+
+#define __rtc_get_scratch_pattern() \
+ while(!__rtc_write_ready()); \
+ (REG_RTC_HSPR)
+#define __rtc_set_scratch_pattern(n) \
+do{ \
+ while(!__rtc_write_ready()); \
+ (REG_RTC_HSPR = n ); \
+}while(0)
+
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __JZ4740_H__ */
diff --git a/package/uboot-xburst/files/include/configs/avt2.h b/package/uboot-xburst/files/include/configs/avt2.h
new file mode 100644
index 000000000..cbf34d720
--- /dev/null
+++ b/package/uboot-xburst/files/include/configs/avt2.h
@@ -0,0 +1,26 @@
+#ifndef __CONFIG_AVT2_H
+#define __CONFIG_AVT2_H
+
+#include <configs/nanonote.h>
+
+#define CONFIG_AVT2 1
+
+#define CONFIG_BOOTARGS "mem=64M console=ttyS0,57600n8 ubi.mtd=2 rootfstype=ubifs root=ubi0:rootfs rw rootwait avt2=1"
+#define CONFIG_BOOTARGSFROMSD "mem=64M console=ttyS0,57600n8 rootfstype=ext2 root=/dev/mmcblk0p1 rw rootwait avt2=1"
+#define CONFIG_BOOTCOMMAND "nand read 0x80600000 0x400000 0x200000;bootm"
+
+/* SDRAM paramters */
+#define SDRAM_BW16 1 /* Data bus width: 0-32bit, 1-16bit */
+#define SDRAM_BANK4 1 /* Banks each chip: 0-2bank, 1-4bank */
+#define SDRAM_ROW 13 /* Row address: 11 to 13 */
+#define SDRAM_COL 10 /* Column address: 8 to 12 */
+#define SDRAM_CASL 2 /* CAS latency: 2 or 3 */
+
+/* SDRAM Timings, unit: ns */
+#define SDRAM_TRAS 45 /* RAS# Active Time */
+#define SDRAM_RCD 20 /* RAS# to CAS# Delay */
+#define SDRAM_TPC 20 /* RAS# Precharge Time */
+#define SDRAM_TRWL 7 /* Write Latency Time */
+#define SDRAM_TREF 15625 /* Refresh period: 8192 cycles/64ms */
+
+#endif /* __CONFIG_AVT_H */
diff --git a/package/uboot-xburst/files/include/configs/n516.h b/package/uboot-xburst/files/include/configs/n516.h
new file mode 100644
index 000000000..c741bfe6c
--- /dev/null
+++ b/package/uboot-xburst/files/include/configs/n516.h
@@ -0,0 +1,311 @@
+/*
+ * (C) Copyright 2006
+ * Ingenic Semiconductor, <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+/*
+ * This file contains the configuration parameters for the pavo board.
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+//#define DEBUG
+//#define DEBUG_SHELL
+
+#define CONFIG_MIPS32 1 /* MIPS32 CPU core */
+#define CONFIG_JzRISC 1 /* JzRISC core */
+#define CONFIG_JZSOC 1 /* Jz SoC */
+#define CONFIG_JZ4740 1 /* Jz4740 SoC */
+#define CONFIG_PAVO 1 /* PAVO validation board */
+
+#define CONFIG_BOARD_NAME "n516"
+#define CONFIG_BOARD_HWREV "1.0"
+#define CONFIG_FIRMWARE_EPOCH "0"
+#define CONFIG_UPDATE_TMPBUF 0x80600000
+#define CONFIG_UPDATE_CHUNKSIZE 0x800000
+#define CONFIG_UPDATE_FILENAME "update.oifw"
+#define CONFIG_UPDATE_FILEEXT ".oifw"
+#define CONFIG_UBI_PARTITION "UBI"
+
+#define CONFIG_SKIP_LOWLEVEL_INIT 1
+#undef CONFIG_SKIP_RELOCATE_UBOOT
+
+#if 0
+#define CONFIG_LCD /* LCD support */
+#define CONFIG_JZLCD_METRONOME_800x600
+#define LCD_BPP LCD_COLOR8
+
+#define WFM_DATA_SIZE ( 1 << 14 )
+#define CONFIG_METRONOME_WF_LEN (64 * (1 << 10))
+#define CONFIG_METRONOME_WF_NAND_OFFSET (0x100000)
+#define BMP_LOGO_HEIGHT 0
+#define CONFIG_UBI_WF_VOLUME "waveforms"
+#define CONFIG_UBI_BOOTSPLASH_VOLUME "bootsplash"
+#define CONFIG_METRONOME_BOOTSPLASH_LEN 480000
+#endif
+
+#if 0
+#define CONFIG_JZSOC_I2C
+#define CONFIG_HARD_I2C
+#define CONFIG_SYS_I2C_SPEED 100000
+#define CONFIG_SYS_I2C_SLAVE 0
+#define CONFIG_LPC_I2C_ADDR 0x54
+#endif
+
+#define JZ4740_NORBOOT_CFG JZ4740_NORBOOT_16BIT /* NOR Boot config code */
+#define JZ4740_NANDBOOT_CFG JZ4740_NANDBOOT_B8R3 /* NAND Boot config code */
+
+#define CONFIG_SYS_CPU_SPEED 336000000 /* CPU clock: 336 MHz */
+#define CONFIG_SYS_EXTAL 12000000 /* EXTAL freq: 12 MHz */
+#define CONFIG_SYS_HZ (CONFIG_SYS_EXTAL/256) /* incrementer freq */
+
+#define CONFIG_SYS_UART_BASE UART0_BASE /* Base of the UART channel */
+
+#define CONFIG_BAUDRATE 57600
+#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
+
+
+#define CONFIG_MMC 1
+#define CONFIG_GENERIC_MMC 1
+#define CONFIG_JZ_MMC 1
+#define CONFIG_FAT 1
+
+#define CONFIG_SYS_HUSH_PARSER
+#define CONFIG_SYS_PROMPT_HUSH_PS2 ">"
+#define CONFIG_CMDLINE_EDITING
+
+/* allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+
+#include <config_cmd_default.h>
+
+#undef CONFIG_CMD_BDI /* bdinfo */
+#undef CONFIG_CMD_FPGA
+#undef CONFIG_CMD_ECHO /* echo arguments */
+#undef CONFIG_CMD_FLASH /* flinfo, erase, protect */
+#undef CONFIG_CMD_FPGA /* FPGA configuration Support */
+#undef CONFIG_CMD_IMI /* iminfo */
+#undef CONFIG_CMD_ITEST /* Integer (and string) test */
+#undef CONFIG_CMD_LOADB /* loadb */
+#undef CONFIG_CMD_LOADS /* loads */
+#undef CONFIG_CMD_NFS /* NFS support */
+#undef CONFIG_CMD_SETGETDCR /* DCR support on 4xx */
+#undef CONFIG_CMD_SOURCE /* "source" command support */
+#undef CONFIG_CMD_XIMG /* Load part of Multi Image */
+#undef CONFIG_CMD_NET
+
+//#define CONFIG_CMD_ASKENV
+//#define CONFIG_CMD_DHCP
+//#define CONFIG_CMD_PING
+#define CONFIG_CMD_NAND
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_FAT
+/*#define CONFIG_CMD_UBI*/
+/*#define CONFIG_CMD_MTDPARTS*/
+//#define CONFIG_CMD_JFFS2
+//#define CONFIG_JFFS2_NAND
+//#define CONFIG_JFFS2_CMDLINE
+#define CONFIG_CMD_UPDATE
+
+#define CONFIG_DOS_PARTITION
+
+/*#define CONFIG_MTD_PARTITIONS*/
+#define CONFIG_RBTREE
+
+#define CONFIG_BOOTP_MASK ( CONFIG_BOOTP_DEFAUL )
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#if 0
+#define CONFIG_ZERO_BOOTDELAY_CHECK
+#define CONFIG_BOOTDELAY 0
+#define CONFIG_BOOTFILE uImage /* file to load */
+#define CONFIG_BOOTARGS "mem=64M console=ttyS0,57600n8 ip=off rootfstype=ubifs root=ubi:rootfs ubi.mtd=UBI rw panic=5 " MTDPARTS_DEFAULT
+#define CONFIG_BOOTCOMMAND "check_and_update; setenv bootargs $bootargs $batt_level_param; ubi read 0x80600000 bootsplash && show_image 0x80600000; ubi read 0x80600000 kernel; bootm 0x80600000; ubi read 0x80600000 errorsplash && show_image 0x80600000; while test 0 = 0; do check_and_update; done"
+#define CONFIG_SYS_AUTOLOAD "n" /* No autoload */
+#define CONFIG_IPADDR 192.168.111.1
+#define CONFIG_SERVERIP 192.168.111.2
+#define MTDIDS_DEFAULT "nand0=jz4740-nand"
+#define MTDPARTS_DEFAULT "mtdparts=jz4740-nand:1M@0(uboot)ro,-@1M(UBI)"
+#define CONFIG_EXTRA_ENV_SETTINGS "mtdids=nand0=jz4740-nand\0mtdparts=mtdparts=jz4740-nand:1M@0(uboot)ro,-@1M(UBI)\0" \
+ "stdout=serial\0stderr=lcd\0"
+#endif
+
+#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAUL)
+#define CONFIG_BOOTDELAY 0
+#define CONFIG_BOOTFILE "uImage" /* file to load */
+#define CONFIG_BOOTARGS "mem=64M console=ttyS0,57600n8 ubi.mtd=2 rootfstype=ubifs root=ubi0:rootfs rw rootwait"
+#define CONFIG_BOOTCOMMAND "nand read 0x80600000 0x400000 0x200000;bootm"
+
+
+
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+
+/*
+ * Serial download configuration
+ *
+ */
+#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */
+#define CONFIG_SYS_LOADS_BAUD_CHANGE 1 /* allow baudrate change */
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CONFIG_SYS_LONGHELP /* undef to save memory */
+#define CONFIG_SYS_PROMPT "n516 # " /* Monitor Command Prompt */
+#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */
+#define CONFIG_SYS_MAXARGS 16 /* max number of command args*/
+
+#define CONFIG_SYS_MALLOC_LEN 1024*1024*2
+#define CONFIG_SYS_BOOTPARAMS_LEN 128*1024
+
+#define CONFIG_SYS_SDRAM_BASE 0x80000000 /* Cached addr */
+
+#define CONFIG_SYS_INIT_SP_OFFSET 0x400000
+
+#define CONFIG_SYS_LOAD_ADDR 0x80600000 /* default load address */
+
+#define CONFIG_SYS_MEMTEST_START 0x80100000
+#define CONFIG_SYS_MEMTEST_END 0x80800000
+
+/*-----------------------------------------------------------------------
+ * Environment
+ *----------------------------------------------------------------------*/
+#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
+#define CONFIG_ENV_IS_IN_FLASH 1 /* use FLASH for environment vars */
+#else
+#define CONFIG_ENV_IS_IN_NAND 1 /* use NAND for environment vars */
+#endif
+
+/*-----------------------------------------------------------------------
+ * NAND FLASH configuration
+ */
+#define CONFIG_SYS_MAX_NAND_DEVICE 1
+#define NAND_MAX_CHIPS 1
+#define CONFIG_SYS_NAND_BASE 0xB8000000
+#define CONFIG_SYS_NAND_SELECT_DEVICE 1 /* nand driver supports mutipl. chips */
+
+/*
+ * IPL (Initial Program Loader, integrated inside CPU)
+ * Will load first 8k from NAND (SPL) into cache and execute it from there.
+ *
+ * SPL (Secondary Program Loader)
+ * Will load special U-Boot version (NUB) from NAND and execute it. This SPL
+ * has to fit into 8kByte. It sets up the CPU and configures the SDRAM
+ * controller and the NAND controller so that the special U-Boot image can be
+ * loaded from NAND to SDRAM.
+ *
+ * NUB (NAND U-Boot)
+ * This NAND U-Boot (NUB) is a special U-Boot version which can be started
+ * from RAM. Therefore it mustn't (re-)configure the SDRAM controller.
+ *
+ */
+#define CONFIG_SYS_NAND_U_BOOT_DST 0x80100000 /* Load NUB to this addr */
+#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_NAND_U_BOOT_DST /* Start NUB from this addr */
+
+/*
+ * Define the partitioning of the NAND chip (only RAM U-Boot is needed here)
+ */
+#define CONFIG_SYS_NAND_U_BOOT_OFFS (256 << 10) /* Offset to RAM U-Boot image */
+#define CONFIG_SYS_NAND_U_BOOT_SIZE (512 << 10) /* Size of RAM U-Boot image */
+
+#define CONFIG_SYS_NAND_PAGE_SIZE 2048
+#define CONFIG_SYS_NAND_BLOCK_SIZE (128 << 10) /* NAND chip block size */
+#define CONFIG_SYS_NAND_BADBLOCK_PAGE 63 /* NAND bad block was marked at this page in a block, starting from 0 */
+#define CONFIG_SYS_NAND_ECC_POS 6
+
+#ifdef CONFIG_ENV_IS_IN_NAND
+//#define CONFIG_ENV_SIZE CONFIG_SYS_NAND_BLOCK_SIZE
+#define CONFIG_ENV_SIZE (128 * 1024)
+//#define CONFIG_ENV_OFFSET (CONFIG_SYS_NAND_BLOCK_SIZE + CONFIG_SYS_NAND_U_BOOT_SIZE + CONFIG_SYS_NAND_BLOCK_SIZE) /* environment starts here */
+#define CONFIG_ENV_OFFSET (CONFIG_SYS_NAND_U_BOOT_SIZE + CONFIG_SYS_NAND_U_BOOT_OFFS)
+//#define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
+#endif
+
+
+/*-----------------------------------------------------------------------
+ * NOR FLASH and environment organization
+ */
+#define CONFIG_SYS_MAX_FLASH_BANKS 1 /* max number of memory banks */
+#define CONFIG_SYS_MAX_FLASH_SECT (128) /* max number of sectors on one chip */
+
+#define PHYS_FLASH_1 0xa8000000 /* Flash Bank #1 */
+
+/* The following #defines are needed to get flash environment right */
+#define CONFIG_SYS_MONITOR_BASE TEXT_BASE /* in pavo/config.mk TEXT_BASE=0x88000000*/
+#define CONFIG_SYS_SYS_MONITOR_BASE TEXT_BASE /* in pavo/config.mk TEXT_BASE=0x88000000*/
+#define CONFIG_SYS_MONITOR_LEN (256*1024) /* Reserve 256 kB for Monitor */
+
+#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
+
+/* timeout values are in ticks */
+#define CONFIG_SYS_FLASH_ERASE_TOUT (2 * CONFIG_SYS_HZ) /* Timeout for Flash Erase */
+#define CONFIG_SYS_FLASH_WRITE_TOUT (2 * CONFIG_SYS_HZ) /* Timeout for Flash Write */
+
+#ifdef CONFIG_ENV_IS_IN_FLASH
+#define CONFIG_ENV_IS_NOWHERE 1
+#define CONFIG_ENV_ADDR 0xa8040000
+#define CONFIG_ENV_SIZE 0x20000
+#endif
+
+/*-----------------------------------------------------------------------
+ * SDRAM Info.
+ */
+#define CONFIG_NR_DRAM_BANKS 1
+
+// SDRAM paramters
+#define SDRAM_BW16 0 /* Data bus width: 0-32bit, 1-16bit */
+#define SDRAM_BANK4 1 /* Banks each chip: 0-2bank, 1-4bank */
+#define SDRAM_ROW 13 /* Row address: 11 to 13 */
+#define SDRAM_COL 9 /* Column address: 8 to 12 */
+#define SDRAM_CASL 2 /* CAS latency: 2 or 3 */
+
+// SDRAM Timings, unit: ns
+#define SDRAM_TRAS 45 /* RAS# Active Time */
+#define SDRAM_RCD 20 /* RAS# to CAS# Delay */
+#define SDRAM_TPC 20 /* RAS# Precharge Time */
+#define SDRAM_TRWL 7 /* Write Latency Time */
+#define SDRAM_TREF 15625 /* Refresh period: 4096 refresh cycles/64ms */
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CONFIG_SYS_DCACHE_SIZE 16384
+#define CONFIG_SYS_ICACHE_SIZE 16384
+#define CONFIG_SYS_CACHELINE_SIZE 32
+
+/*-----------------------------------------------------------------------
+ * GPIO definition
+ */
+#define GPIO_SD_VCC_EN_N 113 /* GPD17 */
+#define GPIO_SD_CD_N 103 /* GPD7 */
+#define GPIO_SD_WP 111 /* GPD15 */
+#define GPIO_USB_DETE 115 /* GPD6 */
+//#define GPIO_DC_DETE_N 103 /* GPD7 */
+#define GPIO_CHARG_STAT_N 112 /* GPD15 */
+#define GPIO_DISP_OFF_N 97 /* GPD1 */
+#define GPIO_UDC_HOTPLUG 100 /* GPD4 */
+#define GPIO_LED_EN 124 /* GPD28 */
+
+#define GPIO_RST_L 50 /* GPB18 LCD_SPL */
+#define GPIO_LCDRDY 49 /* GPB17 LCD_CLS */
+#define GPIO_STBY 86 /* GPC22 LCD_PS */
+#define GPIO_ERR 87 /* GPC23 LCD_REV */
+
+#endif /* __CONFIG_H */
diff --git a/package/uboot-xburst/files/include/configs/nanonote.h b/package/uboot-xburst/files/include/configs/nanonote.h
new file mode 100644
index 000000000..8926877ab
--- /dev/null
+++ b/package/uboot-xburst/files/include/configs/nanonote.h
@@ -0,0 +1,191 @@
+/*
+ * Authors: Xiangfu Liu <xiangfu.z@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 3 of the License, or (at your option) any later version.
+ */
+
+/*
+ * This file contains the configuration parameters for the NanoNote.
+ */
+#ifndef __CONFIG_NANONOTE_H
+#define __CONFIG_NANONOTE_H
+
+#define CONFIG_MIPS32 1 /* MIPS32 CPU core */
+#define CONFIG_JzRISC 1 /* JzRISC core */
+#define CONFIG_JZSOC 1 /* Jz SoC */
+#define CONFIG_JZ4740 1 /* Jz4740 SoC */
+#define CONFIG_NANONOTE 1
+
+#define CONFIG_LCD 1 /* LCD support */
+#define LCD_BPP LCD_COLOR32 /*5:18,24,32 bits per pixel */
+#define CONFIG_SYS_WHITE_ON_BLACK 1
+
+#define CONFIG_SYS_CPU_SPEED 336000000 /* CPU clock: 336 MHz */
+#define CONFIG_SYS_EXTAL 12000000 /* EXTAL freq: 12 MHz */
+#define CONFIG_SYS_HZ (CONFIG_SYS_EXTAL / 256) /* incrementer freq */
+#define CONFIG_SYS_MIPS_TIMER_FREQ CONFIG_SYS_CPU_SPEED
+
+#define CONFIG_SYS_UART_BASE UART0_BASE /* Base of the UART channel */
+#define CONFIG_BAUDRATE 57600
+#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
+
+#define CONFIG_MMC 1
+#define CONFIG_FAT 1
+#define CONFIG_DOS_PARTITION 1
+#define CONFIG_SKIP_LOWLEVEL_INIT 1
+#define CONFIG_BOARD_EARLY_INIT_F 1
+#define CONFIG_SYS_NO_FLASH 1
+#define CONFIG_ENV_OVERWRITE 1
+
+#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAUL)
+#define CONFIG_BOOTDELAY 0
+#define CONFIG_BOOTFILE "uImage" /* file to load */
+/*
+ * Command line configuration.
+ */
+#define CONFIG_CMD_BOOTD /* bootd */
+#define CONFIG_CMD_CONSOLE /* coninfo */
+#define CONFIG_CMD_ECHO /* echo arguments */
+
+#define CONFIG_CMD_LOADB /* loadb */
+#define CONFIG_CMD_LOADS /* loads */
+#define CONFIG_CMD_MEMORY /* md mm nm mw cp cmp crc base loop mtest */
+#define CONFIG_CMD_MISC /* Misc functions like sleep etc*/
+#define CONFIG_CMD_RUN /* run command in env variable */
+#define CONFIG_CMD_SAVEENV /* saveenv */
+#define CONFIG_CMD_SETGETDCR /* DCR support on 4xx */
+#define CONFIG_CMD_SOURCE /* "source" command support */
+
+#define CONFIG_CMD_NAND
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_FAT
+
+/*
+ * Serial download configuration
+ */
+#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */
+#define CONFIG_LOADS_BAUD_CHANGE 1 /* allow baudrate change */
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CONFIG_SYS_LONGHELP /* undef to save memory */
+#define CONFIG_SYS_PROMPT "QI# " /* Monitor Command Prompt */
+#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+/* Print Buffer Size */
+#define CONFIG_SYS_MAXARGS 16 /* max number of command args*/
+
+#define CONFIG_SYS_MALLOC_LEN 896 * 1024
+#define CONFIG_SYS_BOOTPARAMS_LEN 128 * 1024
+
+#define CONFIG_SYS_SDRAM_BASE 0x80000000 /* Cached addr */
+#define CONFIG_SYS_INIT_SP_OFFSET 0x400000
+#define CONFIG_SYS_LOAD_ADDR 0x80600000 /* default load address */
+#define CONFIG_SYS_MEMTEST_START 0x80100000
+#define CONFIG_SYS_MEMTEST_END 0x80800000
+
+/*
+ * Environment
+ */
+#define CONFIG_ENV_IS_IN_NAND 1 /* use NAND for environment vars */
+
+/*
+ * NAND FLASH configuration
+ */
+/* NAND Boot config code */
+#define JZ4740_NANDBOOT_CFG JZ4740_NANDBOOT_B8R3
+
+#define NANONOTE_NAND_SIZE 2 /* if board nand flash is 1GB, set to 1
+ * if board nand flash is 2GB, set to 2
+ * for change the PAGE_SIZE and BLOCK_SIZE
+ * will delete when there is no 1GB flash
+ */
+
+#define CONFIG_SYS_NAND_PAGE_SIZE (2048 * NANONOTE_NAND_SIZE)
+/* nand chip block size */
+#define CONFIG_SYS_NAND_BLOCK_SIZE (256 * NANONOTE_NAND_SIZE << 10)
+/* nand bad block was marked at this page in a block, start from 0 */
+#define CONFIG_SYS_NAND_BADBLOCK_PAGE 127
+/* ECC offset position in oob area, default value is 6 if it isn't defined */
+#define CONFIG_SYS_NAND_ECC_POS (6 * NANONOTE_NAND_SIZE)
+#define CONFIG_SYS_MAX_NAND_DEVICE 1
+#define NAND_MAX_CHIPS 1
+#define CONFIG_SYS_NAND_BASE 0xB8000000
+#define CONFIG_SYS_NAND_SELECT_DEVICE 1 /* nand driver supports mutipl.*/
+#define CONFIG_SYS_ONENAND_BASE CONFIG_SYS_NAND_BASE
+
+/*
+ * IPL (Initial Program Loader, integrated inside CPU)
+ * Will load first 8k from NAND (SPL) into cache and execute it from there.
+ *
+ * SPL (Secondary Program Loader)
+ * Will load special U-Boot version (NUB) from NAND and execute it. This SPL
+ * has to fit into 8kByte. It sets up the CPU and configures the SDRAM
+ * controller and the NAND controller so that the special U-Boot image can be
+ * loaded from NAND to SDRAM.
+ *
+ * NUB (NAND U-Boot)
+ * This NAND U-Boot (NUB) is a special U-Boot version which can be started
+ * from RAM. Therefore it mustn't (re-)configure the SDRAM controller.
+ *
+ */
+#define CONFIG_SYS_NAND_U_BOOT_DST 0x80100000 /* Load NUB to this addr */
+#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_NAND_U_BOOT_DST
+/* Start NUB from this addr*/
+
+/*
+ * Define the partitioning of the NAND chip (only RAM U-Boot is needed here)
+ */
+#define CONFIG_SYS_NAND_U_BOOT_OFFS (256 << 10) /* Offset to RAM U-Boot image */
+#define CONFIG_SYS_NAND_U_BOOT_SIZE (512 << 10) /* Size of RAM U-Boot image */
+
+#define CONFIG_ENV_SIZE CONFIG_SYS_NAND_BLOCK_SIZE
+#define CONFIG_ENV_OFFSET (CONFIG_SYS_NAND_BLOCK_SIZE + CONFIG_SYS_NAND_U_BOOT_SIZE + CONFIG_SYS_NAND_BLOCK_SIZE)
+/* environment starts here */
+#define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
+
+/* in board/nanonote/config.mk TEXT_BAS = 0x88000000 */
+#define CONFIG_SYS_MONITOR_BASE TEXT_BASE
+
+/*
+ * SDRAM Info.
+ */
+#define CONFIG_NR_DRAM_BANKS 1
+
+/*
+ * Cache Configuration
+ */
+#define CONFIG_SYS_DCACHE_SIZE 16384
+#define CONFIG_SYS_ICACHE_SIZE 16384
+#define CONFIG_SYS_CACHELINE_SIZE 32
+
+/*
+ * GPIO definition
+ */
+#define GPIO_LCD_CS (2 * 32 + 21)
+#define GPIO_DISP_OFF_N (3 * 32 + 21)
+#define GPIO_PWM (3 * 32 + 27)
+
+#define GPIO_AMP_EN (3 * 32 + 4)
+
+#define GPIO_SDPW_EN (3 * 32 + 2)
+#define GPIO_SD_DETECT (3 * 32 + 0)
+
+#define GPIO_USB_DETECT (3 * 32 + 27)
+#define GPIO_BUZZ_PWM (3 * 32 + 28)
+
+#define GPIO_AUDIO_POP (1 * 32 + 29)
+#define GPIO_COB_TEST (1 * 32 + 30)
+
+#define GPIO_KEYOUT_BASE (2 * 32 + 10)
+#define GPIO_KEYIN_BASE (3 * 32 + 18)
+#define GPIO_KEYIN_8 (3 * 32 + 26)
+
+#define GPIO_SD_CD_N GPIO_SD_DETECT /* SD Card insert detect */
+#define GPIO_SD_VCC_EN_N GPIO_SDPW_EN /* SD Card Power Enable */
+
+#endif /* __CONFIG_NANONOTE_H */
diff --git a/package/uboot-xburst/files/include/configs/qi_lb60.h b/package/uboot-xburst/files/include/configs/qi_lb60.h
new file mode 100644
index 000000000..1542c3dd6
--- /dev/null
+++ b/package/uboot-xburst/files/include/configs/qi_lb60.h
@@ -0,0 +1,27 @@
+#ifndef __CONFIG_QI_LB60_H
+#define __CONFIG_QI_LB60_H
+
+#include <configs/nanonote.h>
+
+#define CONFIG_QI_LB60 1
+
+#define CONFIG_BOOTARGS "mem=32M console=ttyS0,57600n8 ubi.mtd=2 rootfstype=ubifs root=ubi0:rootfs rw rootwait"
+#define CONFIG_BOOTARGSFROMSD "mem=32M console=ttyS0,57600n8 rootfstype=ext2 root=/dev/mmcblk0p2 rw rootwait"
+#define CONFIG_BOOTCOMMAND "nand read 0x80600000 0x400000 0x200000;bootm"
+#define CONFIG_BOOTCOMMANDFROMSD "mmc init; fatload mmc 0 0x80600000 uImage; bootm"
+
+/* SDRAM paramters */
+#define SDRAM_BW16 1 /* Data bus width: 0-32bit, 1-16bit */
+#define SDRAM_BANK4 1 /* Banks each chip: 0-2bank, 1-4bank */
+#define SDRAM_ROW 13 /* Row address: 11 to 13 */
+#define SDRAM_COL 9 /* Column address: 8 to 12 */
+#define SDRAM_CASL 2 /* CAS latency: 2 or 3 */
+
+/* SDRAM Timings, unit: ns */
+#define SDRAM_TRAS 45 /* RAS# Active Time */
+#define SDRAM_RCD 20 /* RAS# to CAS# Delay */
+#define SDRAM_TPC 20 /* RAS# Precharge Time */
+#define SDRAM_TRWL 7 /* Write Latency Time */
+#define SDRAM_TREF 15625 /* Refresh period: 8192 cycles/64ms */
+
+#endif
diff --git a/package/uboot-xburst/files/include/configs/sakc.h b/package/uboot-xburst/files/include/configs/sakc.h
new file mode 100644
index 000000000..b88d8b08b
--- /dev/null
+++ b/package/uboot-xburst/files/include/configs/sakc.h
@@ -0,0 +1,200 @@
+/*
+ * Authors: Xiangfu Liu <xiangfu.z@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 3 of the License, or (at your option) any later version.
+ */
+
+/*
+ * This file contains the configuration parameters for SAKC.
+ */
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define DEBUG
+#define CONFIG_MIPS32 1 /* MIPS32 CPU core */
+#define CONFIG_JzRISC 1 /* JzRISC core */
+#define CONFIG_JZSOC 1 /* Jz SoC */
+#define CONFIG_JZ4725 1 /* Jz4725 SoC */
+#define CONFIG_JZ4740 1 /* Jz4740 SoC */
+#define CONFIG_SAKC 1 /* SAKC board */
+
+#define MMC_BUS_WIDTH_1BIT 1 /* 1 for MMC 1Bit Bus Width */
+
+//#define CONFIG_LCD 1 /* LCD support */
+//#define LCD_BPP LCD_COLOR32 /*5:18,24,32 bits per pixel */
+//#define CONFIG_SYS_WHITE_ON_BLACK 1
+
+#define CONFIG_SYS_CPU_SPEED 336000000 /* CPU clock: 336 MHz */
+#define CONFIG_SYS_EXTAL 12000000 /* EXTAL freq: 12 MHz */
+#define CONFIG_SYS_HZ (CONFIG_SYS_EXTAL / 256) /* incrementer freq */
+#define CONFIG_SYS_MIPS_TIMER_FREQ CONFIG_SYS_CPU_SPEED
+
+#define CONFIG_SYS_UART_BASE UART0_BASE /* Base of the UART channel */
+#define CONFIG_BAUDRATE 57600
+#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
+
+#define CONFIG_MMC 1
+#define CONFIG_FAT 1
+#define CONFIG_DOS_PARTITION 1
+#define CONFIG_SKIP_LOWLEVEL_INIT 1
+#define CONFIG_BOARD_EARLY_INIT_F 1
+#define CONFIG_SYS_NO_FLASH 1
+#define CONFIG_ENV_OVERWRITE 1
+
+#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAUL)
+#define CONFIG_BOOTDELAY 3
+#define CONFIG_BOOTFILE "uImage" /* file to load */
+#define CONFIG_BOOTARGS "mem=32M console=ttyS0,57600n8 ubi.mtd=2 rootfstype=ubifs root=ubi0:rootfs rw rootwait"
+#define CONFIG_EXTRA_ENV_SETTINGS 1
+#define CONFIG_BOOTARGSFROMSD "mem=32M console=ttyS0,57600n8 rootfstype=ext2 root=/dev/mmcblk0p1 rw rootwait"
+#define CONFIG_BOOTCOMMAND "nand read 0x80600000 0x400000 0x200000;bootm"
+
+/*
+ * Command line configuration.
+ */
+#define CONFIG_CMD_BDI /* bdinfo */
+#define CONFIG_CMD_BOOTD /* bootd */
+#define CONFIG_CMD_CONSOLE /* coninfo */
+#define CONFIG_CMD_ECHO /* echo arguments */
+#define CONFIG_CMD_IMI /* iminfo */
+#define CONFIG_CMD_ITEST /* Integer (and string) test */
+
+#define CONFIG_CMD_LOADB /* loadb */
+#define CONFIG_CMD_LOADS /* loads */
+#define CONFIG_CMD_MEMORY /* md mm nm mw cp cmp crc base loop mtest */
+#define CONFIG_CMD_MISC /* Misc functions like sleep etc*/
+#define CONFIG_CMD_RUN /* run command in env variable */
+#define CONFIG_CMD_SAVEENV /* saveenv */
+#define CONFIG_CMD_SETGETDCR /* DCR support on 4xx */
+#define CONFIG_CMD_SOURCE /* "source" command support */
+#define CONFIG_CMD_XIMG /* Load part of Multi Image */
+
+#define CONFIG_CMD_NAND
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_FAT
+
+/*
+ * Serial download configuration
+ */
+#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */
+#define CONFIG_LOADS_BAUD_CHANGE 1 /* allow baudrate change */
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CONFIG_SYS_LONGHELP /* undef to save memory */
+#define CONFIG_SYS_PROMPT "SAKC# " /* Monitor Command Prompt */
+#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+/* Print Buffer Size */
+#define CONFIG_SYS_MAXARGS 16 /* max number of command args*/
+
+#define CONFIG_SYS_MALLOC_LEN 128 * 1024
+#define CONFIG_SYS_BOOTPARAMS_LEN 128 * 1024
+
+#define CONFIG_SYS_SDRAM_BASE 0x80000000 /* Cached addr */
+#define CONFIG_SYS_INIT_SP_OFFSET 0x400000
+#define CONFIG_SYS_LOAD_ADDR 0x80600000 /* default load address */
+#define CONFIG_SYS_MEMTEST_START 0x80100000
+#define CONFIG_SYS_MEMTEST_END 0x80800000
+
+/*
+ * Environment
+ */
+#define CONFIG_ENV_IS_IN_NAND 1 /* use NAND for environment vars */
+
+/*
+ * NAND FLASH configuration
+ */
+/* NAND Boot config code */
+#define JZ4740_NANDBOOT_CFG JZ4740_NANDBOOT_B8R3
+
+#define SAKC_NAND_SIZE 1 /* if board nand flash is 1GB, set to 1
+ * if board nand flash is 2GB, set to 2
+ * for change the PAGE_SIZE and BLOCK_SIZE
+ * will delete when there is no 1GB flash
+ */
+
+#define CONFIG_SYS_NAND_PAGE_SIZE (2048 * SAKC_NAND_SIZE)
+/* nand chip block size */
+#define CONFIG_SYS_NAND_BLOCK_SIZE (256 * SAKC_NAND_SIZE << 10)
+/* nand bad block was marked at this page in a block, start from 0 */
+#define CONFIG_SYS_NAND_BADBLOCK_PAGE 127
+/* ECC offset position in oob area, default value is 6 if it isn't defined */
+#define CONFIG_SYS_NAND_ECC_POS (6 * SAKC_NAND_SIZE)
+#define CONFIG_SYS_MAX_NAND_DEVICE 1
+#define NAND_MAX_CHIPS 1
+#define CONFIG_SYS_NAND_BASE 0xB8000000
+#define CONFIG_SYS_NAND_SELECT_DEVICE 1 /* nand driver supports mutipl.*/
+#define CONFIG_SYS_ONENAND_BASE CONFIG_SYS_NAND_BASE
+
+/*
+ * IPL (Initial Program Loader, integrated inside CPU)
+ * Will load first 8k from NAND (SPL) into cache and execute it from there.
+ *
+ * SPL (Secondary Program Loader)
+ * Will load special U-Boot version (NUB) from NAND and execute it. This SPL
+ * has to fit into 8kByte. It sets up the CPU and configures the SDRAM
+ * controller and the NAND controller so that the special U-Boot image can be
+ * loaded from NAND to SDRAM.
+ *
+ * NUB (NAND U-Boot)
+ * This NAND U-Boot (NUB) is a special U-Boot version which can be started
+ * from RAM. Therefore it mustn't (re-)configure the SDRAM controller.
+ *
+ */
+#define CONFIG_SYS_NAND_U_BOOT_DST 0x80100000 /* Load NUB to this addr */
+#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_NAND_U_BOOT_DST
+/* Start NUB from this addr*/
+
+/*
+ * Define the partitioning of the NAND chip (only RAM U-Boot is needed here)
+ */
+#define CONFIG_SYS_NAND_U_BOOT_OFFS (256 << 10) /* Offset to RAM U-Boot image */
+#define CONFIG_SYS_NAND_U_BOOT_SIZE (512 << 10) /* Size of RAM U-Boot image */
+
+#define CONFIG_ENV_SIZE CONFIG_SYS_NAND_BLOCK_SIZE
+#define CONFIG_ENV_OFFSET (CONFIG_SYS_NAND_BLOCK_SIZE + CONFIG_SYS_NAND_U_BOOT_SIZE + CONFIG_SYS_NAND_BLOCK_SIZE)
+/* environment starts here */
+#define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
+
+/* in qi_lb60.h/config.mk TEXT_BAS = 0x88000000 */
+#define CONFIG_SYS_MONITOR_BASE TEXT_BASE
+
+/*
+ * SDRAM Info.
+ */
+#define CONFIG_NR_DRAM_BANKS 1
+
+/* SDRAM paramters */
+#define SDRAM_BW16 1 /* Data bus width: 0-32bit, 1-16bit */
+#define SDRAM_BANK4 1 /* Banks each chip: 0-2bank, 1-4bank */
+#define SDRAM_ROW 13 /* Row address: 11 to 13 */
+#define SDRAM_COL 9 /* Column address: 8 to 12 */
+#define SDRAM_CASL 2 /* CAS latency: 2 or 3 */
+
+/* SDRAM Timings, unit: ns */
+#define SDRAM_TRAS 45 /* RAS# Active Time */
+#define SDRAM_RCD 20 /* RAS# to CAS# Delay */
+#define SDRAM_TPC 20 /* RAS# Precharge Time */
+#define SDRAM_TRWL 7 /* Write Latency Time */
+#define SDRAM_TREF 15625 /* Refresh period: 8192 cycles/64ms */
+
+/*
+ * Cache Configuration
+ */
+#define CONFIG_SYS_DCACHE_SIZE 16384
+#define CONFIG_SYS_ICACHE_SIZE 16384
+#define CONFIG_SYS_CACHELINE_SIZE 32
+
+/*
+ * GPIO definition
+ */
+#define GPIO_SD_DETECT (2 * 32 + 27)
+#define GPIO_SD_CD_N GPIO_SD_DETECT /* SD Card insert detect */
+#define GPIO_SD_VCC_EN_N GPIO_SDPW_EN /* SD Card Power Enable */
+
+#endif /* __CONFIG_H */
diff --git a/package/uboot-xburst/files/nand_spl/board/n516/Makefile b/package/uboot-xburst/files/nand_spl/board/n516/Makefile
new file mode 100644
index 000000000..bd45379fd
--- /dev/null
+++ b/package/uboot-xburst/files/nand_spl/board/n516/Makefile
@@ -0,0 +1,104 @@
+#
+# (C) Copyright 2006
+# Stefan Roese, DENX Software Engineering, sr@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+include $(TOPDIR)/nand_spl/board/$(BOARDDIR)/config.mk
+
+LDSCRIPT= $(TOPDIR)/nand_spl/board/$(BOARDDIR)/u-boot.lds
+LDFLAGS = -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE)
+AFLAGS += -DCONFIG_NAND_SPL
+CFLAGS += -DCONFIG_NAND_SPL
+
+SOBJS = start.o usb_boot.o
+COBJS = nand_boot_jz4740.o cpu.o jz4740.o jz_serial.o
+
+SRCS := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c))
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
+__OBJS := $(SOBJS) $(COBJS)
+LNDIR := $(OBJTREE)/nand_spl/board/$(BOARDDIR)
+
+nandobj := $(OBJTREE)/nand_spl/
+
+ALL = $(nandobj)u-boot-spl $(nandobj)u-boot-spl.bin $(nandobj)u-boot-spl-16k.bin
+all: $(obj).depend $(ALL)
+
+$(nandobj)u-boot-spl-16k.bin: $(nandobj)u-boot-spl.bin
+ dd bs=1024 count=8 if=/dev/zero of=$(nandobj)junk1
+ cat $< $(nandobj)junk1 > $(nandobj)junk2
+ dd bs=1024 count=8 if=$(nandobj)junk2 of=$(nandobj)junk3
+ cat $(nandobj)junk3 $(nandobj)junk3 > $(nandobj)junk4
+ dd bs=1024 count=256 if=/dev/zero of=$(nandobj)junk5
+ cat $(nandobj)junk4 $(nandobj)junk5 > $(nandobj)junk6
+ dd bs=1024 count=256 if=$(nandobj)junk6 of=$@
+ rm -f $(nandobj)junk*
+
+$(nandobj)u-boot-spl.bin: $(nandobj)u-boot-spl
+ $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
+
+$(nandobj)u-boot-spl: $(OBJS)
+ cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
+ -Map $(nandobj)u-boot-spl.map \
+ -o $(nandobj)u-boot-spl
+
+# create symbolic links for common files
+
+# from cpu directory
+$(obj)start.S:
+ @rm -f $(obj)start.S
+ ln -s $(SRCTREE)/cpu/mips/start.S $(obj)start.S
+
+$(obj)usb_boot.S:
+ @rm -f $(obj)usb_boot.S
+ ln -s $(SRCTREE)/cpu/mips/usb_boot.S $(obj)usb_boot.S
+
+$(obj)cpu.c:
+ @rm -f $(obj)cpu.c
+ ln -s $(SRCTREE)/cpu/mips/cpu.c $(obj)cpu.c
+
+$(obj)jz4740.c:
+ @rm -f $(obj)jz4740.c
+ ln -s $(SRCTREE)/cpu/mips/jz4740.c $(obj)jz4740.c
+
+$(obj)jz_serial.c:
+ @rm -f $(obj)jz_serial.c
+ ln -s $(SRCTREE)/cpu/mips/jz_serial.c $(obj)jz_serial.c
+
+# from nand_spl directory
+$(obj)nand_boot_jz4740.c:
+ @rm -f $(obj)nand_boot_jz4740.c
+ ln -s $(SRCTREE)/nand_spl/nand_boot_jz4740.c $(obj)nand_boot_jz4740.c
+
+#########################################################################
+
+$(obj)%.o: $(obj)%.S
+ $(CC) $(AFLAGS) -c -o $@ $<
+
+$(obj)%.o: $(obj)%.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/package/uboot-xburst/files/nand_spl/board/n516/config.mk b/package/uboot-xburst/files/nand_spl/board/n516/config.mk
new file mode 100644
index 000000000..698c476fd
--- /dev/null
+++ b/package/uboot-xburst/files/nand_spl/board/n516/config.mk
@@ -0,0 +1,34 @@
+#
+# (C) Copyright 2006
+# Stefan Roese, DENX Software Engineering, sr@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+#
+# Ingenic JZ4740 Reference Platform
+#
+
+#
+# TEXT_BASE for SPL:
+#
+# On JZ4730 platforms the SPL is located at 0x80000000...0x80001000,
+# in the first 4kBytes of memory space in cache. So we set
+# TEXT_BASE to starting address in internal cache here.
+#
+TEXT_BASE = 0x80000000
diff --git a/package/uboot-xburst/files/nand_spl/board/n516/u-boot.lds b/package/uboot-xburst/files/nand_spl/board/n516/u-boot.lds
new file mode 100644
index 000000000..7042388d0
--- /dev/null
+++ b/package/uboot-xburst/files/nand_spl/board/n516/u-boot.lds
@@ -0,0 +1,63 @@
+/*
+ * (C) Copyright 2005
+ * Ingenic Semiconductor, <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradlittlemips", "elf32-tradlittlemips")
+
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .sdata : { *(.sdata) }
+
+ _gp = ALIGN(16);
+
+ __got_start = .;
+ .got : { *(.got) }
+ __got_end = .;
+
+ .sdata : { *(.sdata) }
+
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+ uboot_end_data = .;
+ num_got_entries = (__got_end - __got_start) >> 2;
+
+ . = ALIGN(4);
+ .sbss : { *(.sbss) }
+ .bss : { *(.bss) }
+ uboot_end = .;
+}
diff --git a/package/uboot-xburst/files/nand_spl/board/nanonote/Makefile b/package/uboot-xburst/files/nand_spl/board/nanonote/Makefile
new file mode 100644
index 000000000..bd45379fd
--- /dev/null
+++ b/package/uboot-xburst/files/nand_spl/board/nanonote/Makefile
@@ -0,0 +1,104 @@
+#
+# (C) Copyright 2006
+# Stefan Roese, DENX Software Engineering, sr@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+include $(TOPDIR)/nand_spl/board/$(BOARDDIR)/config.mk
+
+LDSCRIPT= $(TOPDIR)/nand_spl/board/$(BOARDDIR)/u-boot.lds
+LDFLAGS = -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE)
+AFLAGS += -DCONFIG_NAND_SPL
+CFLAGS += -DCONFIG_NAND_SPL
+
+SOBJS = start.o usb_boot.o
+COBJS = nand_boot_jz4740.o cpu.o jz4740.o jz_serial.o
+
+SRCS := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c))
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
+__OBJS := $(SOBJS) $(COBJS)
+LNDIR := $(OBJTREE)/nand_spl/board/$(BOARDDIR)
+
+nandobj := $(OBJTREE)/nand_spl/
+
+ALL = $(nandobj)u-boot-spl $(nandobj)u-boot-spl.bin $(nandobj)u-boot-spl-16k.bin
+all: $(obj).depend $(ALL)
+
+$(nandobj)u-boot-spl-16k.bin: $(nandobj)u-boot-spl.bin
+ dd bs=1024 count=8 if=/dev/zero of=$(nandobj)junk1
+ cat $< $(nandobj)junk1 > $(nandobj)junk2
+ dd bs=1024 count=8 if=$(nandobj)junk2 of=$(nandobj)junk3
+ cat $(nandobj)junk3 $(nandobj)junk3 > $(nandobj)junk4
+ dd bs=1024 count=256 if=/dev/zero of=$(nandobj)junk5
+ cat $(nandobj)junk4 $(nandobj)junk5 > $(nandobj)junk6
+ dd bs=1024 count=256 if=$(nandobj)junk6 of=$@
+ rm -f $(nandobj)junk*
+
+$(nandobj)u-boot-spl.bin: $(nandobj)u-boot-spl
+ $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
+
+$(nandobj)u-boot-spl: $(OBJS)
+ cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
+ -Map $(nandobj)u-boot-spl.map \
+ -o $(nandobj)u-boot-spl
+
+# create symbolic links for common files
+
+# from cpu directory
+$(obj)start.S:
+ @rm -f $(obj)start.S
+ ln -s $(SRCTREE)/cpu/mips/start.S $(obj)start.S
+
+$(obj)usb_boot.S:
+ @rm -f $(obj)usb_boot.S
+ ln -s $(SRCTREE)/cpu/mips/usb_boot.S $(obj)usb_boot.S
+
+$(obj)cpu.c:
+ @rm -f $(obj)cpu.c
+ ln -s $(SRCTREE)/cpu/mips/cpu.c $(obj)cpu.c
+
+$(obj)jz4740.c:
+ @rm -f $(obj)jz4740.c
+ ln -s $(SRCTREE)/cpu/mips/jz4740.c $(obj)jz4740.c
+
+$(obj)jz_serial.c:
+ @rm -f $(obj)jz_serial.c
+ ln -s $(SRCTREE)/cpu/mips/jz_serial.c $(obj)jz_serial.c
+
+# from nand_spl directory
+$(obj)nand_boot_jz4740.c:
+ @rm -f $(obj)nand_boot_jz4740.c
+ ln -s $(SRCTREE)/nand_spl/nand_boot_jz4740.c $(obj)nand_boot_jz4740.c
+
+#########################################################################
+
+$(obj)%.o: $(obj)%.S
+ $(CC) $(AFLAGS) -c -o $@ $<
+
+$(obj)%.o: $(obj)%.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/package/uboot-xburst/files/nand_spl/board/nanonote/config.mk b/package/uboot-xburst/files/nand_spl/board/nanonote/config.mk
new file mode 100644
index 000000000..698c476fd
--- /dev/null
+++ b/package/uboot-xburst/files/nand_spl/board/nanonote/config.mk
@@ -0,0 +1,34 @@
+#
+# (C) Copyright 2006
+# Stefan Roese, DENX Software Engineering, sr@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+#
+# Ingenic JZ4740 Reference Platform
+#
+
+#
+# TEXT_BASE for SPL:
+#
+# On JZ4730 platforms the SPL is located at 0x80000000...0x80001000,
+# in the first 4kBytes of memory space in cache. So we set
+# TEXT_BASE to starting address in internal cache here.
+#
+TEXT_BASE = 0x80000000
diff --git a/package/uboot-xburst/files/nand_spl/board/nanonote/u-boot.lds b/package/uboot-xburst/files/nand_spl/board/nanonote/u-boot.lds
new file mode 100644
index 000000000..7042388d0
--- /dev/null
+++ b/package/uboot-xburst/files/nand_spl/board/nanonote/u-boot.lds
@@ -0,0 +1,63 @@
+/*
+ * (C) Copyright 2005
+ * Ingenic Semiconductor, <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradlittlemips", "elf32-tradlittlemips")
+
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .sdata : { *(.sdata) }
+
+ _gp = ALIGN(16);
+
+ __got_start = .;
+ .got : { *(.got) }
+ __got_end = .;
+
+ .sdata : { *(.sdata) }
+
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+ uboot_end_data = .;
+ num_got_entries = (__got_end - __got_start) >> 2;
+
+ . = ALIGN(4);
+ .sbss : { *(.sbss) }
+ .bss : { *(.bss) }
+ uboot_end = .;
+}
diff --git a/package/uboot-xburst/files/nand_spl/board/sakc/Makefile b/package/uboot-xburst/files/nand_spl/board/sakc/Makefile
new file mode 100644
index 000000000..bd45379fd
--- /dev/null
+++ b/package/uboot-xburst/files/nand_spl/board/sakc/Makefile
@@ -0,0 +1,104 @@
+#
+# (C) Copyright 2006
+# Stefan Roese, DENX Software Engineering, sr@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+include $(TOPDIR)/nand_spl/board/$(BOARDDIR)/config.mk
+
+LDSCRIPT= $(TOPDIR)/nand_spl/board/$(BOARDDIR)/u-boot.lds
+LDFLAGS = -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE)
+AFLAGS += -DCONFIG_NAND_SPL
+CFLAGS += -DCONFIG_NAND_SPL
+
+SOBJS = start.o usb_boot.o
+COBJS = nand_boot_jz4740.o cpu.o jz4740.o jz_serial.o
+
+SRCS := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c))
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
+__OBJS := $(SOBJS) $(COBJS)
+LNDIR := $(OBJTREE)/nand_spl/board/$(BOARDDIR)
+
+nandobj := $(OBJTREE)/nand_spl/
+
+ALL = $(nandobj)u-boot-spl $(nandobj)u-boot-spl.bin $(nandobj)u-boot-spl-16k.bin
+all: $(obj).depend $(ALL)
+
+$(nandobj)u-boot-spl-16k.bin: $(nandobj)u-boot-spl.bin
+ dd bs=1024 count=8 if=/dev/zero of=$(nandobj)junk1
+ cat $< $(nandobj)junk1 > $(nandobj)junk2
+ dd bs=1024 count=8 if=$(nandobj)junk2 of=$(nandobj)junk3
+ cat $(nandobj)junk3 $(nandobj)junk3 > $(nandobj)junk4
+ dd bs=1024 count=256 if=/dev/zero of=$(nandobj)junk5
+ cat $(nandobj)junk4 $(nandobj)junk5 > $(nandobj)junk6
+ dd bs=1024 count=256 if=$(nandobj)junk6 of=$@
+ rm -f $(nandobj)junk*
+
+$(nandobj)u-boot-spl.bin: $(nandobj)u-boot-spl
+ $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
+
+$(nandobj)u-boot-spl: $(OBJS)
+ cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
+ -Map $(nandobj)u-boot-spl.map \
+ -o $(nandobj)u-boot-spl
+
+# create symbolic links for common files
+
+# from cpu directory
+$(obj)start.S:
+ @rm -f $(obj)start.S
+ ln -s $(SRCTREE)/cpu/mips/start.S $(obj)start.S
+
+$(obj)usb_boot.S:
+ @rm -f $(obj)usb_boot.S
+ ln -s $(SRCTREE)/cpu/mips/usb_boot.S $(obj)usb_boot.S
+
+$(obj)cpu.c:
+ @rm -f $(obj)cpu.c
+ ln -s $(SRCTREE)/cpu/mips/cpu.c $(obj)cpu.c
+
+$(obj)jz4740.c:
+ @rm -f $(obj)jz4740.c
+ ln -s $(SRCTREE)/cpu/mips/jz4740.c $(obj)jz4740.c
+
+$(obj)jz_serial.c:
+ @rm -f $(obj)jz_serial.c
+ ln -s $(SRCTREE)/cpu/mips/jz_serial.c $(obj)jz_serial.c
+
+# from nand_spl directory
+$(obj)nand_boot_jz4740.c:
+ @rm -f $(obj)nand_boot_jz4740.c
+ ln -s $(SRCTREE)/nand_spl/nand_boot_jz4740.c $(obj)nand_boot_jz4740.c
+
+#########################################################################
+
+$(obj)%.o: $(obj)%.S
+ $(CC) $(AFLAGS) -c -o $@ $<
+
+$(obj)%.o: $(obj)%.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/package/uboot-xburst/files/nand_spl/board/sakc/config.mk b/package/uboot-xburst/files/nand_spl/board/sakc/config.mk
new file mode 100644
index 000000000..698c476fd
--- /dev/null
+++ b/package/uboot-xburst/files/nand_spl/board/sakc/config.mk
@@ -0,0 +1,34 @@
+#
+# (C) Copyright 2006
+# Stefan Roese, DENX Software Engineering, sr@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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
+#
+#
+# Ingenic JZ4740 Reference Platform
+#
+
+#
+# TEXT_BASE for SPL:
+#
+# On JZ4730 platforms the SPL is located at 0x80000000...0x80001000,
+# in the first 4kBytes of memory space in cache. So we set
+# TEXT_BASE to starting address in internal cache here.
+#
+TEXT_BASE = 0x80000000
diff --git a/package/uboot-xburst/files/nand_spl/board/sakc/u-boot.lds b/package/uboot-xburst/files/nand_spl/board/sakc/u-boot.lds
new file mode 100644
index 000000000..7042388d0
--- /dev/null
+++ b/package/uboot-xburst/files/nand_spl/board/sakc/u-boot.lds
@@ -0,0 +1,63 @@
+/*
+ * (C) Copyright 2005
+ * Ingenic Semiconductor, <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradlittlemips", "elf32-tradlittlemips")
+
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(.rodata) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = ALIGN(4);
+ .sdata : { *(.sdata) }
+
+ _gp = ALIGN(16);
+
+ __got_start = .;
+ .got : { *(.got) }
+ __got_end = .;
+
+ .sdata : { *(.sdata) }
+
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+ uboot_end_data = .;
+ num_got_entries = (__got_end - __got_start) >> 2;
+
+ . = ALIGN(4);
+ .sbss : { *(.sbss) }
+ .bss : { *(.bss) }
+ uboot_end = .;
+}
diff --git a/package/uboot-xburst/files/nand_spl/nand_boot_jz4740.c b/package/uboot-xburst/files/nand_spl/nand_boot_jz4740.c
new file mode 100644
index 000000000..9df0596e8
--- /dev/null
+++ b/package/uboot-xburst/files/nand_spl/nand_boot_jz4740.c
@@ -0,0 +1,429 @@
+/*
+ * Copyright (C) 2007 Ingenic Semiconductor Inc.
+ * Author: Peter <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <nand.h>
+
+#include <asm/io.h>
+#include <asm/jz4740.h>
+
+#define KEY_U_OUT (32 * 2 + 16)
+#define KEY_U_IN (32 * 3 + 19)
+
+/*
+ * NAND flash definitions
+ */
+
+#define NAND_DATAPORT 0xb8000000
+#define NAND_ADDRPORT 0xb8010000
+#define NAND_COMMPORT 0xb8008000
+
+#define ECC_BLOCK 512
+#define ECC_POS 6
+#define PAR_SIZE 9
+
+#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1)
+#define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1))
+#define __nand_ecc_rs_encoding() \
+ (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_ENCODING)
+#define __nand_ecc_rs_decoding() \
+ (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_DECODING)
+#define __nand_ecc_disable() (REG_EMC_NFECR &= ~EMC_NFECR_ECCE)
+#define __nand_ecc_encode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_ENCF))
+#define __nand_ecc_decode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_DECF))
+
+static inline void __nand_dev_ready(void)
+{
+ unsigned int timeout = 10000;
+ while ((REG_GPIO_PXPIN(2) & 0x40000000) && timeout--);
+ while (!(REG_GPIO_PXPIN(2) & 0x40000000));
+}
+
+#define __nand_cmd(n) (REG8(NAND_COMMPORT) = (n))
+#define __nand_addr(n) (REG8(NAND_ADDRPORT) = (n))
+#define __nand_data8() REG8(NAND_DATAPORT)
+#define __nand_data16() REG16(NAND_DATAPORT)
+
+#if (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B8R3)
+ #define NAND_BUS_WIDTH 8
+ #define NAND_ROW_CYCLE 3
+#elif (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B8R2)
+ #define NAND_BUS_WIDTH 8
+ #define NAND_ROW_CYCLE 2
+#elif (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B16R3)
+ #define NAND_BUS_WIDTH 16
+ #define NAND_ROW_CYCLE 3
+#elif (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B16R2)
+ #define NAND_BUS_WIDTH 16
+ #define NAND_ROW_CYCLE 2
+#endif
+
+/*
+ * NAND flash parameters
+ */
+static int page_size = 2048;
+static int oob_size = 64;
+static int ecc_count = 4;
+static int page_per_block = 64;
+static int bad_block_pos = 0;
+static int block_size = 131072;
+
+static unsigned char oob_buf[128] = {0};
+
+/*
+ * External routines
+ */
+extern void flush_cache_all(void);
+extern int serial_init(void);
+extern void serial_puts(const char *s);
+extern void sdram_init(void);
+extern void pll_init(void);
+extern void usb_boot();
+
+/*
+ * NAND flash routines
+ */
+#if NAND_BUS_WIDTH == 16
+static inline void nand_read_buf16(void *buf, int count)
+{
+ int i;
+ u16 *p = (u16 *)buf;
+
+ for (i = 0; i < count; i += 2)
+ *p++ = __nand_data16();
+}
+#define nand_read_buf nand_read_buf16
+
+#elif NAND_BUS_WIDTH == 8
+static inline void nand_read_buf8(void *buf, int count)
+{
+ int i;
+ u8 *p = (u8 *)buf;
+
+ for (i = 0; i < count; i++)
+ *p++ = __nand_data8();
+}
+#define nand_read_buf nand_read_buf8
+
+#endif
+
+/* Correct 1~9-bit errors in 512-bytes data */
+static void rs_correct(unsigned char *dat, int idx, int mask)
+{
+ int i;
+
+ idx--;
+
+ i = idx + (idx >> 3);
+ if (i >= 512)
+ return;
+
+ mask <<= (idx & 0x7);
+
+ dat[i] ^= mask & 0xff;
+ if (i < 511)
+ dat[i+1] ^= (mask >> 8) & 0xff;
+}
+
+static int nand_read_oob(int page_addr, uchar *buf, int size)
+{
+ int col_addr;
+ if (page_size != 512)
+ col_addr = page_size;
+ else {
+ col_addr = 0;
+ __nand_dev_ready();
+ }
+
+ if (page_size != 512)
+ /* Send READ0 command */
+ __nand_cmd(NAND_CMD_READ0);
+ else
+ /* Send READOOB command */
+ __nand_cmd(NAND_CMD_READOOB);
+
+ /* Send column address */
+ __nand_addr(col_addr & 0xff);
+ if (page_size != 512)
+ __nand_addr((col_addr >> 8) & 0xff);
+
+ /* Send page address */
+ __nand_addr(page_addr & 0xff);
+ __nand_addr((page_addr >> 8) & 0xff);
+ #ifdef NAND_ROW_CYCLE == 3
+ __nand_addr((page_addr >> 16) & 0xff);
+ #endif
+
+ /* Send READSTART command for 2048 or 4096 ps NAND */
+ if (page_size != 512)
+ __nand_cmd(NAND_CMD_READSTART);
+
+ /* Wait for device ready */
+ __nand_dev_ready();
+
+ /* Read oob data */
+ nand_read_buf(buf, size);
+ if (page_size == 512)
+ __nand_dev_ready();
+ return 0;
+}
+
+static int nand_read_page(int page_addr, uchar *dst, uchar *oobbuf)
+{
+ uchar *databuf = dst, *tmpbuf;
+ int i, j;
+
+ /*
+ * Read oob data
+ */
+ nand_read_oob(page_addr, oobbuf, oob_size);
+
+ /*
+ * Read page data
+ */
+
+ /* Send READ0 command */
+ __nand_cmd(NAND_CMD_READ0);
+
+ /* Send column address */
+ __nand_addr(0);
+ if (page_size != 512)
+ __nand_addr(0);
+
+ /* Send page address */
+ __nand_addr(page_addr & 0xff);
+ __nand_addr((page_addr >> 8) & 0xff);
+ #if NAND_ROW_CYCLE == 3
+ __nand_addr((page_addr >> 16) & 0xff);
+ #endif
+
+ /* Send READSTART command for 2048 or 4096 ps NAND */
+ if (page_size != 512)
+ __nand_cmd(NAND_CMD_READSTART);
+
+ /* Wait for device ready */
+ __nand_dev_ready();
+
+ /* Read page data */
+ tmpbuf = databuf;
+
+ for (i = 0; i < ecc_count; i++) {
+ volatile unsigned char *paraddr = (volatile unsigned char *)EMC_NFPAR0;
+ unsigned int stat;
+
+ /* Enable RS decoding */
+ REG_EMC_NFINTS = 0x0;
+ __nand_ecc_rs_decoding();
+
+ /* Read data */
+ nand_read_buf((void *)tmpbuf, ECC_BLOCK);
+
+ /* Set PAR values */
+ for (j = 0; j < PAR_SIZE; j++) {
+#if defined(CONFIG_SYS_NAND_ECC_POS)
+ *paraddr++ = oobbuf[CONFIG_SYS_NAND_ECC_POS + i*PAR_SIZE + j];
+#else
+ *paraddr++ = oobbuf[ECC_POS + i*PAR_SIZE + j];
+#endif
+ }
+
+ /* Set PRDY */
+ REG_EMC_NFECR |= EMC_NFECR_PRDY;
+
+ /* Wait for completion */
+ __nand_ecc_decode_sync();
+
+ /* Disable decoding */
+ __nand_ecc_disable();
+
+ /* Check result of decoding */
+ stat = REG_EMC_NFINTS;
+ if (stat & EMC_NFINTS_ERR) {
+ /* Error occurred */
+ /* serial_puts("\n Error occurred\n"); */
+ if (stat & EMC_NFINTS_UNCOR) {
+ /* Uncorrectable error occurred */
+ /* serial_puts("\nUncorrectable error occurred\n"); */
+ }
+ else {
+ unsigned int errcnt, index, mask;
+
+ errcnt = (stat & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT;
+ switch (errcnt) {
+ case 4:
+ index = (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
+ mask = (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
+ rs_correct(tmpbuf, index, mask);
+ /* FALL-THROUGH */
+ case 3:
+ index = (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
+ mask = (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
+ rs_correct(tmpbuf, index, mask);
+ /* FALL-THROUGH */
+ case 2:
+ index = (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
+ mask = (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
+ rs_correct(tmpbuf, index, mask);
+ /* FALL-THROUGH */
+ case 1:
+ index = (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
+ mask = (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
+ rs_correct(tmpbuf, index, mask);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ tmpbuf += ECC_BLOCK;
+ }
+
+ return 0;
+}
+
+#ifndef CONFIG_SYS_NAND_BADBLOCK_PAGE
+#define CONFIG_SYS_NAND_BADBLOCK_PAGE 0 /* NAND bad block was marked at this page in a block, starting from 0 */
+#endif
+
+static void nand_load(int offs, int uboot_size, uchar *dst)
+{
+ int page;
+ int pagecopy_count;
+
+ __nand_enable();
+
+ page = offs / page_size;
+ pagecopy_count = 0;
+ while (pagecopy_count < (uboot_size / page_size)) {
+ if (page % page_per_block == 0) {
+ nand_read_oob(page + CONFIG_SYS_NAND_BADBLOCK_PAGE, oob_buf, oob_size);
+ if (oob_buf[bad_block_pos] != 0xff) {
+ page += page_per_block;
+ /* Skip bad block */
+ continue;
+ }
+ }
+ /* Load this page to dst, do the ECC */
+ nand_read_page(page, dst, oob_buf);
+
+ dst += page_size;
+ page++;
+ pagecopy_count++;
+ }
+
+ __nand_disable();
+}
+
+static void jz_nand_init(void) {
+
+ /* Optimize the timing of nand */
+ REG_EMC_SMCR1 = 0x094c4400;
+}
+
+static void gpio_init(void)
+{
+ /*
+ * Initialize SDRAM pins
+ */
+#if defined(CONFIG_JZ4720)
+ __gpio_as_sdram_16bit_4720();
+#elif defined(CONFIG_JZ4725)
+ __gpio_as_sdram_16bit_4725();
+#else
+ __gpio_as_sdram_32bit();
+#endif
+
+ /*
+ * Initialize UART0 pins
+ */
+ __gpio_as_uart0();
+}
+
+static int is_usb_boot()
+{
+ int keyU = 0;
+
+ __gpio_as_input(KEY_U_IN);
+ __gpio_enable_pull(KEY_U_IN);
+
+ __gpio_as_output(KEY_U_OUT);
+ __gpio_clear_pin(KEY_U_OUT);
+
+ keyU = __gpio_get_pin(KEY_U_IN);
+
+ if (keyU)
+ serial_puts("[U] not pressed\n");
+ else
+ serial_puts("[U] pressed\n");
+
+ return !keyU;
+}
+
+void nand_boot(void)
+{
+ void (*uboot)(void);
+
+ /*
+ * Init hardware
+ */
+ jz_nand_init();
+ gpio_init();
+ serial_init();
+
+ serial_puts("\n\nNAND Secondary Program Loader\n\n");
+
+ pll_init();
+ sdram_init();
+
+#if defined(CONFIG_NANONOTE)
+ if(is_usb_boot()) {
+ serial_puts("enter USB BOOT mode\n");
+ usb_boot();
+ }
+#endif
+
+ page_size = CONFIG_SYS_NAND_PAGE_SIZE;
+ block_size = CONFIG_SYS_NAND_BLOCK_SIZE;
+ page_per_block = CONFIG_SYS_NAND_BLOCK_SIZE / CONFIG_SYS_NAND_PAGE_SIZE;
+ bad_block_pos = (page_size == 512) ? 5 : 0;
+ oob_size = page_size / 32;
+ ecc_count = page_size / ECC_BLOCK;
+
+ /*
+ * Load U-Boot image from NAND into RAM
+ */
+ nand_load(CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE,
+ (uchar *)CONFIG_SYS_NAND_U_BOOT_DST);
+
+ uboot = (void (*)(void))CONFIG_SYS_NAND_U_BOOT_START;
+
+ serial_puts("Starting U-Boot ...\n");
+
+ /*
+ * Flush caches
+ */
+ flush_cache_all();
+
+ /*
+ * Jump to U-Boot image
+ */
+ (*uboot)();
+}
diff --git a/package/uboot-xburst/patches/001-xburst.patch b/package/uboot-xburst/patches/001-xburst.patch
new file mode 100644
index 000000000..be833305e
--- /dev/null
+++ b/package/uboot-xburst/patches/001-xburst.patch
@@ -0,0 +1,1669 @@
+this patch include the u-boot2009.11 change files
+
+From: Xiangfu Liu <xiangfu@sharism.cc>
+
+
+---
+
+ Makefile | 10 +
+ common/env_common.c | 2
+ common/lcd.c | 45 ++++
+ common/main.c | 4
+ cpu/mips/Makefile | 4
+ cpu/mips/cache.S | 280 ++++++++++----------------
+ cpu/mips/config.mk | 6 -
+ cpu/mips/cpu.c | 75 +++++++
+ cpu/mips/start.S | 432 ++++++++++++++++++++++++++++++++--------
+ drivers/mtd/nand/nand_base.c | 88 ++++++++
+ examples/standalone/mips.lds | 2
+ include/asm-mips/addrspace.h | 2
+ include/asm-mips/global_data.h | 11 +
+ include/lcd.h | 56 +++++
+ lib_mips/board.c | 18 +-
+ lib_mips/bootm.c | 7 +
+ lib_mips/time.c | 4
+ 20 files changed, 800 insertions(+), 333 deletions(-)
+
+
+diff --git a/Makefile b/Makefile
+index f06a97c..a318eb4 100644
+--- a/Makefile
++++ b/Makefile
+@@ -3439,6 +3439,22 @@ qemu_mips_config : unconfig
+ @$(MKCONFIG) -a qemu-mips mips mips qemu-mips
+
+ #########################################################################
++## MIPS32 Jz47XX
++#########################################################################
++qi_lb60_config : unconfig
++ @echo "#define CONFIG_NAND_U_BOOT" > $(obj)include/config.h
++ @echo "Compile NAND boot image for QI LB60"
++ @$(MKCONFIG) -a qi_lb60 mips mips nanonote
++ @echo "TEXT_BASE = 0x80100000" > $(obj)board/nanonote/config.tmp
++ @echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk
++
++avt2_config : unconfig
++ @echo "#define CONFIG_NAND_U_BOOT" > $(obj)include/config.h
++ @echo "Compile NAND boot image for AVT2"
++ @$(MKCONFIG) -a avt2 mips mips nanonote
++ @echo "TEXT_BASE = 0x80100000" > $(obj)board/nanonote/config.tmp
++ @echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk
++#########################################################################
+ ## MIPS64 5Kc
+ #########################################################################
+
+diff --git a/common/env_common.c b/common/env_common.c
+index 439a4a9..6cfe30b 100644
+--- a/common/env_common.c
++++ b/common/env_common.c
+@@ -134,7 +134,10 @@ uchar default_environment[] = {
+ "pcidelay=" MK_STR(CONFIG_PCI_BOOTDELAY) "\0"
+ #endif
+-#ifdef CONFIG_EXTRA_ENV_SETTINGS
+- CONFIG_EXTRA_ENV_SETTINGS
++#ifdef CONFIG_BOOTARGSFROMSD
++ "bootargsfromsd=" CONFIG_BOOTARGSFROMSD "\0"
++#endif
++#ifdef CONFIG_BOOTCOMMANDFROMSD
++ "bootcmdfromsd=" CONFIG_BOOTCOMMANDFROMSD "\0"
+ #endif
+ "\0"
+ };
+diff --git a/common/lcd.c b/common/lcd.c
+index 4e31618..ddd5aa8 100644
+--- a/common/lcd.c
++++ b/common/lcd.c
+@@ -64,7 +64,9 @@
+ #ifdef CONFIG_LCD_LOGO
+ # include <bmp_logo.h> /* Get logo data, width and height */
+ # if (CONSOLE_COLOR_WHITE >= BMP_LOGO_OFFSET)
+-# error Default Color Map overlaps with Logo Color Map
++# ifndef CONFIG_JzRISC /* JzRISC core */
++# error Default Color Map overlaps with Logo Color Map
++# endif
+ # endif
+ #endif
+
+@@ -249,6 +251,14 @@ static void lcd_drawchars (ushort x, ushort y, uchar *str, int count)
+ lcd_color_fg : lcd_color_bg;
+ bits <<= 1;
+ }
++#elif LCD_BPP == LCD_COLOR32
++ uint *m = (uint *)d;
++ for (c=0; c<32; ++c) {
++ *m++ = (bits & 0x80) ?
++ lcd_color_fg : lcd_color_bg;
++ //d+=4;
++ bits <<= 1;
++ }
+ #endif
+ }
+ #if LCD_BPP == LCD_MONOCHROME
+@@ -315,6 +325,9 @@ static void test_pattern (void)
+ }
+ #endif /* LCD_TEST_PATTERN */
+
++#ifdef CONFIG_JzRISC /* JzRISC core */
++extern int flush_cache_all(void);
++#endif
+
+ /************************************************************************/
+ /* ** GENERIC Initialization Routines */
+@@ -381,6 +394,7 @@ static int lcd_clear (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+ COLOR_MASK(lcd_getbgcolor()),
+ lcd_line_length*panel_info.vl_row);
+ #endif
++
+ /* Paint the logo and retrieve LCD base address */
+ debug ("[LCD] Drawing the logo...\n");
+ lcd_console_address = lcd_logo ();
+@@ -458,6 +472,8 @@ static void lcd_setfgcolor (int color)
+ {
+ #ifdef CONFIG_ATMEL_LCD
+ lcd_color_fg = color;
++#elif LCD_BPP == LCD_COLOR32
++ lcd_color_fg = color & 0xFFFFFFFF;
+ #else
+ lcd_color_fg = color & 0x0F;
+ #endif
+@@ -469,6 +485,8 @@ static void lcd_setbgcolor (int color)
+ {
+ #ifdef CONFIG_ATMEL_LCD
+ lcd_color_bg = color;
++#elif LCD_BPP == LCD_COLOR32
++ lcd_color_bg = color & 0xFFFFFFFF;
+ #else
+ lcd_color_bg = color & 0x0F;
+ #endif
+@@ -507,6 +525,7 @@ void bitmap_plot (int x, int y)
+ uchar *bmap;
+ uchar *fb;
+ ushort *fb16;
++ uint *fb32;
+ #if defined(CONFIG_PXA250)
+ struct pxafb_info *fbi = &panel_info.pxa;
+ #elif defined(CONFIG_MPC823)
+@@ -567,13 +586,25 @@ void bitmap_plot (int x, int y)
+ }
+ }
+ else { /* true color mode */
+- fb16 = (ushort *)(lcd_base + y * lcd_line_length + x);
+- for (i=0; i<BMP_LOGO_HEIGHT; ++i) {
+- for (j=0; j<BMP_LOGO_WIDTH; j++) {
+- fb16[j] = bmp_logo_palette[(bmap[j])];
++ if(NBITS(panel_info.vl_bpix) == 16){
++ fb16 = (ushort *)(lcd_base + y * lcd_line_length + x);
++ for (i=0; i<BMP_LOGO_HEIGHT; ++i) {
++ for (j=0; j<BMP_LOGO_WIDTH; j++) {
++ fb16[j] = bmp_logo_palette[(bmap[j])];
+ }
+- bmap += BMP_LOGO_WIDTH;
+- fb16 += panel_info.vl_col;
++ bmap += BMP_LOGO_WIDTH;
++ fb16 += panel_info.vl_col;
++ }
++ }
++ else{
++ fb32 = (uint *)(lcd_base + y * lcd_line_length + x);
++ for (i=0; i<BMP_LOGO_HEIGHT; ++i) {
++ for (j=0; j<BMP_LOGO_WIDTH; j++) {
++ fb32[j] = bmp_logo_palette[(bmap[j])];
++ }
++ bmap += BMP_LOGO_WIDTH;
++ fb32 += panel_info.vl_col;
++ }
+ }
+ }
+
+diff --git a/common/main.c b/common/main.c
+index 10d8904..ff11ad7 100644
+--- a/common/main.c
++++ b/common/main.c
+@@ -372,7 +372,9 @@ void main_loop (void)
+ #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
+ s = getenv ("bootdelay");
+ bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
+-
++ DECLARE_GLOBAL_DATA_PTR;
++ if (gd->boot_option == 5)
++ bootdelay = gd->boot_option;
+ debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);
+
+ # ifdef CONFIG_BOOT_RETRY_TIME
+@@ -393,7 +395,9 @@ void main_loop (void)
+ }
+ else
+ #endif /* CONFIG_BOOTCOUNT_LIMIT */
+- s = getenv ("bootcmd");
++ s = gd->boot_option == 1 ?
++ getenv ("bootcmdfromsd"):
++ getenv ("bootcmd") ;
+
+ debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
+
+diff --git a/cpu/mips/Makefile b/cpu/mips/Makefile
+index 28a1cbb..5207bc5 100644
+--- a/cpu/mips/Makefile
++++ b/cpu/mips/Makefile
+@@ -33,6 +33,9 @@ SOBJS-$(CONFIG_INCA_IP) += incaip_wdt.o
+ COBJS-$(CONFIG_INCA_IP) += asc_serial.o incaip_clock.o
+ COBJS-$(CONFIG_PURPLE) += asc_serial.o
+ COBJS-$(CONFIG_SOC_AU1X00) += au1x00_eth.o au1x00_serial.o au1x00_usb_ohci.o
++COBJS-$(CONFIG_JZSOC) += jz4740.o jz_serial.o jz_mmc.o jz4740_nand.o
++COBJS-$(CONFIG_NANONOTE) += nanonote_gpm940b0.o
++
+
+ SRCS := $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+ OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+diff --git a/cpu/mips/cache.S b/cpu/mips/cache.S
+index ff4f11c..cb3baff 100644
+--- a/cpu/mips/cache.S
++++ b/cpu/mips/cache.S
+@@ -23,32 +23,19 @@
+ */
+
+ #include <config.h>
+-#include <asm/asm.h>
++#include <version.h>
+ #include <asm/regdef.h>
+ #include <asm/mipsregs.h>
+ #include <asm/addrspace.h>
+ #include <asm/cacheops.h>
+
+-#define RA t8
++#ifndef CONFIG_JzRISC
+
+-/*
+- * 16kB is the maximum size of instruction and data caches on MIPS 4K,
+- * 64kB is on 4KE, 24K, 5K, etc. Set bigger size for convenience.
+- *
+- * Note that the above size is the maximum size of primary cache. U-Boot
+- * doesn't have L2 cache support for now.
+- */
+-#define MIPS_MAX_CACHE_SIZE 0x10000
+-
+-#define INDEX_BASE CKSEG0
++ /* 16KB is the maximum size of instruction and data caches on
++ * MIPS 4K.
++ */
++#define MIPS_MAX_CACHE_SIZE 0x4000
+
+- .macro cache_op op addr
+- .set push
+- .set noreorder
+- .set mips3
+- cache \op, 0(\addr)
+- .set pop
+- .endm
+
+ /*
+ * cacheop macro to automate cache operations
+@@ -119,79 +106,7 @@
+ #define icacheop(kva, n, cacheSize, cacheLineSize, op) \
+ icacheopn(kva, n, cacheSize, cacheLineSize, 1, (op))
+
+- .macro f_fill64 dst, offset, val
+- LONG_S \val, (\offset + 0 * LONGSIZE)(\dst)
+- LONG_S \val, (\offset + 1 * LONGSIZE)(\dst)
+- LONG_S \val, (\offset + 2 * LONGSIZE)(\dst)
+- LONG_S \val, (\offset + 3 * LONGSIZE)(\dst)
+- LONG_S \val, (\offset + 4 * LONGSIZE)(\dst)
+- LONG_S \val, (\offset + 5 * LONGSIZE)(\dst)
+- LONG_S \val, (\offset + 6 * LONGSIZE)(\dst)
+- LONG_S \val, (\offset + 7 * LONGSIZE)(\dst)
+-#if LONGSIZE == 4
+- LONG_S \val, (\offset + 8 * LONGSIZE)(\dst)
+- LONG_S \val, (\offset + 9 * LONGSIZE)(\dst)
+- LONG_S \val, (\offset + 10 * LONGSIZE)(\dst)
+- LONG_S \val, (\offset + 11 * LONGSIZE)(\dst)
+- LONG_S \val, (\offset + 12 * LONGSIZE)(\dst)
+- LONG_S \val, (\offset + 13 * LONGSIZE)(\dst)
+- LONG_S \val, (\offset + 14 * LONGSIZE)(\dst)
+- LONG_S \val, (\offset + 15 * LONGSIZE)(\dst)
+-#endif
+- .endm
+-
+-/*
+- * mips_init_icache(uint PRId, ulong icache_size, unchar icache_linesz)
+- */
+-LEAF(mips_init_icache)
+- blez a1, 9f
+- mtc0 zero, CP0_TAGLO
+- /* clear tag to invalidate */
+- PTR_LI t0, INDEX_BASE
+- PTR_ADDU t1, t0, a1
+-1: cache_op Index_Store_Tag_I t0
+- PTR_ADDU t0, a2
+- bne t0, t1, 1b
+- /* fill once, so data field parity is correct */
+- PTR_LI t0, INDEX_BASE
+-2: cache_op Fill t0
+- PTR_ADDU t0, a2
+- bne t0, t1, 2b
+- /* invalidate again - prudent but not strictly neccessary */
+- PTR_LI t0, INDEX_BASE
+-1: cache_op Index_Store_Tag_I t0
+- PTR_ADDU t0, a2
+- bne t0, t1, 1b
+-9: jr ra
+- END(mips_init_icache)
+-
+ /*
+- * mips_init_dcache(uint PRId, ulong dcache_size, unchar dcache_linesz)
+- */
+-LEAF(mips_init_dcache)
+- blez a1, 9f
+- mtc0 zero, CP0_TAGLO
+- /* clear all tags */
+- PTR_LI t0, INDEX_BASE
+- PTR_ADDU t1, t0, a1
+-1: cache_op Index_Store_Tag_D t0
+- PTR_ADDU t0, a2
+- bne t0, t1, 1b
+- /* load from each line (in cached space) */
+- PTR_LI t0, INDEX_BASE
+-2: LONG_L zero, 0(t0)
+- PTR_ADDU t0, a2
+- bne t0, t1, 2b
+- /* clear all tags */
+- PTR_LI t0, INDEX_BASE
+-1: cache_op Index_Store_Tag_D t0
+- PTR_ADDU t0, a2
+- bne t0, t1, 1b
+-9: jr ra
+- END(mips_init_dcache)
+-
+-/*******************************************************************************
+-*
+ * mips_cache_reset - low level initialisation of the primary caches
+ *
+ * This routine initialises the primary caches to ensure that they
+@@ -204,112 +119,129 @@ LEAF(mips_init_dcache)
+ * a source of parity.
+ *
+ * RETURNS: N/A
+-*
+ */
+-NESTED(mips_cache_reset, 0, ra)
+- move RA, ra
++ .globl mips_cache_reset
++ .ent mips_cache_reset
++mips_cache_reset:
++
+ li t2, CONFIG_SYS_ICACHE_SIZE
+ li t3, CONFIG_SYS_DCACHE_SIZE
+ li t4, CONFIG_SYS_CACHELINE_SIZE
+ move t5, t4
+
++
+ li v0, MIPS_MAX_CACHE_SIZE
+
+- /*
+- * Now clear that much memory starting from zero.
++ /* Now clear that much memory starting from zero.
+ */
+- PTR_LI a0, CKSEG1
+- PTR_ADDU a1, a0, v0
+-2: PTR_ADDIU a0, 64
+- f_fill64 a0, -64, zero
+- bne a0, a1, 2b
+-
+- /*
+- * The caches are probably in an indeterminate state,
+- * so we force good parity into them by doing an
+- * invalidate, load/fill, invalidate for each line.
++
++ li a0, KSEG1
++ addu a1, a0, v0
++
++2: sw zero, 0(a0)
++ sw zero, 4(a0)
++ sw zero, 8(a0)
++ sw zero, 12(a0)
++ sw zero, 16(a0)
++ sw zero, 20(a0)
++ sw zero, 24(a0)
++ sw zero, 28(a0)
++ addu a0, 32
++ bltu a0, a1, 2b
++
++ /* Set invalid tag.
+ */
+
+- /*
+- * Assume bottom of RAM will generate good parity for the cache.
++ mtc0 zero, CP0_TAGLO
++
++ /*
++ * The caches are probably in an indeterminate state,
++ * so we force good parity into them by doing an
++ * invalidate, load/fill, invalidate for each line.
++ */
++
++ /* Assume bottom of RAM will generate good parity for the cache.
+ */
+
+- /*
+- * Initialize the I-cache first,
++ li a0, K0BASE
++ move a2, t2 # icacheSize
++ move a3, t4 # icacheLineSize
++ move a1, a2
++ icacheopn(a0,a1,a2,a3,121,(Index_Store_Tag_I,Fill))
++
++ /* To support Orion/R4600, we initialise the data cache in 3 passes.
+ */
+- move a1, t2
+- move a2, t4
+- PTR_LA t7, mips_init_icache
+- jalr t7
+
+- /*
+- * then initialize D-cache.
++ /* 1: initialise dcache tags.
+ */
+- move a1, t3
+- move a2, t5
+- PTR_LA t7, mips_init_dcache
+- jalr t7
+
+- jr RA
+- END(mips_cache_reset)
++ li a0, K0BASE
++ move a2, t3 # dcacheSize
++ move a3, t5 # dcacheLineSize
++ move a1, a2
++ icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
+
+-/*******************************************************************************
+-*
+-* dcache_status - get cache status
+-*
+-* RETURNS: 0 - cache disabled; 1 - cache enabled
+-*
+-*/
+-LEAF(dcache_status)
+- mfc0 t0, CP0_CONFIG
+- li t1, CONF_CM_UNCACHED
+- andi t0, t0, CONF_CM_CMASK
+- move v0, zero
+- beq t0, t1, 2f
+- li v0, 1
+-2: jr ra
+- END(dcache_status)
+-
+-/*******************************************************************************
+-*
++ /* 2: fill dcache.
++ */
++
++ li a0, K0BASE
++ move a2, t3 # dcacheSize
++ move a3, t5 # dcacheLineSize
++ move a1, a2
++ icacheopn(a0,a1,a2,a3,1lw,(dummy))
++
++ /* 3: clear dcache tags.
++ */
++
++ li a0, K0BASE
++ move a2, t3 # dcacheSize
++ move a3, t5 # dcacheLineSize
++ move a1, a2
++ icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
++
++ j ra
++ .end mips_cache_reset
++
++
++/*
++ * dcache_status - get cache status
++ *
++ * RETURNS: 0 - cache disabled; 1 - cache enabled
++ */
++ .globl dcache_status
++ .ent dcache_status
++dcache_status:
++
++ mfc0 v0, CP0_CONFIG
++ andi v0, v0, 1
++ j ra
++
++ .end dcache_status
++
++/*
+ * dcache_disable - disable cache
+ *
+ * RETURNS: N/A
+-*
+ */
+-LEAF(dcache_disable)
++ .globl dcache_disable
++ .ent dcache_disable
++dcache_disable:
++
+ mfc0 t0, CP0_CONFIG
+ li t1, -8
+ and t0, t0, t1
+ ori t0, t0, CONF_CM_UNCACHED
+- mtc0 t0, CP0_CONFIG
+- jr ra
+- END(dcache_disable)
++ mtc0 t0, CP0_CONFIG
++ j ra
+
+-/*******************************************************************************
+-*
+-* dcache_enable - enable cache
+-*
+-* RETURNS: N/A
+-*
+-*/
+-LEAF(dcache_enable)
+- mfc0 t0, CP0_CONFIG
+- ori t0, CONF_CM_CMASK
+- xori t0, CONF_CM_CMASK
+- ori t0, CONF_CM_CACHABLE_NONCOHERENT
+- mtc0 t0, CP0_CONFIG
+- jr ra
+- END(dcache_enable)
+-
+-#ifdef CONFIG_SYS_INIT_RAM_LOCK_MIPS
+-/*******************************************************************************
+-*
+-* mips_cache_lock - lock RAM area pointed to by a0 in cache.
+-*
+-* RETURNS: N/A
+-*
+-*/
++ .end dcache_disable
++
++
++/*
++ * mips_cache_lock - lock RAM area pointed to by a0 in cache.
++ *
++ * RETURNS: N/A
++ */
+ #if defined(CONFIG_PURPLE)
+ # define CACHE_LOCK_SIZE (CONFIG_SYS_DCACHE_SIZE/2)
+ #else
+@@ -318,14 +250,14 @@ LEAF(dcache_enable)
+ .globl mips_cache_lock
+ .ent mips_cache_lock
+ mips_cache_lock:
+- li a1, CKSEG0 - CACHE_LOCK_SIZE
++ li a1, K0BASE - CACHE_LOCK_SIZE
+ addu a0, a1
+ li a2, CACHE_LOCK_SIZE
+ li a3, CONFIG_SYS_CACHELINE_SIZE
+ move a1, a2
+ icacheop(a0,a1,a2,a3,0x1d)
+
+- jr ra
+-
++ j ra
+ .end mips_cache_lock
+-#endif /* CONFIG_SYS_INIT_RAM_LOCK_MIPS */
++
++#endif /* CONFIG_JzRISC */
+diff --git a/cpu/mips/config.mk b/cpu/mips/config.mk
+index a173c54..8d27e52 100644
+--- a/cpu/mips/config.mk
++++ b/cpu/mips/config.mk
+@@ -25,15 +25,15 @@ MIPSFLAGS:=$(shell \
+ if [ "$v" -lt "14" ]; then \
+ echo "-mcpu=4kc"; \
+ else \
+- echo "-march=4kc -mtune=4kc"; \
++ echo "-march=4kc -mtune=r4600"; \
+ fi)
+
+ ifneq (,$(findstring 4KCle,$(CROSS_COMPILE)))
+ ENDIANNESS = -EL
+ else
+-ENDIANNESS = -EB
++#ENDIANNESS = -EB
+ endif
+
+-MIPSFLAGS += $(ENDIANNESS)
++MIPSFLAGS += $(ENDIANNESS) -mabicalls -mips32 -O2
+
+ PLATFORM_CPPFLAGS += $(MIPSFLAGS)
+diff --git a/cpu/mips/cpu.c b/cpu/mips/cpu.c
+index d5a1604..48e1cea 100644
+--- a/cpu/mips/cpu.c
++++ b/cpu/mips/cpu.c
+@@ -28,6 +28,12 @@
+ #include <asm/cacheops.h>
+ #include <asm/reboot.h>
+
++#ifdef CONFIG_JZ4740
++#include <asm/jz4740.h>
++#endif
++
++#if !defined (CONFIG_NAND_SPL) && !defined (CONFIG_MSC_SPL)
++
+ #define cache_op(op,addr) \
+ __asm__ __volatile__( \
+ " .set push \n" \
+@@ -40,6 +46,19 @@
+
+ void __attribute__((weak)) _machine_restart(void)
+ {
++#ifdef CONFIG_JZ4740
++ __wdt_select_extalclk();
++ __wdt_select_clk_div64();
++ __wdt_set_data(100);
++ __wdt_set_count(0);
++ __tcu_start_wdt_clock();
++ __wdt_start();
++ while(1);
++#endif
++#if defined(CONFIG_JzRISC)
++ void (*f)(void) = (void *) 0xbfc00000;
++ f();
++#endif
+ }
+
+ int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+@@ -110,3 +129,59 @@ int cpu_eth_init(bd_t *bis)
+ #endif
+ return 0;
+ }
++
++#endif /* !CONFIG_NAND_SPL !CONFIG_MSC_SPL */
++
++#ifdef CONFIG_JzRISC
++void flush_icache_all(void)
++{
++ u32 addr, t = 0;
++
++ asm volatile ("mtc0 $0, $28"); /* Clear Taglo */
++ asm volatile ("mtc0 $0, $29"); /* Clear TagHi */
++
++ for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_ICACHE_SIZE;
++ addr += CONFIG_SYS_CACHELINE_SIZE) {
++ asm volatile (
++ ".set mips3\n\t"
++ " cache %0, 0(%1)\n\t"
++ ".set mips2\n\t"
++ :
++ : "I" (Index_Store_Tag_I), "r"(addr));
++ }
++
++ /* invalicate btb */
++ asm volatile (
++ ".set mips32\n\t"
++ "mfc0 %0, $16, 7\n\t"
++ "nop\n\t"
++ "ori %0,2\n\t"
++ "mtc0 %0, $16, 7\n\t"
++ ".set mips2\n\t"
++ :
++ : "r" (t));
++}
++
++void flush_dcache_all(void)
++{
++ u32 addr;
++
++ for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_DCACHE_SIZE;
++ addr += CONFIG_SYS_CACHELINE_SIZE) {
++ asm volatile (
++ ".set mips3\n\t"
++ " cache %0, 0(%1)\n\t"
++ ".set mips2\n\t"
++ :
++ : "I" (Index_Writeback_Inv_D), "r"(addr));
++ }
++
++ asm volatile ("sync");
++}
++
++void flush_cache_all(void)
++{
++ flush_dcache_all();
++ flush_icache_all();
++}
++#endif /* CONFIG_JzRISC */
+diff --git a/cpu/mips/start.S b/cpu/mips/start.S
+index 57db589..fa6e352 100644
+--- a/cpu/mips/start.S
++++ b/cpu/mips/start.S
+@@ -23,32 +23,33 @@
+ */
+
+ #include <config.h>
++#include <version.h>
+ #include <asm/regdef.h>
+ #include <asm/mipsregs.h>
++#include <asm/addrspace.h>
++#include <asm/cacheops.h>
+
+- /*
+- * For the moment disable interrupts, mark the kernel mode and
+- * set ST0_KX so that the CPU does not spit fire when using
+- * 64-bit addresses.
+- */
+- .macro setup_c0_status set clr
+- .set push
+- mfc0 t0, CP0_STATUS
+- or t0, ST0_CU0 | \set | 0x1f | \clr
+- xor t0, 0x1f | \clr
+- mtc0 t0, CP0_STATUS
+- .set noreorder
+- sll zero, 3 # ehb
+- .set pop
+- .endm
+-
+- .macro setup_c0_status_reset
+-#ifdef CONFIG_64BIT
+- setup_c0_status ST0_KX 0
+-#else
+- setup_c0_status 0 0
++#ifdef CONFIG_JZ4730
++#include <asm/jz4730.h>
++#endif
++
++#ifdef CONFIG_JZ4740
++#include <asm/jz4740.h>
++#endif
++
++#ifdef CONFIG_JZ4750
++#include <asm/jz4750.h>
++#endif
++
++#ifdef CONFIG_JZ4750D
++#include <asm/jz4750d.h>
++#endif
++
++#if defined(CONFIG_JZ4750) || defined(CONFIG_JZ4750D)
++#define JZ4750_NANDBOOT_CFG0 (0x55555500 | (CFG_NAND_BW8*0xff))
++#define JZ4750_NANDBOOT_CFG1 0x55555555
++#define JZ4750_NANDBOOT_CFG2 ((CFG_NAND_PAGE_SIZE==2048)&0xff0000) | ((CFG_NAND_PAGE_SIZE!=512)&0xff00) | ((CFG_NAND_ROW_CYCLE==3)&0xff)
+ #endif
+- .endm
+
+ #define RVECENT(f,n) \
+ b f; nop
+@@ -61,6 +62,28 @@
+ .globl _start
+ .text
+ _start:
++#if defined(CONFIG_JZ4740)
++#if !defined(CONFIG_NAND_SPL) && !defined(CONFIG_NAND_U_BOOT)
++ .word JZ4740_NORBOOT_CFG /* fetched during NOR Boot */
++#else
++#if defined(CONFIG_NAND_SPL)
++ .word JZ4740_NANDBOOT_CFG /* fetched during NAND Boot */
++#endif
++#endif
++#endif /* CONFIG_JZ4740 */
++#if defined(CONFIG_JZ4750) || defined(CONFIG_JZ4750D)
++#if !defined(CONFIG_NAND_SPL) && !defined(CONFIG_NAND_U_BOOT)
++ .word JZ4750_NORBOOT_CFG /* fetched during NOR Boot */
++#else
++#if defined(CONFIG_NAND_SPL) && !defined(CONFIG_MSC_SPL)
++ /* First three words fetched by CPU during NAND Boot */
++ .word JZ4750_NANDBOOT_CFG0
++ .word JZ4750_NANDBOOT_CFG1
++ .word JZ4750_NANDBOOT_CFG2
++#endif
++#endif
++#endif /* CONFIG_JZ4750 || CONFIG_JZ4750D */
++#if !defined(CONFIG_JzRISC)
+ RVECENT(reset,0) /* U-boot entry point */
+ RVECENT(reset,1) /* software reboot */
+ #if defined(CONFIG_INCA_IP)
+@@ -213,7 +236,7 @@ _start:
+ .word 0x00000000
+ .word 0x03e00008
+ .word 0x00000000
+- .word 0x00000000
++ .word 0x00000000
+ /* 0xbfc00428 */
+ .word 0xdc870000
+ .word 0xfca70000
+@@ -224,74 +247,192 @@ _start:
+ .word 0x00000000
+ .word 0x03e00008
+ .word 0x00000000
+- .word 0x00000000
++ .word 0x00000000
+ #endif /* CONFIG_PURPLE */
+ .align 4
++#endif /* CONFIG_JzRISC */
++
+ reset:
+
++#if !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL)
++
++#ifdef CONFIG_JZ4730
++
++ /* Disable interrupts */
++ la t0, INTC_IMR
++ li t1, 0xffffffff
++ sw t1, 0(t0)
++
++ /*
++ * Clear SCR.HGP
++ */
++ la t0, CPM_SCR
++ lw t1, 0(t0)
++ ori t1, 0x8
++ xori t1, 0x8
++ sw t1, 0(t0)
++
++ /*
++ * Set usb port0 as host
++ */
++ la t0, HARB_HAPOR
++ lw t1, 0(t0)
++ ori t1, HARB_HAPOR_UCHSEL
++ sw t1, 0(t0)
++
++ /*
++ * Check reset status
++ */
++ la t0, CPM_RSTR
++ lw t1, 0(t0)
++ andi t1, 0x4
++ bnez t1, resume_from_hibernate
++ nop
++#endif /* CONFIG_JZ4730 */
++
++#ifndef CONFIG_NAND_SPL
+ /* Clear watch registers.
+ */
+ mtc0 zero, CP0_WATCHLO
+ mtc0 zero, CP0_WATCHHI
++#endif
+
+- /* WP(Watch Pending), SW0/1 should be cleared. */
+- mtc0 zero, CP0_CAUSE
++ /* STATUS register */
++#ifdef CONFIG_JzRISC
++ /*
++ * CU0=UM=EXL=IE=0, BEV=ERL=1, IP2~7=1
++ */
++ li t0, 0x0040FC04
++ mtc0 t0, CP0_STATUS
++#else
++#ifdef CONFIG_TB0229
++ li k0, ST0_CU0
++#else
++ mfc0 k0, CP0_STATUS
++#endif
++ li k1, ~ST0_IE
++ and k0, k1
++ mtc0 k0, CP0_STATUS
++#endif
+
+- setup_c0_status_reset
++ /* CAUSE register */
++#ifdef CONFIG_JzRISC
++ /* IV=1, use the specical interrupt vector (0x200) */
++ li t1, 0x00800000
++ mtc0 t1, CP0_CAUSE
++#else
++ mtc0 zero, CP0_CAUSE
++#endif
+
++#ifndef CONFIG_JzRISC
+ /* Init Timer */
+ mtc0 zero, CP0_COUNT
+ mtc0 zero, CP0_COMPARE
++#endif
+
+-#if !defined(CONFIG_SKIP_LOWLEVEL_INIT)
++#endif /* !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) */
++
++#if !defined(CONFIG_NAND_SPL) && !defined(CONFIG_NAND_U_BOOT)
+ /* CONFIG0 register */
+ li t0, CONF_CM_UNCACHED
+ mtc0 t0, CP0_CONFIG
+-#endif /* !CONFIG_SKIP_LOWLEVEL_INIT */
++#endif
+
+- /* Initialize $gp.
++ /* Initialize GOT pointer.
++ */
++ bal 1f
++ nop
++ .word _GLOBAL_OFFSET_TABLE_
++ 1:
++ move gp, ra
++ lw t1, 0(ra)
++ move gp, t1
++
++#ifdef CONFIG_INCA_IP
++ /* Disable INCA-IP Watchdog.
+ */
+- bal 1f
++ la t9, disable_incaip_wdt
++ jalr t9
+ nop
+- .word _gp
+-1:
+- lw gp, 0(ra)
++#endif
+
+-#if !defined(CONFIG_SKIP_LOWLEVEL_INIT)
++/* JzRISC will init external memory in board_init_f,
++ which uses cache as stack and calls into C code. */
++#ifndef CONFIG_JzRISC
+ /* Initialize any external memory.
+ */
+- la t9, lowlevel_init
+- jalr t9
++ la t9, lowlevel_init
++ jalr t9
+ nop
++#endif
+
++#if !defined(CONFIG_NAND_SPL) && !defined(CONFIG_NAND_U_BOOT)
+ /* Initialize caches...
+ */
+- la t9, mips_cache_reset
+- jalr t9
++#ifdef CONFIG_JzRISC
++ .set mips32
++ mtc0 zero, CP0_TAGLO
++ mtc0 zero, CP0_TAGHI
++
++ li t0, K0BASE
++ ori t1, t0, CONFIG_SYS_DCACHE_SIZE
++1:
++ cache Index_Store_Tag_D, 0(t0)
++ bne t0, t1, 1b
++ addiu t0, t0, CONFIG_SYS_CACHELINE_SIZE
++
++ li t0, K0BASE
++ ori t1, t0, CONFIG_SYS_ICACHE_SIZE
++2:
++ cache Index_Store_Tag_I, 0(t0)
++ bne t0, t1, 2b
++ addiu t0, t0, CONFIG_SYS_CACHELINE_SIZE
++
++ /* Invalidate BTB */
++ mfc0 t0, CP0_CONFIG, 7
++ nop
++ ori t0, 2
++ mtc0 t0, CP0_CONFIG, 7
+ nop
+
++ .set mips2
++#else
++ la t9, mips_cache_reset
++ jalr t9
++ nop
++#endif
++
+ /* ... and enable them.
+ */
+ li t0, CONF_CM_CACHABLE_NONCOHERENT
+ mtc0 t0, CP0_CONFIG
+-#endif /* !CONFIG_SKIP_LOWLEVEL_INIT */
++ nop
++
++#endif /* !defined(CONFIG_NAND_SPL) && !defined(CONFIG_NAND_U_BOOT) */
+
+ /* Set up temporary stack.
+ */
+-#ifdef CONFIG_SYS_INIT_RAM_LOCK_MIPS
++#ifndef CONFIG_JzRISC
+ li a0, CONFIG_SYS_INIT_SP_OFFSET
+- la t9, mips_cache_lock
+- jalr t9
++ la t9, mips_cache_lock
++ jalr t9
+ nop
+ #endif
+
++#ifdef CONFIG_NAND_SPL
++ la sp, 0x80004000
++ la t9, nand_boot
++ j t9
++ nop
++#else
+ li t0, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET
+ la sp, 0(t0)
+
+ la t9, board_init_f
+- jr t9
++ j t9
+ nop
+
++
+ /*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+@@ -305,37 +446,28 @@ reset:
+ .globl relocate_code
+ .ent relocate_code
+ relocate_code:
+- move sp, a0 /* Set new stack pointer */
++ move sp, a0 /* Set new stack pointer */
+
+- li t0, CONFIG_SYS_MONITOR_BASE
++ li t0, TEXT_BASE
+ la t3, in_ram
+ lw t2, -12(t3) /* t2 <-- uboot_end_data */
+ move t1, a2
+- move s2, a2 /* s2 <-- destination address */
+
+ /*
+- * Fix $gp:
++ * Fix GOT pointer:
+ *
+- * New $gp = (Old $gp - CONFIG_SYS_MONITOR_BASE) + Destination Address
++ * New GOT-PTR = (old GOT-PTR - TEXT_BASE) + Destination Address
+ */
+ move t6, gp
+- sub gp, CONFIG_SYS_MONITOR_BASE
+- add gp, a2 /* gp now adjusted */
+- sub s1, gp, t6 /* s1 <-- relocation offset */
++ sub gp, TEXT_BASE
++ add gp, a2 /* gp now adjusted */
++ sub t6, gp, t6 /* t6 <-- relocation offset */
+
+ /*
+ * t0 = source address
+ * t1 = target address
+ * t2 = source end address
+ */
+-
+- /*
+- * Save destination address and size for later usage in flush_cache()
+- */
+- move s0, a1 /* save gd in s0 */
+- move a0, t1 /* a0 <-- destination addr */
+- sub a1, t2, t0 /* a1 <-- size */
+-
+ /* On the purple board we copy the code earlier in a special way
+ * in order to solve flash problems
+ */
+@@ -345,47 +477,61 @@ relocate_code:
+ sw t3, 0(t1)
+ addu t0, 4
+ ble t0, t2, 1b
+- addu t1, 4 /* delay slot */
++ addu t1, 4 /* delay slot */
+ #endif
+
+ /* If caches were enabled, we would have to flush them here.
+ */
+-
+- /* a0 & a1 are already set up for flush_cache(start, size) */
+- la t9, flush_cache
+- jalr t9
++#ifdef CONFIG_JzRISC
++ /* flush d-cache */
++ .set mips32
++ li t0, KSEG0
++ addi t1, t0, CONFIG_SYS_DCACHE_SIZE
++2:
++ cache Index_Writeback_Inv_D, 0(t0)
++ bne t0, t1, 2b
++ addi t0, CONFIG_SYS_CACHELINE_SIZE
++
++ sync
++
++ /* flush i-cache */
++ li t0, KSEG0
++ addi t1, t0, CONFIG_SYS_ICACHE_SIZE
++3:
++ cache Index_Invalidate_I, 0(t0)
++ bne t0, t1, 3b
++ addi t0, CONFIG_SYS_CACHELINE_SIZE
++
++ /* Invalidate BTB */
++ mfc0 t0, CP0_CONFIG, 7
++ nop
++ ori t0, 2
++ mtc0 t0, CP0_CONFIG, 7
+ nop
+
++ .set mips0
++#endif
++
+ /* Jump to where we've relocated ourselves.
+ */
+- addi t0, s2, in_ram - _start
+- jr t0
++ addi t0, a2, in_ram - _start
++ j t0
+ nop
+
+- .word _gp
+- .word _GLOBAL_OFFSET_TABLE_
+ .word uboot_end_data
+ .word uboot_end
+ .word num_got_entries
+
+ in_ram:
+- /*
+- * Now we want to update GOT.
+- *
+- * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
+- * generated by GNU ld. Skip these reserved entries from relocation.
++ /* Now we want to update GOT.
+ */
+ lw t3, -4(t0) /* t3 <-- num_got_entries */
+- lw t4, -16(t0) /* t4 <-- _GLOBAL_OFFSET_TABLE_ */
+- lw t5, -20(t0) /* t5 <-- _gp */
+- sub t4, t5 /* compute offset*/
+- add t4, t4, gp /* t4 now holds relocated _GLOBAL_OFFSET_TABLE_ */
+- addi t4, t4, 8 /* Skipping first two entries. */
++ addi t4, gp, 8 /* Skipping first two entries. */
+ li t2, 2
+ 1:
+ lw t1, 0(t4)
+ beqz t1, 2f
+- add t1, s1
++ add t1, t6
+ sw t1, 0(t4)
+ 2:
+ addi t2, 1
+@@ -396,26 +542,134 @@ in_ram:
+ */
+ lw t1, -12(t0) /* t1 <-- uboot_end_data */
+ lw t2, -8(t0) /* t2 <-- uboot_end */
+- add t1, s1 /* adjust pointers */
+- add t2, s1
++ add t1, t6 /* adjust pointers */
++ add t2, t6
+
+ sub t1, 4
+-1:
+- addi t1, 4
++1: addi t1, 4
+ bltl t1, t2, 1b
+ sw zero, 0(t1) /* delay slot */
+
+- move a0, s0 /* a0 <-- gd */
++ move a0, a1
+ la t9, board_init_r
+- jr t9
+- move a1, s2 /* delay slot */
++ j t9
++ move a1, a2 /* delay slot */
+
+ .end relocate_code
+
++#endif /* CONFIG_NAND_SPL */
++
++#if !defined(CONFIG_JzRISC)
+ /* Exception handlers.
+ */
+ romReserved:
+- b romReserved
++ b romReserved
+
+ romExcHandle:
+- b romExcHandle
++ b romExcHandle
++#endif
++
++#ifdef CONFIG_JZ4730
++
++/* These are the runtime values, modify them according to your platform. */
++#define PLCR1_VAL 0x1b000520
++#define CFCR_VAL 0x0c526220
++
++#define DMCR_VAL0 0x042a3211
++#define DMCR_VAL1 0x05aa3211 /*(DMCR_VAL0|EMC_DMCR_RFSH|EMC_DMCR_MRSET)*/
++
++#define RTCOR_VAL 0x10
++#define RTCSR_VAL 0x83
++
++ /*
++ * cpu was reset from hibernate mode
++ */
++resume_from_hibernate:
++ /*
++ * Init PLL
++ */
++ la t0, 0xB0000000 /* CFCR */
++ li t1, CFCR_VAL
++ sw t1, 0(t0)
++
++ la t0, 0xB0000010 /* PLCR1 */
++ li t1, PLCR1_VAL
++ sw t1, 0(t0)
++ nop;nop;nop;nop
++
++ /* Init caches */
++ .set mips32
++ mtc0 zero, CP0_TAGLO
++ mtc0 zero, CP0_TAGHI
++
++ li t0, K0BASE
++ ori t1, t0, CONFIG_SYS_DCACHE_SIZE
++1:
++ cache Index_Store_Tag_D, 0(t0)
++ cache Index_Store_Tag_I, 0(t0)
++ bne t0, t1, 1b
++ addiu t0, t0, CONFIG_SYS_CACHELINE_SIZE
++
++ /*
++ * Init SDRAM
++ */
++ la t0, 0xB0010070 /* GPALR2 */
++ lw t1, 0(t0)
++ li t2, 0x3FFFFFFF
++ and t1, t2
++ li t2, 0x40000000
++ or t1, t2
++ sw t1, 0(t0)
++
++ la t0, 0xB0010074 /* GPAUR2 */
++ lw t1, 0(t0)
++ li t2, 0xFFFF0000
++ and t1, t2
++ li t2, 0x00005555
++ or t1, t2
++ sw t1, 0(t0)
++
++ la t0, 0xB3010000 /* EMC base address */
++
++ li t1, DMCR_VAL0 /* DMCR */
++ sw t1, 0x80(t0)
++
++ li t1, RTCOR_VAL
++ sh t1, 0x8c(t0) /* RTCOR */
++
++ li t1, RTCSR_VAL
++ sh t1, 0x84(t0) /* RTCSR */
++
++ /* precharge all chip-selects */
++ ori t1, t0, 0xa088
++ sb $0, 0(t1)
++ ori t1, t0, 0xb088
++ sb $0, 0(t1)
++
++ /* delay about 200us */
++ li t1, 0x20000
++1:
++ bnez t1, 1b
++ sub t1, 1
++
++ la t1, DMCR_VAL1 /* DMCR */
++ sw t1, 0x80(t0)
++
++ /* write sdram mode register for each chip-select */
++ ori t1, t0, 0xa088
++ sb $0, 0(t1)
++ ori t1, t0, 0xb088
++ sb $0, 0(t1)
++
++ /*
++ * jump to resume entry point
++ */
++ la t0, CPM_SPR
++ lw t1, 0(t0)
++ li t0, 0x80000000
++ or t0, t1
++
++ j t0
++ nop
++
++#endif /* CONFIG_JZ4730 */
+diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
+index 426bb95..6e5fbd3 100644
+--- a/drivers/mtd/nand/nand_base.c
++++ b/drivers/mtd/nand/nand_base.c
+@@ -109,6 +109,22 @@ static struct nand_ecclayout nand_oob_16 = {
+ . length = 8}}
+ };
+
++#if defined(CONFIG_JZ4740)
++static struct nand_ecclayout nand_oob_64 = {
++ .eccbytes = 36,
++ .eccpos = {
++ 6, 7, 8, 9, 10, 11, 12, 13,
++ 14, 15, 16, 17, 18, 19, 20, 21,
++ 22, 23, 24, 25, 26, 27, 28, 29,
++ 30, 31, 32, 33, 34, 35, 36, 37,
++ 38, 39, 40, 41},
++ .oobfree ={
++ {.offset = 2,
++ .length = 4},
++ {.offset = 42,
++ .length = 22}}
++};
++#else
+ static struct nand_ecclayout nand_oob_64 = {
+ .eccbytes = 24,
+ .eccpos = {
+@@ -119,6 +135,7 @@ static struct nand_ecclayout nand_oob_64 = {
+ {.offset = 2,
+ .length = 38}}
+ };
++#endif
+
+ static struct nand_ecclayout nand_oob_128 = {
+ .eccbytes = 48,
+@@ -1116,6 +1133,60 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
+ }
+
+ /**
++ * nand_read_page_hwecc_rs - [REPLACABLE] hardware rs ecc based page read function
++ * @mtd: mtd info structure
++ * @chip: nand chip info structure
++ * @buf: buffer to store read data
++ *
++ * Not for syndrome calculating ecc controllers which need a special oob layout
++ */
++static int nand_read_page_hwecc_rs(struct mtd_info *mtd, struct nand_chip *chip,
++ uint8_t *buf)
++{
++ int i, eccsize = chip->ecc.size;
++ int eccbytes = chip->ecc.bytes;
++ int eccsteps = chip->ecc.steps;
++ uint8_t *p = buf;
++ uint8_t *ecc_calc = chip->buffers->ecccalc;
++ uint8_t *ecc_code = chip->buffers->ecccode;
++ uint32_t *eccpos = chip->ecc.layout->eccpos;
++ uint32_t page;
++ uint8_t flag = 0;
++
++ page = (buf[3]<<24) + (buf[2]<<16) + (buf[1]<<8) + buf[0];
++
++ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
++ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
++
++ for (i = 0; i < chip->ecc.total; i++) {
++ ecc_code[i] = chip->oob_poi[CONFIG_SYS_NAND_ECC_POS + i];
++ if (ecc_code[i] != 0xff)
++ flag = 1;
++ }
++
++ eccsteps = chip->ecc.steps;
++ p = buf;
++
++ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0x00, -1);
++ for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
++ int stat;
++ if (flag) {
++ chip->ecc.hwctl(mtd, NAND_ECC_READ);
++ chip->read_buf(mtd, p, eccsize);
++ stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
++ if (stat < 0)
++ mtd->ecc_stats.failed++;
++ else
++ mtd->ecc_stats.corrected += stat;
++ }
++ else {
++ chip->ecc.hwctl(mtd, NAND_ECC_READ);
++ chip->read_buf(mtd, p, eccsize);
++ }
++ }
++ return 0;
++}
++/**
+ * nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+@@ -1271,9 +1342,17 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
+ bufpoi, page);
+ else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)
+ ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi);
+- else
++ else {
++#if defined(CONFIG_JZ4740)
++ bufpoi[0] = (uint8_t)page;
++ bufpoi[1] = (uint8_t)(page >> 8);
++ bufpoi[2] = (uint8_t)(page >> 16);
++ bufpoi[3] = (uint8_t)(page >> 24);
++#endif
++
+ ret = chip->ecc.read_page(mtd, chip, bufpoi,
+ page);
++ }
+ if (ret < 0)
+ break;
+
+@@ -2791,8 +2870,13 @@ int nand_scan_tail(struct mtd_info *mtd)
+
+ case NAND_ECC_HW:
+ /* Use standard hwecc read page function ? */
+- if (!chip->ecc.read_page)
++ if (!chip->ecc.read_page) {
++#if defined(CONFIG_JZ4740)
++ chip->ecc.read_page = nand_read_page_hwecc_rs;
++#else
+ chip->ecc.read_page = nand_read_page_hwecc;
++#endif
++ }
+ if (!chip->ecc.write_page)
+ chip->ecc.write_page = nand_write_page_hwecc;
+ if (!chip->ecc.read_oob)
+diff --git a/examples/standalone/mips.lds b/examples/standalone/mips.lds
+index 717b201..d4a45f8 100644
+--- a/examples/standalone/mips.lds
++++ b/examples/standalone/mips.lds
+@@ -23,8 +23,8 @@
+
+ /*
+ OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-bigmips")
+-*/
+ OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradbigmips")
++*/
+ OUTPUT_ARCH(mips)
+ SECTIONS
+ {
+diff --git a/include/asm-mips/addrspace.h b/include/asm-mips/addrspace.h
+index 3a1e6d6..2ee6920 100644
+--- a/include/asm-mips/addrspace.h
++++ b/include/asm-mips/addrspace.h
+@@ -131,7 +131,7 @@
+ * Returns the uncached address of a sdram address
+ */
+ #ifndef __ASSEMBLY__
+-#if defined(CONFIG_SOC_AU1X00) || defined(CONFIG_TB0229)
++#if defined(CONFIG_SOC_AU1X00) || defined(CONFIG_TB0229) || defined(CONFIG_JzRISC)
+ /* We use a 36 bit physical address map here and
+ cannot access physical memory directly from core */
+ #define UNCACHED_SDRAM(a) (((unsigned long)(a)) | 0x20000000)
+diff --git a/include/asm-mips/global_data.h b/include/asm-mips/global_data.h
+index b2c4891..23f597e 100644
+--- a/include/asm-mips/global_data.h
++++ b/include/asm-mips/global_data.h
+@@ -39,6 +39,17 @@
+ typedef struct global_data {
+ bd_t *bd;
+ unsigned long flags;
++#if defined(CONFIG_JZSOC)
++ /* There are other clocks in the Jz47xx or Jz5730*/
++ unsigned long cpu_clk; /* CPU core clock */
++ unsigned long sys_clk; /* System bus clock */
++ unsigned long per_clk; /* Peripheral bus clock */
++ unsigned long mem_clk; /* Memory bus clock */
++ unsigned long dev_clk; /* Device clock */
++ unsigned long fb_base; /* base address of framebuffer */
++ unsigned long boot_option; /* 1: boot from sd
++ * 5: boot delay for 5 secs*/
++#endif
+ unsigned long baudrate;
+ unsigned long have_console; /* serial_init() was called */
+ phys_size_t ram_size; /* RAM size */
+diff --git a/include/lcd.h b/include/lcd.h
+index 1f85daa..997e246 100644
+--- a/include/lcd.h
++++ b/include/lcd.h
+@@ -181,8 +181,44 @@ typedef struct vidinfo {
+ u_long mmio; /* Memory mapped registers */
+ } vidinfo_t;
+
+-#else
++#elif defined(CONFIG_JZSOC)
++/*
++ * LCD controller stucture for JZSOC: JZ4730 JZ4740
++ */
++struct jz_fb_dma_descriptor {
++ u_long fdadr; /* Frame descriptor address register */
++ u_long fsadr; /* Frame source address register */
++ u_long fidr; /* Frame ID register */
++ u_long ldcmd; /* Command register */
++};
+
++/*
++ * Jz LCD info
++ */
++struct jz_fb_info {
++
++ u_long fdadr0; /* physical address of frame/palette descriptor */
++ u_long fdadr1; /* physical address of frame descriptor */
++
++ /* DMA descriptors */
++ struct jz_fb_dma_descriptor * dmadesc_fblow;
++ struct jz_fb_dma_descriptor * dmadesc_fbhigh;
++ struct jz_fb_dma_descriptor * dmadesc_palette;
++ u_long screen; /* address of frame buffer */
++ u_long palette; /* address of palette memory */
++ u_int palette_size;
++};
++typedef struct vidinfo {
++ ushort vl_col; /* Number of columns (i.e. 640) */
++ ushort vl_row; /* Number of rows (i.e. 480) */
++ u_char vl_bpix; /* Bits per pixel, 0 = 1, 1 = 2, 2 = 4, 3 = 8 */
++
++ struct jz_fb_info jz_fb;
++} vidinfo_t;
++
++extern vidinfo_t panel_info;
++
++#else
+ typedef struct vidinfo {
+ ushort vl_col; /* Number of columns (i.e. 160) */
+ ushort vl_row; /* Number of rows (i.e. 100) */
+@@ -194,7 +230,7 @@ typedef struct vidinfo {
+ void *priv; /* Pointer to driver-specific data */
+ } vidinfo_t;
+
+-#endif /* CONFIG_MPC823, CONFIG_PXA250 or CONFIG_MCC200 or CONFIG_ATMEL_LCD */
++#endif /* CONFIG_MPC823, CONFIG_PXA250, CONFIG_MCC200 or CONFIG_JZ4740 */
+
+ extern vidinfo_t panel_info;
+
+@@ -234,6 +270,7 @@ void lcd_show_board_info(void);
+ #define LCD_COLOR4 2
+ #define LCD_COLOR8 3
+ #define LCD_COLOR16 4
++#define LCD_COLOR32 5
+
+ /*----------------------------------------------------------------------*/
+ #if defined(CONFIG_LCD_INFO_BELOW_LOGO)
+@@ -285,13 +322,22 @@ void lcd_show_board_info(void);
+ # define CONSOLE_COLOR_GREY 14
+ # define CONSOLE_COLOR_WHITE 15 /* Must remain last / highest */
+
+-#else
++#elif LCD_BPP == LCD_COLOR16
+
+ /*
+ * 16bpp color definitions
+ */
+ # define CONSOLE_COLOR_BLACK 0x0000
+-# define CONSOLE_COLOR_WHITE 0xffff /* Must remain last / highest */
++# define CONSOLE_COLOR_WHITE 0xffff /* Must remain last / highest */
++
++#elif LCD_BPP == LCD_COLOR32
++/*
++ * 18,24,32 bpp color definitions
++ */
++# define CONSOLE_COLOR_BLACK 0x00000000
++# define CONSOLE_COLOR_WHITE 0xffffffff /* Must remain last / highest */
++
++#else
+
+ #endif /* color definitions */
+
+@@ -322,7 +368,7 @@ void lcd_show_board_info(void);
+ #if LCD_BPP == LCD_MONOCHROME
+ # define COLOR_MASK(c) ((c) | (c) << 1 | (c) << 2 | (c) << 3 | \
+ (c) << 4 | (c) << 5 | (c) << 6 | (c) << 7)
+-#elif (LCD_BPP == LCD_COLOR8) || (LCD_BPP == LCD_COLOR16)
++#elif (LCD_BPP == LCD_COLOR8) || (LCD_BPP == LCD_COLOR16) || (LCD_BPP == LCD_COLOR32)
+ # define COLOR_MASK(c) (c)
+ #else
+ # error Unsupported LCD BPP.
+diff --git a/lib_mips/board.c b/lib_mips/board.c
+index b2d113e..87cb12d 100644
+--- a/lib_mips/board.c
++++ b/lib_mips/board.c
+@@ -49,6 +49,10 @@ DECLARE_GLOBAL_DATA_PTR;
+
+ #undef DEBUG
+
++#if defined(CONFIG_JZSOC)
++extern int jz_board_init(void);
++#endif
++
+ extern int timer_init(void);
+
+ extern int incaip_set_cpuclk(void);
+@@ -78,7 +82,6 @@ int __board_early_init_f(void)
+ }
+ int board_early_init_f(void) __attribute__((weak, alias("__board_early_init_f")));
+
+-
+ static int init_func_ram (void)
+ {
+ #ifdef CONFIG_BOARD_TYPES
+@@ -98,7 +101,6 @@ static int init_func_ram (void)
+
+ static int display_banner(void)
+ {
+-
+ printf ("\n\n%s\n\n", version_string);
+ return (0);
+ }
+@@ -147,6 +149,9 @@ static int init_baudrate (void)
+ typedef int (init_fnc_t) (void);
+
+ init_fnc_t *init_sequence[] = {
++#if defined(CONFIG_JZSOC)
++ jz_board_init, /* init gpio/clocks/dram etc. */
++#endif
+ board_early_init_f,
+ timer_init,
+ env_init, /* initialize environment */
+@@ -162,7 +167,6 @@ init_fnc_t *init_sequence[] = {
+ NULL,
+ };
+
+-
+ void board_init_f(ulong bootflag)
+ {
+ gd_t gd_data, *id;
+@@ -202,6 +206,12 @@ void board_init_f(ulong bootflag)
+ addr &= ~(4096 - 1);
+ debug ("Top of RAM usable for U-Boot at: %08lx\n", addr);
+
++#ifdef CONFIG_LCD
++ /* reserve memory for LCD display (always full pages) */
++ addr = lcd_setmem (addr);
++ gd->fb_base = addr;
++#endif /* CONFIG_LCD */
++
+ /* Reserve memory for U-Boot code, data & bss
+ * round down to next 16 kB limit
+ */
+@@ -349,9 +359,9 @@ void board_init_r (gd_t *id, ulong dest_addr)
+ size = flash_init();
+ display_flash_config (size);
+ bd->bi_flashsize = size;
++ bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
+ #endif
+
+- bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
+ #if CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE
+ bd->bi_flashoffset = monitor_flash_len; /* reserved area for U-Boot */
+ #else
+diff --git a/lib_mips/bootm.c b/lib_mips/bootm.c
+index 54af24c..64bcad9 100644
+--- a/lib_mips/bootm.c
++++ b/lib_mips/bootm.c
+@@ -46,7 +46,9 @@ static void linux_env_set (char * env_name, char * env_val);
+ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+ {
+ void (*theKernel) (int, char **, char **, int *);
+- char *commandline = getenv ("bootargs");
++ char *commandline = gd->boot_option == 1 ?
++ getenv ("bootargsfromsd") :
++ getenv ("bootargs");
+ char env_buf[12];
+ char *cp;
+
+@@ -98,6 +100,9 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+ }
+
+ /* we assume that the kernel is in place */
++ if (gd->boot_option == 1)
++ printf ("\n *** Booting from mircoSD ***\n");
++
+ printf ("\nStarting kernel ...\n\n");
+
+ theKernel (linux_argc, linux_argv, linux_env, 0);
+diff --git a/lib_mips/time.c b/lib_mips/time.c
+index 07e356d..4654bf4 100644
+--- a/lib_mips/time.c
++++ b/lib_mips/time.c
+@@ -24,6 +24,8 @@
+ #include <common.h>
+ #include <asm/mipsregs.h>
+
++#ifndef CONFIG_JzRISC
++
+ static unsigned long timestamp;
+
+ /* how many counter cycles in a jiffy */
+@@ -96,3 +98,5 @@ ulong get_tbclk(void)
+ {
+ return CONFIG_SYS_HZ;
+ }
++
++#endif /* !CONFIG_JzRISC */
+
diff --git a/package/uboot-xburst/patches/005-i2c.patch b/package/uboot-xburst/patches/005-i2c.patch
new file mode 100644
index 000000000..b8ad22f0e
--- /dev/null
+++ b/package/uboot-xburst/patches/005-i2c.patch
@@ -0,0 +1,13 @@
+diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
+index ef32f13..4e234b4 100644
+--- a/drivers/i2c/Makefile
++++ b/drivers/i2c/Makefile
+@@ -36,6 +36,7 @@ COBJS-$(CONFIG_DRIVER_S3C24X0_I2C) += s3c24x0_i2c.o
+ COBJS-$(CONFIG_S3C44B0_I2C) += s3c44b0_i2c.o
+ COBJS-$(CONFIG_SOFT_I2C) += soft_i2c.o
+ COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
++COBJS-$(CONFIG_JZSOC_I2C) += jz_i2c.o
+
+ COBJS := $(COBJS-y)
+ SRCS := $(COBJS:.o=.c)
+
diff --git a/package/uboot-xburst/patches/009-n516.patch b/package/uboot-xburst/patches/009-n516.patch
new file mode 100644
index 000000000..49eaf3da4
--- /dev/null
+++ b/package/uboot-xburst/patches/009-n516.patch
@@ -0,0 +1,23 @@
+diff --git a/Makefile b/Makefile
+index ed848f5..04cd32e 100644
+--- a/Makefile
++++ b/Makefile
+@@ -3448,6 +3448,18 @@ pavo_nand_config : unconfig
+ @echo "TEXT_BASE = 0x80100000" > $(obj)board/qi_lb60/config.tmp
+ @echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk
+
++n516_config : unconfig
++ @ >include/config.h
++ @echo "#define CONFIG_N516 1" >>include/config.h
++ @./mkconfig -a n516 mips mips n516
++
++n516_nand_config : unconfig
++ @echo "#define CONFIG_NAND_U_BOOT" > $(obj)include/config.h
++ @echo "Compile NAND boot image for n516"
++ @./mkconfig -a n516 mips mips n516
++ @echo "TEXT_BASE = 0x80100000" > $(obj)board/n516/config.tmp
++ @echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk
++
+ #########################################################################
+ ## MIPS64 5Kc
+ #########################################################################
diff --git a/package/uboot-xburst/patches/010-sakc.patch b/package/uboot-xburst/patches/010-sakc.patch
new file mode 100644
index 000000000..2ec82b7dc
--- /dev/null
+++ b/package/uboot-xburst/patches/010-sakc.patch
@@ -0,0 +1,32 @@
+diff --git a/Makefile b/Makefile
+index a318eb4..7d14b8b 100644
+--- a/Makefile
++++ b/Makefile
+@@ -3448,6 +3448,13 @@ qi_lb60_config : unconfig
+ @echo "TEXT_BASE = 0x80100000" > $(obj)board/n516/config.tmp
+ @echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk
+
++sakc_config : unconfig
++ @echo "#define CONFIG_NAND_U_BOOT" > $(obj)include/config.h
++ @echo "Compile NAND boot image for SAKC"
++ @$(MKCONFIG) -a sakc mips mips sakc
++ @echo "TEXT_BASE = 0x80100000" > $(obj)board/sakc/config.tmp
++ @echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk
++
+ #########################################################################
+ ## MIPS64 5Kc
+ #########################################################################
+diff --git a/cpu/mips/Makefile b/cpu/mips/Makefile
+index 33afb66..a177653 100644
+--- a/cpu/mips/Makefile
++++ b/cpu/mips/Makefile
+@@ -35,7 +35,7 @@ COBJS-$(CONFIG_PURPLE) += asc_serial.o
+ COBJS-$(CONFIG_JZSOC) += jz_serial.o jz_i2c.o jz_mmc.o
+ COBJS-$(CONFIG_JZ4740) += jz4740.o jz4740_nand.o
+ COBJS-$(CONFIG_NANONOTE) += nanonote_gpm940b0.o
+-
++COBJS-$(CONFIG_SAKC) += nanonote_gpm940b0.o
+
+ SRCS := $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+ OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
diff --git a/package/ubus/Makefile b/package/ubus/Makefile
new file mode 100644
index 000000000..274b9a2fc
--- /dev/null
+++ b/package/ubus/Makefile
@@ -0,0 +1,80 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ubus
+PKG_VERSION:=2012-06-01
+PKG_RELEASE=$(PKG_SOURCE_VERSION)
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=git://nbd.name/luci2/ubus.git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=a62e2f8c15a65efb1a82404d8f31e3bfc1cbe7d9
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
+PKG_MIRROR_MD5SUM:=cbca78919d44bcf0f8d1e09743131e6d
+CMAKE_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/ubus
+ SECTION:=luci2
+ CATEGORY:=LuCI2
+ SUBMENU:=System
+ DEPENDS:=+libubus +libblobmsg-json +ubusd
+ TITLE:=OpenWrt RPC client utility
+endef
+
+define Package/ubusd
+ SECTION:=luci2
+ CATEGORY:=LuCI2
+ SUBMENU:=System
+ TITLE:=OpenWrt RPC daemon
+ DEPENDS:=+libubox
+endef
+
+define Package/libubus
+ SECTION:=luci2
+ CATEGORY:=LuCI2
+ SUBMENU:=Libraries
+ DEPENDS:=+libubox
+ TITLE:=OpenWrt RPC client library
+endef
+
+define Package/libubus-lua
+ SECTION:=luci2
+ CATEGORY:=LuCI2
+ SUBMENU:=Libraries
+ DEPENDS:=+libubus +liblua
+ TITLE:=Lua binding for the OpenWrt RPC client
+endef
+
+TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include
+
+CMAKE_OPTIONS = \
+ -DLUAPATH=/usr/lib/lua
+
+define Package/ubus/install
+ $(INSTALL_DIR) $(1)/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/ubus $(1)/bin/
+endef
+
+define Package/ubusd/install
+ $(INSTALL_DIR) $(1)/sbin $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/ubus.init $(1)/etc/init.d/ubus
+ $(CP) $(PKG_INSTALL_DIR)/usr/sbin/ubusd $(1)/sbin/
+endef
+
+define Package/libubus/install
+ $(INSTALL_DIR) $(1)/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/* $(1)/lib/
+endef
+
+define Package/libubus-lua/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua
+ $(CP) $(PKG_BUILD_DIR)/lua/ubus.so $(1)/usr/lib/lua/
+endef
+
+$(eval $(call BuildPackage,ubus))
+$(eval $(call BuildPackage,ubusd))
+$(eval $(call BuildPackage,libubus))
+$(eval $(call BuildPackage,libubus-lua))
+
diff --git a/package/ubus/files/ubus.init b/package/ubus/files/ubus.init
new file mode 100755
index 000000000..70fe21c6a
--- /dev/null
+++ b/package/ubus/files/ubus.init
@@ -0,0 +1,14 @@
+#!/bin/sh /etc/rc.common
+
+START=11
+
+SERVICE_DAEMONIZE=1
+SERVICE_WRITE_PID=1
+
+start() {
+ service_start /sbin/ubusd
+}
+
+stop() {
+ service_stop /sbin/ubusd
+}
diff --git a/package/uci/Makefile b/package/uci/Makefile
new file mode 100644
index 000000000..06dbe8872
--- /dev/null
+++ b/package/uci/Makefile
@@ -0,0 +1,88 @@
+#
+# Copyright (C) 2008-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+UCI_VERSION=2012-03-28
+UCI_RELEASE=1
+
+PKG_NAME:=uci
+PKG_VERSION:=$(UCI_VERSION)$(if $(UCI_RELEASE),.$(UCI_RELEASE))
+PKG_RELEASE:=1
+PKG_REV:=af2665866061c63ba63335b43aa6ff5102d4e492
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=git://nbd.name/uci.git
+PKG_SOURCE_SUBDIR:=uci-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=$(PKG_REV)
+PKG_SOURCE_PROTO:=git
+PKG_MIRROR_MD5SUM:=0ee76d8f79cf99f5539fd090a4e65646
+
+PKG_BUILD_PARALLEL:=0
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+# set to 1 to enable debugging
+DEBUG=
+
+define Package/libuci
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=C library for the Unified Configuration Interface (UCI)
+endef
+
+define Package/uci
+ SECTION:=base
+ CATEGORY:=Base system
+ DEPENDS:=+libuci
+ TITLE:=Utility for the Unified Configuration Interface (UCI)
+endef
+
+define Package/libuci-lua
+ SECTION=libs
+ CATEGORY=Libraries
+ DEPENDS:=+libuci +liblua
+ TITLE:=Lua plugin for UCI
+endef
+
+TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include
+TARGET_LDFLAGS += -L$(STAGING_DIR)/usr/lib
+
+CMAKE_OPTIONS = \
+ -DLUAPATH=/usr/lib/lua \
+ $(if $(DEBUG),-DUCI_DEBUG=ON)
+
+define Package/libuci/install
+ $(INSTALL_DIR) $(1)/lib
+ $(CP) $(PKG_BUILD_DIR)/libuci.so* $(1)/lib/
+endef
+
+define Package/libuci-lua/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua
+ $(CP) $(PKG_BUILD_DIR)/lua/uci.so $(1)/usr/lib/lua/
+endef
+
+define Package/uci/install
+ $(INSTALL_DIR) $(1)/etc/uci-defaults
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/uci $(1)/sbin/
+ $(CP) ./files/* $(1)/
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_BUILD_DIR)/uci{,_config,map}.h $(1)/usr/include
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/libuci.so* $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/libuci.a $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/libucimap.a $(1)/usr/lib
+endef
+
+$(eval $(call BuildPackage,uci))
+$(eval $(call BuildPackage,libuci))
+$(eval $(call BuildPackage,libuci-lua))
diff --git a/package/uci/files/lib/config/uci.sh b/package/uci/files/lib/config/uci.sh
new file mode 100644
index 000000000..db84c8343
--- /dev/null
+++ b/package/uci/files/lib/config/uci.sh
@@ -0,0 +1,137 @@
+#!/bin/sh
+# Shell script compatibility wrappers for /sbin/uci
+#
+# Copyright (C) 2008-2010 OpenWrt.org
+# Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# 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
+
+CONFIG_APPEND=
+uci_load() {
+ local PACKAGE="$1"
+ local DATA
+ local RET
+ local VAR
+
+ _C=0
+ if [ -z "$CONFIG_APPEND" ]; then
+ for VAR in $CONFIG_LIST_STATE; do
+ export ${NO_EXPORT:+-n} CONFIG_${VAR}=
+ export ${NO_EXPORT:+-n} CONFIG_${VAR}_LENGTH=
+ done
+ export ${NO_EXPORT:+-n} CONFIG_LIST_STATE=
+ export ${NO_EXPORT:+-n} CONFIG_SECTIONS=
+ export ${NO_EXPORT:+-n} CONFIG_NUM_SECTIONS=0
+ export ${NO_EXPORT:+-n} CONFIG_SECTION=
+ fi
+
+ DATA="$(/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} ${LOAD_STATE:+-P /var/state} -S -n export "$PACKAGE" 2>/dev/null)"
+ RET="$?"
+ [ "$RET" != 0 -o -z "$DATA" ] || eval "$DATA"
+ unset DATA
+
+ ${CONFIG_SECTION:+config_cb}
+ return "$RET"
+}
+
+uci_set_default() {
+ local PACKAGE="$1"
+ /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q show "$PACKAGE" > /dev/null && return 0
+ /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} import "$PACKAGE"
+ /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} commit "$PACKAGE"
+}
+
+uci_revert_state() {
+ local PACKAGE="$1"
+ local CONFIG="$2"
+ local OPTION="$3"
+
+ /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -P /var/state revert "$PACKAGE${CONFIG:+.$CONFIG}${OPTION:+.$OPTION}"
+}
+
+uci_set_state() {
+ local PACKAGE="$1"
+ local CONFIG="$2"
+ local OPTION="$3"
+ local VALUE="$4"
+
+ [ "$#" = 4 ] || return 0
+ /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -P /var/state set "$PACKAGE.$CONFIG${OPTION:+.$OPTION}=$VALUE"
+}
+
+uci_toggle_state() {
+ uci_revert_state "$1" "$2" "$3"
+ uci_set_state "$1" "$2" "$3" "$4"
+}
+
+uci_set() {
+ local PACKAGE="$1"
+ local CONFIG="$2"
+ local OPTION="$3"
+ local VALUE="$4"
+
+ /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set "$PACKAGE.$CONFIG.$OPTION=$VALUE"
+}
+
+uci_get_state() {
+ uci_get "$1" "$2" "$3" "$4" "/var/state"
+}
+
+uci_get() {
+ local PACKAGE="$1"
+ local CONFIG="$2"
+ local OPTION="$3"
+ local DEFAULT="$4"
+ local STATE="$5"
+
+ /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} ${STATE:+-P $STATE} -q get "$PACKAGE${CONFIG:+.$CONFIG}${OPTION:+.$OPTION}"
+ RET="$?"
+ [ "$RET" -ne 0 ] && [ -n "$DEFAULT" ] && echo "$DEFAULT"
+ return "$RET"
+}
+
+uci_add() {
+ local PACKAGE="$1"
+ local TYPE="$2"
+ local CONFIG="$3"
+
+ if [ -z "$CONFIG" ]; then
+ export ${NO_EXPORT:+-n} CONFIG_SECTION="$(/sbin/uci add "$PACKAGE" "$TYPE")"
+ else
+ /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set "$PACKAGE.$CONFIG=$TYPE"
+ export ${NO_EXPORT:+-n} CONFIG_SECTION="$CONFIG"
+ fi
+}
+
+uci_rename() {
+ local PACKAGE="$1"
+ local CONFIG="$2"
+ local VALUE="$3"
+
+ /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} rename "$PACKAGE.$CONFIG=$VALUE"
+}
+
+uci_remove() {
+ local PACKAGE="$1"
+ local CONFIG="$2"
+ local OPTION="$3"
+
+ /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} del "$PACKAGE.$CONFIG${OPTION:+.$OPTION}"
+}
+
+uci_commit() {
+ local PACKAGE="$1"
+ /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} commit $PACKAGE
+}
diff --git a/package/uclibc++/Makefile b/package/uclibc++/Makefile
new file mode 100644
index 000000000..15c2bce54
--- /dev/null
+++ b/package/uclibc++/Makefile
@@ -0,0 +1,91 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=uclibc++
+PKG_VERSION:=0.2.4
+PKG_RELEASE:=1
+
+PKG_SOURCE:=uClibc++-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://cxx.uclibc.org/src/
+PKG_MD5SUM:=394c119363dd8b469fb898442a6764b8
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/uClibc++-$(PKG_VERSION)
+PKG_BUILD_PARALLEL:=1
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/uclibcxx
+ NAME:=uclibc++
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=C++ library for embedded systems
+ URL:=http://cxx.uclibc.org/src/
+endef
+
+UCLIBC_TARGET_ARCH:=$(shell echo $(ARCH) | sed -e s'/-.*//' \
+ -e 's/i.86/i386/' \
+ -e 's/sparc.*/sparc/' \
+ -e 's/m68k.*/m68k/' \
+ -e 's/ppc/powerpc/g' \
+ -e 's/v850.*/v850/g' \
+ -e 's/sh64/sh/' \
+ -e 's/sh[234].*/sh/' \
+ -e 's/mips.*/mips/' \
+ -e 's/mipsel.*/mips/' \
+ -e 's/cris.*/cris/' \
+)
+
+TARGET_CFLAGS += $(FPIC)
+
+ifneq ($(CONFIG_CCACHE),)
+TARGET_CXX=$(TARGET_CXX_NOCACHE)
+endif
+
+MAKE_FLAGS:= \
+ TOPDIR="$(PKG_BUILD_DIR)/" \
+ $(TARGET_CONFIGURE_OPTS) \
+ CPU_CFLAGS="$(TARGET_CFLAGS)" \
+ CROSS="$(TARGET_CROSS)" \
+ CP="$(CP)" \
+ GEN_LIBS="-lc $(LIBGCC_S)" \
+ check_as_needed=
+
+# check_as_needed overrides dependency on libgcc_s
+
+define Build/Configure
+ if [ -f ./files/config.$(UCLIBC_TARGET_ARCH) ]; then \
+ cp ./files/config.$(UCLIBC_TARGET_ARCH) $(PKG_BUILD_DIR)/.config; \
+ else \
+ cp ./files/config.default $(PKG_BUILD_DIR)/.config; \
+ fi
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(2)/bin $(1)/usr/include/uClibc++ $(1)/usr/lib
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/bin/g++-uc $(TOOLCHAIN_DIR)/bin/
+ $(CP) $(PKG_INSTALL_DIR)/include/* $(1)/usr/include/uClibc++/
+ $(CP) $(PKG_INSTALL_DIR)/lib/libuClibc++*.{a,so}* $(1)/usr/lib/
+ $(SED) 's|-I/include/|-I$(STAGING_DIR)/usr/include/uClibc++/|g' $(TOOLCHAIN_DIR)/bin/g++-uc
+ $(SED) 's|-L/lib/|-L$(STAGING_DIR)/usr/lib/|g' $(TOOLCHAIN_DIR)/bin/g++-uc
+# add another wrapper which links against both uClibc++ and libstdc++
+ $(INSTALL_BIN) $(TOOLCHAIN_DIR)/bin/g++-uc $(TOOLCHAIN_DIR)/bin/g++-uc+std
+ $(SED) 's|^WRAPPER_INCLUDEDIR=.*||g' $(TOOLCHAIN_DIR)/bin/g++-uc+std
+ $(SED) 's|-luClibc++|-Wl,-Bdynamic,-luClibc++,-Bstatic,-lstdc++,-Bdynamic|g' $(TOOLCHAIN_DIR)/bin/g++-uc+std
+ $(SED) 's|-nostdinc++||g' $(TOOLCHAIN_DIR)/bin/g++-uc+std
+endef
+
+define Package/uclibcxx/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/lib/libuClibc++.so.* $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/lib/libuClibc++-*.so $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,uclibcxx))
diff --git a/package/uclibc++/files/config.default b/package/uclibc++/files/config.default
new file mode 100644
index 000000000..944e1a6cf
--- /dev/null
+++ b/package/uclibc++/files/config.default
@@ -0,0 +1,58 @@
+#
+# Automatically generated make config: don't edit
+#
+
+#
+# Target Features and Options
+#
+UCLIBCXX_HAS_FLOATS=y
+# UCLIBCXX_HAS_LONG_DOUBLE is not set
+# UCLIBCXX_HAS_TLS is not set
+WARNINGS="-Wall"
+BUILD_EXTRA_LIBRARIES=""
+HAVE_DOT_CONFIG=y
+
+#
+# String and I/O Stream Support
+#
+UCLIBCXX_HAS_WCHAR=y
+UCLIBCXX_IOSTREAM_BUFSIZE=32
+UCLIBCXX_HAS_LFS=y
+UCLIBCXX_SUPPORT_CDIR=y
+UCLIBCXX_SUPPORT_CIN=y
+UCLIBCXX_SUPPORT_COUT=y
+UCLIBCXX_SUPPORT_CERR=y
+UCLIBCXX_SUPPORT_CLOG=y
+UCLIBCXX_SUPPORT_WCIN=y
+UCLIBCXX_SUPPORT_WCOUT=y
+UCLIBCXX_SUPPORT_WCERR=y
+UCLIBCXX_SUPPORT_WCLOG=y
+
+#
+# STL and Code Expansion
+#
+UCLIBCXX_STL_BUFFER_SIZE=32
+UCLIBCXX_CODE_EXPANSION=y
+UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS=y
+UCLIBCXX_EXPAND_STRING_CHAR=y
+UCLIBCXX_EXPAND_VECTOR_BASIC=y
+UCLIBCXX_EXPAND_IOS_CHAR=y
+UCLIBCXX_EXPAND_STREAMBUF_CHAR=y
+UCLIBCXX_EXPAND_ISTREAM_CHAR=y
+UCLIBCXX_EXPAND_OSTREAM_CHAR=y
+UCLIBCXX_EXPAND_FSTREAM_CHAR=y
+UCLIBCXX_EXPAND_SSTREAM_CHAR=y
+
+#
+# Library Installation Options
+#
+UCLIBCXX_RUNTIME_PREFIX=""
+UCLIBCXX_RUNTIME_INCLUDE_SUBDIR="/include"
+UCLIBCXX_RUNTIME_LIB_SUBDIR="/lib"
+UCLIBCXX_RUNTIME_BIN_SUBDIR="/bin"
+UCLIBCXX_EXCEPTION_SUPPORT=y
+IMPORT_LIBSUP=y
+# IMPORT_LIBGCC_EH is not set
+BUILD_STATIC_LIB=y
+# BUILD_ONLY_STATIC_LIB is not set
+# DODEBUG is not set
diff --git a/package/uclibc++/patches/002-path_to_bash.patch b/package/uclibc++/patches/002-path_to_bash.patch
new file mode 100644
index 000000000..26d88ee4d
--- /dev/null
+++ b/package/uclibc++/patches/002-path_to_bash.patch
@@ -0,0 +1,11 @@
+--- a/bin/Makefile
++++ b/bin/Makefile
+@@ -13,7 +13,7 @@ install:
+ $(INSTALL) -m 755 $(WRAPPER) $(PREFIX)$(UCLIBCXX_RUNTIME_BINDIR)
+
+ $(WRAPPER): Makefile
+- echo '#!/bin/sh' > $@
++ echo '#!/usr/bin/env bash' > $@
+ echo '' >> $@
+ echo 'WRAPPER_INCLUDEDIR="$${WRAPPER_INCLUDEDIR:=-I$(UCLIBCXX_RUNTIME_INCLUDEDIR)}"' >> $@
+ echo 'WRAPPER_LIBDIR="$${WRAPPER_LIBDIR:=-L$(UCLIBCXX_RUNTIME_LIBDIR)}"' >> $@
diff --git a/package/uclibc++/patches/006-eabi_fix.patch b/package/uclibc++/patches/006-eabi_fix.patch
new file mode 100644
index 000000000..65b436cde
--- /dev/null
+++ b/package/uclibc++/patches/006-eabi_fix.patch
@@ -0,0 +1,38 @@
+--- a/include/typeinfo
++++ b/include/typeinfo
+@@ -44,6 +44,7 @@ namespace __cxxabiv1
+ class __class_type_info;
+ } // namespace __cxxabiv1
+
++#ifndef __GXX_MERGED_TYPEINFO_NAMES
+ #if !__GXX_WEAK__
+ // If weak symbols are not supported, typeinfo names are not merged.
+ #define __GXX_MERGED_TYPEINFO_NAMES 0
+@@ -51,6 +52,7 @@ namespace __cxxabiv1
+ // On platforms that support weak symbols, typeinfo names are merged.
+ #define __GXX_MERGED_TYPEINFO_NAMES 1
+ #endif
++#endif
+
+ namespace std
+ {
+--- a/include/unwind-cxx.h
++++ b/include/unwind-cxx.h
+@@ -173,6 +173,7 @@ extern std::unexpected_handler __unexpec
+
+ // This is the exception class we report -- "GNUCC++\0".
+ const _Unwind_Exception_Class __gxx_exception_class
++#ifndef __ARM_EABI_UNWINDER__
+ = ((((((((_Unwind_Exception_Class) 'G'
+ << 8 | (_Unwind_Exception_Class) 'N')
+ << 8 | (_Unwind_Exception_Class) 'U')
+@@ -181,6 +182,9 @@ const _Unwind_Exception_Class __gxx_exce
+ << 8 | (_Unwind_Exception_Class) '+')
+ << 8 | (_Unwind_Exception_Class) '+')
+ << 8 | (_Unwind_Exception_Class) '\0');
++#else
++= "GNUC++";
++#endif
+
+ // GNU C++ personality routine, Version 0.
+ extern "C" _Unwind_Reason_Code __gxx_personality_v0
diff --git a/package/udev/Config.in b/package/udev/Config.in
new file mode 100644
index 000000000..56033d8ee
--- /dev/null
+++ b/package/udev/Config.in
@@ -0,0 +1,118 @@
+# udev package config
+
+menu "Configuration"
+ depends on PACKAGE_udev
+
+config UDEV_DISABLE_LOGGING
+ bool "Disable udev logging to syslog"
+ default n
+ help
+ Disable logging of udev messages to the syslog. If
+ unsure, choose the default N.
+
+config UDEV_ENABLE_DEBUG
+ bool "Enable debug build of the udev package"
+ default n
+ help
+ Compile in udev debug messages. If unsure, choose
+ the default N.
+
+config UDEV_EXTRA_accelerometer
+ bool "Install udev acceleroometer callout"
+ default y
+ help
+ accelerometer - udev callout to export device orientation
+ through property
+
+config UDEV_EXTRA_ata_id
+ bool "Install udev ata_id callout"
+ default y
+ help
+ ata_id - udev callout to read product/serial number
+ from ATA drives
+
+config UDEV_EXTRA_cdrom_id
+ bool "Install udev cdrom_id callout"
+ default y
+ help
+ cdrom_id - udev callout to determine the capabilities
+ of optical drives and media
+
+config UDEV_EXTRA_collect
+ bool "Install udev collect"
+ default n
+ help
+ Adds ID to the list governed by <checkpoint>
+
+config UDEV_EXTRA_edd_id
+ bool "Install udev edd_id callout"
+ default n
+ help
+ edd_id - udev callout to identify BIOS disk drives
+ via EDD
+
+config UDEV_EXTRA_firmware
+ bool "Install firmware support"
+ default n
+ help
+ udev firmware loader
+ via EDD
+
+config UDEV_EXTRA_floppy
+ bool "Install create_floppy_devices callout"
+ default n
+ help
+ create_floppy_devices - udev callout to create all
+ possible floppy device based on the CMOS type
+
+config UDEV_EXTRA_input_id
+ bool "Install input_id callout"
+ default y
+ help
+ input_id - udev callout to classify input devices
+
+config UDEV_EXTRA_mtd_probe
+ bool "Install mtd_probe callout"
+ default y
+ help
+ mtd_probe - udev callout to probe mtd devices
+
+config UDEV_EXTRA_path_id
+ bool "Install udev path_id callout"
+ default y
+ help
+ path_id - udev callout to create a device path based
+ unique name for a device to implement the Linux
+ Persistent Device Naming scheme
+
+config UDEV_EXTRA_qemu
+ bool "Install qemu specific rules"
+ default y
+ help
+ Install rules for autosuspension of QEMU emulated
+ USB HID devices
+
+config UDEV_EXTRA_rule_generator
+ bool "Install udev rule_generator"
+ default y
+ help
+
+config UDEV_EXTRA_scsi_id
+ bool "Install udev scsi_id callout"
+ default y
+ help
+ scsi_id - retrieve and generate a unique SCSI identifier
+
+config UDEV_EXTRA_usb_id
+ bool "Install udev usb_id callout"
+ default y
+ help
+ usb_id - can find the unique id of USB devices
+
+config UDEV_EXTRA_v4l_id
+ bool "Install udev v4l_id callout"
+ default y
+ help
+ v4l_id - udev callout to identify Video4Linux devices
+
+endmenu
diff --git a/package/udev/Makefile b/package/udev/Makefile
new file mode 100644
index 000000000..7673be76f
--- /dev/null
+++ b/package/udev/Makefile
@@ -0,0 +1,156 @@
+#
+# Copyright (C) 2006-2008 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=udev
+PKG_VERSION:=173
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=@KERNEL/linux/utils/kernel/hotplug/
+PKG_MD5SUM:=91a88a359b60bbd074b024883cc0dbde
+
+include $(INCLUDE_DIR)/package.mk
+
+PKG_INSTALL=1
+
+define Package/udev
+ SECTION:=base
+ CATEGORY:=Base system
+ TITLE:=Dynamic device management subsystem
+ URL:=http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html
+ MAINTAINER:=Geoff Levand <geoffrey.levand@am.sony.com>
+ MENU:=1
+ DEPENDS:=+librt
+endef
+
+define Package/udev/description
+ udev allows Linux users to have a dynamic /dev directory and it
+ provides the ability to have persistent device names.
+endef
+
+define Package/udev/conffiles
+/etc/udev/udev.conf
+endef
+
+define Package/udev/config
+ source "$(SOURCE)/Config.in"
+endef
+
+udev-args-$(CONFIG_UDEV_DISABLE_LOGGING) += --disable-logging
+udev-args-$(CONFIG_UDEV_ENABLE_DEBUG) += --enable-debug
+udev-args-$(CONFIG_UDEV_EXTRA_edd_id) += --enable-edd
+udev-args-$(CONFIG_UDEV_EXTRA_floppy) += --enable-floppy
+
+# TODO: make hwdb and introspection work
+
+CONFIGURE_ARGS += --prefix=/usr --exec-prefix= --sysconfdir=/etc \
+ --disable-hwdb --disable-keymap --disable-gudev --disable-introspection \
+ --libexecdir=/lib/udev --disable-gtk-doc-html \
+ --sbindir=/sbin $(udev-args-y)
+
+udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_accelerometer) += accelerometer
+udev-extra-rules-$(CONFIG_UDEV_EXTRA_accelerometer) += 61-accelerometer.rules
+
+udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_ata_id) += ata_id
+
+udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_cdrom_id) += cdrom_id
+udev-extra-rules-$(CONFIG_UDEV_EXTRA_cdrom_id) += 60-cdrom_id.rules
+
+udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_collect) += collect
+
+udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_edd_id) += edd_id
+udev-extra-rules-$(CONFIG_UDEV_EXTRA_edd_id) += 61-persistent-storage-edd.rules
+
+udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_firmware) += firmware
+udev-extra-rules-$(CONFIG_UDEV_EXTRA_firmware) += 50-firmware.rules
+
+udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_floppy) += create_floppy_devices
+
+# TODO: make gudev work
+
+udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_input_id) += input_id
+
+# TODO: make keymap work
+
+udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_mtd_probe) += mtd_probe
+udev-extra-rules-$(CONFIG_UDEV_EXTRA_mtd_probe) += 75-probe_mtd.rules
+
+udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_path_id) += path_id
+
+udev-extra-rules-$(CONFIG_UDEV_EXTRA_qemu) += 42-qemu-usb.rules
+
+udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_rule_generator) += \
+ write_cd_rules write_net_rules
+udev-extra-lib-data-$(CONFIG_UDEV_EXTRA_rule_generator) += \
+ rule_generator.functions
+udev-extra-rules-$(CONFIG_UDEV_EXTRA_rule_generator) += \
+ 75-cd-aliases-generator.rules 75-persistent-net-generator.rules
+
+udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_scsi_id) += scsi_id
+
+# TODO: make udev-acl work
+
+udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_usb_id) += usb_id
+
+udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_v4l_id) += v4l_id
+udev-extra-rules-$(CONFIG_UDEV_EXTRA_v4l_id) += 60-persistent-v4l.rules
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/libudev.h $(1)/usr/include
+ $(INSTALL_DIR) $(1)/usr/share/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/pkgconfig/udev.pc $(1)/usr/share/pkgconfig
+ $(INSTALL_DIR) $(1)/lib
+ $(CP) $(PKG_INSTALL_DIR)/lib/libudev.so* $(1)/lib
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/lib/pkgconfig/libudev.pc $(1)/usr/lib/pkgconfig
+endef
+
+define Package/udev/install
+ $(INSTALL_DIR) $(1)/etc/udev/rules.d
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/udev/udev.conf $(1)/etc/udev
+
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) \
+ $(PKG_INSTALL_DIR)/sbin/udevadm \
+ $(PKG_INSTALL_DIR)/sbin/udevd \
+ $(1)/sbin
+
+ $(INSTALL_DIR) $(1)/lib/udev/rules.d
+ $(INSTALL_DATA) \
+ $(addprefix $(PKG_INSTALL_DIR)/lib/udev/rules.d/, \
+ $(udev-extra-rules-y)) \
+ $(addprefix $(PKG_INSTALL_DIR)/lib/udev/rules.d/, \
+ 50-udev-default.rules \
+ 60-persistent-input.rules \
+ 60-persistent-serial.rules \
+ 60-persistent-storage.rules \
+ 80-drivers.rules \
+ 95-udev-late.rules) \
+ $(1)/lib/udev/rules.d
+
+ $(INSTALL_DIR) $(1)/lib
+ $(CP) $(PKG_INSTALL_DIR)/lib/libudev.so* $(1)/lib
+
+ $(INSTALL_DIR) $(1)/lib/udev
+ifneq ($(udev-extra-lib-bin-y),)
+ $(INSTALL_BIN) \
+ $(addprefix $(PKG_INSTALL_DIR)/lib/udev/, \
+ $(udev-extra-lib-bin-y)) \
+ $(1)/lib/udev/
+endif
+ifneq ($(udev-extra-lib-data-y),)
+ $(INSTALL_DATA) \
+ $(addprefix $(PKG_INSTALL_DIR)/lib/udev/, \
+ $(udev-extra-lib-data-y)) \
+ $(1)/lib/udev/
+endif
+endef
+
+$(eval $(call BuildPackage,udev))
diff --git a/package/udev/patches/0001-build-don-t-use-gc-sections.patch b/package/udev/patches/0001-build-don-t-use-gc-sections.patch
new file mode 100644
index 000000000..f01a5ae1a
--- /dev/null
+++ b/package/udev/patches/0001-build-don-t-use-gc-sections.patch
@@ -0,0 +1,31 @@
+From 971a09345f108189ed899b236784a5440e43c8b6 Mon Sep 17 00:00:00 2001
+From: Daniel Mierswa <impulze@impulze.org>
+Date: Sun, 31 Jul 2011 23:51:49 +0000
+Subject: [PATCH 1/2] build: don't use --gc-sections
+
+somehow won't work with the wrt toolchain
+---
+ Makefile.am | 5 +----
+ 1 files changed, 1 insertions(+), 4 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index a0c007a..3d8ce92 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -18,12 +18,9 @@ AM_CPPFLAGS = \
+ -DLIBEXECDIR=\""$(libexecdir)"\"
+
+ AM_CFLAGS = \
+- -fvisibility=hidden \
+- -ffunction-sections \
+- -fdata-sections
++ -fvisibility=hidden
+
+ AM_LDFLAGS = \
+- -Wl,--gc-sections \
+ -Wl,--as-needed
+
+ DISTCHECK_CONFIGURE_FLAGS = \
+--
+1.7.6
+
diff --git a/package/udev/patches/0002-udevd-add-lrt-for-message-queue-symbols.patch b/package/udev/patches/0002-udevd-add-lrt-for-message-queue-symbols.patch
new file mode 100644
index 000000000..55466bc25
--- /dev/null
+++ b/package/udev/patches/0002-udevd-add-lrt-for-message-queue-symbols.patch
@@ -0,0 +1,25 @@
+From ae90737100d901723af9890e69798bd1dac9a86d Mon Sep 17 00:00:00 2001
+From: Daniel Mierswa <impulze@impulze.org>
+Date: Sun, 31 Jul 2011 23:53:21 +0000
+Subject: [PATCH 2/2] udevd: add -lrt for message queue symbols
+
+---
+ Makefile.am | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index 3d8ce92..7d8a4b6 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -164,7 +164,7 @@ udev_udevd_SOURCES = \
+ udev/udevd.c \
+ udev/sd-daemon.h \
+ udev/sd-daemon.c
+-udev_udevd_LDADD = libudev/libudev-private.la
++udev_udevd_LDADD = libudev/libudev-private.la -lrt
+
+ udev_udevadm_SOURCES = \
+ $(udev_common_sources) \
+--
+1.7.6
+
diff --git a/package/udev/patches/0003-add_btn_trigger_happy_define.patch b/package/udev/patches/0003-add_btn_trigger_happy_define.patch
new file mode 100644
index 000000000..77eaf13aa
--- /dev/null
+++ b/package/udev/patches/0003-add_btn_trigger_happy_define.patch
@@ -0,0 +1,13 @@
+--- a/extras/input_id/input_id.c
++++ b/extras/input_id/input_id.c
+@@ -30,6 +30,10 @@
+ #include "libudev.h"
+ #include "libudev-private.h"
+
++#ifndef BTN_TRIGGER_HAPPY
++#define BTN_TRIGGER_HAPPY 0x2c0
++#endif
++
+ /* we must use this kernel-compatible implementation */
+ #define BITS_PER_LONG (sizeof(unsigned long) * 8)
+ #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
diff --git a/package/uhttpd/Makefile b/package/uhttpd/Makefile
new file mode 100644
index 000000000..245426b4e
--- /dev/null
+++ b/package/uhttpd/Makefile
@@ -0,0 +1,164 @@
+#
+# Copyright (C) 2010-2012 Jo-Philipp Wich <xm@subsignal.org>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=uhttpd
+PKG_RELEASE:=40
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+PKG_CONFIG_DEPENDS := \
+ CONFIG_PACKAGE_uhttpd_debug \
+ CONFIG_PACKAGE_uhttpd-mod-lua \
+ CONFIG_PACKAGE_uhttpd-mod-tls \
+ CONFIG_PACKAGE_uhttpd-mod-tls_cyassl \
+ CONFIG_PACKAGE_uhttpd-mod-tls_openssl \
+ CONFIG_PACKAGE_uhttpd-mod-ubus
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/uhttpd/default
+ SECTION:=net
+ CATEGORY:=Network
+ SUBMENU:=Web Servers/Proxies
+ TITLE:=uHTTPd - tiny, single threaded HTTP server
+ MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org>
+endef
+
+define Package/uhttpd
+ $(Package/uhttpd/default)
+ DEPENDS:=+libubox
+endef
+
+define Package/uhttpd/description
+ uHTTPd is a tiny single threaded HTTP server with TLS, CGI and Lua
+ support. It is intended as a drop-in replacement for the Busybox
+ HTTP daemon.
+endef
+
+define Package/uhttpd/config
+ config PACKAGE_uhttpd_debug
+ bool "Build with debug messages"
+ default n
+endef
+
+
+define Package/uhttpd-mod-tls
+ $(Package/uhttpd/default)
+ TITLE+= (TLS plugin)
+ DEPENDS:=uhttpd +PACKAGE_uhttpd-mod-tls_cyassl:libcyassl +PACKAGE_uhttpd-mod-tls_openssl:libopenssl
+endef
+
+define Package/uhttpd-mod-tls/description
+ The TLS plugin adds HTTPS support to uHTTPd.
+endef
+
+define Package/uhttpd-mod-tls/config
+ choice
+ depends on PACKAGE_uhttpd-mod-tls
+ prompt "TLS Provider"
+ default PACKAGE_uhttpd-mod-tls_cyassl
+
+ config PACKAGE_uhttpd-mod-tls_cyassl
+ bool "CyaSSL"
+
+ config PACKAGE_uhttpd-mod-tls_openssl
+ bool "OpenSSL"
+ endchoice
+endef
+
+UHTTPD_TLS:=
+TLS_CFLAGS:=
+TLS_LDFLAGS:=
+
+ifneq ($(CONFIG_PACKAGE_uhttpd-mod-tls_cyassl),)
+ UHTTPD_TLS:=cyassl
+ TLS_CFLAGS:=-I$(STAGING_DIR)/usr/include/cyassl -DTLS_IS_CYASSL
+ TLS_LDFLAGS:=-lcyassl -lm
+endif
+
+ifneq ($(CONFIG_PACKAGE_uhttpd-mod-tls_openssl),)
+ UHTTPD_TLS:=openssl
+ TLS_CFLAGS:=-DTLS_IS_OPENSSL
+ TLS_LDFLAGS:=-lssl
+endif
+
+
+define Package/uhttpd-mod-lua
+ $(Package/uhttpd/default)
+ TITLE+= (Lua plugin)
+ DEPENDS:=uhttpd +liblua
+endef
+
+define Package/uhttpd-mod-lua/description
+ The Lua plugin adds a CGI-like Lua runtime interface to uHTTPd.
+endef
+
+
+define Package/uhttpd-mod-ubus
+ $(Package/uhttpd/default)
+ TITLE+= (ubus plugin)
+ DEPENDS:=uhttpd +libubus +libblobmsg-json
+endef
+
+define Package/uhttpd-mod-ubus/description
+ The ubus plugin adds a HTTP/JSON RPC proxy for ubus and publishes the
+ session.* namespace and procedures.
+endef
+
+
+TARGET_CFLAGS += $(TLS_CFLAGS) $(if $(CONFIG_PACKAGE_uhttpd_debug),-DDEBUG) -ggdb3
+TARGET_LDFLAGS += -lubox -Wl,-rpath-link=$(STAGING_DIR)/usr/lib
+MAKE_VARS += \
+ FPIC="$(FPIC)" \
+ LUA_SUPPORT="$(if $(CONFIG_PACKAGE_uhttpd-mod-lua),1)" \
+ TLS_SUPPORT="$(if $(CONFIG_PACKAGE_uhttpd-mod-tls),1)" \
+ UBUS_SUPPORT="$(if $(CONFIG_PACKAGE_uhttpd-mod-ubus),1)" \
+ UHTTPD_TLS="$(UHTTPD_TLS)" \
+ TLS_CFLAGS="$(TLS_CFLAGS)" \
+ TLS_LDFLAGS="$(TLS_LDFLAGS)"
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Package/uhttpd/conffiles
+/etc/config/uhttpd
+/etc/uhttpd.crt
+/etc/uhttpd.key
+endef
+
+define Package/uhttpd/install
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/uhttpd.init $(1)/etc/init.d/uhttpd
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_CONF) ./files/uhttpd.config $(1)/etc/config/uhttpd
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/uhttpd $(1)/usr/sbin/uhttpd
+endef
+
+define Package/uhttpd-mod-tls/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/uhttpd_tls.so $(1)/usr/lib/
+endef
+
+define Package/uhttpd-mod-lua/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/uhttpd_lua.so $(1)/usr/lib/
+endef
+
+define Package/uhttpd-mod-ubus/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/uhttpd_ubus.so $(1)/usr/lib/
+endef
+
+
+$(eval $(call BuildPackage,uhttpd))
+$(eval $(call BuildPackage,uhttpd-mod-tls))
+$(eval $(call BuildPackage,uhttpd-mod-lua))
+$(eval $(call BuildPackage,uhttpd-mod-ubus))
diff --git a/package/uhttpd/files/uhttpd.config b/package/uhttpd/files/uhttpd.config
new file mode 100644
index 000000000..b33411e97
--- /dev/null
+++ b/package/uhttpd/files/uhttpd.config
@@ -0,0 +1,89 @@
+# Server configuration
+config uhttpd main
+
+ # HTTP listen addresses, multiple allowed
+ list listen_http 0.0.0.0:80
+# list listen_http [::]:80
+
+ # HTTPS listen addresses, multiple allowed
+ list listen_https 0.0.0.0:443
+# list listen_https [::]:443
+
+ # Server document root
+ option home /www
+
+ # Reject requests from RFC1918 IP addresses
+ # directed to the servers public IP(s).
+ # This is a DNS rebinding countermeasure.
+ option rfc1918_filter 1
+
+ # Maximum number of concurrent requests.
+ # If this number is exceeded, further requests are
+ # queued until the number of running requests drops
+ # below the limit again.
+ option max_requests 3
+
+ # Certificate and private key for HTTPS.
+ # If no listen_https addresses are given,
+ # the key options are ignored.
+ option cert /etc/uhttpd.crt
+ option key /etc/uhttpd.key
+
+ # CGI url prefix, will be searched in docroot.
+ # Default is /cgi-bin
+ option cgi_prefix /cgi-bin
+
+ # List of extension->interpreter mappings.
+ # Files with an associated interpreter can
+ # be called outside of the CGI prefix and do
+ # not need to be executable.
+# list interpreter ".php=/usr/bin/php-cgi"
+# list interpreter ".cgi=/usr/bin/perl"
+
+ # Lua url prefix and handler script.
+ # Lua support is disabled if no prefix given.
+# option lua_prefix /luci
+# option lua_handler /usr/lib/lua/luci/sgi/uhttpd.lua
+
+ # CGI/Lua timeout, if the called script does not
+ # write data within the given amount of seconds,
+ # the server will terminate the request with
+ # 504 Gateway Timeout response.
+ option script_timeout 60
+
+ # Network timeout, if the current connection is
+ # blocked for the specified amount of seconds,
+ # the server will terminate the associated
+ # request process.
+ option network_timeout 30
+
+ # TCP Keep-Alive, send periodic keep-alive probes
+ # over established connections to detect dead peers.
+ # The value is given in seconds to specify the
+ # interval between subsequent probes.
+ # Setting this to 0 will disable TCP keep-alive.
+ option tcp_keepalive 1
+
+ # Basic auth realm, defaults to local hostname
+# option realm OpenWrt
+
+ # Configuration file in busybox httpd format
+# option config /etc/httpd.conf
+
+
+# Certificate defaults for px5g key generator
+config cert px5g
+
+ # Validity time
+ option days 730
+
+ # RSA key size
+ option bits 1024
+
+ # Location
+ option country DE
+ option state Berlin
+ option location Berlin
+
+ # Common name
+ option commonname OpenWrt
diff --git a/package/uhttpd/files/uhttpd.init b/package/uhttpd/files/uhttpd.init
new file mode 100755
index 000000000..379a9f5b5
--- /dev/null
+++ b/package/uhttpd/files/uhttpd.init
@@ -0,0 +1,135 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2010 Jo-Philipp Wich
+
+START=50
+
+SERVICE_DAEMONIZE=1
+SERVICE_WRITE_PID=1
+
+UHTTPD_BIN="/usr/sbin/uhttpd"
+PX5G_BIN="/usr/sbin/px5g"
+
+append_arg() {
+ local cfg="$1"
+ local var="$2"
+ local opt="$3"
+ local def="$4"
+ local val
+
+ config_get val "$cfg" "$var"
+ [ -n "$val" -o -n "$def" ] && append UHTTPD_ARGS "$opt ${val:-$def}"
+}
+
+append_bool() {
+ local cfg="$1"
+ local var="$2"
+ local opt="$3"
+ local def="$4"
+ local val
+
+ config_get_bool val "$cfg" "$var" "$def"
+ [ "$val" = 1 ] && append UHTTPD_ARGS "$opt"
+}
+
+generate_keys() {
+ local cfg="$1"
+ local key="$2"
+ local crt="$3"
+ local days bits country state location commonname
+
+ config_get days "$cfg" days
+ config_get bits "$cfg" bits
+ config_get country "$cfg" country
+ config_get state "$cfg" state
+ config_get location "$cfg" location
+ config_get commonname "$cfg" commonname
+
+ [ -x "$PX5G_BIN" ] && {
+ $PX5G_BIN selfsigned -der \
+ -days ${days:-730} -newkey rsa:${bits:-1024} -keyout "$UHTTPD_KEY" -out "$UHTTPD_CERT" \
+ -subj /C="${country:-DE}"/ST="${state:-Saxony}"/L="${location:-Leipzig}"/CN="${commonname:-OpenWrt}"
+ }
+}
+
+start_instance()
+{
+ UHTTPD_ARGS=""
+ UHTTPD_CERT=""
+ UHTTPD_KEY=""
+
+ local cfg="$1"
+ local realm="$(uci_get system.@system[0].hostname)"
+ local listen http https interpreter path
+
+ append_arg "$cfg" home "-h"
+ append_arg "$cfg" realm "-r" "${realm:-OpenWrt}"
+ append_arg "$cfg" config "-c"
+ append_arg "$cfg" cgi_prefix "-x"
+ append_arg "$cfg" lua_prefix "-l"
+ append_arg "$cfg" lua_handler "-L"
+ append_arg "$cfg" script_timeout "-t"
+ append_arg "$cfg" network_timeout "-T"
+ append_arg "$cfg" tcp_keepalive "-A"
+ append_arg "$cfg" error_page "-E"
+ append_arg "$cfg" index_page "-I"
+ append_arg "$cfg" max_requests "-n" 3
+
+ append_bool "$cfg" no_symlinks "-S" 0
+ append_bool "$cfg" no_dirlists "-D" 0
+ append_bool "$cfg" rfc1918_filter "-R" 0
+
+ config_get http "$cfg" listen_http
+ for listen in $http; do
+ append UHTTPD_ARGS "-p $listen"
+ done
+
+ config_get interpreter "$cfg" interpreter
+ for path in $interpreter; do
+ append UHTTPD_ARGS "-i $path"
+ done
+
+ config_get https "$cfg" listen_https
+ config_get UHTTPD_KEY "$cfg" key /etc/uhttpd.key
+ config_get UHTTPD_CERT "$cfg" cert /etc/uhttpd.crt
+
+ [ -n "$https" ] && {
+ [ -f "$UHTTPD_CERT" -a -f "$UHTTPD_KEY" ] || {
+ config_foreach generate_keys cert
+ }
+
+ [ -f "$UHTTPD_CERT" -a -f "$UHTTPD_KEY" ] && {
+ append_arg "$cfg" cert "-C"
+ append_arg "$cfg" key "-K"
+
+ for listen in $https; do
+ append UHTTPD_ARGS "-s $listen"
+ done
+ }
+ }
+
+ SERVICE_PID_FILE=/var/run/uhttpd_${cfg}.pid
+ service_start $UHTTPD_BIN -f $UHTTPD_ARGS
+
+ # Check if daemon is running, if not then
+ # re-execute in foreground to display error.
+ sleep 1 && service_check $UHTTPD_BIN || \
+ $UHTTPD_BIN -f $UHTTPD_ARGS
+}
+
+stop_instance()
+{
+ local cfg="$1"
+
+ SERVICE_PID_FILE=/var/run/uhttpd_${cfg}.pid
+ service_stop $UHTTPD_BIN
+}
+
+start() {
+ config_load uhttpd
+ config_foreach start_instance uhttpd
+}
+
+stop() {
+ config_load uhttpd
+ config_foreach stop_instance uhttpd
+}
diff --git a/package/uhttpd/src/Makefile b/package/uhttpd/src/Makefile
new file mode 100644
index 000000000..98226ed20
--- /dev/null
+++ b/package/uhttpd/src/Makefile
@@ -0,0 +1,89 @@
+CGI_SUPPORT ?= 1
+LUA_SUPPORT ?= 1
+TLS_SUPPORT ?= 1
+UHTTPD_TLS ?= cyassl
+
+CFLAGS ?= -I./lua-5.1.4/src $(TLS_CFLAGS) -O0 -ggdb3
+LDFLAGS ?= -L./lua-5.1.4/src
+
+CFLAGS += -Wall --std=gnu99
+
+ifeq ($(UHTTPD_TLS),openssl)
+ TLS_LDFLAGS ?= -L./openssl-0.9.8m -lssl
+ TLS_CFLAGS ?= -I./openssl-0.9.8m/include -DTLS_IS_OPENSSL
+else
+ TLS_LDFLAGS ?= -L./cyassl-1.4.0/src/.libs -lcyassl
+ TLS_CFLAGS ?= -I./cyassl-1.4.0/include -DTLS_IS_CYASSL
+endif
+
+OBJ := uhttpd.o uhttpd-file.o uhttpd-utils.o
+LIB := -Wl,--export-dynamic -lcrypt -ldl
+
+TLSLIB :=
+LUALIB :=
+
+HAVE_SHADOW=$(shell echo 'int main(void){ return !getspnam("root"); }' | \
+ $(CC) -include shadow.h -xc -o/dev/null - 2>/dev/null && echo yes)
+
+ifeq ($(HAVE_SHADOW),yes)
+ CFLAGS += -DHAVE_SHADOW
+endif
+
+ifeq ($(TLS_SUPPORT),1)
+ CFLAGS += -DHAVE_TLS
+endif
+
+ifeq ($(CGI_SUPPORT),1)
+ CFLAGS += -DHAVE_CGI
+endif
+
+ifeq ($(LUA_SUPPORT),1)
+ CFLAGS += -DHAVE_LUA
+endif
+
+ifeq ($(UBUS_SUPPORT),1)
+ CFLAGS += -DHAVE_UBUS
+endif
+
+
+world: compile
+
+ifeq ($(CGI_SUPPORT),1)
+ OBJ += uhttpd-cgi.o
+endif
+
+ifeq ($(LUA_SUPPORT),1)
+ LUALIB := uhttpd_lua.so
+
+ $(LUALIB): uhttpd-lua.c
+ $(CC) $(CFLAGS) $(LDFLAGS) $(FPIC) \
+ -shared -lm -llua -ldl \
+ -o $(LUALIB) uhttpd-lua.c
+endif
+
+ifeq ($(TLS_SUPPORT),1)
+ TLSLIB := uhttpd_tls.so
+
+ $(TLSLIB): uhttpd-tls.c
+ $(CC) $(CFLAGS) $(LDFLAGS) $(FPIC) \
+ -shared $(TLS_LDFLAGS) \
+ -o $(TLSLIB) uhttpd-tls.c
+endif
+
+ifeq ($(UBUS_SUPPORT),1)
+ UBUSLIB := uhttpd_ubus.so
+
+ $(UBUSLIB): uhttpd-ubus.c
+ $(CC) $(CFLAGS) $(LDFLAGS) $(FPIC) \
+ -shared -lubus -ljson -lblobmsg_json \
+ -o $(UBUSLIB) uhttpd-ubus.c
+endif
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+compile: $(OBJ) $(TLSLIB) $(LUALIB) $(UBUSLIB)
+ $(CC) -o uhttpd $(LDFLAGS) $(OBJ) $(LIB)
+
+clean:
+ rm -f *.o *.so uhttpd
diff --git a/package/uhttpd/src/uhttpd-cgi.c b/package/uhttpd/src/uhttpd-cgi.c
new file mode 100644
index 000000000..69af90db4
--- /dev/null
+++ b/package/uhttpd/src/uhttpd-cgi.c
@@ -0,0 +1,556 @@
+/*
+ * uhttpd - Tiny single-threaded httpd - CGI handler
+ *
+ * Copyright (C) 2010-2012 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "uhttpd.h"
+#include "uhttpd-utils.h"
+#include "uhttpd-cgi.h"
+
+
+static bool
+uh_cgi_header_parse(struct http_response *res, char *buf, int len, int *off)
+{
+ char *bufptr = NULL;
+ char *hdrname = NULL;
+ int hdrcount = 0;
+ int pos = 0;
+
+ if (((bufptr = strfind(buf, len, "\r\n\r\n", 4)) != NULL) ||
+ ((bufptr = strfind(buf, len, "\n\n", 2)) != NULL))
+ {
+ *off = (int)(bufptr - buf) + ((bufptr[0] == '\r') ? 4 : 2);
+
+ memset(res, 0, sizeof(*res));
+
+ res->statuscode = 200;
+ res->statusmsg = "OK";
+
+ bufptr = &buf[0];
+
+ for (pos = 0; pos < *off; pos++)
+ {
+ if (!hdrname && (buf[pos] == ':'))
+ {
+ buf[pos++] = 0;
+
+ if ((pos < len) && (buf[pos] == ' '))
+ pos++;
+
+ if (pos < len)
+ {
+ hdrname = bufptr;
+ bufptr = &buf[pos];
+ }
+ }
+
+ else if ((buf[pos] == '\r') || (buf[pos] == '\n'))
+ {
+ if (! hdrname)
+ break;
+
+ buf[pos++] = 0;
+
+ if ((pos < len) && (buf[pos] == '\n'))
+ pos++;
+
+ if (pos <= len)
+ {
+ if ((hdrcount+1) < array_size(res->headers))
+ {
+ if (!strcasecmp(hdrname, "Status"))
+ {
+ res->statuscode = atoi(bufptr);
+
+ if (res->statuscode < 100)
+ res->statuscode = 200;
+
+ if (((bufptr = strchr(bufptr, ' ')) != NULL) &&
+ (&bufptr[1] != 0))
+ {
+ res->statusmsg = &bufptr[1];
+ }
+
+ D("CGI: HTTP/1.x %03d %s\n",
+ res->statuscode, res->statusmsg);
+ }
+ else
+ {
+ D("CGI: HTTP: %s: %s\n", hdrname, bufptr);
+
+ res->headers[hdrcount++] = hdrname;
+ res->headers[hdrcount++] = bufptr;
+ }
+
+ bufptr = &buf[pos];
+ hdrname = NULL;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+static char * uh_cgi_header_lookup(struct http_response *res,
+ const char *hdrname)
+{
+ int i;
+
+ foreach_header(i, res->headers)
+ {
+ if (!strcasecmp(res->headers[i], hdrname))
+ return res->headers[i+1];
+ }
+
+ return NULL;
+}
+
+static void uh_cgi_shutdown(struct uh_cgi_state *state)
+{
+ free(state);
+}
+
+static bool uh_cgi_socket_cb(struct client *cl)
+{
+ int i, len, blen, hdroff;
+ char buf[UH_LIMIT_MSGHEAD];
+
+ struct uh_cgi_state *state = (struct uh_cgi_state *)cl->priv;
+ struct http_response *res = &cl->response;
+ struct http_request *req = &cl->request;
+
+ /* there is unread post data waiting */
+ while (state->content_length > 0)
+ {
+ /* remaining data in http head buffer ... */
+ if (cl->httpbuf.len > 0)
+ {
+ len = min(state->content_length, cl->httpbuf.len);
+
+ D("CGI: Child(%d) feed %d HTTP buffer bytes\n", cl->proc.pid, len);
+
+ memcpy(buf, cl->httpbuf.ptr, len);
+
+ cl->httpbuf.len -= len;
+ cl->httpbuf.ptr +=len;
+ }
+
+ /* read it from socket ... */
+ else
+ {
+ len = uh_tcp_recv(cl, buf,
+ min(state->content_length, sizeof(buf)));
+
+ if ((len < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
+ break;
+
+ D("CGI: Child(%d) feed %d/%d TCP socket bytes\n",
+ cl->proc.pid, len, min(state->content_length, sizeof(buf)));
+ }
+
+ if (len)
+ state->content_length -= len;
+ else
+ state->content_length = 0;
+
+ /* ... write to CGI process */
+ len = uh_raw_send(cl->wpipe.fd, buf, len,
+ cl->server->conf->script_timeout);
+
+ /* explicit EOF notification for the child */
+ if (state->content_length <= 0)
+ uh_ufd_remove(&cl->wpipe);
+ }
+
+ /* try to read data from child */
+ while ((len = uh_raw_recv(cl->rpipe.fd, buf, state->header_sent
+ ? sizeof(buf) : state->httpbuf.len, -1)) > 0)
+ {
+ /* we have not pushed out headers yet, parse input */
+ if (!state->header_sent)
+ {
+ /* try to parse header ... */
+ memcpy(state->httpbuf.ptr, buf, len);
+ state->httpbuf.len -= len;
+ state->httpbuf.ptr += len;
+
+ blen = state->httpbuf.ptr - state->httpbuf.buf;
+
+ if (uh_cgi_header_parse(res, state->httpbuf.buf, blen, &hdroff))
+ {
+ /* write status */
+ ensure_out(uh_http_sendf(cl, NULL,
+ "%s %03d %s\r\n"
+ "Connection: close\r\n",
+ http_versions[req->version],
+ res->statuscode, res->statusmsg));
+
+ /* add Content-Type if no Location or Content-Type */
+ if (!uh_cgi_header_lookup(res, "Location") &&
+ !uh_cgi_header_lookup(res, "Content-Type"))
+ {
+ ensure_out(uh_http_send(cl, NULL,
+ "Content-Type: text/plain\r\n", -1));
+ }
+
+ /* if request was HTTP 1.1 we'll respond chunked */
+ if ((req->version > UH_HTTP_VER_1_0) &&
+ !uh_cgi_header_lookup(res, "Transfer-Encoding"))
+ {
+ ensure_out(uh_http_send(cl, NULL,
+ "Transfer-Encoding: chunked\r\n", -1));
+ }
+
+ /* write headers from CGI program */
+ foreach_header(i, res->headers)
+ {
+ ensure_out(uh_http_sendf(cl, NULL, "%s: %s\r\n",
+ res->headers[i], res->headers[i+1]));
+ }
+
+ /* terminate header */
+ ensure_out(uh_http_send(cl, NULL, "\r\n", -1));
+
+ state->header_sent = true;
+
+ /* push out remaining head buffer */
+ if (hdroff < blen)
+ {
+ D("CGI: Child(%d) relaying %d rest bytes\n",
+ cl->proc.pid, blen - hdroff);
+
+ ensure_out(uh_http_send(cl, req,
+ state->httpbuf.buf + hdroff,
+ blen - hdroff));
+ }
+ }
+
+ /* ... failed and head buffer exceeded */
+ else if (!state->httpbuf.len)
+ {
+ /* I would do this ...
+ *
+ * uh_cgi_error_500(cl, req,
+ * "The CGI program generated an "
+ * "invalid response:\n\n");
+ *
+ * ... but in order to stay as compatible as possible,
+ * treat whatever we got as text/plain response and
+ * build the required headers here.
+ */
+
+ ensure_out(uh_http_sendf(cl, NULL,
+ "%s 200 OK\r\n"
+ "Content-Type: text/plain\r\n"
+ "%s\r\n",
+ http_versions[req->version],
+ (req->version > UH_HTTP_VER_1_0)
+ ? "Transfer-Encoding: chunked\r\n" : ""
+ ));
+
+ state->header_sent = true;
+
+ D("CGI: Child(%d) relaying %d invalid bytes\n",
+ cl->proc.pid, len);
+
+ ensure_out(uh_http_send(cl, req, buf, len));
+ }
+ }
+ else
+ {
+ /* headers complete, pass through buffer to socket */
+ D("CGI: Child(%d) relaying %d normal bytes\n", cl->proc.pid, len);
+ ensure_out(uh_http_send(cl, req, buf, len));
+ }
+ }
+
+ /* got EOF or read error from child */
+ if ((len == 0) ||
+ ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (len == -1)))
+ {
+ D("CGI: Child(%d) presumed dead [%s]\n", cl->proc.pid, strerror(errno));
+
+ goto out;
+ }
+
+ return true;
+
+out:
+ if (!state->header_sent)
+ {
+ if (cl->timeout.pending)
+ uh_http_sendhf(cl, 502, "Bad Gateway",
+ "The CGI process did not produce any response\n");
+ else
+ uh_http_sendhf(cl, 504, "Gateway Timeout",
+ "The CGI process took too long to produce a "
+ "response\n");
+ }
+ else
+ {
+ uh_http_send(cl, req, "", 0);
+ }
+
+ uh_cgi_shutdown(state);
+ return false;
+}
+
+bool uh_cgi_request(struct client *cl, struct path_info *pi,
+ struct interpreter *ip)
+{
+ int i;
+
+ int rfd[2] = { 0, 0 };
+ int wfd[2] = { 0, 0 };
+
+ pid_t child;
+
+ struct uh_cgi_state *state;
+ struct http_request *req = &cl->request;
+
+ /* allocate state */
+ if (!(state = malloc(sizeof(*state))))
+ {
+ uh_http_sendhf(cl, 500, "Internal Server Error", "Out of memory");
+ return false;
+ }
+
+ /* spawn pipes for me->child, child->me */
+ if ((pipe(rfd) < 0) || (pipe(wfd) < 0))
+ {
+ if (rfd[0] > 0) close(rfd[0]);
+ if (rfd[1] > 0) close(rfd[1]);
+ if (wfd[0] > 0) close(wfd[0]);
+ if (wfd[1] > 0) close(wfd[1]);
+
+ uh_http_sendhf(cl, 500, "Internal Server Error",
+ "Failed to create pipe: %s\n", strerror(errno));
+
+ return false;
+ }
+
+ /* fork off child process */
+ switch ((child = fork()))
+ {
+ /* oops */
+ case -1:
+ uh_http_sendhf(cl, 500, "Internal Server Error",
+ "Failed to fork child: %s\n", strerror(errno));
+
+ return false;
+
+ /* exec child */
+ case 0:
+#ifdef DEBUG
+ sleep(atoi(getenv("UHTTPD_SLEEP_ON_FORK") ?: "0"));
+#endif
+
+ /* do not leak parent epoll descriptor */
+ uloop_done();
+
+ /* close loose pipe ends */
+ close(rfd[0]);
+ close(wfd[1]);
+
+ /* patch stdout and stdin to pipes */
+ dup2(rfd[1], 1);
+ dup2(wfd[0], 0);
+
+ /* avoid leaking our pipe into child-child processes */
+ fd_cloexec(rfd[1]);
+ fd_cloexec(wfd[0]);
+
+ /* check for regular, world-executable file _or_ interpreter */
+ if (((pi->stat.st_mode & S_IFREG) &&
+ (pi->stat.st_mode & S_IXOTH)) || (ip != NULL))
+ {
+ /* build environment */
+ clearenv();
+
+ /* common information */
+ setenv("GATEWAY_INTERFACE", "CGI/1.1", 1);
+ setenv("SERVER_SOFTWARE", "uHTTPd", 1);
+ setenv("PATH", "/sbin:/usr/sbin:/bin:/usr/bin", 1);
+
+#ifdef HAVE_TLS
+ /* https? */
+ if (cl->tls)
+ setenv("HTTPS", "on", 1);
+#endif
+
+ /* addresses */
+ setenv("SERVER_NAME", sa_straddr(&cl->servaddr), 1);
+ setenv("SERVER_ADDR", sa_straddr(&cl->servaddr), 1);
+ setenv("SERVER_PORT", sa_strport(&cl->servaddr), 1);
+ setenv("REMOTE_HOST", sa_straddr(&cl->peeraddr), 1);
+ setenv("REMOTE_ADDR", sa_straddr(&cl->peeraddr), 1);
+ setenv("REMOTE_PORT", sa_strport(&cl->peeraddr), 1);
+
+ /* path information */
+ setenv("SCRIPT_NAME", pi->name, 1);
+ setenv("SCRIPT_FILENAME", pi->phys, 1);
+ setenv("DOCUMENT_ROOT", pi->root, 1);
+ setenv("QUERY_STRING", pi->query ? pi->query : "", 1);
+
+ if (pi->info)
+ setenv("PATH_INFO", pi->info, 1);
+
+ /* REDIRECT_STATUS, php-cgi wants it */
+ switch (req->redirect_status)
+ {
+ case 404:
+ setenv("REDIRECT_STATUS", "404", 1);
+ break;
+
+ default:
+ setenv("REDIRECT_STATUS", "200", 1);
+ break;
+ }
+
+ /* http version */
+ setenv("SERVER_PROTOCOL", http_versions[req->version], 1);
+
+ /* request method */
+ setenv("REQUEST_METHOD", http_methods[req->method], 1);
+
+ /* request url */
+ setenv("REQUEST_URI", req->url, 1);
+
+ /* remote user */
+ if (req->realm)
+ setenv("REMOTE_USER", req->realm->user, 1);
+
+ /* request message headers */
+ foreach_header(i, req->headers)
+ {
+ if (!strcasecmp(req->headers[i], "Accept"))
+ setenv("HTTP_ACCEPT", req->headers[i+1], 1);
+
+ else if (!strcasecmp(req->headers[i], "Accept-Charset"))
+ setenv("HTTP_ACCEPT_CHARSET", req->headers[i+1], 1);
+
+ else if (!strcasecmp(req->headers[i], "Accept-Encoding"))
+ setenv("HTTP_ACCEPT_ENCODING", req->headers[i+1], 1);
+
+ else if (!strcasecmp(req->headers[i], "Accept-Language"))
+ setenv("HTTP_ACCEPT_LANGUAGE", req->headers[i+1], 1);
+
+ else if (!strcasecmp(req->headers[i], "Authorization"))
+ setenv("HTTP_AUTHORIZATION", req->headers[i+1], 1);
+
+ else if (!strcasecmp(req->headers[i], "Connection"))
+ setenv("HTTP_CONNECTION", req->headers[i+1], 1);
+
+ else if (!strcasecmp(req->headers[i], "Cookie"))
+ setenv("HTTP_COOKIE", req->headers[i+1], 1);
+
+ else if (!strcasecmp(req->headers[i], "Host"))
+ setenv("HTTP_HOST", req->headers[i+1], 1);
+
+ else if (!strcasecmp(req->headers[i], "Referer"))
+ setenv("HTTP_REFERER", req->headers[i+1], 1);
+
+ else if (!strcasecmp(req->headers[i], "User-Agent"))
+ setenv("HTTP_USER_AGENT", req->headers[i+1], 1);
+
+ else if (!strcasecmp(req->headers[i], "Content-Type"))
+ setenv("CONTENT_TYPE", req->headers[i+1], 1);
+
+ else if (!strcasecmp(req->headers[i], "Content-Length"))
+ setenv("CONTENT_LENGTH", req->headers[i+1], 1);
+ }
+
+
+ /* execute child code ... */
+ if (chdir(pi->root))
+ perror("chdir()");
+
+ if (ip != NULL)
+ execl(ip->path, ip->path, pi->phys, NULL);
+ else
+ execl(pi->phys, pi->phys, NULL);
+
+ /* in case it fails ... */
+ printf("Status: 500 Internal Server Error\r\n\r\n"
+ "Unable to launch the requested CGI program:\n"
+ " %s: %s\n", ip ? ip->path : pi->phys, strerror(errno));
+ }
+
+ /* 403 */
+ else
+ {
+ printf("Status: 403 Forbidden\r\n\r\n"
+ "Access to this resource is forbidden\n");
+ }
+
+ close(wfd[0]);
+ close(rfd[1]);
+ exit(0);
+
+ break;
+
+ /* parent; handle I/O relaying */
+ default:
+ memset(state, 0, sizeof(*state));
+
+ cl->rpipe.fd = rfd[0];
+ cl->wpipe.fd = wfd[1];
+ cl->proc.pid = child;
+
+ /* make pipe non-blocking */
+ fd_nonblock(cl->rpipe.fd);
+ fd_nonblock(cl->wpipe.fd);
+
+ /* close unneeded pipe ends */
+ close(rfd[1]);
+ close(wfd[0]);
+
+ D("CGI: Child(%d) created: rfd(%d) wfd(%d)\n", child, rfd[0], wfd[1]);
+
+ state->httpbuf.ptr = state->httpbuf.buf;
+ state->httpbuf.len = sizeof(state->httpbuf.buf);
+
+ state->content_length = cl->httpbuf.len;
+
+ /* find content length */
+ if (req->method == UH_HTTP_MSG_POST)
+ {
+ foreach_header(i, req->headers)
+ {
+ if (!strcasecmp(req->headers[i], "Content-Length"))
+ {
+ state->content_length = atoi(req->headers[i+1]);
+ break;
+ }
+ }
+ }
+
+ cl->cb = uh_cgi_socket_cb;
+ cl->priv = state;
+
+ break;
+ }
+
+ return true;
+}
diff --git a/package/uhttpd/src/uhttpd-cgi.h b/package/uhttpd/src/uhttpd-cgi.h
new file mode 100644
index 000000000..c7094da42
--- /dev/null
+++ b/package/uhttpd/src/uhttpd-cgi.h
@@ -0,0 +1,43 @@
+/*
+ * uhttpd - Tiny single-threaded httpd - CGI header
+ *
+ * Copyright (C) 2010-2012 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UHTTPD_CGI_
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <linux/limits.h>
+
+#include <time.h>
+
+
+struct uh_cgi_state {
+ struct {
+ char buf[UH_LIMIT_MSGHEAD];
+ char *ptr;
+ int len;
+ } httpbuf;
+ int content_length;
+ bool header_sent;
+};
+
+bool uh_cgi_request(struct client *cl, struct path_info *pi,
+ struct interpreter *ip);
+
+#endif
diff --git a/package/uhttpd/src/uhttpd-file.c b/package/uhttpd/src/uhttpd-file.c
new file mode 100644
index 000000000..0bafc2b38
--- /dev/null
+++ b/package/uhttpd/src/uhttpd-file.c
@@ -0,0 +1,438 @@
+/*
+ * uhttpd - Tiny single-threaded httpd - Static file handler
+ *
+ * Copyright (C) 2010-2012 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _XOPEN_SOURCE 500 /* strptime() */
+#define _BSD_SOURCE /* scandir(), timegm() */
+
+#include "uhttpd.h"
+#include "uhttpd-utils.h"
+#include "uhttpd-file.h"
+
+#include "uhttpd-mimetypes.h"
+
+
+static const char * uh_file_mime_lookup(const char *path)
+{
+ struct mimetype *m = &uh_mime_types[0];
+ const char *e;
+
+ while (m->extn)
+ {
+ e = &path[strlen(path)-1];
+
+ while (e >= path)
+ {
+ if ((*e == '.' || *e == '/') && !strcasecmp(&e[1], m->extn))
+ return m->mime;
+
+ e--;
+ }
+
+ m++;
+ }
+
+ return "application/octet-stream";
+}
+
+static const char * uh_file_mktag(struct stat *s)
+{
+ static char tag[128];
+
+ snprintf(tag, sizeof(tag), "\"%x-%x-%x\"",
+ (unsigned int) s->st_ino,
+ (unsigned int) s->st_size,
+ (unsigned int) s->st_mtime);
+
+ return tag;
+}
+
+static time_t uh_file_date2unix(const char *date)
+{
+ struct tm t;
+
+ memset(&t, 0, sizeof(t));
+
+ if (strptime(date, "%a, %d %b %Y %H:%M:%S %Z", &t) != NULL)
+ return timegm(&t);
+
+ return 0;
+}
+
+static char * uh_file_unix2date(time_t ts)
+{
+ static char str[128];
+ struct tm *t = gmtime(&ts);
+
+ strftime(str, sizeof(str), "%a, %d %b %Y %H:%M:%S GMT", t);
+
+ return str;
+}
+
+static char * uh_file_header_lookup(struct client *cl, const char *name)
+{
+ int i;
+
+ foreach_header(i, cl->request.headers)
+ {
+ if (!strcasecmp(cl->request.headers[i], name))
+ return cl->request.headers[i+1];
+ }
+
+ return NULL;
+}
+
+
+static int uh_file_response_ok_hdrs(struct client *cl, struct stat *s)
+{
+ ensure_ret(uh_http_sendf(cl, NULL, "Connection: close\r\n"));
+
+ if (s)
+ {
+ ensure_ret(uh_http_sendf(cl, NULL, "ETag: %s\r\n", uh_file_mktag(s)));
+ ensure_ret(uh_http_sendf(cl, NULL, "Last-Modified: %s\r\n",
+ uh_file_unix2date(s->st_mtime)));
+ }
+
+ return uh_http_sendf(cl, NULL, "Date: %s\r\n", uh_file_unix2date(time(NULL)));
+}
+
+static int uh_file_response_200(struct client *cl, struct stat *s)
+{
+ ensure_ret(uh_http_sendf(cl, NULL, "%s 200 OK\r\n",
+ http_versions[cl->request.version]));
+
+ return uh_file_response_ok_hdrs(cl, s);
+}
+
+static int uh_file_response_304(struct client *cl, struct stat *s)
+{
+ ensure_ret(uh_http_sendf(cl, NULL, "%s 304 Not Modified\r\n",
+ http_versions[cl->request.version]));
+
+ return uh_file_response_ok_hdrs(cl, s);
+}
+
+static int uh_file_response_412(struct client *cl)
+{
+ return uh_http_sendf(cl, NULL,
+ "%s 412 Precondition Failed\r\n"
+ "Connection: close\r\n",
+ http_versions[cl->request.version]);
+}
+
+static int uh_file_if_match(struct client *cl, struct stat *s, int *ok)
+{
+ const char *tag = uh_file_mktag(s);
+ char *hdr = uh_file_header_lookup(cl, "If-Match");
+ char *p;
+ int i;
+
+ if (hdr)
+ {
+ p = &hdr[0];
+
+ for (i = 0; i < strlen(hdr); i++)
+ {
+ if ((hdr[i] == ' ') || (hdr[i] == ','))
+ {
+ hdr[i++] = 0;
+ p = &hdr[i];
+ }
+ else if (!strcmp(p, "*") || !strcmp(p, tag))
+ {
+ *ok = 1;
+ return *ok;
+ }
+ }
+
+ *ok = 0;
+ ensure_ret(uh_file_response_412(cl));
+ return *ok;
+ }
+
+ *ok = 1;
+ return *ok;
+}
+
+static int uh_file_if_modified_since(struct client *cl, struct stat *s, int *ok)
+{
+ char *hdr = uh_file_header_lookup(cl, "If-Modified-Since");
+ *ok = 1;
+
+ if (hdr)
+ {
+ if (uh_file_date2unix(hdr) >= s->st_mtime)
+ {
+ *ok = 0;
+ ensure_ret(uh_file_response_304(cl, s));
+ }
+ }
+
+ return *ok;
+}
+
+static int uh_file_if_none_match(struct client *cl, struct stat *s, int *ok)
+{
+ const char *tag = uh_file_mktag(s);
+ char *hdr = uh_file_header_lookup(cl, "If-None-Match");
+ char *p;
+ int i;
+ *ok = 1;
+
+ if (hdr)
+ {
+ p = &hdr[0];
+
+ for (i = 0; i < strlen(hdr); i++)
+ {
+ if ((hdr[i] == ' ') || (hdr[i] == ','))
+ {
+ hdr[i++] = 0;
+ p = &hdr[i];
+ }
+ else if (!strcmp(p, "*") || !strcmp(p, tag))
+ {
+ *ok = 0;
+
+ if ((cl->request.method == UH_HTTP_MSG_GET) ||
+ (cl->request.method == UH_HTTP_MSG_HEAD))
+ {
+ ensure_ret(uh_file_response_304(cl, s));
+ }
+ else
+ {
+ ensure_ret(uh_file_response_412(cl));
+ }
+
+ break;
+ }
+ }
+ }
+
+ return *ok;
+}
+
+static int uh_file_if_range(struct client *cl, struct stat *s, int *ok)
+{
+ char *hdr = uh_file_header_lookup(cl, "If-Range");
+ *ok = 1;
+
+ if (hdr)
+ {
+ *ok = 0;
+ ensure_ret(uh_file_response_412(cl));
+ }
+
+ return *ok;
+}
+
+static int uh_file_if_unmodified_since(struct client *cl, struct stat *s,
+ int *ok)
+{
+ char *hdr = uh_file_header_lookup(cl, "If-Unmodified-Since");
+ *ok = 1;
+
+ if (hdr)
+ {
+ if (uh_file_date2unix(hdr) <= s->st_mtime)
+ {
+ *ok = 0;
+ ensure_ret(uh_file_response_412(cl));
+ }
+ }
+
+ return *ok;
+}
+
+
+static int uh_file_scandir_filter_dir(const struct dirent *e)
+{
+ return strcmp(e->d_name, ".") ? 1 : 0;
+}
+
+static void uh_file_dirlist(struct client *cl, struct path_info *pi)
+{
+ int i;
+ int count = 0;
+ char filename[PATH_MAX];
+ char *pathptr;
+ struct dirent **files = NULL;
+ struct stat s;
+
+ ensure_out(uh_http_sendf(cl, &cl->request,
+ "<html><head><title>Index of %s</title></head>"
+ "<body><h1>Index of %s</h1><hr /><ol>",
+ pi->name, pi->name));
+
+ if ((count = scandir(pi->phys, &files, uh_file_scandir_filter_dir,
+ alphasort)) > 0)
+ {
+ memset(filename, 0, sizeof(filename));
+ memcpy(filename, pi->phys, sizeof(filename));
+ pathptr = &filename[strlen(filename)];
+
+ /* list subdirs */
+ for (i = 0; i < count; i++)
+ {
+ strncat(filename, files[i]->d_name,
+ sizeof(filename) - strlen(files[i]->d_name));
+
+ if (!stat(filename, &s) &&
+ (s.st_mode & S_IFDIR) && (s.st_mode & S_IXOTH))
+ {
+ ensure_out(uh_http_sendf(cl, &cl->request,
+ "<li><strong><a href='%s%s'>%s</a>/"
+ "</strong><br /><small>modified: %s"
+ "<br />directory - %.02f kbyte<br />"
+ "<br /></small></li>",
+ pi->name, files[i]->d_name,
+ files[i]->d_name,
+ uh_file_unix2date(s.st_mtime),
+ s.st_size / 1024.0));
+ }
+
+ *pathptr = 0;
+ }
+
+ /* list files */
+ for (i = 0; i < count; i++)
+ {
+ strncat(filename, files[i]->d_name,
+ sizeof(filename) - strlen(files[i]->d_name));
+
+ if (!stat(filename, &s) &&
+ !(s.st_mode & S_IFDIR) && (s.st_mode & S_IROTH))
+ {
+ ensure_out(uh_http_sendf(cl, &cl->request,
+ "<li><strong><a href='%s%s'>%s</a>"
+ "</strong><br /><small>modified: %s"
+ "<br />%s - %.02f kbyte<br />"
+ "<br /></small></li>",
+ pi->name, files[i]->d_name,
+ files[i]->d_name,
+ uh_file_unix2date(s.st_mtime),
+ uh_file_mime_lookup(filename),
+ s.st_size / 1024.0));
+ }
+
+ *pathptr = 0;
+ }
+ }
+
+ ensure_out(uh_http_sendf(cl, &cl->request, "</ol><hr /></body></html>"));
+ ensure_out(uh_http_sendf(cl, &cl->request, ""));
+
+out:
+ if (files)
+ {
+ for (i = 0; i < count; i++)
+ free(files[i]);
+
+ free(files);
+ }
+}
+
+
+bool uh_file_request(struct client *cl, struct path_info *pi)
+{
+ int rlen;
+ int ok = 1;
+ int fd = -1;
+ char buf[UH_LIMIT_MSGHEAD];
+
+ /* we have a file */
+ if ((pi->stat.st_mode & S_IFREG) && ((fd = open(pi->phys, O_RDONLY)) > 0))
+ {
+ /* test preconditions */
+ if (ok) ensure_out(uh_file_if_modified_since(cl, &pi->stat, &ok));
+ if (ok) ensure_out(uh_file_if_match(cl, &pi->stat, &ok));
+ if (ok) ensure_out(uh_file_if_range(cl, &pi->stat, &ok));
+ if (ok) ensure_out(uh_file_if_unmodified_since(cl, &pi->stat, &ok));
+ if (ok) ensure_out(uh_file_if_none_match(cl, &pi->stat, &ok));
+
+ if (ok > 0)
+ {
+ /* write status */
+ ensure_out(uh_file_response_200(cl, &pi->stat));
+
+ ensure_out(uh_http_sendf(cl, NULL, "Content-Type: %s\r\n",
+ uh_file_mime_lookup(pi->name)));
+
+ ensure_out(uh_http_sendf(cl, NULL, "Content-Length: %i\r\n",
+ pi->stat.st_size));
+
+ /* if request was HTTP 1.1 we'll respond chunked */
+ if ((cl->request.version > 1.0) &&
+ (cl->request.method != UH_HTTP_MSG_HEAD))
+ {
+ ensure_out(uh_http_send(cl, NULL,
+ "Transfer-Encoding: chunked\r\n", -1));
+ }
+
+ /* close header */
+ ensure_out(uh_http_send(cl, NULL, "\r\n", -1));
+
+ /* send body */
+ if (cl->request.method != UH_HTTP_MSG_HEAD)
+ {
+ /* pump file data */
+ while ((rlen = read(fd, buf, sizeof(buf))) > 0)
+ ensure_out(uh_http_send(cl, &cl->request, buf, rlen));
+
+ /* send trailer in chunked mode */
+ ensure_out(uh_http_send(cl, &cl->request, "", 0));
+ }
+ }
+
+ /* one of the preconditions failed, terminate opened header and exit */
+ else
+ {
+ ensure_out(uh_http_send(cl, NULL, "\r\n", -1));
+ }
+ }
+
+ /* directory */
+ else if ((pi->stat.st_mode & S_IFDIR) && !cl->server->conf->no_dirlists)
+ {
+ /* write status */
+ ensure_out(uh_file_response_200(cl, NULL));
+
+ if (cl->request.version > 1.0)
+ ensure_out(uh_http_send(cl, NULL,
+ "Transfer-Encoding: chunked\r\n", -1));
+
+ ensure_out(uh_http_send(cl, NULL,
+ "Content-Type: text/html\r\n\r\n", -1));
+
+ /* content */
+ uh_file_dirlist(cl, pi);
+ }
+
+ /* 403 */
+ else
+ {
+ ensure_out(uh_http_sendhf(cl, 403, "Forbidden",
+ "Access to this resource is forbidden"));
+ }
+
+out:
+ if (fd > -1)
+ close(fd);
+
+ return false;
+}
diff --git a/package/uhttpd/src/uhttpd-file.h b/package/uhttpd/src/uhttpd-file.h
new file mode 100644
index 000000000..08dbe2cf9
--- /dev/null
+++ b/package/uhttpd/src/uhttpd-file.h
@@ -0,0 +1,36 @@
+/*
+ * uhttpd - Tiny single-threaded httpd - Static file header
+ *
+ * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UHTTPD_FILE_
+
+#include <fcntl.h>
+#include <time.h>
+#include <strings.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <linux/limits.h>
+
+struct mimetype {
+ const char *extn;
+ const char *mime;
+};
+
+bool uh_file_request(struct client *cl, struct path_info *pi);
+
+#endif
diff --git a/package/uhttpd/src/uhttpd-lua.c b/package/uhttpd/src/uhttpd-lua.c
new file mode 100644
index 000000000..e11393739
--- /dev/null
+++ b/package/uhttpd/src/uhttpd-lua.c
@@ -0,0 +1,579 @@
+/*
+ * uhttpd - Tiny single-threaded httpd - Lua handler
+ *
+ * Copyright (C) 2010-2012 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "uhttpd.h"
+#include "uhttpd-utils.h"
+#include "uhttpd-lua.h"
+
+
+static int uh_lua_recv(lua_State *L)
+{
+ size_t length;
+
+ char buffer[UH_LIMIT_MSGHEAD];
+
+ int to = 1;
+ int fd = fileno(stdin);
+ int rlen = 0;
+
+ length = luaL_checknumber(L, 1);
+
+ if ((length > 0) && (length <= sizeof(buffer)))
+ {
+ /* receive data */
+ rlen = uh_raw_recv(fd, buffer, length, to);
+
+ /* data read */
+ if (rlen > 0)
+ {
+ lua_pushnumber(L, rlen);
+ lua_pushlstring(L, buffer, rlen);
+ return 2;
+ }
+
+ /* eof */
+ else if (rlen == 0)
+ {
+ lua_pushnumber(L, 0);
+ return 1;
+ }
+
+ /* no, timeout and actually no data */
+ else
+ {
+ lua_pushnumber(L, -1);
+ return 1;
+ }
+ }
+
+ /* parameter error */
+ lua_pushnumber(L, -2);
+ return 1;
+}
+
+static int uh_lua_send_common(lua_State *L, bool chunked)
+{
+ size_t length;
+
+ char chunk[16];
+ const char *buffer;
+
+ int rv;
+ int to = 1;
+ int fd = fileno(stdout);
+ int slen = 0;
+
+ buffer = luaL_checklstring(L, 1, &length);
+
+ if (chunked)
+ {
+ if (length > 0)
+ {
+ snprintf(chunk, sizeof(chunk), "%X\r\n", length);
+
+ ensure_out(rv = uh_raw_send(fd, chunk, strlen(chunk), to));
+ slen += rv;
+
+ ensure_out(rv = uh_raw_send(fd, buffer, length, to));
+ slen += rv;
+
+ ensure_out(rv = uh_raw_send(fd, "\r\n", 2, to));
+ slen += rv;
+ }
+ else
+ {
+ slen = uh_raw_send(fd, "0\r\n\r\n", 5, to);
+ }
+ }
+ else
+ {
+ slen = uh_raw_send(fd, buffer, length, to);
+ }
+
+out:
+ lua_pushnumber(L, slen);
+ return 1;
+}
+
+static int uh_lua_send(lua_State *L)
+{
+ return uh_lua_send_common(L, false);
+}
+
+static int uh_lua_sendc(lua_State *L)
+{
+ return uh_lua_send_common(L, true);
+}
+
+static int uh_lua_str2str(lua_State *L, int (*xlate_func) (char *, int, const char *, int))
+{
+ size_t inlen;
+ int outlen;
+ const char *inbuf;
+ char outbuf[UH_LIMIT_MSGHEAD];
+
+ inbuf = luaL_checklstring(L, 1, &inlen);
+ outlen = (* xlate_func)(outbuf, sizeof(outbuf), inbuf, inlen);
+ if (outlen < 0)
+ luaL_error(L, "%s on URL-encode codec",
+ (outlen==-1) ? "buffer overflow" : "malformed string");
+
+ lua_pushlstring(L, outbuf, outlen);
+ return 1;
+}
+
+static int uh_lua_urldecode(lua_State *L)
+{
+ return uh_lua_str2str( L, uh_urldecode );
+}
+
+
+static int uh_lua_urlencode(lua_State *L)
+{
+ return uh_lua_str2str( L, uh_urlencode );
+}
+
+
+lua_State * uh_lua_init(const struct config *conf)
+{
+ lua_State *L = lua_open();
+ const char *err_str = NULL;
+
+ /* Load standard libaries */
+ luaL_openlibs(L);
+
+ /* build uhttpd api table */
+ lua_newtable(L);
+
+ /* register global send and receive functions */
+ lua_pushcfunction(L, uh_lua_recv);
+ lua_setfield(L, -2, "recv");
+
+ lua_pushcfunction(L, uh_lua_send);
+ lua_setfield(L, -2, "send");
+
+ lua_pushcfunction(L, uh_lua_sendc);
+ lua_setfield(L, -2, "sendc");
+
+ lua_pushcfunction(L, uh_lua_urldecode);
+ lua_setfield(L, -2, "urldecode");
+
+ lua_pushcfunction(L, uh_lua_urlencode);
+ lua_setfield(L, -2, "urlencode");
+
+ /* Pass the document-root to the Lua handler by placing it in
+ ** uhttpd.docroot. It could alternatively be placed in env.DOCUMENT_ROOT
+ ** which would more closely resemble the CGI protocol; but would mean that
+ ** it is not available at the time when the handler-chunk is loaded but
+ ** rather not until the handler is called, without any code savings. */
+ lua_pushstring(L, conf->docroot);
+ lua_setfield(L, -2, "docroot");
+
+ /* _G.uhttpd = { ... } */
+ lua_setfield(L, LUA_GLOBALSINDEX, "uhttpd");
+
+
+ /* load Lua handler */
+ switch (luaL_loadfile(L, conf->lua_handler))
+ {
+ case LUA_ERRSYNTAX:
+ fprintf(stderr,
+ "Lua handler contains syntax errors, unable to continue\n");
+ exit(1);
+
+ case LUA_ERRMEM:
+ fprintf(stderr,
+ "Lua handler ran out of memory, unable to continue\n");
+ exit(1);
+
+ case LUA_ERRFILE:
+ fprintf(stderr,
+ "Lua cannot open the handler script, unable to continue\n");
+ exit(1);
+
+ default:
+ /* compile Lua handler */
+ switch (lua_pcall(L, 0, 0, 0))
+ {
+ case LUA_ERRRUN:
+ err_str = luaL_checkstring(L, -1);
+ fprintf(stderr,
+ "Lua handler had runtime error, "
+ "unable to continue\n"
+ "Error: %s\n", err_str);
+ exit(1);
+
+ case LUA_ERRMEM:
+ err_str = luaL_checkstring(L, -1);
+ fprintf(stderr,
+ "Lua handler ran out of memory, "
+ "unable to continue\n"
+ "Error: %s\n", err_str);
+ exit(1);
+
+ default:
+ /* test handler function */
+ lua_getglobal(L, UH_LUA_CALLBACK);
+
+ if (! lua_isfunction(L, -1))
+ {
+ fprintf(stderr,
+ "Lua handler provides no "UH_LUA_CALLBACK"(), "
+ "unable to continue\n");
+ exit(1);
+ }
+
+ lua_pop(L, 1);
+ break;
+ }
+
+ break;
+ }
+
+ return L;
+}
+
+static void uh_lua_shutdown(struct uh_lua_state *state)
+{
+ free(state);
+}
+
+static bool uh_lua_socket_cb(struct client *cl)
+{
+ int len;
+ char buf[UH_LIMIT_MSGHEAD];
+
+ struct uh_lua_state *state = (struct uh_lua_state *)cl->priv;
+
+ /* there is unread post data waiting */
+ while (state->content_length > 0)
+ {
+ /* remaining data in http head buffer ... */
+ if (cl->httpbuf.len > 0)
+ {
+ len = min(state->content_length, cl->httpbuf.len);
+
+ D("Lua: Child(%d) feed %d HTTP buffer bytes\n", cl->proc.pid, len);
+
+ memcpy(buf, cl->httpbuf.ptr, len);
+
+ cl->httpbuf.len -= len;
+ cl->httpbuf.ptr += len;
+ }
+
+ /* read it from socket ... */
+ else
+ {
+ len = uh_tcp_recv(cl, buf, min(state->content_length, sizeof(buf)));
+
+ if ((len < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
+ break;
+
+ D("Lua: Child(%d) feed %d/%d TCP socket bytes\n",
+ cl->proc.pid, len, min(state->content_length, sizeof(buf)));
+ }
+
+ if (len)
+ state->content_length -= len;
+ else
+ state->content_length = 0;
+
+ /* ... write to Lua process */
+ len = uh_raw_send(cl->wpipe.fd, buf, len,
+ cl->server->conf->script_timeout);
+
+ /* explicit EOF notification for the child */
+ if (state->content_length <= 0)
+ uh_ufd_remove(&cl->wpipe);
+ }
+
+ /* try to read data from child */
+ while ((len = uh_raw_recv(cl->rpipe.fd, buf, sizeof(buf), -1)) > 0)
+ {
+ /* pass through buffer to socket */
+ D("Lua: Child(%d) relaying %d normal bytes\n", cl->proc.pid, len);
+ ensure_out(uh_tcp_send(cl, buf, len));
+ state->data_sent = true;
+ }
+
+ /* got EOF or read error from child */
+ if ((len == 0) ||
+ ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (len == -1)))
+ {
+ D("Lua: Child(%d) presumed dead [%s]\n",
+ cl->proc.pid, strerror(errno));
+
+ goto out;
+ }
+
+ return true;
+
+out:
+ if (!state->data_sent)
+ {
+ if (cl->timeout.pending)
+ uh_http_sendhf(cl, 502, "Bad Gateway",
+ "The Lua process did not produce any response\n");
+ else
+ uh_http_sendhf(cl, 504, "Gateway Timeout",
+ "The Lua process took too long to produce a "
+ "response\n");
+ }
+
+ uh_lua_shutdown(state);
+ return false;
+}
+
+bool uh_lua_request(struct client *cl, lua_State *L)
+{
+ int i;
+ char *query_string;
+ const char *prefix = cl->server->conf->lua_prefix;
+ const char *err_str = NULL;
+
+ int rfd[2] = { 0, 0 };
+ int wfd[2] = { 0, 0 };
+
+ pid_t child;
+
+ struct uh_lua_state *state;
+ struct http_request *req = &cl->request;
+
+ int content_length = cl->httpbuf.len;
+
+
+ /* allocate state */
+ if (!(state = malloc(sizeof(*state))))
+ {
+ uh_client_error(cl, 500, "Internal Server Error", "Out of memory");
+ return false;
+ }
+
+ /* spawn pipes for me->child, child->me */
+ if ((pipe(rfd) < 0) || (pipe(wfd) < 0))
+ {
+ if (rfd[0] > 0) close(rfd[0]);
+ if (rfd[1] > 0) close(rfd[1]);
+ if (wfd[0] > 0) close(wfd[0]);
+ if (wfd[1] > 0) close(wfd[1]);
+
+ uh_client_error(cl, 500, "Internal Server Error",
+ "Failed to create pipe: %s", strerror(errno));
+
+ return false;
+ }
+
+
+ switch ((child = fork()))
+ {
+ case -1:
+ uh_client_error(cl, 500, "Internal Server Error",
+ "Failed to fork child: %s", strerror(errno));
+
+ return false;
+
+ case 0:
+#ifdef DEBUG
+ sleep(atoi(getenv("UHTTPD_SLEEP_ON_FORK") ?: "0"));
+#endif
+
+ /* do not leak parent epoll descriptor */
+ uloop_done();
+
+ /* close loose pipe ends */
+ close(rfd[0]);
+ close(wfd[1]);
+
+ /* patch stdout and stdin to pipes */
+ dup2(rfd[1], 1);
+ dup2(wfd[0], 0);
+
+ /* avoid leaking our pipe into child-child processes */
+ fd_cloexec(rfd[1]);
+ fd_cloexec(wfd[0]);
+
+ /* put handler callback on stack */
+ lua_getglobal(L, UH_LUA_CALLBACK);
+
+ /* build env table */
+ lua_newtable(L);
+
+ /* request method */
+ lua_pushstring(L, http_methods[req->method]);
+ lua_setfield(L, -2, "REQUEST_METHOD");
+
+ /* request url */
+ lua_pushstring(L, req->url);
+ lua_setfield(L, -2, "REQUEST_URI");
+
+ /* script name */
+ lua_pushstring(L, cl->server->conf->lua_prefix);
+ lua_setfield(L, -2, "SCRIPT_NAME");
+
+ /* query string, path info */
+ if ((query_string = strchr(req->url, '?')) != NULL)
+ {
+ lua_pushstring(L, query_string + 1);
+ lua_setfield(L, -2, "QUERY_STRING");
+
+ if ((int)(query_string - req->url) > strlen(prefix))
+ {
+ lua_pushlstring(L,
+ &req->url[strlen(prefix)],
+ (int)(query_string - req->url) - strlen(prefix)
+ );
+
+ lua_setfield(L, -2, "PATH_INFO");
+ }
+ }
+ else if (strlen(req->url) > strlen(prefix))
+ {
+ lua_pushstring(L, &req->url[strlen(prefix)]);
+ lua_setfield(L, -2, "PATH_INFO");
+ }
+
+ /* http protcol version */
+ lua_pushnumber(L, 0.9 + (req->version / 10.0));
+ lua_setfield(L, -2, "HTTP_VERSION");
+
+ lua_pushstring(L, http_versions[req->version]);
+ lua_setfield(L, -2, "SERVER_PROTOCOL");
+
+
+ /* address information */
+ lua_pushstring(L, sa_straddr(&cl->peeraddr));
+ lua_setfield(L, -2, "REMOTE_ADDR");
+
+ lua_pushinteger(L, sa_port(&cl->peeraddr));
+ lua_setfield(L, -2, "REMOTE_PORT");
+
+ lua_pushstring(L, sa_straddr(&cl->servaddr));
+ lua_setfield(L, -2, "SERVER_ADDR");
+
+ lua_pushinteger(L, sa_port(&cl->servaddr));
+ lua_setfield(L, -2, "SERVER_PORT");
+
+ /* essential env vars */
+ foreach_header(i, req->headers)
+ {
+ if (!strcasecmp(req->headers[i], "Content-Length"))
+ {
+ content_length = atoi(req->headers[i+1]);
+ }
+ else if (!strcasecmp(req->headers[i], "Content-Type"))
+ {
+ lua_pushstring(L, req->headers[i+1]);
+ lua_setfield(L, -2, "CONTENT_TYPE");
+ }
+ }
+
+ lua_pushnumber(L, content_length);
+ lua_setfield(L, -2, "CONTENT_LENGTH");
+
+ /* misc. headers */
+ lua_newtable(L);
+
+ foreach_header(i, req->headers)
+ {
+ if( strcasecmp(req->headers[i], "Content-Length") &&
+ strcasecmp(req->headers[i], "Content-Type"))
+ {
+ lua_pushstring(L, req->headers[i+1]);
+ lua_setfield(L, -2, req->headers[i]);
+ }
+ }
+
+ lua_setfield(L, -2, "headers");
+
+
+ /* call */
+ switch (lua_pcall(L, 1, 0, 0))
+ {
+ case LUA_ERRMEM:
+ case LUA_ERRRUN:
+ err_str = luaL_checkstring(L, -1);
+
+ if (! err_str)
+ err_str = "Unknown error";
+
+ printf("%s 500 Internal Server Error\r\n"
+ "Connection: close\r\n"
+ "Content-Type: text/plain\r\n"
+ "Content-Length: %i\r\n\r\n"
+ "Lua raised a runtime error:\n %s\n",
+ http_versions[req->version],
+ 31 + strlen(err_str), err_str);
+
+ break;
+
+ default:
+ break;
+ }
+
+ close(wfd[0]);
+ close(rfd[1]);
+ exit(0);
+
+ break;
+
+ /* parent; handle I/O relaying */
+ default:
+ memset(state, 0, sizeof(*state));
+
+ cl->rpipe.fd = rfd[0];
+ cl->wpipe.fd = wfd[1];
+ cl->proc.pid = child;
+
+ /* make pipe non-blocking */
+ fd_nonblock(cl->rpipe.fd);
+ fd_nonblock(cl->wpipe.fd);
+
+ /* close unneeded pipe ends */
+ close(rfd[1]);
+ close(wfd[0]);
+
+ D("Lua: Child(%d) created: rfd(%d) wfd(%d)\n", child, rfd[0], wfd[1]);
+
+ state->content_length = cl->httpbuf.len;
+
+ /* find content length */
+ if (req->method == UH_HTTP_MSG_POST)
+ {
+ foreach_header(i, req->headers)
+ {
+ if (!strcasecmp(req->headers[i], "Content-Length"))
+ {
+ state->content_length = atoi(req->headers[i+1]);
+ break;
+ }
+ }
+ }
+
+ cl->cb = uh_lua_socket_cb;
+ cl->priv = state;
+
+ break;
+ }
+
+ return true;
+}
+
+void uh_lua_close(lua_State *L)
+{
+ lua_close(L);
+}
diff --git a/package/uhttpd/src/uhttpd-lua.h b/package/uhttpd/src/uhttpd-lua.h
new file mode 100644
index 000000000..780d845d8
--- /dev/null
+++ b/package/uhttpd/src/uhttpd-lua.h
@@ -0,0 +1,44 @@
+/*
+ * uhttpd - Tiny single-threaded httpd - Lua header
+ *
+ * Copyright (C) 2010-2012 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UHTTPD_LUA_
+
+#include <math.h> /* floor() */
+#include <errno.h>
+
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+
+#define UH_LUA_CALLBACK "handle_request"
+
+#define UH_LUA_ERR_TIMEOUT -1
+#define UH_LUA_ERR_TOOBIG -2
+#define UH_LUA_ERR_PARAM -3
+
+
+struct uh_lua_state {
+ int content_length;
+ bool data_sent;
+};
+
+lua_State * uh_lua_init(const struct config *conf);
+bool uh_lua_request(struct client *cl, lua_State *L);
+void uh_lua_close(lua_State *L);
+
+#endif
diff --git a/package/uhttpd/src/uhttpd-mimetypes.h b/package/uhttpd/src/uhttpd-mimetypes.h
new file mode 100644
index 000000000..21717c000
--- /dev/null
+++ b/package/uhttpd/src/uhttpd-mimetypes.h
@@ -0,0 +1,86 @@
+/*
+ * uhttpd - Tiny single-threaded httpd - MIME type definitions
+ *
+ * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UHTTPD_MIMETYPES_
+
+static struct mimetype uh_mime_types[] = {
+
+ { "txt", "text/plain" },
+ { "log", "text/plain" },
+ { "js", "text/javascript" },
+ { "css", "text/css" },
+ { "htm", "text/html" },
+ { "html", "text/html" },
+ { "diff", "text/x-patch" },
+ { "patch", "text/x-patch" },
+ { "c", "text/x-csrc" },
+ { "h", "text/x-chdr" },
+ { "o", "text/x-object" },
+ { "ko", "text/x-object" },
+
+ { "bmp", "image/bmp" },
+ { "gif", "image/gif" },
+ { "png", "image/png" },
+ { "jpg", "image/jpeg" },
+ { "jpeg", "image/jpeg" },
+ { "svg", "image/svg+xml" },
+
+ { "zip", "application/zip" },
+ { "pdf", "application/pdf" },
+ { "xml", "application/xml" },
+ { "xsl", "application/xml" },
+ { "doc", "application/msword" },
+ { "ppt", "application/vnd.ms-powerpoint" },
+ { "xls", "application/vnd.ms-excel" },
+ { "odt", "application/vnd.oasis.opendocument.text" },
+ { "odp", "application/vnd.oasis.opendocument.presentation" },
+ { "pl", "application/x-perl" },
+ { "sh", "application/x-shellscript" },
+ { "php", "application/x-php" },
+ { "deb", "application/x-deb" },
+ { "iso", "application/x-cd-image" },
+ { "tar.gz", "application/x-compressed-tar" },
+ { "tgz", "application/x-compressed-tar" },
+ { "gz", "application/x-gzip" },
+ { "tar.bz2", "application/x-bzip-compressed-tar" },
+ { "tbz", "application/x-bzip-compressed-tar" },
+ { "bz2", "application/x-bzip" },
+ { "tar", "application/x-tar" },
+ { "rar", "application/x-rar-compressed" },
+
+ { "mp3", "audio/mpeg" },
+ { "ogg", "audio/x-vorbis+ogg" },
+ { "wav", "audio/x-wav" },
+
+ { "mpg", "video/mpeg" },
+ { "mpeg", "video/mpeg" },
+ { "avi", "video/x-msvideo" },
+
+ { "README", "text/plain" },
+ { "log", "text/plain" },
+ { "cfg", "text/plain" },
+ { "conf", "text/plain" },
+
+ { "pac", "application/x-ns-proxy-autoconfig" },
+ { "wpad.dat", "application/x-ns-proxy-autoconfig" },
+
+ { NULL, NULL }
+};
+
+#endif
+
diff --git a/package/uhttpd/src/uhttpd-tls.c b/package/uhttpd/src/uhttpd-tls.c
new file mode 100644
index 000000000..9c6eb81db
--- /dev/null
+++ b/package/uhttpd/src/uhttpd-tls.c
@@ -0,0 +1,170 @@
+/*
+ * uhttpd - Tiny single-threaded httpd - TLS helper
+ *
+ * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "uhttpd.h"
+#include "uhttpd-tls.h"
+#include "uhttpd-utils.h"
+
+#include <syslog.h>
+#define dbg(...) syslog(LOG_INFO, __VA_ARGS__)
+
+SSL_CTX * uh_tls_ctx_init(void)
+{
+ SSL_CTX *c;
+
+ SSL_load_error_strings();
+ SSL_library_init();
+
+#if TLS_IS_OPENSSL
+ if ((c = SSL_CTX_new(SSLv23_server_method())) != NULL)
+#else
+ if ((c = SSL_CTX_new(TLSv1_server_method())) != NULL)
+#endif
+ SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL);
+
+ return c;
+}
+
+int uh_tls_ctx_cert(SSL_CTX *c, const char *file)
+{
+ int rv;
+
+ if( (rv = SSL_CTX_use_certificate_file(c, file, SSL_FILETYPE_PEM)) < 1 )
+ rv = SSL_CTX_use_certificate_file(c, file, SSL_FILETYPE_ASN1);
+
+ return rv;
+}
+
+int uh_tls_ctx_key(SSL_CTX *c, const char *file)
+{
+ int rv;
+
+ if( (rv = SSL_CTX_use_PrivateKey_file(c, file, SSL_FILETYPE_PEM)) < 1 )
+ rv = SSL_CTX_use_PrivateKey_file(c, file, SSL_FILETYPE_ASN1);
+
+ return rv;
+}
+
+void uh_tls_ctx_free(struct listener *l)
+{
+ SSL_CTX_free(l->tls);
+}
+
+
+int uh_tls_client_accept(struct client *c)
+{
+ int rv, err;
+ int fd = c->fd.fd;
+
+ if (!c->server || !c->server->tls)
+ {
+ c->tls = NULL;
+ return 1;
+ }
+
+ if ((c->tls = SSL_new(c->server->tls)))
+ {
+ if ((rv = SSL_set_fd(c->tls, fd)) < 1)
+ {
+ SSL_free(c->tls);
+ c->tls = NULL;
+ }
+ else
+ {
+ while (true)
+ {
+ rv = SSL_accept(c->tls);
+ err = SSL_get_error(c->tls, rv);
+
+ if ((rv != 1) &&
+ (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE))
+ {
+ if (uh_socket_wait(fd, c->server->conf->network_timeout,
+ (err == SSL_ERROR_WANT_WRITE)))
+ {
+ D("TLS: accept(%d) = retry\n", fd);
+ continue;
+ }
+
+ D("TLS: accept(%d) = timeout\n", fd);
+ }
+ else if (rv == 1)
+ {
+ D("TLS: accept(%d) = %p\n", fd, c->tls);
+ return 1;
+ }
+
+#ifdef TLS_IS_OPENSSL
+ D("TLS: accept(%d) = failed: %s\n",
+ fd, ERR_error_string(ERR_get_error(), NULL));
+#endif
+
+ SSL_free(c->tls);
+ c->tls = NULL;
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int uh_tls_client_recv(struct client *c, char *buf, int len)
+{
+ int rv = SSL_read(c->tls, buf, len);
+ int err = SSL_get_error(c->tls, 0);
+
+ if ((rv == -1) && (err == SSL_ERROR_WANT_READ))
+ {
+ D("TLS: recv(%d, %d) = retry\n", c->fd.fd, len);
+ errno = EAGAIN;
+ return -1;
+ }
+
+ D("TLS: recv(%d, %d) = %d\n", c->fd.fd, len, rv);
+ return rv;
+}
+
+int uh_tls_client_send(struct client *c, const char *buf, int len)
+{
+ int rv = SSL_write(c->tls, buf, len);
+ int err = SSL_get_error(c->tls, 0);
+
+ if ((rv == -1) && (err == SSL_ERROR_WANT_WRITE))
+ {
+ D("TLS: send(%d, %d) = retry\n", c->fd.fd, len);
+ errno = EAGAIN;
+ return -1;
+ }
+
+ D("TLS: send(%d, %d) = %d\n", c->fd.fd, len, rv);
+ return rv;
+}
+
+void uh_tls_client_close(struct client *c)
+{
+ if (c->tls)
+ {
+ D("TLS: close(%d)\n", c->fd.fd);
+
+ SSL_shutdown(c->tls);
+ SSL_free(c->tls);
+
+ c->tls = NULL;
+ }
+}
diff --git a/package/uhttpd/src/uhttpd-tls.h b/package/uhttpd/src/uhttpd-tls.h
new file mode 100644
index 000000000..8644c2ac5
--- /dev/null
+++ b/package/uhttpd/src/uhttpd-tls.h
@@ -0,0 +1,36 @@
+/*
+ * uhttpd - Tiny single-threaded httpd - TLS header
+ *
+ * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UHTTPD_TLS_
+
+#include <openssl/ssl.h>
+#ifdef TLS_IS_OPENSSL
+#include <openssl/err.h>
+#endif
+
+SSL_CTX * uh_tls_ctx_init();
+int uh_tls_ctx_cert(SSL_CTX *c, const char *file);
+int uh_tls_ctx_key(SSL_CTX *c, const char *file);
+void uh_tls_ctx_free(struct listener *l);
+
+int uh_tls_client_accept(struct client *c);
+int uh_tls_client_recv(struct client *c, char *buf, int len);
+int uh_tls_client_send(struct client *c, const char *buf, int len);
+void uh_tls_client_close(struct client *c);
+
+#endif
diff --git a/package/uhttpd/src/uhttpd-ubus.c b/package/uhttpd/src/uhttpd-ubus.c
new file mode 100644
index 000000000..20781629b
--- /dev/null
+++ b/package/uhttpd/src/uhttpd-ubus.c
@@ -0,0 +1,957 @@
+/*
+ * uhttpd - Tiny single-threaded httpd - ubus handler
+ *
+ * Copyright (C) 2012 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "uhttpd.h"
+#include "uhttpd-utils.h"
+#include "uhttpd-ubus.h"
+
+
+enum {
+ UH_UBUS_SN_TIMEOUT,
+ __UH_UBUS_SN_MAX,
+};
+
+static const struct blobmsg_policy new_policy[__UH_UBUS_SN_MAX] = {
+ [UH_UBUS_SN_TIMEOUT] = { .name = "timeout", .type = BLOBMSG_TYPE_INT32 },
+};
+
+
+enum {
+ UH_UBUS_SI_SID,
+ __UH_UBUS_SI_MAX,
+};
+
+static const struct blobmsg_policy sid_policy[__UH_UBUS_SI_MAX] = {
+ [UH_UBUS_SI_SID] = { .name = "sid", .type = BLOBMSG_TYPE_STRING },
+};
+
+
+enum {
+ UH_UBUS_SS_SID,
+ UH_UBUS_SS_VALUES,
+ __UH_UBUS_SS_MAX,
+};
+
+static const struct blobmsg_policy set_policy[__UH_UBUS_SS_MAX] = {
+ [UH_UBUS_SS_SID] = { .name = "sid", .type = BLOBMSG_TYPE_STRING },
+ [UH_UBUS_SS_VALUES] = { .name = "values", .type = BLOBMSG_TYPE_TABLE },
+};
+
+
+enum {
+ UH_UBUS_SG_SID,
+ UH_UBUS_SG_KEYS,
+ __UH_UBUS_SG_MAX,
+};
+
+static const struct blobmsg_policy get_policy[__UH_UBUS_SG_MAX] = {
+ [UH_UBUS_SG_SID] = { .name = "sid", .type = BLOBMSG_TYPE_STRING },
+ [UH_UBUS_SG_KEYS] = { .name = "keys", .type = BLOBMSG_TYPE_ARRAY },
+};
+
+
+enum {
+ UH_UBUS_SA_SID,
+ UH_UBUS_SA_OBJECTS,
+ __UH_UBUS_SA_MAX,
+};
+
+static const struct blobmsg_policy acl_policy[__UH_UBUS_SA_MAX] = {
+ [UH_UBUS_SA_SID] = { .name = "sid", .type = BLOBMSG_TYPE_STRING },
+ [UH_UBUS_SA_OBJECTS] = { .name = "objects", .type = BLOBMSG_TYPE_ARRAY },
+};
+
+
+static bool
+uh_ubus_strmatch(const char *str, const char *pat)
+{
+ while (*pat)
+ {
+ if (*pat == '?')
+ {
+ if (!*str)
+ return false;
+
+ str++;
+ pat++;
+ }
+ else if (*pat == '*')
+ {
+ if (uh_ubus_strmatch(str, pat+1))
+ return true;
+
+ if (*str && uh_ubus_strmatch(str+1, pat))
+ return true;
+
+ return false;
+ }
+ else if (*str++ != *pat++)
+ {
+ return false;
+ }
+ }
+
+ return (!*str && !*pat);
+}
+
+static int
+uh_ubus_avlcmp(const void *k1, const void *k2, void *ptr)
+{
+ return strcmp((char *)k1, (char *)k2);
+}
+
+static void
+uh_ubus_random(char *dest)
+{
+ int i;
+ unsigned char buf[16] = { 0 };
+ FILE *f;
+
+ if ((f = fopen("/dev/urandom", "r")) != NULL)
+ {
+ fread(buf, 1, sizeof(buf), f);
+ fclose(f);
+ }
+
+ for (i = 0; i < sizeof(buf); i++)
+ sprintf(dest + (i<<1), "%02x", buf[i]);
+}
+
+static void
+uh_ubus_session_dump_data(struct uh_ubus_session *ses, struct blob_buf *b)
+{
+ struct uh_ubus_session_data *d;
+
+ avl_for_each_element(&ses->data, d, avl)
+ {
+ blobmsg_add_field(b, blobmsg_type(d->attr), blobmsg_name(d->attr),
+ blobmsg_data(d->attr), blobmsg_data_len(d->attr));
+ }
+}
+
+static void
+uh_ubus_session_dump_acls(struct uh_ubus_session *ses, struct blob_buf *b)
+{
+ struct uh_ubus_session_acl *acl;
+ const char *lastobj = NULL;
+ void *c = NULL;
+
+ avl_for_each_element(&ses->acls, acl, avl)
+ {
+ if (!lastobj || strcmp(acl->object, lastobj))
+ {
+ if (c) blobmsg_close_array(b, c);
+ c = blobmsg_open_array(b, acl->object);
+ }
+
+ blobmsg_add_string(b, NULL, acl->function);
+ lastobj = acl->object;
+ }
+
+ if (c) blobmsg_close_array(b, c);
+}
+
+static void
+uh_ubus_session_dump(struct uh_ubus_session *ses,
+ struct ubus_context *ctx,
+ struct ubus_request_data *req)
+{
+ void *c;
+ struct blob_buf b;
+
+ memset(&b, 0, sizeof(b));
+ blob_buf_init(&b, 0);
+
+ blobmsg_add_string(&b, "sid", ses->id);
+ blobmsg_add_u32(&b, "timeout", ses->timeout);
+ blobmsg_add_u32(&b, "touched", ses->touched.tv_sec);
+
+ c = blobmsg_open_table(&b, "acls");
+ uh_ubus_session_dump_acls(ses, &b);
+ blobmsg_close_table(&b, c);
+
+ c = blobmsg_open_table(&b, "data");
+ uh_ubus_session_dump_data(ses, &b);
+ blobmsg_close_table(&b, c);
+
+ ubus_send_reply(ctx, req, b.head);
+ blob_buf_free(&b);
+}
+
+static struct uh_ubus_session *
+uh_ubus_session_create(struct uh_ubus_state *state, int timeout)
+{
+ struct uh_ubus_session *ses;
+
+ ses = malloc(sizeof(*ses));
+
+ /* failed to allocate memory... */
+ if (!ses)
+ return NULL;
+
+ memset(ses, 0, sizeof(*ses));
+
+ uh_ubus_random(ses->id);
+
+ ses->timeout = timeout;
+ ses->avl.key = ses->id;
+
+ avl_insert(&state->sessions, &ses->avl);
+ avl_init(&ses->acls, uh_ubus_avlcmp, true, NULL);
+ avl_init(&ses->data, uh_ubus_avlcmp, false, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &ses->touched);
+
+ return ses;
+}
+
+
+static struct uh_ubus_session *
+uh_ubus_session_get(struct uh_ubus_state *state, const char *id)
+{
+ struct uh_ubus_session *ses;
+
+ ses = avl_find_element(&state->sessions, id, ses, avl);
+
+ if (ses)
+ clock_gettime(CLOCK_MONOTONIC, &ses->touched);
+
+ return ses;
+}
+
+static void
+uh_ubus_session_destroy(struct uh_ubus_state *state,
+ struct uh_ubus_session *ses)
+{
+ struct uh_ubus_session_acl *acl, *nacl;
+ struct uh_ubus_session_data *data, *ndata;
+
+ avl_remove_all_elements(&ses->acls, acl, avl, nacl)
+ free(acl);
+
+ avl_remove_all_elements(&ses->data, data, avl, ndata)
+ free(data);
+
+ avl_delete(&state->sessions, &ses->avl);
+ free(ses);
+}
+
+static void
+uh_ubus_session_cleanup(struct uh_ubus_state *state)
+{
+ struct timespec now;
+ struct uh_ubus_session *ses, *nses;
+
+ clock_gettime(CLOCK_MONOTONIC, &now);
+
+ avl_for_each_element_safe(&state->sessions, ses, avl, nses)
+ {
+ if ((now.tv_sec - ses->touched.tv_sec) >= ses->timeout)
+ uh_ubus_session_destroy(state, ses);
+ }
+}
+
+
+static int
+uh_ubus_handle_create(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct uh_ubus_state *state = container_of(obj, struct uh_ubus_state, ubus);
+ struct uh_ubus_session *ses;
+ struct blob_attr *tb[__UH_UBUS_SN_MAX];
+
+ int timeout = state->timeout;
+
+ blobmsg_parse(new_policy, __UH_UBUS_SN_MAX, tb, blob_data(msg), blob_len(msg));
+
+ /* TODO: make this a uloop timeout */
+ uh_ubus_session_cleanup(state);
+
+ if (tb[UH_UBUS_SN_TIMEOUT])
+ timeout = *(uint32_t *)blobmsg_data(tb[UH_UBUS_SN_TIMEOUT]);
+
+ ses = uh_ubus_session_create(state, timeout);
+
+ if (ses)
+ uh_ubus_session_dump(ses, ctx, req);
+
+ return 0;
+}
+
+static int
+uh_ubus_handle_list(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct uh_ubus_state *state = container_of(obj, struct uh_ubus_state, ubus);
+ struct uh_ubus_session *ses;
+ struct blob_attr *tb[__UH_UBUS_SI_MAX];
+
+ blobmsg_parse(sid_policy, __UH_UBUS_SI_MAX, tb, blob_data(msg), blob_len(msg));
+
+ /* TODO: make this a uloop timeout */
+ uh_ubus_session_cleanup(state);
+
+ if (!tb[UH_UBUS_SI_SID])
+ {
+ avl_for_each_element(&state->sessions, ses, avl)
+ uh_ubus_session_dump(ses, ctx, req);
+ }
+ else
+ {
+ ses = uh_ubus_session_get(state, blobmsg_data(tb[UH_UBUS_SI_SID]));
+
+ if (!ses)
+ return UBUS_STATUS_NOT_FOUND;
+
+ uh_ubus_session_dump(ses, ctx, req);
+ }
+
+ return 0;
+}
+
+
+static int
+uh_ubus_session_grant(struct uh_ubus_session *ses, struct ubus_context *ctx,
+ const char *object, const char *function)
+{
+ struct uh_ubus_session_acl *acl, *nacl;
+
+ acl = avl_find_element(&ses->acls, object, acl, avl);
+
+ if (acl)
+ {
+ avl_for_element_to_last(&ses->acls, acl, acl, avl)
+ {
+ if (!strcmp(acl->function, function))
+ return 1;
+ }
+ }
+
+ nacl = malloc(sizeof(*nacl) + strlen(object) + strlen(function) + 2);
+
+ if (nacl)
+ {
+ memset(nacl, 0, sizeof(*nacl));
+ nacl->function = nacl->object + 1;
+ nacl->function += sprintf(nacl->object, "%s", object);
+ sprintf(nacl->function, "%s", function);
+
+ nacl->avl.key = nacl->object;
+ avl_insert(&ses->acls, &nacl->avl);
+ }
+
+ return 0;
+}
+
+static int
+uh_ubus_session_revoke(struct uh_ubus_session *ses, struct ubus_context *ctx,
+ const char *object, const char *function)
+{
+ struct uh_ubus_session_acl *acl, *nacl;
+
+ if (!object && !function)
+ {
+ avl_remove_all_elements(&ses->acls, acl, avl, nacl)
+ free(acl);
+ }
+ else
+ {
+ avl_for_each_element_safe(&ses->acls, acl, avl, nacl)
+ {
+ if (uh_ubus_strmatch(acl->object, object) &&
+ uh_ubus_strmatch(acl->function, function))
+ {
+ avl_delete(&ses->acls, &acl->avl);
+ free(acl);
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+static int
+uh_ubus_handle_grant(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct uh_ubus_state *state = container_of(obj, struct uh_ubus_state, ubus);
+ struct uh_ubus_session *ses;
+ struct blob_attr *tb[__UH_UBUS_SA_MAX];
+ struct blob_attr *attr, *sattr;
+ const char *object, *function;
+ int rem1, rem2;
+
+ blobmsg_parse(acl_policy, __UH_UBUS_SA_MAX, tb, blob_data(msg), blob_len(msg));
+
+ if (!tb[UH_UBUS_SA_SID] || !tb[UH_UBUS_SA_OBJECTS])
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ ses = uh_ubus_session_get(state, blobmsg_data(tb[UH_UBUS_SA_SID]));
+
+ if (!ses)
+ return UBUS_STATUS_NOT_FOUND;
+
+ blobmsg_for_each_attr(attr, tb[UH_UBUS_SA_OBJECTS], rem1)
+ {
+ if (blob_id(attr) != BLOBMSG_TYPE_ARRAY)
+ continue;
+
+ object = NULL;
+ function = NULL;
+
+ blobmsg_for_each_attr(sattr, attr, rem2)
+ {
+ if (blob_id(sattr) != BLOBMSG_TYPE_STRING)
+ continue;
+
+ if (!object)
+ object = blobmsg_data(sattr);
+ else if (!function)
+ function = blobmsg_data(sattr);
+ else
+ break;
+ }
+
+ if (object && function)
+ uh_ubus_session_grant(ses, ctx, object, function);
+ }
+
+ return 0;
+}
+
+static int
+uh_ubus_handle_revoke(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct uh_ubus_state *state = container_of(obj, struct uh_ubus_state, ubus);
+ struct uh_ubus_session *ses;
+ struct blob_attr *tb[__UH_UBUS_SA_MAX];
+ struct blob_attr *attr, *sattr;
+ const char *object, *function;
+ int rem1, rem2;
+
+ blobmsg_parse(acl_policy, __UH_UBUS_SA_MAX, tb, blob_data(msg), blob_len(msg));
+
+ if (!tb[UH_UBUS_SA_SID])
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ ses = uh_ubus_session_get(state, blobmsg_data(tb[UH_UBUS_SA_SID]));
+
+ if (!ses)
+ return UBUS_STATUS_NOT_FOUND;
+
+ if (!tb[UH_UBUS_SA_OBJECTS])
+ {
+ uh_ubus_session_revoke(ses, ctx, NULL, NULL);
+ }
+ else
+ {
+ blobmsg_for_each_attr(attr, tb[UH_UBUS_SA_OBJECTS], rem1)
+ {
+ if (blob_id(attr) != BLOBMSG_TYPE_ARRAY)
+ continue;
+
+ object = NULL;
+ function = NULL;
+
+ blobmsg_for_each_attr(sattr, attr, rem2)
+ {
+ if (blob_id(sattr) != BLOBMSG_TYPE_STRING)
+ continue;
+
+ if (!object)
+ object = blobmsg_data(sattr);
+ else if (!function)
+ function = blobmsg_data(sattr);
+ else
+ break;
+ }
+
+ if (object && function)
+ uh_ubus_session_revoke(ses, ctx, object, function);
+ }
+ }
+
+ return 0;
+}
+
+static int
+uh_ubus_handle_set(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct uh_ubus_state *state = container_of(obj, struct uh_ubus_state, ubus);
+ struct uh_ubus_session *ses;
+ struct uh_ubus_session_data *data;
+ struct blob_attr *tb[__UH_UBUS_SA_MAX];
+ struct blob_attr *attr;
+ int rem;
+
+ blobmsg_parse(set_policy, __UH_UBUS_SS_MAX, tb, blob_data(msg), blob_len(msg));
+
+ if (!tb[UH_UBUS_SS_SID] || !tb[UH_UBUS_SS_VALUES])
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ ses = uh_ubus_session_get(state, blobmsg_data(tb[UH_UBUS_SS_SID]));
+
+ if (!ses)
+ return UBUS_STATUS_NOT_FOUND;
+
+ blobmsg_for_each_attr(attr, tb[UH_UBUS_SS_VALUES], rem)
+ {
+ if (!blobmsg_name(attr)[0])
+ continue;
+
+ data = avl_find_element(&ses->data, blobmsg_name(attr), data, avl);
+
+ if (data)
+ {
+ avl_delete(&ses->data, &data->avl);
+ free(data);
+ }
+
+ data = malloc(sizeof(*data) + blob_pad_len(attr));
+
+ if (!data)
+ break;
+
+ memset(data, 0, sizeof(*data) + blob_pad_len(attr));
+ memcpy(data->attr, attr, blob_pad_len(attr));
+
+ data->avl.key = blobmsg_name(data->attr);
+ avl_insert(&ses->data, &data->avl);
+ }
+
+ return 0;
+}
+
+static int
+uh_ubus_handle_get(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct uh_ubus_state *state = container_of(obj, struct uh_ubus_state, ubus);
+ struct uh_ubus_session *ses;
+ struct uh_ubus_session_data *data;
+ struct blob_attr *tb[__UH_UBUS_SA_MAX];
+ struct blob_attr *attr;
+ struct blob_buf b;
+ void *c;
+ int rem;
+
+ blobmsg_parse(get_policy, __UH_UBUS_SG_MAX, tb, blob_data(msg), blob_len(msg));
+
+ if (!tb[UH_UBUS_SG_SID])
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ ses = uh_ubus_session_get(state, blobmsg_data(tb[UH_UBUS_SG_SID]));
+
+ if (!ses)
+ return UBUS_STATUS_NOT_FOUND;
+
+ memset(&b, 0, sizeof(b));
+ blob_buf_init(&b, 0);
+ c = blobmsg_open_table(&b, "values");
+
+ if (!tb[UH_UBUS_SG_KEYS])
+ {
+ uh_ubus_session_dump_data(ses, &b);
+ }
+ else
+ {
+ blobmsg_for_each_attr(attr, tb[UH_UBUS_SG_KEYS], rem)
+ {
+ if (blob_id(attr) != BLOBMSG_TYPE_STRING)
+ continue;
+
+ data = avl_find_element(&ses->data, blobmsg_data(attr), data, avl);
+
+ if (!data)
+ continue;
+
+ blobmsg_add_field(&b, blobmsg_type(data->attr),
+ blobmsg_name(data->attr),
+ blobmsg_data(data->attr),
+ blobmsg_data_len(data->attr));
+ }
+ }
+
+ blobmsg_close_table(&b, c);
+ ubus_send_reply(ctx, req, b.head);
+ blob_buf_free(&b);
+
+ return 0;
+}
+
+static int
+uh_ubus_handle_unset(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct uh_ubus_state *state = container_of(obj, struct uh_ubus_state, ubus);
+ struct uh_ubus_session *ses;
+ struct uh_ubus_session_data *data, *ndata;
+ struct blob_attr *tb[__UH_UBUS_SA_MAX];
+ struct blob_attr *attr;
+ int rem;
+
+ blobmsg_parse(get_policy, __UH_UBUS_SG_MAX, tb, blob_data(msg), blob_len(msg));
+
+ if (!tb[UH_UBUS_SG_SID])
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ ses = uh_ubus_session_get(state, blobmsg_data(tb[UH_UBUS_SG_SID]));
+
+ if (!ses)
+ return UBUS_STATUS_NOT_FOUND;
+
+ if (!tb[UH_UBUS_SG_KEYS])
+ {
+ avl_remove_all_elements(&ses->data, data, avl, ndata)
+ free(data);
+ }
+ else
+ {
+ blobmsg_for_each_attr(attr, tb[UH_UBUS_SG_KEYS], rem)
+ {
+ if (blob_id(attr) != BLOBMSG_TYPE_STRING)
+ continue;
+
+ data = avl_find_element(&ses->data, blobmsg_data(attr), data, avl);
+
+ if (!data)
+ continue;
+
+ avl_delete(&ses->data, &data->avl);
+ free(data);
+ }
+ }
+
+ return 0;
+}
+
+static int
+uh_ubus_handle_destroy(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct uh_ubus_state *state = container_of(obj, struct uh_ubus_state, ubus);
+ struct uh_ubus_session *ses;
+ struct blob_attr *tb[__UH_UBUS_SA_MAX];
+
+ blobmsg_parse(sid_policy, __UH_UBUS_SI_MAX, tb, blob_data(msg), blob_len(msg));
+
+ if (!tb[UH_UBUS_SI_SID])
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ ses = uh_ubus_session_get(state, blobmsg_data(tb[UH_UBUS_SI_SID]));
+
+ if (!ses)
+ return UBUS_STATUS_NOT_FOUND;
+
+ uh_ubus_session_destroy(state, ses);
+
+ return 0;
+}
+
+
+struct uh_ubus_state *
+uh_ubus_init(const struct config *conf)
+{
+ int rv;
+ struct uh_ubus_state *state;
+ struct ubus_object *session_object;
+
+ static struct ubus_method session_methods[] = {
+ UBUS_METHOD("create", uh_ubus_handle_create, new_policy),
+ UBUS_METHOD("list", uh_ubus_handle_list, sid_policy),
+ UBUS_METHOD("grant", uh_ubus_handle_grant, acl_policy),
+ UBUS_METHOD("revoke", uh_ubus_handle_revoke, acl_policy),
+ UBUS_METHOD("set", uh_ubus_handle_set, set_policy),
+ UBUS_METHOD("get", uh_ubus_handle_get, get_policy),
+ UBUS_METHOD("unset", uh_ubus_handle_unset, get_policy),
+ UBUS_METHOD("destroy", uh_ubus_handle_destroy, sid_policy),
+ };
+
+ static struct ubus_object_type session_type =
+ UBUS_OBJECT_TYPE("uhttpd", session_methods);
+
+ state = malloc(sizeof(*state));
+
+ if (!state)
+ {
+ fprintf(stderr, "Unable to allocate memory for ubus state\n");
+ exit(1);
+ }
+
+ memset(state, 0, sizeof(*state));
+ state->ctx = ubus_connect(conf->ubus_socket);
+ state->timeout = conf->script_timeout;
+
+ if (!state->ctx)
+ {
+ fprintf(stderr, "Unable to connect to ubus socket\n");
+ exit(1);
+ }
+
+ ubus_add_uloop(state->ctx);
+
+ session_object = &state->ubus;
+ session_object->name = "session";
+ session_object->type = &session_type;
+ session_object->methods = session_methods;
+ session_object->n_methods = ARRAY_SIZE(session_methods);
+
+ rv = ubus_add_object(state->ctx, &state->ubus);
+
+ if (rv)
+ {
+ fprintf(stderr, "Unable to publish ubus object: %s\n",
+ ubus_strerror(rv));
+ exit(1);
+ }
+
+ blob_buf_init(&state->buf, 0);
+ avl_init(&state->sessions, uh_ubus_avlcmp, false, NULL);
+
+ return state;
+}
+
+
+static bool
+uh_ubus_request_parse_url(struct client *cl, char **sid, char **obj, char **fun)
+{
+ char *url = cl->request.url + strlen(cl->server->conf->ubus_prefix);
+
+ for (; url && *url == '/'; *url++ = 0);
+ *sid = url;
+
+ for (url = url ? strchr(url, '/') : NULL; url && *url == '/'; *url++ = 0);
+ *obj = url;
+
+ for (url = url ? strchr(url, '/') : NULL; url && *url == '/'; *url++ = 0);
+ *fun = url;
+
+ for (url = url ? strchr(url, '/') : NULL; url && *url == '/'; *url++ = 0);
+ return (*sid && *obj && *fun);
+}
+
+static bool
+uh_ubus_request_parse_post(struct client *cl, int len, struct blob_buf *b)
+{
+ int rlen;
+ bool rv = false;
+ char buf[UH_LIMIT_MSGHEAD];
+
+ struct json_object *obj = NULL;
+ struct json_tokener *tok = NULL;
+
+ if (!len)
+ return NULL;
+
+ memset(b, 0, sizeof(*b));
+ blob_buf_init(b, 0);
+
+ tok = json_tokener_new();
+
+ while (len > 0)
+ {
+ /* remaining data in http head buffer ... */
+ if (cl->httpbuf.len > 0)
+ {
+ rlen = min(len, cl->httpbuf.len);
+
+ D("ubus: feed %d HTTP buffer bytes\n", rlen);
+
+ memcpy(buf, cl->httpbuf.ptr, rlen);
+
+ cl->httpbuf.len -= rlen;
+ cl->httpbuf.ptr += rlen;
+ }
+
+ /* read it from socket ... */
+ else
+ {
+ ensure_out(rlen = uh_tcp_recv(cl, buf, min(len, sizeof(buf))));
+
+ if ((rlen < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
+ break;
+
+ D("ubus: feed %d/%d TCP socket bytes\n",
+ rlen, min(len, sizeof(buf)));
+ }
+
+ obj = json_tokener_parse_ex(tok, buf, rlen);
+ len -= rlen;
+
+ if (tok->err != json_tokener_continue && !is_error(obj))
+ break;
+ }
+
+out:
+ if (!is_error(obj))
+ {
+ if (json_object_get_type(obj) == json_type_object)
+ {
+ rv = true;
+ json_object_object_foreach(obj, key, val)
+ {
+ if (!blobmsg_add_json_element(b, key, val))
+ {
+ rv = false;
+ break;
+ }
+ }
+ }
+
+ json_object_put(obj);
+ }
+
+ json_tokener_free(tok);
+
+ if (!rv)
+ blob_buf_free(b);
+
+ return rv;
+}
+
+static void
+uh_ubus_request_cb(struct ubus_request *req, int type, struct blob_attr *msg)
+{
+ int len;
+ char *str;
+ struct client *cl = (struct client *)req->priv;
+
+ if (!msg)
+ {
+ uh_http_sendhf(cl, 204, "No content", "Function did not return data\n");
+ return;
+ }
+
+ str = blobmsg_format_json_indent(msg, true, 0);
+ len = strlen(str);
+
+ ensure_out(uh_http_sendf(cl, NULL, "HTTP/1.0 200 OK\r\n"));
+ ensure_out(uh_http_sendf(cl, NULL, "Content-Type: application/json\r\n"));
+ ensure_out(uh_http_sendf(cl, NULL, "Content-Length: %i\r\n\r\n", len));
+ ensure_out(uh_http_send(cl, NULL, str, len));
+
+out:
+ free(str);
+}
+
+bool
+uh_ubus_request(struct client *cl, struct uh_ubus_state *state)
+{
+ int i, len = 0;
+ bool access = false;
+ char *sid, *obj, *fun;
+
+ struct blob_buf buf;
+ struct uh_ubus_session *ses;
+ struct uh_ubus_session_acl *acl;
+
+ uint32_t obj_id;
+
+
+ memset(&buf, 0, sizeof(buf));
+ blob_buf_init(&buf, 0);
+
+ if (!uh_ubus_request_parse_url(cl, &sid, &obj, &fun))
+ {
+ uh_http_sendhf(cl, 400, "Bad Request", "Invalid Request\n");
+ goto out;
+ }
+
+ if (!(ses = uh_ubus_session_get(state, sid)))
+ {
+ uh_http_sendhf(cl, 404, "Not Found", "No such session\n");
+ goto out;
+ }
+
+ avl_for_each_element(&ses->acls, acl, avl)
+ {
+ if (uh_ubus_strmatch(obj, acl->object) &&
+ uh_ubus_strmatch(fun, acl->function))
+ {
+ access = true;
+ break;
+ }
+ }
+
+ if (!access)
+ {
+ uh_http_sendhf(cl, 403, "Denied", "Access to object denied\n");
+ goto out;
+ }
+
+ /* find content length */
+ if (cl->request.method == UH_HTTP_MSG_POST)
+ {
+ foreach_header(i, cl->request.headers)
+ {
+ if (!strcasecmp(cl->request.headers[i], "Content-Length"))
+ {
+ len = atoi(cl->request.headers[i+1]);
+ break;
+ }
+ }
+ }
+
+ if (len > UH_UBUS_MAX_POST_SIZE)
+ {
+ uh_http_sendhf(cl, 413, "Too Large", "Message too big\n");
+ goto out;
+ }
+
+ if (len && !uh_ubus_request_parse_post(cl, len, &buf))
+ {
+ uh_http_sendhf(cl, 400, "Bad Request", "Invalid JSON data\n");
+ goto out;
+ }
+
+ if (ubus_lookup_id(state->ctx, obj, &obj_id))
+ {
+ uh_http_sendhf(cl, 500, "Internal Error", "Unable to lookup object\n");
+ goto out;
+ }
+
+ if (ubus_invoke(state->ctx, obj_id, fun, buf.head,
+ uh_ubus_request_cb, cl, state->timeout * 1000))
+ {
+ uh_http_sendhf(cl, 500, "Internal Error", "Unable to invoke function\n");
+ goto out;
+ }
+
+out:
+ blob_buf_free(&buf);
+ return false;
+}
+
+void
+uh_ubus_close(struct uh_ubus_state *state)
+{
+ if (state->ctx)
+ ubus_free(state->ctx);
+
+ free(state);
+}
diff --git a/package/uhttpd/src/uhttpd-ubus.h b/package/uhttpd/src/uhttpd-ubus.h
new file mode 100644
index 000000000..777ce27fd
--- /dev/null
+++ b/package/uhttpd/src/uhttpd-ubus.h
@@ -0,0 +1,70 @@
+/*
+ * uhttpd - Tiny single-threaded httpd - ubus header
+ *
+ * Copyright (C) 2012 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UHTTPD_UBUS_
+
+#include <time.h>
+
+#include <libubus.h>
+#include <libubox/avl.h>
+#include <libubox/blobmsg_json.h>
+#include <json/json.h>
+
+
+#define UH_UBUS_MAX_POST_SIZE 4096
+
+
+struct uh_ubus_state {
+ struct ubus_context *ctx;
+ struct ubus_object ubus;
+ struct blob_buf buf;
+ struct avl_tree sessions;
+ int timeout;
+};
+
+struct uh_ubus_request_data {
+ const char *sid;
+ const char *object;
+ const char *function;
+};
+
+struct uh_ubus_session {
+ char id[33];
+ int timeout;
+ struct avl_node avl;
+ struct avl_tree data;
+ struct avl_tree acls;
+ struct timespec touched;
+};
+
+struct uh_ubus_session_data {
+ struct avl_node avl;
+ struct blob_attr attr[];
+};
+
+struct uh_ubus_session_acl {
+ struct avl_node avl;
+ char *function;
+ char object[];
+};
+
+struct uh_ubus_state * uh_ubus_init(const struct config *conf);
+bool uh_ubus_request(struct client *cl, struct uh_ubus_state *state);
+void uh_ubus_close(struct uh_ubus_state *state);
+
+#endif
diff --git a/package/uhttpd/src/uhttpd-utils.c b/package/uhttpd/src/uhttpd-utils.c
new file mode 100644
index 000000000..c8d3bb40f
--- /dev/null
+++ b/package/uhttpd/src/uhttpd-utils.c
@@ -0,0 +1,1081 @@
+/*
+ * uhttpd - Tiny single-threaded httpd - Utility functions
+ *
+ * Copyright (C) 2010-2012 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _XOPEN_SOURCE 500 /* crypt() */
+#define _BSD_SOURCE /* strcasecmp(), strncasecmp() */
+
+#include "uhttpd.h"
+#include "uhttpd-utils.h"
+
+#ifdef HAVE_TLS
+#include "uhttpd-tls.h"
+#endif
+
+
+static char *uh_index_files[] = {
+ "index.html",
+ "index.htm",
+ "default.html",
+ "default.htm"
+};
+
+
+const char * sa_straddr(void *sa)
+{
+ static char str[INET6_ADDRSTRLEN];
+ struct sockaddr_in *v4 = (struct sockaddr_in *)sa;
+ struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)sa;
+
+ if (v4->sin_family == AF_INET)
+ return inet_ntop(AF_INET, &(v4->sin_addr), str, sizeof(str));
+ else
+ return inet_ntop(AF_INET6, &(v6->sin6_addr), str, sizeof(str));
+}
+
+const char * sa_strport(void *sa)
+{
+ static char str[6];
+ snprintf(str, sizeof(str), "%i", sa_port(sa));
+ return str;
+}
+
+int sa_port(void *sa)
+{
+ return ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
+}
+
+int sa_rfc1918(void *sa)
+{
+ struct sockaddr_in *v4 = (struct sockaddr_in *)sa;
+ unsigned long a = htonl(v4->sin_addr.s_addr);
+
+ if (v4->sin_family == AF_INET)
+ {
+ return ((a >= 0x0A000000) && (a <= 0x0AFFFFFF)) ||
+ ((a >= 0xAC100000) && (a <= 0xAC1FFFFF)) ||
+ ((a >= 0xC0A80000) && (a <= 0xC0A8FFFF));
+ }
+
+ return 0;
+}
+
+/* Simple strstr() like function that takes len arguments for both haystack and needle. */
+char *strfind(char *haystack, int hslen, const char *needle, int ndlen)
+{
+ int match = 0;
+ int i, j;
+
+ for (i = 0; i < hslen; i++)
+ {
+ if (haystack[i] == needle[0])
+ {
+ match = ((ndlen == 1) || ((i + ndlen) <= hslen));
+
+ for (j = 1; (j < ndlen) && ((i + j) < hslen); j++)
+ {
+ if (haystack[i+j] != needle[j])
+ {
+ match = 0;
+ break;
+ }
+ }
+
+ if (match)
+ return &haystack[i];
+ }
+ }
+
+ return NULL;
+}
+
+bool uh_socket_wait(int fd, int sec, bool write)
+{
+ int rv;
+ struct timeval timeout;
+
+ fd_set fds;
+
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+
+ timeout.tv_sec = sec;
+ timeout.tv_usec = 0;
+
+ while (((rv = select(fd+1, write ? NULL : &fds, write ? &fds : NULL,
+ NULL, &timeout)) < 0) && (errno == EINTR))
+ {
+ D("IO: FD(%d) select interrupted: %s\n",
+ fd, strerror(errno));
+
+ continue;
+ }
+
+ if (rv <= 0)
+ {
+ D("IO: FD(%d) appears dead (rv=%d)\n", fd, rv);
+ return false;
+ }
+
+ return true;
+}
+
+static int __uh_raw_send(struct client *cl, const char *buf, int len, int sec,
+ int (*wfn) (struct client *, const char *, int))
+{
+ ssize_t rv;
+ int fd = cl->fd.fd;
+
+ while (true)
+ {
+ if ((rv = wfn(cl, buf, len)) < 0)
+ {
+ if (errno == EINTR)
+ {
+ D("IO: FD(%d) interrupted\n", cl->fd.fd);
+ continue;
+ }
+ else if ((sec > 0) && (errno == EAGAIN || errno == EWOULDBLOCK))
+ {
+ if (!uh_socket_wait(fd, sec, true))
+ return -1;
+ }
+ else
+ {
+ D("IO: FD(%d) write error: %s\n", fd, strerror(errno));
+ return -1;
+ }
+ }
+ /*
+ * It is not entirely clear whether rv = 0 on nonblocking sockets
+ * is an error. In real world fuzzing tests, not handling it as close
+ * led to tight infinite loops in this send procedure, so treat it as
+ * closed and break out.
+ */
+ else if (rv == 0)
+ {
+ D("IO: FD(%d) appears closed\n", fd);
+ return 0;
+ }
+ else if (rv < len)
+ {
+ D("IO: FD(%d) short write %d/%d bytes\n", fd, rv, len);
+ len -= rv;
+ buf += rv;
+ continue;
+ }
+ else
+ {
+ D("IO: FD(%d) sent %d/%d bytes\n", fd, rv, len);
+ return rv;
+ }
+ }
+}
+
+int uh_tcp_send_lowlevel(struct client *cl, const char *buf, int len)
+{
+ return write(cl->fd.fd, buf, len);
+}
+
+int uh_raw_send(int fd, const char *buf, int len, int sec)
+{
+ struct client_light cl = { .fd = { .fd = fd } };
+ return __uh_raw_send((struct client *)&cl, buf, len, sec,
+ uh_tcp_send_lowlevel);
+}
+
+int uh_tcp_send(struct client *cl, const char *buf, int len)
+{
+ int seconds = cl->server->conf->network_timeout;
+#ifdef HAVE_TLS
+ if (cl->tls)
+ return __uh_raw_send(cl, buf, len, seconds,
+ cl->server->conf->tls_send);
+#endif
+ return __uh_raw_send(cl, buf, len, seconds, uh_tcp_send_lowlevel);
+}
+
+static int __uh_raw_recv(struct client *cl, char *buf, int len, int sec,
+ int (*rfn) (struct client *, char *, int))
+{
+ ssize_t rv;
+ int fd = cl->fd.fd;
+
+ while (true)
+ {
+ if ((rv = rfn(cl, buf, len)) < 0)
+ {
+ if (errno == EINTR)
+ {
+ continue;
+ }
+ else if ((sec > 0) && (errno == EAGAIN || errno == EWOULDBLOCK))
+ {
+ if (!uh_socket_wait(fd, sec, false))
+ return -1;
+ }
+ else
+ {
+ D("IO: FD(%d) read error: %s\n", fd, strerror(errno));
+ return -1;
+ }
+ }
+ else if (rv == 0)
+ {
+ D("IO: FD(%d) appears closed\n", fd);
+ return 0;
+ }
+ else
+ {
+ D("IO: FD(%d) read %d bytes\n", fd, rv);
+ return rv;
+ }
+ }
+}
+
+int uh_tcp_recv_lowlevel(struct client *cl, char *buf, int len)
+{
+ return read(cl->fd.fd, buf, len);
+}
+
+int uh_raw_recv(int fd, char *buf, int len, int sec)
+{
+ struct client_light cl = { .fd = { .fd = fd } };
+ return __uh_raw_recv((struct client *)&cl, buf, len, sec,
+ uh_tcp_recv_lowlevel);
+}
+
+int uh_tcp_recv(struct client *cl, char *buf, int len)
+{
+ int seconds = cl->server->conf->network_timeout;
+#ifdef HAVE_TLS
+ if (cl->tls)
+ return __uh_raw_recv(cl, buf, len, seconds,
+ cl->server->conf->tls_recv);
+#endif
+ return __uh_raw_recv(cl, buf, len, seconds, uh_tcp_recv_lowlevel);
+}
+
+
+int uh_http_sendhf(struct client *cl, int code, const char *summary,
+ const char *fmt, ...)
+{
+ va_list ap;
+
+ char buffer[UH_LIMIT_MSGHEAD];
+ int len;
+
+ len = snprintf(buffer, sizeof(buffer),
+ "HTTP/1.1 %03i %s\r\n"
+ "Connection: close\r\n"
+ "Content-Type: text/plain\r\n"
+ "Transfer-Encoding: chunked\r\n\r\n",
+ code, summary
+ );
+
+ ensure_ret(uh_tcp_send(cl, buffer, len));
+
+ va_start(ap, fmt);
+ len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
+ va_end(ap);
+
+ ensure_ret(uh_http_sendc(cl, buffer, len));
+ ensure_ret(uh_http_sendc(cl, NULL, 0));
+
+ return 0;
+}
+
+
+int uh_http_sendc(struct client *cl, const char *data, int len)
+{
+ char chunk[8];
+ int clen;
+
+ if (len == -1)
+ len = strlen(data);
+
+ if (len > 0)
+ {
+ clen = snprintf(chunk, sizeof(chunk), "%X\r\n", len);
+ ensure_ret(uh_tcp_send(cl, chunk, clen));
+ ensure_ret(uh_tcp_send(cl, data, len));
+ ensure_ret(uh_tcp_send(cl, "\r\n", 2));
+ }
+ else
+ {
+ ensure_ret(uh_tcp_send(cl, "0\r\n\r\n", 5));
+ }
+
+ return 0;
+}
+
+int uh_http_sendf(struct client *cl, struct http_request *req,
+ const char *fmt, ...)
+{
+ va_list ap;
+ char buffer[UH_LIMIT_MSGHEAD];
+ int len;
+
+ va_start(ap, fmt);
+ len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
+ va_end(ap);
+
+ if ((req != NULL) && (req->version > UH_HTTP_VER_1_0))
+ ensure_ret(uh_http_sendc(cl, buffer, len));
+ else if (len > 0)
+ ensure_ret(uh_tcp_send(cl, buffer, len));
+
+ return 0;
+}
+
+int uh_http_send(struct client *cl, struct http_request *req,
+ const char *buf, int len)
+{
+ if (len < 0)
+ len = strlen(buf);
+
+ if ((req != NULL) && (req->version > UH_HTTP_VER_1_0))
+ ensure_ret(uh_http_sendc(cl, buf, len));
+ else if (len > 0)
+ ensure_ret(uh_tcp_send(cl, buf, len));
+
+ return 0;
+}
+
+
+/* blen is the size of buf; slen is the length of src. The input-string need
+** not be, and the output string will not be, null-terminated. Returns the
+** length of the decoded string, -1 on buffer overflow, -2 on malformed string. */
+int uh_urldecode(char *buf, int blen, const char *src, int slen)
+{
+ int i;
+ int len = 0;
+
+#define hex(x) \
+ (((x) <= '9') ? ((x) - '0') : \
+ (((x) <= 'F') ? ((x) - 'A' + 10) : \
+ ((x) - 'a' + 10)))
+
+ for (i = 0; (i < slen) && (len < blen); i++)
+ {
+ if (src[i] == '%')
+ {
+ if (((i+2) < slen) && isxdigit(src[i+1]) && isxdigit(src[i+2]))
+ {
+ buf[len++] = (char)(16 * hex(src[i+1]) + hex(src[i+2]));
+ i += 2;
+ }
+ else
+ {
+ /* Encoding error: it's hard to think of a
+ ** scenario in which returning an incorrect
+ ** 'decoding' of the malformed string is
+ ** preferable to signaling an error condition. */
+ #if 0 /* WORSE_IS_BETTER */
+ buf[len++] = '%';
+ #else
+ return -2;
+ #endif
+ }
+ }
+ else
+ {
+ buf[len++] = src[i];
+ }
+ }
+
+ return (i == slen) ? len : -1;
+}
+
+/* blen is the size of buf; slen is the length of src. The input-string need
+** not be, and the output string will not be, null-terminated. Returns the
+** length of the encoded string, or -1 on error (buffer overflow) */
+int uh_urlencode(char *buf, int blen, const char *src, int slen)
+{
+ int i;
+ int len = 0;
+ const char hex[] = "0123456789abcdef";
+
+ for (i = 0; (i < slen) && (len < blen); i++)
+ {
+ if( isalnum(src[i]) || (src[i] == '-') || (src[i] == '_') ||
+ (src[i] == '.') || (src[i] == '~') )
+ {
+ buf[len++] = src[i];
+ }
+ else if ((len+3) <= blen)
+ {
+ buf[len++] = '%';
+ buf[len++] = hex[(src[i] >> 4) & 15];
+ buf[len++] = hex[ src[i] & 15];
+ }
+ else
+ {
+ len = -1;
+ break;
+ }
+ }
+
+ return (i == slen) ? len : -1;
+}
+
+int uh_b64decode(char *buf, int blen, const unsigned char *src, int slen)
+{
+ int i = 0;
+ int len = 0;
+
+ unsigned int cin = 0;
+ unsigned int cout = 0;
+
+
+ for (i = 0; (i <= slen) && (src[i] != 0); i++)
+ {
+ cin = src[i];
+
+ if ((cin >= '0') && (cin <= '9'))
+ cin = cin - '0' + 52;
+ else if ((cin >= 'A') && (cin <= 'Z'))
+ cin = cin - 'A';
+ else if ((cin >= 'a') && (cin <= 'z'))
+ cin = cin - 'a' + 26;
+ else if (cin == '+')
+ cin = 62;
+ else if (cin == '/')
+ cin = 63;
+ else if (cin == '=')
+ cin = 0;
+ else
+ continue;
+
+ cout = (cout << 6) | cin;
+
+ if ((i % 4) == 3)
+ {
+ if ((len + 3) < blen)
+ {
+ buf[len++] = (char)(cout >> 16);
+ buf[len++] = (char)(cout >> 8);
+ buf[len++] = (char)(cout);
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ buf[len++] = 0;
+ return len;
+}
+
+static char * canonpath(const char *path, char *path_resolved)
+{
+ char path_copy[PATH_MAX];
+ char *path_cpy = path_copy;
+ char *path_res = path_resolved;
+
+ struct stat s;
+
+
+ /* relative -> absolute */
+ if (*path != '/')
+ {
+ getcwd(path_copy, PATH_MAX);
+ strncat(path_copy, "/", PATH_MAX - strlen(path_copy));
+ strncat(path_copy, path, PATH_MAX - strlen(path_copy));
+ }
+ else
+ {
+ strncpy(path_copy, path, PATH_MAX);
+ }
+
+ /* normalize */
+ while ((*path_cpy != '\0') && (path_cpy < (path_copy + PATH_MAX - 2)))
+ {
+ if (*path_cpy == '/')
+ {
+ /* skip repeating / */
+ if (path_cpy[1] == '/')
+ {
+ path_cpy++;
+ continue;
+ }
+
+ /* /./ or /../ */
+ else if (path_cpy[1] == '.')
+ {
+ /* skip /./ */
+ if ((path_cpy[2] == '/') || (path_cpy[2] == '\0'))
+ {
+ path_cpy += 2;
+ continue;
+ }
+
+ /* collapse /x/../ */
+ else if ((path_cpy[2] == '.') &&
+ ((path_cpy[3] == '/') || (path_cpy[3] == '\0')))
+ {
+ while ((path_res > path_resolved) && (*--path_res != '/'))
+ ;
+
+ path_cpy += 3;
+ continue;
+ }
+ }
+ }
+
+ *path_res++ = *path_cpy++;
+ }
+
+ /* remove trailing slash if not root / */
+ if ((path_res > (path_resolved+1)) && (path_res[-1] == '/'))
+ path_res--;
+ else if (path_res == path_resolved)
+ *path_res++ = '/';
+
+ *path_res = '\0';
+
+ /* test access */
+ if (!stat(path_resolved, &s) && (s.st_mode & S_IROTH))
+ return path_resolved;
+
+ return NULL;
+}
+
+/* Returns NULL on error.
+** NB: improperly encoded URL should give client 400 [Bad Syntax]; returning
+** NULL here causes 404 [Not Found], but that's not too unreasonable. */
+struct path_info * uh_path_lookup(struct client *cl, const char *url)
+{
+ static char path_phys[PATH_MAX];
+ static char path_info[PATH_MAX];
+ static struct path_info p;
+
+ char buffer[UH_LIMIT_MSGHEAD];
+ char *docroot = cl->server->conf->docroot;
+ char *pathptr = NULL;
+
+ int slash = 0;
+ int no_sym = cl->server->conf->no_symlinks;
+ int i = 0;
+ struct stat s;
+
+ /* back out early if url is undefined */
+ if (url == NULL)
+ return NULL;
+
+ memset(path_phys, 0, sizeof(path_phys));
+ memset(path_info, 0, sizeof(path_info));
+ memset(buffer, 0, sizeof(buffer));
+ memset(&p, 0, sizeof(p));
+
+ /* copy docroot */
+ memcpy(buffer, docroot,
+ min(strlen(docroot), sizeof(buffer) - 1));
+
+ /* separate query string from url */
+ if ((pathptr = strchr(url, '?')) != NULL)
+ {
+ p.query = pathptr[1] ? pathptr + 1 : NULL;
+
+ /* urldecode component w/o query */
+ if (pathptr > url)
+ {
+ if (uh_urldecode(&buffer[strlen(docroot)],
+ sizeof(buffer) - strlen(docroot) - 1,
+ url, pathptr - url ) < 0)
+ {
+ return NULL; /* bad URL */
+ }
+ }
+ }
+
+ /* no query string, decode all of url */
+ else
+ {
+ if (uh_urldecode(&buffer[strlen(docroot)],
+ sizeof(buffer) - strlen(docroot) - 1,
+ url, strlen(url) ) < 0)
+ {
+ return NULL; /* bad URL */
+ }
+ }
+
+ /* create canon path */
+ for (i = strlen(buffer), slash = (buffer[max(0, i-1)] == '/'); i >= 0; i--)
+ {
+ if ((buffer[i] == 0) || (buffer[i] == '/'))
+ {
+ memset(path_info, 0, sizeof(path_info));
+ memcpy(path_info, buffer, min(i + 1, sizeof(path_info) - 1));
+
+ if (no_sym ? realpath(path_info, path_phys)
+ : canonpath(path_info, path_phys))
+ {
+ memset(path_info, 0, sizeof(path_info));
+ memcpy(path_info, &buffer[i],
+ min(strlen(buffer) - i, sizeof(path_info) - 1));
+
+ break;
+ }
+ }
+ }
+
+ /* check whether found path is within docroot */
+ if (strncmp(path_phys, docroot, strlen(docroot)) ||
+ ((path_phys[strlen(docroot)] != 0) &&
+ (path_phys[strlen(docroot)] != '/')))
+ {
+ return NULL;
+ }
+
+ /* test current path */
+ if (!stat(path_phys, &p.stat))
+ {
+ /* is a regular file */
+ if (p.stat.st_mode & S_IFREG)
+ {
+ p.root = docroot;
+ p.phys = path_phys;
+ p.name = &path_phys[strlen(docroot)];
+ p.info = path_info[0] ? path_info : NULL;
+ }
+
+ /* is a directory */
+ else if ((p.stat.st_mode & S_IFDIR) && !strlen(path_info))
+ {
+ /* ensure trailing slash */
+ if (path_phys[strlen(path_phys)-1] != '/')
+ path_phys[strlen(path_phys)] = '/';
+
+ /* try to locate index file */
+ memset(buffer, 0, sizeof(buffer));
+ memcpy(buffer, path_phys, sizeof(buffer));
+ pathptr = &buffer[strlen(buffer)];
+
+ /* if requested url resolves to a directory and a trailing slash
+ is missing in the request url, redirect the client to the same
+ url with trailing slash appended */
+ if (!slash)
+ {
+ uh_http_sendf(cl, NULL,
+ "HTTP/1.1 302 Found\r\n"
+ "Location: %s%s%s\r\n"
+ "Connection: close\r\n\r\n",
+ &path_phys[strlen(docroot)],
+ p.query ? "?" : "",
+ p.query ? p.query : ""
+ );
+
+ p.redirected = 1;
+ }
+ else if (cl->server->conf->index_file)
+ {
+ strncat(buffer, cl->server->conf->index_file, sizeof(buffer));
+
+ if (!stat(buffer, &s) && (s.st_mode & S_IFREG))
+ {
+ memcpy(path_phys, buffer, sizeof(path_phys));
+ memcpy(&p.stat, &s, sizeof(p.stat));
+ }
+ }
+ else
+ {
+ for (i = 0; i < array_size(uh_index_files); i++)
+ {
+ strncat(buffer, uh_index_files[i], sizeof(buffer));
+
+ if (!stat(buffer, &s) && (s.st_mode & S_IFREG))
+ {
+ memcpy(path_phys, buffer, sizeof(path_phys));
+ memcpy(&p.stat, &s, sizeof(p.stat));
+ break;
+ }
+
+ *pathptr = 0;
+ }
+ }
+
+ p.root = docroot;
+ p.phys = path_phys;
+ p.name = &path_phys[strlen(docroot)];
+ }
+ }
+
+ return p.phys ? &p : NULL;
+}
+
+
+static struct auth_realm *uh_realms = NULL;
+
+struct auth_realm * uh_auth_add(char *path, char *user, char *pass)
+{
+ struct auth_realm *new = NULL;
+ struct passwd *pwd;
+
+#ifdef HAVE_SHADOW
+ struct spwd *spwd;
+#endif
+
+ if((new = (struct auth_realm *)malloc(sizeof(struct auth_realm))) != NULL)
+ {
+ memset(new, 0, sizeof(struct auth_realm));
+
+ memcpy(new->path, path,
+ min(strlen(path), sizeof(new->path) - 1));
+
+ memcpy(new->user, user,
+ min(strlen(user), sizeof(new->user) - 1));
+
+ /* given password refers to a passwd entry */
+ if ((strlen(pass) > 3) && !strncmp(pass, "$p$", 3))
+ {
+#ifdef HAVE_SHADOW
+ /* try to resolve shadow entry */
+ if (((spwd = getspnam(&pass[3])) != NULL) && spwd->sp_pwdp)
+ {
+ memcpy(new->pass, spwd->sp_pwdp,
+ min(strlen(spwd->sp_pwdp), sizeof(new->pass) - 1));
+ }
+
+ else
+#endif
+
+ /* try to resolve passwd entry */
+ if (((pwd = getpwnam(&pass[3])) != NULL) && pwd->pw_passwd &&
+ (pwd->pw_passwd[0] != '!') && (pwd->pw_passwd[0] != 0))
+ {
+ memcpy(new->pass, pwd->pw_passwd,
+ min(strlen(pwd->pw_passwd), sizeof(new->pass) - 1));
+ }
+ }
+
+ /* ordinary pwd */
+ else
+ {
+ memcpy(new->pass, pass,
+ min(strlen(pass), sizeof(new->pass) - 1));
+ }
+
+ if (new->pass[0])
+ {
+ new->next = uh_realms;
+ uh_realms = new;
+
+ return new;
+ }
+
+ free(new);
+ }
+
+ return NULL;
+}
+
+int uh_auth_check(struct client *cl, struct http_request *req,
+ struct path_info *pi)
+{
+ int i, plen, rlen, protected;
+ char buffer[UH_LIMIT_MSGHEAD];
+ char *user = NULL;
+ char *pass = NULL;
+
+ struct auth_realm *realm = NULL;
+
+ plen = strlen(pi->name);
+ protected = 0;
+
+ /* check whether at least one realm covers the requested url */
+ for (realm = uh_realms; realm; realm = realm->next)
+ {
+ rlen = strlen(realm->path);
+
+ if ((plen >= rlen) && !strncasecmp(pi->name, realm->path, rlen))
+ {
+ req->realm = realm;
+ protected = 1;
+ break;
+ }
+ }
+
+ /* requested resource is covered by a realm */
+ if (protected)
+ {
+ /* try to get client auth info */
+ foreach_header(i, req->headers)
+ {
+ if (!strcasecmp(req->headers[i], "Authorization") &&
+ (strlen(req->headers[i+1]) > 6) &&
+ !strncasecmp(req->headers[i+1], "Basic ", 6))
+ {
+ memset(buffer, 0, sizeof(buffer));
+ uh_b64decode(buffer, sizeof(buffer) - 1,
+ (unsigned char *) &req->headers[i+1][6],
+ strlen(req->headers[i+1]) - 6);
+
+ if ((pass = strchr(buffer, ':')) != NULL)
+ {
+ user = buffer;
+ *pass++ = 0;
+ }
+
+ break;
+ }
+ }
+
+ /* have client auth */
+ if (user && pass)
+ {
+ /* find matching realm */
+ for (realm = uh_realms; realm; realm = realm->next)
+ {
+ rlen = strlen(realm->path);
+
+ if ((plen >= rlen) &&
+ !strncasecmp(pi->name, realm->path, rlen) &&
+ !strcmp(user, realm->user))
+ {
+ req->realm = realm;
+ break;
+ }
+ }
+
+ /* found a realm matching the username */
+ if (realm)
+ {
+ /* check user pass */
+ if (!strcmp(pass, realm->pass) ||
+ !strcmp(crypt(pass, realm->pass), realm->pass))
+ return 1;
+ }
+ }
+
+ /* 401 */
+ uh_http_sendf(cl, NULL,
+ "%s 401 Authorization Required\r\n"
+ "WWW-Authenticate: Basic realm=\"%s\"\r\n"
+ "Content-Type: text/plain\r\n"
+ "Content-Length: 23\r\n\r\n"
+ "Authorization Required\n",
+ http_versions[req->version],
+ cl->server->conf->realm);
+
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static struct listener *uh_listeners = NULL;
+static struct client *uh_clients = NULL;
+
+struct listener * uh_listener_add(int sock, struct config *conf)
+{
+ struct listener *new = NULL;
+ socklen_t sl;
+
+ if ((new = (struct listener *)malloc(sizeof(struct listener))) != NULL)
+ {
+ memset(new, 0, sizeof(struct listener));
+
+ new->fd.fd = sock;
+ new->conf = conf;
+
+
+ /* get local endpoint addr */
+ sl = sizeof(struct sockaddr_in6);
+ memset(&(new->addr), 0, sl);
+ getsockname(sock, (struct sockaddr *) &(new->addr), &sl);
+
+ new->next = uh_listeners;
+ uh_listeners = new;
+
+ return new;
+ }
+
+ return NULL;
+}
+
+struct listener * uh_listener_lookup(int sock)
+{
+ struct listener *cur = NULL;
+
+ for (cur = uh_listeners; cur; cur = cur->next)
+ if (cur->fd.fd == sock)
+ return cur;
+
+ return NULL;
+}
+
+
+struct client * uh_client_add(int sock, struct listener *serv,
+ struct sockaddr_in6 *peer)
+{
+ struct client *new = NULL;
+ socklen_t sl;
+
+ if ((new = (struct client *)malloc(sizeof(struct client))) != NULL)
+ {
+ memset(new, 0, sizeof(struct client));
+ memcpy(&new->peeraddr, peer, sizeof(new->peeraddr));
+
+ new->fd.fd = sock;
+ new->server = serv;
+
+ new->rpipe.fd = -1;
+ new->wpipe.fd = -1;
+
+ /* get local endpoint addr */
+ sl = sizeof(struct sockaddr_in6);
+ getsockname(sock, (struct sockaddr *) &(new->servaddr), &sl);
+
+ new->next = uh_clients;
+ uh_clients = new;
+
+ serv->n_clients++;
+
+ D("IO: Client(%d) allocated\n", new->fd.fd);
+ }
+
+ return new;
+}
+
+struct client * uh_client_lookup(int sock)
+{
+ struct client *cur = NULL;
+
+ for (cur = uh_clients; cur; cur = cur->next)
+ if (cur->fd.fd == sock)
+ return cur;
+
+ return NULL;
+}
+
+void uh_client_shutdown(struct client *cl)
+{
+#ifdef HAVE_TLS
+ /* free client tls context */
+ if (cl->server && cl->server->conf->tls)
+ cl->server->conf->tls_close(cl);
+#endif
+
+ /* remove from global client list */
+ uh_client_remove(cl);
+}
+
+void uh_client_remove(struct client *cl)
+{
+ struct client *cur = NULL;
+ struct client *prv = NULL;
+
+ for (cur = uh_clients; cur; prv = cur, cur = cur->next)
+ {
+ if (cur == cl)
+ {
+ if (prv)
+ prv->next = cur->next;
+ else
+ uh_clients = cur->next;
+
+ if (cur->timeout.pending)
+ uloop_timeout_cancel(&cur->timeout);
+
+ if (cur->proc.pid)
+ uloop_process_delete(&cur->proc);
+
+ D("IO: Client(%d) freeing\n", cur->fd.fd);
+
+ uh_ufd_remove(&cur->rpipe);
+ uh_ufd_remove(&cur->wpipe);
+ uh_ufd_remove(&cur->fd);
+
+ cur->server->n_clients--;
+
+ free(cur);
+ break;
+ }
+ }
+}
+
+
+void uh_ufd_add(struct uloop_fd *u, uloop_fd_handler h, unsigned int ev)
+{
+ if (h != NULL)
+ {
+ u->cb = h;
+ uloop_fd_add(u, ev);
+ D("IO: FD(%d) added to uloop\n", u->fd);
+ }
+}
+
+void uh_ufd_remove(struct uloop_fd *u)
+{
+ if (u->cb != NULL)
+ {
+ uloop_fd_delete(u);
+ D("IO: FD(%d) removed from uloop\n", u->fd);
+ u->cb = NULL;
+ }
+
+ if (u->fd > -1)
+ {
+ close(u->fd);
+ D("IO: FD(%d) closed\n", u->fd);
+ u->fd = -1;
+ }
+}
+
+
+#ifdef HAVE_CGI
+static struct interpreter *uh_interpreters = NULL;
+
+struct interpreter * uh_interpreter_add(const char *extn, const char *path)
+{
+ struct interpreter *new = NULL;
+
+ if ((new = (struct interpreter *)malloc(sizeof(struct interpreter))) != NULL)
+ {
+ memset(new, 0, sizeof(struct interpreter));
+
+ memcpy(new->extn, extn, min(strlen(extn), sizeof(new->extn)-1));
+ memcpy(new->path, path, min(strlen(path), sizeof(new->path)-1));
+
+ new->next = uh_interpreters;
+ uh_interpreters = new;
+
+ return new;
+ }
+
+ return NULL;
+}
+
+struct interpreter * uh_interpreter_lookup(const char *path)
+{
+ struct interpreter *cur = NULL;
+ const char *e;
+
+ for (cur = uh_interpreters; cur; cur = cur->next)
+ {
+ e = &path[max(strlen(path) - strlen(cur->extn), 0)];
+
+ if (!strcmp(e, cur->extn))
+ return cur;
+ }
+
+ return NULL;
+}
+#endif
diff --git a/package/uhttpd/src/uhttpd-utils.h b/package/uhttpd/src/uhttpd-utils.h
new file mode 100644
index 000000000..9de919194
--- /dev/null
+++ b/package/uhttpd/src/uhttpd-utils.h
@@ -0,0 +1,140 @@
+/*
+ * uhttpd - Tiny single-threaded httpd - Utility header
+ *
+ * Copyright (C) 2010-2012 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UHTTPD_UTILS_
+
+#include <stdarg.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <sys/stat.h>
+
+#include <libubox/uloop.h>
+
+
+#ifdef HAVE_SHADOW
+#include <shadow.h>
+#endif
+
+#define min(x, y) (((x) < (y)) ? (x) : (y))
+#define max(x, y) (((x) > (y)) ? (x) : (y))
+
+#define array_size(x) \
+ (sizeof(x) / sizeof(x[0]))
+
+#define foreach_header(i, h) \
+ for( i = 0; (i + 1) < (sizeof(h) / sizeof(h[0])) && h[i]; i += 2 )
+
+#define fd_cloexec(fd) \
+ fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC)
+
+#define fd_nonblock(fd) \
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK)
+
+#define ensure_out(x) \
+ do { if((x) < 0) goto out; } while(0)
+
+#define ensure_ret(x) \
+ do { if((x) < 0) return -1; } while(0)
+
+
+struct path_info {
+ char *root;
+ char *phys;
+ char *name;
+ char *info;
+ char *query;
+ int redirected;
+ struct stat stat;
+};
+
+
+const char * sa_straddr(void *sa);
+const char * sa_strport(void *sa);
+int sa_port(void *sa);
+int sa_rfc1918(void *sa);
+
+char *strfind(char *haystack, int hslen, const char *needle, int ndlen);
+
+bool uh_socket_wait(int fd, int sec, bool write);
+
+int uh_raw_send(int fd, const char *buf, int len, int seconds);
+int uh_raw_recv(int fd, char *buf, int len, int seconds);
+int uh_tcp_send(struct client *cl, const char *buf, int len);
+int uh_tcp_send_lowlevel(struct client *cl, const char *buf, int len);
+int uh_tcp_recv(struct client *cl, char *buf, int len);
+int uh_tcp_recv_lowlevel(struct client *cl, char *buf, int len);
+
+int uh_http_sendhf(struct client *cl, int code, const char *summary,
+ const char *fmt, ...);
+
+#define uh_http_response(cl, code, message) \
+ uh_http_sendhf(cl, code, message, message)
+
+int uh_http_sendc(struct client *cl, const char *data, int len);
+
+int uh_http_sendf(
+ struct client *cl, struct http_request *req,
+ const char *fmt, ...
+);
+
+int uh_http_send(
+ struct client *cl, struct http_request *req,
+ const char *buf, int len
+);
+
+
+int uh_urldecode(char *buf, int blen, const char *src, int slen);
+int uh_urlencode(char *buf, int blen, const char *src, int slen);
+int uh_b64decode(char *buf, int blen, const unsigned char *src, int slen);
+
+
+struct auth_realm * uh_auth_add(char *path, char *user, char *pass);
+
+int uh_auth_check(
+ struct client *cl, struct http_request *req, struct path_info *pi
+);
+
+
+struct path_info * uh_path_lookup(struct client *cl, const char *url);
+
+struct listener * uh_listener_add(int sock, struct config *conf);
+struct listener * uh_listener_lookup(int sock);
+
+struct client * uh_client_add(int sock, struct listener *serv,
+ struct sockaddr_in6 *peer);
+
+struct client * uh_client_lookup(int sock);
+
+#define uh_client_error(cl, code, status, ...) do { \
+ uh_http_sendhf(cl, code, status, __VA_ARGS__); \
+ uh_client_shutdown(cl); \
+} while(0)
+
+void uh_client_shutdown(struct client *cl);
+void uh_client_remove(struct client *cl);
+
+void uh_ufd_add(struct uloop_fd *u, uloop_fd_handler h, unsigned int ev);
+void uh_ufd_remove(struct uloop_fd *u);
+
+
+#ifdef HAVE_CGI
+struct interpreter * uh_interpreter_add(const char *extn, const char *path);
+struct interpreter * uh_interpreter_lookup(const char *path);
+#endif
+
+#endif
diff --git a/package/uhttpd/src/uhttpd.c b/package/uhttpd/src/uhttpd.c
new file mode 100644
index 000000000..1efcbf0f5
--- /dev/null
+++ b/package/uhttpd/src/uhttpd.c
@@ -0,0 +1,1288 @@
+/*
+ * uhttpd - Tiny single-threaded httpd - Main component
+ *
+ * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _XOPEN_SOURCE 500 /* crypt() */
+
+#include "uhttpd.h"
+#include "uhttpd-utils.h"
+#include "uhttpd-file.h"
+
+#ifdef HAVE_CGI
+#include "uhttpd-cgi.h"
+#endif
+
+#ifdef HAVE_LUA
+#include "uhttpd-lua.h"
+#endif
+
+#ifdef HAVE_TLS
+#include "uhttpd-tls.h"
+#endif
+
+
+const char * http_methods[] = { "GET", "POST", "HEAD", };
+const char * http_versions[] = { "HTTP/0.9", "HTTP/1.0", "HTTP/1.1", };
+
+static int run = 1;
+
+static void uh_sigterm(int sig)
+{
+ run = 0;
+}
+
+static void uh_config_parse(struct config *conf)
+{
+ FILE *c;
+ char line[512];
+ char *col1 = NULL;
+ char *col2 = NULL;
+ char *eol = NULL;
+
+ const char *path = conf->file ? conf->file : "/etc/httpd.conf";
+
+
+ if ((c = fopen(path, "r")) != NULL)
+ {
+ memset(line, 0, sizeof(line));
+
+ while (fgets(line, sizeof(line) - 1, c))
+ {
+ if ((line[0] == '/') && (strchr(line, ':') != NULL))
+ {
+ if (!(col1 = strchr(line, ':')) || (*col1++ = 0) ||
+ !(col2 = strchr(col1, ':')) || (*col2++ = 0) ||
+ !(eol = strchr(col2, '\n')) || (*eol++ = 0))
+ {
+ continue;
+ }
+
+ if (!uh_auth_add(line, col1, col2))
+ {
+ fprintf(stderr,
+ "Notice: No password set for user %s, ignoring "
+ "authentication on %s\n", col1, line
+ );
+ }
+ }
+ else if (!strncmp(line, "I:", 2))
+ {
+ if (!(col1 = strchr(line, ':')) || (*col1++ = 0) ||
+ !(eol = strchr(col1, '\n')) || (*eol++ = 0))
+ {
+ continue;
+ }
+
+ conf->index_file = strdup(col1);
+ }
+ else if (!strncmp(line, "E404:", 5))
+ {
+ if (!(col1 = strchr(line, ':')) || (*col1++ = 0) ||
+ !(eol = strchr(col1, '\n')) || (*eol++ = 0))
+ {
+ continue;
+ }
+
+ conf->error_handler = strdup(col1);
+ }
+#ifdef HAVE_CGI
+ else if ((line[0] == '*') && (strchr(line, ':') != NULL))
+ {
+ if (!(col1 = strchr(line, '*')) || (*col1++ = 0) ||
+ !(col2 = strchr(col1, ':')) || (*col2++ = 0) ||
+ !(eol = strchr(col2, '\n')) || (*eol++ = 0))
+ {
+ continue;
+ }
+
+ if (!uh_interpreter_add(col1, col2))
+ {
+ fprintf(stderr,
+ "Unable to add interpreter %s for extension %s: "
+ "Out of memory\n", col2, col1
+ );
+ }
+ }
+#endif
+ }
+
+ fclose(c);
+ }
+}
+
+static void uh_listener_cb(struct uloop_fd *u, unsigned int events);
+
+static int uh_socket_bind(const char *host, const char *port,
+ struct addrinfo *hints, int do_tls,
+ struct config *conf)
+{
+ int sock = -1;
+ int yes = 1;
+ int status;
+ int bound = 0;
+
+ int tcp_ka_idl, tcp_ka_int, tcp_ka_cnt;
+
+ struct listener *l = NULL;
+ struct addrinfo *addrs = NULL, *p = NULL;
+
+ if ((status = getaddrinfo(host, port, hints, &addrs)) != 0)
+ {
+ fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(status));
+ }
+
+ /* try to bind a new socket to each found address */
+ for (p = addrs; p; p = p->ai_next)
+ {
+ /* get the socket */
+ if ((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
+ {
+ perror("socket()");
+ goto error;
+ }
+
+ /* "address already in use" */
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)))
+ {
+ perror("setsockopt()");
+ goto error;
+ }
+
+ /* TCP keep-alive */
+ if (conf->tcp_keepalive > 0)
+ {
+ tcp_ka_idl = 1;
+ tcp_ka_cnt = 3;
+ tcp_ka_int = conf->tcp_keepalive;
+
+ if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) ||
+ setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &tcp_ka_idl, sizeof(tcp_ka_idl)) ||
+ setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &tcp_ka_int, sizeof(tcp_ka_int)) ||
+ setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &tcp_ka_cnt, sizeof(tcp_ka_cnt)))
+ {
+ fprintf(stderr, "Notice: Unable to enable TCP keep-alive: %s\n",
+ strerror(errno));
+ }
+ }
+
+ /* required to get parallel v4 + v6 working */
+ if (p->ai_family == AF_INET6)
+ {
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes)) == -1)
+ {
+ perror("setsockopt()");
+ goto error;
+ }
+ }
+
+ /* bind */
+ if (bind(sock, p->ai_addr, p->ai_addrlen) == -1)
+ {
+ perror("bind()");
+ goto error;
+ }
+
+ /* listen */
+ if (listen(sock, UH_LIMIT_CLIENTS) == -1)
+ {
+ perror("listen()");
+ goto error;
+ }
+
+ /* add listener to global list */
+ if (!(l = uh_listener_add(sock, conf)))
+ {
+ fprintf(stderr, "uh_listener_add(): Failed to allocate memory\n");
+ goto error;
+ }
+
+#ifdef HAVE_TLS
+ /* init TLS */
+ l->tls = do_tls ? conf->tls : NULL;
+#endif
+
+ /* add socket to uloop */
+ fd_cloexec(sock);
+ uh_ufd_add(&l->fd, uh_listener_cb, ULOOP_READ);
+
+ bound++;
+ continue;
+
+ error:
+ if (sock > 0)
+ close(sock);
+ }
+
+ freeaddrinfo(addrs);
+
+ return bound;
+}
+
+static struct http_request * uh_http_header_parse(struct client *cl,
+ char *buffer, int buflen)
+{
+ char *method = buffer;
+ char *path = NULL;
+ char *version = NULL;
+
+ char *headers = NULL;
+ char *hdrname = NULL;
+ char *hdrdata = NULL;
+
+ int i;
+ int hdrcount = 0;
+
+ struct http_request *req = &cl->request;
+
+
+ /* terminate initial header line */
+ if ((headers = strfind(buffer, buflen, "\r\n", 2)) != NULL)
+ {
+ buffer[buflen-1] = 0;
+
+ *headers++ = 0;
+ *headers++ = 0;
+
+ /* find request path */
+ if ((path = strchr(buffer, ' ')) != NULL)
+ *path++ = 0;
+
+ /* find http version */
+ if ((path != NULL) && ((version = strchr(path, ' ')) != NULL))
+ *version++ = 0;
+
+
+ /* check method */
+ if (method && !strcmp(method, "GET"))
+ req->method = UH_HTTP_MSG_GET;
+ else if (method && !strcmp(method, "POST"))
+ req->method = UH_HTTP_MSG_POST;
+ else if (method && !strcmp(method, "HEAD"))
+ req->method = UH_HTTP_MSG_HEAD;
+ else
+ {
+ /* invalid method */
+ uh_http_response(cl, 405, "Method Not Allowed");
+ return NULL;
+ }
+
+ /* check path */
+ if (!path || !strlen(path))
+ {
+ /* malformed request */
+ uh_http_response(cl, 400, "Bad Request");
+ return NULL;
+ }
+ else
+ {
+ req->url = path;
+ }
+
+ /* check version */
+ if (version && !strcmp(version, "HTTP/0.9"))
+ req->version = UH_HTTP_VER_0_9;
+ else if (version && !strcmp(version, "HTTP/1.0"))
+ req->version = UH_HTTP_VER_1_0;
+ else if (version && !strcmp(version, "HTTP/1.1"))
+ req->version = UH_HTTP_VER_1_1;
+ else
+ {
+ /* unsupported version */
+ uh_http_response(cl, 400, "Bad Request");
+ return NULL;
+ }
+
+ D("SRV: %s %s %s\n",
+ http_methods[req->method], req->url, http_versions[req->version]);
+
+ /* process header fields */
+ for (i = (int)(headers - buffer); i < buflen; i++)
+ {
+ /* found eol and have name + value, push out header tuple */
+ if (hdrname && hdrdata && (buffer[i] == '\r' || buffer[i] == '\n'))
+ {
+ buffer[i] = 0;
+
+ /* store */
+ if ((hdrcount + 1) < array_size(req->headers))
+ {
+ D("SRV: HTTP: %s: %s\n", hdrname, hdrdata);
+
+ req->headers[hdrcount++] = hdrname;
+ req->headers[hdrcount++] = hdrdata;
+
+ hdrname = hdrdata = NULL;
+ }
+
+ /* too large */
+ else
+ {
+ D("SRV: HTTP: header too big (too many headers)\n");
+ uh_http_response(cl, 413, "Request Entity Too Large");
+ return NULL;
+ }
+ }
+
+ /* have name but no value and found a colon, start of value */
+ else if (hdrname && !hdrdata &&
+ ((i+1) < buflen) && (buffer[i] == ':'))
+ {
+ buffer[i] = 0;
+ hdrdata = &buffer[i+1];
+
+ while ((hdrdata + 1) < (buffer + buflen) && *hdrdata == ' ')
+ hdrdata++;
+ }
+
+ /* have no name and found [A-Za-z], start of name */
+ else if (!hdrname && isalpha(buffer[i]))
+ {
+ hdrname = &buffer[i];
+ }
+ }
+
+ /* valid enough */
+ req->redirect_status = 200;
+ return req;
+ }
+
+ /* Malformed request */
+ uh_http_response(cl, 400, "Bad Request");
+ return NULL;
+}
+
+
+static struct http_request * uh_http_header_recv(struct client *cl)
+{
+ char *bufptr = cl->httpbuf.buf;
+ char *idxptr = NULL;
+
+ ssize_t blen = sizeof(cl->httpbuf.buf)-1;
+ ssize_t rlen = 0;
+
+ memset(bufptr, 0, sizeof(cl->httpbuf.buf));
+
+ while (blen > 0)
+ {
+ /* receive data */
+ ensure_out(rlen = uh_tcp_recv(cl, bufptr, blen));
+ D("SRV: Client(%d) peek(%d) = %d\n", cl->fd.fd, blen, rlen);
+
+ if (rlen <= 0)
+ {
+ D("SRV: Client(%d) dead [%s]\n", cl->fd.fd, strerror(errno));
+ return NULL;
+ }
+
+ blen -= rlen;
+ bufptr += rlen;
+
+ if ((idxptr = strfind(cl->httpbuf.buf, sizeof(cl->httpbuf.buf),
+ "\r\n\r\n", 4)))
+ {
+ /* header read complete ... */
+ cl->httpbuf.ptr = idxptr + 4;
+ cl->httpbuf.len = bufptr - cl->httpbuf.ptr;
+
+ return uh_http_header_parse(cl, cl->httpbuf.buf,
+ (cl->httpbuf.ptr - cl->httpbuf.buf));
+ }
+ }
+
+ /* request entity too large */
+ D("SRV: HTTP: header too big (buffer exceeded)\n");
+ uh_http_response(cl, 413, "Request Entity Too Large");
+
+out:
+ return NULL;
+}
+
+#if defined(HAVE_LUA) || defined(HAVE_CGI)
+static int uh_path_match(const char *prefix, const char *url)
+{
+ if ((strstr(url, prefix) == url) &&
+ ((prefix[strlen(prefix)-1] == '/') ||
+ (strlen(url) == strlen(prefix)) ||
+ (url[strlen(prefix)] == '/')))
+ {
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
+static bool uh_dispatch_request(struct client *cl, struct http_request *req)
+{
+ struct path_info *pin;
+ struct interpreter *ipr = NULL;
+ struct config *conf = cl->server->conf;
+
+#ifdef HAVE_LUA
+ /* Lua request? */
+ if (conf->lua_state &&
+ uh_path_match(conf->lua_prefix, req->url))
+ {
+ return conf->lua_request(cl, conf->lua_state);
+ }
+ else
+#endif
+
+#ifdef HAVE_UBUS
+ /* ubus request? */
+ if (conf->ubus_state &&
+ uh_path_match(conf->ubus_prefix, req->url))
+ {
+ return conf->ubus_request(cl, conf->ubus_state);
+ }
+ else
+#endif
+
+ /* dispatch request */
+ if ((pin = uh_path_lookup(cl, req->url)) != NULL)
+ {
+ /* auth ok? */
+ if (!pin->redirected && uh_auth_check(cl, req, pin))
+ {
+#ifdef HAVE_CGI
+ if (uh_path_match(conf->cgi_prefix, pin->name) ||
+ (ipr = uh_interpreter_lookup(pin->phys)) != NULL)
+ {
+ return uh_cgi_request(cl, pin, ipr);
+ }
+#endif
+ return uh_file_request(cl, pin);
+ }
+ }
+
+ /* 404 - pass 1 */
+ else
+ {
+ /* Try to invoke an error handler */
+ if ((pin = uh_path_lookup(cl, conf->error_handler)) != NULL)
+ {
+ /* auth ok? */
+ if (uh_auth_check(cl, req, pin))
+ {
+ req->redirect_status = 404;
+#ifdef HAVE_CGI
+ if (uh_path_match(conf->cgi_prefix, pin->name) ||
+ (ipr = uh_interpreter_lookup(pin->phys)) != NULL)
+ {
+ return uh_cgi_request(cl, pin, ipr);
+ }
+#endif
+ return uh_file_request(cl, pin);
+ }
+ }
+
+ /* 404 - pass 2 */
+ else
+ {
+ uh_http_sendhf(cl, 404, "Not Found", "No such file or directory");
+ }
+ }
+
+ return false;
+}
+
+static void uh_socket_cb(struct uloop_fd *u, unsigned int events);
+
+static void uh_listener_cb(struct uloop_fd *u, unsigned int events)
+{
+ int new_fd;
+ struct listener *serv;
+ struct client *cl;
+ struct config *conf;
+
+ struct sockaddr_in6 sa;
+ socklen_t sl = sizeof(sa);
+
+ serv = container_of(u, struct listener, fd);
+ conf = serv->conf;
+
+ /* defer client if maximum number of requests is exceeded */
+ if (serv->n_clients >= conf->max_requests)
+ return;
+
+ /* handle new connections */
+ if ((new_fd = accept(u->fd, (struct sockaddr *)&sa, &sl)) != -1)
+ {
+ D("SRV: Server(%d) accept => Client(%d)\n", u->fd, new_fd);
+
+ /* add to global client list */
+ if ((cl = uh_client_add(new_fd, serv, &sa)) != NULL)
+ {
+ /* add client socket to global fdset */
+ uh_ufd_add(&cl->fd, uh_socket_cb, ULOOP_READ);
+ fd_cloexec(cl->fd.fd);
+
+#ifdef HAVE_TLS
+ /* setup client tls context */
+ if (conf->tls)
+ {
+ if (conf->tls_accept(cl) < 1)
+ {
+ D("SRV: Client(%d) SSL handshake failed, drop\n", new_fd);
+
+ /* remove from global client list */
+ uh_client_remove(cl);
+ return;
+ }
+ }
+#endif
+ }
+
+ /* insufficient resources */
+ else
+ {
+ fprintf(stderr, "uh_client_add(): Cannot allocate memory\n");
+ close(new_fd);
+ }
+ }
+}
+
+static void uh_client_cb(struct client *cl, unsigned int events);
+
+static void uh_rpipe_cb(struct uloop_fd *u, unsigned int events)
+{
+ struct client *cl = container_of(u, struct client, rpipe);
+
+ D("SRV: Client(%d) rpipe readable\n", cl->fd.fd);
+
+ uh_client_cb(cl, ULOOP_WRITE);
+}
+
+static void uh_socket_cb(struct uloop_fd *u, unsigned int events)
+{
+ struct client *cl = container_of(u, struct client, fd);
+
+ D("SRV: Client(%d) socket readable\n", cl->fd.fd);
+
+ uh_client_cb(cl, ULOOP_READ);
+}
+
+static void uh_child_cb(struct uloop_process *p, int rv)
+{
+ struct client *cl = container_of(p, struct client, proc);
+
+ D("SRV: Client(%d) child(%d) dead\n", cl->fd.fd, cl->proc.pid);
+
+ uh_client_cb(cl, ULOOP_READ | ULOOP_WRITE);
+}
+
+static void uh_kill9_cb(struct uloop_timeout *t)
+{
+ struct client *cl = container_of(t, struct client, timeout);
+
+ if (!kill(cl->proc.pid, 0))
+ {
+ D("SRV: Client(%d) child(%d) kill(SIGKILL)...\n",
+ cl->fd.fd, cl->proc.pid);
+
+ kill(cl->proc.pid, SIGKILL);
+ }
+}
+
+static void uh_timeout_cb(struct uloop_timeout *t)
+{
+ struct client *cl = container_of(t, struct client, timeout);
+
+ D("SRV: Client(%d) child(%d) timed out\n", cl->fd.fd, cl->proc.pid);
+
+ if (!kill(cl->proc.pid, 0))
+ {
+ D("SRV: Client(%d) child(%d) kill(SIGTERM)...\n",
+ cl->fd.fd, cl->proc.pid);
+
+ kill(cl->proc.pid, SIGTERM);
+
+ cl->timeout.cb = uh_kill9_cb;
+ uloop_timeout_set(&cl->timeout, 1000);
+ }
+}
+
+static void uh_client_cb(struct client *cl, unsigned int events)
+{
+ int i;
+ struct config *conf;
+ struct http_request *req;
+
+ conf = cl->server->conf;
+
+ D("SRV: Client(%d) enter callback\n", cl->fd.fd);
+
+ /* undispatched yet */
+ if (!cl->dispatched)
+ {
+ /* we have no headers yet and this was a write event, ignore... */
+ if (!(events & ULOOP_READ))
+ {
+ D("SRV: Client(%d) ignoring write event before headers\n", cl->fd.fd);
+ return;
+ }
+
+ /* attempt to receive and parse headers */
+ if (!(req = uh_http_header_recv(cl)))
+ {
+ D("SRV: Client(%d) failed to receive header\n", cl->fd.fd);
+ uh_client_shutdown(cl);
+ return;
+ }
+
+ /* process expect headers */
+ foreach_header(i, req->headers)
+ {
+ if (strcasecmp(req->headers[i], "Expect"))
+ continue;
+
+ if (strcasecmp(req->headers[i+1], "100-continue"))
+ {
+ D("SRV: Client(%d) unknown expect header (%s)\n",
+ cl->fd.fd, req->headers[i+1]);
+
+ uh_http_response(cl, 417, "Precondition Failed");
+ uh_client_shutdown(cl);
+ return;
+ }
+ else
+ {
+ D("SRV: Client(%d) sending HTTP/1.1 100 Continue\n", cl->fd.fd);
+
+ uh_http_sendf(cl, NULL, "HTTP/1.1 100 Continue\r\n\r\n");
+ cl->httpbuf.len = 0; /* client will re-send the body */
+ break;
+ }
+ }
+
+ /* RFC1918 filtering */
+ if (conf->rfc1918_filter &&
+ sa_rfc1918(&cl->peeraddr) && !sa_rfc1918(&cl->servaddr))
+ {
+ uh_http_sendhf(cl, 403, "Forbidden",
+ "Rejected request from RFC1918 IP "
+ "to public server address");
+
+ uh_client_shutdown(cl);
+ return;
+ }
+
+ /* dispatch request */
+ if (!uh_dispatch_request(cl, req))
+ {
+ D("SRV: Client(%d) failed to dispach request\n", cl->fd.fd);
+ uh_client_shutdown(cl);
+ return;
+ }
+
+ /* request handler spawned a pipe, register handler */
+ if (cl->rpipe.fd > -1)
+ {
+ D("SRV: Client(%d) pipe(%d) spawned\n", cl->fd.fd, cl->rpipe.fd);
+
+ uh_ufd_add(&cl->rpipe, uh_rpipe_cb, ULOOP_READ);
+ }
+
+ /* request handler spawned a child, register handler */
+ if (cl->proc.pid)
+ {
+ D("SRV: Client(%d) child(%d) spawned\n", cl->fd.fd, cl->proc.pid);
+
+ cl->proc.cb = uh_child_cb;
+ uloop_process_add(&cl->proc);
+
+ cl->timeout.cb = uh_timeout_cb;
+ uloop_timeout_set(&cl->timeout, conf->script_timeout * 1000);
+ }
+
+ /* header processing complete */
+ D("SRV: Client(%d) dispatched\n", cl->fd.fd);
+ cl->dispatched = true;
+ }
+
+ if (!cl->cb(cl))
+ {
+ D("SRV: Client(%d) response callback signalized EOF\n", cl->fd.fd);
+ uh_client_shutdown(cl);
+ return;
+ }
+}
+
+#ifdef HAVE_TLS
+static inline int uh_inittls(struct config *conf)
+{
+ /* library handle */
+ void *lib;
+
+ /* already loaded */
+ if (conf->tls != NULL)
+ return 0;
+
+ /* load TLS plugin */
+ if (!(lib = dlopen("uhttpd_tls.so", RTLD_LAZY | RTLD_GLOBAL)))
+ {
+ fprintf(stderr,
+ "Notice: Unable to load TLS plugin - disabling SSL support! "
+ "(Reason: %s)\n", dlerror()
+ );
+
+ return 1;
+ }
+ else
+ {
+ /* resolve functions */
+ if (!(conf->tls_init = dlsym(lib, "uh_tls_ctx_init")) ||
+ !(conf->tls_cert = dlsym(lib, "uh_tls_ctx_cert")) ||
+ !(conf->tls_key = dlsym(lib, "uh_tls_ctx_key")) ||
+ !(conf->tls_free = dlsym(lib, "uh_tls_ctx_free")) ||
+ !(conf->tls_accept = dlsym(lib, "uh_tls_client_accept")) ||
+ !(conf->tls_close = dlsym(lib, "uh_tls_client_close")) ||
+ !(conf->tls_recv = dlsym(lib, "uh_tls_client_recv")) ||
+ !(conf->tls_send = dlsym(lib, "uh_tls_client_send")))
+ {
+ fprintf(stderr,
+ "Error: Failed to lookup required symbols "
+ "in TLS plugin: %s\n", dlerror()
+ );
+ exit(1);
+ }
+
+ /* init SSL context */
+ if (!(conf->tls = conf->tls_init()))
+ {
+ fprintf(stderr, "Error: Failed to initalize SSL context\n");
+ exit(1);
+ }
+ }
+
+ return 0;
+}
+#endif
+
+int main (int argc, char **argv)
+{
+ /* working structs */
+ struct addrinfo hints;
+ struct sigaction sa;
+ struct config conf;
+
+ /* maximum file descriptor number */
+ int cur_fd = 0;
+
+#ifdef HAVE_TLS
+ int tls = 0;
+ int keys = 0;
+#endif
+
+ int bound = 0;
+ int nofork = 0;
+
+ /* args */
+ int opt;
+ char addr[128];
+ char *port = NULL;
+
+#if defined(HAVE_LUA) || defined(HAVE_TLS) || defined(HAVE_UBUS)
+ /* library handle */
+ void *lib;
+#endif
+
+ /* handle SIGPIPE, SIGINT, SIGTERM */
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &sa, NULL);
+
+ sa.sa_handler = uh_sigterm;
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+
+ /* prepare addrinfo hints */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE;
+
+ /* parse args */
+ memset(&conf, 0, sizeof(conf));
+
+ uloop_init();
+
+ while ((opt = getopt(argc, argv,
+ "fSDRC:K:E:I:p:s:h:c:l:L:d:r:m:n:x:i:t:T:A:u:U:")) > 0)
+ {
+ switch(opt)
+ {
+ /* [addr:]port */
+ case 'p':
+ case 's':
+ memset(addr, 0, sizeof(addr));
+
+ if ((port = strrchr(optarg, ':')) != NULL)
+ {
+ if ((optarg[0] == '[') && (port > optarg) && (port[-1] == ']'))
+ memcpy(addr, optarg + 1,
+ min(sizeof(addr), (int)(port - optarg) - 2));
+ else
+ memcpy(addr, optarg,
+ min(sizeof(addr), (int)(port - optarg)));
+
+ port++;
+ }
+ else
+ {
+ port = optarg;
+ }
+
+#ifdef HAVE_TLS
+ if (opt == 's')
+ {
+ if (uh_inittls(&conf))
+ {
+ fprintf(stderr,
+ "Notice: TLS support is disabled, "
+ "ignoring '-s %s'\n", optarg
+ );
+ continue;
+ }
+
+ tls = 1;
+ }
+#endif
+
+ /* bind sockets */
+ bound += uh_socket_bind(addr[0] ? addr : NULL, port, &hints,
+ (opt == 's'), &conf);
+ break;
+
+#ifdef HAVE_TLS
+ /* certificate */
+ case 'C':
+ if (!uh_inittls(&conf))
+ {
+ if (conf.tls_cert(conf.tls, optarg) < 1)
+ {
+ fprintf(stderr,
+ "Error: Invalid certificate file given\n");
+ exit(1);
+ }
+
+ keys++;
+ }
+
+ break;
+
+ /* key */
+ case 'K':
+ if (!uh_inittls(&conf))
+ {
+ if (conf.tls_key(conf.tls, optarg) < 1)
+ {
+ fprintf(stderr,
+ "Error: Invalid private key file given\n");
+ exit(1);
+ }
+
+ keys++;
+ }
+
+ break;
+#else
+ case 'C':
+ case 'K':
+ fprintf(stderr,
+ "Notice: TLS support not compiled, ignoring -%c\n",
+ opt);
+ break;
+#endif
+
+ /* docroot */
+ case 'h':
+ if (! realpath(optarg, conf.docroot))
+ {
+ fprintf(stderr, "Error: Invalid directory %s: %s\n",
+ optarg, strerror(errno));
+ exit(1);
+ }
+ break;
+
+ /* error handler */
+ case 'E':
+ if ((strlen(optarg) == 0) || (optarg[0] != '/'))
+ {
+ fprintf(stderr, "Error: Invalid error handler: %s\n",
+ optarg);
+ exit(1);
+ }
+ conf.error_handler = optarg;
+ break;
+
+ /* index file */
+ case 'I':
+ if ((strlen(optarg) == 0) || (optarg[0] == '/'))
+ {
+ fprintf(stderr, "Error: Invalid index page: %s\n",
+ optarg);
+ exit(1);
+ }
+ conf.index_file = optarg;
+ break;
+
+ /* don't follow symlinks */
+ case 'S':
+ conf.no_symlinks = 1;
+ break;
+
+ /* don't list directories */
+ case 'D':
+ conf.no_dirlists = 1;
+ break;
+
+ case 'R':
+ conf.rfc1918_filter = 1;
+ break;
+
+ case 'n':
+ conf.max_requests = atoi(optarg);
+ break;
+
+#ifdef HAVE_CGI
+ /* cgi prefix */
+ case 'x':
+ conf.cgi_prefix = optarg;
+ break;
+
+ /* interpreter */
+ case 'i':
+ if ((optarg[0] == '.') && (port = strchr(optarg, '=')))
+ {
+ *port++ = 0;
+ uh_interpreter_add(optarg, port);
+ }
+ else
+ {
+ fprintf(stderr, "Error: Invalid interpreter: %s\n",
+ optarg);
+ exit(1);
+ }
+ break;
+#else
+ case 'x':
+ case 'i':
+ fprintf(stderr,
+ "Notice: CGI support not compiled, ignoring -%c\n",
+ opt);
+ break;
+#endif
+
+#ifdef HAVE_LUA
+ /* lua prefix */
+ case 'l':
+ conf.lua_prefix = optarg;
+ break;
+
+ /* lua handler */
+ case 'L':
+ conf.lua_handler = optarg;
+ break;
+#else
+ case 'l':
+ case 'L':
+ fprintf(stderr,
+ "Notice: Lua support not compiled, ignoring -%c\n",
+ opt);
+ break;
+#endif
+
+#ifdef HAVE_UBUS
+ /* ubus prefix */
+ case 'u':
+ conf.ubus_prefix = optarg;
+ break;
+
+ /* ubus socket */
+ case 'U':
+ conf.ubus_socket = optarg;
+ break;
+#else
+ case 'u':
+ case 'U':
+ fprintf(stderr,
+ "Notice: UBUS support not compiled, ignoring -%c\n",
+ opt);
+ break;
+#endif
+
+#if defined(HAVE_CGI) || defined(HAVE_LUA)
+ /* script timeout */
+ case 't':
+ conf.script_timeout = atoi(optarg);
+ break;
+#endif
+
+ /* network timeout */
+ case 'T':
+ conf.network_timeout = atoi(optarg);
+ break;
+
+ /* tcp keep-alive */
+ case 'A':
+ conf.tcp_keepalive = atoi(optarg);
+ break;
+
+ /* no fork */
+ case 'f':
+ nofork = 1;
+ break;
+
+ /* urldecode */
+ case 'd':
+ if ((port = malloc(strlen(optarg)+1)) != NULL)
+ {
+ /* "decode" plus to space to retain compat */
+ for (opt = 0; optarg[opt]; opt++)
+ if (optarg[opt] == '+')
+ optarg[opt] = ' ';
+ /* opt now contains strlen(optarg) -- no need to re-scan */
+ memset(port, 0, opt+1);
+ if (uh_urldecode(port, opt, optarg, opt) < 0)
+ fprintf(stderr, "uhttpd: invalid encoding\n");
+
+ printf("%s", port);
+ free(port);
+ exit(0);
+ }
+ break;
+
+ /* basic auth realm */
+ case 'r':
+ conf.realm = optarg;
+ break;
+
+ /* md5 crypt */
+ case 'm':
+ printf("%s\n", crypt(optarg, "$1$"));
+ exit(0);
+ break;
+
+ /* config file */
+ case 'c':
+ conf.file = optarg;
+ break;
+
+ default:
+ fprintf(stderr,
+ "Usage: %s -p [addr:]port [-h docroot]\n"
+ " -f Do not fork to background\n"
+ " -c file Configuration file, default is '/etc/httpd.conf'\n"
+ " -p [addr:]port Bind to specified address and port, multiple allowed\n"
+#ifdef HAVE_TLS
+ " -s [addr:]port Like -p but provide HTTPS on this port\n"
+ " -C file ASN.1 server certificate file\n"
+ " -K file ASN.1 server private key file\n"
+#endif
+ " -h directory Specify the document root, default is '.'\n"
+ " -E string Use given virtual URL as 404 error handler\n"
+ " -I string Use given filename as index page for directories\n"
+ " -S Do not follow symbolic links outside of the docroot\n"
+ " -D Do not allow directory listings, send 403 instead\n"
+ " -R Enable RFC1918 filter\n"
+ " -n count Maximum allowed number of concurrent requests\n"
+#ifdef HAVE_LUA
+ " -l string URL prefix for Lua handler, default is '/lua'\n"
+ " -L file Lua handler script, omit to disable Lua\n"
+#endif
+#ifdef HAVE_UBUS
+ " -u string URL prefix for HTTP/JSON handler\n"
+ " -U file Override ubus socket path\n"
+#endif
+#ifdef HAVE_CGI
+ " -x string URL prefix for CGI handler, default is '/cgi-bin'\n"
+ " -i .ext=path Use interpreter at path for files with the given extension\n"
+#endif
+#if defined(HAVE_CGI) || defined(HAVE_LUA) || defined(HAVE_UBUS)
+ " -t seconds CGI, Lua and UBUS script timeout in seconds, default is 60\n"
+#endif
+ " -T seconds Network timeout in seconds, default is 30\n"
+ " -d string URL decode given string\n"
+ " -r string Specify basic auth realm\n"
+ " -m string MD5 crypt given string\n"
+ "\n", argv[0]
+ );
+
+ exit(1);
+ }
+ }
+
+#ifdef HAVE_TLS
+ if ((tls == 1) && (keys < 2))
+ {
+ fprintf(stderr, "Error: Missing private key or certificate file\n");
+ exit(1);
+ }
+#endif
+
+ if (bound < 1)
+ {
+ fprintf(stderr, "Error: No sockets bound, unable to continue\n");
+ exit(1);
+ }
+
+ /* default docroot */
+ if (!conf.docroot[0] && !realpath(".", conf.docroot))
+ {
+ fprintf(stderr, "Error: Can not determine default document root: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+
+ /* default realm */
+ if (!conf.realm)
+ conf.realm = "Protected Area";
+
+ /* config file */
+ uh_config_parse(&conf);
+
+ /* default max requests */
+ if (conf.max_requests <= 0)
+ conf.max_requests = 3;
+
+ /* default network timeout */
+ if (conf.network_timeout <= 0)
+ conf.network_timeout = 30;
+
+#if defined(HAVE_CGI) || defined(HAVE_LUA) || defined(HAVE_UBUS)
+ /* default script timeout */
+ if (conf.script_timeout <= 0)
+ conf.script_timeout = 60;
+#endif
+
+#ifdef HAVE_CGI
+ /* default cgi prefix */
+ if (!conf.cgi_prefix)
+ conf.cgi_prefix = "/cgi-bin";
+#endif
+
+#ifdef HAVE_LUA
+ /* load Lua plugin */
+ if (!(lib = dlopen("uhttpd_lua.so", RTLD_LAZY | RTLD_GLOBAL)))
+ {
+ fprintf(stderr,
+ "Notice: Unable to load Lua plugin - disabling Lua support! "
+ "(Reason: %s)\n", dlerror());
+ }
+ else
+ {
+ /* resolve functions */
+ if (!(conf.lua_init = dlsym(lib, "uh_lua_init")) ||
+ !(conf.lua_close = dlsym(lib, "uh_lua_close")) ||
+ !(conf.lua_request = dlsym(lib, "uh_lua_request")))
+ {
+ fprintf(stderr,
+ "Error: Failed to lookup required symbols "
+ "in Lua plugin: %s\n", dlerror()
+ );
+ exit(1);
+ }
+
+ /* init Lua runtime if handler is specified */
+ if (conf.lua_handler)
+ {
+ /* default lua prefix */
+ if (!conf.lua_prefix)
+ conf.lua_prefix = "/lua";
+
+ conf.lua_state = conf.lua_init(&conf);
+ }
+ }
+#endif
+
+#ifdef HAVE_UBUS
+ /* load ubus plugin */
+ if (!(lib = dlopen("uhttpd_ubus.so", RTLD_LAZY | RTLD_GLOBAL)))
+ {
+ fprintf(stderr,
+ "Notice: Unable to load ubus plugin - disabling ubus support! "
+ "(Reason: %s)\n", dlerror());
+ }
+ else if (conf.ubus_prefix)
+ {
+ /* resolve functions */
+ if (!(conf.ubus_init = dlsym(lib, "uh_ubus_init")) ||
+ !(conf.ubus_close = dlsym(lib, "uh_ubus_close")) ||
+ !(conf.ubus_request = dlsym(lib, "uh_ubus_request")))
+ {
+ fprintf(stderr,
+ "Error: Failed to lookup required symbols "
+ "in ubus plugin: %s\n", dlerror()
+ );
+ exit(1);
+ }
+
+ /* initialize ubus */
+ conf.ubus_state = conf.ubus_init(&conf);
+ }
+#endif
+
+ /* fork (if not disabled) */
+ if (!nofork)
+ {
+ switch (fork())
+ {
+ case -1:
+ perror("fork()");
+ exit(1);
+
+ case 0:
+ /* daemon setup */
+ if (chdir("/"))
+ perror("chdir()");
+
+ if ((cur_fd = open("/dev/null", O_WRONLY)) > -1)
+ dup2(cur_fd, 0);
+
+ if ((cur_fd = open("/dev/null", O_RDONLY)) > -1)
+ dup2(cur_fd, 1);
+
+ if ((cur_fd = open("/dev/null", O_RDONLY)) > -1)
+ dup2(cur_fd, 2);
+
+ break;
+
+ default:
+ exit(0);
+ }
+ }
+
+ /* server main loop */
+ uloop_run();
+
+#ifdef HAVE_LUA
+ /* destroy the Lua state */
+ if (conf.lua_state != NULL)
+ conf.lua_close(conf.lua_state);
+#endif
+
+#ifdef HAVE_UBUS
+ /* destroy the ubus state */
+ if (conf.ubus_state != NULL)
+ conf.ubus_close(conf.ubus_state);
+#endif
+
+ return 0;
+}
diff --git a/package/uhttpd/src/uhttpd.h b/package/uhttpd/src/uhttpd.h
new file mode 100644
index 000000000..f6982db32
--- /dev/null
+++ b/package/uhttpd/src/uhttpd.h
@@ -0,0 +1,214 @@
+/*
+ * uhttpd - Tiny single-threaded httpd - Main header
+ *
+ * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UHTTPD_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <linux/limits.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <errno.h>
+#include <dlfcn.h>
+
+#include <libubox/list.h>
+#include <libubox/uloop.h>
+
+
+#ifdef HAVE_LUA
+#include <lua.h>
+#endif
+
+#ifdef HAVE_TLS
+#include <openssl/ssl.h>
+#endif
+
+/* uClibc... */
+#ifndef SOL_TCP
+#define SOL_TCP 6
+#endif
+
+#ifdef DEBUG
+#define D(...) fprintf(stderr, __VA_ARGS__)
+#else
+#define D(...)
+#endif
+
+
+#define UH_LIMIT_MSGHEAD 4096
+#define UH_LIMIT_HEADERS 64
+#define UH_LIMIT_CLIENTS 64
+
+
+struct listener;
+struct client;
+struct interpreter;
+struct http_request;
+struct uh_ubus_state;
+
+struct config {
+ char docroot[PATH_MAX];
+ char *realm;
+ char *file;
+ char *index_file;
+ char *error_handler;
+ int no_symlinks;
+ int no_dirlists;
+ int network_timeout;
+ int rfc1918_filter;
+ int tcp_keepalive;
+ int max_requests;
+#ifdef HAVE_CGI
+ char *cgi_prefix;
+#endif
+#ifdef HAVE_LUA
+ char *lua_prefix;
+ char *lua_handler;
+ lua_State *lua_state;
+ lua_State * (*lua_init) (const struct config *conf);
+ void (*lua_close) (lua_State *L);
+ bool (*lua_request) (struct client *cl, lua_State *L);
+#endif
+#ifdef HAVE_UBUS
+ char *ubus_prefix;
+ char *ubus_socket;
+ void *ubus_state;
+ struct uh_ubus_state * (*ubus_init) (const struct config *conf);
+ void (*ubus_close) (struct uh_ubus_state *state);
+ bool (*ubus_request) (struct client *cl, struct uh_ubus_state *state);
+#endif
+#if defined(HAVE_CGI) || defined(HAVE_LUA) || defined(HAVE_UBUS)
+ int script_timeout;
+#endif
+#ifdef HAVE_TLS
+ char *cert;
+ char *key;
+ SSL_CTX *tls;
+ SSL_CTX * (*tls_init) (void);
+ int (*tls_cert) (SSL_CTX *c, const char *file);
+ int (*tls_key) (SSL_CTX *c, const char *file);
+ void (*tls_free) (struct listener *l);
+ int (*tls_accept) (struct client *c);
+ void (*tls_close) (struct client *c);
+ int (*tls_recv) (struct client *c, char *buf, int len);
+ int (*tls_send) (struct client *c, const char *buf, int len);
+#endif
+};
+
+enum http_method {
+ UH_HTTP_MSG_GET,
+ UH_HTTP_MSG_POST,
+ UH_HTTP_MSG_HEAD,
+};
+
+extern const char *http_methods[];
+
+enum http_version {
+ UH_HTTP_VER_0_9,
+ UH_HTTP_VER_1_0,
+ UH_HTTP_VER_1_1,
+};
+
+extern const char *http_versions[];
+
+struct http_request {
+ enum http_method method;
+ enum http_version version;
+ int redirect_status;
+ char *url;
+ char *headers[UH_LIMIT_HEADERS];
+ struct auth_realm *realm;
+};
+
+struct http_response {
+ int statuscode;
+ char *statusmsg;
+ char *headers[UH_LIMIT_HEADERS];
+};
+
+struct listener {
+ struct uloop_fd fd;
+ int socket;
+ int n_clients;
+ struct sockaddr_in6 addr;
+ struct config *conf;
+#ifdef HAVE_TLS
+ SSL_CTX *tls;
+#endif
+ struct listener *next;
+};
+
+struct client {
+#ifdef HAVE_TLS
+ SSL *tls;
+#endif
+ struct uloop_fd fd;
+ struct uloop_fd rpipe;
+ struct uloop_fd wpipe;
+ struct uloop_process proc;
+ struct uloop_timeout timeout;
+ bool (*cb)(struct client *);
+ void *priv;
+ bool dispatched;
+ struct {
+ char buf[UH_LIMIT_MSGHEAD];
+ char *ptr;
+ int len;
+ } httpbuf;
+ struct listener *server;
+ struct http_request request;
+ struct http_response response;
+ struct sockaddr_in6 servaddr;
+ struct sockaddr_in6 peeraddr;
+ struct client *next;
+};
+
+struct client_light {
+#ifdef HAVE_TLS
+ SSL *tls;
+#endif
+ struct uloop_fd fd;
+};
+
+struct auth_realm {
+ char path[PATH_MAX];
+ char user[32];
+ char pass[128];
+ struct auth_realm *next;
+};
+
+#ifdef HAVE_CGI
+struct interpreter {
+ char path[PATH_MAX];
+ char extn[32];
+ struct interpreter *next;
+};
+#endif
+
+#endif
diff --git a/package/usbreset/Makefile b/package/usbreset/Makefile
new file mode 100644
index 000000000..75bfd8513
--- /dev/null
+++ b/package/usbreset/Makefile
@@ -0,0 +1,44 @@
+#
+# Copyright (C) 2011-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=usbreset
+PKG_RELEASE:=2
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/usbreset
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Utility to send a USB port reset to a USB device
+ MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org>
+endef
+
+define Package/usbreset/description
+ This package contains the small usbreset utility which
+ can be used to send a USB port reset to a USB device -
+ useful for debugging or to force re-detection of particular
+ devices.
+endef
+
+define Build/Prepare
+ $(INSTALL_DIR) $(PKG_BUILD_DIR)
+ $(INSTALL_DATA) ./src/usbreset.c $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ $(TARGET_CC) $(TARGET_CFLAGS) -Wall \
+ -o $(PKG_BUILD_DIR)/usbreset $(PKG_BUILD_DIR)/usbreset.c
+endef
+
+define Package/usbreset/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/usbreset $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,usbreset))
diff --git a/package/usbreset/src/usbreset.c b/package/usbreset/src/usbreset.c
new file mode 100644
index 000000000..087a14cfa
--- /dev/null
+++ b/package/usbreset/src/usbreset.c
@@ -0,0 +1,253 @@
+/* usbreset -- send a USB port reset to a USB device */
+
+/*
+
+http://marc.info/?l=linux-usb-users&m=116827193506484&w=2
+
+and needs mounted usbfs filesystem
+
+ sudo mount -t usbfs none /proc/bus/usb
+
+There is a way to suspend a USB device. In order to use it,
+you must have a kernel with CONFIG_PM_SYSFS_DEPRECATED turned on. To
+suspend a device, do (as root):
+
+ echo -n 2 >/sys/bus/usb/devices/.../power/state
+
+where the "..." is the ID for your device. To unsuspend, do the same
+thing but with a "0" instead of the "2" above.
+
+Note that this mechanism is slated to be removed from the kernel within
+the next year. Hopefully some other mechanism will take its place.
+
+> To reset a
+> device?
+
+Here's a program to do it. You invoke it as either
+
+ usbreset /proc/bus/usb/BBB/DDD
+or
+ usbreset /dev/usbB.D
+
+depending on how your system is set up, where BBB and DDD are the bus and
+device address numbers.
+
+Alan Stern
+
+*/
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+#include <linux/usbdevice_fs.h>
+
+
+static char *usbfs = NULL;
+
+struct usbentry {
+ int bus_num;
+ int dev_num;
+ int vendor_id;
+ int product_id;
+ char vendor_name[128];
+ char product_name[128];
+};
+
+
+static bool find_usbfs(void)
+{
+ FILE *mtab;
+
+ char buf[1024], type[32];
+ static char path[1024];
+
+ if ((mtab = fopen("/proc/mounts", "r")) != NULL)
+ {
+ while (fgets(buf, sizeof(buf), mtab))
+ {
+ if (sscanf(buf, "%*s %1023s %31s ", path, type) == 2 &&
+ !strncmp(type, "usbfs", 5))
+ {
+ usbfs = path;
+ break;
+ }
+ }
+
+ fclose(mtab);
+ }
+
+ return !!usbfs;
+}
+
+static FILE * open_devlist(void)
+{
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "%s/devices", usbfs);
+ return fopen(buf, "r");
+}
+
+static void close_devlist(FILE *devs)
+{
+ fclose(devs);
+}
+
+static struct usbentry * parse_devlist(FILE *devs)
+{
+ char buf[1024];
+ static struct usbentry dev;
+
+ memset(&dev, 0, sizeof(dev));
+
+ while (fgets(buf, sizeof(buf), devs))
+ {
+ buf[strlen(buf)-1] = 0;
+
+ switch (buf[0])
+ {
+ case 'T':
+ sscanf(buf, "T: Bus=%d Lev=%*d Prnt=%*d Port=%*d Cnt=%*d Dev#=%d",
+ &dev.bus_num, &dev.dev_num);
+ break;
+
+ case 'P':
+ sscanf(buf, "P: Vendor=%x ProdID=%x",
+ &dev.vendor_id, &dev.product_id);
+ break;
+
+ case 'S':
+ if (!strncmp(buf, "S: Manufacturer=", 17))
+ snprintf(dev.vendor_name, sizeof(dev.vendor_name),
+ "%s", buf+17);
+ else if (!strncmp(buf, "S: Product=", 12))
+ snprintf(dev.product_name, sizeof(dev.product_name),
+ "%s", buf+12);
+ break;
+ }
+
+ if (dev.product_name[0])
+ return &dev;
+ }
+
+ return NULL;
+}
+
+static void list_devices(void)
+{
+ FILE *devs = open_devlist();
+ struct usbentry *dev;
+
+ if (!devs)
+ return;
+
+ while ((dev = parse_devlist(devs)) != NULL)
+ {
+ printf(" Number %03d/%03d ID %04x:%04x %s\n",
+ dev->bus_num, dev->dev_num,
+ dev->vendor_id, dev->product_id,
+ dev->product_name);
+ }
+
+ close_devlist(devs);
+}
+
+struct usbentry * find_device(int *bus, int *dev,
+ int *vid, int *pid,
+ const char *product)
+{
+ FILE *devs = open_devlist();
+
+ struct usbentry *e, *match = NULL;
+
+ if (!devs)
+ return NULL;
+
+ while ((e = parse_devlist(devs)) != NULL)
+ {
+ if ((bus && (e->bus_num == *bus) && (e->dev_num == *dev)) ||
+ (vid && (e->vendor_id == *vid) && (e->product_id == *pid)) ||
+ (product && !strcasecmp(e->product_name, product)))
+ {
+ match = e;
+ break;
+ }
+ }
+
+ close_devlist(devs);
+
+ return match;
+}
+
+static void reset_device(struct usbentry *dev)
+{
+ int fd;
+ char path[1024];
+
+ snprintf(path, sizeof(path), "%s/%03d/%03d",
+ usbfs, dev->bus_num, dev->dev_num);
+
+ printf("Resetting %s ... ", dev->product_name);
+
+ if ((fd = open(path, O_WRONLY)) > -1)
+ {
+ if (ioctl(fd, USBDEVFS_RESET, 0) < 0)
+ printf("failed [%s]\n", strerror(errno));
+ else
+ printf("ok\n");
+
+ close(fd);
+ }
+ else
+ {
+ printf("can't open [%s]\n", strerror(errno));
+ }
+}
+
+
+int main(int argc, char **argv)
+{
+ int id1, id2;
+ struct usbentry *dev;
+
+ if (!find_usbfs())
+ {
+ fprintf(stderr, "Unable to find usbfs, is it mounted?\n");
+ return 1;
+ }
+
+ if ((argc == 2) && (sscanf(argv[1], "%3d/%3d", &id1, &id2) == 2))
+ {
+ dev = find_device(&id1, &id2, NULL, NULL, NULL);
+ }
+ else if ((argc == 2) && (sscanf(argv[1], "%4x:%4x", &id1, &id2) == 2))
+ {
+ dev = find_device(NULL, NULL, &id1, &id2, NULL);
+ }
+ else if ((argc == 2) && strlen(argv[1]) < 128)
+ {
+ dev = find_device(NULL, NULL, NULL, NULL, argv[1]);
+ }
+ else
+ {
+ printf("Usage:\n"
+ " usbreset PPPP:VVVV - reset by product and vendor id\n"
+ " usbreset BBB/DDD - reset by bus and device number\n"
+ " usbreset \"Product\" - reset by product name\n\n"
+ "Devices:\n");
+ list_devices();
+ return 1;
+ }
+
+ if (!dev)
+ {
+ fprintf(stderr, "No such device found\n");
+ return 1;
+ }
+
+ reset_device(dev);
+ return 0;
+}
diff --git a/package/util-linux/Makefile b/package/util-linux/Makefile
new file mode 100644
index 000000000..3a6446371
--- /dev/null
+++ b/package/util-linux/Makefile
@@ -0,0 +1,591 @@
+#
+# Copyright (C) 2007-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=util-linux
+PKG_VERSION:=2.21.2
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@KERNEL/linux/utils/$(PKG_NAME)/v2.21
+PKG_MD5SUM:=54ba880f1d66782c2287ee2c898520e9
+
+PKG_BUILD_PARALLEL:=1
+PKG_BUILD_DEPENDS:=libncurses
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/util-linux/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ URL:=http://www.kernel.org/pub/linux/utils/util-linux/
+endef
+
+CONFIGURE_ARGS += \
+ --enable-new-mount \
+ --with-ncurses \
+ --disable-nls \
+ --disable-tls \
+ --without-udev
+
+TARGET_CFLAGS += $(FPIC)
+
+define Build/InstallDev
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ BUILDCC="$(HOSTCC)" \
+ DESTDIR="$(1)" \
+ installdirs install-data
+
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_BUILD_DIR)/libblkid/blkid.pc $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_BUILD_DIR)/libmount/mount.pc $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_BUILD_DIR)/libuuid/uuid.pc $(1)/usr/lib/pkgconfig
+
+ $(INSTALL_DIR) $(1)/usr/include/blkid
+ $(CP) $(PKG_BUILD_DIR)/libblkid/src/blkid.h $(1)/usr/include/blkid
+ $(INSTALL_DIR) $(1)/usr/include/libmount
+ $(CP) $(PKG_BUILD_DIR)/libmount/src/libmount.h $(1)/usr/include/libmount
+ $(INSTALL_DIR) $(1)/usr/include/uuid
+ $(CP) $(PKG_BUILD_DIR)/libuuid/src/uuid.h $(1)/usr/include/uuid
+
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/libblkid/src/.libs/libblkid.{a,so.*} $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/libmount/src/.libs/libmount.{a,so.*} $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/libuuid/src/.libs/libuuid.{a,so.*} $(1)/usr/lib
+endef
+
+define Package/libblkid
+$(call Package/util-linux/Default)
+ DEPENDS:=+libuuid
+ TITLE:=block device id library
+ SECTION:=libs
+ CATEGORY:=Libraries
+endef
+
+define Package/libblkid/description
+ The libblkid library is used to identify block devices (disks) as to their
+ content (e.g. filesystem type, partitions) as well as extracting additional
+ information such as filesystem labels/volume names, partitions, unique
+ identifiers/serial numbers...
+endef
+
+define Package/libmount
+$(call Package/util-linux/Default)
+ DEPENDS:=+libblkid
+ TITLE:=mount library
+ SECTION:=libs
+ CATEGORY:=Libraries
+endef
+
+define Package/libmount/description
+ The libmount library is used to parse /etc/fstab, /etc/mtab and
+ /proc/self/mountinfo files, manage the mtab file, evaluate mount options...
+endef
+
+define Package/libuuid
+$(call Package/util-linux/Default)
+ TITLE:=DCE compatible Universally Unique Identifier library
+ SECTION:=libs
+ CATEGORY:=Libraries
+endef
+
+define Package/libuuid/description
+ The UUID library is used to generate unique identifiers for objects
+ that may be accessible beyond the local system. This library
+ generates UUIDs compatible with those created by the Open Software
+ Foundation (OSF) Distributed Computing Environment (DCE) utility.
+endef
+
+define Package/agetty
+$(call Package/util-linux/Default)
+ TITLE:=alternative Linux getty
+ SUBMENU=Terminal
+endef
+
+define Package/agetty/description
+ agetty opens a tty port, prompts for a login name and invokes the
+ /bin/login command
+endef
+
+define Package/blkid
+$(call Package/util-linux/Default)
+ TITLE:=locate/print block device attributes
+ DEPENDS:= +libblkid
+ SUBMENU=disc
+endef
+
+define Package/blkid/description
+ The blkid program is the command-line interface to working with the libblkid
+ library.
+endef
+
+define Package/cal
+$(call Package/util-linux/Default)
+ TITLE:=display a calendar
+ DEPENDS:= +libncurses
+endef
+
+define Package/cal/description
+ cal displays a simple calendar
+endef
+
+define Package/cfdisk
+$(call Package/util-linux/Default)
+ TITLE:=display or manipulate disk partition table
+ DEPENDS:= +libblkid +libncurses
+ SUBMENU:=disc
+endef
+
+define Package/cfdisk/description
+ cfdisk is a curses-based program for partitioning any hard disk drive
+endef
+
+define Package/dmesg
+$(call Package/util-linux/Default)
+ TITLE:=print or control the kernel ring buffer
+endef
+
+define Package/dmesg/description
+ dmesg is used to examine or control the kernel ring buffer
+endef
+
+define Package/fdisk
+$(call Package/util-linux/Default)
+ TITLE:=manipulate disk partition table
+ DEPENDS:= +libblkid
+ SUBMENU=disc
+endef
+
+define Package/fdisk/description
+ a menu-driven program for creation and manipulation of partition tables
+endef
+
+define Package/findfs
+$(call Package/util-linux/Default)
+ TITLE:=find a filesystem by label or UUID
+ DEPENDS:= +libblkid
+ SUBMENU=disc
+endef
+
+define Package/findfs/description
+ findfs will search the disks in the system looking for a filesystem which has
+ a label matching label or a UUID equal to uuid
+endef
+
+define Package/flock
+$(call Package/util-linux/Default)
+ TITLE:=manage locks from shell scripts
+endef
+
+define Package/flock/description
+ manages flock locks from within shell scripts or the command line
+endef
+
+define Package/getopt
+$(call Package/util-linux/Default)
+ TITLE:=parse command options (enhanced)
+endef
+
+define Package/getopt/description
+ getopt is used to break up (parse) options in command lines for easy parsing
+ by shell procedures, and to check for legal options
+endef
+
+define Package/hwclock
+$(call Package/util-linux/Default)
+ TITLE:=query or set the hardware clock
+endef
+
+define Package/hwclock/description
+ hwclock is a tool for accessing the Hardware Clock
+endef
+
+define Package/logger
+$(call Package/util-linux/Default)
+ TITLE:=a shell command interface to the syslog system log module
+endef
+
+define Package/logger/description
+ logger makes entries in the system log, it provides a shell command interface
+ to the syslog system log module
+endef
+
+define Package/look
+$(call Package/util-linux/Default)
+ TITLE:=display lines beginning with a given string
+endef
+
+define Package/look/description
+ look utility displays any lines in file which contain string
+endef
+
+define Package/losetup
+$(call Package/util-linux/Default)
+ TITLE:=set up and control loop devices
+endef
+
+define Package/losetup/description
+ losetup is used to associate loop devices with regular files or block devices,
+ to detach loop devices and to query the status of a loop device
+endef
+
+define Package/lsblk
+$(call Package/util-linux/Default)
+ TITLE:=list block devices
+ DEPENDS:= +libblkid
+ SUBMENU=disc
+endef
+
+define Package/lsblk/description
+ lsblk lists information about all or the specified block devices
+endef
+
+define Package/mcookie
+$(call Package/util-linux/Default)
+ TITLE:=generate magic cookies for xauth
+endef
+
+define Package/mcookie/description
+ mcookie generates a 128-bit random hexadecimal number for use with the X
+ authority system
+endef
+
+define Package/mount-utils
+$(call Package/util-linux/Default)
+ TITLE:=related (u)mount utilities
+ DEPENDS+= +libmount
+endef
+
+define Package/mount-utils/description
+ contains: mount, umount, findmnt
+endef
+
+define Package/namei
+$(call Package/util-linux/Default)
+ TITLE:=follow a pathname until a terminal point is found
+endef
+
+define Package/namei/description
+ namei uses its arguments as pathnames to any type of Unix file (symlinks,
+ files, directories, and so forth)
+endef
+
+define Package/rename
+$(call Package/util-linux/Default)
+ TITLE:=rename files
+endef
+
+define Package/rename/description
+ rename will rename the specified files by replacing the first occurrence of
+ expression in their name by replacement
+endef
+
+define Package/partx-utils
+$(call Package/util-linux/Default)
+ TITLE:=inform kernel about the presence and numbering of on-disk partitions
+ DEPENDS:= +libblkid
+ SUBMENU=disc
+endef
+
+define Package/partx-utils/description
+ contains partx, addpart, delpart
+endef
+
+define Package/script-utils
+$(call Package/util-linux/Default)
+ TITLE:=make and replay typescript of terminal session
+ SUBMENU=Terminal
+endef
+
+define Package/script-utils/description
+ contains: script, scriptreplay
+endef
+
+define Package/setterm
+$(call Package/util-linux/Default)
+ TITLE:=set terminal attributes
+ DEPENDS:= +libncurses
+ SUBMENU:=Terminal
+endef
+
+define Package/setterm/description
+ setterm writes to standard output a character string that will invoke the
+ specified terminal capabilities
+endef
+
+define Package/sfdisk
+$(call Package/util-linux/Default)
+ TITLE:=partition table manipulator for Linux
+ SUBMENU=disc
+endef
+
+define Package/sfdisk/description
+ list the size of a partition, list the partitions on a device, check the
+ partitions on a device and repartition a device
+endef
+
+define Package/swap-utils
+$(call Package/util-linux/Default)
+ TITLE:=swap space management utilities
+ DEPENDS+= +libblkid
+ SUBMENU:=disc
+endef
+
+define Package/swap-utils/description
+ contains: mkswap, swaplabel, swapon, swapoff
+endef
+
+define Package/uuidd
+$(call Package/util-linux/Default)
+ TITLE:=UUID generation daemon
+ DEPENDS:= +libuuid
+endef
+
+define Package/uuidd/description
+ The uuidd daemon is used by the UUID library to generate universally unique
+ identifiers (UUIDs), especially time-based UUIDs, in a secure and
+ guaranteed-unique fashion, even in the face of large numbers of threads
+ running on different CPUs trying to grab UUIDs.
+endef
+
+define Package/uuidgen
+$(call Package/util-linux/Default)
+ TITLE:=create a new UUID value
+ DEPENDS:= +libuuid
+endef
+
+define Package/uuidgen/description
+ The uuidgen program creates (and prints) a new universally unique identifier
+ (UUID) using the libuuid library. The new UUID can reasonably be considered
+ unique among all UUIDs created on the local system, and among UUIDs created on
+ other systems in the past and in the future.
+endef
+
+define Package/wall
+$(call Package/util-linux/Default)
+ TITLE:=send a message to everybody's terminal
+ SUBMENU=Terminal
+endef
+
+define Package/wall/description
+ wall sends a message to everybody logged in with their mesg permission
+ set to yes
+endef
+
+define Package/whereis
+$(call Package/util-linux/Default)
+ TITLE:=locate the binary, source, and manual page files for a command
+endef
+
+define Package/whereis/description
+ whereis locates source/binary and manuals sections for specified files
+endef
+
+define Package/wipefs
+$(call Package/util-linux/Default)
+ TITLE:=wipe a signature from a device
+ DEPENDS:= +libblkid
+ SUBMENU:=disc
+endef
+
+define Package/wipefs/description
+ wipefs can erase filesystem, raid or partition table signatures (magic
+ strings) from the specified device to make the signature invisible for
+ libblkid.
+endef
+
+define Package/libblkid/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/libblkid/src/.libs/libblkid.so.* $(1)/usr/lib/
+endef
+
+define Package/libmount/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/libmount/src/.libs/libmount.so.* $(1)/usr/lib/
+endef
+
+define Package/libuuid/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/libuuid/src/.libs/libuuid.so.* $(1)/usr/lib/
+endef
+
+define Package/agetty/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/term-utils/agetty $(1)/sbin/
+endef
+
+define Package/blkid/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/.libs/blkid $(1)/sbin/
+endef
+
+define Package/cal/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/cal $(1)/usr/bin/
+endef
+
+define Package/cfdisk/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/fdisk/.libs/cfdisk $(1)/sbin/
+endef
+
+define Package/fdisk/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/fdisk/.libs/fdisk $(1)/sbin/
+endef
+
+define Package/findfs/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/.libs/findfs $(1)/sbin/
+endef
+
+define Package/flock/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/sys-utils/flock $(1)/usr/bin/
+endef
+
+define Package/getopt/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/getopt/getopt $(1)/usr/bin/
+endef
+
+define Package/hwclock/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/hwclock/hwclock $(1)/sbin/
+endef
+
+define Package/logger/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/logger $(1)/usr/bin/
+endef
+
+define Package/look/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/look $(1)/usr/bin/
+endef
+
+define Package/losetup/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/sys-utils/losetup $(1)/sbin/
+endef
+
+define Package/lsblk/install
+ $(INSTALL_DIR) $(1)/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/.libs/lsblk $(1)/bin/
+endef
+
+define Package/mcookie/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/mcookie $(1)/usr/bin/
+endef
+
+define Package/mount-utils/install
+ $(INSTALL_DIR) $(1)/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/sys-utils/.libs/{u,}mount $(1)/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/sys-utils/.libs/mountpoint $(1)/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/.libs/findmnt $(1)/bin/
+endef
+
+define Package/namei/install
+ $(INSTALL_DIR) $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/namei $(1)/usr/bin/
+endef
+
+define Package/rename/install
+ $(INSTALL_DIR) $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/rename $(1)/usr/bin/
+endef
+
+define Package/partx-utils/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/partx/.libs/partx $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/partx/addpart $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/partx/delpart $(1)/usr/sbin/
+endef
+
+define Package/script-utils/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/term-utils/script $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/term-utils/scriptreplay $(1)/usr/bin/
+endef
+
+define Package/setterm/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/term-utils/setterm $(1)/usr/bin/
+endef
+
+define Package/sfdisk/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/fdisk/sfdisk $(1)/sbin/
+endef
+
+define Package/swap-utils/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/disk-utils/.libs/mkswap $(1)/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/disk-utils/.libs/swaplabel $(1)/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/sys-utils/.libs/swapon $(1)/sbin/
+ ln -sf swapon $(1)/sbin/swapoff
+endef
+
+define Package/uuidd/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/.libs/uuidd $(1)/usr/sbin/
+endef
+
+define Package/uuidgen/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/.libs/uuidgen $(1)/usr/bin/
+endef
+
+define Package/wall/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/term-utils/wall $(1)/usr/bin/
+endef
+
+define Package/whereis/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/whereis $(1)/usr/bin/
+endef
+
+define Package/wipefs/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/.libs/wipefs $(1)/sbin/
+endef
+
+$(eval $(call BuildPackage,libblkid))
+$(eval $(call BuildPackage,libmount))
+$(eval $(call BuildPackage,libuuid))
+$(eval $(call BuildPackage,agetty))
+$(eval $(call BuildPackage,blkid))
+$(eval $(call BuildPackage,cal))
+$(eval $(call BuildPackage,cfdisk))
+$(eval $(call BuildPackage,dmesg))
+$(eval $(call BuildPackage,fdisk))
+$(eval $(call BuildPackage,findfs))
+$(eval $(call BuildPackage,flock))
+$(eval $(call BuildPackage,getopt))
+$(eval $(call BuildPackage,hwclock))
+$(eval $(call BuildPackage,logger))
+$(eval $(call BuildPackage,look))
+$(eval $(call BuildPackage,losetup))
+$(eval $(call BuildPackage,lsblk))
+$(eval $(call BuildPackage,mcookie))
+$(eval $(call BuildPackage,mount-utils))
+$(eval $(call BuildPackage,namei))
+$(eval $(call BuildPackage,rename))
+$(eval $(call BuildPackage,partx-utils))
+$(eval $(call BuildPackage,script-utils))
+$(eval $(call BuildPackage,setterm))
+$(eval $(call BuildPackage,sfdisk))
+$(eval $(call BuildPackage,swap-utils))
+$(eval $(call BuildPackage,uuidd))
+$(eval $(call BuildPackage,uuidgen))
+$(eval $(call BuildPackage,wall))
+$(eval $(call BuildPackage,whereis))
+$(eval $(call BuildPackage,wipefs))
diff --git a/package/util-linux/patches/000-compile.patch b/package/util-linux/patches/000-compile.patch
new file mode 100644
index 000000000..b7cc18b40
--- /dev/null
+++ b/package/util-linux/patches/000-compile.patch
@@ -0,0 +1,44 @@
+--- a/misc-utils/cal.c
++++ b/misc-utils/cal.c
+@@ -291,41 +291,6 @@ main(int argc, char **argv) {
+ }
+ #endif
+
+-/*
+- * The traditional Unix cal utility starts the week at Sunday,
+- * while ISO 8601 starts at Monday. We read the start day from
+- * the locale database, which can be overridden with the
+- * -s (Sunday) or -m (Monday) options.
+- */
+-#if HAVE_DECL__NL_TIME_WEEK_1STDAY
+- /*
+- * You need to use 2 locale variables to get the first day of the week.
+- * This is needed to support first_weekday=2 and first_workday=1 for
+- * the rare case where working days span across 2 weeks.
+- * This shell script shows the combinations and calculations involved:
+- *
+- * for LANG in en_US ru_RU fr_FR csb_PL POSIX; do
+- * printf "%s:\t%s + %s -1 = " $LANG $(locale week-1stday first_weekday)
+- * date -d"$(locale week-1stday) +$(($(locale first_weekday)-1))day" +%w
+- * done
+- *
+- * en_US: 19971130 + 1 -1 = 0 #0 = sunday
+- * ru_RU: 19971130 + 2 -1 = 1
+- * fr_FR: 19971201 + 1 -1 = 1
+- * csb_PL: 19971201 + 2 -1 = 2
+- * POSIX: 19971201 + 7 -1 = 0
+- */
+- {
+- int wfd;
+- union { unsigned int word; char *string; } val;
+- val.string = nl_langinfo(_NL_TIME_WEEK_1STDAY);
+-
+- wfd = val.word;
+- wfd = day_in_week(wfd % 100, (wfd / 100) % 100, wfd / (100 * 100));
+- weekstart = (wfd + *nl_langinfo(_NL_TIME_FIRST_WEEKDAY) - 1) % 7;
+- }
+-#endif
+-
+ yflag = 0;
+ while ((ch = getopt_long(argc, argv, "13mjsyVh", longopts, NULL)) != -1)
+ switch(ch) {
diff --git a/package/util-linux/patches/001-no-printf-alloc.patch b/package/util-linux/patches/001-no-printf-alloc.patch
new file mode 100644
index 000000000..e3f048ab3
--- /dev/null
+++ b/package/util-linux/patches/001-no-printf-alloc.patch
@@ -0,0 +1,108 @@
+for systems that don't support latest POSIX standard: %as
+
+https://bugs.gentoo.org/406303
+
+--- a/configure.ac
++++ b/configure.ac
+@@ -688,7 +688,6 @@ AC_ARG_ENABLE([libmount],
+ UL_BUILD_INIT([libmount])
+ UL_REQUIRES_LINUX([libmount])
+ UL_REQUIRES_BUILD([libmount], [libblkid])
+-UL_REQUIRES_HAVE([libmount], [scanf_alloc_modifier], [scanf string alloc modifier])
+ AM_CONDITIONAL(BUILD_LIBMOUNT, test "x$build_libmount" = xyes)
+
+ AC_SUBST([LIBMOUNT_VERSION])
+--- a/libmount/src/tab_parse.c
++++ b/libmount/src/tab_parse.c
+@@ -22,6 +22,10 @@
+ #include "pathnames.h"
+ #include "strutils.h"
+
++#ifndef HAVE_SCANF_MS_MODIFIER
++# define UL_SCNsA "%s"
++#endif
++
+ static inline char *skip_spaces(char *s)
+ {
+ assert(s);
+@@ -61,16 +65,31 @@ static int mnt_parse_table_line(struct l
+ int rc, n = 0, xrc;
+ char *src = NULL, *fstype = NULL, *optstr = NULL;
+
++#ifndef HAVE_SCANF_MS_MODIFIER
++ size_t len = strlen(s) + 1;
++ src = malloc(len);
++ fstype = malloc(len);
++ fs->target = malloc(len);
++ optstr = malloc(len);
++#endif
++
+ rc = sscanf(s, UL_SCNsA" " /* (1) source */
+ UL_SCNsA" " /* (2) target */
+ UL_SCNsA" " /* (3) FS type */
+ UL_SCNsA" " /* (4) options */
+ "%n", /* byte count */
+
++#ifdef HAVE_SCANF_MS_MODIFIER
+ &src,
+ &fs->target,
+ &fstype,
+ &optstr,
++#else
++ src,
++ fs->target,
++ fstype,
++ optstr,
++#endif
+ &n);
+ xrc = rc;
+
+@@ -136,6 +155,16 @@ static int mnt_parse_mountinfo_line(stru
+ unsigned int maj, min;
+ char *fstype = NULL, *src = NULL, *p;
+
++#ifndef HAVE_SCANF_MS_MODIFIER
++ size_t len = strlen(s) + 1;
++ fs->root = malloc(len);
++ fs->target = malloc(len);
++ fs->vfs_optstr = malloc(len);
++ fs->fs_optstr = malloc(len);
++ fstype = malloc(len);
++ src = malloc(len);
++#endif
++
+ rc = sscanf(s, "%u " /* (1) id */
+ "%u " /* (2) parent */
+ "%u:%u " /* (3) maj:min */
+@@ -147,9 +176,15 @@ static int mnt_parse_mountinfo_line(stru
+ &fs->id,
+ &fs->parent,
+ &maj, &min,
++#ifdef HAVE_SCANF_MS_MODIFIER
+ &fs->root,
+ &fs->target,
+ &fs->vfs_optstr,
++#else
++ fs->root,
++ fs->target,
++ fs->vfs_optstr,
++#endif
+ &end);
+
+ if (rc >= 7 && end > 0)
+@@ -167,9 +202,15 @@ static int mnt_parse_mountinfo_line(stru
+ UL_SCNsA" " /* (9) source */
+ UL_SCNsA, /* (10) fs options (fs specific) */
+
++#ifdef HAVE_SCANF_MS_MODIFIER
+ &fstype,
+ &src,
+ &fs->fs_optstr);
++#else
++ fstype,
++ src,
++ fs->fs_optstr);
++#endif
+
+ if (rc >= 10) {
+ fs->flags |= MNT_FS_KERNEL;
diff --git a/package/vsc73x5-ucode/Makefile b/package/vsc73x5-ucode/Makefile
new file mode 100644
index 000000000..3a0712110
--- /dev/null
+++ b/package/vsc73x5-ucode/Makefile
@@ -0,0 +1,94 @@
+#
+# Copyright (C) 2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=vsc73x5-ucode
+PKG_RELEASE:=1
+
+PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
+
+PKG_SOURCE:=vsc73x5-ucode.tar.bz2
+PKG_BUILD_DIR:=$(BUILD_DIR)/vsc73x5-ucode
+
+PKG_MD5SUM:=b32e3debcd118f263c79199a7b5afa68
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/vsc73x5-defaults
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS:=@TARGET_ar71xx
+ DEFAULT:=n
+ TITLE:=$(1)
+endef
+
+define Package/vsc73x5/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(2) $(1)/lib/firmware/$(3)
+endef
+
+define Package/vsc7385-ucode-ap83
+ $(call Package/vsc73x5-defaults,Vitesse VSC7385 microcode for the Atheros AP83 boards)
+endef
+
+define Package/vsc7385-ucode-ap83/description
+ This package contains the Atheros AP83 board specific microcode for
+ the Vitesse VSC7385 ethernet switch.
+endef
+
+define Package/vsc7385-ucode-ap83/install
+ $(call Package/vsc73x5/install,$(1),g5_Plus1_2_31_unmanaged_Atheros_v3.bin,vsc7385_ucode_ap83.bin)
+endef
+
+define Package/vsc7395-ucode-ap83
+ $(call Package/vsc73x5-defaults, Vitesse VSC7395 microcode for the Atheros AP83 boards)
+endef
+
+define Package/vsc7395-ucode-ap83/description
+ This package contains the Atheros AP83 board specific microcode for
+ the Vitesse VSC7395 ethernet switch.
+endef
+
+define Package/vsc7395-ucode-ap83/install
+ $(call Package/vsc73x5/install,$(1),g5_Plus1_2_31_unmanaged_Atheros_v4.bin,vsc7395_ucode_ap83.bin)
+endef
+
+define Package/vsc7385-ucode-pb44
+ $(call Package/vsc73x5-defaults, Vitesse VSC7395 microcode for the Atheros PB44 boards)
+endef
+
+define Package/vsc7385-ucode-pb44/description
+ This package contains the Atheros PB44 board specific microcode for
+ the Vitesse VSC7385 ethernet switch.
+endef
+
+define Package/vsc7385-ucode-pb44/install
+ $(call Package/vsc73x5/install,$(1),g5_Plus1_2_29b_unmanaged_Atheros_v5.bin,vsc7385_ucode_pb44.bin)
+endef
+
+define Package/vsc7395-ucode-pb44
+ $(call Package/vsc73x5-defaults, Vitesse VSC7395 microcode for the Atheros PB44 boards)
+endef
+
+define Package/vsc7395-ucode-pb44/description
+ This package contains the Atheros AP83 board specific microcode for
+ the Vitesse VSC7395 ethernet switch.
+endef
+
+define Package/vsc7395-ucode-pb44/install
+ $(call Package/vsc73x5/install,$(1),g5e_Plus1_2_29a_unmanaged_Atheros_v3.bin,vsc7395_ucode_pb44.bin)
+endef
+
+define Build/Compile
+
+endef
+
+$(eval $(call BuildPackage,vsc7385-ucode-ap83))
+$(eval $(call BuildPackage,vsc7395-ucode-ap83))
+$(eval $(call BuildPackage,vsc7385-ucode-pb44))
+$(eval $(call BuildPackage,vsc7395-ucode-pb44))
diff --git a/package/vsc73x5-ucode/files/Makefile b/package/vsc73x5-ucode/files/Makefile
new file mode 100644
index 000000000..550f51df7
--- /dev/null
+++ b/package/vsc73x5-ucode/files/Makefile
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+CC:=gcc
+OBJCOPY:=objcopy
+
+all: g5_Plus1_2_31_unmanaged_Atheros_v3.bin \
+ g5_Plus1_2_31_unmanaged_Atheros_v4.bin \
+ g5_Plus1_2_29b_unmanaged_Atheros_v5.bin \
+ g5e_Plus1_2_29a_unmanaged_Atheros_v3.bin
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c $^ -o $@
+
+%.bin: %.o
+ $(OBJCOPY) -O binary -j .data $^ $@
diff --git a/package/w1-gpio-custom/Makefile b/package/w1-gpio-custom/Makefile
new file mode 100644
index 000000000..bf50d1a50
--- /dev/null
+++ b/package/w1-gpio-custom/Makefile
@@ -0,0 +1,54 @@
+#
+# Copyright (C) 2008-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=w1-gpio-custom
+PKG_RELEASE:=3
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/w1-gpio-custom
+ SUBMENU:=W1 support
+ TITLE:=Custom GPIO-based 1-wire device
+ DEPENDS:=kmod-w1 +kmod-w1-master-gpio
+ FILES:=$(PKG_BUILD_DIR)/w1-gpio-custom.ko
+ KCONFIG:=
+endef
+
+define KernelPackage/w1-gpio-custom/description
+ Kernel module to register a custom w1-gpio platform device.
+endef
+
+EXTRA_KCONFIG:= \
+ CONFIG_W1_MASTER_GPIO_CUSTOM=m
+
+EXTRA_CFLAGS:= \
+ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \
+ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG))))
+
+MAKE_OPTS:= \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ SUBDIRS="$(PKG_BUILD_DIR)" \
+ EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
+ $(EXTRA_KCONFIG)
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ $(MAKE) -C "$(LINUX_DIR)" \
+ $(MAKE_OPTS) \
+ modules
+endef
+
+$(eval $(call KernelPackage,w1-gpio-custom))
+
diff --git a/package/w1-gpio-custom/src/Kconfig b/package/w1-gpio-custom/src/Kconfig
new file mode 100644
index 000000000..74b9226c5
--- /dev/null
+++ b/package/w1-gpio-custom/src/Kconfig
@@ -0,0 +1,4 @@
+config W1_MASTER_GPIO_CUSTOM
+ tristate "Custom GPIO-based W1 driver"
+ depends on GENERIC_GPIO
+ select W1_GPIO \ No newline at end of file
diff --git a/package/w1-gpio-custom/src/Makefile b/package/w1-gpio-custom/src/Makefile
new file mode 100644
index 000000000..6a527432c
--- /dev/null
+++ b/package/w1-gpio-custom/src/Makefile
@@ -0,0 +1 @@
+obj-${CONFIG_W1_MASTER_GPIO_CUSTOM} += w1-gpio-custom.o \ No newline at end of file
diff --git a/package/w1-gpio-custom/src/w1-gpio-custom.c b/package/w1-gpio-custom/src/w1-gpio-custom.c
new file mode 100644
index 000000000..96cfcabc6
--- /dev/null
+++ b/package/w1-gpio-custom/src/w1-gpio-custom.c
@@ -0,0 +1,185 @@
+/*
+ * Custom GPIO-based W1 driver
+ *
+ * Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org>
+ * Copyright (C) 2008 Bifferos <bifferos at yahoo.co.uk>
+ *
+ * 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.
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * The behaviour of this driver can be altered by setting some parameters
+ * from the insmod command line.
+ *
+ * The following parameters are adjustable:
+ *
+ * bus0 These four arguments must be arrays of
+ * bus1 3 unsigned integers as follows:
+ * bus2
+ * bus3 <id>,<pin>,<od>
+ *
+ * where:
+ *
+ * <id> ID to used as device_id for the corresponding bus (required)
+ * <sda> GPIO pin ID of data pin (required)
+ * <od> Pin is configured as open drain.
+ *
+ * See include/w1-gpio.h for more information about the parameters.
+ *
+ * If this driver is built into the kernel, you can use the following kernel
+ * command line parameters, with the same values as the corresponding module
+ * parameters listed above:
+ *
+ * w1-gpio-custom.bus0
+ * w1-gpio-custom.bus1
+ * w1-gpio-custom.bus2
+ * w1-gpio-custom.bus3
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <linux/w1-gpio.h>
+
+#define DRV_NAME "w1-gpio-custom"
+#define DRV_DESC "Custom GPIO-based W1 driver"
+#define DRV_VERSION "0.1.1"
+
+#define PFX DRV_NAME ": "
+
+#define BUS_PARAM_ID 0
+#define BUS_PARAM_PIN 1
+#define BUS_PARAM_OD 2
+
+#define BUS_PARAM_REQUIRED 3
+#define BUS_PARAM_COUNT 3
+#define BUS_COUNT_MAX 4
+
+static unsigned int bus0[BUS_PARAM_COUNT] __initdata;
+static unsigned int bus1[BUS_PARAM_COUNT] __initdata;
+static unsigned int bus2[BUS_PARAM_COUNT] __initdata;
+static unsigned int bus3[BUS_PARAM_COUNT] __initdata;
+
+static unsigned int bus_nump[BUS_COUNT_MAX] __initdata;
+
+#define BUS_PARM_DESC " config -> id,pin,od"
+
+module_param_array(bus0, uint, &bus_nump[0], 0);
+MODULE_PARM_DESC(bus0, "bus0" BUS_PARM_DESC);
+module_param_array(bus1, uint, &bus_nump[1], 0);
+MODULE_PARM_DESC(bus1, "bus1" BUS_PARM_DESC);
+module_param_array(bus2, uint, &bus_nump[2], 0);
+MODULE_PARM_DESC(bus2, "bus2" BUS_PARM_DESC);
+module_param_array(bus3, uint, &bus_nump[3], 0);
+MODULE_PARM_DESC(bus3, "bus3" BUS_PARM_DESC);
+
+static struct platform_device *devices[BUS_COUNT_MAX];
+static unsigned int nr_devices;
+
+static void w1_gpio_custom_cleanup(void)
+{
+ int i;
+
+ for (i = 0; i < nr_devices; i++)
+ if (devices[i])
+ platform_device_put(devices[i]);
+}
+
+static int __init w1_gpio_custom_add_one(unsigned int id, unsigned int *params)
+{
+ struct platform_device *pdev;
+ struct w1_gpio_platform_data pdata;
+ int err;
+
+ if (!bus_nump[id])
+ return 0;
+
+ if (bus_nump[id] < BUS_PARAM_REQUIRED) {
+ printk(KERN_ERR PFX "not enough parameters for bus%d\n", id);
+ err = -EINVAL;
+ goto err;
+ }
+
+ pdev = platform_device_alloc("w1-gpio", params[BUS_PARAM_ID]);
+ if (!pdev) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ pdata.pin = params[BUS_PARAM_PIN];
+ pdata.is_open_drain = params[BUS_PARAM_OD] ? 1:0;
+ pdata.enable_external_pullup = NULL;
+
+ err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
+ if (err)
+ goto err_put;
+
+ err = platform_device_add(pdev);
+ if (err)
+ goto err_put;
+
+ devices[nr_devices++] = pdev;
+ return 0;
+
+ err_put:
+ platform_device_put(pdev);
+ err:
+ return err;
+}
+
+static int __init w1_gpio_custom_probe(void)
+{
+ int err;
+
+ nr_devices = 0;
+ printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n");
+
+ err = w1_gpio_custom_add_one(0, bus0);
+ if (err) goto err;
+
+ err = w1_gpio_custom_add_one(1, bus1);
+ if (err) goto err;
+
+ err = w1_gpio_custom_add_one(2, bus2);
+ if (err) goto err;
+
+ err = w1_gpio_custom_add_one(3, bus3);
+ if (err) goto err;
+
+ if (!nr_devices) {
+ printk(KERN_ERR PFX "no bus parameter(s) specified\n");
+ err = -ENODEV;
+ goto err;
+ }
+
+ return 0;
+
+err:
+ w1_gpio_custom_cleanup();
+ return err;
+}
+
+#ifdef MODULE
+static int __init w1_gpio_custom_init(void)
+{
+ return w1_gpio_custom_probe();
+}
+module_init(w1_gpio_custom_init);
+
+static void __exit w1_gpio_custom_exit(void)
+{
+ w1_gpio_custom_cleanup();
+}
+module_exit(w1_gpio_custom_exit);
+#else
+subsys_initcall(w1_gpio_custom_probe);
+#endif /* MODULE*/
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Bifferos <bifferos at yahoo.co.uk >");
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_VERSION(DRV_VERSION);
diff --git a/package/wireless-tools/Makefile b/package/wireless-tools/Makefile
new file mode 100644
index 000000000..d553d4b17
--- /dev/null
+++ b/package/wireless-tools/Makefile
@@ -0,0 +1,89 @@
+#
+# Copyright (C) 2006-2009 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=wireless-tools
+PKG_VERSION:=29
+PKG_MINOR:=
+PKG_RELEASE:=5
+
+PKG_SOURCE:=wireless_tools.$(PKG_VERSION)$(PKG_MINOR).tar.gz
+PKG_SOURCE_URL:=http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux
+PKG_MD5SUM:=e06c222e186f7cc013fd272d023710cb
+TAR_OPTIONS += || true
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/wireless_tools.$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/wireless-tools/Default
+ URL:=http://hplabs.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html
+endef
+
+define Package/wireless-tools
+$(call Package/wireless-tools/Default)
+ SECTION:=net
+ CATEGORY:=Base system
+ TITLE:=Tools for manipulating Linux Wireless Extensions
+endef
+
+define Package/wireless-tools/description
+ This package contains a collection of tools for configuring wireless
+ adapters implementing the "Linux Wireless Extensions".
+endef
+
+define Package/libiw
+$(call Package/wireless-tools/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=Library for manipulating Linux Wireless Extensions
+endef
+
+define Package/libiw/description
+ This package contains a library for manipulating
+ "Linux Wireless Extensions".
+endef
+
+define Build/Compile
+ rm -rf $(PKG_INSTALL_DIR)
+ mkdir -p $(PKG_INSTALL_DIR)
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS) -I." \
+ BUILD_WE_ESSENTIAL=y \
+ LIBS="-lm -Wl,--gc-sections" \
+ libiw.so.$(PKG_VERSION) iwmulticall
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ PREFIX="$(PKG_INSTALL_DIR)" \
+ INSTALL_DIR="$(PKG_INSTALL_DIR)/usr/sbin" \
+ INSTALL_LIB="$(PKG_INSTALL_DIR)/usr/lib" \
+ install-iwmulticall
+endef
+
+define Build/InstallDev
+ mkdir -p $(1)/usr/include
+ $(CP) $(PKG_BUILD_DIR)/{iwlib,wireless}.h $(1)/usr/include/
+ mkdir -p $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/libiw.so* $(1)/usr/lib/
+ ln -sf libiw.so.$(PKG_VERSION) $(1)/usr/lib/libiw.so
+endef
+
+define Package/wireless-tools/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/iwconfig $(1)/usr/sbin/
+ ln -sf iwconfig $(1)/usr/sbin/iwlist
+ ln -sf iwconfig $(1)/usr/sbin/iwpriv
+endef
+
+define Package/libiw/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/libiw.so.* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,wireless-tools))
+$(eval $(call BuildPackage,libiw))
diff --git a/package/wireless-tools/patches/001-debian.patch b/package/wireless-tools/patches/001-debian.patch
new file mode 100644
index 000000000..e00bad279
--- /dev/null
+++ b/package/wireless-tools/patches/001-debian.patch
@@ -0,0 +1,35 @@
+--- a/iwlib.c
++++ b/iwlib.c
+@@ -667,6 +667,7 @@ iw_get_basic_config(int skfd,
+ {
+ struct iwreq wrq;
+
++ memset((char *) &wrq, 0, sizeof(struct iwreq));
+ memset((char *) info, 0, sizeof(struct wireless_config));
+
+ /* Get wireless name */
+--- a/Makefile
++++ b/Makefile
+@@ -73,8 +73,8 @@ DYNAMIC_LINK= libiw.so
+ # Install directories
+ INSTALL_DIR= $(PREFIX)/sbin/
+ INSTALL_LIB= $(PREFIX)/lib/
+-INSTALL_INC= $(PREFIX)/include/
+-INSTALL_MAN= $(PREFIX)/man/
++INSTALL_INC= $(PREFIX)/usr/include/
++INSTALL_MAN= $(PREFIX)/usr/share/man/
+
+ # Various commands
+ RM = rm -f
+@@ -102,9 +102,9 @@ ifdef BUILD_WE_ESSENTIAL
+ endif
+
+ # Other flags
+-CFLAGS=-Os -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow \
++#CFLAGS=-Os -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow \
+ -Wpointer-arith -Wcast-qual -Winline -I.
+-#CFLAGS=-O2 -W -Wall -Wstrict-prototypes -I.
++CFLAGS=-O2 -W -Wall -Wstrict-prototypes -I.
+ DEPFLAGS=-MMD
+ XCFLAGS=$(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS) $(WELIB_FLAG) $(WEDEF_FLAG)
+ PICFLAG=-fPIC
diff --git a/package/wireless-tools/patches/002-fix-iwconfig-power-argument-parsing.patch b/package/wireless-tools/patches/002-fix-iwconfig-power-argument-parsing.patch
new file mode 100644
index 000000000..2b61ef291
--- /dev/null
+++ b/package/wireless-tools/patches/002-fix-iwconfig-power-argument-parsing.patch
@@ -0,0 +1,13 @@
+--- a/iwconfig.c
++++ b/iwconfig.c
+@@ -1034,8 +1034,8 @@ set_power_info(int skfd,
+ wrq.u.power.disabled = 0;
+
+ /* Is there any value to grab ? */
+- value = strtod(args[0], &unit);
+- if(unit != args[0])
++ value = strtod(args[i], &unit);
++ if(unit != args[i])
+ {
+ struct iw_range range;
+ int flags;
diff --git a/package/wireless-tools/patches/003-we_essential_def.patch b/package/wireless-tools/patches/003-we_essential_def.patch
new file mode 100644
index 000000000..8666f3e80
--- /dev/null
+++ b/package/wireless-tools/patches/003-we_essential_def.patch
@@ -0,0 +1,359 @@
+--- a/iwlist.c
++++ b/iwlist.c
+@@ -58,7 +58,6 @@ typedef struct iw_auth_descr
+ * Maybe this should go in iwlib.c ?
+ */
+
+-#ifndef WE_ESSENTIAL
+ #define IW_ARRAY_LEN(x) (sizeof(x)/sizeof((x)[0]))
+
+ //static const struct iwmask_name iw_enc_mode_name[] = {
+@@ -161,11 +160,8 @@ static const char * iw_ie_key_mgmt_name[
+ };
+ #define IW_IE_KEY_MGMT_NUM IW_ARRAY_LEN(iw_ie_key_mgmt_name)
+
+-#endif /* WE_ESSENTIAL */
+-
+ /************************* WPA SUBROUTINES *************************/
+
+-#ifndef WE_ESSENTIAL
+ /*------------------------------------------------------------------*/
+ /*
+ * Print all names corresponding to a mask.
+@@ -431,7 +427,6 @@ iw_print_gen_ie(unsigned char * buffer,
+ offset += buffer[offset+1] + 2;
+ }
+ }
+-#endif /* WE_ESSENTIAL */
+
+ /***************************** SCANNING *****************************/
+ /*
+@@ -585,12 +580,10 @@ print_scanning_token(struct stream_descr
+ &event->u.qual, iw_range, has_range);
+ printf(" %s\n", buffer);
+ break;
+-#ifndef WE_ESSENTIAL
+ case IWEVGENIE:
+ /* Informations Elements are complex, let's do only some of them */
+ iw_print_gen_ie(event->u.data.pointer, event->u.data.length);
+ break;
+-#endif /* WE_ESSENTIAL */
+ case IWEVCUSTOM:
+ {
+ char custom[IW_CUSTOM_MAX+1];
+@@ -1302,7 +1295,6 @@ print_pm_info(int skfd,
+ return(0);
+ }
+
+-#ifndef WE_ESSENTIAL
+ /************************** TRANSMIT POWER **************************/
+
+ /*------------------------------------------------------------------*/
+@@ -1405,6 +1397,7 @@ print_txpower_info(int skfd,
+ return(0);
+ }
+
++#ifndef WE_ESSENTIAL
+ /*********************** RETRY LIMIT/LIFETIME ***********************/
+
+ /*------------------------------------------------------------------*/
+@@ -2060,8 +2053,8 @@ static const struct iwlist_entry iwlist_
+ { "encryption", print_keys_info, 0, NULL },
+ { "keys", print_keys_info, 0, NULL },
+ { "power", print_pm_info, 0, NULL },
+-#ifndef WE_ESSENTIAL
+ { "txpower", print_txpower_info, 0, NULL },
++#ifndef WE_ESSENTIAL
+ { "retry", print_retry_info, 0, NULL },
+ { "ap", print_ap_info, 0, NULL },
+ { "accesspoints", print_ap_info, 0, NULL },
+--- a/iwconfig.c
++++ b/iwconfig.c
+@@ -106,16 +106,6 @@ get_info(int skfd,
+ if(wrq.u.data.length > 1)
+ info->has_nickname = 1;
+
+- if((info->has_range) && (info->range.we_version_compiled > 9))
+- {
+- /* Get Transmit Power */
+- if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
+- {
+- info->has_txpower = 1;
+- memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam));
+- }
+- }
+-
+ /* Get sensitivity */
+ if(iw_get_ext(skfd, ifname, SIOCGIWSENS, &wrq) >= 0)
+ {
+@@ -132,6 +122,17 @@ get_info(int skfd,
+ memcpy(&(info->retry), &(wrq.u.retry), sizeof(iwparam));
+ }
+ }
++#endif /* WE_ESSENTIAL */
++
++ if((info->has_range) && (info->range.we_version_compiled > 9))
++ {
++ /* Get Transmit Power */
++ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0)
++ {
++ info->has_txpower = 1;
++ memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam));
++ }
++ }
+
+ /* Get RTS threshold */
+ if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) >= 0)
+@@ -146,7 +147,6 @@ get_info(int skfd,
+ info->has_frag = 1;
+ memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam));
+ }
+-#endif /* WE_ESSENTIAL */
+
+ return(0);
+ }
+@@ -269,7 +269,6 @@ display_info(struct wireless_info * info
+ printf("Bit Rate%c%s ", (info->bitrate.fixed ? '=' : ':'), buffer);
+ }
+
+-#ifndef WE_ESSENTIAL
+ /* Display the Transmit Power */
+ if(info->has_txpower)
+ {
+@@ -286,6 +285,7 @@ display_info(struct wireless_info * info
+ printf("Tx-Power%c%s ", (info->txpower.fixed ? '=' : ':'), buffer);
+ }
+
++#ifndef WE_ESSENTIAL
+ /* Display sensitivity */
+ if(info->has_sens)
+ {
+@@ -340,6 +340,7 @@ display_info(struct wireless_info * info
+ printf(" ");
+ tokens += 5; /* Between 3 and 5, depend on flags */
+ }
++#endif /* WE_ESSENTIAL */
+
+ /* Display the RTS threshold */
+ if(info->has_rts)
+@@ -383,7 +384,6 @@ display_info(struct wireless_info * info
+ /* Formating */
+ if(tokens > 0)
+ printf("\n ");
+-#endif /* WE_ESSENTIAL */
+
+ /* Display encryption information */
+ /* Note : we display only the "current" key, use iwlist to list all keys */
+@@ -1196,6 +1196,7 @@ set_nwid_info(int skfd,
+ /* 1 arg */
+ return(1);
+ }
++#endif /* WE_ESSENTIAL */
+
+ /*------------------------------------------------------------------*/
+ /*
+@@ -1362,6 +1363,7 @@ set_txpower_info(int skfd,
+ return(i);
+ }
+
++#ifndef WE_ESSENTIAL
+ /*------------------------------------------------------------------*/
+ /*
+ * Set Sensitivity
+@@ -1459,6 +1461,7 @@ set_retry_info(int skfd,
+ /* Var args */
+ return(i);
+ }
++#endif /* WE_ESSENTIAL */
+
+ /*------------------------------------------------------------------*/
+ /*
+@@ -1565,6 +1568,7 @@ set_frag_info(int skfd,
+ return(1);
+ }
+
++#ifndef WE_ESSENTIAL
+ /*------------------------------------------------------------------*/
+ /*
+ * Set Modulation
+@@ -1719,21 +1723,21 @@ static const struct iwconfig_entry iwcon
+ "Set Nickname", "NNN" },
+ { "nwid", set_nwid_info, 1, SIOCSIWNWID,
+ "Set NWID", "{NN|on|off}" },
+- { "ap", set_apaddr_info, 1, SIOCSIWAP,
+- "Set AP Address", "{N|off|auto}" },
+- { "txpower", set_txpower_info, 1, SIOCSIWTXPOW,
+- "Set Tx Power", "{NmW|NdBm|off|auto}" },
+ { "sens", set_sens_info, 1, SIOCSIWSENS,
+ "Set Sensitivity", "N" },
++ { "modulation", set_modulation_info, 1, SIOCGIWMODUL,
++ "Set Modulation", "{11g|11a|CCK|OFDMg|...}" },
+ { "retry", set_retry_info, 1, SIOCSIWRETRY,
+ "Set Retry Limit", "{limit N|lifetime N}" },
++#endif /* WE_ESSENTIAL */
++ { "ap", set_apaddr_info, 1, SIOCSIWAP,
++ "Set AP Address", "{N|off|auto}" },
++ { "txpower", set_txpower_info, 1, SIOCSIWTXPOW,
++ "Set Tx Power", "{NmW|NdBm|off|auto}" },
+ { "rts", set_rts_info, 1, SIOCSIWRTS,
+ "Set RTS Threshold", "{N|auto|fixed|off}" },
+ { "frag", set_frag_info, 1, SIOCSIWFRAG,
+ "Set Fragmentation Threshold", "{N|auto|fixed|off}" },
+- { "modulation", set_modulation_info, 1, SIOCGIWMODUL,
+- "Set Modulation", "{11g|11a|CCK|OFDMg|...}" },
+-#endif /* WE_ESSENTIAL */
+ { "commit", set_commit_info, 0, SIOCSIWCOMMIT,
+ "Commit changes", "" },
+ { NULL, NULL, 0, 0, NULL, NULL },
+--- a/iwmulticall.c
++++ b/iwmulticall.c
+@@ -81,7 +81,7 @@ extern int
+ #define main(args...) main_iwspy(args)
+ #include "iwspy.c"
+ #undef main
+-#endif /* WE_ESSENTIAL */
++#endif
+
+ /* Get iwpriv in there. Mandatory for HostAP and some other drivers. */
+ #define main(args...) main_iwpriv(args)
+@@ -90,12 +90,14 @@ extern int
+ #undef iw_usage
+ #undef main
+
++#ifndef WE_ESSENTIAL
+ /* Do we really need iwgetid ? Well, it's not like it's a big one */
+ #define main(args...) main_iwgetid(args)
+ #define iw_usage(args...) iwgetid_usage(args)
+ #include "iwgetid.c"
+ #undef iw_usage
+ #undef main
++#endif
+
+ /* iwevent is useless for most people, don't grab it ? */
+
+@@ -131,11 +133,13 @@ main(int argc,
+ #ifndef WE_ESSENTIAL
+ if(!strcmp(call_name, "iwspy"))
+ return(main_iwspy(argc, argv));
+-#endif /* WE_ESSENTIAL */
++#endif
+ if(!strcmp(call_name, "iwpriv"))
+ return(main_iwpriv(argc, argv));
++#ifndef WE_ESSENTIAL
+ if(!strcmp(call_name, "iwgetid"))
+ return(main_iwgetid(argc, argv));
++#endif
+
+ /* Uh oh... Not supposed to come here. */
+ printf("iwmulticall : you are not supposed to call me this way...\n");
+--- a/iwlib.c
++++ b/iwlib.c
+@@ -113,6 +113,7 @@ const struct iw_modul_descr iw_modul_lis
+ { IW_MODUL_11A, "11a", "IEEE 802.11a (5 GHz, up to 54 Mb/s)" },
+ { IW_MODUL_11B, "11b", "IEEE 802.11b (2.4 GHz, up to 11 Mb/s)" },
+
++#ifndef WE_ESSENTIAL
+ /* Proprietary aggregates */
+ { IW_MODUL_TURBO | IW_MODUL_11A, "turboa",
+ "Atheros turbo mode at 5 GHz (up to 108 Mb/s)" },
+@@ -120,6 +121,7 @@ const struct iw_modul_descr iw_modul_lis
+ "Atheros turbo mode at 2.4 GHz (up to 108 Mb/s)" },
+ { IW_MODUL_PBCC | IW_MODUL_11B, "11+",
+ "TI 802.11+ (2.4 GHz, up to 22 Mb/s)" },
++#endif
+
+ /* Individual modulations */
+ { IW_MODUL_OFDM_G, "OFDMg",
+@@ -129,6 +131,7 @@ const struct iw_modul_descr iw_modul_lis
+ { IW_MODUL_DS, "DS", "802.11 Direct Sequence (2.4 GHz, up to 2 Mb/s)" },
+ { IW_MODUL_FH, "FH", "802.11 Frequency Hopping (2,4 GHz, up to 2 Mb/s)" },
+
++#ifndef WE_ESSENTIAL
+ /* Proprietary modulations */
+ { IW_MODUL_TURBO, "turbo",
+ "Atheros turbo mode, channel bonding (up to 108 Mb/s)" },
+@@ -136,6 +139,7 @@ const struct iw_modul_descr iw_modul_lis
+ "TI 802.11+ higher rates (2.4 GHz, up to 22 Mb/s)" },
+ { IW_MODUL_CUSTOM, "custom",
+ "Driver specific modulation (check driver documentation)" },
++#endif
+ };
+
+ /* Disable runtime version warning in iw_get_range_info() */
+@@ -440,6 +444,7 @@ iw_print_version_info(const char * tooln
+ return -1;
+ }
+
++#ifndef WE_ESSENTIAL
+ /* Information about the tools themselves */
+ if(toolname != NULL)
+ printf("%-8.16s Wireless-Tools version %d\n", toolname, WT_VERSION);
+@@ -452,6 +457,7 @@ iw_print_version_info(const char * tooln
+ if(we_kernel_version > 15)
+ printf("Kernel Currently compiled with Wireless Extension v%d.\n\n",
+ we_kernel_version);
++#endif
+
+ /* Version for each device */
+ iw_enum_devices(skfd, &print_iface_version_info, NULL, 0);
+@@ -501,6 +507,7 @@ iw_get_range_info(int skfd,
+ /* Copy stuff at the right place, ignore extra */
+ memcpy((char *) range, buffer, sizeof(iwrange));
+ }
++#ifndef WE_ESSENTIAL
+ else
+ {
+ /* Zero unknown fields */
+@@ -574,6 +581,7 @@ iw_get_range_info(int skfd,
+ * If the driver source has not been updated to the latest, it doesn't
+ * matter because the new fields are set to zero */
+ }
++#endif
+
+ /* Don't complain twice.
+ * In theory, the test apply to each individual driver, but usually
+@@ -1542,6 +1550,7 @@ iw_print_key(char * buffer,
+ }
+ }
+
++#ifndef WE_ESSENTIAL
+ /*------------------------------------------------------------------*/
+ /*
+ * Convert a passphrase into a key
+@@ -1556,6 +1565,7 @@ iw_pass_key(const char * input,
+ fprintf(stderr, "Error: Passphrase not implemented\n");
+ return(-1);
+ }
++#endif
+
+ /*------------------------------------------------------------------*/
+ /*
+@@ -1578,12 +1588,14 @@ iw_in_key(const char * input,
+ keylen = IW_ENCODING_TOKEN_MAX;
+ memcpy(key, input + 2, keylen);
+ }
++#ifndef WE_ESSENTIAL
+ else
+ if(!strncmp(input, "p:", 2))
+ {
+ /* Second case : as a passphrase (PrismII cards) */
+ return(iw_pass_key(input + 2, key)); /* skip "p:" */
+ }
++#endif
+ else
+ {
+ const char * p;
+--- a/Makefile
++++ b/Makefile
+@@ -195,9 +195,9 @@ install-iwmulticall:: iwmulticall
+ install -m 755 $< $(INSTALL_DIR)/iwconfig
+ ( cd $(INSTALL_DIR) ; \
+ ln -f -s iwconfig iwlist ; \
+- ln -f -s iwconfig iwspy ; \
++ $(if $(BUILD_WE_ESSENTIAL),,ln -f -s iwconfig iwspy ;) \
+ ln -f -s iwconfig iwpriv ; \
+- ln -f -s iwconfig iwgetid )
++ $(if $(BUILD_WE_ESSENTIAL),,ln -f -s iwconfig iwgetid ) )
+
+ clean::
+ $(RM_CMD)
diff --git a/package/wireless-tools/patches/004-increase_iwlist_buffer.patch b/package/wireless-tools/patches/004-increase_iwlist_buffer.patch
new file mode 100644
index 000000000..f2fdb124e
--- /dev/null
+++ b/package/wireless-tools/patches/004-increase_iwlist_buffer.patch
@@ -0,0 +1,46 @@
+--- a/iwlist.c
++++ b/iwlist.c
+@@ -792,7 +792,8 @@ print_scanning_info(int skfd,
+ if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0)
+ {
+ /* Check if buffer was too small (WE-17 only) */
+- if((errno == E2BIG) && (range.we_version_compiled > 16))
++ if((errno == E2BIG) && (range.we_version_compiled > 16)
++ && (buflen < 0xFFFF))
+ {
+ /* Some driver may return very large scan results, either
+ * because there are many cells, or because they have many
+@@ -808,6 +809,10 @@ print_scanning_info(int skfd,
+ else
+ buflen *= 2;
+
++ /* wrq.u.data.length is 16 bits so max size is 65535 */
++ if(buflen > 0xFFFF)
++ buflen = 0xFFFF;
++
+ /* Try again */
+ goto realloc;
+ }
+@@ -2152,6 +2157,7 @@ main(int argc,
+ char **args; /* Command arguments */
+ int count; /* Number of arguments */
+ const iwlist_cmd *iwcmd;
++ int goterr = 0;
+
+ if(argc < 2)
+ iw_usage(1);
+@@ -2199,12 +2205,12 @@ main(int argc,
+
+ /* do the actual work */
+ if (dev)
+- (*iwcmd->fn)(skfd, dev, args, count);
++ goterr = (*iwcmd->fn)(skfd, dev, args, count);
+ else
+ iw_enum_devices(skfd, iwcmd->fn, args, count);
+
+ /* Close the socket. */
+ iw_sockets_close(skfd);
+
+- return 0;
++ return goterr;
+ }
diff --git a/package/wprobe/Makefile b/package/wprobe/Makefile
new file mode 100644
index 000000000..de1ba6d63
--- /dev/null
+++ b/package/wprobe/Makefile
@@ -0,0 +1,143 @@
+#
+# Copyright (C) 2008-2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=wprobe
+PKG_VERSION:=1
+PKG_RELEASE:=1
+
+PKG_BUILD_DEPENDS:=PACKAGE_wprobe-export:libipfix
+
+PKG_CONFIG_DEPENDS = \
+ CONFIG_PACKAGE_kmod-wprobe \
+ CONFIG_PACKAGE_wprobe-export \
+
+include $(INCLUDE_DIR)/package.mk
+
+# XXX: build failure on cris
+# wprobe-lib.c:145: error: 'packed' attribute ignored for field of type 'struct <anonymous>'
+# wprobe-lib.c:149: error: 'packed' attribute ignored for field of type 'struct <anonymous>'
+
+define Package/wprobe/Default
+ DEPENDS:=@(!(TARGET_ps3||TARGET_pxcab||cris)||BROKEN)
+endef
+
+define KernelPackage/wprobe
+$(call Package/wprobe/Default)
+ SUBMENU:=Network Support
+ TITLE:=Wireless driver probe infrastructure
+ MAINTAINER:=Felix Fietkau <nbd@openwrt.org>
+ FILES:= \
+ $(PKG_BUILD_DIR)/kernel/wprobe.ko
+ AUTOLOAD:=$(call AutoLoad,01,wprobe)
+endef
+
+define KernelPackage/wprobe/description
+ A module that exports measurement data from wireless driver to user space
+endef
+
+define Package/wprobe-util
+$(call Package/wprobe/Default)
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS+=+kmod-wprobe +libnl-tiny
+ TITLE:=Wireless measurement utility
+endef
+
+define Package/wprobe-util/description
+ wprobe-util uses the wprobe kernel module to query
+ wireless driver measurement data from an interface
+endef
+
+define Package/wprobe-export
+$(call Package/wprobe/Default)
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS+=+wprobe-util
+ TITLE:=Wireless measurement data exporter
+endef
+
+define Package/wprobe-export/description
+ wprobe-export uses the wprobe kernel module to export
+ wireless driver measurement data via the IPFIX protocol
+endef
+
+define Package/wprobe-export/conffiles
+/etc/config/wprobe
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) src/* $(PKG_BUILD_DIR)/
+endef
+
+TARGET_CPPFLAGS := \
+ -D_GNU_SOURCE \
+ -I$(STAGING_DIR)/usr/include/libnl-tiny \
+ $(TARGET_CPPFLAGS)
+
+ifdef CONFIG_PACKAGE_kmod-wprobe
+ define Build/Compile/kmod
+ $(MAKE) -C $(LINUX_DIR) \
+ CROSS_COMPILE="$(KERNEL_CROSS)" \
+ ARCH="$(LINUX_KARCH)" \
+ SUBDIRS="$(PKG_BUILD_DIR)/kernel" \
+ KERNELDIR=$(LINUX_DIR) \
+ CC="$(TARGET_CC)" \
+ EXTRA_CFLAGS="-I$(PKG_BUILD_DIR)/kernel" \
+ modules
+ endef
+endif
+
+define Build/Compile/lib
+ $(MAKE) -C $(PKG_BUILD_DIR)/user \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ CPPFLAGS="$(TARGET_CPPFLAGS) -I$(PKG_BUILD_DIR)/kernel" \
+ LDFLAGS="$(TARGET_LDFLAGS)" \
+ HOST_OS=Linux \
+ LIBNL="-lnl-tiny"
+endef
+
+ifdef CONFIG_PACKAGE_wprobe-export
+ define Build/Compile/exporter
+ $(MAKE) -C $(PKG_BUILD_DIR)/exporter \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ CPPFLAGS="$(TARGET_CPPFLAGS) -I$(PKG_BUILD_DIR)/kernel -I$(PKG_BUILD_DIR)/user" \
+ LDFLAGS="$(TARGET_LDFLAGS)" \
+ LIBS="$(PKG_BUILD_DIR)/user/libwprobe.a $(STAGING_DIR)/usr/lib/libipfix.a $(STAGING_DIR)/usr/lib/libipfixmisc.a -lnl-tiny -lm"
+ endef
+endif
+
+define Build/Compile
+ $(Build/Compile/kmod)
+ $(Build/Compile/lib)
+ $(Build/Compile/exporter)
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include/wprobe
+ $(CP) $(PKG_BUILD_DIR)/kernel/linux $(1)/usr/include/wprobe
+endef
+
+define Package/wprobe-util/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/user/wprobe-util $(1)/sbin/
+endef
+
+define Package/wprobe-export/install
+ $(INSTALL_DIR) $(1)/sbin $(1)/etc/init.d $(1)/etc/config
+ $(INSTALL_BIN) ./files/wprobe.init $(1)/etc/init.d/wprobe
+ $(INSTALL_BIN) ./files/wprobe.config $(1)/etc/config/wprobe
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/exporter/wprobe-export $(1)/sbin/
+endef
+
+$(eval $(call KernelPackage,wprobe))
+$(eval $(call BuildPackage,wprobe-util))
+$(eval $(call BuildPackage,wprobe-export))
diff --git a/package/wprobe/files/wprobe.config b/package/wprobe/files/wprobe.config
new file mode 100644
index 000000000..63518ef6e
--- /dev/null
+++ b/package/wprobe/files/wprobe.config
@@ -0,0 +1,10 @@
+config export
+ # uncomment this line to enable ipfix export:
+ # option type ipfix
+ option ifname ath0
+ option host ipfix-col
+ option proto tcp
+
+# enable public wprobe protocol access
+config export
+ option type wprobe
diff --git a/package/wprobe/files/wprobe.init b/package/wprobe/files/wprobe.init
new file mode 100755
index 000000000..b35246d42
--- /dev/null
+++ b/package/wprobe/files/wprobe.init
@@ -0,0 +1,72 @@
+#!/bin/sh /etc/rc.common
+START=90
+EXPORTER=/sbin/wprobe-export
+UTIL=/sbin/wprobe-util
+
+wprobe_ssd() {
+ local cmd="$1"; shift
+ local type="$1"; shift
+ local app="$1"; shift
+ start-stop-daemon "$cmd" -p "/var/run/wprobe-$type.pid" -b ${app:+-x "$app"} -m -- "$@"
+}
+
+stop_wprobe() {
+ local type="$1"
+ [ -f "/var/run/wprobe-$type.pid" ] && wprobe_ssd -K "$type"
+ rm -f "/var/run/wprobe-$type.pid"
+}
+
+config_wprobe() {
+ config_get ifname "$cfg" ifname
+ config_get interval "$cfg" interval
+ [ -n "$interval" ] || interval=100
+ $UTIL "$ifname" -i "$interval" 2>/dev/null >/dev/null
+}
+
+start_proxy() {
+ config_get port "$cfg" port
+ wprobe_ssd -S proxy "$UTIL" -P -p "${port:-17990}"
+}
+
+start_ipfix() {
+ local cfg="$1"
+ config_get ifname "$cfg" ifname
+ config_get host "$cfg" host
+ config_get port "$cfg" port
+ config_get proto "$cfg" proto
+ case "$proto" in
+ sctp) proto="-s";;
+ tcp) proto="-t";;
+ udp) proto="-u";;
+ *) proto="-t";;
+ esac
+ [ -z "$ifname" -o -z "$host" ] && {
+ echo "wprobe-export: missing host or interface name in config $cfg"
+ return
+ }
+ config_wprobe "$cfg"
+ wprobe_ssd -S "export-$cfg" "$EXPORTER" "$proto" -i "$ifname" -c "$host" -p "${port:-4739}"
+}
+
+start_export() {
+ local cfg="$1"
+ config_get export_type "$cfg" type
+ case "$export_type" in
+ ipfix) [ -x "$EXPORTER" ] && start_ipfix "$cfg";;
+ wprobe) start_proxy "$cfg";;
+ esac
+}
+
+stop() {
+ for f in /var/run/wprobe-*.pid; do
+ CFG="${f%%.pid}"
+ CFG="${CFG##/var/run/wprobe-}"
+ stop_wprobe "$CFG"
+ done
+}
+
+start() {
+ config_load wprobe
+ config_foreach config_wprobe interface
+ config_foreach start_export export
+}
diff --git a/package/wprobe/src/Makefile.inc b/package/wprobe/src/Makefile.inc
new file mode 100644
index 000000000..5044c0a55
--- /dev/null
+++ b/package/wprobe/src/Makefile.inc
@@ -0,0 +1,12 @@
+HOST_OS=$(shell uname)
+
+CC=gcc
+AR=ar
+RANLIB=ranlib
+
+WFLAGS = -Wall -Werror -Wno-format
+CFLAGS?=-O2
+CPPFLAGS=
+LDFLAGS=
+LIBS=
+
diff --git a/package/wprobe/src/exporter/Makefile b/package/wprobe/src/exporter/Makefile
new file mode 100644
index 000000000..9f8150729
--- /dev/null
+++ b/package/wprobe/src/exporter/Makefile
@@ -0,0 +1,5 @@
+include ../Makefile.inc
+CPPFLAGS += -I../kernel -I../user
+
+wprobe-export: wprobe-export.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
diff --git a/package/wprobe/src/exporter/wprobe-export.c b/package/wprobe/src/exporter/wprobe-export.c
new file mode 100644
index 000000000..a0e52e2f4
--- /dev/null
+++ b/package/wprobe/src/exporter/wprobe-export.c
@@ -0,0 +1,304 @@
+/*
+** exporter.c - example exporter
+**
+** Copyright Fraunhofer FOKUS
+**
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <ipfix_def.h>
+#include <ipfix_def_fokus.h>
+#include <ipfix_fields_fokus.h>
+
+#include <ipfix.h>
+#include <mlog.h>
+#include <wprobe.h>
+#include <stdbool.h>
+
+static ipfix_datarecord_t g_data = { NULL, NULL, 0 };
+static int do_close = 0;
+
+struct wprobe_mapping {
+ int id;
+ bool counter;
+ const char *wprobe_id;
+ struct wprobe_value *val;
+};
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(_array) (sizeof(_array) / sizeof((_array)[0]))
+#endif
+
+#define WMAP(_id, _name, ...) \
+ { \
+ .counter = false, \
+ .id = IPFIX_FT_WPROBE_##_id##_N, \
+ .wprobe_id = _name \
+ , ## __VA_ARGS__ \
+ }
+
+#define WMAP_COUNTER(_id, _name, ...) \
+ { \
+ .counter = true, \
+ .id = IPFIX_FT_WPROBE_##_id, \
+ .wprobe_id = _name \
+ , ## __VA_ARGS__ \
+ }
+
+
+#define WPROBE_OFFSET 2
+
+static struct wprobe_mapping map_globals[] = {
+ WMAP(NOISE, "noise"),
+ WMAP(PHY_BUSY, "phy_busy"),
+ WMAP(PHY_RX, "phy_rx"),
+ WMAP(PHY_TX, "phy_tx"),
+ WMAP_COUNTER(FRAMES, "frames"),
+ WMAP_COUNTER(PROBEREQ, "probereq"),
+};
+
+static struct wprobe_mapping map_perlink[] = {
+ WMAP(IEEE_TX_RATE, "tx_rate"),
+ WMAP(IEEE_RX_RATE, "rx_rate"),
+ WMAP(RSSI, "rssi"),
+ WMAP(SIGNAL, "signal"),
+ WMAP(RETRANSMIT_200, "retransmit_200"),
+ WMAP(RETRANSMIT_400, "retransmit_400"),
+ WMAP(RETRANSMIT_800, "retransmit_800"),
+ WMAP(RETRANSMIT_1600, "retransmit_1600"),
+};
+
+static unsigned char link_local[6];
+static char link_default[6];
+static int nfields = 0;
+
+#define FOKUS_USERID 12325
+
+static void
+match_template(struct wprobe_mapping *map, int n, struct list_head *list)
+{
+ struct wprobe_attribute *attr;
+ int i, j, last = -1;
+
+ list_for_each_entry(attr, list, list) {
+ for (i = 0; i < n; i++) {
+ j = (last + 1 + i) % n;
+ if (!strcmp(attr->name, map[j].wprobe_id))
+ goto found;
+ }
+ continue;
+found:
+ last = j;
+ map[j].val = &attr->val;
+ memset(&attr->val, 0, sizeof(attr->val));
+ nfields++;
+ }
+}
+
+/* name: export_ipfix_get_template()
+ */
+static ipfix_template_t *
+prepare_template(ipfix_t *handle)
+{
+ ipfix_template_t *t = NULL;
+ int size = 3 * nfields + WPROBE_OFFSET;
+ int i;
+
+ if (ipfix_new_data_template( handle, &t, size) < 0) {
+ mlogf( 0, "ipfix_new_template() failed: %s\n", strerror(errno) );
+ exit(1);
+ }
+
+ ipfix_add_field(handle, t, 0, IPFIX_FT_SOURCEMACADDRESS, 6);
+ ipfix_add_field(handle, t, 0, IPFIX_FT_DESTINATIONMACADDRESS, 6);
+
+ g_data.lens = calloc(size, sizeof(g_data.lens[0]));
+ g_data.lens[0] = 6;
+ g_data.lens[1] = 6;
+ for (i = WPROBE_OFFSET; i < size; i++)
+ g_data.lens[i] = 4;
+
+ g_data.addrs = calloc(size, sizeof(g_data.addrs[0]));
+ g_data.addrs[0] = link_local;
+ g_data.maxfields = WPROBE_OFFSET;
+ return t;
+}
+
+static void
+add_template_fields(ipfix_t *handle, ipfix_template_t *t, struct wprobe_mapping *map, int n)
+{
+ int f = g_data.maxfields;
+ int i;
+
+ for (i = 0; i < n; i++) {
+ if (!map[i].val)
+ continue;
+
+ if (map[i].counter)
+ g_data.addrs[f++] = &map[i].val->U32;
+ else
+ g_data.addrs[f++] = &map[i].val->n;
+
+ if (ipfix_add_field( handle, t, FOKUS_USERID, map[i].id + 0, 4) < 0)
+ exit(1);
+
+ if (map[i].counter)
+ continue;
+
+ g_data.lens[f] = 8;
+ g_data.addrs[f++] = &map[i].val->s;
+
+ g_data.lens[f] = 8;
+ g_data.addrs[f++] = &map[i].val->ss;
+ if (ipfix_add_field( handle, t, FOKUS_USERID, map[i].id + 1, 8) < 0)
+ exit(1);
+ if (ipfix_add_field( handle, t, FOKUS_USERID, map[i].id + 2, 8) < 0)
+ exit(1);
+ }
+ g_data.maxfields = f;
+}
+
+static void
+wprobe_dump_data(ipfix_t *ipfixh, ipfix_template_t *ipfixt, struct wprobe_iface *dev)
+{
+ struct wprobe_link *link;
+
+ wprobe_update_links(dev);
+ wprobe_request_data(dev, NULL);
+ if (list_empty(&dev->links)) {
+ g_data.addrs[1] = link_default;
+ ipfix_export_array(ipfixh, ipfixt, g_data.maxfields, g_data.addrs, g_data.lens);
+ ipfix_export_flush(ipfixh);
+ }
+ list_for_each_entry(link, &dev->links, list) {
+ g_data.addrs[1] = link->addr;
+ wprobe_request_data(dev, link->addr);
+ ipfix_export_array(ipfixh, ipfixt, g_data.maxfields, g_data.addrs, g_data.lens);
+ ipfix_export_flush(ipfixh);
+ }
+}
+
+int main ( int argc, char **argv )
+{
+ struct wprobe_iface *dev = NULL;
+ ipfix_template_t *ipfixt = NULL;
+ ipfix_t *ipfixh = NULL;
+ int protocol = IPFIX_PROTO_TCP;
+ char *chost = NULL;
+ char *ifname = NULL;
+ int sourceid = 12345;
+ int port = IPFIX_PORTNO;
+ int verbose_level = 0;
+ int opt, i = 10;
+ char *err = NULL;
+
+ while ((opt = getopt(argc, argv, "hi:c:p:vstu")) != EOF) {
+ switch (opt) {
+ case 'p':
+ if ((port=atoi(optarg)) <0) {
+ fprintf( stderr, "Invalid -p argument!\n" );
+ exit(1);
+ }
+ break;
+ case 'i':
+ ifname = optarg;
+ break;
+ case 'c':
+ chost = optarg;
+ break;
+
+ case 's':
+ protocol = IPFIX_PROTO_SCTP;
+ break;
+
+ case 't':
+ protocol = IPFIX_PROTO_TCP;
+ break;
+
+ case 'u':
+ protocol = IPFIX_PROTO_UDP;
+ break;
+
+ case 'v':
+ verbose_level ++;
+ break;
+
+ case 'h':
+ default:
+ fprintf(stderr, "usage: %s [-hstuv] -i <interface> -c <collector> [-p portno]\n"
+ " -h this help\n"
+ " -i <interface> wprobe interface\n"
+ " -c <collector> collector address\n"
+ " -p <portno> collector port number (default=%d)\n"
+ " -s send data via SCTP\n"
+ " -t send data via TCP (default)\n"
+ " -u send data via UDP\n"
+ " -v increase verbose level\n\n",
+ argv[0], IPFIX_PORTNO );
+ exit(1);
+ }
+ }
+
+ if (!ifname) {
+ fprintf(stderr, "No interface specified\n");
+ return -1;
+ }
+
+ if (!chost) {
+ fprintf(stderr, "No collector specified\n");
+ return -1;
+ }
+
+ dev = wprobe_get_auto(ifname, &err);
+ if (!dev || (list_empty(&dev->global_attr) && list_empty(&dev->link_attr))) {
+ fprintf(stderr, "Cannot connect to wprobe on interface '%s': %s\n", ifname, (err ? err : "Unknown error"));
+ return -1;
+ }
+
+ match_template(map_globals, ARRAY_SIZE(map_globals), &dev->global_attr);
+ match_template(map_perlink, ARRAY_SIZE(map_perlink), &dev->link_attr);
+ if (nfields == 0) {
+ fprintf(stderr, "No usable attributes found\n");
+ return -1;
+ }
+
+ mlog_set_vlevel( verbose_level );
+ if (ipfix_init() < 0) {
+ fprintf( stderr, "cannot init ipfix module: %s\n", strerror(errno) );
+ exit(1);
+ }
+
+ ipfix_add_vendor_information_elements(ipfix_ft_fokus);
+ if (ipfix_open(&ipfixh, sourceid, IPFIX_VERSION) < 0) {
+ fprintf( stderr, "ipfix_open() failed: %s\n", strerror(errno) );
+ exit(1);
+ }
+
+ if (ipfix_add_collector( ipfixh, chost, port, protocol ) < 0) {
+ fprintf( stderr, "ipfix_add_collector(%s,%d) failed: %s\n",
+ chost, port, strerror(errno));
+ exit(1);
+ }
+
+ fprintf(stderr, "Local link address: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ link_local[0], link_local[1], link_local[2],
+ link_local[3], link_local[4], link_local[5]);
+
+ ipfixt = prepare_template(ipfixh);
+ add_template_fields(ipfixh, ipfixt, map_globals, ARRAY_SIZE(map_globals));
+ add_template_fields(ipfixh, ipfixt, map_perlink, ARRAY_SIZE(map_perlink));
+
+ while (!do_close) {
+ sleep(1);
+ wprobe_dump_data(ipfixh, ipfixt, dev);
+ }
+
+ ipfix_delete_template( ipfixh, ipfixt );
+ ipfix_close( ipfixh );
+ ipfix_cleanup();
+ exit(0);
+}
diff --git a/package/wprobe/src/exporter/wprobe-export.h b/package/wprobe/src/exporter/wprobe-export.h
new file mode 100644
index 000000000..89da9e86e
--- /dev/null
+++ b/package/wprobe/src/exporter/wprobe-export.h
@@ -0,0 +1,34 @@
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+/**
+ * struct wprobe_value: data structure for attribute values
+ * see kernel api netlink attributes for more information
+ */
+struct wprobe_value {
+ /* attribute value */
+ union data {
+ const char *STRING;
+ uint8_t U8;
+ uint16_t U16;
+ uint32_t U32;
+ uint64_t U64;
+ int8_t S8;
+ int16_t S16;
+ int32_t S32;
+ int64_t S64;
+ } data;
+ /* statistics */
+ int64_t s, ss;
+ double avg, stdev;
+ unsigned int n;
+ void *usedata; /* Pointer to used data.something */
+};
+
+struct exporter_data {
+ int id; /* ipfix id */
+ int userid; /* focus or global */
+ int size; /* size in byte*/
+ struct wprobe_value val;
+};
diff --git a/package/wprobe/src/filter/README.txt b/package/wprobe/src/filter/README.txt
new file mode 100644
index 000000000..6fa265e4f
--- /dev/null
+++ b/package/wprobe/src/filter/README.txt
@@ -0,0 +1 @@
+To compile pfc you need at least libpcap version 1.0, as it requires proper radiotap header support
diff --git a/package/wprobe/src/filter/gen_filter.pl b/package/wprobe/src/filter/gen_filter.pl
new file mode 100755
index 000000000..f03f477a4
--- /dev/null
+++ b/package/wprobe/src/filter/gen_filter.pl
@@ -0,0 +1,63 @@
+#!/usr/bin/perl
+use strict;
+
+# helpers for custom packet format
+# bytes 0-7 are used by a dummy radiotap header
+my $WLAN_LEN = "radio[8:2]";
+my $SNR = "radio[10:1]";
+my $DEFAULT = undef;
+
+my $MAGIC = "WPFF";
+my $VERSION = 1; # filter binary format version
+my $HDRLEN = 3; # assumed storage space for custom fields
+
+my $output = "filter.bin";
+my $config = {
+ "packetsize" => [
+ [ "small", "$WLAN_LEN < 250" ],
+ [ "medium", "$WLAN_LEN < 800" ],
+ [ "big", $DEFAULT ],
+ ],
+ "snr" => [
+ [ "low", "$SNR < 10" ],
+ [ "medium", "$SNR < 20" ],
+ [ "high", $DEFAULT ],
+ ],
+ "type" => [
+ [ "beacon", "type mgt subtype beacon" ],
+ [ "data", "type data subtype data" ],
+ [ "qosdata", "type data subtype qos-data" ],
+ [ "other", "$DEFAULT" ]
+ ]
+};
+
+sub escape_q($) {
+ my $str = shift;
+ $str =~ s/'/'\\''/g;
+ return $str;
+}
+
+my $GROUPS = scalar(keys %$config);
+open OUTPUT, ">$output" or die "Cannot open output file: $!\n";
+print OUTPUT pack("a4CCn", $MAGIC, $VERSION, $HDRLEN, $GROUPS);
+
+foreach my $groupname (keys %$config) {
+ my $default = 0;
+ my $group = $config->{$groupname};
+ print OUTPUT pack("a32N", $groupname, scalar(@$group));
+ foreach my $filter (@$group) {
+ if (!$filter->[1]) {
+ $default > 0 and print "Cannot add more than one default filter per group: $groupname -> ".$filter->[0]."\n";
+ print OUTPUT pack("a32N", $filter->[0], 0);
+ $default++;
+ } else {
+ open FILTER, "./pfc '".escape_q($filter->[0])."' '".escape_q($filter->[1])."' |"
+ or die "Failed to run filter command for '".$filter->[0]."': $!\n";
+ while (<FILTER>) {
+ print OUTPUT $_;
+ }
+ close FILTER;
+ $? and die "Filter '".$filter->[0]."' did not compile.\n";
+ }
+ }
+}
diff --git a/package/wprobe/src/filter/pfc.c b/package/wprobe/src/filter/pfc.c
new file mode 100644
index 000000000..76fb1412a
--- /dev/null
+++ b/package/wprobe/src/filter/pfc.c
@@ -0,0 +1,58 @@
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <pcap.h>
+#include <pcap-bpf.h>
+
+struct wprobe_filter_hdr {
+ char name[32];
+ uint32_t len;
+} hdr;
+
+int main (int argc, char ** argv)
+{
+ struct bpf_program filter;
+ pcap_t *pc;
+ int i;
+
+ if (argc != 3)
+ {
+ fprintf(stderr, "Usage: %s <name> <expression>\n", argv[0]);
+ return 1;
+ }
+
+ pc = pcap_open_dead(DLT_IEEE802_11_RADIO, 256);
+ if (pcap_compile(pc, &filter, argv[2], 1, 0) != 0)
+ {
+ pcap_perror(pc, argv[0]);
+ exit(1);
+ }
+
+ /* fix up for linux */
+ for (i = 0; i < filter.bf_len; i++) {
+ struct bpf_insn *bi = &filter.bf_insns[i];
+ switch(BPF_CLASS(bi->code)) {
+ case BPF_RET:
+ if (BPF_MODE(bi->code) == BPF_K) {
+ if (bi->k != 0)
+ bi->k = 65535;
+ }
+ break;
+ }
+ bi->code = ntohs(bi->code);
+ bi->k = ntohl(bi->k);
+ }
+
+ memset(&hdr, 0, sizeof(hdr));
+ strncpy(hdr.name, argv[1], sizeof(hdr.name));
+ hdr.len = htonl(filter.bf_len);
+ fwrite(&hdr, sizeof(hdr), 1, stdout);
+ fwrite(filter.bf_insns, 8, filter.bf_len, stdout);
+ fflush(stdout);
+
+ return 0;
+}
diff --git a/package/wprobe/src/kernel/Makefile b/package/wprobe/src/kernel/Makefile
new file mode 100644
index 000000000..2a9875311
--- /dev/null
+++ b/package/wprobe/src/kernel/Makefile
@@ -0,0 +1,5 @@
+EXTRA_CFLAGS += -I.
+
+obj-m := wprobe.o wprobe-dummy.o
+
+wprobe-objs := wprobe-core.o
diff --git a/package/wprobe/src/kernel/linux/wprobe.h b/package/wprobe/src/kernel/linux/wprobe.h
new file mode 100644
index 000000000..901daf3d1
--- /dev/null
+++ b/package/wprobe/src/kernel/linux/wprobe.h
@@ -0,0 +1,397 @@
+/*
+ * wprobe.h: API for the wireless probe interface
+ * Copyright (C) 2008-2009 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+#ifndef __WPROBE_H
+#define __WPROBE_H
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/if_ether.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/filter.h>
+#include <net/genetlink.h>
+#endif
+
+/**
+ * enum wprobe_attr: netlink attribute list
+ *
+ * @WPROBE_ATTR_UNSPEC: unused
+ *
+ * @WPROBE_ATTR_INTERFACE: interface name to process query on (NLA_STRING)
+ * @WPROBE_ATTR_MAC: mac address (used for wireless links) (NLA_STRING)
+ * @WPROBE_ATTR_FLAGS: interface/link/attribute flags (see enum wprobe_flags) (NLA_U32)a
+ * @WPROBE_ATTR_DURATION: sampling duration (in milliseconds) (NLA_MSECS)
+ *
+ * @WPROBE_ATTR_ID: attribute id (NLA_U32)
+ * @WPROBE_ATTR_NAME: attribute name (NLA_STRING)
+ * @WPROBE_ATTR_TYPE: attribute type (NLA_U8)
+ *
+ * attribute values:
+ *
+ * @WPROBE_VAL_STRING: string value (NLA_STRING)
+ * @WPROBE_VAL_S8: signed 8-bit integer (NLA_U8)
+ * @WPROBE_VAL_S16: signed 16-bit integer (NLA_U16)
+ * @WPROBE_VAL_S32: signed 32-bit integer (NLA_U32)
+ * @WPROBE_VAL_S64: signed 64-bit integer (NLA_U64)
+ * @WPROBE_VAL_U8: unsigned 8-bit integer (NLA_U8)
+ * @WPROBE_VAL_U16: unsigned 16-bit integer (NLA_U16)
+ * @WPROBE_VAL_U32: unsigned 32-bit integer (NLA_U32)
+ * @WPROBE_VAL_U64: unsigned 64-bit integer (NLA_U64)
+ *
+ * statistics:
+ * @WPROBE_VAL_SUM: sum of all samples
+ * @WPROBE_VAL_SUM_SQ: sum of all samples^2
+ * @WPROBE_VAL_SAMPLES: number of samples
+ * @WPROBE_VAL_SCALE_TIME: last time the samples were scaled down
+ *
+ * configuration:
+ * @WPROBE_ATTR_INTERVAL: (measurement interval in milliseconds) (NLA_MSECS)
+ * @WPROBE_ATTR_SAMPLES_MIN: minimum samples to keep during inactivity (NLA_U32)
+ * @WPROBE_ATTR_SAMPLES_MAX: maximum samples to keep before scaling down (NLA_U32)
+ * @WPROBE_ATTR_SAMPLES_SCALE_M: multiplier for scaling down samples (NLA_U32)
+ * @WPROBE_ATTR_SAMPLES_SCALE_D: divisor for scaling down samples (NLA_U32)
+ *
+ * @WPROBE_ATTR_LAST: unused
+ */
+enum wprobe_attr {
+ /* query attributes */
+ WPROBE_ATTR_UNSPEC,
+ WPROBE_ATTR_INTERFACE,
+ WPROBE_ATTR_MAC,
+ WPROBE_ATTR_FLAGS,
+
+ /* response data */
+ WPROBE_ATTR_ID,
+ WPROBE_ATTR_NAME,
+ WPROBE_ATTR_TYPE,
+ WPROBE_ATTR_DURATION,
+
+ /* value type attributes */
+ WPROBE_VAL_STRING,
+ WPROBE_VAL_S8,
+ WPROBE_VAL_S16,
+ WPROBE_VAL_S32,
+ WPROBE_VAL_S64,
+ WPROBE_VAL_U8,
+ WPROBE_VAL_U16,
+ WPROBE_VAL_U32,
+ WPROBE_VAL_U64,
+
+ /* aggregates for statistics */
+ WPROBE_VAL_SUM,
+ WPROBE_VAL_SUM_SQ,
+ WPROBE_VAL_SAMPLES,
+ WPROBE_VAL_SCALE_TIME,
+
+ /* config attributes */
+ WPROBE_ATTR_INTERVAL,
+ WPROBE_ATTR_SAMPLES_MIN,
+ WPROBE_ATTR_SAMPLES_MAX,
+ WPROBE_ATTR_SAMPLES_SCALE_M,
+ WPROBE_ATTR_SAMPLES_SCALE_D,
+ WPROBE_ATTR_FILTER,
+
+ WPROBE_ATTR_FILTER_GROUP,
+ WPROBE_ATTR_RXCOUNT,
+ WPROBE_ATTR_TXCOUNT,
+
+ WPROBE_ATTR_LAST
+};
+
+
+/**
+ * enum wprobe_cmd: netlink commands for interacting with wprobe
+ *
+ * @WPROBE_CMD_UNSPEC: unused
+ *
+ * @WPROBE_CMD_GET_LIST: get global/link property list
+ * @WPROBE_CMD_GET_INFO: get global/link properties
+ * @WPROBE_CMD_SET_FLAGS: set global/link flags
+ * @WPROBE_CMD_MEASURE: take a snapshot of the current data
+ * @WPROBE_CMD_GET_LINKS: get a list of links
+ * @WPROBE_CMD_CONFIG: set config options
+ * @WPROBE_CMD_GET_FILTER: get counters for active filters
+ *
+ * @WPROBE_CMD_LAST: unused
+ *
+ * options for GET_INFO and SET_FLAGS:
+ * - mac address set: per-link
+ * - mac address unset: globalsa
+ */
+enum wprobe_cmd {
+ WPROBE_CMD_UNSPEC,
+ WPROBE_CMD_GET_LIST,
+ WPROBE_CMD_GET_INFO,
+ WPROBE_CMD_SET_FLAGS,
+ WPROBE_CMD_MEASURE,
+ WPROBE_CMD_GET_LINKS,
+ WPROBE_CMD_CONFIG,
+ WPROBE_CMD_GET_FILTER,
+ WPROBE_CMD_LAST
+};
+
+/**
+ * enum wprobe_flags: flags for wprobe links and items
+ * @WPROBE_F_KEEPSTAT: keep statistics for this link/device
+ * @WPROBE_F_RESET: reset statistics now
+ * @WPROBE_F_NEWDATA: used to indicate that a value has been updated
+ */
+enum wprobe_flags {
+ WPROBE_F_KEEPSTAT = (1 << 0),
+ WPROBE_F_RESET = (1 << 1),
+ WPROBE_F_NEWDATA = (1 << 2),
+};
+
+#ifdef __KERNEL__
+
+struct wprobe_link;
+struct wprobe_item;
+struct wprobe_source;
+struct wprobe_value;
+
+/**
+ * struct wprobe_link - data structure describing a wireless link
+ * @iface: pointer to the wprobe_iface that this link belongs to
+ * @addr: BSSID of the remote link partner
+ * @flags: link flags (see wprobe_flags)
+ * @priv: user pointer
+ *
+ * @list: for internal use
+ * @val: for internal use
+ */
+struct wprobe_link {
+ struct list_head list;
+ struct wprobe_iface *iface;
+ char addr[ETH_ALEN];
+ u32 flags;
+ void *priv;
+ struct wprobe_value *val;
+};
+
+/**
+ * struct wprobe_item - data structure describing the format of wprobe_link::data or wprobe_iface::data
+ * @name: name of the field
+ * @type: data type of this field
+ * @flags: measurement item flags (see wprobe_flags)
+ */
+struct wprobe_item {
+ const char *name;
+ enum wprobe_attr type;
+ u32 flags;
+};
+
+struct wprobe_value {
+ bool pending;
+ union {
+ /*
+ * the following are kept uppercase to allow
+ * for automated checking against WPROBE_VAL_*
+ * via BUG_ON()
+ */
+ const char *STRING;
+ u8 U8;
+ u16 U16;
+ u32 U32;
+ u64 U64;
+ s8 S8;
+ s16 S16;
+ s32 S32;
+ s64 S64;
+ };
+ s64 s, ss;
+ unsigned int n;
+
+ /* timestamps */
+ u64 first, last;
+ u64 scale_timestamp;
+};
+
+struct wprobe_filter_item_hdr {
+ char name[32];
+ __be32 n_items;
+} __attribute__((packed));
+
+struct wprobe_filter_item {
+ struct wprobe_filter_item_hdr hdr;
+ struct sock_filter filter[];
+} __attribute__((packed));
+
+struct wprobe_filter_counter {
+ u64 tx;
+ u64 rx;
+};
+
+struct wprobe_filter_group {
+ const char *name;
+ int n_items;
+ struct wprobe_filter_item **items;
+ struct wprobe_filter_counter *counters;
+};
+
+struct wprobe_filter_hdr {
+ __u8 magic[4];
+ __u8 version;
+ __u8 hdrlen;
+ __u16 n_groups;
+} __attribute__((packed));
+
+struct wprobe_filter {
+ spinlock_t lock;
+ struct sk_buff *skb;
+ void *data;
+ int n_groups;
+ int hdrlen;
+ struct wprobe_filter_item **items;
+ struct wprobe_filter_counter *counters;
+ struct wprobe_filter_group groups[];
+};
+
+enum {
+ WPROBE_PKT_RX = 0x00,
+ WPROBE_PKT_TX = 0x10,
+};
+
+struct wprobe_wlan_hdr {
+ u16 len;
+ u8 snr;
+ u8 type;
+} __attribute__((packed));
+
+
+/**
+ * struct wprobe_source - data structure describing a wireless interface
+ *
+ * @name: name of the interface
+ * @addr: local mac address of the interface
+ * @links: list of wireless links to poll
+ * @link_items: description of the per-link data structure
+ * @n_link_items: number of link description items
+ * @global_items: description of the per-interface data structure
+ * @n_global_items: number of per-interface description items
+ * @sync_data: callback allowing the driver to prepare data for the wprobe poll
+ *
+ * @list: head for the list of interfaces
+ * @priv: user pointer
+ * @lock: spinlock protecting value data access
+ * @val: internal use
+ * @query_val: internal use
+ *
+ * if sync_data is NULL, wprobe assumes that it can access the data structure
+ * at any time (in atomic context). if sync_data returns a negative error code,
+ * the poll request will not be handled for the given link
+ */
+struct wprobe_iface {
+ /* to be filled in by wprobe source drivers */
+ const char *name;
+ const char *addr;
+ const struct wprobe_item *link_items;
+ int n_link_items;
+ const struct wprobe_item *global_items;
+ int n_global_items;
+
+ int (*sync_data)(struct wprobe_iface *dev, struct wprobe_link *l,
+ struct wprobe_value *val, bool measure);
+ void *priv;
+
+ /* handled by the wprobe core */
+ struct list_head list;
+ struct list_head links;
+ spinlock_t lock;
+ struct wprobe_value *val;
+ struct wprobe_value *query_val;
+ struct wprobe_filter *active_filter;
+
+ u32 measure_interval;
+ struct timer_list measure_timer;
+
+ u32 scale_min;
+ u32 scale_max;
+ u32 scale_m;
+ u32 scale_d;
+};
+
+
+#define WPROBE_FILL_BEGIN(_ptr, _list) do { \
+ struct wprobe_value *__val = (_ptr); \
+ const struct wprobe_item *__item = _list; \
+ u64 __msecs = jiffies_to_msecs(jiffies)
+
+#define WPROBE_SET(_idx, _type, _value) \
+ if (__item[_idx].type != WPROBE_VAL_##_type) { \
+ printk("ERROR: invalid data type at %s:%d\n", __FILE__, __LINE__); \
+ break; \
+ } \
+ __val[_idx].pending = true; \
+ __val[_idx]._type = _value; \
+ if (!__val[_idx].first) \
+ __val[_idx].first = __msecs; \
+ __val[_idx].first = __msecs
+
+#define WPROBE_FILL_END() \
+} while(0)
+
+/**
+ * wprobe_add_iface: register an interface with the wireless probe subsystem
+ * @dev: wprobe_iface structure describing the interface
+ */
+extern int __weak wprobe_add_iface(struct wprobe_iface *dev);
+
+/**
+ * wprobe_remove_iface: deregister an interface from the wireless probe subsystem
+ * @dev: wprobe_iface structure describing the interface
+ */
+extern void __weak wprobe_remove_iface(struct wprobe_iface *dev);
+
+/**
+ * wprobe_add_link: register a new wireless link
+ * @dev: wprobe_iface structure describing the interface
+ * @l: storage space for the wprobe_link structure
+ * @addr: mac address of the new link
+ *
+ * the entire wprobe_link structure is overwritten by this function call
+ */
+extern int __weak wprobe_add_link(struct wprobe_iface *dev, struct wprobe_link *l, const char *addr);
+
+/**
+ * wprobe_remove_link: deregister a previously registered wireless link
+ * @dev: wprobe_iface structure describing the interface
+ * @l: wprobe_link data structure
+ */
+extern void __weak wprobe_remove_link(struct wprobe_iface *dev, struct wprobe_link *l);
+
+/**
+ * wprobe_update_stats: update statistics after sampling values
+ * @dev: wprobe_iface structure describing the interface
+ * @l: wprobe_link data structure
+ *
+ * if l == NULL, then the stats for globals are updated
+ */
+extern void __weak wprobe_update_stats(struct wprobe_iface *dev, struct wprobe_link *l);
+
+/**
+ * wprobe_add_frame: add frame for layer 2 analysis
+ * @dev: wprobe_iface structure describing the interface
+ * @hdr: metadata for the frame
+ * @data: 802.11 header pointer
+ * @len: length of the 802.11 header
+ */
+extern int __weak wprobe_add_frame(struct wprobe_iface *dev, const struct wprobe_wlan_hdr *hdr, void *data, int len);
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/package/wprobe/src/kernel/wprobe-core.c b/package/wprobe/src/kernel/wprobe-core.c
new file mode 100644
index 000000000..6ec847a7a
--- /dev/null
+++ b/package/wprobe/src/kernel/wprobe-core.c
@@ -0,0 +1,1164 @@
+/*
+ * wprobe-core.c: Wireless probe interface core
+ * Copyright (C) 2008-2009 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/rcupdate.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+#include <linux/rculist.h>
+#else
+#include <linux/list.h>
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)
+#include <linux/prefetch.h>
+#endif
+#include <linux/skbuff.h>
+#include <linux/wprobe.h>
+#include <linux/math64.h>
+
+#define static
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+#define list_for_each_rcu(pos, head) \
+for (pos = rcu_dereference((head)->next); \
+prefetch(pos->next), pos != (head); \
+pos = rcu_dereference(pos->next))
+#endif
+
+#define WPROBE_MIN_INTERVAL 100 /* minimum measurement interval in msecs */
+#define WPROBE_MAX_FILTER_SIZE 1024
+#define WPROBE_MAX_FRAME_SIZE 1900
+
+static struct list_head wprobe_if;
+static spinlock_t wprobe_lock;
+
+static struct genl_family wprobe_fam = {
+ .id = GENL_ID_GENERATE,
+ .name = "wprobe",
+ .hdrsize = 0,
+ .version = 1,
+ /* only the first set of attributes is used for queries */
+ .maxattr = WPROBE_ATTR_LAST,
+};
+
+/* fake radiotap header */
+struct wprobe_rtap_hdr {
+ __u8 version;
+ __u8 padding;
+ __le16 len;
+ __le32 present;
+};
+
+static void wprobe_update_stats(struct wprobe_iface *dev, struct wprobe_link *l);
+static int wprobe_sync_data(struct wprobe_iface *dev, struct wprobe_link *l, bool query);
+static void wprobe_free_filter(struct wprobe_filter *f);
+
+int
+wprobe_add_link(struct wprobe_iface *s, struct wprobe_link *l, const char *addr)
+{
+ unsigned long flags;
+
+ INIT_LIST_HEAD(&l->list);
+ l->val = kzalloc(sizeof(struct wprobe_value) * s->n_link_items, GFP_ATOMIC);
+ if (!l->val)
+ return -ENOMEM;
+
+ l->iface = s;
+ memcpy(&l->addr, addr, ETH_ALEN);
+ spin_lock_irqsave(&wprobe_lock, flags);
+ list_add_tail_rcu(&l->list, &s->links);
+ spin_unlock_irqrestore(&wprobe_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(wprobe_add_link);
+
+void
+wprobe_remove_link(struct wprobe_iface *s, struct wprobe_link *l)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&wprobe_lock, flags);
+ list_del_rcu(&l->list);
+ spin_unlock_irqrestore(&wprobe_lock, flags);
+ synchronize_rcu();
+ kfree(l->val);
+}
+EXPORT_SYMBOL(wprobe_remove_link);
+
+static void
+wprobe_measure_timer(unsigned long data)
+{
+ struct wprobe_iface *dev = (struct wprobe_iface *) data;
+
+ /* set next measurement interval */
+ mod_timer(&dev->measure_timer, jiffies +
+ msecs_to_jiffies(dev->measure_interval));
+
+ /* perform measurement */
+ wprobe_sync_data(dev, NULL, false);
+}
+
+int
+wprobe_add_iface(struct wprobe_iface *s)
+{
+ unsigned long flags;
+ int vsize;
+
+ /* reset only wprobe private area */
+ memset(&s->list, 0, sizeof(struct wprobe_iface) - offsetof(struct wprobe_iface, list));
+
+ BUG_ON(!s->name);
+ INIT_LIST_HEAD(&s->list);
+ INIT_LIST_HEAD(&s->links);
+ setup_timer(&s->measure_timer, wprobe_measure_timer, (unsigned long) s);
+
+ s->val = kzalloc(sizeof(struct wprobe_value) * s->n_global_items, GFP_ATOMIC);
+ if (!s->val)
+ goto error;
+
+ vsize = max(s->n_link_items, s->n_global_items);
+ s->query_val = kzalloc(sizeof(struct wprobe_value) * vsize, GFP_ATOMIC);
+ if (!s->query_val)
+ goto error;
+
+ /* initialize defaults to be able to handle overflow,
+ * user space will need to handle this if it keeps an
+ * internal histogram */
+ s->scale_min = 20;
+ s->scale_max = (1 << 31);
+
+ s->scale_m = 1;
+ s->scale_d = 10;
+
+ spin_lock_irqsave(&wprobe_lock, flags);
+ list_add_rcu(&s->list, &wprobe_if);
+ spin_unlock_irqrestore(&wprobe_lock, flags);
+
+ return 0;
+
+error:
+ if (s->val)
+ kfree(s->val);
+ return -ENOMEM;
+}
+EXPORT_SYMBOL(wprobe_add_iface);
+
+void
+wprobe_remove_iface(struct wprobe_iface *s)
+{
+ unsigned long flags;
+
+ BUG_ON(!list_empty(&s->links));
+
+ del_timer_sync(&s->measure_timer);
+ spin_lock_irqsave(&wprobe_lock, flags);
+ list_del_rcu(&s->list);
+ spin_unlock_irqrestore(&wprobe_lock, flags);
+
+ /* wait for all queries to finish before freeing the
+ * temporary value storage buffer */
+ synchronize_rcu();
+
+ kfree(s->val);
+ kfree(s->query_val);
+ if (s->active_filter)
+ wprobe_free_filter(s->active_filter);
+}
+EXPORT_SYMBOL(wprobe_remove_iface);
+
+static struct wprobe_iface *
+wprobe_get_dev(struct nlattr *attr)
+{
+ struct wprobe_iface *dev = NULL;
+ struct wprobe_iface *p;
+ const char *name;
+ int i = 0;
+
+ if (!attr)
+ return NULL;
+
+ name = nla_data(attr);
+ list_for_each_entry_rcu(p, &wprobe_if, list) {
+ i++;
+ if (strcmp(name, p->name) != 0)
+ continue;
+
+ dev = p;
+ break;
+ }
+
+ return dev;
+}
+
+int
+wprobe_add_frame(struct wprobe_iface *dev, const struct wprobe_wlan_hdr *hdr, void *data, int len)
+{
+ struct wprobe_wlan_hdr *new_hdr;
+ struct wprobe_filter *f;
+ struct sk_buff *skb;
+ unsigned long flags;
+ int i, j;
+
+ rcu_read_lock();
+ f = rcu_dereference(dev->active_filter);
+ if (!f)
+ goto out;
+
+ spin_lock_irqsave(&f->lock, flags);
+
+ skb = f->skb;
+ skb->len = sizeof(struct wprobe_rtap_hdr);
+ skb->tail = skb->data + skb->len;
+ if (len + skb->len > WPROBE_MAX_FRAME_SIZE)
+ len = WPROBE_MAX_FRAME_SIZE - skb->len;
+
+ new_hdr = (struct wprobe_wlan_hdr *) skb_put(skb, f->hdrlen);
+ memcpy(new_hdr, hdr, sizeof(struct wprobe_wlan_hdr));
+ new_hdr->len = cpu_to_be16(new_hdr->len);
+
+ memcpy(skb_put(skb, len), data, len);
+
+ for(i = 0; i < f->n_groups; i++) {
+ struct wprobe_filter_group *fg = &f->groups[i];
+ bool found = false;
+ int def = -1;
+
+ for (j = 0; j < fg->n_items; j++) {
+ struct wprobe_filter_item *fi = fg->items[j];
+
+ if (!fi->hdr.n_items) {
+ def = j;
+ continue;
+ }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+ if (sk_run_filter(skb, fi->filter) == 0)
+ continue;
+#else
+ if (sk_run_filter(skb, fi->filter, fi->hdr.n_items) == 0)
+ continue;
+#endif
+
+ found = true;
+ break;
+ }
+ if (!found && def >= 0) {
+ j = def;
+ found = true;
+ }
+ if (found) {
+ struct wprobe_filter_counter *c = &fg->counters[j];
+
+ if (hdr->type >= WPROBE_PKT_TX)
+ c->tx++;
+ else
+ c->rx++;
+ }
+ }
+
+ spin_unlock_irqrestore(&f->lock, flags);
+out:
+ rcu_read_unlock();
+ return 0;
+}
+EXPORT_SYMBOL(wprobe_add_frame);
+
+static int
+wprobe_sync_data(struct wprobe_iface *dev, struct wprobe_link *l, bool query)
+{
+ struct wprobe_value *val;
+ unsigned long flags;
+ int n, err;
+
+ if (l) {
+ n = dev->n_link_items;
+ val = l->val;
+ } else {
+ n = dev->n_global_items;
+ val = dev->val;
+ }
+
+ spin_lock_irqsave(&dev->lock, flags);
+ err = dev->sync_data(dev, l, val, !query);
+ if (err)
+ goto done;
+
+ if (query)
+ memcpy(dev->query_val, val, sizeof(struct wprobe_value) * n);
+
+ wprobe_update_stats(dev, l);
+done:
+ spin_unlock_irqrestore(&dev->lock, flags);
+ return 0;
+}
+EXPORT_SYMBOL(wprobe_sync_data);
+
+static void
+wprobe_scale_stats(struct wprobe_iface *dev, const struct wprobe_item *item,
+ struct wprobe_value *val, int n)
+{
+ u64 scale_ts = jiffies_64;
+ int i;
+
+ for (i = 0; i < n; i++) {
+ if (!(item[i].flags & WPROBE_F_KEEPSTAT))
+ continue;
+
+ if (val[i].n <= dev->scale_min)
+ continue;
+
+ /* FIXME: div_s64 seems to be very imprecise here, even when
+ * the values are scaled up */
+ val[i].s *= dev->scale_m;
+ val[i].s = div_s64(val[i].s, dev->scale_d);
+
+ val[i].ss *= dev->scale_m;
+ val[i].ss = div_s64(val[i].ss, dev->scale_d);
+
+ val[i].n = (val[i].n * dev->scale_m) / dev->scale_d;
+ val[i].scale_timestamp = scale_ts;
+ }
+}
+
+
+void
+wprobe_update_stats(struct wprobe_iface *dev, struct wprobe_link *l)
+{
+ const struct wprobe_item *item;
+ struct wprobe_value *val;
+ bool scale_stats = false;
+ int i, n;
+
+ if (l) {
+ n = dev->n_link_items;
+ item = dev->link_items;
+ val = l->val;
+ } else {
+ n = dev->n_global_items;
+ item = dev->global_items;
+ val = dev->val;
+ }
+
+ /* process statistics */
+ for (i = 0; i < n; i++) {
+ s64 v;
+
+ if (!val[i].pending)
+ continue;
+
+ val[i].n++;
+ if ((item[i].flags & WPROBE_F_KEEPSTAT) &&
+ (dev->scale_max > 0) && (val[i].n > dev->scale_max)) {
+ scale_stats = true;
+ }
+
+ switch(item[i].type) {
+ case WPROBE_VAL_S8:
+ v = val[i].S8;
+ break;
+ case WPROBE_VAL_S16:
+ v = val[i].S16;
+ break;
+ case WPROBE_VAL_S32:
+ v = val[i].S32;
+ break;
+ case WPROBE_VAL_S64:
+ v = val[i].S64;
+ break;
+ case WPROBE_VAL_U8:
+ v = val[i].U8;
+ break;
+ case WPROBE_VAL_U16:
+ v = val[i].U16;
+ break;
+ case WPROBE_VAL_U32:
+ v = val[i].U32;
+ break;
+ case WPROBE_VAL_U64:
+ v = val[i].U64;
+ break;
+ default:
+ continue;
+ }
+
+ val[i].s += v;
+ val[i].ss += v * v;
+ val[i].pending = false;
+ }
+ if (scale_stats)
+ wprobe_scale_stats(dev, item, val, n);
+}
+EXPORT_SYMBOL(wprobe_update_stats);
+
+static const struct nla_policy wprobe_policy[WPROBE_ATTR_LAST+1] = {
+ [WPROBE_ATTR_INTERFACE] = { .type = NLA_NUL_STRING },
+ [WPROBE_ATTR_MAC] = { .type = NLA_STRING },
+ [WPROBE_ATTR_FLAGS] = { .type = NLA_U32 },
+
+ /* config */
+ [WPROBE_ATTR_INTERVAL] = { .type = NLA_MSECS },
+ [WPROBE_ATTR_SAMPLES_MIN] = { .type = NLA_U32 },
+ [WPROBE_ATTR_SAMPLES_MAX] = { .type = NLA_U32 },
+ [WPROBE_ATTR_SAMPLES_SCALE_M] = { .type = NLA_U32 },
+ [WPROBE_ATTR_SAMPLES_SCALE_D] = { .type = NLA_U32 },
+ [WPROBE_ATTR_FILTER] = { .type = NLA_BINARY, .len = 32768 },
+};
+
+static bool
+wprobe_check_ptr(struct list_head *list, struct list_head *ptr)
+{
+ struct list_head *p;
+
+ list_for_each_rcu(p, list) {
+ if (ptr == p)
+ return true;
+ }
+ return false;
+}
+
+static bool
+wprobe_send_item_value(struct sk_buff *msg, struct netlink_callback *cb,
+ struct wprobe_iface *dev, struct wprobe_link *l,
+ const struct wprobe_item *item,
+ int i, u32 flags)
+{
+ struct genlmsghdr *hdr;
+ struct wprobe_value *val = dev->query_val;
+ u64 time = val[i].last - val[i].first;
+
+ hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
+ &wprobe_fam, NLM_F_MULTI, WPROBE_CMD_GET_INFO);
+
+ NLA_PUT_U32(msg, WPROBE_ATTR_ID, i);
+ NLA_PUT_U32(msg, WPROBE_ATTR_FLAGS, flags);
+ NLA_PUT_U8(msg, WPROBE_ATTR_TYPE, item[i].type);
+ NLA_PUT_U64(msg, WPROBE_ATTR_DURATION, time);
+
+ switch(item[i].type) {
+ case WPROBE_VAL_S8:
+ case WPROBE_VAL_U8:
+ NLA_PUT_U8(msg, item[i].type, val[i].U8);
+ break;
+ case WPROBE_VAL_S16:
+ case WPROBE_VAL_U16:
+ NLA_PUT_U16(msg, item[i].type, val[i].U16);
+ break;
+ case WPROBE_VAL_S32:
+ case WPROBE_VAL_U32:
+ NLA_PUT_U32(msg, item[i].type, val[i].U32);
+ break;
+ case WPROBE_VAL_S64:
+ case WPROBE_VAL_U64:
+ NLA_PUT_U64(msg, item[i].type, val[i].U64);
+ break;
+ case WPROBE_VAL_STRING:
+ if (val[i].STRING)
+ NLA_PUT_STRING(msg, item[i].type, val[i].STRING);
+ else
+ NLA_PUT_STRING(msg, item[i].type, "");
+ /* bypass avg/stdev */
+ goto done;
+ default:
+ /* skip unknown values */
+ goto done;
+ }
+ if (item[i].flags & WPROBE_F_KEEPSTAT) {
+ NLA_PUT_U64(msg, WPROBE_VAL_SUM, val[i].s);
+ NLA_PUT_U64(msg, WPROBE_VAL_SUM_SQ, val[i].ss);
+ NLA_PUT_U32(msg, WPROBE_VAL_SAMPLES, (u32) val[i].n);
+ NLA_PUT_MSECS(msg, WPROBE_VAL_SCALE_TIME, val[i].scale_timestamp);
+ }
+done:
+ genlmsg_end(msg, hdr);
+ return true;
+
+nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ return false;
+}
+
+static bool
+wprobe_send_item_info(struct sk_buff *msg, struct netlink_callback *cb,
+ struct wprobe_iface *dev,
+ const struct wprobe_item *item, int i)
+{
+ struct genlmsghdr *hdr;
+
+ hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
+ &wprobe_fam, NLM_F_MULTI, WPROBE_CMD_GET_LIST);
+
+ if ((i == 0) && (dev->addr != NULL))
+ NLA_PUT(msg, WPROBE_ATTR_MAC, 6, dev->addr);
+ NLA_PUT_U32(msg, WPROBE_ATTR_ID, (u32) i);
+ NLA_PUT_STRING(msg, WPROBE_ATTR_NAME, item[i].name);
+ NLA_PUT_U8(msg, WPROBE_ATTR_TYPE, item[i].type);
+ NLA_PUT_U32(msg, WPROBE_ATTR_FLAGS, item[i].flags);
+ genlmsg_end(msg, hdr);
+ return true;
+
+nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ return false;
+}
+
+
+static struct wprobe_link *
+wprobe_find_link(struct wprobe_iface *dev, const char *mac)
+{
+ struct wprobe_link *l;
+
+ list_for_each_entry_rcu(l, &dev->links, list) {
+ if (!memcmp(l->addr, mac, 6))
+ return l;
+ }
+ return NULL;
+}
+
+static bool
+wprobe_dump_filter_group(struct sk_buff *msg, struct wprobe_filter_group *fg, struct netlink_callback *cb)
+{
+ struct genlmsghdr *hdr;
+ struct nlattr *group, *item;
+ int i;
+
+ hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
+ &wprobe_fam, NLM_F_MULTI, WPROBE_CMD_GET_FILTER);
+ if (!hdr)
+ return false;
+
+ NLA_PUT_STRING(msg, WPROBE_ATTR_NAME, fg->name);
+ group = nla_nest_start(msg, WPROBE_ATTR_FILTER_GROUP);
+ for (i = 0; i < fg->n_items; i++) {
+ struct wprobe_filter_item *fi = fg->items[i];
+ struct wprobe_filter_counter *fc = &fg->counters[i];
+
+ item = nla_nest_start(msg, WPROBE_ATTR_FILTER_GROUP);
+ NLA_PUT_STRING(msg, WPROBE_ATTR_NAME, fi->hdr.name);
+ NLA_PUT_U64(msg, WPROBE_ATTR_RXCOUNT, fc->rx);
+ NLA_PUT_U64(msg, WPROBE_ATTR_TXCOUNT, fc->tx);
+ nla_nest_end(msg, item);
+ }
+
+ nla_nest_end(msg, group);
+ genlmsg_end(msg, hdr);
+ return true;
+
+nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ return false;
+}
+
+static int
+wprobe_dump_filters(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct wprobe_iface *dev = (struct wprobe_iface *)cb->args[0];
+ struct wprobe_filter *f;
+ int err = 0;
+ int i = 0;
+
+ if (!dev) {
+ err = nlmsg_parse(cb->nlh, GENL_HDRLEN + wprobe_fam.hdrsize,
+ wprobe_fam.attrbuf, wprobe_fam.maxattr, wprobe_policy);
+ if (err)
+ goto done;
+
+ dev = wprobe_get_dev(wprobe_fam.attrbuf[WPROBE_ATTR_INTERFACE]);
+ if (!dev) {
+ err = -ENODEV;
+ goto done;
+ }
+
+ cb->args[0] = (long) dev;
+ cb->args[1] = 0;
+ } else {
+ if (!wprobe_check_ptr(&wprobe_if, &dev->list)) {
+ err = -ENODEV;
+ goto done;
+ }
+ }
+
+ rcu_read_lock();
+ f = rcu_dereference(dev->active_filter);
+ if (!f)
+ goto abort;
+
+ for (i = cb->args[1]; i < f->n_groups; i++) {
+ if (unlikely(!wprobe_dump_filter_group(skb, &f->groups[i], cb)))
+ break;
+ }
+ cb->args[1] = i;
+abort:
+ rcu_read_unlock();
+ err = skb->len;
+done:
+ return err;
+}
+
+static bool
+wprobe_dump_link(struct sk_buff *msg, struct wprobe_link *l, struct netlink_callback *cb)
+{
+ struct genlmsghdr *hdr;
+
+ hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
+ &wprobe_fam, NLM_F_MULTI, WPROBE_CMD_GET_LINKS);
+ if (!hdr)
+ return false;
+
+ NLA_PUT(msg, WPROBE_ATTR_MAC, 6, l->addr);
+ genlmsg_end(msg, hdr);
+ return true;
+
+nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ return false;
+}
+
+static int
+wprobe_dump_links(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct wprobe_iface *dev = (struct wprobe_iface *)cb->args[0];
+ struct wprobe_link *l;
+ int err = 0;
+ int i = 0;
+
+ if (!dev) {
+ err = nlmsg_parse(cb->nlh, GENL_HDRLEN + wprobe_fam.hdrsize,
+ wprobe_fam.attrbuf, wprobe_fam.maxattr, wprobe_policy);
+ if (err)
+ goto done;
+
+ dev = wprobe_get_dev(wprobe_fam.attrbuf[WPROBE_ATTR_INTERFACE]);
+ if (!dev) {
+ err = -ENODEV;
+ goto done;
+ }
+
+ cb->args[0] = (long) dev;
+ } else {
+ if (!wprobe_check_ptr(&wprobe_if, &dev->list)) {
+ err = -ENODEV;
+ goto done;
+ }
+ }
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(l, &dev->links, list) {
+ if (i < cb->args[1])
+ continue;
+
+ if (unlikely(!wprobe_dump_link(skb, l, cb)))
+ break;
+
+ i++;
+ }
+ cb->args[1] = i;
+ rcu_read_unlock();
+ err = skb->len;
+done:
+ return err;
+}
+
+#define WPROBE_F_LINK (1 << 31) /* for internal use */
+static int
+wprobe_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct wprobe_iface *dev = (struct wprobe_iface *)cb->args[0];
+ struct wprobe_link *l = (struct wprobe_link *)cb->args[1];
+ struct wprobe_value *val;
+ const struct wprobe_item *item;
+ struct genlmsghdr *hdr;
+ unsigned long flags;
+ int cmd, n, i = cb->args[3];
+ u32 vflags = cb->args[2];
+ int err = 0;
+
+ hdr = (struct genlmsghdr *)nlmsg_data(cb->nlh);
+ cmd = hdr->cmd;
+
+ /* since the attribute value list might be too big for a single netlink
+ * message, the device, link and offset get stored in the netlink callback.
+ * if this is the first request, we need to do the full lookup for the device.
+ *
+ * access to the device and link structure is synchronized through rcu.
+ */
+ rcu_read_lock();
+ if (!dev) {
+ err = nlmsg_parse(cb->nlh, GENL_HDRLEN + wprobe_fam.hdrsize,
+ wprobe_fam.attrbuf, wprobe_fam.maxattr, wprobe_policy);
+ if (err)
+ goto done;
+
+ err = -ENOENT;
+ dev = wprobe_get_dev(wprobe_fam.attrbuf[WPROBE_ATTR_INTERFACE]);
+ if (!dev)
+ goto done;
+
+ if (cmd == WPROBE_CMD_GET_INFO) {
+ if (wprobe_fam.attrbuf[WPROBE_ATTR_MAC]) {
+ l = wprobe_find_link(dev, nla_data(wprobe_fam.attrbuf[WPROBE_ATTR_MAC]));
+ if (!l)
+ goto done;
+
+ vflags = l->flags;
+ }
+
+ if (l) {
+ item = dev->link_items;
+ n = dev->n_link_items;
+ val = l->val;
+ } else {
+ item = dev->global_items;
+ n = dev->n_global_items;
+ val = dev->val;
+ }
+
+ /* sync data and move to temp storage for the query */
+ spin_lock_irqsave(&dev->lock, flags);
+ err = wprobe_sync_data(dev, l, true);
+ if (!err)
+ memcpy(dev->query_val, val, n * sizeof(struct wprobe_value));
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ if (err)
+ goto done;
+ }
+
+ if (wprobe_fam.attrbuf[WPROBE_ATTR_FLAGS])
+ vflags |= nla_get_u32(wprobe_fam.attrbuf[WPROBE_ATTR_FLAGS]);
+
+ if (wprobe_fam.attrbuf[WPROBE_ATTR_MAC])
+ vflags |= WPROBE_F_LINK;
+
+ cb->args[0] = (long) dev;
+ cb->args[1] = (long) l;
+ cb->args[2] = vflags;
+ cb->args[3] = 0;
+ } else {
+ /* when pulling pointers from the callback, validate them
+ * against the list using rcu to make sure that we won't
+ * dereference pointers to free'd memory after the last
+ * grace period */
+ err = -ENOENT;
+ if (!wprobe_check_ptr(&wprobe_if, &dev->list))
+ goto done;
+
+ if (l && !wprobe_check_ptr(&dev->links, &l->list))
+ goto done;
+ }
+
+ if (vflags & WPROBE_F_LINK) {
+ item = dev->link_items;
+ n = dev->n_link_items;
+ } else {
+ item = dev->global_items;
+ n = dev->n_global_items;
+ }
+
+ err = 0;
+ switch(cmd) {
+ case WPROBE_CMD_GET_INFO:
+ while (i < n) {
+ if (!wprobe_send_item_value(skb, cb, dev, l, item, i, vflags))
+ break;
+ i++;
+ }
+ break;
+ case WPROBE_CMD_GET_LIST:
+ while (i < n) {
+ if (!wprobe_send_item_info(skb, cb, dev, item, i))
+ break;
+ i++;
+ }
+ break;
+ default:
+ err = -EINVAL;
+ goto done;
+ }
+ cb->args[3] = i;
+ err = skb->len;
+
+done:
+ rcu_read_unlock();
+ return err;
+}
+#undef WPROBE_F_LINK
+
+static int
+wprobe_update_auto_measurement(struct wprobe_iface *dev, u32 interval)
+{
+ if (interval && (interval < WPROBE_MIN_INTERVAL))
+ return -EINVAL;
+
+ if (!interval && dev->measure_interval)
+ del_timer_sync(&dev->measure_timer);
+
+ dev->measure_interval = interval;
+ if (!interval)
+ return 0;
+
+ /* kick of a new measurement immediately */
+ mod_timer(&dev->measure_timer, jiffies + 1);
+
+ return 0;
+}
+
+static int
+wprobe_measure(struct sk_buff *skb, struct genl_info *info)
+{
+ struct wprobe_iface *dev;
+ struct wprobe_link *l = NULL;
+ int err = -ENOENT;
+
+ rcu_read_lock();
+ dev = wprobe_get_dev(info->attrs[WPROBE_ATTR_INTERFACE]);
+ if (!dev)
+ goto done;
+
+ if (info->attrs[WPROBE_ATTR_MAC]) {
+ l = wprobe_find_link(dev, nla_data(wprobe_fam.attrbuf[WPROBE_ATTR_MAC]));
+ if (!l)
+ goto done;
+ }
+
+ err = wprobe_sync_data(dev, l, false);
+
+done:
+ rcu_read_unlock();
+ return err;
+}
+
+static int
+wprobe_check_filter(void *data, int datalen, int gs)
+{
+ struct wprobe_filter_item_hdr *hdr;
+ void *orig_data = data;
+ void *end = data + datalen;
+ int i, j, k, is, cur_is;
+
+ for (i = j = is = 0; i < gs; i++) {
+ hdr = data;
+ data += sizeof(*hdr);
+
+ if (data > end)
+ goto overrun;
+
+ hdr->name[31] = 0;
+ cur_is = be32_to_cpu(hdr->n_items);
+ hdr->n_items = cur_is;
+ is += cur_is;
+ for (j = 0; j < cur_is; j++) {
+ struct sock_filter *sf;
+ int n_items;
+
+ hdr = data;
+ data += sizeof(*hdr);
+ if (data > end)
+ goto overrun;
+
+ hdr->name[31] = 0;
+ n_items = be32_to_cpu(hdr->n_items);
+ hdr->n_items = n_items;
+
+ if (n_items > 1024)
+ goto overrun;
+
+ sf = data;
+ if (n_items > 0) {
+ for (k = 0; k < n_items; k++) {
+ sf->code = be16_to_cpu(sf->code);
+ sf->k = be32_to_cpu(sf->k);
+ sf++;
+ }
+ if (sk_chk_filter(data, n_items) != 0) {
+ printk("%s: filter check failed at group %d, item %d\n", __func__, i, j);
+ return 0;
+ }
+ }
+ data += n_items * sizeof(struct sock_filter);
+ }
+ }
+ return is;
+
+overrun:
+ printk(KERN_ERR "%s: overrun during filter check at group %d, item %d, offset=%d, len=%d\n", __func__, i, j, (data - orig_data), datalen);
+ return 0;
+}
+
+static void
+wprobe_free_filter(struct wprobe_filter *f)
+{
+ if (f->skb)
+ kfree_skb(f->skb);
+ if (f->data)
+ kfree(f->data);
+ if (f->items)
+ kfree(f->items);
+ if (f->counters)
+ kfree(f->counters);
+ kfree(f);
+}
+
+
+static int
+wprobe_set_filter(struct wprobe_iface *dev, void *data, int len)
+{
+ struct wprobe_filter_hdr *fhdr;
+ struct wprobe_rtap_hdr *rtap;
+ struct wprobe_filter *f;
+ int i, j, cur_is, is, gs;
+
+ if (len < sizeof(*fhdr))
+ return -EINVAL;
+
+ fhdr = data;
+ data += sizeof(*fhdr);
+ len -= sizeof(*fhdr);
+
+ if (memcmp(fhdr->magic, "WPFF", 4) != 0) {
+ printk(KERN_ERR "%s: filter rejected (invalid magic)\n", __func__);
+ return -EINVAL;
+ }
+
+ gs = be16_to_cpu(fhdr->n_groups);
+ is = wprobe_check_filter(data, len, gs);
+ if (is == 0)
+ return -EINVAL;
+
+ f = kzalloc(sizeof(struct wprobe_filter) +
+ gs * sizeof(struct wprobe_filter_group), GFP_ATOMIC);
+ if (!f)
+ return -ENOMEM;
+
+ f->skb = alloc_skb(WPROBE_MAX_FRAME_SIZE, GFP_ATOMIC);
+ if (!f->skb)
+ goto error;
+
+ f->data = kmalloc(len, GFP_ATOMIC);
+ if (!f->data)
+ goto error;
+
+ f->items = kzalloc(sizeof(struct wprobe_filter_item *) * is, GFP_ATOMIC);
+ if (!f->items)
+ goto error;
+
+ f->counters = kzalloc(sizeof(struct wprobe_filter_counter) * is, GFP_ATOMIC);
+ if (!f->counters)
+ goto error;
+
+ spin_lock_init(&f->lock);
+ memcpy(f->data, data, len);
+ f->n_groups = gs;
+
+ if (f->hdrlen < sizeof(struct wprobe_wlan_hdr))
+ f->hdrlen = sizeof(struct wprobe_wlan_hdr);
+
+ rtap = (struct wprobe_rtap_hdr *)skb_put(f->skb, sizeof(*rtap));
+ memset(rtap, 0, sizeof(*rtap));
+ rtap->len = cpu_to_le16(sizeof(struct wprobe_rtap_hdr) + f->hdrlen);
+ data = f->data;
+
+ cur_is = 0;
+ for (i = 0; i < gs; i++) {
+ struct wprobe_filter_item_hdr *hdr = data;
+ struct wprobe_filter_group *g = &f->groups[i];
+
+ data += sizeof(*hdr);
+ g->name = hdr->name;
+ g->items = &f->items[cur_is];
+ g->counters = &f->counters[cur_is];
+ g->n_items = hdr->n_items;
+
+ for (j = 0; j < g->n_items; j++) {
+ hdr = data;
+ f->items[cur_is++] = data;
+ data += sizeof(*hdr) + hdr->n_items * sizeof(struct sock_filter);
+ }
+ }
+ rcu_assign_pointer(dev->active_filter, f);
+ return 0;
+
+error:
+ wprobe_free_filter(f);
+ return -ENOMEM;
+}
+
+static int
+wprobe_set_config(struct sk_buff *skb, struct genl_info *info)
+{
+ struct wprobe_iface *dev;
+ unsigned long flags;
+ int err = -ENOENT;
+ u32 scale_min, scale_max;
+ u32 scale_m, scale_d;
+ struct nlattr *attr;
+ struct wprobe_filter *filter_free = NULL;
+
+ rcu_read_lock();
+ dev = wprobe_get_dev(info->attrs[WPROBE_ATTR_INTERFACE]);
+ if (!dev)
+ goto done_unlocked;
+
+ err = -EINVAL;
+ spin_lock_irqsave(&dev->lock, flags);
+ if (info->attrs[WPROBE_ATTR_MAC]) {
+ /* not supported yet */
+ goto done;
+ }
+
+ if (info->attrs[WPROBE_ATTR_FLAGS]) {
+ u32 flags = nla_get_u32(info->attrs[WPROBE_ATTR_FLAGS]);
+
+ if (flags & BIT(WPROBE_F_RESET)) {
+ struct wprobe_link *l;
+
+ memset(dev->val, 0, sizeof(struct wprobe_value) * dev->n_global_items);
+ list_for_each_entry_rcu(l, &dev->links, list) {
+ memset(l->val, 0, sizeof(struct wprobe_value) * dev->n_link_items);
+ }
+ }
+ }
+
+ if (info->attrs[WPROBE_ATTR_SAMPLES_MIN] ||
+ info->attrs[WPROBE_ATTR_SAMPLES_MAX]) {
+ if ((attr = info->attrs[WPROBE_ATTR_SAMPLES_MIN]))
+ scale_min = nla_get_u32(attr);
+ else
+ scale_min = dev->scale_min;
+
+ if ((attr = info->attrs[WPROBE_ATTR_SAMPLES_MAX]))
+ scale_max = nla_get_u32(attr);
+ else
+ scale_max = dev->scale_max;
+
+ if ((!scale_min && !scale_max) ||
+ (scale_min && scale_max && (scale_min < scale_max))) {
+ dev->scale_min = scale_min;
+ dev->scale_max = scale_max;
+ } else {
+ goto done;
+ }
+ }
+
+ if (info->attrs[WPROBE_ATTR_SAMPLES_SCALE_M] &&
+ info->attrs[WPROBE_ATTR_SAMPLES_SCALE_D]) {
+
+ scale_m = nla_get_u32(info->attrs[WPROBE_ATTR_SAMPLES_SCALE_M]);
+ scale_d = nla_get_u32(info->attrs[WPROBE_ATTR_SAMPLES_SCALE_D]);
+
+ if (!scale_d || (scale_m > scale_d))
+ goto done;
+
+ dev->scale_m = scale_m;
+ dev->scale_d = scale_d;
+ }
+
+ if ((attr = info->attrs[WPROBE_ATTR_FILTER])) {
+ filter_free = rcu_dereference(dev->active_filter);
+ rcu_assign_pointer(dev->active_filter, NULL);
+ if (nla_len(attr) > 0)
+ wprobe_set_filter(dev, nla_data(attr), nla_len(attr));
+ }
+
+ err = 0;
+ if (info->attrs[WPROBE_ATTR_INTERVAL]) {
+ /* change of measurement interval requested */
+ err = wprobe_update_auto_measurement(dev,
+ (u32) nla_get_u64(info->attrs[WPROBE_ATTR_INTERVAL]));
+ }
+
+done:
+ spin_unlock_irqrestore(&dev->lock, flags);
+done_unlocked:
+ rcu_read_unlock();
+ if (filter_free) {
+ synchronize_rcu();
+ wprobe_free_filter(filter_free);
+ }
+ return err;
+}
+
+static struct genl_ops wprobe_ops[] = {
+ {
+ .cmd = WPROBE_CMD_GET_INFO,
+ .dumpit = wprobe_dump_info,
+ .policy = wprobe_policy,
+ },
+ {
+ .cmd = WPROBE_CMD_GET_LIST,
+ .dumpit = wprobe_dump_info,
+ .policy = wprobe_policy,
+ },
+ {
+ .cmd = WPROBE_CMD_MEASURE,
+ .doit = wprobe_measure,
+ .policy = wprobe_policy,
+ },
+ {
+ .cmd = WPROBE_CMD_GET_LINKS,
+ .dumpit = wprobe_dump_links,
+ .policy = wprobe_policy,
+ },
+ {
+ .cmd = WPROBE_CMD_CONFIG,
+ .doit = wprobe_set_config,
+ .policy = wprobe_policy,
+ },
+ {
+ .cmd = WPROBE_CMD_GET_FILTER,
+ .dumpit = wprobe_dump_filters,
+ .policy = wprobe_policy,
+ },
+};
+
+static void __exit
+wprobe_exit(void)
+{
+ BUG_ON(!list_empty(&wprobe_if));
+ genl_unregister_family(&wprobe_fam);
+}
+
+
+static int __init
+wprobe_init(void)
+{
+ int i, err;
+
+ spin_lock_init(&wprobe_lock);
+ INIT_LIST_HEAD(&wprobe_if);
+
+ err = genl_register_family(&wprobe_fam);
+ if (err)
+ return err;
+
+ for (i = 0; i < ARRAY_SIZE(wprobe_ops); i++) {
+ err = genl_register_ops(&wprobe_fam, &wprobe_ops[i]);
+ if (err)
+ goto error;
+ }
+
+ return 0;
+
+error:
+ genl_unregister_family(&wprobe_fam);
+ return err;
+}
+
+module_init(wprobe_init);
+module_exit(wprobe_exit);
+MODULE_LICENSE("GPL");
+
diff --git a/package/wprobe/src/kernel/wprobe-dummy.c b/package/wprobe/src/kernel/wprobe-dummy.c
new file mode 100644
index 000000000..4231223e0
--- /dev/null
+++ b/package/wprobe/src/kernel/wprobe-dummy.c
@@ -0,0 +1,96 @@
+/*
+ * wprobe-core.c: Wireless probe interface dummy driver
+ * Copyright (C) 2008-2009 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/random.h>
+#include <linux/wprobe.h>
+
+static const char local_addr[] = "\x00\x13\x37\xba\xbe\x00";
+
+enum dummy_global_values {
+ DUMMY_GLOBAL_MEDIUM_BUSY
+};
+enum dummy_link_values {
+ DUMMY_LINK_SNR
+};
+
+struct wprobe_item dummy_perlink[] = {
+ [DUMMY_LINK_SNR] = {
+ .name = "snr",
+ .type = WPROBE_VAL_U8,
+ .flags = WPROBE_F_KEEPSTAT,
+ },
+};
+
+struct wprobe_item dummy_globals[] = {
+ [DUMMY_GLOBAL_MEDIUM_BUSY] = {
+ .name = "medium_busy",
+ .type = WPROBE_VAL_U8,
+ .flags = WPROBE_F_KEEPSTAT,
+ }
+};
+
+int dummy_sync(struct wprobe_iface *dev, struct wprobe_link *l, struct wprobe_value *val, bool measure)
+{
+ u8 intval = 0;
+
+ get_random_bytes(&intval, 1);
+ if (l) {
+ WPROBE_FILL_BEGIN(val, dummy_perlink);
+ WPROBE_SET(DUMMY_LINK_SNR, U8, (intval % 40));
+ WPROBE_FILL_END();
+ } else {
+ WPROBE_FILL_BEGIN(val, dummy_globals);
+ WPROBE_SET(DUMMY_GLOBAL_MEDIUM_BUSY, U8, (intval % 100));
+ WPROBE_FILL_END();
+ }
+ return 0;
+}
+
+static struct wprobe_iface dummy_dev = {
+ .name = "dummy",
+ .addr = local_addr,
+ .link_items = dummy_perlink,
+ .n_link_items = ARRAY_SIZE(dummy_perlink),
+ .global_items = dummy_globals,
+ .n_global_items = ARRAY_SIZE(dummy_globals),
+ .sync_data = dummy_sync,
+};
+
+static struct wprobe_link dummy_link;
+
+static int __init
+wprobe_dummy_init(void)
+{
+ wprobe_add_iface(&dummy_dev);
+ wprobe_add_link(&dummy_dev, &dummy_link, "\x00\x13\x37\xda\xda\x00");
+ return 0;
+}
+
+static void __exit
+wprobe_dummy_exit(void)
+{
+ wprobe_remove_link(&dummy_dev, &dummy_link);
+ wprobe_remove_iface(&dummy_dev);
+}
+
+module_init(wprobe_dummy_init);
+module_exit(wprobe_dummy_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/package/wprobe/src/user/Makefile b/package/wprobe/src/user/Makefile
new file mode 100644
index 000000000..01e83da3e
--- /dev/null
+++ b/package/wprobe/src/user/Makefile
@@ -0,0 +1,38 @@
+include ../Makefile.inc
+
+CPPFLAGS += -I../kernel
+LDFLAGS =
+
+ifneq ($(HOST_OS),Linux)
+USE_LIBNL_MICRO=1
+else
+USE_LIBNL_MICRO=
+endif
+
+ifeq ($(USE_LIBNL_MICRO),1)
+LIBNL_PREFIX = /usr/local
+LIBNL = $(LIBNL_PREFIX)/lib/libnl-micro.a
+CPPFLAGS += -I$(LIBNL_PREFIX)/include/libnl-micro
+EXTRA_CFLAGS += -DNO_LOCAL_ACCESS
+else
+LIBNL = -lnl
+endif
+
+LIBM = -lm
+LIBS = $(LIBNL) $(LIBM)
+
+all: libwprobe.a wprobe-util
+
+libwprobe.a: wprobe-lib.o
+ rm -f $@
+ $(AR) rcu $@ $^
+ $(RANLIB) $@
+
+%.o: %.c
+ $(CC) $(WFLAGS) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) $<
+
+wprobe-util: wprobe-util.o wprobe-lib.o
+ $(CC) -o $@ $^ $(LDFLAGS) $(LIBS)
+
+clean:
+ rm -f *.o *.a wprobe-util
diff --git a/package/wprobe/src/user/list.h b/package/wprobe/src/user/list.h
new file mode 100644
index 000000000..2959a061d
--- /dev/null
+++ b/package/wprobe/src/user/list.h
@@ -0,0 +1,601 @@
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+#include <stddef.h>
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr: the pointer to the member.
+ * @type: the type of the container struct this is embedded in.
+ * @member: the name of the member within the struct.
+ *
+ */
+#ifndef container_of
+#define container_of(ptr, type, member) ( \
+ (type *)( (char *)ptr - offsetof(type,member) ))
+#endif
+
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void INIT_LIST_HEAD(struct list_head *list)
+{
+ list->next = list;
+ list->prev = list;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty() on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ entry->next = NULL;
+ entry->prev = NULL;
+}
+
+/**
+ * list_replace - replace old entry by new one
+ * @old : the element to be replaced
+ * @new : the new element to insert
+ *
+ * If @old was empty, it will be overwritten.
+ */
+static inline void list_replace(struct list_head *old,
+ struct list_head *new)
+{
+ new->next = old->next;
+ new->next->prev = new;
+ new->prev = old->prev;
+ new->prev->next = new;
+}
+
+static inline void list_replace_init(struct list_head *old,
+ struct list_head *new)
+{
+ list_replace(old, new);
+ INIT_LIST_HEAD(old);
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+ struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add_tail(list, head);
+}
+
+/**
+ * list_is_last - tests whether @list is the last entry in list @head
+ * @list: the entry to test
+ * @head: the head of the list
+ */
+static inline int list_is_last(const struct list_head *list,
+ const struct list_head *head)
+{
+ return list->next == head;
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+ return head->next == head;
+}
+
+/**
+ * list_empty_careful - tests whether a list is empty and not being modified
+ * @head: the list to test
+ *
+ * Description:
+ * tests whether a list is empty _and_ checks that no other CPU might be
+ * in the process of modifying either member (next or prev)
+ *
+ * NOTE: using list_empty_careful() without synchronization
+ * can only be safe if the only activity that can happen
+ * to the list entry is list_del_init(). Eg. it cannot be used
+ * if another CPU could re-list_add() it.
+ */
+static inline int list_empty_careful(const struct list_head *head)
+{
+ struct list_head *next = head->next;
+ return (next == head) && (next == head->prev);
+}
+
+static inline void __list_splice(struct list_head *list,
+ struct list_head *head)
+{
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(struct list_head *list, struct list_head *head)
+{
+ if (!list_empty(list))
+ __list_splice(list, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head);
+ INIT_LIST_HEAD(list);
+ }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+/**
+ * list_first_entry - get the first element from a list
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_first_entry(ptr, type, member) \
+ list_entry((ptr)->next, type, member)
+
+/**
+ * list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ */
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); \
+ pos = pos->next)
+
+/**
+ * __list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ *
+ * This variant differs from list_for_each() in that it's the
+ * simplest possible list iteration code, no prefetching is done.
+ * Use this for code that knows the list to be very short (empty
+ * or 1 entry) most of the time.
+ */
+#define __list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_prev - iterate over a list backwards
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+ for (pos = (head)->prev; pos != (head); \
+ pos = pos->prev)
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/**
+ * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_prev_safe(pos, n, head) \
+ for (pos = (head)->prev, n = pos->prev; \
+ pos != (head); \
+ pos = n, n = pos->prev)
+
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_reverse - iterate backwards over list of given type.
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_reverse(pos, head, member) \
+ for (pos = list_entry((head)->prev, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.prev, typeof(*pos), member))
+
+/**
+ * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
+ * @pos: the type * to use as a start point
+ * @head: the head of the list
+ * @member: the name of the list_struct within the struct.
+ *
+ * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
+ */
+#define list_prepare_entry(pos, head, member) \
+ ((pos) ? : list_entry(head, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue - continue iteration over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Continue to iterate over list of given type, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue(pos, head, member) \
+ for (pos = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue_reverse - iterate backwards from the given point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Start to iterate over list of given type backwards, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue_reverse(pos, head, member) \
+ for (pos = list_entry(pos->member.prev, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.prev, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_from - iterate over list of given type from the current point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type, continuing from current position.
+ */
+#define list_for_each_entry_from(pos, head, member) \
+ for (; &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_continue
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type, continuing after current point,
+ * safe against removal of list entry.
+ */
+#define list_for_each_entry_safe_continue(pos, n, head, member) \
+ for (pos = list_entry(pos->member.next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_from
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type from current point, safe against
+ * removal of list entry.
+ */
+#define list_for_each_entry_safe_from(pos, n, head, member) \
+ for (n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_reverse
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate backwards over list of given type, safe against removal
+ * of list entry.
+ */
+#define list_for_each_entry_safe_reverse(pos, n, head, member) \
+ for (pos = list_entry((head)->prev, typeof(*pos), member), \
+ n = list_entry(pos->member.prev, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.prev, typeof(*n), member))
+
+/*
+ * Double linked lists with a single pointer list head.
+ * Mostly useful for hash tables where the two pointer list head is
+ * too wasteful.
+ * You lose the ability to access the tail in O(1).
+ */
+
+struct hlist_head {
+ struct hlist_node *first;
+};
+
+struct hlist_node {
+ struct hlist_node *next, **pprev;
+};
+
+#define HLIST_HEAD_INIT { .first = NULL }
+#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
+#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
+static inline void INIT_HLIST_NODE(struct hlist_node *h)
+{
+ h->next = NULL;
+ h->pprev = NULL;
+}
+
+static inline int hlist_unhashed(const struct hlist_node *h)
+{
+ return !h->pprev;
+}
+
+static inline int hlist_empty(const struct hlist_head *h)
+{
+ return !h->first;
+}
+
+static inline void __hlist_del(struct hlist_node *n)
+{
+ struct hlist_node *next = n->next;
+ struct hlist_node **pprev = n->pprev;
+ *pprev = next;
+ if (next)
+ next->pprev = pprev;
+}
+
+static inline void hlist_del(struct hlist_node *n)
+{
+ __hlist_del(n);
+ n->next = NULL;
+ n->pprev = NULL;
+}
+
+static inline void hlist_del_init(struct hlist_node *n)
+{
+ if (!hlist_unhashed(n)) {
+ __hlist_del(n);
+ INIT_HLIST_NODE(n);
+ }
+}
+
+
+static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
+{
+ struct hlist_node *first = h->first;
+ n->next = first;
+ if (first)
+ first->pprev = &n->next;
+ h->first = n;
+ n->pprev = &h->first;
+}
+
+
+/* next must be != NULL */
+static inline void hlist_add_before(struct hlist_node *n,
+ struct hlist_node *next)
+{
+ n->pprev = next->pprev;
+ n->next = next;
+ next->pprev = &n->next;
+ *(n->pprev) = n;
+}
+
+static inline void hlist_add_after(struct hlist_node *n,
+ struct hlist_node *next)
+{
+ next->next = n->next;
+ n->next = next;
+ next->pprev = &n->next;
+
+ if(next->next)
+ next->next->pprev = &next->next;
+}
+
+#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
+
+#define hlist_for_each(pos, head) \
+ for (pos = (head)->first; pos; pos = pos->next)
+
+#define hlist_for_each_safe(pos, n, head) \
+ for (pos = (head)->first; pos; pos = n)
+
+/**
+ * hlist_for_each_entry - iterate over list of given type
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry(tpos, pos, head, member) \
+ for (pos = (head)->first; pos && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_continue(tpos, pos, member) \
+ for (pos = (pos)->next; pos && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_from - iterate over a hlist continuing from current point
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_from(tpos, pos, member) \
+ for (; pos && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @n: another &struct hlist_node to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
+ for (pos = (head)->first; \
+ pos && ({ n = pos->next; 1; }) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = n)
+
+#endif
diff --git a/package/wprobe/src/user/wprobe-lib.c b/package/wprobe/src/user/wprobe-lib.c
new file mode 100644
index 000000000..7a5460bb0
--- /dev/null
+++ b/package/wprobe/src/user/wprobe-lib.c
@@ -0,0 +1,1210 @@
+/*
+ * wprobe.c: Wireless probe user space library
+ * Copyright (C) 2008-2009 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+#define _ISOC99_SOURCE
+#define _BSD_SOURCE
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <math.h>
+#include <linux/wprobe.h>
+#include <netlink/netlink.h>
+#include <netlink/attr.h>
+#include <netlink/genl/genl.h>
+#ifndef NO_LOCAL_ACCESS
+#include <netlink/genl/ctrl.h>
+#include <netlink/genl/family.h>
+#include <endian.h>
+#endif
+#include "wprobe.h"
+
+#define DEBUG 1
+#ifdef DEBUG
+#define DPRINTF(fmt, ...) fprintf(stderr, "%s(%d): " fmt, __func__, __LINE__, ##__VA_ARGS__)
+#else
+#define DPRINTF(fmt, ...) do {} while (0)
+#endif
+
+#if defined(BYTE_ORDER) && !defined(__BYTE_ORDER)
+#define __LITTLE_ENDIAN LITTLE_ENDIAN
+#define __BIG_ENDIAN BIG_ENDIAN
+#define __BYTE_ORDER BYTE_ORDER
+#endif
+
+#ifndef __BYTE_ORDER
+#error Unknown endian type
+#endif
+
+#define WPROBE_MAX_MSGLEN 65536
+
+static inline __u16 __swab16(__u16 x)
+{
+ return x<<8 | x>>8;
+}
+
+static inline __u32 __swab32(__u32 x)
+{
+ return x<<24 | x>>24 |
+ (x & (__u32)0x0000ff00UL)<<8 |
+ (x & (__u32)0x00ff0000UL)>>8;
+}
+
+static inline __u64 __swab64(__u64 x)
+{
+ return x<<56 | x>>56 |
+ (x & (__u64)0x000000000000ff00ULL)<<40 |
+ (x & (__u64)0x0000000000ff0000ULL)<<24 |
+ (x & (__u64)0x00000000ff000000ULL)<< 8 |
+ (x & (__u64)0x000000ff00000000ULL)>> 8 |
+ (x & (__u64)0x0000ff0000000000ULL)>>24 |
+ (x & (__u64)0x00ff000000000000ULL)>>40;
+}
+
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define SWAP16(var) var = __swab16(var)
+#define SWAP32(var) var = __swab32(var)
+#define SWAP64(var) var = __swab64(var)
+#else
+#define SWAP16(var) do {} while(0)
+#define SWAP32(var) do {} while(0)
+#define SWAP64(var) do {} while(0)
+#endif
+
+int wprobe_port = 17990;
+static struct nlattr *tb[WPROBE_ATTR_LAST+1];
+static struct nla_policy attribute_policy[WPROBE_ATTR_LAST+1] = {
+ [WPROBE_ATTR_ID] = { .type = NLA_U32 },
+ [WPROBE_ATTR_MAC] = { .type = NLA_UNSPEC, .minlen = 6, .maxlen = 6 },
+ [WPROBE_ATTR_NAME] = { .type = NLA_STRING },
+ [WPROBE_ATTR_FLAGS] = { .type = NLA_U32 },
+ [WPROBE_ATTR_TYPE] = { .type = NLA_U8 },
+ [WPROBE_ATTR_FLAGS] = { .type = NLA_U32 },
+ [WPROBE_VAL_S8] = { .type = NLA_U8 },
+ [WPROBE_VAL_S16] = { .type = NLA_U16 },
+ [WPROBE_VAL_S32] = { .type = NLA_U32 },
+ [WPROBE_VAL_S64] = { .type = NLA_U64 },
+ [WPROBE_VAL_U8] = { .type = NLA_U8 },
+ [WPROBE_VAL_U16] = { .type = NLA_U16 },
+ [WPROBE_VAL_U32] = { .type = NLA_U32 },
+ [WPROBE_VAL_U64] = { .type = NLA_U64 },
+ [WPROBE_VAL_SUM] = { .type = NLA_U64 },
+ [WPROBE_VAL_SUM_SQ] = { .type = NLA_U64 },
+ [WPROBE_VAL_SAMPLES] = { .type = NLA_U32 },
+ [WPROBE_VAL_SCALE_TIME] = { .type = NLA_U64 },
+ [WPROBE_ATTR_INTERVAL] = { .type = NLA_U64 },
+ [WPROBE_ATTR_SAMPLES_MIN] = { .type = NLA_U32 },
+ [WPROBE_ATTR_SAMPLES_MAX] = { .type = NLA_U32 },
+ [WPROBE_ATTR_SAMPLES_SCALE_M] = { .type = NLA_U32 },
+ [WPROBE_ATTR_SAMPLES_SCALE_D] = { .type = NLA_U32 },
+ [WPROBE_ATTR_FILTER_GROUP] = { .type = NLA_NESTED },
+ [WPROBE_ATTR_RXCOUNT] = { .type = NLA_U64 },
+ [WPROBE_ATTR_TXCOUNT] = { .type = NLA_U64 },
+};
+
+typedef int (*wprobe_cb_t)(struct nl_msg *, void *);
+
+struct wprobe_iface_ops {
+ int (*send_msg)(struct wprobe_iface *dev, struct nl_msg *msg, wprobe_cb_t cb, void *arg);
+ void (*free)(struct wprobe_iface *dev);
+};
+
+struct wprobe_attr_cb {
+ struct list_head *list;
+ char *addr;
+};
+
+#define WPROBE_MAGIC_STR "WPROBE"
+struct wprobe_init_hdr {
+ struct {
+ char magic[sizeof(WPROBE_MAGIC_STR)];
+
+ /* protocol version */
+ uint8_t version;
+
+ /* extra header length (unused for now) */
+ uint16_t extra;
+ } pre __attribute__((packed));
+ union {
+ struct {
+ uint16_t genl_family;
+ } v0 __attribute__((packed));
+ };
+} __attribute__((packed));
+
+struct wprobe_msg_hdr {
+ __u16 status;
+ __u16 error;
+ __u32 len;
+};
+
+enum wprobe_resp_status {
+ WPROBE_MSG_DONE = 0,
+ WPROBE_MSG_DATA = 1,
+};
+
+static inline void
+wprobe_swap_msg_hdr(struct wprobe_msg_hdr *mhdr)
+{
+ SWAP16(mhdr->status);
+ SWAP16(mhdr->error);
+ SWAP32(mhdr->len);
+}
+
+static int
+save_attribute_handler(struct nl_msg *msg, void *arg)
+{
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ const char *name = "N/A";
+ struct wprobe_attribute *attr;
+ int type = 0;
+ struct wprobe_attr_cb *cb = arg;
+
+ nla_parse(tb, WPROBE_ATTR_LAST, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), attribute_policy);
+
+ if (tb[WPROBE_ATTR_NAME])
+ name = nla_data(tb[WPROBE_ATTR_NAME]);
+
+ attr = malloc(sizeof(struct wprobe_attribute) + strlen(name) + 1);
+ if (!attr)
+ return -1;
+
+ memset(attr, 0, sizeof(struct wprobe_attribute));
+
+ if (tb[WPROBE_ATTR_ID])
+ attr->id = nla_get_u32(tb[WPROBE_ATTR_ID]);
+
+ if (tb[WPROBE_ATTR_MAC] && cb->addr)
+ memcpy(cb->addr, nla_data(tb[WPROBE_ATTR_MAC]), 6);
+
+ if (tb[WPROBE_ATTR_FLAGS])
+ attr->flags = nla_get_u32(tb[WPROBE_ATTR_FLAGS]);
+
+ if (tb[WPROBE_ATTR_TYPE])
+ type = nla_get_u8(tb[WPROBE_ATTR_TYPE]);
+
+ if ((type < WPROBE_VAL_STRING) ||
+ (type > WPROBE_VAL_U64))
+ type = 0;
+
+ attr->type = type;
+ strcpy(attr->name, name);
+ INIT_LIST_HEAD(&attr->list);
+ list_add(&attr->list, cb->list);
+ return 0;
+}
+
+static struct nl_msg *
+wprobe_new_msg(struct wprobe_iface *dev, int cmd, bool dump)
+{
+ struct nl_msg *msg;
+ uint32_t flags = 0;
+
+ msg = nlmsg_alloc_size(65536);
+ if (!msg)
+ return NULL;
+
+ if (dump)
+ flags |= NLM_F_DUMP;
+
+ genlmsg_put(msg, 0, 0, dev->genl_family,
+ 0, flags, cmd, 0);
+
+ NLA_PUT_STRING(msg, WPROBE_ATTR_INTERFACE, dev->ifname);
+nla_put_failure:
+ return msg;
+}
+
+
+static int
+dump_attributes(struct wprobe_iface *dev, bool link, struct list_head *list, char *addr)
+{
+ struct nl_msg *msg;
+ struct wprobe_attr_cb cb;
+
+ cb.list = list;
+ cb.addr = addr;
+ msg = wprobe_new_msg(dev, WPROBE_CMD_GET_LIST, true);
+ if (!msg)
+ return -ENOMEM;
+
+ if (link)
+ NLA_PUT(msg, WPROBE_ATTR_MAC, 6, "\x00\x00\x00\x00\x00\x00");
+
+ return dev->ops->send_msg(dev, msg, save_attribute_handler, &cb);
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -EINVAL;
+}
+
+static struct wprobe_iface *
+wprobe_alloc_dev(void)
+{
+ struct wprobe_iface *dev;
+
+ dev = malloc(sizeof(struct wprobe_iface));
+ if (!dev)
+ return NULL;
+
+ memset(dev, 0, sizeof(struct wprobe_iface));
+
+ dev->interval = -1;
+ dev->scale_min = -1;
+ dev->scale_max = -1;
+ dev->scale_m = -1;
+ dev->scale_d = -1;
+ dev->sockfd = -1;
+
+ INIT_LIST_HEAD(&dev->global_attr);
+ INIT_LIST_HEAD(&dev->link_attr);
+ INIT_LIST_HEAD(&dev->links);
+ return dev;
+}
+
+static int
+wprobe_init_dev(struct wprobe_iface *dev)
+{
+ dump_attributes(dev, false, &dev->global_attr, NULL);
+ dump_attributes(dev, true, &dev->link_attr, NULL);
+ return 0;
+}
+
+#ifndef NO_LOCAL_ACCESS
+static int n_devs = 0;
+static struct nl_sock *handle = NULL;
+static struct nl_cache *cache = NULL;
+static struct genl_family *family = NULL;
+
+static int
+error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
+{
+ int *ret = arg;
+ *ret = err->error;
+ return NL_STOP;
+}
+
+static int
+finish_handler(struct nl_msg *msg, void *arg)
+{
+ int *ret = arg;
+ *ret = 0;
+ return NL_SKIP;
+}
+
+static int
+ack_handler(struct nl_msg *msg, void *arg)
+{
+ int *ret = arg;
+ *ret = 0;
+ return NL_STOP;
+}
+
+static void
+wprobe_local_free(struct wprobe_iface *dev)
+{
+ /* should not happen */
+ if (n_devs == 0)
+ return;
+
+ if (--n_devs != 0)
+ return;
+
+ if (cache)
+ nl_cache_free(cache);
+ if (handle)
+ nl_socket_free(handle);
+ handle = NULL;
+ cache = NULL;
+}
+
+static int
+wprobe_local_init(void)
+{
+ int ret;
+
+ if (n_devs++ > 0)
+ return 0;
+
+ handle = nl_socket_alloc();
+ if (!handle) {
+ DPRINTF("Failed to create handle\n");
+ goto err;
+ }
+
+ if (genl_connect(handle)) {
+ DPRINTF("Failed to connect to generic netlink\n");
+ goto err;
+ }
+
+ ret = genl_ctrl_alloc_cache(handle, &cache);
+ if (ret < 0) {
+ DPRINTF("Failed to allocate netlink cache\n");
+ goto err;
+ }
+
+ family = genl_ctrl_search_by_name(cache, "wprobe");
+ if (!family) {
+ DPRINTF("wprobe API not present\n");
+ goto err;
+ }
+ return 0;
+
+err:
+ wprobe_local_free(NULL);
+ return -EINVAL;
+}
+
+
+static int
+wprobe_local_send_msg(struct wprobe_iface *dev, struct nl_msg *msg, wprobe_cb_t callback, void *arg)
+{
+ struct nl_cb *cb;
+ int err = 0;
+
+ cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!cb)
+ goto out_no_cb;
+
+ if (callback)
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, callback, arg);
+
+ err = nl_send_auto_complete(handle, msg);
+ if (err < 0)
+ goto out;
+
+ err = 1;
+
+ nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
+ nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
+ nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
+
+ while (err > 0)
+ nl_recvmsgs(handle, cb);
+
+out:
+ nl_cb_put(cb);
+out_no_cb:
+ nlmsg_free(msg);
+ return err;
+}
+
+static const struct wprobe_iface_ops wprobe_local_ops = {
+ .send_msg = wprobe_local_send_msg,
+ .free = wprobe_local_free,
+};
+
+struct wprobe_iface *
+wprobe_get_dev(const char *ifname)
+{
+ struct wprobe_iface *dev;
+
+ if (wprobe_local_init() != 0)
+ return NULL;
+
+ dev = wprobe_alloc_dev();
+ if (!dev)
+ goto error_alloc;
+
+ dev->ifname = strdup(ifname);
+ dev->ops = &wprobe_local_ops;
+ dev->genl_family = genl_family_get_id(family);
+
+ if (wprobe_init_dev(dev) < 0)
+ goto error;
+
+ return dev;
+
+error:
+ free(dev);
+error_alloc:
+ wprobe_local_free(NULL);
+ return NULL;
+}
+
+#endif
+
+static void swap_nlmsghdr(struct nlmsghdr *nlh)
+{
+ SWAP32(nlh->nlmsg_len);
+ SWAP16(nlh->nlmsg_type);
+ SWAP16(nlh->nlmsg_flags);
+ SWAP32(nlh->nlmsg_seq);
+ SWAP32(nlh->nlmsg_pid);
+}
+
+static void swap_genlmsghdr(struct genlmsghdr *gnlh)
+{
+#if 0 /* probably unnecessary */
+ SWAP16(gnlh->reserved);
+#endif
+}
+
+static void
+wprobe_swap_nested(void *data, int len, bool outgoing)
+{
+ void *end = data + len;
+
+ while (data < end) {
+ struct nlattr *nla = data;
+ unsigned int type, len;
+
+ if (!outgoing) {
+ SWAP16(nla->nla_len);
+ SWAP16(nla->nla_type);
+
+ /* required for further sanity checks */
+ if (data + nla->nla_len > end)
+ nla->nla_len = end - data;
+ }
+
+ len = NLA_ALIGN(nla->nla_len);
+ type = nla->nla_type & NLA_TYPE_MASK;
+
+ if (type <= WPROBE_ATTR_LAST) {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ switch(attribute_policy[type].type) {
+ case NLA_U16:
+ SWAP16(*(__u16 *)nla_data(nla));
+ break;
+ case NLA_U32:
+ SWAP32(*(__u32 *)nla_data(nla));
+ break;
+ case NLA_U64:
+ SWAP64(*(__u64 *)nla_data(nla));
+ break;
+ case NLA_NESTED:
+ wprobe_swap_nested(nla_data(nla), nla_len(nla), outgoing);
+ break;
+ }
+#endif
+ }
+ data += len;
+
+ if (outgoing) {
+ SWAP16(nla->nla_len);
+ SWAP16(nla->nla_type);
+ }
+ if (!nla->nla_len)
+ break;
+ }
+}
+
+static struct nl_msg *
+wprobe_msg_from_network(int socket, int len)
+{
+ struct genlmsghdr *gnlh;
+ struct nlmsghdr *nlh;
+ struct nl_msg *msg;
+ void *data;
+
+ msg = nlmsg_alloc_size(len + 32);
+ if (!msg)
+ return NULL;
+
+ nlh = nlmsg_hdr(msg);
+ if (read(socket, nlh, len) != len)
+ goto free;
+
+ swap_nlmsghdr(nlh);
+ if (nlh->nlmsg_len > len)
+ goto free;
+
+ gnlh = nlmsg_data(nlh);
+ swap_genlmsghdr(gnlh);
+
+ data = genlmsg_data(gnlh);
+ wprobe_swap_nested(data, genlmsg_len(gnlh), false);
+
+ return msg;
+free:
+ nlmsg_free(msg);
+ return NULL;
+}
+
+static int
+wprobe_msg_to_network(int socket, struct nl_msg *msg)
+{
+ struct nlmsghdr *nlh = nlmsg_hdr(msg);
+ struct wprobe_msg_hdr mhdr;
+ struct genlmsghdr *gnlh;
+ void *buf, *data;
+ int buflen, datalen;
+ int ret;
+
+ buflen = nlh->nlmsg_len;
+ buf = malloc(buflen);
+ if (!buf)
+ return -ENOMEM;
+
+ memset(&mhdr, 0, sizeof(mhdr));
+ mhdr.status = WPROBE_MSG_DATA;
+ mhdr.len = buflen;
+ wprobe_swap_msg_hdr(&mhdr);
+ ret = write(socket, &mhdr, sizeof(mhdr));
+ if (ret < 0)
+ goto out;
+
+ memcpy(buf, nlh, buflen);
+ nlh = buf;
+ gnlh = nlmsg_data(nlh);
+ data = genlmsg_data(gnlh);
+ datalen = genlmsg_len(gnlh);
+
+ wprobe_swap_nested(data, datalen, true);
+ swap_genlmsghdr(gnlh);
+ swap_nlmsghdr(nlh);
+ ret = write(socket, buf, buflen);
+
+out:
+ free(buf);
+
+ return ret;
+}
+
+static int
+wprobe_remote_send_msg(struct wprobe_iface *dev, struct nl_msg *msg, wprobe_cb_t callback, void *arg)
+{
+ struct wprobe_msg_hdr mhdr;
+ int msgs = 0;
+
+ wprobe_msg_to_network(dev->sockfd, msg);
+ nlmsg_free(msg);
+ do {
+ if (read(dev->sockfd, &mhdr, sizeof(mhdr)) != sizeof(mhdr)) {
+ DPRINTF("Failed to read response header\n");
+ return -1;
+ }
+ wprobe_swap_msg_hdr(&mhdr);
+
+ switch(mhdr.status) {
+ case WPROBE_MSG_DATA:
+ if (mhdr.len > WPROBE_MAX_MSGLEN) {
+ fprintf(stderr, "Invalid length in received response message.\n");
+ exit(1);
+ }
+
+ msg = wprobe_msg_from_network(dev->sockfd, mhdr.len);
+ if (!msg)
+ return -EINVAL;
+
+ msgs++;
+ callback(msg, arg);
+ nlmsg_free(msg);
+ break;
+ }
+ } while (mhdr.status != WPROBE_MSG_DONE);
+
+ if (mhdr.error)
+ return -mhdr.error;
+ else
+ return msgs;
+}
+
+
+static void
+wprobe_socket_dev_free(struct wprobe_iface *dev)
+{
+ if (dev->sockfd >= 0)
+ close(dev->sockfd);
+}
+
+static const struct wprobe_iface_ops wprobe_remote_ops = {
+ .send_msg = wprobe_remote_send_msg,
+ .free = wprobe_socket_dev_free,
+};
+
+
+#ifndef NO_LOCAL_ACCESS
+int
+wprobe_server_init(int socket)
+{
+ struct wprobe_init_hdr hdr;
+ int ret;
+
+ ret = wprobe_local_init();
+ if (ret != 0)
+ return ret;
+
+ memset(&hdr, 0, sizeof(hdr));
+ memcpy(hdr.pre.magic, WPROBE_MAGIC_STR, sizeof(WPROBE_MAGIC_STR));
+ hdr.pre.version = 0;
+ hdr.v0.genl_family = genl_family_get_id(family);
+ SWAP16(hdr.v0.genl_family);
+ write(socket, (unsigned char *)&hdr, sizeof(hdr));
+
+ return 0;
+}
+
+static int
+wprobe_server_cb(struct nl_msg *msg, void *arg)
+{
+ int *socket = arg;
+ int ret;
+
+ ret = wprobe_msg_to_network(*socket, msg);
+ if (ret > 0)
+ ret = 0;
+
+ return ret;
+}
+
+
+int
+wprobe_server_handle(int socket)
+{
+ struct wprobe_msg_hdr mhdr;
+ struct nl_msg *msg;
+ int ret;
+
+ ret = read(socket, &mhdr, sizeof(mhdr));
+ if (ret != sizeof(mhdr)) {
+ if (ret <= 0)
+ return -1;
+
+ DPRINTF("Failed to read request header\n");
+ return -EINVAL;
+ }
+ wprobe_swap_msg_hdr(&mhdr);
+
+ switch(mhdr.status) {
+ case WPROBE_MSG_DATA:
+ if (mhdr.len > WPROBE_MAX_MSGLEN) {
+ DPRINTF("Invalid length in received response message.\n");
+ return -EINVAL;
+ }
+ msg = wprobe_msg_from_network(socket, mhdr.len);
+ break;
+ default:
+ DPRINTF("Invalid request header type\n");
+ return -ENOENT;
+ }
+
+ if (!msg) {
+ DPRINTF("Failed to get message\n");
+ return -EINVAL;
+ }
+
+ ret = wprobe_local_send_msg(NULL, msg, wprobe_server_cb, &socket);
+
+ memset(&mhdr, 0, sizeof(mhdr));
+ mhdr.status = WPROBE_MSG_DONE;
+ if (ret < 0)
+ mhdr.error = (uint16_t) -ret;
+
+ ret = write(socket, (unsigned char *)&mhdr, sizeof(mhdr));
+ if (ret > 0)
+ ret = 0;
+
+ return ret;
+}
+
+void
+wprobe_server_done(void)
+{
+ wprobe_local_free(NULL);
+}
+#endif
+
+struct wprobe_iface *
+wprobe_get_from_socket(int socket, const char *name)
+{
+ struct wprobe_iface *dev;
+ struct wprobe_init_hdr hdr;
+
+ dev = wprobe_alloc_dev();
+ if (!dev)
+ goto out;
+
+ dev->ops = &wprobe_remote_ops;
+ dev->sockfd = socket;
+ dev->ifname = strdup(name);
+
+ /* read version and header length */
+ if (read(socket, &hdr.pre, sizeof(hdr.pre)) != sizeof(hdr.pre)) {
+ DPRINTF("Could not read header\n");
+ goto error;
+ }
+
+ /* magic not found */
+ if (memcmp(hdr.pre.magic, WPROBE_MAGIC_STR, sizeof(hdr.pre.magic)) != 0) {
+ DPRINTF("Magic does not match\n");
+ goto error;
+ }
+
+ /* unsupported version */
+ if (hdr.pre.version != 0) {
+ DPRINTF("Protocol version does not match\n");
+ goto error;
+ }
+
+ if (read(socket, &hdr.v0, sizeof(hdr.v0)) != sizeof(hdr.v0)) {
+ DPRINTF("Could not read header data\n");
+ goto error;
+ }
+
+ SWAP16(hdr.pre.extra);
+ SWAP16(hdr.v0.genl_family);
+ dev->genl_family = hdr.v0.genl_family;
+
+ if (wprobe_init_dev(dev) < 0) {
+ DPRINTF("Could not initialize device\n");
+ goto error;
+ }
+
+out:
+ return dev;
+
+error:
+ wprobe_free_dev(dev);
+ return NULL;
+}
+
+struct wprobe_iface *
+wprobe_get_auto(const char *arg, char **err)
+{
+ static struct sockaddr_in sa;
+ static char errbuf[512];
+
+ struct wprobe_iface *dev = NULL;
+ struct hostent *h;
+ char *devstr = strdup(arg);
+ char *sep = NULL;
+ int sock = -1;
+ int len;
+
+ if (err)
+ *err = NULL;
+
+ sep = strchr(devstr, ':');
+ if (!sep) {
+#ifndef NO_LOCAL_ACCESS
+ free(devstr);
+ return wprobe_get_dev(arg);
+#else
+ if (err)
+ *err = "Invalid argument";
+ goto out;
+#endif
+ }
+
+ *sep = 0;
+ sep++;
+
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock < 0)
+ goto syserr;
+
+ h = gethostbyname(devstr);
+ if (!h) {
+ sprintf(errbuf, "Host not found");
+ goto out_err;
+ }
+
+ memcpy(&sa.sin_addr, h->h_addr, h->h_length);
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons(wprobe_port);
+ if (connect(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0)
+ goto syserr;
+
+ dev = wprobe_get_from_socket(sock, sep);
+ if (!dev) {
+ sprintf(errbuf, "wprobe connection initialization failed");
+ goto out_err;
+ }
+ goto out;
+
+syserr:
+ if (err) {
+ strcpy(errbuf, "Connection failed: ");
+ len = strlen(errbuf);
+ strerror_r(errno, errbuf + len, sizeof(errbuf) - len - 1);
+ }
+out_err:
+ if (err)
+ *err = errbuf;
+ if (sock >= 0)
+ close(sock);
+out:
+ if (devstr)
+ free(devstr);
+ return dev;
+}
+
+static void
+free_attr_list(struct list_head *list)
+{
+ struct wprobe_attribute *attr, *tmp;
+
+ list_for_each_entry_safe(attr, tmp, list, list) {
+ list_del(&attr->list);
+ free(attr);
+ }
+}
+
+void
+wprobe_free_dev(struct wprobe_iface *dev)
+{
+ if (dev->ops->free)
+ dev->ops->free(dev);
+ free_attr_list(&dev->global_attr);
+ free_attr_list(&dev->link_attr);
+ free((void *)dev->ifname);
+ free(dev);
+}
+
+static struct wprobe_link *
+get_link(struct list_head *list, const char *addr)
+{
+ struct wprobe_link *l;
+
+ list_for_each_entry(l, list, list) {
+ if (!memcmp(l->addr, addr, 6)) {
+ list_del_init(&l->list);
+ goto out;
+ }
+ }
+
+ /* no previous link found, allocate a new one */
+ l = malloc(sizeof(struct wprobe_link));
+ if (!l)
+ goto out;
+
+ memset(l, 0, sizeof(struct wprobe_link));
+ memcpy(l->addr, addr, sizeof(l->addr));
+ INIT_LIST_HEAD(&l->list);
+
+out:
+ return l;
+}
+
+struct wprobe_save_cb {
+ struct list_head *list;
+ struct list_head old_list;
+};
+
+static int
+save_link_handler(struct nl_msg *msg, void *arg)
+{
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct wprobe_link *link;
+ struct wprobe_save_cb *cb = arg;
+ const char *addr;
+
+ nla_parse(tb, WPROBE_ATTR_LAST, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), attribute_policy);
+
+ if (!tb[WPROBE_ATTR_MAC] || (nla_len(tb[WPROBE_ATTR_MAC]) != 6))
+ return -1;
+
+ addr = nla_data(tb[WPROBE_ATTR_MAC]);
+ link = get_link(&cb->old_list, addr);
+ if (!link)
+ return -1;
+
+ if (tb[WPROBE_ATTR_FLAGS])
+ link->flags = nla_get_u32(tb[WPROBE_ATTR_FLAGS]);
+
+ list_add_tail(&link->list, cb->list);
+ return 0;
+}
+
+
+int
+wprobe_update_links(struct wprobe_iface *dev)
+{
+ struct wprobe_link *l, *tmp;
+ struct nl_msg *msg;
+ struct wprobe_save_cb cb;
+ int err;
+
+ INIT_LIST_HEAD(&cb.old_list);
+ list_splice_init(&dev->links, &cb.old_list);
+ cb.list = &dev->links;
+
+ msg = wprobe_new_msg(dev, WPROBE_CMD_GET_LINKS, true);
+ if (!msg)
+ return -ENOMEM;
+
+ err = dev->ops->send_msg(dev, msg, save_link_handler, &cb);
+ if (err < 0)
+ return err;
+
+ list_for_each_entry_safe(l, tmp, &cb.old_list, list) {
+ list_del(&l->list);
+ free(l);
+ }
+
+ return 0;
+}
+
+
+struct wprobe_filter_data
+{
+ wprobe_filter_cb cb;
+ void *arg;
+ struct wprobe_filter_item *buf;
+ int buflen;
+};
+
+static int
+dump_filter_handler(struct nl_msg *msg, void *arg)
+{
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct wprobe_filter_data *data = arg;
+ struct nlattr *p;
+ const char *name;
+ int count = 0;
+ int len;
+
+ nla_parse(tb, WPROBE_ATTR_LAST, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), attribute_policy);
+
+ if (!tb[WPROBE_ATTR_NAME] || !tb[WPROBE_ATTR_FILTER_GROUP])
+ return -1;
+
+ name = nla_data(tb[WPROBE_ATTR_NAME]);
+ nla_for_each_nested(p, tb[WPROBE_ATTR_FILTER_GROUP], len) {
+ count++;
+ }
+
+ if (data->buflen < count) {
+ if (data->buf)
+ free(data->buf);
+ data->buflen = count;
+ data->buf = malloc(sizeof(struct wprobe_filter_item) * count);
+ memset(data->buf, 0, sizeof(struct wprobe_filter_item) * count);
+ }
+
+ count = 0;
+ nla_for_each_nested(p, tb[WPROBE_ATTR_FILTER_GROUP], len) {
+ struct wprobe_filter_item *fi;
+
+ nla_parse(tb, WPROBE_ATTR_LAST, nla_data(p),
+ nla_len(p), attribute_policy);
+
+ if (!tb[WPROBE_ATTR_NAME] || !tb[WPROBE_ATTR_RXCOUNT]
+ || !tb[WPROBE_ATTR_TXCOUNT])
+ continue;
+
+ fi = &data->buf[count++];
+ strncpy(fi->name, nla_data(tb[WPROBE_ATTR_NAME]), sizeof(fi->name) - 1);
+ fi->name[sizeof(fi->name) - 1] = 0;
+ fi->rx = nla_get_u64(tb[WPROBE_ATTR_RXCOUNT]);
+ fi->tx = nla_get_u64(tb[WPROBE_ATTR_TXCOUNT]);
+ }
+ data->cb(data->arg, name, data->buf, count);
+
+ return 0;
+}
+
+int
+wprobe_dump_filters(struct wprobe_iface *dev, wprobe_filter_cb cb, void *arg)
+{
+ struct wprobe_filter_data data;
+ struct nl_msg *msg;
+ int err;
+
+ data.buf = 0;
+ data.buflen = 0;
+ data.cb = cb;
+ data.arg = arg;
+
+ msg = wprobe_new_msg(dev, WPROBE_CMD_GET_FILTER, true);
+ if (!msg)
+ return -ENOMEM;
+
+ err = dev->ops->send_msg(dev, msg, dump_filter_handler, &data);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+int
+wprobe_apply_config(struct wprobe_iface *dev)
+{
+ struct nl_msg *msg;
+
+ msg = wprobe_new_msg(dev, WPROBE_CMD_CONFIG, false);
+ if (!msg)
+ return -ENOMEM;
+
+ if (dev->interval >= 0)
+ NLA_PUT_MSECS(msg, WPROBE_ATTR_INTERVAL, dev->interval);
+
+ if (dev->filter_len < 0) {
+ NLA_PUT(msg, WPROBE_ATTR_FILTER, 0, NULL);
+ dev->filter_len = 0;
+ } else if (dev->filter && dev->filter_len > 0) {
+ NLA_PUT(msg, WPROBE_ATTR_FILTER, dev->filter_len, dev->filter);
+ }
+ dev->filter = NULL;
+
+ dev->ops->send_msg(dev, msg, NULL, NULL);
+ return 0;
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -ENOMEM;
+}
+
+int
+wprobe_measure(struct wprobe_iface *dev)
+{
+ struct nl_msg *msg;
+
+ msg = wprobe_new_msg(dev, WPROBE_CMD_MEASURE, false);
+ if (!msg)
+ return -ENOMEM;
+
+ dev->ops->send_msg(dev, msg, NULL, NULL);
+ return 0;
+}
+
+struct wprobe_request_cb {
+ struct list_head *list;
+ struct list_head old_list;
+ char *addr;
+};
+
+static int
+save_attrdata_handler(struct nl_msg *msg, void *arg)
+{
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct wprobe_request_cb *cb = arg;
+ struct wprobe_attribute *attr;
+ int type, id;
+
+ nla_parse(tb, WPROBE_ATTR_LAST, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), attribute_policy);
+
+ if (!tb[WPROBE_ATTR_ID])
+ return -1;
+
+ if (!tb[WPROBE_ATTR_TYPE])
+ return -1;
+
+ id = nla_get_u32(tb[WPROBE_ATTR_ID]);
+ list_for_each_entry(attr, &cb->old_list, list) {
+ if (attr->id == id)
+ goto found;
+ }
+ /* not found */
+ return -1;
+
+found:
+ list_del_init(&attr->list);
+
+ type = nla_get_u8(tb[WPROBE_ATTR_TYPE]);
+ if (type != attr->type) {
+ DPRINTF("WARNING: type mismatch for %s attribute '%s' (%d != %d)\n",
+ (cb->addr ? "link" : "global"),
+ attr->name,
+ type, attr->type);
+ goto out;
+ }
+
+ if ((type < WPROBE_VAL_STRING) ||
+ (type > WPROBE_VAL_U64))
+ goto out;
+
+ memset(&attr->val, 0, sizeof(attr->val));
+
+#define HANDLE_INT_TYPE(_idx, _type) \
+ case WPROBE_VAL_S##_type: \
+ case WPROBE_VAL_U##_type: \
+ attr->val.U##_type = nla_get_u##_type(tb[_idx]); \
+ break
+
+ switch(type) {
+ HANDLE_INT_TYPE(type, 8);
+ HANDLE_INT_TYPE(type, 16);
+ HANDLE_INT_TYPE(type, 32);
+ HANDLE_INT_TYPE(type, 64);
+ case WPROBE_VAL_STRING:
+ /* unimplemented */
+ break;
+ }
+#undef HANDLE_TYPE
+
+ if (attr->flags & WPROBE_F_KEEPSTAT) {
+ if (tb[WPROBE_VAL_SUM])
+ attr->val.s = nla_get_u64(tb[WPROBE_VAL_SUM]);
+
+ if (tb[WPROBE_VAL_SUM_SQ])
+ attr->val.ss = nla_get_u64(tb[WPROBE_VAL_SUM_SQ]);
+
+ if (tb[WPROBE_VAL_SAMPLES])
+ attr->val.n = nla_get_u32(tb[WPROBE_VAL_SAMPLES]);
+
+ if (attr->val.n > 0) {
+ float avg = ((float) attr->val.s) / attr->val.n;
+ float stdev = sqrt((((float) attr->val.ss) / attr->val.n) - (avg * avg));
+ if (isnan(stdev))
+ stdev = 0.0f;
+ if (isnan(avg))
+ avg = 0.0f;
+ attr->val.avg = avg;
+ attr->val.stdev = stdev;
+ }
+ }
+
+out:
+ list_add_tail(&attr->list, cb->list);
+ return 0;
+}
+
+
+int
+wprobe_request_data(struct wprobe_iface *dev, const unsigned char *addr)
+{
+ struct wprobe_request_cb cb;
+ struct list_head *attrs;
+ struct nl_msg *msg;
+ int err;
+
+ msg = wprobe_new_msg(dev, WPROBE_CMD_GET_INFO, true);
+ if (!msg)
+ return -ENOMEM;
+
+ if (addr) {
+ attrs = &dev->link_attr;
+ NLA_PUT(msg, WPROBE_ATTR_MAC, 6, addr);
+ } else {
+ attrs = &dev->global_attr;
+ }
+
+ INIT_LIST_HEAD(&cb.old_list);
+ list_splice_init(attrs, &cb.old_list);
+ cb.list = attrs;
+
+ err = dev->ops->send_msg(dev, msg, save_attrdata_handler, &cb);
+ list_splice(&cb.old_list, attrs->prev);
+ return err;
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -ENOMEM;
+}
+
+
diff --git a/package/wprobe/src/user/wprobe-util.c b/package/wprobe/src/user/wprobe-util.c
new file mode 100644
index 000000000..654442f9c
--- /dev/null
+++ b/package/wprobe/src/user/wprobe-util.c
@@ -0,0 +1,450 @@
+/*
+ * wprobe-test.c: Wireless probe user space test code
+ * Copyright (C) 2008-2009 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include <linux/wprobe.h>
+#include "wprobe.h"
+
+static bool simple_mode = false;
+
+static const char *
+wprobe_dump_value(struct wprobe_attribute *attr)
+{
+ static char buf[128];
+
+#define HANDLE_TYPE(_type, _format) \
+ case WPROBE_VAL_##_type: \
+ snprintf(buf, sizeof(buf), _format, attr->val._type); \
+ break
+
+ switch(attr->type) {
+ HANDLE_TYPE(S8, "%d");
+ HANDLE_TYPE(S16, "%d");
+ HANDLE_TYPE(S32, "%d");
+ HANDLE_TYPE(S64, "%lld");
+ HANDLE_TYPE(U8, "%d");
+ HANDLE_TYPE(U16, "%d");
+ HANDLE_TYPE(U32, "%d");
+ HANDLE_TYPE(U64, "%lld");
+ case WPROBE_VAL_STRING:
+ /* FIXME: implement this */
+ default:
+ strncpy(buf, "<unknown>", sizeof(buf));
+ break;
+ }
+ if ((attr->flags & WPROBE_F_KEEPSTAT) &&
+ (attr->val.n > 0)) {
+ int len = strlen(buf);
+ if (simple_mode)
+ snprintf(buf + len, sizeof(buf) - len, ";%.02f;%.02f;%d;%lld;%lld", attr->val.avg, attr->val.stdev, attr->val.n, attr->val.s, attr->val.ss);
+ else
+ snprintf(buf + len, sizeof(buf) - len, " (avg: %.02f; stdev: %.02f, n=%d)", attr->val.avg, attr->val.stdev, attr->val.n);
+ }
+#undef HANDLE_TYPE
+
+ return buf;
+}
+
+
+static void
+wprobe_dump_data(struct wprobe_iface *dev)
+{
+ struct wprobe_attribute *attr;
+ struct wprobe_link *link;
+ bool first = true;
+
+ if (!simple_mode)
+ fprintf(stdout, "\n");
+ wprobe_request_data(dev, NULL);
+ list_for_each_entry(attr, &dev->global_attr, list) {
+ if (simple_mode) {
+ if (first)
+ fprintf(stdout, "[global]\n");
+ fprintf(stdout, "%s=%s\n", attr->name, wprobe_dump_value(attr));
+ } else {
+ fprintf(stdout, (first ?
+ "Global: %s=%s\n" :
+ " %s=%s\n"),
+ attr->name,
+ wprobe_dump_value(attr)
+ );
+ }
+ first = false;
+ }
+
+ list_for_each_entry(link, &dev->links, list) {
+ first = true;
+ wprobe_request_data(dev, link->addr);
+ list_for_each_entry(attr, &dev->link_attr, list) {
+ if (first) {
+ fprintf(stdout,
+ (simple_mode ?
+ "[%02x:%02x:%02x:%02x:%02x:%02x]\n%s=%s\n" :
+ "%02x:%02x:%02x:%02x:%02x:%02x: %s=%s\n"),
+ link->addr[0], link->addr[1], link->addr[2],
+ link->addr[3], link->addr[4], link->addr[5],
+ attr->name,
+ wprobe_dump_value(attr));
+ first = false;
+ } else {
+ fprintf(stdout,
+ (simple_mode ? "%s=%s\n" :
+ " %s=%s\n"),
+ attr->name,
+ wprobe_dump_value(attr));
+ }
+ }
+ }
+ fflush(stdout);
+}
+
+static const char *attr_typestr[] = {
+ [0] = "Unknown",
+ [WPROBE_VAL_STRING] = "String",
+ [WPROBE_VAL_U8] = "Unsigned 8 bit",
+ [WPROBE_VAL_U16] = "Unsigned 16 bit",
+ [WPROBE_VAL_U32] = "Unsigned 32 bit",
+ [WPROBE_VAL_U64] = "Unsigned 64 bit",
+ [WPROBE_VAL_S8] = "Signed 8 bit",
+ [WPROBE_VAL_S16] = "Signed 16 bit",
+ [WPROBE_VAL_S32] = "Signed 32 bit",
+ [WPROBE_VAL_S64] = "Signed 64 bit",
+};
+
+static int usage(const char *prog)
+{
+ fprintf(stderr,
+#ifndef NO_LOCAL_ACCESS
+ "Usage: %s <interface>|<host>:<device>|-P [options]\n"
+#else
+ "Usage: %s <host>:<device> [options]\n"
+#endif
+ "\n"
+ "Options:\n"
+ " -a: Print attributes\n"
+ " -c: Only apply configuration\n"
+ " -d: Delay between measurement dumps (in milliseconds, default: 1000)\n"
+ " A value of 0 (zero) prints once and exits; useful for scripts\n"
+ " -f: Dump contents of layer 2 filter counters during measurement\n"
+ " -F <file>: Apply layer 2 filters from <file>\n"
+ " -h: This help text\n"
+ " -i <interval>: Set measurement interval\n"
+ " -m: Run measurement loop\n"
+ " -p: Set the TCP port for server/client (default: 17990)\n"
+#ifndef NO_LOCAL_ACCESS
+ " -P: Run in proxy mode (listen on network)\n"
+#endif
+ "\n"
+ , prog);
+ exit(1);
+}
+
+static void show_attributes(struct wprobe_iface *dev)
+{
+ struct wprobe_attribute *attr;
+ if (simple_mode)
+ return;
+ list_for_each_entry(attr, &dev->global_attr, list) {
+ fprintf(stdout, "Global attribute: '%s' (%s)\n",
+ attr->name, attr_typestr[attr->type]);
+ }
+ list_for_each_entry(attr, &dev->link_attr, list) {
+ fprintf(stdout, "Link attribute: '%s' (%s)\n",
+ attr->name, attr_typestr[attr->type]);
+ }
+}
+
+static void show_filter_simple(void *arg, const char *group, struct wprobe_filter_item *items, int n_items)
+{
+ int i;
+
+ fprintf(stdout, "[filter:%s]\n", group);
+ for (i = 0; i < n_items; i++) {
+ fprintf(stdout, "%s=%lld;%lld\n",
+ items[i].name, items[i].tx, items[i].rx);
+ }
+ fflush(stdout);
+}
+
+
+static void show_filter(void *arg, const char *group, struct wprobe_filter_item *items, int n_items)
+{
+ int i;
+ fprintf(stdout, "Filter group: '%s' (tx/rx)\n", group);
+ for (i = 0; i < n_items; i++) {
+ fprintf(stdout, " - %s (%lld/%lld)\n",
+ items[i].name, items[i].tx, items[i].rx);
+ }
+}
+
+static void loop_measurement(struct wprobe_iface *dev, bool print_filters, unsigned long delay)
+{
+ do {
+ wprobe_update_links(dev);
+ wprobe_dump_data(dev);
+ if (print_filters)
+ wprobe_dump_filters(dev, simple_mode ? show_filter_simple : show_filter, NULL);
+ usleep(delay * 1000);
+ }
+ while (delay);
+}
+
+static void set_filter(struct wprobe_iface *dev, const char *filename)
+{
+ unsigned char *buf = NULL;
+ unsigned int buflen = 0;
+ unsigned int len = 0;
+ int fd;
+
+ /* clear filter */
+ if (filename[0] == 0) {
+ dev->filter_len = -1;
+ return;
+ }
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ perror("open filter");
+ return;
+ }
+
+ do {
+ int rlen;
+
+ if (!buf) {
+ len = 0;
+ buflen = 1024;
+ buf = malloc(1024);
+ } else {
+ buflen *= 2;
+ buf = realloc(buf, buflen);
+ }
+ rlen = read(fd, buf + len, buflen - len);
+ if (rlen < 0)
+ break;
+
+ len += rlen;
+ } while (len == buflen);
+
+ dev->filter = buf;
+ dev->filter_len = len;
+ close(fd);
+}
+
+#ifndef NO_LOCAL_ACCESS
+
+static void sigchld_handler(int s)
+{
+ while (waitpid(-1, NULL, WNOHANG) > 0);
+}
+
+static int run_proxy(int port)
+{
+ struct sockaddr_in sa;
+ struct sigaction sig;
+ int v = 1;
+ int s;
+
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s < 0) {
+ perror("socket");
+ return 1;
+ }
+
+ sig.sa_handler = sigchld_handler; // Signal Handler fuer Zombie Prozesse
+ sigemptyset(&sig.sa_mask);
+ sig.sa_flags = SA_RESTART;
+ sigaction(SIGCHLD, &sig, NULL);
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
+ sa.sin_addr.s_addr = htonl(INADDR_ANY);
+ sa.sin_port = htons(wprobe_port);
+
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v));
+ if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
+ perror("bind");
+ return 1;
+ }
+ if (listen(s, 10)) {
+ perror("listen");
+ return 1;
+ }
+ while(1) {
+ unsigned int addrlen = sizeof(struct sockaddr_in);
+ int ret, c;
+
+ c = accept(s, (struct sockaddr *)&sa, &addrlen);
+ if (c < 0) {
+ if (errno == EINTR)
+ continue;
+
+ perror("accept");
+ return 1;
+ }
+ if (fork() == 0) {
+ /* close server socket, stdin, stdout, stderr */
+ close(s);
+ close(0);
+ close(1);
+ close(2);
+
+ wprobe_server_init(c);
+ do {
+ ret = wprobe_server_handle(c);
+ } while (ret >= 0);
+ wprobe_server_done();
+ close(c);
+ exit(0);
+ }
+ close(c);
+ }
+
+ return 0;
+}
+#endif
+
+int main(int argc, char **argv)
+{
+ struct wprobe_iface *dev = NULL;
+ const char *ifname;
+ const char *prog = argv[0];
+ char *err = NULL;
+ enum {
+ CMD_NONE,
+ CMD_CONFIG,
+ CMD_MEASURE,
+ CMD_PROXY,
+ } cmd = CMD_NONE;
+ const char *filter = NULL;
+ bool print_attributes = false;
+ bool print_filters = false;
+ unsigned long delay = 1000;
+ int interval = -1;
+ int ch;
+
+ if (argc < 2)
+ return usage(prog);
+
+#ifndef NO_LOCAL_ACCESS
+ if (!strcmp(argv[1], "-P")) {
+ while ((ch = getopt(argc - 1, argv + 1, "p:")) != -1) {
+ switch(ch) {
+ case 'p':
+ /* set port */
+ wprobe_port = strtoul(optarg, NULL, 0);
+ break;
+ default:
+ return usage(prog);
+ }
+ }
+ return run_proxy(wprobe_port);
+ }
+#endif
+
+ if (argv[1][0] == '-')
+ return usage(prog);
+
+ ifname = argv[1];
+ argv++;
+ argc--;
+
+ while ((ch = getopt(argc, argv, "acd:fF:hi:msp:")) != -1) {
+ switch(ch) {
+ case 'a':
+ print_attributes = true;
+ break;
+ case 'c':
+ cmd = CMD_CONFIG;
+ break;
+ case 'd':
+ delay = strtoul(optarg, NULL, 10);
+ break;
+ case 'm':
+ cmd = CMD_MEASURE;
+ break;
+ case 'i':
+ interval = strtoul(optarg, NULL, 10);
+ break;
+ case 'f':
+ print_filters = true;
+ break;
+ case 'F':
+ if (filter) {
+ fprintf(stderr, "Cannot set multiple filters\n");
+ return usage(prog);
+ }
+ filter = optarg;
+ break;
+ case 's':
+ simple_mode = true;
+ break;
+ case 'p':
+ /* set port */
+ wprobe_port = strtoul(optarg, NULL, 0);
+ break;
+ case 'h':
+ default:
+ usage(prog);
+ break;
+ }
+ }
+
+ dev = wprobe_get_auto(ifname, &err);
+ if (!dev || (list_empty(&dev->global_attr) &&
+ list_empty(&dev->link_attr))) {
+ if (err)
+ fprintf(stdout, "%s\n", err);
+ else
+ fprintf(stderr, "Interface '%s' not found\n", ifname);
+ return 1;
+ }
+
+ if (filter || interval >= 0) {
+ if (filter)
+ set_filter(dev, filter);
+ if (interval >= 0)
+ dev->interval = interval;
+
+ wprobe_apply_config(dev);
+ }
+
+ if (cmd != CMD_CONFIG) {
+ if (print_attributes)
+ show_attributes(dev);
+ }
+ if (cmd == CMD_MEASURE)
+ loop_measurement(dev, print_filters, delay);
+
+ wprobe_free_dev(dev);
+
+ return 0;
+}
diff --git a/package/wprobe/src/user/wprobe.h b/package/wprobe/src/user/wprobe.h
new file mode 100644
index 000000000..706facc80
--- /dev/null
+++ b/package/wprobe/src/user/wprobe.h
@@ -0,0 +1,213 @@
+/*
+ * wprobe.h: Wireless probe user space library
+ * Copyright (C) 2008-2009 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+#ifndef __WPROBE_USER_H
+#define __WPROBE_USER_H
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "list.h"
+
+/**
+ * struct wprobe_value: data structure for attribute values
+ * @STRING: string value (currently unsupported)
+ * @U8: unsigned 8-bit integer value
+ * @U16: unsigned 16-bit integer value
+ * @U32: unsigned 32-bit integer value
+ * @U64: unsigned 64-bit integer value
+ * @S8: signed 8-bit integer value
+ * @S16: signed 16-bit integer value
+ * @S32: signed 32-bit integer value
+ * @S64: signed 64-bit integer value
+ *
+ * @n: number of sample values
+ * @avg: average value
+ * @stdev: standard deviation
+ * @s: sum of all sample values (internal use)
+ * @ss: sum of all sample values squared (internal use)
+ */
+struct wprobe_value {
+ /* attribute value */
+ union {
+ const char *STRING;
+ uint8_t U8;
+ uint16_t U16;
+ uint32_t U32;
+ uint64_t U64;
+ int8_t S8;
+ int16_t S16;
+ int32_t S32;
+ int64_t S64;
+ };
+ /* statistics */
+ int64_t s, ss;
+ float avg, stdev;
+ unsigned int n;
+};
+
+/**
+ * struct wprobe_attribute: data structures for attribute descriptions
+ * @list: linked list data structure for a list of attributes
+ * @id: attribute id
+ * @type: netlink type for the attribute (see kernel api documentation)
+ * @flags: attribute flags (see kernel api documentation)
+ * @val: cached version of the last netlink query, will be overwritten on each request
+ * @name: attribute name
+ */
+struct wprobe_attribute {
+ struct list_head list;
+ int id;
+ int type;
+ uint32_t flags;
+ struct wprobe_value val;
+ char name[];
+};
+
+/**
+ * struct wprobe_link: data structure for the link description
+ * @list: linked list data structure for a list of links
+ * @flags: link flags (see kernel api documentation)
+ * @addr: mac address of the remote link partner
+ */
+struct wprobe_link {
+ struct list_head list;
+ uint32_t flags;
+ unsigned char addr[6];
+};
+
+struct wprobe_filter_item {
+ char name[32];
+ uint64_t rx;
+ uint64_t tx;
+};
+
+struct wprobe_iface_ops;
+struct wprobe_iface {
+ const struct wprobe_iface_ops *ops;
+
+ int sockfd;
+ const char *ifname;
+ unsigned int genl_family;
+ char addr[6];
+
+ struct list_head global_attr;
+ struct list_head link_attr;
+ struct list_head links;
+
+ /* config */
+ int interval;
+ int scale_min;
+ int scale_max;
+ int scale_m;
+ int scale_d;
+
+ /* filter */
+ void *filter;
+
+ /* filter_len:
+ * set to -1 to drop the current filter
+ * automatically reset to 0 after config apply
+ */
+ int filter_len;
+};
+
+typedef void (*wprobe_filter_cb)(void *arg, const char *group, struct wprobe_filter_item *items, int n_items);
+extern int wprobe_port;
+
+/**
+ * wprobe_update_links: get a list of all link partners
+ * @dev: wprobe device structure
+ * @list: linked list for storing link descriptions
+ *
+ * when wprobe_update_links is called multiple times, the linked list
+ * is updated with new link partners, old entries are automatically expired
+ */
+extern int wprobe_update_links(struct wprobe_iface *dev);
+
+/**
+ * wprobe_dump_filters: dump all layer 2 filter counters
+ * @dev: wprobe device structure
+ * @cb: callback (called once per filter group)
+ * @arg: user argument for the callback
+ */
+extern int wprobe_dump_filters(struct wprobe_iface *dev, wprobe_filter_cb cb, void *arg);
+
+/**
+ * wprobe_measure: start a measurement request for all global attributes
+ * @dev: wprobe device structure
+ *
+ * not all attributes are automatically filled with data, since for some
+ * it may be desirable to control the sampling interval from user space
+ * you can use this function to do that.
+ */
+extern int wprobe_measure(struct wprobe_iface *dev);
+
+/**
+ * wprobe_get_dev: get a handle to a local wprobe device
+ * @ifname: name of the wprobe interface
+ *
+ * queries the wprobe interface for all attributes
+ * must be freed with wprobe_free_dev
+ */
+extern struct wprobe_iface *wprobe_get_dev(const char *ifname);
+
+/**
+ * wprobe_get_auto: get a handle to a local or remote wprobe device
+ * @arg: pointer to the wprobe device, either <dev> (local) or <host>:<dev> (remote)
+ */
+extern struct wprobe_iface *wprobe_get_auto(const char *arg, char **err);
+
+/**
+ * wprobe_get_dev: free all device information
+ * @dev: wprobe device structure
+ */
+extern void wprobe_free_dev(struct wprobe_iface *dev);
+
+/**
+ * wprobe_apply_config: apply configuration data
+ * @dev: wprobe device structure
+ *
+ * uploads all configuration values from @dev that are not set to -1
+ */
+extern int wprobe_apply_config(struct wprobe_iface *dev);
+
+/**
+ * wprobe_request_data: request new sampling values for the given list of attributes
+ * @dev: wprobe device structure
+ * @addr: (optional) mac address of the link partner
+ *
+ * if addr is unset, global values are stored in the global attributes list
+ * if addr is set, per-link values for the given address are stored in the link attributes list
+ */
+extern int wprobe_request_data(struct wprobe_iface *dev, const unsigned char *addr);
+
+/**
+ * wprobe_server_init: send a wprobe server init message to a server's client socket
+ * @socket: socket of the connection to the client
+ */
+extern int wprobe_server_init(int socket);
+
+/**
+ * wprobe_server_handle: read a request from the client socket, process it, send the response
+ * @socket: socket of the connection to the client
+ */
+extern int wprobe_server_handle(int socket);
+
+/**
+ * wprobe_server_done: release memory allocated for the server connection
+ */
+extern void wprobe_server_done(void);
+
+#endif
diff --git a/package/wrt55agv2-spidevs/Makefile b/package/wrt55agv2-spidevs/Makefile
new file mode 100644
index 000000000..236c9a3be
--- /dev/null
+++ b/package/wrt55agv2-spidevs/Makefile
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2008 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=wrt55agv2-spidevs
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/wrt55agv2-spidevs
+ SUBMENU:=Other modules
+ TITLE:=WRT55AG v2 SPI devices support
+ DEPENDS:=@TARGET_atheros +kmod-spi-gpio-old +kmod-spi-ks8995
+ FILES:=$(PKG_BUILD_DIR)/wrt55agv2_spidevs.ko
+endef
+
+define KernelPackage/wrt55agv2-spidevs/description
+ Kernel module for the SPI devices on the WRT55AG v2 board.
+endef
+
+EXTRA_KCONFIG:= \
+ CONFIG_WRT55AGV2_SPIDEVS=m
+
+EXTRA_CFLAGS:= \
+ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \
+ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \
+
+MAKE_OPTS:= \
+ ARCH="$(LINUX_KARCH)" \
+ CROSS_COMPILE="$(TARGET_CROSS)" \
+ SUBDIRS="$(PKG_BUILD_DIR)" \
+ EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
+ LINUXINCLUDE="-I$(LINUX_DIR)/include -I$(LINUX_DIR)/arch/mips/include -include generated/autoconf.h" \
+ $(EXTRA_KCONFIG)
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+ $(MAKE) -C "$(LINUX_DIR)" \
+ $(MAKE_OPTS) \
+ modules
+endef
+
+$(eval $(call KernelPackage,wrt55agv2-spidevs))
diff --git a/package/wrt55agv2-spidevs/src/Kconfig b/package/wrt55agv2-spidevs/src/Kconfig
new file mode 100644
index 000000000..75e8242be
--- /dev/null
+++ b/package/wrt55agv2-spidevs/src/Kconfig
@@ -0,0 +1,3 @@
+config WRT55AGV2_SPIDEVS
+ tristate "SPI device support for the WRT55AG v2 board"
+ depends on SPI && MIPS_ATHEROS
diff --git a/package/wrt55agv2-spidevs/src/Makefile b/package/wrt55agv2-spidevs/src/Makefile
new file mode 100644
index 000000000..7f2ddb4e5
--- /dev/null
+++ b/package/wrt55agv2-spidevs/src/Makefile
@@ -0,0 +1 @@
+obj-${CONFIG_WRT55AGV2_SPIDEVS} += wrt55agv2_spidevs.o \ No newline at end of file
diff --git a/package/wrt55agv2-spidevs/src/wrt55agv2_spidevs.c b/package/wrt55agv2-spidevs/src/wrt55agv2_spidevs.c
new file mode 100644
index 000000000..dfb7f6abe
--- /dev/null
+++ b/package/wrt55agv2-spidevs/src/wrt55agv2_spidevs.c
@@ -0,0 +1,114 @@
+/*
+ * SPI driver for the Linksys WRT55AG v2 board.
+ *
+ * Copyright (C) 2008 Gabor Juhos <juhosg at openwrt.org>
+ *
+ * This file was based on the mmc_over_gpio driver:
+ * Copyright 2008 Michael Buesch <mb@bu3sch.de>
+ *
+ * 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/platform_device.h>
+#include <linux/spi/spi_gpio_old.h>
+#include <linux/module.h>
+
+#define DRV_NAME "wrt55agv2-spidevs"
+#define DRV_DESC "SPI driver for the WRT55AG v2 board"
+#define DRV_VERSION "0.1.0"
+#define PFX DRV_NAME ": "
+
+#define GPIO_PIN_MISO 1
+#define GPIO_PIN_CS 2
+#define GPIO_PIN_CLK 3
+#define GPIO_PIN_MOSI 4
+
+static struct platform_device *spi_gpio_dev;
+
+static int __init boardinfo_setup(struct spi_board_info *bi,
+ struct spi_master *master, void *data)
+{
+
+ strlcpy(bi->modalias, "spi-ks8995", sizeof(bi->modalias));
+
+ bi->max_speed_hz = 5000000 /* Hz */;
+ bi->bus_num = master->bus_num;
+ bi->mode = SPI_MODE_0;
+
+ return 0;
+}
+
+static int __init wrt55agv2_spidevs_init(void)
+{
+ struct spi_gpio_platform_data pdata;
+ int err;
+
+ spi_gpio_dev = platform_device_alloc("spi-gpio", 0);
+ if (!spi_gpio_dev) {
+ printk(KERN_ERR PFX "no memory for spi-gpio device\n");
+ return -ENOMEM;
+ }
+
+ memset(&pdata, 0, sizeof(pdata));
+ pdata.pin_miso = GPIO_PIN_MISO;
+ pdata.pin_cs = GPIO_PIN_CS;
+ pdata.pin_clk = GPIO_PIN_CLK;
+ pdata.pin_mosi = GPIO_PIN_MOSI;
+ pdata.cs_activelow = 1;
+ pdata.no_spi_delay = 1;
+ pdata.boardinfo_setup = boardinfo_setup;
+ pdata.boardinfo_setup_data = NULL;
+
+ err = platform_device_add_data(spi_gpio_dev, &pdata, sizeof(pdata));
+ if (err)
+ goto err_free_dev;
+
+ err = platform_device_register(spi_gpio_dev);
+ if (err) {
+ printk(KERN_ERR PFX "unable to register device\n");
+ goto err_free_pdata;
+ }
+
+ return 0;
+
+err_free_pdata:
+ kfree(spi_gpio_dev->dev.platform_data);
+ spi_gpio_dev->dev.platform_data = NULL;
+
+err_free_dev:
+ platform_device_put(spi_gpio_dev);
+ return err;
+}
+
+static void __exit wrt55agv2_spidevs_cleanup(void)
+{
+ if (!spi_gpio_dev)
+ return;
+
+ platform_device_unregister(spi_gpio_dev);
+
+ kfree(spi_gpio_dev->dev.platform_data);
+ spi_gpio_dev->dev.platform_data = NULL;
+ platform_device_put(spi_gpio_dev);
+}
+
+static int __init wrt55agv2_spidevs_modinit(void)
+{
+ printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n");
+ return wrt55agv2_spidevs_init();
+}
+module_init(wrt55agv2_spidevs_modinit);
+
+static void __exit wrt55agv2_spidevs_modexit(void)
+{
+ wrt55agv2_spidevs_cleanup();
+}
+module_exit(wrt55agv2_spidevs_modexit);
+
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
+MODULE_LICENSE("GPL v2");
+
diff --git a/package/xfsprogs/Makefile b/package/xfsprogs/Makefile
new file mode 100644
index 000000000..a7a865a0e
--- /dev/null
+++ b/package/xfsprogs/Makefile
@@ -0,0 +1,87 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=xfsprogs
+PKG_RELEASE:=1
+PKG_VERSION:=3.1.7
+PKG_SOURCE_URL:=ftp://oss.sgi.com/projects/xfs/previous/
+PKG_MD5SUM:=049cf9873794ea49d0bb3f12d45748a4
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_INSTALL:=1
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/xfsprogs/default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libuuid +libpthread +librt
+ URL:=http://oss.sgi.com/projects/xfs
+endef
+
+define Package/xfs-mkfs
+$(call Package/xfsprogs/default)
+ TITLE:=Utility for creating XFS filesystems
+endef
+
+define Package/xfs-fsck
+$(call Package/xfsprogs/default)
+ TITLE:=Utilities for checking and repairing XFS filesystems
+endef
+
+define Package/xfs-growfs
+$(call Package/xfsprogs/default)
+ TITLE:=Utility for increasing the size of XFS filesystems
+endef
+
+CONFIGURE_ARGS += \
+ --enable-gettext=no \
+ --enable-lib64=no
+
+TARGET_CFLAGS += \
+ -I$(STAGING_DIR)/usr/include \
+ -D_LARGEFILE64_SOURCE \
+ -D_FILE_OFFSET_BITS=64 \
+ -D_GNU_SOURCE
+
+MAKE_FLAGS += \
+ DEBUG= Q= \
+ PCFLAGS="-Wall" \
+ PKG_PLATFORM=linux \
+ ENABLE_GETTEXT=no \
+ prefix=$(PKG_INSTALL_DIR)/usr \
+ exec_prefix=$(PKG_INSTALL_DIR)/usr \
+ PKG_SBIN_DIR=$(PKG_INSTALL_DIR)/usr/sbin \
+ PKG_ROOT_SBIN_DIR=$(PKG_INSTALL_DIR)/sbin \
+ PKG_MAN_DIR=$(PKG_INSTALL_DIR)/usr/man \
+ PKG_LOCALE_DIR=$(PKG_INSTALL_DIR)/usr/share/locale \
+ PKG_ROOT_LIB_DIR=$(PKG_INSTALL_DIR)/lib \
+ PKG_DOC_DIR=$(PKG_INSTALL_DIR)/usr/share/doc/xfsprogs
+
+define Package/xfs-mkfs/install
+ mkdir -p $(1)/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/sbin/mkfs.xfs $(1)/sbin
+endef
+
+define Package/xfs-fsck/install
+ mkdir -p $(1)/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/sbin/xfs_repair $(1)/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/xfs_db $(1)/sbin
+endef
+
+define Package/xfs-growfs/install
+ mkdir -p $(1)/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/xfs_growfs $(1)/sbin
+endef
+
+$(eval $(call BuildPackage,xfs-mkfs))
+$(eval $(call BuildPackage,xfs-fsck))
+$(eval $(call BuildPackage,xfs-growfs))
diff --git a/package/xfsprogs/patches/001-automake-compat.patch b/package/xfsprogs/patches/001-automake-compat.patch
new file mode 100644
index 000000000..3003d6d21
--- /dev/null
+++ b/package/xfsprogs/patches/001-automake-compat.patch
@@ -0,0 +1,84 @@
+commit 2222aa77e11b959e0e5a0ded3482e56799593bc2
+Author: Jens Muecke <jens@nons.de>
+Date: Thu Jan 26 00:34:15 2012 +0100
+
+ 001-automake-compat
+
+diff --git a/configure.in b/configure.in
+index 664c0e9..d91b6ec 100644
+--- a/configure.in
++++ b/configure.in
+@@ -2,7 +2,8 @@ AC_INIT(include/libxfs.h)
+ AC_PREREQ(2.50)
+ AC_CONFIG_AUX_DIR([.])
+ AC_CONFIG_MACRO_DIR([m4])
+-AC_CONFIG_HEADER(include/platform_defs.h)
++# Put a dummy here (http://www.mail-archive.com/automake@gnu.org/msg09241.html)
++AC_CONFIG_HEADERS([doesnotexist.h include/platform_defs.h])
+ AC_PREFIX_DEFAULT(/usr)
+
+ AC_PROG_LIBTOOL
+diff --git a/include/builddefs.in b/include/builddefs.in
+index 81ebfcd..5a4a0e8 100644
+--- a/include/builddefs.in
++++ b/include/builddefs.in
+@@ -20,6 +20,8 @@
+ ifndef _BUILDDEFS_INCLUDED_
+ _BUILDDEFS_INCLUDED_ = 1
+
++SHELL = @SHELL@
++
+ DEBUG = @debug_build@
+ OPTIMIZER = @opt_build@
+ MALLOCLIB = @malloc_lib@
+diff --git a/m4/package_types.m4 b/m4/package_types.m4
+index 0a0e087..66a136a 100644
+--- a/m4/package_types.m4
++++ b/m4/package_types.m4
+@@ -9,7 +9,7 @@ AC_DEFUN([AC_TYPE_PSINT],
+ #include <stddef.h>
+ ], [
+ __psint_t psint;
+- ], AC_DEFINE(HAVE___PSINT_T) AC_MSG_RESULT(yes) , AC_MSG_RESULT(no))
++ ], AC_DEFINE([HAVE___PSINT_T], [1], [Define if __psint_t exists]) AC_MSG_RESULT(yes) , AC_MSG_RESULT(no))
+ ])
+
+ #
+@@ -23,7 +23,7 @@ AC_DEFUN([AC_TYPE_PSUNSIGNED],
+ #include <stddef.h>
+ ], [
+ __psunsigned_t psuint;
+- ], AC_DEFINE(HAVE___PSUNSIGNED_T) AC_MSG_RESULT(yes) , AC_MSG_RESULT(no))
++ ], AC_DEFINE([HAVE___PSUNSIGNED_T], [1], [Define if __psunsigned_t exists]) AC_MSG_RESULT(yes) , AC_MSG_RESULT(no))
+ ])
+
+ #
+@@ -37,7 +37,7 @@ AC_DEFUN([AC_TYPE_U32],
+ #include <stddef.h>
+ ], [
+ __u32 u32;
+- ], AC_DEFINE(HAVE___U32) AC_MSG_RESULT(yes) , AC_MSG_RESULT(no))
++ ], AC_DEFINE([HAVE___U32], [1], [Define if __u32 exists]) AC_MSG_RESULT(yes) , AC_MSG_RESULT(no))
+ ])
+
+ #
+@@ -50,15 +50,15 @@ AC_DEFUN([AC_SIZEOF_POINTERS_AND_LONG],
+ AC_CHECK_SIZEOF(long, 4)
+ AC_CHECK_SIZEOF(char *, 4)
+ if test $ac_cv_sizeof_long -eq 4 -o $ac_cv_sizeof_long -eq 0; then
+- AC_DEFINE(HAVE_32BIT_LONG)
++ AC_DEFINE([HAVE_32BIT_LONG], [1], [Define if long is 32bit])
+ fi
+ if test $ac_cv_sizeof_long -eq 8; then
+- AC_DEFINE(HAVE_64BIT_LONG)
++ AC_DEFINE([HAVE_64BIT_LONG], [1], [Define if long is 64bit])
+ fi
+ if test $ac_cv_sizeof_char_p -eq 4 -o $ac_cv_sizeof_char_p -eq 0; then
+- AC_DEFINE(HAVE_32BIT_PTR)
++ AC_DEFINE([HAVE_32BIT_PTR], [1], [Define if char* is 32bit])
+ fi
+ if test $ac_cv_sizeof_char_p -eq 8; then
+- AC_DEFINE(HAVE_64BIT_PTR)
++ AC_DEFINE([HAVE_64BIT_PTR], [1], [Define if char* is 64bit])
+ fi
+ ])
diff --git a/package/xfsprogs/patches/100-no_aio.patch b/package/xfsprogs/patches/100-no_aio.patch
new file mode 100644
index 000000000..30d36b4da
--- /dev/null
+++ b/package/xfsprogs/patches/100-no_aio.patch
@@ -0,0 +1,21 @@
+commit e72b7bd12fdef06c3494b919376bfe886aa8bb4d
+Author: Jens Muecke <jens@nons.de>
+Date: Thu Jan 26 00:35:43 2012 +0100
+
+ 100-no_aio
+
+diff --git a/configure.in b/configure.in
+index d91b6ec..8dc8b4a 100644
+--- a/configure.in
++++ b/configure.in
+@@ -92,8 +92,8 @@ AC_PACKAGE_GLOBALS(xfsprogs)
+ AC_PACKAGE_UTILITIES(xfsprogs)
+ AC_MULTILIB($enable_lib64)
+
+-AC_PACKAGE_NEED_AIO_H
+-AC_PACKAGE_NEED_LIO_LISTIO
++librt="-lrt"
++AC_SUBST(librt)
+
+ AC_PACKAGE_NEED_UUID_H
+ AC_PACKAGE_NEED_UUIDCOMPARE
diff --git a/package/xfsprogs/patches/110-uclibc_no_ustat.patch b/package/xfsprogs/patches/110-uclibc_no_ustat.patch
new file mode 100644
index 000000000..c46e8025c
--- /dev/null
+++ b/package/xfsprogs/patches/110-uclibc_no_ustat.patch
@@ -0,0 +1,36 @@
+commit 7b1d0a98e779170232c0a81b4749ab934ec67a7e
+Author: Jens Muecke <jens@nons.de>
+Date: Thu Jan 26 00:36:42 2012 +0100
+
+ 110-uclibc_no_ustat
+
+diff --git a/libxfs/linux.c b/libxfs/linux.c
+index 2e07d54..6a6c905 100644
+--- a/libxfs/linux.c
++++ b/libxfs/linux.c
+@@ -21,7 +21,9 @@
+ #include <mntent.h>
+ #include <sys/stat.h>
+ #undef ustat
++#ifndef __UCLIBC__
+ #include <sys/ustat.h>
++#endif
+ #include <sys/mount.h>
+ #include <sys/ioctl.h>
+ #include <sys/sysinfo.h>
+@@ -49,6 +51,7 @@ static int max_block_alignment;
+ int
+ platform_check_ismounted(char *name, char *block, struct stat64 *s, int verbose)
+ {
++#ifndef __UCLIBC__
+ /* Pad ust; pre-2.6.28 linux copies out too much in 32bit compat mode */
+ struct ustat ust[2];
+ struct stat64 st;
+@@ -68,6 +71,7 @@ platform_check_ismounted(char *name, char *block, struct stat64 *s, int verbose)
+ progname, name);
+ return 1;
+ }
++#endif
+ return 0;
+ }
+
diff --git a/package/xfsprogs/patches/120-portability.patch b/package/xfsprogs/patches/120-portability.patch
new file mode 100644
index 000000000..1e9b53365
--- /dev/null
+++ b/package/xfsprogs/patches/120-portability.patch
@@ -0,0 +1,47 @@
+commit d2aef8b3967e53fe58178f5af50fef488ee0faed
+Author: Jens Muecke <jens@nons.de>
+Date: Thu Jan 26 00:37:52 2012 +0100
+
+ 120-portability
+
+diff --git a/copy/xfs_copy.c b/copy/xfs_copy.c
+index c01e0b9..2e2f320 100644
+--- a/copy/xfs_copy.c
++++ b/copy/xfs_copy.c
+@@ -463,6 +463,15 @@ read_ag_header(int fd, xfs_agnumber_t agno, wbuf *buf, ag_header_t *ag,
+ }
+
+
++static void sig_mask(int type)
++{
++ sigset_t mask;
++ sigemptyset(&mask);
++ sigaddset(&mask, SIGCHLD);
++ sigprocmask(type, &mask, NULL);
++}
++
++
+ void
+ write_wbuf(void)
+ {
+@@ -478,9 +487,9 @@ write_wbuf(void)
+ if (target[i].state != INACTIVE)
+ pthread_mutex_unlock(&targ[i].wait); /* wake up */
+
+- sigrelse(SIGCHLD);
++ sig_mask(SIG_UNBLOCK);
+ pthread_mutex_lock(&mainwait);
+- sighold(SIGCHLD);
++ sig_mask(SIG_BLOCK);
+ }
+
+
+@@ -847,7 +856,7 @@ main(int argc, char **argv)
+ /* set up sigchild signal handler */
+
+ signal(SIGCHLD, handler);
+- sighold(SIGCHLD);
++ sig_mask(SIG_BLOCK);
+
+ /* make children */
+
diff --git a/package/xfsprogs/patches/130-uclibc_no_xattr.patch b/package/xfsprogs/patches/130-uclibc_no_xattr.patch
new file mode 100644
index 000000000..b1ecda71e
--- /dev/null
+++ b/package/xfsprogs/patches/130-uclibc_no_xattr.patch
@@ -0,0 +1,36 @@
+commit 10d6058b24f18cb31889154f830b191849f45106
+Author: Jens Muecke <jens@nons.de>
+Date: Thu Jan 26 00:38:27 2012 +0100
+
+ 130-uclibc_no_xattr
+
+diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c
+index 40c2e6f..4f54059 100644
+--- a/fsr/xfs_fsr.c
++++ b/fsr/xfs_fsr.c
+@@ -35,7 +35,9 @@
+ #include <sys/wait.h>
+ #include <sys/vfs.h>
+ #include <sys/statvfs.h>
++#ifndef __UCLIBC__
+ #include <sys/xattr.h>
++#endif
+
+
+ #ifndef XFS_XFLAG_NODEFRAG
+@@ -990,6 +992,7 @@ fsr_setup_attr_fork(
+ int tfd,
+ xfs_bstat_t *bstatp)
+ {
++#ifndef __UCLIBC__
+ struct stat64 tstatbuf;
+ int i;
+ int last_forkoff = 0;
+@@ -1108,6 +1111,7 @@ fsr_setup_attr_fork(
+ out:
+ if (dflag)
+ fsrprintf(_("set temp attr\n"));
++#endif
+ return 0;
+ }
+
diff --git a/package/xfsprogs/patches/140-no_po.patch b/package/xfsprogs/patches/140-no_po.patch
new file mode 100644
index 000000000..f915a9cf2
--- /dev/null
+++ b/package/xfsprogs/patches/140-no_po.patch
@@ -0,0 +1,20 @@
+diff -urN xfsprogs-3.1.7/Makefile xfsprogs-3.1.7.new/Makefile
+--- xfsprogs-3.1.7/Makefile 2011-11-18 00:30:24.000000000 +0100
++++ xfsprogs-3.1.7.new/Makefile 2012-04-20 14:15:48.641722955 +0200
+@@ -41,7 +41,7 @@
+
+ LIB_SUBDIRS = libxfs libxlog libxcmd libhandle libdisk
+ TOOL_SUBDIRS = copy db estimate fsck fsr growfs io logprint mkfs quota \
+- mdrestore repair rtcp m4 man doc po debian
++ mdrestore repair rtcp m4 man doc debian
+
+ SUBDIRS = include $(LIB_SUBDIRS) $(TOOL_SUBDIRS)
+
+@@ -135,7 +135,6 @@
+ $(Q)$(MAKE) $(MAKEOPTS) -C . $@
+ else
+ $(Q)$(MAKE) $(MAKEOPTS) $(SRCDIR)
+- $(Q)$(MAKE) $(MAKEOPTS) -C po
+ $(Q)$(MAKE) $(MAKEOPTS) source-link
+ $(Q)cd $(SRCDIR) && dpkg-buildpackage
+ endif
diff --git a/package/yamonenv/Makefile b/package/yamonenv/Makefile
new file mode 100644
index 000000000..35d1f6d17
--- /dev/null
+++ b/package/yamonenv/Makefile
@@ -0,0 +1,38 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=yamonenv
+PKG_VERSION:=20051022
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)_gruen.4g__$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://downloads.openwrt.org/sources/
+PKG_MD5SUM:=a3e4f24155aa3ba5aa502bc63fdaa6ad
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/yamonenv
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=@TARGET_au1000
+ TITLE:=YAMON configuration utility
+ URL:=http://meshcube.org/nylon/stable/sources/
+endef
+
+define Build/Configure
+endef
+
+define Package/yamonenv/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(CP) $(PKG_BUILD_DIR)/src/$(PKG_NAME) $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,yamonenv))
diff --git a/package/yamonenv/patches/001-yamonenv_mtd_partition.patch b/package/yamonenv/patches/001-yamonenv_mtd_partition.patch
new file mode 100644
index 000000000..e1def28af
--- /dev/null
+++ b/package/yamonenv/patches/001-yamonenv_mtd_partition.patch
@@ -0,0 +1,11 @@
+--- a/src/yamonenv.c
++++ b/src/yamonenv.c
+@@ -12,7 +12,7 @@
+ #include <fcntl.h>
+ #include <unistd.h>
+
+-#define DEFAULT_YAMON_ENV_FILE "/dev/mtd/3"
++#define DEFAULT_YAMON_ENV_FILE "/dev/mtd3"
+
+
+ // control byte definitions:
diff --git a/package/zlib/Makefile b/package/zlib/Makefile
new file mode 100644
index 000000000..18b8884cd
--- /dev/null
+++ b/package/zlib/Makefile
@@ -0,0 +1,69 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=zlib
+PKG_VERSION:=1.2.7
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://www.zlib.net @SF/libpng
+PKG_MD5SUM:=2ab442d169156f34c379c968f3f482dd
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/zlib
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=Library implementing the deflate compression method
+ URL:=http://www.zlib.net/
+endef
+
+define Build/Configure
+ (cd $(PKG_BUILD_DIR); \
+ $(TARGET_CONFIGURE_OPTS) \
+ LDSHARED="$(TARGET_CC) -shared -Wl,-soname,libz.so.1" \
+ CFLAGS="$(TARGET_CFLAGS) $(FPIC)" \
+ ./configure \
+ --prefix=/usr \
+ --shared \
+ --uname=Linux \
+ );
+endef
+
+define Build/Compile
+ +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ libz.a libz.so.$(PKG_VERSION)
+ mkdir -p $(PKG_INSTALL_DIR)
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ install
+endef
+
+define Build/InstallDev
+ mkdir -p $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/z{conf,lib}.h \
+ $(1)/usr/include/
+ mkdir -p $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libz.{a,so*} \
+ $(1)/usr/lib/
+ mkdir -p $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/zlib.pc \
+ $(1)/usr/lib/pkgconfig/
+endef
+
+# libz.so is needed for openssl (zlib-dynamic)
+define Package/zlib/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libz.so $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libz.so.* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,zlib))